Index: /code/branches/RacingBots_FS18/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,195 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures some basics and controls the configuration scripts
+ #
+
+# Defined LINUX
+IF(UNIX AND NOT APPLE)
+  SET(LINUX TRUE)
+ENDIF()
+
+# Keep devs from using the root directory as binary directory (messes up the source tree)
+IF(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
+  MESSAGE(FATAL_ERROR "Please do not use the root directory as CMake output directory!
+  mkdir build; cd build; cmake ..
+  And you will have to clean the source directory by deleting CMakeCache.txt and the folder CMakeFiles")
+ENDIF()
+
+PROJECT(Orxonox C CXX)
+
+# Check AFTER the PROJECT command because MSVC10 gets defined there
+IF(WIN32)
+  IF(MSVC10)
+    CMAKE_MINIMUM_REQUIRED(VERSION 2.8.3 FATAL_ERROR)
+  ELSE()
+    CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR)
+  ENDIF()
+ELSE()
+  CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR)
+ENDIF()
+
+################ General Config #################
+
+# Version info
+SET(ORXONOX_VERSION_MAJOR 0)
+SET(ORXONOX_VERSION_MINOR 0)
+SET(ORXONOX_VERSION_PATCH 5)
+SET(ORXONOX_VERSION
+  ${ORXONOX_VERSION_MAJOR}.${ORXONOX_VERSION_MINOR}.${ORXONOX_VERSION_PATCH}
+)
+SET(ORXONOX_VERSION_NAME "Arcturus")
+
+# Standard path suffixes
+SET(DEFAULT_RUNTIME_PATH bin)
+SET(DEFAULT_LIBRARY_PATH lib)
+SET(DEFAULT_ARCHIVE_PATH lib/static)
+SET(DEFAULT_MODULE_PATH  lib/modules)
+SET(DEFAULT_PLUGIN_PATH  lib/plugins)
+SET(DEFAULT_DOC_PATH     doc)
+SET(DEFAULT_DATA_PATH    data)
+SET(DEFAULT_CONFIG_PATH  config)
+SET(DEFAULT_LOG_PATH     log)
+SET(DEFAULT_BUNDLE_PATH  bundle)
+
+# Set output directories
+SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DEFAULT_RUNTIME_PATH})
+SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DEFAULT_LIBRARY_PATH})
+SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${DEFAULT_ARCHIVE_PATH})
+SET(CMAKE_MODULE_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR}/${DEFAULT_MODULE_PATH})
+SET(CMAKE_PLUGIN_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR}/${DEFAULT_PLUGIN_PATH})
+SET(CMAKE_DOC_OUTPUT_DIRECTORY     ${CMAKE_BINARY_DIR}/${DEFAULT_DOC_PATH})
+# Data directories are only inputs, no delclaration here
+SET(CMAKE_CONFIG_OUTPUT_DIRECTORY  ${CMAKE_BINARY_DIR}/${DEFAULT_CONFIG_PATH})
+SET(CMAKE_LOG_OUTPUT_DIRECTORY     ${CMAKE_BINARY_DIR}/${DEFAULT_LOG_PATH})
+
+# Set the extension of the helper-files for dynamic modules
+SET(ORXONOX_MODULE_EXTENSION ".module")
+SET(ORXONOX_PLUGIN_EXTENSION ".plugin")
+
+# Delete all existing helper-files for dynamic modules
+# modules:
+FILE(GLOB_RECURSE _helper_files ${CMAKE_MODULE_OUTPUT_DIRECTORY}/*${ORXONOX_MODULE_EXTENSION})
+IF(_helper_files)
+  FILE(REMOVE ${_helper_files})
+ENDIF()
+# plugins:
+FILE(GLOB_RECURSE _helper_files ${CMAKE_PLUGIN_OUTPUT_DIRECTORY}/*${ORXONOX_PLUGIN_EXTENSION})
+IF(_helper_files)
+  FILE(REMOVE ${_helper_files})
+ENDIF()
+
+# Sets where to find the external libraries like OgreMain.dll at runtime
+# On Unix you should not have to change this at all.
+# This only applies to development runs in the build tree
+SET(RUNTIME_LIBRARY_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+
+# Take care of some CMake 2.6.0 leftovers
+MARK_AS_ADVANCED(EXECUTABLE_OUTPUT_PATH LIBRARY_OUTPUT_PATH)
+
+# This sets where to look for CMake modules (e.g. "Find*.cmake" files)
+SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_SOURCE_DIR}/cmake/tools)
+
+# Flag variables for extra configuration "RelForDevs" should be hidden
+MARK_AS_ADVANCED(
+  CMAKE_CXX_FLAGS_RELFORDEVS
+  CMAKE_C_FLAGS_RELFORDEVS
+  CMAKE_EXE_LINKER_FLAGS_RELFORDEVS
+  CMAKE_MODULE_LINKER_FLAGS_RELFORDEVS
+  CMAKE_SHARED_LINKER_FLAGS_RELFORDEVS
+)
+
+IF(NOT CMAKE_CONFIGURATION_TYPES)
+  # Set Debug build to default when not having multi-config generator like MSVC or XCODE
+  IF(NOT CMAKE_BUILD_TYPE)
+    SET(CMAKE_BUILD_TYPE Debug CACHE STRING
+        "Build types are: Debug, RelForDevs, RelWithDebInfo, Release, MinSizeRel" FORCE)
+  ENDIF()
+  MARK_AS_ADVANCED(CLEAR CMAKE_BUILD_TYPE)
+
+  MESSAGE(STATUS "*** Build type is ${CMAKE_BUILD_TYPE} ***")
+ELSE()
+  # Make sure no build type is ever set
+  IF(CMAKE_BUILD_TYPE)
+    SET(CMAKE_BUILD_TYPE CACHE STRING FORCE)
+  ENDIF()
+  MARK_AS_ADVANCED(FORCE CMAKE_BUILD_TYPE)
+  # Add our extra configuration "RelForDevs"
+  SET(CMAKE_CONFIGURATION_TYPES "Debug;RelForDevs;RelWithDebInfo;Release;MinSizeRel"
+      CACHE STRING "Semicolon separated list of supported configuration types." FORCE)
+ENDIF()
+
+# Debug builds can not be installed
+INSTALL(SCRIPT cmake/InstallCheck.cmake)
+
+IF(APPLE)
+  # Set 10.5 as the base SDK by default
+  SET(XCODE_ATTRIBUTE_SDKROOT macosx10.5)
+
+  # 10.6 sets x86_64 as the default architecture.
+  # Because Carbon isn't supported on 64-bit and we still need it, force the architectures to ppc and i386
+  IF(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
+    SET(CMAKE_OSX_ARCHITECTURES "i386")
+  ENDIF()
+  IF(CMAKE_OSX_ARCHITECTURES MATCHES "ppc64")
+    SET(CMAKE_OSX_ARCHITECTURES "ppc")
+  ENDIF()
+  IF(NOT CMAKE_OSX_ARCHITECTURES)
+    SET(CMAKE_OSX_ARCHITECTURES "i386")
+  ENDIF()
+ENDIF()
+
+########### Subfolders and Subscripts ###########
+
+# General build and compiler options and configurations
+INCLUDE(CompilerConfig)
+
+# Library finding
+INCLUDE(LibraryConfig)
+
+# Configure installation paths and options
+INCLUDE(InstallConfig)
+
+# Configure data directory location and installation
+ADD_SUBDIRECTORY(data)
+
+# Create the actual project
+ADD_SUBDIRECTORY(src)
+
+# Create the test suites
+ADD_SUBDIRECTORY(test)
+
+# Configure the binary output directory. Do this after src!
+ADD_SUBDIRECTORY(bin)
+
+# System specific files (mostly for installation)
+ADD_SUBDIRECTORY(contrib)
+
+# Last but not least: Try to make a doc target with Doxygen
+ADD_SUBDIRECTORY(doc)
+
+########### CPack Packaging ###########
+
+# Currently only testing on Apple
+#IF(APPLE)
+#  INCLUDE(BundleConfig)
+#ENDIF(APPLE)
Index: /code/branches/RacingBots_FS18/INSTALL
===================================================================
--- /code/branches/RacingBots_FS18/INSTALL	(revision 11817)
+++ /code/branches/RacingBots_FS18/INSTALL	(revision 11817)
@@ -0,0 +1,25 @@
+************* Build System **************
+To make platform support as easy as possible we have decided to use CMake as our build system.
+Therefore the first thing you need to do is to get
+CMake v.2.6 or later.
+
+************** Libraries ****************
+
+In order to compile Orxonox you will need the following libraries:
+(for windows there are already precompiled packages on the website)
+
+OGRE 3D Graphics Engine          1.6 - 1.7
+CEGUI (Crazy Eddie's GUI System) 0.6 - 0.7
+Boost libraries                  1.40 -
+Lua (scripting language)         5.1
+Tcl (shell script language)      8.4 - 8.5
+OpenAL (audio)                   (no version requirements specified yet)
+ALUT (audio)                     (no version requirements specified yet)
+LibOgg                           (no version requirements specified yet)
+LibVorbis                        (no version requirements specified yet)
+ZLib (compression)               (no version requirements specified yet)
+
+OGRE supports both OpenGL and DirectX9 rendering. You will also need OGRE for the dedicated server!
+
+Further information about installing and running this application can be found on
+http://www.orxonox.net/wiki/Running
Index: /code/branches/RacingBots_FS18/LICENSE
===================================================================
--- /code/branches/RacingBots_FS18/LICENSE	(revision 11817)
+++ /code/branches/RacingBots_FS18/LICENSE	(revision 11817)
@@ -0,0 +1,344 @@
+
+        GNU GENERAL PUBLIC LICENSE
+           Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+        GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software
+    interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Program does not specify a
+version number of this License, you may choose any version ever
+published by the Free Software Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+          NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+         END OF TERMS AND CONDITIONS
+
+      How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /code/branches/RacingBots_FS18/README
===================================================================
--- /code/branches/RacingBots_FS18/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/README	(revision 11817)
@@ -0,0 +1,22 @@
+Hi there,
+
+We are proud to present you Orxonox - the most ferious 3D space shooter ever to exist.
+
+This game is free, if you have paid for this, get your money back! The source code of this game is licensed under the GPL (GNU General Public License).
+The game content is licensed under the Creative Commons Attribution-Sharealike 3.0 license. For more information read LICENSE in the same folder you found this file.
+
+For directions to install this game, please check out the file INSTALL or http://www.orxonox.net/wiki/Running
+
+This application uses the Ogre Graphics Engine (http://www.ogre3d.org), if you haven't already downloaded a precompiled version of Ogre with this package. Visit our webpage to get your Orxonox compatible version of the Ogre libraries.
+
+This is an open source game. If you want to contribute check out http://www.orxonox.net/wiki/development to find more information how you could help us making the game better. We are always looking for programmers and content designers, who like to contribute.
+
+We hope you have fun playing the game. Check out http://www.orxonox.net for news and newer versions of the game.
+
+Please contact us in our forum ( http://forum.orxonox.net ) or check out our contact page ( http://www.orxonox.net/wiki/about#Contact ). We hope to hear from you and are looking forward to your feedback.
+
+
+
+Cheers,
+The Orxonox Development Team
+
Index: /code/branches/RacingBots_FS18/bin/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/bin/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,68 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Creates run scripts in the root directory of the build tree and
+ #    the runtime output directory.
+ #
+
+# Create run scripts for Windows to manually add the DLL path when executing
+SET(RUN_SCRIPTS run standalone client1 client2 server dedicated dedicatedClient masterserver)
+IF(WIN32)
+  FOREACH(_script ${RUN_SCRIPTS})
+    LIST(REMOVE_ITEM RUN_SCRIPTS ${_script})
+    LIST(APPEND RUN_SCRIPTS ${_script}.bat)
+  ENDFOREACH(_script)
+ENDIF()
+
+IF(NOT CMAKE_CONFIGURATION_TYPES)
+  SET(_subdirs .)
+  SEt(_default_subdir .)
+ELSE()
+  SET(_subdirs ${CMAKE_CONFIGURATION_TYPES})
+  SEt(_default_subdir) # No default subdir
+ENDIF()
+STRING(REPLACE "/" "\\" RUNTIME_LIBRARY_DIRECTORY_WINDOWS ${RUNTIME_LIBRARY_DIRECTORY})
+FOREACH(_subdir ${_subdirs})
+  GET_FILENAME_COMPONENT(CURRENT_RUNTIME_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_subdir} ABSOLUTE)
+
+  # Note: Do not use FILE(TO_NATIVE_PATH) because it doesn't work for MinGW
+  STRING(REGEX REPLACE "^([A-Z]\\:)\\/.*$" "\\1" WINDOWS_DRIVE_CHANGE ${CURRENT_RUNTIME_DIR})
+  STRING(REPLACE "/" "\\" CURRENT_RUNTIME_DIR_WINDOWS ${CURRENT_RUNTIME_DIR})
+
+  FOREACH(_script ${RUN_SCRIPTS})
+    CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${_script}.in ${CURRENT_RUNTIME_DIR}/${_script} @ONLY)
+    IF(_subdir STREQUAL _default_subdir)
+      # Convenience script to be used when sitting in the binary directory. Does nothing for MSVC
+      CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${_script}.in ${CMAKE_BINARY_DIR}/${_script} @ONLY)
+    ENDIF()
+  ENDFOREACH(_script)
+
+  # In order to evaluate at run time whether it is a dev build in the build tree,
+  # we plant a special file
+  CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/orxonox_dev_build.keep_me ${CURRENT_RUNTIME_DIR}/orxonox_dev_build.keep_me)
+ENDFOREACH(_subdir)
+
+
+# Make a symlink to be able to run from the root directory when installing copyable on Unix
+IF(UNIX AND INSTALL_COPYABLE)
+  INSTAll(CODE "EXECUTE_PROCESS(COMMAND cmake -E create_symlink \"${CMAKE_INSTALL_PREFIX}/${RUNTIME_INSTALL_DIRECTORY}/${ORXONOX_EXECUTABLE_NAME}\" \"${CMAKE_INSTALL_PREFIX}/${ORXONOX_EXECUTABLE_NAME}\")")
+ENDIF()
Index: /code/branches/RacingBots_FS18/bin/client1.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/client1.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/client1.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --client --writingPathSuffix client1
+pause
Index: /code/branches/RacingBots_FS18/bin/client1.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/client1.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/client1.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --client --writingPathSuffix client1 $@
Index: /code/branches/RacingBots_FS18/bin/client2.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/client2.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/client2.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --client --writingPathSuffix client2
+pause
Index: /code/branches/RacingBots_FS18/bin/client2.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/client2.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/client2.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --client --writingPathSuffix client2 $@
Index: /code/branches/RacingBots_FS18/bin/dedicated.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/dedicated.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/dedicated.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --dedicated --writingPathSuffix dedicated
+pause
Index: /code/branches/RacingBots_FS18/bin/dedicated.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/dedicated.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/dedicated.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --dedicated --writingPathSuffix dedicated $@
Index: /code/branches/RacingBots_FS18/bin/dedicatedClient.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/dedicatedClient.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/dedicatedClient.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --dedicatedClient --writingPathSuffix dedicatedClient
+pause
Index: /code/branches/RacingBots_FS18/bin/dedicatedClient.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/dedicatedClient.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/dedicatedClient.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --dedicatedClient --writingPathSuffix dedicatedClient $@
Index: /code/branches/RacingBots_FS18/bin/masterserver.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/masterserver.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/masterserver.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --masterserver --writingPathSuffix masterserver
+pause
Index: /code/branches/RacingBots_FS18/bin/masterserver.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/masterserver.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/masterserver.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --masterserver --writingPathSuffix masterserver $@
Index: /code/branches/RacingBots_FS18/bin/run.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/run.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/run.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@"
+pause
Index: /code/branches/RacingBots_FS18/bin/run.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/run.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/run.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ $@
Index: /code/branches/RacingBots_FS18/bin/server.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/server.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/server.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --server --writingPathSuffix server
+pause
Index: /code/branches/RacingBots_FS18/bin/server.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/server.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/server.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --server --writingPathSuffix server $@
Index: /code/branches/RacingBots_FS18/bin/standalone.bat.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/standalone.bat.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/standalone.bat.in	(revision 11817)
@@ -0,0 +1,4 @@
+title @PROJECT_NAME@
+path @RUNTIME_LIBRARY_DIRECTORY_WINDOWS@;%path%
+"@CURRENT_RUNTIME_DIR_WINDOWS@\@ORXONOX_EXECUTABLE_NAME@" --standalone --writingPathSuffix standalone
+pause
Index: /code/branches/RacingBots_FS18/bin/standalone.in
===================================================================
--- /code/branches/RacingBots_FS18/bin/standalone.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/bin/standalone.in	(revision 11817)
@@ -0,0 +1,4 @@
+#!/bin/sh
+# convenience script for starting orxonox on Linux
+
+exec @CURRENT_RUNTIME_DIR@/@ORXONOX_EXECUTABLE_NAME@ --standalone --writingPathSuffix standalone $@
Index: /code/branches/RacingBots_FS18/cmake/BundleConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/BundleConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/BundleConfig.cmake	(revision 11817)
@@ -0,0 +1,65 @@
+#
+#             ORXONOX - the hottest 3D action shooter ever to exist
+#                             > www.orxonox.net <
+#
+#        This program 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.
+#
+#       This program 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 this program; if not, write to the Free Software Foundation,
+#     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+#
+#  Author:
+#    Kevin Young
+#  Description:
+#    Sets all necessary variables for CPack package generation
+#
+
+# Common properties across all generators
+
+#SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY FALSE)
+SET(CPACK_INSTALL_CMAKE_PROJECTS ${CMAKE_BINARY_DIR};${PROJECT_NAME};ALL;/)
+SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_NAME}")
+SET(CPACK_PACKAGE_EXECUTABLES ${ORXONOX_EXECUTABLE_NAME};${PROJECT_NAME})
+SET(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}")
+SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME} ${ORXONOX_VERSION_NAME}")
+SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "${PROJECT_NAME} ${ORXONOX_VERSION}")
+# Defaults to PROJECT_NAME anyway
+#SET(CPACK_PACKAGE_NAME "${PROJECT_NAME}")
+SET(CPACK_PACKAGE_VENDOR "www.orxonox.net")
+SET(CPACK_PACKAGE_VERSION_MAJOR ${ORXONOX_VERSION_MAJOR})
+SET(CPACK_PACKAGE_VERSION_MINOR ${ORXONOX_VERSION_MINOR})
+SET(CPACK_PACKAGE_VERSION_PATCH ${ORXONOX_VERSION_PATCH})
+#SET(CPACK_PROJECT_CONFIG_FILE ${CMAKE_BINARY_DIR}/CPackOptions.cmake)
+SET(CPACK_SOURCE_GENERATOR TGZ;ZIP)
+# Unsure what pattern to set here
+#SET(CPACK_SOURCE_IGNORE_FILES /CVS/;/\\.svn/;\\.swp$;\\.#;/#;.*~;cscope.*)
+SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${ORXONOX_VERSION}")
+#SET(CPACK_SOURCE_STRIP_FILES FALSE)
+# Defaults to CMAKE_SYSTEM_NAME anyway
+#SET(CPACK_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}")
+
+# Advanced settings
+SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENCE")
+  
+# Apple specific settings
+IF(APPLE)
+  SET(CPACK_GENERATOR "Bundle")
+
+  SET(CPACK_BUNDLE_NAME "${CPACK_PACKAGE_FILE_NAME}")
+  SET(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/Icon.icns")
+  SET(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/Orxonox-Info.plist")
+  SET(CPACK_BUNDLE_STARTUP_COMMAND "${CMAKE_SOURCE_DIR}/${DEFAULT_RUNTIME_PATH}/mac/OrxonoxMac")
+ENDIF(APPLE)
+
+# Fire up CPack
+INCLUDE(CPack)
Index: /code/branches/RacingBots_FS18/cmake/CompilerConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/CompilerConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/CompilerConfig.cmake	(revision 11817)
@@ -0,0 +1,37 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Calls a compiler specific script and sets some options.
+ #
+
+OPTION(EXTRA_COMPILER_WARNINGS "Enable some extra warnings (heavily pollutes the output)" FALSE)
+
+# Configure the compiler specific build options
+IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+  INCLUDE(CompilerConfigGCC)
+ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+  INCLUDE(CompilerConfigMSVC)
+ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  INCLUDE(CompilerConfigClang)
+ELSE()
+  MESSAGE(STATUS "Warning: Your compiler is not officially supported.")
+ENDIF()
Index: /code/branches/RacingBots_FS18/cmake/CompilerConfigClang.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/CompilerConfigClang.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/CompilerConfigClang.cmake	(revision 11817)
@@ -0,0 +1,84 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Martin Mueller
+ #  Description:
+ #    Sets the right compiler and linker flags for Clang.
+ #
+
+INCLUDE(FlagUtilities)
+
+# Shortcut for CMAKE_CXX_COMPILER_ID MATCHES Clang
+SET(CMAKE_COMPILER_IS_CLANG TRUE)
+
+# Generate compilation database for clang tooling
+SET(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
+
+SET(PCH_COMPILER_SUPPORT TRUE)
+SET(HAVE_COUNTER_MACRO TRUE)
+
+# Also include environment flags. Could cause conflicts though
+SET_COMPILER_FLAGS("$ENV{CXXFLAGS}" CXX CACHE)
+SET_COMPILER_FLAGS("$ENV{CFLAGS}"   C   CACHE)
+
+# These flags get added to the flags above
+SET_COMPILER_FLAGS("    -g -D_DEBUG" Debug          CACHE)
+SET_COMPILER_FLAGS("       -DNDEBUG" ReleaseAll     CACHE)
+ADD_COMPILER_FLAGS("-O2 -g"          RelForDevs     CACHE)
+ADD_COMPILER_FLAGS("-O3 -g"          RelWithDebInfo CACHE)
+ADD_COMPILER_FLAGS("-O3"             Release        CACHE)
+ADD_COMPILER_FLAGS("-Os"             MinSizeRel     CACHE)
+
+# Introducing c++11
+ADD_COMPILER_FLAGS("-std=c++11" CXX CACHE)
+
+# Never omit frame pointers that could interfere with proper stack traces
+ADD_COMPILER_FLAGS("-fno-omit-frame-pointer" CACHE)
+
+# Enable non standard floating point optimisations
+ADD_COMPILER_FLAGS("-ffast-math" CACHE)
+
+ADD_COMPILER_FLAGS("-DORXONOX_GCC_VISIBILITY -fvisibility=default -fvisibility-inlines-hidden" CACHE)
+
+# We have some unconformant code, disable an optimisation feature
+ADD_COMPILER_FLAGS("-fno-strict-aliasing" CACHE)
+
+# Don't display hundreds of annoying deprecated messages
+ADD_COMPILER_FLAGS("-Wno-deprecated" CXX CACHE)
+
+# Clang doesn't like some narrowing bullet does
+ADD_COMPILER_FLAGS("-Wno-c++11-narrowing" CXX CACHE)
+
+# Always show why a precompiled header file could not be used
+ADD_COMPILER_FLAGS("-Winvalid-pch" CXX CACHE)
+
+# Increase warning level if requested
+IF(EXTRA_COMPILER_WARNINGS)
+  ADD_COMPILER_FLAGS("-Wall -Wextra -Wno-unused-parameter" CACHE)
+ELSE()
+  REMOVE_COMPILER_FLAGS("-Wextra -Wno-unused-parameter" CACHE)
+  ADD_COMPILER_FLAGS("-Wall" CACHE)
+ENDIF()
+
+# Linker flags
+IF(LINUX)
+  # Don't allow undefined symbols in a shared library
+  SET_LINKER_FLAGS("-Wl,--no-undefined" CACHE)
+ENDIF()
Index: /code/branches/RacingBots_FS18/cmake/CompilerConfigGCC.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/CompilerConfigGCC.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/CompilerConfigGCC.cmake	(revision 11817)
@@ -0,0 +1,132 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder, Adrian Friedli
+ #  Description:
+ #    Sets the right compiler and linker flags for GCC.
+ #
+
+INCLUDE(FlagUtilities)
+INCLUDE(CompareVersionStrings)
+INCLUDE(CheckCXXCompilerFlag)
+
+# Shortcut for CMAKE_COMPILER_IS_GNUCXX and ..._GNUC
+SET(CMAKE_COMPILER_IS_GNU TRUE)
+
+# Determine compiler version
+EXEC_PROGRAM(
+  ${CMAKE_CXX_COMPILER}
+  ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
+  OUTPUT_VARIABLE GCC_VERSION
+)
+
+# GCC only supports PCH in versions 3.4 and above
+INCLUDE(CompareVersionStrings)
+COMPARE_VERSION_STRINGS("${GCC_VERSION}" "3.4.0" _compare_result)
+IF(_compare_result GREATER -1)
+  SET(PCH_COMPILER_SUPPORT TRUE)
+ENDIF()
+
+# __COUNTER__ macro was only added in GCC 4.3
+# It might be required to make full build units work
+COMPARE_VERSION_STRINGS("${GCC_VERSION}" "4.3.0" _compare_result)
+IF(_compare_result GREATER -1)
+  SET(HAVE_COUNTER_MACRO TRUE)
+ENDIF()
+
+# Also include environment flags. Could cause conflicts though
+SET_COMPILER_FLAGS("$ENV{CXXFLAGS}" CXX CACHE)
+SET_COMPILER_FLAGS("$ENV{CFLAGS}"   C   CACHE)
+
+# These flags get added to the flags above
+SET_COMPILER_FLAGS("    -g -ggdb -D_DEBUG" Debug          CACHE)
+SET_COMPILER_FLAGS("             -DNDEBUG" ReleaseAll     CACHE)
+ADD_COMPILER_FLAGS("-O2 -g -ggdb"          RelForDevs     CACHE)
+ADD_COMPILER_FLAGS("-O3 -g -ggdb"          RelWithDebInfo CACHE)
+ADD_COMPILER_FLAGS("-O3"                   Release        CACHE)
+ADD_COMPILER_FLAGS("-Os"                   MinSizeRel     CACHE)
+
+# Introducing c++11
+ADD_COMPILER_FLAGS("-std=gnu++11" CACHE)
+
+# CMake doesn't seem to set the PIC flags right on certain 64 bit systems
+IF(NOT MINGW AND ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
+  ADD_COMPILER_FLAGS("-fPIC" CACHE)
+ENDIF()
+
+# Never omit frame pointers that could interfere with proper stack traces
+ADD_COMPILER_FLAGS("-fno-omit-frame-pointer" CACHE)
+
+# Enable non standard floating point optimisations
+ADD_COMPILER_FLAGS("-ffast-math" CACHE)
+
+# Use SSE if possible
+# Commented because this might not work for cross compiling
+#CHECK_CXX_COMPILER_FLAG(-msse _gcc_have_sse)
+#IF(_gcc_have_sse)
+#  ADD_COMPILER_FLAGS("-msse" CACHE)
+#ENDIF()
+
+IF(NOT MINGW)
+  # Have GCC visibility?
+  CHECK_CXX_COMPILER_FLAG("-fvisibility=hidden" _gcc_have_visibility)
+  IF(_gcc_have_visibility)
+    # Note: There is a possible bug with the flag in gcc < 4.2 and Debug versions
+    COMPARE_VERSION_STRINGS("${GCC_VERSION}" "4.2.0" _compare_result)
+    IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug" OR _compare_result GREATER -1)
+      ADD_COMPILER_FLAGS("-DORXONOX_GCC_VISIBILITY -fvisibility=default -fvisibility-inlines-hidden" CACHE)
+    ENDIF()
+  ENDIF(_gcc_have_visibility)
+ENDIF()
+
+# We have some unconformant code, disable an optimisation feature
+ADD_COMPILER_FLAGS("-fno-strict-aliasing" CACHE)
+
+# For newer GCC (4.3 and above), don't display hundreds of annoying deprecated
+# messages. Other versions don't seem to show any such warnings at all.
+ADD_COMPILER_FLAGS("-Wno-deprecated" CXX CACHE)
+
+# Since GCC 4.8 -Wall includes -Wunused-local-typedefs which triggers lots of warnings
+# in Boost headers, hence we disable it
+ADD_COMPILER_FLAGS("-Wno-unused-local-typedefs" CXX CACHE)
+
+# Always show why a precompiled header file could not be used
+ADD_COMPILER_FLAGS("-Winvalid-pch" CXX CACHE)
+
+# Increase warning level if requested
+IF(EXTRA_COMPILER_WARNINGS)
+  ADD_COMPILER_FLAGS("-Wall -Wextra -Wno-unused-parameter" CACHE)
+ELSE()
+  REMOVE_COMPILER_FLAGS("-Wextra -Wno-unused-parameter" CACHE)
+  ADD_COMPILER_FLAGS("-Wall" CACHE)
+ENDIF()
+
+# Linker flags
+IF(LINUX)
+  # Don't allow undefined symbols in a shared library
+  SET_LINKER_FLAGS("-Wl,--no-undefined" CACHE)
+ENDIF()
+
+# Add compiler and linker flags for MinGW
+IF (MINGW)
+  ADD_COMPILER_FLAGS("-gstabs+" Debug RelForDevs RelWithDebInfo CACHE)
+
+  ADD_LINKER_FLAGS("-Wl,--enable-auto-import" CACHE)
+ENDIF()
Index: /code/branches/RacingBots_FS18/cmake/CompilerConfigMSVC.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/CompilerConfigMSVC.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/CompilerConfigMSVC.cmake	(revision 11817)
@@ -0,0 +1,146 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Sets the right compiler and linker flags for the Microsoft Compiler.
+ #
+
+INCLUDE(FlagUtilities)
+
+# We make use of variadic macros, which is only supported by MSVC 8 and above
+IF(MSVC_VERSION LESS 1400)
+  MESSAGE(FATAL_ERROR "Microsoft Visual Studio versions below 8 (2005) are not supported.")
+ENDIF()
+
+# Orxonox only supports MSVC 8 and above, which gets asserted above
+SET(PCH_COMPILER_SUPPORT TRUE)
+
+# __COUNTER__ macro has been around since VS 2005
+# It might be required to make full build units work
+SET(HAVE_COUNTER_MACRO TRUE)
+
+
+#################### Compiler Flags #####################
+
+# CMake default flags : -DWIN32 -D_WINDOWS -W3 -Zm1000
+# additionally for CXX: -EHsc -GR
+# We keep these flags but reset the build specific flags
+SET_COMPILER_FLAGS("" Debug RelForDevs RelWithDebInfo Release MinSizeRel CACHE)
+
+# Make sure we define all the possible macros for identifying Windows
+ADD_COMPILER_FLAGS("-D__WIN32__ -D_WIN32"  CACHE)
+# Suppress some annoying warnings
+ADD_COMPILER_FLAGS("-D_CRT_SECURE_NO_WARNINGS" CACHE)
+ADD_COMPILER_FLAGS("-D_SCL_SECURE_NO_WARNINGS" CACHE)
+
+# Use multiprocessed compiling (like "make -j3" on Unix)
+ADD_COMPILER_FLAGS("-MP" CACHE)
+
+# Never omit frame pointers to avoid useless stack traces (the performance
+# loss is almost not measurable)
+ADD_COMPILER_FLAGS("-Oy-" CACHE)
+# Enable non standard floating point optimisations
+ADD_COMPILER_FLAGS("-fp:fast" CACHE)
+
+# Set build specific flags.
+# -MD[d]    Multithreaded [debug] shared MSVC runtime library
+# -Zi       Generate debug symbols
+# -O[d|2|1] No optimisations, optimise for speed, optimise for size
+# -Oi[-]    Use or disable use of intrinisic functions
+# -GL       Link time code generation (see -LTCG in linker flags)
+# -RTC1     Both basic runtime checks
+ADD_COMPILER_FLAGS("-MDd -Zi -Od -Oi  -D_DEBUG -RTC1" Debug          CACHE)
+ADD_COMPILER_FLAGS("-MD  -Zi -O2 -Oi  -DNDEBUG"       RelForDevs     CACHE)
+ADD_COMPILER_FLAGS("-MD  -Zi -O2 -Oi  -DNDEBUG -GL"   RelWithDebInfo CACHE)
+ADD_COMPILER_FLAGS("-MD      -O2 -Oi  -DNDEBUG -GL"   Release        CACHE)
+ADD_COMPILER_FLAGS("-MD      -O1 -Oi- -DNDEBUG -GL"   MinSizeRel     CACHE)
+
+
+####################### Warnings ########################
+
+# -WX    General warning Level X
+# -wdX   Disable specific warning X
+# -wnX   Set warning level of specific warning X to level n
+
+# Increase warning level if requested
+IF(EXTRA_COMPILER_WARNINGS)
+  REMOVE_COMPILER_FLAGS("-W1 -W2 -W3" CACHE)
+  ADD_COMPILER_FLAGS   ("-W4" CACHE)
+ELSE()
+  REMOVE_COMPILER_FLAGS("-W1 -W2 -W4" CACHE)
+  ADD_COMPILER_FLAGS   ("-W3" CACHE)
+ENDIF()
+
+# "<type> needs to have dll-interface to be used by clients'
+# Happens on STL member variables which are not public
+ADD_COMPILER_FLAGS("-w44251" CACHE)
+ADD_COMPILER_FLAGS("-w44275" CACHE) # For inheritance
+
+# Multiple assignment operators specified
+ADD_COMPILER_FLAGS("-w44522" CACHE)
+
+# Forcing values to bool
+ADD_COMPILER_FLAGS("-w44800" CACHE)
+
+# TODO: Resolve the cause of this warning!
+# ('class1' : inherits 'class2::member' via dominance)
+ADD_COMPILER_FLAGS("-w44250" CACHE)
+
+# conversion from 'double' to 'float', possible loss of data
+# conversion from 'ogg_int64_t' to 'long', possible loss of data
+# ADD_COMPILER_FLAGS("-w44244" CACHE)
+
+# "conversion from 'size_t' to 'unsigned int', possible loss of data
+# ADD_COMPILER_FLAGS("-w44267" CACHE)
+
+# "truncation from 'double' to 'float'
+# ADD_COMPILER_FLAGS("-w44305" CACHE)
+
+# "non dll-interface class used as base for dll-interface class"
+# ADD_COMPILER_FLAGS("-w44275" CACHE)
+
+
+##################### Linker Flags ######################
+
+# CMake default flags: -MANIFEST -STACK:10000000 -machine:I386
+# We keep these flags but reset the build specific flags
+SET_LINKER_FLAGS("" Debug RelForDevs RelWithDebInfo Release MinSizeRel CACHE)
+
+# Never fold multiple functions into a single one because we might compare
+# function pointers (for instance with network functions)
+ADD_LINKER_FLAGS("-OPT:NOICF" CACHE)
+
+# Very old flag that would do some extra Windows 98 alignment optimisations
+ADD_LINKER_FLAGS("-OPT:NOWIN98" MSVC80 CACHE)
+
+# Generate debug symbols
+ADD_LINKER_FLAGS("-DEBUG" Debug RelForDevs RelWithDebInfo CACHE)
+
+# Incremental linking speeds up development builds
+ADD_LINKER_FLAGS("-INCREMENTAL"    Debug   RelForDevs                CACHE)
+ADD_LINKER_FLAGS("-INCREMENTAL:NO" Release RelWithDebInfo MinSizeRel CACHE)
+
+# Eliminate unreferenced data
+ADD_LINKER_FLAGS("-OPT:REF" Release RelWithDebInfo MinSizeRel CACHE)
+
+# Link time code generation can improve run time performance at the cost of
+# hugely increased link time (the total build time is about the same though)
+ADD_LINKER_FLAGS("-LTCG" Release RelWithDebInfo MinSizeRel CACHE)
Index: /code/branches/RacingBots_FS18/cmake/InstallCheck.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/InstallCheck.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/InstallCheck.cmake	(revision 11817)
@@ -0,0 +1,30 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Prevents user from installing debug builds.
+ #  Note:
+ #    This script is executed at install time, not CMake time!
+ #
+
+IF("${CMAKE_INSTALL_CONFIG_NAME}" STREQUAL "Debug")
+  MESSAGE(FATAL_ERROR "Installing debug builds is not supported!")
+ENDIF()
Index: /code/branches/RacingBots_FS18/cmake/InstallConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/InstallConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/InstallConfig.cmake	(revision 11817)
@@ -0,0 +1,108 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the installation (paths, rpaths, options)
+ #
+
+IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) # Variable provided by CMake
+  IF("$ENV{ORXONOX_DEV}" OR TARDIS)
+    SET(_install_prefix_changed 1)
+    SET(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH
+        "Install path prefix, prepended onto install directories." FORCE)
+  ENDIF()
+ENDIF()
+
+SET(_info_text "Puts all installed files in subfolders of the install prefix path. That root folder can then be moved, copied and renamed as you wish. The executable will not write to folders like ~/.orxonox or \"Applictation Data\"")
+IF(UNIX AND NOT _install_prefix_changed)
+  OPTION(INSTALL_COPYABLE "${_info_text}" FALSE)
+ELSE()
+  OPTION(INSTALL_COPYABLE "${_info_text}" TRUE)
+ENDIF()
+
+IF(MSVC)
+  # Allow developers to install the debug symbols as well (safes the copying)
+  OPTION(INSTALL_PDB_FILES "Also installs the debug symbol files" FALSE)
+ENDIF()
+
+# Default relative installation paths
+SET(RUNTIME_INSTALL_DIRECTORY ${DEFAULT_RUNTIME_PATH})
+SET(LIBRARY_INSTALL_DIRECTORY ${DEFAULT_LIBRARY_PATH})
+SET(ARCHIVE_INSTALL_DIRECTORY ${DEFAULT_ARCHIVE_PATH})
+SET(MODULE_INSTALL_DIRECTORY  ${DEFAULT_MODULE_PATH})
+SET(PLUGIN_INSTALL_DIRECTORY  ${DEFAULT_PLUGIN_PATH})
+SET(DOC_INSTALL_DIRECTORY     ${DEFAULT_DOC_PATH})
+SET(DATA_INSTALL_DIRECTORY    ${DEFAULT_DATA_PATH})
+SET(CONFIG_INSTALL_DIRECTORY  ${DEFAULT_CONFIG_PATH})
+SET(LOG_INSTALL_DIRECTORY     ${DEFAULT_LOG_PATH})
+
+IF(NOT INSTALL_COPYABLE)
+  IF(LINUX)
+    # Using absolute paths
+    SET(RUNTIME_INSTALL_DIRECTORY games)
+    SET(LIBRARY_INSTALL_DIRECTORY lib/games/orxonox)
+    SET(ARCHIVE_INSTALL_DIRECTORY lib/games/orxonox/static)
+    SET(MODULE_INSTALL_DIRECTORY  lib/games/orxonox/modules)
+    SET(PLUGIN_INSTALL_DIRECTORY  lib/games/orxonox/plugins)
+    SET(DOC_INSTALL_DIRECTORY     share/doc/orxonox)
+    SET(DATA_INSTALL_DIRECTORY    share/games/orxonox)
+  ELSEIF(WIN32)
+    # Leave on default (installs to only one location anyway)
+  ELSEIF(APPLE)
+    # TODO: Figure out what's the best way to install the application
+  ENDIF()
+
+  # Leave empty because it is user and therefore runtime dependent
+  SET(CONFIG_INSTALL_DIRECTORY)
+  SET(LOG_INSTALL_DIRECTORY)
+ENDIF()
+
+################## Unix rpath ###################
+
+# Use, i.e. don't skip the full RPATH for the build tree
+SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
+
+# When building, don't use the install RPATH already
+# (but later on when installing)
+SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
+
+# The RPATH to be used when installing
+IF(INSTALL_COPYABLE)
+  # Get relative paths from run to lib and from module/plugin to lib directory.
+  FILE(RELATIVE_PATH _runtime_rpath "/${RUNTIME_INSTALL_DIRECTORY}" "/${LIBRARY_INSTALL_DIRECTORY}")
+  FILE(RELATIVE_PATH _module_rpath  "/${MODULE_INSTALL_DIRECTORY}" "/${LIBRARY_INSTALL_DIRECTORY}")
+  FILE(RELATIVE_PATH _plugin_rpath  "/${PLUGIN_INSTALL_DIRECTORY}" "/${LIBRARY_INSTALL_DIRECTORY}")
+  # $ORIGIN (with $ escaped) refers to the actual location of the library
+  # The UNIX loader recognises this special variable
+  SET(RUNTIME_RPATH "\$ORIGIN/${_runtime_rpath}")
+  SET(LIBRARY_RPATH "\$ORIGIN")
+  SET(MODULE_RPATH  "\$ORIGIN:\$ORIGIN/${_module_rpath}")
+  SET(PLUGIN_RPATH  "\$ORIGIN:\$ORIGIN/${_plugin_rpath}")
+ELSE()
+  SET(RUNTIME_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBRARY_INSTALL_DIRECTORY}")
+  SET(LIBRARY_RPATH "${CMAKE_INSTALL_PREFIX}/${LIBRARY_INSTALL_DIRECTORY}")
+  SET(MODULE_RPATH  "${LIBRARY_RPATH}:${CMAKE_INSTALL_PREFIX}/${MODULE_INSTALL_DIRECTORY}")
+  SET(PLUGIN_RPATH  "${LIBRARY_RPATH}:${CMAKE_INSTALL_PREFIX}/${PLUGIN_INSTALL_DIRECTORY}")
+ENDIF()
+
+# Add the automatically determined parts of the RPATH
+# which point to directories outside the build tree to the install RPATH
+SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
Index: /code/branches/RacingBots_FS18/cmake/LibraryConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/LibraryConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/LibraryConfig.cmake	(revision 11817)
@@ -0,0 +1,215 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the external libraries. Whenever possible, the find scripts
+ #    from the CMake module path are used, but that required some adjustments
+ #    for certain libraries (Boost, OpenAL, TCL)
+ #
+
+INCLUDE(CompareVersionStrings)
+INCLUDE(FindPackageHandleStandardArgs)
+
+# Prevent CMake from finding libraries in the installation folder on Windows.
+# There might already be an installation from another compiler
+IF(WIN32)
+  LIST(REMOVE_ITEM CMAKE_SYSTEM_PREFIX_PATH  "${CMAKE_INSTALL_PREFIX}")
+  LIST(REMOVE_ITEM CMAKE_SYSTEM_LIBRARY_PATH "${CMAKE_INSTALL_PREFIX}/bin")
+ENDIF()
+
+############## Platform Scripts #################
+
+# On Windows using a package causes way less problems
+SET(_option_msg "Set this to true to use precompiled dependecy archives")
+IF(WIN32 OR APPLE)
+  OPTION(DEPENDENCY_PACKAGE_ENABLE "${_option_msg}" ON)
+ELSE()
+  OPTION(DEPENDENCY_PACKAGE_ENABLE "${_option_msg}" FALSE)
+ENDIF()
+
+# Scripts for specific library and CMake config
+INCLUDE(LibraryConfigTardis)
+
+IF(DEPENDENCY_PACKAGE_ENABLE)
+  IF(APPLE AND NOT EXISTS ${CMAKE_SOURCE_DIR}/dependencies)
+    # Let CMake automatically download and extract the dependency package on Mac OS X
+    # TODO: Handle download errors and always select newest package
+    SET(_dep_package_current "OrxonoxDeps_110428_2.0_OSX.tar.bz2")
+    SET(_dep_package_url "http://svn.orxonox.net/ogre/apple/precompiled_dependencies")
+    MESSAGE(STATUS "Downloading Mac OS X dependency package.")
+    FILE(DOWNLOAD
+      ${_dep_package_url}/${_dep_package_current}
+      ${CMAKE_SOURCE_DIR}/${_dep_package_current}
+    )
+    MESSAGE(STATUS "Extracting Mac OS X dependency package.")
+    EXECUTE_PROCESS(
+      COMMAND ${CMAKE_COMMAND} -E tar -jxf ${_dep_package_current}
+      WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+      OUTPUT_FILE ${CMAKE_BINARY_DIR}/dep_pack_extract_log.keep_me
+    )
+    # Delete the dependency archive once we no longer need it
+    FILE(REMOVE ${CMAKE_SOURCE_DIR}/${_dep_package_current})
+  ENDIF()
+
+  GET_FILENAME_COMPONENT(_dep_dir_1 ${CMAKE_SOURCE_DIR}/../dependencies ABSOLUTE)
+  GET_FILENAME_COMPONENT(_dep_dir_2 ${CMAKE_SOURCE_DIR}/../lib_dist ABSOLUTE)
+  IF(MINGW)
+    SET(_compiler_prefix mingw)
+  ELSEIF(MSVC80)
+    SET(_compiler_prefix msvc8)
+  ELSEIF(MSVC90)
+    SET(_compiler_prefix msvc9)
+  ELSEIF(MSVC10)
+    SET(_compiler_prefix msvc10)
+  ENDIF()
+  FIND_PATH(DEPENDENCY_PACKAGE_DIR
+    NAMES version.txt
+    PATHS
+      ${CMAKE_SOURCE_DIR}/dependencies
+      ${_dep_dir_1}
+      ${_dep_dir_2}
+    PATH_SUFFIXES ${_compiler_prefix} ${_compiler_prefix}/dependencies
+    NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH
+  )
+  IF(NOT DEPENDENCY_PACKAGE_DIR)
+    MESSAGE(STATUS "Warning: Could not find dependency directory."
+                   "Disable LIBRARY_USE_PACKAGE if you have none intalled.")
+  ELSE()
+    IF(WIN32)
+      INCLUDE(PackageConfigMinGW)
+      INCLUDE(PackageConfigMSVC)
+      INCLUDE(PackageConfig) # For both msvc and mingw
+    ELSEIF(APPLE)
+      INCLUDE(PackageConfigOSX)
+    ENDIF(WIN32)
+  ENDIF()
+ENDIF(DEPENDENCY_PACKAGE_ENABLE)
+
+# User script
+SET(LIBRARY_CONFIG_USER_SCRIPT "" CACHE FILEPATH
+    "Specify a CMake script if you wish to write your own library path config.
+     See LibraryConfigTardis.cmake for an example.")
+IF(LIBRARY_CONFIG_USER_SCRIPT)
+  IF(EXISTS ${CMAKE_MODULE_PATH}/${LIBRARY_CONFIG_USER_SCRIPT})
+    INCLUDE(${CMAKE_MODULE_PATH}/${LIBRARY_CONFIG_USER_SCRIPT})
+  ENDIF()
+ENDIF(LIBRARY_CONFIG_USER_SCRIPT)
+
+
+############### Library finding #################
+# Performs the search and sets the variables    #
+
+#FIND_PACKAGE(ENet     1.2    REQUIRED)
+FIND_PACKAGE(CEGUI    0.6    REQUIRED)
+FIND_PACKAGE(Lua5.1          REQUIRED)
+FIND_PACKAGE(Ogg             REQUIRED)
+FIND_PACKAGE(Vorbis          REQUIRED)
+FIND_PACKAGE(ALUT            REQUIRED)
+FIND_PACKAGE(ZLIB            REQUIRED)
+
+IF(WIN32)
+  IF(MSVC)
+    # Check whether we can use Visual Leak Detector
+    FIND_PACKAGE(VLD QUIET)
+    FIND_PACKAGE(DbgHelp)
+    FIND_PACKAGE(DirectX       REQUIRED)
+  ENDIF()
+ENDIF()
+
+
+##### OpenAL #####
+FIND_PACKAGE(OpenAL REQUIRED)
+# Also use parent include dir (without AL/) for ALUT
+IF(OPENAL_INCLUDE_DIR MATCHES "/AL$")
+  GET_FILENAME_COMPONENT(ALT_OPENAL_INCLUDE_DIR ${OPENAL_INCLUDE_DIR} PATH)
+ENDIF()
+SET(OPENAL_INCLUDE_DIRS ${OPENAL_INCLUDE_DIR} ${ALT_OPENAL_INCLUDE_DIR})
+# Notfiy user
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenAL DEFAULT_MSG OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
+# Hide variables created by the script
+MARK_AS_ADVANCED(OPENAL_INCLUDE_DIR OPENAL_LIBRARY)
+
+##### Tcl #####
+# We only require Tcl, so avoid confusing user about other Tcl stuff by
+# applying a little workaround
+SET(Tclsh_FIND_QUIETLY TRUE)
+FIND_PACKAGE(TCL QUIET)
+# Display messages separately
+SET(TCL_FIND_QUIETLY FALSE)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(TCL DEFAULT_MSG TCL_LIBRARY TCL_INCLUDE_PATH)
+
+##### Boost #####
+# Expand the next statement if newer boost versions are released
+SET(Boost_ADDITIONAL_VERSIONS 1.40 1.40.0 1.41 1.41.0 1.42 1.42.0 1.43 1.43.0
+                              1.44 1.44.0 1.45 1.45.0 1.46 1.46.0 1.46.1 1.49.0
+                              1.53.0)
+FIND_PACKAGE(Boost 1.40 REQUIRED thread filesystem system date_time)
+# No auto linking, so this option is useless anyway
+MARK_AS_ADVANCED(Boost_LIB_DIAGNOSTIC_DEFINITIONS)
+
+##### OGRE #####
+FIND_PACKAGE(OGRE 1.6 REQUIRED)
+# For Ogre >= 1.7, we might need a threading library
+# Variables are either defined by dependency package config or by FindOGRE
+IF(OGRE_NEEDS_POCO)
+  FIND_PACKAGE(POCO REQUIRED)
+  # Always link against POCO too because of threading
+  SET(OGRE_LIBRARY ${OGRE_LIBRARY} ${POCO_LIBRARY})
+ELSEIF(OGRE_NEEDS_BOOST)
+  # Always link against boost too because of threading
+  SET(OGRE_LIBRARY ${OGRE_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY})
+ENDIF()
+
+
+####### Static/Dynamic linking options ##########
+
+# On Windows dynamically linked libraries need some special treatment
+# You may want to edit these settings if you provide your own libraries
+# Note: Default option in the libraries vary, but our default option is dynamic
+IF(WIN32)
+  OPTION(LINK_BOOST_DYNAMIC  "Link Boost dynamically on Windows" TRUE)
+  OPTION(LINK_CEGUI_DYNAMIC  "Link CEGUI dynamicylly on Windows" TRUE)
+  #OPTION(LINK_ENET_DYNAMIC   "Link ENet dynamically on Windows" TRUE)
+  OPTION(LINK_OGRE_DYNAMIC   "Link OGRE dynamically on Windows" TRUE)
+  OPTION(LINK_TCL_DYNAMIC    "Link TCL dynamically on Windows" TRUE)
+  OPTION(LINK_ZLIB_DYNAMIC   "Link ZLib dynamically on Windows" TRUE)
+  OPTION(LINK_LUA5.1_DYNAMIC "Link Lua dynamically on Windows" TRUE)
+
+  IF(DEPENDENCY_PACKAGE_ENABLE)
+    MARK_AS_ADVANCED(
+      LINK_BOOST_DYNAMIC LINK_CEGUI_DYNAMIC #LINK_ENET_DYNAMIC
+      LINK_OGRE_DYNAMIC  LINK_TCL_DYNAMIC   LINK_ZLIB_DYNAMIC
+      LINK_LUA5.1_DYNAMIC
+    )
+  ENDIF()
+ENDIF(WIN32)
+
+
+################# OGRE Plugins ##################
+
+# Check the plugins and determine the plugin folder
+# You can give a hint by setting the environment variable ENV{OGRE_PLUGIN_DIR}
+INCLUDE(CheckOGREPlugins)
+# Note 1: First argument (as string!) are for mandatory plugins, second one is
+#         for optional ones.
+# Note 2: Render systems are found automatically (at least one required)
+CHECK_OGRE_PLUGINS("Plugin_ParticleFX" "Plugin_CgProgramManager")
+
Index: /code/branches/RacingBots_FS18/cmake/LibraryConfigTardis.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/LibraryConfigTardis.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/LibraryConfigTardis.cmake	(revision 11817)
@@ -0,0 +1,72 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Adrian Friedli
+ #  Description:
+ #    Sets the correct find script paths on the ETH Tardis workstations.
+ #    Also sets the TARDIS variable.
+ #
+
+IF(LINUX AND EXISTS /etc/hostname)
+  FILE(STRINGS /etc/hostname HOSTNAME LIMIT_COUNT 1)
+  IF(${HOSTNAME} MATCHES "^tardis-[a-z][0-9][0-9]$")
+    SET (TARDIS ON)
+  ENDIF()
+ENDIF()
+
+IF(TARDIS)
+  MESSAGE(STATUS "Running on D-ITET isg.ee Tardis Computer. Using customized paths.")
+
+  SET(DO_NOT_UNLOAD_PLUGINS ON)
+
+#  SET(CMAKE_C_COMPILER "gcc-4.1.1")
+#  SET(CMAKE_CXX_COMPILER "g++-4.1.1")
+
+#  LIST(APPEND CMAKE_INCLUDE_PATH "/usr/pack/cegui-0.6.2-sd")
+#  LIST(APPEND CMAKE_LIBRARY_PATH "/usr/pack/cegui-0.6.2-sd/amd64-debian-linux5.0")
+#  LIST(APPEND CMAKE_INCLUDE_PATH "/usr/pack/ogre-1.6.1-sd")
+#  LIST(APPEND CMAKE_LIBRARY_PATH "/usr/pack/ogre-1.6.1-sd/amd64-debian-linux5.0")
+
+  #Solution to the problem that on the new tardis machines, we needed to run Orxonox with the command
+  # bash && LD_LIBRARY_PATH=/usr/pack/libcg-1.5-sd/amd64-debian-linux3.1/lib/ ./run
+  link_directories(/usr/pack/libcg-1.5-sd/amd64-debian-linux3.1/lib/)
+  #SET(ENV{CEGUIDIR}    "/usr/pack/cegui-0.6.2-sd;/usr/pack/cegui-0.6.2-sd/i686-debian-linux5.0")
+  #SET(ENV{ENETDIR}     "/usr/pack/enet-1.2-sd;/usr/pack/enet-1.2-sd/i686-debian-linux4.0")
+  #SET(ENV{ALUTDIR}     "/usr/pack/openal-0.0.8-cl;/usr/pack/openal-0.0.8-cl/i686-debian-linux3.1")
+  #SET(ENV{OGGDIR}      "/usr/pack/oggvorbis-1.0-ds;/usr/pack/oggvorbis-1.0-ds/i686-debian-linux3.0")
+  #SET(ENV{VORBISDIR}   "/usr/pack/oggvorbis-1.0-ds;/usr/pack/oggvorbis-1.0-ds/i686-debian-linux3.0")
+  #SET(ENV{LUA5.1_DIR}  "/usr/pack/lua-5.1.4-sd;/usr/pack/lua-5.1.4-sd/i686-debian-linux4.0")
+  #SET(ENV{OGRE_HOME}   "/usr/pack/ogre-1.4.9-sd;/usr/pack/ogre-1.4.9-sd/i686-debian-linux4.0")
+  #SET(ENV{OPENALDIR}   "/usr/pack/openal-0.0.8-cl;/usr/pack/openal-0.0.8-cl/i686-debian-linux3.1")
+  #SET(TCL_INCLUDE_PATH "/usr/pack/tcltk-8.4.9.linux-mo/include")
+
+  # New paths for the new tardis system. The ogre includes need to be at ../dependencies.
+  SET(OGRE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../dependencies/ogre_src_v1-8-0/OgreMain/include/")
+  SET(OGRE_LIBRARY_OPTIMIZED "/usr/lib/x86_64-linux-gnu/libOgreMain.so.1.8.0")
+  SET(OGRE_PLUGIN_Plugin_ParticleFX_OPTIMIZED "/usr/lib/x86_64-linux-gnu/OGRE-1.8.0/Plugin_ParticleFX.so")
+  SET(OGRE_PLUGIN_RenderSystem_GL_OPTIMIZED "/usr/lib/x86_64-linux-gnu/OGRE-1.8.0/RenderSystem_GL.so")
+
+
+  # Sandro fix: add flag that re-enables boost threads. This makes the combination
+  #             of GCC version > 4.7 and older libboost work. See 
+  # http://stackoverflow.com/questions/5389853/doesnt-compile-if-included-boost-thread-in-linux-ubuntu10-10
+  #             for more information.
+  ADD_COMPILER_FLAGS("-D_GLIBCXX__PTHREADS=1" CXX CACHE)
+ENDIF(TARDIS)
Index: /code/branches/RacingBots_FS18/cmake/PackageConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/PackageConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/PackageConfig.cmake	(revision 11817)
@@ -0,0 +1,112 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    General package configuration. Merely sets the include paths.
+ #    Library files are treated separately.
+ #
+
+IF(NOT _INTERNAL_PACKAGE_MESSAGE)
+  MESSAGE(STATUS "Using library package for the dependencies.")
+  SET(_INTERNAL_PACKAGE_MESSAGE 1 CACHE INTERNAL "Do not edit!" FORCE)
+ENDIF()
+
+# Ogre versions >= 1.7 require the POCO library on Windows with MSVC for threading
+COMPARE_VERSION_STRINGS(${DEPENDENCY_VERSION} 5 _result TRUE)
+IF(NOT _result EQUAL -1 AND NOT APPLE)
+  # In dependency package 7 poco is not used anymore - instead we use boost
+  COMPARE_VERSION_STRINGS(${DEPENDENCY_VERSION} 7 _result TRUE)
+  IF(NOT _result EQUAL -1)
+    SET(OGRE_NEEDS_BOOST TRUE)
+  ELSE()
+    SET(OGRE_NEEDS_POCO TRUE)
+  ENDIF()
+ENDIF()
+
+# Include paths and other special treatments
+SET(ENV{ALUTDIR}               ${DEP_INCLUDE_DIR}/freealut)
+SET(ENV{BOOST_ROOT}            ${DEP_INCLUDE_DIR}/boost)
+SET(ENV{CEGUIDIR}              ${DEP_INCLUDE_DIR}/cegui)
+SET(ENV{DBGHELP_DIR}           ${DEP_INCLUDE_DIR}/dbghelp)
+SET(ENV{DXSDK_DIR}             ${DEP_INCLUDE_DIR}/directx)
+#SET(ENV{ENETDIR}               ${DEP_INCLUDE_DIR}/enet)
+SET(ENV{LUA5.1_DIR}            ${DEP_INCLUDE_DIR}/lua)
+SET(ENV{OGGDIR}                ${DEP_INCLUDE_DIR}/libogg)
+SET(ENV{VORBISDIR}             ${DEP_INCLUDE_DIR}/libvorbis)
+SET(ENV{OGRE_HOME}             ${DEP_INCLUDE_DIR}/ogre)
+SET(ENV{OGRE_PLUGIN_DIR}       ${DEP_BINARY_DIR})
+SET(ENV{OPENALDIR}             ${DEP_INCLUDE_DIR}/openal)
+SET(ENV{POCODIR}               ${DEP_INCLUDE_DIR}/poco)
+LIST(APPEND CMAKE_INCLUDE_PATH ${DEP_INCLUDE_DIR}/tcl/include)
+LIST(APPEND CMAKE_INCLUDE_PATH ${DEP_INCLUDE_DIR}/zlib/include)
+
+### INSTALL ###
+
+# Tcl script library
+INSTALL(
+  DIRECTORY ${DEP_LIBRARY_DIR}/tcl/
+  DESTINATION lib/tcl
+)
+
+# On Windows, DLLs have to be in the executable folder, install them
+IF(WIN32 AND DEP_BINARY_DIR)
+  ## DEBUG
+  # When installing a debug version, we really can't know which libraries
+  # are used in released mode because there might be deps of deps.
+  # --> Copy all of them, except the debug databases
+  INSTALL(
+    DIRECTORY ${DEP_BINARY_DIR}/
+    DESTINATION bin
+    CONFIGURATIONS Debug
+    REGEX "^.*\\.pdb$" EXCLUDE
+  )
+
+  ## RELEASE
+  IF(EXISTS ${DEP_BINARY_DIR}/install_manifest.txt)
+    FILE(STRINGS ${DEP_BINARY_DIR}/install_manifest.txt _files)
+    FOREACH(_file ${_files})
+      INSTALL(
+        FILES ${DEP_BINARY_DIR}/${_file}
+        DESTINATION bin
+        CONFIGURATIONS RelForDevs Release RelWithDebInfo MinSizeRel
+      )
+      IF(INSTALL_PDB_FILES) # MSVC specific: install debug symbols files
+        GET_FILENAME_COMPONENT(_base_name ${_file} NAME_WE)
+        IF(EXISTS ${DEP_BINARY_DIR}/${_base_name}.pdb)
+          INSTALL(
+            FILES ${DEP_BINARY_DIR}/${_base_name}.pdb
+            DESTINATION bin
+            CONFIGURATIONS RelForDevs RelWithDebInfo
+          )
+        ENDIF()
+      ENDIF()
+    ENDFOREACH(_file)
+  ELSE()
+    # Try to filter out all the debug libraries. If the regex doesn't do the
+    # job anymore, simply adjust it.
+    INSTALL(
+      DIRECTORY ${DEP_BINARY_DIR}/
+      DESTINATION bin
+      CONFIGURATIONS RelForDevs Release RelWithDebInfo MinSizeRel
+      REGEX "_[Dd]\\.[a-zA-Z0-9+-]+$|-mt-gd-|^.*\\.pdb$" EXCLUDE
+    )
+  ENDIF()
+ENDIF()
Index: /code/branches/RacingBots_FS18/cmake/PackageConfigMSVC.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/PackageConfigMSVC.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/PackageConfigMSVC.cmake	(revision 11817)
@@ -0,0 +1,81 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Sets the library directories when using precompiled dependency archives
+ #  Note:
+ #    When setting ENV${} variables, make sure to use quotes for lists
+ #
+
+IF(MSVC)
+
+  INCLUDE(CheckPackageVersion)
+  CHECK_PACKAGE_VERSION(6.0 7.0)
+
+  # 64 bit system?
+  IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    SET(BINARY_POSTFIX x64)
+  ELSE()
+    SET(BINARY_POSTFIX x86)
+  ENDIF()
+
+  # Choose right MSVC version
+  STRING(REGEX REPLACE "^Visual Studio ([0-9][0-9]?).*$" "\\1"
+         _msvc_version "${CMAKE_GENERATOR}")
+
+  SET(DEP_INCLUDE_DIR ${DEPENDENCY_PACKAGE_DIR}/include)
+  SET(DEP_LIBRARY_DIR ${DEPENDENCY_PACKAGE_DIR}/lib/msvc${_msvc_version}-${BINARY_POSTFIX})
+  SET(DEP_BINARY_DIR  ${DEPENDENCY_PACKAGE_DIR}/bin/msvc${_msvc_version}-${BINARY_POSTFIX})
+  IF(NOT EXISTS ${DEP_LIBRARY_DIR})
+    message(FATAL_ERROR "No binaries found for your MSVC Version (${CMAKE_GENERATOR})")
+  ENDIF()
+
+  # Also the directory with the runtime libraries
+  SET(RUNTIME_LIBRARY_DIRECTORY ${DEP_BINARY_DIR})
+
+  # Sets the library path for the FIND_LIBRARY
+  SET(CMAKE_LIBRARY_PATH ${DEP_LIBRARY_DIR})
+  
+  # Certain find scripts don't behave as ecpected to we have
+  # to specify the libraries ourselves. (dependency older than 7 only)
+  COMPARE_VERSION_STRINGS(${DEPENDENCY_VERSION} 7 _result TRUE)
+  IF(_result EQUAL -1)
+    IF(MSVC10)
+      SET(TCL_LIBRARY
+        optimized ${DEP_LIBRARY_DIR}/tcl85t.lib
+        debug     ${DEP_LIBRARY_DIR}/tcl85tg.lib
+        CACHE FILEPATH ""
+      )
+      SET(ZLIB_LIBRARY
+        optimized ${DEP_LIBRARY_DIR}/zlib-vc100.lib
+        debug     ${DEP_LIBRARY_DIR}/zlib-vc100_d.lib
+        CACHE FILEPATH ""
+      )
+    ELSE()
+      SET(TCL_LIBRARY  ${DEP_LIBRARY_DIR}/tcl85.lib CACHE FILEPATH "")
+      SET(ZLIB_LIBRARY ${DEP_LIBRARY_DIR}/zdll.lib  CACHE FILEPATH "")
+    ENDIF()
+  ENDIF()
+
+  # Part of Platform SDK and usually gets linked automatically
+  SET(WMI_LIBRARY  wbemuuid.lib)
+
+ENDIF(MSVC)
Index: /code/branches/RacingBots_FS18/cmake/PackageConfigMinGW.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/PackageConfigMinGW.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/PackageConfigMinGW.cmake	(revision 11817)
@@ -0,0 +1,63 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Sets the library directories when using precompiled dependency archives
+ #  Note:
+ #    When setting ENV${} variables, make sure to use quotes for lists
+ #
+
+IF(MINGW)
+
+  INCLUDE(CheckPackageVersion)
+  CHECK_PACKAGE_VERSION(7.1 8.0)
+
+  # 64 bit system?
+  IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    SET(BINARY_POSTFIX x64)
+  ELSE()
+    SET(BINARY_POSTFIX x86)
+  ENDIF()
+
+  SET(DEP_INCLUDE_DIR ${DEPENDENCY_PACKAGE_DIR}/include)
+  SET(DEP_LIBRARY_DIR ${DEPENDENCY_PACKAGE_DIR}/lib/mingw-${BINARY_POSTFIX})
+  SET(DEP_BINARY_DIR  ${DEPENDENCY_PACKAGE_DIR}/bin/mingw-${BINARY_POSTFIX})
+
+  # Also the directory with the runtime libraries
+  SET(RUNTIME_LIBRARY_DIRECTORY ${DEP_BINARY_DIR})
+
+  # Sets the library path for the FIND_LIBRARY
+  SET(CMAKE_LIBRARY_PATH ${DEP_LIBRARY_DIR} ${DEP_BINARY_DIR})
+
+  # Certain find scripts don't behave as ecpected to we have
+  # to specify the libraries ourselves.
+  SET(TCL_LIBRARY  ${DEP_BINARY_DIR}/tcl85.dll CACHE FILEPATH "")
+  SET(ZLIB_LIBRARY ${DEP_BINARY_DIR}/libzlib.dll CACHE FILEPATH "")
+
+  # Define libraries that are part of mingw64:
+  #  - DirectX (Needed for OIS):
+  SET(DIRECTX_LIBRARIES dinput8 dxguid)
+  SET(WMI_LIBRARY wbemuuid)
+  #  - DbgHelp (Needed for SignalHandler in util library):
+  SET(DBGHELP_FOUND true)
+  SET(DBGHELP_LIBRARY dbghelp)
+
+ENDIF(MINGW)
Index: /code/branches/RacingBots_FS18/cmake/PackageConfigOSX.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/PackageConfigOSX.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/PackageConfigOSX.cmake	(revision 11817)
@@ -0,0 +1,103 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    OS X package configuration
+ #
+
+INCLUDE(CheckPackageVersion)
+
+CHECK_PACKAGE_VERSION(2.0)
+
+IF(NOT _INTERNAL_PACKAGE_MESSAGE)
+  MESSAGE(STATUS "Using library package for the dependencies.")
+  
+  # The following shell script sets the appropriate install_names for our libraries
+  # and therefore it must be run before anything else is set, dep-package-wise.
+  IF(NOT EXISTS ${CMAKE_BINARY_DIR}/dep_pack_install_log.keep_me)
+    MESSAGE(STATUS "Installing Mac OS X dependency package to current dir.")
+    EXECUTE_PROCESS(
+      COMMAND ${DEPENDENCY_PACKAGE_DIR}/install_dependencies.sh
+      WORKING_DIRECTORY ${DEPENDENCY_PACKAGE_DIR}
+      OUTPUT_FILE ${CMAKE_BINARY_DIR}/dep_pack_install_log.keep_me 
+    )
+  ENDIF()
+  SET(_INTERNAL_PACKAGE_MESSAGE 1 CACHE INTERNAL "Do not edit!" FORCE)
+ENDIF()
+
+SET(DEP_INCLUDE_DIR   ${DEPENDENCY_PACKAGE_DIR}/include)
+SET(DEP_LIBRARY_DIR   ${DEPENDENCY_PACKAGE_DIR}/lib)
+SET(DEP_BINARY_DIR    ${DEPENDENCY_PACKAGE_DIR}/bin)
+SET(DEP_FRAMEWORK_DIR ${DEPENDENCY_PACKAGE_DIR}/Library/Frameworks)
+
+# Sets the library and framwork paths for the FIND_LIBRARY commands
+SET(CMAKE_LIBRARY_PATH   ${DEP_LIBRARY_DIR})
+SET(CMAKE_FRAMEWORK_PATH ${DEP_FRAMEWORK_DIR})
+
+# Include paths and other special treatments
+SET(ENV{BOOST_ROOT}      ${DEPENDENCY_PACKAGE_DIR})
+SET(ENV{OGGDIR}          ${DEP_INCLUDE_DIR})
+SET(ENV{VORBISDIR}       ${DEP_INCLUDE_DIR})
+SET(ENV{OGRE_PLUGIN_DIR} ${DEP_BINARY_DIR})
+
+# Linking to OGRE requires linking to the boost threading library
+SET(OGRE_NEEDS_BOOST TRUE)
+
+# For OS X 10.5 we have to ship modified headers to make it compile
+# on gcc >= 4.2 (binaries stay the same)
+# Sets the library path for the FIND_LIBRARY
+IF(CMAKE_SYSTEM_VERSION STREQUAL "10.5")
+  SET(ENV{OPENALDIR} ${DEP_INCLUDE_DIR}/openal)
+ENDIF()
+
+### INSTALL ###
+
+# Tcl script library
+# TODO: How does this work on OS X?
+# Concerning all OS X install procedures: use CPACK
+#INSTALL(
+#  DIRECTORY ${DEP_LIBRARY_DIR}/tcl/
+#  DESTINATION lib/tcl
+#)
+
+# TODO: Install on OSX
+IF(FALSE)
+  ## DEBUG
+  # When installing a debug version, we really can't know which libraries
+  # are used in released mode because there might be deps of deps.
+  # --> Copy all of them, except the debug databases
+  INSTALL(
+    DIRECTORY ${DEP_BINARY_DIR}/
+    DESTINATION bin
+    CONFIGURATIONS Debug
+    REGEX "^.*\\.pdb$" EXCLUDE
+  )
+
+  ## RELEASE
+  # Try to filter out all the debug libraries. If the regex doesn't do the
+  # job anymore, simply adjust it.
+  INSTALL(
+    DIRECTORY ${DEP_BINARY_DIR}/
+    DESTINATION bin
+    CONFIGURATIONS RelForDevs Release RelWithDebInfo MinSizeRel
+    REGEX "_[Dd]\\.[a-zA-Z0-9+-]+$|-mt-gd-|^.*\\.pdb$" EXCLUDE
+  )
+ENDIF()
Index: /code/branches/RacingBots_FS18/cmake/PrepareDevBundle.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/PrepareDevBundle.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/PrepareDevBundle.cmake	(revision 11817)
@@ -0,0 +1,59 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Kevin Young
+ #  Description:
+ #    Creates the file structure for the development application bundle
+ #
+
+IF(NOT CMAKE_CONFIGURATION_TYPES)
+  SET(_subdirs .)
+  SET(_default_subdir .)
+ELSE()
+  SET(_subdirs ${CMAKE_CONFIGURATION_TYPES})
+  SET(_default_subdir) # No default subdir
+ENDIF()
+
+FOREACH(_subdir ${_subdirs})
+  GET_FILENAME_COMPONENT(CURRENT_RUNTIME_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${_subdir} ABSOLUTE)
+
+  # Convenience variables
+  # Note that this is just an empty bundle! The executable itself will
+  # be added at build time
+  SET(DEVBUNDLE_CURRENT_DIR "${CURRENT_RUNTIME_DIR}/${PROJECT_NAME}.app/Contents")
+  SET(DEVBUNDLE_CURRENT_BIN "${DEVBUNDLE_CURRENT_DIR}/MacOS")
+  SET(DEVBUNDLE_CURRENT_RESOURCES "${DEVBUNDLE_CURRENT_DIR}/Resources")
+  SET(DEVBUNDLE_DEFAULT_LANGFILE "English.lproj")
+  SET(DEVBUNDLE_NIB_FILE "MainMenu.nib")
+
+  # Create bundle folder structure
+  FILE(MAKE_DIRECTORY "${DEVBUNDLE_CURRENT_DIR}")
+  FILE(MAKE_DIRECTORY "${DEVBUNDLE_CURRENT_BIN}")
+  FILE(MAKE_DIRECTORY "${DEVBUNDLE_CURRENT_RESOURCES}")
+  FILE(MAKE_DIRECTORY "${DEVBUNDLE_CURRENT_RESOURCES}/${DEVBUNDLE_DEFAULT_LANGFILE}/${DEVBUNDLE_NIB_FILE}")
+  
+  # Populate with Info.plist, NIB-file and the Icon.icns
+  CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/Orxonox-Info.plist" "${DEVBUNDLE_CURRENT_DIR}/Info.plist")
+  CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/Icon.icns" "${DEVBUNDLE_CURRENT_RESOURCES}/Icon.icns" COPYONLY)
+  CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/${DEVBUNDLE_DEFAULT_LANGFILE}/${DEVBUNDLE_NIB_FILE}/designable.nib" "${DEVBUNDLE_CURRENT_RESOURCES}/${DEVBUNDLE_DEFAULT_LANGFILE}/${DEVBUNDLE_NIB_FILE}/designable.nib" COPYONLY)
+  CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/${DEVBUNDLE_DEFAULT_LANGFILE}/${DEVBUNDLE_NIB_FILE}/keyedobjects.nib" "${DEVBUNDLE_CURRENT_RESOURCES}/${DEVBUNDLE_DEFAULT_LANGFILE}/${DEVBUNDLE_NIB_FILE}/keyedobjects.nib" COPYONLY)
+  CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/${DEFAULT_DATA_PATH}/mac/${DEVBUNDLE_DEFAULT_LANGFILE}/InfoPlist.strings" "${DEVBUNDLE_CURRENT_RESOURCES}/${DEVBUNDLE_DEFAULT_LANGFILE}/InfoPlist.strings")
+
+ENDFOREACH(_subdir)
Index: /code/branches/RacingBots_FS18/cmake/tools/BuildUnits.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/BuildUnits.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/BuildUnits.cmake	(revision 11817)
@@ -0,0 +1,146 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #
+
+FUNCTION(GENERATE_BUILD_UNITS _target_name _all_files_var)
+  SET(_source_files)
+  SET(_total_file_count 0)
+
+  # Count the number of actual C++ source files
+  FOREACH(_file ${${_all_files_var}})
+    # Only look at C++ source files
+    IF(_file MATCHES "\\.(cpp|cc|cxx)$")
+      # Some files might be marked as not to compile at all
+      GET_SOURCE_FILE_PROPERTY(_skip1 ${_file} HEADER_FILE_ONLY)
+      GET_SOURCE_FILE_PROPERTY(_skip2 ${_file} EXCLUDE_FROM_BUILD_UNITS)
+      IF(NOT _skip1 AND NOT _skip2)
+        GET_SOURCE_FILE_PROPERTY(_size ${_file} BUILD_UNIT_SIZE)
+        IF(NOT _size)
+          SET(_size 1)
+        ENDIF()
+        # Append file AND size to the list (like storing an std::pair)
+        LIST(APPEND _source_files ${_file} ${_size})
+        MATH(EXPR _total_file_count "${_total_file_count} + ${_size}")
+        # Don't compile
+        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
+      ENDIF()
+    ENDIF()
+  ENDFOREACH(_file)
+
+  # Get number of build units we have to make. The default is NR_OF_BUILD_UNITS
+  # However we can specify different values in a config file
+  SET(_config ${BUILD_UNITS_CONFIG_${NR_OF_BUILD_UNITS}_THREADS})
+  SET(_nr_of_units)
+  IF(_config)
+    LIST(FIND _config ${_target_name} _index)
+    IF(NOT _index EQUAL -1)
+      # Nr of build units is the next element in the list (we assume it exists)
+      MATH(EXPR _index "${_index} + 1")
+      LIST(GET _config ${_index} _nr_of_units)
+    ENDIF()
+  ENDIF()
+  IF(NOT _nr_of_units)
+    # Use default as specified (e.g. "full4" --> 4) or 1 for externals
+    IF(_arg_ORXONOX_EXTERNAL)
+      SET(_nr_of_units 1)
+    ELSE()
+      SET(_nr_of_units ${NR_OF_BUILD_UNITS})
+    ENDIF()
+  ENDIF()
+
+  # Disable precompiled header files for targets with two or less build units
+  IF(_nr_of_units LESS 3)
+    SET(PCH_DISABLE_${_target_name} TRUE PARENT_SCOPE)
+  ENDIF()
+
+  SET(_remaining_files ${_total_file_count})
+  SET(_remaining_units ${_nr_of_units})
+  SET(_unit_nr 1)
+  # Loop counts back from ${_nr_of_units} to 1
+  FOREACH(_remaining_units RANGE ${_nr_of_units} 1 -1)
+    # Use integer division to get the current build unit size
+    MATH(EXPR _aimed_size "${_remaining_files} / ${_remaining_units}")
+
+    SET(_current_size 0)
+    SET(_current_unit)
+
+    SET(_file_index 0)
+    LIST(LENGTH _source_files _list_size)
+    WHILE(${_file_index} LESS ${_list_size} AND NOT ${_current_size} EQUAL ${_aimed_size})
+      # _source_files stores pairs of values (file followed by its size)
+      MATH(EXPR _size_index "${_file_index} + 1")
+      LIST(GET _source_files ${_file_index} _file)
+      LIST(GET _source_files ${_size_index} _size)
+
+      MATH(EXPR _new_size "${_current_size} + ${_size}")
+      IF(${_new_size} GREATER ${_aimed_size})
+        # Try next file in list (jump 2 because pairs are stored)
+        MATH(EXPR _file_index "${_file_index} + 2")
+      ELSE()
+        SET(_current_size ${_new_size})
+        LIST(APPEND _current_unit ${_file})
+        # Remove from _source_files list
+        LIST(REMOVE_AT _source_files ${_file_index} ${_size_index})
+        MATH(EXPR _list_size "${_list_size} - 2")
+      ENDIF()
+    ENDWHILE()
+
+    # Finalise
+    LIST(LENGTH _current_unit _nr_of_included_files)
+    IF(_nr_of_included_files EQUAL 1)
+      # If unit consists of one file, we can compile it the old fashioned way
+      SET_SOURCE_FILES_PROPERTIES(${_current_unit} PROPERTIES HEADER_FILE_ONLY FALSE)
+    ELSEIF(_nr_of_included_files GREATER 1)
+      # Assemble unit by writing some #include statements
+      SET(_include_string)
+      FOREACH(_file ${_current_unit})
+        SET(_include_string "${_include_string}#include \"${_file}\"\n")
+      ENDFOREACH(_file)
+
+      # Generate the filename
+      IF(NOT _nr_of_units EQUAL 1)
+        SET(_suffix ${_unit_nr})
+      ENDIF()
+      SET(_unit_file ${CMAKE_CURRENT_BINARY_DIR}/${_target_name}BuildUnit${_suffix}.cc)
+      # Only write if content has changed (avoids recompile)
+      IF(EXISTS ${_unit_file})
+        FILE(READ ${_unit_file} _file_include_string)
+      ENDIF()
+      IF(NOT _include_string STREQUAL "${_file_include_string}")
+        FILE(WRITE ${_unit_file} "${_include_string}")
+      ENDIF()
+
+      LIST(APPEND _build_units ${_unit_file})
+
+      # Increase file name counter
+      MATH(EXPR _unit_nr "${_unit_nr} + 1")
+    ENDIF()
+
+    # Compute remaining files
+    MATH(EXPR _remaining_files "${_remaining_files} - ${_current_size}")
+  ENDFOREACH(_remaining_units)
+
+  # Add units to list of source files (function, not macro --> parent scope)
+  # Do this ONCE because parent scope changes will NOT be visible here
+  SET(${_all_files_var} ${${_all_files_var}} ${_build_units} PARENT_SCOPE)
+
+ENDFUNCTION(GENERATE_BUILD_UNITS)
Index: /code/branches/RacingBots_FS18/cmake/tools/CapitaliseName.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/CapitaliseName.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/CapitaliseName.cmake	(revision 11817)
@@ -0,0 +1,33 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Examples:
+ #    "orxonox"  --> "Orxonox"
+ #    "ORXONOX"  --> "ORXONOX"
+ #    "1orxonox" --> "1orxonox"
+ #
+
+FUNCTION(CAPITALISE_NAME _name _output_var)
+  STRING(SUBSTRING "${_name}" 0 1 _first_letter)
+  STRING(TOUPPER "${_first_letter}" _first_letter)
+  STRING(REGEX REPLACE "^.(.*)$" "\\1" _rest "${_name}")
+  SET(${_output_var} "${_first_letter}${_rest}" PARENT_SCOPE)
+ENDFUNCTION(CAPITALISE_NAME)
Index: /code/branches/RacingBots_FS18/cmake/tools/CheckOGREPlugins.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/CheckOGREPlugins.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/CheckOGREPlugins.cmake	(revision 11817)
@@ -0,0 +1,119 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Finds OGRE plugins and their folder, which has to be unique each set
+ #    of plugins (Debug, Release).
+ #    Specify arguments as strings: mandatory and optional plugins.
+ #    Input:
+ #      _mandatory_plugins Have to be found, error issued otherwise
+ #      _optional_plugins  Added as well if found
+ #    Output:
+ #      OGRE_PLUGINS_FOLDER_DEBUG   Folder with the debug plugins
+ #      OGRE_PLUGINS_FOLDER_RELEASE Folder with the release plugins
+ #      OGRE_PLUGINS_DEBUG          Names of the debug plugins without extension
+ #      OGRE_PLUGINS_RELEASE        Names of the release plugins without ext.
+ #  Note:
+ #    You must not specify render systems as input. That will be taken care of
+ #    automatically.
+ #
+
+FUNCTION(CHECK_OGRE_PLUGINS _mandatory_plugins _optional_plugins)
+
+  IF(WIN32)
+    # On Windows we need only *.dll, not *.lib. Especially the MSVC generator doesn't look for *.dll
+    SET(CMAKE_FIND_LIBRARY_SUFFIXES .dll)
+  ENDIF(WIN32)
+  # Do not prefix "lib" on any platform
+  SET(CMAKE_FIND_LIBRARY_PREFIXES "")
+
+  SET(OGRE_RENDER_SYSTEMS RenderSystem_GL RenderSystem_Direct3D9)
+  SET(OGRE_RENDER_SYSTEM_FOUND FALSE)
+  FOREACH(_plugin ${_mandatory_plugins} ${_optional_plugins} ${OGRE_RENDER_SYSTEMS})
+    FIND_LIBRARY(OGRE_PLUGIN_${_plugin}_OPTIMIZED
+      NAMES ${_plugin}
+      PATHS $ENV{OGRE_HOME} $ENV{OGRE_PLUGIN_DIR}
+      PATH_SUFFIXES bin/Release bin/release Release release lib lib/OGRE bin Ogre.framework/Resources OGRE-${OGRE_VERSION}
+    )
+    FIND_LIBRARY(OGRE_PLUGIN_${_plugin}_DEBUG
+      NAMES ${_plugin}d ${_plugin}_d ${_plugin}
+      PATHS $ENV{OGRE_HOME} $ENV{OGRE_PLUGIN_DIR}
+      PATH_SUFFIXES bin/Debug bin/debug Debug debug lib lib/OGRE bin Ogre.framework/Resources OGRE-${OGRE_VERSION}
+    )
+    # We only need at least one render system. Check at the end.
+    IF(NOT ${_plugin} MATCHES "RenderSystem")
+      IF(${_plugin} MATCHES "${_mandatory_plugins}" AND NOT OGRE_PLUGIN_${_plugin}_OPTIMIZED)
+        MESSAGE(FATAL_ERROR "Could not find OGRE plugin named ${_plugin}")
+      ENDIF()
+    ELSEIF(OGRE_PLUGIN_${_plugin}_OPTIMIZED)
+      SET(OGRE_RENDER_SYSTEM_FOUND TRUE)
+    ENDIF()
+
+    IF(OGRE_PLUGIN_${_plugin}_OPTIMIZED)
+      # If debug version is not available, release will do as well
+      IF(OGRE_PLUGIN_${_plugin}_DEBUG STREQUAL OGRE_PLUGIN_${_plugin}_OPTIMIZED)
+        # In this case the library finder didn't find real debug versions
+        SET(OGRE_PLUGIN_${_plugin}_DEBUG "OGRE_PLUGIN_${_plugin}_DEBUG-NOTFOUND" CACHE STRING "" FORCE)
+      ENDIF()
+      MARK_AS_ADVANCED(OGRE_PLUGIN_${_plugin}_OPTIMIZED OGRE_PLUGIN_${_plugin}_DEBUG)
+
+      ### Set variables to configure orxonox.ini correctly afterwards in bin/ ###
+      # Check and set the folders
+      GET_FILENAME_COMPONENT(_plugins_folder ${OGRE_PLUGIN_${_plugin}_OPTIMIZED} PATH)
+      IF(OGRE_PLUGINS_FOLDER_RELEASE AND NOT OGRE_PLUGINS_FOLDER_RELEASE STREQUAL _plugins_folder)
+        MESSAGE(FATAL_ERROR "Ogre release plugins have to be in the same folder!")
+      ENDIF()
+      SET(OGRE_PLUGINS_FOLDER_RELEASE ${_plugins_folder})
+      IF(OGRE_PLUGIN_${_plugin}_DEBUG)
+        GET_FILENAME_COMPONENT(_plugins_folder ${OGRE_PLUGIN_${_plugin}_DEBUG} PATH)
+      ENDIF()
+      IF(OGRE_PLUGINS_FOLDER_DEBUG AND NOT OGRE_PLUGINS_FOLDER_DEBUG STREQUAL _plugins_folder)
+        MESSAGE(FATAL_ERROR "Ogre debug plugins have to be in the same folder!")
+      ENDIF()
+      SET(OGRE_PLUGINS_FOLDER_DEBUG ${_plugins_folder})
+
+      # Create a list with the plugins for release and debug configurations
+      LIST(APPEND OGRE_PLUGINS_RELEASE ${_plugin})
+      # Determine debug postfix ("d" or "_d" or none)
+      IF(OGRE_PLUGIN_${_plugin}_DEBUG MATCHES "_d\\.|_d$")
+        LIST(APPEND OGRE_PLUGINS_DEBUG "${_plugin}_d")
+      ELSEIF(OGRE_PLUGIN_${_plugin}_DEBUG MATCHES "d\\.|d$")
+        LIST(APPEND OGRE_PLUGINS_DEBUG "${_plugin}d")
+      ELSE()
+        LIST(APPEND OGRE_PLUGINS_DEBUG "${_plugin}")
+      ENDIF()
+    ENDIF(OGRE_PLUGIN_${_plugin}_OPTIMIZED)
+  ENDFOREACH(_plugin)
+  IF(NOT OGRE_RENDER_SYSTEM_FOUND)
+      MESSAGE(FATAL_ERROR "Could not find an OGRE render system plugin")
+  ENDIF()
+
+  # List has to be comma separated for orxonox.ini
+  STRING(REPLACE ";" ", " OGRE_PLUGINS_RELEASE "${OGRE_PLUGINS_RELEASE}")
+  STRING(REPLACE ";" ", " OGRE_PLUGINS_DEBUG   "${OGRE_PLUGINS_DEBUG}")
+
+  # Set variables outside function scope
+  SET(OGRE_PLUGINS_FOLDER_DEBUG ${OGRE_PLUGINS_FOLDER_DEBUG} PARENT_SCOPE)
+  SET(OGRE_PLUGINS_FOLDER_RELEASE ${OGRE_PLUGINS_FOLDER_RELEASE} PARENT_SCOPE)
+  SET(OGRE_PLUGINS_RELEASE ${OGRE_PLUGINS_RELEASE} PARENT_SCOPE)
+  SET(OGRE_PLUGINS_DEBUG ${OGRE_PLUGINS_DEBUG} PARENT_SCOPE)
+
+ENDFUNCTION(CHECK_OGRE_PLUGINS)
Index: /code/branches/RacingBots_FS18/cmake/tools/CheckPackageVersion.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/CheckPackageVersion.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/CheckPackageVersion.cmake	(revision 11817)
@@ -0,0 +1,66 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Check package version info
+ #    MAJOR: Breaking change
+ #    MINOR: No breaking changes by the dependency package
+ #           For example any code running on 3.0 should still run on 3.1
+ #           But you can specify that the code only runs on 3.1 and higher
+ #           or 4.0 and higher (so both 3.1 and 4.0 will work).
+
+MACRO(CHECK_PACKAGE_VERSION)
+  SET(_allowed_minimum_versions ${ARGN})
+
+  IF(NOT EXISTS ${DEPENDENCY_PACKAGE_DIR}/version.txt)
+    SET(DEPENDENCY_VERSION 1.0)
+  ELSE()
+    # Get version from file
+    FILE(READ ${DEPENDENCY_PACKAGE_DIR}/version.txt _file_content)
+    SET(_match)
+    STRING(REGEX MATCH "([0-9]+.[0-9]+)" _match ${_file_content})
+    IF(_match)
+      SET(DEPENDENCY_VERSION ${_match})
+    ELSE()
+      MESSAGE(FATAL_ERROR "The version.txt file in the dependency file has corrupt version information.")
+    ENDIF()
+  ENDIF()
+  
+  INCLUDE(CompareVersionStrings)
+  SET(_version_match FALSE)
+  FOREACH(_version ${_allowed_minimum_versions})
+    # Get major version
+    STRING(REGEX REPLACE "^([0-9]+)\\..*$" "\\1" _major_version "${_version}")
+    COMPARE_VERSION_STRINGS(${DEPENDENCY_VERSION} ${_major_version} _result TRUE)
+    IF(_result EQUAL 0)
+      COMPARE_VERSION_STRINGS(${DEPENDENCY_VERSION} ${_version} _result FALSE)
+      IF(NOT _result LESS 0)
+        SET(_version_match TRUE)
+      ENDIF()
+    ENDIF()
+  ENDFOREACH(_version)
+  IF(NOT _version_match)
+    MESSAGE(FATAL_ERROR "Your dependency package version is ${DEPENDENCY_VERSION}\n"
+            "Possible required versions: ${_allowed_minimum_versions}\n"
+            "You can get a new version from www.orxonox.net")
+  ENDIF()
+  
+ENDMACRO(CHECK_PACKAGE_VERSION)
Index: /code/branches/RacingBots_FS18/cmake/tools/CompareVersionStrings.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/CompareVersionStrings.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/CompareVersionStrings.cmake	(revision 11817)
@@ -0,0 +1,78 @@
+# Computes the relationship between two version strings.  A version
+# string is a number delineated by '.'s such as 1.3.2 and 0.99.9.1.
+# You can feed version strings with different number of dot versions,
+# and the shorter version number will be padded with zeros: 9.2 <
+# 9.2.1 will actually compare 9.2.0 < 9.2.1.
+#
+# Input: a_in - value, not variable
+#        b_in - value, not variable
+#        result_out - variable with value:
+#                         -1 : a_in <  b_in
+#                          0 : a_in == b_in
+#                          1 : a_in >  b_in
+#        optional argument - TRUE or default FALSE:
+#              When passing 1.2.3 and 1.2 and this switch is on
+#              the function will actually compare 1.2 < 1.2
+#              Caution: Only the first string is adjusted!
+#
+# Written by James Bigler.
+# Extended with an optional argument by Reto Grieder
+
+FUNCTION(COMPARE_VERSION_STRINGS a_in b_in result_out)
+  # Additional argument can be a switch to change compare behaviour
+  SET(cut_first ${ARGN})
+
+  # Replace '.' with ';' to allow easy tokenization of the string.
+  STRING(REPLACE "." ";" a ${a_in})
+  STRING(REPLACE "." ";" b ${b_in})
+
+  # Check the size of each list to see if they are equal.
+  LIST(LENGTH a a_length)
+  LIST(LENGTH b b_length)
+
+  # Pad the shorter list with zeros.
+
+  IF(a_length LESS b_length)
+    # a is shorter
+    SET(shorter a)
+    MATH(EXPR pad_range "${b_length} - ${a_length} - 1")
+  ELSE(a_length LESS b_length)
+    # b is shorter
+    SET(shorter b)
+    SET(first_longer a)
+    MATH(EXPR pad_range "${a_length} - ${b_length} - 1")
+  ENDIF(a_length LESS b_length)
+
+  # PAD out if we need to
+  IF(NOT pad_range LESS 0)
+    FOREACH(pad RANGE ${pad_range})
+      # Since shorter is an alias for b, we need to get to it by dereferencing shorter.
+      IF(cut_first AND first_longer)
+        LIST(REMOVE_AT a -1) # remove last element
+      ELSE(cut_first AND first_longer)
+        LIST(APPEND ${shorter} 0)
+      ENDIF(cut_first AND first_longer)
+    ENDFOREACH(pad)
+  ENDIF(NOT pad_range LESS 0)
+
+  SET(result 0)
+  SET(index 0)
+  FOREACH(a_version ${a})
+    IF(result EQUAL 0)
+      # Only continue to compare things as long as they are equal
+      LIST(GET b ${index} b_version)
+      # LESS
+      IF(a_version LESS b_version)
+        SET(result -1)
+      ENDIF(a_version LESS b_version)
+      # GREATER
+      IF(a_version GREATER b_version)
+        SET(result 1)
+      ENDIF(a_version GREATER b_version)
+    ENDIF(result EQUAL 0)
+    MATH(EXPR index "${index} + 1")
+  ENDFOREACH(a_version)
+
+  # Copy out the return result
+  SET(${result_out} ${result} PARENT_SCOPE)
+ENDFUNCTION(COMPARE_VERSION_STRINGS)
Index: /code/branches/RacingBots_FS18/cmake/tools/DetermineVersion.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/DetermineVersion.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/DetermineVersion.cmake	(revision 11817)
@@ -0,0 +1,60 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Inspects a given file for the following expressions
+ #    "NAME_VERSION_MAJOR #"
+ #    "NAME_VERSION_MINOR #"
+ #    "NAME_VERSION_PATCH #"
+ #    and sets NAME_VERSION accordingly. NAME_PART_VERSION variables are also
+ #    set. If you wish to look for different parts (e.g. "first" "second", etc.)
+ #    simply deliver them as additional arguments (have to be three though).
+ #
+
+FUNCTION(DETERMINE_VERSION _name _file)
+  IF(EXISTS ${_file})
+    FILE(READ ${_file} _file_content)
+    SET(_parts ${ARGN})
+    LIST(LENGTH _parts _parts_length)
+    IF(NOT ${_parts_length} EQUAL 3)
+      SET(_parts MAJOR MINOR PATCH)
+    ENDIF()
+
+    FOREACH(_part ${_parts})
+      STRING(REGEX MATCH "${_name}_VERSION_${_part} +([0-9]+)" _match ${_file_content})
+      IF(_match)
+        SET(${_name}_VERSION_${_part} ${CMAKE_MATCH_1})
+        SET(${_name}_VERSION_${_part} ${CMAKE_MATCH_1} PARENT_SCOPE)
+      ELSE()
+        SET(${_name}_VERSION_${_part} "0")
+        SET(${_name}_VERSION_${_part} "0" PARENT_SCOPE)
+      ENDIF()
+      IF("${_parts}" MATCHES "^${_part}") # First?
+        SET(${_name}_VERSION "${${_name}_VERSION_${_part}}")
+      ELSE()
+        SET(${_name}_VERSION "${${_name}_VERSION}.${${_name}_VERSION_${_part}}")
+      ENDIF()
+    ENDFOREACH(_part)
+    SET(${_name}_VERSION "${${_name}_VERSION}" PARENT_SCOPE)
+  ELSE(EXISTS ${_file})
+    SET(${_name}_VERSION "NOTFOUND" PARENT_SCOPE)
+  ENDIF(EXISTS ${_file})
+ENDFUNCTION(DETERMINE_VERSION)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindALUT.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindALUT.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindALUT.cmake	(revision 11817)
@@ -0,0 +1,60 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Kevin Young
+ #  Description:
+ #    Variables defined:
+ #      ALUT_FOUND
+ #      ALUT_INCLUDE_DIR
+ #      ALUT_LIBRARY
+ #
+
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(ALUT_INCLUDE_DIR alut.h
+  PATHS $ENV{ALUTDIR}
+  PATH_SUFFIXES include include/AL
+)
+FIND_LIBRARY(ALUT_LIBRARY_OPTIMIZED
+  NAMES alut ALUT
+  PATHS $ENV{ALUTDIR}
+  PATH_SUFFIXES lib bin/Release bin/release Release release ALUT
+)
+FIND_LIBRARY(ALUT_LIBRARY_DEBUG
+  NAMES alutd alut_d alutD alut_D ALUTd ALUT_d ALUTD ALUT_D
+  PATHS $ENV{ALUTDIR}
+  PATH_SUFFIXES lib bin/Debug bin/debug Debug debug ALUT
+)
+
+# Handle the REQUIRED argument and set ALUT_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(ALUT DEFAULT_MSG
+  ALUT_LIBRARY_OPTIMIZED
+  ALUT_INCLUDE_DIR
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(ALUT)
+
+MARK_AS_ADVANCED(
+  ALUT_INCLUDE_DIR
+  ALUT_LIBRARY_OPTIMIZED
+  ALUT_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindCEGUI.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindCEGUI.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindCEGUI.cmake	(revision 11817)
@@ -0,0 +1,182 @@
+# Find CEGUI includes and library
+#
+# This module defines
+#  CEGUI_INCLUDE_DIR
+#  CEGUI_LIBRARY, the library to link against to use CEGUI.
+#  CEGUILUA_LIBRARY, the library to link against to use the CEGUI script module.
+#  CEGUI_TOLUA_LIBRARY, the library to link against to use Tolua++.
+#  CEGUI_FOUND, If false, do not try to use CEGUI
+#  CEGUI_VERSION, the version as string "x.y.z"
+#
+# Input:
+#  ENV{CEGUIDIR}, CEGUI path, optional
+#
+# Created by Matt Williams to find OGRE libraries
+# Copyright © 2007, Matt Williams
+#
+# Modified by Nicolas Schlumberger to find CEGUI libraries
+# and make it run on the Tardis-Infrastucture of the ETH Zurich
+# Copyright 2007, Nicolas Schlumberger
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+#
+# Several changes and additions by Fabian 'x3n' Landau
+# Lots of simplifications by Adrian Friedli and Reto Grieder
+# Version checking and CEGUILua finding by Reto Grieder
+#                 > www.orxonox.net <
+
+INCLUDE(CompareVersionStrings)
+INCLUDE(DetermineVersion)
+INCLUDE(FindPackageHandleAdvancedArgs)
+INCLUDE(HandleLibraryTypes)
+
+# Determine CEGUI's version
+FIND_FILE(CEGUI_VERSION_FILE CEGUIVersion.h Version.h
+  PATHS $ENV{CEGUIDIR}
+  PATH_SUFFIXES include include/CEGUI
+)
+DETERMINE_VERSION(CEGUI ${CEGUI_VERSION_FILE})
+
+# Find CEGUI headers
+COMPARE_VERSION_STRINGS("${CEGUI_VERSION}" "0.8" _version_0_8_compare TRUE)
+# Version 0.8 introduced a new directory and file naming convention
+IF(_version_0_8_compare GREATER -1)
+  # 0.8 and newer
+  FIND_PATH(CEGUI_INCLUDE_DIR CEGUI/CEGUI.h
+    PATHS $ENV{CEGUIDIR}
+    PATH_SUFFIXES include
+  )
+ELSE()
+  # 0.7 and older
+  FIND_PATH(CEGUI_INCLUDE_DIR CEGUI.h
+    PATHS $ENV{CEGUIDIR}
+    PATH_SUFFIXES include include/CEGUI
+  )
+ENDIF()
+
+# Find CEGUI library
+FIND_LIBRARY(CEGUI_LIBRARY_OPTIMIZED
+  NAMES CEGUIBase CEGUI CEGUIBase-0
+  PATHS $ENV{CEGUIDIR}
+  PATH_SUFFIXES lib bin
+)
+FIND_LIBRARY(CEGUI_LIBRARY_DEBUG
+  NAMES
+    CEGUIBased CEGUIBase_d CEGUIBaseD CEGUIBase_D
+    CEGUId CEGUI_d CEGUID CEGUI_D CEGUIBase-0_d
+  PATHS $ENV{CEGUIDIR}
+  PATH_SUFFIXES lib bin
+)
+
+# Find CEGUILua headers
+FIND_PATH(CEGUILUA_INCLUDE_DIR CEGUILua.h Functor.h
+  PATHS
+    $ENV{CEGUIDIR}
+    $ENV{CEGUILUADIR}
+    ${CEGUI_INCLUDE_DIR}/ScriptingModules/LuaScriptModule
+    ${CEGUI_INCLUDE_DIR}/CEGUI/ScriptModules/Lua
+  PATH_SUFFIXES include include/CEGUI
+)
+# Find CEGUILua libraries
+FIND_LIBRARY(CEGUILUA_LIBRARY_OPTIMIZED
+  NAMES CEGUILua CEGUILuaScriptModule CEGUILuaScriptModule-0
+  PATHS $ENV{CEGUIDIR} $ENV{CEGUILUADIR}
+  PATH_SUFFIXES lib bin
+)
+FIND_LIBRARY(CEGUILUA_LIBRARY_DEBUG
+  NAMES CEGUILuad CEGUILua_d CEGUILuaScriptModuled CEGUILuaScriptModule_d
+  CEGUILuaScriptModule-0_d
+  PATHS $ENV{CEGUIDIR} $ENV{CEGUILUADIR}
+  PATH_SUFFIXES lib bin
+)
+
+# Find CEGUI Tolua++ include file
+# We only need to add this path since we use tolua++ like a normal
+# dependency but it is shipped with CEGUILua.
+FIND_PATH(CEGUI_TOLUA_INCLUDE_DIR tolua++.h
+  PATHS
+    ${CEGUILUA_INCLUDE_DIR}
+    # For newer CEGUI versions >= 0.7
+    ${CEGUILUA_INCLUDE_DIR}/support/tolua++
+    ${DEP_INCLUDE_DIR}/tolua++/include
+    # For Mac OS X, tolua++ is a separate framework in the dependency package
+    ${DEP_FRAMEWORK_DIR}
+  NO_DEFAULT_PATH # Don't attempt to find tolua++ installed on the system
+)
+# Find CEGUI Tolua++ libraries
+FIND_LIBRARY(CEGUI_TOLUA_LIBRARY_OPTIMIZED
+  NAMES CEGUItoluapp tolua++ toluapp ceguitolua++ tolua++5.1
+  PATHS $ENV{CEGUIDIR} ${CEGUITOLUADIR}
+  PATH_SUFFIXES lib bin
+)
+FIND_LIBRARY(CEGUI_TOLUA_LIBRARY_DEBUG
+  NAMES CEGUItoluappd CEGUItoluapp_d tolua++d tolua++_d
+  PATHS $ENV{CEGUIDIR} ${CEGUITOLUADIR}
+  PATH_SUFFIXES lib bin
+)
+
+# Newer versions of CEGUI have the renderer for OGRE shipped with them
+COMPARE_VERSION_STRINGS("${CEGUI_VERSION}" "0.7" _version_0_7_compare TRUE)
+IF(_version_0_7_compare GREATER -1)
+  # Find CEGUI OGRE Renderer headers
+  FIND_PATH(CEGUI_OGRE_RENDERER_INCLUDE_DIR CEGUIOgreRenderer.h Renderer.h
+    PATHS
+      $ENV{CEGUIDIR}
+      $ENV{CEGUIOGRERENDERERDIR}
+      ${CEGUI_INCLUDE_DIR}/RendererModules/Ogre
+    PATH_SUFFIXES include include/CEGUI
+  )
+  # Find CEGUI OGRE Renderer libraries
+  FIND_LIBRARY(CEGUI_OGRE_RENDERER_LIBRARY_OPTIMIZED
+    NAMES CEGUIOgreRenderer CEGUIOgreRenderer-0
+    PATHS $ENV{CEGUIDIR} $ENV{CEGUIOGRERENDERERDIR}
+    PATH_SUFFIXES lib bin
+  )
+  FIND_LIBRARY(CEGUI_OGRE_RENDERER_LIBRARY_DEBUG
+    NAMES CEGUIOgreRendererd CEGUIOgreRenderer_d CEGUIOgreRenderer-0_d
+    PATHS $ENV{CEGUIDIR} $ENV{CEGUIOGRERENDERERDIR}
+    PATH_SUFFIXES lib bin
+  )
+  SET(CEGUI_OGRE_RENDERER_REQUIRED_VARIABLES
+    CEGUI_OGRE_RENDERER_INCLUDE_DIR
+    CEGUI_OGRE_RENDERER_LIBRARY_OPTIMIZED
+  )
+ELSE()
+  SET(CEGUI_OLD_VERSION TRUE)
+  SET(CEGUI_OGRE_RENDERER_BUILD_REQUIRED TRUE)
+ENDIF()
+
+# Handle the REQUIRED argument and set CEGUI_FOUND
+# Also checks the version requirements if given
+FIND_PACKAGE_HANDLE_ADVANCED_ARGS(CEGUI DEFAULT_MSG "${CEGUI_VERSION}"
+  CEGUI_INCLUDE_DIR
+  CEGUI_LIBRARY_OPTIMIZED
+  CEGUILUA_INCLUDE_DIR
+  CEGUILUA_LIBRARY_OPTIMIZED
+  CEGUI_TOLUA_INCLUDE_DIR
+  CEGUI_TOLUA_LIBRARY_OPTIMIZED
+  ${CEGUI_OGRE_RENDERER_REQUIRED_VARIABLES}
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(CEGUI)
+HANDLE_LIBRARY_TYPES(CEGUILUA)
+HANDLE_LIBRARY_TYPES(CEGUI_TOLUA)
+IF(NOT CEGUI_OGRE_RENDERER_BUILD_REQUIRED)
+  HANDLE_LIBRARY_TYPES(CEGUI_OGRE_RENDERER)
+ENDIF()
+
+MARK_AS_ADVANCED(
+  CEGUI_INCLUDE_DIR
+  CEGUI_LIBRARY_OPTIMIZED
+  CEGUI_LIBRARY_DEBUG
+  CEGUILUA_INCLUDE_DIR
+  CEGUILUA_LIBRARY_OPTIMIZED
+  CEGUILUA_LIBRARY_DEBUG
+  CEGUI_TOLUA_INCLUDE_DIR
+  CEGUI_TOLUA_LIBRARY_OPTIMIZED
+  CEGUI_TOLUA_LIBRARY_DEBUG
+  CEGUI_OGRE_RENDERER_INCLUDE_DIR
+  CEGUI_OGRE_RENDERER_LIBRARY_OPTIMIZED
+  CEGUI_OGRE_RENDERER_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindDbgHelp.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindDbgHelp.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindDbgHelp.cmake	(revision 11817)
@@ -0,0 +1,27 @@
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(DBGHELP_INCLUDE_DIR dbghelp.h
+  PATHS $ENV{DBGHELP_DIR}
+  PATH_SUFFIXES include
+)
+FIND_LIBRARY(DBGHELP_LIBRARY dbghelp.lib
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES lib Lib lib/x86 Lib/x86
+  NO_DEFAULT_PATH # Or else CMake 2.6.0 will find the dll in system32 on windows
+)
+FIND_LIBRARY(DBGHELP_LIBRARY dbghelp.lib # search again if the library wasn't found in the dependencies package
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES lib Lib lib/x86 Lib/x86
+)
+
+# Handle the REQUIRED argument and set DBGHELP_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(DbgHelp DEFAULT_MSG
+  DBGHELP_LIBRARY
+  DBGHELP_INCLUDE_DIR
+)
+
+MARK_AS_ADVANCED(
+  DBGHELP_INCLUDE_DIR
+  DBGHELP_LIBRARY
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindDirectX.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindDirectX.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindDirectX.cmake	(revision 11817)
@@ -0,0 +1,53 @@
+# Find script for DirectX on Windows
+# Specifically designed to find dxguid and dinput8 for OIS
+# Once loaded this will define
+#   DIRECTX_FOUND        - system has DirectX
+#   DIRECTX_INCLUDE_DIR  - include directory for DirectX
+#   DIRECTX_LIBRARIES    - libraries for DirectX
+#
+# Set ENV{DXSD_DIR} if that has not been done the SDK installation.
+#
+# Several changes and additions by Fabian 'x3n' Landau
+# Simplifications and CMake 2.6.0 bugfix by Reto Grieder
+#                 > www.orxonox.net <
+
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(DIRECTX_INCLUDE_DIR dinput.h
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES include
+)
+FIND_LIBRARY(DIRECTX_LIBRARY_input dinput8
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES lib Lib lib/x86 Lib/x86
+  NO_DEFAULT_PATH # Or else CMake 2.6.0 will find the dll in system32 on windows
+)
+FIND_LIBRARY(DIRECTX_LIBRARY_input dinput8
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES lib Lib lib/x86 Lib/x86
+)
+FIND_LIBRARY(DIRECTX_LIBRARY_guid dxguid
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES lib Lib lib/x86 Lib/x86
+  NO_DEFAULT_PATH # Or else CMake 2.6.0 will find the dll in system32 on windows
+)
+FIND_LIBRARY(DIRECTX_LIBRARY_guid dxguid
+  PATHS $ENV{DXSDK_DIR}
+  PATH_SUFFIXES lib Lib lib/x86 Lib/x86
+)
+
+# Handle the REQUIRED argument and set DIRECTX_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(DirectX DEFAULT_MSG
+  DIRECTX_LIBRARY_input
+  DIRECTX_LIBRARY_guid
+  DIRECTX_INCLUDE_DIR
+)
+
+SET(DIRECTX_LIBRARIES ${DIRECTX_LIBRARY_input} ${DIRECTX_LIBRARY_guid})
+
+MARK_AS_ADVANCED(
+  DIRECTX_INCLUDE_DIR
+  DIRECTX_LIBRARY_input
+  DIRECTX_LIBRARY_guid
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindENet.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindENet.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindENet.cmake	(revision 11817)
@@ -0,0 +1,80 @@
+# - Try to find enet
+# Once done this will define
+#
+#  ENET_FOUND - system has enet
+#  ENet_INCLUDE_DIR - the enet include directory
+#  ENet_LIBRARY - the library needed to link against enet
+#
+# $ENETDIR is an environment variable used for finding enet.
+#
+#  Borrowed from The Mana World
+#  http://themanaworld.org/
+#
+# Several changes and additions by Fabian 'x3n' Landau
+# Lots of simplifications by Adrian Friedli and Reto Grieder
+# Version checking by Reto Grieder
+#                 > www.orxonox.net <
+
+INCLUDE(FindPackageHandleAdvancedArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(ENET_INCLUDE_DIR enet/enet.h
+  PATHS $ENV{ENETDIR}
+  PATH_SUFFIXES include
+)
+FIND_LIBRARY(ENET_LIBRARY_OPTIMIZED
+  NAMES enet
+  PATHS $ENV{ENETDIR}
+  PATH_SUFFIXES lib
+)
+FIND_LIBRARY(ENET_LIBRARY_DEBUG
+  NAMES enetd enet_d enet_D
+  PATHS $ENV{ENETDIR}
+  PATH_SUFFIXES lib
+)
+
+# Only works for 1.2.2 and higher, otherwise see below
+DETERMINE_VERSION(ENET ${ENET_INCLUDE_DIR}/enet/enet.h)
+IF(${ENET_VERSION} STREQUAL "0.0.0")
+  # Try to determine the version. Note that enet only stores the major
+  # version in the header file. So we check for existing functions.
+  # Hence the this script only distinguishes between 1.0, 1.1 and 1.2
+  FILE(STRINGS ${ENET_INCLUDE_DIR}/enet/enet.h _enet_header REGEX "ENET_")
+  IF(_enet_header MATCHES "ENET_VERSION[ \t]*=[ \t]*1")
+    IF(_enet_header MATCHES "enet_socket_set_option")
+      SET(ENET_VERSION 1.2)
+    ELSEIF(_enet_header MATCHES "enet_peer_disconnect_later")
+      SET(ENET_VERSION 1.1)
+    ELSE()
+      SET(ENET_VERSION 1.0)
+    ENDIF()
+  ELSE()
+    SET(ENET_VERSION 0) # Script doesn't support versions below 1.0
+  ENDIF()
+ENDIF()
+
+# Handle the REQUIRED argument and set ENET_FOUND
+# Also check the the version requirements
+FIND_PACKAGE_HANDLE_ADVANCED_ARGS(ENet DEFAULT_MSG ${ENET_VERSION}
+  ENET_LIBRARY_OPTIMIZED
+  ENET_INCLUDE_DIR
+)
+
+COMPARE_VERSION_STRINGS(${ENET_VERSION} 1.2 _comparison TRUE)
+IF(${_comparison} EQUAL 1)
+  MESSAGE(STATUS "Warning: Using ENet version 1.3, which is not protocol compatible with 1.1 and 1.2.")
+ENDIF()
+
+# Collect optimized and debug libraries
+IF(NOT LINK_ENET_DYNAMIC AND WIN32)
+  # ENet is linked statically, hence we need to add some windows dependencies
+  HANDLE_LIBRARY_TYPES(ENET ws2_32 winmm)
+ELSE()
+  HANDLE_LIBRARY_TYPES(ENET)
+ENDIF()
+
+MARK_AS_ADVANCED(
+  ENET_INCLUDE_DIR
+  ENET_LIBRARY_OPTIMIZED
+  ENET_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindLua5.1.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindLua5.1.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindLua5.1.cmake	(revision 11817)
@@ -0,0 +1,106 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Finds Lua 5.1 on the system.
+ #    Handles REQUIRED and QUIET arguments.
+ #    When the search was successful, the following variables are set:
+ #    LUA5.1_INCLUDE_DIR, LUA5.1_LIBRARY, LUA5.1_VERSION, LUA5.1_FOUND
+ #
+
+INCLUDE(CompareVersionStrings)
+INCLUDE(FindPackageHandleAdvancedArgs)
+INCLUDE(HandleLibraryTypes)
+
+# Macro that determines Lua version. Should work for versions 2.2 and above (current release: 5.3.2)
+FUNCTION(DETERMINE_LUA_VERSION _file _varname)
+  IF(EXISTS ${_file})
+    FILE(STRINGS ${_file} _file_content REGEX "LUA_VERSION|LUA_RELEASE")
+  ELSE()
+    SET(${_varname} "0" PARENT_SCOPE)
+    RETURN()
+  ENDIF()
+  STRING(REGEX REPLACE "^.*LUA_RELEASE[ \t]+\"Lua[ \t]+([.0-9]+)\".*$" "\\1" ${_varname} "${_file_content}")
+  IF(${_varname} STREQUAL "${_file_content}")
+    # At most version 5.1.0
+    STRING(REGEX REPLACE "^.*LUA_VERSION[ \t]+\"Lua[ \t]+([.0-9]+)\".*$" "\\1" ${_varname} "${_file_content}")
+    IF(${_varname} STREQUAL "${_file_content}")
+      # Last chance, search for LUA_VERSION_MAJOR and LUA_VERSION_MINOR
+      STRING(REGEX REPLACE "^.*LUA_VERSION_MAJOR[ \t]+\"([0-9]+)\".*$" "\\1" _major "${_file_content}")
+      STRING(REGEX REPLACE "^.*LUA_VERSION_MINOR[ \t]+\"([0-9]+)\".*$" "\\1" _minor "${_file_content}")
+      IF(_major STREQUAL "${_file_content}" OR _minor STREQUAL "${_file_content}")
+        MESSAGE(FATAL_ERROR "Could not determine Lua version which means this script has a bug")
+      ENDIF()
+      SET(${_varname} "${_major}.${_minor}")
+    ENDIF()
+    IF(${_varname} MATCHES "^[0-9]+\\.[0-9]+$")
+      SET(${_varname} "${${_varname}}.0") # E.g. "3.2" is "3.2.0" actually
+    ENDIF()
+  ENDIF()
+  SET(${_varname} "${${_varname}}" PARENT_SCOPE)
+ENDFUNCTION(DETERMINE_LUA_VERSION)
+
+
+# Find include path
+FIND_PATH(LUA5.1_INCLUDE_DIR lua.h
+  PATHS $ENV{LUA5.1_DIR} $ENV{LUA_DIR}
+  PATH_SUFFIXES lua5.1 include/lua51 include/lua5.1 include/lua include
+)
+
+# Check whether we really found Lua version 5.1
+IF(LUA5.1_INCLUDE_DIR)
+  DETERMINE_LUA_VERSION(${LUA5.1_INCLUDE_DIR}/lua.h LUA5.1_VERSION)
+  COMPARE_VERSION_STRINGS("${LUA5.1_VERSION}" "5.1" _version_compare TRUE)
+  IF(NOT _version_compare EQUAL 0)
+    # Wrong version
+    MESSAGE(SEND_ERROR "Version of Lua header found is not 5.1")
+    SET(LUA5.1_INCLUDE_DIR "LUA5.1_INCLUDE_DIR-NOTFOUND" CACHE PATH "" FORCE)
+  ENDIF(NOT _version_compare EQUAL 0)
+ENDIF(LUA5.1_INCLUDE_DIR)
+
+# Find library
+FIND_LIBRARY(LUA5.1_LIBRARY_OPTIMIZED
+  NAMES lua51 lua5.1 lua
+  PATHS $ENV{LUA5.1_DIR} $ENV{LUA_DIR}
+  PATH_SUFFIXES lib64 lib
+)
+FIND_LIBRARY(LUA5.1_LIBRARY_DEBUG
+  NAMES lua51d lua51_d lua5.1d lua5.1_d
+        lua51D lua51_D lua5.1D lua5.1_D
+        luad lua_d luad lua_D
+  PATHS $ENV{LUA5.1_DIR} $ENV{LUA_DIR}
+  PATH_SUFFIXES lib64 lib
+)
+
+# Handle the REQUIRED argument and set LUA5.1_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua5.1 DEFAULT_MSG
+  LUA5.1_LIBRARY_OPTIMIZED
+  LUA5.1_INCLUDE_DIR
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(LUA5.1)
+
+MARK_AS_ADVANCED(
+  LUA5.1_INCLUDE_DIR
+  LUA5.1_LIBRARY_OPTIMIZED
+  LUA5.1_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindOGRE.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindOGRE.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindOGRE.cmake	(revision 11817)
@@ -0,0 +1,55 @@
+# Find OGRE includes and library
+#
+# This module defines
+#  OGRE_INCLUDE_DIR
+#  OGRE_LIBRARY, the library to link against to use OGRE.
+#  OGRE_FOUND, If false, do not try to use OGRE
+#
+# Copyright © 2007, Matt Williams
+# Modified by Nicolas Schlumberger to make it work on the Tardis-Infrastucture
+# of the ETH Zurich (removed later on)
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+#
+# Several changes and additions by Fabian 'x3n' Landau
+# Lots of simplifications by Adrian Friedli
+# Version checking by Reto Grieder
+#                 > www.orxonox.net <
+
+INCLUDE(DetermineVersion)
+INCLUDE(FindPackageHandleAdvancedArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(OGRE_INCLUDE_DIR Ogre.h
+  PATHS $ENV{OGRE_HOME}
+  PATH_SUFFIXES include include/OGRE
+)
+FIND_LIBRARY(OGRE_LIBRARY_OPTIMIZED
+  NAMES OgreMain Ogre
+  PATHS $ENV{OGRE_HOME}
+  PATH_SUFFIXES lib bin/Release bin/release Release release
+)
+FIND_LIBRARY(OGRE_LIBRARY_DEBUG
+  NAMES OgreMaind OgreMain_d OgreMainD OgreMain_D Ogred Ogre_d OgreD Ogre_d
+  PATHS $ENV{OGRE_HOME}
+  PATH_SUFFIXES lib bin/Debug bin/debug Debug debug
+)
+
+# Inspect OgrePrerquisites.h for the version number
+DETERMINE_VERSION(OGRE ${OGRE_INCLUDE_DIR}/OgrePrerequisites.h)
+
+# Handle the REQUIRED argument and set OGRE_FOUND
+# Also check the version requirements
+FIND_PACKAGE_HANDLE_ADVANCED_ARGS(OGRE DEFAULT_MSG ${OGRE_VERSION}
+  OGRE_LIBRARY_OPTIMIZED
+  OGRE_INCLUDE_DIR
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(OGRE)
+
+MARK_AS_ADVANCED(
+  OGRE_INCLUDE_DIR
+  OGRE_LIBRARY_OPTIMIZED
+  OGRE_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindOgg.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindOgg.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindOgg.cmake	(revision 11817)
@@ -0,0 +1,47 @@
+# - Try to find ogg
+# Once done this will define
+#
+#  OGG_FOUND - system has ogg
+#  OGG_INCLUDE_DIR
+#  OGG_LIBRARY
+#
+# $OGGDIR is an environment variable used
+# for finding ogg.
+#
+# Several changes and additions by Fabian 'x3n' Landau
+# Most of all rewritten by Adrian Friedli
+# Debug versions and simplifications by Reto Grieder
+#                 > www.orxonox.net <
+
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(OGG_INCLUDE_DIR ogg/ogg.h
+  PATHS $ENV{OGGDIR}
+  PATH_SUFFIXES include
+)
+FIND_LIBRARY(OGG_LIBRARY_OPTIMIZED
+  NAMES ogg ogg-0 libogg
+  PATHS $ENV{OGGDIR}
+  PATH_SUFFIXES lib
+)
+FIND_LIBRARY(OGG_LIBRARY_DEBUG
+  NAMES oggd ogg_d oggD ogg_D libogg_d
+  PATHS $ENV{OGGDIR}
+  PATH_SUFFIXES lib
+)
+
+# Handle the REQUIRED argument and set OGG_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Ogg DEFAULT_MSG
+  OGG_LIBRARY_OPTIMIZED
+  OGG_INCLUDE_DIR
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(OGG)
+
+MARK_AS_ADVANCED(
+  OGG_INCLUDE_DIR
+  OGG_LIBRARY_OPTIMIZED
+  OGG_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindPOCO.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindPOCO.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindPOCO.cmake	(revision 11817)
@@ -0,0 +1,57 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Finds the POCO Foundation library.
+ #
+
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(POCO_INCLUDE_DIR Poco/Poco.h
+  PATHS $ENV{POCODIR}
+  PATH_SUFFIXES include Foundation/include
+)
+FIND_LIBRARY(POCO_LIBRARY_OPTIMIZED
+  NAMES PocoFoundation
+  PATHS $ENV{POCODIR}
+  PATH_SUFFIXES lib
+)
+FIND_LIBRARY(POCO_LIBRARY_DEBUG
+  NAMES PocoFoundationd PocoFoundation_d PocoFoundationD PocoFoundation_D
+  PATHS $ENV{POCODIR}
+  PATH_SUFFIXES lib
+)
+
+# Handle the REQUIRED argument and set POCO_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(POCO DEFAULT_MSG
+  POCO_LIBRARY_OPTIMIZED
+  POCO_INCLUDE_DIR
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(POCO)
+
+MARK_AS_ADVANCED(
+  POCO_INCLUDE_DIR
+  POCO_LIBRARY_OPTIMIZED
+  POCO_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindPackageHandleAdvancedArgs.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindPackageHandleAdvancedArgs.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindPackageHandleAdvancedArgs.cmake	(revision 11817)
@@ -0,0 +1,66 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Extension of the standard module "FindPackageHandleStandardArgs".
+ #    This function also checks the version requirements. Also regards the
+ #    EXACT keyword if specified in FIND_PACKAGE(...).
+ #
+
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(CompareVersionStrings)
+
+FUNCTION(FIND_PACKAGE_HANDLE_ADVANCED_ARGS _name _fail_msg _version)
+
+  # Modify the message to include version requirements
+  IF("${_fail_msg}" STREQUAL "DEFAULT_MSG")
+    SET(_fail_msg_adv "Could NOT find ${_name}")
+  ELSE()
+    SET(_fail_msg_adv "${_fail_msg}")
+  ENDIF()
+  IF(${_name}_FIND_VERSION_EXACT)
+    SET(_fail_msg_adv "${_fail_msg_adv} (version requirements: exactly ${${_name}_FIND_VERSION})")
+  ELSE()
+    SET(_fail_msg_adv "${_fail_msg_adv} (version requirements: at least ${${_name}_FIND_VERSION})")
+  ENDIF()
+  FIND_PACKAGE_HANDLE_STANDARD_ARGS("${_name}" "${_fail_msg_adv}" ${ARGN})
+  STRING(TOUPPER ${_name} _NAME_UPPER)
+
+  # Also check version requirements if given to FindPackage(...)
+  IF(${_name}_FIND_VERSION)
+    # Note: the last argument of the function tells it to cut the first
+    #       version string instead of padding it with zeros if necessary
+    COMPARE_VERSION_STRINGS("${_version}" "${${_name}_FIND_VERSION}" _compatible TRUE)
+    IF(${_name}_FIND_VERSION_EXACT AND NOT _compatible EQUAL 0)
+      MESSAGE(FATAL_ERROR "Exact ${_name} version required is ${${_name}_FIND_VERSION}\n"
+                          "Your version is ${_version}")
+      SET(${_NAME_UPPER}_FOUND FALSE)
+    ELSEIF(_compatible LESS 0)
+      MESSAGE(FATAL_ERROR "Minimum ${_name} version required is ${${_name}_FIND_VERSION}\n"
+                          "Your version is ${_version}")
+      SET(${_NAME_UPPER}_FOUND FALSE)
+    ENDIF()
+  ENDIF(${_name}_FIND_VERSION)
+
+  # Raise scope (FindPackageHandleStandardArgs uses PARENT_SCOPE)
+  SET(${_NAME_UPPER}_FOUND ${${_NAME_UPPER}_FOUND} PARENT_SCOPE)
+
+ENDFUNCTION(FIND_PACKAGE_HANDLE_ADVANCED_ARGS)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindVLD.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindVLD.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindVLD.cmake	(revision 11817)
@@ -0,0 +1,40 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Finds the Visual Leak Detector if installed
+ #
+
+INCLUDE(FindPackageHandleStandardArgs)
+
+FIND_LIBRARY(VLD_LIBRARY
+  NAMES vld
+  PATH_SUFFIXES "Visual Leak Detector/lib/Win32" "../../lib/Win32"
+)
+
+# Handle the REQUIRED argument and set POCO_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(VLD DEFAULT_MSG
+  VLD_LIBRARY
+)
+
+MARK_AS_ADVANCED(
+  VLD_LIBRARY
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FindVorbis.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FindVorbis.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FindVorbis.cmake	(revision 11817)
@@ -0,0 +1,62 @@
+# - Try to find ogg/vorbis
+# Once done this will define
+#
+#  VORBIS_FOUND - system has vorbis
+#  VORBIS_INCLUDE_DIR
+#  VORBIS_LIBRARIES - vorbis and vorbisfile libraries
+#
+# $VORBISDIR is an environment variable used
+# for finding vorbis.
+#
+# Several changes and additions by Fabian 'x3n' Landau
+# Most of all rewritten by Adrian Friedli
+# Debug versions and simplifications by Reto Grieder
+#                 > www.orxonox.net <
+
+INCLUDE(FindPackageHandleStandardArgs)
+INCLUDE(HandleLibraryTypes)
+
+FIND_PATH(VORBIS_INCLUDE_DIR vorbis/codec.h
+  PATHS $ENV{VORBISDIR}
+  PATH_SUFFIXES include
+)
+FIND_LIBRARY(VORBIS_LIBRARY_OPTIMIZED
+  NAMES vorbis vorbis-0 libvorbis
+  PATHS $ENV{VORBISDIR}
+  PATH_SUFFIXES lib
+)
+FIND_LIBRARY(VORBIS_LIBRARY_DEBUG
+  NAMES vorbisd vorbis_d vorbisD vorbis_D libvorbis_d
+  PATHS $ENV{VORBISDIR}
+  PATH_SUFFIXES lib
+)
+FIND_LIBRARY(VORBISFILE_LIBRARY_OPTIMIZED
+  NAMES vorbisfile vorbisfile-3 libvorbisfile
+  PATHS $ENV{VORBISDIR}
+  PATH_SUFFIXES lib
+)
+FIND_LIBRARY(VORBISFILE_LIBRARY_DEBUG
+  NAMES vorbisfiled vorbisfile_d vorbisfileD vorbisfile_D libvorbisfile_d
+  PATHS $ENV{VORBISDIR}
+  PATH_SUFFIXES lib
+)
+
+# Handle the REQUIRED argument and set VORBIS_FOUND
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Vorbis DEFAULT_MSG
+  VORBIS_LIBRARY_OPTIMIZED
+  VORBISFILE_LIBRARY_OPTIMIZED
+  VORBIS_INCLUDE_DIR
+)
+
+# Collect optimized and debug libraries
+HANDLE_LIBRARY_TYPES(VORBIS)
+HANDLE_LIBRARY_TYPES(VORBISFILE)
+SET(VORBIS_LIBRARIES ${VORBIS_LIBRARY} ${VORBISFILE_LIBRARY})
+
+MARK_AS_ADVANCED(
+  VORBIS_INCLUDE_DIR
+  VORBIS_LIBRARY_OPTIMIZED
+  VORBIS_LIBRARY_DEBUG
+  VORBISFILE_LIBRARY_OPTIMIZED
+  VORBISFILE_LIBRARY_DEBUG
+)
Index: /code/branches/RacingBots_FS18/cmake/tools/FlagUtilities.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/FlagUtilities.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/FlagUtilities.cmake	(revision 11817)
@@ -0,0 +1,177 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Sets the compiler/linker flags. After the flags you can specify more args:
+ #    Release, Debug, RelWithDebInfo, MinSizeRel, RelForDevs: Build configs
+ #    ReleaseAll: Sets the flags of all four release builds
+ #    CACHE: Values are witten with SET_CACHE_ADVANCED
+ #    FORCE: When writing to the cache, the values are set anyway
+ #    Any variable names (like WIN32, MSVC, etc.): Condition (combined with AND)
+ #    You can suffix the condition with a NOT if you wish
+ #  Function names:
+ #    [ADD/SET/REMOVE]_[COMPILER/LINKER]_FLAGS
+ #  Caution: -If you use CACHE after calling the macro without CACHE, the value
+ #            Will not be written unless FORCE is specified.
+ #          - Also be aware to always specify the flags in quotes.
+ #  Example:
+ #    REMOVE_COMPILER_FLAGS("/Gm "asdf" -q"test -foo" CXX ReleaseAll NOT UNIX)
+ #    This will only remove the CXX (C++) flags on a non Unix system for the
+ #    Release, RelWithDebInfo, MinSizeRel, RelForDevs configurations. The macros
+ #    should be able to cope with "test -foo" as string argument for a flag.
+ #
+
+INCLUDE(SeparateFlags)
+INCLUDE(SetCacheAdvanced)
+
+# Compiler flags, additional arguments:
+# C, CXX: Specify a language, default is both
+MACRO(SET_COMPILER_FLAGS _flags)
+  _INTERNAL_PARSE_FLAGS_ARGS(SET "C;CXX" "" "${_flags}" "${ARGN}")
+ENDMACRO(SET_COMPILER_FLAGS)
+# Add flags (flags don't get added twice)
+MACRO(ADD_COMPILER_FLAGS _flags)
+  _INTERNAL_PARSE_FLAGS_ARGS(APPEND "C;CXX" "" "${_flags}" "${ARGN}")
+ENDMACRO(ADD_COMPILER_FLAGS)
+# Remove flags
+MACRO(REMOVE_COMPILER_FLAGS _flags)
+  _INTERNAL_PARSE_FLAGS_ARGS(REMOVE_ITEM "C;CXX" "" "${_flags}" "${ARGN}")
+ENDMACRO(REMOVE_COMPILER_FLAGS)
+
+
+# Linker flags, additional arguments:
+# EXE, SHARED, MODULE: Specify a linker mode, default is all three
+MACRO(SET_LINKER_FLAGS _flags)
+  _INTERNAL_PARSE_FLAGS_ARGS(SET "EXE;SHARED;MODULE" "_LINKER" "${_flags}" "${ARGN}")
+ENDMACRO(SET_LINKER_FLAGS)
+# Add flags (flags don't get added twice)
+MACRO(ADD_LINKER_FLAGS _flags)
+  _INTERNAL_PARSE_FLAGS_ARGS(APPEND "EXE;SHARED;MODULE" "_LINKER" "${_flags}" "${ARGN}")
+ENDMACRO(ADD_LINKER_FLAGS)
+# Remove flags
+MACRO(REMOVE_LINKER_FLAGS _flags)
+  _INTERNAL_PARSE_FLAGS_ARGS(REMOVE_ITEM "EXE;SHARED;MODULE" "_LINKER" "${_flags}" "${ARGN}")
+ENDMACRO(REMOVE_LINKER_FLAGS)
+
+
+# Internal macro, do not use
+# Parses the given additional arguments and sets the flags to the
+# corresponding variables.
+MACRO(_INTERNAL_PARSE_FLAGS_ARGS _mode _keys _key_postfix _flags)
+  SET(_langs)
+  SET(_build_types)
+  SET(_cond TRUE)
+  SET(_invert_condition FALSE)
+  SET(_write_to_cache FALSE)
+  SET(_force FALSE)
+  STRING(REPLACE ";" "|" _key_regex "${_keys}")
+  SET(_key_regex "^(${_key_regex})$")
+
+  FOREACH(_arg ${ARGN})
+    IF(_arg MATCHES "${_key_regex}")
+      LIST(APPEND _langs "${_arg}")
+    ELSEIF(   _arg MATCHES "^(Debug|Release|MinSizeRel|RelWithDebInfo|RelForDevs)$"
+           OR _arg MATCHES "^(DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO|RELFORDEVS)$")
+      STRING(TOUPPER "${_arg}" _upper_arg)
+      LIST(APPEND _build_types ${_upper_arg})
+    ELSEIF(_arg STREQUAL "ReleaseAll")
+      LIST(APPEND _build_types RELEASE MINSIZEREL RELWITHDEBINFO RELFORDEVS)
+    ELSEIF(_arg STREQUAL "CACHE")
+      SET(_write_to_cache TRUE)
+    ELSEIF(_arg STREQUAL "FORCE")
+      SET(_force TRUE)
+    ELSEIF(_arg MATCHES "^[Nn][Oo][Tt]$")
+      SET(_invert_condition TRUE)
+    ELSE()
+      IF(_invert_condition)
+        SET(_invert_condition FALSE)
+        IF(${_arg})
+          SET(_arg_cond FALSE)
+        ELSE()
+          SET(_arg_cond TRUE)
+       ENDIF()
+      ELSE()
+        SET(_arg_cond ${${_arg}})
+      ENDIF()
+      IF(_cond AND _arg_cond)
+        SET(_cond TRUE)
+      ELSE()
+        SET(_cond FALSE)
+      ENDIF()
+    ENDIF()
+  ENDFOREACH(_arg)
+
+  # No language specified, use all: C and CXX or EXE, SHARED and MODULE
+  IF(NOT DEFINED _langs)
+    SET(_langs ${_keys})
+  ENDIF()
+
+  IF(_cond)
+    FOREACH(_lang ${_langs})
+      SET(_varname "CMAKE_${_lang}${_key_postfix}_FLAGS")
+      IF(DEFINED _build_types)
+        FOREACH(_build_type ${_build_types})
+          _INTERNAL_PARSE_FLAGS(${_mode} "${_flags}" ${_varname}_${_build_type} ${_write_to_cache} ${_force})
+        ENDFOREACH(_build_type)
+      ELSE()
+        _INTERNAL_PARSE_FLAGS(${_mode} "${_flags}" ${_varname} ${_write_to_cache} ${_force})
+      ENDIF()
+    ENDFOREACH(_lang ${_langs})
+  ENDIF(_cond)
+ENDMACRO(_INTERNAL_PARSE_FLAGS_ARGS)
+
+
+# Internal macro, do not use
+# Modifies the flags according to the mode: set, add or remove
+# Also sets flags according to the CACHE and FORCE parameter.
+# If only CACHE is specified, SET_CACHE_ADVANCED() is used.
+MACRO(_INTERNAL_PARSE_FLAGS _mode _flags _varname _write_to_cache _force)
+  SEPARATE_FLAGS("${_flags}" _arg_flag_list)
+
+  IF("${_mode}" STREQUAL "SET")
+    # SET
+    SET(_flag_list "${_arg_flag_list}")
+  ELSE()
+    # ADD or REMOVE
+    SEPARATE_FLAGS("${${_varname}}" _flag_list)
+    IF(NOT _flag_list)
+      SET(_flag_list "") # LIST command requires a list in any case
+    ENDIF()
+    FOREACH(_flag ${_arg_flag_list})
+      LIST(${_mode} _flag_list "${_flag}")
+    ENDFOREACH(_flag)
+  ENDIF()
+
+  LIST(REMOVE_DUPLICATES _flag_list)
+  LIST(SORT _flag_list)
+  STRING(REPLACE ";" " " _flag_list "${_flag_list}")
+
+  IF(_write_to_cache)
+    IF(_force)
+      SET(${_varname} "${_flag_list}" CACHE STRING "${${_varname}}" FORCE)
+      SET(${_varname} "${_flag_list}" CACHE STRING "${${_varname}}" FORCE)
+    ELSE()
+      SET_CACHE_ADVANCED(${_varname} STRING "${${_varname}}" "${_flag_list}")
+    ENDIF()
+  ELSE()
+    SET(${_varname} "${_flag_list}")
+  ENDIF()
+ENDMACRO(_INTERNAL_PARSE_FLAGS)
Index: /code/branches/RacingBots_FS18/cmake/tools/GenerateToluaBindings.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/GenerateToluaBindings.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/GenerateToluaBindings.cmake	(revision 11817)
@@ -0,0 +1,95 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Adrian Friedli
+ #  Description:
+ #    Sets the CMake options that will generate Tolua++ bindings.
+ #  Parameters:
+ #    _tolua_package - Name of the package, e.g. "Core"
+ #    _target_source_files - Variable name of the target source files, the
+ #                           script will add the generated files to this list.
+ #    ARGN - The header files in the style "INTPUTFILES Foo.h Bar.h"
+ #  Global Variables: (need to be set before)
+ #    TOLUA_PARSER_SOURCE - Lua file with the parser source code
+ #    TOLUA_PARSER_DEPENDENCIES - All the dependent lua files
+ #    RUNTIME_LIBRARY_DIRECTORY - Working directory
+ #
+
+# Workaround for XCode: The folder where the bind files are written to has
+# to be present beforehand.
+# We have to do this here because the header files are all stored in a single
+# location per configuration.
+IF(CMAKE_CONFIGURATION_TYPES)
+  FOREACH(_dir ${CMAKE_CONFIGURATION_TYPES})
+    FILE(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/src/toluabind/${_dir}")
+  ENDFOREACH(_dir)
+ENDIF()
+
+FUNCTION(GENERATE_TOLUA_BINDINGS _tolua_package _target_source_files)
+  SET(_tolua_inputfiles ${ARGN})
+  LIST(REMOVE_ITEM _tolua_inputfiles "INPUTFILES")
+
+  SET(_tolua_pkgfile "${CMAKE_CURRENT_BINARY_DIR}/tolua.pkg")
+  SET(_tolua_cxxfile "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ToluaBind${_tolua_package}.cc")
+  #SET(_tolua_hfile   "${CMAKE_BINARY_DIR}/src/toluabind/${CMAKE_CFG_INTDIR}/ToluaBind${_tolua_package}.h")
+
+  SET(${_target_source_files}
+    ${${_target_source_files}}
+    ${_tolua_cxxfile}
+    PARENT_SCOPE
+  )
+
+  IF(CMAKE_COMPILER_IS_GNU)
+    # Disable annoying GCC warnings
+    SET_SOURCE_FILES_PROPERTIES(${_tolua_cxxfile} PROPERTIES COMPILE_FLAGS "-w")
+  ENDIF()
+
+  IF(MSVC)
+    # Including the file in a build unit is impossible because CMAKE_CFG_INTDIR
+    # exands to an expression that the compiler doesn't understand
+    SET_SOURCE_FILES_PROPERTIES(${_tolua_cxxfile} PROPERTIES EXCLUDE_FROM_BUILD_UNITS TRUE)
+  ENDIF()
+
+  # Create temporary package file and implicit dependencies
+  FILE(REMOVE ${_tolua_pkgfile})
+  FOREACH(_tolua_inputfile ${_tolua_inputfiles})
+    FILE(APPEND ${_tolua_pkgfile} "\$cfile \"${_tolua_inputfile}\"\n")
+    LIST(APPEND _implicit_dependencies CXX ${_tolua_inputfile})
+  ENDFOREACH(_tolua_inputfile)
+
+  IF(TOLUA_PARSER_HOOK_SCRIPT)
+    # Hook scripts may contain functions that act as Tolua hooks
+    SET(_hook_script -L "${TOLUA_PARSER_HOOK_SCRIPT}")
+  ENDIF()
+
+  ADD_CUSTOM_COMMAND(
+    OUTPUT ${_tolua_cxxfile}
+    COMMAND toluaapp_orxonox -n ${_tolua_package}
+                             -w ${CMAKE_CURRENT_SOURCE_DIR}
+                             -o ${_tolua_cxxfile}
+                             -s ${TOLUA_PARSER_SOURCE}
+                                ${_hook_script}
+                                ${_tolua_pkgfile}
+    DEPENDS           ${TOLUA_PARSER_DEPENDENCIES}
+    IMPLICIT_DEPENDS  ${_implicit_dependencies}
+    WORKING_DIRECTORY ${RUNTIME_LIBRARY_DIRECTORY}
+    COMMENT "Generating tolua bind files for package ${_tolua_package}"
+  )
+ENDFUNCTION(GENERATE_TOLUA_BINDINGS)
Index: /code/branches/RacingBots_FS18/cmake/tools/GetGCCCompilerFlags.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/GetGCCCompilerFlags.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/GetGCCCompilerFlags.cmake	(revision 11817)
@@ -0,0 +1,76 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Tries to return all GCC compiler flags set for a target. This also
+ #    all definitions of the current directory.
+ #
+
+INCLUDE(SeparateFlags)
+
+FUNCTION(GET_GCC_COMPILER_FLAGS _target _flagsvar)
+
+  # General flags
+  STRING(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type_upper)
+  SET(_flag_str "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${_build_type_upper}}")
+
+  # Include directories
+  GET_DIRECTORY_PROPERTY(_include_dirs INCLUDE_DIRECTORIES)
+  IF(_include_dirs)
+    FOREACH(_directory ${_include_dirs})
+      SET(_flag_str "${_flag_str} -I${_directory}")
+    ENDFOREACH(_directory)
+  ENDIF()
+
+  # For shared libraries linked with gcc, we have to add -fPIC
+  GET_TARGET_PROPERTY(_target_type ${_target} TYPE)
+  IF(NOT MINGW AND ${_target_type} STREQUAL SHARED_LIBRARY)
+    SET(_flag_str "${_flag_str} -fPIC")
+  ENDIF()
+
+  # Target compile flags
+  GET_TARGET_PROPERTY(_target_flags ${_target} COMPILE_FLAGS)
+  IF(_target_flags)
+    SET(_flag_str "${_flag_str} ${_target_flags}")
+  ENDIF()
+
+  # Definitions from target and directory
+  GET_DIRECTORY_PROPERTY(_directory_defs                 COMPILE_DEFINITIONS)
+  GET_DIRECTORY_PROPERTY(_directory_defs_build_type      COMPILE_DEFINITIONS_${_build_type_upper})
+  GET_TARGET_PROPERTY(_target_defs            ${_target} COMPILE_DEFINITIONS)
+  GET_TARGET_PROPERTY(_target_defs_build_type ${_target} COMPILE_DEFINITIONS_${_build_type_upper})
+  IF(${_target_type} STREQUAL SHARED_LIBRARY)
+    GET_TARGET_PROPERTY(_target_def_symbol    ${_target} DEFINE_SYMBOL)
+  ENDIF()
+
+  # Prefix them all with a "-D" if the property was found
+  FOREACH(_def ${_directory_defs} ${_directory_defs_build_type} ${_target_defs}
+               ${_target_defs_build_type} ${_target_def_symbol})
+    IF(_def)
+      SET(_flag_str "${_flag_str} -D${_def}")
+    ENDIF(_def)
+  ENDFOREACH(_def)
+
+  SEPARATE_FLAGS("${_flag_str}" _flags)
+  LIST(REMOVE_DUPLICATES _flags)
+  SET(${_flagsvar} ${_flags} PARENT_SCOPE)
+
+ENDFUNCTION(GET_GCC_COMPILER_FLAGS)
Index: /code/branches/RacingBots_FS18/cmake/tools/HandleLibraryTypes.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/HandleLibraryTypes.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/HandleLibraryTypes.cmake	(revision 11817)
@@ -0,0 +1,42 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Checks debug and optimized libaries and sets the variable ${_name}_LIBRARY
+ #    accordingly. If only an optimized library was found, the "optimized"
+ #    keyword is omitted to support the debug version too.
+ #
+
+FUNCTION(HANDLE_LIBRARY_TYPES _name)
+  # Additional libraries can be added as additional arguments
+  IF(${_name}_LIBRARY_DEBUG AND ${_name}_LIBRARY_OPTIMIZED)
+    SET(${_name}_LIBRARY
+      optimized ${${_name}_LIBRARY_OPTIMIZED} ${ARGN}
+      debug     ${${_name}_LIBRARY_DEBUG}     ${ARGN}
+      PARENT_SCOPE
+    )
+  ELSE()
+    SET(${_name}_LIBRARY
+      ${${_name}_LIBRARY_OPTIMIZED} ${ARGN}
+      PARENT_SCOPE
+     )
+  ENDIF()
+ENDFUNCTION(HANDLE_LIBRARY_TYPES)
Index: /code/branches/RacingBots_FS18/cmake/tools/ParseMacroArguments.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/ParseMacroArguments.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/ParseMacroArguments.cmake	(revision 11817)
@@ -0,0 +1,91 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Parses a list of macro arguments which are separated by keywords and
+ #    writes the result to the _arg_KEYWORD variable. Switches are set to their
+ #    literal name if found and the lists contain their elements.
+ #    The order of the arguments is arbitrary.
+ #  Note:
+ #    You have to specify the switches and list_names as a
+ #    semicolon separated list or all hell breaks loose!
+ #  Example:
+ #    The arguments  BLUBB_FILES foo.cc bar.c NO_ASDF  will do the following:
+ #    SET(_arg_NO_ASDF _arg_NO_ASDF)
+ #    SET(_arg_BLUBB_FILES foo.cc bar.c)
+ #    But NO_FOO will not be set at all if it was specified as a switch
+ #
+
+MACRO(PARSE_MACRO_ARGUMENTS _switches _list_names)
+
+  # Using LIST(FIND ...) speeds up the process
+  SET(_keywords ${_switches} ${_list_names})
+
+  # Reset all arguments
+  FOREACH(_arg ${_switches} ${_list_names})
+    SET(_arg_${_arg})
+  ENDFOREACH(_arg)
+
+  # Parse all the arguments and set the corresponding variable
+  # If the option is just a switch, set the variable to its name for later use
+  FOREACH(_arg ${ARGN})
+
+    # Is the argument a keyword?
+    LIST(FIND _keywords ${_arg} _keyword_index)
+    IF(NOT _keyword_index EQUAL -1)
+
+      # Another optimisation
+      SET(_arg_found FALSE)
+      # Switches
+      FOREACH(_switch ${_switches})
+        IF(${_switch} STREQUAL ${_arg})
+          SET(_arg_${_switch} ${_switch})
+          SET(_arg_found TRUE)
+          # Avoid interpreting arguments after this one as options args for the previous one
+          SET(_storage_var)
+          BREAK()
+        ENDIF()
+      ENDFOREACH(_switch)
+
+      # Input options
+      IF(NOT _arg_found)
+        FOREACH(_list_name ${_list_names})
+          IF(${_list_name} STREQUAL ${_arg})
+            SET(_storage_var _arg_${_list_name})
+            BREAK()
+          ENDIF()
+        ENDFOREACH(_list_name)
+      ENDIF(NOT _arg_found)
+
+    ELSE()
+
+      # Arguments of an input option (like source files for SOURCE_FILES)
+      IF(_storage_var)
+        # Store in variable define above in the foreach loop
+        SET(${_storage_var} ${${_storage_var}} ${_arg})
+      ELSE()
+        MESSAGE(FATAL_ERROR "ORXONOX_ADD_${_target_type} was given a non compliant argument: ${_arg}")
+      ENDIF(_storage_var)
+
+    ENDIF()
+
+  ENDFOREACH(_arg)
+ENDMACRO(PARSE_MACRO_ARGUMENTS)
Index: /code/branches/RacingBots_FS18/cmake/tools/PrecompiledHeaderFiles.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/PrecompiledHeaderFiles.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/PrecompiledHeaderFiles.cmake	(revision 11817)
@@ -0,0 +1,159 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #
+
+INCLUDE(GetGCCCompilerFlags)
+
+MACRO(PRECOMPILED_HEADER_FILES_PRE_TARGET _target_name _header_file_arg _sourcefile_var)
+
+  GET_FILENAME_COMPONENT(_pch_header_file ${_header_file_arg} ABSOLUTE)
+  GET_FILENAME_COMPONENT(_pch_header_filename ${_pch_header_file} NAME)
+  GET_FILENAME_COMPONENT(_pch_header_filename_we ${_pch_header_file} NAME_WE)
+
+  IF(NOT EXISTS ${_pch_header_file})
+    MESSAGE(FATAL_ERROR "Specified precompiled headerfile '${_header_file_arg}' does not exist.")
+  ENDIF()
+
+  # Extract arguments from ARGN
+  FOREACH(_arg ${ARGN})
+    IF(NOT "${_arg}" STREQUAL "EXCLUDE")
+      IF(NOT _arg_second)
+        # Source files with PCH support
+        SET(_included_files ${_included_files} ${_arg})
+      ELSE()
+        # Source files to be excluded from PCH support (easier syntax this way)
+        SET(_excluded files ${_excluded_files} ${_arg})
+      ENDIF()
+    ELSE()
+      SET(_arg_second TRUE)
+    ENDIF()
+  ENDFOREACH(_arg)
+
+  # Use ${_sourcefile_var} if no files were specified explicitely
+  IF(NOT _included_files)
+    SET(_source_files ${${_sourcefile_var}})
+  ELSE()
+    SET(_source_files ${_included_files})
+  ENDIF()
+
+  # Exclude files (if specified)
+  FOREACH(_file ${_excluded_files})
+    LIST(FIND _source_files ${_file} _list_index)
+    IF(_list_index GREATER -1)
+      LIST(REMOVE_AT _source_files _list_index)
+    ELSE()
+      MESSAGE(FATAL_ERROR "Could not exclude file ${_file} in target ${_target_name}")
+    ENDIF()
+  ENDFOREACH(_file)
+
+  LIST(FIND ${_sourcefile_var} ${_pch_header_file} _list_index)
+  IF(_list_index EQUAL -1) # Header file could already be included with GET_ALL_HEADER_FILES
+    LIST(APPEND ${_sourcefile_var} ${_pch_header_file})
+  ENDIF()
+
+  IF(MSVC)
+
+    # Write and add one source file, which generates the precompiled header file
+    SET(_pch_source_file "${CMAKE_CURRENT_BINARY_DIR}/${_pch_header_filename_we}.cc")
+    IF(NOT EXISTS ${_pch_source_file})
+      FILE(WRITE ${_pch_source_file} "#include \"${_pch_header_file}\"\n")
+    ENDIF()
+    SET_SOURCE_FILES_PROPERTIES(_pch_source_file PROPERTIES GENERATED TRUE)
+    LIST(APPEND ${_sourcefile_var} ${_pch_source_file})
+
+    SET(_pch_file "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_pch_header_filename}.pch")
+    # Set compile flags for generated source file
+    SET_SOURCE_FILES_PROPERTIES(${_pch_source_file} PROPERTIES COMPILE_FLAGS "/c /Yc\"${_pch_header_file}\" /Fp\"${_pch_file}\"")
+    # Set Compile flags for the other source files
+    FOREACH(_file ${_source_files})
+      GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY)
+      IF(NOT _is_header)
+        GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS)
+        IF(NOT _old_flags)
+          SET(_old_flags "")
+        ENDIF()
+        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES COMPILE_FLAGS "${_old_flags} /FI\"${_pch_header_file}\" /Yu\"${_pch_header_file}\" /Fp\"${_pch_file}\"")
+      ENDIF(NOT _is_header)
+    ENDFOREACH(_file)
+
+  ELSEIF(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
+
+    # Append the gch-dir to make sure compiler finds the pch file
+    INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+
+    # Set Compile flags for the other source files
+    FOREACH(_file ${_source_files})
+      GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY)
+      # Don't use pch file for header-only files and *.rc files
+      IF((NOT _is_header) AND (NOT _file MATCHES "\\.rc$"))
+        GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS)
+        IF(NOT _old_flags)
+          SET(_old_flags "")
+        ENDIF()
+        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES
+          COMPILE_FLAGS "${_old_flags} -I ${CMAKE_CURRENT_SOURCE_DIR} -include ${_pch_header_filename}"
+          OBJECT_DEPENDS "${_pch_header_file}"
+        )
+      ENDIF()
+    ENDFOREACH(_file)
+
+  ENDIF()
+
+ENDMACRO(PRECOMPILED_HEADER_FILES_PRE_TARGET)
+
+FUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET _target_name)
+    # This macro is only necessary for GCC and Clang
+    IF(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
+
+      SET(_pch_file "${CMAKE_CURRENT_BINARY_DIR}/${_pch_header_filename}.gch")
+      SET(_pch_dep_helper_file "${CMAKE_CURRENT_BINARY_DIR}/${_target_name}PCHDependencyHelper.h")
+
+      # Workaround for distcc
+      IF(CMAKE_CXX_COMPILER_ARG1)
+        # remove leading space in compiler argument
+        STRING(REGEX REPLACE "^ +" "" _pch_cmake_cxx_compiler_arg1 "${CMAKE_CXX_COMPILER_ARG1}")
+      ENDIF()
+
+      # Get compiler flags of the source files
+      GET_GCC_COMPILER_FLAGS(${_target_name} _pch_gcc_flags)
+
+      # Make sure we recompile the pch file even if only the flags change
+      IF(NOT "${_pch_gcc_flags}" STREQUAL "${_INTERNAL_${_target_name}_PCH_GCC_FLAGS}" OR NOT EXISTS "${_pch_dep_helper_file}")
+        SET(_INTERNAL_${_target_name}_PCH_GCC_FLAGS "${_pch_gcc_flags}" CACHE INTERNAL "")
+        FILE(WRITE ${_pch_dep_helper_file} "/* ${_pch_gcc_flags} */")
+      ENDIF()
+
+      # Compile the header file
+      ADD_CUSTOM_COMMAND(
+        OUTPUT ${_pch_file}
+        COMMAND ${CMAKE_CXX_COMPILER}
+        ARGS ${pchsupport_compiler_cxx_arg1} ${_pch_gcc_flags} -c -x c++-header -o ${_pch_file} ${_pch_header_file}
+        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+        DEPENDS ${_pch_dep_helper_file}
+        IMPLICIT_DEPENDS CXX ${_pch_header_file}
+        VERBATIM
+      )
+      ADD_CUSTOM_TARGET(${_target_name}PrecompiledHeader DEPENDS ${_pch_file})
+      ADD_DEPENDENCIES(${_target_name} ${_target_name}PrecompiledHeader)
+
+    ENDIF(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
+ENDFUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET)
Index: /code/branches/RacingBots_FS18/cmake/tools/SeparateFlags.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/SeparateFlags.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/SeparateFlags.cmake	(revision 11817)
@@ -0,0 +1,63 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Separates a string of program flags like "--blubb -test -D AA".
+ #    " -" or " /" denotes the start of a flag.
+ #    The same sequence inside double quotation marks is being ignored.
+ #    Spaces not within quotes are cleaned meaningfully.
+ #  Note:
+ #    This macro cannot cope with semicolons in the flag string!
+
+FUNCTION(SEPARATE_FLAGS _flags _output_variable)
+  # Visual studio (esp. IntelliSense) doesn't like dashes to specify arguments
+  # Always use foward slashes instead
+  IF(MSVC)
+    SET(_argument_starter "/")
+  ELSE()
+    SET(_argument_starter "-")
+  ENDIF(MSVC)
+
+  SET(_flags_prep " ${_flags} -")
+  # Separate the chunks
+  STRING(REPLACE " " " ;" _flag_chunks "${_flags_prep}") # Max loop iterations
+  SET(_flag_string)
+  SET(_parsed_flags)
+  # Loop is necessary because the regex engine is greedy
+  FOREACH(_chunk ${_flag_chunks})
+    SET(_flag_string "${_flag_string}${_chunk}")
+    # Replace all " -" and " /" inside quotation marks
+    STRING(REGEX REPLACE "^(([^\"]*\"[^\"]*\")*[^\"]*\"[^\"]*) [/-]([^\"]*\")"
+           "\\1@39535493@\\3" _flag_string "${_flag_string}")
+    # Extract one flag if possible
+    SET(_flag)
+    STRING(REGEX REPLACE "^.* [/-](.+)( [/-].*$)" "${_argument_starter}\\1" _flag "${_flag_string}")
+    STRING(REGEX REPLACE "^.* [/-](.+)( [/-].*$)" "\\2"  _flag_string "${_flag_string}")
+    IF(NOT _flag STREQUAL _flag_string)
+      STRING(STRIP "${_flag}" _flag_stripped)
+      LIST(APPEND _parsed_flags "${_flag_stripped}")
+    ENDIF(NOT _flag STREQUAL _flag_string)
+  ENDFOREACH(_chunk)
+
+  # Re-replace all " -" and " /" inside quotation marks
+  STRING(REGEX REPLACE "@39535493@" " -" _parsed_flags "${_parsed_flags}")
+  SET(${_output_variable} "${_parsed_flags}" PARENT_SCOPE)
+ENDFUNCTION(SEPARATE_FLAGS)
Index: /code/branches/RacingBots_FS18/cmake/tools/SetCacheAdvanced.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/SetCacheAdvanced.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/SetCacheAdvanced.cmake	(revision 11817)
@@ -0,0 +1,36 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Write to the cache by force, but only if the user hasn't changed the value
+ #    Additional argument is the value (may also be a list)
+
+FUNCTION(SET_CACHE_ADVANCED _varname _type _docstring)
+  SET(_value ${ARGN})
+  IF(NOT "${_type}" MATCHES "^(STRING|BOOL|PATH|FILEPATH)$")
+    MESSAGE(FATAL_ERROR "${_type} is not a valid CACHE entry type")
+  ENDIF()
+
+  IF(NOT DEFINED _INTERNAL_${_varname} OR "${_INTERNAL_${_varname}}" STREQUAL "${${_varname}}")
+    SET(${_varname} "${_value}" CACHE ${_type} "${_docstring}" FORCE)
+    SET(_INTERNAL_${_varname} "${_value}" CACHE INTERNAL "Do not edit in any case!")
+  ENDIF()
+ENDFUNCTION(SET_CACHE_ADVANCED)
Index: /code/branches/RacingBots_FS18/cmake/tools/SourceFileUtilities.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/SourceFileUtilities.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/SourceFileUtilities.cmake	(revision 11817)
@@ -0,0 +1,91 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Several functions that help organising the source tree.
+ #    [ADD/SET]_SOURCE_FILES - Writes source files to the cache by force and
+ #                             adds the current directory.
+ #                             Also compiles multiple source files into a single
+ #                             translation unit (faster)
+ #                             Use [END_]BUILD_UNIT in
+ #                             [ADD|SET]_SOURCE_FILES and specify the name of
+ #                             the new source file after BUILD_UNIT
+ #    GET_ALL_HEADER_FILES   - Finds all header files recursively.
+ #    GENERATE_SOURCE_GROUPS - Set Visual Studio source groups.
+ #
+
+FUNCTION(PREPARE_SOURCE_FILES)
+  SET(_source_files)
+  FOREACH(_file ${ARGN})
+    IF(_file MATCHES "^(BUILD_UNIT|END_BUILD_UNIT)$")
+      # Append keywords verbatim
+      LIST(APPEND _source_files ${_file})
+    ELSE()
+      # Store file with path relative to the root source directory
+      FILE(RELATIVE_PATH _file_rel ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
+      LIST(APPEND _source_files ./${_file_rel})
+    ENDIF()
+  ENDFOREACH(_file)
+  SET(_source_files ${_source_files} PARENT_SCOPE)
+ENDFUNCTION(PREPARE_SOURCE_FILES)
+
+
+# Adds source files with the full path to a list
+FUNCTION(ADD_SOURCE_FILES _varname)
+  PREPARE_SOURCE_FILES(${ARGN})
+  # Write into the cache to avoid variable scoping in subdirs
+  SET(${_varname} ${${_varname}} ${_source_files} CACHE INTERNAL "Do not edit")
+ENDFUNCTION(ADD_SOURCE_FILES)
+
+
+# Sets source files with the full path
+FUNCTION(SET_SOURCE_FILES _varname)
+  PREPARE_SOURCE_FILES(${ARGN})
+  # Write into the cache to avoid variable scoping in subdirs
+  SET(${_varname} ${_source_files} CACHE INTERNAL "Do not edit")
+ENDFUNCTION(SET_SOURCE_FILES)
+
+
+# Search the entire directory tree for header files and add them to a variable
+MACRO(GET_ALL_HEADER_FILES _target_varname)
+  FILE(GLOB_RECURSE ${_target_varname} ${CMAKE_CURRENT_SOURCE_DIR} "*.h")
+ENDMACRO(GET_ALL_HEADER_FILES)
+
+
+# Generate source groups according to the directory structure
+FUNCTION(GENERATE_SOURCE_GROUPS)
+
+  FOREACH(_file ${ARGN})
+    GET_SOURCE_FILE_PROPERTY(_full_filepath ${_file} LOCATION)
+    FILE(RELATIVE_PATH _relative_path ${CMAKE_CURRENT_SOURCE_DIR} ${_full_filepath})
+    IF(NOT _relative_path MATCHES "^\\.\\./") # Has "../" at the beginning
+      GET_FILENAME_COMPONENT(_relative_path ${_relative_path} PATH)
+      STRING(REPLACE "/" "\\\\" _group_path "${_relative_path}")
+      SOURCE_GROUP("Source\\${_group_path}" FILES ${_file})
+    ELSEIF(_relative_path MATCHES ".*\\.rc") #Resource files
+      SOURCE_GROUP("Resource Files" FILES ${_file})
+    ELSE()
+      # File is being generated in the binary directory
+      SOURCE_GROUP("Generated" FILES ${_file})
+    ENDIF()
+  ENDFOREACH(_file)
+
+ENDFUNCTION(GENERATE_SOURCE_GROUPS)
Index: /code/branches/RacingBots_FS18/cmake/tools/TargetUtilities.cmake
===================================================================
--- /code/branches/RacingBots_FS18/cmake/tools/TargetUtilities.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/cmake/tools/TargetUtilities.cmake	(revision 11817)
@@ -0,0 +1,502 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Adds a library or an executable like ADD_LIBRARY/ADD_EXECUTABLE, but
+ #    accepts a lot more input information. Simply supply the keywords
+ #    described below in any order you wish.
+ #    The output is then stored in "_arg_ARGNAME" where ARGNAME is the the
+ #    name of the switch or list.
+ #
+ #    Switches: (when given --> TRUE, FALSE otherwise)
+ #      FIND_HEADER_FILES: Searches the current directory for all header files
+ #                         and adds them to the target.
+ #      EXCLUDE_FROM_ALL:  Inherited from ADD_LIBRARY/ADD_EXECUTABLE
+ #      ORXONOX_EXTERNAL:  Specify this for third party libraries
+ #      NO_DLL_INTERFACE:  Link statically with MSVC
+ #      NO_SOURCE_GROUPS:  Don't create msvc source groups
+ #      MODULE:            For dynamic module libraries (libraries only)
+ #      PLUGIN:            For dynamic plugin libraries (libraries only)
+ #                         Plugins are a special kind of modules that can be
+ #                         loaded and unloaded during runtime on demand
+ #      WIN32:             Inherited from ADD_EXECUTABLE (executables only)
+ #      PCH_NO_DEFAULT:    Do not make precompiled header files default if
+ #                         specified with PCH_FILE
+ #      NO_INSTALL:        Do not install the target at all
+ #      NO_VERSION:        Prevents adding any version to a target
+ #      NO_BUILD_UNITS:    Disables automatic (full) build units
+ #
+ #    Lists:
+ #      LINK_LIBRARIES:    Redirects to TARGET_LINK_LIBRARIES
+ #      LINK_LIBS_LINUX:   Redirects to TARGET_LINK_LIBRARIES only on Linux
+ #      LINK_LIBS_WIN32:   Redirects to TARGET_LINK_LIBRARIES only on Windows
+ #      LINK_LIBS_APPLE:   Redirects to TARGET_LINK_LIBRARIES only on Apple
+ #      LINK_LIBS_UNIX:    Redirects to TARGET_LINK_LIBRARIES only on UNIX
+ #      VERSION:           Set version to the binary
+ #      SOURCE_FILES:      Source files for the target
+ #      DEFINE_SYMBOL:     Sets the DEFINE_SYMBOL target property
+ #      TOLUA_FILES:       Files with tolua interface
+ #      PCH_FILE:          Precompiled header file
+ #      PCH_EXCLUDE:       Source files to be excluded from PCH support
+ #      OUTPUT_NAME:       If you want a different name than the target name
+ #      EXCLUDE_FROM_BUILD_UNITS: Specifies files that are not put into
+ #                         automatic (full) build units. They can still
+ #                         explicitely be included in a BUILD_UNIT (partial)
+ #  Note:
+ #    This function also installs the target!
+ #  Prerequisistes:
+ #    ORXONOX_DEFAULT_LINK
+ #  Parameters:
+ #    _target_name, ARGN for the macro arguments
+ #
+
+INCLUDE(BuildUnits)
+INCLUDE(CMakeDependentOption)
+INCLUDE(CapitaliseName)
+INCLUDE(GenerateToluaBindings)
+INCLUDE(ParseMacroArguments)
+INCLUDE(SourceFileUtilities)
+IF(PCH_COMPILER_SUPPORT)
+  INCLUDE(PrecompiledHeaderFiles)
+ENDIF()
+
+MACRO(ORXONOX_ADD_LIBRARY _target_name)
+  SET(_additional_switches MODULE PLUGIN)
+  TU_ADD_TARGET(${_target_name} LIBRARY "${_additional_switches}" ${ARGN})
+ENDMACRO(ORXONOX_ADD_LIBRARY)
+
+MACRO(ORXONOX_ADD_EXECUTABLE _target_name)
+  SET(_additional_switches WIN32)
+  TU_ADD_TARGET(${_target_name} EXECUTABLE "${_additional_switches}" ${ARGN})
+  
+  # When using Visual Studio we want to use the output directory as working
+  # directory and we also want to specify where the external dlls
+  # (lua, ogre, etc.) are. The problem hereby is that these information cannot
+  # be specified in CMake because they are not stored in the actual project file.
+  # This workaround will create a configured *.vcproj.user file that holds the
+  # right values. When starting the solution for the first time,
+  # these get written to the *vcproj.yourPCname.yourname.user
+  IF(MSVC)
+    IF(CMAKE_CL_64)
+      SET(MSVC_PLATFORM "x64")
+    ELSE()
+      SET(MSVC_PLATFORM "Win32")
+    ENDIF()
+    IF(NOT (MSVC_VERSION LESS 1600)) #For all versions >= Visual Studio 2010
+      CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/src/template.vcxproj.user.in" "${CMAKE_CURRENT_BINARY_DIR}/${_target_name}.vcxproj.user")
+    ELSE()
+      STRING(REGEX REPLACE "^Visual Studio ([0-9][0-9]?).*$" "\\1"
+             VISUAL_STUDIO_VERSION_SIMPLE "${CMAKE_GENERATOR}")
+      CONFIGURE_FILE("${CMAKE_SOURCE_DIR}/src/template.vcproj.user.in" "${CMAKE_CURRENT_BINARY_DIR}/${_target_name}.vcproj.user")
+    ENDIF()
+  ENDIF(MSVC)
+ENDMACRO(ORXONOX_ADD_EXECUTABLE)
+
+
+MACRO(TU_ADD_TARGET _target_name _target_type _additional_switches)
+  CAPITALISE_NAME(${_target_name} _target_name_capitalised)
+  STRING(TOUPPER "${_target_name}" _target_name_upper)
+
+  # Specify all possible options (either switch or with add. arguments)
+  SET(_switches   FIND_HEADER_FILES  EXCLUDE_FROM_ALL  ORXONOX_EXTERNAL
+                  NO_DLL_INTERFACE   NO_SOURCE_GROUPS  PCH_NO_DEFAULT 
+                  NO_INSTALL         NO_VERSION        NO_BUILD_UNITS
+                  ${_additional_switches})
+  SET(_list_names LINK_LIBRARIES     VERSION           SOURCE_FILES
+                  DEFINE_SYMBOL      TOLUA_FILES       PCH_FILE
+                  PCH_EXCLUDE        OUTPUT_NAME       LINK_LIBS_LINUX
+                  LINK_LIBS_WIN32    LINK_LIBS_APPLE   LINK_LIBS_UNIX
+                  EXCLUDE_FROM_BUILD_UNITS)
+
+  PARSE_MACRO_ARGUMENTS("${_switches}" "${_list_names}" ${ARGN})
+
+  # Process source files with support for build units
+  # Note: All file paths are relative to the root source directory, even the
+  #       name of the build unit.
+  SET(_${_target_name}_source_files)
+  SET(_get_build_unit_file FALSE)
+  SET(_add_to_build_unit FALSE)
+  FOREACH(_file ${_arg_SOURCE_FILES})
+    IF(_file STREQUAL "BUILD_UNIT")
+      # Next file is the name of the build unit
+      SET(_get_build_unit_file TRUE)
+    ELSEIF(_file STREQUAL "END_BUILD_UNIT")
+      IF(NOT _build_unit_file)
+        MESSAGE(FATAL_ERROR "No name provided for build unit")
+      ENDIF()
+      IF(ENABLE_BUILD_UNITS)
+        IF(NOT _build_unit_include_string)
+          MESSAGE(STATUS "Warning: Empty build unit!")
+        ENDIF()
+        IF(EXISTS ${_build_unit_file})
+          FILE(READ ${_build_unit_file} _include_string_file)
+        ENDIF()
+        IF(NOT _build_unit_include_string STREQUAL "${_include_string_file}")
+          FILE(WRITE ${_build_unit_file} "${_build_unit_include_string}")
+        ENDIF()
+        LIST(APPEND _${_target_name}_source_files ${_build_unit_file})
+        LIST(APPEND _${_target_name}_build_units ${_build_unit_file})
+        # Store the number of files included. May be used for full build units.
+        SET_SOURCE_FILES_PROPERTIES(${_build_unit_file}
+          PROPERTIES BUILD_UNIT_SIZE "${_build_unit_count}")
+      ENDIF()
+      SET(_add_to_build_unit FALSE)
+    ELSEIF(_get_build_unit_file)
+      # Note: ${_file} is relative to the binary directory
+      SET(_build_unit_file ${CMAKE_BINARY_DIR}/${_file})
+      SET(_get_build_unit_file FALSE)
+      SET(_add_to_build_unit TRUE)
+      SET(_build_unit_include_string)
+      SET(_build_unit_count "0")
+    ELSE()
+      # Default, add source file
+
+      # Prepare relative paths
+      IF(NOT _file MATCHES "^(.\\:|\\/)")
+        # Path can be relative to the current source directory if the file was
+        # not added with the source file macros. Otherwise there is a "./" at
+        # the beginning of each file and the filename is relative
+        # to the CMAKE_SOURCE_DIR
+        STRING(REGEX REPLACE "^\\.\\/(.+)$" "\\1" _temp ${_file})
+        IF(NOT ${_temp} STREQUAL ${_file})
+          SET(_file ${CMAKE_SOURCE_DIR}/${_temp})
+        ELSE()
+          SET(_file ${CMAKE_CURRENT_SOURCE_DIR}/${_file})
+        ENDIF()
+      ENDIF()
+
+      LIST(APPEND _${_target_name}_source_files ${_file})
+
+      # Handle build units
+      IF(_add_to_build_unit AND ENABLE_BUILD_UNITS)
+        IF(_file MATCHES "\\.(c|cc|cpp|cxx)$")
+          SET(_build_unit_include_string "${_build_unit_include_string}#include \"${_file}\"\n")
+          MATH(EXPR _build_unit_count "1 + ${_build_unit_count}")
+        ENDIF()
+        # Don't compile these files, even if they are source files
+        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
+      ENDIF()
+    ENDIF()
+  ENDFOREACH(_file)
+
+  # Assemble all header files of the library
+  IF(_arg_FIND_HEADER_FILES)
+    GET_ALL_HEADER_FILES(_${_target_name}_header_files)
+  ENDIF()
+
+  # Combine source and header files
+  SET(_${_target_name}_files
+    ${_${_target_name}_header_files}
+    ${_${_target_name}_source_files}
+  )
+  # Remove potential duplicates
+  LIST(REMOVE_DUPLICATES _${_target_name}_files)
+
+  # TOLUA_FILES
+  IF(_arg_TOLUA_FILES)
+    GENERATE_TOLUA_BINDINGS(${_target_name_capitalised} _${_target_name}_files
+                            INPUTFILES ${_arg_TOLUA_FILES})
+    # Workaround for XCode: The folder where the bind files are written to has
+    # to be present beforehand.
+    IF(CMAKE_CONFIGURATION_TYPES)
+      FOREACH(_dir ${CMAKE_CONFIGURATION_TYPES})
+        FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${_dir})
+      ENDFOREACH(_dir)
+    ENDIF()
+  ENDIF()
+
+  # Mark files to be excluded from build units
+  IF(_arg_EXCLUDE_FROM_BUILD_UNITS)
+    SET_SOURCE_FILES_PROPERTIES(${_arg_EXCLUDE_FROM_BUILD_UNITS}
+      PROPERTIES EXCLUDE_FROM_BUILD_UNITS TRUE)
+  ENDIF()
+
+  # Full build units
+  IF(ENABLE_BUILD_UNITS AND NOT _arg_NO_BUILD_UNITS)
+    # Use full build units even in partial mode for externals
+    IF(ENABLE_BUILD_UNITS MATCHES "full" OR _arg_ORXONOX_EXTERNAL)
+      GENERATE_BUILD_UNITS(${_target_name} _${_target_name}_files)
+    ENDIF()
+  ENDIF()
+
+  # First part (pre target) of precompiled header files
+  IF(PCH_COMPILER_SUPPORT AND _arg_PCH_FILE)
+    # Provide convenient option to control PCH
+    IF(_arg_PCH_NO_DEFAULT)
+      SET(PCH_DEFAULT FALSE)
+    ELSE()
+      SET(PCH_DEFAULT TRUE)
+    ENDIF()
+    CMAKE_DEPENDENT_OPTION(PCH_ENABLE_${_target_name_upper}
+      "Enable using precompiled header files for library ${_target_name}." ${PCH_DEFAULT} PCH_ENABLE OFF)
+    # Almost never used individually, but produces a lot of options --> hide
+    MARK_AS_ADVANCED(PCH_ENABLE_${_target_name_upper})
+
+    IF(PCH_ENABLE_${_target_name_upper} AND NOT PCH_DISABLE_${_target_name})
+      PRECOMPILED_HEADER_FILES_PRE_TARGET(${_target_name} ${_arg_PCH_FILE} _${_target_name}_files EXCLUDE ${_arg_PCH_EXCLUDE})
+    ENDIF()
+  ENDIF()
+
+  # Generate the source groups
+  IF(MSVC AND NOT _arg_NO_SOURCE_GROUPS)
+    GENERATE_SOURCE_GROUPS(${_${_target_name}_files})
+
+    IF(NOT _arg_ORXONOX_EXTERNAL)
+      # Move the ...Prereqs.h and the PCH files to the 'Config' section
+      IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_target_name_capitalised}Prereqs.h)
+        SOURCE_GROUP("Config" FILES ${_target_name_capitalised}Prereqs.h)
+      ENDIF()
+      IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_arg_PCH_FILE})
+        SOURCE_GROUP("Config" FILES ${CMAKE_CURRENT_SOURCE_DIR}/${_arg_PCH_FILE})
+      ENDIF()
+    ENDIF()
+  ENDIF()
+
+  # Set link mode (SHARED/STATIC)
+  IF(MSVC AND _arg_NO_DLL_INTERFACE)
+    # Certain libraries don't have dllexport/dllimport and can't be linked shared with MSVC
+    SET(_link_mode STATIC)
+  ELSEIF(_arg_ORXONOX_EXTERNAL)
+    # Externals can be linked shared or statically
+    SET(_link_mode ${ORXONOX_EXTERNAL_LINK_MODE})
+  ELSE()
+    # All our own libraries are linked dynamically because of static symbols
+    SET(_link_mode SHARED)
+  ENDIF()
+
+  # No warnings needed from third party libraries
+  IF(_arg_ORXONOX_EXTERNAL)
+    REMOVE_COMPILER_FLAGS("-W3 -W4" MSVC)
+    ADD_COMPILER_FLAGS("-w" NOT MSVC)
+    ADD_COMPILER_FLAGS("-W0" MSVC)
+  ENDIF()
+
+  # Don't compile header files
+  FOREACH(_file ${_${_target_name}_files})
+    IF(NOT _file MATCHES "\\.(c|cc|cpp|cxx|mm|rc)$")
+      SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES HEADER_FILE_ONLY TRUE)
+    ENDIF()
+  ENDFOREACH(_file)
+
+
+
+  # Add the library/executable
+  IF("${_target_type}" STREQUAL "LIBRARY")
+    ADD_LIBRARY(${_target_name} ${_link_mode}
+                ${_arg_EXCLUDE_FROM_ALL} ${_${_target_name}_files})
+  ELSE()
+    ADD_EXECUTABLE(${_target_name} ${_arg_WIN32} ${_arg_EXCLUDE_FROM_ALL}
+                   ${_${_target_name}_files})
+  ENDIF()
+
+
+
+  # Change library prefix to "lib"
+  IF(MSVC AND ${_target_type} STREQUAL "LIBRARY")
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES
+      PREFIX "lib"
+    )
+  ENDIF()
+
+  # MSVC hack to exclude external library sources from the intellisense database
+  # (IntelliSense stops working when adding "-Zm1000" as compile flag. "/Zm1000"
+  # would not work because of the slash)
+  IF(_arg_ORXONOX_EXTERNAL AND MSVC)
+    GET_TARGET_PROPERTY(_compile_flags ${_target_name} COMPILE_FLAGS)
+    IF(NOT _compile_flags)
+      SET(_compile_flags)
+    ENDIF()
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES COMPILE_FLAGS "${_compile_flags} -Zm1000")
+  ENDIF()
+
+  # Configure modules
+  IF (_arg_MODULE)
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES
+      RUNTIME_OUTPUT_DIRECTORY ${CMAKE_MODULE_OUTPUT_DIRECTORY} # Windows
+      LIBRARY_OUTPUT_DIRECTORY ${CMAKE_MODULE_OUTPUT_DIRECTORY} # Unix
+    )
+    ADD_MODULE_OR_PLUGIN(${_target_name} ${CMAKE_MODULE_OUTPUT_DIRECTORY} ${MODULE_INSTALL_DIRECTORY} ${ORXONOX_MODULE_EXTENSION})
+    # Ensure that the main program depends on the module
+    SET(ORXONOX_MODULES ${ORXONOX_MODULES} ${_target_name} CACHE INTERNAL "")
+  ENDIF()
+
+  # Configure plugins
+  IF (_arg_PLUGIN)
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES
+      RUNTIME_OUTPUT_DIRECTORY ${CMAKE_PLUGIN_OUTPUT_DIRECTORY} # Windows
+      LIBRARY_OUTPUT_DIRECTORY ${CMAKE_PLUGIN_OUTPUT_DIRECTORY} # Unix
+    )
+    ADD_MODULE_OR_PLUGIN(${_target_name} ${CMAKE_PLUGIN_OUTPUT_DIRECTORY} ${PLUGIN_INSTALL_DIRECTORY} ${ORXONOX_PLUGIN_EXTENSION})
+    # Ensure that the main program depends on the plugin
+    SET(ORXONOX_MODULES ${ORXONOX_MODULES} ${_target_name} CACHE INTERNAL "")
+  ENDIF()
+
+  # Static library flags are not globally available
+  IF(ORXONOX_STATIC_LINKER_FLAGS)
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES STATIC_LIBRARY_FLAGS ${ORXONOX_STATIC_LINKER_FLAGS})
+  ENDIF()
+
+  # LINK_LIBRARIES
+  IF(_arg_LINK_LIBRARIES)
+    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBRARIES})
+  ENDIF()
+  IF(_arg_LINK_LIBS_LINUX AND LINUX)
+    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_LINUX})
+  ENDIF()
+  IF(_arg_LINK_LIBS_WIN32 AND WIN32)
+    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_WIN32})
+  ENDIF()
+  IF(_arg_LINK_LIBS_APPLE AND APPLE)
+    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_APPLE})
+  ENDIF()
+  IF(_arg_LINK_LIBS_UNIX AND UNIX)
+    TARGET_LINK_LIBRARIES(${_target_name} ${_arg_LINK_LIBS_UNIX})
+  ENDIF()
+
+  # Enable gcov (gcc code coverage analysis tool) if ENABLE_GCOV flag is defined
+  IF(ENABLE_GCOV)
+    TARGET_LINK_LIBRARIES(${_target_name} gcov)
+    ADD_COMPILER_FLAGS("-fprofile-arcs")
+    ADD_COMPILER_FLAGS("-ftest-coverage")
+  ENDIF()
+
+  # Visual Leak Detector specific stuff (avoids the include)
+  IF(VISUAL_LEAK_DETECTOR_ENABLE)
+    TARGET_LINK_LIBRARIES(${_target_name} debug ${VLD_LIBRARY})
+  ENDIF()
+
+  # RPATH settings for the installation
+  IF("${_target_type}" STREQUAL "LIBRARY")
+    IF(_arg_MODULE)
+      SET(_rpath "${MODULE_RPATH}")
+    ELSEIF(_arg_PLUGIN)
+      SET(_rpath "${PLUGIN_RPATH}")
+    ELSE()
+      SET(_rpath "${LIBRARY_RPATH}")
+    ENDIF()
+  ELSE()
+    SET(_rpath "${RUNTIME_RPATH}")
+  ENDIF()
+  SET_TARGET_PROPERTIES(${_target_name} PROPERTIES INSTALL_RPATH "${_rpath}")
+
+  # DEFINE_SYMBOL
+  IF(_arg_DEFINE_SYMBOL)
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES DEFINE_SYMBOL ${_arg_DEFINE_SYMBOL})
+  ELSEIF(NOT _arg_ORXONOX_EXTERNAL)
+    # Automatically add the macro definitions for our own libraries
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES DEFINE_SYMBOL "${_target_name_upper}_SHARED_BUILD")
+  ENDIF()
+
+  # VERSION
+  IF(_arg_VERSION)
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES VERSION ${_arg_VERSION})
+  ELSEIF(NOT _arg_ORXONOX_EXTERNAL AND NOT _arg_NO_VERSION AND NOT ${_target_type} STREQUAL "EXECUTABLE")
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES VERSION ${ORXONOX_VERSION})
+  ENDIF()
+
+  # OUTPUT_NAME
+  IF(_arg_OUTPUT_NAME)
+    SET_TARGET_PROPERTIES(${_target_name} PROPERTIES OUTPUT_NAME  ${_arg_OUTPUT_NAME})
+  ENDIF()
+
+  # Second part of precompiled header files
+  IF(PCH_COMPILER_SUPPORT AND PCH_ENABLE_${_target_name_upper} AND _arg_PCH_FILE AND NOT PCH_DISABLE_${_target_name})
+    PRECOMPILED_HEADER_FILES_POST_TARGET(${_target_name} ${_arg_PCH_FILE})
+  ENDIF()
+
+  # Install all targets except for static ones (executables also have SHARED in _link_mode)
+  IF(${_link_mode} STREQUAL "SHARED" AND NOT _arg_NO_INSTALL)
+    IF(_arg_MODULE)
+      INSTALL(TARGETS ${_target_name}
+        RUNTIME DESTINATION ${MODULE_INSTALL_DIRECTORY}
+        LIBRARY DESTINATION ${MODULE_INSTALL_DIRECTORY}
+      )
+    ELSEIF(_arg_PLUGIN)
+      INSTALL(TARGETS ${_target_name}
+        RUNTIME DESTINATION ${PLUGIN_INSTALL_DIRECTORY}
+        LIBRARY DESTINATION ${PLUGIN_INSTALL_DIRECTORY}
+      )
+    ELSE()
+      INSTALL(TARGETS ${_target_name}
+        RUNTIME DESTINATION ${RUNTIME_INSTALL_DIRECTORY}
+        LIBRARY DESTINATION ${LIBRARY_INSTALL_DIRECTORY}
+      )
+    ENDIF()
+    IF(INSTALL_PDB_FILES) # MSVC specific: install debug symbols files
+      FOREACH(_config RelForDevs RelWithDebInfo)
+        GET_TARGET_PROPERTY(_location ${_target_name} LOCATION_${_config})
+        # Get absolute location without dll/exe extension
+        STRING(REGEX REPLACE "^(.+)\\.(dll|exe)$" "\\1" _location_we ${_location})
+        IF(_arg_MODULE)
+          INSTALL(FILES ${_location_we}.pdb
+            DESTINATION ${MODULE_INSTALL_DIRECTORY}
+            CONFIGURATIONS ${_config}
+          )
+        ELSEIF(_arg_PLUGIN)
+          INSTALL(FILES ${_location_we}.pdb
+            DESTINATION ${PLUGIN_INSTALL_DIRECTORY}
+            CONFIGURATIONS ${_config}
+          )
+        ELSE()
+          INSTALL(FILES ${_location_we}.pdb
+            DESTINATION ${RUNTIME_INSTALL_DIRECTORY}
+            CONFIGURATIONS ${_config}
+          )
+        ENDIF()
+      ENDFOREACH(_config)
+    ENDIF()
+  ENDIF()
+
+ENDMACRO(TU_ADD_TARGET)
+
+
+# Creates a helper file with name <target_name>.<extension> and content <filename_of_the_library>
+# This helps finding dynamically loadable modules or plugins at runtime
+
+FUNCTION(ADD_MODULE_OR_PLUGIN _target_name _output_dir _install_dir _extension)
+
+  IF(CMAKE_CONFIGURATION_TYPES)
+    FOREACH(_config ${CMAKE_CONFIGURATION_TYPES})
+      SET(_helper_directory ${_output_dir}/${_config})
+      FILE(MAKE_DIRECTORY ${_helper_directory})
+      SET(_helper_filename ${_helper_directory}/${_target_name}${_extension})
+
+      FILE(GENERATE OUTPUT ${_helper_filename} CONTENT $<TARGET_FILE_NAME:${_target_name}>)
+
+      INSTALL(
+        FILES ${_helper_filename}
+        DESTINATION ${_install_dir}
+        CONFIGURATIONS ${_config}
+      )
+    ENDFOREACH()
+  ELSE()
+    SET(_helper_directory ${_output_dir})
+    FILE(MAKE_DIRECTORY ${_helper_directory})
+    SET(_helper_filename ${_helper_directory}/${_target_name}${_extension})
+
+    FILE(GENERATE OUTPUT ${_helper_filename} CONTENT $<TARGET_FILE_NAME:${_target_name}>)
+
+    INSTALL(
+      FILES ${_helper_filename}
+      DESTINATION ${_install_dir}
+    )
+  ENDIF()
+ENDFUNCTION(ADD_MODULE_OR_PLUGIN)
Index: /code/branches/RacingBots_FS18/contrib/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/contrib/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/contrib/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,30 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Installs system specific files
+ #
+
+IF(LINUX)
+  INSTALL(FILES orxonox.desktop     DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
+  #INSTALL(FILES orxonox.manpage.xml DESTINATION /usr/man)
+  INSTALL(FILES orxonox.png         DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps)
+ENDIF()
Index: /code/branches/RacingBots_FS18/contrib/orxonox.desktop
===================================================================
--- /code/branches/RacingBots_FS18/contrib/orxonox.desktop	(revision 11817)
+++ /code/branches/RacingBots_FS18/contrib/orxonox.desktop	(revision 11817)
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Name=Orxonox
+Comment=A spacecraft shooter
+Exec=/usr/games/orxonox
+Icon=/usr/share/pixmaps/orxonox.png
+Type=Application
+Categories=Game;ActionGame;
Index: /code/branches/RacingBots_FS18/contrib/orxonox.manpage.xml
===================================================================
--- /code/branches/RacingBots_FS18/contrib/orxonox.manpage.xml	(revision 11817)
+++ /code/branches/RacingBots_FS18/contrib/orxonox.manpage.xml	(revision 11817)
@@ -0,0 +1,275 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+
+<!--
+
+`xsltproc -''-nonet \
+          -''-param man.charmap.use.subset "0" \
+          -''-param make.year.ranges "1" \
+          -''-param make.single.year.ranges "1" \
+          /usr/share/xml/docbook/stylesheet/nwalsh/manpages/docbook.xsl \
+          manpage.xml'
+
+A manual page <package>.<section> will be generated. You may view the
+manual page with: nroff -man <package>.<section> | less'. A typical entry
+in a Makefile or Makefile.am is:
+
+DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl
+XP     = xsltproc -''-nonet -''-param man.charmap.use.subset "0"
+
+manpage.1: manpage.xml
+        $(XP) $(DB2MAN) $<
+
+The xsltproc binary is found in the xsltproc package. The XSL files are in
+docbook-xsl. A description of the parameters you can use can be found in the
+docbook-xsl-doc-* packages. Please remember that if you create the nroff
+version in one of the debian/rules file targets (such as build), you will need
+to include xsltproc and docbook-xsl in your Build-Depends control field.
+Alternatively use the xmlto command/package. That will also automatically
+pull in xsltproc and docbook-xsl.
+
+Notes for using docbook2x: docbook2x-man does not automatically create the
+AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as
+<refsect1> ... </refsect1>.
+
+To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections
+read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be
+found in the docbook-xsl-doc-html package.
+
+Validation can be done using: `xmllint -''-noout -''-valid manpage.xml`
+
+General documentation about man-pages and man-page-formatting:
+man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
+
+-->
+
+  <!ENTITY dhfirstname "Adrian">
+  <!ENTITY dhsurname   "Friedli">
+  <!ENTITY dhusername  "&dhfirstname; &dhsurname;">
+  <!ENTITY dhemail     "adi@koalatux.ch">
+  <!ENTITY dhsection   "6">
+  <!ENTITY dhtitle     "orxonox Gamer Manual">
+  <!ENTITY dhucpackage "ORXONOX">
+  <!ENTITY dhpackage   "orxonox">
+]>
+
+<refentry>
+  <refentryinfo>
+    <title>&dhtitle;</title>
+    <productname>&dhpackage;</productname>
+    <authorgroup>
+      <author>
+       <firstname>&dhfirstname;</firstname>
+        <surname>&dhsurname;</surname>
+        <contrib>Wrote this manpage for the Debian system.</contrib>
+        <address>
+          <email>&dhemail;</email>
+        </address>
+      </author>
+    </authorgroup>
+    <copyright>
+      <year>2010</year>
+      <holder>&dhusername;</holder>
+    </copyright>
+    <legalnotice>
+      <para>This manual page was written for the Debian system
+        (and may be used by others).</para>
+      <para>Permission is granted to copy, distribute and/or modify this
+        document under the terms of the GNU General Public License,
+        Version 2 or (at your option) any later version published by
+        the Free Software Foundation.</para>
+      <para>On Debian systems, the complete text of the GNU General Public
+        License can be found in
+        <filename>/usr/share/common-licenses/GPL-2</filename>.</para>
+    </legalnotice>
+  </refentryinfo>
+  <refmeta>
+    <refentrytitle>&dhucpackage;</refentrytitle>
+    <manvolnum>&dhsection;</manvolnum>
+  </refmeta>
+  <refnamediv>
+    <refname>&dhpackage;</refname>
+    <refpurpose>a spacecraft shooter</refpurpose>
+  </refnamediv>
+  <refsynopsisdiv>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <arg choice="opt"><replaceable class="option">options</replaceable></arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <arg choice="plain"><option>--standalone</option></arg>
+      <arg choice="opt">
+        <group choice="req">
+          <arg choice="plain"><option>-l</option></arg>
+          <arg choice="plain"><option>--level</option></arg>
+        </group>
+        <arg choice="plain"><replaceable>file</replaceable></arg>
+      </arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <arg choice="plain"><option>--client</option></arg>
+      <arg choice="opt"><option>--dest <replaceable>address</replaceable></option></arg>
+      <arg choice="opt">
+        <group choice="req">
+          <arg choice="plain"><option>-p</option></arg>
+          <arg choice="plain"><option>--port</option></arg>
+        </group>
+        <arg choice="plain"><replaceable>port</replaceable></arg>
+      </arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <group choice="req">
+        <arg choice="plain"><option>--dedicated</option></arg>
+        <arg choice="plain"><option>--server</option></arg>
+      </group>
+      <arg choice="opt">
+        <group choice="req">
+          <arg choice="plain"><option>-p</option></arg>
+          <arg choice="plain"><option>--port</option></arg>
+        </group>
+        <arg choice="plain"><replaceable>port</replaceable></arg>
+      </arg>
+      <arg choice="opt">
+        <group choice="req">
+          <arg choice="plain"><option>-l</option></arg>
+          <arg choice="plain"><option>--level</option></arg>
+        </group>
+        <arg choice="plain"><replaceable>file</replaceable></arg>
+      </arg>
+    </cmdsynopsis>
+    <cmdsynopsis>
+      <command>&dhpackage;</command>
+      <arg choice="plain"><option>--masterserver</option></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+  <refsect1 id="description">
+    <title>DESCRIPTION</title>
+    <para>This manual page documents briefly the
+      <command>&dhpackage;</command> command.</para>
+    <para><command>&dhpackage;</command> is a spacecraft shooter that plays in
+      the post-apocalyptic world of our future. Humanity struggles to survive
+      under the threat of wars, economic and ecological disasters. A lot of
+      people search for their luck in the vast space of the solar system. But
+      the human race faces extinction when they realize they are not alone in
+      the galaxy. The Noxons, an evil alien species, believes the human race
+      must be destroyed to free themselves from their cruel god Nox.</para>
+  </refsect1>
+  <refsect1 id="options">
+    <title>OPTIONS</title>
+    <variablelist>
+      <varlistentry>
+        <term><option>--client</option></term>
+        <listitem>
+          <para>Start in client mode.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--console</option></term>
+        <listitem>
+          <para>Start in console mode (text IO only).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--dedicated</option></term>
+        <listitem>
+          <para>Start in dedicated server mode.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--externalDataPath <replaceable>path</replaceable></option></term>
+        <listitem>
+          <para>Path to the external data files.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+          <term><option>--dest <replaceable>address</replaceable></option></term>
+        <listitem>
+          <para>Server hostname/IP (IP in the form of #.#.#.#).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--keyboard_no_grab</option></term>
+        <listitem>
+          <para>Whether not to exclusively grab the keyboard.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-l <replaceable>file</replaceable></option></term>
+        <term><option>--level <replaceable>file</replaceable></option></term>
+        <listitem>
+          <para>Default level file (overrides LevelManager::defaultLevelName_ configValue).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--masterserver</option></term>
+        <listitem>
+          <para>Start in master server mode.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--noIOConsole</option></term>
+        <listitem>
+          <para>Use this if you don't want to use the IOConsole (for instance for Lua debugging).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>-p <replaceable>port</replaceable></option></term>
+        <term><option>--port <replaceable>port</replaceable></option></term>
+        <listitem>
+          <para>Network communication port to be used 0-65535 (default: 55556).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--server</option></term>
+        <listitem>
+          <para>Start in server mode.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--settingsFile <replaceable>file</replaceable></option></term>
+        <listitem>
+          <para>THE configuration file.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--standalone</option></term>
+        <listitem>
+          <para>Start in standalone mode.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><option>--writingPathSuffix <replaceable>suffix</replaceable></option></term>
+        <listitem>
+          <para>Additional subfolder for config and log files.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1 id="files">
+    <title>FILES</title>
+    <variablelist>
+      <varlistentry>
+        <term><filename>${HOME}/.orxonox/config/</filename></term>
+        <listitem>
+          <para>Per-user configuration files to control the
+            behaviour of <application>&dhpackage;</application>.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><filename>${HOME}/.orxonox/log/</filename></term>
+        <listitem>
+          <para>Log files of <application>&dhpackage;</application>.</para>
+        </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1 id="bugs">
+    <title>BUGS</title>
+    <para>The upstreams "<acronym>BTS</acronym>" can be found
+      at <ulink url="http://forum.orxonox.net/viewforum.php?f=6"/>.</para>
+  </refsect1>
+</refentry>
Index: /code/branches/RacingBots_FS18/contrib/orxonox_old.svg
===================================================================
--- /code/branches/RacingBots_FS18/contrib/orxonox_old.svg	(revision 11817)
+++ /code/branches/RacingBots_FS18/contrib/orxonox_old.svg	(revision 11817)
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   version="1.0"
+   width="512"
+   height="512"
+   id="svg2470">
+  <defs
+     id="defs2473" />
+  <g
+     transform="matrix(1.1599689,0,0,1.1599689,-61.312471,31.367136)"
+     id="g2926">
+    <path
+       d="m 273.28125,-3.125 c -0.33753,0 -0.65944,0.08735 -0.90625,0.25 -5.92032,7.076685 -7.84063,17.421024 -12.65625,24.90625 C 253.18934,15.254565 248.02475,7.185974 241.375,0.625 236.24444,0.487636 237.24295,7.769684 236,11.09375 c -1.40718,5.637813 -1.54432,13.090512 -3.71875,17.75 -8.1499,-4.590776 -14.00418,-13.119802 -22.65625,-16.65625 -5.54138,0.49717 -2.26469,8.117402 -2.75,11.625 0.41171,5.885154 1.1234,11.752708 1.21875,17.65625 -9.50055,-2.306123 -17.81793,-8.969835 -27.4375,-10.65625 -3.0683,3.596395 1.24993,8.896672 1.6875,13.09375 1.55845,5.265262 3.58081,10.764988 4.53125,15.90625 -9.11905,0.01479 -18.15995,-4.436704 -27.25,-3.34375 -4.30764,3.112184 1.42027,8.14505 2.78125,11.34375 2.73464,4.97687 6.87252,10.35987 8.40625,15.25 -8.53732,2.40472 -17.83424,0.0399 -26.3125,2.34375 -4.10152,3.72395 2.46967,8.12489 4.59375,10.8125 3.93039,4.27106 9.2141,8.7766 12,13.28125 -8.53218,3.6784 -18.53609,4.45017 -26.5625,9.0625 -2.42321,4.35828 4.70455,6.09961 7.25,8.125 4.54859,1.64473 9.10784,6.62509 14.09375,5.46875 8.13723,-6.11487 16.83861,-12.32293 23.15625,-20.34375 1.00807,-4.69869 -5.24641,-7.46118 -7.3125,-11.0625 -3.66639,-2.9888 -3.46849,-4.56704 1.46875,-4.03125 5.78421,-1.06632 12.57867,0.2104 17.71875,-2.75 0.55821,-5.59782 -4.82637,-10.12365 -7.03125,-15 -1.60907,-2.75911 -5.59927,-7.49445 0.3125,-5.4375 6.54924,0.33788 13.62847,4.26334 20,2 -0.0463,-7.6094 -4.34262,-15.3235 -5.46875,-22.21875 7.15363,1.852187 13.62354,7.6005 21.125,7.46875 3.74883,-2.879531 0.94331,-8.917904 1.25,-12.9375 0.22935,-2.626039 -1.92354,-9.40513 0.0312,-9.5625 6.2856,3.664902 11.23114,10.11029 18.03125,12.5625 4.58537,-1.52821 3.05426,-8.404676 4.5625,-12.125 1.14998,-2.101484 0.31871,-10.345824 2.78125,-9 4.92337,4.70408 8.30534,11.451021 14.3125,14.96875 5.20466,-2.13308 5.66461,-9.220405 8.375,-13.53125 1.15641,-1.528772 2.49879,-8.326772 3.96875,-4.125 3.5119,6.843474 5.79708,14.413287 11.1875,20.15625 4.86052,-6.260249 9.20592,-13.13261 14.59375,-18.84375 2.0846,7.256092 1.73134,15.440104 4.84375,22.28125 3.71306,1.852801 6.89994,-3.785302 10.09375,-5.21875 2.85776,-1.935856 6.57948,-5.653071 9.25,-6.3125 0.74248,7.049444 -1.49508,14.673134 0.96875,21.4375 4.97094,1.63046 9.95865,-3.049665 14.59375,-4.375 2.06444,-0.257305 8.81732,-5.477872 6.875,-0.84375 -1.129,6.58358 -6.01032,13.0311 -4.71875,19.78125 3.10906,3.48067 8.59157,-0.39671 12.53125,-0.1875 3.13681,0.19129 13.05964,-4.50259 9.09375,0.875 -2.92401,5.77285 -7.54509,10.95675 -8.9375,17.34375 2.62412,3.90386 8.77423,1.98887 12.84375,3.21875 2.23111,1.00437 10.53001,-0.7558 8.9375,1.71875 -3.12096,4.0206 -7.83072,7.17714 -9.875,12.0625 5.9344,7.73633 14.64175,13.5482 22,19.90625 2.7109,2.82784 6.84075,3.85912 10,1.1875 5.20461,-3.25861 11.59896,-5.90672 15.125,-11.0625 -0.50167,-4.58807 -7.50322,-3.80105 -10.78125,-5.71875 -4.91178,-1.7421 -12.28829,-2.78454 -15.75,-5.46875 5.3611,-7.20545 13.81313,-12.44008 18.03125,-20.5 -0.0544,-5.63131 -8.06821,-3.59256 -11.5625,-4.0625 -5.50764,-0.26559 -11.93251,-0.17594 -16.78125,-1.53125 3.98173,-8.18256 9.92897,-15.7419 13.75,-24.15625 -1.22332,-5.067064 -8.08293,-1.666959 -11.4375,-1.625 -5.93821,0.79112 -12.659,3.0636 -18.1875,3 1.87474,-9.859316 7.27683,-19.139097 7.90625,-29.21875 -8.3624,0.490945 -15.58786,6.120862 -23.40625,8.71875 -3.19942,1.72205 -6.8437,3.13256 -5.21875,-2.0625 0.29875,-8.263748 1.84585,-16.689658 0.84375,-24.90625 -3.47068,-3.010059 -7.04365,3.652336 -10.3125,4.8125 -4.88832,3.447496 -10.07698,8.395552 -15.09375,10.6875 -2.99429,-8.524686 -2.5226,-18.377103 -6.65625,-26.375 -4.54699,-2.424893 -6.8748,5.195985 -9.78125,7.375 -3.45573,4.331751 -6.79478,8.854684 -10.5625,12.8125 -5.09233,-7.827683 -7.28948,-17.778902 -13.34375,-24.8125 -0.24681,-0.162653 -0.59997,-0.25 -0.9375,-0.25 z m -0.625,96.09375 c -83.26931,0 -150.84375,67.57444 -150.84375,150.84375 0,83.26931 67.57444,150.87502 150.84375,150.875 83.26931,0 150.84373,-67.60569 150.84375,-150.875 0,-83.26931 -67.57444,-150.84375 -150.84375,-150.84375 z"
+       id="path2499"
+       style="fill:#f07905;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.86755997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
+    <path
+       d="m 283.75551,118.69825 c 3.8326,-2.92327 6.59672,-7.30905 6.59672,-10.46691 0,-1.34297 -0.91624,-2.10791 -3.03159,-2.53098 -5.03084,-1.00617 -29.76323,-0.2524 -30.95725,0.94348 -2.45839,2.4622 3.48285,11.25959 9.48884,14.05044 4.86268,2.25958 13.60121,1.28532 17.90328,-1.99603 z m -121.40328,6.85736 c 1.375,-1.48313 5.425,-5.00387 9,-7.82385 3.575,-2.81999 6.82351,-5.58801 7.21891,-6.15116 0.39617,-0.56426 -2.40958,-4.17692 -6.25,-8.04744 -3.8329,-3.86293 -6.96891,-7.35043 -6.96891,-7.75 0,-0.39956 2.85899,-0.72648 6.35331,-0.72648 9.68177,0 18.64695,-1.1504 18.64458,-2.39246 -0.001,-0.60915 -2.70021,-5.15754 -5.99789,-10.10754 -8.49307,-12.74857 -8.48584,-12.76107 5.5,-9.5 9.10186,2.12228 13.5,2.51208 13.5,1.19648 0,-0.44193 -1.575,-5.48035 -3.5,-11.19648 -1.925,-5.716132 -3.5,-10.75455 -3.5,-11.196484 0,-1.628868 2.99886,-0.696708 11.89199,3.696484 12.59254,6.22069 12.53395,6.23695 11.71425,-3.25 -0.36829,-4.2625 -0.93833,-9.8875 -1.26676,-12.5 -0.4112,-3.270922 -0.2373,-4.75 0.55848,-4.75 0.63559,0 5.21065,3.375 10.16679,7.5 4.95614,4.125 9.4237,7.5 9.9279,7.5 0.9686,0 1.28832,-1.459199 3.26869,-14.918223 0.69491,-4.722809 1.77231,-8.595424 2.45433,-8.821889 0.66861,-0.222016 4.22099,3.678685 7.89417,8.668223 3.67319,4.989539 7.24664,9.071889 7.94102,9.071889 0.69438,0 2.62557,-3.2625 4.29153,-7.25 1.66597,-3.9875 3.75454,-8.974691 4.64127,-11.082648 2.17969,-5.181579 3.42785,-3.956447 8.16629,8.015595 3.82395,9.661498 5.73859,11.908239 7.74466,9.087976 12.20994,-17.165585 13.87349,-18.833994 14.97713,-15.020923 0.27858,0.9625 0.99821,5.35 1.59918,9.75 1.43433,10.50148 1.89914,12.5 2.90721,12.5 0.46201,0 4.61594,-3.145402 9.23095,-6.989783 11.34683,-9.452104 11.97892,-9.342636 10.73188,1.858597 -1.22969,11.045385 -1.04683,15.131186 0.67721,15.131186 0.83499,0 6.02051,-2.259383 11.52338,-5.020852 7.47785,-3.752561 10.1364,-4.679002 10.52453,-3.667553 0.28562,0.744314 -1.07491,5.757378 -3.02339,11.140145 -1.94848,5.38276 -3.54269,10.40816 -3.54269,11.16755 0,1.8498 2.71696,1.7257 13.90179,-0.63496 5.17098,-1.09138 9.78348,-1.98433 10.25,-1.98433 1.74445,0 0.6888,2.30419 -5.15179,11.24492 -3.3,5.05161 -6,9.70039 -6,10.33062 0,1.36134 7.65859,2.40367 17.75,2.41577 3.9875,0.005 7.25,0.35919 7.25,0.78758 0,0.42839 -2.925,3.67789 -6.5,7.22111 -3.575,3.54322 -6.5,6.76642 -6.5,7.16266 0,0.39625 2.8125,2.87597 6.25,5.5105 3.4375,2.63454 9.05115,7.38584 12.47478,10.55845 3.42362,3.17262 6.54497,5.76839 6.93632,5.76839 1.96193,0 20.39401,-11.33531 20.06133,-12.33727 -0.31695,-0.95457 -12.37571,-4.68026 -25.97243,-8.02445 -1.5125,-0.37201 -2.75,-1.30537 -2.75,-2.07412 0,-0.76876 4.77592,-5.89576 10.61316,-11.39334 6.00519,-5.65575 10.32132,-10.46781 9.94099,-11.08321 -0.40876,-0.66138 -4.46999,-1.09102 -10.36317,-1.0963 -12.08431,-0.0108 -20.19098,-0.94514 -20.19098,-2.32703 0,-0.58143 3.375,-6.30911 7.5,-12.72818 4.125,-6.41908 7.5,-12.231779 7.5,-12.917118 0,-1.475879 -5.24971,-0.85761 -17.5,2.061008 -8.11306,1.93293 -13.5,2.44367 -13.5,1.27994 0,-0.35204 2.025,-6.460874 4.5,-13.575178 4.72438,-13.580062 5.19919,-15.784752 3.39951,-15.784752 -0.60526,0 -6.74484,2.7 -13.6435,6 -6.89866,3.3 -12.92844,6 -13.39951,6 -1.18694,0 -1.07003,-8.050505 0.2907,-20.016962 0.67616,-5.946273 0.7788,-10.437646 0.25,-10.938626 -0.50832,-0.481563 -5.79404,3.225572 -12.19478,8.552804 -6.21368,5.171531 -11.8876,9.402784 -12.60873,9.402784 -0.91335,0 -2.03664,-4.452943 -3.70242,-14.677108 -1.3152,-8.07241 -2.86795,-14.831304 -3.45056,-15.019765 -0.58261,-0.18846 -5.02611,5.085074 -9.87443,11.718965 -4.84833,6.633891 -9.29756,11.900815 -9.88718,11.704274 -0.58962,-0.19654 -3.60758,-6.402876 -6.70657,-13.791856 -3.09899,-7.388981 -6.19526,-13.43451 -6.8806,-13.43451 -0.68534,0 -3.40443,5.210644 -6.04241,11.579209 -6.6252,15.994386 -6.83333,16.3451 -8.75412,14.750987 -0.86082,-0.714416 -5.15653,-6.163606 -9.54603,-12.109311 -4.3895,-5.945705 -8.49131,-10.64066 -9.11514,-10.433234 -0.62995,0.209463 -2.08921,6.704772 -3.28218,14.609363 -1.18138,7.827723 -2.41955,14.503823 -2.75151,14.835778 -0.99435,0.994348 -4.68014,-1.459487 -12.60054,-8.388879 -13.78758,-12.062461 -14.44707,-12.027309 -13.04987,0.69558 1.90971,17.389793 1.98663,20.047545 0.59566,20.581308 -0.72679,0.278895 -6.76499,-2.221691 -13.41823,-5.556859 -11.4611,-5.745273 -15.10486,-7.023738 -15.1453,-5.313942 -0.01,0.4125 2.11162,6.91613 4.71416,14.45251 2.60254,7.536381 4.38099,14.05341 3.95212,14.48228 -0.42888,0.42888 -6.72787,-0.44975 -13.99777,-1.952506 -14.48094,-2.993347 -16.65077,-3.220331 -16.65077,-1.741826 0,0.544752 3.375,6.188702 7.5,12.542112 4.125,6.3534 7.5,12.14502 7.5,12.87025 0,1.6575 -7.17092,2.57681 -20.19098,2.58849 -5.33004,0.005 -9.93756,0.40765 -10.23892,0.89527 -0.30136,0.48761 4.46569,5.68401 10.59344,11.54754 7.28363,6.96956 10.80171,11.00063 10.16039,11.64195 -0.53954,0.53954 -4.32065,1.89248 -8.40246,3.00652 -15.61864,4.26278 -20.92147,6.00563 -20.92147,6.87615 0,0.49564 3.2625,2.70155 7.25,4.90202 13.75669,7.59151 12.76761,7.26443 15.67205,5.18259 1.41787,-1.0163 3.70295,-3.06129 5.07795,-4.54442 z m 116.32772,52.1375 c 6.21918,-2.59854 8.82323,-9.33419 6.2319,-16.11948 -1.32921,-3.48048 -2.56557,-4.82551 -5.93502,-6.45663 -5.26956,-2.55095 -6.71546,-2.56478 -11.52683,-0.1102 -8.8964,4.53861 -9.34294,16.88095 -0.79922,22.09036 3.76575,2.29612 7.51549,2.48189 12.02917,0.59595 z m -14.32772,9.24514 c -3.51581,-1.39459 -8.82894,-6.70968 -11.08763,-11.09173 -2.50192,-4.85393 -2.50966,-13.90488 -0.0165,-19.28984 3.6453,-7.87347 11.08629,-12.5 20.10414,-12.5 12.54847,0 21.92612,9.29405 21.97804,21.78212 0.0375,9.01634 -4.30692,16.25553 -12.1882,20.30946 -4.0851,2.10128 -14.39162,2.5346 -18.78984,0.78999 z m 13.92327,37.52954 c 8.37671,-7.04854 -1.68036,-19.10963 -10.28841,-12.33853 -5.69971,4.48339 -1.87824,14.76223 5.53841,14.89701 0.92031,0.0167 3.05781,-1.13459 4.75,-2.55848 z m -12.42327,10.2322 c -5.86793,-2.71551 -10.52257,-10.20574 -10.47804,-16.86119 0.0353,-5.27144 3.37778,-11.35651 7.87164,-14.3304 3.64903,-2.41482 4.75759,-2.64062 11.18196,-2.27761 6.98,0.39441 7.22319,0.50015 11.45774,4.98195 4.65442,4.9262 6.1445,9.41744 5.05364,15.23219 -0.76894,4.09882 -4.10988,9.20408 -7.8235,11.95502 -3.45878,2.56216 -12.98582,3.27961 -17.26344,1.30004 z m 114.36335,104.81583 c 10.227,-11.18997 21.60848,-30.86393 27.22645,-47.06351 5.19823,-14.98922 7.25863,-28.09743 7.21407,-45.89563 -0.0603,-24.08431 -4.08687,-41.09285 -14.93452,-63.08463 -16.34302,-33.13269 -46.45087,-59.24979 -81.71803,-70.88642 -15.43414,-5.09259 -16.44217,-5.20925 -17.64628,-2.0422 -0.55277,1.4539 -1.00504,3.01652 -1.00504,3.4725 0,0.45597 5.9625,2.71466 13.25,5.01931 35.76077,11.30924 63.64553,34.83748 80.02378,67.52144 10.22567,20.40604 13.92278,36.2862 13.96881,60 0.0662,34.11089 -9.34457,60.19434 -31.49722,87.29949 -5.77277,7.06334 -5.90867,7.36259 -4.20058,9.25 0.97085,1.07278 2.32529,1.95051 3.00986,1.95051 0.68456,0 3.52348,-2.49339 6.3087,-5.54086 z m -205.69209,3.88587 c 1.00581,-0.91024 1.82874,-2.07292 1.82874,-2.58373 0,-0.51082 -2.63201,-4.15357 -5.84891,-8.09502 -14.63358,-17.92951 -23.6031,-36.73187 -28.71576,-60.19538 -2.42673,-11.13698 -2.45896,-39.78834 -0.0573,-50.97088 4.2612,-19.84118 13.1935,-40.10618 24.05507,-54.57452 12.18896,-16.23652 30.18715,-31.27508 48.18988,-40.26551 7.30272,-3.64692 22.54194,-9.03747 28.94511,-10.23871 4.30443,-0.80752 5.21481,-2.57753 3.036,-5.9028 -1.958,-2.9883 -3.54655,-2.79413 -18.01964,2.20251 -21.27489,7.34487 -38.57605,18.19197 -54.61522,34.24145 -20.39953,20.41264 -32.7968,43.46168 -39.14531,72.77907 -2.80784,12.96658 -3.05515,38.46814 -0.50195,51.75851 3.58768,18.67525 11.52311,38.42277 21.37736,53.19814 5.83969,8.75598 15.31468,20.30186 16.66046,20.30186 0.54052,0 1.8057,-0.74474 2.81151,-1.65499 z m 63.83532,-15.91082 c 15.67138,-15.71119 30.21346,-29.94977 32.31572,-31.64129 l 3.8223,-3.07549 31.78931,31.73223 31.7893,31.73222 3.88839,-1.99361 c 2.13862,-1.09649 4.9045,-3.08274 6.1464,-4.4139 l 2.258,-2.42028 -38.00974,-37.92703 c -20.90536,-20.85987 -38.51355,-38.09524 -39.12932,-38.30081 -1.29795,-0.43333 -76.87694,74.79013 -76.87694,76.5153 0,1.40138 9.90102,8.26028 12.00658,8.31751 0.82862,0.0225 14.32862,-12.81365 30,-28.52485 z m 116.73476,34.94403 c 2.89226,-1.99198 5.25866,-3.93853 5.25866,-4.32568 0,-0.38715 -1.08902,-1.72699 -2.42004,-2.97742 l -2.42003,-2.2735 -5.54202,3.84919 c -3.04812,2.11705 -5.5591,4.26376 -5.57997,4.77045 -0.0538,1.30643 3.06103,4.57874 4.35839,4.57874 0.59749,0 3.45275,-1.6298 6.34501,-3.62178 z m -153.74134,-2.42161 c -1.375,-1.07766 -4.44655,-3.12269 -6.82568,-4.5445 -4.13205,-2.46941 -4.4118,-2.50717 -6.25,-0.84362 -3.05881,2.76819 -2.33103,4.21226 4.27459,8.48168 l 6.19892,4.00655 2.55108,-2.57036 2.55109,-2.57036 -2.5,-1.95939 z m 100.28084,25.57404 c 14.49567,-2.98776 28.71916,-8.12289 28.71916,-10.36853 0,-1.74786 -53.77251,-56.16212 -55.49976,-56.16212 -1.98511,0 -57.97468,56.92568 -56.97196,57.92449 3.0777,3.06569 28.15674,9.52931 44.47172,11.46169 7.53063,0.89195 28.49235,-0.63187 39.28084,-2.85553 z M 224.9987,293.20072 c 23.01944,-23.02077 42.83645,-42.37077 44.03779,-43 5.92891,-3.10537 5.18763,-3.71608 50.80424,41.85596 23.67313,23.65 43.55992,43 44.19287,43 1.9432,0 11.52658,-11.38528 17.16943,-20.39769 6.71527,-10.72521 12.42692,-23.8951 15.79143,-36.41178 3.52441,-13.11156 4.47549,-39.90506 1.90583,-53.69053 -5.8373,-31.31537 -23.37566,-60.16462 -47.7345,-78.51955 -14.94825,-11.26385 -26.56227,-17.02054 -45.2778,-22.44271 l -8.96423,-2.59707 -2.78905,2.06203 c -7.30846,5.40338 -10.29113,6.9611 -15.33301,8.00779 -9.08811,1.88669 -15.89094,-0.24766 -26.99841,-8.47059 -1.85434,-1.37278 -2.85156,-1.29243 -10.5,0.84604 -12.51114,3.49807 -21.4908,7.12277 -30.45106,12.29177 -33.29597,19.2078 -55.04883,49.48194 -62.91392,87.55925 -2.09944,10.16404 -2.14356,36.3479 -0.0794,47.13488 3.08197,16.10609 10.04627,33.16984 19.08974,46.77315 4.72103,7.10145 13.99627,17.85501 15.40042,17.85501 0.43787,0 19.63022,-18.83518 42.64966,-41.85596 z m 26.3145,116.39371 c -13.41757,-1.95334 -23.67774,-4.45026 -33.96097,-8.26475 -53.67022,-19.90862 -91.52045,-63.25337 -104.5902,-119.773 -2.57257,-11.12502 -2.77864,-13.60412 -2.82616,-34 -0.0452,-19.38999 0.22598,-23.29899 2.28561,-32.94931 5.42694,-25.42767 15.84433,-48.32494 30.78186,-67.65802 4.02331,-5.20722 5.35439,-7.66039 4.71044,-8.68127 -0.49368,-0.78264 -8.28662,-5.53788 -17.31765,-10.56719 -9.03104,-5.02932 -16.44793,-9.58799 -16.48198,-10.13039 -0.0524,-0.83409 14.13749,-5.27085 30.18808,-9.43895 2.3375,-0.60702 4.25,-1.58421 4.25,-2.17153 0,-0.58733 -5.92016,-6.76835 -13.15592,-13.73561 l -13.15592,-12.66773 11.40592,-0.61844 c 6.27326,-0.34014 14.66842,-0.67764 18.65592,-0.75 5.70792,-0.10358 7.25,-0.44951 7.25,-1.62637 0,-0.82215 -4.05,-7.72656 -9,-15.34315 -4.95,-7.616579 -9,-14.368915 -9,-15.005185 0,-1.519175 1.80635,-1.459466 9.29448,0.307227 17.46435,4.120404 25.84557,5.729198 26.48996,5.084808 0.39267,-0.392671 -1.92663,-8.348367 -5.15401,-17.679325 -3.22737,-9.330958 -5.58601,-17.247316 -5.24142,-17.591906 0.34459,-0.34459 7.84837,2.891627 16.67507,7.191593 9.41482,4.586473 16.41674,7.448713 16.93929,6.924435 0.521,-0.52272 0.50612,-4.837107 -0.0358,-10.393687 -1.90746,-19.556685 -2.2458,-25.99992 -1.36506,-25.995728 0.49364,0.0023 6.81731,4.952349 14.0526,11 12.6624,10.583917 14.67165,11.894136 15.69664,10.235664 0.25836,-0.418034 1.44038,-7.505534 2.62671,-15.75 2.41317,-16.770562 2.95493,-19.491433 3.87999,-19.486549 0.35287,0.0019 5.36659,6.51928 11.14159,14.483149 5.775,7.963868 10.95,14.338764 11.5,14.166436 1.36768,-0.428529 2.60055,-2.981854 9.14362,-18.936915 3.109,-7.581169 6.1149,-13.629885 6.67978,-13.44159 0.56488,0.188295 4.01645,7.516069 7.67014,16.283943 3.6537,8.767875 7.18786,15.94159 7.85369,15.94159 0.66584,0 5.8101,-6.283603 11.43169,-13.963562 5.62159,-7.679959 10.67108,-13.979959 11.22108,-14 0.55,-0.02004 2.1992,7.838562 3.6649,17.463562 1.46569,9.625 2.70319,17.6125 2.75,17.75 0.46648,1.370372 4.60065,-1.444814 15.80023,-10.759263 7.26832,-6.044905 13.51823,-10.990737 13.8887,-10.990737 0.37047,0 0.40295,3.9375 0.0722,8.75 -0.33077,4.8125 -0.90931,13.1375 -1.28563,18.5 -0.44057,6.277885 -0.3288,9.75 0.31386,9.75 0.54894,0 8.07894,-3.411119 16.73332,-7.580264 8.65439,-4.169145 16.00184,-7.313665 16.32769,-6.987822 0.32584,0.325842 -1.97234,8.092659 -5.10708,17.259592 -3.13473,9.166933 -5.32382,17.042839 -4.86465,17.502014 0.45917,0.459174 8.56474,-0.825257 18.01237,-2.854293 9.44763,-2.029036 17.46801,-3.398662 17.82306,-3.043613 0.35505,0.355049 -3.51161,6.971258 -8.59257,14.702686 -5.08097,7.73143 -9.45165,14.87369 -9.71263,15.87169 -0.43269,1.65461 0.6037,1.87253 11.75787,2.47228 6.72781,0.36175 15.12423,0.65773 18.65871,0.65773 3.53449,0 6.27634,0.41284 6.093,0.91741 -0.18333,0.50458 -5.95833,6.2343 -12.83333,12.73271 -6.875,6.49841 -12.64069,12.36064 -12.81265,13.02717 -0.17933,0.69511 1.52635,1.70496 4,2.3682 17.3265,4.64561 29.03181,7.97193 29.86472,8.48669 0.5393,0.33331 0.744,0.98877 0.45488,1.45657 -0.28912,0.46781 -7.9898,5.01287 -17.11264,10.10014 -9.12283,5.08727 -16.79973,9.80403 -17.05977,10.48169 -0.26004,0.67766 2.71613,5.43901 6.61372,10.58077 12.46431,16.4431 24.22171,42.46825 28.44385,62.9608 5.90375,28.65437 4.1256,60.51234 -4.87756,87.38785 -15.13556,45.18148 -50.99084,82.75639 -95.86343,100.46107 -23.96807,9.45671 -56.39879,13.25862 -81.69015,9.57668 z"
+       id="path2887"
+       style="fill:#120d0a" />
+  </g>
+</svg>
Index: /code/branches/RacingBots_FS18/contrib/winresource.rc
===================================================================
--- /code/branches/RacingBots_FS18/contrib/winresource.rc	(revision 11817)
+++ /code/branches/RacingBots_FS18/contrib/winresource.rc	(revision 11817)
@@ -0,0 +1,1 @@
+101 ICON orxonox.ico
Index: /code/branches/RacingBots_FS18/data/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/data/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,65 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Finds the external data directory and configures the data installation.
+ #    Default search paths are: ../../data and ../data_extern
+ #
+
+# For dev runs we've got two data directories. The one from the other repository root folder
+# is called EXTERNAL_DATA
+SET(DATA_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+SET(DATA_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
+
+# Specify data directory
+GET_FILENAME_COMPONENT(_search_path_1 ${CMAKE_SOURCE_DIR}/../data_extern ABSOLUTE)
+FIND_PATH(EXTERNAL_DATA_DIRECTORY resources.oxr
+  PATHS
+    ${CMAKE_SOURCE_DIR}/data_extern
+    ${_search_path_1}
+  NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH
+)
+
+IF(NOT EXTERNAL_DATA_DIRECTORY)
+  MESSAGE(STATUS "Warning: External data directory not found. If you want to compile while downloading the data files, you will have to recompile about four files afterwards and relink everything.")
+  MESSAGE(STATUS "You can specify your own folder with the EXTERNAL_DATA_DIRECTORY variable. Default location for the path is orxonox_root/data_extern")
+  # Temporary override to the default location.
+  SET(EXTERNAL_DATA_DIRECTORY ${CMAKE_SOURCE_DIR}/data_extern)
+ENDIF()
+
+
+################ Installation #################
+
+# Internal directory
+INSTALL(
+  DIRECTORY ${DATA_DIRECTORY}/
+  DESTINATION ${DATA_INSTALL_DIRECTORY}
+  REGEX "\\.svn$|_svn$|CMakeLists.txt|InstallScript.cmake" EXCLUDE
+)
+# External directory
+# User may want to install separately, ignore if not found.
+IF(EXISTS ${EXTERNAL_DATA_DIRECTORY})
+  INSTALL(
+    DIRECTORY ${EXTERNAL_DATA_DIRECTORY}/
+    DESTINATION ${DATA_INSTALL_DIRECTORY}
+    REGEX "\\.svn$|_svn$" EXCLUDE
+  )
+ENDIF()
Index: /code/branches/RacingBots_FS18/data/DefaultResources.oxr
===================================================================
--- /code/branches/RacingBots_FS18/data/DefaultResources.oxr	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/DefaultResources.oxr	(revision 11817)
@@ -0,0 +1,12 @@
+<ResourceCollection resourceGroup = "General" >
+    <ResourceLocation path = "levels" recursive=true/>
+    <ResourceLocation path = "lua" />
+    <ResourceLocation path = "overlays" />
+    <ResourceLocation path = "particle" />
+    <ResourceLocation path = "tcl" />
+
+    <ResourceLocation path = "gui/configs" />
+    <ResourceLocation path = "gui/layouts" />
+    <ResourceLocation path = "gui/schemes" />
+    <ResourceLocation path = "gui/scripts" />
+</ResourceCollection>
Index: /code/branches/RacingBots_FS18/data/defaultConfig/keybindings.ini
===================================================================
--- /code/branches/RacingBots_FS18/data/defaultConfig/keybindings.ini	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/defaultConfig/keybindings.ini	(revision 11817)
@@ -0,0 +1,171 @@
+[Keys]
+KeyA="scale -1 moveRightLeft"
+KeyABNT_C1=
+KeyABNT_C2=
+KeyAT=
+KeyAX=
+KeyApostrophe=
+KeyApps=
+KeyB =
+KeyBack=
+KeyBackslash=
+KeyC=switchCamera
+KeyCalculator=
+KeyCapsLock=
+KeyColon=
+KeyComma=
+KeyConvert=
+KeyD="scale 1 moveRightLeft"
+KeyDelete="scale 1 rotateRoll"
+KeyDivide=
+KeyDown="scale -1 moveFrontBack"
+KeyE="scale -1 rotateRoll"
+KeyEnd="boost"
+KeyEquals=
+KeyEscape="keyESC"
+KeyF="scale -1 moveUpDown"
+KeyF1="OverlayGroup toggleVisibility Debug"
+KeyF10=
+KeyF11=
+KeyF12=
+KeyF13=
+KeyF14=
+KeyF15=
+KeyF2="OverlayGroup toggleVisibility Stats"
+KeyF3="OrxonoxOverlay show QuestGUI"
+KeyF4="OrxonoxOverlay show PickupInventory"
+KeyF5="reloadLevel"
+KeyF6="startchat"
+KeyF7=
+KeyF8=
+KeyF9=
+KeyG=greet
+KeyGrave="InGameConsole openConsole"
+KeyH=
+KeyHome=
+KeyI=
+KeyInsert=
+KeyJ=
+KeyK=
+KeyKana=
+KeyKanji=
+KeyL=
+KeyLeft="scale -1 moveRightLeft"
+KeyLeftAlt=
+KeyLeftBracket=
+KeyLeftControl=mouseLook
+KeyLeftShif
+KeyLeftWindows=
+KeyLessThan=
+KeyM="WorldAmbientSound nextsong"
+KeyMail=
+KeyMediaSelect=
+KeyMediaStop=
+KeyMinus=
+KeyMultiply=
+KeyMute=
+KeyMyComputer=
+KeyN=
+KeyNextTrack=
+KeyNoConvert=
+KeyNumLock=
+KeyNumRow0=
+KeyNumRow1="toggleFormationFlight"
+KeyNumRow2="FFChangeMode"
+KeyNumRow3=
+KeyNumRow4=
+KeyNumRow5=
+KeyNumRow6=
+KeyNumRow7=
+KeyNumRow8=
+KeyNumRow9=
+KeyNumpad0=
+KeyNumpad1=
+KeyNumpad2=
+KeyNumpad3=
+KeyNumpad4=
+KeyNumpad5=
+KeyNumpad6=
+KeyNumpad7=
+KeyNumpad8=
+KeyNumpad9=
+KeyNumpadAdd=
+KeyNumpadComma=
+KeyNumpadEnter=
+KeyNumpadEquals=
+KeyNumpadPeriod=
+KeyNumpadSubtract=
+KeyO=
+KeyP=
+KeyPageDown="scale -1 rotateRoll"
+KeyPageUp=
+KeyPause=pause
+KeyPeriod=
+KeyPlayPause=
+KeyPower=
+KeyPreviousTrack=
+KeyQ="scale 1 rotateRoll"
+KeyR="scale 1 moveUpDown"
+KeyReturn=
+KeyRight="scale 1 moveRightLeft"
+KeyRightAlt=
+KeyRightBracket=
+KeyRightControl="scale -1 moveUpDown"
+KeyRightShift="scale 1 moveUpDown"
+KeyRightWindows=
+KeyS="scale -1 moveFrontBack"
+KeyScrollLock=
+KeySemicolon=
+KeySlash=
+KeySleep=
+KeySpace="boost"
+KeyStop=
+KeySystemRequest="printScreen"
+KeyT="onpress fire 3"
+KeyTab="NewHumanController changeMode"
+KeyU=""
+KeyUP="scale 1 moveFrontBack"
+KeyUnassigned="InGameConsole openConsole"
+KeyUnderline=
+KeyUnlabeled=
+KeyV=
+KeyVolumeDown=
+KeyVolumeUp=
+KeyW="scale 1 moveFrontBack"
+KeyWake=
+KeyWebBack=
+KeyWebFavorites=
+KeyWebForward=
+KeyWebHome=
+KeyWebRefresh=
+KeyWebSearch=
+KeyWebStop=
+KeyX="selectClosest"
+KeyY="onpress fire 4"
+KeyYen=
+KeyZ="selectNext"
+
+[MouseButtons]
+Button3=
+Button4=
+Button5=
+Button6=
+Button7=
+Left="fire 0"
+Middle="fire 2"
+Right= fire 1 | unfire
+Wheel1Down="NewHumanController decelerate"
+Wheel1Up="NewHumanController accelerate"
+Wheel2Down=
+Wheel2Up=
+
+[MouseAxes]
+MouseXNeg="scale 1 rotateYaw"
+MouseXPos="scale -1 rotateYaw"
+MouseYNeg="scale -1 rotatePitch"
+MouseYPos="scale 1 rotatePitch"
+XNeg="scale 1 rotateYaw"
+XPos="scale -1 rotateYaw"
+YNeg="scale -1 rotatePitch"
+YPos="scale 1 rotatePitch"
+
Index: /code/branches/RacingBots_FS18/data/defaultConfig/orxonox.ini
===================================================================
--- /code/branches/RacingBots_FS18/data/defaultConfig/orxonox.ini	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/defaultConfig/orxonox.ini	(revision 11817)
@@ -0,0 +1,10 @@
+[LevelManager]
+campaignMissions_[0] = "missionOne.oxw"
+campaignMissions_[1] = "fightInOurBack.oxw"
+campaignMissions_[2] = "pirateAttack.oxw"
+campaignMissions_[3] = "iJohnVane_TriptoArea51.oxw"
+campaignMissions_[4] = "iiJohnVane_Area51UnderFire.oxw"
+campaignMissions_[5] = "iiiJohnVane_EscapeTheBastards.oxw"
+campaignMissions_[6] = "expeditionSector.oxw"
+campaignMissions_[7] = "shuttleAttack.oxw"
+campaignMissions_[8] = "shuttleRetaliation.oxw"
Index: /code/branches/RacingBots_FS18/data/gui/configs/CEGUIConfig.xsd
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/configs/CEGUIConfig.xsd	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/configs/CEGUIConfig.xsd	(revision 11817)
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+
+    <xsd:element name="CEGUIConfig" type="CEGUIConfigType"/>
+
+    <xsd:simpleType name="LogLevel">
+        <xsd:restriction base="xsd:string">
+            <xsd:enumeration value="Errors"/>
+            <xsd:enumeration value="Standard"/>
+            <xsd:enumeration value="Informative"/>
+            <xsd:enumeration value="Insane"/>
+        </xsd:restriction>
+    </xsd:simpleType>
+
+    <xsd:complexType name="CEGUIConfigType">
+        <xsd:attribute name="Logfile" type="xsd:string" use="optional" default=""/>
+        <xsd:attribute name="Scheme" type="xsd:string" use="optional" default=""/>
+        <xsd:attribute name="DefaultFont" type="xsd:string" use="optional" default=""/>
+        <xsd:attribute name="Layout" type="xsd:string" use="optional" default=""/>
+        <xsd:attribute name="InitScript" type="xsd:string" use="optional" default=""/>
+        <xsd:attribute name="TerminateScript" type="xsd:string" use="optional" default=""/>
+        <xsd:attribute name="DefaultResourceGroup" type="xsd:string" use="optional"  default="" />
+        <xsd:attribute name="LoggingLevel" type="LogLevel" use="optional"  default="Standard" />
+    </xsd:complexType>
+
+</xsd:schema>
+
+
Index: /code/branches/RacingBots_FS18/data/gui/layouts/AudioMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/AudioMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/AudioMenu.layout	(revision 11817)
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/AudioBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/AudioWindow" >
+            <Property Name="Text" Value="Audio" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2,0},{0.2875,0},{0.8,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/MasterVolume" >
+                <Property Name="Text" Value="Master volume               " />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.041666,0},{0.15,0},{0.5625,0},{0.3525,0}}" />
+                <Window Type="MenuWidgets/HorizontalScrollbar" Name="orxonox/MasterScrollbar" >
+                    <Property Name="PageSize" Value="0" />
+                    <Property Name="StepSize" Value="1" />
+                    <Property Name="OverlapSize" Value="0" />
+                    <Property Name="DocumentSize" Value="1" />
+                    <Property Name="ScrollPosition" Value="0" />
+                    <Property Name="StepSize" Value="0.1" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.04,0},{0.6,0},{0.71,0},{0.8,0}}" />
+                    <Event Name="ThumbTrackStarted" Function="AudioMenu.AudioMasterScrollbar_started" />
+                    <Event Name="ThumbTrackEnded" Function="AudioMenu.AudioMasterScrollbar_ended" />
+                    <Event Name="ScrollPosChanged" Function="AudioMenu.AudioMasterScrollbar_changed" />
+                </Window>
+                <Window Type="MenuWidgets/Checkbox" Name="orxonox/MasterCheckbox" >
+                    <Property Name="Text" Value="Mute" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.775,0},{0.45,0},{0.96,0},{0.9,0}}" />
+                    <Event Name="CheckStateChanged" Function="AudioMenu.AudioMuteMasterCheckbox_clicked"/>
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/MusicVolume" >
+                <Property Name="Text" Value="Music volume               " />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.041666,0},{0.4335,0},{0.5625,0},{0.636,0}}" />
+                <Window Type="MenuWidgets/HorizontalScrollbar" Name="orxonox/MusicScrollbar" >
+                    <Property Name="PageSize" Value="0" />
+                    <Property Name="StepSize" Value="1" />
+                    <Property Name="OverlapSize" Value="0" />
+                    <Property Name="DocumentSize" Value="1" />
+                    <Property Name="ScrollPosition" Value="0" />
+                    <Property Name="StepSize" Value="0.1" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.04,0},{0.6,0},{0.71,0},{0.8,0}}" />
+                    <Event Name="ThumbTrackStarted" Function="AudioMenu.AudioMusicScrollbar_started" />
+                    <Event Name="ThumbTrackEnded" Function="AudioMenu.AudioMusicScrollbar_ended" />
+                    <Event Name="ScrollPosChanged" Function="AudioMenu.AudioMusicScrollbar_changed" />
+                </Window>
+                <Window Type="MenuWidgets/Checkbox" Name="orxonox/MusicCheckbox" >
+                    <Property Name="Text" Value="Mute" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.775,0},{0.45,0},{0.96,0},{0.9,0}}" />
+                    <Event Name="CheckStateChanged" Function="AudioMenu.AudioMuteMusicCheckbox_clicked"/>
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/EffectsVolume" >
+                <Property Name="Text" Value="Effects volume               " />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.041666,0},{0.717,0},{0.5625,0},{0.9195,0}}" />
+                <Window Type="MenuWidgets/HorizontalScrollbar" Name="orxonox/EffectsScrollbar" >
+                    <Property Name="PageSize" Value="0" />
+                    <Property Name="StepSize" Value="1" />
+                    <Property Name="OverlapSize" Value="0" />
+                    <Property Name="DocumentSize" Value="1" />
+                    <Property Name="ScrollPosition" Value="0" />
+                    <Property Name="StepSize" Value="0.1" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.04,0},{0.6,0},{0.71,0},{0.8,0}}" />
+                    <Event Name="ThumbTrackStarted" Function="AudioMenu.AudioEffectsScrollbar_started" />
+                    <Event Name="ThumbTrackEnded" Function="AudioMenu.AudioEffectsScrollbar_ended" />
+                    <Event Name="ScrollPosChanged" Function="AudioMenu.AudioEffectsScrollbar_changed" />
+                </Window>
+                <Window Type="MenuWidgets/Checkbox" Name="orxonox/EffectsCheckbox" >
+                    <Property Name="Text" Value="Mute" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.775,0},{0.45,0},{0.96,0},{0.9,0}}" />
+                    <Event Name="CheckStateChanged" Function="AudioMenu.AudioMuteEffectsCheckbox_clicked"/>
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/AudioTheme" >
+                <Property Name="Text" Value="Theme" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.604166,0},{0.15,0},{0.958333,0},{0.636,0}}" />
+                <Window Type="MenuWidgets/Listbox" Name="orxonox/AudioThemeListbox" >
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.225,0},{0.95,0},{0.92,0}}" />
+                    <Event Name="ItemSelectionChanged" Function="AudioMenu.AudioThemeListbox_changed" />
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/AudioInfo" >
+                <Property Name="Text" >Theme changes might take
+up to a minute.</Property>
+                <Property Name="TextColours" Value="FFFFFFFF" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.604166,0},{0.717,0},{0.958333,0},{0.9195,0}}" />
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/AudioBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="AudioMenu.AudioBackButton_clicked" />
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/CampaignMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/CampaignMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/CampaignMenu.layout	(revision 11817)
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/CampaignBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1.0,0},{1.0,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+
+        <!-- Misson 1************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission1Text" >
+            <Property Name="Text" Value="Mission One" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.6,0},{0.3,0},{0.65,0}}" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission1Button_clicked"/>
+        </Window>
+
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission1Button" >
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.75,0},{0.25,0},{0.95,0}}" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission1Button_clicked"/>
+        </Window>
+
+        <!-- Misson 2************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission2Text" >
+            <Property Name="Text" Value="Fight in our Back" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.35,0},{0.6,0},{0.55,0},{0.65,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission2Button_clicked"/>
+        </Window>
+
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission2Button" >
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.7,0},{0.5,0},{0.85,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission2Button_clicked"/>
+        </Window>
+
+        <!-- Misson 3************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission3Text" >
+            <Property Name="Text" Value="Pirate Attack" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.75,0},{0.8,0},{0.8,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission3Button_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission3Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.685,0},{0.605,0},{0.75,0},{0.71,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission3Button_clicked"/>
+        </Window>
+
+        <!-- Misson 4************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission4Text" >
+            <Property Name="Text" Value="Trip to Area 51" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.575,0},{0.5,0},{0.775,0},{0.55,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission4Button_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission4Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.78,0},{0.48,0},{0.87,0},{0.59,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission4Button_clicked"/>
+        </Window>
+
+        <!-- Misson 5************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission5Text" >
+            <Property Name="Text" Value="Area 51 under Fire" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.625,0},{0.4,0},{0.825,0},{0.45,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission5Button_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission5Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.725,0},{0.27,0},{0.775,0},{0.37,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission5Button_clicked"/>
+        </Window>
+
+        <!-- Misson 6************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission6Text" >
+            <Property Name="Text" Value="Escape the Bastards" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.525,0},{0.1,0},{0.725,0},{0.15,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission6Button_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission6Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.17,0},{0.65,0},{0.27,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission6Button_clicked"/>
+        </Window>
+
+        <!-- Misson 7************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission7Text" >
+            <Property Name="Text" Value="Expedition to Sector 5C" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission7Button_clicked"/>
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.025,0},{0.6,0},{0.075,0}}" />
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission7Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.47,0},{0.13,0},{0.525,0},{0.23,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission7Button_clicked"/>
+        </Window>
+
+        <!-- Misson 8************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission8Text" >
+            <Property Name="Text" Value="Shuttle under Attack" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="Disabled" Value="True" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2,0},{0.45,0},{0.25,0}}" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission8Button_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission8Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.33,0},{0.1,0},{0.38,0},{0.18,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission8Button_clicked"/>
+        </Window>
+
+        <!-- Misson 9************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/Mission9Text" >
+            <Property Name="Text" Value="Retaliation" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="Disabled" Value="True" />
+            <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.145,0},{0.3,0},{0.195,0}}" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission9Button_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/JuuButton" Name="orxonox/Mission9Button" >
+
+            <Property Name="Visible" Value="False"/>
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.18,0},{0.07,0},{0.24,0},{0.145,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="CampaignMenu.Mission9Button_clicked"/>
+        </Window>
+
+        <!-- Back Button************************************* -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/CampaignMenuBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.75,0},{0.9,0},{0.95,0},{0.95,0}}" />
+            <Event Name="Clicked" Function="CampaignMenu.CampaignMenuBackButton_clicked"/> 
+        </Window>
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/CampaignMenuCongratulation" >
+            <Property Name="Text" Value="Campaign Completed!!!" />
+            <Property Name="Visible" Value="False"/>
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedMaxSize" Value="{{2,1},{2,1}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.15,0},{0.6,0},{0.2,0}}" />
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/ChatBox-inputonly.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/ChatBox-inputonly.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/ChatBox-inputonly.layout	(revision 11817)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/ChatBox-inputonly/Root" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/Editbox" Name="orxonox/ChatBox-inputonly/input" >
+            <Property Name="Text" Value="" />
+            <Property Name="Font" Value="Monofur-10" />
+            <Property Name="AlwaysOnTop" Value="True" />
+            <Property Name="MaxTextLength" Value="12981298" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.02,0},{0,5},{0.98,0},{0,30}}" />
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/ChatBox.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/ChatBox.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/ChatBox.layout	(revision 11817)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/ChatBox/Root" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/FrameWindow" Name="orxonox/ChatBox" >
+            <Property Name="Text" Value="Chat" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="TitlebarEnabled" Value="True" />
+            <!--<Property Name="UnifiedAreaRect" Value="{{0.01,0},{0.03,0},{0.6,0},{0.69375,0}}" />-->
+            <Property Name="UnifiedAreaRect" Value="{{0.35,0},{0.10,0},{0.98,0},{0.65,0}}" />
+            <Event Name="CloseClicked" Function="ChatBox.ChatBoxCloseButton_clicked"/>
+            <Window Type="MenuWidgets/Listbox" Name="orxonox/ChatBox/history" >
+                <Property Name="Font" Value="Monofur-10" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.02,0},{0.078,0},{0.98,0},{1,-30}}" />
+            </Window>
+            <Window Type="MenuWidgets/Editbox" Name="orxonox/ChatBox/input" >
+                <Property Name="Text" Value="" />
+                <Property Name="Font" Value="Monofur-10" />
+                <Property Name="MaxTextLength" Value="1073741823" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.02,0},{1,-30},{0.98,0},{1,-5}}" />
+            </Window>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/ControlsMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/ControlsMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/ControlsMenu.layout	(revision 11817)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/ControlsBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/ControlsWindow" >
+            <Property Name="Text" Value="Controls" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.3625,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/Button" Name="orxonox/MouseControlsButton" >
+                <Property Name="Text" Value="Mouse controls" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.3,0},{0.318181,0},{0.7,0},{0.5,0}}" />
+                <Event Name="Clicked" Function="ControlsMenu.ControlsMouseControlsButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/KeybindingsButton" >
+                <Property Name="Text" Value="Keybindings" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.3,0},{0.590909,0},{0.7,0},{0.772727,0}}" />
+                <Event Name="Clicked" Function="ControlsMenu.ControlsKeyboardControlsButton_clicked"/>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/ControlsBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="ControlsMenu.ControlsBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/CreditsMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/CreditsMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/CreditsMenu.layout	(revision 11817)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/CreditsMenu/Background" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/CreditsWindow" >
+            <Property Name="Text" Value="Credits" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.2125,0},{0.85,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/CreditsMenuWrapper" >
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/CreditsMenuPane" >
+                    <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                    <Property Name="HorzStepSize" Value="0.005" />
+                    <Property Name="VertStepSize" Value="0.005" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="HorzOverlapSize" Value="0.01" />
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{0.997,0},{0.997,0}}" />
+                    <Property Name="VertOverlapSize" Value="0.01" />
+                    <Property Name="HorzScrollPosition" Value="0" />
+                    <Property Name="VertScrollPosition" Value="0" />
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/CreditsText" >
+                        <Property Name="TextColours" Value="FFFFFFFF" />
+                        <Property Name="InheritsAlpha" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="VertFormatting" Value="TopAligned" />
+                        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                        <Property Name="Text">Orxonox version 0.0.3
+    
+    Programming Language:  C++ - lua - tcl
+    Environment:  OpenAL - Ogre - OIS - CEGUI - enet - ODE
+    Licence:  GNU General Public Licence - Creative Commons
+    
+    http://www.orxonox.net
+    
+    Credits:
+    http://www.orxonox.net/wiki/credits
+
+    Thanks to AMIV:
+    https://www.amiv.ethz.ch/
+                      </Property>
+                    </Window>
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/CreditsBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="CreditsMenu.CreditsBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/DecisionPopup.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/DecisionPopup.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/DecisionPopup.layout	(revision 11817)
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/DecisionPopup_RootWindow" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticImage" Name="orxonox/DecisionPopup_Background" >
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+            <Property Name="Alpha" Value="0.6" />
+            <Window Type="MenuWidgets/Button" Name="orxonox/DecisionPopup_button_yes" >
+                <Property Name="Text" Value="Yes" />
+                <Property Name="Alpha" Value="0.7" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.5625,0},{0.4875,0},{0.6125,0}}" />
+                <Event Name="Clicked" Function="DecisionPopup.button_yes"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/DecisionPopup_button_no" >
+                <Property Name="Text" Value="No" />
+                <Property Name="Alpha" Value="0.8" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.5625,0},{0.7125,0},{0.6125,0}}" />
+                <Event Name="Clicked" Function="DecisionPopup.button_no"/>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/DecisionPopup_text" >
+                <Property Name="Text" Value="Template text" />
+                <Property Name="HorzFormatting" Value="WordWrapCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.4375,0},{0.75,0},{0.5375,0}}" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="Alpha" Value="0.8" />
+            </Window>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/Dialog.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/Dialog.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/Dialog.layout	(revision 11817)
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/Dialog/Background" > 
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/Dialog/Options" >
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.15,0},{0.85,0},{0.8,0}}" />
+
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/Dialog/Person" >
+                <Property Name="Alpha" Value="0.8" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="LeftAligned" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="CentreAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.05,0},{0.25,0},{0.15,0}}" />
+            </Window>
+
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestionWrapper" >
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.3,0},{0.05,0},{0.95,0},{0.45,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/QuestionPane" >
+                        <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                        <Property Name="HorzStepSize" Value="0.005" />
+                        <Property Name="VertStepSize" Value="0.005" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="HorzOverlapSize" Value="0.01" />
+                        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{0.997,0},{0.997,0}}" />
+                        <Property Name="VertOverlapSize" Value="0.01" />
+                        <Property Name="HorzScrollPosition" Value="0" />
+                        <Property Name="VertScrollPosition" Value="0" />
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Dialog/Question" >
+                            <Property Name="Alpha" Value="0.8" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Property Name="HorzFormatting" Value="WordWrapLeftAligned" />
+                            <Property Name="VertFormatting" Value="CentreAligned" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                        </Window>
+                </Window>
+            </Window>
+
+            <Window Type="MenuWidgets/Listbox" Name="orxonox/AnsListbox" >
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.5,0},{0.95,0},{0.85,0}}" />
+                <Event Name="ItemSelectionChanged" Function="Dialog.answer_changed" />
+            </Window>
+        
+            <Window Type="MenuWidgets/Button" Name="orxonox/SayButton" >
+                <Property Name="Text" Value="Say" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.425,0},{0.9,0},{0.575,0},{0.975,0}}" />
+                <Event Name="Clicked" Function="Dialog.Button_clicked"/>
+            </Window>
+        </Window>
+         
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/DockingDialog.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/DockingDialog.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/DockingDialog.layout	(revision 11817)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/Docking/Background" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/Docking/Title" >
+            <Property Name="Text" Value="Docking" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.7,0}}" />
+            <Window Type="MenuWidgets/Listbox" Name="orxonox/Docking/Docks" >
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.85,0}}" />
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/Docking/DockButton" >
+            <Property Name="Text" Value="Dock" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.725,0},{0.4875,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="DockingDialog.dockButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/Docking/CancelButton" >
+            <Property Name="Text" Value="Cancel" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.725,0},{0.7125,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="DockingDialog.cancelButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/GUILayout.xsd
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/GUILayout.xsd	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/GUILayout.xsd	(revision 11817)
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+
+    <xsd:element name="GUILayout" type="GUILayoutType"/>
+
+    <xsd:complexType name="GUILayoutType">
+        <xsd:sequence>
+            <xsd:element name="Window" type="WindowType" />
+        </xsd:sequence>
+        <xsd:attribute name="Parent" type="xsd:string" use="optional" default=""/>
+    </xsd:complexType>
+
+    <xsd:complexType name="WindowType">
+        <xsd:sequence>
+            <xsd:element name="LayoutImport" type="LayoutImportType"  minOccurs="0" maxOccurs="unbounded" />
+            <xsd:element name="Property" type="PropertyType"  minOccurs="0" maxOccurs="unbounded" />
+            <xsd:element name="Event" type="EventType"  minOccurs="0" maxOccurs="unbounded" />
+            <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                <xsd:element name="Window" type="WindowType" />
+                <xsd:element name="AutoWindow" type="AutoWindowType" />
+            </xsd:choice>
+            <xsd:element name="Property" type="PropertyType"  minOccurs="0" maxOccurs="unbounded" />
+        </xsd:sequence>
+        <xsd:attribute name="Type" type="xsd:string" use="required"/>
+        <xsd:attribute name="Name" type="xsd:string" use="optional" default="" />
+    </xsd:complexType>
+
+    <xsd:complexType name="AutoWindowType">
+        <xsd:sequence>
+            <xsd:element name="LayoutImport" type="LayoutImportType"  minOccurs="0" maxOccurs="unbounded" />
+            <xsd:element name="Property" type="PropertyType"  minOccurs="0" maxOccurs="unbounded" />
+            <xsd:element name="Event" type="EventType"  minOccurs="0" maxOccurs="unbounded" />
+            <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                <xsd:element name="Window" type="WindowType" />
+                <xsd:element name="AutoWindow" type="AutoWindowType" />
+            </xsd:choice>
+            <xsd:element name="Property" type="PropertyType"  minOccurs="0" maxOccurs="unbounded" />
+        </xsd:sequence>
+        <xsd:attribute name="NameSuffix" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="PropertyType">
+        <xsd:simpleContent>
+            <xsd:extension base="xsd:string">
+                <xsd:attribute name="Name" type="xsd:string" use="required"/>
+                <xsd:attribute name="Value" type="xsd:string" use="optional"/>
+            </xsd:extension>
+        </xsd:simpleContent>
+    </xsd:complexType>
+
+    <xsd:complexType name="LayoutImportType">
+        <xsd:attribute name="Filename" type="xsd:string" use="required"/>
+        <xsd:attribute name="Prefix" type="xsd:string" use="optional" default="" />
+        <xsd:attribute name="ResourceGroup" type="xsd:string" use="optional"  default="" />
+    </xsd:complexType>
+
+    <xsd:complexType name="EventType">
+        <xsd:attribute name="Name" type="xsd:string" use="required"/>
+        <xsd:attribute name="Function" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+</xsd:schema>
+
Index: /code/branches/RacingBots_FS18/data/gui/layouts/GameplayMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/GameplayMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/GameplayMenu.layout	(revision 11817)
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/GameplayBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/GameplayWindow" >
+            <Property Name="Text" Value="Gameplay" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.3625,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/Difficulty" >
+                <Property Name="Text" Value="Difficulty" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.2,0},{0.475,0},{0.9,0}}" />
+                <Window Type="MenuWidgets/RadioButton" Name="orxonox/DifficultyEasyButton" >
+                    <Property Name="Text" Value="Easy" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.325,0},{0.325,0},{0.675,0},{0.45,0}}" />
+                    <Event Name="SelectStateChanged" Function="GameplayMenu.GameplayDifficultyEasyButton_clicked"/>
+                </Window>
+                <Window Type="MenuWidgets/RadioButton" Name="orxonox/DifficultyNormalButton" >
+                    <Property Name="Text" Value="Normal" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.325,0},{0.525,0},{0.675,0},{0.65,0}}" />
+                    <Event Name="SelectStateChanged" Function="GameplayMenu.GameplayDifficultyNormalButton_clicked"/>
+                </Window>
+                <Window Type="MenuWidgets/RadioButton" Name="orxonox/DifficultyHardButton" >
+                    <Property Name="Text" Value="Hard" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.325,0},{0.725,0},{0.675,0},{0.85,0}}" />
+                    <Event Name="SelectStateChanged" Function="GameplayMenu.GameplayDifficultyHardButton_clicked"/>
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/Theme" >
+                <Property Name="Text" Value="Theme" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.525,0},{0.2,0},{0.95,0},{0.9,0}}" />
+                <Window Type="MenuWidgets/Combobox" Name="orxonox/ThemeCombobox" >
+                    <Property Name="AlwaysOnTop" Value="True" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.21,0},{0.95,0},{0.9,0}}" />
+                    <Property Name="MaxEditTextLength" Value="1073741823" />
+                    <Property Name="ReadOnly" Value="True" />
+                    <Event Name="ListSelectionAccepted" Function="GameplayMenu.GameplayThemeCombobox_changed" />
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/GameplayBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="GameplayMenu.GameplayBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/GraphicsMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/GraphicsMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/GraphicsMenu.layout	(revision 11817)
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/GraphicsBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/GraphicsWindow" >
+            <Property Name="Text" Value="Graphics" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.15,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/TabControl" Name="orxonox/GraphicsTabControl" >
+                <Property Name="TabHeight" Value="{0,26.4388}" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="TabPanePosition" Value="Top" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.1,0},{0.95,0},{0.925,0}}" />
+                <Window Type="DefaultWindow" Name="orxonox/Display" >
+                    <Property Name="Text" Value="Display" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Resolution" >
+                        <Property Name="Text" Value="Resolution" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="VertFormatting" Value="TopAligned" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.025,0},{0.035,0},{0.4875,0},{0.96,0}}" />
+                        <Window Type="MenuWidgets/Checkbox" Name="orxonox/Display/Resolution/Fullscreen" >
+                            <Property Name="Text" Value="Fullscreen" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.27,0}}" />
+                            <Event Name="CheckStateChanged" Function="GraphicsMenu.callback_FullscreenCheckbox_CheckStateChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/Combobox" Name="orxonox/Display/Resolution/Combobox" >
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="ClippedByParent" Value="False" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.3,0},{0.95,0},{1.2,0}}" />
+                            <Property Name="MaxEditTextLength" Value="1073741823" />
+                            <Event Name="ListSelectionAccepted" Function="GraphicsMenu.callback_ResolutionCombobox_ListSelectionAccepted" />
+                        </Window>
+                        <Window Type="MenuWidgets/Editbox" Name="orxonox/Display/Resolution/EditboxWidth" >
+                            <Property Name="MaxTextLength" Value="1073741823" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.45,0},{0.45,0},{0.57,0}}" />
+                            <Event Name="TextChanged" Function="GraphicsMenu.callback_ResolutionEditboxWidth_TextChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/Editbox" Name="orxonox/Display/Resolution/EditboxHeight" >
+                            <Property Name="MaxTextLength" Value="1073741823" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.45,0},{0.95,0},{0.57,0}}" />
+                            <Event Name="TextChanged" Function="GraphicsMenu.callback_ResolutionEditboxHeight_TextChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Resolution/x" >
+                            <Property Name="Text" Value="x" />
+                            <Property Name="FrameEnabled" Value="False" />
+                            <Property Name="HorzFormatting" Value="HorzCentred" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.45,0},{0.45,0},{0.55,0},{0.57,0}}" />
+                            <Property Name="BackgroundEnabled" Value="False" />
+                        </Window>
+                        <Window Type="MenuWidgets/Button" Name="orxonox/Display/Resolution/Apply" >
+                            <Property Name="Text" Value="Apply" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.61,0},{0.75,0},{0.73,0}}" />
+                            <Event Name="Clicked" Function="GraphicsMenu.callback_Apply_Clicked" />
+                        </Window>
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Resolution/AspectRatioLabel" >
+                            <Property Name="Text" Value="Aspect Ratio" />
+                            <Property Name="FrameEnabled" Value="False" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.825,0},{0.6,0},{0.95,0}}" />
+                            <Property Name="BackgroundEnabled" Value="False" />
+                        </Window>
+                        <Window Type="MenuWidgets/Editbox" Name="orxonox/Display/Resolution/AspectRatio" >
+                            <Property Name="Text" Value="1" />
+                            <Property Name="MaxTextLength" Value="1073741823" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.65,0},{0.825,0},{0.95,0},{0.95,0}}" />
+                        </Window>
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Theme" >
+                        <Property Name="Text" Value="Theme" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="VertFormatting" Value="TopAligned" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.035,0},{0.975,0},{0.32,0}}" />
+                        <Window Type="MenuWidgets/Combobox" Name="orxonox/Display/Theme/Combobox" >
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="ClippedByParent" Value="False" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.5,0},{0.95,0},{1.6,0}}" />
+                            <Property Name="MaxEditTextLength" Value="1073741823" />
+                            <Event Name="ListSelectionAccepted" Function="GraphicsMenu.callback_ThemeCombobox_ListSelectionAccepted" />
+                        </Window>
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/More" >
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.37,0},{0.975,0},{0.7,0}}" />
+                        <Window Type="MenuWidgets/Checkbox" Name="orxonox/Display/More/VSync" >
+                            <Property Name="Text" Value="VSync" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.1,0},{0.95,0},{0.45,0}}" />
+                            <Event Name="CheckStateChanged" Function="GraphicsMenu.callback_VSyncCheckbox_CheckStateChanged" />
+                        </Window>
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/More/FSAALabel" >
+                            <Property Name="Text" Value="FSAA" />
+                            <Property Name="FrameEnabled" Value="False" />
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.55,0},{0.3,0},{0.9,0}}" />
+                            <Property Name="BackgroundEnabled" Value="False" />
+                        </Window>
+                        <Window Type="MenuWidgets/Combobox" Name="orxonox/Display/More/FSAA" >
+                            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                            <Property Name="ClippedByParent" Value="False" />
+                            <Property Name="UnifiedAreaRect" Value="{{0.3,0},{0.55,0},{0.95,0},{2.1,0}}" />
+                            <Property Name="MaxEditTextLength" Value="1073741823" />
+                            <Event Name="ListSelectionAccepted" Function="GraphicsMenu.callback_FSAACombobox_ListSelectionAccepted" />
+                        </Window>
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/Notice" >
+                        <Property Name="Font" Value="BlueHighway-12" />
+                        <Property Name="Text" >Changing the theme, FSAA,
+or VSync requires a restart</Property>
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.75,0},{0.975,0},{0.96,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Display/NoticeRed" >
+                        <Property Name="Font" Value="BlueHighway-12" />
+                        <Property Name="Text" >Restart required</Property>
+                        <Property Name="TextColours" Value="tl:FFFF0000 tr:FFFF8888 bl:FFFF8888 br:FFFFFFFF" />
+                        <Property Name="HorzFormatting" Value="HorzCentred" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.75,0},{0.975,0},{0.96,0}}" />
+                    </Window>
+                </Window>
+                <Window Type="DefaultWindow" Name="orxonox/Settings" >
+                    <Property Name="Text" Value="Settings" />
+                    <Property Name="Visible" Value="False" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Settings/FovLabel" >
+                        <Property Name="Text" Value="Vertical field of view (FOV)" />
+                        <Property Name="FrameEnabled" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.05,0},{0.5,0},{0.12,0}}" />
+                        <Property Name="BackgroundEnabled" Value="False" />
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Settings/FpsLimitLabel" >
+                        <Property Name="Text" Value="Maximal frame rate" />
+                        <Property Name="FrameEnabled" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.18,0},{0.5,0},{0.25,0}}" />
+                        <Property Name="BackgroundEnabled" Value="False" />
+                    </Window>
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/Settings/ParticleLodLabel" >
+                        <Property Name="Text" Value="Particle detail level" />
+                        <Property Name="FrameEnabled" Value="False" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.31,0},{0.5,0},{0.38,0}}" />
+                        <Property Name="BackgroundEnabled" Value="False" />
+                    </Window>
+                    <Window Type="MenuWidgets/Editbox" Name="orxonox/Settings/Fov" >
+                        <Property Name="MaxTextLength" Value="1073741823" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.03,0},{0.65,0},{0.14,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/Editbox" Name="orxonox/Settings/FpsLimit" >
+                        <Property Name="MaxTextLength" Value="1073741823" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.16,0},{0.65,0},{0.27,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/Combobox" Name="orxonox/Settings/ParticleLodCombobox" >
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="ClippedByParent" Value="False" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.29,0},{0.7,0},{0.725,0}}" />
+                        <Property Name="MaxEditTextLength" Value="1073741823" />
+                    </Window>
+                    <Window Type="MenuWidgets/Checkbox" Name="orxonox/Settings/MeshLodCheckbox" >
+                        <Property Name="Text" Value="Enable mesh LOD" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.44,0},{0.5,0},{0.51,0}}" />
+                    </Window>
+                    <Window Type="MenuWidgets/Checkbox" Name="orxonox/Settings/MotionBlurCheckbox" >
+                        <Property Name="Text" Value="Enable motion blur" />
+                        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                        <Property Name="UnifiedAreaRect" Value="{{0.035,0},{0.57,0},{0.5,0},{0.64,0}}" />
+                    </Window>
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/GraphicsOkButton" >
+            <Property Name="Text" Value="OK" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.6625,0},{0.4875,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="GraphicsMenu.callback_Ok_Clicked" />
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/GraphicsCancelButton" >
+            <Property Name="Text" Value="Cancel" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.6625,0},{0.7125,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="GraphicsMenu.callback_Cancel_Clicked" />
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/HighscoreMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/HighscoreMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/HighscoreMenu.layout	(revision 11817)
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/HighscoreMenu/Background" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/HighscoreWindow" >
+            <Property Name="Text" Value="Highscore" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.1,0},{0.85,0},{0.85,0}}" />
+            <Window Type="MenuWidgets/TabControl" Name="orxonox/HighscoreTabControl" >
+                <Property Name="TabHeight" Value="{0,30}" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="TabPanePosition" Value="Top" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.105,0},{0.95,0},{0.99,0}}" />
+            </Window>
+            <!--<Window Type="MenuWidgets/StaticText" Name="orxonox/HighscoreMenuWrapper" >
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/HighscoreMenuPane" >
+                    <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                    <Property Name="HorzStepSize" Value="0.005" />
+                    <Property Name="VertStepSize" Value="0.005" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="HorzOverlapSize" Value="0.01" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.005,0},{0.01,0},{0.995,0},{0.99,0}}" />
+                    <Property Name="VertOverlapSize" Value="0.01" />
+                    <Property Name="HorzScrollPosition" Value="0" />
+                    <Property Name="VertScrollPosition" Value="0" />
+                </Window>
+            
+            </Window>
+            -->
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/HighscoreBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.8625,0},{0.6,0},{0.9125,0}}" />
+            <Event Name="Clicked" Function="HighscoreMenu.HighscoreBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/HostMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/HostMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/HostMenu.layout	(revision 11817)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/HostMenuBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/HostMenuWindow" >
+            <Property Name="Text" Value="Multiplayer" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.7,0}}" />
+            <Window Type="MenuWidgets/Listbox" Name="orxonox/HostMenuListbox" >
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.85,0}}" />
+            </Window>
+            <Window Type="MenuWidgets/RadioButton" Name="orxonox/HostMenuHostButton" >
+                <Property Name="Text" Value="Build Server"/>
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.87,0},{0.3,0},{0.97,0}}" />
+                <Event Name="SelectStateChanged" Function="HostMenu.HostMenuBuildServerButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/RadioButton" Name="orxonox/HostMenuDedicatedButton" >
+                <Property Name="Text" Value="Dedicated" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0.87,0},{0.7,0},{0.97,0}}" />
+                <Event Name="SelectStateChanged" Function="HostMenu.HostMenuDedicatedButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Checkbox" Name="orxonox/MultiplayerShowAllCheckbox" >
+                <Property Name="Text" Value="show all" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.8,0},{0.87,0},{1,0},{.97,0}}" />
+                <Event Name="CheckStateChanged" Function="HostMenu.MultiplayerShowAll_clicked"/>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/HostMenuStartButton" >
+            <Property Name="Text" Value="Start" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.725,0},{0.4875,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="HostMenu.HostMenuStartButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/HostMenuBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.725,0},{0.7125,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="HostMenu.HostMenuBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
+
Index: /code/branches/RacingBots_FS18/data/gui/layouts/InGameMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/InGameMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/InGameMenu.layout	(revision 11817)
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/InGameMenu_RootWindow" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/Button" Name="orxonox/InGameMenu_ReturnButton" >
+            <Property Name="Text" Value="Return to Game" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.2875,0},{0.6,0},{0.3375,0}}" />
+            <Property Name="Alpha" Value="0.9" />
+            <Event Name="Clicked" Function="InGameMenu.button_return_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/InGameMenu_ReloadLevelButton" >
+            <Property Name="Text" Value="Reload level" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.3625,0},{0.6,0},{0.4125,0}}" />
+            <Property Name="Alpha" Value="0.9" />
+            <Event Name="Clicked" Function="InGameMenu.button_reloadLevel_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/InGameMenu_MainMenuButton" >
+            <Property Name="Text" Value="Main Menu" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.4375,0},{0.6,0},{0.4875,0}}" />
+            <Property Name="Alpha" Value="0.9" />
+            <Event Name="Clicked" Function="InGameMenu.button_mainmenu_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/InGameMenu_SettingsButton" >
+            <Property Name="Text" Value="Settings" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.5125,0},{0.6,0},{0.5625,0}}" />
+            <Property Name="Alpha" Value="0.9" />
+            <Event Name="Clicked" Function="InGameMenu.button_settings_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/InGameMenu_QuitButton" >
+            <Property Name="Text" Value="Quit" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.5875,0},{0.6,0},{0.6375,0}}" />
+            <Property Name="Alpha" Value="0.9" />
+            <Event Name="Clicked" Function="InGameMenu.button_quit_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/InGamePickupHUD.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/InGamePickupHUD.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/InGamePickupHUD.layout	(revision 11817)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout>
+    <Window Type="DefaultWindow" Name="orxonox/InGamePickupHUD_RootWindow" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="TaharezLook/StaticImage" Name="orxonox/InGamePickupHUD_Overview" >
+            <Property Name="Font" Value="BlueHighway-12" />
+            <Property Name="Text" Value="Pickup List" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0,5},{0.15,0},{0.2,0},{0.45,0}}" />
+            <Property Name="Alpha" Value="0.3" />
+            <!--Event Name="Clicked" Function="InGameMenu.button_return_clicked"/-->
+            <Window Type="TaharezLook/StaticText" Name="orxonox/InGamePickupHUD_PickupTitle" >
+                <Property Name="Alpha" Value="0.8"/>
+                <Property Name="Text" Value="Pickup List" />
+                <Property Name="Font" Value="BlueHighway-10" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,-20},{0,20}}" />
+            </Window>
+            <Window Type="TaharezLook/Button" Name="orxonox/InGamePickupHUD_closeButton" >
+                <Property Name="Alpha" Value="0.8" />
+                <Property Name="Font" Value="BlueHighway-12" />
+                <Property Name="Text" Value="X" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{1,-20},{0,0},{1,0},{0,20}}" />
+                <!-- alle Grössen / anordnungen angepasst - da überschneidungen von absoluten
+                und relativen Positionsangaben (problematisch bei kleinen auflösungen) -->
+                <Event Name="Clicked" Function="InGamePickupHUD.close_button_clicked"/>
+            </Window>
+            <Window Type="TaharezLook/Listbox" Name="orxonox/InGamePickupHUD_PickupListBox">
+                <Property Name="Alpha" Value="0.8" />
+                <Property Name="Font" Value="BlueHighway-12" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0,5},{0,25},{1,-5},{1,-5}}" />
+                <!--
+                <Window Type="TaharezLook/ListboxItem" Name="orxonox/InGamePickupHUD_TestPickupOne">
+                    <Property Name="Alpha" Value="0.8" />
+                    <Property Name="Font" Value="BlueHighway-12" />
+                    <Property Name="Text" Value="First Pickup" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{0,30},{1,0}}" />
+                </Window>
+                -->
+            </Window>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/InGameTest.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/InGameTest.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/InGameTest.layout	(revision 11817)
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?>
+<GUILayout>
+    <Window Type="DefaultGUISheet" Name="orxonox/TestWindow">
+    <Property Name="UnifiedSize" Value="{{1.0,0},{1.0,0}}"/>
+
+        <Window Type="MenuWidgets/Button" Name="orxonox/TestButton">
+            <Property Name="UnifiedPosition" Value="{{0.11,0},{0.528,0}}"/>
+            <Property Name="UnifiedSize" Value="{{0.15,0},{0.05,0}}"/>
+            <Property Name="Text" Value="NoFunction"/>
+        </Window>
+
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/InfoPopup.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/InfoPopup.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/InfoPopup.layout	(revision 11817)
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/InfoPopup_RootWindow" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticImage" Name="orxonox/InfoPopup_Background" >
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+            <Property Name="Alpha" Value="0.7" />
+            <Window Type="MenuWidgets/Button" Name="orxonox/InfoPopup_close" >
+                <Property Name="Text" Value="Close" />
+                <Property Name="Alpha" Value="0.7" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.5,0},{0.6,0},{0.55,0}}" />
+                <Event Name="Clicked" Function="InfoPopup.close"/>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/InfoPopup_text" >
+                <Property Name="Text" Value="Template text" />
+                <Property Name="TextColours" Value="FF4444FF" />
+                <Property Name="HorzFormatting" Value="WordWrapCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.375,0},{0.75,0},{0.475,0}}" />
+                <Property Name="InheritsAlpha" Value="False" />
+               <Property Name="Alpha" Value="0.8" />
+            </Window>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/KeyBindMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/KeyBindMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/KeyBindMenu.layout	(revision 11817)
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/KeyBindMenu/Background" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/KeyBindWindow" >
+            <Property Name="Text" Value="Keybindings" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.2125,0},{0.85,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/KeyBindWrapper" >
+                <Property Name="TextColours" Value="FF4444FF" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/KeyBindPane" >
+                    <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                    <Property Name="HorzStepSize" Value="0.005" />
+                    <Property Name="VertStepSize" Value="0.005" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="HorzOverlapSize" Value="0.01" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.005,0},{0.01,0},{0.995,0},{0.99,0}}" />
+                    <Property Name="VertOverlapSize" Value="0.01" />
+                    <Property Name="HorzScrollPosition" Value="0" />
+                    <Property Name="VertScrollPosition" Value="0" />
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/KeyBindBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="KeyBindMenu.KeyBindBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/MainMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/MainMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/MainMenu.layout	(revision 11817)
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/MainMenuBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1.0,0},{1.0,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/Button" Name="orxonox/QuickGameTestButton" >
+            <Property Name="Text" Value="Quickstart" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.25,0},{0.6,0},{0.3,0}}" />
+            <Event Name="Clicked" Function="MainMenu.QuickGameTestButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SingleplayerButton" >
+            <Property Name="Text" Value="Singleplayer" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.325,0},{0.6,0},{0.375,0}}" />
+            <Event Name="Clicked" Function="MainMenu.SingleplayerButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MultiplayerButton" >
+            <Property Name="Text" Value="Multiplayer" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.4,0},{0.6,0},{0.45,0}}" />
+            <Event Name="Clicked" Function="MainMenu.MultiplayerButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/HighscoreButton" >
+            <Property Name="Text" Value="Highscore" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.475,0},{0.6,0},{0.525,0}}" />
+            <Event Name="Clicked" Function="MainMenu.HighscoreButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SettingsButton" >
+            <Property Name="Text" Value="Settings" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.55,0},{0.6,0},{0.6,0}}" />
+            <Event Name="Clicked" Function="MainMenu.SettingsButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/CreditsButton" >
+            <Property Name="Text" Value="Credits" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.625,0},{0.6,0},{0.675,0}}" />
+            <Event Name="Clicked" Function="MainMenu.CreditsButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/ExitButton" >
+            <Property Name="Text" Value="Exit" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.7,0},{0.6,0},{0.75,0}}" />
+            <Event Name="Clicked" Function="MainMenu.ExitButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/MainMenuBackground.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/MainMenuBackground.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/MainMenuBackground.layout	(revision 11817)
@@ -0,0 +1,10 @@
+<?xml version="1.0" ?>
+<GUILayout>
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/Background">
+        <Property Name="UnifiedSize" Value="{{1.0,0},{1.0,0}}"/>
+        <Property Name="Image" Value="set:MainMenuBackground image:Background"/>
+        <Property Name="FrameEnabled" Value="set:true"/>
+        <Property Name="BackgroundEnabled" Value="set:false"/>
+        <Property Name="InheritsAlpha" Value="False" />
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/MiscConfigMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/MiscConfigMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/MiscConfigMenu.layout	(revision 11817)
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/MiscConfigMenu/Background" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/MicsConfigMenu/ConfigWindow" >
+            <Property Name="Text" Value="Miscellaneous" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.2125,0},{0.85,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/MiscConfigMenu/Wrapper" >
+                <Property Name="TextColours" Value="FF4444FF" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/MiscConfigMenu/MiscConfigPane" >
+                    <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                    <Property Name="HorzStepSize" Value="0.005" />
+                    <Property Name="VertStepSize" Value="0.005" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="HorzOverlapSize" Value="0.01" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.005,0},{0.01,0},{0.995,0},{0.99,0}}" />
+                    <Property Name="VertOverlapSize" Value="0.01" />
+                    <Property Name="HorzScrollPosition" Value="0" />
+                    <Property Name="VertScrollPosition" Value="0" />
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MiscConfigMenu/CancelButton" >
+            <Property Name="Text" Value="Cancel" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.725,0},{0.4,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="MiscConfigMenu.MiscConfigCancelButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MiscConfigMenu/OKButton" >
+            <Property Name="Text" Value="OK" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.725,0},{0.75,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="MiscConfigMenu.MiscConfigOKButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/MouseControlsMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/MouseControlsMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/MouseControlsMenu.layout	(revision 11817)
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/MouseControlsBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/MouseControlsWindow" >
+            <Property Name="Text" Value="Mouse controls" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.3625,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/MouseNormalSensitivity" >
+                <Property Name="Text" Value="Sensitivity (normal mode)                                      " />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.2,0},{0.95,0},{0.45,0}}" />
+                <Window Type="MenuWidgets/HorizontalScrollbar" Name="orxonox/MouseNormalScrollbar" >
+                    <Property Name="PageSize" Value="0" />
+                    <Property Name="StepSize" Value="1" />
+                    <Property Name="OverlapSize" Value="0" />
+                    <Property Name="DocumentSize" Value="1" />
+                    <Property Name="ScrollPosition" Value="0" />
+                    <Property Name="StepSize" Value="0.1" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.02,0},{0.6,0},{0.565,0},{0.8,0}}" />
+                    <Event Name="ThumbTrackStarted" Function="MouseControlsMenu.MouseControlsMouseNormalScrollbar_started" />
+                    <Event Name="ThumbTrackEnded" Function="MouseControlsMenu.MouseControlsMouseNormalScrollbar_ended" />
+                    <Event Name="ScrollPosChanged" Function="MouseControlsMenu.MouseControlsMouseNormalScrollbar_changed" />
+                </Window>
+                <Window Type="MenuWidgets/RadioButton" Name="orxonox/MouseNormalButton" >
+                    <Property Name="Text" Value="Normal mouse input" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.61,0},{0.5,0},{0.975,0},{0.85,0}}" />
+                    <Event Name="SelectStateChanged" Function="MouseControlsMenu.MouseNormalButton_clicked" />
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/MouseDeriveSensitivity" >
+                <Property Name="Text" Value="Sensitivity (derive mode)                                      " />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.55,0},{0.95,0},{0.8,0}}" />
+                <Window Type="MenuWidgets/HorizontalScrollbar" Name="orxonox/MouseDeriveScrollbar" >
+                    <Property Name="PageSize" Value="0" />
+                    <Property Name="StepSize" Value="1" />
+                    <Property Name="OverlapSize" Value="0" />
+                    <Property Name="DocumentSize" Value="1" />
+                    <Property Name="ScrollPosition" Value="0" />
+                    <Property Name="StepSize" Value="0.1" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.02,0},{0.6,0},{0.565,0},{0.8,0}}" />
+                    <Event Name="ThumbTrackStarted" Function="MouseControlsMenu.MouseControlsMouseDeriveScrollbar_started" />
+                    <Event Name="ThumbTrackEnded" Function="MouseControlsMenu.MouseControlsMouseDeriveScrollbar_ended" />
+                    <Event Name="ScrollPosChanged" Function="MouseControlsMenu.MouseControlsMouseDeriveScrollbar_changed" />
+                </Window>
+                <Window Type="MenuWidgets/RadioButton" Name="orxonox/MouseDeriveButton" >
+                    <Property Name="Text" Value="Derive mouse input" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.61,0},{0.5,0},{0.975,0},{0.85,0}}" />
+                    <Event Name="SelectStateChanged" Function="MouseControlsMenu.MouseDeriveButton_clicked" />
+                </Window>
+            </Window>
+            <Window Type="MenuWidgets/Checkbox" Name="orxonox/MouseInvertCheckbox" >
+                <Property Name="Text" Value="Invert mouse" />
+                <Property Name="Disabled" Value="true" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.39,0},{0.85,0},{0.61,0},{0.95,0}}" />
+                <Event Name="CheckStateChanged" Function="MouseControlsMenu.MouseInvertCheckbox_clicked" />
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MouseControlsBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="MouseControlsMenu.MouseControlsBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/MultiplayerMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/MultiplayerMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/MultiplayerMenu.layout	(revision 11817)
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/MultiplayerBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/MultiplayerWindow" >
+            <Property Name="Text" Value="Multiplayer" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/Listbox" Name="orxonox/MultiplayerListbox" >
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.8,0}}" />
+            </Window>
+            <Window Type="MenuWidgets/RadioButton" Name="orxonox/MultiplayerLanButton" >
+                <Property Name="Text" Value="LAN"/>
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.2,0},{0.87,0},{0.4,0},{0.97,0}}" />
+                <Event Name="SelectStateChanged" Function="MultiplayerMenu.LanButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/RadioButton" Name="orxonox/MultiplayerInternetButton" >
+                <Property Name="Text" Value="Internet" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.87,0},{0.8,0},{0.97,0}}" />
+                <Event Name="SelectStateChanged" Function="MultiplayerMenu.InternetButton_clicked"/>
+            </Window>
+        </Window>
+         <Window Type="MenuWidgets/Button" Name="orxonox/MultiplayerBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.7125,0},{0.8625,0},{0.9125,0},{0.9125,0}}" />
+            <Event Name="Clicked" Function="MultiplayerMenu.MultiplayerBackButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MultiplayerJoinButton" >
+            <Property Name="Text" Value="Join" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.6625,0},{0.4875,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="MultiplayerMenu.MultiplayerJoinButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MultiplayerHostButton" >
+            <Property Name="Text" Value="Host" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.6625,0},{0.7125,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="MultiplayerMenu.MultiplayerHostButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
+
Index: /code/branches/RacingBots_FS18/data/gui/layouts/MultiplayerOptionsMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/MultiplayerOptionsMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/MultiplayerOptionsMenu.layout	(revision 11817)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/MultiplayerOptionsBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/MultiplayerOptionsWindow" >
+            <Property Name="Text" Value="Multiplayer options" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.3625,0},{0.75,0},{0.6375,0}}" />
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/MultiplayerOptionsBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.625,0},{0.6,0},{0.675,0}}" />
+            <Event Name="Clicked" Function="MultiplayerOptionsMenu.MultiplayerOptionsBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/NotificationLayer.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/NotificationLayer.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/NotificationLayer.layout	(revision 11817)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/NotificationLayer/Root" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/PickupInventory.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/PickupInventory.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/PickupInventory.layout	(revision 11817)
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="DefaultWindow" Name="orxonox/PickupInventory/Background" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/PickupInventory/PickupInventory" >
+            <Property Name="Text" Value="Pickup Inventory" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.15,0},{0.85,0},{0.8,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/PickupInventory/Wrapper" >
+                <Property Name="TextColours" Value="FF4444FF" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/PickupInventory/Inventory" >
+                    <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                    <Property Name="HorzStepSize" Value="0.005" />
+                    <Property Name="VertStepSize" Value="0.005" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="HorzOverlapSize" Value="0.01" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.005,0},{0.01,0},{0.995,0},{0.99,0}}" />
+                    <Property Name="VertOverlapSize" Value="0.01" />
+                    <Property Name="HorzScrollPosition" Value="0" />
+                    <Property Name="VertScrollPosition" Value="0" />
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/PickupInventory/InventoryBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.8350,0},{0.6,0},{0.8800,0}}" />
+            <Event Name="Clicked" Function="PickupInventory.InventoryBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/QuestGUI.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/QuestGUI.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/QuestGUI.layout	(revision 11817)
@@ -0,0 +1,78 @@
+<?xml version="1.0" ?>
+<GUILayout>
+    <Window Type="DefaultWindow" Name="orxonox/QuestGUI/Background">
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+
+        <Window Type="DefaultWindow" Name="orxonox/QuestGUI/MainWindow">
+            <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.1,0},{0.9,0},{0.9,0}}" />
+
+            <Window Type="MenuWidgets/Titlebar" Name="orxonox/QuestGUI/Title">
+                <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0,30}}" />
+                <Property Name="Text" Value="Your Quests"/>
+            </Window>
+
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/MainWindow/LeftPanel">
+                <Property Name="UnifiedAreaRect" Value="{{0,0},{0,30},{0.5,0},{1,0}}" />
+
+                <Window Type="MenuWidgets/TabButton" Name="orxonox/QuestGUI/ActiveQuestsButton">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{0.5,0},{0,30}}" />
+                    <Property Name="Text" Value="active quests"/>
+                    <Event Name="Clicked" Function="QuestGUI.showActiveQuestsButton_clicked"/>
+                </Window>
+                <Window Type="MenuWidgets/TabButton" Name="orxonox/QuestGUI/FinishedQuestsButton">
+                    <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0,0},{1,0},{0,30}}" />
+                    <Property Name="Text" Value="finished quests"/>
+                    <Event Name="Clicked" Function="QuestGUI.showFinishedQuestsButton_clicked"/>
+                </Window>
+
+                <Window Type="MenuWidgets/Listbox" Name="orxonox/QuestGUI/QuestsList">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,30},{1,0},{1,0}}" />
+                    <Event Name="ItemSelectionChanged" Function="QuestGUI.changeQuest_clicked"/>
+                </Window>
+            </Window>
+
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/MainWindow/RightPanel">
+                <Property Name="UnifiedAreaRect" Value="{{0.5,0},{0,30},{1,0},{1,0}}" />
+
+                <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Title">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0,30}}" />
+                    <Property Name="Text" Value="Quest Title"/>
+                </Window>
+
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/QuestGUI/Quest/ScrollWrapper">
+                    <Property Name="UnifiedAreaRect" Value="{{0,0},{0,30},{1,-4},{1,-4}}" />
+
+                    <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Wrapper">
+                        <Property Name="UnifiedAreaRect" Value="{{0,5},{0,5},{1,-5},{0,0}}" />
+                        <Property Name="FrameEnabled" Value="false" />
+                        <Property Name="Alpha" Value="0" />
+
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Description">
+                            <Property Name="UnifiedAreaRect" Value="{{0,5},{0,0},{1,-5},{0,0}}" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Property Name="HorzFormatting" Value="WordWrapLeftAligned" />
+                            <Property Name="VertFormatting" Value="TopAligned" />
+                            <Property Name="FrameEnabled" Value="false" />
+                            <Property Name="Text" Value="Quest Description"/>
+                        </Window>
+
+                        <Window Type="MenuWidgets/Listbox" Name="orxonox/QuestGUI/Quest/SubquestsList">
+                            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Event Name="ItemSelectionChanged" Function="QuestGUI.changeToSubquest_clicked"/>
+                        </Window>
+
+                        <Window Type="MenuWidgets/StaticText" Name="orxonox/QuestGUI/Quest/Hints">
+                            <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{0,0}}" />
+                            <Property Name="InheritsAlpha" Value="False" />
+                            <Property Name="VertFormatting" Value="TopAligned" />
+                            <Property Name="FrameEnabled" Value="false" />
+                            <Property Name="Text" Value="Hints:" />
+                        </Window>
+                    </Window>
+                </Window>
+            </Window>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/SettingsMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/SettingsMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/SettingsMenu.layout	(revision 11817)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/SettingsMenu/Background" >
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/SettingsMenu/SettingsWindow" >
+            <Property Name="Text" Value="Settings" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.3625,0},{0.75,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/GameplayButton" >
+                <Property Name="Text" Value="Gameplay" />
+                <Property Name="Disabled" Value="True" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.181818,0},{0.45,0},{0.363636,0}}" />
+                <Event Name="Clicked" Function="SettingsMenu.SettingsGameplayButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/MultiplayerOptionsButton" >
+                <Property Name="Text" Value="Multiplayer options" />
+                <Property Name="Disabled" Value="True" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.454545,0},{0.45,0},{0.636363,0}}" />
+                <Event Name="Clicked" Function="SettingsMenu.SettingsMultiplayerOptionsButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/ControlsButton" >
+                <Property Name="Text" Value="Controls" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.727272,0},{0.45,0},{0.909090,0}}" />
+                <Event Name="Clicked" Function="SettingsMenu.SettingsControlsButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/GraphicsButton" >
+                <Property Name="Text" Value="Graphics" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.181818,0},{0.95,0},{0.363636,0}}" />
+                <Event Name="Clicked" Function="SettingsMenu.SettingsGraphicsButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/AudioButton" >
+                <Property Name="Text" Value="Audio" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.454545,0},{0.95,0},{0.636363,0}}" />
+                <Event Name="Clicked" Function="SettingsMenu.SettingsAudioButton_clicked"/>
+            </Window>
+            <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/MiscellaneousButton" >
+                <Property Name="Text" Value="Miscellaneous" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.727272,0},{0.95,0},{0.909090,0}}" />
+                <Event Name="Clicked" Function="SettingsMenu.SettingsMiscellaneousButton_clicked"/>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SettingsMenu/SettingsBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.6625,0},{0.6,0},{0.7125,0}}" />
+            <Event Name="Clicked" Function="SettingsMenu.SettingsBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/ShipSelectionMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/ShipSelectionMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/ShipSelectionMenu.layout	(revision 11817)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/ShipSelectionBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <!-- -->
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/ShipSelectionWindow" >
+            <Property Name="Text" Value="ShipSelection" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2,0},{0.15,0},{0.8,0},{0.7,0}}" />
+            <Window Type="MenuWidgets/TabControl" Name="orxonox/ShipSelectionTabControl" >
+                <Property Name="TabHeight" Value="{0,26.4388}" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="TabPanePosition" Value="Top" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.1,0},{0.95,0},{0.925,0}}" />
+
+            </Window>
+
+            <!-- TODO: Ship Description and Image
+            <Window Type="MenuWidgets/StaticImage" Name="orxonox/ShipSelectionShipImage" >
+                <Property Name="AlwaysOnTop" Value="True" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.25,0},{0.9,0},{0.675,0}}" />
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/ShipSelectionLevelDescription" >
+                <Property Name="AlwaysOnTop" Value="True" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertScrollbar" Value="True" />
+                <Property Name="HorzScrollbar" Value="True" />
+                <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.725,0},{0.9,0},{0.875,0}}" />
+            </Window>-->
+
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/ShipSelectionStartButton" >
+            <Property Name="Text" Value="Start" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.725,0},{0.4,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="ShipSelectionMenu.ShipSelectionStartButton_clicked"/>
+        </Window>
+        <!-- TODO: set ship properties
+        <Window Type="MenuWidgets/Button" Name="orxonox/ShipSelectionConfigButton" >
+            <Property Name="Text" Value="Configure" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.425,0},{0.725,0},{0.575,0},{0.775,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="ShipSelectionMenu.ShipSelectionConfigButton_clicked"/>
+        </Window> -->
+        <Window Type="MenuWidgets/Button" Name="orxonox/ShipSelectionBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.725,0},{0.75,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="ShipSelectionMenu.ShipSelectionBackButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/SingleplayerConfigMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/SingleplayerConfigMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/SingleplayerConfigMenu.layout	(revision 11817)
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/SingleplayerConfigMenu/Background" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/SingleplayerConfigMenu/ConfigWindow" >
+            <Property Name="Text" Value="Config" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.15,0},{0.2125,0},{0.85,0},{0.6375,0}}" />
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/SingleplayerConfigMenu/Wrapper" >
+                <Property Name="TextColours" Value="FF4444FF" />
+                <Property Name="InheritsAlpha" Value="False" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="HorzFormatting" Value="HorzCentred" />
+                <Property Name="VertFormatting" Value="TopAligned" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.92,0}}" />
+                <Window Type="MenuWidgets/ScrollablePane" Name="orxonox/SingleplayerConfigMenu/MiscConfigPane" >
+                    <Property Name="ContentArea" Value="l:0 t:0 r:0 b:0" />
+                    <Property Name="HorzStepSize" Value="0.005" />
+                    <Property Name="VertStepSize" Value="0.005" />
+                    <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                    <Property Name="HorzOverlapSize" Value="0.01" />
+                    <Property Name="UnifiedAreaRect" Value="{{0.005,0},{0.01,0},{0.995,0},{0.99,0}}" />
+                    <Property Name="VertOverlapSize" Value="0.01" />
+                    <Property Name="HorzScrollPosition" Value="0" />
+                    <Property Name="VertScrollPosition" Value="0" />
+                </Window>
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SingleplayerConfigMenu/CancelButton" >
+            <Property Name="Text" Value="Cancel" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.725,0},{0.4,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="SingleplayerConfigMenu.SingleplayerConfigCancelButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SingleplayerConfigMenu/OKButton" >
+            <Property Name="Text" Value="OK" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.725,0},{0.75,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="SingleplayerConfigMenu.SingleplayerConfigOKButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/SingleplayerMenu.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/SingleplayerMenu.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/SingleplayerMenu.layout	(revision 11817)
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/SingleplayerBackground" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/SingleplayerWindow" >
+            <Property Name="Text" Value="Singleplayer" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2,0},{0.15,0},{0.8,0},{0.7,0}}" />
+            <Window Type="MenuWidgets/TabControl" Name="orxonox/SingleplayerTabControl" >
+                <Property Name="TabHeight" Value="{0,26.4388}" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="TabPanePosition" Value="Top" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.1,0},{0.95,0},{0.925,0}}" />
+            </Window>
+            <Window Type="MenuWidgets/StaticImage" Name="orxonox/SingleplayerLevelImage" >
+                <Property Name="AlwaysOnTop" Value="True" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.55,0},{0.25,0},{0.9,0},{0.675,0}}" />
+            </Window>
+            <Window Type="MenuWidgets/StaticText" Name="orxonox/SingleplayerLevelDescription" >
+                <Property Name="AlwaysOnTop" Value="True" />
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="VertScrollbar" Value="True" />
+                <Property Name="HorzScrollbar" Value="False" />
+                <Property Name="UnifiedAreaRect" Value="{{0.1,0},{0.725,0},{0.9,0},{0.875,0}}" />
+                <Property Name="HorzFormatting" Value="WordWrapLeftAligned" />
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SingleplayerStartButton" >
+            <Property Name="Text" Value="Start" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.725,0},{0.4,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="SingleplayerMenu.SingleplayerStartButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SingleplayerConfigButton" >
+            <Property Name="Text" Value="Configure" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.425,0},{0.725,0},{0.575,0},{0.775,0}}" />
+            <Property Name="Disabled" Value="True" />
+            <Event Name="Clicked" Function="SingleplayerMenu.SingleplayerConfigButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/SingleplayerBackButton" >
+            <Property Name="Text" Value="Back" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.6,0},{0.725,0},{0.75,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="SingleplayerMenu.SingleplayerBackButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/CampaignButton" >
+            <Property Name="Text" Value="Campaign" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.4,0},{0.8,0},{0.6,0},{0.85,0}}" />
+            <Event Name="Clicked" Function="SingleplayerMenu.CampaignButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/layouts/UndockingDialog.layout
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/layouts/UndockingDialog.layout	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/layouts/UndockingDialog.layout	(revision 11817)
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<GUILayout >
+    <Window Type="MenuWidgets/StaticImage" Name="orxonox/Undocking/Background" >
+        <Property Name="FrameEnabled" Value="False" />
+        <Property Name="InheritsAlpha" Value="False" />
+        <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+        <Property Name="UnifiedAreaRect" Value="{{0,0},{0,0},{1,0},{1,0}}" />
+        <Property Name="BackgroundEnabled" Value="False" />
+        <Window Type="MenuWidgets/StaticText" Name="orxonox/Undocking/Title" >
+            <Property Name="Text" Value="Undocking" />
+            <Property Name="Alpha" Value="0.8" />
+            <Property Name="InheritsAlpha" Value="False" />
+            <Property Name="HorzFormatting" Value="HorzCentred" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="VertFormatting" Value="TopAligned" />
+            <Property Name="UnifiedAreaRect" Value="{{0.25,0},{0.2875,0},{0.75,0},{0.7,0}}" />
+            <Window Type="MenuWidgets/Listbox" Name="orxonox/Undocking/Docks" >
+                <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+                <Property Name="UnifiedAreaRect" Value="{{0.05,0},{0.15,0},{0.95,0},{0.85,0}}" />
+            </Window>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/Undocking/DockButton" >
+            <Property Name="Text" Value="Undock" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.2875,0},{0.725,0},{0.4875,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="UndockingDialog.undockButton_clicked"/>
+        </Window>
+        <Window Type="MenuWidgets/Button" Name="orxonox/Undocking/CancelButton" >
+            <Property Name="Text" Value="Cancel" />
+            <Property Name="UnifiedMaxSize" Value="{{1,0},{1,0}}" />
+            <Property Name="UnifiedAreaRect" Value="{{0.5125,0},{0.725,0},{0.7125,0},{0.775,0}}" />
+            <Event Name="Clicked" Function="UndockingDialog.cancelButton_clicked"/>
+        </Window>
+    </Window>
+</GUILayout>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/GUIScheme.xsd
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/GUIScheme.xsd	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/GUIScheme.xsd	(revision 11817)
@@ -0,0 +1,54 @@
+<?xml version="1.0" ?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
+    <xsd:element name="GUIScheme" type="SchemeType" />
+    <xsd:complexType name="SchemeType">
+        <xsd:choice minOccurs="0" maxOccurs="unbounded">
+            <xsd:element name="Imageset" type="NamedDataType" />
+            <xsd:element name="ImagesetFromImage" type="NamedDataType" />
+            <xsd:element name="Font" type="NamedDataType" />
+            <xsd:element name="LookNFeel" type="FileDataType" />
+            <xsd:element name="WindowSet" type="WindowSetType" />
+            <xsd:element name="WindowRendererSet" type="WindowRendererSetType" />
+            <xsd:element name="WindowAlias" type="WindowAliasType" />
+            <xsd:element name="FalagardMapping" type="FalagardMapType" />
+        </xsd:choice>
+        <xsd:attribute name="Name" type="xsd:string" use="required" />
+    </xsd:complexType>
+    <xsd:complexType name="WindowSetType">
+        <xsd:sequence>
+            <xsd:element name="WindowFactory" type="WindowFactoryType" minOccurs="0" maxOccurs="unbounded" />
+        </xsd:sequence>
+        <xsd:attribute name="Filename" type="xsd:string" use="required" />
+    </xsd:complexType>
+    <xsd:complexType name="WindowRendererSetType">
+        <xsd:sequence>
+            <xsd:element name="WindowRendererFactory" type="WindowRendererFactoryType" minOccurs="0" maxOccurs="unbounded" />
+        </xsd:sequence>
+        <xsd:attribute name="Filename" type="xsd:string" use="required" />
+    </xsd:complexType>
+    <xsd:complexType name="FileDataType">
+        <xsd:attribute name="Filename" type="xsd:string" use="required" />
+        <xsd:attribute name="ResourceGroup" type="xsd:string" use="optional"  default="" />
+    </xsd:complexType>
+    <xsd:complexType name="NamedDataType">
+        <xsd:attribute name="Name" type="xsd:string" use="required" />
+        <xsd:attribute name="Filename" type="xsd:string" use="required" />
+        <xsd:attribute name="ResourceGroup" type="xsd:string" use="optional"  default="" />
+    </xsd:complexType>
+    <xsd:complexType name="WindowFactoryType">
+        <xsd:attribute name="Name" type="xsd:string" use="required" />
+    </xsd:complexType>
+    <xsd:complexType name="WindowRendererFactoryType">
+        <xsd:attribute name="Name" type="xsd:string" use="required" />
+    </xsd:complexType>
+    <xsd:complexType name="WindowAliasType">
+        <xsd:attribute name="Alias" type="xsd:string" use="required" />
+        <xsd:attribute name="Target" type="xsd:string" use="required" />
+    </xsd:complexType>
+    <xsd:complexType name="FalagardMapType">
+        <xsd:attribute name="WindowType" type="xsd:string" use="required" />
+        <xsd:attribute name="TargetType" type="xsd:string" use="required" />
+        <xsd:attribute name="Renderer" type="xsd:string" use="required" />
+        <xsd:attribute name="LookNFeel" type="xsd:string" use="required" />
+    </xsd:complexType>
+</xsd:schema>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/Looks.txt
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/Looks.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/Looks.txt	(revision 11817)
@@ -0,0 +1,28 @@
+We use TaharezLook as default and reference. That means each new look ideally
+has to implement all widgets from TaharezLook except 4 (see below).
+If not, please use the Taharez version in the look files.
+
+
+*******
+*LOOKS*
+*******
+
+Taharez
+'''''''
+Missing   :
+Additional: AlternateProgressBar, LargeVerticalScrollbar,
+            LargeVerticalScrollbarThumb
+
+Windows
+'''''''
+Missing   : ComboEditbox, ImageButton, Tree
+Additional: IconButton, Static
+
+SleekSpace
+''''''''''
+LookNFeel file does not yet work with CEGUI > 0.4 because of missing property
+definitions.
+
+Vanilla
+'''''''
+LookNFeel file also misses some property definitions.
Index: /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxGUIScheme.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxGUIScheme.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxGUIScheme.scheme	(revision 11817)
@@ -0,0 +1,9 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="OrxonoxGUI">
+    <Imageset Name="MainMenuBackground" Filename="MainMenuBackground.imageset"/>
+    <Imageset Name="PickupInventory" Filename="PickupInventory.imageset"/>
+    <Font Name="BlueHighway-12" Filename="bluehighway-12.font" />
+    <Font Name="BlueHighway-10" Filename="bluehighway-10.font" />
+    <Font Name="BlueHighway-8"  Filename="bluehighway-8.font"  />
+    <Font Name="Monofur-10"     Filename="Monofur-10.font" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxHUDWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxHUDWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxHUDWidgets.scheme	(revision 11817)
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="OrxonoxHUDWidgets">
+    <WindowAlias Alias="HUDWidgets/StaticImage"              Target="OrxonoxLook/StaticImage" />
+    <WindowAlias Alias="HUDWidgets/StaticText"               Target="OrxonoxLook/StaticText" />
+    <WindowAlias Alias="HUDWidgets/TabButtonPane"            Target="OrxonoxLook/TabButtonPane" />
+    <WindowAlias Alias="HUDWidgets/TabContentPane"           Target="OrxonoxLook/TabContentPane" />
+    <WindowAlias Alias="HUDWidgets/Checkbox"                 Target="OrxonoxLook/Checkbox" />
+    <WindowAlias Alias="HUDWidgets/Combobox"                 Target="OrxonoxLook/Combobox" />
+    <WindowAlias Alias="HUDWidgets/ComboDropList"            Target="OrxonoxLook/ComboDropList" />
+    <WindowAlias Alias="HUDWidgets/ComboEditbox"             Target="OrxonoxLook/ComboEditbox" />
+    <WindowAlias Alias="HUDWidgets/Editbox"                  Target="OrxonoxLook/Editbox" />
+    <WindowAlias Alias="HUDWidgets/FrameWindow"              Target="OrxonoxLook/FrameWindow" />
+    <WindowAlias Alias="HUDWidgets/GroupBox"                 Target="OrxonoxLook/GroupBox" />
+    <WindowAlias Alias="HUDWidgets/ItemListbox"              Target="OrxonoxLook/ItemListbox" />
+    <WindowAlias Alias="HUDWidgets/ListboxItem"              Target="OrxonoxLook/ListboxItem" />
+    <WindowAlias Alias="HUDWidgets/Listbox"                  Target="OrxonoxLook/Listbox" />
+    <WindowAlias Alias="HUDWidgets/ListHeader"               Target="OrxonoxLook/ListHeader" />
+    <WindowAlias Alias="HUDWidgets/ListHeaderSegment"        Target="OrxonoxLook/ListHeaderSegment" />
+    <WindowAlias Alias="HUDWidgets/MultiLineEditbox"         Target="OrxonoxLook/MultiLineEditbox" />
+    <WindowAlias Alias="HUDWidgets/Menubar"                  Target="OrxonoxLook/Menubar" />
+    <WindowAlias Alias="HUDWidgets/MenuItem"                 Target="OrxonoxLook/MenuItem" />
+    <WindowAlias Alias="HUDWidgets/MultiColumnList"          Target="OrxonoxLook/MultiColumnList" />
+    <WindowAlias Alias="HUDWidgets/PopupMenu"                Target="OrxonoxLook/PopupMenu" />
+    <WindowAlias Alias="HUDWidgets/ProgressBar"              Target="OrxonoxLook/ProgressBar" />
+    <WindowAlias Alias="HUDWidgets/Button"                   Target="OrxonoxLook/Button" />
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="OrxonoxLook/ImageButton" />
+    <WindowAlias Alias="HUDWidgets/RadioButton"              Target="OrxonoxLook/RadioButton" />
+    <WindowAlias Alias="HUDWidgets/SystemButton"             Target="OrxonoxLook/SystemButton" />
+    <WindowAlias Alias="HUDWidgets/ScrollablePane"           Target="OrxonoxLook/ScrollablePane" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbar"      Target="OrxonoxLook/HorizontalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbar"        Target="OrxonoxLook/VerticalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/Slider"                   Target="OrxonoxLook/Slider" />
+    <WindowAlias Alias="HUDWidgets/Spinner"                  Target="OrxonoxLook/Spinner" />
+    <WindowAlias Alias="HUDWidgets/TabButton"                Target="OrxonoxLook/TabButton" />
+    <WindowAlias Alias="HUDWidgets/TabControl"               Target="OrxonoxLook/TabControl" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbarThumb" Target="OrxonoxLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/SliderThumb"              Target="OrxonoxLook/SliderThumb" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbarThumb"   Target="OrxonoxLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/Titlebar"                 Target="OrxonoxLook/Titlebar" />
+    <WindowAlias Alias="HUDWidgets/Tooltip"                  Target="OrxonoxLook/Tooltip" />
+    <WindowAlias Alias="HUDWidgets/Tree"                     Target="OrxonoxLook/Tree" />
+
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="OrxonoxLook/JuuButton" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxLook.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxLook.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxLook.scheme	(revision 11817)
@@ -0,0 +1,57 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="OrxonoxLook">
+    <Imageset Name="OrxonoxLook" Filename="OrxonoxLook.imageset" />
+    <LookNFeel Filename="OrxonoxLook.looknfeel" />
+    <WindowRendererSet Filename="CEGUIFalagardWRBase" />
+
+    <!-- Standard widgets -->
+    <FalagardMapping WindowType="OrxonoxLook/StaticImage"              TargetType="DefaultWindow"           Renderer="Falagard/StaticImage"       LookNFeel="OrxonoxLook/StaticImage" />
+    <FalagardMapping WindowType="OrxonoxLook/StaticText"               TargetType="DefaultWindow"           Renderer="Falagard/StaticText"        LookNFeel="OrxonoxLook/StaticText" />
+    <FalagardMapping WindowType="OrxonoxLook/TabButtonPane"            TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="OrxonoxLook/TabButtonPane" />
+    <FalagardMapping WindowType="OrxonoxLook/TabContentPane"           TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="OrxonoxLook/TabContentPane" />
+    <FalagardMapping WindowType="OrxonoxLook/Checkbox"                 TargetType="CEGUI/Checkbox"          Renderer="Falagard/ToggleButton"      LookNFeel="OrxonoxLook/Checkbox" />
+    <FalagardMapping WindowType="OrxonoxLook/Combobox"                 TargetType="CEGUI/Combobox"          Renderer="Falagard/Default"           LookNFeel="OrxonoxLook/Combobox" />
+    <FalagardMapping WindowType="OrxonoxLook/ComboDropList"            TargetType="CEGUI/ComboDropList"     Renderer="Falagard/Listbox"           LookNFeel="OrxonoxLook/ComboDropList" />
+    <FalagardMapping WindowType="OrxonoxLook/ComboEditbox"             TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="OrxonoxLook/ComboEditbox" />
+    <FalagardMapping WindowType="OrxonoxLook/Editbox"                  TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="OrxonoxLook/Editbox" />
+    <FalagardMapping WindowType="OrxonoxLook/FrameWindow"              TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="OrxonoxLook/FrameWindow" />
+    <FalagardMapping WindowType="OrxonoxLook/GroupBox"                 TargetType="CEGUI/GroupBox"          Renderer="Falagard/Default"           LookNFeel="OrxonoxLook/GroupBox" />
+    <FalagardMapping WindowType="OrxonoxLook/ItemListbox"              TargetType="CEGUI/ItemListbox"       Renderer="Falagard/ItemListbox"       LookNFeel="OrxonoxLook/ItemListbox" />
+    <FalagardMapping WindowType="OrxonoxLook/ListboxItem"              TargetType="CEGUI/ItemEntry"         Renderer="Falagard/ItemEntry"         LookNFeel="OrxonoxLook/ListboxItem" />
+    <FalagardMapping WindowType="OrxonoxLook/Listbox"                  TargetType="CEGUI/Listbox"           Renderer="Falagard/Listbox"           LookNFeel="OrxonoxLook/Listbox" />
+    <FalagardMapping WindowType="OrxonoxLook/ListHeader"               TargetType="CEGUI/ListHeader"        Renderer="Falagard/ListHeader"        LookNFeel="OrxonoxLook/ListHeader" />
+    <FalagardMapping WindowType="OrxonoxLook/ListHeaderSegment"        TargetType="CEGUI/ListHeaderSegment" Renderer="Falagard/ListHeaderSegment" LookNFeel="OrxonoxLook/ListHeaderSegment" />
+    <FalagardMapping WindowType="OrxonoxLook/MultiLineEditbox"         TargetType="CEGUI/MultiLineEditbox"  Renderer="Falagard/MultiLineEditbox"  LookNFeel="OrxonoxLook/MultiLineEditbox" />
+    <FalagardMapping WindowType="OrxonoxLook/Menubar"                  TargetType="CEGUI/Menubar"           Renderer="Falagard/Menubar"           LookNFeel="OrxonoxLook/Menubar" />
+    <FalagardMapping WindowType="OrxonoxLook/MenuItem"                 TargetType="CEGUI/MenuItem"          Renderer="Falagard/MenuItem"          LookNFeel="OrxonoxLook/MenuItem" />
+    <FalagardMapping WindowType="OrxonoxLook/MultiColumnList"          TargetType="CEGUI/MultiColumnList"   Renderer="Falagard/MultiColumnList"   LookNFeel="OrxonoxLook/MultiColumnList" />
+    <FalagardMapping WindowType="OrxonoxLook/PopupMenu"                TargetType="CEGUI/PopupMenu"         Renderer="Falagard/PopupMenu"         LookNFeel="OrxonoxLook/PopupMenu" />
+    <FalagardMapping WindowType="OrxonoxLook/ProgressBar"              TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="OrxonoxLook/ProgressBar" />
+    <FalagardMapping WindowType="OrxonoxLook/Button"                   TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="OrxonoxLook/Button" />
+    <FalagardMapping WindowType="OrxonoxLook/ImageButton"              TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="OrxonoxLook/ImageButton" />
+    <FalagardMapping WindowType="OrxonoxLook/RadioButton"              TargetType="CEGUI/RadioButton"       Renderer="Falagard/ToggleButton"      LookNFeel="OrxonoxLook/RadioButton" />
+    <FalagardMapping WindowType="OrxonoxLook/SystemButton"             TargetType="CEGUI/PushButton"        Renderer="Falagard/SystemButton"      LookNFeel="OrxonoxLook/Button" />
+    <FalagardMapping WindowType="OrxonoxLook/ScrollablePane"           TargetType="CEGUI/ScrollablePane"    Renderer="Falagard/ScrollablePane"    LookNFeel="OrxonoxLook/ScrollablePane" />
+    <FalagardMapping WindowType="OrxonoxLook/HorizontalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="OrxonoxLook/HorizontalScrollbar" />
+    <FalagardMapping WindowType="OrxonoxLook/VerticalScrollbar"        TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="OrxonoxLook/VerticalScrollbar" />
+    <FalagardMapping WindowType="OrxonoxLook/Slider"                   TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="OrxonoxLook/Slider" />
+    <FalagardMapping WindowType="OrxonoxLook/Spinner"                  TargetType="CEGUI/Spinner"           Renderer="Falagard/Default"           LookNFeel="OrxonoxLook/Spinner" />
+    <FalagardMapping WindowType="OrxonoxLook/TabButton"                TargetType="CEGUI/TabButton"         Renderer="Falagard/TabButton"         LookNFeel="OrxonoxLook/TabButton" />
+    <FalagardMapping WindowType="OrxonoxLook/TabControl"               TargetType="CEGUI/TabControl"        Renderer="Falagard/TabControl"        LookNFeel="OrxonoxLook/TabControl" />
+    <FalagardMapping WindowType="OrxonoxLook/HorizontalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="OrxonoxLook/HorizontalScrollbarThumb" />
+    <FalagardMapping WindowType="OrxonoxLook/SliderThumb"              TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="OrxonoxLook/SliderThumb" />
+    <FalagardMapping WindowType="OrxonoxLook/VerticalScrollbarThumb"   TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="OrxonoxLook/VerticalScrollbarThumb" />
+    <FalagardMapping WindowType="OrxonoxLook/Titlebar"                 TargetType="CEGUI/Titlebar"          Renderer="Falagard/Titlebar"          LookNFeel="OrxonoxLook/Titlebar" />
+    <FalagardMapping WindowType="OrxonoxLook/Tooltip"                  TargetType="CEGUI/Tooltip"           Renderer="Falagard/Tooltip"           LookNFeel="OrxonoxLook/Tooltip" />
+    <FalagardMapping WindowType="OrxonoxLook/Tree"                     TargetType="CEGUI/Tree"              Renderer="Falagard/Tree"              LookNFeel="OrxonoxLook/Tree" />
+
+    <!-- Additional widgets -->
+    <FalagardMapping WindowType="OrxonoxLook/AlternateProgressBar"        TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="OrxonoxLook/AltProgressBar" />
+    <FalagardMapping WindowType="OrxonoxLook/VUMeter"                     TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="OrxonoxLook/VUMeter" />
+    <FalagardMapping WindowType="OrxonoxLook/LargeVerticalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="OrxonoxLook/LargeVerticalScrollbar" />
+    <FalagardMapping WindowType="OrxonoxLook/LargeVerticalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"         LookNFeel="OrxonoxLook/LargeVerticalScrollbarThumb" />
+
+    <!-- Special Button for CampaignMenu -->
+    <FalagardMapping WindowType="OrxonoxLook/JuuButton"              TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="OrxonoxLook/JuuButton" />
+
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxMenuWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxMenuWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/OrxonoxMenuWidgets.scheme	(revision 11817)
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="OrxonoxMenuWidgets">
+    <WindowAlias Alias="MenuWidgets/StaticImage"              Target="OrxonoxLook/StaticImage" />
+    <WindowAlias Alias="MenuWidgets/StaticText"               Target="OrxonoxLook/StaticText" />
+    <WindowAlias Alias="MenuWidgets/TabButtonPane"            Target="OrxonoxLook/TabButtonPane" />
+    <WindowAlias Alias="MenuWidgets/TabContentPane"           Target="OrxonoxLook/TabContentPane" />
+    <WindowAlias Alias="MenuWidgets/Checkbox"                 Target="OrxonoxLook/Checkbox" />
+    <WindowAlias Alias="MenuWidgets/Combobox"                 Target="OrxonoxLook/Combobox" />
+    <WindowAlias Alias="MenuWidgets/ComboDropList"            Target="OrxonoxLook/ComboDropList" />
+    <WindowAlias Alias="MenuWidgets/ComboEditbox"             Target="OrxonoxLook/ComboEditbox" />
+    <WindowAlias Alias="MenuWidgets/Editbox"                  Target="OrxonoxLook/Editbox" />
+    <WindowAlias Alias="MenuWidgets/FrameWindow"              Target="OrxonoxLook/FrameWindow" />
+    <WindowAlias Alias="MenuWidgets/GroupBox"                 Target="OrxonoxLook/GroupBox" />
+    <WindowAlias Alias="MenuWidgets/ItemListbox"              Target="OrxonoxLook/ItemListbox" />
+    <WindowAlias Alias="MenuWidgets/ListboxItem"              Target="OrxonoxLook/ListboxItem" />
+    <WindowAlias Alias="MenuWidgets/Listbox"                  Target="OrxonoxLook/Listbox" />
+    <WindowAlias Alias="MenuWidgets/ListHeader"               Target="OrxonoxLook/ListHeader" />
+    <WindowAlias Alias="MenuWidgets/ListHeaderSegment"        Target="OrxonoxLook/ListHeaderSegment" />
+    <WindowAlias Alias="MenuWidgets/MultiLineEditbox"         Target="OrxonoxLook/MultiLineEditbox" />
+    <WindowAlias Alias="MenuWidgets/Menubar"                  Target="OrxonoxLook/Menubar" />
+    <WindowAlias Alias="MenuWidgets/MenuItem"                 Target="OrxonoxLook/MenuItem" />
+    <WindowAlias Alias="MenuWidgets/MultiColumnList"          Target="OrxonoxLook/MultiColumnList" />
+    <WindowAlias Alias="MenuWidgets/PopupMenu"                Target="OrxonoxLook/PopupMenu" />
+    <WindowAlias Alias="MenuWidgets/ProgressBar"              Target="OrxonoxLook/ProgressBar" />
+    <WindowAlias Alias="MenuWidgets/Button"                   Target="OrxonoxLook/Button" />
+    <WindowAlias Alias="MenuWidgets/ImageButton"              Target="OrxonoxLook/ImageButton" />
+    <WindowAlias Alias="MenuWidgets/RadioButton"              Target="OrxonoxLook/RadioButton" />
+    <WindowAlias Alias="MenuWidgets/SystemButton"             Target="OrxonoxLook/SystemButton" />
+    <WindowAlias Alias="MenuWidgets/ScrollablePane"           Target="OrxonoxLook/ScrollablePane" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbar"      Target="OrxonoxLook/HorizontalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbar"        Target="OrxonoxLook/VerticalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/Slider"                   Target="OrxonoxLook/Slider" />
+    <WindowAlias Alias="MenuWidgets/Spinner"                  Target="OrxonoxLook/Spinner" />
+    <WindowAlias Alias="MenuWidgets/TabButton"                Target="OrxonoxLook/TabButton" />
+    <WindowAlias Alias="MenuWidgets/TabControl"               Target="OrxonoxLook/TabControl" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbarThumb" Target="OrxonoxLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/SliderThumb"              Target="OrxonoxLook/SliderThumb" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbarThumb"   Target="OrxonoxLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/Titlebar"                 Target="OrxonoxLook/Titlebar" />
+    <WindowAlias Alias="MenuWidgets/Tooltip"                  Target="OrxonoxLook/Tooltip" />
+    <WindowAlias Alias="MenuWidgets/Tree"                     Target="OrxonoxLook/Tree" />
+
+    <WindowAlias Alias="MenuWidgets/JuuButton"                Target="OrxonoxLook/JuuButton" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceHUDWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceHUDWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceHUDWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="SleekSpaceHUDWidgets">
+    <WindowAlias Alias="HUDWidgets/StaticImage"              Target="SleekSpace/StaticImage" />
+    <WindowAlias Alias="HUDWidgets/StaticText"               Target="SleekSpace/StaticText" />
+    <WindowAlias Alias="HUDWidgets/TabButtonPane"            Target="SleekSpace/TabButtonPane" />
+    <WindowAlias Alias="HUDWidgets/TabContentPane"           Target="SleekSpace/TabContentPane" />
+    <WindowAlias Alias="HUDWidgets/Checkbox"                 Target="SleekSpace/Checkbox" />
+    <WindowAlias Alias="HUDWidgets/Combobox"                 Target="SleekSpace/Combobox" />
+    <WindowAlias Alias="HUDWidgets/ComboDropList"            Target="SleekSpace/ComboDropList" />
+    <WindowAlias Alias="HUDWidgets/ComboEditbox"             Target="SleekSpace/ComboEditbox" />
+    <WindowAlias Alias="HUDWidgets/Editbox"                  Target="SleekSpace/Editbox" />
+    <WindowAlias Alias="HUDWidgets/FrameWindow"              Target="SleekSpace/FrameWindow" />
+    <WindowAlias Alias="HUDWidgets/GroupBox"                 Target="SleekSpace/GroupBox" />
+    <WindowAlias Alias="HUDWidgets/ItemListbox"              Target="SleekSpace/ItemListbox" />
+    <WindowAlias Alias="HUDWidgets/ListboxItem"              Target="SleekSpace/ListboxItem" />
+    <WindowAlias Alias="HUDWidgets/Listbox"                  Target="SleekSpace/Listbox" />
+    <WindowAlias Alias="HUDWidgets/ListHeader"               Target="SleekSpace/ListHeader" />
+    <WindowAlias Alias="HUDWidgets/ListHeaderSegment"        Target="SleekSpace/ListHeaderSegment" />
+    <WindowAlias Alias="HUDWidgets/MultiLineEditbox"         Target="SleekSpace/MultiLineEditbox" />
+    <WindowAlias Alias="HUDWidgets/Menubar"                  Target="SleekSpace/Menubar" />
+    <WindowAlias Alias="HUDWidgets/MenuItem"                 Target="SleekSpace/MenuItem" />
+    <WindowAlias Alias="HUDWidgets/MultiColumnList"          Target="SleekSpace/MultiColumnList" />
+    <WindowAlias Alias="HUDWidgets/PopupMenu"                Target="SleekSpace/PopupMenu" />
+    <WindowAlias Alias="HUDWidgets/ProgressBar"              Target="SleekSpace/ProgressBar" />
+    <WindowAlias Alias="HUDWidgets/Button"                   Target="SleekSpace/Button" />
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="SleekSpace/ImageButton" />
+    <WindowAlias Alias="HUDWidgets/RadioButton"              Target="SleekSpace/RadioButton" />
+    <WindowAlias Alias="HUDWidgets/SystemButton"             Target="SleekSpace/SystemButton" />
+    <WindowAlias Alias="HUDWidgets/ScrollablePane"           Target="SleekSpace/ScrollablePane" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbar"      Target="SleekSpace/HorizontalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbar"        Target="SleekSpace/VerticalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/Slider"                   Target="SleekSpace/Slider" />
+    <WindowAlias Alias="HUDWidgets/Spinner"                  Target="SleekSpace/Spinner" />
+    <WindowAlias Alias="HUDWidgets/TabButton"                Target="SleekSpace/TabButton" />
+    <WindowAlias Alias="HUDWidgets/TabControl"               Target="SleekSpace/TabControl" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbarThumb" Target="SleekSpace/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/SliderThumb"              Target="SleekSpace/SliderThumb" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbarThumb"   Target="SleekSpace/VerticalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/Titlebar"                 Target="SleekSpace/Titlebar" />
+    <WindowAlias Alias="HUDWidgets/Tooltip"                  Target="SleekSpace/Tooltip" />
+    <WindowAlias Alias="HUDWidgets/Tree"                     Target="SleekSpace/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceLook.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceLook.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceLook.scheme	(revision 11817)
@@ -0,0 +1,61 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="SleekSpaceLook">
+    <Imageset Name="SleekSpace" Filename="SleekSpace.imageset" />
+    <Imageset Name="TaharezLook" Filename="TaharezLook.imageset" />
+    <LookNFeel Filename="SleekSpace.looknfeel" />
+    <LookNFeel Filename="TaharezLook.looknfeel" />
+    <WindowRendererSet Filename="CEGUIFalagardWRBase" />
+
+    <!-- Standard widgets -->
+    <FalagardMapping WindowType="SleekSpace/StaticImage"                 TargetType="DefaultWindow"           Renderer="Falagard/StaticImage"       LookNFeel="SleekSpace/StaticImage" />
+    <FalagardMapping WindowType="SleekSpace/StaticText"                  TargetType="DefaultWindow"           Renderer="Falagard/StaticText"        LookNFeel="SleekSpace/StaticText" />
+    <FalagardMapping WindowType="SleekSpace/Checkbox"                    TargetType="CEGUI/Checkbox"          Renderer="Falagard/ToggleButton"      LookNFeel="SleekSpace/Checkbox" />
+    <FalagardMapping WindowType="SleekSpace/Combobox"                    TargetType="CEGUI/Combobox"          Renderer="Falagard/Default"           LookNFeel="SleekSpace/Combobox" />
+    <FalagardMapping WindowType="SleekSpace/ComboDropList"               TargetType="CEGUI/ComboDropList"     Renderer="Falagard/Listbox"           LookNFeel="SleekSpace/ComboDropList" />
+    <FalagardMapping WindowType="SleekSpace/ComboEditbox"                TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="SleekSpace/ComboEditbox" />
+    <FalagardMapping WindowType="SleekSpace/Editbox"                     TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="SleekSpace/Editbox" />
+    <FalagardMapping WindowType="SleekSpace/FrameWindow"                 TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="SleekSpace/FrameWindow" />
+    <FalagardMapping WindowType="SleekSpace/Listbox"                     TargetType="CEGUI/Listbox"           Renderer="Falagard/Listbox"           LookNFeel="SleekSpace/Listbox" />
+    <FalagardMapping WindowType="SleekSpace/ListHeader"                  TargetType="CEGUI/ListHeader"        Renderer="Falagard/ListHeader"        LookNFeel="SleekSpace/ListHeader" />
+    <FalagardMapping WindowType="SleekSpace/ListHeaderSegment"           TargetType="CEGUI/ListHeaderSegment" Renderer="Falagard/ListHeaderSegment" LookNFeel="SleekSpace/ListHeaderSegment" />
+    <FalagardMapping WindowType="SleekSpace/MultiLineEditbox"            TargetType="CEGUI/MultiLineEditbox"  Renderer="Falagard/MultiLineEditbox"  LookNFeel="SleekSpace/MultiLineEditbox" />
+    <FalagardMapping WindowType="SleekSpace/Menubar"                     TargetType="CEGUI/Menubar"           Renderer="Falagard/Menubar"           LookNFeel="SleekSpace/Menubar" />
+    <FalagardMapping WindowType="SleekSpace/MenuItem"                    TargetType="CEGUI/MenuItem"          Renderer="Falagard/MenuItem"          LookNFeel="SleekSpace/MenuItem" />
+    <FalagardMapping WindowType="SleekSpace/MultiColumnList"             TargetType="CEGUI/MultiColumnList"   Renderer="Falagard/MultiColumnList"   LookNFeel="SleekSpace/MultiColumnList" />
+    <FalagardMapping WindowType="SleekSpace/PopupMenu"                   TargetType="CEGUI/PopupMenu"         Renderer="Falagard/PopupMenu"         LookNFeel="SleekSpace/PopupMenu" />
+    <FalagardMapping WindowType="SleekSpace/ProgressBar"                 TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="SleekSpace/ProgressBar" />
+    <FalagardMapping WindowType="SleekSpace/Button"                      TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="SleekSpace/Button" />
+    <FalagardMapping WindowType="SleekSpace/RadioButton"                 TargetType="CEGUI/RadioButton"       Renderer="Falagard/ToggleButton"      LookNFeel="SleekSpace/RadioButton" />
+    <FalagardMapping WindowType="SleekSpace/SystemButton"                TargetType="CEGUI/PushButton"        Renderer="Falagard/SystemButton"      LookNFeel="SleekSpace/Button" />
+    <FalagardMapping WindowType="SleekSpace/ScrollablePane"              TargetType="CEGUI/ScrollablePane"    Renderer="Falagard/ScrollablePane"    LookNFeel="SleekSpace/ScrollablePane" />
+    <FalagardMapping WindowType="SleekSpace/HorizontalScrollbar"         TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="SleekSpace/HorizontalScrollbar" />
+    <FalagardMapping WindowType="SleekSpace/VerticalScrollbar"           TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="SleekSpace/VerticalScrollbar" />
+    <FalagardMapping WindowType="SleekSpace/Slider"                      TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="SleekSpace/Slider" />
+    <FalagardMapping WindowType="SleekSpace/Spinner"                     TargetType="CEGUI/Spinner"           Renderer="Falagard/Default"           LookNFeel="SleekSpace/Spinner" />
+    <FalagardMapping WindowType="SleekSpace/TabButton"                   TargetType="CEGUI/TabButton"         Renderer="Falagard/TabButton"         LookNFeel="SleekSpace/TabButton" />
+    <FalagardMapping WindowType="SleekSpace/TabControl"                  TargetType="CEGUI/TabControl"        Renderer="Falagard/TabControl"        LookNFeel="SleekSpace/TabControl" />
+    <FalagardMapping WindowType="SleekSpace/HorizontalScrollbarThumb"    TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="SleekSpace/HorizontalScrollbarThumb" />
+    <FalagardMapping WindowType="SleekSpace/SliderThumb"                 TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="SleekSpace/SliderThumb" />
+    <FalagardMapping WindowType="SleekSpace/VerticalScrollbarThumb"      TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="SleekSpace/VerticalScrollbarThumb" />
+    <FalagardMapping WindowType="SleekSpace/Titlebar"                    TargetType="CEGUI/Titlebar"          Renderer="Falagard/Titlebar"          LookNFeel="SleekSpace/Titlebar" />
+    <FalagardMapping WindowType="SleekSpace/Tooltip"                     TargetType="CEGUI/Tooltip"           Renderer="Falagard/Tooltip"           LookNFeel="SleekSpace/Tooltip" />
+    
+    <!-- Missing widgets (using Taharez LookNFeel) -->
+    <FalagardMapping WindowType="SleekSpace/TabButtonPane"               TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/TabButtonPane" />
+    <FalagardMapping WindowType="SleekSpace/TabContentPane"              TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/TabContentPane" />
+    <FalagardMapping WindowType="SleekSpace/GroupBox"                    TargetType="CEGUI/GroupBox"          Renderer="Falagard/Default"           LookNFeel="TaharezLook/GroupBox" />
+    <FalagardMapping WindowType="SleekSpace/ListboxItem"                 TargetType="CEGUI/ItemEntry"         Renderer="Falagard/ItemEntry"         LookNFeel="TaharezLook/ListboxItem" />
+    <FalagardMapping WindowType="SleekSpace/ItemListbox"                 TargetType="CEGUI/ItemListbox"       Renderer="Falagard/ItemListbox"       LookNFeel="TaharezLook/ItemListbox" />
+    <FalagardMapping WindowType="SleekSpace/ImageButton"                 TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezLook/ImageButton" />
+    <FalagardMapping WindowType="SleekSpace/Tree"                        TargetType="CEGUI/Tree"              Renderer="Falagard/Tree"              LookNFeel="TaharezLook/Tree" />
+
+    <!-- Additional widgets -->
+    <FalagardMapping WindowType="SleekSpace/TabPane"                     TargetType="DefaultWindow"           Renderer="Falagard/TabPane"           LookNFeel="SleekSpace/TabPane" />
+    <FalagardMapping WindowType="SleekSpace/ReticleWindow"               TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="SleekSpace/ReticleWindow" />
+    <FalagardMapping WindowType="SleekSpace/AlternateProgressBar"        TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="SleekSpace/AltProgressBar" />
+    <FalagardMapping WindowType="SleekSpace/VUMeter"                     TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="SleekSpace/VUMeter" />
+    <FalagardMapping WindowType="SleekSpace/LargeVerticalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="SleekSpace/LargeVerticalScrollbar" />
+    <FalagardMapping WindowType="SleekSpace/VSlider"                     TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="SleekSpace/VSlider" />
+    <FalagardMapping WindowType="SleekSpace/LargeVerticalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="SleekSpace/LargeVerticalScrollbarThumb" />
+    <FalagardMapping WindowType="SleekSpace/VSliderThumb"                TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="SleekSpace/VSliderThumb" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceMenuWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceMenuWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/SleekSpaceMenuWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="SleekSpaceMenuWidgets">
+    <WindowAlias Alias="MenuWidgets/StaticImage"              Target="SleekSpace/StaticImage" />
+    <WindowAlias Alias="MenuWidgets/StaticText"               Target="SleekSpace/StaticText" />
+    <WindowAlias Alias="MenuWidgets/TabButtonPane"            Target="SleekSpace/TabButtonPane" />
+    <WindowAlias Alias="MenuWidgets/TabContentPane"           Target="SleekSpace/TabContentPane" />
+    <WindowAlias Alias="MenuWidgets/Checkbox"                 Target="SleekSpace/Checkbox" />
+    <WindowAlias Alias="MenuWidgets/Combobox"                 Target="SleekSpace/Combobox" />
+    <WindowAlias Alias="MenuWidgets/ComboDropList"            Target="SleekSpace/ComboDropList" />
+    <WindowAlias Alias="MenuWidgets/ComboEditbox"             Target="SleekSpace/ComboEditbox" />
+    <WindowAlias Alias="MenuWidgets/Editbox"                  Target="SleekSpace/Editbox" />
+    <WindowAlias Alias="MenuWidgets/FrameWindow"              Target="SleekSpace/FrameWindow" />
+    <WindowAlias Alias="MenuWidgets/GroupBox"                 Target="SleekSpace/GroupBox" />
+    <WindowAlias Alias="MenuWidgets/ItemListbox"              Target="SleekSpace/ItemListbox" />
+    <WindowAlias Alias="MenuWidgets/ListboxItem"              Target="SleekSpace/ListboxItem" />
+    <WindowAlias Alias="MenuWidgets/Listbox"                  Target="SleekSpace/Listbox" />
+    <WindowAlias Alias="MenuWidgets/ListHeader"               Target="SleekSpace/ListHeader" />
+    <WindowAlias Alias="MenuWidgets/ListHeaderSegment"        Target="SleekSpace/ListHeaderSegment" />
+    <WindowAlias Alias="MenuWidgets/MultiLineEditbox"         Target="SleekSpace/MultiLineEditbox" />
+    <WindowAlias Alias="MenuWidgets/Menubar"                  Target="SleekSpace/Menubar" />
+    <WindowAlias Alias="MenuWidgets/MenuItem"                 Target="SleekSpace/MenuItem" />
+    <WindowAlias Alias="MenuWidgets/MultiColumnList"          Target="SleekSpace/MultiColumnList" />
+    <WindowAlias Alias="MenuWidgets/PopupMenu"                Target="SleekSpace/PopupMenu" />
+    <WindowAlias Alias="MenuWidgets/ProgressBar"              Target="SleekSpace/ProgressBar" />
+    <WindowAlias Alias="MenuWidgets/Button"                   Target="SleekSpace/Button" />
+    <WindowAlias Alias="MenuWidgets/ImageButton"              Target="SleekSpace/ImageButton" />
+    <WindowAlias Alias="MenuWidgets/RadioButton"              Target="SleekSpace/RadioButton" />
+    <WindowAlias Alias="MenuWidgets/SystemButton"             Target="SleekSpace/SystemButton" />
+    <WindowAlias Alias="MenuWidgets/ScrollablePane"           Target="SleekSpace/ScrollablePane" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbar"      Target="SleekSpace/HorizontalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbar"        Target="SleekSpace/VerticalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/Slider"                   Target="SleekSpace/Slider" />
+    <WindowAlias Alias="MenuWidgets/Spinner"                  Target="SleekSpace/Spinner" />
+    <WindowAlias Alias="MenuWidgets/TabButton"                Target="SleekSpace/TabButton" />
+    <WindowAlias Alias="MenuWidgets/TabControl"               Target="SleekSpace/TabControl" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbarThumb" Target="SleekSpace/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/SliderThumb"              Target="SleekSpace/SliderThumb" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbarThumb"   Target="SleekSpace/VerticalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/Titlebar"                 Target="SleekSpace/Titlebar" />
+    <WindowAlias Alias="MenuWidgets/Tooltip"                  Target="SleekSpace/Tooltip" />
+    <WindowAlias Alias="MenuWidgets/Tree"                     Target="SleekSpace/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenHUDWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenHUDWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenHUDWidgets.scheme	(revision 11817)
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="TaharezGreenHUDWidgets">
+    <WindowAlias Alias="HUDWidgets/StaticImage"              Target="TaharezGreenLook/StaticImage" />
+    <WindowAlias Alias="HUDWidgets/StaticText"               Target="TaharezGreenLook/StaticText" />
+    <WindowAlias Alias="HUDWidgets/TabButtonPane"            Target="TaharezGreenLook/TabButtonPane" />
+    <WindowAlias Alias="HUDWidgets/TabContentPane"           Target="TaharezGreenLook/TabContentPane" />
+    <WindowAlias Alias="HUDWidgets/Checkbox"                 Target="TaharezGreenLook/Checkbox" />
+    <WindowAlias Alias="HUDWidgets/Combobox"                 Target="TaharezGreenLook/Combobox" />
+    <WindowAlias Alias="HUDWidgets/ComboDropList"            Target="TaharezGreenLook/ComboDropList" />
+    <WindowAlias Alias="HUDWidgets/ComboEditbox"             Target="TaharezGreenLook/ComboEditbox" />
+    <WindowAlias Alias="HUDWidgets/Editbox"                  Target="TaharezGreenLook/Editbox" />
+    <WindowAlias Alias="HUDWidgets/FrameWindow"              Target="TaharezGreenLook/FrameWindow" />
+    <WindowAlias Alias="HUDWidgets/GroupBox"                 Target="TaharezGreenLook/GroupBox" />
+    <WindowAlias Alias="HUDWidgets/ItemListbox"              Target="TaharezGreenLook/ItemListbox" />
+    <WindowAlias Alias="HUDWidgets/ListboxItem"              Target="TaharezGreenLook/ListboxItem" />
+    <WindowAlias Alias="HUDWidgets/Listbox"                  Target="TaharezGreenLook/Listbox" />
+    <WindowAlias Alias="HUDWidgets/ListHeader"               Target="TaharezGreenLook/ListHeader" />
+    <WindowAlias Alias="HUDWidgets/ListHeaderSegment"        Target="TaharezGreenLook/ListHeaderSegment" />
+    <WindowAlias Alias="HUDWidgets/MultiLineEditbox"         Target="TaharezGreenLook/MultiLineEditbox" />
+    <WindowAlias Alias="HUDWidgets/Menubar"                  Target="TaharezGreenLook/Menubar" />
+    <WindowAlias Alias="HUDWidgets/MenuItem"                 Target="TaharezGreenLook/MenuItem" />
+    <WindowAlias Alias="HUDWidgets/MultiColumnList"          Target="TaharezGreenLook/MultiColumnList" />
+    <WindowAlias Alias="HUDWidgets/PopupMenu"                Target="TaharezGreenLook/PopupMenu" />
+    <WindowAlias Alias="HUDWidgets/ProgressBar"              Target="TaharezGreenLook/ProgressBar" />
+    <WindowAlias Alias="HUDWidgets/Button"                   Target="TaharezGreenLook/Button" />
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="TaharezGreenLook/ImageButton" />
+    <WindowAlias Alias="HUDWidgets/RadioButton"              Target="TaharezGreenLook/RadioButton" />
+    <WindowAlias Alias="HUDWidgets/SystemButton"             Target="TaharezGreenLook/SystemButton" />
+    <WindowAlias Alias="HUDWidgets/ScrollablePane"           Target="TaharezGreenLook/ScrollablePane" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbar"      Target="TaharezGreenLook/HorizontalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbar"        Target="TaharezGreenLook/VerticalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/Slider"                   Target="TaharezGreenLook/Slider" />
+    <WindowAlias Alias="HUDWidgets/Spinner"                  Target="TaharezGreenLook/Spinner" />
+    <WindowAlias Alias="HUDWidgets/TabButton"                Target="TaharezGreenLook/TabButton" />
+    <WindowAlias Alias="HUDWidgets/TabControl"               Target="TaharezGreenLook/TabControl" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbarThumb" Target="TaharezGreenLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/SliderThumb"              Target="TaharezGreenLook/SliderThumb" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbarThumb"   Target="TaharezGreenLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/Titlebar"                 Target="TaharezGreenLook/Titlebar" />
+    <WindowAlias Alias="HUDWidgets/Tooltip"                  Target="TaharezGreenLook/Tooltip" />
+    <WindowAlias Alias="HUDWidgets/Tree"                     Target="TaharezGreenLook/Tree" />
+
+     <WindowAlias Alias="HUDWidgets/ImageButton"              Target="TaharezGreenLook/JuuButton" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenLook.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenLook.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenLook.scheme	(revision 11817)
@@ -0,0 +1,56 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="TaharezGreenLook">
+    <Imageset Name="TaharezGreenLook" Filename="TaharezGreenLook.imageset" />
+    <LookNFeel Filename="TaharezGreenLook.looknfeel" />
+    <WindowRendererSet Filename="CEGUIFalagardWRBase" />
+
+    <!-- Standard widgets -->
+    <FalagardMapping WindowType="TaharezGreenLook/StaticImage"              TargetType="DefaultWindow"           Renderer="Falagard/StaticImage"       LookNFeel="TaharezGreenLook/StaticImage" />
+    <FalagardMapping WindowType="TaharezGreenLook/StaticText"               TargetType="DefaultWindow"           Renderer="Falagard/StaticText"        LookNFeel="TaharezGreenLook/StaticText" />
+    <FalagardMapping WindowType="TaharezGreenLook/TabButtonPane"            TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezGreenLook/TabButtonPane" />
+    <FalagardMapping WindowType="TaharezGreenLook/TabContentPane"           TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezGreenLook/TabContentPane" />
+    <FalagardMapping WindowType="TaharezGreenLook/Checkbox"                 TargetType="CEGUI/Checkbox"          Renderer="Falagard/ToggleButton"      LookNFeel="TaharezGreenLook/Checkbox" />
+    <FalagardMapping WindowType="TaharezGreenLook/Combobox"                 TargetType="CEGUI/Combobox"          Renderer="Falagard/Default"           LookNFeel="TaharezGreenLook/Combobox" />
+    <FalagardMapping WindowType="TaharezGreenLook/ComboDropList"            TargetType="CEGUI/ComboDropList"     Renderer="Falagard/Listbox"           LookNFeel="TaharezGreenLook/ComboDropList" />
+    <FalagardMapping WindowType="TaharezGreenLook/ComboEditbox"             TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="TaharezGreenLook/ComboEditbox" />
+    <FalagardMapping WindowType="TaharezGreenLook/Editbox"                  TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="TaharezGreenLook/Editbox" />
+    <FalagardMapping WindowType="TaharezGreenLook/FrameWindow"              TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="TaharezGreenLook/FrameWindow" />
+    <FalagardMapping WindowType="TaharezGreenLook/GroupBox"                 TargetType="CEGUI/GroupBox"          Renderer="Falagard/Default"           LookNFeel="TaharezGreenLook/GroupBox" />
+    <FalagardMapping WindowType="TaharezGreenLook/ItemListbox"              TargetType="CEGUI/ItemListbox"       Renderer="Falagard/ItemListbox"       LookNFeel="TaharezGreenLook/ItemListbox" />
+    <FalagardMapping WindowType="TaharezGreenLook/ListboxItem"              TargetType="CEGUI/ItemEntry"         Renderer="Falagard/ItemEntry"         LookNFeel="TaharezGreenLook/ListboxItem" />
+    <FalagardMapping WindowType="TaharezGreenLook/Listbox"                  TargetType="CEGUI/Listbox"           Renderer="Falagard/Listbox"           LookNFeel="TaharezGreenLook/Listbox" />
+    <FalagardMapping WindowType="TaharezGreenLook/ListHeader"               TargetType="CEGUI/ListHeader"        Renderer="Falagard/ListHeader"        LookNFeel="TaharezGreenLook/ListHeader" />
+    <FalagardMapping WindowType="TaharezGreenLook/ListHeaderSegment"        TargetType="CEGUI/ListHeaderSegment" Renderer="Falagard/ListHeaderSegment" LookNFeel="TaharezGreenLook/ListHeaderSegment" />
+    <FalagardMapping WindowType="TaharezGreenLook/MultiLineEditbox"         TargetType="CEGUI/MultiLineEditbox"  Renderer="Falagard/MultiLineEditbox"  LookNFeel="TaharezGreenLook/MultiLineEditbox" />
+    <FalagardMapping WindowType="TaharezGreenLook/Menubar"                  TargetType="CEGUI/Menubar"           Renderer="Falagard/Menubar"           LookNFeel="TaharezGreenLook/Menubar" />
+    <FalagardMapping WindowType="TaharezGreenLook/MenuItem"                 TargetType="CEGUI/MenuItem"          Renderer="Falagard/MenuItem"          LookNFeel="TaharezGreenLook/MenuItem" />
+    <FalagardMapping WindowType="TaharezGreenLook/MultiColumnList"          TargetType="CEGUI/MultiColumnList"   Renderer="Falagard/MultiColumnList"   LookNFeel="TaharezGreenLook/MultiColumnList" />
+    <FalagardMapping WindowType="TaharezGreenLook/PopupMenu"                TargetType="CEGUI/PopupMenu"         Renderer="Falagard/PopupMenu"         LookNFeel="TaharezGreenLook/PopupMenu" />
+    <FalagardMapping WindowType="TaharezGreenLook/ProgressBar"              TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezGreenLook/ProgressBar" />
+    <FalagardMapping WindowType="TaharezGreenLook/Button"                   TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/Button" />
+    <FalagardMapping WindowType="TaharezGreenLook/ImageButton"              TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/ImageButton" />
+    <FalagardMapping WindowType="TaharezGreenLook/RadioButton"              TargetType="CEGUI/RadioButton"       Renderer="Falagard/ToggleButton"      LookNFeel="TaharezGreenLook/RadioButton" />
+    <FalagardMapping WindowType="TaharezGreenLook/SystemButton"             TargetType="CEGUI/PushButton"        Renderer="Falagard/SystemButton"      LookNFeel="TaharezGreenLook/Button" />
+    <FalagardMapping WindowType="TaharezGreenLook/ScrollablePane"           TargetType="CEGUI/ScrollablePane"    Renderer="Falagard/ScrollablePane"    LookNFeel="TaharezGreenLook/ScrollablePane" />
+    <FalagardMapping WindowType="TaharezGreenLook/HorizontalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="TaharezGreenLook/HorizontalScrollbar" />
+    <FalagardMapping WindowType="TaharezGreenLook/VerticalScrollbar"        TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="TaharezGreenLook/VerticalScrollbar" />
+    <FalagardMapping WindowType="TaharezGreenLook/Slider"                   TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="TaharezGreenLook/Slider" />
+    <FalagardMapping WindowType="TaharezGreenLook/Spinner"                  TargetType="CEGUI/Spinner"           Renderer="Falagard/Default"           LookNFeel="TaharezGreenLook/Spinner" />
+    <FalagardMapping WindowType="TaharezGreenLook/TabButton"                TargetType="CEGUI/TabButton"         Renderer="Falagard/TabButton"         LookNFeel="TaharezGreenLook/TabButton" />
+    <FalagardMapping WindowType="TaharezGreenLook/TabControl"               TargetType="CEGUI/TabControl"        Renderer="Falagard/TabControl"        LookNFeel="TaharezGreenLook/TabControl" />
+    <FalagardMapping WindowType="TaharezGreenLook/HorizontalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/HorizontalScrollbarThumb" />
+    <FalagardMapping WindowType="TaharezGreenLook/SliderThumb"              TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/SliderThumb" />
+    <FalagardMapping WindowType="TaharezGreenLook/VerticalScrollbarThumb"   TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/VerticalScrollbarThumb" />
+    <FalagardMapping WindowType="TaharezGreenLook/Titlebar"                 TargetType="CEGUI/Titlebar"          Renderer="Falagard/Titlebar"          LookNFeel="TaharezGreenLook/Titlebar" />
+    <FalagardMapping WindowType="TaharezGreenLook/Tooltip"                  TargetType="CEGUI/Tooltip"           Renderer="Falagard/Tooltip"           LookNFeel="TaharezGreenLook/Tooltip" />
+    <FalagardMapping WindowType="TaharezGreenLook/Tree"                     TargetType="CEGUI/Tree"              Renderer="Falagard/Tree"              LookNFeel="TaharezGreenLook/Tree" />
+
+    <!-- Additional widgets -->
+    <FalagardMapping WindowType="TaharezGreenLook/AlternateProgressBar"        TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezGreenLook/AltProgressBar" />
+    <FalagardMapping WindowType="TaharezGreenLook/VUMeter"                     TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezGreenLook/VUMeter" />
+    <FalagardMapping WindowType="TaharezGreenLook/LargeVerticalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="TaharezGreenLook/LargeVerticalScrollbar" />
+    <FalagardMapping WindowType="TaharezGreenLook/LargeVerticalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/LargeVerticalScrollbarThumb" />
+
+    <!-- Special Button for CampaignMenu -->
+    <FalagardMapping WindowType="TaharezGreenLook/JuuButton"              TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezGreenLook/JuuButton" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenMenuWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenMenuWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/TaharezGreenMenuWidgets.scheme	(revision 11817)
@@ -0,0 +1,44 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="TaharezGreenMenuWidgets">
+    <WindowAlias Alias="MenuWidgets/StaticImage"              Target="TaharezGreenLook/StaticImage" />
+    <WindowAlias Alias="MenuWidgets/StaticText"               Target="TaharezGreenLook/StaticText" />
+    <WindowAlias Alias="MenuWidgets/TabButtonPane"            Target="TaharezGreenLook/TabButtonPane" />
+    <WindowAlias Alias="MenuWidgets/TabContentPane"           Target="TaharezGreenLook/TabContentPane" />
+    <WindowAlias Alias="MenuWidgets/Checkbox"                 Target="TaharezGreenLook/Checkbox" />
+    <WindowAlias Alias="MenuWidgets/Combobox"                 Target="TaharezGreenLook/Combobox" />
+    <WindowAlias Alias="MenuWidgets/ComboDropList"            Target="TaharezGreenLook/ComboDropList" />
+    <WindowAlias Alias="MenuWidgets/ComboEditbox"             Target="TaharezGreenLook/ComboEditbox" />
+    <WindowAlias Alias="MenuWidgets/Editbox"                  Target="TaharezGreenLook/Editbox" />
+    <WindowAlias Alias="MenuWidgets/FrameWindow"              Target="TaharezGreenLook/FrameWindow" />
+    <WindowAlias Alias="MenuWidgets/GroupBox"                 Target="TaharezGreenLook/GroupBox" />
+    <WindowAlias Alias="MenuWidgets/ItemListbox"              Target="TaharezGreenLook/ItemListbox" />
+    <WindowAlias Alias="MenuWidgets/ListboxItem"              Target="TaharezGreenLook/ListboxItem" />
+    <WindowAlias Alias="MenuWidgets/Listbox"                  Target="TaharezGreenLook/Listbox" />
+    <WindowAlias Alias="MenuWidgets/ListHeader"               Target="TaharezGreenLook/ListHeader" />
+    <WindowAlias Alias="MenuWidgets/ListHeaderSegment"        Target="TaharezGreenLook/ListHeaderSegment" />
+    <WindowAlias Alias="MenuWidgets/MultiLineEditbox"         Target="TaharezGreenLook/MultiLineEditbox" />
+    <WindowAlias Alias="MenuWidgets/Menubar"                  Target="TaharezGreenLook/Menubar" />
+    <WindowAlias Alias="MenuWidgets/MenuItem"                 Target="TaharezGreenLook/MenuItem" />
+    <WindowAlias Alias="MenuWidgets/MultiColumnList"          Target="TaharezGreenLook/MultiColumnList" />
+    <WindowAlias Alias="MenuWidgets/PopupMenu"                Target="TaharezGreenLook/PopupMenu" />
+    <WindowAlias Alias="MenuWidgets/ProgressBar"              Target="TaharezGreenLook/ProgressBar" />
+    <WindowAlias Alias="MenuWidgets/Button"                   Target="TaharezGreenLook/Button" />
+    <WindowAlias Alias="MenuWidgets/ImageButton"              Target="TaharezGreenLook/ImageButton" />
+    <WindowAlias Alias="MenuWidgets/RadioButton"              Target="TaharezGreenLook/RadioButton" />
+    <WindowAlias Alias="MenuWidgets/SystemButton"             Target="TaharezGreenLook/SystemButton" />
+    <WindowAlias Alias="MenuWidgets/ScrollablePane"           Target="TaharezGreenLook/ScrollablePane" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbar"      Target="TaharezGreenLook/HorizontalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbar"        Target="TaharezGreenLook/VerticalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/Slider"                   Target="TaharezGreenLook/Slider" />
+    <WindowAlias Alias="MenuWidgets/Spinner"                  Target="TaharezGreenLook/Spinner" />
+    <WindowAlias Alias="MenuWidgets/TabButton"                Target="TaharezGreenLook/TabButton" />
+    <WindowAlias Alias="MenuWidgets/TabControl"               Target="TaharezGreenLook/TabControl" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbarThumb" Target="TaharezGreenLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/SliderThumb"              Target="TaharezGreenLook/SliderThumb" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbarThumb"   Target="TaharezGreenLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/Titlebar"                 Target="TaharezGreenLook/Titlebar" />
+    <WindowAlias Alias="MenuWidgets/Tooltip"                  Target="TaharezGreenLook/Tooltip" />
+    <WindowAlias Alias="MenuWidgets/Tree"                     Target="TaharezGreenLook/Tree" />
+
+        <WindowAlias Alias="MenuWidgets/JuuButton"                Target="TaharezGreenLook/JuuButton" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/TaharezHUDWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/TaharezHUDWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/TaharezHUDWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="TaharezHUDWidgets">
+    <WindowAlias Alias="HUDWidgets/StaticImage"              Target="TaharezLook/StaticImage" />
+    <WindowAlias Alias="HUDWidgets/StaticText"               Target="TaharezLook/StaticText" />
+    <WindowAlias Alias="HUDWidgets/TabButtonPane"            Target="TaharezLook/TabButtonPane" />
+    <WindowAlias Alias="HUDWidgets/TabContentPane"           Target="TaharezLook/TabContentPane" />
+    <WindowAlias Alias="HUDWidgets/Checkbox"                 Target="TaharezLook/Checkbox" />
+    <WindowAlias Alias="HUDWidgets/Combobox"                 Target="TaharezLook/Combobox" />
+    <WindowAlias Alias="HUDWidgets/ComboDropList"            Target="TaharezLook/ComboDropList" />
+    <WindowAlias Alias="HUDWidgets/ComboEditbox"             Target="TaharezLook/ComboEditbox" />
+    <WindowAlias Alias="HUDWidgets/Editbox"                  Target="TaharezLook/Editbox" />
+    <WindowAlias Alias="HUDWidgets/FrameWindow"              Target="TaharezLook/FrameWindow" />
+    <WindowAlias Alias="HUDWidgets/GroupBox"                 Target="TaharezLook/GroupBox" />
+    <WindowAlias Alias="HUDWidgets/ItemListbox"              Target="TaharezLook/ItemListbox" />
+    <WindowAlias Alias="HUDWidgets/ListboxItem"              Target="TaharezLook/ListboxItem" />
+    <WindowAlias Alias="HUDWidgets/Listbox"                  Target="TaharezLook/Listbox" />
+    <WindowAlias Alias="HUDWidgets/ListHeader"               Target="TaharezLook/ListHeader" />
+    <WindowAlias Alias="HUDWidgets/ListHeaderSegment"        Target="TaharezLook/ListHeaderSegment" />
+    <WindowAlias Alias="HUDWidgets/MultiLineEditbox"         Target="TaharezLook/MultiLineEditbox" />
+    <WindowAlias Alias="HUDWidgets/Menubar"                  Target="TaharezLook/Menubar" />
+    <WindowAlias Alias="HUDWidgets/MenuItem"                 Target="TaharezLook/MenuItem" />
+    <WindowAlias Alias="HUDWidgets/MultiColumnList"          Target="TaharezLook/MultiColumnList" />
+    <WindowAlias Alias="HUDWidgets/PopupMenu"                Target="TaharezLook/PopupMenu" />
+    <WindowAlias Alias="HUDWidgets/ProgressBar"              Target="TaharezLook/ProgressBar" />
+    <WindowAlias Alias="HUDWidgets/Button"                   Target="TaharezLook/Button" />
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="TaharezLook/ImageButton" />
+    <WindowAlias Alias="HUDWidgets/RadioButton"              Target="TaharezLook/RadioButton" />
+    <WindowAlias Alias="HUDWidgets/SystemButton"             Target="TaharezLook/SystemButton" />
+    <WindowAlias Alias="HUDWidgets/ScrollablePane"           Target="TaharezLook/ScrollablePane" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbar"      Target="TaharezLook/HorizontalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbar"        Target="TaharezLook/VerticalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/Slider"                   Target="TaharezLook/Slider" />
+    <WindowAlias Alias="HUDWidgets/Spinner"                  Target="TaharezLook/Spinner" />
+    <WindowAlias Alias="HUDWidgets/TabButton"                Target="TaharezLook/TabButton" />
+    <WindowAlias Alias="HUDWidgets/TabControl"               Target="TaharezLook/TabControl" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbarThumb" Target="TaharezLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/SliderThumb"              Target="TaharezLook/SliderThumb" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbarThumb"   Target="TaharezLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/Titlebar"                 Target="TaharezLook/Titlebar" />
+    <WindowAlias Alias="HUDWidgets/Tooltip"                  Target="TaharezLook/Tooltip" />
+    <WindowAlias Alias="HUDWidgets/Tree"                     Target="TaharezLook/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/TaharezLook.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/TaharezLook.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/TaharezLook.scheme	(revision 11817)
@@ -0,0 +1,54 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="TaharezLook">
+    <Imageset Name="TaharezLook" Filename="TaharezLook.imageset" />
+    <LookNFeel Filename="TaharezLook.looknfeel" />
+    <WindowRendererSet Filename="CEGUIFalagardWRBase" />
+
+    <!-- Standard widgets -->
+    <FalagardMapping WindowType="TaharezLook/StaticImage"              TargetType="DefaultWindow"           Renderer="Falagard/StaticImage"       LookNFeel="TaharezLook/StaticImage" />
+    <FalagardMapping WindowType="TaharezLook/StaticText"               TargetType="DefaultWindow"           Renderer="Falagard/StaticText"        LookNFeel="TaharezLook/StaticText" />
+    <FalagardMapping WindowType="TaharezLook/TabButtonPane"            TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/TabButtonPane" />
+    <FalagardMapping WindowType="TaharezLook/TabContentPane"           TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/TabContentPane" />
+    <FalagardMapping WindowType="TaharezLook/Checkbox"                 TargetType="CEGUI/Checkbox"          Renderer="Falagard/ToggleButton"      LookNFeel="TaharezLook/Checkbox" />
+    <FalagardMapping WindowType="TaharezLook/Combobox"                 TargetType="CEGUI/Combobox"          Renderer="Falagard/Default"           LookNFeel="TaharezLook/Combobox" />
+    <FalagardMapping WindowType="TaharezLook/ComboDropList"            TargetType="CEGUI/ComboDropList"     Renderer="Falagard/Listbox"           LookNFeel="TaharezLook/ComboDropList" />
+    <FalagardMapping WindowType="TaharezLook/ComboEditbox"             TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="TaharezLook/ComboEditbox" />
+    <FalagardMapping WindowType="TaharezLook/Editbox"                  TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="TaharezLook/Editbox" />
+    <FalagardMapping WindowType="TaharezLook/FrameWindow"              TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="TaharezLook/FrameWindow" />
+    <FalagardMapping WindowType="TaharezLook/GroupBox"                 TargetType="CEGUI/GroupBox"          Renderer="Falagard/Default"           LookNFeel="TaharezLook/GroupBox" />
+    <FalagardMapping WindowType="TaharezLook/ItemListbox"              TargetType="CEGUI/ItemListbox"       Renderer="Falagard/ItemListbox"       LookNFeel="TaharezLook/ItemListbox" />
+    <FalagardMapping WindowType="TaharezLook/ListboxItem"              TargetType="CEGUI/ItemEntry"         Renderer="Falagard/ItemEntry"         LookNFeel="TaharezLook/ListboxItem" />
+    <FalagardMapping WindowType="TaharezLook/Listbox"                  TargetType="CEGUI/Listbox"           Renderer="Falagard/Listbox"           LookNFeel="TaharezLook/Listbox" />
+    <FalagardMapping WindowType="TaharezLook/ListHeader"               TargetType="CEGUI/ListHeader"        Renderer="Falagard/ListHeader"        LookNFeel="TaharezLook/ListHeader" />
+    <FalagardMapping WindowType="TaharezLook/ListHeaderSegment"        TargetType="CEGUI/ListHeaderSegment" Renderer="Falagard/ListHeaderSegment" LookNFeel="TaharezLook/ListHeaderSegment" />
+    <FalagardMapping WindowType="TaharezLook/MultiLineEditbox"         TargetType="CEGUI/MultiLineEditbox"  Renderer="Falagard/MultiLineEditbox"  LookNFeel="TaharezLook/MultiLineEditbox" />
+    <FalagardMapping WindowType="TaharezLook/Menubar"                  TargetType="CEGUI/Menubar"           Renderer="Falagard/Menubar"           LookNFeel="TaharezLook/Menubar" />
+    <FalagardMapping WindowType="TaharezLook/MenuItem"                 TargetType="CEGUI/MenuItem"          Renderer="Falagard/MenuItem"          LookNFeel="TaharezLook/MenuItem" />
+    <FalagardMapping WindowType="TaharezLook/MultiColumnList"          TargetType="CEGUI/MultiColumnList"   Renderer="Falagard/MultiColumnList"   LookNFeel="TaharezLook/MultiColumnList" />
+    <FalagardMapping WindowType="TaharezLook/PopupMenu"                TargetType="CEGUI/PopupMenu"         Renderer="Falagard/PopupMenu"         LookNFeel="TaharezLook/PopupMenu" />
+    <FalagardMapping WindowType="TaharezLook/ProgressBar"              TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezLook/ProgressBar" />
+    <FalagardMapping WindowType="TaharezLook/Button"                   TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezLook/Button" />
+    <FalagardMapping WindowType="TaharezLook/ImageButton"              TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezLook/ImageButton" />
+    <FalagardMapping WindowType="TaharezLook/RadioButton"              TargetType="CEGUI/RadioButton"       Renderer="Falagard/ToggleButton"      LookNFeel="TaharezLook/RadioButton" />
+    <FalagardMapping WindowType="TaharezLook/SystemButton"             TargetType="CEGUI/PushButton"        Renderer="Falagard/SystemButton"      LookNFeel="TaharezLook/Button" />
+    <FalagardMapping WindowType="TaharezLook/ScrollablePane"           TargetType="CEGUI/ScrollablePane"    Renderer="Falagard/ScrollablePane"    LookNFeel="TaharezLook/ScrollablePane" />
+    <FalagardMapping WindowType="TaharezLook/HorizontalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="TaharezLook/HorizontalScrollbar" />
+    <FalagardMapping WindowType="TaharezLook/VerticalScrollbar"        TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="TaharezLook/VerticalScrollbar" />
+    <FalagardMapping WindowType="TaharezLook/Slider"                   TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="TaharezLook/Slider" />
+    <FalagardMapping WindowType="TaharezLook/Spinner"                  TargetType="CEGUI/Spinner"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/Spinner" />
+    <FalagardMapping WindowType="TaharezLook/TabButton"                TargetType="CEGUI/TabButton"         Renderer="Falagard/TabButton"         LookNFeel="TaharezLook/TabButton" />
+    <FalagardMapping WindowType="TaharezLook/TabControl"               TargetType="CEGUI/TabControl"        Renderer="Falagard/TabControl"        LookNFeel="TaharezLook/TabControl" />
+    <FalagardMapping WindowType="TaharezLook/HorizontalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezLook/HorizontalScrollbarThumb" />
+    <FalagardMapping WindowType="TaharezLook/SliderThumb"              TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezLook/SliderThumb" />
+    <FalagardMapping WindowType="TaharezLook/VerticalScrollbarThumb"   TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezLook/VerticalScrollbarThumb" />
+    <FalagardMapping WindowType="TaharezLook/Titlebar"                 TargetType="CEGUI/Titlebar"          Renderer="Falagard/Titlebar"          LookNFeel="TaharezLook/Titlebar" />
+    <FalagardMapping WindowType="TaharezLook/Tooltip"                  TargetType="CEGUI/Tooltip"           Renderer="Falagard/Tooltip"           LookNFeel="TaharezLook/Tooltip" />
+    <FalagardMapping WindowType="TaharezLook/Tree"                     TargetType="CEGUI/Tree"              Renderer="Falagard/Tree"              LookNFeel="TaharezLook/Tree" />
+
+    <!-- Additional widgets -->
+    <FalagardMapping WindowType="TaharezLook/AlternateProgressBar"        TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezLook/AltProgressBar" />
+    <FalagardMapping WindowType="TaharezLook/VUMeter"                     TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezLook/VUMeter" />
+    <FalagardMapping WindowType="TaharezLook/LargeVerticalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="TaharezLook/LargeVerticalScrollbar" />
+    <FalagardMapping WindowType="TaharezLook/LargeVerticalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezLook/LargeVerticalScrollbarThumb" />
+    
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/TaharezMenuWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/TaharezMenuWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/TaharezMenuWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="TaharezMenuWidgets">
+    <WindowAlias Alias="MenuWidgets/StaticImage"              Target="TaharezLook/StaticImage" />
+    <WindowAlias Alias="MenuWidgets/StaticText"               Target="TaharezLook/StaticText" />
+    <WindowAlias Alias="MenuWidgets/TabButtonPane"            Target="TaharezLook/TabButtonPane" />
+    <WindowAlias Alias="MenuWidgets/TabContentPane"           Target="TaharezLook/TabContentPane" />
+    <WindowAlias Alias="MenuWidgets/Checkbox"                 Target="TaharezLook/Checkbox" />
+    <WindowAlias Alias="MenuWidgets/Combobox"                 Target="TaharezLook/Combobox" />
+    <WindowAlias Alias="MenuWidgets/ComboDropList"            Target="TaharezLook/ComboDropList" />
+    <WindowAlias Alias="MenuWidgets/ComboEditbox"             Target="TaharezLook/ComboEditbox" />
+    <WindowAlias Alias="MenuWidgets/Editbox"                  Target="TaharezLook/Editbox" />
+    <WindowAlias Alias="MenuWidgets/FrameWindow"              Target="TaharezLook/FrameWindow" />
+    <WindowAlias Alias="MenuWidgets/GroupBox"                 Target="TaharezLook/GroupBox" />
+    <WindowAlias Alias="MenuWidgets/ItemListbox"              Target="TaharezLook/ItemListbox" />
+    <WindowAlias Alias="MenuWidgets/ListboxItem"              Target="TaharezLook/ListboxItem" />
+    <WindowAlias Alias="MenuWidgets/Listbox"                  Target="TaharezLook/Listbox" />
+    <WindowAlias Alias="MenuWidgets/ListHeader"               Target="TaharezLook/ListHeader" />
+    <WindowAlias Alias="MenuWidgets/ListHeaderSegment"        Target="TaharezLook/ListHeaderSegment" />
+    <WindowAlias Alias="MenuWidgets/MultiLineEditbox"         Target="TaharezLook/MultiLineEditbox" />
+    <WindowAlias Alias="MenuWidgets/Menubar"                  Target="TaharezLook/Menubar" />
+    <WindowAlias Alias="MenuWidgets/MenuItem"                 Target="TaharezLook/MenuItem" />
+    <WindowAlias Alias="MenuWidgets/MultiColumnList"          Target="TaharezLook/MultiColumnList" />
+    <WindowAlias Alias="MenuWidgets/PopupMenu"                Target="TaharezLook/PopupMenu" />
+    <WindowAlias Alias="MenuWidgets/ProgressBar"              Target="TaharezLook/ProgressBar" />
+    <WindowAlias Alias="MenuWidgets/Button"                   Target="TaharezLook/Button" />
+    <WindowAlias Alias="MenuWidgets/ImageButton"              Target="TaharezLook/ImageButton" />
+    <WindowAlias Alias="MenuWidgets/RadioButton"              Target="TaharezLook/RadioButton" />
+    <WindowAlias Alias="MenuWidgets/SystemButton"             Target="TaharezLook/SystemButton" />
+    <WindowAlias Alias="MenuWidgets/ScrollablePane"           Target="TaharezLook/ScrollablePane" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbar"      Target="TaharezLook/HorizontalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbar"        Target="TaharezLook/VerticalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/Slider"                   Target="TaharezLook/Slider" />
+    <WindowAlias Alias="MenuWidgets/Spinner"                  Target="TaharezLook/Spinner" />
+    <WindowAlias Alias="MenuWidgets/TabButton"                Target="TaharezLook/TabButton" />
+    <WindowAlias Alias="MenuWidgets/TabControl"               Target="TaharezLook/TabControl" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbarThumb" Target="TaharezLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/SliderThumb"              Target="TaharezLook/SliderThumb" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbarThumb"   Target="TaharezLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/Titlebar"                 Target="TaharezLook/Titlebar" />
+    <WindowAlias Alias="MenuWidgets/Tooltip"                  Target="TaharezLook/Tooltip" />
+    <WindowAlias Alias="MenuWidgets/Tree"                     Target="TaharezLook/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/VanillaHUDWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/VanillaHUDWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/VanillaHUDWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="VanillaHUDWidgets">
+    <WindowAlias Alias="HUDWidgets/StaticImage"              Target="Vanilla/StaticImage" />
+    <WindowAlias Alias="HUDWidgets/StaticText"               Target="Vanilla/StaticText" />
+    <WindowAlias Alias="HUDWidgets/TabButtonPane"            Target="Vanilla/TabButtonPane" />
+    <WindowAlias Alias="HUDWidgets/TabContentPane"           Target="Vanilla/TabContentPane" />
+    <WindowAlias Alias="HUDWidgets/Checkbox"                 Target="Vanilla/Checkbox" />
+    <WindowAlias Alias="HUDWidgets/Combobox"                 Target="Vanilla/Combobox" />
+    <WindowAlias Alias="HUDWidgets/ComboDropList"            Target="Vanilla/ComboDropList" />
+    <WindowAlias Alias="HUDWidgets/ComboEditbox"             Target="Vanilla/ComboEditbox" />
+    <WindowAlias Alias="HUDWidgets/Editbox"                  Target="Vanilla/Editbox" />
+    <WindowAlias Alias="HUDWidgets/FrameWindow"              Target="Vanilla/FrameWindow" />
+    <WindowAlias Alias="HUDWidgets/GroupBox"                 Target="Vanilla/GroupBox" />
+    <WindowAlias Alias="HUDWidgets/ItemListbox"              Target="Vanilla/ItemListbox" />
+    <WindowAlias Alias="HUDWidgets/ListboxItem"              Target="Vanilla/ListboxItem" />
+    <WindowAlias Alias="HUDWidgets/Listbox"                  Target="Vanilla/Listbox" />
+    <WindowAlias Alias="HUDWidgets/ListHeader"               Target="Vanilla/ListHeader" />
+    <WindowAlias Alias="HUDWidgets/ListHeaderSegment"        Target="Vanilla/ListHeaderSegment" />
+    <WindowAlias Alias="HUDWidgets/MultiLineEditbox"         Target="Vanilla/MultiLineEditbox" />
+    <WindowAlias Alias="HUDWidgets/Menubar"                  Target="Vanilla/Menubar" />
+    <WindowAlias Alias="HUDWidgets/MenuItem"                 Target="Vanilla/MenuItem" />
+    <WindowAlias Alias="HUDWidgets/MultiColumnList"          Target="Vanilla/MultiColumnList" />
+    <WindowAlias Alias="HUDWidgets/PopupMenu"                Target="Vanilla/PopupMenu" />
+    <WindowAlias Alias="HUDWidgets/ProgressBar"              Target="Vanilla/ProgressBar" />
+    <WindowAlias Alias="HUDWidgets/Button"                   Target="Vanilla/Button" />
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="Vanilla/ImageButton" />
+    <WindowAlias Alias="HUDWidgets/RadioButton"              Target="Vanilla/RadioButton" />
+    <WindowAlias Alias="HUDWidgets/SystemButton"             Target="Vanilla/SystemButton" />
+    <WindowAlias Alias="HUDWidgets/ScrollablePane"           Target="Vanilla/ScrollablePane" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbar"      Target="Vanilla/HorizontalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbar"        Target="Vanilla/VerticalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/Slider"                   Target="Vanilla/Slider" />
+    <WindowAlias Alias="HUDWidgets/Spinner"                  Target="Vanilla/Spinner" />
+    <WindowAlias Alias="HUDWidgets/TabButton"                Target="Vanilla/TabButton" />
+    <WindowAlias Alias="HUDWidgets/TabControl"               Target="Vanilla/TabControl" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbarThumb" Target="Vanilla/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/SliderThumb"              Target="Vanilla/SliderThumb" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbarThumb"   Target="Vanilla/VerticalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/Titlebar"                 Target="Vanilla/Titlebar" />
+    <WindowAlias Alias="HUDWidgets/Tooltip"                  Target="Vanilla/Tooltip" />
+    <WindowAlias Alias="HUDWidgets/Tree"                     Target="Vanilla/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/VanillaLook.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/VanillaLook.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/VanillaLook.scheme	(revision 11817)
@@ -0,0 +1,53 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="VanillaLook">
+    <Imageset Name="Vanilla-Images" Filename="Vanilla.imageset" />
+    <Imageset Name="TaharezLook"    Filename="TaharezLook.imageset" />
+    <LookNFeel Filename="Vanilla.looknfeel" />
+    <LookNFeel Filename="TaharezLook.looknfeel" />
+    <WindowRendererSet Filename="CEGUIFalagardWRBase" />
+
+    <!-- Standard widgets -->
+    <FalagardMapping WindowType="Vanilla/StaticImage"              TargetType="DefaultWindow"           Renderer="Falagard/StaticImage"       LookNFeel="Vanilla/StaticImage" />
+    <FalagardMapping WindowType="Vanilla/StaticText"               TargetType="DefaultWindow"           Renderer="Falagard/StaticText"        LookNFeel="Vanilla/StaticText" />
+    <FalagardMapping WindowType="Vanilla/Editbox"                  TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="Vanilla/Editbox" />
+    <FalagardMapping WindowType="Vanilla/FrameWindow"              TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="Vanilla/FrameWindow" />
+    <FalagardMapping WindowType="Vanilla/Listbox"                  TargetType="CEGUI/Listbox"           Renderer="Falagard/Listbox"           LookNFeel="Vanilla/Listbox" />
+    <FalagardMapping WindowType="Vanilla/MultiLineEditbox"         TargetType="CEGUI/MultiLineEditbox"  Renderer="Falagard/MultiLineEditbox"  LookNFeel="Vanilla/MultiLineEditbox" />
+    <FalagardMapping WindowType="Vanilla/Button"                   TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="Vanilla/Button" />
+    <FalagardMapping WindowType="Vanilla/HorizontalScrollbar"      TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="Vanilla/HorizontalScrollbar" />
+    <FalagardMapping WindowType="Vanilla/VerticalScrollbar"        TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="Vanilla/VerticalScrollbar" />
+    <FalagardMapping WindowType="Vanilla/HorizontalScrollbarThumb" TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="Vanilla/HorizontalScrollbarThumb" />
+    <FalagardMapping WindowType="Vanilla/VerticalScrollbarThumb"   TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="Vanilla/VerticalScrollbarThumb" />
+    <FalagardMapping WindowType="Vanilla/Titlebar"                 TargetType="CEGUI/Titlebar"          Renderer="Falagard/Titlebar"          LookNFeel="Vanilla/Titlebar" />
+
+    <!-- Missing widgets (using Taharez LookNFeel) -->
+    <FalagardMapping WindowType="Vanilla/TabButtonPane"            TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/TabButtonPane" />
+    <FalagardMapping WindowType="Vanilla/TabContentPane"           TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/TabContentPane" />
+    <FalagardMapping WindowType="Vanilla/Checkbox"                 TargetType="CEGUI/Checkbox"          Renderer="Falagard/ToggleButton"      LookNFeel="TaharezLook/Checkbox" />
+    <FalagardMapping WindowType="Vanilla/Combobox"                 TargetType="CEGUI/Combobox"          Renderer="Falagard/Default"           LookNFeel="TaharezLook/Combobox" />
+    <FalagardMapping WindowType="Vanilla/ComboDropList"            TargetType="CEGUI/ComboDropList"     Renderer="Falagard/Listbox"           LookNFeel="TaharezLook/ComboDropList" />
+    <FalagardMapping WindowType="Vanilla/ComboEditbox"             TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="TaharezLook/ComboEditbox" />
+    <FalagardMapping WindowType="Vanilla/GroupBox"                 TargetType="CEGUI/GroupBox"          Renderer="Falagard/Default"           LookNFeel="TaharezLook/GroupBox" />
+    <FalagardMapping WindowType="Vanilla/ItemListbox"              TargetType="CEGUI/ItemListbox"       Renderer="Falagard/ItemListbox"       LookNFeel="TaharezLook/ItemListbox" />
+    <FalagardMapping WindowType="Vanilla/ListboxItem"              TargetType="CEGUI/ItemEntry"         Renderer="Falagard/ItemEntry"         LookNFeel="TaharezLook/ListboxItem" />
+    <FalagardMapping WindowType="Vanilla/ListHeader"               TargetType="CEGUI/ListHeader"        Renderer="Falagard/ListHeader"        LookNFeel="TaharezLook/ListHeader" />
+    <FalagardMapping WindowType="Vanilla/ListHeaderSegment"        TargetType="CEGUI/ListHeaderSegment" Renderer="Falagard/ListHeaderSegment" LookNFeel="TaharezLook/ListHeaderSegment" />
+    <FalagardMapping WindowType="Vanilla/Menubar"                  TargetType="CEGUI/Menubar"           Renderer="Falagard/Menubar"           LookNFeel="TaharezLook/Menubar" />
+    <FalagardMapping WindowType="Vanilla/MenuItem"                 TargetType="CEGUI/MenuItem"          Renderer="Falagard/MenuItem"          LookNFeel="TaharezLook/MenuItem" />
+    <FalagardMapping WindowType="Vanilla/MultiColumnList"          TargetType="CEGUI/MultiColumnList"   Renderer="Falagard/MultiColumnList"   LookNFeel="TaharezLook/MultiColumnList" />
+    <FalagardMapping WindowType="Vanilla/PopupMenu"                TargetType="CEGUI/PopupMenu"         Renderer="Falagard/PopupMenu"         LookNFeel="TaharezLook/PopupMenu" />
+    <FalagardMapping WindowType="Vanilla/ProgressBar"              TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="TaharezLook/ProgressBar" />
+    <FalagardMapping WindowType="Vanilla/ImageButton"              TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezLook/ImageButton" />
+    <FalagardMapping WindowType="Vanilla/RadioButton"              TargetType="CEGUI/RadioButton"       Renderer="Falagard/ToggleButton"      LookNFeel="TaharezLook/RadioButton" />
+    <FalagardMapping WindowType="Vanilla/SystemButton"             TargetType="CEGUI/PushButton"        Renderer="Falagard/SystemButton"      LookNFeel="TaharezLook/Button" />
+    <FalagardMapping WindowType="Vanilla/ScrollablePane"           TargetType="CEGUI/ScrollablePane"    Renderer="Falagard/ScrollablePane"    LookNFeel="TaharezLook/ScrollablePane" />
+    <FalagardMapping WindowType="Vanilla/Slider"                   TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="TaharezLook/Slider" />
+    <FalagardMapping WindowType="Vanilla/Spinner"                  TargetType="CEGUI/Spinner"           Renderer="Falagard/Default"           LookNFeel="TaharezLook/Spinner" />
+    <FalagardMapping WindowType="Vanilla/TabButton"                TargetType="CEGUI/TabButton"         Renderer="Falagard/TabButton"         LookNFeel="TaharezLook/TabButton" />
+    <FalagardMapping WindowType="Vanilla/TabControl"               TargetType="CEGUI/TabControl"        Renderer="Falagard/TabControl"        LookNFeel="TaharezLook/TabControl" />
+    <FalagardMapping WindowType="Vanilla/SliderThumb"              TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="TaharezLook/SliderThumb" />
+    <FalagardMapping WindowType="Vanilla/Tooltip"                  TargetType="CEGUI/Tooltip"           Renderer="Falagard/Tooltip"           LookNFeel="TaharezLook/Tooltip" />
+    <FalagardMapping WindowType="Vanilla/Tree"                     TargetType="CEGUI/Tree"              Renderer="Falagard/Tree"              LookNFeel="TaharezLook/Tree" />
+    
+    <!-- Additional widgets -->
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/VanillaMenuWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/VanillaMenuWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/VanillaMenuWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="VanillaMenuWidgets">
+    <WindowAlias Alias="MenuWidgets/StaticImage"              Target="Vanilla/StaticImage" />
+    <WindowAlias Alias="MenuWidgets/StaticText"               Target="Vanilla/StaticText" />
+    <WindowAlias Alias="MenuWidgets/TabButtonPane"            Target="Vanilla/TabButtonPane" />
+    <WindowAlias Alias="MenuWidgets/TabContentPane"           Target="Vanilla/TabContentPane" />
+    <WindowAlias Alias="MenuWidgets/Checkbox"                 Target="Vanilla/Checkbox" />
+    <WindowAlias Alias="MenuWidgets/Combobox"                 Target="Vanilla/Combobox" />
+    <WindowAlias Alias="MenuWidgets/ComboDropList"            Target="Vanilla/ComboDropList" />
+    <WindowAlias Alias="MenuWidgets/ComboEditbox"             Target="Vanilla/ComboEditbox" />
+    <WindowAlias Alias="MenuWidgets/Editbox"                  Target="Vanilla/Editbox" />
+    <WindowAlias Alias="MenuWidgets/FrameWindow"              Target="Vanilla/FrameWindow" />
+    <WindowAlias Alias="MenuWidgets/GroupBox"                 Target="Vanilla/GroupBox" />
+    <WindowAlias Alias="MenuWidgets/ItemListbox"              Target="Vanilla/ItemListbox" />
+    <WindowAlias Alias="MenuWidgets/ListboxItem"              Target="Vanilla/ListboxItem" />
+    <WindowAlias Alias="MenuWidgets/Listbox"                  Target="Vanilla/Listbox" />
+    <WindowAlias Alias="MenuWidgets/ListHeader"               Target="Vanilla/ListHeader" />
+    <WindowAlias Alias="MenuWidgets/ListHeaderSegment"        Target="Vanilla/ListHeaderSegment" />
+    <WindowAlias Alias="MenuWidgets/MultiLineEditbox"         Target="Vanilla/MultiLineEditbox" />
+    <WindowAlias Alias="MenuWidgets/Menubar"                  Target="Vanilla/Menubar" />
+    <WindowAlias Alias="MenuWidgets/MenuItem"                 Target="Vanilla/MenuItem" />
+    <WindowAlias Alias="MenuWidgets/MultiColumnList"          Target="Vanilla/MultiColumnList" />
+    <WindowAlias Alias="MenuWidgets/PopupMenu"                Target="Vanilla/PopupMenu" />
+    <WindowAlias Alias="MenuWidgets/ProgressBar"              Target="Vanilla/ProgressBar" />
+    <WindowAlias Alias="MenuWidgets/Button"                   Target="Vanilla/Button" />
+    <WindowAlias Alias="MenuWidgets/ImageButton"              Target="Vanilla/ImageButton" />
+    <WindowAlias Alias="MenuWidgets/RadioButton"              Target="Vanilla/RadioButton" />
+    <WindowAlias Alias="MenuWidgets/SystemButton"             Target="Vanilla/SystemButton" />
+    <WindowAlias Alias="MenuWidgets/ScrollablePane"           Target="Vanilla/ScrollablePane" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbar"      Target="Vanilla/HorizontalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbar"        Target="Vanilla/VerticalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/Slider"                   Target="Vanilla/Slider" />
+    <WindowAlias Alias="MenuWidgets/Spinner"                  Target="Vanilla/Spinner" />
+    <WindowAlias Alias="MenuWidgets/TabButton"                Target="Vanilla/TabButton" />
+    <WindowAlias Alias="MenuWidgets/TabControl"               Target="Vanilla/TabControl" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbarThumb" Target="Vanilla/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/SliderThumb"              Target="Vanilla/SliderThumb" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbarThumb"   Target="Vanilla/VerticalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/Titlebar"                 Target="Vanilla/Titlebar" />
+    <WindowAlias Alias="MenuWidgets/Tooltip"                  Target="Vanilla/Tooltip" />
+    <WindowAlias Alias="MenuWidgets/Tree"                     Target="Vanilla/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/WindowsHUDWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/WindowsHUDWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/WindowsHUDWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="WindowsHUDWidgets">
+    <WindowAlias Alias="HUDWidgets/StaticImage"              Target="WindowsLook/StaticImage" />
+    <WindowAlias Alias="HUDWidgets/StaticText"               Target="WindowsLook/StaticText" />
+    <WindowAlias Alias="HUDWidgets/TabButtonPane"            Target="WindowsLook/TabButtonPane" />
+    <WindowAlias Alias="HUDWidgets/TabContentPane"           Target="WindowsLook/TabContentPane" />
+    <WindowAlias Alias="HUDWidgets/Checkbox"                 Target="WindowsLook/Checkbox" />
+    <WindowAlias Alias="HUDWidgets/Combobox"                 Target="WindowsLook/Combobox" />
+    <WindowAlias Alias="HUDWidgets/ComboDropList"            Target="WindowsLook/ComboDropList" />
+    <WindowAlias Alias="HUDWidgets/ComboEditbox"             Target="WindowsLook/ComboEditbox" />
+    <WindowAlias Alias="HUDWidgets/Editbox"                  Target="WindowsLook/Editbox" />
+    <WindowAlias Alias="HUDWidgets/FrameWindow"              Target="WindowsLook/FrameWindow" />
+    <WindowAlias Alias="HUDWidgets/GroupBox"                 Target="WindowsLook/GroupBox" />
+    <WindowAlias Alias="HUDWidgets/ItemListbox"              Target="WindowsLook/ItemListbox" />
+    <WindowAlias Alias="HUDWidgets/ListboxItem"              Target="WindowsLook/ListboxItem" />
+    <WindowAlias Alias="HUDWidgets/Listbox"                  Target="WindowsLook/Listbox" />
+    <WindowAlias Alias="HUDWidgets/ListHeader"               Target="WindowsLook/ListHeader" />
+    <WindowAlias Alias="HUDWidgets/ListHeaderSegment"        Target="WindowsLook/ListHeaderSegment" />
+    <WindowAlias Alias="HUDWidgets/MultiLineEditbox"         Target="WindowsLook/MultiLineEditbox" />
+    <WindowAlias Alias="HUDWidgets/Menubar"                  Target="WindowsLook/Menubar" />
+    <WindowAlias Alias="HUDWidgets/MenuItem"                 Target="WindowsLook/MenuItem" />
+    <WindowAlias Alias="HUDWidgets/MultiColumnList"          Target="WindowsLook/MultiColumnList" />
+    <WindowAlias Alias="HUDWidgets/PopupMenu"                Target="WindowsLook/PopupMenu" />
+    <WindowAlias Alias="HUDWidgets/ProgressBar"              Target="WindowsLook/ProgressBar" />
+    <WindowAlias Alias="HUDWidgets/Button"                   Target="WindowsLook/Button" />
+    <WindowAlias Alias="HUDWidgets/ImageButton"              Target="WindowsLook/ImageButton" />
+    <WindowAlias Alias="HUDWidgets/RadioButton"              Target="WindowsLook/RadioButton" />
+    <WindowAlias Alias="HUDWidgets/SystemButton"             Target="WindowsLook/SystemButton" />
+    <WindowAlias Alias="HUDWidgets/ScrollablePane"           Target="WindowsLook/ScrollablePane" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbar"      Target="WindowsLook/HorizontalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbar"        Target="WindowsLook/VerticalScrollbar" />
+    <WindowAlias Alias="HUDWidgets/Slider"                   Target="WindowsLook/Slider" />
+    <WindowAlias Alias="HUDWidgets/Spinner"                  Target="WindowsLook/Spinner" />
+    <WindowAlias Alias="HUDWidgets/TabButton"                Target="WindowsLook/TabButton" />
+    <WindowAlias Alias="HUDWidgets/TabControl"               Target="WindowsLook/TabControl" />
+    <WindowAlias Alias="HUDWidgets/HorizontalScrollbarThumb" Target="WindowsLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/SliderThumb"              Target="WindowsLook/SliderThumb" />
+    <WindowAlias Alias="HUDWidgets/VerticalScrollbarThumb"   Target="WindowsLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="HUDWidgets/Titlebar"                 Target="WindowsLook/Titlebar" />
+    <WindowAlias Alias="HUDWidgets/Tooltip"                  Target="WindowsLook/Tooltip" />
+    <WindowAlias Alias="HUDWidgets/Tree"                     Target="WindowsLook/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/WindowsLook.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/WindowsLook.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/WindowsLook.scheme	(revision 11817)
@@ -0,0 +1,55 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="WindowsLook">
+    <Imageset Name="WindowsLook" Filename="WindowsLook.imageset" />
+    <Imageset Name="TaharezLook" Filename="TaharezLook.imageset" />
+    <LookNFeel Filename="WindowsLook.looknfeel" />
+    <LookNFeel Filename="TaharezLook.looknfeel" />
+    <WindowRendererSet Filename="CEGUIFalagardWRBase" />
+
+    <!-- Standard widgets -->
+    <FalagardMapping WindowType="WindowsLook/StaticImage"                 TargetType="DefaultWindow"           Renderer="Falagard/StaticImage"       LookNFeel="WindowsLook/StaticImage" />
+    <FalagardMapping WindowType="WindowsLook/StaticText"                  TargetType="DefaultWindow"           Renderer="Falagard/StaticText"        LookNFeel="WindowsLook/StaticText" />
+    <FalagardMapping WindowType="WindowsLook/TabButtonPane"               TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="WindowsLook/TabButtonPane" />
+    <FalagardMapping WindowType="WindowsLook/TabContentPane"              TargetType="DefaultWindow"           Renderer="Falagard/Default"           LookNFeel="WindowsLook/TabContentPane" />
+    <FalagardMapping WindowType="WindowsLook/Checkbox"                    TargetType="CEGUI/Checkbox"          Renderer="Falagard/ToggleButton"      LookNFeel="WindowsLook/Checkbox" />
+    <FalagardMapping WindowType="WindowsLook/Combobox"                    TargetType="CEGUI/Combobox"          Renderer="Falagard/Default"           LookNFeel="WindowsLook/Combobox" />
+    <FalagardMapping WindowType="WindowsLook/ComboDropList"               TargetType="CEGUI/ComboDropList"     Renderer="Falagard/Listbox"           LookNFeel="WindowsLook/ComboDropList" />
+    <FalagardMapping WindowType="WindowsLook/Editbox"                     TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="WindowsLook/Editbox" />
+    <FalagardMapping WindowType="WindowsLook/FrameWindow"                 TargetType="CEGUI/FrameWindow"       Renderer="Falagard/FrameWindow"       LookNFeel="WindowsLook/FrameWindow" />
+    <FalagardMapping WindowType="WindowsLook/GroupBox"                    TargetType="CEGUI/GroupBox"          Renderer="Falagard/Default"           LookNFeel="WindowsLook/GroupBox" />
+    <FalagardMapping WindowType="WindowsLook/ItemListbox"                 TargetType="CEGUI/ItemListbox"       Renderer="Falagard/ItemListbox"       LookNFeel="WindowsLook/ItemListbox" />
+    <FalagardMapping WindowType="WindowsLook/ListboxItem"                 TargetType="CEGUI/ItemEntry"         Renderer="Falagard/ItemEntry"         LookNFeel="WindowsLook/ListboxItem" />
+    <FalagardMapping WindowType="WindowsLook/Listbox"                     TargetType="CEGUI/Listbox"           Renderer="Falagard/Listbox"           LookNFeel="WindowsLook/Listbox" />
+    <FalagardMapping WindowType="WindowsLook/ListHeader"                  TargetType="CEGUI/ListHeader"        Renderer="Falagard/ListHeader"        LookNFeel="WindowsLook/ListHeader" />
+    <FalagardMapping WindowType="WindowsLook/ListHeaderSegment"           TargetType="CEGUI/ListHeaderSegment" Renderer="Falagard/ListHeaderSegment" LookNFeel="WindowsLook/ListHeaderSegment" />
+    <FalagardMapping WindowType="WindowsLook/MultiLineEditbox"            TargetType="CEGUI/MultiLineEditbox"  Renderer="Falagard/MultiLineEditbox"  LookNFeel="WindowsLook/MultiLineEditbox" />
+    <FalagardMapping WindowType="WindowsLook/Menubar"                     TargetType="CEGUI/Menubar"           Renderer="Falagard/Menubar"           LookNFeel="WindowsLook/Menubar" />
+    <FalagardMapping WindowType="WindowsLook/MenuItem"                    TargetType="CEGUI/MenuItem"          Renderer="Falagard/MenuItem"          LookNFeel="WindowsLook/MenuItem" />
+    <FalagardMapping WindowType="WindowsLook/MultiColumnList"             TargetType="CEGUI/MultiColumnList"   Renderer="Falagard/MultiColumnList"   LookNFeel="WindowsLook/MultiColumnList" />
+    <FalagardMapping WindowType="WindowsLook/PopupMenu"                   TargetType="CEGUI/PopupMenu"         Renderer="Falagard/PopupMenu"         LookNFeel="WindowsLook/PopupMenu" />
+    <FalagardMapping WindowType="WindowsLook/ProgressBar"                 TargetType="CEGUI/ProgressBar"       Renderer="Falagard/ProgressBar"       LookNFeel="WindowsLook/ProgressBar" />
+    <FalagardMapping WindowType="WindowsLook/Button"                      TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="WindowsLook/Button" />
+    <FalagardMapping WindowType="WindowsLook/RadioButton"                 TargetType="CEGUI/RadioButton"       Renderer="Falagard/ToggleButton"      LookNFeel="WindowsLook/RadioButton" />
+    <FalagardMapping WindowType="WindowsLook/SystemButton"                TargetType="CEGUI/PushButton"        Renderer="Falagard/SystemButton"      LookNFeel="WindowsLook/Button" />
+    <FalagardMapping WindowType="WindowsLook/ScrollablePane"              TargetType="CEGUI/ScrollablePane"    Renderer="Falagard/ScrollablePane"    LookNFeel="WindowsLook/ScrollablePane" />
+    <FalagardMapping WindowType="WindowsLook/HorizontalScrollbar"         TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="WindowsLook/HorizontalScrollbar" />
+    <FalagardMapping WindowType="WindowsLook/VerticalScrollbar"           TargetType="CEGUI/Scrollbar"         Renderer="Falagard/Scrollbar"         LookNFeel="WindowsLook/VerticalScrollbar" />
+    <FalagardMapping WindowType="WindowsLook/Slider"                      TargetType="CEGUI/Slider"            Renderer="Falagard/Slider"            LookNFeel="WindowsLook/Slider" />
+    <FalagardMapping WindowType="WindowsLook/Spinner"                     TargetType="CEGUI/Spinner"           Renderer="Falagard/Default"           LookNFeel="WindowsLook/Spinner" />
+    <FalagardMapping WindowType="WindowsLook/TabButton"                   TargetType="CEGUI/TabButton"         Renderer="Falagard/TabButton"         LookNFeel="WindowsLook/TabButton" />
+    <FalagardMapping WindowType="WindowsLook/TabControl"                  TargetType="CEGUI/TabControl"        Renderer="Falagard/TabControl"        LookNFeel="WindowsLook/TabControl" />
+    <FalagardMapping WindowType="WindowsLook/HorizontalScrollbarThumb"    TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="WindowsLook/HorizontalScrollbarThumb" />
+    <FalagardMapping WindowType="WindowsLook/SliderThumb"                 TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="WindowsLook/SliderThumb" />
+    <FalagardMapping WindowType="WindowsLook/VerticalScrollbarThumb"      TargetType="CEGUI/Thumb"             Renderer="Falagard/Button"            LookNFeel="WindowsLook/VerticalScrollbarThumb" />
+    <FalagardMapping WindowType="WindowsLook/Titlebar"                    TargetType="CEGUI/Titlebar"          Renderer="Falagard/Titlebar"          LookNFeel="WindowsLook/Titlebar" />
+    <FalagardMapping WindowType="WindowsLook/Tooltip"                     TargetType="CEGUI/Tooltip"           Renderer="Falagard/Tooltip"           LookNFeel="WindowsLook/Tooltip" />
+    
+    <!-- Missing widgets (using Taharez LookNFeel) -->
+    <FalagardMapping WindowType="WindowsLook/ComboEditbox"                TargetType="CEGUI/Editbox"           Renderer="Falagard/Editbox"           LookNFeel="TaharezLook/ComboEditbox" />
+    <FalagardMapping WindowType="WindowsLook/ImageButton"                 TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="TaharezLook/ImageButton" />
+    <FalagardMapping WindowType="WindowsLook/Tree"                        TargetType="CEGUI/Tree"              Renderer="Falagard/Tree"              LookNFeel="TaharezLook/Tree" />
+
+    <!-- Additional widgets -->
+    <FalagardMapping WindowType="WindowsLook/IconButton"                  TargetType="CEGUI/PushButton"        Renderer="Falagard/Button"            LookNFeel="WindowsLook/IconButton" />
+    <FalagardMapping WindowType="WindowsLook/Static"                      TargetType="DefaultWindow"           Renderer="Falagard/Static"            LookNFeel="WindowsLook/Static" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/schemes/WindowsMenuWidgets.scheme
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/schemes/WindowsMenuWidgets.scheme	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/schemes/WindowsMenuWidgets.scheme	(revision 11817)
@@ -0,0 +1,42 @@
+<?xml version="1.0" ?>
+<GUIScheme Name="WindowsMenuWidgets">
+    <WindowAlias Alias="MenuWidgets/StaticImage"              Target="WindowsLook/StaticImage" />
+    <WindowAlias Alias="MenuWidgets/StaticText"               Target="WindowsLook/StaticText" />
+    <WindowAlias Alias="MenuWidgets/TabButtonPane"            Target="WindowsLook/TabButtonPane" />
+    <WindowAlias Alias="MenuWidgets/TabContentPane"           Target="WindowsLook/TabContentPane" />
+    <WindowAlias Alias="MenuWidgets/Checkbox"                 Target="WindowsLook/Checkbox" />
+    <WindowAlias Alias="MenuWidgets/Combobox"                 Target="WindowsLook/Combobox" />
+    <WindowAlias Alias="MenuWidgets/ComboDropList"            Target="WindowsLook/ComboDropList" />
+    <WindowAlias Alias="MenuWidgets/ComboEditbox"             Target="WindowsLook/ComboEditbox" />
+    <WindowAlias Alias="MenuWidgets/Editbox"                  Target="WindowsLook/Editbox" />
+    <WindowAlias Alias="MenuWidgets/FrameWindow"              Target="WindowsLook/FrameWindow" />
+    <WindowAlias Alias="MenuWidgets/GroupBox"                 Target="WindowsLook/GroupBox" />
+    <WindowAlias Alias="MenuWidgets/ItemListbox"              Target="WindowsLook/ItemListbox" />
+    <WindowAlias Alias="MenuWidgets/ListboxItem"              Target="WindowsLook/ListboxItem" />
+    <WindowAlias Alias="MenuWidgets/Listbox"                  Target="WindowsLook/Listbox" />
+    <WindowAlias Alias="MenuWidgets/ListHeader"               Target="WindowsLook/ListHeader" />
+    <WindowAlias Alias="MenuWidgets/ListHeaderSegment"        Target="WindowsLook/ListHeaderSegment" />
+    <WindowAlias Alias="MenuWidgets/MultiLineEditbox"         Target="WindowsLook/MultiLineEditbox" />
+    <WindowAlias Alias="MenuWidgets/Menubar"                  Target="WindowsLook/Menubar" />
+    <WindowAlias Alias="MenuWidgets/MenuItem"                 Target="WindowsLook/MenuItem" />
+    <WindowAlias Alias="MenuWidgets/MultiColumnList"          Target="WindowsLook/MultiColumnList" />
+    <WindowAlias Alias="MenuWidgets/PopupMenu"                Target="WindowsLook/PopupMenu" />
+    <WindowAlias Alias="MenuWidgets/ProgressBar"              Target="WindowsLook/ProgressBar" />
+    <WindowAlias Alias="MenuWidgets/Button"                   Target="WindowsLook/Button" />
+    <WindowAlias Alias="MenuWidgets/ImageButton"              Target="WindowsLook/ImageButton" />
+    <WindowAlias Alias="MenuWidgets/RadioButton"              Target="WindowsLook/RadioButton" />
+    <WindowAlias Alias="MenuWidgets/SystemButton"             Target="WindowsLook/SystemButton" />
+    <WindowAlias Alias="MenuWidgets/ScrollablePane"           Target="WindowsLook/ScrollablePane" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbar"      Target="WindowsLook/HorizontalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbar"        Target="WindowsLook/VerticalScrollbar" />
+    <WindowAlias Alias="MenuWidgets/Slider"                   Target="WindowsLook/Slider" />
+    <WindowAlias Alias="MenuWidgets/Spinner"                  Target="WindowsLook/Spinner" />
+    <WindowAlias Alias="MenuWidgets/TabButton"                Target="WindowsLook/TabButton" />
+    <WindowAlias Alias="MenuWidgets/TabControl"               Target="WindowsLook/TabControl" />
+    <WindowAlias Alias="MenuWidgets/HorizontalScrollbarThumb" Target="WindowsLook/HorizontalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/SliderThumb"              Target="WindowsLook/SliderThumb" />
+    <WindowAlias Alias="MenuWidgets/VerticalScrollbarThumb"   Target="WindowsLook/VerticalScrollbarThumb" />
+    <WindowAlias Alias="MenuWidgets/Titlebar"                 Target="WindowsLook/Titlebar" />
+    <WindowAlias Alias="MenuWidgets/Tooltip"                  Target="WindowsLook/Tooltip" />
+    <WindowAlias Alias="MenuWidgets/Tree"                     Target="WindowsLook/Tree" />
+</GUIScheme>
Index: /code/branches/RacingBots_FS18/data/gui/scripts/AudioMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/AudioMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/AudioMenu.lua	(revision 11817)
@@ -0,0 +1,195 @@
+-- AudioMenu.lua
+
+local P = createMenuSheet("AudioMenu")
+
+function P.onLoad()
+    soundMgr = orxonox.SoundManager:getInstance()
+    block = false
+    masterscrollbar_active = false
+    musicscrollbar_active = false
+    effectsscrollbar_active = false
+    mastervolume = soundMgr:getVolume(orxonox.SoundType.All)
+    musicvolume = soundMgr:getVolume(orxonox.SoundType.Music)
+    effectsvolume = soundMgr:getVolume(orxonox.SoundType.Effects)
+    mastermute = soundMgr:getMute(orxonox.SoundType.All)
+    musicmute = soundMgr:getMute(orxonox.SoundType.Music)
+    effectsmute = soundMgr:getMute(orxonox.SoundType.Effects)
+    masterscrollbarwindow = tolua.cast(winMgr:getWindow("orxonox/MasterScrollbar"),"CEGUI::Scrollbar")
+    musicscrollbarwindow = tolua.cast(winMgr:getWindow("orxonox/MusicScrollbar"),"CEGUI::Scrollbar")
+    effectsscrollbarwindow = tolua.cast(winMgr:getWindow("orxonox/EffectsScrollbar"),"CEGUI::Scrollbar")
+    mastermutewindow = tolua.cast(winMgr:getWindow("orxonox/MasterCheckbox"),"CEGUI::Checkbox")
+    musicmutewindow = tolua.cast(winMgr:getWindow("orxonox/MusicCheckbox"),"CEGUI::Checkbox")
+    effectsmutewindow = tolua.cast(winMgr:getWindow("orxonox/EffectsCheckbox"),"CEGUI::Checkbox")
+    masterscrollbarwindow:setScrollPosition(mastervolume)
+    musicscrollbarwindow:setScrollPosition(musicvolume)
+    effectsscrollbarwindow:setScrollPosition(effectsvolume)
+    mastermutewindow:setSelected(mastermute)
+    musicmutewindow:setSelected(musicmute)
+    effectsmutewindow:setSelected(effectsmute)
+    choice = "Default"
+    listboxwindow = winMgr:getWindow("orxonox/AudioThemeListbox")
+    local themeList = {}
+    table.insert(themeList, "Default")
+    table.insert(themeList, "Drum n' Bass")
+    table.insert(themeList, "8-Bit Style")
+    table.insert(themeList, "Corny Jazz")
+    table.insert(themeList, "Metal")
+    for k,v in pairs(themeList) do
+        item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        CEGUI.toListbox(listboxwindow):addItem(item)
+    end
+    if orxonox.getConfig("MoodManager", "mood_") == "dnb" then
+        listboxwindow:setItemSelectState(1,true)
+    elseif orxonox.getConfig("MoodManager", "mood_") == "eightbit" then
+        listboxwindow:setItemSelectState(2,true)
+    elseif orxonox.getConfig("MoodManager", "mood_") == "jazzy" then
+        listboxwindow:setItemSelectState(3,true)
+    elseif orxonox.getConfig("MoodManager", "mood_") == "metal" then
+        listboxwindow:setItemSelectState(4,true)
+    else
+        listboxwindow:setItemSelectState(0,true)
+    end
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/AudioBackButton"),
+            ["callback"]  = P.AudioBackButton_clicked
+    })
+end
+
+function P.AudioMasterScrollbar_changed(e)
+    if mastermute then
+        block = true
+        mastermutewindow:setSelected(false)
+        block = false
+        mastermute = false
+    end
+    if masterscrollbar_active == false then
+        mastervolume = masterscrollbarwindow:getScrollPosition()
+        orxonox.config("SoundManager", "soundVolume_", mastervolume)
+    end
+end
+
+function P.AudioMasterScrollbar_started(e)
+    masterscrollbar_active = true
+end
+
+function P.AudioMasterScrollbar_ended(e)
+    mastervolume = masterscrollbarwindow:getScrollPosition()
+    orxonox.config("SoundManager", "soundVolume_", mastervolume)
+    masterscrollbar_active = false
+end
+
+function P.AudioMusicScrollbar_changed(e)
+    if musicmute then
+        block = true
+        musicmutewindow:setSelected(false)
+        block = false
+        musicmute = false
+    end
+    if musicscrollbar_active == false then
+        musicvolume = musicscrollbarwindow:getScrollPosition()
+        orxonox.config("SoundManager", "ambientVolume_", musicvolume)
+    end
+end
+
+function P.AudioMusicScrollbar_started(e)
+    musicscrollbar_active = true
+end
+
+function P.AudioMusicScrollbar_ended(e)
+    musicmutewindow:setSelected(false)
+    musicvolume = musicscrollbarwindow:getScrollPosition()
+    orxonox.config("SoundManager", "ambientVolume_", musicvolume)
+    musicscrollbar_active = false
+end
+
+function P.AudioEffectsScrollbar_changed(e)
+    if effectsmute then
+        block = true
+        effectsmutewindow:setSelected(false)
+        block = false
+        effectsmute = false
+    end
+    if effectsscrollbar_active == false then
+        effectsvolume = effectsscrollbarwindow:getScrollPosition()
+        orxonox.config("SoundManager", "effectsVolume_", effectsvolume)
+    end
+end
+
+function P.AudioEffectsScrollbar_started(e)
+    effectsscrollbar_active = true
+end
+
+function P.AudioEffectsScrollbar_ended(e)
+    effectsmutewindow:setSelected(false)
+    effectsvolume = effectsscrollbarwindow:getScrollPosition()
+    orxonox.config("SoundManager", "effectsVolume_", effectsvolume)
+    effectsscrollbar_active = false
+end
+
+function P.AudioMuteMasterCheckbox_clicked(e)
+    if block == false then
+        if mastermute then
+            masterscrollbarwindow:setScrollPosition(mastervolume)
+            mastermute = false
+        else
+            temp = masterscrollbarwindow:getScrollPosition()
+            masterscrollbarwindow:setScrollPosition(0)
+            mastervolume = temp
+            mastermute = true
+        end
+    end
+    soundMgr:toggleMute(orxonox.SoundType.All)
+end
+
+function P.AudioMuteMusicCheckbox_clicked(e)
+    if block == false then
+        if musicmute then
+            musicscrollbarwindow:setScrollPosition(musicvolume)
+            musicmute = false
+        else
+            temp = musicscrollbarwindow:getScrollPosition()
+            musicscrollbarwindow:setScrollPosition(0)
+            musicvolume = temp
+            musicmute = true
+        end
+    end
+    soundMgr:toggleMute(orxonox.SoundType.Music)
+end
+
+function P.AudioMuteEffectsCheckbox_clicked(e)
+    if block == false then
+        if effectsmute then
+            effectsscrollbarwindow:setScrollPosition(effectsvolume)
+            effectsmute = false
+        else
+            temp = effectsscrollbarwindow:getScrollPosition()
+            effectsscrollbarwindow:setScrollPosition(0)
+            effectsvolume = temp
+            effectsmute = true
+        end
+    end
+    soundMgr:toggleMute(orxonox.SoundType.Effects)
+end
+
+function P.AudioThemeListbox_changed(e)
+    if listboxwindow:isItemSelected(1) then
+        orxonox.config("MoodManager", "mood_", "dnb")
+    elseif listboxwindow:isItemSelected(2) then
+        orxonox.config("MoodManager", "mood_", "eightbit")
+    elseif listboxwindow:isItemSelected(3) then
+        orxonox.config("MoodManager", "mood_", "jazzy")
+    elseif listboxwindow:isItemSelected(4) then
+        orxonox.config("MoodManager", "mood_", "metal")
+    else
+        orxonox.config("MoodManager", "mood_", "default")
+    end
+end
+
+function P.AudioBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/CampaignMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/CampaignMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/CampaignMenu.lua	(revision 11817)
@@ -0,0 +1,133 @@
+--CampaignMenu.lua
+
+local P = createMenuSheet("CampaignMenu")
+
+function P:onShow()
+    P:updateButtons()
+end
+
+function P.updateButtons()
+    P.updateButton(0, winMgr:getWindow("orxonox/Mission1Button"))
+    P.updateButton(0, winMgr:getWindow("orxonox/Mission1Text"))
+    P.updateButton(1, winMgr:getWindow("orxonox/Mission2Button"))
+    P.updateButton(1, winMgr:getWindow("orxonox/Mission2Text"))
+    P.updateButton(2, winMgr:getWindow("orxonox/Mission3Button"))
+    P.updateButton(2, winMgr:getWindow("orxonox/Mission3Text"))
+    P.updateButton(3, winMgr:getWindow("orxonox/Mission4Button"))
+    P.updateButton(3, winMgr:getWindow("orxonox/Mission4Text"))
+    P.updateButton(4, winMgr:getWindow("orxonox/Mission5Button"))
+    P.updateButton(4, winMgr:getWindow("orxonox/Mission5Text"))
+    P.updateButton(5, winMgr:getWindow("orxonox/Mission6Button"))
+    P.updateButton(5, winMgr:getWindow("orxonox/Mission6Text"))
+    P.updateButton(6, winMgr:getWindow("orxonox/Mission7Button"))
+    P.updateButton(6, winMgr:getWindow("orxonox/Mission7Text"))
+    P.updateButton(7, winMgr:getWindow("orxonox/Mission8Button"))
+    P.updateButton(7, winMgr:getWindow("orxonox/Mission8Text"))
+    P.updateButton(8, winMgr:getWindow("orxonox/Mission9Button"))
+    P.updateButton(8, winMgr:getWindow("orxonox/Mission9Text"))
+
+
+    if (P.getIndexOfLastFinishedMission() == orxonox.LevelManager:getInstance():getNumberOfCampaignMissions() - 1) then
+        local label = winMgr:getWindow("orxonox/CampaignMenuCongratulation")
+        label:setProperty("Visible","True")
+    end
+end
+
+function P.updateButton(index, button)
+    if (P.shouldDisplayButton(index)) then
+        button:setProperty("Visible", "True")
+
+        if (P.shouldEnableButton(index)) then
+            button:setProperty("Disabled", "False")
+        end
+    end
+end
+
+function P.shouldDisplayButton(index)
+    local size = orxonox.LevelManager:getInstance():getNumberOfCampaignMissions()
+    return index < size
+end
+
+function P.shouldEnableButton(index)
+    return index <= P.getIndexOfLastFinishedMission() + 1
+end
+
+function P.getIndexOfLastFinishedMission()
+    local lastMission = orxonox.LevelManager:getInstance():getLastFinishedCampaignMission()
+    if (lastMission and lastMission ~= "") then
+        local size = orxonox.LevelManager:getInstance():getNumberOfCampaignMissions()
+        local index = 0
+        while index < size do
+            local mission = orxonox.LevelManager:getInstance():getCampaignMission(index)
+            if (mission == lastMission) then 
+                return index
+            end
+            index = index + 1
+        end
+    end
+    return -1
+end
+
+function P.Mission1Button_clicked(e)
+    P.loadLevel(P.FindLevel(0))
+end
+
+function P.Mission2Button_clicked(e)
+    P.loadLevel(P.FindLevel(1))
+end
+
+function P.Mission3Button_clicked(e)
+    P.loadLevel(P.FindLevel(2))
+end
+
+function P.Mission4Button_clicked(e)
+    P.loadLevel(P.FindLevel(3))
+end
+
+function P.Mission5Button_clicked(e)
+    P.loadLevel(P.FindLevel(4))
+end
+
+function P.Mission6Button_clicked(e)
+    P.loadLevel(P.FindLevel(5))
+end
+
+function P.Mission7Button_clicked(e)
+    P.loadLevel(P.FindLevel(6))
+end
+
+function P.Mission8Button_clicked(e)
+    P.loadLevel(P.FindLevel(7))
+end
+
+function P.Mission9Button_clicked(e)
+    P.loadLevel(P.FindLevel(8))
+end
+
+function P.loadLevel(level)
+    orxonox.execute("changeGame " .. level:getXMLFilename())
+    hideAllMenuSheets()
+end
+
+function P.FindLevel(index)
+    local filename = orxonox.LevelManager:getInstance():getCampaignMission(index)
+    local level = nil
+    local templevel = nil
+    local size = orxonox.LevelManager:getInstance():getNumberOfLevels()
+    local index = 0
+    while index < size do
+        templevel = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
+        if(templevel:getXMLFilename()==filename) then 
+            level = templevel
+        end
+    index=index+1
+    end
+    return level
+end
+
+function P.CampaignMenuBackButton_clicked(e)
+    orxonox.execute("startMainMenu")
+    hideMenuSheet("CampaignMenu")
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/ChatBox-inputonly.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/ChatBox-inputonly.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/ChatBox-inputonly.lua	(revision 11817)
@@ -0,0 +1,5 @@
+-- ChatBox-inputonly.lua
+
+local P = createMenuSheet("ChatBox-inputonly", true, tribool(true), tribool(dontcare), false)
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/ChatBox.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/ChatBox.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/ChatBox.lua	(revision 11817)
@@ -0,0 +1,10 @@
+-- ChatBox.lua
+
+local P = createMenuSheet("ChatBox", true, tribool(true), tribool(dontcare), false)
+
+function P.ChatBoxCloseButton_clicked(e)
+    orxonox.ChatInputHandler:getInstance():deactivate()
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/ControlsMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/ControlsMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/ControlsMenu.lua	(revision 11817)
@@ -0,0 +1,39 @@
+-- ControlsMenu.lua
+
+local P = createMenuSheet("ControlsMenu")
+P.loadAlong = { "MouseControlsMenu", "KeyBindMenu" }
+
+function P.onLoad()
+    P.multiplayerMode = "startClient"
+
+    --buttons are arranged in a 3x1 matrix:
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/MouseControlsButton"),
+            ["callback"]  = P.ControlsMouseControlsButton_clicked
+    })
+
+    P:setButton(2, 1, {
+            ["button"] = winMgr:getWindow("orxonox/KeybindingsButton"),
+            ["callback"]  = P.ControlsKeyboardControlsButton_clicked
+    })
+
+    P:setButton(3, 1, {
+            ["button"] = winMgr:getWindow("orxonox/ControlsBackButton"),
+            ["callback"]  = P.ControlsBackButton_clicked
+    })
+end
+
+function P.ControlsMouseControlsButton_clicked(e)
+    showMenuSheet("MouseControlsMenu", true)
+end
+
+function P.ControlsKeyboardControlsButton_clicked(e)
+    showMenuSheet("KeyBindMenu", true)
+end
+
+function P.ControlsBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/CreditsMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/CreditsMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/CreditsMenu.lua	(revision 11817)
@@ -0,0 +1,26 @@
+-- CreditsMenu.lua
+
+local P = createMenuSheet("CreditsMenu")
+
+P.scrollbarWidth = 13
+
+function P.onLoad()
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/CreditsBackButton"),
+            ["callback"]  = P.CreditsBackButton_clicked
+    })
+end
+
+function P.onShow()
+    local description = winMgr:getWindow("orxonox/CreditsText")
+
+    height = getStaticTextWindowHeight(description)
+    description:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(0.0, height)))
+end
+
+function P.CreditsBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/DecisionPopup.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/DecisionPopup.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/DecisionPopup.lua	(revision 11817)
@@ -0,0 +1,47 @@
+-- DecisionPopup.lua
+
+local P = createMenuSheet("DecisionPopup")
+
+function P.onLoad()
+
+    --button are arranged in a 1x2 matrix
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/DecisionPopup_button_yes"),
+            ["callback"]  = P.button_yes
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/DecisionPopup_button_no"),
+            ["callback"]  = P.button_no
+    })
+end
+
+function P.onShow()
+    P:setSelection(1, 1)
+end
+
+function P.setCallback(functionPtr)
+    P.functionPtr = functionPtr
+end
+
+function P.setText( text )
+    winMgr:getWindow("orxonox/DecisionPopup_text"):setText( text )
+end
+
+-- events for ingamemenu
+function P.button_yes(e)
+    if P.functionPtr ~= nil then
+        P.functionPtr(true)
+    end
+    hideMenuSheet("DecisionPopup")
+end
+
+function P.button_no(e)
+    if P.functionPtr ~= nil then
+        P.functionPtr(false)
+    end
+    hideMenuSheet("DecisionPopup")
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/Dialog.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/Dialog.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/Dialog.lua	(revision 11817)
@@ -0,0 +1,127 @@
+-- Dialog.lua
+
+local P = createMenuSheet("Dialog")
+
+P.wrapper = nil
+P.detailsWindows = {}
+P.showing = false
+P.choice = 0
+P.scrollbarWidth = 12
+
+function P.onLoad() --wird ausgefuert wenn Fenster geladen
+    P.wrapper = nil
+end
+
+function P.onShow() --wird ausgefuert wenn Dialogfenster gezeigt
+
+    orxonox.CommandExecutor:execute("setTimeFactor 0")
+    P.createDialog()
+    P.showing = true
+
+end
+
+function P.onHide() --aufgefuert wenn Fenster geschlossen wird
+    orxonox.CommandExecutor:execute("setTimeFactor 1")
+    P.showing = false
+    P.cleanup(true)
+end
+
+function P.createDialog() -- initiallisiert das Dialog Fenster, setzt Namen sowie die erste Frage mit enstprechenden Antworten
+
+    local manager = orxonox.DialogManager:getInstance()
+    
+    
+    local personfield = winMgr:getWindow("orxonox/Dialog/Person")
+    local person = manager:getPerson()
+    personfield:setText(person)
+
+    local questionfield = winMgr:getWindow("orxonox/Dialog/Question")
+    local question = manager:getQuestion()
+    questionfield:setText(question)
+
+    local listboxwindow = winMgr:getWindow("orxonox/AnsListbox")
+    CEGUI.toListbox(listboxwindow):resetList()
+
+    local ansList = {}
+    local anssize = manager:getSize()
+
+    for index = 0, anssize -1, 1 do
+        table.insert(ansList, manager:getAnswer(index))
+    end  
+
+    for k,v in pairs(ansList) do
+        item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        CEGUI.toListbox(listboxwindow):addItem(item)
+    end
+end
+
+function P.updateDialog()   --updated den Dialog entsprechend der Ausgeaehlten option der letzten Frage, setzt Frage und Antwortmoeglichkeiten neu
+    local manager = orxonox.DialogManager:getInstance()
+    manager:update(P.choice)
+
+    local questionfield = winMgr:getWindow("orxonox/Dialog/Question")
+    local question = manager:getQuestion()
+    questionfield:setText(question)
+
+    local listboxwindow = winMgr:getWindow("orxonox/AnsListbox")
+    listboxwindow:resetList()
+
+    local ansList = {}
+    local anssize = manager:getSize()
+
+    for index = 0, anssize -1, 1 do
+        table.insert(ansList, manager:getAnswer(index))
+    end  
+
+    for k,v in pairs(ansList) do
+        item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        CEGUI.toListbox(listboxwindow):addItem(item)
+    end
+
+    P.choice = 0
+end
+
+function P.answer_changed(e)    --wird aufgerufen falls Auswahl geaendert wird und setzt enstprechenden Indexparameter  
+    listboxwindow = winMgr:getWindow("orxonox/AnsListbox")
+    selection = listboxwindow:getFirstSelectedItem()
+    if selection ~= nil then
+    P.choice = listboxwindow:getItemIndex(selection)
+    else 
+        P.choice = 0
+    end
+end
+
+
+function P.cleanup(destroyDetails)  --loest Fenster wieder auf (!nicht selbst geschrieben, nur uebernommen, eventuell nicht noetiger code)
+
+    if P.wrapper ~= nil then
+        winMgr:destroyWindow(P.wrapper)
+    end
+    
+    --Destroy details windows.
+    if destroyDetails == false then
+        return
+    end
+    for k,v in pairs(P.detailsWindows) do
+        if v ~= nil then
+            P.destroyDetailWindow(k)
+        end
+    end
+    
+end
+
+
+
+function P.Button_clicked(e)    --wird bei click auf say knopf ausgeloest, entscheidet ob Dialog schliesst oder updated und fuert entsprechen aus
+    local ending = orxonox.DialogManager:getInstance():endtest(P.choice)
+    
+    if ending then
+        orxonox.CommandExecutor:execute("OrxonoxOverlay toggleVisibility Dialog")
+    else 
+        P.updateDialog(index)
+    end
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/DockingDialog.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/DockingDialog.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/DockingDialog.lua	(revision 11817)
@@ -0,0 +1,69 @@
+-- DockingDialog.lua
+
+local P = createMenuSheet("DockingDialog")
+
+P.docks = {}
+
+function P.onLoad()
+
+     --button are arranged in a 1x2 matrix
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/Docking/DockButton"),
+            ["callback"]  = P.dockButton_clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/Docking/CancelButton"),
+            ["callback"]  = P.cancelButton_clicked
+    })
+    
+end
+
+function P.onShow()
+    orxonox.execute("setPause 1")
+    P.update()
+end
+
+function P.onHide()
+    orxonox.execute("setPause 0")
+end
+
+function P.update()
+    -- update dock list
+    P.docks = {}
+    local docks = orxonox.Dock:getNumberOfActiveDocks()
+    for i = 0, docks-1 do
+        table.insert(P.docks, orxonox.Dock:getActiveDockAtIndex(i))
+    end
+
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/Docking/Docks"))
+    listbox:resetList()
+
+    for k in pairs(P.docks) do
+        local item = CEGUI.createListboxTextItem("Dock " .. k)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        listbox:addItem(item)
+        if k == 1 then
+            listbox:setItemSelectState(item, true)
+        end
+    end
+end
+
+function P.dockButton_clicked(e)
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/Docking/Docks"))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = listbox:getItemIndex(choice)
+        local dock = P.docks[index+1]
+        if dock ~= nil then
+            dock:dock()
+        end
+    end
+    hideMenuSheet(P.name)
+end
+
+function P.cancelButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/GUISheet.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/GUISheet.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/GUISheet.lua	(revision 11817)
@@ -0,0 +1,398 @@
+-- GUISheet.lua
+
+local P = {}
+_G[_REQUIREDNAME or "GUISheet"] = P
+P.__index = P
+
+-- Don't use directly --> use HUDSheet.new or MenuSheet.new
+function P.new(_name)
+    local newSheet = { name = _name }
+    setmetatable(newSheet, P)
+    return newSheet
+end
+
+-- Override this function if you need to do work on load
+function P:onLoad()
+end
+
+-- Override this function if you need to do work on show
+function P:onShow()
+end
+
+-- Override this function if you need to do work on hide
+function P:onHide()
+end
+
+-- Override this function if you need to do work on quit
+function P:onQuit()
+end
+
+-- Override this function if you want to react on keystrokes
+function P:onKeyPressed()
+end
+
+-- Override this function if you want to update the gui after the window was resized
+function P:onWindowResized()
+end
+
+-- show function for the GUI
+function P:show()
+    self.window:show()
+    self.bVisible = true
+
+    -- set the selected button's state
+    self:setSelectedButtonsStateToSelected()
+
+    self:onShow()
+end
+
+-- hide function for the GUI
+function P:hide()
+    self.window:hide()
+    self.bVisible = false
+
+    self:onHide()
+end
+
+function P:quit()
+    -- reset the selected button
+    if self.buttons then
+        self:resetSelection()
+    end
+
+    self:onQuit()
+end
+
+function P:load()
+    -- Load the layout that describes the sheet
+    self.window = winMgr:loadWindowLayout(self.name .. ".layout")
+    if self.window == nil then
+        error("Could not load layout file for GUI sheet '"..self.name.."'")
+    end
+    -- Hide it at first
+    self:hide()
+    -- Allow sheets to do some work upon loading
+    self:onLoad()
+
+    -- Also load additional sheets to avoid display lags
+    if self.loadAlong and orxonox.GUIManager:preloadMenuSheets() then
+        for k, sheet in pairs(self.loadAlong) do
+            loadSheet(sheet)
+        end
+    end
+    return self
+end
+
+-- Handles key pressed while the gui sheed is displayed
+function P:keyPressed()
+    if self.buttons then
+        if code == "208" then     -- key down
+            self:moveSelectionRow(1)
+        elseif code == "200" then -- key up
+            self:moveSelectionRow(-1)
+        elseif code == "205" then -- key right
+            self:moveSelectionColumn(1)
+        elseif code == "203" then -- key left
+            self:moveSelectionColumn(-1)
+        elseif code == "28" or code == "156"  then -- key enter or key numpad enter
+            self:pressSelectedButton()
+        end
+    end
+
+    self:onKeyPressed()
+end
+
+function P:windowResized()
+    self:onWindowResized()
+end
+
+
+-------------------------------------------------------------------------------
+-- Keyboard control -----------------------------------------------------------
+-------------------------------------------------------------------------------
+
+-- Initializes the buttons table, used to control the menu with the keyboard
+function P:initButtons(rows, columns)
+    self.rows = rows
+    self.columns = columns
+    self.buttons = {}
+    self.selectedRow = 0
+    self.selectedColumn = 0
+    self.ratio = 1
+end
+
+-- ratio: the button's with divided by the button's height (used to calculate distance between buttons - adjust this until you get the desired behavior)
+function P:setRatio(ratio)
+    self.ratio = ratio
+end
+
+-- Defines the button for a given position in the table. The upper-left button is at position (1, 1)
+function P:setButton(row, column, button)
+    if not self.buttons then
+        -- init the table
+        self:initButtons(row, column)
+    elseif row > self.rows or column > self.columns then
+        -- rearrange the table
+        local maxRows = math.max(self.rows, row)
+        local maxColumns = math.max(self.columns, column)
+
+        for r = self.rows, 1, -1 do
+            for c = self.columns, 1, -1 do
+                local b = self:getButton(r, c)
+                if b then
+                    self.buttons[(r - 1) * self.columns + (c - 1)] = nil
+                    self.buttons[(r - 1) * maxColumns + (c - 1)] = b
+                end
+            end
+        end
+
+        self.rows = maxRows
+        self.columns = maxColumns
+    end
+
+    self.buttons[(row - 1) * self.columns + (column - 1)] = button
+end
+
+-- Returns the button at a given position in the table. The upper-left button is at position (1, 1)
+function P:getButton(row, column)
+    if self.buttons then
+        return self.buttons[(row - 1) * self.columns + (column - 1)]
+    else
+        return nil
+    end
+end
+
+-- Returns the selected button
+function P:getSelectedButton()
+    if self:hasSelection() then
+        return self:getButton(self.selectedRow, self.selectedColumn)
+    else
+        return nil
+    end
+end
+
+-- Presses the selected button if any
+function P:pressSelectedButton()
+    if self:getSelectedButton() then
+        self.pressedEnter = true
+        self:getSelectedButton().callback()
+        self.pressedEnter = false
+    end
+end
+
+-- Sets the selection to a given row and column. The upper-left button is at position (1, 1)
+function P:setSelection(row, column)
+    if not self.buttons then
+        return
+    end
+
+    assert(row > 0 and column > 0 and row <= self.rows and column <= self.columns, "(" .. row .. "/" .. column .. ") is not in the valid bounds of the table (1/1)-(" .. self.rows .. "/" .. self.columns .. ")")
+
+    self:setSelectedButtonsStateToNormal()
+
+    self.selectedRow = row
+    self.selectedColumn = column
+
+    self:setSelectedButtonsStateToSelected()
+end
+
+-- Sets the selection to the button closest to the given row and column. The upper-left button is at position (1, 1)
+function P:setSelectionNear(row, column)
+    if not self.buttons then
+        return
+    end
+
+    assert(row > 0 and column > 0 and row <= self.rows and column <= self.columns, "(" .. row .. "/" .. column .. ") is not in the valid bounds of the table (1/1)-(" .. self.rows .. "/" .. self.columns .. ")")
+
+    if self:getButton(row, column) then
+        self:setSelection(row, column)
+    else
+        local min = 1000000
+        local minRow, minColumn
+
+        for r = 1, self.rows do
+            for c = 1, self.columns do
+                if self:getButton(r, c) then
+                    local distance = math.sqrt((row - r)^2 + ((column - c) * self.ratio)^2)
+                    if distance < min then
+                        min = distance; minRow = r; minColumn = c
+                    end
+                end
+            end
+        end
+
+        if minRow and minColumn then
+            self:setSelection(minRow, minColumn)
+        else
+            self:resetSelection()
+        end
+    end
+end
+
+-- Moves the selection by a given number of rows (a positive value means down, a negative value means up)
+function P:moveSelectionRow(relRow)
+    self:moveSelection(relRow, "selectedRow", "selectedColumn", "rows", "columns", true)
+end
+
+-- Moves the selection by a given number of columns (a positive value means right, a negative value means left)
+function P:moveSelectionColumn(relColumn)
+    self:moveSelection(relColumn, "selectedColumn", "selectedRow", "columns", "rows", false)
+end
+
+-- Generic move function, the values are determined at runtime depending on the arguments
+function P:moveSelection(relMove, selectedThis, selectedOther, limitThis, limitOther, isRow)
+    if not self.buttons then
+        return
+    end
+
+    -- if there's no selection yet, prepare it such that the selection enters the table from the desired side
+    if self.selectedRow > 0 or self.selectedColumn > 0 then
+        self:setSelectedButtonsStateToNormal()
+    else
+        if relMove > 0 then
+            self[selectedThis] = 0
+            self[selectedOther] = 1
+        elseif relMove < 0 then
+            self[selectedThis] = self[limitThis] + 1
+            self[selectedOther] = 1
+        else
+            return
+        end
+    end
+
+    -- move the selection according to the parameters
+    self[selectedThis] = self[selectedThis] + relMove
+
+    -- wrap around on overflow or underflow
+    while self[selectedThis] > self[limitThis] do self[selectedThis] = self[selectedThis] - self[limitThis] end
+    while self[selectedThis] <= 0              do self[selectedThis] = self[selectedThis] + self[limitThis] end
+
+    -- if the button is deactivated, search the button closest to the desired location
+    if self:getSelectedButton() == nil then
+        local min = 1000000
+        local minV1, minV2
+        local limit, step
+
+        if relMove > 0 then
+            limit = self[limitThis]
+            step = 1
+        else
+            limit = 1
+            step = -1
+        end
+
+        for v1 = self[selectedThis], limit, step do
+            for v2 = 1, self[limitOther] do
+                local button
+                if isRow == true then
+                    button = self:getButton(v1, v2)
+                else
+                    button = self:getButton(v2, v1)
+                end
+                if button then
+                    local distance
+                    if isRow == true then
+                        distance = math.sqrt((self[selectedThis] - v1)^2 + ((self[selectedOther] - v2) * self.ratio)^2)
+                    else
+                        distance = math.sqrt(((self[selectedThis] - v1) * self.ratio)^2 + (self[selectedOther] - v2)^2)
+                    end
+                    if distance < min then
+                        min = distance; minV1 = v1; minV2 = v2
+                    end
+                end
+            end
+        end
+
+        if minV1 and minV2 then
+            self[selectedThis] = minV1
+            self[selectedOther] = minV2
+        elseif self:hasButtons() then
+            -- no suitable button found - wrap around and search again
+            if relMove > 0 then
+                self[selectedThis] = 0
+            else
+                self[selectedThis] = self[limitThis] + 1
+            end
+            self:moveSelection(relMove, selectedThis, selectedOther, limitThis, limitOther, isRow)
+        end
+    end
+
+    self:setSelectedButtonsStateToSelected()
+end
+
+-- Resets the selection
+function P:resetSelection()
+    self:setSelectedButtonsStateToNormal()
+
+    self.selectedRow = 0
+    self.selectedColumn = 0
+end
+
+-- Checks if there's at least one button in the table
+function P:hasButtons()
+    local count = 0
+    for r = 1, self.rows do
+        for c = 1, self.columns do
+            if self:getButton(r, c) then
+                count = count + 1
+            end
+        end
+    end
+
+    return (count > 0)
+end
+
+-- Determines if a button is selected
+function P:hasSelection()
+    if self.selectedRow and self.selectedRow > 0 and self.selectedColumn and self.selectedColumn > 0 then
+        return true
+    else
+        return false
+    end
+end
+
+-- Sets the selected button's state to normal
+function P:setSelectedButtonsStateToNormal()
+    self:setSelectedButtonsState("Normal")
+end
+
+-- Sets the selected button's state to selected
+function P:setSelectedButtonsStateToSelected()
+    self:setSelectedButtonsState("Selected")
+end
+
+-- Sets the selected button's state to pushed
+function P:setSelectedButtonsStateToPushed()
+    self:setSelectedButtonsState("Pushed")
+end
+
+-- Sets the selected button's state
+function P:setSelectedButtonsState(state)
+    if self:getSelectedButton() then
+        local element = self:getSelectedButton().button
+        local offset = getElementStateOffset(element)
+
+        if offset then
+            element:setProperty("NormalImageRightEdge",  string.sub(element:getProperty("NormalImageRightEdge"),  1, offset) .. state)
+            element:setProperty("NormalImageLeftEdge",   string.sub(element:getProperty("NormalImageLeftEdge"),   1, offset) .. state)
+            element:setProperty("NormalImageBackground", string.sub(element:getProperty("NormalImageBackground"), 1, offset) .. state)
+        end
+    end
+end
+
+-- Gets the offset of the button's current state
+function getElementStateOffset(element)
+    local property = element:getProperty("NormalImageRightEdge")
+
+    if string.sub(property, string.len(property) - 5, string.len(property)) == "Normal" then
+        return -7
+    elseif string.sub(property, string.len(property) - 7, string.len(property)) == "Selected" then
+        return -9
+    elseif string.sub(property, string.len(property) - 5, string.len(property)) == "Pushed" then
+        return -7
+    else
+        return nil
+    end
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/GUITools.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/GUITools.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/GUITools.lua	(revision 11817)
@@ -0,0 +1,63 @@
+-- Returns a new menu sheet
+-- See MenuSheet.new for details about the parameters
+function createMenuSheet(name, bHidePrevious, tShowCursor, tUseKeyboard, bBlockJoyStick)
+    local sheet = require("MenuSheet").new(name, bHidePrevious, tShowCursor, tUseKeyboard, bBlockJoyStick)
+    _G[sheet.name] = sheet -- Global access required because of the event handlers
+    return sheet
+end
+
+-- Returns a new HUD sheet
+function createHUDSheet(name)
+    local sheet = require("HUDSheet").new(name)
+    _G[sheet.name] = sheet -- Global access required because of the event handlers
+    return sheet
+end
+
+function openDecisionPopup( text, callbackPtr )
+    showMenuSheet("DecisionPopup", false, true)
+    DecisionPopup.setCallback(callbackPtr)
+    DecisionPopup.setText(text)
+end
+
+function openInfoPopup(text, functionPtr, closeButton, arguments)
+    showMenuSheet("InfoPopup", false, true)
+    InfoPopup.execute(functionPtr, arguments)
+    InfoPopup.setText(text)
+    InfoPopup.setCloseButton(closeButton)
+end
+
+function getMinTextSize(window)
+    local size = {}
+
+    local lookAndFeel = CEGUI.WidgetLookManager:getSingleton():getWidgetLook(window:getLookNFeel())
+    local height = window:getFont():getLineSpacing() + window:getUnclippedOuterRect():getHeight() - lookAndFeel:getNamedArea("WithFrameTextRenderArea"):getArea():getPixelRect(window):getHeight()
+    local width =  window:getFont():getTextExtent(window:getText()) + window:getUnclippedOuterRect():getWidth() - lookAndFeel:getNamedArea("WithFrameTextRenderArea"):getArea():getPixelRect(window):getWidth()
+
+    table.insert(size, height)
+    table.insert(size, width)
+    return size
+end
+
+function getScrollingStepSize(window)
+    local height = window:getUnclippedOuterRect():getHeight()
+    local maxHeight = CEGUI.System:getSingleton():getGUISheet():getUnclippedOuterRect():getHeight()
+    local ratio = height/maxHeight
+    return 0.008*ratio/0.3204
+end
+
+function getStaticTextWindowHeight(window)
+    -- Get the area the text is formatted and drawn into.
+    local lookAndFeel = CEGUI.WidgetLookManager:getSingleton():getWidgetLook(window:getLookNFeel())
+    local formattedArea = lookAndFeel:getNamedArea("WithFrameTextRenderArea"):getArea():getPixelRect(window)
+    -- Calculate the pixel height of the frame by subtracting the height of the area above from the total height of the window.
+    local frameHeight = window:getUnclippedOuterRect():getHeight() - formattedArea:getHeight()
+
+    local height = 0
+    if ORXONOX_OLD_CEGUI then
+        local lines = window:getFont():getFormattedLineCount(window:getText(), formattedArea, CEGUI.WordWrapLeftAligned)
+        height = lines * window:getFont():getLineSpacing() + frameHeight
+    else
+        height = math.floor(CEGUI.PropertyHelper:stringToFloat(window:getProperty("VertExtent")) + frameHeight) + 1
+    end
+    return height
+end
Index: /code/branches/RacingBots_FS18/data/gui/scripts/GameplayMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/GameplayMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/GameplayMenu.lua	(revision 11817)
@@ -0,0 +1,43 @@
+-- GameplayMenu.lua
+
+local P = createMenuSheet("GameplayMenu")
+
+function P.onLoad()
+    dropdown = winMgr:getWindow("orxonox/ThemeCombobox")
+    local themeList = {}
+    table.insert(themeList, "Theme 1")
+    table.insert(themeList, "Theme 2")
+    table.insert(themeList, "Theme 3")
+    for k,v in pairs(themeList) do
+        item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        CEGUI.toCombobox(dropdown):addItem(item)
+    end
+end
+
+function P.GameplayThemeCombobox_changed(e)
+    -- theme
+    orxout("event: theme")
+end
+
+function P.GameplayDifficultyEasyButton_clicked(e)
+    -- difficulty easy
+    orxout("event: easy")
+end
+
+function P.GameplayDifficultyNormalButton_clicked(e)
+    -- difficulty normal
+    orxout("event: normal")
+end
+
+function P.GameplayDifficultyHardButton_clicked(e)
+    -- difficulty hard
+    orxout("event: hard")
+end
+
+function P.GameplayBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/GraphicsMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/GraphicsMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/GraphicsMenu.lua	(revision 11817)
@@ -0,0 +1,421 @@
+-- GraphicsMenu.lua
+
+local P = createMenuSheet("GraphicsMenu")
+
+P.resolutionList = {"custom", "640 x 480", "720 x 480", "720 x 576", "800 x 600", "1024 x 600", "1024 x 768", "1152 x 864", "1280 x 720", "1280 x 800", "1280 x 960", "1280 x 1024", "1360 x 768", "1440 x 900", "1600 x 900", "1600 x 1200", "1680 x 1050"}
+P.schemeList = {"TaharezGreen", "Orxonox"}
+P.fsaaList = {"0", "2", "4", "8", "8 [Quality]"}
+P.particleLodList = {"None", "Low", "Normal", "High"}
+
+function P:onLoad()
+    -------------------
+    -- Button matrix --
+    -------------------
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/GraphicsOkButton"),
+            ["callback"]  = P.callback_Ok_Clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/GraphicsCancelButton"),
+            ["callback"]  = P.callback_Cancel_Clicked
+    })
+
+    -- place apply button at the bottom in the matrix, even though it's in fact at the top, to make the OK button highlighted by default
+    P:setButton(2, 1, {
+            ["button"] = winMgr:getWindow("orxonox/Display/Resolution/Apply"),
+            ["callback"]  = P.callback_Apply_Clicked
+    })
+
+    -----------------
+    -- Combo boxes --
+    -----------------
+
+    -- resolution combobox
+    local resolutionCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/Resolution/Combobox"))
+    resolutionCombobox:setReadOnly(true)
+
+    for k,v in pairs(P.resolutionList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        resolutionCombobox:addItem(item)
+    end
+
+    -- themes combobox
+    local themeCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/Theme/Combobox"))
+    themeCombobox:setReadOnly(true)
+
+    for k,v in pairs(P.schemeList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        themeCombobox:addItem(item)
+    end
+
+    -- fsaa combobox
+    local fsaaCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/More/FSAA"))
+    fsaaCombobox:setReadOnly(true)
+
+    for k,v in pairs(P.fsaaList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        fsaaCombobox:addItem(item)
+    end
+
+    -- particle lod combobox
+    local particleLodCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Settings/ParticleLodCombobox"))
+    particleLodCombobox:setReadOnly(true)
+
+    for k,v in pairs(P.particleLodList) do
+        local item = CEGUI.createListboxTextItem(v)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        particleLodCombobox:addItem(item)
+    end
+end
+
+function P:onShow()
+    -----------------
+    -- Display tab --
+    -----------------
+
+    -- fullscreen checkbox / resolution combobox / resolution editboxes
+    self:onWindowResized()
+
+    -- apply button
+    self.updateApplyButton()
+
+    -- aspect ratio editbox
+    local aspectRatioEditbox = winMgr:getWindow("orxonox/Display/Resolution/AspectRatio")
+    local currentAspectRatio = orxonox.CommandExecutor:query("getConfig Camera aspectRatio_")
+    aspectRatioEditbox:setText(currentAspectRatio)
+
+    -- themes combobox
+    local themeCombobox =  CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/Theme/Combobox"))
+    local currentTheme = orxonox.CommandExecutor:query("getConfig GUIManager guiScheme_")
+
+    for i = 0, themeCombobox:getDropList():getItemCount() - 1 do
+        local item = themeCombobox:getListboxItemFromIndex(i)
+        themeCombobox:setItemSelectState(item, (item:getText() == currentTheme))
+    end
+
+    -- vsync checkbox
+    local vsyncCheckbox = winMgr:getWindow("orxonox/Display/More/VSync")
+    local hasVSync = orxonox.GraphicsManager:getInstance():hasVSyncEnabled()
+    CEGUI.toCheckbox(vsyncCheckbox):setSelected(hasVSync)
+
+    -- fsaa combobox
+    local fsaaCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/More/FSAA"))
+    local currentFSAAMode = orxonox.GraphicsManager:getInstance():getFSAAMode()
+
+    for i = 0, fsaaCombobox:getDropList():getItemCount() - 1 do
+        local item = fsaaCombobox:getListboxItemFromIndex(i)
+        fsaaCombobox:setItemSelectState(item, (item:getText() == currentFSAAMode))
+    end
+
+    -- notice
+    self:updateRedLabel()
+
+    ------------------
+    -- Settings tab --
+    ------------------
+
+    -- fov editbox
+    local fovEditbox = winMgr:getWindow("orxonox/Settings/Fov")
+    local currentFov = orxonox.CommandExecutor:query("getConfig Camera fov_")
+    fovEditbox:setText(currentFov)
+
+    -- fps limit editbox
+    local fpsEditbox = winMgr:getWindow("orxonox/Settings/FpsLimit")
+    local currentFpsLimit = orxonox.CommandExecutor:query("getConfig GraphicsSettings fpsLimit")
+    fpsEditbox:setText(currentFpsLimit)
+
+    -- particle lod combobox
+    local particleLodCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Settings/ParticleLodCombobox"))
+    local currentParticleLod = orxonox.CommandExecutor:query("getConfig GraphicsSettings particlesDetailLevel")
+
+    if currentParticleLod == "" then
+        particleLodCombobox:disable()
+    else
+        particleLodCombobox:enable()
+
+        for i = 0, particleLodCombobox:getDropList():getItemCount() - 1 do
+            local item = particleLodCombobox:getListboxItemFromIndex(i)
+            particleLodCombobox:setItemSelectState(item, (tostring(i) == currentParticleLod))
+        end
+    end
+
+    -- mesh lod checkbox
+    local meshLodCheckbox = winMgr:getWindow("orxonox/Settings/MeshLodCheckbox")
+    local hasMeshLod = orxonox.CommandExecutor:query("getConfig GraphicsSettings enableMeshLoD")
+    if hasMeshLod == "true" then
+        hasMeshLod = true
+    elseif hasMeshLod == "false" then
+        hasMeshLod = false
+    end
+    CEGUI.toCheckbox(meshLodCheckbox):setSelected(hasMeshLod)
+
+    -- motion blur checkbox
+    local motionBlurCheckbox = winMgr:getWindow("orxonox/Settings/MotionBlurCheckbox")
+    local hasMotionBlur = orxonox.CommandExecutor:query("getConfig GraphicsSettings enableMotionBlur")
+    if hasMotionBlur == "true" then
+        hasMotionBlur = true
+    elseif hasMotionBlur == "false" then
+        hasMotionBlur = false
+    end
+    CEGUI.toCheckbox(motionBlurCheckbox):setSelected(hasMotionBlur)
+end
+
+function P:onWindowResized()
+    -- fullscreen checkbox
+    local fullscreenCheckbox = winMgr:getWindow("orxonox/Display/Resolution/Fullscreen")
+    local isFullscreen = orxonox.GraphicsManager:getInstance():isFullScreen()
+    CEGUI.toCheckbox(fullscreenCheckbox):setSelected(isFullscreen)
+
+    -- resolution combobox
+    local resolutionCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/Resolution/Combobox"))
+
+    local currentWidth = orxonox.GraphicsManager:getInstance():getWindowWidth()
+    local currentHeight = orxonox.GraphicsManager:getInstance():getWindowHeight()
+
+    if P.forceResolutionEditboxes then
+        currentWidth = P.newWidth
+        currentHeight = P.newHeight
+        P.forceResolutionEditboxes = false
+    end
+
+    local currentResolution = currentWidth .. " x " .. currentHeight
+
+    for i = 0, resolutionCombobox:getDropList():getItemCount() - 1 do
+        local item = resolutionCombobox:getListboxItemFromIndex(i)
+        resolutionCombobox:setItemSelectState(item, item:getText() == currentResolution)
+    end
+
+    -- resolution editboxes
+    self.updateResolutionEditboxes()
+end
+
+----------------------
+-- Helper functions --
+----------------------
+
+-- updates the text of the resolution checkboxes and checks if they should be enabled (only if the "custom" resolution was selected)
+function P.updateResolutionEditboxes()
+    -- resolution combobox
+    local resolutionCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Display/Resolution/Combobox"))
+
+    local currentWidth = orxonox.GraphicsManager:getInstance():getWindowWidth()
+    local currentHeight = orxonox.GraphicsManager:getInstance():getWindowHeight()
+
+    -- resolution editboxes
+    local widthEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxWidth")
+    local heightEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxHeight")
+    widthEditbox:disable()
+    heightEditbox:disable()
+
+    -- selected combobox item
+    local item = resolutionCombobox:getSelectedItem()
+    if item then
+        local itemText = item:getText()
+        if itemText ~= "custom" then
+            currentWidth = string.sub(itemText, 1, string.find(itemText, "x") - 2)
+            currentHeight = string.sub(itemText, string.find(itemText, "x") + 2)
+        else
+            widthEditbox:enable()
+            heightEditbox:enable()
+        end
+    end
+
+    widthEditbox:setText(currentWidth)
+    heightEditbox:setText(currentHeight)
+end
+
+-- checks if the apply button should be enabled or disabled (only enabled if the current settings are different from the selected values)
+function P.updateApplyButton()
+    -- fullscreen checkbox
+    local fullscreenCheckbox = winMgr:getWindow("orxonox/Display/Resolution/Fullscreen")
+    local isFullscreen = orxonox.GraphicsManager:getInstance():isFullScreen()
+    local fullscreenChanged = (isFullscreen ~= CEGUI.toCheckbox(fullscreenCheckbox):isSelected())
+
+    -- resolution editboxes
+    local widthEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxWidth")
+    local heightEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxHeight")
+    local currentWidth = tostring(orxonox.GraphicsManager:getInstance():getWindowWidth())
+    local currentHeight = tostring(orxonox.GraphicsManager:getInstance():getWindowHeight())
+    local widthChanged = (currentWidth ~= widthEditbox:getText())
+    local heightChanged = (currentHeight ~= heightEditbox:getText())
+    local resolutionEditboxesEnabled = not widthEditbox:isDisabled()
+
+    -- apply button
+    local applyButton = winMgr:getWindow("orxonox/Display/Resolution/Apply")
+
+    if fullscreenChanged or widthChanged or heightChanged or resolutionEditboxesEnabled then
+        applyButton:enable()
+    else
+        applyButton:disable()
+    end
+end
+
+function P.updateRedLabel()
+    -- theme
+    local themeCombobox = winMgr:getWindow("orxonox/Display/Theme/Combobox")
+    local currentTheme = orxonox.CommandExecutor:query("getConfig GUIManager guiScheme_")
+    local themeChanged = (currentTheme ~= themeCombobox:getText())
+
+    -- vsync
+    local vsyncCheckbox = winMgr:getWindow("orxonox/Display/More/VSync")
+    local hasVSync = orxonox.GraphicsManager:getInstance():hasVSyncEnabled()
+    local vsyncChanged = (hasVSync ~= CEGUI.toCheckbox(vsyncCheckbox):isSelected())
+
+    -- fsaa
+    local fsaaCombobox = winMgr:getWindow("orxonox/Display/More/FSAA")
+    local currentFSAAMode = orxonox.GraphicsManager:getInstance():getFSAAMode()
+    local fsaaChanged = (currentFSAAMode ~= fsaaCombobox:getText())
+
+    local needRestart = themeChanged or vsyncChanged or fsaaChanged
+
+    local notice = winMgr:getWindow("orxonox/Display/Notice")
+    notice:setVisible(not needRestart)
+    local noticeRed = winMgr:getWindow("orxonox/Display/NoticeRed")
+    noticeRed:setVisible(needRestart)
+end
+
+---------------------
+-- Event callbacks --
+---------------------
+
+-- resolution
+
+function P.callback_FullscreenCheckbox_CheckStateChanged(e)
+    P.updateApplyButton()
+end
+
+function P.callback_ResolutionCombobox_ListSelectionAccepted(e)
+    P.updateResolutionEditboxes()
+end
+
+function P.callback_ResolutionEditboxWidth_TextChanged(e)
+    P.updateApplyButton()
+end
+
+function P.callback_ResolutionEditboxHeight_TextChanged(e)
+    P.updateApplyButton()
+end
+
+-- theme
+
+function P.callback_ThemeCombobox_ListSelectionAccepted(e)
+    P.updateRedLabel()
+end
+
+-- vsync
+
+function P.callback_VSyncCheckbox_CheckStateChanged(e)
+    P.updateRedLabel()
+end
+
+-- fsaa
+
+function P.callback_FSAACombobox_ListSelectionAccepted(e)
+    P.updateRedLabel()
+end
+
+-- buttons
+
+function P.callback_Apply_Clicked(e)
+    -- resolution
+    local fullscreenCheckbox = winMgr:getWindow("orxonox/Display/Resolution/Fullscreen")
+    local checkedFullscreen = tostring(CEGUI.toCheckbox(fullscreenCheckbox):isSelected())
+
+    local widthEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxWidth")
+    local heightEditbox = winMgr:getWindow("orxonox/Display/Resolution/EditboxHeight")
+
+    P.newWidth = widthEditbox:getText()
+    P.newHeight = heightEditbox:getText()
+    P.forceResolutionEditboxes = true
+
+    -- start revert timer
+    P.oldWidth = orxonox.GraphicsManager:getInstance():getWindowWidth()
+    P.oldHeight = orxonox.GraphicsManager:getInstance():getWindowHeight()
+    P.oldFullscreen = orxonox.GraphicsManager:getInstance():isFullScreen()
+
+    P.revertTimerHandle = orxonox.CommandExecutor:query("delayreal 10 {hideGUI DecisionPopup; GraphicsManager setScreenResolution " .. P.oldWidth .. " " .. P.oldHeight .. " " .. tostring(P.oldFullscreen) .. "; config Core lastLevelTimestamp_ [expr [getConfig Core ogreConfigTimestamp_] + 1]}")
+
+    -- change settings
+    orxonox.CommandExecutor:execute("GraphicsManager setScreenResolution " .. P.newWidth .. " " .. P.newHeight .. " " .. checkedFullscreen)
+
+    P.updateApplyButton()
+
+    -- prompt for confirmation
+    openDecisionPopup("Do you want to keep these settings? (Settings will be reverted in 10 seconds if not accepted)", GraphicsMenu.callback_ApplyDecisionPopup)
+    if checkedFullscreen then
+        showCursor()
+    end
+end
+
+function P.callback_ApplyDecisionPopup(pressedOK)
+    orxonox.CommandExecutor:execute("killdelay " .. P.revertTimerHandle)
+
+    if not pressedOK then
+        orxonox.CommandExecutor:execute("GraphicsManager setScreenResolution " .. P.oldWidth .. " " .. P.oldHeight .. " " .. tostring(P.oldFullscreen))
+        P:onShow()
+    end
+
+    -- update timestamp to avoid showing the ogre config dialog again after the user accepted or reverted the resolution
+    orxonox.CommandExecutor:execute("config Core lastLevelTimestamp_ [expr [getConfig Core ogreConfigTimestamp_] + 1]")
+end
+
+function P.callback_Ok_Clicked(e)
+    -- aspect ratio
+    local aspectRatioEditbox = winMgr:getWindow("orxonox/Display/Resolution/AspectRatio")
+    orxonox.CommandExecutor:execute("config Camera aspectRatio_ " .. aspectRatioEditbox:getText())
+
+    -- theme
+    local themeCombobox = winMgr:getWindow("orxonox/Display/Theme/Combobox")
+    orxonox.CommandExecutor:execute("config GUIManager guiScheme_ " .. themeCombobox:getText())
+
+    -- vsync
+    local vsyncCheckbox = winMgr:getWindow("orxonox/Display/More/VSync")
+    local hasVSync = orxonox.GraphicsManager:getInstance():hasVSyncEnabled()
+    if hasVSync ~= CEGUI.toCheckbox(vsyncCheckbox):isSelected() then
+        orxonox.CommandExecutor:execute("GraphicsManager setVSync " .. tostring(CEGUI.toCheckbox(vsyncCheckbox):isSelected()))
+    end
+
+    -- fsaa
+    local fsaaCombobox = winMgr:getWindow("orxonox/Display/More/FSAA")
+    local currentFSAAMode = orxonox.GraphicsManager:getInstance():getFSAAMode()
+    if currentFSAAMode ~= fsaaCombobox:getText() then
+        orxonox.CommandExecutor:execute("GraphicsManager setFSAA {" .. fsaaCombobox:getText() .. "}") -- enclose argument in { ... } because it can contain [brackets] (conflicts with tcl)
+    end
+
+    -- fov
+    local fovEditbox = winMgr:getWindow("orxonox/Settings/Fov")
+    orxonox.CommandExecutor:execute("config Camera fov_ " .. fovEditbox:getText())
+
+    -- fps limit
+    local fpsEditbox = winMgr:getWindow("orxonox/Settings/FpsLimit")
+    orxonox.CommandExecutor:execute("config GraphicsSettings fpsLimit " .. fpsEditbox:getText())
+
+    -- particle lod
+    local particleLodCombobox = CEGUI.toCombobox(winMgr:getWindow("orxonox/Settings/ParticleLodCombobox"))
+    local item = particleLodCombobox:getSelectedItem()
+    if item then
+        orxonox.CommandExecutor:execute("config GraphicsSettings particlesDetailLevel " .. particleLodCombobox:getItemIndex(item))
+    end
+
+    -- mesh lod
+    local meshLodCheckbox = winMgr:getWindow("orxonox/Settings/MeshLodCheckbox")
+    orxonox.CommandExecutor:execute("config GraphicsSettings enableMeshLoD " .. tostring(CEGUI.toCheckbox(meshLodCheckbox):isSelected()))
+
+    -- motion blur
+    local motionBlurCheckbox = winMgr:getWindow("orxonox/Settings/MotionBlurCheckbox")
+    orxonox.CommandExecutor:execute("config GraphicsSettings enableMotionBlur " .. tostring(CEGUI.toCheckbox(motionBlurCheckbox):isSelected()))
+
+    hideMenuSheet(P.name)
+end
+
+function P.callback_Cancel_Clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/HUDSheet.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/HUDSheet.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/HUDSheet.lua	(revision 11817)
@@ -0,0 +1,15 @@
+-- HUDSheet.lua
+
+local P = {} -- Local alias, always use it in this file
+HUDSheet = P -- Global name
+setmetatable(P, require("GUISheet")) -- Inherit from GUISheet
+P.__index = P -- Provide class character
+
+-- Use this function to construct a new HUDSheet
+function P.new(name)
+    local newSheet = GUISheet.new(name)
+    setmetatable(newSheet, P)
+    return newSheet
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/HighscoreMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/HighscoreMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/HighscoreMenu.lua	(revision 11817)
@@ -0,0 +1,169 @@
+-- HighscoreMenu.lua
+
+local P = createMenuSheet("HighscoreMenu")
+
+P.highscoreList = {}
+P.tabList = {}
+P.linesList = {}
+P.levelList = {}
+
+
+P.imageHeight = 50
+
+function P.onLoad()
+    P.createLevelList()    
+end
+
+function P.onShow()
+    
+    -- reset tables
+    P.highscoreList = {}
+    P.tabList = {}
+    P.linesList = {}
+
+    -- fetch save scores and write it into the list
+    for i=orxonox.Highscore:getInstance():getNumberOfHighscores()-1,0,-1 do
+        table.insert(P.highscoreList, orxonox.Highscore:getInstance():getHighscore(i))
+    
+    end
+    
+    -- read minigames out of the levelList
+    for k,v in pairs(P.levelList) do
+        if(v:getName() ~= "Hover level" and v:getName() ~= "Pong") then   -- hover and pong dont contain relevant scores
+            P.createFilterTab(v:getName(), v:getName())
+        end
+    end
+  
+end
+function P.onHide()
+
+    -- delete old windows to reload them on show
+    local tabControl = winMgr:getWindow("orxonox/HighscoreTabControl")
+    for k,v in pairs(P.tabList) do
+            local default = winMgr:getWindow(v)
+            tabControl:removeChildWindow(default)
+            winMgr:destroyWindow(default)
+    end
+end
+function P.createLevelList()
+    P.levelList = {}
+    local size = orxonox.LevelManager:getInstance():getNumberOfLevels()
+    local index = 0
+    local level = nil
+    while index < size do
+        level = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
+        if (level ~= nil and level:getXMLFilename() ~= "_temp.oxw" and level:hasTag("minigame")) then
+            table.insert(P.levelList, level)
+        end
+        index = index + 1
+    end
+end
+function P.createFilterTab(name, tag)
+    -- create unique tab window name
+    local tabName = "orxonox/HighscoreLevelTab"
+    if tag ~= nil then
+        tabName = tabName..tag
+    end
+
+    table.insert(P.tabList, tabName)
+    -- create new tab window with desired name
+    local default = (winMgr:createWindow("DefaultWindow", tabName))
+    default:setText(name)
+    default:setProperty("UnifiedMaxSize", "{{1,0},{1,0}}")
+    default:setProperty("UnifiedAreaRect", "{{0,0},{0,0},{1,0},{1,0}}")
+    local pane = winMgr:createWindow("MenuWidgets/ScrollablePane", tabName .. "pane") 
+    pane:setSize(CEGUI.UVector2(CEGUI.UDim(1,0),CEGUI.UDim(1,0)))
+    default:addChildWindow(pane)
+
+   
+    local offset = 2
+    for k,v in pairs(P.highscoreList) do
+        -- split the score ("Playername./.game./.score")
+        local splitlist = P.Split(v,"./.")
+        if(splitlist[2] == name)then  
+            local line = P.createPickupEntry(tabName .. k,k,tag)
+            table.insert(P.linesList, line)
+            line:setYPosition(CEGUI.UDim(0,offset))
+            offset = offset + line:getHeight():asAbsolute(1)+2
+            pane:addChildWindow(line)
+        end
+        
+    end
+
+    local tabControl = winMgr:getWindow("orxonox/HighscoreTabControl")
+    tabControl:addChildWindow(default)
+ 
+
+    
+end
+function P.createPickupEntry(parent,k,tag)
+   
+    local name = "orxonox/HiscoreEntry" .. parent
+    local splitlist = P.Split(P.highscoreList[k],"./.")
+    local item = winMgr:createWindow("DefaultWindow", name)
+    item:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0), CEGUI.UDim(0, P.imageHeight)))
+    item:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
+
+    local player = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Player")
+    player:setText(splitlist[1])
+    player:setPosition(CEGUI.UVector2(CEGUI.UDim(0.005,0), CEGUI.UDim(0,0)))
+    player:setSize(CEGUI.UVector2(CEGUI.UDim(0.49, 0), CEGUI.UDim(0, P.imageHeight)))
+    
+    item:addChildWindow(player)
+        
+    local score = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Score")
+    score:setText(splitlist[3])
+    score:setPosition(CEGUI.UVector2(CEGUI.UDim(0.5,0), CEGUI.UDim(0,0)))
+    score:setSize(CEGUI.UVector2(CEGUI.UDim(0.495, 0), CEGUI.UDim(0, P.imageHeight)))
+    
+    item:addChildWindow(score)
+
+    return item
+end
+function P.HighscoreGetSelectedLevel()
+    -- choose the active listbox
+    local tabControl = CEGUI.toTabControl(winMgr:getWindow("orxonox/HighscoreTabControl"))
+    local listbox = CEGUI.toListbox(tabControl:getTabContentsAtIndex(tabControl:getSelectedTabIndex()))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        -- get the right tab and the right index
+        local tabIndexes = P.activeTabIndexes[tabControl:getSelectedTabIndex()+1]
+        local index = tabIndexes[listbox:getItemIndex(choice)+1]
+        return P.levelList[index]
+    else
+        return nil
+    end
+end
+function P.Split(str, delim, maxNb)
+    -- Eliminate bad cases...
+    if string.find(str, delim) == nil then
+        return { str }
+    end
+    if maxNb == nil or maxNb < 1 then
+        maxNb = 0    -- No limit
+    end
+    local result = {}
+    local pat = "(.-)" .. delim .. "()"
+    local nb = 0
+    local lastPos
+    for part, pos in string.gfind(str, pat) do
+        nb = nb + 1
+        result[nb] = part
+        lastPos = pos
+        if nb == maxNb then break end
+    end
+    -- Handle the last field
+    if nb ~= maxNb then
+        result[nb + 1] = string.sub(str, lastPos)
+    end
+    return result
+end
+
+
+
+function P.HighscoreBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/HostMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/HostMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/HostMenu.lua	(revision 11817)
@@ -0,0 +1,121 @@
+-- HostMenu.lua
+
+local P = createMenuSheet("HostMenu")
+
+P.multiplayerMode = "startServer"
+
+P.levelList = {}
+P.itemList = {}
+P.showAll = false
+
+function P.onLoad()
+    P.multiplayerMode = "startServer"
+    local window = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+    local button = tolua.cast(window,"CEGUI::Checkbox")
+    button:setSelected(false)
+    P.createLevelList()
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/HostMenuStartButton"),
+            ["callback"]  = P.HostMenuStartButton_clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/HostMenuBackButton"),
+            ["callback"]  = P.HostMenuBackButton_clicked
+    })
+end
+
+function P.onShow()
+    if P.showAll ~= orxonox.GUIManager:inDevMode() then
+        local window = winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox")
+        local button = tolua.cast(window,"CEGUI::Checkbox")
+        P.showAll = not P.showAll
+        button:setSelected(P.showAll)
+    end
+
+    if P.multiplayerMode == "startServer" then
+        local window = winMgr:getWindow("orxonox/HostMenuHostButton")
+        local button = tolua.cast(window,"CEGUI::RadioButton")
+        button:setSelected(true)
+        P.createLevelList()
+    end
+
+    if P.multiplayerMode == "startDedicated" then
+        local window = winMgr:getWindow("orxonox/HostMenuDedicatedButton")
+        local button = tolua.cast(window,"CEGUI::RadioButton")
+        button:setSelected(true)
+        P.createLevelList()
+    end
+end
+
+function P.createLevelList()
+    P.levelList = {}
+    P.itemList = {}
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/HostMenuListbox"))
+    listbox:resetList()
+    orxonox.GUIManager:setItemTooltipsEnabledHelper(listbox, true)
+    local preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
+    local size = orxonox.LevelManager:getInstance():getNumberOfLevels()
+    local index = 0
+    local level = nil
+    while index < size do
+        level = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
+        if level ~= nil then
+            if P.showAll or not level:hasTag("test") then
+                table.insert(P.levelList, level)
+            end
+        end
+        index = index + 1
+    end
+    --TODO: Reintroduce sorting, if needed. At the moment it's sorted by filename.
+    --table.sort(levelList)
+    for k,v in pairs(P.levelList) do
+        local item = CEGUI.createListboxTextItem(v:getName())
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        listbox:addItem(item)
+        if v:getXMLFilename() == preselect then
+            listbox:setItemSelectState(item, true)
+        end
+        P.itemList[k] = listbox:getListboxItemFromIndex(k-1)
+        orxonox.GUIManager:setTooltipTextHelper(P.itemList[k], v:getDescription())
+    end
+end
+
+function P.HostMenuBuildServerButton_clicked(e)
+    P.multiplayerMode = "startServer"
+    P.createLevelList()
+end
+
+function P.HostMenuDedicatedButton_clicked(e)
+    P.multiplayerMode = "startDedicated"
+    P.createLevelList()
+end
+
+function P.HostMenuBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+function P.HostMenuStartButton_clicked(e)
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/HostMenuListbox"))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = listbox:getItemIndex(choice)
+        local level = P.levelList[index+1]
+        if level ~= nil then
+            orxonox.execute(P.multiplayerMode .. " " .. level:getXMLFilename())
+            hideAllMenuSheets()
+        end
+    end
+end
+
+function P.MultiplayerShowAll_clicked(e)
+    local checkbox = tolua.cast(winMgr:getWindow("orxonox/MultiplayerShowAllCheckbox"), "CEGUI::Checkbox")
+    local show = checkbox:isSelected()
+    if show ~= P.showAll then
+        P.showAll = show
+        P.createLevelList()
+   end
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/InGameMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/InGameMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/InGameMenu.lua	(revision 11817)
@@ -0,0 +1,89 @@
+-- InGameMenu.lua
+
+local P = createMenuSheet("InGameMenu")
+P.loadAlong = { "DecisionPopup" }
+
+function P.onLoad()
+    P.multiplayerMode = "startClient"
+
+    --button are arranged in a 5x1 matrix, the left lower item is nil
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/InGameMenu_ReturnButton"),
+            ["callback"]  = P.button_return_clicked
+    })
+
+    P:setButton(2, 1, {
+            ["button"] = winMgr:getWindow("orxonox/InGameMenu_ReloadLevelButton"),
+            ["callback"]  = P.button_reloadLevel_clicked
+    })
+
+    P:setButton(3, 1, {
+            ["button"] = winMgr:getWindow("orxonox/InGameMenu_MainMenuButton"),
+            ["callback"]  = P.button_mainmenu_clicked
+    })
+
+    P:setButton(4, 1, {
+            ["button"] = winMgr:getWindow("orxonox/InGameMenu_SettingsButton"),
+            ["callback"]  = P.button_settings_clicked
+    })
+
+    P:setButton(5, 1, {
+            ["button"] = winMgr:getWindow("orxonox/InGameMenu_QuitButton"),
+            ["callback"]  = P.button_quit_clicked
+    })
+end
+
+function P.onShow()
+    if P:hasSelection() == false then
+        P:setSelection(1, 1)
+    end
+
+    orxonox.execute("setPause 1")
+end
+
+function P.onQuit()
+    orxonox.execute("setPause 0")
+end
+
+-- events for ingamemenu
+function P.button_quit_clicked(e)
+    openDecisionPopup( "Do you really want to quit the game?", InGameMenu.exitCallback )
+end
+
+function P.button_mainmenu_clicked(e)
+    openDecisionPopup( "Do you really want to return to the main menu?", InGameMenu.mainMenuCallback )
+end
+
+function P.button_settings_clicked(e)
+    showMenuSheet("SettingsMenu", true)
+end
+
+function P.button_reloadLevel_clicked(e)
+    hideMenuSheet("InGameMenu")
+    orxonox.execute("reloadLevel")
+end
+
+function P.button_return_clicked(e)
+    hideMenuSheet("InGameMenu")
+end
+
+function P.mainMenuCallback(doExit)
+    if doExit then
+        orxonox.execute("startMainMenu")
+        hideMenuSheet("InGameMenu")
+    else
+        P.onShow()
+    end
+end
+
+function P.exitCallback(doExit)
+    if doExit then
+        hideMenuSheet("InGameMenu")
+        orxonox.execute("exit")
+    else
+        P.onShow()
+    end
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/InGamePickupHUD.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/InGamePickupHUD.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/InGamePickupHUD.lua	(revision 11817)
@@ -0,0 +1,33 @@
+-- InGamePickupHUD.lua
+
+BasicGUI = require("BasicGUI")
+local P = BasicGUI:new() --inherit everything from the gui package
+if _REQUIREDNAME == nil then
+    InGamePickupHUD = P
+else
+    _G[_REQUIREDNAME] = P
+end
+
+P.filename = "InGamePickupHUD"
+P.layoutString = "InGamePickupHUD.layout"
+
+function P:init()
+end
+
+
+-- events for ingamemenu
+
+
+function P.button_Pickup_clicked(e)
+    orxonox.Game:getInstance():popState()
+    orxonox.Game:getInstance():popState()
+    orxonox.Game:getInstance():requestState("mainmenu")
+    hideGUI("InGameMenu")
+end
+
+function P.close_button_clicked()
+    hideGUI("InGamePickupHUD")
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/InfoPopup.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/InfoPopup.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/InfoPopup.lua	(revision 11817)
@@ -0,0 +1,34 @@
+-- InfoPopup.lua
+
+local P = createMenuSheet("InfoPopup")
+
+function P.execute(functionPtr, arguments)
+    if functionPtr ~= nil then
+        if arguments ~= nil then
+            functionPtr(arguments)
+        else
+            functionPtr()
+        end
+    end
+end
+
+function P.setText(text)
+    winMgr:getWindow("orxonox/InfoPopup_text"):setText( text )
+end
+
+function P.setCloseButton(closeButton)
+    close = winMgr:getWindow("orxonox/InfoPopup_close")
+    close:setVisible(closeButton)
+    if(not closeButton) then
+        close:deactivate();
+    else
+        close:activate();
+    end
+end
+
+-- events for ingamemenu
+function P.close(e)
+    hideMenuSheet(P.name)
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/InitialiseGUI.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/InitialiseGUI.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/InitialiseGUI.lua	(revision 11817)
@@ -0,0 +1,37 @@
+-- Define some global shortcuts for common Managers
+guiMgr    = orxonox.GUIManager:getInstance()
+inputMgr  = orxonox.InputManager:getInstance()
+schemeMgr = CEGUI.SchemeManager:getSingleton()
+winMgr    = CEGUI.WindowManager:getSingleton()
+
+local scheme = orxonox.CommandExecutor:query("getConfig GUIManager guiScheme_")
+-- Load all required skins
+--schemeMgr:create("TaharezGreenLook.scheme")
+schemeMgr:create(scheme .. "Look.scheme")
+--schemeMgr:create("TaharezLook.scheme")
+--schemeMgr:create("WindowsLook.scheme")
+--schemeMgr:create("VanillaLook.scheme")
+--schemeMgr:create("SleekSpaceLook.scheme")
+
+-- Connect skin specific window types with our own window types
+-- By loading a different file (if there is) you can change the skin
+-- of the menus or the HUD independently
+--schemeMgr:create("TaharezGreenMenuWidgets.scheme")
+--menuImageSet = "TaharezGreenLook"
+--schemeMgr:create("TaharezGreenHUDWidgets.scheme")
+--hudImageSet = "TaharezGreenLook"
+schemeMgr:create(scheme .. "MenuWidgets.scheme")
+menuImageSet = scheme .. "Look"
+schemeMgr:create(scheme .. "HUDWidgets.scheme")
+hudImageSet = scheme .. "Look"
+
+-- Just a remaining test hack
+schemeMgr:create("OrxonoxGUIScheme.scheme")
+
+local system = CEGUI.System:getSingleton()
+system:setDefaultMouseCursor(menuImageSet, "MouseArrow")
+system:setDefaultFont("BlueHighway-12")
+system:setDefaultTooltip("MenuWidgets/Tooltip")
+
+-- Convenience function and additional tools
+require("GUITools")
Index: /code/branches/RacingBots_FS18/data/gui/scripts/KeyBindMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/KeyBindMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/KeyBindMenu.lua	(revision 11817)
@@ -0,0 +1,275 @@
+-- KeyBindMenu.lua
+
+local P = createMenuSheet("KeyBindMenu")
+P.loadAlong = { "InfoPopup" }
+
+function P.onLoad()
+
+    commandList = {}
+    table.insert(commandList, "fire 0")
+    table.insert(commandList, "fire 1 | unfire")
+    table.insert(commandList, "onpress fire 2")
+    table.insert(commandList, "onpress fire 3")
+    table.insert(commandList, "scale 1 moveFrontBack")
+    table.insert(commandList, "scale -1 moveFrontBack")
+    table.insert(commandList, "boost")
+    table.insert(commandList, "scale 1 moveRightLeft")
+    table.insert(commandList, "scale -1 moveRightLeft")
+    table.insert(commandList, "scale 1 moveUpDown")
+    table.insert(commandList, "scale -1 moveUpDown")
+    table.insert(commandList, "scale -1 rotateRoll")
+    table.insert(commandList, "scale 1 rotateRoll")
+    table.insert(commandList, "scale 1 rotateYaw")
+    table.insert(commandList, "scale -1 rotateYaw")
+    table.insert(commandList, "scale 1 rotatePitch")
+    table.insert(commandList, "scale -1 rotatePitch")
+    table.insert(commandList, "NewHumanController changeMode")
+    table.insert(commandList, "switchCamera")
+    table.insert(commandList, "InGameConsole openConsole")
+    table.insert(commandList, "OverlayGroup toggleVisibility Debug")
+    table.insert(commandList, "OverlayGroup toggleVisibility Stats")
+    table.insert(commandList, "OrxonoxOverlay toggleVisibility QuestGUI")
+    table.insert(commandList, "OrxonoxOverlay toggleVisibility PickupInventory")
+    table.insert(commandList, "startchat")
+    table.insert(commandList, "startchat_small")
+    table.insert(commandList, "mouseLook")
+    table.insert(commandList, "pause")
+    table.insert(commandList, "printScreen")
+    if orxonox.GUIManager:inDevMode() then
+        table.insert(commandList, "printScreenHD")
+        table.insert(commandList, "createSkybox")
+    end
+
+    nameList = {}
+    table.insert(nameList, "Primary Fire")
+    table.insert(nameList, "Secondary Fire")
+    table.insert(nameList, "Fire Rocket")
+    table.insert(nameList, "Fire Alternative Rocket")
+    table.insert(nameList, "Accelerate")
+    table.insert(nameList, "Break")
+    table.insert(nameList, "Boost")
+    table.insert(nameList, "Move Right")
+    table.insert(nameList, "Move Left")
+    table.insert(nameList, "Move Up")
+    table.insert(nameList, "Move Down")
+    table.insert(nameList, "Roll Right")
+    table.insert(nameList, "Roll Left")
+    table.insert(nameList, "Yaw Left")
+    table.insert(nameList, "Yaw Right")
+    table.insert(nameList, "Pitch Up")
+    table.insert(nameList, "Pitch Down")
+    table.insert(nameList, "Switch Input Mode")
+    table.insert(nameList, "Switch Camera")
+    table.insert(nameList, "Open Console")
+    table.insert(nameList, "Show Debug")
+    table.insert(nameList, "Show Stats")
+    table.insert(nameList, "Show Quests")
+    table.insert(nameList, "Show Pickups")
+    table.insert(nameList, "Show Chat")
+    table.insert(nameList, "Show small Chat")
+    table.insert(nameList, "Look Around")
+    table.insert(nameList, "Pause")
+    table.insert(nameList, "Screenshot")
+    if orxonox.GUIManager:inDevMode() then
+        table.insert(nameList, "HD screenshot")
+        table.insert(nameList, "Create Skybox")
+    end
+
+    linesList = {}
+
+    --Calculate design parameters:
+    sampleWindow = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/KeyBindPane/SampleWindow")
+    sampleWindow:setText("SampleText")
+
+    local size = getMinTextSize(sampleWindow)
+    lineHeight = size[1]
+
+    commandWidth = 0
+    for k,v in pairs(commandList) do
+        sampleWindow:setText(nameList[k])
+        size = getMinTextSize(sampleWindow)
+        if size[2] > commandWidth then
+            commandWidth = size[2]
+        end
+    end
+
+    sampleWindow:setText("add")
+    size = getMinTextSize(sampleWindow)
+    addWidth = size[2]
+
+    sampleWindow:setText("X")
+    size = getMinTextSize(sampleWindow)
+    clearWidth = size[2]
+
+    spaceWidth = math.floor(1/14*commandWidth)
+
+    buttonWidth = 145
+
+    P.createLines()
+
+    local funct = luaState:createLuaFunctor("KeyBindMenu.callback()")
+    orxonox.KeyBinderManager:getInstance():registerKeybindCallback(funct)
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/KeyBindBackButton"),
+            ["callback"]  = P.KeyBindBackButton_clicked
+    })
+end
+
+function P.KeyNameNiceifier(key)
+    local name = string.sub(key, string.find(key, '%.(.*)')+1)
+    local group = string.sub(key, string.find(key, '(.*)%.'))
+    group = string.sub(group,1,string.len(group)-1)
+    if( group == "Keys") then
+        return "Key " .. string.sub(name, string.find(name, 'Key(.*)')+3)
+    elseif( group == "MouseButtons") then
+        return "Mouse " .. name
+    elseif( string.find(group, "JoyStickButtons") ~= nil ) then
+        return "Joystick " .. name
+    elseif( string.find(group, "JoyStickAxes") ~= nil ) then
+        return "Joystick Axis " .. string.sub(name, 5, 6) .. string.sub(name, string.find(name, 'Axis%d%d(.*)')+6)
+    elseif( group == "MouseAxes" ) then
+        return "Mouse " .. string.sub(name, string.find(name, '.(.*)')+1) .. " " .. string.sub(name, 1, 1) .. "-Axis"
+    end
+    return key
+end
+
+function P.createLine(k)
+    local offset = 0
+    local line = winMgr:createWindow("DefaultWindow", "orxonox/KeyBindPane/Binding" .. k)
+    line:setHeight(CEGUI.UDim(0, lineHeight))
+    line:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, lineHeight*(k-1))))
+
+    local command = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/KeyBindPane/Binding" .. k .. "/Command")
+    command:setText(nameList[k])
+    command:setSize(CEGUI.UVector2(CEGUI.UDim(0, commandWidth), CEGUI.UDim(1, 0)))
+    command:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0, 0)))
+    line:addChildWindow(command)
+    offset = offset + commandWidth + spaceWidth
+
+    local plus = winMgr:createWindow("MenuWidgets/TabButton", "orxonox/KeyBindPane/Binding" .. k .. "/Plus")
+    plus:setSize(CEGUI.UVector2(CEGUI.UDim(0, addWidth), CEGUI.UDim(0.7, 0)))
+    plus:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.15, 0)))
+    plus:setText("add")
+    orxonox.GUIManager:subscribeEventHelper(plus, "Clicked", P.name .. ".KeyBindPlus_clicked")
+    line:addChildWindow(plus)
+    offset = offset + addWidth + spaceWidth
+
+    local numButtons = orxonox.KeyBinderManager:getInstance():getCurrent():getNumberOfBindings(commandList[k]);
+    for i=0,(numButtons-1) do
+        local button = winMgr:createWindow("MenuWidgets/TabButton", "orxonox/KeyBindPane/Binding" .. k .. "/Button" .. i)
+        local name = orxonox.KeyBinderManager:getInstance():getCurrent():getBinding(commandList[k],i)
+        name = P.KeyNameNiceifier(name)
+        button:setText(name)
+        sampleWindow:setText(name)
+        local size = getMinTextSize(sampleWindow)
+        local buttonWidth = size[2]
+        button:setSize(CEGUI.UVector2(CEGUI.UDim(0, buttonWidth), CEGUI.UDim(0.7, 0)))
+        button:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.15, 0)))
+        orxonox.GUIManager:subscribeEventHelper(button, "Clicked", P.name .. ".KeyBindButton_clicked")
+        --button:subscribeScriptedEvent("EventClicked", P.name .. ".KeyBindButton_clicked")
+        line:addChildWindow(button)
+        offset = offset + buttonWidth
+
+        local clear = winMgr:createWindow("MenuWidgets/TabButton", "orxonox/KeyBindPane/Binding" .. k .. "/Clear" .. i)
+        clear:setSize(CEGUI.UVector2(CEGUI.UDim(0, clearWidth), CEGUI.UDim(0.7, 0)))
+        clear:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.15, 0)))
+        clear:setText("X")
+        orxonox.GUIManager:subscribeEventHelper(clear, "Clicked", P.name .. ".KeyBindClear_clicked")
+        line:addChildWindow(clear)
+        offset = offset + clearWidth + spaceWidth
+    end
+
+    line:setWidth(CEGUI.UDim(0, offset+clearWidth))
+
+    return line
+end
+
+function P.createLines()
+    local window = winMgr:getWindow("orxonox/KeyBindPane")
+
+    for k,v in pairs(commandList) do
+        local line = P.createLine(k)
+        table.insert(linesList, line)
+        window:addChildWindow(line)
+    end
+
+    local pane = tolua.cast(window, "CEGUI::ScrollablePane")
+    pane:setVerticalStepSize(getScrollingStepSize(window))
+end
+
+function P.KeyBindButton_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+    local buttonNr = tonumber(match())
+
+    local arguments = {}
+    arguments[1] = commandNr
+    arguments[2] = buttonNr
+    openInfoPopup("Press any button/key or move a mouse/joystick axis.", KeyBindMenu.keybind, false, arguments)
+end
+
+function P.KeyBindPlus_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+
+    local arguments = {}
+    arguments[1] = commandNr
+    openInfoPopup("Press any button/key or move a mouse/joystick axis.", KeyBindMenu.keybind, false, arguments)
+end
+
+function P.KeyBindClear_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+    local buttonNr = tonumber(match())
+
+    local str = orxonox.KeyBinderManager:getInstance():getCurrent():getBinding(commandList[commandNr], buttonNr)
+    orxonox.KeyBinderManager:getInstance():unbind(str)
+
+    P.callback()
+end
+
+function P.keybind(arguments)
+    local commandNr = arguments[1]
+    local buttonNr = arguments[2]
+    if buttonNr ~= nil then
+        local str = orxonox.KeyBinderManager:getInstance():getCurrent():getBinding(commandList[commandNr], buttonNr)
+        orxonox.KeyBinderManager:getInstance():unbind(str)
+    end
+
+    orxonox.KeyBinderManager:getInstance():keybind(commandList[commandNr])
+end
+
+function P.callback()
+    local pane = tolua.cast(winMgr:getWindow("orxonox/KeyBindPane"), "CEGUI::ScrollablePane")
+    local position = pane:getVerticalScrollPosition()
+    while table.getn(linesList) ~= 0 do
+        if linesList[1] ~= nil then
+            winMgr:destroyWindow(linesList[1]:getName())
+        end
+        table.remove(linesList, 1)
+    end
+
+    linesList = {}
+
+    P.createLines()
+    if(InfoPopup ~= nil) then
+        InfoPopup.close()
+    end
+    pane:setVerticalScrollPosition( position )
+end
+
+function P.KeyBindBackButton_clicked(e)
+    hideMenuSheet("KeyBindMenu")
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/MainMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/MainMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/MainMenu.lua	(revision 11817)
@@ -0,0 +1,75 @@
+-- MainMenu.lua
+
+local P = createMenuSheet("MainMenu")
+P.loadAlong = { "SingleplayerMenu", "MultiplayerMenu", "HighscoreMenu", "SettingsMenu", "CreditsMenu" }
+
+function P.onLoad()
+    --buttons are arranged in a 6x1 Matrix (list)
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/QuickGameTestButton"),
+            ["callback"]  = P.QuickGameTestButton_clicked
+    })
+
+    P:setButton(2, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerButton"),
+            ["callback"]  = P.SingleplayerButton_clicked
+    })
+
+    P:setButton(3, 1, {
+            ["button"] = winMgr:getWindow("orxonox/MultiplayerButton"),
+            ["callback"]  = P.MultiplayerButton_clicked
+    })
+
+    P:setButton(4, 1, {
+            ["button"] = winMgr:getWindow("orxonox/HighscoreButton"),
+            ["callback"]  = P.MultiplayerButton_clicked
+    })
+
+    P:setButton(5, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SettingsButton"),
+            ["callback"]  = P.SettingsButton_clicked
+    })
+
+    P:setButton(6, 1, {
+            ["button"] = winMgr:getWindow("orxonox/CreditsButton"),
+            ["callback"]  = P.CreditsButton_clicked
+    })
+
+    P:setButton(7, 1, {
+            ["button"] = winMgr:getWindow("orxonox/ExitButton"),
+            ["callback"]  = P.ExitButton_clicked
+    })
+end
+
+-- events for MainMenu
+function P.QuickGameTestButton_clicked(e)
+    hideAllMenuSheets()
+    orxonox.execute("startGame")
+end
+
+function P.SingleplayerButton_clicked(e)
+    showMenuSheet("SingleplayerMenu", true)
+end
+
+function P.MultiplayerButton_clicked(e)
+    showMenuSheet("MultiplayerMenu", true)
+end
+
+function P.HighscoreButton_clicked(e)
+    showMenuSheet("HighscoreMenu", true)
+end
+
+function P.SettingsButton_clicked(e)
+    showMenuSheet("SettingsMenu", true)
+end
+
+function P.CreditsButton_clicked(e)
+    showMenuSheet("CreditsMenu", true)
+end
+
+function P.ExitButton_clicked(e)
+    orxonox.execute("exit")
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/MenuSheet.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/MenuSheet.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/MenuSheet.lua	(revision 11817)
@@ -0,0 +1,36 @@
+-- MenuSheet.lua
+-- Base class for all GUI sheets that represent a menu.
+-- Inherits itself from GUISheet
+
+local P = {}  -- Local alias, always use it in this file
+MenuSheet = P -- Global name
+setmetatable(P, require("GUISheet")) -- Inherit from GUISheet
+P.__index = P -- Provide class character
+
+-- Use this function to construct a new MenuSheet.
+-- Parameters:
+-- Except for _name, you can provide nil. Then the default value will be used.
+-- For _tShowCusor and _tUseKeyboard you can specify tribool(dontcare) if the value doesn't matter at all. Then the value of the underlaying sheet will be used.
+function P.new(_name, _bHidePrevious, _tShowCursor, _tUseKeyboard, _bBlockJoyStick)
+    local newSheet = GUISheet.new(_name)
+    newSheet.bHidePrevious  = handleDefArg(_bHidePrevious,  true)
+    newSheet.tShowCursor    = handleDefArg(_tShowCusor,     tribool(true))
+    newSheet.tUseKeyboard   = handleDefArg(_tUseKeyboard,   tribool(true))
+    newSheet.bBlockJoyStick = handleDefArg(_bBlockJoyStick, false)
+
+    setmetatable(newSheet, P)
+    return newSheet
+end
+
+function P:load()
+    -- Create the input state
+    self.inputState = guiMgr:createInputState("GUI_" .. self.name,
+        self.tShowCursor, self.tUseKeyboard, self.bBlockJoyStick)
+
+    -- load() of base 'class'
+    GUISheet.load(self)
+
+    return self
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/MiscConfigMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/MiscConfigMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/MiscConfigMenu.lua	(revision 11817)
@@ -0,0 +1,209 @@
+-- MiscConfigMenu.lua
+
+local P = createMenuSheet("MiscConfigMenu", true, tribool(true), tribool(true))
+
+P.commandList = {}
+P.nameList = {}
+P.linesList = {}
+
+P.sampleWindow = nil
+
+P.lineHeight = 0
+P.commandWidth = 0
+P.editboxWidth = 0
+P.resetWidth = 0
+P.spaceWidth = 0
+
+function P.onLoad()
+
+    P.commandList = {}
+    table.insert(P.commandList, "Highscore playerName_")
+    table.insert(P.commandList, "KeyBinder mouseSensitivity_")
+    table.insert(P.commandList, "KeyBinder mouseSensitivityDerived_")
+    table.insert(P.commandList, "KeyBinder bDeriveMouseInput_")
+    table.insert(P.commandList, "KeyBinder mouseWheelStepSize_")
+    table.insert(P.commandList, "Shell maxHistoryLength_")
+    table.insert(P.commandList, "Core bStartIOConsole_")
+    table.insert(P.commandList, "Game fpsLimit_")
+    table.insert(P.commandList, "Spectator speed_")
+    table.insert(P.commandList, "SpaceShip bInvertYAxis_")
+    table.insert(P.commandList, "LevelManager defaultLevelName_")
+    table.insert(P.commandList, "Gametype initialStartCountdown_")
+    table.insert(P.commandList, "Gametype bAutoStart_")
+    table.insert(P.commandList, "Gametype bAutoEnd_")
+    table.insert(P.commandList, "Gametype numberOfBots_")
+    table.insert(P.commandList, "UnderAttack gameTime_")
+    table.insert(P.commandList, "TeamDeathmatch teams_")
+    table.insert(P.commandList, "TeamDeathmatch maxScore_")
+    table.insert(P.commandList, "HumanPlayer nick_")
+    table.insert(P.commandList, "ChatOverlay displayTime_")
+    table.insert(P.commandList, "Core bDevMode_")
+    table.insert(P.commandList, "HUDNavigation MarkerLimit_")
+    table.insert(P.commandList, "HUDNavigation showDistance")
+    table.insert(P.commandList, "HUDRadar RadarMode_")
+
+    P.nameList = {}
+    table.insert(P.nameList, "Playername")
+    table.insert(P.nameList, "Mouse sensitivity")
+    table.insert(P.nameList, "Mouse acceleration")
+    table.insert(P.nameList, "Derive mouse input")
+    table.insert(P.nameList, "Mouse wheel stepsize")
+    table.insert(P.nameList, "Shell: max. History length")
+    table.insert(P.nameList, "Start IOConsole")
+    table.insert(P.nameList, "FPS limit")
+    table.insert(P.nameList, "Spectator speed")
+    table.insert(P.nameList, "Invert Y-axis")
+    table.insert(P.nameList, "Default level")
+    table.insert(P.nameList, "Start countdown")
+    table.insert(P.nameList, "Autostart")
+    table.insert(P.nameList, "Autoend")
+    table.insert(P.nameList, "Number of Bots")
+    table.insert(P.nameList, "UnderAttack: game time")
+    table.insert(P.nameList, "TeamDeathmatch: Number of teams")
+    table.insert(P.nameList, "TeamDeathmatch: Score needed to end the game")
+    table.insert(P.nameList, "Playername")
+    table.insert(P.nameList, "Chat: display time")
+    table.insert(P.nameList, "Developer's Mode")
+    table.insert(P.nameList, "Marker Limit")
+    table.insert(P.nameList, "Show Distance next to cursor")
+    table.insert(P.nameList, "Set Radar on 3D mode")
+
+    P.linesList = {}
+
+    --Calculate design parameters:
+    P.sampleWindow = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/MiscConfigMenu/MiscConfigPane/SampleWindow")
+    P.sampleWindow:setText("SampleText")
+
+    local size = getMinTextSize(P.sampleWindow)
+    P.lineHeight = size[1]
+
+    P.commandWidth = 0
+    for k,v in pairs(P.commandList) do
+        P.sampleWindow:setText(P.nameList[k])
+        size = getMinTextSize(P.sampleWindow)
+        if size[2] > P.commandWidth then
+            P.commandWidth = size[2]
+        end
+    end
+
+    P.sampleWindow:setText("reset")
+    size = getMinTextSize(P.sampleWindow)
+    P.resetWidth = size[2]+20
+
+    P.spaceWidth = 10
+    
+    local pane = tolua.cast(winMgr:getWindow("orxonox/MiscConfigMenu/MiscConfigPane"), "CEGUI::ScrollablePane")
+    size = pane:getViewableArea()
+    P.editboxWidth = size:getWidth() - P.commandWidth - P.resetWidth - 5*P.spaceWidth
+
+    P.createLines()
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/MiscConfigMenu/CancelButton"),
+            ["callback"]  = P.MiscConfigCancelButton_clicked
+    })
+    
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/MiscConfigMenu/OKButton"),
+            ["callback"]  = P.MiscConfigOKButton_clicked
+    })
+end
+
+function P.createLine(k)
+    local offset = 0
+    -- content window for the entire line
+    local line = winMgr:createWindow("DefaultWindow", "orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. k)
+    line:setHeight(CEGUI.UDim(0, P.lineHeight))
+    line:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, P.lineHeight*(k-1))))
+
+    -- config name
+    local command = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Command")
+    command:setText(P.nameList[k])
+    command:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.commandWidth), CEGUI.UDim(1, 0)))
+    command:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0, 0)))
+    line:addChildWindow(command)
+    offset = offset + P.commandWidth + P.spaceWidth
+
+    -- config value (editable)
+    local configvalue = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Configvalue")
+    configvalue:setProperty("ReadOnly", "set:False")
+    local value = orxonox.CommandExecutor:query("getConfig " .. P.commandList[k])
+    configvalue:setText(value)
+    configvalue:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.editboxWidth), CEGUI.UDim(0.9, 0)))
+    configvalue:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.05, 0)))
+    -- enable the reset button if the value changed
+    orxonox.GUIManager:subscribeEventHelper(configvalue, "TextAccepted", P.name .. ".MiscConfigEditbox_textAccepted")
+    line:addChildWindow(configvalue)
+    offset = offset + P.editboxWidth + P.spaceWidth
+
+    -- reset button (only available when value changed)
+    local reset = winMgr:createWindow("MenuWidgets/Button", "orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Reset")
+    reset:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.resetWidth), CEGUI.UDim(0.9, 0)))
+    reset:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.05, 0)))
+    reset:setText("reset")
+    orxonox.GUIManager:subscribeEventHelper(reset, "Clicked", P.name .. ".MiscConfigResetButton_clicked")
+    line:addChildWindow(reset)
+    reset:setEnabled(false)
+    offset = offset + P.resetWidth + P.spaceWidth
+
+    line:setWidth(CEGUI.UDim(0, offset))
+
+    return line
+end
+
+function P.createLines()
+    local window = winMgr:getWindow("orxonox/MiscConfigMenu/MiscConfigPane")
+
+    for k,v in pairs(P.commandList) do
+        local line = P.createLine(k)
+        table.insert(P.linesList, line)
+        window:addChildWindow(line)
+    end
+
+    local pane = tolua.cast(window, "CEGUI::ScrollablePane")
+    pane:setVerticalStepSize(getScrollingStepSize(window))
+end
+
+function P.MiscConfigOKButton_clicked(e)
+    for k,v in pairs(P.commandList) do
+        -- save the changes
+        local editbox = winMgr:getWindow("orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Configvalue")
+        orxonox.CommandExecutor:execute("config " .. P.commandList[k] .. " " .. editbox:getText())
+        local resetButton = winMgr:getWindow("orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Reset")
+        resetButton:setEnabled(false)
+    end
+    
+    hideMenuSheet("MiscConfigMenu")
+end
+
+function P.MiscConfigCancelButton_clicked(e)
+    hideMenuSheet("MiscConfigMenu")
+end
+
+function P.MiscConfigEditbox_textAccepted(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+
+    local resetButton = winMgr:getWindow("orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. commandNr .. "/Reset")
+    resetButton:setEnabled(true)
+end
+
+function P.MiscConfigResetButton_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+
+    -- reload the old value
+    local editbox = winMgr:getWindow("orxonox/MiscConfigMenu/MiscConfigPane/ConfigCommand" .. commandNr .. "/Configvalue")
+    local value = orxonox.CommandExecutor:query("getConfig " .. P.commandList[commandNr])
+    editbox:setText(value)
+    
+    we.window:setEnabled(false)
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/MouseControlsMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/MouseControlsMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/MouseControlsMenu.lua	(revision 11817)
@@ -0,0 +1,106 @@
+-- MouseControlsMenu.lua
+
+local P = createMenuSheet("MouseControlsMenu")
+
+function P.onLoad()
+    block = false
+    mousenormalscrollbarwindow = tolua.cast(winMgr:getWindow("orxonox/MouseNormalScrollbar"),"CEGUI::Scrollbar")
+    mousederivescrollbarwindow = tolua.cast(winMgr:getWindow("orxonox/MouseDeriveScrollbar"),"CEGUI::Scrollbar")
+    normalwindow = tolua.cast(winMgr:getWindow("orxonox/MouseNormalButton"),"CEGUI::RadioButton")
+    derivewindow = tolua.cast(winMgr:getWindow("orxonox/MouseDeriveButton"),"CEGUI::RadioButton")
+    invertwindow = tolua.cast(winMgr:getWindow("orxonox/MouseInvertCheckbox"),"CEGUI::Checkbox")
+    mousenormalscrollbar_active = false
+    mousederivescrollbar_active = false
+    derive_active = orxonox.getConfig("KeyBinder","bDeriveMouseInput_")
+    invert_active = false
+    mousenormalsensitivity = orxonox.getConfig("KeyBinder","mouseSensitivity_")
+    mousederivesensitivity = orxonox.getConfig("KeyBinder","mouseSensitivityDerived_")
+    mousenormalscrollbarwindow:setScrollPosition((math.log(14*mousenormalsensitivity-6))/(6*math.log(2)))
+    mousederivescrollbarwindow:setScrollPosition((math.log(14*mousederivesensitivity-6))/(6*math.log(2)))
+    if derive_active == "true" then
+        normal_active = false
+        derive_active = true
+        derivewindow:setSelected(derive_active)
+    else
+        normal_active = true
+        derive_active = false
+        normalwindow:setSelected(normal_active)
+    end
+    if invert_active == "true" then
+        invert_active = true
+    else
+        invert_active = false
+    end
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/MouseControlsBackButton"),
+            ["callback"]  = P.MouseControlsBackButton_clicked
+    })
+end
+
+function P.MouseControlsMouseNormalScrollbar_changed(e)
+    if mousenormalscrollbar_active == false then
+        scrollposition = mousenormalscrollbarwindow:getScrollPosition()
+        mousenormalsensitivity = (math.pow(64,scrollposition)+6)/14
+        orxonox.config("KeyBinder", "mouseSensitivity_", mousenormalsensitivity)
+    end
+end
+
+function P.MouseControlsMouseNormalScrollbar_started(e)
+    mousenormalscrollbar_active = true
+end
+
+function P.MouseControlsMouseNormalScrollbar_ended(e)
+    scrollposition = mousenormalscrollbarwindow:getScrollPosition()
+    mousenormalsensitivity = (math.pow(64,scrollposition)+6)/14
+    orxonox.config("KeyBinder", "mouseSensitivity_", mousenormalsensitivity)
+    mousenormalscrollbar_active = false
+end
+
+function P.MouseControlsMouseDeriveScrollbar_changed(e)
+    if mousederivescrollbar_active == false then
+        scrollposition = mousederivescrollbarwindow:getScrollPosition()
+        mousederivesensitivity = (math.pow(64,scrollposition)+6)/14
+        orxonox.config("KeyBinder", "mouseSensitivityDerived_", mousederivesensitivity)
+    end
+end
+
+function P.MouseControlsMouseDeriveScrollbar_started(e)
+    mousederivescrollbar_active = true
+end
+
+function P.MouseControlsMouseDeriveScrollbar_ended(e)
+    scrollposition = mousederivescrollbarwindow:getScrollPosition()
+    mousederivesensitivity = (math.pow(64,scrollposition)+6)/14
+    orxonox.config("KeyBinder", "mouseSensitivityDerived_", mousederivesensitivity)
+    mousederivescrollbar_active = false
+end
+
+function P.MouseNormalButton_clicked(e)
+    if block == false then
+        block = true
+        derivewindow:setSelected(false)
+        block = false
+        orxonox.config("KeyBinder", "bDeriveMouseInput_", 0)
+    end
+end
+
+function P.MouseDeriveButton_clicked(e)
+    if block == false then
+        block = true
+        normalwindow:setSelected(false)
+        block = false
+        orxonox.config("KeyBinder", "bDeriveMouseInput_", 1)
+    end
+end
+
+function P.MouseInvertCheckbox_clicked(e)
+    -- invert mouse
+end
+
+function P.MouseControlsBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/MultiplayerMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/MultiplayerMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/MultiplayerMenu.lua	(revision 11817)
@@ -0,0 +1,161 @@
+-- MultiplayerMenu.lua
+
+local P = createMenuSheet("MultiplayerMenu")
+
+--joinMode is 1 for choice "LAN" and 2 for "Internet"
+--initial status 1
+P.joinMode = 1
+
+function P.onLoad()
+    P.multiplayerMode = "startClient"
+
+    --button are arranged in a 3x2 matrix, Join and Host buttons are in the upper left and middle, the back button in the lower right of the table
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/MultiplayerJoinButton"),
+            ["callback"]  = P.MultiplayerJoinButton_clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/MultiplayerHostButton"),
+            ["callback"]  = P.MultiplayerHostButton_clicked
+    })
+
+    P:setButton(2, 3, {
+            ["button"] = winMgr:getWindow("orxonox/MultiplayerBackButton"),
+            ["callback"]  = P.MultiplayerBackButton_clicked
+    })
+end
+
+function P.onShow()
+    --P.showServerList()
+
+    if P.joinMode == 1 then
+        local window = winMgr:getWindow("orxonox/MultiplayerLanButton")
+        local button = tolua.cast(window,"CEGUI::RadioButton")
+        button:setSelected(true)
+    end
+    if P.joinMode == 2 then
+        local window = winMgr:getWindow("orxonox/MultiplayerInternetButton")
+        local button = tolua.cast(window,"CEGUI::RadioButton")
+        button:setSelected(true)
+    end
+end
+
+function P.LanButton_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local button = tolua.cast(we.window,"CEGUI::RadioButton")
+    P.joinMode = 1
+    if button:isSelected() == true then
+        P.showServerList()
+    end
+end
+
+function P.InternetButton_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local button = tolua.cast(we.window,"CEGUI::RadioButton")
+    P.joinMode = 2
+    if button:isSelected() == true then
+        P.showServerList()
+    end
+end
+
+function P.MultiplayerHostButton_clicked(e)
+    showMenuSheet("HostMenu", true)
+end
+
+
+function P.MultiplayerJoinButton_clicked(e)
+    local choice = winMgr:getWindow("orxonox/MultiplayerListbox"):getFirstSelectedItem()
+    local destination = nil
+    if choice then
+        local index = tolua.cast(choice, "CEGUI::ListboxItem"):getID()
+        destination = P.serverList[index][1]
+    else
+        return
+    end
+    orxonox.execute("startClient " .. destination)
+    hideAllMenuSheets()
+end
+
+function P.MultiplayerBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+function P.showServerList()
+    -- LAN Discovery
+    if P.joinMode == 1 then
+        local listbox = winMgr:getWindow("orxonox/MultiplayerListbox")
+        CEGUI.toListbox(listbox):resetList()
+        local discovery = orxonox.LANDiscovery:getInstance()
+        discovery:discover()
+        P.serverList = {}
+        local index = 0
+        local servername = ""
+        local serverip = ""
+        local serverrtt = ""
+        local playernumber = ""
+        while true do
+            servername = discovery:getServerListItemName(index)
+            if servername == "" then
+                break
+            end
+            serverip = discovery:getServerListItemIP(index)
+            if serverip == "" then
+                break
+            end
+            --serverrtt = discovery:getServerListItemRTT(index)
+            playernumber = discovery:getServerListItemPlayerNumber(index)
+
+            table.insert(P.serverList, {serverip, servername, playernumber})
+            index = index + 1
+        end
+        index = 1
+        for k,v in pairs(P.serverList) do
+            local item = CEGUI.createListboxTextItem("IP: " .. v[1] .. " Name: " .. v[2] .. " Players: " .. v[3])
+            item:setID(index)
+            index = index + 1
+            item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+            CEGUI.toListbox(listbox):addItem(item)
+        end
+    -- WAN Discovery
+    elseif P.joinMode == 2 then
+        local listbox = winMgr:getWindow("orxonox/MultiplayerListbox")
+        CEGUI.toListbox(listbox):resetList()
+        local discovery = orxonox.WANDiscovery()
+        orxout("discovering." )
+        discovery:discover()
+        orxout("discovered." )
+        P.serverList = {}
+        local index = 0
+        local servername = ""
+        local serverip = ""
+        local serverrtt = ""
+        local playernumber = ""
+        while true do
+            servername = discovery:getServerListItemName(index)
+            if servername == "" then
+                break
+            end
+            serverip = discovery:getServerListItemIP(index)
+            if serverip == "" then
+                break
+            end
+            --serverrtt = discovery:getServerListItemRTT(index)
+            playernumber = discovery:getServerListItemPlayerNumber(index)
+
+            table.insert(P.serverList, {serverip, servername, playernumber})
+            index = index + 1
+        end
+        index = 1
+        for k,v in pairs(P.serverList) do
+            local item = CEGUI.createListboxTextItem("IP: " .. v[1] .. " Name: " .. v[2] .. " Players: " .. v[3])
+            item:setID(index)
+            index = index + 1
+            item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+            CEGUI.toListbox(listbox):addItem(item)
+        end
+    end
+
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/MultiplayerOptionsMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/MultiplayerOptionsMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/MultiplayerOptionsMenu.lua	(revision 11817)
@@ -0,0 +1,9 @@
+-- MultiplayerOptionsMenu.lua
+
+local P = createMenuSheet("MultiplayerOptionsMenu")
+
+function P.MultiplayerOptionsBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/NotificationLayer.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/NotificationLayer.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/NotificationLayer.lua	(revision 11817)
@@ -0,0 +1,297 @@
+-- NotificationLayer.lua
+
+local P = createMenuSheet("NotificationLayer", true, tribool(true), tribool(true))
+
+P.queueList = {}
+
+P.sampleWindow = nil
+
+-- Loads the queues from the NotificationManager and creates the sample window, that is used to measure the width various strings need.
+function P.onLoad()
+    orxonox.NotificationManager:getInstance():loadQueues()
+    P.sampleWindow = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/SampleWindow")
+end
+
+-- Creates a queue in the GUI.
+function P.createQueue(name, size)
+    local root = winMgr:getWindow("orxonox/NotificationLayer/Root")
+    --local queue = winMgr:createWindow("MenuWidgets/Listbox", "orxonox/NotificationLayer/Root/Queue/" .. name)
+    --queue:setProperty("BackgroundColor", "00FFFFFF") -- Set background to be fully transparent.
+    local queue = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/NotificationLayer/Root/Queue/" .. name)
+    queue:setProperty("Alpha", 0.0)
+    --queue:setProperty("FrameEnabled", "false")
+    root:addChildWindow(queue)
+
+    local queueTuple =
+    {
+        ["window"]    = queue,
+        ["name"]      = name,
+        ["maxSize"]   = size,
+        ["visible"]   = false,
+        ["fontSize"]  = 12,
+        ["fontColor"] = "FFFFFFFF",
+        ["alignment"] = "LeftAligned",
+        ["items"]     = {},
+        ["first"]     = 1,
+        ["last"]      = 1
+    }
+    
+    queue:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
+    queue:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, 0), CEGUI.UDim(0, P.queueHeightHelper(queueTuple, size))))
+
+    P.queueList[name] = queueTuple -- name access
+    P.setVisible(queueTuple, false) -- Set the queue to invisible as long as there are no notifications in it.
+end
+
+-- Removes a queue from the GUI.
+function P.removeQueue(queueName)
+    local queue = P.queueList[queueName]
+
+    if queue ~= nil then
+        queue.window:getParent():removeChildWindow(queue.window)
+        winMgr:destroyWindow(queue.window)
+    end
+    P.queueList[queueName] = nil
+end
+
+-- Pushes an input notification to the input queue.
+function P.pushNotification(queueName, notification)
+    local queue = P.queueList[queueName]
+    if queue == nil then
+        return
+    end
+
+    if not guiMgr:usingOldCEGUI() then
+        notification = string.gsub(notification, "%[", "\\%[") -- escape '[' which is used to format text since cegui 0.7
+    end
+
+    local item = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/Queue/" .. queueName .. "/" .. queue.last)
+    item:setText(notification)
+    P.setItemFontHelper(item, queue, true)
+    -- Add the item to the top of the queue.
+    local itemHeight = P.itemHeightHelper(queue)
+    if queue.last-queue.first > 0 then -- If the queue is not empty move all items down
+        for i=queue.first,queue.last-1 do
+            local item = queue.items[i]
+            item:setYPosition(CEGUI.UDim(0, itemHeight*(queue.last-i)))
+        end
+    end
+    queue.window:addChildWindow(item)
+    item:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0), CEGUI.UDim(0, itemHeight)))
+    item:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
+    item:setProperty("Alpha", 1.0)
+    item:setProperty("InheritsAlpha", "false")
+    item:setProperty("BackgroundEnabled", "false")
+    item:setProperty("FrameEnabled", "false")
+    item:setProperty("HorzFormatting", queue.alignment)
+    queue.items[queue.last] = item
+    queue.last = queue.last+1
+
+    -- If the queue has been invisible, set it to visible.
+    if queue.visible == false then
+        P.setVisible(queue, true)
+    end
+end
+
+-- Pops the least recently added notification from the queue.
+function P.popNotification(queueName)
+    local queue = P.queueList[queueName]
+    if queue == nil then
+        return
+    end
+    local item = queue.items[queue.first]
+    -- Removes the item from the bottom of the queue.
+    queue.window:removeChildWindow(item)
+    winMgr:destroyWindow(item)
+    queue.first = queue.first+1
+
+    -- Sets the queue to invisible if there are no more notifications in it.
+    if queue.last-queue.first == 0 then
+        P.setVisible(queue, false)
+    end
+end
+
+-- Removes a notification at a given index from the queue. Where the 0th item is the newest and the nth the (n+1)th newest.
+function P.removeNotification(queueName, index)
+    local queue = P.queueList[queueName]
+    if queue == nil then
+        return
+    end
+
+    index = queue.last-tonumber(index)-1
+    --if index == queue.first then -- If we want to remove the oldest notification, we can just use pop.
+    --    P.popNotification(queueName)
+    --    return
+    --end
+
+    -- Removes the item.
+    local item = queue.items[index]
+    queue.window:removeChildWindow(item)
+    winMgr:destroyWindow(item)
+    queue.items[index] = nil
+
+    -- Move the items below, up.
+    local itemHeight = P.itemHeightHelper(queue)
+    local moved = false
+    if index > queue.first then -- Move all older notifications up in the list.
+        for i=index-1,-1,queue.first do
+            orxout(i)
+            item = queue.items[i]
+            item:setYposition(CEGUI.UDim(0, itemHeight*(queue.last-i-1)))
+            queue.items[i+1] = item
+        end
+    end
+    queue.items[queue.first] = nil
+    queue.first = queue.first+1
+
+    -- Sets the queue to invisible if there are no more notifications in it.
+    if queue.last-queue.first == 0 then
+        P.setVisible(queue, false)
+    end
+end
+
+-- Clears the queue. Removes all notifications from it.
+function P.clearQueue(queueName)
+    local queue = P.queueList[queueName]
+    if queue == nil then
+        return
+    end
+    for i=queue.first,queue.last-1 do
+        local item = queue.items[i]
+        queue.window:removeChildWindow(item)
+        winMgr:destroyWindow(item)
+    end
+    queue.items = {}
+    queue.first = 1
+    queue.last = 1
+
+    -- Sets the queue to invisible.
+    P.setVisible(queue, false)
+end
+
+-- Sets the visibility of the queue.
+function P.setVisible(queue, visible)
+    if queue == nil then
+        return
+    end
+    queue.window:setVisible(visible)
+    queue.visible = visible
+end
+
+-- Change the position of the queue.
+-- The parameters are (in order) 'name of the queue', 'relative x-position', 'absolute x-position in pixel', 'relative y-position', 'absolute y-position in pixel'.
+function P.moveQueue(queueName, relativeXPos, absoluteXPos, relativeYpos, absoluteYPos)
+    local queueWindow = P.queueList[queueName].window
+    queueWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(relativeXPos, absoluteXPos), CEGUI.UDim(relativeYpos, absoluteYPos)))
+end
+
+-- Change the size of the queue.
+-- The parameters are (in order) 'name of the queue', 'relative width', 'absolute width in pixel', 'relative height', 'absolute heigth in pixel'.
+-- Additionally the last two parameters can be ommitted, which leads to the height being set such that all notifications can be displayed. using the size of the queue.
+function P.resizeQueue(queueName, relativeWidth, absoluteWidth, relativeHeight, absoluteHeigth)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
+        return
+    end
+    if absoluteHeigth == nil then
+        absoluteHeigth = P.queueHeightHelper(queue, queue.maxSize)
+        relativeHeight = 0
+    end
+    queueWindow:setSize(CEGUI.UVector2(CEGUI.UDim(relativeWidth, absoluteWidth), CEGUI.UDim(relativeHeight, absoluteHeigth)))
+end
+
+-- Change the horizontal alignment of the displayed notifications.
+-- The parameters are the name of the queue and the alignment parameter,
+function P.changeQueueAlignment(queueName, alignment)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
+        return
+    end
+
+    queue.alignment = alignment
+    local item = nil
+    for i=queue.first,queue.last-1 do
+        item = queue.items[i]
+        item:setProperty("HorzFormatting", queue.alignment)
+    end
+end
+
+-- Change the font size  of all notifications in a queue.
+-- The parameters are (in order) 'name of the queue', 'font size'.
+function P.changeQueueFontSize(queueName, size)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
+        return
+    end
+
+    queue.fontSize = size
+    for i=queue.first,queue.last-1 do
+        P.setItemFontHelper(queue.items[i], queue, false)
+    end
+end
+
+-- Change the font color of all notifications in a queue.
+-- The parameters are (in order) 'name of the queue', 'ARGB of the font color in hex notation'.
+function P.changeQueueFontColor(queueName, color)
+    local queue = P.queueList[queueName]
+    local queueWindow = queue.window
+    if queueWindow == nil then
+        return
+    end
+
+    queue.fontColor = color
+    for i=queue.first,queue.last-1 do
+        P.setItemFontHelper(queue.items[i], queue, true)
+    end
+end
+
+-- Helper function to set the font size and color of a item of a queue.
+-- The parameters are (in order) 'the ListboxItem', 'the queue table', 'whether color should be changed as well'
+function P.setItemFontHelper(item, queue, changeColor)
+    --local item = tolua.cast(item, "CEGUI::ListboxTextItem")
+    local fontMgr = CEGUI.FontManager:getSingleton()
+    if (fontMgr["isFontPresent"] and fontMgr:isFontPresent("BlueHighway-" .. queue.fontSize)) or -- cegui 0.6
+        (fontMgr["isDefined"] and fontMgr:isDefined("BlueHighway-" .. queue.fontSize)) then -- cegui 0.7
+        item:setFont("BlueHighway-" .. queue.fontSize)
+    else
+        orxonox.GUIManager:addFontHelper("BlueHighway-" .. queue.fontSize, queue.fontSize, "bluehigh.ttf")
+        item:setFont("BlueHighway-" .. queue.fontSize)
+    end
+    if changeColor then
+        item:setProperty("TextColours", "tl:" .. queue.fontColor .. " tr:" .. queue.fontColor .. " bl:" .. queue.fontColor .. " br:" .. queue.fontColor .. "")
+    end
+end
+
+-- Helper function. Returns height a queue needs to have to display 'size' items.
+function P.queueHeightHelper(queue, size)
+    --local listbox = CEGUI.toListbox(queue.window)
+    --local item = CEGUI.createListboxTextItem("Text")
+    --P.setItemFontHelper(item, queue, false)
+    --listbox:addItem(item)
+    --local singleItemHeight = listbox:getTotalItemsHeight()
+    local singleItemHeight = P.itemHeightHelper(queue)
+    --local lookAndFeel = CEGUI.WidgetLookManager:getSingleton():getWidgetLook(queue.window:getLookNFeel())
+    --local formattedArea = lookAndFeel:getNamedArea("ItemRenderingArea"):getArea():getPixelRect(queue.window)
+    --local frameHeight = queue.window:getUnclippedOuterRect():getHeight() - formattedArea:getHeight()
+    --listbox:removeItem(item)
+    --return frameHeight + singleItemHeight*size
+    return singleItemHeight*size + 1
+end
+
+function P.itemHeightHelper(queue)
+    local item = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/NotificationLayer/Root/Test/")
+    item:setText("text")
+    P.setItemFontHelper(item, queue, true)
+    queue.window:addChildWindow(item)
+    item:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0), CEGUI.UDim(1, 0)))
+    item:setProperty("FrameEnabled", "false")
+    local height = getStaticTextWindowHeight(item)
+    queue.window:removeChildWindow(item)
+    winMgr:destroyWindow(item)
+    return height
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/PickupInventory.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/PickupInventory.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/PickupInventory.lua	(revision 11817)
@@ -0,0 +1,331 @@
+-- PickupInventory.lua
+
+local P = createMenuSheet("PickupInventory")
+
+P.wrapper = nil
+P.detailsWindows = {}
+P.detailPickups = {}
+P.pickupsList = {}
+
+P.showing = false
+
+-- Design parameters
+P.imageHeight = 50
+P.detailImageSize = 100
+P.textHeight = 30
+P.buttonWidth = 85
+
+function P.onLoad()
+    P.wrapper = nil
+    P.detailsWindows = {}
+    P.detailPickups = {}
+    P.pickupsList = {}
+end
+
+function P.onShow()
+    P.createInventory()
+    P.showing = true
+end
+
+function P.onHide()
+    P.showing = false
+    P.cleanup(true)
+end
+
+function P.update()
+    if P.showing == false then
+        return
+    end
+
+    -- Update opened detail windows.
+    for k,v in pairs(P.detailsWindows) do
+        if v ~= nil then
+            local pickup = P.detailPickups[k]
+            if pickup ~= nil and pickup ~= 0 then
+                local useButton = winMgr:getWindow("orxonox/PickupInventory/Details" .. k .. "/UseButton")
+                local dropButton = winMgr:getWindow("orxonox/PickupInventory/Details" .. k .. "/DropButton")
+                if orxonox.PickupManager:getInstance():isValidPickup(pickup.pickup) == false then
+                    useButton:setEnabled(false)
+                    dropButton:setEnabled(false)
+                    P.detailPickups[k] = nil
+                else
+                    useButton:setEnabled(true)
+                    if pickup.inUse == false then
+                        useButton:setText("use")
+                        if pickup.usable == false then
+                            useButton:setEnabled(false)
+                        end
+                    else
+                        useButton:setText("unuse")
+                        if pickup.unusable == false then
+                            useButton:setEnabled(false)
+                        end
+                    end
+
+                    if pickup.pickedUp == false then
+                        useButton:setEnabled(false)
+                        dropButton:setEnabled(false)
+                        P.detailPickups[k] = nil
+                    end
+                end
+            end
+        end
+    end
+
+    -- Update main inventory.
+    P.cleanup(false)
+    P.createInventory()
+    -- TODO: Recover scrolling position
+    
+end
+
+function P.createInventory()
+    local pickupManager = orxonox.PickupManager:getInstance()
+    
+    local root = winMgr:getWindow("orxonox/PickupInventory/Inventory")
+    P.wrapper = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/PickupInventory/Inventory/Wrapper")
+    P.wrapper:setSize(CEGUI.UVector2(CEGUI.UDim(1,0),CEGUI.UDim(1,0)))
+    root:addChildWindow(P.wrapper)
+    
+    P.pickupsList = {}
+
+    local numPickups = pickupManager:getNumPickups()
+    local counter = 1
+    local offset = 0
+    while counter <= numPickups do
+        local pickup = pickupManager:popPickup()
+        table.insert(P.pickupsList, pickup)
+        local window = P.createPickupEntry(counter, pickup)
+        window:setYPosition(CEGUI.UDim(0,offset))
+        offset = offset + window:getHeight():asAbsolute(1)
+        P.wrapper:addChildWindow(window)
+        counter = counter + 1
+    end
+
+end
+
+function P.createPickupEntry(index, pickup)
+    local representation = orxonox.PickupManager:getInstance():getRepresentation(pickup.representationName)
+
+    local name = "orxonox/PickupInventory/Box/Pickup" .. index
+
+    local item = winMgr:createWindow("MenuWidgets/StaticText", name)
+    item:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0), CEGUI.UDim(0, P.imageHeight)))
+    item:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, 0)))
+
+    local image = winMgr:createWindow("MenuWidgets/StaticImage", name .. "/Image")
+    image:setProperty("Image", "set:PickupInventory image:" .. representation:getInventoryRepresentation())
+    image:setProperty("BackgroundEnabled", "set:False")
+    image:setProperty("FrameEnabled", "set:True")
+    image:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.imageHeight), CEGUI.UDim(0, P.imageHeight)))
+    item:addChildWindow(image)
+
+    local title = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Title")
+    title:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.imageHeight+5), CEGUI.UDim(0, (P.imageHeight-P.textHeight)/2)))
+    title:setSize(CEGUI.UVector2(CEGUI.UDim(0.3, 0), CEGUI.UDim(0, P.textHeight)))
+    title:setText(representation:getPickupName())
+    title:setProperty("FrameEnabled", "set:False")
+    item:addChildWindow(title)
+
+    local useButton = winMgr:createWindow("MenuWidgets/Button", name .. "/UseButton")
+    useButton:setPosition(CEGUI.UVector2(CEGUI.UDim(0.3, P.imageHeight+10),CEGUI.UDim(0, (P.imageHeight-P.textHeight)/2)))
+    useButton:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.buttonWidth), CEGUI.UDim(0, P.textHeight)))
+    if pickup.inUse == false then
+        useButton:setText("use")
+        if pickup.usable == false then
+            useButton:setEnabled(false)
+        end
+    else
+        useButton:setText("unuse")
+        if pickup.unusable == false then
+            useButton:setEnabled(false)
+        end
+    end
+    orxonox.GUIManager:subscribeEventHelper(useButton, "Clicked", P.name .. ".InventoryUseUnuseButton_clicked")
+    item:addChildWindow(useButton)
+
+    local dropButton = winMgr:createWindow("MenuWidgets/Button", name .. "/DropButton")
+    dropButton:setPosition(CEGUI.UVector2(CEGUI.UDim(0.3, P.imageHeight+15+P.buttonWidth),CEGUI.UDim(0, (P.imageHeight-P.textHeight)/2)))
+    dropButton:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.buttonWidth), CEGUI.UDim(0, P.textHeight)))
+    dropButton:setText("drop")
+    orxonox.GUIManager:subscribeEventHelper(dropButton, "Clicked", P.name .. ".InventoryDropButton_clicked")
+    item:addChildWindow(dropButton)
+
+    local detailsButton = winMgr:createWindow("MenuWidgets/Button", name .. "/DetailsButton")
+    detailsButton:setPosition(CEGUI.UVector2(CEGUI.UDim(0.3, P.imageHeight+20+2*P.buttonWidth),CEGUI.UDim(0, (P.imageHeight-P.textHeight)/2)))
+    detailsButton:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.buttonWidth), CEGUI.UDim(0, P.textHeight)))
+    detailsButton:setText("details")
+    orxonox.GUIManager:subscribeEventHelper(detailsButton, "Clicked", P.name .. ".InventoryDetailsButton_clicked")
+    item:addChildWindow(detailsButton)
+
+    return item
+end
+
+function P.cleanup(destroyDetails)
+    if P.wrapper ~= nil then
+        winMgr:destroyWindow(P.wrapper)
+    end
+    
+    --Destroy details windows.
+    if destroyDetails == false then
+        return
+    end
+    for k,v in pairs(P.detailsWindows) do
+        if v ~= nil then
+            P.destroyDetailWindow(k)
+        end
+    end
+end
+
+function P.windowToPickupHelper(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local pickupIndex = tonumber(match())
+
+    return pickupIndex
+end
+
+function P.createDetailsWindow(pickupIndex)
+    local pickup = P.pickupsList[pickupIndex]
+    local representation = orxonox.PickupManager:getInstance():getRepresentation(pickup.representationName)
+
+    local index = P.getNewDetailNumber()
+    local name = "orxonox/PickupInventory/Details" .. index
+    
+    local window = winMgr:createWindow("MenuWidgets/FrameWindow", name)
+    window:setSize(CEGUI.UVector2(CEGUI.UDim(0.5,0),CEGUI.UDim(0.4,0)))
+    orxonox.GUIManager:subscribeEventHelper(window, "CloseClicked", P.name .. ".closeDetailWindow")
+    
+    local root = winMgr:getWindow("orxonox/PickupInventory/Background")
+    root:addChildWindow(window)
+    
+    local wrapper = winMgr:createWindow("DefaultWindow", name .. "/Wrapper")
+    wrapper:setSize(CEGUI.UVector2(CEGUI.UDim(1, -20),CEGUI.UDim(1, -50)))
+    wrapper:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 10),CEGUI.UDim(0, 40)))
+    window:addChildWindow(wrapper)
+    
+    local title = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Title")
+    title:setText(representation:getPickupName())
+    title:setHeight(CEGUI.UDim(0, P.textHeight))
+    title:setProperty("FrameEnabled", "set:False")
+    title:setProperty("BackgroundEnabled", "set:False")
+    wrapper:addChildWindow(title)
+    
+    local image = winMgr:createWindow("MenuWidgets/StaticImage", name .. "/Image")
+    image:setProperty("Image", "set:PickupInventory image:" .. representation:getInventoryRepresentation())
+    image:setProperty("BackgroundEnabled", "set:False")
+    image:setProperty("FrameEnabled", "set:True")
+    image:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.detailImageSize), CEGUI.UDim(0, P.detailImageSize)))
+    image:setYPosition(CEGUI.UDim(0, P.textHeight + 5))
+    wrapper:addChildWindow(image)
+    
+    local box = winMgr:createWindow("MenuWidgets/ScrollablePane", name .. "/Description")
+    box:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -1*(P.detailImageSize + 10)),CEGUI.UDim(1, -(P.textHeight + 5 + P.textHeight + 20))))
+    box:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.detailImageSize + 10),CEGUI.UDim(0, P.textHeight + 5)))
+    local description = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Description/Text")
+    description:setText(representation:getPickupDescription())
+    description:setProperty("HorzFormatting", "WordWrapLeftAligned")
+    description:setProperty("VertFormatting", "TopAligned")
+    box:addChildWindow(description)
+    wrapper:addChildWindow(box)
+
+    local useButton = winMgr:createWindow("MenuWidgets/Button", name .. "/UseButton")
+    useButton:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.detailImageSize+10),CEGUI.UDim(1, -40)))
+    useButton:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.buttonWidth), CEGUI.UDim(0, P.textHeight)))
+    if pickup.inUse == false then
+        useButton:setText("use")
+        if pickup.usable == false then
+            useButton:setEnabled(false)
+        end
+    else
+        useButton:setText("unuse")
+        if pickup.unusable == false then
+            useButton:setEnabled(false)
+        end
+    end
+    orxonox.GUIManager:subscribeEventHelper(useButton, "Clicked", P.name .. ".InventoryUseUnuseDetailButton_clicked")
+    wrapper:addChildWindow(useButton)
+    
+    local dropButton = winMgr:createWindow("MenuWidgets/Button", name .. "/DropButton")
+    dropButton:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.detailImageSize+10+P.buttonWidth+10),CEGUI.UDim(1, -40)))
+    dropButton:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.buttonWidth), CEGUI.UDim(0, P.textHeight)))
+    dropButton:setText("drop")
+    orxonox.GUIManager:subscribeEventHelper(dropButton, "Clicked", P.name .. ".InventoryDropDetailButton_clicked")
+    wrapper:addChildWindow(dropButton)
+
+    P.detailsWindows[index] = window
+    P.detailPickups[index] = pickup
+    
+end
+
+function P.getNewDetailNumber()
+    local number = table.getn(P.detailsWindows)
+    for k,v in pairs(P.detailsWindows) do
+        if v == nil then
+            number = k-1
+        end
+    end
+    return number+1
+end
+
+function P.InventoryUseUnuseButton_clicked(e)
+    local pickupIndex = P.windowToPickupHelper(e)
+    local pickup = P.pickupsList[pickupIndex]
+    if pickup.inUse == false then
+        orxonox.PickupManager:getInstance():usePickup(pickup.pickup, true)
+    else
+        orxonox.PickupManager:getInstance():usePickup(pickup.pickup, false)
+    end
+end
+
+function P.InventoryDropButton_clicked(e)
+    local pickupIndex = P.windowToPickupHelper(e)
+    local pickup = P.pickupsList[pickupIndex]
+    orxonox.PickupManager:getInstance():dropPickup(pickup.pickup)
+end
+
+function P.InventoryDetailsButton_clicked(e)
+    local pickupIndex = P.windowToPickupHelper(e)
+    P.createDetailsWindow(pickupIndex)
+end
+
+function P.InventoryUseUnuseDetailButton_clicked(e)
+    local pickupIndex = P.windowToPickupHelper(e)
+    local pickup = P.detailPickups[pickupIndex]
+    if pickup.inUse == false then
+        orxonox.PickupManager:getInstance():usePickup(pickup.pickup, true)
+    else
+        orxonox.PickupManager:getInstance():usePickup(pickup.pickup, false)
+    end
+end
+
+function P.InventoryDropDetailButton_clicked(e)
+    local pickupIndex = P.windowToPickupHelper(e)
+    local pickup = P.detailPickups[pickupIndex]
+    orxonox.PickupManager:getInstance():dropPickup(pickup.pickup)
+end
+
+function P.closeDetailWindow(e)
+    --Get some numbers from the window
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+    local match = string.gmatch(name, "%d+")
+    local detailNr = tonumber(match())
+    
+    P.destroyDetailWindow(detailNr)
+end
+
+function P.destroyDetailWindow(detailNr)
+    local window = P.detailsWindows[detailNr]
+    winMgr:destroyWindow(window)
+    P.detailsWindows[detailNr] = nil
+    P.detailPickups[detailNr] = nil
+end
+
+function P.InventoryBackButton_clicked(e)
+    orxonox.CommandExecutor:execute("OrxonoxOverlay toggleVisibility PickupInventory")
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/QuestGUI.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/QuestGUI.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/QuestGUI.lua	(revision 11817)
@@ -0,0 +1,579 @@
+-- QuestGUI.lua
+
+local P = createMenuSheet("QuestGUI")
+
+P.questManager = nil -- The QuestManager.
+P.showActive = true -- Whether the active or finished quest list is displayed.
+P.player = nil -- The player the quests are displayed for.
+P.quests = {}
+P.subquests = {}
+
+-- design parameters
+P.scrollbarWidth = 13
+P.frameHeigth = 18
+P.borderSize = 5
+P.titleHeight = 26
+
+--TODO:
+-- Highlight whether we are currently looking at active or finished quests
+-- Distinguish completed from failed quests
+
+function P.onLoad()
+    P.questManager = orxonox.QuestManager:getInstance() -- Store the pointer to the QuestManager as an internal variable to allow for faster access,
+end
+
+function P.onShow()
+    -- Get the player.
+    P.player = orxonox.GUIManager:getInstance():getPlayer(P.name)
+
+    -- Load the list of quests to be displayed.
+    P.loadQuestsList()
+    -- Pause the game - possible conflict for multiplayer quests
+    orxonox.execute("setPause 1")
+end
+
+function P.onQuit()
+    orxonox.execute("setPause 0")
+end
+
+-- Loads the list of quests, depending on P.showActive, either the active (P.showActive == true) or the finished, i.e. inactive quests are loaded.
+-- selectQuest is a pointer to a quest that should be selected, if it is nil the first quest is selected.
+function P.loadQuestsList(selectQuest)
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    P.clearQuestList()
+
+    local selectQuestId = nil
+    if selectQuest ~= nil then
+        selectQuestId = P.questManager:getId(selectQuest)
+    end
+
+    -- Iterate through all root-quests.
+    local numRootQuests = P.questManager:getNumRootQuests(P.player)
+    if numRootQuests > 0 then
+        local i = 0
+        while i <= numRootQuests-1 do
+            local quest = P.questManager:getRootQuest(P.player, i)
+            -- Insert the current quest into the list.
+            local item = P.insertQuest(list, quest)
+            -- If the quest was inserted in the list and is has the same id as the selectQuest (thus it is the same quest) it is selected.
+            if selectQuestId ~= nil and item ~= nil and selectQuestId == P.questManager:getId(quest) then
+                list:setItemSelectState(item, true)
+            end
+            -- Insert all subquests of this rootquest.
+            P.insertSubQuests(list, quest, selectQuestId)
+            i = i+1
+        end
+        -- If there were quests added to the list but there was no selectQuest specified (i.e. selectQuest was nil), the first item is selected.
+        if list:getItemCount() > 0 then
+            if selectQuestId == nil then
+                list:setItemSelectState(list:getListboxItemFromIndex(0), true)  -- Select first quest.
+            end
+        -- If there werent any quests added the standard "no quests" message is loaded.
+        else
+            P.loadQuest()
+        end
+    end
+end
+
+-- Helper function, recursively inserts all the (active or inactive, depending on P.showActive) subquests of the input quest.
+-- list is the list into which the subquests should be insterted.
+-- quest is the quest, whose subquests should be inserted.
+-- selectQuestId is the id of the quest that should be selected.
+function P.insertSubQuests(list, quest, selectQuestId)
+    -- Iterate through all sub-quests.
+    local numQuests = P.questManager:getNumSubQuests(quest, P.player)
+    if numQuests > 0 then
+        local i = 0
+        while i <= numQuests-1 do
+            local subquest = P.questManager:getSubQuest(quest, P.player, i)
+            -- Insert the current quest into the list.
+            local item = P.insertQuest(list, subquest)
+            -- If the quest was inserted in the list and is has the same id as the selectQuest (thus it is the same quest) it is selected.
+            if selectQuestId ~= nil and item ~= nil and selectQuestId == P.questManager:getId(subquest) then
+                list:setItemSelectState(item, true)
+            end
+            i = i+1
+        end
+    end
+end
+
+-- Helper function, inserts a quest into the list (depending whether active or inactive quests are being shown). Returns nil if the quest was not inserted.
+-- list is the list into which the quets should be inserted.
+-- quest is the quest to be inserted.
+function P.insertQuest(list, quest)
+    if P.showActive == quest:isActive(P.player) then
+        local item = CEGUI.createListboxTextItem(P.questManager:getDescription(quest):getTitle())
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        list:addItem(item)
+        table.insert(P.quests, quest)
+        return item
+    end
+    return nil
+end
+
+-- Loads the input quest.
+-- quest the quest to be loaded.
+function P.loadQuest(quest)
+
+    P.clearQuest() -- Clear the old quest.
+    if quest == nil then -- If quets is nil there is nothing to display.
+        return
+    else
+        local offset = 0
+
+        -- Load title and description
+        local description = P.questManager:getDescription(quest)
+        local titleWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Title")
+        titleWindow:setText(description:getTitle())
+        local descriptionWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Description")
+        descriptionWindow:setText(description:getDescription())
+        descriptionWindow:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(1, 0)))
+        descriptionWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, P.borderSize)))
+        local height = getStaticTextWindowHeight(descriptionWindow)
+        descriptionWindow:setHeight(CEGUI.UDim(0, height))
+        offset = offset + height
+
+        -- Load subquests
+        local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/Quest/SubquestsList"))
+        local numQuests = P.questManager:getNumSubQuests(quest, P.player)
+        local i = 0
+        while i <= numQuests-1 do
+            local quest = P.questManager:getSubQuest(quest, P.player, i)
+            local item = CEGUI.createListboxTextItem(P.questManager:getDescription(quest):getTitle())
+            item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+            list:addItem(item)
+            table.insert(P.subquests, quest)
+            i = i+1
+        end
+        height = list:getTotalItemsHeight()
+        if height > 0 then
+            height = height+P.frameHeigth
+        end
+        list:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(0, height)))
+        list:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, offset)))
+        offset = offset + height + P.borderSize
+
+        -- Load hints
+        local hintsWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Hints")
+        hintsWindow:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, offset)))
+        hintsWindow:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(0, 0)))
+        height = P.titleHeight
+        local numHints = P.questManager:getNumHints(quest, P.player)
+        local i = 0
+        while i <= numHints-1 do
+            local hint = P.questManager:getHints(quest, P.player, i)
+            height = height + P.insertHint(hintsWindow, hint, i, height)
+            i = i+1
+        end
+        if numHints == 0 then
+            height = 0
+        end
+        hintsWindow:setHeight(CEGUI.UDim(0, height))
+        offset = offset + height
+
+        -- Set the size of the wrapper
+        local window = winMgr:getWindow("orxonox/QuestGUI/Quest/Wrapper")
+        window:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize-P.scrollbarWidth), CEGUI.UDim(0,offset+P.borderSize)))
+    end
+end
+
+-- Clear the currently displayed quest.
+function P.clearQuest()
+    -- clear title
+    local titleWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Title")
+    titleWindow:setText("no Quests")
+
+    -- clear description
+    local descriptionWindow = winMgr:getWindow("orxonox/QuestGUI/Quest/Description")
+    descriptionWindow:setText("There is currently no quest that can be displayed.")
+
+    -- clear list fo subquests
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/Quest/SubquestsList"))
+    list:resetList()
+    list:setHeight(CEGUI.UDim(0, 0))
+    P.subquests = {}
+
+    -- clear hints
+    local hints = winMgr:getWindow("orxonox/QuestGUI/Quest/Hints")
+    local numChildren = hints:getChildCount()-2 -- TODO: HACK
+    local i = 0
+    while i < numChildren do
+        local hint = hints:getChild("orxonox/QuestGUI/Quest/Hints/" .. i)
+        if hint ~= nil then
+            hints:removeChildWindow(hint)
+            winMgr:destroyWindow(hint)
+        end
+        i = i+1
+    end
+    hints:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.scrollbarWidth-P.borderSize), CEGUI.UDim(0, 0)))
+end
+
+-- Clear the quests list
+function P.clearQuestList()
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    list:resetList()
+    P.quests = {}
+end
+
+-- Select an input quest in the input list.
+-- list is the list in which the input quest is to be selected.
+-- quest is the quest to be selected.
+function P.selectQuest(list, quest)
+    if quest == nil then -- If the input quest is nil, there is nothing to be selected, an error is output and the first quest is selected instead.
+        orxout(orxonox.level.internal_error, "Error in QuestGUI: selectQuest(), input quest is nil. Selecting first.")
+        list:setItemSelectState(list:getListboxItemFromIndex(0), true) -- Select first
+        return
+    end
+
+    local questId = P.questManager:getId(quest)
+    local found = false
+    local index = 0
+    -- Iterate over all quests currently in the list.
+    for k,v in pairs(P.quests) do
+        -- If the id's are the same we have found the quest.
+        if P.questManager:getId(v) == questId then
+            found = true
+            index = k-1
+        end
+    end
+
+    if found then -- If the quest was found it is selected.
+        list:setItemSelectState(list:getListboxItemFromIndex(index), true)
+    else -- If the quest isn't found an error is output and the first quest is selected instead.
+        orxout(orxonox.level.internal_error, "Error in QuestGUI: selectQuest(), input quest is not in list. Selecting first.")
+        list:setItemSelectState(list:getListboxItemFromIndex(0), true) -- Select first
+    end
+end
+
+-- Helper function, insert the input hint into the input hintsWindow. Returns the height of the newly inserted hint.
+-- hintsWindow is the window in which the hint is to be inserted.
+-- hint is the hint to be inserted.
+-- index is the index of the hint.
+-- offset is the current offset in the hintsWindow.
+function P.insertHint(hintsWindow, hint, index, offset)
+    -- Create the window for the hint.
+    local window = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/QuestGUI/Quest/Hints/" .. index)
+    window:setProperty("HorzFormatting", "WordWrapLeftAligned")
+    window:setProperty("VertFormatting", "TopAligned")
+    window:setProperty("FrameEnabled", "false")
+    window:setID(index)
+    hintsWindow:addChildWindow(window)
+    local description = P.questManager:getDescription(hint)
+    window:setText(description:getDescription())
+    window:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.borderSize), CEGUI.UDim(1, 0)))
+    local height = getStaticTextWindowHeight(window)
+    window:setHeight(CEGUI.UDim(0, height))
+    window:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderSize), CEGUI.UDim(0, offset)))
+    return height
+end
+
+-- Show the currently active quests in the quests list.
+function P.showActiveQuestsButton_clicked(e)
+    if P.showActive == false then
+        P.showActive = true
+        P.loadQuestsList()
+    end
+end
+
+-- Show the finished (i.e. inactive) quests in the quests list.
+function P.showFinishedQuestsButton_clicked(e)
+    if P.showActive == true then
+        P.showActive = false
+        P.loadQuestsList()
+    end
+end
+
+-- Change to a new quest.
+function P.changeQuest_clicked(e)
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    local choice = list:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = list:getItemIndex(choice)
+        local quest = P.quests[index+1]
+        if quest ~= nil then
+            P.loadQuest(quest)
+        end
+    end
+end
+
+-- Change to a new subquest.
+function P.changeToSubquest_clicked(e)
+    local list = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/Quest/SubquestsList"))
+    local questsList = CEGUI.toListbox(winMgr:getWindow("orxonox/QuestGUI/QuestsList"))
+    local choice = list:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = list:getItemIndex(choice)
+        local quest = P.subquests[index+1]
+        if quest ~= nil then
+            -- If the P.showActive must be changed to display the quest the quests list also has to be regenerated.
+            if quest:isActive(P.player) == P.showActive then
+                P.selectQuest(questsList, quest)
+            else
+                P.showActive = quest:isActive(P.player)
+                P.loadQuestsList(quest)
+            end
+        else
+            orxout(orxonox.level.internal_error, "Error in QuestGUI: changeToSubquest(), quest was nil. Ignoring...")
+        end
+    end
+end
+
+-- old:
+--[[
+function P.createQuestGUI()
+    local questManager = orxonox.QuestManager:getInstance()
+
+    local depth = 0
+    local index = 0
+
+    local questWindow = winMgr:createWindow("MenuWidgets/ScrollablePane", "orxonox/QuestGUI/Quests")
+    questWindow:setSize(CEGUI.UVector2(CEGUI.UDim(1, 0),CEGUI.UDim(1, 0)))
+
+    -- Iterate through all root-quests.
+    local numRootQuests = orxonox.QuestManager:getInstance():getNumRootQuests(P.player)
+    local i = 0
+    while i <= numRootQuests-1 do
+        local quest = orxonox.QuestManager:getInstance():getRootQuest(P.player, i)
+        index = P.createQuestNodes(questWindow, quest, depth, index)
+        i = i+1
+    end
+
+    return questWindow
+end
+
+function P.createQuestNodes(root, parent, depth, index)
+    local number = table.getn(P.quests)+1
+    local name = "orxonox/QuestGUI/Quests/" .. number
+    local node = winMgr:createWindow("MenuWidgets/TabButton", name)
+    node:setText(orxonox.QuestManager:getInstance():getDescription(parent):getTitle())
+    node:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.indentWidth*depth), CEGUI.UDim(0, P.buttonHeight*index)))
+    node:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.indentWidth*depth-P.scrollbarWidth), CEGUI.UDim(0, P.buttonHeight)))
+    orxonox.GUIManager:subscribeEventHelper(node, "Clicked", P.name .. ".openDetails_clicked")
+    root:addChildWindow(node)
+    
+    table.insert(P.quests, parent)
+
+    index = index+1
+
+    -- Iterate through all sub-quests.
+    local numQuests = orxonox.QuestManager:getInstance():getNumSubQuests(parent, P.player)
+    local i = 0
+    while i <= numQuests-1 do
+        local quest = orxonox.QuestManager:getInstance():getSubQuest(parent, P.player, i)
+        index = P.createQuestNodes(root, quest, depth+1, index)
+        i = i+1
+    end
+
+    return index
+end
+
+function P.cleanup()
+    winMgr:destroyWindow(P.rootWindow)
+    for k,v in pairs(P.detailsWindows) do
+        if v ~= nil then
+            winMgr:destroyWindow(v)
+            P.detailsWindows[k] = nil
+        end
+    end
+    P.detailsWindows = {}
+
+    P.quests = {}
+    P.hints = {}
+    P.player = nil
+
+    winMgr:destroyWindow(P.rootWindow)
+    P.rootWindow = nil
+end
+
+function P.openDetails_clicked(e)
+    --Get some numbers from the window
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+    local match = string.gmatch(name, "%d+")
+    local questNr = tonumber(match())
+
+    name = name .. "/Details" .. P.getNewDetailNumber()
+    quest = P.quests[questNr]
+
+    local details = winMgr:createWindow("MenuWidgets/FrameWindow", name)
+    details:setSize(CEGUI.UVector2(CEGUI.UDim(0.7, 0), CEGUI.UDim(0.7, 0)))
+    details:setPosition(CEGUI.UVector2(CEGUI.UDim(0.1, 0), CEGUI.UDim(0.1, 0)))
+    details:setText(orxonox.QuestManager:getInstance():getDescription(quest):getTitle())
+    details:setProperty("Alpha", 1.0)
+    details:setProperty("InheritsAlpha", "setFalse")
+    orxonox.GUIManager:subscribeEventHelper(details, "CloseClicked", P.name .. ".closeDetails_clicked")
+
+    table.insert(P.detailsWindows, details)
+
+    name = name .. "/Scrollable"
+    local window = winMgr:createWindow("MenuWidgets/ScrollablePane", name)
+    window:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -2*P.borderWidth),CEGUI.UDim(1.0, -P.titleHeight)))
+    window:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderWidth), CEGUI.UDim(0, P.titleHeight)))
+    details:addChildWindow(window)
+
+    local offset = 0
+
+    local status = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Status")
+    window:addChildWindow(status)
+    status:setProperty("HorzFormatting", "WordWrapLeftAligned")
+    status:setProperty("VertFormatting", "TopAligned")
+    if quest:isActive(P.player) then
+        status:setText("This quest is active.")
+    elseif quest:isCompleted(P.player) then
+        status:setText("This quest was completed.")
+    elseif quest:isFailed(P.player) then
+        status:setText("This quest was failed.")
+    end
+    status:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+    status:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(1.0, 0)))
+    local height = getStaticTextWindowHeight(status)
+    status:setHeight(CEGUI.UDim(0, height))
+    offset = offset + height
+
+    local descriptionTitle = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Description/Title")
+    window:addChildWindow(descriptionTitle)
+    descriptionTitle:setProperty("HorzFormatting", "HorzCentred")
+    descriptionTitle:setProperty("VertFormatting", "TopAligned")
+    descriptionTitle:setText("Description:")
+    descriptionTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+    descriptionTitle:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(1.0, 0)))
+    height = getStaticTextWindowHeight(descriptionTitle)
+    descriptionTitle:setHeight(CEGUI.UDim(0, height))
+    offset = offset + height
+
+    local description = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Description")
+    window:addChildWindow(description)
+    description:setProperty("HorzFormatting", "WordWrapLeftAligned")
+    description:setProperty("VertFormatting", "TopAligned")
+    description:setText(orxonox.QuestManager:getInstance():getDescription(quest):getDescription())
+    description:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+    description:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(1.0, 0)))
+    height = getStaticTextWindowHeight(description)
+    description:setHeight(CEGUI.UDim(0, height))
+    offset = offset + height
+
+    -- Display the hints of this quest
+    local numHints = orxonox.QuestManager:getInstance():getNumHints(quest, P.player)
+    if numHints > 0 then
+        local hintsTitle = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Hints/Title")
+        window:addChildWindow(hintsTitle)
+        hintsTitle:setProperty("HorzFormatting", "HorzCentred")
+        hintsTitle:setProperty("VertFormatting", "TopAligned")
+        hintsTitle:setText("Hints:")
+        hintsTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+        hintsTitle:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(1.0, 0)))
+        height = getStaticTextWindowHeight(hintsTitle)
+        hintsTitle:setHeight(CEGUI.UDim(0, height))
+        offset = offset + height
+    end
+    local i = 0
+    while i <= numHints-1 do
+        local hint = orxonox.QuestManager:getInstance():getHints(quest, P.player, i)
+        table.insert(P.hints, hint)
+        local number = table.getn(P.hints)
+        local node = winMgr:createWindow("MenuWidgets/TabButton", name .. "/Hints" .. number)
+        node:setText(orxonox.QuestManager:getInstance():getDescription(hint):getTitle())
+        node:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+        node:setSize(CEGUI.UVector2(CEGUI.UDim(1, -P.scrollbarWidth), CEGUI.UDim(0, P.buttonHeight)))
+        window:addChildWindow(node)
+        offset = offset + P.buttonHeight
+
+        orxonox.GUIManager:subscribeEventHelper(node, "Clicked", P.name .. ".openHintDetails_clicked")
+        i = i+1
+    end
+
+    local window = winMgr:getWindow("orxonox/QuestGUI/Background")
+    window:addChildWindow(details)
+end
+
+function P.getNewDetailNumber()
+    local number = table.getn(P.detailsWindows)
+    for k,v in pairs(P.detailsWindows) do
+        if v == nil then
+            number = k-1
+        end
+    end
+    return number+1
+end
+
+function P.closeDetails_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+    local match = string.gmatch(name, "%d+")
+    match()
+    local detailsNr = tonumber(match())
+
+    winMgr:destroyWindow(P.detailsWindows[detailsNr])
+    P.detailsWindows[detailsNr] = nil
+end
+
+function P.openHintDetails_clicked(e)
+    --Get some numbers from the window
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+    local match = string.gmatch(name, "%d+")
+    match()
+    match()
+    local hintNr = tonumber(match())
+
+    name = name .. "/Details" .. P.getNewDetailNumber()
+    hint = P.hints[hintNr]
+
+    local details = winMgr:createWindow("MenuWidgets/FrameWindow", name)
+    details:setSize(CEGUI.UVector2(CEGUI.UDim(0.7, 0), CEGUI.UDim(0.7, 0)))
+    details:setPosition(CEGUI.UVector2(CEGUI.UDim(0.1, 0), CEGUI.UDim(0.1, 0)))
+    details:setText(orxonox.QuestManager:getInstance():getDescription(hint):getTitle())
+    details:setProperty("Alpha", 1.0)
+    details:setProperty("InheritsAlpha", "setFalse")
+    orxonox.GUIManager:subscribeEventHelper(details, "CloseClicked", P.name .. ".closeHintDetails_clicked")
+
+    table.insert(P.detailsWindows, details)
+
+    name = name .. "/Scrollable"
+    local window = winMgr:createWindow("MenuWidgets/ScrollablePane", name)
+    window:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -2*P.borderWidth),CEGUI.UDim(1.0, -P.titleHeight)))
+    window:setPosition(CEGUI.UVector2(CEGUI.UDim(0, P.borderWidth), CEGUI.UDim(0, P.titleHeight)))
+    details:addChildWindow(window)
+
+    local offset = 0
+    
+    local descriptionTitle = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Description/Title")
+    window:addChildWindow(descriptionTitle)
+    descriptionTitle:setProperty("HorzFormatting", "HorzCentred")
+    descriptionTitle:setProperty("VertFormatting", "TopAligned")
+    descriptionTitle:setText("Description:")
+    descriptionTitle:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+    descriptionTitle:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(1.0, 0)))
+    height = getStaticTextWindowHeight(descriptionTitle)
+    descriptionTitle:setHeight(CEGUI.UDim(0, height))
+    offset = offset + height
+
+    local description = winMgr:createWindow("MenuWidgets/StaticText", name .. "/Description")
+    window:addChildWindow(description)
+    description:setProperty("HorzFormatting", "WordWrapLeftAligned")
+    description:setProperty("VertFormatting", "TopAligned")
+    description:setText(orxonox.QuestManager:getInstance():getDescription(hint):getDescription())
+    description:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, offset)))
+    description:setSize(CEGUI.UVector2(CEGUI.UDim(1.0, -P.scrollbarWidth), CEGUI.UDim(1.0, 0)))
+    height = getStaticTextWindowHeight(description)
+    description:setHeight(CEGUI.UDim(0, height))
+
+    local window = winMgr:getWindow("orxonox/QuestGUI/Background")
+    window:addChildWindow(details)
+end
+
+function P.closeHintDetails_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+    local match = string.gmatch(name, "%d+")
+    match()
+    match()
+    match()
+    local detailsNr = tonumber(match())
+
+    winMgr:destroyWindow(P.detailsWindows[detailsNr])
+    P.detailsWindows[detailsNr] = nil
+end --]]
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/SettingsMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/SettingsMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/SettingsMenu.lua	(revision 11817)
@@ -0,0 +1,75 @@
+-- SettingsMenu.lua
+
+local P = createMenuSheet("SettingsMenu")
+P.loadAlong = { "ControlsMenu", "AudioMenu", "GraphicsMenu" }
+
+function P.onLoad()
+    --"Gameplay" and "Multiplayer Options" are not integrated in the list
+    --buttons are arranged in a 4x2 matrix.
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/SettingsMenu/GraphicsButton"),
+            ["callback"]  = P.SettingsGraphicsButton_clicked
+    })
+
+    P:setButton(2, 2, {
+            ["button"] = winMgr:getWindow("orxonox/SettingsMenu/AudioButton"),
+            ["callback"]  = P.SettingsAudioButton_clicked
+    })
+
+    P:setButton(3, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SettingsMenu/ControlsButton"),
+            ["callback"]  = P.SettingsControlsButton_clicked
+    })
+
+    P:setButton(3, 2, {
+            ["button"] = winMgr:getWindow("orxonox/SettingsMenu/MiscellaneousButton"),
+            ["callback"]  = P.SettingsMiscellaneousButton_clicked
+    })
+
+    P:setButton(4, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SettingsMenu/SettingsBackButton"),
+            ["callback"]  = P.SettingsBackButton_clicked
+    })
+
+    P:setButton(4, 2, P:getButton(4, 1))
+end
+
+function P.onShow()
+    local window = winMgr:getWindow("orxonox/SettingsMenu/AudioButton")
+    if not orxonox.SoundManager:exists() then
+        window:setProperty("Disabled", "true")
+    else
+        window:setProperty("Disabled", "false")
+    end
+end
+
+function P.SettingsGameplayButton_clicked(e)
+    showMenuSheet("GameplayMenu", true)
+end
+
+function P.SettingsMultiplayerOptionsButton_clicked(e)
+    showMenuSheet("MultiplayerOptionsMenu", true)
+end
+
+function P.SettingsControlsButton_clicked(e)
+    showMenuSheet("ControlsMenu", true)
+end
+
+function P.SettingsGraphicsButton_clicked(e)
+    showMenuSheet("GraphicsMenu", true)
+end
+
+function P.SettingsAudioButton_clicked(e)
+    showMenuSheet("AudioMenu", true)
+end
+
+function P.SettingsMiscellaneousButton_clicked(e)
+    showMenuSheet("MiscConfigMenu", true)
+end
+
+function P.SettingsBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/SheetManager.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/SheetManager.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/SheetManager.lua	(revision 11817)
@@ -0,0 +1,326 @@
+-- SheetManager.lua
+
+local cursor = CEGUI.MouseCursor:getSingleton()
+local loadedSheets = {}
+local activeMenuSheets = {size = 0, topSheetTuple = nil}
+local menuSheetsRoot = guiMgr:getMenuRootWindow()
+local bInGameConsoleClosed = false
+local mainMenuLoaded = false
+orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "KeyDown", "keyPressed")
+orxonox.GUIManager:subscribeEventHelper(menuSheetsRoot, "Sized", "windowResized")
+
+------------------------
+--- Global functions ---
+------------------------
+
+function hideCursor()
+    if cursor:isVisible() then
+        cursor:hide()
+    end
+end
+
+function showCursor()
+    if not cursor:isVisible() and inputMgr:isMouseExclusive() then
+        cursor:show()
+    end
+end
+
+function getLoadedSheets()
+    local names = ""
+    for name, sheet in pairs(loadedSheets) do
+        names = names .. name
+        names = names .. ","
+    end
+    return names
+end
+
+-- Loads the GUI with the specified name
+-- The name corresponds to the filename of the *.lua and *.layout files
+-- but without the extension
+function loadSheet(name)
+    -- Check if it has already been loaded
+    local sheet = loadedSheets[name]
+    if sheet == nil then
+        -- Load the sheet
+        sheet = require(name)
+        sheet:load()
+        loadedSheets[name] = sheet
+    end
+    return sheet
+end
+
+-- ?
+function showMenuSheet(name, bHidePrevious, bNoInput, ptr)
+    local sheet = showMenuSheet(name, bHidePrevious, bNoInput)
+    sheet.overlay = ptr
+    return sheet
+end
+
+-- Shows the specified menu sheet and loads it if neccessary
+function showMenuSheet(name, bHidePrevious, bNoInput)
+    if name == "" then
+        return nil
+    end
+    -- Get sheet (or load it)
+    local menuSheet = loadSheet(name)
+
+    -- Use sheet's value if nil was provided
+    if bHidePrevious == nil then
+        bHidePrevious = menuSheet.bHidePrevious
+        assert(bHidePrevious ~= nil)
+    end
+
+    -- Set bNoInput to false if it hasn't been set.
+    if bNoInput == nil then
+        bNoInput = false
+    end
+
+    -- Count the number of sheets that don't need input till the first that does.
+    local counter = noInputSheetIndex()
+    -- Pause game control if this is the first menu to be displayed
+    -- HUGE HACK?
+    if bNoInput == false and counter == 0 then
+        orxonox.HumanController:pauseControl()
+    end
+
+    -- Hide if already displayed (to make sure it is up front in the end)
+    if activeMenuSheets[name] ~= nil then
+        hideMenuSheet(name)
+    end
+
+    if bNoInput == true then
+        menuSheet.tShowCursor = tribool(dontcare)
+    end
+
+    -- Add the sheet in a tuple of additional information
+    local sheetTuple =
+    {
+        ["sheet"]          = menuSheet,
+        ["bHidePrevious"]  = bHidePrevious,
+        ["bNoInput"]       = bNoInput,
+        ["name"]           = name
+    }
+    table.insert(activeMenuSheets, sheetTuple) -- indexed array access
+    activeMenuSheets[name] = sheetTuple -- name access
+    activeMenuSheets.size = activeMenuSheets.size + 1
+    activeMenuSheets.topSheetTuple = sheetTuple
+
+    -- Add sheet to the root window
+    menuSheetsRoot:addChildWindow(menuSheet.window)
+
+    -- If sheet is the MainMenu
+    if name == "MainMenu" then
+        mainMenuLoaded = true
+    end
+
+    -- Handle input distribution
+    if bNoInput == false then
+        inputMgr:enterState(menuSheet.inputState)
+    end
+
+    -- Only change cursor situation if menuSheet.tShowCursor ~= tribool(dontcare)
+    if menuSheet.tShowCursor == tribool(true) then
+        showCursor()
+    elseif menuSheet.tShowCursor == tribool(false) then
+        hideCursor()
+    end
+
+    -- Hide all previous sheets if necessary
+    local previous
+    if bHidePrevious then
+        for i = 1, activeMenuSheets.size - 1 do
+            previous = activeMenuSheets[i].sheet
+            previous:hide()
+        end
+    end
+
+    menuSheet:show()
+    menuSheetsRoot:activate()
+
+    -- select first button if the menu was opened with the keyboard
+    if previous and previous.pressedEnter and menuSheet:hasSelection() == false then
+        menuSheet:setSelectionNear(1, 1)
+    end
+
+    return menuSheet
+end
+
+function hideMenuSheet(name)
+    local sheetTuple = activeMenuSheets[name]
+    if sheetTuple == nil then
+        return
+    end
+
+    -- Hide the sheet
+    sheetTuple.sheet:hide()
+
+    -- Show sheets that were hidden by the sheet to be removed
+    local i = activeMenuSheets.size
+    -- Only do something if all sheets on top of sheetTuple
+    -- have bHidePrevious == true and sheetTuple.bHidePrevious == true
+    while i > 0 do
+        if activeMenuSheets[i].bHidePrevious then
+            if activeMenuSheets[i] == sheetTuple then
+                i = i - 1
+                while i > 0 do
+                    activeMenuSheets[i].sheet:show()
+                    if activeMenuSheets[i].bHidePrevious then
+                        break
+                    end
+                    i = i - 1
+                end
+            end
+            break
+        end
+        i = i - 1
+    end
+
+    -- Remove sheet with its tuple from the table
+    menuSheetsRoot:removeChildWindow(sheetTuple.sheet.window)
+    table.remove(activeMenuSheets, table.findIndex(activeMenuSheets, sheetTuple))
+    activeMenuSheets[name] = nil
+    activeMenuSheets.size = activeMenuSheets.size - 1
+    activeMenuSheets.topSheetTuple = activeMenuSheets[activeMenuSheets.size]
+
+    -- If sheet is the MainMenu
+    if name == "MainMenu" then
+        mainMenuLoaded = false
+    end
+
+    -- Leave the input state
+    if not sheetTuple.bNoInput then
+        inputMgr:leaveState(sheetTuple.sheet.inputState)
+    end
+
+    -- CURSOR SHOWING
+    local i = activeMenuSheets.size
+    -- Find top most sheet that doesn't have tShowCusor == tribool(dontcare)
+    while i > 0 and activeMenuSheets[i].sheet.tShowCursor == tribool(dontcare) do
+        i = i - 1
+    end
+    if i > 0 and activeMenuSheets[i].sheet.tShowCursor == tribool(true) then
+        showCursor()
+    else
+        hideCursor()
+    end
+
+    -- Count the number of sheets that don't need input till the first that does.
+    local counter = noInputSheetIndex()
+    -- Resume control if the last (non-noInput) menu is hidden
+    if counter == 0 then
+        orxonox.HumanController:resumeControl()
+        hideCursor()
+    end
+
+    sheetTuple.sheet:quit()
+end
+
+-- Hides all menu GUI sheets
+function hideAllMenuSheets()
+    while activeMenuSheets.size ~= 0 do
+        hideMenuSheet(activeMenuSheets.topSheetTuple.sheet.name)
+    end
+end
+
+function keyESC()
+    -- HUGE, very HUGE hacks!
+
+    -- If the InGameConsole is active, ignore the ESC command.
+    if bInGameConsoleClosed == true then
+        bInGameConsoleClosed = false
+        if activeMenuSheets[1] and activeMenuSheets[1].sheet.name == "MainMenu" then
+            return
+        end
+    end
+
+    -- Count the number of sheets that don't need input till the first that does.
+    local counter = noInputSheetIndex()
+
+    -- If the first sheet that needs input is the MainMenu.
+    if noInputSheetCounter() == 1 and activeMenuSheets[counter].sheet.name == "MainMenu" then
+        orxonox.execute("exit")
+    -- If there is at least one sheet that needs input.
+    elseif counter > 0 then
+        orxonox.execute("hideGUI "..activeMenuSheets[counter].sheet.name)
+    else
+        showMenuSheet("InGameMenu")
+    end
+end
+
+function keyPressed(e)
+    local we = tolua.cast(e, "CEGUI::KeyEventArgs")
+    local sheet = activeMenuSheets[activeMenuSheets.size]
+    code = tostring(we.scancode)
+    -- Some preprocessing
+    if not mainMenuLoaded and not sheet.bNoInput then
+        if code == "1" then
+            keyESC()
+        elseif code == "0"then
+            orxonox.CommandExecutor:execute("InGameConsole openConsole")
+        end
+    end
+    sheet.sheet:keyPressed()
+end
+
+function windowResized(e)
+    for name, sheet in pairs(loadedSheets) do
+        if orxonox.GraphicsManager:getInstance():isFullScreen() or sheet.tShowCursor == tribool(false) then
+            inputMgr:setMouseExclusive(sheet.inputState, tribool(true))
+        else
+            inputMgr:setMouseExclusive(sheet.inputState, tribool(false))
+        end
+    end
+    local sheetTuple = activeMenuSheets[activeMenuSheets.size]
+    if sheetTuple then
+        if orxonox.GraphicsManager:getInstance():isFullScreen() and sheetTuple.sheet.tShowCursor ~= tribool(false) then
+            showCursor()
+        else
+            hideCursor()
+        end
+        sheetTuple.sheet:windowResized()
+    end
+end
+
+function setBackgroundImage(imageSet, imageName)
+    guiMgr:setBackgroundImage(imageSet, imageName)
+end
+
+function noInputSheetIndex()
+    -- Count the number of sheets that don't need input till the first that does.
+    local index = activeMenuSheets.size
+    while index > 0 and activeMenuSheets[index].bNoInput do
+        index = index - 1
+    end
+    return index
+end
+
+function noInputSheetCounter()
+    -- Count the number of sheets that do need input.
+    local counter = activeMenuSheets.size
+    for i = 1,activeMenuSheets.size do
+        if activeMenuSheets[i].bNoInput then
+            counter = counter - 1
+        end
+    end
+    return counter
+end
+
+function inGameConsoleClosed()
+    bInGameConsoleClosed = not bInGameConsoleClosed;
+end
+
+function getGUIFirstActive(name, bHidePrevious, bNoInput)
+    local sheet = activeMenuSheets.topSheetTuple
+    -- If the topmost gui sheet has the input name
+    if sheet ~= nil and sheet.name == name then
+        guiMgr:toggleGUIHelper(name, bHidePrevious, bNoInput, false);
+    else
+        guiMgr:toggleGUIHelper(name, bHidePrevious, bNoInput, true);
+    end
+end
+
+----------------------
+--- Initialisation ---
+----------------------
+
+hideCursor()
Index: /code/branches/RacingBots_FS18/data/gui/scripts/ShipSelectionMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/ShipSelectionMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/ShipSelectionMenu.lua	(revision 11817)
@@ -0,0 +1,132 @@
+-- ShipSelectionMenu.lua
+
+local P = createMenuSheet("ShipSelectionMenu")
+P.activeTabIndexes = {}
+P.scrollbarWidth = 13
+P.shipList = {}
+function P.onLoad()
+    orxonox.execute("set shipmodelsfile [open {../levels/templates/.shipmodels} w+]")
+    orxonox.execute("foreach line [glob -directory ../levels/templates/ spaceship*] { regexp {.*/(.*)\\..*} $line matchall match1; puts $shipmodelsfile $match1 }")
+    orxonox.execute("close $shipmodelsfile")
+    P.createFilterTab("All Ships")
+end
+
+function P.createShipList() --generates list with tagged shipmodels
+    P.shipList = {}
+    file = io.open("../levels/templates/.shipmodels")
+    if file ~= nil then
+        for line in file:lines() do  --checks if shipmodel is included in level file
+            if selectedlevel:hasStartingShip(string.lower(line)) then
+                P.shipList[#P.shipList+1] = string.lower(line)
+            end
+        end
+        --file.close() -- TODO: investigate why close() seems to crash?
+    end
+end
+
+function P.update() --updates listbox with found models
+    P.createShipList()
+    listbox:resetList()
+    --orxonox.GUIManager:setItemTooltipsEnabledHelper(listbox, true)
+    local tabIndexes = {}
+    for k,v in pairs(P.shipList) do
+        --TODO: only add ship if is in the right filter tab
+        --if tag == nil or v:hasStartingShip(tag) then
+            local item = CEGUI.createListboxTextItem(v)
+            item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+            listbox:addItem(item)
+            table.insert(tabIndexes, k)
+            --orxonox.GUIManager:setTooltipTextHelper(item, v:getDescription())
+        --end
+    end
+    table.insert(P.activeTabIndexes, tabIndexes)
+end
+
+function P.createFilterTab(name) -- generates filter tab and list box, sets handler for selection changes
+    tabName = "orxonox/ShipSelectionLevelTab"
+    -- create new tab window with desired name
+    listbox = CEGUI.toListbox(winMgr:createWindow("MenuWidgets/Listbox", tabName))
+    listbox:setText(name)
+    listbox:setProperty("UnifiedMaxSize", "{{1,0},{1,0}}")
+    --[[TODO: smaller list if image and description is implemented.
+    listbox:setProperty("UnifiedAreaRect", "{{0.05,0},{0.1,0},{0.5,0},{0.675,0}}") --]]
+    listbox:setProperty("UnifiedAreaRect", "{{0,0},{0,0},{1,0},{1,0}}")
+    -- fill listbox with items
+    P.update()
+    -- listen to selection changes
+    orxonox.GUIManager:subscribeEventHelper(listbox, "ItemSelectionChanged", P.name..".ShipSelectionSelectionChanged")
+    local tabControl = winMgr:getWindow("orxonox/ShipSelectionTabControl")
+    orxonox.GUIManager:subscribeEventHelper(tabControl, "TabSelectionChanged", P.name..".ShipSelectionSelectionChanged")
+    if listbox:getItemCount() > 0 then
+        tabControl:addChildWindow(tabName)
+    end
+end
+
+function P.ShipSelectionGetSelectedModel() --returns selected model, if available.
+    -- choose the active listbox
+    local tabControl = CEGUI.toTabControl(winMgr:getWindow("orxonox/ShipSelectionTabControl"))
+    local listbox = CEGUI.toListbox(tabControl:getTabContentsAtIndex(tabControl:getSelectedTabIndex()))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        -- get the right tab and the right index
+        local tabIndexes = P.activeTabIndexes[tabControl:getSelectedTabIndex()+1]
+        local index = tabIndexes[listbox:getItemIndex(choice)+1]
+        return P.shipList[index]
+    else
+        return nil
+    end
+end
+
+function P.ShipSelectionSelectionChanged(e)
+    --[[ TODO: Get image and description from template file
+    local levelImage = winMgr:getWindow("orxonox/ShipSelectionLevelImage")
+    local levelDescription = winMgr:getWindow("orxonox/ShipSelectionLevelDescription")
+    local configButton = winMgr:getWindow("orxonox/ShipSelectionConfigButton")
+    local level = P.ShipSelectionGetSelectedModel()
+    if level ~= nil then
+        --local levelXMLFilename = selectedlevel:getXMLFilename()
+        --local imageName = selectedlevel:getScreenshot()
+        -- set the screenshot and the description for the selected level
+        --levelImage:setProperty("Image", "set:"..levelXMLFilename..imageName.." image:full_image")
+        --levelDescription:setText(level:getDescription())
+        -- only enable config button for "gametype" levels
+        --if level:hasTag("gametype") then
+         --   configButton:setProperty("Disabled", "False")
+        --else
+        --    configButton:setProperty("Disabled", "True")
+        --end
+    else
+        -- also take care of "no level selected"
+        levelImage:setProperty("Image", nil)
+        levelDescription:setText("")
+    end
+   --]]
+end
+
+function P.ShipSelectionStartButton_clicked(e)
+
+    if (selectedlevel ~= nil and P.ShipSelectionGetSelectedModel() ~= nil)  then
+    selectedlevel:selectStartingShip(P.ShipSelectionGetSelectedModel())
+        orxonox.execute("startGame " .. "_temp.oxw")
+        hideAllMenuSheets()
+    else
+    orxonox.execute("orxout user_warning no ship model selected or no tagged shipmodel installed")
+    end
+end
+
+--[[ TODO: function P.ShipSelectionConfigButton_clicked(e)
+
+    local level = P.ShipSelectionGetSelectedModel()
+    if level ~= nil then
+        local configMenu = showMenuSheet("ShipSelectionConfigMenu")
+        configMenu:loadConfig(level)
+    end
+end
+--]]
+
+
+function P.ShipSelectionBackButton_clicked(e)
+    orxonox.execute("keyESC")
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/SingleplayerConfigMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/SingleplayerConfigMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/SingleplayerConfigMenu.lua	(revision 11817)
@@ -0,0 +1,198 @@
+-- SingleplayerMenu.lua
+
+local P = createMenuSheet("SingleplayerConfigMenu")
+
+P.commandList = {}
+P.nameList = {}
+P.linesList = {}
+
+P.sampleWindow = nil
+
+P.lineHeight = 0
+P.commandWidth = 0
+P.editboxWidth = 0
+P.resetWidth = 0
+P.spaceWidth = 0
+
+function P.onLoad()
+    P.sampleWindow = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/SingleplayerConfigMenu/MiscConfigPane/SampleWindow")
+    P.sampleWindow:setText("SampleText")
+
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerConfigMenu/CancelButton"),
+            ["callback"]  = P.SingleplayerConfigCancelButton_clicked
+    })
+    
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerConfigMenu/OKButton"),
+            ["callback"]  = P.SingleplayerConfigOKButton_clicked
+    })
+end
+
+function P.loadConfig(level)
+    P.commandList = {}
+    table.insert(P.commandList, "Gametype initialStartCountdown_")
+    table.insert(P.commandList, "Gametype bAutoStart_")
+    table.insert(P.commandList, "Gametype numberOfBots_")
+    table.insert(P.commandList, "Dynamicmatch gameTime_")
+    table.insert(P.commandList, "Dynamicmatch friendlyfire")
+    table.insert(P.commandList, "Dynamicmatch tutorial")
+    table.insert(P.commandList, "LastManStanding lives")
+    table.insert(P.commandList, "LastManStanding respawnDelay")
+    table.insert(P.commandList, "LastManStanding bNoPunishment")
+    table.insert(P.commandList, "LastManStanding bHardPunishment")
+    table.insert(P.commandList, "LastTeamStanding lives")
+    table.insert(P.commandList, "LastTeamStanding respawnDelay")
+    table.insert(P.commandList, "LastTeamStanding bNoPunishment")
+    table.insert(P.commandList, "LastTeamStanding bHardPunishment")
+    table.insert(P.commandList, "TeamDeathmatch teams_")
+    table.insert(P.commandList, "UnderAttack gameTime_")
+
+    P.nameList = {}
+    table.insert(P.nameList, "Start countdown")
+    table.insert(P.nameList, "Autostart")
+    table.insert(P.nameList, "Number of Bots")
+    table.insert(P.nameList, "Dynamicmatch: game time")
+    table.insert(P.nameList, "Dynamicmatch: friendly fire")
+    table.insert(P.nameList, "Dynamicmatch: tutorial")
+    table.insert(P.nameList, "LastManStanding: lives")
+    table.insert(P.nameList, "LastManStanding: respawn delay")
+    table.insert(P.nameList, "LastManStanding: no punishment")
+    table.insert(P.nameList, "LastManStanding: hard punishment")
+    table.insert(P.nameList, "LastTeamStanding: lives")
+    table.insert(P.nameList, "LastTeamStanding: respawn delay")
+    table.insert(P.nameList, "LastTeamStanding: no punishment")
+    table.insert(P.nameList, "LastTeamStanding: hard punishment")
+    table.insert(P.nameList, "TeamDeathmatch: Number of teams")
+    table.insert(P.nameList, "UnderAttack: game time")
+
+    P.linesList = {}
+    
+    --Calculate design parameters:
+    local size = getMinTextSize(P.sampleWindow)
+    P.lineHeight = size[1]
+
+    P.commandWidth = 0
+    for k,v in pairs(P.commandList) do
+        P.sampleWindow:setText(P.nameList[k])
+        size = getMinTextSize(P.sampleWindow)
+        if size[2] > P.commandWidth then
+            P.commandWidth = size[2]
+        end
+    end
+
+    P.sampleWindow:setText("reset")
+    size = getMinTextSize(P.sampleWindow)
+    P.resetWidth = size[2]+20
+
+    P.spaceWidth = 10
+    
+    local pane = tolua.cast(winMgr:getWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane"), "CEGUI::ScrollablePane")
+    size = pane:getViewableArea()
+    P.editboxWidth = size:getWidth() - P.commandWidth - P.resetWidth - 5*P.spaceWidth
+
+    P.createLines()
+end
+
+function P.createLine(k)
+    local offset = 0
+    -- destroy config line, if it already exists (otherwise would cause an error)
+    if winMgr:isWindowPresent("orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k) then
+        winMgr:destroyWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k)
+    end
+    -- content window for the entire line
+    local line = winMgr:createWindow("DefaultWindow", "orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k)
+    line:setHeight(CEGUI.UDim(0, P.lineHeight))
+    line:setPosition(CEGUI.UVector2(CEGUI.UDim(0, 0), CEGUI.UDim(0, P.lineHeight*(k-1))))
+
+    -- config name
+    local command = winMgr:createWindow("MenuWidgets/StaticText", "orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Command")
+    command:setText(P.nameList[k])
+    command:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.commandWidth), CEGUI.UDim(1, 0)))
+    command:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0, 0)))
+    line:addChildWindow(command)
+    offset = offset + P.commandWidth + P.spaceWidth
+
+    -- config value (editable)
+    local configvalue = winMgr:createWindow("MenuWidgets/Editbox", "orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Configvalue")
+    configvalue:setProperty("ReadOnly", "set:False")
+    local value = orxonox.CommandExecutor:query("getConfig " .. P.commandList[k])
+    configvalue:setText(value)
+    configvalue:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.editboxWidth), CEGUI.UDim(0.9, 0)))
+    configvalue:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.05, 0)))
+    -- enable the reset button if the value changed
+    orxonox.GUIManager:subscribeEventHelper(configvalue, "TextAccepted", P.name .. ".SingleplayerConfigEditbox_textAccepted")
+    line:addChildWindow(configvalue)
+    offset = offset + P.editboxWidth + P.spaceWidth
+
+    -- reset button (only available when value changed)
+    local reset = winMgr:createWindow("MenuWidgets/Button", "orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Reset")
+    reset:setSize(CEGUI.UVector2(CEGUI.UDim(0, P.resetWidth), CEGUI.UDim(0.9, 0)))
+    reset:setPosition(CEGUI.UVector2(CEGUI.UDim(0, offset), CEGUI.UDim(0.05, 0)))
+    reset:setText("reset")
+    orxonox.GUIManager:subscribeEventHelper(reset, "Clicked", P.name .. ".SingleplayerConfigResetButton_clicked")
+    line:addChildWindow(reset)
+    reset:setEnabled(false)
+    offset = offset + P.resetWidth + P.spaceWidth
+
+    line:setWidth(CEGUI.UDim(0, offset))
+
+    return line
+end
+
+function P.createLines()
+    local window = winMgr:getWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane")
+
+    for k,v in pairs(P.commandList) do
+        local line = P.createLine(k)
+        table.insert(P.linesList, line)
+        window:addChildWindow(line)
+    end
+
+    local pane = tolua.cast(window, "CEGUI::ScrollablePane")
+    pane:setVerticalStepSize(getScrollingStepSize(window))
+end
+
+function P.SingleplayerConfigOKButton_clicked(e)
+    for k,v in pairs(P.commandList) do
+        -- save the changes
+        local editbox = winMgr:getWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Configvalue")
+        orxonox.CommandExecutor:execute("config " .. P.commandList[k] .. " " .. editbox:getText())
+        local resetButton = winMgr:getWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. k .. "/Reset")
+        resetButton:setEnabled(false)
+    end
+    
+    hideMenuSheet("SingleplayerConfigMenu")
+end
+
+function P.SingleplayerConfigCancelButton_clicked(e)
+    hideMenuSheet("SingleplayerConfigMenu")
+end
+
+function P.SingleplayerConfigEditbox_textAccepted(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+
+    local resetButton = winMgr:getWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. commandNr .. "/Reset")
+    resetButton:setEnabled(true)
+end
+
+function P.SingleplayerConfigResetButton_clicked(e)
+    local we = CEGUI.toWindowEventArgs(e)
+    local name = we.window:getName()
+
+    local match = string.gmatch(name, "%d+")
+    local commandNr = tonumber(match())
+
+    -- reload the old value
+    local editbox = winMgr:getWindow("orxonox/SingleplayerConfigMenu/MiscConfigPane/ConfigCommand" .. commandNr .. "/Configvalue")
+    local value = orxonox.CommandExecutor:query("getConfig " .. P.commandList[commandNr])
+    editbox:setText(value)
+    
+    we.window:setEnabled(false)
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/SingleplayerMenu.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/SingleplayerMenu.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/SingleplayerMenu.lua	(revision 11817)
@@ -0,0 +1,179 @@
+-- SingleplayerMenu.lua
+
+local P = createMenuSheet("SingleplayerMenu")
+P.loadAlong = {"ShipSelectionMenu","CampaignMenu"}
+P.levelList = {}
+P.activeTabIndexes = {}
+P.scrollbarWidth = 13
+selectedlevel = {} -- level for ship selection
+
+function P.onLoad()
+    P.createLevelList()
+
+    -- create tabs with desired tab as argument (nil for all)
+    P.createFilterTab("Gametypes", "gametype")
+    P.createFilterTab("Missions", "mission")
+    P.createFilterTab("Minigames", "minigame")
+    P.createFilterTab("Showcases", "showcase")
+    P.createFilterTab("Presentations", "presentation")
+    P.createFilterTab("Tests", "test")
+    P.createFilterTab("Show All", nil)
+
+    -- update description and screenshot boxes
+    P.SingleplayerSelectionChanged()
+
+    --buttons are arranged in a 2x3 matrix
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerStartButton"),
+            ["callback"]  = P.SingleplayerStartButton_clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerConfigButton"),
+            ["callback"]  = P.SingleplayerConfigButton_clicked
+    })
+
+    P:setButton(1, 3, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerBackButton"),
+            ["callback"]  = P.SingleplayerBackButton_clicked
+    })
+
+    P:setButton(2, 2,{
+            ["button"] = winMgr:getWindow("orxonox/CampaignButton"),
+            ["callback"] = P.CampaignButton_clicked
+    })
+end
+
+function P.createLevelList()
+    P.levelList = {}
+    local size = orxonox.LevelManager:getInstance():getNumberOfLevels()
+    local index = 0
+    local level = nil
+    while index < size do
+        level = orxonox.LevelManager:getInstance():getAvailableLevelListItem(index)
+        if (level ~= nil and level:getXMLFilename() ~= "_temp.oxw") then
+            local levelXMLFilename = level:getXMLFilename()
+            -- create an imageset for each screenshot
+            local imageName = level:getScreenshot()
+            if imageName ~= "" then
+                CEGUI.ImagesetManager:getSingleton():createFromImageFile(levelXMLFilename..imageName, imageName)
+            else
+                CEGUI.ImagesetManager:getSingleton():createFromImageFile(levelXMLFilename..imageName, "noscreenshot.png")
+            end
+            table.insert(P.levelList, level)
+        end
+        index = index + 1
+    end
+end
+
+function P.createFilterTab(name, tag)
+    -- create unique tab window name
+    local tabName = "orxonox/SingleplayerLevelTab"
+    if tag ~= nil then
+        tabName = tabName..tag
+    end
+    -- create new tab window with desired name
+    local listbox = CEGUI.toListbox(winMgr:createWindow("MenuWidgets/Listbox", tabName))
+    listbox:setText(name)
+    listbox:setProperty("UnifiedMaxSize", "{{1,0},{1,0}}")
+    listbox:setProperty("UnifiedAreaRect", "{{0.05,0},{0.1,0},{0.5,0},{0.675,0}}")
+    -- fill listbox with items
+    listbox:resetList()
+    orxonox.GUIManager:setItemTooltipsEnabledHelper(listbox, true)
+    local preselect = orxonox.LevelManager:getInstance():getDefaultLevel()
+    local tabIndexes = {}
+    for k,v in pairs(P.levelList) do
+        -- only add level if it has desired tag
+        if tag == nil or v:hasTag(tag) then
+            local item = CEGUI.createListboxTextItem(v:getName())
+            item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+            listbox:addItem(item)
+            table.insert(tabIndexes, k)
+            if v:getXMLFilename() == preselect then
+                listbox:setItemSelectState(item, true)
+            end
+            orxonox.GUIManager:setTooltipTextHelper(item, v:getDescription())
+        end
+    end
+    table.insert(P.activeTabIndexes, tabIndexes)
+    -- listen to selection changes
+    orxonox.GUIManager:subscribeEventHelper(listbox, "ItemSelectionChanged", P.name..".SingleplayerSelectionChanged")
+    local tabControl = winMgr:getWindow("orxonox/SingleplayerTabControl")
+    orxonox.GUIManager:subscribeEventHelper(tabControl, "TabSelectionChanged", P.name..".SingleplayerSelectionChanged")
+    if listbox:getItemCount() > 0 then
+        tabControl:addChildWindow(tabName)
+    end
+end
+
+function P.SingleplayerGetSelectedLevel()
+    -- choose the active listbox
+    local tabControl = CEGUI.toTabControl(winMgr:getWindow("orxonox/SingleplayerTabControl"))
+    local listbox = CEGUI.toListbox(tabControl:getTabContentsAtIndex(tabControl:getSelectedTabIndex()))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        -- get the right tab and the right index
+        local tabIndexes = P.activeTabIndexes[tabControl:getSelectedTabIndex()+1]
+        local index = tabIndexes[listbox:getItemIndex(choice)+1]
+        return P.levelList[index]
+    else
+        return nil
+    end
+end
+
+function P.SingleplayerSelectionChanged(e)
+    local levelImage = winMgr:getWindow("orxonox/SingleplayerLevelImage")
+    local levelDescription = winMgr:getWindow("orxonox/SingleplayerLevelDescription")
+    local configButton = winMgr:getWindow("orxonox/SingleplayerConfigButton")
+    local level = P.SingleplayerGetSelectedLevel()
+    if level ~= nil then
+        local levelXMLFilename = level:getXMLFilename()
+        local imageName = level:getScreenshot()
+        -- set the screenshot and the description for the selected level
+        levelImage:setProperty("Image", "set:"..levelXMLFilename..imageName.." image:full_image")
+        levelDescription:setText(level:getDescription())
+        -- only enable config button for "gametype" levels
+        if level:hasTag("gametype") then
+            configButton:setProperty("Disabled", "False")
+        else
+            configButton:setProperty("Disabled", "True")
+        end
+    else
+        -- also take care of "no level selected"
+        levelImage:setProperty("Image", "")
+        levelDescription:setText("")
+        configButton:setProperty("Disabled", "True")
+    end
+end
+
+function P.SingleplayerStartButton_clicked(e)
+    selectedlevel = P.SingleplayerGetSelectedLevel()
+    if selectedlevel ~= nil then
+        if selectedlevel:hasTag("shipselection") then
+            local shipSelectionMenu = showMenuSheet("ShipSelectionMenu", true)
+            shipSelectionMenu:update()
+        else
+            orxonox.execute("startGame " .. selectedlevel:getXMLFilename())
+            hideAllMenuSheets()
+        end
+    end
+end
+
+function P.SingleplayerConfigButton_clicked(e)
+    local level = P.SingleplayerGetSelectedLevel()
+    if level ~= nil then
+        local configMenu = showMenuSheet("SingleplayerConfigMenu")
+        configMenu:loadConfig(level)
+    end
+end
+
+function P.SingleplayerBackButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+function P.CampaignButton_clicked(e)
+    -- showMenuSheet("CampaignMenu", true)
+    hideAllMenuSheets()
+    orxonox.execute("startGame StoryModeMap.oxw")
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/TestDialogButttons.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/TestDialogButttons.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/TestDialogButttons.lua	(revision 11817)
@@ -0,0 +1,30 @@
+local P = createMenuSheet("dialogue")
+
+function P.onLoad()
+    --buttons are arranged in a 2x1 Matrix (list)
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/QuickGameTestButton"),
+            ["callback"]  = P.QuickGameTestButton_clicked
+    })
+
+    P:setButton(2, 1, {
+            ["button"] = winMgr:getWindow("orxonox/SingleplayerButton"),
+            ["callback"]  = P.SingleplayerButton_clicked
+    })
+
+end
+
+-- events for options
+function P.QuickGameTestButton_clicked(e)
+    hideAllMenuSheets()
+    orxonox.execute("startGame")
+end
+
+function P.SingleplayerButton_clicked(e)
+    showMenuSheet("SingleplayerMenu", true)
+end
+
+
+
+return P
+
Index: /code/branches/RacingBots_FS18/data/gui/scripts/UndockingDialog.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/UndockingDialog.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/UndockingDialog.lua	(revision 11817)
@@ -0,0 +1,69 @@
+-- DockingDialog.lua
+
+local P = createMenuSheet("UndockingDialog")
+
+P.docks = {}
+
+function P.onLoad()
+
+     --button are arranged in a 1x2 matrix
+    P:setButton(1, 1, {
+            ["button"] = winMgr:getWindow("orxonox/Undocking/DockButton"),
+            ["callback"]  = P.undockButton_clicked
+    })
+
+    P:setButton(1, 2, {
+            ["button"] = winMgr:getWindow("orxonox/Undocking/CancelButton"),
+            ["callback"]  = P.cancelButton_clicked
+    })
+    
+end
+
+function P.onShow()
+    orxonox.execute("setPause 1")
+    P.update()
+end
+
+function P.onHide()
+    orxonox.execute("setPause 0")
+end
+
+function P.update()
+    -- update dock list
+    P.docks = {}
+    local docks = orxonox.Dock:getNumberOfActiveDocks()
+    for i = 0, docks-1 do
+        table.insert(P.docks, orxonox.Dock:getActiveDockAtIndex(i))
+    end
+
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/Undocking/Docks"))
+    listbox:resetList()
+
+    for k in pairs(P.docks) do
+        local item = CEGUI.createListboxTextItem("Dock " .. k)
+        item:setSelectionBrushImage(menuImageSet, "MultiListSelectionBrush")
+        listbox:addItem(item)
+        if k == 1 then
+            listbox:setItemSelectState(item, true)
+        end
+    end
+end
+
+function P.undockButton_clicked(e)
+    local listbox = CEGUI.toListbox(winMgr:getWindow("orxonox/Undocking/Docks"))
+    local choice = listbox:getFirstSelectedItem()
+    if choice ~= nil then
+        local index = listbox:getItemIndex(choice)
+        local dock = P.docks[index+1]
+        if dock ~= nil then
+            dock:undock()
+        end
+    end
+    hideMenuSheet(P.name)
+end
+
+function P.cancelButton_clicked(e)
+    hideMenuSheet(P.name)
+end
+
+return P
Index: /code/branches/RacingBots_FS18/data/gui/scripts/presentation.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/presentation.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/presentation.lua	(revision 11817)
@@ -0,0 +1,37 @@
+-- Set some test variables
+x0 = 0
+y0 = 500
+z0 = 500
+
+xo = 2000 
+yo = 0
+zo = 0
+
+x1 = 3000
+y1 = 0 
+z1 = 0
+
+x2 = 2000
+y2 = 2000 
+z2 = 0
+
+-- Get a local pointer to a scriptcontroller
+local ctrl = orxonox.ScriptController:getScriptController()
+
+-- If it worked, call its "movetoposition" function
+if ctrl ~= nil then
+
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("chl", x0, y0, z0, xo, yo, zo, 2)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("mal", x2, y2, z2, xo, yo, zo, 2)
+  ctrl:eventScheduler("mal", x1, y1, z1, xo, yo, zo, 2)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("ral", xo, yo, zo, 3, 1000, 0, 5)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("ral", xo, yo, zo, 2, 1000, 0, 5)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("ral", xo, yo, zo, 1, 1000, 0, 5)
+  ctrl:eventScheduler("idle", 1)
+
+end
Index: /code/branches/RacingBots_FS18/data/gui/scripts/testscript.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/gui/scripts/testscript.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/gui/scripts/testscript.lua	(revision 11817)
@@ -0,0 +1,40 @@
+-- Set some test variables
+xm = 1000 
+ym = 0
+zm = 0
+
+xl = -1000 
+yl = 3000 
+zl = -1000
+
+xr = 2000
+yr = 500
+zr = 2000
+
+d = 5
+Tabs = 0
+
+pi = 3.1415
+
+-- Get a local pointer to a scriptcontroller
+local ctrl = orxonox.ScriptController:getScriptController()
+
+-- If it worked, call its "movetoposition" function
+if ctrl ~= nil then
+
+  ctrl:eventScheduler("mal", xl,yl,zl, xl,yl,zl, 2)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("ral", xl, yl, zl, 3, 3000, 0, math.pi)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("mal", 0,0,1000, xl,yl,zl, 3)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("chl", xl, yl, zl, xr, yr, zr, 2)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("mal", xr + 600,yr,zr, xr,yr,zr, 4)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("chl", xr, yr, zr, xl, yl, zl, 3)
+  ctrl:eventScheduler("idle", 1)
+  ctrl:eventScheduler("spi", xm,ym,zm, 0,0,0, 4)
+  ctrl:eventScheduler("idle", 1)
+
+end
Index: /code/branches/RacingBots_FS18/data/levels/4Dtest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/4Dtest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/4Dtest.oxw	(revision 11817)
@@ -0,0 +1,83 @@
+<LevelInfo
+ name = "4Dtest"
+ description = "Test of 4D minigame."
+  screenshot = "asteroidFieldTest.png"
+ tags = "test, showcase"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<!-- Templates here -->
+
+
+<Level
+ plugins=mini4dgame
+ gametype=Mini4Dgame
+>
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+	<WorldAmbientSound
+      source="Ganymede.ogg"
+      looping="true"
+      playOnLoad="true"
+    />
+    
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    
+    
+    <SpawnPoint position="-330,330,165" lookat="0,0,0" />
+
+	<Mini4DgameBoard>
+    	<attached>
+      	<?lua
+        	for i = -90, 90, 60
+        	do
+        	?>
+        		<?lua
+        		for j = -90, 90, 60
+        		do
+        		?>
+        			<?lua
+        			for k = -90, 90, 60
+        			do
+        			?>
+        				<Model
+        				position="<?lua print(i) ?>,<?lua print(j) ?>,<?lua print(k) ?>"
+        				mesh="checkPoint.mesh"
+        				scale="5" />
+        			<?lua
+    		  		end
+    				?>
+    			<?lua
+    		  	end
+    			?>
+        	<?lua
+    		end
+    		?>
+    	</attached>
+    	
+  	</Mini4DgameBoard>
+
+<!--
+<attached>
+    <BlinkingBillboard position="0,0,0" frequency=0.6 amplitude=0.4 material="Flares/lensflare" colour="0,1,0" visabilaty=gone>
+	</BlinkingBillboard>
+</attached>
+-->
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/AITest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/AITest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/AITest.oxw	(revision 11817)
@@ -0,0 +1,351 @@
+<LevelInfo
+ name = "New AI testing level"
+ description = "A level with two opposing new AI teams"
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipRing.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <TeamSpawnPoint team=0 position="2000, 2000, 2000" lookat="1,1,-1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+       
+    <Pawn position = "100000, 100000, 100000">
+      <controller>
+        <MasterController>
+        </MasterController>
+      </controller>
+    </Pawn>
+<!--     
+    <PickupSpawner pickup=largedamageboostpickup position="0,0,0" triggerDistance="20" respawnTime="30" maxSpawnedItems="10" />
+<PickupSpawner pickup=crazyhealthpickup position="0,0,0" triggerDistance="50" respawnTime="30" maxSpawnedItems="10" />
+<PickupSpawner pickup=hugeshieldpickup position="4000,4500, 4500" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+<PickupSpawner pickup=smalljumppickup position="6500,6500, 6000" triggerDistance="20" respawnTime="10" maxSpawnedItems="99" />
+<PickupSpawner pickup=largedamageboostpickup position="9500,9500, 9500" triggerDistance="20" respawnTime="30" maxSpawnedItems="10" />
+<PickupSpawner pickup=largedamageboostpickup position="13000,13000,13000" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+ -->
+<!-- HERE STARTS DEMO FOR THE "WAYPOINTS" -->
+      <!-- 
+    <SpaceShip position="-1500, -1500, -1500" lookat="0,0,0" team=0 name="ss1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=1 formationMode="finger4">
+          <actionpoints>
+            <Model mesh="cube.mesh" scale=8 position="  0,2000,-600" />
+            <Model mesh="cube.mesh" scale=8 position="  0,2000,-1000" />
+            <Model mesh="cube.mesh" scale=8 position="400,2000,-1000" />
+            <Model mesh="cube.mesh" scale=8 position="400,2000,-600" />
+          </actionpoints>
+        </DivisionController>
+      </controller>
+    </SpaceShip> 
+ -->
+    <!-- those two are same -->
+
+ <!--    
+    <Model mesh="cube.mesh" scale=8 position="  0,2000,-600" />
+    <Model mesh="cube.mesh" scale=8 position="  0,2000,-1000" />
+    <Model mesh="cube.mesh" scale=8 position="400,2000,-1000" />
+    <Model mesh="cube.mesh" scale=8 position="400,2000,-600" />
+    <SpaceShip position="-1500, 1500, -1000" lookat="0,0,0" team=0 name="ss1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=0 formationMode="finger4">
+          <actionpoints>
+            <Actionpoint position="  0,2000,-600" action="FLY" loopStart=true/>
+            <Actionpoint position="  0,2000,-1000" action="FLY"  />
+            <Actionpoint position="400,2000,-1000" action="FLY" />
+            <Actionpoint position="400,2000,-600" action="FLY" loopEnd=true />
+          </actionpoints>
+        </DivisionController>
+      </controller>
+    </SpaceShip>  -->
+   
+<!-- HERE ENDS DEMO FOR THE "WAYPOINTS" -->
+
+<!-- HERE STARTS DEMO FOR THE ACTIONPOINTS. 
+P.S. Never set protectMe in the first actionpoint: if human didn't spawn, that actionpoint will be skipped -->
+       <!-- 
+    <Model mesh="cube.mesh" scale=8 position="0,0,0" />
+
+    <SpaceShip position="-2000, 1500, -1000" lookat="0,0,0" team=0 name="ss2">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=0 formationMode="finger4">
+          <actionpoints>
+            <Actionpoint position="0,0,0" action="FLY" /> 
+            <Actionpoint position="-1000,750,-500" action="ATTACK" attack="attack" />
+            <Actionpoint position="-1000,750,-500" action="PROTECt" protectMe=true />
+            <Actionpoint position="-1000,750,-500" action="PROTECt" protect="protect" /> 
+            <Actionpoint position="-1000,750,-500" action="FIGHTALL" />
+           </actionpoints>
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-2000, 1900, -1000" lookat="0,0,0" team=0>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <SectionController team=0>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-2000, 2100, -1000" lookat="0,0,0" team=0>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-2000, 2400, -1000" lookat="0,0,0" team=0>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="0, 0, 0" lookat="0,0,0" team=2 name="ss4">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+    </SpaceShip>
+    <SpaceShip position="3000, 1000, 2000" lookat="0,0,0" team=2 name="attack">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+    </SpaceShip>
+    <SpaceShip position="-500, -300, -300" lookat="0,0,0" team=0 name="protect">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+    </SpaceShip> 
+  -->
+   
+<!-- HERE ENDS DEMO FOR THE ACTIONPOINTS -->
+<!-- HERE STARTS DEMO FOR FIGHTING -->
+    
+
+    <SpaceShip position="-4000, 1500, -1000" lookat="0,0,0" team=0 name="d1sd1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=0 formationMode="WALL">
+
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-4000, 1900, -1000" lookat="0,0,0" team=0 name="d1ss1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <SectionController team=0>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-4000, 2100, -1000" lookat="0,0,0" team=0 name="d1sw1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-4000, 2400, -1000" lookat="0,0,0" team=0 name="d1sw2">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="2000, -1500, 1000" lookat="0,0,0" team=1  name="d2sd1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=1 formationMode="DIAMOND">
+
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="2000, -1900, 1000" lookat="0,0,0" team=1 name="d2ss1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <SectionController team=1>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="2000, -2100, 1000" lookat="0,0,0" team=1 name="d2sw1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=1>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="2000, -2400, 1000" lookat="0,0,0" team=1 name="d2sw2">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=1>
+        </WingmanController>
+      </controller>
+    </SpaceShip> 
+
+<!-- HERE ENDS DEMO FOR FIGHTING -->
+<!-- HERE STARTS DEMO FOR FORMATIONS -->
+    <!-- 
+    <Model mesh="cube.mesh" scale=8 position="   0,2000,    0" />
+    <Model mesh="cube.mesh" scale=8 position="   0,2000,-2000" />
+    <Model mesh="cube.mesh" scale=8 position="2000,2000,-2000" />
+    <Model mesh="cube.mesh" scale=8 position="2000,2000,    0" />
+
+    <SpaceShip position="-1500, 1500, -1000" lookat="0,0,0" team=0 name="ss1">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=0 formationMode="diamond" spread=100>
+          <actionpoints>
+            <Actionpoint position="   0,2000,    0" action="FLY" loopStart=true/>
+            <Actionpoint position="   0,2000,-2000" action="FLY"  />
+            <Actionpoint position="2000,2000,-2000" action="FLY" />
+            <Actionpoint position="2000,2000,    0" action="FLY" loopEnd=true />
+          </actionpoints>
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-2000, 1900, -1000" lookat="0,0,0" team=0>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <SectionController team=0>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-2000, 2100, -1000" lookat="0,0,0" team=0>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="-2000, 2400, -1000" lookat="0,0,0" team=0>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip> 
+    -->
+<!-- HERE ENDS DEMO FOR FORMATIONS -->
+    <!-- 1 division is roughly equal to 6 AIControllers--!>
+<!-- 
+    <SpaceShip position="2000, -1500, 1000" lookat="0,0,0" team=1 >
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <DivisionController team=1 formationMode="WALL">
+
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="2000, -1900, 1000" lookat="0,0,0" team=1>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <SectionController team=1>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="2000, -2100, 1000" lookat="0,0,0" team=1>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=1>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="2000, -2400, 1000" lookat="0,0,0" team=1>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WingmanController team=1>
+        </WingmanController>
+      </controller>
+    </SpaceShip> 
+
+    <?lua
+      for i = 0, 5, 1 do
+        ?>
+      <SpaceShip position="<?lua print(7000) ?>,<?lua print(i*500) ?>,<?lua print(0) ?>" team=2>
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <AIController team=2 />
+        </controller>
+      </SpaceShip>
+    <?lua end ?> -->
+    
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/AnihilationThreat.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/AnihilationThreat.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/AnihilationThreat.oxw	(revision 11817)
@@ -0,0 +1,750 @@
+<!--########################  Level by Jean-Marc Sujata #############################-->
+
+<LevelInfo
+	name= "Total Annihilation"
+	description= "Save humanity from its total annihilation."
+	tags= "mission"
+	screenshot= "screenshot.png"
+/>
+<!--########################  ALL INCLUSIONS #############################-->
+
+ <?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+
+?>
+
+
+
+<?lua
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipGhost.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipTransporter.oxt")
+
+
+?>
+
+<Level 	gametype = "Mission" >
+ 
+<templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+  
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=8
+    displayTime=4
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.8, 0.5, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+
+   <?lua
+    dofile("includes/CuboidSpaceStation.lua")
+   ?>
+
+
+
+<Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+    hasPhysics = true
+ >
+
+<?lua
+      include("includes/pickups.oxi")
+   ?>
+  
+  <Light 
+  	type=directional position="0,0,0" 
+  	direction="0.522, 0.198, -0.354" 
+  	diffuse="1.0, 0.9, 0.9, 1.0" 
+  	specular="1.0, 0.9, 0.9, 1.0"/>
+  	
+  	
+  <SpawnPoint 
+	team=0 position="0,0,0" 
+	lookat="0,1,0" 
+	spawnclass=SpaceShip 
+	pawndesign=spaceshipassff >
+	<DistanceTriggerBeacon name="coolSpaceship" />
+	</SpawnPoint>
+	
+	<Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Model mesh="Spacegate.mesh" yaw="90"/>
+            </attached>
+        </PortalEndPoint>
+    </Template>
+    
+    				
+    
+
+
+
+
+<!--########################  Billboards and Pickups #############################-->
+    
+    
+  
+    
+    
+    <!--Billboard which tirggers the next Quest and spawns the enemy ships-->
+<Billboard position=" 500,500, 500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 1500,1500, 1500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 2500,2500, 2500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 3500,3500, 3500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 4500,4500, 4500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 6500,6500, 6500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 8500,8500, 8500" material="Examples/Flare" colour="1.0, 0.0, 0.0" />  
+<Billboard position=" 9500,9500, 9500" material="Examples/Flare" colour="1.0, 1.0, 0.0" />  
+<Billboard position=" 16700,16700,16700" material="Examples/Flare" colour="0.8, 0.2, 1.0" />  
+
+
+						<!--#########Pickups##########-->
+			
+<PickupSpawner pickup=largedamageboostpickup position="1000,1000,1000" triggerDistance="20" respawnTime="30" maxSpawnedItems="10" />
+<PickupSpawner pickup=crazyhealthpickup position="3500,3500, 3500" triggerDistance="20" respawnTime="30" maxSpawnedItems="10" />
+<PickupSpawner pickup=hugeshieldpickup position="4000,4500, 4500" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+<PickupSpawner pickup=smalljumppickup position="6500,6500, 6000" triggerDistance="20" respawnTime="10" maxSpawnedItems="99" />
+<PickupSpawner pickup=largedamageboostpickup position="9500,9500, 9500" triggerDistance="20" respawnTime="30" maxSpawnedItems="10" />
+<PickupSpawner pickup=largedamageboostpickup position="13000,13000,13000" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+    
+    	    <!--******************************-Mission starts here****************************-->
+    			
+    			
+    	    <!--########################  On screen notifications and distance triggers #############################-->
+    			 
+
+    
+<DistanceTrigger name="flying2" position="0,0,0" target="Pawn" distance=40 stayActive="true" delay=7/>
+    <SimpleNotification message="in order to reach our fleet,">
+        <events>
+            <trigger>
+                <EventListener event="flying2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    
+    
+<DistanceTrigger name="flying2" position="0,0,0" target="Pawn" distance=100 stayActive="true" delay=7/>
+    <SimpleNotification message="read the quest description">
+        <events>
+            <trigger>
+                <EventListener event="flying2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    
+    <DistanceTrigger name="flying1" position="0,0,0" target="Pawn" distance=100 stayActive="true" delay=1/>
+    <SimpleNotification message="Welcome Major Walker">
+        <events>
+            <trigger>
+                <EventListener event="flying1" />
+            </trigger>
+        </events>
+    </SimpleNotification>        
+
+<DistanceTrigger name="flying3" position="500,500,500" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="follow the red dots">
+    <events>
+        <trigger>
+            <EventListener event="flying3" />
+        </trigger>
+    </events>
+</SimpleNotification>        
+
+
+<DistanceTrigger name="flying6" position="1000,1000,1000" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="Major! You can't face the enemy yet">
+    <events>
+        <trigger>
+            <EventListener event="flying6" />
+        </trigger>
+    </events>
+</SimpleNotification>        
+
+<DistanceTrigger name="flying7" position="1060,1060,1060" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="You'll ned to get some upgrades first">
+    <events>
+        <trigger>
+            <EventListener event="flying7" />
+        </trigger>
+    </events>
+</SimpleNotification>      
+
+<DistanceTrigger name="flying8" position="1110,1110,1110" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="You can find them close to the signals">
+    <events>
+        <trigger>
+            <EventListener event="flying8" />
+        </trigger>
+    </events>
+</SimpleNotification>     
+
+<DistanceTrigger name="flying9" position="6500,6500,6000" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="You're almost here!">
+    <events>
+        <trigger>
+            <EventListener event="flying9" />
+        </trigger>
+    </events>
+</SimpleNotification>     
+
+<DistanceTrigger name="flying4" position="9500,9500,9500" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="You're late!">
+    <events>
+        <trigger>
+            <EventListener event="flying4" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+
+<DistanceTrigger name="flying5" position="9550,9550,9550" target="Pawn" distance=50 stayActive="true" delay=1/>
+<SimpleNotification message="The enemy is eager to be beaten">
+    <events>
+        <trigger>
+            <EventListener event="flying5" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<DistanceTrigger name="flying11" position="13000,13000,13000" target="Pawn" distance=200 stayActive="true" delay=1/>
+<SimpleNotification message="There they are. Destroy them!">
+    <events>
+        <trigger>
+            <EventListener event="flying11" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<DistanceTrigger name="flying12" position="13050,13050,13050" target="Pawn" distance=200 stayActive="true" delay=1/>
+<SimpleNotification message="Don't fotget to loot the final boss">
+    <events>
+        <trigger>
+            <EventListener event="flying12" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<SimpleNotification message="Congratulations! You saved humanity!" broadcast="true">
+    <events>
+        <trigger>
+            <EventListener event="endboss" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<DistanceTrigger name="endMissio" position="16700,16700,16700" target="Pawn" distance=50 stayActive="true" delay=1/>
+
+
+
+
+<!--######################## Meteoriten #############################-->
+
+   <?lua
+      for i = 1, 800, 1
+      do
+      j = math.random()
+      x = math.random()
+      y = math.random()
+      z = math.random()
+   ?>
+
+   <MovableEntity    
+      position = "<?lua print(math.random()* 10000) ?>,<?lua print(math.random() * 10000 + 0) ?>,<?lua print(math.random() * 10000) ?>"
+      scale = "<?lua print(j * 40)?>"
+      velocity = "0,0,0"
+      collisionType = dynamic
+      collisiondamage = 0.5
+      enablecollisiondamage = true 
+      active = true
+      visible = true
+   >                 
+          <attached>           
+              <Model mass="<?lua print(j * 1000) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" >
+                  
+              </Model>                          
+          </attached> 
+         <collisionShapes>
+             <SphereCollisionShape radius="<?lua print(j * 50) ?>" />
+         </collisionShapes>   
+   </MovableEntity>
+
+   <?lua
+      end
+   ?>
+      	<!--****************************In the Asteroid Field***************************-->
+ <!--Enemy team-->
+  
+ <!--########################  spaceships within the asteroid field #############################-->
+
+       
+  <SpaceShip position="1900,1500,1500" lookat="2050,0,-1000" name="allied" health="200" maxhealth="200" initialhealth="200" >
+	  <templates>
+            <Template link=spaceshipassff />
+      </templates>
+       <controller>
+          <WaypointPatrolController alertnessradius=300 team=1 >
+				<waypoints>
+	  	  	  	  <Model mesh="cube.mesh" scale=0 position="1000,1500,1500" />
+                  <Model mesh="cube.mesh" scale=0 position="1900,1500,1500" />
+     	  	  	                    
+              </waypoints>
+						
+          </WaypointPatrolController>
+
+       </controller>
+	  
+  </SpaceShip>
+      
+            
+      <SpaceShip position="2900,2500,2500" lookat="2050,0,-1000" name="allied" health="200" maxhealth="200" initialhealth="200" >
+    	  <templates>
+                <Template link=spaceshippirate />
+          </templates>
+           <controller>
+              <WaypointPatrolController alertnessradius=300 team=1 >
+    				<waypoints>
+    	  	  	  	  <Model mesh="cube.mesh" scale=0 position="2000,2500,2500" />
+                      <Model mesh="cube.mesh" scale=0 position="2900,2500,2500" />
+         	  	  	                        
+                  </waypoints>
+    						
+              </WaypointPatrolController>
+
+           </controller>
+    	  
+      </SpaceShip>
+      
+      <SpaceShip position="2020,2400,2500" lookat="2050,0,-1000" name="allied" health="200" maxhealth="200" initialhealth="200" >
+    	  <templates>
+                <Template link=spaceshippirate />
+          </templates>
+           <controller>
+              <WaypointPatrolController alertnessradius=300 team=1 >
+    				<waypoints>
+    	  	  	  	  
+                      <Model mesh="cube.mesh" scale=0 position="2920,2500,2500" />
+         	  	  	  <Model mesh="cube.mesh" scale=0 position="2020,2500,2500" />
+                    
+                  </waypoints>
+    						
+              </WaypointPatrolController>
+
+           </controller>
+    	  
+      </SpaceShip>
+ 
+      <SpaceShip position="3520,3520, 3500" lookat="2050,0,-1000" name="allied" health="150" maxhealth="150" initialhealth="150" >
+         	  <templates>
+                     <Template link=spaceshippirate />
+               </templates>
+                <controller>
+                   <WaypointPatrolController alertnessradius=300 team=1 >
+         				<waypoints>
+         	  	  	  	  
+                           <Model mesh="cube.mesh" scale=0 position="3920,3500,3500" />
+              	  	  	  <Model mesh="cube.mesh" scale=0 position="3020,3500,3500" />
+                         
+                       </waypoints>
+         						
+                   </WaypointPatrolController>
+
+                </controller>
+         	  
+           </SpaceShip>
+      
+        <!--****************************After the Asteroid Field***************************-->
+        
+   <DistanceTrigger name="afterPortal" position="9500,9500, 9500" target="Pawn"  distance=50 stayActive="true" delay=1/>
+      
+    
+<!--Creating player's team OK-->
+        <!--Spaceships team 0 (player:team=0)-->
+
+        
+<!--####################################### allied team  ################################################-->
+
+
+             
+             
+
+             <SpaceShip position="10150,10150,10150" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+           	  <templates>
+                       <Template link=spaceshipassff />
+                 </templates>
+                  <controller>
+                     <WaypointPatrolController alertnessradius=2000 team=0 >
+                         <events>
+                                    <activity>
+                                        <EventListener event="afterPortal" />
+                                     </activity>
+                                </events>
+       					<waypoints>
+      	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15150,15150,15150" />
+
+                         </waypoints>
+       							
+                     </WaypointPatrolController>
+
+                  </controller>
+             </SpaceShip>
+
+      
+      <SpaceShip position="10300,10000,10300" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+                 	  <templates>
+                             <Template link=spaceshipassff />
+                       </templates>
+                        <controller>
+                           <WaypointPatrolController alertnessradius=2000 team=0 >
+                               <events>
+                                          <activity>
+                                              <EventListener event="afterPortal" />
+                                           </activity>
+                                      </events>
+             					<waypoints>
+            	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15300,15300,15300" />
+
+                               </waypoints>
+             							
+                           </WaypointPatrolController>
+
+                        </controller>
+                   </SpaceShip>
+      
+      <SpaceShip position="10450,10000,10300" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+                      	  <templates>
+                                  <Template link=spaceshipassff />
+                            </templates>
+                             <controller>
+                                <WaypointPatrolController alertnessradius=2000 team=0 >
+                                    <events>
+                                               <activity>
+                                                   <EventListener event="afterPortal" />
+                                                </activity>
+                                           </events>
+                  					<waypoints>
+                 	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15450,15000,15300" />
+
+                                    </waypoints>
+                  							
+                                </WaypointPatrolController>
+
+                             </controller>
+                        </SpaceShip>
+      
+      <SpaceShip position="10450,10000,10450" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+                            	  <templates>
+                                        <Template link=spaceshipassff />
+                                  </templates>
+                                   <controller>
+                                      <WaypointPatrolController alertnessradius=2000 team=0 >
+                                          <events>
+                                                     <activity>
+                                                         <EventListener event="afterPortal" />
+                                                      </activity>
+                                                 </events>
+                        					<waypoints>
+                       	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15450,15000,15450" />
+
+                                          </waypoints>
+                        							
+                                      </WaypointPatrolController>
+
+                                   </controller>
+                              </SpaceShip>
+      
+      
+      <SpaceShip position="10300,10000,9850" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+                                	  <templates>
+                                            <Template link=spaceshipassff />
+                                      </templates>
+                                       <controller>
+                                          <WaypointPatrolController alertnessradius=2000 team=0 >
+                                              <events>
+                                                         <activity>
+                                                             <EventListener event="afterPortal" />
+                                                          </activity>
+                                                     </events>
+                            					<waypoints>
+                           	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="17300,17000,17850" />
+
+                                              </waypoints>
+                            							
+                                          </WaypointPatrolController>
+
+                                       </controller>
+                                  </SpaceShip>
+      
+      <SpaceShip position="10150,10000,9700" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+                                      	  <templates>
+                                                  <Template link=spaceshipassff />
+                                            </templates>
+                                             <controller>
+                                                <WaypointPatrolController alertnessradius=2000 team=0 >
+                                                    <events>
+                                                               <activity>
+                                                                   <EventListener event="afterPortal" />
+                                                                </activity>
+                                                           </events>
+                                  					<waypoints>
+                                 	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="17150,17000,17700" />
+
+                                                    </waypoints>
+                                  							
+                                                </WaypointPatrolController>
+
+                                             </controller>
+                                        </SpaceShip>
+      
+      <SpaceShip position="10300,10000,9700" lookat="2050,0,-1000" name="allied" health="800" maxhealth="800" initialhealth="800" >
+                                      	  <templates>
+                                                  <Template link=spaceshipassff />
+                                            </templates>
+                                             <controller>
+                                                <WaypointPatrolController alertnessradius=2000 team=0 >
+                                                    <events>
+                                                               <activity>
+                                                                   <EventListener event="afterPortal" />
+                                                                </activity>
+                                                           </events>
+                                  					<waypoints>
+                                 	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="17300,17000,17700" />
+
+                                                    </waypoints>
+                                  							
+                                                </WaypointPatrolController>
+
+                                             </controller>
+                                        </SpaceShip>
+      
+<!--Creating player's team END  -->
+
+<!--#########################################Creating enemy team END #################################  -->
+        
+
+<SpaceShip position="15500,15500,15500" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                	  <templates>
+                                            <Template link=spaceshipghost />
+                                      </templates>
+                                       <controller>
+                                          <WaypointPatrolController alertnessradius=2000 team=1 >
+                                             <waypoints>
+                           	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15500,15500,15500" />
+
+                                              </waypoints>
+                            							
+                                          </WaypointPatrolController>
+
+                                       </controller>
+                                  </SpaceShip>
+      
+      
+      <SpaceShip position="15750,15500,15750" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                          	  <templates>
+                                                      <Template link=spaceshipghost />
+                                                </templates>
+                                                 <controller>
+          	  	  	  	  	  	  	  	  	  	  	  <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                       <waypoints>
+                                     	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15750,15500,15750" />
+
+                                                        </waypoints>
+                                      							
+                                                    </WaypointPatrolController>
+
+                                                 </controller>
+                                            </SpaceShip>
+      <SpaceShip position="16000,15500,16000" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                               	  <templates>
+                                                   <Template link=spaceshipghost />
+                                                     </templates>
+                                                      <controller>
+               	  	  	  	  	  	  	  	  	  	  	  <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                            <waypoints>
+                                          	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="16000,15500,16000" />
+
+                                                             </waypoints>
+                                           							
+                                                         </WaypointPatrolController>
+                                                           
+
+                                                      </controller>
+                                                 </SpaceShip>
+               
+               
+               
+               <SpaceShip position="15250,15500,15250" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                               	  <templates>
+                                                    <Template link=spaceshipghost />
+                                                     </templates>
+                                                      <controller>
+                                                         <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                            <waypoints>
+                                          	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15250,15500,15250" />
+
+                                                             </waypoints>
+                                           							
+                                                         </WaypointPatrolController>
+
+                                                      </controller>
+                                                 </SpaceShip>
+               
+               
+               
+               <SpaceShip position="15000,15500,15000" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                               	  <templates>
+                                                   <Template link=spaceshipghost />
+                                                     </templates>
+                                                      <controller>
+                                                         <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                            <waypoints>
+                                          	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15000,15500,15000" />
+
+                                                             </waypoints>
+                                           							
+                                                         </WaypointPatrolController>
+
+                                                      </controller>
+                                                 </SpaceShip>
+               
+               
+               
+               <SpaceShip position="15500,15500,15750" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                               	  <templates>
+                                                   <Template link=spaceshipghost />
+                                                     </templates>
+                                                      <controller>
+               	  	  	  	  	  	  	  	  	  	  	 <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                            <waypoints>
+                                          	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="15500,15500,15750" />
+
+                                                             </waypoints>
+                                           							
+                                                         </WaypointPatrolController>
+
+                                                      </controller>
+                                                 </SpaceShip>
+
+      <SpaceShip position="16000,15500,16250" lookat="2050,0,-1000" name="enemy" health="200" maxhealth="200" initialhealth="200" >
+                                                  	  <templates>
+                                                      <Template link=spaceshipghost />
+                                                        </templates>
+                                                         <controller>
+                  	  	  	  	  	  	  	  	  	  	  	 <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                               <waypoints>
+                                             	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="16000,15500,16250" />
+
+                                                                </waypoints>
+                                              							
+                                                            </WaypointPatrolController>
+
+                                                         </controller>
+                                                    </SpaceShip>
+      
+      <SpaceShip position="16500,16500,16500" lookat="2050,0,-1000" name="endboss" health="800" maxhealth="800" initialhealth="800" >
+                                                              	  <templates>
+                                                                  <Template link=spaceshipTransporter />
+                                                                    </templates>
+                                                                     <controller>
+      	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  <WaypointPatrolController alertnessradius=2000 team=1 >
+                                                                           <waypoints>
+                                                         	  	  	  	  	  <Model mesh="cube.mesh" scale=0 position="16500,16500,16500" />
+
+                                                                            </waypoints>
+                                                          							
+                                                                        </WaypointPatrolController>
+
+                                                                     </controller>
+                                                                </SpaceShip>
+      
+      <!-- ##################### End the Mission (success) ##########################################-->
+     
+
+      
+      
+      <Script code="Mission endMission true" onLoad="false">
+          <events>
+              <trigger>
+                  <EventListener event="endMissio" />
+              </trigger>
+          </events>
+      </Script> 
+         
+      <!--########################  Quests #############################-->
+
+
+ <QuestEffectBeacon times=1>
+            <effects>
+                <AddQuest questId="quest0" />
+                   <AddQuestHint hintId ="quest1hint2" />
+                <AddQuestHint hintId ="quest1hint3" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=spawntrigger />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+    
+    
+
+<Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+<GlobalQuest id="quest0">
+		<QuestDescription title="Mission" description="Humanity is at war! Recently, an ashrocian ship attacked two transporters carrying highly expensive ETHium. Despite the fact, that the Ashrocs are a technological superpower, we, the human race cannot allow them to treat us like insects. Your mission's to group up with yout fellow soldiers and retaliate even harder. Follow the red marks which were left by the star fleet. But beware, there might be spies on your way. See to it, that you terminate their mission ;)" />
+	<hints>
+                <QuestHint id="quest1hint0">
+                    <QuestDescription title="The super Hint." description="Be proud of yourself." />
+                </QuestHint>
+    </hints>             
+</GlobalQuest>
+		
+		
+		
+	<DistanceTrigger name=QuestTrigger0 position="0,0,0" distance=10 target="Pawn" />
+
+
+
+ <QuestEffectBeacon times=1>
+            <effects>
+                <AddQuest questId="quest0" />
+                   <AddQuestHint hintId ="quest1hint2" />
+                <AddQuestHint hintId ="quest1hint3" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=QuestTrigger0 />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+    
+
+
+
+
+
+    
+    
+	
+    
+   
+    
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/ArrowLevel.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/ArrowLevel.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/ArrowLevel.oxw	(revision 11817)
@@ -0,0 +1,79 @@
+<LevelInfo
+ name = "ArrowLevel"
+ description = "A level to show the funtionality of the Waypoint Arrow."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/HeavyCruiser.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipEscort.oxt")
+  include("templates/endurancetest_template.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipAssff.oxt")
+
+
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=3.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+   <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/Starbox"
+  >
+
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+    
+    <SpawnPoint position="50,0,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+
+    
+    
+    <Arrow>
+      <attached>
+       <Model scale="10" mesh="Arrow.mesh"/>
+      </attached>
+      <controller>
+        <ArrowController accuracy = 2000>
+          <gpspoints>
+            <Model mesh="cube.mesh" scale=8 position="100,100,100"/>
+            <Model mesh="cube.mesh" scale=8 position="400,200,187"/>
+            <Model mesh="cube.mesh" scale=8 position="-200,-500,615"/>
+            <Model mesh="cube.mesh" scale=8 position="0,0,0"/>      
+          </gpspoints>
+        </ArrowController>
+      </controller>
+    </Arrow>
+
+
+
+
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/AsteroidFarming.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/AsteroidFarming.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/AsteroidFarming.oxw	(revision 11817)
@@ -0,0 +1,142 @@
+<LevelInfo
+ name = "AsteroidFarming"
+ description = "Testing the Asteroid Mining Project, PPS HS 17"
+ tags = "test, showcase"
+ screenshot = "asteroids.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+
+<WorldAmbientSound source="Asteroid_rocks.ogg" looping="true" playOnLoad="true" />
+
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+    hasPhysics = true
+  >
+
+
+  <?lua
+      include("includes/pickups.oxi")
+  ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <SpawnPoint team=0 position="0,0,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    
+
+     <!-- Asteroid Display: -->
+      <Model position="0,  0,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast1.mesh" />
+      <Model position="0, 20,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast2.mesh" />
+      <Model position="0, 40,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast3.mesh" />
+      <Model position="0, 60,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast4.mesh" />
+      <Model position="0,-20,40" yaw="90" pitch="-90" roll="0" scale="4" mesh="ast5.mesh" />
+      <Model position="0,-40,40" yaw="90" pitch="-90" roll="0" scale="4" mesh="ast6.mesh" />
+      <Model position="0,-60,40" yaw="90" pitch="-90" roll="0" scale="5" mesh="asteroid_ice.mesh" />
+      <Model position="0,-80,40" yaw="90" pitch="-90" roll="0" scale="5" mesh="asteroid_UV.mesh" />
+
+     <!-- Display some pickup, 'Meta' -->
+    <PickupSpawner pickup=usemetapickup position="-25,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=dropmetapickup position="0,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=destroymetapickup position="25,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=destroycarriermetapickup position="50,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- Drone pickup -->
+    <PickupSpawner pickup=dronepickup position="-25,100,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+
+    <!-- @Objects: 4 boxes (uncontrolled pawns) Trying to understand the pickup generation-->
+    <Pawn team=1 health=30 position="0,100,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box RVName = "Box 4" >
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+
+    </Pawn>
+
+    <!----Just a box with different mesh-->
+    <Pawn team=1 health=50 position="0,1000,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box RVName = "Globi Asteroid" >
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="ast4.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+
+
+    <!-- AsteroidMinable -->
+    <AsteroidMinable size=15 position="0,-500,0" />
+    <AsteroidMinable size=5 position="100,-500,100" />
+    <AsteroidMinable size=50 position="500,-500, 500" />
+    <AsteroidMinable size=30 position="-100, -500, -100" velocity= "0, -30, 0"/>
+
+    <!-- SpicedAsteroidField -->
+    <SpicedAsteroidField count=30 mDensity= 0.5 maxSize=40 minSize=1 position="5000, 0, 0" radius=1000 velocity="0,0,0"/>
+
+
+    <!-- Asteroid Belt with a planet -->
+
+    <SpicedAsteroidBelt position="-15000,0,0" mDensity=0.3 segments=50 minSize=1 maxSize=50 radius0=7190 radius1 = 7800 count=250 tiltBy=0.5 tiltAt=0/>
+    <Planet
+      position="-15000,0,0"
+      scale="5000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >      
+      <attached>
+        <ForceField position="5000,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+
+
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/Asteroids2D.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/Asteroids2D.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/Asteroids2D.oxw	(revision 11817)
@@ -0,0 +1,82 @@
+<LevelInfo
+ name = "Asteroids2D"
+ description = "Try to prevent asteroids from colliding into your spaceship. Be prepared to dodge all asteroids or destroy them."
+ tags = "minigame"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipAsteroids2D.oxt")
+  include("templates/enemyInvader.oxt")
+  include("overlays/Asteroids2DHUD.oxo")
+  include("templates/asteroidsAsteroids2D.oxt")
+?>
+
+<Level
+  plugins = asteroids2D
+  gametype = Asteroids2D
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "1.0, 1.0, 1.0"
+    skybox       = "Orxonox/Starbox"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+  >
+
+  <WorldAmbientSound
+    source="Earth.ogg"
+    looping="true"
+    playOnLoad="true"
+  />
+
+    <!-- <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/> -->
+    <Light type=directional position="-100, 10000, -700" lookat="0.2, -1, 0" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint team=0 position="0,0,0" lookat="0,0,0" spawnclass= Asteroids2DShip pawndesign=spaceshipasteroids2d />
+
+    <!--<Model mesh="axes.mesh" scale=10 position="0,0,0" /> -->
+
+
+    <!--<?lua
+      for i = 1, 250, 1
+      do
+      j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(math.random()* 15000 - 1000) ?>,<?lua print(math.random() * 12000 - 4000) ?>,<?lua print(math.random() * 12000 - 4000) ?>"
+      collisionType = dynamic
+      linearDamping = 0.8
+      angularDamping = 0
+      scale = "<?lua print(j * 150)?>"
+      collisiondamage = 1
+      enablecollisiondamage = true
+    >
+      <attached>
+        <Model mass="<?lua print(j * 1000) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 350) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+
+    <?lua
+      end
+    ?>-->
+
+    <Asteroids2DCenterPoint name=asteroids2Dcenter />
+  
+    
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/DialogShowcase.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/DialogShowcase.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/DialogShowcase.oxw	(revision 11817)
@@ -0,0 +1,131 @@
+<LevelInfo
+ name = "DialogShowase"
+ description = "A level to show and test the functionality of the Dialog module."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/HeavyCruiser.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipEscort.oxt")
+  include("templates/endurancetest_template.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+  
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+ <DistanceTrigger name="test" position="100,0,100" target="Pawn" distance=25 stayActive="true" />
+ <Backlight position="100,0,100" visible=true frequency=0.6 amplitude=3 material="Flares/lensflare" colour="1,0,1"/>
+    
+    <Dialog name="Kurt" currentQuestionId="loop1">
+      <questions>
+        <Question Id="loop1" question="Wanna be looped?" >
+          <answerIds>
+            <AnswerId Id="yes"/>
+            <AnswerId Id="no"/>
+            <AnswerId Id="giveItToMe"/>
+          </answerIds>
+        </Question>
+        <Question Id="lorem" question="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." >
+          <answerIds>
+            <AnswerId Id="endIt"/>
+          </answerIds>
+        </Question>
+        <Question Id="loop2" question="Wanna be looped again?" >
+          <answerIds>
+            <AnswerId Id="yes"/>
+            <AnswerId Id="no"/>
+            <AnswerId Id="endIt"/>
+          </answerIds>
+        </Question>
+        <Question  Id="ok" question="Guess not then"/>
+      </questions>
+      <answers>
+        <Answer Id="giveItToMe" answer="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." nextQuestionId="lorem"/>
+        <Answer Id="yes" answer="yeah loop me" nextQuestionId="loop2"/>
+        <Answer Id="no" answer="i'd rather not" nextQuestionId="ok"/>
+        <Answer Id="endIt" answer="i will go now..." nextQuestionId="end"/>
+      </answers>
+      <events>
+        <execute>
+          <EventListener event="test"/>
+        </execute>
+      </events>
+    </Dialog>
+    
+
+
+
+  <DistanceTrigger name="troll" position="100,0,200" target="Pawn" distance=25 stayActive="true" />
+  <Backlight position="100,0,200" visible=true frequency=0.3 amplitude=3 material="Flares/lensflare" colour="1,0,1"/>
+  
+    <Dialog name="Rick" currentQuestionId="start">
+      <questions>
+        <Question Id= "start" question= "hey can you predect what i will do next?"> 
+          <answerIds>
+            <AnswerId Id="NeverGonnaGiveMeUp" />
+            <AnswerId Id="DontCare"/>
+            <AnswerId Id="Serious" />
+          </answerIds>
+        </Question>
+        
+        <Question Id= "WeAreNoStrangers" question= "We're no strangers to love. You know the rules and so do I. A full commitment's what I'm thinking of,
+You wouldn't get this from any other guy.">
+          <answerIds>
+            <AnswerId Id="whatIamFeeling"/>
+            <AnswerId Id="DontCare"/>
+            <AnswerId Id="IGoNow"/>
+          </answerIds>
+        </Question>
+        
+        <Question Id= "NeverGonnaLetYouDown" question= "Never gonna give you up
+Never gonna let you down
+Never gonna run around and desert you
+Never gonna make you cry
+Never gonna say goodbye
+Never gonna tell a lie and hurt you" >
+          <answerIds>
+            <AnswerId Id="Again"/>
+            <AnswerId Id="IGoNow"/>
+          </answerIds>
+        </Question>
+
+        <Question Id= "leave" question= "That was not what i had in mind but that is way better, thanks for the advidce. I will leave now."/>
+
+      </questions>
+    
+      <answers>
+        <Answer Id= "NeverGonnaGiveMeUp" nextQuestionId ="WeAreNoStrangers" answer= "wait are you the RICK?!" />
+        <Answer Id= "DontCare" nextQuestionId ="end" answer= "I could not care less" />
+        <Answer Id= "Serious" nextQuestionId ="leave" answer= "The same thing you do every night? - try to take over the world?" />
+        <Answer Id= "whatIamFeeling" nextQuestionId ="NeverGonnaLetYouDown" answer= "I just wanna tell you how I'm feeling, gotta make you understand" />
+        <Answer Id= "IGoNow" nextQuestionId ="" answer= "well that strange i guess i go now..." />
+        <Answer Id= "Again" nextQuestionId ="WeAreNoStrangers" answer= "I didn't quiet get it." />
+      </answers>
+
+      <events>
+          <execute>
+              <EventListener event="troll"/>
+          </execute>
+      </events>
+    </Dialog>
+    
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+    
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/DodgeRace.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/DodgeRace.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/DodgeRace.oxw	(revision 11817)
@@ -0,0 +1,70 @@
+<LevelInfo
+ name = "Dodge Race"
+ description = "Try to come as far as possible"
+ tags = "minigame"
+ screenshot = "DodgeRace.png"
+/>
+<?lua
+  include("stats.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipDodgeRace.oxt")
+  include("templates/enemyInvader.oxt")
+  include("templates/DodgeRacePattern.oxt")
+  include("overlays/DodgeRaceHUD.oxo")
+?>
+
+<Level
+  plugins = dodgerace
+  gametype = DodgeRace
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "1.0, 1.0, 1.0"
+    skybox       = "Orxonox/skyBoxClouds"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+  >
+
+  <WorldAmbientSound
+    source="Earth.ogg"
+    looping="true"
+    playOnLoad="true"
+  />
+
+    <!-- <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/> -->
+    <Light type=directional position="-100, 10000, -700" lookat="0.2, -1, 0" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=DodgeRaceShip pawndesign=spaceshipdodgerace />
+
+    <DistanceTrigger name="start" position="-200,0,0" target="Pawn" distance=10 stayActive="true" delay=0 />
+
+
+    <DodgeRaceCenterPoint name=invadercenter />
+  
+  <StaticEntity position="0,-50,0" direction="0,0,0"   scale="1" collisionType=static mass=1 friction=0.01 >
+      <attached>
+        <Model position="0,0,0" mesh="plane.mesh" scale3D="100000,0,100000" />
+      </attached>
+
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="1,1,1" />
+      </collisionShapes>
+
+  </StaticEntity>
+    
+    
+    
+    
+    
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/Endurancefinal.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/Endurancefinal.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/Endurancefinal.oxw	(revision 11817)
@@ -0,0 +1,42 @@
+<LevelInfo
+ name = "Endurancefinal"
+ description = "Endurance Bigship."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/HeavyCruiser.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipEscort.oxt")
+  include("templates/endurancetest_template.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+    <ModularSpaceShip velocity= "20,0,0" position="0,0,200" lookat= "0,0,0" health="1000" maxhealth="1000" initialhealth="1000">
+      <templates>
+        <Template link=endurance />
+      </templates>
+    </ModularSpaceShip>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/FPSTest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/FPSTest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/FPSTest.oxw	(revision 11817)
@@ -0,0 +1,72 @@
+<!-- -->
+<LevelInfo
+ name = "FPS testlevel"
+ description = "Level to test First Person Shooter"
+ tags = "test"
+ screenshot = "fpstestlevel.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/FPS.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.1, 0.1, 0.1"
+   skybox       = "Orxonox/skyBoxBasic"
+   gravity      = "0,-1000,0"
+   negativeWorldRange = "-100000, -100000, -100000"
+   positiveWorldRange = " 100000,  100000,  100000"
+   hasPhysics   = true
+  >
+    <Light type=directional position="0,-100000,0" direction="0.02, -1, 0.05" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+  <StaticEntity position="0,-10000,0" direction="0,-1,0" collisionType=static mass=100000 friction=0.01 >
+      <attached>
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="10000,10000,1000" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="10000,10000,1000" />
+      </collisionShapes>
+  </StaticEntity>
+
+<?lua
+for i = 1, 10, 1
+do ?>
+    <SpawnPoint position="<?lua print(math.random() * 1000 - 500) ?>,100,<?lua print(math.random() * 1000 - 500) ?>" direction="-1, 0, 0" lookat="0,0,0" spawnclass=FpsPlayer pawndesign=fps />
+<?lua
+end
+?>
+
+
+<?lua
+for i = 1, 200, 1
+do
+j = math.random()
+?>
+  <MovableEntity position="<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000 - 2000) ?>" collisionType=dynamic linearDamping=0.8 angularDamping=0 mass=<?lua print(j * 100) ?> scale=<?lua print(j * 5) ?> rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>" >
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 100) ?>" />
+      </collisionShapes>
+  </MovableEntity>
+<?lua
+end
+?>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/FPS_Level_HS14.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/FPS_Level_HS14.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/FPS_Level_HS14.oxw	(revision 11817)
@@ -0,0 +1,349 @@
+<!--FPS mode level
+	autor: Florian Süess-->
+<LevelInfo
+ name = "FPS Level HS14"
+ description = "Entering a Space Station & finde a way through it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/bigship.oxt")
+  include("templates/spaceshipTurret.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+  include("templates/FPS.oxt")
+  include("templates/HeavyCruiser.oxt")
+  include("templates/spacestation_elements.oxt")
+?>
+
+<Level
+  gametype = Deathmatch
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+    gravity      = "0,0,0"
+    hasPhysics   = true
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+	
+	<!-- my ships -->
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0,1.0,1.0,0.5" specular="1.0, 0.9, 0.9, 1.0"/>
+    
+    <SpawnPoint team=1 position="6000,2000,500" lookat="4000,-1000,-1000" spawnclass=SpaceShip pawndesign=spaceshipescort />
+	<!--Position normal Level: "6000,2000,500"; postion for work at the spacesation: "3000,0,0 "-->
+	
+	<!--1,200,0-->
+	<SpaceShip			
+        template            = "spaceshipassff"
+        team                = "1"
+        position            = "3337,-19,-320"
+        orientation         = "5800,-200,-1200,0"
+        health              = "200"
+        initialhealth       = "200"
+        maxhealth           = "200"
+        shieldhealth        = "50"
+        initialshieldhealth = "50"
+        maxshieldhealth     = "50"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "100"
+        shieldrechargewaittime = "0.1"
+        name                = "Tanis1"
+        radarname           = "Light Destroyer" >
+		<attached>
+        	<DockingTarget name="spaceShip" />
+        	<DistanceTriggerBeacon name="bcnSpaceShip" />
+		</attached>
+    </SpaceShip>
+	
+	
+        
+    <StaticEntity position  = "2800,0,0" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </StaticEntity>
+
+
+	<!-- Docking I -->
+	    <Dock position="2830,20,50" roll=0 yaw=0 >
+	        <animations>
+	            <MoveToDockingTarget target="fistperson" />
+	        </animations>
+	        <effects>
+	            <DockToShip target="fistperson" />
+	        </effects>
+	        <events>
+	            <execute>
+	                <EventListener event="dockMe" />
+	            </execute>
+
+		    <undocking>
+			<EventListener event="undockMe" />
+		    </undocking>
+		
+	        </events>
+	        <attached>
+		<!-- Trigger for docking with billboard -->
+	            <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+	            <DistanceTrigger position="0,0,0" distance="200" target="Pawn"
+	                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"
+	            />
+		<!-- Trigger for undocking with billboard -2800,-20055,-700-->
+		    <Billboard position="-1500,-20021,-50" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+		    <DistanceTrigger position="-1500,-20021,-50" distance="150" target="Pawn"
+	                beaconMode="identify" targetname="bcnDestroyer" name="undockMe"
+	            />
+	        </attached>
+
+	    </Dock>
+	    
+	<!-- FPS Player as destination of the dock -->
+	<!-- My position after docking -->
+	    <FpsPlayer template = "fps" radarname = "First Person Player" position = "1330,-20016,0" >
+	      <attached>
+	        <DistanceTriggerBeacon name="bcnDestroyer" />
+	        <DockingTarget name="fistperson" />
+	      </attached>
+	    </FpsPlayer>
+
+
+
+
+	<!-- Docking  II -->
+	    <Dock position="86,-20005,-700" roll=0 yaw=0 >
+	        <animations>
+	            <MoveToDockingTarget target="spaceShip" />
+	        </animations>
+	        <effects>
+	            <DockToShip target="spaceShip" />
+	        </effects>
+	        <events>
+	            <execute>
+	                <EventListener event="dockMe" />
+	            </execute>
+
+		    <undocking>
+				<EventListener event="undockMe" />
+		    </undocking>
+		
+	        </events>
+	        <attached>
+		<!-- Trigger for docking with billboard -->
+	            <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.3,0.4,0.5" scale=1 />
+	            <DistanceTrigger position="0,0,0" distance="100" target="Pawn"
+	                beaconMode="exclude" targetname="bcnSpaceShip" name="dockMe"
+	            />
+		<!-- Trigger for undocking with billboard -->
+		    <Billboard position="3251,20006,380" material="Flares/ringflare2" colour="0.3,0.4,0.5" scale=1 />
+		    <DistanceTrigger position="3251,20006,380" distance="100" target="Pawn"
+	                beaconMode="identify" targetname="bcnSpaceShip" name="undockMe"
+	            />
+	        </attached>	
+	 </Dock>
+	
+
+
+ <!-- Enemy ships -->
+ 
+ 	<SpaceShip			
+        template            = "HeavyCruiser"
+        team                = "0"
+        position            = "5800,-200,-1200"
+        orientation         = "1,200,0,0"
+        health              = "2000"
+        initialhealth       = "2000"
+        maxhealth           = "2000"
+        shieldhealth        = "200"
+        initialshieldhealth = "200"
+        maxshieldhealth     = "200"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "1"
+        shieldrechargewaittime = "1"
+        name                = "Tanis0"
+        radarname           = "Tanis big ship" >
+   </SpaceShip>
+		-->
+    
+	<SpaceShip			
+        template            = "spaceshippirate"
+        team                = "0"
+        position            = "11000,0,-2500"
+        orientation         = "1,200,0,0"
+        health              = "200"
+        initialhealth       = "200"
+        maxhealth           = "200"
+        shieldhealth        = "50"
+        initialshieldhealth = "50"
+        maxshieldhealth     = "50"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "1"
+        shieldrechargewaittime = "1"
+        name                = "Tanis0"
+        radarname           = "Pirate1" >
+        
+        <controller>
+            <AIController team=0/>           
+        </controller>
+        
+   </SpaceShip>
+   
+   <SpaceShip			
+        template            = "spaceshippirate"
+        team                = "0"
+        position            = "11000,0,-2500"
+        orientation         = "1,200,0,0"
+        health              = "200"
+        initialhealth       = "200"
+        maxhealth           = "200"
+        shieldhealth        = "50"
+        initialshieldhealth = "50"
+        maxshieldhealth     = "50"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "1"
+        shieldrechargewaittime = "1"
+        name                = "Tanis0"
+        radarname           = "Pirate2" >
+        
+        <controller>
+            <AIController team=0/>           
+        </controller>
+        
+   </SpaceShip>
+	
+
+<!-- SpaceStation
+
+The station can either be hidden outside of the skybox, within the hull of the space station if it is big enough or within a planet.
+Complex spacestations can be placed very far away from the spaceship so it is rendered at low resolution while the player uses the space ship.
+
+-->
+
+<!-- Hilfsobjekte fuer Koordinatensystem -->
+
+<!-- The axis from the coordinatesystem are "red,green,yellow" and the orange boxe shows the negative direction.
+	 But atention, each element is different! A few of them are already rotatet with yaw, roll and pitch:
+	 -> "pitch" is a rotation around "red" in the "yellow, green" plain.
+	 -> "yaw" is a rotation around "green" in the "red, yellow" plain.
+	 -> "roll" is a rotation around "yellow" in the "green,red" plain.
+	 this chanches their negativ/positiv direction of the axis.
+	 -->
+			
+
+<!--<Model position="0,0,0" mesh="cube_red.mesh" scale3D="10000,10,10" />
+<Model position="0,0,0" mesh="cube_green.mesh" scale3D="10,10000,10" />
+<Model position="0,0,0" mesh="cube.mesh" scale3D="10,10,10000" />
+
+<Model position="0,-100,0" mesh="cube_orange.mesh" scale3D="15,15,15" />
+<Model position="-100,0,0" mesh="cube_orange.mesh" scale3D="15,15,15" />
+<Model position="0,0,-100" mesh="cube_orange.mesh" scale3D="15,15,15" />
+
+<Model position="0,-20000,0" mesh="cube_red.mesh" scale3D="100,10,10" />
+<Model position="0,-20000,0" mesh="cube_green.mesh" scale3D="10,100,10" />
+<Model position="0,-20000,0" mesh="cube.mesh" scale3D="10,10,100" />
+
+<Model position="0,-20100,0" mesh="cube_orange.mesh" scale3D="15,15,15" />
+<Model position="-100,-20000,0" mesh="cube_orange.mesh" scale3D="15,15,15" />
+<Model position="0,-20000,-100" mesh="cube_orange.mesh" scale3D="15,15,15" /> -->
+
+
+<!-- Spacestation elements merged -->
+<StaticEntity position="0,-20000,0" direction="0,-1,0" collisionType=static mass=100000 friction=0.01 pitch=-90> 
+     
+ <attached>
+
+	<Model template	= "ss_flag_room" position="750,-16,0"	yaw=180 />
+	
+	<Model template	= "ss_machine"	 position="1545,190,370"	yaw=32 	pitch=180 />
+	<Model template	= "ss_flag_aean" position="1330,16,0"		pitch=180 />
+	<Model template	= "ss_chair" 	 position="1700,145,0" />
+	
+	<Model template	= "ss_tube"	 	 position="500,0,0" />
+	<Model template	= "ss_table" 	 position="650,100,0" />
+	<Model template	= "ss_cylinder"	 position="0,75,0" />
+	
+	<Model template	= "ss_curve" 	 position="-200,0,0" 	yaw=180 />
+	<Model template	= "ss_tube_x" 	 position="-10,0,700" />
+	 
+	<Model template	= "ss_curve" 	 position="-905,0,700" 	yaw=180 />
+	<Model template	= "ss_curve" 	 position="-810,0,1500" yaw=270/>
+	<Model template	= "ss_curve" 	 position="-10,0,1405" 	yaw=0 />
+	 
+	<Model template	= "ss_wall"  		  	yaw=0	position="250,20,700" />
+	<Model template	= "ss_table_cracked" 	yaw=0	position="-110,100,700" />
+
+		
+ </attached>
+</StaticEntity>
+	
+   
+<!-- Homogenous gravitationfield to simulate local gravity (activating the normal gravity will affect the spaceship terribly) -->
+<ForceField position="0,-20200,0" mode="homogen" diameter="5000" forcedirection = "0,-500,0" />
+
+
+
+
+
+<!-- Some more stuff -->
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, -19900, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, -19900, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, -19900, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+    <Model position="0,-19900,0" mesh="planets/ganymede.mesh" scale="5000" />
+    
+    
+
+  </Scene>
+
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/FlappyOrx.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/FlappyOrx.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/FlappyOrx.oxw	(revision 11817)
@@ -0,0 +1,65 @@
+<LevelInfo
+ name = "Flappy Orx"
+ description = "A clone of the iconic Flappy Bird"
+ tags = "minigame"
+ screenshot = "FlappyOrx.png"
+/>
+
+<?lua
+  include("templates/lodInformation.oxt")
+  include("templates/spaceshipFlappyOrx.oxt")
+  include("overlays/FlappyOrxHUD.oxo")
+
+?>
+
+<Level
+  plugins = flappyorx
+  gametype = FlappyOrx
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <Scene
+    ambientlight = "0.8, 0.7, 0.4"
+    skybox     = "Orxonox/skyBoxBasic"
+  >
+  <WorldAmbientSound
+    source="Earth.ogg"
+    looping="true"
+    playOnLoad="true"
+  />
+
+ <Light type=directional position="11000, 11000, -7000" lookat="0, 0, 0" diffuse="1, 1, 1, 1" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint team=0 position="0,0,0" lookat="0,0,0" spawnclass=FlappyOrxShip pawndesign=spaceshipFlappyOrx />
+  
+    <?lua
+      for i = 1, 5, 1 do
+        for j = 3, 12,3 do
+    ?>
+
+        <Template name=Asteroid<?lua print(j) ?>_<?lua print(i) ?>>
+          <MovableEntity
+            collisionType = dynamic
+            linearDamping = 0.8
+            angularDamping = 1
+            scale = "<?lua print(j) ?>"
+            collisiondamage = 10000
+            enablecollisiondamage = true
+          >
+          
+            <attached>
+              <Model mass="1000" mesh="ast<?lua print(i) ?>.mesh" />
+            </attached>
+            <collisionShapes>
+               <SphereCollisionShape radius="<?lua print(j + 8) ?>" />
+            </collisionShapes>
+          </MovableEntity>
+        </Template>
+
+    <?lua
+        end
+      end
+    ?>
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/HeavyCruiser.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/HeavyCruiser.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/HeavyCruiser.oxw	(revision 11817)
@@ -0,0 +1,926 @@
+<LevelInfo
+ name = "Heavy Cruiser Demo"
+ description = "Demonstration of the Heavy Cruiser."
+ tags = "test"
+ screenshot = "HeavyCruiser_level.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipTurret.oxt")
+  include("templates/HeavyCruiser.oxt")
+  include("templates/HeavyCruiserBody.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+<!-- HeavyCruiser and all its parts in one static entity -->
+    <!--StaticEntity position="-300,0,-2000" direction="0,0,0" yaw="180" collisionType=static mass=100000 friction=0.01 >
+    <attached>
+            <Model mesh="HeavyCruiser_body.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_frontR.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_frontL.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_partL.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_partR.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_sidearmL.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_sidearmLfront.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_sidearmR.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            <Model mesh="HeavyCruiser_sidearmRfront.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            
+            <BlinkingBillboard position="75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+            <BlinkingBillboard position="-75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+            <BlinkingBillboard position="74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+            <BlinkingBillboard position="-74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+            <BlinkingBillboard position="73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+            <BlinkingBillboard position="-73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+
+            <BlinkingBillboard position="67,-5,-240" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <BlinkingBillboard position="-67,-5,-240" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+            <BlinkingBillboard position="72,51,-380" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+            <BlinkingBillboard position="-72,51,-380" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+
+            <BlinkingBillboard position="95,-15,483" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+            <BlinkingBillboard position="-95,-15,483" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <BlinkingBillboard position="74,103,524" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <BlinkingBillboard position="-74,103,524" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="80,33,-320" halfExtents="7,11,54" info="frontR"/>
+        <BoxCollisionShape position="79,31,-399" halfExtents="3,6,26" info="frontR"/>
+
+
+        <BoxCollisionShape position="-80,33,-320" halfExtents="7,11,54" info="frontL"/>
+        <BoxCollisionShape position="-79,31,-399" halfExtents="3,6,26" info="frontL"/>
+
+
+        <BoxCollisionShape position="94,33,-179" halfExtents="11,13,45" info="partR"/>
+        <BoxCollisionShape position="96,33,-230" halfExtents="13,17,22" info="partR"/>
+
+
+        <BoxCollisionShape position="-94,33,-179" halfExtents="11,13,45" info="partL"/>
+        <BoxCollisionShape position="-96,33,-230" halfExtents="13,17,22" info="partL"/>
+
+
+        <BoxCollisionShape position="109,47,87" halfExtents="29,8,26" info="sidearmR, upper connection"/>
+        <BoxCollisionShape position="99,-1,79" roll="-15" halfExtents="40,4,9" info="sidearmR, lower connection"/>
+        <BoxCollisionShape position="151,47,115" roll="-15" halfExtents="16,2,105" info="sidearmR, frontTop"/>
+        <BoxCollisionShape position="136,-7,115" roll="-15" halfExtents="16,2,105" info="sidearmR, frontBottom"/>
+        <BoxCollisionShape position="127,26,115" roll="-15" halfExtents="2,28,105" info="sidearmR, frontInner"/>
+        <BoxCollisionShape position="161,16,115" roll="-15" halfExtents="2,28,105" info="sidearmR, frontOuter"/>
+        <BoxCollisionShape position="145,21,12" roll="-15" halfExtents="16,28,2" info="sidearmR, front"/>
+        <BoxCollisionShape position="140,12,261" roll="-15" halfExtents="22,41,43" info="sidearmR, back"/>
+        <BoxCollisionShape position="145,25,5" roll="-15" halfExtents="10,18,5" info="sidearmR, front break"/>
+        <BoxCollisionShape position="133,-13,29" roll="-15" halfExtents="12,6,17" info="sidearmR, bottom cylinder"/>
+        <BoxCollisionShape position="165,-4,31" roll="-15" halfExtents="7,21,13" info="sidearmR, box"/>
+        <BoxCollisionShape position="153,59,96" roll="-15" halfExtents="6,7,60" info="sidearmR, upper beam"/>
+        <BoxCollisionShape position="143,57,119" roll="-15" halfExtents="3,4,85" info="sidearmR, upper inner beam"/>
+        <BoxCollisionShape position="142,53,212" pitch="21" yaw="-5" roll="-15" halfExtents="3,4,10" info="sidearmR, upper inner beam"/>
+        <BoxCollisionShape position="160,52,119" roll="-15" halfExtents="3,4,85" info="sidearmR, upper outer beam"/>
+        <BoxCollisionShape position="159,48,212" pitch="21" yaw="-5" roll="-15" halfExtents="3,4,10" info="sidearmR, upper outer beam"/>
+        <BoxCollisionShape position="152,54,34" pitch="-46" yaw="14" roll="-15" halfExtents="6,7,10" info="sidearmR, upper beam front"/>
+        <BoxCollisionShape position="152,54,162" pitch="30" yaw="-9" roll="-15" halfExtents="6,7,12" info="sidearmR, upper beam back"/>
+        <BoxCollisionShape position="168,21,119" roll="-15" halfExtents="3,5,109" info="sidearmR, outer beam"/>
+        <BoxCollisionShape position="134,-10,169" roll="-15" halfExtents="6,4,55" info="sidearmR, lower beam front"/>
+        <BoxCollisionShape position="131,-20,217" pitch="-20" roll="-15" yaw="5" halfExtents="6,12,3" info="sidearmR, lower beam middle"/>
+        <BoxCollisionShape position="130,-29,233" roll="-15" halfExtents="6,3,15" info="sidearmR, lower beam back"/>
+
+        <BoxCollisionShape position="145,21,71" halfExtents="10,10,1" info="sidearmR, HOOKBOX"/>
+        <BoxCollisionShape position="145,21,29" halfExtents="10,10,1" info="sidearmR, HOOKBOX"/>
+        <BoxCollisionShape position="145,32,50" halfExtents="10,1,20" info="sidearmR, HOOKBOX"/>
+        <BoxCollisionShape position="145,10,50" halfExtents="10,1,20" info="sidearmR, HOOKBOX"/>
+        <BoxCollisionShape position="156,21,50" halfExtents="1,10,20" info="sidearmR, HOOKBOX"/>
+        <BoxCollisionShape position="134,21,50" halfExtents="1,10,20" info="sidearmR, HOOKBOX"/>
+
+
+        <BoxCollisionShape position="141,15,-53" roll="-15" halfExtents="27,44,62" info="sidearmRfront"/>
+        <BoxCollisionShape position="153,59,-30" roll="-15" halfExtents="4,2,38" info="sidearmRfront, top"/>
+        <BoxCollisionShape position="153,61,-41" roll="-15" halfExtents="4,4,11" info="sidearmRfront, top"/>
+        <BoxCollisionShape position="153,60,-65" roll="-15" halfExtents="4,3,4" info="sidearmRfront, top"/>
+        <BoxCollisionShape position="153,59,-41" roll="-15" halfExtents="8,2,11" info="sidearmRfront, top"/>
+
+        <BoxCollisionShape position="145,21,50" halfExtents="10,10,20" info="sidearmRfront, HOOK"/>
+
+
+        <BoxCollisionShape position="-109,47,87" halfExtents="29,8,26" info="sidearmL, upper connection"/>
+        <BoxCollisionShape position="-99,-1,79" roll="15" halfExtents="40,4,9" info="sidearmL, lower connection"/>
+        <BoxCollisionShape position="-151,47,115" roll="15" halfExtents="16,2,105" info="sidearmL, frontTop"/>
+        <BoxCollisionShape position="-136,-7,115" roll="15" halfExtents="16,2,105" info="sidearmL, frontBottom"/>
+        <BoxCollisionShape position="-127,26,115" roll="15" halfExtents="2,28,105" info="sidearmL, frontInner"/>
+        <BoxCollisionShape position="-161,16,115" roll="15" halfExtents="2,28,105" info="sidearmL, frontOuter"/>
+        <BoxCollisionShape position="-145,21,12" roll="15" halfExtents="16,28,2" info="sidearmL, front"/>
+        <BoxCollisionShape position="-140,12,261" roll="15" halfExtents="22,41,43" info="sidearmL, back"/>
+        <BoxCollisionShape position="-145,25,5" roll="15" halfExtents="10,18,5" info="sidearmL, front break"/>
+        <BoxCollisionShape position="-133,-13,29" roll="15" halfExtents="12,6,17" info="sidearmL, bottom cylinder"/>
+        <BoxCollisionShape position="-165,-4,31" roll="15" halfExtents="7,21,13" info="sidearmL, box"/>
+        <BoxCollisionShape position="-153,59,96" roll="15" halfExtents="6,7,60" info="sidearmL, upper beam"/>
+        <BoxCollisionShape position="-143,57,119" roll="15" halfExtents="3,4,85" info="sidearmL, upper inner beam"/>
+        <BoxCollisionShape position="-142,53,212" pitch="21" yaw="5" roll="15" halfExtents="3,4,10" info="sidearmL, upper inner beam"/>
+        <BoxCollisionShape position="-160,52,119" roll="15" halfExtents="3,4,85" info="sidearmL, upper outer beam"/>
+        <BoxCollisionShape position="-159,48,212" pitch="21" yaw="5" roll="15" halfExtents="3,4,10" info="sidearmL, upper outer beam"/>
+        <BoxCollisionShape position="-152,54,34" pitch="-46" yaw="-14" roll="15" halfExtents="6,7,10" info="sidearmL, upper beam front"/>
+        <BoxCollisionShape position="-152,54,162" pitch="30" yaw="9" roll="15" halfExtents="6,7,12" info="sidearmL, upper beam back"/>
+        <BoxCollisionShape position="-168,21,119" roll="15" halfExtents="3,5,109" info="sidearmL, outer beam"/>
+        <BoxCollisionShape position="-134,-10,169" roll="15" halfExtents="6,4,55" info="sidearmL, lower beam front"/>
+        <BoxCollisionShape position="-131,-20,217" pitch="-20" roll="15" yaw="-5" halfExtents="6,12,3" info="sidearmL, lower beam middle"/>
+        <BoxCollisionShape position="-130,-29,233" roll="15" halfExtents="6,3,15" info="sidearmL, lower beam back"/>
+        
+        <BoxCollisionShape position="-145,21,71" halfExtents="10,10,1" info="sidearmL, HOOKBOX"/>
+        <BoxCollisionShape position="-145,21,29" halfExtents="10,10,1" info="sidearmL, HOOKBOX"/>
+        <BoxCollisionShape position="-145,32,50" halfExtents="10,1,20" info="sidearmL, HOOKBOX"/>
+        <BoxCollisionShape position="-145,10,50" halfExtents="10,1,20" info="sidearmL, HOOKBOX"/>
+        <BoxCollisionShape position="-156,21,50" halfExtents="1,10,20" info="sidearmL, HOOKBOX"/>
+        <BoxCollisionShape position="-134,21,50" halfExtents="1,10,20" info="sidearmL, HOOKBOX"/>
+
+
+        <BoxCollisionShape position="-141,15,-53" roll="15" halfExtents="27,44,62" info="sidearmLfront"/>
+        <BoxCollisionShape position="-153,59,-30" roll="15" halfExtents="4,2,38" info="sidearmLfront, top"/>
+        <BoxCollisionShape position="-153,61,-41" roll="15" halfExtents="4,4,11" info="sidearmLfront, top"/>
+        <BoxCollisionShape position="-153,60,-65" roll="15" halfExtents="4,3,4" info="sidearmLfront, top"/>
+        <BoxCollisionShape position="-153,59,-41" roll="15" halfExtents="8,2,11" info="sidearmLfront, top"/>
+
+        <BoxCollisionShape position="-145,21,50" halfExtents="10,10,20" info="sidearmLfront, HOOK"/>
+
+
+        <BoxCollisionShape position="60,35,-310" halfExtents="13,28,60" info="body, bay1, Rwall"/>
+        <BoxCollisionShape position="-60,35,-310" halfExtents="13,28,60" info="body, bay1, Lwall"/>
+        <BoxCollisionShape position="0,56,-310" halfExtents="65,6,60" info="body, bay1, Twall"/>
+        <BoxCollisionShape position="0,33,-260" halfExtents="65,28,5" info="body, bay1, Bwall"/>
+        <BoxCollisionShape position="0,10,-310" halfExtents="65,5,60" info="body, bay1, BottomWall"/>
+
+        <BoxCollisionShape position="0,35,-125" halfExtents="83,30,130" info="body, front"/>
+        <BoxCollisionShape position="0,6,-307" halfExtents="19,3,43" info="body, frontbottom"/>
+        <BoxCollisionShape position="0,5,-196" halfExtents="27,3,24" info="body, dock"/>
+        <BoxCollisionShape position="0,7,-248" pitch="25" halfExtents="63,4,12" info="body, dockF"/>
+        <BoxCollisionShape position="70,6,-120" roll="20" halfExtents="12,6,120" info="body, dockR"/>
+        <BoxCollisionShape position="63,-2,-180" halfExtents="3,3,60" info="body, dockR"/>
+        <BoxCollisionShape position="-70,6,-120" roll="-20" halfExtents="12,6,120" info="body, dockL"/>
+        <BoxCollisionShape position="-63,-2,-180" halfExtents="3,3,60" info="body, dockL"/>
+        <BoxCollisionShape position="87,32,-63" halfExtents="4,23,50" info="body, frontCR"/>
+        <BoxCollisionShape position="-87,32,-63" halfExtents="4,23,50" info="body, frontCL"/>
+
+        <BoxCollisionShape position="0,72,-213" halfExtents="37,8,60" info="body, Fbridge"/>
+        <BoxCollisionShape position="0,72,-110" halfExtents="53,11,53" info="body, Cbridge"/>
+        <BoxCollisionShape position="0,86,-110" halfExtents="40,4,40" info="body, Cbridge"/>
+        <BoxCollisionShape position="0,70,-60" halfExtents="65,11,30" info="body, Bbridge"/>
+        <BoxCollisionShape position="0,84,-45" halfExtents="33,11,26" info="body, Bbridge"/>
+        <BoxCollisionShape position="0,79,-6" pitch="10" halfExtents="32,13,17" info="body, Bbridge"/>
+        <BoxCollisionShape position="38,67,-45" roll="50" halfExtents="16,23,25" info="body, BbridgeR"/>
+        <BoxCollisionShape position="35,63,-17" pitch="25" yaw="-20" roll="40" halfExtents="16,23,16" info="body, BbridgeR"/>
+        <BoxCollisionShape position="-38,67,-45" roll="-50" halfExtents="16,23,25" info="body, BbridgeL"/>
+        <BoxCollisionShape position="-35,63,-17" pitch="25" yaw="20" roll="-40" halfExtents="16,23,16" info="body, BbridgeL"/>
+
+        <BoxCollisionShape position="0,69,80" halfExtents="8,4,80" info="body, Cbeam"/>
+        <BoxCollisionShape position="-67,18,58" roll="-22" halfExtents="13,5,53" info="body, CF, L"/>
+        <BoxCollisionShape position="-76,36,86" halfExtents="5,18,81" info="body, C, L"/>
+        <BoxCollisionShape position="-91,46,86" halfExtents="11,6,20" info="body, C, L upper beam"/>
+        <BoxCollisionShape position="-64,8,79" roll="10" halfExtents="8,3,8" info="body, C, L lower beam"/>
+        <BoxCollisionShape position="-71,55,140" pitch="-4" roll="31" halfExtents="9,5,27" info="body, CB, TopL"/>
+        <BoxCollisionShape position="-62,2,140" roll="24" halfExtents="10,24,32" info="body, CB, BottomL"/>
+        <BoxCollisionShape position="67,18,58" roll="22" halfExtents="13,5,53" info="body, CF, R"/>
+        <BoxCollisionShape position="76,36,86" halfExtents="5,18,81" info="body, C, R"/>
+        <BoxCollisionShape position="91,46,86" halfExtents="11,6,20" info="body, C, R upper beam"/>
+        <BoxCollisionShape position="64,8,79" roll="-10" halfExtents="8,3,8" info="body, C, R lower beam"/>
+        <BoxCollisionShape position="71,55,140" pitch="-4" roll="-31" halfExtents="9,5,27" info="body, CB, TopR"/>
+        <BoxCollisionShape position="62,2,140" roll="-24" halfExtents="10,24,32" info="body, CB, BottomR"/>
+        <BoxCollisionShape position="0,60,12" halfExtents="81,5,11" info="body, CF, Top"/>
+        <BoxCollisionShape position="0,55,40" pitch="15" halfExtents="81,5,20" info="body, CF, Top"/>
+        <BoxCollisionShape position="0,50,85" pitch="1" halfExtents="81,5,29" info="body, C, Top"/>
+        <BoxCollisionShape position="0,59,140" pitch="-4" halfExtents="68,5,27" info="body, CB, Top"/>
+        
+
+
+        <BoxCollisionShape position="0,-7,90" halfExtents="40,4,90" info="body, bay3, Twall"/>
+        <BoxCollisionShape position="0,-15,-60" halfExtents="60,25,65" info="body, bay3, Fwall"/>
+        <BoxCollisionShape position="47,-11,90" halfExtents="13,20,90" info="body, bay3, Rwall"/>
+        <BoxCollisionShape position="-47,-11,90" halfExtents="13,20,90" info="body, bay3, Lwall"/>
+        <BoxCollisionShape position="0,-29,149" halfExtents="10,2,11" info="body, bay3, platform"/>
+        <BoxCollisionShape position="0,-20,227" halfExtents="60,20,65" info="body, bay3, Bwall"/>
+
+        <BoxCollisionShape position="0,81,238" halfExtents="26,5,59" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,67,234" halfExtents="54,5,67" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,77,175" pitch="-36" halfExtents="26,5,9" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,62,161" pitch="-30" halfExtents="56,5,10" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,69,162" halfExtents="16,7,10" info="body, BF, Top"/>
+        <BoxCollisionShape position="31,76,238" roll="-46" halfExtents="10,3,59" info="body, BF, TopR"/>
+        <BoxCollisionShape position="64,64,234" roll="-24" halfExtents="13,3,67" info="body, BF, TopR"/>
+        <BoxCollisionShape position="-31,76,238" roll="46" halfExtents="10,3,59" info="body, BF, TopL"/>
+        <BoxCollisionShape position="-64,64,234" roll="24" halfExtents="13,3,67" info="body, BF, TopL"/>
+
+        <BoxCollisionShape position="77,40,244" roll="16" halfExtents="7,20,79" info="body, BF, R"/>
+        <BoxCollisionShape position="95,9,234" roll="2" halfExtents="18,16,59" info="body, BF, R"/>
+        <BoxCollisionShape position="74,1,255" roll="-20" halfExtents="18,19,82" info="body, BF, BottomR"/>
+        <BoxCollisionShape position="66,-21,255" roll="9" halfExtents="17,5,82" info="body, BF, BottomR"/>
+        <BoxCollisionShape position="-77,40,244" roll="-16" halfExtents="7,20,79" info="body, BF, L"/>
+        <BoxCollisionShape position="-95,9,234" roll="-2" halfExtents="18,16,59" info="body, BF, L"/>
+        <BoxCollisionShape position="-74,1,255" roll="20" halfExtents="18,19,82" info="body, BF, BottomL"/>
+        <BoxCollisionShape position="-66,-21,255" roll="-9" halfExtents="17,5,82" info="body, BF, BottomL"/>
+
+        <BoxCollisionShape position="0,106,381" halfExtents="36,5,71" info="body, BTop"/>
+        <BoxCollisionShape position="0,93,299" pitch="-49" halfExtents="34,5,20" info="body, BTop"/>
+        <BoxCollisionShape position="41,101,381" roll="-42" halfExtents="10,4,71" info="body, BTopR"/>
+        <BoxCollisionShape position="-41,101,381" roll="42" halfExtents="10,4,71" info="body, BTopL"/>
+
+        <BoxCollisionShape position="78,45,332" pitch="-10" roll="-10" yaw="20" halfExtents="10,20,30" info="body, back, R"/>
+        <BoxCollisionShape position="68,77,332" pitch="-10" roll="35" yaw="20" halfExtents="10,20,30" info="body, back, TR"/>
+        <BoxCollisionShape position="50,70,290" pitch="-10" roll="35" yaw="43" halfExtents="5,20,20" info="body, back, TR"/>
+        <BoxCollisionShape position="37,95,307" pitch="-10" roll="30" yaw="43" halfExtents="5,8,8" info="body, back, TR"/>
+        <BoxCollisionShape position="52,92,332" pitch="-10" yaw="30" halfExtents="10,5,30" info="body, back, TR"/>
+        <BoxCollisionShape position="88,4,322" halfExtents="10,24,30" info="body, back, RB"/>
+        <BoxCollisionShape position="54,-24,314" roll="35" pitch="-10" halfExtents="8,5,23" info="body, back, RB"/>
+        <BoxCollisionShape position="68,-19,346" pitch="-17" roll="8" halfExtents="16,4,11" info="body, back, bottomR"/>
+        <BoxCollisionShape position="-78,45,332" pitch="-10" roll="10" yaw="-20" halfExtents="10,20,30" info="body, back, L"/>
+        <BoxCollisionShape position="-68,77,332" pitch="-10" roll="-35" yaw="-20" halfExtents="10,20,30" info="body, back, TL"/>
+        <BoxCollisionShape position="-50,70,290" pitch="-10" roll="-35" yaw="-43" halfExtents="5,20,20" info="body, back, TL"/>
+        <BoxCollisionShape position="-37,95,307" pitch="-10" roll="-30" yaw="-43" halfExtents="5,8,8" info="body, back, TL"/>
+        <BoxCollisionShape position="-52,92,332" pitch="-10" yaw="-30" halfExtents="10,5,30" info="body, back, TL"/>
+        <BoxCollisionShape position="-88,4,322" halfExtents="10,24,30" info="body, back, LB"/>
+        <BoxCollisionShape position="-54,-24,314" roll="-35" pitch="-10" halfExtents="8,5,23" info="body, back, LB"/>
+        <BoxCollisionShape position="-68,-19,346" pitch="-17" roll="-8" halfExtents="16,4,11" info="body, back, bottomL"/>
+        <BoxCollisionShape position="0,-30,314" pitch="-8" halfExtents="52,4,23" info="body, back, bottom"/>
+        <BoxCollisionShape position="0,-22,346" pitch="-24" halfExtents="52,4,11" info="body, back, bottom"/>
+
+        <BoxCollisionShape position="48,-29,400" halfExtents="5,8,58" info="body, BBottomRBeam"/>
+        <BoxCollisionShape position="48,-29,451" halfExtents="10,13,14" info="body, BBottomRBeam"/>
+        <BoxCollisionShape position="-48,-29,400" halfExtents="5,8,58" info="body, BBottomLBeam"/>
+        <BoxCollisionShape position="-48,-31,451" halfExtents="10,13,14" info="body, BBottomLBeam"/>
+
+        <BoxCollisionShape position="103,60,420" halfExtents="18,9,64" info="body, back, Rextrusion"/>
+        <BoxCollisionShape position="-103,60,420" halfExtents="18,9,64" info="body, back, Lextrusion"/>
+        <BoxCollisionShape position="-85,7,417" halfExtents="10,21,67" info="body, back, LB"/>
+        <BoxCollisionShape position="85,7,417" halfExtents="10,21,67" info="body, back, RB"/>
+        <BoxCollisionShape position="0,-8,473" halfExtents="90,6,10" info="body, back, Bback"/>
+        <BoxCollisionShape position="0,-13,474" pitch="-23" halfExtents="76,5,8" info="body, back, Bback"/>
+        <BoxCollisionShape position="-79,-13,405" roll="-12" halfExtents="15,5,73" info="body, back, BL"/>
+        <BoxCollisionShape position="79,-13,405" roll="12" halfExtents="15,5,73" info="body, back, BR"/>
+        <BoxCollisionShape position="0,-15,410" halfExtents="66,6,58" info="body, back, B"/>
+
+        <BoxCollisionShape position="78,32,440" roll="-18" halfExtents="18,35,85" info="body, bay2, Rwall"/>
+        <BoxCollisionShape position="75,71,440" roll="35" halfExtents="18,27,85" info="body, bay2, Rwall"/>
+        <BoxCollisionShape position="-78,32,440" roll="18" halfExtents="18,35,85" info="body, bay2, Lwall"/>
+        <BoxCollisionShape position="-75,71,440" roll="-35" halfExtents="18,27,85" info="body, bay2, Lwall"/>
+        <BoxCollisionShape position="0,75,435" halfExtents="72,28,90" info="body, bay2, Twall"/>
+        <BoxCollisionShape position="0,35,423" halfExtents="85,35,5" info="body, bay2, Fwall"/>
+        <BoxCollisionShape position="0,-3,465" halfExtents="84,5,60" info="body, bay2, BottomWall"/>
+        <BoxCollisionShape position="0,78,526" halfExtents="43,17,5" info="body, bay2, Twall"/>
+        
+        
+        <BoxCollisionShape position="0,7,80" halfExtents="23,1,34" info="HOOKBOX at 0,18,80, bottom"/>
+        <BoxCollisionShape position="0,29,80" halfExtents="23,1,34" info="HOOKBOX, top"/>
+        <BoxCollisionShape position="-22,18,80" halfExtents="1,12,34" info="HOOKBOX, left long"/>
+        <BoxCollisionShape position="0,18,80" halfExtents="1,12,34" info="HOOKBOX, center long"/>
+        <BoxCollisionShape position="22,18,80" halfExtents="1,12,34" info="HOOKBOX, right long"/>
+        <BoxCollisionShape position="0,18,113" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+        <BoxCollisionShape position="0,18,91" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+        <BoxCollisionShape position="0,18,69" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+        <BoxCollisionShape position="0,18,47" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+    </collisionShapes>
+    </StaticEntity-->
+
+    <!-- Width/Height/Lenght--><!-- B=back F=front C=center-->
+    <!--StaticEntity position="300,0,-2000" direction="0,0,0" yaw="180" collisionType=static mass=100000 friction=0.01 >
+    <attached>
+        <Model position="80,33,-320" mesh="cube.mesh" scale3D="7,11,54" info="frontR"/>
+        <Model position="79,31,-399" mesh="cube.mesh" scale3D="3,6,26" info="frontR"/>
+
+
+        <Model position="-80,33,-320" mesh="cube.mesh" scale3D="7,11,54" info="frontL"/>
+        <Model position="-79,31,-399" mesh="cube.mesh" scale3D="3,6,26" info="frontL"/>
+
+
+        <Model position="94,33,-179" mesh="cube.mesh" scale3D="11,13,45" info="partR"/>
+        <Model position="96,33,-230" mesh="cube.mesh" scale3D="13,17,22" info="partR"/>
+
+
+        <Model position="-94,33,-179" mesh="cube.mesh" scale3D="11,13,45" info="partL"/>
+        <Model position="-96,33,-230" mesh="cube.mesh" scale3D="13,17,22" info="partL"/>
+
+
+        <Model position="109,47,87" mesh="cube.mesh" scale3D="29,8,26" info="sidearmR, upper connection"/>
+        <Model position="99,-1,79" roll="-15" mesh="cube.mesh" scale3D="40,4,9" info="sidearmR, lower connection"/>
+        <Model position="151,47,115" roll="-15" mesh="cube.mesh" scale3D="16,2,105" info="sidearmR, frontTop"/>
+        <Model position="136,-7,115" roll="-15" mesh="cube.mesh" scale3D="16,2,105" info="sidearmR, frontBottom"/>
+        <Model position="127,26,115" roll="-15" mesh="cube.mesh" scale3D="2,28,105" info="sidearmR, frontInner"/>
+        <Model position="161,16,115" roll="-15" mesh="cube.mesh" scale3D="2,28,105" info="sidearmR, frontOuter"/>
+        <Model position="145,21,12" roll="-15" mesh="cube.mesh" scale3D="16,28,2" info="sidearmR, front"/>
+        <Model position="140,12,261" roll="-15" mesh="cube.mesh" scale3D="22,41,43" info="sidearmR, back"/>
+        <Model position="145,25,5" roll="-15" mesh="cube.mesh" scale3D="10,18,5" info="sidearmR, front break"/>
+        <Model position="133,-13,29" roll="-15" mesh="cube.mesh" scale3D="12,6,17" info="sidearmR, bottom cylinder"/>
+        <Model position="165,-4,31" roll="-15" mesh="cube.mesh" scale3D="7,21,13" info="sidearmR, box"/>
+        <Model position="153,59,96" roll="-15" mesh="cube.mesh" scale3D="6,7,60" info="sidearmR, upper beam"/>
+        <Model position="143,57,119" roll="-15" mesh="cube.mesh" scale3D="3,4,85" info="sidearmR, upper inner beam"/>
+        <Model position="142,53,212" pitch="21" yaw="-5" roll="-15" mesh="cube.mesh" scale3D="3,4,10" info="sidearmR, upper inner beam"/>
+        <Model position="160,52,119" roll="-15" mesh="cube.mesh" scale3D="3,4,85" info="sidearmR, upper outer beam"/>
+        <Model position="159,48,212" pitch="21" yaw="-5" roll="-15" mesh="cube.mesh" scale3D="3,4,10" info="sidearmR, upper outer beam"/>
+        <Model position="152,54,34" pitch="-46" yaw="14" roll="-15" mesh="cube.mesh" scale3D="6,7,10" info="sidearmR, upper beam front"/>
+        <Model position="152,54,162" pitch="30" yaw="-9" roll="-15" mesh="cube.mesh" scale3D="6,7,12" info="sidearmR, upper beam back"/>
+        <Model position="168,21,119" roll="-15" mesh="cube.mesh" scale3D="3,5,109" info="sidearmR, outer beam"/>
+        <Model position="134,-10,169" roll="-15" mesh="cube.mesh" scale3D="6,4,55" info="sidearmR, lower beam front"/>
+        <Model position="131,-20,217" pitch="-20" roll="-15" yaw="5" mesh="cube.mesh" scale3D="6,12,3" info="sidearmR, lower beam middle"/>
+        <Model position="130,-29,233" roll="-15" mesh="cube.mesh" scale3D="6,3,15" info="sidearmR, lower beam back"/>
+
+        <Model position="145,21,71" mesh="cube.mesh" scale3D="10,10,1" info="sidearmR, HOOKBOX"/>
+        <Model position="145,21,29" mesh="cube.mesh" scale3D="10,10,1" info="sidearmR, HOOKBOX"/>
+        <Model position="145,32,50" mesh="cube.mesh" scale3D="10,1,20" info="sidearmR, HOOKBOX"/>
+        <Model position="145,10,50" mesh="cube.mesh" scale3D="10,1,20" info="sidearmR, HOOKBOX"/>
+        <Model position="156,21,50" mesh="cube.mesh" scale3D="1,10,20" info="sidearmR, HOOKBOX"/>
+        <Model position="134,21,50" mesh="cube.mesh" scale3D="1,10,20" info="sidearmR, HOOKBOX"/>
+
+
+        <Model position="141,15,-53" roll="-15" mesh="cube.mesh" scale3D="27,44,62" info="sidearmRfront"/>
+        <Model position="153,59,-30" roll="-15" mesh="cube.mesh" scale3D="4,2,38" info="sidearmRfront, top"/>
+        <Model position="153,61,-41" roll="-15" mesh="cube.mesh" scale3D="4,4,11" info="sidearmRfront, top"/>
+        <Model position="153,60,-65" roll="-15" mesh="cube.mesh" scale3D="4,3,4" info="sidearmRfront, top"/>
+        <Model position="153,59,-41" roll="-15" mesh="cube.mesh" scale3D="8,2,11" info="sidearmRfront, top"/>
+
+
+        <Model position="-109,47,87" mesh="cube.mesh" scale3D="29,8,26" info="sidearmL, upper connection"/>
+        <Model position="-99,-1,79" roll="15" mesh="cube.mesh" scale3D="40,4,9" info="sidearmL, lower connection"/>
+        <Model position="-151,47,115" roll="15" mesh="cube.mesh" scale3D="16,2,105" info="sidearmL, frontTop"/>
+        <Model position="-136,-7,115" roll="15" mesh="cube.mesh" scale3D="16,2,105" info="sidearmL, frontBottom"/>
+        <Model position="-127,26,115" roll="15" mesh="cube.mesh" scale3D="2,28,105" info="sidearmL, frontInner"/>
+        <Model position="-161,16,115" roll="15" mesh="cube.mesh" scale3D="2,28,105" info="sidearmL, frontOuter"/>
+        <Model position="-145,21,12" roll="15" mesh="cube.mesh" scale3D="16,28,2" info="sidearmL, front"/>
+        <Model position="-140,12,261" roll="15" mesh="cube.mesh" scale3D="22,41,43" info="sidearmL, back"/>
+        <Model position="-145,25,5" roll="15" mesh="cube.mesh" scale3D="10,18,5" info="sidearmL, front break"/>
+        <Model position="-133,-13,29" roll="15" mesh="cube.mesh" scale3D="12,6,17" info="sidearmL, bottom cylinder"/>
+        <Model position="-165,-4,31" roll="15" mesh="cube.mesh" scale3D="7,21,13" info="sidearmL, box"/>
+        <Model position="-153,59,96" roll="15" mesh="cube.mesh" scale3D="6,7,60" info="sidearmL, upper beam"/>
+        <Model position="-143,57,119" roll="15" mesh="cube.mesh" scale3D="3,4,85" info="sidearmL, upper inner beam"/>
+        <Model position="-142,53,212" pitch="21" yaw="5" roll="15" mesh="cube.mesh" scale3D="3,4,10" info="sidearmL, upper inner beam"/>
+        <Model position="-160,52,119" roll="15" mesh="cube.mesh" scale3D="3,4,85" info="sidearmL, upper outer beam"/>
+        <Model position="-159,48,212" pitch="21" yaw="5" roll="15" mesh="cube.mesh" scale3D="3,4,10" info="sidearmL, upper outer beam"/>
+        <Model position="-152,54,34" pitch="-46" yaw="-14" roll="15" mesh="cube.mesh" scale3D="6,7,10" info="sidearmL, upper beam front"/>
+        <Model position="-152,54,162" pitch="30" yaw="9" roll="15" mesh="cube.mesh" scale3D="6,7,12" info="sidearmL, upper beam back"/>
+        <Model position="-168,21,119" roll="15" mesh="cube.mesh" scale3D="3,5,109" info="sidearmL, outer beam"/>
+        <Model position="-134,-10,169" roll="15" mesh="cube.mesh" scale3D="6,4,55" info="sidearmL, lower beam front"/>
+        <Model position="-131,-20,217" pitch="-20" roll="15" yaw="-5" mesh="cube.mesh" scale3D="6,12,3" info="sidearmL, lower beam middle"/>
+        <Model position="-130,-29,233" roll="15" mesh="cube.mesh" scale3D="6,3,15" info="sidearmL, lower beam back"/>
+        
+        <Model position="-145,21,71" mesh="cube.mesh" scale3D="10,10,1" info="sidearmL, HOOKBOX"/>
+        <Model position="-145,21,29" mesh="cube.mesh" scale3D="10,10,1" info="sidearmL, HOOKBOX"/>
+        <Model position="-145,32,50" mesh="cube.mesh" scale3D="10,1,20" info="sidearmL, HOOKBOX"/>
+        <Model position="-145,10,50" mesh="cube.mesh" scale3D="10,1,20" info="sidearmL, HOOKBOX"/>
+        <Model position="-156,21,50" mesh="cube.mesh" scale3D="1,10,20" info="sidearmL, HOOKBOX"/>
+        <Model position="-134,21,50" mesh="cube.mesh" scale3D="1,10,20" info="sidearmL, HOOKBOX"/>
+
+
+        <Model position="-141,15,-53" roll="15" mesh="cube.mesh" scale3D="27,44,62" info="sidearmLfront"/>
+        <Model position="-153,59,-30" roll="15" mesh="cube.mesh" scale3D="4,2,38" info="sidearmLfront, top"/>
+        <Model position="-153,61,-41" roll="15" mesh="cube.mesh" scale3D="4,4,11" info="sidearmLfront, top"/>
+        <Model position="-153,60,-65" roll="15" mesh="cube.mesh" scale3D="4,3,4" info="sidearmLfront, top"/>
+        <Model position="-153,59,-41" roll="15" mesh="cube.mesh" scale3D="8,2,11" info="sidearmLfront, top"/>
+
+
+        <Model position="60,35,-310" mesh="cube.mesh" scale3D="13,28,60" info="body, bay1, Rwall"/>
+        <Model position="-60,35,-310" mesh="cube.mesh" scale3D="13,28,60" info="body, bay1, Lwall"/>
+        <Model position="0,56,-310" mesh="cube.mesh" scale3D="65,6,60" info="body, bay1, Twall"/>
+        <Model position="0,33,-260" mesh="cube.mesh" scale3D="65,28,5" info="body, bay1, Bwall"/>
+        <Model position="0,10,-310" mesh="cube.mesh" scale3D="65,5,60" info="body, bay1, BottomWall"/>
+
+        <Model position="0,35,-125" mesh="cube.mesh" scale3D="83,30,130" info="body, front"/>
+        <Model position="0,6,-307" mesh="cube.mesh" scale3D="19,3,43" info="body, frontbottom"/>
+        <Model position="0,5,-196" mesh="cube.mesh" scale3D="27,3,24" info="body, dock"/>
+        <Model position="0,7,-248" pitch="25" mesh="cube.mesh" scale3D="63,4,12" info="body, dockF"/>
+        <Model position="70,6,-120" roll="20" mesh="cube.mesh" scale3D="12,6,120" info="body, dockR"/>
+        <Model position="63,-2,-180" mesh="cube.mesh" scale3D="3,3,60" info="body, dockR"/>
+        <Model position="-70,6,-120" roll="-20" mesh="cube.mesh" scale3D="12,6,120" info="body, dockL"/>
+        <Model position="-63,-2,-180" mesh="cube.mesh" scale3D="3,3,60" info="body, dockL"/>
+        <Model position="87,32,-63" mesh="cube.mesh" scale3D="4,23,50" info="body, frontCR"/>
+        <Model position="-87,32,-63" mesh="cube.mesh" scale3D="4,23,50" info="body, frontCL"/>
+
+        <Model position="0,72,-213" mesh="cube.mesh" scale3D="37,8,60" info="body, Fbridge"/>
+        <Model position="0,72,-110" mesh="cube.mesh" scale3D="53,11,53" info="body, Cbridge"/>
+        <Model position="0,86,-110" mesh="cube.mesh" scale3D="40,4,40" info="body, Cbridge"/>
+        <Model position="0,70,-60" mesh="cube.mesh" scale3D="65,11,30" info="body, Bbridge"/>
+        <Model position="0,84,-45" mesh="cube.mesh" scale3D="33,11,26" info="body, Bbridge"/>
+        <Model position="0,79,-6" pitch="10" mesh="cube.mesh" scale3D="32,13,17" info="body, Bbridge"/>
+        <Model position="38,67,-45" roll="50" mesh="cube.mesh" scale3D="16,23,25" info="body, BbridgeR"/>
+        <Model position="35,63,-17" pitch="25" yaw="-20" roll="40" mesh="cube.mesh" scale3D="16,23,16" info="body, BbridgeR"/>
+        <Model position="-38,67,-45" roll="-50" mesh="cube.mesh" scale3D="16,23,25" info="body, BbridgeL"/>
+        <Model position="-35,63,-17" pitch="25" yaw="20" roll="-40" mesh="cube.mesh" scale3D="16,23,16" info="body, BbridgeL"/>
+
+        <Model position="0,69,80" mesh="cube.mesh" scale3D="8,4,80" info="body, Cbeam"/>
+        <Model position="-67,18,58" roll="-22" mesh="cube.mesh" scale3D="13,5,53" info="body, CF, L"/>
+        <Model position="-76,36,86" mesh="cube.mesh" scale3D="5,18,81" info="body, C, L"/>
+        <Model position="-91,46,86" mesh="cube.mesh" scale3D="11,6,20" info="body, C, L upper beam"/>
+        <Model position="-64,8,79" roll="10" mesh="cube.mesh" scale3D="8,3,8" info="body, C, L lower beam"/>
+        <Model position="-71,55,140" pitch="-4" roll="31" mesh="cube.mesh" scale3D="9,5,27" info="body, CB, TopL"/>
+        <Model position="-62,2,140" roll="24" mesh="cube.mesh" scale3D="10,24,32" info="body, CB, BottomL"/>
+        <Model position="67,18,58" roll="22" mesh="cube.mesh" scale3D="13,5,53" info="body, CF, R"/>
+        <Model position="76,36,86" mesh="cube.mesh" scale3D="5,18,81" info="body, C, R"/>
+        <Model position="91,46,86" mesh="cube.mesh" scale3D="11,6,20" info="body, C, R upper beam"/>
+        <Model position="64,8,79" roll="-10" mesh="cube.mesh" scale3D="8,3,8" info="body, C, R lower beam"/>
+        <Model position="71,55,140" pitch="-4" roll="-31" mesh="cube.mesh" scale3D="9,5,27" info="body, CB, TopR"/>
+        <Model position="62,2,140" roll="-24" mesh="cube.mesh" scale3D="10,24,32" info="body, CB, BottomR"/>
+        <Model position="0,60,12" mesh="cube.mesh" scale3D="81,5,11" info="body, CF, Top"/>
+        <Model position="0,55,40" pitch="15" mesh="cube.mesh" scale3D="81,5,20" info="body, CF, Top"/>
+        <Model position="0,50,85" pitch="1" mesh="cube.mesh" scale3D="81,5,29" info="body, C, Top"/>
+        <Model position="0,59,140" pitch="-4" mesh="cube.mesh" scale3D="68,5,27" info="body, CB, Top"/>
+        
+
+
+        <Model position="0,-7,90" mesh="cube.mesh" scale3D="40,4,90" info="body, bay3, Twall"/>
+        <Model position="0,-15,-60" mesh="cube.mesh" scale3D="60,25,65" info="body, bay3, Fwall"/>
+        <Model position="47,-11,90" mesh="cube.mesh" scale3D="13,20,90" info="body, bay3, Rwall"/>
+        <Model position="-47,-11,90" mesh="cube.mesh" scale3D="13,20,90" info="body, bay3, Lwall"/>
+        <Model position="0,-29,149" mesh="cube.mesh" scale3D="10,2,11" info="body, bay3, platform"/>
+        <Model position="0,-20,227" mesh="cube.mesh" scale3D="60,20,65" info="body, bay3, Bwall"/>
+
+        <Model position="0,81,238" mesh="cube.mesh" scale3D="26,5,59" info="body, BF, Top"/>
+        <Model position="0,67,234" mesh="cube.mesh" scale3D="54,5,67" info="body, BF, Top"/>
+        <Model position="0,77,175" pitch="-36" mesh="cube.mesh" scale3D="26,5,9" info="body, BF, Top"/>
+        <Model position="0,62,161" pitch="-30" mesh="cube.mesh" scale3D="56,5,10" info="body, BF, Top"/>
+        <Model position="0,69,162" mesh="cube.mesh" scale3D="16,7,10" info="body, BF, Top"/>
+        <Model position="31,76,238" roll="-46" mesh="cube.mesh" scale3D="10,3,59" info="body, BF, TopR"/>
+        <Model position="64,64,234" roll="-24" mesh="cube.mesh" scale3D="13,3,67" info="body, BF, TopR"/>
+        <Model position="-31,76,238" roll="46" mesh="cube.mesh" scale3D="10,3,59" info="body, BF, TopL"/>
+        <Model position="-64,64,234" roll="24" mesh="cube.mesh" scale3D="13,3,67" info="body, BF, TopL"/>
+
+        <Model position="77,40,244" roll="16" mesh="cube.mesh" scale3D="7,20,79" info="body, BF, R"/>
+        <Model position="95,9,234" roll="2" mesh="cube.mesh" scale3D="18,16,59" info="body, BF, R"/>
+        <Model position="74,1,255" roll="-20" mesh="cube.mesh" scale3D="18,19,82" info="body, BF, BottomR"/>
+        <Model position="66,-21,255" roll="9" mesh="cube.mesh" scale3D="17,5,82" info="body, BF, BottomR"/>
+        <Model position="-77,40,244" roll="-16" mesh="cube.mesh" scale3D="7,20,79" info="body, BF, L"/>
+        <Model position="-95,9,234" roll="-2" mesh="cube.mesh" scale3D="18,16,59" info="body, BF, L"/>
+        <Model position="-74,1,255" roll="20" mesh="cube.mesh" scale3D="18,19,82" info="body, BF, BottomL"/>
+        <Model position="-66,-21,255" roll="-9" mesh="cube.mesh" scale3D="17,5,82" info="body, BF, BottomL"/>
+
+        <Model position="0,106,381" mesh="cube.mesh" scale3D="36,5,71" info="body, BTop"/>
+        <Model position="0,93,299" pitch="-49" mesh="cube.mesh" scale3D="34,5,20" info="body, BTop"/>
+        <Model position="41,101,381" roll="-42" mesh="cube.mesh" scale3D="10,4,71" info="body, BTopR"/>
+        <Model position="-41,101,381" roll="42" mesh="cube.mesh" scale3D="10,4,71" info="body, BTopL"/>
+
+        <Model position="78,45,332" pitch="-10" roll="-10" yaw="20" mesh="cube.mesh" scale3D="10,20,30" info="body, back, R"/>
+        <Model position="68,77,332" pitch="-10" roll="35" yaw="20" mesh="cube.mesh" scale3D="10,20,30" info="body, back, TR"/>
+        <Model position="50,70,290" pitch="-10" roll="35" yaw="43" mesh="cube.mesh" scale3D="5,20,20" info="body, back, TR"/>
+        <Model position="37,95,307" pitch="-10" roll="30" yaw="43" mesh="cube.mesh" scale3D="5,8,8" info="body, back, TR"/>
+        <Model position="52,92,332" pitch="-10" yaw="30" mesh="cube.mesh" scale3D="10,5,30" info="body, back, TR"/>
+        <Model position="88,4,322" mesh="cube.mesh" scale3D="10,24,30" info="body, back, RB"/>
+        <Model position="54,-24,314" roll="35" pitch="-10" mesh="cube.mesh" scale3D="8,5,23" info="body, back, RB"/>
+        <Model position="68,-19,346" pitch="-17" roll="8" mesh="cube.mesh" scale3D="16,4,11" info="body, back, bottomR"/>
+        <Model position="-78,45,332" pitch="-10" roll="10" yaw="-20" mesh="cube.mesh" scale3D="10,20,30" info="body, back, L"/>
+        <Model position="-68,77,332" pitch="-10" roll="-35" yaw="-20" mesh="cube.mesh" scale3D="10,20,30" info="body, back, TL"/>
+        <Model position="-50,70,290" pitch="-10" roll="-35" yaw="-43" mesh="cube.mesh" scale3D="5,20,20" info="body, back, TL"/>
+        <Model position="-37,95,307" pitch="-10" roll="-30" yaw="-43" mesh="cube.mesh" scale3D="5,8,8" info="body, back, TL"/>
+        <Model position="-52,92,332" pitch="-10" yaw="-30" mesh="cube.mesh" scale3D="10,5,30" info="body, back, TL"/>
+        <Model position="-88,4,322" mesh="cube.mesh" scale3D="10,24,30" info="body, back, LB"/>
+        <Model position="-54,-24,314" roll="-35" pitch="-10" mesh="cube.mesh" scale3D="8,5,23" info="body, back, LB"/>
+        <Model position="-68,-19,346" pitch="-17" roll="-8" mesh="cube.mesh" scale3D="16,4,11" info="body, back, bottomL"/>
+        <Model position="0,-30,314" pitch="-8" mesh="cube.mesh" scale3D="52,4,23" info="body, back, bottom"/>
+        <Model position="0,-22,346" pitch="-24" mesh="cube.mesh" scale3D="52,4,11" info="body, back, bottom"/>
+
+        <Model position="48,-29,400" mesh="cube.mesh" scale3D="5,8,58" info="body, BBottomRBeam"/>
+        <Model position="48,-29,451" mesh="cube.mesh" scale3D="10,13,14" info="body, BBottomRBeam"/>
+        <Model position="-48,-29,400" mesh="cube.mesh" scale3D="5,8,58" info="body, BBottomLBeam"/>
+        <Model position="-48,-31,451" mesh="cube.mesh" scale3D="10,13,14" info="body, BBottomLBeam"/>
+
+        <Model position="103,60,420" mesh="cube.mesh" scale3D="18,9,64" info="body, back, Rextrusion"/>
+        <Model position="-103,60,420" mesh="cube.mesh" scale3D="18,9,64" info="body, back, Lextrusion"/>
+        <Model position="-85,7,417" mesh="cube.mesh" scale3D="10,21,67" info="body, back, LB"/>
+        <Model position="85,7,417" mesh="cube.mesh" scale3D="10,21,67" info="body, back, RB"/>
+        <Model position="0,-8,473" mesh="cube.mesh" scale3D="90,6,10" info="body, back, Bback"/>
+        <Model position="0,-13,474" pitch="-23" mesh="cube.mesh" scale3D="76,5,8" info="body, back, Bback"/>
+        <Model position="-79,-13,405" roll="-12" mesh="cube.mesh" scale3D="15,5,73" info="body, back, BL"/>
+        <Model position="79,-13,405" roll="12" mesh="cube.mesh" scale3D="15,5,73" info="body, back, BR"/>
+        <Model position="0,-15,410" mesh="cube.mesh" scale3D="66,6,58" info="body, back, B"/>
+
+        <Model position="78,32,440" roll="-18" mesh="cube.mesh" scale3D="18,35,85" info="body, bay2, Rwall"/>
+        <Model position="75,71,440" roll="35" mesh="cube.mesh" scale3D="18,27,85" info="body, bay2, Rwall"/>
+        <Model position="-78,32,440" roll="18" mesh="cube.mesh" scale3D="18,35,85" info="body, bay2, Lwall"/>
+        <Model position="-75,71,440" roll="-35" mesh="cube.mesh" scale3D="18,27,85" info="body, bay2, Lwall"/>
+        <Model position="0,75,435" mesh="cube.mesh" scale3D="72,28,90" info="body, bay2, Twall"/>
+        <Model position="0,35,423" mesh="cube.mesh" scale3D="85,35,5" info="body, bay2, Fwall"/>
+        <Model position="0,-3,465" mesh="cube.mesh" scale3D="84,5,60" info="body, bay2, BottomWall"/>
+        <Model position="0,78,526" mesh="cube.mesh" scale3D="43,17,5" info="body, bay2, Twall"/>
+
+        
+        <Model position="0,7,80" mesh="cube.mesh" scale3D="23,1,34" info="HOOKBOX at 0,18,80, bottom"/>
+        <Model position="0,29,80" mesh="cube.mesh" scale3D="23,1,34" info="HOOKBOX, top"/>
+        <Model position="-22,18,80" mesh="cube.mesh" scale3D="1,12,34" info="HOOKBOX, left long"/>
+        <Model position="0,18,80" mesh="cube.mesh" scale3D="1,12,34" info="HOOKBOX, center long"/>
+        <Model position="22,18,80" mesh="cube.mesh" scale3D="1,12,34" info="HOOKBOX, right long"/>
+        <Model position="0,18,113" mesh="cube.mesh" scale3D="23,12,1" info="HOOKBOX, wide"/>
+        <Model position="0,18,91" mesh="cube.mesh" scale3D="23,12,1" info="HOOKBOX, wide"/>
+        <Model position="0,18,69" mesh="cube.mesh" scale3D="23,12,1" info="HOOKBOX, wide"/>
+        <Model position="0,18,47" mesh="cube.mesh" scale3D="23,12,1" info="HOOKBOX, wide"/>
+        
+        <Model position="-11,18,102" mesh="cube.mesh" scale3D="10,10,10" info="HOOK, frontL"/>
+        <Model position="11,18,102" mesh="cube.mesh" scale3D="10,10,10" info="HOOK, frontR"/>
+        <Model position="-11,18,80" mesh="cube.mesh" scale3D="10,10,10" info="HOOK, partL"/>
+        <Model position="11,18,80" mesh="cube.mesh" scale3D="10,10,10" info="HOOK, partR"/>
+        <Model position="-11,18,58" mesh="cube.mesh" scale3D="10,10,10" info="HOOK, sidearmL"/>
+        <Model position="11,18,58" mesh="cube.mesh" scale3D="10,10,10" info="HOOK, sidearmR"/>
+    </attached>
+    <collisionShapes>
+    </collisionShapes>
+    </StaticEntity-->
+
+
+
+<!-- 9 Pawns, each being a part of HeavyCruiser.
+    The first Pawn, being the ships main body, is in comments, allowing the playable SpaceShip to be spawned there instead.
+    All Pawns can easily be included into a level using the lua file "HeavyCruiserParts" -->
+
+    <Pawn team=1 health=1000 initialhealth=1000 maxhealth=1000 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=10000 name=HeavyCruiser_body radarname = "HeavyCruiser" >
+        <explosion>
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_sparks2" scale=2.5 />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flame2" scale=2.5 />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" scale=12 />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" scale=2.5 />
+
+            <ExplosionPart offset="50,50,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_sparks2" scale=2.5 delay=0.3 />
+            <ExplosionPart offset="50,50,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flame2" scale=2.5 delay=0.3 />
+            <ExplosionPart offset="50,50,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" scale=12 delay=0.3 />
+            <ExplosionPart offset="50,50,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" scale=2.5 delay=0.3 />
+
+            <ExplosionPart offset="50,-50,-50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_sparks2" scale=2.5 delay=0.6 />
+            <ExplosionPart offset="50,-50,-50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flame2" scale=2.5 delay=0.6 />
+            <ExplosionPart offset="50,-50,-50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" scale=12 delay=0.6 />
+            <ExplosionPart offset="50,-50,-50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" scale=2.5 delay=0.6 />
+
+            <ExplosionPart offset="-50,0,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_sparks2" scale=2.5 delay=0.9 />
+            <ExplosionPart offset="-50,0,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flame2" scale=2.5 delay=0.9 />
+            <ExplosionPart offset="-50,0,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" scale=12 delay=0.9 />
+            <ExplosionPart offset="-50,0,50" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" scale=2.5 delay=0.9 />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_body.mesh" scale="40" />
+
+            <BlinkingBillboard position="75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+            <BlinkingBillboard position="-75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+            <BlinkingBillboard position="74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+            <BlinkingBillboard position="-74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+            <BlinkingBillboard position="73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+            <BlinkingBillboard position="-73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+            
+            <BlinkingBillboard position="67,-5,-240" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <BlinkingBillboard position="-67,-5,-240" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+            <BlinkingBillboard position="72,51,-380" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+            <BlinkingBillboard position="-72,51,-380" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            
+            <BlinkingBillboard position="95,-15,483" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+            <BlinkingBillboard position="-95,-15,483" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <BlinkingBillboard position="74,103,524" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <BlinkingBillboard position="-74,103,524" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="60,35,-310" halfExtents="13,28,60" info="body, bay1, Rwall"/>
+            <BoxCollisionShape position="-60,35,-310" halfExtents="13,28,60" info="body, bay1, Lwall"/>
+            <BoxCollisionShape position="0,56,-310" halfExtents="65,6,60" info="body, bay1, Twall"/>
+            <BoxCollisionShape position="0,33,-260" halfExtents="65,28,5" info="body, bay1, Bwall"/>
+            <BoxCollisionShape position="0,10,-310" halfExtents="65,5,60" info="body, bay1, BottomWall"/>
+
+            <BoxCollisionShape position="0,35,-125" halfExtents="83,30,130" info="body, front"/>
+            <BoxCollisionShape position="0,6,-307" halfExtents="19,3,43" info="body, frontbottom"/>
+            <BoxCollisionShape position="0,5,-196" halfExtents="27,3,24" info="body, dock"/>
+            <BoxCollisionShape position="0,7,-248" pitch="25" halfExtents="63,4,12" info="body, dockF"/>
+            <BoxCollisionShape position="70,6,-120" roll="20" halfExtents="12,6,120" info="body, dockR"/>
+            <BoxCollisionShape position="63,-2,-180" halfExtents="3,3,60" info="body, dockR"/>
+            <BoxCollisionShape position="-70,6,-120" roll="-20" halfExtents="12,6,120" info="body, dockL"/>
+            <BoxCollisionShape position="-63,-2,-180" halfExtents="3,3,60" info="body, dockL"/>
+            <BoxCollisionShape position="87,32,-63" halfExtents="4,23,50" info="body, frontCR"/>
+            <BoxCollisionShape position="-87,32,-63" halfExtents="4,23,50" info="body, frontCL"/>
+
+            <BoxCollisionShape position="0,72,-213" halfExtents="37,8,60" info="body, Fbridge"/>
+            <BoxCollisionShape position="0,72,-110" halfExtents="53,11,53" info="body, Cbridge"/>
+            <BoxCollisionShape position="0,86,-110" halfExtents="40,4,40" info="body, Cbridge"/>
+            <BoxCollisionShape position="0,70,-60" halfExtents="65,11,30" info="body, Bbridge"/>
+            <BoxCollisionShape position="0,84,-45" halfExtents="33,11,26" info="body, Bbridge"/>
+            <BoxCollisionShape position="0,79,-6" pitch="10" halfExtents="32,13,17" info="body, Bbridge"/>
+            <BoxCollisionShape position="38,67,-45" roll="50" halfExtents="16,23,25" info="body, BbridgeR"/>
+            <BoxCollisionShape position="35,63,-17" pitch="25" yaw="-20" roll="40" halfExtents="16,23,16" info="body, BbridgeR"/>
+            <BoxCollisionShape position="-38,67,-45" roll="-50" halfExtents="16,23,25" info="body, BbridgeL"/>
+            <BoxCollisionShape position="-35,63,-17" pitch="25" yaw="20" roll="-40" halfExtents="16,23,16" info="body, BbridgeL"/>
+
+            <BoxCollisionShape position="0,69,80" halfExtents="8,4,80" info="body, Cbeam"/>
+            <BoxCollisionShape position="-67,18,58" roll="-22" halfExtents="13,5,53" info="body, CF, L"/>
+            <BoxCollisionShape position="-76,36,86" halfExtents="5,18,81" info="body, C, L"/>
+            <BoxCollisionShape position="-91,46,86" halfExtents="11,6,20" info="body, C, L upper beam"/>
+            <BoxCollisionShape position="-64,8,79" roll="10" halfExtents="8,3,8" info="body, C, L lower beam"/>
+            <BoxCollisionShape position="-71,55,140" pitch="-4" roll="31" halfExtents="9,5,27" info="body, CB, TopL"/>
+            <BoxCollisionShape position="-62,2,140" roll="24" halfExtents="10,24,32" info="body, CB, BottomL"/>
+            <BoxCollisionShape position="67,18,58" roll="22" halfExtents="13,5,53" info="body, CF, R"/>
+            <BoxCollisionShape position="76,36,86" halfExtents="5,18,81" info="body, C, R"/>
+            <BoxCollisionShape position="91,46,86" halfExtents="11,6,20" info="body, C, R upper beam"/>
+            <BoxCollisionShape position="64,8,79" roll="-10" halfExtents="8,3,8" info="body, C, R lower beam"/>
+            <BoxCollisionShape position="71,55,140" pitch="-4" roll="-31" halfExtents="9,5,27" info="body, CB, TopR"/>
+            <BoxCollisionShape position="62,2,140" roll="-24" halfExtents="10,24,32" info="body, CB, BottomR"/>
+            <BoxCollisionShape position="0,60,12" halfExtents="81,5,11" info="body, CF, Top"/>
+            <BoxCollisionShape position="0,55,40" pitch="15" halfExtents="81,5,20" info="body, CF, Top"/>
+            <BoxCollisionShape position="0,50,85" pitch="1" halfExtents="81,5,29" info="body, C, Top"/>
+            <BoxCollisionShape position="0,59,140" pitch="-4" halfExtents="68,5,27" info="body, CB, Top"/>
+
+            <BoxCollisionShape position="0,-7,90" halfExtents="40,4,90" info="body, bay3, Twall"/>
+            <BoxCollisionShape position="0,-15,-60" halfExtents="60,25,65" info="body, bay3, Fwall"/>
+            <BoxCollisionShape position="47,-11,90" halfExtents="13,20,90" info="body, bay3, Rwall"/>
+            <BoxCollisionShape position="-47,-11,90" halfExtents="13,20,90" info="body, bay3, Lwall"/>
+            <BoxCollisionShape position="0,-29,149" halfExtents="10,2,11" info="body, bay3, platform"/>
+            <BoxCollisionShape position="0,-20,227" halfExtents="60,20,65" info="body, bay3, Bwall"/>
+
+            <BoxCollisionShape position="0,81,238" halfExtents="26,5,59" info="body, BF, Top"/>
+            <BoxCollisionShape position="0,67,234" halfExtents="54,5,67" info="body, BF, Top"/>
+            <BoxCollisionShape position="0,77,175" pitch="-36" halfExtents="26,5,9" info="body, BF, Top"/>
+            <BoxCollisionShape position="0,62,161" pitch="-30" halfExtents="56,5,10" info="body, BF, Top"/>
+            <BoxCollisionShape position="0,69,162" halfExtents="16,7,10" info="body, BF, Top"/>
+            <BoxCollisionShape position="31,76,238" roll="-46" halfExtents="10,3,59" info="body, BF, TopR"/>
+            <BoxCollisionShape position="64,64,234" roll="-24" halfExtents="13,3,67" info="body, BF, TopR"/>
+            <BoxCollisionShape position="-31,76,238" roll="46" halfExtents="10,3,59" info="body, BF, TopL"/>
+            <BoxCollisionShape position="-64,64,234" roll="24" halfExtents="13,3,67" info="body, BF, TopL"/>
+
+            <BoxCollisionShape position="77,40,244" roll="16" halfExtents="7,20,79" info="body, BF, R"/>
+            <BoxCollisionShape position="95,9,234" roll="2" halfExtents="18,16,59" info="body, BF, R"/>
+            <BoxCollisionShape position="74,1,255" roll="-20" halfExtents="18,19,82" info="body, BF, BottomR"/>
+            <BoxCollisionShape position="66,-21,255" roll="9" halfExtents="17,5,82" info="body, BF, BottomR"/>
+            <BoxCollisionShape position="-77,40,244" roll="-16" halfExtents="7,20,79" info="body, BF, L"/>
+            <BoxCollisionShape position="-95,9,234" roll="-2" halfExtents="18,16,59" info="body, BF, L"/>
+            <BoxCollisionShape position="-74,1,255" roll="20" halfExtents="18,19,82" info="body, BF, BottomL"/>
+            <BoxCollisionShape position="-66,-21,255" roll="-9" halfExtents="17,5,82" info="body, BF, BottomL"/>
+
+            <BoxCollisionShape position="0,106,381" halfExtents="36,5,71" info="body, BTop"/>
+            <BoxCollisionShape position="0,93,299" pitch="-49" halfExtents="34,5,20" info="body, BTop"/>
+            <BoxCollisionShape position="41,101,381" roll="-42" halfExtents="10,4,71" info="body, BTopR"/>
+            <BoxCollisionShape position="-41,101,381" roll="42" halfExtents="10,4,71" info="body, BTopL"/>
+
+            <BoxCollisionShape position="78,45,332" pitch="-10" roll="-10" yaw="20" halfExtents="10,20,30" info="body, back, R"/>
+            <BoxCollisionShape position="68,77,332" pitch="-10" roll="35" yaw="20" halfExtents="10,20,30" info="body, back, TR"/>
+            <BoxCollisionShape position="50,70,290" pitch="-10" roll="35" yaw="43" halfExtents="5,20,20" info="body, back, TR"/>
+            <BoxCollisionShape position="37,95,307" pitch="-10" roll="30" yaw="43" halfExtents="5,8,8" info="body, back, TR"/>
+            <BoxCollisionShape position="52,92,332" pitch="-10" yaw="30" halfExtents="10,5,30" info="body, back, TR"/>
+            <BoxCollisionShape position="88,4,322" halfExtents="10,24,30" info="body, back, RB"/>
+            <BoxCollisionShape position="54,-24,314" roll="35" pitch="-10" halfExtents="8,5,23" info="body, back, RB"/>
+            <BoxCollisionShape position="68,-19,346" pitch="-17" roll="8" halfExtents="16,4,11" info="body, back, bottomR"/>
+            <BoxCollisionShape position="-78,45,332" pitch="-10" roll="10" yaw="-20" halfExtents="10,20,30" info="body, back, L"/>
+            <BoxCollisionShape position="-68,77,332" pitch="-10" roll="-35" yaw="-20" halfExtents="10,20,30" info="body, back, TL"/>
+            <BoxCollisionShape position="-50,70,290" pitch="-10" roll="-35" yaw="-43" halfExtents="5,20,20" info="body, back, TL"/>
+            <BoxCollisionShape position="-37,95,307" pitch="-10" roll="-30" yaw="-43" halfExtents="5,8,8" info="body, back, TL"/>
+            <BoxCollisionShape position="-52,92,332" pitch="-10" yaw="-30" halfExtents="10,5,30" info="body, back, TL"/>
+            <BoxCollisionShape position="-88,4,322" halfExtents="10,24,30" info="body, back, LB"/>
+            <BoxCollisionShape position="-54,-24,314" roll="-35" pitch="-10" halfExtents="8,5,23" info="body, back, LB"/>
+            <BoxCollisionShape position="-68,-19,346" pitch="-17" roll="-8" halfExtents="16,4,11" info="body, back, bottomL"/>
+            <BoxCollisionShape position="0,-30,314" pitch="-8" halfExtents="52,4,23" info="body, back, bottom"/>
+            <BoxCollisionShape position="0,-22,346" pitch="-24" halfExtents="52,4,11" info="body, back, bottom"/>
+
+            <BoxCollisionShape position="48,-29,400" halfExtents="5,8,58" info="body, BBottomRBeam"/>
+            <BoxCollisionShape position="48,-29,451" halfExtents="10,13,14" info="body, BBottomRBeam"/>
+            <BoxCollisionShape position="-48,-29,400" halfExtents="5,8,58" info="body, BBottomLBeam"/>
+            <BoxCollisionShape position="-48,-31,451" halfExtents="10,13,14" info="body, BBottomLBeam"/>
+
+            <BoxCollisionShape position="103,60,420" halfExtents="18,9,64" info="body, back, Rextrusion"/>
+            <BoxCollisionShape position="-103,60,420" halfExtents="18,9,64" info="body, back, Lextrusion"/>
+            <BoxCollisionShape position="-85,7,417" halfExtents="10,21,67" info="body, back, LB"/>
+            <BoxCollisionShape position="85,7,417" halfExtents="10,21,67" info="body, back, RB"/>
+            <BoxCollisionShape position="0,-8,473" halfExtents="90,6,10" info="body, back, Bback"/>
+            <BoxCollisionShape position="0,-13,474" pitch="-23" halfExtents="76,5,8" info="body, back, Bback"/>
+            <BoxCollisionShape position="-79,-13,405" roll="-12" halfExtents="15,5,73" info="body, back, BL"/>
+            <BoxCollisionShape position="79,-13,405" roll="12" halfExtents="15,5,73" info="body, back, BR"/>
+            <BoxCollisionShape position="0,-15,410" halfExtents="66,6,58" info="body, back, B"/>
+
+            <BoxCollisionShape position="78,32,440" roll="-18" halfExtents="18,35,85" info="body, bay2, Rwall"/>
+            <BoxCollisionShape position="75,71,440" roll="35" halfExtents="18,27,85" info="body, bay2, Rwall"/>
+            <BoxCollisionShape position="-78,32,440" roll="18" halfExtents="18,35,85" info="body, bay2, Lwall"/>
+            <BoxCollisionShape position="-75,71,440" roll="-35" halfExtents="18,27,85" info="body, bay2, Lwall"/>
+            <BoxCollisionShape position="0,75,435" halfExtents="72,28,90" info="body, bay2, Twall"/>
+            <BoxCollisionShape position="0,35,423" halfExtents="85,35,5" info="body, bay2, Fwall"/>
+            <BoxCollisionShape position="0,-3,465" halfExtents="84,5,60" info="body, bay2, BottomWall"/>
+            <BoxCollisionShape position="0,78,526" halfExtents="43,17,5" info="body, bay2, Twall"/>
+            
+            
+            <BoxCollisionShape position="0,7,80" halfExtents="23,1,34" info="HOOKBOX at 0,18,80, bottom"/>
+            <BoxCollisionShape position="0,29,80" halfExtents="23,1,34" info="HOOKBOX, top"/>
+            <BoxCollisionShape position="-22,18,80" halfExtents="1,12,34" info="HOOKBOX, left long"/>
+            <BoxCollisionShape position="0,18,80" halfExtents="1,12,34" info="HOOKBOX, center long"/>
+            <BoxCollisionShape position="22,18,80" halfExtents="1,12,34" info="HOOKBOX, right long"/>
+            <BoxCollisionShape position="0,18,113" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+            <BoxCollisionShape position="0,18,91" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+            <BoxCollisionShape position="0,18,69" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+            <BoxCollisionShape position="0,18,47" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+
+            <BoxCollisionShape position="0,107,80" halfExtents="23,1,34" info="HOOKBOX at 0,18,80, bottom"/>
+            <BoxCollisionShape position="0,129,80" halfExtents="23,1,34" info="HOOKBOX, top"/>
+            <BoxCollisionShape position="-22,118,80" halfExtents="1,12,34" info="HOOKBOX, left long"/>
+            <BoxCollisionShape position="0,118,80" halfExtents="1,12,34" info="HOOKBOX, center long"/>
+            <BoxCollisionShape position="22,118,80" halfExtents="1,12,34" info="HOOKBOX, right long"/>
+            <BoxCollisionShape position="0,118,113" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+            <BoxCollisionShape position="0,118,91" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+            <BoxCollisionShape position="0,118,69" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+            <BoxCollisionShape position="0,118,47" halfExtents="23,12,1" info="HOOKBOX, wide"/>
+        </collisionShapes>
+    </Pawn>
+
+    <!--Pawn team=1 health=300 initialhealth=300 maxhealth=300 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_sidearmL radarname = "HIDDEN" >
+
+        <explosion>
+            <ExplosionPart offset="-140,0,115" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="-140,0,115" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="-140,0,115" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_sidearmL.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="-11,18,102" halfExtents="10,10,10" info="HOOK, sidearmL"/>
+            
+            <BoxCollisionShape position="-151,47,115" roll="15" halfExtents="16,2,105" info="sidearmL, frontTop"/>
+            <BoxCollisionShape position="-136,-7,115" roll="15" halfExtents="16,2,105" info="sidearmL, frontBottom"/>
+            <BoxCollisionShape position="-127,26,115" roll="15" halfExtents="2,28,105" info="sidearmL, frontInner"/>
+            <BoxCollisionShape position="-161,16,115" roll="15" halfExtents="2,28,105" info="sidearmL, frontOuter"/>
+            <BoxCollisionShape position="-145,21,12" roll="15" halfExtents="16,28,2" info="sidearmL, front"/>
+            <BoxCollisionShape position="-140,12,261" roll="15" halfExtents="22,41,43" info="sidearmL, back"/>
+            <BoxCollisionShape position="-133,-13,29" roll="15" halfExtents="12,6,17" info="sidearmL, bottom cylinder"/>
+            <BoxCollisionShape position="-165,-4,31" roll="15" halfExtents="7,21,13" info="sidearmL, box"/>
+            <BoxCollisionShape position="-153,59,96" roll="15" halfExtents="6,7,60" info="sidearmL, upper beam"/>
+            <BoxCollisionShape position="-143,57,119" roll="15" halfExtents="3,4,85" info="sidearmL, upper inner beam"/>
+            <BoxCollisionShape position="-142,53,212" pitch="21" yaw="5" roll="15" halfExtents="3,4,10" info="sidearmL, upper inner beam"/>
+            <BoxCollisionShape position="-160,52,119" roll="15" halfExtents="3,4,85" info="sidearmL, upper outer beam"/>
+            <BoxCollisionShape position="-159,48,212" pitch="21" yaw="5" roll="15" halfExtents="3,4,10" info="sidearmL, upper outer beam"/>
+            <BoxCollisionShape position="-152,54,34" pitch="-46" yaw="-14" roll="15" halfExtents="6,7,10" info="sidearmL, upper beam front"/>
+            <BoxCollisionShape position="-152,54,162" pitch="30" yaw="9" roll="15" halfExtents="6,7,12" info="sidearmL, upper beam back"/>
+            <BoxCollisionShape position="-168,21,119" roll="15" halfExtents="3,5,109" info="sidearmL, outer beam"/>
+            <BoxCollisionShape position="-134,-10,169" roll="15" halfExtents="6,4,55" info="sidearmL, lower beam front"/>
+            <BoxCollisionShape position="-131,-20,217" pitch="-20" roll="15" yaw="-5" halfExtents="6,12,3" info="sidearmL, lower beam middle"/>
+            <BoxCollisionShape position="-130,-29,233" roll="15" halfExtents="6,3,15" info="sidearmL, lower beam back"/>
+            
+            <BoxCollisionShape position="-145,21,71" halfExtents="10,10,1" info="sidearmL, HOOKBOX"/>
+            <BoxCollisionShape position="-145,21,29" halfExtents="10,10,1" info="sidearmL, HOOKBOX"/>
+            <BoxCollisionShape position="-145,32,50" halfExtents="10,1,20" info="sidearmL, HOOKBOX"/>
+            <BoxCollisionShape position="-145,10,50" halfExtents="10,1,20" info="sidearmL, HOOKBOX"/>
+            <BoxCollisionShape position="-156,21,50" halfExtents="1,10,20" info="sidearmL, HOOKBOX"/>
+            <BoxCollisionShape position="-134,21,50" halfExtents="1,10,20" info="sidearmL, HOOKBOX"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=100 initialhealth=100 maxhealth=100 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_sidearmLfront radarname = "HIDDEN" >
+
+        <explosion>
+            <ExplosionPart offset="-141,15,-53" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="-141,15,-53" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="-141,15,-53" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_sidearmLfront.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="-145,21,50" halfExtents="10,10,20" info="sidearmLfront, HOOK"/>
+            <BoxCollisionShape position="-141,15,-53" roll="15" halfExtents="27,44,62" info="sidearmLfront"/>
+            <BoxCollisionShape position="-153,59,-30" roll="15" halfExtents="4,2,38" info="sidearmLfront, top"/>
+            <BoxCollisionShape position="-153,61,-41" roll="15" halfExtents="4,4,11" info="sidearmLfront, top"/>
+            <BoxCollisionShape position="-153,60,-65" roll="15" halfExtents="4,3,4" info="sidearmLfront, top"/>
+            <BoxCollisionShape position="-153,59,-41" roll="15" halfExtents="8,2,11" info="sidearmLfront, top"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=300 initialhealth=300 maxhealth=300 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_sidearmR radarname = "HIDDEN" >
+        <explosion>
+            <ExplosionPart offset="140,0,115" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="140,0,115" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="140,0,115" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_sidearmR.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="11,18,102" halfExtents="10,10,10" info="HOOK, sidearmR"/>
+            <BoxCollisionShape position="151,47,115" roll="-15" halfExtents="16,2,105" info="sidearmR, frontTop"/>
+            <BoxCollisionShape position="136,-7,115" roll="-15" halfExtents="16,2,105" info="sidearmR, frontBottom"/>
+            <BoxCollisionShape position="127,26,115" roll="-15" halfExtents="2,28,105" info="sidearmR, frontInner"/>
+            <BoxCollisionShape position="161,16,115" roll="-15" halfExtents="2,28,105" info="sidearmR, frontOuter"/>
+            <BoxCollisionShape position="145,21,12" roll="-15" halfExtents="16,28,2" info="sidearmR, front"/>
+            <BoxCollisionShape position="140,12,261" roll="-15" halfExtents="22,41,43" info="sidearmR, back"/>
+            <BoxCollisionShape position="133,-13,29" roll="-15" halfExtents="12,6,17" info="sidearmR, bottom cylinder"/>
+            <BoxCollisionShape position="165,-4,31" roll="-15" halfExtents="7,21,13" info="sidearmR, box"/>
+            <BoxCollisionShape position="153,59,96" roll="-15" halfExtents="6,7,60" info="sidearmR, upper beam"/>
+            <BoxCollisionShape position="143,57,119" roll="-15" halfExtents="3,4,85" info="sidearmR, upper inner beam"/>
+            <BoxCollisionShape position="142,53,212" pitch="21" yaw="-5" roll="-15" halfExtents="3,4,10" info="sidearmR, upper inner beam"/>
+            <BoxCollisionShape position="160,52,119" roll="-15" halfExtents="3,4,85" info="sidearmR, upper outer beam"/>
+            <BoxCollisionShape position="159,48,212" pitch="21" yaw="-5" roll="-15" halfExtents="3,4,10" info="sidearmR, upper outer beam"/>
+            <BoxCollisionShape position="152,54,34" pitch="-46" yaw="14" roll="-15" halfExtents="6,7,10" info="sidearmR, upper beam front"/>
+            <BoxCollisionShape position="152,54,162" pitch="30" yaw="-9" roll="-15" halfExtents="6,7,12" info="sidearmR, upper beam back"/>
+            <BoxCollisionShape position="168,21,119" roll="-15" halfExtents="3,5,109" info="sidearmR, outer beam"/>
+            <BoxCollisionShape position="134,-10,169" roll="-15" halfExtents="6,4,55" info="sidearmR, lower beam front"/>
+            <BoxCollisionShape position="131,-20,217" pitch="-20" roll="-15" yaw="5" halfExtents="6,12,3" info="sidearmR, lower beam middle"/>
+            <BoxCollisionShape position="130,-29,233" roll="-15" halfExtents="6,3,15" info="sidearmR, lower beam back"/>
+
+            <BoxCollisionShape position="145,21,71" halfExtents="10,10,1" info="sidearmR, HOOKBOX"/>
+            <BoxCollisionShape position="145,21,29" halfExtents="10,10,1" info="sidearmR, HOOKBOX"/>
+            <BoxCollisionShape position="145,32,50" halfExtents="10,1,20" info="sidearmR, HOOKBOX"/>
+            <BoxCollisionShape position="145,10,50" halfExtents="10,1,20" info="sidearmR, HOOKBOX"/>
+            <BoxCollisionShape position="156,21,50" halfExtents="1,10,20" info="sidearmR, HOOKBOX"/>
+            <BoxCollisionShape position="134,21,50" halfExtents="1,10,20" info="sidearmR, HOOKBOX"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=100 initialhealth=100 maxhealth=100 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=sidearmRfront radarname = "HIDDEN" >
+        <explosion>
+            <ExplosionPart offset="141,15,-53" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="141,15,-53" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="141,15,-53" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_sidearmRfront.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="145,21,50" halfExtents="10,10,20" info="sidearmRfront, HOOK"/>
+            <BoxCollisionShape position="141,15,-53" roll="-15" halfExtents="27,44,62" info="sidearmRfront"/>
+            <BoxCollisionShape position="153,59,-30" roll="-15" halfExtents="4,2,38" info="sidearmRfront, top"/>
+            <BoxCollisionShape position="153,61,-41" roll="-15" halfExtents="4,4,11" info="sidearmRfront, top"/>
+            <BoxCollisionShape position="153,60,-65" roll="-15" halfExtents="4,3,4" info="sidearmRfront, top"/>
+            <BoxCollisionShape position="153,59,-41" roll="-15" halfExtents="8,2,11" info="sidearmRfront, top"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=100 initialhealth=100 maxhealth=100 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_frontL radarname = "HIDDEN" >
+        <explosion>
+            <ExplosionPart offset="-80,33,-320" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="-80,33,-320" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="-80,33,-320" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_frontL.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="-11,18,58" halfExtents="10,10,10" info="HOOK, frontL"/>
+            <BoxCollisionShape position="-80,33,-320" halfExtents="7,11,54" info="frontL"/>
+            <BoxCollisionShape position="-79,31,-399" halfExtents="3,6,26" info="frontL"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=100 initialhealth=100 maxhealth=100 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_frontR radarname = "HIDDEN" >
+        <explosion>
+            <ExplosionPart offset="80,33,-320" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="80,33,-320" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="80,33,-320" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_frontR.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="11,18,58" halfExtents="10,10,10" info="HOOK, frontR"/>
+            <BoxCollisionShape position="80,33,-320" halfExtents="7,11,54" info="frontR"/>
+            <BoxCollisionShape position="79,31,-399" halfExtents="3,6,26" info="frontR"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=100 initialhealth=100 maxhealth=100 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_partL radarname = "HIDDEN" >
+        <explosion>
+            <ExplosionPart offset="-94,33,-179" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="-94,33,-179" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="-94,33,-179" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_partL.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="-11,18,80" halfExtents="10,10,10" info="HOOK, partL"/>
+            <BoxCollisionShape position="-94,33,-179" halfExtents="11,13,45" info="partL"/>
+            <BoxCollisionShape position="-96,33,-230" halfExtents="13,17,22" info="partL"/>
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=100 initialhealth=100 maxhealth=100 position="0,300,-2000" yaw="180" direction="0,0,0" collisionType=dynamic mass=1000 name=HeavyCruiser_partR radarname = "HIDDEN" >
+        <explosion>
+            <ExplosionPart offset="94,33,-179" minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart offset="94,33,-179" minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart offset="94,33,-179" minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+        <attached>
+            <Model position="0,0,0" direction="-1,0,0" mesh="HeavyCruiser_partR.mesh" scale="40" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="11,18,80" halfExtents="10,10,10" info="HOOK, partR"/>
+            <BoxCollisionShape position="94,33,-179" halfExtents="11,13,45" info="partR"/>
+            <BoxCollisionShape position="96,33,-230" halfExtents="13,17,22" info="partR"/>
+        </collisionShapes>
+    </Pawn-->
+    
+
+    
+    <Light type=directional position="0,0,0" direction="0.253, -0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <SpawnPoint team=0 position="0,0,0" lookat="0,0,-100" spawnclass=SpaceShip pawndesign=HeavyCruiserBody />
+    
+    <!-- <SpawnPoint team=0 position="0,-200,0" lookat="0,-200,-100" spawnclass=SpaceShip pawndesign=HeavyCruiser /> -->
+    <!-- <SpawnPoint team=0 position="0,-100,0" lookat="0,-100,0" spawnclass=SpaceShip pawndesign=spaceshipassff /> -->
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/Hover.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/Hover.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/Hover.oxw	(revision 11817)
@@ -0,0 +1,85 @@
+<LevelInfo
+ name = "Hover level"
+ description = "Level for Minigame Hover"
+ tags = "minigame"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipHover.oxt")
+  include("overlays/HoverHUD.oxo")
+?>
+
+<?lua
+MAZE_NUM_CELLS = 10
+MAZE_CELL_SIZE = 100
+MAZE_CELL_HEIGHT = 30
+MAZE_SIZE = MAZE_NUM_CELLS*MAZE_CELL_SIZE
+?>
+
+<Level
+plugins = hover
+gametype = Hover
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+    gravity      = "0, -200, 0"
+  >
+
+    <StaticEntity position="0,0,0" collisionType="static">
+      <attached>
+        <HoverOrigin
+          numCells="<?lua print(MAZE_NUM_CELLS)?>"
+          cellSize="<?lua print(MAZE_CELL_SIZE)?>"
+          cellHeight="<?lua print(MAZE_CELL_HEIGHT)?>"
+        />
+        <Model
+          position="<?lua print(MAZE_SIZE/2)?>,-16,<?lua print(MAZE_SIZE/2)?>"
+          scale3D="<?lua print(MAZE_SIZE/2)?>,16,<?lua print(MAZE_SIZE/2)?>"
+          mesh="CubeGround.mesh"
+        />
+      </attached> 
+      <collisionShapes>
+        <BoxCollisionShape
+          position="<?lua print(MAZE_SIZE/2)?>,<?lua print(MAZE_CELL_HEIGHT+1)?>,<?lua print(MAZE_SIZE/2)?>"
+          halfExtents="<?lua print(MAZE_SIZE/2)?>,1,<?lua print(MAZE_SIZE/2)?>"
+        />
+        <BoxCollisionShape
+          position="<?lua print(MAZE_SIZE/2)?>,-1,<?lua print(MAZE_SIZE/2)?>"
+          halfExtents="<?lua print(MAZE_SIZE/2)?>,1,<?lua print(MAZE_SIZE/2)?>"
+        />
+      </collisionShapes>
+    </StaticEntity>
+
+    <Light
+      type=directional
+      position="-50,500,-50"
+      direction="0.577, -0.577, 0.577"
+      diffuse="1.0, 0.9, 0.9, 1.0"
+      specular="1.0, 0.9, 0.9, 1.0"
+    />
+    
+    <SpawnPoint
+      team=0
+      position="50,20,50"
+      lookat="100,20,100"
+      spawnclass=HoverShip
+      pawndesign=spaceshiphover
+    />
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/InsideSpaceStation.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/InsideSpaceStation.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/InsideSpaceStation.oxw	(revision 11817)
@@ -0,0 +1,89 @@
+<!-- -->
+<LevelInfo
+ name = "Inside Space Station"
+ description = "Level to test the Space Station"
+ tags = "test"
+ screenshot = "InsideSpaceStation.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/FPS.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.3, 0.3, 0.3"
+   skybox       = "Orxonox/skyBoxBasic"
+   gravity      = "0,-1000,0"
+   negativeWorldRange = "-100000, -100000, -100000"
+   positiveWorldRange = " 100000,  100000,  100000"
+   hasPhysics   = true
+  >
+    <Light type=directional position="0,-100000,0" direction="0.02, -1, 0.05" diffuse="1.0, 1.0, 1.0, 1.0" specular="1.0, 1.0, 1.0, 1.0" />
+
+  <StaticEntity position="0,0,0" direction="1,0,0" pitch=180 collisionType=static mass=100000 friction=0.01 >
+      <attached>
+        <Model position="0,0,0" mesh="ss_tube.mesh" scale3D="100,100,100" />
+	<Model position="500,0,0" mesh="ss_tube.mesh" scale3D="100,100,100" />
+	<Model position="1200,0,0" mesh="ss_tube_x.mesh" scale3D="100,100,100" />
+	<Model position="-5000,0,0" mesh="ss_curve.mesh" scale3D="100,100,100" />
+	<Model position="-250,-16,0" pitch=-90 mesh="ss_flag_room.mesh" scale3D="100,100,100" />
+	<Model position="1200,100,-100" roll=180 mesh="ss_machine.mesh" scale3D="0.15,0.15,0.15" />
+	<Model position="-100,100,0" roll=180 mesh="ss_table.mesh" scale3D="25,25,25" />
+	<Model position="-300,100,0" roll=180 mesh="ss_table_cracked.mesh" scale3D="25,25,25" />
+	<Model position="600,75,0" roll=180 mesh="ss_cylinder.mesh" scale3D="25,25,25" />
+	<Model position="300,50,0" roll=180  pitch=20 mesh="ss_chair.mesh" scale3D="20,20,20" />
+	<Model position="1000,50,0" roll=180 mesh="ss_wall.mesh" scale3D="20,20,20" />
+	<Model position="-830,20,0" roll=180 mesh="ss_flag_aean.mesh" scale3D="40,40,40" />
+	<Model position="-1900,50,0" roll=180 mesh="ss_flag_eu.mesh" scale3D="20,20,20" />
+	<Model position="-1500,50,0" roll=180 mesh="ss_flag_cau.mesh" scale3D="20,20,20" />
+	<Model position="-1650,50,0" roll=180 mesh="ss_flag_csa.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,-100,0" halfExtents="5000000,0,100000" />
+	<BoxCollisionShape position="0,50,0" halfExtents="500000,0,100000" />
+	<BoxCollisionShape position="0,0,100" halfExtents="50000,100000,0" />
+	<BoxCollisionShape position="0,0,-100" halfExtents="500000,100000,0" />
+      </collisionShapes>
+  </StaticEntity>
+
+<?lua
+for i = 1, 10, 1
+do ?>
+    <SpawnPoint position="0,0,0" direction="-1, 0, 0" scale3D="0.5,100,0.5" lookat="0,0,0" spawnclass=FpsPlayer pawndesign=fps />
+<?lua
+end
+?>
+
+
+<?lua
+for i = 1, 200, 1
+do
+j = math.random()
+?>
+  <MovableEntity position="<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000 - 2000) ?>" collisionType=dynamic linearDamping=0.8 angularDamping=0 mass=<?lua print(j * 100) ?> scale=<?lua print(j * 5) ?> rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>" >
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 100) ?>" />
+      </collisionShapes>
+  </MovableEntity>
+<?lua
+end
+?>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/Invaders.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/Invaders.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/Invaders.oxw	(revision 11817)
@@ -0,0 +1,79 @@
+<LevelInfo
+ name = "Orxonox Arcade"
+ description = "2D Arcade shooter. Maximise your points!!!\nTip: try to keep the multiplier high by avoiding shots and enemies."
+ tags = "minigame"
+ screenshot = "orxonoxArcade.png"
+/>
+<?lua
+  include("stats.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipInvader.oxt")
+  include("templates/enemyInvader.oxt")
+  include("overlays/InvaderHUD.oxo")
+?>
+
+<Level
+  plugins = invader
+  gametype = Invader
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+    <!-- ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox" -->
+  <Scene
+    ambientlight = "0.8, 0.7, 0.4"
+    skybox     = "Orxonox/skyBoxBasic"
+  >
+
+  <WorldAmbientSound
+    source="Earth.ogg"
+    looping="true"
+    playOnLoad="true"
+  />
+
+    <!-- <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/> -->
+    <Light type=directional position="1100, 11000, -7000" lookat="0, 0, 0" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=InvaderShip pawndesign=spaceshipinvader />
+
+    <DistanceTrigger name="start" position="-200,0,0" target="Pawn" distance=10 stayActive="true" delay=0 />
+
+
+    <InvaderCenterPoint name=invadercenter />
+    
+    <?lua
+      for i = 1, 300, 1 do
+        j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(math.random()* 40000 + 1000) ?>,-1000,<?lua print(math.random() * 4000 - 2000) ?>"
+      collisionType = dynamic
+      linearDamping = 0.8
+      angularDamping = 0
+      scale = "<?lua print(j * 150)?>"
+      collisiondamage = 0
+      enablecollisiondamage = true
+    >
+      <attached>
+        <Model mass="<?lua print(j * 1000) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 350) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+
+    <?lua
+      end
+    ?>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/MilleniumFalconTest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/MilleniumFalconTest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/MilleniumFalconTest.oxw	(revision 11817)
@@ -0,0 +1,38 @@
+<LevelInfo
+ name = "MilleniumFalconTest"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/HeavyCruiser.oxt")
+?>
+
+<?lua
+  include("templates/MFalcon.oxt")
+  include("templates/endurancetest_template.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=MFalcon />
+
+    <Model mesh="MilleniumFalcon.mesh" position="0,0,0" scale=10/>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/ModularShipsTest0.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/ModularShipsTest0.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/ModularShipsTest0.oxw	(revision 11817)
@@ -0,0 +1,76 @@
+<LevelInfo
+ name = "Modular Ships - Test 0"
+ description = "A level to test the basic functions of modular spaceships using simple boxes."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/HeavyCruiser.oxt")
+  include("templates/ModularSpaceShipTest.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+    
+    <ModularSpaceShip position="0,0,0" health="2000" maxhealth="4000" initialhealth="2000">
+      <templates>
+        <Template link=ModularSpaceShipTest />
+      </templates>
+    </ModularSpaceShip>
+    
+    <StaticEntity position="0,0,60" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+        <attached>
+            <Model position="0,0,0" mesh="cube.mesh" scale3D="10,10,10" />
+        </attached>
+        <collisionShapes>
+        </collisionShapes>
+    </StaticEntity>
+    
+        <StaticEntity position="0,60,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+        <attached>
+            <Model position="0,0,0" mesh="cube.mesh" scale3D="10,10,10" />
+        </attached>
+        <collisionShapes>
+        </collisionShapes>
+    </StaticEntity>
+    
+        <StaticEntity position="0,0,-60" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+        <attached>
+            <Model position="0,0,0" mesh="cube.mesh" scale3D="10,10,10" />
+        </attached>
+        <collisionShapes>
+        </collisionShapes>
+    </StaticEntity>
+    
+    <StaticEntity position="0,-60,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+        <attached>
+            <Model position="0,0,0" mesh="cube.mesh" scale3D="10,10,10" />
+        </attached>
+        <collisionShapes>
+        </collisionShapes>
+    </StaticEntity>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/ModularShipsTest1.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/ModularShipsTest1.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/ModularShipsTest1.oxw	(revision 11817)
@@ -0,0 +1,109 @@
+<LevelInfo
+ name = "Modular Ships - Test 1"
+ description = "A level to test the implementation of HeavyCruiser as modular spaceship."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/HeavyCruiser.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <!-- <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort /> -->
+    <SpawnPoint team=0 position="-500,0,0" lookat="0,0,0" spawnclass=ModularSpaceShip pawndesign=HeavyCruiser />
+    
+    <MovableEntity position="0,0,0" collisionType=dynamic scale=1 linearDamping=0.8 angularDamping=0  collisiondamage=0.005 enablecollisiondamage=true>
+    <attached> 
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="40,40,40" /> 
+        <StaticEntity position="0,90,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" /> 
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" /> 
+            </collisionShapes> 
+        </StaticEntity>
+    </attached> 
+    <collisionShapes> 
+        <BoxCollisionShape position="0,0,0" halfExtents="40,40,40" /> 
+    </collisionShapes> 
+    </MovableEntity>
+    
+    <Pawn health=1000 initialhealth=1000 maxhealth=1000 position="0,-100,-100" direction="0,0,0" collisionType=dynamic mass=1000 name=box radarname = "Pawn 0" >
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="6,6,6" />
+            <Model position="0,-60,0" mesh="cube.mesh" scale3D="30,30,30" />
+            <StaticEntity position="0,-120,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+                <attached> 
+                    <Model position="0,0,0" mesh="crate.mesh" scale3D="6,6,6" />
+                    <Model position="0,0,60" mesh="cube.mesh" scale3D="30,30,30" /> 
+                </attached> 
+                <collisionShapes> 
+                    <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" /> 
+                    <BoxCollisionShape position="0,0,60" halfExtents="30,30,30" /> 
+                </collisionShapes> 
+            </StaticEntity>
+            <StaticEntity position="0,-180,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+                <attached> 
+                    <Model position="0,0,0" mesh="crate.mesh" scale3D="6,6,6" />
+                    <Model position="0,-60,0" mesh="cube.mesh" scale3D="30,30,30" /> 
+                </attached> 
+                <collisionShapes> 
+                    <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" /> 
+                    <BoxCollisionShape position="0,-60,0" halfExtents="30,30,30" /> 
+                </collisionShapes> 
+            </StaticEntity>
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            <BoxCollisionShape position="0,-60,0" halfExtents="30,30,30" />
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn health=1000 initialhealth=1000 maxhealth=1000 position="0,-100,100" direction="0,0,0" collisionType=dynamic mass=1000 name=box radarname = "Pawn 1" >
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="6,6,6" />
+            <Model position="0,-60,0" mesh="cube.mesh" scale3D="30,30,30" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            <BoxCollisionShape position="0,-60,0" halfExtents="30,30,30" />
+        </collisionShapes>
+    </Pawn>
+    
+    <ModularSpaceShip position="0,-100,-200">
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+    </ModularSpaceShip>
+    
+    <ModularSpaceShip position="0,-1000,-200" health="2000" maxhealth="4000" initialhealth="2000">
+      <templates>
+        <Template link=HeavyCruiser />
+      </templates>
+    </ModularSpaceShip>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/NC_StoryModeLevel.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/NC_StoryModeLevel.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/NC_StoryModeLevel.oxw	(revision 11817)
@@ -0,0 +1,65 @@
+<LevelInfo
+ name = "NC StoryMode"
+ description = "A level in which the Campaign Menu is defined, which opens other levels."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/StoryMode.oxt")
+  include("StoryModeHUD2.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/StoryModeEscort.oxt")
+  include("templates/endurancetest_template.oxt")
+?>
+
+<Level  gametype = StoryMode>
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+  <SpawnPoint position="000.000, 000.000, 000.000" spawnclass=StoryModePawn orientation="0, 0, 0, 1" pawndesign=StoryModeEscort /> 
+
+ <NameableStaticEntity levelName="Level 1" position="0,0,-500" direction="0,1,0">
+  <attached>
+    <Model position="0,0,0" mesh="ETH.mesh" scale=80 />
+  </attached>
+ </NameableStaticEntity>
+
+<NameableStaticEntity levelName="Level 2" position="500,0,-1000" direction="0,0,0">
+  <attached>
+    <Model position="0,0,0" mesh="planets/moon.mesh" scale=50 />
+  </attached>
+ </NameableStaticEntity>
+    
+<NameableStaticEntity levelName="Level 3" position="-500,0,-1000" direction="0,1,0">
+  <attached>
+    <Model position="0,0,0" mesh="can.mesh" scale=50 />
+  </attached>
+</NameableStaticEntity>
+
+<NameableStaticEntity levelName="Level 4" position="1000,0,-1500" direction="0,0,0">
+  <attached>
+    <Model position="0,0,0" mesh="cube.mesh" scale=50 />
+  </attached>
+ </NameableStaticEntity>
+
+ <NameableStaticEntity levelName="Level 5" position="-1000,0,-1500" direction="0,0,0">
+  <attached>
+    <Model position="0,0,0" mesh="Pilz.mesh" scale=50 />
+  </attached>
+ </NameableStaticEntity>
+
+  
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/ProtectBoss.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/ProtectBoss.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/ProtectBoss.oxw	(revision 11817)
@@ -0,0 +1,362 @@
+<LevelInfo
+ name = "ProtectBoss"
+ description = "Protect a disabled cargo ship!"
+ tags = "mission"
+ screenshot = "emptylevel.png"
+/>
+
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/HeavyCruiser.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/endurancetest_template.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level gametype="Mission">
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=7
+    position="0.2, 0, 0.1, 0"
+    fontSize="16"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+  />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" /> <!-- AlphaCentauri.ogg, Mars.ogg-->
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <EventMultiTrigger name=spawntrigger>
+      <events>
+        <trigger>
+          <SpawnPoint team=0 position="0,0,1" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+        </trigger>
+      </events>
+    </EventMultiTrigger>
+    
+    <Pawn
+        team      = 0
+        collisionType = kinematic
+        enablecollisiondamage=true
+        collisiondamage = 5
+        position  = "0,0,-2500"
+        mass      = 100000
+        health    = 2500 initialhealth=2500 maxhealth="2500"
+        direction = "1,0,0"
+        rotationaxis="0,0,1" rotationrate="4.5" velocity="0,0,30"
+        vulnerable=true
+        name      = "CargoShip"
+        radarname = "Cargo Ship" >
+      <attached>
+        <DistanceTriggerBeacon name="CargoShip" />
+        <Model mesh="escortShip.mesh" mass=10000 position="0,0,0" scale=100 />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="300,100,200" /> <!-- laenge  ,   dicke    , breite -->
+        <BoxCollisionShape position="-100,-50,-280" halfExtents="220,70,100" />
+        <BoxCollisionShape position="-100,-50,280" halfExtents="220,70,100" />
+      </collisionShapes>
+      <explosion>
+        <ExplosionPart scale = 12 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+        <ExplosionPart scale = 12 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+        <ExplosionPart scale = 12 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        <ExplosionPart offset="94,33,-50" delay=1 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+        <ExplosionPart offset="94,33,-50" delay=1 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+        <ExplosionPart offset="94,33,-50" delay=1 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+   
+        <ExplosionPart scale = 5 mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart scale = 5 mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart delay=0.8 scale = 2.5 mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart delay=0.8 scale = 2.5 mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart delay=0.8 scale = 2.5 mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+        <ExplosionPart delay=0.8 scale = 2.5 mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+       
+        <ExplosionPart offset="20,13,-15" scale=7 delay=1.3 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+        <ExplosionPart offset="30,13,-15" scale=7 delay=1.3 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+        <ExplosionPart offset="20,13,-15" scale=7 delay=1.3 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        <ExplosionPart offset="-20,-13,-15" scale=5 delay=1.8 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+        <ExplosionPart offset="-20,-13,-15" scale=5 delay=1.8 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+        <ExplosionPart offset="-20,-13,-15" scale=5 delay=1.8 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+      </explosion>
+    </Pawn>
+
+    <!-- triggers some time after start -->
+    <DistanceTrigger name="someTimeAfterStart" beaconMode=identify position="0,0,1000" distance=1000 target="Pawn" targetname="CargoShip" />
+
+    <!-- triggers when first quest is completed -->
+    <DistanceTrigger name="passedAsteroidFieldOne" beaconMode=identify position="0,0,3000" distance=1000 target="Pawn" targetname="CargoShip" />
+
+    <!-- triggers when first pirate wave is defeated -->
+
+    <Trigger name="firstPirateWaveKilled" mode="and">
+      <?lua
+        for n = 1, 3, 1 do
+          print("<EventTrigger activations=1 stayactive=true><events><trigger><EventListener event=p" .. n .. "/></trigger></events></EventTrigger>")
+        end
+      ?>
+    </Trigger>
+
+    <!-- triggers when second pirate wave is defeated -->
+    <Trigger name="secondPirateWaveKilled" mode="and">
+      <?lua
+        for n = 1, 6, 1 do
+          print("<EventTrigger activations=1 stayactive=true><events><trigger><EventListener event=p1" .. n .. "/></trigger></events></EventTrigger>")
+        end
+      ?>
+    </Trigger>
+
+    <!-- triggers some time after the second pirate wave was defeated -->
+    <Trigger name="thirdPirateWaveStarting" delay=15>
+      <EventTrigger activations="1" stayactive="true" >
+        <events>
+          <trigger>
+             <EventListener event="secondPirateWaveKilled" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <!-- triggers when third pirate wave is defeated -->
+    <Trigger name="thirdPirateWaveKilled" mode="and">
+      <?lua
+        for n = 1, 7, 1 do
+          print("<EventTrigger activations=1 stayactive=true><events><trigger><EventListener event=p2" .. n .. "/></trigger></events></EventTrigger>")
+        end
+      ?>
+    </Trigger>
+
+    <Trigger name="succeedMission" mode=and delay=1>
+      <EventTrigger activations="1" stayactive="true" >
+        <events>
+          <trigger>
+             <EventListener event="thirdPirateWaveKilled" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" stayactive="false" name="cargoShipStillAlive" invert=true>
+        <events>
+          <trigger>
+             <EventListener event="CargoShip" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <EventTrigger activations="1" stayactive="true" name="failMission" delay=0.1>
+      <events>
+        <trigger>
+           <EventListener event="CargoShip" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <!-- create asteroids and pickups -->
+    <?lua
+      function asteroidMesh()
+        x = math.random(8)
+        if x < 7 then
+          return "ast" .. x .. ".mesh"
+        elseif x == 7 then
+          return "asteroid_ice.mesh"
+        else
+          return "asteroid_UV.mesh"
+        end
+      end
+
+      for count = 1, 60, 1 do
+        x = math.random(-1000, 1000)
+        y = math.random(-1000, 1000)
+        z = 125 * count + math.random(-250, 250)
+        vmax = 7
+        if count > 30 then
+          vmax = 2
+        end
+        rx = math.random(-vmax, vmax)
+        ry = math.random(-vmax, vmax)
+        rz = math.random(-vmax, vmax)
+        vx = math.random(-vmax, vmax)
+        vy = math.random(-vmax, vmax)
+        vz = math.random(-vmax, vmax)
+        rr = math.random() * 10
+        print("<ShootableObstacle team=1 enablecollisiondamage=true collisiondamage=10 health=100 maxhealth=100 initialhealth=100 position=\"" .. x .. "," .. y .. "," .. z .. "\" direction=\"0,0,-1\" velocity=\"" .. vx .. "," .. vy .. "," .. vz .. "\"rotationaxis=\"" .. rx .. "," .. ry .. "," .. rz .. "\" rotationrate=" .. rr .. " collisionType=dynamic mass=1 name=asteroid radarname=Asteroid> <attached> <Model position=\"0,0,0\" mesh=\"" .. asteroidMesh() .. "\" scale3D=\"10,10,10\" /> </attached> <collisionShapes> <SphereCollisionShape position=\"0,0,0\" radius=5 /> </collisionShapes> <controller> <WaypointController team=1> </WaypointController> </controller> <explosion> <ExplosionPart minspeed=0 maxspeed=0 effect1=\"orxonox/explosion_flash2\" effect2=\"orxonox/explosion_flame2\" /> <ExplosionPart minspeed=0 maxspeed=0 effect1=\"orxonox/explosion_shockwave2\" effect2=\"orxonox/explosion_sparks2\" /> <ExplosionPart minspeed=0 maxspeed=0 effect1=\"orxonox/explosion_streak2\" effect2=\"orxonox/explosion_afterglow\" /> </explosion> </ShootableObstacle>")
+      end
+
+      for count = 1, 60, 1 do
+        x = math.random(-1000, 1000)
+        y = math.random(-1000, 1000)
+        z = 3000 + 125 * count + math.random(-250, 250)
+        typenum = math.random(11)
+        type = ""
+        if typenum == 1 then
+          type = "smallmunition"
+        elseif typenum == 2 then
+          type = "mediummunition"
+        elseif typenum == 3 then
+          type = "hugemunition"
+        elseif typenum == 4 then
+          type = "smallhealth"
+        elseif typenum == 5 then
+          type = "mediumhealth"
+        elseif typenum == 6 then
+          type = "hugehealth"
+        elseif typenum == 7 then
+          type = "crazyhealth"
+        elseif typenum == 8 then
+          type = "smallshield"
+        elseif typenum == 9 then
+          type = "mediumshield"
+        elseif typenum == 10 then
+          type = "hugeshield"
+        else
+          type = "drone"
+        end
+        type = type .. "pickup"
+        print("<PickupSpawner pickup=\"" .. type .. "\" position=\"" .. x .. "," .. y .. "," .. z .. "\" triggerDistance=10 respawnTime=5 maxSpawnedItems=1 />")
+      end
+    ?>
+
+    <!-- start first quest -->
+    <QuestEffectBeacon times=1>
+      <effects>
+        <AddQuest questId="ProtectBoss.AsteroidField" />
+      </effects>
+      <events>
+        <execute>
+          <EventListener event=spawntrigger />
+        </execute>
+      </events>
+    </QuestEffectBeacon>
+
+    <!-- start second quest (doesn't work yet) -->
+    <QuestEffectBeacon times=1>
+      <effects>
+        <CompleteQuest questId="ProtectBoss.AsteroidField" />
+        <!--AddQuest questId="ProtectBoss.PirateAttack" /-->
+      </effects>
+      <events>
+        <execute>
+          <EventListener event=passedAsteroidFieldOne />
+        </execute>
+      </events>
+    </QuestEffectBeacon>
+
+    <SimpleNotification message="Protect the cargo ship! (Info: F3)" broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=spawntrigger />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <LocalQuest id="ProtectBoss.AsteroidField">
+        <QuestDescription title="Protect the Cargo Ship" description="The cargo ship in front of you is disabled and is drifting uncontrolled! Shoot the asteroids out of the way to protect it!" failmessage="The cargo ship has been hit!" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="ProtectBoss.PirateAttack" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="ProtectBoss.PirateAttack">
+      <QuestDescription title="Pirate Attack" description="Protect the cargo ship from the attacking pirates!" failmessage="The pirates boarded the cargo ship!" completeMessage="" />
+    </LocalQuest>
+
+    <SimpleNotification message="There are pirates around!" broadcast="true" >
+        <events>
+            <trigger>
+                <EventListener event="someTimeAfterStart" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="The cargo ship got destroyed! Game over!" broadcast=true >
+      <events>
+            <trigger>
+                <EventListener event="CargoShip" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="A second pirate wave is approaching!" broadcast=true >
+      <events>
+            <trigger>
+                <EventListener event="firstPirateWaveKilled" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="The third and last pirate wave is near!" broadcast=true >
+      <events>
+            <trigger>
+                <EventListener event="secondPirateWaveKilled" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="The cargo ship is out of danger. You made it!" broadcast=true >
+      <events>
+            <trigger>
+                <EventListener event="succeedMission" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- A function to put pirates to a certain location -->
+    <?lua
+      function placePirate(posX, posY, posZ, name, trigger)
+        print("<SpaceShip mass=10 health=25 initialhealth=25 maxhealth=25 shieldhealth=10 maxshieldhealth=10 initialshieldhealth=10 shieldabsorption=0.3 shieldrechargerate=1 shieldrechargewaittime=1 primaryThrust=20 auxiliaryThrust=5 rotationThrust=5 boostpower=2 boostrate=1 boostCooldownDuration = 50 accuracy=1 position=\"" .. posX .. "," .. posY .. "," .. posZ .. "\" name=\"" .. name .. "\" radarname=Pirate><!--events><visibility><EventListener event=\"" .. trigger .. "\"/></visibility><activity><EventListener event=\"" .. trigger .. "\"/></activity></events--><templates><Template link=spaceshippirate /></templates><controller><WaypointPatrolController alertnessradius=2700 attackradius=1850 team=1 active=true><waypoints><StaticEntity position=\"" .. posX .. "," .. posY .. "," .. posZ .. "\"/><StaticEntity position=\"" .. (posX + 100) .. "," .. posY .. "," .. posZ .. "\"/><!--Model mesh=\"cube.mesh\" scale=0 position=\"-1300,-600,900\" /><Model mesh=\"cube.mesh\" scale=0 position=\"0,0,0\" /--></waypoints><events><activity><EventListener event=attack /></activity></events></WaypointPatrolController></controller></SpaceShip>")
+      end
+    ?>
+
+    <?lua
+      placePirate(0, 0, 4800, "p1", "passedAsteroidFieldOne")
+      placePirate(50, 0, 4900, "p2", "passedAsteroidFieldOne")
+      placePirate(0, 50, 5000, "p3", "passedAsteroidFieldOne")
+      placePirate(0, 0, 6500, "p11", "firstPirateWaveKilled")
+      placePirate(50, 0, 6600, "p12", "firstPirateWaveKilled")
+      placePirate(-50, 0, 6700, "p13", "firstPirateWaveKilled")
+      placePirate(0, 50, 6800, "p14", "firstPirateWaveKilled")
+      placePirate(0, -50, 6900, "p15", "firstPirateWaveKilled")
+      placePirate(0, 0, 7000, "p16", "firstPirateWaveKilled")
+      placePirate(0, 0, 8000, "p21", "thirdPirateWaveStarting")
+      placePirate(50, 0, 8100, "p22", "thirdPirateWaveStarting")
+      placePirate(-50, 0, 8200, "p23", "thirdPirateWaveStarting")
+      placePirate(0, 50, 8300, "p24", "thirdPirateWaveStarting")
+      placePirate(0, -50, 8400, "p25", "thirdPirateWaveStarting")
+      placePirate(50, 50, 8500, "p26", "thirdPirateWaveStarting")
+      placePirate(-50, -50, 8600, "p27", "thirdPirateWaveStarting")
+    ?>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/SOB.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/SOB.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/SOB.oxw	(revision 11817)
@@ -0,0 +1,776 @@
+<LevelInfo
+	name = "Super Orxo Bros."
+	description = "The retro-game Super Mario Bros. in Orxonox."
+	tags = "minigame"
+	screenshot = "SOB.png"
+	/>
+
+	<?lua
+	include("stats.oxo")
+	include("templates/lodInformation.oxt")
+	include("overlays/SOBHUD.oxo")
+	?>
+
+
+
+	<Template name=mushroom defaults=0>
+		<SOBMushroom collisionType="dynamic" speed=30>
+			<attached>
+				<Model mesh="Pilz.mesh" position="0,0,21" scale=3 pitch=90/> 
+			</attached>
+			<collisionShapes>
+				<BoxCollisionShape position="0,0,20" halfExtents="5,5,5" />
+			</collisionShapes>
+		</SOBMushroom>
+	</Template>
+
+	<Template name=coin defaults=0 >
+		<SOBCoin speed = 15 lifetime = 0.7>
+			<attached>
+				<Model mesh="Coin.mesh" position="0,0,11" scale=3 pitch=-90 roll=90/> 
+			</attached>
+			
+		</SOBCoin>
+	</Template>
+
+
+
+	<Template name=sobfigurecameras defaults=0>
+		<SOBFigure>
+			<camerapositions>
+				<CameraPosition position="0,-150,30" absolute=true mouselook=false drag=false direction="0,1,0"/>
+			</camerapositions>
+		</SOBFigure>
+	</Template>
+
+
+
+
+	<Template name=sobFigureTemplate>
+		<SOBFigure camerapositiontemplate=sobfigurecameras collisionType="dynamic" position="0,0,30">
+			<attached>
+				<Model  mesh="orxo.mesh" position = "0,0,12" scale=2.5 pitch=0 roll=90 yaw=90/>
+				<ParticleSpawner source="Orxonox/fire4" startdelay=0  position="-4,0,0" visible="false"/>
+			</attached>
+
+			<collisionShapes>
+				<BoxCollisionShape position="0,0,2" halfExtents="3,1,10" />
+			</collisionShapes>
+
+
+		</SOBFigure>
+	</Template> 
+
+
+	<Template name=fireball>
+		<SOBFireball collisionType="dynamic" speed=90>
+			<attached>
+				<Model mesh="planets/sol.mesh" position="0,0,0" scale=3 pitch=90/> 
+
+				<ParticleSpawner source="Orxonox/fire4" startdelay=0  position="-4,0,0" visible="false"/>
+				
+			</attached>
+			<collisionShapes>
+				<SphereCollisionShape position="0,0,0" radius="3" /> 			
+			</collisionShapes>
+		</SOBFireball>
+	</Template>
+
+	<Template name=gumbaShootable>
+		<SOBGumba collisionType="dynamic" speed=60>
+			<attached>
+				<Model mesh="Goomba.mesh" position="0,0,1" scale=3 pitch=90/> 				
+			</attached>
+			<collisionShapes>
+				<BoxCollisionShape position="0,0,0" halfExtents="5,5,3" /> 			
+			</collisionShapes>
+		</SOBGumba>
+	</Template>
+
+
+	<Level
+		plugins = "superorxobros"
+		gametype = "SOB"
+		>-
+
+
+		<templates>
+			<Template link=lodtemplate_default />
+		</templates>
+		<?lua include("includes/notifications.oxi") ?>
+
+		<WorldAmbientSound source="Ganymede.ogg" looping="true" playOnLoad="true"/>
+
+
+		<Scene ambientlight="1.0, 1.0, 1.0" skybox="Orxonox/skyBoxBasic">
+			<Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+			<SpawnPoint position="1984,-5,88 " orientation="0.534038, 0.563456, 0.212168, 0.593553" />
+
+
+
+			<MovableEntity >
+				<attached>
+					<SOBCenterpoint name=jumpcenter cameraOffset="10" figureTemplate=sobFigureTemplate>
+						<attached>  
+						</attached>
+					</SOBCenterpoint>
+
+				</attached>
+			</MovableEntity>
+
+
+
+
+
+
+
+					<SOBGumba collisionType="dynamic" speed=40 position = "240,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,1" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=30 position = "420,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+					<SOBGumba collisionType="dynamic" speed=30 position = "500,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=30 position = "510,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+					<SOBGumba collisionType="dynamic" speed=30 position = "930,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=20 position = "940,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=30 position = "1180,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=20 position = "1190,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=30 position = "1320,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<SOBGumba collisionType="dynamic" speed=20 position = "1330,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=3 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="5,5,3" /> 			
+						</collisionShapes>
+					</SOBGumba>
+
+					<!--GumbaBoss-->
+					<SOBGumbaBoss collisionType="dynamic" speed=20 position = "1750,0,0">
+						<attached>
+							<Model mesh="Goomba.mesh" position="0,0,21" scale=6 pitch=90/> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,20" halfExtents="10,10,6" /> 			
+						</collisionShapes>
+					</SOBGumbaBoss>
+x	
+
+					<!--CollisionShape for Gumba-->
+					<StaticEntity collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,-20" halfExtents="5,5,5" />
+							<BoxCollisionShape position="890,0,-20" halfExtents="5,5,5" />
+							
+							
+							
+							
+						</collisionShapes>
+					</StaticEntity>
+
+
+					<!-- Boden 1 -->
+					<Model mesh="Cube2.12.mesh" position="0,0,-30" scale=10 Pitch=90/> 					<!-- B1.1 -->
+					<Model mesh="Cube2.12.mesh" position="120,0,-30" scale=10 Pitch=90/> 				<!-- B1.2-->
+					<Model mesh="Cube2.12.mesh" position="240,0,-30" scale=10 Pitch=90/> 				<!-- B1.3 -->
+					<Model mesh="Cube2.12.mesh" position="360,0,-30" scale=10 Pitch=90/> 				<!-- B1.4 -->
+					<Model mesh="Cube2.12.mesh" position="480,0,-30" scale=10 Pitch=90/> 				<!-- B1.5 -->
+					<Model mesh="Cube2.6.mesh" position="600,0,-30" scale=10 Pitch=90/> 				<!-- B1.6 -->
+					<Model mesh="Cube2.3.mesh" position="660,0,-30" scale=10 Pitch=90/> 				<!-- B1.7 -->
+
+
+					<StaticEntity collisionType="static" mass='-1'>
+						<collisionShapes>
+							<BoxCollisionShape position="340,0,-20" halfExtents="345,5,5" />
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+					<!-- Luft 1 -->
+
+
+					<SOBQBlock collisionType="static" type="Coin" position="170,0,20" mass='-1'> 						 	<!-- L1.1 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90 />
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/> 
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<SOBQBlock collisionType="static" type="Coin" position="230,0,60" mass='-1' > 
+						<attached>
+							<Model mesh="QCube.mesh"  scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>									<!-- L1.2 --> 
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" /> 			
+						</collisionShapes>
+					</SOBQBlock>
+
+					<Model mesh="Cube1.1.mesh" position="210,0,20" scale=10 /> 												<!-- L1.3 -->
+
+
+					<SOBQBlock collisionType="static" type="Mushroom" position="220,0,20" mass='-1'><!--ITEM-->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/> 													<!-- L1.4 --> 
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" /><!-- 3 -->
+						</collisionShapes>
+					</SOBQBlock>
+
+					<Model mesh="Cube1.1.mesh" position="230,0,20" scale=10/> 												<!-- L1.5 -->
+
+					<SOBQBlock collisionType="static" type="Coin" position="240,0,20" mass='-1'><!-- ? Block --> 
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/> 
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/> 								<!-- L1.6 -->
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock> 
+					
+					<Model mesh="Cube1.1.mesh" position="250,0,20" scale=10/> 												<!-- L1.7 -->
+					<!-- Rohre-->
+					<Model mesh="Rohr.mesh" position="295,5,-35" scale=10 roll=90 yaw=90 pitch=-90/> 						<!-- L1.8 -->
+					<Model mesh="Rohr.mesh" position="395,5,-25" scale=10 roll=90 yaw=90 pitch=-90/>						<!-- L1.9 -->
+					<Model mesh="Rohr.mesh" position="475,5,-15" scale=10 roll=90 yaw=90 pitch=-90 />						<!-- L1.10 -->
+					<Model mesh="Rohr.mesh" position="585,5,-15" scale=10 roll=90 yaw=90 pitch=-90 />						<!-- L1.11 -->	
+
+					<SOBQBlock collisionType="static" type="Mushroom" position="650,0,30" mass='-1'>
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/> 													<!-- L1.12 --> 
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>			
+					
+					
+
+
+
+
+					<StaticEntity collisionType="static"  mass='-1'>
+						<collisionShapes>
+							
+							<BoxCollisionShape position="210,0,20" halfExtents="5,5,5" /> 						<!-- 1.3 -->
+							<BoxCollisionShape position="230,0,20" halfExtents="5,5,5" /> 						<!-- 1.5 -->
+							<BoxCollisionShape position="250,0,20" halfExtents="5,5,5" /> 						<!-- 1.7 -->
+							
+
+						</collisionShapes>
+					</StaticEntity>
+
+
+					<StaticEntity collisionType="static" >
+						<collisionShapes>
+							
+
+							<BoxCollisionShape position="295,0,-4" halfExtents="12,5,12" /> 					<!-- 1.8 -->
+							<BoxCollisionShape position="395,0,1" halfExtents="12,5,17" /> 						<!-- 1.9 -->
+							<BoxCollisionShape position="475,0,6" halfExtents="12,5,22" /> 						<!-- 1.10 -->
+							<BoxCollisionShape position="585,0,6" halfExtents="12,5,22" /> 						<!-- 1.11 -->
+
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+
+
+
+					<!-- Boden 2 -->
+					<Model mesh="Cube2.12.mesh" position="710,0,-30" scale=10 Pitch=90/>						<!-- B2.1 -->
+					<Model mesh="Cube2.3.mesh" position="830,0,-30" scale=10 Pitch=90/>							<!-- B2.2 -->
+
+					<StaticEntity collisionType="static" mass='-1'>
+						<collisionShapes>
+							<BoxCollisionShape position="780,0,-20" halfExtents="75,5,5" />
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+
+					<!-- Luft 2 -->
+					<Model mesh="Cube1.1.mesh" position="770,0,20" scale=10/>									<!-- L2.1 -->
+
+					<SOBQBlock collisionType="static" type="Mushroom" position="780,0,20" mass='-1'>			<!-- L2.2 -->
+						<attached>
+							<Model mesh="QCube.mesh"  scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<Model mesh="Cube1.1.mesh" position="790,0,20" scale=10/>									<!-- L2.3 -->
+					<Model mesh="Cube1.6.mesh" position="800,0,60" scale=10/>									<!-- L2.4 -->
+					<Model mesh="Cube1.1.mesh" position="860,0,60" scale=10/>									<!-- L2.5 -->
+					<Model mesh="Cube1.1.mesh" position="870,0,60" scale=10/>									<!-- L2.6 -->
+
+					<StaticEntity collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="770,0,20" halfExtents="5,5,5" />									<!-- 2.1 -->
+							
+							<BoxCollisionShape position="790,0,20" halfExtents="5,5,5" />									<!-- 2.3 -->
+							<BoxCollisionShape position="835,0,60" halfExtents="40,5,5" />									<!-- 2.4 to 2.6 -->
+
+
+
+
+						</collisionShapes>
+					</StaticEntity>
+					
+
+					<!-- Luft 3 -->
+					<Model mesh="Cube1.3.mesh" position="910,0,60" scale=10/> 												<!-- L3.1 -->
+
+					<SOBQBlock collisionType="static" type="Coin" position="940,0,60" mass='-1'> 				 			<!-- L3.2 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<SOBQBlock collisionType="static" type="Mushroom" position="940,0,20" mass='-1'> 						<!-- L3.3 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+							
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<Model mesh="Cube1.1.mesh" position="1000,0,20" scale=10/>												<!-- L3.4 -->
+
+
+					<SOBQBlock collisionType="static" type="Mushroom" position="1010,0,20" mass='-1'> 						 <!-- L3.5 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<SOBQBlock collisionType="static" type="Coin" position="1060,0,20" mass='-1'> 							<!-- L3.6 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					
+					<SOBQBlock collisionType="static" type="Mushroom" position="1090,0,60" mass='-1'> 						 <!-- L3.7 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<SOBQBlock collisionType="static" type="Coin" position="1090,0,20" mass='-1'> 							<!-- L3.8 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+					
+					<SOBQBlock collisionType="static" type="Coin" position="1120,0,20" mass='-1'> 							<!-- L3.9 -->
+						<attached>
+							<Model mesh="QCube.mesh" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>					
+
+					<Model mesh="Cube1.1.mesh" position="1180,0,20" scale=10/> 												<!-- L3.10 -->
+
+					<Model mesh="Cube1.3.mesh" position="1210,0,60" scale=10/> 												<!-- L3.11 -->
+
+					<Model mesh="Cube1.1.mesh" position="1280,0,60" scale=10/> 												<!-- L3.12 -->
+
+					<SOBQBlock collisionType="static" type="Coin" position="1290,0,60" mass='-1'> 							<!-- L3.13 -->
+						<attached>
+							<Model mesh="QCube.mesh" type="Mushroom" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+
+					<SOBQBlock collisionType="static" type="Coin" position="1300,0,60" mass='-1'> 							<!-- L3.14 -->
+						<attached>
+							<Model mesh="QCube.mesh" type="Mushroom" scale=10 pitch=90/>
+							<Model mesh="QCube-grey.mesh" scale=10 pitch=90 visible=false/>
+						</attached>
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBQBlock>
+
+					<Model mesh="Cube1.1.mesh" position="1310,0,60" scale=10/> 												<!-- L3.15 -->
+					<Model mesh="Cube1.1.mesh" position="1290,0,20" scale=10/> 												<!-- L3.16 --> 
+					<Model mesh="Cube1.1.mesh" position="1300,0,20" scale=10/> 												<!-- L3.17 -->
+					
+
+					
+					<Model mesh="Dreieck.mesh" position="1370,0,-10" scale=10 Roll=90 Pitch=90 yaw=90/> 					<!-- L3.18 --> 
+					<Model mesh="Dreieck.mesh" position="1400,0,-10" scale=10 Roll=90 Pitch=-90 yaw=90/> 					<!-- L3.19 -->
+					<Model mesh="Dreieck_links+1.mesh" position="1510,0,-10" scale=10 Roll=90 Pitch=90 yaw=90/> 			<!-- L3.20 -->  
+					
+
+
+					<StaticEntity collisionType="static">
+						<collisionShapes>
+							
+							<BoxCollisionShape position="1355,0,-10" halfExtents="20,5,5" /> 								<!-- 3.18 -->
+							<BoxCollisionShape position="1360,0,0" halfExtents="15,5,5" />
+							<BoxCollisionShape position="1365,0,10" halfExtents="10,5,5" />
+							<BoxCollisionShape position="1370,0,20" halfExtents="5,5,5" />
+
+							<BoxCollisionShape position="1415,0,-10" halfExtents="20,5,5" /> 								<!-- 3.19--> 
+							<BoxCollisionShape position="1410,0,0" halfExtents="15,5,5" />
+							<BoxCollisionShape position="1405,0,10" halfExtents="10,5,5" />
+							<BoxCollisionShape position="1400,0,20" halfExtents="5,5,5" />
+
+							<BoxCollisionShape position="1500,0,-10" halfExtents="25,5,5" /> 								<!-- 3.20 -->
+							<BoxCollisionShape position="1505,0,0" halfExtents="20,5,5" />
+							<BoxCollisionShape position="1510,0,10" halfExtents="15,5,5" />
+							<BoxCollisionShape position="1515,0,20" halfExtents="10,5,5" />
+							
+
+
+
+
+						</collisionShapes>
+					</StaticEntity>
+
+					<StaticEntity collisionType="static" mass='-1'>
+						<collisionShapes>
+							<BoxCollisionShape position="920,0,60" halfExtents="15,5,5" /> 							<!-- 3.1 -->
+
+							<BoxCollisionShape position="1000,0,20" halfExtents="5,5,5" /> 							<!-- 3.4 -->
+
+
+							<BoxCollisionShape position="1180,0,20" halfExtents="5,5,5" /> 							<!-- 3.10 -->
+							<BoxCollisionShape position="1220,0,60" halfExtents="15,5,5" /> 						<!-- 3.11 -->
+							<BoxCollisionShape position="1280,0,60" halfExtents="5,5,5" /> 							<!-- 3.12 -->
+							<BoxCollisionShape position="1310,0,60" halfExtents="5,5,5" /> 							<!-- 3.15 -->
+							<BoxCollisionShape position="1300,0,20" halfExtents="10,5,5" /> 						<!-- 3.16 and 3.17-->
+							
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+					<!-- Boden3 -->
+					<Model mesh="Cube2.12.mesh" position="890,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="1010,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="1130,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="1250,0,-30" scale=10 Pitch=90/>
+
+					<Model mesh="Cube2.12.mesh" position="1370,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.2.mesh" position="1490,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.2.mesh" position="1510,0,-30" scale=10 Pitch=90/>
+					
+
+					<StaticEntity collisionType="static" mass='-1'>
+						<collisionShapes>
+							<BoxCollisionShape position="1205,0,-20" halfExtents="320,5,5" />
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+
+					<!-- Luft4 (BossAbschnitt)-->
+					<Model mesh="Dreieck.mesh" position="1560,0,-10" scale=10 Roll=90 Pitch=-90 yaw=90/> 			<!-- L4.1 -->
+
+					<Model mesh="Rohr.mesh" position="1645,5,-35" scale=10  roll=90 yaw=90 pitch=-90 /> 			<!-- L4.2 -->
+					<Model mesh="Rohr.mesh" position="1805,5,-35" scale=10  roll=90 yaw=90 pitch=-90 /> 			<!-- L4.7 -->
+					<Model mesh="Dreieckgross.mesh" position="1850,0,-10" scale=10 pitch=90 /> 						<!-- L4.8 -->
+
+
+
+
+					<Model mesh="Schloss.mesh" position="2050,40,80" scale=15 pitch=90/>					<!-- L4.12 -->
+					<Model mesh="Fahne.mesh" position="1984,-5,88" scale=10 pitch=90/>						<!-- L4.11 -->
+					<Model mesh="Fahnenstange.mesh" position="1990,0,95" pitch=90 scale=3/>					<!-- L4.10 -->
+					<Model mesh="Fundament.mesh" position="1990,0,-10" scale=10 yaw=180/>					<!-- L4.9 -->
+
+
+
+					
+					<!-- FLAG -->
+					<SOBFlagstone points = 100  position="1990,0,10" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 200  position="1990,0,20" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 400  position="1990,0,30" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 800  position="1990,0,40" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 1600  position="1990,0,50" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 2200  position="1990,0,60" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 2700  position="1990,0,70" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 3400  position="1990,0,80" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+					<SOBFlagstone points = 4000  position="1990,0,90" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBFlagstone>
+
+
+					<!-- Castlestone -->
+					<SOBCastlestone position="2060,0,-10" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBCastlestone>
+
+					<SOBCastlestone position="2050,40,-10" collisionType="static">
+						<collisionShapes>
+							<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+						</collisionShapes>
+					</SOBCastlestone>
+					<StaticEntity collisionType="static" mass='-1'>
+						<collisionShapes>
+							<BoxCollisionShape position="2050,20,-20" halfExtents="5,20,5" />
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+					<StaticEntity collisionType="static">
+						<collisionShapes>
+
+							<BoxCollisionShape position="1575,0,-10" halfExtents="20,5,5" /> 					<!-- 4.1--> 
+							<BoxCollisionShape position="1570,0,0" halfExtents="15,5,5" />
+							<BoxCollisionShape position="1565,0,10" halfExtents="10,5,5" />
+							<BoxCollisionShape position="1560,0,20" halfExtents="5,5,5" />
+
+							<BoxCollisionShape position="1645,0,-4" halfExtents="12,5,12" /> 					<!-- 4.2 -->
+
+
+							<BoxCollisionShape position="1805,0,-4" halfExtents="12,5,12" /> 					<!-- 4.7 -->
+
+							<BoxCollisionShape position="1860,0,-10" halfExtents="45,5,5" /> 					<!-- 4.8 -->
+							<BoxCollisionShape position="1865,0,0" halfExtents="40,5,5" />
+							<BoxCollisionShape position="1870,0,10" halfExtents="35,5,5" />
+							<BoxCollisionShape position="1875,0,20" halfExtents="30,5,5" />
+							<BoxCollisionShape position="1880,0,30" halfExtents="25,5,5" />
+							<BoxCollisionShape position="1885,0,40" halfExtents="20,5,5" />
+							<BoxCollisionShape position="1890,0,50" halfExtents="15,5,5" />
+							<BoxCollisionShape position="1895,0,60" halfExtents="10,5,5" />
+							<BoxCollisionShape position="1990,0,125" halfExtents="5,5,30" />
+							<BoxCollisionShape position="1940,0,150" halfExtents="45,5,5" />
+							
+
+
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+
+					
+
+					//Boden4
+					<Model mesh="Cube2.12.mesh" position="1560,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="1680,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="1800,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="1920,0,-30" scale=10 Pitch=90/>
+					<Model mesh="Cube2.12.mesh" position="2040,0,-30" scale=10 Pitch=90/>
+
+
+					
+					<Model mesh="Cube1.3.mesh" position="1990,10,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.3.mesh" position="1990,20,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.3.mesh" position="1990,30,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.3.mesh" position="1990,40,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.3.mesh" position="1960,10,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.1.mesh" position="1980,20,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.1.mesh" position="1970,20,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.1.mesh" position="1980,30,-20" scale=10 Pitch=90/>
+
+					<Model mesh="Cube1.1.mesh" position="2000,50,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.1.mesh" position="2010,50,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.1.mesh" position="2010,60,-20" scale=10 Pitch=90/>
+					
+
+					<Model mesh="Cube1.6.mesh" position="2020,10,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2020,20,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2020,30,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2020,40,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2020,50,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2020,60,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2020,70,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2080,10,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2080,20,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2080,30,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2080,40,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.6.mesh" position="2080,50,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.3.mesh" position="2080,60,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.1.mesh" position="2110,60,-20" scale=10 Pitch=90/>
+					<Model mesh="Cube1.3.mesh" position="2080,70,-20" scale=10 Pitch=90/>
+
+					
+
+					<StaticEntity collisionType="static" mass='-1'>
+						<collisionShapes>
+							<BoxCollisionShape position="1855,0,-20" halfExtents="300,5,5" />
+						</collisionShapes>
+					</StaticEntity>
+
+
+
+
+
+
+					
+
+
+				</Scene>
+			</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/StoryModeMap.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/StoryModeMap.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/StoryModeMap.oxw	(revision 11817)
@@ -0,0 +1,70 @@
+
+
+<LevelInfo
+ name = "StoryModeMap"
+ description = "The Campaign Menu Map with all the Campaignmissons in it"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("StoryModeHUD.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/StoryMode.oxt")
+?>
+
+<Level
+gametype = StoryMode
+>
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.2, 0.2, 0.2"
+    skybox       = "Orxonox/Starbox"
+  >
+
+
+    <StaticEntity position="0,0,0" direction="0,0,0" >
+      <attached>
+
+        <Model position="600,370,0" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="600,370,-80"  material="Flares/lensflare" scale=4.5 />
+  
+        <Model position="100,350,-250" mesh="planets/moon.mesh" scale=100  />
+        <Billboard colour="1,1,0.05" position="100,350,-330"  material="Flares/lensflare" scale=4.5 />
+
+        <Model position="-600,250,-500" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="-600,250,-580"  material="Flares/lensflare" scale=5 />
+
+        <Model position="-1000,50,-750" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="-1000,50,-830"  material="Flares/lensflare" scale=5 />
+
+        <Model position="-900,-400,-1000" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="-900,-400,-1080"  material="Flares/lensflare" scale=5 />
+
+        <Model position="-500,-700,-1250" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="-500,-700,-1330"  material="Flares/lensflare" scale=5 />
+
+        <Model position="0,-900,-1500" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="0,-900,-1580" material="Flares/lensflare" scale=5 />
+
+        <Model position="700,-1100,-1750" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="700,-1100,-1830"  material="Flares/lensflare" scale=5 />
+
+        <Model position="1500,-1300,-2000" mesh="planets/moon.mesh" scale=100 />
+        <Billboard colour="1,1,0.05" position="1500,-1300,-2080"  material="Flares/lensflare" scale=5 />
+
+      </attached>
+    </StaticEntity>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <SpawnPoint position="000.000, 000.000, 1000.000" orientation="0, 0, 0, -1" pawndesign=StoryMode />
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/asteroidField.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/asteroidField.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/asteroidField.oxw	(revision 11817)
@@ -0,0 +1,101 @@
+<LevelInfo
+ name = "asteroidFieldTest"
+ description = "Test of the asteroidField generator."
+  screenshot = "asteroidFieldTest.png"
+ tags = "test, showcase"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+<WorldAmbientSound source="Asteroid_rocks.ogg" looping="true" playOnLoad="true" />
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level
+ name         = "Sample"
+ description  = "Just a few tests"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+    hasPhysics   = true
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+
+
+
+    <!-- Belt that's far away  *** TURNED OFF FOR PERFORMANCE REASONS *** -->
+    <!-- Generate asteroid field and asteroid belt -->
+    <!--
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, 0, 0, -48, -34, 70, 100, 200, 219900, 210000, 900, 1)
+    ?>
+    -->
+
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+
+
+    <!-- Planet close to spawn point -->
+    <Planet
+      position="15000,0,0"
+      scale="5000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="5000,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+
+
+
+
+
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/asteroids.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/asteroids.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/asteroids.oxw	(revision 11817)
@@ -0,0 +1,465 @@
+<LevelInfo
+ name = "Asteroids Race"
+ description = "Reach the checkpoints and avoid asteroids."
+ tags = "gametype"
+ screenshot = "asteroids.png"
+/>
+<WorldAmbientSound source="Asteroid_rocks.ogg" looping="true" playOnLoad="true" />
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "Asteroids"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="-300,300,0" name="playerstart" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <?lua
+      for i = 1, 250, 1
+      do
+      j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(math.random()* 15000 - 1000) ?>,<?lua print(math.random() * 12000 - 4000) ?>,<?lua print(math.random() * 12000 - 4000) ?>"
+      collisionType = dynamic
+      linearDamping = 0.8
+      angularDamping = 0
+      scale = "<?lua print(j * 150)?>"
+      collisiondamage = 1
+      enablecollisiondamage = true
+    >
+      <attached>
+        <Model mass="<?lua print(j * 1000) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 350) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+
+    <?lua
+      end
+    ?>
+
+<!--
+    <MovableEntity position="0,0,0" collisionType=dynamic scale=5 linearDamping=0.8 angularDamping=0  collisiondamage=0.005 enablecollisiondamage=true>
+      <attached>
+        <Model mass=100 mesh="ast1.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius=11.75 />
+      </collisionShapes>
+    </MovableEntity>
+
+
+    <MovableEntity position="0,300,0" scale=10 collisionType=dynamic linearDamping=0.8 angularDamping=0  collisiondamage=0.005 enablecollisiondamage=true>
+      <attached>
+        <Model mass=100 mesh="ast1.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius=22.5 />
+      </collisionShapes>
+    </MovableEntity>
+
+
+    <MovableEntity position="0,600,0"  scale=34  collisionType=dynamic linearDamping=0.8 angularDamping=0 collisiondamage=0.005 enablecollisiondamage=true>
+      <attached>
+        <Model mass=100 mesh="ast1.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius=76.5 />
+      </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity position="0,1200,0" scale=80 collisionType=dynamic linearDamping=0.8 angularDamping=0  collisiondamage=0.005 enablecollisiondamage=true>
+      <attached>
+        <Model mass=100 mesh="ast1.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius=200 />
+      </collisionShapes>
+    </MovableEntity>
+-->
+
+    <SpaceShip position="2000,200,0" lookat="0,0,0" >
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <AIController />
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="8000,300,700" lookat="0,0,0" >
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <AIController />
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="10200,400,-600" lookat="0,0,0" >
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <AIController />
+      </controller>
+    </SpaceShip>
+
+    <ForceField position="200,300,-500" direction="0,0,1" diameter=500 velocity=120>
+      <attached>
+        <ParticleEmitter source="Orxonox/ForceFieldPurpleSmall" startdelay=0 />
+      </attached>
+    </ForceField>
+
+    <ForceField position="2200,-300,1200" direction="1,0.3,-0.7" diameter=800 velocity=200>
+      <attached>
+        <ParticleEmitter source="Orxonox/ForceFieldBlueBig" startdelay=0 />
+      </attached>
+    </ForceField>
+
+    <ForceField position="8600,1400,500" direction="-1,-1,-1" diameter=500 velocity=400>
+      <attached>
+        <ParticleEmitter source="Orxonox/ForceFieldGreenSmall" startdelay=0 />
+      </attached>
+    </ForceField>
+
+    <ForceField position="11800,500,-2600" direction="-1,0,1" diameter=900 velocity=300>
+      <attached>
+        <ParticleEmitter source="Orxonox/ForceFieldPurpleBig" startdelay=0 />
+      </attached>
+    </ForceField>
+
+
+    <CheckPoint name=trigger1 position="-300,300,0" scale=1 isdestination=false isfirst=true stayactive=true distance=10 addtime=24 />
+
+
+    <CheckPoint name=trigger2 position="2200,600,0" scale=3 isdestination=false stayactive=true distance=100 addtime=20>
+      <events>
+        <activity>
+          <EventListener event=trigger1 />
+        </activity>
+      </events>
+      <attached>
+        <Billboard material="Flares/lensflare" colour="1,0,0">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger1 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </Billboard>
+        <BlinkingBillboard frequency=0.2 amplitude=1 material="Flares/lensflare" colour="1,1,0">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger1 />
+                  </trigger>
+                </events>
+                <EventTrigger invert=true>
+                  <events>
+                    <trigger>
+                      <EventListener event=trigger2 />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </BlinkingBillboard>
+        <Billboard material="Flares/lensflare" colour="0,1,0">
+          <events>
+            <visibility>
+              <EventListener event=trigger2 />
+            </visibility>
+          </events>
+        </Billboard>
+      </attached>
+    </CheckPoint>
+
+
+    <CheckPoint name=trigger3 position="4100,0,400" scale=3 isdestination=false stayactive=true distance=100 addtime=10>
+      <events>
+        <activity>
+          <EventListener event=trigger2 />
+        </activity>
+      </events>
+      <attached>
+        <Billboard material="Flares/lensflare" colour="1,0,0">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger2 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </Billboard>
+        <BlinkingBillboard frequency=0.2 amplitude=1 material="Flares/lensflare" colour="1,1,0">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger2 />
+                  </trigger>
+                </events>
+                <EventTrigger invert=true>
+                  <events>
+                    <trigger>
+                      <EventListener event=trigger3 />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </BlinkingBillboard>
+        <Billboard material="Flares/lensflare" colour="0,1,0">
+          <events>
+            <visibility>
+              <EventListener event=trigger3 />
+            </visibility>
+          </events>
+        </Billboard>
+      </attached>
+    </CheckPoint>
+
+
+    <CheckPoint name=trigger4 position="5600,400,0" scale=3 isdestination=false stayactive=true distance=100 addtime=10>
+      <events>
+        <activity>
+          <EventListener event=trigger3 />
+        </activity>
+      </events>
+      <attached>
+        <Billboard material="Flares/lensflare" colour="1,0,0">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger3 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </Billboard>
+        <BlinkingBillboard frequency=0.2 amplitude=1 material="Flares/lensflare" colour="1,1,0">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger3 />
+                  </trigger>
+                </events>
+                <EventTrigger invert=true>
+                  <events>
+                    <trigger>
+                      <EventListener event=trigger4 />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </BlinkingBillboard>
+        <Billboard material="Flares/lensflare" colour="0,1,0">
+          <events>
+            <visibility>
+              <EventListener event=trigger4 />
+            </visibility>
+          </events>
+        </Billboard>
+      </attached>
+    </CheckPoint>
+
+
+    <CheckPoint name=trigger5 position="7200,600,-200" scale=3 isdestination=false stayactive=true distance=100 addtime=10>
+      <events>
+        <activity>
+          <EventListener event=trigger4 />
+        </activity>
+      </events>
+      <attached>
+        <Billboard material="Flares/lensflare" colour="1,0,0">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger4 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </Billboard>
+        <BlinkingBillboard frequency=0.2 amplitude=1 material="Flares/lensflare" colour="1,1,0">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger4 />
+                  </trigger>
+                </events>
+                <EventTrigger invert=true>
+                  <events>
+                    <trigger>
+                      <EventListener event=trigger5 />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </BlinkingBillboard>
+        <Billboard material="Flares/lensflare" colour="0,1,0">
+          <events>
+            <visibility>
+              <EventListener event=trigger5 />
+            </visibility>
+          </events>
+        </Billboard>
+      </attached>
+    </CheckPoint>
+
+
+    <CheckPoint name=trigger6 position="9200, 800,-800" scale=3 isdestination=false stayactive=true distance=100 addtime=15>
+      <events>
+        <activity>
+          <EventListener event=trigger5 />
+        </activity>
+      </events>
+      <attached>
+        <Billboard material="Flares/lensflare" colour="1,0,0">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger5 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </Billboard>
+        <BlinkingBillboard frequency=0.2 amplitude=1 material="Flares/lensflare" colour="1,1,0">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=trigger5 />
+                  </trigger>
+                </events>
+                <EventTrigger invert=true>
+                  <events>
+                    <trigger>
+                      <EventListener event=trigger6 />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </EventTrigger>
+            </visibility>
+          </events>
+        </BlinkingBillboard>
+        <Billboard material="Flares/lensflare" colour="0,1,0">
+          <events>
+            <visibility>
+              <EventListener event=trigger6 />
+            </visibility>
+          </events>
+        </Billboard>
+      </attached>
+    </CheckPoint>
+
+
+    <Model position="11200,400,-1800" scale=10 pitch=-90  mesh="Carrier.mesh">
+      <attached>
+        <CheckPoint position="-10,0,0" name=trigger7 scale=0.6 isdestination=true stayactive=true distance=100>
+          <events>
+            <activity>
+              <EventListener event=trigger6 />
+            </activity>
+          </events>
+          <attached>
+            <Billboard material="Flares/lensflare" colour="1,0,0">
+              <events>
+                <visibility>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event=trigger6 />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </visibility>
+              </events>
+            </Billboard>
+            <BlinkingBillboard frequency=0.2 amplitude=1 material="Flares/lensflare" colour="1,1,0">
+              <events>
+                <visibility>
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event=trigger6 />
+                      </trigger>
+                    </events>
+                    <EventTrigger invert=true>
+                      <events>
+                        <trigger>
+                          <EventListener event=trigger7 />
+                        </trigger>
+                      </events>
+                    </EventTrigger>
+                  </EventTrigger>
+                </visibility>
+              </events>
+            </BlinkingBillboard>
+            <Billboard material="Flares/lensflare" colour="0,1,0">
+              <events>
+                <visibility>
+                  <EventListener event=trigger7 />
+                </visibility>
+              </events>
+            </Billboard>
+          </attached>
+        </CheckPoint>
+      </attached>
+    </Model>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/bigshipPresentation.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/bigshipPresentation.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/bigshipPresentation.oxw	(revision 11817)
@@ -0,0 +1,34 @@
+<LevelInfo
+ name = "bigship Presentation"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/bigship.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=bigship />
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/cityLevelHS15.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/cityLevelHS15.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/cityLevelHS15.oxw	(revision 11817)
@@ -0,0 +1,85 @@
+<LevelInfo
+ name = "City level"
+ description = "A large random generated city"
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipRing.oxt")
+  include("templates/spaceshipSwallow.oxt")
+?>
+
+
+<!-- Global variable definition -->
+<?lua
+X = 20
+Y = 20
+CELL_SIZE = 600
+
+NIGHTMODE = true
+if (NIGHTMODE) then
+  AMBIENT_MULT = 0.2
+  LIGHT_MULT = 0.4
+else
+  AMBIENT_MULT = 1.0
+  LIGHT_MULT = 1.0
+end
+?>
+
+<!-- city generator -->
+<?lua
+function randomHouses(x,y,cellSize)
+    returnString = ""
+    for currentX = 1, x, 1 do
+      for currentY = 1, y, 1 do
+        houseNr = math.floor(math.random()*7 + 1)
+        orientation = math.floor(math.random()*4)*90
+        houses = {"Glasstower1","ETH","Hausc1","PrimeTower","Hausc2","101","hausc3"}
+        scales = {100,100,100,100,100,100,100}
+        collisionShapes = {--[[Glasstower1]]"<BoxCollisionShape position=\"0,405,0\" halfExtents=\"90,405,90\" /><BoxCollisionShape  position=\"0,855,0\" halfExtents=\"110, 45, 110\" /><BoxCollisionShape      position=\"0,957,0\" halfExtents=\"5, 70, 5\" />  ",--[[ETH]]"<BoxCollisionShape      position=\"-46.16,22.423,3.439\" halfExtents=\"89.5,30.4,151.5\" /><BoxCollisionShape      position=\"105.607996,22.905,-137.980005\" halfExtents=\"31.40,23.55,39.25\" /><BoxCollisionShape      position=\"105.607996,22.905,137.078003\" halfExtents=\"31.40,23.55,39.25\" /><BoxCollisionShape      position=\"65.356,22.905,118.208997\" halfExtents=\"31.40,23.55,20.40\" /><BoxCollisionShape      position=\"65.356,22.905,-121.712\" halfExtents=\"31.40,23.55,20.40\" /><SphereCollisionShape  position=\"44.985001,60.196997,0.352 \" radius=\"31.65\" />",--[[Hausc1]]"<BoxCollisionShape position=\"0,71.43,0\" halfExtents=\"142.86, 71.43, 142.86\" /><BoxCollisionShape position=\"-71.43,285.72,-71.43\" halfExtents=\"71.43, 142.86, 71.43\" /><BoxCollisionShape position=\"71.43,428.58,0\" halfExtents=\"71.43, 285.72, 142.86\" /><BoxCollisionShape position=\"71.43,857.16,-71.43\" halfExtents=\"71.43, 142.86, 71.43\" /><BoxCollisionShape position=\"-35.715,214.29,35.715\" halfExtents=\"35.715, 71.43, 35.715\" /><BoxCollisionShape position=\"-35.715,500.01,-107.145\" halfExtents=\"35.715, 71.43, 35.715\" /><BoxCollisionShape position=\"107.145,785.73,35.715\" halfExtents=\"35.715, 71.43, 35.715\" />",--[[PrimeTower]]"<BoxCollisionShape      position=\"-16.1,278.6,053.\" halfExtents=\"063,296,063\" yaw=\"-16.5\" /> <BoxCollisionShape      position=\"007.1,278.6,027.3\" halfExtents=\"065,296,065\" yaw=\"-28\" /><BoxCollisionShape      position=\"012.8,278.6,-63.3\" halfExtents=\"076,296,076\" yaw=\"4\" /> <BoxCollisionShape      position=\"023.18,278.6,-135.4\" halfExtents=\"067.7,296,067.7\" yaw=\"-36\" />",--[[Hausc2]]"<BoxCollisionShape      position=\"0,349.999,-166.667\" halfExtents=\"83.333, 349.999, 83.333\" /><BoxCollisionShape      position=\"0,349.999,166.667\" halfExtents=\"83.333, 349.999, 83.333\" /><BoxCollisionShape      position=\"41.666,291.666,0\" halfExtents=\"41.666, 58.333, 83.333\" /><BoxCollisionShape      position=\"-41.666,524.999,0\" halfExtents=\"41.666, 58.333, 83.333\" /> ",--[[101]]"<BoxCollisionShape    position=\"0,565.7,0\" halfExtents=\"76,565.7,76\" /><BoxCollisionShape position=\"-2.8,1210,1\" halfExtents=\"39,82,39\" />",--[[hausc3]]"<BoxCollisionShape      position=\"0,300,-208.33\" halfExtents=\"250,0,65.1\" pitch=\"-50.194\" /><BoxCollisionShape      position=\"0,300,-125\" halfExtents=\"250,0,65.1\" pitch=\"50.194\" /><BoxCollisionShape      position=\"125,275,0\" halfExtents=\"48.59,0,250\" roll=\"30.964\" /><BoxCollisionShape      position=\"208.33,275,0\" halfExtents=\"48.59,0,250\" roll=\"-30.964\" /><BoxCollisionShape      position=\"166.67,125,0\" halfExtents=\"83.33,125,250\" /><BoxCollisionShape      position=\"-83.33,125,-166.67\" halfExtents=\"166.66,125,83.33\" />"}
+        if (currentX > 0 and currentX < x and currentY > 1 --[[and currentY ~= y]]) then
+          returnString = returnString .. "<StaticEntity collisionType=\"static\" position=\"" .. (currentX*cellSize) .. ",0," .. (currentY*cellSize - (cellSize/2)) .. "\" direction=\"0,0,1\" pitch=\"0\" roll=\"0\" yaw=\"" .. orientation .. "\">  <attached> <Model position=\"0,0,0\" mesh=\"" .. houses[houseNr] .. ".mesh\" scale=\"" .. scales[houseNr] .. "\"/></attached><collisionShapes>" .. collisionShapes[houseNr] .. "</collisionShapes></StaticEntity>\n\n"
+        end
+        if (NIGHTMODE) then
+          billboards = "<Billboard position=\"40,82,55\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"-40,82,55\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"40,82,192\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"-40,82,192\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"40,82,-55\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"-40,82,-55\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"40,82,-192\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" /><Billboard position=\"-40,82,-192\" scale=\"0.5\" material=\"Examples/Flare\" colour=\"1.0, 0.9, 0.9\" />"
+        else
+          billboards = ""
+        end
+        returnString = returnString .. "<StaticEntity collisionType=\"static\" position=\"" .. (currentX*cellSize - cellSize/2) .. ",0," .. (currentY*cellSize) .. "\" direction=\"0,0,1\" pitch=\"0\" roll=\"0\" yaw=\"0\">  <attached> " .. billboards .. " <Model position=\"0,0,0\" mesh=\"CityGroundLamps.mesh\" scale=\"" .. cellSize .. "\"/><Model position=\"0,0,0\" mesh=\"CityGround.mesh\" scale=\"" .. cellSize .. "\"/></attached><collisionShapes><BoxCollisionShape position=\"0,0,0\" halfExtents=\"500,0,500\"/><BoxCollisionShape position=\"48.5,50.88,192\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"48.5,50.88,-192\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"48.5,50.88,-54\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"48.5,50.88,54\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"-48.5,50.88,192\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"-48.5,50.88,-192\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"-48.5,50.88,-54\" halfExtents=\"5,50.88,5\"/><BoxCollisionShape position=\"-48.5,50.88,54\" halfExtents=\"5,50.88,5\"/></collisionShapes></StaticEntity>\n\n"
+      end
+    end
+    return returnString
+end
+
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <?lua include("includes/notifications.oxi") ?>
+
+
+  <Scene
+    ambientlight = "<?lua print(0.45 * AMBIENT_MULT) ?>, <?lua print(0.4 * AMBIENT_MULT) ?>, <?lua print(0.35 * AMBIENT_MULT) ?>"
+    skybox       = "Orxonox/skyBoxClouds<?lua if (NIGHTMODE) then print('Dark') end ?>"
+  >
+    <?lua print(randomHouses(X,Y,CELL_SIZE)) ?>
+
+    <Light type="directional" position="-100,52,-59" lookat="0,0,0" diffuse="<?lua print(1.0 * LIGHT_MULT) ?>, <?lua print(0.9 * LIGHT_MULT) ?>, <?lua print(0.9 * LIGHT_MULT) ?>, 1.0" specular="<?lua print(1.0 * LIGHT_MULT) ?>, <?lua print(0.9 * LIGHT_MULT) ?>, <?lua print(0.9 * LIGHT_MULT) ?>, 1.0"/>
+    <LensFlare position="-100000,52000,-59000" />
+
+    <SpawnPoint team=0 position="<?lua print(X*CELL_SIZE/2) ?>,500,<?lua print(Y*CELL_SIZE/2) ?>" spawnclass=SpaceShip pawndesign=spaceshipescort />
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/clangenb.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/clangenb.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/clangenb.oxw	(revision 11817)
@@ -0,0 +1,55 @@
+<LevelInfo
+ name = "clangenb"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipHeartAttack.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipHeartAttack />
+    <SpaceShip position="0,2000,200" lookat="0,0,0" name="movingtarget" radarname="Pirate">
+                            <events>
+                                <visibility>
+                                    <EventListener event="boxtrigger4" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointController team=1>
+                         <waypoints>
+                          <Model mesh="cube.mesh" scale=8 position="  0,1700,-200" />
+                          <Model mesh="cube.mesh" scale=8 position="  0,1700,-700" />
+                          <Model mesh="cube.mesh" scale=8 position="500,1700,-700" />
+                          <Model mesh="cube.mesh" scale=8 position="500,1700,-200" />
+                       </waypoints>
+                    </WaypointController>
+                  </controller>
+                </SpaceShip>
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/collateralDamageDemo.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/collateralDamageDemo.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/collateralDamageDemo.oxw	(revision 11817)
@@ -0,0 +1,36 @@
+<LevelInfo
+ name = "Collateral Damage Demo"
+ description = " "
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage />
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/collisionShapes.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/collisionShapes.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/collisionShapes.oxw	(revision 11817)
@@ -0,0 +1,46 @@
+<LevelInfo
+ name = "Collision shapes"
+ description = "A level with some collision shapes."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+    
+	<StaticEntity position="1000,0,0" collisionType="static">
+		<collisionShapes>
+			<SphereCollisionShape   yaw="20" pitch="20" roll="20" position="0,-300,0" radius="100" />
+			<CylinderCollisionShape yaw="20" pitch="20" roll="20" position="0,+000,0" radius="50" height="150" />
+			<BoxCollisionShape      yaw="20" pitch="20" roll="20" position="0,+200,0" halfExtents="30, 50, 80" />
+			<ConeCollisionShape     yaw="20" pitch="20" roll="20" position="0,+400,0" radius="50" height="150" />
+			<PlaneCollisionShape    yaw="20" pitch="20" roll="20" position="0,+600,0" normal="0, -1, 0" offset="30" />
+		</collisionShapes>
+	</StaticEntity>
+	
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/docking.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/docking.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/docking.oxw	(revision 11817)
@@ -0,0 +1,209 @@
+<!-- -->
+<LevelInfo
+ name = "Transporter"
+ description = "Level with a Transporter. Demonstrates the docking system."
+ tags = "showcase"
+ screenshot = "transporter.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link="lodtemplate_default" />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+
+    <Light type="directional" position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <?lua for i = 1, 10, 1 do ?>
+      <SpawnPoint position="<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>" lookat="0,0,0" spawnclass="SpaceShip" pawndesign="spaceshipassff" />
+    <?lua end ?>
+
+
+
+      <SpaceShip
+   position               = "280, 150, 115"
+   orientation            = "0.5, 0.5, 0.5, 0.5"
+   hudtemplate            = "spaceshiphud"
+   camerapositiontemplate = "spaceshipassffcameras"
+   engine                 = "spaceshipassffengine"
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = "3"
+   explosionchunks        = "6"
+
+   health            = "100"
+   maxhealth         = "200"
+   initialhealth     = "100"
+
+   primaryThrust     = "100;"
+   auxilaryThrust    = "30;"
+   rotationThrust    = "25;"
+
+   collisionType     = "dynamic"
+   mass              = "100"
+   linearDamping     = "0.7"
+   angularDamping    = "0.9999999"
+  >
+    <attached>
+        <DistanceTriggerBeacon name="bcnSpaceShip" />
+        <DockingTarget name="spaceShip" />
+
+      <Model position="0,0,0" yaw="90" pitch="-90" roll="0" scale="4" mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude="0.1" frequency="0.5" quadratic="1" />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude="0.1" frequency="0.5" phase="180" quadratic="1" />
+      <DistanceTriggerBeacon name="PlayerDistanceTrigger" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+<?lua
+  include("includes/weaponSettingsAssff.oxi")
+?>
+  </SpaceShip>
+
+    
+
+
+    <Destroyer
+      position          = "100,150,100"
+      collisionType     = "dynamic"
+      mass              = "100000"
+      velocity          = "0,0,0"
+      angularDamping    = "0.9999999"
+      health            = "10000"
+      maxhealth         = "10000"
+      initialhealth     = "10000"
+    >
+
+      <attached>
+
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+
+
+        <Dock orientation="0.5, 0.5, 0.5, 0.5">
+            <animations>
+                <MoveToDockingTarget target="destroyer" position="10,150,40" />
+            </animations>
+            <effects>
+                <DockToShip target="spaceShip" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="dockMe" />
+                </execute>
+            </events>
+            <attached>
+                <DistanceTrigger position="0,0,-200" distance="30" target="Pawn" beaconMode="exclude" targetname="bcnDestroyer" name="dockMe" />
+                <Billboard position="0,0,-200" material="Examples/Flare" colour="1.0, 0, 0" />
+            </attached>
+        </Dock>
+
+
+        <TeamSpawnPoint team="1" position="150,0,7" direction="-1,0,0" roll="90" yaw="0" spawnclass="SpaceShip" pawndesign="spaceshipassff" />
+        <TeamSpawnPoint team="1" position="0,0,7" lookat="-1,0,0" roll="90"  yaw="0" spawnclass="SpaceShip" pawndesign="spaceshipassff" />
+        <TeamSpawnPoint team="1" position="-50,0,7" lookat="-1,0,0" roll="90" yaw="0" spawnclass="SpaceShip" pawndesign="spaceshipassff" />
+        <TeamSpawnPoint team="1" position="100,0,7" lookat="-1,0,0" roll="90" yaw="0" spawnclass="SpaceShip" pawndesign="spaceshipassff" />
+        <TeamSpawnPoint team="1" position="50,0,7" lookat="-1,0,0" roll="90" yaw="0" spawnclass="SpaceShip" pawndesign="spaceshipassff" />
+        <?lua for i = 1, 100, 1 do ?>
+          <TeamSpawnPoint
+            team="0"
+            position="<?lua print((math.random() * 500 + 500) * (math.floor(math.random() + 0.5) * 2 - 1)) ?>,<?lua print((math.random() * 500 + 500) * (math.floor(math.random() + 0.5) * 2 - 1)) ?>,<?lua print((math.random() * 500 + 500) * (math.floor(math.random() + 0.5) * 2 - 1)) ?>"
+            lookat="0,0,0"
+            spawnclass="SpaceShip"
+            pawndesign="spaceshipassff"
+          />
+        <?lua end ?>
+
+        <Model mesh="Carrier.mesh" scale="5" />
+        <Backlight
+          mainstate="activity"
+          active="false"
+          scale="0.4"
+          name="bltest"
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width="15"
+          length="1500"
+          lifetime="2"
+          elements="50"
+          trailmaterial="Trail/backlighttrail"
+          turnontime="1"
+          turnofftime="1"
+          material="Flares/ThrusterFlare1"
+        />
+        <Backlight
+                  scale="1"
+                  position=" 169, 75, -15"
+                  colour="1, 0.85, 0.5, 0.5"
+                  width="40"
+                  length="1000"
+                  lifetime="5"
+                  elements="15"
+                  trailmaterial="Trail/backlighttrail"
+                  material="Examples/Flare"
+                  />
+        <Backlight
+                  scale="1"
+                  position=" 169, -75, -15"
+                  colour="1, 0.85, 0.5, 0.5"
+                  width="40"
+                  length="1000"
+                  lifetime="5"
+                  elements="15"
+                  trailmaterial="Trail/backlighttrail"
+                  material="Examples/Flare"
+         />
+        <?lua for i=0,8,1 do ?>
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?> ,15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude="0.1"
+            frequency="0.5"
+            quadratic="1"
+          />
+
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?>,-15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude="0.1"
+            frequency="0.5"
+            quadratic="1"
+          />
+        <?lua end ?>
+
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+
+    </Destroyer>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/dockingToASpaceStation.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/dockingToASpaceStation.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/dockingToASpaceStation.oxw	(revision 11817)
@@ -0,0 +1,183 @@
+<!--  -->
+<LevelInfo
+ name = "Docking to a Space Station"
+ description = "Docking into a spacestation."
+ tags = "showcase"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/bigship.oxt")
+  include("templates/spaceshipTurret.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+  include("templates/FPS.oxt")
+?>
+
+<Level
+  gametype = Deathmatch
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+    gravity      = "0,0,0"
+    hasPhysics   = true
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0,1.0,1.0,0.5" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="3200,0,0" lookat="2800,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+    <StaticEntity position  = "2800,0,0" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </StaticEntity>
+
+<!-- Docking  -->
+    <Dock position="2830,20,50" roll=0 yaw=0 >
+        <animations>
+            <MoveToDockingTarget target="destroyer" />
+        </animations>
+        <effects>
+            <DockToShip target="spaceShip" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+
+	    <undocking>
+		<EventListener event="undockMe" />
+	    </undocking>
+	
+            <activity>
+                <EventListener event=notGameEnd />
+            </activity>
+        </events>
+        <attached>
+	<!-- Trigger for docking with billboard -->
+            <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+            <DistanceTrigger position="0,0,0" distance="200" target="Pawn"
+                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"
+            />
+	<!-- Trigger for undocking with billboard -->
+	    <Billboard position="-2630,-19970,150" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+	    <DistanceTrigger position="-2630,-19970,150" distance="50" target="Pawn"
+                beaconMode="identify" targetname="bcnDestroyer" name="undockMe"
+            />
+        </attached>
+
+    </Dock>
+
+<!-- FPS Player as destination of the dock -->
+<FpsPlayer template = "fps" radarname = "First Person Player" position = "0,-19900,0" >
+      <attached>
+        <DockingTarget name="spaceShip" />
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+      </attached>
+</FpsPlayer>
+
+
+<!-- Cube as test SpaceStation
+
+The station can either be hidden outside of the skybox, within the hull of the space station if it is big enough or within a planet.
+Complex spacestations can be placed very far away from the spaceship so it is rendered at low resolution while the player uses the space ship.
+
+-->
+  <StaticEntity position="0,-20000,0" direction="0,-1,0" collisionType=static mass=100000 friction=0.01 >
+      <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="80,80,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="400,400,25" />
+      </collisionShapes>
+  </StaticEntity>
+
+<!-- Homogenous gravitationfield to simulate local gravity (activating the normal gravity will affect the spaceship terribly) -->
+<ForceField position="0,-20000,0" mode="homogen" diameter="2000" forcedirection = "0,-500,0" />
+
+
+<!-- Some more stuff -->
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+    <Planet
+      position="15000,0,-1000"
+      scale="5000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/ganymede.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="5000,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+  </Scene>
+
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/dynamicMatch.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/dynamicMatch.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/dynamicMatch.oxw	(revision 11817)
@@ -0,0 +1,134 @@
+<LevelInfo
+ name = "Dynamic Match"
+ description = "Dynamicmatch: Take care of what you're shooting at."
+ tags = "gametype"
+ screenshot = "dynamicMatch.png"
+/>
+<WorldAmbientSound source="Mars.ogg" looping="true" playOnLoad="true" />
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipGhost.oxt")
+  include("dynamicMatchHUD.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "Dynamicmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/Starbox"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+<!-- ------------------Planet needs gravity----------------- -->
+<Planet position="0,0,0" scale=500 pitch=-90 mesh="iceplanet.mesh" atmosphere="atmosphere1" rotationaxis="8,1,0" rotationrate="1" atmospheresize=224.0f imagesize=1024.0f />
+<StaticEntity position="0,0,0" collisionType=static>
+      <collisionShapes>
+        <SphereCollisionShape radius="499" />
+      </collisionShapes>
+    </StaticEntity>
+
+<!-- -----------12-Spawnpoints around the planet------------- -->
+<!-- inner Spawnpoints -->
+<TeamSpawnPoint team=0 position="1000,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="-1000,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,1000,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,-1000,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,0,1000" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,0,-1000" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<!--outer Spawnpoints -->
+<TeamSpawnPoint team=0 position="2000,0,0" lookat="0,0,1" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="-2000,0,0" lookat="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,2000,0" lookat="0,1,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,-2000,0" lookat="0,-1,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,0,2000" lookat="1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+<TeamSpawnPoint team=0 position="0,0,-2000" lookat="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+
+<?lua
+    dofile("includes/CuboidSpaceStation.lua")
+  ?>
+<!-- ----------------Rotating satellite--------------- -->
+<MovableEntity position="1,1,1" rotationrate="-4.5" rotationaxis="0,0,1">
+        <attached>
+          <StaticEntity position="-2500,0,0" yaw=90 pitch=90>
+            <attached>
+              <?lua
+                createSpaceStationPar(0,2,1,2,1,4,1,50)
+              ?>
+                <TeamSpawnPoint team=2 position="20,20,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+                <TeamSpawnPoint team=2 position="-20,-20,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+                <TeamSpawnPoint team=2 position="-10,10,20" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate/>
+            </attached>
+          </StaticEntity>
+        </attached>
+</MovableEntity>
+
+<!-- ---------------asteroid ellypse----------------- -->
+<?lua
+max = 20
+for i = 0, max, 1
+do
+    y = math.sin(i/max*6)*4000
+    z = math.cos(i/max*6)*5000
+    x = 0
+    ?>
+<?lua
+for k = 1, 25, 1
+do
+j = math.random()
+?>
+
+    <StaticEntity position="<?lua print(x + math.random() * 1000-500) ?>,<?lua print(y + math.random() * 1000-500) ?>,<?lua print(z + math.random() * 5000-2500) ?>" scale="<?lua print(j * 5) ?>" >
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh">
+          <attached><!-- ---------asteroid fog----- -->
+            <ParticleEmitter position="0,0,0" source="Orxonox/Steam" />
+          </attached>
+        </Model>
+      </attached>
+      <?lua if i == 5 then ?><collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 70) ?>" />
+      </collisionShapes> <?lua end ?>
+    </StaticEntity>
+<?lua
+end
+?>
+<?lua end ?>
+
+    <GlobalShader compositor="Bloom" visible=false>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,0,0" distance=30 target="Spectator" switch=true />
+        </visibility>
+      </events>
+    </GlobalShader>
+<!-- ----------------random fog --- not in use
+<?lua
+for i = 1, 100, 1
+do
+j = math.random()
+?>
+
+    <StaticEntity position="<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000 - 2000) ?>">
+      <attached>
+        <ParticleEmitter position="0,0,0" source="Orxonox/Steam" />
+      </attached>
+    </StaticEntity>
+
+<?lua
+end
+?>
+-->
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/earth.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/earth.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/earth.oxw	(revision 11817)
@@ -0,0 +1,114 @@
+<LevelInfo
+ name = "Earth Demonstration"
+ description = "1:100 Scale Model of Earth with Gravity"
+ tags = "showcase"
+ screenshot = "earthdemonstration.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/spaceshipHXY.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link="lodtemplate_default" />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Template name=PortalDefault>
+      <PortalEndPoint>
+          <attached>
+              <Billboard material="Portals/Default" />
+          </attached>
+      </PortalEndPoint>
+  </Template>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyboxempty"
+  >
+    <WorldAmbientSound
+      source="Earth.ogg"
+      looping="true"
+      playOnLoad="true"
+    />
+
+    <Light
+      type="directional"
+      position="-500000,-500000,0"
+      direction="0.253, 0.593, -0.765"
+      diffuse="1.0, 0.9, 0.9, 1.0"
+      specular="1.0, 0.9, 0.9, 1.0"
+    />
+
+
+
+    <SpawnPoint
+      position="70000,0,0"
+      lookat="0,0,0"
+      spawnclass="SpaceShip"
+      pawndesign="spaceshipHXY"
+    />
+    <PortalEndPoint position="70500,100,0" id="1" distance="40" target="MobileEntity" design="PortalDefault"/>
+
+    <!-- This is a model of Earth: mass=EarthMass/1000 and radius=EarthRadius[km]*10 -->
+    <Planet
+      position="0,0,0"
+      scale="63000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="5.9e21"
+      pitch="0"
+      mesh="planets/earth.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="0,1,0"
+      rotationrate="0.2"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="newtonianGravity" diameter="140000" massDiameter="126000" mass="5.9e21" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="63000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <!-- This is a model of our Moon: mass=MoonMass/1000 and radius=MoonRadius[km]*10 and position=DistanceFromEarth[km]*10 -->
+    <Planet
+      position="3625700,0,0"
+      scale="17370"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="7.36e19"
+      pitch="0"
+      mesh="planets/moon.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="0,1,0"
+      rotationrate="0.2"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="newtonianGravity" diameter="40000" massDiameter="34740" mass="7.36e19" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="17370" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+    <PortalEndPoint position="3603330,100,0" id="2" distance="40" target="MobileEntity" design="PortalDefault"/>
+
+    <!-- Create portals from Earth to the Moon -->
+    <PortalLink fromID="1" toID="2" />
+    <PortalLink fromID="2" toID="1" />
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/emptyLevel.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/emptyLevel.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/emptyLevel.oxw	(revision 11817)
@@ -0,0 +1,34 @@
+<LevelInfo
+ name = "Empty level"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipEscort.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/events.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/events.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/events.oxw	(revision 11817)
@@ -0,0 +1,274 @@
+<!-- -->
+<LevelInfo
+  name = "Events showcase"
+  description = "Level to test and showcase events."
+  tags = "test, showcase"
+  screenshot = "eventsshowcase.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="0,-100,0" lookat="0,0,0" roll=180 spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <Billboard position=" 300,100,  0" material="Examples/Flare" colour="1.0, 0.0, 0.0" />
+    <Billboard position=" 200,100,  0" material="Examples/Flare" colour="1.0, 0.5, 0.0" />
+    <Billboard position=" 200,100,100" material="Examples/Flare" colour="1.0, 0.5, 0.0" />
+    <Billboard position=" 100,100,  0" material="Examples/Flare" colour="1.0, 1.0, 0.0" />
+    <Billboard position="   0,100,  0" material="Examples/Flare" colour="0.0, 1.0, 0.0" />
+    <Billboard position="-100,100,  0" material="Examples/Flare" colour="0.0, 1.0, 1.0" />
+    <Billboard position="-100,100,100" material="Examples/Flare" colour="0.0, 1.0, 1.0" />
+    <Billboard position="-200,100,  0" material="Examples/Flare" colour="0.0, 0.0, 1.0" />
+    <Billboard position="-300,100,  0" material="Examples/Flare" colour="1.0, 0.0, 1.0" />
+
+
+
+    <!--
+      Begin of the tutorial section.
+    -->
+
+
+
+    <!--
+      Note:
+      All following examples use only one subobject (in nested layouts). But of course you can add more
+      objects. They will all follow the same rules (depending on the example receive, send or pipe events).
+
+      Some examples address objects by name. Those methods always address ALL objects with this name, no
+      matter where they are in the XML-file (before or after the addressing object). Of course this also
+      works with all amounts of objects from zero to infinity. In the examples I used two objects each.
+    -->
+
+    <DistanceTrigger name="test" position="0,0,0" target="Pawn" distance=25 stayActive="true" />
+    <Backlight position="0,0,0" visible=true frequency=0.6 amplitude=3 material="Flares/lensflare" colour="1,0,1"/>
+    
+    <NextQuestion  question="Continue?" a1="yes" a2="no" >
+     <possibleQuestions> 
+        <NextQuestion  question="Are you sure?" a1="yep let me continue" a2="no actually not" />
+        <NextQuestion  question="Why?" a1="Got a dentist's appointment" a2="this sucks" >
+        <possibleQuestions>
+          <NextQuestion  question="Are your teeth that bad mate?" a1="yep" a2="leave me alone godammit" />
+          <NextQuestion  question="You suck" a1="..." a2="Im going now okay" />
+        </possibleQuestions>
+      </NextQuestion>
+      </possibleQuestions>    
+      <events>
+        <execute>
+           <EventListener event="test" />
+        </execute>
+      </events>
+    </NextQuestion>
+
+    <DistanceTrigger name="test1" position="100,300,0" target="Pawn" distance=25 stayActive="true" />
+    <Backlight position="100,300,0" visible=true frequency=0.6 amplitude=3 material="Flares/lensflare" colour="1,1,1"/>
+    
+    <NextQuestion  question="Wazzp bud?" a1="yes" a2="no" >
+     <possibleQuestions> 
+        <NextQuestion  question="Do you like fish" a1="yep let me continue" a2="no actually not" />
+        <NextQuestion  question="Whats your favourite pastime?" a1="Got a dentist's appointment" a2="this sucks" >
+        <possibleQuestions>
+          <NextQuestion  question="Whatever?" a1="yep" a2="leave me alone godammit" />
+          <NextQuestion  question="Turtles then?" a1="..." a2="Im going now okay" />
+        </possibleQuestions>
+      </NextQuestion>
+      </possibleQuestions>    
+      <events>
+        <execute>
+           <EventListener event="test1" />
+        </execute>
+      </events>
+    </NextQuestion>
+
+
+    <!-- red -->
+    <!--
+      Standard:
+      Direct event-connection between an event-listener (Billboard) and an event source (DistanceTrigger).
+      Every fired event of the source is mapped to the "visibility" state of the listener.
+
+      This is a 1:1 mapping between event-listener and event-source.
+    -->
+    <Billboard position="300,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0>
+      <events>
+        <visibility>
+          <DistanceTrigger position="300,100,0" distance=25 target="ControllableEntity" />
+        </visibility>
+      </events>
+    </Billboard>
+
+
+    <!-- orange -->
+    <!--
+      EventListener:
+      The EventListener object forwards all events from objects, whose names equal the "event" attribute
+      of the EventListener, to the enclosing object (Billboard).
+      In this case, both triggers have the name "trigger2" and thus both triggers send events to the Billboard.
+
+      The EventListener provides an 1:n mapping between one listener and multiple event-sources.
+    -->
+    <Billboard position="200,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0>
+      <events>
+        <visibility>
+          <EventListener event="trigger2" />
+        </visibility>
+      </events>
+    </Billboard>
+    <DistanceTrigger name="trigger2" position="200,100,0" distance=25 target="ControllableEntity" />
+    <DistanceTrigger name="trigger2" position="200,100,100" distance=25 target="ControllableEntity" />
+
+
+    <!-- yellow -->
+    <!--
+      EventTarget:
+      The EventTarget object forwards the events, received from objects whithin the "events" subsection,
+      to all  objects whose names equal the "name" attribute.
+      In this case, the EventTarget forwards the event from the DistanceTrigger to all listeners with
+      name "bb3".
+
+      The EventTarget provides an n:1 mapping between several listeners and one event-source.
+    -->
+    <Billboard name="bb3" position="100,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 />
+    <Billboard name="bb3" position="100,150,100" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 />
+    <EventTarget target="bb3">
+      <events>
+        <visibility>
+          <DistanceTrigger position="100,100,0" distance=25 target="ControllableEntity" />
+        </visibility>
+      </events>
+    </EventTarget>
+
+
+    <!-- green -->
+    <!--
+      EventDispatcher:
+      The EventDispatcher catches events from objects in its "events" subsection. Those events are forwared
+      to all objects in the "targets" subsection. The EventDispatcher resembles the EventTarget, but
+      doesn't address objects with the "name" attribute. It rather places them directly inside the "targets"
+      subsection.
+      In this case, the EventDispatcher receives events from the DistanceTrigger and forwards those events
+      to the Billboard object.
+
+      The EventDispatcher provides an n:1 mapping between several targets (listeners) and one event source.
+    -->
+    <EventDispatcher>
+      <targets>
+        <Billboard position="0,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 />
+      </targets>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,100,0" distance=25 target="ControllableEntity" />
+        </visibility>
+      </events>
+    </EventDispatcher>
+
+
+    <!-- turquoise -->
+    <!--
+      Combination:
+      By combinding the above three classes, namely EventDispatcher, EventTarget and EventListener, you can
+      extract the event logic completely from the actual objects (Billboards and DistanceTriggers).
+      In this case, both triggers (whith names "trigger5") send events to both Billboards (with names "bb5").
+
+      This combination allows an n:n mapping between event-listeners and event-sources.
+    -->
+    <Billboard name="bb5" position="-100,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 />
+    <Billboard name="bb5" position="-100,150,100" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 />
+    <DistanceTrigger name="trigger5" position="-100,100,0" distance=25 target="ControllableEntity" />
+    <DistanceTrigger name="trigger5" position="-100,100,100" distance=25 target="ControllableEntity" />
+    <EventDispatcher>
+      <targets>
+        <EventTarget target="bb5" />
+      </targets>
+      <events>
+        <visibility>
+          <EventListener event="trigger5" />
+        </visibility>
+      </events>
+    </EventDispatcher>
+
+
+    <!-- blue -->
+    <!--
+      Mainstate:
+      Apart from the standard states (like activity and visibility), each object can have a mainstate.
+      You can define the mainstate with an xml-attribute: mainstate="state". "state" must be one of the
+      supported states of the object (except states which need the originator as a second argument). If
+      the mainstate is set (by default that's not the case), you can send events to the "mainstate" state.
+      This allows you to hide the actually affected state in the event-listener, while the event-source
+      just sends events.
+      Note that this example is exactly like the standard case, but the event is sent to the main-state,
+      which in turn is set to "visibility".
+    -->
+    <Billboard position="-200,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 mainstate="visibility">
+      <events>
+        <mainstate>
+          <DistanceTrigger position="-200,100,0" distance=25 target="ControllableEntity" />
+        </mainstate>
+      </events>
+    </Billboard>
+
+
+    <!-- violet -->
+    <!--
+      Event forwarding:
+      As a consequence of the mainstate, events can also be sent without any explicit declaration of
+      the targets state. This allows us to forward events from an event-source directly to a bunch of
+      event-listeners. The events are automatically piped into the mainstate. Therefore the listeners
+      have to declare their main-state.
+      In this example, the DistanceTrigger forwards the events to the Billboards main-state (visibility).
+      This does the same like the example above, but instead of piping events backwards from the source
+      into the mainstate of the listener, we're forwarding the event implicitly to the mainstate.
+    -->
+    <DistanceTrigger position="-300,100,0" distance=25 target="ControllableEntity">
+      <eventlisteners>
+        <Billboard position="-300,150,0" material="Examples/Flare" colour="1.0, 1.0, 1.0" visible=0 mainstate="visibility" />
+      </eventlisteners>
+    </DistanceTrigger>
+
+
+
+    <!--
+      End of the tutorial section.
+    -->
+
+
+
+    <!--
+      The following example shows again the red (standard layout) and the violet (event forwarding) example,
+      but this time with a memoryless state (spawn) from the ParticleSpawner instead of the boolean state
+      (visibility) in the other examples.
+    -->
+    <Billboard position=" 300,100,300" material="Examples/Flare" colour="1.0, 0.0, 0.0" />
+    <Billboard position="-300,100,300" material="Examples/Flare" colour="1.0, 0.0, 1.0" />
+    <ParticleSpawner position="300,150,300" source="Orxonox/BigExplosion1part1" lifetime=3.0 autostart=0>
+      <events>
+        <spawn>
+          <DistanceTrigger position="300,100,300" distance=25 target="ControllableEntity" />
+        </spawn>
+      </events>
+    </ParticleSpawner>
+    <DistanceTrigger position="-300,100,300" distance=25 target="ControllableEntity">
+      <eventlisteners>
+        <ParticleSpawner position="-300,150,300" source="Orxonox/BigExplosion1part1" lifetime=3.0 autostart=0 mainstate="spawn" />
+      </eventlisteners>
+    </DistanceTrigger>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/expeditionSector.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/expeditionSector.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/expeditionSector.oxw	(revision 11817)
@@ -0,0 +1,859 @@
+<LevelInfo
+    name = "Expedition to Sector 5C"
+    description = "Commander, our scientists are reporting strange binary radio signals from a yet unexplored and thought to be uninhabited region, sector 5C. Explore the sector and get to the bottom of these messages!"
+    tags = "mission"
+    screenshot = "expeditionSector.png"
+/>
+
+<?lua
+    include("stats.oxo")
+    include("HUDTemplates3.oxo")
+    include("HUDTemplatesFPS.oxo")
+    include("templates/lodInformation.oxt")
+
+    include("templates/spaceshipAssff.oxt")
+    include("templates/spaceshipPirate.oxt")
+    include("templates/spaceshipEscort.oxt")
+    include("templates/spaceshipShuttle.oxt")
+    include("templates/FPS.oxt")
+    include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level gametype = "Mission">
+    <templates>
+        <Template link="lodtemplate_default" />
+    </templates>
+
+    <?lua include("includes/notifications.oxi") ?>
+
+    <NotificationQueueCEGUI
+        name="narrative"
+        targets="simpleNotification"
+        size=3
+        displayTime=3.9
+        position="0.15, 0, 0.1, 0"
+        fontSize="15"
+        fontColor="0.3, 1, 0.2, 0.8"
+        alignment="HorzCentred"
+        displaySize="0.7, 0, 0, 0"
+    />
+
+    <!-- GLOBAL LUA VARIABLES -->
+    <?lua
+
+        --[[ Coordinates in (y,z,x). NOTE: Indexing starts at 1 in lua! Don´t forget to adapt the for loops, too! ]]--
+        cCenter = {0, 0, 0}
+        cSpawn = {-50, 0, 0}
+        cSector = {-15000, -5500, -9000}
+        cSectorEntry = {-4710, -5500, -2826}
+        cPathToEntry = {{0, -2000, 0}}
+        cBeacon = {-6500, -5500, -4400}
+
+        radSector = 12000
+
+	    cStationA = {1400, 400, -800}
+        cNewShip = {1000, 250, -350}
+
+        cPlanet1 = {20000, 0, 29000}
+        cPlanet2 = {-22000, 0, -29000}
+
+      	cEnemyBasePlanet = {-20000, -5500, -8000}
+
+        cEnemyBaseStation1 = {-12500, -4500, -3500}
+
+	      cField1 = {-5000, -4000, -3000}
+ 	      cField2 = {4000, 2000, 4500}
+
+        --[[ Function to print Coordinates. Quotes not included! ]]--
+        function printC(coord)
+          print(coord[1] .. [[,]] .. coord[2] .. [[,]] .. coord[3])
+        end
+
+        --[[ Function to add Coordinates.]]--
+        function addC(coord1, coord2)
+            return {coord1[1]+coord2[1], coord1[2]+coord2[2], coord1[3]+coord2[3]}
+        end
+    ?>
+
+    <Scene
+        ambientlight = "0.8, 0.8, 0.8"
+        skybox = "Orxonox/skyBoxMoreNebula"
+        hasPhysics = true
+    >
+
+    <SpawnPoint name="playerSpawn" team=0 position="<?lua printC(cSpawn) ?>" lookat="<?lua printC(cCenter) ?>" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" />
+
+    <Light type=directional position="<?lua printC(cCenter) ?>" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <!--QUEST DEFINITIONS-->
+
+    <GlobalQuest id="quest1">
+        <QuestDescription title="Get the scout ship" description="We received some extraterrestial binary radio signals from Sector 5C! We'd like you to get to the outer base in sector 4A and get a scout ship to explore the sector!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <complete-effects>
+            <AddQuest questId="quest2" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest2">
+        <QuestDescription title="Explore the sector" description="Now then, Commander, fly over there to check out if life can be found in what we believed it to be an inhabitated region in space. We have marked 5B with red lights so you can easily find it." failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <subquests>
+            <GlobalQuest id="quest2.1">
+                <QuestDescription title="> Get to the Field Source" description="We percieve a large magnetic field source at a certain spot in the sector. You should check it out! We have marked it with a blue light." failMessage="" completeMessage="" />
+                <hints>
+                </hints>
+                <complete-effects>
+                    <AddQuest questId="quest2.2" />
+                </complete-effects>
+            </GlobalQuest>
+            <GlobalQuest id="quest2.2">
+                <QuestDescription title="> Fight your way out" description="Oh no... this cannot be happening! We discovered an alien race, and it does not seem to be interested in peace. In fact, they seem to be planning an attack! You must get out of the hot zone. Fight if necessary!" failMessage="" completeMessage="" />
+                <hints>
+                </hints>
+                <complete-effects>
+                    <AddQuest questId="quest3" />
+                </complete-effects>
+            </GlobalQuest>
+        </subquests>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest3">
+        <QuestDescription title="Get back to 4A" description="You made it out in one piece. Now report to base 4A to warn the others!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+    </GlobalQuest>
+
+    <!--EVENTS AND TRIGGERS
+        Usable events and triggers:
+        spawntrigger
+        dockA
+        reachedSector
+        reachedEnemyStation
+        fightEnd
+        backToA
+
+        BASE-STORY-LINE:
+        We receive a message from commander (SimpleNotification -> SpawnTrigger) about alien radio activity in a nearby sector and are asked to change our spaceship
+        QUEST1: Dock to Station and get better Spaceship
+        TRIGGER: Docked to Station
+        EVENT: Change Spaceship and Sector 5C becomes visilbe
+
+        We are asked to go to the sector and explore it
+        QUEST2.1: Go to Sector 5C and see what you can find there
+        TRIGGER: Distance Trigger at enemy spacestation, with a rather large radius
+        EVENT: The 25 Enemies and there SpaceStation become visible, the planet should stay invisible; the patroling enemies on your way back become visible as well.
+
+        On your way back you discover the patroling enemy spaceships, they attack you, but you must survive and report to your commander about an possible upcoming attack from the aliens
+        QUEST2.2: Destroy the patroling spaceships, spare no one
+        TRIGGER: -------- The patroling spaceships should triggered bythemselves?
+        EVENT: After destroying all 5 enemy ships, you can return to your base and safety, the Distancetrigger for next quest is activated
+        FAIL: You fail if you die here
+
+        After destroying the enemy ships, you make it bake to your station in time to report about the hord of enemies you saw and start preparing for the upcoming fight!
+        QUEST3: Go back to spacestation
+        TRIGGER: Distancetrigger i suppose?
+        EVENT: You win this level, and the main level is unlocked.
+    -->
+
+    <EventMultiTrigger name="spawntrigger">
+        <events>
+            <trigger>
+                <EventListener event="playerSpawn" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <!-- HACK: just waited out 3sec for animation. Cannot link an event to the COMPLETION of a dock. How is this not possible?? -->
+    <EventMultiTrigger name="dockedA" activations="1" stayactive="true" delay=3>
+        <events>
+            <trigger>
+                <EventListener event="dockA" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger name="reachedSector" position="<?lua printC(cSector) ?>" distance="<?lua print(radSector) ?>" target="SpaceShip" beaconMode="identify" targetname="newSpaceShip" stayactive=true />
+
+    <DistanceTrigger name="reachedEnemyStation" position="<?lua printC(cEnemyBaseStation1) ?>" distance="5000" target="SpaceShip" beaconMode="identify" targetname="newSpaceShip" stayactive=true />
+
+    <!-- Recursive helper function for the fightEnd event -->
+    <?lua
+    function enemyTriggerRecursor(i)
+    if i > 0 then
+    return [[
+    <EventTrigger name=killedEnemy]] .. i .. [[ activations=1 stayactive=true delay=0.1>
+        <events>
+            <trigger>
+                <EventListener event=enemy />
+            </trigger>
+        </events>
+        ]] .. enemyTriggerRecursor(i-1) .. [[
+    </EventTrigger>
+    ]]
+    else return ""
+    end
+    end
+    ?>
+    <!-- Actual Event for the enemies. -->
+    <?lua print(enemyTriggerRecursor(5)) ?>
+    <EventMultiTrigger name="fightEnd" delay=0.1 stayactive=true>
+        <events>
+            <trigger>
+                <EventListener event="killedEnemy5" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger active=false name="closeToPatrol" position="<?lua printC(cStationA) ?>" distance="6000" target="SpaceShip" beaconMode="identify" targetname="newSpaceShip" stayactive=true >
+        <events>
+            <activity>
+                <EventListener event="reachedEnemyStation" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <DistanceTrigger active=false name="backToA" position="<?lua printC(cStationA) ?>" distance="600" target="SpaceShip" beaconMode="identify" targetname="newSpaceShip" stayactive=true >
+        <events>
+            <activity>
+                <EventListener event="fightEnd" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <Script code="Mission endMission true" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="backToA" />
+            </trigger>
+        </events>
+    </Script>
+
+    <DistanceTrigger invert=true active=false name="hasDied" position="<?lua printC(cSector) ?>" distance="100000" target="SpaceShip" beaconMode="identify" targetname="newSpaceShip" stayactive=true >
+        <events>
+            <activity>
+                <EventListener event="reachedSector" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <Script code="Mission endMission fail" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="hasDied" />
+            </trigger>
+        </events>
+    </Script>
+
+    <!--QUEST EFFECT BEACONS -->
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuest questId="quest1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="spawntrigger" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockedA" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuest questId="quest2.1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="reachedSector" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest2.1" />
+            <AddQuest questId="quest2.2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="reachedEnemyStation" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest2.2" />
+            <CompleteQuest questId="quest2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="fightEnd" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!--NOTIFICATIONS -->
+
+    <SimpleNotification broadcast="true" message="Welcome, Commander.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="We've picked up strange radio Signals from Sector 5B!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=8 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Please dock to the outer base and get into the scout ship!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=12 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="We have marked the sector in red Lights. Enter it!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=0 >
+                   <events>
+                      <trigger>
+                         <EventListener event="dockedA" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Huh? Something's emanating a strong field... We marked it in blue.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=0 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedSector" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Woah! What the hell? We made alien contact!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=0 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedEnemyStation" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="It looks like they are getting ready to attack someone...">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedEnemyStation" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="It must be us! Commander, get back to the base and report!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=8 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedEnemyStation" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Oh no! A patrol! When did it get here?!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=0 >
+                   <events>
+                      <trigger>
+                         <EventListener event="closeToPatrol" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Phew, that was close. Now get back here!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=0 >
+                   <events>
+                      <trigger>
+                         <EventListener event="fightEnd" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!--STATIONS -->
+
+    <Template name="station">
+        <Pawn mass=10000000 collisionType=dynamic friction=0.01>
+            <attached>
+                <Model mesh="HydroHarvester.mesh" position="0,0,0" scale=50 />
+                <DistanceTriggerBeacon name="NPC" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+                <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+                <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+                <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+                <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+                <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+                <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+                <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+                <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+                <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+                <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+                <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+                <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+                <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+                <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+                <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+            </collisionShapes>
+        </Pawn>
+    </Template>
+
+    <Pawn name="statA" team=0 radarname="Outer Base - Sector 4B" position="<?lua printC(cStationA) ?>" direction="<?lua printC(cSpawn) ?>" yaw=45 pitch=-5 roll=-25 initialhealth=10000 maxhealth=10000 >
+        <templates>
+            <Template link="station" />
+        </templates>
+        <attached>
+            <DockingTarget name="dockTargetA" />
+            <Dock position="0,0,0" active=true>
+                <animations>
+                    <MoveToDockingTarget target="dockTargetA" />
+                </animations>
+                <effects>
+                    <DockToShip target="newSpaceShip" />
+                </effects>
+                <events>
+                    <execute>
+                        <EventListener event="dockA" />
+                    </execute>
+                </events>
+                <attached>
+                    <DistanceTrigger position="0,0,0" distance="200" target="SpaceShip" beaconMode="exclude" targetname="NPC" name="dockA" />
+                    <Billboard position="0,0,0" amplitude=1 material="Flares/lensflare" colour="1,0,0.05" />
+                </attached>
+            </Dock>
+        </attached>
+    </Pawn>
+
+    <!-- EnemyStation -->
+
+    <!-- Marking Billboard -->
+    <Billboard visible=false position="<?lua printC(cEnemyBaseStation1) ?>" amplitude=30 scale=2 material="Flares/lensflare" colour="0,0,1">
+        <events>
+           <visibility>
+              <EventListener event="reachedSector" />
+          </visibility>
+        </events>
+    </Billboard>
+
+
+    <Pawn name="statB" team=1 radarname="EnemyBase" position="<?lua printC(cEnemyBaseStation1) ?>" direction="<?lua printC(cSpawn) ?>" yaw=45 pitch=-5 roll=-25 initialhealth=10000 maxhealth=10000 >
+        <templates>
+            <Template link="station" />
+        </templates>
+        <events>
+            <visibility>
+                <EventListener event="reachedEnemyStation" />
+            </visibility>
+            <activity>
+                <EventListener event="reachedEnemyStation" />
+            </activity>
+        </events>
+    </Pawn>
+
+    <!-- New SpaceShip as destination of dock A-->
+    <SpaceShip
+            template            = "spaceshipassff"
+            team                = "0"
+            position            = "<?lua printC(cNewShip) ?>"
+            lookat              = "<?lua printC(cSector) ?>"
+            health              = "1500"
+            initialhealth       = "1500"
+            maxhealth           = "1500"
+            shieldhealth        = "80"
+            initialshieldhealth = "80"
+            maxshieldhealth     = "120"
+            shieldabsorption    = "0.8"
+            reloadrate          = "1"
+            reloadwaittime      = "1"
+            name                = "newSpaceShip"
+            radarname           = "ScoutShip" >
+        <attached>
+            <DockingTarget name="newSpaceShip" />
+            <DistanceTriggerBeacon name="newSpaceShip" />
+        </attached>
+    </SpaceShip>
+
+    <!--ELEMENTS -->
+
+    <?lua
+    for i = 1, 64, 1
+    do
+    rBillboard = {math.sin(i*math.pi/32)*radSector, 0, math.cos(i*math.pi/32)*radSector}
+    cBillNow = addC(cSector,rBillboard)
+    ?>
+    <Billboard position="<?lua printC(cBillNow) ?>"  scale=10 material="Flares/lensflare" colour="1,0.2,0.2" visible=false>
+        <events>
+            <visibility>
+                <EventListener event="dockedA" />
+            </visibility>
+        </events>
+    </Billboard>
+    <?lua end ?>
+
+    <!-- Asteroids you have to fly through to get to the EnemyBase -->
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+       asteroidField(cField1[1], cField1[2], cField1[3], 20, 30, 4500, 500, 0)
+    ?>
+
+    <!-- Other Asteroid-Fields -->
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+       asteroidField(cField2[1], cField2[2], cField2[3], 20, 30, 4500, 500, 0)
+    ?>
+
+    <!-- Planets -->
+
+   <Planet
+        position="<?lua printC(cPlanet1) ?>"
+        scale="3000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/muunilinst.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage=2
+        enablecollisiondamage=true
+	      visible=true
+	      active=ture
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="6000" velocity="-500" />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="3000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(cPlanet1[1], cPlanet1[2], cPlanet1[3], 30, 20, 100, 20, 40, 3400, 3700, 400, 1)
+    ?>
+
+    <Planet
+        position="<?lua printC(cPlanet2) ?>"
+        scale="2000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/ganymede.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage=2
+        enablecollisiondamage=true
+	      visible=true
+	      active=true
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="4000" velocity="-500" />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="2000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(cPlanet2[1], cPlanet2[2], cPlanet2[3], 30, 20, 100, 20, 40, 3400, 3700, 400, 1)
+    ?>
+
+    <!-- EnemyPlanet(s) -->
+
+    <Planet
+        position="<?lua printC(cEnemyBasePlanet) ?>"
+        scale="5000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/jupiter.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage=2
+        enablecollisiondamage=true
+	      visible=false
+	      active=false
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="10000" velocity="-500" />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+      xi = 5
+      zi = 5
+      for k = 1, xi, 1
+      do
+    ?>
+    <?lua
+      for j = 1, zi, 1
+      do
+      x = -2500+k*100
+      z = -4400+j*100
+    ?>
+    <SpaceShip visible=false active=false name="enemyStalled" radarname="Attacker" position="-11000,<?lua print(z)?>,<?lua print(x)?>" lookat="0,0,0" team=1>
+        <templates>
+            <Template link="spaceshippirate" />
+        </templates>
+        <events>
+            <visibility>
+                <EventListener event="reachedEnemyStation" />
+            </visibility>
+        </events>
+    </SpaceShip>
+    <?lua end ?>
+    <?lua end ?>
+
+    <SpaceShip visible=false active=false name="enemy" radarname="Guard" position="-2700,-800,-800" lookat="0,0,0" team=1>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <events>
+          <visibility>
+              <EventListener event="reachedEnemyStation" />
+          </visibility>
+          <activity>
+              <EventListener event="reachedEnemyStation" />
+          </activity>
+      </events>
+      <controller>
+        <WaypointPatrolController active=false accuracy=40 alertnessradius=2000 team=1>
+            <events>
+                <activity>
+                    <EventListener event="reachedEnemyStation" />
+                </activity>
+            </events>
+          <waypoints>
+            <StaticEntity position="-3400,-1200,-200" />
+            <StaticEntity position="-1600,-1000,-200" />
+            <StaticEntity position="-1700,-1400,-940" />
+            <StaticEntity position="-2100,-1200,-1250" />
+            <StaticEntity position="-2700,-800,-800" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip visible=false active=false name="enemy" radarname="Guard" position="-3400,-1200,-200" lookat="0,0,0" team=1>
+        <events>
+            <visibility>
+                <EventListener event="reachedEnemyStation" />
+            </visibility>
+            <activity>
+                <EventListener event="reachedEnemyStation" />
+            </activity>
+        </events>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <controller>
+        <WaypointPatrolController active=false accuracy=40 alertnessradius=2000 team=1>
+            <events>
+                <activity>
+                    <EventListener event="reachedEnemyStation" />
+                </activity>
+            </events>
+          <waypoints>
+            <StaticEntity position="-1600,-1000,-200" />
+            <StaticEntity position="-1700,-1400,-940" />
+            <StaticEntity position="-2100,-1200,-1250" />
+            <StaticEntity position="-2700,-800,-800" />
+            <StaticEntity position="-3400,-1200,-200" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip visible=false active=false name="enemy" radarname="Guard" position="-1600,-1000,-200" lookat="0,0,0" team=1>
+        <events>
+            <visibility>
+                <EventListener event="reachedEnemyStation" />
+            </visibility>
+            <activity>
+                <EventListener event="reachedEnemyStation" />
+            </activity>
+        </events>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <controller>
+        <WaypointPatrolController active=false accuracy=40 alertnessradius=2000 team=1>
+            <events>
+                <activity>
+                    <EventListener event="reachedEnemyStation" />
+                </activity>
+            </events>
+          <waypoints>
+            <StaticEntity position="-1700,-1400,-940" />
+            <StaticEntity position="-2100,-1200,-1250" />
+            <StaticEntity position="-2700,-800,-800" />
+            <StaticEntity position="-3400,-1200,-200" />
+            <StaticEntity position="-1600,-1000,-200" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip visible=false active=false name="enemy" radarname="Guard" position="-1700,-1400,-940" lookat="0,0,0" team=1>
+        <events>
+            <visibility>
+                <EventListener event="reachedEnemyStation" />
+            </visibility>
+            <activity>
+                <EventListener event="reachedEnemyStation" />
+            </activity>
+        </events>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <controller>
+        <WaypointPatrolController active=false accuracy=40 alertnessradius=2000 team=1>
+            <events>
+                <activity>
+                    <EventListener event="reachedEnemyStation" />
+                </activity>
+            </events>
+          <waypoints>
+            <StaticEntity position="-2100,-1200,-1250" />
+            <StaticEntity position="-2700,-800,-800" />
+            <StaticEntity position="-3400,-1200,-200" />
+            <StaticEntity position="-1600,-1000,-200" />
+            <StaticEntity position="-1700,-1400,-940" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip visible=false active=false name="enemy" radarname="Guard" position="-2100,-1200,-1250" lookat="0,0,0" team=1>
+        <events>
+            <visibility>
+                <EventListener event="reachedEnemyStation" />
+            </visibility>
+            <activity>
+                <EventListener event="reachedEnemyStation" />
+            </activity>
+        </events>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <controller>
+        <WaypointPatrolController active=false accuracy=40 alertnessradius=2000 team=1>
+            <events>
+                <activity>
+                    <EventListener event="reachedEnemyStation" />
+                </activity>
+            </events>
+          <waypoints>
+            <StaticEntity position="-2700,-800,-800" />
+            <StaticEntity position="-3400,-1200,-200" />
+            <StaticEntity position="-1600,-1000,-200" />
+            <StaticEntity position="-1700,-1400,-940" />
+            <StaticEntity position="-2100,-1200,-1250" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/fightInOurBack.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/fightInOurBack.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/fightInOurBack.oxw	(revision 11817)
@@ -0,0 +1,531 @@
+<LevelInfo
+  name = "Fight in our Back"
+  description = "Our fleet is far ahead of us. We need to get rid of all the enemies in its back, because we do not want our enemies to attack from everywhere. So let us clear this Sector!"
+  screenshot = "fightinourback.png"  
+  tags = "mission" 
+/>
+
+<?lua
+    include("stats.oxo")
+    include("HUDTemplates3.oxo")
+    include("templates/lodInformation.oxt")
+    include("templates/spaceshipAssff.oxt")
+    include("templates/spaceshipPirate.oxt")
+    include("templates/spaceshipTransporter.oxt")
+?>
+
+<!--*****************************************************************************************************************************************************************************************-->
+<!--Including Template for triggering on player-->
+
+<Template name=spaceshipassffplayer>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   primaryThrust     = 100;
+   auxilaryThrust    = 30;
+   rotationThrust    = 25;
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+      <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+      <DistanceTriggerBeacon name="PlayerDistanceTrigger" /> <!--added DistanceTrigger-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+<?lua
+  include("includes/weaponSettingsAssff.oxi")
+?>
+  </SpaceShip>
+</Template>
+<Template name=spaceshipassffengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+      <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
+<!--*****************************************************************************************************************************************************************************************-->
+<Level
+  name="Fight in our back"
+  description="Our fleet is far ahead of us. We need to get rid of all the enemies in its back, because we do not want our enemies to attack from everywhere. So let us clear this Sector!"
+  gametype=Mission
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+    <!-- Ausgang: Szene ===> ambientlight/skybox -->
+    <Scene
+     ambientlight="0.8,0.8,0.8"
+     skybox="Orxonox/skyBoxBasic"
+    >
+
+        <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+        <!--Light: noch zu aendern -->
+        <Light type=directional position="0,0,0" direction="0, 0, 0" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 1.0, 0.9" />
+
+
+<!--*****************************************************************************************************************************************************************************************-->
+<!--Quests-->
+    <GlobalQuest id="FightInOurBack.DiscoveryMission_">
+        <QuestDescription title="Discovery mission" description="Your team has to scout out this sector." failMessage="You failed!" completeMessage="You won. You have reached the end of this level." />
+        <subquests>
+            <GlobalQuest id="FightInOurBack.FollowYourGroupLeader">
+                <QuestDescription title="Follow your group leader" description="Your task is to follow the team leader and to destroy all the enemy spaceships on your way!" failMessage="You failed!" completeMessage="Good job!" />
+            </GlobalQuest>
+            <GlobalQuest id="FightInOurBack.TransportersAhead">
+                <QuestDescription title="Transporters ahead" description="This is a lucky day for us. We have found supplies that the enemy is transporting in these Transporters. We have to destroy them." failMessage="You failed!" completeMessage="Good job!" />
+            </GlobalQuest>
+            <GlobalQuest id="FightInOurBack.TheySentUsAssistance">
+                <QuestDescription title="They sent us assistance" description="The transporters will surely be heavily protected but our base sent us assistance. It should now be easier to destroy them." failMessage="You failed" completeMessage="Good job!" />
+            </GlobalQuest>
+        </subquests>
+    </GlobalQuest>
+
+
+<!--Quests____END-->
+<!--*****************************************************************************************************************************************************************************************-->
+
+
+<!--Player's Spawnpoints -->
+        <!--Spieler Spawnpoint ===> position/direction--> <!-- funktioniert noch nicht ab naechtem Mal wahrscheinlich-->
+        <SpawnPoint position="0,50,25" direction="2000,0,-1000" spawnclass=SpaceShip pawndesign=spaceshipassffplayer team=0 active="true" >
+            <events>
+                <activity>
+                    <EventListener event="activateFirstSpawnpoint" />
+                </activity>
+            </events>
+        </SpawnPoint>
+
+        <SpawnPoint position="10000,0,3000" direction="2000,0,-1000" spawnclass=SpaceShip pawndesign=spaceshipassffplayer team=0 active="false" >
+            <events>
+                <activity>
+                    <EventListener event="activateSecondSpawnpoint" />
+                </activity>
+            </events>
+        </SpawnPoint>
+
+<!--Player's Spawnpoint END-->
+
+<!--Launching Quests -->
+        <QuestEffectBeacon position="0,50,25" times="1">
+            <effects>
+                <AddQuest questId="FightInOurBack.DiscoveryMission_" />
+                <AddQuest questId="FightInOurBack.FollowYourGroupLeader" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="FightInOurBack_MainStart_FollowStart"/>
+                </execute>
+            </events>
+            <attached>
+                <DistanceTrigger name="FightInOurBack_MainStart_FollowStart" position="0,0,0" distance="50" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" />
+                <!--<Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Examples/Flare" />-->
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="8000,0,3100" times=1 >
+            <effects>
+                <AddQuest questID="FightInOurBack.TransportersAhead" />
+                <AddQuest questID="FightInOurBack.TheySentUsAssistance" />
+                <CompleteQuest questID="FightInOurBack.FollowYourGroupLeader" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="FightInOurBack_FollowEnd_DTranspStart_AssisStart" />
+                </execute>
+            </events>
+            <attached>
+                <!--<Billboard position="0,0,0" colour="1,1,1" material="Examples/Flare" />-->
+                <DistanceTrigger name="FightInOurBack_FollowEnd_DTranspStart_AssisStart" position="0,0,0" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" stayactive=1 activations=1 />
+            </attached>
+        </QuestEffectBeacon>
+
+<!---->
+
+<!--Launching Quests END -->
+
+<!--Creating Transporters OK-->
+
+
+<?lua for i=0,0,1 do
+x=800
+health=1500
+?>
+    <!--Transporter 1-->
+    <EventTrigger name="activateTeam1No1" acitvations=1 stayactive="true">
+    <events>
+    <trigger>
+        <SpaceShip position="<?lua print(3800-i*x) ?>,0,3000" lookat="<?lua print(4800-i*x) ?>,0,4000" health="<?lua print(health) ?>" maxhealth="<?lua print(health) ?>" initialhealth="<?lua print(health) ?>" >
+            <templates>
+                   <Template link=spaceshipTransporter />
+             </templates>
+             <controller>
+                <WaypointPatrolController alertnessradius=1000 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(14800-i*x) ?>,0,3000"/>
+                    </waypoints>
+                </WaypointPatrolController>
+             </controller>
+        </SpaceShip><!---->
+    </trigger>
+    </events>
+    </EventTrigger>
+<?lua end ?>
+
+
+<?lua for j=0,1,1 do
+health=1300
+x=800
+z=j*300
+?>
+    <!--Transporter 2,3-->
+    <EventTrigger name="activateTeam1No1" acitvations=1 stayactive="true">
+    <events>
+    <trigger>
+        <SpaceShip position="<?lua print(2600+x) ?>,0,<?lua print(3150-z) ?>" lookat="<?lua print(3500+x) ?>,0,<?lua print(4150-z) ?>" health="<?lua print(health) ?>" maxhealth="<?lua print(health) ?>" initialhealth="<?lua print(health) ?>" >
+            <templates>
+                   <Template link=spaceshipTransporter />
+             </templates>
+             <controller>
+                <WaypointPatrolController alertnessradius=1000 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(13500+x) ?>,0,<?lua print(3150-z) ?>"/>
+                    </waypoints>
+                </WaypointPatrolController>
+             </controller>
+        </SpaceShip><!---->
+    </trigger>
+    </events>
+    </EventTrigger>
+<?lua end ?>
+
+
+<!--Creating Transporters END _-->
+
+<!--Creating player's team OK-->
+        <!--Spaceships team 0 (player:team=0)-->
+        <SpaceShip position="50,0,0" lookat="2050,0,-1000" health="500" maxhealth="500" initialhealth="500" >
+             <templates>
+                  <Template link=spaceshipassff />
+            </templates>
+             <controller>
+                <WaypointPatrolController alertnessradius=2000 team=0 >
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="2050,0,-1000" />
+                        <Model mesh="cube.mesh" scale=0 position="6050,0,0" />
+                        <Model mesh="cube.mesh" scale=0 position="10050,0,3000" />
+                        <Model mesh="cube.mesh" scale=0 position="3050,0,3000" />
+                        <Model mesh="cube.mesh" scale=0 position="-4050,0,3000" />
+                    </waypoints>
+                </WaypointPatrolController>
+             </controller>
+        </SpaceShip>
+        <!--Second Spaceship team 0 (player: team 0)-->
+        <SpaceShip position="0,0,100" lookat="2000,0,-950" health="500" maxhealth="400" initialhealth="400" >
+             <templates>
+                  <Template link=spaceshipassff />
+            </templates>
+             <controller>
+                <WaypointPatrolController alertnessradius=2000 team=0 >
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="2000,0,-900" />
+                        <Model mesh="cube.mesh" scale=0 position="6000,0,0" />
+                        <Model mesh="cube.mesh" scale=0 position="10000,0,3100" />
+                        <Model mesh="cube.mesh" scale=0 position="3000,0,3100" />
+                        <Model mesh="cube.mesh" scale=0 position="-4000,0,3100"/>
+                    </waypoints>
+                </WaypointPatrolController>
+             </controller>
+        </SpaceShip>
+        <!--third Spaceship team 0 (player: team 0)-->
+        <SpaceShip position="0,0,-100" lookat="2000,0,-1050" health="500" maxhealth="400" initialhealth="400" >
+             <templates>
+                  <Template link=spaceshipassff />
+            </templates>
+             <controller>
+                <WaypointPatrolController alertnessradius=2000 team=0 >
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="2000,0,-1100" />
+                        <Model mesh="cube.mesh" scale=0 position="6000,0,-100" />
+                        <Model mesh="cube.mesh" scale=0 position="10000,0,2900" />
+                        <Model mesh="cube.mesh" scale=0 position="3000,0,2900" />
+                        <Model mesh="cube.mesh" scale=0 position="-4000,0,2900" />
+                    </waypoints>
+                </WaypointPatrolController>
+             </controller>
+        </SpaceShip>
+<!--Creating player's team END  -->
+
+
+<!--Asteroids (field OK -->
+
+<?lua for i=0,100,1 do
+x=math.random(250,4000)
+y=math.random(-500,500)
+z=math.random(1000,2000)
+scale=math.random(20,70)
+?>
+<MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=0 mass="<?lua print(scale * 5) ?>" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" rotationaxis="<?lua print(math.random()) ?>,<?lua print(math.random()) ?>,<?lua print(math.random()) ?>" rotationrate="<?lua print(math.random()*15) ?>">
+    <attached>
+        <Model scale="<?lua print(scale) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false/>
+    </attached>
+    <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(scale * 3) ?>" />
+    </collisionShapes>
+</MovableEntity>
+<?lua end ?>
+
+<!--Asteroids (field) END -->
+
+<!--Asteroids (random) END OK-->
+
+<?lua for i=0,150,1 do
+x=math.random(-8000,8000)
+y=math.random(-8000,8000)
+z=math.random(-8000,8000)
+?>
+<MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=0 mass="<?lua print(scale * 5) ?>" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" rotationaxis="<?lua print(math.random()) ?>,<?lua print(math.random()) ?>,<?lua print(math.random()) ?>" rotationrate="<?lua print(math.random()*15) ?>" >
+    <attached>
+        <Model scale="<?lua print(math.random(20,70)) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false/>
+    </attached>
+    <collisionShapes>
+            <SphereCollisionShape radius="<?lua print(scale * 3) ?>" />
+        </collisionShapes>
+</MovableEntity>
+<?lua end ?>
+
+<!--Asteroids (random) END -->
+
+<!--Creating spaceships (player's team) OK-->
+<!---->
+<!--Trigger to activate this Team (TEAM NO 1)-->
+    <DistanceTrigger name="activateTeam0No1" position="8000,0,3100" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
+
+<!--TEAM NO 1 (activationType : distance || killing a spaceship what belongs to TEAM 0 NO 0)-->
+<?lua for i=0,14,1 do
+x=math.random(-500,500)
+y=math.random(-300,300)
+z=math.random(-300,300)
+?>
+    <EventTrigger name="activateTeam0No1" activations=1 stayactive="true">
+        <events>
+            <trigger>
+                <SpaceShip position="<?lua print(x+4500) ?>,<?lua print(y) ?>,<?lua print(z+6000) ?>" lookat="<?lua print(4000+x) ?>,<?lua print(y) ?>,<?lua print(z+3000) ?>">
+                    <templates>
+                        <Template link=spaceshipassff />
+                    </templates>
+                    <controller>
+                        <WaypointPatrolController alertnessradius=2100 team=0 active=false>
+                            <waypoints>
+                                <Model mesh="cube.mesh" scale=0 position="<?lua print(4500+x) ?>,<?lua print(y) ?>,<?lua print(z+3000) ?>" />
+                                <Model mesh="cube.mesh" scale=0 position="<?lua print(x-4000) ?>,<?lua print(y) ?>,<?lua print(z+3000) ?>" />
+                            </waypoints>
+                            <events>
+                                <activity>
+                                    <EventListener event="activateTeam0No1" />
+                                </activity>
+                            </events>
+                        </WaypointPatrolController>
+                    </controller>
+                </SpaceShip>
+            </trigger>
+        </events>
+    </EventTrigger>
+
+
+<?lua end ?>
+
+<!---->
+<!--Creating spaceships (player's team) END -->
+
+<!--Creating spaceships (enemy) OK-->
+<!---->
+<!--TEAM 1 NO 1 (activationType : killing a Transporter || killing a spaceship what belongs to TEAM 1 NO 1)-->
+<?lua for i=0,11,1 do
+x=math.random(-500,500)
+y=math.random(-300,300)
+z=math.random(-300,300)
+?>
+    <EventTrigger name="activateTeam1No1" activations=1 stayactive="true" >
+        <events>
+            <trigger>
+                <SpaceShip position="<?lua print(x+3800) ?>,<?lua print(y+3000) ?>,<?lua print(z+3000) ?>" lookat="<?lua print(4000+x) ?>,<?lua print(y) ?>,<?lua print(z+3000) ?>">
+                    <templates>
+                        <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                        <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+                            <waypoints>
+                                <Model mesh="cube.mesh" scale=0 position="<?lua print(4000+x) ?>,<?lua print(y) ?>,<?lua print(z+3000) ?>" />
+                            </waypoints>
+                            <events>
+                                <activity>
+                                    <EventListener event="activateTeam1No1" />
+                                </activity>
+                            </events>
+                        </WaypointPatrolController>
+                    </controller>
+                </SpaceShip>
+            </trigger>
+        </events>
+    </EventTrigger>
+
+<?lua end ?>
+<!---->
+<!--Creating spaceships (enemy) END -->
+
+<!--Enemies on the way to the transporters -->
+
+<?lua for i=0,1,1 do
+z=math.random(-300,300)
+?>
+<!--NO 1-->
+        <SpaceShip position="<?lua print(5900+i*100) ?>,0,-3000" lookat="2500,0,-1000">
+            <templates>
+                <Template link=spaceshippirate/>
+            </templates>
+            <controller>
+                <WaypointPatrolController alertnessRadius=1500 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(2500+100*i) ?>,0,-1000" />
+                    </waypoints>
+                </WaypointPatrolController>
+            </controller>
+        </SpaceShip>
+
+<!--NO 4-->
+        <SpaceShip position="<?lua print(9000) ?>,13000,<?lua print(z*i+3000) ?>" lookat="1000,0,3000">
+            <templates>
+                <Template link=spaceshippirate/>
+            </templates>
+            <controller>
+                <WaypointPatrolController alertnessRadius=1500 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(10000) ?>,0,<?lua print(3000+z*i) ?>" />
+                    </waypoints>
+                </WaypointPatrolController>
+            </controller>
+        </SpaceShip>
+<?lua end ?>
+
+
+<!--NO 3-->
+        <SpaceShip position="<?lua print(200+13000) ?>,0,10000" lookat="8000,0,1000">
+            <templates>
+                <Template link=spaceshippirate/>
+            </templates>
+            <controller>
+                <WaypointPatrolController alertnessRadius=1500 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(200+8000) ?>,0,1000" />
+                    </waypoints>
+                </WaypointPatrolController>
+            </controller>
+        </SpaceShip>
+<?lua for i=0,1,1 do ?>
+        <SpaceShip position="<?lua print(i*400+13000) ?>,100,10000" lookat="8000,0,1000">
+            <templates>
+                <Template link=spaceshippirate/>
+            </templates>
+            <controller>
+                <WaypointPatrolController alertnessRadius=1500 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(i*400+8000) ?>,0,1000" />
+                    </waypoints>
+                </WaypointPatrolController>
+            </controller>
+        </SpaceShip>
+<?lua end ?>
+
+
+<!--NO 2-->
+<?lua for i=0,3,1 do ?>
+        <SpaceShip position="<?lua print(math.random(5500,6500)+2000) ?>,0,1000" lookat="2500,0,-1000">
+            <templates>
+                <Template link=spaceshippirate/>
+            </templates>
+            <controller>
+                <WaypointPatrolController alertnessRadius=1500 team=1>
+                    <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(math.random(5750,6250)+2000) ?>,0,1250" />
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(math.random(5750,6250)+2000) ?>,250,1000" />
+                        <Model mesh="cube.mesh" scale=0 position="<?lua print(math.random(5750,6250)+2000) ?>,0,1000" />
+                    </waypoints>
+                </WaypointPatrolController>
+            </controller>
+        </SpaceShip>
+<?lua end ?>
+
+<!--Creating spaceships (enemy) END -->
+
+<Trigger invert=true name="activateFirstSpawnpoint">
+    <DistanceTrigger name="activateSecondSpawnpoint" position="10000,0,3000" distance="1000" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" activations="1" stayactive="true" />
+</Trigger>
+
+    </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/gallery.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/gallery.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/gallery.oxw	(revision 11817)
@@ -0,0 +1,238 @@
+<!-- Collection of almost all models in orxonox -->
+<LevelInfo
+ name =        "Gallery"
+ description = "Collection of almost all models."
+ tags =        "test, showcase"
+ screenshot =  "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+
+<!---
+    Gallery:
+    all Objects are organized in columns
+---->
+
+<!--- Spacestation --->
+      <!--Model position="0,0,-160" yaw="90" pitch="-90" roll="0" scale="1" mesh="ss_box_lowpoly.mesh" /-->
+      <Model position="0, 20,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_box_lowpoly_ad1.mesh" />
+      <Model position="0, 40,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_box_lowpoly_ad2.mesh" />
+      <Model position="0, 60,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_box_lowpoly_ad3.mesh" />
+      <Model position="0, 80,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_box_lowpoly_ad4.mesh" />
+      <Model position="0,-20,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_tube.mesh" />
+      <Model position="0,-40,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_tube_twd.mesh" />
+      <Model position="0,-60,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_tube_x.mesh" />
+      <Model position="0,-80,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_wall.mesh" />
+      <Model position="0,-100,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_table_cracked.mesh" />
+      <Model position="0,-120,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_table.mesh" />
+      <Model position="0,-140,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_spind.mesh" />
+      <Model position="0,-160,-160" yaw="90" pitch="-90" roll="0" scale="0.01" mesh="ss_machine.mesh" />
+      <Model position="0,-180,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_flag_room.mesh" />
+      <Model position="0,-200,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_flag_eu.mesh" />
+      <Model position="0,-220,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_flag_csa.mesh" />
+      <Model position="0,-240,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_flag_cau.mesh" />
+      <Model position="0,-260,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_flag_aean.mesh" />
+      <Model position="0,-280,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_door.mesh" />
+      <Model position="0,-300,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_cylinder.mesh" />
+      <Model position="0,-320,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_curve.mesh" />
+      <Model position="0,-340,-160" yaw="90" pitch="-90" roll="0" scale="5" mesh="ss_chair.mesh" />
+      
+
+<!--- Whole Objects --->
+      <Model position="0, 0,-120" yaw="90" pitch="0" roll="0" scale="1" mesh="HydroHarvester.mesh" />
+
+      <Model position="0,30,-130" yaw="90" pitch="-90" roll="0" scale=1 mesh="DuBall2.mesh" />
+      <Model position="0,30,-110" yaw="90" pitch="-90" roll="0" scale=1 mesh="DuBall1.mesh" />
+
+      <StaticEntity position="0,60,-120" yaw=0 pitch=0>
+       <attached>
+        <Model position="0,0,0" mesh="turretSocketFront.mesh" scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketIn.mesh"    scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketTop.mesh"   scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketLeft.mesh"  scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketRight.mesh" scale3D="10,10,10" />
+      </attached>
+     </StaticEntity>
+
+
+
+
+
+<!--- PLANETS --->
+      <!--Model position="0,0,-80" yaw="90" pitch="-90" roll="0" scale="1" mesh="planet.mesh" /-->
+      <Model position="0, 20,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="iceplanet.mesh" />
+      <Model position="0, 40,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/earth.mesh" />
+      <Model position="0, 60,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/moon.mesh" />
+      <Model position="0, 80,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/sol.mesh" />
+      <Model position="0,-20,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/ganymede.mesh" />
+      <Model position="0,-40,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/jupiter.mesh" />
+      <Model position="0,-60,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/muunilinst.mesh" />
+      <Model position="0,-80,-80" yaw="90" pitch="-90" roll="0" scale="5" mesh="planets/planet3.mesh" />
+
+
+
+<!--- WEAPONS --->
+      <!--Model position="0,0,-40" yaw="90" pitch="-90" roll="0" scale="1" mesh="stunweapon.mesh" /-->
+      <Model position="0, 20,-40" yaw="90" pitch="-90" roll="0" scale="2" mesh="LightningGun.mesh" />
+      <Model position="0, 40,-40" yaw="90" pitch="-90" roll="0" scale="2" mesh="LightningGun-s.mesh" />
+      <Model position="0, 60,-40" yaw="90" pitch="-90" roll="0" scale="1.5" mesh="LaserBeam2.mesh" />
+      <Model position="0, 80,-40" yaw="90" pitch="-90" roll="0" scale="2" mesh="rocket.mesh" />
+      <Model position="0,-20,-40" yaw="90" pitch="-90" roll="0" scale="5" mesh="hs-w01.mesh" />
+      <Model position="0,-40,-40" yaw="90" pitch="-90" roll="0" scale="5" mesh="hs-w01s.mesh" />
+      <Model position="0,-60,-40" yaw="90" pitch="-90" roll="0" scale="2" mesh="hs-w01_reduced.mesh" />
+      <Model position="0,-80,-40" yaw="90" pitch="-90" roll="0" scale="0.5" mesh="Spacebomb.mesh" />
+
+    
+<!--- SPACESHIPS --->
+      <Model position="0,  0,  0" yaw="90" pitch="-90" roll="0" scale="4" mesh="assff.mesh" />
+      <Model position="0, 20,  0" yaw="90" pitch="-90" roll="0" scale="4" mesh="pirate.mesh" />
+      <Model position="0, 40,  0" yaw="90" pitch="-90" roll="0" scale="0.7" mesh="Carrier.mesh" />
+      <Model position="0, 60,  0" yaw="90" pitch="-90" roll="0" scale="1" mesh="ghost.mesh" />
+      <Model position="0, 80,  0" yaw="90" pitch="-90" roll="0" scale="1" mesh="h2_green.mesh" />
+      <Model position="0,100,  0" yaw="0" pitch="0" roll="0" scale="1" mesh="collateralDamage.mesh" />
+      <Model position="0,-20,-10" yaw="180" pitch="-90" roll="0" scale="4" mesh="HXY.mesh" />
+      <Model position="0,-40,  0" yaw="90" pitch="-90" roll="0" scale="1" mesh="spacecruiser.mesh" />
+      <Model position="0,-60,  0" yaw="90" pitch="-90" roll="0" scale="1" mesh="swallow_mat.mesh" />
+
+      <Model position="0,-80,  0" yaw="0" pitch="0" roll="0" scale="1" mesh="Transporter.mesh" />
+      
+      
+
+<!--- ASTEROIDS --->
+      <Model position="0,  0,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast1.mesh" />
+      <Model position="0, 20,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast2.mesh" />
+      <Model position="0, 40,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast3.mesh" />
+      <Model position="0, 60,40" yaw="90" pitch="-90" roll="0" scale="3" mesh="ast4.mesh" />
+      <Model position="0,-20,40" yaw="90" pitch="-90" roll="0" scale="4" mesh="ast5.mesh" />
+      <Model position="0,-40,40" yaw="90" pitch="-90" roll="0" scale="4" mesh="ast6.mesh" />
+      <Model position="0,-60,40" yaw="90" pitch="-90" roll="0" scale="5" mesh="asteroid_ice.mesh" />
+      <Model position="0,-80,40" yaw="90" pitch="-90" roll="0" scale="5" mesh="asteroid_UV.mesh" />
+
+
+<!--- Satellites & co --->
+      <Model position="0,  0,80" yaw="90" pitch="-90" roll="0" scale="3" mesh="satellite.mesh" />
+      <Model position="0, 20,80" yaw="90" pitch="0" roll="0" scale="3" mesh="broke-satellite.mesh" />
+      <Model position="0, 40,80" yaw="90" pitch="-90" roll="0" scale="3" mesh="satellitedish.mesh" />
+      <Model position="0, 60,80" yaw="90" pitch="-90" roll="0" scale="3" mesh="SolarPanel.mesh" />
+      <Model position="0, 80,80" yaw="90" pitch="0" roll="0" scale="2" mesh="drone.mesh" />
+      <Model position="0,-20,80" yaw="90" pitch="0" roll="0" scale="3" mesh="drone.mesh" />
+      <Model position="0,-40,80" yaw="90" pitch="-90" roll="0" scale="4" mesh="Thruster.mesh" />
+
+
+
+
+<!--- ABSTRACT SHAPES --->
+      <Model position="0,  0,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="sphere.mesh" />
+      <!--Model position="0,20,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="blackcube.mesh" /-->
+      <Model position="0, 40,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="cube.mesh" />
+      <Model position="0, 60,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="cube_green.mesh" />
+      <Model position="0, 80,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="cube_orange.mesh" />
+      <Model position="0,-20,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="CubeGround.mesh" />
+      <Model position="0,-40,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="cube_red.mesh" />
+      <Model position="0,-60,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="testcube.mesh" />
+      <Model position="0,-80,120" yaw="90" pitch="-90" roll="0" scale="3" mesh="cylinder.mesh" />
+
+
+<!--- SPACEJUNK --->
+      <Model position="0, 0,160" yaw="90" pitch="-90" roll="0" scale="8" mesh="debris-steelbeam.mesh" />
+      <Model position="0,20,160" yaw="90" pitch="-90" roll="0" scale="2" mesh="Thruster.mesh" />
+      <Model position="0,40,160" yaw="90" pitch="-90" roll="0" scale="1" mesh="crate.mesh" />
+      <Model position="0,60,160" yaw="90" pitch="-90" roll="0" scale="3" mesh="debris-fueltank.mesh" />
+      <Model position="0,80,160" yaw="90" pitch="-90" roll="0" scale="3" mesh="debris-glass.mesh" />
+      <!--Model position="0,-20,160" yaw="90" pitch="-90" roll="0" scale="3" mesh="debris-pile01.mesh" />
+      <Model position="0,-40,160" yaw="90" pitch="-90" roll="0" scale="3" mesh="debris-pile02.mesh" />
+      <Model position="0,-60,160" yaw="90" pitch="-90" roll="0" scale="3" mesh="debris-pile03.mesh" />
+      <Model position="0,-80,160" yaw="90" pitch="-90" roll="0" scale="3" mesh="debris-plane.mesh" />
+
+
+
+<!--- STUFF --->
+      <Model position="0,  0,200" yaw="90" pitch="-90" roll="0" scale="3" mesh="can.mesh" />
+      <Model position="0, 20,200" yaw="90" pitch="-90" roll="0" scale="3" mesh="cokebottle.mesh" />
+      <Model position="0, 40,200" yaw="90" pitch="-90" roll="0" scale="3" mesh="Tower.mesh" />
+      <!--Model position="0,60,200" yaw="90" pitch="-90" roll="0" scale="3" mesh="Tower_ME.mesh" /-->
+      <!--Model position="0,80,200" yaw="90" pitch="-90" roll="0" scale="5" mesh="SmallPart1.mesh" /-->
+      <Model position="0,-20,200" yaw="90" pitch="-90" roll="0" scale="4" mesh="raceCheckPoint.mesh" />
+      <Model position="0,-40,200" yaw="90" pitch="0" roll="0" scale="0.5" mesh="Spacegate.mesh" />
+
+      <Model position="0,-60,200" yaw="90" pitch="-90" roll="0" scale="0.5" mesh="BigSpacegate.mesh" />
+      <!--Model position="0,-80,200" yaw="90" pitch="-90" roll="0" scale="5" mesh="SmallPart2" /> <!--- WHY doesn't it load ??--->
+
+<!--- The REST --->
+      <Model position="0,   0,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="axes.mesh" />
+      <Model position="0,  20,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="BodyDebris1.mesh" />
+      <Model position="0,  40,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="CockpitDebris.mesh" />
+      <Model position="0,  60,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="CuboidBody.mesh" />
+      <Model position="0,  80,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="CuboidConnBody.mesh" />
+      <Model position="0, -20,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="CuboidConnection.mesh" />
+      <Model position="0, -40,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="CuboidLandingZone.mesh" />
+      <Model position="0, -60,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="DoubleCuboidBody.mesh" />
+      <Model position="0, -80,240" yaw="90" pitch="-90" roll="0" scale="1" mesh="plane.mesh" />
+      <Model position="0,-100,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="WingDebris1.mesh" />
+      <Model position="0,-120,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="WingDebris2.mesh" />
+      <Model position="0,-140,240" yaw="90" pitch="-90" roll="0" scale="5" mesh="SemiCircleCockpit.mesh" />
+      <Model position="0,-160,240" yaw="90" pitch="-90" roll="0" scale="1" mesh="Playfield_ME.mesh" />
+
+<!--- Big ship: Planetary Destroyer --->
+	<Model position="0,   0,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsBody.mesh" />
+	<Model position="0,  30,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsDuseL.mesh" />
+	<Model position="0,  60,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsDuseR.mesh" />
+	<Model position="0,  90,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsKuppelV.mesh" />
+	<Model position="0, 120,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsKuppelK.mesh" />
+	<Model position="0, -30,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsAntL.mesh" />
+	<Model position="0, -60,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsAntR.mesh" />
+	<Model position="0, -90,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsGarage.mesh" />
+	<Model position="0,-120,280" yaw=0 pitch=180 roll=0 scale=1 mesh="bsStation.mesh" />
+
+
+
+
+<!-- BILLBOARDS - Flares -->
+    <Billboard position="-400,0,0" material="Flares/ringflare" colour="0.7,0.4,0.1" scale=1/>
+    <Billboard position="-400,60,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+    <Billboard position="-400,120,0" material="Flares/point_lensflare" colour="0.7,0.4,0.1" scale=0.5/>
+    <Billboard position="-400,180,0" material="Flares/Flare" colour="0.7,0.4,0.1" scale=1/>
+    <Billboard position="-400,-60,0" material="Flares/backlightflare" colour="0.7,0.4,0.1" scale=1/>
+    <Billboard position="-400,-120,0" material="Flares/ThrusterFlare1" colour="0.7,0.4,0.1" scale=1/>
+    <Billboard position="-400,-180,0" material="Flares/LightningBall_1" colour="0.7,0.4,0.1" scale=1/>
+    <Billboard position="-400,-240,0" material="Portals/Default" />
+
+
+
+<!-- Particle Emitters -->
+    <ParticleEmitter pitch=-135 roll=30 position="-400,0,300" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+
+
+
+
+
+
+
+
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/iJohnVane_TriptoArea51.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/iJohnVane_TriptoArea51.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/iJohnVane_TriptoArea51.oxw	(revision 11817)
@@ -0,0 +1,669 @@
+<!-- -->
+
+<LevelInfo
+   name = "(i) John Vane - Trip to Area 51"
+   description = "John Vane's first mission to rescue the Commander."
+   tags = "mission"
+   screenshot = "JohnVane.png" 
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+?>
+
+<Level gametype="Mission">
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=3.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+    hasPhysics   = true
+
+  >
+
+   <?lua
+      include("includes/pickups.oxi")
+   ?>
+
+   <?lua
+    dofile("includes/CuboidSpaceStation.lua")
+   ?>
+
+
+   <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>    
+
+   <TeamSpawnPoint team=0 position="0,0,0" direction="1,1,1" spawnclass=SpaceShip pawndesign=spaceshipescort>
+         <events>
+            <activity>
+                <EventListener event="start" />
+            </activity>
+        </events>
+    </TeamSpawnPoint>
+   <!-- HELPER FOR LEVEL DESIGNERS: go directly to the racing part of the level -->
+   <!--TeamSpawnPoint team=0 position="0,94000,0" lookat="0,118000,0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage/-->
+
+   <Script code="Mission setLives 1" onLoad="true" times="1" />
+
+   <DistanceTrigger name="spawntrigger" position="0,0,0" distance=10 target="SpaceShip" stayActive="true" delay=0.1/>
+
+<!----------------------------------------------------------------------------------------------------->
+<!-------------------------------------- PART ZERO: Docking on  --------------------------------------->
+<!----------------------------------------------------------------------------------------------------->
+
+<!-- OBJECTS IN THIS PART -->
+
+<!-- @Objects: HYDROGEN FARMER & DOCKING -->
+   
+<!-- @Objects: HYDROGEN FARMER & DOCKING -->
+   <SpaceShip
+        team      = 0
+        position  = "5000,5100,5000"
+        roll      = 90   yaw=0  pitch=20
+        mass      = 10000
+        health    = 100000 initialhealth=100000 maxhealth="100000"
+        name      = "HydroFarmer"
+        radarname = "Main station" > 
+      <attached>
+        <!-- Docking -->
+         <DistanceTriggerBeacon name="bcnDestroyer" />
+         <DockingTarget name="destroyer" />
+
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+   <!-- <Model mesh="cube.mesh" mass=10 position="-560,0,0" scale3D="115,100,245"  />
+        <Model mesh="cube.mesh" mass=10 position="290,0,-480" scale3D="115,100,245" yaw=-120 />
+        <Model mesh="cube.mesh" mass=10 position="290,0,480" scale3D="115,100,245" yaw=-240 />
+        <Model mesh="cube.mesh" mass=10 position="-280,0,0" scale3D="163,50,50" />
+        <Model mesh="cube.mesh" mass=10 position="140,0,-240" scale3D="163,50,50"  yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="140,0,240" scale3D="163,50,50" yaw=-240/>
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" />
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" yaw=-240/>
+        <Model mesh="cube.mesh" mass=10 position="0,400,0" scale3D="43,110,26" yaw=-30 />
+        <Model mesh="cube.mesh" mass=10 position="-200,100,0" scale3D="26,50,43" />
+        <Model mesh="cube.mesh" mass=10 position="100,100,-173" scale3D="43,50,26" yaw=-30/>
+        <Model mesh="cube.mesh" mass=10 position="100,100,173" scale3D="43,50,26" yaw=30/>
+        <Model mesh="cube.mesh" mass=10 position="-100,264,0" scale3D="26,105,43" roll=-49/>
+        <Model mesh="cube.mesh" mass=10 position="50,264,-87" scale3D="26,105,43" roll=-49 yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="50,264,87" scale3D="26,105,43" roll=-49 yaw=-240/>     -->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </SpaceShip>
+
+   <Dock position="5000,5000,5000" roll=90 yaw=180 >
+      <animations>
+         <MoveToDockingTarget target="destroyer" />
+      </animations>
+      <effects>
+         <DockToShip target="spaceShip" />
+      </effects>
+      <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+            <activity>
+                <EventListener event=notGameEnd />
+            </activity>
+        </events>
+        <attached>
+            <DistanceTrigger position="10,-202, -42" distance="800" target="Pawn"
+                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"/>
+       <Billboard position="10,-202,-42" material="Flares/ringflare" colour="0.7,0.4,0.1" scale=1/>
+        </attached>
+
+    </Dock> 
+
+<!--@Objects: SpaceCruiser as docking target -->
+    <SpaceShip
+        template            = "spaceshipcollateraldamage"
+        team                = "0"
+        position            = "5000,5800,5000"
+        orientation         = "-0.14, 0.68, 0.68, 0.223"
+        health              = "400"
+        initialhealth       = "400"
+        maxhealth           = "500"
+        shieldhealth        = "80"
+        initialshieldhealth = "80"
+        maxshieldhealth     = "120"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "1"
+        shieldrechargewaittime = "1"
+        name                = "cruiser"
+        radarname           = "Spacecruiser" >
+      <attached>
+        <DockingTarget name="spaceShip" />
+      </attached>
+    </SpaceShip>
+
+
+<BlinkingBillboard position="1500,1500,1500" frequency=0.6 amplitude=3 material="Flares/lensflare" colour="1,1,0.05">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=flying3 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</BlinkingBillboard>
+<Billboard position="1500,1500,1500" amplitude=1 material="Flares/lensflare" colour="0,0.8,0.1">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=flying4 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</Billboard>
+
+  <DistanceTrigger name="flying1" position="0,0,0" target="Pawn" distance=100 stayActive="true" delay=1/>
+    <SimpleNotification message="Housten: John Vane do you hear us?">
+        <events>
+            <trigger>
+                <EventListener event="flying1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+   <DistanceTrigger name="flying2" position="0,0,0" target="Pawn" distance=100 stayActive="true" delay=5/>
+   <SimpleNotification message="Housten: We got a new mission for you">
+        <events>
+            <trigger>
+                <EventListener event="flying2" />
+            </trigger>
+        </events>
+   </SimpleNotification>
+
+
+  <DistanceTrigger name="flying3" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=9/>
+    <SimpleNotification message="John: I hear you. What is it about?">
+        <events>
+            <trigger>
+                <EventListener event="flying3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+ <DistanceTrigger name="flying4" position="0,0,0" target="Pawn" distance=100 stayActive="true" delay=13/>
+    <SimpleNotification message="Housten: Our Commander was kidnapped">
+        <events>
+            <trigger>
+                <EventListener event="flying4" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+ <DistanceTrigger name="flying5" position="0,0, 0" target="Pawn" distance=100 stayActive="true" delay=17/>
+    <SimpleNotification message="Housten: We need you to rescue him.">
+        <events>
+            <trigger>
+                <EventListener event="flying5" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<DistanceTrigger name="flying6" position="0,0, 0" target="Pawn" distance=100 stayActive="true" delay=21/>
+    <SimpleNotification message="John: I'm right on the way.">
+        <events>
+            <trigger>
+                <EventListener event="flying6" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<DistanceTrigger name="flying7" position="0,0,0" target="Pawn" distance=100 stayActive="true" delay=25/>
+    <SimpleNotification message="Houston: First dock on the station">
+        <events>
+            <trigger>
+                <EventListener event="flying7" />
+            </trigger>
+        </events>
+    </SimpleNotification> 
+
+   <QuestEffectBeacon times=1>
+      <effects>
+                <AddQuest questId="Level_Kaan.docking" />
+      </effects>
+            <events>
+                <execute>
+                    <EventListener event=spawntrigger />
+                </execute>
+            </events>
+   </QuestEffectBeacon>
+
+   <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="Level_Kaan.docking" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="dockMe" />
+                </execute>
+            </events>
+   </QuestEffectBeacon>
+
+   <LocalQuest id="Level_Kaan.docking">
+      <QuestDescription title="Docking" description="Our Commander was kidnapped in Area 51. Fly to the Main Station and get a better Spaceship to rescue him.
+
+    Flying moves:
+    break (S)
+    roll     (Q) and (E)
+    boost (Space)
+
+    Whenever a new quest is added you can view it by pressing (F3). Quit this menu via (Esc)." failmessage="" completeMessage="" />
+      <complete-effects>
+         <AddQuest questId="Level_Kaan.portals" />
+      </complete-effects>
+   </LocalQuest> 
+
+   <LocalQuest id="Level_Kaan.portals">
+      <QuestDescription title="Portals" description="Now you received a spaceship that is suited for your mission.
+It is faster, has more health and is equipped with stronger weapons.
+Your next goal is to pass through the portal and find there the wormhole to Area 51" failmessage="" completeMessage="" />
+      <complete-effects>
+         <AddQuest questId="Level_Kaan.asteroids" />
+      </complete-effects>
+   </LocalQuest> 
+
+
+   <QuestEffectBeacon times=1>
+      <effects>
+         <CompleteQuest questId="Level_Kaan.portals" />
+      </effects>
+      <events>
+         <execute>
+            <EventListener event=start />
+         </execute>
+      </events>
+   </QuestEffectBeacon>
+
+ <LocalQuest id="Level_Kaan.asteroids">
+      <QuestDescription title="Asteroids" description="The wormhole is at the end of the asteroid shower.
+Find your way through the asteroids without hitting the rocks and reach Area 51.
+You have to get there in time - the wormhole cannot be forced open forever.
+Your Mission is to fly straight through the wormhole." failmessage="" completeMessage="" />
+   </LocalQuest> 
+
+ <QuestEffectBeacon times=1>
+      <effects>
+         <CompleteQuest questId="Level_Kaan.asteroids" />
+      </effects>
+      <events>
+         <execute>
+            <EventListener event=endOfLevel />
+         </execute>
+      </events>
+   </QuestEffectBeacon>
+
+<!----------------------------------------------------------------------------------------------------->
+<!-------------------------------- PART ONE: Passing throug wormhole  --------------------------------->
+<!----------------------------------------------------------------------------------------------------->
+
+
+<!------------------------------------- OBJECTS IN THIS PART  lookat="0,118000,0" ------------------------------------------>
+
+   <Template name=PortalDefault>
+      <PortalEndPoint>
+         <attached>
+            <Model mesh="Spacegate.mesh" />
+         </attached>
+      </PortalEndPoint>
+   </Template>
+
+   <PortalEndPoint position="5000,6400,5000" id="1" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0" lookat="5000,5800,5000"/>
+   <PortalEndPoint position="0,94000,0" id="2" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0" />
+   <PortalLink fromID="1" toID="2" />
+   <!--<PortalLink fromID="2" toID="1" />-->
+
+<!-- Meteoriten, die sich bewegen -->
+   <?lua
+      for i = 1, 300, 1
+      do
+      j = math.random()
+      x = math.random()
+      y = math.random()
+      z = math.random()
+   ?>
+
+   <MovableEntity    
+      position = "<?lua print(math.random()* 600-300) ?>,<?lua print(math.random() * 40000 + 97000) ?>,<?lua print(math.random() * 600-300) ?>"
+      scale = "<?lua print(j * 40)?>"
+      velocity = "<?lua print(x*20-10)?>, <?lua print(y*60-160)?>, <?lua print(z*20-10)?>"
+      collisionType = dynamic
+      collisiondamage = 0.05
+      enablecollisiondamage = true 
+      active = false
+   >                 
+          <attached>           
+              <Model mass="<?lua print(j * 1000) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+          </attached> 
+         <collisionShapes>
+             <SphereCollisionShape radius="<?lua print(j * 50) ?>" />
+         </collisionShapes>   
+         <events>           
+           <activity>           
+             <EventListener event="portal3" />           
+           </activity>           
+         </events>
+   </MovableEntity>
+
+   <?lua
+      end
+   ?>
+
+
+<!-- Fiese Meteoriten, die direkt auf den Spieler zufliegen-->
+
+   <?lua
+      for i = 1, 240, 1
+      do
+      j = math.random()
+      x = math.random()
+      y = math.random()
+      z = math.random()
+   ?>
+   <MovableEntity    
+      position = "<?lua print(math.random()* 240-120) ?>,<?lua print(math.random() * 40000 + 97000) ?>,<?lua print(math.random()* 240-120) ?>"
+      scale = "10"
+      velocity = "0, -160, 0"
+      collisionType = dynamic
+      collisiondamage = 0.05
+      enablecollisiondamage = true 
+      active = false
+   >                     
+          <attached>           
+              <Model mass="2000" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+          </attached> 
+         <collisionShapes>
+             <SphereCollisionShape radius="10" />
+         </collisionShapes>   
+         <events>           
+           <activity>           
+             <EventListener event="portal3" />           
+           </activity>           
+         </events>
+   </MovableEntity>
+   <?lua
+      end
+   ?>
+
+<BlinkingBillboard position="5000,5700,5000" frequency=0.6 amplitude=3 material="Flares/lensflare" colour="1,1,0.05">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=portal2 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</BlinkingBillboard>
+
+<Billboard position="5000,5700,5000" amplitude=1 material="Flares/lensflare" colour="0,0.8,0.1">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=portal2 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</Billboard>
+
+<DistanceTrigger name="start" position="0,94000,0" target="SpaceShip" beaconMode="exclude" targetname="bcnDestroyer" distance=20 stayActive="true" delay=0 />
+
+<DistanceTrigger name="portal2" position="5000,5700,5000" target="Pawn" distance=20 stayActive="true" delay=3/>
+    <SimpleNotification message="Housten: Now go through the portal!">
+        <events>
+            <trigger>
+                <EventListener event="portal2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+
+<!----------------------------------------------------------------------------------------------------->
+<!--------------------------- PART TWO: Passing throug area with meteorits ---------------------------->
+<!----------------------------------------------------------------------------------------------------->
+   
+  <Pawn
+        team      = 0
+        position  = "0,118000,0"
+        roll      = 0   yaw=90  pitch=0
+        mass      = 10000
+        health    = 100000 initialhealth=100000 maxhealth="100000"
+        name      = "wormhole"
+        radarname = "Wormhole to Area 51" >
+   </Pawn>     
+  <StaticEntity position="0,118000,0" collisionType=static yaw=90>
+      <attached>
+         <DistanceTriggerBeacon name="bcnDestroyer" />
+         <Billboard position="0,0,0" material="Portals/Default" >
+           <events>
+             <visibility>
+               <EventTrigger invert=true>
+                 <events>
+                   <trigger>
+                     <EventListener event="portaldelaytrigger" />
+                   </trigger>
+                 </events>
+               </EventTrigger>
+             </visibility>
+           </events>
+         </Billboard>
+         <DistanceTrigger name="endOfLevel" position="0,0,0" target="SpaceShip" beaconMode="exclude"
+                          targetname="bcnDestroyer" distance=50 stayActive="true" delay=0/>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 visible=false >
+          <events>           
+            <visibility>           
+              <EventListener event="portal3" />           
+            </visibility>           
+          </events>
+        </Model>
+      </attached>
+  </StaticEntity>
+
+    <OverlayGroup name="spacefightHUD" scale = "1, 1">
+      <CountDown
+         position    = "0.9, 0.02"
+         pickpoint   = "0.0, 0.0"
+         font        = "ShareTechMono"
+         textsize    = "0.1"
+         colour      = "1.0, 0.2, 0.2, 0.8"
+         align       = "center"                  
+         counter     = "100.0"
+         speedfactor = "1.0"
+         active      = "false"
+      >
+        <events>
+          <activity>
+            <EventListener event="portal4" />
+          </activity>
+        </events>
+      </CountDown>
+      <OverlayText
+       position  = "0.05, 0.02"
+       pickpoint = "0.0, 0.0"
+       font      = "ShareTechMono"
+       textsize  = "0.1"
+       colour    = "1.0, 0.2, 0.2, 0.8"
+       align     = "left"
+       caption   = "Wormhole closing in:"
+       visible    = "false"
+      >
+        <events>
+          <visibility>
+            <EventListener event="portal4" />
+          </visibility>
+        </events>
+      </OverlayText>
+    </OverlayGroup>
+
+
+  <DistanceTrigger name="portaldelaytrigger" position="0,94000,0" target="Pawn" distance=500 stayActive="true" delay=106 />
+   <Script code="Mission endMission false" onLoad="false" times="1" >
+        <events>
+            <trigger>
+                <EventListener event="portaldelaytrigger" />
+            </trigger>
+        </events>
+    </Script> 
+
+ <DistanceTrigger name="portal3" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=1/>
+   <SimpleNotification message="Housten: Reach the wormhole to Area 51">
+      <events>
+         <trigger>
+            <EventListener event="portal3" />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+  <DistanceTrigger name="portal4" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=5/>
+   <SimpleNotification message="Housten: Hurry up John, time is running out!">
+      <events>
+         <trigger>
+            <EventListener event="portal4"  />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+   <DistanceTrigger name="portal5" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=9/>
+   <SimpleNotification message="Houston: Pay attention to the asteroids!">
+      <events>
+         <trigger>
+            <EventListener event="portal5" />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+   <DistanceTrigger name="portal6" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=13/>
+   <SimpleNotification message="Houston: Reach the wormhole in time!" >
+      <events>
+         <trigger>
+            <EventListener event="portal6" />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+
+   <DistanceTrigger name="portal7" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=17/>
+   <SimpleNotification message="Houston: We cannot keep it open much longer.">
+      <events>
+         <trigger>
+            <EventListener event="portal7" />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+   <DistanceTrigger name="portal8" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=21/>
+   <SimpleNotification message="Houston: Boost your way through the asteroids.">
+      <events>
+         <trigger>
+            <EventListener event="portal8" />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+
+   <!--DistanceTrigger name="portal9" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=25/>
+   <SimpleNotification message="Houston: It should really look like a black hole.">
+      <events>
+         <trigger>
+            <EventListener event="portal9" />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+   <DistanceTrigger name="portal10" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=29/>
+   <SimpleNotification message="John: It does... ">
+      <events>
+         <trigger>
+            <EventListener event="portal10" />
+         </trigger>
+      </events>
+   </SimpleNotification-->
+
+   <DistanceTrigger name="portal11" position="0,94000,0" target="SpaceShip" distance=50 stayActive="true" delay=33/>
+   <SimpleNotification message="Houston: Hahaha ">
+      <events>
+         <trigger>
+            <EventListener event="Houston: Fly though the black hole, if you can." />
+         </trigger>
+      </events>
+   </SimpleNotification>
+
+
+    <!--SimpleNotification message="End of game">
+        <events>
+            <trigger>
+                <EventListener event="endOfLevel" />
+            </trigger>
+        </events>
+    </SimpleNotification-->
+
+   <Script code="Mission endMission true" onLoad="false" times="1" >
+        <events>
+            <trigger>
+                <EventListener event=endOfLevel />
+            </trigger>
+        </events>
+    </Script> 
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/iiJohnVane_Area51UnderFire.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/iiJohnVane_Area51UnderFire.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/iiJohnVane_Area51UnderFire.oxw	(revision 11817)
@@ -0,0 +1,2203 @@
+<!-- (ii) John Vane : Trip to Area 51 -->
+
+<!--
+To Do:
+- Quest-Problem
+- Time the explosion right and no loops
+- Bigger explosion?
+- If possible, do the scout with DistanceTriggerBeacon
+- DistanceTriggerBeacon for Captain Hood
+-->
+
+<LevelInfo
+ name = "(ii) John Vane : Area 51 Under Fire"
+ description = "John Vane on rampage to free his commander."
+ tags = "mission"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+?>
+<?lua
+    dofile("includes/CuboidSpaceStation.lua")
+?>
+
+<Level
+  gametype = "Mission"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <?lua include("includes/notifications.oxi") ?>
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=4.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+  <?lua include("includes/pickups.oxi") ?>
+
+    <Script code="showGUI NotificationLayer false true" needsGraphics="true" times="1"/>
+    <OverlayGroup name="spacefightHUD" scale = "1, 1">
+      <CountDown
+         position    = "0.91, 0.05"
+         pickpoint   = "0.0, 0.0"
+         font        = "ShareTechMono"
+         textsize    = 0.1
+         colour      = "1.0, 1.0, 1.0, 1.0"
+         align       = "center"                  
+         counter     = "10.0"
+         speedfactor = "1.0"
+         active      = "false"
+      >
+        <events>
+          <activity>
+            <EventListener event="dockDelay2" />
+          </activity>
+        </events>
+      </CountDown>
+    </OverlayGroup>
+
+<!-- SPAWNTRIGGER -->
+    <!-- StartPoint  0, 0, 0 --> 
+    <SpawnPoint team=0 position="-12470, -21870, 25200" lookat="100, 0, 0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage >
+          <events>
+            <activity>
+              <EventListener event="flying12" />
+            </activity>
+          </events>
+    </SpawnPoint>
+    <Billboard position="-10,0,0" material="Portals/Default" />
+    <ForceField position="0, 0, 0" lookat="100, 0, 0" diameter=200 velocity=1800 length=1400 />
+
+    <EventTrigger name="flying12" invert="true" >
+      <events>
+        <trigger>
+          <EventListener event="flying1" />
+        </trigger>
+          </events>
+    </EventTrigger>
+
+    <!-- Second Spawnpoint (after first guard) -->
+    <SpawnPoint team=0 position="13500, 2500, 10500" lookat="18000,5000,18000" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage >
+      <events>
+            <activity>
+          <EventTrigger>
+        <EventTrigger invert=true >
+          <events>
+            <trigger>
+              <EventListener event="reached" />
+            </trigger>
+          </events>
+        </EventTrigger>
+        <events>
+          <trigger>
+                    <EventListener event="flying1" />
+          </trigger>
+        </events>
+          </EventTrigger>
+            </activity>
+          </events>
+        </SpawnPoint>
+    
+    <!-- Thirth Spawnpoint (when reached Captain Hood) -->
+    <SpawnPoint team=0 position="-4000, -18000, 19000" lookat="-12000, -22000, 25000" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage >
+      <events>
+        <activity>
+          <EventTrigger>
+            <EventTrigger invert=true >
+              <events>
+                <trigger>
+                  <EventListener event="timerEnd" />
+                </trigger>
+              </events>
+            </EventTrigger>
+            <events>
+              <trigger>
+                <EventListener event="reached" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </activity>
+      </events>
+    </SpawnPoint>
+
+    <!-- Distance-Spawn-Trigger -->
+    <DistanceTrigger name=spawntrigger2 position="0, 0, 0" target="SpaceShip" distance=10 stayActive="true" delay=0 />
+
+    <!-- Drone pickup -->
+    <PickupSpawner pickup=dronepickup position="9750, -5350, 5650" triggerDistance="100" respawnTime="30" maxSpawnedItems="2" />
+
+    <!-- QUEST DESCRIPTION -->
+    <LocalQuest id="spacefight.guard1">
+        <QuestDescription 
+            title="The first guard!" 
+            description="You've reached the enemys Station and they haven't seen you yet.
+
+Ahead you see the first little patrol.
+There are two little battleships and also two unarmed ships.
+The unarmed could not attack you. So first destroy the battleships!"
+            failMessage="You've lost all your ships!"
+            completeMessage="Well done!" />
+    </LocalQuest>
+
+    <LocalQuest id="spacefight.upgrade1">
+        <QuestDescription
+            title="Prepare for the fight (optional)"
+            description="Your friends has an arsenal left behind near by your position.
+Perhaps you find something useful there...
+Hint: look for a big asteroid."
+            failMessage="You've lost all your ships!"
+            completeMessage="Your ship is well prepared for the second and last guard on the way to the mainship.
+                Now attack the second guard!" />
+    </LocalQuest>
+
+    <!-- Quest-Problem: Quests couldn't be started and completed --
+    <LocalQuest id="spacefight.guard2">
+        <QuestDescription
+            title="The second guard!"
+            description="There is also a second guard. The blinking light shows you the direction.
+                Destroy also this guard!"
+            failMessage="You've lost all your ships!"
+            completeMessage="" />
+    </LocalQuest>
+
+    <LocalQuest id="spacefight.escape">
+        <QuestDescription
+            title="Catch the messenger!"
+            description="A messenger is on the way to warn the troups of the mainship.
+                Destroy him before he is near by the mainship. 
+                Else the fight against the enemys troups will be much more difficult."
+            failMessage="The messenger has reached the mainship.
+                Prepare to fight against a strong enmey!"
+            completeMessage="Well done! Now the element of surprise will be ours!" />
+    </LocalQuest>
+
+    <!-- 2 different possibilitys --
+    <!-- Spion is destroyed --
+    <LocalQuest id="spacefight.mainfight(min)" >
+        <QuestDescription
+            title="The big fight!"
+            description="Now the time is come!
+                You've done all you can to prepare you for this spacebattle.
+                Let us see, if it was enough.
+                
+                ATTACK!!!"
+            failMessage="You've lost all your ships!"
+            completeMessage="YEEEHAAA!
+                You managed it! For that you will get the golden medal of the united space armies." />
+        <complete-effects>
+            <AddQuest questId="spacefight.rescue" />
+        </complete-effects>
+    </LocalQuest>
+
+    <!-- Spion isn't destroyed --
+    <LocalQuest id="spacefight.mainfight(max)" >
+        <QuestDescription
+            title="The big fight!"
+            description="Now the time is come!
+                You've done all you can to prepare you for this spacebattle.
+                Unfortunately the spion has alert the mainship. So the soldiers will also be prepared for you.
+                But you can manage it.
+                Good luck!"
+            failMessage="You've lost all your ships!"
+            completeMessage="YEEEHAAA!
+                You managed it! For that you will get the golden medal of the united space armies." />
+        <complete-effects>
+            <AddQuest questId="spacefight.rescue" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="spacefight.rescue" >
+        <QuestDescription
+            title="Rescue and place the bomb"
+            description="Now you have to free the commander and place a bomb in the pirates' mainship."
+            failMessage="You've lost all your ships!"
+            completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="spacefight.moveAway" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="spacefight.moveAway" >
+        <QuestDescription
+            title="Get away!"
+            description="Get away of the mainship before the bomb detonates."
+            failMessage="You've lost all your ships!"
+            completeMessage="Done!" />
+    </LocalQuest>
+
+    <!-- End of Mission -->
+    
+<!-- ---------------------------------------------------------------------- -->
+<!-- QuestEffectBeacon's (not all necessary, because not all Quests work -->
+    <!-- START -->
+    <QuestEffectBeacon times=0>
+        <effects>
+            <AddQuest questId="spacefight.guard1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event=spawntrigger2 />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=0>
+        <events>
+            <execute>
+                <EventListener event="flying1" />
+            </execute>
+        </events>
+        <effects>
+            <CompleteQuest questId="spacefight.guard1" />
+        </effects>
+    </QuestEffectBeacon>
+
+    <SimpleNotification message="Houston: Well done!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="flying1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="flying1delay" activations="1" stayactive="true" delay=5.1 >
+      <events>
+        <trigger>
+          <EventListener event="flying1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: The green light shows you the way!"  broadcast="true" >
+        <events>
+            <trigger>
+                <EventListener event="flying1delay" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- Is activ at flying 1 and again inactive when flying2-->
+    <BlinkingBillboard position="11000, 1000, 7000" colour="0.0, 1.0, 0.0" frequency=0.5 amplitude=10 material="Examples/Flare" >
+      <events>
+        <visibility>
+          <EventTrigger>
+            <EventTrigger invert=true>
+              <events>
+                <trigger>
+                  <EventListener event="flying2" />
+                </trigger>
+              </events>
+            </EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="flying1" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+    </BlinkingBillboard>
+    
+    <!-- Drone (optional quest) -->
+    <QuestEffectBeacon times=0>
+        <effects>
+            <AddQuest questId="spacefight.upgrade1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="droneTrigger" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>    
+
+    <QuestEffectBeacon times=0>
+        <effects>
+            <CompleteQuest questId="spacefight.upgrade1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="drone1" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=0>
+        <effects>
+            <CompleteQuest questId="spacefight.upgrade1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="victory" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+    
+    <!-- Guard 2 -->
+    <QuestEffectBeacon times=0>
+        <effects>
+            <AddQuest questId="spacefight.guard2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="droneTrigger" />
+            </execute>        
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=0>
+        <effects>
+            <CompleteQuest questId="spacefight.guard2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="flying2" />
+            </execute>        
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- ESCAPE -->
+    <SimpleNotification message="Houston: A scout started to the mainship!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="guard2trigger1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <QuestEffectBeacon times=0>
+        <effects>
+            <AddQuest questId="spacefight.escape" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="escape10" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- ESCAPE ENDING -->
+    <!-- Spion escaped -->
+    <QuestEffectBeacon times=0>
+        <effects>
+            <CompleteQuest questId="spacefight.escape" />
+            <AddQuest questId="spacefight.mainfight(max)" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="spionTrigger" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- Spion destroyed -->
+    <QuestEffectBeacon>
+        <effects>
+            <CompleteQuest questId="spacefight.escape" />
+            <AddQuest questId="spacefight.mainfight(min)" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="spion5" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- LAST FIGHT -->
+    <!-- Spion destroyed -->
+    <QuestEffectBeacon>
+        <effects>
+            <CompleteQuest questId="spacefight.mainfight(min)" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="guard3trigger4" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- Spion escaped -->
+    <QuestEffectBeacon>
+        <effects>
+            <CompleteQuest questId="spacefight.mainfight(max)" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="guard3trigger6" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- COMMANDER RESCUE -->
+    <QuestEffectBeacon>
+        <effects>
+            <CompleteQuest questId="spacefight.rescue" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dock" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- FLY AWAY -->
+    <QuestEffectBeacon>
+        <effects>
+            <CompleteQuest questId="spacefight.moveAway" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!-- End with explosion -->
+
+<!-- ---------------------------------------------------------------------- -->
+    <!-- Helper-Trigger for first guard -->
+    <EventTrigger name="spawntrigger2Delay" stayactive="true" delay=2 >
+        <events>
+            <trigger>
+                <EventListener event=spawntrigger2 />
+            </trigger>
+        </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Attack the first guard!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spawntrigger2Delay" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="flying1" position="9000, 0, 0" target="SpaceShip" distance=10000 stayActive="true" delay=0.1 >
+        <EventTrigger>
+            <events>
+                <trigger>
+                    <EventListener event="guard1trigger4" />
+                </trigger>
+            </events>
+        </EventTrigger>
+    </DistanceTrigger>
+
+    <!-- Trigger to activate the upgrade1-Quest -->
+    <DistanceTrigger name="droneTrigger" position="11000, 1000, 7000" target="SpaceShip" distance=2000 stayActive="true" delay=0.1 />
+    <SimpleNotification message="Houston: Need an Upgrade?"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="droneTrigger" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="droneTriggerDelay" stayactive="true" delay=5 >
+        <events>
+            <trigger>
+                <EventListener event="droneTrigger" />
+            </trigger>
+        </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Search the drone!"  broadcast="true" >
+        <events>
+            <trigger>
+                <EventListener event="droneTriggerDelay" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="droneTriggerDelay2" stayactive="true" delay=5 >
+        <events>
+            <trigger>
+                <EventListener event="droneTriggerDelay" />
+            </trigger>
+        </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Else you see the second guard ahead..."  broadcast="true" >
+        <events>
+            <trigger>
+                <EventListener event="droneTriggerDelay2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+            
+
+    <!-- Helper-Trigger for the drone -->
+    <DistanceTrigger name="drone1" position="9750, -5350, 5650" target="SpaceShip" distance=100 stayActive="true" delay=0.1 />
+    <SimpleNotification message="Houston: Now your are prepared best!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="drone1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="drone1Delay" stayactive="true" delay=5.1 >
+        <events>
+            <trigger>
+                <EventListener event="drone1" />
+            </trigger>
+        </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Fly back to the green light."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="drone1Delay" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Trigger name="secondDroneTrigger" mode="and" stayActive="true">
+      <DistanceTrigger name="droneTrigger" position="11000, 1000, 7000" target="SpaceShip" distance=1000 stayActive="true" delay=0.1 />
+          <EventTrigger>
+            <events>
+              <trigger>
+                <EventListener event="drone1" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </Trigger>
+
+    <SimpleNotification message="Houston: The red light shows you the direction."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="secondDroneTrigger" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <BlinkingBillboard position="12000, 1500, 10000" colour="1.0, 0.0, 0.0" frequency=0.5 amplitude=5 material="Examples/Flare" >
+      <events>
+        <visibility>
+          <EventTrigger>
+        <EventTrigger invert=true>
+          <events>
+            <trigger>
+              <EventListener event="guard2trigger1" />
+            </trigger>
+          </events>
+        </EventTrigger>
+            <events>
+              <trigger>
+                <EventListener event="secondDroneTrigger" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </visibility>
+      </events>
+    </BlinkingBillboard>
+
+    <!-- Helper-Trigger for second guard -->
+    <DistanceTrigger name="flying2" position="17000,5000,15000" target="SpaceShip" distance=20000 stayActive="true" delay=0 >
+        <EventTrigger>
+            <events>
+                <trigger>
+                    <EventListener event="guard2trigger4" />
+                </trigger>
+            </events>
+        </EventTrigger>
+    </DistanceTrigger>    
+
+    <SimpleNotification message="Houston: Well done!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="flying2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Trigger name="guard2withoutScout" mode="and" stayActive="true" delay=0 >
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="flying2" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" invert="true" >
+        <events>
+          <trigger>
+            <EventListener event="spionEnd" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <EventTrigger name="flying2delay1" activations="1" stayactive="true" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="guard2withoutScout" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Catch the scout!"  broadcast="true" >
+        <events>
+            <trigger>
+                <EventListener event="flying2delay1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="flying2delay2" activations="1" stayactive="true" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="flying2delay1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Before he reachs the red light..."  broadcast="true" >
+        <events>
+            <trigger>
+                <EventListener event="flying2delay2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- DistanceTrigger for scout -->
+    <Trigger name="spionTrigger" mode="and" stayActive="true">
+      <DistanceTrigger position="14000, 1000, 22000" target="SpaceShip" distance=50 stayActive="true" delay=0.1 />
+          <EventTrigger activations="1" invert="true">
+            <events>
+              <trigger>
+                <EventListener event="spion5" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </Trigger>
+
+    <SimpleNotification message="Houston: Scout is arrived!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spionTrigger" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="spionTriggerDelay" stayactive="true" delay=5 >
+        <events>
+            <trigger>
+                <EventListener event="spionTrigger" />
+            </trigger>
+        </events>
+    </EventTrigger>    
+
+    <SimpleNotification message="Houston: Now the mainship is alarmed..."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spionTriggerDelay" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <BlinkingBillboard position="14000, 1000, 22000" colour="1.0, 0.0, 0.0" frequency=0.3 amplitude=7 material="Examples/Flare" >
+      <events>
+        <visibility>
+          <EventTrigger>
+        <EventTrigger invert=true>
+          <events>
+            <trigger>
+              <EventListener event="spionEnd" />
+            </trigger>
+          </events>
+        </EventTrigger>
+            <events>
+              <trigger>
+                <EventListener event="guard2trigger1" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </visibility>
+      </events>
+    </BlinkingBillboard>
+
+    <!-- If scout destroyed -->
+    <SimpleNotification message="Houston: Scout destroyed!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spion5" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Trigger name="scoutDestroydAddon" mode="and" stayActive="true" delay=5 >
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="spion5" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="spionTrigger" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <SimpleNotification message="Houston: But the mainship is already warned."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="scoutDestroydAddon" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- Scout end -->
+    <Trigger name="spionEnd" mode="or" stayActive="true" delay=0 >
+      <EventTrigger>
+        <events>
+          <trigger>
+            <EventListener event="spion5" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger>
+        <events>
+          <trigger>
+            <EventListener event="spionTrigger" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <EventTrigger name="spionEndDelay" activations="1" delay=5>
+      <events>
+        <trigger>
+          <EventListener event="spionEnd" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <!-- Intro to Captain Hood -->
+    <Trigger name="introHood" mode="and" stayActive="true">
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="spionEndDelay" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="guard2trigger4" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <EventTrigger name="introHoodDelay1" activations="1" stayactive="true" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="introHood" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Your friend, Captain Hood, is"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="introHoodDelay1.2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="introHoodDelay1.2" activations="1" stayactive="true" delay=0.1 >
+      <events>
+        <trigger>
+          <EventListener event="introHoodDelay1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="near by you!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="introHoodDelay1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="introHoodDelay2" activations="1" stayactive="true" delay=5.1 >
+      <events>
+        <trigger>
+          <EventListener event="introHoodDelay1" />
+        </trigger>
+      </events>
+    </EventTrigger>    
+
+    <SimpleNotification message="Houston: He'll show you the way"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="introHoodDelay2.2" />
+            </trigger>
+        </events>
+    </SimpleNotification>    
+
+    <EventTrigger name="introHoodDelay2.2" activations="1" stayactive="true" delay=0.1 >
+      <events>
+        <trigger>
+          <EventListener event="introHoodDelay2" />
+        </trigger>
+      </events>
+    </EventTrigger>    
+
+    <SimpleNotification message="to the mainship!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="introHoodDelay2" />
+            </trigger>
+        </events>
+    </SimpleNotification>    
+
+    <!-- Helper-Trigger for Captain Hood -->
+    <DistanceTrigger name="reached" position="10000, 2000, 17000" target="SpaceShip" distance=1000 stayActive="true" delay=0.1 >
+        <EventTrigger>
+            <events>
+                <trigger>
+                    <EventListener event="guard2trigger4" />
+                </trigger>
+            </events>
+        </EventTrigger>
+    </DistanceTrigger>
+
+    <SimpleNotification message="Houston: Follow Captain Hood!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reached" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="reachedDelay1" activations="1" stayactive="true" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="reached" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Hood: Hello my friend!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="reachedDelay2" activations="1" stayactive="true" delay=7 >
+      <events>
+        <trigger>
+          <EventListener event="reachedDelay1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Hood: Good work at the first two guards..."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="reachedDelay3" activations="1" stayactive="true" delay=7 >
+      <events>
+        <trigger>
+          <EventListener event="reachedDelay2" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Hood: But the heaviest part is waiting"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay4" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="reachedDelay4" activations="1" stayactive="true" delay=0.1 >
+      <events>
+        <trigger>
+          <EventListener event="reachedDelay3" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="for us..."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="reachedDelay5" activations="1" stayactive="true" delay=7 >
+      <events>
+        <trigger>
+          <EventListener event="reachedDelay4" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <Trigger name="reachedDelay6.destroyed" mode="and" stayActive="true">
+      <EventTrigger>
+        <events>
+          <trigger>
+        <EventListener event="reachedDelay5" />
+          </trigger>
+        </events>
+      </EventTrigger>
+          <EventTrigger invert=true >
+            <events>
+              <trigger>
+                <EventListener event="spionTrigger" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </Trigger>
+
+    <SimpleNotification message="Hood: Good that you've destroyed the scout!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay6.destroyed" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Trigger name="reachedDelay6.arrived" mode="and" stayActive="true">
+      <EventTrigger>
+        <events>
+          <trigger>
+        <EventListener event="reachedDelay5" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger>
+        <events>
+          <trigger>
+            <EventListener event="spionTrigger" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <SimpleNotification message="Hood: What a pity that you couldn't"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay6.arrived2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="reachedDelay6.arrived2" activations="1" stayactive="true" delay=0.1 >
+      <events>
+        <trigger>
+          <EventListener event="reachedDelay6.arrived" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="destroy the scout..."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="reachedDelay6.arrived" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="discuss" position="-4000, -9000, 18000" target="SpaceShip" distance=50 stayActive="true" delay=0.1 />
+    <SimpleNotification message="Hood: Look, there is the mainship!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="discuss" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- End of Mainfight -->
+    <Trigger name="victory1" mode="and" stayActive="true">
+      <EventTrigger>
+        <events>
+          <trigger>
+        <EventListener event="guard3trigger4" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="spion5" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <Trigger name="victory2" mode="and" stayActive="true">
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="guard3trigger6" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="spionTrigger" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <Trigger name="victory" mode="or" stayActive="true">
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+        <EventListener event="victory1" />
+          </trigger>
+        </events>
+      </EventTrigger>
+      <EventTrigger activations="1" >
+        <events>
+          <trigger>
+            <EventListener event="victory2" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </Trigger>
+
+    <SimpleNotification message="Houston: YEEEHAAA! You managed it!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="victory" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="victoryDelay1" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="victory" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <EventTrigger name="victoryDelay1.1" delay=5.1 >
+      <events>
+        <trigger>
+          <EventListener event="victory" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: For that you will get the golden medal"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="victoryDelay1.1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="of the united space armies."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="victoryDelay1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="victoryDelay2" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="victoryDelay1.1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <EventTrigger name="victoryDelay2.1" delay=5.1 >
+      <events>
+        <trigger>
+          <EventListener event="victoryDelay1.1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: Now dock at the mainship and"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="victoryDelay2.1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="free the Commander!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="victoryDelay2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="victoryDelay3" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="victoryDelay2" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: The light shows you the hatch"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="victoryDelay3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- Rescue the commander -->
+    <BlinkingBillboard position="-12470, -21870, 25200" colour="0.0, 0.0, 1.0" frequency=0.5 amplitude=5 material="Examples/Flare" >
+      <events>
+        <visibility>
+          <EventTrigger>
+            <EventTrigger invert=true>
+              <events>
+                <trigger>
+                  <EventListener event="dock" />
+                </trigger>
+              </events>
+            </EventTrigger>
+            <events>
+              <trigger>
+                <EventListener event="victory" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </visibility>
+      </events>
+    </BlinkingBillboard>
+    
+    <DistanceTrigger
+     name="dock"
+     position="-12470, -21870, 25200"
+     beaconMode="exclude"
+     targetname="NPC"
+     target="SpaceShip"
+     distance=50
+     stayActive="true"
+     delay=0 />
+    <SimpleNotification message="Houston: The Commander is on board!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="dock" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    
+    <!-- TIMER-EVENTS -->
+    <EventTrigger name="dockDelay1" stayactive="true" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="dock" />
+        </trigger>
+      </events>
+    </EventTrigger>    
+    
+    <SimpleNotification message="Houston: A bomb is placed in the mainship..."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="dockDelay1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <EventTrigger name="dockDelay2" activations="1" stayactive="true" delay=5.0 >
+      <events>
+        <trigger>
+          <EventListener event="dockDelay1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Houston: You have 10 seconds to move away..."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="dockDelay2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <EventTrigger name="timer1" activations="1" stayactive="true" delay=5 >
+      <events>
+        <trigger>
+          <EventListener event="dockdelay2" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+
+    <DistanceTrigger
+     name="dockdelay3"
+     position="-12470, -21870, 25200"
+     beaconMode="exclude"
+     targetname="NPC"
+     target="SpaceShip"
+     distance=50
+     stayActive="true"
+     delay=20 />
+
+    <DistanceTrigger
+     name="inExplosionRange"
+     position="-12000, -22000, 25000"
+     beaconMode="exclude"
+     targetname="NPC"
+     target="SpaceShip"
+     distance=1000
+     stayActive="true"
+     delay=0 >
+        <EventTrigger>
+            <events>
+                <trigger>
+                    <EventListener event="dockdelay3" />
+                </trigger>
+            </events>
+        </EventTrigger>
+    </DistanceTrigger>
+
+    <DistanceTrigger
+     name="dockdelay4"
+     position="-12470, -21870, 25200"
+     beaconMode="exclude"
+     targetname="NPC"
+     target="SpaceShip"
+     distance=50
+     stayActive="true"
+     delay=23.1 />
+
+    <EventTrigger name="timerEnd" activations="1" stayactive="true" delay=10 >
+      <events>
+        <trigger>
+          <EventListener event="timer1" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <EventTrigger name="negativeTimerEnd" invert="true" delay=0 >
+      <events>
+        <trigger>
+          <EventListener event="timerEnd" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+<!-- ----------------------------------------------------- -->    
+<!-- For Guard 1 -->
+<!-- @Triggers: attacktriggerX <-> X enemies destroyed , X is an element of [1,4] -->
+    <EventTrigger name="guard1trigger4" activations="1" stayactive="true" delay=0.1>
+      <events>
+        <trigger>
+          <EventListener event="firstPatrol" />
+        </trigger>
+      </events>
+      <EventTrigger name="guard1trigger3" activations="1" stayactive="true" delay=0.1>
+        <events>
+          <trigger>
+            <EventListener event="firstPatrol" />
+          </trigger>
+        </events>
+        <EventTrigger name="guard1trigger2" activations="1" stayactive="true" delay=0.1>
+          <events>
+            <trigger>
+              <EventListener event="firstPatrol" />
+            </trigger>
+          </events>
+          <EventTrigger name="guard1trigger1" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="firstPatrol" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </EventTrigger>
+      </EventTrigger>
+    </EventTrigger>
+
+<!-- For Guard 2 -->
+<!-- @Triggers: attacktriggerX <-> X enemies destroyed , X is an element of [1,4] -->
+    <EventTrigger name="guard2trigger4" activations="1" stayactive="true" delay=0.1>
+      <events>
+        <trigger>
+          <EventListener event="secondPatrol" />
+        </trigger>
+      </events>
+      <EventTrigger name="guard2trigger3" activations="1" stayactive="true" delay=0.1>
+        <events>
+          <trigger>
+            <EventListener event="secondPatrol" />
+          </trigger>
+        </events>
+        <EventTrigger name="guard2trigger2" activations="1" stayactive="true" delay=0.1>
+          <events>
+            <trigger>
+              <EventListener event="secondPatrol" />
+            </trigger>
+          </events>
+          <EventTrigger name="guard2trigger1" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="secondPatrol" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </EventTrigger>
+      </EventTrigger>
+    </EventTrigger>
+
+<!-- For Escape -->
+    <EventTrigger name="spion5" stayactive="true" >
+      <events>
+        <trigger>
+          <EventListener event="spion" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+<!-- For last fight -->
+    <EventTrigger name="guard3trigger6" activations="1" stayactive="true" delay=0.1 >
+      <events>
+        <trigger>
+          <EventListener event="lastGuard" />
+        </trigger>
+      </events>
+      <EventTrigger name="guard3trigger5" activations="1" stayactive="true" delay=0.1 >
+        <events>
+          <trigger>
+            <EventListener event="lastGuard" />
+          </trigger>
+        </events>
+        <EventTrigger name="guard3trigger4" activations="1" stayactive="true" delay=0.1 >
+          <events>
+            <trigger>
+              <EventListener event="lastGuard" />
+            </trigger>
+          </events>
+          <EventTrigger name="guard3trigger3" activations="1" stayactive="true" delay=0.1 >
+            <events>
+              <trigger>
+                <EventListener event="lastGuard" />
+              </trigger>
+            </events>
+            <EventTrigger name="guard3trigger2" activations="1" stayactive="true" delay=0.1 >
+              <events>
+            <trigger>
+              <EventListener event="lastGuard" />
+            </trigger>
+              </events>
+              <EventTrigger name="guard3trigger1" activations="1" stayactive="true" delay=0.1 >
+                <events>
+                  <trigger>
+                    <EventListener event="lastGuard" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </EventTrigger>
+          </EventTrigger>
+        </EventTrigger>
+      </EventTrigger>
+    </EventTrigger>
+    
+<!-- ----------------------------------------------------- -->
+<!-- Passive Pirates: Guard 1 -->
+<SpaceShip position="8000,1000,0" lookat="8000,-1000,0" name="firstPatrol" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event=spawntrigger2 />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointController team=1>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="8000,-1000,0" />
+        <Model mesh="cube.mesh" scale=0 position="8000,1000,0" />
+      </waypoints>
+    </WaypointController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="8000,0,0" lookat="8000,0,-1000" name="firstPatrol" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event=spawntrigger2 />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointController team=1>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="8000,400,2000" />
+        <Model mesh="cube.mesh" scale=0 position="8000,0,0" />
+      </waypoints>
+    </WaypointController>
+  </controller>
+</SpaceShip>
+
+
+<!-- Active Pirates: Guard 1 -->
+<SpaceShip position="8000,-1000,1000" lookat="8000,1000,-1000" name="firstPatrol" visible="true" radarname="Patrol" >
+  <events>
+    <visibility>
+      <EventListener event=spawntrigger2 />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="8000,1000,-1000" />
+        <Model mesh="cube.mesh" scale=0 position="8000,-1000,1000" />
+      </waypoints>
+      <events>
+        <activity>
+          <EventListener event=spawntrigger2 />
+        </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="8000,-500,-500" lookat="8000,1000,1000" name="firstPatrol" visible="true" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event=spawntrigger2 />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="8000,1000,1000" />
+        <Model mesh="cube.mesh" scale=0 position="8000,-1000,-1000" />
+      </waypoints>
+      <events>
+        <activity>
+          <EventListener event=spawntrigger2 />
+        </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<!-- Pirates Guard 2 -->
+<SpaceShip position="18000,5000,15000" lookat="17700,4300,15000" name="secondPatrol" visible="true" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event="guard1trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="17700,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,4000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16300,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16000,5000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16300,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,6000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17700,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="18000,5000,15000" />
+      </waypoints>
+      <events>
+        <activity>
+          <EventListener event="guard1trigger4" />
+        </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="16000,5000,15000" lookat="16300,5700,15000" name="secondPatrol" visible="true" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event="guard1trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="16300,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,6000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17700,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="18000,5000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17700,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,4000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16300,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16000,5000,15000" />
+      </waypoints>
+      <events>
+        <activity>
+          <EventListener event="guard1trigger4" />
+        </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="17000,4000,15000" lookat="16300,4300,15000" name="secondPatrol" visible="true" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event="guard1trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="16300,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16000,5000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16300,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,6000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17700,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="18000,5000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17700,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,4000,15000" />
+      </waypoints>
+      <events>
+        <activity>
+          <EventListener event="guard1trigger4" />
+        </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="17000,6000,15000" lookat="17700,5700,15000" name="secondPatrol" visible="true" radarname="Patrol">
+  <events>
+    <visibility>
+      <EventListener event="guard1trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="17700,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="18000,5000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17700,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,4000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16300,4300,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16000,5000,15000" />
+        <Model mesh="cube.mesh" scale=0 position="16300,5700,15000" />
+        <Model mesh="cube.mesh" scale=0 position="17000,6000,15000" />
+      </waypoints>
+      <events>
+        <activity>
+          <EventListener event="guard1trigger4" />
+        </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<!-- Escape-Ship (Scout) -->
+<SpaceShip position="16000,4000,16000" lookat="-12000, -22000, 25000" name="spion" visible="true" radarname="Scout" >
+  <events>
+    <visibility>
+      <EventListener event="guard2trigger1" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <controller>
+    <WaypointController team=1>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="14000, 1000, 22000" />
+        <Model mesh="cube.mesh" scale=0 position="0, -10000, 42000" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="guard2trigger1" />
+    </activity>
+      </events>
+    </WaypointController>
+  </controller>
+<!--  Should be realized, if possible...
+  <attached>
+    <DistanceTriggerBeacon name="spionBeacon" />
+  </attached>
+-->
+</SpaceShip>
+
+<!-- Pirates Mainship -->
+<SpaceShip position="-10000, -20000, 24000" lookat="-10000, -22000, 24000" name="lastGuard" visible="true" radarname="Pirate" >
+  <events>
+    <visibility>
+      <EventListener event="guard2trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-9500, -22000, 24000" /> <!-- -12000, -22000, 25000    -4000, -18000, 19000 -->
+        <Model mesh="cube.mesh" scale=0 position="-10500, -22000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-11000, -20000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-10000, -20000, 24000" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="guard2trigger4" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="-10000, -22000, 24000" lookat="-11000, -22000, 23000" name="lastGuard" visible="true" radarname="Pirate" >
+  <events>
+    <visibility>
+      <EventListener event="guard2trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-10500, -22000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-11000, -20000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-10000, -20000, 24000" />        
+        <Model mesh="cube.mesh" scale=0 position="-9500, -22000, 24000" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="guard2trigger4" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="-11000, -22000, 23000" lookat="-11000, -20000, 23000" name="lastGuard" visible="true" radarname="Pirate" >
+  <events>
+    <visibility>
+      <EventListener event="guard2trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-11000, -20000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-10000, -20000, 24000" />        
+        <Model mesh="cube.mesh" scale=0 position="-9500, -22000, 24000" />
+        <Model mesh="cube.mesh" scale=0 position="-10500, -22000, 23000" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="guard2trigger4" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="-11000, -20000, 23000" lookat="-10000, -20000, 24000" name="lastGuard" visible="true" radarname="Pirate" >
+  <events>
+    <visibility>
+      <EventListener event="guard2trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-10000, -20000, 24000" />        
+        <Model mesh="cube.mesh" scale=0 position="-9500, -22000, 24000" />
+        <Model mesh="cube.mesh" scale=0 position="-10500, -22000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-11000, -20000, 23000" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="guard2trigger4" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<!-- Additional pirates if the scout has warned the mainship -->
+<SpaceShip position="-10500, -20000, 23500" lookat="-10000, -21000, 24000" name="lastGuard" visible="true" radarname="Pirate" >
+  <events>
+    <visibility>
+      <EventListener event="spionTrigger" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-9750, -21000, 24000" />
+        <Model mesh="cube.mesh" scale=0 position="-10000, -22000, 23500" />
+        <Model mesh="cube.mesh" scale=0 position="-10750, -21000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-10500, -20000, 23500" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="spionTrigger" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<SpaceShip position="-10500, -22000, 23500" lookat="-11000, -21000, 23000" name="lastGuard" visible="true" radarname="Pirate" >
+  <events>
+    <visibility>
+      <EventListener event="spionTrigger" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshippirate />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=1 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-10750, -21000, 23000" />
+        <Model mesh="cube.mesh" scale=0 position="-10500, -20000, 23500" />
+        <Model mesh="cube.mesh" scale=0 position="-9750, -21000, 24000" />
+        <Model mesh="cube.mesh" scale=0 position="-10000, -22000, 23500" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="spionTrigger" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<!-- Captain Hood (Friend) -->
+<SpaceShip position="8500, 2000, 17000" lookat="0, -1000, 18000" name="friend" visible="true" radarname="Hood" >
+  <events>
+    <visibility>
+      <EventListener event="guard2trigger4" />
+    </visibility>
+  </events>
+  <templates>
+    <Template link=spaceshipswallow />
+  </templates>
+  <attached>
+    <DistanceTriggerBeacon name="NPC" />
+  </attached>
+  <controller>
+    <WaypointPatrolController alertnessradius=5000 team=0 active=false>
+      <waypoints>
+        <Model mesh="cube.mesh" scale=0 position="-4000, -9000, 18000" />
+        <Model mesh="cube.mesh" scale=0 position="-11500, -22000, 25000" />
+      </waypoints>
+      <events>
+    <activity>
+      <EventListener event="reached" />
+    </activity>
+      </events>
+    </WaypointPatrolController>
+  </controller>
+</SpaceShip>
+
+<BlinkingBillboard position="10000, 2000, 17000" colour="1.0, 1.0, 0.0" frequency=0.5 amplitude=20 material="Examples/Flare" >
+  <events>
+    <visibility>
+      <EventTrigger>
+    <EventTrigger invert=true>
+      <events>
+        <trigger>
+          <EventListener event="reached" />
+        </trigger>
+      </events>
+    </EventTrigger>
+        <events>
+          <trigger>
+            <EventListener event="spion5" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </visibility>
+  </events>
+</BlinkingBillboard>
+
+<SimpleNotification message="Houston: Your friend Captain Hood is dead..."  broadcast="true">
+    <events>
+        <trigger>
+            <EventListener event="friend" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<EventTrigger name="friendDelay1" stayactive="true" delay=5.0 >
+  <events>
+    <trigger>
+      <EventListener event="friend" />
+    </trigger>
+  </events>
+</EventTrigger>
+
+<SimpleNotification message="Vane: NOOOOO!!!"  broadcast="true">
+    <events>
+        <trigger>
+            <EventListener event="friendDelay1" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<EventTrigger name="friendDelay2" stayactive="true" delay=5.0 >
+  <events>
+    <trigger>
+      <EventListener event="friendDelay1" />
+    </trigger>
+  </events>
+</EventTrigger>
+
+<SimpleNotification message="Houston: He died in a fight like he wished it!"  broadcast="true">
+    <events>
+        <trigger>
+            <EventListener event="friendDelay2" />
+        </trigger>
+    </events>
+</SimpleNotification>
+
+<!-- ----------------------------------------------------- -->
+
+<Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+<!-- ASTEROIDS & ASTEROID-FIELDS -->
+    <!-- Asteroids -->
+    <Model
+        position="9800, -5000, 5700" 
+        yaw="90" 
+        pitch="-90" 
+        roll="0" 
+        scale="200" 
+        mesh="asteroid_ice.mesh" >
+      <attached>
+<!--        <Model mass=10 scale3D="0.5,0.5,0.5" mesh="cube.mesh" position = "0,0,0" yaw=0 pitch=0 roll=0 /> -->
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius=0.5 />
+      </collisionShapes>
+    </Model>
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(2000, -250, 9000, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(2000, -250, 9000, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(2000, -250, 9000, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+    <!-- between guard 2 & mainship -->
+        <!-- Core -->    
+        <?lua
+            dofile("includes/asteroidField.lua")
+            asteroidField(-5000, -10000, 30000, 10, 700, 8000, 80, 0)
+        ?>
+    
+        <!-- Peripherie -->
+        <?lua
+            dofile("includes/asteroidField.lua")
+            asteroidField(-5000, -10000, 30000, 10, 50, 10000, 100, 0)
+        ?>
+
+        <?lua
+            dofile("includes/asteroidField.lua")
+            asteroidBelt(-10000, -12500, 0, 0, 0, 30, 30, 500, 0, 7850, 150, 0)
+        ?>
+
+    <!-- PLANETS -->
+      <Planet
+            position="2000,-250,9000" 
+            scale=5000 
+            pitch=1 
+            mesh="iceplanet.mesh" 
+            atmosphere="atmosphere1" 
+            rotationaxis="1,1,0" 
+            rotationrate="0.5" 
+            atmospheresize=224.0f 
+            imagesize=1024.0f
+            mass="10000000"
+            angularDamping=0
+            collisiondamage=2
+            enablecollisiondamage=true
+            collisionType="dynamic" />
+
+<!--  PICKUPS to make travelling faster  -->
+    <PickupSpawner pickup=hugespeedpickup position="11473,1275,7689" triggerDistance="400" respawnTime="10" maxSpawnedItems="5" />
+    <PickupSpawner pickup=mediumspeedpickup position="9455,1309,16891" triggerDistance="400" respawnTime="10" maxSpawnedItems="5" />
+
+<!-- ----------------Rotating SpaceStation--------------- -->
+    <!-- first guard -->
+    <StaticEntity position="9000,0,0" collisionType=static yaw=112 pitch=67 >
+      <attached>
+        <?lua
+          createSpaceStationPar(0,2,1,2,1,4,1,50)
+        ?>
+      </attached>
+    </StaticEntity>
+
+    <!-- second guard -->
+    <StaticEntity position="17000,5000,15000" collisionType=static yaw=12 pitch=75 >
+      <attached>
+        <?lua
+          createSpaceStationPar(0,2,1,2,1,4,1,50)
+        ?>
+      </attached>
+    </StaticEntity>
+
+<!-- ------------------------- Mainship ------------------ -->
+    <SpaceShip
+        team      = 1
+        position  = "-12000, -22000, 25000"
+        mass      = 10000000000
+        health    = 100000 initialhealth=100000 maxhealth="100000"
+        name      = "Mainship"
+        radarname = "Mainship" 
+        visible   = "true" >
+      <events>
+        <visibility>
+          <EventTrigger invert=true>
+            <events>
+              <trigger>
+                <EventListener event="dockdelay3" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </visibility>
+      </events>
+      <controller>
+        <WaypointController team=1 active="true" >
+          <waypoints/>
+          <events>
+            <activity>
+              <EventListener event=spawntrigger2 />
+            </activity>
+          </events>
+        </WaypointController>
+      </controller>
+      <attached>
+        <Model scale=200 mesh="drone.mesh" position = "0,0,0" lookat="40000, 4000, 27000" />
+        <DistanceTriggerBeacon name="NPC" />
+<!--    <Model mesh="cube.mesh" mass=10 position="-445,110,120" scale3D="45,45,150"  yaw=56 pitch=-4 roll=0 />
+        <Model mesh="cube.mesh" mass=10 position="-295,125,220" scale3D="28,28,28" yaw=56 pitch=-4 roll=0 />
+        <Model mesh="cube.mesh" mass=10 position="-400,350,-200" scale3D="80,280,800" yaw=56 pitch=-4 roll=5 />
+        <Model mesh="cube.mesh" mass=10 position="-300,630,-100" scale3D="250,50,500" yaw=56 pitch=-4 roll=5 />
+        <Model mesh="cube.mesh" mass=10 position="-150,-150,-550" scale3D="80,280,800"  yaw=56 pitch=-4 roll=65 />
+        <Model mesh="cube.mesh" mass=10 position="150,-270,-600" scale3D="250,50,500" yaw=56 pitch=-4 roll=65 />
+        <Model mesh="cube.mesh" mass=10 position="-500,-250,0" scale3D="80,280,800" yaw=56 pitch=-4 roll=-50 />
+        <Model mesh="cube.mesh" mass=10 position="-500,-420,250" scale3D="250,50,500" yaw=56 pitch=-4 roll=-50 /> -->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-445,110,120" halfExtents="45,45,150" yaw=56 pitch=-4 roll=0 />
+        <BoxCollisionShape  position="-295,125,220" halfExtents="28,28,28" yaw=56 pitch=-4 roll=0 />
+        <BoxCollisionShape  position="-400,350,-200" halfExtents="80,280,800" yaw=56 pitch=-4 roll=5 />
+        <BoxCollisionShape  position="-300,630,-100" halfExtents="250,50,500" yaw=56 pitch=-4 roll=5 />
+        <BoxCollisionShape  position="-150,-150,-550" halfExtents="80,280,800" yaw=56 pitch=-4 roll=65 />
+        <BoxCollisionShape  position="150,-270,-600" halfExtents="250,50,500" yaw=56 pitch=-4 roll=65 />
+        <BoxCollisionShape  position="-500,-250,0" halfExtents="80,280,800" yaw=56 pitch=-4 roll=-50 />
+        <BoxCollisionShape  position="-500,-420,250" halfExtents="250,50,500" yaw=56 pitch=-4 roll=-50 />
+      </collisionShapes>
+      <events>
+        <visibility>
+          <EventListener event="negativeTimerEnd" />
+        </visibility>
+      </events>
+    </SpaceShip>
+
+    <!-- PARTICLE EFFECT -->
+    <ParticleSpawner position="-12000, -22000, 25000" source="Orxonox/RingExp" autostart="false" lifetime=600 loop=0 startdelay=0.5>
+        <events>
+            <spawn>
+                <EventListener event="dockdelay3" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+    <ParticleSpawner position="-12000, -22000, 25000" source="Orxonox/RingExp2" autostart="false" lifetime=600 loop=0 startdelay=0>
+        <events>
+            <spawn>
+                <EventListener event="dockdelay3" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+    <ParticleSpawner position="-12000, -22000, 25000" source="Orxonox/RingExp3" autostart="false" lifetime=600 loop=0 startdelay=0>
+        <events>
+            <spawn>
+                <EventListener event="dockdelay3" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+    
+    <!-- The fire is set ->
+    <EventTrigger name="kaboom1" activations="1" stayactive="true" delay=3 >
+      <events>
+        <trigger>
+          <EventListener event="dockdelay2" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    
+    <ParticleSpawner position="-12370,-21954.7,24993.4" source="Orxonox/bigexplosion" lifetime=3.5 loop=0 autostart=0>
+        <events>
+            <spawn>
+                <EventListener event="kaboom1" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+
+    <ParticleSpawner position="-11983.6,-21599,25172.2" source="Orxonox/bigexplosion" lifetime=3.5 loop=0 autostart=false>
+        <events>
+            <spawn>
+                <EventListener event="kaboom1" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+
+    <ParticleSpawner position="-12738.7,-22278.6,24827.4" source="Orxonox/bigexplosion" lifetime=3.5 loop=0 autostart=false>
+        <events>
+            <spawn>
+                <EventListener event="kaboom1" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+
+    <ParticleSpawner position="-11830.5,-22207.2,24714.7" source="Orxonox/bigexplosion" lifetime=3.5 loop=0 autostart=false>
+        <events>
+            <spawn>
+                <EventListener event="kaboom1" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+
+    <ParticleSpawner position="-11772.2,-21992.9,25151.8" source="Orxonox/bigexplosion" lifetime=3.5 loop=0 autostart=false>
+        <events>
+            <spawn>
+                <EventListener event="kaboom1" />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+
+    <ParticleSpawner position="-12953.1,-22107.5,24330.7" source="Orxonox/bigexplosion" lifetime=3.5 loop=0 autostart=false>
+        <events>
+            <spawn>
+                <EventListener event="kaboom1" />
+            </spawn>
+        </events>
+    </ParticleSpawner-->
+
+    
+   <!-- TODO: End the game -->
+   <Script code="Mission endMission true" onLoad="false" times="1" >
+        <events>
+            <trigger>
+                <EventListener event="dockdelay4" />
+            </trigger>
+        </events>
+    </Script>
+    <Script code="Mission endMission false" onLoad="false" times="1" >
+        <events>
+            <trigger>
+                <EventListener event="inExplosionRange" />
+            </trigger>
+        </events>
+    </Script> 
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/iiiJohnVane_EscapeTheBastards.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/iiiJohnVane_EscapeTheBastards.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/iiiJohnVane_EscapeTheBastards.oxw	(revision 11817)
@@ -0,0 +1,1420 @@
+<!-- -->
+
+<!--TODO
+
+Everything works fine, there are just some design issues:
+
+- Better Homeplanet Design
+- Change Boxdesign at the End (metal_crate.mesh instead of crate.mesh)
+- Apply Boxcollison
+- Green Box at the end Triangular
+- Better Portal Jump
+- better forcefield
+- Sun Background (Particle Effects)
+- Asteroid Belts around Planets (without lags!!!)
+-->
+
+
+<!--
+Basic ------------------------------------------------------------------------------------------------------------------------>
+<!--Basic Infos-->
+
+<LevelInfo
+ name = "(iii) John Vane: Escape the Bastards"
+ description = "You destroyed their Base, you accomplished the mission. Now get out of there, and get rid of the haunters."
+ tags = "mission"
+ screenshot = "EscapeTheBastards.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/pickupRepresentationTemplates.oxt")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+  include("templates/spaceshipTurret.oxt")
+?>
+
+<Level
+  name = "Escape the bastards"
+  description = "You destroyed their Base, you accomplished the mission. Now get out of there, and get rid of the haunters"
+  gametype=Mission
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  
+  <?lua include("includes/notifications.oxi") ?>
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=4.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxMoreNebula" 
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <!-- SpawnPoint team=0 position="-1000,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff / -->
+
+<!-- Pickups -->
+
+    <PickupSpawner pickup=dronepickup position="-5000,-1300,-209" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+    <PickupSpawner pickup=hugehealthpickup position="0,-4,-1540" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" visible="true">
+        <events>
+            <visibility>
+                <EventListener event="boxtrigger" />
+            </visibility>
+        </events>
+    </PickupSpawner>
+    <PickupSpawner pickup=mediumspeedpickup position="0,4,-1540" triggerDistance="10" respawnTime="10" maxSpawnedItems="99"  visible="true">
+        <events>
+            <visibility>
+                <EventListener event="boxtrigger" />
+            </visibility>
+        </events>
+    </PickupSpawner>
+
+<!-- Pickups heal the box, so one cant destroy the box -->
+
+<!-- Pickups END -->
+<!--Basic Infos end-->
+
+<!--Story----------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+
+
+<!--Quests (Fly to the Ally)-->
+    <EventMultiTrigger name=spawntrigger>
+        <events>
+            <trigger>
+                <TeamSpawnPoint team=0 position="-8050,0,0" direction="1,0.3,0.2" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage>
+<!-- Spawnpoint aendern zu -8050,0,0 nachher direction="1,0.3,0.2"-->
+<!-- Spawnpoint aendern zu 3000,12000,-5500 nachher direction="0.3,1.2,-5.5" Fuer homeplanet-->
+<!-- Spawnpoint aendern zu -46950,-30000,30000 nachher direction="1,0,0" Fuer inBox-->
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="missionfinish" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </TeamSpawnPoint>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+
+    <TeamSpawnPoint team=0 position="0,-2500,0" direction="0,-1,0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage active =false>
+        <events>
+            <activity>
+                <EventListener event="reachedally" />
+            </activity>
+        </events>
+    </TeamSpawnPoint>
+
+    <TeamSpawnPoint team=0 position="-46950,-30000,30000" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage active =false>
+        <events>
+            <activity>
+                <EventListener event="cave1" />
+            </activity>
+        </events>
+    </TeamSpawnPoint>
+
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <AddQuest questId="Helpisontheway.1" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=spawntrigger />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="Helpisontheway.1" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="missionfinish" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+
+        <QuestEffectBeacon times=1 >
+            <effects>
+                <CompleteQuest questId="defend.2" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="Boxdestroyed" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon times=1 >
+            <effects>
+                <CompleteQuest questId="leave.3" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="reachedhomeplanet" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon times=1 >
+            <effects>
+                <CompleteQuest questId="wayhome.4" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="reachedend" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+    <!-- END OF GAME -->
+    <SimpleNotification message="Well done, you've finished">
+        <events>
+            <trigger>
+                <EventListener event=reachedend />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <Script code="Mission endMission true" onLoad="false" times="1">
+        <events>
+            <trigger>
+                <EventListener event="reachedend" />
+            </trigger>
+        </events>
+    </Script>
+    
+    <Script code="Mission setLives 1" onLoad="true" times="1" />
+    <!-- END OF GAME END -->
+
+
+    <DistanceTrigger name="missionfinish" position="-120,0,0" target="Pawn" distance=60 stayActive="true" delay=1>
+    </DistanceTrigger>
+    <DistanceTrigger name="reachedally" position="-120,0,0" target="Pawn" distance=60 stayActive="true" delay=0>
+    </DistanceTrigger>
+    <DistanceTrigger name="reachedhomeplanet" position="-3000,12000,-6990" target="Pawn" distance=100 stayActive="true" delay=0>
+    </DistanceTrigger>
+    <DistanceTrigger name="reachedend" position="-41000,-30000,33800" target="Pawn" distance=60 stayActive="true" delay=2>
+    </DistanceTrigger>
+
+          <EventTrigger name="boxtrigger" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="box" />
+              </trigger>
+            </events>
+          </EventTrigger>
+
+
+<!-- Billboard Allyplanet -->
+
+<BlinkingBillboard position="-120,0,0" frequency=0.4 amplitude=3 material="Flares/lensflare" colour="1,1,0.05">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event="missionfinish" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</BlinkingBillboard>
+
+<Billboard position="-120,0,0" amplitude=1 material="Flares/lensflare" colour="0,0.8,0.1">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="missionfinish" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</Billboard>
+
+<!-- Billboard Allyplanet END-->
+
+
+<!-- Box with Pickups -->
+    <Pawn team=1 health=30 position="0,0,-1500" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "Something" >
+        <events>
+          <visibility>
+            <EventListener event="target3" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="5,5,5" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    <controller>
+                      <WaypointController team=1>
+                    </WaypointController>
+        </controller>
+        <explosion >
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+    </Pawn>
+
+<Billboard position="0,0,-1540" amplitude=1 material="Flares/lensflare" colour="0,0.8,0.1">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="boxtrigger" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</Billboard>
+<!-- Box with Pickups END -->
+
+<!-- Billboard Homeplanet -->
+
+<!-- evt Blinking light before landing on planet, Entfernen nach architektur-->
+<BlinkingBillboard position="-3000,12000,-6990" frequency=0.4 amplitude=3 material="Flares/lensflare" colour="1,1,0.05">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="boxtrigger"/> <!-- reachedhomeplanet--> 
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</BlinkingBillboard>
+
+
+<!-- Billboard Homeplanet END-->
+
+
+<!--Quests (Fly to the Ally) END-->
+
+<!--Quests (Fight Enemies)-->
+
+
+ <SpaceShip position="1000,0,0" lookat="0,0,1" name="attacker" radarname="Fighter1" visible="true">
+                            <events>
+                                <visibility>
+                                    <EventListener event="missionfinish" />
+                                </visibility>
+                            </events>
+
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointPatrolController alertnessradius=750  team=1 active=false>
+                         <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="1000,0,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="500,500,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,1000,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="-500,500,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="-1000,0,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="-500,-500,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,-1000,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="500,-500,0"/>
+                       </waypoints>
+                       <events>
+                         <activity>
+                              <EventListener event="reachedally" />
+                         </activity>
+                       </events>
+                    </WaypointPatrolController>
+                  </controller>
+                </SpaceShip>
+
+ <SpaceShip position="0,1000,0" lookat="1,0,0" name="attacker" radarname="Fighter2" visible="true">
+                            <events>
+                                <visibility>
+                                    <EventListener event="missionfinish" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointPatrolController alertnessradius=750  team=1 active=false>
+                         <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="0,1000,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,500,500"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,0,1000"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,-500,500"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,-1000,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,-500,-500"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,0,-1000"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,500,-500"/>
+                       </waypoints>
+                       <events>
+                         <activity>
+                              <EventListener event="reachedally" />
+                         </activity>
+                       </events>
+                    </WaypointPatrolController>
+                  </controller>
+                </SpaceShip>
+
+ <SpaceShip position="0,0,1000" lookat="0,1,0" name="attacker" radarname="Fighter3" visible="true">
+                            <events>
+                                <visibility>
+                                    <EventListener event="missionfinish" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointPatrolController alertnessradius=750  team=1 active=false>
+                         <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="1000,0,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="500,0,500"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,0,1000"/>
+                        <Model mesh="cube.mesh" scale=0 position="-500,0,500"/>
+                        <Model mesh="cube.mesh" scale=0 position="-1000,0,0"/>
+                        <Model mesh="cube.mesh" scale=0 position="-500,0,-500"/>
+                        <Model mesh="cube.mesh" scale=0 position="0,0,-1000"/>
+                        <Model mesh="cube.mesh" scale=0 position="500,0,-500"/>
+                       </waypoints>
+                       <events>
+                         <activity>
+                              <EventListener event="reachedally" />
+                         </activity>
+                       </events>
+                    </WaypointPatrolController>
+                  </controller>
+                </SpaceShip>
+
+<!-- @Triggers: Attakers, Fight one by one  -->
+
+    <EventTrigger name="target3" activations="1" stayactive="true" delay=0.1>
+          <events>
+            <trigger>
+              <EventListener event="attacker" />
+            </trigger>
+          </events>
+       <EventTrigger name="target2" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="attacker" />
+              </trigger>
+        </events>
+       <EventTrigger name="target1" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="attacker" />
+              </trigger>
+        </events>
+          </EventTrigger>
+        </EventTrigger>
+        </EventTrigger>
+
+
+    <SimpleNotification message="Wow, That's an explosion."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="target1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Booom, you got him!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="target2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <SimpleNotification message="No Mercy!! .. What's that?"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="target3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+
+
+<!-- @Triggers: Attakers, Fight one by one END  -->
+
+
+<!--Quests (Fight Enemies) END-->
+
+
+<!-- LocalQuests -->
+    <LocalQuest id="Helpisontheway.1">
+        <QuestDescription title="Help is on the way" description="An allied pilot is cast away on a planet in front of you. Pick him up and leave.
+
+
+        Hint: He will blink with his lamp
+
+        PS: Remind the gravitation field"
+
+ 
+    failmessage="Well, you sucked" completeMessage="Well done, You're a hero" />
+        <complete-effects>
+            <AddQuest questId="defend.2" />
+        </complete-effects>
+    </LocalQuest>
+
+
+    <LocalQuest id="defend.2">
+        <QuestDescription title="Defend the Planet" description="Well your enemies trapped you. Kill'em all."
+
+    failmessage="Well, you sucked" completeMessage="Well done, You're a hero" />
+        <complete-effects>
+            <AddQuest questId="leave.3" />
+        </complete-effects>
+    </LocalQuest>
+
+
+
+    <LocalQuest id="leave.3">
+        <QuestDescription title="Leave the Place" description="You've blown their minds. Let's go home. Aim the Big blue planet to reach your home." failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="wayhome.4" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="wayhome.4">
+        <QuestDescription title="Let's go home" description="You've reached the portal. You've been teleportet to the passage to your home, but your enemies trapped you again" failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="end.5" />
+        </complete-effects>
+    </LocalQuest>
+
+<!-- LocalQuests END -->
+
+<!-- Message Triggers -->
+    <DistanceTrigger name="StartofMission" position="-8050,0,0" target="Pawn" distance=10 stayActive="true" delay=1.2/>
+    <SimpleNotification message="Houston: John can you hear me?">
+        <events>
+            <trigger>
+                <EventListener event="StartofMission" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="Introduction1" position="-8050,0,0" target="Pawn" distance=30 stayActive="true" delay=6.4/>
+    <SimpleNotification message="John: No. Can i go home now?">
+        <events>
+            <trigger>
+                <EventListener event="Introduction1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="Introduction2" position="-8050,0,0" target="Pawn" distance=30 stayActive="true" delay=10.8/>
+    <SimpleNotification message="Houston: Not yet, another ally needs your help.">
+        <events>
+            <trigger>
+                <EventListener event="Introduction2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="Introduction3" position="-8050,0,0" target="Pawn" distance=30 stayActive="true" delay=15.2/>
+    <SimpleNotification message="Houston: He had to force land near you.">
+        <events>
+            <trigger>
+                <EventListener event="Introduction3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <DistanceTrigger name="PickedUpAlly" position="-120,0,0" target="Pawn" distance=30 stayActive="true" delay=0.1/>
+    <SimpleNotification message="John: Are you kidding me, thats a kitty.">
+        <events>
+            <trigger>
+                <EventListener event="PickedUpAlly" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="PickedUpAlly1" position="-120,0,0" target="Pawn" distance=30 stayActive="true" delay=4.4/>
+    <SimpleNotification message="Houston: ... but if there is no ally...">
+        <events>
+            <trigger>
+                <EventListener event="PickedUpAlly1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="PickedUpAlly2" position="-120,0,0" target="Pawn" distance=30 stayActive="true" delay=8.8/>
+    <SimpleNotification message="Houston: F***, they trapped us">
+        <events>
+            <trigger>
+                <EventListener event="PickedUpAlly2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <SimpleNotification message="Houston: Pickups! Pick them up :-)"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="boxtrigger" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="Boxdestroyed" position="0,0,-1540" target="SpaceShip" distance=50 stayActive="true" delay=0.1 />
+    <SimpleNotification message="Houston: Now aim the blue planet">
+        <events>
+            <trigger>
+                <EventListener event="Boxdestroyed" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="Boxdestroyed2" position="0,0,-1540" target="SpaceShip" distance=50 stayActive="true" delay=4.4 />
+    <SimpleNotification message="Houston: Land near the blinking light!">
+        <events>
+            <trigger>
+                <EventListener event="Boxdestroyed2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Houston: You're almost there">
+        <events>
+            <trigger>
+                <EventListener event="reachedhomeplanet" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<DistanceTrigger name="cave1" position="-46300,-30000,30000" target="SpaceShip" distance=100 stayActive="true" delay=0.1 />
+    <SimpleNotification message="Houston: You reached the cave, you're safe!!">
+        <events>
+            <trigger>
+                <EventListener event="cave1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<DistanceTrigger name="cave2" position="-46300,-30000,30000" target="SpaceShip" distance=100 stayActive="true" delay=4.4 />
+    <SimpleNotification message="Houston: ... wait it's a tr#@$%&^#$...">
+        <events>
+            <trigger>
+                <EventListener event="cave2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<DistanceTrigger name="cave3" position="-46300,-30000,30000" target="SpaceShip" distance=100 stayActive="true" delay=8.8 />
+    <SimpleNotification message="John: not again ...">
+        <events>
+            <trigger>
+                <EventListener event="cave3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <SimpleNotification message="Sanchez: I waited for you ...">
+        <events>
+            <trigger>
+                <EventListener event="Reachedtheend" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+
+<!-- Message Triggers END -->
+
+<!--Quests____END-->
+
+
+
+<!--Enviroment-------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+
+    <!--Asteroids Field-->
+
+    <?lua for i=0,650,1 do
+        x=math.random(-8000,-1000)
+        y=math.random(-2345,2345)
+        z=math.random(-2500,2500)
+    scale=math.random(20,70)
+    ?>
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=0 mass="<?lua print(scale * 5) ?>" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" rotationaxis="<?lua print(math.random()) ?>,<?lua print(math.random()) ?>,<?lua print(math.random()) ?>" rotationrate="<?lua print(math.random()*15) ?>"       collisiondamage = 0.005
+      enablecollisiondamage = true >
+        <attached>
+            <Model scale="<?lua print(scale) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="<?lua print(scale * 3) ?>" />
+        </collisionShapes>
+    </MovableEntity>
+    <?lua end ?>
+
+                            <!--Asteroids Field end -->
+
+
+                            <!--Asteroids Random
+
+                "The game lags, when you're flying far away"
+
+
+    <?lua for i=0,300,1 do
+        x=math.random(-12000,4000)
+        y=math.random(-8000,8000)
+        z=math.random(-8000,8000)
+    ?>
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=0 mass="<?lua print(scale * 5) ?>" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" rotationaxis="<?lua print(math.random()) ?>,<?lua print(math.random()) ?>,<?lua print(math.random()) ?>" rotationrate="<?lua print(math.random()*15) ?>"      collisiondamage = 0.005
+      enablecollisiondamage = true  >
+        <attached>
+            <Model scale="<?lua print(math.random(20,70)) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false/>
+        </attached>
+        <collisionShapes>
+            <SphereCollisionShape radius="<?lua print(scale * 3) ?>" />
+        </collisionShapes>
+    </MovableEntity>
+    <?lua end ?>
+-->
+                            <!--Asteroids  Random end-->
+
+                                <!--Asteroid Elipse-->
+<!-- LAAAGS :-(
+
+                "The game lags, when you're flying far away"        
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(-3000,12000,-10000, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(-3000,12000,-10000, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+-->
+
+
+    <?lua
+    max = 20
+    for i = 0, max, 1
+    do
+    y = math.sin(i/max*6)*2000
+    z = math.cos(i/max*6)*2500
+    x = 0
+    ?>
+    <?lua
+    for k = 1, 15, 1
+    do
+    j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(x + math.random() * 500) ?>,<?lua print(y + math.random() * 500) ?>,<?lua print(z + math.random() * 1000) ?>"
+      collisionType = "dynamic"
+      linearDamping = "0.5"
+      angularDamping = "0.01"
+      collisiondamage = "0.01"
+      enablecollisiondamage = "true"
+      scale="<?lua print(j * 5) ?>" >
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh">
+      <?lua if k == 5 then ?><attached>            <!--asteroid fog-->
+            <ParticleEmitter position="0,0,0" source="Orxonox/Steam" />
+          </attached> <?lua end ?>
+        </Model>
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 80) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+    <?lua
+    end
+    ?>
+    <?lua end ?>
+<!--Asteroid Elipse end-->
+
+<!--Planet sun-->
+    <Planet position="15000,0,0" scale=1500 pitch=-90 mesh="planets/sol.mesh" atmosphere="atmosphere1" rotationaxis="8,1,0" rotationrate="1" atmospheresize=0 imagesize=1024.0f />
+    <StaticEntity position="2600,0,0" collisionType=static>
+        <collisionShapes>
+            <SphereCollisionShape radius="399" />
+        </collisionShapes>
+    </StaticEntity>
+
+    <Billboard position="15100,0,0" material="Flares/backlightflare" colour="0.7,0.4,0.1" scale=600 />
+
+<!--Planet END-->
+
+<!--Planet with Ally-->
+    <Planet
+      position="0,0,0"
+      scale="100"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="5000000"
+      pitch="0"
+      mesh="iceplanet.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="1000" velocity="-500" />
+                    <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="100" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+<!-- Planet with Ally END-->
+
+
+<!-- Homeplanet -->
+    <Planet
+      position="-3000,12000,-10000"
+      scale="3000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="5000000000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="0,0,0"
+      rotationrate="0.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="10000" velocity="-900" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="3000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+<!-- Homeplanet  END-->
+
+<!-- Planet around the cave-->
+
+<Planet position="-43500,-30000,31900" scale=5000 pitch=-90 mesh="planets/moon.mesh" atmosphere="atmosphere1" rotationaxis="8,1,0" rotationrate="1" atmospheresize=0 imagesize=1024.0f />
+
+<!-- Planet around the cave END-->
+
+<!-- Anotherplanet -->
+    <Planet
+      position="-20000,6000,7000"
+      scale="3000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="5000000000000"
+      pitch="0"
+      mesh="planets/ganymede.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="0,0,0"
+      rotationrate="0.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+    >
+      <collisionShapes>
+        <SphereCollisionShape radius="3000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+<!-- LAAAGS :-(
+
+                "The game lags, when you're flying far away"
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(-20000,6000,7000, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+-->
+                              <!-- Anotherplanet  END-->
+
+                              <!-- Homeplanet Architecture-->
+<!-- -3000,12000,-6990  = Billboard position-->
+
+     <!--     <Model  position="-3070,12070,-6990" yaw="90" pitch="-90" roll="0" scale="70" mesh="asteroid_ice.mesh" >
+      <collisionShapes>
+        <SphereCollisionShape radius="70" position="0,0,0" />
+      </collisionShapes>
+    </Model>
+-->
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=0 mass="500"  pitch="90" roll="86" yaw="12" position="-2900,12080,-6990" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="70" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="70" />
+        </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500"   pitch="30" roll="11" yaw="51" position="-3200,11950,-6990" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="90" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="90" />
+        </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500"  pitch="0" roll="12" yaw="81"  position="-2800,12150,-6990" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="90" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="90" />
+        </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500"  pitch="0" roll="0" yaw="0" position="-3300,11800,-6990" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="155" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="155" />
+        </collisionShapes>
+    </MovableEntity>
+
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500"  pitch="0" roll="0" yaw="12" position="-3230,12300,-6990" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="150" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="150" />
+        </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500" pitch="13" roll="23"yaw="120" position="-3000,12000,-6820" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="100" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="100" />
+        </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500" pitch="2" roll="12" yaw="43" position="-3250,12100,-6850" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="70" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="70" />
+        </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity collisionType=kinematic linearDamping=0.8 angularDamping=5 mass="500" pitch="0" roll="0" yaw="0"  position="-3230,11800,-6990" rotationaxis="0,0,0" rotationrate="0"       collisiondamage = 0.01  enablecollisiondamage = true >
+        <attached>
+            <Model scale="85" mesh="asteroid_ice.mesh"  shadow=false/>
+        </attached>
+        <collisionShapes>
+               <SphereCollisionShape radius="85" />
+        </collisionShapes>
+    </MovableEntity>
+
+                             <!-- Homeplanet Architecture END-->
+
+
+                            <!-- Portal-->
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Model mesh="Spacegate.mesh" yaw="90"/>
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="-3000,12000,-6990" id="1" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0"/>
+    <PortalEndPoint position="-47000,-30000,30000" id="2" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0" pitch = "180"/>
+    <PortalLink fromID="1" toID="2" />
+
+
+                            <!-- Portal END-->
+
+
+    <!-- The Cave-->
+<!-- verhaeltniss Cube.mesh <-> Crate.mesh 1:5 -->
+
+                    <!-- Enemies-->
+<Turret position="-43700,-30000,30000" pitch="0" yaw="90" roll="90">
+    <templates>
+        <Template link=spaceshipturret />
+    </templates>
+    <controller>
+        <WaypointPatrolController alertnessradius=700 team=3>
+        </WaypointPatrolController>
+     </controller>
+</Turret>
+
+<Turret position="-43700,-30000,33600" pitch="0" yaw="0" roll="0">
+    <templates>
+        <Template link=spaceshipturret />
+    </templates>
+    <controller>
+        <WaypointPatrolController alertnessradius=3000 team=3>
+        </WaypointPatrolController>
+     </controller>
+</Turret>
+
+<Turret position="-43720,-30000,31000" pitch="0" yaw="0" roll="0">
+    <templates>
+        <Template link=spaceshipturret />
+    </templates>
+    <controller>
+        <WaypointPatrolController alertnessradius=3000 team=3>
+        </WaypointPatrolController>
+     </controller>
+</Turret>
+
+<Turret position="-43700,-29980,32100" pitch="0" yaw="0" roll="0">
+    <templates>
+        <Template link=spaceshipturret />
+    </templates>
+    <controller>
+        <WaypointPatrolController alertnessradius=3000 team=3>
+        </WaypointPatrolController>
+     </controller>
+</Turret>
+
+
+ <DistanceTrigger name="Reachedtheend" position="-43700,-29980,33000" target="SpaceShip" distance=300 stayActive="true" delay=0 />
+
+ <SpaceShip position="-42000,-30000,33800" lookat="-1,0,0" name="attacker" radarname="Enemy1" visible="true">
+                            <events>
+                                <visibility>
+                                    <EventListener event="Reachedtheend" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointPatrolController alertnessradius=1500  team=3 active=false>
+                         <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="-41200,-30000,33800"/>
+                       </waypoints>
+                       <events>
+                         <activity>
+                              <EventListener event="Reachedtheend" />
+                         </activity>
+                       </events>
+                    </WaypointPatrolController>
+                  </controller>
+                </SpaceShip>
+ <SpaceShip position="-42200,-30000,33800" lookat="-1,0,0" name="attacker" radarname="Enemy2" visible="true">
+                            <events>
+                                <visibility>
+                                    <EventListener event="Reachedtheend" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointPatrolController alertnessradius=1500  team=3 active=false>
+                         <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="-41600,-30000,33800"/>
+                       </waypoints>
+                       <events>
+                         <activity>
+                              <EventListener event="Reachedtheend" />
+                         </activity>
+                       </events>
+                    </WaypointPatrolController>
+                  </controller>
+                </SpaceShip>
+ <SpaceShip position="-42400,-30000,33800" lookat="-1,0,0" name="attacker" radarname="Sanchez" visible="true">
+                            <events>
+                                <visibility>
+                                    <EventListener event="Reachedtheend" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointPatrolController alertnessradius=1500  team=3 active=false>
+                         <waypoints>
+                        <Model mesh="cube.mesh" scale=0 position="-41400,-30000,33800"/>
+                       </waypoints>
+                       <events>
+                         <activity>
+                              <EventListener event="Reachedtheend" />
+                         </activity>
+                       </events>
+                    </WaypointPatrolController>
+                  </controller>
+                </SpaceShip>
+
+<!-- Enemies END-->
+
+
+<!-- 15 Boxes forward-->
+ <?lua
+    max = 15
+    for i = 0, max, 1
+    do
+    y=(i*200)-47200
+
+    ?>
+
+    <?lua
+    for j = 0, 2, 1
+    do
+    z =30200-(j*200)
+    ?>    
+    
+    <?lua
+    for k = 0, 1, 1
+    do
+    x =-30200+(k*400)
+    ?>
+
+
+
+
+  <StaticEntity position="<?lua print(y) ?>,<?lua print(x) ?>,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01 >
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20"  />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+
+    <?lua end ?>
+    <?lua end ?>
+    <?lua end ?>
+
+ <?lua
+    max = 15
+    for i = 0, max, 1
+    do
+    y=(i*200)-47200
+
+    ?>
+    <?lua
+    for j = 0, 1, 1
+    do
+    z =30200-(j*400)
+    ?>    
+  <StaticEntity position="<?lua print(y) ?>,-30000,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+    <?lua end ?>
+    <?lua end ?>
+
+  <StaticEntity position="-47200,-30000,30000" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+                    <!-- 15 Boxes forward END -->
+                    <!-- 18 Boxes right-->
+
+ <?lua
+    max = 18
+    for i = 0, max, 1
+    do
+    z=29800+(i*200)
+
+    ?>
+
+    <?lua
+    for j = 0, 2, 1
+    do
+    y = (j*200)-44000
+    ?>    
+    
+    <?lua
+    for k = 0, 1, 1
+    do
+    x =-30200+(k*400)
+    ?>
+
+
+
+
+  <StaticEntity position="<?lua print(y) ?>,<?lua print(x) ?>,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+
+    <?lua end ?>
+    <?lua end ?>
+    <?lua end ?>
+
+ <?lua
+    max = 16
+    for i = 0, max, 1
+    do
+    z = 30200+(i*200)
+
+    ?>
+    <?lua
+    for j = 0, 1, 1
+    do
+     y = (j*400)-44000
+    ?>    
+  <StaticEntity position="<?lua print(y) ?>,-30000,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+    <?lua end ?>
+    <?lua end ?>
+
+  <StaticEntity position="-43600,-30000,30000" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+ <?lua
+    for i = 0, 2, 1
+    do
+    y = -44000+(i*200)
+
+    ?>
+  <StaticEntity position="<?lua print(y) ?>,-30000,29800" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+    <?lua end ?>
+
+    <!-- 18 Boxes right END-->
+    <!-- 17 Boxes forward-->
+ <?lua
+    max = 17
+    for i = 0, max, 1
+    do
+    y=(i*200)-44000
+
+    ?>
+
+    <?lua
+    for j = 0, 2, 1
+    do
+    z =34000 - (j*200)
+    ?>    
+    
+    <?lua
+    for k = 0, 1, 1
+    do
+    x =-30200+(k*400)
+    ?>
+
+
+
+
+  <StaticEntity position="<?lua print(y) ?>,<?lua print(x) ?>,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+
+    <?lua end ?>
+    <?lua end ?>
+    <?lua end ?>
+
+ <?lua
+    max = 15
+    for i = 0, max, 1
+    do
+    y=(i*200)-43600
+
+    ?>
+
+    <?lua
+    for j = 0, 0, 1
+    do
+    z =34000 - (i*5.5)
+    ?>
+
+  <StaticEntity position="<?lua print(y) ?>,-30000,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+    <?lua end ?>
+    <?lua end ?>
+ <?lua
+    max = 15
+    for i = 0, max, 1
+    do
+    y=(i*200)-43600
+
+    ?>
+
+    <?lua
+    for j = 0, 0, 1
+    do
+    z =33600 + (i*5.5)
+    ?>
+
+  <StaticEntity position="<?lua print(y) ?>,-30000,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+    <?lua end ?>
+    <?lua end ?>
+
+
+ <?lua
+    for i = 0, 1, 1
+    do
+    y = -44000+(i*200)
+
+    ?>
+  <StaticEntity position="<?lua print(y) ?>,-30000,34000" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+    <?lua end ?>
+
+  <StaticEntity position="-44000,-30000,33800" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+
+  <StaticEntity position="-44000,-30000,33600" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="20,20,20" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+
+      </collisionShapes>
+</StaticEntity>
+<!-- 17 Boxes forward END-->
+    <Billboard position="-41000,-30000,33800" material="Flares/backlightflare" colour="0,1.4,2.1" scale=15 />
+
+  <StaticEntity position="-40400,-30000,33800" direction="0,0,0" collisionType=static mass=100000 friction=0.01>
+     <attached>
+        <Model position="0,0,0" mesh="cube_green.mesh" scale3D="100,100,100" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,100" />
+      </collisionShapes>
+</StaticEntity>
+
+<!-- FORCEFIELD -->
+<ForceField position="-47000,-30000,30000" direction="1,0,0" diameter=2000 velocity=2000 length=2000 />
+
+
+<!-- The Cave END-->
+
+<!-- Planet around the cave-->
+
+  </Scene>
+</Level>
+
+
+
Index: /code/branches/RacingBots_FS18/data/levels/includes/CuboidSpaceStation.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/CuboidSpaceStation.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/CuboidSpaceStation.lua	(revision 11817)
@@ -0,0 +1,678 @@
+----------------------------------------------------------------------------------------------------
+-- This lua script creates a totally random generated space station for the orxonox computer game!--
+-- (c) Wallah 2008, published under GPL licence!                                                  --
+----------------------------------------------------------------------------------------------------
+
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- IMPORTANT: If you need more parameters, do the following: copy the actual function (just the headline and the end statement) to the end of the file,           --
+-- like I did with createSpaceStation() and let that function call the new function where you can modify the parameters. For all parameters which the old function--
+-- doesn't have you just give the standard default values, which I have defined. This is to make sure, that anyone else who uses the old function can still use it--
+-- the same way he/she always did. If you want a function with less parameters, just create a new one at the end of the file and call this function with some     --
+-- default values. REMEMBER: Function overloading is not possible, be sure to call your function differently from others already existing ones.                   --
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+-- This function creates a randomly generated space station.
+-- The first argument ranSeed, must be 0, or a positive Integer, if it is 0 your space station is always chosen randomly, if you give an integer,
+--  your space station will be generated randomly, but once you have the space station it will always be the same.
+-- The argument xLength defines how large the space station will be into the x-direction.
+-- The argument xVar defines how much the space station will vary at the ends in x-direction, this is so that the station is no cube.
+-- The argument yLength is the same as xLength, but for the y-direction.
+-- The argument yVar is the same as xLength, but for the y-direction.
+-- The argument zLength is the same as xLength, but for the z-direction.
+-- The argument zVar is the same as xLength, but for the z-direction.
+-- The argument sSScale scales the station proportionally in all directions.
+function createSpaceStationPar(ranSeed, xLength, xVar, yLength, yVar, zLength, zVar, sSScale)
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- This prints xml code, which creates a MovableEntity, which I need to attach all the parts of the space station.
+print("<MovableEntity scale=1 position=\"0,0,0\" >")
+-- End create Movable Entity.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Create a randomseed, so that the math.random() function is actually random.
+if ranSeed == 0 then
+    math.randomseed(os.time())
+else
+    math.randomseed(ranSeed)
+end
+-- End create randomseed.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Here you can define some global variables, with which you can modify the space station.
+
+-- Define the maximal size of the grid, this value is based on how large you define the area of bodyparts plus 20 gridpoints for attachparts.
+sSSize=30
+if xLength>=yLength and xLength>=zLength then
+    sSSize=xLength+20
+elseif yLength>=xLength and yLength>=zLength then
+    sSSize=yLength+20
+elseif zLength>=xLength and zLength>=yLength then
+    sSSize=zLength+20
+end
+-- Define how many parts the space station has, this value has to be exact, so be sure to increment it if you're adding a new part.
+sSParts=9
+-- Define how many body parts the space station has, this value has to be exact. Body part means a part, which has connections at least in two directions.
+sSBodyParts=3
+-- Define how many frontParts you have.
+frontParts=1
+-- Define how many backParts you have.
+backParts=1
+-- Define how many side parts for the left side you have.
+leftSideParts=1
+-- Define how many side parts for the right side you have.
+rightSideParts=1
+-- Define how many top parts you have.
+topParts=2
+-- Define how many connection parts you have.
+connParts=1
+-- Define the maximal dimension of a single part, be sure this value is big enough, better it's too big, it's only a matter of efficiency.
+-- It should be at least 1 bigger than the biggest part needs, because I guarantee that it works with odd numbers, to do so I use the math.floor function.
+pDim=6
+-- Define the griddimension, be sure this value matches the size of a single space station part plus the size of a connection part, which means your parts must be:
+--  integer*(gridDim-connectionSize), then integer tells you how many griddimensions your part is.
+gridDim=2.25
+-- End define global parameters.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- This creates a 4-dimensional grid, which tells us if there is a part or not, and in which direction it has connections.
+-- The parameters x,y,z are the axis of the space station, which iterate to sSSize, the maximal size of the space station.
+-- The griddimension, this word I will use later, means that the distance of a point to the next point is gridDim in the game, so the absolute x-axis is x*gridDim*sSScale,
+--  and so on for the other dimensions y and z.
+-- grid[x][y][z][0] contains 0 if there is no part at the position (x,y,z), otherwise 1.
+-- grid[x][y][z][1] contains 0 if there is no connection from (x,y,z) in x-direction, "+" if there is one in the positive x-direction,
+--  "-" if there is one in the negative x-direction, "+-" if there are in both x-directions.
+-- grid[x][y][z][2] contains 0 if there is no connection from (x,y,z) in y-direction, "+" if there is one in the positive y-direction,
+--  "-" if there is one in the negative y-direction, "+-" if there are in both y-directions.
+-- grid[x][y][z][3] contains 0 if there is no connection from (x,y,z) in z-direction, "+" if there is one in the positive z-direction,
+--  "-" if there is one in the negative z-direction, "+-" if there are in both z-directions.
+grid = {}
+for x=-math.floor(sSSize/2),math.floor(sSSize/2) do
+    grid[x] = {}
+    for y=-math.floor(sSSize/2),math.floor(sSSize/2) do
+        grid[x][y]= {}
+        for z=-math.floor(sSSize/2),math.floor(sSSize/2) do
+            grid[x][y][z]={}
+            for i=0,3 do
+                grid[x][y][z][i]=0
+            end
+        end
+    end
+end
+-- End create 4-dim grid.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- This creates an array which stores all the parts, it's size is depending on the global values pDim and sSParts.
+-- The first parameter i, tells us how many parts fit into the array, so it iterates from 1 to sSParts, each part has his own value i.
+-- The second, third and fourth parameters are the relative coordinates of the part, you have to start at (0,0,0) and be sure you fill the array into the right direction.
+--  A short example: your part is 2 griddimensions long and you place it in the game, that the relative coordinate point is at (0,0,0) and the part lies in the positive
+--  z-axis, then you have to use the coordinate point (0,0,1).
+-- The fifth parameter is an array with size 4, at index=0, you have to set 1 if your part covers the gridpoint at (x,y,z), otherwise 0.
+--  At index=1,2,3 you define the possible connection directions (1 for x, 2 for y and 3 for z), be sure to use the notation from above (0, "+-", "+", "-").
+bodyParts={}
+for i=1,sSParts do
+    bodyParts[i]={}
+    for x=-math.floor(pDim/2),math.floor(pDim/2) do
+        bodyParts[i][x]={}
+        for y=-math.floor(pDim/2),math.floor(pDim/2) do
+            bodyParts[i][x][y]={}
+            for z=-math.floor(pDim/2),math.floor(pDim/2) do
+                bodyParts[i][x][y][z]={}
+                for k=0,3 do
+                    bodyParts[i][x][y][z][k]=0
+                end
+            end
+        end
+    end
+    -- This contains the name of the mesh file.
+    bodyParts[i][0][0][0][4]=""
+    -- This contains the first possible rotation of your part, pitch=... yaw=... roll=... .
+    bodyParts[i][0][0][0][5]=""
+    -- This contains the second possible rotation of your part, pitch=... yaw=... roll=... .
+    bodyParts[i][0][0][0][6]=""
+    -- This contains the third possible rotation of your part, pitch=... yaw=... roll=... .
+    bodyParts[i][0][0][0][7]=""
+    -- Contains the movement rotation, rotationaxis=... rotationrate=... .
+    bodyParts[i][0][0][0][8]=""
+    -- Contains the attachment, if your part has an attachment, e.g. <ParticleEmitter .../>.
+    bodyParts[i][0][0][0][9]=""
+    -- Contains how many of this part you want to attach to your space station.
+    bodyParts[i][0][0][0][10]=1
+end
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Here you can add a part to the space station, there are some examples here and how to describe your part is written above in the commentary.
+
+-- The part must be inserted so, that the center of reference is at position (0,0,0).
+-- At position bodyParts[i][0][0][0][4] you have to put the mesh name of your part.
+-- At bodyParts[i][0][0][0][5] you can rotate your part, with pitch=angle, yaw=angle or roll=angle (x,y or z). Positive angle means in screw direction.
+-- At bodyParts[i][0][0][0][6] you have another possibility to rotate your part in a different way, e.g. for left and right side parts.
+-- At bodyParts[i][0][0][0][7] you have a third possibility to rotate your part, e.g. connection parts must be rotated into 3 different ways.
+-- At bodyParts[i][0][0][0][8] you can rotate your part around his own axis, with rotationaxis="x,y,z" rotationrate=number.
+-- At bodyParts[i][0][0][0][9] you can attach something to your model, e.g. <ParticleEmitter .../>.
+
+-- Insert the CuboidBody, which is only one griddimension and can have connections in every direction.
+bodyParts[1][0][0][0][4]="CuboidBody.mesh"
+
+bodyParts[1][0][0][0][0]=1
+bodyParts[1][0][0][0][1]="+-"
+bodyParts[1][0][0][0][2]="+-"
+bodyParts[1][0][0][0][3]="+-"
+-- End insert CuboidBody.
+
+-- Insert the DoubleCuboidBody, which is two griddimensions long, and one wide and high and can have connections in every direction except in the middle.
+bodyParts[2][0][0][0][4]="DoubleCuboidBody.mesh"
+bodyParts[2][0][0][0][5]="pitch=-90"
+
+bodyParts[2][0][0][0][0]=1
+bodyParts[2][0][0][0][1]="+-"
+bodyParts[2][0][0][0][2]="+-"
+bodyParts[2][0][0][0][3]="-"
+
+bodyParts[2][0][0][1][0]=1
+bodyParts[2][0][0][1][1]="+-"
+bodyParts[2][0][0][1][2]="+-"
+bodyParts[2][0][0][1][3]="+"
+-- End insert DoubleCuboidBody.
+
+-- Insert the CuboidConnectionBody, it is three griddimensions long and one wide and high and can have only connections at griddimension 1
+--  (except the side in direction of griddimension 2) and griddimension 3 (except the side in direction of griddimension 2).
+bodyParts[3][0][0][0][4]="CuboidConnBody.mesh"
+bodyParts[3][0][0][0][5]="pitch=-90"
+
+bodyParts[3][0][0][0][0]=1
+bodyParts[3][0][0][0][1]="+-"
+bodyParts[3][0][0][0][2]="+-"
+bodyParts[3][0][0][0][3]="-"
+
+bodyParts[3][0][0][1][0]=1
+
+bodyParts[3][0][0][2][0]=1
+bodyParts[3][0][0][2][1]="+-"
+bodyParts[3][0][0][2][2]="+-"
+bodyParts[3][0][0][2][3]="+"
+-- End insert CuboidConnectionBody.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Insert the back parts.
+-- If you're space station has no back parts, be sure to set backPartsIndex[0]=false.
+backPartsIndex={}
+backPartsIndex[0]=""
+
+-- Insert the thruster, which is one griddimension long, two wide and high, it can only have a connection into the negative z-direction.
+backPartsIndex[1]=4
+bodyParts[backPartsIndex[1]][0][0][0][4]="Thruster.mesh"
+bodyParts[backPartsIndex[1]][0][0][0][5]="pitch=-90"
+bodyParts[backPartsIndex[1]][0][0][0][9]="<ParticleEmitter position=\"0,-0.5,0\" source=\"Orxonox/ThrusterFire\" />"
+bodyParts[backPartsIndex[1]][0][0][0][10]=5
+
+bodyParts[backPartsIndex[1]][0][0][0][0]=1
+bodyParts[backPartsIndex[1]][0][0][0][3]="-"
+bodyParts[backPartsIndex[1]][1][0][0][0]=1
+bodyParts[backPartsIndex[1]][-1][0][0][0]=1
+bodyParts[backPartsIndex[1]][0][1][0][0]=1
+bodyParts[backPartsIndex[1]][0][-1][0][0]=1
+-- End insert the thruster.
+
+-- End insert the back parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Insert the front parts. If your space station has no front parts, be sure to set frontPartsIndex[0]=false.
+frontPartsIndex={}
+frontPartsIndex[0]=""
+
+-- The SemiCircleCockpit is 3 x-griddimensions long, 3 y-griddimensions and 2 z-griddimensions, it can only have a connection in the positive z-direction.
+frontPartsIndex[1]=5
+bodyParts[frontPartsIndex[1]][0][0][0][4]="SemiCircleCockpit.mesh"
+bodyParts[frontPartsIndex[1]][0][0][0][5]="pitch=-90 yaw=180"
+bodyParts[frontPartsIndex[1]][0][0][0][9]="<Billboard scale=0.01 position=\"0,-0.1,2.2\" colour=\"1.0,1.0,1.0\" material=\"Examples/Flare\" /> <Billboard scale=0.01 position=\"0.5,-0.1,2.2\" colour=\"1.0,1.0,1.0\" material=\"Examples/Flare\" /> <Billboard scale=0.01 position=\"-0.5,-0.1,2.2\" colour=\"1.0,1.0,1.0\" material=\"Examples/Flare\" />"
+
+bodyParts[frontPartsIndex[1]][0][0][0][0]=1
+bodyParts[frontPartsIndex[1]][0][0][0][3]="+"
+
+bodyParts[frontPartsIndex[1]][-1][0][0][0]=1
+bodyParts[frontPartsIndex[1]][1][0][0][0]=1
+bodyParts[frontPartsIndex[1]][0][-1][0][0]=1
+bodyParts[frontPartsIndex[1]][0][1][0][0]=1
+bodyParts[frontPartsIndex[1]][-1][-1][0][0]=1
+bodyParts[frontPartsIndex[1]][1][-1][0][0]=1
+bodyParts[frontPartsIndex[1]][-1][1][0][0]=1
+bodyParts[frontPartsIndex[1]][1][1][0][0]=1
+bodyParts[frontPartsIndex[1]][0][0][-1][0]=1
+bodyParts[frontPartsIndex[1]][-1][0][-1][0]=1
+bodyParts[frontPartsIndex[1]][1][0][-1][0]=1
+bodyParts[frontPartsIndex[1]][0][-1][-1][0]=1
+bodyParts[frontPartsIndex[1]][0][1][-1][0]=1
+bodyParts[frontPartsIndex[1]][-1][-1][-1][0]=1
+bodyParts[frontPartsIndex[1]][1][-1][-1][0]=1
+bodyParts[frontPartsIndex[1]][-1][1][-1][0]=1
+bodyParts[frontPartsIndex[1]][1][1][-1][0]=1
+-- End insert SemiCircleCockpit.
+
+-- End insert the front parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Insert the side parts.
+-- If your space station has no left side parts, be sure to set leftsidePartsIndex[0]=false.
+-- If your space station has no right side parts, be sure to set rightsidePartsIndex[0]=false.
+leftSidePartsIndex={}
+leftSidePartsIndex[0]=""
+rightSidePartsIndex={}
+rightSidePartsIndex[0]=""
+
+-- Insert the solar panel, which i wanna use as left and right side part.
+leftSidePartsIndex[1]=6
+rightSidePartsIndex[1]=leftSidePartsIndex[1]
+bodyParts[leftSidePartsIndex[1]][0][0][0][4]="SolarPanel.mesh"
+bodyParts[leftSidePartsIndex[1]][0][0][0][5]="roll=90 pitch="..math.random(0,180)
+bodyParts[rightSidePartsIndex[1]][0][0][0][6]="roll=-90 pitch="..math.random(0,180)
+bodyParts[rightSidePartsIndex[1]][0][0][0][8]="rotationaxis=\"1,0,0\" rotationrate=2"
+bodyParts[leftSidePartsIndex[1]][0][0][0][0]=1
+bodyParts[leftSidePartsIndex[1]][0][0][1][0]=1
+bodyParts[leftSidePartsIndex[1]][0][0][-1][0]=1
+bodyParts[leftSidePartsIndex[1]][0][1][0][0]=1
+bodyParts[leftSidePartsIndex[1]][0][1][1][0]=1
+bodyParts[leftSidePartsIndex[1]][0][1][-1][0]=1
+bodyParts[leftSidePartsIndex[1]][0][-1][0][0]=1
+bodyParts[leftSidePartsIndex[1]][0][-1][1][0]=1
+bodyParts[leftSidePartsIndex[1]][0][-1][-1][0]=1
+-- End insert solar panel.
+
+-- End insert side parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Insert the top parts.
+-- If you have no top parts, be sure to set topPartsIndex[0]=false
+topPartsIndex={}
+topPartsIndex[0]=""
+
+-- Insert the CuboidLandingZone.
+topPartsIndex[1]=7
+bodyParts[topPartsIndex[1]][0][0][0][4]="CuboidLandingZone.mesh"
+bodyParts[topPartsIndex[1]][0][0][0][5]="pitch=-90"
+
+bodyParts[topPartsIndex[1]][0][0][0][0]=1
+bodyParts[topPartsIndex[1]][0][0][0][2]="+-"
+bodyParts[topPartsIndex[1]][1][0][0][0]=1
+bodyParts[topPartsIndex[1]][-1][0][0][0]=1
+bodyParts[topPartsIndex[1]][0][0][1][0]=1
+bodyParts[topPartsIndex[1]][1][0][1][0]=1
+bodyParts[topPartsIndex[1]][-1][0][1][0]=1
+bodyParts[topPartsIndex[1]][0][0][2][0]=1
+bodyParts[topPartsIndex[1]][1][0][2][0]=1
+bodyParts[topPartsIndex[1]][-1][0][2][0]=1
+bodyParts[topPartsIndex[1]][0][0][3][0]=1
+bodyParts[topPartsIndex[1]][1][0][3][0]=1
+bodyParts[topPartsIndex[1]][-1][0][3][0]=1
+-- End insert the CuboidLandingZone.
+
+-- Insert the SatelliteDish.
+topPartsIndex[2]=8
+bodyParts[topPartsIndex[2]][0][0][0][4]="satellitedish.mesh"
+bodyParts[topPartsIndex[2]][0][0][0][5]="pitch=-90"
+bodyParts[topPartsIndex[2]][0][0][0][8]="rotationaxis=\"0,1,0\" rotationrate=5"
+
+bodyParts[topPartsIndex[2]][0][0][0][0]=1
+bodyParts[topPartsIndex[2]][0][0][1][0]=1
+bodyParts[topPartsIndex[2]][0][0][-1][0]=1
+bodyParts[topPartsIndex[2]][1][0][0][0]=1
+bodyParts[topPartsIndex[2]][1][0][1][0]=1
+bodyParts[topPartsIndex[2]][1][0][-1][0]=1
+bodyParts[topPartsIndex[2]][-1][0][0][0]=1
+bodyParts[topPartsIndex[2]][-1][0][1][0]=1
+bodyParts[topPartsIndex[2]][-1][0][-1][0]=1
+-- End insert the SatelliteDish.
+
+-- End insert the top parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Insert the connection parts, which are used to connect all the bodyparts.
+-- If you're spacestation has no connection parts, be sure to set connPartsIndex[0]=false.
+connPartsIndex={}
+connPartsIndex[0]=""
+
+-- Insert the CuboidConnection.
+connPartsIndex[1]=9
+bodyParts[connPartsIndex[1]][0][0][0][4]="CuboidConnection.mesh"
+bodyParts[connPartsIndex[1]][0][0][0][5]="roll=90"
+bodyParts[connPartsIndex[1]][0][0][0][6]=""
+bodyParts[connPartsIndex[1]][0][0][0][7]="pitch=90"
+-- End insert the CuboidConnection.
+
+-- End insert the connection parts.
+
+-- End create array bodyParts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Here I define some functions which I will use later.
+
+--This function actualizes the grid, which I have to call always after I have added a new part to the space station.
+function actualizeGrid(Index,x,y,z)
+    for i=math.floor(-pDim/2)+1,math.floor(pDim/2) do
+        for j=math.floor(-pDim/2)+1,math.floor(pDim/2) do
+            for k=math.floor(-pDim/2)+1,math.floor(pDim/2) do
+                if bodyParts[Index][i][j][k][0] == 1 then
+                    for l=0,3 do
+                        grid[x+i][y+j][z+k][l] = bodyParts[Index][i][j][k][l]
+                    end
+                end
+            end
+        end
+    end
+end
+-- End actualizeGrid.
+
+-- This function checks wheter a given parts fits at that position or not.
+-- If the part fits there it returns 1, otherwise 0.
+function checkPart(Index,x,y,z)
+    check=1
+    for i=math.floor(-pDim/2)+1,math.floor(pDim/2) do
+        for j=math.floor(-pDim/2)+1,math.floor(pDim/2) do
+            for k=math.floor(-pDim/2)+1,math.floor(pDim/2) do
+                -- If the part occupies the position (i,j,k), the grid must be empty there ((x+i, y+j, z+k)==0), if not, check is zero,
+                --  which means that the part doesn't fit there.
+                if bodyParts[Index][i][j][k][0] == 1 and grid[x+i][y+j][z+k][0] == 1 then
+                    check=0
+                end
+            end
+        end
+    end
+    return check
+end
+-- End checkPart function.
+
+-- This function prints the model with tempPartIndex in the bodyParts array at position lx,ly,lz.
+-- If you need to rotate the model around his own axis, then you have to set movEntity true and define the details of the rotation in
+--  bodyParts[tempPartIndex][0][0][0][8].
+-- If your model needs to be rotated like bodyParts[tempPartIndex][0][0][0][5], then side must be 1, for bodyParts[tempPartIndex][0][0][0][6] side must be 2,
+--  for bodyParts[tempPartIndex][0][0][0][7] side must be 3.
+function printModel(lx,ly,lz,tempPartIndex,movEntity,side)
+    if movEntity == true then
+        print("<MovableEntity scale=1 position=\"") print(lx*gridDim*sSScale) print(",") print(ly*gridDim*sSScale) print(",") print(lz*gridDim*sSScale) print("\" ")
+        print(bodyParts[tempPartIndex][0][0][0][8]) print(">")
+        print("<attached>")
+        lx=0 ly=0 lz=0
+    end
+
+    print("<Model position=\"") print(lx*gridDim*sSScale) print(",") print(ly*gridDim*sSScale) print(",") print(lz*gridDim*sSScale)
+    print("\" scale=") print(sSScale) print(" mesh= \"") print(bodyParts[tempPartIndex][0][0][0][4]) print("\"")
+
+        if side == 1 then
+            print(bodyParts[tempPartIndex][0][0][0][5]) print(">")
+        elseif side == 2 then
+            print(bodyParts[tempPartIndex][0][0][0][6]) print(">")
+        elseif side == 3 then
+            print(bodyParts[tempPartIndex][0][0][0][7]) print(">")
+        end
+
+        print("<attached>")
+            print(bodyParts[tempPartIndex][0][0][0][9])
+        print("</attached>")
+
+    print("</Model>")
+
+    if movEntity == true then
+        print("</attached>")
+        print("</MovableEntity>")
+    end
+end
+-- End function printModel().
+
+-- This function sets a part to a side of the space station.
+-- The arguments lx,ly,lz are the coordinates of the grid, where you want to set the part.
+-- The arguments xAxis,yAxis,zAxis can be 0 or 1, but only one argument out of the three can be 1. This means two of them must always be zero. You have to set xAxis to one,
+--  if your part is attached to a side, which faces into the x-direction (negative or positive, this is later specified with Dir), that means the x-Axis is a normal vector
+--  of the side to which you want to attach the part. The same for yAxis and zAxis.
+-- The argument Dir must be 1 if your side, where you want to attach the part, faces into the positive direction, -1 if the side faces into the negative direction. The side
+--  faces into the positive direction means, that the side of the side where the part will be attached is directed into the direction of the positive direction of the
+--  corresponding axis.
+-- The argument index is the index of the part for the bodyParts array.
+-- The argument printMovEnt must be false if your part doesn't need to be attached to an extra MovableEntity. If your part must be attached to an extra MovableEntity
+--  this argument must be true. The extra MovableEntity is used to rotate the part around his own axis, or something like that.
+-- The argument printSide is like the argument side of the printModel() function. It defines how your part will be rotated. Read the commentary there.
+-- The function returns 0 if the part couldn't be set, because it did not fit there or there was no side to attach the part. It returns 1 if the part is successfully set.
+function setPart(lx,ly,lz,xAxis,yAxis,zAxis,Dir,index,printMovEnt,printSide)
+
+    partSet=0
+    -- For the bodyParts array I use 1 as x-, 2 as y- and 3 as z-Axis for the definition in which directions a part can have connections.
+    coord=1*xAxis+2*yAxis+3*zAxis
+    -- If I try to attach the part from the positive direction to the side of the space station, the part of the station (where I want to attach the new part) must have
+    --  a connection into the positive direction. Otherwise I look from the negative side and so the part of the station must have a connection into the negative direction.
+    if Dir==1 then
+        conn="+"
+    elseif Dir==-1 then
+        conn="-"
+    end
+    -- I look from the direction defined through Dir, and here I check, whether I have reached a side of the space station, which means at position lx,ly,lz is nothing and
+    --  at the next position is a part which can have a connection into the direction from where I look.
+    if grid[lx][ly][lz][0] == 0 and grid[lx+(-1*xAxis*Dir)][ly+(-1*yAxis*Dir)][lz+(-1*zAxis*Dir)][0] == 1 and (grid[lx+(-1*xAxis*Dir)][ly+(-1*yAxis*Dir)][lz+(-1*zAxis*Dir)][coord]=="+-" or grid[lx+(-1*xAxis*Dir)][ly+(-1*yAxis*Dir)][lz+(-1*zAxis*Dir)][coord]==conn) then
+        -- This checks whether the part fits at that position or not.
+        check=checkPart(index,lx,ly,lz)
+        if check == 1 then
+            -- This prints the part.
+            printModel(lx,ly,lz,index,printMovEnt,printSide)
+            partSet=1
+            -- This actualizes the grid array with the values of the array bodyParts at the position index.
+            actualizeGrid(index,lx,ly,lz)
+        end
+    end
+    return partSet
+end
+-- End function setPart().
+
+-- This function sets a part to a side of the space station. It is called spiralSet, because it starts in the middle of the side and goes out in a form of a spiral.
+-- The argument xAxis,yAxis,zAxis,Dir,printMovEnt,printSide are the same as the arguments from the setPart() function, please read the commentary there.
+-- The argument index here must be an array, where you define the index for your part for the bodyParts array. The first used index is 1 and goes up to parts.
+-- The argument parts is the number of different parts which you want to attach to a side.
+function spiralSet(xAxis,yAxis,zAxis,Dir,index,parts,printMovEnt,printSide)
+    if index[0] ~= false then
+        -- The array vector contains the actual position where you try to set the part. vector[0],vector[1] and vector[3] contains the x,y,z-coordinate.
+        vector={}
+        -- This must be done, because there are different sides from where I try to attach a part.
+        coord1=1*yAxis+2*zAxis
+        coord2=math.mod(coord1+1,3)
+        coord3=math.mod(coord2+1,3)
+
+        for pc=1,parts do
+            tempIndex = index[pc]
+            for eachPart=1,bodyParts[tempIndex][0][0][0][10] do
+                partSet=0
+                vector[coord1]=math.floor(Dir*sSSize/2)-2*Dir
+                while vector[coord1]~=math.floor(-1*Dir*sSSize/2)+2*Dir and partSet==0 do
+                    round=0
+                    while round<=math.floor(sSSize/2)-2 and partSet==0 do
+                        vector[coord2]=round
+                        vector[coord3]=-round
+                        while vector[coord3]<=round and partSet==0 do
+                            partSet=setPart(vector[0],vector[1],vector[2],xAxis,yAxis,zAxis,Dir,tempIndex,printMovEnt,printSide)
+                            vector[coord3]=vector[coord3]+1
+                        end
+                        while vector[coord2]>=-round and partSet==0 do
+                            partSet=setPart(vector[0],vector[1],vector[2],xAxis,yAxis,zAxis,Dir,tempIndex,printMovEnt,printSide)
+                            vector[coord2]=vector[coord2]-1
+                        end
+                        while vector[coord3]>-round and partSet==0 do
+                            partSet=setPart(vector[0],vector[1],vector[2],xAxis,yAxis,zAxis,Dir,tempIndex,printMovEnt,printSide)
+                            vector[coord3]=vector[coord3]-1
+                        end
+                        while vector[coord2]<=round and partSet==0 do
+                            partSet=setPart(vector[0],vector[1],vector[2],xAxis,yAxis,zAxis,Dir,tempIndex,printMovEnt,printSide)
+                            vector[coord2]=vector[coord2]+1
+                        end
+                        round=round+1
+                    end
+                    vector[coord1]=vector[coord1]-Dir
+                end
+            end
+        end
+    end
+end
+-- End function spiralSet().
+
+-- End define functions.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- This is xml code, which means now we attach some parts to the MovableEntity.
+print("<attached>")
+-- End attach to the MovableEntity.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach all bodyparts.
+-- Define at which position in the x-direction you're space station will start.
+x=math.random(-math.floor(xLength/2),-math.floor(xLength/2)+xVar)
+-- Define at which position in the x-direction you're space station will end.
+xMax=math.random(math.floor(xLength/2),math.floor(xLength/2)+xVar)
+while x<xMax do
+    -- The same for the y- and z-direction.
+    y=math.random(-math.floor(yLength/2),-math.floor(yLength/2)+yVar)
+    yMax=math.random(math.floor(yLength/2),math.floor(yLength/2)+yVar)
+    while y<yMax do
+        yMax=math.random(math.floor(yLength/2),math.floor(yLength/2)+yVar)
+        z=math.random(-math.floor(zLength/2),-math.floor(zLength/2)+zVar)
+        zMax=math.random(math.floor(zLength/2),math.floor(zLength/2)+zVar)
+        while z<zMax do
+            -- This loop choses a bodypart, which fits at position (x,y,z).
+            -- If after the fifth time the part does still not fit we terminate the loop and set no part at postition (x,y,z).
+            partSet=0
+            counter=0
+            while counter<5 and partSet==0 do
+                -- This choses randomly a bodyPartIndex, which is the index used for the parts in the array bodyParts.
+                tempBodyPartIndex=math.random(1,sSBodyParts)
+                check=checkPart(tempBodyPartIndex,x,y,z)
+                -- If check == 1, this means that the part fits there, so we put it there and break the while true loop, to go on.
+                if check == 1 then
+                    -- This prints the chosen part at position (x*gridDim*sSScale,y*gridDim*sSScale,z*gridDim*sSScale).
+                    printModel(x,y,z,tempBodyPartIndex,false,1)
+                    -- This actualizes the grid array with the values of the array bodyParts at the position tempBodyPartIndex, which is our randomly chosen part.
+                    actualizeGrid(tempBodyPartIndex,x,y,z)
+                    partSet=1
+                end
+                counter=counter+1
+            end
+            z=z+1
+        end
+        y=y+1
+    end
+    x=x+1
+end
+-- End attach all bodyparts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach backParts, if there are some.
+    spiralSet(0,0,1,1,backPartsIndex,backParts,false,1)
+-- End attach backParts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach frontParts, if there are.
+    spiralSet(0,0,1,-1,frontPartsIndex,frontParts,false,1)
+-- End attach frontParts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach parts on the left side of the space station.
+    spiralSet(1,0,0,-1,leftSidePartsIndex,leftSideParts,true,1)
+-- End attach left side parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach parts on the right side of the space station.
+    spiralSet(1,0,0,1,rightSidePartsIndex,rightSideParts,true,2)
+-- End attach right side parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach parts on top of the space station.
+    spiralSet(0,1,0,1,topPartsIndex,topParts,true,1)
+-- End attach top parts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- Attach all connectionparts.
+-- This iterates through the whole grid array.
+if connPartsIndex[0] ~= false then
+    for x=math.floor(-sSSize/2)+2,math.floor(sSSize/2)-2 do
+        for y=math.floor(-sSSize/2)+2,math.floor(sSSize/2)-2 do
+            for z=math.floor(-sSSize/2)+2,math.floor(sSSize/2)-2 do
+                tempConnPartIndex=connPartsIndex[math.random(1,connParts)]
+                -- This checks whether there has to be a connection part between (x,y,z) and (x+1,y,z) or not. First it checks if there is a part at (x,y,z) and
+                --  then it checks if that part can have a connection into the positive x-direction, if it can, it checks if there is a part at (x+1,y,z) and
+                --  if that part can have a connection into the negative x-direction, if both can, it prints the xml code to set a connection part.
+                if grid[x][y][z][0]==1 and (grid[x][y][z][1]=="+" or grid[x][y][z][1]=="+-") and grid[x+1][y][z][0]==1 and (grid[x+1][y][z][1]=="-" or grid[x+1][y][z][1]=="+-") then
+                    -- This prints the connection part, the +1/2 is because the connection is set exactly in the middle of two gridpoints.
+                    printModel(x+1/2,y,z,tempConnPartIndex,false,1)
+                end
+                -- The same as in the x-direction, but for the y-direction.
+                if grid[x][y][z][0]==1 and ( grid[x][y][z][2]=="+" or grid[x][y][z][2]=="+-" ) and grid[x][y+1][z][0]==1 and ( grid[x][y+1][z][2]=="-" or grid[x][y+1][z][2]=="+-" ) then
+                    printModel(x,y+1/2,z,tempConnPartIndex,false,2)
+                end
+                -- The same as in the x-direction, but for the z-direction.
+                if grid[x][y][z][0]==1 and ( grid[x][y][z][3]=="+" or grid[x][y][z][3]=="+-" ) and grid[x][y][z+1][0]==1 and ( grid[x][y][z+1][3]=="-" or grid[x][y][z+1][3]=="+-" ) then
+                    printModel(x,y,z+1/2,tempConnPartIndex,false,3)
+                end
+            end
+        end
+    end
+end
+-- End attach all connectionparts.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+-- This is xml code, which ends the attachment and the MovableEntity.
+print("</attached>")
+print("</MovableEntity>")
+-- End ends attachment and MovableEntity.
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+end
+-- End createSpaceStationPar() function.
+
+
+
+-- This function is for the lazy guys, which do not care how the space station looks like, so I use some good standard values.
+function createSpaceStation()
+    createSpaceStationPar(0,4,1,2,1,6,1,100)
+end
+-- End createSpaceStaion() function.
+
+
+
Index: /code/branches/RacingBots_FS18/data/levels/includes/HeavyCruiserParts.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/HeavyCruiserParts.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/HeavyCruiserParts.lua	(revision 11817)
@@ -0,0 +1,168 @@
+--[[ place all parts
+places all sub-parts of HeavyCruiser as Pawns
+  posX, posY, posZ - position in space
+  dirX, dirY, dirZ - direction
+  team - team
+--]]
+
+function placeAllSubParts(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placeSidearmL(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placeSidearmLfront(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placeSidearmR(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placeSidearmRfront(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placeFrontL(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placeFrontR(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placePartL(team, posX, posY, posZ, dirX, dirY, dirZ)
+    placePartR(team, posX, posY, posZ, dirX, dirY, dirZ)
+end
+
+
+--[[ place individual parts
+places sub-parts of HeavyCruiser as Pawns
+  posX, posY, posZ - position in space
+  dirX, dirY, dirZ - direction arguments
+  team - team
+--]]
+
+function placeSidearmL(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=300 initialhealth=300 maxhealth=300 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_sidearmL radarname = \"HIDDEN\" >")
+    print("<attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_sidearmL.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"-11,18,102\" halfExtents=\"10,10,10\" info=\"HOOK, sidearmL\"/> <BoxCollisionShape position=\"-151,47,115\" roll=\"15\" halfExtents=\"16,2,105\" info=\"sidearmL, frontTop\"/> <BoxCollisionShape position=\"-136,-7,115\" roll=\"15\" halfExtents=\"16,2,105\" info=\"sidearmL, frontBottom\"/> <BoxCollisionShape position=\"-127,26,115\" roll=\"15\" halfExtents=\"2,28,105\" info=\"sidearmL, frontInner\"/> <BoxCollisionShape position=\"-161,16,115\" roll=\"15\" halfExtents=\"2,28,105\" info=\"sidearmL, frontOuter\"/> <BoxCollisionShape position=\"-145,21,12\" roll=\"15\" halfExtents=\"16,28,2\" info=\"sidearmL, front\"/> <BoxCollisionShape position=\"-140,12,261\" roll=\"15\" halfExtents=\"22,41,43\" info=\"sidearmL, back\"/> <BoxCollisionShape position=\"-133,-13,29\" roll=\"15\" halfExtents=\"12,6,17\" info=\"sidearmL, bottom cylinder\"/> <BoxCollisionShape position=\"-165,-4,31\" roll=\"15\" halfExtents=\"7,21,13\" info=\"sidearmL, box\"/> <BoxCollisionShape position=\"-153,59,96\" roll=\"15\" halfExtents=\"6,7,60\" info=\"sidearmL, upper beam\"/> <BoxCollisionShape position=\"-143,57,119\" roll=\"15\" halfExtents=\"3,4,85\" info=\"sidearmL, upper inner beam\"/> <BoxCollisionShape position=\"-142,53,212\" pitch=\"21\" yaw=\"5\" roll=\"15\" halfExtents=\"3,4,10\" info=\"sidearmL, upper inner beam\"/> <BoxCollisionShape position=\"-160,52,119\" roll=\"15\" halfExtents=\"3,4,85\" info=\"sidearmL, upper outer beam\"/> <BoxCollisionShape position=\"-159,48,212\" pitch=\"21\" yaw=\"5\" roll=\"15\" halfExtents=\"3,4,10\" info=\"sidearmL, upper outer beam\"/> <BoxCollisionShape position=\"-152,54,34\" pitch=\"-46\" yaw=\"-14\" roll=\"15\" halfExtents=\"6,7,10\" info=\"sidearmL, upper beam front\"/> <BoxCollisionShape position=\"-152,54,162\" pitch=\"30\" yaw=\"9\" roll=\"15\" halfExtents=\"6,7,12\" info=\"sidearmL, upper beam back\"/> <BoxCollisionShape position=\"-168,21,119\" roll=\"15\" halfExtents=\"3,5,109\" info=\"sidearmL, outer beam\"/> <BoxCollisionShape position=\"-134,-10,169\" roll=\"15\" halfExtents=\"6,4,55\" info=\"sidearmL, lower beam front\"/> <BoxCollisionShape position=\"-131,-20,217\" pitch=\"-20\" roll=\"15\" yaw=\"-5\" halfExtents=\"6,12,3\" info=\"sidearmL, lower beam middle\"/> <BoxCollisionShape position=\"-130,-29,233\" roll=\"15\" halfExtents=\"6,3,15\" info=\"sidearmL, lower beam back\"/> <BoxCollisionShape position=\"-145,21,71\" halfExtents=\"10,10,1\" info=\"sidearmL, HOOKBOX\"/> <BoxCollisionShape position=\"-145,21,29\" halfExtents=\"10,10,1\" info=\"sidearmL, HOOKBOX\"/> <BoxCollisionShape position=\"-145,32,50\" halfExtents=\"10,1,20\" info=\"sidearmL, HOOKBOX\"/> <BoxCollisionShape position=\"-145,10,50\" halfExtents=\"10,1,20\" info=\"sidearmL, HOOKBOX\"/> <BoxCollisionShape position=\"-156,21,50\" halfExtents=\"1,10,20\" info=\"sidearmL, HOOKBOX\"/> <BoxCollisionShape position=\"-134,21,50\" halfExtents=\"1,10,20\" info=\"sidearmL, HOOKBOX\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placeSidearmLfront(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=100 initialhealth=100 maxhealth=100 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_sidearmLfront radarname = \"HIDDEN\" >")
+    print(" <attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_sidearmLfront.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"-145,21,50\" halfExtents=\"10,10,20\" info=\"sidearmLfront, HOOK\"/> <BoxCollisionShape position=\"-141,15,-53\" roll=\"15\" halfExtents=\"27,44,62\" info=\"sidearmLfront\"/> <BoxCollisionShape position=\"-153,59,-30\" roll=\"15\" halfExtents=\"4,2,38\" info=\"sidearmLfront, top\"/> <BoxCollisionShape position=\"-153,61,-41\" roll=\"15\" halfExtents=\"4,4,11\" info=\"sidearmLfront, top\"/> <BoxCollisionShape position=\"-153,60,-65\" roll=\"15\" halfExtents=\"4,3,4\" info=\"sidearmLfront, top\"/> <BoxCollisionShape position=\"-153,59,-41\" roll=\"15\" halfExtents=\"8,2,11\" info=\"sidearmLfront, top\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placeSidearmR(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=300 initialhealth=300 maxhealth=300 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_sidearmR radarname = \"HIDDEN\" >")
+    print("<attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_sidearmR.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"11,18,102\" halfExtents=\"10,10,10\" info=\"HOOK, sidearmR\"/> <BoxCollisionShape position=\"151,47,115\" roll=\"-15\" halfExtents=\"16,2,105\" info=\"sidearmR, frontTop\"/> <BoxCollisionShape position=\"136,-7,115\" roll=\"-15\" halfExtents=\"16,2,105\" info=\"sidearmR, frontBottom\"/> <BoxCollisionShape position=\"127,26,115\" roll=\"-15\" halfExtents=\"2,28,105\" info=\"sidearmR, frontInner\"/> <BoxCollisionShape position=\"161,16,115\" roll=\"-15\" halfExtents=\"2,28,105\" info=\"sidearmR, frontOuter\"/> <BoxCollisionShape position=\"145,21,12\" roll=\"-15\" halfExtents=\"16,28,2\" info=\"sidearmR, front\"/> <BoxCollisionShape position=\"140,12,261\" roll=\"-15\" halfExtents=\"22,41,43\" info=\"sidearmR, back\"/> <BoxCollisionShape position=\"133,-13,29\" roll=\"-15\" halfExtents=\"12,6,17\" info=\"sidearmR, bottom cylinder\"/> <BoxCollisionShape position=\"165,-4,31\" roll=\"-15\" halfExtents=\"7,21,13\" info=\"sidearmR, box\"/> <BoxCollisionShape position=\"153,59,96\" roll=\"-15\" halfExtents=\"6,7,60\" info=\"sidearmR, upper beam\"/> <BoxCollisionShape position=\"143,57,119\" roll=\"-15\" halfExtents=\"3,4,85\" info=\"sidearmR, upper inner beam\"/> <BoxCollisionShape position=\"142,53,212\" pitch=\"21\" yaw=\"-5\" roll=\"-15\" halfExtents=\"3,4,10\" info=\"sidearmR, upper inner beam\"/> <BoxCollisionShape position=\"160,52,119\" roll=\"-15\" halfExtents=\"3,4,85\" info=\"sidearmR, upper outer beam\"/> <BoxCollisionShape position=\"159,48,212\" pitch=\"21\" yaw=\"-5\" roll=\"-15\" halfExtents=\"3,4,10\" info=\"sidearmR, upper outer beam\"/> <BoxCollisionShape position=\"152,54,34\" pitch=\"-46\" yaw=\"14\" roll=\"-15\" halfExtents=\"6,7,10\" info=\"sidearmR, upper beam front\"/> <BoxCollisionShape position=\"152,54,162\" pitch=\"30\" yaw=\"-9\" roll=\"-15\" halfExtents=\"6,7,12\" info=\"sidearmR, upper beam back\"/> <BoxCollisionShape position=\"168,21,119\" roll=\"-15\" halfExtents=\"3,5,109\" info=\"sidearmR, outer beam\"/> <BoxCollisionShape position=\"134,-10,169\" roll=\"-15\" halfExtents=\"6,4,55\" info=\"sidearmR, lower beam front\"/> <BoxCollisionShape position=\"131,-20,217\" pitch=\"-20\" roll=\"-15\" yaw=\"5\" halfExtents=\"6,12,3\" info=\"sidearmR, lower beam middle\"/> <BoxCollisionShape position=\"130,-29,233\" roll=\"-15\" halfExtents=\"6,3,15\" info=\"sidearmR, lower beam back\"/> <BoxCollisionShape position=\"145,21,71\" halfExtents=\"10,10,1\" info=\"sidearmR, HOOKBOX\"/> <BoxCollisionShape position=\"145,21,29\" halfExtents=\"10,10,1\" info=\"sidearmR, HOOKBOX\"/> <BoxCollisionShape position=\"145,32,50\" halfExtents=\"10,1,20\" info=\"sidearmR, HOOKBOX\"/> <BoxCollisionShape position=\"145,10,50\" halfExtents=\"10,1,20\" info=\"sidearmR, HOOKBOX\"/> <BoxCollisionShape position=\"156,21,50\" halfExtents=\"1,10,20\" info=\"sidearmR, HOOKBOX\"/> <BoxCollisionShape position=\"134,21,50\" halfExtents=\"1,10,20\" info=\"sidearmR, HOOKBOX\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placeSidearmRfront(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=100 initialhealth=100 maxhealth=100 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_sidearmRfront radarname = \"HIDDEN\" >")
+    print("<attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_sidearmRfront.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"145,21,50\" halfExtents=\"10,10,20\" info=\"sidearmRfront, HOOK\"/> <BoxCollisionShape position=\"141,15,-53\" roll=\"-15\" halfExtents=\"27,44,62\" info=\"sidearmRfront\"/> <BoxCollisionShape position=\"153,59,-30\" roll=\"-15\" halfExtents=\"4,2,38\" info=\"sidearmRfront, top\"/> <BoxCollisionShape position=\"153,61,-41\" roll=\"-15\" halfExtents=\"4,4,11\" info=\"sidearmRfront, top\"/> <BoxCollisionShape position=\"153,60,-65\" roll=\"-15\" halfExtents=\"4,3,4\" info=\"sidearmRfront, top\"/> <BoxCollisionShape position=\"153,59,-41\" roll=\"-15\" halfExtents=\"8,2,11\" info=\"sidearmRfront, top\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placeFrontL(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=100 initialhealth=100 maxhealth=100 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_frontL radarname = \"HIDDEN\" >")
+    print(" <attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_frontL.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"-11,18,58\" halfExtents=\"10,10,10\" info=\"HOOK, frontL\"/> <BoxCollisionShape position=\"-80,33,-320\" halfExtents=\"7,11,54\" info=\"frontL\"/> <BoxCollisionShape position=\"-79,31,-399\" halfExtents=\"3,6,26\" info=\"frontL\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placeFrontR(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=100 initialhealth=100 maxhealth=100 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_frontR radarname = \"HIDDEN\" >")
+    print(" <attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_frontR.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"11,18,58\" halfExtents=\"10,10,10\" info=\"HOOK, frontR\"/> <BoxCollisionShape position=\"80,33,-320\" halfExtents=\"7,11,54\" info=\"frontR\"/> <BoxCollisionShape position=\"79,31,-399\" halfExtents=\"3,6,26\" info=\"frontR\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placePartL(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=100 initialhealth=100 maxhealth=100 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_partL radarname = \"HIDDEN\" >")
+    print("<attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_partL.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"-11,18,80\" halfExtents=\"10,10,10\" info=\"HOOK, partL\"/> <BoxCollisionShape position=\"-94,33,-179\" halfExtents=\"11,13,45\" info=\"partL\"/> <BoxCollisionShape position=\"-96,33,-230\" halfExtents=\"13,17,22\" info=\"partL\"/> </collisionShapes>")
+    print("</Pawn>")
+end
+
+
+function placePartR(team, posX, posY, posZ, dirX, dirY, dirZ)
+    print("<Pawn health=100 initialhealth=100 maxhealth=100 ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("direction = \"")
+            print(dirX) print(",")
+            print(dirY) print(",")
+            print(dirZ) print("\" ")
+        print("team = ")
+            print(team) print(" ")
+    print("collisionType=dynamic mass=100 name=HeavyCruiser_partR radarname = \"HIDDEN\" >")
+    print(" <attached> <Model position=\"0,0,0\" direction=\"-1,0,0\" mesh=\"HeavyCruiser_partR.mesh\" scale=\"40\" /> </attached> <collisionShapes> <BoxCollisionShape position=\"11,18,80\" halfExtents=\"10,10,10\" info=\"HOOK, partR\"/> <BoxCollisionShape position=\"94,33,-179\" halfExtents=\"11,13,45\" info=\"partR\"/> <BoxCollisionShape position=\"96,33,-230\" halfExtents=\"13,17,22\" info=\"partR\"/> </collisionShapes>")
+    print("</Pawn>")
+end
Index: /code/branches/RacingBots_FS18/data/levels/includes/MFalconWeapon.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/MFalconWeapon.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/MFalconWeapon.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position="9.5,0,0" />
+      <WeaponSlot position=" 9.5,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="LaserBeam2.mesh" />
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="LaserBeam2.mesh" />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/asteroidField.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/asteroidField.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/asteroidField.lua	(revision 11817)
@@ -0,0 +1,101 @@
+--[[ fog generator
+generates fog
+    posX, posY, posZ - position in space
+    size - size of billboard
+    brightness - [0,1] fog brightness
+--]]
+function generateFog(posX, posY, posZ, size, brightness)
+    print("<Billboard ")
+        print("position = \"")
+            print(posX) print(",")
+            print(posY) print(",")
+            print(posZ) print("\" ")
+        print("colour=\"")
+            print(brightness) print(",")
+            print(brightness) print(",")
+            print(brightness) print("\" ")
+        print("material=\"Smoke/Smoke\" scale=")
+        print(size)
+    print(" />")
+end
+
+--[[ asteroid field generator
+generates asteroid field
+    posX, posY, posZ - position in space
+    minSize, maxSize - size boundaries of each asteroid
+    radius - size of the cube around position in space
+    count - number of asteroids
+    fog - enable fog 0/1
+--]]
+function asteroidField(posX, posY, posZ, minSize, maxSize, radius, count, fog)
+    for i = 1, count, 1 do
+        size = (math.random() * (maxSize - minSize)) + minSize
+        pX = (2 * math.random() * radius) - radius + posX
+        pY = (2 * math.random() * radius) - radius + posY
+        pZ = (2 * math.random() * radius) - radius + posZ
+        print("<StaticEntity ")
+
+        print("position = \"")
+        print(pX) print(",")
+        print(pY) print(",")
+        print(pZ) print("\" ")
+
+        print("scale = \"") print(size) print("\" ")
+
+        print("collisionType = static linearDamping = 0.8 angularDamping = 1 ")
+        print("collisiondamage = 1000 enablecollisiondamage = true>")
+
+        print("<attached>")
+            print("<Model mass=\"") print(size * 10) print("\" ")
+            print("mesh=\"ast") print(math.mod(i,6) + 1) print(".mesh\" />")
+        print("</attached>")
+
+        print("<collisionShapes> ")
+            print("<SphereCollisionShape radius=\"")
+            print(size * 2.5) print("\" />")
+        print("</collisionShapes>")
+
+        print("</StaticEntity>")
+
+        if fog == 1 and i % 5 == 0 then
+            generateFog(pX, pY, pZ, radius*0.04, 0.2)
+        end
+    end
+end
+
+
+--[[ asteroid belt generator
+generates asteroid belt
+    posX, posY, posZ - position in space
+    yaw, pitch - rotation
+    minSize, maxSize - size boundaries of each asteroid
+    radius0, radius1 - inner/outer radius
+    count - number of asteroids
+    fog - enable fog 0/1
+--]]
+function asteroidBelt(centerX, centerY, centerZ, yaw, pitch, segments, minSize, maxSize, radius0, radius1, count, fog)
+    dPhi = (2 * math.pi) / segments
+    width = math.abs(radius1 - radius0)
+    radius = (radius1 + radius0) / 2
+    segmentCount = count / segments
+
+    print("<StaticEntity collisionType=static yaw=") print(yaw)
+    print(" pitch=") print(pitch)
+
+    print(" position = \"")
+        print(centerX) print(",")
+        print(centerY) print(",")
+        print(centerZ) print("\"")
+    print(">")
+
+    print("<attached>")
+
+    for i = 0, segments - 1, 1 do
+        asteroidField((radius * math.cos(i * dPhi)),
+                    (radius * math.sin(i * dPhi)),
+                    0, minSize, maxSize, width, segmentCount, fog)
+    end
+
+    print("</attached>")
+    print("</StaticEntity>")
+end
Index: /code/branches/RacingBots_FS18/data/levels/includes/asteroids2DWeapon.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/asteroids2DWeapon.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/asteroids2DWeapon.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position="-9.2,2,-13" />
+      <WeaponSlot position=" 9.2,2,-13" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <Asteroids2DWeapon mode=0 munitionpershot=0 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="laserbeam.mesh" />
+        </Weapon>
+        <Weapon>
+          <Asteroids2DWeapon mode=0 munitionpershot=0 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="laserbeam.mesh" />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=0.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/invaderWeapon.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/invaderWeapon.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/invaderWeapon.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position="-9.2,2,-13" />
+      <WeaponSlot position=" 9.2,2,-13" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <InvaderWeapon mode=0 munitionpershot=0 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="laserbeam.mesh" />
+        </Weapon>
+        <Weapon>
+          <InvaderWeapon mode=0 munitionpershot=0 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="laserbeam.mesh" />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=0.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/invaderWeaponEnemy.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/invaderWeaponEnemy.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/invaderWeaponEnemy.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position="-9.2,2,-13" />
+      <WeaponSlot position=" 9.2,2,-13" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <InvaderWeaponEnemy mode=0 munitionpershot=0 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="laserbeam.mesh" />
+        </Weapon>
+        <Weapon>
+          <InvaderWeaponEnemy mode=0 munitionpershot=0 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="laserbeam.mesh" />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=0.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/notifications.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/notifications.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/notifications.oxi	(revision 11817)
@@ -0,0 +1,20 @@
+<Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+<NotificationQueueCEGUI
+    name="all"
+    targets="questsystem"
+    displaySize="0.5, 0, 0, 0"
+    position="0, 10, 0.3, 0"
+/>
+
+<NotificationQueueCEGUI
+    name="info"
+    targets="gameinfo"
+    size=1
+    displayTime=-1
+    position="0.2, 0, 0.8, 0"
+    fontSize="24"
+    fontColor="1, 1, 0, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+/>
Index: /code/branches/RacingBots_FS18/data/levels/includes/pickups.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/pickups.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/pickups.oxi	(revision 11817)
@@ -0,0 +1,276 @@
+
+<!-- Shield pickups -->
+
+<PickupRepresentation
+    name = "smallshieldpickup"
+    pickupName = "Small Shield Pickup"
+    pickupDescription = "Gives you a small-sized shield for 30 seconds."
+    inventoryRepresentation = "SmallShield"
+    spawnerTemplate = "smallshieldpickupRepresentation"
+/>
+
+<PickupRepresentation
+    name = "mediumshieldpickup"
+    pickupName = "Medium Shield Pickup"
+    pickupDescription = "Gives you a medium-sized shield for 30 seconds."
+    inventoryRepresentation = "MediumShield"
+    spawnerTemplate = "mediumshieldpickupRepresentation"
+/>
+
+<PickupRepresentation
+    name = "hugeshieldpickup"
+    pickupName = "Huge Shield Pickup"
+    pickupDescription = "Gives you a big shield for 60 seconds."
+    inventoryRepresentation = "HugeShield"
+    spawnerTemplate = "hugeshieldpickupRepresentation"
+/>
+
+<!-- Health pickups -->
+
+<PickupRepresentation
+    name = "smallhealthpickup"
+    pickupName = "Small Health Boost"
+    pickupDescription = "Adds a small amout of health to the ship."
+    inventoryRepresentation = "SmallHealth"
+    spawnerTemplate = "smallhealthpickupRepresentation"
+/>
+
+<PickupRepresentation
+    name = "mediumhealthpickup"
+    pickupName = "Medium Health Boost"
+    pickupDescription = "Adds a medium amout of health to the ship."
+    spawnerTemplate = "mediumhealthpickupRepresentation"
+    inventoryRepresentation = "MediumHealth"
+/>
+
+<PickupRepresentation
+    name = "hugehealthpickup"
+    pickupName = "Huge Health Boost"
+    pickupDescription = "Adds a huge amout of health to the ship."
+    spawnerTemplate = "hugehealthpickupRepresentation"
+    inventoryRepresentation = "HugeHealth"
+/>
+
+<PickupRepresentation
+    name = "crazyhealthpickup"
+    pickupName = "Crazy Madness Health Boost"
+    pickupDescription = "Adds a crazy amout of health to the ship."
+    spawnerTemplate = "crazyhealthpickupRepresentation"
+    inventoryRepresentation = "CrazyMadnessHealth"
+/>
+
+<!-- Meta pickups -->
+
+<PickupRepresentation
+    name = "use"
+    pickupName = "Use Pickup"
+    pickupDescription = "Uses all pickups you have."
+    spawnerTemplate = "usepickupRepresentation"
+    inventoryRepresentation = "usePickup"
+/>
+
+<PickupRepresentation
+    name = "drop"
+    pickupName = "Drop Pickup"
+    pickupDescription = "Drops all pickups you have."
+    spawnerTemplate = "droppickupRepresentation"
+    inventoryRepresentation = "dropPickup"
+/>
+
+<PickupRepresentation
+    name = "destroy"
+    pickupName = "Destroy Pickup"
+    pickupDescription = "Destroy all pickups you have."
+    spawnerTemplate = "destroypickupRepresentation"
+    inventoryRepresentation = "detroyPickup"
+/>
+
+<PickupRepresentation
+    name = "destroycarrier"
+    pickupName = "Destroy Carrier Pickup"
+    pickupDescription = "destroys you."
+    spawnerTemplate = "destroycarrierpickupRepresentation"
+    inventoryRepresentation = "destroyCarrierPickup"
+/>
+
+<!-- Speed pickups -->
+
+<PickupRepresentation
+    name = "smallspeedpickup"
+    pickupName = "Small Speed Boost"
+    pickupDescription = "Multiplies Speed of the Ship by a small amount."
+    spawnerTemplate = "smallspeedpickupRepresentation"
+    inventoryRepresentation = "SmallSpeed"
+/>
+
+<PickupRepresentation
+    name = "mediumspeedpickup"
+    pickupName = "Medium Speed Boost"
+    pickupDescription = "Multiplies Speed of the Ship by a bigger amount."
+    spawnerTemplate = "mediumspeedpickupRepresentation"
+    inventoryRepresentation = "MediumSpeed"
+/>
+
+<PickupRepresentation
+    name = "hugespeedpickup"
+    pickupName = "Huge Speed Boost"
+    pickupDescription = "Multiplies Speed of the Ship by a huge amount."
+    spawnerTemplate = "hugespeedpickupRepresentation"
+    inventoryRepresentation = "HugeSpeed"
+/>
+
+<PickupRepresentation
+    name = "smalljumppickup"
+    pickupName = "Small Jump Boost"
+    pickupDescription = "Boosts the Ship with a massive amount for a very short time."
+    spawnerTemplate = "smalljumppickupRepresentation"
+    inventoryRepresentation = "SmallSpeed"
+/>
+
+<!-- Invisible pickups -->
+
+<PickupRepresentation
+    name = "smallinvisiblepickup"
+    pickupName = "Small Invisibility"
+    pickupDescription = "Makes you invisible for 5 seconds."
+    spawnerTemplate = "smallinvisiblepickupRepresentation"
+    inventoryRepresentation = "SmallInvisible"
+/>
+
+<PickupRepresentation
+    name = "mediuminvisiblepickup"
+    pickupName = "Medium Invisibility"
+    pickupDescription = "Makes you invisible for 10 seconds."
+    spawnerTemplate = "mediuminvisiblepickupRepresentation"
+    inventoryRepresentation = "MediumInvisible"
+/>
+
+<PickupRepresentation
+    name = "hugeinvisiblepickup"
+    pickupName = "Huge Invisibility"
+    pickupDescription = "Makes you invisible for 20 seconds."
+    spawnerTemplate = "hugeinvisiblepickupRepresentation"
+    inventoryRepresentation = "HugeInvisible"
+/>
+
+<!-- Munition pickups -->
+
+<PickupRepresentation
+    name = "smallmunitionpickup"
+    pickupName = "Small munition"
+    pickupDescription = "Gives a small amount of munition."
+    spawnerTemplate = "smallmunitionpickupRepresentation"
+    inventoryRepresentation = "SmallMunition"
+/>
+
+<PickupRepresentation
+    name = "mediummunitionpickup"
+    pickupName = "Medium munition"
+    pickupDescription = "Gives a medium amount of munition."
+    spawnerTemplate = "mediummunitionpickupRepresentation"
+    inventoryRepresentation = "MediumMunition"
+/>
+
+<PickupRepresentation
+    name = "hugemunitionpickup"
+    pickupName = "Huge munition"
+    pickupDescription = "Gives a huge amount of munition."
+    spawnerTemplate = "hugemunitionpickupRepresentation"
+    inventoryRepresentation = "HugeMunition"
+/>
+
+<!-- Pickup Collection pickups -->
+
+<PickupRepresentation
+    name = "triplehealthspeedinvisibilitypickup"
+    pickupName = "Tri Pickup"
+    pickupDescription = "Adds health, speed and invisibility."
+    spawnerTemplate = "triplehealthspeedinvisibilitypickupRepresentation"
+/>
+
+<!-- Drone Pickup -->
+
+<PickupRepresentation
+    name = "dronepickup"
+    pickupName = "Drone Pickup"
+    pickupDescription = "Adds a Drone to the Player's Spaceship"
+    spawnerTemplate = "dronepickupRepresentation"
+/>
+
+<!-- DamageBoost Pickup -->
+
+<PickupRepresentation
+    name = "smalldamageboostpickup"
+    pickupName = "Small DamageBoost Pickup"
+    pickupDescription = "Multiplies the ship damage with 2."
+    spawnerTemplate = "smalldamageboostpickupRepresentation"
+    inventoryRepresentation = "SmallDamageBoost"
+/>
+
+<PickupRepresentation
+    name = "mediumdamageboostpickup"
+    pickupName = "Medium DamageBoost Pickup"
+    pickupDescription = "Multiplies the ship damage with 5."
+    spawnerTemplate = "mediumdamageboostpickupRepresentation"
+    inventoryRepresentation = "MediumDamageBoost"
+/>
+
+<PickupRepresentation
+    name = "hugedamageboostpickup"
+    pickupName = "Huge DamageBoost Pickup"
+    pickupDescription = "Multiplies the ship damage with 7."
+    spawnerTemplate = "hugedamageboostpickupRepresentation"
+    inventoryRepresentation = "HugeDamageBoost"
+/>
+
+<!-- Shrink Pickup -->
+
+<PickupRepresentation
+    name = "smallshrinkpickup"
+    pickupName = "Small Shrink"
+    pickupDescription = "Shrinks the Ship by a bit"
+    spawnerTemplate = "smallshrinkpickupRepresentation"
+    inventoryRepresentation = "SmallShrink"
+/>
+
+<PickupRepresentation
+    name = "mediumshrinkpickup"
+    pickupName = "Medium Shrink"
+    pickupDescription = "Shrinks the Ship"
+    spawnerTemplate = "mediumshrinkpickupRepresentation"
+    inventoryRepresentation = "MediumShrink"
+/>
+
+<PickupRepresentation
+    name = "hugeshrinkpickup"
+    pickupName = "Huge Shrink"
+    pickupDescription = "Shrinks the Ship considerably"
+    spawnerTemplate = "hugeshrinkpickupRepresentation"
+    inventoryRepresentation = "HugeShrink"
+/>
+
+<!-- Boost Pickup -->
+
+<PickupRepresentation
+    name = "smallboostpickup"
+    pickupName = "Small Boost"
+    pickupDescription = "Restores the boost by a bit"
+    spawnerTemplate = "smallboostpickupRepresentation"
+    inventoryRepresentation = "SmallBoost"
+/>
+
+<PickupRepresentation
+    name = "mediumboostpickup"
+    pickupName = "Medium Boost"
+    pickupDescription = "Restores the boost"
+    spawnerTemplate = "mediumboostpickupRepresentation"
+    inventoryRepresentation = "MediumBoost"
+/>
+
+<PickupRepresentation
+    name = "hugeboostpickup"
+    pickupName = "Huge Boost"
+    pickupDescription = "Restores the boost considerably"
+    spawnerTemplate = "hugeboostpickupRepresentation"
+    inventoryRepresentation = "HugeBoost"
+/>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsAssff.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsAssff.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsAssff.oxi	(revision 11817)
@@ -0,0 +1,50 @@
+    <weaponslots>
+      <WeaponSlot position="-15.0,-1.5,0" />
+      <WeaponSlot position=" 15.0,-1.5,0" />
+      <WeaponSlot position="    0,   0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 munitionpershot=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="103" roll="90" yaw="90" position="0,-1.35,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="103" roll="90" yaw="90" position="0.2,-1.35,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-104" yaw="-90" position="0,1.3,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 munitionpershot=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=8 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=2 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsAssff2.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsAssff2.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsAssff2.oxi	(revision 11817)
@@ -0,0 +1,48 @@
+    <weaponslots>
+      <WeaponSlot position="-15.0,-1.5,0" />
+      <WeaponSlot position=" 15.0,-1.5,0" />
+      <WeaponSlot position="    0,   0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets> 
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <attached>
+            <Model mesh="stunweapon.mesh" pitch="180" roll="0" yaw="0" position="-1.9,-.5,1" scale=".5" />
+            <BlinkingBillboard position="-1.9, -.5, -5.5" material="PE/lensflare" colour="0.128, 0.28, 1" amplitude=0.25 frequency=16 quadratic=0 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 healthamage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6,1.3,-2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0 healthdamage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6,1.3,-2.0" />
+          <LightningGun mode=1 munitionpershot=1 muzzleoffset="0,0,0" shielddamage=23 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="stunweapon.mesh" pitch="180" roll="0" yaw="0" position="1.9,-.5,1" scale=".5"/>
+            <BlinkingBillboard position="1.9, -.5, -5.5" material="PE/lensflare" colour="0.128, 0.28, 1" amplitude=0.25 frequency=16 quadratic=0 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0 healthdamage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6,1.3,-2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 healthdamage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1,1.6,-2.0" />
+          <LightningGun mode=1 munitionpershot=1 muzzleoffset="0,0,0" shielddamage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=50 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=100 fuel=10 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsCollateral.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsCollateral.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsCollateral.oxi	(revision 11817)
@@ -0,0 +1,52 @@
+    <weaponslots>
+      <WeaponSlot position="-15.0,-1.5,0" />
+      <WeaponSlot position=" 15.0,-1.5,0" />
+      <WeaponSlot position="    0,   0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+
+        <Weapon>
+          <attached>
+            <!--Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="5,-1.3,0" /--> <!-- ROCKET LAUNCHER -->
+            <!--Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" /--> <!-- THING BETWEEN -->
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="90" yaw="-90" position="-1.5, 1, -0.3" scale=0.6 /> <!-- MACHINE GUN -->
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 munitionpershot=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+
+        <Weapon>
+          <attached>
+            <!--Model mesh="LightningGun.mesh" pitch="103" roll="90" yaw="90" position="0,-1.35,0" /-->
+            <!--Model mesh="LightningGun-s.mesh" pitch="103" roll="90" yaw="90" position="0.2,-1.35,0" /-->
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="90" yaw="-90" position="1.8, 1, -0.3" scale=0.6 /> <!-- MACHINE GUN -->
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsEscort.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsEscort.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsEscort.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position="-9.2,2,-13" />
+      <WeaponSlot position=" 9.2,2,-13" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="LaserBeam2.mesh" />
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="LaserBeam2.mesh" />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsEscortMine.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsEscortMine.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsEscortMine.oxi	(revision 11817)
@@ -0,0 +1,34 @@
+    <weaponslots>
+      <WeaponSlot position="-9.2,2,-13" />
+      <WeaponSlot position=" 9.2,2,-13" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="LaserBeam2.mesh" />
+          <MineGun mode=0 munitionpershot=1 delay=0.125 damage=50 shielddamage=15 healthdamage=10 muzzleoffset=" 0.1, 1.4,-10" maxtimeuntilexplosion=25 timeuntilactivation=2.5/>
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="LaserBeam2.mesh" />
+          <IceGun mode=0 munitionpershot=1 delay=0.125 damage=9.3 muzzleoffset=" 0.1, 1.4,-3" freezefactor=0.5 freezetime=2.0 />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <IceMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+      <MineMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsFPS.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsFPS.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsFPS.oxi	(revision 11817)
@@ -0,0 +1,32 @@
+    <weaponslots>
+      <WeaponSlot position="0,0,0" yaw=0 pitch=0 roll=0 />
+<!--
+      <WeaponSlot position="-0.5,0.8,2.5" yaw=0 pitch=0 roll=0 />
+      <WeaponSlot position="15,-1.5,-25" yaw=0 pitch=0 roll=0 />
+      <WeaponSlot position="0,0,-45" yaw=0 pitch=0 roll=0 />
+-->
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack firemode=0>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=0 delay=0.0 damage=2.5 material="Flares/point_lensflare" muzzleoffset="0.7,-0.3,-3" />
+          <FlameGun mode=1 munitionpershot=1 damage=0.5 muzzleoffset="0.7,-0.3,-3"/>
+          <LightningGun mode=2 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20/>
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=5 replenishamount=1 replenishinterval=7.5/>
+      <FlameMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=20/>
+      <LightningMunition initialmagazines=2 maxmagazines=2 munitionpermagazine=8 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsFS15.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsFS15.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsFS15.oxi	(revision 11817)
@@ -0,0 +1,57 @@
+<weaponslots>
+  <WeaponSlot position=" 0, 0, 0" />
+  <WeaponSlot position=" 0, 0, 0" />
+  <WeaponSlot position=" 0, 0, 0" />
+  <WeaponSlot position=" 0, 0, 0" />
+</weaponslots>
+<weaponsets>
+  <WeaponSet firemode=0 />
+  <WeaponSet firemode=1 />
+  <WeaponSet firemode=2 />
+  <WeaponSet firemode=3 />
+  <WeaponSet firemode=4 />
+</weaponsets>
+<weaponpacks>
+  <WeaponPack>
+    <links>
+      <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+      <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+      <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+      <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+      <DefaultWeaponmodeLink firemode=4 weaponmode=4 />
+    </links>
+    <Weapon>
+      <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -11.4, 0, -5" />
+      <HsW01 mode=0 munitionpershot=0 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -11.4, 0, -5" />
+      <HsW01 mode=0 munitionpershot=0 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 11.4, 0, -5" />
+      <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 11.4, 0, -5" />
+    </Weapon>
+    <Weapon>
+      <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -15, 1.6, -2" />
+      <HsW01 mode=0 munitionpershot=0 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -15, 1.6, -2" />
+      <HsW01 mode=0 munitionpershot=0 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 15, 1.6, -2" />
+      <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 15, 1.6, -2" />
+    </Weapon>
+    <Weapon>
+      <LaserFire mode=1 munitionpershot=0 muzzleoffset="2.2,6,16" damage=30 shielddamage=20 />
+      <LaserFire mode=1 munitionpershot=0 muzzleoffset="-2.2,6,16" damage=30 shielddamage=20 />
+      <GravityBombFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+      <RocketFireOld mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 />
+      <RocketFire mode=4 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+    </Weapon>
+  </WeaponPack>
+  <WeaponPack>
+    <links>
+      <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+    </links>
+    <!--Weapon>
+      <EnergyDrink mode=0 munitionpershot=0 delay=0  material="Flares/point_lensflare"muzzleoffset="2,-0.2,-1" />
+    </Weapon-->
+  </WeaponPack>
+</weaponpacks>
+<munition>
+  <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+  <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+  <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+  <GravityBombMunition initialmagazines=3 maxmagazines=3 munitionpermagazine=1 />
+</munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsGhost.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsGhost.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsGhost.oxi	(revision 11817)
@@ -0,0 +1,41 @@
+    <weaponslots>
+      <WeaponSlot position=" 1.3,4.66,-20" />
+      <WeaponSlot position="-1.3,4.66,-20" />
+      <WeaponSlot position="0,4.66,-20" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 healthdamage=3.14159 delay=0 material="Flares/point_lensflare" />
+          <HsW01 mode=0 munitionpershot=1 healthdamage=3.14159 delay=0.125 material="Flares/point_lensflare" muzzleoffset=" 0.5,0.6,1.7" />
+          <FusionFire mode=1 muzzleoffset="0,0,0" damage=30 shielddamage=10 />
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 damage=3.14159 delay=0  material="Flares/point_lensflare" />
+          <HsW01 mode=0 munitionpershot=1 damage=3.14159 delay=0.125 material="Flares/point_lensflare" muzzleoffset="-0.5,0.6,1.7" />
+          <FusionFire mode=1 muzzleoffset="0,0,0" damage=30 shielddamage=10 />
+        </Weapon>
+        <Weapon>
+          <FlameGun mode=2 munitionpershot=1 damage=0.5 muzzleoffset="0,0,0"/>
+          <SplitGun mode=3 munitionpershot=1 damage=6.0 muzzleoffset="0.5,0.6,1.7" splittime=0.2 numberofsplits=2 numberofchilds=3 spread=0.1 damagereduction=2.0 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <FusionMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <FlameMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=20/>
+      <SplitMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsH2.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsH2.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsH2.oxi	(revision 11817)
@@ -0,0 +1,48 @@
+    <weaponslots>
+      <WeaponSlot position="-7.5, 4, 8.5" />
+      <WeaponSlot position=" 7.5, 4, 8.5" />
+      <WeaponSlot position=" 0.0, 0,-13" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <attached>
+            <Model mesh="hs-w01.mesh"  roll="180" position="0.0, 0.5, 0.0" scale=2 />
+            <Model mesh="hs-w01s.mesh" roll="180" position="0.1, 0.0, 0.0" scale=2 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=2.5 material="Flares/point_lensflare" muzzleoffset=" 0.8, 0.9,-4" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=2.5 material="Flares/point_lensflare" muzzleoffset="-0.8, 0.9,-4" />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="hs-w01.mesh"  roll="180" position=" 0.0, 0.5, 0.0" scale=2 />
+            <Model mesh="hs-w01s.mesh" roll="180" position="-0.1, 0.0, 0.0" scale=2 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=2.5 material="Flares/point_lensflare" muzzleoffset=" 0.8, 0.9, -4.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=2.5 material="Flares/point_lensflare" muzzleoffset="-0.8, 0.9, -4.0" />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh"   pitch="90" roll="90" yaw="90" position="0,  -1.3,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="90" roll="90" yaw="90" position="0.2,-1.3,0" />
+          </attached>
+          <LightningGun mode=0 muzzleoffset="0,0,0" />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=10 maxmagazines=10 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+    </munition>
+
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHXY.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHXY.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHXY.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position=" 6,-2,2" />
+      <WeaponSlot position="-6,-2,2" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=0 damage=2.5 delay=0 material="Flares/point_lensflare" />
+          <HsW01 mode=0 munitionpershot=0 damage=2.5 delay=0.1 material="Flares/point_lensflare" muzzleoffset=" 0.5,0.6,1.7" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20/>
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=0 damage=2.5 delay=0  material="Flares/point_lensflare" />
+          <HsW01 mode=0 munitionpershot=0 damage=2.5 delay=0.1 material="Flares/point_lensflare" muzzleoffset="-0.5,0.6,1.7" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20/>
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=10 maxmagazines=10 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeartAttack.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeartAttack.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeartAttack.oxi	(revision 11817)
@@ -0,0 +1,48 @@
+    <weaponslots>
+      <WeaponSlot position=" 0, 0, 0" />
+      <WeaponSlot position=" 0, 0, 0" />
+      <WeaponSlot position=" 0, 0, 0" />
+      <WeaponSlot position=" 0, 0, 0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -11.4, 0, -5" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -11.4, 0, -5" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 11.4, 0, -5" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 11.4, 0, -5" />
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -15, 1.6, -2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" -15, 1.6, -2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 15, 1.6, -2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 15, 1.6, -2" />
+        </Weapon>
+        <Weapon>
+          <LaserFire mode=1 munitionpershot=1 muzzleoffset="2.2,6,16" damage=30 shielddamage=20 />
+          <LaserFire mode=1 munitionpershot=1 muzzleoffset="-2.2,6,16" damage=30 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+          <GravityBombFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=20 maxmagazines=20 munitionpermagazine=10 replenishamount=1 replenishinterval=6.0/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=1 />
+      <GravityBombMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeavyCruiser.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeavyCruiser.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeavyCruiser.oxi	(revision 11817)
@@ -0,0 +1,50 @@
+    <weaponslots>
+      <WeaponSlot position="79,30,-420" />
+      <WeaponSlot position="-79,30,-420" />  
+      <WeaponSlot position="-60,30,-370" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,-10" />
+            <Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,-10" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,-10.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=12 maxmagazines=12 munitionpermagazine=10 replenishamount=1 replenishinterval=5.0/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeavyCruiserBody.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeavyCruiserBody.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHeavyCruiserBody.oxi	(revision 11817)
@@ -0,0 +1,52 @@
+    <weaponslots>
+      <WeaponSlot position="79,30,-450" /> <!-- z value should be -420, increased to avoid destroying front parts-->
+      <WeaponSlot position="-79,30,-450" />  
+      <WeaponSlot position="-60,30,-370" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <attached>
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+        <!--Weapon>
+          <EnergyDrink mode=0 munitionpershot=0 delay=0  material="Flares/point_lensflare"muzzleoffset="2,-0.2,-1" />
+        </Weapon-->
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=12 maxmagazines=12 munitionpermagazine=10 replenishamount=1 replenishinterval=7.0/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHover.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHover.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsHover.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+<weaponslots>
+  <WeaponSlot position="-3,2,-3" />
+  <WeaponSlot position=" 3,2,-3" />
+</weaponslots>
+<weaponsets>
+  <WeaponSet firemode=0 />
+  <WeaponSet firemode=1 />
+</weaponsets>
+<weaponpacks>
+  <WeaponPack>
+    <links>
+      <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+      <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+    </links>
+    <Weapon>
+      <IceGun mode=0 munitionpershot=0 delay=0.125 damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" projectileMesh="LaserBeam2.mesh" />
+    </Weapon>
+    <Weapon>
+      <IceGun mode=0 munitionpershot=0 delay=0     damage=9.3 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" projectileMesh="LaserBeam2.mesh" />
+    </Weapon>
+  </WeaponPack>
+  <WeaponPack>
+    <links>
+      <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+    </links>
+  </WeaponPack>
+</weaponpacks>  
+<munition>
+  <IceMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+</munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsImmTest.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsImmTest.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsImmTest.oxi	(revision 11817)
@@ -0,0 +1,62 @@
+    <weaponslots>
+      <WeaponSlot position="-15.0,-1.5,0" />
+      <WeaponSlot position=" 15.0,-1.5,0" />
+      <WeaponSlot position="    0,   0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+            <!-- HsW01 is the standard Weapon, 4 slots => 4 Projectiles spawned at one click -->
+            <!-- LightningGun is the spiral weapon, 2 slots -->
+            <!-- SimpleRocket is the target-following rocket -->
+            <!-- Rocket is the player-guided rocket -->
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,0" />
+            <!--Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" /-->
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=0 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" shielddamage=5 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="103" roll="90" yaw="90" position="0,-1.35,0" />
+            <!--Model mesh="LightningGun-s.mesh" pitch="103" roll="90" yaw="90" position="0.2,-1.35,0" /-->
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-104" yaw="-90" position="0,1.3,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=0 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" healthdamage=0 shielddamage=500 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" shielddamage=50 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" healthdamage=80 shielddamage=20 fuel=10 />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+        <!--Weapon>
+          <EnergyDrink mode=0 munitionpershot=0 delay=0  material="Flares/point_lensflare"muzzleoffset="2,-0.2,-1" />
+        </Weapon-->
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=12 maxmagazines=12 munitionpermagazine=10 replenishamount=1 replenishinterval=7.0/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsPirate.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsPirate.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsPirate.oxi	(revision 11817)
@@ -0,0 +1,27 @@
+    <weaponslots>
+      <WeaponSlot position=" 4.3,-6,-10" />
+      <WeaponSlot position="-4.3,-6,-10" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=2.5 material="Flares/point_lensflare" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=2.5 material="Flares/point_lensflare" muzzleoffset=" 0.5,0.6,1.7" />
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=2.5 material="Flares/point_lensflare" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=2.5 material="Flares/point_lensflare" muzzleoffset="-0.5,0.6,1.7" />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=12 maxmagazines=12 munitionpermagazine=10 replenishamount=1 replenishinterval=7.0/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsRing.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsRing.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsRing.oxi	(revision 11817)
@@ -0,0 +1,35 @@
+    <weaponslots>
+      <WeaponSlot position="11,0,-7" />
+      <WeaponSlot position="-11,0,-7" />
+      <WeaponSlot position="0,0,-7" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+        </links>
+        <Weapon>
+          <LaserFire mode=0 munitionpershot=1 damage=10 shielddamage=5 />
+          <IceGun mode=1 munitionpershot=1 delay=0.125 damage=9.3 muzzleoffset="11,0,-3" freezefactor=0.5 freezetime=2.0 />
+        </Weapon>
+        <Weapon>
+          <LaserFire mode=0 munitionpershot=1 damage=10 shielddamage=5 />
+          <IceGun mode=1 munitionpershot=1 delay=0.125 damage=9.3 muzzleoffset=" -11,0,-3" freezefactor=0.5 freezetime=2.0 />
+        </Weapon>
+        <Weapon>
+          <GravityBombFire mode=2 munitionpershot=1 delay=0.125 damage=3 muzzleoffset="0,0,-7"/>
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=12 maxmagazines=12 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <GravityBombMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=1 />
+      <IceMunition initialmagazines=16 maxmagazines=16 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsSpacecruiser.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsSpacecruiser.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsSpacecruiser.oxi	(revision 11817)
@@ -0,0 +1,94 @@
+    <weaponslots>
+      <WeaponSlot position="-20,10,2" />
+      <WeaponSlot position=" 20,10,2" />
+      <WeaponSlot position="  0,18,0" />
+      <WeaponSlot position="-14,-6,-74" />
+      <WeaponSlot position=" 14,-6,-74" />
+      <WeaponSlot position="-34,-5,-59" />
+      <WeaponSlot position=" 34,-5,-59" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="103" roll="90" yaw="90" position="0,-1.35,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="103" roll="90" yaw="90" position="0.2,-1.35,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-104" yaw="-90" position="0,1.3,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="103" roll="90" yaw="90" position="0,-1.35,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="103" roll="90" yaw="90" position="0.2,-1.35,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-104" yaw="-90" position="0,1.3,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="100" roll="90" yaw="90" position="0,-1.3,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="78" roll="90" yaw="90" position="0.2,-1.3,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-76" yaw="-90" position="-1.5,1,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+            <Model mesh="LightningGun.mesh" pitch="103" roll="90" yaw="90" position="0,-1.35,0" />
+            <Model mesh="LightningGun-s.mesh" pitch="103" roll="90" yaw="90" position="0.2,-1.35,0" />
+            <Model mesh="hs-w01_reduced.mesh" roll="90" pitch="-104" yaw="-90" position="0,1.3,0.3" scale=0.6 />
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=20 maxmagazines=20 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsSwallow.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsSwallow.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsSwallow.oxi	(revision 11817)
@@ -0,0 +1,29 @@
+    <weaponslots>
+      <WeaponSlot position=" 8,1.66,-17.5" />
+      <WeaponSlot position="-8,1.66,-17.5" />
+      <WeaponSlot position="0,1.66,-17.5" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <SplitGun mode=0 munitionpershot=1 damage=6.0 muzzleoffset="0.5,0.6,1.7" splittime=0.2 numberofsplits=2 numberofchilds=3 spread=0.1 damagereduction=2.0 />
+          <LaserFire mode=1 munitionpershot=1 damage=10.0 muzzleoffset="0.5,0.6,1.7" />
+        </Weapon>
+        <Weapon>
+          <SplitGun mode=0 munitionpershot=1 damage=6.0 muzzleoffset="-0.5,0.6,1.7" splittime=0.2 numberofsplits=2 numberofchilds=3 spread=0.1 damagereduction=2.0 />
+          <LaserFire mode=1 munitionpershot=1 damage=10.0 muzzleoffset="-0.5,0.6,1.7" />
+        </Weapon>       
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=20 maxmagazines=20 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <SplitMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTransporter.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTransporter.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTransporter.oxi	(revision 11817)
@@ -0,0 +1,30 @@
+    <weaponslots>
+      <WeaponSlot position=" 55,-10,20" />
+      <WeaponSlot position="-55,-10,20" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.1   damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0"   damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=1 delay=0.1   damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0"   damage=3.14159 shielddamage=20 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=20 maxmagazines=20 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTurret.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTurret.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTurret.oxi	(revision 11817)
@@ -0,0 +1,25 @@
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <!-- <attached>
+            <Model mesh="sphere.mesh" position="1.7,1.7,-24.5" scale=0.6 />
+          </attached> -->
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=1 material="Flares/point_lensflare" muzzleoffset="1.7, 1.7,-30" />
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=1 material="Flares/point_lensflare" muzzleoffset="1.7, -1.7,-30" />
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=1 material="Flares/point_lensflare" muzzleoffset="-1.7, 1.7,-30" />
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=1 material="Flares/point_lensflare" muzzleoffset="-1.7, -1.7,-30" />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTurret1.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTurret1.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsTurret1.oxi	(revision 11817)
@@ -0,0 +1,25 @@
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <!-- <attached>
+            <Model mesh="sphere.mesh" position="1.7,1.7,-24.5" scale=0.6 />
+          </attached> -->
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=20 material="Flares/point_lensflare" muzzleoffset="1.7, 1.7,-30" />
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=20 material="Flares/point_lensflare" muzzleoffset="1.7, -1.7,-30" />
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=20 material="Flares/point_lensflare" muzzleoffset="-1.7, 1.7,-30" />
+          <HsW01 mode=0 munitionpershot=0 delay=0 damage=20 material="Flares/point_lensflare" muzzleoffset="-1.7, -1.7,-30" />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=8 maxmagazines=8 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsbigship.oxi
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsbigship.oxi	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/includes/weaponSettingsbigship.oxi	(revision 11817)
@@ -0,0 +1,53 @@
+    <weaponslots>
+      <WeaponSlot position="-1.5,-5,-3" />
+      <WeaponSlot position=" 1.5,-5,-3" />  
+      <WeaponSlot position="    0,   0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+      <WeaponSet firemode=1 />
+      <WeaponSet firemode=2 />
+      <WeaponSet firemode=3 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+          <DefaultWeaponmodeLink firemode=1 weaponmode=1 />
+          <DefaultWeaponmodeLink firemode=2 weaponmode=2 />
+          <DefaultWeaponmodeLink firemode=3 weaponmode=3 />
+        </links>
+        <Weapon>
+          <attached>
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 0.1, 1.6,-2" />
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-1.6, 1.3,-2" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=3.14159 shielddamage=20 />
+        </Weapon>
+        <Weapon>
+          <attached>
+           
+          </attached>
+          <HsW01 mode=0 munitionpershot=1 delay=0     damage=3.14159 material="Flares/point_lensflare" muzzleoffset=" 1.6, 1.3, -2.0" />
+          <HsW01 mode=0 munitionpershot=1 delay=0.125 damage=3.14159 material="Flares/point_lensflare" muzzleoffset="-0.1, 1.6, -2.0" />
+          <LightningGun mode=1 muzzleoffset="0,0,0" damage=23 />
+        </Weapon>
+        <Weapon>
+          <SimpleRocketFire mode=2 muzzleoffset="0,0,0" damage=30 shielddamage=20 />
+          <RocketFire mode=3 muzzleoffset="0,0,0" damage=30 healthdamage=50 shielddamage=20 fuel=10 />
+        </Weapon>
+      </WeaponPack>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=1 weaponmode=0 />
+        </links>
+        <!--Weapon>
+          <EnergyDrink mode=0 munitionpershot=0 delay=0  material="Flares/point_lensflare"muzzleoffset="2,-0.2,-1" />
+        </Weapon-->
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=12 maxmagazines=12 munitionpermagazine=10 replenishamount=1 replenishinterval=7.5/>
+      <LightningMunition initialmagazines=4 maxmagazines=4 munitionpermagazine=8 />
+      <RocketMunition initialmagazines=5 maxmagazines=5 munitionpermagazine=1 />
+    </munition>
Index: /code/branches/RacingBots_FS18/data/levels/jump.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/jump.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/jump.oxw	(revision 11817)
@@ -0,0 +1,263 @@
+<LevelInfo
+ name = "Jump"
+ description = "Jump as high as you can. Use the mouse to guide the jumper."
+ tags = "minigame"
+ screenshot = "jump.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")  
+  include("jumpHUD.oxo")
+  include("stats.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<Template name=jumpfigurecameras defaults=0>
+  <JumpFigure>
+    <camerapositions>
+      <CameraPosition position="0,-150,0" absolute=true mouselook=false drag=false lookat="0,0,0"/>
+    </camerapositions>
+  </JumpFigure>
+</Template>
+
+<Template name=figureLeftHand defaults=0>
+  <Model position="4.0,0.0,5.0" mesh="JumpFigureLeftHand.mesh" scale=1 pitch=90>
+  </Model>
+</Template>
+
+<Template name=figureRightHand defaults=0>
+  <Model position="-4.0,0.0,5.0" mesh="JumpFigureRightHand.mesh" scale=1 pitch=90>
+  </Model>
+</Template>
+
+<Template name=jumpFigureTemplate>
+  <JumpFigure camerapositiontemplate=jumpfigurecameras mouseFactor="100.0" modelLefthand=figureLeftHand  modelRighthand=figureRightHand rocketPos=10.0 propellerPos=10.0 bootsPos=-5.2 jumpSpeed=250.0 handMinAngle=-20 handMaxAngle=75 handSpeed=250 rocketSpeed=250.0 propellerSpeed=150.0>
+    <attached>
+      <Model position="0,0,0" mesh="JumpFigure.mesh" scale=1 pitch=90/>
+    </attached>
+  </JumpFigure>
+</Template>
+
+<Template name=jumpProjectileTemplate>
+  <JumpProjectile>
+    <attached>
+      <Model mesh="JumpProjectile.mesh" scale=1  pitch=90/>
+      <ParticleEmitter scale=1 pitch=0 roll=0 position="0, 0, 0" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=0.0 />
+    </attached>
+  </JumpProjectile>
+</Template>
+
+<Template name=jumpPlatformStaticTemplate>
+  <JumpPlatformStatic height=3 width=19>
+    <attached>
+      <Model mesh="JumpPlatform01.mesh" scale=1  pitch=90/>
+      <Backlight scale=0.2 colour="0.9, 0.4, 0.0" width=7 length=500 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" loop=1 />
+    </attached>
+  </JumpPlatformStatic>
+</Template>
+
+<Template name=jumpPlatformHMoveTemplate>
+  <JumpPlatformHMove height=3 width=19>
+    <attached>
+      <Model mesh="JumpPlatform02.mesh" scale=1  pitch=90/>
+      <Backlight scale=0.2 colour="0.1, 0.1, 1.0" width=7 length=500 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" loop=1 />
+    </attached>
+  </JumpPlatformHMove>
+</Template>
+
+<Template name=jumpPlatformVMoveTemplate>
+  <JumpPlatformVMove height=3 width=19>
+    <attached>
+      <Model mesh="JumpPlatform03.mesh" scale=1  pitch=90/>
+      <Backlight scale=0.2 colour="1.0, 0.1, 1.0" width=7 length=500 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" loop=1 />
+    </attached>
+  </JumpPlatformVMove>
+</Template>
+
+<Template name=jumpPlatformDisappearTemplate>
+  <JumpPlatformDisappear height=3 width=19>
+    <attached>
+      <Model mesh="JumpPlatform04.mesh" scale=1  pitch=90/>
+      <Backlight scale=0.2 colour="0.1, 1.0, 0.1" width=7 length=500 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" loop=1 />
+    </attached>
+  </JumpPlatformDisappear>
+</Template>
+
+<Template name=jumpPlatformTimerTemplate>
+  <JumpPlatformTimer height=3 width=19 effectPath="Orxonox/BigExplosion1part2" effectStartTime="0.4">
+    <attached>
+      <Model mesh="JumpPlatform05.mesh" scale=1  pitch=90/>
+      <ParticleEmitter scaled3D="5.0, 1.0, 2.0" pitch=0 roll=0 position="-4, 0, -2.0" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=0.0 />
+      <ParticleEmitter scaled3D="5.0, 1.0, 2.0" pitch=0 roll=0 position="0, 0, -2.0" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=0.0 />
+      <ParticleEmitter scaled3D="5.0, 1.0, 2.0" pitch=0 roll=0 position="4, 0, -2.0" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=0.0 />      
+    </attached>
+  </JumpPlatformTimer>
+</Template>
+
+<Template name=jumpPlatformFakeTemplate>
+  <JumpPlatformFake height=3 width=19>
+    <attached>
+      <Model mesh="JumpPlatform06.mesh" scale=1  pitch=90/>
+      <ParticleEmitter scale3D="0.2,0.2,0.2" pitch=0 roll=0 position="0, 0, -2.5" source="Orxonox/sparks" lifetime=1.0 loop=1 startdelay=0.0 />
+    </attached>
+  </JumpPlatformFake>
+</Template>
+
+<Template name=jumpEnemy1Template>
+  <JumpEnemy height=7 width=18>
+    <attached>
+      <Model mesh="JumpEnemy1.mesh" scale=1  pitch=90/>
+      <FadingBillboard active=true scale=0.09 position="0, 0, 10" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <Backlight scale=0.33 name=bltest position="0, 0, -10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />            
+    </attached>
+  </JumpEnemy>
+</Template>
+
+<Template name=jumpEnemy2Template>
+  <JumpEnemy height=8 width=20>
+    <attached>
+      <Model mesh="JumpEnemy2.mesh" scale=1  pitch=90/>
+      <MovableEntity position="-17, 0, 4" rotationaxis="0, 1, 0" rotationrate=500 >
+        <attached>
+          <Model mesh="JumpEnemy2Wing.mesh" scale=1 pitch=90/>
+        </attached>
+      </MovableEntity>      
+      <MovableEntity position="17, 0, 4" rotationaxis="0, 1, 0" rotationrate=500 >
+        <attached>
+          <Model mesh="JumpEnemy2Wing.mesh" scale=1 pitch=90/>
+        </attached>
+      </MovableEntity> 
+      <ParticleEmitter scale3D="1.0,1.0,1.0" pitch=0 roll=0 position="-1, 0, -3" source="Orxonox/laser" lifetime=1.0 loop=1 startdelay=0.0 />
+    </attached>
+  </JumpEnemy>
+</Template>
+
+<Template name=jumpEnemy3Template>
+  <JumpEnemy height=8.2 width=11.2>
+    <attached>
+      <Model mesh="JumpEnemy3.mesh" scale=1  pitch=90/>
+      <Backlight scale3D="0.1, 0.1, 1.0" position="0, -11, -4" colour="1.0, 0.0, 0.9, 1.0" width=1 length=1 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1"/>
+      <Backlight scale3D="0.1, 0.1, 1.0" position="6.32, 5.5, -4" colour="1.0, 0.0, 0.9, 1.0" width=1 length=1 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1"/>
+      <Backlight scale3D="0.1, 0.1, 1.0" position="-6.32, 5.5, -4" colour="1.0, 0.0, 0.9, 1.0" width=1 length=1 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1"/>            
+    </attached>
+  </JumpEnemy>
+</Template>
+
+<Template name=jumpEnemy4Template>
+  <JumpEnemy height=7.5 width=21.5 rotationaxis="0, 0, 1" rotationrate=40 >
+    <attached>
+      <Model mesh="JumpEnemy4.mesh" scale=1  pitch=90/>
+    </attached>
+  </JumpEnemy>
+</Template>
+
+<Template name=jumpSpringTemplate>
+  <JumpSpring height=6 width=9.25>
+    <attached>
+      <Model mesh="JumpSpring.mesh" scale=1  rotationaxis="0, 0, 1" pitch=90 position="0.0, 0.0, 0.0"/>
+    </attached>
+  </JumpSpring>
+</Template>
+
+<Template name=jumpRocketTemplate>
+  <JumpRocket height=8.5 width=13.5>
+    <attached>
+      <Model mesh="JumpRocket.mesh" scale=1  pitch=90 position="0.0, 0.0, 1.0"/>
+    </attached>
+  </JumpRocket>
+</Template>
+
+<Template name=jumpPropellerTemplate>
+  <JumpPropeller height=4 width=15.5>
+    <attached>
+      <Model mesh="JumpPropeller.mesh" scale=1  pitch=90 position="0.0, 0.0, 1.0"/>
+    </attached>
+  </JumpPropeller>
+</Template>
+
+<Template name=jumpBootsTemplate>
+  <JumpBoots height=5.2 width=3.5>
+    <attached>
+      <Model mesh="JumpBoots.mesh" scale=1  pitch=90 position="0.0, 0.0, 1.0"/>
+    </attached>
+  </JumpBoots>
+</Template>
+
+<Template name=jumpShieldTemplate>
+  <JumpShield height=1.55 width=15.5>
+    <attached>
+      <Model mesh="JumpShield.mesh" scale=1 pitch=90 position="0.0, 0.0, 1.0"/>
+    </attached>
+  </JumpShield>
+</Template>
+
+<Level
+ plugins = "jump"
+ gametype = "Jump"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <WorldAmbientSound source="Ganymede.ogg" looping="true" playOnLoad="true"/>
+  <JumpBot />
+
+  <Scene ambientlight="1.0, 1.0, 1.0" skybox="Orxonox/skyBoxBasic">
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="991.729, -110.11, 435.404" orientation="0.534038, 0.563456, 0.212168, 0.593553" />
+
+    <MovableEntity>
+      <attached>
+        <JumpCenterpoint
+          name=jumpcenter
+          dimension="120,80"
+          sectionLength="150"
+          platformSpeed="20"
+          cameraOffset="10"
+
+          platformStaticTemplate=jumpPlatformStaticTemplate
+          platformHMoveTemplate=jumpPlatformHMoveTemplate
+          platformVMoveTemplate=jumpPlatformVMoveTemplate
+          platformDisappearTemplate=jumpPlatformDisappearTemplate
+          platformTimerTemplate=jumpPlatformTimerTemplate
+          platformFakeTemplate=jumpPlatformFakeTemplate          
+          figureTemplate=jumpFigureTemplate
+          projectileTemplate=jumpProjectileTemplate
+          springTemplate=jumpSpringTemplate
+          rocketTemplate=jumpRocketTemplate
+          propellerTemplate=jumpPropellerTemplate
+          bootsTemplate=jumpBootsTemplate
+          shieldTemplate=jumpShieldTemplate
+          enemy1Template=jumpEnemy1Template
+          enemy2Template=jumpEnemy2Template
+          enemy3Template=jumpEnemy3Template
+          enemy4Template=jumpEnemy4Template
+          >
+
+          <attached>
+
+            <Model position="0,0,-1000" mesh="JumpPlatform01.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpPlatform02.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpPlatform03.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpPlatform04.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpPlatform05.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpPlatform06.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpProjectile.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpEnemy1.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpEnemy2.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpEnemy3.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpEnemy4.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpSpring.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpRocket.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpPropeller.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpBoots.mesh" scale="1" />
+            <Model position="0,0,-1000" mesh="JumpShield.mesh" scale="1" />
+          </attached>
+        </JumpCenterpoint>
+      </attached>
+    </MovableEntity>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/kecks.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/kecks.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/kecks.oxw	(revision 11817)
@@ -0,0 +1,456 @@
+<LevelInfo
+ name = "kecks"
+ description = "Save your planet."
+ tags = "test"
+ screenshot = "kecks.png"
+ gametype=Mission
+/>
+
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+
+?>
+
+<?lua
+    dofile("includes/asteroidField.lua")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipHXY.oxt")
+?>
+
+<Level gametype = "Mission">
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+<?lua include("includes/notifications.oxi") ?>
+
+<NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=3.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+<Scene
+	ambientlight = "0.8, 0.8, 0.8"
+	skybox       = "Orxonox/skyBoxBasic"
+>
+<!-- TODO: Trigger fuer Boxen, SimpleNotification, Gegner sollen nicht explodieren, Spawnpoint 2 -->
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <SpawnPoint roll="180" position="0,0, 0" lookat="0, 1000, 0" spawnclass=SpaceShip pawndesign=spaceshipHXY team=0 active="true" />
+
+<!-- 2. Spawnpoint
+	<SpawnPoint roll="180" position="0, 114500, 0" lookat="0, 150000, 0" spawnclass=SpaceShip pawndesign=spaceshipHXY team=0 active="false" />	
+		<events>
+               <activity>
+                   <EventListener event="atPortal1" />
+               </activity>
+           </events>
+       </SpawnPoint>
+-->
+<DistanceTrigger name="startmission" position="0,100,0" target="SpaceShip" targetname="spaceshipHXY"  distance=90 activations=1 stayActive=true />
+
+	<SimpleNotification message="Follow the spaceships to escape" boadcast="true">
+		<events>
+			  <trigger>
+				  <EventListener event="startmission" />
+			  </trigger>
+		  </events>
+	</SimpleNotification>
+
+<SimpleNotification message="Destroy the box to free the spaceships." boadcast="true">
+	<events>
+		  <trigger>
+			  <EventListener event="atPortal1" />
+		  </trigger>
+	  </events>
+</SimpleNotification>
+
+	<SimpleNotification message="Defend your planet." broadcast="true">
+		<events>
+			  <trigger>
+				  <EventListener event="boxDestroyed" />
+			  </trigger>
+		  </events>
+	</SimpleNotification>
+
+
+	<!-- Distance Trigger-->
+	
+	<DistanceTrigger name="atPortal1" position="0,112000,0" target="SpaceShip" targetname="spaceshipHXY" distance=100 activations=1 stayActive=true />
+	<EventTrigger name="boxtrigger" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="boxDestroyed" />
+              </trigger>
+            </events>
+          </EventTrigger>
+
+    <!--Asteroiden-Guertel Versuch Schlaufe
+    <?lua
+    	for i = 1, 3, 1
+    		do
+    ?>
+
+     asteroidBelt(0, 0, 0, 0, 0, 100, 50+10*i, 100+10*i, 3000*i+500, 3000*i, 100+100*i	, 0)
+
+	<?lua
+	end
+	?>
+    -->
+ 
+    
+    <!-- Asteroidenguertel-->
+    <?lua
+	asteroidBelt(0, 0, 0, 0, 0, 50, 60, 110, 3300, 3000, 100	, 1)
+	asteroidBelt(0, 0, 0, 0, 0, 50, 70, 120, 6400, 6000, 125	, 1)
+	asteroidBelt(0, 0, 0, 0, 0, 50, 80, 130, 9500, 9000, 150	, 1)
+	?>
+    <!--ENDE Asteroidenguertel-->
+
+	<!-- Beschuetzer und Wegweiser Innen-->		 
+				
+	<?lua
+			for i = 0, (3*math.pi/2), (math.pi/2)
+				  do       
+	?>
+				
+				
+	
+	<SpaceShip position="<?lua print(250*math.sin(i)) ?>, <?lua print(250*math.cos(i)) ?>,0" lookat="<?lua print(1500*math.sin(i)) ?>,  <?lua print(1500*math.cos(i)) ?>,0" maxhealt="150" initialhealth="150" roll="<?lua print(180-i*180/math.pi)?>"  >
+		<templates>
+		  <Template link=spaceshipassff2 /> <!--spaceshipTransporter -->
+		</templates>
+		  <controller>
+			 <WaypointPatrolController alertnessradius=1500 active=true team=0>
+			   <waypoints>
+				 <StaticEntity position="0,10350,0"/>
+			   </waypoints>
+			 </WaypointPatrolController>
+		  </controller>
+	</SpaceShip>
+		  
+				  
+	<?lua
+	end
+	?>
+				  
+	<!-- ENDE Beschuetzer und Wegweiser Innen-->	
+	
+	<!-- Gegner Innen-->		
+	
+	 <?lua
+			for i = 0, (3*math.pi/2), (math.pi/2)
+				  do
+	?>
+				  
+				  
+	<SpaceShip position="<?lua print(1500*math.sin(i)) ?>,<?lua print(1500*math.cos(i)) ?>,0" roll="<?lua print(180-i*180/math.pi)?>" lookat="0, 0, 0">
+	
+	  <templates>
+		  <Template link=spaceshippirate />
+	  </templates>
+		  <controller>
+		<WaypointPatrolController alertnessradius=1500 active=true team=1>
+		  <waypoints>
+			<StaticEntity position="0,0,0"/>
+		  </waypoints>
+		</WaypointPatrolController>
+		  </controller>
+	</SpaceShip>
+								  
+	<?lua
+	end
+	?>
+				  
+	<!-- ENDE Gegner Innen-->
+				 
+	<!-- Gegnerische Patrouille -->	
+			  
+	<?lua
+		for i = 0, (7*math.pi/4), (math.pi/4)
+			do
+	?>
+	
+		 <?lua
+			for j = 1, 3, 1
+			   do
+		 ?>
+			<SpaceShip position="<?lua print((600+3200*j)*math.sin(i)) ?>,<?lua print((600+3200*j)*math.cos(i)) ?>,0" roll="<?lua print(180-i*180/math.pi)?>" lookat="0, 0, 0" >
+	
+			   <templates>
+			   <Template link=spaceshippirate />
+			   </templates>
+				<controller>
+			   <WaypointPatrolController alertnessradius=1500 active=true team=1>
+			   <waypoints>
+					   <?lua
+						 for k = 0, (29*math.pi/15), (math.pi/15)
+							   do 
+						?>  
+				   
+						   <Model mesh="cube.mesh" scale=0 position="<?lua print((600+3200*j)*math.sin(i+k)) ?>,<?lua print((600+3200*j)*math.cos(i+k)) ?>,0" />
+	
+					   <?lua	
+						end
+						?>
+									
+			   </waypoints>
+				</WaypointPatrolController>
+			   </controller>
+			</SpaceShip>
+		<?lua
+		end
+		?>
+	<?lua
+	end
+	?>
+	
+	<!-- ENDE Gegnerische Patrouille -->							   
+							   
+	<!-- Gegnerische Flotte/ Totenkopfflotte-->						   
+	
+	<?lua
+		for j = 0, 1, 1
+			do
+	?>
+		<?lua
+			for i = 0, 4, 1
+				do
+		?>
+		<SpaceShip position="<?lua print (50*i-100)?>, 120000 ,<?lua print (-200*j+150)?>" roll="180" lookat="0, 0, 0">
+		  <templates>
+			  <Template link=spaceshippirate />
+		  </templates>
+			  <controller>
+			<WaypointPatrolController alertnessradius=1000 active=false team=1>
+			  <waypoints>
+				<StaticEntity position="<?lua print (5000*i-10000)?>, 0 ,<?lua print (-20000*j+15000)?>"/>
+			  </waypoints>
+				 <events>
+					  <activity>
+						  <EventListener event="atPortal1" />
+					  </activity>
+				  </events>
+			</WaypointPatrolController>
+			  </controller>
+		</SpaceShip>			
+		<?lua
+		end
+		?>
+	<?lua
+	end
+	?>
+				
+	<?lua
+		for j = 0, 1, 1
+			do
+	?>
+		<?lua
+				for i = 0, 6, 1
+					do
+		?>
+			<SpaceShip position="<?lua print (50*i-150)?>, 120000 ,<?lua print (100-100*j)?>" roll="180" lookat="0, 0, 0">
+			  <templates>
+				  <Template link=spaceshippirate />
+			  </templates>
+				  <controller>
+				<WaypointPatrolController alertnessradius=1250 active=false team=1>
+				  <waypoints>
+					<StaticEntity position="<?lua print (5000*i-15000)?>, 0 ,<?lua print (10000-10000*j)?>"/>
+				  </waypoints>
+					 <events>
+					  <activity>
+						  <EventListener event="atPortal1" />
+					  </activity>
+				  </events>
+				</WaypointPatrolController>
+				  </controller>
+			</SpaceShip>			
+		<?lua
+		end
+		?>
+	<?lua
+	end
+	?>
+	
+	<?lua
+		for i = 0, 6, 3
+			do
+	?>
+			<SpaceShip position="<?lua print (50*i-150)?>, 120000 ,50" roll="180" lookat="0, 0, 0">
+			  <templates>
+				  <Template link=spaceshippirate />
+			  </templates>
+				  <controller>
+				<WaypointPatrolController alertnessradius=1500 active=false team=1>
+				  <waypoints>
+					<StaticEntity position="<?lua print (5000*i-15000)?>, 0 ,5000"/>
+				  </waypoints>
+			 <events>
+				  <activity>
+					  <EventListener event="atPortal1" />
+				  </activity>
+			  </events>
+				</WaypointPatrolController>
+				  </controller>
+			</SpaceShip>			
+	<?lua
+	end
+	?>
+			
+		
+	<?lua
+		for i = 1, 5, 2
+			do
+	?>
+			
+		<SpaceShip position="<?lua print (50*i-150)?>, 120000 ,-100" roll="180" lookat="0, 0, 0">
+		  <templates>
+			  <Template link=spaceshippirate />
+		  </templates>
+			  <controller>
+			<WaypointPatrolController alertnessradius=1000 active=false team=1>
+			  <waypoints>
+				<StaticEntity position="<?lua print (5000*i-15000)?>, 0 ,-10000"/>
+			  </waypoints>
+			 <events>
+				  <activity>
+					  <EventListener event="atPortal1" />
+				  </activity>
+			  </events>
+			</WaypointPatrolController>
+			  </controller>
+		</SpaceShip>
+			
+	<?lua
+	end
+	?>
+			
+	<!-- ENDE Gegnerische Flotte/ Totenkopfflotte-->	
+	
+	<!-- Boxen um Flotte zu befreien -->
+
+
+			<Pawn health=20 position="0, 112900, 0" direction="0,-1,0" name="boxDestroyed" collisionType=dynamic mass=100000  radarname = "Gravitation Box" explosionchunks=0 >
+				<attached>
+					<Model position="0,0,0" scale="10" mesh="CuboidBody.mesh"  />
+				</attached>
+				<collisionShapes>
+					<BoxCollisionShape position="0,0,0" halfExtents="5,5,5" />
+				</collisionShapes>
+				<controller>
+					<WaypointController team=1>
+					</WaypointController>
+				</controller>
+				<explosion >
+            		<ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            		<ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            		<ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        		</explosion>
+			 </Pawn>
+
+	
+	<!-- Flotte Erde-->
+	<?lua
+			for j = 0, 2, 1
+				  do       
+	?>
+		<?lua
+			for i = 0, 2, 1
+				  do       
+		?>
+				
+
+			<SpaceShip position="<?lua print(50-i*50) ?>, 113000,<?lua print(50-j*50) ?>" lookat="0,150000,0" maxhealt="200" initialhealth="200" >
+				<templates>
+				  <Template link=spaceshipassff2 /> <!--spaceshipTransporter -->
+				</templates>
+				  <controller>
+					 <WaypointPatrolController alertnessradius=5000 active=false team=0>
+					   <waypoints>
+						 <StaticEntity position="<?lua print(200-i*200) ?>,113000,<?lua print(400-j*400) ?>"/>
+					   </waypoints>
+				  <events>
+					  <activity>
+						  <EventListener event="boxtrigger" />
+					  </activity>
+				  </events>
+					 </WaypointPatrolController>
+				  </controller>
+			</SpaceShip>  
+   
+					
+		<?lua
+		end
+		?>
+				  
+	<?lua
+	end
+	?>
+					  
+	<!-- ENDE Flotte Erde-->
+			
+	<!--Portal-->
+		<Template name=PortalDefault>
+			<PortalEndPoint>
+				<attached>
+					<Model mesh="Spacegate.mesh" />
+				</attached>
+			</PortalEndPoint>
+		</Template>
+	
+		<PortalEndPoint position="0,112000,0" id="1" pitch="90" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0"/>
+		<PortalEndPoint position="0,10350,0" id="2"  pitch="90" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0"/>
+		<PortalLink fromID="1" toID="2" />
+		<PortalLink fromID="2" toID="1" />
+	<!--ENDE Portal-->
+	   
+	<!--Heimatplanet-->
+		<Planet
+		  position="0,100000,0"
+		  scale="10000"
+		  collisionType="dynamic"
+		  linearDamping="0.8"
+		  angularDamping="0"
+		  mass="5000000"
+		  pitch="180"
+		  yaw="0"
+		  roll="0"
+		  mesh="planets/earth.mesh"
+		  atmosphere="atmosphere1"
+		  rotationaxis="0,0,1"
+		  rotationrate="5.0"
+		  atmospheresize="80.0f"
+		  imagesize="1024.0f"
+		  collisiondamage = 1
+		  enablecollisiondamage = true
+		  >
+		  <attached>
+			  <ForceField position="0,0,0" mode="sphere" diameter="1000" velocity="-500" />
+			</attached>
+			<collisionShapes>
+			  <SphereCollisionShape radius="10000" position="0,0,0" />
+			</collisionShapes>
+		  </Planet>	 
+	<!--ENDE Heimatplanet-->	
+
+  </Scene>
+						   
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/lastManStanding.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/lastManStanding.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/lastManStanding.oxw	(revision 11817)
@@ -0,0 +1,149 @@
+<LevelInfo
+ name = "Last Man Standing"
+ description = "Be the sole survivor."
+ tags = "gametype"
+ screenshot = "lastmanstanding.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("lastManStandingHUD.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level
+ gametype = "LastManStanding"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+    
+    <WorldAmbientSound source="Nebula_metal.ogg" looping="true" playOnLoad="true" />
+
+<!----- Spawnpoints
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-1150,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint team=0 position="1150,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint team=0 position="-700,0,700" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint team=0 position="700,0,-700" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint team=0 position="0,0,-1150" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint team=0 position="0,0,1150" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff /> ----->
+<Bot />
+
+<!-- ------------ middle asteroid -------------- -->
+    <StaticEntity position="0,0,0" collisionType=static>
+        <attached>
+            <MovableEntity position="0,20,0" rotationrate="-4.5" rotationaxis="0,1,0" >
+                <attached>
+                    <Model position="0,0,0" scale=140 mesh="asteroid_UV.mesh" shadow=true />
+                    <Model position="-160,40,28.4" scale=1 mesh="sphere.mesh" /><!--EasterEgg indicator-->
+                    <PickupSpawner pickup=hugeinvisiblepickup position="-160,40,17" triggerDistance="20" respawnTime="5" maxSpawnedItems="15" /><!--EasterEgg : invisible pickup is hidden inside the asteroid -->
+                </attached>
+            </MovableEntity>
+        </attached>
+        <collisionShapes>
+            <SphereCollisionShape radius="145" />
+        </collisionShapes>
+    </StaticEntity>
+
+
+<!-- ---------------asteroid dome----------------- -->
+<?lua
+max = 16
+for i = 0, max, 1
+do
+    y = math.sin(i/max*6)*750
+    z = math.cos(i/max*6)*750
+    j = 1
+    ?>
+
+    <SpawnPoint team=0 position="<?lua print(y*1.4+z*0.2) ?>,0,<?lua print(z*1.4-y*0.2) ?>" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <StaticEntity position="<?lua print(y) ?>,0,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="<?lua print(j * 2) ?>,100,<?lua print(j * 2) ?>" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,100,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i+3,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,200,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i*5,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,-100,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i*13+1,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,-200,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i*17,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+<!-- ---------Top Asteroid----------- -->
+    <StaticEntity position="<?lua print(y) ?>,300,<?lua print(z) ?>" scale="<?lua print(j * 2.1) ?>" pitch="90" roll="180" yaw="<?lua print(-90+i*360/max) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=25 mesh="ast6.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="50,140,30" position="0,0,0"/>
+      </collisionShapes>
+    </StaticEntity>
+
+<!-- top explosion, this is instantiated here so it does not load all resources
+     later when the first kill happens. Far away since we don't want to see it -->
+     <BigExplosion position="1e12,0,0" visible=false >
+     </BigExplosion>
+
+
+
+<?lua end ?><!-- ---------------asteroid dome END------------------->
+
+  </Scene>
+</Level>
+
+
Index: /code/branches/RacingBots_FS18/data/levels/lastTeamStanding.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/lastTeamStanding.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/lastTeamStanding.oxw	(revision 11817)
@@ -0,0 +1,137 @@
+<LevelInfo
+ name = "Last Team Standing"
+ description = "Survive as a team."
+ tags = "gametype"
+ screenshot = "lastteamstanding.png"
+/>
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("lastTeamStandingHUD.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level
+ name         = "Last Team Standing"
+ description  = "testmap for gametype last team standing"
+ gametype     =  "LastTeamStanding"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxBasic"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+    
+    <WorldAmbientSound source="Nebula_metal.ogg" looping="true" playOnLoad="true" />
+
+<Bot />
+
+<!-- ------------ middle asteroid -------------- -->
+    <StaticEntity position="0,20,0" collisionType=static>
+       <attached>
+           <Model position="0,0,0" scale=140 mesh="asteroid_UV.mesh" shadow=true />
+           <!-- ParticleEmitter position="0,0,0" source="Orxonox/Steam" / -->
+       </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="145" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <PickupSpawner pickup=hugeinvisiblepickup position="-160,60,17" triggerDistance="20" respawnTime="5" maxSpawnedItems="10" /><!--EasterEgg-->
+    <StaticEntity position="-160,60,28.4"><!--EasterEgg-Indicator-->
+      <attached>
+        <Model position="0,0,0" scale=1 mesh="sphere.mesh" />
+      </attached>
+    </StaticEntity>
+
+<!-- ---------------asteroid dome----------------- -->
+<?lua
+max = 16
+for i = 0, max, 1
+do
+    y = math.sin(i/max*6)*750
+    z = math.cos(i/max*6)*750
+    j = 1
+    ?>
+
+    <TeamSpawnPoint team="<?lua print( math.mod(i,4)) ?>" position="<?lua print(y*1.4+z*0.2) ?>,0,<?lua print(z*1.4-y*0.2) ?>" direction="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <StaticEntity position="<?lua print(y) ?>,0,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="<?lua print(j * 2) ?>,100,<?lua print(j * 2) ?>" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,100,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i+3,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,200,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i*5,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,-100,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i*13+1,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="<?lua print(y) ?>,-200,<?lua print(z) ?>" scale="<?lua print(j * 2) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=15 mesh="ast<?lua print( math.mod(i*17,6) + 1) ?>.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="45,100,45" position = "0,0,0" />
+      </collisionShapes>
+    </StaticEntity>
+
+<!-- ---------Top Asteroid----------- -->
+    <StaticEntity position="<?lua print(y) ?>,300,<?lua print(z) ?>" scale="<?lua print(j * 2.1) ?>" pitch="90" roll="180" yaw="<?lua print(-90+i*360/max) ?>" collisionType=static >
+      <attached>
+        <Model position="0,0,0" scale=25 mesh="ast6.mesh">
+        </Model>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape    halfExtents="50,140,30" position="0,0,0"/>
+      </collisionShapes>
+    </StaticEntity>
+
+
+<?lua end ?>
+
+  </Scene>
+</Level>
+
+
Index: /code/branches/RacingBots_FS18/data/levels/lastTeamStandingII.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/lastTeamStandingII.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/lastTeamStandingII.oxw	(revision 11817)
@@ -0,0 +1,420 @@
+<LevelInfo
+ name = "Last Team Standing II"
+ description = "Last Team Standing in an abstract level."
+ screenshot = "onthefly.png"
+ tags = "gametype"
+/>
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("lastTeamStandingHUD.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level
+ gametype     = "LastTeamStanding"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxBasic"
+  >
+  <WorldAmbientSound source="Nebula_metal.ogg" looping="true" playOnLoad="true" />
+  
+<!-- TODO:
+1. make collisionshapes bulletproof: -> attach movable entity with dynamic collisionshape within a static collisionshape 
+2. add forcefields -> there should be several "streams" through the level
+3. add teamspawnpoints (different spaceships?) (where should the spawnpoints be placed?)
+-->
+<!--Bot / -->
+
+<!-------------------- Box: TopLayer + BottomLayer + 4 invisible Walls --------------------->
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,-400,0" mesh="cube_orange.mesh" scale3D="1000,10,1000" />
+           <Model position="0,-420,0" mesh="cube_orange.mesh" scale3D="1000,10,1000" /><!-- Second Model in order to avoid graphic errors-->
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,-400,0" halfExtents="1500,10,1500" />
+       </collisionShapes>
+   </StaticEntity>
+
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,400,0" mesh="cube_orange.mesh" scale3D="1000,10,1000" />
+           <Model position="0,420,0" mesh="cube_orange.mesh" scale3D="1000,10,1000" />
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,400,0" halfExtents="1000,10,1000" />
+       </collisionShapes>
+   </StaticEntity>
+
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <!--Model position="1000,0,0" mesh="cube_green.mesh" scale3D="10,400,1000" /-->
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="1000,0,0" halfExtents="10,400,1000" />
+       </collisionShapes>
+   </StaticEntity>
+
+
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <!-- Model position="-1000,0,0" mesh="cube_green.mesh" scale3D="10,400,1000" / -->
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="-1000,0,0" halfExtents="10,400,1000" />
+       </collisionShapes>
+   </StaticEntity>
+
+
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,0,1000" mesh="cube_green.mesh" scale3D="1000,400,10" />
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,0,1000" halfExtents="1000,400,10" />
+       </collisionShapes>
+   </StaticEntity>
+
+
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,0,-1000" mesh="cube_green.mesh" scale3D="1000,400,10" />
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,0,-1000" halfExtents="1000,400,10" />
+       </collisionShapes>
+   </StaticEntity>
+<!-- END of CUBE-->
+
+<!-------------- Centered Thin Gate -------------->
+
+   <StaticEntity position="0,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,-1200,0" mesh="hs-w01.mesh" scale3D="300,400,900" pitch="90" roll="0" yaw="0"/>
+           <!--Model position="121,0,-80" mesh="cube.mesh" scale3D="18,400,18" />
+           <Model position="-121,0,-80" mesh="cube.mesh" scale3D="18,400,18" /-->
+           <Model position="0,0,-80" scale=150 mesh="sphere.mesh" />
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="121,0,-80" halfExtents="18,400,18" />
+           <BoxCollisionShape position="-121,0,-80" halfExtents="18,400,18" />
+           <SphereCollisionShape position="0,0,-80" radius="150" />
+       </collisionShapes>
+   </StaticEntity>
+
+   <ForceField position="0,270,-80" direction="-3,-4,-3" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="0,270,-80" direction="-3,-4,-3">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- to bulk gate, left -->
+   <ForceField position="0,-275,-80" direction="3,0,2" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="0,-275,-80" direction="3,0,2">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+
+
+<!-------------- Bulk Gate -------------->
+   <StaticEntity position="300,0,500" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,-100,0" mesh="hs-w01.mesh" scale3D="500,400,600" pitch="270" roll="0" yaw="0"/>
+           <!--Model position="205,-105,20" mesh="cube.mesh" scale3D="135,280,60" />
+           <Model position="-205,-105,20" mesh="cube.mesh" scale3D="135,280,60" />
+           <Model position="0,235,0" mesh="cube.mesh" scale3D="180,35,35" />
+           <Model position="0,-344,-18" mesh="cube.mesh" scale3D="210,38,36" /-->
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="205,-105,20" halfExtents="135,280,60" />
+           <BoxCollisionShape position="-205,-105,20" halfExtents="135,280,60" />
+           <BoxCollisionShape position="0,235,0" halfExtents="180,35,35" />
+           <BoxCollisionShape position="0,-344,-18" halfExtents="210,38,36" />
+       </collisionShapes>
+   </StaticEntity>
+<!-- back to thin gate -->
+   <ForceField position="300,0,650" direction="1,1.5,-4" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="300,0,650" direction="1,1.5,-4">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- to thin gate -->
+   <ForceField position="300,300,500" direction="-1,0,-2" diameter=100 velocity=1500 length=900 />
+   <MovableEntity position="300,300,500" direction="-1,0,-2">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream -->
+   <ForceField position="830,-300,830" direction="-1,0,0" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="830,-300,830" direction="-1,0,0">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0,0" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.5,0,0" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream II-->
+   <ForceField position="830,350,830" direction="0,0,-1" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="830,350,830" direction="0,0,-1">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0,0,0.5" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0,0,0.5" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+
+
+<!-------------- Bar -------------->
+   <StaticEntity position="-495,0,-495" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,0,0" mesh="CuboidBody.mesh" scale3D="20,720,20" pitch="90" roll="45" yaw="0"/>
+           <!--Model position="0,0,0" mesh="cube.mesh" scale3D="19,719,19" pitch="90" roll="45" yaw="0"/-->
+       </attached>
+
+       <collisionShapes>
+           <BoxCollisionShape position="0,0,0" halfExtents="20,720,20" pitch="90" roll="45" yaw="0"/>
+       </collisionShapes>
+   </StaticEntity>
+<!-- "lift" -->
+   <ForceField position="-700,-300,-700" direction="0,1,0" diameter=100 velocity=2000 length=400 />
+   <MovableEntity position="-700,-300,-700" direction="0,1,0">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- to thin gate, low -->
+   <ForceField position="0,60,-830" direction="0,-1,2" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="0,60,-830" direction="0,-1,2">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream -->
+   <ForceField position="-830,-350,-830" direction="2,0,0" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="-830,-350,-830" direction="2,0,0">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0,0" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.5,0,0" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream II-->
+   <ForceField position="-870,350,-830" direction="0,0,1" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="-870,350,-830" direction="0,0,1">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0,0,0.5" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0,0,0.5" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+
+<!-------------- 2 Side-Bars -------------->
+   <StaticEntity position="0,0,-1000" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,0,0" mesh="CuboidBody.mesh" scale3D="20,405,20" pitch="0" roll="10" yaw="0"/>
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,0,0" halfExtents="20,400,20" pitch="0" roll="0" yaw="0"/>
+       </collisionShapes>
+   </StaticEntity>
+   <StaticEntity position="-1000,0,0" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,0,0" mesh="CuboidBody.mesh" scale3D="20,405,20" pitch="7" roll="0" yaw="0"/>
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,0,0" halfExtents="20,400,20" pitch="0" roll="0" yaw="0"/>
+       </collisionShapes>
+   </StaticEntity>
+<!-- to solar panels -->
+   <ForceField position="-850,-300,-200" direction="1,0,2" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="-850,-300,-200" direction="1,0,2">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- along the bar -->
+   <ForceField position="-900,50,-100" direction="1,0,-1" diameter=150 velocity=2000 length=900 />
+   <MovableEntity position="-900,50,-100" direction="1,0,-1">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+
+<!-------------- 3 Solar Panels --------------->
+
+<?lua
+for i = 1, 3, 1
+do
+    x = i/4*1000
+    z = i/4*500
+?>
+   <StaticEntity position="<?lua print(-1000+x) ?>,-310,<?lua print(z) ?>" direction="0,0,0" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,0,0" mesh="SolarPanel.mesh" scale3D="60,80,30" pitch="0" roll="0" yaw="120"/>
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="0,300,0" halfExtents="155,460,3" pitch="0" roll="0" yaw="120"/>
+       </collisionShapes>
+   </StaticEntity>
+<?lua end ?>
+
+   <ForceField position="-600,100,400" direction="0,-1,-3" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="-600,100,400" direction="0,-1,-3">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream -->
+   <ForceField position="-830,-100,830" direction="0,0,-1" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="-830,-100,830" direction="0,0,-1">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0,0" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.5,0,0" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream II -->
+   <ForceField position="-830,350,830" direction="1,0,0" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="-830,350,830" direction="1,0,0">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0,0,0.5" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0,0,0.5" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- along the panels -->
+   <ForceField position="-830,250,250" direction="3,0,2" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="-830,250,250" direction="3,0,2">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+
+<!-------------- Thin Gate -------------->
+
+   <StaticEntity position="500,0,-500" direction="1,0,-1" collisionType=static mass=100000 >
+       <attached>
+           <Model position="0,-1200,0" mesh="hs-w01.mesh" scale3D="300,400,900" pitch="90" roll="0" yaw="0"/>
+           <Model position="0,100,-80" scale=150 mesh="sphere.mesh" />
+       </attached>
+       <collisionShapes>
+           <BoxCollisionShape position="121,0,-80" halfExtents="18,400,18" />
+           <BoxCollisionShape position="-121,0,-80" halfExtents="18,400,18" />
+           <SphereCollisionShape position="0,100,-80" radius="150" />
+       </collisionShapes>
+   </StaticEntity>
+<!-- to thin gate middle -->
+   <ForceField position="550,350,-550" direction="-3.3,0,3" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="550,350,-550" direction="-3.3,0,3">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- across the field -->
+   <ForceField position="550,-350,-550" direction="-3,0,1" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="550,-350,-550" direction="-3,0,1">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream -->
+   <ForceField position="830,-350,-830" direction="0,0,1" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="830,-350,-830" direction="0,0,1">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0,0" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.5,0,0" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+<!-- alternative stream II -->
+   <ForceField position="830,350,-830" direction="-1,0,0" diameter=100 velocity=2000 length=900 />
+   <MovableEntity position="830,350,-830" direction="-1,0,0">
+       <attached>
+           <Billboard position="0,0,0" material="Flares/ringflare2" colour="0,0,0.5" scale=1/>
+           <?lua for i=0,4,1 do ?>
+               <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0,0,0.5" scale=1/>
+           <?lua end ?>
+       </attached>
+   </MovableEntity>
+
+<!---------------- Spawnpoints ------------------>
+    <TeamSpawnPoint team=0 position="845,350,-835" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=0 position="845,-350,-835" direction="0,0,1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=0 position="835,350,-845" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=0 position="835,-350,-845" direction="0,0,1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <TeamSpawnPoint team=1 position="-845,350,835" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=1 position="-845,-100,835" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=1 position="-835,350,845" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=1 position="-835,-100,845" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <TeamSpawnPoint team=2 position="-870,350,-835" direction="0,0,1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=2 position="-840,-350,-835" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=2 position="-865,350,-840" direction="0,0,1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=2 position="-835,-350,-840" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <TeamSpawnPoint team=3 position="835,350,845" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=3 position="835,-300,845" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=3 position="845,350,835" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=3 position="845,-300,835" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+<Bot /><!-- at least one bot is needed to stat the game properly. Else the game finishes. This could be avoided, if the menue allows a preselection of the number of players. --> 
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/levelTry.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/levelTry.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/levelTry.oxw	(revision 11817)
@@ -0,0 +1,179 @@
+<!-- First levelFile of mkronig and samuezu. It was copied from dockingToASpaceStation.oxw and modified a little bit -->
+<LevelInfo
+ name = "levelTry"
+ description = "Docking into a spacestation."
+ tags = "showcase"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/bigship.oxt")
+  include("templates/spaceshipTurret.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+  include("templates/FPS.oxt")
+?>
+
+<Level
+  gametype = Deathmatch
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+    gravity      = "0,0,0"
+    hasPhysics   = true
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0,1.0,1.0,0.5" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="3200,0,0" lookat="2800,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+    <!--
+    <StaticEntity position  = "2800,0,0" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" />
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" />
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 />
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 />
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </StaticEntity>
+    -->
+
+
+    <Billboard position="2500,0,0" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=10 />
+    <DistanceTrigger position="2500,0,0" distance="200" target="Pawn"
+      beaconMode="exclude" targetname="bcnDestroyer" name="takeControl"
+    />
+
+    <StaticEntity position  = "2000,500,2000" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=10 />
+      </attached>
+    </StaticEntity>
+
+    <StaticEntity position  = "-1000,3000,-1000" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=80 />
+      </attached>
+    </StaticEntity>
+
+
+
+
+<!-- ControllerDirector waits for the event takeControl to attach a new Controller -->
+    <ControllerDirector position="0,0,0">
+        <events>
+            <takeControl>
+                <EventListener event="takeControl" />
+            </takeControl>
+        </events>
+    </ControllerDirector>
+
+<!-- FPS Player as destination of the dock -->
+<FpsPlayer template = "fps" radarname = "First Person Player" position = "0,-19900,0" >
+      <attached>
+        <DockingTarget name="spaceShip" />
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+      </attached>
+</FpsPlayer>
+
+
+<!-- Cube as test SpaceStation
+
+The station can either be hidden outside of the skybox, within the hull of the space station if it is big enough or within a planet.
+Complex spacestations can be placed very far away from the spaceship so it is rendered at low resolution while the player uses the space ship.
+
+-->
+  <StaticEntity position="0,-20000,0" direction="0,-1,0" collisionType=static mass=100000 friction=0.01 >
+      <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="80,80,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="400,400,25" />
+      </collisionShapes>
+  </StaticEntity>
+
+<!-- Homogenous gravitationfield to simulate local gravity (activating the normal gravity will affect the spaceship terribly) -->
+<ForceField position="0,-20000,0" mode="homogen" diameter="2000" forcedirection = "0,-500,0" />
+
+
+<!-- Some more stuff -->
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+    <Planet
+      position="15000,0,-1000"
+      scale="5000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/ganymede.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="5000,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+  </Scene>
+
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/maxim.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/maxim.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/maxim.oxw	(revision 11817)
@@ -0,0 +1,130 @@
+<!-- -->
+
+<LevelInfo
+ name = "Maxim's Test"
+ description = "Intelligent Formation"
+ tags = "test"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/spaceshipTransporter.oxt")
+?>
+
+<Level
+ gametype = "Mission"
+>                  
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+  
+  <WorldAmbientSound source="Nebula_metal.ogg" looping="true" playOnLoad="true" />
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=3.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+  >
+
+  <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+  <TeamSpawnPoint team=0 position="800,700,600" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipswallow/>
+
+  <!-- TRIGGERS -->
+    <DistanceTrigger name="FormationInit" position="800,700,600"  target="Pawn" distance=60 stayActive="true" delay=0.1 />
+    <DistanceTrigger name="LetsGo"        position="200,-200,1000" target="Pawn" distance=180 stayActive="true" delay=0.1 />
+    <BlinkingBillboard colour="1,1,0.05" position="200,-200,1000" frequency=0.6 amplitude=3 material="Flares/lensflare" />
+	<DistanceTrigger name="Fight"        position="-600,3000,-2000" target="Pawn" distance=180 stayActive="true" delay=0.1 />
+    <BlinkingBillboard colour="0,0,1" position="-600,3000,-2000" frequency=0.6 amplitude=3 material="Flares/lensflare" />
+
+
+
+    <Script code="formationcontroller formationflight true" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=FormationInit />
+            </trigger>
+        </events>
+    </Script> <!-- !!! activates formation behaviour !!! -->
+
+    <Script code="artificialcontroller setbotlevel 5" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=FormationInit />
+            </trigger>
+        </events>
+    </Script>
+
+    <SimpleNotification message="Let's go!">
+        <events>
+            <trigger>
+                <EventListener event="LetsGo" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+
+
+<!-- ADDING FORMATION: 2 Swallows -->
+<?lua for i=0,1,1 do
+?>
+    <SpaceShip position="<?lua print(400+i*200) ?>,-200,1000" lookat="-1300,-600,900" visible="true">
+        <templates>
+            <Template link=spaceshipswallow /> <!--spaceshipTransporter spaceshippirate-->
+        </templates>
+        <controller>
+            <AIController team=0>
+                <events>
+                    <activity>
+                        <EventListener event="LetsGo" />
+                     </activity>
+                </events>
+            </AIController>
+        </controller>
+    </SpaceShip>
+<?lua end ?>
+
+<?lua for i=0,2,1 do
+?>
+
+
+<!-- ENEMY SWALLOWS -->
+    <SpaceShip position="<?lua print(-400+i*200) ?>,3000,-2000" lookat="-1300,-600,900" visible="true">
+        <templates>
+            <Template link=spaceshipswallow />
+        </templates>
+        <controller>
+            <AIController team=1>
+                <events>
+                    <activity>
+                        <EventListener event="Fight" />
+                     </activity>
+                </events>
+            </AIController>
+        </controller>
+    </SpaceShip>
+<?lua end ?>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/michaelstestfile.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/michaelstestfile.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/michaelstestfile.lua	(revision 11817)
@@ -0,0 +1,1 @@
+orxout("event: theme")
Index: /code/branches/RacingBots_FS18/data/levels/mineLevel.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/mineLevel.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/mineLevel.oxw	(revision 11817)
@@ -0,0 +1,64 @@
+ <LevelInfo
+ name = "Mine level"
+ description = "A test level with the new mine weapon."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipEscortMine.oxt")
+  include("templates/spaceshipHover.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescortmine />
+
+        <Pawn team=1 health=30 position="0,100,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box RVName = "Box 4" >
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=30 position="0,200,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box RVName = "Box 3">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+           <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/missionOne.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/missionOne.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/missionOne.oxw	(revision 11817)
@@ -0,0 +1,1742 @@
+<!---->
+<LevelInfo
+ name = "Mission One"
+ description = "Codename: Awakening - First Guided Steps in the Orxonoxian Universe."
+ screenshot = "missionOne.png"
+ tags = "mission"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipSpacecruiser.oxt")
+  include("templates/spaceshipTransporter.oxt")
+?>
+
+<?lua
+include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level
+ gametype     = "Mission"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=3.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" /> <!-- AlphaCentauri.ogg, Mars.ogg-->
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+<!-- END OF INCLUDES & NECESSARITIES -->
+
+<!-- SPAWNPOINT & START OF QUESTS via spawntrigger -->
+    <EventMultiTrigger name=spawntrigger>
+        <events>
+            <trigger>
+                <TeamSpawnPoint team=0 position="800,700,600" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="attack" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </TeamSpawnPoint>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <AddQuest questId="missionOne.basicFlying" />
+                <!--AddQuestHint hintId ="quest1hint3" /-->
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=spawntrigger />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.basicFlying" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="flying4" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.navigation" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="navigationend" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!--helper trigger to end the weaponsystemI quest -->
+    <DistanceTrigger name="boxend" position="0,0,0" distance=950 target="SpaceShip" stayActive="false" delay=0.1>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="boxtrigger4" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+    </DistanceTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.weaponsystemI" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="boxend" />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!--helper trigger to end the weaponsystemII quest -->
+    <DistanceTrigger name="piratesend" position="0,0,0" distance=2000 target="SpaceShip" stayActive="false" delay=0.1>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="movingpirates2" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+    </DistanceTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.weaponsystemII" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=piratesend />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!--helper trigger to end the DuBallStation quest -->
+    <DistanceTrigger name="duballend" position="-1000,-300,700" distance=2000 target="SpaceShip" stayActive="false" delay=0.1>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="duball3" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+    </DistanceTrigger>
+
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.DuballStation" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=duballend />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon times=1> <!--  alternative quest end  -->
+            <effects>
+                <CompleteQuest questId="missionOne.DuballStation" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=toHydroFarmer />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!--helper trigger to end the getHelp quest -->
+    <DistanceTrigger name="getHelpEnd" position="-47000,-1000,1300" distance=1400 target="SpaceShip" stayActive="false" delay=0.1>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="ondock" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+    </DistanceTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.getHelp" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=getHelpEnd />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!--helper trigger to end the getHome quest -->
+    <DistanceTrigger name="getHomeEnd" position="0,0,0" distance=4000 target="SpaceShip" stayActive="false" delay=0.1>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="attack" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+    </DistanceTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.getHome" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=getHomeEnd />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!--helper trigger to end the defence quest -->
+    <DistanceTrigger name="defenceEnd" position="0,0,0" distance=4000 target="SpaceShip" stayActive="false" delay=0.1>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event="attacktrigger6" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+    </DistanceTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <CompleteQuest questId="missionOne.defence" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=defenceEnd />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+<!-- End the quest after own destruction of spacecruiser -->
+        <QuestEffectBeacon position="-100,0,0" times=1>
+            <effects>
+                <FailQuest questId="missionOne.getHelp" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event="failQuest" />
+                </execute>
+            </events>
+            <attached>
+                <DistanceTrigger name="failQuest" position="-47000,-1000,1300" distance=2300 target="SpaceShip">
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event="gameEnd" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </DistanceTrigger>
+            </attached>
+        </QuestEffectBeacon>
+
+
+
+
+    <LocalQuest id="missionOne.basicFlying">
+        <QuestDescription title="Flying" description="Can you see the blinking light straight ahead? Your goal is to fly through it.
+Use (W) to accelerate and steer with your mouse.
+
+Further flying moves:
+break (S)
+roll     (Q) and (E)
+boost (Space)
+
+Whenever a new quest is added you can view it by pressing (F3). Quit this menu via (Esc)." failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="missionOne.navigation" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="missionOne.navigation">
+        <QuestDescription title="Navigation" description="The next goal is to find and move towards the test targets for your weaponsystem. The three arrows that just appeared down in the right corner of your screen indicate in which direction you have to turn your spacefighter to find your next targets.
+
+Alternative navigation: There's a green circle in the left corner - the radar. The red dots on the radar represent your targets. If you manage to move your spaceship in a way such that a dot is at the center of the radar, you will be able to see the concerning object straight ahead." failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="missionOne.weaponsystemI" />
+        </complete-effects>
+    </LocalQuest>
+
+            <LocalQuest id ="missionOne.weaponsystemI">
+                <QuestDescription title="Destroy the Boxes" description="Test your four different weapons on the four boxes:
+1. laser (left click)
+2. plasma (right click)
+3. target seeking rockets (middle click)
+4. manual rockets (T)
+
+Attention if you use manual rockets: Press (T) only once to start the rocket. If you miss your target you can get out of the rocket, by clicking or pressing (T) once more." failmessage="" completeMessage="" />
+                    <hints>
+                        <QuestHint id="missionOne.weaponsystem.laser">
+                            <QuestDescription title="Laser" description="The laser is a standard weapon. It is fast and precise but does not deal much damage." />
+                        </QuestHint>
+                        <QuestHint id="missionOne.weaponsystem.lightningGun">
+                            <QuestDescription title="Lightninggun" description="That was the lightning gun. Its plasma munition is quite slow, but a normal spaceship can't take more than three hits of such a strong weapon. That could be your favourite weapon for close range combat or if you want to hit a really slow enemy." />
+                        </QuestHint>
+                        <QuestHint id="missionOne.weaponsystem.targetSeekingRocket">
+                            <QuestDescription title="Target Seeking Rocket" description="The target seeking rockets follow slow targets on their own." />
+                        </QuestHint>
+                        <QuestHint id="missionOne.weaponsystem.manualrocket">
+                            <QuestDescription title="Manual Rocket" description="Manual rockets are your most powerful weapon. But since you have to steer it to your target yourself, you will leave your spaceship unprotected for a while. The total amount of both manual and target seeking rockets is limited to 10." />
+                        </QuestHint>
+                    </hints>
+                <complete-effects>
+                    <AddQuest questId="missionOne.weaponsystemII" />
+                </complete-effects>
+            </LocalQuest>
+
+            <LocalQuest id="missionOne.weaponsystemII">
+                <QuestDescription title="Kill the pirates" description="Get rid of the patrolling pirates.
+Find out which weapon is best to tackle moving targets. Get close enough." failmessage="" completeMessage="" />
+                <complete-effects>
+                    <AddQuest questId="missionOne.DuballStation" />
+                </complete-effects>
+            </LocalQuest>
+
+    <LocalQuest id="missionOne.DuballStation">
+        <QuestDescription title="Duball Space Station" description="Fly towards the Duball Space Station. The grey radar marker will lead you to its position." failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="missionOne.getHelp" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="missionOne.getHelp">
+        <QuestDescription title="Get Help" description="There are several enemies approaching. You can't handle it on your own. Fortunately there's a shortcut to the next friendly unit. Use the portal (grey dot) to get near the Hydrogen Farmer.
+The Hydrogen Farmer is a large spaceship with three legs.
+There you might get help - as far as we know there should be a strong spaceruiser docked to the Hydrogen Farmer. In order to be able to use that stronger spaceship, you have to dock to the Hydrogen Farmer.
+Simply fly to the center of the Hydrogen Farmer, which is between its three legs.
+
+How to dock: Accept the dialogue, take your hands off the keyboard and watch." failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="missionOne.getHome" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="missionOne.getHome">
+        <QuestDescription title="Return ASAP" description="So you managed to get the spacecruiser. Use the portal to return to the DuBall Space Station.
+Hurry! Your help is desperately needed." failmessage="" completeMessage="" />
+        <complete-effects>
+            <AddQuest questId="missionOne.defence" />
+        </complete-effects>
+    </LocalQuest>
+
+    <LocalQuest id="missionOne.defence">
+        <QuestDescription title="Defence" description="Seven enemies were detected that seem to launch a coordinated attack.
+Do not hesitate to fight or you will be the target.
+
+Always take care of the enemy that is the closest to you." failmessage="" completeMessage="Yeah! You did it." />
+    </LocalQuest>
+<!-- --------------------- END OF QUESTS -------------------------- -->
+
+
+    <DistanceTrigger name="spawndelaytrigger0" position="800,700,600" target="Pawn" distance=10 stayActive="true" delay=2/>
+    <SimpleNotification message="Press (F3) to see your mission briefing.">
+        <events>
+            <trigger>
+                <EventListener event="spawndelaytrigger0" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-- Blinking Billboard should be replaced with WAYPOINT -->
+<BlinkingBillboard position="-900,640,600" frequency=0.6 amplitude=3 material="Flares/lensflare" colour="1,1,0.05">
+          <events>
+            <visibility>
+              <EventTrigger invert=true>
+                <events>
+                  <trigger>
+                    <EventListener event=flying4 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</BlinkingBillboard>
+<Billboard position="-900,640,600" amplitude=1 material="Flares/lensflare" colour="0,0.8,0.1">
+          <events>
+            <visibility>
+              <EventTrigger>
+                <events>
+                  <trigger>
+                    <EventListener event=flying4 />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </visibility>
+          </events>
+</Billboard>
+
+<!-------------------------------------- PART ZERO: How to fly --------------------------------------->
+
+    <DistanceTrigger name="flying1" position="800,700,600" target="Pawn" distance=10 stayActive="true" delay=6/>
+    <SimpleNotification message="Let's fly to the blinking light.">
+        <events>
+            <trigger>
+                <EventListener event="flying1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="flying2" position="800,700,600" target="Pawn" distance=10 stayActive="true" delay=10/>
+    <SimpleNotification message="Use (W) to accelerate and the mouse to steer.">
+        <events>
+            <trigger>
+                <EventListener event="flying2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-- QUEST-Trigger && Message Trigger: navigationend is activated after flying4 was triggered -->
+    <DistanceTrigger name="navigationend" position="0,0,0" distance=950 target="SpaceShip" stayActive="false" delay=1.1>
+        <DistanceTrigger name="flying4" position="-900,640,600" target="Pawn" distance=60 stayActive="true" delay=1/>
+    </DistanceTrigger>
+
+
+    <SimpleNotification message="Three arrows just appeared.">
+        <events>
+            <trigger>
+                <EventListener event="flying4" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <DistanceTrigger name="flying5" position="-900,640,600" target="Pawn" distance=60 stayActive="true" delay=5/>
+    <SimpleNotification message="Follow those arrows.">
+        <events>
+            <trigger>
+                <EventListener event="flying5" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-------------------------------------- PART ONE : Destroy boxes --------------------------------------->
+<!-- @ triggers: spawndelaytriggerX: textoutput only if no box was destroyed -->
+    <Trigger name="spawndelaytrigger1" mode="and" stayActive="true">
+        <DistanceTrigger position="-900,640,600" target="Pawn" distance=60 stayActive="true" delay=9 />
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="boxtrigger1" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+    <Trigger name="spawndelaytrigger2" mode="and" stayActive="true">
+        <DistanceTrigger position="-900,640,600" target="Pawn" distance=60 stayActive="true" delay=13 />
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="boxtrigger1" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+    <Trigger name="spawndelaytrigger3" mode="and" stayActive="true">
+        <DistanceTrigger position="-900,640,600" target="Pawn" distance=60 stayActive="true" delay=17 />
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="boxtrigger1" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+<!-- @Text: How to shoot-->
+    <SimpleNotification message="Destroy the four boxes." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spawndelaytrigger1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message=" 1. Aim the a red cycle." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spawndelaytrigger2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="2. Click! (hold the left mouse button)" broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="spawndelaytrigger3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-- @Objects: 4 boxes (uncontrolled pawns) -->
+    <Pawn health=30 position="0,0,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "Box 4" >
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+        <controller>
+            <WaypointController team=1>
+            </WaypointController>
+        </controller>
+        <explosion >
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+    </Pawn>
+
+    <Pawn health=30 position="0,100,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "Box 3">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+           <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+        <controller>
+            <WaypointController team=1>
+            </WaypointController>
+        </controller>
+        <explosion >
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+    </Pawn>
+
+    <Pawn health=30 position="0,200,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "Box 2">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+           <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <controller>
+            <WaypointController team=1>
+            </WaypointController>
+        </controller>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+        <explosion >
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+    </Pawn>
+
+    <Pawn health=30 position="0,300,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "Box 1">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+           <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+        <controller>
+            <WaypointController team=1>
+            </WaypointController>
+        </controller>
+        <explosion >
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+            <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+        </explosion>
+    </Pawn>
+
+<!-- @Triggers: boxtrigger1 <-> one   box   destroyed
+                boxtrigger2 <-> two   boxes destroyed
+                boxtrigger3 <-> three boxes destroyed
+                boxtrigger4 <-> four  boxes destroyed  -->
+    <EventTrigger name="boxtrigger4" activations="1" stayactive="true" delay=0.1>
+      <events>
+        <trigger>
+          <EventListener event="box" />
+        </trigger>
+      </events>
+      <EventTrigger name="boxtrigger3" activations="1" stayactive="true" delay=0.1>
+        <events>
+          <trigger>
+            <EventListener event="box" />
+          </trigger>
+        </events>
+        <EventTrigger name="boxtrigger2" activations="1" stayactive="true" delay=0.1>
+          <events>
+            <trigger>
+              <EventListener event="box" />
+            </trigger>
+          </events>
+          <EventTrigger name="boxtrigger1" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="box" />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </EventTrigger>
+      </EventTrigger>
+    </EventTrigger>
+
+
+  <SimpleNotification message="Right click on the next target." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="boxtrigger1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+  <SimpleNotification message="Middle click on the next target." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="boxtrigger2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+  <SimpleNotification message="Aim at the last target and press (T)." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="boxtrigger3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+  <SimpleNotification message="Try to hit the pirates while you are flying." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="boxtrigger4" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+<!--------------------------------------PART TWO: Moving targets --------------------------------------->
+
+<!-- @Objects: 2 pirates moving in squares, nonlethal -->
+                <SpaceShip position="0,2000,200" lookat="0,0,0" name="movingtarget" radarname="Pirate">
+                            <events>
+                                <visibility>
+                                    <EventListener event="boxtrigger4" />
+                                </visibility>
+                            </events>
+                    <templates>
+                      <Template link=spaceshippirate />
+                    </templates>
+                    <controller>
+                      <WaypointController team=1>
+                         <waypoints>
+                          <Model mesh="cube.mesh" scale=8 position="  0,1700,-200" />
+                          <Model mesh="cube.mesh" scale=8 position="  0,1700,-700" />
+                          <Model mesh="cube.mesh" scale=8 position="500,1700,-700" />
+                          <Model mesh="cube.mesh" scale=8 position="500,1700,-200" />
+                       </waypoints>
+                    </WaypointController>
+                  </controller>
+                </SpaceShip>
+
+                <SpaceShip position="0,2000,400" lookat="0,0,0" name="movingtarget" radarname="Pirate">
+                            <events>
+                                <visibility>
+                                    <EventListener event="boxtrigger4" />
+                                </visibility>
+                            </events>
+                  <templates>
+                    <Template link=spaceshippirate />
+                  </templates>
+                  <controller>
+                    <WaypointController team=1>
+                      <waypoints>
+                        <Model mesh="cube.mesh" scale=8 position="  0,2400,1000" />
+                        <Model mesh="cube.mesh" scale=8 position="  0,2400, 500" />
+                        <Model mesh="cube.mesh" scale=8 position="500,2400, 500" />
+                        <Model mesh="cube.mesh" scale=8 position="500,2400,1000" />
+                      </waypoints>
+                    </WaypointController>
+                  </controller>
+                </SpaceShip>
+
+<!-- @Triggers: movingpirates1 <-> one  pirate  dead
+                movingpirates2 <-> both pirates dead  -->
+    <EventTrigger name="movingpirates2" activations="1" stayactive="true" delay=0.1>
+      <events>
+        <trigger>
+          <EventListener event="movingtarget" />
+        </trigger>
+      </events>
+      <EventTrigger name="movingpirates1" activations="1" stayactive="true" delay=0.1>
+        <events>
+          <trigger>
+            <EventListener event="movingtarget" />
+          </trigger>
+        </events>
+      </EventTrigger>
+    </EventTrigger>
+
+
+    <SimpleNotification message="Now get the other one."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="movingpirates1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Fly towards the space station (grey dot)."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="movingpirates2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+
+<!--------------------------------------PART THREE: the space station --------------------------------------->
+    <DistanceTrigger name="duball1" position="-1000,-300,700" target="Pawn" distance=700 stayActive="true" delay=1 >
+      <events>
+        <activity>
+          <EventListener event="movingpirates2" />
+        </activity>
+      </events>
+    </DistanceTrigger>
+
+    <Trigger name="duball2" mode="and" stayActive="true">
+        <EventTrigger activations="1" stayactive="true" delay=4 >
+           <events>
+              <trigger>
+                 <EventListener event="duball1" />
+              </trigger>
+           </events>
+        </EventTrigger>
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="toHydroFarmer" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+    <Trigger name="duball3" mode="and" stayActive="true">
+        <EventTrigger activations="1" stayactive="true" delay=4 >
+           <events>
+              <trigger>
+                 <EventListener event="duball2" />
+              </trigger>
+           </events>
+        </EventTrigger>
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="toHydroFarmer" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+
+    <SimpleNotification message="Welcome to the Duball Space Station!">
+        <events>
+            <trigger>
+                <EventListener event=duball1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Warning: Something big is coming." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=duball2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Use the portals to get help. (grey dot)" broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=duball3 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+<!-- @Objects: DuBall Space Station, (no pawn!) -->
+    <StaticEntity position="-1000,-300,700" collisionType=static>
+      <attached>
+        <Model scale=13 mesh="DuBall1.mesh" position = "-100,0,0"/>
+        <Model scale=13 mesh="DuBall2.mesh" position = "100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "-100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "100,0,0"/>
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="80"            position = "-100,0,0" />
+        <SphereCollisionShape radius="120"           position = "100,0,0" />
+        <BoxCollisionShape    halfExtents="90,25,45" position = "-155,0,40" />
+      </collisionShapes>
+    </StaticEntity>
+
+
+<!-- @Objects: PORTAL: from DuBall to HydroHarvester  -->
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Billboard material="Portals/Default" />
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="-1400,-500,800" id="1" distance="50" target="MobileEntity" design="PortalDefault">
+          <events>
+            <activity>
+              <Trigger mode="or" activations="2">
+                <Trigger mode="and" activations="1">
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event="movingpirates2" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="toHydroFarmer" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </Trigger>
+                <Trigger mode="and" activations="1">
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event="ondock" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="attack" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </Trigger>
+                <EventTrigger>
+                  <events>
+                    <trigger>
+                      <EventListener event="HydroFarmer" />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </Trigger>
+            </activity>
+          </events>
+    </PortalEndPoint>
+
+    <PortalEndPoint position="-47000,-1000,1300" id="2" distance="70" target="MobileEntity" design="PortalDefault">
+          <events>
+            <activity>
+              <Trigger mode="or" activations="3">
+                <Trigger mode="and" activations="1">
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event="movingpirates2" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="toHydroFarmer" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </Trigger>
+                <Trigger mode="and" activations="1">
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event="ondock" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="attack" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </Trigger>
+                <EventTrigger>
+                  <events>
+                    <trigger>
+                      <EventListener event="HydroFarmer" />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+              </Trigger>
+            </activity>
+          </events>
+    </PortalEndPoint>
+    <PortalLink fromID="1" toID="2" />
+    <PortalLink fromID="2" toID="1" />
+<!-- ????????????????????????????????????????????????????? why does this NOT work ??
+                <Trigger mode="and" activations="1">
+                  <EventTrigger>
+                    <events>
+                      <trigger>
+                        <EventListener event="HydroFarmer" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                    <events>
+                      <trigger>
+                        <EventListener event="attack" />
+                      </trigger>
+                    </events>
+                  </EventTrigger>
+                </Trigger>
+-->
+<!-- PORTALS END-->
+
+
+    <SimpleNotification message="Dock to the Hydrogen Farmer." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=toHydroFarmer />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-------------------------------------- PART FOUR : Get Help --------------------------------------->
+
+    <Trigger name="famer1" mode="and" stayActive="true">
+        <DistanceTrigger position="-48200,100,0" target="Pawn" distance=650 stayActive="true" delay=0 />
+        <EventTrigger name="notGameEnd" activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="gameEnd" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+    <Trigger name="famer2" mode="and" stayActive="true">
+        <DistanceTrigger position="-48200,100,0" target="Pawn" distance=650 stayActive="true" delay=4 />
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="gameEnd" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </Trigger>
+
+    <SimpleNotification message="We just received a message from DuBall." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=famer1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+    <SimpleNotification message="We will lend you our strongest ship." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=famer2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+<!-- @Objects: HYDROGEN FARMER & DOCKING -->
+    <SpaceShip
+        team      = 0
+        position  = "-48900,100,0"
+        roll      = 90   yaw=0  pitch=20
+        mass      = 10000
+        health    = 100000 initialhealth=100000 maxhealth="100000"
+        name      = "HydroFarmer"
+        radarname = "Hydrogen Farmer" >
+      <attached>
+        <!-- Docking -->
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+   <!-- <Model mesh="cube.mesh" mass=10 position="-560,0,0" scale3D="115,100,245"  />
+        <Model mesh="cube.mesh" mass=10 position="290,0,-480" scale3D="115,100,245" yaw=-120 />
+        <Model mesh="cube.mesh" mass=10 position="290,0,480" scale3D="115,100,245" yaw=-240 />
+        <Model mesh="cube.mesh" mass=10 position="-280,0,0" scale3D="163,50,50" />
+        <Model mesh="cube.mesh" mass=10 position="140,0,-240" scale3D="163,50,50"  yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="140,0,240" scale3D="163,50,50" yaw=-240/>
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" />
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" yaw=-240/>
+        <Model mesh="cube.mesh" mass=10 position="0,400,0" scale3D="43,110,26" yaw=-30 />
+        <Model mesh="cube.mesh" mass=10 position="-200,100,0" scale3D="26,50,43" />
+        <Model mesh="cube.mesh" mass=10 position="100,100,-173" scale3D="43,50,26" yaw=-30/>
+        <Model mesh="cube.mesh" mass=10 position="100,100,173" scale3D="43,50,26" yaw=30/>
+        <Model mesh="cube.mesh" mass=10 position="-100,264,0" scale3D="26,105,43" roll=-49/>
+        <Model mesh="cube.mesh" mass=10 position="50,264,-87" scale3D="26,105,43" roll=-49 yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="50,264,87" scale3D="26,105,43" roll=-49 yaw=-240/>     -->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </SpaceShip>
+
+    <Dock position="-48900,0,0" roll=90 yaw=180 >
+        <animations>
+            <MoveToDockingTarget target="destroyer" />
+        </animations>
+        <effects>
+            <DockToShip target="spaceShip" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+            <activity>
+                <EventListener event=notGameEnd />
+            </activity>
+        </events>
+        <attached>
+            <DistanceTrigger position="10,-202, -42" distance="800" target="Pawn"
+                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"
+            />
+        </attached>
+
+    </Dock>
+
+<!--@Objects: SpaceCruiser as docking target -->
+    <SpaceShip
+        template            = "spaceshipspacecruiser"
+        team                = "0"
+        position            = "-48900,800,0"
+        orientation         = "-0.14, 0.68, 0.68, 0.223"
+        health              = "400"
+        initialhealth       = "400"
+        maxhealth           = "500"
+        shieldhealth        = "80"
+        initialshieldhealth = "80"
+        maxshieldhealth     = "120"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "1"
+        shieldrechargewaittime = "1"
+        name                = "cruiser"
+        radarname           = "Spacecruiser" >
+      <attached>
+        <DockingTarget name="spaceShip" />
+      </attached>
+    </SpaceShip>
+
+
+<!-- cruiserKilled: if cuiser is killed & player hasn't taken control of spacecrusier -->
+          <Trigger name="cruiserKilled" mode="and" stayActive="true">
+            <EventTrigger  stayActive="true">
+              <events>
+                <trigger>
+                  <EventListener event="cruiser"/>
+                </trigger>
+              </events>
+            </EventTrigger>
+            <EventTrigger invert=true>
+              <events>
+                <trigger>
+                  <EventListener event="ondock" />
+                </trigger>
+              </events>
+            </EventTrigger>
+          </Trigger>
+
+
+<!-- triggers when either hydrofarmer or cruiser is killed -->
+            <Trigger mode=or name="gameEnd">
+                <EventTrigger activations="1">
+                  <events>
+                    <trigger>
+                      <EventListener event="HydroFarmer" />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+                <EventTrigger activations="1">
+                  <events>
+                    <trigger>
+                      <EventListener event="cruiserKilled" />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+            </Trigger>
+
+<!-- triggers delayed when either hydrofarmer or cruiser is killed -->
+            <EventTrigger delay=4 name="earlyEnd">
+              <events>
+                <trigger>
+                  <EventListener event="gameEnd" />
+                </trigger>
+              </events>
+              <events>
+                <activity>
+                  <EventListener event="movingpirates2" />
+                </activity>
+              </events>
+            </EventTrigger>
+
+
+    <SimpleNotification message="Oh no! You killed the Hydrogen Farmer!" broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="HydroFarmer" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Oh no! You killed the SpaceCruiser!" broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="cruiserKilled" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Press (Esc) and restart the mission." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event="earlyEnd" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-- hydrogen farmer & docking END -->
+
+
+<!-- @Objects: Pickup - find better place !! -->
+    <PickupSpawner pickup=hugeshieldpickup position="-48650,700,100" triggerDistance="70" respawnTime="30" maxSpawnedItems="1" />
+
+
+    <DistanceTrigger name="pickup" position="-48650,700,100" target="Pawn" distance=60 stayActive="true" delay=0 />
+    <SimpleNotification message="This pickup protects your spaceship.">
+        <events>
+            <trigger>
+                <EventListener event=pickup />
+            </trigger>
+        </events>
+    </SimpleNotification>
+<!-- Pickup-->
+
+
+<!-- @Objects: planet && spaceboundaries  -->
+    <Planet
+      position="-44000,0,0"
+      scale="2500"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = "2"
+      enablecollisiondamage = "false"
+    >
+      <!--attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached-->  <!-- Forcefield kills HYDROGEN FARMER-->
+      <collisionShapes>
+        <SphereCollisionShape radius="2500" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+
+<!-------------------------------------- The attack --------------------------------------->
+<!-- TODO:
+     - update spaceshipTransporter
+     - bots do friendly fire (is drone function reusable?)
+-->
+
+<!-- Fallback Spawnpoint: on cruiserdeath caused by pirates. Unfortunately unstable behaviour concerning activity. -->
+    <TeamSpawnPoint team=0 position="2000,1500,-1500" direction="-1,-1,1" spawnclass=SpaceShip pawndesign=spaceshipspacecruiser>
+        <events>
+            <activity>
+                <EventListener event="attack" />
+            </activity>
+        </events>
+    </TeamSpawnPoint>
+
+<!-- @Triggers: toHydroFamer <-> first  portal usage
+                ondock       <-> successfull docking
+                attack       <-> second portal usage -->
+
+    <DistanceTrigger name="attack" position="-1400,-500,800" target="Pawn" distance=100 stayActive="true" mode="and">
+        <EventTrigger name="ondock" activations="1" stayactive="true" delay=6>
+          <events>
+            <trigger>
+              <EventListener event="dockMe" />
+            </trigger>
+          </events>
+            <Trigger mode=and>
+              <DistanceTrigger name="toHydroFarmer" position="-47000,-1000,1300" target="Pawn" distance=100 stayActive="true" />
+              <EventTrigger activations="1" invert="true">
+                <events>
+                  <trigger>
+                    <EventListener event="gameEnd" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </Trigger>
+        </EventTrigger>
+        <EventTrigger activations="1" invert="true">
+          <events>
+            <trigger>
+              <EventListener event="earlyEnd" />
+            </trigger>
+          </events>
+        </EventTrigger>
+    </DistanceTrigger>
+
+    <SimpleNotification message="Return before it's too late. Boost with (Space)." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=ondock />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Several serious enemies are approaching!">
+        <events>
+            <trigger>
+                <EventListener event=attack />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+<!-- @Objects: 6 pirates, heading towards DuBall, attacking  -->
+<!-- TODO: re-hide pirates on early end-->
+<!-- 1 -->
+    <SpaceShip position="3000,-4000,4000" lookat="-1300,-600,900" name="attacker"visible="true">
+        <events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events>
+        <templates>
+            <Template link=spaceshippirate /> <!--spaceshipTransporter -->
+        </templates>
+        <controller>
+            <WaypointPatrolController alertnessradius=3129 team=1 active=false>
+                <waypoints>
+                    <Model mesh="cube.mesh" scale=0 position="-1300,-600,900" />
+                    <Model mesh="cube.mesh" scale=0 position="0,0,0" />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="attack" /> <!-- activates enemies-->
+                     </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+<!-- 2 -->
+    <SpaceShip position="3000,-4000,-4000" lookat="-1300,-600,900" name="attacker" visible="true">
+        <events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events>
+        <templates>
+            <Template link=spaceshippirate /> <!--spaceshipTransporter -->
+        </templates>
+        <controller>
+            <WaypointPatrolController alertnessradius=3129 team=1 active=false>
+                <waypoints>
+                    <Model mesh="cube.mesh" scale=0 position="-1300,-600,900" />
+                    <Model mesh="cube.mesh" scale=0 position="0,0,0" />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="attack" /> <!-- activates enemies-->
+                     </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+<!-- 3 -->
+    <SpaceShip position="-4000,-3000,4000" lookat="-1300,-600,900" name="attacker" visible="true">
+        <events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events>
+        <templates>
+            <Template link=spaceshippirate /> <!--spaceshipTransporter -->
+        </templates>
+        <controller>
+            <WaypointPatrolController alertnessradius=3129 team=1 active=false>
+                <waypoints>
+                    <Model mesh="cube.mesh" scale=0 position="-1300,-600,900" />
+                    <Model mesh="cube.mesh" scale=0 position="0,0,0" />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="attack" /> <!-- activates enemies-->
+                     </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+<!-- 4 -->
+    <SpaceShip position="-3000,-3000,-5000" lookat="-1300,-600,900" name="attacker" visible="true">
+        <events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events>
+        <templates>
+            <Template link=spaceshippirate /> <!--spaceshipTransporter -->
+        </templates>
+        <controller>
+            <WaypointPatrolController alertnessradius=3129 team=1 active=false>
+                <waypoints>
+                    <Model mesh="cube.mesh" scale=0 position="-1300,-600,900" />
+                    <Model mesh="cube.mesh" scale=0 position="0,0,0" />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="attack" /> <!-- activates enemies-->
+                     </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+<!-- 5 -->
+    <SpaceShip position="4000,4000,3000" lookat="-1300,-600,900" name="attacker"visible="true">
+        <events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events>
+        <templates>
+            <Template link=spaceshippirate /> <!--spaceshipTransporter -->
+        </templates>
+        <controller>
+            <WaypointPatrolController alertnessradius=3129 team=1 active=false>
+                <waypoints>
+                    <Model mesh="cube.mesh" scale=0 position="-1300,-600,900" />
+                    <Model mesh="cube.mesh" scale=0 position="0,0,0" />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="attack" /> <!-- activates enemies-->
+                     </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+<!-- 6 -->
+    <SpaceShip position="2000,-4000,5000" lookat="-1300,-600,900" name="attacker" visible="true">
+        <events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events>
+        <templates>
+            <Template link=spaceshippirate /> <!--spaceshipTransporter -->
+        </templates>
+        <controller>
+            <WaypointPatrolController alertnessradius=3129 team=1 active=false>
+                <waypoints>
+                    <Model mesh="cube.mesh" scale=0 position="-1300,-600,900" />
+                    <Model mesh="cube.mesh" scale=0 position="0,0,0" />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="attack" /> <!-- activates enemies-->
+                     </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+
+
+<!-- @Triggers: attacktriggerX <-> X enemies destroyed , X is an element of [1,6] -->
+    <EventTrigger name="attacktrigger6" activations="1" stayactive="true">
+      <events>
+        <trigger>
+          <EventListener event="attacker" />
+        </trigger>
+      </events>
+      <EventTrigger name="attacktrigger5" activations="1" stayactive="true" delay=0.1>
+        <events>
+          <trigger>
+            <EventListener event="attacker" />
+          </trigger>
+        </events>
+        <EventTrigger name="attacktrigger4" activations="1" stayactive="true" delay=0.1>
+          <events>
+            <trigger>
+              <EventListener event="attacker" />
+            </trigger>
+          </events>
+          <EventTrigger name="attacktrigger3" activations="1" stayactive="true" delay=0.1>
+            <events>
+              <trigger>
+                <EventListener event="attacker" />
+              </trigger>
+            </events>
+            <EventTrigger name="attacktrigger2" activations="1" stayactive="true" delay=0.1>
+              <events>
+                <trigger>
+                  <EventListener event="attacker" />
+                </trigger>
+              </events>
+              <EventTrigger name="attacktrigger1" activations="1" stayactive="true" delay=0.1>
+                <events>
+                  <trigger>
+                    <EventListener event="attacker" />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </EventTrigger>
+          </EventTrigger>
+        </EventTrigger>
+      </EventTrigger>
+    </EventTrigger>
+
+
+    <SimpleNotification message="5 enemies left!" broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger1" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="4 enemies left!" broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger2" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="3 enemies left!" broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger3" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="2 enemies left!" broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger4" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="One enemy left!" broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger5" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Well done. You finished this tutorial." broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+<!-- @Triggers: postAttack <-> delayed attacktrigger6 -->
+    <EventTrigger name="postAttack1" activations="1" stayactive="true" delay=4.1>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <EventTrigger name="postAttack2" activations="1" stayactive="true" delay=8.2>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+    <SimpleNotification message="Either quit by pressing (Esc) or ..." broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="postAttack1" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="... stay here to learn some tricks." broadcast="true">
+      <events>
+        <trigger>
+          <EventListener event="postAttack2" />
+        </trigger>
+      </events>
+    </SimpleNotification>
+
+<!-------------------------------------- |Bonus Part| --------------------------------------->
+<!-- @Triggers: "bonusX" <->  delayed "attacktrigger6" -->
+    <EventTrigger name="bonus1" activations="1" stayactive="true" delay=12.3>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="bonus2" activations="1" stayactive="true" delay=16.4>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="bonus3" activations="1" stayactive="true" delay=22>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="bonus4" activations="1" stayactive="true" delay=28.1>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="bonus5" activations="1" stayactive="true" delay=32.3>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="bonus6" activations="1" stayactive="true" delay=36.5>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="bonus7" activations="1" stayactive="true" delay=4.1>
+      <events>
+        <trigger>
+          <EventListener event="bonus6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+
+
+    <SimpleNotification message="Rotate your ship. Press (Q) or (E). "  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Switch the camera's position. Press (C). "  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="360° view: press (Ctrl) + use the mouse "  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus3 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Have a look at the main menu's settings."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus4 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="E.g: Settings > Miscellaneous > Nr. of bots"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus5 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="You successfully finished Mission One!"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus6 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Press (Esc) and return to the main menu."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=bonus7 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-- @Triggers: HACK. The attacktrigger6 Event is created, but does not trigger the Script.
+(WTF?) TODO: looks like a BUG
+Thus a distanceTrigger is created, that gets enabled, when the inner trigger gets activated.
+Due to the large radius it is likely that it actually gets triggered.
+-->
+
+  <DistanceTrigger name="testDistanceTrigger" position="0,0,0" distance=10000 target="Pawn" stayActive="true" delay=37.0>
+    <EventTrigger name="testEventTrigger" activations="1" stayactive="true" delay=0.1>
+      <events>
+        <trigger>
+          <EventListener event="attacktrigger6" />
+        </trigger>
+      </events>
+    </EventTrigger>
+  </DistanceTrigger>
+
+    <Script code="Mission endMission true" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="testDistanceTrigger" />
+            </trigger>
+        </events>
+    </Script>
+
+    <Script code="Mission endMission false" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="gameEnd" />
+            </trigger>
+        </events>
+    </Script>
+
+
+
+
+
+
+    <!--Script code="addBots 3" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=bonus6 />
+            </trigger>
+        </events>
+    </Script>
+
+    <Script code="artificialcontroller setbotlevel 0.1" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=bonus6 />
+            </trigger>
+        </events>
+    </Script-->
+    <!-- Script code="artificialcontroller setbotlevel 0.1" /-->
+  </Scene>
+</Level>
+
+<!-- TODO:
+- Story & more precise Questmessages; more quest hints; fail-quest;
+- Colouring: Show who is friend or foe via the colour
+- Waypoints: show the player the way
+- Foolproof text messages (e.g. verspätete Nachrichten unterdrücken ~done )
+- End Tutorial, if either the Hydrogen Farmer or the SpaceCruiser gets destroyed. (~done)
+ -->
Index: /code/branches/RacingBots_FS18/data/levels/myTestLevel.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/myTestLevel.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/myTestLevel.oxw	(revision 11817)
@@ -0,0 +1,39 @@
+<LevelInfo
+ name = "MyTestLevel"
+ description = "A level to test the Class SpaceBoundaries."
+ tags = "test"
+ screenshot = "mytestlevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="0,0,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    
+    <SpaceBoundaries warnDistance="1" maxDistance="200" showDistance="150" reactionMode="0" healthDecrease="0.9" position="0,0,0"/>
+    
+    <Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Flares/backlightflare" scale=1 />
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/newnewnewspacerace.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/newnewnewspacerace.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/newnewnewspacerace.oxw	(revision 11817)
@@ -0,0 +1,507 @@
+
+  <!-- Authors:
+Louis Meile
+Berkay Berabi
+@2016
+-->
+
+<LevelInfo
+ name = "The Space Race "
+ description = "Fell The Blaze of The ONE and ONLY Space Race"
+ tags = "gametype"
+ screenshot = "spacerace.png"
+/>
+   
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/fastship.oxt")
+  include("templates/spaceshipPirate.oxt")
+
+  include("templates/spaceshipAssff.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+
+?>
+
+<Level
+ plugins = "gametypes"
+ gametype = "SpaceRace"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+  >
+  
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+
+  <!-- SOUNDS & MUSIC 
+
+to hear the sound one has to use a headphones  
+countdown at the beginning of the race 
+at the and of the countdown we have the sound "go"
+racetheme will be played during the whole race-->
+  
+   
+<WorldSound name="Countdown" position="0,0,0" source="sounds/Countdown.ogg" >
+      <events>
+        <play>
+          <EventListener event="start1" />
+        </play>
+      </events>
+    </WorldSound>
+
+
+<WorldSound name="Go" position="0,0,0" source="sounds/Go.ogg" >
+      <events>
+        <play>
+          <EventListener event="go" />
+        </play>
+      </events>
+    </WorldSound>
+    <DistanceTrigger name="start1" position="0,0,0"  target="Pawn" distance=100 stayActive="true" delay=0.5 />
+    <DistanceTrigger name="go" position="0,0,0"  target="Pawn" distance=100 stayActive="true" delay=10.5  />
+
+    <DistanceTrigger name="racetheme" position="0,0,0"  target="Pawn" distance=100 stayActive="true" delay=10.75  />
+      <WorldAmbientSound source="racetheme.ogg" looping="true" playOnLoad="false" >
+    <events>
+        <play>
+          <EventListener event="racetheme" />
+        </play>
+      </events>
+    </WorldAmbientSound>
+
+
+    <?lua math.randomseed(98) ?>
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SimpleNotification message="Reach the last check point within 150 seconds!!" />
+
+    <!-- ------------------SpawnPoint of the human player----------------- -->
+    <!-- to change the starting positions of bots go to spacerace.cc star function -->
+    <SpawnPoint position="-50,0,0" lookat="1,0,0" spawnclass=SpaceShip pawndesign=fastship active="true" />
+
+  <!-- Launch station of the aircrafts also starting place of the race-->
+  <StaticEntity mass="50" position="-400,-20,0" direction="0,-90,0" collisionType="static">
+    <attached>
+      <Model scale="20" mesh="Carrier.mesh" />
+    </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="280,0,-100"      halfExtents="600, 200, 100" />
+        <BoxCollisionShape position="380,300,-64"     halfExtents="280, 40, 48" />
+        <BoxCollisionShape position="380,-300,-64"    halfExtents="280, 40, 48" />
+        <BoxCollisionShape position="308, 188,120"      halfExtents="440, 80, 120" />
+        <BoxCollisionShape position="308,-188,120"     halfExtents="440, 80, 120" />
+        <BoxCollisionShape position="308,0,200"       halfExtents="440, 180, 24" />
+        <BoxCollisionShape position="668,0,280"      halfExtents="108, 80, 80" />
+      </collisionShapes>
+  </StaticEntity>
+
+  <!-- ---------------ForceFields----------------- -->
+    <ForceField position="0,0,0" direction="0,-1,0" diameter=700 velocity=2000 length=2000/>
+
+    <!-- ------------------Planet----------------- -->
+    <Planet position="25000,5000,5000" scale=3000 pitch=-90 mesh="iceplanet.mesh" atmosphere="atmosphere1" rotationaxis="8,1,0" rotationrate="1" atmospheresize=224.0f imagesize=1024.0f />
+    <StaticEntity position="0,0,0" collisionType=static>
+        <collisionShapes>
+            <SphereCollisionShape radius="1" />
+        </collisionShapes>
+    </StaticEntity>
+
+   <!-- ---------------asteroid belt1----------------- -->
+    <?lua
+    max = 50
+    for i = 0, max, 1
+    do
+    x = 800+ i*1000
+    y = -500+ math.cos(i)*20
+    z = -500+ math.sin(i)*20
+    ?>
+    <?lua
+    for k = 1, 15, 1
+    do
+    j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(x + math.random() * 500) ?>,<?lua print(y + math.random() * 1000) ?>,<?lua print(z + math.random() * 1000) ?>"
+      collisionType = "dynamic"
+      linearDamping = "0.5"
+      angularDamping = "0.01"
+      collisiondamage = "0.02"
+      enablecollisiondamage = "true"
+      scale="<?lua print(j * 5) ?>" >
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh">
+      <?lua if k == 5 then ?><attached><!-- ---------asteroid fog----- -->
+            <ParticleEmitter position="0,0,0" source="Orxonox/Steam" />
+          </attached> <?lua end ?>
+        </Model>
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 80) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+    <?lua
+    end
+    ?>
+    <?lua end ?>
+
+   <!-- ---------------asteroid belt2----------------- -->
+    <?lua
+    max = 50
+    for i = 0, max, 1
+    do
+    x = 800+ i*1000
+    y = 100+ math.cos(i)*-20
+    z = 100+ math.sin(i)*-20
+    ?>
+    <?lua
+    for k = 1, 15, 1
+    do
+    j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(x + math.random() * 500) ?>,<?lua print(y + math.random() * 1000) ?>,<?lua print(z + math.random() * 1000) ?>"
+      collisionType = "dynamic"
+      linearDamping = "0.5"
+      angularDamping = "0.01"
+      collisiondamage = "0.02"
+      enablecollisiondamage = "true"
+      scale="<?lua print(j * 5) ?>" >
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh">
+      <?lua if k == 5 then ?><attached><!-- ---------asteroid fog----- -->
+            <ParticleEmitter position="0,0,0" source="Orxonox/Steam" />
+          </attached> <?lua end ?>
+        </Model>
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 80) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+    <?lua
+    end
+    ?>
+    <?lua end ?>
+
+
+    <!-- ------------------Boards----------------- -->
+    <StaticEntity position="1000,160,0" direction="-1,0,0" yaw=90 pitch=0 roll=-30 collisionType="static">
+    <attached>
+      <Model scale="20" mesh="Board1.mesh" />
+    </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0"      halfExtents="5,10,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+  <StaticEntity position="5000,230,500" direction="-1,0,0" yaw=90 pitch=0 roll=-30 collisionType="static">
+    <attached>
+      <Model scale="20" mesh="Board2.mesh" />
+    </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0"      halfExtents="5,10,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+<StaticEntity position="10000,-70,200" direction="-1,0,0" yaw=90 pitch=0 roll=-30 collisionType="static">
+    <attached>
+      <Model scale="20" mesh="Board2.mesh" />
+    </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0"      halfExtents="5,10,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+<!-- ---------------------Checkpoints---------------------- -->
+
+<SpaceRaceManager>
+ <checkpoints>
+    
+    <!-- distance = how far from the middle point of a check point do i have to fly ? distance variable answers this question   -->
+
+
+    <RaceCheckPoint name="checkpoint1" yaw=90 pitch=90 position="1000,30,0" roll="0" direction="0,1,0" collisionType="static" scale="1" distance="60" checkpointindex="0" islast="false" nextcheckpoints="1,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_Green.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+
+<RaceCheckPoint name="checkpoint2" yaw=90 pitch=90 position="3000,200,100" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="1" islast="false" nextcheckpoints="2,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+<RaceCheckPoint name="checkpoint3" yaw=90 pitch=90 position="5000,100,500" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="2" islast="false" nextcheckpoints="3,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+<RaceCheckPoint name="checkpoint4"  yaw=90 pitch=90 position="8000,-150,150" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="3" islast="false" nextcheckpoints="4,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+<RaceCheckPoint name="checkpoint5"  yaw=90 pitch=90 position="10000,-200,200" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="4" islast="false" nextcheckpoints="5,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+
+<RaceCheckPoint name="checkpoint6" yaw=90 pitch=90 position="13000,200,400" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="5" islast="false" nextcheckpoints="6,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+
+<RaceCheckPoint name="checkpoint7" yaw=90 pitch=90 position="15000,0,0" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="6" islast="false" nextcheckpoints="7,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+<RaceCheckPoint name="checkpoint8" yaw=90 pitch=90 position="18000,150,-150" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="7" islast="false" nextcheckpoints="8,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+<RaceCheckPoint name="checkpoint9" yaw=90 pitch=90 position="21000,200,-120" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="8" islast="false" nextcheckpoints="9,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<RaceCheckPoint name="checkpoint10" yaw=90 pitch=90 position="24000,-150,-80" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="9" islast="false" nextcheckpoints="10,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<RaceCheckPoint name="checkpoint11" yaw=90 pitch=90 position="27000,-200,0" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="10" islast="false" nextcheckpoints="11,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+
+<RaceCheckPoint name="checkpoint12" yaw=90 pitch=90 position="30000,-300,900" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="11" islast="false" nextcheckpoints="12,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+<RaceCheckPoint name="checkpoint13" yaw=90 pitch=90 position="33000,600,60" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="12" islast="false" nextcheckpoints="13,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+
+<RaceCheckPoint name="checkpoint14" yaw=90 pitch=90 position="35000,120,20" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="13" islast="false" nextcheckpoints="14,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<RaceCheckPoint name="checkpoint15" yaw=90 pitch=90 position="38000,-200,0" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="14" islast="false" nextcheckpoints="15,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<RaceCheckPoint name="checkpoint16" yaw=90 pitch=90 position="41000,30,-50" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="15" islast="false" nextcheckpoints="16,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<RaceCheckPoint name="checkpoint17" yaw=90 pitch=90 position="44000,90,0" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="16" islast="false" nextcheckpoints="17,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<RaceCheckPoint name="checkpoint18" yaw=90 pitch=90 position="47000,120,30" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="17" islast="false" nextcheckpoints="18,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+    <RaceCheckPoint name="checkpoint19" yaw=90 pitch=90 position="50000,0,100" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="18" islast="false" nextcheckpoints="19,-1,-1">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_InnerRing.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,70"      halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="0,0,-70"     halfExtents="70, 10, 10" />
+        <BoxCollisionShape position="70,0,0"      halfExtents="10, 10, 70" />
+        <BoxCollisionShape position="-70,0,0"     halfExtents="10, 10, 70" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+<!-- the last checkpoint is bigger and red -->
+    <RaceCheckPoint name="checkpoint20" yaw=90 pitch=90 position="53000,0,0" direction="0,1,0" roll="0" collisionType="static" scale="1" distance="60" checkpointindex="19" islast="true">
+        <attached>
+      <Model position="0,0,0" scale="70" mesh="Checkpoint_Finish.mesh"/>
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,90"      halfExtents="90, 13, 13" />
+        <BoxCollisionShape position="0,0,-90"     halfExtents="90, 13, 13" />
+        <BoxCollisionShape position="90,0,0"      halfExtents="13, 13, 90" />
+        <BoxCollisionShape position="-90,0,0"     halfExtents="13, 13, 90" />
+    </collisionShapes>
+    </RaceCheckPoint>
+
+
+</checkpoints>
+</SpaceRaceManager>
+
+
+
+<!-- ---------------------PickUps---------------------- -->
+
+    <PickupSpawner pickup=smallshrinkpickup position="10000,-200,200" triggerDistance="60" respawnTime="10" maxSpawnedItems="10" scale="8"/>
+    <PickupSpawner pickup=mediumboostpickup position="24000,-150,-80" triggerDistance="60" respawnTime="10" maxSpawnedItems="8" scale="10"/>
+    <PickupSpawner pickup=smallboostpickup position="38000,-200,0" triggerDistance="60" respawnTime="10" maxSpawnedItems="8" scale="10"/>
+
+    <PickupSpawner pickup=smallspeedpickup position="7000,-200,100" triggerDistance="60" respawnTime="10" maxSpawnedItems="8" scale="10"/>
+    <PickupSpawner pickup=mediumshinkpickup position="16000,150,50" triggerDistance="60" respawnTime="10" maxSpawnedItems="8" scale="10"/>
+    <PickupSpawner pickup=triplehealthspeedinvisibilitypickup position="41000,-300,100" triggerDistance="60" respawnTime="10" maxSpawnedItems="8" scale="10"/>
+  </Scene>
+</Level>
+ 
Index: /code/branches/RacingBots_FS18/data/levels/notifications.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/notifications.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/notifications.oxw	(revision 11817)
@@ -0,0 +1,60 @@
+<LevelInfo
+ name = "Notifications showcase"
+ description = "Level to test and showcase notifications."
+ tags = "test, showcase"
+ screenshot = "notificationsshowcase.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+    <templates>
+        <Template link=lodtemplate_default />
+    </templates>
+    <?lua include("includes/notifications.oxi") ?>
+
+    <NotificationQueueCEGUI
+      name="narrative"
+      targets="simpleNotification,commandNotification"
+      size=3
+      displayTime=3.9
+      position="0.2, 0, 0.1, 0"
+      fontSize="23"
+      fontColor="0.3, 1, 0.2, 0.8"
+      alignment="HorzCentred"
+      displaySize="0.6, 0, 0, 0"
+      />
+
+    <Scene
+        ambientlight = "0.5, 0.5, 0.5"
+        skybox       = "Orxonox/skyBoxBasic"
+    >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <CommandNotification preMessage="Open the PickupInventory by pressing '" postMessage="'." command="OrxonoxOverlay show PickupInventory">
+        <events>
+            <trigger>
+                <DistanceTrigger name=trigger position="0,0,-100" distance=10 target="Pawn" />
+            </trigger>
+        </events>
+    </CommandNotification>
+    <Billboard position="0,0,-100" colour="1.0,1.0,0" material="Examples/Flare" />
+
+    <SimpleNotification message="Awesome!!!">
+        <events>
+            <trigger>
+                <DistanceTrigger name=trigger position="0,0,100" distance=10 target="Pawn" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    <Billboard position="0,0,100" colour="1.0,0,1.0" material="Examples/Flare" />
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/CuboidSpaceStation.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/CuboidSpaceStation.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/CuboidSpaceStation.oxw	(revision 11817)
@@ -0,0 +1,112 @@
+<?lua
+    include("HUDTemplates3.oxo")
+?>
+
+<?lua
+    include("templates/spaceshipAssff.oxt")
+?>
+
+<Level
+    name = "SpaceStation test Space!"
+    description = "All the new SpaceStations are created here!"
+>
+    <Scene
+        ambientlight = "0.5, 0.5, 0.5"
+        skybox = "Orxonox/Starbox"
+    >
+
+
+
+<!-------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+<?lua
+    dofile("includes/CuboidSpaceStation.lua")
+?>
+
+<!-- The following examples insert some space station in various ways, so I guess you will understand how to use my .lua file and the functions of it.
+--->
+
+<!-- Here I add a space station at position 0,0,0 without velocity and no rotation.
+--->
+<?lua
+    createSpaceStation()
+?>
+
+
+
+<!-- Here I add a space station at position 0,0,-5000 without velocity and no rotation.
+--->
+<PositionableEntity scale=1 position="0,0,-5000">
+    <attached>
+        <?lua
+            createSpaceStation()
+        ?>
+    </attached>
+</PositionableEntity>
+
+
+
+<!-- Here I add a space station at position 5000,0,0 with velocity 50,0,0 and a rotation so that the space station faces into the positive x-axis.
+--->
+<MovableEntity scale=1 position="5000,0,0" velocity="50,0,0" yaw=-90>
+    <attached>
+        <?lua
+            createSpaceStation()
+        ?>
+    </attached>
+</MovableEntity>
+
+
+
+<!-- Here I add a space station at position -5000,0,0 without velocity but rotation around his own y-axis.
+--->
+<MovableEntity scale=1 position="-5000,0,0" rotationaxis="0,1,0" rotationrate=5>
+    <attached>
+        <?lua
+            createSpaceStation()
+        ?>
+    </attached>
+</MovableEntity>
+
+
+
+<!-- Here I add a space station at position 10000,0,0 which will rotate around the position 0,0,0 and around his own axis in flight direction.
+---- To do so, I create a MovableEntity at position 0,0,0 and attach another MovableEntity with relative coordinates to the first MovableEntity 10000,0,0.
+---- I rotate the first MovableEntity, so the second Entity rotates around 0,0,0 in the x-,z-area with a radius 10000, and so does the space station,
+---- because the space station is attached to the second MovableEntity with relative coordinates 0,0,0 (this is defined in the .lua file).
+---- Then I rotate also the second MovableEntity around his own z-axis, so the space station rotates also around its own axis.
+--->
+<MovableEntity scale=1 position="0,0,0" rotationaxis="0,1,0" rotationrate=3>
+    <attached>
+        <MovableEntity scale=1 position="10000,0,0" rotationaxis="0,0,1" rotationrate=2>
+            <attached>
+                <?lua
+                    -- Here I use the createSpaceStationPar(...) function, which has 8 arguments, see the .lua file at the top to understand them.
+                    createSpaceStationPar(0,2,1,2,1,2,1,50)
+                ?>
+            </attached>
+        </MovableEntity>
+    </attached>
+</MovableEntity>
+
+
+
+<!-------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
+
+
+
+    <ParticleSpawner position="0,0,0" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+      <events>
+        <spawn>
+          <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </spawn>
+      </events>
+    </ParticleSpawner>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/physicsTest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/physicsTest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/physicsTest.oxw	(revision 11817)
@@ -0,0 +1,19 @@
+<Ambient colourvalue="0.8, 0.8, 0.8" />
+<Skybox src="Orxonox/Starbox" />
+<SpaceShip camera="true" position="50,0,0" scale="10" yawpitchroll="0,-90,0" mesh="assff.mesh" maxSpeed="500" maxSideAndBackSpeed="50" maxRotation="1.0" transAcc="200" rotAcc="3.0" transDamp="75" rotDamp="1.0" />
+<Model position="2000,0,0" scale="10" mesh="tomato.mesh" yawpitchroll="-40,30,0" rotationAxis="1,0,0" rotationRate="-30"/>
+<Model position="0,2000,0" scale="10" mesh="tomato.mesh" yawpitchroll="-50,60,0" rotationAxis="1,0,0" rotationRate="-30"/>
+<Model position="0,0,2000" scale="10" mesh="tomato.mesh" yawpitchroll="-50,-30,0" rotationAxis="1,0,0" rotationRate="-30"/>
+<Model position="10000,16000,0" scale="100" mesh="DuBall1.mesh"/>
+<Model position="11400,16000,0" scale="60" mesh="DuBall2.mesh"/>
+
+<HelloBullet/>
+
+
+<?lua
+for i = 1, 226, 1
+do ?>
+  <Model position="<?lua print(math.random() * 40000 - 20000)?>, <?lua print(math.random() * 40000 - 20000) ?>, <?lua print(math.random() * 40000 - 20000) ?>" scale="<?lua print(math.random() * 250 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" rotationAxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationRate="<?lua print(math.random() * 30 + 15) ?>" />
+<?lua
+end
+?>
Index: /code/branches/RacingBots_FS18/data/levels/old/physicsTest2.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/physicsTest2.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/physicsTest2.oxw	(revision 11817)
@@ -0,0 +1,280 @@
+<?lua
+  include("spaceshipTemplatesPhysics.oxw")
+?>
+<?lua
+  include("HUDTemplates3.oxo")
+?>
+
+<Level
+ name         = "Sample"
+ description  = "Just a few tests"
+>
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/Starbox"
+   negativeWorldRange = "-100000, -100000, -100000"
+   positiveWorldRange = " 100000,  100000,  100000"
+   hasPhysics   = true
+  >
+      <!--SpawnPoint position="0,   0,  100"           spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0,   0, -700" yaw  =180 spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0, 300, -300" pitch=-90 spawnclass=SpaceShip pawndesign=spaceshipassff /-->
+
+    <!-- axes in ogre's origin of coordinate system for phsics engine testing purposes-->
+    <StaticEntity
+     position        = "0,0,0"
+     name            = "banana"
+     collisionType   = "static"
+     mass            = 1000
+    >
+      <attached>
+        <Model position="0,0,0" scale=100 mesh="plane.mesh" />
+        <Model position="0,-0.0001,0" roll=180 scale=100 mesh="plane.mesh" />
+      </attached>
+      <collisionShapes>
+        <PlaneCollisionShape name="thePlane" planeNormal="0,1,0" planeOffset=0 />
+      </collisionShapes>
+    </StaticEntity>
+
+    <!-- red sphere for phsics engine testing purposes-->
+    <!--StaticEntity position="40,0,0">
+      <attached>
+        <Model position="0,0,0" scale=1 mesh="sphere.mesh" />
+      </attached>
+    </StaticEntity-->
+
+    <!-- yellow cube for phsics engine testing purposes-->
+    <!--StaticEntity position="80,0,0">
+      <attached>
+        <Model position="0,0,0" scale=1 mesh="cube.mesh" />
+      </attached>
+    </StaticEntity-->
+
+    <MovableEntity
+     name            = "blubb"
+     position        = "-150, 20, -500"
+     collisionType   = "kinematic"
+     mass            = 10000
+     velocity        = "30, 0, 0"
+    >
+      <attached>
+        <Model name = "moedeli" position="0,0,0" scale=20 mesh="sphere.mesh" />
+        <StaticEntity name="hahaha" position="0,0,0" collisionType="static">
+          <collisionShapes>
+            <SphereCollisionShape name="firstSphere" radius=20/>
+          </collisionShapes>
+        </StaticEntity>
+      </attached>
+
+      <!--attached>
+        <SphereCollisionShape name = "secondSphere" radius=0.4 position="1,1,1"/>
+        <CompoundCollisionShape position="4,4,4">
+          <SphereCollisionShape name = "thirdSphere" radius=1.0/>
+        </CompoundCollisionShape>
+      </attached-->
+    </MovableEntity>
+
+    <MovableEntity
+     name            = "blubb2"
+     position        = "150, 30, -500"
+     collisionType   = "dynamic"
+     mass            = 10
+     velocity        = "-30, 0, 0"
+    >
+      <attached>
+        <Model position="0,0,0" scale=20 mesh="sphere.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape name = "secondSphere" radius=20 position="0,0,0"/>
+      </collisionShapes>
+    </MovableEntity>
+
+    <StaticEntity
+     name            = "blubbStatic"
+     position        = "0, 15, -500"
+     collisionType   = "Static"
+     mass            = 10
+    >
+      <attached>
+        <Model position="0,0,0" scale=20 mesh="sphere.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape name = "secondSphere" radius=20 position="0,0,0"/>
+      </collisionShapes>
+    </StaticEntity>
+
+    <!--SpawnPoint position="0,   0,  100"           spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0,   0, -700" yaw  =180 spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0, 300, -300" pitch=-90 spawnclass=SpaceShip pawndesign=spaceshipassff /-->
+
+    <MovableEntity
+     name            = "apple1"
+     position        = "-150, 80, -500"
+     collisionType   = "dynamic"
+     mass            = 10
+     velocity        = "30, 0, 0"
+    >
+      <attached>
+        <Model position="0,0,0" scale=20 mesh="sphere.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape name = "secondSphere" radius=20 position="0,0,0"/>
+      </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity
+     name            = "apple2"
+     position        = "50, 80, -500"
+     collisionType   = "dynamic"
+     mass            = 10
+     velocity        = "-30, 0, 0"
+    >
+      <attached>
+        <Model position="0,0,0" scale=20 mesh="sphere.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape name = "secondSphere" radius=20 position="0,0,0"/>
+        <SphereCollisionShape name = "secondSphere" radius=20 position="1,0,0"/>
+      </collisionShapes>
+    </MovableEntity>
+
+    <MovableEntity
+     name            = "apple3"
+     position        = "150, 80, -500"
+     collisionType   = "dynamic"
+     mass            = 10
+     velocity        = "-30, 0, 0"
+    >
+      <attached>
+        <Model position="0,0,0" scale=20 mesh="sphere.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape name = "secondSphere" radius=20 position="0,0,0"/>
+      </collisionShapes>
+    </MovableEntity>
+
+    <!--MovableEntity scale=1.5 position="0,0,-300" velocity="0,0,0" rotationaxis="0,1,0" rotationrate=90>
+      <events>
+        <activity>
+          <DistanceTrigger position="0,0,-300" distance=50 target="ControllableEntity" invert=1 />
+        </activity>
+      </events>
+      <attached>
+        <Model position="0,0,0" scale=10 mesh="ast1.mesh" />
+        <StaticEntity position="0,0,100">
+          <attached>
+            <Model position="0,0,0" scale=6 mesh="ast1.mesh" />
+            <MovableEntity position="0,0,0" velocity="0,0,0" rotationaxis="0,0,1" rotationrate=500>
+              <attached>
+                <Model position="0,35,0" scale=2 mesh="ast1.mesh" />
+                <Model position="0,-35,0" scale=2 mesh="ast1.mesh" />
+                <Model position="35,0,0" scale=2 mesh="ast1.mesh">
+                  <attached>
+                    <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+                  </attached>
+                </Model>
+                <Model position="-35,0,0" scale=2 mesh="ast1.mesh">
+                  <attached>
+                    <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+                  </attached>
+                </Model>
+              </attached>
+            </MovableEntity>
+          </attached>
+        </StaticEntity>
+        <MovableEntity position="0,0,-100" velocity="0,0,0" rotationaxis="0,1,0" rotationrate=200>
+          <attached>
+            <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+            <Model position="0,0,0" scale=6 mesh="ast1.mesh" />
+            <Model position="0,0,-50" scale=3 mesh="ast1.mesh" />
+            <Model position="0,0,50" scale=3 mesh="ast1.mesh" />
+          </attached>
+        </MovableEntity>
+      </attached>
+    </MovableEntity-->
+
+
+    <!--ParticleSpawner position="-500,0,-200" source="Orxonox/BigExplosion1part1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-300" source="Orxonox/BigExplosion1part1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-400" source="Orxonox/BigExplosion1part1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-500" source="Orxonox/BigExplosion1part1" lifetime=2.5 loop=1 />
+    <ParticleSpawner position="-500,0,-600" source="Orxonox/BigExplosion1part1" lifetime=2.5 loop=1 /-->
+
+
+    <ParticleSpawner position="0,20,100" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+      <events>
+        <spawn>
+          <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="0,20,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </spawn>
+      </events>
+    </ParticleSpawner>
+
+
+    <!--ParticleEmitter name=fireright position="200,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <DistanceTrigger name=firetrigger1 position="200,0,0" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </ParticleEmitter>
+    <ParticleEmitter name=fireleft position="-200,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <DistanceTrigger name=firetrigger2 position="-200,0,0" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </ParticleEmitter>
+    <ParticleEmitter name=firecenter position="0,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <EventListener event=firetrigger1 />
+          <EventListener event=firetrigger2 />
+        </activity>
+      </events>
+    </ParticleEmitter-->
+
+
+    <!--EventDispatcher>
+      <targets>
+        <EventTarget target=fireright />
+        <EventTarget target=firecenter />
+        <EventTarget target=fireleft />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="0,0,200" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </EventDispatcher-->
+
+
+    <!--Model position="0,50,0" scale=3 mesh="assff.mesh">
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,50,0" distance=50 target="ControllableEntity" invert=1 />
+        </visibility>
+      </events>
+    </Model-->
+
+
+    <Model position="0,0,200" scale=10 mesh="ast2.mesh" shadow=true />
+    <!--Model position="0,0,-200" scale=10 mesh="ast1.mesh" shadow=true /-->
+    <Model position="0,200,0" scale=10 mesh="ast3.mesh" shadow=true />
+    <Model position="0,-200,0" scale=10 mesh="ast4.mesh" shadow=true />
+    <Model position="200,0,0" scale=10 mesh="ast5.mesh" shadow=false />
+    <Model position="-200,0,0" scale=10 mesh="ast6.mesh" shadow=false />
+
+    <Model position="1000,-200,0" scale3D="1,100,100" mesh="ast1.mesh" />
+
+    <Model position="0, 0,-100" pitch=-90 roll=-90 scale=4 mesh="assff.mesh" />
+    <!--Model position="0,100,-100" pitch=-90 roll=-90 scale=4 mesh="pirate.mesh" />
+    <Model position="0,300,-100" pitch=-90 roll=-90 scale=4 mesh="spacecruiser.mesh" /-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/planetTest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/planetTest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/planetTest.oxw	(revision 11817)
@@ -0,0 +1,38 @@
+<?lua
+  include("HUDTemplates3.oxo")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+?>
+
+<Level
+ name         = "Sample"
+ description  = "Just a few tests"
+>
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/Starbox"
+  >
+
+    <ParticleSpawner position="0,0,100" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+      <events>
+        <spawn>
+          <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </spawn>
+      </events>
+    </ParticleSpawner>
+
+
+    <Planet position="2500,0,-9000" scale=1000 pitch=-90 mesh="earth.mesh" rotationaxis="0,0,1" rotationrate="0.1" atmospheresize=130.0f imagesize=1024.0f />
+    <Planet position="0,0,-5001" scale=1000 pitch=-90 mesh="iceplanet.mesh" atmosphere="atmosphere1" rotationaxis="1,1,0" rotationrate="1" atmospheresize=224.0f imagesize=1024.0f />
+    <Model position="0, 0,-100" pitch=-90 roll=-90 scale=4 mesh="assff.mesh" />
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/presentationLOD.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/presentationLOD.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/presentationLOD.oxw	(revision 11817)
@@ -0,0 +1,35 @@
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level
+ name         = "Sample"
+ description  = "Just a few tests"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <lodinformation>
+      <MeshLodInformation mesh=ast2.mesh lodQuality=500 />
+  </lodinformation>
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <Model position="0,10,0" scale=3 mesh="ast3.mesh"/>
+    <Model position="0,-10,0" scale=3 mesh="ast2.mesh"/>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/presentationPhysics.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/presentationPhysics.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/presentationPhysics.oxw	(revision 11817)
@@ -0,0 +1,109 @@
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  math.randomseed(344)
+?>
+
+<Level
+ name         = "Physics"
+ description  = "Just a few tests"
+>
+  <Scene
+   ambientlight = "0.8, 0.8, 0.8"
+   skybox       = "Orxonox/skyBoxBasic"
+   gravity      = "0, -10, 0"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <StaticEntity
+     position        = "0,0,0"
+     name            = "floor"
+     collisionType   = "static"
+     friction        = 1
+    >
+      <attached>
+        <Model position="0,0,0" scale=100 mesh="plane.mesh" />
+        <Model position="0,-0.0001,0" roll=180 scale=100 mesh="plane.mesh" />
+      </attached>
+      <collisionShapes>
+        <PlaneCollisionShape planeNormal="0,1,0" planeOffset=0 />
+      </collisionShapes>
+    </StaticEntity>
+
+    <MovableEntity
+     position        = "0,250,500"
+     rotationaxis    = "1, 1, 1"
+     rotationrate    = 360
+     velocity        = "0, 0, -80"
+     name            = "ship"
+     collisionType   = "dynamic"
+     friction        = 0.5
+     mass            = 500
+     restitution     = 0
+    >
+      <attached>
+        <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+        <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+        <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+
+        <!--Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+        <Model position="0,0,0" scale3D="10, 3, 5" mesh="cube.mesh" />
+        <Model position="13,-1.3,0" scale3D="3, 1, 2" mesh="cube.mesh" />
+        <Model position="-13,-1.3,0" scale3D="3, 1, 2" mesh="cube.mesh" />
+        <Model position="0,0,7" scale3D="3, 2, 2" mesh="cube.mesh" />
+        <Model position="0,0.1,-11" scale3D="2.2, 1.8, 6" mesh="cube.mesh" />
+        <Model position="0,0.1,-19" scale3D="1.4, 1, 2" mesh="cube.mesh" /-->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+        <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+        <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+        <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+        <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+        <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+      </collisionShapes>
+    </MovableEntity>
+
+    <?lua
+    for i = -20, 20, 8
+    do
+      for i2 = -20, 20, 8
+      do
+        for i3 = -20, 20, 8
+        do ?>
+        <MovableEntity
+         position="<?lua print(i)?>, <?lua print(i3 + 250)?>, <?lua print(i2) ?>"
+         collisionType = "dynamic"
+         mass = 1
+         restitution = 0
+         friction = 0.5
+        >
+          <attached>
+            <Model position="0,0,0" scale=2 mesh="cube.mesh" />
+          </attached>
+          <collisionShapes>
+            <BoxCollisionShape halfExtents="2, 2, 2" />
+          </collisionShapes>
+        </MovableEntity>
+    <?lua
+        end
+      end
+    end
+    ?>
+
+    <ParticleSpawner position="-100,170,30" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+      <events>
+        <spawn>
+          <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="-100,170,30" spawnclass=SpaceShip pawndesign=spaceshipassff />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </spawn>
+      </events>
+    </ParticleSpawner>
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/princessAeryn.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/princessAeryn.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/princessAeryn.oxw	(revision 11817)
@@ -0,0 +1,312 @@
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+?>
+
+<?lua
+    dofile("includes/CuboidSpaceStation.lua")
+?>
+
+<Level
+ name         = "The Tale of Princess Aeryn"
+ description  = "The Tale of Princess Aeryn"
+>
+    <Scene
+        ambientlight = "0.3, 0.3, 0.3"
+        skybox       = "Orxonox/skyBoxBasic"
+    >
+
+        <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+      <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+        <Template name=turboitem baseclass=Turbo>
+          <Turbo
+            playerclass=SpaceShip
+            duration=15
+          />
+        </Template>
+
+        <ParticleSpawner position="200,0,-500" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+          <events>
+            <spawn>
+              <PickupSpawner position="200,0,-500" distance=50 respawntimer=25 item=turboitem>
+                <attached>
+                  <Model mesh="sphere.mesh" scale=3 />
+                  <Billboard material="Examples/Flare" colour="0.5, 1.0, 0.3" scale=0.5 />
+                </attached>
+              </PickupSpawner>
+            </spawn>
+          </events>
+        </ParticleSpawner>
+
+        <Template name=turboequipment baseclass=Turbo>
+          <Turbo
+            playerclass=SpaceShip
+            duration=0
+          />
+        </Template>
+
+        <ParticleSpawner position="400,0,-1000" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+          <events>
+            <spawn>
+              <PickupSpawner position="400,0,-1000" distance=50 respawntimer=25 item=turboequipment>
+                <attached>
+                  <Model mesh="sphere.mesh" scale=3 />
+                  <Billboard material="Examples/Flare" colour="1.0, 0.5, 0.3" scale=0.5 />
+                </attached>
+              </PickupSpawner>
+            </spawn>
+          </events>
+        </ParticleSpawner>
+
+        <!-- Quest: -->
+        <GlobalQuest id="b80c2c60-e62c-4637-80f8-5aa18dc93b34">
+            <QuestDescription title="The Tale of Princess Aeryn" description="Princess Aeryn has been kidnapped by evil Mr. M and you were just a little too late to save her.\nYou have to find and save her from her captors." failMessage="You cannot fail, how did you?" completeMessage="You did it John. You're a hero. Princess Aeryn however will still not marry you." />
+            <subquests>
+                <GlobalQuest id="43766602-7e2f-4d24-976a-3f9de1474d5b">
+                    <QuestDescription title="Find Aeryn's S.H.O.E.S." description="Oh, the kidnappers must have been in a hurry because they overlooked princess Aeryns S.H.O.E.S. (Super Heavily Organized Escape Ship) hidden in the asteroid field over there.\nFind it and look there for clues to Princess Aeryns whereabouts." completeMessage="You did it, Looking through her stuff you find an odd looking device - Could this be the receiver of Princess Aeryns locator beacon? - But it must be broken, the screen remains blank." />
+                    <complete-effects>
+                        <AddQuest questId="50845552-c8af-4091-947c-76bd850b224e" />
+                    </complete-effects>
+                </GlobalQuest>
+                <GlobalQuest id="50845552-c8af-4091-947c-76bd850b224e">
+                    <QuestDescription title="Repair the receiver." description="There is a space station called 'Serenity Station' near here. An engineer called Nathan Stark who shoud be able to help you lives there." completeMessage="'Yeah Nathan lives here, he'll shurely help you.'\nAnd he does, apparenty the device was just low on batteries so you're now able to locate your beloved Princess Aeryn." />
+                    <hints>
+                        <QuestHint id="b9b10841-b045-4797-b1d3-cfce760e1de6">
+                            <QuestDescription title="The Katratzi Station" description="'We ain't buying!'\n'What do you want?'\n'No there lives no Nathan here.'\n'Fuck off.''" />
+                        </QuestHint>
+                        <QuestHint id="1ee785f8-b71d-4b51-b080-42cec5be8e3c">
+                            <QuestDescription title="The Pegasus Station" description="'Hello friend.'\n'How can we help you?'\n'A Mr. Stark you say? Sorry no man with such a name lives here.'" />
+                        </QuestHint>
+                    </hints>
+                    <complete-effects>
+                        <AddQuest questId="97628524-b243-492c-b7b6-498f325b21d4" />
+                    </complete-effects>
+                </GlobalQuest>
+                <GlobalQuest id="97628524-b243-492c-b7b6-498f325b21d4">
+                    <QuestDescription title="Follow the dots" description="Just follow the dots, they'll lead you right to her." completeMessage="You found Princess Aeryn. Her captors give up at the shere sight ou you." />
+                    <complete-effects>
+                        <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+                    </complete-effects>
+                </GlobalQuest>
+            </subquests>
+        </GlobalQuest>
+
+        <!-- Create spaceship spawner: -->
+        <ParticleSpawner position="0,0,100" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+          <events>
+            <spawn>
+              <EventTrigger delay=1>
+                <events>
+                  <trigger>
+                    <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+                  </trigger>
+                </events>
+              </EventTrigger>
+            </spawn>
+          </events>
+          <attached>
+            <QuestEffectBeacon position="0,0,0" times=1>
+                <effects>
+                    <AddQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+                    <AddQuest questId="43766602-7e2f-4d24-976a-3f9de1474d5b" />
+                </effects>
+                <events>
+                    <execute>
+                        <EventListener event=questbeacon1 />
+                    </execute>
+                </events>
+                <attached>
+                    <DistanceTrigger name=questbeacon1 position="0,0,0" distance=10 target="ControllableEntity" />
+                </attached>
+            </QuestEffectBeacon>
+          </attached>
+        </ParticleSpawner>
+
+        <!-- Create world -->
+
+            <!-- Kidnapper flying away -->
+            <MovableEntity position="200,0,0" velocity="-140,0,-140" yaw=45>
+                <attached>
+                    <Model position="0,0,0" scale=4 yaw=180 pitch=-90 roll=-90 mesh="pirate.mesh" />
+                    <ParticleSpawner position="0,0,10" source="Orxonox/fire3" lifetime=2.0 loop=0 autostart=1 />
+                    <QuestEffectBeacon position="0,0,0" times=1 active=false name=trail >
+                        <effects>
+                            <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+                        </effects>
+                        <events>
+                            <execute>
+                                <EventListener event=questbeacon7 />
+                            </execute>
+                        </events>
+                        <attached>
+                            <DistanceTrigger name=questbeacon7 position="0,0,0" distance=10 target="ControllableEntity" />
+                        </attached>
+                    </QuestEffectBeacon>
+                </attached>
+            </MovableEntity>
+
+            <!-- Asteroid field -->
+            <StaticEntity position="-500,0,-3000">
+                <attached>
+                    <?lua
+                        for i = 1, 200
+                        do ?>
+                        <MovableEntity position="<?lua print(math.random() * 2000 - 1000)?>, <?lua print(math.random() * 2000 - 1000) ?>, <?lua print(math.random() * 2000 - 1000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.abs(math.random() * 30 -10)) ?>">
+                            <attached>
+                                <Model scale="<?lua print(math.random() * 50) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+                            </attached>
+                        </MovableEntity>
+                    <?lua
+                        end
+                    ?>
+                    <!-- S.H.O.E.S -->
+                    <StaticEntity position="-300,0,0">
+                        <attached>
+                            <Model position="0,0,0" scale=4 yaw=180 pitch=-90 roll=-90 mesh="assff.mesh" />
+                            <QuestEffectBeacon position="0,0,0" times=-1>
+                                <effects>
+                                    <CompleteQuest questId="43766602-7e2f-4d24-976a-3f9de1474d5b" />
+                                </effects>
+                                <events>
+                                    <execute>
+                                        <EventListener event=questbeacon2 />
+                                    </execute>
+                                </events>
+                                <attached>
+                                    <DistanceTrigger name=questbeacon2 position="0,0,0" distance=50 target="ControllableEntity" />
+                                </attached>
+                            </QuestEffectBeacon>
+                        </attached>
+                    </StaticEntity>
+                </attached>
+            </StaticEntity>
+
+
+
+            <!-- Spacestations -->
+
+            <!-- Serenity Station -->
+            <StaticEntity scale=1 position="0,0,5000" yaw=30>
+                <attached>
+                    <?lua
+                        createSpaceStationPar(65461,2,1,2,1,2,1,100)
+                    ?>
+                    <QuestEffectBeacon position="0,450,0" times=1>
+                        <effects>
+                            <CompleteQuest questId="50845552-c8af-4091-947c-76bd850b224e" />
+                        </effects>
+                        <events>
+                            <execute>
+                                <EventListener event=questbeacon3 />
+                            </execute>
+                        </events>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1.0,1.0,0" material="Examples/Flare" />
+                            <DistanceTrigger name=questbeacon3 position="0,0,0" distance=100 target="ControllableEntity" />
+                        </attached>
+                    </QuestEffectBeacon>
+                </attached>
+            </StaticEntity>
+
+            <!-- Katratzi Station -->
+            <StaticEntity scale=1 position="0,5000,300" yaw=60>
+                <attached>
+                    <?lua
+                        createSpaceStationPar(9851,2,1,2,1,2,1,100)
+                    ?>
+                    <QuestEffectBeacon position="0,450,0" times=1>
+                        <effects>
+                            <AddQuestHint hintId="b9b10841-b045-4797-b1d3-cfce760e1de6" />
+                        </effects>
+                        <events>
+                            <execute>
+                                <EventListener event=questbeacon4 />
+                            </execute>
+                        </events>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1.0,1.0,0" material="Examples/Flare" />
+                            <DistanceTrigger name=questbeacon4 position="0,0,0" distance=100 target="ControllableEntity" />
+                        </attached>
+                    </QuestEffectBeacon>
+                </attached>
+            </StaticEntity>
+
+            <!-- Pegasus Station -->
+            <StaticEntity scale=1 position="-5000,100,1000" roll=30>
+                <attached>
+                    <?lua
+                        createSpaceStationPar(3574,2,1,2,1,2,1,100)
+                    ?>
+                    <QuestEffectBeacon position="200,450,0" times=1>
+                        <effects>
+                            <AddQuestHint hintId="1ee785f8-b71d-4b51-b080-42cec5be8e3c" />
+                        </effects>
+                        <events>
+                            <execute>
+                                <EventListener event=questbeacon5 />
+                            </execute>
+                        </events>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1.0,1.0,0" material="Examples/Flare" />
+                            <DistanceTrigger name=questbeacon5 position="0,0,0" distance=100 target="ControllableEntity" />
+                        </attached>
+                    </QuestEffectBeacon>
+                </attached>
+            </StaticEntity>
+
+            <!-- Trail -->
+            <EventDispatcher>
+                <targets>
+                    <EventTarget target=trail />
+                </targets>
+                <events>
+                    <visibility>
+                        <QuestListener questId="50845552-c8af-4091-947c-76bd850b224e" mode="complete" />
+                    </visibility>
+                    <activity>
+                        <QuestListener questId="50845552-c8af-4091-947c-76bd850b224e" mode="complete" />
+                    </activity>
+                </events>
+            </EventDispatcher>
+
+            <?lua
+                for i = 1, 25
+                do
+            ?>
+                <Billboard position="<?lua print(i*5000/25) ?>,<?lua print(450+i*(5000-450)/25) ?>,5000" colour="1.0,0,0" material="Examples/Flare" name=trail visible=false/>
+            <?lua
+                end
+            ?>
+
+            <!-- Hideout -->
+            <StaticEntity position="5000,5000,5000" >
+                <attached>
+                    <Model scale="100" mesh="ast2.mesh" shadow=false />
+                </attached>
+            </StaticEntity>
+
+            <StaticEntity position="5400,5400,5000" visible=false name=trail >
+                <attached>
+                    <Model position="0,0,0" scale=4 yaw=180 pitch=-90 roll=-90 mesh="pirate.mesh" visible=false name=trail />
+                    <QuestEffectBeacon position="0,0,0" times=1 active=false name=trail >
+                        <effects>
+                            <CompleteQuest questId="97628524-b243-492c-b7b6-498f325b21d4" />
+                        </effects>
+                        <events>
+                            <execute>
+                                <EventListener event=questbeacon6 />
+                            </execute>
+                        </events>
+                        <attached>
+                            <DistanceTrigger name=questbeacon6 position="0,0,0" distance=100 target="ControllableEntity" />
+                        </attached>
+                    </QuestEffectBeacon>
+                </attached>
+            </StaticEntity>
+
+    </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/old/questSystem.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/questSystem.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/questSystem.oxw	(revision 11817)
@@ -0,0 +1,111 @@
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+?>
+
+<Level
+ name         = "Questsystem"
+ description  = "Just a few tests"
+>
+    <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+    >
+
+        <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+        <GlobalQuest id="b80c2c60-e62c-4637-80f8-5aa18dc93b34">
+            <QuestDescription title="The Main QUest" description="This is the main quest hooray. Solve it!" failMessage="You fail. Looser." completeMessage="You Win." />
+            <hints>
+                <QuestHint id="022a859d-08dd-4eac-a085-c28c29c06d48">
+                    <QuestDescription title="The super Hint." description="Be proud of yourself." />
+                </QuestHint>
+            </hints>
+        </GlobalQuest>
+
+        <ParticleSpawner position="0,0,100" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+            <events>
+                <spawn>
+                    <EventTrigger delay=1>
+                        <events>
+                            <trigger>
+                                <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                </spawn>
+            </events>
+        </ParticleSpawner>
+
+        <QuestEffectBeacon position="0,0,100" times=-1>
+            <effects>
+                <AddQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt1 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt1 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="-100,0,0" times=-1>
+            <effects>
+                <FailQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt2 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,0,0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt2 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="100,0,0" times=-1>
+            <effects>
+                <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt3 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,1.0,0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt3 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="0,100,0" times=-1>
+            <effects>
+                <AddQuestHint hintId="022a859d-08dd-4eac-a085-c28c29c06d48" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt4 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,0,1.0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt4 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <ParticleEmitter name=firecenter position="0,0,0" source="Orxonox/fire3" active=false>
+            <events>
+                <activity>
+                    <QuestListener questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" mode="complete" />
+                </activity>
+            </events>
+        </ParticleEmitter>
+
+    </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/old/sample4.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/sample4.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/sample4.oxw	(revision 11817)
@@ -0,0 +1,160 @@
+<?lua
+  include("HUDTemplates3.oxo")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+?>
+
+<Level
+ name         = "Sample"
+ description  = "Just a few tests"
+>
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/Starbox"
+  >
+    <!--SpawnPoint position="0,   0,  100"           spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0,   0, -700" yaw  =180 spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0, 300, -300" pitch=-90 spawnclass=SpaceShip pawndesign=spaceshipassff /-->
+
+    <MovableEntity position="-300,200,-800" velocity="5,0,0" rotationaxis="1,0,0" rotationrate=0>
+      <attached>
+        <Model position="0,0,0" scale=10 mesh="satellite.mesh" />
+        <MovableEntity position="-4,0,0" velocity="0,0,0" rotationaxis="0,0,1" rotationrate=50>
+          <attached>
+            <Model position="4,0,0" scale=10 mesh="satellitedish.mesh"/>
+          </attached>
+        </MovableEntity>
+        <ParticleEmitter pitch=-135 roll=30 position="-14, 3.5,-2.5" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+        <ParticleEmitter pitch=135 roll=30 position="-14, 3.5,-9" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+        <ParticleEmitter pitch=-45 roll=30 position="-14,-3.5,-2.5" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+        <ParticleEmitter pitch=45 roll=30 position="-14,-3.5,-9" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+      </attached>
+    </MovableEntity>
+
+    <MovableEntity scale=1.5 position="0,0,-300" velocity="0,0,0" rotationaxis="0,1,0" rotationrate=90>
+      <events>
+        <activity>
+          <DistanceTrigger position="0,0,-300" distance=50 target="ControllableEntity" invert=1 />
+        </activity>
+      </events>
+      <attached>
+        <Model position="0,0,0" scale=10 mesh="ast1.mesh" />
+        <PositionableEntity position="0,0,100">
+          <attached>
+            <Model position="0,0,0" scale=6 mesh="ast1.mesh" />
+            <MovableEntity position="0,0,0" velocity="0,0,0" rotationaxis="0,0,1" rotationrate=500>
+              <attached>
+                <Model position="0,35,0" scale=2 mesh="ast1.mesh" />
+                <Model position="0,-35,0" scale=2 mesh="ast1.mesh" />
+                <Model position="35,0,0" scale=2 mesh="ast1.mesh">
+                  <attached>
+                    <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+                  </attached>
+                </Model>
+                <Model position="-35,0,0" scale=2 mesh="ast1.mesh">
+                  <attached>
+                    <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+                  </attached>
+                </Model>
+              </attached>
+            </MovableEntity>
+          </attached>
+        </PositionableEntity>
+        <MovableEntity position="0,0,-100" velocity="0,0,0" rotationaxis="0,1,0" rotationrate=200>
+          <attached>
+            <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+            <Model position="0,0,0" scale=6 mesh="ast1.mesh" />
+            <Model position="0,0,-50" scale=3 mesh="ast1.mesh" />
+            <Model position="0,0,50" scale=3 mesh="ast1.mesh" />
+          </attached>
+        </MovableEntity>
+      </attached>
+    </MovableEntity>
+
+
+    <ParticleSpawner position="-500,0,-200" source="Orxonox/BigExplosion1part1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-300" source="Orxonox/BigExplosion1part1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-400" source="Orxonox/BigExplosion1part1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-500" source="Orxonox/BigExplosion1part1" lifetime=2.5 loop=1 />
+    <ParticleSpawner position="-500,0,-600" source="Orxonox/BigExplosion1part1" lifetime=2.5 loop=1 />
+
+
+    <ParticleSpawner position="0,0,100" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+      <events>
+        <spawn>
+          <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </spawn>
+      </events>
+    </ParticleSpawner>
+
+
+    <ParticleEmitter name=fireright position="200,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <DistanceTrigger name=firetrigger1 position="200,0,0" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </ParticleEmitter>
+    <ParticleEmitter name=fireleft position="-200,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <DistanceTrigger name=firetrigger2 position="-200,0,0" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </ParticleEmitter>
+    <ParticleEmitter name=firecenter position="0,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <EventListener event=firetrigger1 />
+          <EventListener event=firetrigger2 />
+        </activity>
+      </events>
+    </ParticleEmitter>
+
+
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=fireright />
+        <EventTarget target=firecenter />
+        <EventTarget target=fireleft />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="0,0,200" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+
+    <Model position="0,50,0" scale=3 mesh="assff.mesh">
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,50,0" distance=50 target="ControllableEntity" invert=1 />
+        </visibility>
+      </events>
+    </Model>
+
+
+    <Model position="0,0,200" scale=10 mesh="ast2.mesh" shadow=true />
+    <!--Model position="0,0,-200" scale=10 mesh="ast1.mesh" shadow=true /-->
+    <Model position="0,200,0" scale=10 mesh="ast3.mesh" shadow=true />
+    <Model position="0,-200,0" scale=10 mesh="ast4.mesh" shadow=true />
+    <Model position="200,0,0" scale=10 mesh="ast5.mesh" shadow=false />
+    <Model position="-200,0,0" scale=10 mesh="ast6.mesh" shadow=false />
+
+    <Model position="1000,-200,0" scale3D="1,100,100" mesh="ast1.mesh" />
+
+    <Model position="0, 0,-100" pitch=-90 roll=-90 scale=4 mesh="assff.mesh" />
+    <!--Model position="0,100,-100" pitch=-90 roll=-90 scale=4 mesh="pirate.mesh" />
+    <Model position="0,300,-100" pitch=-90 roll=-90 scale=4 mesh="spacecruiser.mesh" /-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/old/spaceshipTemplatesPhysics.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/spaceshipTemplatesPhysics.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/spaceshipTemplatesPhysics.oxw	(revision 11817)
@@ -0,0 +1,87 @@
+<Template name=spaceshipassff>
+  <SpaceShip
+   camerapositiontemplate = spaceshipassffcameras
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   primaryThrust     = 100;
+   auxilaryThrust    = 30;
+   rotationThrust    = 10;
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.999
+   name              = "blubbbeliblubb"
+  >
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <!--Light position="0,0,20" diffuse="0,0,1" specular="0,0,1" type=point /-->
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+      <!--ParticleEmitter position="0,0,-100" source="Orxonox/smoke5" /-->
+    </attached>
+    <collisionShapes>
+      <!--SphereCollisionShape position="0,0,0"      radius=20 /-->
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffcameras>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10,40" />
+      <CameraPosition position="0,150,-25" pitch=-90 />
+      <CameraPosition position="0,0,-30" yaw=180 />
+      <CameraPosition position="0,3,-14" yaw=0 />
+      <CameraPosition position="-50,5,-8" yaw=-90 />
+      <CameraPosition position="50,5,-8" yaw=90 />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<!--Template name=spaceshippirate>
+  <SpaceShip
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   maxspeed          = 250
+   maxsecondaryspeed = 50
+   maxrotation       = 100
+   transacc          = 200
+   rotacc            = 140
+   transdamp         = 75
+  >
+    <attached>
+      <Model position="0,-10,-45" yaw=90 pitch=-90 roll=0 scale=4 mesh="pirate.mesh" />
+    </attached>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipspacecruiser>
+  <SpaceShip
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   maxspeed          = 250
+   maxsecondaryspeed = 50
+   maxrotation       = 100
+   transacc          = 200
+   rotacc            = 140
+   transdamp         = 75
+  >
+    <attached>
+      <Model position="8,-30,-120" yaw=90 pitch=-90 roll=0 scale=4 mesh="spacecruiser.mesh" />
+    </attached>
+  </SpaceShip>
+</Template-->
Index: /code/branches/RacingBots_FS18/data/levels/old/tutorialHS08.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/old/tutorialHS08.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/old/tutorialHS08.oxw	(revision 11817)
@@ -0,0 +1,26 @@
+<Ambient colourvalue="0.8, 0.8, 0.8" />
+<Skybox src="Orxonox/Starbox" />
+
+<!-- This is your own space ship. The complicated XML values are not important -->
+<TutorialShip
+    camera="true" position="0,0,0" scale="10" yawpitchroll="0,0,0" mesh="assff.mesh" maxSpeed="500" maxSideAndBackSpeed="50" maxRotation="1.0" transAcc="200" rotAcc="3.0" transDamp="75" rotDamp="1.0"
+
+SpecialEffects="true"
+
+/>
+
+<!-- A few models flying around -->
+<Model position="2000,0,0" scale="10" mesh="tomato.mesh" yawpitchroll="-40,30,0" rotationAxis="1,0,0" rotationRate="-30"/>
+<Model position="0,2000,0" scale="10" mesh="tomato.mesh" yawpitchroll="-50,60,0" rotationAxis="1,0,0" rotationRate="-30"/>
+<Model position="0,0,2000" scale="10" mesh="tomato.mesh" yawpitchroll="-50,-30,0" rotationAxis="1,0,0" rotationRate="-30"/>
+<Model position="10000,16000,0" scale="100" mesh="DuBall1.mesh"/>
+<Model position="11400,16000,0" scale="60" mesh="DuBall2.mesh"/>
+
+<!-- Embedded lua code (creates random asteroids) -->
+<?lua
+for i = 1, 226, 1
+do ?>
+  <Model position="<?lua print(math.random() * 40000 - 20000)?>, <?lua print(math.random() * 40000 - 20000) ?>, <?lua print(math.random() * 40000 - 20000) ?>" scale="<?lua print(math.random() * 250 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" rotationAxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationRate="<?lua print(math.random() * 30 + 15) ?>" />
+<?lua
+end
+?>
Index: /code/branches/RacingBots_FS18/data/levels/pickups.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/pickups.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/pickups.oxw	(revision 11817)
@@ -0,0 +1,178 @@
+<!-- -->
+<LevelInfo
+ name = "Pickups showcase"
+ description = "Level to test and showcase pickups."
+ tags = "test, showcase"
+ screenshot = "pickupsshowcase.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <!-- Boost pickup -->
+    
+    <PickupSpawner pickup=smallboostpickup position="-25,-125,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=mediumboostpickup position="0,-125,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=hugeboostpickup position="25,-125,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+    <!-- DamageBoost pickup -->
+    
+    <PickupSpawner pickup=smalldamageboostpickup position="-25,-100,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=mediumdamageboostpickup position="0,-100,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=hugedamageboostpickup position="25,-100,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+    <!-- Munition pickups -->
+
+    <PickupSpawner pickup=smallmunitionpickup position="-25,-75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=mediummunitionpickup position="0,-75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=hugemunitionpickup position="25,-75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />    
+
+    <!-- Shrink pickup -->
+
+    <PickupSpawner pickup=smallshrinkpickup position="-25,-50,-125" triggerDistance="20" respawnTime="60" maxSpawnedItems="5" />
+    <PickupSpawner pickup=mediumshrinkpickup position="0,-50,-125" triggerDistance="20" respawnTime="60" maxSpawnedItems="5" />
+    <PickupSpawner pickup=hugeshrinkpickup position="25,-50,-125" triggerDistance="20" respawnTime="60" maxSpawnedItems="5" />    
+
+    <!-- Shield pickups -->
+
+    <PickupSpawner pickup=smallshieldpickup position="-25,-25,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=mediumshieldpickup position="0,-25,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=hugeshieldpickup position="25,-25,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- Health pickups -->
+
+    <PickupSpawner pickup=smallhealthpickup position="-25,0,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=mediumhealthpickup position="0,0,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=hugehealthpickup position="25,0,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    <PickupSpawner pickup=crazyhealthpickup position="50,0,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+    <!-- Speed pickups -->
+
+    <PickupSpawner pickup=smallspeedpickup position="-25,25,-125" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" />
+    <PickupSpawner pickup=mediumspeedpickup position="0,25,-125" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" />
+    <PickupSpawner pickup=hugespeedpickup position="25,25,-125" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" />
+    <PickupSpawner pickup=smalljumppickup position="50,25,-125" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" />
+
+    <!-- Invisible pickups -->
+
+    <PickupSpawner pickup=smallinvisiblepickup position="-25,50,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=mediuminvisiblepickup position="0,50,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=hugeinvisiblepickup position="25,50,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- Meta pickups -->
+    
+    <PickupSpawner pickup=usemetapickup position="-25,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=dropmetapickup position="0,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=destroymetapickup position="25,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+    <PickupSpawner pickup=destroycarriermetapickup position="50,75,-125" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- Pickup Collection pickups -->
+
+    <PickupSpawner pickup=triplehealthspeedinvisibilitypickup position="-50,25,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    
+    <!-- Drone pickup -->
+    
+    <PickupSpawner pickup=dronepickup position="-25,100,-125" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+    
+    <!-- Other pickups -->
+
+    <!-- PickupRepresentation for the pickup below, since it is not a standard pickup provided by pickups.oxi -->
+    <PickupRepresentation
+      name = "ContinousHealth"
+      pickupName = "Continous Health Pack"
+      pickupDescription = "While useing adds a medium amout of health to the ship."
+      spawnerTemplate = "mediumhealthpickupRepresentation"
+      inventoryRepresentation = "MediumHealth"
+    />
+
+    <Template name=continuoushealthpickup baseclass=HealthPickup>
+      <HealthPickup representation="ContinousHealth" health=500 activationType=immediate healthRate=10 durationType=continuous />
+    </Template>
+    
+    <PickupSpawner pickup=continuoushealthpickup position="-50,0,-125" respawnTime="60" triggerDistance="20" maxSpawnedItems="5" />
+    
+    <!-- @Objects: 4 boxes (uncontrolled pawns) -->
+    <Pawn team=1 health=30 position="0,100,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box RVName = "Box 4" >
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn team=1 health=30 position="0,200,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box RVName = "Box 3">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+           <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn health=30 position="0,300,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box team=1 RVName = "Box 2">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+           <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+
+    <Pawn health=30 position="0,400,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box team=1 RVName = "Box 1">
+        <events>
+          <visibility>
+            <EventListener event="flying4" />
+          </visibility>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        </attached>
+        <collisionShapes>
+           <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        </collisionShapes>
+    </Pawn>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/pirateAttack.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/pirateAttack.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/pirateAttack.oxw	(revision 11817)
@@ -0,0 +1,564 @@
+<LevelInfo
+ name = "Pirate Attack"
+ description = "Dani's Testlevel"
+ tags = "mission"
+ screenshot = "pirateattack.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Template name=spaceshipassffplayer defaults=0>
+  <SpaceShip template=spaceshipassff name=player>
+    <attached>
+    <DistanceTriggerBeacon name=Me/>
+    </attached>
+  </SpaceShip>
+</Template>
+
+<?lua
+    dofile("includes/CuboidSpaceStation.lua")
+?>
+
+<WorldAmbientSound source="Mars.ogg" looping="true" playOnLoad="true" />
+    
+<Level
+name="Dani's Testlevel"
+description="Erste Versuche mit den Quests"
+gametype=Mission
+>
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+    <Scene
+        ambientlight = "0.3, 0.3, 0.3"
+        skybox       = "Orxonox/skyBoxBasic"
+    >
+
+        <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+        <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+          <GlobalQuest id="dbd02b4c-ab7c-46fd-bdaf-fd4c19ac1551">
+        <QuestDescription title="Fight for freedom"
+                    description="Just a few hours ago, a group of pirates attacked an killed all your  squad members. Now you are very angry and you want to take revenge. Find the pirates and kill them!"
+                    failmessage="You are a loser, now the whole universe will be controlled by the pirates!"
+                    completeMessage="Yeah, you did it! You,ve eliminated the enemies. But why attacked them the Humans here? For tousands of years, there was peace in this sun system.
+                                You have to find out what happened exactly and why the pirates attacked..."/>
+            <subquests>
+                <GlobalQuest id="3159b4d4-bc86-4190-ba1d-4530668dfe31">
+                    <QuestDescription title="The stolen stick..."
+                    description="Now you can see it: There are more pirates... the pirates you killed were only a small part of the whole fleet. You received a message from your Headquarter: The pirates have stolen
+                            a very important memory stick with secret infos (military locations etc.), the holy stick. You must get it back! Otherwise the humans are in great danger..."
+                    failmessage=""
+                    completeMessage="Unbelievable, you annihilated all pirates and got the stolen memory stick.
+                                But wait... this isn't the memory stick you looked for, this stick is one from a pirate... anyway, it's helpful: There is a map saved on it, which leads you to a pirate - base. Perhaps you'll find more
+                                about their plans there..."/>
+                </GlobalQuest>
+                <GlobalQuest id="8d8ed3a6-74a6-4491-9172-26155cff151d">
+                    <QuestDescription title="Find the Base"
+                    description="Now you are in possession of the map and it should be easy to find the base. Because you are a Member of an elite-fight-squad, your ship has been pimped before you started your mission.
+                        They installed a very modern navigation system, which leads you precisely to your desired destination. Use it to find the pirate - base."
+                    failmessage=""
+                    completeMessage="The navigation system worked very well and now you should be near a pirate -base." />
+                    <hints>
+                        <QuestHint id="965101b3-26ce-4fcf-bc71-17cc2a87d2e9">
+                        <QuestDescription title="3 Ways?"
+                        description="The different ways leads you to the possible positions where the base could be. The problem is that the map is encrypted and your on board system is not
+                                able to decrypt it exactly. Therefore you have to try 3 possible ways...Tha base is Huge, but it could be that it's invisible when ou are in longer distance (some Big Ships
+                                have a special shield aroud them which make them invisible at longer range)."/>
+                        </QuestHint>
+                    </hints>
+                </GlobalQuest>
+                <GlobalQuest  id="9930a598-98bc-4ff8-8cc0-31311a6ccaaa">
+                    <QuestDescription title=":(" description="Here isn't the base you look for... try another way."/>
+                </GlobalQuest>
+                <GlobalQuest id="9930a598-98bc-4ff8-8cc0-31311a6ccaab">
+                    <QuestDescription title=":(" description="Here isn't the base you look for... try another way."/>
+                </GlobalQuest>
+                <GlobalQuest id="8a62408b-c47b-4e02-bd3d-06bb9ec0b363">
+                    <QuestDescription title="The Base"
+                    description="Yeah, you found the Base... now let's check if there is the important holy stick..."
+                    failmessage=""
+                    completeMessage="There it is, the Holy stick. Yes, you're right. It looks like a rocket because there are so many rockets in the universe, that it's nearly impossible to find the holy stick between them.
+                                Anyway, the pirates found the stick... another part which is confusing. Why did they know where the holy stick is? Perpaps they know more about the humans than you think."/>
+                </GlobalQuest>
+                <GlobalQuest id="85380d05-b791-45d1-82e9-01f0bc930367">
+                    <QuestDescription title="Find out more about the pirates"
+                    description= "Now, the Holy stick is back in your possession. Your new mission is to get some more infos about the pirates. You've got an info about a near mining company
+                    which delivers Hydrogen out of special asteroids. Hydrogen is a very rare ressource on earth and is delivered by a few great mining companys. There is no oil anymore on earth since many years.
+                    Therefore hydrogen became the most important energy source for all humans.
+                    But back to your mission. The mining company has it's own security. Ask some of their security staff if they know more about the pirates... it's actually your only hope to get more infos.
+                    You'll find the mining company at the near planet with the asteroid belt."
+                    failmessage=""
+                    completeMessage=""/>
+                </GlobalQuest>
+                <GlobalQuest id="d8afe2eb-b3b9-4c98-8ed7-cc1a2a8e3734">
+                    <QuestDescription title="Interesting..."
+                    description= "You're very lucky. The first security man has interesting infos about the pirates. He said that they made a few attacks in de last few weeks and they intensified the attacks in the last days...
+                    Shit, they attack one more time. Fight them back!"
+                    failmessage=""
+                    completeMessage=""/>
+                </GlobalQuest>
+            </subquests>
+            <hints>
+                <QuestHint id="2b85f32c-2433-4f1a-bdd4-f24d20c9403c">
+                    <QuestDescription title="Useful to know" description="Pirates like to hide themselves behind asteroids."/>
+                </QuestHint>
+            </hints>
+            <fail-effects>
+            </fail-effects>
+            <complete-effects>
+            </complete-effects>
+        </GlobalQuest>
+    
+          <ParticleSpawner position="0,0,0" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+          <events>
+            <spawn>
+              <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassffplayer name=spawnpoint1 team=0 active=true/>
+              </trigger>
+            </events>
+              </EventTrigger>
+            </spawn>
+          </events>
+          <attached>
+            <QuestEffectBeacon position="0,0,0" times=1>
+            <effects>
+                <AddQuest questId="dbd02b4c-ab7c-46fd-bdaf-fd4c19ac1551" />
+            </effects>
+            <events>
+                <execute>
+                <EventListener event=questbeacon1 />
+                </execute>
+            </events>
+            <attached>
+                <DistanceTrigger name=questbeacon1 position="0,0,0" distance=100 target="Pawn" beaconMode="identify" targetname=Me/>
+            </attached>
+            </QuestEffectBeacon>
+          </attached>
+        </ParticleSpawner>
+    
+        <SpawnPoint position="600,300,-6000" spawnclass=SpaceShip pawndesign=spaceshipassffplayer name=spawnpoint2 active=false/>
+    
+    
+    
+        <!-- Add second Quest-->
+        <QuestEffectBeacon position="250,-300,-1500" times=1>
+                    <attached>
+                        <Billboard position="0,0,0" scale=3 colour="1.0,1.0,0" material="Examples/Flare" />
+                        <DistanceTrigger name=questbeacon2 targetname=Me position="0,0,0" target="Pawn" beaconMode="identify" distance=400 />
+                    </attached>
+                    <effects>
+                        <AddQuest questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" />
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon2 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+    
+        <!-- Hint to first Quest-->
+        <QuestEffectBeacon position="0,0,0" times=1>
+                    <attached>
+                        <DistanceTrigger name=questbeacon3  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me delay="5" />
+                    </attached>
+                    <effects>
+                        <AddQuestHint hintId="2b85f32c-2433-4f1a-bdd4-f24d20c9403c" />
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon3 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+    
+    
+        <!--Pirates killed... navi leads you to possible Base stations-->
+        <QuestEffectBeacon position="600,300,-6000" times=1>
+                    <attached>
+                        <Billboard position="0,0,0" scale=3 colour="0,1.0,0" material="Examples/Flare" />
+                        <DistanceTrigger name=questbeacon4  position="0,0,0" distance=200 target="Pawn" beaconMode="identify" targetname=Me />
+                    </attached>
+    
+                    <effects>
+                        <CompleteQuest questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" />
+                        <AddQuest questId="8d8ed3a6-74a6-4491-9172-26155cff151d" />
+                        <AddQuestHint hintId="965101b3-26ce-4fcf-bc71-17cc2a87d2e9" />
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon4 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+    
+    
+        <!-- Wrong way 1-->
+        <QuestEffectBeacon position="7600,300,-8000" times=1>
+                    <attached>
+                        <DistanceTrigger name=questbeacon5  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me />
+                    </attached>
+                    <effects>
+                        <AddQuest questId="9930a598-98bc-4ff8-8cc0-31311a6ccaaa" />
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon5 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+    
+        <!-- Wrong way 2-->
+        <QuestEffectBeacon position="1600,2300,-10000" times=1>
+                    <attached>
+                        <DistanceTrigger name=questbeacon8  position="0,0,0" distance=300 target="Pawn" beaconMode="identify" targetname=Me />
+                    </attached>
+                    <effects>
+                        <AddQuest questId="9930a598-98bc-4ff8-8cc0-31311a6ccaab" />
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon8 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+    
+        <!-- Base found!-->
+        <QuestEffectBeacon position="4600,5300,-11000" times=1>
+                    <attached>
+                        <DistanceTrigger name=questbeacon6  position="0,0,0" distance=600 target="Pawn" beaconMode="identify" targetname=Me />
+                    </attached>
+                    <effects>
+                        <CompleteQuest questId="8d8ed3a6-74a6-4491-9172-26155cff151d" />
+                        <AddQuest questId="8a62408b-c47b-4e02-bd3d-06bb9ec0b363" />
+                        <CompleteQuest questId="9930a598-98bc-4ff8-8cc0-31311a6ccaaa" />
+                        <CompleteQuest questId="9930a598-98bc-4ff8-8cc0-31311a6ccaab" />
+    
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon6 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+        <!--Stick found-->
+        <QuestEffectBeacon position="4800,5785,-10725" times=1>
+                    <attached>
+                        <DistanceTrigger name=questbeacon7  position="0,0,0" distance=30 target="Pawn" beaconMode="identify" targetname=Me />
+                    </attached>
+                    <effects>
+                        <CompleteQuest questId="8a62408b-c47b-4e02-bd3d-06bb9ec0b363" />
+                        <AddQuest questId="85380d05-b791-45d1-82e9-01f0bc930367" />
+    
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon7 />
+                        </execute>
+                    </events>
+                </QuestEffectBeacon>
+    
+    
+        <!--Security Man found-->
+        <QuestEffectBeacon position="4000,4000,-20000" times=1>
+                    <attached>
+                        <Billboard position="0,0,0" scale=3 colour="0,0,1.0" material="Examples/Flare" />
+                        <DistanceTrigger name=questbeacon9 position="0,0,0" distance=500 target="Pawn" beaconMode="identify" targetname=Me />
+                    </attached>
+                    <effects>
+                        <CompleteQuest questId="85380d05-b791-45d1-82e9-01f0bc930367" />
+                        <AddQuest questId="d8afe2eb-b3b9-4c98-8ed7-cc1a2a8e3734" />
+    
+                    </effects>
+                    <events>
+                        <execute>
+                            <EventListener event=questbeacon9 />
+                        </execute>
+                    </events>
+        </QuestEffectBeacon>
+    
+    <!--Navigation System which shows possiple positions of base-->
+    <EventDispatcher>
+                <targets>
+                    <EventTarget target=Navi />
+                </targets>
+                <events>
+                    <visibility>
+                        <QuestListener questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" mode="complete" />
+                    </visibility>
+                    <activity>
+                        <QuestListener questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" mode="complete" />
+                    </activity>
+                </events>
+            </EventDispatcher>
+
+            <?lua
+                for i = 0, 30
+                do
+            ?>
+        <Billboard position="<?lua print(i*1000/30+600) ?>,<?lua print(i*2000/30+300) ?>,<?lua print(-i*4000/30-6000) ?>" colour="1.0,0,0" scale=1 material="Examples/Flare" name=Navi visible=false/><!--endpos:1600,2300,-10000-->
+        <Billboard position="<?lua print(i*7000/30+600) ?>,<?lua print(i*0/30+300) ?>,<?lua print(-i*2000/30-6000) ?>" colour="0,1.0,0" scale=1 material="Examples/Flare" name=Navi visible=false/><!--endpos:7600,300,-8000-->
+        <Billboard position="<?lua print(i*4000/30+600) ?>,<?lua print(i*5000/30+300) ?>,<?lua print(-i*5000/30-6000) ?>" colour="0,0,1.0" scale=1 material="Examples/Flare" name=Navi visible=false/><!--endpos:4600,5300,-11000-->
+            <?lua
+                end
+            ?>
+    
+    <!--Base&Stick spawn*****************************************************************-->
+    <StaticEntity scale=1 position="4650,5350,-11050" name=base visible=true active=true yaw=60>
+                <attached>
+                    <?lua
+                        createSpaceStationPar(9851,2,1,2,1,2,1,100)
+                    ?>
+                </attached>
+            </StaticEntity>
+    
+    <ParticleSpawner position="4650,5350,-11050" source="Orxonox/explosion1" name=base visible=false active=false loop=0/>
+    <Model position="4800,5785,-10725" scale=3 mesh="rocket.mesh" visible=true active=true name=base />
+    <EventDispatcher>
+                <targets>
+                    <EventTarget target=base />
+             <EventTarget target=navipirate1 />
+              <EventTarget target=navipirate2 />
+                </targets>
+                <events>
+                    <visibility>
+          <EventTrigger invert=true>
+            <events>
+              <trigger>
+                <QuestListener questId="dbd02b4c-ab7c-46fd-bdaf-fd4c19ac1551" mode="start" />
+              </trigger>
+            </events>
+          </EventTrigger>
+                    </visibility>
+                    <activity>
+                <EventTrigger invert=true>
+            <events>
+              <trigger>
+                             <QuestListener questId="dbd02b4c-ab7c-46fd-bdaf-fd4c19ac1551" mode="start" />
+              </trigger>
+            </events>
+          </EventTrigger>
+                    </activity>
+                </events>
+            </EventDispatcher>
+
+    
+    <EventDispatcher>
+                <targets>
+                    <EventTarget target=base />
+                </targets>
+                <events>
+                    <visibility>
+                        <QuestListener questId="8d8ed3a6-74a6-4491-9172-26155cff151d" mode="complete" />
+                    </visibility>
+                    <activity>
+                        <QuestListener questId="8d8ed3a6-74a6-4491-9172-26155cff151d" mode="complete" />
+                    </activity>
+                </events>
+            </EventDispatcher>
+    
+    <!--Base&Stick spawn********end*****************************************************-->
+    
+    <!--Change spawnoint-->
+    <EventDispatcher>
+                <targets>
+                    <EventTarget target=spawnpoint1 />
+                </targets>
+                <events>
+                    <activity>
+                <EventTrigger invert=true>
+            <events>
+              <trigger>
+                             <QuestListener questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" mode="complete" />
+              </trigger>
+            </events>
+          </EventTrigger>
+                    </activity>
+                </events>
+    
+            </EventDispatcher>
+            <EventDispatcher>
+                <targets>
+                    <EventTarget target=spawnpoint2/>
+                </targets>
+                <events>
+                    <activity>
+                             <QuestListener questId="3159b4d4-bc86-4190-ba1d-4530668dfe31" mode="complete" />
+                    </activity>
+                </events>
+            </EventDispatcher>
+    <!--Change spawnoint end-->
+    
+    <!-- pirates -->
+        <?lua
+        for i = 1,1, 1
+        do
+        ?>
+            <SpaceShip position="<?lua print(math.random()*100)?>,<?lua print(math.random()*100)?>,<?lua print(math.random()*100-2000)?>">
+              <templates>
+            <Template link=spaceshippirate />
+              </templates>
+              <controller>
+            <WaypointPatrolController alertnessradius=1000 active=true team=1>
+              <waypoints>
+                <StaticEntity position="0,<?lua print(math.random()*50)?> ,<?lua print(i*50 -2000) ?>" />
+              </waypoints>
+            </WaypointPatrolController>
+              </controller>
+            </SpaceShip>
+        <?lua
+        end
+        ?>
+    
+        <?lua
+        for i = 1,2, 1
+        do
+        ?>
+            <SpaceShip position="600,300,-6000">
+              <templates>
+            <Template link=spaceshippirate />
+              </templates>
+              <controller>
+            <WaypointPatrolController alertnessradius=1000 active=true team=1>
+              <waypoints>
+                <StaticEntity position="600,300,-6000" />
+              </waypoints>
+            </WaypointPatrolController>
+              </controller>
+            </SpaceShip>
+        <?lua
+        end
+        ?>
+    
+    <!-- Pirates at the end of wrong Navi line (get visible when you get near them)-->
+     <SpaceShip position="1600,2300,-10000" active=true visible=true name=navipirate1>
+              <templates>
+            <Template link=spaceshippirate />
+              </templates>
+              <controller>
+            <WaypointPatrolController alertnessradius=1000 name=navipirate1 active=true team=1>
+              <waypoints>
+                <StaticEntity position="1600,2300,-10000" />
+              </waypoints>
+            </WaypointPatrolController>
+              </controller>
+            </SpaceShip>
+    
+    <SpaceShip position="7600,300,-8000" active=true visible=true name=navipirate2>
+              <templates>
+            <Template link=spaceshippirate />
+              </templates>
+              <controller>
+            <WaypointPatrolController alertnessradius=1000 name=navipirate2 active=true team=1>
+              <waypoints>
+                <StaticEntity position="7600,300,-8000" />
+              </waypoints>
+            </WaypointPatrolController>
+              </controller>
+        </SpaceShip>
+    
+    
+    <EventDispatcher>
+                <targets>
+                    <EventTarget target=navipirate1 />
+                </targets>
+                <events>
+                    <visibility>
+                        <QuestListener questId="9930a598-98bc-4ff8-8cc0-31311a6ccaab" mode="start" />
+                    </visibility>
+                    <activity>
+                        <QuestListener questId="9930a598-98bc-4ff8-8cc0-31311a6ccaab" mode="start" />
+                    </activity>
+                </events>
+            </EventDispatcher>
+    
+    <EventDispatcher>
+                <targets>
+                    <EventTarget target=navipirate2 />
+                </targets>
+                <events>
+                    <visibility>
+                        <QuestListener questId="9930a598-98bc-4ff8-8cc0-31311a6ccaaa" mode="start" />
+                    </visibility>
+                    <activity>
+                        <QuestListener questId="9930a598-98bc-4ff8-8cc0-31311a6ccaaa" mode="start" />
+                    </activity>
+                </events>
+            </EventDispatcher>
+    <!-- Pirates at the end of wrong Navi line **** end-->
+    
+    <!--Security man from mining corp.-->
+    <SpaceShip position="4000,4000,-20000">
+              <templates>
+            <Template link=spaceshipassff/>
+              </templates>
+              <controller>
+            <WaypointPatrolController alertnessradius=1000 team=0 active=false>
+              <waypoints>
+                <StaticEntity position="4000,4000,-20000" />
+              </waypoints>
+            </WaypointPatrolController>
+              </controller>
+    </SpaceShip>
+    
+    <!-- Asteroid field-->
+            <StaticEntity position="-400,2000,-7000">
+                <attached>
+                    <?lua
+                        for i = 1, 180
+                        do ?>
+                        <MovableEntity position="<?lua print(math.random() * 10000 -5000)?>, <?lua print(math.random() * 10000-5000) ?>, <?lua print(math.random() * 10000 -7000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.abs(math.random() * 30 -10)) ?>">
+                            <attached>
+                                <Model scale="<?lua print(math.random() * 100) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+                            </attached>
+                        </MovableEntity>
+                    <?lua
+                        end
+                    ?>
+            </attached>
+        </StaticEntity>
+    <!--Planet with asteroid belt-->
+    <Planet mesh="iceplanet.mesh" position="2600,4300,-20000" scale=1000 atmosphere="atmosphere1" atmospheresize=224.0f imagesize=1024.0f/>
+    <StaticEntity position="2600,4300,-20000" collisionType=static>
+          <collisionShapes>
+            <SphereCollisionShape radius="1000" />
+          </collisionShapes>
+                          <attached>
+                <?lua
+                for i = 1, 100
+                do
+                k=(math.random() * 2600 -1300)
+                if math.random()<0.5 then
+                l=(1300^2-k^2)^(0.5)
+                else
+                l=-(1300^2-k^2)^(0.5)
+                end
+                ?>
+    
+                <MovableEntity position="<?lua print(k) ?>,<?lua print(l) ?>, <?lua print(math.random() * 100) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.abs(math.random() * 30 -10)) ?>">
+
+                    <attached>
+                    <Model scale="<?lua print(math.random() * 25) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+                    </attached>
+                </MovableEntity>
+                <?lua
+                end
+                ?>
+                            </attached>
+        </StaticEntity>
+    
+    </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/planets.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/planets.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/planets.oxw	(revision 11817)
@@ -0,0 +1,97 @@
+<LevelInfo
+ name = "Planet Demonstration"
+ description = "Demonstration of Planets"
+ tags = "showcase"
+ screenshot = "planetdemonstration.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/spaceshipHXY.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link="lodtemplate_default" />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxBasic"
+  >
+
+    <WorldAmbientSound
+      ambientSource="AlphaCentauri.ogg"
+      looping="true"
+      playOnLoad="true"
+    />
+    
+    <Light
+      type="directional"
+      position="-10000,-10000,0"
+      direction="0.253, 0.593, -0.765"
+      diffuse="1.0, 0.9, 0.9, 1.0"
+      specular="1.0, 0.9, 0.9, 1.0"
+    />
+
+    <SpawnPoint
+      position="1500,0,0"
+      lookat="0,0,0"
+      spawnclass="SpaceShip"
+      pawndesign="spaceshipHXY"
+    />
+
+    <Planet
+      position="0,0,0"
+      scale="1000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="1000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <Planet
+      position="10000,0,0"
+      scale="100"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="5000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="1000" velocity="-500" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="100" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/pong.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/pong.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/pong.oxw	(revision 11817)
@@ -0,0 +1,240 @@
+<LevelInfo
+ name = "Pong"
+ description = "Pong in space!"
+ tags = "minigame"
+ screenshot = "pong.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("pongHUD.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<Template name=pongbatcameras defaults=0>
+  <PongBat>
+    <camerapositions>
+      <CameraPosition position="0,150,0" pitch=-90 absolute=true />
+      <CameraPosition position="0,50,160" drag=true mouselook=true />
+      <CameraPosition position="0,40,125" drag=true mouselook=true />
+      <CameraPosition position="0,30, 90" drag=true mouselook=true />
+    </camerapositions>
+  </PongBat>
+</Template>
+
+<Template name=pongbat>
+  <PongBat camerapositiontemplate=pongbatcameras>
+    <attached>
+      <Model position="0,0,3" mesh="cube.mesh" scale3D="14,2,2" />
+      <!--Model roll=180 mesh="pongbat.mesh" scale=0.045 /-->
+    </attached>
+  </PongBat>
+</Template>
+
+<Template name=pongball>
+  <PongBall 
+   defScoreSound = "sounds/PlayerWinScore_cut.ogg"
+   defBatSound = "sounds/Button.ogg"
+   defBoundarySound = "sounds/Button.ogg">
+    <attached>
+      <Model mesh="sphere.mesh" scale=2 />
+      <!--Billboard scale=0.2 colour="1.0, 1.0, 0.5" material="Examples/Flare" /-->
+      <Backlight scale=0.2 colour="1.0, 1.0, 0.5" width=7 length=500 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" />
+      <Light type=point diffuse="1.0, 1.0, 0.5" specular="1.0, 1.0, 0.5" attenuation="1200, 1.0, 0.0035, 0.00005" />
+      <ParticleSpawner name=hiteffect position="0,0,0" source="Orxonox/sparks2" lifetime=0.01 autostart=0 mainstate=spawn />
+    </attached>
+    <eventlisteners>
+      <EventTarget target=hiteffect />
+    </eventlisteners>
+  </PongBall>
+</Template>
+
+
+<Level
+ plugins = "pong"
+ gametype = "Pong"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <WorldAmbientSound source="Ganymede.ogg" looping="true" playOnLoad="true"/>
+  <PongBot />
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="991.729, -110.11, 435.404" orientation="0.534038, 0.563456, 0.212168, 0.593553" />
+
+    <MovableEntity rotationrate=5 rotationaxis="0,0,1">
+      <attached>
+        <PongCenterpoint name=pongcenter dimension="200,120" balltemplate=pongball battemplate=pongbat ballspeed=200 ballaccfactor=1.0 batspeed=130 batlength=0.25>
+          <attached>
+            <Model position="0,0,60" mesh="cube.mesh" scale3D="105,1,1" />
+            <Model position="0,0,-60" mesh="cube.mesh" scale3D="105,1,1" />
+
+            <ParticleSpawner name=scoreeffect_right position="120,0, 45" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_right position="120,0, 30" source="Orxonox/BigExplosion1part2" lifetime=3.0 autostart=0 />
+            <ParticleSpawner name=scoreeffect_right position="120,0, 15" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_right position="120,0,  0" source="Orxonox/BigExplosion1part2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_right position="120,0,-15" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_right position="120,0,-30" source="Orxonox/BigExplosion1part2" lifetime=3.0 autostart=0 />
+            <ParticleSpawner name=scoreeffect_right position="120,0,-45" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+
+            <ParticleSpawner name=scoreeffect_left position="-120,0, 45" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_left position="-120,0, 30" source="Orxonox/BigExplosion1part2" lifetime=3.0 autostart=0 />
+            <ParticleSpawner name=scoreeffect_left position="-120,0, 15" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_left position="-120,0,  0" source="Orxonox/BigExplosion1part2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_left position="-120,0,-15" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+            <ParticleSpawner name=scoreeffect_left position="-120,0,-30" source="Orxonox/BigExplosion1part2" lifetime=3.0 autostart=0 />
+            <ParticleSpawner name=scoreeffect_left position="-120,0,-45" source="Orxonox/sparks2" lifetime=0.1 autostart=0 />
+
+<!-- TODO: Create a Pong Score Sound and include it here.
+This WorldSound works, but doesn't make sense, since it is played together with ambient/moodDependedDirectory/Ganymede.ogg -->
+            <!--WorldSound name="scoreSound" position="0,0,0" source="sounds/PongScore_cut.ogg" >
+              <events>
+                <play>
+                  <EventListener event=pongcenter />
+                </play>
+              </events>
+            </WorldSound-->
+
+            <?lua
+              for i = 1, 15, 1 do
+            ?>
+              <ParticleSpawner name=scoreeffect_center position="<?lua print(math.random() * 200 - 100) ?>,0,<?lua print(math.random() * 120 - 60) ?>" source="Orxonox/sparks2" lifetime=0.02 autostart=0 startdelay=<?lua print(math.random() * 0.7) ?> />
+            <?lua end ?>
+
+          </attached>
+        </PongCenterpoint>
+      </attached>
+    </MovableEntity>
+
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=scoreeffect_right />
+        <EventTarget target=scoreeffect_center />
+      </targets>
+      <events>
+        <spawn>
+          <EventFilter>
+            <names>
+              <EventName name=right />
+            </names>
+            <EventListener event=pongcenter />
+          </EventFilter>
+        </spawn>
+      </events>
+    </EventDispatcher>
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=scoreeffect_left />
+        <EventTarget target=scoreeffect_center />
+      </targets>
+      <events>
+        <spawn>
+          <EventFilter>
+            <names>
+              <EventName name=left />
+            </names>
+            <EventListener event=pongcenter />
+          </EventFilter>
+        </spawn>
+      </events>
+    </EventDispatcher>
+
+    <?lua
+      dofile("includes/CuboidSpaceStation.lua")
+    ?>
+
+    <StaticEntity pitch=15>
+      <attached>
+        <MovableEntity rotationrate="-4.15786" rotationaxis="0,0,1">
+          <attached>
+            <StaticEntity position="-2500,0,0" yaw=90 pitch=90>
+              <attached>
+                <?lua
+                  createSpaceStationPar(0,2,1,2,1,4,1,50)
+                ?>
+              </attached>
+            </StaticEntity>
+          </attached>
+        </MovableEntity>
+      </attached>
+    </StaticEntity>
+
+    <StaticEntity position="0,1200,-200" yaw=50 pitch=60 roll=45>
+      <attached>
+        <Model scale=10 mesh="Carrier.mesh" />
+        <Model position="0,30,20" scale=10 mesh="pirate.mesh" roll="180" />
+        <Model position="-80,-30,20" scale=10 mesh="pirate.mesh" roll="180" />
+      </attached>
+    </StaticEntity>
+
+    <StaticEntity pitch=70>
+      <attached>
+        <MovableEntity rotationaxis="0,0,1" rotationrate=8.5974>
+          <attached>
+            <StaticEntity yaw=-90 pitch=0 roll=90 position="800,0,0">
+              <attached>
+                <Model position="0,0,0" scale=10 mesh="satellite.mesh" />
+                <MovableEntity position="-4,0,20" velocity="0,0,0" rotationaxis="0,0,1" rotationrate=50>
+                  <attached>
+                    <Model position="0,0,0" scale=10 mesh="satellitedish.mesh"/>
+                  </attached>
+                </MovableEntity>
+                <ParticleEmitter pitch=-135 roll=30 position="-14, 3.5,-2.5" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+                <ParticleEmitter pitch=135 roll=30 position="-14, 3.5,-9" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+                <ParticleEmitter pitch=-45 roll=30 position="-14,-3.5,-2.5" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+                <ParticleEmitter pitch=45 roll=30 position="-14,-3.5,-9" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+              </attached>
+            </StaticEntity>
+          </attached>
+        </MovableEntity>
+      </attached>
+    </StaticEntity>
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 600 - 300)?>, <?lua print(math.random() * 600 - 300) ?>, <?lua print(math.random() * 100 + 300) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 10 + 5) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 600 - 300)?>, <?lua print(math.random() * 600 - 300) ?>, <?lua print(math.random() * -100 - 300) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 10 + 5) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 600 - 300)?>, <?lua print(math.random() * 100 + 300) ?>, <?lua print(math.random() * 600 - 300) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 10 + 5) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 600 - 300)?>, <?lua print(math.random() * -100 - 300) ?>, <?lua print(math.random() * 600 - 300) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 10 + 5) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 100 + 300)?>, <?lua print(math.random() * 600 - 300) ?>, <?lua print(math.random() * 600 - 300) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 10 + 5) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * -100 - 300)?>, <?lua print(math.random() * 600 - 300) ?>, <?lua print(math.random() * 600 - 300) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 10 + 5) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/portals.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/portals.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/portals.oxw	(revision 11817)
@@ -0,0 +1,106 @@
+<!-- -->
+<LevelInfo
+ name = "Portals"
+ description = "Level for testing portals"
+ tags = "test"
+ screenshot = "portals.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Model mesh="Spacegate.mesh" yaw="90"/>
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="0,0,0" id="1" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0"/>
+    <PortalEndPoint position="-300,0,0" id="2" distance="40" target="MobileEntity" design="PortalDefault" reenterDelay="0"/>
+    <PortalLink fromID="1" toID="2" />
+    <PortalLink fromID="2" toID="1" />
+
+    <!--PickupSpawner pickup=dronepickup position="-200,0,0" triggerDistance="10" respawnTime="10" maxSpawnedItems="10" /-->
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <GlobalShader compositor="Bloom" visible=false>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,0,0" distance=30 target="Spectator" switch=true />
+        </visibility>
+      </events>
+    </GlobalShader>
+
+
+<!--
+    <Model position="0,0,0" scale=8 mesh="ast1.mesh" />
+    <StaticEntity position="0,0,0" collisionType=static>
+      <collisionShapes>
+        <SphereCollisionShape radius="20" />
+      </collisionShapes>
+    </StaticEntity>
+-->
+
+
+<!--
+    <?lua
+      for i = 1, 70, 1 do
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 1000 + 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * -1000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 1000 + 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * -1000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 1000 + 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * -1000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentation.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentation.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentation.oxw	(revision 11817)
@@ -0,0 +1,200 @@
+<!-- -->
+
+<LevelInfo
+ name = "Presentation"
+ description = "Presentation Level"
+ tags = "presentation"
+ screenshot = "presentation.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.3, 0.3, 0.3"
+   skybox       = "Orxonox/Starbox"
+  >
+    <Light type=directional position="0,0,0" direction="1, -0.3, 0.3" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <!--SpawnPoint position="0,   0,  100"           spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0,   0, -700" yaw  =180 spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <SpawnPoint position="0, 300, -300" pitch=-90 spawnclass=SpaceShip pawndesign=spaceshipassff /-->
+
+
+    <!-- axes in ogre's origin of coordinate system for phsics engine testing purposes-->
+    <!--StaticEntity position="0,0,0">
+      <attached>
+        <Model position="0,0,0" scale=1 mesh="axes.mesh" />
+      </attached>
+    </StaticEntity -->
+
+    <!-- red sphere for phsics engine testing purposes-->
+    <!--StaticEntity position="40,0,0">
+      <attached>
+        <Model position="0,0,0" scale=1 mesh="sphere.mesh" />
+      </attached>
+    </StaticEntity-->
+
+    <!-- yellow cube for phsics engine testing purposes-->
+    <!--StaticEntity position="80,0,0">
+      <attached>
+        <Model position="0,0,0" scale=1 mesh="cube.mesh" />
+      </attached>
+    </StaticEntity-->
+
+    <!-- Carrier with guns not implemented yet -->
+    <MovableEntity position="-2000,-1000,-2000" pitch="-90" roll="90">
+      <attached>
+        <Model position="0,0,0" scale=10 mesh="Carrier.mesh" />
+        <Model position="0,30,20" scale=10 mesh="pirate.mesh" roll="180" />
+        <Model position="-80,-30,20" scale=10 mesh="pirate.mesh" roll="180" />
+      </attached>
+    </MovableEntity>
+
+    <MovableEntity position="-300,200,-800" velocity="5,0,0" rotationaxis="1,0,0" rotationrate=0>
+      <attached>
+        <Model position="0,0,0" scale=10 mesh="satellite.mesh" />
+        <MovableEntity position="-4,0,0" velocity="0,0,0" rotationaxis="0,0,1" rotationrate=50>
+          <attached>
+            <Model position="4,0,0" scale=10 mesh="satellitedish.mesh"/>
+          </attached>
+        </MovableEntity>
+        <ParticleEmitter pitch=-135 roll=30 position="-14, 3.5,-2.5" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+        <ParticleEmitter pitch=135 roll=30 position="-14, 3.5,-9" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+        <ParticleEmitter pitch=-45 roll=30 position="-14,-3.5,-2.5" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+        <ParticleEmitter pitch=45 roll=30 position="-14,-3.5,-9" source="Orxonox/thruster3" lifetime=2.0 loop=1 startdelay=3.0 />
+      </attached>
+    </MovableEntity>
+
+    <MovableEntity scale=1.5 position="0,0,-300" velocity="0,0,0" rotationaxis="0,1,0" rotationrate=90>
+      <events>
+        <activity>
+          <DistanceTrigger position="0,0,-300" distance=50 target="ControllableEntity" invert=1 />
+        </activity>
+      </events>
+      <attached>
+        <Model position="0,0,0" scale=10 mesh="ast1.mesh" />
+        <StaticEntity position="0,0,100">
+          <attached>
+            <Model position="0,0,0" scale=6 mesh="ast1.mesh" />
+            <MovableEntity position="0,0,0" velocity="0,0,0" rotationaxis="0,0,1" rotationrate=500>
+              <attached>
+                <Model position="0,35,0" scale=2 mesh="ast1.mesh" />
+                <Model position="0,-35,0" scale=2 mesh="ast1.mesh" />
+                <Model position="35,0,0" scale=2 mesh="ast1.mesh">
+                  <attached>
+                    <ParticleEmitter position="0,0,0" source="Orxonox/ExplosionComp4" />
+                  </attached>
+                </Model>
+                <Model position="-35,0,0" scale=2 mesh="ast1.mesh">
+                  <attached>
+                    <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+                  </attached>
+                </Model>
+              </attached>
+            </MovableEntity>
+          </attached>
+        </StaticEntity>
+        <MovableEntity position="0,0,-100" velocity="0,0,0" rotationaxis="0,1,0" rotationrate=200>
+          <attached>
+            <ParticleEmitter position="0,0,0" source="Orxonox/fire3" />
+            <Model position="0,0,0" scale=6 mesh="ast1.mesh" />
+            <Model position="0,0,-50" scale=3 mesh="ast1.mesh" />
+            <Model position="0,0,50" scale=3 mesh="ast1.mesh" />
+          </attached>
+        </MovableEntity>
+      </attached>
+    </MovableEntity>
+
+    <ExplosionChunk position="-500,0,-200" lifetime=3.0 loop=1/>
+
+    <ParticleSpawner position="-500,0,-200" source="Orxonox/ExplosionComp1" lifetime=3.0 loop=1 />
+    <ParticleSpawner position="-500,0,-200" source="Orxonox/ExplosionComp2" lifetime=3.0 loop=1 />
+
+    <ParticleSpawner position="0,0,100" source="Orxonox/ExplosionComp1" lifetime=2.0 loop=0 autostart=0>
+      <events>
+        <spawn>
+          <EventTrigger delay=1>
+            <events>
+              <trigger>
+                <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+              </trigger>
+            </events>
+          </EventTrigger>
+        </spawn>
+      </events>
+    </ParticleSpawner>
+
+
+    <ParticleEmitter name=fireright position="200,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <DistanceTrigger name=firetrigger1 position="200,0,0" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </ParticleEmitter>
+    <ParticleEmitter name=fireleft position="-200,0,0" source="Orxonox/fire3" active=true>
+      <events>
+        <activity>
+          <DistanceTrigger name=firetrigger2 position="-200,0,0" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </ParticleEmitter>
+    <ParticleEmitter name=firecenter position="0,0,0" source="Orxonox/fire3" active=false>
+      <events>
+        <activity>
+          <EventListener event=firetrigger1 />
+          <EventListener event=firetrigger2 />
+        </activity>
+      </events>
+    </ParticleEmitter>
+
+
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=fireright />
+        <EventTarget target=firecenter />
+        <EventTarget target=fireleft />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="0,0,200" distance=100 target="ControllableEntity" />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+
+    <Model position="0,50,0" scale=3 mesh="assff.mesh">
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,50,0" distance=50 target="ControllableEntity" invert=1 />
+        </visibility>
+      </events>
+    </Model>
+
+
+    <Model position="0,0,200" scale=10 mesh="ast2.mesh" shadow=true />
+    <!--Model position="0,0,-200" scale=10 mesh="ast1.mesh" shadow=true /-->
+    <Model position="0,200,0" scale=10 mesh="ast3.mesh" shadow=true />
+    <Model position="0,-200,0" scale=10 mesh="ast4.mesh" shadow=true />
+    <Model position="200,0,0" scale=10 mesh="ast5.mesh" shadow=false />
+    <Model position="-200,0,0" scale=10 mesh="ast6.mesh" shadow=false />
+
+    <Model position="1000,-200,0" scale3D="1,100,100" mesh="ast1.mesh" />
+
+    <Model position="0, 0,-100" pitch=-90 roll=-90 scale=4 mesh="assff.mesh" />
+    <!--Model position="0,100,-100" pitch=-90 roll=-90 scale=4 mesh="pirate.mesh" />
+    <Model position="0,300,-100" pitch=-90 roll=-90 scale=4 mesh="spacecruiser.mesh" /-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentation09.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentation09.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentation09.oxw	(revision 11817)
@@ -0,0 +1,62 @@
+<LevelInfo
+ name = "Presentation X 3rd"
+ description = "3rd Presentation level for Orxonox Convention X"
+ tags = "presentation"
+ screenshot = "presentationx3rd.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+  
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+    <SpawnPoint position="<?lua print(math.sin(1.5) *40000) ?>,<?lua print(math.cos(1.5) *40000) ?>,<?lua print(500) ?>" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+
+    <?lua
+      max = 20
+      for i = 1, max, 1
+      do
+        x = math.sin(i/max*6)*40000
+        y = math.cos(i/max*6)*40000
+        z = i*100
+    ?>
+      <?lua
+        for k = 1, 25, 1
+        do
+        j = math.random()
+      ?>
+
+      <MovableEntity position="<?lua print(x + math.random() * 10000-2500) ?>,<?lua print(y + math.random() * 5000-2500) ?>,<?lua print(z + math.random() * 1000-500) ?>" <?lua if i == 5 then ?> collisionType=dynamic linearDamping=0.8 angularDamping=0 mass="<?lua print(j * 50) ?>" <?lua end ?> scale="<?lua print(j * 5) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+        </attached>
+        <?lua if i == 5 then ?><collisionShapes>
+          <SphereCollisionShape radius="<?lua print(j * 70) ?>" />
+        </collisionShapes> <?lua end ?>
+      </MovableEntity>
+    
+      <?lua end ?>
+    <?lua end ?>
+    
+    <Planet position="0,0,0" scale=10000 pitch=-90 mesh="iceplanet.mesh" atmosphere="atmosphere1" rotationaxis="1,1,0" rotationrate="1" atmospheresize=224.0f imagesize=1024.0f />
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentation09b.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentation09b.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentation09b.oxw	(revision 11817)
@@ -0,0 +1,376 @@
+<LevelInfo
+ name = "Presentation X2"
+ description = "2nd Presentation level for Orxonox Convention X"
+ tags = "presentation"
+ screenshot = "presentationx2.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "TeamDeathmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxSomeNebula"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+    
+    <Light type=directional position="0,0,0" direction="0.683, 0.289, 0.670" diffuse="1.0, 1.0, 1.0, 1.0" specular="1.0, 1.0, 1.0, 1.0" />
+
+    <SpawnPoint position="-3800, 2500, 1500" direction="-0.683, -0.289, -0.670"  spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <SpaceShip position="-3900,3000,1000">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0>
+          <waypoints>
+            <StaticEntity position="-3850,2800,1450" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4100,2600,1600">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0>
+          <waypoints>
+            <StaticEntity position="-3850,2800,1450" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4000,2500,1500">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0>
+          <waypoints>
+            <StaticEntity position="-3850,2800,1450" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4100,2700,1500">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0 />
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4150,2750,1550">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0 />
+      </controller>
+    </SpaceShip>
+
+    <PickupSpawner pickup=smalljumppickup position="-3800, 2500, 1500" respawnTime="60" triggerDistance="20" maxSpawnedItems="5" />
+
+    <!-- PickupRepresentation for the pickup below, since it is not a standard pickup provided by pickups.oxi -->
+    <PickupRepresentation
+      name = "MediumHealth"
+      pickupName = "Medium Health Pack"
+      pickupDescription = "Once used adds a medium amout of health to the ship."
+      spawnerTemplate = "mediumhealthpickupRepresentation"
+      inventoryRepresentation = "MediumHealth"
+    />
+
+    <Template name=onusehealthpickup baseclass=HealthPickup>
+      <HealthPickup representation="MediumHealth" health=100 activationType=onUse durationType=once />
+    </Template>
+
+    <PickupSpawner pickup=onusehealthpickup position="-4150,2750,1550" respawnTime="60" triggerDistance="20" maxSpawnedItems="5" />
+
+    <PickupSpawner pickup=mediumhealthpickup position="2300, 4300, 2400" respawnTime="5" triggerDistance="20" />
+
+    <Billboard position="-2500, 2400, 1500" material="Examples/Flare" />
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=pirates />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="-2500, 2400, 1500" distance=250 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpaceShip position="<?lua print(5000 + math.random() * 4000 - 2000) ?>,<?lua print(0 + math.random() * 2000 - 1000) ?>,<?lua print(math.random() * 2000 - 1000) ?>">
+        <templates>
+          <Template link=spaceshippirate />
+        </templates>
+        <controller>
+          <WaypointPatrolController name=pirates alertnessradius=1000 team=1 active=false>
+            <waypoints>
+              <StaticEntity position="3100, 2000, 1500" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <?lua
+      for i = 1, 12, 1 do
+    ?>
+      <SpaceShip position="<?lua print(2800 + math.random() * 2000 - 1000) ?>,<?lua print(2500+ math.random() * 1000 - 500) ?>,<?lua print(2500 + math.random() * 1000 - 500) ?>" >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=1000 team=0>
+            <waypoints>
+              <StaticEntity position="<?lua print(2800 + math.random() * 1000 - 500) ?>,<?lua print(2500 + math.random() * 1000 - 500) ?>,<?lua print(1500 + math.random() * 1000 - 500) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <Billboard position="2300, 4400, 2500" material="Examples/Flare" />
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=attacker />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="2300, 4400, 2500" distance=50 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <?lua
+      for i = 1, 12, 1 do
+    ?>
+      <SpaceShip position="<?lua print(2500 + math.random() * 500 - 250) ?>,<?lua print(4800 + math.random() * 500 - 250) ?>,<?lua print(2500 + math.random() * 500 - 250) ?>" >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <WaypointPatrolController name=attacker alertnessradius=1000 team=0 active=false>
+            <waypoints>
+              <StaticEntity position="<?lua print(2800 + math.random() * 500 - 250) ?>,<?lua print(2500 + math.random() * 500 - 250) ?>,<?lua print(1500 + math.random() * 500 - 250) ?>" />
+              <StaticEntity position="<?lua print(5000 + math.random() * 500 - 250) ?>,<?lua print(0 + math.random() * 500 - 250) ?>,<?lua print(0 + math.random() * 500 - 250) ?>" />
+              <StaticEntity position="<?lua print(7500 + math.random() * 500 - 250) ?>,<?lua print(-2500 + math.random() * 500 - 250) ?>,<?lua print(-1500 + math.random() * 500 - 250) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <StaticEntity position="2800, 2500, 2500">
+      <attached>
+        <CheckPoint />
+        <Model position="400, 0, 0" scale="40" mesh="DuBall2.mesh"/>
+        <Model position="-400, 0, 0" scale="40" mesh="DuBall1.mesh"/>
+      </attached>
+    </StaticEntity>
+
+<!--
+    <Destroyer position="6500, -2000, -1000" collisionType=dynamic linearDamping=0.8 angularDamping=0 mass=500>
+      <attached>
+        <CheckPoint />
+        <Model position="0,0,0" scale="5" mesh="Carrier.mesh"/>
+        <Backlight
+          mainstate=activity
+          active=false
+          scale=0.4
+          name=bltest
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width=15
+          length=1500
+          lifetime=2
+          elements=50
+          trailmaterial="Trail/backlighttrail"
+          turnontime=1
+          turnofftime=1
+          material="Flares/ThrusterFlare1"
+        />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+    </Destroyer>
+-->
+
+    <Destroyer
+      position          = "6500,-2000,-1000"
+      collisionType     = dynamic
+      mass              = 100000
+      angularDamping    = 0.9999999
+      health            = 1000
+      maxhealth         = 1000
+      initialhealth     = 1000
+    >
+      <controller>
+        <WaypointPatrolController team=1 />
+      </controller>
+      <attached>
+        <Model mesh="Carrier.mesh" scale="5" />
+        <Backlight
+          mainstate=activity
+          active=false
+          scale=0.4
+          name=bltest
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width=15
+          length=1500
+          lifetime=2
+          elements=50
+          trailmaterial="Trail/backlighttrail"
+          turnontime=1
+          turnofftime=1
+          material="Flares/ThrusterFlare1"
+        />
+
+        <?lua
+          for i=0,8,1 do
+        ?>
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?> ,15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?>,-15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+        <?lua end ?>
+
+        <Backlight
+          scale=1
+          position=" 169, 75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare"
+        />
+        <Backlight
+          scale=1
+          position=" 169, -75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+    </Destroyer>
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpaceShip position="<?lua print(6200 + math.random() * 2000 - 1000) ?>,<?lua print(-1500 + math.random() * 1000 - 500) ?>,<?lua print(-700 + math.random() * 1000 - 500) ?>" >
+        <templates>
+          <Template link=spaceshippirate />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=1000 team=1>
+            <waypoints>
+              <StaticEntity position="<?lua print(6000 + math.random() * 1000 - 500) ?>,<?lua print(-2000 + math.random() * 1000 - 500) ?>,<?lua print(-1000 + math.random() * 1000 - 500) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <?lua
+      for i = 1, 200, 1 do
+        x = math.random() * 100  + (i-70) * 100
+        y = math.random() * 3000 - 1500
+        z = math.random() * 3000 - 1500 + (i-100) * 10
+        s = math.random() * 60 + 30
+    ?>
+      <MovableEntity position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.8 angularDamping=0.8 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 - 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(s) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+    <?lua
+      elements = {"BodyDebris1.mesh", "CockpitDebris.mesh", "LightningGun.mesh", "WingDebris1.mesh", "WingDebris2.mesh", "satellitedish.mesh", "Thruster.mesh"}
+      sizes = {4, 4, 4, 4, 4, 10, 20}
+      
+      elements.length = function()
+        return table.getn(elements)
+      end
+      
+      for i = 1, 150, 1 do
+        x = math.random() * 750 - 4500
+        y = math.random() * 1000 + 2000
+        z = math.random() * 500 + 1000
+        e = math.floor(math.random()*elements.length()+1)
+    ?>
+
+      <MovableEntity position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.8 angularDamping=0.8 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 - 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(sizes[e]) ?>" mesh="<?lua print( elements[e]) ?>" />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationDM.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationDM.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationDM.oxw	(revision 11817)
@@ -0,0 +1,100 @@
+<LevelInfo
+ name = "Presentation DM"
+ description = "Presentation Level"
+ tags = "presentation"
+ screenshot = "presentationdm.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "Deathmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpawnPoint position="<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <?lua end ?>
+
+    <GlobalShader compositor="Bloom" visible=false>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,0,0" distance=30 target="Spectator" switch=true />
+        </visibility>
+      </events>
+    </GlobalShader>
+
+    <?lua
+      for i = 1, 100, 1 do
+        j = math.random()
+        scale = j * 50 + 5
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000-2000) ?>,<?lua print(math.random() * 5000 - 2000) ?>" collisionType=dynamic linearDamping=0.8 angularDamping=0 mass="<?lua print(scale) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(scale) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+        </attached>
+        <collisionShapes>
+          <SphereCollisionShape radius="<?lua print(scale * 2.5) ?>" />
+        </collisionShapes>
+      </MovableEntity>
+    <?lua end ?>
+
+<!--
+    <?lua
+      for i = 1, 70, 1 do
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 1000 + 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * -1000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 1000 + 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * -1000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 1000 + 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * -1000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationFS10.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationFS10.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationFS10.oxw	(revision 11817)
@@ -0,0 +1,139 @@
+<LevelInfo
+ name = "Presentation XI"
+ description = "1st Presentation level for Orxonox Convention XI"
+ tags = "presentation"
+ screenshot = "presentationxi.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+?>
+
+<?lua
+  include("templates/lodInformation.oxt")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level
+ gametype = "TeamDeathmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipswallow />
+
+    <Billboard position="12.5, -30, -500" material="Banners/Pickups" scale="0.5"/>
+    <Billboard position="500, -30, -500" material="Banners/Drone" scale="0.5"/>
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=pirate />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="500, -50, -500" distance=20 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <Billboard position="1000, -30, -500" material="Banners/Formation" scale="0.5"/>
+    <Billboard position="1000, -50, -500" material="Examples/Flare" scale="0.5"/>
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=formation />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="1000, -50, -500" distance=20 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <SpaceShip position="500,0,-1500">
+        <templates>
+          <Template link=spaceshippirate />
+        </templates>
+        <controller>
+          <AIController team=1 active=false name=pirate formationFlight=false passive=false />
+        </controller>
+    </SpaceShip>
+
+
+    <?lua
+      for i = 1, 10, 1 do
+        ?>
+      <SpaceShip position="<?lua print(5000 + math.random() * 4000 - 2000) ?>,<?lua print(0 + math.random() * 2000 - 1000) ?>,<?lua print(math.random() * 2000 - 1000) ?>">
+        <templates>
+          <Template link=spaceshippirate />
+        </templates>
+        <controller>
+          <AIController formationFlight=true passive=true team=0 name=formation active=false />
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+
+    <?lua
+      for i = 1, 10, 1 do
+        ?>
+      <SpaceShip position="<?lua print(5000 + math.random() * 4000 - 2000) ?>,<?lua print(0 + math.random() * 2000 - 1000) ?>,<?lua print(math.random() * 2000 - 1000) ?>">
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <AIController formationFlight=true passive=true team=1 name=formation active=false/>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <PickupSpawner pickup=dronepickup position="500,-50,-500" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- Shield pickups -->
+
+    <PickupSpawner pickup=hugeshieldpickup position="-25,-50,-500" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- Health pickups -->
+
+    <PickupSpawner pickup=hugehealthpickup position="0,-75,-500" triggerDistance="10" respawnTime="30" maxSpawnedItems="10" />
+
+    <!-- Speed pickups -->
+
+    <PickupSpawner pickup=hugespeedpickup position="25,-50,-500" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" />
+    <PickupSpawner pickup=smalljumppickup position="50,-50,-500" triggerDistance="10" respawnTime="10" maxSpawnedItems="99" />
+
+    <!-- Invisible pickups -->
+
+    <PickupSpawner pickup=hugeinvisiblepickup position="0,-50,-500" triggerDistance="10" respawnTime="5" maxSpawnedItems="10" />
+
+    <!-- PickupRepresentation for the pickup below, since it is not a standard pickup provided by pickups.oxi -->
+    <PickupRepresentation
+      name = "MediumHealth"
+      pickupName = "Medium Health Pack"
+      pickupDescription = "Once used adds a medium amout of health to the ship."
+      spawnerTemplate = "mediumhealthpickupRepresentation"
+      inventoryRepresentation = "MediumHealth"
+    />
+
+    <Template name=onusehealthpickup baseclass=HealthPickup>
+      <HealthPickup representation="MediumHealth" health=50 activationType=onUse durationType=once />
+    </Template>
+
+    <PickupSpawner pickup=onusehealthpickup position="25,-75,-500" respawnTime="60" triggerDistance="20" maxSpawnedItems="5" />
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationFS102.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationFS102.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationFS102.oxw	(revision 11817)
@@ -0,0 +1,107 @@
+<LevelInfo
+ name = "Presentation XI FPS 1st"
+ description = "2nd Presentation level for Orxonox Convention XI, FPS"
+ tags = "presentation"
+ screenshot = "presentationxifps1st.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/FPS.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.1, 0.1, 0.1"
+   skybox       = "Orxonox/skyBoxBasic"
+   gravity      = "0,-1000,0"
+   negativeWorldRange = "-100000, -100000, -100000"
+   positiveWorldRange = " 100000,  100000,  100000"
+   hasPhysics   = true
+  >
+    <Light type=directional position="0,-100000,0" direction="0.02, -1, 0.05" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+  <Pawn health=100 position="600,35,0" direction="0,-1,0" collisionType=dynamic mass=100000>
+      <attached>
+        <Model position="0,0,0" mesh="fish.mesh" scale3D="5,5,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="25,25,25" />
+      </collisionShapes>
+  </Pawn>
+  
+  <Pawn health=100 position="0,-35,0" direction="0,-1,0" collisionType=dynamic mass=100000>
+      <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="5,5,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="25,25,25" />
+      </collisionShapes>
+  </Pawn>
+  
+  <StaticEntity position="0,-50,0" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+   <StaticEntity position="210,-30,0" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_orange.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+  
+   <StaticEntity position="600,-20,0" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_green.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+<StaticEntity position="600,10,120" direction="0,-1,1" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_red.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+  
+  <StaticEntity position="600,40,250" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+  
+<?lua
+for i = 1, 10, 1
+do ?>
+    <SpawnPoint position="0,300,0" direction="0, 0, 0" lookat="0,0,100000000" spawnclass=FpsPlayer pawndesign=fps />
+<?lua
+end
+?>
+
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationFS10Ed.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationFS10Ed.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationFS10Ed.oxw	(revision 11817)
@@ -0,0 +1,181 @@
+<LevelInfo
+ name = "Presentation XI FPS 2nd"
+ description = "3rd Presentation level for Orxonox Convention XI, FPS"
+ tags = "presentation"
+ screenshot = "presentationxifps2nd.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/FPS.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.1, 0.1, 0.1"
+   skybox       = "Orxonox/skyBoxBasic"
+   gravity      = "0,-1000,0"
+   negativeWorldRange = "-100000, -100000, -100000"
+   positiveWorldRange = " 100000,  100000,  100000"
+   hasPhysics   = true
+  >
+    <Light type=directional position="0,-100000,0" direction="0.02, -1, 0.05" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+  <Pawn health=100 position="600,35,0" direction="0,-1,0" collisionType=dynamic mass=100000>
+      <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="5,5,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="25,25,25" />
+      </collisionShapes>
+  </Pawn>
+
+  <Pawn health=100 position="0,-35,0" direction="0,-1,0" collisionType=dynamic mass=100000>
+      <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="5,5,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="25,25,25" />
+      </collisionShapes>
+  </Pawn>
+
+  <StaticEntity position="0,-50,0" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+   <StaticEntity position="210,-30,0" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_orange.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+   <StaticEntity position="600,-20,0" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_green.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+<StaticEntity position="600,10,120" direction="0,-1,1" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_red.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+  <StaticEntity position="600,40,250" direction="0,-1,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="100,100,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="100,100,10" />
+      </collisionShapes>
+  </StaticEntity>
+
+
+   <StaticEntity position="6000,0,10250" direction="0,0,0" collisionType=static mass=100000 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_green.mesh" scale3D="10000,10,10000" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="10000,10,10000" />
+      </collisionShapes>
+  </StaticEntity>
+
+  <Pawn health=100 position="530,70,1450" direction="-1,0,0" collisionType=dynamic mass=1 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_red.mesh" scale3D="60,60,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="60,60,10" />
+      </collisionShapes>
+  </Pawn>
+
+  <Pawn health=100 position="670,70,1450" direction="-1,0,0" collisionType=dynamic mass=1 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_red.mesh" scale3D="60,60,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="60,60,10" />
+      </collisionShapes>
+  </Pawn>
+
+   <Pawn health=100 position="600,70,1500" direction="0,0,-1" collisionType=dynamic mass=1 >
+      <attached>
+        <Model position="0,0,0" mesh="cube_red.mesh" scale3D="60,60,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="60,60,10" />
+      </collisionShapes>
+  </Pawn>
+
+   <Pawn health=100 position="600,150,1450" direction="0,-1,0" collisionType=dynamic mass=1 >
+      <attached>
+        <Model position="0,0,0" mesh="cube.mesh" scale3D="90,80,10" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="90,80,10" />
+      </collisionShapes>
+  </Pawn>
+
+  <Pawn health=100 position="600,35,1450" direction="0,-1,0" collisionType=dynamic mass=1 >
+      <attached>
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="5,5,5" />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="25,25,25" />
+      </collisionShapes>
+  </Pawn>
+
+
+  <SpawnPoint position="0,300,0" direction="0, 0, 0" lookat="0,0,100000000" spawnclass=FpsPlayer pawndesign=fps />
+
+
+<?lua
+for i = 1, 100, 1
+do
+j = math.random()
+g = math.random()
+h = math.random()
+?>
+  <Pawn position="<?lua print( (math.random()+10) * 1000 - 9800) ?>,<?lua print(math.random()) ?>,<?lua print( (math.random()+10) * 2000 - 19500) ?>" direction="<?lua print( (math.random()+10) * 10 - 100) ?>,<?lua print(math.random()) ?>,<?lua print(math.random()) ?>" collisionType=dynamic linearDamping=0.8 angularDamping=0 mass=<?lua print(j * 100)?> >
+      <attached>
+        <Model position="0,0,0" scale3D="<?lua print(j*100) ?>,<?lua print(g*100) ?>,<?lua print(h*100) ?>" mesh="cube<?lua
+        if math.mod(i,4)==0 then print('_green') end
+        if math.mod(i,4)==1 then print('_red') end
+        if math.mod(i,4)==2 then print('_orange') end
+        ?>.mesh" /> <!--if it's 3, cube.mesh is taken -> yellow -->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="<?lua print(j*100) ?>,<?lua print(g*100) ?>,<?lua print(h*100) ?>" />
+      </collisionShapes>
+  </Pawn>
+<?lua
+end
+?>
+
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationFS11.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationFS11.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationFS11.oxw	(revision 11817)
@@ -0,0 +1,478 @@
+<!---->
+
+<LevelInfo
+ name = "Presentation FS11"
+ description = "Presentation level spring semester '11"
+ tags = "presentation"
+ screenshot = "presentationfs11.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<?lua
+include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=1
+    displayTime=30
+    position="0.2, 0, 0.1, 0"
+    fontSize="24"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyboxempty"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <!-- SOUND -->
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" />
+    <WorldAmbientSound source="Mars.ogg" looping="true">
+        <events>
+            <activity>
+                <DistanceTrigger position="-72369,803,2" distance=1700 target="Camera" />
+            </activity>
+        </events>
+    </WorldAmbientSound>
+    <WorldAmbientSound source="Jupiter.ogg" looping="true">
+        <events>
+            <activity>
+                <DistanceTrigger position="-73450,5067,-351" distance=800 target="Camera" />
+            </activity>
+        </events>
+    </WorldAmbientSound>
+
+    <!-- EARTH ORBIT -->
+
+    <DistanceTrigger name="spawntrigger" position="0,0,0" target="Pawn" distance=10 stayActive="true" />
+    <DistanceTrigger name="spawndelaytrigger1" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=1 />
+    <DistanceTrigger name="spawndelaytrigger2" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=7 />
+    <DistanceTrigger name="spawndelaytrigger3" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=12 />
+    <DistanceTrigger name="spawndelaytrigger4" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=15 />
+    <DistanceTrigger name="spawndelaytrigger5" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=25 />
+    <DistanceTrigger name="spawndelaytrigger6" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=35 />
+    <DistanceTrigger name="spawndelaytrigger7" position="0,0,0" target="Pawn" distance=10 stayActive="true" delay=40 />
+
+    <SpawnPoint position="0,0,0" lookat="-2,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff>
+        <events>
+            <activity>
+                <EventTrigger invert="true">
+                    <events>
+                        <trigger>
+                            <EventListener event="spawndelaytrigger1" />
+                        </trigger>
+                    </events>
+                </EventTrigger>
+            </activity>
+        </events>
+    </SpawnPoint>
+
+    <SimpleNotification message="Welcome to Earth Orbit" >
+        <events>
+            <trigger>
+                <EventListener event=spawntrigger />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    <SimpleNotification message="Turn right to witness an explosion" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- EARTH -->
+    <Planet
+      position="80500,0,0"
+      scale="63000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="5.9e21"
+      pitch="-90"
+      yaw="50"
+      mesh="planets/earth.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="0,1,0"
+      rotationrate="0.2"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="newtonianGravity" diameter="140000" massDiameter="126000" mass="5.9e21" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="63000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <!-- PARTICLE EFFECT -->
+
+    <ParticleSpawner position="-50,50,-125" source="Orxonox/RingExp" autostart="false" lifetime=500 loop=1 startdelay=2.5>
+        <events>
+            <spawn>
+                <EventListener event=spawndelaytrigger1 />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+    <ParticleSpawner position="-50,50,-125" source="Orxonox/RingExp2" autostart="false" lifetime=500 loop=1 startdelay=2>
+        <events>
+            <spawn>
+                <EventListener event=spawndelaytrigger1 />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+    <ParticleSpawner position="-50,50,-125" source="Orxonox/RingExp3" autostart="false" lifetime=500 loop=1 startdelay=2>
+        <events>
+            <spawn>
+                <EventListener event=spawndelaytrigger1 />
+            </spawn>
+        </events>
+    </ParticleSpawner>
+    <StaticEntity collisionType = "static" position = "-50,50,-125" scale=1 >
+      <attached>
+        <Model position="0,0,0" scale="2" mesh="ast1.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="8" />
+      </collisionShapes>
+    </StaticEntity>
+       
+    <SimpleNotification message="A particle effect by Tibor" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- ENEMIES 1st ROUND -->
+
+    <SimpleNotification message="Enemies attacking" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger3 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Script code="addBots 3" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger3 />
+            </trigger>
+        </events>
+    </Script>
+
+    <SpawnPoint position="100,0,0" lookat="-2,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff active="false" >
+        <events>
+            <activity>
+                <EventListener event=spawnpointtrigger />
+            </activity>
+        </events>
+    </SpawnPoint>
+
+    <SpawnPoint position="0,-100,0" lookat="-2,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff active="false" >
+        <events>
+            <activity>
+                <EventListener event=spawnpointtrigger />
+            </activity>
+        </events>
+    </SpawnPoint>
+
+    <SpawnPoint position="0,0,100" lookat="-2,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff active="false" >
+        <events>
+            <activity>
+                <EventListener event=spawnpointtrigger />
+            </activity>
+        </events>
+    </SpawnPoint>
+
+    <Trigger name="spawnpointtrigger" mode="xor" invert="true" >
+        <EventTrigger>
+            <events>
+                <trigger>
+                    <EventListener event=spawndelaytrigger1 />
+                </trigger>
+            </events>
+        </EventTrigger>
+        <EventTrigger invert="true">
+            <events>
+                <trigger>
+                    <EventListener event=portaltrigger />
+                </trigger>
+            </events>
+        </EventTrigger>
+    </Trigger>
+
+    <!-- SPACE BOUNDARY -->
+
+    <SpaceBoundaries warnDistance="1" maxDistance="400" showDistance="300" healthDecrease="0.1" position="-90000,0,0"/>
+    <SpaceBoundaries warnDistance="1" maxDistance="400" showDistance="300" healthDecrease="0.1" position="0,10000,0"/>
+    <SpaceBoundaries warnDistance="1" maxDistance="450" showDistance="300" healthDecrease="0.1" position="0,0,0"/>
+    <SpaceBoundaries warnDistance="1" maxDistance="400" showDistance="300" healthDecrease="0.1" position="-30000,0,0"/>
+
+    <SimpleNotification message="Notice the shields by Simon" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger4 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="and space boundaries by Maurus" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger5 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Let's get out of here" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger6 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Script code="killBots" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger6 />
+            </trigger>
+        </events>
+    </Script>
+
+    <SimpleNotification message="Boost enhancement by Dominik" >
+        <events>
+            <trigger>
+                <EventListener event=spawndelaytrigger7 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    
+    <!-- PORTALS -->
+
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Billboard material="Portals/Default" />
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="-350,0,0" id="3" distance="40" target="MobileEntity" design="PortalDefault" active="false">
+        <events>
+            <activity>
+                <EventListener event=spawndelaytrigger6 />
+            </activity>
+        </events>
+    </PortalEndPoint>
+    <PortalEndPoint position="-72000,0,0" id="4" distance="40" target="MobileEntity" design="PortalDefault" />
+    <PortalLink fromID="3" toID="4" />
+    <PortalLink fromID="4" toID="3" />
+
+    <DistanceTrigger name="portaltrigger" position="-72000,0,0" target="Pawn" distance=10 stayActive="true" />
+    <DistanceTrigger name="portaldelaytrigger1" position="-72000,0,0" target="Pawn" distance=10 stayActive="true" delay=5 />
+    <DistanceTrigger name="portaldelaytrigger2" position="-72000,0,0" target="Pawn" distance=10 stayActive="true" delay=10 />
+    <DistanceTrigger name="portaldelaytrigger3" position="-72000,0,0" target="Pawn" distance=10 stayActive="true" delay=15 />
+    <DistanceTrigger name="portaldelaytrigger4" position="-72000,0,0" target="Pawn" distance=10 stayActive="true" delay=17 />
+
+    <SimpleNotification message="Welcome to Moon Orbit" >
+        <events>
+            <trigger>
+                <EventListener event=portaltrigger />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Portals by Andreas" >
+        <events>
+            <trigger>
+                <EventListener event=portaldelaytrigger1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- MOON AREA -->
+    
+    <!-- MOON -->
+    <Planet
+      position="-80000,0,0"
+      scale="4000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="7.36e19"
+      pitch="0"
+      mesh="planets/moon.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="0,1,0"
+      rotationrate="0.2"
+      atmospheresize="0.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="0,0,0" mode="newtonianGravity" diameter="40000" massDiameter="34740" mass="7.36e19" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="4000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <SimpleNotification message="Hydrogen farmer/space station by Hans" >
+        <events>
+            <trigger>
+                <EventListener event=portaldelaytrigger2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- HYDROGEN FARMER & DOCKING -->
+    <SpaceShip position="-74000,2500,0" roll=90 yaw=180 pitch=20 mass=10000 health=100000 >
+      <attached>
+        <!-- Docking -->
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=100 />
+        <!-- <Model mesh="cube.mesh" mass=10 position="-1120,0,0" scale3D="230,200,490"  /> -->
+        <!-- <Model mesh="cube.mesh" mass=10 position="580,0,-960" scale3D="230,200,490" yaw=-120 /> -->
+        <!-- <Model mesh="cube.mesh" mass=10 position="580,0,960" scale3D="230,200,490" yaw=-240 /> -->
+        <!-- <Model mesh="cube.mesh" mass=10 position="0,0,0" scale3D="600,200,100" /> -->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-1120,0,0" halfExtents="230,200,490" />
+        <BoxCollisionShape  position="580,0,-960" halfExtents="230,200,490" yaw=-120 />
+        <BoxCollisionShape  position="580,0,960" halfExtents="230,200,490" yaw=-240 />
+      </collisionShapes>
+    </SpaceShip>
+
+    <Dock position="-73942, 1288, -255" roll=90 yaw=180 >
+        <animations>
+            <MoveToDockingTarget target="destroyer" />
+        </animations>
+        <effects>
+            <DockToShip target="spaceShip" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+        </events>
+        <attached>
+            <DistanceTrigger position="10,-202, -42" distance="800" target="Pawn"
+                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"
+            />
+        </attached>
+    </Dock>
+
+    <SpaceShip template="spaceshipassff2" position="-73915,3786,67" orientation="-0.14045, 0.68254, 0.68144, 0.223774" >
+      <attached>
+        <DockingTarget name="spaceShip" />
+      </attached>
+    </SpaceShip>
+
+    <!-- PICKUPS -->
+    <SimpleNotification message="Oh, what have we here?" >
+        <events>
+            <trigger>
+                <EventListener event=portaldelaytrigger3 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Shrink pickup by Sandro" >
+        <events>
+            <trigger>
+                <EventListener event=portaldelaytrigger4 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <PickupSpawner pickup="smallshrinkpickup" position="-72487,420,-63" respawnTime="10" triggerDistance="20" maxSpawnedItems="5" active="false">
+      <events>
+        <activity>
+            <EventListener event=portaldelaytrigger3 />
+        </activity>
+      </events>
+      <attached>
+        <ParticleSpawner position="0,0,0" source="Orxonox/Shield" autostart="false" lifetime=500 loop=0 >
+            <events>
+                <spawn>
+                    <EventListener event=portaldelaytrigger3 />
+                </spawn>
+            </events>
+        </ParticleSpawner>
+      </attached>
+    </PickupSpawner>
+
+    <SpaceBoundaries warnDistance="1" maxDistance="1700" showDistance="500" healthDecrease="0.1" position="-72369,803,2"/>
+    <SpaceBoundaries warnDistance="1" maxDistance="800" showDistance="300" healthDecrease="0.1" position="-73450,5067,-351"/>
+
+    <!-- FINISH -->
+
+    <DistanceTrigger name="dockingtrigger" position="-73942, 1288, -255" target="Pawn" distance=20 stayActive="true" />
+    <DistanceTrigger name="dockingdelaytrigger1" position="-73942, 1288, -255" target="Pawn" distance=20 stayActive="true" delay=3 />
+    <DistanceTrigger name="dockingdelaytrigger2" position="-73942, 1288, -255" target="Pawn" distance=20 stayActive="true" delay=10 />
+
+    <SimpleNotification message="Docking by Sven" >
+        <events>
+            <trigger>
+                <EventListener event=dockingtrigger />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Weapons by Jonas" >
+        <events>
+            <trigger>
+                <EventListener event=dockingdelaytrigger1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Steering enhancement by Manuel" >
+        <events>
+            <trigger>
+                <EventListener event=dockingdelaytrigger2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/presentationFS15.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationFS15.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationFS15.oxw	(revision 11817)
@@ -0,0 +1,103 @@
+<LevelInfo
+ name = "Presentation FS15"
+ description = "Level for Presentation."
+ tags = "presentation"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipRing.oxt")
+  include("templates/spaceshipHeartAttack.oxt")
+  include("templates/orbStation.oxt")
+  include("templates/spaceshipSwallow.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-500,0,0" lookat="-1000,0,0" spawnclass=SpaceShip pawndesign=spaceshipHeartAttack/>
+
+    <?lua for i=0,4,1 do ?>
+      <SpaceShip position="-3000,<?lua print(i*200)?>,0" lookat="-500,0,0" visible="true">
+        <templates>
+          <Template link=spaceshipswallow />
+        </templates>
+      </SpaceShip>
+    <?lua end ?>
+
+
+    <!-- Docking  -->
+    <Dock position="-2000,0,-1000" roll=0 yaw=0 >
+      <attached>
+        <Billboard position="0,0,0" material="Alien" scale=5/>
+        <DistanceTrigger position="0,0,0" distance="200" target="Pawn" beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"/>
+      </attached>
+      <animations>
+        <MoveToDockingTarget target="destroyer" />
+      </animations>
+      <effects>
+        <DockToShip target="destroyer" />
+      </effects>
+      <events>
+        <execute>
+          <EventListener event="dockMe" />
+        </execute>
+      </events>
+    </Dock>
+
+    <SpaceShip position="0,0,0" lookat="0,1000,1000" >
+      <attached>
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+      </attached>
+      <templates>
+        <Template link=spaceshipring />
+      </templates>
+      <events>
+        <visibility>
+          <EventListener event="dockMe" />
+        </visibility>
+      </events>
+    </SpaceShip>
+
+    <MovableEntity position="2000,0,0" >
+      <templates>
+        <Template link=orbStation/>
+      </templates>
+      <events>
+        <visibility>
+          <EventListener event="dockMe" />
+        </visibility>
+      </events>
+    </MovableEntity>
+
+    <Billboard position="0,500,500" material="Flares/ringflare2" colour="0.8,0.4,0.2" scale=1 />
+    <DistanceTrigger position="0,500,500" distance="20" target="Pawn" name="takeControl"/>
+    
+    <ControllerDirector position="0,500,500" scriptname="presentation">
+      <events>
+        <takeControl>
+          <EventListener event="takeControl" />
+        </takeControl>
+      </events>
+    </ControllerDirector>
+
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/presentationHS09.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationHS09.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationHS09.oxw	(revision 11817)
@@ -0,0 +1,401 @@
+<LevelInfo
+ name = "Presentation X 1st"
+ description = "1st Presentation level for Orxonox Convention X"
+ tags = "presentation"
+ screenshot = "presentationx1st.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "TeamDeathmatch"
+ hasPhysics = true
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.6, 0.4, 0.4"
+   skybox       = "Orxonox/skyBoxSomeNebula"
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.683, 0.289, 0.670" diffuse="0.8, 0.5, 0.5, 1.0" specular="0.8, 0.4, 0.4, 1.0" />
+
+    <SpawnPoint position="-3800, 2500, 1500" direction="-0.683, -0.289, -0.670"  spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <SpaceShip position="-3900,3000,1000">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0>
+          <waypoints>
+            <StaticEntity position="-3850,2800,1450" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4100,2600,1600">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0>
+          <waypoints>
+            <StaticEntity position="-3850,2800,1450" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4000,2500,1500">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0>
+          <waypoints>
+            <StaticEntity position="-3850,2800,1450" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4100,2700,1500">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0 />
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="-4150,2750,1550">
+      <templates>
+        <Template link=spaceshipHtwo/>
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=100 team=0 />
+      </controller>
+    </SpaceShip>
+
+    <Billboard material="Test/Fog" position="-3800, 2500, 1500" alpha="0.1" color="1, 1, 1, 0.1" scale="0.5" />
+
+    <PickupSpawner pickup=smalljumppickup position="-3800, 2500, 1500" respawnTime="60" triggerDistance="20" maxSpawnedItems="5" />
+
+    <!-- PickupRepresentation for the pickup below, since it is not a standard pickup provided by pickups.oxi -->
+    <PickupRepresentation
+      name = "MediumHealth"
+      pickupName = "Medium Health Pack"
+      pickupDescription = "Once used adds a medium amout of health to the ship."
+      spawnerTemplate = "mediumhealthpickupRepresentation"
+      inventoryRepresentation = "MediumHealth"
+    />
+
+    <Template name=onusehealthpickup baseclass=HealthPickup>
+      <HealthPickup representation="MediumHealth" health=100 activationType=onUse durationType=once />
+    </Template>
+
+    <PickupSpawner pickup=onusehealthpickup position="-4150,2750,1550" respawnTime="60" triggerDistance="20" maxSpawnedItems="5" />
+
+    <PickupSpawner pickup=mediumhealthpickup position="2300, 4300, 2400" respawnTime="5" triggerDistance="20" />
+
+    <Billboard position="-2500, 2400, 1500" material="Examples/Flare" />
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=pirates />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="-2500, 2400, 1500" distance=250 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpaceShip position="<?lua print(5000 + math.random() * 4000 - 2000) ?>,<?lua print(0 + math.random() * 2000 - 1000) ?>,<?lua print(math.random() * 2000 - 1000) ?>">
+        <templates>
+          <Template link=spaceshippirate />
+        </templates>
+        <controller>
+          <WaypointPatrolController name=pirates alertnessradius=1000 team=1 active=false>
+            <waypoints>
+              <StaticEntity position="3100, 2000, 1500" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <?lua
+      for i = 1, 12, 1 do
+    ?>
+      <SpaceShip position="<?lua print(2800 + math.random() * 2000 - 1000) ?>,<?lua print(2500+ math.random() * 1000 - 500) ?>,<?lua print(2500 + math.random() * 1000 - 500) ?>" >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=1000 team=0>
+            <waypoints>
+              <StaticEntity position="<?lua print(2800 + math.random() * 1000 - 500) ?>,<?lua print(2500 + math.random() * 1000 - 500) ?>,<?lua print(1500 + math.random() * 1000 - 500) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <Billboard position="2300, 4400, 2500" material="Examples/Flare" />
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=attacker />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="2300, 4400, 2500" distance=50 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <?lua
+      for i = 1, 12, 1 do
+    ?>
+      <SpaceShip position="<?lua print(2500 + math.random() * 500 - 250) ?>,<?lua print(4800 + math.random() * 500 - 250) ?>,<?lua print(2500 + math.random() * 500 - 250) ?>" >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <WaypointPatrolController name=attacker alertnessradius="<?lua print(math.random() * 2000) ?>" team=0 active=false>
+            <waypoints>
+              <StaticEntity position="<?lua print(2800 + math.random() * 500 - 250) ?>,<?lua print(2500 + math.random() * 500 - 250) ?>,<?lua print(1500 + math.random() * 500 - 250) ?>" />
+              <StaticEntity position="<?lua print(5000 + math.random() * 500 - 250) ?>,<?lua print(0 + math.random() * 500 - 250) ?>,<?lua print(0 + math.random() * 500 - 250) ?>" />
+              <StaticEntity position="<?lua print(7500 + math.random() * 500 - 250) ?>,<?lua print(-2500 + math.random() * 500 - 250) ?>,<?lua print(-1500 + math.random() * 500 - 250) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <StaticEntity position="2800, 2500, 2500">
+      <attached>
+        <CheckPoint />
+        <Model position="400, 0, 0" scale="40" mesh="DuBall2.mesh"/>
+        <Model position="-400, 0, 0" scale="40" mesh="DuBall1.mesh"/>
+      </attached>
+    </StaticEntity>
+
+<!--
+    <Destroyer position="6500, -2000, -1000" collisionType=dynamic linearDamping=0.8 angularDamping=0 mass=500>
+      <attached>
+        <CheckPoint />
+        <Model position="0,0,0" scale="5" mesh="Carrier.mesh"/>
+        <Backlight
+          mainstate=activity
+          active=false
+          scale=0.4
+          name=bltest
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width=15
+          length=1500
+          lifetime=2
+          elements=50
+          trailmaterial="Trail/backlighttrail"
+          turnontime=1
+          turnofftime=1
+          material="Flares/ThrusterFlare1"
+        />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+    </Destroyer>
+-->
+
+    <Destroyer
+      position          = "6500,-2000,-1000"
+      collisionType     = dynamic
+      mass              = 100000
+      angularDamping    = 0.9999999
+      health            = 1000
+      maxhealth         = 1000
+      initialhealth     = 1000
+    >
+      <controller>
+        <WaypointPatrolController team=1 />
+      </controller>
+      <attached>
+        <Model mesh="Carrier.mesh" scale="5" />
+        <Backlight
+          mainstate=activity
+          active=false
+          scale=0.4
+          name=bltest
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width=15
+          length=1500
+          lifetime=2
+          elements=50
+          trailmaterial="Trail/backlighttrail"
+          turnontime=1
+          turnofftime=1
+          material="Flares/ThrusterFlare1"
+        />
+
+        <?lua
+          for i=0,8,1 do
+        ?>
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?> ,15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?>,-15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+        <?lua end ?>
+
+        <Backlight
+          scale=1
+          position=" 169, 75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare"
+        />
+        <Backlight
+          scale=1
+          position=" 169, -75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare"
+        />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+    </Destroyer>
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpaceShip position="<?lua print(6200 + math.random() * 2000 - 1000) ?>,<?lua print(-1500 + math.random() * 1000 - 500) ?>,<?lua print(-700 + math.random() * 1000 - 500) ?>" >
+        <templates>
+          <Template link=spaceshippirate />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=1000 team=1>
+            <waypoints>
+              <StaticEntity position="<?lua print(6000 + math.random() * 1000 - 500) ?>,<?lua print(-2000 + math.random() * 1000 - 500) ?>,<?lua print(-1000 + math.random() * 1000 - 500) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <?lua
+      elements = {"asteroid_ice.mesh", "asteroid_UV.mesh", "ast1.mesh", "ast2.mesh", "ast3.mesh", "ast4.mesh", "ast5.mesh", "ast6.mesh"}
+
+      elements.length = function()
+        return table.getn(elements)
+      end
+
+      for i = 1, 100, 1 do
+        x = math.random() * 100  + (i) * 100
+        y = math.random() * 3000 - 1500
+        z = math.random() * 3000 - 1500 + (i-100) * 10
+        s = math.random() * 60 + 30
+        e = math.floor(math.random()*elements.length()+1)
+    ?>
+      <MovableEntity mass=90000 position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.8 angularDamping=0.8 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 100 - 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(s) ?>" mesh="<?lua print(elements[e])?>" />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+    <?lua
+      for i = 1, 100, 1 do
+        x = math.random() * 200 + i*200
+        y = math.random() * 3000 - 1500
+        z = math.random() * 3000 - 1500 + (i-100) * 10
+        s = math.random() * 60 + 30
+    ?>
+      <ParticleSpawner position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" source="Orxonox/Steam" lifetime=3.0 loop=1 />
+      <!-- Billboard material="Test/Fog" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>"  color="1, 1, 1, 0.01" scale="20" /-->
+    <?lua end ?>
+
+    <?lua
+      elements = {"BodyDebris1.mesh", "CockpitDebris.mesh", "LightningGun.mesh", "WingDebris1.mesh", "WingDebris2.mesh", "satellitedish.mesh", "Thruster.mesh"}
+      sizes = {4, 4, 4, 4, 4, 10, 20}
+      
+      elements.length = function()
+        return table.getn(elements)
+      end
+      
+      for i = 1, 150, 1 do
+        x = math.random() * 750 - 4500
+        y = math.random() * 1000 + 2000
+        z = math.random() * 500 + 1000
+        e = math.floor(math.random()*elements.length()+1)
+    ?>
+      <MovableEntity mass=90000 position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.8 angularDamping=0.8 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30- 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(sizes[e]) ?>" mesh="<?lua print( elements[e]) ?>" />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+    
+<!--
+    <Planet position="1000,0,0" mass=900000 scale=1000 pitch=-90 mesh="iceplanet.mesh" atmosphere="atmosphere1" rotationaxis="1,1,0" rotationrate="1" atmospheresize=224.0f imagesize=1024.0f />
+-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationHS09b.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationHS09b.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationHS09b.oxw	(revision 11817)
@@ -0,0 +1,269 @@
+<LevelInfo
+ name = "Presentation X 2nd"
+ description = "2nd Presentation level for Orxonox Convention X"
+ tags = "presentation"
+ screenshot = "presentationx2nd.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipGhost.oxt")
+  include("templates/spaceshipHXY.oxt")
+  include("templates/spaceshipTransporter.oxt")
+  include("templates/spaceshipHXYSL.oxt")
+  include("templates/spaceshipTransporterSL.oxt")
+?>
+
+<Level
+ gametype = "TeamDeathmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <WorldAmbientSound source="Mars.ogg" looping="true" playOnLoad="true" />
+
+   <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+   
+    <?lua
+      for i = 1, 50, 1 do
+        x = math.random() * 2000  + 4000
+        y = math.random() * 4000 - 2000
+        z = math.random() * 2000 - 1000
+        s = math.random() * 100
+    ?>
+      <MovableEntity collisiontype=dynamic mass="<?lua print(s*10)?>" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.01 angularDamping=0 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 100 - 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(s) ?>" mesh="asteroid_UV.mesh" />
+        </attached>
+        <collisionShapes>
+          <SphereCollisionShape radius="<?lua print(s*0.9) ?>" />
+        </collisionShapes>
+      </MovableEntity>
+      <ParticleSpawner position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" source="Orxonox/Steam" lifetime=3.0 loop=1 />
+    <?lua end ?>
+
+    <?lua
+      elements = {"BodyDebris1.mesh", "CockpitDebris.mesh", "LightningGun.mesh", "WingDebris1.mesh", "WingDebris2.mesh", "satellitedish.mesh", "Thruster.mesh"}
+      sizes = {4, 4, 4, 4, 4, 10, 20}
+      
+      elements.length = function()
+        return table.getn(elements)
+      end
+      
+      for i = 1, 100, 1 do
+        x = math.random() * 750 - 4500
+        y = math.random() * 1000 + 2000
+        z = math.random() * 500 + 1000
+        e = math.floor(math.random()*elements.length()+1)
+    ?>
+      <MovableEntity mass=90000 position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.8 angularDamping=0.8 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30- 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(sizes[e]) ?>" mesh="<?lua print( elements[e]) ?>" />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+    <?lua
+      for i = 1,12, 1 do
+    ?>
+      <SpaceShip position="<?lua print(math.random()*500 + 4500) ?>,<?lua print(-(math.random()*500 -250)) ?>,<?lua print(i*50 - 150) ?>" >
+        <templates>
+          <Template link=spaceshipHXYSL />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=4000 team=0 active=true>
+            <waypoints>
+              <StaticEntity position="5000,<?lua print(math.random()*50)?> ,<?lua print(i*50 -150) ?>" />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <SpaceShip position="5000,100,100" >
+      <templates>
+        <Template link=spaceshipTransporterSL />
+      </templates>
+      <controller>
+        <WaypointPatrolController name=pirate  target=pirate alertnessradius=1000 team=0 active=false>
+          <waypoints>
+            <StaticEntity position="5000,100,1100" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <Destroyer
+      position          = "-5000,100 ,100"
+      collisionType     = dynamic
+      mass              = 100000
+      angularDamping    = 0.9999999
+      health            = 1000
+      maxhealth         = 1000
+      initialhealth     = 1000
+    >
+      <controller>
+        <WaypointPatrolController team=1 />
+      </controller>
+      <attached>
+        <Model mesh="Carrier.mesh" scale="5" />
+        <Backlight
+          mainstate=activity
+          active=false
+          scale=0.4
+          name=bltest
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width=15
+          length=1500
+          lifetime=2
+          elements=50
+          trailmaterial="Trail/backlighttrail"
+          turnontime=1
+          turnofftime=1
+          material="Flares/ThrusterFlare1"
+        />
+        <?lua
+          for i=0,8,1 do
+        ?>
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?> ,15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?>,-15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+        <?lua end ?>
+
+        <Backlight
+          scale=1
+          position=" 169, 75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare"
+        />
+        <Backlight
+          scale=1
+          position=" 169, -75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare"
+        />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+    </Destroyer>
+
+    <?lua
+      for i = 1, 50, 1 do
+        x = -(math.random() * 2000  + 4000)
+        y = math.random() * 4000 - 2000
+        z = math.random() * 2000 - 1000
+        s = math.random() * 100
+    ?>
+      <MovableEntity collisiontype=dynamic mass="<?lua print(s*10)?>" position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.01 angularDamping=0 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 100 - 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(s) ?>" mesh="asteroid_ice.mesh" />
+        </attached>
+        <collisionShapes>
+          <SphereCollisionShape radius="<?lua print(s*0.9)?>" />
+        </collisionShapes>
+      </MovableEntity>
+      <ParticleSpawner position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" source="Orxonox/Steam" lifetime=3.0 loop=1 />
+    <?lua end ?>
+
+    <!-- EventDispatcher>
+      <targets>
+        <EventTarget target=attack />
+        <EventTarget target=wait />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="0, 0, 4500" distance=100 target="SpaceShip" stayactive=true />
+        </activity>
+      </events>
+    </EventDispatcher>
+
+    <EventDispatcher>
+      <targets>
+        <EventTarget target=wait />
+      </targets>
+      <events>
+        <activity>
+          <DistanceTrigger position="0, 0, 4500" distance=100 target="SpaceShip" stayactive=false />
+        </activity>
+      </events>
+    </EventDispatcher -->
+
+    <?lua
+      for i = 1,25, 1 do
+    ?>
+      <SpaceShip position="<?lua print(-(math.random()*500 + 4500)) ?>,<?lua print(-(math.random()*500 -250)) ?>,<?lua print(i*50 - 150) ?>" >
+        <templates>
+          <Template link=spaceshipghost />
+        </templates>
+        <controller>
+          <WaypointPatrolController name=attack alertnessradius=15000 team=1 active=false>
+            <events>
+              <activity>
+                <DistanceTrigger position="-5000, 100, 100" distance=2000 target="Camera" stayactive=true />
+              </activity>
+            </events>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="false">
+      <events>
+        <activity>
+          <DistanceTrigger position="2000,0,0" distance=500 target="Camera" />
+        </activity>
+      </events>
+    </WorldAmbientSound>
+
+    <SpawnPoint position="5000,0,2000" spawnclass=SpaceShip pawndesign=spaceshipassff  team=0 />
+    
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/presentationHS11.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationHS11.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationHS11.oxw	(revision 11817)
@@ -0,0 +1,245 @@
+<!--  -->
+
+
+<LevelInfo
+ name = "Presentation HS 2011"
+ description = "New Features: Asteroid field/belt generator; Formationflight; HUD (Enemyhealthbar, displaying Names)"
+ tags = "presentation"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/spaceshipTransporter.oxt")
+?>
+
+<Level
+ gametype = "Mission"
+>                      <!--ALTERNATIVE: TeamGametype-->
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=3
+    displayTime=3.9
+    position="0.2, 0, 0.1, 0"
+    fontSize="23"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+  >
+
+  <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+  <TeamSpawnPoint team=0 position="800,700,600" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshipswallow/>
+
+  <!-- TRIGGERS -->
+    <DistanceTrigger name="FormationInit" position="800,700,600"  target="Pawn" distance=60 stayActive="true" delay=0.1 />
+    <DistanceTrigger name="LetsGo"        position="200,-200,1000" target="Pawn" distance=180 stayActive="true" delay=0.1 />
+      <BlinkingBillboard colour="1,1,0.05"position="200,-200,1000" frequency=0.6 amplitude=3 material="Flares/lensflare" >
+      </BlinkingBillboard>
+
+
+
+
+    <Script code="formationcontroller formationflight true" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=FormationInit />
+            </trigger>
+        </events>
+    </Script> <!-- !!! activates formation behaviour !!! -->
+
+    <Script code="artificialcontroller setbotlevel 0.1" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=FormationInit />
+            </trigger>
+        </events>
+    </Script> <!-- make bots "friendly", doesn't work yet :-( -->
+
+    <SimpleNotification message="Let's go!">
+        <events>
+            <trigger>
+                <EventListener event="LetsGo" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+
+
+
+<!-- ADDING FORMATION: 5 Swallows -->
+<?lua for i=0,4,1 do
+?>
+    <SpaceShip position="<?lua print(400+i*200) ?>,-200,1000" lookat="-1300,-600,900" visible="true">
+        <!--events>
+            <visibility>
+                <EventListener event="ondock" />
+            </visibility>
+        </events-->
+        <templates>
+            <Template link=spaceshipswallow /> <!--spaceshipTransporter spaceshippirate-->
+        </templates>
+        <controller>
+            <AIController team=0>
+                <events>
+                    <activity>
+                        <EventListener event="LetsGo" />
+                     </activity>
+                </events>
+            </AIController>
+        </controller>
+    </SpaceShip>
+<?lua end ?>
+
+<?lua for i=0,2,1 do
+?>
+
+
+<!-- ENEMY TRANSPORTER -->
+    <SpaceShip position="<?lua print(-400+i*200) ?>,3000,-2000" lookat="-1300,-600,900" visible="true">
+        <!--events>
+            <visibility>
+                <EventListener event="LetsGo" />
+            </visibility>
+        </events-->
+        <templates>
+            <Template link=spaceshipTransporter />
+        </templates>
+        <controller>
+            <AIController team=1>
+                <events>
+                    <activity>
+                        <EventListener event="LetsGo" />
+                     </activity>
+                </events>
+            </AIController>
+        </controller>
+    </SpaceShip>
+<?lua end ?>
+
+<!-- @Triggers: "hintX" <->  delayed LetsGo -->
+    <EventTrigger name="hint1" activations="1" stayactive="true" delay=4.2>
+      <events>
+        <trigger>
+          <EventListener event="LetsGo" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="hint2" activations="1" stayactive="true" delay=8.4>
+      <events>
+        <trigger>
+          <EventListener event="LetsGo" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="hint3" activations="1" stayactive="true" delay=12.6>
+      <events>
+        <trigger>
+          <EventListener event="LetsGo" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="hint4" activations="1" stayactive="true" delay=16.8>
+      <events>
+        <trigger>
+          <EventListener event="LetsGo" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="hint5" activations="1" stayactive="true" delay=21>
+      <events>
+        <trigger>
+          <EventListener event="LetsGo" />
+        </trigger>
+      </events>
+    </EventTrigger>
+    <EventTrigger name="hint6" activations="1" stayactive="true" delay=25.2>
+      <events>
+        <trigger>
+          <EventListener event="LetsGo" />
+        </trigger>
+      </events>
+    </EventTrigger>
+
+
+
+    <SimpleNotification message="Make bots follow you: Press (1)"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=hint1 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Toggle group behaviour: Press (1)"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=hint2 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Tell the bots to defend you: Press (2)"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=hint3 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Make them attack opponents: Press (2) again"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=hint4 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Let the bots behave 'normal': Press (2) again"  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=hint5 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Have a look at the console to verify this."  broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=hint6 />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+<!-- Generate asteroid field and asteroid belt -->
+<!-- asteroidBelt(centerX, centerY, centerZ, yaw, pitch, segments, minSize, maxSize, radius0, radius1, count, fog) -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(20000, 0, 13000, -48, -34, 70, 100, 200, 22000, 20000, 500, 1)
+
+    ?>
+
+
+
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/presentationHS12.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationHS12.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationHS12.oxw	(revision 11817)
@@ -0,0 +1,502 @@
+<!-- NEW FEATURES:
+- Three new Spaceships: collateralDamage; planetDestroyer; lightEscortship;
+- Shaders (not included here, since the ogre plugin is missing on Ubuntu)
+- Sound Effects (not included)
+- Animation (not included)
+- HUD aiming assistant
+- Turret
+- Racing Bots
+-->
+<LevelInfo
+ name = "Presentation HS 2012"
+ description = "New Features: new Spaceships, Racing AI, HUD Aiming Assistant, Turret, Shaders, Sound Effects"
+ tags = "presentation"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/bigship.oxt")
+  include("templates/spaceshipTurret.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+?>
+
+<Level
+  plugins = gametypes
+  gametype = SpaceRace
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <NotificationQueueCEGUI
+    name="narrative"
+    targets="simpleNotification"
+    size=1
+    displayTime=30
+    position="0.2, 0, 0.1, 0"
+    fontSize="24"
+    fontColor="0.3, 1, 0.2, 0.8"
+    alignment="HorzCentred"
+    displaySize="0.6, 0, 0, 0"
+    />
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+  > <!-- Orxonox/Starbox -->
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-900,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+    <!--SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=bigship /-->
+    <!--SpawnPoint team=0 position="-900,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage /-->
+    <!--SpawnPoint team=0 position="6000,0,2000" lookat="1,1,0" spawnclass=SpaceShip pawndesign=spaceshipcollateraldamage /-->
+    
+    <SpaceRaceManager>
+        <checkpoints>
+            <RaceCheckPoint name="checkpoint1" position="000,0,0" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="0" islast="false" nextcheckpoints="1,2,3">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+<!--- first three alternative paths --->
+            <RaceCheckPoint name="checkpoint2" position="1300,0,-800" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="1" islast="false" nextcheckpoints="7,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90/>
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint3" position="1200,-400,0" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="2" islast="false" nextcheckpoints="4,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint4" position="1200,100,700" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="3" islast="false" nextcheckpoints="5,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+<!--- second three alternative paths --->
+            <RaceCheckPoint name="checkpoint5" position="2000,0,0" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="4" islast="false" nextcheckpoints="7,8,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint6" position="2000,-500,400" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="5" islast="false" nextcheckpoints="9,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+
+<!--- third generation --->
+
+            <RaceCheckPoint name="checkpoint7" position="5000,0,-3000" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="6" islast="false" nextcheckpoints="11,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=135 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint8" position="3500,800,0" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="7" islast="false" nextcheckpoints="10,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint9" position="3500,-800,0" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="8" islast="false" nextcheckpoints="10,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint10" position="3500,0,1000" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="9" islast="false" nextcheckpoints="11,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+<!-- Intermediate Solo Gate -->
+            <RaceCheckPoint name="checkpoint11" position="4500,0,-100" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="10" islast="false" nextcheckpoints="11,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=90 />
+                </attached>
+            </RaceCheckPoint>
+
+<!----  First Common Point  ---->
+            <RaceCheckPoint name="checkpoint12" position="6000,0,2000" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="11" islast="false" nextcheckpoints="12,14,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=100 pitch=45 />
+                </attached>
+            </RaceCheckPoint>
+
+<!-- Two Paths (1) -->
+            <RaceCheckPoint name="checkpoint13" position="7500,-1500,2500" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="12" islast="false" nextcheckpoints="14,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=100 pitch=130 roll=1 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint14" position="7500,-1500,1500" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="13" islast="false" nextcheckpoints="15,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=100 pitch=90 />
+                </attached>
+            </RaceCheckPoint>
+
+<!-- Two Paths (2) -->
+            <RaceCheckPoint name="checkpoint15" position="9000,-3000, 3000" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="14" islast="false" nextcheckpoints="16,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=100 pitch=130 roll=1 />
+                </attached>
+            </RaceCheckPoint>
+
+            <RaceCheckPoint name="checkpoint16" position="9000,-3000,1000" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="15" islast="false" nextcheckpoints="16,-1,-1">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=100 pitch=110 />
+                </attached>
+            </RaceCheckPoint>
+
+<!-- GOAL -->
+            <RaceCheckPoint name="checkpoint17" position="12000,-4000,2000" direction="0,-1,1" collisionType="static" scale="1" distance="100" checkpointindex="16" islast="true">
+                <attached>
+                    <Model mass="50" scale="6" mesh="BigSpacegate.mesh" yaw=100 pitch=135 />
+                </attached>
+            </RaceCheckPoint>
+        </checkpoints>
+    </SpaceRaceManager>
+
+
+<!-- Simplify paths -->
+    <!-- PORTALS -->
+
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Billboard material="Portals/Default" scale="3"/>
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="2000,0,-1000" id="3" distance="60" target="MobileEntity" design="PortalDefault" />
+    <PortalEndPoint position="4500,0,-3400" id="4" distance="60" target="MobileEntity" design="PortalDefault" />
+    <PortalLink fromID="3" toID="4" />
+    <PortalLink fromID="4" toID="3" />
+
+
+    <!-- ForceField -->
+800,400,0
+        <ForceField position="1200,-400,0" direction="8,4,0" diameter=500 velocity=2000 length=500 />
+        <MovableEntity position="1200,-400,0">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.1,0.1,0.1" scale=1/>
+                <?lua for i=0,4,1 do ?>
+                    <Billboard position="<?lua print(i*200) ?>,<?lua print(i*100) ?>,-100" material="Examples/Flare" colour="0.1,0.1,0.1" scale=1/>
+                    <Billboard position="<?lua print(i*200) ?>,<?lua print(i*100) ?>,100" material="Examples/Flare" colour="0.1,0.1,0.1" scale=1/>
+                <?lua end ?>
+                </attached>
+        </MovableEntity>
+
+
+   <!-- Pickup -->
+   <PickupSpawner pickup=smallspeedpickup position="5300,0,-2300" triggerDistance="60" respawnTime="10" maxSpawnedItems="99" scale="12" />
+
+
+<!--- SCENERY --->
+    <!-- @Objects: HYDROGEN FARMER-->
+    <StaticEntity position="5700,0,-3700" mass=10000 >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+        <ParticleEmitter position="0,0,0" source="Orxonox/ThrusterFire" scale=1.2 />
+   <!-- <Model mesh="cube.mesh" mass=10 position="-560,0,0" scale3D="115,100,245"  />
+        <Model mesh="cube.mesh" mass=10 position="290,0,-480" scale3D="115,100,245" yaw=-120 />
+        <Model mesh="cube.mesh" mass=10 position="290,0,480" scale3D="115,100,245" yaw=-240 />
+        <Model mesh="cube.mesh" mass=10 position="-280,0,0" scale3D="163,50,50" />
+        <Model mesh="cube.mesh" mass=10 position="140,0,-240" scale3D="163,50,50"  yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="140,0,240" scale3D="163,50,50" yaw=-240/>
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" />
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="0,530,0" scale3D="172,52,298" yaw=-240/>
+        <Model mesh="cube.mesh" mass=10 position="0,400,0" scale3D="43,110,26" yaw=-30 />
+        <Model mesh="cube.mesh" mass=10 position="-200,100,0" scale3D="26,50,43" />
+        <Model mesh="cube.mesh" mass=10 position="100,100,-173" scale3D="43,50,26" yaw=-30/>
+        <Model mesh="cube.mesh" mass=10 position="100,100,173" scale3D="43,50,26" yaw=30/>
+        <Model mesh="cube.mesh" mass=10 position="-100,264,0" scale3D="26,105,43" roll=-49/>
+        <Model mesh="cube.mesh" mass=10 position="50,264,-87" scale3D="26,105,43" roll=-49 yaw=-120/>
+        <Model mesh="cube.mesh" mass=10 position="50,264,87" scale3D="26,105,43" roll=-49 yaw=-240/>     -->
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </StaticEntity>
+
+    <StaticEntity position="2800,0,0" mass=10000 pitch=0 roll=45 yaw=240 >
+      <attached>
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsBody.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsDuseL.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsDuseR.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsKuppelV.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsKuppelK.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsAntL.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsAntR.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsGarage.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=40 mesh="bsStation.mesh" />
+
+	<BlinkingBillboard position="20,-24,160" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+      	<BlinkingBillboard position="-20,-24,160" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="20,-25,190" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=40 quadratic=1 />
+      	<BlinkingBillboard position="-20,-25,190" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=40 quadratic=1 />
+	<BlinkingBillboard position="20,-25,220" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=80 quadratic=0 />
+      	<BlinkingBillboard position="-20,-25,220" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=80 quadratic=0 />
+	<BlinkingBillboard position="20,-26,250" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=120 quadratic=0 />
+      	<BlinkingBillboard position="-20,-26,250" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=120 quadratic=0 />
+	<BlinkingBillboard position="20,-26,28" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=160 quadratic=0 />
+      	<BlinkingBillboard position="-20,-26,28" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=160 quadratic=0 />
+	<BlinkingBillboard position="29,-35,142" material="Examples/Flare" colour="1, 0.4, 0.4, 0.1" amplitude=0.2 frequency=30 phase=0 quadratic=0 />
+      	<BlinkingBillboard position="-29,-35,142" material="Examples/Flare" colour="1, 0.4, 0.4, 0.1" amplitude=0.2 frequency=30 phase=0 quadratic=0 />
+      </attached>
+    </StaticEntity>
+
+   <!-- Docking -->
+    <Dock position="2830,20,50" roll=0 yaw=0 >
+        <animations>
+            <MoveToDockingTarget target="destroyer" />
+        </animations>
+        <effects>
+            <DockToShip target="spaceShip" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+            <activity>
+                <EventListener event=notGameEnd />
+            </activity>
+        </events>
+        <attached>
+                    <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+	<BlinkingBillboard position="10,0,0" material="Examples/Flare" colour="1, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="20,0,0" material="Examples/Flare" colour="1, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="30,0,0" material="Examples/Flare" colour="1, 0.3, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="0,10,0" material="Examples/Flare" colour="0.3, 1, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="0,20,0" material="Examples/Flare" colour="0.3, 1, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="0,30,0" material="Examples/Flare" colour="0.3, 1, 1, 0.1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="0,0,10" material="Examples/Flare" colour="0.3, 0.3, 1, 1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="0,0,20" material="Examples/Flare" colour="0.3, 0.3, 1, 1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="0,0,30" material="Examples/Flare" colour="0.3, 0.3, 1, 1" amplitude=0.2 frequency=0.4 phase=0 quadratic=1 />
+            <DistanceTrigger position="0,0,0" distance="200" target="Pawn"
+                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"
+            />
+        </attached>
+
+    </Dock>
+    <SpaceShip
+        template            = "spaceshipcollateraldamage"
+        team                = "0"
+        position            = "2890,-40,6"
+        orientation         = "-0.14, 0.68, 0.68, 0.223"
+        lookat              = "0,0,0"
+        roll                = "180"
+        name                = "collateralDamage"
+        radarname           = "Collateral Damage" >
+        <!--
+        pitch               = "90"
+        yaw                 = "0"-->
+      <attached>
+        <DockingTarget name="spaceShip" />
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="destroyer" />
+      </attached>
+    </SpaceShip>
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+    <Planet
+      position="15000,0,-1000"
+      scale="5000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/ganymede.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="5000,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+<StaticEntity position="6750,-750,2000" yaw=0 pitch=0>
+    <attached>
+        <Model position="0,0,0" mesh="turretSocketFront.mesh" scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketIn.mesh"    scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketTop.mesh"   scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketLeft.mesh"  scale3D="10,10,10" />
+        <Model position="0,0,0" mesh="turretSocketRight.mesh" scale3D="10,10,10" />
+    </attached>
+</StaticEntity>
+<SpaceShip position="6750,-740,2000" pitch="90" yaw="0" roll="0" radarname="Automatic Turret">
+    <templates>
+        <Template link=spaceshipturret />
+    </templates>
+    <controller>
+        <WaypointPatrolController alertnessradius=1000 team=10>
+        </WaypointPatrolController>
+     </controller>
+</SpaceShip>
+
+
+    <!--- Some Randomn Asteroids  --->
+    <?lua
+      for i = 1, 250, 1
+      do
+      j = math.random()
+    ?>
+
+    <MovableEntity
+      position = "<?lua print(math.random()* 15000 - 1000) ?>,<?lua print(math.random() * 12000 - 4000) ?>,<?lua print(math.random() * 12000 - 4000) ?>"
+      collisionType = dynamic
+      linearDamping = 0.8
+      angularDamping = 0
+      scale = "<?lua print(j * 150)?>"
+      collisiondamage = 1
+      enablecollisiondamage = true
+    >
+      <attached>
+        <Model mass="<?lua print(j * 1000) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 350) ?>" />
+      </collisionShapes>
+    </MovableEntity>
+
+    <?lua
+      end
+    ?>
+
+
+
+
+
+
+<!-- INTERACTIVE PART -->
+    <DistanceTrigger name="start" position="-900,0,0"  target="Pawn" distance=100 stayActive="true" delay=0.5 />
+    <DistanceTrigger name="spawnBots" position="-900,0,0"  target="Pawn" distance=100 stayActive="true" delay=4.5 />
+    <DistanceTrigger name="creditPetar" position="2000,0,0"  target="Pawn" distance=100 stayActive="true" delay=0.5 />
+    <DistanceTrigger name="creditDario" position="4500,0,-100"  target="Pawn" distance=200 stayActive="true" delay=5 />
+
+    <SimpleNotification message="Sound Effetcs by Mike." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=start />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Racing Bots by Michael." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=spawnBots />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Planetary Destroyer by Petar." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=creditPetar />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Collateral Damage by Raphael." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=dockMe />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification message="Automatic Turret by Dario." broadcast="true">
+        <events>
+            <trigger>
+                <EventListener event=creditDario />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <Script code="addBots 3" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event=spawnBots />
+            </trigger>
+        </events>
+    </Script>
+
+
+<!-- SOUNDS & MUSIC -->
+            <WorldSound name="scoreSound" position="-920,0,0" source="sounds/ReadyGo.ogg" >
+              <events>
+                <play>
+                  <EventListener event="start" />
+                </play>
+              </events>
+            </WorldSound>
+
+
+
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/presentationHS13.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/presentationHS13.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/presentationHS13.oxw	(revision 11817)
@@ -0,0 +1,259 @@
+<!--  -->
+<LevelInfo
+ name = "Presentation HS 13"
+ description = "Entering a Space Station."
+ tags = "presentation"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("HUDTemplatesFPS.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+  include("templates/bigship.oxt")
+  include("templates/spaceshipTurret.oxt")
+  include("templates/spaceshipCollateralDamage.oxt")
+  include("templates/FPS.oxt")
+  include("templates/HeavyCruiser.oxt")
+?>
+
+<Level
+  gametype = Deathmatch
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/skyBoxMoreNebula"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+    gravity      = "0,0,0"
+    hasPhysics   = true
+  >
+
+    <?lua
+      include("includes/pickups.oxi")
+    ?>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0,1.0,1.0,0.5" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="4320,1610,-741" lookat="2800,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+
+    <StaticEntity position  = "2800,0,0" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=50 />
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+        <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+        <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+        <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+        <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+        <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+        <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+        <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+        <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+        <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+        <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+        <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+        <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+      </collisionShapes>
+    </StaticEntity>
+
+<!-- Docking  -->
+    <Dock position="2830,20,50" roll=0 yaw=0 >
+        <animations>
+            <MoveToDockingTarget target="fistperson" />
+        </animations>
+        <effects>
+            <DockToShip target="fistperson" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+
+	    <undocking>
+		<EventListener event="undockMe" />
+	    </undocking>
+	
+        </events>
+        <attached>
+	<!-- Trigger for docking with billboard -->
+            <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+            <DistanceTrigger position="0,0,0" distance="200" target="Pawn"
+                beaconMode="exclude" targetname="bcnDestroyer" name="dockMe"
+            />
+	<!-- Trigger for undocking with billboard -->
+	    <Billboard position="-2800,-20055,-700" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=1 />
+	    <DistanceTrigger position="-2800,-20055,-700" distance="150" target="Pawn"
+                beaconMode="identify" targetname="bcnDestroyer" name="undockMe"
+            />
+        </attached>
+
+    </Dock>
+    
+<!-- FPS Player as destination of the dock -->
+    <FpsPlayer template = "fps" radarname = "First Person Player" position = "172,-20000,-676" >
+      <attached>
+        <DistanceTriggerBeacon name="bcnDestroyer" />
+        <DockingTarget name="fistperson" />
+      </attached>
+    </FpsPlayer>
+
+
+
+
+<!-- Docking  II -->
+    <Dock position="-840,-20055,1.8" roll=0 yaw=0 >
+        <animations>
+            <MoveToDockingTarget target="spaceShip" />
+        </animations>
+        <effects>
+            <DockToShip target="spaceShip" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockMe" />
+            </execute>
+
+	    <undocking>
+			<EventListener event="undockMe" />
+	    </undocking>
+	
+        </events>
+        <attached>
+	<!-- Trigger for docking with billboard -->
+            <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.3,0.4,0.5" scale=1 />
+            <DistanceTrigger position="0,0,0" distance="200" target="Pawn"
+                beaconMode="exclude" targetname="bcnSpaceShip" name="dockMe"
+            />
+	<!-- Trigger for undocking with billboard -->
+	    <Billboard position="4140,20055,-295" material="Flares/ringflare2" colour="0.3,0.4,0.5" scale=1 />
+	    <DistanceTrigger position="4140,20055,-295" distance="300" target="Pawn"
+                beaconMode="identify" targetname="bcnSpaceShip" name="undockMe"
+            />
+        </attached>
+
+    </Dock>
+
+    <SpaceShip
+        template            = "HeavyCruiser"
+        team                = "0"
+        position            = "3600,-20,-120"
+        orientation         = "1,0,0,0"
+        health              = "400"
+        initialhealth       = "400"
+        maxhealth           = "500"
+        shieldhealth        = "80"
+        initialshieldhealth = "80"
+        maxshieldhealth     = "120"
+        shieldabsorption    = "0.8"
+        shieldrechargerate  = "1"
+        shieldrechargewaittime = "1"
+        name                = "Tanis1"
+        radarname           = "Tanis Cruiser" >
+      <attached>
+        <DockingTarget name="spaceShip" />
+        <DistanceTriggerBeacon name="bcnSpaceShip" />
+      </attached>
+    </SpaceShip>
+
+
+
+
+<!-- SpaceStation
+
+The station can either be hidden outside of the skybox, within the hull of the space station if it is big enough or within a planet.
+Complex spacestations can be placed very far away from the spaceship so it is rendered at low resolution while the player uses the space ship.
+
+-->
+  <StaticEntity position="0,-20000,0" direction="0,-1,0" collisionType=static mass=100000 friction=0.01 pitch=-90>
+      <attached>
+    <Model position="0,0,0" mesh="ss_tube.mesh" scale3D="100,100,100" />
+	<Model position="500,0,0" mesh="ss_tube.mesh" scale3D="100,100,100" />
+	<Model position="1200,0,0" mesh="ss_tube_x.mesh" scale3D="100,100,100" />
+	<Model position="1900,0,0" mesh="ss_curve.mesh" scale3D="100,100,100" />
+	<Model position="1200,0,703.5" mesh="ss_curve.mesh" scale3D="100,100,100" />
+	<Model position="1805.0,0,-800" mesh="ss_curve.mesh" scale3D="100,100,100" yaw=90 />
+	<Model position="1010.0,0,-700.0" mesh="ss_curve.mesh" scale3D="100,100,100" yaw=-180 />
+	
+	
+	<Model position="750,-16,703.5" pitch=-90 mesh="ss_flag_room.mesh" scale3D="100,100,100" />
+	<Model position="-250,-16,0" pitch=-90 mesh="ss_flag_room.mesh" scale3D="100,100,100" />
+	<Model position="1200,100,-100" roll=180 mesh="ss_machine.mesh" scale3D="0.15,0.15,0.15" />
+	<Model position="-100,100,0" roll=180 mesh="ss_table.mesh" scale3D="25,25,25" />
+	<Model position="-300,100,0" roll=180 mesh="ss_table_cracked.mesh" scale3D="25,25,25" />
+	<Model position="600,75,0" roll=180 mesh="ss_cylinder.mesh" scale3D="25,25,25" />
+	<Model position="300,50,0" roll=180  pitch=20 mesh="ss_chair.mesh" scale3D="20,20,20" />
+	<Model position="1000,50,0" roll=180 mesh="ss_wall.mesh" scale3D="20,20,20" />
+	<Model position="-830,20,0" roll=180 mesh="ss_flag_aean.mesh" scale3D="40,40,40" />
+	
+	<!--Model mesh="cube.mesh" mass=10 position="0,-100,0" scale3D="5000,0.5,1000" yaw=0 />
+    <Model mesh="cube.mesh" mass=10 position="0,100,0" scale3D="2000,0.5,1000" yaw=0 />
+    <!--Model mesh="cube.mesh" mass=10 position="0,0,100" scale3D="5000,100,0.5" yaw=0 />
+    <Model mesh="cube.mesh" mass=10 position="0,0,-100" scale3D="5000,100,0.5" yaw=0 /-->
+      </attached>
+      <collisionShapes>
+        <!--BoxCollisionShape position="0,-100,0" halfExtents="5000,0,100" /-->
+	    <BoxCollisionShape position="0,100,0" halfExtents="2000,0,1000" />
+	    <!--BoxCollisionShape position="0,0,100" halfExtents="5000,100,0" />
+	    <BoxCollisionShape position="0,0,-100" halfExtents="5000,100,0" /-->
+      </collisionShapes>
+  </StaticEntity>
+
+<!--       
+
+-->
+
+
+  <!--Model position="2820,-20,-160" yaw="90" pitch="-90" roll="0" scale="10" mesh="ss_tube.mesh" />
+  <Model position="2820,-20,-210" yaw="90" pitch="-90" roll="0" scale="10" mesh="ss_tube.mesh" />
+  <Model position="2820,-20,-280" yaw="90" pitch="-90" roll="0" scale="10" mesh="ss_curve.mesh" />
+  <Model position="2820,-100,-270.5" yaw="0" pitch="180" roll="90" scale="10" mesh="ss_curve.mesh" /-->
+  
+   
+<!-- Homogenous gravitationfield to simulate local gravity (activating the normal gravity will affect the spaceship terribly) -->
+<ForceField position="0,-20000,0" mode="homogen" diameter="3000" forcedirection = "0,-500,0" />
+
+
+
+
+
+<!-- Some more stuff -->
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, -19900, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, -19900, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, -19900, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+    <Model position="0,-19900,0" mesh="planets/ganymede.mesh" scale="5000" />
+    
+    
+
+  </Scene>
+
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/princessAeryn.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/princessAeryn.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/princessAeryn.oxw	(revision 11817)
@@ -0,0 +1,277 @@
+<LevelInfo
+ name = "The Tale of Princess Aeryn"
+ description = "The Tale of the elusive but beautiful Princess Aeryn"
+ tags = "mission"
+ screenshot = "thetaleofprincessaeryn.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  dofile("includes/CuboidSpaceStation.lua")
+?>
+
+<Level>
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.3, 0.3, 0.3"
+    skybox     = "Orxonox/skyBoxBasic"
+  >
+
+    <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <!-- Quest: -->
+    <GlobalQuest id="b80c2c60-e62c-4637-80f8-5aa18dc93b34">
+      <QuestDescription title="The Tale of Princess Aeryn" description="Princess Aeryn has been kidnapped by evil Mr. M and you were just a little too late to save her.\nYou have to find and save her from her captors." failMessage="You cannot fail, how did you?" completeMessage="You did it John. You're a hero. Princess Aeryn however will still not marry you." />
+      <subquests>
+        <GlobalQuest id="43766602-7e2f-4d24-976a-3f9de1474d5b">
+          <QuestDescription title="Find Aeryn's S.H.O.E.S." description="Oh, the kidnappers must have been in a hurry because they overlooked princess Aeryns S.H.O.E.S. (Super Heavily Organized Escape Ship) hidden in the asteroid field over there.\nFind it and look there for clues to Princess Aeryns whereabouts." completeMessage="You did it, Looking through her stuff you find an odd looking device - Could this be the receiver of Princess Aeryns locator beacon? - But it must be broken, the screen remains blank." />
+          <complete-effects>
+            <AddQuest questId="50845552-c8af-4091-947c-76bd850b224e" />
+          </complete-effects>
+        </GlobalQuest>
+        <GlobalQuest id="50845552-c8af-4091-947c-76bd850b224e">
+          <QuestDescription title="Repair the receiver." description="There is a space station called 'Serenity Station' near here. An engineer called Nathan Stark who shoud be able to help you lives there." completeMessage="'Yeah Nathan lives here, he'll shurely help you.'\nAnd he does, apparenty the device was just low on batteries so you're now able to locate your beloved Princess Aeryn." />
+          <hints>
+            <QuestHint id="b9b10841-b045-4797-b1d3-cfce760e1de6">
+              <QuestDescription title="The Katratzi Station" description="'We ain't buying!'\n'What do you want?'\n'No there lives no Nathan here.'\n'Fuck off.''" />
+            </QuestHint>
+            <QuestHint id="1ee785f8-b71d-4b51-b080-42cec5be8e3c">
+              <QuestDescription title="The Pegasus Station" description="'Hello friend.'\n'How can we help you?'\n'A Mr. Stark you say? Sorry no man with such a name lives here.'" />
+            </QuestHint>
+          </hints>
+          <complete-effects>
+            <AddQuest questId="97628524-b243-492c-b7b6-498f325b21d4" />
+          </complete-effects>
+        </GlobalQuest>
+        <GlobalQuest id="97628524-b243-492c-b7b6-498f325b21d4">
+          <QuestDescription title="Follow the dots" description="Just follow the dots, they'll lead you right to her." completeMessage="You found Princess Aeryn. Her captors give up at the shere sight ou you." />
+          <complete-effects>
+            <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+          </complete-effects>
+        </GlobalQuest>
+      </subquests>
+    </GlobalQuest>
+
+    <!-- Create spaceship spawner: -->
+    <ParticleSpawner position="0,0,100" source="Orxonox/BigExplosion1part3" lifetime=2.0 loop=0 autostart=0>
+      <events>
+      <spawn>
+        <EventTrigger delay=1>
+        <events>
+          <trigger>
+          <SpawnPoint position="0,0,100" spawnclass=SpaceShip pawndesign=spaceshipassff />
+          </trigger>
+        </events>
+        </EventTrigger>
+      </spawn>
+      </events>
+      <attached>
+      <QuestEffectBeacon position="0,0,0" times=1>
+        <effects>
+          <AddQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+          <AddQuest questId="43766602-7e2f-4d24-976a-3f9de1474d5b" />
+        </effects>
+        <events>
+          <execute>
+            <EventListener event=questbeacon1 />
+          </execute>
+        </events>
+        <attached>
+          <DistanceTrigger name=questbeacon1 position="0,0,0" distance=10 target="Pawn" />
+        </attached>
+      </QuestEffectBeacon>
+      </attached>
+    </ParticleSpawner>
+
+    <!-- Create world -->
+
+      <!-- Kidnapper flying away -->
+      <MovableEntity position="200,0,0" velocity="-140,0,-140" yaw=45>
+        <attached>
+          <Model position="0,0,0" scale=4 yaw=180 pitch=-90 roll=-90 mesh="pirate.mesh" />
+          <ParticleSpawner position="0,0,10" source="Orxonox/fire3" lifetime=2.0 loop=0 autostart=1 />
+          <QuestEffectBeacon position="0,0,0" times=1 active=false name=trail >
+            <effects>
+              <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+              <execute>
+                <EventListener event=questbeacon7 />
+              </execute>
+            </events>
+            <attached>
+              <DistanceTrigger name=questbeacon7 position="0,0,0" distance=10 target="Pawn" />
+            </attached>
+          </QuestEffectBeacon>
+        </attached>
+      </MovableEntity>
+
+      <!-- Asteroid field -->
+      <StaticEntity position="-500,0,-3000">
+        <attached>
+          <?lua
+            for i = 1, 200 do
+          ?>
+            <MovableEntity position="<?lua print(math.random() * 2000 - 1000)?>, <?lua print(math.random() * 2000 - 1000) ?>, <?lua print(math.random() * 2000 - 1000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.abs(math.random() * 30 -10)) ?>">
+              <attached>
+                <Model scale="<?lua print(math.random() * 50) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+              </attached>
+            </MovableEntity>
+          <?lua end ?>
+          <!-- S.H.O.E.S -->
+          <StaticEntity position="-300,0,0">
+            <attached>
+              <Model position="0,0,0" scale=4 yaw=180 pitch=-90 roll=-90 mesh="assff.mesh" />
+              <QuestEffectBeacon position="0,0,0" times=-1>
+                <effects>
+                  <CompleteQuest questId="43766602-7e2f-4d24-976a-3f9de1474d5b" />
+                </effects>
+                <events>
+                  <execute>
+                    <EventListener event=questbeacon2 />
+                  </execute>
+                </events>
+                <attached>
+                  <DistanceTrigger name=questbeacon2 position="0,0,0" distance=50 target="Pawn" />
+                </attached>
+              </QuestEffectBeacon>
+            </attached>
+          </StaticEntity>
+        </attached>
+      </StaticEntity>
+
+
+
+      <!-- Spacestations -->
+
+      <!-- Serenity Station -->
+      <StaticEntity scale=1 position="0,0,5000" yaw=30>
+        <attached>
+          <?lua
+            createSpaceStationPar(65461,2,1,2,1,2,1,100)
+          ?>
+          <QuestEffectBeacon position="0,450,0" times=1>
+            <effects>
+              <CompleteQuest questId="50845552-c8af-4091-947c-76bd850b224e" />
+            </effects>
+            <events>
+              <execute>
+                <EventListener event=questbeacon3 />
+              </execute>
+            </events>
+            <attached>
+              <Billboard position="0,0,0" colour="1.0,1.0,0" material="Examples/Flare" />
+              <DistanceTrigger name=questbeacon3 position="0,0,0" distance=100 target="Pawn" />
+            </attached>
+          </QuestEffectBeacon>
+        </attached>
+      </StaticEntity>
+
+      <!-- Katratzi Station -->
+      <StaticEntity scale=1 position="0,5000,300" yaw=60>
+        <attached>
+          <?lua
+            createSpaceStationPar(9851,2,1,2,1,2,1,100)
+          ?>
+          <QuestEffectBeacon position="0,450,0" times=1>
+            <effects>
+              <AddQuestHint hintId="b9b10841-b045-4797-b1d3-cfce760e1de6" />
+            </effects>
+            <events>
+              <execute>
+                <EventListener event=questbeacon4 />
+              </execute>
+            </events>
+            <attached>
+              <Billboard position="0,0,0" colour="1.0,1.0,0" material="Examples/Flare" />
+              <DistanceTrigger name=questbeacon4 position="0,0,0" distance=100 target="Pawn" />
+            </attached>
+          </QuestEffectBeacon>
+        </attached>
+      </StaticEntity>
+
+      <!-- Pegasus Station -->
+      <StaticEntity scale=1 position="-5000,100,1000" roll=30>
+        <attached>
+          <?lua
+            createSpaceStationPar(3574,2,1,2,1,2,1,100)
+          ?>
+          <QuestEffectBeacon position="200,450,0" times=1>
+            <effects>
+              <AddQuestHint hintId="1ee785f8-b71d-4b51-b080-42cec5be8e3c" />
+            </effects>
+            <events>
+              <execute>
+                <EventListener event=questbeacon5 />
+              </execute>
+            </events>
+            <attached>
+              <Billboard position="0,0,0" colour="1.0,1.0,0" material="Examples/Flare" />
+              <DistanceTrigger name=questbeacon5 position="0,0,0" distance=100 target="Pawn" />
+            </attached>
+          </QuestEffectBeacon>
+        </attached>
+      </StaticEntity>
+
+      <!-- Trail -->
+      <EventDispatcher>
+        <targets>
+          <EventTarget target=trail />
+        </targets>
+        <events>
+          <visibility>
+            <QuestListener questId="50845552-c8af-4091-947c-76bd850b224e" mode="complete" />
+          </visibility>
+          <activity>
+            <QuestListener questId="50845552-c8af-4091-947c-76bd850b224e" mode="complete" />
+          </activity>
+        </events>
+      </EventDispatcher>
+
+      <?lua
+        for i = 1, 25 do
+      ?>
+        <Billboard position="<?lua print(i*5000/25) ?>,<?lua print(450+i*(5000-450)/25) ?>,5000" colour="1.0,0,0" material="Examples/Flare" name=trail visible=false/>
+      <?lua end ?>
+
+      <!-- Hideout -->
+      <StaticEntity position="5000,5000,5000" >
+        <attached>
+          <Model scale="100" mesh="ast2.mesh" shadow=false />
+        </attached>
+      </StaticEntity>
+
+      <StaticEntity position="5400,5400,5000" visible=false name=trail >
+        <attached>
+          <Model position="0,0,0" scale=4 yaw=180 pitch=-90 roll=-90 mesh="pirate.mesh" visible=false name=trail />
+          <QuestEffectBeacon position="0,0,0" times=1 active=false name=trail >
+            <effects>
+              <CompleteQuest questId="97628524-b243-492c-b7b6-498f325b21d4" />
+            </effects>
+            <events>
+              <execute>
+                <EventListener event=questbeacon6 />
+              </execute>
+            </events>
+            <attached>
+              <DistanceTrigger name=questbeacon6 position="0,0,0" distance=100 target="Pawn" />
+            </attached>
+          </QuestEffectBeacon>
+        </attached>
+      </StaticEntity>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/quests.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/quests.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/quests.oxw	(revision 11817)
@@ -0,0 +1,231 @@
+<!-- -->
+<LevelInfo
+ name = "Quests showcase"
+ description = "Level to test and showcase quests."
+ tags = "test, showcase"
+ screenshot = "questsshowcase.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+    <templates>
+        <Template link=lodtemplate_default />
+    </templates>
+    <?lua include("includes/notifications.oxi") ?>
+
+    <Scene
+        ambientlight = "0.5, 0.5, 0.5"
+        skybox       = "Orxonox/Starbox"
+    >
+
+        <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+
+        <GlobalQuest id="quest0">
+            <QuestDescription title="Quest 0" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+            Ut consequat leo ut quam congue semper et eget nibh. Nunc sit amet velit eu lorem pretium adipiscing eu ut ante. Nulla facilisi. Pellentesque interdum, neque nec consectetur vulputate, mauris risus feugiat nunc, ac sollicitudin neque quam ut tellus. Morbi elit velit, tincidunt et hendrerit eget, rutrum at erat. Duis eros nulla, faucibus vitae blandit vitae, pharetra sollicitudin justo." failMessage="Fail message 0" completeMessage="Complete message 0" />
+        </GlobalQuest>
+        <GlobalQuest id="quest1">
+            <QuestDescription title="Quest 1" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor." failMessage="Fail message 1" completeMessage="Complete message 1" />
+            <hints>
+                <QuestHint id="quest1hint1">
+                    <QuestDescription title="The super Hint." description="Be proud of yourself." />
+                </QuestHint>
+                <QuestHint id="quest1hint2">
+                    <QuestDescription title="The super Hint2." description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor." />
+                </QuestHint>
+                <QuestHint id="quest1hint3">
+                    <QuestDescription title="The super Hint3." description="Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus." />
+                </QuestHint>
+            </hints>
+            <subquests>
+                <GlobalQuest id="quest1.1">
+                    <QuestDescription title="Quest 1: Subquest 1" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.2">
+                    <QuestDescription title="Quest 1: Subquest 2" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.3">
+                    <QuestDescription title="Quest 1: Subquest 3" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.4">
+                    <QuestDescription title="Quest 1: Subquest 4" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+                <GlobalQuest id="quest1.5">
+                    <QuestDescription title="Quest 1: Subquest 5" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam." failMessage="Fail message 2" completeMessage="Complete message 2" />
+                </GlobalQuest>
+            </subquests>
+        </GlobalQuest>
+        <GlobalQuest id="quest2">
+            <QuestDescription title="Quest 2" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac." failMessage="Fail message 2" completeMessage="Complete message 2" />
+        </GlobalQuest>
+        <GlobalQuest id="quest3">
+            <QuestDescription title="Quest 3" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit." failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+        <GlobalQuest id="quest4">
+            <QuestDescription title="Quest 4" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. Integer a nisl odio, in iaculis tortor. Nam erat erat, commodo quis tincidunt et, congue at quam. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+            Ut consequat leo ut quam congue semper et eget nibh. Nunc sit amet velit eu lorem pretium adipiscing eu ut ante. Nulla facilisi. Pellentesque interdum, neque nec consectetur vulputate, mauris risus feugiat nunc, ac sollicitudin neque quam ut tellus. Morbi elit velit, tincidunt et hendrerit eget, rutrum at erat. Duis eros nulla, faucibus vitae blandit vitae, pharetra sollicitudin justo. Donec luctus est a tortor auctor feugiat." failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+        <GlobalQuest id="quest5">
+            <QuestDescription title="Quest 5" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa." failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+        <GlobalQuest id="quest6">
+            <QuestDescription title="Quest 6" description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus at dolor quis dui gravida faucibus quis ut augue. Nulla sed accumsan nulla. Sed eleifend arcu ante, vel congue neque. Praesent vel felis sit amet lacus elementum laoreet at et massa. Pellentesque imperdiet orci sit amet sem gravida a ornare odio tempor. Donec posuere scelerisque purus, et porttitor ipsum dictum ac. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Sed non turpis non eros porttitor dignissim. Phasellus at elit vel diam gravida malesuada ut a lorem. Etiam vel lacus massa. In arcu neque, ultrices at placerat in, facilisis a metus. Curabitur erat nunc, molestie sed pretium ac, ullamcorper eget tellus. Vivamus tortor magna, mollis ut vulputate vel, lacinia nec neque. " failMessage="Fail message 1" completeMessage="Complete message 1" />
+        </GlobalQuest>
+
+        <EventMultiTrigger name=spawntrigger>
+            <events>
+                <trigger>
+                    <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+                </trigger>
+            </events>
+        </EventMultiTrigger>
+
+        <QuestEffectBeacon times=1>
+            <effects>
+                <AddQuest questId="quest0" />
+                <AddQuest questId="quest1" />
+                <AddQuest questId="quest1.1" />
+                <AddQuest questId="quest1.2" />
+                <AddQuest questId="quest1.3" />
+                <AddQuest questId="quest1.4" />
+                <AddQuest questId="quest1.5" />
+                <AddQuest questId="quest2" />
+                <AddQuest questId="quest3" />
+                <AddQuest questId="quest4" />
+                <AddQuest questId="quest5" />
+                <AddQuest questId="quest6" />
+                <AddQuestHint hintId ="quest1hint1" />
+                <AddQuestHint hintId ="quest1hint2" />
+                <AddQuestHint hintId ="quest1hint3" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=spawntrigger />
+                </execute>
+            </events>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="-100,0,0" times=1>
+            <effects>
+                <FailQuest questId="quest1.1" />
+                <FailQuest questId="quest1.2" />
+                <FailQuest questId="quest1.3" />
+                <FailQuest questId="quest1.4" />
+                <FailQuest questId="quest1.5" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=dtrigger1 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,0,0" material="Examples/Flare" />
+                <DistanceTrigger name=dtrigger1 position="0,0,0" distance=10 target="Pawn" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="100,0,0" times=-1>
+            <effects>
+                <CompleteQuest questId="quest0" />
+                <CompleteQuest questId="quest1" />
+                <CompleteQuest questId="quest1.1" />
+                <CompleteQuest questId="quest1.2" />
+                <CompleteQuest questId="quest1.3" />
+                <CompleteQuest questId="quest1.4" />
+                <CompleteQuest questId="quest1.5" />
+                <CompleteQuest questId="quest2" />
+                <CompleteQuest questId="quest3" />
+                <CompleteQuest questId="quest4" />
+                <CompleteQuest questId="quest5" />
+                <CompleteQuest questId="quest6" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=dtrigger2 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,1.0,0" material="Examples/Flare" />
+                <DistanceTrigger name=dtrigger2 position="0,0,0" distance=10 target="Pawn" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <!--QuestEffectBeacon position="0,0,100" times=-1>
+            <effects>
+                <AddQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt1 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt1 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="-100,0,0" times=-1>
+            <effects>
+                <FailQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt2 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="1.0,0,0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt2 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="100,0,0" times=-1>
+            <effects>
+                <CompleteQuest questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt3 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,1.0,0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt3 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <QuestEffectBeacon position="0,100,0" times=-1>
+            <effects>
+                <AddQuestHint hintId="022a859d-08dd-4eac-a085-c28c29c06d48" />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=qebdt4 />
+                </execute>
+            </events>
+            <attached>
+                <Billboard position="0,0,0" colour="0,0,1.0" material="Examples/Flare" />
+                <DistanceTrigger name=qebdt4 position="0,0,0" distance=10 target="ControllableEntity" />
+            </attached>
+        </QuestEffectBeacon>
+
+        <ParticleEmitter name=firecenter position="0,0,0" source="Orxonox/fire3" active=false>
+            <events>
+                <activity>
+                    <QuestListener questId="b80c2c60-e62c-4637-80f8-5aa18dc93b34" mode="complete" />
+                </activity>
+            </events>
+        </ParticleEmitter-->
+
+    </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/radar3D_test.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/radar3D_test.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/radar3D_test.oxw	(revision 11817)
@@ -0,0 +1,77 @@
+<LevelInfo
+ name = "radar3D_test"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipEscort.oxt")
+?>
+
+<Level
+  gametype     = "Mission"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-500,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+    
+
+
+	<Pawn team=0 health=30 position="0,0,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "0,0,0" >
+      		<attached>
+        	    <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+        	</attached>
+        	<collisionShapes>
+        	    <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+        	</collisionShapes>
+    	</Pawn>
+
+	<Pawn team=1 health=30 position="0,1000,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "0,1000,0" >
+		<attached>
+	            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+	        </attached>
+	        <collisionShapes>
+	            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+	        </collisionShapes>
+    	</Pawn>
+
+
+	<Pawn team=2 health=30 position="0,0,1000" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "0,0,1000" >
+		<attached>
+	            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+	        </attached>
+	        <collisionShapes>
+	            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+	        </collisionShapes>
+    	</Pawn>
+
+	<Pawn team=3 health=30 position="1000,0,0" direction="0,-1,0" collisionType=dynamic mass=100000 name=box radarname = "1000,0,0" >
+		<attached>
+	            <Model position="0,0,0" mesh="crate.mesh" scale3D="3,3,3" />
+	        </attached>
+	        <collisionShapes>
+	            <BoxCollisionShape position="0,0,0" halfExtents="15,15,15" />
+	        </collisionShapes>
+    	</Pawn>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/screenshot.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/screenshot.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/screenshot.oxw	(revision 11817)
@@ -0,0 +1,141 @@
+<LevelInfo
+ name = "Screenshot"
+ description = "Level to make awesome screenshots in."
+ tags = "test, showcase"
+ screenshot = "screenshot.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "TeamDeathmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.7, 0.6, 0.6"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <!--Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" /-->
+    <Light type=directional position="1100, 11000, -7000" lookat="0, 0, 0" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <TeamSpawnPoint team=0 position="1100, 11000, -7000" orientation="0.509856, -0.379863, 0.650825, 0.414944" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <SpaceShip position="1170, 11250, -6780" roll=90>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=1100 team=0>
+          <waypoints>
+            <StaticEntity position="1000,10300,-7000" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="1100,10700,-7000" roll=90>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=0 team=0 />
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="1100,10600,-7000" roll=90>
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+    </SpaceShip>
+
+<!--
+    <TeamSpawnPoint team=1 position="2000,  0,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+    <TeamSpawnPoint team=1 position="2000, 50,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+    <TeamSpawnPoint team=1 position="2000,100,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+    <TeamSpawnPoint team=1 position="2000,150,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+
+    <TeamSpawnPoint team=2 position="1000,  0,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+    <TeamSpawnPoint team=2 position="1000, 50,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+    <TeamSpawnPoint team=2 position="1000,100,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+    <TeamSpawnPoint team=2 position="1000,150,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+-->
+
+    <StaticEntity position="1100,9700,-7500" lookat="1500, 10000, -6700" yaw="-90" pitch="-90">
+      <attached>
+        <Model scale=10 mesh="Carrier.mesh" />
+        <Model position="0,30,20" scale=10 mesh="pirate.mesh" roll="180" />
+        <Model position="-80,-30,20" scale=10 mesh="pirate.mesh" roll="180" />
+      </attached>
+    </StaticEntity>
+
+    <?lua
+      elements = {"BodyDebris1.mesh", "CockpitDebris.mesh", "LightningGun.mesh", "WingDebris1.mesh", "WingDebris2.mesh", "satellitedish.mesh", "Thruster.mesh"}
+      sizes = {4, 4, 4, 4, 4, 10, 20}
+      
+      elements.length = function()
+        return table.getn(elements)
+      end
+      
+      for i = 1, 150, 1 do
+        x = math.random() * 750 - 375 + 1000
+        y = math.random() * 1000 - 500 + 10200
+        z = math.random() * 500 - 250 - 6600
+        e = math.floor(math.random()*elements.length()+1)
+    ?>
+
+      <MovableEntity position="<?lua print(x) ?>,<?lua print(y) ?>,<?lua print(z) ?>" linearDamping=0.8 angularDamping=0.8 rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 - 15) ?>">
+        <attached>
+          <Model position="0,0,0" scale="<?lua print(sizes[e]) ?>" mesh="<?lua print( elements[e]) ?>" />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+    <?lua
+      for i = 1, 70, 1 do
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 1000 + 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * -1000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 1000 + 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * -1000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 1000 + 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * -1000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/scriptController.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/scriptController.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/scriptController.oxw	(revision 11817)
@@ -0,0 +1,67 @@
+<!-- First levelFile of mkronig and samuezu. It was copied from dockingToASpaceStation.oxw and modified a little bit -->
+<LevelInfo
+ name = "Scriptable Controller"
+ description = "Showcase for Scriptable Controller"
+ tags = "showcase"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipEscort.oxt")
+?>
+
+<Level
+  gametype = Deathmatch
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <Scene
+    ambientlight = "0.5, 0.5, 0.5"
+    skybox       = "Orxonox/Starbox"
+    negativeWorldRange = "-100000, -100000, -100000"
+    positiveWorldRange = " 100000,  100000,  100000"
+    gravity      = "0,0,0"
+    hasPhysics   = true
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0,1.0,1.0,0.5" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <SpawnPoint team=0 position="3200,0,0" lookat="2800,0,0" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+    <Billboard position="2500,0,0" material="Flares/ringflare2" colour="0.2,0.4,0.8" scale=10 />
+    <DistanceTrigger position="2500,0,0" distance="200" target="Pawn"
+      beaconMode="exclude" targetname="bcnDestroyer" name="takeControl"
+    />
+
+    <StaticEntity position  = "2000,500,2000" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=10 />
+      </attached>
+    </StaticEntity>
+
+    <StaticEntity position  = "-1000,3000,-1000" mass=10000 collisionType=static >
+      <attached>
+        <Model mesh="HydroHarvester.mesh" mass=10 position="0,0,0" scale=80 />
+      </attached>
+    </StaticEntity>
+
+<!-- ControllerDirector waits for the event takeControl to attach a new Controller -->
+    <ControllerDirector position="0,0,0" scriptname="presentation">
+        <events>
+            <takeControl>
+                <EventListener event="takeControl" />
+            </takeControl>
+        </events>
+    </ControllerDirector>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/shadertest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/shadertest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/shadertest.oxw	(revision 11817)
@@ -0,0 +1,112 @@
+<LevelInfo
+ name = "Shader Test"
+ description = "Level to test shader functionality. Based on Asteroidfields."
+ tags = "test"
+ screenshot = "codingtutorial.png"
+ startingships = "spaceshipassff, spaceshipghost, spaceshipspacecruiser"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level
+ name         = "Sample"
+ description  = "Just a few tests"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+    hasPhysics   = true
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+
+
+
+    <!-- Belt that's far away  *** TURNED OFF FOR PERFORMANCE REASONS *** -->
+    <!-- Generate asteroid field and asteroid belt -->
+    <!--
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(0, 0, 0, -48, -34, 70, 100, 200, 219900, 210000, 900, 1)
+    ?>
+    -->
+
+
+    <!-- triple large belt around the planet  -->
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 7190, 7800, 250, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 10000, 11000, 300, 1)
+    ?>
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(15000, 0, 0, 30, 0, 30, 30, 50, 14000, 15000, 350, 1)
+    ?>
+
+<Drone name="meineDrohne" primarythrust="80" auxilarythrust="10" rotationthrust="10" mass="50" linearDamping="0.9" angularDamping="0.7">
+  <attached>
+    <Model position="10,10,10" scale="30" mesh="planets/earth.mesh" renderQueueGroup="stencil glow" material="glow"/>
+    <Model position="10,10,10" scale="30" mesh="planets/earth.mesh" renderQueueGroup="main" />
+  </attached>
+  <collisionShapes>
+    <SphereCollisionShape position="10,10,10" radius="30" />
+  </collisionShapes>
+</Drone>
+
+<LensFlare position="10000,20,5000" fadeOnViewBorder="true" fadeResolution="11" fadeExponent="2.0" scale="1.0" colour="1.0,0.85,0.8">
+</LensFlare>
+
+    <!-- Planet close to spawn point -->
+
+    <Planet
+      position="15000,0,-1000"
+      scale="5000"
+      collisionType="dynamic"
+      linearDamping="0.8"
+      angularDamping="0"
+      mass="10000000"
+      pitch="0"
+      mesh="planets/muunilinst.mesh"
+      atmosphere="atmosphere1"
+      rotationaxis="1,0,0"
+      rotationrate="1.0"
+      atmospheresize="80.0f"
+      imagesize="1024.0f"
+      collisiondamage = 2
+      enablecollisiondamage = true
+    >
+      <attached>
+        <ForceField position="5000,0,0" mode="sphere" diameter="10000" velocity="-50" />
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="5000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+
+
+
+
+
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/shieldTest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/shieldTest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/shieldTest.oxw	(revision 11817)
@@ -0,0 +1,81 @@
+<LevelInfo
+ name = "Shield Testlevel"
+ description = "A simple Level with one shielded drone to shoot at"
+ tags = "test"
+ screenshot = "shieldtestlevel.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipImmTest.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+
+<templates>
+  <Template link=lodtemplate_default />
+</templates>
+<?lua include("includes/notifications.oxi") ?>
+
+<Scene
+   ambientlight = "0.8, 0.5, 0.5"
+   skybox       = "Orxonox/Starbox"
+>
+
+<Drone name="meineDrohne"
+    primarythrust= "80"
+    auxilarythrust= "10"
+    rotationthrust= "10"
+    mass= "50"
+    linearDamping= "0.9"
+    angularDamping= "0.7"
+
+    health= 100
+    maxhealth= 150
+    inithealth= 200
+
+    shieldhealth= 100
+    initialshieldhealth= 200
+    maxshieldhealth= 250
+
+    shieldabsorption= 1
+
+    shieldrechargerate = "10"
+    shieldrechargewaittime = 1
+
+>
+  <attached>
+    <Model scale="4" mesh="drone.mesh"/>
+  </attached>
+  <collisionShapes>
+    <BoxCollisionShape position="0,0,0"      halfExtents="10, 10, 10" />
+  </collisionShapes>
+</Drone>
+
+<Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpawnPoint position="<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipimmtest />
+    <?lua end ?>
+
+    <GlobalShader compositor="Bloom" visible=false>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,0,0" distance=30 target="Spectator" switch=true />
+        </visibility>
+      </events>
+    </GlobalShader>
+    <Model position="0,0,0" scale=8 mesh="ast1.mesh" />
+    <StaticEntity position="0,0,0" collisionType=static>
+      <collisionShapes>
+        <SphereCollisionShape radius="20" />
+      </collisionShapes>
+    </StaticEntity>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/shuttleAttack.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/shuttleAttack.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/shuttleAttack.oxw	(revision 11817)
@@ -0,0 +1,1172 @@
+<!--TODO: Shuttle and Stations -->
+<LevelInfo
+    name = "Shuttle under Attack"
+    description = "The newly discovered hostile alien species is attacking one of our outset stations, Andromeda! There is no protecting it; you have to escort the escape shuttle to a safer location."
+    tags = "mission"
+    screenshot = "shuttleProtect.png"
+/>
+
+<?lua
+    include("stats.oxo")
+    include("HUDTemplates3.oxo")
+    include("HUDTemplatesFPS.oxo")
+    include("templates/lodInformation.oxt")
+
+    include("templates/spaceshipAssff.oxt")
+    include("templates/spaceshipPirate.oxt")
+    include("templates/spaceshipEscort.oxt")
+    include("templates/spaceshipShuttle.oxt")
+    include("templates/FPS.oxt")
+    include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level gametype = "Mission">
+    <templates>
+        <Template link="lodtemplate_default" />
+    </templates>
+
+    <?lua include("includes/notifications.oxi") ?>
+
+    <NotificationQueueCEGUI
+        name="narrative"
+        targets="simpleNotification"
+        size=3
+        displayTime=3.9
+        position="0.15, 0, 0.1, 0"
+        fontSize="15"
+        fontColor="0.3, 1, 0.2, 0.8"
+        alignment="HorzCentred"
+        displaySize="0.7, 0, 0, 0"
+    />
+
+    <!-- GLOBAL LUA VARIABLES -->
+    <?lua
+        waves = 3
+        enemiesInit = 5
+        enemiesIncrease = 2
+        allies = 3
+
+        --[[ Coordinates in (y,z,x). NOTE: Indexing starts at 1 in lua! Don´t forget to adapt the for loops, too! ]]--
+        cCenter = {0, 0, 0}
+        cSpawn = {-50, 0, 0}
+        cUnit = {-2000, 0, 3000}
+        cA = {-3000, 0, 5000}
+        cB = {-3000, 0, -5000}
+        cC = {-2300, 0, 0}
+        dStation = {1, 0, 0}
+        cNewShip = {-2100, 0, 4100}
+        cFPSGround = {-2300, 800, 0}
+        cFPS = {-2300, 1000, 0}
+        cField1 = {400, 0, 2500}
+        cField2 = {400, 0, -2500}
+        cPlanet1 = {8000, -2000, 15000}
+        cPlanet2 = {-20000, 4000, -1000}
+        rAllies = {3000, -2000}         --[[ To be addressed directly, hence r. Do not permute! ]]--
+
+        --[[ Function to print Coordinates. Quotes not included! ]]--
+        function printC(coord)
+          print(coord[1] .. [[,]] .. coord[2] .. [[,]] .. coord[3])
+        end
+    ?>
+
+    <Scene
+        ambientlight = "0.8, 0.8, 0.8"
+        skybox = "Orxonox/skyBoxMoreNebula"
+        hasPhysics = true
+    >
+
+    <SpawnPoint name="playerSpawn" team=0 position="<?lua printC(cSpawn) ?>" lookat="<?lua printC(cA) ?>" spawnclass=SpaceShip pawndesign=spaceshipescort />
+
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" />
+
+    <Light type=directional position="<?lua printC(cCenter) ?>" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <!--QUEST DEFINITIONS-->
+
+    <GlobalQuest id="quest1">
+        <QuestDescription title="Reach Andromeda Station!" description="You need to get in contact with your base! Word is enemies are preparing to attack our people and goods! Be quick!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <complete-effects>
+            <AddQuest questId="quest2" />
+            <AddQuest questId="quest2.1" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest2">
+        <QuestDescription title="Prepare to fight the Enemy" description="You need to be prepared, mentally and physically! So gather all your strength and forces to destroy those space pirates!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <subquests>
+            <GlobalQuest id="quest2.1">
+                <QuestDescription title="> Get a better Spaceship" description="Take over the faster, stronger, more secure and overall better spaceship!" failMessage="" completeMessage="" />
+                <complete-effects>
+                    <AddQuest questId="quest2.2" />
+                </complete-effects>
+            </GlobalQuest>
+            <GlobalQuest id="quest2.2">
+                <QuestDescription title="> Meet your Unit" description="Your unit will help you, where ever you go. To victory or to death, they will be loyal to you!" failMessage="" completeMessage="" />
+            </GlobalQuest>
+        </subquests>
+        <complete-effects>
+            <AddQuest questId="quest3" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest3">
+        <QuestDescription title="Fight the first Wave" description="Five enemies are approaching you! There main target is the shuttle though, so destroy them - before the destroy the escape shuttle with the valuebals goods (and of course the people aboard)!" failMessage="Oh no! You have to be better, they destroyed the shuttle!" completeMessage="Good Job!" />
+        <hints>
+        </hints>
+        <complete-effects>
+            <AddQuest questId="quest4" />
+            <AddQuest questId="quest4.1" />
+            <AddQuest questId="quest4.2" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest4">
+        <QuestDescription title="Prepare for the next Wave" description="This was just a scouting troop from the enemies, they know now how many there are from us and will send a bigger troop next time! Prepare yourself..." failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <subquests>
+            <GlobalQuest id="quest4.1">
+                <QuestDescription title="> Get to the Defense Station" description="Fly to the defense station, we will guard your spaceship while you will fight them with the Cannon Suit." failMessage="" completeMessage="" />
+            </GlobalQuest>
+            <GlobalQuest id="quest4.2">
+                <QuestDescription title="> Get into the Cannon Suit!" description="Dock to the defense station, you will be able to contol the Cannon Suit on top of the station, perfect for fighting off a hord of enemies!" failMessage="" completeMessage="" />
+            </GlobalQuest>
+        </subquests>
+        <complete-effects>
+            <AddQuest questId="quest5" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest5">
+        <QuestDescription title="Fight the Hord!" description="Destroy the next wave!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <complete-effects>
+            <AddQuest questId="quest6" />
+            <AddQuest questId="quest6.1" />
+            <AddQuest questId="quest6.2" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest6">
+        <QuestDescription title="Get back for the Showdown" description="Undock from the defense station and get into your Spaceship!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <subquests>
+            <GlobalQuest id="quest6.1">
+                <QuestDescription title="> Collect the local Pickups" description="There is a box with pickups close to the station, you can collect them if you want to, but it is advised to do so. They will support your task in destroying the enemies and make your life easier." failMessage="" completeMessage="" />
+            </GlobalQuest>
+            <GlobalQuest id="quest6.2">
+                <QuestDescription title="> Get back to the Shuttle" description="Fly to the Shuttle!" failMessage="" completeMessage="" />
+            </GlobalQuest>
+        </subquests>
+        <complete-effects>
+            <AddQuest questId="quest7" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest7">
+        <QuestDescription title="Fight the final Wave" description="Good gracious, another hord of pirate ships!" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <subquests>
+        </subquests>
+    </GlobalQuest>
+
+    <!--EVENTS AND TRIGGERS
+        Usable events and triggers:
+        _spawntrigger
+        _reachedA
+        _dock<A|B|C>
+        _docked<A>      WIP; see below
+        -joinedUnit
+        _wave<k>
+        _killedEnemy<k>.<i>
+        _waveClear<k>
+    -->
+
+
+
+    <EventMultiTrigger name="spawntrigger" activations=1>
+        <events>
+            <trigger>
+                <EventListener event="playerSpawn" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger name="reachedA" position="<?lua printC(cA) ?>" distance=1000 target="SpaceShip" beaconMode="exclude" targetname="NPC" stayactive=true />
+
+    <!-- HACK: just waited out 3sec for animation. Cannot link an event to the COMPLETION of a dock. How is this not possible?? -->
+    <EventMultiTrigger name="dockedA" activations="1" stayactive="true" delay=3>
+        <events>
+            <trigger>
+                <EventListener event="dockA" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger name="joinedUnit" active=false position="<?lua printC(cUnit) ?>" distance=100 target="SpaceShip" beaconMode="exclude" targetname="NPC" stayactive=true>
+        <events>
+            <activity>
+                    <EventListener event="dockedA" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <EventMultiTrigger name="wave1" activations="1" delay=4>
+        <events>
+            <trigger>
+                <EventListener event="joinedUnit" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <!-- Recursive helper function for the end-of-wave events. F*ck the event system, seriously. -->
+    <?lua
+    function enemyTriggerRecursor(i, k)
+    if i > 0 then
+    return [[
+    <EventTrigger name=killedEnemy]] .. k .. [[.]] .. i .. [[ activations=1 stayactive=true delay=0.1>
+        <events>
+            <trigger>
+                <EventListener event=attackers]] .. k .. [[ />
+            </trigger>
+        </events>
+        ]] .. enemyTriggerRecursor(i-1, k) .. [[
+    </EventTrigger>
+    ]]
+    else return ""
+    end
+    end
+    ?>
+    <!-- Actual recursive Event(s) for the respective waves. -->
+    <?lua
+    enemies = enemiesInit
+    for k = 1, waves, 1
+    do
+    print(enemyTriggerRecursor(enemies,k))
+    ?>
+    <EventMultiTrigger name="waveClear<?lua print(k) ?>" delay=4.0>
+        <events>
+            <trigger>
+                <EventListener event="killedEnemy<?lua print(k .. [[.]] .. enemies) ?>" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+    <?lua enemies = enemies + enemiesIncrease ?>
+    <?lua end ?>
+
+    <!-- This controls the ally AI controller so it is only active when active enemies are around! -->
+    <EventDispatcher name="allyControllerDispatcher">
+      <targets>
+        <EventTarget target="allyController" />
+      </targets>
+      <events>
+          <activity>
+              <?lua
+              for k = 1, waves, 1 do
+              ?>
+              <Trigger mode=and>
+                  <EventTrigger>
+                      <events>
+                          <trigger>
+                              <EventListener event="wave<?lua print(k) ?>" />
+                          </trigger>
+                      </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                      <events>
+                          <trigger>
+                              <EventListener event="waveClear<?lua print(k) ?>" />
+                          </trigger>
+                      </events>
+                  </EventTrigger>
+              </Trigger>
+              <?lua end ?>
+          </activity>
+      </events>
+    </EventDispatcher>
+
+    <DistanceTrigger active=false name="reachedC" position="<?lua printC(cC) ?>" distance=400 target="SpaceShip" beaconMode="exclude" targetname="NPC" stayactive=true>
+        <events>
+            <activity>
+                <EventListener event="waveClear1" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <EventMultiTrigger name="dockedC" activations="1" stayactive="true" delay=3>
+        <events>
+            <trigger>
+                <EventListener event="dockC" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventMultiTrigger name="wave2" activations="1" delay=8>
+        <events>
+            <trigger>
+                <EventListener event="dockedC" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventMultiTrigger name="readyAfterWave2" activations="1" delay=2 stayactive=true>
+        <events>
+            <trigger>
+                <Trigger mode=and>
+                    <EventTrigger>
+                        <events>
+                            <trigger>
+                                <EventListener event="undockC" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                    <EventTrigger>
+                        <events>
+                            <trigger>
+                                <EventListener event="waveClear2" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                </Trigger>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <!-- See the DistanceTrigger attached to the shuttle here! !-->
+
+    <EventMultiTrigger name="wave3" activations="1" delay=12>
+        <events>
+            <trigger>
+                <EventListener event="reachedShuttle" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger active=false name="reachedB" position="<?lua printC(cB) ?>" distance=400 target="SpaceShip" beaconMode="exclude" targetname="NPC" stayactive=true>
+        <events>
+            <activity>
+                <EventListener event="waveClear3" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <Script code="Mission endMission true" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="reachedB" />
+            </trigger>
+        </events>
+    </Script>
+
+    <EventMultiTrigger name="missionFailed" activations="1" stayactive=true>
+        <events>
+            <trigger>
+                <EventListener event="transporter" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventMultiTrigger name="failMissionHelper" delay=4 stayactive=true>
+        <events>
+            <trigger>
+                <EventListener event="missionFailed" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger active=false name="failMission" position="<?lua printC(cA) ?>" distance=100 target="SpaceShip" beaconMode="exclude" targetname="NPC" stayactive=true>
+        <events>
+            <activity>
+                <EventListener event="failMissionHelper" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <!--HACK: Ultimately settled on docking A to fail the mission... that makes a whole lot of sense. -->
+
+    <Script code="Mission endMission fail" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="failMission" />
+            </trigger>
+        </events>
+    </Script>
+
+    <!--QUEST EFFECT BEACONS -->
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuest questId="quest1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="spawntrigger" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="reachedA" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest2.1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockedA" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest2.2" />
+            <CompleteQuest questId="quest2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="joinedUnit" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest3" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="waveClear1" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest4.1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="reachedC" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest4.2" />
+            <CompleteQuest questId="quest4" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="dockedC" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest5" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="waveClear2" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest6.1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="gotPickups" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest6.2" />
+            <CompleteQuest questId="quest6" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="reachedShuttle" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest7" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="waveClear3" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!--NOTIFICATIONS -->
+
+    <SimpleNotification broadcast="true" message="Welcome, Commander. Please report at Andromeda Station.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Our enemy is set to attack us very soon.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=8 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Please study your mission briefing!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=12 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Welcome to Andromeda, Commander.">
+        <events>
+            <trigger>
+                <EventListener event="reachedA" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="We've prepared a reinforced Ship for you.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedA" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Now join our defense Team.">
+        <events>
+            <trigger>
+                <EventListener event="dockedA" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Howdy Commander! Ready to kick some alien ass?">
+        <events>
+            <trigger>
+                <EventListener event="joinedUnit" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!-- HACK: Somehow only fires a second time if the (notification,event) pairs are separate! WTF -->
+    <?lua
+    for k = 1, waves, 1 do
+    ?>
+    <SimpleNotification broadcast="true" message="An enemy wave is approaching the shuttle!">
+        <events>
+            <trigger>
+                <EventListener event="wave<?lua print(k) ?>" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+    <?lua end ?>
+
+    <SimpleNotification broadcast="true" message="yippie ki yay motherf*cker!">
+        <events>
+            <trigger>
+                <EventListener event="attackers1" />
+                <EventListener event="attackers2" />
+                <EventListener event="attackers3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Phew, that was close! Well done, Commmander.">
+        <events>
+            <trigger>
+                <EventListener event="waveClear1" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="But it's not over yet! Get to the defense station and dock!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="waveClear1" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="This is our powerful reinforced cannon suit.">
+        <events>
+            <trigger>
+                <EventListener event="dockedC" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="It should deal with those pesky invaders!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="dockedC" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Brilliant work, Commander! now undock again.">
+        <events>
+            <trigger>
+                <EventListener event="waveClear2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Here's some supplies for you. Shoot that crate!">
+        <events>
+            <trigger>
+                <EventListener event="readyAfterWave2" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Our Intelligence reports one more wave...">
+        <events>
+            <trigger>
+                <EventListener event="reachedShuttle" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Ready to be a hero, Commander?">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedShuttle" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Congrats, Commander! You saved our skin.">
+        <events>
+            <trigger>
+                <EventListener event="waveClear3" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Get over to the safe base to take a break.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="waveClear3" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="It's over... we failed. Retreat to Andromeda!">
+        <events>
+            <trigger>
+                <EventListener event="missionFailed" />
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <!--STATIONS -->
+
+    <!-- (Temporary) Template for stations. Used to define common features of all Stations. -->
+    <Template name="station">
+        <Pawn mass=10000000 collisionType=dynamic friction=0.01>
+            <attached>
+                <Model mesh="HydroHarvester.mesh" position="0,0,0" scale=50 />
+                <DistanceTriggerBeacon name="NPC" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape  position="-560,0,0" halfExtents="115,100,245" /><!-- Three lower boxes -->
+                <BoxCollisionShape  position="290,0,-480" halfExtents="115,100,245" yaw=-120 />
+                <BoxCollisionShape  position="290,0,480" halfExtents="115,100,245" yaw=-240 />
+                <BoxCollisionShape  position="-280,0,0" halfExtents="163,50,50" /><!-- Three lower connections -->
+                <BoxCollisionShape  position="140,0,-240" halfExtents="163,50,50" yaw=-120 />
+                <BoxCollisionShape  position="140,0,240" halfExtents="163,50,50" yaw=-240 />
+                <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" /><!-- Upper Tower -->
+                <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-120 />
+                <BoxCollisionShape  position="0,530,0" halfExtents="172,52,298" yaw=-240 />
+                <BoxCollisionShape  position="0,400,0" halfExtents="43,110,26" yaw=-30 /><!-- Middle one-->
+                <BoxCollisionShape  position="-200,100,0" halfExtents="26,50,43" /><!--Three lower legs -->
+                <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=-30 />
+                <BoxCollisionShape  position="100,100,-173" halfExtents="43,50,26" yaw=30 />
+                <BoxCollisionShape  position="-100,264,0" halfExtents="26,105,43" roll=-49 /><!--Three upper legs -->
+                <BoxCollisionShape  position="50,264,-87" halfExtents="26,105,43" roll=-49 yaw=-120 />
+                <BoxCollisionShape  position="50,264,87" halfExtents="26,105,43" roll=-49 yaw=-240 />
+            </collisionShapes>
+        </Pawn>
+    </Template>
+
+    <!-- A, Coordinates are approx. (cos(29pi/16), sin(29pi/16), 0)*3000 -->
+    <Pawn name="statA" team=0 radarname="Andromeda Station" position="<?lua printC(cA) ?>" direction="<?lua printC(dStation) ?>" yaw=-50 initialhealth=10000 maxhealth=10000>
+        <templates>
+            <Template link="station" />
+        </templates>
+        <attached>
+            <DockingTarget name="dockTargetA" />
+            <Dock position="0,0,0" active=true>
+                <animations>
+                    <MoveToDockingTarget target="dockTargetA" />
+                </animations>
+                <effects>
+                    <DockToShip target="newSpaceShip" />
+                </effects>
+                <events>
+                    <execute>
+                        <EventListener event="dockA" />
+                    </execute>
+                </events>
+                <attached>
+                    <DistanceTrigger position="0,0,0" distance="200" target="SpaceShip" beaconMode="exclude" targetname="NPC" name="dockA" />
+                    <Billboard position="0,0,0" amplitude=1 material="Flares/lensflare" colour="1,0,0.05" />
+                </attached>
+            </Dock>
+        </attached>
+    </Pawn>
+
+    <!-- B, Coordinates are approx. (-cos(29pi/16), sin(29pi/16), 0)*3000 -->
+    <Pawn name="statB" team=0 radarname="Safe Base" position="<?lua printC(cB) ?>" direction="<?lua printC(dStation) ?>" yaw=210 initialhealth=10000 maxhealth=10000>
+        <templates>
+            <Template link="station" />
+        </templates>
+        <attached>
+            <DockingTarget name="dockTargetB" />
+            <Dock position="0,0,0" active=false>
+                <animations>
+                    <MoveToDockingTarget target="dockTargetB" />
+                </animations>
+                <effects>
+                    <DockToShip target="newSpaceShip" />
+                </effects>
+                <events>
+                    <execute>
+                        <EventListener event="dockB" />
+                    </execute>
+                </events>
+                <attached>
+                    <DistanceTrigger position="0,0,0" distance="200" target="SpaceShip" beaconMode="exclude" targetname="NPC" name="dockB" />
+                    <Billboard position="0,0,0" amplitude=1 material="Flares/lensflare" colour="1,0,0.05" />
+                </attached>
+            </Dock>
+        </attached>
+    </Pawn>
+
+    <!-- C -->
+    <Pawn name="statC" team=0 radarname="Defense Station" position="<?lua printC(cC) ?>" direction="<?lua printC(dStation) ?>" initialhealth=10000 maxhealth=10000>
+        <templates>
+            <Template link="station" />
+        </templates>
+        <attached>
+            <DockingTarget name="dockTargetC" />
+            <Dock position="0,0,0">
+                <animations>
+                    <MoveToDockingTarget target="dockTargetC" />
+                </animations>
+                <effects>
+                    <DockToShip target="fpsMode" />
+                </effects>
+                <events>
+                    <execute>
+                        <EventListener event="dockC" />
+                    </execute>
+                </events>
+                <attached>
+                    <!--HACK: We use another dock to undock back to the ship since undocking is not implemented... -->
+                    <Dock position="0,0,0" active=true>
+                        <effects>
+                            <DockToShip target="newSpaceShip" />
+                        </effects>
+                        <events>
+                            <execute>
+                                <EventListener event="undockC" />
+                            </execute>
+                        </events>
+                    </Dock>
+                    <DistanceTrigger active=false position="0,0,0" distance="200" target="SpaceShip" beaconMode="exclude" targetname="NPC" name="dockC">
+                        <events>
+                            <activity>
+                                <EventListener event="reachedC" />
+                            </activity>
+                        </events>
+                    </DistanceTrigger>
+                    <Billboard position="0,0,0" amplitude=1 material="Flares/lensflare" colour="1,0,0.05" />
+                </attached>
+            </Dock>
+        </attached>
+    </Pawn>
+
+    <!-- New SpaceShip as destination of dock A-->
+    <SpaceShip
+            template            = "spaceshipassff"
+            team                = "0"
+            position            = "<?lua printC(cNewShip) ?>"
+            lookat              = "<?lua print(rAllies[2] .. ',' .. [[0]] .. ',' .. rAllies[1]) ?>"
+            health              = "400"
+            initialhealth       = "400"
+            maxhealth           = "1500"
+            shieldhealth        = "80"
+            initialshieldhealth = "80"
+            maxshieldhealth     = "120"
+            shieldabsorption    = "0.8"
+            reloadrate          = "1"
+            reloadwaittime      = "1"
+            name                = "newSpaceShip"
+            radarname           = "Defender" >
+        <attached>
+            <DockingTarget name="newSpaceShip" />
+            <DistanceTriggerBeacon name="newSpaceShip" />
+        </attached>
+    </SpaceShip>
+
+    <!-- FPS Player as destination of dock C -->
+    <FpsPlayer team=0 template = "fps" radarname = "Cannon Suit" position = "<?lua printC(cFPS) ?>" lookat="<?lua printC(cCenter) ?>">
+        <attached>
+            <DockingTarget name="fpsMode" />
+            <DistanceTriggerBeacon name="fpsPlayer" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="1,1,1"/>
+        </collisionShapes>
+    </FpsPlayer>
+
+    <!-- Floor for FPS Player -->
+    <StaticEntity position="<?lua printC(cFPSGround) ?>" collisionType=static mass=100000 friction=0.01 >
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="80,5,80" />
+            <Billboard position="320,50,320" material="Flares/ringflare2" colour="0.2,0.4,0.8" />
+    	    <DistanceTrigger position="320,50,320" distance="50" target="Pawn" beaconMode="identify" targetname="fpsPlayer" name="undockC" stayactive=true />
+            <ForceField active=false position="0,0,0" mode="homogen" diameter="600" forcedirection = "0,-500,0" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="400,25,400" />
+        </collisionShapes>
+    </StaticEntity>
+
+    <!--ELEMENTS -->
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+       asteroidField(cField1[1], cField1[2], cField1[3], 20, 30, 2000, 250, 0)
+    ?>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+       asteroidField(cField2[1], cField2[2], cField2[3], 20, 30, 2000, 250, 0)
+    ?>
+
+    <Planet
+        position="<?lua printC(cPlanet1) ?>"
+        scale="2000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/muunilinst.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage = 2
+        enablecollisiondamage = true
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="4000" velocity="-500" />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="2000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(cPlanet1[1], cPlanet1[2], cPlanet1[3], 30, 0, 30, 20, 40, 2800, 3000, 200, 1)
+    ?>
+
+    <Planet
+        position="<?lua printC(cPlanet2) ?>"
+        scale="3000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/planet3.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage = 2
+        enablecollisiondamage = true
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="6000" velocity="-500" />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="3000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(cPlanet2[1], cPlanet2[2], cPlanet2[3], 30, 20, 100, 20, 40, 3400, 3700, 400, 1)
+    ?>
+
+    <Pawn team=0 health=30 position="<?lua print((cC[1]+600) .. ',' .. cC[2] .. ',' .. (cC[3]-600)) ?>" direction="0,-1,0" collisionType=dynamic mass=1000 radarname="Supplies" name="gotPickups">
+        <events>
+            <visibility>
+                <EventListener event="readyAfterWave2" />
+            </visibility>
+            <activity>
+                <EventListener event="readyAfterWave2" />
+            </activity>
+        </events>
+        <attached>
+            <Model position="0,0,0" mesh="crate.mesh" scale3D="10,10,10" />
+        </attached>
+        <collisionShapes>
+            <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+        </collisionShapes>
+    </Pawn>
+
+    <?lua
+        include("includes/pickups.oxi")
+    ?>
+
+    <PickupSpawner pickup=hugeshieldpickup position="<?lua print((cC[1]+585) .. ',' .. cC[2] .. ',' .. (cC[3]-585)) ?>" triggerDistance="15" maxSpawnedItems="1">
+        <events>
+            <visibility>
+                <EventListener event="readyAfterWave2" />
+            </visibility>
+            <activity>
+                <EventListener event="readyAfterWave2" />
+            </activity>
+        </events>
+    </PickupSpawner>
+
+    <PickupSpawner pickup=crazyhealthpickup position="<?lua print((cC[1]+615) .. ',' .. cC[2] .. ',' .. (cC[3]-615)) ?>" triggerDistance="15" maxSpawnedItems="1">
+        <events>
+            <visibility>
+                <EventListener event="readyAfterWave2" />
+            </visibility>
+            <activity>
+                <EventListener event="readyAfterWave2" />
+            </activity>
+        </events>
+    </PickupSpawner>
+
+    <PickupSpawner pickup=hugespeedpickup position="<?lua print((cC[1]+585) .. ',' .. cC[2] .. ',' .. (cC[3]-615)) ?>" triggerDistance="15" maxSpawnedItems="1" >
+        <events>
+            <visibility>
+                <EventListener event="readyAfterWave2" />
+            </visibility>
+            <activity>
+                <EventListener event="readyAfterWave2" />
+            </activity>
+        </events>
+    </PickupSpawner>
+
+    <!-- Allies -->
+    <?lua
+    for i = 1, allies, 1
+    do
+    x = rAllies[1] + math.cos(2*math.pi/allies*(i+1))*100
+    y = rAllies[2] + math.sin(2*math.pi/allies*(i+1))*100
+    ?>
+    <SpaceShip visible=false active=false name="allies<?lua print(k)?>" radarname="Ally" position="<?lua print(y)?>,<?lua print(math.pow(-1,i)*100) ?>,<?lua print(x)?>" lookat="0,0,0" team=0>
+        <templates>
+            <Template link="spaceshipassff" />
+        </templates>
+        <events>
+            <visibility>
+                <EventListener event="dockedA" />
+            </visibility>
+            <activity>
+                <EventListener event="dockedA" />
+            </activity>
+        </events>
+        <attached>
+            <DistanceTriggerBeacon name="NPC" />
+        </attached>
+        <controller>
+            <!-- also see allyControllerDispatcher -->
+            <AIController name="allyController" accuracy=100 team=0 active=false />
+        </controller>
+    </SpaceShip>
+    <?lua end ?>
+
+    <!-- Enemies. Outer loop defines waves, inner loop defines enemies in every wave. -->
+    <?lua
+    enemies = enemiesInit
+    for k = 1, waves, 1
+    do
+    ?>
+    <?lua
+    for i = 1, enemies, 1
+    do
+    x = math.cos(math.pi/(2*enemies - 2)*(i+k))*1500
+    y = math.sin(math.pi/(2*enemies - 2)*(i+k))*1500
+    ?>
+    <SpaceShip visible=false active=false name="attackers<?lua print(k)?>" radarname="Attacker" position="<?lua print(y)?>,<?lua print(math.pow(-1,i)*250) ?>,<?lua print(x)?>" lookat="0,0,0" team=1>
+        <templates>
+            <Template link="spaceshippirate" />
+        </templates>
+        <events>
+            <visibility>
+                <EventListener event="wave<?lua print(k)?>" />
+            </visibility>
+            <activity>
+                <EventListener event="wave<?lua print(k)?>" />
+            </activity>
+        </events>
+        <attached>
+            <DistanceTriggerBeacon name="NPC" />
+        </attached>
+        <controller>
+            <WaypointPatrolController name="attackController" accuracy=100 alertnessradius=100 team=1 active=false>
+                <waypoints>
+                    <Attacher target="transporter" deletewithparent=false />
+                </waypoints>
+                <events>
+                    <activity>
+                        <EventListener event="wave<?lua print(k)?>" />
+                    </activity>
+                </events>
+            </WaypointPatrolController>
+        </controller>
+    </SpaceShip>
+    <?lua end ?>
+    <?lua
+    enemies = enemies + enemiesIncrease
+    end ?>
+
+    <!-- Transporter, starting Point is near A, end Point near B, the circle parameters for the waypoints are: Center = (0, -887, 0), r = 2613 -->
+    <SpaceShip position="<?lua printC(cA) ?>" lookat="<?lua printC(cB) ?>" team=0 name="transporter" radarname="Shuttle" >
+        <templates>
+            <Template link="spaceshipShuttle" />
+        </templates>
+        <attached>
+            <DistanceTriggerBeacon name="NPC" />
+            <DistanceTriggerBeacon name="transporter" />
+            <DistanceTrigger active=false name="reachedShuttle" position="0,0,0" distance=400 target="SpaceShip" beaconMode="exclude" targetname="NPC" stayactive=true initialhealth=1000 maxhealth=1000>
+                <events>
+                    <activity>
+                        <EventListener event="readyAfterWave2" />
+                    </activity>
+                </events>
+            </DistanceTrigger>
+        </attached>
+        <controller>
+            <WaypointController accuracy=10 team=0>
+                <waypoints>
+                    <!-- A to B -->
+                    <?lua
+                    max = 5
+                    for i = 1, max, 1
+                    do
+                    x = math.cos(math.pi*(i+1)/8)*5000
+                    y = -math.sin(math.pi*(i+1)/8)*700-3000
+                    ?>
+                    <Billboard position="<?lua print(y) ?>,0,<?lua print(x) ?>" amplitude=1 material="Flares/lensflare" colour="1,1,0.05"/>
+                    <?lua end ?>
+
+                    <!-- Return Point -->
+                    <Billboard position="<?lua printC(cB) ?>" amplitude=1 material="Flares/lensflare" colour="1,1,0.05"/>
+
+                    <!-- B to A -->
+                    <?lua
+                    max = 5
+                    for i = 1, max, 1
+                    do
+                    x = math.cos(math.pi*(max+2-i)/8)*5000
+                    y = -math.sin(math.pi*(max+2-i)/8)*700-3000
+                    ?>
+                    <Billboard position="<?lua print(y) ?>,0,<?lua print(x) ?>" amplitude=1 material="Flares/lensflare" colour="1,1,0.05"/>
+                    <?lua end ?>
+
+                    <!-- Start Point -->
+                    <Billboard position="<?lua printC(cA) ?>" amplitude=1 material="Flares/lensflare" colour="1,1,0.05"/>
+                </waypoints>
+            </WaypointController>
+        </controller>
+    </SpaceShip>
+
+    </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/shuttleRetaliation.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/shuttleRetaliation.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/shuttleRetaliation.oxw	(revision 11817)
@@ -0,0 +1,1182 @@
+<LevelInfo
+    name = "Retaliation"
+    description = "This attack cannot be met with no consequences! Commander, we order you to get back to sector 5C and erradicate the alien menace at once!"
+    tags = "mission"
+    screenshot = "retailiation.png"
+/>
+
+<?lua
+    include("stats.oxo")
+    include("HUDTemplates3.oxo")
+    include("HUDTemplatesFPS.oxo")
+    include("templates/lodInformation.oxt")
+
+    include("templates/spaceshipAssff.oxt")
+    include("templates/spaceshipPirate.oxt")
+    include("templates/spaceshipEscort.oxt")
+    include("templates/spaceshipShuttle.oxt")
+    include("templates/FPS.oxt")
+    include("templates/pickupRepresentationTemplates.oxt")
+?>
+
+<Level gametype = "Mission">
+    <templates>
+        <Template link="lodtemplate_default" />
+    </templates>
+
+    <?lua include("includes/notifications.oxi") ?>
+
+    <NotificationQueueCEGUI
+        name="narrative"
+        targets="simpleNotification"
+        size=3
+        displayTime=3.9
+        position="0.15, 0, 0.1, 0"
+        fontSize="15"
+        fontColor="0.3, 1, 0.2, 0.8"
+        alignment="HorzCentred"
+        displaySize="0.7, 0, 0, 0"
+    />
+
+    <!-- GLOBAL LUA VARIABLES -->
+    <?lua
+
+        enemies = 2
+        allies = 2
+
+        radSector = 12000
+
+        --[[ Coordinates in (y,z,x). NOTE: Indexing starts at 1 in lua! Don´t forget to adapt the for loops, too! ]]--
+        cCenter = {0, 0, 0}
+        cSpawn = {1500, -2000, 900}
+        cSector = {-15000, -5500, -9000}
+        cSectorEntry = {-4710, -5500, -2826}
+        cPathToEntry = {{0, -2000, 0}}
+        cBeacon = {-6500, -5500, -4400}
+         cAllyWait = cBeacon
+
+        cAlly = cSpawn
+        cEnemy = {-9600, -5500, -6000}
+
+        rSection= {0, -200, 0}
+        rWingman1 = {0, -100, 100}
+        rWingman2 = {0, -100, -100}
+
+        cPlanet1 = {20000, 0, 29000}
+        cPlanet2 = {-22000, 0, -29000}
+
+        cEnemyBasePlanet = {-20000, -8000, -10000}
+
+        cField1 = {-5000, -4000, -3000}
+        cField2 = {4000, 2000, 4500}
+
+
+        --[[ Function to print Coordinates. Quotes not included! ]]--
+        function printC(coord)
+          print(coord[1] .. [[,]] .. coord[2] .. [[,]] .. coord[3])
+        end
+
+        --[[ Function to add Coordinates.]]--
+        function addC(coord1, coord2)
+            return {coord1[1]+coord2[1], coord1[2]+coord2[2], coord1[3]+coord2[3]}
+        end
+    ?>
+
+    <Scene
+        ambientlight = "0.8, 0.8, 0.8"
+        skybox = "Orxonox/skyBoxMoreNebula"
+        hasPhysics = true
+    >
+
+    <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" />
+
+    <Light type=directional position="<?lua printC(cSpawn) ?>" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <!--SPAWNING-->
+
+    <Template name=commander>
+        <SpaceShip
+            template            = "spaceshipassff"
+            team                = "0"
+            health              = "800"
+            initialhealth       = "800"
+            maxhealth           = "1500"
+            shieldhealth        = "80"
+            initialshieldhealth = "80"
+            maxshieldhealth     = "120"
+            shieldabsorption    = "0.8"
+            reloadrate          = "1"
+            reloadwaittime      = "1"
+            name                = "commander"
+            radarname           = "Commander"
+            >
+            <attached>
+                <DistanceTriggerBeacon name="Commander" />
+            </attached>
+        </SpaceShip>
+    </Template>
+
+    <Template name=ally>
+        <SpaceShip
+            template            = "spaceshipassff"
+            team                = "0"
+            radarname           = "Ally"
+            lookat              = "<?lua printC(cPathToEntry[1]) ?>"
+        >
+            <attached>
+                <DistanceTriggerBeacon name="Ally" />
+            </attached>
+        </SpaceShip>
+    </Template>
+
+    <Template name=enemy>
+        <SpaceShip
+            template            = "spaceshippirate"
+            team                = "1"
+            radarname           = "Invader"
+            lookat              = "<?lua printC(cBeacon) ?>"
+            active              = false
+            visible             = false
+        >
+            <attached>
+                <DistanceTriggerBeacon name="Enemy" />
+            </attached>
+        </SpaceShip>
+    </Template>
+
+    <TeamSpawnPoint active=false name="playerSpawn" team=0 position="<?lua printC(cSpawn) ?>" lookat="<?lua printC(cPathToEntry[1]) ?>" spawnclass=SpaceShip pawndesign=commander>
+        <events>
+            <activity>
+                <EventTrigger invert=true>
+                  <events>
+                    <trigger>
+                      <EventListener event="reachedSector" />
+                    </trigger>
+                  </events>
+                </EventTrigger>
+            </activity>
+        </events>
+    </TeamSpawnPoint>
+
+    <TeamSpawnPoint active=false name="altSpawn" team=0 position="<?lua printC(cBeacon) ?>" lookat="<?lua printC(cSector) ?>" spawnclass=SpaceShip pawndesign=commander>
+        <events>
+            <activity>
+                <EventListener event="reachedSector" />
+            </activity>
+        </events>
+    </TeamSpawnPoint>
+
+    <!--QUEST DEFINITIONS-->
+
+    <GlobalQuest id="quest1">
+        <QuestDescription title="Enter Sector 5C" description="It is time to retaliate against the aggressors. Get back to Sector 5C to kill every last one of them! We have you covered with <?lua print(allies) ?> of our finest Divisions. They will guide, help and protect you if necessary." failMessage="" completeMessage="" />
+        <hints>
+            <QuestHint id="quest1hint1">
+                <QuestDescription title="Markings" description="We have marked the bounds of Sector 5C in red lights, you can follow the green trail to get there." />
+            </QuestHint>
+        </hints>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest2">
+        <QuestDescription title="Find them" description="It seems they have hidden themselves, that is, their whole civilization, in fear of retaliation. Our scientists presume some cloaking technology to be in use. Look out for a way to make the aggressors visible!" failMessage="" completeMessage="" />
+        <hints>
+            <QuestHint id="quest2hint1">
+                <QuestDescription title="The detector beacon" description="Our scientists claim cloaking is generally toggled by a visible Switch called a detector beacon. Try to find a bright light in your Area and approach it!" />
+            </QuestHint>
+        </hints>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest3">
+        <QuestDescription title="Fight their army" description="You have successfully uncovered their civilization and home planet, and it is much worse than we thought... they came prepared! You have to fight their army to fulfill your mission." failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <complete-effects>
+            <AddQuest questId="quest4" />
+            <AddQuest questId="quest4.1" />
+            <AddQuest questId="quest4.2" />
+            <AddQuestHint hintId="quest4.1hint1" />
+            <AddQuestHint hintId="quest4.2hint1" />
+        </complete-effects>
+    </GlobalQuest>
+
+    <GlobalQuest id="quest4">
+        <QuestDescription title="Do the right thing" description="The aggressors have surrendered and seem to have had good reasons for their actions. Yet they did not talk to us beforehand and tried to kill us. What will you do?" failMessage="" completeMessage="" />
+        <hints>
+        </hints>
+        <subquests>
+            <GlobalQuest id="quest4.1">
+                <QuestDescription title="> Destroy their civilisation" description="Even if they had reasons, they are still murderers and can not be trusted anymore. This whole thing might even be a setup... We need to kill them and destroy their planet!" failMessage="" completeMessage="" />
+                <hints>
+                    <QuestHint id="quest4.1hint1">
+                        <QuestDescription title="Choosing" description="To make this choice, kill the remaining enemy ships. The divisions will follow your decision." />
+                    </QuestHint>
+                </hints>
+            </GlobalQuest>
+            <GlobalQuest id="quest4.2">
+                <QuestDescription title="> Spare them and leave" description="Military tension arising from a missunderstanding is no valid reasoning for a genocide. Nothing is. We should leave and talk this out later." failMessage="" completeMessage="" />
+                <hints>
+                    <QuestHint id="quest4.2hint1">
+                        <QuestDescription title="Choosing" description="To make this choice, fly out of the sector. The divisions will follow your decision." />
+                    </QuestHint>
+                </hints>
+            </GlobalQuest>
+        </subquests>
+    </GlobalQuest>
+
+    <!--EVENTS AND TRIGGERS
+        Usable events and triggers:
+        spawntrigger
+    -->
+
+    <EventMultiTrigger name="spawntrigger" activations=1>
+        <events>
+            <trigger>
+                <EventListener event="playerSpawn" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventMultiTrigger name="spawned" stayactive=true activations=1>
+        <events>
+            <trigger>
+                <EventListener event="spawntrigger" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger name="reachedSector" position="<?lua printC(cSector) ?>" distance="<?lua print(radSector) ?>" target="SpaceShip" beaconMode="identify" targetname="Commander" stayactive=true />
+
+    <EventMultiTrigger name="addQuest2">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=10 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedSector" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger name="alliesReachedWait" position="<?lua printC(cAllyWait) ?>" distance="1000" target="SpaceShip" beaconMode="identify" targetname="Ally" stayactive=true />
+
+    <!-- So the allies stall when they reached their position for negociation and don´t fire away... -->
+
+    <EventDispatcher name="allyControllerDispatcher">
+      <targets>
+        <EventTarget target="allyController" />
+      </targets>
+      <events>
+          <activity>
+                <Trigger mode=or>
+                    <EventTrigger invert=true>
+                        <events>
+                            <trigger>
+                                <EventListener event="alliesReachedWait" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                    <EventTrigger>
+                        <events>
+                            <trigger>
+                                <EventListener event="noMercy" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                    <Trigger mode=and>
+                        <EventTrigger>
+                            <events>
+                                <trigger>
+                                    <EventListener event="fightBegun" />
+                                </trigger>
+                            </events>
+                        </EventTrigger>
+                        <EventTrigger invert=true>
+                            <events>
+                                <trigger>
+                                    <EventListener event="oneUnitLeft" />
+                                </trigger>
+                            </events>
+                        </EventTrigger>
+                    </Trigger>
+                </Trigger>
+          </activity>
+      </events>
+    </EventDispatcher>
+
+    <EventMultiTrigger name="hintBeacon">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=70 >
+                   <events>
+                      <trigger>
+                         <EventListener event="reachedSector" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <DistanceTrigger name="cloakBeacon" position="<?lua printC(cBeacon) ?>" distance=100 target="SpaceShip" beaconMode="identify" targetname="Commander" stayactive=true />
+
+    <EventMultiTrigger name="fightBegun" stayactive=true>
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=12>
+                   <events>
+                      <trigger>
+                         <EventListener event="cloakBeacon" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventDispatcher name="enemyControllerDispatcher">
+      <targets>
+        <EventTarget target="enemyController" />
+      </targets>
+      <events>
+          <activity>
+              <Trigger mode=and>
+                  <EventTrigger>
+                      <events>
+                          <trigger>
+                              <EventListener event="fightBegun" />
+                          </trigger>
+                      </events>
+                  </EventTrigger>
+                  <EventTrigger invert=true>
+                      <events>
+                          <trigger>
+                              <EventListener event="oneUnitLeft" />
+                          </trigger>
+                      </events>
+                  </EventTrigger>
+              </Trigger>
+          </activity>
+      </events>
+    </EventDispatcher>
+
+    <EventMultiTrigger name="noMercy" stayactive=true>
+        <events>
+            <trigger>
+                <EventListener event="allUnitsDown" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventMultiTrigger name="enemyPlanetMulti">
+     <events>
+         <trigger>
+             <EventListener event="enemyPlanet" />
+         </trigger>
+     </events>
+    </EventMultiTrigger>
+
+    <!-- Recursive helper function for the event at the "end" of a Unit.-->
+    <?lua
+    function enemyTriggerRecursor(i, k)
+    if i > 0 then
+    return [[
+    <EventTrigger name=killedEnemy]] .. ((k-1)*4+i) .. [[ activations=1 stayactive=true delay=0.1>
+        <events>
+            <trigger>
+                <EventListener event=enemy]] .. k .. [[ />
+            </trigger>
+        </events>
+        ]] .. enemyTriggerRecursor(i-1, k) .. [[
+    </EventTrigger>
+    ]]
+    else return ""
+    end
+    end
+    ?>
+    <!-- Actual recursive Event(s) for the respective Units. (packs of 4 Enemies that is!) -->
+    <?lua
+    for k = 1, enemies, 1
+    do
+    print(enemyTriggerRecursor(4,k))
+    ?>
+    <EventMultiTrigger name="unit<?lua print(k) ?>Down" delay=0.1 stayactive=true>
+        <events>
+            <trigger>
+                <EventListener event="killedEnemy<?lua print(k*4) ?>" />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+    <?lua end ?>
+
+    <EventMultiTrigger name="oneUnitLeft" stayactive=true>
+        <events>
+            <trigger>
+                <Trigger mode=or>
+                    <?lua
+                    for k = 1, enemies, 1
+                    do
+                    ?>
+                        <Trigger mode=and>
+                            <EventTrigger invert=true>
+                                <events>
+                                    <trigger>
+                                        <EventListener event="unit<?lua print(k) ?>Down" />
+                                    </trigger>
+                                </events>
+                            </EventTrigger>
+                            <?lua
+                            for i = 1, enemies, 1
+                            do
+                            if not (i == k) then
+                            ?>
+                            <EventTrigger>
+                                <events>
+                                    <trigger>
+                                        <EventListener event="unit<?lua print(i) ?>Down" />
+                                    </trigger>
+                                </events>
+                            </EventTrigger>
+                            <?lua end end ?>
+                        </Trigger>
+                    <?lua end ?>
+                </Trigger>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <EventMultiTrigger name="allUnitsDown" stayactive=true>
+        <events>
+            <trigger>
+                <Trigger mode=and>
+                    <?lua
+                    for k = 1, enemies, 1
+                    do
+                    ?>
+                    <EventTrigger>
+                        <events>
+                            <trigger>
+                                <EventListener event="unit<?lua print(k) ?>Down" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                    <?lua end ?>
+                </Trigger>
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+
+    <!--TODO: Complete the DistanceTriggers for completing/succeeding correctly! -->
+
+    <DistanceTrigger active=false invert=true name="almostLeft" position="<?lua printC(cSector) ?>" distance="<?lua print(radSector-200) ?>" target="SpaceShip" beaconMode="identify" targetname="Commander" stayactive=true>
+        <events>
+            <activity>
+                <Trigger mode=and>
+                    <EventTrigger>
+                        <events>
+                            <trigger>
+                                <EventListener event="oneUnitLeft" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                    <EventTrigger invert=true>
+                        <events>
+                            <trigger>
+                                <EventListener event="enemyPlanetMulti" />
+                            </trigger>
+                        </events>
+                    </EventTrigger>
+                </Trigger>
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <DistanceTrigger active=false invert=true name="leftSector" position="<?lua printC(cSector) ?>" distance="<?lua print(radSector) ?>" target="SpaceShip" beaconMode="identify" targetname="Commander" stayactive=true>
+        <events>
+            <activity>
+                <EventListener event="oneUnitLeft" />
+            </activity>
+        </events>
+    </DistanceTrigger>
+
+    <Script code="Mission endMission true" onLoad="false">
+        <events>
+            <trigger>
+                <EventListener event="leftSector" />
+            </trigger>
+        </events>
+    </Script>
+
+    <!--QUEST EFFECT BEACONS -->
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuest questId="quest1" />
+            <AddQuestHint HintId="quest1hint1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="spawntrigger" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest1" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="reachedSector" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuest questId="quest2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="addQuest2" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuestHint hintId="quest2hint1
+                " />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="hintBeacon" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest2" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="cloakBeacon" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <AddQuest questId="quest3" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="fightBegun" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest3" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="oneUnitLeft" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+    <!--TODO: Include planet destruction and quitting -->
+
+    <QuestEffectBeacon times=1>
+        <effects>
+            <CompleteQuest questId="quest4" />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event="enemyAllGone" />
+            </execute>
+        </events>
+    </QuestEffectBeacon>
+
+
+    <!--NOTIFICATIONS -->
+
+    <SimpleNotification broadcast="true" message="Welcome, Commander. It is time to retaliate!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=4 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Get to section 5C and erradicate the aggressors!">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=8 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="That seems extreme. Is there no way around it?">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=12 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Stick to your objective, Commander. This is war.">
+        <events>
+            <trigger>
+                <EventTrigger stayactive="true" delay=16 >
+                   <events>
+                      <trigger>
+                         <EventListener event="spawntrigger" />
+                      </trigger>
+                   </events>
+                </EventTrigger>
+            </trigger>
+        </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Huh?! The sector is empty! where are they hiding?">
+       <events>
+           <trigger>
+               <EventTrigger stayactive="true" delay=2 >
+                  <events>
+                     <trigger>
+                        <EventListener event="reachedSector" />
+                     </trigger>
+                  </events>
+               </EventTrigger>
+           </trigger>
+       </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="They must be cloaking themselves! But we'll figure it out...">
+      <events>
+          <trigger>
+              <EventTrigger stayactive="true" delay=6 >
+                 <events>
+                    <trigger>
+                       <EventListener event="reachedSector" />
+                    </trigger>
+                 </events>
+              </EventTrigger>
+          </trigger>
+      </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Got it! Look out for a bright light and touch it!">
+     <events>
+         <trigger>
+             <EventListener event="addQuest2" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Divisions are standing by, Sir.">
+     <events>
+         <trigger>
+             <EventListener event="alliesReachedWait" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Woah! what the hell! they boobytrapped us!">
+     <events>
+         <trigger>
+             <EventListener event="cloakBeacon" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Greetings, Humans. Are you here to resign to your menace and make amends?">
+     <events>
+         <trigger>
+             <EventTrigger stayactive="true" delay=4 >
+                <events>
+                   <trigger>
+                      <EventListener event="cloakBeacon" />
+                   </trigger>
+                </events>
+             </EventTrigger>
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Menace? What is he on about, General?">
+     <events>
+         <trigger>
+             <EventTrigger stayactive="true" delay=8 >
+                <events>
+                   <trigger>
+                      <EventListener event="cloakBeacon" />
+                   </trigger>
+                </events>
+             </EventTrigger>
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="None of your concern, Commander. Launch the attack!">
+     <events>
+         <trigger>
+             <EventTrigger stayactive="true" delay=12 >
+                <events>
+                   <trigger>
+                      <EventListener event="cloakBeacon" />
+                   </trigger>
+                </events>
+             </EventTrigger>
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Unit 1 down!">
+     <events>
+         <trigger>
+             <EventListener event="unit1Down" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Unit 2 down!">
+     <events>
+         <trigger>
+             <EventListener event="unit2Down" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Unit 3 down!">
+     <events>
+         <trigger>
+             <EventListener event="unit3Down" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Unit 4 down!">
+     <events>
+         <trigger>
+             <EventListener event="unit4Down" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Please! No More! We surrender!">
+     <events>
+         <trigger>
+             <EventListener event="oneUnitLeft" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Roger that, Commander. We destroy their planet.">
+     <events>
+         <trigger>
+             <EventListener event="allUnitsDown" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="Well done, Commander! Now exfiltrate the sector!">
+     <events>
+         <trigger>
+             <EventListener event="enemyPlanetMulti" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <SimpleNotification broadcast="true" message="This will have dire consequences, Commander!">
+     <events>
+         <trigger>
+             <EventListener event="almostLeft" />
+         </trigger>
+     </events>
+    </SimpleNotification>
+
+    <!--ELEMENTS -->
+
+    <!-- Billboard Path to Sector 5C. Height changes in an atan shape -->
+
+    <?lua
+    for i = 1, 11, 1
+    do
+    heightNow = cPathToEntry[1][2] - (cPathToEntry[1][2]-cSectorEntry[2])*(math.atan(-1.6+0.3*i) + 1)/2
+    cBillNow = {(cSectorEntry[1]-cPathToEntry[1][1])*i/12, heightNow, (cSectorEntry[3]-cPathToEntry[1][3])*i/12}
+    cPathToEntry[i+1] = cBillNow
+    ?>
+    <Billboard position="<?lua printC(cBillNow) ?>"  scale=2 material="Flares/ringflare" colour="0.2,0.9,0.2"/>
+    <?lua
+    end
+    cPathToEntry[13] = cSectorEntry
+    ?>
+
+    <Billboard position="<?lua printC(cSectorEntry) ?>"  scale=5 material="Flares/ringflare" colour="0.2,0.9,0.2"/>
+
+    <!-- Circular Billboard Ring around Sector 5C -->
+
+    <?lua
+    for i = 1, 64, 1
+    do
+    rBillboard = {math.sin(i*math.pi/32)*radSector, 0, math.cos(i*math.pi/32)*radSector}
+    cBillNow = addC(cSector,rBillboard)
+    ?>
+    <Billboard position="<?lua printC(cBillNow) ?>"  scale=10 material="Flares/lensflare" colour="1,0.2,0.2"/>
+    <?lua end ?>
+
+    <!-- Cloaking Beacon -->
+
+    <BlinkingBillboard visible=false active=false scale=2 position="<?lua printC(cBeacon) ?>" material="Flares/lensflare" frequency=1 amplitude=3 colour="0.4,0.4,1">
+        <events>
+            <activity>
+                <EventListener event="addQuest2" />
+            </activity>
+            <visibility>
+                <EventListener event="addQuest2" />
+            </visibility>
+        </events>
+    </BlinkingBillboard>
+
+    <!-- Asteroids you have to fly through to get to the EnemyBase -->
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+       asteroidField(cField1[1], cField1[2], cField1[3], 20, 30, 4500, 500, 0)
+    ?>
+
+    <!-- Other Asteroid-Fields -->
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+       asteroidField(cField2[1], cField2[2], cField2[3], 20, 30, 4500, 500, 0)
+    ?>
+
+    <!-- Planets -->
+
+   <Planet
+        position="<?lua printC(cPlanet1) ?>"
+        scale="3000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/muunilinst.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage = 2
+        enablecollisiondamage = true
+    visible=true
+    active=true
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="6000" velocity="-500" />
+        </attached>
+        <collisionShapes>
+            <SphereCollisionShape radius="3000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(cPlanet1[1], cPlanet1[2], cPlanet1[3], 30, 20, 100, 20, 40, 3400, 3700, 400, 1)
+    ?>
+
+    <Planet
+        position="<?lua printC(cPlanet2) ?>"
+        scale="2000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/ganymede.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage = 2
+        enablecollisiondamage = true
+        visible=true
+        active=true
+      >
+      <attached>
+        <ForceField position="0,0,0" mode="sphere" diameter="4000" velocity="-500" />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="2000" position="0,0,0" />
+      </collisionShapes>
+    </Planet>
+
+    <?lua
+        dofile("includes/asteroidField.lua")
+        asteroidBelt(cPlanet2[1], cPlanet2[2], cPlanet2[3], 30, 20, 100, 20, 40, 3400, 3700, 400, 1)
+    ?>
+
+    <!-- EnemyPlanet -->
+
+    <Planet
+        position="<?lua printC(cEnemyBasePlanet) ?>"
+        scale="5000"
+        collisionType="dynamic"
+        linearDamping="0.8"
+        angularDamping="0"
+        mass="5000000"
+        pitch="0"
+        mesh="planets/jupiter.mesh"
+        atmosphere="atmosphere1"
+        rotationaxis="1,0,0"
+        rotationrate="1.0"
+        atmospheresize="80.0f"
+        imagesize="1024.0f"
+        collisiondamage = 2
+        enablecollisiondamage = true
+        visible=false
+        active=false
+    >
+        <attached>
+           <ForceField position="0,0,0" rotationaxis="0.1,1,0.1"mode="sphere" diameter="10000" velocity="-500" />
+        </attached>
+        <events>
+            <activity>
+                <Trigger  name="enemyPlanetVisible" mode=and>
+                   <EventTrigger>
+                         <events>
+                             <trigger>
+                                 <EventListener event="cloakBeacon" />
+                             </trigger>
+                         </events>
+                     </EventTrigger>
+                     <EventTrigger invert=true>
+                         <events>
+                             <trigger>
+                                 <EventListener event="enemyPlanetMulti" />
+                             </trigger>
+                         </events>
+                     </EventTrigger>
+                 </Trigger>
+            </activity>
+            <visibility>
+                <Trigger  name="enemyPlanetVisible" mode=and>
+                   <EventTrigger>
+                         <events>
+                             <trigger>
+                                 <EventListener event="cloakBeacon" />
+                             </trigger>
+                         </events>
+                     </EventTrigger>
+                     <EventTrigger invert=true>
+                         <events>
+                             <trigger>
+                                 <EventListener event="enemyPlanetMulti" />
+                             </trigger>
+                         </events>
+                     </EventTrigger>
+                 </Trigger>
+            </visibility>
+        </events>
+        <collisionShapes>
+          <SphereCollisionShape position="0,0,0" radius=5000/>
+        </collisionShapes>
+    </Planet>
+
+    <!-- Pawn that represents the planet during destruction -->
+
+    <Pawn team=1 visible=false active=false scale=5000 health=500 name="enemyPlanet" position="<?lua printC(cEnemyBasePlanet) ?>" collisionType=dynamic mass=5000000 radarname="Enemy home planet">
+        <events>
+            <activity>
+                <EventListener event="allUnitsDown" />
+            </activity>
+            <visibility>
+                <EventListener event="allUnitsDown" />
+            </visibility>
+        </events>
+        <collisionShapes>
+          <SphereCollisionShape position="0,0,0" radius=5005/>
+        </collisionShapes>
+    </Pawn>
+    <!--SHIPS -->
+    <!-- one Controller to rule them all -->
+    <Pawn position = "100000, 100000, 100000">
+      <controller>
+        <MasterController>
+        </MasterController>
+      </controller>
+    </Pawn>
+    <!--Allied units-->
+
+    <?lua
+    for i = 1, allies, 1
+    do
+    rUnit = {-math.sin(math.pi*((i-1/2)/allies))*125, math.pow(-1,i)*80, math.cos(math.pi*((i-1/2)/allies))*800}
+    cAllyNow = addC(cAlly,rUnit)
+    ?>
+
+    <SpaceShip health=600 initialhealth=600 maxhealth=600 position="<?lua printC(cAllyNow) ?>" name="ally<?lua print(i) ?>.D">
+      <templates>
+        <Template link=ally />
+      </templates>
+      <controller>
+        <DivisionController name="allyController" team=0 formationMode="diamond" spread=100>
+          <actionpoints>
+              <?lua
+              for i = 1, 13, 1
+              do
+              ?>
+              <Actionpoint position="<?lua printC(addC(cPathToEntry[i], rUnit)) ?>" action="fly"/>
+              <?lua end ?>
+           </actionpoints>
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip health=600 initialhealth=600 maxhealth=600 position="<?lua printC(addC(cAllyNow,rSection)) ?>" lookat="0,0,0" name="ally<?lua print(i) ?>.S">
+      <templates>
+        <Template link=ally />
+      </templates>
+      <controller>
+        <SectionController name="allyController" team=0>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip health=600 initialhealth=600 maxhealth=600 position="<?lua printC(addC(cAllyNow,rWingman1)) ?>" lookat="0,0,0" name="ally<?lua print(i) ?>.W1">
+      <templates>
+        <Template link=ally />
+      </templates>
+      <controller>
+        <WingmanController name="allyController" team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip health=600 initialhealth=600 maxhealth=600 position="<?lua printC(addC(cAllyNow,rWingman2)) ?>" lookat="0,0,0" name="ally<?lua print(i) ?>.W2">
+      <templates>
+        <Template link=ally />
+      </templates>
+      <controller>
+        <WingmanController name="allyController" team=0>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+
+    <?lua end ?>
+
+    <!-- Enemy Units -->
+
+    <?lua
+    for k = 1, enemies, 1
+    do
+    rUnit = {125 -math.sin(math.pi*((k-1/2)/enemies))*200, math.pow(-1,k)*300, math.cos(math.pi*((k-1/2)/enemies))*1000}
+    cEnemyNow = addC(cEnemy,rUnit)
+    ?>
+
+    <SpaceShip health=400 initialhealth=400 maxhealth=400 position="<?lua printC(cEnemyNow) ?>" name="enemy<?lua print(k) ?>">
+      <templates>
+        <Template link=enemy />
+      </templates>
+      <events>
+          <activity>
+              <EventListener event="cloakBeacon" />
+          </activity>
+          <visibility>
+              <EventListener event="cloakBeacon" />
+          </visibility>
+      </events>
+      <controller>
+        <DivisionController name="enemyController" active=false team=1 formationMode="diamond" spread=100>
+          <actionpoints>
+              <Actionpoint position="<?lua printC(cEnemyNow) ?>" action="fightall" />
+          </actionpoints>
+        </DivisionController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip health=400 initialhealth=400 maxhealth=400 position="<?lua printC(addC(cEnemyNow,rSection)) ?>" name="enemy<?lua print(k) ?>">
+      <templates>
+        <Template link=enemy />
+      </templates>
+      <events>
+          <activity>
+              <EventListener event="cloakBeacon" />
+          </activity>
+          <visibility>
+              <EventListener event="cloakBeacon" />
+          </visibility>
+      </events>
+      <controller>
+        <SectionController name="enemyController" active=false team=1>
+        </SectionController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip health=400 initialhealth=400 maxhealth=400 position="<?lua printC(addC(cEnemyNow,rWingman1)) ?>" lookat="0,0,0" name="enemy<?lua print(k) ?>">
+      <templates>
+        <Template link=enemy />
+      </templates>
+      <events>
+          <activity>
+              <EventListener event="cloakBeacon" />
+          </activity>
+          <visibility>
+              <EventListener event="cloakBeacon" />
+          </visibility>
+      </events>
+      <controller>
+        <WingmanController name="enemyController" active=false team=1>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip health=400 initialhealth=400 maxhealth=400 position="<?lua printC(addC(cEnemyNow,rWingman2)) ?>" name="enemy<?lua print(k) ?>">
+      <templates>
+        <Template link=enemy />
+      </templates>
+      <events>
+          <activity>
+              <EventListener event="cloakBeacon" />
+          </activity>
+          <visibility>
+              <EventListener event="cloakBeacon" />
+          </visibility>
+      </events>
+      <controller>
+        <WingmanController name="enemyController" active=false team=1>
+        </WingmanController>
+      </controller>
+    </SpaceShip>
+
+    <?lua end ?>
+
+    </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/simone.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/simone.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/simone.oxw	(revision 11817)
@@ -0,0 +1,37 @@
+<LevelInfo
+ name = "Simone"
+ description = "A level with absolutely nothing in it."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipRing.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipring />
+    <Model position="0,0,0" mesh="ship.mesh" scale="3"/>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/sound.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/sound.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/sound.oxw	(revision 11817)
@@ -0,0 +1,59 @@
+<LevelInfo
+ name = "Sound showcase"
+ description = "Level to test and showcase sound."
+ tags = "test, showcase"
+ screenshot = "soundshowcase.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+  <WorldAmbientSound source="Earth.ogg" looping="true" playOnLoad="true" />
+  <WorldAmbientSound source="Mars.ogg" looping="true">
+    <events>
+      <activity>
+        <DistanceTrigger position="400,0,0" distance=200 target="Camera">
+          <attached>
+            <ParticleSpawner position="0,0,0" source="Orxonox/fire3" lifetime=0 loop=0 autostart=1 />
+          </attached>
+        </DistanceTrigger>
+      </activity>
+    </events>
+  </WorldAmbientSound>
+  <WorldAmbientSound source="Jupiter.ogg" looping="true">
+    <events>
+      <activity>
+        <DistanceTrigger position="400,150,0" distance=200 target="Camera">
+          <attached>
+            <ParticleSpawner position="0,0,0" source="Orxonox/fire3" lifetime=0 loop=0 autostart=1 />
+          </attached>
+        </DistanceTrigger>
+      </activity>
+    </events>
+  </WorldAmbientSound>
+
+
+  <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+  <SpawnPoint position="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+  
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/teamBaseMatch.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/teamBaseMatch.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/teamBaseMatch.oxw	(revision 11817)
@@ -0,0 +1,248 @@
+<LevelInfo
+ name = "Teambase Match"
+ description = "Fight for the bases. Capture bases by shooting at them and defend them against attackers."
+ tags = "gametype"
+ screenshot = "teambasematch.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("teamBaseMatchHUD.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "TeamBaseMatch"
+>
+
+<WorldAmbientSound source="Jupiter.ogg" looping="true" playOnLoad="true" />
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <TeamSpawnPoint team=0 position=" 900,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=1 position="-900,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+
+    <TeamBaseMatchBase
+     name              = "base 1"
+     position          = "1200, 0, 0"
+     pitch = -90
+
+     health            = 1000
+     maxhealth         = 1000
+     initialhealth     = 1000
+
+     collisionType     = "dynamic"
+     mass              = 10000
+     linearDamping     = 0.9
+     angularDamping    = 0.99999
+    >
+      <attached>
+        <Model scale=10 mesh="DuBall1.mesh" position = "-100,0,0"/>
+        <Model scale=10 mesh="DuBall2.mesh" position = "100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "-100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "100,0,0"/>
+
+        <?lua
+          for i = 1, 10, 1 do
+        ?>
+          <ParticleSpawner position="<?lua print(math.random() * 400 - 200) ?>,<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>" startdelay="<?lua print(math.random()) ?>" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+            <events>
+              <spawn>
+                <EventListener event="base 1" />
+              </spawn>
+            </events>
+          </ParticleSpawner>
+        <?lua end ?>
+        
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="80"            position = "-100,0,0" />
+        <SphereCollisionShape radius="120"           position = "100,0,0" />
+        <BoxCollisionShape    halfExtents="90,25,45" position = "-155,0,40" />
+      </collisionShapes>
+    </TeamBaseMatchBase>
+
+
+    <TeamBaseMatchBase
+     name              = "base 2"
+     position          = "-1200, 0, 0"
+     pitch = -90
+
+     health            = 1000
+     maxhealth         = 1000
+     initialhealth     = 1000
+
+     collisionType     = "dynamic"
+     mass              = 10000
+     linearDamping     = 0.9
+     angularDamping    = 0.99999
+    >
+      <attached>
+        <Model scale=10 mesh="DuBall1.mesh" position = "-100,0,0"/>
+        <Model scale=10 mesh="DuBall2.mesh" position = "100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "-100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "100,0,0"/>
+
+        <?lua
+          for i = 1, 10, 1 do
+        ?>
+          <ParticleSpawner position="<?lua print(math.random() * 400 - 200) ?>,<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>" startdelay="<?lua print(math.random()) ?>" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+            <events>
+              <spawn>
+                <EventListener event="base 2" />
+              </spawn>
+            </events>
+          </ParticleSpawner>
+        <?lua end ?>
+        
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="80"            position = "-100,0,0" />
+        <SphereCollisionShape radius="120"           position = "100,0,0" />
+        <BoxCollisionShape    halfExtents="90,25,45" position = "-155,0,40" />
+      </collisionShapes>
+    </TeamBaseMatchBase>
+
+
+    <TeamBaseMatchBase
+     name              = "base 3"
+     position          = "0, 0, 1200"
+     pitch = -90
+
+     health            = 1000
+     maxhealth         = 1000
+     initialhealth     = 1000
+
+     collisionType     = "dynamic"
+     mass              = 10000
+     linearDamping     = 0.9
+     angularDamping    = 0.99999
+    >
+      <attached>
+        <Model scale=10 mesh="DuBall1.mesh" position = "-100,0,0"/>
+        <Model scale=10 mesh="DuBall2.mesh" position = "100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "-100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "100,0,0"/>
+
+        <?lua
+          for i = 1, 10, 1 do
+        ?>
+          <ParticleSpawner position="<?lua print(math.random() * 400 - 200) ?>,<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>" startdelay="<?lua print(math.random()) ?>" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+            <events>
+              <spawn>
+                <EventListener event="base 3" />
+              </spawn>
+            </events>
+          </ParticleSpawner>
+        <?lua end ?>
+
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="80"            position = "-100,0,0" />
+        <SphereCollisionShape radius="120"           position = "100,0,0" />
+        <BoxCollisionShape    halfExtents="90,25,45" position = "-155,0,40" />
+      </collisionShapes>
+    </TeamBaseMatchBase>
+
+    <TeamBaseMatchBase
+     name              = "base 4"
+     position          = "0, 0, -1200"
+
+     health            = 1000
+     maxhealth         = 1000
+     initialhealth     = 1000
+     pitch = -90
+
+     collisionType     = "dynamic"
+     mass              = 10000
+     linearDamping     = 0.9
+     angularDamping    = 0.99999
+    >
+      <attached>
+        <Model scale=10 mesh="DuBall1.mesh" position = "-100,0,0"/>
+        <Model scale=10 mesh="DuBall2.mesh" position = "100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "-100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "100,0,0"/>
+
+        <?lua
+          for i = 1, 10, 1 do
+        ?>
+          <ParticleSpawner position="<?lua print(math.random() * 400 - 200) ?>,<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>" startdelay="<?lua print(math.random()) ?>" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+            <events>
+              <spawn>
+                <EventListener event="base 4" />
+              </spawn>
+            </events>
+          </ParticleSpawner>
+        <?lua end ?>
+
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="80"            position = "-100,0,0" />
+        <SphereCollisionShape radius="120"           position = "100,0,0" />
+        <BoxCollisionShape    halfExtents="90,25,45" position = "-155,0,40" />
+      </collisionShapes>
+    </TeamBaseMatchBase>
+
+
+    <TeamBaseMatchBase
+     name              = "base 5"
+     position          = "0, 0, 0"
+     pitch = -90
+
+     health            = 1000
+     maxhealth         = 1000
+     initialhealth     = 1000
+
+     collisionType     = "dynamic"
+     mass              = 10000
+     linearDamping     = 0.9
+     angularDamping    = 0.99999
+    >
+      <attached>
+        <Model scale=10 mesh="DuBall1.mesh" position = "-100,0,0"/>
+        <Model scale=10 mesh="DuBall2.mesh" position = "100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "-100,0,0"/>
+        <Billboard scale=7 material="Examples/Flare" colour="0.5,0.5,0.5" position = "100,0,0"/>
+
+        <?lua
+          for i = 1, 10, 1 do
+        ?>
+          <ParticleSpawner position="<?lua print(math.random() * 400 - 200) ?>,<?lua print(math.random() * 200 - 100) ?>,<?lua print(math.random() * 200 - 100) ?>" startdelay="<?lua print(math.random()) ?>" source="Orxonox/BigExplosion1part1" lifetime=2.0 loop=0 autostart=0>
+            <events>
+              <spawn>
+                <EventListener event="base 5" />
+              </spawn>
+            </events>
+          </ParticleSpawner>
+        <?lua end ?>
+
+      </attached>
+      <collisionShapes>
+        <SphereCollisionShape radius="80"            position = "-100,0,0" />
+        <SphereCollisionShape radius="120"           position = "100,0,0" />
+        <BoxCollisionShape    halfExtents="90,25,45" position = "-155,0,40" />
+      </collisionShapes>
+    </TeamBaseMatchBase>
+
+    <!--Model position="0,0,0" scale=8 mesh="ast1.mesh" />
+    <StaticEntity position="0,0,0" collisionType=static>
+      <collisionShapes>
+        <SphereCollisionShape radius="20" />
+      </collisionShapes>
+    </StaticEntity-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/teamDeathMatch.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/teamDeathMatch.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/teamDeathMatch.oxw	(revision 11817)
@@ -0,0 +1,87 @@
+<LevelInfo
+ name = "Team Deathmatch"
+ description = "Fight against each other in teams."
+ tags = "gametype"
+ screenshot = "teamdeathmatch.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "TeamDeathmatch"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+  
+  <WorldAmbientSound source="Jupiter.ogg" looping="true" playOnLoad="true" />
+
+  <Scene
+   ambientlight = "0.7, 0.6, 0.6"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <TeamSpawnPoint team=0 position="0,  0,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=0 position="0, 50,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=0 position="0,100,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+    <TeamSpawnPoint team=0 position="0,150,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <TeamSpawnPoint team=1 position="2000,  0,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+    <TeamSpawnPoint team=1 position="2000, 50,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+    <TeamSpawnPoint team=1 position="2000,100,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+    <TeamSpawnPoint team=1 position="2000,150,0" direction="-1,0,0" spawnclass=SpaceShip pawndesign=spaceshippirate />
+
+    <TeamSpawnPoint team=2 position="1000,  0,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+    <TeamSpawnPoint team=2 position="1000, 50,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+    <TeamSpawnPoint team=2 position="1000,100,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+    <TeamSpawnPoint team=2 position="1000,150,1500" direction="0,0,-1" spawnclass=SpaceShip pawndesign=spaceshipHtwo />
+
+
+    <?lua
+      for i = 1, 70, 1 do
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 1000 + 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * -1000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 1000 + 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * -1000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 1000 + 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * -1000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 50 + 20) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/templates/DodgeRacePattern.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/DodgeRacePattern.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/DodgeRacePattern.oxt	(revision 11817)
@@ -0,0 +1,61 @@
+<Template name=DodgeRaceCube01>
+  
+	<DodgeRaceCube position="0,0,0" direction="0,0,0"   scale="1" collisionType=dynamic mass=1 friction=0.01 >
+      <attached>
+        <Model position="700,0,50" 		mesh="CuboidBody.mesh" 		scale3D="300,50,50" 	/>
+		<Model position="700,0,1150" 	mesh="CuboidBody.mesh" 		scale3D="300,50,50" 	/>
+		<Model position="1200,0,200" 	mesh="CuboidBody.mesh" 		scale3D="100,50,100" 	/>
+		<Model position="1200,0,1000"	mesh="CuboidBody.mesh" 		scale3D="100,50,100" 	/>
+		<Model position="1250,-10,430"	mesh="CuboidBody.mesh" 		scale3D="50,40,30" 		/>
+		<Model position="1250,-10,600"	mesh="CuboidBody.mesh" 		scale3D="50,40,30" 		/>
+		<Model position="1250,-10,770"	mesh="CuboidBody.mesh" 		scale3D="50,40,30" 		/>
+		<Model position="1650,0,350"	mesh="CuboidBody.mesh" 		scale3D="50,50,150" 	/>
+		<Model position="1650,0,850"	mesh="CuboidBody.mesh" 		scale3D="50,50,150" 	/>
+		<Model position="2100,0,150" 	mesh="CuboidBody.mesh" 		scale3D="100,50,150" 	/>
+		<Model position="2100,0,1050"	mesh="CuboidBody.mesh" 		scale3D="100,50,150" 	/>
+		<Model position="2150,0,600"	mesh="CuboidBody.mesh"		scale3D="50,50,100"		/>
+      </attached>
+
+      <collisionShapes>
+		<BoxCollisionShape position="700,0,50" 		 		halfExtents="300,50,50" 	/>
+		<BoxCollisionShape position="700,0,1150" 	 		halfExtents="300,50,50" 	/>
+		<BoxCollisionShape position="1200,0,200" 	 		halfExtents="100,50,100" 	/>
+		<BoxCollisionShape position="1200,0,1000"	 		halfExtents="100,50,100" 	/>
+		<BoxCollisionShape position="1250,-10,430"	 		halfExtents="50,40,30" 		/>
+		<BoxCollisionShape position="1250,-10,600"	 		halfExtents="50,40,30" 		/>
+		<BoxCollisionShape position="1250,-10,770"	 		halfExtents="50,40,30" 		/>
+		<BoxCollisionShape position="1650,0,350"	 		halfExtents="50,50,150" 	/>
+		<BoxCollisionShape position="1650,0,850"	 		halfExtents="50,50,150" 	/>
+		<BoxCollisionShape position="2100,0,150" 	 		halfExtents="100,50,150" 	/>
+		<BoxCollisionShape position="2100,0,1050"	 		halfExtents="100,50,150" 	/>
+		<BoxCollisionShape position="2150,0,600"			halfExtents="50,50,100"		/>
+      </collisionShapes>
+	</DodgeRaceCube>
+
+</Template>
+
+<Template name=DodgeRaceCube02>
+  
+	<DodgeRaceCube position="0,0,0" direction="0,0,0"   scale="1" collisionType=dynamic mass=1 friction=0.01 >
+      <attached>
+		<Model position="450,0,300" 	mesh="CuboidBody.mesh" 		scale3D="50,50,300" 	/>
+		<Model position="950,0,850" 	mesh="CuboidBody.mesh" 		scale3D="50,50,350" 	/>
+		<Model position="1350,0,200" 	mesh="CuboidBody.mesh" 		scale3D="50,50,200" 	/>
+		<Model position="1350,0,700"	mesh="CuboidBody.mesh" 		scale3D="50,50,100" 	/>
+		<Model position="1750,0,350"	mesh="CuboidBody.mesh" 		scale3D="50,50,350" 	/>
+		<Model position="2000,0,1000"	mesh="CuboidBody.mesh" 		scale3D="100,50,100" 	/>
+		<Model position="1650,0,1150"	mesh="CuboidBody.mesh" 		scale3D="450,50,50" 	/>
+      </attached>
+
+      <collisionShapes>
+		<BoxCollisionShape position="450,0,300" 		 		halfExtents="50,50,300" 	/>
+		<BoxCollisionShape position="950,0,850" 	 		halfExtents="50,50,350" 	/>
+		<BoxCollisionShape position="1350,0,200" 	 		halfExtents="50,50,200" 	/>
+		<BoxCollisionShape position="1350,0,700"		 		halfExtents="50,50,100" 	/>
+		<BoxCollisionShape position="1750,0,350"	 		halfExtents="50,50,350" 	/>
+		<BoxCollisionShape position="2000,0,1000"	 		halfExtents="100,50,100" 	/>
+		<BoxCollisionShape position="1650,0,1150"	 		halfExtents="450,50,50" 	/>
+      </collisionShapes>
+	</DodgeRaceCube>
+
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/FPS.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/FPS.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/FPS.oxt	(revision 11817)
@@ -0,0 +1,66 @@
+<Template name=fps>
+  <FpsPlayer
+   hudtemplate            = fpshud
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 30
+   initialshieldhealth = 30
+   maxshieldhealth     = 30
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 0;
+   auxilaryThrust    = 0;
+   rotationThrust    = 0;
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+   friction          = 0.01
+
+   weapon            = "hs-w01.mesh"
+  >
+    <collisionShapes>			<!-- old values: position="0,-20,0"  halfExtents="15,25,15"  -->
+      <BoxCollisionShape position="0,-25,0" halfExtents="15,20,15" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+    </explosion>
+
+    <camerapositions>
+      <CameraPosition position="-1,1,2.2" drag=false mouselook=true />
+    </camerapositions>
+
+    <?lua
+        include("../includes/weaponSettingsFPS.oxi")
+    ?>
+
+  </FpsPlayer>
+</Template>
+<!--
+<Template name=fpscamera defaults=0>
+  <FpsPlayer>
+    <camerapositions>
+      <CameraPosition position="0,0,20" drag=false mouselook=true />
+
+      <!--
+      CameraPosition position="0,150,-25" pitch=-90 drag=true />
+      <CameraPosition position="0,0,-40" yaw=180 drag=true />
+      <CameraPosition position="0,3,-14" yaw=0 />
+      <CameraPosition position="-50,5,-8" yaw=-90 drag=true />
+      <CameraPosition position="50,5,-8" yaw=90 drag=true /
+
+    </camerapositions>
+  </FpsPlayer>
+</Template>
+-->
Index: /code/branches/RacingBots_FS18/data/levels/templates/HeavyCruiser.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/HeavyCruiser.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/HeavyCruiser.oxt	(revision 11817)
@@ -0,0 +1,607 @@
+<!-- This template includes HeavyCruiser with all its parts (not individually destructible) -->
+
+<Template name=HeavyCruiser>
+  <ModularSpaceShip
+   name = HeavyCruiser
+   
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = heavycruisercameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 2000
+   maxhealth         = 4000
+   initialhealth     = 2000
+
+   shieldhealth        = 100
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 300
+   auxilaryThrust    = 30
+   rotationThrust    = 0.1
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 30
+   boostPowerRate        = 1.5
+   boostRate             = 4
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 10000
+   linearDamping     = 0.1
+   angularDamping    = 0.5
+  >
+    <engines>
+      <MultiStateEngine position="0,0,0" template=HeavyCruiser_body_engine1 />
+
+      <MultiStateEngine position="-140,0,308" template=HeavyCruiser_sidearmL_engine1 />
+      <MultiStateEngine position="140,0,308" template=HeavyCruiser_sidearmR_engine1 />
+    </engines>
+    
+    <parts>
+        <ShipPart name="frontL" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="-76,30,-330">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship" targetParam="shieldhealth" operation="*" value="0.5"/>
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="frontR" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="76,30,-330">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship" targetParam="shieldhealth" operation="*" value="0.5"/>
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="partL" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="-100,33,-200">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship" targetParam="boostpowerrate" operation="-" value="0.5" message="One of your ship's generators was destroyed!"/>
+                <PartDestructionEvent targetType="engine" targetName="bodyengine" targetParam="speedfront" operation="-" value="50"/>
+                <PartDestructionEvent targetType="engine" targetName="bodyengine" targetParam="accelerationfront" operation="-" value="3"/>
+                <PartDestructionEvent targetType="engine" targetName="bodyengine" targetParam="boostfactor" operation="set" value="1"/>
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="partR" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="100,33,-200">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship" targetParam="boostpowerrate" operation="-" value="0.5" message="One of your ship's generators was destroyed!"/>
+                <PartDestructionEvent targetType="engine" targetName="bodyengine" targetParam="speedfront" operation="-" value="50"/>
+                <PartDestructionEvent targetType="engine" targetName="bodyengine" targetParam="accelerationfront" operation="-" value="3"/>
+                <PartDestructionEvent targetType="engine" targetName="bodyengine" targetParam="boostfactor" operation="set" value="1"/>
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="sidearmL" initialhealth="20" maxhealth="20" damageabsorption="0.2" explosionposition="-140,30,100">
+            <destructionevents>
+                <PartDestructionEvent targetType="engine" targetName="sidearmLengine" operation="destroy" message="The left auxiliary engine was destroyed!"/>
+                <PartDestructionEvent targetType="part" targetName="sidearmLfront" operation="destroy"/>
+                <PartDestructionEvent targetType="ship" targetParam="rotationthrust" operation="-" value="0.04" />
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="sidearmLfront" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="-140,20,-50">
+            <destructionevents>
+                <PartDestructionEvent targetType="engine" targetName="sidearmLengine" targetParam="boostfactor" operation="set" value="1" message="The left auxiliary engine lost it's booster!"/>
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="sidearmR" initialhealth="20" maxhealth="20" damageabsorption="0.2" explosionposition="140,30,100">
+            <destructionevents>
+                <PartDestructionEvent targetType="engine" targetName="sidearmRengine" operation="destroy" message="The right auxiliary engine was destroyed!"/>
+                <PartDestructionEvent targetType="part" targetName="sidearmRfront" operation="destroy"/> 
+                <PartDestructionEvent targetType="ship" targetParam="rotationthrust" operation="-" value="0.04" />           
+            </destructionevents>
+        </ShipPart>
+        <ShipPart name="sidearmRfront" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="140,20,-50">
+            <destructionevents>
+                <PartDestructionEvent targetType="engine" targetName="sidearmRengine" targetParam="boostfactor" operation="set" value="1" message="The right auxiliary engine lost it's booster!"/>
+            </destructionevents>
+        </ShipPart>
+    </parts>
+    
+    <attached>
+        <Model mesh="HeavyCruiser_body.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+        
+        <StaticEntity name="frontL" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_frontL.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+                <BlinkingBillboard position="-75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+                <BlinkingBillboard position="-74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+                <BlinkingBillboard position="-73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="-80,33,-320" halfExtents="7,11,54" info="frontL"/>
+                <BoxCollisionShape position="-79,31,-399" halfExtents="3,6,26" info="frontL"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+        <StaticEntity name="frontR" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_frontR.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+                <BlinkingBillboard position="75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+                <BlinkingBillboard position="74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+                <BlinkingBillboard position="73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="80,33,-320" halfExtents="7,11,54" info="frontR"/>
+                <BoxCollisionShape position="79,31,-399" halfExtents="3,6,26" info="frontR"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+        <StaticEntity name="partL" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_partL.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="-94,33,-179" halfExtents="11,13,45" info="partL"/>
+                <BoxCollisionShape position="-96,33,-230" halfExtents="13,17,22" info="partL"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+        <StaticEntity name="partR" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_partR.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="94,33,-179" halfExtents="11,13,45" info="partR"/>
+                <BoxCollisionShape position="96,33,-230" halfExtents="13,17,22" info="partR"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+                <StaticEntity name="sidearmL" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_sidearmL.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="-109,47,87" halfExtents="29,8,26" info="sidearmL, upper connection"/>
+                <BoxCollisionShape position="-99,-1,79" roll="15" halfExtents="40,4,9" info="sidearmL, lower connection"/>
+                <BoxCollisionShape position="-145,21,115" roll="15" halfExtents="19,31,105" info="sidearmL, front"/>
+                <BoxCollisionShape position="-140,12,261" roll="15" halfExtents="22,41,43" info="sidearmL, back"/>
+                <BoxCollisionShape position="-145,25,5" roll="15" halfExtents="10,18,5" info="sidearmL, front break"/>
+                <BoxCollisionShape position="-133,-13,29" roll="15" halfExtents="12,6,17" info="sidearmL, bottom cylinder"/>
+                <BoxCollisionShape position="-165,-4,31" roll="15" halfExtents="7,21,13" info="sidearmL, box"/>
+                <BoxCollisionShape position="-153,59,96" roll="15" halfExtents="6,7,60" info="sidearmL, upper beam"/>
+                <BoxCollisionShape position="-143,57,119" roll="15" halfExtents="3,4,85" info="sidearmL, upper inner beam"/>
+                <BoxCollisionShape position="-142,53,212" pitch="21" yaw="5" roll="15" halfExtents="3,4,10" info="sidearmL, upper inner beam"/>
+                <BoxCollisionShape position="-160,52,119" roll="15" halfExtents="3,4,85" info="sidearmL, upper outer beam"/>
+                <BoxCollisionShape position="-159,48,212" pitch="21" yaw="5" roll="15" halfExtents="3,4,10" info="sidearmL, upper outer beam"/>
+                <BoxCollisionShape position="-152,54,34" pitch="-46" yaw="-14" roll="15" halfExtents="6,7,10" info="sidearmL, upper beam front"/>
+                <BoxCollisionShape position="-152,54,162" pitch="30" yaw="9" roll="15" halfExtents="6,7,12" info="sidearmL, upper beam back"/>
+                <BoxCollisionShape position="-168,21,119" roll="15" halfExtents="3,5,109" info="sidearmL, outer beam"/>
+                <BoxCollisionShape position="-134,-10,169" roll="15" halfExtents="6,4,55" info="sidearmL, lower beam front"/>
+                <BoxCollisionShape position="-131,-20,217" pitch="-20" roll="15" yaw="-5" halfExtents="6,12,3" info="sidearmL, lower beam middle"/>
+                <BoxCollisionShape position="-130,-29,233" roll="15" halfExtents="6,3,15" info="sidearmL, lower beam back"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+        <StaticEntity name="sidearmLfront" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_sidearmLfront.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="-141,15,-53" roll="15" halfExtents="27,44,62" info="sidearmLfront"/>
+                <BoxCollisionShape position="-153,59,-30" roll="15" halfExtents="4,2,38" info="sidearmLfront, top"/>
+                <BoxCollisionShape position="-153,61,-41" roll="15" halfExtents="4,4,11" info="sidearmLfront, top"/>
+                <BoxCollisionShape position="-153,60,-65" roll="15" halfExtents="4,3,4" info="sidearmLfront, top"/>
+                <BoxCollisionShape position="-153,59,-41" roll="15" halfExtents="8,2,11" info="sidearmLfront, top"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+        <StaticEntity name="sidearmR" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_sidearmR.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="109,47,87" halfExtents="29,8,26" info="sidearmR, upper connection"/>
+                <BoxCollisionShape position="99,-1,79" roll="-15" halfExtents="40,4,9" info="sidearmR, lower connection"/>
+                <BoxCollisionShape position="145,21,115" roll="-15" halfExtents="19,31,105" info="sidearmR, front"/>
+                <BoxCollisionShape position="140,12,261" roll="-15" halfExtents="22,41,43" info="sidearmR, back"/>
+                <BoxCollisionShape position="145,25,5" roll="-15" halfExtents="10,18,5" info="sidearmR, front break"/>
+                <BoxCollisionShape position="133,-13,29" roll="-15" halfExtents="12,6,17" info="sidearmR, bottom cylinder"/>
+                <BoxCollisionShape position="165,-4,31" roll="-15" halfExtents="7,21,13" info="sidearmR, box"/>
+                <BoxCollisionShape position="153,59,96" roll="-15" halfExtents="6,7,60" info="sidearmR, upper beam"/>
+                <BoxCollisionShape position="143,57,119" roll="-15" halfExtents="3,4,85" info="sidearmR, upper inner beam"/>
+                <BoxCollisionShape position="142,53,212" pitch="21" yaw="-5" roll="-15" halfExtents="3,4,10" info="sidearmR, upper inner beam"/>
+                <BoxCollisionShape position="160,52,119" roll="-15" halfExtents="3,4,85" info="sidearmR, upper outer beam"/>
+                <BoxCollisionShape position="159,48,212" pitch="21" yaw="-5" roll="-15" halfExtents="3,4,10" info="sidearmR, upper outer beam"/>
+                <BoxCollisionShape position="152,54,34" pitch="-46" yaw="14" roll="-15" halfExtents="6,7,10" info="sidearmR, upper beam front"/>
+                <BoxCollisionShape position="152,54,162" pitch="30" yaw="-9" roll="-15" halfExtents="6,7,12" info="sidearmR, upper beam back"/>
+                <BoxCollisionShape position="168,21,119" roll="-15" halfExtents="3,5,109" info="sidearmR, outer beam"/>
+                <BoxCollisionShape position="134,-10,169" roll="-15" halfExtents="6,4,55" info="sidearmR, lower beam front"/>
+                <BoxCollisionShape position="131,-20,217" pitch="-20" roll="-15" yaw="5" halfExtents="6,12,3" info="sidearmR, lower beam middle"/>
+                <BoxCollisionShape position="130,-29,233" roll="-15" halfExtents="6,3,15" info="sidearmR, lower beam back"/>
+            </collisionShapes> 
+        </StaticEntity>
+        
+        <StaticEntity name="sidearmRfront" position="0,0,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached> 
+                <Model mesh="HeavyCruiser_sidearmRfront.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>
+            </attached> 
+            <collisionShapes> 
+                <BoxCollisionShape position="141,15,-53" roll="-15" halfExtents="27,44,62" info="sidearmRfront"/>
+                <BoxCollisionShape position="153,59,-30" roll="-15" halfExtents="4,2,38" info="sidearmRfront, top"/>
+                <BoxCollisionShape position="153,61,-41" roll="-15" halfExtents="4,4,11" info="sidearmRfront, top"/>
+                <BoxCollisionShape position="153,60,-65" roll="-15" halfExtents="4,3,4" info="sidearmRfront, top"/>
+                <BoxCollisionShape position="153,59,-41" roll="-15" halfExtents="8,2,11" info="sidearmRfront, top"/>
+            </collisionShapes> 
+        </StaticEntity>   
+
+            <!-- front position lights -->
+        <BlinkingBillboard position="67,-5,-240" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+        <BlinkingBillboard position="-67,-5,-240" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        <BlinkingBillboard position="72,51,-380" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        <BlinkingBillboard position="-72,51,-380" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <!-- rear position lights -->
+        <BlinkingBillboard position="95,-15,483" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        <BlinkingBillboard position="-95,-15,483" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+        <BlinkingBillboard position="74,103,524" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+        <BlinkingBillboard position="-74,103,524" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="60,35,-310" halfExtents="13,28,60" info="body, bay1, Rwall"/> 
+        <BoxCollisionShape position="-60,35,-310" halfExtents="13,28,60" info="body, bay1, Lwall"/> 
+        <BoxCollisionShape position="0,56,-310" halfExtents="65,6,60" info="body, bay1, Twall"/> 
+        <BoxCollisionShape position="0,33,-260" halfExtents="65,28,5" info="body, bay1, Bwall"/>
+        <BoxCollisionShape position="0,10,-310" halfExtents="65,5,60" info="body, bay1, BottomWall"/>  
+
+        <BoxCollisionShape position="0,35,-125" halfExtents="83,30,130" info="body, front"/>
+        <BoxCollisionShape position="0,6,-307" halfExtents="19,3,43" info="body, frontbottom"/>
+        <BoxCollisionShape position="0,5,-196" halfExtents="27,3,24" info="body, dock"/>
+        <BoxCollisionShape position="0,7,-248" pitch="25" halfExtents="63,4,12" info="body, dockF"/>
+        <BoxCollisionShape position="70,6,-120" roll="20" halfExtents="12,6,120" info="body, dockR"/>
+        <BoxCollisionShape position="63,-2,-180" halfExtents="3,3,60" info="body, dockR"/>
+        <BoxCollisionShape position="-70,6,-120" roll="-20" halfExtents="12,6,120" info="body, dockL"/>
+        <BoxCollisionShape position="-63,-2,-180" halfExtents="3,3,60" info="body, dockL"/>
+        <BoxCollisionShape position="87,32,-63" halfExtents="4,23,50" info="body, frontCR"/>
+        <BoxCollisionShape position="-87,32,-63" halfExtents="4,23,50" info="body, frontCL"/>
+
+        <BoxCollisionShape position="0,72,-213" halfExtents="37,8,60" info="body, Fbridge"/>
+        <BoxCollisionShape position="0,72,-110" halfExtents="53,11,53" info="body, Cbridge"/>
+        <BoxCollisionShape position="0,86,-110" halfExtents="40,4,40" info="body, Cbridge"/>
+        <BoxCollisionShape position="0,70,-60" halfExtents="65,11,30" info="body, Bbridge"/>
+        <BoxCollisionShape position="0,84,-45" halfExtents="33,11,26" info="body, Bbridge"/>
+        <BoxCollisionShape position="0,79,-6" pitch="10" halfExtents="32,13,17" info="body, Bbridge"/>
+        <BoxCollisionShape position="38,67,-45" roll="50" halfExtents="16,23,25" info="body, BbridgeR"/>
+        <BoxCollisionShape position="35,63,-17" pitch="25" yaw="-20" roll="40" halfExtents="16,23,16" info="body, BbridgeR"/>
+        <BoxCollisionShape position="-38,67,-45" roll="-50" halfExtents="16,23,25" info="body, BbridgeL"/>
+        <BoxCollisionShape position="-35,63,-17" pitch="25" yaw="20" roll="-40" halfExtents="16,23,16" info="body, BbridgeL"/>
+
+        <BoxCollisionShape position="0,69,80" halfExtents="8,4,80" info="body, Cbeam"/> 
+        <BoxCollisionShape position="-67,18,58" roll="-22" halfExtents="13,5,53" info="body, CF, L"/>
+        <BoxCollisionShape position="-76,36,86" halfExtents="5,18,81" info="body, C, L"/>
+        <BoxCollisionShape position="-91,46,86" halfExtents="11,6,20" info="body, C, L upper beam"/>
+        <BoxCollisionShape position="-64,8,79" roll="10" halfExtents="8,3,8" info="body, C, L lower beam"/>
+        <BoxCollisionShape position="-71,55,140" pitch="-4" roll="31" halfExtents="9,5,27" info="body, CB, TopL"/>
+        <BoxCollisionShape position="-62,2,140" roll="24" halfExtents="10,24,32" info="body, CB, BottomL"/>
+        <BoxCollisionShape position="67,18,58" roll="22" halfExtents="13,5,53" info="body, CF, R"/>
+        <BoxCollisionShape position="76,36,86" halfExtents="5,18,81" info="body, C, R"/>
+        <BoxCollisionShape position="91,46,86" halfExtents="11,6,20" info="body, C, R upper beam"/>
+        <BoxCollisionShape position="64,8,79" roll="-10" halfExtents="8,3,8" info="body, C, R lower beam"/> 
+        <BoxCollisionShape position="71,55,140" pitch="-4" roll="-31" halfExtents="9,5,27" info="body, CB, TopR"/>
+        <BoxCollisionShape position="62,2,140" roll="-24" halfExtents="10,24,32" info="body, CB, BottomR"/>
+        <BoxCollisionShape position="0,60,12" halfExtents="81,5,11" info="body, CF, Top"/>
+        <BoxCollisionShape position="0,55,40" pitch="15" halfExtents="81,5,20" info="body, CF, Top"/>
+        <BoxCollisionShape position="0,50,85" pitch="1" halfExtents="81,5,29" info="body, C, Top"/>
+        <BoxCollisionShape position="0,59,140" pitch="-4" halfExtents="68,5,27" info="body, CB, Top"/>
+        
+
+
+        <BoxCollisionShape position="0,-7,90" halfExtents="40,4,90" info="body, bay3, Twall"/>
+        <BoxCollisionShape position="0,-15,-60" halfExtents="60,25,65" info="body, bay3, Fwall"/>
+        <BoxCollisionShape position="47,-11,90" halfExtents="13,20,90" info="body, bay3, Rwall"/>
+        <BoxCollisionShape position="-47,-11,90" halfExtents="13,20,90" info="body, bay3, Lwall"/>
+        <BoxCollisionShape position="0,-29,149" halfExtents="10,2,11" info="body, bay3, platform"/>
+        <BoxCollisionShape position="0,-20,227" halfExtents="60,20,65" info="body, bay3, Bwall"/>
+
+        <BoxCollisionShape position="0,81,238" halfExtents="26,5,59" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,67,234" halfExtents="54,5,67" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,77,175" pitch="-36" halfExtents="26,5,9" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,62,161" pitch="-30" halfExtents="56,5,10" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,69,162" halfExtents="16,7,10" info="body, BF, Top"/>
+        <BoxCollisionShape position="31,76,238" roll="-46" halfExtents="10,3,59" info="body, BF, TopR"/>
+        <BoxCollisionShape position="64,64,234" roll="-24" halfExtents="13,3,67" info="body, BF, TopR"/>
+        <BoxCollisionShape position="-31,76,238" roll="46" halfExtents="10,3,59" info="body, BF, TopL"/>
+        <BoxCollisionShape position="-64,64,234" roll="24" halfExtents="13,3,67" info="body, BF, TopL"/>
+
+        <BoxCollisionShape position="77,40,244" roll="16" halfExtents="7,20,79" info="body, BF, R"/>
+        <BoxCollisionShape position="95,9,234" roll="2" halfExtents="18,16,59" info="body, BF, R"/>
+        <BoxCollisionShape position="74,1,255" roll="-20" halfExtents="18,19,82" info="body, BF, BottomR"/>
+        <BoxCollisionShape position="66,-21,255" roll="9" halfExtents="17,5,82" info="body, BF, BottomR"/>
+        <BoxCollisionShape position="-77,40,244" roll="-16" halfExtents="7,20,79" info="body, BF, L"/>
+        <BoxCollisionShape position="-95,9,234" roll="-2" halfExtents="18,16,59" info="body, BF, L"/>
+        <BoxCollisionShape position="-74,1,255" roll="20" halfExtents="18,19,82" info="body, BF, BottomL"/>
+        <BoxCollisionShape position="-66,-21,255" roll="-9" halfExtents="17,5,82" info="body, BF, BottomL"/>
+
+        <BoxCollisionShape position="0,106,381" halfExtents="36,5,71" info="body, BTop"/>
+        <BoxCollisionShape position="0,93,299" pitch="-49" halfExtents="34,5,20" info="body, BTop"/>
+        <BoxCollisionShape position="41,101,381" roll="-42" halfExtents="10,4,71" info="body, BTopR"/>
+        <BoxCollisionShape position="-41,101,381" roll="42" halfExtents="10,4,71" info="body, BTopL"/>
+
+        <BoxCollisionShape position="78,45,332" pitch="-10" roll="-10" yaw="20" halfExtents="10,20,30" info="body, back, R"/>
+        <BoxCollisionShape position="68,77,332" pitch="-10" roll="35" yaw="20" halfExtents="10,20,30" info="body, back, TR"/>
+        <BoxCollisionShape position="50,70,290" pitch="-10" roll="35" yaw="43" halfExtents="5,20,20" info="body, back, TR"/>
+        <BoxCollisionShape position="37,95,307" pitch="-10" roll="30" yaw="43" halfExtents="5,8,8" info="body, back, TR"/>
+        <BoxCollisionShape position="52,92,332" pitch="-10" yaw="30" halfExtents="10,5,30" info="body, back, TR"/>
+        <BoxCollisionShape position="88,4,322" halfExtents="10,24,30" info="body, back, RB"/>
+        <BoxCollisionShape position="54,-24,314" roll="35" pitch="-10" halfExtents="8,5,23" info="body, back, RB"/>
+        <BoxCollisionShape position="68,-19,346" pitch="-17" roll="8" halfExtents="16,4,11" info="body, back, bottomR"/>
+        <BoxCollisionShape position="-78,45,332" pitch="-10" roll="10" yaw="-20" halfExtents="10,20,30" info="body, back, L"/>
+        <BoxCollisionShape position="-68,77,332" pitch="-10" roll="-35" yaw="-20" halfExtents="10,20,30" info="body, back, TL"/>
+        <BoxCollisionShape position="-50,70,290" pitch="-10" roll="-35" yaw="-43" halfExtents="5,20,20" info="body, back, TL"/>
+        <BoxCollisionShape position="-37,95,307" pitch="-10" roll="-30" yaw="-43" halfExtents="5,8,8" info="body, back, TL"/>
+        <BoxCollisionShape position="-52,92,332" pitch="-10" yaw="-30" halfExtents="10,5,30" info="body, back, TL"/>
+        <BoxCollisionShape position="-88,4,322" halfExtents="10,24,30" info="body, back, LB"/>
+        <BoxCollisionShape position="-54,-24,314" roll="-35" pitch="-10" halfExtents="8,5,23" info="body, back, LB"/>
+        <BoxCollisionShape position="-68,-19,346" pitch="-17" roll="-8" halfExtents="16,4,11" info="body, back, bottomL"/>
+        <BoxCollisionShape position="0,-30,314" pitch="-8" halfExtents="52,4,23" info="body, back, bottom"/>
+        <BoxCollisionShape position="0,-22,346" pitch="-24" halfExtents="52,4,11" info="body, back, bottom"/>
+
+        <BoxCollisionShape position="48,-29,400" halfExtents="5,8,58" info="body, BBottomRBeam"/>
+        <BoxCollisionShape position="48,-29,451" halfExtents="10,13,14" info="body, BBottomRBeam"/>
+        <BoxCollisionShape position="-48,-29,400" halfExtents="5,8,58" info="body, BBottomLBeam"/>
+        <BoxCollisionShape position="-48,-31,451" halfExtents="10,13,14" info="body, BBottomLBeam"/>
+
+        <BoxCollisionShape position="103,60,420" halfExtents="18,9,64" info="body, back, Rextrusion"/>
+        <BoxCollisionShape position="-103,60,420" halfExtents="18,9,64" info="body, back, Lextrusion"/>
+        <BoxCollisionShape position="-85,7,417" halfExtents="10,21,67" info="body, back, LB"/>
+        <BoxCollisionShape position="85,7,417" halfExtents="10,21,67" info="body, back, RB"/>
+        <BoxCollisionShape position="0,-8,473" halfExtents="90,6,10" info="body, back, Bback"/>
+        <BoxCollisionShape position="0,-13,474" pitch="-23" halfExtents="76,5,8" info="body, back, Bback"/>
+        <BoxCollisionShape position="-79,-13,405" roll="-12" halfExtents="15,5,73" info="body, back, BL"/>
+        <BoxCollisionShape position="79,-13,405" roll="12" halfExtents="15,5,73" info="body, back, BR"/>
+        <BoxCollisionShape position="0,-15,410" halfExtents="66,6,58" info="body, back, B"/>
+
+        <BoxCollisionShape position="78,32,440" roll="-18" halfExtents="18,35,85" info="body, bay2, Rwall"/>
+        <BoxCollisionShape position="75,71,440" roll="35" halfExtents="18,27,85" info="body, bay2, Rwall"/>             
+        <BoxCollisionShape position="-78,32,440" roll="18" halfExtents="18,35,85" info="body, bay2, Lwall"/>
+        <BoxCollisionShape position="-75,71,440" roll="-35" halfExtents="18,27,85" info="body, bay2, Lwall"/>             
+        <BoxCollisionShape position="0,75,435" halfExtents="72,28,90" info="body, bay2, Twall"/>
+        <BoxCollisionShape position="0,35,423" halfExtents="85,35,5" info="body, bay2, Fwall"/> 
+        <BoxCollisionShape position="0,-3,465" halfExtents="84,5,60" info="body, bay2, BottomWall"/>
+        <BoxCollisionShape position="0,78,526" halfExtents="43,17,5" info="body, bay2, Twall"/> 
+        
+        
+        <BoxCollisionShape position="0,7,80" halfExtents="23,1,34" info="HOOKBOX at 0,18,80, bottom"/>
+        <BoxCollisionShape position="0,29,80" halfExtents="23,1,34" info="HOOKBOX, top"/>
+        <BoxCollisionShape position="-22,18,80" halfExtents="1,12,34" info="HOOKBOX, left long"/>
+        <BoxCollisionShape position="0,18,80" halfExtents="1,12,34" info="HOOKBOX, center long"/>
+        <BoxCollisionShape position="22,18,80" halfExtents="1,12,34" info="HOOKBOX, right long"/>
+        <BoxCollisionShape position="0,18,113" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        <BoxCollisionShape position="0,18,91" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        <BoxCollisionShape position="0,18,69" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        <BoxCollisionShape position="0,18,47" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+       
+<!-- Following the position of the other parts collisionboxes, used to attach them to the body --> 
+<!--         <BoxCollisionShape position="-11,18,102" halfExtents="10,10,10" info="HOOK, sidearmL"/>
+        <BoxCollisionShape position="11,18,102" halfExtents="10,10,10" info="HOOK, sidearmR"/>
+        <BoxCollisionShape position="-11,18,80" halfExtents="10,10,10" info="HOOK, partL"/>
+        <BoxCollisionShape position="11,18,80" halfExtents="10,10,10" info="HOOK, partR"/>
+        <BoxCollisionShape position="-11,18,58" halfExtents="10,10,10" info="HOOK, frontL"/>
+        <BoxCollisionShape position="11,18,58" halfExtents="10,10,10" info="HOOK, frontR"/> -->
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsHeavyCruiser.oxi")
+?>
+  </ModularSpaceShip>
+
+</Template>
+
+
+
+
+<Template name=heavycruisercameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,200, 1000" drag=true mouselook=true />
+      <CameraPosition position="0,100, 1000" drag=true mouselook=true />
+      <CameraPosition position="0,150,600" drag=true mouselook=true />
+      <CameraPosition position="0,80,-300" drag=false mouselook=false />
+      <CameraPosition position="200,80,300" drag=false mouselook=false />
+      <CameraPosition position="0,1100,60" pitch="-90" drag=false mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+
+
+
+<Template name=HeavyCruiser_body_engine1 baseclass=MultiStateEngine>
+  <MultiStateEngine
+   name		  = bodyengine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  40
+   speedleftright =  40
+   speedupdown    =  40
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 8
+   accelerationback      =  4
+   accelerationleftright =  4
+   accelerationupdown    =  4
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-66,87,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-73,77,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-80,68,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.8 position="-86,58,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-82,46,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-80,34,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-76,21,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.6 position="-71,9,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="66,87,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="73,77,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="80,68,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.8 position="86,58,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="82,46,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="80,34,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="76,21,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.6 position="71,9,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="66,87,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="73,77,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,68,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="86,58,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="82,46,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,34,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.4 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="76,21,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="71,9,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-66,87,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-73,77,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,68,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-86,58,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-82,46,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,34,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.4 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-76,21,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-71,9,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="85,58,525" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-85,58,525" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="66,87,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="73,77,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,68,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="86,58,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="82,46,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,34,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="76,21,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="71,9,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-66,87,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-73,77,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,68,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-86,58,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-82,46,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,34,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-76,21,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-71,9,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
+
+
+<Template name=HeavyCruiser_sidearmL_engine1 baseclass=MultiStateEngine>
+  <MultiStateEngine
+   name		  = sidearmLengine
+   boostfactor    = 2
+
+   speedfront     = 300
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 8
+   accelerationback      =  4
+   accelerationleftright =  4
+   accelerationupdown    =  4
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=1 position="-147,35,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position="-136,-5,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-147,35,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-136,-5,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-147,35,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-136,-5,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-148,35,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-136,-5,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
+
+
+<Template name=HeavyCruiser_sidearmR_engine1 baseclass=MultiStateEngine>
+  <MultiStateEngine
+   name		  = sidearmRengine
+   boostfactor    = 2
+
+   speedfront     = 300
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 8
+   accelerationback      =  4
+   accelerationleftright =  4
+   accelerationupdown    =  4
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=1 position="147,35,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position="136,-5,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="147,35,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="136,-5,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="147,35,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="136,-5,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="147,35,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="136,-5,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/HeavyCruiserBody.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/HeavyCruiserBody.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/HeavyCruiserBody.oxt	(revision 11817)
@@ -0,0 +1,431 @@
+<!-- This template includes HeavyCruiser's main body only. Its parts can be attached as Pawns -->
+
+<Template name=HeavyCruiserBody>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = HeavyCruiser_cameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 1000
+   maxhealth         = 2000
+   initialhealth     = 1000
+
+   shieldhealth        = 1000
+   initialshieldhealth = 300
+   maxshieldhealth     = 500
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 300
+   auxilaryThrust    = 30
+   rotationThrust    = 0.1
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 30
+   boostPowerRate        = 1.5
+   boostRate             = 4
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 3
+
+   collisionType     = "dynamic"
+   mass              = 10000
+   linearDamping     = 0.1
+   angularDamping    = 0.5
+  >
+    <engines>
+      <MultiStateEngine position="85,0,0" template=HeavyCruiser_body_engine /> <!-- engine attached to main body-->
+      <MultiStateEngine position="-85,0,0" template=HeavyCruiser_body_engine /> <!-- engine attached to main body-->
+
+      <MultiStateEngine position="-140,0,308" template=HeavyCruiser_sidearmL_engine /> <!-- engine attached to sidearmL-->
+      <MultiStateEngine position="140,0,308" template=HeavyCruiser_sidearmR_engine /> <!-- engine attached to sidearmR-->
+    </engines>
+    <attached>
+
+        <Model mesh="HeavyCruiser_body.mesh" direction="-1,0,0" position="0,0,0" scale="40"/>       
+
+            <!-- bay1 lights -->
+        <BlinkingBillboard position="75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+        <BlinkingBillboard position="-75,30,-416" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.05 frequency=0.3 phase=240 quadratic=1 />
+        <BlinkingBillboard position="74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+        <BlinkingBillboard position="-74,30,-402" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.1 frequency=0.3 phase=120 quadratic=1 />
+        <BlinkingBillboard position="73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+        <BlinkingBillboard position="-73,30,-388" material="Examples/Flare" colour="0.8, 0.8, 0, 0.1" amplitude=0.15 frequency=0.3 phase=0 quadratic=1 />
+            <!-- front position lights -->
+        <BlinkingBillboard position="67,-5,-240" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+        <BlinkingBillboard position="-67,-5,-240" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        <BlinkingBillboard position="72,51,-380" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        <BlinkingBillboard position="-72,51,-380" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+            <!-- rear position lights -->
+        <BlinkingBillboard position="95,-15,483" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+        <BlinkingBillboard position="-95,-15,483" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+        <BlinkingBillboard position="74,103,524" material="Examples/Flare" colour="0, 0.7, 0, 0.1" amplitude=0.3 frequency=0.15 phase=0 quadratic=1 />
+        <BlinkingBillboard position="-74,103,524" material="Examples/Flare" colour="0.7, 0, 0, 0.1" amplitude=0.3 frequency=0.15 phase=360 quadratic=1 />
+
+    </attached>
+    <collisionShapes>
+        <BoxCollisionShape position="60,35,-310" halfExtents="13,28,60" info="body, bay1, Rwall"/> 
+        <BoxCollisionShape position="-60,35,-310" halfExtents="13,28,60" info="body, bay1, Lwall"/> 
+        <BoxCollisionShape position="0,56,-310" halfExtents="65,6,60" info="body, bay1, Twall"/> 
+        <BoxCollisionShape position="0,33,-260" halfExtents="65,28,5" info="body, bay1, Bwall"/>
+        <BoxCollisionShape position="0,10,-310" halfExtents="65,5,60" info="body, bay1, BottomWall"/>  
+
+        <BoxCollisionShape position="0,35,-125" halfExtents="83,30,130" info="body, front"/>
+        <BoxCollisionShape position="0,6,-307" halfExtents="19,3,43" info="body, frontbottom"/>
+        <BoxCollisionShape position="0,5,-196" halfExtents="27,3,24" info="body, dock"/>
+        <BoxCollisionShape position="0,7,-248" pitch="25" halfExtents="63,4,12" info="body, dockF"/>
+        <BoxCollisionShape position="70,6,-120" roll="20" halfExtents="12,6,120" info="body, dockR"/>
+        <BoxCollisionShape position="63,-2,-180" halfExtents="3,3,60" info="body, dockR"/>
+        <BoxCollisionShape position="-70,6,-120" roll="-20" halfExtents="12,6,120" info="body, dockL"/>
+        <BoxCollisionShape position="-63,-2,-180" halfExtents="3,3,60" info="body, dockL"/>
+        <BoxCollisionShape position="87,32,-63" halfExtents="4,23,50" info="body, frontCR"/>
+        <BoxCollisionShape position="-87,32,-63" halfExtents="4,23,50" info="body, frontCL"/>
+
+        <BoxCollisionShape position="0,72,-213" halfExtents="37,8,60" info="body, Fbridge"/>
+        <BoxCollisionShape position="0,72,-110" halfExtents="53,11,53" info="body, Cbridge"/>
+        <BoxCollisionShape position="0,86,-110" halfExtents="40,4,40" info="body, Cbridge"/>
+        <BoxCollisionShape position="0,70,-60" halfExtents="65,11,30" info="body, Bbridge"/>
+        <BoxCollisionShape position="0,84,-45" halfExtents="33,11,26" info="body, Bbridge"/>
+        <BoxCollisionShape position="0,79,-6" pitch="10" halfExtents="32,13,17" info="body, Bbridge"/>
+        <BoxCollisionShape position="38,67,-45" roll="50" halfExtents="16,23,25" info="body, BbridgeR"/>
+        <BoxCollisionShape position="35,63,-17" pitch="25" yaw="-20" roll="40" halfExtents="16,23,16" info="body, BbridgeR"/>
+        <BoxCollisionShape position="-38,67,-45" roll="-50" halfExtents="16,23,25" info="body, BbridgeL"/>
+        <BoxCollisionShape position="-35,63,-17" pitch="25" yaw="20" roll="-40" halfExtents="16,23,16" info="body, BbridgeL"/>
+
+        <BoxCollisionShape position="0,69,80" halfExtents="8,4,80" info="body, Cbeam"/> 
+        <BoxCollisionShape position="-67,18,58" roll="-22" halfExtents="13,5,53" info="body, CF, L"/>
+        <BoxCollisionShape position="-76,36,86" halfExtents="5,18,81" info="body, C, L"/>
+        <BoxCollisionShape position="-91,46,86" halfExtents="11,6,20" info="body, C, L upper beam"/>
+        <BoxCollisionShape position="-64,8,79" roll="10" halfExtents="8,3,8" info="body, C, L lower beam"/>
+        <BoxCollisionShape position="-71,55,140" pitch="-4" roll="31" halfExtents="9,5,27" info="body, CB, TopL"/>
+        <BoxCollisionShape position="-62,2,140" roll="24" halfExtents="10,24,32" info="body, CB, BottomL"/>
+        <BoxCollisionShape position="67,18,58" roll="22" halfExtents="13,5,53" info="body, CF, R"/>
+        <BoxCollisionShape position="76,36,86" halfExtents="5,18,81" info="body, C, R"/>
+        <BoxCollisionShape position="91,46,86" halfExtents="11,6,20" info="body, C, R upper beam"/>
+        <BoxCollisionShape position="64,8,79" roll="-10" halfExtents="8,3,8" info="body, C, R lower beam"/> 
+        <BoxCollisionShape position="71,55,140" pitch="-4" roll="-31" halfExtents="9,5,27" info="body, CB, TopR"/>
+        <BoxCollisionShape position="62,2,140" roll="-24" halfExtents="10,24,32" info="body, CB, BottomR"/>
+        <BoxCollisionShape position="0,60,12" halfExtents="81,5,11" info="body, CF, Top"/>
+        <BoxCollisionShape position="0,55,40" pitch="15" halfExtents="81,5,20" info="body, CF, Top"/>
+        <BoxCollisionShape position="0,50,85" pitch="1" halfExtents="81,5,29" info="body, C, Top"/>
+        <BoxCollisionShape position="0,59,140" pitch="-4" halfExtents="68,5,27" info="body, CB, Top"/>
+
+        <BoxCollisionShape position="0,-7,90" halfExtents="40,4,90" info="body, bay3, Twall"/>
+        <BoxCollisionShape position="0,-15,-60" halfExtents="60,25,65" info="body, bay3, Fwall"/>
+        <BoxCollisionShape position="47,-11,90" halfExtents="13,20,90" info="body, bay3, Rwall"/>
+        <BoxCollisionShape position="-47,-11,90" halfExtents="13,20,90" info="body, bay3, Lwall"/>
+        <BoxCollisionShape position="0,-29,149" halfExtents="10,2,11" info="body, bay3, platform"/>
+        <BoxCollisionShape position="0,-20,227" halfExtents="60,20,65" info="body, bay3, Bwall"/>
+
+        <BoxCollisionShape position="0,81,238" halfExtents="26,5,59" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,67,234" halfExtents="54,5,67" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,77,175" pitch="-36" halfExtents="26,5,9" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,62,161" pitch="-30" halfExtents="56,5,10" info="body, BF, Top"/>
+        <BoxCollisionShape position="0,69,162" halfExtents="16,7,10" info="body, BF, Top"/>
+        <BoxCollisionShape position="31,76,238" roll="-46" halfExtents="10,3,59" info="body, BF, TopR"/>
+        <BoxCollisionShape position="64,64,234" roll="-24" halfExtents="13,3,67" info="body, BF, TopR"/>
+        <BoxCollisionShape position="-31,76,238" roll="46" halfExtents="10,3,59" info="body, BF, TopL"/>
+        <BoxCollisionShape position="-64,64,234" roll="24" halfExtents="13,3,67" info="body, BF, TopL"/>
+
+        <BoxCollisionShape position="77,40,244" roll="16" halfExtents="7,20,79" info="body, BF, R"/>
+        <BoxCollisionShape position="95,9,234" roll="2" halfExtents="18,16,59" info="body, BF, R"/>
+        <BoxCollisionShape position="74,1,255" roll="-20" halfExtents="18,19,82" info="body, BF, BottomR"/>
+        <BoxCollisionShape position="66,-21,255" roll="9" halfExtents="17,5,82" info="body, BF, BottomR"/>
+        <BoxCollisionShape position="-77,40,244" roll="-16" halfExtents="7,20,79" info="body, BF, L"/>
+        <BoxCollisionShape position="-95,9,234" roll="-2" halfExtents="18,16,59" info="body, BF, L"/>
+        <BoxCollisionShape position="-74,1,255" roll="20" halfExtents="18,19,82" info="body, BF, BottomL"/>
+        <BoxCollisionShape position="-66,-21,255" roll="-9" halfExtents="17,5,82" info="body, BF, BottomL"/>
+
+        <BoxCollisionShape position="0,106,381" halfExtents="36,5,71" info="body, BTop"/>
+        <BoxCollisionShape position="0,93,299" pitch="-49" halfExtents="34,5,20" info="body, BTop"/>
+        <BoxCollisionShape position="41,101,381" roll="-42" halfExtents="10,4,71" info="body, BTopR"/>
+        <BoxCollisionShape position="-41,101,381" roll="42" halfExtents="10,4,71" info="body, BTopL"/>
+
+        <BoxCollisionShape position="78,45,332" pitch="-10" roll="-10" yaw="20" halfExtents="10,20,30" info="body, back, R"/>
+        <BoxCollisionShape position="68,77,332" pitch="-10" roll="35" yaw="20" halfExtents="10,20,30" info="body, back, TR"/>
+        <BoxCollisionShape position="50,70,290" pitch="-10" roll="35" yaw="43" halfExtents="5,20,20" info="body, back, TR"/>
+        <BoxCollisionShape position="37,95,307" pitch="-10" roll="30" yaw="43" halfExtents="5,8,8" info="body, back, TR"/>
+        <BoxCollisionShape position="52,92,332" pitch="-10" yaw="30" halfExtents="10,5,30" info="body, back, TR"/>
+        <BoxCollisionShape position="88,4,322" halfExtents="10,24,30" info="body, back, RB"/>
+        <BoxCollisionShape position="54,-24,314" roll="35" pitch="-10" halfExtents="8,5,23" info="body, back, RB"/>
+        <BoxCollisionShape position="68,-19,346" pitch="-17" roll="8" halfExtents="16,4,11" info="body, back, bottomR"/>
+        <BoxCollisionShape position="-78,45,332" pitch="-10" roll="10" yaw="-20" halfExtents="10,20,30" info="body, back, L"/>
+        <BoxCollisionShape position="-68,77,332" pitch="-10" roll="-35" yaw="-20" halfExtents="10,20,30" info="body, back, TL"/>
+        <BoxCollisionShape position="-50,70,290" pitch="-10" roll="-35" yaw="-43" halfExtents="5,20,20" info="body, back, TL"/>
+        <BoxCollisionShape position="-37,95,307" pitch="-10" roll="-30" yaw="-43" halfExtents="5,8,8" info="body, back, TL"/>
+        <BoxCollisionShape position="-52,92,332" pitch="-10" yaw="-30" halfExtents="10,5,30" info="body, back, TL"/>
+        <BoxCollisionShape position="-88,4,322" halfExtents="10,24,30" info="body, back, LB"/>
+        <BoxCollisionShape position="-54,-24,314" roll="-35" pitch="-10" halfExtents="8,5,23" info="body, back, LB"/>
+        <BoxCollisionShape position="-68,-19,346" pitch="-17" roll="-8" halfExtents="16,4,11" info="body, back, bottomL"/>
+        <BoxCollisionShape position="0,-30,314" pitch="-8" halfExtents="52,4,23" info="body, back, bottom"/>
+        <BoxCollisionShape position="0,-22,346" pitch="-24" halfExtents="52,4,11" info="body, back, bottom"/>
+
+        <BoxCollisionShape position="48,-29,400" halfExtents="5,8,58" info="body, BBottomRBeam"/>
+        <BoxCollisionShape position="48,-29,451" halfExtents="10,13,14" info="body, BBottomRBeam"/>
+        <BoxCollisionShape position="-48,-29,400" halfExtents="5,8,58" info="body, BBottomLBeam"/>
+        <BoxCollisionShape position="-48,-31,451" halfExtents="10,13,14" info="body, BBottomLBeam"/>
+
+        <BoxCollisionShape position="103,60,420" halfExtents="18,9,64" info="body, back, Rextrusion"/>
+        <BoxCollisionShape position="-103,60,420" halfExtents="18,9,64" info="body, back, Lextrusion"/>
+        <BoxCollisionShape position="-85,7,417" halfExtents="10,21,67" info="body, back, LB"/>
+        <BoxCollisionShape position="85,7,417" halfExtents="10,21,67" info="body, back, RB"/>
+        <BoxCollisionShape position="0,-8,473" halfExtents="90,6,10" info="body, back, Bback"/>
+        <BoxCollisionShape position="0,-13,474" pitch="-23" halfExtents="76,5,8" info="body, back, Bback"/>
+        <BoxCollisionShape position="-79,-13,405" roll="-12" halfExtents="15,5,73" info="body, back, BL"/>
+        <BoxCollisionShape position="79,-13,405" roll="12" halfExtents="15,5,73" info="body, back, BR"/>
+        <BoxCollisionShape position="0,-15,410" halfExtents="66,6,58" info="body, back, B"/>
+
+        <BoxCollisionShape position="78,32,440" roll="-18" halfExtents="18,35,85" info="body, bay2, Rwall"/>
+        <BoxCollisionShape position="75,71,440" roll="35" halfExtents="18,27,85" info="body, bay2, Rwall"/>             
+        <BoxCollisionShape position="-78,32,440" roll="18" halfExtents="18,35,85" info="body, bay2, Lwall"/>
+        <BoxCollisionShape position="-75,71,440" roll="-35" halfExtents="18,27,85" info="body, bay2, Lwall"/>             
+        <BoxCollisionShape position="0,75,435" halfExtents="72,28,90" info="body, bay2, Twall"/>
+        <BoxCollisionShape position="0,35,423" halfExtents="85,35,5" info="body, bay2, Fwall"/> 
+        <BoxCollisionShape position="0,-3,465" halfExtents="84,5,60" info="body, bay2, BottomWall"/>
+        <BoxCollisionShape position="0,78,526" halfExtents="43,17,5" info="body, bay2, Twall"/> 
+        
+        
+        <BoxCollisionShape position="0,7,80" halfExtents="23,1,34" info="HOOKBOX at 0,18,80, bottom"/>
+        <BoxCollisionShape position="0,29,80" halfExtents="23,1,34" info="HOOKBOX, top"/>
+        <BoxCollisionShape position="-22,18,80" halfExtents="1,12,34" info="HOOKBOX, left long"/>
+        <BoxCollisionShape position="0,18,80" halfExtents="1,12,34" info="HOOKBOX, center long"/>
+        <BoxCollisionShape position="22,18,80" halfExtents="1,12,34" info="HOOKBOX, right long"/>
+        <BoxCollisionShape position="0,18,113" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        <BoxCollisionShape position="0,18,91" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        <BoxCollisionShape position="0,18,69" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        <BoxCollisionShape position="0,18,47" halfExtents="23,12,1" info="HOOKBOX, wide"/> 
+        
+<!-- Following the position of the other parts collisionboxes, used to attach them to the body --> 
+<!--         <BoxCollisionShape position="-11,18,102" halfExtents="10,10,10" info="sidearmL, HOOK"/>
+        <BoxCollisionShape position="11,18,102" halfExtents="10,10,10" info="sidearmR, HOOK"/>
+        <BoxCollisionShape position="-11,18,80" halfExtents="10,10,10" info="partL, HOOK"/>
+        <BoxCollisionShape position="11,18,80" halfExtents="10,10,10" info="partR, HOOK"/>
+        <BoxCollisionShape position="-11,18,58" halfExtents="10,10,10" info="frontL, HOOK"/>
+        <BoxCollisionShape position="11,18,58" halfExtents="10,10,10" info="frontR, HOOK"/> -->
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsHeavyCruiserBody.oxi")
+?>
+  </SpaceShip>
+
+</Template>
+
+
+
+
+<Template name=HeavyCruiser_cameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,200, 1000" drag=true mouselook=true />
+      <CameraPosition position="0,100, 1000" drag=true mouselook=true />
+      <CameraPosition position="0,150,600" drag=true mouselook=true />
+      <CameraPosition position="0,80,-300" drag=false mouselook=false />
+      <CameraPosition position="200,80,300" drag=false mouselook=false />
+      <CameraPosition position="0,1100,60" pitch="-90" drag=false mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+
+
+
+<Template name=HeavyCruiser_body_engine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  40
+   speedleftright =  40
+   speedupdown    =  40
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 8
+   accelerationback      =  4
+   accelerationleftright =  4
+   accelerationupdown    =  4
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-66,87,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-73,77,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-80,68,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.8 position="-86,58,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-82,46,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-80,34,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="-76,21,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.6 position="-71,9,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="66,87,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="73,77,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="80,68,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.8 position="86,58,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="82,46,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="80,34,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.7 position="76,21,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.6 position="71,9,525" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="66,87,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="73,77,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,68,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="86,58,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="82,46,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,34,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.4 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="76,21,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="71,9,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-66,87,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-73,77,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,68,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-86,58,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-82,46,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.5 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,34,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.4 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-76,21,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1.2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-71,9,525" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="85,58,525" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-85,58,525" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="66,87,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="73,77,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,68,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="86,58,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="82,46,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="80,34,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="76,21,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="71,9,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-66,87,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-73,77,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,68,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-86,58,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-82,46,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-80,34,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.7 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-76,21,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.6 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-71,9,525" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=0.5 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
+
+
+<Template name=HeavyCruiser_sidearmL_engine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 300
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 8
+   accelerationback      =  4
+   accelerationleftright =  4
+   accelerationupdown    =  4
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=1 position="-147,35,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position="-136,-5,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-147,35,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-136,-5,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-147,35,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-136,-5,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-148,35,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="-136,-5,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
+
+
+<Template name=HeavyCruiser_sidearmR_engine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 300
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 8
+   accelerationback      =  4
+   accelerationleftright =  4
+   accelerationupdown    =  4
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=1 position="147,35,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position="136,-5,308" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="147,35,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="136,-5,308" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="147,35,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="136,-5,308" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="147,35,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.6 name=bltest position="136,-5,308" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/MFalcon.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/MFalcon.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/MFalcon.oxt	(revision 11817)
@@ -0,0 +1,133 @@
+<Template name=MFalcon>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 10
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   shieldhealth        = 35
+   initialshieldhealth = 35
+   maxshieldhealth     = 60
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 80
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="MilleniumFalcon.mesh" />
+      <!-- <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" /> -->
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="explosionparts/escort_part_1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_3.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_4.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_5.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_6.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/MFalconWeapon.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,15, 60" drag=true mouselook=true />
+      <CameraPosition position="0,20, 90" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipescortengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+       />
+       <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" -6, 1.75, 11" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+	<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" -5, 1.75, 12" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+	<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" -3.75, 1.75, 13" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+	<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 0,1.75, 14" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="3.75, 1.75, 13" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+	<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 5, 1.75, 12" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+	<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 6, 1.75, 11" colour="0.2, 0.5, 0.65, 1.0" width=15 length=50 lifetime=100 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+     <!-- <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 /-->
+      <!-- <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 /-->
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <!-- <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=5 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" /-->
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="0, 2, 14" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+
+    <EffectContainer condition="boost">
+      <!-- <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" /-->
+       <Backlight mainstate=activity active=false scale=0.33 name=bltest position="0, 1, 14" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/ModularSpaceShipTest.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/ModularSpaceShipTest.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/ModularSpaceShipTest.oxt	(revision 11817)
@@ -0,0 +1,172 @@
+<Template name=ModularSpaceShipTest>
+  <ModularSpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 1000
+   maxhealth         = 2000
+   initialhealth     = 1000
+
+   shieldhealth        = 30
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+    
+        <Model position="0,0,0" mesh="crate.mesh" scale3D="6,6,6" />
+        
+        <StaticEntity name="one" position="0,60,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached>
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            </collisionShapes>
+        </StaticEntity>
+        
+        <StaticEntity name="two" position="0,0,62" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached>
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            </collisionShapes>
+        </StaticEntity>
+        
+        <StaticEntity name="two_2" position="0,0,124" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached>
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            </collisionShapes>
+        </StaticEntity>
+        
+        <StaticEntity name="three" position="0,-60,0" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached>
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            </collisionShapes>
+        </StaticEntity>
+        
+        <StaticEntity name="four" position="0,0,-59" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached>
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            </collisionShapes>
+        </StaticEntity>
+        
+        <StaticEntity name="four_2" position="0,0,-118" direction="0,0,0" collisionType=static mass=100 friction=0.01 >
+            <attached>
+                <Model position="0,0,0" mesh="cube.mesh" scale3D="30,30,30" />
+            </attached>
+            <collisionShapes>
+                <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+            </collisionShapes>
+        </StaticEntity>
+
+    </attached>
+    
+    <parts>
+        <ShipPart name="one" initialhealth="20" damageabsorption="1" />
+        <ShipPart name="two" initialhealth="20" damageabsorption="1" />
+        <ShipPart name="two_2" initialhealth="20" damageabsorption="1" />
+        <ShipPart name="three" initialhealth="20" damageabsorption="1" />
+        <ShipPart name="four" initialhealth="20" damageabsorption="1" />
+        <ShipPart name="four_2" initialhealth="20" damageabsorption="1" />
+    </parts>
+    
+    <collisionShapes>
+        <BoxCollisionShape position="0,0,0" halfExtents="30,30,30" />
+    </collisionShapes>
+
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsAssff.oxi")
+?>
+  </ModularSpaceShip>
+</Template>
+
+<Template name=spaceshipassffcameras defaults=0>
+  <ModularSpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+    </camerapositions>
+  </ModularSpaceShip>
+</Template>
+
+<Template name=spaceshipassffengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+   
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+
+    </EffectContainer>
+    <EffectContainer condition="boost">
+
+    </EffectContainer>
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/StoryMode.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/StoryMode.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/StoryMode.oxt	(revision 11817)
@@ -0,0 +1,5 @@
+<Template name=StoryMode>
+  <Pawn
+   hudtemplate            = StoryModeMap
+  />
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/StoryModeEscort.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/StoryModeEscort.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/StoryModeEscort.oxt	(revision 11817)
@@ -0,0 +1,128 @@
+<Template name=StoryModeEscort>
+  <StoryModePawn
+   hudtemplate            = StoryModeHUD2
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 10
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   shieldhealth        = 35
+   initialshieldhealth = 35
+   maxshieldhealth     = 60
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 80
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="escortShip.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" />
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="explosionparts/escort_part_1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_3.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_4.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_5.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_6.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsEscort.oxi")
+?>
+  </StoryModePawn>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <StoryModePawn>
+    <camerapositions>
+      <CameraPosition position="0, 500, 400" drag=true mouselook=false />
+      <CameraPosition position="0,20, 90" drag=true mouselook=false />
+      <CameraPosition position="0,30,120" drag=true mouselook=false />
+    </camerapositions>
+  </StoryModePawn>
+</Template>
+
+<Template name=spaceshipescortengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 0.5, 0.65, 1.0" width=150 length=15 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, -2, 14" colour="0.2, 0.5, 0.65, 1.0" width=15 length=15 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=5 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/asteroidsAsteroids2D.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/asteroidsAsteroids2D.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/asteroidsAsteroids2D.oxt	(revision 11817)
@@ -0,0 +1,62 @@
+<Template name = stone1>
+  <Asteroids2DStone
+    collisionType = dynamic
+    linearDamping = 0
+    angularDamping = 0
+    scale= 10
+    enablecollisiondamage = true
+
+    health            = 10
+    maxhealth         = 10
+    initialhealth     = 10
+  >
+    <attached>
+      <Model mass= 4000 mesh="ast1.mesh" />
+    </attached>
+    <collisionShapes>
+      <SphereCollisionShape radius="10" />
+    </collisionShapes>
+  </Asteroids2DStone>
+</Template>
+
+<Template name = stone2>
+  <Asteroids2DStone
+    collisionType = dynamic
+    linearDamping = 0
+    angularDamping = 0
+    scale= 20
+    enablecollisiondamage = true
+
+    health            = 10
+    maxhealth         = 10
+    initialhealth     = 10
+  >
+    <attached>
+      <Model mass= 8000 mesh="ast1.mesh" />
+    </attached>
+    <collisionShapes>
+      <SphereCollisionShape radius="20" />
+    </collisionShapes>
+  </Asteroids2DStone>
+</Template>
+
+<Template name = stone3>
+  <Asteroids2DStone
+    collisionType = dynamic
+    linearDamping = 0
+    angularDamping = 0
+    scale= 30
+    enablecollisiondamage = true
+
+    health            = 10
+    maxhealth         = 10
+    initialhealth     = 10
+  >
+    <attached>
+      <Model mass= 16000 mesh="ast1.mesh" />
+    </attached>
+    <collisionShapes>
+      <SphereCollisionShape radius="30" />
+    </collisionShapes>
+  </Asteroids2DStone>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/bigship.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/bigship.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/bigship.oxt	(revision 11817)
@@ -0,0 +1,158 @@
+<Template name=bigship>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = bigshipcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 100
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 30
+   auxilaryThrust    = 30
+   rotationThrust    = 10
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 30
+   boostPowerRate        = 1.5
+   boostRate             = 4
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 1000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 15, 0, 0" template=bigshipengine />
+      <MultiStateEngine position="-15, 0, 0" template=bigshipengine />
+    </engines>
+    <attached>
+
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsBody.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsDuseL.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsDuseR.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsKuppelV.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsKuppelK.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsAntL.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsAntR.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsGarage.mesh" />
+	<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=4 mesh="bsStation.mesh" />
+
+	<BlinkingBillboard position="2,-2.4,16" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=0 quadratic=1 />
+      	<BlinkingBillboard position="-2,-2.4,16" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=0 quadratic=1 />
+	<BlinkingBillboard position="2,-2.5,19" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=40 quadratic=1 />
+      	<BlinkingBillboard position="-2,-2.5,19" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=40 quadratic=1 />
+	<BlinkingBillboard position="2,-2.5,22" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=80 quadratic=0 />
+      	<BlinkingBillboard position="-2,-2.5,22" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=80 quadratic=0 />
+	<BlinkingBillboard position="2,-2.6,25" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=120 quadratic=0 />
+      	<BlinkingBillboard position="-2,-2.6,25" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=120 quadratic=0 />
+	<BlinkingBillboard position="2,-2.6,28" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=160 quadratic=0 />
+      	<BlinkingBillboard position="-2,-2.6,28" material="Examples/Flare" colour="0.3, 0.3, 1, 0.1" amplitude=0.02 frequency=0.4 phase=160 quadratic=0 />
+	<BlinkingBillboard position="2.9,-3.5,14.2" material="Examples/Flare" colour="1, 0.4, 0.4, 0.1" amplitude=0.02 frequency=30 phase=0 quadratic=0 />
+      	<BlinkingBillboard position="-2.9,-3.5,14.2" material="Examples/Flare" colour="1, 0.4, 0.4, 0.1" amplitude=0.02 frequency=30 phase=0 quadratic=0 />
+
+
+
+<!--	<Model position="0,8,17" yaw=0 pitch=180 roll=0 scale3D="8, 10, 10" mesh="cube.mesh" />
+	<Model position="0,0,22" yaw=0 pitch=180 roll=0 scale3D="18, 2, 10" mesh="cube.mesh" />
+	<Model position="0,0,9" yaw=0 pitch=180 roll=0 scale3D="12, 2, 20" mesh="cube.mesh" />
+	<Model position="0,0,-18" yaw=0 pitch=180 roll=0 scale3D="6, 2, 18" mesh="cube.mesh" />
+-->
+
+    </attached>
+    <collisionShapes>
+	<BoxCollisionShape position="0,8,17"      halfExtents="8,10,10" />
+	<BoxCollisionShape position="0,0,22"      halfExtents="18, 2, 10" />
+	<BoxCollisionShape position="0,0,9"      halfExtents="12, 2, 20" />
+	<BoxCollisionShape position="0,0,-18"      halfExtents="6, 2, 18" />
+      
+    </collisionShapes>
+
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsbigship.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=bigshipcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,30, 50" drag=true mouselook=true />
+      <CameraPosition position="0,10,80" drag=true mouselook=true />
+      <CameraPosition position="0,40,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=bigshipengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 10
+   accelerationbrake     = 10
+   accelerationback      =  10
+   accelerationleftright =  10
+   accelerationupdown    =  10
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 10.5, 0, 32" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-10.5, 0, 32" colour="0.2, 0.65, 1.0, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 2.5, 13, 26.5" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-2.5, 13, 26.5" colour="0.2, 0.65, 1, 0.4" width=5 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+ </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 10, 0, 32" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-10, 0, 32" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/endurancetest_template.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/endurancetest_template.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/endurancetest_template.oxt	(revision 11817)
@@ -0,0 +1,813 @@
+<Template name = endurance>
+
+    <!-- Spaceship parameters -->
+
+	<ModularSpaceShip 
+	name = endurance
+	collisionType= "dynamic" 
+	mass = 10000000 
+
+	health = 1000
+	initialhealth = 1000
+	maxhealth = 1000
+	
+	
+	
+	
+	rotationaxis = "1,0,0" 
+	
+	
+   	rotationrate = "5"
+   	>
+	
+   	<!-- Destructible parts -->
+
+   	<parts>
+
+   		<ShipPart name = "tunnelsystem" initialhealth="1000" maxhealth="1000" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "mistery1" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "mistery2" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+   		<ShipPart name = "EnduranceSmallShip1" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "EnduranceSmallShip2" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct12" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+         <ShipPart name = "ct11" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct10" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct9" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct8" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct7" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct6" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct5" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct4" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct3" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct2" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "ct1" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+    	<ShipPart name = "part1" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct12"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct11"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part2" initialhealth="10" maxhealth="10" damageabsorption="0.9" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct11"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct10"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part3" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct10"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct9"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part4" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct9"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct8"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part5" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct8"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct7"   operation="destroy" />  
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part6" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct7"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct6"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part7" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct6"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct5"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part8" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct5"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct4"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part9" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct4"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct3"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part10" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct3"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct2"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part11" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct2"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct1"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+        <ShipPart name = "part12" initialhealth="10" maxhealth="10" damageabsorption="0.5" explosionposition="0,0,0">
+            <destructionevents>
+                <PartDestructionEvent targetType="ship"  operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct1"   operation="destroy" />
+                <PartDestructionEvent targetType="part" targetName ="ct12"   operation="destroy" />
+            </destructionevents>
+        </ShipPart>
+
+    </parts>
+
+    <!-- Explosion effects -->
+
+    <explosion >
+
+
+      <ExplosionPart scale = 5 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart scale = 5 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart scale = 5 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+      <ExplosionPart offset="94,33,-50" delay=1 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart offset="94,33,-50" delay=1 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart offset="94,33,-50" delay=1 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+ 
+      <ExplosionPart scale = 2.5 mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart scale = 2.5 mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart delay=0.8 scale = 2.5 mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart delay=0.8 scale = 2.5 mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart delay=0.8 scale = 2.5 mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart delay=0.8 scale = 2.5 mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+     
+      <ExplosionPart offset="20,13,-15" delay=1.3 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart offset="30,13,-15" delay=1.3 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart offset="20,13,-15" delay=1.3 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+      <ExplosionPart offset="-20,-13,-15" delay=1.8 minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart offset="-20,-13,-15" delay=1.8 minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart offset="-20,-13,-15" delay=1.8 minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+    </explosion>
+
+
+    <attached>
+
+
+
+
+        <Model  mesh="Endurance_Tunnelsystem.mesh" scale="66" lookat="0,0,0" pitch="-30" yaw="0" roll="90" />
+
+
+		<!-- coordinates (0,0,0) element 0-->
+        
+		<!-- Small-Ship 1/2 -->
+
+		<StaticEntity  name = "EnduranceSmallShip1" collisionType=static position ="21,14.4,-9.6"  pitch="60" yaw="0" roll="90" >
+			<attached>
+				<Model  mesh="Endurance_Small_Ship.mesh" scale="36" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,-25,2.5" halfExtents="15,30,1" />
+			<BoxCollisionShape  position ="0,5,-7" halfExtents="7,7,7" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- Small-Ship 1/2 -->
+
+		<StaticEntity  name = "EnduranceSmallShip2" collisionType=static position ="21,-14.4,9.6"  pitch="-120" yaw="0" roll="90" >
+			<attached>
+				<Model  mesh="Endurance_Small_Ship.mesh" scale="36" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,-25,2.5" halfExtents="15,30,1" />
+			<BoxCollisionShape  position ="3,5,-7" halfExtents="7,7,7" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- Tunnelsystem -->
+
+		<StaticEntity  name = "tunnelsystem"collisionType=static position ="0,0,0" lookat="0,0,0" pitch="-30" yaw="0" roll="90" >
+			<attached>
+				<Model  mesh="Endurance_Tunnelsystem.mesh" scale="66" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position = "30,0,0" halfExtents="65,9,9" />
+			<BoxCollisionShape  position = "0,40,0" halfExtents="8,30,8" />
+			<BoxCollisionShape  position = "0,-20,0" halfExtents="7,12,7" />
+			<BoxCollisionShape  position = "0,0,18" halfExtents="8,8,12" />
+			<BoxCollisionShape  position = "0,0,-18" halfExtents="8,8,12" />
+			<BoxCollisionShape  position = "-39,0,0" halfExtents="5,5,7" />
+			
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct12 -->
+
+		<StaticEntity name ="ct12" collisionType=static position ="0,-30,105"  yaw="0" roll="90" pitch="-60" >
+			<attached>
+		
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- 2 Mistery elements --> 
+
+		<StaticEntity name = "mistery1" collisionType=static position ="0,-6,-9.6"  yaw="0" roll="90" pitch="-30" >
+			<attached>
+		
+				<Model  mesh="Endurance_Mystery.mesh" scale="48" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape position ="0,0,-28" halfExtents="25,32,8" />
+			<BoxCollisionShape position ="0,-30,-28" halfExtents="25,8,8" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<StaticEntity name = "mistery2" collisionType=static position ="0,3.6,7.2"  yaw="0" roll="90" pitch="150" >
+			<attached>
+		
+				<Model  mesh="Endurance_Mystery.mesh" scale="48" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape position ="0,0,-28" halfExtents="25,32,8" />
+			<BoxCollisionShape position ="0,-30,-28" halfExtents="25,8,8" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (100,0,0) element 1-->
+
+		<StaticEntity name= "part1" collisionType=static lookat="0,0,0" position ="0,0,120" direction="0,0,0" yaw="-90" roll="-90" pitch="0">
+
+			<attached>
+				<Model  mesh="Endurance_MainEngine.mesh" scale="5" />
+				
+		
+				<ParticleEmitter scale=5  position= "0,-5,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,3,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,10,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,-5" halfExtents="14,22,30"  />
+
+			</collisionShapes>	
+
+		</StaticEntity>
+
+
+		<!-- ct11 -->
+
+		<StaticEntity name = "ct11" collisionType=static position ="0,30,105"  yaw="0" roll="90" pitch="270" >
+			<attached>
+	
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (86,50,0) element 2 -->
+
+		<StaticEntity name = "part2" collisionType=static lookat="0,0,0" position ="0,60,103.2" direction="0,0,0" yaw="0" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_Habitat.mesh" scale="5" />
+				
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,3" halfExtents="14,24,26"  />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct10 -->
+
+		<StaticEntity name ="ct10" collisionType=static position ="0,78,78"  yaw="0" roll="90" pitch="240" >
+			<attached>
+		
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (50,86,0) element 3 -->	
+
+		<StaticEntity name="part3" collisionType=static lookat="0,0,0" position ="0,103.2,60" direction="0,0,0" yaw="-90" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_MainEngine.mesh" scale="5" />
+
+				<ParticleEmitter scale=5  position= "0,-5,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,3,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,10,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,-5" halfExtents="14,22,30" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct9 -->
+
+		<StaticEntity name ="ct9" collisionType=static position ="0,105,30"  yaw="0" roll="90" pitch="210" >
+			<attached>
+		
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (0,100,0) element 4 -->	
+
+		<StaticEntity name ="part4" collisionType=static position ="0,120,0" lookat="0,0,0" yaw="0" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_Landig_Module.mesh" scale="5" />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,3" halfExtents="14,25,26" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct8 -->
+
+		<StaticEntity name ="ct8" collisionType=static position ="0,105,-30"  yaw="0" roll="90" pitch="180" >
+			<attached>
+			
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (-50,86,0) element 5 -->	
+
+		<StaticEntity name= "part5" collisionType=static position ="0,103.2,-60" lookat="0,0,0" direction="0,0,0" yaw="0" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_Habitat.mesh" scale="5" />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,3" halfExtents="14,25,26" />
+
+			</collisionShapes>
+
+
+		</StaticEntity>
+
+		<!-- ct7 -->
+
+		<StaticEntity name ="ct7"  collisionType=static position ="0,78,-78"  yaw="0" roll="90" pitch="150" >
+			<attached>
+		
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+		
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (-86,50,0) element 6  -->	
+
+		<StaticEntity name="part6" collisionType=static position ="0,60,-103.2" lookat="0,0,0" yaw="0" roll="-90" >
+			<attached>
+				<Model  mesh="Endurance_Landig_Module.mesh" scale="5" />
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,3" halfExtents="14,25,26" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct6 -->
+
+		<StaticEntity name ="ct6" collisionType=static position ="0,30,-105"  yaw="0" roll="90" pitch="120" >
+			<attached>
+				
+
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+			
+				
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (-100,0,0) element 7 -->	
+
+		<StaticEntity name= "part7" collisionType=static position ="0,0,-120" lookat="0,0,0" direction="0,0,0" yaw="90" roll="90">
+			<attached>
+				<Model  mesh="Endurance_MainEngine.mesh" scale="5" />
+
+				<ParticleEmitter scale=5  position= "0,-5,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,3,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,10,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,-5" halfExtents="14,22,30" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct5 -->
+
+		<StaticEntity name ="ct5" collisionType=static position ="0,-30,-105"  yaw="0" roll="90" pitch="90" >
+			<attached>
+				
+
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+				
+				
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+
+		<!-- coordinates (-86,-50,0) element 8 -->	
+
+		<StaticEntity name ="part8" collisionType=static position ="0,-60,-103.2" lookat="0,0,0" direction="0,0,0" yaw="0" roll="-90" >
+			<attached>
+				<Model  mesh="Endurance_Habitat.mesh" scale="5" />
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,2" halfExtents="14,25,26" />
+
+			</collisionShapes>
+
+
+		</StaticEntity>
+
+		<!-- ct4 -->
+
+		<StaticEntity name ="ct4" collisionType=static position ="0,-78,-78"  yaw="0" roll="90" pitch="60" >
+			<attached>
+				
+
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+				
+				
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (-50,-86,0) element 9 -->	
+
+		<StaticEntity name="part9" collisionType=static position ="0,-103.2,-60" lookat="0,0,0" direction="0,0,0" yaw="-90" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_MainEngine.mesh" scale="5" />
+
+				<ParticleEmitter scale=5  position= "0,-5,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,3,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+				<ParticleEmitter scale=5  position= "0,10,28" source="Orxonox/thruster2" lifetime=2.0 loop=1 startdelay=0.0 />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,-5" halfExtents="14,22,30" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct3 -->
+
+		<StaticEntity name ="ct3" collisionType=static position ="0,-105,-30"  yaw="0" roll="90" pitch="30" >
+			<attached>
+				
+
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+				
+				
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (0,-100,0) element 10 -->	
+
+		<StaticEntity name ="part10" collisionType=static position ="0,-120,0" lookat="0,0,0" yaw="0" roll="-90">
+			<attached>
+				
+				<Model  mesh="Endurance_Landig_Module.mesh" scale="5" />
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,2" halfExtents="14,25,26" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- ct2 -->
+
+		<StaticEntity name ="ct2" collisionType=static position ="0,-105,30"  yaw="0" roll="90" pitch="0" >
+			<attached>
+				
+
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+			
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (50,-86,0) element 11 -->	
+
+		<StaticEntity name ="part11" collisionType=static position ="0,-103.2,60" lookat="0,0,0" yaw="0" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_Commando_Module.mesh" scale="5" />
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,3" halfExtents="14,25,27" />
+			<BoxCollisionShape  position ="0,30,-20" halfExtents="15,5,6" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- connecting tunnel 1 (ct1) -->
+
+		<StaticEntity name ="ct1" collisionType=static position ="0,-78,78"  yaw="0" roll="90" pitch="-30" >
+			<attached>
+	
+				<Model  mesh="Endurance_Connecting_Tunnel.mesh" scale="6" />
+	
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  halfExtents="8,8,10" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		<!-- coordinates (86,-50,0) element 12 -->	
+
+		<StaticEntity name ="part12" collisionType=static position ="0,-60,103.2" lookat="0,0,0" yaw="0" roll="-90">
+			<attached>
+				<Model  mesh="Endurance_Landig_Module.mesh" scale="5" />
+				
+
+			</attached>
+
+			<collisionShapes>
+
+			<BoxCollisionShape  position ="0,0,3" halfExtents="14,25,27" />
+
+			</collisionShapes>
+
+		</StaticEntity>
+
+		
+	</attached>
+
+	
+
+	</ModularSpaceShip>
+
+</Template>
+
+
+
+
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/enemyFlappyOrx.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/enemyFlappyOrx.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/enemyFlappyOrx.oxt	(revision 11817)
@@ -0,0 +1,174 @@
+<Template name=enemyFlappyOrx>
+  <FlappyOrxEnemy
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 10
+   maxhealth         = 10
+   initialhealth     = 10
+
+   shieldhealth        = 10
+   initialshieldhealth = 10
+   maxshieldhealth     = 10
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 0.00001
+   linearDamping     = 0
+   angularDamping    = 0
+
+    collisiondamage = 100
+    enablecollisiondamage = true
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="swallow_mat.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="escortWeapon.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/FlappyOrxWeapon.oxi")
+?>
+  </FlappyOrxEnemy>
+</Template>
+
+<Template name=enemyFlappyOrxshooter>
+  <FlappyOrxEnemyShooter
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 20
+   maxhealth         = 20
+   initialhealth     = 20
+
+   shieldhealth        = 20
+   initialshieldhealth = 20
+   maxshieldhealth     = 20
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0
+   angularDamping    = 0
+
+    collisiondamage = 100
+    enablecollisiondamage = true
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="ghost.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="escortWeapon.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+<?lua
+  include("../includes/FlappyOrxWeaponEnemy.oxi")
+?>
+  </FlappyOrxEnemyShooter>
+</Template>
+
+<Template name=spaceshipescortengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/enemyInvader.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/enemyInvader.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/enemyInvader.oxt	(revision 11817)
@@ -0,0 +1,174 @@
+<Template name=enemyinvader>
+  <InvaderEnemy
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 10
+   maxhealth         = 10
+   initialhealth     = 10
+
+   shieldhealth        = 10
+   initialshieldhealth = 10
+   maxshieldhealth     = 10
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 0.00001
+   linearDamping     = 0
+   angularDamping    = 0
+
+    collisiondamage = 100
+    enablecollisiondamage = true
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="swallow_mat.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="escortWeapon.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/invaderWeapon.oxi")
+?>
+  </InvaderEnemy>
+</Template>
+
+<Template name=enemyinvadershooter>
+  <InvaderEnemyShooter
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 20
+   maxhealth         = 20
+   initialhealth     = 20
+
+   shieldhealth        = 20
+   initialshieldhealth = 20
+   maxshieldhealth     = 20
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0
+   angularDamping    = 0
+
+    collisiondamage = 100
+    enablecollisiondamage = true
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="ghost.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=270 roll=0 scale=2 mesh="escortWeapon.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+<?lua
+  include("../includes/invaderWeaponEnemy.oxi")
+?>
+  </InvaderEnemyShooter>
+</Template>
+
+<Template name=spaceshipescortengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/fastship.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/fastship.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/fastship.oxt	(revision 11817)
@@ -0,0 +1,129 @@
+<Template name=fastship>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+
+   health            = 150
+   maxhealth         = 200
+   initialhealth     = 150
+
+   shieldhealth        = 70
+   initialshieldhealth = 50
+   maxshieldhealth     = 100
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 2000
+   auxilaryThrust    = 1000
+   rotationThrust    = 50
+
+   lift = 0;
+   stallSpeed = 220;
+
+
+   boostPower            = 8
+   boostPowerRate        = 3
+   boostRate             = 8
+   boostCooldownDuration = 6
+
+   shakeFrequency = 50
+   shakeAmplitude = 30
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsAssff.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+  boostfactor    = 4
+
+   speedfront     =  3000
+   speedback      =  1500
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+   
+   accelerationfront     = 400
+   accelerationbrake     = 300
+   accelerationback      = 125
+   accelerationleftright = 125
+   accelerationupdown    = 125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/lodInformation.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/lodInformation.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/lodInformation.oxt	(revision 11817)
@@ -0,0 +1,49 @@
+<Template name=lodtemplate_default defaults=false>
+  <Level>
+    <lodinformation>
+      <MeshLodInformation mesh=Carrier.mesh lodQuality=1.8 />
+      <MeshLodInformation mesh=assff.mesh lodQuality=3 />
+      <MeshLodInformation mesh=rocket.mesh lodQuality=5 enabled=true />
+      <MeshLodInformation mesh=laserbeam.mesh enabled=false />
+      <MeshLodInformation mesh=HXY.mesh enabled=true numLevels=8 />
+      <MeshLodInformation mesh=Transporter.mesh enabled=true numLevels=8 />
+      <MeshLodInformation mesh=CuboidConnBody.mesh enabled=false/>
+      <MeshLodInformation mesh=CuboidBody.mesh enabled=false/>
+      <MeshLodInformation mesh=DoubleCuboidBody.mesh enabled=false/>
+      <MeshLodInformation mesh=SemiCircleCockpit.mesh enabled=false/>
+      <MeshLodInformation mesh=SolarPanel.mesh enabled=false/>
+      <MeshLodInformation mesh=CuboidLandingZone.mesh enabled=false/>
+      <MeshLodInformation mesh=HydroHarvester.mesh enabled=false />
+      <MeshLodInformation mesh=turretHead.mesh enabled=false />
+      <MeshLodInformation mesh=LaserBeam2.mesh enabled=false/>
+      <MeshLodInformation mesh=asteroid_ice.mesh enabled=false/>
+      <MeshLodInformation mesh=ast1.mesh  lodQuality=0.1/>
+      <MeshLodInformation mesh=ast2.mesh  lodQuality=0.1/>
+      <MeshLodInformation mesh=ast3.mesh  lodQuality=0.1/>
+      <MeshLodInformation mesh=ast4.mesh  lodQuality=0.1/>
+      <MeshLodInformation mesh=ast5.mesh  lodQuality=0.1/>
+      <MeshLodInformation mesh=ast6.mesh  lodQuality=0.1/>
+
+      <!-- disable LOD for some debris meshes which caused a crash (fixed in Ogre 1.7.3) -->
+      <MeshLodInformation mesh=BodyDebris1.mesh enabled=false/>
+      <MeshLodInformation mesh=WingDebris2.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_body.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_frontL.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_frontR.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_partL.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_partR.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_sidearmL.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_sidearmLfront.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_sidearmR.mesh enabled=false/>
+      <MeshLodInformation mesh=HeavyCruiser_sidearmRfront.mesh enabled=false/>
+
+	  <MeshLodInformation mesh=ss_cylinder.mesh enabled=false/>
+	  <MeshLodInformation mesh=ss_chair.mesh enabled=false/>
+	  <MeshLodInformation mesh=ss_flag_room.mesh enabled=false/>
+	  <MeshLodInformation mesh=ss_wall.mesh enabled=false/>
+	  <MeshLodInformation mesh=ss_tube_twd.mesh enabled=false/>
+	  <MeshLodInformation mesh=ss_spind.mesh enabled=false/>
+	  
+    </lodinformation>
+  </Level>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/orbStation.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/orbStation.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/orbStation.oxt	(revision 11817)
@@ -0,0 +1,64 @@
+<Template name=orbStation>
+  <MovableEntity>
+    <attached>
+      
+
+      <MovableEntity rotationaxis = "0,1,0" rotationrate="50,0,0">
+        <attached>
+          <Model position=“0,0,0“ yaw = 0 mesh="OrbStation_Sphere.mesh" scale="40"/>
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity rotationaxis = "1,1,1" rotationrate="50,0,0">
+        <attached>
+          <Model position=“0,0,0“ mesh="OrbStation_Ring_2.mesh" scale="40" />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity rotationaxis = "1,1,-1" rotationrate="50,0,0">
+        <attached>
+           <Model position=“0,0,0“ mesh="OrbStation_Ring_3.mesh" scale="40" />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity rotationaxis = "-1,1,1" rotationrate="50,0,0">
+        <attached>
+          <Model position=“0,0,0“ mesh="OrbStation_Ring_4.mesh" scale="40" />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity rotationaxis = "-1,1,-1" rotationrate="50,0,0">
+        <attached>
+          <Model position=“0,0,0“ mesh="OrbStation_Ring_5.mesh" scale="40"/>
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity rotationaxis = "0,1,0" rotationrate="1,0,0">
+        <attached>
+          
+          
+          <Model position=“0,0,0“ mesh="OrbStation_Ring_1.mesh" scale="40" />
+
+          <Model position= "180,0,0" yaw = 0 mesh="OrbStation_Platform.mesh" scale="40"/>
+          <Model position= "0,0,180" yaw = -90 mesh="OrbStation_Platform.mesh" scale="40"/>
+          <Model position= "0,0,-180" yaw = -90 mesh="OrbStation_OpenPlat.mesh" scale="40"/>
+          
+          <Model position= "-200,0,0" yaw = 90 mesh="OrbStation_Antenna.mesh" scale="40"/>          
+          <MovableEntity position= "-305,0,0" rotationaxis = "1,0,0" rotationrate="50,0,0">
+            <attached>
+              <Model position= "0,0,0" yaw = 90 mesh="OrbStation_Parabola.mesh" scale="40"/>
+            </attached>
+          </MovableEntity>
+          
+
+        </attached>
+      </MovableEntity>
+
+
+      <Backlight position="0,0,0" scale=10 colour="0.2, 0.4, 0.8" width=100 length=500 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" loop=1 />
+
+    </attached>
+  </MovableEntity>
+</Template>
+  
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/pickupRepresentationTemplates.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/pickupRepresentationTemplates.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/pickupRepresentationTemplates.oxt	(revision 11817)
@@ -0,0 +1,885 @@
+<!-- Boost pickups: -->
+
+<Template name=smallboostpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.0,1.0,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.0,1.0,0.8" material="Flash" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallboostpickup baseclass=BoostPickup>
+  <BoostPickup
+    representation = "smallboostpickup"
+    boostrefill = 0.5
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<Template name=mediumboostpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.0,1.0,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.0,1.0,0.8" material="Flash" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediumboostpickup baseclass=BoostPickup>
+  <BoostPickup
+    representation = "mediumboostpickup"
+    boostrefill = 0.75
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<Template name=hugeboostpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.0,1.0,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.0,1.0,0.8" material="Flash" scale=0.7 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugeboostpickup baseclass=BoostPickup>
+  <BoostPickup
+    representation = "hugeboostpickup"
+    boostrefill = 1.0
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<!-- Shield pickups: -->
+
+<Template name=smallshieldpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="1,1,1" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1,1,1" material="Shield" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallshieldpickup baseclass=ShieldPickup>
+  <ShieldPickup
+    representation = "smallshieldpickup"
+    duration = 10
+    shieldabsorption = 0.7
+    shieldhealth = 300
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=mediumshieldpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="1,1,1" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1,1,1" material="Shield" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediumshieldpickup baseclass=ShieldPickup>
+  <ShieldPickup
+    representation = "mediumshieldpickup"
+    duration = 30
+    shieldabsorption = 0.8
+    shieldhealth = 500
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+
+<Template name=hugeshieldpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="1,1,1" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1,1,1" material="Shield" scale=0.7 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugeshieldpickup baseclass=ShieldPickup>
+  <ShieldPickup
+    representation = "hugeshieldpickup"
+    duration = 60
+    shieldabsorption = 0.95
+    shieldhealth = 700
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<!-- Health pickups: -->
+
+<Template name=smallhealthpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.50,0.90,0.25" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.36,0.81,0.10" material="Cross" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallhealthpickup baseclass=HealthPickup>
+  <HealthPickup
+    representation = "smallhealthpickup"
+    health = 10
+    healthType = "limited"
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<Template name=mediumhealthpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.50,0.90,0.25" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.36,0.81,0.10" material="Cross" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediumhealthpickup baseclass=HealthPickup>
+  <HealthPickup
+    representation = "mediumhealthpickup"
+    health = 50
+    healthType = "limited"
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<Template name=hugehealthpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.50,0.90,0.25" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.36,0.81,0.10" material="Cross" scale=0.7 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugehealthpickup baseclass=HealthPickup>
+  <HealthPickup
+    representation = "hugehealthpickup"
+    health = 100
+    healthType = "limited"
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<Template name=crazyhealthpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.50,0.90,0.25" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.36,0.81,0.10" material="Cross" scale=1.2 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=crazyhealthpickup baseclass=HealthPickup>
+  <HealthPickup
+    representation = "crazyhealthpickup"
+    health = 1000
+    healthType = "permanent"
+    activationType = "immediate"
+    durationType = "once"
+  />
+</Template>
+
+<!-- Munition pickups: -->
+
+<Template name=smallmunitionpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.59,0.30,0.16" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.47,0.24,0.13" material="Munition" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallmunitionpickup baseclass=MunitionPickup>
+  <MunitionPickup
+    representation = "smallmunitionpickup"
+    activationType = "immediate"
+    durationType = "once"
+  >
+    <munitioncontainers>
+        <MunitionContainer munitiontype="LaserMunition" munitionamount=16 magazinesamount=0 />
+        <MunitionContainer munitiontype="FusionMunition" munitionamount=8 magazinesamount=0 />
+        <MunitionContainer munitiontype="LightningMunition" munitionamount=8 magazinesamount=0 />
+    </munitioncontainers>
+  </MunitionPickup>
+</Template>
+
+<Template name=mediummunitionpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.59,0.30,0.16" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.47,0.24,0.13" material="Munition" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediummunitionpickup baseclass=MunitionPickup>
+  <MunitionPickup
+    representation = "mediummunitionpickup"
+    activationType = "immediate"
+    durationType = "once"
+  >
+    <munitioncontainers>
+        <MunitionContainer munitiontype="LaserMunition" munitionamount=32 magazinesamount=0 />
+        <MunitionContainer munitiontype="FusionMunition" munitionamount=16 magazinesamount=0 />
+        <MunitionContainer munitiontype="LightningMunition" munitionamount=16 magazinesamount=0 />        
+        <MunitionContainer munitiontype="SplitMunition" munitionamount=8 magazinesamount=0 />
+        <MunitionContainer munitiontype="RocketMunition" munitionamount=0 magazinesamount=2 />
+        <MunitionContainer munitiontype="MineMunition" munitionamount=0 magazinesamount=2 />
+    </munitioncontainers>
+  </MunitionPickup>
+</Template>
+
+<Template name=hugemunitionpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.59,0.30,0.16" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.47,0.24,0.13" material="Munition" scale=0.7 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugemunitionpickup baseclass=MunitionPickup>
+  <MunitionPickup
+    representation = "hugemunitionpickup"
+    activationType = "immediate"
+    durationType = "once"
+  >
+    <munitioncontainers>
+        <MunitionContainer munitiontype="LaserMunition" munitionamount=64 magazinesamount=0 />
+        <MunitionContainer munitiontype="FusionMunition" munitionamount=32 magazinesamount=0 />
+        <MunitionContainer munitiontype="LightningMunition" munitionamount=32 magazinesamount=0 />        
+        <MunitionContainer munitiontype="SplitMunition" munitionamount=16 magazinesamount=0 />
+        <MunitionContainer munitiontype="RocketMunition" munitionamount=0 magazinesamount=10 />
+        <MunitionContainer munitiontype="IceMunition" munitionamount=0 magazinesamount=10 />
+        <MunitionContainer munitiontype="FlameMunition" munitionamount=0 magazinesamount=10 />
+        <MunitionContainer munitiontype="GravityBombMunition" munitionamount=0 magazinesamount=10 />
+        <MunitionContainer munitiontype="MineMunition" munitionamount=0 magazinesamount=10 />
+    </munitioncontainers>
+  </MunitionPickup>
+</Template>
+
+<!-- Meta pickups: -->
+
+<Template name=usepickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="ArrowUp" scale=0.65 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=usemetapickup baseclass=MetaPickup>
+  <MetaPickup representation="use" metaType="use" />
+</Template>
+
+<Template name=droppickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="ArrowDown" scale=0.65 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=dropmetapickup baseclass=MetaPickup>
+  <MetaPickup representation="drop" metaType="drop" />
+</Template>
+
+<Template name=destroypickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="Splash" scale=0.65 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=destroymetapickup baseclass=MetaPickup>
+  <MetaPickup representation="destroy" metaType="destroy" />
+</Template>
+
+<Template name=destroycarrierpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.6,0.⁰,0.8" material="Asterisk" scale=0.65 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=destroycarriermetapickup baseclass=MetaPickup>
+  <MetaPickup representation="destroycarrier" metaType="destroyCarrier" />
+</Template>
+
+<!-- DamageBoost pickups -->
+
+<Template name=smalldamageboostpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.95,0.10,0.05" material="Sphere2" scale=0.1 >
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.70,0.10,0.10" material="Damage" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smalldamageboostpickup baseclass=DamageBoostPickup>
+  <DamageBoostPickup
+    representation = "smalldamageboostpickup"
+    duration = 10.0
+    damageMultiplier = 2.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=mediumdamageboostpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.95,0.10,0.05" material="Sphere2" scale=0.1 >
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.70,0.10,0.10" material="Damage" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediumdamageboostpickup baseclass=DamageBoostPickup>
+  <DamageBoostPickup
+    representation = "mediumdamageboostpickup"
+    duration = 10.0
+    damageMultiplier = 5.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=hugedamageboostpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.95,0.10,0.05" material="Sphere2" scale=0.1 >
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.70,0.10,0.10" material="Damage" scale=0.7 />                            
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugedamageboostpickup baseclass=DamageBoostPickup>
+  <DamageBoostPickup
+    representation = "hugedamageboostpickup"
+    duration = 10.0
+    damageMultiplier = 7.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+
+<!-- Speed pickups -->
+
+<Template name=smallspeedpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.99,0.96,0.52" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.98,0.94,0.22" material="3arrowsup" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallspeedpickup baseclass=SpeedPickup>
+  <SpeedPickup
+    representation = "smallspeedpickup"
+    duration = 10.0
+    speedAdd = 0.0
+    SpeedMultiply = 10.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=mediumspeedpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.99,0.96,0.52" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.98,0.94,0.22" material="3arrowsup" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediumspeedpickup baseclass=SpeedPickup>
+  <SpeedPickup
+    representation = "mediumspeedpickup"
+    duration = 10.0
+    speedAdd = 0.0
+    SpeedMultiply = 25.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=hugespeedpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.99,0.96,0.52" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.98,0.94,0.22" material="3arrowsup" scale=0.7 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugespeedpickup baseclass=SpeedPickup>
+  <SpeedPickup
+    representation = "hugespeedpickup"
+    duration = 10.0
+    speedAdd = 0.0
+    SpeedMultiply = 50.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=smalljumppickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.99,0.96,0.52" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1,0,0" material="3arrowsup" scale=0.3 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smalljumppickup baseclass=SpeedPickup>
+  <SpeedPickup
+    representation = "smalljumppickup"
+    duration = 0.7
+    speedAdd = 5000.0
+    SpeedMultiply = 1.0
+    activationType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<!-- Invisible pickups -->
+
+<Template name=smallinvisiblepickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.22,0.32,0.86" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.06,0.14,0.63" material="Eye" scale=0.5 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallinvisiblepickup baseclass=InvisiblePickup>
+  <InvisiblePickup 
+    representation = "smallinvisiblepickup"
+    duration = 5.0
+    activaionType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=mediuminvisiblepickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.22,0.32,0.86" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.06,0.14,0.63" material="Eye" scale=0.7 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediuminvisiblepickup baseclass=InvisiblePickup>
+  <InvisiblePickup 
+    representation = "mediuminvisiblepickup"
+    duration = 10.0
+    activaionType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=hugeinvisiblepickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.22,0.32,0.86" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="0.06,0.14,0.63" material="Eye" scale=0.9 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugeinvisiblepickup baseclass=InvisiblePickup>
+  <InvisiblePickup 
+    representation = "hugeinvisiblepickup"
+    duration = 20.0
+    activaionType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=smallshrinkpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="1.0,0.55,1.0" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1.0,0.55,1.0" material="Shrink" scale=0.35 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=smallshrinkpickup baseclass=ShrinkPickup>
+  <ShrinkPickup 
+    representation = "smallshrinkpickup"
+    duration = 10.0
+    shrinkFactor = 2.5
+    activaionType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=mediumshrinkpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="1.0,0.55,1.0" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1.0,0.55,1.0" material="Shrink" scale=0.55 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=mediumshrinkpickup baseclass=ShrinkPickup>
+  <ShrinkPickup 
+    representation = "mediumshrinkpickup"
+    duration = 30.0
+    shrinkFactor = 5.0
+    activaionType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<Template name=hugeshrinkpickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="1.0,0.55,1.0" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,0,0" colour="1.0,0.55,1.0" material="Shrink" scale=0.75 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=hugeshrinkpickup baseclass=ShrinkPickup>
+  <ShrinkPickup 
+    representation = "hugeshrinkpickup"
+    duration = 60.0
+    shrinkFactor = 10.0
+    activaionType = "immediate"
+    durationType = "continuous"
+  />
+</Template>
+
+<!-- Pickup Collection pickups -->
+
+<Template name=triplehealthspeedinvisibilitypickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.95,0.85,0.27" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Billboard position="0,20,0" colour="0.36,0.81,0.10" material="Cross" scale=0.25 />
+                            <Billboard position="-20,-10,0" colour="0.98,0.94,0.22" material="3arrowsup" scale=0.25 />
+                            <Billboard position="20,-10,0" colour="0.06,0.14,0.63" material="Eye" scale=0.35 />
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=triplehealthspeedinvisibilitypickup baseclass=PickupCollection>
+    <PickupCollection
+        representation = "triplehealthspeedinvisibilitypickup"
+    >
+        <pickupables>
+            <HealthPickup template=mediumhealthpickup />
+            <SpeedPickup template=mediumspeedpickup />
+            <InvisiblePickup template=mediuminvisiblepickup />
+        </pickupables>
+    </PickupCollection>
+</Template>
+
+<!-- Drone Pickup -->
+
+<Template name=droneTemplate>
+    <Drone name="Drone"  mass= "50" linearDamping = "0.7" angularDamping = "0.99999" maxDistanceToOwner_=150 minDistanceToOwner_=75 maxShootingRange_=1000 primaryThrust_=250 auxilaryThrust_=250 rotationThrust_=50>
+        <attached>
+            <Model scale="1" mesh="drone.mesh"/>
+        </attached>
+        <collisionShapes>
+            <SphereCollisionShape position="0,0,0" radius=5 />
+        </collisionShapes>
+        <weaponslots>
+            <WeaponSlot position="0,0,0" />
+        </weaponslots>
+        <weaponsets>
+            <WeaponSet firemode=0 />
+        </weaponsets>
+        <weaponpacks>
+            <WeaponPack>
+                <links>
+                    <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+                </links>
+                <Weapon>
+                    <attached>
+                        <Model mesh="hs-w01.mesh" roll="195" position="0,1,0" scale=2 />
+                        <Model mesh="hs-w01s.mesh" roll="195" position="0.1,0.5,0" scale=2 />
+                    </attached>
+                    <HsW01 mode=0 munitionpershot=0 delay=0.125 damage=1.5708 material="Flares/point_lensflare" muzzleoffset=" 0.7, 1.5,-4" />
+                    <HsW01 mode=0 munitionpershot=0 delay=0     damage=1.5708 material="Flares/point_lensflare" muzzleoffset="-0.9, 1.1,-4" />
+                </Weapon>
+            </WeaponPack>
+        </weaponpacks>
+        <munition>
+            <LaserMunition initialmagazines=2 maxmagazines=2 munitionpermagazine=10 replenishamount=1 replenishinterval=0.5/>
+        </munition>
+    </Drone>
+</Template>
+
+<Template name=dronepickupRepresentation>
+    <PickupRepresentation>
+        <spawner-representation>
+            <StaticEntity>
+                <attached>
+                    <Billboard position="0,0,0" colour="0.96,0.35,0.02" material="Sphere2" scale=0.1>
+                        <attached>
+                            <Model scale="5" mesh="drone.mesh"/>
+                        </attached>
+                    </Billboard>
+                </attached>
+            </StaticEntity>
+        </spawner-representation>
+    </PickupRepresentation>
+</Template>
+
+<Template name=dronepickup baseclass=DronePickup>
+    <DronePickup representation=dronepickup droneTemplate=droneTemplate />
+</Template>
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAssff.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAssff.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAssff.oxt	(revision 11817)
@@ -0,0 +1,128 @@
+<Template name=spaceshipassff>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 30
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsAssff.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+   
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAssff2.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAssff2.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAssff2.oxt	(revision 11817)
@@ -0,0 +1,130 @@
+<Template name=spaceshipassff2>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras2
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 50
+   maxhealth         = 100
+   initialhealth     = 50
+
+   shieldhealth        = 130
+   initialshieldhealth = 130
+   maxshieldhealth     = 150
+   shieldabsorption    = 0.95
+   shieldrechargerate  = 5
+   shieldrechargewaittime = 0.5
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 10
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine2 />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine2 />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsAssff2.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffcameras2 defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffengine2 baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAsteroids2D.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAsteroids2D.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipAsteroids2D.oxt	(revision 11817)
@@ -0,0 +1,137 @@
+<Template name=spaceshipasteroids2d>
+  <Asteroids2DShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 10
+   maxhealth         = 10
+   initialhealth     = 10
+
+   shieldhealth        = 20
+   initialshieldhealth = 20
+   maxshieldhealth     = 20
+   shieldabsorption    = 0.1
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 100
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 4200000
+   linearDamping     = 0.9
+   angularDamping    = 0.9999999
+
+   collisiondamage = 100
+   enablecollisiondamage = true
+   
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipasteroids2dengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipasteroids2dengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="escortShip.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" />
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/asteroids2DWeapon.oxi")
+?>
+  </Asteroids2DShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <Asteroids2DShip>
+    <camerapositions>
+    <!--<CameraPosition position="0,100,180" direction="0, -0.2, -1" drag=false mouselook=true />
+    <CameraPosition position="0,200,250" direction="0, -0.4, -1" drag=false mouselook=true />
+    <CameraPosition position="0,30,150" direction="0, 0, -1" drag=false mouselook=true />
+    <CameraPosition position="0,1300,-100" direction="0, -1, 0" drag=false mouselook=true />
+-->
+    <CameraPosition position="0,600,0" pitch=-90 absolute=true drag = false mouselook=true/>
+    <CameraPosition position="0,50,160" drag=true mouselook=true />
+    <CameraPosition position="0,40,125" drag=true mouselook=true />
+    <CameraPosition position="0,30, 90" drag=true mouselook=true />
+    </camerapositions>
+  </Asteroids2DShip>
+</Template>
+
+<Template name=spaceshipasteroids2dengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      = 200
+   speedleftright =  100
+   speedupdown    =  100
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      = 700
+   accelerationleftright =  500
+   accelerationupdown    =  500
+  >
+
+  <!-- backlight error if you fly over the edge
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  -->
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipCollateralDamage.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipCollateralDamage.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipCollateralDamage.oxt	(revision 11817)
@@ -0,0 +1,154 @@
+<!-- keuschr /-->
+<Template name=spaceshipcollateraldamage>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipCDcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 200
+   maxhealth         = 400
+   initialhealth     = 200
+
+   shieldhealth        = 30
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 12
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipCDengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipCDengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=-90 pitch=0 roll=0 scale=4 mesh="collateralDamage.mesh" />
+      
+      <BlinkingBillboard position="18.5,0.5,1.5" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=.5 quadratic=1 />
+      <BlinkingBillboard position="-18.5,0.5,1.5" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=.5 phase=180 quadratic=1 />
+
+	<!--Model mesh="cube.mesh" mass=10 position="0,0,0" scale3D="18,2,14" /-->
+	<!--Model mesh="cube.mesh" mass=10 position="0,2.5,0" scale3D="8,2.5,14" /-->
+
+    </attached>
+
+    <collisionShapes>
+      	<BoxCollisionShape position="0,0,0" halfExtents="18,2,14" />
+	<BoxCollisionShape position="0,2.5,0" halfExtents="8,2.5,14" />
+
+
+
+
+    </collisionShapes>
+
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+
+
+<?lua
+  include("../includes/weaponSettingsCollateral.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipCDcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+      <CameraPosition position="0,50,150" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipCDengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 5
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    
+<EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.05 position="1, 0.5, 14" colour="1.0, 0.65, 0.2, 1.0" material="Examples/Flare" turnontime=0.2 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.05 position="-1, 0.5, 14" colour="1.0, 0.65, 0.2, 1.0" material="Examples/Flare" turnontime=0.2 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+    </EffectContainer>
+
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 1, 0, 17" colour="1, 0.4, 0.15, 1.0" width=6 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1.5 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-1, 0, 17" colour="1, 0.4, 0.15, 1.0" width=6 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1.5 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 8, 0, 12" colour="1, 0.8, 0, 0.3" width=6 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=3 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-8, 0, 12" colour="1, 0.8, 0, 0.3" width=6 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=3 turnofftime=1 material="Flares/ThrusterFlare1" />
+
+      <FadingBillboard mainstate=activity active=false scale=0.05 position="8, -1, 12" colour="1, 0.8, 0, 0.3" material="Examples/Flare" turnontime=1 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.05 position="-8, -1, 12" colour="1, 0.8, 0, 0.3" material="Examples/Flare" turnontime=1 turnofftime=0.5 />
+
+    </EffectContainer>
+
+
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 3, 0, 20" colour="0.8,0.4,0, 0.15" width=5 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1.5 turnofftime=0.5 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-3, 0, 20" colour="0.8,0.4,0, 0.15" width=5 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1.5 turnofftime=0.5 material="Examples/Flare" />
+    </EffectContainer>
+
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipDodgeRace.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipDodgeRace.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipDodgeRace.oxt	(revision 11817)
@@ -0,0 +1,128 @@
+<Template name=spaceshipdodgerace>
+  <DodgeRaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 40
+   maxhealth         = 40
+   initialhealth     = 40
+
+   shieldhealth        = 20
+   initialshieldhealth = 20
+   maxshieldhealth     = 20
+   shieldabsorption    = 0.1
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 4200000
+   linearDamping     = 0.9999999
+   angularDamping    = 0.9999999
+
+   collisiondamage = 100
+   enablecollisiondamage = true
+   
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipinvaderengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipinvaderengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="escortShip.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" />
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/invaderWeapon.oxi")
+?>
+  </DodgeRaceShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <DodgeRaceShip>
+    <camerapositions>
+		<CameraPosition position="0,100,180" direction="0, -0.2, -1" drag=false mouselook=true />
+		<CameraPosition position="0,200,250" direction="0, -0.4, -1" drag=false mouselook=true />
+		<CameraPosition position="0,30,150" direction="0, 0, -1" drag=false mouselook=true />
+		<CameraPosition position="0,1300,-100" direction="0, -1, 0" drag=false mouselook=true />
+    </camerapositions>
+  </DodgeRaceShip>
+</Template>
+
+<Template name=spaceshipinvaderengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipEscort.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipEscort.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipEscort.oxt	(revision 11817)
@@ -0,0 +1,128 @@
+<Template name=spaceshipescort>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 10
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   shieldhealth        = 35
+   initialshieldhealth = 35
+   maxshieldhealth     = 60
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 80
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="escortShip.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" />
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="explosionparts/escort_part_1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_3.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_4.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_5.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_6.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsEscort.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,15, 60" drag=true mouselook=true />
+      <CameraPosition position="0,20, 90" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipescortengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+       />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 0.5, 0.65, 1.0" width=150 length=15 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, -2, 14" colour="0.2, 0.5, 0.65, 1.0" width=15 length=15 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=5 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipEscortMine.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipEscortMine.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipEscortMine.oxt	(revision 11817)
@@ -0,0 +1,127 @@
+<Template name=spaceshipescortmine>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 10
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   shieldhealth        = 35
+   initialshieldhealth = 35
+   maxshieldhealth     = 60
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 80
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipescortengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipescortengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="escortShip.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" />
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="explosionparts/escort_part_1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_3.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_4.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_5.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/escort_part_6.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsEscortMine.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,15, 60" drag=true mouselook=true />
+      <CameraPosition position="0,20, 90" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipescortengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+       />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 0.5, 0.65, 1.0" width=150 length=15 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, -2, 14" colour="0.2, 0.5, 0.65, 1.0" width=15 length=15 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=2 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=5 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, -2, 14" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=1 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipFlappyOrx.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipFlappyOrx.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipFlappyOrx.oxt	(revision 11817)
@@ -0,0 +1,56 @@
+<Template name=spaceshipFlappyOrx>
+  <FlappyOrxShip
+
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 6
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   collisionType     = "dynamic"
+   mass              = 4200000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+  collisiondamage = 100
+  enablecollisiondamage = true
+
+  speedBase = 100
+  speedIncrease = 0.5
+  tubeDistanceBase = 200
+  tubeDistanceIncrease = -1
+
+  upwardThrust = 220
+  gravity = 700
+
+  >
+   
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=90 roll=270 scale=9 mesh="FlappyOrxShip.mesh" />
+
+      <ParticleSpawner source="Orxonox/fire3" startdelay=0  position="0,0,20" visible="true"/>
+    
+    </attached>
+    <collisionShapes>
+      <SphereCollisionShape position="-1.8    ,0 ,  -11" radius="15" />
+      <SphereCollisionShape position="-0.8   ,0 ,  0" radius="16" />
+      <!-- <SphereCollisionShape position="0   ,0 ,  11" radius="12.5" /> -->
+    </collisionShapes>
+  
+  </FlappyOrxShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <FlappyOrxShip>
+    <camerapositions>
+      <CameraPosition position="0,300,-100" direction="0, -1, 0" drag=false absolute=true mouselook=true />
+    </camerapositions>
+  </FlappyOrxShip>
+</Template>
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipGhost.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipGhost.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipGhost.oxt	(revision 11817)
@@ -0,0 +1,114 @@
+<Template name=spaceshipghost>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipghostcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 30
+   maxhealth         = 50
+   initialhealth     = 30
+
+   shieldhealth        = 100
+   initialshieldhealth = 100
+   maxshieldhealth     = 150
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 3
+   shieldrechargewaittime = 0.0
+
+   primaryThrust     = 600
+   auxilaryThrust    = 30
+   rotationThrust    = 25
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 30
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 15
+
+   shakeFrequency = 20
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position="0,0,0" template=spaceshipghostengine/>
+    </engines>
+    <attached>
+      <Model position="0,0,0" scale=2 yaw=90 pitch=-90 roll=0 mesh="ghost.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsGhost.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipghostcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,20,80" drag=true mouselook=true />
+      <CameraPosition position="0,40,160" drag=true mouselook=true />
+      <CameraPosition position="0,50,200" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipghostengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 600
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   accelerationfront     = 1000
+   accelerationbrake     = 300
+   accelerationback      =  100
+   accelerationleftright =  100
+   accelerationupdown    =  100
+  >
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 3, 6" colour="0.0, 0.0, 0.0, 0.5" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 3, 6" colour="0.0, 0.0, 0.0, 0.5" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 3, 6" colour="0.0, 0.0, 0.0, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 3, 6" colour="0.0, 0.0, 0.0, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.4 position="7.6, 3, 6" colour="1, 1, 1, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.4 position="-7.6, 3, 6" colour="1, 1, 1, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.2, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.2, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+</MultiStateEngine>
+</Template>
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipH2.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipH2.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipH2.oxt	(revision 11817)
@@ -0,0 +1,100 @@
+<Template name=spaceshipHtwo>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipHtwocameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   primaryThrust     = 100;
+   auxilaryThrust    = 30;
+   rotationThrust    = 25;
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+
+<?lua
+  include("../includes/weaponSettingsH2.oxi")
+?>
+    <engines>
+      <MultiStateEngine position="0,0,0" template=spaceshipHtwoengine />
+
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale3D="3,0.833,0.833" mesh="h2_green.mesh" />
+      <BlinkingBillboard position=" 11.7,4.0,8.5" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-11.7,4.0,8.5" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipHtwocameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipHtwoengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <active>
+      <FadingBillboard mainstate=activity active=false scale=0.05 position=" 0.0, 2.0, 12.0" colour="0.0, 0.65, 0.0, 0.5" material="Examples/FlareZwei_1" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.05 position=" 3.8, 7.5, 11.0" colour="1.0, 1.00, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.05 position="-3.8, 7.5, 11.0" colour="1.0, 1.00, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.05 position=" 3.5, 0.0,-10.8" colour="1.0, 1.00, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.05 position="-3.5, 0.0,-10.8" colour="1.0, 1.00, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </active>
+    <forward>
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.06, 1.66, 11.6" colour="0, 0.65, 0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.26, 1.66, 11.6" colour="0, 0.65, 0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </forward>
+    <boost>
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.06, 1.66, 11.6" colour="0.5, 0.85, 0.5, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.26, 1.66, 11.6" colour="0.5, 0.85, 0.5, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </boost>
+  </MultiStateEngine>
+</Template>
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHXY.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHXY.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHXY.oxt	(revision 11817)
@@ -0,0 +1,108 @@
+<Template name=spaceshipHXY>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipHXYcameras
+   engine                 = spaceshipHXYengine
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   primaryThrust     = 100;
+   auxilaryThrust    = 30;
+   rotationThrust    = 25;
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshipHXYengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=-90 roll=0 scale=4 mesh="HXY.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+<?lua
+  include("../includes/weaponSettingsHXY.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipHXYcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,8, 60" drag=true mouselook=true />
+      <CameraPosition position="0,16, 120" drag=true mouselook=true />
+      <CameraPosition position="0,24,180" drag=true mouselook=true />
+      <CameraPosition position="0,60,10" pitch="-80" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipHXYengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 6
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 2, 0, 20" colour="1, 0.7, 0.1, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-2, 0, 20" colour="1, 0.7, 0.1, 1.0" width=10 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 2, 0, 20" colour="1, 0.7, 0.1, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-2, 0, 20" colour="1, 0.7, 0.1, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 2, 0, 20" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-2, 0, 20" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 2, 0, 20" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-2, 0, 20" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHXYSL.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHXYSL.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHXYSL.oxt	(revision 11817)
@@ -0,0 +1,52 @@
+<Template name=spaceshipHXYSL>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipHXYcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   primaryThrust     = 100;
+   auxilaryThrust    = 30;
+   rotationThrust    = 25;
+
+   collisionType     = "dynamic"
+   mass              = 1000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshipHXYengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=-90 roll=0 scale=4 mesh="HXY.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+<?lua
+  include("../includes/weaponSettingsHXY.oxi")
+?>
+  </SpaceShip>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHeartAttack.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHeartAttack.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHeartAttack.oxt	(revision 11817)
@@ -0,0 +1,136 @@
+<Template name=spaceshipHeartAttack>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipheartattackcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 200
+   maxhealth         = 300
+   initialhealth     = 150
+
+   shieldhealth        = 50
+   initialshieldhealth = 50
+   maxshieldhealth     = 800
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 40
+   auxilaryThrust    = 30
+   rotationThrust    = 35
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 19" template=spaceshipheartattackengine />
+      <MultiStateEngine position="-7.6, 0, 19" template=spaceshipheartattackengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="HeartAttack.mesh" />
+      <!--BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0.8,6"      halfExtents="12, 3, 10" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="4.7,1,-8"      halfExtents="2, 3, 5" />
+      <BoxCollisionShape position="-4.7,1,-8"      halfExtents="2, 3, 5" />
+      <BoxCollisionShape position="13.5,1,5"  halfExtents="1.4, 3, 7" />
+      <BoxCollisionShape position="-13.5,1,5"  halfExtents="1.4, 3, 7" />
+      <BoxCollisionShape position="16,2,4"  halfExtents="1.4, 1.5, 4" />
+      <BoxCollisionShape position="-16,2,4"  halfExtents="1.4, 1.5, 4" />
+      <BoxCollisionShape position="-2.8,5,4"  halfExtents="1.4, 1.5, 2" />
+      <BoxCollisionShape position="2.8,5,4"  halfExtents="1.4, 1.5, 2" />
+      <BoxCollisionShape position="5,5,4.3"  halfExtents="1.4, 1.5, 1.4" />
+      <BoxCollisionShape position="-5,5,4.3"  halfExtents="1.4, 1.5, 1.4" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsHeartAttack.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipheartattackcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,12, 48" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipheartattackengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+   
+   accelerationfront     = 420
+   accelerationbrake     = 420
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="4, 1.9, 19" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-4, 1.9, 19" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 4, 1.9, 19" colour="0.6, 0.2, 0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-4, 1.9, 19" colour="0.6, 0.2, 0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 4, 1.9, 19" colour="1, 0, 0, 0.5" width=20 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-4, 1.9, 19" colour="1, 0, 0, 1" width=20 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+   <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 4, 1.9, 19" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-4, 1.9, 19" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 4, 1.9, 19" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-4, 1.9, 19" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHover.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHover.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipHover.oxt	(revision 11817)
@@ -0,0 +1,109 @@
+<Template name=spaceshiphover>
+  <SpaceShip
+   hudtemplate            = spaceshiphoverhud
+   camerapositiontemplate = spaceshiphovercameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 25
+   initialshieldhealth = 25
+   maxshieldhealth     = 40
+   shieldabsorption    = 0.6
+   reloadrate          = 2
+   reloadwaittime      = 0.5
+
+   primaryThrust     = 200
+   auxilaryThrust    = 30
+   rotationThrust    = 25
+
+   jumpBoost = 90
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 10
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.2
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshiphoverengine />
+    </engines>
+    <attached>
+      <Model position="0,0,-20" mesh="hovership_body.mesh" scale="5" yaw=180/>	
+      <Model position="0,0,-20" mesh="hovership_engine.mesh" scale="5" yaw=180/>	
+      <Model position="0,0,-20" mesh="hovership_gun.mesh" scale="5" yaw=180/>	
+      
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,-2 ,7" halfExtents="7, 4 ,30" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" scale=2 />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="explosionparts/pirate_part_1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/pirate_part_2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/pirate_part_3.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/pirate_part_4.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+<?lua
+  include("../includes/weaponSettingsHover.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshiphovercameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,8, 5" drag=true mouselook=true />
+      <CameraPosition position="0,8,5" yaw="180" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshiphoverengine baseclass=Engine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 90
+   speedback      =  40
+   speedleftright =  40
+   speedupdown    =  40
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.02 position=" 1.3, 0, 15" colour="1.0, 0.65, 0.2, 1.0" material="Examples/FlareZwei" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.02 position=" 0, 0, 15" colour="1.0, 0.65, 0.2, 1.0" material="Examples/FlareZwei" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.02 position="-1.3, 0, 15" colour="1.0, 0.65, 0.2, 1.0" material="Examples/FlareZwei" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.8 name=bltest position=" 0, 0,  40" colour="1.0, 0.65, 0.2, 1.0" width=10 length=800 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+     
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.8 name=bltest position="  0, 0, 40" colour="1.0, 0.65, 0.2, 1.0" width=10 length=1600 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.5 position=" 0, 0, 40" colour="0.8, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      
+    </EffectContainer>
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipInvader.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipInvader.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipInvader.oxt	(revision 11817)
@@ -0,0 +1,127 @@
+<Template name=spaceshipinvader>
+  <InvaderShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipescortcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   shieldhealth        = 35
+   initialshieldhealth = 35
+   maxshieldhealth     = 60
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 4200000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+    collisiondamage = 100
+    enablecollisiondamage = true
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipinvaderengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipinvaderengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="escortShip.mesh" />
+      <Model position="0,0,0" yaw=180 pitch=90 roll=0 scale=4 mesh="escortWeapon.mesh" />
+<!--Model mesh="cube.mesh" mass=10 position="0,0,3" scale3D="10,4,8" />
+<Model mesh="cube.mesh" mass=10 position="12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="-12.6,-2,3" scale3D="2.8,2.8,11" />
+<Model mesh="cube.mesh" mass=10 position="0,0,-12" scale3D="4,4,7" /-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/invaderWeapon.oxi")
+?>
+  </InvaderShip>
+</Template>
+
+<Template name=spaceshipescortcameras defaults=0>
+  <InvaderShip>
+    <camerapositions>
+<!--       <CameraPosition position="0,15, 60" drag=true mouselook=true />
+      <CameraPosition position="0,20, 90" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true /> -->
+      <CameraPosition position="0,300,-100" direction="0, -1, 0" drag=false mouselook=true />
+    </camerapositions>
+  </InvaderShip>
+</Template>
+
+<Template name=spaceshipinvaderengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-12, -2, 13" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.2, 1.0, 0.65, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position="-12, 0, 10" colour="0.6, 0.8, 0.75, 0.7" width=25 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipPirate.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipPirate.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipPirate.oxt	(revision 11817)
@@ -0,0 +1,115 @@
+<Template name=spaceshippirate>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshippiratecameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 25
+   initialshieldhealth = 25
+   maxshieldhealth     = 40
+   shieldabsorption    = 0.6
+   shieldrechargerate  = 2
+   shieldrechargewaittime = 0.5
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 25
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 10
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshippirateengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="pirate.mesh" />
+      <BlinkingBillboard position=" 12.7,-3.8,0" material="Examples/Flare" colour="1.0, 1.0, 1" amplitude=0.04 frequency=1 quadratic=1 />
+      <BlinkingBillboard position="-12.7,-3.8,0" material="Examples/Flare" colour="1.0, 1.0, 1" amplitude=0.04 frequency=1 quadratic=1 phase="90"/>
+      <BlinkingBillboard position=" 8.7,-0.5,2.5" material="Examples/Flare" colour="1.0, 1.0, 1" amplitude=0.04 frequency=1 quadratic=1 phase="30"/>
+      <BlinkingBillboard position="-8.7,-0.5,2.5" material="Examples/Flare" colour="1.0, 1.0, 1" amplitude=0.04 frequency=1 quadratic=1 phase="60"/>
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion>
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" scale=2 />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart mesh="explosionparts/pirate_part_1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/pirate_part_2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/pirate_part_3.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="explosionparts/pirate_part_4.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+<?lua
+  include("../includes/weaponSettingsPirate.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshippiratecameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,8, 60" drag=true mouselook=true />
+      <CameraPosition position="0,16, 120" drag=true mouselook=true />
+      <CameraPosition position="0,24,180" drag=true mouselook=true />
+      <CameraPosition position="0,60,10" pitch="-80" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshippirateengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 150
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.02 position=" 1.3, -4, -15" colour="1.0, 0.65, 0.2, 1.0" material="Examples/FlareZwei" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.02 position=" 0, -4, -15" colour="1.0, 0.65, 0.2, 1.0" material="Examples/FlareZwei" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.02 position="-1.3, -4, -15" colour="1.0, 0.65, 0.2, 1.0" material="Examples/FlareZwei" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 13, -4,  9.5" colour="1.0, 0.65, 0.2, 1.0" width=8 length=800 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-13, -4,  9.5" colour="1.0, 0.65, 0.2, 1.0" width=8 length=800 lifetime=1 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="  0,  5, 15.5" colour="1.0, 0.65, 0.2, 1.0" width=16 length=1600 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position=" 4.4, -5.5, 5" colour="0.8, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-4.4, -5.5, 5" colour="0.8, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipRace.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipRace.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipRace.oxt	(revision 11817)
@@ -0,0 +1,130 @@
+<Template name=spaceshiprace>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 30
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+    </attached>
+    <collisionShapes>
+
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsAssff.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipassffengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 2500
+   speedback      =  50
+   speedleftright =  50
+   speedupdown    =  50
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-7.6, 0, 9" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-7.6, 0, 6" colour="0.6, 0.75, 0.8, 0.7" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position=" 8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-8, 0, 6" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipRing.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipRing.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipRing.oxt	(revision 11817)
@@ -0,0 +1,121 @@
+<Template name=spaceshipring>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipringcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 4
+
+   health            = 80
+   maxhealth         = 200
+   initialhealth     = 80
+
+   shieldhealth        = 35
+   initialshieldhealth = 35
+   maxshieldhealth     = 60
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 150
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 6
+
+   collisionType     = "dynamic"
+   mass              = 80
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 0" template=spaceshipringengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipringengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=0 roll=0 scale=4 mesh="ship.mesh" />
+      <Model position="11,1,-9" yaw=-90 pitch=0 roll=90 scale=0.15 mesh="ringWeapon.mesh" />
+      <Model position="-11,1,-9" yaw=-90 pitch=0 roll=90 scale=0.15 mesh="ringWeapon.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0    ,0 ,  3" halfExtents="10,   4,8" />
+      <BoxCollisionShape position="12.6 ,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="-12.6,-2,  3" halfExtents="2.8,2.8,11"/>
+      <BoxCollisionShape position="0,     0,-12" halfExtents="4  , 4 ,7" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsRing.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipringcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,15, 60" drag=true mouselook=true />
+      <CameraPosition position="0,20, 90" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipringengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2.2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 700
+   accelerationbrake     = 700
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="13, 0, 16" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.09 position="-13, 0, 16" colour="0.2, 1.0, 0.65, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 0, 2, 16" colour="0.2, 1.0, 0.65, 1.0" width=25 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 13, 0, 16" colour="0.2, 1.0, 0.65, 1.0" width=20 length=1000
+ lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+<Backlight mainstate=activity active=false scale=0.33 name=bltest position=" -13, 0, 16" colour="0.2, 1.0, 0.65, 1.0" width=20 length=1000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.33 name=bltest position=" 0, 2, 16" colour="0.6, 0.8, 0.75, 0.7" width=35 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipShuttle.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipShuttle.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipShuttle.oxt	(revision 11817)
@@ -0,0 +1,101 @@
+<Template name=spaceshipShuttle>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipTransportercameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 2000
+   maxhealth         = 2500
+   initialhealth     = 2000
+
+   primaryThrust     = 120;
+   auxilaryThrust    = 20;
+   rotationThrust    = 30;
+
+   collisionType     = "dynamic"
+   mass              = 1000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshipTransporterengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=180 pitch=0 roll=0 scale=10 mesh="Transporterspaceship.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position=" 0, 0, 20"      halfExtents=" 37, 25, 80" />
+      <BoxCollisionShape position=" 0, 21, 20"      halfExtents=" 37, 21, 80" />
+      <BoxCollisionShape position=" 0, 40, 110"      halfExtents=" 20, 10, 40" />
+      <BoxCollisionShape position=" 0, 45, 170"      halfExtents=" 33, 25, 20" />
+      <BoxCollisionShape position=" -60, 33, 0"      halfExtents=" 24, 16, 120" />
+      <BoxCollisionShape position=" 60, 33, 0"      halfExtents=" 24, 16, 120" />
+      <BoxCollisionShape position=" 0, 10, -90"      halfExtents=" 30, 25, 30" />
+      <BoxCollisionShape position=" 0, -3, -145"      halfExtents=" 20, 20, 30" />
+    </collisionShapes>
+
+<?lua
+  include("../includes/weaponSettingsTransporter.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipTransportercameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,90,350" drag=true mouselook=true />
+      <CameraPosition position="0,125, 400" drag=true mouselook=true />
+      <CameraPosition position="0,200,550" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipTransporterengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 120
+   speedback      =  20
+   speedleftright =  20
+   speedupdown    =  20
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 40
+   accelerationbrake     = 30
+   accelerationback      = 20
+   accelerationleftright =  20
+   accelerationupdown    =  20
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=2 name=bltest position=" -80, 33, 100" colour="1, 0.7, 0.1, 1.0" width=10 length=3000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=2 name=bltest position=" 80, 33, 100" colour="1, 0.7, 0.1, 1.0" width=10 length=3000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=2 name=bltest position=" -75, 25, -57" colour="1, 0.7, 0.1, 1.0" width=10 length=3000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=2 name=bltest position=" 75, 25, -57" colour="1, 0.7, 0.1, 1.0" width=10 length=3000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=3 name=bltest position=" -80, 33, 100" colour="1, 0.7, 0.1, 0.7" width=25 length=2000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=3 name=bltest position=" 80, 33, 100" colour="1, 0.7, 0.1, 0.7" width=25 length=2000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=3 name=bltest position=" -75, 25, -57" colour="1, 0.7, 0.1, 0.7" width=25 length=2000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=3 name=bltest position=" 75, 25, -57" colour="1, 0.7, 0.1, 0.7" width=25 length=2000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=2 position=" -75, 33, 40" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=2 position=" 75, 33, 40" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position=" -68, 25, -115" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position=" 68, 25, -115" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipSpacecruiser.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipSpacecruiser.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipSpacecruiser.oxt	(revision 11817)
@@ -0,0 +1,140 @@
+<Template name=spaceshipspacecruiser>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipcruisercameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 2
+   explosionchunks        = 12
+
+   health            = 300
+   maxhealth         = 400
+   initialhealth     = 300
+
+   shieldhealth        = 75
+   initialshieldhealth = 75
+   maxshieldhealth     = 90
+   shieldabsorption    = 0.9
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 90
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 16
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 12
+   shakeAmplitude = 7
+
+   collisionType     = "dynamic"
+   mass              = 300
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, -20, 6" template=spaceshipcruiserengine />
+      <MultiStateEngine position="-7.6, -20, 0" template=spaceshipcruiserengine />
+      <MultiStateEngine position=" 7.6, 20, 6" template=spaceshipcruiserengine />
+      <MultiStateEngine position="-7.6, 20, 0" template=spaceshipcruiserengine />
+    </engines>
+    <attached>
+      <Model position="12,-5,-10" yaw=90 pitch=-90 roll=0 scale=6 mesh="spacecruiser.mesh" />
+      <!--Model mesh="cube.mesh" mass=10 position="0,-30,-108" scale3D="38,6,62" />
+      <Model mesh="cube.mesh" mass=10 position="0,-20,-108" scale3D="20,6,40" />
+      <Model mesh="cube.mesh" mass=10 position="-16,-35,-112" scale3D="15,5,57" roll=-14 pitch=3.5/>
+      <Model mesh="cube.mesh" mass=10 position="16,-35,-112" scale3D="15,5,57" roll=14 pitch=3.5/>
+      <Model mesh="cube.mesh" mass=10 position="19,-21.5,-108" scale3D="18,5,52" roll=-21 />
+      <Model mesh="cube.mesh" mass=10 position="-19,-21.5,-108" scale3D="18,5,52" roll=21 />
+      <Model mesh="cube.mesh" mass=10 position="0,-21,-169" scale3D="18,1,16" pitch=-30 /-->
+
+
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,-5,2"     halfExtents="38,6,62" />
+      <BoxCollisionShape position="0,5,2"      halfExtents="20,6,40" />
+      <BoxCollisionShape position="-16,-10,-2" halfExtents="15,5,57" roll=-14 pitch=3.5/>
+      <BoxCollisionShape position="16,-10,-2"  halfExtents="15,5,57" roll=14  pitch=3.5/>
+      <BoxCollisionShape position="19,3.5,2"   halfExtents="18,5,52" roll=-21 />
+      <BoxCollisionShape position="-19,4.5,2"  halfExtents="18,5,52" roll=21  />
+      <BoxCollisionShape position="0,4,-59"    halfExtents="18,1,16" pitch=-30/>
+
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsSpacecruiser.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipcruisercameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,40, 170" drag=true mouselook=true />
+      <CameraPosition position="0,55, 230" drag=true mouselook=true />
+      <CameraPosition position="0,65, 460" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipcruiserengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 200
+   speedback      =  70
+   speedleftright =  70
+   speedupdown    =  70
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 500
+   accelerationbrake     = 500
+   accelerationback      =  125
+   accelerationleftright =  125
+   accelerationupdown    =  125
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="20,  0, 70" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.1 position="-20, 0, 70" colour="0.2, 0.65, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 20, 0, 70" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1300 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-20, 0, 70" colour="0.2, 0.65, 1.0, 1.0" width=15 length=1300 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 20, 0, 70" colour="0.6, 0.75, 0.8, 0.7" width=40 length=800 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-20, 0, 70" colour="0.6, 0.75, 0.8, 0.7" width=40 length=800 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+<!--    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 20,  0, 70" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-20,  0, 70" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="20,  0, 70" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.15 position="-20, 0, 70" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+-->
+  </MultiStateEngine>
+</Template>
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipSwallow.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipSwallow.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipSwallow.oxt	(revision 11817)
@@ -0,0 +1,115 @@
+<Template name=spaceshipswallow>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipswallowcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 50
+   maxhealth         = 120
+   initialhealth     = 50
+
+   shieldhealth        = 60
+   initialshieldhealth = 60
+   maxshieldhealth     = 80
+   shieldabsorption    = 0.75
+   shieldrechargerate  = 1.5
+   shieldrechargewaittime = 0.2
+
+   primaryThrust     = 600;
+   auxilaryThrust    = 30;
+   rotationThrust    = 25;
+
+   lift = 1.2;
+   stallSpeed = 220;
+
+   boostPower            = 20
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshipswallowengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" scale=2 yaw=90 pitch=-90 roll=0 mesh="swallow_mat.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsSwallow.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipswallowcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,25,85" drag=true mouselook=true />
+      <CameraPosition position="0,40,140" drag=true mouselook=true />
+      <CameraPosition position="0,50,160" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipswallowengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 600
+   speedback      =  60
+   speedleftright =  60
+   speedupdown    =  60
+
+   accelerationfront     = 1000
+   accelerationbrake     = 300
+   accelerationback      =  100
+   accelerationleftright =  120
+   accelerationupdown    =  120
+  >
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 6.6, 0, 22" colour="1.0, 1.0, 1.0, 0.5" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-6.6, 0, 22" colour="1.0, 1.0, 1.0, 0.5" width=15 length=1500 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=0.023 name=bltest position=" 2.1, 1.66, 23.8" colour="0.5, 0.15, 0.0, 1.0" width=40 length=10 lifetime=1 elements=30 trailmaterial="Trail/backlighttrailzwei" turnontime=1 turnofftime=500000 material="Examples/Flaredrei" />
+      <Backlight mainstate=activity active=false scale=0.023 name=bltest position="-2.1, 1.66, 23.8" colour="0.5, 0.15, 0.0, 1.0" width=40 length=10 lifetime=1 elements=30 trailmaterial="Trail/backlighttrailzwei" turnontime=1 turnofftime=500000 material="Examples/Flaredrei" />      
+
+
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position=" 6.6, 0, 22" colour="1.0, 1.0, 1.0, 0.5" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=0.4 name=bltest position="-6.6, 0, 22" colour="1.0, 1.0, 1.0, 0.5" width=40 length=1000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+      <FadingBillboard mainstate=activity active=false scale=0.4 position="6.6, 0, 22" colour="0, 0.6, 0.85, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=10000 />
+      <FadingBillboard mainstate=activity active=false scale=0.4 position="-6.9, 0, 22" colour="0, 0.6, 0.85, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=10000/>
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=0.3 position=" 8, 0, 6" colour="1.0, 1.0, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=0.3 position="-8, 0, 6" colour="1.0, 1.0, 1.0, 1.0" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+</MultiStateEngine>
+</Template>
+
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTransporter.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTransporter.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTransporter.oxt	(revision 11817)
@@ -0,0 +1,107 @@
+<Template name=spaceshipTransporter>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipTransportercameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 1000
+   maxhealth         = 1500
+   initialhealth     = 1000
+
+   primaryThrust     = 50;
+   auxilaryThrust    = 10;
+   rotationThrust    = 15;
+
+   collisionType     = "dynamic"
+   mass              = 1000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshipTransporterengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=0 pitch=0 roll=0 scale=10 mesh="Transporter.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+<?lua
+  include("../includes/weaponSettingsTransporter.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipTransportercameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,90,350" drag=true mouselook=true />
+      <CameraPosition position="0,150, 400" drag=true mouselook=true />
+      <CameraPosition position="0,200,550" drag=true mouselook=true />
+      <CameraPosition position="0,120,200" pitch="-80" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipTransporterengine baseclass=MultiStateEngine>
+  <MultiStateEngine
+   boostfactor    = 2
+
+   speedfront     = 50
+   speedback      =  10
+   speedleftright =  10
+   speedupdown    =  10
+
+   defEngineSndNormal = "sounds/Engine_low.ogg"
+   defEngineSndBoost = "sounds/Engine_high.ogg"
+
+   accelerationfront     = 20
+   accelerationbrake     = 20
+   accelerationback      = 10
+   accelerationleftright =  10
+   accelerationupdown    =  10
+  >
+    <EffectContainer condition="idle">
+      <WorldSound mainstate="activity" source="sounds/Engine_idle.ogg" looping=1 active=false/>
+    </EffectContainer>
+    <EffectContainer condition="not idle">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or brake">
+
+    </EffectContainer>
+    <EffectContainer condition="normal or boost">
+      <Backlight mainstate=activity active=false scale=2 name=bltest position=" 22, -10, 87" colour="1, 0.7, 0.1, 1.0" width=10 length=3000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+      <Backlight mainstate=activity active=false scale=2 name=bltest position="-22, -10, 87" colour="1, 0.7, 0.1, 1.0" width=10 length=3000 lifetime=2 elements=50 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Flares/ThrusterFlare1" />
+    </EffectContainer>
+    <EffectContainer condition="boost">
+      <Backlight mainstate=activity active=false scale=3 name=bltest position=" 22, -10, 87" colour="1, 0.7, 0.1, 0.7" width=25 length=2000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+      <Backlight mainstate=activity active=false scale=3 name=bltest position="-22, -10, 87" colour="1, 0.7, 0.1, 0.7" width=25 length=2000 lifetime=1 elements=30 trailmaterial="Trail/backlighttrail" turnontime=1 turnofftime=1 material="Examples/Flare" />
+    </EffectContainer>
+    <EffectContainer condition="brake">
+      <FadingBillboard mainstate=activity active=false scale=2 position=" 22, -10, 87" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=2 position="-22, -10, 87" colour="0.5, 0.0, 0.0, 0.3" material="Examples/Flare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position="22, -10, 87" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+      <FadingBillboard mainstate=activity active=false scale=1 position="-22, -10, 87" colour="1.0, 0.0, 0.0, 1.0" material="Flares/backlightflare" turnontime=0.5 turnofftime=0.5 />
+    </EffectContainer>
+  </MultiStateEngine>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTransporterSL.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTransporterSL.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTransporterSL.oxt	(revision 11817)
@@ -0,0 +1,52 @@
+<Template name=spaceshipTransporterSL>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipTransportercameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 1000
+   maxhealth         = 1500
+   initialhealth     = 1000
+
+   primaryThrust     = 50;
+   auxilaryThrust    = 10;
+   rotationThrust    = 15;
+
+   collisionType     = "dynamic"
+   mass              = 1000
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 0, 0, 0" template=spaceshipTransporterengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=0 pitch=0 roll=0 scale=10 mesh="Transporter.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+
+<?lua
+  include("../includes/weaponSettingsTransporter.oxi")
+?>
+  </SpaceShip>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTurret.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTurret.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spaceshipTurret.oxt	(revision 11817)
@@ -0,0 +1,71 @@
+<Template name=spaceshipturret>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipturretcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   shieldhealth        = 30
+   initialshieldhealth = 30
+   maxshieldhealth     = 50
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 50
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <attached>
+        <Model position="0,0,0" yaw="90" roll="-90" mesh="turretHead.mesh" scale3D="10,10,10"/>
+    </attached>
+    <collisionShapes>
+        <SphereCollisionShape radius="10"   position = "0,0,0"/>
+    </collisionShapes>
+    <explosion >
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_flash2" effect2="orxonox/explosion_flame2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_shockwave2" effect2="orxonox/explosion_sparks2" />
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="orxonox/explosion_streak2" effect2="orxonox/explosion_afterglow" />
+
+      <ExplosionPart minspeed=0 maxspeed=0 effect1="Orxonox/explosion2b" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="CockpitDebris.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="BodyDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris1.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+      <ExplosionPart mesh="WingDebris2.mesh" effect1="Orxonox/fire4" effect2="Orxonox/smoke6" />
+    </explosion>
+<?lua
+  include("../includes/weaponSettingsTurret.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<Template name=spaceshipturretcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/spacestation_elements.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/spacestation_elements.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/spacestation_elements.oxt	(revision 11817)
@@ -0,0 +1,466 @@
+<!--Templates of spacestation elements with alle their collisionshapes,
+	for creating a spacestation very easy.
+	Autor: Florian Süess
+	Test Level: FPS_Level_HS14 	-->	
+<Template name=spacestation_elements>
+	<SpaceStation
+	normalTubetemplate		= ss_tube
+	curvedTubetemplate		= ss_curve
+	crossingTubetemplate	= ss_tube_x
+	wall					= ss_wall
+	flagg					= ss_flag_aean
+	>
+	</SpaceStation>
+</Template>
+	
+	
+<!-- to place the different collisionshapes, I used some help boxes and an help coordinate system.
+	 The axis from the coordinatesystem are "red,green,yellow" and the orange boxe shows the negative direction.
+	 But atention, each element is different! A few of them are already rotatet with yaw, roll and pitch:
+	 -> "pitch" is a rotation around "red" in the "yellow, green" plain.
+	 -> "yaw" is a rotation around "green" in the "red, yellow" plain.
+	 -> "roll" is a rotation around "yellow" in the "green,red" plain.
+	 this chanches their negativ/positiv direction of the axis.
+	 -->
+			
+
+<!-- Spacestation Element Tube -->
+<Template name=ss_tube>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<Model position="0,0,0" yaw=0 scale3D="100,100,100" mesh="ss_tube.mesh" />
+
+	</attached>
+	 <collisionShapes>
+		<BoxCollisionShape position="0,0,100"  			halfExtents="250,100,0" />	<!--Wand links-->
+		<BoxCollisionShape position="0,0,-100"     		halfExtents="250,100,0" />	<!--Wand rechts-->
+		<BoxCollisionShape position="0,100,0"    	 	halfExtents="250,0,100" />	<!--Decke-->
+		<BoxCollisionShape position="0,-100,0"     		halfExtents="250,0,100" />	<!--Boden-->
+		
+      
+     </collisionShapes>
+   
+<Model position="-200,0,-275"  mesh="cube_green.mesh" scale3D="0,100,75" />
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Curve -->
+<Template name=ss_curve>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<!-- Boxes helps to place collisionShapes -->
+
+	<!--<Model position="0,0,-200"  mesh="cube_green.mesh" scale3D="0,100,150" />
+		<Model position="-300,0,100"  mesh="cube_green.mesh" scale3D="150,100,0" />
+		<Model position="-100,0,0" yaw=45 mesh="cube_red.mesh" scale3D="150,100,0" />
+
+		<Model position="-200,0,-275"  mesh="cube_green.mesh" scale3D="0,100,75" />
+		<Model position="-375,0,-100"  mesh="cube_green.mesh" scale3D="75,100,0" />
+		<Model position="-245,0,-148" yaw=45 mesh="cube_red.mesh" scale3D="70.71,100,0" />
+
+		<Model position="-225,100,-125"  mesh="cube_red.mesh" scale3D="225,0,225" /> -->
+
+
+	<Model position="0,0,0" yaw=0 scale3D="100,100,100" mesh="ss_curve.mesh" />
+
+
+	</attached>
+	 <collisionShapes>
+		<BoxCollisionShape position="0,0,-200"  				halfExtents="0,100,150" />	<!--Wand rechts-->
+		<BoxCollisionShape position="-300,0,100"  				halfExtents="150,100,0" />	<!--Wand rechts-->
+		<BoxCollisionShape position="-100,0,0"   	yaw=45		halfExtents="150,100,0" />	<!--Wand rechts-->
+		<BoxCollisionShape position="-200,0,-275"  				halfExtents="0,100,75" />	<!--Wand links-->
+		<BoxCollisionShape position="-375,0,-100"  				halfExtents="75,100,0" />	<!--Wand links-->
+		<BoxCollisionShape position="-245,0,-148"  	yaw=45		halfExtents="70.7,100,0" />	<!--Wand links-->
+		<BoxCollisionShape position="-225,100,-125" 			halfExtents="225,0,225" />	<!--Boden-->
+		<BoxCollisionShape position="-225,-100,-125"     		halfExtents="250,0,225" />	<!--Decke-->
+      
+     </collisionShapes>
+  
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Crossing -->
+<Template name=ss_tube_x>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<!-- Boxes helps to place collisionShapes -->
+
+	<!--<Model position="175,0,100" 	mesh="cube_green.mesh" scale3D="75,100,0" />
+		<Model position="-0,0,275"  	mesh="cube_green.mesh" scale3D="0,100,75" />
+		<Model position="-200,0,275" 	mesh="cube_red.mesh" scale3D="0,100,75" />
+		<Model position="-375,0,100" 	mesh="cube_red.mesh" scale3D="75,100,0" />
+
+		<Model position="175,0,-100"  	mesh="cube_green.mesh" scale3D="75,100,0" />
+		<Model position="0,0,-275" 		mesh="cube_green.mesh" scale3D="0,100,75" />
+		<Model position="-200,0,-275" 	mesh="cube_red.mesh" scale3D="0,100,75" />
+		<Model position="-375,0,-100" 	mesh="cube_red.mesh" scale3D="75,100,0" />
+
+		<Model position="-245,0,-147"  	yaw=45		mesh="cube_red.mesh" scale3D="70.7,100,0" />
+		<Model position="50,0,-147"  	yaw=-45		mesh="cube_red.mesh" scale3D="70.7,100,0" />
+		<Model position="-245,0,149" 	yaw=-45		mesh="cube_orange.mesh" scale3D="70.7,100,0" />
+		<Model position="50,0,148"  	yaw=45		mesh="cube_orange.mesh" scale3D="70.7,100,0" /> -->
+	
+	<Model position="0,0,0" scale3D="100,100,100" mesh="ss_tube_x.mesh" />
+
+	</attached>
+	 <collisionShapes>
+		<BoxCollisionShape position="175,0,100"  			halfExtents="75,100,0" />	<!--Wand links-->
+		<BoxCollisionShape position="0,0,275"  				halfExtents="0,100,75" />	<!--Wand links-->
+		<BoxCollisionShape position="-200,0,275"  			halfExtents="0,100,75" />	<!--Wand links-->
+		<BoxCollisionShape position="-375,0,100"  			halfExtents="75,100,0" />	<!--Wand links-->
+		
+		<BoxCollisionShape position="175,0,-100"     		halfExtents="75,100,0" />	<!--Wand rechts-->
+		<BoxCollisionShape position="0,0,-275"     			halfExtents="0,100,75" />	<!--Wand rechts-->
+		<BoxCollisionShape position="-200,0,-275"     		halfExtents="0,100,75" />	<!--Wand rechts-->
+		<BoxCollisionShape position="-375,0,-100"     		halfExtents="75,100,0" />	<!--Wand rechts-->
+		
+		<BoxCollisionShape position="-245,0,-147"   yaw=45  	halfExtents="70.7,100,0" />	<!--Wand schraeg rechts-->
+		<BoxCollisionShape position="50,0,-149"     yaw=-45		halfExtents="70.7,100,0" />	<!--Wand schraeg rechts-->
+		<BoxCollisionShape position="-245,0,149"  	yaw=-45  	halfExtents="70.7,100,0" />	<!--Wand schraeg links-->
+		<BoxCollisionShape position="50,0,148" 		yaw=45 		halfExtents="70.7,100,0" />	<!--Wand schraeg links-->
+		
+		
+		
+		<BoxCollisionShape position="-100,100,0"    	 	halfExtents="350,0,350" />	<!--Boden-->
+		<BoxCollisionShape position="-100,-110,0"     		halfExtents="350,0,350" />	<!--decke-->
+      
+     </collisionShapes>
+    
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Flagroom -->
+<Template name=ss_flag_room>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<!-- Boxes helps to place collisionShapes -->
+	
+	<!--<Model position="-125,116,0" 				mesh="cube_green.mesh" 	scale3D="130,0,125" />
+		<Model position="-275,116,235" 	yaw=55		mesh="cube_green.mesh" 	scale3D="140,0,50" />
+		<Model position="-275,116,-235"	yaw=-55		mesh="cube_red.mesh"	scale3D="140,0,50" />
+		<Model position="-365,116,320" 	yaw=35		mesh="cube_green.mesh"	scale3D="100,0,50" />
+		<Model position="-365,116,-320"	yaw=-35		mesh="cube_red.mesh" 	scale3D="100,0,50" />
+		<Model position="-520,156,380" 	roll=-25	mesh="cube_green.mesh" 	scale3D="100,0,50" />
+		<Model position="-520,156,-380"	roll=-25	mesh="cube_red.mesh" 	scale3D="100,0,50" />	
+
+
+		<Model position="-80,0,100" 				mesh="cube_green.mesh" 	scale3D="80,100,0" />
+		<Model position="-160,0,150" 	yaw=90		mesh="cube_green.mesh" 	scale3D="50,200,0" />
+		<Model position="-220,0,260" 	yaw=55		mesh="cube_green.mesh" 	scale3D="140,200,0" />
+		<Model position="-360,0,390" 	yaw=33		mesh="cube_green.mesh" 	scale3D="110,200,0" />
+		<Model position="-600,16,430" 				mesh="cube_green.mesh" 	scale3D="200,200,0" />
+		<Model position="-810,16,405"	yaw=-32		mesh="cube_green.mesh" 	scale3D="150,200,0" />
+		<Model position="-965,166,270"	yaw=-55		mesh="cube_green.mesh" 	scale3D="150,50,0" />
+
+		<Model position="-80,0,-100" 				mesh="cube_red.mesh" 	scale3D="80,100,0" />
+		<Model position="-160,0,-150" 	yaw=-90		mesh="cube_red.mesh" 	scale3D="50,200,0" />
+		<Model position="-220,0,-260" 	yaw=-55		mesh="cube_red.mesh" 	scale3D="140,200,0" />
+		<Model position="-360,0,-390" 	yaw=-33		mesh="cube_red.mesh" 	scale3D="110,200,0" />
+		<Model position="-600,16,-430" 				mesh="cube_red.mesh" 	scale3D="200,200,0" />
+		<Model position="-810,16,-405"  yaw=32		mesh="cube_red.mesh" 	scale3D="150,200,0" />
+		<Model position="-965,166,-270" yaw=55		mesh="cube_red.mesh" 	scale3D="150,50,0" />	
+
+		<Model position="-1045,166,0" 				mesh="cube_orange.mesh" 	scale3D="0,50,160" />
+
+
+		<Model position="-650,200,0"  	mesh="cube_green.mesh" scale3D="400,0,450" />
+
+		<Model position="-500,-200,0" 	mesh="cube_green.mesh" scale3D="400,0,400" />	
+		<Model position="-60,-84,0" 	mesh="cube_green.mesh" scale3D="60,0,100" />	
+	
+		<Model position="-1015,156,0" 	mesh="cube_orange.mesh" scale3D="27,25,120" />	
+		<Model position="-580,185,0" 	mesh="cube_orange.mesh" scale3D="30,12,30" />
+		<Model position="-580,195,0" 	mesh="cube_orange.mesh" scale3D="50,10,50" />
+
+
+
+		<Model position="-255,121,0" 				mesh="cube_green.mesh" 	scale3D="0,85,125" />
+		<Model position="-300,116,190" 	yaw=-35		mesh="cube_green.mesh" 	scale3D="0,80,75" />	
+		<Model position="-300,116,-190"	yaw=35		mesh="cube_green.mesh" 	scale3D="0,80,75" />
+		<Model position="-410,116,290" 	yaw=-55		mesh="cube_green.mesh" 	scale3D="0,80,75" />	
+		<Model position="-410,116,-290"	yaw=55		mesh="cube_green.mesh" 	scale3D="0,80,75" />	
+		<Model position="-500,185,328"  yaw=2		roll=-25	mesh="cube_green.mesh" 	scale3D="100,35,0" />
+		<Model position="-500,185,-328"	yaw=-2		roll=-25	mesh="cube_red.mesh"	scale3D="100,35,0" />	-->
+
+
+
+	<!-- points for the orientation -->
+	<!--<Model position="0,0,0" 			mesh="cube_orange.mesh" scale3D="10,10,10" />
+		<Model position="-260,0,0" 			mesh="cube_orange.mesh" scale3D="10,10,10" />
+		<Model position="-580,0,400" 		mesh="cube_orange.mesh" scale3D="10,10,10" />
+		<Model position="-580,0,-400" 		mesh="cube_orange.mesh" scale3D="10,10,10" />
+	
+		<Model position="-580,0,0" 			mesh="cube_orange.mesh" scale3D="10,10,10" />	-->
+	
+
+	<Model position="0,0,0" yaw=0 pitch=-90 scale3D="100,100,100"  mesh="ss_flag_room.mesh" />
+
+	</attached>
+	 <collisionShapes>
+		<BoxCollisionShape position="-125,116,0"    	 		halfExtents="130,0,125" />	<!--Boden oben mitte-->
+		<BoxCollisionShape position="-275,116,235"   yaw=55 	halfExtents="140,0,50" />	<!--Boden oben rechts-->
+		<BoxCollisionShape position="-275,116,-235"  yaw=-55  	halfExtents="140,0,50" />	<!--Boden oben links-->
+		<BoxCollisionShape position="-365,116,320"   yaw=35	 	halfExtents="100,0,50" />	<!--Boden oben rechts-->
+		<BoxCollisionShape position="-365,116,-320"  yaw=-35 	halfExtents="100,0,50" />	<!--Boden oben links-->
+		<BoxCollisionShape position="-520,156,380"   roll=-25	halfExtents="100,0,50" />	<!--Boden oben rechts-->
+		<BoxCollisionShape position="-520,156,-380"  roll=-25 	halfExtents="100,0,50" />	<!--Boden oben links-->
+		
+		
+		<BoxCollisionShape position="-80,0,100"    	 			halfExtents="80,100,0" />	<!--Wand oben rechts-->
+		<BoxCollisionShape position="-160,0,150"  	yaw=90 		halfExtents="50,200,0" />	<!--Wand oben rechts-->	
+		<BoxCollisionShape position="-220,0,260"  	yaw=55 		halfExtents="100,200,0" />	<!--Wand oben rechts-->
+		<BoxCollisionShape position="-360,0,390"  	yaw=33 		halfExtents="110,200,0" />	<!--Wand oben rechts-->
+		<BoxCollisionShape position="-600,16,430"  		 		halfExtents="200,200,0" />	<!--Wand unten rechts-->
+		<BoxCollisionShape position="-810,16,405"   yaw=-32 	halfExtents="150,200,0" />	<!--Wand unten rechts-->
+		<BoxCollisionShape position="-965,166,270"  yaw=-55 	halfExtents="150,50,0" />	<!--Wand unten rechts-->		
+		
+		<BoxCollisionShape position="-80,0,-100"    	 		halfExtents="80,100,0" />	<!--Wand oben links-->
+		<BoxCollisionShape position="-160,0,-150" 	yaw=-90		halfExtents="50,200,0" />	<!--Wand oben links-->	
+		<BoxCollisionShape position="-220,0,-260" 	yaw=-55		halfExtents="100,200,0" />	<!--Wand oben links-->
+		<BoxCollisionShape position="-360,0,-390" 	yaw=-33		halfExtents="110,200,0" />	<!--Wand oben links-->
+		<BoxCollisionShape position="-600,16,-430" 				halfExtents="200,200,0" />	<!--Wand unten links-->
+		<BoxCollisionShape position="-810,16,-405"  yaw=32		halfExtents="150,200,0" />	<!--Wand unten links-->
+		<BoxCollisionShape position="-965,166,-270" yaw=55		halfExtents="150,50,0" />	<!--Wand unten links-->
+		
+		<BoxCollisionShape position="-1045,166,0" 				halfExtents="0,50,160" />	<!--Wand unten mitte-->
+		
+			
+	
+		<BoxCollisionShape position="-650,200,0"    	 		halfExtents="400,0,450" />	<!--Boden unten-->
+	
+		<BoxCollisionShape position="-500,-200,0"     			halfExtents="400,0,400" />	<!--decke-->
+		<BoxCollisionShape position="-60,-84,0"     			halfExtents="60,0,100" />	<!--decke oben-->
+		
+		<BoxCollisionShape position="-1015,156,0"     			halfExtents="27,25,120" />	<!--Tisch-->		
+		<BoxCollisionShape position="-580,185,0"     				halfExtents="30,12,30" />	<!--Stufe "Mittelpkt"-->
+		<BoxCollisionShape position="-580,195,0"     				halfExtents="50,10,50" />	<!--Stufe "Mittelpkt"-->
+		
+		
+		<BoxCollisionShape position="-255,121,0"    	 		halfExtents="0,85,125" />	<!--Wand innen-->
+		<BoxCollisionShape position="-300,116,190"    yaw=-35	halfExtents="0,80,75" />	<!--Wand innen-->
+		<BoxCollisionShape position="-300,116,-190"   yaw=35	halfExtents="0,80,75" />	<!--Wand innen-->		
+		<BoxCollisionShape position="-410,116,290"    yaw=-55	halfExtents="0,80,75" />	<!--Wand innen-->
+		<BoxCollisionShape position="-410,116,-290"   yaw=55	halfExtents="0,80,75" />	<!--Wand innen-->
+		<BoxCollisionShape position="-500,185,328"    yaw=2		roll=-25	halfExtents="100,35,0" />	<!--Wand innen-->
+		<BoxCollisionShape position="-500,185,-328"   yaw=-2  	roll=-25	halfExtents="100,35,0" />	<!--Wand innen-->
+		
+		      
+     </collisionShapes>
+ 	   
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Machine -->
+<Template name=ss_machine>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+
+	<!-- Boxes helps to place collisionShapes -->
+	
+	<!--<Model position="0,80,0" 			mesh="cube_orange.mesh" scale3D="40,80,25" />	-->
+
+	<Model position="0,0,0" roll=0 scale3D="0.15,0.15,0.15" mesh="ss_machine.mesh" />
+
+	</attached>
+	 <collisionShapes>
+
+		<BoxCollisionShape position="0,80,0"		halfExtents="40,80,25" />	<!--whole machine-->
+      
+     </collisionShapes>
+ 	 -->   
+    
+ 	 </MovableEntity>   
+roll=180 mesh="ss_table.mesh" scale3D="25,25,25"
+</Template>
+
+
+<!-- Spacestation Element Table-->		
+<Template name=ss_table>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<!-- Boxes helps to place collisionShapes -->
+			
+	<!--<Model position="0,-32,0"		mesh="cube_orange.mesh" scale3D="60,32,40" />	-->
+	
+	<Model position="0,0,0"	roll=180 scale3D="25,25,25" mesh="ss_table.mesh"  />
+
+	</attached>
+	 <collisionShapes>
+	
+		<BoxCollisionShape position="0,-32,0"	yaw=15	halfExtents="60,32,40" />	<!--ganzer Tisch-->
+      
+	 </collisionShapes>
+
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Table (cracked) -->
+<Template name=ss_table_cracked>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+	
+	<!-- Boxes helps to place collisionShapes -->
+		
+	<!--<Model position="0,-32,0" 			mesh="cube_orange.mesh" scale3D="60,32,40" />	-->
+
+
+	<Model position="0,0,0" roll=180 scale3D="25,25,25" mesh="ss_table_cracked.mesh"  />
+
+	</attached>
+	 <collisionShapes>
+	
+		<BoxCollisionShape position="0,-32,0"		halfExtents="60,32,40" />	<!--ganzer Tisch-->
+      
+	 </collisionShapes>
+
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Cylinder -->
+<Template name=ss_cylinder>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+	
+	<!-- Boxes helps to place collisionShapes -->
+			
+	<!--<Model position="0,-40,0" 	yaw=15		mesh="cube_red.mesh" scale3D="7,65,25" />
+		<Model position="0,-40,0" 	yaw=45		mesh="cube_red.mesh" scale3D="7,65,25" />
+		<Model position="0,-40,0" 	yaw=75		mesh="cube_red.mesh" scale3D="7,65,25" />
+		<Model position="0,-40,0" 	yaw=105		mesh="cube_red.mesh" scale3D="7,65,25" />
+		<Model position="0,-40,0" 	yaw=135		mesh="cube_red.mesh" scale3D="7,65,25" />
+		<Model position="0,-40,0" 	yaw=165		mesh="cube_red.mesh" scale3D="7,65,25" />	-->
+	
+	
+	<Model position="0,0,0" roll=180 scale3D="25,25,25" mesh="ss_cylinder.mesh"  />
+
+	</attached>
+	 <collisionShapes>
+		
+		<BoxCollisionShape position="0,-40,0"	yaw=15	halfExtents="10,65,25" />	<!--Fuellung-->
+		<BoxCollisionShape position="0,-40,0"	yaw=45	halfExtents="10,65,25" />	<!--Fuellung-->
+		<BoxCollisionShape position="0,-40,0"	yaw=75	halfExtents="10,65,25" />	<!--Fuellung-->
+		<BoxCollisionShape position="0,-40,0"	yaw=105	halfExtents="10,65,25" />	<!--Fuellung-->
+		<BoxCollisionShape position="0,-40,0"	yaw=135	halfExtents="10,65,25" />	<!--Fuellung-->
+		<BoxCollisionShape position="0,-40,0"	yaw=165	halfExtents="10,65,25" />	<!--Fuellung-->
+		      
+	 </collisionShapes>
+
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Chair -->
+<Template name=ss_chair>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<!-- Boxes helps to place collisionShapes -->
+	
+	<!--<Model position="-5,18,0" 			mesh="cube_orange.mesh" scale3D="20,20,20" />
+		<Model position="-23,-30,0" 			mesh="cube_orange.mesh" scale3D="2,33,18" />	-->
+	
+
+	<Model position="0,0,0" roll=0 pitch=180 scale3D="20,20,20" mesh="ss_chair.mesh"  />
+
+	</attached>
+	 <collisionShapes>
+				
+		<BoxCollisionShape position="-5,18,0"    	 		halfExtents="20,20,20" />	<!--Unterer Teil-->
+		<BoxCollisionShape position="-23,-30,0"    	 		halfExtents="2,33,20" />	<!--Rueckenlaehne-->
+		
+	 </collisionShapes>
+
+    
+ 	 </MovableEntity>   
+
+</Template>
+
+
+<!-- Spacestation Element Wall -->
+<Template name=ss_wall>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+	
+	<!-- Boxes helps to place collisionShapes -->
+	
+	<!--<Model position="-78,0,0"		mesh="cube_orange.mesh" scale3D="2,100,100" />	-->
+	
+
+	<Model position="0,0,0" roll=0	pitch=180	scale3D="80,80,80" mesh="ss_wall.mesh"  />
+
+	</attached>
+	 <collisionShapes>
+	
+		<BoxCollisionShape position="-78,0,0"		halfExtents="2,100,100" />	<!--Flache Seite-->
+	
+	 </collisionShapes>
+
+    
+ 	 </MovableEntity>   
+
+</Template>
+	
+
+<!-- Spacestation Element Flag -->
+<Template name=ss_flag_aean>
+
+	<MovableEntity position="0,0,0">
+	<attached>
+
+	<!-- Boxes helps to place collisionShapes -->
+	
+	<!--<Model position="0,0,0" 			mesh="cube_orange.mesh" scale3D="2,160,2" />
+		<Model position="0,108,80" 		mesh="cube_orange.mesh" scale3D="1,50,80" />	-->
+	
+
+	<Model position="0,0,0" roll=0 scale3D="40,40,40" mesh="ss_flag_aean.mesh"  />
+
+	</attached>
+	 <collisionShapes>
+
+		<BoxCollisionShape position="0,0,0"    	 		halfExtents="2,160,2" />	<!--Mast-->
+		<BoxCollisionShape position="0,108,80"    	 	halfExtents="1,50,80" />	<!--Flagge-->
+      
+	 </collisionShapes>
+
+    
+ 	 </MovableEntity>   
+
+</Template>
+		
Index: /code/branches/RacingBots_FS18/data/levels/templates/ss_tube01.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/ss_tube01.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/ss_tube01.oxt	(revision 11817)
@@ -0,0 +1,20 @@
+<Template name=ss_tube01>
+
+<MovableEntity position="0,0,0">
+<attached>
+
+<Model position="0,0,0" yaw=0 pitch=180 roll=0 scale=1 mesh="ss_tube.mesh" />
+
+</attached>
+<!--    <collisionShapes>
+	<BoxCollisionShape position="0,8,17"      halfExtents="8,10,10" />
+	<BoxCollisionShape position="0,0,22"      halfExtents="18, 2, 10" />
+	<BoxCollisionShape position="0,0,9"      halfExtents="12, 2, 20" />
+	<BoxCollisionShape position="0,0,-18"      halfExtents="6, 2, 18" />
+      
+    </collisionShapes>
+ -->   
+    
+</MovableEntity>   
+ 
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/standardTurret.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/standardTurret.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/standardTurret.oxt	(revision 11817)
@@ -0,0 +1,40 @@
+<Template name=standardturret>
+  <Turret>
+    <attached>
+      <Model position="0,0,0" mesh="turretSocketFront.mesh" scale3D="10,10,10" pitch=-90/>
+      <Model position="0,0,0" mesh="turretSocketIn.mesh" scale3D="10,10,10" pitch=-90/>
+      <Model position="0,0,0" mesh="turretSocketTop.mesh" scale3D="10,10,10" pitch=-90/>
+      <Model position="0,0,0" mesh="turretSocketLeft.mesh" scale3D="10,10,10" pitch=-90/>
+      <Model position="0,0,0" mesh="turretSocketRight.mesh" scale3D="10,10,10" pitch=-90/>
+
+      <Turret position="0,0,-10" mass=100 maxPitch=90 maxYaw=90 maxAttackRadius=2000 minAttackRadius=30>
+        <attached>
+          <Model position="0,0,0" pitch="-90" roll="0" mesh="turretHead.mesh" scale3D="10,10,10"/>
+        </attached>
+        <collisionShapes>
+          <SphereCollisionShape radius="10"   position = "0,0,0"/>
+        </collisionShapes>
+        <controller>
+          <TurretController/>
+        </controller>
+        <?lua
+          include("../includes/weaponSettingsTurret.oxi")
+        ?>
+      </Turret>
+    </attached>
+    
+    <controller>
+      <TeamTargetProxy/>
+    </controller>
+  </Turret>
+</Template>
+
+<Template name=spaceshipturretcameras defaults=0>
+  <SpaceShip>
+    <camerapositions>
+      <CameraPosition position="0,10, 40" drag=true mouselook=true />
+      <CameraPosition position="0,20, 80" drag=true mouselook=true />
+      <CameraPosition position="0,30,120" drag=true mouselook=true />
+    </camerapositions>
+  </SpaceShip>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/templates/towerdefensetower.oxt
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/templates/towerdefensetower.oxt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/templates/towerdefensetower.oxt	(revision 11817)
@@ -0,0 +1,38 @@
+<Template name=towerdefensetower>
+  <TowerDefenseTower
+
+
+   	explosionchunks        = 6
+	shieldrechargerate=10 
+	shieldrechargewaittime=5 
+	collisionType="none" 
+	pitch="0" 
+	yaw="0" 
+	roll="0" 
+	maxPitch=90 
+	maxYaw=90 
+	maxAttackRadius=1000 
+	minAttackRadius=30
+   	team = 0
+
+
+  >
+  
+     <controller>
+     <TurretController team = 0/>
+  </controller>
+  
+    
+
+
+
+    <!--collisionShapes>
+
+    </collisionShapes-->
+
+
+    <?lua
+      include("../includes/weaponSettingsTurret.oxi")
+    ?>
+  </TowerDefenseTower>
+</Template>
Index: /code/branches/RacingBots_FS18/data/levels/testStars.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/testStars.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/testStars.oxw	(revision 11817)
@@ -0,0 +1,53 @@
+<LevelInfo
+ name = "Stars Testlevel"
+ description = "Level to test stars"
+ tags = "test"
+ screenshot = "starstestlevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipPirate.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+  >
+
+<!--Rocket position="-10, 3.5,800" velocity="0,0,-100">
+      <attached>
+        <Model pitch=180 position="0,0,0" scale=1.5 mesh="rocket_test.mesh" >
+          <attached>
+            <ParticleEmitter pitch=0 roll=0 position="0,5,0" source="Orxonox/laser" lifetime=2.0 loop=1 startdelay=3.0/>
+            <ParticleEmitter pitch=-90 roll=0 position="0,-5,0" source="Orxonox/particlecanon" lifetime=2.0 loop=1 startdelay=3.0/>
+            <ParticleEmitter pitch=-90 roll=0 position="0,0,-2" source="Orxonox/rocketfire" lifetime=2.0 loop=1 startdelay=3.0 />
+            <ParticleEmitter pitch=-90 roll=0 position="0,0,-2" source="Orxonox/smoke" lifetime=2.0 loop=1 startdelay=3.0 />
+          </attached>
+        </Model>
+      </attached>
+    </Rocket-->
+
+    <CreateStars numStars="6000" material="Examples/Flare" colour="1,1,1" radius=10000 colourDiff=0.1/>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+    <SpawnPoint position="0,0,100" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <ParticleEmitter position="0,10000,0" source="Orxonox/fog" />
+    <ParticleEmitter position="6000,7000,0" source="Orxonox/fog2" />
+    <ParticleEmitter position="-6000,-7000,0" source="Orxonox/fog3" />
+    <ParticleEmitter position="-6000,0,9000" source="Orxonox/fog4" />
+    <ParticleEmitter position="2000,-7000,-5963" source="Orxonox/fog3" />
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/testSwallow.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/testSwallow.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/testSwallow.oxw	(revision 11817)
@@ -0,0 +1,61 @@
+<LevelInfo
+ name = "Swallow Testlevel"
+ description = "Level to test the swallow spaceship."
+ tags = "test"
+ screenshot = "swallowtestlevel.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+<SpawnPoint position="<?lua print(math.sin(1.5) *40000) ?>,<?lua print(math.cos(1.5) *40000) ?>,<?lua print(500) ?>" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipswallow />
+
+
+<?lua
+max = 20
+for i = 1, max, 1
+do
+    x = math.sin(i/max*6)*40000
+    y = math.cos(i/max*6)*40000
+    z = i*100
+    ?>
+<?lua
+for k = 1, 25, 1
+do
+j = math.random()
+?>
+
+    <MovableEntity position="<?lua print(x + math.random() * 10000-2500) ?>,<?lua print(y + math.random() * 5000-2500) ?>,<?lua print(z + math.random() * 1000-500) ?>" <?lua if i == 5 then ?> collisionType=dynamic linearDamping=0.8 angularDamping=0 mass="<?lua print(j * 50) ?>" <?lua end ?> scale="<?lua print(j * 5) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+      <attached>
+        <Model position="0,0,0" scale="<?lua print(j * 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" />
+      </attached>
+      <?lua if i == 5 then ?><collisionShapes>
+        <SphereCollisionShape radius="<?lua print(j * 70) ?>" />
+      </collisionShapes> <?lua end ?>
+    </MovableEntity>
+<?lua
+end
+?>
+<?lua end ?>
+    <Planet position="0,0,0" scale=10000 pitch=-90 mesh="iceplanet.mesh" atmosphere="atmosphere1" rotationaxis="1,1,0" rotationrate="1" atmospheresize=224.0f imagesize=1024.0f />
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/tetris.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/tetris.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/tetris.oxw	(revision 11817)
@@ -0,0 +1,191 @@
+<LevelInfo
+ name = "Tetris"
+ description = "Tetris in space!"
+ tags = "minigame"
+ screenshot = "tetris.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("tetrisHUD.oxo")
+  include("templates/lodInformation.oxt")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipGhost.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/spaceshipSwallow.oxt")
+  include("templates/spaceshipTransporter.oxt")
+  include("templates/spaceshipH2.oxt")
+?>
+
+<Template name=tetrisstonecameras defaults=0>
+  <TetrisStone>
+    <camerapositions>
+      <CameraPosition position="55,75,200" absolute=true />
+    </camerapositions>
+  </TetrisStone>
+</Template>
+
+<Template name=tetrisstone>
+  <TetrisStone camerapositiontemplate=tetrisstonecameras>
+    <attached>
+      <Model position="0,0,0" mesh="CuboidBody.mesh" scale=4.5 />
+      <Model position="0,0,0" mesh="cube_orange.mesh" scale=4.3 />
+    </attached>
+  </TetrisStone>
+</Template>
+
+
+
+<Template name=tetrisbrickcameras defaults=0>
+  <TetrisBrick>
+    <camerapositions>
+      <CameraPosition position="55,75,200" absolute=true />
+      <!--CameraPosition position="0,50,160" drag=true mouselook=true />
+      <CameraPosition position="0,50,0" pitch=-90 drag=true mouselook=true /-->
+    </camerapositions>
+  </TetrisBrick>
+</Template>
+
+<Template name=tetrisbrick>
+  <TetrisBrick camerapositiontemplate=tetrisbrickcameras>
+  </TetrisBrick>
+</Template>
+
+
+<Level
+ plugins = "tetris"
+ gametype = "Tetris"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+<!--luke_grey_-_hypermode.ogg allgorythm-lift_up.ogg Fight1.ogg -->
+    <WorldAmbientSound
+      source="Ganymede.ogg"
+      looping="true"
+      playOnLoad="true"
+    />
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpawnPoint position="<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>" lookat="0,0,0" />
+    <?lua end ?>
+
+    <TetrisCenterpoint name=tetriscenter width=11 height=15 stoneSize=10 stoneTemplate=tetrisstone brickTemplate=tetrisbrick stoneSpeed=10 position="-55,-75,0">
+        <attached>
+            <Model position="55,-1,0" mesh="cube.mesh" scale3D="57,1,11" />
+            <Model position="-1,76,0" mesh="cube.mesh" scale3D="1,76,1" />
+            <Model position="111,76,0" mesh="cube.mesh" scale3D="1,76,1" />
+        </attached>
+        <!--collisionShapes>
+            <BoxCollisionShape position="55,-1,0"  halfExtents="57,1,11" />
+            <BoxCollisionShape position="-1,76,0"  halfExtents="1,76,1" />
+            <BoxCollisionShape position="111,76,0" halfExtents="1,76,1" />
+        </collisionShapes-->
+    </TetrisCenterpoint>
+
+<!-- ------------ insert eye candy here  ---------------- -->
+
+<!-- asteroidBelt(centerX, centerY, centerZ, yaw, pitch, segments, minSize, maxSize, radius0, radius1, count, fog) -->
+<!-- DONT DARE TO TURN THE FOG ON, whithout finding a better belt position -->
+    <?lua
+    	dofile("includes/asteroidField.lua")
+    	asteroidBelt(10000, 0, 0, -40, -90, 70, 100, 200, 24000, 20000, 500, 0)
+
+    ?>
+<!-- -------- 4 spaceships rotating around the tetris field --------- -->
+    <SpaceShip position="1000,-75,1" lookat="0,0,0">
+      <templates>
+        <Template link=spaceshipswallow />
+      </templates>
+      <controller>
+        <WaypointController team=10 accuracy=200>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=0 position="1000,-75,0" />
+            <Model mesh="cube.mesh" scale=0 position="650,-75,650" />
+            <Model mesh="cube.mesh" scale=0 position="-55,-75,1000" />
+            <Model mesh="cube.mesh" scale=0 position="-700,-75,650" />
+            <Model mesh="cube.mesh" scale=0 position="-1000,-75,0" />
+            <Model mesh="cube.mesh" scale=0 position="-700,-75,-650" />
+            <Model mesh="cube.mesh" scale=0 position="-55,-75,-1000" />
+            <Model mesh="cube.mesh" scale=0 position="650,-75,-650" />
+          </waypoints>
+        </WaypointController>
+      </controller>
+    </SpaceShip>
+    
+   <SpaceShip position="-500,-500,-400" lookat="0,0,0">
+      <templates>
+        <Template link=spaceshippirate />
+      </templates>
+      <controller>
+        <WaypointController team=10>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=0 position="-1000,-200,0" />
+            <Model mesh="cube.mesh" scale=0 position="-700,-150,650" />
+            <Model mesh="cube.mesh" scale=0 position="-55,-75,1000" />
+            <Model mesh="cube.mesh" scale=0 position="650,100,650" />          
+            <Model mesh="cube.mesh" scale=0 position="1000,150,0" />
+            <Model mesh="cube.mesh" scale=0 position="650,100,-650" />
+            <Model mesh="cube.mesh" scale=0 position="-55,0,-1000" />
+            <Model mesh="cube.mesh" scale=0 position="-700,-100,-650" />
+          </waypoints>
+        </WaypointController>
+      </controller>
+    </SpaceShip>
+    
+       <SpaceShip position="-700,200,651" lookat="1,0,0">
+      <templates>
+        <Template link=spaceshipghost />
+      </templates>
+      <controller>
+        <WaypointController team=10 accuracy=300>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=0 position="-700,200,650" />
+            <Model mesh="cube.mesh" scale=0 position="-55,100,1000" />
+            <Model mesh="cube.mesh" scale=0 position="650,0,650" />          
+            <Model mesh="cube.mesh" scale=0 position="1000,-100,0" />
+            <Model mesh="cube.mesh" scale=0 position="650,0,-650" />
+            <Model mesh="cube.mesh" scale=0 position="-55,100,-1000" />
+            <Model mesh="cube.mesh" scale=0 position="-700,200,-650" />
+            <Model mesh="cube.mesh" scale=0 position="-1000,300,0" />
+          </waypoints>
+        </WaypointController>
+      </controller>
+    </SpaceShip>
+    
+    <SpaceShip position="1000,-75,0" lookat="0,0,0">
+      <templates>
+        <Template link=spaceshipHtwo />
+      </templates>
+      <controller>
+        <WaypointController team=10>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=0 position="400,240,400" />
+            <Model mesh="cube.mesh" scale=0 position="-55,240,700" />
+            <Model mesh="cube.mesh" scale=0 position="-500,240,400" />
+            <Model mesh="cube.mesh" scale=0 position="-700,240,0" />
+            <Model mesh="cube.mesh" scale=0 position="-500,240,-400" />
+            <Model mesh="cube.mesh" scale=0 position="-55,240,-700" />
+            <Model mesh="cube.mesh" scale=0 position="400,240,-400" />
+            <Model mesh="cube.mesh" scale=0 position="700,240,0" />
+          </waypoints>
+        </WaypointController>
+      </controller>
+    </SpaceShip>
+    
+    
+    
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/theTimeMachine.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/theTimeMachine.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/theTimeMachine.oxw	(revision 11817)
@@ -0,0 +1,665 @@
+<LevelInfo
+ name = "The Time Machine"
+ description = "A simple level. The only goal is to defeat as much enemies as you can."
+ tags = "gametype"
+ screenshot = "thetimemachine.png"
+/>
+
+<?lua 
+    include("stats.oxo")
+    include("HUDTemplates3.oxo")
+    include("templates/lodInformation.oxt")
+    include("templates/spaceshipAssff.oxt")
+    include("templates/spaceshipPirate.oxt")
+?>
+
+<!--*****************************************************************************************************************************************************************************************-->
+<!--Including Template for triggering on player-->
+
+<Template name=spaceshipassffplayer>
+  <SpaceShip
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   engine                 = spaceshipassffengine
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 100
+   maxhealth         = 200
+   initialhealth     = 100
+
+   primaryThrust     = 100;
+   auxilaryThrust    = 30;
+   rotationThrust    = 25;
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+  >
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=-90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+      <DistanceTriggerBeacon name="PlayerDistanceTrigger" /> <!--added DistanceTriggerBeacon-->
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+<?lua
+  include("includes/weaponSettingsAssff.oxi")
+?>
+  </SpaceShip>
+</Template>
+
+<!--*****************************************************************************************************************************************************************************************-->
+
+<Level
+ gametype = "TeamDeathmatch"
+>
+    <templates>
+        <Template link=lodtemplate_default />
+    </templates>
+    <?lua include("includes/notifications.oxi") ?>
+    
+    <Scene
+        ambientlight="0.8,0.8,0.8"
+        skybox="Orxonox/skyBoxSomeNebula"
+    >
+
+        <Light type=directional position="0,0,0" direction="0, 0, 0" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 1.0, 0.9" />
+
+<!--CREATING SPAWNPOINTS_____________________________________________________________________________________________________________________________________________________________________-->
+<?lua for i=0,4,1 do
+    x=500
+?>    
+
+        <TeamSpawnPoint team=0 position="-4000,0,<?lua print(i*x-1000) ?>" direction="5000,0,<?lua print(i*x-1000) ?>" spawnclass=SpaceShip pawndesign=spaceshipassffplayer />
+<!--friendly spaceships spawnpoints-->
+        <!-- TeamSpawnPoint team=0 position="-4000,0,<?lua print(i*x-1000) ?>" lookat="5000,0,<?lua print(i*x-1000) ?>" spawnclass=SpaceShip pawndesign=spaceshipassff /-->
+
+<!--enemy spaceship spawnpoint-->
+        <!--TeamSpawnPoint team=1 position="4000,0,<?lua print(i*x-1000) ?>" lookat="-5000,0,<?lua print(i*x-1000) ?>" spawnclass=SpaceShip pawndesign=spaceshippirate /-->
+<?lua end ?>
+
+<!--CREATING SPAWNPOINTS END______________________________________________________________________________________________________________________________________________________________-->
+
+
+<!--Triggers (used for the Time Machine effect)___________________________________________________________________________________________________________________________________________-->
+    
+        <!--TRIGGERS IF THE PLAYERS REACHES THE "TIME MACHINE"-->
+        <DistanceTrigger name="EnterTimeMachine" position="0,0,0" distance="100" target="Pawn" beaconMode="identify" targetname="PlayerDistanceTrigger" >
+            <attached>
+                <Billboard position="0,0,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+                <Billboard position="100,0,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+                <Billboard position="0,100,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+                <Billboard position="0,0,100" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+                <Billboard position="-100,0,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+                <Billboard position="0,-100,0" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+                <Billboard position="0,0,-100" material="Examples/Flare" colour="0, 0, 1" scale=1/>
+            </attached>
+        </DistanceTrigger>
+
+        <EventTrigger switch=true name=trigger4>
+            <events>
+                <trigger>
+                    <EventListener event=BotDied />
+                </trigger>
+            </events>
+        </EventTrigger>
+
+        <!-- This Trigger flips to true if the player is in the TimeMachine and shoots another player and flips right back after that. -->
+        <Trigger name=trigger1 mode=and >
+            <EventTrigger name=trigger6>
+                <events>
+                    <trigger>
+                        <EventListener event=EnterTimeMachine />
+                    </trigger>
+                </events>
+            </EventTrigger>
+            <EventTrigger switch=true name=trigger4>
+                <events>
+                    <trigger>
+                        <EventListener event=BotDied />
+                        <EventListener event=trigger2 />
+                    </trigger>
+                </events>
+            </EventTrigger>
+            <EventTrigger invert=true name=trigger5>
+                <events>
+                    <trigger>
+                        <EventListener event=trigger2 />
+                    </trigger>
+                </events>
+            </EventTrigger>
+        </Trigger>
+
+        <!-- This Trigger is true if the player is in the TimeMachine and has shot another player -->
+        <EventTrigger name=trigger2 switch=true >
+            <events>
+                <trigger>
+                    <EventListener event=trigger1 />
+                    <EventListener event=trigger3 />
+                </trigger>
+            </events>
+        </EventTrigger>
+
+        <!-- This Trigger flips trigger2 back to false after the player has left the TimeMachine. -->
+        <Trigger name=trigger3 mode=and >
+            <EventTrigger>
+                <events>
+                    <trigger>
+                        <EventListener event=trigger2 />
+                    </trigger>
+                </events>
+            </EventTrigger>
+            <EventTrigger invert=true>
+                <events>
+                    <trigger>
+                        <EventListener event=EnterTimeMachine />
+                    </trigger>
+                </events>
+            </EventTrigger>
+        </Trigger>
+
+    
+<!--Triggers (used for the Time Machine effect)_____________________________________________________________________________________________________________________________________________-->
+
+<!--Creating Spaceships_____________________________________________________________________________________________________________________________________________________________________-->
+    
+<?lua for i=0,5,1 do 
+    y=math.random(-500,500)
+    z=math.random(-1000,1000)
+    y2=math.random(-500,500)
+    z2=math.random(-1000,1000)
+    health=230
+    addh=100
+?>
+    
+        <EventTrigger name="BotDied" >
+            <events>
+                <trigger>
+                    <SpaceShip position="-4000,<?lua print(y) ?>,<?lua print(z) ?>" lookat="1000,<?lua print(y) ?>,<?lua print(z) ?>" health=<?lua print(health) ?> maxhealth=<?lua print(health) ?> initialhealth=<?lua print(health) ?> >
+                        <templates>
+                            <Template link=spaceshipassff />
+                         </templates>
+                          <controller>
+                            <WaypointPatrolController alertnessradius=1000 team=0 active=1 >
+                                <waypoints>
+                                    <Model mesh="cube.mesh" scale=0 position="1000,<?lua print(math.random(-1000,1000)) ?>,<?lua print(math.random(-1000,1000)) ?>" />
+                                </waypoints>
+                                <events>
+                                    <activity>
+                                        <Trigger mode=or>
+                                            <EventTrigger invert=true>
+                                                <events>
+                                                    <trigger>
+                                                        <EventListener event=EnterTimeMachine />
+                                                    </trigger>
+                                                </events>
+                                            </EventTrigger>
+                                            <EventTrigger>
+                                                <events>
+                                                    <trigger>
+                                                        <EventListener event=trigger2 />
+                                                    </trigger>
+                                                </events>
+                                            </EventTrigger>
+                                        </Trigger>
+                                    </activity>
+                                </events>
+                            </WaypointPatrolController>
+                          </controller>
+                    </SpaceShip>
+                </trigger>
+            </events>
+        </EventTrigger>
+
+        <EventTrigger name="BotDied" >
+            <events>
+                <trigger>
+                    <SpaceShip position="4000,<?lua print(y2) ?>,<?lua print(z2) ?>" lookat="-1000,<?lua print(y2) ?>, <?lua print(z2) ?>" health=<?lua print(health+addh) ?> maxhealth=<?lua print(health+addh) ?> initialhealth=<?lua print(health+addh) ?> >
+                        <templates>
+                            <Template link=spaceshippirate />
+                         </templates>
+                          <controller>
+                            <WaypointPatrolController alertnessradius=1000 team=1 active=1 >
+                                <waypoints>
+                                    <Model mesh="cube.mesh" scale=0 position="-1000,<?lua print(math.random(-1000,1000)) ?>, <?lua print(math.random(-1000,1000)) ?>" />
+                                </waypoints>
+                                <events>
+                                    <activity>
+                                        <Trigger mode=or>
+                                            <EventTrigger invert=true>
+                                                <events>
+                                                    <trigger>
+                                                        <EventListener event=EnterTimeMachine />
+                                                    </trigger>
+                                                </events>
+                                            </EventTrigger>
+                                            <EventTrigger>
+                                                <events>
+                                                    <trigger>
+                                                        <EventListener event=trigger2 />
+                                                    </trigger>
+                                                </events>
+                                            </EventTrigger>
+                                        </Trigger>
+                                    </activity>
+                                </events>
+                            </WaypointPatrolController>
+                          </controller>
+                    </SpaceShip>
+                </trigger>
+            </events>
+        </EventTrigger>
+<?lua end ?>
+
+<!--Creating Spaceships_____END_____________________________________________________________________________________________________________________________________________________________-->
+
+<!--BILLBOARD IN THE MIDDLE OF THE BATTLEFIELD-->
+        <Billboard position="0,0,0" colour="1.0,1.0,1.0" material="Flares/backlightflare" scale=1 />
+    
+<!--TIME MACHINE____________________________________________________________________________________________________________________________________________________________________________-->
+<ForceField mode="invertedSphere" position="0,0,0" velocity=50000 diameter=6500 length=500 />
+        <StaticEntity>
+            <attached>
+                <MovableEntity position="0,0,0">
+                    <attached>
+<!--MIDDLE-->
+<?lua for i=0,2,1 do ?>
+                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=<?lua print(-255-i*120) ?> >
+                            <attached>
+                                <Billboard position="<?lua print(10+i*10) ?>,<?lua print(-10-i*10) ?>,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                            </attached>
+                        </MovableEntity>
+    
+                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=<?lua print(-245-i*90) ?> >
+                            <attached>
+                                <Billboard position="<?lua print(10+i*20) ?>,<?lua print(-10-i*20) ?>,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                <Billboard position="<?lua print(-10-i*20) ?>,<?lua print(10+i*20) ?>,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                            </attached>
+                        </MovableEntity>
+    
+                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=<?lua print(265+i*110) ?> >
+                            <attached>
+                                <Billboard position="<?lua print(10+i*20) ?>,0,<?lua print(-10-i*20) ?>" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                <Billboard position="<?lua print(-10-i*20) ?>,0,<?lua print(10+i*20) ?>" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                            </attached>
+                        </MovableEntity>
+    
+                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=<?lua print(240+i*80) ?> >
+                            <attached>
+                                <Billboard position="<?lua print(15+i*30) ?>,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                <Billboard position="<?lua print(-15-i*30) ?>,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                            </attached>
+                        </MovableEntity>
+
+                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=<?lua print(232+i*70) ?> >
+                            <attached>
+                                <Billboard position="0,<?lua print(15+i*30) ?>,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                <Billboard position="0,<?lua print(-15-i*30) ?>,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                            </attached>
+                        </MovableEntity>
+<?lua end ?>
+
+
+<!--FIRST DISTANT PAIR-->
+<?lua for i=0,1,1 do ?>
+                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=10 >
+                            <attached>
+                                <MovableEntity position="<?lua print(1500-3000*i) ?>,0,0">
+                                    <attached>
+                                        <ForceField position="0,0,0" mode="sphere" diameter=500 velocity=100000 />
+                                        <Billboard position="0,0,0" material="Examples/Flare" colour="1.0,1.0,1.0" scale=0.3/>
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=-255 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=-245 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=265 >
+                                            <attached>
+                                                <Billboard position="10,0,-10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,0,10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=240 >
+                                            <attached>
+                                                <Billboard position="15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=232 >
+                                            <attached>
+                                                <Billboard position="0,15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="0,-15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                    </attached>
+                                </MovableEntity>
+                            </attached>
+                        </MovableEntity>
+<?lua end ?>
+<!--SECOND DISTANT PAIR-->
+<?lua for i=0,1,1 do ?>
+                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=8 >
+                            <attached>
+                                <MovableEntity position="0,<?lua print(1500-3000*i) ?>,0">
+                                    <attached>
+                                        <ForceField position="0,0,0" mode="sphere" diameter=500 velocity=100000 />
+                                        <Billboard position="0,0,0" material="Examples/Flare" colour="1.0,1.0,1.0" scale=0.3/>
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=-255 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=-245 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=265 >
+                                            <attached>
+                                                <Billboard position="10,0,-10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,0,10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=240 >
+                                            <attached>
+                                                <Billboard position="15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=232 >
+                                            <attached>
+                                                <Billboard position="0,15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="0,-15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                    </attached>
+                                </MovableEntity>
+                            </attached>
+                        </MovableEntity>
+<?lua end ?>
+<!--THIRD DISTANT PAIR-->
+<?lua for i=0,1,1 do ?>
+                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=9 >
+                            <attached>
+                                <MovableEntity position="<?lua print(1000-2000*i) ?>,<?lua print(-1000+2000*i) ?>,0">
+                                    <attached>
+                                        <ForceField position="0,0,0" mode="sphere" diameter=500 velocity=100000 />
+                                        <Billboard position="0,0,0" material="Examples/Flare" colour="1.0,1.0,1.0" scale=0.3/>
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=-255 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=-245 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=265 >
+                                            <attached>
+                                                <Billboard position="10,0,-10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,0,10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=240 >
+                                            <attached>
+                                                <Billboard position="15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=232 >
+                                            <attached>
+                                                <Billboard position="0,15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="0,-15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                    </attached>
+                                </MovableEntity>
+                            </attached>
+                        </MovableEntity>
+<?lua end ?>
+<!--FOURTH DISTANT PAIR-->
+<?lua for i=0,1,1 do ?>
+                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=12 >
+                            <attached>
+                                <MovableEntity position="<?lua print(1000-2000*i) ?>,<?lua print(-1000+2000*i) ?>,0">
+                                    <attached>
+                                        <ForceField position="0,0,0" mode="sphere" diameter=500 velocity=100000 />
+                                        <Billboard position="0,0,0" material="Examples/Flare" colour="1.0,1.0,1.0" scale=0.3/>
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=-255 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=-245 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=265 >
+                                            <attached>
+                                                <Billboard position="10,0,-10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,0,10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=240 >
+                                            <attached>
+                                                <Billboard position="15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=232 >
+                                            <attached>
+                                                <Billboard position="0,15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="0,-15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                    </attached>
+                                </MovableEntity>
+                            </attached>
+                        </MovableEntity>
+<?lua end ?>
+<!--FIFTH DISTANT PAIR-->
+<?lua for i=0,1,1 do ?>
+                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=11 >
+                            <attached>
+                                <MovableEntity position="<?lua print(1000-2000*i) ?>,0,<?lua print(-1000+2000*i) ?>">
+                                    <attached>
+                                        <ForceField position="0,0,0" mode="sphere" diameter=500 velocity=100000 />
+                                        <Billboard position="0,0,0" material="Examples/Flare" colour="1.0,1.0,1.0" scale=0.3/>
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,1,0" rotationrate=-255 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=-245 >
+                                            <attached>
+                                                <Billboard position="10,-10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,10,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,1" rotationrate=265 >
+                                            <attached>
+                                                <Billboard position="10,0,-10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-10,0,10" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="0,1,0" rotationrate=240 >
+                                            <attached>
+                                                <Billboard position="15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="-15,0,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                        <MovableEntity    position="0,0,0" rotationaxis="1,0,0" rotationrate=232 >
+                                            <attached>
+                                                <Billboard position="0,15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                                <Billboard position="0,-15,0" material="Examples/Flare" colour="0.8, 0.8, 0.8" scale=0.1/>
+                                            </attached>
+                                        </MovableEntity>
+
+                                    </attached>
+                                </MovableEntity>
+                            </attached>
+                        </MovableEntity>
+<?lua end ?>
+                    </attached>
+                </MovableEntity>
+            </attached>
+        </StaticEntity>
+    
+
+<!--TIME MACHINE END____________________________________________________________________________________________________________________________________________________________________-->
+
+<!--Forcefields_________________________________________________________________________________________________________________________________________________________________________-->
+
+<!--NO 1-->
+        <ForceField position="-2500,0,800" direction="1,0,0" diameter=500 velocity=5000 length=1000 />
+        <MovableEntity position="-2500,0,800">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0,0" scale=2/>
+                <?lua for i=0,20,1 do ?>
+                    <Billboard position="<?lua print(i*200) ?>,0,-100" material="Examples/Flare" colour="0.5,0,0" scale=1/>
+                    <Billboard position="<?lua print(i*200) ?>,0,100" material="Examples/Flare" colour="0.5,0,0" scale=1/>
+                <?lua end ?>
+                </attached>
+        </MovableEntity>
+<!--NO 2-->
+        <ForceField position="2500,0,-800" direction="-1,0,0" diameter=500 velocity=5000 length=1000 />
+        <MovableEntity position="2500,0,-800">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0,0.5,0" scale=2/>
+                <?lua for i=0,20,1 do ?>
+                    <Billboard position="<?lua print(-i*200) ?>,0,-100" material="Examples/Flare" colour="0,0.5,0" scale=1/>
+                    <Billboard position="<?lua print(-i*200) ?>,0,100" material="Examples/Flare" colour="0,0.5,0" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+    
+<!--NO 3-->
+        <ForceField position="-2500,0,-600" direction="0.75,0.5,1" diameter=500 velocity=5000 length=1000 />
+        <MovableEntity position="-2500,0,-600">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0,0.5" scale=2/>
+                <?lua for i=0,20,1 do ?>
+                    <Billboard position="<?lua print(i*115-100) ?>,<?lua print(i*75) ?>,<?lua print(i*150) ?>" material="Examples/Flare" colour="0.5,0,0.5" scale=1/>
+                    <Billboard position="<?lua print(i*115+100) ?>,<?lua print(i*75) ?>,<?lua print(i*150) ?>" material="Examples/Flare" colour="0.5,0,0.5" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+
+<!--NO 4-->
+        <ForceField position="2500,0,600" direction="-0.75,-0.5,-1" diameter=500 velocity=5000 length=1000 />
+        <MovableEntity position="2500,0,600">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0,0.5,0.5" scale=2/>
+                <?lua for i=0,20,1 do ?>
+                    <Billboard position="<?lua print(i*(-115)-100) ?>,<?lua print(i*(-75)) ?>,<?lua print(i*(-150)) ?>" material="Examples/Flare" colour="0,0.5,0.5" scale=1/>
+                    <Billboard position="<?lua print(i*(-115)+100) ?>,<?lua print(i*-(75)) ?>,<?lua print(i*(-150)) ?>" material="Examples/Flare" colour="0,0.5,0.5" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+
+<!--NO 5 (samller)-->
+        <ForceField position="0,-500,500" direction="0,1,0" diameter=500 velocity=3000 length=1000 />
+        <MovableEntity position="0,-500,500">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0.5,0" scale=2/>
+                <?lua for i=0,15,1 do ?>
+                    <Billboard position="0,<?lua print(i*100) ?>,0" material="Examples/Flare" colour="0.5,0.5,0" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+
+<!--No 6 (smaller)-->
+        <ForceField position="0,500,-500" direction="0,-1,0" diameter=500 velocity=3000 length=1000 />
+        <MovableEntity position="0,500,-500">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0.3,0.2" scale=2/>
+                <?lua for i=0,15,1 do ?>
+                    <Billboard position="0,<?lua print(i*(-100)) ?>,0" material="Examples/Flare" colour="0.5,0.3,0.2" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+
+<!--No 7 (smaller)-->
+        <ForceField position="500,0,-500" direction="0,0,1" diameter=500 velocity=2500 length=750 />
+        <MovableEntity position="500,0,-500">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.5,0.4,0.6" scale=2/>
+                <?lua for i=0,8,1 do ?>
+                    <Billboard position="0,0,<?lua print(i*(100)) ?>" material="Examples/Flare" colour="0.5,0.4,0.6" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+
+<!--No 8 (smaller)-->
+        <ForceField position="-500,0,500" direction="0,0,-1" diameter=500 velocity=2500 length=750 />
+        <MovableEntity position="-500,0,500">
+            <attached>
+                <Billboard position="0,0,0" material="Flares/ringflare2" colour="0.7,0.4,0.1" scale=2/>
+                <?lua for i=0,8,1 do ?>
+                    <Billboard position="0,0,<?lua print(i*(-100)) ?>" material="Examples/Flare" colour="0.7,0.4,0.1" scale=1/>
+                <?lua end ?>
+            </attached>
+        </MovableEntity>
+
+<!--Invisible Forcefield (immediatly sends the player to the time machine)-->
+        <ForceField position="-2500,2500,800" direction="1,-1,-0.32" diameter=200 velocity=10000 length=880 />
+        <Billboard position="-2500,2500,800" material="Examples/Flare" colour="1,1,1" /> <!--This Billboard looks like a star on the Skybox-->
+    
+    
+    </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/towerDefense.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/towerDefense.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/towerDefense.oxw	(revision 11817)
@@ -0,0 +1,528 @@
+<!-- TODO: Update the level's image-->
+
+<!-- See TowerDefenseReadme.txt for Information on this file -->
+
+<LevelInfo
+ name = "Tower Defense"
+ description = "Defend your Spacestation from incoming waves."
+ tags = "minigame"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("towerdefenseHUD.oxo")
+  include("templates/lodInformation.oxt")
+  include("includes/weaponSettingsTurret.oxi")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/standardTurret.oxt")
+?>
+
+<Template name=selectercameras defaults=0>
+  <TowerDefenseSelecter>
+    <camerapositions>
+      <CameraPosition position="0,0,1300" lookat="0,0,0" absolute=true drag=true mouselook=true/>
+    </camerapositions>
+  </TowerDefenseSelecter>
+</Template>
+
+<Template name=selectertemplate>
+  <TowerDefenseSelecter team=0 camerapositiontemplate=selectercameras>
+    <attached>
+      <Model position="0,0,0" pitch=90 mesh="TD_Selection.mesh" scale=25/>
+    </attached>
+  </TowerDefenseSelecter>
+</Template>
+
+<Template name=tower1template>
+  <TowerDefenseTower
+  explosionchunks=6
+  shieldrechargerate=10 
+  shieldrechargewaittime=5 
+  collisionType="none" 
+  pitch="0" 
+  yaw="0" 
+  roll="0" 
+  maxPitch=360 
+  maxYaw=360 
+  maxAttackRadius=1000 
+  minAttackRadius=0
+  team=0
+  >
+    <controller>
+       <TurretController team = 0/>
+    </controller>
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <HsW01 mode=0 munitionpershot=0 muzzleoffset="0,0,0" damage=2 shielddamage=1 material="Flares/point_lensflare" delay=0/>
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LaserMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10 replenishamount=1 replenishinterval=0.3/>
+    </munition>
+  </TowerDefenseTower>
+</Template>
+
+<Template name=tower2template>
+  <TowerDefenseTower
+  explosionchunks=6
+  shieldrechargerate=10 
+  shieldrechargewaittime=5 
+  collisionType="none" 
+  pitch="0" 
+  yaw="0" 
+  roll="0" 
+  maxPitch=360 
+  maxYaw=360 
+  maxAttackRadius=1000 
+  minAttackRadius=0
+  team=0
+  >
+    <controller>
+       <TurretController team = 0/>
+    </controller>
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>          
+          <LightningGun mode=0 munitionpershot=0 muzzleoffset="0,0,0" damage=2 shielddamage=4 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <LightningMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+    </munition>
+    <attached>
+      <Backlight position="0,0,0" scale=2.0 colour="0.4, 0.0, 1.0" width=10 length=10 lifetime=0.3 elements=20 trailmaterial="Trail/backlighttrail" material="Examples/Flare" loop=1 />
+    </attached>    
+  </TowerDefenseTower>
+</Template>
+
+<Template name=tower3template>
+  <TowerDefenseTower
+  explosionchunks=6
+  shieldrechargerate=10 
+  shieldrechargewaittime=5 
+  collisionType="none" 
+  pitch="0" 
+  yaw="0" 
+  roll="0" 
+  maxPitch=360 
+  maxYaw=360 
+  maxAttackRadius=1000 
+  minAttackRadius=0
+  team=0
+  >
+    <controller>
+       <TurretController team = 0/>
+    </controller>
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <SplitGun mode=0 munitionpershot=0 damage=9.3 muzzleoffset=" 1.6, 1.3, -2.0" splittime=0.2 numberofsplits=2 numberofchilds=5 spread=0.1 damagereduction=3.0 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <SplitMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+    </munition>
+  </TowerDefenseTower>
+</Template>
+
+<Template name=tower4template>
+  <TowerDefenseTower
+  explosionchunks=6
+  shieldrechargerate=10 
+  shieldrechargewaittime=5 
+  collisionType="none" 
+  pitch="0" 
+  yaw="0" 
+  roll="0" 
+  maxPitch=360 
+  maxYaw=360 
+  maxAttackRadius=1000 
+  minAttackRadius=0
+  team=0
+  >
+    <controller>
+       <TurretController team = 0/>
+    </controller>
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <RocketFire mode=0 munitionpershot=0 muzzleoffset="0,0,0" damage=2 shielddamage=4 fuel=10/>  
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <RocketMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+    </munition>
+      <attached>
+      <ParticleSpawner position="0,0,0" source="Orxonox/sparks" lifetime=3.0 autostart=1 loop=1 />
+    </attached>
+  </TowerDefenseTower>
+</Template>
+
+<Template name=tower5template>
+  <TowerDefenseTower
+  explosionchunks=6
+  shieldrechargerate=10 
+  shieldrechargewaittime=5 
+  collisionType="none" 
+  pitch="0" 
+  yaw="0" 
+  roll="0" 
+  maxPitch=360 
+  maxYaw=360 
+  maxAttackRadius=1000 
+  minAttackRadius=0
+  team=0
+  >
+    <controller>
+       <TurretController team = 0/>
+    </controller>
+    <weaponslots>
+      <WeaponSlot position="0,0,0" />
+    </weaponslots>
+    <weaponsets>
+      <WeaponSet firemode=0 />
+    </weaponsets>
+    <weaponpacks>
+      <WeaponPack>
+        <links>
+          <DefaultWeaponmodeLink firemode=0 weaponmode=0 />
+        </links>
+        <Weapon>
+          <IceGun mode=0 munitionpershot=0 delay=0.125 damage=9.3 muzzleoffset=" 0,0,0" freezefactor=0.5 freezetime=2.0 />
+        </Weapon>
+      </WeaponPack>
+    </weaponpacks>
+    <munition>
+      <IceMunition initialmagazines=1 maxmagazines=1 munitionpermagazine=10/>
+    </munition>
+  </TowerDefenseTower>
+</Template>
+
+<Template name=enemytowerdefense1>
+  <TowerDefenseEnemy
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 15
+   maxhealth         = 15
+   initialhealth     = 15
+
+   shieldhealth        = 15
+   initialshieldhealth = 15
+   maxshieldhealth     = 15
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 1000
+   auxilaryThrust    = 30
+   rotationThrust    = 80
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 10
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"   
+  >
+
+    <engines>
+      <MultiStateEngine position=" 7.6, 0, 6" template=spaceshipassffengine />
+      <MultiStateEngine position="-7.6, 0, 0" template=spaceshipassffengine />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=90 pitch=90 roll=0 scale=4 mesh="assff.mesh" />
+      <BlinkingBillboard position="17,-1.5,0" material="Examples/Flare" colour="1.0, 0.5, 0.3" amplitude=0.1 frequency=0.5 quadratic=1 />
+      <BlinkingBillboard position="-17,-1.5,0" material="Examples/Flare" colour="0.5, 1.0, 0.3" amplitude=0.1 frequency=0.5 phase=180 quadratic=1 />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <controller>
+       <WaypointController accuracy = 50/>
+    </controller>
+  </TowerDefenseEnemy>
+</Template>
+
+<Template name=enemytowerdefense2>
+  <TowerDefenseEnemy
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 30
+   maxhealth         = 30
+   initialhealth     = 30
+
+   shieldhealth        = 0
+   initialshieldhealth = 0
+   maxshieldhealth     = 0
+   shieldabsorption    = 0.8
+   shieldrechargerate = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 80
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+
+    <engines>
+      <Engine position=" 0, 0, 0" 
+        boostfactor    = 2
+        speedfront     = 100
+        speedback      =  50
+        speedleftright =  50
+        speedupdown    =  50        
+        accelerationfront     = 500
+        accelerationbrake     = 500
+        accelerationback      =  125
+        accelerationleftright =  125
+        accelerationupdown    =  125
+      />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=0 pitch=0 roll=0 scale=2.5 mesh="JumpEnemy3.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes> 
+    <controller>
+       <WaypointController accuracy = 50/>
+    </controller>
+  </TowerDefenseEnemy>
+</Template>
+
+<Template name=enemytowerdefense3>
+  <TowerDefenseEnemy
+   hudtemplate            = spaceshiphud
+   camerapositiontemplate = spaceshipassffcameras
+   spawnparticlesource    = "Orxonox/fairytwirl"
+   spawnparticleduration  = 3
+   explosionchunks        = 6
+
+   health            = 15
+   maxhealth         = 15
+   initialhealth     = 15
+   
+   shieldhealth        = 5
+   initialshieldhealth = 5
+   maxshieldhealth     = 5
+   shieldabsorption    = 0.8
+   shieldrechargerate  = 1
+   shieldrechargewaittime = 1
+
+   primaryThrust     = 100
+   auxilaryThrust    = 30
+   rotationThrust    = 80
+
+   lift = 1;
+   stallSpeed = 220;
+
+   boostPower            = 15
+   boostPowerRate        = 1
+   boostRate             = 5
+   boostCooldownDuration = 10
+
+   shakeFrequency = 15
+   shakeAmplitude = 9
+
+   collisionType     = "dynamic"
+   mass              = 100
+   linearDamping     = 0.7
+   angularDamping    = 0.9999999
+
+   explosionSound = "sounds/Explosion2.ogg"
+  >
+
+    <engines>
+      <Engine position=" 0, 0, 0" 
+        boostfactor    = 2
+        speedfront     = 300
+        speedback      =  300
+        speedleftright =  300
+        speedupdown    =  300         
+        accelerationfront     = 500
+        accelerationbrake     = 500
+        accelerationback      =  500
+        accelerationleftright =  500
+        accelerationupdown    =  500
+      />
+    </engines>
+    <attached>
+      <Model position="0,0,0" yaw=0 pitch=0 roll=0 scale=2.5 mesh="JumpEnemy4.mesh" />
+    </attached>
+    <collisionShapes>
+      <BoxCollisionShape position="0,0,0"      halfExtents="10, 3, 5" />
+      <BoxCollisionShape position="13,-1.3,0"  halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="-13,-1.3,0" halfExtents="3, 1, 2" />
+      <BoxCollisionShape position="0,0,7"      halfExtents="3, 2, 2" />
+      <BoxCollisionShape position="0,0.1,-11"  halfExtents="2.2, 1.8, 6" />
+      <BoxCollisionShape position="0,0.1,-19"  halfExtents="1.4, 1, 2" />
+    </collisionShapes>
+    <controller>
+       <WaypointController accuracy = 50/>
+    </controller>
+  </TowerDefenseEnemy>
+</Template>
+
+<Level plugins = "towerdefense" gametype = "TowerDefense">
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+
+    <SpawnPoint team=0 position="0,0,0"/> 
+
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_S1.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_S2.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_S3.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_S4.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_S5.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_T1.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_T2.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_T3.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_T4.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_T5.mesh" scale=1/>
+    <Model position="0,0,10000" lodLevel=1 mesh="TD_F1.mesh" scale=1/>
+
+    <!-- PlayField -->
+    <TowerDefenseCenterpoint
+    name=towerdefensecenter
+    selecterTemplate=selectertemplate
+    tower1Template=tower1template
+    tower2Template=tower2template
+    tower3Template=tower3template
+    tower4Template=tower4template
+    tower5Template=tower5template
+    tower1Cost=100
+    tower2Cost=100
+    tower3Cost=100
+    tower4Cost=100
+    tower5Cost=100
+    fields="F1F1F1R1I1I1I1I1O1F1F1F1F1F1F1F1
+            F1F1F1I2F1F1F1F1F1F1F1F1F1F1F1F1
+            F1F1F1I2F1F1F1F1F1F1F1F1F1F1F1F1
+            F1F1F1I2F1F1F1F1F1F1F1Y1Y1Y1F1F1
+            F1F1F1I2F1F1F1F1F1F1F1F1F1F1F1F1
+            F1F1F1I2F1F1F1F1F1F1F1Y1Y1Y1F1F1
+            F1F1F1R2I3I3I3I3L3F1F1F1F1F1F1F1
+            F1F1F1F1F1F1F1F1I2F1F1F1F1F1F1F1
+            F1F1F1F1F1F1F1F1I2F1F1F1F1F1F1F1
+            X1I1I1I1R0F1F1F1I2F1F1F1F1F1F1F1
+            F1F1F1F1I0F1F1F1I2F1F1F1F1F1F1F1
+            F1F1F1F1I0F1F1F1I2F1F1F1F1F1F1F1
+            F1F1F1F1L1I1I1I1L2F1F1F1F1F1F1F1
+            F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1
+            F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1
+            F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1"
+    width=16
+    height=16
+    tileScale=100
+    position="0,0,0"
+    direction="0,0,0"
+    collisionType=dynamic
+    mass=100000
+    >
+      <camerapositions>
+        <CameraPosition position="0,0,1400" lookat="0,0,0" absolute=true />
+      </camerapositions>    
+    </TowerDefenseCenterpoint>
+
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/turretTest.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/turretTest.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/turretTest.oxw	(revision 11817)
@@ -0,0 +1,57 @@
+<!-- -->
+
+<LevelInfo
+ name = "turret Test"
+ description = "A level to test turrets with."
+ tags = "test"
+ screenshot = "emptylevel.png"
+/>
+
+<?lua
+  include("stats.oxo")
+  include("HUDTemplates3.oxo")
+  include("templates/lodInformation.oxt")
+?>
+
+<?lua
+  include("templates/spaceshipAssff.oxt")
+  include("templates/standardTurret.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+    ambientlight = "0.8, 0.8, 0.8"
+    skybox       = "Orxonox/Starbox"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0"/>
+    <SpawnPoint team=0 position="-200,0,0" lookat="0,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+<SpaceShip position = "0,0,800" collisionType="dynamic" team=10>
+  <controller>
+    <TeamTargetProxy team=10/>
+  </controller>
+  <attached>
+    <Model position="0,0,0" mesh="plane.mesh" scale3D="20,20,20" pitch=-90/>
+
+    <?lua for i = 1, 10, 1 do ?>
+      <Turret position="<?lua print(150-i*30) ?>,<?lua print(150-i*30) ?>,0" pitch="0" yaw="0" roll="0">
+        <templates>
+          <Template link=standardturret />
+        </templates>
+      </Turret>
+    <?lua end ?>
+
+  </attached>
+  <collisionShapes>
+    <BoxCollisionShape radius="10"   position="0,0,0" halfExtents="200, 200, 0"/>
+  </collisionShapes>
+</SpaceShip>
+    
+  </Scene>
+</Level>
+
Index: /code/branches/RacingBots_FS18/data/levels/tutorial.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/tutorial.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/tutorial.oxw	(revision 11817)
@@ -0,0 +1,111 @@
+<LevelInfo
+ name = "Coding Tutorial"
+ description = "Level for the coding tutorial."
+ tags = "tutorial, shipselection"
+ screenshot = "codingtutorial.png"
+ startingships = "spaceshipassff, spaceshipghost, spaceshipspacecruiser"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipGhost.oxt")
+  include("templates/spaceshipSpacecruiser.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+<Drone name="meineDrohne" primarythrust="80" auxilarythrust="10" rotationthrust="10" mass= "50" linearDamping = "0.9" angularDamping = "0.7">
+  <attached>
+    <Model scale="1" mesh="drone.mesh"/>
+  </attached>
+  <collisionShapes>
+    <BoxCollisionShape position="0,0,0"      halfExtents="10, 10, 10" />
+  </collisionShapes>
+</Drone>
+
+    <Drone name="meineDrohne" primarythrust="80" auxilarythrust="10" rotationthrust="10" mass= "50" linearDamping = "0.9" angularDamping = "0.7">
+      <attached>
+        <Model scale="1" mesh="rocket.mesh"/>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="0,0,0"      halfExtents="10, 10, 10" />
+      </collisionShapes>
+    </Drone>
+
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <Model mesh="hs-w01.mesh" scale=10 position="0,0,-100" />
+    <Model mesh="hs-w01s.mesh" scale=10 position="0,0,-100" />
+
+    <?lua
+      for i = 1, 10, 1 do
+    ?>
+      <SpawnPoint position="<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>" lookat="0,0,0" spawnclass=SpaceShip pawndesign=shipselection />
+    <?lua end ?>
+
+    <GlobalShader compositor="Bloom" visible=false>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,0,0" distance=30 target="Spectator" switch=true />
+        </visibility>
+      </events>
+    </GlobalShader>
+    <Model position="0,0,0" scale=8 mesh="ast1.mesh" />
+    <StaticEntity position="0,0,0" collisionType=static>
+      <collisionShapes>
+        <SphereCollisionShape radius="20" />
+      </collisionShapes>
+    </StaticEntity>
+
+<!--
+    <?lua
+      for i = 1, 70, 1 do
+    ?>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 1000 + 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * -1000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * 1000 + 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * 6000 - 3000)?>, <?lua print(math.random() * -1000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+
+      <MovableEntity position="<?lua print(math.random() * 1000 + 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+      <MovableEntity position="<?lua print(math.random() * -1000 - 3000)?>, <?lua print(math.random() * 6000 - 3000) ?>, <?lua print(math.random() * 6000 - 3000) ?>" rotationaxis="<?lua print(math.random()) ?>, <?lua print(math.random()) ?>, <?lua print(math.random()) ?>" rotationrate="<?lua print(math.random() * 30 + 5) ?>">
+        <attached>
+          <Model scale="<?lua print(math.random() * 30 + 10) ?>" mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh" shadow=false />
+        </attached>
+      </MovableEntity>
+    <?lua end ?>
+-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/underAttack.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/underAttack.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/underAttack.oxw	(revision 11817)
@@ -0,0 +1,254 @@
+<!---->
+
+<LevelInfo
+ name = "Under Attack"
+ description = "Fight the transporter."
+ tags = "gametype"
+ screenshot = "underattack.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/standardTurret.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level
+ gametype = "UnderAttack"
+>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+  <WorldAmbientSound source="Jupiter.ogg" looping="true" playOnLoad="true" />
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <?lua for i = 1, 30, 1 do ?>
+      <MovableEntity
+          position="<?lua print(math.random() * 10000 - 5000) ?>, <?lua print(math.random() * 10000 - 5000) ?>, <?lua print(math.random() * 10000 - 5000) ?>"
+          velocity="<?lua print(math.random() * 500 - 250) ?>, <?lua print(math.random() * 500 - 250) ?>, <?lua print(math.random() * 500 - 250) ?>"
+      >
+        <attached>
+          <Model
+              <?lua x = math.random() * 150 + 30 ?>
+              scale="<?lua print(x) ?>"
+              mesh="ast<?lua print( math.mod(i,6) + 1) ?>.mesh"
+              position="0,0,0"
+          />
+        </attached>
+          <collisionShapes>
+            <SphereCollisionShape radius="<?lua print(x) ?>" position="0,0,0" />
+          </collisionShapes>
+      </MovableEntity>
+    <?lua end ?>
+
+    <Destroyer
+      position          = "100,150,0"
+      collisionType     = dynamic
+      mass              = 100000
+      velocity          = "-35,0,0"
+      angularDamping    = 0.9999999
+      health            = 10000
+      maxhealth         = 10000000
+      initialhealth     = 10000
+      radarname         = "Transporter"
+      team              = 1
+    >
+
+      <attached>
+        <SpaceBoundaries position="1,2,3" maxDistance="1600" warnDistance="300" showDistance="300" reactionMode="1" healthDecrease="5.0" />
+        <TeamSpawnPoint team=1 position="200,0,20" direction="-1,0,0" roll=90 yaw=0 spawnclass=SpaceShip pawndesign=spaceshipassff />
+        <TeamSpawnPoint team=1 position="50,0,100" lookat="-1,0,0" roll="90"  yaw=0 spawnclass=SpaceShip pawndesign=spaceshipassff />
+        <TeamSpawnPoint team=1 position="-200,0,-60" lookat="-1,0,0" roll="90" yaw=0 spawnclass=SpaceShip pawndesign=spaceshipassff />
+        <TeamSpawnPoint team=1 position="100,0,-50" lookat="-1,0,0" roll="90" yaw=0 spawnclass=SpaceShip pawndesign=spaceshipassff />
+        <TeamSpawnPoint team=1 position="400,0,20" lookat="-1,0,0" roll="90" yaw=0 spawnclass=SpaceShip pawndesign=spaceshipassff />
+        <?lua for i = 1, 100, 1 do ?>
+          <TeamSpawnPoint
+            team=0
+            position="<?lua print((math.random() * 450 + 450) * (math.floor(math.random() + 0.5) * 2 - 1)) ?>,<?lua print((math.random() * 450 + 450) * (math.floor(math.random() + 0.5) * 2 - 1)) ?>,<?lua print((math.random() * 450 + 450) * (math.floor(math.random() + 0.5) * 2 - 1)) ?>"
+            lookat="0,0,0"
+            spawnclass=SpaceShip
+            pawndesign=spaceshipassff
+          />
+
+          <!--more spawnpoints for team1-->
+          <!--
+          <TeamSpawnPoint
+            team=1 position="<?lua print((math.random() * 500 + 500)) ?>,<?lua print((math.random() * 500 + 500) ) ?>,<?lua print((math.random() * 500 + 500)) ?>"
+            lookat="0,0,0"
+            spawnclass=SpaceShip
+            pawndesign=spaceshipassff
+          />-->
+        <?lua end ?>
+
+        <Model mesh="Carrier.mesh" scale="5" />
+        <Backlight
+          mainstate=activity
+          active=false
+          scale=0.4
+          name=bltest
+          position=" 7.6, 0, 6"
+          colour="0.2, 0.65, 1.0, 1.0"
+          width=15
+          length=1500
+          lifetime=2
+          elements=50
+          trailmaterial="Trail/backlighttrail"
+          turnontime=1
+          turnofftime=1
+          material="Flares/ThrusterFlare1"
+        />
+        <?lua for i=0,8,1 do ?>
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?> ,15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+
+          <BlinkingBillboard
+            position="<?lua print(200-270/8*i)?>,-15,2"
+            material="Examples/Flare"
+            colour="1.0, 0.5, 0.3"
+            phase="<?lua print(-360/8*i)?>"
+            amplitude=0.1
+            frequency=0.5
+            quadratic=1
+          />
+        <?lua end ?>
+
+        <Backlight
+          scale=1
+          position=" 169, 75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare"
+        />
+        <Backlight
+          scale=1
+          position=" 169, -75, -15"
+          colour="1, 0.85, 0.5, 0.5"
+          width=40
+          length=1000
+          lifetime=5
+          elements=15
+          trailmaterial="Trail/backlighttrail"
+          material="Examples/Flare" />
+        <Turret position="170,47,35" pitch="90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="170,-47,35" pitch="-90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="167,0,90" pitch="180" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="140,85,-15" pitch="90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="70,85,-15" pitch="90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="105,75,-3" pitch="180" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="25,75,-15" yaw="90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="140,-85,-15" pitch="-90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="70,-85,-15" pitch="-90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="105,-75,-3" pitch="180" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="25,-75,-15" yaw="90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="203,-35,-15" yaw="-90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="203,35,-15" yaw="-90" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="-55,42,-15" yaw="90" pitch="73" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+        <Turret position="-55,-42,-15" yaw="90" pitch="-73" scale="0.5">
+          <templates>
+            <Template link=standardturret />
+          </templates>
+        </Turret>
+      </attached>
+      <collisionShapes>
+        <BoxCollisionShape position="70,0,-25"      halfExtents="150, 50, 25" />
+        <BoxCollisionShape position="95,75,-16"     halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="95,-75,-16"    halfExtents="70, 10, 12" />
+        <BoxCollisionShape position="77,47,30"      halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,-47,30"     halfExtents="110, 2, 30" />
+        <BoxCollisionShape position="77,0,50"       halfExtents="110, 45, 6" />
+        <BoxCollisionShape position="167,0,70"      halfExtents="17, 20, 20" />
+      </collisionShapes>
+    </Destroyer>
+
+    <GlobalShader compositor="Bloom" visible=false>
+      <events>
+        <visibility>
+          <DistanceTrigger position="0,0,0" distance=30 target="Spectator" switch=true />
+        </visibility>
+      </events>
+    </GlobalShader>
+
+    <Model position="0,0,0" scale=8 mesh="ast1.mesh" />
+    <StaticEntity position="0,0,0" collisionType=static>
+      <collisionShapes>
+        <SphereCollisionShape radius="20" />
+      </collisionShapes>
+    </StaticEntity>
+    
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/levels/waypoints.oxw
===================================================================
--- /code/branches/RacingBots_FS18/data/levels/waypoints.oxw	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/levels/waypoints.oxw	(revision 11817)
@@ -0,0 +1,160 @@
+<LevelInfo
+ name = "Waypoints Testlevel"
+ description = "Testing waypoings for AI controlled spaceships."
+ tags = "test"
+ screenshot = "waypointstestlevel.png"
+/>
+
+<?lua
+  include("HUDTemplates3.oxo")
+  include("stats.oxo")
+  include("templates/spaceshipAssff.oxt")
+  include("templates/spaceshipH2.oxt")
+  include("templates/spaceshipPirate.oxt")
+  include("templates/lodInformation.oxt")
+?>
+
+<Level>
+  <templates>
+    <Template link=lodtemplate_default />
+  </templates>
+  <?lua include("includes/notifications.oxi") ?>
+
+  <Scene
+   ambientlight = "0.5, 0.5, 0.5"
+   skybox       = "Orxonox/skyBoxBasic"
+  >
+    <Light type=directional position="0,0,0" direction="0.253, 0.593, -0.765" diffuse="1.0, 0.9, 0.9, 1.0" specular="1.0, 0.9, 0.9, 1.0" />
+
+    <SpawnPoint position="0,0,0" direction="1,0,0" spawnclass=SpaceShip pawndesign=spaceshipassff />
+
+    <SpaceShip position="0,2000,200" lookat="0,0,0">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=1000 team=10>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=8 position="  0,2000,-200" />
+            <Model mesh="cube.mesh" scale=8 position="  0,2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="500,2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="500,2000,-200" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+    <SpaceShip position="0,2000,400" lookat="0,0,0">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=1000 team=10>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=8 position="  0,2000,-200" />
+            <Model mesh="cube.mesh" scale=8 position="  0,2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="500,2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="500,2000,-200" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="1500,2000,200" lookat="0,0,0">
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=1000 team=11>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=8 position="1500,2000,-200" />
+            <Model mesh="cube.mesh" scale=8 position="1500,2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="1000,2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="1000,2000,-200" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <SpaceShip position="1500,-2000,200" lookat="0,0,0" name=polonaise1>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=1000 team=12>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=8 position="1500,-2000,-200" />
+<!--
+            <Attacher target=polonaise6 deletewithparent=false />
+            <Model mesh="cube.mesh" scale=8 position="1500,-2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="1000,-2000,-700" />
+            <Model mesh="cube.mesh" scale=8 position="1000,-2000,-200" />
+-->
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <?lua
+      for i = 1, 5, 1 do
+    ?>
+      <SpaceShip position="1500,<?lua print(-2000 + 50*i) ?>,200" lookat="0,0,0" name=polonaise<?lua print(i+1) ?> >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=1000 team=12>
+            <waypoints>
+              <Attacher target=polonaise<?lua print(i) ?> deletewithparent=false />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+    <SpaceShip position="-1500,-2000,200" lookat="0,0,0" name=attack1>
+      <templates>
+        <Template link=spaceshipassff />
+      </templates>
+      <controller>
+        <WaypointPatrolController alertnessradius=1000 team=13>
+          <waypoints>
+            <Model mesh="cube.mesh" scale=8 position="1500,-2000,-200" />
+          </waypoints>
+        </WaypointPatrolController>
+      </controller>
+    </SpaceShip>
+
+    <?lua
+      for i = 1, 5, 1 do
+    ?>
+      <SpaceShip position="-1500,<?lua print(-2000 + 50*i) ?>,200" lookat="0,0,0" name=attack<?lua print(i+1) ?> >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <WaypointPatrolController alertnessradius=1000 team=13>
+            <waypoints>
+              <Attacher target=attack<?lua print(i) ?> deletewithparent=false />
+            </waypoints>
+          </WaypointPatrolController>
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+
+<!--
+    <?lua
+      for i = 1, 50, 1 do
+    ?>
+      <SpaceShip position="<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>,<?lua print(math.random() * 1000 - 500) ?>" lookat="0,0,0" >
+        <templates>
+          <Template link=spaceshipassff />
+        </templates>
+        <controller>
+          <AIController />
+        </controller>
+      </SpaceShip>
+    <?lua end ?>
+-->
+
+  </Scene>
+</Level>
Index: /code/branches/RacingBots_FS18/data/lua/Debugger.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/lua/Debugger.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/lua/Debugger.lua	(revision 11817)
@@ -0,0 +1,1358 @@
+
+--{{{  history
+
+--28/03/10 ORX Adjusted show() to work with the Orxonox resource system
+--15/03/06 DCN Created based on RemDebug
+--28/04/06 DCN Update for Lua 5.1
+--01/06/06 DCN Fix command argument parsing
+--             Add step/over N facility
+--             Add trace lines facility
+--05/06/06 DCN Add trace call/return facility
+--06/06/06 DCN Make it behave when stepping through the creation of a coroutine
+--06/06/06 DCN Integrate the simple debugger into the main one
+--07/06/06 DCN Provide facility to step into coroutines
+--13/06/06 DCN Fix bug that caused the function environment to get corrupted with the global one
+--14/06/06 DCN Allow 'sloppy' file names when setting breakpoints
+--04/08/06 DCN Allow for no space after command name
+--11/08/06 DCN Use io.write not print
+--30/08/06 DCN Allow access to array elements in 'dump'
+--10/10/06 DCN Default to breakfile for all commands that require a filename and give '-'
+--06/12/06 DCN Allow for punctuation characters in DUMP variable names
+--03/01/07 DCN Add pause on/off facility
+--19/06/07 DCN Allow for duff commands being typed in the debugger (thanks to Michael.Bringmann@lsi.com)
+--             Allow for case sensitive file systems               (thanks to Michael.Bringmann@lsi.com)
+
+--}}}
+--{{{  description
+
+--A simple command line debug system for Lua written by Dave Nichols of
+--Match-IT Limited. Its public domain software. Do with it as you wish.
+
+--This debugger was inspired by:
+-- RemDebug 1.0 Beta
+-- Copyright Kepler Project 2005 (http://www.keplerproject.org/remdebug)
+
+--Usage:
+--  require('debugger')        --load the debug library
+--  pause(message)             --start/resume a debug session
+
+--An assert() failure will also invoke the debugger.
+
+--}}}
+
+local IsWindows = string.find(string.lower(os.getenv('OS') or ''),'^windows')
+
+local coro_debugger
+local events = { BREAK = 1, WATCH = 2, STEP = 3, SET = 4 }
+local breakpoints = {}
+local watches = {}
+local step_into   = false
+local step_over   = false
+local step_lines  = 0
+local step_level  = {main=0}
+local stack_level = {main=0}
+local trace_level = {main=0}
+local trace_calls = false
+local trace_returns = false
+local trace_lines = false
+local ret_file, ret_line, ret_name
+local current_thread = 'main'
+local started = false
+local pause_off = false
+local _g      = _G
+local cocreate, cowrap = coroutine.create, coroutine.wrap
+local pausemsg = 'pause'
+
+--{{{  local hints -- command help
+--The format in here is name=summary|description
+local hints = {
+
+pause =   [[
+pause(msg)          -- start/resume a debugger session|
+
+This can only be used in your code or from the console as a means to
+start/resume a debug session.
+If msg is given that is shown when the session starts/resumes. Useful to
+give a context if you've instrumented your code with pause() statements.
+]],
+
+poff =    [[
+poff                -- turn off pause() command|
+
+This causes all pause() commands to be ignored. This is useful if you have
+instrumented your code in a busy loop and want to continue normal execution
+with no further interruption.
+]],
+
+pon =     [[
+pon                 -- turn on pause() command|
+
+This re-instates honouring the pause() commands you may have instrumented
+your code with.
+]],
+
+setb =    [[
+setb [line file]    -- set a breakpoint to line/file|
+
+If file is omitted or is "-" the breakpoint is set at the file for the
+currently set level (see "set"). Execution pauses when this line is about
+to be executed and the debugger session is re-activated.
+
+The file can be given as the fully qualified name, partially qualified or
+just the file name. E.g. if file is set as "myfile.lua", then whenever
+execution reaches any file that ends with "myfile.lua" it will pause.
+]],
+
+delb =    [[
+delb [line file]    -- removes a breakpoint|
+
+If file is omitted or is "-" the breakpoint is removed for the file of the
+currently set level (see "set").
+]],
+
+delallb = [[
+delallb             -- removes all breakpoints|
+]],
+
+setw =    [[
+setw <exp>          -- adds a new watch expression|
+
+The expression is evaluated before each line is executed. If the expression
+yields true then execution is paused and the debugger session re-activated.
+The expression is executed in the context of the line about to be executed.
+]],
+
+delw =    [[
+delw <index>        -- removes the watch expression at index|
+
+The index is that returned when the watch expression was set by setw.
+]],
+
+delallw = [[
+delallw             -- removes all watch expressions|
+]],
+
+run     = [[
+run                 -- run until next breakpoint or watch expression|
+]],
+
+step    = [[
+step [N]            -- run next N lines, stepping into function calls|
+
+If N is omitted, use 1.
+]],
+
+over    = [[
+over [N]            -- run next N lines, stepping over function calls|
+
+If N is omitted, use 1.
+]],
+
+out     = [[
+out [N]             -- run lines until stepped out of N functions|
+
+If N is omitted, use 1.
+If you are inside a function, using "out 1" will run until you return
+from that function to the caller.
+]],
+
+goto    = [[
+goto <line>         -- step to line number <line> in the current file|
+
+The line and current file are those in the currently set context level.
+]],
+
+listb   = [[
+listb               -- lists breakpoints|
+]],
+
+listw   = [[
+listw               -- lists watch expressions|
+]],
+
+set     = [[
+set [level]         -- set context to stack level, omitted=show|
+
+If level is omitted it just prints the current level set.
+This sets the current context to the level given. This affects the
+context used for several other functions (e.g. vars). The possible
+levels are those shown by trace.
+]],
+
+vars    = [[
+vars [depth]        -- list context locals to depth, omitted=1|
+
+If depth is omitted then uses 1.
+Use a depth of 0 for the maximum.
+Lists all non-nil local variables and all non-nil upvalues in the
+currently set context. For variables that are tables, lists all fields
+to the given depth.
+]],
+
+fenv    = [[
+fenv [depth]        -- list context function env to depth, omitted=1|
+
+If depth is omitted then uses 1.
+Use a depth of 0 for the maximum.
+Lists all function environment variables in the currently set context.
+For variables that are tables, lists all fields to the given depth.
+]],
+
+glob    = [[
+glob [depth]        -- list globals to depth, omitted=1|
+
+If depth is omitted then uses 1.
+Use a depth of 0 for the maximum.
+Lists all global variables.
+For variables that are tables, lists all fields to the given depth.
+]],
+
+ups     = [[
+ups                 -- list all the upvalue names|
+
+These names will also be in the "vars" list unless their value is nil.
+This provides a means to identify which vars are upvalues and which are
+locals. If a name is both an upvalue and a local, the local value takes
+precedance.
+]],
+
+locs    = [[
+locs                -- list all the locals names|
+
+These names will also be in the "vars" list unless their value is nil.
+This provides a means to identify which vars are upvalues and which are
+locals. If a name is both an upvalue and a local, the local value takes
+precedance.
+]],
+
+dump    = [[
+dump <var> [depth]  -- dump all fields of variable to depth|
+
+If depth is omitted then uses 1.
+Use a depth of 0 for the maximum.
+Prints the value of <var> in the currently set context level. If <var>
+is a table, lists all fields to the given depth. <var> can be just a
+name, or name.field or name.# to any depth, e.g. t.1.f accesses field
+'f' in array element 1 in table 't'.
+
+Can also be called from a script as dump(var,depth).
+]],
+
+tron    = [[
+tron [crl]          -- turn trace on for (c)alls, (r)etuns, (l)lines|
+
+If no parameter is given then tracing is turned off.
+When tracing is turned on a line is printed to the console for each
+debug 'event' selected. c=function calls, r=function returns, l=lines.
+]],
+
+trace   = [[
+trace               -- dumps a stack trace|
+
+Format is [level] = file,line,name
+The level is a candidate for use by the 'set' command.
+]],
+
+info    = [[
+info                -- dumps the complete debug info captured|
+
+Only useful as a diagnostic aid for the debugger itself. This information
+can be HUGE as it dumps all variables to the maximum depth, so be careful.
+]],
+
+show    = [[
+show line file X Y  -- show X lines before and Y after line in file|
+
+If line is omitted or is '-' then the current set context line is used.
+If file is omitted or is '-' then the current set context file is used.
+If file is not fully qualified and cannot be opened as specified, then
+a search for the file in the package[path] is performed using the usual
+"require" searching rules. If no file extension is given, .lua is used.
+Prints the lines from the source file around the given line.
+]],
+
+exit    = [[
+exit                -- exits debugger, re-start it using pause()|
+]],
+
+help    = [[
+help [command]      -- show this list or help for command|
+]],
+
+["<statement>"] = [[
+<statement>         -- execute a statement in the current context|
+
+The statement can be anything that is legal in the context, including
+assignments. Such assignments affect the context and will be in force
+immediately. Any results returned are printed. Use '=' as a short-hand
+for 'return', e.g. "=func(arg)" will call 'func' with 'arg' and print
+the results, and "=var" will just print the value of 'var'.
+]],
+
+what    = [[
+what <func>         -- show where <func> is defined (if known)|
+]],
+
+}
+--}}}
+
+--{{{  local function getinfo(level,field)
+
+--like debug.getinfo but copes with no activation record at the given level
+--and knows how to get 'field'. 'field' can be the name of any of the
+--activation record fields or any of the 'what' names or nil for everything.
+--only valid when using the stack level to get info, not a function name.
+
+local function getinfo(level,field)
+  level = level + 1  --to get to the same relative level as the caller
+  if not field then return debug.getinfo(level) end
+  local what
+  if field == 'name' or field == 'namewhat' then
+    what = 'n'
+  elseif field == 'what' or field == 'source' or field == 'linedefined' or field == 'lastlinedefined' or field == 'short_src' then
+    what = 'S'
+  elseif field == 'currentline' then
+    what = 'l'
+  elseif field == 'nups' then
+    what = 'u'
+  elseif field == 'func' then
+    what = 'f'
+  else
+    return debug.getinfo(level,field)
+  end
+  local ar = debug.getinfo(level,what)
+  if ar then return ar[field] else return nil end
+end
+
+--}}}
+--{{{  local function indented( level, ... )
+
+local function indented( level, ... )
+  io.write( string.rep('  ',level), table.concat({...}), '\n' )
+end
+
+--}}}
+--{{{  local function dumpval( level, name, value, limit )
+
+local dumpvisited
+
+local function dumpval( level, name, value, limit )
+  local index
+  if type(name) == 'number' then
+    index = string.format('[%d] = ',name)
+  elseif type(name) == 'string'
+     and (name == '__VARSLEVEL__' or name == '__ENVIRONMENT__' or name == '__GLOBALS__' or name == '__UPVALUES__' or name == '__LOCALS__') then
+    --ignore these, they are debugger generated
+    return
+  elseif type(name) == 'string' and string.find(name,'^[_%a][_.%w]*$') then
+    index = name ..' = '
+  else
+    index = string.format('[%q] = ',tostring(name))
+  end
+  if type(value) == 'table' then
+    if dumpvisited[value] then
+      indented( level, index, string.format('ref%q;',dumpvisited[value]) )
+    else
+      dumpvisited[value] = tostring(value)
+      if (limit or 0) > 0 and level+1 >= limit then
+        indented( level, index, dumpvisited[value] )
+      else
+        indented( level, index, '{  -- ', dumpvisited[value] )
+        for n,v in pairs(value) do
+          dumpval( level+1, n, v, limit )
+        end
+        indented( level, '};' )
+      end
+    end
+  else
+    if type(value) == 'string' then
+      if string.len(value) > 40 then
+        indented( level, index, '[[', value, ']];' )
+      else
+        indented( level, index, string.format('%q',value), ';' )
+      end
+    else
+      indented( level, index, tostring(value), ';' )
+    end
+  end
+end
+
+--}}}
+--{{{  local function dumpvar( value, limit, name )
+
+local function dumpvar( value, limit, name )
+  dumpvisited = {}
+  dumpval( 0, name or tostring(value), value, limit )
+end
+
+--}}}
+--{{{  local function show(file,line,before,after)
+
+--show +/-N lines of a file around line M
+
+local function show(file,line,before,after)
+
+  line   = tonumber(line   or 1)
+  before = tonumber(before or 10)
+  after  = tonumber(after  or before)
+
+  -- Try to find the file in the Orxonox resources
+  local text = luaState:getSourceCode(file)
+
+  if text == "" then
+    if not string.find(file,'%.') then file = file..'.lua' end
+
+    local f = io.open(file,'r')
+    if not f then
+      --{{{  try to find the file in the path
+    
+      --
+      -- looks for a file in the package path
+      --
+      local path = package.path or LUA_PATH or ''
+      for c in string.gmatch (path, "[^;]+") do
+        local c = string.gsub (c, "%?%.lua", file)
+        f = io.open (c,'r')
+        if f then
+          break
+        end
+      end
+    
+      --}}}
+
+      if f then
+        -- Read file into 'text'
+        text = f:read("*a")
+        f:close()
+      else
+        io.write('Cannot find '..file..'\n')
+        return
+      end
+    end
+  end
+
+  -- Transform line endings to \n
+  text:gsub("\r\n", "\n") -- Windows to Unix
+  text:gsub("\r", "\n")   -- Mac to Unix
+  if text[-1] ~= "\n" then
+      text = text.."\n"
+  end
+  -- Print requested lines
+  local i = 0
+  for l in text:gmatch("[^\n]*[\n]") do
+    i = i + 1
+    if i >= (line-before) then
+      if i > (line+after) then break end
+      if i == line then
+        io.write(i..'***\t'..l)
+      else
+        io.write(i..'\t'..l)
+      end
+    end
+  end
+end
+
+--}}}
+--{{{  local function tracestack(l)
+
+local function gi( i )
+  return function() i=i+1 return debug.getinfo(i),i end
+end
+
+local function gl( level, j )
+  return function() j=j+1 return debug.getlocal( level, j ) end
+end
+
+local function gu( func, k )
+  return function() k=k+1 return debug.getupvalue( func, k ) end
+end
+
+local  traceinfo
+
+local function tracestack(l)
+  local l = l + 1                        --NB: +1 to get level relative to caller
+  traceinfo = {}
+  traceinfo.pausemsg = pausemsg
+  for ar,i in gi(l) do
+    table.insert( traceinfo, ar )
+    local names  = {}
+    local values = {}
+    for n,v in gl(i,0) do
+      if string.sub(n,1,1) ~= '(' then   --ignore internal control variables
+        table.insert( names, n )
+        table.insert( values, v )
+      end
+    end
+    if #names > 0 then
+      ar.lnames  = names
+      ar.lvalues = values
+    end
+    if ar.func then
+      local names  = {}
+      local values = {}
+      for n,v in gu(ar.func,0) do
+        if string.sub(n,1,1) ~= '(' then   --ignore internal control variables
+          table.insert( names, n )
+          table.insert( values, v )
+        end
+      end
+      if #names > 0 then
+        ar.unames  = names
+        ar.uvalues = values
+      end
+    end
+  end
+end
+
+--}}}
+--{{{  local function trace()
+
+local function trace(set)
+  local mark
+  for level,ar in ipairs(traceinfo) do
+    if level == set then
+      mark = '***'
+    else
+      mark = ''
+    end
+    io.write('['..level..']'..mark..'\t'..(ar.name or ar.what)..' in '..ar.short_src..':'..ar.currentline..'\n')
+  end
+end
+
+--}}}
+--{{{  local function info()
+
+local function info() dumpvar( traceinfo, 0, 'traceinfo' ) end
+
+--}}}
+
+--{{{  local function set_breakpoint(file, line)
+
+local function set_breakpoint(file, line)
+  if not breakpoints[line] then
+    breakpoints[line] = {}
+  end
+  breakpoints[line][file] = true
+end
+
+--}}}
+--{{{  local function remove_breakpoint(file, line)
+
+local function remove_breakpoint(file, line)
+  if breakpoints[line] then
+    breakpoints[line][file] = nil
+  end
+end
+
+--}}}
+--{{{  local function has_breakpoint(file, line)
+
+--allow for 'sloppy' file names
+--search for file and all variations walking up its directory hierachy
+--ditto for the file with no extension
+
+local function has_breakpoint(file, line)
+  if not breakpoints[line] then return false end
+  local noext = string.gsub(file,"(%..-)$",'',1)
+  if noext == file then noext = nil end
+  while file do
+    if breakpoints[line][file] then return true end
+    file = string.match(file,"[:/\](.+)$")
+  end
+  while noext do
+    if breakpoints[line][noext] then return true end
+    noext = string.match(noext,"[:/\](.+)$")
+  end
+  return false
+end
+
+--}}}
+--{{{  local function capture_vars(ref,level,line)
+
+local function capture_vars(ref,level,line)
+  --get vars, file and line for the given level relative to debug_hook offset by ref
+
+  local lvl = ref + level                --NB: This includes an offset of +1 for the call to here
+
+  --{{{  capture variables
+  
+  local ar = debug.getinfo(lvl, "f")
+  if not ar then return {},'?',0 end
+  
+  local vars = {__UPVALUES__={}, __LOCALS__={}}
+  local i
+  
+  local func = ar.func
+  if func then
+    i = 1
+    while true do
+      local name, value = debug.getupvalue(func, i)
+      if not name then break end
+      if string.sub(name,1,1) ~= '(' then  --NB: ignoring internal control variables
+        vars[name] = value
+        vars.__UPVALUES__[i] = name
+      end
+      i = i + 1
+    end
+    vars.__ENVIRONMENT__ = getfenv(func)
+  end
+  
+  vars.__GLOBALS__ = getfenv(0)
+  
+  i = 1
+  while true do
+    local name, value = debug.getlocal(lvl, i)
+    if not name then break end
+    if string.sub(name,1,1) ~= '(' then    --NB: ignoring internal control variables
+      vars[name] = value
+      vars.__LOCALS__[i] = name
+    end
+    i = i + 1
+  end
+  
+  vars.__VARSLEVEL__ = level
+  
+  if func then
+    --NB: Do not do this until finished filling the vars table
+    setmetatable(vars, { __index = getfenv(func), __newindex = getfenv(func) })
+  end
+  
+  --NB: Do not read or write the vars table anymore else the metatable functions will get invoked!
+  
+  --}}}
+
+  local file = getinfo(lvl, "source")
+  if string.find(file, "@") == 1 then
+    file = string.sub(file, 2)
+  end
+  -- Orxonox changes: Our resource system is case sensisive, even on Windows
+  --if IsWindows then file = string.lower(file) end
+
+  if not line then
+    line = getinfo(lvl, "currentline")
+  end
+
+  return vars,file,line
+
+end
+
+--}}}
+--{{{  local function restore_vars(ref,vars)
+
+local function restore_vars(ref,vars)
+
+  if type(vars) ~= 'table' then return end
+
+  local level = vars.__VARSLEVEL__       --NB: This level is relative to debug_hook offset by ref
+  if not level then return end
+
+  level = level + ref                    --NB: This includes an offset of +1 for the call to here
+
+  local i
+  local written_vars = {}
+
+  i = 1
+  while true do
+    local name, value = debug.getlocal(level, i)
+    if not name then break end
+    if vars[name] and string.sub(name,1,1) ~= '(' then     --NB: ignoring internal control variables
+      debug.setlocal(level, i, vars[name])
+      written_vars[name] = true
+    end
+    i = i + 1
+  end
+
+  local ar = debug.getinfo(level, "f")
+  if not ar then return end
+
+  local func = ar.func
+  if func then
+
+    i = 1
+    while true do
+      local name, value = debug.getupvalue(func, i)
+      if not name then break end
+      if vars[name] and string.sub(name,1,1) ~= '(' then   --NB: ignoring internal control variables
+        if not written_vars[name] then
+          debug.setupvalue(func, i, vars[name])
+        end
+        written_vars[name] = true
+      end
+      i = i + 1
+    end
+
+  end
+
+end
+
+--}}}
+--{{{  local function trace_event(event, line, level)
+
+local function print_trace(level,depth,event,file,line,name)
+
+  --NB: level here is relative to the caller of trace_event, so offset by 2 to get to there
+  level = level + 2
+
+  local file = file or getinfo(level,'short_src')
+  local line = line or getinfo(level,'currentline')
+  local name = name or getinfo(level,'name')
+
+  local prefix = ''
+  if current_thread ~= 'main' then prefix = '['..tostring(current_thread)..'] ' end
+
+  io.write(prefix..
+           string.format('%08.2f:%02i.',os.clock(),depth)..
+           string.rep('.',depth%32)..
+           (file or '')..' ('..(line or '')..') '..
+           (name or '')..
+           ' ('..event..')\n')
+
+end
+
+local function trace_event(event, line, level)
+
+  if event == 'return' and trace_returns then
+    --note the line info for later
+    ret_file = getinfo(level+1,'short_src')
+    ret_line = getinfo(level+1,'currentline')
+    ret_name = getinfo(level+1,'name')
+  end
+
+  if event ~= 'line' then return end
+
+  local slevel = stack_level[current_thread]
+  local tlevel = trace_level[current_thread]
+
+  if trace_calls and slevel > tlevel then
+    --we are now in the function called, so look back 1 level further to find the calling file and line
+    print_trace(level+1,slevel-1,'c',nil,nil,getinfo(level+1,'name'))
+  end
+
+  if trace_returns and slevel < tlevel then
+    print_trace(level,slevel,'r',ret_file,ret_line,ret_name)
+  end
+
+  if trace_lines then
+    print_trace(level,slevel,'l')
+  end
+
+  trace_level[current_thread] = stack_level[current_thread]
+
+end
+
+--}}}
+--{{{  local function debug_hook(event, line, level, thread)
+
+local function debug_hook(event, line, level, thread)
+  if not started then debug.sethook() return end
+  current_thread = thread or 'main'
+  local level = level or 2
+  trace_event(event,line,level)
+  if event == "call" then
+    stack_level[current_thread] = stack_level[current_thread] + 1
+  elseif event == "return" then
+    stack_level[current_thread] = stack_level[current_thread] - 1
+    if stack_level[current_thread] < 0 then stack_level[current_thread] = 0 end
+  else
+    local vars,file,line = capture_vars(level,1,line)
+    local stop, ev, idx = false, events.STEP, 0
+    while true do
+      for index, value in pairs(watches) do
+        setfenv(value.func, vars)
+        local status, res = pcall(value.func)
+        if status and res then
+          ev, idx = events.WATCH, index
+          stop = true
+          break
+        end
+      end
+      if stop then break end
+      if (step_into)
+      or (step_over and (stack_level[current_thread] <= step_level[current_thread] or stack_level[current_thread] == 0)) then
+        step_lines = step_lines - 1
+        if step_lines < 1 then
+          ev, idx = events.STEP, 0
+          break
+        end
+      end
+      if has_breakpoint(file, line) then
+        ev, idx = events.BREAK, 0
+        break
+      end
+      return
+    end
+    tracestack(level)
+    local last_next = 1
+    local err, next = assert(coroutine.resume(coro_debugger, ev, vars, file, line, idx))
+    while true do
+      if next == 'cont' then
+        return
+      elseif next == 'stop' then
+        started = false
+        debug.sethook()
+        return
+      elseif tonumber(next) then --get vars for given level or last level
+        next = tonumber(next)
+        if next == 0 then next = last_next end
+        last_next = next
+        restore_vars(level,vars)
+        vars, file, line = capture_vars(level,next)
+        err, next = assert(coroutine.resume(coro_debugger, events.SET, vars, file, line, idx))
+      else
+        io.write('Unknown command from debugger_loop: '..tostring(next)..'\n')
+        io.write('Stopping debugger\n')
+        next = 'stop'
+      end
+    end
+  end
+end
+
+--}}}
+--{{{  local function report(ev, vars, file, line, idx_watch)
+
+local function report(ev, vars, file, line, idx_watch)
+  local vars = vars or {}
+  local file = file or '?'
+  local line = line or 0
+  local prefix = ''
+  if current_thread ~= 'main' then prefix = '['..tostring(current_thread)..'] ' end
+  if ev == events.STEP then
+    io.write(prefix.."Paused at file "..file.." line "..line..' ('..stack_level[current_thread]..')\n')
+  elseif ev == events.BREAK then
+    io.write(prefix.."Paused at file "..file.." line "..line..' ('..stack_level[current_thread]..') (breakpoint)\n')
+  elseif ev == events.WATCH then
+    io.write(prefix.."Paused at file "..file.." line "..line..' ('..stack_level[current_thread]..')'.." (watch expression "..idx_watch.. ": ["..watches[idx_watch].exp.."])\n")
+  elseif ev == events.SET then
+    --do nothing
+  else
+    io.write(prefix.."Error in application: "..file.." line "..line.."\n")
+  end
+  if ev ~= events.SET then
+    if pausemsg and pausemsg ~= '' then io.write('Message: '..pausemsg..'\n') end
+    pausemsg = ''
+  end
+  return vars, file, line
+end
+
+--}}}
+
+--{{{  local function debugger_loop(server)
+
+local function debugger_loop(ev, vars, file, line, idx_watch)
+
+  io.write("Lua Debugger\n")
+  local eval_env, breakfile, breakline = report(ev, vars, file, line, idx_watch)
+  io.write("Type 'help' for commands\n")
+
+  local command, args
+
+  --{{{  local function getargs(spec)
+  
+  --get command arguments according to the given spec from the args string
+  --the spec has a single character for each argument, arguments are separated
+  --by white space, the spec characters can be one of:
+  -- F for a filename    (defaults to breakfile if - given in args)
+  -- L for a line number (defaults to breakline if - given in args)
+  -- N for a number
+  -- V for a variable name
+  -- S for a string
+  
+  local function getargs(spec)
+    local res={}
+    local char,arg
+    local ptr=1
+    for i=1,string.len(spec) do
+      char = string.sub(spec,i,i)
+      if     char == 'F' then
+        _,ptr,arg = string.find(args..' ',"%s*([%w%p]*)%s*",ptr)
+        if not arg or arg == '' then arg = '-' end
+        if arg == '-' then arg = breakfile end
+      elseif char == 'L' then
+        _,ptr,arg = string.find(args..' ',"%s*([%w%p]*)%s*",ptr)
+        if not arg or arg == '' then arg = '-' end
+        if arg == '-' then arg = breakline end
+        arg = tonumber(arg) or 0
+      elseif char == 'N' then
+        _,ptr,arg = string.find(args..' ',"%s*([%w%p]*)%s*",ptr)
+        if not arg or arg == '' then arg = '0' end
+        arg = tonumber(arg) or 0
+      elseif char == 'V' then
+        _,ptr,arg = string.find(args..' ',"%s*([%w%p]*)%s*",ptr)
+        if not arg or arg == '' then arg = '' end
+      elseif char == 'S' then
+        _,ptr,arg = string.find(args..' ',"%s*([%w%p]*)%s*",ptr)
+        if not arg or arg == '' then arg = '' end
+      else
+        arg = ''
+      end
+      table.insert(res,arg or '')
+    end
+    return unpack(res)
+  end
+  
+  --}}}
+
+  while true do
+    io.write("[DEBUG]> ")
+    local line = io.read("*line")
+    if line == nil then io.write('\n'); line = 'exit' end
+
+    if string.find(line, "^[a-z]+") then
+      command = string.sub(line, string.find(line, "^[a-z]+"))
+      args    = string.gsub(line,"^[a-z]+%s*",'',1)            --strip command off line
+    else
+      command = ''
+    end
+
+    if command == "setb" then
+      --{{{  set breakpoint
+      
+      local line, filename  = getargs('LF')
+      if filename ~= '' and line ~= '' then
+        set_breakpoint(filename,line)
+        io.write("Breakpoint set in file "..filename..' line '..line..'\n')
+      else
+        io.write("Bad request\n")
+      end
+      
+      --}}}
+
+    elseif command == "delb" then
+      --{{{  delete breakpoint
+      
+      local line, filename = getargs('LF')
+      if filename ~= '' and line ~= '' then
+        remove_breakpoint(filename, line)
+        io.write("Breakpoint deleted from file "..filename..' line '..line.."\n")
+      else
+        io.write("Bad request\n")
+      end
+      
+      --}}}
+
+    elseif command == "delallb" then
+      --{{{  delete all breakpoints
+      breakpoints = {}
+      io.write('All breakpoints deleted\n')
+      --}}}
+
+    elseif command == "listb" then
+      --{{{  list breakpoints
+      for i, v in pairs(breakpoints) do
+        for ii, vv in pairs(v) do
+          io.write("Break at: "..i..' in '..ii..'\n')
+        end
+      end
+      --}}}
+
+    elseif command == "setw" then
+      --{{{  set watch expression
+      
+      if args and args ~= '' then
+        local func = loadstring("return(" .. args .. ")")
+        local newidx = #watches + 1
+        watches[newidx] = {func = func, exp = args}
+        io.write("Set watch exp no. " .. newidx..'\n')
+      else
+        io.write("Bad request\n")
+      end
+      
+      --}}}
+
+    elseif command == "delw" then
+      --{{{  delete watch expression
+      
+      local index = tonumber(args)
+      if index then
+        watches[index] = nil
+        io.write("Watch expression deleted\n")
+      else
+        io.write("Bad request\n")
+      end
+      
+      --}}}
+
+    elseif command == "delallw" then
+      --{{{  delete all watch expressions
+      watches = {}
+      io.write('All watch expressions deleted\n')
+      --}}}
+
+    elseif command == "listw" then
+      --{{{  list watch expressions
+      for i, v in pairs(watches) do
+        io.write("Watch exp. " .. i .. ": " .. v.exp..'\n')
+      end
+      --}}}
+
+    elseif command == "run" then
+      --{{{  run until breakpoint
+      step_into = false
+      step_over = false
+      eval_env, breakfile, breakline = report(coroutine.yield('cont'))
+      --}}}
+
+    elseif command == "step" then
+      --{{{  step N lines (into functions)
+      local N = tonumber(args) or 1
+      step_over  = false
+      step_into  = true
+      step_lines = tonumber(N or 1)
+      eval_env, breakfile, breakline = report(coroutine.yield('cont'))
+      --}}}
+
+    elseif command == "over" then
+      --{{{  step N lines (over functions)
+      local N = tonumber(args) or 1
+      step_into  = false
+      step_over  = true
+      step_lines = tonumber(N or 1)
+      step_level[current_thread] = stack_level[current_thread]
+      eval_env, breakfile, breakline = report(coroutine.yield('cont'))
+      --}}}
+
+    elseif command == "out" then
+      --{{{  step N lines (out of functions)
+      local N = tonumber(args) or 1
+      step_into  = false
+      step_over  = true
+      step_lines = 1
+      step_level[current_thread] = stack_level[current_thread] - tonumber(N or 1)
+      eval_env, breakfile, breakline = report(coroutine.yield('cont'))
+      --}}}
+
+    elseif command == "goto" then
+      --{{{  step until reach line
+      local N = tonumber(args)
+      if N then
+        step_over  = false
+        step_into  = false
+        if has_breakpoint(breakfile,N) then
+          eval_env, breakfile, breakline = report(coroutine.yield('cont'))
+        else
+          local bf = breakfile
+          set_breakpoint(breakfile,N)
+          eval_env, breakfile, breakline = report(coroutine.yield('cont'))
+          if breakfile == bf and breakline == N then remove_breakpoint(breakfile,N) end
+        end
+      else
+        io.write("Bad request\n")
+      end
+      --}}}
+
+    elseif command == "set" then
+      --{{{  set/show context level
+      local level = args
+      if level and level == '' then level = nil end
+      if level then
+        eval_env, breakfile, breakline = report(coroutine.yield(level))
+      end
+      if eval_env.__VARSLEVEL__ then
+        io.write('Level: '..eval_env.__VARSLEVEL__..'\n')
+      else
+        io.write('No level set\n')
+      end
+      --}}}
+
+    elseif command == "vars" then
+      --{{{  list context variables
+      local depth = args
+      if depth and depth == '' then depth = nil end
+      depth = tonumber(depth) or 1
+      dumpvar(eval_env, depth+1, 'variables')
+      --}}}
+
+    elseif command == "glob" then
+      --{{{  list global variables
+      local depth = args
+      if depth and depth == '' then depth = nil end
+      depth = tonumber(depth) or 1
+      dumpvar(eval_env.__GLOBALS__,depth+1,'globals')
+      --}}}
+
+    elseif command == "fenv" then
+      --{{{  list function environment variables
+      local depth = args
+      if depth and depth == '' then depth = nil end
+      depth = tonumber(depth) or 1
+      dumpvar(eval_env.__ENVIRONMENT__,depth+1,'environment')
+      --}}}
+
+    elseif command == "ups" then
+      --{{{  list upvalue names
+      dumpvar(eval_env.__UPVALUES__,2,'upvalues')
+      --}}}
+
+    elseif command == "locs" then
+      --{{{  list locals names
+      dumpvar(eval_env.__LOCALS__,2,'upvalues')
+      --}}}
+
+    elseif command == "what" then
+      --{{{  show where a function is defined
+      if args and args ~= '' then
+        local v = eval_env
+        local n = nil
+        for w in string.gmatch(args,"[%w_]+") do
+          v = v[w]
+          if n then n = n..'.'..w else n = w end
+          if not v then break end
+        end
+        if type(v) == 'function' then
+          local def = debug.getinfo(v,'S')
+          if def then
+            io.write(def.what..' in '..def.short_src..' '..def.linedefined..'..'..def.lastlinedefined..'\n')
+          else
+            io.write('Cannot get info for '..v..'\n')
+          end
+        else
+          io.write(v..' is not a function\n')
+        end
+      else
+        io.write("Bad request\n")
+      end
+      --}}}
+
+    elseif command == "dump" then
+      --{{{  dump a variable
+      local name, depth = getargs('VN')
+      if name ~= '' then
+        if depth == '' or depth == 0 then depth = nil end
+        depth = tonumber(depth or 1)
+        local v = eval_env
+        local n = nil
+        for w in string.gmatch(name,"[^%.]+") do     --get everything between dots
+          if tonumber(w) then
+            v = v[tonumber(w)]
+          else
+            v = v[w]
+          end
+          if n then n = n..'.'..w else n = w end
+          if not v then break end
+        end
+        dumpvar(v,depth+1,n)
+      else
+        io.write("Bad request\n")
+      end
+      --}}}
+
+    elseif command == "show" then
+      --{{{  show file around a line or the current breakpoint
+      
+      local line, file, before, after = getargs('LFNN')
+      if before == 0 then before = 10     end
+      if after  == 0 then after  = before end
+      
+      if file ~= '' and file ~= "=stdin" then
+        show(file,line,before,after)
+      else
+        io.write('Nothing to show\n')
+      end
+      
+      --}}}
+
+    elseif command == "poff" then
+      --{{{  turn pause command off
+      pause_off = true
+      --}}}
+
+    elseif command == "pon" then
+      --{{{  turn pause command on
+      pause_off = false
+      --}}}
+
+    elseif command == "tron" then
+      --{{{  turn tracing on/off
+      local option = getargs('S')
+      trace_calls   = false
+      trace_returns = false
+      trace_lines   = false
+      if string.find(option,'c') then trace_calls   = true end
+      if string.find(option,'r') then trace_returns = true end
+      if string.find(option,'l') then trace_lines   = true end
+      --}}}
+
+    elseif command == "trace" then
+      --{{{  dump a stack trace
+      trace(eval_env.__VARSLEVEL__)
+      --}}}
+
+    elseif command == "info" then
+      --{{{  dump all debug info captured
+      info()
+      --}}}
+
+    elseif command == "pause" then
+      --{{{  not allowed in here
+      io.write('pause() should only be used in the script you are debugging\n')
+      --}}}
+
+    elseif command == "help" then
+      --{{{  help
+      local command = getargs('S')
+      if command ~= '' and hints[command] then
+        io.write(hints[command]..'\n')
+      else
+        for _,v in pairs(hints) do
+          local _,_,h = string.find(v,"(.+)|")
+          io.write(h..'\n')
+        end
+      end
+      --}}}
+
+    elseif command == "exit" then
+      --{{{  exit debugger
+      return 'stop'
+      --}}}
+
+    elseif line ~= '' then
+      --{{{  just execute whatever it is in the current context
+      
+      --map line starting with "=..." to "return ..."
+      if string.sub(line,1,1) == '=' then line = string.gsub(line,'=','return ',1) end
+      
+      local ok, func = pcall(loadstring,line)
+      if func == nil then                             --Michael.Bringmann@lsi.com
+        io.write("Compile error: "..line..'\n')
+      elseif not ok then
+        io.write("Compile error: "..func..'\n')
+      else
+        setfenv(func, eval_env)
+        local res = {pcall(func)}
+        if res[1] then
+          if res[2] then
+            table.remove(res,1)
+            for _,v in ipairs(res) do
+              io.write(tostring(v))
+              io.write('\t')
+            end
+            io.write('\n')
+          end
+          --update in the context
+          eval_env, breakfile, breakline = report(coroutine.yield(0))
+        else
+          io.write("Run error: "..res[2]..'\n')
+        end
+      end
+      
+      --}}}
+    end
+  end
+
+end
+
+--}}}
+
+--{{{  coroutine.create
+
+--This function overrides the built-in for the purposes of propagating
+--the debug hook settings from the creator into the created coroutine.
+
+_G.coroutine.create = function(f)
+  local thread
+  local hook, mask, count = debug.gethook()
+  if hook then
+    local function thread_hook(event,line)
+      hook(event,line,3,thread)
+    end
+    thread = cocreate(function(...)
+                        stack_level[thread] = 0
+                        trace_level[thread] = 0
+                        step_level [thread] = 0
+                        debug.sethook(thread_hook,mask,count)
+                        return f(...)
+                      end)
+    return thread
+  else
+    return cocreate(f)
+  end
+end
+
+--}}}
+--{{{  coroutine.wrap
+
+--This function overrides the built-in for the purposes of propagating
+--the debug hook settings from the creator into the created coroutine.
+
+_G.coroutine.wrap = function(f)
+  local thread
+  local hook, mask, count = debug.gethook()
+  if hook then
+    local function thread_hook(event,line)
+      hook(event,line,3,thread)
+    end
+    thread = cowrap(function(...)
+                      stack_level[thread] = 0
+                      trace_level[thread] = 0
+                      step_level [thread] = 0
+                      debug.sethook(thread_hook,mask,count)
+                      return f(...)
+                    end)
+    return thread
+  else
+    return cowrap(f)
+  end
+end
+
+--}}}
+
+--{{{  function pause()
+
+--
+-- Starts/resumes a debug session
+--
+
+function pause(x)
+  if pause_off then return end               --being told to ignore pauses
+  pausemsg = x or 'pause'
+  local lines
+  local src = getinfo(2,'short_src')
+  if src == "stdin" then
+    lines = 1   --if in a console session, stop now
+  else
+    lines = 2   --if in a script, stop when get out of pause()
+  end
+  if started then
+    --we'll stop now 'cos the existing debug hook will grab us
+    step_lines = lines
+    step_into  = true
+  else
+    coro_debugger = cocreate(debugger_loop)  --NB: Use original coroutune.create
+    --set to stop when get out of pause()
+    trace_level[current_thread] = 0
+    step_level [current_thread] = 0
+    stack_level[current_thread] = 1
+    step_lines = lines
+    step_into  = true
+    started    = true
+    debug.sethook(debug_hook, "crl")         --NB: this will cause an immediate entry to the debugger_loop
+  end
+end
+
+--}}}
+--{{{  function dump()
+
+--shows the value of the given variable, only really useful
+--when the variable is a table
+--see dump debug command hints for full semantics
+
+function dump(v,depth)
+  dumpvar(v,(depth or 1)+1,tostring(v))
+end
+
+--}}}
+--{{{  function debug.traceback(x)
+
+local _traceback = debug.traceback       --note original function
+
+--override standard function
+debug.traceback = function(x)
+  local assertmsg = _traceback(x)        --do original function
+  pause(x)                               --let user have a look at stuff
+  return assertmsg                       --carry on
+end
+
+_TRACEBACK = debug.traceback             --Lua 5.0 function
+
+--}}}
+
Index: /code/branches/RacingBots_FS18/data/lua/LuaStateInit.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/lua/LuaStateInit.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/lua/LuaStateInit.lua	(revision 11817)
@@ -0,0 +1,139 @@
+-- Note: luaState is a pointer to the LuaState instance that created this lua state
+
+-- Redirect print to the C++ print function
+original_print = print
+print = function(s)
+  luaState:luaPrint(s)
+end
+
+-- Prints output to the console and the logfile
+--
+-- Accepts the following arguments:
+--   orxout("message")
+--   orxout(orxonox.level.levelname, "message")
+--   orxout(orxonox.level.levelname, "context", "message)
+orxout = function(arg1, arg2, arg3)
+  if arg1 and arg2 and arg3 then
+    luaState:luaOutput(arg1, arg2, arg3)
+  elseif arg1 and arg2 then
+    luaState:luaOutput(arg1, arg2)
+  else
+    luaState:luaOutput(arg1)
+  end
+end
+
+-- Redirect dofile in order to load with the resource manager
+original_dofile = dofile
+dofile = function(filename)
+  if not luaState:doFile(filename) then
+    error("Error propagation. Do not display")
+  end
+  -- Required because if the file returns a table, it cannot be passed through the C++ function
+  return LuaStateReturnValue -- C-injected global variable
+end
+doFile = dofile
+
+-- Create includeFile function that preparses the file according
+-- to a function provided to the LuaState constructor (in C++)
+include = function(filename)
+  if not luaState:includeFile(filename) then
+    error("Error propagation. Do not display")
+  end
+  -- Required because if the file returns a table, it cannot be passed through the C++ function
+  return LuaStateReturnValue -- C-injected global variable
+end
+
+-- Replace require function with almost similar behaviour
+-- The loaded modules are then stored with their names (where name has no .lua extension)
+-- Furthermore the ".lua" extension is appended to the moduleName parameter when looking for the file
+original_require = require
+_REQUIREDNAME = ""
+LuaStateReturnValue = true
+require = function(moduleName)
+  if not luaState:fileExists(moduleName .. ".lua") then
+    orxout(orxonox.level.internal_warning, "Warning: Lua function require() could not find file '" .. moduleName .. ".lua' ")
+    return nil
+  end
+
+  if not _LOADED then
+    _LOADED = {}
+  end
+  if not _LOADED_RETURN_VALUES then
+      _LOADED_RETURN_VALUES = {}
+  end
+
+  if not _LOADED[moduleName] then
+    -- save old value for the required name
+    local _REQUIREDNAME_OLD = _REQUIREDNAME
+    _REQUIREDNAME = moduleName
+
+    if not luaState:doFile(moduleName .. ".lua") then
+      error("Error propagation. Do not display")
+    end
+    -- LuaStateReturnValue is required because if the file returns a table,
+    -- it cannot be passed through the C++ function
+    _LOADED_RETURN_VALUES[moduleName] = LuaStateReturnValue
+    _LOADED[moduleName] = true
+
+    -- restore old value
+    _REQUIREDNAME = _REQUIREDNAME_OLD
+  end
+  local asdf = _LOADED_RETURN_VALUES[moduleName]
+  return asdf
+end
+
+
+-- Load useful tool functions (like handleDefaultArgument)
+require("Tools")
+
+
+-- Include command line debugger for lua 5.1
+-- Note: It doesn't work if the IOConsole was started. Then we replace pause() with a warning
+if _VERSION ~= "Lua 5.0"  and not luaState:usingIOConsole() then
+  require("Debugger")
+else
+  -- Fallback pause function
+  pause = function()
+    orxout(orxonox.level.internal_warning, [["Warning: debug() called in Lua, but Debugger is not active.
+Do you have the IOConsole disabled and are you using Lua version 5.1?"]])
+  end
+end
+
+-- General error handler that gets called whenever an error happens at runtime
+errorHandler = function(err)
+  if type(err) == "string" then
+    -- Simply return if the error has already been handled
+    if string.find(err, "Error propagation. Do not display") ~= nil then
+      return err
+    end
+    -- Display the error message
+    orxout(orxonox.level.internal_error, "Lua runtime error: "..err)
+  end
+
+  -- Start debugger if possible
+  if _LOADED and _LOADED["Debugger"] ~= nil then
+    pause()
+  else
+    -- Fallback: print stack trace
+    orxout(orxonox.level.internal_error, debug.traceback(""))
+  end
+  return err -- Hello Lua debugger user! Please type 'set 2' to get to the
+             -- actual position in the stack where the error occurred
+end
+
+
+-- Convenience function for console commands
+orxonox.execute = function(command)
+  orxonox.CommandExecutor:execute(command)
+end
+
+-- Convenience function for config values
+orxonox.getConfig = function(section, entry)
+  return orxonox.SettingsConfigFile:getInstance():getConfig(section, entry)
+end
+orxonox.config = function(section, entry, value)
+  return orxonox.SettingsConfigFile:getInstance():config(section, entry, value)
+end
+orxonox.tconfig = function(section, entry, value)
+  return orxonox.SettingsConfigFile:getInstance():tconfig(section, entry, value)
+end
Index: /code/branches/RacingBots_FS18/data/lua/Strict.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/lua/Strict.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/lua/Strict.lua	(revision 11817)
@@ -0,0 +1,39 @@
+--
+-- strict.lua
+-- checks uses of undeclared global variables
+-- All global variables must be 'declared' through a regular assignment
+-- (even assigning nil will do) in a main chunk before being used
+-- anywhere or assigned to inside a function.
+--
+
+local mt = getmetatable(_G)
+if mt == nil then
+  mt = {}
+  setmetatable(_G, mt)
+end
+
+__STRICT = false
+mt.__declared = {}
+
+mt.__newindex = function (t, n, v)
+  if __STRICT and not mt.__declared[n] then
+    local d = debug.getinfo(2, "S")
+    local w = d and d.what or "C"
+    if w ~= "main" and w ~= "C" then
+      error("assign to undeclared variable '"..n.."'", 2)
+    end
+    mt.__declared[n] = true
+  end
+  rawset(t, n, v)
+end
+  
+mt.__index = function (t, n)
+  if not mt.__declared[n] and debug.getinfo(2, "S").what ~= "C" then
+    error("variable '"..n.."' is not declared", 2)
+  end
+  return rawget(t, n)
+end
+
+function global(...)
+   for _, v in ipairs{...} do mt.__declared[v] = true end
+end
Index: /code/branches/RacingBots_FS18/data/lua/Tools.lua
===================================================================
--- /code/branches/RacingBots_FS18/data/lua/Tools.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/lua/Tools.lua	(revision 11817)
@@ -0,0 +1,20 @@
+function handleDefArg(argument, defaultValue)
+    if argument == nil then
+        return defaultValue
+    else
+        return argument
+    end
+end
+
+function table.findIndex(table, value)
+    for i, v in ipairs(table) do
+        if v == value then
+            return i
+        end
+    end
+    return 0
+end
+
+-- Shortcuts for tribool
+tribool  = orxonox.tribool
+dontcare = orxonox.dontcare_keyword_t()
Index: /code/branches/RacingBots_FS18/data/mac/English.lproj/InfoPlist.strings
===================================================================
--- /code/branches/RacingBots_FS18/data/mac/English.lproj/InfoPlist.strings	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/mac/English.lproj/InfoPlist.strings	(revision 11817)
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
Index: /code/branches/RacingBots_FS18/data/mac/English.lproj/MainMenu.nib/designable.nib
===================================================================
--- /code/branches/RacingBots_FS18/data/mac/English.lproj/MainMenu.nib/designable.nib	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/mac/English.lproj/MainMenu.nib/designable.nib	(revision 11817)
@@ -0,0 +1,734 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1060</int>
+		<string key="IBDocument.SystemVersion">10J567</string>
+		<string key="IBDocument.InterfaceBuilderVersion">823</string>
+		<string key="IBDocument.AppKitVersion">1038.35</string>
+		<string key="IBDocument.HIToolboxVersion">462.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">823</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1021">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomObject" id="1014">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1050">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomObject" id="163992474">
+				<string key="NSClassName">NSFontManager</string>
+			</object>
+			<object class="NSMenu" id="649796088">
+				<string key="NSTitle">Orxonox</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="694149608">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Orxonox</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<object class="NSCustomResource" key="NSOnImage" id="353210768">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuCheckmark</string>
+						</object>
+						<object class="NSCustomResource" key="NSMixedImage" id="549394948">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuMixedState</string>
+						</object>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="110575045">
+							<string key="NSTitle">Orxonox</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238522557">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">About Orxonox</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="304266470">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="609285721">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Preferences…</string>
+									<string key="NSKeyEquiv">,</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="481834944">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="1046388886">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<string key="NSTitle">Services</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="752062318">
+										<string key="NSTitle">Services</string>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+										</object>
+										<string key="NSName">_NSServicesMenu</string>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="646227648">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="755159360">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Orxonox</string>
+									<string key="NSKeyEquiv">h</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="342932134">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Others</string>
+									<string key="NSKeyEquiv">h</string>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="908899353">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Show All</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="1056857174">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="632727374">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Quit Orxonox</string>
+									<string key="NSKeyEquiv">q</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+							</object>
+							<string key="NSName">_NSAppleMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="713487014">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Window</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="353210768"/>
+						<reference key="NSMixedImage" ref="549394948"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="835318025">
+							<string key="NSTitle">Window</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="1011231497">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Minimize</string>
+									<string key="NSKeyEquiv">m</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="575023229">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Zoom</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="299356726">
+									<reference key="NSMenu" ref="835318025"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="625202149">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Bring All to Front</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+							</object>
+							<string key="NSName">_NSWindowsMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="391199113">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Help</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="353210768"/>
+						<reference key="NSMixedImage" ref="549394948"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="374024848">
+							<string key="NSTitle">Help</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238773614">
+									<reference key="NSMenu" ref="374024848"/>
+									<string key="NSTitle">Orxonox Help</string>
+									<string key="NSKeyEquiv">?</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+							</object>
+							<string key="NSName">_NSHelpMenu</string>
+						</object>
+					</object>
+				</object>
+				<string key="NSName">_NSMainMenu</string>
+			</object>
+			<object class="NSCustomObject" id="505502289">
+				<string key="NSClassName">OrxonoxAppDelegate</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performMiniaturize:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1011231497"/>
+					</object>
+					<int key="connectionID">37</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">arrangeInFront:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="625202149"/>
+					</object>
+					<int key="connectionID">39</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">orderFrontStandardAboutPanel:</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="238522557"/>
+					</object>
+					<int key="connectionID">142</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performZoom:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="575023229"/>
+					</object>
+					<int key="connectionID">240</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">showHelp:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="238773614"/>
+					</object>
+					<int key="connectionID">360</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="755159360"/>
+					</object>
+					<int key="connectionID">369</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hideOtherApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="342932134"/>
+					</object>
+					<int key="connectionID">370</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">unhideAllApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="908899353"/>
+					</object>
+					<int key="connectionID">372</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="505502289"/>
+					</object>
+					<int key="connectionID">822</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">terminate:</string>
+						<reference key="source" ref="1050"/>
+						<reference key="destination" ref="632727374"/>
+					</object>
+					<int key="connectionID">823</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1048"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1021"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1014"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1050"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="649796088"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="713487014"/>
+							<reference ref="391199113"/>
+							<reference ref="694149608"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Orxonox Main Menu</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="713487014"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="835318025"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">56</int>
+						<reference key="object" ref="694149608"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="110575045"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">103</int>
+						<reference key="object" ref="391199113"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="374024848"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">106</int>
+						<reference key="object" ref="374024848"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238773614"/>
+						</object>
+						<reference key="parent" ref="391199113"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">111</int>
+						<reference key="object" ref="238773614"/>
+						<reference key="parent" ref="374024848"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">57</int>
+						<reference key="object" ref="110575045"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238522557"/>
+							<reference ref="755159360"/>
+							<reference ref="908899353"/>
+							<reference ref="632727374"/>
+							<reference ref="646227648"/>
+							<reference ref="609285721"/>
+							<reference ref="481834944"/>
+							<reference ref="304266470"/>
+							<reference ref="1046388886"/>
+							<reference ref="1056857174"/>
+							<reference ref="342932134"/>
+						</object>
+						<reference key="parent" ref="694149608"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">58</int>
+						<reference key="object" ref="238522557"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">134</int>
+						<reference key="object" ref="755159360"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">150</int>
+						<reference key="object" ref="908899353"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="632727374"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">144</int>
+						<reference key="object" ref="646227648"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">129</int>
+						<reference key="object" ref="609285721"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="481834944"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">236</int>
+						<reference key="object" ref="304266470"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="1046388886"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="752062318"/>
+						</object>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="1056857174"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">145</int>
+						<reference key="object" ref="342932134"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">130</int>
+						<reference key="object" ref="752062318"/>
+						<reference key="parent" ref="1046388886"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="835318025"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="299356726"/>
+							<reference ref="625202149"/>
+							<reference ref="575023229"/>
+							<reference ref="1011231497"/>
+						</object>
+						<reference key="parent" ref="713487014"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">92</int>
+						<reference key="object" ref="299356726"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="625202149"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">239</int>
+						<reference key="object" ref="575023229"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="1011231497"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">373</int>
+						<reference key="object" ref="163992474"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">821</int>
+						<reference key="object" ref="505502289"/>
+						<reference key="parent" ref="0"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-3.IBPluginDependency</string>
+					<string>103.IBPluginDependency</string>
+					<string>103.ImportedFromIB2</string>
+					<string>106.IBEditorWindowLastContentRect</string>
+					<string>106.IBPluginDependency</string>
+					<string>106.ImportedFromIB2</string>
+					<string>106.editorWindowContentRectSynchronizationRect</string>
+					<string>111.IBPluginDependency</string>
+					<string>111.ImportedFromIB2</string>
+					<string>129.IBPluginDependency</string>
+					<string>129.ImportedFromIB2</string>
+					<string>130.IBEditorWindowLastContentRect</string>
+					<string>130.IBPluginDependency</string>
+					<string>130.ImportedFromIB2</string>
+					<string>130.editorWindowContentRectSynchronizationRect</string>
+					<string>131.IBPluginDependency</string>
+					<string>131.ImportedFromIB2</string>
+					<string>134.IBPluginDependency</string>
+					<string>134.ImportedFromIB2</string>
+					<string>136.IBPluginDependency</string>
+					<string>136.ImportedFromIB2</string>
+					<string>143.IBPluginDependency</string>
+					<string>143.ImportedFromIB2</string>
+					<string>144.IBPluginDependency</string>
+					<string>144.ImportedFromIB2</string>
+					<string>145.IBPluginDependency</string>
+					<string>145.ImportedFromIB2</string>
+					<string>149.IBPluginDependency</string>
+					<string>149.ImportedFromIB2</string>
+					<string>150.IBPluginDependency</string>
+					<string>150.ImportedFromIB2</string>
+					<string>19.IBPluginDependency</string>
+					<string>19.ImportedFromIB2</string>
+					<string>23.IBPluginDependency</string>
+					<string>23.ImportedFromIB2</string>
+					<string>236.IBPluginDependency</string>
+					<string>236.ImportedFromIB2</string>
+					<string>239.IBPluginDependency</string>
+					<string>239.ImportedFromIB2</string>
+					<string>24.IBEditorWindowLastContentRect</string>
+					<string>24.IBPluginDependency</string>
+					<string>24.ImportedFromIB2</string>
+					<string>24.editorWindowContentRectSynchronizationRect</string>
+					<string>29.IBEditorWindowLastContentRect</string>
+					<string>29.IBPluginDependency</string>
+					<string>29.ImportedFromIB2</string>
+					<string>29.WindowOrigin</string>
+					<string>29.editorWindowContentRectSynchronizationRect</string>
+					<string>5.IBPluginDependency</string>
+					<string>5.ImportedFromIB2</string>
+					<string>56.IBPluginDependency</string>
+					<string>56.ImportedFromIB2</string>
+					<string>57.IBEditorWindowLastContentRect</string>
+					<string>57.IBPluginDependency</string>
+					<string>57.ImportedFromIB2</string>
+					<string>57.editorWindowContentRectSynchronizationRect</string>
+					<string>58.IBPluginDependency</string>
+					<string>58.ImportedFromIB2</string>
+					<string>821.IBPluginDependency</string>
+					<string>92.IBPluginDependency</string>
+					<string>92.ImportedFromIB2</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{593, 709}, {166, 23}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{596, 852}, {216, 23}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{674, 654}, {64, 6}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{436, 809}, {64, 6}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{523, 657}, {194, 73}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{525, 802}, {197, 73}}</string>
+					<string>{{431, 730}, {224, 20}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{74, 862}</string>
+					<string>{{11, 977}, {478, 20}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{443, 547}, {195, 183}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{23, 794}, {245, 183}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">823</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">OrxonoxAppDelegate</string>
+					<string key="superclassName">NSObject</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>NSMenuCheckmark</string>
+				<string>NSMenuMixedState</string>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>{9, 8}</string>
+				<string>{7, 2}</string>
+			</object>
+		</object>
+	</data>
+</archive>
Index: /code/branches/RacingBots_FS18/data/mac/English.lproj/MainMenu.xib
===================================================================
--- /code/branches/RacingBots_FS18/data/mac/English.lproj/MainMenu.xib	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/mac/English.lproj/MainMenu.xib	(revision 11817)
@@ -0,0 +1,734 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1060</int>
+		<string key="IBDocument.SystemVersion">10J567</string>
+		<string key="IBDocument.InterfaceBuilderVersion">823</string>
+		<string key="IBDocument.AppKitVersion">1038.35</string>
+		<string key="IBDocument.HIToolboxVersion">462.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">823</string>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1021">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomObject" id="1014">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1050">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomObject" id="163992474">
+				<string key="NSClassName">NSFontManager</string>
+			</object>
+			<object class="NSMenu" id="649796088">
+				<string key="NSTitle">Orxonox</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="694149608">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Orxonox</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<object class="NSCustomResource" key="NSOnImage" id="353210768">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuCheckmark</string>
+						</object>
+						<object class="NSCustomResource" key="NSMixedImage" id="549394948">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuMixedState</string>
+						</object>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="110575045">
+							<string key="NSTitle">Orxonox</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238522557">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">About Orxonox</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="304266470">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="609285721">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Preferences…</string>
+									<string key="NSKeyEquiv">,</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="481834944">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="1046388886">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<string key="NSTitle">Services</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="752062318">
+										<string key="NSTitle">Services</string>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+										</object>
+										<string key="NSName">_NSServicesMenu</string>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="646227648">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="755159360">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Orxonox</string>
+									<string key="NSKeyEquiv">h</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="342932134">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Others</string>
+									<string key="NSKeyEquiv">h</string>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="908899353">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Show All</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="1056857174">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="632727374">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Quit Orxonox</string>
+									<string key="NSKeyEquiv">q</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+							</object>
+							<string key="NSName">_NSAppleMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="713487014">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Window</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="353210768"/>
+						<reference key="NSMixedImage" ref="549394948"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="835318025">
+							<string key="NSTitle">Window</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="1011231497">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Minimize</string>
+									<string key="NSKeyEquiv">m</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="575023229">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Zoom</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="299356726">
+									<reference key="NSMenu" ref="835318025"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+								<object class="NSMenuItem" id="625202149">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Bring All to Front</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+							</object>
+							<string key="NSName">_NSWindowsMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="391199113">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Help</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="353210768"/>
+						<reference key="NSMixedImage" ref="549394948"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="374024848">
+							<string key="NSTitle">Help</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238773614">
+									<reference key="NSMenu" ref="374024848"/>
+									<string key="NSTitle">Orxonox Help</string>
+									<string key="NSKeyEquiv">?</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="353210768"/>
+									<reference key="NSMixedImage" ref="549394948"/>
+								</object>
+							</object>
+							<string key="NSName">_NSHelpMenu</string>
+						</object>
+					</object>
+				</object>
+				<string key="NSName">_NSMainMenu</string>
+			</object>
+			<object class="NSCustomObject" id="505502289">
+				<string key="NSClassName">OrxonoxAppDelegate</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performMiniaturize:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1011231497"/>
+					</object>
+					<int key="connectionID">37</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">arrangeInFront:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="625202149"/>
+					</object>
+					<int key="connectionID">39</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">orderFrontStandardAboutPanel:</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="238522557"/>
+					</object>
+					<int key="connectionID">142</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performZoom:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="575023229"/>
+					</object>
+					<int key="connectionID">240</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">showHelp:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="238773614"/>
+					</object>
+					<int key="connectionID">360</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="755159360"/>
+					</object>
+					<int key="connectionID">369</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hideOtherApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="342932134"/>
+					</object>
+					<int key="connectionID">370</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">unhideAllApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="908899353"/>
+					</object>
+					<int key="connectionID">372</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="505502289"/>
+					</object>
+					<int key="connectionID">822</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">terminate:</string>
+						<reference key="source" ref="1050"/>
+						<reference key="destination" ref="632727374"/>
+					</object>
+					<int key="connectionID">823</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1048"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1021"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1014"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1050"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="649796088"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="713487014"/>
+							<reference ref="391199113"/>
+							<reference ref="694149608"/>
+						</object>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Orxonox Main Menu</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="713487014"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="835318025"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">56</int>
+						<reference key="object" ref="694149608"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="110575045"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">103</int>
+						<reference key="object" ref="391199113"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="374024848"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">106</int>
+						<reference key="object" ref="374024848"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238773614"/>
+						</object>
+						<reference key="parent" ref="391199113"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">111</int>
+						<reference key="object" ref="238773614"/>
+						<reference key="parent" ref="374024848"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">57</int>
+						<reference key="object" ref="110575045"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238522557"/>
+							<reference ref="755159360"/>
+							<reference ref="908899353"/>
+							<reference ref="632727374"/>
+							<reference ref="646227648"/>
+							<reference ref="609285721"/>
+							<reference ref="481834944"/>
+							<reference ref="304266470"/>
+							<reference ref="1046388886"/>
+							<reference ref="1056857174"/>
+							<reference ref="342932134"/>
+						</object>
+						<reference key="parent" ref="694149608"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">58</int>
+						<reference key="object" ref="238522557"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">134</int>
+						<reference key="object" ref="755159360"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">150</int>
+						<reference key="object" ref="908899353"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="632727374"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">144</int>
+						<reference key="object" ref="646227648"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">129</int>
+						<reference key="object" ref="609285721"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="481834944"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">236</int>
+						<reference key="object" ref="304266470"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="1046388886"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="752062318"/>
+						</object>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="1056857174"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">145</int>
+						<reference key="object" ref="342932134"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">130</int>
+						<reference key="object" ref="752062318"/>
+						<reference key="parent" ref="1046388886"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="835318025"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="299356726"/>
+							<reference ref="625202149"/>
+							<reference ref="575023229"/>
+							<reference ref="1011231497"/>
+						</object>
+						<reference key="parent" ref="713487014"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">92</int>
+						<reference key="object" ref="299356726"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">5</int>
+						<reference key="object" ref="625202149"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">239</int>
+						<reference key="object" ref="575023229"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="1011231497"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">373</int>
+						<reference key="object" ref="163992474"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">821</int>
+						<reference key="object" ref="505502289"/>
+						<reference key="parent" ref="0"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-3.IBPluginDependency</string>
+					<string>103.IBPluginDependency</string>
+					<string>103.ImportedFromIB2</string>
+					<string>106.IBEditorWindowLastContentRect</string>
+					<string>106.IBPluginDependency</string>
+					<string>106.ImportedFromIB2</string>
+					<string>106.editorWindowContentRectSynchronizationRect</string>
+					<string>111.IBPluginDependency</string>
+					<string>111.ImportedFromIB2</string>
+					<string>129.IBPluginDependency</string>
+					<string>129.ImportedFromIB2</string>
+					<string>130.IBEditorWindowLastContentRect</string>
+					<string>130.IBPluginDependency</string>
+					<string>130.ImportedFromIB2</string>
+					<string>130.editorWindowContentRectSynchronizationRect</string>
+					<string>131.IBPluginDependency</string>
+					<string>131.ImportedFromIB2</string>
+					<string>134.IBPluginDependency</string>
+					<string>134.ImportedFromIB2</string>
+					<string>136.IBPluginDependency</string>
+					<string>136.ImportedFromIB2</string>
+					<string>143.IBPluginDependency</string>
+					<string>143.ImportedFromIB2</string>
+					<string>144.IBPluginDependency</string>
+					<string>144.ImportedFromIB2</string>
+					<string>145.IBPluginDependency</string>
+					<string>145.ImportedFromIB2</string>
+					<string>149.IBPluginDependency</string>
+					<string>149.ImportedFromIB2</string>
+					<string>150.IBPluginDependency</string>
+					<string>150.ImportedFromIB2</string>
+					<string>19.IBPluginDependency</string>
+					<string>19.ImportedFromIB2</string>
+					<string>23.IBPluginDependency</string>
+					<string>23.ImportedFromIB2</string>
+					<string>236.IBPluginDependency</string>
+					<string>236.ImportedFromIB2</string>
+					<string>239.IBPluginDependency</string>
+					<string>239.ImportedFromIB2</string>
+					<string>24.IBEditorWindowLastContentRect</string>
+					<string>24.IBPluginDependency</string>
+					<string>24.ImportedFromIB2</string>
+					<string>24.editorWindowContentRectSynchronizationRect</string>
+					<string>29.IBEditorWindowLastContentRect</string>
+					<string>29.IBPluginDependency</string>
+					<string>29.ImportedFromIB2</string>
+					<string>29.WindowOrigin</string>
+					<string>29.editorWindowContentRectSynchronizationRect</string>
+					<string>5.IBPluginDependency</string>
+					<string>5.ImportedFromIB2</string>
+					<string>56.IBPluginDependency</string>
+					<string>56.ImportedFromIB2</string>
+					<string>57.IBEditorWindowLastContentRect</string>
+					<string>57.IBPluginDependency</string>
+					<string>57.ImportedFromIB2</string>
+					<string>57.editorWindowContentRectSynchronizationRect</string>
+					<string>58.IBPluginDependency</string>
+					<string>58.ImportedFromIB2</string>
+					<string>821.IBPluginDependency</string>
+					<string>92.IBPluginDependency</string>
+					<string>92.ImportedFromIB2</string>
+				</object>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{593, 709}, {166, 23}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{596, 852}, {216, 23}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{674, 654}, {64, 6}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{436, 809}, {64, 6}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{523, 657}, {194, 73}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{525, 802}, {197, 73}}</string>
+					<string>{{431, 730}, {224, 20}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{74, 862}</string>
+					<string>{{11, 977}, {478, 20}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{443, 547}, {195, 183}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>{{23, 794}, {245, 183}}</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<integer value="1"/>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<object class="NSMutableArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+				</object>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">823</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">OrxonoxAppDelegate</string>
+					<string key="superclassName">NSObject</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBUserSource</string>
+						<string key="minorKey"/>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<nil key="IBDocument.LastKnownRelativeProjectPath"/>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>NSMenuCheckmark</string>
+				<string>NSMenuMixedState</string>
+			</object>
+			<object class="NSMutableArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>{9, 8}</string>
+				<string>{7, 2}</string>
+			</object>
+		</object>
+	</data>
+</archive>
Index: /code/branches/RacingBots_FS18/data/mac/Orxonox-Info.plist
===================================================================
--- /code/branches/RacingBots_FS18/data/mac/Orxonox-Info.plist	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/mac/Orxonox-Info.plist	(revision 11817)
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>English</string>
+	<key>CFBundleExecutable</key>
+	<string>${EXECUTABLE_NAME}</string>
+	<key>CFBundleIconFile</key>
+	<string>Icon.icns</string>
+	<key>CFBundleIdentifier</key>
+	<string>net.orxonox.${PROJECT_NAME}</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>${PROJECT_NAME}</string>
+	<key>CFBundleVersion</key>
+	<string>${ORXONOX_VERSION}</string>
+	<key>CFBundleShortVersionString</key>
+	<string>${ORXONOX_VERSION}, ${ORXONOX_VERSION_NAME}</string>
+	<key>CFBundleGetInfoString</key>
+	<string>Orxonox: The hottest space shooter ever to exist!</string>
+	<key>NSHumanReadableCopyright</key>
+	<string>GPL version 2 or higher, and CC-BY-SA</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.5</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+</dict>
+</plist>
Index: /code/branches/RacingBots_FS18/data/overlays/Asteroids2DHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/Asteroids2DHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/Asteroids2DHUD.oxo	(revision 11817)
@@ -0,0 +1,84 @@
+<Template name="spectatorhud">
+  <OverlayGroup name = "spectatorhud" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+
+<Template name="Asteroids2DHUD">
+  <OverlayGroup name="Asteroids2DHUD" scale = "1, 1">
+
+    <OverlayText
+     position  = "0.02, 0.1"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Lives:   "
+    />
+
+    <Asteroids2DHUDinfo
+     position  = "0.14, 0.1"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = true
+     showlevel     = false
+     showpoints     = false
+    />
+
+    <OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Points: "
+    />
+
+    <Asteroids2DHUDinfo
+     position  = "0.14, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showpoints     = true
+    />
+
+    <OverlayText
+     position  = "0.02, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Level: "
+    />
+
+    <Asteroids2DHUDinfo
+     position  = "0.14, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = false
+     showlevel     = true
+     showpoints     = false
+    />
+
+    
+  </OverlayGroup>
+</Template>
+
+<Template name="spaceshiphud">
+  <OverlayGroup name = "spaceshiphud" scale = "1, 1">
+    
+ </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/DodgeRaceHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/DodgeRaceHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/DodgeRaceHUD.oxo	(revision 11817)
@@ -0,0 +1,38 @@
+<Template name="spectatorhud">
+  <OverlayGroup name = "spectatorhud" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+
+<Template name="DodgeRaceHUD">
+  <OverlayGroup name="DodgeRaceHUD" scale = "1, 1">
+
+    <OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Points: "
+    />
+
+    <DodgeRaceHUDinfo
+     position  = "0.14, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showpoints     = true
+    />
+
+    
+  </OverlayGroup>
+</Template>
+
+<Template name="spaceshiphud">
+  <OverlayGroup name = "spaceshiphud" scale = "1, 1">
+    
+ </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/FlappyOrxHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/FlappyOrxHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/FlappyOrxHUD.oxo	(revision 11817)
@@ -0,0 +1,69 @@
+<Template name="spectatorhud">
+  <OverlayGroup name = "spectatorhud" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+<Template name="FlappyOrxHUD">
+  <OverlayGroup name="FlappyOrxHUD" scale = "1, 1">
+   
+    <FlappyOrxHUDinfo
+     position  = "0.02, 0.01"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showpoints     = true
+    />
+
+    <FlappyOrxHUDinfo
+     position  = "0.5, 0.5"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 0.0, 0.0, 1.0"
+     align     = "center"
+
+     showmessage     = true
+     messageID = 0
+
+    />
+
+    <FlappyOrxHUDinfo
+         position  = "0.5, 0.6"
+         pickpoint = "0.0, 0.0"
+         font      = "ShareTechMono"
+         textsize  = 0.04
+         colour    = "1.0, 1.0, 1.0, 1.0"
+         align     = "center"
+
+         showmessage     = true
+         messageID = 1
+    />
+    <FlappyOrxHUDinfo
+     position  = "0.5, 0.65"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "center"
+
+     showmessage     = true
+     messageID = 2
+    />
+    <FlappyOrxHUDinfo
+     position  = "0.5, 0.7"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "center"
+
+     showmessage     = true
+     messageID = 3
+
+    />
+
+    
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/HUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/HUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/HUD.oxo	(revision 11817)
@@ -0,0 +1,109 @@
+<!-- HUD OVERLAY -->
+<OverlayGroup name = "HUD" scale = "1, 1">
+
+  <HUDSpeedBar
+   name       = "SpeedBar1"
+   background = "Orxonox/BarBackground"
+   size       = "0.35, 0.05"
+   position   = "0.0 , 1.0 "
+   pickPoint  = "0, 1"
+   value      = 0
+  >
+    <BarColour position = 0.7 colour = "0.2,0.7,0.2" />
+    <BarColour position = 0.4 colour = "0.7,0.5,0.2" />
+    <BarColour position = 0.1 colour = "0.7,0.2,0.2" />
+  </HUDSpeedBar>
+
+  <!--HUDSpeedBar
+   name       = "SpeedBar2"
+   background = "Orxonox/BarBackground"
+   size       = "0.35, 0.05"
+   position   = "1.0 , 1.0 "
+   pickPoint  = "1, 1"
+   value      = 0
+   rightToLeft = true
+  >
+    <BarColour position = 0.7 colour = "0.2,0.7,0.2" />
+    <BarColour position = 0.4 colour = "0.7,0.5,0.2" />
+    <BarColour position = 0.1 colour = "0.7,0.2,0.2" />
+  </HUDSpeedBar>
+
+  <HUDSpeedBar
+   name       = "SpeedBar3"
+   background = "Orxonox/BarBackground"
+   size       = "0.35, 0.05"
+   position   = "1.0 , 0.0 "
+   pickPoint  = "1, 0"
+   value      = 0
+   rightToLeft = true
+  >
+    <BarColour position = 0.7 colour = "0.2,0.7,0.2" />
+    <BarColour position = 0.4 colour = "0.7,0.5,0.2" />
+    <BarColour position = 0.1 colour = "0.7,0.2,0.2" />
+  </HUDSpeedBar>
+
+  <HUDSpeedBar
+   name       = "SpeedBar4"
+   background = "Orxonox/BarBackground"
+   size       = "0.35, 0.05"
+   position   = "0.0 , 0.0 "
+   pickPoint  = "0, 0"
+   rotation   = 0
+   value      = 0
+  >
+    <BarColounar position = 0.7 colour = "0.2,0.7,0.2" />
+    <BarColour position = 0.4 colour = "0.7,0.5,0.2" />
+    <BarColour position = 0.1 colour = "0.7,0.2,0.2" />
+  </HUDSpeedBar-->
+
+  <HUDNavigation
+   name          = "Navigation"
+   correctAspect = true
+   font          = "Monofur"
+   textSize      = 0.02
+   navMarkerSize = 0.03
+   aimMarkerSize = 0.02
+  />
+
+  <HUDRadar
+   name          = "Radar"
+   background    = "Orxonox/radar"
+   correctAspect = true
+   size          = "0.17, 0.17"
+   position      = "0.5, 1.0"
+   pickPoint     = "0.5, 1.0"
+   rotation      = 0
+   sensitivity   = 1.0
+   halfDotSizeDistance = 3000
+   maximumDotSize      = 0.1
+  />
+
+  <ChatOverlay
+   name     = "chat"
+   position = "0.03, 0.5"
+   font     = "VeraMono"
+   caption  = ""
+   textSize = 0.025
+  />
+</OverlayGroup>
+
+
+<!-- DEBUG OVERLAY -->
+<OverlayGroup name = "Debug" scale = "1.0, 1.0" scroll = "0, 0" visible=false>
+
+  <DebugFPSText
+   name     = "FPSText"
+   position = "0.03, 0.05"
+   font     = "Monofur"
+   caption  = "Frames per second: "
+   textSize = 0.03
+  />
+
+  <DebugRTRText
+   name     = "RTRText"
+   position = "0.03, 0.09"
+   font     = "Monofur"
+   caption  = "Tick time in ms: "
+   textSize = 0.03
+  />
+</OverlayGroup>
Index: /code/branches/RacingBots_FS18/data/overlays/HUDTemplates3.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/HUDTemplates3.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/HUDTemplates3.oxo	(revision 11817)
@@ -0,0 +1,225 @@
+<!--
+<Template name="defaultHUD">
+  <OverlayGroup name = "defaultHUD" scale = "1, 1">
+    <ChatOverlay
+     name     = "chat"
+     position = "0.03, 0.5"
+     font     = "VeraMono"
+     caption  = ""
+     textsize = 0.025
+    />
+
+    <GametypeStatus
+     name     = "state"
+     position = "0.5, 0.85"
+     font     = "VeraMono"
+     textsize = 0.05
+     colour   = "1.0, 1.0, 0.0, 0.8"
+     align    = "center"
+    />
+  </OverlayGroup>
+</Template>
+-->
+
+<Template name="spectatorhud">
+  <OverlayGroup name = "spectatorhud" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+
+<Template name="rockethud">
+  <OverlayGroup name = "rockethud" scale = "1, 1">
+    <HUDRocketFuelBar
+     name          = "RocketFuelBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "0.0 , 1.0 "
+     pickpoint     = "0, 1"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconFuel"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDRocketFuelBar>
+  </OverlayGroup>
+</Template>
+
+<Template name="spaceshiphud">
+  <OverlayGroup name = "spaceshiphud" scale = "1, 1">
+
+
+    <HUDHealthBar
+     name              = "HealthBar1"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.40, 0.08"
+     position          = "0.0 , 0.85 "
+     pickpoint         = "0, 1"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale          = 0.4
+     textoffset        = "0.325, -0.825"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDHealthBar>
+
+    <HUDShieldBar
+     name          = "ShieldBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "0.0 , 0.9 "
+     pickpoint     = "0, 1"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconShield"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDShieldBar>    
+
+    <HUDSpeedBar
+     name          = "SpeedBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "0.0 , 0.95 "
+     pickpoint     = "0, 1"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconSpeed"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.5,0.2" />
+      <BarColour position = 0.5 colour = "0.2,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.7,0.2,0.2" />
+    </HUDSpeedBar>
+
+    <HUDBoostBar
+     name          = "BoostBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "0.0 , 1.0 "
+     pickpoint     = "0, 1"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconBoost"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDBoostBar>
+
+    <HUDEnemyHealthBar
+     name              = "EnemyHealthBar"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.4, 0.08"
+     position          = "1 ,0"
+     pickpoint         = "1, 0"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale         = 0.4
+     textoffset        = "-0.675, 0.175"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDEnemyHealthBar>
+
+    <HUDEnemyShieldBar
+     name          = "EnemyShieldBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "1.0 , 0.1 "
+     pickpoint     = "1, 0"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconShield"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDEnemyShieldBar>   
+
+    <HUDNavigation
+     name          = "Navigation"
+     correctaspect = true
+     font          = "Monofur"
+     textsize      = 0.02
+     navMarkerSize = 0.03
+     aimMarkerSize = 0.02
+    />
+
+    <HUDRadar
+     name                   = "Radar"
+     background             = "Orxonox/Radar3D"
+     material2D             = "Orxonox/Radar"
+     material3DMiddle       = "Orxonox/Radar3D"
+     material3DFront        = "Orxonox/Radar3DFront"
+     material3DBack         = "Orxonox/Radar3DBack"
+     correctaspect          = true
+     size                   = "0.17, 0.17"
+     position               = "1.0, 1.0"
+     pickpoint              = "1.0, 1.0"
+     rotation               = 0
+     sensitivity            = 1.0
+     halfDotSizeDistance    = 3000
+     detectionLimit         = 10000.0
+     maximumDotSize         = 0.1
+     maximumDotSize3D       = 0.06
+     mapAngle3D             = 0.6435011
+    />
+
+    <HUDWeaponSystem
+     name                   = "WeaponSystem"
+     correctaspect          = true
+     position               = "0.01, 0.01"
+     pickpoint              = "0, 0"
+     visible                = "true"
+     weaponModeHUDSize      = "0.09, 0.03"
+    />
+    
+    <HUDPickupSystem
+     name                   = "PickupSystem"
+     background             = "PickupBar"
+     correctaspect          = true
+     size                   = "0.20, 0.08"
+     position               = "0.01, 0.15"
+     pickpoint              = "0.0, 0.0"
+     visible                = "true"
+    />
+
+    <HUDTimer
+     name     = "Timer"
+     position = "0.5, 0.25"
+     font     = "VeraMono"
+     textsize = 0.1
+     colour   = "1.0, 1.0, 0.0, 0.8"
+     align    = "center"
+    />
+
+    <GUIOverlay
+      name = "QuestGUI"
+      guiname = "QuestGUI"
+      visible = "false"
+    />
+    
+    <GUIOverlay
+      name = "PickupInventory"
+      guiname = "PickupInventory"
+      visible = "false"
+    />
+
+    <GUIOverlay
+      name = "Dialog"
+      guiname = "Dialog"
+      visible = "false"
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/HUDTemplatesFPS.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/HUDTemplatesFPS.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/HUDTemplatesFPS.oxo	(revision 11817)
@@ -0,0 +1,136 @@
+<Template name="fpshud">
+  <OverlayGroup name = "fpshud" scale = "1, 1">
+    <HUDHealthBar
+     name              = "HealthBar1"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.40, 0.08"
+     position          = "0.0 , 0.95 "
+     pickpoint         = "0, 1"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale          = 0.4
+     textoffset        = "0.325, -0.825"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDHealthBar>
+
+    <HUDShieldBar
+     name          = "ShieldBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "0.0 , 1.0 "
+     pickpoint     = "0, 1"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconShield"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDShieldBar>
+
+    <HUDEnemyHealthBar
+     name              = "EnemyHealthBar"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.4, 0.08"
+     position          = "1 ,0"
+     pickpoint         = "1, 0"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale         = 0.4
+     textoffset        = "-0.675, 0.175"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDEnemyHealthBar>
+
+    <HUDEnemyShieldBar
+     name          = "EnemyShieldBar1"
+     background    = "Orxonox/BarBackground"
+     size          = "0.40, 0.04"
+     position      = "1.0 , 0.1 "
+     pickpoint     = "1, 0"
+     correctaspect = true
+     iconmaterial  = "Orxonox/BarIconShield"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDEnemyShieldBar> 
+
+    <HUDNavigation
+     name          = "Navigation"
+     correctaspect = true
+     font          = "Monofur"
+     textsize      = 0.02
+     navMarkerSize = 0.03
+     aimMarkerSize = 0.04
+    />
+
+    <HUDRadar
+     name          = "Radar"
+     background    = "Orxonox/Radar"
+     correctaspect = true
+     size          = "0.17, 0.17"
+     position      = "1.0, 1.0"
+     pickpoint     = "1.0, 1.0"
+     rotation      = 0
+     sensitivity   = 1.0
+     halfDotSizeDistance = 3000
+     maximumDotSize      = 0.1
+    />
+
+    <HUDWeaponSystem
+     name                   = "WeaponSystem"
+     correctaspect          = true
+     position               = "0.01, 0.01"
+     pickpoint              = "0, 0"
+     visible                = "true"
+     weaponModeHUDSize      = "0.09, 0.03"
+    />
+
+    <HUDPickupSystem
+     name                   = "PickupSystem"
+     background             = "PickupBar"
+     correctaspect          = true
+     size                   = "0.20, 0.08"
+     position               = "0.01, 0.15"
+     pickpoint              = "0.0, 0.0"
+     visible                = "true"
+    />
+
+    <HUDTimer
+     name     = "Timer"
+     position = "0.5, 0.85"
+     font     = "VeraMono"
+     textsize = 0.1
+     colour   = "1.0, 1.0, 0.0, 0.8"
+     align    = "center"
+    />
+
+    <GUIOverlay
+      name = "QuestGUI"
+      guiname = "QuestGUI"
+      visible = "false"
+    />
+    
+    <GUIOverlay
+      name = "PickupInventory"
+      guiname = "PickupInventory"
+      visible = "false"
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/HoverHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/HoverHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/HoverHUD.oxo	(revision 11817)
@@ -0,0 +1,46 @@
+<Template name="HoverHUD">
+  <OverlayGroup name="HoverHUD" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+
+
+<Template name="spaceshiphoverhud">
+  <OverlayGroup name = "spaceshiphoverhud" scale = "1, 1">
+    <TimeHUD
+     name       = "TimerHUD"
+     position  = "0.95, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "right"
+    />
+
+    <FlagHUD
+     name      = "FlagHUD"
+     position  = "0.05, 0.02"
+     size      = "0.18, 0.05"
+    />
+
+    <HUDHealthBar
+     name              = "HealthBar1"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.35, 0.0875"
+     position          = "0.0 , 0.97"
+     pickpoint         = "0, 1"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale          = 0.4
+     textoffset        = "0.325, -0.825"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDHealthBar>
+ </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/InvaderHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/InvaderHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/InvaderHUD.oxo	(revision 11817)
@@ -0,0 +1,113 @@
+<Template name="spectatorhud">
+  <OverlayGroup name = "spectatorhud" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+
+<Template name="InvaderHUD">
+  <OverlayGroup name="InvaderHUD" scale = "1, 1">
+    <InvaderHUDinfo
+     position  = "0.14, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = true
+     showlevel     = false
+     showpoints     = false
+    />
+    <OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Lives:   "
+    />
+
+    <OverlayText
+     position  = "0.02, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Level: "
+    />
+
+    <InvaderHUDinfo
+     position  = "0.14, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = false
+     showlevel     = true
+     showpoints     = false
+    />
+
+    <OverlayText
+     position  = "0.02, 0.1"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Points: "
+    />
+
+    <InvaderHUDinfo
+     position  = "0.14, 0.1"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = false
+     showlevel     = false
+     showpoints     = true
+    />
+
+    <InvaderHUDinfo
+     position  = "0.25, 0.1"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showMultiplier = true
+    />
+  </OverlayGroup>
+</Template>
+
+
+<Template name="spaceshiphud">
+  <OverlayGroup name = "spaceshiphud" scale = "1, 1">
+    <HUDHealthBar
+     name              = "HealthBar1"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.35, 0.0875"
+     position          = "0.0 , 0.9 "
+     pickpoint         = "0, 1"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale          = 0.4
+     textoffset        = "0.325, -0.825"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDHealthBar>
+ </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/SOBHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/SOBHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/SOBHUD.oxo	(revision 11817)
@@ -0,0 +1,123 @@
+<Template name="spectatorhud">
+  <OverlayGroup name = "spectatorhud" scale = "1, 1">
+  </OverlayGroup>
+</Template>
+
+<Template name="SOBHUD">
+  <OverlayGroup name="SOBHUD" scale = "1, 1">
+  
+    <OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "O R X O\n"
+    />
+    <SOBHUDInfo
+     position  = "0.02, 0.06"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.045
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     type      = "Points"
+     
+    />
+
+
+
+    <SOBHUDInfo
+     position  = "0.22, 0.06"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.045
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     type      = "Coins"
+     
+    />
+
+
+
+    <OverlayText
+     position  = "0.75, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "center"
+     caption   = "WORLD\n1-1"
+    />
+
+
+
+
+
+
+    <OverlayText
+     position  = "0.98, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "right"
+     caption   = "TIME\n"
+    />
+    <SOBHUDInfo
+     position  = "0.98, 0.06"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "right"
+     type      = "Time"
+  
+    />
+
+    
+
+    <SOBHUDInfo
+     position = "0.55,0.5"
+     pickpoint = "0.5, 0.5"
+     textposition  = "0.5, 0.5"
+     textpickpoint = "0.5, 0.5"
+     font      = "ShareTechMono"
+     textsize  = 0.07
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "center"
+     type      = "Info"
+     
+    />
+   
+
+    
+  </OverlayGroup>
+</Template>
+
+
+<Template name="spaceshiphud">
+  <OverlayGroup name = "spaceshiphud" scale = "1, 1">
+    <HUDHealthBar
+     name              = "HealthBar1"
+     background        = "Orxonox/HealthBarBackground"
+     size              = "0.35, 0.0875"
+     position          = "0.0 , 0.9 "
+     pickpoint         = "0, 1"
+     bartexture        = "healthbar_bar.png"
+     textfont          = "VeraMono"
+     textusebarcolour  = true
+     textscale          = 0.4
+     textoffset        = "0.325, -0.825"
+     textpickpoint     = "0, 0"
+     textalign         = "right"
+     correctaspect     = true
+     iconmaterial      = "Orxonox/BarIconHealth"
+    >
+      <BarColour position = 0.0 colour = "0.7,0.2,0.2" />
+      <BarColour position = 0.5 colour = "0.7,0.7,0.2" />
+      <BarColour position = 1.0 colour = "0.2,0.7,0.2" />
+    </HUDHealthBar>
+ </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/StoryModeHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/StoryModeHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/StoryModeHUD.oxo	(revision 11817)
@@ -0,0 +1,12 @@
+
+<Template name="StoryModeMap">
+  <OverlayGroup name = "spaceshiphud" scale = "1, 1">
+
+     <GUIOverlay
+      name = "CampaignMenu"
+      guiname = "CampaignMenu"
+      visible = "true"
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/StoryModeHUD2.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/StoryModeHUD2.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/StoryModeHUD2.oxo	(revision 11817)
@@ -0,0 +1,13 @@
+<Template name="StoryModeHUD2">
+  <OverlayGroup name = "StoryModeHUD2" scale = "1, 1">\
+
+    <StoryModeHUD
+     name           = "StoryMode"
+     correctaspect  = false
+     font           = "VeraMono"
+     textSize       = 0.0420
+     align          = "center"
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/debug.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/debug.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/debug.oxo	(revision 11817)
@@ -0,0 +1,102 @@
+<!-- DEBUG OVERLAY -->
+<OverlayGroup
+ name    = "Debug"
+ scale   = "1.0, 1.0"
+ scroll  = "0, 0"
+ visible = false
+>
+  <OverlayText
+   name     = "FPSTextCaption"
+   position = "0.03, 0.05"
+   font     = "Monofur"
+   caption  = "Frames per second:"
+   textsize = 0.03
+  />
+
+  <DebugFPSText
+   name     = "FPSText"
+   position = "0.3, 0.05"
+   font     = "Monofur"
+   textsize = 0.03
+  />
+
+  <OverlayText
+   name     = "RTRTextCaption"
+   position = "0.03, 0.09"
+   font     = "Monofur"
+   caption  = "Tick time in ms: "
+   textsize = 0.03
+  />
+
+  <DebugRTRText
+   name     = "RTRText"
+   position = "0.3, 0.09"
+   font     = "Monofur"
+   textsize = 0.03
+  />
+  
+  <OverlayText
+   name     = "PositionTextCaption"
+   position = "0.03, 0.13"
+   font     = "Monofur"
+   caption  = "Position: "
+   textsize = 0.03
+  />
+  
+  <DebugPositionText
+   name     = "PositionText"
+   position = "0.3, 0.13"
+   font     = "Monofur"
+   textsize = 0.03
+  />
+
+</OverlayGroup>
+
+<Template name="defaultHUD">
+  <OverlayGroup name = "defaultHUD" scale = "1, 1">
+    <KillMessage
+     name     = "killmessage"
+     position = "0.5, 0.15"
+     font     = "VeraMono"
+     textsize = 0.035
+     colour   = "1.0, 1.0, 0.5, 1.0"
+     align    = "center"
+    />
+
+    <DeathMessage
+     name     = "deathmessage"
+     position = "0.5, 0.20"
+     font     = "VeraMono"
+     textsize = 0.035
+     colour   = "1.0, 0.3, 0.3, 1.0"
+     align    = "center"
+    />
+
+    <PauseNotice
+     name     = "pausenotice"
+     position = "0.5, 0.1"
+     font     = "VeraMono"
+     textsize = 0.03
+     colour   = "1.0, 1.0, 1.0, 1.0"
+     align    = "center"
+    />
+
+    <AnnounceMessage
+     name     = "announcemessage"
+     position = "0.5, 0.75"
+     font     = "VeraMono"
+     textsize = 0.05
+     colour   = "0.5, 0.5, 1.0, 1.0"
+     align    = "center"
+    />
+
+    <ChatOverlay
+     name     = "chat"
+     position = "0.03, 0.08"
+     font     = "VeraMono"
+     caption  = ""
+     textsize = 0.025
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/dynamicMatchHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/dynamicMatchHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/dynamicMatchHUD.oxo	(revision 11817)
@@ -0,0 +1,45 @@
+<Template name="DynamicmatchHUD">
+  <OverlayGroup name="DynamicmatcHUD" scale = "1, 1">
+   
+    <!--OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Target:"
+    />
+
+    <OverlayText
+     position  = "0.02, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Score:"
+    /-->
+
+
+ <GametypeStaticMessage
+   name     = "staticmessage"
+   position = "0.5, 0.01"
+   font     = "VeraMono"
+   caption  = ""
+   textsize = 0.033
+   colour   = "1.0, 1.0, 0.5, 1.0"
+   align    = "center"
+  />
+
+<GametypeFadingMessage
+     name     = "fadingmessage"
+     position = "0.5, 0.05"
+     font     = "VeraMono"
+     textsize = 0.04
+     colour   = "1.0, 1.0, 0.5, 1.0"
+     align    = "center"
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/jumpHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/jumpHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/jumpHUD.oxo	(revision 11817)
@@ -0,0 +1,42 @@
+<Template name="JumpHUD">
+  <OverlayGroup name="JumpHUD" scale = "1, 1">
+
+    <JumpScore
+     position  = "0.5, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.06
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "center"
+     showScore = true
+     showFuel = false
+     showMessages = false
+    />
+
+    <JumpScore
+     position  = "0.1, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 0.5, 0.0, 1.0"
+     align     = "left"
+     showScore = false
+     showFuel = true
+     showMessages = false
+    />
+
+    <JumpScore
+     position  = "0.5, 0.5"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.2
+     colour    = "1.0, 0.0, 0.0, 1.0"
+     align     = "center"
+     gameOverText = "GAME OVER"
+     showScore = false
+     showFuel = false
+     showMessages = true
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/lastManStandingHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/lastManStandingHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/lastManStandingHUD.oxo	(revision 11817)
@@ -0,0 +1,77 @@
+<Template name="LastmanstandingHUD">
+  <OverlayGroup name="LastmanstandingHUD" scale = "1, 1">
+    <LastManStandingInfos
+     position  = "0.14, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = true
+     showplayers     = false
+    />
+    <OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Lives:   "
+    />
+
+    <OverlayText
+     position  = "0.02, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Players: "
+    />
+
+    <LastManStandingInfos
+     position  = "0.14, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = false
+     showplayers     = true
+    />
+
+    <!--OverlayText
+     position  = "0.02, 0.07"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "__________|"
+    />
+
+    <OverlayText
+     position  = "0.022, 0.07"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "__________"
+    />
+
+    <OverlayText
+     position  = "0.1733, 0.038"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "|"
+    /-->
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/lastTeamStandingHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/lastTeamStandingHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/lastTeamStandingHUD.oxo	(revision 11817)
@@ -0,0 +1,48 @@
+<Template name="lastTeamStandingHUD">
+  <OverlayGroup name="lastTeamStandingHUD" scale = "1, 1">
+    <LastTeamStandingInfos
+     position  = "0.14, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = true
+     showteams     = false
+    />
+
+    <OverlayText
+     position  = "0.02, 0.02"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Lives:   "
+    />
+
+    <OverlayText
+     position  = "0.02, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     caption   = "Teams: "
+    />
+
+    <LastTeamStandingInfos
+     position  = "0.14, 0.055"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showlives     = false
+     showteams     = true
+    />
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/pongHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/pongHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/pongHUD.oxo	(revision 11817)
@@ -0,0 +1,70 @@
+<Template name="PongHUD">
+  <OverlayGroup name="PongHUD" scale = "1, 1">
+    <PongScore
+     position  = "0.05, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.06
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showleftplayer  = true
+     showrightplayer = false
+     showname        = true
+     showscore       = false
+    />
+
+    <PongScore
+     position  = "0.49, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.06
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "right"
+
+     showleftplayer  = true
+     showrightplayer = false
+     showname        = false
+     showscore       = true
+    />
+
+    <OverlayText
+     position  = "0.505, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.06
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "center"
+
+     caption   = ":"
+    />
+
+    <PongScore
+     position  = "0.51, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.06
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     showleftplayer  = false
+     showrightplayer = true
+     showname        = false
+     showscore       = true
+    />
+
+    <PongScore
+     position  = "0.95, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.06
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "right"
+
+     showleftplayer  = false
+     showrightplayer = true
+     showname        = true
+     showscore       = false
+    />
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/stats.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/stats.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/stats.oxo	(revision 11817)
@@ -0,0 +1,56 @@
+<!-- Statistics Overlay -->
+<Template name=defaultScoreboard>
+    <OverlayGroup name = "Stats" scale = "1, 1" visible=false>
+
+      <!--OverlayText
+       name      = "Title"
+       position  = "0.79, 0.19"
+       pickpoint = "1, 1"
+       font      = "Monofur"
+       caption   = "Scoreboard"
+       colour    = "0, 0.75, 0.2, 1"
+       textsize  = 0.04
+      /-->
+
+      <OverlayText
+       name      = "descr1"
+       position  = "0.1, 0.20"
+       pickpoint = "0, 1"
+       font      = "Monofur"
+       caption   = "player name"
+       colour    = "0, 0.75, 0.2, 1"
+       textsize  = 0.04
+      />
+      <OverlayText
+       name      = "descr2"
+       position  = "0.6, 0.20"
+       pickpoint = "0, 1"
+       font      = "Monofur"
+       caption   = "score"
+       colour    = "0, 0.75, 0.2, 1"
+       textsize  = 0.04
+      />
+      <OverlayText
+       name      = "descr3"
+       position  = "0.8, 0.20"
+       pickpoint = "0, 1"
+       font      = "Monofur"
+       caption   = "deaths"
+       colour    = "0, 0.75, 0.2, 1"
+       textsize  = 0.04
+      />
+
+      <!--Stats
+       name     = "Statistics"
+       position = "0.5, 0.7"
+       size = "0.85, 0.4"
+       correctaspect = false
+       pickpoint = "0.5, 0.5"
+      /-->
+
+      <Scoreboard
+       name     = "Scores"
+      />
+
+    </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/teamBaseMatchHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/teamBaseMatchHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/teamBaseMatchHUD.oxo	(revision 11817)
@@ -0,0 +1,90 @@
+<Template name="TeamBaseMatchHUD">
+  <OverlayGroup name="TeamBaseMatchHUD" scale = "1, 1">
+    <OverlayText
+     position  = "0.2, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 0.5, 0.5, 1.0"
+     align     = "left"
+     caption   = "Red team"
+    />
+
+    <TeamBaseMatchScore
+     position  = "0.37, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 0.8, 0.8, 1.0"
+     align     = "left"
+
+     showleftteam  = true
+     showrightteam = false
+     showbases     = true
+     showscore     = false
+    />
+
+    <TeamBaseMatchScore
+     position  = "0.49, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "1.0, 0.8, 0.8, 1.0"
+     align     = "right"
+
+     showleftteam  = true
+     showrightteam = false
+     showbases     = false
+     showscore     = true
+    />
+
+    <OverlayText
+     position  = "0.505, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "0.8, 0.8, 0.8, 1.0"
+     align     = "center"
+
+     caption   = ":"
+    />
+
+    <TeamBaseMatchScore
+     position  = "0.51, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "0.8, 0.8, 1.0, 1.0"
+     align     = "left"
+
+     showleftteam  = false
+     showrightteam = true
+     showbases     = false
+     showscore     = true
+    />
+
+    <TeamBaseMatchScore
+     position  = "0.63, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "0.8, 0.8, 1.0, 1.0"
+     align     = "right"
+
+     showleftteam  = false
+     showrightteam = true
+     showbases     = true
+     showscore     = false
+    />
+
+    <OverlayText
+     position  = "0.8, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.04
+     colour    = "0.5, 0.5, 1.0, 1.0"
+     align     = "right"
+     caption   = "Blue team"
+    />
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/tetrisHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/tetrisHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/tetrisHUD.oxo	(revision 11817)
@@ -0,0 +1,37 @@
+<Template name="TetrisHUD">
+  <OverlayGroup name="TetrisHUD" scale = "1, 1">
+    <TetrisScore
+     position  = "0.9, 0.1"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+    />
+
+    <OverlayText
+     position  = "0.7, 0.10"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     caption   = "Points: "
+    />
+    
+    <OverlayText
+     position  = "0.7, 0.20"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     caption   = "Next Brick"
+    />
+    
+    
+
+  </OverlayGroup>
+</Template>
Index: /code/branches/RacingBots_FS18/data/overlays/towerdefenseHUD.oxo
===================================================================
--- /code/branches/RacingBots_FS18/data/overlays/towerdefenseHUD.oxo	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/overlays/towerdefenseHUD.oxo	(revision 11817)
@@ -0,0 +1,82 @@
+<Template name="TowerDefenseHUD">
+
+
+  <OverlayGroup name="TowerDefenseHUD" scale = "1, 1">
+  
+  
+    <OverlayText
+     position  = "0.83, 0.05"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     caption = "Cash:"
+    />
+    
+    
+     <TowerDefenseHUDController
+     position  = "0.88, 0.10"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     showlives = false
+     showcredits = true
+     showwaves = false
+    />
+    
+        <OverlayText
+     position  = "0.83, 0.22"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     caption = "Lifes:"
+    />
+    
+         <TowerDefenseHUDController
+     position  = "0.88, 0.27"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     showlives = true
+     showcredits = false
+     showwaves = false
+    />
+    
+            <OverlayText
+     position  = "0.83, 0.39"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+
+     caption = "Waves:"
+    />
+    
+         <TowerDefenseHUDController
+     position  = "0.88, 0.44"
+     pickpoint = "0.0, 0.0"
+     font      = "ShareTechMono"
+     textsize  = 0.05
+     colour    = "1.0, 1.0, 1.0, 1.0"
+     align     = "left"
+     showlives = false
+     showcredits = false
+     showwaves = true
+
+    />
+    
+    
+  </OverlayGroup>
+</Template>
+
+
Index: /code/branches/RacingBots_FS18/data/particle/Example-Water.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/Example-Water.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/Example-Water.particle	(revision 11817)
@@ -0,0 +1,35 @@
+particle_system Examples/Water/Rain
+{
+    material        Examples/Droplet
+    particle_width  100
+    particle_height 300
+    cull_each       true
+    quota           100
+    // Make common direction straight down (faster than self oriented)
+    billboard_type  oriented_common
+    common_direction 0 -1 0
+    
+    // Area emitter
+    emitter Box
+    {
+        angle           0
+        emission_rate   20
+        time_to_live    5
+        direction       0 -1 0
+        velocity    	1000
+        colour_range_start  0.3 1 0.3
+        colour_range_end    0.7 1 0.7
+        width           3000
+        height          3000
+        depth           0
+    }
+
+    // Gravity
+    affector LinearForce
+    {
+        force_vector      0 -1000 0
+        force_application add
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/data/particle/Example.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/Example.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/Example.particle	(revision 11817)
@@ -0,0 +1,395 @@
+// Example particle systems
+
+// Exudes greeny particles which float upwards
+particle_system Examples/GreenyNimbus
+{
+    material        Examples/FlarePointSprite
+	point_rendering	true
+	// point rendering means size is controlled by material
+	// provide fallback sizes for hardware that doesn't support point sprite
+    particle_width  30
+    particle_height 30
+    cull_each       false
+	cull_each       false
+    quota           10000
+    billboard_type  point
+    
+    // Area emitter
+    emitter Box
+    {
+        angle           30
+        emission_rate   30
+        time_to_live    5
+        direction       0 1 0
+        velocity    	0
+        colour_range_start  1 1 0
+        colour_range_end    0.3 1 0.3
+        width           60
+        height          60
+        depth           60
+    }
+
+    // Make em float upwards
+    affector LinearForce
+    {
+        force_vector      0 100 0
+        force_application add
+    }
+
+    // Fader
+    affector ColourFader
+    {
+        red -0.25
+        green -0.25
+        blue -0.25
+    }
+
+
+}
+
+// A sparkly purple fountain
+particle_system Examples/PurpleFountain
+{
+    material        Examples/Flare2
+    particle_width  20
+    particle_height 40
+    cull_each       false
+    quota           10000
+    billboard_type  oriented_self
+    
+    // Area emitter
+    emitter Point
+    {
+        angle           15
+        emission_rate   75
+        time_to_live    3
+        direction       0 1 0
+        velocity_min    250
+        velocity_max    300
+        colour_range_start  0 0 0
+        colour_range_end    1 1 1
+    }
+
+    // Gravity
+    affector LinearForce
+    {
+        force_vector      0 -100 0
+        force_application add
+    }
+
+    // Fader
+    affector ColourFader
+    {
+        red -0.25
+        green -0.25
+        blue -0.25
+    }
+}
+
+
+// A downpour
+particle_system Examples/Rain
+{
+    material        Examples/Droplet
+    particle_width  20
+    particle_height 100
+    cull_each       true
+    quota           10000
+    // Make common direction straight down (faster than self oriented)
+    billboard_type  oriented_common
+    common_direction 0 -1 0
+    
+    // Area emitter
+    emitter Box
+    {
+        angle           0
+        emission_rate   100
+        time_to_live    5
+        direction       0 -1 0
+        velocity    	50
+        colour_range_start  0.3 1 0.3
+        colour_range_end    0.7 1 0.7
+        width           1000
+        height          1000
+        depth           0
+    }
+
+    // Gravity
+    affector LinearForce
+    {
+        force_vector      0 -200 0
+        force_application add
+    }
+
+}
+
+// A jet engine (of sorts)
+particle_system Examples/JetEngine1
+{
+	material 		Examples/Flare
+	particle_width 	25
+	particle_height	25
+	cull_each		false
+	quota			200
+	billboard_type	point
+
+	emitter Point
+	{
+		angle 5
+		emission_rate 100
+        time_to_live    1
+        direction       0 -1 0
+        velocity_min    250
+        velocity_max    300
+        colour_range_start  1 1 0.5
+        colour_range_end    1 0.8 0.3
+		
+	}
+	affector ColourFader
+	{
+		red -0.25
+		green -1
+		blue -1
+	}
+	
+}
+particle_system Examples/JetEngine2
+{
+	material 		Examples/Flare
+	particle_width 	15
+	particle_height	15
+	cull_each		false
+	quota			200
+	billboard_type	point
+
+	emitter Point
+	{
+		angle 3
+		emission_rate 100
+        time_to_live    1
+        direction       0 -1 0
+        velocity_min    350
+        velocity_max    400
+        colour_range_start  0.5 1 1
+        colour_range_end    0.3 0.8 1
+		
+	}
+	affector ColourFader
+	{
+		red -1
+		green -1
+		blue -0.5
+	}
+	
+}
+
+// Exudes aureola particles which around the model float upwards
+particle_system Examples/Aureola
+{
+    material        Examples/Aureola
+    particle_width  200
+    particle_height 200
+    cull_each       false
+    quota           100
+    billboard_type  perpendicular_common
+    common_direction 0 1 0
+    common_up_vector 0 0 1
+
+    // Area emitter
+    emitter Box
+    {
+        angle           30
+        emission_rate   4
+        time_to_live    5
+        position        0 -100 0
+        direction       0 1 0
+        velocity_min  	0
+        velocity_max  	30
+        colour_range_start  0.3 0.3 0.3 0.0
+        colour_range_end    0.8 0.8 0.8 0.0
+        width           10
+        height          10
+        depth           30
+    }
+
+    // Make em float upwards
+    affector LinearForce
+    {
+        force_vector      0 70 0
+        force_application add
+    }
+
+    // Fader
+    affector ColourFader2
+    {
+        red1 +0.4
+        green1 +0.4
+        blue1 +0.4
+        alpha1 +0.7
+
+        red2 -0.25
+        green2 -0.25
+        blue2 -0.25
+        alpha2 -0.3333
+
+        state_change 3.5
+    }
+
+    // Rotater
+    affector Rotator
+    {
+        rotation_range_start 0
+        rotation_range_end 360
+        rotation_speed_range_start 0
+        rotation_speed_range_end 180
+    }
+}
+
+
+particle_system Examples/Swarm
+{
+	quota	3000
+	material	Examples/Flare2
+	particle_width	12
+	particle_height	24
+	cull_each	true
+	renderer	billboard
+	sorted	true
+	local_space	false
+	billboard_type	oriented_self
+
+	emitter Box
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	30
+		position	0 0 0
+		velocity	50
+		velocity_min	50
+		velocity_max	1
+		time_to_live	20
+		time_to_live_min	20
+		time_to_live_max	20
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	80
+		height	80
+		depth	80
+	}
+
+	affector ColourFader
+	{
+		red	-0.05
+		green	0
+		blue	0
+		alpha	0
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 -50 0
+		plane_normal	0 1 0
+		bounce	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 50 0
+		plane_normal	0 -1 0
+		bounce	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	50 0 0
+		plane_normal	-1 0 0
+		bounce	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	-50 0 0
+		plane_normal	1 0 0
+		bounce	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 0 50
+		plane_normal	0 0 -1
+		bounce	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 0 -50
+		plane_normal	0 0 1
+		bounce	1
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	60
+	}
+}
+
+
+particle_system Examples/Snow
+{
+	quota	2000
+	material	Examples/Flare
+	particle_width	4
+	particle_height	4
+	cull_each	true
+	renderer	billboard
+	sorted	true
+	local_space	false
+	billboard_type	point
+
+	emitter Box
+	{
+		angle	0
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 -1 0
+		emission_rate	100
+		position	0 200 0
+		velocity	20
+		velocity_min	20
+		velocity_max	20
+		time_to_live	20
+		time_to_live_min	20
+		time_to_live_max	20
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	200
+		height	200
+		depth	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 0 0
+		plane_normal	0 1 0
+		bounce	0
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	10
+	}
+}
+
+
Index: /code/branches/RacingBots_FS18/data/particle/ExplosionComp1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ExplosionComp1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ExplosionComp1.particle	(revision 11817)
@@ -0,0 +1,66 @@
+
+particle_system Orxonox/ExplosionComp1
+{
+	quota	150
+	material	PE/explosion
+	particle_width	20
+	particle_height	40
+	cull_each	true
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	300
+		position	0 0 0
+		velocity	75
+		velocity_min	75
+		velocity_max	75
+		time_to_live	0.6
+		time_to_live_min	0.4
+		time_to_live_max	0.8
+		duration	0.4
+		duration_min	0.3
+		duration_max	0.6
+		repeat_delay	2.5
+		repeat_delay_min	2.5
+		repeat_delay_max	2.5
+		width		20
+		height		20
+		depth		0
+	}
+
+	affector Scaler
+	{
+		rate	5
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	130.6
+		scope	0.4505
+		keep_velocity	false
+	}
+
+	affector ColourFader
+	{
+		red	1
+		green	1
+		blue	1
+		alpha	-0.06306
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/ExplosionComp2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ExplosionComp2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ExplosionComp2.particle	(revision 11817)
@@ -0,0 +1,56 @@
+
+particle_system Orxonox/ExplosionComp2
+{
+	quota	1000
+	material	PE/smoke
+	particle_width	10
+	particle_height	10
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 0.62963
+		colour_range_start	1 1 1 0.62963
+		colour_range_end	1 1 1 0.62963
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	80
+		velocity_min	80
+		velocity_max	80
+		time_to_live	0.8
+		time_to_live_min	0.8
+		time_to_live_max	0.8
+		duration	0.79
+		duration_min	0.79
+		duration_max	0.79
+		repeat_delay	1.5
+		repeat_delay_min	1.5
+		repeat_delay_max	1.5
+	}
+
+	affector Scaler
+	{
+		rate	12.07
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-1
+		alpha	-0.4234
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/ExplosionComp4.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ExplosionComp4.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ExplosionComp4.particle	(revision 11817)
@@ -0,0 +1,76 @@
+
+particle_system ExplosionComp4
+{
+	quota	10
+	material	BaseWhite
+	particle_width	100
+	particle_height	100
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+}
+
+particle_system Orxonox/ExplosionComp4
+{
+	quota	500
+	material	PE/explosion
+	particle_width	24.19
+	particle_height	25.08
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	9.73
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	300
+		velocity_min	300
+		velocity_max	300
+		time_to_live	0.1802
+		time_to_live_min	0.1802
+		time_to_live_max	0.1802
+		duration	0.08
+		duration_min	0.08
+		duration_max	0.08
+		repeat_delay	0.1802
+		repeat_delay_min	0.1802
+		repeat_delay_max	0.1802
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	0
+		scope	0.2703
+		keep_velocity	false
+	}
+
+	affector LinearForce
+	{
+		force_vector	-16.8065 62.4805 6.57674
+		force_application	add
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/FieldExplosion.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/FieldExplosion.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/FieldExplosion.particle	(revision 11817)
@@ -0,0 +1,84 @@
+particle_system Orxonox/FieldExplosion
+
+{
+	material PE/lensflare
+	particle_width 152.940002441406
+	particle_height 154.119995117188
+	quota 2000
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin center
+	billboard_rotation_type texcoord
+	point_rendering false
+	accurate_facing false
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 1.0 0.0 0.0
+		angle 0.0
+		emission_rate 200.0
+		velocity_min -1000.0
+		velocity_max 1000.0
+		time_to_live_min 2.0
+		time_to_live_max 4.0
+		duration_min 0.0
+		duration_max 0.0
+		repeat_delay_min 0.0
+		repeat_delay_max 0.0
+		colour_range_start 1 1 1 1
+		colour_range_end 0.666667 0 0 1
+	}
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0.0
+		emission_rate 200.0
+		velocity_min -1000.0
+		velocity_max 1000.0
+		time_to_live_min 2.0
+		time_to_live_max 4.0
+		duration_min 0.0
+		duration_max 0.0
+		repeat_delay_min 0.0
+		repeat_delay_max 0.0
+		colour_range_start 1 1 1 1
+		colour_range_end 0.333333 0 1 1
+	}
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 1.0 0.0
+		angle 0.0
+		emission_rate 200.0
+		velocity_min -1000.0
+		velocity_max 1000.0
+		time_to_live_min 2.0
+		time_to_live_max 4.0
+		duration_min 0.0
+		duration_max 0.0
+		repeat_delay_min 0.0
+		repeat_delay_max 0.0
+		colour_range_start 1 1 1 1
+		colour_range_end 0 1 0.498039 1
+	}
+
+	affector LinearForce
+	{
+		force_vector 0.0 -45.62 0.0
+		force_application add
+	}
+
+	affector Scaler
+	{
+		rate 16.47
+	}
+	
+}
Index: /code/branches/RacingBots_FS18/data/particle/FireComp2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/FireComp2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/FireComp2.particle	(revision 11817)
@@ -0,0 +1,69 @@
+
+particle_system Orxonox/FireComp2
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	4
+	particle_height	4
+	cull_each	true
+	renderer	billboard
+	sorted	true
+	local_space	true
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	true
+
+	emitter HollowEllipsoid
+	{
+		angle	1.69
+		colour	1 1 1 0.506173
+		colour_range_start	1 1 1 0.506173
+		colour_range_end	1 1 1 0.506173
+		direction	0 1 0
+		emission_rate	1680
+		position	0 60 0
+		velocity	300
+		velocity_min	300
+		velocity_max	300
+		time_to_live	0.2
+		time_to_live_min	0.2
+		time_to_live_max	0.2
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	28.83
+		height	39.64
+		depth	88.29
+		inner_width	0.5
+		inner_height	0.5
+		inner_depth	0.5
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	250
+		scope	0.4865
+		keep_velocity	false
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-1
+		alpha	0.1351
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/GravityBombField.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/GravityBombField.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/GravityBombField.particle	(revision 11817)
@@ -0,0 +1,65 @@
+particle_system Orxonox/GravityBombField
+{
+	material PE/lensflare
+	particle_width 33.6500015258789
+	particle_height 1.91999995708466
+	quota 2000
+	cull_each false
+	sorted false
+	local_space true
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin center
+	billboard_rotation_type vertex
+	point_rendering false
+	accurate_facing false
+
+	emitter HollowEllipsoid
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 1.0 0.0
+		angle 180
+		width 350
+		height 350
+		depth 350
+		inner_width 0.99
+		inner_height 0.99
+		inner_depth 0.99
+		emission_rate 2000
+		velocity_min 0
+		velocity_max 5
+		time_to_live_min 2
+		time_to_live_max 5
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0.666667 0 1
+		colour_range_end 1 0 0 1
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start 0
+		rotation_speed_range_end 0
+		rotation_range_start 0
+		rotation_range_end 180
+	}
+
+	affector ColourInterpolator
+	{
+		time0 0
+		colour0 1 0.666667 0 1
+		time1 0.2
+		colour1 1 0.584314 0 1
+		time2 0.4
+		colour2 1 0 0 1
+		time3 0.6
+		colour3 1 0 0 1
+		time4 0.8
+		colour4 0.666667 0 0 1
+		time5 1
+		colour5 0 0 0 1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/LaserGun.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/LaserGun.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/LaserGun.particle	(revision 11817)
@@ -0,0 +1,51 @@
+
+particle_system Orxonox/LaserGun
+{
+	quota	1000
+	material	PE/Streak
+	particle_width	1.892
+	particle_height	1.892
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	3.243
+		colour	1 0 0 1
+		colour_range_start	1 0 0 1
+		colour_range_end	1 0.0432099 0 1
+		direction	0 -1 0
+		emission_rate	1027
+		position	0 0 0
+		velocity	113.5
+		velocity_min	113.5
+		velocity_max	113.5
+		time_to_live	0.3604
+		time_to_live_min	0.3604
+		time_to_live_max	0.3604
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	0.2613
+		blue	-0.1712
+		alpha	-1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/MineExpl.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/MineExpl.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/MineExpl.particle	(revision 11817)
@@ -0,0 +1,95 @@
+particle_system Orxonox/MineExpl
+{
+	material PE/lensflare
+	particle_width 65.0
+	particle_height 40.0
+	quota 500
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type oriented_self
+	billboard_origin center
+	billboard_rotation_type vertex
+	point_rendering false
+	accurate_facing false
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction -1.0 0.0 0.0
+		angle 55
+		emission_rate 1250
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 1
+		time_to_live_max 2
+		duration_min 0.1
+		duration_max 0.1
+		repeat_delay_min 10
+		repeat_delay_max 10
+		colour_range_start 0 0.333333 1 1
+		colour_range_end 0 0.333333 1 1
+	}
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 1.0 0.0 0.0
+		angle 55
+		emission_rate 200
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 2
+		time_to_live_max 2.5
+		duration_min 0.1
+		duration_max 0.1
+		repeat_delay_min 10
+		repeat_delay_max 10
+		colour_range_start 0 0.333333 1 1
+		colour_range_end 0 0.333333 1 1
+	}
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 -1.0
+		angle 55
+		emission_rate 1250
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 2
+		time_to_live_max 2.5
+		duration_min 0.1
+		duration_max 0.1
+		repeat_delay_min 10
+		repeat_delay_max 10
+		colour_range_start 0 0.333333 1 1
+		colour_range_end 0 0.333333 1 1
+	}
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 55
+		emission_rate 1250
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 2
+		time_to_live_max 2.5
+		duration_min 0.1
+		duration_max 0.1
+		repeat_delay_min 10
+		repeat_delay_max 10
+		colour_range_start 0 0.333333 1 1
+		colour_range_end 0 0.333333 1 1
+	}
+
+	
+	affector Scaler
+	{
+		rate -2
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/MineExpl1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/MineExpl1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/MineExpl1.particle	(revision 11817)
@@ -0,0 +1,47 @@
+particle_system Orxonox/MineExpl1
+{
+	material PE/lensflare
+	particle_width 35.0
+	particle_height 35.0
+	quota 500
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type oriented_self
+	billboard_origin center
+	billboard_rotation_type vertex
+	point_rendering false
+	accurate_facing false
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 1.0 0.0
+		angle 30
+		emission_rate 2000
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 3
+		time_to_live_max 4
+		duration_min 2.0
+		duration_max 2.5
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+		colour_range_start 0 0.333333 1 1
+		colour_range_end 0 0.333333 1 1
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness 5
+		scope 1
+		keep_velocity true
+	}
+	affector Scaler
+	{
+		rate -2
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/MineExpl2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/MineExpl2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/MineExpl2.particle	(revision 11817)
@@ -0,0 +1,47 @@
+particle_system Orxonox/MineExpl2
+{
+	material PE/lensflare
+	particle_width 35.0
+	particle_height 35.0
+	quota 500
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type oriented_self
+	billboard_origin center
+	billboard_rotation_type vertex
+	point_rendering false
+	accurate_facing false
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 -1.0 0.0
+		angle 30
+		emission_rate 2000
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 2
+		time_to_live_max 2.5
+		duration_min 0.5
+		duration_max 1.5
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+		colour_range_start 0 0.333333 1 1
+		colour_range_end 0 0.333333 1 1
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness 5
+		scope 1
+		keep_velocity true
+	}
+	affector Scaler
+	{
+		rate -2
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/RingExp.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/RingExp.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/RingExp.particle	(revision 11817)
@@ -0,0 +1,135 @@
+
+particle_system Orxonox/RingExp
+{
+	quota	500
+	material	PE/lensflare
+	particle_width	65
+	particle_height	40
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	55
+		colour	0.9 0.9 1 1
+		colour_range_start	0.9 0.9 1 1
+		colour_range_end	0.9 0.9 1 1
+		direction	-1 0 0
+		emission_rate	1250
+		position	0 0 0
+		velocity	65
+		velocity_min	65
+		velocity_max	65
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+	}
+
+	emitter Point
+	{
+		angle	55
+		colour	0.9 0.9 1 1
+		colour_range_start	0.9 0.9 1 1
+		colour_range_end	0.9 0.9 1 1
+		direction	1 0 0
+		emission_rate	1250
+		position	0 0 0
+		velocity	65
+		velocity_min	65
+		velocity_max	65
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+	}
+
+	emitter Point
+	{
+		angle	55
+		colour	0.9 0.9 1 1
+		colour_range_start	0.9 0.9 1 1
+		colour_range_end	0.9 0.9 1 1
+		direction	0 0 -1
+		emission_rate	1250
+		position	0 0 0
+		velocity	65
+		velocity_min	65
+		velocity_max	65
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+	}
+
+	emitter Point
+	{
+		angle	55
+		colour	0.9 0.9 1 1
+		colour_range_start	0.9 0.9 1 1
+		colour_range_end	0.9 0.9 1 1
+		direction	0 0 1
+		emission_rate	1250
+		position	0 0 0
+		velocity	65
+		velocity_min	65
+		velocity_max	65
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 -2 0
+		plane_normal	0 1 0
+		bounce  1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 2 0
+		plane_normal	0 -1 0
+		bounce	1
+	}
+
+	affector ColourFader
+	{
+		red	-0.3
+		green	-0.3
+		blue	-0.3
+		alpha	-0.3
+	}
+
+}
Index: /code/branches/RacingBots_FS18/data/particle/RingExp2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/RingExp2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/RingExp2.particle	(revision 11817)
@@ -0,0 +1,58 @@
+
+particle_system Orxonox/RingExp2
+{
+	quota	500
+	material	PE/ringflare
+	particle_width	35
+	particle_height	35
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	30
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 0.7 0.7 1
+		direction	0 1 0
+		emission_rate	1000
+		position	0 0 0
+		velocity	50
+		velocity_min	50
+		velocity_max	100
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.5
+		duration_min	0.5
+		duration_max	0.5
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+	}
+
+	affector ColourFader
+	{
+		red	-0.3
+		green	-0.3
+		blue	-0.3
+		alpha	-0.3
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	5
+		scope	1.0
+		keep_velocity	true
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/RingExp3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/RingExp3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/RingExp3.particle	(revision 11817)
@@ -0,0 +1,58 @@
+
+particle_system Orxonox/RingExp3
+{
+	quota	500
+	material	PE/ringflare
+	particle_width	35
+	particle_height	35
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	30
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 0.7 0.7 1
+		direction	0 -1 0
+		emission_rate	1000
+		position	0 0 0
+		velocity	50
+		velocity_min	50
+		velocity_max	100
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.5
+		duration_min	0.5
+		duration_max	0.5
+		repeat_delay	10
+		repeat_delay_min	10
+		repeat_delay_max	10
+	}
+
+	affector ColourFader
+	{
+		red	-0.3
+		green	-0.3
+		blue	-0.3
+		alpha	-0.3
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	5
+		scope	1.0
+		keep_velocity	true
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/Shield.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/Shield.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/Shield.particle	(revision 11817)
@@ -0,0 +1,49 @@
+
+particle_system Orxonox/Shield
+{
+	quota	2000
+	material	PE/lensflare
+	particle_width	25
+	particle_height	25
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	true
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter HollowEllipsoid
+	{
+		angle	0
+		colour	0 0.298701 1 0.1
+		colour_range_start	0 0.298701 1 0.1
+		colour_range_end	0 0.298701 1 0.1
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	0.1
+		time_to_live_min	0.1
+		time_to_live_max	0.3
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.2
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+		width	100
+		height	100
+		depth	100
+		inner_width	0.999999
+		inner_height	0.999999
+		inner_depth	0.999999
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/Steam.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/Steam.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/Steam.particle	(revision 11817)
@@ -0,0 +1,44 @@
+
+particle_system Orxonox/Steam
+{
+	quota 1
+	material	PE/smoke
+	particle_width	2000
+	particle_height	2000
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	0
+		colour	1 1 1 0.1
+		colour_range_start	1 1 1 0.1
+		colour_range_end	1 1 1 0.02
+		direction	0 1 0
+		emission_rate	1
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	200
+		time_to_live_min	200
+		time_to_live_max	300
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+}
+
Index: /code/branches/RacingBots_FS18/data/particle/ThrusterFire.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ThrusterFire.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ThrusterFire.particle	(revision 11817)
@@ -0,0 +1,72 @@
+
+particle_system Orxonox/ThrusterFire
+{
+	quota	50
+	material	PE/explosion3
+	particle_width	100
+	particle_height	100
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	50
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	20
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	40
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	0.3 0.3 0.3 0
+		time1	0.1
+		colour2	0.2 0.2 0.2 0
+		time2	0.4
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/bigexplosion.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/bigexplosion.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/bigexplosion.particle	(revision 11817)
@@ -0,0 +1,72 @@
+particle_system Orxonox/bigexplosion
+{
+	quota	3000
+	material	PE/explosion
+	particle_width	100
+	particle_height	100
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	300
+		velocity_min	300
+		velocity_max	300
+		time_to_live	1.4
+		time_to_live_min	1.4
+		time_to_live_max	1.8
+		duration	0.3
+		duration_min	0.3
+		duration_max	0.3
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	-7.2
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.5 0.5 0.5 0
+		time0	0
+		colour1	0.4 0.4 0.4 0
+		time1	0.1
+		colour2	0.2 0.2 0.2 0
+		time2	0.3
+		colour3	0 0 0 0
+		time3	1.4
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1.5
+	}
+}
+
Index: /code/branches/RacingBots_FS18/data/particle/bigexplosion1part1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/bigexplosion1part1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/bigexplosion1part1.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/BigExplosion1part1
+{
+	quota	100
+	material	PE/Flare
+	particle_width	60
+	particle_height	60
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	top_center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	1000
+		position	0 0 0
+		velocity	50
+		velocity_min	50
+		velocity_max	100
+		time_to_live	1.3
+		time_to_live_min	1.3
+		time_to_live_max	1.6
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+	}
+
+	affector Scaler
+	{
+		rate	40
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	1 1 1 0
+		time0	0
+		colour1	1 1 0.8 0
+		time1	0.1
+		colour2	0.1 0.1 0.1 0
+		time2	0.6
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/bigexplosion1part2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/bigexplosion1part2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/bigexplosion1part2.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/BigExplosion1part2
+{
+	quota	50
+	material	PE/ringflare
+	particle_width	60
+	particle_height	60
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	250
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	80
+		time_to_live	1.3
+		time_to_live_min	1.3
+		time_to_live_max	1.3
+		duration	0.2
+		duration_min	0.2
+		duration_max	0.2
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+	}
+
+	affector Scaler
+	{
+		rate	40
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.5 0.5 0.5 0
+		time0	0
+		colour1	1 1 1 0
+		time1	0.1
+		colour2	0.1 0.1 0.1 0
+		time2	0.6
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/bigexplosion1part3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/bigexplosion1part3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/bigexplosion1part3.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/BigExplosion1part3
+{
+	quota	120
+	material	PE/point_lensflare
+	particle_width	18
+	particle_height	18
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ring
+	{
+		angle	0
+		colour	0 0 0 1
+		colour_range_start	0 0 0 1
+		colour_range_end	0 0 0 1
+		direction	0 1 0
+		emission_rate	1200
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+		width	150
+		height	150
+		depth	0
+		inner_width	0.99
+		inner_height	0.99
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	1 1 1 0
+		time1	0.5
+		colour2	0 0 0 0
+		time2	1
+		colour3	0.5 0.5 0.5 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/emitted_emitter.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/emitted_emitter.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/emitted_emitter.particle	(revision 11817)
@@ -0,0 +1,56 @@
+// Example emitted emitters
+particle_system Examples/Fireworks
+{
+     material Examples/Flare
+     point_rendering            false
+     particle_width             10
+     particle_height            10
+     cull_each                  false
+     quota                      1000
+     emit_emitter_quota         10
+     billboard_type             point
+     
+     // Emitter that emits multiple Point emitters with name 'explosion'
+     emitter Box
+     {
+         name                    mainEmitter
+         emit_emitter            explosion
+         angle                   30
+         emission_rate           1000
+         time_to_live            3
+         direction               0 1 0
+         velocity                200
+     }
+
+     // This Point emitter is emitted by the Box emitter and emits billboard particles itself
+     emitter Point
+     {
+         name                    explosion
+         angle                   360
+         emission_rate           1000
+         time_to_live            2
+         direction               0 1 0
+         velocity                80
+         duration                0.1
+         repeat_delay_min        2
+         repeat_delay_max        3
+     }
+
+     // Make em float downwards
+     affector LinearForce
+     {
+         force_vector            0 -100 0
+         force_application       add
+     } 
+
+     // Give em some nice colours
+     affector ColourInterpolator
+     {
+         time0                   0
+         colour0                 1 1 0
+         time1                   0.5
+         colour1                 1 0 0
+         time2                   0.9
+         colour2                 0 0 1
+     }
+} 
Index: /code/branches/RacingBots_FS18/data/particle/engine.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/engine.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/engine.particle	(revision 11817)
@@ -0,0 +1,70 @@
+particle_system Orxonox/engine
+{
+	material PE/glowEffect
+	particle_width 10.0
+	particle_height 10.0
+	quota 2000
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin center
+	billboard_rotation_type texcoord
+	point_rendering false
+	accurate_facing false
+
+	
+
+	emitter Ring
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 0.5
+		height 0.5
+		depth 0
+		inner_width 0.99
+		inner_height 0.99
+		emission_rate 250
+		velocity_min 50
+		velocity_max 55
+		time_to_live_min 0.075
+		time_to_live_max 0.09
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0.333333 0 1
+		colour_range_end 1 0.333333 0 1
+	}
+
+	emitter Ring
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 0.5
+		height 0.5
+		depth 0
+		inner_width 0.1
+		inner_height 0.25
+		emission_rate 250
+		velocity_min 50
+		velocity_max 55
+		time_to_live_min 0.1
+		time_to_live_max 0.125
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0 0 1
+		colour_range_end 1 0 0 1
+	}
+
+	affector Scaler
+	{
+		rate -40
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/engineglow.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/engineglow.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/engineglow.particle	(revision 11817)
@@ -0,0 +1,114 @@
+particle_system Orxonox/engineglow
+{
+	material PE/glowEffect
+	particle_width 100.0
+	particle_height 100.0
+	quota 2000
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin center
+	billboard_rotation_type texcoord
+	point_rendering false
+	accurate_facing false
+
+	emitter Ring
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 150
+		height 150
+		depth 1
+		inner_width 0.99
+		inner_height 0.99
+		emission_rate 30
+		velocity_min 20
+		velocity_max 20
+		time_to_live_min 5
+		time_to_live_max 5
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 0.666667 1 0 1
+		colour_range_end 0 1 0 1
+	}
+
+	emitter Ring
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 130
+		height 130
+		depth 0
+		inner_width 0.99
+		inner_height 0.99
+		emission_rate 10
+		velocity_min 200
+		velocity_max 200
+		time_to_live_min 0.75
+		time_to_live_max 0.75
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 1 0 1
+		colour_range_end 1 1 0.498039 1
+	}
+
+	emitter Ring
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 80
+		height 80
+		depth 0
+		inner_width 0.99
+		inner_height 0.99
+		emission_rate 57.89
+		velocity_min 250
+		velocity_max 250
+		time_to_live_min 1
+		time_to_live_max 1
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0.333333 0 1
+		colour_range_end 1 0.333333 0 1
+	}
+
+	emitter Ring
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 50
+		height 50
+		depth 0
+		inner_width 0.01
+		inner_height 0.5
+		emission_rate 37.89
+		velocity_min 300
+		velocity_max 300
+		time_to_live_min 1.5
+		time_to_live_max 1.5
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0 0 1
+		colour_range_end 1 0 0 1
+	}
+
+	affector Scaler
+	{
+		rate -20
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/explosion1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/explosion1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/explosion1.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/explosion1
+{
+	quota	200
+	material	PE/explosion
+	particle_width	100
+	particle_height	40
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	1 0.9 0.8 1
+		colour_range_start	1 0.9 0.8 1
+		colour_range_end	1 0.9 0.8 1
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	75
+		time_to_live	0.75
+		time_to_live_min	0.75
+		time_to_live_max	0.75
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.2 0.2 0.2 0
+		time0	0
+		colour1	0.4 0.3 0.2 0
+		time1	0.3
+		colour2	0.1 0.1 0.1 0
+		time2	0.5
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/explosion2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/explosion2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/explosion2.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/explosion2
+{
+	quota	150
+	material	PE/explosion
+	particle_width	50
+	particle_height	20
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	1 0.9 0.8 1
+		colour_range_start	1 0.9 0.8 1
+		colour_range_end	1 0.9 0.8 1
+		direction	0 1 0
+		emission_rate	300
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	75
+		time_to_live	0.75
+		time_to_live_min	0.75
+		time_to_live_max	0.75
+		duration	0.5
+		duration_min	0.5
+		duration_max	0.5
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	1 1 1 0
+		time0	0
+		colour1	0.7 0.7 1 0
+		time1	0.5
+		colour2	0.2 0.3 0.5 0
+		time2	0.7
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/explosion2b.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/explosion2b.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/explosion2b.particle	(revision 11817)
@@ -0,0 +1,67 @@
+
+particle_system Orxonox/explosion2b
+{
+	quota	150
+	material	PE/explosion
+	particle_width	20
+	particle_height	40
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	0 0 0 1
+		colour_range_start	0 0 0 1
+		colour_range_end	0 0 0 1
+		direction	0 1 0
+		emission_rate	300
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	75
+		time_to_live	0.75
+		time_to_live_min	0.75
+		time_to_live_max	0.75
+		duration	0.5
+		duration_min	0.5
+		duration_max	0.5
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+		width	20
+		height	20
+		depth	0
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.8 1 1 0
+		time0	0
+		colour1	0.5 0.7 1 0
+		time1	0.5
+		colour2	0.2 0.3 0.5 0
+		time2	0.7
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/explosion3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/explosion3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/explosion3.particle	(revision 11817)
@@ -0,0 +1,72 @@
+
+particle_system Orxonox/explosion3
+{
+	quota	10
+	material	PE/explosion3
+	particle_width	7
+	particle_height	7
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	40
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	0.5
+		time_to_live_min	0.5
+		time_to_live_max	0.5
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	0.5 0.5 0.5 0
+		time1	0.2
+		colour2	0.1 0.1 0.1 0
+		time2	0.6
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/explosion4.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/explosion4.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/explosion4.particle	(revision 11817)
@@ -0,0 +1,71 @@
+particle_system Orxonox/explosion4
+{
+	quota	1000
+	material	PE/explosion3
+	particle_width	10
+	particle_height	10
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	15
+		velocity_min	15
+		velocity_max	15
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1.4
+		duration	0.05
+		duration_min	0.05
+		duration_max	0.05
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	-7.2
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.5 0.5 0.5 0
+		time0	0
+		colour1	0.4 0.4 0.4 0
+		time1	0.2
+		colour2	0.2 0.2 0.2 0
+		time2	0.5
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/fairytwirl.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/fairytwirl.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/fairytwirl.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/fairytwirl
+{
+	quota	500
+	material	PE/lensflare
+	particle_width	2
+	particle_height	2
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ring
+	{
+		angle	0
+		colour	0 0 0 1
+		colour_range_start	0 0 0 1
+		colour_range_end	0 0 0 1
+		direction	0 1 0
+		emission_rate	500
+		position	0 -10 0
+		velocity	15
+		velocity_min	15
+		velocity_max	15
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	1
+		duration_min	1
+		duration_max	1
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+		width	35
+		height	35
+		depth	20
+		inner_width	0.99
+		inner_height	0.99
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	1 1 1 0
+		time1	0.5
+		colour2	0 0 0 0
+		time2	1
+		colour3	0.5 0.5 0.5 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/fire3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/fire3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/fire3.particle	(revision 11817)
@@ -0,0 +1,69 @@
+
+particle_system Orxonox/fire3
+{
+	quota	50
+	material	PE/explosion3
+	particle_width	20
+	particle_height	20
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	50
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	20
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	40
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	0.3 0.3 0.3 0
+		time1	0.1
+		colour2	0.2 0.2 0.2 0
+		time2	0.4
+		colour3	0 0 0 0
+		time3	1
+		
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/fire4.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/fire4.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/fire4.particle	(revision 11817)
@@ -0,0 +1,67 @@
+
+particle_system Orxonox/fire4
+{
+	quota	25
+	material	PE/explosion3
+	particle_width	4
+	particle_height	4
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	35
+		position	0 0 0
+		velocity	5
+		velocity_min	5
+		velocity_max	10
+		time_to_live	0.25
+		time_to_live_min	0.25
+		time_to_live_max	0.25
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	1 1 1 0
+		time0	0
+		colour1	0.6 0.6 0.6 0
+		time1	0.1
+		colour2	0.4 0.4 0.4 0
+		time2	0.4
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/fog.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/fog.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/fog.particle	(revision 11817)
@@ -0,0 +1,241 @@
+
+particle_system Orxonox/fog
+{
+	quota	1000
+	material	PE/smoke4
+	particle_width	2000
+	particle_height	1500
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	0.3 0.3 0.3 0.25
+		colour_range_start	0.3 0.3 0.3 0.1
+		colour_range_end	0.3 0.3 0.3 0.25
+		direction	0 1 0
+		emission_rate	16
+		position	0 0 0
+		velocity	2
+		velocity_min	2
+		velocity_max	2
+		time_to_live	100000
+		time_to_live_min	100000
+		time_to_live_max	100000
+		duration	5
+		duration_min	4
+		duration_max	7
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	6000
+		height	1800
+		depth	100
+	}
+
+	affector Scaler
+	{
+		rate	3
+	}
+
+    affector Rotator
+    {
+        rotation_range_start 0
+        rotation_range_end 360
+        rotation_speed_range_start 0
+        rotation_speed_range_end 0
+    }
+
+}
+
+
+particle_system Orxonox/fog2
+{
+	quota	1000
+	material	PE/smoke4
+	particle_width	2000
+	particle_height	1500
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	0.3 0.3 0.3 0.3
+		colour_range_start	0.3 0.3 0.3 0.1
+		colour_range_end	0.3 0.3 0.3 0.3
+		direction	0 1 0
+		emission_rate	16
+		position	0 0 0
+		velocity	2
+		velocity_min	2
+		velocity_max	2
+		time_to_live	100000
+		time_to_live_min	100000
+		time_to_live_max	100000
+		duration	5
+		duration_min	4
+		duration_max	7
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	10000
+		height	4000
+		depth	100
+	}
+
+	affector Scaler
+	{
+		rate	3
+	}
+
+    affector Rotator
+    {
+        rotation_range_start 0
+        rotation_range_end 360
+        rotation_speed_range_start 0
+        rotation_speed_range_end 0
+    }
+
+}
+
+particle_system Orxonox/fog3
+{
+	quota	1000
+	material	PE/smoke4
+	particle_width	2000
+	particle_height	1500
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	0.3 0.3 0.3 0.3
+		colour_range_start	0.3 0.3 0.3 0.1
+		colour_range_end	0.3 0.3 0.3 0.25
+		direction	0 1 0
+		emission_rate	22
+		position	0 0 0
+		velocity	2
+		velocity_min	2
+		velocity_max	2
+		time_to_live	100000
+		time_to_live_min	100000
+		time_to_live_max	100000
+		duration	5
+		duration_min	4
+		duration_max	7
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	8000
+		height	10000
+		depth	6000
+	}
+
+	affector Scaler
+	{
+		rate	3
+	}
+
+    affector Rotator
+    {
+        rotation_range_start 0
+        rotation_range_end 360
+        rotation_speed_range_start 0
+        rotation_speed_range_end 0
+    }
+
+}
+
+particle_system Orxonox/fog4
+{
+	quota	1000
+	material	PE/smoke4
+	particle_width	2000
+	particle_height	1500
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	0.3 0.3 0.3 0.3
+		colour_range_start	0.3 0.3 0.3 0.1
+		colour_range_end	0.3 0.3 0.3 0.25
+		direction	0 1 0
+		emission_rate	22
+		position	0 0 0
+		velocity	2
+		velocity_min	2
+		velocity_max	2
+		time_to_live	100000
+		time_to_live_min	100000
+		time_to_live_max	100000
+		duration	5
+		duration_min	4
+		duration_max	7
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	10000
+		height	10000
+		depth	10000
+	}
+
+	affector Scaler
+	{
+		rate	3
+	}
+
+    affector Rotator
+    {
+        rotation_range_start 0
+        rotation_range_end 360
+        rotation_speed_range_start 0
+        rotation_speed_range_end 0
+    }
+
+}
Index: /code/branches/RacingBots_FS18/data/particle/forcefield.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/forcefield.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/forcefield.particle	(revision 11817)
@@ -0,0 +1,554 @@
+particle_system Orxonox/ForceFieldPurpleBig
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	30
+	particle_height	500
+	cull_each	true
+	renderer	billboard
+	sorted		false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	1 0 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0.744444 0 1 0.05
+		colour_range_end	0.533333 0 1 0.05
+		emission_rate	10
+                direction 0 0 -1
+		velocity	87.1
+		velocity_min	87.1
+		velocity_max	87.1
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	1
+		width 600
+		height 600
+	}
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0.3 0 0.3 0.05
+		colour_range_end	0.4 0 0.5 0.05
+		emission_rate	10
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 300
+		height 300
+	}
+	
+	emitter Cylinder
+	{
+		angle	1 1 1 0.05
+		colour_range_start	0.9 0.9 0.9 0.05
+		colour_range_end	1 1 1 0.05
+		emission_rate	5
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 900
+		height 900
+	}
+}
+
+particle_system Orxonox/ForceFieldPurpleSmall
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	30
+	particle_height	500
+	cull_each	true
+	renderer	billboard
+	sorted		false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	1 0 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0.744444 0 1 0.05
+		colour_range_end	0.533333 0 1 0.05
+		emission_rate	7
+                direction 0 0 -1
+		velocity	87.1
+		velocity_min	87.1
+		velocity_max	87.1
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	1
+		width 300
+		height 300
+	}
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0.3 0 0.3 0.05
+		colour_range_end	0.4 0 0.5 0.05
+		emission_rate	6
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 200
+		height 200
+	}
+	
+	emitter Cylinder
+	{
+		angle	1 1 1 0.05
+		colour_range_start	0.9 0.9 0.9 0.05
+		colour_range_end	1 1 1 0.05
+		emission_rate	4
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 500
+		height 500
+	}
+}	
+
+particle_system Orxonox/ForceFieldGreenBig
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	30
+	particle_height	500
+	cull_each	true
+	renderer	billboard
+	sorted		false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	1 0 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0 0.744444 1 0.05
+		colour_range_end	0 0.533333 1 0.05
+		emission_rate	10
+                direction 0 0 -1
+		velocity	87.1
+		velocity_min	87.1
+		velocity_max	87.1
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	1
+		width 600
+		height 600
+	}
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0 0.455556 0 0.05
+		colour_range_end	0 0.8 0 0.05
+		emission_rate	10
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 300
+		height 300
+	}
+	
+	emitter Cylinder
+	{
+		angle	1 1 1 0.05
+		colour_range_start	0.9 0.9 0.9 0.05
+		colour_range_end	1 1 1 0.05
+		emission_rate	5
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 900
+		height 900
+	}
+}
+
+particle_system Orxonox/ForceFieldGreenSmall
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	30
+	particle_height	500
+	cull_each	true
+	renderer	billboard
+	sorted		false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	1 0 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	0
+		colour	0 0.744444 1 0.05
+		colour_range_start	0 0.744444 1 0.05
+		colour_range_end	0 0.533333 1 0.05
+		emission_rate	7
+                direction 0 0 -1
+		velocity	87.1
+		velocity_min	87.1
+		velocity_max	87.1
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	1
+		width 300
+		height 300
+	}
+
+	emitter Cylinder
+	{
+		angle	0
+		colour	0 0.455556 0 0.05
+		colour_range_start	0 0.455556 0 0.05
+		colour_range_end	0 0.8 0 0.05
+		emission_rate	6
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 200
+		height 200
+	}
+	
+	emitter Cylinder
+	{
+		angle	1 1 1 0.05
+		colour_range_start	0.9 0.9 0.9 0.05
+		colour_range_end	1 1 1 0.05
+		emission_rate	4
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 500
+		height 500
+	}
+}
+
+			
+particle_system Orxonox/ForceFieldBlueBig
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	30
+	particle_height	500
+	cull_each	true
+	renderer	billboard
+	sorted		false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	1 0 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0 0 0.744444 0.05
+		colour_range_end	0.5 0 0.533333 0.05
+		emission_rate	10
+                direction 0 0 -1
+		velocity	87.1
+		velocity_min	87.1
+		velocity_max	87.1
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	1
+		width 600
+		height 600
+	}
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0 0.3 0.455556 0.05
+		colour_range_end	0 0.5 0.8 0.05
+		emission_rate	10
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 300
+		height 300
+	}
+	
+	emitter Cylinder
+	{
+		angle	1 1 1 0.05
+		colour_range_start	0.9 0.9 0.9 0.05
+		colour_range_end	1 1 1 0.05
+		emission_rate	5
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 900
+		height 900
+	}
+}
+
+particle_system Orxonox/ForceFieldBlueSmall
+{
+	quota	10000
+	material	PE/smoke
+	particle_width	30
+	particle_height	500
+	cull_each	true
+	renderer	billboard
+	sorted		false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	1 0 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0 0 0.744444 0.05
+		colour_range_end	0.5 0 0.533333 0.05
+		emission_rate	7
+                direction 0 0 -1
+		velocity	87.1
+		velocity_min	87.1
+		velocity_max	87.1
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	1
+		width 300
+		height 300
+	}
+
+	emitter Cylinder
+	{
+		angle	0
+		colour_range_start	0 0.3 0.455556 0.05
+		colour_range_end	0 0.5 0.8 0.05
+		emission_rate	6
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 200
+		height 200
+	}
+	
+	emitter Cylinder
+	{
+		angle	1 1 1 0.05
+		colour_range_start	0.9 0.9 0.9 0.05
+		colour_range_end	1 1 1 0.05
+		emission_rate	4
+                direction 0 0 -1
+		velocity	77.42
+		velocity_min	77.42
+		velocity_max	77.42
+		time_to_live	30
+		time_to_live_min	30
+		time_to_live_max	30
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		depth	0
+		width 500
+		height 500
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/ice.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ice.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ice.particle	(revision 11817)
@@ -0,0 +1,59 @@
+particle_system Orxonox/ice
+{
+	material PE/iceCrystal
+	particle_width 5
+	particle_height 5
+	quota 7000
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin center
+	billboard_rotation_type texcoord
+	point_rendering false
+	accurate_facing false
+
+	emitter Box
+	{
+		position 0.0 0.0 0.0
+		direction 1.0 1.0 1.0
+		angle 45
+		width 20
+		height 20
+		depth 20
+		emission_rate 200
+		velocity_min 1
+		velocity_max 1
+		time_to_live_min 3
+		time_to_live_max 6
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 1 1 1
+		colour_range_end 0.9 1 1 1
+	}
+
+	affector LinearForce
+	{
+		force_vector 0.0 -0.5 1.0
+		force_application add
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness 50
+		scope 100
+		keep_velocity true
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start 43.26
+		rotation_speed_range_end 0
+		rotation_range_start 0
+		rotation_range_end 0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/laser.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/laser.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/laser.particle	(revision 11817)
@@ -0,0 +1,47 @@
+particle_system Orxonox/laser
+{
+	quota	200
+	material	PE/point_lensflare
+	particle_width	7.08
+	particle_height	7.08
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 1 0.275862 1
+		colour_range_start	0 1 0.275862 1
+		colour_range_end	0 1 0.275862 1
+		direction	0 1 0
+		emission_rate	80
+		position	0 0 0
+		velocity	11
+		velocity_min	11
+		velocity_max	11
+		time_to_live	0.7
+		time_to_live_min	0.7
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	1.6
+		repeat_delay_min	1.6
+		repeat_delay_max	1.6
+	}
+
+	affector Scaler
+	{
+		rate	-8.8
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/load.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/load.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/load.particle	(revision 11817)
@@ -0,0 +1,141 @@
+particle_system Orxonox/load
+{
+	quota	50
+	material	PE/ringflare
+	particle_width	1
+	particle_height	1.3
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	5
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	4
+		position	0 -5 0
+		velocity	5
+		velocity_min	5
+		velocity_max	5
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	emitter Point
+	{
+		angle	5
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	1 0 0
+		emission_rate	3
+		position	-5 0 0
+		velocity	5
+		velocity_min	5
+		velocity_max	5
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	emitter Point
+	{
+		angle	5
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	-1 0 0
+		emission_rate	3
+		position	5 0 0
+		velocity	5
+		velocity_min	5
+		velocity_max	5
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	emitter Point
+	{
+		angle	5
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 -1 0
+		emission_rate	4
+		position	0 5 0
+		velocity	5
+		velocity_min	5
+		velocity_max	5
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	14.4
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	1 1 0.5 0
+		time0	1
+		colour1	0.5 0.5 0.5 0
+		time1	1
+		colour2	0.5 0.5 0.5 0
+		time2	1
+		colour3	0.5 0.5 0.5 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	15
+		scope	0.8
+		keep_velocity	false
+	}
+
+	
+}
Index: /code/branches/RacingBots_FS18/data/particle/mineparticle.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/mineparticle.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/mineparticle.particle	(revision 11817)
@@ -0,0 +1,53 @@
+particle_system Orxonox/mineparticle
+{
+	material PE/lensflare
+	particle_width 5.0
+	particle_height 5.0
+	quota 2000
+	cull_each true
+	sorted true
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin bottom_right
+	billboard_rotation_type vertex
+	point_rendering false
+	accurate_facing false
+
+	emitter HollowEllipsoid
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 20
+		height 20
+		depth 20
+		inner_width 0.99
+		inner_height 0.99
+		inner_depth 0.99
+		emission_rate 20.12
+		velocity_min 1
+		velocity_max 1
+		time_to_live_min 5
+		time_to_live_max 5
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0 0 1
+		colour_range_end 1 0 0 1
+	}
+
+	affector Scaler
+	{
+		rate -2
+	}
+	affector Rotator
+	{
+		rotation_speed_range_start 100
+		rotation_speed_range_end 500
+		rotation_range_start 0
+		rotation_range_end 180
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionAfterglow.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionAfterglow.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionAfterglow.particle	(revision 11817)
@@ -0,0 +1,47 @@
+
+particle_system orxonox/explosion_afterglow
+{
+	quota	200
+	material	PE/Flare
+	particle_width	40
+	particle_height	40
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_self
+
+	emitter Point
+	{
+		angle	180
+		colour	0.664063 0.917969 0.925781 1
+		colour_range_start	0.664063 0.917969 0.925781 1
+		colour_range_end	0.0820313 0.757813 0.980469 1
+		direction	0 1 0
+		emission_rate	700
+		position	0 0 0
+		velocity	20
+		velocity_min	20
+		velocity_max	75
+		time_to_live	0.2
+		time_to_live_min	0.2
+		time_to_live_max	5
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+	}
+
+	affector ColourFader
+	{
+		red	-0.7273
+		green	-0.7049
+		blue	-0.6216
+		alpha	0
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlame.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlame.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlame.particle	(revision 11817)
@@ -0,0 +1,58 @@
+
+particle_system orxonox/explosion_flame
+{
+	quota	500
+	material	PE/bigFlame
+	particle_width	20.52
+	particle_height	20.25
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Box
+	{
+		angle	180
+		colour	1 0.533333 0.0631577 1
+		colour_range_start	1 0.533333 0.0631577 1
+		colour_range_end	0.441667 0 0 1
+		direction	1 0 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	30
+		velocity_min	30
+		velocity_max	80
+		time_to_live	0.2
+		time_to_live_min	0.2
+		time_to_live_max	3
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+		width	2
+		height	2
+		depth	2
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-1
+		alpha	-1
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	-360
+		rotation_speed_range_end	360
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlame2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlame2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlame2.particle	(revision 11817)
@@ -0,0 +1,58 @@
+
+particle_system orxonox/explosion_flame2
+{
+	quota	500
+	material	PE/bigFlame
+	particle_width	20.52
+	particle_height	20.25
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Box
+	{
+		angle	180
+		colour	1 0.566667 0.5 1
+		colour_range_start	1 0.566667 0.5 1
+		colour_range_end	1 0.566667 0.5 1
+		direction	1 0 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	30
+		velocity_min	30
+		velocity_max	80
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	3
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+		width	2
+		height	2
+		depth	2
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-0.7027
+		alpha	-1
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	-360
+		rotation_speed_range_end	360
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlash.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlash.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlash.particle	(revision 11817)
@@ -0,0 +1,55 @@
+
+particle_system orxonox/explosion_flash
+{
+	quota	50
+	material	orxonox/explosion_flash
+	particle_width	50
+	particle_height	50
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 0 0
+		emission_rate	10
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	0.05
+		time_to_live_min	0.05
+		time_to_live_max	0.05
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	100000
+		repeat_delay_min	100000
+		repeat_delay_max	100000
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector Scaler
+	{
+		rate	1000
+	}
+	
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-1
+		alpha	-1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlash2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlash2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionFlash2.particle	(revision 11817)
@@ -0,0 +1,47 @@
+
+particle_system orxonox/explosion_flash2
+{
+	quota	50
+	material	orxonox/explosion_flash
+	particle_width	50
+	particle_height	50
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 0 0
+		emission_rate	10
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	0.05
+		time_to_live_min	0.05
+		time_to_live_max	0.05
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector Scaler
+	{
+		rate	100
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionShockwave.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionShockwave.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionShockwave.particle	(revision 11817)
@@ -0,0 +1,48 @@
+
+particle_system orxonox/explosion_shockwave
+{
+	quota	4000
+	material	orxonox/explosion_shockwave
+	particle_width	20
+	particle_height	20
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_common
+	common_direction	0 0.25 0.5
+
+	emitter Point
+	{
+		angle	0
+		colour	0.441667 0.441667 0.441667 1
+		colour_range_start	0.441667 0.441667 0.441667 1
+		colour_range_end	0.441667 0.441667 0.441667 1
+		direction	0 1 0
+		emission_rate	10
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	100000
+		repeat_delay_min	100000
+		repeat_delay_max	100000
+	}
+
+	affector Scaler
+	{
+		rate	500
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-1
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionShockwave2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionShockwave2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionShockwave2.particle	(revision 11817)
@@ -0,0 +1,48 @@
+
+particle_system orxonox/explosion_shockwave2
+{
+	quota	4000
+	material	orxonox/explosion_shockwave
+	particle_width	20
+	particle_height	20
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_common
+	common_direction	0 0.25 0.5
+
+	emitter Point
+	{
+		angle	0
+		colour	0.85 0.85 1 1
+		colour_range_start	0.85 0.85 1 1
+		colour_range_end	0.85 0.85 1 1
+		direction	0 1 0
+		emission_rate	10
+		position	0 0 0
+		velocity	0
+		velocity_min	0
+		velocity_max	0
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	1
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+	}
+
+	affector Scaler
+	{
+		rate	500
+	}
+
+	affector ColourFader
+	{
+		red	-1
+		green	-1
+		blue	-1
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionSparks.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionSparks.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionSparks.particle	(revision 11817)
@@ -0,0 +1,42 @@
+
+particle_system orxonox/explosion_sparks
+{
+	quota	2000
+	material	PE/explosion
+	particle_width	1.5
+	particle_height	12.33
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_self
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	-0.684313 -0.325257 0.652628
+		emission_rate	1000
+		position	0 0 0
+		velocity	100
+		velocity_min	100
+		velocity_max	200
+		time_to_live	0.2
+		time_to_live_min	0.2
+		time_to_live_max	0.5
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	100000
+		repeat_delay_min	100000
+		repeat_delay_max	100000
+	}
+
+	affector ColourFader
+	{
+		red	0.2432
+		green	-1
+		blue	-1
+		alpha	-1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionSparks2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionSparks2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionSparks2.particle	(revision 11817)
@@ -0,0 +1,42 @@
+
+particle_system orxonox/explosion_sparks2
+{
+	quota	2000
+	material	PE/explosion
+	particle_width	1.5
+	particle_height	13.98
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_self
+
+	emitter Point
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	-0.684313 -0.325257 0.652628
+		emission_rate	1000
+		position	0 0 0
+		velocity	150
+		velocity_min	150
+		velocity_max	200
+		time_to_live	0.2
+		time_to_live_min	0.2
+		time_to_live_max	0.75
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+	}
+
+	affector ColourFader
+	{
+		red	0.2432
+		green	-1
+		blue	-1
+		alpha	-1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionStreak1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionStreak1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionStreak1.particle	(revision 11817)
@@ -0,0 +1,42 @@
+
+particle_system orxonox/explosion_streak1
+{
+	quota	4000
+	material	orxonox/explosion_streak1
+	particle_width	12.15
+	particle_height	82.13
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_self
+
+	emitter Point
+	{
+		angle	180
+		colour	0.191667 0.191667 0.191667 1
+		colour_range_start	0.191667 0.191667 0.191667 1
+		colour_range_end	0.191667 0.191667 0.191667 1
+		direction	0 1 0
+		emission_rate	400
+		position	0 0 0
+		velocity	30
+		velocity_min	30
+		velocity_max	100
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	2
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+	}
+
+	affector ColourFader
+	{
+		red	-0.2
+		green	-0.2
+		blue	-0.2
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/orxonox_explosionStreak2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/orxonox_explosionStreak2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/orxonox_explosionStreak2.particle	(revision 11817)
@@ -0,0 +1,47 @@
+
+particle_system orxonox/explosion_streak2
+{
+	quota	4000
+	material	orxonox/explosion_streak1
+	particle_width	14
+	particle_height	75
+	cull_each	false
+	renderer	billboard
+	billboard_type	oriented_self
+
+	emitter Point
+	{
+		angle	180
+		colour	0.466667 0.341667 0.216667 1
+		colour_range_start	0.466667 0.341667 0.216667 1
+		colour_range_end	0.466667 0.341667 0.216667 1
+		direction	0 1 0
+		emission_rate	400
+		position	0 0 0
+		velocity	50
+		velocity_min	50
+		velocity_max	80
+		time_to_live	1
+		time_to_live_min	1
+		time_to_live_max	2
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	20
+		repeat_delay_min	20
+		repeat_delay_max	20
+	}
+
+	affector ColourFader
+	{
+		red	-0.3
+		green	-0.25
+		blue	-0.2
+		alpha	0
+	}
+
+	affector Scaler
+	{
+		rate	10
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/particlecanon.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/particlecanon.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/particlecanon.particle	(revision 11817)
@@ -0,0 +1,43 @@
+particle_system Orxonox/particlecanon
+{
+	quota	1000
+	material	PE/point_lensflare
+	particle_width	6
+	particle_height	6
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	1
+		colour	0.965517 0.544828 0 1
+		colour_range_start	0.965517 0.544828 0 1
+		colour_range_end	0.965517 0.544828 0 1
+		direction	0 1 0
+		emission_rate	1220
+		position	0 0 0
+		velocity	300
+		velocity_min	300
+		velocity_max	300
+		time_to_live	0.05
+		time_to_live_min	0.05
+		time_to_live_max	0.05
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+}
Index: /code/branches/RacingBots_FS18/data/particle/psygun.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/psygun.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/psygun.particle	(revision 11817)
@@ -0,0 +1,62 @@
+particle_system Orxonox/psygun
+{
+	material PE/glowEffect
+	particle_width 200.0
+	particle_height 200.0
+	quota 300
+	cull_each false
+	sorted false
+	local_space false
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin top_right
+	billboard_rotation_type vertex
+	point_rendering false
+	accurate_facing true
+
+	emitter Point
+	{
+		position 0.0 0.0 0.0
+		direction 0.0 1.0 0.0
+		angle 154.8
+		emission_rate 400
+		velocity_min 100
+		velocity_max 300
+		time_to_live_min 0
+		time_to_live_max 3.38
+		duration_min 1
+		duration_max 1
+		repeat_delay_min 0.11
+		repeat_delay_max 2.81
+		colour_range_start 0.666667 0 0.498039 1
+		colour_range_end 1 0 0.498039 1
+	}
+
+	affector LinearForce
+	{
+		force_vector 0.0 12.32 0.0
+		force_application add
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start 100
+		rotation_speed_range_end 500
+		rotation_range_start 0
+		rotation_range_end 180
+	}
+
+	affector Scaler
+	{
+		rate -98.82
+	}
+
+	affector ColourFader
+	{
+		red -0.93
+		green -1
+		blue 1
+		alpha -1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/ray1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ray1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ray1.particle	(revision 11817)
@@ -0,0 +1,30 @@
+
+particle_system Orxonox/ray1
+{
+	quota	1000
+	material	PE/lensflare
+	particle_width	4
+	particle_height	4
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Point
+	{
+		angle	0
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	100
+		position	0 0 0
+		velocity	50
+		time_to_live	8
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/ray2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/ray2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/ray2.particle	(revision 11817)
@@ -0,0 +1,38 @@
+
+particle_system Orxonox/ray2
+{
+	quota	1200
+	material	PE/lensflare
+	particle_width	4
+	particle_height	4
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Ring
+	{
+		angle	0
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 1 0
+		emission_rate	7
+		position	0 0 0
+		velocity	20
+		velocity_min	20
+		velocity_max	50
+		time_to_live	10
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	15
+		height	15
+		depth	15
+		inner_width	0.5
+		inner_height	0.5
+	}
+
+}
Index: /code/branches/RacingBots_FS18/data/particle/repairGold.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/repairGold.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/repairGold.particle	(revision 11817)
@@ -0,0 +1,49 @@
+
+particle_system Orxonox/repairGold
+{
+	quota	200
+	material	PE/lensflare
+	particle_width	47.38
+	particle_height	47.38
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter HollowEllipsoid
+	{
+		angle	180
+		colour	0.91358 0.734568 0 1
+		colour_range_start	0.91358 0.734568 0 1
+		colour_range_end	0.91358 0.734568 0 1
+		direction	0 1 0
+		emission_rate	216.2
+		position	0 0 0
+		velocity	1
+		velocity_min	1
+		velocity_max	1
+		time_to_live	0.5405
+		time_to_live_min	0.5405
+		time_to_live_max	0.5405
+		duration	1.441
+		duration_min	1.441
+		duration_max	1.622
+		repeat_delay	0.7207
+		repeat_delay_min	0.7207
+		repeat_delay_max	0.7207
+		width	200
+		height	200
+		depth	200
+		inner_width	0.9
+		inner_height	0.9
+		inner_depth	0.9
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/repairSilver.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/repairSilver.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/repairSilver.particle	(revision 11817)
@@ -0,0 +1,49 @@
+
+particle_system Orxonox/repairSilver
+{
+	quota	500
+	material	PE/lensflare
+	particle_width	47.38
+	particle_height	47.38
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter HollowEllipsoid
+	{
+		angle	0
+		colour	0.691358 0.814815 1 1
+		colour_range_start	0.691358 0.814815 1 1
+		colour_range_end	0.691358 0.814815 1 1
+		direction	0 1 0
+		emission_rate	342.3
+		position	0 0 0
+		velocity	1
+		velocity_min	1
+		velocity_max	1
+		time_to_live	0.4
+		time_to_live_min	0.4
+		time_to_live_max	0.4
+		duration	0.7
+		duration_min	0.7
+		duration_max	0.7
+		repeat_delay	0.7207
+		repeat_delay_min	0.7207
+		repeat_delay_max	0.7207
+		width	200
+		height	200
+		depth	200
+		inner_width	0.9
+		inner_height	0.9
+		inner_depth	0.9
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/rocketfire.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/rocketfire.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/rocketfire.particle	(revision 11817)
@@ -0,0 +1,63 @@
+particle_system Orxonox/rocketfire
+{
+	material PE/glowEffect
+	particle_width 2
+	particle_height 2
+	quota 10000
+	cull_each true
+	sorted true
+	local_space true
+	iteration_interval 0.0
+	nonvisible_update_timeout 0.0
+	billboard_type point
+	billboard_origin center
+	billboard_rotation_type texcoord
+	point_rendering false
+	accurate_facing false
+
+	emitter Ellipsoid
+	{
+		position 0.05 0.0 2.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 0
+		height 0
+		depth 0
+		emission_rate 1200
+		velocity_min 10
+		velocity_max 20
+		time_to_live_min 0.1
+		time_to_live_max 0.1
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 1 0.333333 0 1
+		colour_range_end 1 0 0 1
+	}
+	emitter Ellipsoid
+	{
+		position 0.05 0.0 2.0
+		direction 0.0 0.0 1.0
+		angle 0
+		width 0
+		height 0
+		depth 0
+		emission_rate 100
+		velocity_min 5
+		velocity_max 10
+		time_to_live_min 0.1
+		time_to_live_max 0.1
+		duration_min 0
+		duration_max 0
+		repeat_delay_min 0
+		repeat_delay_max 0
+		colour_range_start 0.2 0.5 0.65
+		colour_range_end 0.25 0.55 0.7
+	}
+
+	affector Scaler
+	{
+		rate -8
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/rocketfire2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/rocketfire2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/rocketfire2.particle	(revision 11817)
@@ -0,0 +1,50 @@
+particle_system Orxonox/rocketfire2
+{
+	quota	300
+	material	PE/explosion
+	particle_width	5
+	particle_height	2
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	2
+		colour	1 0.682759 1 1
+		colour_range_start	1 0.682759 1 1
+		colour_range_end	1 0.682759 1 1
+		direction	0 0 1
+		emission_rate	1200
+		position	0 0 3
+		velocity	10
+		velocity_min	10
+		velocity_max	48
+		time_to_live	0.1
+		time_to_live_min	0.1
+		time_to_live_max	0.2
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	0.8
+		height	0.8
+		depth	4
+	}
+
+	affector Scaler
+	{
+		rate	-20
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/shot1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/shot1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/shot1.particle	(revision 11817)
@@ -0,0 +1,36 @@
+particle_system Orxonox/shot1
+{
+	quota	5000
+	material	PE/lensflare
+	particle_width	3
+	particle_height	3
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Cylinder
+	{
+		angle	0
+		colour	1 1 0 1
+		colour_range_start	1 1 0 1
+		colour_range_end	0.3 1 0.3 1
+		direction	0 1 0
+		emission_rate	260.9
+		position	0 0 0
+		velocity	120
+		velocity_min	120
+		velocity_max	120
+		time_to_live	2
+		time_to_live_min	2
+		time_to_live_max	2
+		duration	0.1
+		duration_min	0.1
+		duration_max	0.1
+		repeat_delay	0.5
+		repeat_delay_min	0.5
+		repeat_delay_max	0.5
+		width	0.5
+		height	0.5
+		depth	5
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/shot2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/shot2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/shot2.particle	(revision 11817)
@@ -0,0 +1,56 @@
+
+particle_system Orxonox/shot2
+{
+	quota	25
+	material	PE/point_lensflare
+	particle_width	40
+	particle_height	100
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	0
+		colour	0 0 0 1
+		colour_range_start	0 0 0 1
+		colour_range_end	0.5 0.5 0.7 1
+		direction	0 -1 0
+		emission_rate	40
+		position	0 0 0
+		velocity	200
+		velocity_min	200
+		velocity_max	300
+		time_to_live	0.5
+		time_to_live_min	0.5
+		time_to_live_max	0.5
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	-20
+	}
+
+	affector ColourFader
+	{
+		red	-0.8
+		green	-0.8
+		blue	-0.5
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/shot2_small.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/shot2_small.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/shot2_small.particle	(revision 11817)
@@ -0,0 +1,56 @@
+
+particle_system Orxonox/shot2_small
+{
+	quota	25
+	material	PE/point_lensflare
+	particle_width	10
+	particle_height	25
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	true
+
+	emitter Point
+	{
+		angle	0
+		colour	0 0 0 1
+		colour_range_start	0.4 0.4 0.6 1
+		colour_range_end	0.5 0.5 0.7 1
+		direction	0 -1 0
+		emission_rate	80
+		position	0 0 0
+		velocity	1
+		velocity_min	1
+		velocity_max	1
+		time_to_live	0.25
+		time_to_live_min	0.25
+		time_to_live_max	0.25
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	-20
+	}
+
+	affector ColourFader
+	{
+		red	-1.6
+		green	-1.6
+		blue	-1.0
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/shot3_small.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/shot3_small.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/shot3_small.particle	(revision 11817)
@@ -0,0 +1,56 @@
+
+particle_system Orxonox/shot3_small
+{
+	quota	25
+	material	PE/point_lensflare
+	particle_width	10
+	particle_height	25
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	true
+
+	emitter Point
+	{
+		angle	0
+		colour	0 0 0 1
+		colour_range_start	0.4 0.4 0.6 1
+		colour_range_end	0.5 0.5 0.7 1
+		direction	0 -1 0
+		emission_rate	80
+		position	0 0 0
+		velocity	1
+		velocity_min	1
+		velocity_max	1
+		time_to_live	0.25
+		time_to_live_min	0.25
+		time_to_live_max	0.25
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	-15
+	}
+
+	affector ColourFader
+	{
+		red	-1.6
+		green	-1.6
+		blue	-1.0
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/shotTest.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/shotTest.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/shotTest.particle	(revision 11817)
@@ -0,0 +1,55 @@
+
+particle_system Orxonox/shotTest
+{
+	quota	3000
+	material	PE/bigFlame
+	particle_width	1
+	particle_height	10
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	true
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	7.2
+		colour	1 0 0 0.9
+		colour_range_start	1 0 0 0.9
+		colour_range_end	1 0.185185 0 0.9
+		direction	0 1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	300
+		velocity_min	300
+		velocity_max	300
+		time_to_live	0.2
+		time_to_live_min	0.2
+		time_to_live_max	0.2
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	500
+		scope	1
+		keep_velocity	false
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/simplerocketfire.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/simplerocketfire.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/simplerocketfire.particle	(revision 11817)
@@ -0,0 +1,50 @@
+	particle_system Orxonox/simplerocketfire
+{
+	quota	300
+	material	PE/explosion
+	particle_width	5
+	particle_height	2
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	2
+		colour	1 0.682759 1 1
+		colour_range_start	1 0.682759 1 1
+		colour_range_end	1 0.682759 1 1
+		direction	0 0 1
+		emission_rate	1200
+		position	0 0 3
+		velocity	10
+		velocity_min	10
+		velocity_max	48
+		time_to_live	0.1
+		time_to_live_min	0.1
+		time_to_live_max	0.2
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	0.8
+		height	0.8
+		depth	7
+	}
+
+	affector Scaler
+	{
+		rate	-20
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke.particle	(revision 11817)
@@ -0,0 +1,45 @@
+particle_system Orxonox/smoke
+{
+	quota	300
+	material	PE/explosion
+	particle_width	6.94
+	particle_height	7.93
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	13
+		colour	0.156897 0.326207 1 1
+		colour_range_start	0.156897 0.326207 1 1
+		colour_range_end	0.156897 0.326207 1 1
+		direction	0 1 0
+		emission_rate	65
+		position	0 0 0
+		velocity	25
+		velocity_min	25
+		velocity_max	25
+		time_to_live	2.2
+		time_to_live_min	2.2
+		time_to_live_max	2.2
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	3
+		height	3
+		depth	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke2.particle	(revision 11817)
@@ -0,0 +1,45 @@
+
+particle_system Orxonox/smoke2
+{
+	quota	1000
+	material	PE/smoke
+	particle_width	4
+	particle_height	4
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Ellipsoid
+	{
+		angle	150
+		colour	0.0547945 0.0547945 0.0547945 0.9
+		colour_range_start	0.0547945 0.0547945 0.0547945 0.9
+		colour_range_end	0.0547945 0.0547945 0.0547945 0.9
+		direction	0 1 0
+		emission_rate	40
+		position	0 0 0
+		velocity	2
+		velocity_min	2
+		velocity_max	2
+		time_to_live	3
+		time_to_live_min	3
+		time_to_live_max	5
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	0.2
+		height	0.2
+		depth	0.2
+	}
+
+	affector ColourFader
+	{
+		red	0.3
+		green	0.3
+		blue	0.3
+		alpha	-0.35
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke3.particle	(revision 11817)
@@ -0,0 +1,79 @@
+
+particle_system Orxonox/smoke3
+{
+	quota	10
+	material	PE/smoke2
+	particle_width	30
+	particle_height	30
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	10
+		position	0 0 0
+		velocity	7
+		velocity_min	7
+		velocity_max	7
+		time_to_live	5
+		time_to_live_min	5
+		time_to_live_max	5
+		duration	1
+		duration_min	1
+		duration_max	1
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+	}
+
+	affector Scaler
+	{
+		rate	20
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	150
+		scope	1
+		keep_velocity	true
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	-20
+		rotation_speed_range_end	20
+		rotation_range_start	0
+		rotation_range_end	0
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	0.5 0.5 0.5 0.2
+		time1	0.2
+		colour2	0.5 0.5 0.5 0.5
+		time2	0.5
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke4.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke4.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke4.particle	(revision 11817)
@@ -0,0 +1,72 @@
+
+particle_system Orxonox/smoke4
+{
+	quota	10
+	material	PE/smoke3
+	particle_width	7
+	particle_height	7
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	15
+		position	0 0 0
+		velocity	20
+		velocity_min	20
+		velocity_max	20
+		time_to_live	1.5
+		time_to_live_min	1.5
+		time_to_live_max	1.5
+		duration	0.3
+		duration_min	0.3
+		duration_max	0.3
+		repeat_delay	1000000
+		repeat_delay_min	1000000
+		repeat_delay_max	1000000
+	}
+
+	affector Scaler
+	{
+		rate	15
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	-50
+		rotation_speed_range_end	50
+		rotation_range_start	0
+		rotation_range_end	0
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	0.5 0.5 0.5 0.4
+		time1	0.2
+		colour2	0.5 0.5 0.5 0.8
+		time2	0.5
+		colour3	0 0 0 0
+		time3	1
+		colour4	0.5 0.5 0.5 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke5.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke5.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke5.particle	(revision 11817)
@@ -0,0 +1,72 @@
+
+particle_system Orxonox/smoke5
+{
+	quota	80
+	material	PE/smoke3
+	particle_width	40
+	particle_height	40
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	20
+		position	0 0 0
+		velocity	7
+		velocity_min	7
+		velocity_max	7
+		time_to_live	3
+		time_to_live_min	3
+		time_to_live_max	3
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	30
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	-50
+		rotation_speed_range_end	50
+		rotation_range_start	0
+		rotation_range_end	0
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0 0 0 0
+		time0	0
+		colour1	0.5 0.5 0.5 0.4
+		time1	0.05
+		colour2	0.3 0.3 0.3 0.8
+		time2	0.5
+		colour3	0.1 0.1 0.1 0.4
+		time3	0.8
+		colour4	0 0 0 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke6.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke6.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke6.particle	(revision 11817)
@@ -0,0 +1,64 @@
+
+particle_system Orxonox/smoke6
+{
+	quota	50
+	material	PE/smoke2
+	particle_width	25
+	particle_height	10
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 1
+		colour_range_start	0 0 0 1
+		colour_range_end	0 0 0 1
+		direction	0 1 0
+		emission_rate	50
+		position	0 0 0
+		velocity	40
+		velocity_min	40
+		velocity_max	60
+		time_to_live	1.5
+		time_to_live_min	1.5
+		time_to_live_max	1.5
+		duration	1
+		duration_min	1
+		duration_max	1
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+	}
+
+	affector Scaler
+	{
+		rate	100
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.3 0.3 0.3 0.0
+		time0	0.1
+		colour1	0.2 0.2 0.2 0.2
+		time1	0.2
+		colour2	0.2 0.2 0.2 0.2
+		time2	0.6
+		colour3	0 0 0 0
+		time3	1
+		colour4	0 0 0 0
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/smoke7.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/smoke7.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/smoke7.particle	(revision 11817)
@@ -0,0 +1,72 @@
+
+particle_system Orxonox/smoke7
+{
+	quota	25
+	material	PE/smoke2
+	particle_width	8
+	particle_height	8
+	cull_each	false
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	vertex
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0 0 0 0
+		colour_range_start	0 0 0 0
+		colour_range_end	0 0 0 0
+		direction	0 1 0
+		emission_rate	25
+		position	0 0 0
+		velocity	5
+		velocity_min	5
+		velocity_max	10
+		time_to_live	1.0
+		time_to_live_min	1.0
+		time_to_live_max	1.0
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector Scaler
+	{
+		rate	3
+	}
+
+	affector Rotator
+	{
+		rotation_speed_range_start	0
+		rotation_speed_range_end	0
+		rotation_range_start	0
+		rotation_range_end	360
+	}
+
+	affector ColourInterpolator
+	{
+		colour0	0.2 0.2 0.2 0
+		time0	0
+		colour1	0.15 0.15 0.15 0.7
+		time1	0.1
+		colour2	0.15 0.15 0.15 1
+		time2	0.6
+		colour3	0.1 0.1 0.1 0
+		time3	1
+		colour4	0.5 0.5 0.5 1
+		time4	1
+		colour5	0.5 0.5 0.5 0
+		time5	1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/sparks.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/sparks.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/sparks.particle	(revision 11817)
@@ -0,0 +1,61 @@
+
+particle_system Orxonox/sparks
+{
+	quota	100
+	material	PE/lensflare
+	particle_width	4
+	particle_height	4
+	cull_each	true
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	point
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Ellipsoid
+	{
+		angle	180
+		colour	0.8 0.6 0.4 1
+		colour_range_start	0.8 0.6 0.4 1
+		colour_range_end	1 0.7 0.5 1
+		direction	0 -1 0
+		emission_rate	2000
+		position	0 0 0
+		velocity	1
+		velocity_min	1
+		velocity_max	1
+		time_to_live	4
+		time_to_live_min	4
+		time_to_live_max	4
+		duration	0.05
+		duration_min	0.05
+		duration_max	0.05
+		repeat_delay	5
+		repeat_delay_min	5
+		repeat_delay_max	5
+		width	75
+		height	75
+		depth	75
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	250
+		scope	0.1
+		keep_velocity	true
+	}
+
+	affector ColourFader
+	{
+		red	-0.25
+		green	-0.20
+		blue	-0.15
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/sparks2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/sparks2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/sparks2.particle	(revision 11817)
@@ -0,0 +1,51 @@
+
+particle_system Orxonox/sparks2
+{
+	quota	1000
+	material	PE/Flare
+	particle_width	15
+	particle_height	40
+	cull_each	true
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	oriented_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Point
+	{
+		angle	180
+		colour	0.1 0.1 0.1 1
+		colour_range_start	0.1 0.1 0.1 1
+		colour_range_end	1 1 1 1
+		direction	0 0 -1
+		emission_rate	5000
+		position	0 0 0
+		velocity	10
+		velocity_min	15
+		velocity_max	150
+		time_to_live	0.5
+		time_to_live_min	0.5
+		time_to_live_max	0.5
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+	}
+
+	affector ColourFader
+	{
+		red	-2.0
+		green	-2.0
+		blue	-2.0
+		alpha	0
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/tes3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/tes3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/tes3.particle	(revision 11817)
@@ -0,0 +1,59 @@
+particle_system Orxonox/tes3
+{
+	quota	500
+	material	PE/lensflare
+	particle_width	10
+	particle_height	10
+	cull_each	true
+	renderer	billboard
+	sorted	false
+	local_space	false
+	iteration_interval	0
+	nonvisible_update_timeout	0
+	billboard_type	perpendicular_self
+	billboard_origin	center
+	billboard_rotation_type	texcoord
+	common_up_vector	0 1 0
+	point_rendering	false
+	accurate_facing	false
+
+	emitter Cylinder
+	{
+		angle	180
+		colour	1 1 1 1
+		colour_range_start	1 1 1 1
+		colour_range_end	1 1 1 1
+		direction	0 -1 0
+		emission_rate	100
+		position	0 100 0
+		velocity	26
+		velocity_min	26
+		velocity_max	26
+		time_to_live	9.6
+		time_to_live_min	9.6
+		time_to_live_max	9.6
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	200
+		height	200
+		depth	1
+	}
+
+	affector DeflectorPlane
+	{
+		plane_point	0 0 0
+		plane_normal	0 1 0
+		bounce	2
+	}
+
+	affector DirectionRandomiser
+	{
+		randomness	7
+		scope	1
+		keep_velocity	true
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/thruster1.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/thruster1.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/thruster1.particle	(revision 11817)
@@ -0,0 +1,53 @@
+particle_system Orxonox/thruster1
+{
+	quota	100
+	material	PE/bigFlame
+	particle_width	15
+	particle_height	15
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter HollowEllipsoid
+	{
+		angle	0
+		colour	0.493151 0.246575 0.0410959 1
+		colour_range_start	0.493151 0.246575 0.0410959 1
+		colour_range_end	0.684932 0.547945 0.315068 1
+		direction	0 1 0
+		emission_rate	300
+		position	0 0 0
+		velocity	100
+		velocity_min	18
+		velocity_max	30
+		time_to_live	0.25
+		time_to_live_min	0
+		time_to_live_max	0.25
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	5
+		height	5
+		depth	2.8
+		inner_width	0.8
+		inner_height	0.8
+		inner_depth	0.8
+	}
+
+
+	affector ColourFader2
+	{
+		red1	0
+		green1	0
+		blue1	0
+		alpha1	0
+		red2	-0.3
+		green2	-0.6
+		blue2	-0.6
+		alpha2	0
+		state_change	0.25
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/thruster2.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/thruster2.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/thruster2.particle	(revision 11817)
@@ -0,0 +1,47 @@
+particle_system Orxonox/thruster2
+{
+	quota	150
+	material	PE/bigFlame
+	particle_width	15
+	particle_height	15
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter HollowEllipsoid
+	{
+		angle	0
+		colour	0.4 0.3 0.8 1
+		colour_range_start	0.4 0.3 0.8 1
+		colour_range_end	0.5 0.4 0.9 1
+		direction	0 1 0
+		emission_rate	400
+		position	0 0 0
+		velocity	5
+		velocity_min	4
+		velocity_max	6
+		time_to_live	0.1
+		time_to_live_min	0.15
+		time_to_live_max	0.25
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	4
+		height	2.5
+		depth	1.3
+		inner_width	0.5
+		inner_height	0.3
+		inner_depth	0.2
+	}
+
+	affector ColourFader
+	{
+		red	-0.5
+		green	-0.5
+		blue	-0.6
+		alpha	-0.5
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/thruster3.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/thruster3.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/thruster3.particle	(revision 11817)
@@ -0,0 +1,53 @@
+particle_system Orxonox/thruster3
+{
+	quota	100
+	material	PE/bigFlame
+	particle_width	2
+	particle_height	2
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter HollowEllipsoid
+	{
+		angle	0
+		colour	0.493151 0.246575 0.0410959 1
+		colour_range_start	0.493151 0.246575 0.0410959 1
+		colour_range_end	0.684932 0.547945 0.315068 1
+		direction	-1 0 0
+		emission_rate	300
+		position	0 0 0
+		velocity	6
+		velocity_min	5
+		velocity_max	7
+		time_to_live	0.125
+		time_to_live_min	0.100
+		time_to_live_max	0.125
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	1
+		height	1
+		depth	2.8
+		inner_width	0.8
+		inner_height	0.8
+		inner_depth	0.8
+	}
+
+
+	affector ColourFader2
+	{
+		red1	0
+		green1	0
+		blue1	0
+		alpha1	0
+		red2	-0.2
+		green2	-0.5
+		blue2	-0.5
+		alpha2	0
+		state_change	0.1
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/weaponflare.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/weaponflare.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/weaponflare.particle	(revision 11817)
@@ -0,0 +1,46 @@
+
+particle_system Orxonox/weaponflare
+{
+	quota	10000
+	material	PE/lensflare
+	particle_width	4
+	particle_height	4
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter HollowEllipsoid
+	{
+		angle	0
+		colour	0.128 0.28 1 1
+		colour_range_start	0.128 0.28 1 1
+		colour_range_end	0.05 0.05 1 1
+		direction	0 0 0
+		emission_rate	130
+		position	0 0 0
+		velocity	-0.8
+		velocity_min	-0.8
+		velocity_max	-0.8
+		time_to_live	.000001
+		time_to_live_min	.000001
+		time_to_live_max	.000004
+		duration	0
+		duration_min	0
+		duration_max	0
+		repeat_delay	0
+		repeat_delay_min	0
+		repeat_delay_max	0
+		width	0.1
+		height	0.1
+		depth	0.1
+		inner_width	0.001
+		inner_height	0.001
+		inner_depth	0.001
+	}
+
+	affector LinearForce
+	{
+		force_vector	0 0 0
+		force_application	add
+	}
+}
Index: /code/branches/RacingBots_FS18/data/particle/weaponshoot.particle
===================================================================
--- /code/branches/RacingBots_FS18/data/particle/weaponshoot.particle	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/particle/weaponshoot.particle	(revision 11817)
@@ -0,0 +1,57 @@
+
+particle_system Orxonox/weaponshoot
+{
+	quota	2000
+	material	PE/lensflare
+	particle_width	3
+	particle_height	3
+	cull_each	false
+	renderer	billboard
+	billboard_type	point
+
+	emitter Point
+	{
+		angle	0.5
+		colour	0 0 0.8 1
+		colour_range_start	0 0 0.8 1
+		colour_range_end	0.1 0.1 0.9 1
+		direction	0 0 1
+		emission_rate	6
+		position	0 0 0
+		velocity	35
+		velocity_min	35
+		velocity_max	35
+		time_to_live	5
+		time_to_live_min	5
+		time_to_live_max	5
+		duration	1
+		duration_min	1
+		duration_max	1
+		repeat_delay	4
+		repeat_delay_min	4
+		repeat_delay_max	4
+	}
+
+	emitter Point
+	{
+		angle	90
+		colour	0 0 0.8 1
+		colour_range_start	0 0 0.8 1
+		colour_range_end	0.1 0.1 1 1
+		direction	0 0 -1
+		emission_rate	1500
+		position	0 0 0
+		velocity	15
+		velocity_min	15
+		velocity_max	15
+		time_to_live	0.005
+		time_to_live_min	0.005
+		time_to_live_max	0.0075
+		duration	0.75
+		duration_min	0.75
+		duration_max	0.75
+		repeat_delay	4.25
+		repeat_delay_min	4.25
+		repeat_delay_max	4.25
+	}
+}
Index: /code/branches/RacingBots_FS18/data/tcl/init.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/init.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/init.tcl	(revision 11817)
@@ -0,0 +1,305 @@
+# Check if Tcl was properly initialized
+info library
+
+# Create orxonox namespace
+namespace eval orxonox {}
+
+# query --
+# Sends a query to the CommandExecutor of Orxonox and waits for the response.
+# This dummy procedure will be changed to it's real implementation by Orxonox itself.
+#
+# Arguments:
+# args - The command to send to Orxonox
+
+proc query args {
+    return -code error "Can't query Orxonox now"
+}
+
+
+# crossquery --
+# Sends a query to another Tcl-interpreter in Orxonox and waits for the response.
+# This dummy procedure will be changed to it's real implementation by Orxonox itself.
+#
+# Arguments:
+# id   - The ID of the other interpreter
+# args - The command to send to Orxonox
+
+proc crossquery {id args} {
+    return -code error "Can't query interpreter with ID $id now"
+}
+
+
+# execute --
+# Sends a command to the queue of Orxonox where it will be executed by the CommandExecutor after some time
+# This dummy procedure will be changed to it's real implementation by Orxonox itself.
+#
+# Arguments:
+# args - The command
+
+proc execute args {
+    return -code error "Can't execute a command now"
+}
+
+
+# crossexecute --
+# Sends a command to the queue of another Tcl-interpreter where it will be executed by after some time
+# This dummy procedure will be changed to it's real implementation by Orxonox itself.
+#
+# Arguments:
+# id   - The ID of the other interpreter
+# args - The command
+
+proc crossexecute {id args} {
+    return -code error "Can't execute a command now"
+}
+
+
+# running --
+# Returns true if the interpreter is still suposed to be running
+# This dummy procedure will be changed to it's real implementation by Orxonox itself.
+
+proc running {} {
+    return 1
+}
+
+
+# orxonox::while --
+# Works like while but breaks the loop if orxonox::running returns false
+
+proc ::orxonox::while {condition body} {
+    set condition_cmd [list expr $condition]
+    ::tcl::while {1} {
+        if {![uplevel 1 $condition_cmd] || ![::running]} {
+            break
+        }
+        uplevel 1 $body
+    }
+}
+
+
+# orxonox::for --
+# Works like for but breaks the loop if orxonox::running returns false
+
+proc ::orxonox::for {start condition step body} {
+    set condition_cmd [list expr $condition]
+    uplevel 1 $start
+    ::tcl::while {1} {
+        if {![uplevel 1 $condition_cmd] || ![::running]} {
+            break
+        }
+        uplevel 1 $body
+        uplevel 1 $step
+    }
+}
+
+
+# add the path to this file to the auto path
+
+set filepath [info script]
+#set ::orxonox::mediapath [string range $filepath 0 [string last "/" $filepath]]
+set ::orxonox::mediapath [file dirname $filepath]
+
+if {![info exists auto_path]} {
+   set auto_path [list]
+}
+
+if {[lsearch $auto_path $::orxonox::mediapath] == -1} {
+    lappend auto_path $::orxonox::mediapath
+}
+unset filepath
+
+
+# save the start directory and the library directory
+
+proc psd {} "return [pwd]"
+proc pld {} "return $::orxonox::mediapath"
+
+set pwd [pwd]
+set psd [psd]
+set pld [pld]
+
+
+# modify cd to automatically set $pwd
+
+if {[llength [info command ::tcl::cd]] == 0} {
+    rename cd ::tcl::cd
+}
+proc cd {{path "~"}} {
+    global pwd
+    ::tcl::cd $path
+    set pwd [pwd]
+}
+
+
+# change the working directory to the media path
+
+cd $::orxonox::mediapath
+
+
+# Redefines puts to write directly into the Orxonox console if the channel is stdout or stderr.
+
+if {[llength [info command ::tcl::puts]] == 0} {
+    rename puts ::tcl::puts
+}
+proc puts args {
+    set argc [llength $args]
+    if {$argc < 1 || $argc > 3} {
+        error "wrong # args: should be \"puts ?-nonewline? ?channelId? string\""
+    }
+
+    set newline 1
+    set input $args
+
+    if {$argc > 1 && [lindex $input 0] == "-nonewline"} {
+        set newline 0
+        set input [lrange $input 1 end]
+    } elseif {$argc == 3} {
+        if {[lindex $input 2] == "nonewline"} {
+            set newline 0
+            set input [lrange $input 0 1]
+        } else {
+            error "bad argument \"[lindex $input 2]\": should be \"nonewline\""
+        }
+    }
+
+    if {[llength $input] == 1} {
+        set input [list stdout [join $input]]
+    }
+
+    foreach {channel s} $input break
+
+    if {$channel == "stdout"} {
+        execute log $s
+    } elseif {$channel == "stderr"} {
+        execute error $s
+    } else {
+        eval [concat ::tcl::puts $args]
+    }
+}
+
+
+# Redefines unknown to send unknown commands back to orxonox
+
+if {[llength [info commands unknown]] != 0} {
+    # check if a command named "undefined_proc" exists, if yes rename it temporarily
+    set undefined_was_defined 0
+    if {[llength [info commands undefined_proc]] != 0} {
+        set undefined_was_defined 0
+        rename undefined_proc _undefined
+    }
+
+    # get the returned errormessage if an undefined_proc command is called
+    if {[llength [info commands ::tcl::unknown]] == 0} {
+        set errorcode [catch {unknown undefined_proc} result]
+    } else {
+        set errorcode [catch {::tcl::unknown undefined_proc} result]
+    }
+
+    if {$errorcode} {
+        set result_list [split $result]
+        set ::orxonox::errormessage_unknown [list]
+
+        # parse the error message (the original message was something like "invalid command name "undefined_proc"" but we just want "invalid command name")
+        foreach token $result_list {
+            if {![string match "*undefined_proc*" $token]} {
+                lappend ::orxonox::errormessage_unknown $token
+            }
+        }
+
+        unset result_list
+        unset token
+
+        set ::orxonox::errormessage_unknown_length [llength $::orxonox::errormessage_unknown]
+
+        # rename the original unknown procedure
+        if {[llength [info commands ::tcl::unknown]] == 0} {
+            rename unknown ::tcl::unknown
+        }
+
+        # define the modified version of unknown
+        # we implement two versions, because tcl8.4 complains if this fork is moved inside [unknown]
+        if {[info tclversion] >= 8.5} {
+            # version >= 8.5
+            proc unknown args {
+                global ::orxonox::errormessage_unknown ::orxonox::errormessage_unknown_length
+
+                set cmd [concat ::tcl::unknown $args]
+                set errorcode [catch {eval $cmd} result options]
+                set resultlist [split $result]
+                set success 1
+
+                if {$errorcode && [llength $resultlist] >= $::orxonox::errormessage_unknown_length} {
+                    for {set i 0} {$i < $::orxonox::errormessage_unknown_length} {incr i} {
+                        if {[lindex $::orxonox::errormessage_unknown $i] != [lindex $resultlist $i]} {
+                            set success 0
+                            break
+                        }
+                    }
+                } else {
+                    set success 0
+                }
+
+                if {!$success} {
+                    return -code $errorcode -options $options $result
+                } else {
+                    return [query $args]
+                }
+            }
+        } else {
+            # version < 8.5
+            proc unknown args {
+                global ::orxonox::errormessage_unknown ::orxonox::errormessage_unknown_length
+
+                set cmd [concat ::tcl::unknown $args]
+                set errorcode [catch {eval $cmd} result]
+                set resultlist [split $result]
+                set success 1
+
+                if {$errorcode && [llength $resultlist] >= $::orxonox::errormessage_unknown_length} {
+                    for {set i 0} {$i < $::orxonox::errormessage_unknown_length} {incr i} {
+                        if {[lindex $::orxonox::errormessage_unknown $i] != [lindex $resultlist $i]} {
+                            set success 0
+                            break
+                        }
+                    }
+                } else {
+                    set success 0
+                }
+
+                if {!$success} {
+                    return -code $errorcode $result
+                } else {
+                    return [query $args]
+                }
+            }
+        }
+
+        set success 1
+    } else {
+        set success 0
+    }
+
+    unset errorcode
+    unset result
+
+    # if the "undefined_proc" command was renamed previously, undo this
+    if {$undefined_was_defined} {
+        rename _undefined undefined_proc
+    }
+
+    unset undefined_was_defined
+
+    if {!$success} {
+        unset success
+        # something went wrong, use the default method
+        proc unknown args {
+            return [query $args]
+        }
+    }
+    unset success
+} else {
+    # no original unknown procedure defined, use the default method
+    proc unknown args {
+        return [query $args]
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irc.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irc.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irc.tcl	(revision 11817)
@@ -0,0 +1,6 @@
+proc every {ms body} { eval $body; after $ms [list every $ms $body] }
+package require irk
+set conn [irk::connect orxonox $nickname]
+irk::join $conn #orxonox
+every 25 {}
+vwait termination
Index: /code/branches/RacingBots_FS18/data/tcl/irk/README
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/README	(revision 11817)
@@ -0,0 +1,76 @@
+IRK README
+==========
+
+Welcome to IRK, a Tcl IRC client library. IRK is intended for Tcl
+programmers that want to use the IRC protocol for communication. It
+can be used to ease the creation of IRC "bots", as shown by the
+examples in the examples directory, and it can also serve as the basis
+for graphical chat clients. Finally, it can be used to allow IRKs to
+find each other without centralized coordination, by meeting on a
+designated IRC server and channel. It is therefore ideal for setting
+up the initial contact for P2P programs without requiring a central
+registry or server.
+
+LICENSE
+=======
+
+IRK is distributed under the BSD license, the same license as Tcl.
+
+INSTALLATION
+============
+
+IRK is written in pure Tcl, which means it requires no extensions. It
+works with Tcl 8.0 and all later releases of Tcl.
+
+IRK has been tested on Solaris 7, Red Hat Linux 7.2, Windows 98,
+Windows 2000 and FreeBSD 4.2. It should work on any platform that is
+able to support Tcl 8.0 or later.
+
+Just drop this directory into one of the directories in Tcl's auto
+path. In your Tcl scripts, add the line:
+
+	package require irk
+
+and the IRK package should load into your Tcl interpreter.
+
+USAGE
+=====
+
+Read docs/usage.txt for a short overview of the commands provided by
+IRK.
+
+RECENT CHANGES AND CURRENT VERSION
+==================================
+
+Please read docs/changes.txt to see a list of all changes, ordered
+chronologically by release.
+
+REQUIREMENTS
+============
+
+IRK is event driven, and it requires the event loop to be active. If
+you want to use IRK from tclsh or other programs embedding a Tcl
+interpreter where the event loop is inactive, enter the event loop by
+adding the following line somewhere in your program:
+
+	vwait infinitely
+
+If you are using IRK in Wish, you do not need to take any action.
+
+TODO
+====
+
+Please docs/todo.txt for a list of planned enhancements.
+
+CREDITS AND CONTACT
+===================
+
+IRK benefited from examination of the Zircon and savIRC code written
+by Lindsay Marshall and Saverio Castellano, respectively. The future
+OO wrapper API is based on an idea suggested by Dave N. Welton.
+
+You can contact Jacob Levy, the author of IRK, at jyl@best.com. Please
+do drop a note if you use IRK, or if you have suggestions for
+enhancements, or if you run into problems.
+
+
Index: /code/branches/RacingBots_FS18/data/tcl/irk/docs/changes.txt
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/docs/changes.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/docs/changes.txt	(revision 11817)
@@ -0,0 +1,22 @@
+IRK 0.01, 02/07/2002
+    This is the first release of IRK.
+
+    What's implemented:
+
+    * Connection management.
+    * Integrated support for SOCKS5 to get through firewalls.
+    * Rudimentary flow control and queueing. Needs more work.
+    * Ping, MOTD, and informational messages management.
+    * Channel and nick management.
+    * Users on channels tracking.
+    * CTCP and all its subcommands.
+    * Special CTCP TCL protocol for communication between IRKs. All Tcl code
+      received from remote IRKs is run in a safe interpreter.
+    * Generalized persistent authorization and password management mechanism.
+    * Two usage examples:
+      + tontalou.tcl: a "bot" modelled after SmallSaints on DalNet. This
+        bot is unfinished.
+      + fortunebot.tcl: a "bot" that demonstrates grabbing a page from
+        the web and presenting its information in IRC.
+      Unfortunately no documentation is provided for these bots but they do
+      provide excellent examples on how you can use IRK to write Tcl "bots".
Index: /code/branches/RacingBots_FS18/data/tcl/irk/docs/todo.txt
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/docs/todo.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/docs/todo.txt	(revision 11817)
@@ -0,0 +1,10 @@
+TODO LIST FOR IRK
+=================
+
+* Implement DCC.
+* Implement object based command structure.
+* Implement event bindings modelled after the Tk Text widget.
+* Improve flow control.
+* Implement the last remaining RFC1439 protocol elements.
+* Implement proxy IRK commands for CTCP TCL safe interpreters.
+* Implement /mode commands.
Index: /code/branches/RacingBots_FS18/data/tcl/irk/docs/usage.txt
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/docs/usage.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/docs/usage.txt	(revision 11817)
@@ -0,0 +1,59 @@
+A VERY ABBREVIATED INTRO TO IRK
+===============================
+
+All IRK commands are found within the ::irk namespace.
+
+To open a connection with an IRC server, use:
+
+   set conn [irk::connect twisted panda1]
+
+This opens a connection to the server named 'twisted' (This is
+actually the server twisted.ma.us.dal.net) with the nickname
+'panda1'. It also saves the connection token in the variable 'conn'
+for later use.
+
+If you're behind a SOCKS5 firewall, you can configure IRK to use a
+SOCKS5 proxy:
+
+   irk::config -sockproxy <proxyhost> -sockport <port>
+
+Do this before attempting to open connections to servers outside the
+firewall. After this step all communication with remote IRC servers
+goes through the SOCKS5 proxy. At present it is not possible to have
+connections simultaneously to IRC servers inside and outside the firewall.
+
+You can open any number of connections to different servers at the
+same time, limited only by the resources available on the host
+machine. Most IRC servers disallow opening two or more connections
+from the same user to a single server.
+
+Next, to join a channel, type:
+
+   irk::join $conn #mycoolchannel
+
+You can join any number of channels (no limits except those imposed by
+the server).
+
+To talk to a channel, do:
+
+   irk::say $conn #mycoolchannel {Wow, I'm on IRC!}
+
+The message "Wow, I'm on IRC!" (without the quotes) is sent to the
+channel #mycoolchannel.
+
+You can also send a private message to a specific nickname, via:
+
+   irk::say $conn somenick {Hey, I'm talking to you}
+
+To leave a channel use irk::leave. To close a connection with a server
+use irk::close. Read lib/irkcommand.tcl for all the commands
+provided. Full documentation will be provided eventually.
+
+The above API is likely to be subsumed by a more OO API that will look
+something like this:
+
+   set conn [irk::connect twisted panda1]
+   set mychan [$conn join #mycoolchannel]
+   $mychan say {Wow, I'm on IRC!}
+   set somenick [$conn user somenick]
+   $somenick say {Hey, I'm taling to you}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/examples/fortunebot.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/examples/fortunebot.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/examples/fortunebot.tcl	(revision 11817)
@@ -0,0 +1,151 @@
+# fortunebot.tcl --
+#
+# Demo bot using the irc TCL client library. This is a VERY simple bot that
+# demonstrates some simple uses of the irc TCL library.
+#
+# The bot sits on any number of channels and networks. It periodically grabs
+# a fortune from a web site and sends the fortune with appropriate delays
+# between each line to all channels on all networks it is on.
+
+# Example use in Tcl:
+#
+# % source fortunebot.tcl
+# % set token [irc::connect ....]
+# % fortune::join $token #mychannel
+# % fortune::start 120
+#
+# What this does:
+# * Loads the bot, which in turn will load the IRC library and HTTP.
+# * Connect to IRC
+# * Send the bot to join #mychannel
+# * Start the bot, with 120 seconds delay. Now it'll do its actions every
+#   120 seconds.
+#
+# To stop the bot:
+#
+# % fortune::stop
+#
+# Make him leave a channel:
+#
+# % fortune::leave $token #mychannel
+
+package require irk
+package require http
+
+namespace eval fortune {
+    variable state
+
+    array set state {
+	linedelay		2000
+	fortuneurl		http://www.earth.com/fortune
+    }
+}
+
+# Bot control:
+
+proc ::fortune::start {{delay 60}} {
+    variable state
+
+    # Compute the delay in milliseconds:
+
+    set state(delay) [expr $delay * 1000]
+
+    # Schedule the bot to run each $delay milliseconds:
+
+    set state(after) [after $state(delay) [list ::fortune::doquote]]
+}
+
+proc ::fortune::stop {} {
+    variable state
+
+    # Stop the bot if its running:
+
+    if {[info exists state(after)]} {
+	after cancel $state(after)
+	unset state(after)
+    }
+}
+
+
+# This is the actual body of the bot:
+#
+# Grab a quote from a web page and post it to all channels we're on:
+
+proc ::fortune::doquote {} {
+    variable state
+
+    # Grab the quote. The command callback does all the work:
+
+    http::geturl $state(fortuneurl) -command ::fortune::httpdone
+
+    # Finally reschedule ourselves, after events are one-shots
+
+    set state(after) [after $state(delay) [list ::fortune::doquote]]
+}
+
+proc ::fortune::httpdone {http} {
+    variable state
+    upvar #0 $http response
+
+    # Scrape the fortune off of the page:
+
+    set fortune [grabfortune $response(body)]
+
+    # Discard the HTTP array:
+
+    unset response
+
+    # Check if the quote is too long. If it is then punt.
+
+    if {[llength $fortune] > 3} {
+	return
+    }
+
+    # Say this quote on all channels on all connections we're on:
+
+    foreach conn [irk::connections] {
+	tell $fortune $conn
+    }
+}
+
+# This procedure scrapes the quote off of an HTML page:
+
+proc ::fortune::grabfortune {body} {
+    set body [split $body "\n"]
+    set beg [lsearch $body <PRE>]
+    set end [lsearch $body </PRE>]
+    return [lrange $body [expr $beg+1] [expr $end-1]]
+}
+
+# This procedure sends the quote to all channels we want the bot to be on:
+
+proc ::fortune::tell {fort conn} {
+    variable state
+
+    # Send the fortune to each channel we're on:
+
+    foreach chan [irk::onchannels $conn] {
+	tellchan $fort $conn $chan
+    }
+}
+
+# Asynchronously send lines to the channel:
+
+proc ::fortune::tellchan {fort conn channel} {
+    variable state
+
+    # Check if we are still on the channel:
+
+    if {![irk::onchannel $conn $channel]} {
+	return
+    }
+
+    # OK we're still on this channel, so say the current line and schedule
+    # the next line for later:
+
+    if {[llength $fort] > 0} {
+	irk::say $conn $channel [lindex $fort 0]
+	after $state(linedelay) \
+	    [list ::fortune::tellchan [lrange $fort 1 end] $conn $channel]
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/examples/mysaint.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/examples/mysaint.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/examples/mysaint.tcl	(revision 11817)
@@ -0,0 +1,277 @@
+# mysaint.tcl
+#
+# I got the inspiration to write this bot from the SmallSaints
+# bot on DalNet and the request of some Malay friends to create a clone.
+#
+# The bot sits on a channel and simply counts words that each user says.
+
+package require irk
+
+namespace eval ::mysaint {
+
+    variable state
+
+    set state(thisdir) [file dir [info script]]
+    set state(words,save) [file join $state(thisdir) savedwords.dat]
+    set state(save,interval) 30000
+
+    # For each identified user, there are several entries in the state array:
+    #
+    # state($user,words)	How many words they have total.
+    # state($user,session)	How many words they said this time.
+    # state($user,password)	What's their password
+    # state($user,ident)	What's their ident
+    #
+    # We also keep a mapping from nicknames to users:
+    #
+    # state($nick,user)		What's the user mask associated with this
+    #				nick name
+
+    proc initialize {} {
+	variable state
+	variable thisdir
+
+	# Set up a timer to save words:
+
+	set state(saver) [after $state(save,interval) ::mysaint::save]
+
+	# See if we have a saved words file. If so, read it in.
+
+	if {[file exists $state(words,save)]} {
+	    uplevel #0 source $state(words,save)
+	}
+    }
+
+    proc userSays {token nick user comm dest rest} {
+	if {[string match "!*" [lindex $rest 0]]} {
+	    userSaysCommand $token $dest $nick $user \
+		    [lindex $rest 0] [lrange $rest 1 end]
+	} else {
+	    userSaysWords $nick $user [llength $rest]
+	}
+    }
+
+    proc userSaysWords {nick user n} {
+	variable state
+
+	set seconds [clock seconds]
+	if {![info exists state($user,session,time)]} {
+	    set state($user,session,time) [clock seconds]
+	}
+	set state($user,time) $seconds
+
+	if {![info exists state($user,session)]} {
+	    set state($user,session) $n
+	} else {
+	    incr state($user,session) $n
+	}
+	if {![info exists state($user,words)]} {
+	    set state($user,words) $n
+	} else {
+	    incr state($user,words) $n
+	}
+
+	set state($nick,user) $user
+    }
+
+    proc userSaysCommand {token dest nick user cmd rest} {
+	variable state
+
+	# Determine destination of any reply we're going to send:
+
+	if {![string compare $dest $state(nick)]} {
+	    set dest $nick
+	}
+
+	switch -exact $cmd {
+	    "!help"	{userAsksHelp $token $nick}
+	    "!time"	{userAsksTime $token $nick $user $rest $dest}
+	    "!heard"	{userAsksHeard $token $nick $user $rest $dest}
+	    "!words"	{userAsksWords $token $nick $user $rest $dest}
+	    "!donate"	{userDonates $token $nick $user $rest $dest}
+	    "!pass"	{::irk::pass $token mysaint $nick $user $rest}
+	    "!ident"	{::irk::id $token mysaint $nick $user $rest}
+	    "!newpass"	{::irk::np $token mysaint $nick $user $rest}
+	}
+    }
+
+    proc userAsksHelp {token nick} {
+	::irk::say $token $nick \
+		[list Hello $nick, the following commands are supported: ]
+	::irk::say $token $nick "!help ---- prints this message"
+	::irk::say $token $nick "!words --- how many words you have"
+	::irk::say $token $nick "!donate -- to donate words to someone"
+	after 2000 [list ::irk::say $token $nick \
+				"!heard --- when did some speak last time"]
+	after 2500 [list ::irk::say $token $nick \
+				"!time ---- when someone connected"]
+	after 5000 [list ::irk::say $token $nick \
+		    "Note: To donate you have to have a password"]
+	after 7500 [list ::irk::say $token $nick \
+		    "Note: You can get a password with !pass"]
+    }
+
+    proc userAsksWords {token nick user rest dest} {
+	variable state
+
+	set target [lindex $rest 0]
+	if {[string compare $target ""]} {
+	    if {[catch {set user $state($target,user)}]} {
+		set who "The unknown user $target"
+		set target "The unknown user $target"
+	    } else {
+		set who $user
+	    }
+	} else {
+	    set who ""
+	}
+	if {[string compare $who ""]} {
+	    if {[catch {set words $state($who,words)}]} {
+		set words 0
+	    }
+	    if {[catch {set session $state($who,session)}]} {
+		set session 0
+	    }
+	    set reply \
+		    "$nick, $target has $session words now, total $words words"
+	} else {
+	    if {[catch {set words $state($user,words)}]} {
+		set words 0
+	    }
+	    if {[catch {set session $state($user,session)}]} {
+		set session 0
+	    }
+	    set reply \
+		    "$nick, you have $session words now, $words total words"
+	}
+	::irk::say $token $dest $reply
+    }
+
+    proc userAsksHeard {token nick user rest dest} {
+	variable state
+
+	set target [lindex $rest 0]
+	if {[string compare $target ""]} {
+	    if {[catch {set user $state($target,user)}]} {
+		set answer "I haven't heard $target speak recently."
+	    } else {
+		set time $state($user,time)
+		set time [clock format $time]
+		set answer "I heard $target speak last at $time"
+	    }
+	} else {
+	    set answer "I'm talking to you just now, $nick"
+	}
+
+	::irk::say $token $dest $answer
+    }
+
+    proc userAsksTime {token nick user rest dest} {
+	variable state
+
+	set target [lindex $rest 0]
+	if {[string compare $target ""]} {
+	    if {[catch {set user $state($target,user)}]} {
+		set answer "I don't know when $target connected"
+	    } else {
+		if {[catch {set time $state($user,session,time)}]} {
+		    set answer "I don't know when $target connected"
+		} else {
+		    set time [clock format $time]
+		    set answer \
+			    "I first noticed $target at $time"
+		}
+	    }
+	} else {
+	    if {[catch {set user $state($nick,user)}]} {
+		set answer "$nick, I don't know when you connected"
+	    } else {
+		if {[catch {set time $state($user,session,time)}]} {
+		    set answer "$nick, I don't know when you connected"
+		} else {
+		    set time [clock format $time]
+		    set answer \
+			    "$nick, I first noticed you at $time"
+		}
+	    }
+	}
+
+	::irk::say $token $dest $answer
+    }
+
+    # Start the bot:
+
+    proc start {token} {
+	variable state
+
+	set state($token,token) $token
+
+	set symsrv $::irk::state($token,symsrv)
+	set state(nick) $::irk::state(-$symsrv,nick)
+	set nick $state(nick)
+
+	foreach chan [::irk::onchannels $token] {
+	    ::irk::setaction2 $token PRIVMSG $chan ::mysaint::userSays
+	}
+	::irk::setaction2 $token PRIVMSG $nick ::mysaint::userSays
+
+	# Set up a timer to save the words info.
+
+	if {![info exists state(saver)]} {
+	    initialize
+	}
+
+	return ""
+    }
+
+    # Stop the bot:
+
+    proc stop {} {
+	variable state
+
+	foreach conn [array names state *,token] {
+	    stopcon $state($conn)
+	}
+
+	after cancel $state(saver)
+	catch {unset state(saver)}
+
+	return ""
+    }
+    proc stopcon {token} {
+	variable state
+
+	if {[catch {set symsrv $::irk::state($token,symsrv)}]} {
+	    return
+	}
+	set nick $state(nick)
+
+	foreach chan [::irk::onchannels $token] {
+	    ::irk::remaction2 $token PRIVMSG $chan ::mysaint::userSays
+	}
+	::irk::remaction2 $token PRIVMSG $nick ::mysaint::userSays
+
+	return ""
+    }
+
+    # Save words to a disk file:
+
+    proc save {} {
+	variable state
+
+	puts "Saving words in $state(words,save)"
+
+	# First of all reschedule ourselves:
+
+	set state(saver) [after $state(save,interval) ::mysaint::save]
+
+	# Save the words:
+
+	set pt "*,words"
+	if {![catch {set fd [open $state(words,save) w]}]} {
+	    puts $fd "array set ::mysaint::state [list [array get state $pt]]"
+
+	    catch {close $fd}
+	}
+    }	
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/irk.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/irk.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/irk.tcl	(revision 11817)
@@ -0,0 +1,24 @@
+# IRK: A client library for IRC programming written in Tcl.
+
+# We need the socks package to get through firewalls:
+
+package require socks
+
+# We provide the IRK package:
+
+package provide irk 0.1
+
+set thisdir [file dir [info script]]
+
+# Source the rest of the package:
+
+source [file join $thisdir lib irkstate.tcl]
+source [file join $thisdir lib irkconnect.tcl]
+source [file join $thisdir lib irkdispatch.tcl]
+source [file join $thisdir lib irkreceive.tcl]
+source [file join $thisdir lib irkcommand.tcl]
+source [file join $thisdir lib irkflow.tcl]
+source [file join $thisdir lib irkutil.tcl]
+source [file join $thisdir lib irkctcptcl.tcl]
+source [file join $thisdir lib irkauth.tcl]
+source [file join $thisdir lib irkservers.tcl]
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkauth.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkauth.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkauth.tcl	(revision 11817)
@@ -0,0 +1,303 @@
+# irkauth.tcl:
+#
+# Various procedures that deal with user authentication:
+
+namespace eval ::irk {
+
+    # The AUTH module keeps information about each user and facility ($fac)
+    # in the state array:
+    #
+    # auth(auth,$fac,$user)		If set, then $user has authenticated
+    #					successfully for the facility $fac.
+    # auth(user,$fac,$user,pass)	The password for this $user and $fac.
+    # auth(user,$fac,$user,ident)	The ident token for this $user & $fac.
+    #
+    # auth(ident,$fac,$ident,pass)	The password for this $ident and $fac.
+    # auth(ident,$fac,$ident,user)	The user for this $ident and $fac.
+    #
+    # auth(identcounter,$fac)		The ident token counter for $fac. This
+    #					is incremented each time a new user
+    #					establishes themselves with $fac.
+
+    # This procedure can be called by programs using the IRK library
+    # when a user sends a password.
+
+    proc pass {token fac nick user rest} {
+	variable auth
+
+	if {[llength $rest] != 1} {
+	    # Incorrect syntax:
+
+	    set reply "$nick, syntax is !pass <yourpass> (one word, no spaces)"
+	} elseif {[info exists auth(user,$fac,$user,pass)]} {
+
+	    # If this user has already established a password,
+	    # check that they're giving the right password.
+
+	    if {[string compare $auth(user,$fac,$user,pass) \
+				[lindex $rest 0]]} {
+		set reply "$nick, sorry, wrong password!"
+	    } else {
+		set reply "$nick, thanks for entering your password!"
+		set auth(auth,$fac,$user) 1
+	    }
+	} else {
+
+	    # This is the first time we're seeing this user. Accept
+	    # their password and send them an ident token. They can
+	    # use the ident token to reestablish themselves when their
+	    # user mask changes significantly.
+
+	    if {![info exists auth(identcounter,$fac)]} {
+		set auth(identcounter,$fac) 0
+	    }
+	    set ident $auth(identcounter,$fac)
+	    incr auth(identcounter,$fac)
+
+	    set auth(ident,$fac,$ident,user) $user
+	    set auth(ident,$fac,$ident,pass) [lindex $rest 0]
+
+	    set auth(user,$fac,$user,ident) $ident
+	    set auth(user,$fac,$user,pass) [lindex $rest 0]
+
+	    # Save the changes
+
+	    saveauth
+
+	    # Save them a step and also authorize them:
+
+	    set auth(ident,$fac,$user) 1
+
+	    set reply [list \
+	        $nick, your password is [lindex $rest 0]. Your ident is \
+	        $ident, write it down, you will need it later to \
+		reidentify yourself if your user mask changes. \
+		You user mask is currently $user. You are now authorised \
+		to use $fac.]
+	}
+
+	# Tell them what happened:
+
+	::irk::say $token $nick $reply
+
+	return ""
+    }
+
+    # This procedure can be called by programs when the user attempts to
+    # reestablish themselves with the existing ident and password.
+
+    proc id {token fac nick user rest} {
+	variable auth
+
+	set len [llength $rest]
+	set reply "Wrong syntax. Call !ident or !ident <ident> <pass>"
+
+	if {$len == 0} {
+
+	    # Calling ident with zero arguments. The user is trying to
+	    # retrieve their ident. Give it to them only if they did
+	    # identify successfully with the correct password.
+
+	    if {![info exists auth(user,$fac,$user,pass)]} {
+		set reply "$nick, first set a password"
+	    } elseif {[info exists auth(auth,$fac,$user)]} {
+		set reply \
+		    "$nick, your ident is $auth(user,$fac,$user,ident)"
+	    } else {
+		set reply \
+		   "$nick, identify with password before getting your ident!"
+	    }
+	} elseif {$len == 2} {
+
+	    # Calling ident with two arguments. The user is trying to
+	    # establish a new value for $user to associate with this
+	    # ident and password. If $auth($ident,pass) is the password
+	    # she gave, then they're the rightfull owner of the ident and
+	    # so we now recognize the new $user mask.
+
+	    set ident [lindex $rest 0]
+	    set pass [lindex $rest 1]
+
+	    if {[info exists auth(ident,$fac,$ident,pass)]} {
+		if {![string compare $auth(ident,$fac,$ident,pass) $pass]} {
+
+		    # Identify the old user mask they were using:
+
+		    set olduser $auth(ident,$fac,$ident,user)
+
+		    # Clean up the state associated with the old mask:
+
+		    array unset auth user,$fac,$olduser,*
+		    catch {unset auth(ident,$face,$olduser)}
+
+		    # Link up the new state:
+
+		    set auth(ident,$fac,$ident,user) $user
+
+		    set auth(user,$fac,$user,ident) $ident
+		    set auth(user,$fac,$user,pass) $pass
+
+		    # Save the changes
+
+		    saveauth
+
+		    # Save them a step and also treat them as authenticated:
+
+		    set auth(ident,$fac,$user) 1
+
+		    set reply \
+			    "OK, $nick, I'm now recognising you as $user.\
+			     You are now authorised to use $fac."
+		} else {
+		    set reply "$nick, sorry, wrong ident or password"
+		}
+	    } else {
+		set reply "$nick, sorry, wrong ident or password"
+	    }
+	}
+
+	# Tell them what happened:
+
+	::irk::say $token $nick $reply
+
+	return ""
+    }
+
+    # This procedure can be invoked by a program when a user tries to
+    # change her password.
+
+    proc np {token fac nick user rest} {
+	variable auth
+
+	set reply "Wrong syntax. Call !newpass <oldpass> <newpass>"
+
+	if {[llength $rest] == 2} {
+	    set opw [lindex $rest 0]
+	    set npw [lindex $rest 1]
+
+	    if {![info exists auth(user,$fac,$user,pass)]} {
+		# Unknown $user, probably their user mask changed. Help
+		# them reestablish the connection.
+
+		set reply \
+		   [list $nick, I don't have you in my database. Perhaps \
+			 your user mask changed drastically. If so, please \
+			 reestablish your user mask by using !ident <ident> \
+			 <oldpass>.]
+	    } elseif {[string compare $auth(user,$fac,$user,pass) $opw]} {
+		# Wrong old password!
+
+		set reply "$nick, sorry, wrong old password!"
+	    } else {
+		# Their user mask matches and they gave the correct old
+		# password, so we accept their new password:
+
+		set ident $auth(user,$fac,$user,ident)
+
+		set auth(ident,$fac,$ident,pass) $npw
+		set auth(user,$fac,$user,pass) $npw
+
+		# Save the changes:
+
+		saveauth
+
+		# Save them a step by also recording that they
+		# authenticated:
+
+		set auth(auth,$fac,$user) 1
+
+		set reply "OK, $nick, your new password is now $npw"
+	    }
+	}
+
+	# Tell them what happened:
+
+	::irk::say $token $nick $reply
+
+	return ""
+    }
+
+    # This procedure can be called by programs when the user wants to
+    # "log out" or lose her authentication with a given facility:
+
+    proc logout {token fac nick user rest} {
+	variable auth
+
+	set reply "You were not logged into $fac. Now you certainly aren't."
+
+	if {[info exists auth(auth,$fac,$user)]} {
+	    unset auth(auth,$fac,$user)
+
+	    set reply \
+		[list $nick, you logged out successfully from $fac. Thank you \
+		      for using $fac.]
+	}
+
+	# Tell them what happened:
+
+	::irk::say $token $nick $reply
+
+	return ""
+    }
+
+    # Is the user authenticated with the given facility?
+
+    proc userauthenticated {fac user} {
+	variable auth
+
+	# If auth(auth,$fac,$user) exists, then she is authenticated.
+
+	if {[info exists auth(auth,$fac,$user)]} {
+	    return 1
+	}
+	return 0
+    }
+
+    # This procedure automatically saves the authorization database:
+
+    proc saveauth {} {
+	variable state
+	variable auth
+
+	puts "Saving!"
+
+	# Define the patterns to save:
+
+	set p1 "identcounter,*"
+	set p2 "user,*"
+	set p3 "ident,*"
+
+	# Try to open the save file:
+
+	if {[info exists state(auth,save,file)]} {
+	    if {![catch {set fd [open $state(auth,save,file) w]}]} {
+		puts $fd "array set ::irk::auth [list [array get auth $p1]]"
+		puts $fd "array set ::irk::auth [list [array get auth $p2]]"
+		puts $fd "array set ::irk::auth [list [array get auth $p3]]"
+
+		catch {close $fd}
+	    }
+	}
+    }
+
+    # This procedure restores the authorization database:
+
+    proc restoreauth {} {
+	variable state
+
+	if {[info exists state(auth,save,file)]} {
+	    catch {uplevel #0 source $state(auth,save,file)}
+	}
+	set state(auth,restored) 1
+    }
+
+    # If this is the first time we're loading the IRK package, then
+    # restore the authorization database. Otherwise we'd be overwriting
+    # a potentially unsaved state.
+
+    variable state
+
+    if {![info exists state(auth,restored)]} {
+	restoreauth
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkcommand.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkcommand.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkcommand.tcl	(revision 11817)
@@ -0,0 +1,420 @@
+# irkcommand.tcl:
+#
+# Various commands that can be invoked by the user of the IRK library:
+
+namespace eval irk {
+
+    # Say something to a user or to a channel
+
+    proc say {token chan saying} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	if {![string compare "" $saying]} {
+	    return
+	}
+	sendit $sock "PRIVMSG $chan :[string trim $saying]"
+    }
+
+    # Send a NOTICE to a user or a channel
+
+    proc notice {token chan args} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	sendit $sock "NOTICE $chan :$args"
+    }
+
+    # Send a raw command to the server:
+
+    proc send {token args} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	puts $sock $args
+    }
+
+    # Change your NICK
+
+    proc nick {token {newnick ""}} {
+	variable state
+
+	if {![string compare "" $newnick]} {
+	    return $state($token,nick)
+	}
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	puts $sock "NICK $newnick"
+    }
+
+    # Join a channel
+
+    proc join {token chans {keys ""}} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	puts $sock "JOIN $chans $keys"
+    }
+
+    # Leave a channel
+
+    proc leave {token chans {partmsg ""}} {
+	variable state
+
+	if {![string compare $partmsg ""]} {
+	    if {[info exists state(partmsg)]} {
+		set partmsg $state(partmsg)
+	    }
+	}
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	puts $sock "PART $chans $partmsg"
+    }
+
+    # Return a list of all connections that are open:
+
+    proc connections {} {
+	variable state
+
+	if {![info exists state(connections)]} {
+	    return {}
+	}
+	return $state(connections)
+    }
+
+    # Return a list of channels we're on in a give connection:
+
+    proc onchannels {token} {
+	variable state
+
+	if {![info exists state($token,channels)]} {
+	    return {}
+	}
+	return $state($token,channels)
+    }
+
+    # Returns 1 if we are on the given channel.
+
+    proc onchannel {token channel} {
+	variable state
+
+	if {![info exists state($token,channels)]} {
+	    return 0
+	}
+
+	set idx [lsearch $state($token,channels) $channel]
+	if {$idx == -1} {
+	    return 0
+	}
+	return 1
+    }
+
+    # Return a list of users on a given channel (we must be on that channel).
+
+    proc whoison {token chan} {
+	variable state
+
+	if {![info exists state($token,$chan,NAMES)]} {
+	    return {}
+	}
+	return $state($token,$chan,NAMES)
+    }
+
+    # Ping a server
+
+    proc ping {token} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	set state($token,PINGSTART) [clock clicks -millis]
+	puts $sock "PING $state($token,host)"
+    }
+
+    # Quit this connection
+
+    proc quit {token} {
+	disconnect $token
+    }
+
+    # Query information about someone
+
+    proc whois {token nick} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	puts $sock "WHOIS $nick"
+    }
+
+    # Set an away message
+
+    proc away {token args} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	puts $sock "AWAY :$args"
+    }
+
+    # This procedure lets the client do CTCP actions:
+
+    proc ctcp {token target action args} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	sendit $sock "PRIVMSG $target :\001$action $args\001"
+    }
+
+    # This command implements the TCL CTCP protocol:
+
+    proc tcl {token target args} {
+	variable state
+
+	# Send it to the channel:
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid irc connection"
+	}
+	sendit $sock "PRIVMSG $target :\001TCL $args\001"
+
+	# Apply it locally:
+
+	if {[info exists state($token,channel,ctcp,TCL,LOCAL)]} {
+	    $state($token,channel,ctcp,TCL,LOCAL) \
+		    $token $state($token,nick) $state($token,user) \
+		    PRIVMSG $target TCL $args
+	}
+    }
+
+    # These procedures add and remove action handlers:
+
+    # These procedures add actions that will be called when the user
+    # with the given nick causes the supplied comm(and) to be executed
+    # on the given dest(ination). This is the most specific form of action.
+
+    proc addaction3 {token nick comm dest cmd} {
+	variable state
+
+	if {![info exists state($token,$nick,$comm,$dest)]} {
+	    set state($token,$nick,$comm,$dest) [list $cmd]
+	} else {
+	    lappend state($token,$nick,$comm,$dest) $cmd
+	}
+    }
+
+    proc setaction3 {token nick comm dest cmd} {
+	variable state
+
+	set state($token,$nick,$comm,$dest) [list $cmd]
+    }
+
+    # This procedure removes an action set by either of the above two
+    # procedures.
+
+    proc remaction3 {token nick comm dest cmd} {
+	variable state
+
+	if {![info exists state($token,$nick,$comm,$dest)]} {
+	    return
+	}
+	set cmds $state($token,$nick,$comm,$dest)
+	set idx [lsearch $cmds $cmd]
+	if {$idx == -1} {
+	    return
+	}
+	set state($token,$nick,$comm,$dest) [lreplace $cmds $idx $idx]
+	if {![string compare "" $state($token,$nick,$comm,$dest)]} {
+	    unset state($token,$nick,$comm,$dest)
+	}
+    }
+
+    # These procedures add actions that will be called when the
+    # specific comm(and) is caused for the given dest(ination).
+
+    proc addaction2 {token comm dest cmd} {
+	variable state
+
+	if {![info exists state($token,$comm,$dest)]} {
+	    set state($token,$comm,$dest) [list $cmd]
+	} else {
+	    lappend state($token,$comm,$dest) $cmd
+	}
+    }
+
+    proc setaction2 {token comm dest cmd} {
+	variable state
+
+	set state($token,$comm,$dest) [list $cmd]
+    }
+
+    # This procedure removes an action set by either of the above two
+    # procedures.
+
+    proc remaction2 {token comm dest cmd} {
+	variable state
+
+	if {![info exists state($token,$comm,$dest)]} {
+	    return
+	}
+	set cmds $state($token,$comm,$dest)
+	set idx [lsearch $cmds $cmd]
+	if {$idx == -1} {
+	    return
+	}
+	set state($token,$comm,$dest) [lreplace $cmds $idx $idx]
+	if {![string compare "" $state($token,$comm,$dest)]} {
+	    unset state($token,$comm,$dest)
+	}
+    }
+
+    # These procedures add actions that will be called when the
+    # specific comm(and) is caused any dest(ination).
+
+    proc addaction1 {token comm cmd} {
+	variable state
+
+	if {![info exists state($token,$comm)]} {
+	    set state($token,$comm) [list $cmd]
+	} else {
+	    lappend state($token,$comm) $cmd
+	}
+    }
+
+    proc setaction1 {token comm cmd} {
+	variable state
+
+	set state($token,$comm) [list $cmd]
+    }
+
+    # This procedure removes an action set by either of the above two
+    # procedures.
+
+    proc remaction1 {token comm cmd} {
+	variable state
+
+	if {![info exists state($token,$comm)]} {
+	    return
+	}
+	set cmds $state($token,$comm)
+	set idx [lsearch $cmds $cmd]
+	if {$idx == -1} {
+	    return
+	}
+	set state($token,$comm) [lreplace $cmds $idx $idx]
+	if {![string compare "" $state($token,$comm)]} {
+	    unset state($token,$comm)
+	}
+    }
+
+    # These procedures add global actions that will be called
+    # when the specific comm(and) is caused on any dest(ination) and
+    # any irc connection. These are the lowest priority commands.
+
+    proc addactionglobal {comm cmd} {
+	variable state
+
+	if {![info exists state(cmd,$comm)]} {
+	    set state(cmd,$comm) [list $cmd]
+	} else {
+	    lappend state(cmd,$comm) $cmd
+	}
+    }
+
+    proc setactionglobal {comm cmd} {
+	variable state
+
+	set state(cmd,$comm) [list $cmd]
+    }
+
+    # This procedure removes an action set by either of the above two
+    # procedures.
+
+    proc remactionglobal {comm cmd} {
+	variable state
+
+	if {![info exists state(cmd,$comm)]} {
+	    return
+	}
+	set cmds $state(cmd,$comm)
+	set idx [lsearch $cmds $cmd]
+	if {$idx == -1} {
+	    return
+	}
+	set state(cmd,$comm) [lreplace $cmds $idx $idx]
+	if {![string compare "" $state(cmd,$comm)]} {
+	    unset state(cmd,$comm)
+	}
+    }
+
+    # This procedure manages configuration information for IRC:
+
+    proc config {args} {
+	if {$args == {}} {
+	    return [collectConfig]
+	}
+
+	if {[llength $args] == 1} {
+	    return [queryConfig [lindex $args 0]]
+	}
+
+	if {[expr [llength $args] % 2] != 0} {
+	    error "incorrect number of argument, must be multiple of 2"
+	}
+
+	setConfig $args
+    }
+
+    # Helper procedure to return a list with all important user settable
+    # configuration information.
+
+    proc collectConfig {} {
+	variable state
+
+	set config {}
+
+	foreach name [array names state "-*"] {
+	    lappend config [list $name $state($name)]
+	}
+	return $config
+    }
+
+    # Helper procedure to return the value of one option.
+
+    proc queryConfig {option} {
+	variable state
+
+	if {![info exists state($option)]} {
+	    return {}
+	}
+	return $state($option)
+    }
+
+    # Helper procedure to modify the configuration of a set of options.
+
+    proc setConfig {theargs} {
+	variable state
+
+	foreach {opt val} $theargs {
+	    if {![string match "-*" $opt]} {
+		continue
+	    }
+	    set state($opt) $val
+	}
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkconnect.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkconnect.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkconnect.tcl	(revision 11817)
@@ -0,0 +1,239 @@
+# irkconnect.tcl:
+#
+# This file provides the IRK commands to connect to remote servers
+# as well as some attendant utility procedures:
+
+namespace eval ::irk {
+
+    # The "connect" procedure returns a token
+    # for the connection to this server.
+    #
+    # symsrv		The symbolic name of the server to connect to.
+    # nick		The nick name to use.
+    # user		The user name to use.
+    # pass		The password to use. 
+    # disp		The command dispatcher expression to use.
+
+    proc connect {{symsrv ""} {nick ""} {user ""} {pass ""} {disp ""}} {
+	variable state
+
+	# Auto initialize the list of connections. We do this so that
+	# the list is not reset each time the irk.tcl file is sourced.
+
+	if {![info exists state(connections)]} {
+	    set state(connections) {}
+	}
+
+	# Try to convert the symbolic server name to a
+	# server description. This may throw an error,
+	# we propagate it.
+
+	set servdesc [locate $symsrv]
+
+	# If the nickname is not specified, there must be
+	# a nick setting in the state array; use that
+
+	if {![string compare $nick ""]} {
+	    if {![info exists state(-$symsrv,nick)]} {
+		error "No nick given or set in global state"
+	    }
+	    set nick $state(-$symsrv,nick)
+	}
+
+	# If a global nick is not set, save this nick for use
+	# as a global nick.
+
+	if {![info exists state(-$symsrv,nick)]} {
+	    set state(-$symsrv,nick) $nick
+	}
+
+	# If user is not supplied, see if there is a global
+	# user registered in the IRK package state. If not,
+	# invent a user.
+
+	if {![string compare $user ""]} {
+	    if {[info exists state(-$symsrv,user)]} {
+		set user $state(-$symsrv,user)
+	    } else {
+		set user $nick
+		set state(-$symsrv,user) $user
+	    }
+	}
+
+	# If a password is not supplied, see if there is a global
+	# one registered. If so, use that. Otherwise, do not
+	# use a password.
+
+	if {![string compare $pass ""]} {
+	    if {[info exists state(-$symsrv,pass)]} {
+		set pass $state(-$symsrv,pass)
+	    }
+	}
+
+	# If a dispatcher expression is not supplied, there must be a
+	# global dispatcher expression in the state array, and use that.
+
+	if {![string compare $disp ""]} {
+	    if {![info exists state(dispatcher)]} {
+		error "ERROR: o dispatch given or found in global state"
+	    }
+	    set disp $state(dispatcher)
+	}
+
+	# Try to connect to the given server.
+
+	set h [lindex $servdesc 0]
+	set p [randselect [lindex $servdesc 1]]
+
+	set s [opensocket $h $p]
+
+	# The socket is line buffered and consumed by the
+	# supplied consumer
+
+	fconfigure $s -translation auto -buffering line
+	fileevent $s readable [list ::irk::consumer $s]
+
+
+	# Identify ourselves to the IRK server: If a password is given
+	# send that first. Then send the nick name and user name.
+
+	if {[string compare $pass ""]} {
+	    puts $s "PASS $pass"
+	}
+
+	puts $s "NICK $nick"
+	puts $s "USER $user $h $h :$user"
+
+	# Make a connection token:
+
+	set contok [contok $s $symsrv]
+
+	# Save the state for this new connection
+
+	lappend state(connections) $contok
+
+	set state($contok,port) $p
+	set state($contok,host) $h
+	set state($contok,symsrv) $symsrv
+	set state($contok,nick) $nick
+	set state($contok,user) $user
+	set state($contok,pass) $pass
+	set state($contok,disp) $disp
+
+	# Set up some default behavior for the connection:
+
+	setupDefaultActions $contok $nick
+
+	# Collect information about who the server thinks we are
+
+	puts $s "WHOIS $nick"
+
+	# Finally return the token for this connection:
+
+	return $contok
+    }
+
+    # This procedure makes an easy to remember connection token. It takes
+    # the symbolic server's name and appends _<n> to it, where n is an
+    # integer starting at 0 and monotonically increasing for every new
+    # connection to that server.
+    #
+    # Once it figures out what the connection token is going to be,
+    # it associates it with the given socket so it can be used.
+
+    proc contok {sock symsrv} {
+	variable state
+
+	# Compute the symbolic name for this connection:
+
+	if {![info exists state($symsrv,counter)]} {
+	    set state($symsrv,counter) 0
+	}
+	set contok ${symsrv}_$state($symsrv,counter)
+	incr state($symsrv,counter)
+
+	# Associate the symbolic name with the socket:
+
+	set state($contok,socket) $sock
+	set state($sock,contok) $contok
+
+	return $contok
+    }
+
+    # The locate procedure tries to convert the symbolic name for
+    # a connection to a server/port specification.
+
+    proc locate {s} {
+	variable symsrv
+	variable state
+
+	# If the caller specified "" as the name of the server, select
+	# a random one from the list of known servers.
+
+	if {![string compare $s ""]} {
+	    set s [randselect $state(servers)]
+	}
+
+	# Now see if the requested server exists:
+
+	if {![info exists symsrv($s)]} {
+	    error \
+		"Could not find a match for symbolic IRK server name \"$s\""
+	}
+
+	# It does, return the server specification:
+
+	return $symsrv($s)
+    }
+
+    # opensocket connects to the requested server and port, either
+    # directly or through a SOCKS5 proxy.
+
+    proc opensocket {server port} {
+	variable state
+
+	if {[info exists state(-socksproxy)] \
+		&& [info exists state(-socksport)]} {
+	    set sock [socket $state(-socksproxy) $state(-socksport)]
+	    return [::socks::init $sock $server $port]
+	}
+
+	return [socket $server $port]
+    }
+
+    # The disconnect procedure disconnects from a given connection
+    # identified by its symbolic name, and cleans up state associated
+    # with the connection.
+
+    proc disconnect {contok} {
+	variable state
+
+	if {[catch {set s $state($contok,socket)} err]} {
+	    error "ERROR: $contok: No such IRC connection"
+	}
+
+	# Send a QUIT message.
+
+	if {[info exists state(quitmsg)]} {
+	    set q ":$state($contok,nick) $state(quitmsg)"
+	} else {
+	    set q ":$state($contok,nick) quit"
+	}
+	puts $s "QUIT $q"
+
+	# Try to close the connection with the server.
+
+	catch {close $s}
+
+	# And clean up all state associated with this connection:
+
+	array unset state $contok,*
+	
+	# Remove this connection from the list of active connections:
+
+	set i [lsearch $state(connections) $s]
+	set state(connections) [lreplace $state(connections) $i $i]
+
+	return ""
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkctcptcl.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkctcptcl.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkctcptcl.tcl	(revision 11817)
@@ -0,0 +1,45 @@
+# irkctcptcl.tcl:
+#
+# This file implements the IRK CTCP TCL protocol:
+
+namespace eval ::irk {
+
+    # This procedure sets up a safe interpreter for the channel in which
+    # the CTCP TCL action occurs:
+
+    proc setupInterp {token chan} {
+	variable state
+
+	if {![info exists state($token,$chan,interp)]} {
+	    catch {interp delete ${token}${chan}}
+	    set state($token,$chan,interp) [safe::interpCreate ${token}${chan}]
+	    safe::loadTk $state($token,$chan,interp)
+	}
+	if {![interp exists ${token}${chan}]} {
+	    set state($token,$chan,interp) [safe::interpCreate ${token}${chan}]
+	    safe::loadTk $state($token,$chan,interp)
+	}
+    }
+
+    # This procedure dispatches the Tcl command embedded within the
+    # CTCP TCL action to the associated interpreter:
+
+    proc RECV,CTCP,TCL {token nick user comm dest action rest} {
+	variable state
+
+	puts stderr "Tcl command is: $rest [llength $rest]"
+	setupInterp $token $dest
+	interp eval $state($token,$dest,interp) [::join $rest]
+    }
+
+    # This procedure dispatches the Tcl command embedded within the
+    # CTCP TCL action for local execution on the issuer's side:
+
+    proc RECV,CTCP,TCL,LOCAL {token nick user comm dest action rest} {
+	variable state
+
+	puts stderr "Tcl command is: $rest [llength $rest]"
+	setupInterp $token $dest
+	interp eval $state($token,$dest,interp) $rest
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkdispatch.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkdispatch.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkdispatch.tcl	(revision 11817)
@@ -0,0 +1,248 @@
+# irkdispatch.tcl:
+#
+# Based on the input received from the server, dispatch control to various
+# command procedures.
+
+namespace eval ::irk {
+
+    # This procedure sets up the default actions for a connection:
+
+    proc setupDefaultActions {s nick} {
+	variable state
+
+	# Catch any unexpected PRIVMSG actions:
+
+	set state($s,PRIVMSG,$nick)	$state(PRIVMSG,unsolicited)
+
+	# Set up CTCP global actions:
+
+	set state($s,cmd,ctcp,PING)	::irk::RECV,CTCP,PING
+	set state($s,cmd,ctcp,TIME)	::irk::RECV,CTCP,TIME
+	set state($s,cmd,ctcp,VERSION)	::irk::RECV,CTCP,VERSION
+	set state($s,cmd,ctcp,USERINFO) \
+					::irk::RECV,CTCP,USERINFO
+
+	# Set up CTCP channel specific actions:
+
+	set state($s,channel,ctcp,ACTION) \
+					::irk::RECV,CTCP,ACTION
+
+	# Set up the CTCP TCL protocol:
+
+	set state($s,channel,ctcp,TCL)	::irk::RECV,CTCP,TCL
+	set state($s,channel,ctcp,TCL,LOCAL) \
+					::irk::RECV,CTCP,TCL,LOCAL
+
+	# Deal with CTCP commands we do not understand:
+
+	set state($s,cmd,ctcp,error) 	::irk::RECV,CTCP,ERROR
+	set state($s,channel,ctcp,error) \
+					::irk::RECV,CTCP,ERROR
+    }
+
+    # The consumer procedure consumes input received from
+    # a connection. It calls the dispatcher for the given connection
+    # with each input line.
+
+    proc consumer {s} {
+	variable state
+
+	if {[eof $s]} {
+	    disconnect $s
+	} else {
+	    set l [gets $s]
+	    if {[info exists state($s,trace)]} {
+		$state($s,trace) $l
+	    }
+	    if {[string compare $l ""]} {
+		dissect $state($s,contok) $l
+	    }
+	}
+    }
+
+    # This procedure dissects the input into its parts:
+
+    proc dissect {token line} {
+	variable state
+
+	# Make a list out of the line:
+
+	set line [split $line " "]
+
+	# Split first token into nickname and user mask:
+
+	set nandu [split [lindex $line 0] \!]
+
+	# Call dispatcher for this connection:
+
+	$state($token,disp) \
+		$token \
+		[lindex $nandu 0] \
+		[lindex $nandu 1] \
+		[lindex $line 1] \
+		[lindex $line 2] \
+		[lrange $line 3 end]
+    }
+
+    # This procedure is the default command dispatcher:
+    
+    proc defaultDispatcher {token nick user comm dest rest} {
+	variable state
+
+	# Check if the nick starts with ':'. If not then this is
+	# a special action, handled by the built in actions.
+
+	if {![string match ":*" $nick]} {
+	    return [specialAction $token $nick $user $comm $dest $rest]
+	}
+
+	# Trim off the leading ':' on the $nick, if present.
+
+	if {[string match ":*" $nick]} {
+	    set nick [string range $nick 1 end]
+	}
+
+	# If a ':' is present in the $dest, trim that off too.
+
+	if {[string match ":*" $dest]} {
+	    set dest [string range $dest 1 end]
+	}
+
+	# If a ':' is present in the $rest, trim that off too.
+
+	set firstrest [lindex $rest 0]
+	if {[string match ":*" $firstrest]} {
+	    set firstrest [string range $firstrest 1 end]
+	    set rest [lreplace $rest 0 0 $firstrest]
+	}
+
+	# Clean up the payload:
+
+	set rest [split [string trim [eval concat $rest]] " "]
+
+	# Now try to dispatch to specific handlers.
+	#
+	# First see if there is a handler for the specific combination
+	# of $token, $nick, $comm and $dest. This is used for PRIVMSG.
+
+	if {[info exists state($token,$nick,$comm,$dest)]} {
+	    foreach cmd $state($token,$nick,$comm,$dest) {
+		if {[catch {set res [$cmd $token $nick $user \
+					  $comm $dest $rest]} err]} {
+		    if {[info exists state(errorhandler)]} {
+			$state(errorhandler) $err $token $comm $dest
+		    }
+		    return
+		}
+
+		# If this handler said to go on to a more general handler,
+		# then don't return. Otherwise return.
+
+		if {[string compare $res pass]} {
+		    return
+		}
+	    }
+	}
+
+	# If there's a handler for $token, $comm and $dest, use that.
+
+	if {[info exists state($token,$comm,$dest)]} {
+	    foreach cmd $state($token,$comm,$dest) {
+		if {[catch {set res [$cmd $token $nick $user \
+					  $comm $dest $rest]} err]} {
+		    if {[info exists state(errorhandler)]} {
+			$state(errorhandler) $err $token $comm $dest
+		    }
+		    return
+		}
+
+		# If this handler said to go on to a more general handler,
+		# then don't return. Otherwise return.
+
+		if {[string compare $res pass]} {
+		    return
+		}
+	    }
+	}
+
+	# See if there's a handler for $token and $comm. If so use that.
+
+	if {[info exists state($token,$comm)]} {
+	    foreach cmd $state($token,$comm) {
+		if {[catch {set res [$cmd $token $nick $user \
+					  $comm $dest $rest]} err]} {
+		    if {[info exists state(errorhandler)]} {
+			$state(errorhandler) $err $token $comm $dest
+		    }
+		    return
+		}
+
+		# If this handler said to go on to a more general handler,
+		# then don't return. Otherwise return.
+
+		if {[string compare $res pass]} {
+		    return
+		}
+	    }
+	}
+
+	# See if there's a global handler for the command. All the
+	# default handlers are defined here.
+
+	if {[info exists state(cmd,$comm)]} {
+	    foreach cmd $state(cmd,$comm) {
+		if {[catch {set res [$cmd $token $nick $user \
+					  $comm $dest $rest]} err]} {
+		    if {[info exists state(errorhandler)]} {
+			$state(errorhandler) $err $token $comm $dest
+		    }
+		    return
+		}
+
+		# If this handler said to go on to a more general handler,
+		# then don't return. Otherwise return.
+
+		if {[string compare $res pass]} {
+		    return
+		}
+	    }
+	}
+
+	# If all of the above fail, send this input to the default
+	# action handler:
+
+	if {[catch {set res [$state(action) \
+				$token $nick $user \
+				$comm $dest $rest]} err]} {
+	    if {[info exists state(errorhandler)]} {
+		$state(errorhandler) $err $token $comm $dest
+	    }
+	    return
+	}
+    }
+
+    # This procedure deals with special actions (built in, cannot
+    # easily be modified by users). I use this to e.g deal with
+    # PING, NOTICE, ERROR etc., automatically.
+
+    proc specialAction {token nick user comm dest rest} {
+	variable state
+
+	# The nick is the special action selector:
+
+	$state(special,$nick) $token $nick $user $comm $dest $rest
+    }
+
+    # This is the default error handler:
+
+    proc echoerror {args} {
+	puts stderr $args
+    }
+
+    # This procedure provides a default tracing facility (it just prints
+    # the lines received to stderr):
+
+    proc trace {args} {
+	puts stderr "Received: $args"
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkflow.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkflow.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkflow.tcl	(revision 11817)
@@ -0,0 +1,102 @@
+# irkflow.tcl
+#
+# Simple flow control management so as to avoid flooding.
+
+namespace eval ::irk {
+
+    # For each combination of destination+connection, we keep three items:
+    # 
+    # flowctl($dest,$conn,after)	The "after" token for the next time
+    #					we send anything to this destination.
+    # flowctl($dest,$conn,queue)	A list of items to send to this
+    #					destination on this connection.
+    # flowctl($dest,$conn,lastsend)	The time we last sent to this
+    #					destination on this connection.
+    #
+    # NOTE: We do not limit the length of each item to send. This
+    # would lead to extremely hard to diagnose bugs due to commands
+    # (e.g. ctcp's) getting cut up into chunks.
+
+    variable flowctl
+
+    # The following setting controls how often (in msecs) we can send
+    # to a given connection. It should not be modified by user code or
+    # flooding may occur.
+
+    set flowctl(floodlimit) 1500
+
+    # This procedure sends an item to a specific destination+connection.
+    # If possible, the item is sent right away. Otherwise it is enqueued
+    # for later sending.
+
+    proc sendit {conn item} {
+	variable flowctl
+
+	# If this connection has a backlog, append the new
+	# items. Otherwise, check if the previous send was
+	# less than flowctl(floodlimit) msecs ago. If so, enqueue
+	# it for later sending. Otherwise send it now and record
+	# the time we sent this item.
+
+	if {[info exists flowctl($conn,after)]} {
+	    lappend flowctl($conn,queue) $item
+	} else {
+	    if {[catch {set lastsend $flowctl($conn,lastsend)}]} {
+		set lastsend 0
+	    }
+	    set now [clock clicks -milliseconds]
+	    set lim $flowctl(floodlimit)
+	    if {[expr $now - $lastsend] < $lim} {
+		lappend flowctl($conn,queue) $item
+		set wait [expr ($lim - ($now - $lastsend))]
+		set flowctl($conn,after) \
+			[after $wait [list ::irk::sendlater $conn]]
+	    } else {
+		set flowctl($conn,lastsend) $now
+		puts $conn $item
+	    }
+	}
+
+	return ""
+    }
+
+    # This procedure does the sending when flow control for a connection
+    # is activated.
+
+    proc sendlater {conn} {
+	variable flowctl
+
+	# First of all clear the after entry.
+
+	unset flowctl($conn,after)
+
+	# Grab the first item on the queue:
+
+	if {[info exists flowctl($conn,queue)]} {
+	    set items $flowctl($conn,queue)
+	    if {[string compare $items ""]} {
+		set item [lindex $items 0]
+		set rest [lrange $items 1 end]
+		if {[string compare $rest ""]} {
+		    set flowctl($conn,queue) $rest
+		    set flowctl($conn,after) \
+			    [after $flowctl(floodlimit) \
+				[list ::irk::sendlater $conn]]
+		} else {
+		    unset flowctl($conn,queue)
+		}
+
+		# Record time we last sent to this destination.
+
+		set flowctl($conn,lastsend) [clock clicks -milliseconds]
+
+		# Send this item:
+
+		puts $conn $item
+	    } else {
+		unset flowctl($conn,queue)
+	    }
+	}
+    }
+}
+
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkqueue.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkqueue.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkqueue.tcl	(revision 11817)
@@ -0,0 +1,103 @@
+# irkenqueue.tcl
+#
+# Simple flow control management so as to avoid flooding.
+
+namespace eval ::irk {
+
+    # For each combination of destination+connection, we keep three items:
+    # 
+    # flowctl($dest,$conn,after)	The "after" token for the next time
+    #					we send anything to this destination.
+    # flowctl($dest,$conn,queue)	A list of items to send to this
+    #					destination on this connection.
+    # flowctl($dest,$conn,lastsend)	The time we last sent to this
+    #					destination on this connection.
+    #
+    # NOTE: We do not limit the length of each item to send. This
+    # would lead to extremely hard to diagnose bugs due to commands
+    # (e.g. ctcp's) getting cut up into chunks.
+
+    variable flowctl
+
+    # The following setting determines the number of seconds that must
+    # pass between sends to any one destination+connection. If fewer
+    # seconds have passed since the last send, then flow control is
+    # activated for this destination+connection.
+
+    set flowctl(sendlimit) 2
+
+    # This procedure sends an item to a specific destination+connection.
+    # If possible, the item is sent right away. Otherwise it is enqueued
+    # for later sending.
+
+    proc enqueue {dest conn item} {
+	variable flowctl
+
+	# If this destination has a backlog, append the new
+	# items. Otherwise, check if the previous send was
+	# less than 2 seconds ago. If so, enqueue it for
+	# later sending. Otherwise send it now and record
+	# the time we sent this item.
+
+	if {[info exists flowctl($dest,$conn,after)]} {
+	    lappend flowctl($dest,$conn,queue) $item
+	} else {
+	    if {[catch {set lastsend $flowctl($dest,$conn,lastsend)}]} {
+		set lastsend 0
+	    }
+	    set now [clock seconds]
+	    set lim $flowctl(sendlimit)
+	    if {[expr $now - $lastsend] < $lim} {
+		lappend flowctl($dest,$conn,queue) $item
+		set wait [expr ($lim - ($now - $lastsend)) * 1000]
+		set flowctl($dest,$conn,after) \
+			[after $wait [list ::irk::sender $dest $conn]]
+	    } else {
+		set flowctl($dest,$conn,lastsend) $now
+		puts $conn $item
+	    }
+	}
+
+	return ""
+    }
+
+    # This procedure does the sending when flow control for a connection
+    # is activated.
+
+    proc sender {dest conn} {
+	variable flowctl
+
+	# First of all clear the after entry.
+
+	unset flowctl($dest,$conn,after)
+
+	# Grab the first item on the queue:
+
+	if {[info exists flowctl($dest,$conn,queue)]} {
+	    set items $flowctl($dest,$conn,queue)
+	    if {[string compare $items ""]} {
+		set item [lindex $items 0]
+		set rest [lrange $items 1 end]
+		if {[string compare $rest ""]} {
+		    set lim [expr $flowctl(sendlimit) * 1000]
+		    set flowctl($dest,$conn,queue) $rest
+		    set flowctl($dest,$conn,after) \
+			    [after $lim [list ::irk::sender $dest $conn]]
+		} else {
+		    unset flowctl($dest,$conn,queue)
+		}
+
+		# Record time we last sent to this destination.
+
+		set flowctl($dest,$conn,lastsend) [clock seconds]
+
+		# Send this item:
+
+		puts $conn $item
+	    } else {
+		unset flowctl($dest,$conn,queue)
+	    }
+	}
+    }
+}
+
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkreceive.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkreceive.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkreceive.tcl	(revision 11817)
@@ -0,0 +1,618 @@
+# irkreceive.tcl:
+#
+# Various commands invoked in response to input received from the server:
+
+namespace eval irk {
+
+    # This procedure deals with the PING special action:
+
+    proc RECV,PING {token nick user comm dest rest} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid IRK connection"
+	}
+	puts $sock "PONG :$comm $rest"
+
+	return ""
+    }
+
+    # This procedure deals with the NOTICE special action:
+
+    proc RECV,NOTICE {token nick user comm dest rest} {
+	variable state
+
+	append state($token,GLOBALNOTICES) "$rest\n"
+
+	return ""
+    }
+
+
+    # This procedure deals with the ERROR special action:
+
+    proc RECV,ERROR {token nick user comm dest rest} {
+	variable state
+
+	set rest [eval concat $rest]
+	append state($token,ERRORS) "$nick $dest $rest\n"
+#	puts "Got ERROR: $token $nick ---> $dest: $rest"
+	::orxonox::execute error "Got ERROR: $token $nick ---> $dest: $rest"
+
+	return ""
+    }
+
+    # This procedure deals with the AWAY response:
+
+    proc RECV,AWAY {token nick user comm dest rest} {
+	set id [lindex $rest 0]
+	set rest [lrange $rest 1 end]
+	set rest [lreplace $rest 0 0 [string range [lindex $rest 0] 1 end]]
+	set rest [eval concat $rest]
+	puts "$id is away: $rest"
+
+	return ""
+    }
+
+    # This procedure deals with the WHOIS USER message:
+
+    proc RECV,WHOIS,NICK,USER {token nick user comm dest rest} {
+	variable state
+
+	# Split the rest of the line on space:
+
+	foreach {unick uuser uhost ustar urnm} [split $rest " "] break
+
+	# If the WHOIS information is about this user, save it specially:
+
+	if {[isus $token $unick]} {
+	    set state($token,uuser)	$uuser
+	    set state($token,uhost)	$uhost
+	    set state($token,urnm)	$urnm
+	}
+
+	# Save the information for a regular user:
+
+	set state($token,ident,$unick,uuser)	$uuser
+	set state($token,ident,$unick,uhost)	$uhost
+	set state($token,ident,$unick,urnm)	$urnm
+    }
+
+    # This procedure deals with the WHOIS SERVER message:
+
+    proc RECV,WHOIS,NICK,SERVER {token nick user comm dest rest} {
+	variable state
+
+	# Split the rest of the line on space:
+
+	foreach {unick userv} [split $rest " "] break
+
+	# If the WHOIS information is about this user, save it specially:
+
+	if {[isus $token $unick]} {
+	    set state($token,userv) $userv
+	}
+
+	# Save the information for a regular user:
+
+	set state($token,ident,$unick,userv) $userv
+    }
+
+    # This procedure deals with the WHOIS IDENT message
+
+    proc RECV,WHOIS,NICK,IDENT {token nick user comm dest rest} {
+	variable state
+
+	# Extract the nick of the user who has identified
+
+	set unick [lindex [split $rest " "] 0]
+
+	# If the WHOIS information is about this user, save it specially:
+
+	if {[isus $token $unick]} {
+	    set state($token,ident) 1
+	}
+
+	# Save the information for a regular user:
+
+	set state($token,ident,$unick,ident) 1
+    }
+
+    # This procedure deals with the WHOIS CONNECTTIME message:
+
+    proc RECV,WHOIS,NICK,CONNECTTIME {token nick user comm dest rest} {
+	variable state
+
+	# Split the rest of the input on space:
+
+	foreach {unick idle connecttime} [split $rest " "] break
+
+	# Format the connect time for this user:
+
+	set connecttime [clock format $connecttime]
+
+	# If the WHOIS information is about this user, save it specially:
+
+	if {[isus $token $unick]} {
+	    set state($token,connecttime) $connecttime
+	}
+
+	# Save the information for a regular user:
+
+	set state($token,ident,$unick,connecttime) $connecttime
+    }
+
+    # Handle the WHOIS CHANNELS message:
+
+    proc RECV,WHOIS,NICK,CHANNELS {token nick user comm dest rest} {
+	variable state
+
+	# Split the rest on space.
+
+	set rest [split $rest " "]
+
+	# Get the nick for which this is the channel list:
+
+	set unick [lindex $rest 0]
+	set rest [lrange $rest 1 end]
+
+	# The first channel may have an extra ":", if it does get rid of it.
+
+	set firstchan [lindex $rest 0]
+	if {[string match ":*" $firstchan]} {
+	    set rest [lreplace $rest 0 0 [string range $firstchan 1 end]]
+	}
+
+	# If the WHOIS information is about this user, save it specially:
+
+	if {[isus $token $unick]} {
+	    set state($token,channels) $channels
+	}
+
+	# Save the information for a regular user:
+
+	set state($token,ident,$unick,channels) $rest
+    }
+
+    # This procedure deals with the WHOIS END message:
+
+    proc RECV,WHOIS,NICK,END {token nick user comm dest rest} {
+	variable state
+
+	set state($token,whois,done) 1
+    }
+
+    # This procedure deals with various MOTD actions:
+
+    proc RECV,MOTD {token nick user comm dest rest} {
+	variable state
+
+	append state($token,MOTD) "${rest}\n"
+
+	return ""
+    }
+
+    # This procedure deals with PONG actions:
+
+    proc RECV,PONG {token nick user comm dest rest} {
+	variable state
+
+	if {[info exists state($token,PINGSTART)]} {
+	    set elapsed \
+		[expr [clock clicks -millis] - $state($token,PINGSTART)]
+	    puts "$nick: $elapsed msecs"
+	    unset state($token,PINGSTART)
+	}
+
+	return ""
+    }
+
+    # This procedure deals with NOTICE received from a regular user:
+
+    proc RECV,NOTICE,USER {token nick user comm dest rest} {
+	if {[string match "\001*" [lindex $rest 0]]} {
+	    set rest [ctcpcleanup $rest]
+	    RECV,NOTICE,CTCP,USER $token $nick $user $comm $dest \
+		    [lindex $rest 0] [lrange $rest 1 end]
+	} else {
+	    set rest [eval concat $rest]
+	    puts "$nick sends $dest a notice: $rest"
+	}
+
+	return ""
+    }
+
+    # This procedure helps with CTCP notice actions:
+
+    proc RECV,NOTICE,CTCP,USER {token nick user comm dest action rest} {
+	variable state
+
+	if {[info exists state($token,response,ctcp,$action)]} {
+	    $state($token,response,ctcp,$action) \
+					$token $nick $user $comm $dest \
+					$action $rest
+	} else {
+	    $state($token,response,ctcp,error) \
+					$token $nick $user $comm $dest \
+					$action $rest
+	}
+
+	return ""
+    }
+
+    # This procedure deals with JOIN actions:
+
+    proc RECV,JOIN {token nick user comm dest rest} {
+	variable state
+
+	# Check if it's us that joined the channel or someone else.
+
+	if {[isus $token $nick]} {
+#	    puts "You joined $dest"
+          ::orxonox::irc::info $token "You joined $dest"
+
+	    addChannel $token $dest
+	} else {
+#	    puts "$nick joined $dest"
+          ::orxonox::irc::info $token "$nick joined $dest"
+
+	    addToChannel $token $nick $dest
+	}
+
+	return ""
+    }
+
+    # This procedure deals with PART actions:
+
+    proc RECV,PART {token nick user comm dest rest} {
+	variable state
+
+	set chan [string tolower $dest]
+
+	if {[isus $token $nick]} {
+#	    puts "You left channel $chan"
+          ::orxonox::irc::info $token "You left channel $chan"
+	} else {
+#	    puts "$nick left [string tolower $dest]"
+          ::orxonox::irc::info $token "$nick left [string tolower $dest]"
+	}
+	removeFromChannel $token $nick $chan
+	removeFromChannel $token @$nick $chan
+
+	return ""
+    }
+
+    # This procedure deals with MODE actions:
+
+    proc RECV,MODE {token nick user comm dest rest} {
+	set rest [eval concat $rest]
+#	puts "$nick sets mode $dest $rest"
+      ::orxonox::irc::info "$nick $token sets mode $dest $rest"
+
+	return ""
+    }
+
+    # This procedure deals with NICK actions:
+
+    proc RECV,NICK {token nick user comm dest rest} {
+	variable state
+
+	set newnick [string range $dest 0 end]
+
+	# If our nick changed, remember it as the nick associated with
+	# this connection:
+
+	if {[isus $token $nick]} {
+	    set state($token,nick) $newnick
+	    set state($token,$newnick,PRIVMSG)	$state(PRIVMSG,unsolicited)
+	    catch {unset state($token,$nick,PRIVMSG)}
+	}
+
+	# Replace the old nick with the new in all channels that we're on:
+
+	replaceAllChannels $token $nick $newnick
+
+#	puts "$nick ${user} ($token) changes his/her nickname to $newnick"
+      ::orxonox::irc::info $token "$nick changes his/her nickname to $newnick"
+
+	return ""
+    }
+
+    # This procedure deals with QUIT actions:
+
+    proc RECV,QUIT {token nick user comm dest rest} {
+	variable state
+
+	set rest [eval concat $rest]
+#	puts "Received QUIT $token $nick $rest"
+      ::orxonox::irc::info $token "Received QUIT $token $nick $rest"
+
+	if {[string match ":*" $dest]} {
+	    set dest [string range $dest 1 end]
+	}
+	if {[isus $token $nick]} {
+#	    puts "You left the server $state($token,host) ($dest $rest)"
+          ::orxonox::irc::info $token "You left the server $state($token,host) ($dest $rest)"
+	    forgetConnection $token
+	} else {
+	    puts "$nick quits IRK ($dest $rest)"
+	    removeFromAllChannels $token $nick
+	    removeFromAllChannels $token @$nick
+	}
+
+	return ""
+    }
+
+    # This procedure deals with expected PRIVMSG actions:
+
+    proc RECV,PRIVMSG {token nick user comm dest rest} {
+	if {[string match "\001*" [lindex $rest 0]]} {
+	    set rest [ctcpcleanup $rest]
+	    RECV,PRIVMSG,CTCP,CHANNEL $token $nick $user $comm $dest \
+		    [lindex $rest 0] [lrange $rest 1 end]
+	} else {
+#	    puts "$nick$dest: [eval concat $rest]"
+          ::orxonox::irc::say $token $nick [eval concat $rest]
+	}
+
+	return ""
+    }
+
+    # This procedure handles CTCP actions on the channel:
+
+    proc RECV,PRIVMSG,CTCP,CHANNEL {token nick user comm dest action rest} {
+	variable state
+
+	if {[info exists state($token,channel,ctcp,$action)]} {
+	    $state($token,channel,ctcp,$action) \
+					$token $nick $user $comm $dest \
+					$action $rest
+	} else {
+	    $state($token,channel,ctcp,error) \
+					$token $nick $user $comm $dest \
+					$action $rest
+	}
+
+	return ""
+    }
+
+    # This procedure stores the result of USERHOST actions:
+
+    proc RECV,USERHOST {token nick user comm dest rest} {
+	return ""
+    }
+
+    # This procedure stores the channel topic:
+
+    proc RECV,CHANNEL,TOPIC {token nick user comm dest rest} {
+	variable state
+
+	set chan [lindex $rest 0]
+	set rest [lrange $rest 1 end]
+	if {[string match ":*" [lindex $rest 0]]} {
+	    set rest [lreplace $rest 0 0 \
+			       [string range [lindex $rest 0] 1 end]]
+	}
+	set state($token,$chan,TOPIC) $rest
+	set state($token,$chan,TOPIC,SETBY) $nick
+	set state($token,$chan,TOPIC,SETAT) [clock format [clock seconds]]
+
+	return ""
+    }
+
+    # This procedure stores the channel byline:
+
+    proc RECV,CHANNEL,SETBY {token nick user comm dest rest} {
+	variable state
+
+	set chan [lindex $rest 0]
+	set rest [lrange $rest 1 end]
+	if {[string match ":*" [lindex $rest 0]]} {
+	    set rest [lreplace $rest 0 0 \
+			       [string range [lindex $rest 0] 1 end]]
+	}
+	set state($token,$chan,TOPIC,SETBY) [lindex $rest 0]
+	set state($token,$chan,TOPIC,SETAT) [clock format [lindex $rest 1]]
+
+	return ""
+    }
+
+    # This procedure deals with unsolicited PRIVMSG actions:
+
+    proc RECV,PRIVMSG,unsolicited {token nick user comm dest rest} {
+	if {[string match "\001*" [lindex $rest 0]]} {
+	    set rest [ctcpcleanup $rest]
+	    RECV,PRIVMSG,CTCP,USER $token $nick $user $comm $dest \
+		    [lindex $rest 0] [lrange $rest 1 end]
+	} else {
+#	    puts "$nick: [eval concat $rest]"
+          ::orxonox::irc::privmsg $nick $nick [eval concat $rest]
+	}
+
+	return ""
+    }
+
+    # This procedure helps with CTCP private messages:
+
+    proc RECV,PRIVMSG,CTCP,USER {token nick user comm dest action rest} {
+	variable state
+
+	if {[info exists state($token,cmd,ctcp,$action)]} {
+	    $state($token,cmd,ctcp,$action) \
+					$token $nick $user $comm $dest \
+					$action $rest
+	} else {
+	    $state($token,cmd,ctcp,error) \
+					$token $nick $user $comm $dest \
+					$action $rest
+	}
+
+	return ""
+    }
+
+    # This procedure deals with a KICK action:
+
+    proc RECV,KICK {token nick user comm dest rest} {
+	set kicked [lindex $rest 0]
+	if {[string match ":*" $kicked]} {
+	    set kicked [string range $kicked 1 end]
+	}
+	set reason [eval concat [lrange $rest 1 end]]
+	if {[string match ":*" $reason]} {
+	    set reason [string range $reason 1 end]
+	}
+
+	if {[isus $token $kicked]} {
+#	    puts "$nick kicked you from $dest because $reason"
+          ::orxonox::irc::info $token "$nick kicked you from $dest because $reason"
+
+	    removeChannel $token $dest
+	} else {
+#	    puts "$nick kicks $kicked from $dest because $reason"
+          ::orxonox::irc::info $token "$nick kicks $kicked from $dest because $reason"
+
+	    removeFromChannel $token $kicked $dest
+	    removeFromChannel $token @$kicked $dest
+	}
+
+	return ""
+    }
+
+    # These procedures collect the name list for a channel:
+
+    proc RECV,CHANNEL,NAMELIST {token nick user comm dest rest} {
+	variable state
+
+	# Scan forward in $rest for the channel name:
+
+	for {set i 0; set l [llength $rest]} {$i < $l} {incr i} {
+	    if {[string match "#*" [lindex $rest $i]]} {
+		break
+	    }
+	}
+
+	# Didn't find it?
+
+	if {$i == $l} {
+	    return
+	}
+
+	# Extract the channel name and the rest of the input:
+
+	set chan [lindex $rest $i]
+	set rest [lrange $rest [expr $i + 1] end]
+	set rest [lreplace $rest 0 0 [string range [lindex $rest 0] 1 end]]
+	set rest [eval concat $rest]
+
+	if {![info exists state($token,$chan,NAMES)]} {
+	    set state($token,$chan,NAMES) ""
+	}
+	set state($token,$chan,NAMES) [concat $state($token,$chan,NAMES) $rest]
+
+	return ""
+    }
+
+    proc RECV,CHANNEL,NAMELIST,END {token nick user comm dest rest} {
+	variable state
+
+	set chan [lindex $rest 0]
+	set $state($token,$chan,NAMES) [split $state($token,$chan,NAMES) " "]
+    }
+
+    # This procedure deals with a request from the server to send a PONG
+    # with a given code.
+
+    proc RECV,PONG,REQUEST {token nick user comm dest rest} {
+	set pongcode [lindex $rest [expr [llength $rest] - 1]]
+	puts $token "PONG $pongcode"
+
+	return ""
+    }
+
+    # This procedure deals with a CTCP PING request:
+
+    proc RECV,CTCP,PING {token nick user comm dest action rest} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid IRK connection"
+	}
+	puts $sock "NOTICE $nick :\001PING ${rest}\001"
+
+	return ""
+    }
+
+    # This procedure deals with a CTCP TIME request:
+
+    proc RECV,CTCP,TIME {token nick user comm dest action rest} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid IRK connection"
+	}
+	puts $sock \
+	    "NOTICE $nick :\001TIME :[clock format [clock seconds]]\001"
+
+	return ""
+    }
+
+    # This procedure deals with a CTCP VERSION request:
+
+    proc RECV,CTCP,VERSION {token nick user comm dest action rest} {
+	variable state
+	global tcl_platform
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid IRK connection"
+	}
+	set version "$state(-useragent):$state(-version):$tcl_platform(os)"
+	puts $sock "NOTICE $nick :\001VERSION ${version}\001"
+    }
+
+    # This procedure deals with a CTCP USERINFO request:
+
+    proc RECV,CTCP,USERINFO {token nick user comm dest action rest} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid IRK connection"
+	}
+	puts $sock "NOTICE $nick :\001USERINFO $state(-$token,user)\001"
+    }
+
+    # This procedure deals with CTCP ACTION messages:
+
+    proc RECV,CTCP,ACTION {token nick user comm dest action rest} {
+#	puts "$nick $rest"
+      ::orxonox::irc::action $token $nick $rest
+
+	return ""
+    }
+
+    # This procedure is a catch all for CTCP actions that we do not
+    # understand:
+
+    proc RECV,CTCP,ERROR {token nick user comm dest action rest} {
+	variable state
+
+	if {[catch {set sock $state($token,socket)}]} {
+	    error "$token: not a valid IRC connection"
+	}
+	if {[llength $rest] > 0} {
+	    puts $sock \
+		"NOTICE $nick :\001ERRMSG $action $rest: unknown CTCP\001"
+	} else {
+	    puts $sock "NOTICE $nick :\001ERRMSG $action: unknown CTCP\001"
+	}
+    }
+
+    # This is the default action, used by the default dispatcher
+    # when no action can be found for the given $token, $nick, $user,
+    # $comm, and $dest.
+
+    proc defaultAction {token nick user comm dest rest} {
+#	puts "$token: $nick $user: $comm -> $dest ... [eval concat $rest]"
+      ::orxonox::execute log "$token: $nick $user: $comm -> $dest ... [eval concat $rest]"
+
+	return ""
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkservers.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkservers.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkservers.tcl	(revision 11817)
@@ -0,0 +1,57 @@
+# irkservers.tcl:
+#
+# This file defines the servers that are known to the Tcl IRK library.
+# It is actually a Tcl script and is source'd by the irk.tcl file.
+
+namespace eval ::irk {
+
+    # This procedure helps define a new server:
+
+    proc defineserver {symname host ports} {
+	variable state
+	variable symsrv
+
+	# Auto initialize the list of known (symbolic names for) servers:
+
+	if {![info exists state(servers)]} {
+	    set state(servers) {}
+	}
+
+	# Add an entry in the list of (symbolic names for) servers:
+
+	lappend state(servers) $symname
+
+	# Add an entry for the contact information of this symbolic server:
+
+	set symsrv($symname) [list $host $ports]
+    }
+
+    # OK, now define a bunch of servers. This is where you can add your
+    # own, or edit if things change:
+
+    defineserver twisted	twisted.ma.us.dal.net {6660 6661 6662 6663}
+    defineserver dalnet		irc.dal.net			6667
+    defineserver undernet	McLean.VA.us.undernet.org	{6667 6668}
+    defineserver efnet		irc.Prison.NET			6666
+    defineserver ircnet		irc.stealth.net			{6663 6664}
+    defineserver powersurf	irc.powersurfr.com		6667
+    defineserver coins		coins.dal.net	{6667 6668 6669 7000}
+    defineserver sodre		sodre.on.ca.dal.net {6667 6668 6669 7000}
+    defineserver austnet	au.austnet.org 6667
+    defineserver nznet		nz.austnet.org 6667
+    defineserver sgnet		sg.austnet.org 6667
+    defineserver us.efnet	us.rr.efnet.net 6667
+    defineserver eu.efnet	eu.rr.efnet.net 6667
+    defineserver ca.efnet	ca.rr.efnet.net 6667
+    defineserver au.efnet	au.rr.efnet.net 6667
+    defineserver us.ircnet	us.ircnet.org {6665 6666 6667 6668}
+    defineserver eu.ircnet	eu.ircnet.org {6665 6666 6667 6668}
+    defineserver ca.ircnet	ca.ircnet.org {6665 6666 6667 6668}
+    defineserver au.ircnet	au.ircnet.org {6665 6666 6667 6668}
+    defineserver us.undernet	us.undernet.org 6667
+    defineserver eu.undernet	eu.undernet.org 6667
+    defineserver othernet	irc.othernet.org 6667
+    defineserver de.quakenet  de.quakenet.org 6667
+    defineserver datacore     irc.datacore.ch 6667
+    defineserver orxonox      irc.orxonox.net 6667
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkstate.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkstate.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkstate.tcl	(revision 11817)
@@ -0,0 +1,134 @@
+# irkstate.tcl:
+#
+# This file defines the contents of the ::irk::state array
+
+namespace eval ::irk {
+
+    # The state array contains all the state for the IRK package:
+    #
+    # These options can be configured with irk::config:
+    #
+    # state(-useragent)		Name of this IRK user agent.
+    # state(-version)		Version of this IRK user agent.
+    #
+    # state(-sockproxy)		Name of SOCKS5 proxy to use (optional).
+    # state(-socksport)		Port on which SOCKS5 server accepts
+    #				connections (optional).
+    #
+    # state(-$symsrv,nick)	If set and connect is called without giving
+    #				a nick, use this as the nickname.
+    # state(-$symsrv,user)	If set and connect is called without giving
+    #				a user, this is used. Otherwise, if it's not
+    #				set when connect is called without a user,
+    #				it is set to the given nickname (and used).
+    # state(-$symsrv,pass)	If set, and connect is called without giving
+    #				a password, this is used.
+    #
+    # state(-quitmessage)	If set, the message is sent when a connection
+    #				is closed, as part of a QUIT command.
+    #
+    # These options cannot be configured with irk::config:
+    #
+    # state(connections)	A list of all active connections.
+    # state(dispatcher)		The default command dispatcher (must be set).
+    # state(action)		The default action (must be set).
+    # state(servers)		List of known servers (further described in
+    #				the symsrv array below).
+    #
+    # The following state is kept per connection (identified by $contok):
+    #
+    # state($contok,socket)	The socket for a given connection
+    # state($contok,port)	The port of a given connection
+    # state($contok,host)	The host of a given connection
+    # state($contok,symsrv)	The symbolic name of the server for
+    #				this connection.
+    # state($contok,nick)	The nick name used on a given connection
+    # state($contok,user)	The real user used on a given connection
+    # state($contok,pass)	The password used on a given connection
+    # state($contok,disp)	The command dispatcher for the connection
+    #
+    # Depending on the dispatcher associated with each connection, there
+    # may be many more settings of the general form:
+    #
+    # state($contok,action,...)
+    #
+    # System wide responses to common commands are handled by
+    # special actions, stored in the state array:
+    #
+    # state(PRIVMSG,unsolicited)
+    #				Action that responds to unsolicited private
+    #				messages directed at this user's nickname.
+    # state(special,PING)	Responds to PING messages.
+    # state(special,NOTICE)	Responds to NOTICE messages.
+    # state(special,ERROR)	Responds to ERROR messages.
+    #
+    # The IRK library provides a unified authorization mechanism, implemented
+    # in irkauth.tcl. The state array contains two settings that affect the
+    # behavior of the authorization mechanism:
+    #
+    # state(auth,save,file)	Name of a file to save the authorization
+    #				information in. Defaults to auth.dat in the
+    #				directory containing the IRK package.
+    # state(auth,save,interval)	The number of milliseconds that pass between
+    #				autosaves of the authorization data.
+    
+    variable state
+    array set state {
+	-useragent		"Tcl IRK Library"
+	-version		0.1
+	-quitmessage		"gives up the ghost"
+
+	dispatcher		::irk::defaultDispatcher
+	action			::irk::defaultAction
+
+	cmd,QUIT		::irk::RECV,QUIT
+	cmd,JOIN		::irk::RECV,JOIN
+	cmd,PART		::irk::RECV,PART
+	cmd,MODE		::irk::RECV,MODE
+	cmd,NICK		::irk::RECV,NICK
+	cmd,PONG		::irk::RECV,PONG
+	cmd,PRIVMSG		::irk::RECV,PRIVMSG
+	cmd,NOTICE		::irk::RECV,NOTICE,USER
+	cmd,KICK		::irk::RECV,KICK
+	cmd,001			::irk::RECV,MOTD
+	cmd,002			::irk::RECV,MOTD
+	cmd,003			::irk::RECV,MOTD
+	cmd,004			::irk::RECV,MOTD
+	cmd,005			::irk::RECV,MOTD
+	cmd,250			::irk::RECV,MOTD
+	cmd,251			::irk::RECV,MOTD
+	cmd,252			::irk::RECV,MOTD
+	cmd,253			::irk::RECV,MOTD
+	cmd,254			::irk::RECV,MOTD
+	cmd,255			::irk::RECV,MOTD
+	cmd,265			::irk::RECV,MOTD
+	cmd,266			::irk::RECV,MOTD
+	cmd,301			::irk::RECV,AWAY
+	cmd,307			::irk::RECV,WHOIS,NICK,IDENT
+	cmd,311			::irk::RECV,WHOIS,NICK,USER
+	cmd,312			::irk::RECV,WHOIS,NICK,SERVER
+	cmd,317			::irk::RECV,WHOIS,NICK,CONNECTTIME
+	cmd,318			::irk::RECV,WHOIS,NICK,END
+	cmd,319			::irk::RECV,WHOIS,NICK,CHANNELS
+	cmd,372			::irk::RECV,MOTD
+	cmd,375			::irk::RECV,MOTD
+	cmd,376			::irk::RECV,MOTD
+	cmd,332			::irk::RECV,CHANNEL,TOPIC
+	cmd,333			::irk::RECV,CHANNEL,SETBY
+	cmd,353			::irk::RECV,CHANNEL,NAMELIST
+	cmd,366			::irk::RECV,CHANNEL,NAMELIST,END
+
+	cmd,513			::irk::RECV,PONG,REQUEST
+
+	special,PING		::irk::RECV,PING
+	special,NOTICE		::irk::RECV,NOTICE
+	special,ERROR		::irk::RECV,ERROR
+
+	PRIVMSG,unsolicited	::irk::RECV,PRIVMSG,unsolicited
+
+	errorhandler		::irk::echoerror
+
+	auth,save,file		[file join [file dir [info script]] auth.dat]
+	auth,save,interval	300000
+    }
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkutil.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkutil.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/lib/irkutil.tcl	(revision 11817)
@@ -0,0 +1,144 @@
+# irkutil.tcl:
+#
+# Utility procedures used throughout the IRK package.
+
+namespace eval ::irk {
+
+    # The randselect randomly selects an element of a given list.
+
+    proc randselect {l} {
+	lindex $l [expr int(floor(rand() * [llength $l]))]
+    }
+
+    # Remove a user from the list of users on a channel
+
+    proc removeFromChannel {token user chan} {
+	variable state
+
+	# If it's us that left the channel, forget the channel:
+
+	if {![string compare $state($token,nick) $user]} {
+	    removeChannel $token $chan
+	    return
+	}
+
+	# Try to retrieve the channel's user list:
+
+	if {[catch {set users $state($token,$chan,NAMES)}]} {
+	    return
+	}
+	set idx [lsearch $users $user]
+	if {$idx == -1} {
+	    return
+	}
+
+	# Remove the user:
+
+	set state($token,$chan,NAMES) [lreplace $users $idx $idx]
+    }
+
+    # Remove a user from all the channels I am on (for QUIT etc.)
+
+    proc removeFromAllChannels {token user} {
+	variable state
+
+	foreach chan $state($token,channels) {
+	    removeFromChannel $token $user $chan
+	}
+    }
+
+    # Add a user to a channel I am on.
+
+    proc addToChannel {token user chan} {
+	variable state
+
+	lappend state($token,$chan,NAMES) $user
+    }
+
+    # Add a channel to the list of channels we're on:
+
+    proc addChannel {token chan} {
+	variable state
+
+	lappend state($token,channels) $chan
+    }
+
+    # Remove a channel from the list of channels we're on:
+
+    proc removeChannel {token chan} {
+	variable state
+
+	if {[catch {set channels $state($token,channels)}]} {
+	    return
+	}
+	set idx [lsearch $channels $chan]
+	if {$idx == -1} {
+	    return
+	}
+
+	# Remove this channel from the list of channels we're on:
+
+	set state($token,channels) [lreplace $channels $idx $idx]
+
+	# Forget all state for this channel:
+
+	array unset state $token,$chan,*
+    }
+
+    # This procedure cleans up all state associated with a connection:
+
+    proc forgetConnection {token} {
+	variable state
+
+	array unset state $token,*
+    }
+
+    # This procedure updates the channel names for all channels we're on
+    # due to a nick change.
+
+    proc replaceAllChannels {token nick newnick} {
+	variable state
+
+	# If we're not on any channels, then no need to replace.
+
+	if {![info exists state($token,channels)]} {
+	    return
+	}
+
+	# Replace the old nick with the new nick in all the channels I'm on.
+
+	foreach chan $state($token,channels) {
+	    if {[catch {set names $state($token,$chan,NAMES)}]} {
+		continue
+	    }
+	    set idx [lsearch $names $nick]
+	    if {$idx != -1} {
+		set state($token,$chan,NAMES) \
+			[lreplace $names $idx $idx $newnick]
+	    }
+	}
+    }
+
+    # This procedure determines whether a nick is our nick.
+    
+    proc isus {token nick} {
+	variable state
+
+	if {![string compare $nick $state($token,nick)]} {
+	    return 1
+	}
+	return 0
+    }
+
+    # This procedure cleans up input received as part of a CTCP action.
+
+    proc ctcpcleanup {l} {
+	if {[llength $l] > 1} {
+	    set h [string range [lindex $l 0] 1 end]
+	    set t [string range [lindex $l end] 0 end-1]
+	    return [lreplace [lreplace $l 0 0 $h] end end $t]
+	}
+	return [string range $l 1 end-1]
+    }
+	
+}
Index: /code/branches/RacingBots_FS18/data/tcl/irk/pkgIndex.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/pkgIndex.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/pkgIndex.tcl	(revision 11817)
@@ -0,0 +1,12 @@
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+package ifneeded socks 1.2 [list source [file join $dir socks socks.tcl]]
+package ifneeded irk 0.1 [list source [file join $dir irk.tcl]]
Index: /code/branches/RacingBots_FS18/data/tcl/irk/socks/socks.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/irk/socks/socks.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/irk/socks/socks.tcl	(revision 11817)
@@ -0,0 +1,347 @@
+# Socks5 Client Library v1.2
+#
+# Original author: (C)2000 Kerem 'Waster_' HADIMLI
+#
+# Author contact information:
+#   E-mail :  waster@iname.com
+#   ICQ#   :  27216346
+#   Jabber :  waster@jabber.org   (New IM System - http://www.jabber.org)
+#
+# Cleaned up a little by Jacob Levy, jyl@best.com (01/07/2001)
+#
+# * Moved everything into the ::socks:: namespace.
+# * Parameterized so that constants do not get reset for every connection.
+# * Uniform error handling and cleanup.
+# * Incremented the version number to 1.2.
+#
+# How to use:
+#
+# Step 1: Create your client socket connected to the SOCKS5 server.
+#
+# Step 2: Call socks::init sock host port ?auth? ?user? ?pass?
+#    where:
+#
+#	sock		The socket from step #1.
+#	host		The remote host to connect to through the proxy.
+#	port		The remote port to connect to through the proxy.
+#	auth		Optional. If 1, it means that we do an
+#			authentication with the proxy server.
+#	user		Optional. If present, the user name to use for
+#			authentication with the proxy server.
+#	pass		Optional. If present, the password for the user
+#			name to use for authentication with the
+#			proxy server.
+#
+# If auth == 1, user and pass are not present, and socks::state(username)
+# and socks::state(pass) are set, then socks::init uses the values from
+# socks::state(username) and socks::state(password) for user name and
+# password, respectively.
+#
+# If anything goes wrong during the attempt to connect through the
+# proxy server, socks::init throws an appropriate error and closes
+# the socket. If the operation succeeds, socks::init returns $sock.
+#
+# You can set up your socket with fconfigure before calling socks::init,
+# the socks::init procedure is careful to restore the state to what it
+# was before the call upon successful completion. Likewise, you can
+# have fileevent handlers installed for handling socket readable and
+# socket writable events. These will also be preserved.
+
+# This file provides the "socks" package:
+
+package provide socks 1.2
+
+# Global settings:
+
+namespace eval ::socks {
+    variable state
+
+    array set state {
+	protocolversion		"\x05"
+	cmdconnect		"\x01"
+	addresstype		"\x03"
+	reserved		"\x00"
+
+	noauthmethod		"\x00"
+	noauthlengthstr		"\x01"
+
+	authmethod		"\x00\x02"
+	authlengthstr		"\x02"
+
+	nomatchingmethod	"\xFF"
+	nomatchlengthstr	"\x01"
+
+	authenticationversion	"\x01"
+
+	errorheader		"Error: "
+	error1			"General SOCKS server failure"
+	error2			"Connection not allowed by ruleset"
+	error3			"Network unreachable"
+	error4			"Host unreachable"
+	error5			"Connection refused"
+	error6			"TTL expired"
+	error7			"Command not supported"
+	error8			"Address type not supported"
+	errorUnknown		"Unknown error"
+
+	errorDisconnect		"SOCKS server disconnected"
+	errorNotSOCKS5		"SOCKS server does not support SOCKS 5"
+	errorMustAuthenticate	"SOCKS server demands user/pass authentication"
+	errorAuthMethodNotSup	"SOCKS server doesn't support user/pass auth"
+	errorWrongUserPass	"Wrong user name or password"
+	errorIncorrectAuthVal	"Incorrect value for $auth, expecting 1 or 0"
+	errorMissingUserAndPass	"Missing user and pass, required for auth == 1"
+    }
+}
+
+# Error handling and cleanup:
+
+proc ::socks::Error {sock errorMsg} {
+    variable state
+
+    # Attempt to close the socket. This also cancels any installed
+    # fileevent handlers, so no need to do that explicitly.
+
+    catch {close $sock}
+
+    # Clean up the state we keep about this socket:
+
+    catch {array unset state $sock,*}
+
+    # Report the requested error:
+
+    error "$state(errorheader)$state($errorMsg)"
+}
+    
+# Main entry point: socks::init
+#
+# See comment at head of file for how to use.
+
+proc ::socks::init {sock addr port {auth 0} {user {}} {pass {}}} {
+    variable state
+
+    # Save current configuration state for $sock
+
+    set currentConfiguration [fconfigure $sock]
+
+    # We cannot configure -peername so if its present (it should be)
+    # then remove it from the list of options.
+
+    set idx [lsearch $currentConfiguration -peername]
+    if {$idx != -1} {
+	set currentConfiguration \
+	    [lreplace $currentConfiguration $idx [expr $idx + 1]]
+    }
+
+    # Same for -sockname.
+
+    set idx [lsearch $currentConfiguration -sockname]
+    if {$idx != -1} {
+	set currentConfiguration \
+	    [lreplace $currentConfiguration $idx [expr $idx + 1]]
+    }
+
+    # Save any currently installed handler for fileevent readable:
+
+    set currentReadableHandler [fileevent $sock readable]
+
+    # If the user has "set and forget" user name and password, and
+    # indicates that she wants to use them, use them now:
+
+    if {($auth == 1) && (![string compare {} $user]) \
+	    && (![string compare {} $pass])} {
+	if {[info exists state(username)] && [info exists state(password)]} {
+	    set auth 1
+	    set user $state(username)
+	    set pass $state(password)
+	} else {
+	    Error $sock errorMissingUserAndPass
+	}
+    }
+
+    # Figure out the authentication method to use:
+
+    if {$auth == 0} {
+	set nmethods $state(noauthlengthstr)
+	set method $state(noauthmethod)
+    } elseif {$auth == 1} {
+	set nmethods $state(authlengthstr)
+	set method $state(authmethod)
+    } else {
+	Error $sock errorIncorrectAuthVal
+    }
+
+    # Encode the length of the address given (binary 1 byte):
+
+    set domainlen "[binary format c [string length $addr]]"
+
+    # Encode the port (network byte order, 2 bytes):
+
+    set port [binary format S $port]
+
+    if {$auth == 1} {
+	# Encode the length of the user given (binary 1 byte):
+
+	set userlen "[binary format c [string length $user]]"
+
+	# Encode the length of the password given (binary 1 byte):
+
+	set passlen "[binary format c [string length $pass]]"
+    }
+
+    # Set up initial state for the given socket:
+
+    set state($sock,state) $sock
+    set state($sock,data) ""
+
+    # Prepare the socket:
+
+    fconfigure $sock -translation {binary binary} -blocking 0
+    fileevent $sock readable "::socks::readable $sock"
+
+    # Tell the server what version and authentication method we're using:
+
+    puts -nonewline $sock "$state(protocolversion)$nmethods$method"
+    flush $sock
+
+    # Wait for server response and retrieve the information sent by the
+    # server:
+
+    vwait ::socks::state($sock,state)
+    set serverReply $state($sock,data)
+
+    if {[eof $sock]} {
+	Error $sock errorDisconnect
+    }
+
+    # Analyze the server's reply:
+
+    set serverVersion ""
+    set serverMethod $state(nomatchingmethod)
+
+    binary scan $serverReply "cc" serverVersion serverMethod
+
+    # Check for various error conditions:
+
+    if {$serverVersion != 5} {
+
+	# Server does not support SOCKS5 protocol
+
+	Error $sock errorNotSOCKS5
+    }
+
+    # If server demands authentication, do that step now:
+
+    if {$serverMethod == 2} {
+
+	if {$auth == 0} {
+
+	    # We didn't supply user/pass but server wants us to authenticate:
+
+	    Error $sock errorMustAuthenticate
+	}
+
+	puts -nonewline $sock \
+	    "$state(authenticationversion)$userlen$user$passlen$pass"
+	flush $sock
+
+	# Wait again for server reply:
+
+	vwait ::socks::state($sock,state)
+	set serverReply $state($sock,data)
+
+	# Analyze the server reply:
+
+	set authenticationVersion ""
+	set serverStatus "\x00"
+
+	binary scan $serverReply "cc" authenticationVersion serverStatus
+
+	# Deal with errors:
+
+	if {$authenticationVersion != 1} {
+
+	    # Server does not support our user/pass authentication method:
+
+	    Error $sock errorAuthMethodNotSup
+	}
+
+	if {$serverStatus != 0} {
+
+	    # We supplied wrong user/pass combination:
+
+	    Error $Sock errorWrongUserPass
+	}
+    } elseif {$serverMethod != 0} {
+
+	# Unknown method. Clean up:
+
+	Error $sock errorUnsupportedMethod
+    }
+
+    # Finally tell the server to connect us to the requested host and port:
+
+    puts -nonewline $sock \
+	"$state(protocolversion)$state(cmdconnect)$state(reserved)"
+    puts -nonewline $sock "$state(addresstype)$domainlen$addr$port"
+    flush $sock
+
+    # Wait again for server response:
+
+    vwait ::socks::state($sock,state)
+    set serverReply $state($sock,data)
+
+    if {[eof $sock]} {
+	Error $sock errorDisconnect
+    }
+
+    # Analyze server reply:
+
+    set serverVersion ""
+    set serverReplyCode ""
+
+    binary scan $serverReply "cc" serverVersion serverReplyCode
+
+    # Deal with errors:
+
+    if {$serverVersion != 5} {
+	Error $sock errorNotSOCKS5
+    }
+
+    if {$serverReplyCode != 0} {
+	if {($serverReplyCode > 0) && ($serverReplyCode < 9)} {
+	    Error $sock error$serverReplyCode
+	}
+	Error $sock errorUnknown
+    }
+
+    # All done, clean up state, reconfigure $sock to its original state,
+    # remove our fileevent handler and potentially restore the original
+    # one if one was present.
+
+    fileevent $sock readable {}
+    if {[string compare $currentReadableHandler ""]} {
+	fileevent $sock readable $currentReadableHandler
+    }
+    catch {eval fconfigure $sock $currentConfiguration}
+    catch {array unset state $sock,*}
+
+    # For good measure return the socket:
+
+    return $sock
+}
+
+# This procedure reads input available from the server socket and then
+# changes a state variable so that the main program will be woken up.
+
+proc ::socks::readable {sock} {
+    variable state
+
+    # Wake up the vwait:
+
+    set state($sock,state) $sock
+
+    # Read the data:
+
+    set state($sock,data) [read $sock]
+}
Index: /code/branches/RacingBots_FS18/data/tcl/remote.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/remote.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/remote.tcl	(revision 11817)
@@ -0,0 +1,2 @@
+set telnetserverthreadid [TclThreadManager create]
+TclThreadManager execute $telnetserverthreadid source $pld/telnet_server.tcl
Index: /code/branches/RacingBots_FS18/data/tcl/telnet_server.tcl
===================================================================
--- /code/branches/RacingBots_FS18/data/tcl/telnet_server.tcl	(revision 11817)
+++ /code/branches/RacingBots_FS18/data/tcl/telnet_server.tcl	(revision 11817)
@@ -0,0 +1,213 @@
+ #!/usr/bin/env tclsh
+ # Pseudo-telnet server.  Includes basic auth, but no separate identities
+ # or proper multi-threaded operation, so whoever runs this had better
+ # trust those he gives identities/passwords to and they had better trust
+ # each other too.  Note this script does not support command-line arguments.
+
+ ## The names of this array are IP addresses of hosts that are not permitted
+ ## to connect to any of our services.  Admin account(s) can change this
+ ## at run-time, though this info is not maintained across whole-server shutdowns.
+ array set denyHosts {}
+
+ ## Keep the Tcl-thread busy
+ proc every {ms body} { eval $body; after $ms [list every $ms $body] }
+ every 200 {}
+
+ ## Create a server on the given port with the given name/password map
+ ## and the given core interaction handler.
+ proc telnetServer {port {passmap} {handlerCmd remoteCommand}} {
+     if {$port == 0} {
+         return -code error "Only non-zero port numbers are supported"
+     }
+     set server [socket -server [list connect $port $handlerCmd] $port]
+     global passwords services
+     foreach {id pass} $passmap {set passwords($port,$id) $pass}
+     set services($server) $handlerCmd
+     return $server
+ }
+
+ ## Removes the server on the given port, cleaning up the extra state too.
+ proc closedownServer {server} {
+     global services passwords connections auth
+     set port [lindex [fconfigure $server -sockname] 2]
+     catch {close $server}
+     unset services($server)
+     foreach passmap [array names passwords $port,*] {
+         unset passwords($passmap)
+     }
+     # Hmph!  Have to remove unauthorized connections too, though any
+     # connection which has been authorized can continue safely.
+     foreach {client data} [array get connections] {
+         if {$port == [lindex $data 0] && !$auth($client)} {
+             disconnect $client
+         }
+     }
+ }
+
+ ## Handle an incoming connection to the given server
+ proc connect {serverport handlerCmd client clienthost clientport} {
+     global auth cmd denyHosts connections
+     if {[info exist denyHosts($clienthost)]} {
+         puts stdout "${clienthost}:${clientport} attempted connection"
+         catch {puts $client "Connection denied"}
+         catch {close $client}
+         return
+     }
+     puts stdout "${clienthost}:${clientport} connected on $client"
+     fileevent $client readable "handle $serverport $client"
+     set auth($client) 0
+     set cmd($client) $handlerCmd
+     set connections($client) [list $serverport $clienthost $clientport]
+     fconfigure $client -buffering none
+     catch {puts -nonewline $client "Login: "}
+ }
+
+ ## Disconnect the given client, cleaning up any connection-specific data
+ proc disconnect {client} {
+     catch {close $client}
+     global auth cmd connections
+     unset auth($client)
+     unset cmd($client)
+     unset connections($client)
+     puts stdout "$client disconnected"
+ }
+
+ ## Handle data sent from the client.  Log-in is handled directly by this
+ ## procedure, and requires the name and password on the same line
+ proc handle {serverport client} {
+     global passwords auth cmd
+     if {[gets $client line] < 0} {
+         disconnect $client
+         return
+     }
+     if {[string equal $line "logout"] || [string equal $line "quit"]} {
+         disconnect $client
+         return
+     }
+     if {[string equal $line "exit"]} {
+         set ::termination 1
+         return
+     }
+     if {$auth($client)} {
+         eval $cmd($client) [list $client $line 0]
+         eval $cmd($client) [list $client $line 1]
+         return
+     }
+     foreach {id pass} [split $line] {break}
+     if {![info exist pass]} {
+         catch {puts -nonewline $client "Login: "}
+         return
+     }
+     if {
+         [info exist passwords($serverport,$id)] &&
+         [string equal $passwords($serverport,$id) $pass]
+     } then {
+         set auth($client) 1
+         puts stdout "$id logged in on $client"
+         catch {puts $client "Welcome, $id!"}
+         eval $cmd($client) [list $client $line 1]
+         return
+     }
+     puts stdout "AUTH FAILURE ON $client"
+     catch {puts $client "Unknown name or password"}
+     disconnect $client
+ }
+
+ ## Standard handler for logged-in conversations and prompt-generation.
+ proc execCommand {client line prompt} {
+     global tcl_platform
+     if {$prompt} {
+         catch {puts -nonewline $client "\$ "}
+         return
+     }
+     switch $tcl_platform(platform) {
+         unix {
+             catch {exec sh -c $line <@$client >@$client 2>@$client}
+         }
+         default {
+             catch {exec $line} data
+             puts $client $data
+         }
+     }
+ }
+
+ ## Administration service handler.  Chains to the normal handler for
+ ## everything it doesn't recognise itself.
+ proc admin {client line prompt} {
+     if {$prompt} {
+         catch {puts -nonewline $client "# "}
+         return
+     }
+     set cmd [split $line]
+     global denyHosts connections services
+     if {[string equal $line "shutdown"]} {
+         set ::termination 1
+         puts stdout "Shutdown requested on $client"
+         catch {puts $client "System will shut down as soon as possible"}
+         return -code return "SHUTTING DOWN"
+     } elseif {[string equal [lindex $cmd 0] "deny"]} {
+         set denyHosts([lindex $cmd 1]) 1
+     } elseif {[string equal [lindex $cmd 0] "allow"]} {
+         catch {unset denyHosts([lindex $cmd 1])}
+     } elseif {[string equal $line "denied"]} {
+         foreach host [array names denyHosts] {
+             catch {puts $client $host}
+         }
+     } elseif {[string equal $line "connections"]} {
+         set len 0
+         foreach conn [array names connections] {
+             if {$len < [string length $conn]} {
+                 set len [string length $conn]
+             }
+         }
+         foreach {conn details} [array get connections] {
+             catch {puts $client [format "%-*s = %s" $len $conn $details]}
+         }
+     } elseif {[string equal [lindex $cmd 0] "close"]} {
+         set sock [lindex $cmd 1]
+         if {[info exist connections($sock)]} {
+             disconnect $sock
+         }
+     } elseif {[string equal $line "services"]} {
+         set len 0
+         foreach serv [array names services] {
+             if {$len < [string length $serv]} {
+                 set len [string length $serv]
+             }
+         }
+         foreach {serv handler} [array get services] {
+             set port [lindex [fconfigure $serv -sockname] 2]
+             catch {puts $client [format "%-*s (port %d) = handler %s" $len $serv $port $handler]}
+         }
+     } elseif {[string equal [lindex $cmd 0] "addService"]} {
+         set service [eval telnetServer [lrange $cmd 1 end]]
+         catch {puts $client "Created service as $service"}
+     } elseif {[string equal [lindex $cmd 0] "removeService"]} {
+         set service [lindex $cmd 1]
+         if {[info exist services($service)]} {
+             closedownServer $service
+         }
+     } else {
+         # CHAIN TO DEFAULT
+         execCommand $client $line 0
+     }
+ }
+ 
+ ## Executes a given command
+ proc remoteCommand {client line prompt} {
+     global tcl_platform
+     if {$prompt} {
+         catch {puts -nonewline $client "\$ "}
+         return
+     }
+     catch {eval $line} data
+     puts $client $data
+ }
+
+ telnetServer 2560 {orxonox rocks} remoteCommand
+ telnetServer 2561 {orxadmin *****} admin
+
+ puts stdout "Ready for service"
+
+ vwait termination
+ execute exit
Index: /code/branches/RacingBots_FS18/doc/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/doc/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,5 @@
+# Add a "doc" target with CMake build system.
+# And configure doxy.config.in to doxy.config
+#
+# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
+ADD_SUBDIRECTORY(api)
Index: /code/branches/RacingBots_FS18/doc/api/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,121 @@
+# Add a "doc" target with CMake build system.
+# And configure doxy.config.in to doxy.config
+#
+# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
+# Creates .chm windows help file if MS HTML help workshop
+# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
+# is installed with its DLLs in PATH.
+#
+#
+# Please note, that the tools, e.g.:
+# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
+# must be in path.
+#
+# Note about Visual Studio Projects:
+# MSVS hast its own path environment which may differ from the shell.
+# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
+#
+# author Jan Woetzel 2004-2006
+# www.mip.informatik.uni-kiel.de/~jw
+# Adjustments for Orxonox by Reto Grieder
+
+FIND_PACKAGE(Doxygen QUIET)
+
+IF (DOXYGEN_FOUND)
+  # click+jump in Emacs and Visual Studio (for doxy.config) (jw)
+  IF(CMAKE_BUILD_TOOL MATCHES "msdev|devenv")
+    SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
+  ELSE()
+    SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
+  ENDIF()
+
+  SET(DOXY_INPUT_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
+  SET(DOXY_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+  # we need latex for doxygen because of the formulas
+  # Orxonox doesn't
+  #FIND_PACKAGE(LATEX)
+  #IF    (NOT LATEX_COMPILER)
+  #  MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
+  #ENDIF (NOT LATEX_COMPILER)
+  #IF    (NOT MAKEINDEX_COMPILER)
+  #  MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
+  #ENDIF (NOT MAKEINDEX_COMPILER)
+  #IF    (NOT DVIPS_CONVERTER)
+  #  MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
+  #ENDIF (NOT DVIPS_CONVERTER)
+
+  SET(INTERNAL_DOCFILE ${CMAKE_CURRENT_BINARY_DIR}/Internal.dox)
+  IF(WIN32)
+    SET(_working_dir ${RUNTIME_LIBRARY_DIRECTORY})
+  ELSE()
+    SET(_working_dir ${CMAKE_CURRENT_BINARY_DIR})
+  ENDIF()
+  ADD_CUSTOM_COMMAND(
+    OUTPUT ${INTERNAL_DOCFILE}
+    COMMAND orxonox-main
+    ARGS --noIOConsole --generateDoc ${INTERNAL_DOCFILE}
+    WORKING_DIRECTORY ${_working_dir}
+    COMMENT "Generating additional Doxygen documentation from Orxonox executable"
+  )
+  ADD_CUSTOM_TARGET(doc_internal DEPENDS ${INTERNAL_DOCFILE})
+  IF (NOT EXISTS ${INTERNAL_DOCFILE})
+    FILE(WRITE ${INTERNAL_DOCFILE} "// empty...")
+  ENDIF()
+
+  # Take care of most of the conditional compilation problems
+  # (Doxygen requires separate input for that)
+  IF(WIN32)
+    SET(DOXY_PLATFORM_DEF "ORXONOX_PLATFORM_WINDOWS")
+  ELSEIF(APPLE)
+    SET(DOXY_PLATFORM_DEF "ORXONOX_PLATFORM_APPLE ORXONOX_PLATFORM_UNIX")
+  ELSE()
+    SET(DOXY_PLATFORM_DEF "ORXONOX_PLATFORM_LINUX ORXONOX_PLATFORM_UNIX")
+  ENDIF()
+  IF(MSVC)
+    SET(DOXY_COMPILER_DEF "ORXONOX_COMPILER_MSVC")
+  ELSE()
+    SET(DOXY_COMPILER_DEF "ORXONOX_COMPILER_GCC")
+  ENDIF()
+
+  IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in)
+    # use (configured) doxy.config from (out of place) BUILD tree:
+    SET(DOXY_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
+    SET(DOXY_LOGFILE ${CMAKE_CURRENT_BINARY_DIR}/doxy.log)
+    CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.config @ONLY)
+  ELSE()
+    MESSAGE(FATAL_ERROR "Warning: Could not find dox.config.in in the root directory.")
+  ENDIF()
+
+  ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG})
+
+  # create a windows help .chm file using hhc.exe
+  # HTMLHelp DLL must be in path!
+  # fallback: use hhw.exe interactively
+  IF(WIN32)
+    FIND_PACKAGE(HTMLHelp)
+    IF(HTML_HELP_COMPILER)
+      SET(TMP ${DOXY_OUTPUT_DIR}/html/index.hhp)
+      STRING(REGEX REPLACE "/" "\\\\" HHP_FILE ${TMP})
+      ADD_CUSTOM_TARGET(doc_chm ${HTML_HELP_COMPILER} ${HHP_FILE})
+      ADD_DEPENDENCIES(doc_chm doc)
+      # Adding a dependency somehow adds doc target as default build target
+      SET_TARGET_PROPERTIES(doc doc_chm PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE)
+    ENDIF(HTML_HELP_COMPILER)
+  ENDIF (WIN32)
+
+
+  # Installation
+  INSTALL(
+    FILES ${DOXY_CONFIG} ${CMAKE_CURRENT_BINARY_DIR}/doxy.log
+    DESTINATION ${DOC_INSTALL_DIRECTORY}/api OPTIONAL
+  )
+  # Install command always needs the directory
+  IF(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/html)
+    FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html)
+  ENDIF()
+  INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
+    DESTINATION ${DOC_INSTALL_DIRECTORY}/api
+  )
+ENDIF(DOXYGEN_FOUND)
Index: /code/branches/RacingBots_FS18/doc/api/Groups.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/Groups.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/Groups.dox	(revision 11817)
@@ -0,0 +1,167 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @defgroup Util Util
+
+    The util library contains several functions, classes, and templates that can be used in different
+    parts of the Orxonox-code. They provide functionalities for mathematical use, string manipulation,
+    typeconversion, multi-types, error- and exception-handling, debug output, and many more.
+*/
+
+/**
+    @defgroup Core Core
+
+    The core library contains the framework of Orxonox - all important classes, functions, and macros
+    that are used to create and manage classes and objects. Almost all classes in Orxonox need at least
+    one of the core features.
+*/
+
+/**
+    @defgroup Class Class management
+    @ingroup Core
+*/
+
+/**
+    @defgroup Object Object management
+    @ingroup Core
+*/
+
+/**
+    @defgroup Command Command
+    @ingroup Core
+*/
+
+/**
+    @defgroup Config Config
+    @ingroup Core
+*/
+
+/**
+    @defgroup Input Input
+    @ingroup Core
+*/
+
+/**
+    @defgroup Management Management
+    @ingroup Core
+*/
+
+/**
+    @defgroup XML XML
+    @ingroup Core
+*/
+
+/**
+    @defgroup Network Network
+
+    The network library is used to connect clients and server, to synchronize objects and variables, and
+    to transmit network function calls. It contains the central @ref orxonox::Server "Server" and
+    @ref orxonox::Client "Client" classes as well as several functions and macros for
+    @ref orxonox::Synchronisable "synchronisable" classes.
+*/
+
+/**
+    @defgroup Tools Tools
+
+    The tools are a bunch of utilities that belong to the Orxonox library, but are independent of other
+    features.
+*/
+
+/**
+    @defgroup Orxonox Orxonox
+
+    The Orxonox library contains the central and most important classes of the game. Managers, interfaces,
+    base-classes, and more are located in Orxonox. More specialized classes that inherit of the base-classes
+    in Orxonox are often sourced out to the modules.
+*/
+
+/**
+    @defgroup Modules Modules
+
+    The modules are libraries that depend on the Orxonox library and that are loaded dynamically on runtime
+    (in contrast to statically loaded libraries like util and core). Each module contains some classes that
+    are usually connected to each other, but they are independent of other modules. However modules can still
+    link to other modules, but only in a hierarchical order, no circular dependencies.
+*/
+
+/**
+    @defgroup Designtools Designtools
+    @ingroup Modules
+*/
+
+/**
+    @defgroup Notifications Notifications
+    @ingroup Modules
+*/
+
+/**
+    @defgroup Objects Objects
+    @ingroup Modules
+
+    @defgroup Collisionshapes Collisionshapes
+    @ingroup Objects
+
+    @defgroup Eventsystem Eventsystem
+    @ingroup Objects
+
+    @defgroup Triggers Triggers
+    @ingroup Objects
+*/
+
+/**
+    @defgroup Overlays Overlays
+    @ingroup Modules
+*/
+
+/**
+    @defgroup Pickup Pickup
+    @ingroup Modules
+*/
+
+/**
+    @defgroup Pong Pong
+    @ingroup Modules
+
+    Pong is a minigame.
+*/
+
+/**
+    @defgroup Portals Portals
+    @ingroup Modules
+*/
+
+/**
+    @defgroup Questsystem Questsystem
+    @ingroup Modules
+*/
+
+/**
+    @defgroup Weapons Weapons
+    @ingroup Modules
+*/
Index: /code/branches/RacingBots_FS18/doc/api/doxy.config.in
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/doxy.config.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/doxy.config.in	(revision 11817)
@@ -0,0 +1,1582 @@
+# Doxyfile 1.6.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "@PROJECT_NAME@"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         = "@ORXONOX_VERSION@ Codename: @ORXONOX_VERSION_NAME@"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = "@DOXY_OUTPUT_DIR@"
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        = "@CMAKE_SOURCE_DIR@/src" \
+                         "@CMAKE_BINARY_DIR@/src"
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = "@DOXYGEN_INCLUDE_DIRECTORIES@"
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = YES
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = YES
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE            =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = @DOXY_WARN_FORMAT@
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           = @DOXY_LOGFILE@
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = "@CMAKE_SOURCE_DIR@/src" \
+                         "@CMAKE_CURRENT_SOURCE_DIR@" \
+                         "@CMAKE_BINARY_DIR@/src/OrxonoxConfig.h" \
+                         "@CMAKE_BINARY_DIR@/src/SpecialConfig.h" \
+                         "@INTERNAL_DOCFILE@"
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = *.cpp \
+                         *.cc \
+                         *.c \
+                         *.h \
+                         *.hpp \
+                         *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = "@CMAKE_SOURCE_DIR@/src/external/bullet/" \
+                         "@CMAKE_SOURCE_DIR@/src/external/cpptcl/" \
+                         "@CMAKE_SOURCE_DIR@/src/libraries/core/command/IOConsoleWindows.h" \
+                         "@CMAKE_SOURCE_DIR@/src/libraries/core/command/IOConsoleWindows.cc" \
+                         "@CMAKE_SOURCE_DIR@/src/libraries/tools/bsp" \
+                         "@CMAKE_SOURCE_DIR@/src/external/enet/docs" \
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = */.svn/*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = orxonox::detail
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           = "@CMAKE_CURRENT_SOURCE_DIR@/examples/"
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *.cpp \
+                         *.cc \
+                         *.h \
+                         *.hh \
+                         INSTALL DEPENDENCIES CHANGELOG LICENSE LGPL
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             = "@CMAKE_CURRENT_SOURCE_DIR@/images/"
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 2
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+#  plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = @LATEX_COMPILER@
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = @MAKEINDEX_COMPILER@
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = YES
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = YES
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = NO
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           = #@DOXYGEN_INCLUDE_DIRECTORIES@
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             = DOXYGEN_SHOULD_SKIP_THIS \
+                         @DOXY_PLATFORM_DEF@ \
+                         @DOXY_COMPILER_DEF@
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = "@DOXY_OUTPUT_DIR@/html/@PROJECT_NAME@.TAGFILE"
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = "@DOXYGEN_DOT_EXECUTABLE_PATH@"
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           = "@CMAKE_CURRENT_SOURCE_DIR@/dot"
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 1000
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
Index: /code/branches/RacingBots_FS18/doc/api/groups/Notifications.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/groups/Notifications.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/groups/Notifications.dox	(revision 11817)
@@ -0,0 +1,64 @@
+/**
+    @addtogroup Notifications Notifications
+    @ingroup Modules
+
+    @ref orxonox::Notification "Notifications" are short messages, that can be sent from anywhere in Orxonox and then are displayed on the screen to inform the user about some occurence he has to know about. Such an occurence could be, that he just shot and killed his Archnemesis Overlord3, that he just got a new Pickup or that he received a Quest and needs to have a look at the Quest-Menu.
+
+    @section NotificationsUsage Usage
+    Let's very briefly talk about what you have to do to either send @ref orxonox::Notification "Notifications" from some part of Orxonox or display Notifications on your screen.
+
+    @subsection NotifictionsSending Sending notifications
+    Sending a new @ref orxonox::Notification "Notification" from (almost) anywhere in Orxonox is fairly easy.
+    You first have to decide on a message, it shouldn't be too long but be long enough to get your point accross.
+    Then you have to decide on a sender. The sender is a string by which the different @ref orxonox::NotificationQueue "NotificationQueues" (the entities that display the @ref orxonox::Notification "Notifications") can decide whether they should display the @ref orxonox::Notification "Notification" or not. So the sender is some string that identifies a group of @ref orxonox::Notification "Notifications" that have something in common or some entity that is sending them. For example: All @ref orxonox::Notification "Notifications" sent by any part of the Questsystem have "questsystem" as sender and thus we could create a @ref orxonox::NotificationQueue "NotificationQueue" that only displays @ref orxonox::Notification "Notifications" from the Questsystem, but more to that later.
+    And lastly you have to decide to whom you want to send this @ref orxonox::Notification "Notification". You have to get the clientId of the intended recipient (e.g. trough a @ref orxonox::PlayerInfo "PlayerInfo") or you only send the @ref orxonox::Notification "Notification" locally, either by setting the clientId to Host::getPlayerID() or by setting the variable 'isLocal' to true, and setting clientId to what ever you want, since it will be ignored.
+    Once you have decided all that you can send the Notification by calling:
+    @code
+    NotificationManager::sendNotification(message, clientId, sender, isLocal); // isLocal = false can be ommitted since that is the default value.
+    @endcode
+
+    @subsection NotificationsDisplay Displaying notifications
+    Displaying @ref orxonox::Notification "Notifications" is even easier, all you need to do is to load the NotificationLayer in the level, where you want @ref orxonox::Notification "Notifications" displayed. You can either do this manually by executing the following command in the console:
+    @code
+    showGUI NotificationLayer false true
+    @endcode
+    Or automatically, by adding a @ref orxonox::Script "Script" to the levelfile that does it for you:
+    @code
+    <Script code="showGUI NotificationLayer false true" needsGraphics="true" />
+    @endcode
+
+    If you want to change the way the @ref orxonox::Notification "Notifications" are displayed, you can enter the (at this point rather rudimentary) edit mode and add new @ref orxonox::NotificationQueue "NotificationQueues" or change position and properties of the existing ones, by executing the following command in the console:
+    @code
+    enterEditMode
+    @endcode
+
+    @section NotificationsTechincalDetails Technical details
+    The Notifications module has three major parts that interact with each other. First there is the @ref orxonox::NotificationQueue "NotificationQueue", this is the entity that (logically, not effectively) displays @ref orxonox::Notification "Notifications" according to some rules, then there is the NotificationLayer, which is the GUI which (actually) displays @ref orxonox::Notification "Notifications" by visualizing the @ref orxonox::NotificationQueue "NotificationQueues" and as a result also the @ref orxonox::Notification "Notifications", that are displayed by the respective @ref orxonox::NotificationQueue "NotificationQueues" and lastly there is the @ref orxonox::NotificationManager "NotificationManager", which connects these two.
+
+    @subsection NotificationQueue NotificationQueue
+    The @ref orxonox::NotificationQueue "NotificationQueue" is the entity, that (as said earlier) logically displays @ref orxonox::Notification "Notifications". Furthermore a @ref orxonox::NotificationQueue "NotificationQueue" displays only a subset of all the @ref orxonox::Notification "Notifications". The parameters that reduce the range of displayed @ref orxonox::Notification "Notifications" are:
+    - @b senders The senders, the set of targets of a @ref orxonox::NotificationQueue "NotificationQueue" is the set of senders a @ref orxonox::NotificationQueue "NotificationQueue" displays  @ref orxonox::Notification "Notifications" from. E.g. If one would set the senders to "questsystem" then only  @ref orxonox::Notification "Notifications" from the Questsystem would be displayed in that particular queue. If you set senders to "all" then all Notifications will be displayed. Different senders can be concatinated with commas.
+    - @b size The size specifies how many @ref orxonox::Notification "Notifications" are displayed at the most, if there are more @ref orxonox::Notification "Notifications" that could be displayed, then only the most recent are displayed.
+    - @b displayTime The display time specifies how long a @ref orxonox::Notification "Notification" is displayed at the most.
+
+    @subsection NotificationLayer NotificationLayer
+    The NotificationLayer is a GUI sheet, that displays all the @ref orxonox::NotificationQueue "NotificationQueues" and their @ref orxonox::Notification "Notifications". In its normal mode of operation it is transparent to input, meaning that it only functions as a means of displaying, however if switched to edit mode the NotificationLayer no longer is transparent to input and allows for the adding, removal and modification of @ref orxonox::NotificationQueue "NotificationQueues". For every @ref orxonox::NotificationQueue "NotificationQueue" there is the equivalent representation in the NotificationLayer. So @ref orxonox::NotificationQueue "NotificationQueues" are not each represented by a GUI sheet, but thely all belong to one and the same GUI sheet, the NotificationLayer.
+
+    @subsection NotificationManager NotificationManager
+    The @ref orxonox::NotificationManager "NotificationManager" is (hence the name) the managing entity in this setting. It is responsible for the registering and unregistering of @ref orxonox::NotificationListener "NotificationListeners" (which the @ref orxonox::NotificationQueue "NotificationQueue" is) and also informs them about changes related to @ref orxonox::Notification "Notifications". It is also responsible for the creation and destruction of @ref orxonox::NotificationQueue "NotificationQueues" through the NotificationLayer and is also the point of approach for the NotificationLayer to get information it needs to display the queues. Finally the @ref orxonox::NotificationManager "NotificationManager" is responsible for sending (and in the process creating) @ref orxonox::Notification "Notifications" and is a means for the @ref orxonox::NotificationQueue "NotificationQueues" to get the information they need about @ref orxonox::Notification "Notifications".
+
+    @subsection Notification Notification
+    The @ref orxonox::Notification "Notification" class is more or less a data structure that groups the notification message and the sender, and possibly other future parameters, together to form a comprehensive structure that we call Notification.
+
+    Additionally there is another important class of objects belonging to the Notifications module. The @ref orxonox::NotificationDispatcher "NotificationDispatchers".
+
+    @subsection NotificationDispatcher NotificationDispatcher
+    @ref orxonox::NotificationDispatcher "NotificationDispatchers" are entities that are instantiated in a level file (through XML) and that dispatch (or send) a specific @ref orxonox::Notification "Notification" upon having received a triggering event.
+
+    @defgroup NotificationDispatchers Dispatchers
+    @ingroup Notifications
+
+    @ref orxonox::NotificationDispatcher "NotificationDispatchers" are entities that are instantiated in a level file (through XML) and that dispatch (or send) a specific @ref orxonox::Notification "Notification" upon having received a triggering event.
+
+    At this point there are two @ref orxonox::NotificationDispatcher "NotificationDispatchers", the @ref orxonox::SimpleNotification "SimpleNotification", which just displays a specified message, and the @ref orxonox::CommandNotification "CommandNotification" which displays a message with a binding for a specified command in it.
+*/
Index: /code/branches/RacingBots_FS18/doc/api/groups/Pickup.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/groups/Pickup.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/groups/Pickup.dox	(revision 11817)
@@ -0,0 +1,221 @@
+/**
+    @addtogroup Pickup Pickup
+    @ingroup Modules
+
+    The Pickup module adds a special type of object to Orxonox, the so-called @ref orxonox::Pickupable "Pickupables". @ref orxonox::Pickupable "Pickupables" are objects that can be picked up (by virtually any entity, but commonly by the @ref orxonox::Pawn "Pawn") and have some kind of effect on the entity that picked the @ref orxonox::Pickupable "Pickupable" up.
+
+    @section IncludingPickups Including pickups in a level
+    @ref orxonox::Pickupable "Pickupables" are designed so that they can be included in levels fairly easily, while also ensuring, that the pickup itself (its game-logic component) and how it is represented (e.g. in the PickupInventory (the GUI that displays @ref orxonox::Pickupable "Pickupables") or in the game) are neatly seperated.
+    To be able to use @ref orxonox::Pickupable "Pickupables" in a level one must understand some basic concepts.
+    - @ref orxonox::Pickupable "Pickupables" are entities which (by itself) have no physical (or graphical) dimension. The simply represent the effect they will have on a @ref orxonox::PickupCarrier "PickupCarrier" (the entity that can pick up @ref orxonox::Pickupable "Pickupables", @ref orxonox::Pawn "Pawn" for example inherits from @ref orxonox::PickupSpawner "PickupSpawner" and thus is able to pick up and carry @ref orxonox::Pickupable "Pickupables"), when used and the mechanism that leads to that.
+    - The physical (or graphical) dimension of a pickup is called a @ref orxonox::PickupRepresentation "PickupRepresentation".
+    - The @ref orxonox::PickupRepresentation "PickupRepresentation" of a @ref orxonox::Pickupable "Pickupable" and the @ref orxonox::Pickupable "Pickupable" itself are linked to each other, in such a way that a @ref orxonox::PickupRepresentation "PickupRepresentation" can only represent one type of @ref orxonox::Pickupable "Pickupable".
+    - A type of @ref orxonox::Pickupable "Pickupable" is a specific pickup class (inheriting from @ref orxonox::Pickupable "Pickupable") with specific values for all its relevant parameters. This means, that a pickup of the same class with the same values for all parameters except for one is a different type of pickup and will therefore have a different @ref orxonox::PickupRepresentation "PickupRepresentation". Which parameters are the ones relevant to destinguish between two types of pickups can be defined in the class description of the specific pickup.
+    - The entity that actually gives a @ref orxonox::Pickupable "Pickupable" to a @ref orxonox::PickupCarrier "PickupCarrier" is called a @ref orxonox::PickupSpawner "PickupSpawner". A @ref orxonox::PickupSpawner "PickupSpawner" creates (based on some parameters) @ref orxonox::Pickupable "Pickupables" which then is picked up by the @ref orxonox::PickupCarrier "PickupCarrier", that caused the @ref orxonox::PickupSpawner "PickupSpawner" to spawn a new pickup. How the spawner looks in the game is defined by the @ref orxonox::PickupRepresentation "PickupRepresentation" of the @ref orxonox::Pickupable "Pickupable" it spawns.
+
+    @subsection UsingPredifinedPickups Using predefined pickups
+    There is a file called <code>pickupRepresentationTemplates.oxt</code> in <code>levels/templates</code>, which holds the templates for the @ref orxonox::PickupRepresentation "PickupRepresentations" and also templates for @ref orxonox::Pickupable "Pickupables". The templates for the @ref orxonox::PickupRepresentation "PickupRepresentations" define the @ref orxonox::StaticEntity "StaticEntities" that are attached to the @ref orxonox::PickupSpawner "PickupSpawners" to make them look like the @ref orxonox::Pickupable "Pickupable" they are spawning. The templates for the @ref orxonox::Pickupable "Pickupables" can be added just for ease of use.
+    If you want to use pickups you will have to include this file in your level file, somewhere above the Level-tag.
+    @code
+    <?lua
+        include("templates/pickupRepresentationTemplates.oxt")
+    ?>
+    ...
+    <Level>
+    ...
+    @endcode
+    There is another file called <code>pickups.oxi</code> in <code>level/includes</code> which creates all @ref orxonox::PickupRepresentation "PickupRepresentations" needed for the @ref orxonox::Pickupable "Pickupable" supplied by the <code>pickupRepresentationTemplates.oxt</code> file. This file will have to be included as well. It has to be somewhere after the opening Scene-tag and your first use of a pickup.
+    @code
+    <Scene>
+    ...
+    <?lua
+        include("includes/pickups.oxi")
+    ?>
+    @endcode
+    After that all the predefined pickups specified in those two files can be used just by creating a @ref orxonox::PickupSpawner "PickupSpawner" for them in the respective level.
+    For example:
+    @code
+    <PickupSpawner position="-100,0,-100" respawnTime="30" maxSpawnedItems="10">
+        <pickup>
+            <HealthPickup
+                health = 10
+                healthType = "limited"
+                activationType = "immediate"
+                durationType = "once"
+            />
+        </pickup>
+    </PickupSpawner>
+    @endcode
+    Please be aware, that the @ref orxonox::Pickupable "Pickupable" specified for the @ref orxonox::PickupSpawner "PickupSpawner", has to be exactly the same (including all parameters) to the one specified in the <code>pickups.oxi</code> file.
+    To make things simpler, one could just use the templates specified in the <code>pickupRepresentationTemplates.oxt</code> file. Which, following the previous example, would look like this:
+    @code
+    <PickupSpawner position="-100,0,-100" respawnTime="30" maxSpawnedItems="10">
+        <pickup>
+            <HealthPickup template="smallhealthpickup" />
+        </pickup>
+    </PickupSpawner>
+    @endcode
+
+    @subsection UnsingNon-PredefinedPickups Using non-predefined pickups
+    To include a type of pickup (which, as we remember, is the class of the @ref orxonox::Pickupable "Pickupable" with specific values for all the relevant parameters) in a level file, you can just create a new @ref orxonox::PickupSpawner "PickupSpawner" and specify the @ref orxonox::Pickupable "Pickupable".
+    @code
+    <PickupSpawner position="-100,0,-100" respawnTime="30" maxSpawnedItems="10">
+    <pickup>
+        <HealthPickup
+            health = 33
+            healthType = "limited"
+            activationType = "immediate"
+            durationType = "once"
+        />
+    </pickup>
+    </PickupSpawner>
+    @endcode
+    As can be seen in the <code>pickupRepresentationTemplates.oxt</code> file and the <code>pickups.oxi</code> file there is no @ref orxonox::PickupRepresentation "PickupRepresentation" defined for this type of pickup. Thus the default representation will be used.
+
+    To create an appropriate @ref orxonox::PickupRepresentation "PickupRepresentation" for the inserted pickup above, you can just create a @ref orxonox::PickupRepresentation "PickupRepresentation" within the scene (Within the Scene-tags).
+    @code
+    <PickupRepresentation
+        name = "My new health pickup"
+        description = "This is an awesome new health pickup."
+        spawnerTemplate = "mediumhealthpickupRepresentation"
+        inventoryRepresentation = "MediumHealth"
+    >
+        <pickup>
+            <HealthPickup
+            health = 33
+            healthType = "limited"
+            activationType = "immediate"
+            durationType = "once"
+        />
+        </pickup>
+    </PickupRepresentation>
+    @endcode
+    Notice, that the type of pickup specified for the @ref orxonox::PickupRepresentation "PickupRepresentation", naturally, needs to be the same (this is the way they can be connected). Also, we just used an existing <em>spawnerTemplate</em>, to make things simpler.
+
+    The next step is to create a <em>spawnerRepresentation</em> uniquely for our new type of pickup. Lets call it <code>newhealthpickupRepresentation</code>. Thus the parameter <em>spawnerTemplate</em> of the @ref orxonox::PickupRepresentation "PickupRepresentation" has to be changed to that value.
+    @code
+    spawnerTemplate = "newhealthpickupRepresentation"
+    @endcode
+    The <em>spawnerTemplate</em> defines how the @ref orxonox::PickupSpawner "PickupSpawner" is displayed in a level.
+    In our example case it could look like this:
+    @code
+    <Template name=newhealthpickupRepresentation>
+        <PickupRepresentation>
+            <spawner-representation>
+                <StaticEntity>
+                    <attached>
+                        -- Here you can put all the objects which define the look of the spawner. --
+                    </attached>
+                </StaticEntity>
+            </spawner-representation>
+        </PickupRepresentation>
+    </Template>
+    @endcode
+    Please refer to the <code>pickupRepresentationTemplates.oxt</code> for more examples.
+
+    The @ref orxonox::PickupRepresentation "PickupRepresentation" also needs another parameter the <em>inventoryRepresentation</em>. This parameter defined how the @ref orxonox::Pickupable "Pickupable" is displayed in the PickupInventory (a menu to browse the currently equipped pickups).
+    @code
+    inventoryRepresentation = "MediumHealth"
+    @endcode
+    This is the name of an image defined in the PickupInventory imageset (<code>PickupInventory.imageset</code>), which can be found in <code>data_extern/gui/imagesets</code>.
+
+    This is all that has to be done. Now you have a new pickup type with an appropriate @ref orxonox::PickupRepresentation "PickupRepresentation" for your use. If you feel that your pickup is useful in general, please don't hesitate to create a template for the pickup and add your pickup to the <code>pickupRepresentationTemplates.oxt</code> file and the <code>pickups.oxi</code> file, so that anyone who wants to use it can do so quite easily.
+
+    There is also an additional way to create new types of pickups to be used in a level (without having to do any coding). There is a @ref orxonox::Pickupable "Pickupable" called the @ref orxonox::PickupCollection "PickupCollection", which is just a collection (hence the name) of @ref orxonox::Pickupable "Pickupables" (more precisely of @ref orxonox::CollectiblePickup "CollectiblePickups"), behaving as if it was just one @ref orxonox::Pickupable "Pickupable".
+    A @ref orxonox::PickupCollection "PickupCollection" can be created as follows:
+    @code
+    <PickupCollection>
+        <pickupables>
+            -- some pickups you want to have in your collection, e.g. --
+            <HealthPickup template=smallhealthpickup />
+            <HealthPickup health=50 healthRate=5 durationType=continuous activationType=immediate healthType=limited />
+        </pickupables>
+    </PickupCollection>
+    @endcode
+    Of which types of pickups a collection is made up is entirely up to the one creating the @ref orxonox::PickupCollection "PickupCollection", they can be mixed freely.
+
+    @section CreatingAPickup Creating a new pickup
+    Things have been fairly straightforward so far. Creating a @ref orxonox::Pickupable "Pickupable" form scratch isn't as easy. Therefore I'm just going to supply you with a recipe, or a set of steps you have to take, without which your pickup won't work and point out some common pitfalls.
+
+    @subsection CreatingAPickupClass Creating the class
+    For a new @ref orxonox::Pickupable "Pickupable" you need to create a new class in <code>>modules/pickup/items</code>. Your class needs to be derived from another pickup class, normally this would either be @ref orxonox::Pickupable "Pickupable", @ref orxonox::CollectiblePickup "CollectiblePickup" or @ref orxonox::Pickup "Pickup". @ref orxonox::Pickupable "Pickupable" is (as mentioned earlier) the base class of all things that can be picked up, thus of all pickups. @ref orxonox::CollectiblePickup "CollectiblePickup" is a (directly) derived class of @ref orxonox::Pickupable  "Pickupable" and provides the additional functionality of enabling your pickup to be used in a @ref orxonox::PickupCollection "PickupCollection". However you are probably going to want to derive your class form @ref orxonox::Pickup "Pickup", because it is a @ref orxonox::CollectiblePickup "CollectiblePickup" and provides some useful methods. So have a look at @ref orxonox::Pickup "Pickup".
+    Once you have created your new pickup class you have to insert it in the <code>PickupPrereqs.h</code> file in the <code>modules/pickup</code> folder and in the <code>CMakeList.txt</code> file in the <code>modules/pickup/items</code> folder. Also have a look at other pickups to make sure you include all the necessary files in your class.
+
+    @subsection ChoosingTheCarriers Coosing the carriers
+    You also have to choose the entities that are allowed to pick your pickup up. After you have chosen the entity that carries your pickup, you need to do the following.
+    - The enity that carries your pickup needs to be derived from the @ref orxonox::PickupCarrier "PickupCarrier" interface. And you need to implement the @ref orxonox::PickupCarrier "PickupCarriers'" virtual functions <code>getCarrierChildren()</code> and <code>getCarrierParent()</code>. These tow methods are needed, because all pickups are initially picked up by a @ref orxonox::Pawn "Pawn" and then handed down to the entity that effectively carries them. With the above mentioned two function just that is accomplished. A hierarchical structure is established with one parent and a set of children, where the @ref orxonox::Pawn "Pawn" is the root node of this hierarchical structure, the only entity with no parent.
+    - Once you have done that you will also want to specify in your pickup which carriers can pick it up, this is done via the <code>addTarget()</code> function. So you have to make sure the target is added whenever one of your pickups is created (so, most conveniently somewhere in the constructor), with the following command.
+    @code
+    this->addTarget(ClassIdentifier<MyCarrierClass>::getIdentifier());
+    @endcode
+
+    @subsection CreatingTheInnerWorkings Creating the inner workings of your pickup
+    @todo This is completely outdated. Someone who knows how pickups work should update this.
+    
+    Now that we have the skeleton of a pickup and we have defined which carriers are allowed to pick our pickup up we are going to take a look at all the methods we can (or sometimes have to) overload from @ref orxonox::Pickupable "Pickupable", for our pickup to work properly. But first I will introduce some more concepts to make the need for these methods more obvious.
+    - Since one pickup class can by itself be many pickup types, we need a way to find out whether a particular instance of a pickup is of the same type as another instance of a pickup. To that end the @ref orxonox::PickupIdentifier "PickupIdentifier" was created. The @ref orxonox::PickupIdentifier "PickupIdentifier" accounts for the type of class your pickup is of and also for the parameters (and their values) that distinguish different types of pickups of the same class. Much of the functionality of the pickup module relies on this identifier being correct, thus it is very important to initialize it correctly. (We will see, how that is done in a short while.)
+    - Every @ref orxonox::Pickupable "Pickupable" has at least two states which are very important. The first is, whether the @ref orxonox::Pickupable "Pickupable" is currently in use or not and the second is whether the pickup is currently picked up or not.
+
+    Let's have a look at the important methods.
+    - <b>changedUsed()</b> The <code>changedUsed()</code> method is called whenever the state of the @ref orxonox::Pickupable "Pickupable" transits from being used to not being used or the other way around. Which means this method is probably the most important method you have at your fingertips, since it enables you to apply the effect of your pickup when it gets used and remove the effect as soon as it is no longer in use.
+    - <b>changedPickedUp()</b> The <code>changedPickedUp()</code> method is called whenever the state of the @ref orxonox::Pickupable "Pickupable" changes from being picked up to not being picked up or the other way around. For example if you want your pickup to be used as soon as it is picked up, this is the method you have to overload to achieve that behavior (or just let your pickup be derived from @ref orxonox::Pickup "Pickup", which implements exactly that behavior, if the <em>activationType</em> is set to <em>immediate</em>). You don't have to concern yourself with destroying the pickup or creating a spawner when it changes to not picked up, since that is already implemented with the @ref orxonox::Pickupable "Pickupable" and @ref orxonox::PickupCarrier "PickupCarrier" classes. If you want a different behavior, however, once again, this is the method.
+    - <b>changedCarrier()</b> The <code>changedCarrier()</code> method is called whenever the carrier of the @ref orxonox::Pickupable "Pickupable" changes. And by that I don't mean the class that is allowed to carry the pickup, but the object that actually carries (or carried) the pickup. Please do not overload this class to implement behavior for picked up -> not picked up transitions, use <code>changedPickedUp()</code> for that. For most pickup classes this method doesn't need to be overloaded. Where it is used, however is in the @ref orxonox::PickupCollection "PickupCollection" class, where the new carrier needed to be communicated to all pickups the collection consists of, whenever the carrier was changed.
+
+    Please be aware, that these three methods are methods registered with @ref Super.h "Super", meaning, that whenever overloading them, don't forget to call <code>SUPER(MyClass, myMethod);</code>.
+    Also when implementing the above methods you should think of what should happen in unexpected situations, e.g. when your pickup is unused manually and set to used again.
+    Additionally you should use the <code>destroy()</code> method of Pickupable instead of the method provided by @ref orxonox::OrxonoxClass "OrxonoxClass", meaning <code>Pickupable::destroy()</code> instead of plain <code>destroy()</code>.
+
+    - <b>clone()</b> The <code>clone()</code> method creates a new pickup of the same type as the pickup it is cloned from. So the cloned pickup is not exactly the same, as it doesn't necessarily completely reflect the status of the pickup it is cloned from, but it reflects all the parameters and their values, that distinguish different types of this pickup class. It needs to be implemented by every pickup class. And it is best if this is done in a very specific way. Below is shown how:
+    @code
+    void MyPickup::clone(OrxonoxClass*& item)
+    {
+        if(item == NULL)
+            item = new MyPickup(this);
+
+        SUPER(MyPickup, clone, item);
+
+        MyPickup* pickup = dynamic_cast<MyPickup*>(item);
+        // Here you should set all the important parameters (that distinguish the different types of this pickup), e.g.
+        pickup->setSomeParameter(this->getSomeParameter());
+        // You must also initialize the identifier of the new pickup, this is normally done in a member function called in
+        pickup->initializeIdentifier();
+    }
+    @endcode
+    - <b>initializeIdentifier()</b> The <code>initializeIdentifier()</code> method initializes (or more simply put, creates) the @ref orxonox::PickupIdentifier "PickupIdentifier" of the instance of your pickup. Since the important values of the parameters are not yet available in the constructor of your pickup this <code>initializeIdentifier()</code> method must be called as soon as they are available, which normally is in the <code>XMLPort()</code> method, and the <code>clone()</code> method, as seen above. In the <code>initializeIdentifier()</code> method you need to register each parameter that is important for the type of your pickup to its identifier, this is normally done as follows:
+    @code
+    void Pickup::initializeIdentifier(void)
+    {
+        // If the get method returns a string.
+        std::string val1 = this->getSomeParameter();
+        std::string type1 = "someParameter";
+        this->pickupIdentifier_->addParameter(type1, val1);
+        // If the get method doesn't return a string
+        std::stringstream stream;
+        stream << this->getSomeOtherParameter();
+        std::string type2 = "someOtherParameter";
+        std::string val2 = stream.str();
+        this->pickupIdentifier_->addParameter(type2, val2);
+    }
+    @endcode
+
+    Be aware, this only works for parameters that are simple enough, meaning with pointers for example it will, naturally, not work, and other ways must be found (this is for example done in @ref orxonox::PickupCollection "PickupCollection" with a derived class of the @ref orxonox::PickupIdentifier "PickupIdentifier", the @ref orxonox::PickupCollectionIdentifier "PickupCollectionIdentifier") or in the @ref orxonox::DronePickup "DronePickup" class by using a @ref orxonox::Template "Template".
+    - <b>createSpawner()</b> The <code>createSpawner()</code> method needs to be implemented by any pickup directly inheriting from @ref orxonox::Pickupable "Pickupable" (or directly from @ref orxonox::CollectiblePickup "CollectiblePickup"), so if you inherit from @ref orxonox::Pickup "Pickup", you don't need to implement this. It is used to create a @ref orxonox::PickupSpawner "PickupSpawner", when the pickup is dropped. A standard implementation would look like this.
+    @code
+    bool MyPickup::createSpawner(void)
+    {
+        new DroppedPickup(this, this, this->getCarrier());
+        return true;
+    }
+    @endcode
+
+    @section PickupTechnicalDetails Technical details
+
+    @image html pickupmodule.png
+*/
+
+/**
+    @defgroup PickupItems Items
+    @ingroup Pickup
+
+    The actual pickups can be found here.
+*/
Index: /code/branches/RacingBots_FS18/doc/api/groups/Portals.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/groups/Portals.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/groups/Portals.dox	(revision 11817)
@@ -0,0 +1,61 @@
+/**
+    @addtogroup Portals Portals
+    @ingroup Modules
+
+    This module allows you to place @ref orxonox::PortalEndPoint "PortalEndPoints" in space and connect pairs of them with a @ref orxonox::PortalLink "PortalLink" in order to allow fast travelling from A to B.
+
+    @section FastHowTo Fast HowTo: Including portals in a level
+    The simplest way to use portals is show by the following piece of xml-code
+    @code
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Billboard material="Portals/Default" />
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="0,0,0" id="1" design="PortalDefault"/>
+    <PortalEndPoint position="-100,0,0" id="2" design="PortalDefault"/>
+    <PortalLink fromID="1" toID="2" />
+    @endcode
+    This
+     - creates two @ref orxonox::PortalEndPoint "PortalEndPoints", one at 0,0,0 and the other at -100,0,0
+     - makes them visible by attaching a Billboard made of the "Portals/Default" material to each of them and
+     - connects them, meaning that any @ref orxonox::Pawn "Pawn" which gets near 0,0,0 is immediately "warped" to -100,0,0 (but not the other way round)
+
+    @section IncludePortals Detailed HowTo: Including portals in a level
+    In the example above some default values are used. The full possibilities are shown below
+    @code
+    <Template name=PortalDefault>
+        <PortalEndPoint>
+            <attached>
+                <Billboard material="Portals/Default" />
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <Template name=PortalBig>
+        <PortalEndPoint>
+            <attached>
+                <Billboard material="Portals/Big" />
+            </attached>
+        </PortalEndPoint>
+    </Template>
+
+    <PortalEndPoint position="0,0,0" id="1" distance="40" target="MobileEntity" design="PortalDefault"/>
+    <PortalEndPoint position="-100,0,0" id="2" distance="40" target="MobileEntity" design="PortalBig"/>
+    <PortalLink fromID="1" toID="2" />
+    <PortalLink fromID="2" toID="1" />
+    @endcode
+
+    step by step
+    @subsection Templates "Templates"
+    In order to make @ref orxonox::PortalEndPoint "PortalEndPoints" visible in the game there must be something visible.
+    The idea (as shown above) is to define or include arbitrary Templates which make a PortalEndPoint visible and use them later by setting the design attribute of a @ref orxonox::PortalEndPoint "PortalEndPoint" to the template name
+    @subsection Parameters "Parameters"
+     - position: 3d-coordinate in space
+     - distance (default: 50): distance at which a valid entity gets pulled in (if the end point is an entrance).
+     - target (default: "Pawn"): the class which is able to enter this end point (if it is an entrance)
+     - design: the name of the @ref orxonox::Template "design template"
+*/
Index: /code/branches/RacingBots_FS18/doc/api/groups/Questsystem.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/groups/Questsystem.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/groups/Questsystem.dox	(revision 11817)
@@ -0,0 +1,197 @@
+/**
+    @addtogroup Questsystem Questsystem
+    @ingroup Modules
+
+    The Questsystem is a module that enhances Orxonox with @ref orxonox::Quest "Quests". @ref orxonox::Quest "Quests" are objects that challenge the player that receives such an object to fulfill some specific task (e.g. Rescue a princess, fetch some rare metal alloy, destroy the evil pirates den, ...). Upon having fulfilled that task the player can be rewarded with some kind of reward. Quests can be hierarchically structured, meaning that to fulfill some @ref orxonox::Quest "Quest" you first have to fulfill all (or some, depending on the quest) sub-quests.
+
+    @section QuestsystemTechnicalDetails Technical details
+    The Questsystem essentially consists of the @ref orxonox::Quest "Quest" entity which is the quest itself (and sub- or helper-entities, such as @ref orxonox::QuestHint "QuestHint" (hints for quests) or @ref orxonox::QuestDescription "QuestDescription" (descriptions for quests and hints, to separate content from function)), the @ref orxonox::QuestEffect "QuestEffect" and @ref orxonox::QuestListener "QuestListener" entities which are the only tools for quests to have any influence on the game world. By enabling quests to have @ref orxonox::QuestEffect "QuestEffects" they are able to (for example) fail or complete other quests, activate hints, give rewards or even add a quest to a player. @ref orxonox::QuestListener "QuestListeners" on the other hand can be used by any object to react to a status change of a quest. The @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" is the physical entity which finally makes quests available for the player in the game, by being able to invoke a @ref orxonox::QuestEffect "QuestEffect" on a player (under some conditions).
+    @image html questsystem.png
+
+    @section CreatingQuests Creating Quests
+
+    @subsection CreatingTheQuestHierarchy Creating the Quest-Hierarchy
+    To start you have to create a Quest-Hierarchy in the XML-Levelfile by hierarchically nesting your quests. There are two types of Quests you can use, the LocalQuest and the GlobalQuest.
+
+    @subsubsection LocalQuest LocalQuest
+    A @ref orxonox::LocalQuest "LocalQuest" is a @ref orxonox::Quest "Quest" which has different states for each player, that means each @ref orxonox::LocalQuest "LocalQuest" can be obtained and completed (or failed) by each player in parallel. A questId is some string that uniquely identifies the quest, this can either be a name or, to ensure uniqueness, you can use a GUID generator (<a href="http://www.google.com/search?q=guid+generator">google</a> or you can use this <a href="http://www.famkruithof.net/uuid/uuidgen">generator</a>). The advantage of GUID is, that you can be quite sure that your id is unique, the drawback is, that it provides less overview and can be quite confusing when looking at the level file. So make your own choice.
+
+    Creating a @ref orxonox::LocalQuest "LocalQuest" in XML goes as follows:
+    @code
+    <LocalQuest id="questId">
+        <QuestDescription title="Title" description="Description." /> //The description of the quest.
+        <subquests>
+            <Quest id ="questId1" /> //A list of n subquest, be aware, each of the <Quest /> tags must have a description and so on and so forth as well.
+            ...
+            <Quest id="questIdn" />
+        </subquests>
+        <hints>
+            <QuestHint id="hintId1" /> //A list of n QuestHints, see QuestHint for the full XML representation of those.
+            ...
+            <QuestHint id="hintIdn" />
+        </hints>
+        <fail-effects>
+            <QuestEffect /> //A list of QuestEffects, invoked when the Quest is failed, see QuestEffect for the full XML representation.
+            ...
+            <QuestEffect />
+        </fail-effects>
+        <complete-effects>
+            <QuestEffect /> //A list of QuestEffects, invoked when the Quest is completed, see QuestEffect for the full XML representation.
+            ...
+            <QuestEffect />
+        </complete-effects>
+    </LocalQuest>
+    @endcode
+
+    @subsubsection GlobalQuest GlobalQuest
+    @ref orxonox::GlobalQuest "GlobalQuests" are different, they can be obtained by every player but the changes made to the @ref orxonox::Quest "Quest" (e.g. completion of the quest) affect all owners of the quest. A short example: There are 3 Players, A, B and C. Player A obtains the quest, a while later player B obtains the quest and completes it. Since it is a @ref orxonox::GlobalQuest "GlobalQuest" it is completed for all players having obtained the Quest which means it is also completed for player A. Player C though, never having obtained the quest, can now never complete it.
+
+    Creating a @ref orxonox::GlobalQuest "GlobalQuest" in XML goes as follows:
+    @code
+    <GlobalQuest id="questId">
+        <QuestDescription title="Title" description="Description." /> //The description of the quest.
+        <subquests>
+            <Quest id ="questId1" /> //A list of n subquest, be aware, each of the <Quest /> tags must have a description and so on and so forth as well.
+            ...
+            <Quest id="questIdn" />
+        </subquests>
+        <hints>
+            <QuestHint id="hintId1" /> //A list of n QuestHints, see QuestHint for the full XML representation of those.
+            ...
+            <QuestHint id="hintIdn" />
+        </hints>
+        <fail-effects>
+            <QuestEffect /> //A list of QuestEffects, invoked on all players possessing this quest, when the Quest is failed, see QuestEffect for the full XML representation.
+            ...
+            <QuestEffect />
+        </fail-effects>
+        <complete-effects>
+            <QuestEffect /> //A list of QuestEffects, invoked on all players possessing this quest, when the Quest is completed, see QuestEffect for the full XML representation.
+            ...
+            <QuestEffect />
+        </complete-effects>
+        <reward-effects>
+            <QuestEffect /> //A list of QuestEffects, invoked on the player completing this quest. See QuestEffect for the full XML representation.
+            ...
+            <QuestEffect />
+        </reward-effects>
+    </GlobalQuest>
+    @endcode
+
+    As you may see that another difference between a @ref orxonox::GlobalQuest "GlobalQuest" and a @ref orxonox::LocalQuest "LocalQuest" is, that with a @ref orxonox::GlobalQuest "GlobalQuest" having @ref orxonox::AddReward "RewardEffects", the RewardEffects are only executed on the player completing the quest. Additionally @ref orxonox::CompleteQuest "CompleteEffects" are executed on all players having obtained the quest before it was completed, when it is completed., while with a @ref orxonox::LocalQuest "LocalQuest" each player that completes a quest, completes it for himself alone, but also gets the reward, regardless whether another player completed the quest before him.
+
+    @subsubsection QuestHint QuestHint
+    @ref orxonox::QuestHint "QuestHints" can be used to give a player useful information for @ref orxonox::Quest "Quests" he is working on completing. @ref orxonox::QuestHint "QuestHints" cannot have any side effects, but also have an identifier which follows the same form as in the @ref orxonox::Quest "Quests".
+
+    Creating a @ref orxonox::QuestHint "QuestHint" in XML goes as follows:
+    @code
+    <QuestHint id="hintId">
+        <QuestDesctription title="" description="" />
+    </QuestHint>
+    @endcode
+
+    @subsubsection QuestDescription QuestDescription
+    Each @ref orxonox::Quest "Quest" (and also each @ref orxonox::QuestHint "QuestHint") must have a @ref orxonox::QuestDescription "QuestDescription" consisting of a title and description, and for @ref orxonox::Quest "Quests" also messages for the event the quest is either failed or completed. Of course these are (as is the title and the description) optional.
+
+    Creating a @ref orxonox::QuestDescription "QuestDescription" in XML goes as follows:
+    @code
+    <QuestDescription title="Title" description="Description Text" failMessage="You fail." completeMessage="You win!" />
+    @endcode
+
+    @subsection CreatingSideEffects Creating side effects
+    @ref orxonox::Quest "Quests" can have side effects, in fact that is mostly what they are about. This means that they can have an influence on the game world. @ref orxonox::Quest "Quests" do that through two distinct devices, @ref orxonox::QuestEffect "QuestEffects" (active) and @ref orxonox::QuestListener "QuestListeners" (passive).
+
+    @subsubsection QuestEffect QuestEffect
+    A @ref orxonox::QuestEffect "QuestEffect" is the first (and probably most important) device for @ref orxonox::Quest "Quests" to have side effects. There are two entities that can have @ref orxonox::QuestEffect "QuestEffects": @ref orxonox::Quest "Quests" and @ref orxonox::QuestEffectBeacon "QuestEffectBeacons" (which will be explained later on). @ref orxonox::QuestEffect "QuestEffects", for example, can start a @ref orxonox::Quest "Quest" for a player, complete/fail @ref orxonox::Quest "Quests" for a player, add a @ref orxonox::QuestHint "QuestHint" or a @ref orxonox::Rewardable "Reward" to a player, and potentially much, much more.
+
+    These @ref orxonox::QuestEffect "QuestEffects" are implemented so far, but feel free to <a href="http://www.orxonox.net/wiki/DamianFrick">contact me</a> if you have suggestions for new @ref orxonox::QuestEffect "QuestEffects" or if you need help implementing a new one yourself.
+
+    @paragraph AddQuest AddQuest
+    This @ref orxonox::QuestEffect "QuestEffect" adds (respectively starts) a @ref orxonox::Quest "Quest" (identified by the given questId) to the player.
+    @code
+    <AddQuest questId="id" />  //Where id identifies the Quest that should be added.
+    @endcode
+
+    @paragraph FailQuest FailQuest
+    This @ref orxonox::QuestEffect "QuestEffect" fails a @ref orxonox::Quest "Quest" (identified by the given questId) for the player.
+    @code
+    <FailQuest questId="id" />  //Where id identifies the Quest that should be added.
+    @endcode
+
+    @paragraph CompleteQuest CompleteQuest
+    This @ref orxonox::QuestEffect "QuestEffect" completes a @ref orxonox::Quest "Quest" (identified by the given questId) for the player.
+    @code
+    <CompleteQuest questId="id" />  //Where id identifies the Quest that should be added.
+    @endcode
+
+    @paragraph AddQuestHint AddQuestHint
+    This @ref orxonox::QuestEffect "QuestEffect" adds a @ref orxonox::QuestHint "QuestHint" to a @ref orxonox::Quest "Quest" (identified by the given questId) of a player.
+    @code
+    <AddQuestHint hintId="id" />  //Where id identifies the QuestHint that should be added.
+    @endcode
+
+    @paragraph AddReward AddReward
+    This @ref orxonox::QuestEffect "QuestEffect" adds a @ref orxonox::Rewardable "Rewardable" (@ref orxonox::Rewardable "Rewardable" is an Interface which can be implemented by an object that its creator thinks should be able to be rewarded a player for completing (or failing for that matter) a @ref orxonox::Quest "Quest") to the player. @ref Pickup Pickups for example wold be good @ref orxonox::Rewardable "Rewardables".
+    @code
+    <AddReward>
+        <Rewardable /> //A list of Rewardable objects to be rewarded the player, see the specific Rewardables for their respective XML representations.
+        ...
+        <Rewardable />
+    </AddReward>
+    @endcode
+
+    @subsubsection QuestListener QuestListener
+    The @ref orxonox::QuestListener "QuestListener" is the second device you can use to create side effects. As opposed to @ref orxonox::QuestEffect "QuestEffects" (that are executed (or invoked) either as a result of failing or completing a Quest or by a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon"), @ref orxonox::QuestListener "QuestListeners" are passive, meaning that they relay information regarding status changes of @ref orxonox::Quest "Quests" rather than enforcing status changes. @ref orxonox::QuestListener "QuestListeners" have a certain mode (all, start, complete or fail) and a @ref orxonox::Quest "Quest" which they belong to (resp. to which they react). You then can use @ref orxonox::QuestListener "QuestListeners" to make basically any object aware of when the status of the given @ref orxonox::Quest "Quest" changes (the way you defined through the mode) and take any action you may think of.
+
+    Here is an example of the usage of @ref orxonox::QuestListener "QuestListeners" in XML:
+    @code
+    <BaseObject> // The object that should react to the status change of a Quest.
+        <events>
+            <function> // Where function is the method of the object that schould be executed. Normally this would be visibility or activity.
+                <QuestListener questId="someQuestId" mode="someMode" /> // Where someQuestId is the identifier for the Quest the QuestListener is reacting to, and someMode is the kind of status change the QUestListener reacts to (all, start, complete or fail).
+            </function>
+        </events>
+    </BaseObject>
+    @endcode
+
+    I hope this example has made the usage of @ref orxonox::QuestListener "QuestListeners" a little clearer. The @ref orxonox::QuestListener "QuestListener" actually reacts exactly as any @ref orxonox::Trigger "Trigger" or @ref orxonox::EventListener "EventListener" would (although the @ref orxonox::QuestListener "QuestListener" is really neighter the one nor the other) which means you can use it in exactly the same way you would use one of the above, it just reacts to a different thing. Namely to the change in a @ref orxonox::Quest "Quests" status.
+
+    @subsection PuttingTheQuestsInTheGameWorld Putting the Quests in the game world
+    As of now we know how to create @ref orxonox::Quest "Quests" and @ref orxonox::QuestHint "QuestHints", we have a way for quests to add new quests, or even complete/fail other quests. We also have a way of reacting to a status change in a @ref orxonox::Quest "Quest". In short we know how quests can be created, how they can influence other quests and how we can react to changes in quests. But our @ref orxonox::Quest "Quests" have no ties (well, not really at least) to the game world as of yet, meaning, that the game world cannot influence quests. For this we have @ref orxonox::QuestEffectBeacon "QuestEffectBeacons".
+
+    @subsubsection QuestEffectBeacon QuestEffectBeacon
+    The @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" is a @ref orxonox::StaticEntity "StaticEntity" and has the ability to (when triggered trough some circumstance) invoke a specified list of @ref orxonox::QuestEffect "QuestEffects" on the player triggering the @ref orxonox::QuestEffectBeacon "QuestEffectBeacon".
+
+    Creating a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" in XML goes as follows:
+    @code
+    <QuestEffectBeacon times=n> //Where 'n' is either a number >= 0, which means the QuestEffectBeacon can be executed n times. Or n = -1, which means the QuestEffectBeacon can be executed an infinite number of times.
+        <effects>
+            <QuestEffect /> //A list of QuestEffects, invoked when the QuestEffectBeacon is executed, see QuestEffect for the full XML representation.
+            ...
+            <QuestEffect />
+        </effects>
+        <events>
+            <execute>
+                <EventListener event=eventIdString />
+            </execute>
+        </events>
+        <attached>
+            <PlayerTrigger name=eventIdString /> //A PlayerTrigger triggering the execution of the QuestEffectBeacon.
+        </attached>
+    </QuestEffectBeacon>
+    @endcode
+
+    The @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" can only be executed a defined number of times (where -1 times stands for an infinite number of times) and the @ref orxonox::QuestEffect "QuestEffects" are invoked whenever the method 'execute' is called, which is (indirectly through an @ref orxonox::EventListener "EventListener", because I wanted to attach the @ref orxonox::PlayerTrigger "PlayerTrigger" so that its position is always relative to the @ref orxonox::QuestEffectBeacon "QuestEffectBeacons" position) done by the @ref orxonox::PlayerTrigger "PlayerTrigger".
+
+    A @ref orxonox::PlayerTrigger "PlayerTrigger" is a special sort of @ref orxonox::Trigger "Trigger" that knows the player that triggered it and therefore can be asked who that was. This allows the @ref orxonox::QuestEffect "QuestEffects" to be executed on the right player.
+
+    @section SampleQuest Sample quest
+    To get your head around all of this and see some of the things mentioned here in action you might want to check out the "The Tale of Princess Aeryn"-Quest (Levelfile: princessAeryn.oxw) in the level-folder.
+*/
+
+/**
+    @defgroup QuestEffects Effects
+    @ingroup Questsystem
+
+    A @ref orxonox::QuestEffect "QuestEffect" is a device for @ref orxonox::Quest "Quests" to have side effects. There are two entities that can have @ref orxonox::QuestEffect "QuestEffects": @ref orxonox::Quest "Quests" and \ref orxonox::QuestEffectBeacon "QuestEffectBeacons". @ref orxonox::QuestEffect "QuestEffects", for example, can start a @ref orxonox::Quest "Quest" for a player, complete/fail @ref orxonox::Quest "Quests" for a player, add a @ref orxonox::QuestHint "QuestHint" or a @ref orxonox::Rewardable "Reward" to a player, and potentially much, much more.
+*/
Index: /code/branches/RacingBots_FS18/doc/api/groups/Triggers.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/groups/Triggers.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/groups/Triggers.dox	(revision 11817)
@@ -0,0 +1,147 @@
+/**
+    @addtogroup Triggers Triggers
+    @ingroup Objects
+
+    Triggers are objects which react to certain events. They can be combined and used as simple overlay logic in levels.
+
+    @defgroup NormalTrigger Trigger
+    @ingroup Triggers
+    
+    @ref orxonox::Trigger "Triggers" are objects which react to certain events by changing their boolean state. That state is the trigger's activity @ref orxonox::Trigger can be either <em>active</em> or <em>not active</em>.
+    
+    @section TriggerTechnicalDetails Technical Details
+    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. Each time a switch occurs an @ref orxonox::Event "Event" is fired (see the @ref Eventsystem "Eventsystem" for more information about how that works exactly), with th @ref orxonox::Trigger "Trigger" as the originator. This way the entity that reacts to the @ref orxonox::Trigger "Trigger" triggering receives information about the @ref orxonox::Trigger "Trigger" that created the @ref orxonox::Event "Event". If the @ref orxonox::Trigger "Trigger" is also a @ref orxonox::PlayerTrigger "PlayerTrigger", under some conditions, the entity that caused the @ref orxonox::Trigger "Trigger" to trigger can be accessed.
+
+    Also, just as with all triggers, @ref orxonox::Trigger "Triggers" can be nested (even with e.g. @ref orxonox::MultiTrigger "MultiTriggers").
+    @code
+    <Trigger switch="true" delay="2">
+        <DistanceTrigger position="100,0,0" distance="80" />
+        <EventMultiTrigger ... />
+    </Trigger>
+    @endcode
+
+    @ref orxonox::Trigger "Triggers" also allow for additional complexity which can be added through the choice of the parameters explained below.
+    But first it is important to understand a small implementation detail. There is a distinction between the @ref orxonox::Trigger "Trigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::Trigger "Trigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em> to the outside, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::Trigger "Trigger" transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
+
+    The parameters of the @ref orxonox::Trigger "Trigger" are: 
+    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::Trigger "Trigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0.0</code>.
+    - @b switch Switch is a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is <em>triggered</em>, not when it is <em>not triggered</em> (Just like a light switch does). This means, that in <em>switch-mode</em> the <em>activity</em> only changes, when the trigger changes from being <em>not triggered</em> to being <em>triggered</em> but not the other way around. The default is <code>false</code>.
+    - @b stayActive Stay active is also a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" stays active after it has been activated as many times as specified by the parameter <em>activations</em>. In essence this means, that after the last time it is activated it cannot be deactivated. The default is <code>false</code>.
+    - @b activations Activations is the number of times the @ref orxonox::Trigger "Trigger" can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+    - @b invert Invert is a boolean, if <code>true</code> the @ref orxonox::Trigger "Trigger" is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the @ref orxonox::Trigger "Trigger" will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it inverts the behavior of the @ref orxonox::Trigger "Trigger". The default is <code>false</code>.
+    - @b mode The mode describes how the @ref orxonox::Trigger "Trigger" acts in relation to all the triggers (its children), that are appended to it. There are 3 modes: <em>and</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the @ref orxonox::Trigger "Trigger" can only be triggered if one and only one appended trigger is active. Note, that I wrote 'can only be active', that implies, that there is an additional condition to the <em>activity</em> of the @ref orxonox::Trigger "Trigger" and that is the fulfillment of the triggering condition (the @ref orxonox::Trigger "Trigger" class itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a @ref orxonox::Trigger "Trigger" is still coupled to the object that triggered it. The default is <em>and</em>.
+
+    @subsection Sub-typesOfTriggers Sub-types of Triggers
+
+    @subsubsection EventTrigger EventTrigger
+    An @ref orxonox::EventTrigger "EventTrigger" can either be used to be triggered when an @ref orxonox::Event "Event", that itself is triggering, arrives at its event port.
+
+    A common usage could look like this:
+    @code
+    <EventTrigger invert="true" delay="1">
+        <events>
+            <trigger>
+                <Trigger ... />
+                <Trigger ... />
+            </trigger>
+        </events>
+    </EventTrigger>
+    @endcode
+
+    @subsubsection DistanceTrigger DistanceTrigger
+    The @ref orxonox::DistanceTrigger "DistanceTrigger" is a Trigger that triggers whenever an object (that is of the specified target type) is in a specified range of the @ref orxonox::DistanceTrigger "DistanceTrigger". The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+    Parameters are (additional to the ones of Trigger):
+    - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceTrigger "DistanceTrigger" still triggers, i.e. its range. Default is <code>100</code>.
+    - @b target Which specifies the class of objects that can trigger the @ref orxonox::DistanceTrigger "DistanceTrigger". Default is <code>"Pawn"</code>.
+    - @b beaconMode Which specifies, whether the @ref orxonox::DistanceTrigger "DistanceTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceTrigger "DistanceTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+    - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceTrigger "DistanceTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+
+    A simple @ref orxonox::DistanceTrigger "DistanceTrigger" could look like this:
+    @code
+    <DistanceTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
+    @endcode
+
+    An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
+    @code
+    <DistanceTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
+    @endcode
+    This particular @ref orxonox::DistanceTrigger "DistanceTrigger" would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
+
+    @defgroup MultiTrigger MultiTrigger
+    @ingroup Triggers
+
+    @ref orxonox::MultiTrigger "MultiTriggers" are (as they are @ref orxonox::TriggerBase "Triggers") objects which react to certain events. They offer all the functionality that the common @ref orxonox::Trigger "Triggers" do with one significant difference. The common @ref orxonox::Trigger "Trigger" has just one state, it can either be <em>active</em> or <em>not acive</em>, it doesn't discriminate between who's triggering (or not triggering) it. A @ref orxonox::MultiTrigger "MultiTrigger", on the other hand, has a distinct state (<em>active</em> or <em>not actve</em>) for each entity that is defined as being able to trigger said @ref orxonox::MultiTrigger "MultiTrigger".
+
+    This difference becomes significant, when, for example, you want a @ref orxonox::DistanceTrigger "DistanceTrigger" to trigger a @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" to hand out a @ref orxonox::Quest "Quest" to any @ref orxonox::Pawn "Pawn" that enters its range. With a simple @ref orxonox::DistanceTrigger "DistanceTrigger" (as opposed to the more complex @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger") the first @ref orxonox::Pawn "Pawn" to be in range would trigger it an receive the @ref orxonox::Quest "Quest", however if a second @ref orxonox::Pawn "Pawn" would enter the range, while the first @ref orxonox::Pawn "Pawn" still is in the range nothing would happen and even after the first @ref orxonox::Pawn "Pawn" left nothing would happen, since the whole time the @ref orxonox::DistanceTrigger "DistanceTrigger" would just be <em>active</em>. In contrast with a @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" the first @ref orxonox::Pawn "Pawn" would enter the range and the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would have the state <em>active</em> for this exact @ref orxonox::Pawn "Pawn" (but for none else) and thus the @ref orxonox::Pawn "Pawn" would receive the @ref orxonox::Quest "Quest" and when the second @ref orxonox::Pawn "Pawn" enters the range the state of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" for that second @ref orxonox::Pawn "Pawn" would change to <em>active</em> and it would receive the @ref orxonox::Quest "Quest" as well.
+
+    @section WhenToUseMultiTriggers When to use MultiTriggers
+    Consequentially you would use @ref orxonox::MultiTrigger "MultiTriggers" (instead of common @ref orxonox::Trigger "Triggers"), when it is important that the trigger has different states for each triggering entity and when that fact is essential in the concept of the object that reacts to the triggering. However you should not just use @ref orxonox::MultiTrigger "MultiTrigger" instead of @ref orxonox::Trigger "Trigger", when in doubt, because @ref orxonox::MultiTrigger "MultiTrigger" produces significantly more overhead than @ref orxonox::Trigger "Trigger" due to the added complexity.
+
+    @section HowToUseMultiTriggers How to use MultiTriggers
+    ...
+    
+    @section HowToCreateANewMultiTrigger How to create a new MultiTrigger.
+    ...
+
+    @section MultiTriggerTechnicalDetails Technical Details
+    A common @ref orxonox::Trigger "Trigger" is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A @ref orxonox::MultiTrigger "MultiTrigger" generalizes that behavior for multiple objects triggering the trigger. A @ref orxonox::MultiTrigger "MultiTrigger" can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for all other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired (see the @ref Eventsystem "Eventsystem" for more information about how that works exactly), with a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer" as the originator, containing a pointer to the @ref orxonox::MultiTrigger "MultiTrigger" that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity. This way the entity that reacts to the @ref orxonox::MultiTrigger "MultiTrigger" triggering receives the information it needs about the entity that triggered the @ref orxonox::MultiTrigger "MultiTrigger".
+
+    Also, just as with all triggers, @ref orxonox::MultiTrigger "MultiTriggers" can be nested (even with triggers other than @ref orxonox::MultiTrigger "MultiTriggers").
+    @code
+    <MultiTrigger switch="true" delay="2">
+        <DistanceMultiTrigger position="100,0,0" distance="80" />
+        <EventTrigger ... />
+    </Trigger>
+    @endcode
+
+    @ref orxonox::MultiTrigger "MultiTriggers" also allow for additional complexity which can be added through the choice of the parameters (some of which are also present in the common @ref orxonox::Trigger "Trigger") explained (briefly) below.
+    But first it is important to understand a small implementation detail. There is a distinction between the @ref orxonox::MultiTrigger "MultiTrigger" being triggered (there is the state <em>triggered</em> for that) and the @ref orxonox::MultiTrigger "MultiTrigger" being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em> to the outside, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the @ref orxonox::MultiTrigger "MultiTrigger" transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
+
+    The parameters of the @ref orxonox::MultiTrigger "MultiTrigger" are: 
+    - @b delay The delay is the time in seconds, that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled. Internally this is handled by a state queue coupled with a counter, for each state that is delayed. The state becomes <em>active</em> when the counter runs out. This allows the @ref orxonox::MultiTrigger "MultiTrigger" to work even if the delay changes at runtime. However if the delay changes it only affects newly arriving states not the ones already in the queue. The default is <code>0.0</code>.
+    - @b switch Switch is a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, not when it is un-triggered (Just like a light switch does). This means, that in <em>switch-mode</em> the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
+    - @b stayActive Stay active is also a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" stays active after it has been activated as many times as specified by the parameter <em>activations</em>. In essence this means, that after the last time it is activated it cannot be deactivated. The default is <code>false</code>.
+    - @b activations Activations is the number of times the @ref orxonox::MultiTrigger "MultiTrigger" can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+    - @b invert Invert is a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the @ref orxonox::MultiTrigger "MultiTrigger" will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it inverts the behavior of the @ref orxonox::MultiTrigger "MultiTrigger". The default is <code>false</code>.
+    - @b simultaneousTriggerers The number of simultaneous triggerers limits the number of objects that are allowed to trigger the @ref orxonox::MultiTrigger "MultiTrigger" at the same time. Or more precisely, the number of distinct objects the @ref orxonox::MultiTrigger "MultiTrigger" has positive <em>triggered</em> states for, at each point in time. The default is <code>-1</code>, which denotes infinity.
+    - @b mode The mode describes how the @ref orxonox::MultiTrigger "MultiTrigger" acts in relation to all the triggers (its children), that are appended to it. There are 3 modes: <em>and</em>, meaning that the @ref orxonox::MultiTrigger "MultiTrigger" can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the @ref orxonox::MultiTrigger "MultiTrigger" can only be triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the @ref orxonox::MultiTrigger "MultiTrigger" can only be triggered if one and only one appended trigger is active. Note, that I wrote 'can only be active', that implies, that there is an additional condition to the <em>activity</em> of the @ref orxonox::MultiTrigger "MultiTrigger" and that is the fulfillment of the triggering condition (the @ref orxonox::MultiTrigger "MultiTrigger" class itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a @ref orxonox::MultiTrigger "MultiTrigger" is still coupled to the object that triggered it. The default is <em>and</em>.
+    - @b broadcast Broadcast is a boolean, if <code>true</code> the @ref orxonox::MultiTrigger "MultiTrigger" is in <em>broadcast-mode</em>, meaning, that all trigger events that are caused by no originator (originator is <code>NULL</code>) are broadcast as having come from every possible originator, or more precisely as having come from all objects that are specified targets of this @ref orxonox::MultiTrigger "MultiTrigger". The default is <code>false</code>.
+    - @b target The target describes the kind of objects that are allowed to trigger this @ref orxonox::MultiTrigger "MultiTrigger". The parameter has to be set to the class name of the class that is allowed to trigger the @ref orxonox::MultiTrigger "MultiTrigger". The default is <code>Pawn</code>.
+
+    @subsection Sub-typesOfMultiTriggers Sub-types of MultiTriggers
+
+    @subsubsection EventMultiTrigger EventMultiTrigger
+    An @ref orxonox::EventMultiTrigger "EventMultiTrigger" can either be used to broadcast an @ref orxonox::Event "Event" that does not come from a @ref orxonox::MultiTrigger "MultiTrigger" to all entities that are targets of the @ref orxonox::EventMultiTrigger "EventMultiTrigger" or, more in line with its prototype the @ref orxonox::EventTrigger "EventTrigger", to be triggered for an entity when an @ref orxonox::Event "Event" that was caused by an entity of the same type is captured.
+
+    A common usage could look like this:
+    @code
+    <EventMultiTrigger invert="true" delay="1">
+        <events>
+            <trigger>
+                <MultiTrigger ... />
+                <Trigger ... />
+            </trigger>
+        </events>
+    </EventMultiTrigger>
+    @endcode
+
+    @subsubsection DistanceMultiTrigger DistanceMultiTrigger
+    A @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is the @ref orxonox::MultiTrigger "MultiTrigger" equivalent of the @ref orxonox::DistanceTrigger "DistanceTrigger" and works just the same way. It triggers (now separately for each object triggering it, since it's a @ref orxonox::MultiTrigger "MultiTrigger") whenever an object that is a target of the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is in the specified range.
+
+    The target object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+    Parameters are (additional to the ones of @ref orxonox::MultiTrigger "MultiTrigger"):
+    - @b distance Which specifies the maximum distance at which the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" still triggers. Default is <code>100</code>.
+    - @b beaconMode Which specifies, whether the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" works as usual. If set to <em>identify</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+    - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+
+    A simple @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" could look like this:
+    @code
+    <@ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" position="0,0,0" switch="true" target="Pawn" distance="20" />
+    @endcode
+
+    An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
+    @code
+    <@ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
+    @endcode
+    This particular @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
+*/
Index: /code/branches/RacingBots_FS18/doc/api/groups/Weapons.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/groups/Weapons.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/groups/Weapons.dox	(revision 11817)
@@ -0,0 +1,27 @@
+/**
+    @addtogroup Weapons Weapons
+    @ingroup Modules
+
+    The Weapons module adds additional weapons to the Orxonox arsenal.
+*/
+
+/**
+    @defgroup WeaponsMunitions Munitions
+    @ingroup Weapons
+
+    The different munitions.
+*/
+
+/**
+    @defgroup WeaponsProjectiles Projectiles
+    @ingroup Weapons
+
+    The different projectiles.
+*/
+
+/**
+    @defgroup WeaponsWeaponModes Weapon Modes
+    @ingroup Weapons
+
+    The different weapon modes.
+*/
Index: /code/branches/RacingBots_FS18/doc/api/main.dox
===================================================================
--- /code/branches/RacingBots_FS18/doc/api/main.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/doc/api/main.dox	(revision 11817)
@@ -0,0 +1,15 @@
+/**
+    @mainpage
+
+    @image html orxonox.jpg
+
+    This is the documentation of Orxonox. It contains descriptions of our classes and functions and
+    explains their usage with several examples and background information. Because Orxonox is so big,
+    we can't document all of our code - sorry for that! But we do your best to document the most
+    important parts of it, namely the @ref Core "core" and @ref Util "util" libraries, as well as the
+    central classes in the @ref Orxonox "orxonox" main library and some @ref Modules "modules".
+
+    To understand the connection between different classes in Orxonox, have a look at the
+    <a href="modules.html"><b>Modules section</b></a>. It contains a list of the most important topics
+    and groups files that contribute to the same feature.
+*/
Index: /code/branches/RacingBots_FS18/src/BuildUnitsConfigGCC.cmake
===================================================================
--- /code/branches/RacingBots_FS18/src/BuildUnitsConfigGCC.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/BuildUnitsConfigGCC.cmake	(revision 11817)
@@ -0,0 +1,74 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the number of build units per library
+ #
+
+SET(BUILD_UNITS_CONFIG_1_THREADS
+  util              1
+  core              2
+  network           1
+  tools             1
+  orxonox           8
+  designtools       1
+  notifications     1
+  objects           2
+  overlays          2
+  pickup            2
+  pong              1
+  questsystem       1
+  weapons           1
+)
+
+SET(BUILD_UNITS_CONFIG_2_THREADS ${BUILD_UNITS_CONFIG_1_THREADS})
+
+SET(BUILD_UNITS_CONFIG_4_THREADS
+  util              1
+  core              4
+  network           2
+  tools             2
+  orxonox           8
+  designtools       1
+  notifications     1
+  objects           2
+  overlays          2
+  pickup            1
+  pong              1
+  questsystem       1
+  weapons           1
+)
+
+SET(BUILD_UNITS_CONFIG_8_THREADS
+  util              2
+  core              8
+  network           5
+  tools             3
+  orxonox           8
+  designtools       1
+  notifications     1
+  objects           3
+  overlays          3
+  pickup            2
+  pong              1
+  questsystem       3
+  weapons           3
+)
Index: /code/branches/RacingBots_FS18/src/BuildUnitsConfigMSVC.cmake
===================================================================
--- /code/branches/RacingBots_FS18/src/BuildUnitsConfigMSVC.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/BuildUnitsConfigMSVC.cmake	(revision 11817)
@@ -0,0 +1,88 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the number of build units per library
+ #
+
+SET(BUILD_UNITS_CONFIG_1_THREADS
+  util              1
+  core              1
+  network           1
+  tools             1
+  orxonox           2 # Avoids running out of symbol adresses (fix with /bigobj)
+  designtools       1
+  notifications     1
+  objects           1
+  overlays          1
+  pickup            1
+  pong              1
+  questsystem       1
+  weapons           1
+)
+
+SET(BUILD_UNITS_CONFIG_2_THREADS
+  util              1
+  core              2
+  network           1
+  tools             1
+  orxonox           2
+  designtools       1
+  notifications     1
+  objects           2
+  overlays          1
+  pickup            1
+  pong              1
+  questsystem       1
+  weapons           1
+)
+
+SET(BUILD_UNITS_CONFIG_4_THREADS
+  util              2
+  core              4
+  network           2
+  tools             2
+  orxonox           4
+  designtools       1
+  notifications     1
+  objects           2
+  overlays          2
+  pickup            1
+  pong              1
+  questsystem       2
+  weapons           2
+)
+
+SET(BUILD_UNITS_CONFIG_8_THREADS
+  util              2
+  core              8
+  network           5
+  tools             3
+  orxonox           8
+  designtools       1
+  notifications     1
+  objects           3
+  overlays          3
+  pickup            2
+  pong              1
+  questsystem       3
+  weapons           3
+)
Index: /code/branches/RacingBots_FS18/src/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,114 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the compilers and sets build options.
+ #
+
+# Required macros and functions
+INCLUDE(FlagUtilities)
+INCLUDE(TargetUtilities)
+
+INCLUDE(SourceConfig.cmake)
+
+# Configure the two headers and set some options
+INCLUDE(OrxonoxConfig.cmake)
+
+################ Sub Directories ################
+
+ADD_SUBDIRECTORY(external)
+ADD_SUBDIRECTORY(libraries)
+ADD_SUBDIRECTORY(orxonox)
+SET(ORXONOX_MODULES CACHE INTERNAL "")
+SET(ORXONOX_PLUGINS CACHE INTERNAL "")
+ADD_SUBDIRECTORY(modules)
+
+################## Executable ###################
+
+INCLUDE_DIRECTORIES(
+  ${CMAKE_CURRENT_SOURCE_DIR}/libraries
+  ${CMAKE_CURRENT_SOURCE_DIR}/orxonox
+)
+
+# Translate argument
+IF(ORXONOX_USE_WINMAIN)
+  SET(ORXONOX_WIN32 WIN32)
+ENDIF()
+
+SET(ORXONOX_MAIN_FILES Orxonox.cc)
+
+# Add special source file for OS X
+IF(APPLE)
+  LIST(APPEND ORXONOX_MAIN_FILES OrxonoxMac.mm)
+# Add the icon for win32 builds
+ELSEIF(WIN32)
+  LIST(APPEND ORXONOX_MAIN_FILES ${CMAKE_SOURCE_DIR}/contrib/winresource.rc)
+ENDIF()
+
+SET(ORXONOX_EXECUTABLE_NAME "orxonox" CACHE INTERNAL "")
+
+ORXONOX_ADD_EXECUTABLE(orxonox-main
+  # When defined as WIN32 this removes the console window on Windows
+  ${ORXONOX_WIN32}
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES
+    ${ORXONOX_MAIN_FILES}
+  OUTPUT_NAME
+    ${ORXONOX_EXECUTABLE_NAME}
+)
+# Main executable should depend on all modules (but not on plugins)
+ADD_DEPENDENCIES(orxonox-main ${ORXONOX_MODULES})
+
+
+# Apple Mac OS X specific build settings
+IF(APPLE)
+  # On Apple we need to link to AppKit and Foundation frameworks
+  TARGET_LINK_LIBRARIES(orxonox-main 
+    "-framework AppKit"
+    "-framework Foundation"
+  )
+
+  # Post-build step for the creation of the Dev-App bundle
+  INCLUDE(PrepareDevBundle)
+  ADD_CUSTOM_COMMAND(
+    TARGET orxonox-main
+    POST_BUILD 
+    # Copy the executable into the Orxonox.app
+    COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${ORXONOX_EXECUTABLE_NAME}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${PROJECT_NAME}.app/Contents/MacOS"
+    # Copy the dev-build marker file to Orxonox.app
+    COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/orxonox_dev_build.keep_me" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${PROJECT_NAME}.app/Contents/MacOS"
+    # Create a shortcut of the application to the root of the build tree
+    COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${PROJECT_NAME}.app" "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app" 
+  ) 
+ENDIF(APPLE)
+
+#################### Doxygen ####################
+
+# Prepare include paths for Doxygen. This is necessary to display
+# the correct path to use when including a file, e.g.
+# core/XMLPort.h instead of src/core/XMLPort.h
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/modules)
+GET_DIRECTORY_PROPERTY(_temp INCLUDE_DIRECTORIES)
+# Replace ';' by spaces
+STRING(REPLACE ";" " " _temp "${_temp}")
+SET(DOXYGEN_INCLUDE_DIRECTORIES "${_temp}" PARENT_SCOPE)
Index: /code/branches/RacingBots_FS18/src/Orxonox.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/Orxonox.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/Orxonox.cc	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Entry point of the program.
+*/
+
+#include "SpecialConfig.h"
+
+#ifdef ORXONOX_USE_WINMAIN
+# ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+# endif
+#include <windows.h>
+#endif
+
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "orxonox/Main.h"
+
+/*
+@brief
+    Main method. Game starts here (except for static initialisations).
+*/
+#ifdef ORXONOX_USE_WINMAIN
+INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT)
+#elif defined(ORXONOX_PLATFORM_APPLE)
+int main_mac(int argc, char** argv)
+#else
+int main(int argc, char** argv)
+#endif
+{
+    using namespace orxonox;
+
+    orxout(user_status) << "Welcome to Orxonox (v" << ORXONOX_VERSION_MAJOR << '.' << ORXONOX_VERSION_MINOR << '.' << ORXONOX_VERSION_PATCH << ' ' << ORXONOX_VERSION_NAME << ')' << endl;
+    orxout(internal_status) << "Congratulations, you survived the static initialization. Entering main()" << endl;
+    if (argc > 0)
+        orxout(internal_info) << "argv[0]: " << argv[0] << endl;
+
+    try
+    {
+#ifndef ORXONOX_USE_WINMAIN
+
+#ifdef ORXONOX_PLATFORM_APPLE
+        // On Apples, the kernel supplies a second argument, which we have to circumvent
+        const int firstArgument = 2;
+#else
+        // 0 is the execution path
+        const int firstArgument = 1;
+#endif
+
+        std::string strCmdLine;
+        for (int i = firstArgument; i < argc; ++i)
+            strCmdLine = strCmdLine + argv[i] + ' ';
+#endif
+
+        int value = main(strCmdLine);
+        orxout(internal_status) << "Terminating main() normally with value " << value << endl;
+        return value;
+    }
+    catch (...)
+    {
+        orxout(user_error) << "Exception caught in main(): " << orxonox::Exception::handleMessage() << endl;
+        orxout(user_error) << "Terminating program." << endl;
+        return 1;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/OrxonoxConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/src/OrxonoxConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/OrxonoxConfig.cmake	(revision 11817)
@@ -0,0 +1,133 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the header files OrxonoxConfig.h and SpecialConfig.h
+ #    and sets some other options. All the build related options should be
+ #    found and set here if possible.
+ #
+
+#################### Options ####################
+
+# Global switch to disable Precompiled Header Files
+# Note: PCH temporarily disabled on Mac because of severe problems
+IF(PCH_COMPILER_SUPPORT AND NOT APPLE)
+  OPTION(PCH_ENABLE "Global PCH switch" TRUE)
+ENDIF()
+
+# Global option to steer building muliple files as a single one
+# off/false: Turn off completely
+# partial:   Only combine files explicitly specified with BUILD_UNIT
+# full##:    Use ## source files per orxonox library and use manual build units
+#            for external dependencies. Example: full8 will in general use 8
+#            source files per library, but more specifically tries to occupy
+#            8 CPU threads.
+#            This is configured manually in BuildUnitsConfig.cmake
+SET(ENABLE_BUILD_UNITS "partial" CACHE STRING "Enables building multiple source files as one.")
+IF(ENABLE_BUILD_UNITS)
+  IF(NOT "${ENABLE_BUILD_UNITS}" STREQUAL "partial")
+    STRING(REGEX REPLACE "^full([1-9][0-9]?)$" "\\1" _nr_of_units "${ENABLE_BUILD_UNITS}")
+    IF("${_nr_of_units}" STREQUAL "${ENABLE_BUILD_UNITS}") # Regex match failed
+      MESSAGE(FATAL_ERROR "Unrecognised option for ENABLE_BUILD_UNITS: ${ENABLE_BUILD_UNITS}")
+    ELSE()
+      SET(NR_OF_BUILD_UNITS ${_nr_of_units})
+      IF(NOT HAVE_COUNTER_MACRO)
+        MESSAGE(WARNING "Your compiler doesn't support the __COUNTER__ macro. Full build units might not work!")
+      ENDIF()
+    ENDIF()
+  ENDIF()
+  IF(CMAKE_COMPILER_IS_GNU OR CMAKE_COMPILER_IS_CLANG)
+    INCLUDE(BuildUnitsConfigGCC.cmake)
+  ELSEIF(MSVC)
+    INCLUDE(BuildUnitsConfigMSVC.cmake)
+  ENDIF()
+ENDIF()
+
+# Use WinMain() or main()?
+IF(WIN32)
+  OPTION(ORXONOX_USE_WINMAIN "Use WinMain (doesn't show console) or main" FALSE)
+ENDIF()
+
+################ Platform Config ################
+
+# Check endianness
+INCLUDE(TestBigEndian)
+TEST_BIG_ENDIAN(ORXONOX_BIG_ENDIAN)
+IF(NOT ORXONOX_BIG_ENDIAN)
+  SET(ORXONOX_LITTLE_ENDIAN TRUE)
+ENDIF()
+
+# Platforms
+SET(ORXONOX_PLATFORM_WINDOWS ${WIN32})
+SET(ORXONOX_PLATFORM_APPLE   ${APPLE})
+SET(ORXONOX_PLATFORM_UNIX    ${UNIX})
+SET(ORXONOX_PLATFORM_LINUX   ${LINUX})
+
+# Check __forceinline
+IF(MSVC)
+  INCLUDE(CheckCXXSourceCompiles)
+  SET(_source "int main() { return 0; } __forceinline void test() { return; }")
+  CHECK_CXX_SOURCE_COMPILES("${_source}" HAVE_FORCEINLINE)
+ENDIF(MSVC)
+
+# Check some non standard system includes
+INCLUDE(CheckIncludeFileCXX)
+CHECK_INCLUDE_FILE_CXX(iso646.h HAVE_ISO646_H)
+CHECK_INCLUDE_FILE_CXX(stdint.h HAVE_STDINT_H)
+
+# Part of a woraround for OS X warnings. See OrxonoxConfig.h.in
+SET(ORX_HAVE_STDINT_H ${HAVE_STDINT_H})
+
+# XCode and Visual Studio support multiple configurations. In order to tell
+# about the active one we have to define the macro for each configuration
+ADD_COMPILER_FLAGS("-DCMAKE_Debug_BUILD"          Debug)
+ADD_COMPILER_FLAGS("-DCMAKE_RelForDevs_BUILD"     RelForDevs)
+ADD_COMPILER_FLAGS("-DCMAKE_Release_BUILD"        Release)
+ADD_COMPILER_FLAGS("-DCMAKE_RelWithDebInfo_BUILD" RelWithDebInfo)
+ADD_COMPILER_FLAGS("-DCMAKE_MinSizeRel_BUILD"     MinSizeRel)
+
+############## Configured Headers ###############
+
+SET(GENERATED_FILE_COMMENT
+   "DO NOT EDIT THIS FILE! <br>
+    It has been automatically generated by CMake from OrxonoxConfig.h.in")
+# Copy and configure OrxonoxConfig which gets included in every file
+CONFIGURE_FILE(OrxonoxConfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/OrxonoxConfig.h)
+# This file only gets included by very few classes to avoid a large recompilation
+CONFIGURE_FILE(SpecialConfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/SpecialConfig.h)
+
+SET(ORXONOX_CONFIG_FILES
+  ${CMAKE_CURRENT_SOURCE_DIR}/OrxonoxConfig.h.in
+  ${CMAKE_CURRENT_SOURCE_DIR}/SpecialConfig.h.in
+)
+SET(ORXONOX_CONFIG_FILES_GENERATED
+  ${CMAKE_CURRENT_BINARY_DIR}/OrxonoxConfig.h
+  ${CMAKE_CURRENT_BINARY_DIR}/SpecialConfig.h
+)
+
+# Make special target including the configured header files for Visual Studio
+IF(MSVC)
+  ADD_CUSTOM_TARGET(config
+    SOURCES
+      ${ORXONOX_CONFIG_FILES}
+      ${ORXONOX_CONFIG_FILES_GENERATED}
+  )
+ENDIF()
Index: /code/branches/RacingBots_FS18/src/OrxonoxConfig.h.in
===================================================================
--- /code/branches/RacingBots_FS18/src/OrxonoxConfig.h.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/OrxonoxConfig.h.in	(revision 11817)
@@ -0,0 +1,223 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ *   Original code: OgrePlatform.h, licensed under the LGPL. The code
+ *   has changed almost completely though.
+ *
+ *   Caution: Do not configure this file CMake configuration (Debug, Release, etc.)
+ *            dependent! XCode and Visual Studio have the same file for all.
+ *
+ */
+
+/**
+@file
+@brief
+    Various constants for compiler, architecture and platform.
+@remarks
+    @GENERATED_FILE_COMMENT@
+*/
+
+#ifndef _OrxonoxConfig_H__
+#define _OrxonoxConfig_H__
+
+/*---------------------------------
+ * Platform and compiler related options
+ *-------------------------------*/
+#cmakedefine ORXONOX_PLATFORM_WINDOWS
+#cmakedefine ORXONOX_PLATFORM_LINUX
+#cmakedefine ORXONOX_PLATFORM_APPLE
+#cmakedefine ORXONOX_PLATFORM_UNIX /* Apple and Linux */
+
+// Determine compiler and set ORXONOX_COMP_VER
+#if defined( _MSC_VER )
+#  define ORXONOX_COMPILER_MSVC
+#  define ORXONOX_COMP_VER _MSC_VER
+
+#elif defined( __GNUC__ )
+#  define ORXONOX_COMPILER_GCC
+#  define ORXONOX_COMP_VER (((__GNUC__)*100) + \
+        (__GNUC_MINOR__*10) + \
+        __GNUC_PATCHLEVEL__)
+#  if defined(__MINGW32__)
+#    define ORXONOX_COMPILER_MINGW
+#  endif
+
+#elif defined( __BORLANDC__ )
+#  define ORXONOX_COMPILER_BORLAND
+#  define ORXONOX_COMP_VER __BCPLUSPLUS__
+
+#else
+#  pragma error "No known compiler. Abort!"
+
+#endif
+
+// Endianness
+#cmakedefine ORXONOX_BIG_ENDIAN
+#cmakedefine ORXONOX_LITTLE_ENDIAN
+
+// Architecture
+#if defined(__x86_64__) || defined(_M_X64) || defined(__powerpc64__) || defined(__alpha__) || defined(__ia64__) || defined(__s390__) || defined(__s390x__)
+#   define ORXONOX_ARCH_64
+#else
+#   define ORXONOX_ARCH_32
+#endif
+
+// See if we can use __forceinline or if we need to use __inline instead
+#cmakedefine HAVE_FORCEINLINE
+#ifndef ORX_FORCEINLINE
+#  ifdef HAVE_FORCEINLINE
+#    define ORX_FORCEINLINE __forceinline
+#  else
+#    define ORX_FORCEINLINE __inline
+#  endif
+#endif
+
+// Try to define function information
+#ifndef __FUNCTIONNAME__
+#  ifdef ORXONOX_COMPILER_BORLAND
+#    define __FUNCTIONNAME__ __FUNC__
+#  elif defined(ORXONOX_COMPILER_GCC)
+#    define __FUNCTIONNAME__ __PRETTY_FUNCTION__
+#  elif defined(ORXONOX_COMPILER_MSVC)
+#    define __FUNCTIONNAME__ __FUNCTION__
+#  else
+#    define __FUNCTIONNAME__
+#  endif
+#endif
+
+// Declare a function deprecated
+#ifndef __DEPRECATED__
+#  if defined(ORXONOX_COMPILER_GCC)
+#    define __DEPRECATED__(function) function __attribute__ ((deprecated))
+#  elif defined(ORXONOX_COMPILER_MSVC)
+#    define __DEPRECATED__(function) __declspec(deprecated) function
+#  else
+#    define __DEPRECATED__(function) function
+#  endif
+#endif
+
+#ifndef __UNIQUE_NUMBER__
+#  if defined(ORXONOX_COMPILER_GCC) && ORXONOX_COMP_VER >= 430
+#    define __UNIQUE_NUMBER__ __COUNTER__
+#  elif defined(ORXONOX_COMPILER_MSVC)
+#    define __UNIQUE_NUMBER__ __COUNTER__
+#  else
+#    define __UNIQUE_NUMBER__ __LINE__
+#  endif
+#endif
+
+/*---------------------------------
+ * Version information
+ *-------------------------------*/
+#define ORXONOX_VERSION_MAJOR @ORXONOX_VERSION_MAJOR@
+#define ORXONOX_VERSION_MINOR @ORXONOX_VERSION_MINOR@
+#define ORXONOX_VERSION_PATCH @ORXONOX_VERSION_PATCH@
+#define ORXONOX_VERSION_NAME "@ORXONOX_VERSION_NAME@"
+
+//! Defines version info encoded as 0xMMIIPP (M: Major version, I: Minor version, P: Patch version, all as hex)
+#define ORXONOX_VERSION \
+    ((ORXONOX_VERSION_MAJOR << 16) | (ORXONOX_VERSION_MINOR << 8) | ORXONOX_VERSION_PATCH)
+
+
+/*---------------------------------
+ * Unix settings
+ *-------------------------------*/
+#ifdef ORXONOX_PLATFORM_UNIX
+
+// TODO: Check what this actually is and whether we need it or not
+#if 0
+#  ifdef ORXONOX_PLATFORM_APPLE
+#    define ORXONOX_PLATFORM_LIB "OrxonoxPlatform.bundle"
+#  else // ORXONOX_PLATFORM_LINUX
+#    define ORXONOX_PLATFORM_LIB "libOrxonoxPlatform.so"
+#  endif
+#endif
+
+#endif /* Patform Unix */
+
+
+/*---------------------------------
+ * Apple Settings
+ *-------------------------------*/
+
+
+/*---------------------------------
+ * Includes and Declarations
+ *-------------------------------*/
+// Define the english written operators like and, or, xor
+// This is C++ standard, but the Microsoft compiler doesn't define them.
+#cmakedefine HAVE_ISO646_H
+#ifdef HAVE_ISO646_H
+#  include <iso646.h>
+#endif
+
+// On OS X some headers already define HAVE_STDINT_H and that spits out
+// some warnings. Therefore we use this macro.
+// Note: This requires some extra code in OrxonoxConfig.cmake
+#cmakedefine ORX_HAVE_STDINT_H
+#ifdef ORX_HAVE_STDINT_H
+#  include <stdint.h>
+#elif defined(ORXONOX_COMPILER_MSVC)
+typedef __int8            int8_t;
+typedef __int16           int16_t;
+typedef __int32           int32_t;
+typedef __int64           int64_t;
+typedef unsigned __int8   uint8_t;
+typedef unsigned __int16  uint16_t;
+typedef unsigned __int32  uint32_t;
+typedef unsigned __int64  uint64_t;
+#endif
+
+#cmakedefine HAVE_STDDEF_H
+/* Quite large, do not include unless necessary
+#ifdef HAVE_STDDEF_H
+#  include <stddef.h>
+#endif
+*/
+
+// Configurations Release, RelWithDebInfo and MinSizeRel are designed for
+// redistribution while RelForDevs is for development purposes
+// ORXONOX_RELEASE simplifies this a little bit
+#if defined(CMAKE_Release_BUILD) || defined(CMAKE_MinSizeRel_BUILD) \
+    || defined(CMAKE_RelWithDebInfo_BUILD)
+#  define ORXONOX_RELEASE
+#endif
+
+// Define Boost Filesystem version
+#include <boost/version.hpp>
+#ifndef BOOST_FILESYSTEM_VERSION
+#  if (BOOST_VERSION < 104600)
+#    define BOOST_FILESYSTEM_VERSION 2
+#  else
+#    define BOOST_FILESYSTEM_VERSION 3
+#  endif
+#endif
+
+// CEGUI changed its file naming convention in version 0.8 thus we cannot even include CEGUI's Version.h file before knowing its version
+#include <@CEGUI_VERSION_FILE@>
+#define CEGUI_VERSION ((CEGUI_VERSION_MAJOR << 16) | (CEGUI_VERSION_MINOR << 8) | CEGUI_VERSION_PATCH)
+
+#endif /* _OrxonoxConfig_H__ */
Index: /code/branches/RacingBots_FS18/src/OrxonoxMac.h
===================================================================
--- /code/branches/RacingBots_FS18/src/OrxonoxMac.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/OrxonoxMac.h	(revision 11817)
@@ -0,0 +1,38 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin J. Young (youngk) 2011
+ *   Co-authors:
+ *      Fabian Landau (x3n)
+ *
+ */
+
+#import <Cocoa/Cocoa.h>
+
+int main_mac(int argc, char** argv);
+int main(int argc, char** argv);
+
+@interface OrxonoxAppDelegate : NSObject <NSApplicationDelegate>
+{
+}
+
+@end
Index: /code/branches/RacingBots_FS18/src/OrxonoxMac.mm
===================================================================
--- /code/branches/RacingBots_FS18/src/OrxonoxMac.mm	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/OrxonoxMac.mm	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin J. Young (youngk) 2011
+ *   Co-authors:
+ *      Fabian Landau (x3n)
+ *
+ */
+
+#import "OrxonoxMac.h"
+
+static int argc_s = 0;
+static char** argv_s = 0;
+
+int main(int argc, char** argv)
+{
+    argc_s = argc;
+    argv_s = argv;
+    
+    int retVal = NSApplicationMain(argc, (const char**)argv);
+    
+    return retVal;
+}
+
+@implementation OrxonoxAppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+    exit(main_mac(argc_s, argv_s));
+}
+
+@end
Index: /code/branches/RacingBots_FS18/src/SourceConfig.cmake
===================================================================
--- /code/branches/RacingBots_FS18/src/SourceConfig.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/SourceConfig.cmake	(revision 11817)
@@ -0,0 +1,145 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Reto Grieder
+ #  Description:
+ #    Configures the compilers and sets build options.
+ #
+
+# Required macros and functions
+INCLUDE(FlagUtilities)
+
+####### Library Behaviour (dependencies) ########
+
+# Disable auto linking completely for Boost and POCO
+ADD_COMPILER_FLAGS("-DBOOST_ALL_NO_LIB")
+ADD_COMPILER_FLAGS("-DPOCO_NO_AUTOMATIC_LIBS")
+
+IF(WIN32)
+  # If no defines are specified, these libs get linked statically
+  ADD_COMPILER_FLAGS("-DBOOST_ALL_DYN_LINK" LINK_BOOST_DYNAMIC)
+  #ADD_COMPILER_FLAGS("-DENET_DLL"           LINK_ENET_DYNAMIC)
+  ADD_COMPILER_FLAGS("-DLUA_BUILD_AS_DLL"   LINK_LUA5.1_DYNAMIC)
+  # If no defines are specified, these libs get linked dynamically
+  ADD_COMPILER_FLAGS("-DCEGUI_STATIC -DTOLUA_STATIC" NOT LINK_CEGUI_DYNAMIC)
+  ADD_COMPILER_FLAGS("-DOGRE_STATIC_LIB"    NOT LINK_OGRE_DYNAMIC)
+  ADD_COMPILER_FLAGS("-DSTATIC_BUILD"       NOT LINK_TCL_DYNAMIC)
+
+  # Target Windows XP as minimum Windows version
+  # And try to catch all the different macro defines for that...
+  ADD_COMPILER_FLAGS("-D_WIN32_WINNT=0x0501")
+  ADD_COMPILER_FLAGS("-D_WIN32_WINDOWS=0x0501")
+  ADD_COMPILER_FLAGS("-DWINVER=0x0501")
+  ADD_COMPILER_FLAGS("-DNTDDI_VERSION=0x05010000")
+ENDIF(WIN32)
+
+# Visual Leak Dectector configuration
+IF(MSVC AND VLD_FOUND)
+  OPTION(VISUAL_LEAK_DETECTOR_ENABLE "Memory leak detector" OFF)
+  IF(VISUAL_LEAK_DETECTOR_ENABLE)
+    # Force library linking by forcing the inclusion of a symbol
+    ADD_LINKER_FLAGS("-INCLUDE:__imp_?g_vld@@3VVisualLeakDetector@@A" Debug)
+    IF(MSVC90)
+      # VS 2008 incremental linker crashes with /INCLUDE most of the time
+      REMOVE_LINKER_FLAGS("-INCREMENTAL:YES" Debug)
+      ADD_LINKER_FLAGS   ("-INCREMENTAL:NO"  Debug)
+    ENDIF()
+  ENDIF()
+ENDIF()
+
+######### Library Behaviour (external) ##########
+
+# Use TinyXML++
+ADD_COMPILER_FLAGS("-DTIXML_USE_TICPP")
+
+# Default linking for externals
+IF(CMAKE_BUILD_TYPE MATCHES "(Debug|RelForDevs)")
+  SET(_default_link_mode "SHARED")
+ELSE()
+  SET(_default_link_mode "STATIC")
+ENDIF()
+SET(_message "Link mode for external libraries that we build ourselves.
+MSVC Note: certain libraries will not be linked shared.")
+SET(ORXONOX_EXTERNAL_LINK_MODE "${_default_link_mode}" CACHE STRING "${_message}")
+
+IF(ORXONOX_EXTERNAL_LINK_MODE STREQUAL "SHARED")
+  SET(_external_shared_link TRUE)
+ELSE()
+  SET(_external_shared_link FALSE)
+ENDIF()
+# If no defines are specified, these libs get linked dynamically
+ADD_COMPILER_FLAGS("-DENET_DLL"                    WIN32     _external_shared_link)
+ADD_COMPILER_FLAGS("-DOGRE_GUIRENDERER_STATIC_LIB" WIN32 NOT _external_shared_link)
+ADD_COMPILER_FLAGS("-DOIS_STATIC_LIB"              WIN32 NOT _external_shared_link)
+
+############## Include Directories ##############
+
+# Set the search paths for include files
+INCLUDE_DIRECTORIES(
+  # OrxonoxConfig.h
+  ${CMAKE_CURRENT_BINARY_DIR}
+
+  # All includes in "externals" should be prefixed with the path
+  # relative to "external" to avoid conflicts
+  ../src/external
+  # Include directories needed even if only included by Orxonox
+  ../src/external/bullet
+  ../src/external/ois
+)
+
+INCLUDE_DIRECTORIES(
+  SYSTEM
+  
+  # External
+  ${OGRE_INCLUDE_DIR}
+  ${CEGUI_INCLUDE_DIR}
+  ${CEGUI_TOLUA_INCLUDE_DIR}
+  #${ENET_INCLUDE_DIR}
+  ${Boost_INCLUDE_DIRS}
+  ${POCO_INCLUDE_DIR}
+  ${OPENAL_INCLUDE_DIRS}
+  ${ALUT_INCLUDE_DIR}
+  ${VORBIS_INCLUDE_DIR}
+  ${OGG_INCLUDE_DIR}
+  ${LUA5.1_INCLUDE_DIR}
+  ${TCL_INCLUDE_PATH}
+  ${DIRECTX_INCLUDE_DIR}
+  ${ZLIB_INCLUDE_DIR}
+)
+
+IF(CEGUI_OLD_VERSION)
+  INCLUDE_DIRECTORIES(SYSTEM ${CEGUILUA_INCLUDE_DIR})
+ENDIF()
+
+IF (DBGHELP_FOUND)
+  INCLUDE_DIRECTORIES(SYSTEM ${DBGHELP_INCLUDE_DIR})
+ENDIF()
+
+############## CEGUI OGRE Renderer ##############
+
+IF(CEGUI_OGRE_RENDERER_BUILD_REQUIRED)
+  SET(CEGUI_OGRE_RENDERER_LIBRARY ogreceguirenderer_orxonox)
+ENDIF()
+
+################### Tolua Bind ##################
+
+# Add hook script to the lua code that generates the bindings
+SET(TOLUA_PARSER_HOOK_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/libraries/core/ToluaInterfaceHook.lua)
+SET(TOLUA_PARSER_DEPENDENCIES ${TOLUA_PARSER_DEPENDENCIES} ${TOLUA_PARSER_HOOK_SCRIPT})
Index: /code/branches/RacingBots_FS18/src/SpecialConfig.h.in
===================================================================
--- /code/branches/RacingBots_FS18/src/SpecialConfig.h.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/SpecialConfig.h.in	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Various constants and options that only affect very little code.
+@note
+    This is merely to avoid recompiling everything when only a path changes.
+@remarks
+    @GENERATED_FILE_COMMENT@
+*/
+
+#ifndef _SpecialConfig_H__
+#define _SpecialConfig_H__
+
+#include "OrxonoxConfig.h"
+
+#cmakedefine DEPENDENCY_PACKAGE_ENABLE      ///< Defined if a precompiled depdency package was used. We then copy all libraries too when installing.
+
+#cmakedefine INSTALL_COPYABLE               ///< Orxonox either gets installed to the system or just into a folder. The latter uses relative paths.
+
+#cmakedefine CMAKE_CONFIGURATION_TYPES      ///< Using MSVC or XCode IDE
+
+#cmakedefine DBGHELP_FOUND                  ///< If DbgHelp was found on windows
+
+#cmakedefine ORXONOX_USE_WINMAIN            ///< Whether or not the console window is started as well
+
+#cmakedefine DO_NOT_UNLOAD_PLUGINS          ///< If defined then plugins are not unloaded (but merely deactivated) when the reference count drops to zero.
+
+// Handle default ConfigValues
+namespace orxonox { namespace specialConfig
+{
+    // DEFAULT RELATIVE PATHS (might not be used at all)
+    const char defaultRuntimePath[] = "@DEFAULT_RUNTIME_PATH@";
+    const char defaultLibraryPath[] = "@DEFAULT_LIBRARY_PATH@";
+    const char defaultArchivePath[] = "@DEFAULT_ARCHIVE_PATH@";
+    const char defaultModulePath[]  = "@DEFAULT_MODULE_PATH@";
+    const char defaultPluginPath[]  = "@DEFAULT_PLUGIN_PATH@";
+    const char defaultDocPath[]     = "@DEFAULT_DOC_PATH@";
+    const char defaultDataPath[]    = "@DEFAULT_DATA_PATH@";
+    const char defaultConfigPath[]  = "@DEFAULT_CONFIG_PATH@";
+    const char defaultLogPath[]     = "@DEFAULT_LOG_PATH@";
+
+#ifndef INSTALL_COPYABLE
+    // INSTALLATION PATHS
+    const char dataInstallDirectory[]       = "@CMAKE_INSTALL_PREFIX@/@DATA_INSTALL_DIRECTORY@";
+    const char moduleInstallDirectory[]     = "@CMAKE_INSTALL_PREFIX@/@MODULE_INSTALL_DIRECTORY@";
+    const char pluginInstallDirectory[]     = "@CMAKE_INSTALL_PREFIX@/@PLUGIN_INSTALL_DIRECTORY@";
+#endif
+
+    // DEVELOPMENT RUN PATHS
+    const char dataDevDirectory[]           = "@DATA_DIRECTORY@";
+    const char externalDataDevDirectory[]   = "@EXTERNAL_DATA_DIRECTORY@";
+#ifdef CMAKE_CONFIGURATION_TYPES
+    const char moduleDevDirectory[]         = "@CMAKE_MODULE_OUTPUT_DIRECTORY@/" CMAKE_INTDIR;
+    const char pluginDevDirectory[]         = "@CMAKE_PLUGIN_OUTPUT_DIRECTORY@/" CMAKE_INTDIR;
+    const char configDevDirectory[]         = "@CMAKE_CONFIG_OUTPUT_DIRECTORY@/" CMAKE_INTDIR;
+    const char logDevDirectory[]            = "@CMAKE_LOG_OUTPUT_DIRECTORY@/"    CMAKE_INTDIR;
+#else
+    const char moduleDevDirectory[]         = "@CMAKE_MODULE_OUTPUT_DIRECTORY@";
+    const char pluginDevDirectory[]         = "@CMAKE_PLUGIN_OUTPUT_DIRECTORY@";
+    const char configDevDirectory[]         = "@CMAKE_CONFIG_OUTPUT_DIRECTORY@";
+    const char logDevDirectory[]            = "@CMAKE_LOG_OUTPUT_DIRECTORY@";
+#endif
+
+#ifdef DEPENDENCY_PACKAGE_ENABLE
+    const char dependencyLibraryDirectory[] = "@DEP_LIBRARY_DIR@";
+#endif
+
+    // Module and plugin extension
+    const char moduleExtension[] = "@ORXONOX_MODULE_EXTENSION@";
+    const char pluginExtension[] = "@ORXONOX_PLUGIN_EXTENSION@";
+
+    // OGRE PLUGINS
+#ifdef NDEBUG
+    const char ogrePlugins[] = "@OGRE_PLUGINS_RELEASE@";
+    const char ogrePluginsDirectory[] = "@OGRE_PLUGINS_FOLDER_RELEASE@";
+#else
+    const char ogrePlugins[] = "@OGRE_PLUGINS_DEBUG@";
+    const char ogrePluginsDirectory[] = "@OGRE_PLUGINS_FOLDER_DEBUG@";
+#endif
+} }
+
+#endif /* _SpecialConfig_H__ */
Index: /code/branches/RacingBots_FS18/src/external/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,33 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+################ Sub Directories ################
+
+ADD_SUBDIRECTORY(tolua)
+ADD_SUBDIRECTORY(bullet)
+ADD_SUBDIRECTORY(cpptcl)
+ADD_SUBDIRECTORY(enet)
+ADD_SUBDIRECTORY(gmock)
+ADD_SUBDIRECTORY(gtest)
+ADD_SUBDIRECTORY(loki)
+IF(CEGUI_OGRE_RENDERER_BUILD_REQUIRED)
+  ADD_SUBDIRECTORY(ogreceguirenderer)
+ENDIF()
+ADD_SUBDIRECTORY(ois)
+ADD_SUBDIRECTORY(tinyxml)
Index: /code/branches/RacingBots_FS18/src/external/bullet/AUTHORS
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/AUTHORS	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/AUTHORS	(revision 11817)
@@ -0,0 +1,22 @@
+
+Bullet Physics Library is an open source project with help from the community at the Physics Forum
+See the forum at http://bulletphysics.com
+
+The project was started by Erwin Coumans
+
+Following people contributed to Bullet
+(random order, please let us know on the forum if your name should be in this list)
+
+Gino van den Bergen: LinearMath classes
+Christer Ericson: parts of the voronoi simplex solver
+Simon Hobbs: 3d axis sweep and prune, Extras/SATCollision, separating axis theorem + SIMD code
+Dirk Gregorius: generic D6 constraint
+Erin Catto: accumulated impulse in sequential impulse
+Nathanael Presson: EPA penetration depth calculation
+Francisco Leon: GIMPACT Concave Concave collision
+Joerg Henrichs: make buildsystem (work in progress)
+Eric Sunshine: jam + msvcgen buildsystem
+Steve Baker: GPU physics and general implementation improvements
+Jay Lee: Double precision support
+KleMiX, aka Vsevolod Klementjev, managed version, rewritten in C# for XNA
+Erwin Coumans: most other source code
Index: /code/branches/RacingBots_FS18/src/external/bullet/Bullet-C-Api.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/Bullet-C-Api.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/Bullet-C-Api.h	(revision 11817)
@@ -0,0 +1,176 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+	Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
+	Work in progress, functionality will be added on demand.
+
+	If possible, use the richer Bullet C++ API, by including "btBulletDynamicsCommon.h"
+*/
+
+#ifndef BULLET_C_API_H
+#define BULLET_C_API_H
+
+#define PL_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifdef BT_USE_DOUBLE_PRECISION
+typedef double	plReal;
+#else
+typedef float	plReal;
+#endif
+
+typedef plReal	plVector3[3];
+typedef plReal	plQuaternion[4];
+
+#ifdef __cplusplus
+extern "C" { 
+#endif
+
+/**	Particular physics SDK (C-API) */
+	PL_DECLARE_HANDLE(plPhysicsSdkHandle);
+
+/** 	Dynamics world, belonging to some physics SDK (C-API)*/
+	PL_DECLARE_HANDLE(plDynamicsWorldHandle);
+
+/** Rigid Body that can be part of a Dynamics World (C-API)*/	
+	PL_DECLARE_HANDLE(plRigidBodyHandle);
+
+/** 	Collision Shape/Geometry, property of a Rigid Body (C-API)*/
+	PL_DECLARE_HANDLE(plCollisionShapeHandle);
+
+/** Constraint for Rigid Bodies (C-API)*/
+	PL_DECLARE_HANDLE(plConstraintHandle);
+
+/** Triangle Mesh interface (C-API)*/
+	PL_DECLARE_HANDLE(plMeshInterfaceHandle);
+
+/** Broadphase Scene/Proxy Handles (C-API)*/
+	PL_DECLARE_HANDLE(plCollisionBroadphaseHandle);
+	PL_DECLARE_HANDLE(plBroadphaseProxyHandle);
+	PL_DECLARE_HANDLE(plCollisionWorldHandle);
+
+/**
+	Create and Delete a Physics SDK	
+*/
+
+	extern	plPhysicsSdkHandle	plNewBulletSdk(void); //this could be also another sdk, like ODE, PhysX etc.
+	extern	void		plDeletePhysicsSdk(plPhysicsSdkHandle	physicsSdk);
+
+/** Collision World, not strictly necessary, you can also just create a Dynamics World with Rigid Bodies which internally manages the Collision World with Collision Objects */
+
+	typedef void(*btBroadphaseCallback)(void* clientData, void* object1,void* object2);
+
+	extern plCollisionBroadphaseHandle	plCreateSapBroadphase(btBroadphaseCallback beginCallback,btBroadphaseCallback endCallback);
+
+	extern void	plDestroyBroadphase(plCollisionBroadphaseHandle bp);
+
+	extern 	plBroadphaseProxyHandle plCreateProxy(plCollisionBroadphaseHandle bp, void* clientData, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+	extern void plDestroyProxy(plCollisionBroadphaseHandle bp, plBroadphaseProxyHandle proxyHandle);
+
+	extern void plSetBoundingBox(plBroadphaseProxyHandle proxyHandle, plReal minX,plReal minY,plReal minZ, plReal maxX,plReal maxY, plReal maxZ);
+
+/* todo: add pair cache support with queries like add/remove/find pair */
+	
+	extern plCollisionWorldHandle plCreateCollisionWorld(plPhysicsSdkHandle physicsSdk);
+
+/* todo: add/remove objects */
+	
+
+/* Dynamics World */
+
+	extern  plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdk);
+
+	extern  void           plDeleteDynamicsWorld(plDynamicsWorldHandle world);
+
+	extern	void	plStepSimulation(plDynamicsWorldHandle,	plReal	timeStep);
+
+	extern  void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+	extern  void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object);
+
+
+/* Rigid Body  */
+
+	extern  plRigidBodyHandle plCreateRigidBody(	void* user_data,  float mass, plCollisionShapeHandle cshape );
+
+	extern  void plDeleteRigidBody(plRigidBodyHandle body);
+
+
+/* Collision Shape definition */
+
+	extern  plCollisionShapeHandle plNewSphereShape(plReal radius);
+	extern  plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z);
+	extern  plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height);	
+	extern  plCollisionShapeHandle plNewConeShape(plReal radius, plReal height);
+	extern  plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height);
+	extern	plCollisionShapeHandle plNewCompoundShape(void);
+	extern	void	plAddChildShape(plCollisionShapeHandle compoundShape,plCollisionShapeHandle childShape, plVector3 childPos,plQuaternion childOrn);
+
+	extern  void plDeleteShape(plCollisionShapeHandle shape);
+
+	/* Convex Meshes */
+	extern  plCollisionShapeHandle plNewConvexHullShape(void);
+	extern  void		plAddVertex(plCollisionShapeHandle convexHull, plReal x,plReal y,plReal z);
+/* Concave static triangle meshes */
+	extern  plMeshInterfaceHandle		   plNewMeshInterface(void);
+	extern  void		plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
+	extern  plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+
+	extern  void plSetScaling(plCollisionShapeHandle shape, plVector3 scaling);
+
+/* SOLID has Response Callback/Table/Management */
+/* PhysX has Triggers, User Callbacks and filtering */
+/* ODE has the typedef void dNearCallback (void *data, dGeomID o1, dGeomID o2); */
+
+/*	typedef void plUpdatedPositionCallback(void* userData, plRigidBodyHandle	rbHandle, plVector3 pos); */
+/*	typedef void plUpdatedOrientationCallback(void* userData, plRigidBodyHandle	rbHandle, plQuaternion orientation); */
+
+	/* get world transform */
+	extern void	plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+	extern void	plGetPosition(plRigidBodyHandle object,plVector3 position);
+	extern void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation);
+
+	/* set world transform (position/orientation) */
+	extern  void plSetPosition(plRigidBodyHandle object, const plVector3 position);
+	extern  void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation);
+	extern	void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient);
+	extern	void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix);
+
+	typedef struct plRayCastResult {
+		plRigidBodyHandle		m_body;  
+		plCollisionShapeHandle	m_shape; 		
+		plVector3				m_positionWorld; 		
+		plVector3				m_normalWorld;
+	} plRayCastResult;
+
+	extern  int plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plRayCastResult res);
+
+	/* Sweep API */
+
+	/* extern  plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal); */
+
+	/* Continuous Collision Detection API */
+	
+	// needed for source/blender/blenkernel/intern/collision.c
+	double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3]);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //BULLET_C_API_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp	(revision 11817)
@@ -0,0 +1,37 @@
+
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+
+//
+// btAxisSweep3
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+#include "btAxisSweep3.h"
+
+
+btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+	// 1 handle is reserved as sentinel
+	btAssert(maxHandles > 1 && maxHandles < 32767);
+
+}
+
+
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+	// 1 handle is reserved as sentinel
+	btAssert(maxHandles > 1 && maxHandles < 2147483647);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h	(revision 11817)
@@ -0,0 +1,1051 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#ifndef BT_AXIS_SWEEP_3_H
+#define BT_AXIS_SWEEP_3_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+
+//#define DEBUG_BROADPHASE 1
+#define USE_OVERLAP_TEST_ON_REMOVES 1
+
+/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
+/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
+/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
+template <typename BP_FP_INT_TYPE>
+class btAxisSweep3Internal : public btBroadphaseInterface
+{
+protected:
+
+	BP_FP_INT_TYPE	m_bpHandleMask;
+	BP_FP_INT_TYPE	m_handleSentinel;
+
+public:
+	
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	class Edge
+	{
+	public:
+		BP_FP_INT_TYPE m_pos;			// low bit is min/max
+		BP_FP_INT_TYPE m_handle;
+
+		BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
+	};
+
+public:
+	class	Handle : public btBroadphaseProxy
+	{
+	public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+	
+		// indexes into the edge arrays
+		BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3];		// 6 * 2 = 12
+//		BP_FP_INT_TYPE m_uniqueId;
+		btBroadphaseProxy*	m_dbvtProxy;//for faster raycast
+		//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
+	
+		SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
+		SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
+	};		// 24 bytes + 24 for Edge structures = 44 bytes total per entry
+
+	
+protected:
+	btVector3 m_worldAabbMin;						// overall system bounds
+	btVector3 m_worldAabbMax;						// overall system bounds
+
+	btVector3 m_quantize;						// scaling factor for quantization
+
+	BP_FP_INT_TYPE m_numHandles;						// number of active handles
+	BP_FP_INT_TYPE m_maxHandles;						// max number of handles
+	Handle* m_pHandles;						// handles pool
+	
+	BP_FP_INT_TYPE m_firstFreeHandle;		// free handles list
+
+	Edge* m_pEdges[3];						// edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+	void* m_pEdgesRawPtr[3];
+
+	btOverlappingPairCache* m_pairCache;
+
+	///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+	btOverlappingPairCallback* m_userPairCallback;
+	
+	bool	m_ownsPairCache;
+
+	int	m_invalidPair;
+
+	///additional dynamic aabb structure, used to accelerate ray cast queries.
+	///can be disabled using a optional argument in the constructor
+	btDbvtBroadphase*	m_raycastAccelerator;
+	btOverlappingPairCache*	m_nullPairCache;
+
+
+	// allocation/deallocation
+	BP_FP_INT_TYPE allocHandle();
+	void freeHandle(BP_FP_INT_TYPE handle);
+	
+
+	bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
+
+#ifdef DEBUG_BROADPHASE
+	void debugPrintAxis(int axis,bool checkCardinality=true);
+#endif //DEBUG_BROADPHASE
+
+	//Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+	//void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+
+	
+
+	void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+	void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+	void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+	void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+
+public:
+
+	btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false);
+
+	virtual	~btAxisSweep3Internal();
+
+	BP_FP_INT_TYPE getNumHandles() const
+	{
+		return m_numHandles;
+	}
+
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher);
+	
+	BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+	void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
+	void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+	SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+
+	virtual void resetPool(btDispatcher* dispatcher);
+
+	void	processAllOverlappingPairs(btOverlapCallback* callback);
+
+	//Broadphase Interface
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+	virtual void  getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+	
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+	
+	void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
+	///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
+	void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+	
+	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+	btOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_pairCache;
+	}
+	const btOverlappingPairCache*	getOverlappingPairCache() const
+	{
+		return m_pairCache;
+	}
+
+	void	setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
+	{
+		m_userPairCallback = pairCallback;
+	}
+	const btOverlappingPairCallback*	getOverlappingPairUserCallback() const
+	{
+		return m_userPairCallback;
+	}
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		aabbMin = m_worldAabbMin;
+		aabbMax = m_worldAabbMax;
+	}
+
+	virtual void	printStats()
+	{
+/*		printf("btAxisSweep3.h\n");
+		printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+		printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
+			m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
+			*/
+
+	}
+
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#ifdef DEBUG_BROADPHASE
+#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
+{
+	int numEdges = m_pHandles[0].m_maxEdges[axis];
+	printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
+
+	int i;
+	for (i=0;i<numEdges+1;i++)
+	{
+		Edge* pEdge = m_pEdges[axis] + i;
+		Handle* pHandlePrev = getHandle(pEdge->m_handle);
+		int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
+		char beginOrEnd;
+		beginOrEnd=pEdge->IsMax()?'E':'B';
+		printf("	[%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
+	}
+
+	if (checkCardinality)
+		btAssert(numEdges == m_numHandles*2+1);
+}
+#endif //DEBUG_BROADPHASE
+
+template <typename BP_FP_INT_TYPE>
+btBroadphaseProxy*	btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+		(void)shapeType;
+		BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
+		
+		Handle* handle = getHandle(handleId);
+		
+		if (m_raycastAccelerator)
+		{
+			btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0);
+			handle->m_dbvtProxy = rayProxy;
+		}
+		return handle;
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+	Handle* handle = static_cast<Handle*>(proxy);
+	if (m_raycastAccelerator)
+		m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher);
+	removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
+}
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+	Handle* handle = static_cast<Handle*>(proxy);
+	handle->m_aabbMin = aabbMin;
+	handle->m_aabbMax = aabbMax;
+	updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+	if (m_raycastAccelerator)
+		m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher);
+
+}
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	if (m_raycastAccelerator)
+	{
+		m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
+	} else
+	{
+		//choose axis?
+		BP_FP_INT_TYPE axis = 0;
+		//for each proxy
+		for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+		{
+			if (m_pEdges[axis][i].IsMax())
+			{
+				rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
+			}
+		}
+	}
+}
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+	if (m_raycastAccelerator)
+	{
+		m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
+	} else
+	{
+		//choose axis?
+		BP_FP_INT_TYPE axis = 0;
+		//for each proxy
+		for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+		{
+			if (m_pEdges[axis][i].IsMax())
+			{
+				Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
+				if (TestAabbAgainstAabb2(aabbMin,aabbMax,handle->m_aabbMin,handle->m_aabbMax))
+				{
+					callback.process(handle);
+				}
+			}
+		}
+	}
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	Handle* pHandle = static_cast<Handle*>(proxy);
+	aabbMin = pHandle->m_aabbMin;
+	aabbMax = pHandle->m_aabbMax;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	Handle* pHandle = static_cast<Handle*>(proxy);
+
+	unsigned short vecInMin[3];
+	unsigned short vecInMax[3];
+
+	vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ;
+	vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ;
+	vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ;
+	vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ;
+	vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ;
+	vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ;
+	
+	aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ()));
+	aabbMin += m_worldAabbMin;
+	
+	aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ()));
+	aabbMax += m_worldAabbMin;
+}
+
+
+
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0),
+m_raycastAccelerator(0)
+{
+	BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
+
+	if (!m_pairCache)
+	{
+		void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+		m_pairCache = new(ptr) btHashedOverlappingPairCache();
+		m_ownsPairCache = true;
+	}
+
+	if (!disableRaycastAccelerator)
+	{
+		m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache();
+		m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache);
+		m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs
+	}
+
+	//btAssert(bounds.HasVolume());
+
+	// init bounds
+	m_worldAabbMin = worldAabbMin;
+	m_worldAabbMax = worldAabbMax;
+
+	btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
+
+	BP_FP_INT_TYPE	maxInt = m_handleSentinel;
+
+	m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
+
+	// allocate handles buffer, using btAlignedAlloc, and put all handles on free list
+	m_pHandles = new Handle[maxHandles];
+	
+	m_maxHandles = maxHandles;
+	m_numHandles = 0;
+
+	// handle 0 is reserved as the null index, and is also used as the sentinel
+	m_firstFreeHandle = 1;
+	{
+		for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
+			m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+		m_pHandles[maxHandles - 1].SetNextFree(0);
+	}
+
+	{
+		// allocate edge buffers
+		for (int i = 0; i < 3; i++)
+		{
+			m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+			m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
+		}
+	}
+	//removed overlap management
+
+	// make boundary sentinels
+	
+	m_pHandles[0].m_clientObject = 0;
+
+	for (int axis = 0; axis < 3; axis++)
+	{
+		m_pHandles[0].m_minEdges[axis] = 0;
+		m_pHandles[0].m_maxEdges[axis] = 1;
+
+		m_pEdges[axis][0].m_pos = 0;
+		m_pEdges[axis][0].m_handle = 0;
+		m_pEdges[axis][1].m_pos = m_handleSentinel;
+		m_pEdges[axis][1].m_handle = 0;
+#ifdef DEBUG_BROADPHASE
+		debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+	}
+
+}
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
+{
+	if (m_raycastAccelerator)
+	{
+		m_nullPairCache->~btOverlappingPairCache();
+		btAlignedFree(m_nullPairCache);
+		m_raycastAccelerator->~btDbvtBroadphase();
+		btAlignedFree (m_raycastAccelerator);
+	}
+
+	for (int i = 2; i >= 0; i--)
+	{
+		btAlignedFree(m_pEdgesRawPtr[i]);
+	}
+	delete [] m_pHandles;
+
+	if (m_ownsPairCache)
+	{
+		m_pairCache->~btOverlappingPairCache();
+		btAlignedFree(m_pairCache);
+	}
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
+{
+#ifdef OLD_CLAMPING_METHOD
+	///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
+	///see http://code.google.com/p/bullet/issues/detail?id=87
+	btVector3 clampedPoint(point);
+	clampedPoint.setMax(m_worldAabbMin);
+	clampedPoint.setMin(m_worldAabbMax);
+	btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
+	out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
+	out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
+	out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
+#else
+	btVector3 v = (point - m_worldAabbMin) * m_quantize;
+	out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
+	out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
+	out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
+#endif //OLD_CLAMPING_METHOD
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
+{
+	btAssert(m_firstFreeHandle);
+
+	BP_FP_INT_TYPE handle = m_firstFreeHandle;
+	m_firstFreeHandle = getHandle(handle)->GetNextFree();
+	m_numHandles++;
+
+	return handle;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
+{
+	btAssert(handle > 0 && handle < m_maxHandles);
+
+	getHandle(handle)->SetNextFree(m_firstFreeHandle);
+	m_firstFreeHandle = handle;
+
+	m_numHandles--;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+	// quantize the bounds
+	BP_FP_INT_TYPE min[3], max[3];
+	quantize(min, aabbMin, 0);
+	quantize(max, aabbMax, 1);
+
+	// allocate a handle
+	BP_FP_INT_TYPE handle = allocHandle();
+	
+
+	Handle* pHandle = getHandle(handle);
+	
+	pHandle->m_uniqueId = static_cast<int>(handle);
+	//pHandle->m_pOverlaps = 0;
+	pHandle->m_clientObject = pOwner;
+	pHandle->m_collisionFilterGroup = collisionFilterGroup;
+	pHandle->m_collisionFilterMask = collisionFilterMask;
+	pHandle->m_multiSapParentProxy = multiSapProxy;
+
+	// compute current limit of edge arrays
+	BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
+
+	
+	// insert new edges just inside the max boundary edge
+	for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
+	{
+
+		m_pHandles[0].m_maxEdges[axis] += 2;
+
+		m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
+
+		m_pEdges[axis][limit - 1].m_pos = min[axis];
+		m_pEdges[axis][limit - 1].m_handle = handle;
+
+		m_pEdges[axis][limit].m_pos = max[axis];
+		m_pEdges[axis][limit].m_handle = handle;
+
+		pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
+		pHandle->m_maxEdges[axis] = limit;
+	}
+
+	// now sort the new edges to their correct position
+	sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
+	sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
+	sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
+	sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
+	sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
+	sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
+
+
+	return handle;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
+{
+
+	Handle* pHandle = getHandle(handle);
+
+	//explicitly remove the pairs containing the proxy
+	//we could do it also in the sortMinUp (passing true)
+	///@todo: compare performance
+	if (!m_pairCache->hasDeferredRemoval())
+	{
+		m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+	}
+
+	// compute current limit of edge arrays
+	int limit = static_cast<int>(m_numHandles * 2);
+	
+	int axis;
+
+	for (axis = 0;axis<3;axis++)
+	{
+		m_pHandles[0].m_maxEdges[axis] -= 2;
+	}
+
+	// remove the edges by sorting them up to the end of the list
+	for ( axis = 0; axis < 3; axis++)
+	{
+		Edge* pEdges = m_pEdges[axis];
+		BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
+		pEdges[max].m_pos = m_handleSentinel;
+
+		sortMaxUp(axis,max,dispatcher,false);
+
+
+		BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
+		pEdges[i].m_pos = m_handleSentinel;
+
+
+		sortMinUp(axis,i,dispatcher,false);
+
+		pEdges[limit-1].m_handle = 0;
+		pEdges[limit-1].m_pos = m_handleSentinel;
+		
+#ifdef DEBUG_BROADPHASE
+			debugPrintAxis(axis,false);
+#endif //DEBUG_BROADPHASE
+
+
+	}
+
+
+	// free the handle
+	freeHandle(handle);
+
+	
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* dispatcher)
+{
+	if (m_numHandles == 0)
+	{
+		m_firstFreeHandle = 1;
+		{
+			for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
+				m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+			m_pHandles[m_maxHandles - 1].SetNextFree(0);
+		}
+	}
+}       
+
+
+extern int gOverlappingPairs;
+//#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+	if (m_pairCache->hasDeferredRemoval())
+	{
+	
+		btBroadphasePairArray&	overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+
+		
+		int i;
+
+		btBroadphasePair previousPair;
+		previousPair.m_pProxy0 = 0;
+		previousPair.m_pProxy1 = 0;
+		previousPair.m_algorithm = 0;
+		
+		
+		for (i=0;i<overlappingPairArray.size();i++)
+		{
+		
+			btBroadphasePair& pair = overlappingPairArray[i];
+
+			bool isDuplicate = (pair == previousPair);
+
+			previousPair = pair;
+
+			bool needsRemoval = false;
+
+			if (!isDuplicate)
+			{
+				///important to use an AABB test that is consistent with the broadphase
+				bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+				if (hasOverlap)
+				{
+					needsRemoval = false;//callback->processOverlap(pair);
+				} else
+				{
+					needsRemoval = true;
+				}
+			} else
+			{
+				//remove duplicate
+				needsRemoval = true;
+				//should have no algorithm
+				btAssert(!pair.m_algorithm);
+			}
+			
+			if (needsRemoval)
+			{
+				m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+		//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+		//		m_overlappingPairArray.pop_back();
+				pair.m_pProxy0 = 0;
+				pair.m_pProxy1 = 0;
+				m_invalidPair++;
+				gOverlappingPairs--;
+			} 
+			
+		}
+
+	///if you don't like to skip the invalid pairs in the array, execute following code:
+	#define CLEAN_INVALID_PAIRS 1
+	#ifdef CLEAN_INVALID_PAIRS
+
+		//perform a sort, to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+	#endif//CLEAN_INVALID_PAIRS
+		
+		//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+	}
+
+}
+
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	const Handle* pHandleA = static_cast<Handle*>(proxy0);
+	const Handle* pHandleB = static_cast<Handle*>(proxy1);
+	
+	//optimization 1: check the array index (memory address), instead of the m_pos
+
+	for (int axis = 0; axis < 3; axis++)
+	{ 
+		if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || 
+			pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) 
+		{ 
+			return false; 
+		} 
+	} 
+	return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
+{
+	//optimization 1: check the array index (memory address), instead of the m_pos
+
+	if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || 
+		pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
+		pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
+		pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) 
+	{ 
+		return false; 
+	} 
+	return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+//	btAssert(bounds.IsFinite());
+	//btAssert(bounds.HasVolume());
+
+	Handle* pHandle = getHandle(handle);
+
+	// quantize the new bounds
+	BP_FP_INT_TYPE min[3], max[3];
+	quantize(min, aabbMin, 0);
+	quantize(max, aabbMax, 1);
+
+	// update changed edges
+	for (int axis = 0; axis < 3; axis++)
+	{
+		BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
+		BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
+
+		int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
+		int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
+
+		m_pEdges[axis][emin].m_pos = min[axis];
+		m_pEdges[axis][emax].m_pos = max[axis];
+
+		// expand (only adds overlaps)
+		if (dmin < 0)
+			sortMinDown(axis, emin,dispatcher,true);
+
+		if (dmax > 0)
+			sortMaxUp(axis, emax,dispatcher,true);
+
+		// shrink (only removes overlaps)
+		if (dmin > 0)
+			sortMinUp(axis, emin,dispatcher,true);
+
+		if (dmax < 0)
+			sortMaxDown(axis, emax,dispatcher,true);
+
+#ifdef DEBUG_BROADPHASE
+	debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+	}
+
+	
+}
+
+
+
+
+// sorting a min edge downwards can only ever *add* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pPrev = pEdge - 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pEdge->m_pos < pPrev->m_pos)
+	{
+		Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+		if (pPrev->IsMax())
+		{
+			// if previous edge is a maximum check the bounds and add an overlap if necessary
+			const int axis1 = (1  << axis) & 3;
+			const int axis2 = (1  << axis1) & 3;
+			if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
+			{
+				m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
+				if (m_userPairCallback)
+					m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
+
+				//AddOverlap(pEdge->m_handle, pPrev->m_handle);
+
+			}
+
+			// update edge reference in other handle
+			pHandlePrev->m_maxEdges[axis]++;
+		}
+		else
+			pHandlePrev->m_minEdges[axis]++;
+
+		pHandleEdge->m_minEdges[axis]--;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pPrev;
+		*pPrev = swap;
+
+		// decrement
+		pEdge--;
+		pPrev--;
+	}
+
+#ifdef DEBUG_BROADPHASE
+	debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a min edge upwards can only ever *remove* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pNext = pEdge + 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+	{
+		Handle* pHandleNext = getHandle(pNext->m_handle);
+
+		if (pNext->IsMax())
+		{
+			Handle* handle0 = getHandle(pEdge->m_handle);
+			Handle* handle1 = getHandle(pNext->m_handle);
+			const int axis1 = (1  << axis) & 3;
+			const int axis2 = (1  << axis1) & 3;
+			
+			// if next edge is maximum remove any overlap between the two handles
+			if (updateOverlaps 
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+				&& testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+				)
+			{
+				
+
+				m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);	
+				if (m_userPairCallback)
+					m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+				
+			}
+
+
+			// update edge reference in other handle
+			pHandleNext->m_maxEdges[axis]--;
+		}
+		else
+			pHandleNext->m_minEdges[axis]--;
+
+		pHandleEdge->m_minEdges[axis]++;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pNext;
+		*pNext = swap;
+
+		// increment
+		pEdge++;
+		pNext++;
+	}
+
+
+}
+
+// sorting a max edge downwards can only ever *remove* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pPrev = pEdge - 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pEdge->m_pos < pPrev->m_pos)
+	{
+		Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+		if (!pPrev->IsMax())
+		{
+			// if previous edge was a minimum remove any overlap between the two handles
+			Handle* handle0 = getHandle(pEdge->m_handle);
+			Handle* handle1 = getHandle(pPrev->m_handle);
+			const int axis1 = (1  << axis) & 3;
+			const int axis2 = (1  << axis1) & 3;
+
+			if (updateOverlaps  
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+				&& testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+				)
+			{
+				//this is done during the overlappingpairarray iteration/narrowphase collision
+
+				
+				m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+				if (m_userPairCallback)
+					m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+			
+
+
+			}
+
+			// update edge reference in other handle
+			pHandlePrev->m_minEdges[axis]++;;
+		}
+		else
+			pHandlePrev->m_maxEdges[axis]++;
+
+		pHandleEdge->m_maxEdges[axis]--;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pPrev;
+		*pPrev = swap;
+
+		// decrement
+		pEdge--;
+		pPrev--;
+	}
+
+	
+#ifdef DEBUG_BROADPHASE
+	debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a max edge upwards can only ever *add* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pNext = pEdge + 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+	{
+		Handle* pHandleNext = getHandle(pNext->m_handle);
+
+		const int axis1 = (1  << axis) & 3;
+		const int axis2 = (1  << axis1) & 3;
+
+		if (!pNext->IsMax())
+		{
+			// if next edge is a minimum check the bounds and add an overlap if necessary
+			if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
+			{
+				Handle* handle0 = getHandle(pEdge->m_handle);
+				Handle* handle1 = getHandle(pNext->m_handle);
+				m_pairCache->addOverlappingPair(handle0,handle1);
+				if (m_userPairCallback)
+					m_userPairCallback->addOverlappingPair(handle0,handle1);
+			}
+
+			// update edge reference in other handle
+			pHandleNext->m_minEdges[axis]--;
+		}
+		else
+			pHandleNext->m_maxEdges[axis]--;
+
+		pHandleEdge->m_maxEdges[axis]++;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pNext;
+		*pNext = swap;
+
+		// increment
+		pEdge++;
+		pNext++;
+	}
+	
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+
+/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
+/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
+/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
+class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
+{
+public:
+
+	btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
+/// This comes at the cost of more memory per handle, and a bit slower performance.
+/// It uses arrays rather then lists for storage of the 3 axis.
+class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
+{
+public:
+
+	bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+#endif
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef		BT_BROADPHASE_INTERFACE_H
+#define 	BT_BROADPHASE_INTERFACE_H
+
+
+
+struct btDispatcherInfo;
+class btDispatcher;
+#include "btBroadphaseProxy.h"
+
+class btOverlappingPairCache;
+
+
+
+struct	btBroadphaseAabbCallback
+{
+	virtual ~btBroadphaseAabbCallback() {}
+	virtual bool	process(const btBroadphaseProxy* proxy) = 0;
+};
+
+
+struct	btBroadphaseRayCallback : public btBroadphaseAabbCallback
+{
+	///added some cached data to accelerate ray-AABB tests
+	btVector3		m_rayDirectionInverse;
+	unsigned int	m_signs[3];
+	btScalar		m_lambda_max;
+
+	virtual ~btBroadphaseRayCallback() {}
+};
+
+#include "LinearMath/btVector3.h"
+
+///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
+///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
+///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
+class btBroadphaseInterface
+{
+public:
+	virtual ~btBroadphaseInterface() {}
+
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0;
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
+	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
+
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
+
+	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
+
+	///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+
+	virtual	btOverlappingPairCache*	getOverlappingPairCache()=0;
+	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const =0;
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
+
+	virtual void	printStats() = 0;
+
+};
+
+#endif //BT_BROADPHASE_INTERFACE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp	(revision 11817)
@@ -0,0 +1,17 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBroadphaseProxy.h"
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h	(revision 11817)
@@ -0,0 +1,270 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BROADPHASE_PROXY_H
+#define BT_BROADPHASE_PROXY_H
+
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+/// btDispatcher uses these types
+/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
+/// to facilitate type checking
+/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code
+enum BroadphaseNativeTypes
+{
+	// polyhedral convex shapes
+	BOX_SHAPE_PROXYTYPE,
+	TRIANGLE_SHAPE_PROXYTYPE,
+	TETRAHEDRAL_SHAPE_PROXYTYPE,
+	CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
+	CONVEX_HULL_SHAPE_PROXYTYPE,
+	CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
+	CUSTOM_POLYHEDRAL_SHAPE_TYPE,
+//implicit convex shapes
+IMPLICIT_CONVEX_SHAPES_START_HERE,
+	SPHERE_SHAPE_PROXYTYPE,
+	MULTI_SPHERE_SHAPE_PROXYTYPE,
+	CAPSULE_SHAPE_PROXYTYPE,
+	CONE_SHAPE_PROXYTYPE,
+	CONVEX_SHAPE_PROXYTYPE,
+	CYLINDER_SHAPE_PROXYTYPE,
+	UNIFORM_SCALING_SHAPE_PROXYTYPE,
+	MINKOWSKI_SUM_SHAPE_PROXYTYPE,
+	MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
+	BOX_2D_SHAPE_PROXYTYPE,
+	CONVEX_2D_SHAPE_PROXYTYPE,
+	CUSTOM_CONVEX_SHAPE_TYPE,
+//concave shapes
+CONCAVE_SHAPES_START_HERE,
+	//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
+	TRIANGLE_MESH_SHAPE_PROXYTYPE,
+	SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
+	///used for demo integration FAST/Swift collision library and Bullet
+	FAST_CONCAVE_MESH_PROXYTYPE,
+	//terrain
+	TERRAIN_SHAPE_PROXYTYPE,
+///Used for GIMPACT Trimesh integration
+	GIMPACT_SHAPE_PROXYTYPE,
+///Multimaterial mesh
+    MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
+	
+	EMPTY_SHAPE_PROXYTYPE,
+	STATIC_PLANE_PROXYTYPE,
+	CUSTOM_CONCAVE_SHAPE_TYPE,
+CONCAVE_SHAPES_END_HERE,
+
+	COMPOUND_SHAPE_PROXYTYPE,
+
+	SOFTBODY_SHAPE_PROXYTYPE,
+	HFFLUID_SHAPE_PROXYTYPE,
+	HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
+	INVALID_SHAPE_PROXYTYPE,
+
+	MAX_BROADPHASE_COLLISION_TYPES
+	
+};
+
+
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. 
+///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
+{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+	
+	///optional filtering to cull potential collisions
+	enum CollisionFilterGroups
+	{
+	        DefaultFilter = 1,
+	        StaticFilter = 2,
+	        KinematicFilter = 4,
+	        DebrisFilter = 8,
+			SensorTrigger = 16,
+			CharacterFilter = 32,
+	        AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+	};
+
+	//Usually the client btCollisionObject or Rigidbody class
+	void*	m_clientObject;
+	short int m_collisionFilterGroup;
+	short int m_collisionFilterMask;
+	void*	m_multiSapParentProxy;		
+	int			m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+	btVector3	m_aabbMin;
+	btVector3	m_aabbMax;
+
+	SIMD_FORCE_INLINE int getUid() const
+	{
+		return m_uniqueId;
+	}
+
+	//used for memory pools
+	btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
+	{
+	}
+
+	btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
+		:m_clientObject(userPtr),
+		m_collisionFilterGroup(collisionFilterGroup),
+		m_collisionFilterMask(collisionFilterMask),
+		m_aabbMin(aabbMin),
+		m_aabbMax(aabbMax)
+	{
+		m_multiSapParentProxy = multiSapParentProxy;
+	}
+
+	
+
+	static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
+	{
+		return (proxyType  < IMPLICIT_CONVEX_SHAPES_START_HERE);
+	}
+
+	static SIMD_FORCE_INLINE bool	isConvex(int proxyType)
+	{
+		return (proxyType < CONCAVE_SHAPES_START_HERE);
+	}
+
+	static SIMD_FORCE_INLINE bool	isNonMoving(int proxyType)
+	{
+		return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
+	}
+
+	static SIMD_FORCE_INLINE bool	isConcave(int proxyType)
+	{
+		return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
+			(proxyType < CONCAVE_SHAPES_END_HERE));
+	}
+	static SIMD_FORCE_INLINE bool	isCompound(int proxyType)
+	{
+		return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
+	}
+
+	static SIMD_FORCE_INLINE bool	isSoftBody(int proxyType)
+	{
+		return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
+	}
+
+	static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
+	{
+		return (proxyType == STATIC_PLANE_PROXYTYPE);
+	}
+
+	static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
+	{
+		return (proxyType == BOX_2D_SHAPE_PROXYTYPE) ||	(proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
+	}
+
+	
+}
+;
+
+class btCollisionAlgorithm;
+
+struct btBroadphaseProxy;
+
+
+
+///The btBroadphasePair class contains a pair of aabb-overlapping objects.
+///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
+{
+	btBroadphasePair ()
+		:
+	m_pProxy0(0),
+		m_pProxy1(0),
+		m_algorithm(0),
+		m_internalInfo1(0)
+	{
+	}
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btBroadphasePair(const btBroadphasePair& other)
+		:		m_pProxy0(other.m_pProxy0),
+				m_pProxy1(other.m_pProxy1),
+				m_algorithm(other.m_algorithm),
+				m_internalInfo1(other.m_internalInfo1)
+	{
+	}
+	btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
+	{
+
+		//keep them sorted, so the std::set operations work
+		if (proxy0.m_uniqueId < proxy1.m_uniqueId)
+        { 
+            m_pProxy0 = &proxy0; 
+            m_pProxy1 = &proxy1; 
+        }
+        else 
+        { 
+			m_pProxy0 = &proxy1; 
+            m_pProxy1 = &proxy0; 
+        }
+
+		m_algorithm = 0;
+		m_internalInfo1 = 0;
+
+	}
+	
+	btBroadphaseProxy* m_pProxy0;
+	btBroadphaseProxy* m_pProxy1;
+	
+	mutable btCollisionAlgorithm* m_algorithm;
+	union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
+
+};
+
+/*
+//comparison for set operation, see Solid DT_Encounter
+SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) 
+{ 
+    return a.m_pProxy0 < b.m_pProxy0 || 
+        (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); 
+}
+*/
+
+
+
+class btBroadphasePairSortPredicate
+{
+	public:
+
+		bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b )
+		{
+			const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
+			const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
+			const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
+			const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
+
+			 return uidA0 > uidB0 || 
+				(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
+				(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); 
+		}
+};
+
+
+SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b) 
+{
+	 return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
+}
+
+
+#endif //BT_BROADPHASE_PROXY_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,23 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionAlgorithm.h"
+#include "btDispatcher.h"
+
+btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+{
+	m_dispatcher = ci.m_dispatcher1;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_ALGORITHM_H
+#define BT_COLLISION_ALGORITHM_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btBroadphaseProxy;
+class btDispatcher;
+class btManifoldResult;
+class btCollisionObject;
+struct btDispatcherInfo;
+class	btPersistentManifold;
+
+typedef btAlignedObjectArray<btPersistentManifold*>	btManifoldArray;
+
+struct btCollisionAlgorithmConstructionInfo
+{
+	btCollisionAlgorithmConstructionInfo()
+		:m_dispatcher1(0),
+		m_manifold(0)
+	{
+	}
+	btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
+		:m_dispatcher1(dispatcher)
+	{
+		(void)temp;
+	}
+
+	btDispatcher*	m_dispatcher1;
+	btPersistentManifold*	m_manifold;
+
+//	int	getDispatcherId();
+
+};
+
+
+///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
+///It is persistent over frames
+class btCollisionAlgorithm
+{
+
+protected:
+
+	btDispatcher*	m_dispatcher;
+
+protected:
+//	int	getDispatcherId();
+	
+public:
+
+	btCollisionAlgorithm() {};
+
+	btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+	virtual ~btCollisionAlgorithm() {};
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) = 0;
+};
+
+
+#endif //BT_COLLISION_ALGORITHM_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp	(revision 11817)
@@ -0,0 +1,1295 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray<btDbvtNode*>			tNodeArray;
+typedef btAlignedObjectArray<const btDbvtNode*>	tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+	tConstNodeArray	nodes;
+	void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int			indexof(const btDbvtNode* node)
+{
+	return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume	merge(	const btDbvtVolume& a,
+									  const btDbvtVolume& b)
+{
+#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
+	ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
+	btDbvtVolume&	res=*(btDbvtVolume*)locals;
+#else
+		btDbvtVolume	res;
+#endif
+	Merge(a,b,res);
+	return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar		size(const btDbvtVolume& a)
+{
+	const btVector3	edges=a.Lengths();
+	return(	edges.x()*edges.y()*edges.z()+
+		edges.x()+edges.y()+edges.z());
+}
+
+//
+static void						getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+	if(node->isinternal())
+	{
+		getmaxdepth(node->childs[0],depth+1,maxdepth);
+		getmaxdepth(node->childs[1],depth+1,maxdepth);
+	} else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void			deletenode(	btDbvt* pdbvt,
+										   btDbvtNode* node)
+{
+	btAlignedFree(pdbvt->m_free);
+	pdbvt->m_free=node;
+}
+
+//
+static void						recursedeletenode(	btDbvt* pdbvt,
+												  btDbvtNode* node)
+{
+	if(!node->isleaf())
+	{
+		recursedeletenode(pdbvt,node->childs[0]);
+		recursedeletenode(pdbvt,node->childs[1]);
+	}
+	if(node==pdbvt->m_root) pdbvt->m_root=0;
+	deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
+										   btDbvtNode* parent,
+										   void* data)
+{
+	btDbvtNode*	node;
+	if(pdbvt->m_free)
+	{ node=pdbvt->m_free;pdbvt->m_free=0; }
+	else
+	{ node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+	node->parent	=	parent;
+	node->data		=	data;
+	node->childs[1]	=	0;
+	return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
+										   btDbvtNode* parent,
+										   const btDbvtVolume& volume,
+										   void* data)
+{
+	btDbvtNode*	node=createnode(pdbvt,parent,data);
+	node->volume=volume;
+	return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
+										   btDbvtNode* parent,
+										   const btDbvtVolume& volume0,
+										   const btDbvtVolume& volume1,
+										   void* data)
+{
+	btDbvtNode*	node=createnode(pdbvt,parent,data);
+	Merge(volume0,volume1,node->volume);
+	return(node);
+}
+
+//
+static void						insertleaf(	btDbvt* pdbvt,
+										   btDbvtNode* root,
+										   btDbvtNode* leaf)
+{
+	if(!pdbvt->m_root)
+	{
+		pdbvt->m_root	=	leaf;
+		leaf->parent	=	0;
+	}
+	else
+	{
+		if(!root->isleaf())
+		{
+			do	{
+				root=root->childs[Select(	leaf->volume,
+					root->childs[0]->volume,
+					root->childs[1]->volume)];
+			} while(!root->isleaf());
+		}
+		btDbvtNode*	prev=root->parent;
+		btDbvtNode*	node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+		if(prev)
+		{
+			prev->childs[indexof(root)]	=	node;
+			node->childs[0]				=	root;root->parent=node;
+			node->childs[1]				=	leaf;leaf->parent=node;
+			do	{
+				if(!prev->volume.Contain(node->volume))
+					Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+				else
+					break;
+				node=prev;
+			} while(0!=(prev=node->parent));
+		}
+		else
+		{
+			node->childs[0]	=	root;root->parent=node;
+			node->childs[1]	=	leaf;leaf->parent=node;
+			pdbvt->m_root	=	node;
+		}
+	}
+}
+
+//
+static btDbvtNode*				removeleaf(	btDbvt* pdbvt,
+										   btDbvtNode* leaf)
+{
+	if(leaf==pdbvt->m_root)
+	{
+		pdbvt->m_root=0;
+		return(0);
+	}
+	else
+	{
+		btDbvtNode*	parent=leaf->parent;
+		btDbvtNode*	prev=parent->parent;
+		btDbvtNode*	sibling=parent->childs[1-indexof(leaf)];			
+		if(prev)
+		{
+			prev->childs[indexof(parent)]=sibling;
+			sibling->parent=prev;
+			deletenode(pdbvt,parent);
+			while(prev)
+			{
+				const btDbvtVolume	pb=prev->volume;
+				Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+				if(NotEqual(pb,prev->volume))
+				{
+					prev=prev->parent;
+				} else break;
+			}
+			return(prev?prev:pdbvt->m_root);
+		}
+		else
+		{								
+			pdbvt->m_root=sibling;
+			sibling->parent=0;
+			deletenode(pdbvt,parent);
+			return(pdbvt->m_root);
+		}			
+	}
+}
+
+//
+static void						fetchleaves(btDbvt* pdbvt,
+											btDbvtNode* root,
+											tNodeArray& leaves,
+											int depth=-1)
+{
+	if(root->isinternal()&&depth)
+	{
+		fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+		fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+		deletenode(pdbvt,root);
+	}
+	else
+	{
+		leaves.push_back(root);
+	}
+}
+
+//
+static void						split(	const tNodeArray& leaves,
+									  tNodeArray& left,
+									  tNodeArray& right,
+									  const btVector3& org,
+									  const btVector3& axis)
+{
+	left.resize(0);
+	right.resize(0);
+	for(int i=0,ni=leaves.size();i<ni;++i)
+	{
+		if(btDot(axis,leaves[i]->volume.Center()-org)<0)
+			left.push_back(leaves[i]);
+		else
+			right.push_back(leaves[i]);
+	}
+}
+
+//
+static btDbvtVolume				bounds(	const tNodeArray& leaves)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+	ATTRIBUTE_ALIGNED16(char	locals[sizeof(btDbvtVolume)]);
+	btDbvtVolume&	volume=*(btDbvtVolume*)locals;
+	volume=leaves[0]->volume;
+#else
+	btDbvtVolume volume=leaves[0]->volume;
+#endif
+	for(int i=1,ni=leaves.size();i<ni;++i)
+	{
+		Merge(volume,leaves[i]->volume,volume);
+	}
+	return(volume);
+}
+
+//
+static void						bottomup(	btDbvt* pdbvt,
+										 tNodeArray& leaves)
+{
+	while(leaves.size()>1)
+	{
+		btScalar	minsize=SIMD_INFINITY;
+		int			minidx[2]={-1,-1};
+		for(int i=0;i<leaves.size();++i)
+		{
+			for(int j=i+1;j<leaves.size();++j)
+			{
+				const btScalar	sz=size(merge(leaves[i]->volume,leaves[j]->volume));
+				if(sz<minsize)
+				{
+					minsize		=	sz;
+					minidx[0]	=	i;
+					minidx[1]	=	j;
+				}
+			}
+		}
+		btDbvtNode*	n[]	=	{leaves[minidx[0]],leaves[minidx[1]]};
+		btDbvtNode*	p	=	createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
+		p->childs[0]		=	n[0];
+		p->childs[1]		=	n[1];
+		n[0]->parent		=	p;
+		n[1]->parent		=	p;
+		leaves[minidx[0]]	=	p;
+		leaves.swap(minidx[1],leaves.size()-1);
+		leaves.pop_back();
+	}
+}
+
+//
+static btDbvtNode*			topdown(btDbvt* pdbvt,
+									tNodeArray& leaves,
+									int bu_treshold)
+{
+	static const btVector3	axis[]={btVector3(1,0,0),
+		btVector3(0,1,0),
+		btVector3(0,0,1)};
+	if(leaves.size()>1)
+	{
+		if(leaves.size()>bu_treshold)
+		{
+			const btDbvtVolume	vol=bounds(leaves);
+			const btVector3			org=vol.Center();
+			tNodeArray				sets[2];
+			int						bestaxis=-1;
+			int						bestmidp=leaves.size();
+			int						splitcount[3][2]={{0,0},{0,0},{0,0}};
+			int i;
+			for( i=0;i<leaves.size();++i)
+			{
+				const btVector3	x=leaves[i]->volume.Center()-org;
+				for(int j=0;j<3;++j)
+				{
+					++splitcount[j][btDot(x,axis[j])>0?1:0];
+				}
+			}
+			for( i=0;i<3;++i)
+			{
+				if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+				{
+					const int	midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+					if(midp<bestmidp)
+					{
+						bestaxis=i;
+						bestmidp=midp;
+					}
+				}
+			}
+			if(bestaxis>=0)
+			{
+				sets[0].reserve(splitcount[bestaxis][0]);
+				sets[1].reserve(splitcount[bestaxis][1]);
+				split(leaves,sets[0],sets[1],org,axis[bestaxis]);
+			}
+			else
+			{
+				sets[0].reserve(leaves.size()/2+1);
+				sets[1].reserve(leaves.size()/2);
+				for(int i=0,ni=leaves.size();i<ni;++i)
+				{
+					sets[i&1].push_back(leaves[i]);
+				}
+			}
+			btDbvtNode*	node=createnode(pdbvt,0,vol,0);
+			node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
+			node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
+			node->childs[0]->parent=node;
+			node->childs[1]->parent=node;
+			return(node);
+		}
+		else
+		{
+			bottomup(pdbvt,leaves);
+			return(leaves[0]);
+		}
+	}
+	return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	sort(btDbvtNode* n,btDbvtNode*& r)
+{
+	btDbvtNode*	p=n->parent;
+	btAssert(n->isinternal());
+	if(p>n)
+	{
+		const int		i=indexof(n);
+		const int		j=1-i;
+		btDbvtNode*	s=p->childs[j];
+		btDbvtNode*	q=p->parent;
+		btAssert(n==p->childs[i]);
+		if(q) q->childs[indexof(p)]=n; else r=n;
+		s->parent=n;
+		p->parent=n;
+		n->parent=q;
+		p->childs[0]=n->childs[0];
+		p->childs[1]=n->childs[1];
+		n->childs[0]->parent=p;
+		n->childs[1]->parent=p;
+		n->childs[i]=p;
+		n->childs[j]=s;
+		btSwap(p->volume,n->volume);
+		return(p);
+	}
+	return(n);
+}
+
+#if 0
+static DBVT_INLINE btDbvtNode*	walkup(btDbvtNode* n,int count)
+{
+	while(n&&(count--)) n=n->parent;
+	return(n);
+}
+#endif
+
+//
+// Api
+//
+
+//
+btDbvt::btDbvt()
+{
+	m_root		=	0;
+	m_free		=	0;
+	m_lkhd		=	-1;
+	m_leaves	=	0;
+	m_opath		=	0;
+}
+
+//
+btDbvt::~btDbvt()
+{
+	clear();
+}
+
+//
+void			btDbvt::clear()
+{
+	if(m_root)	
+		recursedeletenode(this,m_root);
+	btAlignedFree(m_free);
+	m_free=0;
+	m_lkhd		=	-1;
+	m_stkStack.clear();
+	m_opath		=	0;
+	
+}
+
+//
+void			btDbvt::optimizeBottomUp()
+{
+	if(m_root)
+	{
+		tNodeArray leaves;
+		leaves.reserve(m_leaves);
+		fetchleaves(this,m_root,leaves);
+		bottomup(this,leaves);
+		m_root=leaves[0];
+	}
+}
+
+//
+void			btDbvt::optimizeTopDown(int bu_treshold)
+{
+	if(m_root)
+	{
+		tNodeArray	leaves;
+		leaves.reserve(m_leaves);
+		fetchleaves(this,m_root,leaves);
+		m_root=topdown(this,leaves,bu_treshold);
+	}
+}
+
+//
+void			btDbvt::optimizeIncremental(int passes)
+{
+	if(passes<0) passes=m_leaves;
+	if(m_root&&(passes>0))
+	{
+		do	{
+			btDbvtNode*		node=m_root;
+			unsigned	bit=0;
+			while(node->isinternal())
+			{
+				node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+				bit=(bit+1)&(sizeof(unsigned)*8-1);
+			}
+			update(node);
+			++m_opath;
+		} while(--passes);
+	}
+}
+
+//
+btDbvtNode*	btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+	btDbvtNode*	leaf=createnode(this,0,volume,data);
+	insertleaf(this,m_root,leaf);
+	++m_leaves;
+	return(leaf);
+}
+
+//
+void			btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+	btDbvtNode*	root=removeleaf(this,leaf);
+	if(root)
+	{
+		if(lookahead>=0)
+		{
+			for(int i=0;(i<lookahead)&&root->parent;++i)
+			{
+				root=root->parent;
+			}
+		} else root=m_root;
+	}
+	insertleaf(this,root,leaf);
+}
+
+//
+void			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
+{
+	btDbvtNode*	root=removeleaf(this,leaf);
+	if(root)
+	{
+		if(m_lkhd>=0)
+		{
+			for(int i=0;(i<m_lkhd)&&root->parent;++i)
+			{
+				root=root->parent;
+			}
+		} else root=m_root;
+	}
+	leaf->volume=volume;
+	insertleaf(this,root,leaf);
+}
+
+//
+bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
+{
+	if(leaf->volume.Contain(volume)) return(false);
+	volume.Expand(btVector3(margin,margin,margin));
+	volume.SignedExpand(velocity);
+	update(leaf,volume);
+	return(true);
+}
+
+//
+bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
+{
+	if(leaf->volume.Contain(volume)) return(false);
+	volume.SignedExpand(velocity);
+	update(leaf,volume);
+	return(true);
+}
+
+//
+bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
+{
+	if(leaf->volume.Contain(volume)) return(false);
+	volume.Expand(btVector3(margin,margin,margin));
+	update(leaf,volume);
+	return(true);
+}
+
+//
+void			btDbvt::remove(btDbvtNode* leaf)
+{
+	removeleaf(this,leaf);
+	deletenode(this,leaf);
+	--m_leaves;
+}
+
+//
+void			btDbvt::write(IWriter* iwriter) const
+{
+	btDbvtNodeEnumerator	nodes;
+	nodes.nodes.reserve(m_leaves*2);
+	enumNodes(m_root,nodes);
+	iwriter->Prepare(m_root,nodes.nodes.size());
+	for(int i=0;i<nodes.nodes.size();++i)
+	{
+		const btDbvtNode* n=nodes.nodes[i];
+		int			p=-1;
+		if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
+		if(n->isinternal())
+		{
+			const int	c0=nodes.nodes.findLinearSearch(n->childs[0]);
+			const int	c1=nodes.nodes.findLinearSearch(n->childs[1]);
+			iwriter->WriteNode(n,i,p,c0,c1);
+		}
+		else
+		{
+			iwriter->WriteLeaf(n,i,p);
+		}	
+	}
+}
+
+//
+void			btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+	dest.clear();
+	if(m_root!=0)
+	{	
+		btAlignedObjectArray<sStkCLN>	stack;
+		stack.reserve(m_leaves);
+		stack.push_back(sStkCLN(m_root,0));
+		do	{
+			const int		i=stack.size()-1;
+			const sStkCLN	e=stack[i];
+			btDbvtNode*			n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+			stack.pop_back();
+			if(e.parent!=0)
+				e.parent->childs[i&1]=n;
+			else
+				dest.m_root=n;
+			if(e.node->isinternal())
+			{
+				stack.push_back(sStkCLN(e.node->childs[0],n));
+				stack.push_back(sStkCLN(e.node->childs[1],n));
+			}
+			else
+			{
+				iclone->CloneLeaf(n);
+			}
+		} while(stack.size()>0);
+	}
+}
+
+//
+int				btDbvt::maxdepth(const btDbvtNode* node)
+{
+	int	depth=0;
+	if(node) getmaxdepth(node,1,depth);
+	return(depth);
+}
+
+//
+int				btDbvt::countLeaves(const btDbvtNode* node)
+{
+	if(node->isinternal())
+		return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+	else
+		return(1);
+}
+
+//
+void			btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
+{
+	if(node->isinternal())
+	{
+		extractLeaves(node->childs[0],leaves);
+		extractLeaves(node->childs[1],leaves);
+	}
+	else
+	{
+		leaves.push_back(node);
+	}	
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+World scale: 100.000000
+Extents base: 1.000000
+Extents range: 4.000000
+Leaves: 8192
+sizeof(btDbvtVolume): 32 bytes
+sizeof(btDbvtNode):   44 bytes
+[1] btDbvtVolume intersections: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+	struct NilPolicy : btDbvt::ICollide
+	{
+		NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true)		{}
+		void	Process(const btDbvtNode*,const btDbvtNode*)				{ ++m_pcount; }
+		void	Process(const btDbvtNode*)									{ ++m_pcount; }
+		void	Process(const btDbvtNode*,btScalar depth)
+		{
+			++m_pcount;
+			if(m_checksort)
+			{ if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+		}
+		int			m_pcount;
+		btScalar	m_depth;
+		bool		m_checksort;
+	};
+	struct P14 : btDbvt::ICollide
+	{
+		struct Node
+		{
+			const btDbvtNode*	leaf;
+			btScalar			depth;
+		};
+		void Process(const btDbvtNode* leaf,btScalar depth)
+		{
+			Node	n;
+			n.leaf	=	leaf;
+			n.depth	=	depth;
+		}
+		static int sortfnc(const Node& a,const Node& b)
+		{
+			if(a.depth<b.depth) return(+1);
+			if(a.depth>b.depth) return(-1);
+			return(0);
+		}
+		btAlignedObjectArray<Node>		m_nodes;
+	};
+	struct P15 : btDbvt::ICollide
+	{
+		struct Node
+		{
+			const btDbvtNode*	leaf;
+			btScalar			depth;
+		};
+		void Process(const btDbvtNode* leaf)
+		{
+			Node	n;
+			n.leaf	=	leaf;
+			n.depth	=	dot(leaf->volume.Center(),m_axis);
+		}
+		static int sortfnc(const Node& a,const Node& b)
+		{
+			if(a.depth<b.depth) return(+1);
+			if(a.depth>b.depth) return(-1);
+			return(0);
+		}
+		btAlignedObjectArray<Node>		m_nodes;
+		btVector3						m_axis;
+	};
+	static btScalar			RandUnit()
+	{
+		return(rand()/(btScalar)RAND_MAX);
+	}
+	static btVector3		RandVector3()
+	{
+		return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+	}
+	static btVector3		RandVector3(btScalar cs)
+	{
+		return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+	}
+	static btDbvtVolume	RandVolume(btScalar cs,btScalar eb,btScalar es)
+	{
+		return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+	}
+	static btTransform		RandTransform(btScalar cs)
+	{
+		btTransform	t;
+		t.setOrigin(RandVector3(cs));
+		t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+		return(t);
+	}
+	static void				RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+	{
+		dbvt.clear();
+		for(int i=0;i<leaves;++i)
+		{
+			dbvt.insert(RandVolume(cs,eb,es),0);
+		}
+	}
+};
+
+void			btDbvt::benchmark()
+{
+	static const btScalar	cfgVolumeCenterScale		=	100;
+	static const btScalar	cfgVolumeExentsBase			=	1;
+	static const btScalar	cfgVolumeExentsScale		=	4;
+	static const int		cfgLeaves					=	8192;
+	static const bool		cfgEnable					=	true;
+
+	//[1] btDbvtVolume intersections
+	bool					cfgBenchmark1_Enable		=	cfgEnable;
+	static const int		cfgBenchmark1_Iterations	=	8;
+	static const int		cfgBenchmark1_Reference		=	3499;
+	//[2] btDbvtVolume merges
+	bool					cfgBenchmark2_Enable		=	cfgEnable;
+	static const int		cfgBenchmark2_Iterations	=	4;
+	static const int		cfgBenchmark2_Reference		=	1945;
+	//[3] btDbvt::collideTT
+	bool					cfgBenchmark3_Enable		=	cfgEnable;
+	static const int		cfgBenchmark3_Iterations	=	512;
+	static const int		cfgBenchmark3_Reference		=	5485;
+	//[4] btDbvt::collideTT self
+	bool					cfgBenchmark4_Enable		=	cfgEnable;
+	static const int		cfgBenchmark4_Iterations	=	512;
+	static const int		cfgBenchmark4_Reference		=	2814;
+	//[5] btDbvt::collideTT xform
+	bool					cfgBenchmark5_Enable		=	cfgEnable;
+	static const int		cfgBenchmark5_Iterations	=	512;
+	static const btScalar	cfgBenchmark5_OffsetScale	=	2;
+	static const int		cfgBenchmark5_Reference		=	7379;
+	//[6] btDbvt::collideTT xform,self
+	bool					cfgBenchmark6_Enable		=	cfgEnable;
+	static const int		cfgBenchmark6_Iterations	=	512;
+	static const btScalar	cfgBenchmark6_OffsetScale	=	2;
+	static const int		cfgBenchmark6_Reference		=	7270;
+	//[7] btDbvt::rayTest
+	bool					cfgBenchmark7_Enable		=	cfgEnable;
+	static const int		cfgBenchmark7_Passes		=	32;
+	static const int		cfgBenchmark7_Iterations	=	65536;
+	static const int		cfgBenchmark7_Reference		=	6307;
+	//[8] insert/remove
+	bool					cfgBenchmark8_Enable		=	cfgEnable;
+	static const int		cfgBenchmark8_Passes		=	32;
+	static const int		cfgBenchmark8_Iterations	=	65536;
+	static const int		cfgBenchmark8_Reference		=	2105;
+	//[9] updates (teleport)
+	bool					cfgBenchmark9_Enable		=	cfgEnable;
+	static const int		cfgBenchmark9_Passes		=	32;
+	static const int		cfgBenchmark9_Iterations	=	65536;
+	static const int		cfgBenchmark9_Reference		=	1879;
+	//[10] updates (jitter)
+	bool					cfgBenchmark10_Enable		=	cfgEnable;
+	static const btScalar	cfgBenchmark10_Scale		=	cfgVolumeCenterScale/10000;
+	static const int		cfgBenchmark10_Passes		=	32;
+	static const int		cfgBenchmark10_Iterations	=	65536;
+	static const int		cfgBenchmark10_Reference	=	1244;
+	//[11] optimize (incremental)
+	bool					cfgBenchmark11_Enable		=	cfgEnable;
+	static const int		cfgBenchmark11_Passes		=	64;
+	static const int		cfgBenchmark11_Iterations	=	65536;
+	static const int		cfgBenchmark11_Reference	=	2510;
+	//[12] btDbvtVolume notequal
+	bool					cfgBenchmark12_Enable		=	cfgEnable;
+	static const int		cfgBenchmark12_Iterations	=	32;
+	static const int		cfgBenchmark12_Reference	=	3677;
+	//[13] culling(OCL+fullsort)
+	bool					cfgBenchmark13_Enable		=	cfgEnable;
+	static const int		cfgBenchmark13_Iterations	=	1024;
+	static const int		cfgBenchmark13_Reference	=	2231;
+	//[14] culling(OCL+qsort)
+	bool					cfgBenchmark14_Enable		=	cfgEnable;
+	static const int		cfgBenchmark14_Iterations	=	8192;
+	static const int		cfgBenchmark14_Reference	=	3500;
+	//[15] culling(KDOP+qsort)
+	bool					cfgBenchmark15_Enable		=	cfgEnable;
+	static const int		cfgBenchmark15_Iterations	=	8192;
+	static const int		cfgBenchmark15_Reference	=	1151;
+	//[16] insert/remove batch
+	bool					cfgBenchmark16_Enable		=	cfgEnable;
+	static const int		cfgBenchmark16_BatchCount	=	256;
+	static const int		cfgBenchmark16_Passes		=	16384;
+	static const int		cfgBenchmark16_Reference	=	5138;
+	//[17] select
+	bool					cfgBenchmark17_Enable		=	cfgEnable;
+	static const int		cfgBenchmark17_Iterations	=	4;
+	static const int		cfgBenchmark17_Reference	=	3390;
+
+	btClock					wallclock;
+	printf("Benchmarking dbvt...\r\n");
+	printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
+	printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
+	printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
+	printf("\tLeaves: %u\r\n",cfgLeaves);
+	printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
+	printf("\tsizeof(btDbvtNode):   %u bytes\r\n",sizeof(btDbvtNode));
+	if(cfgBenchmark1_Enable)
+	{// Benchmark 1	
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<bool>			results;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		printf("[1] btDbvtVolume intersections: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark1_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					results[k]=Intersect(volumes[j],volumes[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+	}
+	if(cfgBenchmark2_Enable)
+	{// Benchmark 2	
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<btDbvtVolume>	results;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		printf("[2] btDbvtVolume merges: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark2_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					Merge(volumes[j],volumes[k],results[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+	}
+	if(cfgBenchmark3_Enable)
+	{// Benchmark 3	
+		srand(380843);
+		btDbvt						dbvt[2];
+		btDbvtBenchmark::NilPolicy	policy;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+		dbvt[0].optimizeTopDown();
+		dbvt[1].optimizeTopDown();
+		printf("[3] btDbvt::collideTT: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark3_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+	}
+	if(cfgBenchmark4_Enable)
+	{// Benchmark 4
+		srand(380843);
+		btDbvt						dbvt;
+		btDbvtBenchmark::NilPolicy	policy;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[4] btDbvt::collideTT self: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark4_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+	}
+	if(cfgBenchmark5_Enable)
+	{// Benchmark 5	
+		srand(380843);
+		btDbvt								dbvt[2];
+		btAlignedObjectArray<btTransform>	transforms;
+		btDbvtBenchmark::NilPolicy			policy;
+		transforms.resize(cfgBenchmark5_Iterations);
+		for(int i=0;i<transforms.size();++i)
+		{
+			transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+		dbvt[0].optimizeTopDown();
+		dbvt[1].optimizeTopDown();
+		printf("[5] btDbvt::collideTT xform: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark5_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+	}
+	if(cfgBenchmark6_Enable)
+	{// Benchmark 6	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btTransform>	transforms;
+		btDbvtBenchmark::NilPolicy			policy;
+		transforms.resize(cfgBenchmark6_Iterations);
+		for(int i=0;i<transforms.size();++i)
+		{
+			transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[6] btDbvt::collideTT xform,self: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark6_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);		
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+	}
+	if(cfgBenchmark7_Enable)
+	{// Benchmark 7	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		rayorg;
+		btAlignedObjectArray<btVector3>		raydir;
+		btDbvtBenchmark::NilPolicy			policy;
+		rayorg.resize(cfgBenchmark7_Iterations);
+		raydir.resize(cfgBenchmark7_Iterations);
+		for(int i=0;i<rayorg.size();++i)
+		{
+			rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+			raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[7] btDbvt::rayTest: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark7_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark7_Iterations;++j)
+			{
+				btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		unsigned	rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
+		printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+	}
+	if(cfgBenchmark8_Enable)
+	{// Benchmark 8	
+		srand(380843);
+		btDbvt								dbvt;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[8] insert/remove: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark8_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark8_Iterations;++j)
+			{
+				dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
+		printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+	}
+	if(cfgBenchmark9_Enable)
+	{// Benchmark 9	
+		srand(380843);
+		btDbvt										dbvt;
+		btAlignedObjectArray<const btDbvtNode*>	leaves;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		dbvt.extractLeaves(dbvt.m_root,leaves);
+		printf("[9] updates (teleport): ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark9_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark9_Iterations;++j)
+			{
+				dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
+					btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+		printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+	}
+	if(cfgBenchmark10_Enable)
+	{// Benchmark 10	
+		srand(380843);
+		btDbvt										dbvt;
+		btAlignedObjectArray<const btDbvtNode*>	leaves;
+		btAlignedObjectArray<btVector3>				vectors;
+		vectors.resize(cfgBenchmark10_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		dbvt.extractLeaves(dbvt.m_root,leaves);
+		printf("[10] updates (jitter): ");
+		wallclock.reset();
+
+		for(int i=0;i<cfgBenchmark10_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark10_Iterations;++j)
+			{			
+				const btVector3&	d=vectors[j];
+				btDbvtNode*		l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
+				btDbvtVolume		v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+				dbvt.update(l,v);
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+		printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+	}
+	if(cfgBenchmark11_Enable)
+	{// Benchmark 11	
+		srand(380843);
+		btDbvt										dbvt;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[11] optimize (incremental): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark11_Passes;++i)
+		{
+			dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
+		printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+	}
+	if(cfgBenchmark12_Enable)
+	{// Benchmark 12	
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<bool>				results;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		printf("[12] btDbvtVolume notequal: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark12_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					results[k]=NotEqual(volumes[j],volumes[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+	}
+	if(cfgBenchmark13_Enable)
+	{// Benchmark 13	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		vectors;
+		btDbvtBenchmark::NilPolicy			policy;
+		vectors.resize(cfgBenchmark13_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[13] culling(OCL+fullsort): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark13_Iterations;++i)
+		{
+			static const btScalar	offset=0;
+			policy.m_depth=-SIMD_INFINITY;
+			dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	t=cfgBenchmark13_Iterations;
+		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+	}
+	if(cfgBenchmark14_Enable)
+	{// Benchmark 14	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		vectors;
+		btDbvtBenchmark::P14				policy;
+		vectors.resize(cfgBenchmark14_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		policy.m_nodes.reserve(cfgLeaves);
+		printf("[14] culling(OCL+qsort): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark14_Iterations;++i)
+		{
+			static const btScalar	offset=0;
+			policy.m_nodes.resize(0);
+			dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+			policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	t=cfgBenchmark14_Iterations;
+		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+	}
+	if(cfgBenchmark15_Enable)
+	{// Benchmark 15	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		vectors;
+		btDbvtBenchmark::P15				policy;
+		vectors.resize(cfgBenchmark15_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		policy.m_nodes.reserve(cfgLeaves);
+		printf("[15] culling(KDOP+qsort): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark15_Iterations;++i)
+		{
+			static const btScalar	offset=0;
+			policy.m_nodes.resize(0);
+			policy.m_axis=vectors[i];
+			dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+			policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	t=cfgBenchmark15_Iterations;
+		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+	}
+	if(cfgBenchmark16_Enable)
+	{// Benchmark 16	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btDbvtNode*>	batch;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		batch.reserve(cfgBenchmark16_BatchCount);
+		printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark16_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+			{
+				batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+			}
+			for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+			{
+				dbvt.remove(batch[j]);
+			}
+			batch.resize(0);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
+		printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+	}
+	if(cfgBenchmark17_Enable)
+	{// Benchmark 17
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<int>			results;
+		btAlignedObjectArray<int>			indices;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		indices.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			indices[i]=i;
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			btSwap(indices[i],indices[rand()%cfgLeaves]);
+		}
+		printf("[17] btDbvtVolume select: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark17_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					const int idx=indices[k];
+					results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+	}
+	printf("\r\n\r\n");
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvt.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvt.h	(revision 11817)
@@ -0,0 +1,1256 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAabbUtil2.h"
+
+//
+// Compile time configuration
+//
+
+
+// Implementation profiles
+#define DBVT_IMPL_GENERIC		0	// Generic implementation	
+#define DBVT_IMPL_SSE			1	// SSE
+
+// Template implementation of ICollide
+#ifdef _WIN32
+#if (defined (_MSC_VER) && _MSC_VER >= 1400)
+#define	DBVT_USE_TEMPLATE		1
+#else
+#define	DBVT_USE_TEMPLATE		0
+#endif
+#else
+#define	DBVT_USE_TEMPLATE		0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE	1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE		1
+
+// Enable benchmarking code
+#define	DBVT_ENABLE_BENCHMARK	0
+
+// Inlining
+#define DBVT_INLINE				SIMD_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined (BT_USE_SSE) && defined (_WIN32)
+#define DBVT_SELECT_IMPL		DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL			DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL			DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL		DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL			DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL			DBVT_IMPL_GENERIC
+#endif
+
+#if	(DBVT_SELECT_IMPL==DBVT_IMPL_SSE)||	\
+	(DBVT_MERGE_IMPL==DBVT_IMPL_SSE)||	\
+	(DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define	DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX					template <typename T>
+#define DBVT_IPOLICY				T& policy
+#define DBVT_CHECKTYPE				static const ICollide&	typechecker=*(T*)1;(void)typechecker;
+#else
+#define	DBVT_VIRTUAL_DTOR(a)		virtual ~a() {}
+#define DBVT_VIRTUAL				virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY				ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm			*/ 
+struct	btDbvtAabbMm
+{
+	DBVT_INLINE btVector3			Center() const	{ return((mi+mx)/2); }
+	DBVT_INLINE btVector3			Lengths() const	{ return(mx-mi); }
+	DBVT_INLINE btVector3			Extents() const	{ return((mx-mi)/2); }
+	DBVT_INLINE const btVector3&	Mins() const	{ return(mi); }
+	DBVT_INLINE const btVector3&	Maxs() const	{ return(mx); }
+	static inline btDbvtAabbMm		FromCE(const btVector3& c,const btVector3& e);
+	static inline btDbvtAabbMm		FromCR(const btVector3& c,btScalar r);
+	static inline btDbvtAabbMm		FromMM(const btVector3& mi,const btVector3& mx);
+	static inline btDbvtAabbMm		FromPoints(const btVector3* pts,int n);
+	static inline btDbvtAabbMm		FromPoints(const btVector3** ppts,int n);
+	DBVT_INLINE void				Expand(const btVector3& e);
+	DBVT_INLINE void				SignedExpand(const btVector3& e);
+	DBVT_INLINE bool				Contain(const btDbvtAabbMm& a) const;
+	DBVT_INLINE int					Classify(const btVector3& n,btScalar o,int s) const;
+	DBVT_INLINE btScalar			ProjectMinimum(const btVector3& v,unsigned signs) const;
+	DBVT_INLINE friend bool			Intersect(	const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+	
+	DBVT_INLINE friend bool			Intersect(	const btDbvtAabbMm& a,
+		const btVector3& b);
+
+	DBVT_INLINE friend btScalar		Proximity(	const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+	DBVT_INLINE friend int			Select(		const btDbvtAabbMm& o,
+		const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+	DBVT_INLINE friend void			Merge(		const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b,
+		btDbvtAabbMm& r);
+	DBVT_INLINE friend bool			NotEqual(	const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+private:
+	DBVT_INLINE void				AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+	btVector3	mi,mx;
+};
+
+// Types	
+typedef	btDbvtAabbMm	btDbvtVolume;
+
+/* btDbvtNode				*/ 
+struct	btDbvtNode
+{
+	btDbvtVolume	volume;
+	btDbvtNode*		parent;
+	DBVT_INLINE bool	isleaf() const		{ return(childs[1]==0); }
+	DBVT_INLINE bool	isinternal() const	{ return(!isleaf()); }
+	union
+	{
+		btDbvtNode*	childs[2];
+		void*	data;
+		int		dataAsInt;
+	};
+};
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct	btDbvt
+{
+	/* Stack element	*/ 
+	struct	sStkNN
+	{
+		const btDbvtNode*	a;
+		const btDbvtNode*	b;
+		sStkNN() {}
+		sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+	};
+	struct	sStkNP
+	{
+		const btDbvtNode*	node;
+		int			mask;
+		sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+	};
+	struct	sStkNPS
+	{
+		const btDbvtNode*	node;
+		int			mask;
+		btScalar	value;
+		sStkNPS() {}
+		sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+	};
+	struct	sStkCLN
+	{
+		const btDbvtNode*	node;
+		btDbvtNode*		parent;
+		sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+	};
+	// Policies/Interfaces
+
+	/* ICollide	*/ 
+	struct	ICollide
+	{		
+		DBVT_VIRTUAL_DTOR(ICollide)
+			DBVT_VIRTUAL void	Process(const btDbvtNode*,const btDbvtNode*)		{}
+		DBVT_VIRTUAL void	Process(const btDbvtNode*)					{}
+		DBVT_VIRTUAL void	Process(const btDbvtNode* n,btScalar)			{ Process(n); }
+		DBVT_VIRTUAL bool	Descent(const btDbvtNode*)					{ return(true); }
+		DBVT_VIRTUAL bool	AllLeaves(const btDbvtNode*)					{ return(true); }
+	};
+	/* IWriter	*/ 
+	struct	IWriter
+	{
+		virtual ~IWriter() {}
+		virtual void		Prepare(const btDbvtNode* root,int numnodes)=0;
+		virtual void		WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+		virtual void		WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+	};
+	/* IClone	*/ 
+	struct	IClone
+	{
+		virtual ~IClone()	{}
+		virtual void		CloneLeaf(btDbvtNode*) {}
+	};
+
+	// Constants
+	enum	{
+		SIMPLE_STACKSIZE	=	64,
+		DOUBLE_STACKSIZE	=	SIMPLE_STACKSIZE*2
+	};
+
+	// Fields
+	btDbvtNode*		m_root;
+	btDbvtNode*		m_free;
+	int				m_lkhd;
+	int				m_leaves;
+	unsigned		m_opath;
+
+	
+	btAlignedObjectArray<sStkNN>	m_stkStack;
+
+
+	// Methods
+	btDbvt();
+	~btDbvt();
+	void			clear();
+	bool			empty() const { return(0==m_root); }
+	void			optimizeBottomUp();
+	void			optimizeTopDown(int bu_treshold=128);
+	void			optimizeIncremental(int passes);
+	btDbvtNode*		insert(const btDbvtVolume& box,void* data);
+	void			update(btDbvtNode* leaf,int lookahead=-1);
+	void			update(btDbvtNode* leaf,btDbvtVolume& volume);
+	bool			update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin);
+	bool			update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity);
+	bool			update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin);	
+	void			remove(btDbvtNode* leaf);
+	void			write(IWriter* iwriter) const;
+	void			clone(btDbvt& dest,IClone* iclone=0) const;
+	static int		maxdepth(const btDbvtNode* node);
+	static int		countLeaves(const btDbvtNode* node);
+	static void		extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves);
+#if DBVT_ENABLE_BENCHMARK
+	static void		benchmark();
+#else
+	static void		benchmark(){}
+#endif
+	// DBVT_IPOLICY must support ICollide policy/interface
+	DBVT_PREFIX
+		static void		enumNodes(	const btDbvtNode* root,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		static void		enumLeaves(	const btDbvtNode* root,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		void		collideTT(	const btDbvtNode* root0,
+		const btDbvtNode* root1,
+		DBVT_IPOLICY);
+
+	DBVT_PREFIX
+		void		collideTTpersistentStack(	const btDbvtNode* root0,
+		  const btDbvtNode* root1,
+		  DBVT_IPOLICY);
+#if 0
+	DBVT_PREFIX
+		void		collideTT(	const btDbvtNode* root0,
+		const btDbvtNode* root1,
+		const btTransform& xform,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		void		collideTT(	const btDbvtNode* root0,
+		const btTransform& xform0,
+		const btDbvtNode* root1,
+		const btTransform& xform1,
+		DBVT_IPOLICY);
+#endif
+
+	DBVT_PREFIX
+		void		collideTV(	const btDbvtNode* root,
+		const btDbvtVolume& volume,
+		DBVT_IPOLICY);
+	///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
+	///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+	DBVT_PREFIX
+		static void		rayTest(	const btDbvtNode* root,
+		const btVector3& rayFrom,
+		const btVector3& rayTo,
+		DBVT_IPOLICY);
+	///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+	///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
+	DBVT_PREFIX
+		void		rayTestInternal(	const btDbvtNode* root,
+								const btVector3& rayFrom,
+								const btVector3& rayTo,
+								const btVector3& rayDirectionInverse,
+								unsigned int signs[3],
+								btScalar lambda_max,
+								const btVector3& aabbMin,
+								const btVector3& aabbMax,
+								DBVT_IPOLICY) const;
+
+	DBVT_PREFIX
+		static void		collideKDOP(const btDbvtNode* root,
+		const btVector3* normals,
+		const btScalar* offsets,
+		int count,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		static void		collideOCL(	const btDbvtNode* root,
+		const btVector3* normals,
+		const btScalar* offsets,
+		const btVector3& sortaxis,
+		int count,								
+		DBVT_IPOLICY,
+		bool fullsort=true);
+	DBVT_PREFIX
+		static void		collideTU(	const btDbvtNode* root,
+		DBVT_IPOLICY);
+	// Helpers	
+	static DBVT_INLINE int	nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+	{
+		int	m=0;
+		while(l<h)
+		{
+			m=(l+h)>>1;
+			if(a[i[m]].value>=v) l=m+1; else h=m;
+		}
+		return(h);
+	}
+	static DBVT_INLINE int	allocate(	btAlignedObjectArray<int>& ifree,
+		btAlignedObjectArray<sStkNPS>& stock,
+		const sStkNPS& value)
+	{
+		int	i;
+		if(ifree.size()>0)
+		{ i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+		else
+		{ i=stock.size();stock.push_back(value); }
+		return(i); 
+	}
+	//
+private:
+	btDbvt(const btDbvt&)	{}	
+};
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+	btDbvtAabbMm box;
+	box.mi=c-e;box.mx=c+e;
+	return(box);
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+	return(FromCE(c,btVector3(r,r,r)));
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+	btDbvtAabbMm box;
+	box.mi=mi;box.mx=mx;
+	return(box);
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+	btDbvtAabbMm box;
+	box.mi=box.mx=pts[0];
+	for(int i=1;i<n;++i)
+	{
+		box.mi.setMin(pts[i]);
+		box.mx.setMax(pts[i]);
+	}
+	return(box);
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
+{
+	btDbvtAabbMm box;
+	box.mi=box.mx=*ppts[0];
+	for(int i=1;i<n;++i)
+	{
+		box.mi.setMin(*ppts[i]);
+		box.mx.setMax(*ppts[i]);
+	}
+	return(box);
+}
+
+//
+DBVT_INLINE void		btDbvtAabbMm::Expand(const btVector3& e)
+{
+	mi-=e;mx+=e;
+}
+
+//
+DBVT_INLINE void		btDbvtAabbMm::SignedExpand(const btVector3& e)
+{
+	if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
+	if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
+	if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+}
+
+//
+DBVT_INLINE bool		btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+	return(	(mi.x()<=a.mi.x())&&
+		(mi.y()<=a.mi.y())&&
+		(mi.z()<=a.mi.z())&&
+		(mx.x()>=a.mx.x())&&
+		(mx.y()>=a.mx.y())&&
+		(mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int		btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+	btVector3			pi,px;
+	switch(s)
+	{
+	case	(0+0+0):	px=btVector3(mi.x(),mi.y(),mi.z());
+		pi=btVector3(mx.x(),mx.y(),mx.z());break;
+	case	(1+0+0):	px=btVector3(mx.x(),mi.y(),mi.z());
+		pi=btVector3(mi.x(),mx.y(),mx.z());break;
+	case	(0+2+0):	px=btVector3(mi.x(),mx.y(),mi.z());
+		pi=btVector3(mx.x(),mi.y(),mx.z());break;
+	case	(1+2+0):	px=btVector3(mx.x(),mx.y(),mi.z());
+		pi=btVector3(mi.x(),mi.y(),mx.z());break;
+	case	(0+0+4):	px=btVector3(mi.x(),mi.y(),mx.z());
+		pi=btVector3(mx.x(),mx.y(),mi.z());break;
+	case	(1+0+4):	px=btVector3(mx.x(),mi.y(),mx.z());
+		pi=btVector3(mi.x(),mx.y(),mi.z());break;
+	case	(0+2+4):	px=btVector3(mi.x(),mx.y(),mx.z());
+		pi=btVector3(mx.x(),mi.y(),mi.z());break;
+	case	(1+2+4):	px=btVector3(mx.x(),mx.y(),mx.z());
+		pi=btVector3(mi.x(),mi.y(),mi.z());break;
+	}
+	if((btDot(n,px)+o)<0)		return(-1);
+	if((btDot(n,pi)+o)>=0)	return(+1);
+	return(0);
+}
+
+//
+DBVT_INLINE btScalar	btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+	const btVector3*	b[]={&mx,&mi};
+	const btVector3		p(	b[(signs>>0)&1]->x(),
+		b[(signs>>1)&1]->y(),
+		b[(signs>>2)&1]->z());
+	return(btDot(p,v));
+}
+
+//
+DBVT_INLINE void		btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+	for(int i=0;i<3;++i)
+	{
+		if(d[i]<0)
+		{ smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+		else
+		{ smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+	}
+}
+
+//
+DBVT_INLINE bool		Intersect(	const btDbvtAabbMm& a,
+								  const btDbvtAabbMm& b)
+{
+#if	DBVT_INT0_IMPL == DBVT_IMPL_SSE
+	const __m128	rt(_mm_or_ps(	_mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+		_mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+	const __int32*	pu((const __int32*)&rt);
+	return((pu[0]|pu[1]|pu[2])==0);
+#else
+	return(	(a.mi.x()<=b.mx.x())&&
+		(a.mx.x()>=b.mi.x())&&
+		(a.mi.y()<=b.mx.y())&&
+		(a.mx.y()>=b.mi.y())&&
+		(a.mi.z()<=b.mx.z())&&		
+		(a.mx.z()>=b.mi.z()));
+#endif
+}
+
+
+
+//
+DBVT_INLINE bool		Intersect(	const btDbvtAabbMm& a,
+								  const btVector3& b)
+{
+	return(	(b.x()>=a.mi.x())&&
+		(b.y()>=a.mi.y())&&
+		(b.z()>=a.mi.z())&&
+		(b.x()<=a.mx.x())&&
+		(b.y()<=a.mx.y())&&
+		(b.z()<=a.mx.z()));
+}
+
+
+
+
+
+//////////////////////////////////////
+
+
+//
+DBVT_INLINE btScalar	Proximity(	const btDbvtAabbMm& a,
+								  const btDbvtAabbMm& b)
+{
+	const btVector3	d=(a.mi+a.mx)-(b.mi+b.mx);
+	return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+}
+
+
+
+//
+DBVT_INLINE int			Select(	const btDbvtAabbMm& o,
+							   const btDbvtAabbMm& a,
+							   const btDbvtAabbMm& b)
+{
+#if	DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+	static ATTRIBUTE_ALIGNED16(const unsigned __int32)	mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+	///@todo: the intrinsic version is 11% slower
+#if DBVT_USE_INTRINSIC_SSE
+
+	union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
+	{
+	   __m128		ssereg;
+	   float		floats[4];
+	   int			ints[4];
+	};
+
+	__m128	omi(_mm_load_ps(o.mi));
+	omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+	__m128	ami(_mm_load_ps(a.mi));
+	ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+	ami=_mm_sub_ps(ami,omi);
+	ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+	__m128	bmi(_mm_load_ps(b.mi));
+	bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+	bmi=_mm_sub_ps(bmi,omi);
+	bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+	__m128	t0(_mm_movehl_ps(ami,ami));
+	ami=_mm_add_ps(ami,t0);
+	ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+	__m128 t1(_mm_movehl_ps(bmi,bmi));
+	bmi=_mm_add_ps(bmi,t1);
+	bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+	
+	btSSEUnion tmp;
+	tmp.ssereg = _mm_cmple_ss(bmi,ami);
+	return tmp.ints[0]&1;
+
+#else
+	ATTRIBUTE_ALIGNED16(__int32	r[1]);
+	__asm
+	{
+		mov		eax,o
+			mov		ecx,a
+			mov		edx,b
+			movaps	xmm0,[eax]
+		movaps	xmm5,mask
+			addps	xmm0,[eax+16]	
+		movaps	xmm1,[ecx]
+		movaps	xmm2,[edx]
+		addps	xmm1,[ecx+16]
+		addps	xmm2,[edx+16]
+		subps	xmm1,xmm0
+			subps	xmm2,xmm0
+			andps	xmm1,xmm5
+			andps	xmm2,xmm5
+			movhlps	xmm3,xmm1
+			movhlps	xmm4,xmm2
+			addps	xmm1,xmm3
+			addps	xmm2,xmm4
+			pshufd	xmm3,xmm1,1
+			pshufd	xmm4,xmm2,1
+			addss	xmm1,xmm3
+			addss	xmm2,xmm4
+			cmpless	xmm2,xmm1
+			movss	r,xmm2
+	}
+	return(r[0]&1);
+#endif
+#else
+	return(Proximity(o,a)<Proximity(o,b)?0:1);
+#endif
+}
+
+//
+DBVT_INLINE void		Merge(	const btDbvtAabbMm& a,
+							  const btDbvtAabbMm& b,
+							  btDbvtAabbMm& r)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+	__m128	ami(_mm_load_ps(a.mi));
+	__m128	amx(_mm_load_ps(a.mx));
+	__m128	bmi(_mm_load_ps(b.mi));
+	__m128	bmx(_mm_load_ps(b.mx));
+	ami=_mm_min_ps(ami,bmi);
+	amx=_mm_max_ps(amx,bmx);
+	_mm_store_ps(r.mi,ami);
+	_mm_store_ps(r.mx,amx);
+#else
+	for(int i=0;i<3;++i)
+	{
+		if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
+		if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+	}
+#endif
+}
+
+//
+DBVT_INLINE bool		NotEqual(	const btDbvtAabbMm& a,
+								 const btDbvtAabbMm& b)
+{
+	return(	(a.mi.x()!=b.mi.x())||
+		(a.mi.y()!=b.mi.y())||
+		(a.mi.z()!=b.mi.z())||
+		(a.mx.x()!=b.mx.x())||
+		(a.mx.y()!=b.mx.y())||
+		(a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void		btDbvt::enumNodes(	const btDbvtNode* root,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		policy.Process(root);
+	if(root->isinternal())
+	{
+		enumNodes(root->childs[0],policy);
+		enumNodes(root->childs[1],policy);
+	}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::enumLeaves(	const btDbvtNode* root,
+								   DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root->isinternal())
+		{
+			enumLeaves(root->childs[0],policy);
+			enumLeaves(root->childs[1],policy);
+		}
+		else
+		{
+			policy.Process(root);
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTT(	const btDbvtNode* root0,
+								  const btDbvtNode* root1,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root0&&root1)
+		{
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-4;
+			btAlignedObjectArray<sStkNN>	stkStack;
+			stkStack.resize(DOUBLE_STACKSIZE);
+			stkStack[0]=sStkNN(root0,root1);
+			do	{		
+				sStkNN	p=stkStack[--depth];
+				if(depth>treshold)
+				{
+					stkStack.resize(stkStack.size()*2);
+					treshold=stkStack.size()-4;
+				}
+				if(p.a==p.b)
+				{
+					if(p.a->isinternal())
+					{
+						stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+						stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+						stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+					}
+				}
+				else if(Intersect(p.a->volume,p.b->volume))
+				{
+					if(p.a->isinternal())
+					{
+						if(p.b->isinternal())
+						{
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+						}
+						else
+						{
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+						}
+					}
+					else
+					{
+						if(p.b->isinternal())
+						{
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+						}
+						else
+						{
+							policy.Process(p.a,p.b);
+						}
+					}
+				}
+			} while(depth);
+		}
+}
+
+
+
+DBVT_PREFIX
+inline void		btDbvt::collideTTpersistentStack(	const btDbvtNode* root0,
+								  const btDbvtNode* root1,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root0&&root1)
+		{
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-4;
+			
+			m_stkStack.resize(DOUBLE_STACKSIZE);
+			m_stkStack[0]=sStkNN(root0,root1);
+			do	{		
+				sStkNN	p=m_stkStack[--depth];
+				if(depth>treshold)
+				{
+					m_stkStack.resize(m_stkStack.size()*2);
+					treshold=m_stkStack.size()-4;
+				}
+				if(p.a==p.b)
+				{
+					if(p.a->isinternal())
+					{
+						m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+						m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+						m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+					}
+				}
+				else if(Intersect(p.a->volume,p.b->volume))
+				{
+					if(p.a->isinternal())
+					{
+						if(p.b->isinternal())
+						{
+							m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+							m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+							m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+							m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+						}
+						else
+						{
+							m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+							m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+						}
+					}
+					else
+					{
+						if(p.b->isinternal())
+						{
+							m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+							m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+						}
+						else
+						{
+							policy.Process(p.a,p.b);
+						}
+					}
+				}
+			} while(depth);
+		}
+}
+
+#if 0
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTT(	const btDbvtNode* root0,
+								  const btDbvtNode* root1,
+								  const btTransform& xform,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root0&&root1)
+		{
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-4;
+			btAlignedObjectArray<sStkNN>	stkStack;
+			stkStack.resize(DOUBLE_STACKSIZE);
+			stkStack[0]=sStkNN(root0,root1);
+			do	{
+				sStkNN	p=stkStack[--depth];
+				if(Intersect(p.a->volume,p.b->volume,xform))
+				{
+					if(depth>treshold)
+					{
+						stkStack.resize(stkStack.size()*2);
+						treshold=stkStack.size()-4;
+					}
+					if(p.a->isinternal())
+					{
+						if(p.b->isinternal())
+						{					
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+						}
+						else
+						{
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+						}
+					}
+					else
+					{
+						if(p.b->isinternal())
+						{
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+						}
+						else
+						{
+							policy.Process(p.a,p.b);
+						}
+					}
+				}
+			} while(depth);
+		}
+}
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTT(	const btDbvtNode* root0,
+								  const btTransform& xform0,
+								  const btDbvtNode* root1,
+								  const btTransform& xform1,
+								  DBVT_IPOLICY)
+{
+	const btTransform	xform=xform0.inverse()*xform1;
+	collideTT(root0,root1,xform,policy);
+}
+#endif 
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTV(	const btDbvtNode* root,
+								  const btDbvtVolume& vol,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			ATTRIBUTE_ALIGNED16(btDbvtVolume)		volume(vol);
+			btAlignedObjectArray<const btDbvtNode*>	stack;
+			stack.resize(0);
+			stack.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(root);
+			do	{
+				const btDbvtNode*	n=stack[stack.size()-1];
+				stack.pop_back();
+				if(Intersect(n->volume,volume))
+				{
+					if(n->isinternal())
+					{
+						stack.push_back(n->childs[0]);
+						stack.push_back(n->childs[1]);
+					}
+					else
+					{
+						policy.Process(n);
+					}
+				}
+			} while(stack.size()>0);
+		}
+}
+
+DBVT_PREFIX
+inline void		btDbvt::rayTestInternal(	const btDbvtNode* root,
+								const btVector3& rayFrom,
+								const btVector3& rayTo,
+								const btVector3& rayDirectionInverse,
+								unsigned int signs[3],
+								btScalar lambda_max,
+								const btVector3& aabbMin,
+								const btVector3& aabbMax,
+								DBVT_IPOLICY) const
+{
+        (void) rayTo;
+	DBVT_CHECKTYPE
+	if(root)
+	{
+		btVector3 resultNormal;
+
+		int								depth=1;
+		int								treshold=DOUBLE_STACKSIZE-2;
+		btAlignedObjectArray<const btDbvtNode*>	stack;
+		stack.resize(DOUBLE_STACKSIZE);
+		stack[0]=root;
+		btVector3 bounds[2];
+		do	
+		{
+			const btDbvtNode*	node=stack[--depth];
+			bounds[0] = node->volume.Mins()-aabbMax;
+			bounds[1] = node->volume.Maxs()-aabbMin;
+			btScalar tmin=1.f,lambda_min=0.f;
+			unsigned int result1=false;
+			result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+			if(result1)
+			{
+				if(node->isinternal())
+				{
+					if(depth>treshold)
+					{
+						stack.resize(stack.size()*2);
+						treshold=stack.size()-2;
+					}
+					stack[depth++]=node->childs[0];
+					stack[depth++]=node->childs[1];
+				}
+				else
+				{
+					policy.Process(node);
+				}
+			}
+		} while(depth);
+	}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::rayTest(	const btDbvtNode* root,
+								const btVector3& rayFrom,
+								const btVector3& rayTo,
+								DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			btVector3 rayDir = (rayTo-rayFrom);
+			rayDir.normalize ();
+
+			///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+			btVector3 rayDirectionInverse;
+			rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+			rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+			rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+			unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+			btScalar lambda_max = rayDir.dot(rayTo-rayFrom);
+
+			btVector3 resultNormal;
+
+			btAlignedObjectArray<const btDbvtNode*>	stack;
+
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-2;
+
+			stack.resize(DOUBLE_STACKSIZE);
+			stack[0]=root;
+			btVector3 bounds[2];
+			do	{
+				const btDbvtNode*	node=stack[--depth];
+
+				bounds[0] = node->volume.Mins();
+				bounds[1] = node->volume.Maxs();
+				
+				btScalar tmin=1.f,lambda_min=0.f;
+				unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+				btScalar param=1.f;
+				bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
+				btAssert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
+
+				if(result1)
+				{
+					if(node->isinternal())
+					{
+						if(depth>treshold)
+						{
+							stack.resize(stack.size()*2);
+							treshold=stack.size()-2;
+						}
+						stack[depth++]=node->childs[0];
+						stack[depth++]=node->childs[1];
+					}
+					else
+					{
+						policy.Process(node);
+					}
+				}
+			} while(depth);
+
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideKDOP(const btDbvtNode* root,
+									const btVector3* normals,
+									const btScalar* offsets,
+									int count,
+									DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			const int						inside=(1<<count)-1;
+			btAlignedObjectArray<sStkNP>	stack;
+			int								signs[sizeof(unsigned)*8];
+			btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+			for(int i=0;i<count;++i)
+			{
+				signs[i]=	((normals[i].x()>=0)?1:0)+
+					((normals[i].y()>=0)?2:0)+
+					((normals[i].z()>=0)?4:0);
+			}
+			stack.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(sStkNP(root,0));
+			do	{
+				sStkNP	se=stack[stack.size()-1];
+				bool	out=false;
+				stack.pop_back();
+				for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+				{
+					if(0==(se.mask&j))
+					{
+						const int	side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+						switch(side)
+						{
+						case	-1:	out=true;break;
+						case	+1:	se.mask|=j;break;
+						}
+					}
+				}
+				if(!out)
+				{
+					if((se.mask!=inside)&&(se.node->isinternal()))
+					{
+						stack.push_back(sStkNP(se.node->childs[0],se.mask));
+						stack.push_back(sStkNP(se.node->childs[1],se.mask));
+					}
+					else
+					{
+						if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+					}
+				}
+			} while(stack.size());
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideOCL(	const btDbvtNode* root,
+								   const btVector3* normals,
+								   const btScalar* offsets,
+								   const btVector3& sortaxis,
+								   int count,
+								   DBVT_IPOLICY,
+								   bool fsort)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			const unsigned					srtsgns=(sortaxis[0]>=0?1:0)+
+				(sortaxis[1]>=0?2:0)+
+				(sortaxis[2]>=0?4:0);
+			const int						inside=(1<<count)-1;
+			btAlignedObjectArray<sStkNPS>	stock;
+			btAlignedObjectArray<int>		ifree;
+			btAlignedObjectArray<int>		stack;
+			int								signs[sizeof(unsigned)*8];
+			btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+			for(int i=0;i<count;++i)
+			{
+				signs[i]=	((normals[i].x()>=0)?1:0)+
+					((normals[i].y()>=0)?2:0)+
+					((normals[i].z()>=0)?4:0);
+			}
+			stock.reserve(SIMPLE_STACKSIZE);
+			stack.reserve(SIMPLE_STACKSIZE);
+			ifree.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+			do	{
+				const int	id=stack[stack.size()-1];
+				sStkNPS		se=stock[id];
+				stack.pop_back();ifree.push_back(id);
+				if(se.mask!=inside)
+				{
+					bool	out=false;
+					for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+					{
+						if(0==(se.mask&j))
+						{
+							const int	side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+							switch(side)
+							{
+							case	-1:	out=true;break;
+							case	+1:	se.mask|=j;break;
+							}
+						}
+					}
+					if(out) continue;
+				}
+				if(policy.Descent(se.node))
+				{
+					if(se.node->isinternal())
+					{
+						const btDbvtNode* pns[]={	se.node->childs[0],se.node->childs[1]};
+						sStkNPS		nes[]={	sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+							sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+						const int	q=nes[0].value<nes[1].value?1:0;				
+						int			j=stack.size();
+						if(fsort&&(j>0))
+						{
+							/* Insert 0	*/ 
+							j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+							stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+							memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+							for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+							stack[j]=allocate(ifree,stock,nes[q]);
+							/* Insert 1	*/ 
+							j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+							stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+							memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+							for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+							stack[j]=allocate(ifree,stock,nes[1-q]);
+						}
+						else
+						{
+							stack.push_back(allocate(ifree,stock,nes[q]));
+							stack.push_back(allocate(ifree,stock,nes[1-q]));
+						}
+					}
+					else
+					{
+						policy.Process(se.node,se.value);
+					}
+				}
+			} while(stack.size());
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTU(	const btDbvtNode* root,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			btAlignedObjectArray<const btDbvtNode*>	stack;
+			stack.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(root);
+			do	{
+				const btDbvtNode*	n=stack[stack.size()-1];
+				stack.pop_back();
+				if(policy.Descent(n))
+				{
+					if(n->isinternal())
+					{ stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+					else
+					{ policy.Process(n); }
+				}
+			} while(stack.size()>0);
+		}
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp	(revision 11817)
@@ -0,0 +1,796 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+
+#include "btDbvtBroadphase.h"
+
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
+#include <stdio.h>
+#endif
+
+#if DBVT_BP_PROFILE
+struct	ProfileScope
+{
+	__forceinline ProfileScope(btClock& clock,unsigned long& value) :
+	m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+	{
+	}
+	__forceinline ~ProfileScope()
+	{
+		(*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+	}
+	btClock*		m_clock;
+	unsigned long*	m_value;
+	unsigned long	m_base;
+};
+#define	SPC(_value_)	ProfileScope	spc_scope(m_clock,_value_)
+#else
+#define	SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template <typename T>
+static inline void	listappend(T* item,T*& list)
+{
+	item->links[0]=0;
+	item->links[1]=list;
+	if(list) list->links[0]=item;
+	list=item;
+}
+
+//
+template <typename T>
+static inline void	listremove(T* item,T*& list)
+{
+	if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+	if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template <typename T>
+static inline int	listcount(T* root)
+{
+	int	n=0;
+	while(root) { ++n;root=root->links[1]; }
+	return(n);
+}
+
+//
+template <typename T>
+static inline void	clear(T& value)
+{
+	static const struct ZeroDummy : T {} zerodummy;
+	value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider	*/ 
+struct	btDbvtTreeCollider : btDbvt::ICollide
+{
+	btDbvtBroadphase*	pbp;
+	btDbvtProxy*		proxy;
+	btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+	void	Process(const btDbvtNode* na,const btDbvtNode* nb)
+	{
+		if(na!=nb)
+		{
+			btDbvtProxy*	pa=(btDbvtProxy*)na->data;
+			btDbvtProxy*	pb=(btDbvtProxy*)nb->data;
+#if DBVT_BP_SORTPAIRS
+			if(pa->m_uniqueId>pb->m_uniqueId) 
+				btSwap(pa,pb);
+#endif
+			pbp->m_paircache->addOverlappingPair(pa,pb);
+			++pbp->m_newpairs;
+		}
+	}
+	void	Process(const btDbvtNode* n)
+	{
+		Process(n,proxy->leaf);
+	}
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+	m_deferedcollide	=	false;
+	m_needcleanup		=	true;
+	m_releasepaircache	=	(paircache!=0)?false:true;
+	m_prediction		=	0;
+	m_stageCurrent		=	0;
+	m_fixedleft			=	0;
+	m_fupdates			=	1;
+	m_dupdates			=	0;
+	m_cupdates			=	10;
+	m_newpairs			=	1;
+	m_updates_call		=	0;
+	m_updates_done		=	0;
+	m_updates_ratio		=	0;
+	m_paircache			=	paircache? paircache	: new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+	m_gid				=	0;
+	m_pid				=	0;
+	m_cid				=	0;
+	for(int i=0;i<=STAGECOUNT;++i)
+	{
+		m_stageRoots[i]=0;
+	}
+#if DBVT_BP_PROFILE
+	clear(m_profiling);
+#endif
+}
+
+//
+btDbvtBroadphase::~btDbvtBroadphase()
+{
+	if(m_releasepaircache) 
+	{
+		m_paircache->~btOverlappingPairCache();
+		btAlignedFree(m_paircache);
+	}
+}
+
+//
+btBroadphaseProxy*				btDbvtBroadphase::createProxy(	const btVector3& aabbMin,
+															  const btVector3& aabbMax,
+															  int /*shapeType*/,
+															  void* userPtr,
+															  short int collisionFilterGroup,
+															  short int collisionFilterMask,
+															  btDispatcher* /*dispatcher*/,
+															  void* /*multiSapProxy*/)
+{
+	btDbvtProxy*		proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy(	aabbMin,aabbMax,userPtr,
+		collisionFilterGroup,
+		collisionFilterMask);
+
+	btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+
+	//bproxy->aabb			=	btDbvtVolume::FromMM(aabbMin,aabbMax);
+	proxy->stage		=	m_stageCurrent;
+	proxy->m_uniqueId	=	++m_gid;
+	proxy->leaf			=	m_sets[0].insert(aabb,proxy);
+	listappend(proxy,m_stageRoots[m_stageCurrent]);
+	if(!m_deferedcollide)
+	{
+		btDbvtTreeCollider	collider(this);
+		collider.proxy=proxy;
+		m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
+		m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+	}
+	return(proxy);
+}
+
+//
+void							btDbvtBroadphase::destroyProxy(	btBroadphaseProxy* absproxy,
+															   btDispatcher* dispatcher)
+{
+	btDbvtProxy*	proxy=(btDbvtProxy*)absproxy;
+	if(proxy->stage==STAGECOUNT)
+		m_sets[1].remove(proxy->leaf);
+	else
+		m_sets[0].remove(proxy->leaf);
+	listremove(proxy,m_stageRoots[proxy->stage]);
+	m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+	btAlignedFree(proxy);
+	m_needcleanup=true;
+}
+
+void	btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy;
+	aabbMin = proxy->m_aabbMin;
+	aabbMax = proxy->m_aabbMax;
+}
+
+struct	BroadphaseRayTester : btDbvt::ICollide
+{
+	btBroadphaseRayCallback& m_rayCallback;
+	BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
+		:m_rayCallback(orgCallback)
+	{
+	}
+	void					Process(const btDbvtNode* leaf)
+	{
+		btDbvtProxy*	proxy=(btDbvtProxy*)leaf->data;
+		m_rayCallback.process(proxy);
+	}
+};	
+
+void	btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	BroadphaseRayTester callback(rayCallback);
+
+	m_sets[0].rayTestInternal(	m_sets[0].m_root,
+		rayFrom,
+		rayTo,
+		rayCallback.m_rayDirectionInverse,
+		rayCallback.m_signs,
+		rayCallback.m_lambda_max,
+		aabbMin,
+		aabbMax,
+		callback);
+
+	m_sets[1].rayTestInternal(	m_sets[1].m_root,
+		rayFrom,
+		rayTo,
+		rayCallback.m_rayDirectionInverse,
+		rayCallback.m_signs,
+		rayCallback.m_lambda_max,
+		aabbMin,
+		aabbMax,
+		callback);
+
+}
+
+
+struct	BroadphaseAabbTester : btDbvt::ICollide
+{
+	btBroadphaseAabbCallback& m_aabbCallback;
+	BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
+		:m_aabbCallback(orgCallback)
+	{
+	}
+	void					Process(const btDbvtNode* leaf)
+	{
+		btDbvtProxy*	proxy=(btDbvtProxy*)leaf->data;
+		m_aabbCallback.process(proxy);
+	}
+};	
+
+void	btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
+{
+	BroadphaseAabbTester callback(aabbCallback);
+
+	const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(aabbMin,aabbMax);
+		//process all children, that overlap with  the given AABB bounds
+	m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
+	m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
+
+}
+
+
+
+//
+void							btDbvtBroadphase::setAabb(		btBroadphaseProxy* absproxy,
+														  const btVector3& aabbMin,
+														  const btVector3& aabbMax,
+														  btDispatcher* /*dispatcher*/)
+{
+	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy;
+	ATTRIBUTE_ALIGNED16(btDbvtVolume)	aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+#if DBVT_BP_PREVENTFALSEUPDATE
+	if(NotEqual(aabb,proxy->leaf->volume))
+#endif
+	{
+		bool	docollide=false;
+		if(proxy->stage==STAGECOUNT)
+		{/* fixed -> dynamic set	*/ 
+			m_sets[1].remove(proxy->leaf);
+			proxy->leaf=m_sets[0].insert(aabb,proxy);
+			docollide=true;
+		}
+		else
+		{/* dynamic set				*/ 
+			++m_updates_call;
+			if(Intersect(proxy->leaf->volume,aabb))
+			{/* Moving				*/ 
+
+				const btVector3	delta=aabbMin-proxy->m_aabbMin;
+				btVector3		velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
+				if(delta[0]<0) velocity[0]=-velocity[0];
+				if(delta[1]<0) velocity[1]=-velocity[1];
+				if(delta[2]<0) velocity[2]=-velocity[2];
+				if	(
+#ifdef DBVT_BP_MARGIN				
+					m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
+#else
+					m_sets[0].update(proxy->leaf,aabb,velocity)
+#endif
+					)
+				{
+					++m_updates_done;
+					docollide=true;
+				}
+			}
+			else
+			{/* Teleporting			*/ 
+				m_sets[0].update(proxy->leaf,aabb);
+				++m_updates_done;
+				docollide=true;
+			}	
+		}
+		listremove(proxy,m_stageRoots[proxy->stage]);
+		proxy->m_aabbMin = aabbMin;
+		proxy->m_aabbMax = aabbMax;
+		proxy->stage	=	m_stageCurrent;
+		listappend(proxy,m_stageRoots[m_stageCurrent]);
+		if(docollide)
+		{
+			m_needcleanup=true;
+			if(!m_deferedcollide)
+			{
+				btDbvtTreeCollider	collider(this);
+				m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+				m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+			}
+		}	
+	}
+}
+
+
+//
+void							btDbvtBroadphase::setAabbForceUpdate(		btBroadphaseProxy* absproxy,
+														  const btVector3& aabbMin,
+														  const btVector3& aabbMax,
+														  btDispatcher* /*dispatcher*/)
+{
+	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy;
+	ATTRIBUTE_ALIGNED16(btDbvtVolume)	aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+	bool	docollide=false;
+	if(proxy->stage==STAGECOUNT)
+	{/* fixed -> dynamic set	*/ 
+		m_sets[1].remove(proxy->leaf);
+		proxy->leaf=m_sets[0].insert(aabb,proxy);
+		docollide=true;
+	}
+	else
+	{/* dynamic set				*/ 
+		++m_updates_call;
+		/* Teleporting			*/ 
+		m_sets[0].update(proxy->leaf,aabb);
+		++m_updates_done;
+		docollide=true;
+	}
+	listremove(proxy,m_stageRoots[proxy->stage]);
+	proxy->m_aabbMin = aabbMin;
+	proxy->m_aabbMax = aabbMax;
+	proxy->stage	=	m_stageCurrent;
+	listappend(proxy,m_stageRoots[m_stageCurrent]);
+	if(docollide)
+	{
+		m_needcleanup=true;
+		if(!m_deferedcollide)
+		{
+			btDbvtTreeCollider	collider(this);
+			m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+		}
+	}	
+}
+
+//
+void							btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+	collide(dispatcher);
+#if DBVT_BP_PROFILE
+	if(0==(m_pid%DBVT_BP_PROFILING_RATE))
+	{	
+		printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+		unsigned int	total=m_profiling.m_total;
+		if(total<=0) total=1;
+		printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
+		printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
+		printf("cleanup:   %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
+		printf("total:     %uus\r\n",total/DBVT_BP_PROFILING_RATE);
+		const unsigned long	sum=m_profiling.m_ddcollide+
+			m_profiling.m_fdcollide+
+			m_profiling.m_cleanup;
+		printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
+		printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+		clear(m_profiling);
+		m_clock.reset();
+	}
+#endif
+
+	performDeferredRemoval(dispatcher);
+
+}
+
+void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
+{
+
+	if (m_paircache->hasDeferredRemoval())
+	{
+
+		btBroadphasePairArray&	overlappingPairArray = m_paircache->getOverlappingPairArray();
+
+		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+		int invalidPair = 0;
+
+		
+		int i;
+
+		btBroadphasePair previousPair;
+		previousPair.m_pProxy0 = 0;
+		previousPair.m_pProxy1 = 0;
+		previousPair.m_algorithm = 0;
+		
+		
+		for (i=0;i<overlappingPairArray.size();i++)
+		{
+		
+			btBroadphasePair& pair = overlappingPairArray[i];
+
+			bool isDuplicate = (pair == previousPair);
+
+			previousPair = pair;
+
+			bool needsRemoval = false;
+
+			if (!isDuplicate)
+			{
+				//important to perform AABB check that is consistent with the broadphase
+				btDbvtProxy*		pa=(btDbvtProxy*)pair.m_pProxy0;
+				btDbvtProxy*		pb=(btDbvtProxy*)pair.m_pProxy1;
+				bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume);
+
+				if (hasOverlap)
+				{
+					needsRemoval = false;
+				} else
+				{
+					needsRemoval = true;
+				}
+			} else
+			{
+				//remove duplicate
+				needsRemoval = true;
+				//should have no algorithm
+				btAssert(!pair.m_algorithm);
+			}
+			
+			if (needsRemoval)
+			{
+				m_paircache->cleanOverlappingPair(pair,dispatcher);
+
+				pair.m_pProxy0 = 0;
+				pair.m_pProxy1 = 0;
+				invalidPair++;
+			} 
+			
+		}
+
+		//perform a sort, to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+		overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+	}
+}
+
+//
+void							btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+	/*printf("---------------------------------------------------------\n");
+	printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+	printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+	printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+	{
+		int i;
+		for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
+		{
+			printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+				getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+		}
+		printf("\n");
+	}
+*/
+
+
+
+	SPC(m_profiling.m_total);
+	/* optimize				*/ 
+	m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+	if(m_fixedleft)
+	{
+		const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
+		m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+		m_fixedleft=btMax<int>(0,m_fixedleft-count);
+	}
+	/* dynamic -> fixed set	*/ 
+	m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+	btDbvtProxy*	current=m_stageRoots[m_stageCurrent];
+	if(current)
+	{
+		btDbvtTreeCollider	collider(this);
+		do	{
+			btDbvtProxy*	next=current->links[1];
+			listremove(current,m_stageRoots[current->stage]);
+			listappend(current,m_stageRoots[STAGECOUNT]);
+#if DBVT_BP_ACCURATESLEEPING
+			m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
+			collider.proxy=current;
+			btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
+			btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
+#endif
+			m_sets[0].remove(current->leaf);
+			ATTRIBUTE_ALIGNED16(btDbvtVolume)	curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
+			current->leaf	=	m_sets[1].insert(curAabb,current);
+			current->stage	=	STAGECOUNT;	
+			current			=	next;
+		} while(current);
+		m_fixedleft=m_sets[1].m_leaves;
+		m_needcleanup=true;
+	}
+	/* collide dynamics		*/ 
+	{
+		btDbvtTreeCollider	collider(this);
+		if(m_deferedcollide)
+		{
+			SPC(m_profiling.m_fdcollide);
+			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+		}
+		if(m_deferedcollide)
+		{
+			SPC(m_profiling.m_ddcollide);
+			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+		}
+	}
+	/* clean up				*/ 
+	if(m_needcleanup)
+	{
+		SPC(m_profiling.m_cleanup);
+		btBroadphasePairArray&	pairs=m_paircache->getOverlappingPairArray();
+		if(pairs.size()>0)
+		{
+
+			int			ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
+			for(int i=0;i<ni;++i)
+			{
+				btBroadphasePair&	p=pairs[(m_cid+i)%pairs.size()];
+				btDbvtProxy*		pa=(btDbvtProxy*)p.m_pProxy0;
+				btDbvtProxy*		pb=(btDbvtProxy*)p.m_pProxy1;
+				if(!Intersect(pa->leaf->volume,pb->leaf->volume))
+				{
+#if DBVT_BP_SORTPAIRS
+					if(pa->m_uniqueId>pb->m_uniqueId) 
+						btSwap(pa,pb);
+#endif
+					m_paircache->removeOverlappingPair(pa,pb,dispatcher);
+					--ni;--i;
+				}
+			}
+			if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+		}
+	}
+	++m_pid;
+	m_newpairs=1;
+	m_needcleanup=false;
+	if(m_updates_call>0)
+	{ m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
+	else
+	{ m_updates_ratio=0; }
+	m_updates_done/=2;
+	m_updates_call/=2;
+}
+
+//
+void							btDbvtBroadphase::optimize()
+{
+	m_sets[0].optimizeTopDown();
+	m_sets[1].optimizeTopDown();
+}
+
+//
+btOverlappingPairCache*			btDbvtBroadphase::getOverlappingPairCache()
+{
+	return(m_paircache);
+}
+
+//
+const btOverlappingPairCache*	btDbvtBroadphase::getOverlappingPairCache() const
+{
+	return(m_paircache);
+}
+
+//
+void							btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+	ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds;
+
+	if(!m_sets[0].empty())
+		if(!m_sets[1].empty())	Merge(	m_sets[0].m_root->volume,
+			m_sets[1].m_root->volume,bounds);
+		else
+			bounds=m_sets[0].m_root->volume;
+	else if(!m_sets[1].empty())	bounds=m_sets[1].m_root->volume;
+	else
+		bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
+	aabbMin=bounds.Mins();
+	aabbMax=bounds.Maxs();
+}
+
+void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
+{
+	
+	int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+	if (!totalObjects)
+	{
+		//reset internal dynamic tree data structures
+		m_sets[0].clear();
+		m_sets[1].clear();
+		
+		m_deferedcollide	=	false;
+		m_needcleanup		=	true;
+		m_stageCurrent		=	0;
+		m_fixedleft			=	0;
+		m_fupdates			=	1;
+		m_dupdates			=	0;
+		m_cupdates			=	10;
+		m_newpairs			=	1;
+		m_updates_call		=	0;
+		m_updates_done		=	0;
+		m_updates_ratio		=	0;
+		
+		m_gid				=	0;
+		m_pid				=	0;
+		m_cid				=	0;
+		for(int i=0;i<=STAGECOUNT;++i)
+		{
+			m_stageRoots[i]=0;
+		}
+	}
+}
+
+//
+void							btDbvtBroadphase::printStats()
+{}
+
+//
+#if DBVT_BP_ENABLE_BENCHMARK
+
+struct	btBroadphaseBenchmark
+{
+	struct	Experiment
+	{
+		const char*			name;
+		int					object_count;
+		int					update_count;
+		int					spawn_count;
+		int					iterations;
+		btScalar			speed;
+		btScalar			amplitude;
+	};
+	struct	Object
+	{
+		btVector3			center;
+		btVector3			extents;
+		btBroadphaseProxy*	proxy;
+		btScalar			time;
+		void				update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
+		{
+			time		+=	speed;
+			center[0]	=	btCos(time*(btScalar)2.17)*amplitude+
+				btSin(time)*amplitude/2;
+			center[1]	=	btCos(time*(btScalar)1.38)*amplitude+
+				btSin(time)*amplitude;
+			center[2]	=	btSin(time*(btScalar)0.777)*amplitude;
+			pbi->setAabb(proxy,center-extents,center+extents,0);
+		}
+	};
+	static int		UnsignedRand(int range=RAND_MAX-1)	{ return(rand()%(range+1)); }
+	static btScalar	UnitRand()							{ return(UnsignedRand(16384)/(btScalar)16384); }
+	static void		OutputTime(const char* name,btClock& c,unsigned count=0)
+	{
+		const unsigned long	us=c.getTimeMicroseconds();
+		const unsigned long	ms=(us+500)/1000;
+		const btScalar		sec=us/(btScalar)(1000*1000);
+		if(count>0)
+			printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+		else
+			printf("%s : %u us (%u ms)\r\n",name,us,ms);
+	}
+};
+
+void							btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+{
+	static const btBroadphaseBenchmark::Experiment		experiments[]=
+	{
+		{"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
+		/*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+		{"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
+	};
+	static const int										nexperiments=sizeof(experiments)/sizeof(experiments[0]);
+	btAlignedObjectArray<btBroadphaseBenchmark::Object*>	objects;
+	btClock													wallclock;
+	/* Begin			*/ 
+	for(int iexp=0;iexp<nexperiments;++iexp)
+	{
+		const btBroadphaseBenchmark::Experiment&	experiment=experiments[iexp];
+		const int									object_count=experiment.object_count;
+		const int									update_count=(object_count*experiment.update_count)/100;
+		const int									spawn_count=(object_count*experiment.spawn_count)/100;
+		const btScalar								speed=experiment.speed;	
+		const btScalar								amplitude=experiment.amplitude;
+		printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
+		printf("\tObjects: %u\r\n",object_count);
+		printf("\tUpdate: %u\r\n",update_count);
+		printf("\tSpawn: %u\r\n",spawn_count);
+		printf("\tSpeed: %f\r\n",speed);
+		printf("\tAmplitude: %f\r\n",amplitude);
+		srand(180673);
+		/* Create objects	*/ 
+		wallclock.reset();
+		objects.reserve(object_count);
+		for(int i=0;i<object_count;++i)
+		{
+			btBroadphaseBenchmark::Object*	po=new btBroadphaseBenchmark::Object();
+			po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
+			po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
+			po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
+			po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
+			po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
+			po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
+			po->time=btBroadphaseBenchmark::UnitRand()*2000;
+			po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+			objects.push_back(po);
+		}
+		btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
+		/* First update		*/ 
+		wallclock.reset();
+		for(int i=0;i<objects.size();++i)
+		{
+			objects[i]->update(speed,amplitude,pbi);
+		}
+		btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
+		/* Updates			*/ 
+		wallclock.reset();
+		for(int i=0;i<experiment.iterations;++i)
+		{
+			for(int j=0;j<update_count;++j)
+			{				
+				objects[j]->update(speed,amplitude,pbi);
+			}
+			pbi->calculateOverlappingPairs(0);
+		}
+		btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
+		/* Clean up			*/ 
+		wallclock.reset();
+		for(int i=0;i<objects.size();++i)
+		{
+			pbi->destroyProxy(objects[i]->proxy,0);
+			delete objects[i];
+		}
+		objects.resize(0);
+		btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+	}
+
+}
+#else
+void							btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{}
+#endif
+
+#if DBVT_BP_PROFILE
+#undef	SPC
+#endif
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h	(revision 11817)
@@ -0,0 +1,146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define	DBVT_BP_PROFILE					0
+//#define DBVT_BP_SORTPAIRS				1
+#define DBVT_BP_PREVENTFALSEUPDATE		0
+#define DBVT_BP_ACCURATESLEEPING		0
+#define DBVT_BP_ENABLE_BENCHMARK		0
+#define DBVT_BP_MARGIN					(btScalar)0.05
+
+#if DBVT_BP_PROFILE
+#define	DBVT_BP_PROFILING_RATE	256
+#include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+	/* Fields		*/ 
+	//btDbvtAabbMm	aabb;
+	btDbvtNode*		leaf;
+	btDbvtProxy*	links[2];
+	int				stage;
+	/* ctor			*/ 
+	btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
+	btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+	{
+		links[0]=links[1]=0;
+	}
+};
+
+typedef btAlignedObjectArray<btDbvtProxy*>	btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct	btDbvtBroadphase : btBroadphaseInterface
+{
+	/* Config		*/ 
+	enum	{
+		DYNAMIC_SET			=	0,	/* Dynamic set index	*/ 
+		FIXED_SET			=	1,	/* Fixed set index		*/ 
+		STAGECOUNT			=	2	/* Number of stages		*/ 
+	};
+	/* Fields		*/ 
+	btDbvt					m_sets[2];					// Dbvt sets
+	btDbvtProxy*			m_stageRoots[STAGECOUNT+1];	// Stages list
+	btOverlappingPairCache*	m_paircache;				// Pair cache
+	btScalar				m_prediction;				// Velocity prediction
+	int						m_stageCurrent;				// Current stage
+	int						m_fupdates;					// % of fixed updates per frame
+	int						m_dupdates;					// % of dynamic updates per frame
+	int						m_cupdates;					// % of cleanup updates per frame
+	int						m_newpairs;					// Number of pairs created
+	int						m_fixedleft;				// Fixed optimization left
+	unsigned				m_updates_call;				// Number of updates call
+	unsigned				m_updates_done;				// Number of updates done
+	btScalar				m_updates_ratio;			// m_updates_done/m_updates_call
+	int						m_pid;						// Parse id
+	int						m_cid;						// Cleanup index
+	int						m_gid;						// Gen id
+	bool					m_releasepaircache;			// Release pair cache on delete
+	bool					m_deferedcollide;			// Defere dynamic/static collision to collide call
+	bool					m_needcleanup;				// Need to run cleanup?
+#if DBVT_BP_PROFILE
+	btClock					m_clock;
+	struct	{
+		unsigned long		m_total;
+		unsigned long		m_ddcollide;
+		unsigned long		m_fdcollide;
+		unsigned long		m_cleanup;
+		unsigned long		m_jobcount;
+	}				m_profiling;
+#endif
+	/* Methods		*/ 
+	btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+	~btDbvtBroadphase();
+	void							collide(btDispatcher* dispatcher);
+	void							optimize();
+	
+	/* btBroadphaseInterface Implementation	*/
+	btBroadphaseProxy*				createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+	virtual void					destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void					setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+	virtual void					rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+	virtual void					aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+	virtual void					getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+	virtual	void					calculateOverlappingPairs(btDispatcher* dispatcher);
+	virtual	btOverlappingPairCache*	getOverlappingPairCache();
+	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const;
+	virtual	void					getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+	virtual	void					printStats();
+
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher);
+
+	void	performDeferredRemoval(btDispatcher* dispatcher);
+	
+	void	setVelocityPrediction(btScalar prediction)
+	{
+		m_prediction = prediction;
+	}
+	btScalar getVelocityPrediction() const
+	{
+		return m_prediction;
+	}
+
+	///this setAabbForceUpdate is similar to setAabb but always forces the aabb update. 
+	///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
+	///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+	///http://code.google.com/p/bullet/issues/detail?id=223
+	void							setAabbForceUpdate(		btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
+
+	static void						benchmark(btBroadphaseInterface*);
+
+
+};
+
+#endif
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp	(revision 11817)
@@ -0,0 +1,22 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDispatcher.h"
+
+btDispatcher::~btDispatcher()
+{
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DISPATCHER_H
+#define BT_DISPATCHER_H
+#include "LinearMath/btScalar.h"
+
+class btCollisionAlgorithm;
+struct btBroadphaseProxy;
+class btRigidBody;
+class	btCollisionObject;
+class btOverlappingPairCache;
+
+
+class btPersistentManifold;
+class btStackAlloc;
+class btPoolAllocator;
+
+struct btDispatcherInfo
+{
+	enum DispatchFunc
+	{
+		DISPATCH_DISCRETE = 1,
+		DISPATCH_CONTINUOUS
+	};
+	btDispatcherInfo()
+		:m_timeStep(btScalar(0.)),
+		m_stepCount(0),
+		m_dispatchFunc(DISPATCH_DISCRETE),
+		m_timeOfImpact(btScalar(1.)),
+		m_useContinuous(true),
+		m_debugDraw(0),
+		m_enableSatConvex(false),
+		m_enableSPU(true),
+		m_useEpa(true),
+		m_allowedCcdPenetration(btScalar(0.04)),
+		m_useConvexConservativeDistanceUtil(false),
+		m_convexConservativeDistanceThreshold(0.0f),
+		m_stackAllocator(0)
+	{
+
+	}
+	btScalar	m_timeStep;
+	int			m_stepCount;
+	int			m_dispatchFunc;
+	mutable btScalar	m_timeOfImpact;
+	bool		m_useContinuous;
+	class btIDebugDraw*	m_debugDraw;
+	bool		m_enableSatConvex;
+	bool		m_enableSPU;
+	bool		m_useEpa;
+	btScalar	m_allowedCcdPenetration;
+	bool		m_useConvexConservativeDistanceUtil;
+	btScalar	m_convexConservativeDistanceThreshold;
+	btStackAlloc*	m_stackAllocator;
+};
+
+///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
+///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
+class btDispatcher
+{
+
+
+public:
+	virtual ~btDispatcher() ;
+
+	virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0;
+
+	virtual btPersistentManifold*	getNewManifold(void* body0,void* body1)=0;
+
+	virtual void releaseManifold(btPersistentManifold* manifold)=0;
+
+	virtual void clearManifold(btPersistentManifold* manifold)=0;
+
+	virtual bool	needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0;
+
+	virtual bool	needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
+
+	virtual void	dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)  =0;
+
+	virtual int getNumManifolds() const = 0;
+
+	virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
+
+	virtual	btPersistentManifold**	getInternalManifoldPointer() = 0;
+
+	virtual	btPoolAllocator*	getInternalManifoldPool() = 0;
+
+	virtual	const btPoolAllocator*	getInternalManifoldPool() const = 0;
+
+	virtual	void* allocateCollisionAlgorithm(int size)  = 0;
+
+	virtual	void freeCollisionAlgorithm(void* ptr) = 0;
+
+};
+
+
+#endif //BT_DISPATCHER_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp	(revision 11817)
@@ -0,0 +1,489 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMultiSapBroadphase.h"
+
+#include "btSimpleBroadphase.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btQuantizedBvh.h"
+
+///	btSapBroadphaseArray	m_sapBroadphases;
+
+///	btOverlappingPairCache*	m_overlappingPairs;
+extern int gOverlappingPairs;
+
+/*
+class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
+{
+public:
+
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+	{
+		return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
+	}
+};
+
+*/
+
+btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
+:m_overlappingPairs(pairCache),
+m_optimizedAabbTree(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+	if (!m_overlappingPairs)
+	{
+		m_ownsPairCache = true;
+		void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
+		m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
+	}
+
+	struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
+	{
+		virtual ~btMultiSapOverlapFilterCallback()
+		{}
+		// return true when pairs need collision
+		virtual bool	needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
+		{
+			btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
+			btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
+			
+			bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
+			collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
+	
+			return collides;
+		}
+	};
+
+	void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
+	m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
+
+	m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
+//	mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
+//	m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
+}
+
+btMultiSapBroadphase::~btMultiSapBroadphase()
+{
+	if (m_ownsPairCache)
+	{
+		m_overlappingPairs->~btOverlappingPairCache();
+		btAlignedFree(m_overlappingPairs);
+	}
+}
+
+
+void	btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
+{
+	m_optimizedAabbTree = new btQuantizedBvh();
+	m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
+	QuantizedNodeArray&	nodes = m_optimizedAabbTree->getLeafNodeArray();
+	for (int i=0;i<m_sapBroadphases.size();i++)
+	{
+		btQuantizedBvhNode node;
+		btVector3 aabbMin,aabbMax;
+		m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
+		m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+		m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+		int partId = 0;
+		node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+		nodes.push_back(node);
+	}
+	m_optimizedAabbTree->buildInternal();
+}
+
+btBroadphaseProxy*	btMultiSapBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
+{
+	//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
+
+	void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
+	btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin,  aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
+	m_multiSapProxies.push_back(proxy);
+
+	///this should deal with inserting/removal into child broadphases
+	setAabb(proxy,aabbMin,aabbMax,dispatcher);
+	return proxy;
+}
+
+void	btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+{
+	///not yet
+	btAssert(0);
+
+}
+
+
+void	btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*	childBroadphase)
+{
+	void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
+	btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
+	bridgeProxyRef->m_childProxy = childProxy;
+	bridgeProxyRef->m_childBroadphase = childBroadphase;
+	parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
+}
+
+
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
+{
+return
+amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
+amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
+amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
+}
+
+
+
+
+
+
+void	btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+	aabbMin = multiProxy->m_aabbMin;
+	aabbMax = multiProxy->m_aabbMax;
+}
+
+void	btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	for (int i=0;i<m_multiSapProxies.size();i++)
+	{
+		rayCallback.process(m_multiSapProxies[i]);
+	}
+}
+
+
+//#include <stdio.h>
+
+void	btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+	btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+	multiProxy->m_aabbMin = aabbMin;
+	multiProxy->m_aabbMax = aabbMax;
+	
+	
+//	bool fullyContained = false;
+//	bool alreadyInSimple = false;
+	
+
+
+	
+	struct MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btMultiSapBroadphase*	m_multiSap;
+		btMultiSapProxy*		m_multiProxy;
+		btDispatcher*			m_dispatcher;
+
+		MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
+			:m_multiSap(multiSap),
+			m_multiProxy(multiProxy),
+			m_dispatcher(dispatcher)
+		{
+
+		}
+
+		virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
+		{
+			btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
+
+			int containingBroadphaseIndex = -1;
+			//already found?
+			for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
+			{
+
+				if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+				{
+					containingBroadphaseIndex = i;
+					break;
+				}
+			}
+			if (containingBroadphaseIndex<0)
+			{
+				//add it
+				btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
+				m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
+
+			}
+		}
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(this,multiProxy,dispatcher);
+
+
+
+	
+	if (m_optimizedAabbTree)
+		m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+
+	int i;
+
+	for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+	{
+		btVector3 worldAabbMin,worldAabbMax;
+		multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+		bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+		if (!overlapsBroadphase)
+		{
+			//remove it now
+			btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
+
+			btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+			bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+			
+			multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
+			multiProxy->m_bridgeProxies.pop_back();
+
+		}
+	}
+
+
+	/*
+
+	if (1)
+	{
+
+		//find broadphase that contain this multiProxy
+		int numChildBroadphases = getBroadphaseArray().size();
+		for (int i=0;i<numChildBroadphases;i++)
+		{
+			btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+			btVector3 worldAabbMin,worldAabbMax;
+			childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+			bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+			
+		//	fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+			int containingBroadphaseIndex = -1;
+			
+			//if already contains this
+			
+			for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
+			{
+				if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+				{
+					containingBroadphaseIndex = i;
+				}
+				alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
+			}
+
+			if (overlapsBroadphase)
+			{
+				if (containingBroadphaseIndex<0)
+				{
+					btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+					childProxy->m_multiSapParentProxy = multiProxy;
+					addToChildBroadphase(multiProxy,childProxy,childBroadphase);
+				}
+			} else
+			{
+				if (containingBroadphaseIndex>=0)
+				{
+					//remove
+					btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
+
+					btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+					bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+					
+					multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
+					multiProxy->m_bridgeProxies.pop_back();
+				}
+			}
+		}
+
+
+		///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
+		///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
+		if (0)//!multiProxy->m_bridgeProxies.size())
+		{
+			///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+			///this is needed to be able to calculate the aabb overlap
+			btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+			childProxy->m_multiSapParentProxy = multiProxy;
+			addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+		}
+	}
+
+	if (!multiProxy->m_bridgeProxies.size())
+	{
+		///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+		///this is needed to be able to calculate the aabb overlap
+		btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+		childProxy->m_multiSapParentProxy = multiProxy;
+		addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+	}
+*/
+
+
+	//update
+	for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+	{
+		btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
+		bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
+	}
+
+}
+bool stopUpdating=false;
+
+
+
+class btMultiSapBroadphasePairSortPredicate
+{
+	public:
+
+		bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
+		{
+				btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
+				btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
+				btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
+				btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
+
+				 return aProxy0 > bProxy0 || 
+					(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
+					(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); 
+		}
+};
+
+
+        ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+void    btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+//	m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
+
+	if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
+	{
+	
+		btBroadphasePairArray&	overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
+
+	//	quicksort(overlappingPairArray,0,overlappingPairArray.size());
+
+		overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+	//	overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+
+		
+		int i;
+
+		btBroadphasePair previousPair;
+		previousPair.m_pProxy0 = 0;
+		previousPair.m_pProxy1 = 0;
+		previousPair.m_algorithm = 0;
+		
+		
+		for (i=0;i<overlappingPairArray.size();i++)
+		{
+		
+			btBroadphasePair& pair = overlappingPairArray[i];
+
+			btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
+			btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
+			btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
+			btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
+
+			bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
+			
+			previousPair = pair;
+
+			bool needsRemoval = false;
+
+			if (!isDuplicate)
+			{
+				bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+				if (hasOverlap)
+				{
+					needsRemoval = false;//callback->processOverlap(pair);
+				} else
+				{
+					needsRemoval = true;
+				}
+			} else
+			{
+				//remove duplicate
+				needsRemoval = true;
+				//should have no algorithm
+				btAssert(!pair.m_algorithm);
+			}
+			
+			if (needsRemoval)
+			{
+				getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
+
+		//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+		//		m_overlappingPairArray.pop_back();
+				pair.m_pProxy0 = 0;
+				pair.m_pProxy1 = 0;
+				m_invalidPair++;
+				gOverlappingPairs--;
+			} 
+			
+		}
+
+	///if you don't like to skip the invalid pairs in the array, execute following code:
+	#define CLEAN_INVALID_PAIRS 1
+	#ifdef CLEAN_INVALID_PAIRS
+
+		//perform a sort, to sort 'invalid' pairs to the end
+		//overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+		overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+	#endif//CLEAN_INVALID_PAIRS
+		
+		//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+	}
+
+
+}
+
+
+bool	btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
+{
+	btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
+		btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
+
+		return	TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
+			multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
+		
+}
+
+
+void	btMultiSapBroadphase::printStats()
+{
+/*	printf("---------------------------------\n");
+	
+		printf("btMultiSapBroadphase.h\n");
+		printf("numHandles = %d\n",m_multiSapProxies.size());
+			//find broadphase that contain this multiProxy
+		int numChildBroadphases = getBroadphaseArray().size();
+		for (int i=0;i<numChildBroadphases;i++)
+		{
+
+			btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+			childBroadphase->printStats();
+
+		}
+		*/
+
+}
+
+void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
+{
+	// not yet
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h	(revision 11817)
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_MULTI_SAP_BROADPHASE
+#define BT_MULTI_SAP_BROADPHASE
+
+#include "btBroadphaseInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCache.h"
+
+
+class btBroadphaseInterface;
+class btSimpleBroadphase;
+
+
+typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
+
+///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
+///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
+///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
+///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
+///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
+///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
+class btMultiSapBroadphase :public btBroadphaseInterface
+{
+	btSapBroadphaseArray	m_sapBroadphases;
+	
+	btSimpleBroadphase*		m_simpleBroadphase;
+
+	btOverlappingPairCache*	m_overlappingPairs;
+
+	class btQuantizedBvh*			m_optimizedAabbTree;
+
+
+	bool					m_ownsPairCache;
+	
+	btOverlapFilterCallback*	m_filterCallback;
+
+	int			m_invalidPair;
+
+	struct	btBridgeProxy
+	{
+		btBroadphaseProxy*		m_childProxy;
+		btBroadphaseInterface*	m_childBroadphase;
+	};
+
+
+public:
+
+	struct	btMultiSapProxy	: public btBroadphaseProxy
+	{
+
+		///array with all the entries that this proxy belongs to
+		btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
+		btVector3	m_aabbMin;
+		btVector3	m_aabbMax;
+
+		int	m_shapeType;
+
+/*		void*	m_userPtr;
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+*/
+		btMultiSapProxy(const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
+			:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
+			m_aabbMin(aabbMin),
+			m_aabbMax(aabbMax),
+			m_shapeType(shapeType)
+		{
+			m_multiSapParentProxy =this;
+		}
+
+		
+	};
+
+protected:
+
+
+	btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
+
+public:
+
+	btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
+
+
+	btSapBroadphaseArray&	getBroadphaseArray()
+	{
+		return m_sapBroadphases;
+	}
+
+	const btSapBroadphaseArray&	getBroadphaseArray() const
+	{
+		return m_sapBroadphases;
+	}
+
+	virtual ~btMultiSapBroadphase();
+
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
+
+	void	addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*	childBroadphase);
+
+	///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher);
+
+	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+	virtual	btOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_overlappingPairs;
+	}
+	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const
+	{
+		return m_overlappingPairs;
+	}
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+		aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+	}
+
+	void	buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+
+	virtual void	printStats();
+
+	void quicksort (btBroadphasePairArray& a, int lo, int hi);
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher);
+
+};
+
+#endif //BT_MULTI_SAP_BROADPHASE
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp	(revision 11817)
@@ -0,0 +1,633 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btOverlappingPairCache.h"
+
+#include "btDispatcher.h"
+#include "btCollisionAlgorithm.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <stdio.h>
+
+int	gOverlappingPairs = 0;
+
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
+
+
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache():
+	m_overlapFilterCallback(0),
+	m_blockedForChanges(false),
+	m_ghostPairCallback(0)
+{
+	int initialAllocatedSize= 2;
+	m_overlappingPairArray.reserve(initialAllocatedSize);
+	growTables();
+}
+
+
+
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
+{
+}
+
+
+
+void	btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+	if (pair.m_algorithm)
+	{
+		{
+			pair.m_algorithm->~btCollisionAlgorithm();
+			dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+			pair.m_algorithm=0;
+		}
+	}
+}
+
+
+
+
+void	btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	CleanPairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_cleanProxy;
+		btOverlappingPairCache*	m_pairCache;
+		btDispatcher* m_dispatcher;
+
+	public:
+		CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+			:m_cleanProxy(cleanProxy),
+			m_pairCache(pairCache),
+			m_dispatcher(dispatcher)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			if ((pair.m_pProxy0 == m_cleanProxy) ||
+				(pair.m_pProxy1 == m_cleanProxy))
+			{
+				m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+			}
+			return false;
+		}
+		
+	};
+
+	CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+	processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+
+
+void	btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	RemovePairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_obsoleteProxy;
+
+	public:
+		RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+			:m_obsoleteProxy(obsoleteProxy)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+				(pair.m_pProxy1 == m_obsoleteProxy));
+		}
+		
+	};
+
+
+	RemovePairCallback removeCallback(proxy);
+
+	processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+
+
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+	gFindPairs++;
+	if(proxy0->m_uniqueId>proxy1->m_uniqueId) 
+		btSwap(proxy0,proxy1);
+	int proxyId1 = proxy0->getUid();
+	int proxyId2 = proxy1->getUid();
+
+	/*if (proxyId1 > proxyId2) 
+		btSwap(proxyId1, proxyId2);*/
+
+	int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+	if (hash >= m_hashTable.size())
+	{
+		return NULL;
+	}
+
+	int index = m_hashTable[hash];
+	while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+	{
+		index = m_next[index];
+	}
+
+	if (index == BT_NULL_PAIR)
+	{
+		return NULL;
+	}
+
+	btAssert(index < m_overlappingPairArray.size());
+
+	return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void	btHashedOverlappingPairCache::growTables()
+{
+
+	int newCapacity = m_overlappingPairArray.capacity();
+
+	if (m_hashTable.size() < newCapacity)
+	{
+		//grow hashtable and next table
+		int curHashtableSize = m_hashTable.size();
+
+		m_hashTable.resize(newCapacity);
+		m_next.resize(newCapacity);
+
+
+		int i;
+
+		for (i= 0; i < newCapacity; ++i)
+		{
+			m_hashTable[i] = BT_NULL_PAIR;
+		}
+		for (i = 0; i < newCapacity; ++i)
+		{
+			m_next[i] = BT_NULL_PAIR;
+		}
+
+		for(i=0;i<curHashtableSize;i++)
+		{
+	
+			const btBroadphasePair& pair = m_overlappingPairArray[i];
+			int proxyId1 = pair.m_pProxy0->getUid();
+			int proxyId2 = pair.m_pProxy1->getUid();
+			/*if (proxyId1 > proxyId2) 
+				btSwap(proxyId1, proxyId2);*/
+			int	hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));	// New hash value with new mask
+			m_next[i] = m_hashTable[hashValue];
+			m_hashTable[hashValue] = i;
+		}
+
+
+	}
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+	if(proxy0->m_uniqueId>proxy1->m_uniqueId) 
+		btSwap(proxy0,proxy1);
+	int proxyId1 = proxy0->getUid();
+	int proxyId2 = proxy1->getUid();
+
+	/*if (proxyId1 > proxyId2) 
+		btSwap(proxyId1, proxyId2);*/
+
+	int	hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));	// New hash value with new mask
+
+
+	btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+	if (pair != NULL)
+	{
+		return pair;
+	}
+	/*for(int i=0;i<m_overlappingPairArray.size();++i)
+		{
+		if(	(m_overlappingPairArray[i].m_pProxy0==proxy0)&&
+			(m_overlappingPairArray[i].m_pProxy1==proxy1))
+			{
+			printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
+			internalFindPair(proxy0, proxy1, hash);
+			}
+		}*/
+	int count = m_overlappingPairArray.size();
+	int oldCapacity = m_overlappingPairArray.capacity();
+	void* mem = &m_overlappingPairArray.expandNonInitializing();
+
+	//this is where we add an actual pair, so also call the 'ghost'
+	if (m_ghostPairCallback)
+		m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+
+	int newCapacity = m_overlappingPairArray.capacity();
+
+	if (oldCapacity < newCapacity)
+	{
+		growTables();
+		//hash with new capacity
+		hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+	}
+	
+	pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+//	pair->m_pProxy0 = proxy0;
+//	pair->m_pProxy1 = proxy1;
+	pair->m_algorithm = 0;
+	pair->m_internalTmpValue = 0;
+	
+
+	m_next[count] = m_hashTable[hash];
+	m_hashTable[hash] = count;
+
+	return pair;
+}
+
+
+
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+	gRemovePairs++;
+	if(proxy0->m_uniqueId>proxy1->m_uniqueId) 
+		btSwap(proxy0,proxy1);
+	int proxyId1 = proxy0->getUid();
+	int proxyId2 = proxy1->getUid();
+
+	/*if (proxyId1 > proxyId2) 
+		btSwap(proxyId1, proxyId2);*/
+
+	int	hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+	btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+	if (pair == NULL)
+	{
+		return 0;
+	}
+
+	cleanOverlappingPair(*pair,dispatcher);
+
+	void* userData = pair->m_internalInfo1;
+
+	btAssert(pair->m_pProxy0->getUid() == proxyId1);
+	btAssert(pair->m_pProxy1->getUid() == proxyId2);
+
+	int pairIndex = int(pair - &m_overlappingPairArray[0]);
+	btAssert(pairIndex < m_overlappingPairArray.size());
+
+	// Remove the pair from the hash table.
+	int index = m_hashTable[hash];
+	btAssert(index != BT_NULL_PAIR);
+
+	int previous = BT_NULL_PAIR;
+	while (index != pairIndex)
+	{
+		previous = index;
+		index = m_next[index];
+	}
+
+	if (previous != BT_NULL_PAIR)
+	{
+		btAssert(m_next[previous] == pairIndex);
+		m_next[previous] = m_next[pairIndex];
+	}
+	else
+	{
+		m_hashTable[hash] = m_next[pairIndex];
+	}
+
+	// We now move the last pair into spot of the
+	// pair being removed. We need to fix the hash
+	// table indices to support the move.
+
+	int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+	if (m_ghostPairCallback)
+		m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+	// If the removed pair is the last pair, we are done.
+	if (lastPairIndex == pairIndex)
+	{
+		m_overlappingPairArray.pop_back();
+		return userData;
+	}
+
+	// Remove the last pair from the hash table.
+	const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+		/* missing swap here too, Nat. */ 
+	int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
+
+	index = m_hashTable[lastHash];
+	btAssert(index != BT_NULL_PAIR);
+
+	previous = BT_NULL_PAIR;
+	while (index != lastPairIndex)
+	{
+		previous = index;
+		index = m_next[index];
+	}
+
+	if (previous != BT_NULL_PAIR)
+	{
+		btAssert(m_next[previous] == lastPairIndex);
+		m_next[previous] = m_next[lastPairIndex];
+	}
+	else
+	{
+		m_hashTable[lastHash] = m_next[lastPairIndex];
+	}
+
+	// Copy the last pair into the remove pair's spot.
+	m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+	// Insert the last pair into the hash table
+	m_next[pairIndex] = m_hashTable[lastHash];
+	m_hashTable[lastHash] = pairIndex;
+
+	m_overlappingPairArray.pop_back();
+
+	return userData;
+}
+//#include <stdio.h>
+
+void	btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+	int i;
+
+//	printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+	for (i=0;i<m_overlappingPairArray.size();)
+	{
+	
+		btBroadphasePair* pair = &m_overlappingPairArray[i];
+		if (callback->processOverlap(*pair))
+		{
+			removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+			gOverlappingPairs--;
+		} else
+		{
+			i++;
+		}
+	}
+}
+
+void	btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+	///need to keep hashmap in sync with pair address, so rebuild all
+	btBroadphasePairArray tmpPairs;
+	int i;
+	for (i=0;i<m_overlappingPairArray.size();i++)
+	{
+		tmpPairs.push_back(m_overlappingPairArray[i]);
+	}
+
+	for (i=0;i<tmpPairs.size();i++)
+	{
+		removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
+	}
+	
+	for (i = 0; i < m_next.size(); i++)
+	{
+		m_next[i] = BT_NULL_PAIR;
+	}
+
+	tmpPairs.quickSort(btBroadphasePairSortPredicate());
+
+	for (i=0;i<tmpPairs.size();i++)
+	{
+		addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
+	}
+
+	
+}
+
+
+void*	btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
+{
+	if (!hasDeferredRemoval())
+	{
+		btBroadphasePair findPair(*proxy0,*proxy1);
+
+		int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+		if (findIndex < m_overlappingPairArray.size())
+		{
+			gOverlappingPairs--;
+			btBroadphasePair& pair = m_overlappingPairArray[findIndex];
+			void* userData = pair.m_internalInfo1;
+			cleanOverlappingPair(pair,dispatcher);
+			if (m_ghostPairCallback)
+				m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+			
+			m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+			m_overlappingPairArray.pop_back();
+			return userData;
+		}
+	}
+
+	return 0;
+}
+
+
+
+
+
+
+
+
+btBroadphasePair*	btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	//don't add overlap with own
+	btAssert(proxy0 != proxy1);
+
+	if (!needsBroadphaseCollision(proxy0,proxy1))
+		return 0;
+	
+	void* mem = &m_overlappingPairArray.expandNonInitializing();
+	btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+	
+	gOverlappingPairs++;
+	gAddedPairs++;
+	
+	if (m_ghostPairCallback)
+		m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+	return pair;
+	
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ btBroadphasePair*	btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	if (!needsBroadphaseCollision(proxy0,proxy1))
+		return 0;
+
+	btBroadphasePair tmpPair(*proxy0,*proxy1);
+	int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+	if (findIndex < m_overlappingPairArray.size())
+	{
+		//btAssert(it != m_overlappingPairSet.end());
+		 btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+		return pair;
+	}
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
+//#include <stdio.h>
+
+void	btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+	int i;
+
+	for (i=0;i<m_overlappingPairArray.size();)
+	{
+	
+		btBroadphasePair* pair = &m_overlappingPairArray[i];
+		if (callback->processOverlap(*pair))
+		{
+			cleanOverlappingPair(*pair,dispatcher);
+			pair->m_pProxy0 = 0;
+			pair->m_pProxy1 = 0;
+			m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+			m_overlappingPairArray.pop_back();
+			gOverlappingPairs--;
+		} else
+		{
+			i++;
+		}
+	}
+}
+
+
+
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache():
+	m_blockedForChanges(false),
+	m_hasDeferredRemoval(true),
+	m_overlapFilterCallback(0),
+	m_ghostPairCallback(0)
+{
+	int initialAllocatedSize= 2;
+	m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+}
+
+void	btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+	if (pair.m_algorithm)
+	{
+		{
+			pair.m_algorithm->~btCollisionAlgorithm();
+			dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+			pair.m_algorithm=0;
+			gRemovePairs--;
+		}
+	}
+}
+
+
+void	btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	CleanPairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_cleanProxy;
+		btOverlappingPairCache*	m_pairCache;
+		btDispatcher* m_dispatcher;
+
+	public:
+		CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+			:m_cleanProxy(cleanProxy),
+			m_pairCache(pairCache),
+			m_dispatcher(dispatcher)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			if ((pair.m_pProxy0 == m_cleanProxy) ||
+				(pair.m_pProxy1 == m_cleanProxy))
+			{
+				m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+			}
+			return false;
+		}
+		
+	};
+
+	CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+	processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+void	btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	RemovePairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_obsoleteProxy;
+
+	public:
+		RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+			:m_obsoleteProxy(obsoleteProxy)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+				(pair.m_pProxy1 == m_obsoleteProxy));
+		}
+		
+	};
+
+	RemovePairCallback removeCallback(proxy);
+
+	processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+void	btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+	//should already be sorted
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h	(revision 11817)
@@ -0,0 +1,469 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OVERLAPPING_PAIR_CACHE_H
+#define BT_OVERLAPPING_PAIR_CACHE_H
+
+
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+typedef btAlignedObjectArray<btBroadphasePair>	btBroadphasePairArray;
+
+struct	btOverlapCallback
+{
+	virtual ~btOverlapCallback()
+	{}
+	//return true for deletion of the pair
+	virtual bool	processOverlap(btBroadphasePair& pair) = 0;
+
+};
+
+struct btOverlapFilterCallback
+{
+	virtual ~btOverlapFilterCallback()
+	{}
+	// return true when pairs need collision
+	virtual bool	needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
+};
+
+
+
+
+
+
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
+///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
+class btOverlappingPairCache : public btOverlappingPairCallback
+{
+public:
+	virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+	virtual btBroadphasePair*	getOverlappingPairArrayPtr() = 0;
+	
+	virtual const btBroadphasePair*	getOverlappingPairArrayPtr() const = 0;
+
+	virtual btBroadphasePairArray&	getOverlappingPairArray() = 0;
+
+	virtual	void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+
+	virtual int getNumOverlappingPairs() const = 0;
+
+	virtual void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+
+	virtual	void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+
+	virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+	virtual bool	hasDeferredRemoval() = 0;
+
+	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
+
+	virtual void	sortOverlappingPairs(btDispatcher* dispatcher) = 0;
+
+
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+class btHashedOverlappingPairCache : public btOverlappingPairCache
+{
+	btBroadphasePairArray	m_overlappingPairArray;
+	btOverlapFilterCallback* m_overlapFilterCallback;
+	bool		m_blockedForChanges;
+
+
+public:
+	btHashedOverlappingPairCache();
+	virtual ~btHashedOverlappingPairCache();
+
+	
+	void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+	
+	SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+	{
+		if (m_overlapFilterCallback)
+			return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+		bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+		collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+		
+		return collides;
+	}
+
+	// Add a pair and return the new pair. If the pair already exists,
+	// no new pair is created and the old one is returned.
+	virtual btBroadphasePair* 	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+	{
+		gAddedPairs++;
+
+		if (!needsBroadphaseCollision(proxy0,proxy1))
+			return 0;
+
+		return internalAddPair(proxy0,proxy1);
+	}
+
+	
+
+	void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+	
+	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+	virtual btBroadphasePair*	getOverlappingPairArrayPtr()
+	{
+		return &m_overlappingPairArray[0];
+	}
+
+	const btBroadphasePair*	getOverlappingPairArrayPtr() const
+	{
+		return &m_overlappingPairArray[0];
+	}
+
+	btBroadphasePairArray&	getOverlappingPairArray()
+	{
+		return m_overlappingPairArray;
+	}
+
+	const btBroadphasePairArray&	getOverlappingPairArray() const
+	{
+		return m_overlappingPairArray;
+	}
+
+	void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+
+
+	btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+	int GetCount() const { return m_overlappingPairArray.size(); }
+//	btBroadphasePair* GetPairs() { return m_pairs; }
+
+	btOverlapFilterCallback* getOverlapFilterCallback()
+	{
+		return m_overlapFilterCallback;
+	}
+
+	void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+	{
+		m_overlapFilterCallback = callback;
+	}
+
+	int	getNumOverlappingPairs() const
+	{
+		return m_overlappingPairArray.size();
+	}
+private:
+	
+	btBroadphasePair* 	internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+	void	growTables();
+
+	SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
+	{	
+		return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
+	}
+
+	/*
+	// Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+	// This assumes proxyId1 and proxyId2 are 16-bit.
+	SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+	{
+		int key = (proxyId2 << 16) | proxyId1;
+		key = ~key + (key << 15);
+		key = key ^ (key >> 12);
+		key = key + (key << 2);
+		key = key ^ (key >> 4);
+		key = key * 2057;
+		key = key ^ (key >> 16);
+		return key;
+	}
+	*/
+
+
+	
+	SIMD_FORCE_INLINE	unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+	{
+		int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+		// Thomas Wang's hash
+
+		key += ~(key << 15);
+		key ^=  (key >> 10);
+		key +=  (key << 3);
+		key ^=  (key >> 6);
+		key += ~(key << 11);
+		key ^=  (key >> 16);
+		return static_cast<unsigned int>(key);
+	}
+	
+
+
+
+
+	SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+	{
+		int proxyId1 = proxy0->getUid();
+		int proxyId2 = proxy1->getUid();
+		#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+		if (proxyId1 > proxyId2) 
+			btSwap(proxyId1, proxyId2);
+		#endif
+
+		int index = m_hashTable[hash];
+		
+		while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+		{
+			index = m_next[index];
+		}
+
+		if ( index == BT_NULL_PAIR )
+		{
+			return NULL;
+		}
+
+		btAssert(index < m_overlappingPairArray.size());
+
+		return &m_overlappingPairArray[index];
+	}
+
+	virtual bool	hasDeferredRemoval()
+	{
+		return false;
+	}
+
+	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+	{
+		m_ghostPairCallback = ghostPairCallback;
+	}
+
+	virtual void	sortOverlappingPairs(btDispatcher* dispatcher);
+	
+
+protected:
+	
+	btAlignedObjectArray<int>	m_hashTable;
+	btAlignedObjectArray<int>	m_next;
+	btOverlappingPairCallback*	m_ghostPairCallback;
+	
+};
+
+
+
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
+class	btSortedOverlappingPairCache : public btOverlappingPairCache
+{
+	protected:
+		//avoid brute-force finding all the time
+		btBroadphasePairArray	m_overlappingPairArray;
+
+		//during the dispatch, check that user doesn't destroy/create proxy
+		bool		m_blockedForChanges;
+
+		///by default, do the removal during the pair traversal
+		bool		m_hasDeferredRemoval;
+		
+		//if set, use the callback instead of the built in filter in needBroadphaseCollision
+		btOverlapFilterCallback* m_overlapFilterCallback;
+
+		btOverlappingPairCallback*	m_ghostPairCallback;
+
+	public:
+			
+		btSortedOverlappingPairCache();	
+		virtual ~btSortedOverlappingPairCache();
+
+		virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+		void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+		void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+		
+		btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+		btBroadphasePair*	findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+			
+		
+		void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+		void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+		inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+		{
+			if (m_overlapFilterCallback)
+				return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+			bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+			collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			
+			return collides;
+		}
+		
+		btBroadphasePairArray&	getOverlappingPairArray()
+		{
+			return m_overlappingPairArray;
+		}
+
+		const btBroadphasePairArray&	getOverlappingPairArray() const
+		{
+			return m_overlappingPairArray;
+		}
+
+		
+
+
+		btBroadphasePair*	getOverlappingPairArrayPtr()
+		{
+			return &m_overlappingPairArray[0];
+		}
+
+		const btBroadphasePair*	getOverlappingPairArrayPtr() const
+		{
+			return &m_overlappingPairArray[0];
+		}
+
+		int	getNumOverlappingPairs() const
+		{
+			return m_overlappingPairArray.size();
+		}
+		
+		btOverlapFilterCallback* getOverlapFilterCallback()
+		{
+			return m_overlapFilterCallback;
+		}
+
+		void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+		{
+			m_overlapFilterCallback = callback;
+		}
+
+		virtual bool	hasDeferredRemoval()
+		{
+			return m_hasDeferredRemoval;
+		}
+
+		virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+		{
+			m_ghostPairCallback = ghostPairCallback;
+		}
+
+		virtual void	sortOverlappingPairs(btDispatcher* dispatcher);
+		
+
+};
+
+
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
+class btNullPairCache : public btOverlappingPairCache
+{
+
+	btBroadphasePairArray	m_overlappingPairArray;
+
+public:
+
+	virtual btBroadphasePair*	getOverlappingPairArrayPtr()
+	{
+		return &m_overlappingPairArray[0];
+	}
+	const btBroadphasePair*	getOverlappingPairArrayPtr() const
+	{
+		return &m_overlappingPairArray[0];
+	}
+	btBroadphasePairArray&	getOverlappingPairArray()
+	{
+		return m_overlappingPairArray;
+	}
+	
+	virtual	void	cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
+	{
+
+	}
+
+	virtual int getNumOverlappingPairs() const
+	{
+		return 0;
+	}
+
+	virtual void	cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+	{
+
+	}
+
+	virtual	void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+	{
+	}
+
+	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+	{
+	}
+
+	virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
+	{
+		return 0;
+	}
+
+	virtual bool	hasDeferredRemoval()
+	{
+		return true;
+	}
+
+	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
+	{
+
+	}
+
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+	{
+		return 0;
+	}
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+	{
+		return 0;
+	}
+
+	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+	{
+	}
+	
+	virtual void	sortOverlappingPairs(btDispatcher* dispatcher)
+	{
+        (void) dispatcher;
+	}
+
+
+};
+
+
+#endif //BT_OVERLAPPING_PAIR_CACHE_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h	(revision 11817)
@@ -0,0 +1,40 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct  btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+public:
+	virtual ~btOverlappingPairCallback()
+	{
+
+	}
+	
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp	(revision 11817)
@@ -0,0 +1,1375 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+#define RAYAABB2
+
+btQuantizedBvh::btQuantizedBvh() : 
+					m_bulletVersion(BT_BULLET_VERSION),
+					m_useQuantization(false), 
+					//m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+					m_traversalMode(TRAVERSAL_STACKLESS)
+					//m_traversalMode(TRAVERSAL_RECURSIVE)
+					,m_subtreeHeaderCount(0) //PCK: add this line
+{
+	m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY);
+	m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+}
+
+
+
+
+
+void btQuantizedBvh::buildInternal()
+{
+	///assumes that caller filled in the m_quantizedLeafNodes
+	m_useQuantization = true;
+	int numLeafNodes = 0;
+	
+	if (m_useQuantization)
+	{
+		//now we have an array of leafnodes in m_leafNodes
+		numLeafNodes = m_quantizedLeafNodes.size();
+
+		m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+	}
+
+	m_curNodeIndex = 0;
+
+	buildTree(0,numLeafNodes);
+
+	///if the entire tree is small then subtree size, we need to create a header info for the tree
+	if(m_useQuantization && !m_SubtreeHeaders.size())
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+		subtree.m_rootNodeIndex = 0;
+		subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+	}
+
+	//PCK: update the copy of the size
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+	//PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+	m_quantizedLeafNodes.clear();
+	m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+btVector3 color[4]=
+{
+	btVector3(1,0,0),
+	btVector3(0,1,0),
+	btVector3(0,0,1),
+	btVector3(0,1,1)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void	btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+{
+	//enlarge the AABB to avoid division by zero when initializing the quantization values
+	btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+	m_bvhAabbMin = bvhAabbMin - clampValue;
+	m_bvhAabbMax = bvhAabbMax + clampValue;
+	btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+	m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+	m_useQuantization = true;
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void	btQuantizedBvh::buildTree	(int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+	gStackDepth++;
+	if (gStackDepth > gMaxStackDepth)
+		gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+	int splitAxis, splitIndex, i;
+	int numIndices =endIndex-startIndex;
+	int curIndex = m_curNodeIndex;
+
+	btAssert(numIndices>0);
+
+	if (numIndices==1)
+	{
+#ifdef DEBUG_TREE_BUILDING
+		gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+		
+		assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+		m_curNodeIndex++;
+		return;	
+	}
+	//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+	
+	splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+	splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+	int internalNodeIndex = m_curNodeIndex;
+	
+	//set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+	//the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+	setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
+	setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
+	
+	
+	for (i=startIndex;i<endIndex;i++)
+	{
+		mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+	}
+
+	m_curNodeIndex++;
+	
+
+	//internalNode->m_escapeIndex;
+	
+	int leftChildNodexIndex = m_curNodeIndex;
+
+	//build left child tree
+	buildTree(startIndex,splitIndex);
+
+	int rightChildNodexIndex = m_curNodeIndex;
+	//build right child tree
+	buildTree(splitIndex,endIndex);
+
+#ifdef DEBUG_TREE_BUILDING
+	gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+	int escapeIndex = m_curNodeIndex - curIndex;
+
+	if (m_useQuantization)
+	{
+		//escapeIndex is the number of nodes of this subtree
+		const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
+		const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+		if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+		{
+			updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+		}
+	} else
+	{
+
+	}
+
+	setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
+
+}
+
+void	btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+	btAssert(m_useQuantization);
+
+	btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+	int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+	int leftSubTreeSizeInBytes =  leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+	
+	btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+	int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+	int rightSubTreeSizeInBytes =  rightSubTreeSize *  static_cast<int>(sizeof(btQuantizedBvhNode));
+
+	if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(leftChildNode);
+		subtree.m_rootNodeIndex = leftChildNodexIndex;
+		subtree.m_subtreeSize = leftSubTreeSize;
+	}
+
+	if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(rightChildNode);
+		subtree.m_rootNodeIndex = rightChildNodexIndex;
+		subtree.m_subtreeSize = rightSubTreeSize;
+	}
+
+	//PCK: update the copy of the size
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+}
+
+
+int	btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+{
+	int i;
+	int splitIndex =startIndex;
+	int numIndices = endIndex - startIndex;
+	btScalar splitValue;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+	
+	splitValue = means[splitAxis];
+	
+	//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		if (center[splitAxis] > splitValue)
+		{
+			//swap
+			swapLeafNodes(i,splitIndex);
+			splitIndex++;
+		}
+	}
+
+	//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+	//otherwise the tree-building might fail due to stack-overflows in certain cases.
+	//unbalanced1 is unsafe: it can cause stack overflows
+	//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+	//unbalanced2 should work too: always use center (perfect balanced trees)	
+	//bool unbalanced2 = true;
+
+	//this should be safe too:
+	int rangeBalancedIndices = numIndices/3;
+	bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+	
+	if (unbalanced)
+	{
+		splitIndex = startIndex+ (numIndices>>1);
+	}
+
+	bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+	(void)unbal;
+	btAssert(!unbal);
+
+	return splitIndex;
+}
+
+
+int	btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+{
+	int i;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+	int numIndices = endIndex-startIndex;
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+		
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		btVector3 diff2 = center-means;
+		diff2 = diff2 * diff2;
+		variance += diff2;
+	}
+	variance *= (btScalar(1.)/	((btScalar)numIndices-1)	);
+	
+	return variance.maxAxis();
+}
+
+
+
+void	btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	//either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
+
+	if (m_useQuantization)
+	{
+		///quantize query AABB
+		unsigned short int quantizedQueryAabbMin[3];
+		unsigned short int quantizedQueryAabbMax[3];
+		quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
+		quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+
+		switch (m_traversalMode)
+		{
+		case TRAVERSAL_STACKLESS:
+				walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
+			break;
+		case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+				walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+			break;
+		case TRAVERSAL_RECURSIVE:
+			{
+				const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+				walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+			}
+			break;
+		default:
+			//unsupported
+			btAssert(0);
+		}
+	} else
+	{
+		walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+	}
+}
+
+
+int maxIterations = 0;
+
+
+void	btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	btAssert(!m_useQuantization);
+
+	const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+	int escapeIndex, curIndex = 0;
+	int walkIterations = 0;
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap;
+
+	while (curIndex < m_curNodeIndex)
+	{
+		//catch bugs in tree data
+		btAssert (walkIterations < m_curNodeIndex);
+
+		walkIterations++;
+		aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+		isLeafNode = rootNode->m_escapeIndex == -1;
+		
+		//PCK: unsigned instead of bool
+		if (isLeafNode && (aabbOverlap != 0))
+		{
+			nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+		} 
+		
+		//PCK: unsigned instead of bool
+		if ((aabbOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->m_escapeIndex;
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void	btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
+	if (aabbOverlap)
+	{
+		isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
+		if (isLeafNode)
+		{
+			nodeCallback->processNode(rootNode);
+		} else
+		{
+			walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
+			walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
+		}
+	}
+
+}
+*/
+
+void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+	btAssert(m_useQuantization);
+	
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap;
+
+	//PCK: unsigned instead of bool
+	aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+	isLeafNode = currentNode->isLeafNode();
+		
+	//PCK: unsigned instead of bool
+	if (aabbOverlap != 0)
+	{
+		if (isLeafNode)
+		{
+			nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
+		} else
+		{
+			//process left and right children
+			const btQuantizedBvhNode* leftChildNode = currentNode+1;
+			walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+
+			const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
+			walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+		}
+	}		
+}
+
+
+
+void	btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+	btAssert(!m_useQuantization);
+
+	const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+	int escapeIndex, curIndex = 0;
+	int walkIterations = 0;
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap=0;
+	unsigned rayBoxOverlap=0;
+	btScalar lambda_max = 1.0;
+	
+		/* Quick pruning by quantized box */
+	btVector3 rayAabbMin = raySource;
+	btVector3 rayAabbMax = raySource;
+	rayAabbMin.setMin(rayTarget);
+	rayAabbMax.setMax(rayTarget);
+
+	/* Add box cast extents to bounding box */
+	rayAabbMin += aabbMin;
+	rayAabbMax += aabbMax;
+
+#ifdef RAYAABB2
+	btVector3 rayDir = (rayTarget-raySource);
+	rayDir.normalize ();
+	lambda_max = rayDir.dot(rayTarget-raySource);
+	///what about division by zero? --> just set rayDirection[i] to 1.0
+	btVector3 rayDirectionInverse;
+	rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+	rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+	rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+	unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+#endif
+
+	btVector3 bounds[2];
+
+	while (curIndex < m_curNodeIndex)
+	{
+		btScalar param = 1.0;
+		//catch bugs in tree data
+		btAssert (walkIterations < m_curNodeIndex);
+
+		walkIterations++;
+
+		bounds[0] = rootNode->m_aabbMinOrg;
+		bounds[1] = rootNode->m_aabbMaxOrg;
+		/* Add box cast extents */
+		bounds[0] -= aabbMax;
+		bounds[1] -= aabbMin;
+
+		aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+		//perhaps profile if it is worth doing the aabbOverlap test first
+
+#ifdef RAYAABB2
+			///careful with this check: need to check division by zero (above) and fix the unQuantize method
+			///thanks Joerg/hiker for the reproduction case!
+			///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+		rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+
+#else
+		btVector3 normal;
+		rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
+#endif
+
+		isLeafNode = rootNode->m_escapeIndex == -1;
+		
+		//PCK: unsigned instead of bool
+		if (isLeafNode && (rayBoxOverlap != 0))
+		{
+			nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+		} 
+		
+		//PCK: unsigned instead of bool
+		if ((rayBoxOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->m_escapeIndex;
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+
+
+void	btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+	btAssert(m_useQuantization);
+	
+	int curIndex = startNodeIndex;
+	int walkIterations = 0;
+	int subTreeSize = endNodeIndex - startNodeIndex;
+	(void)subTreeSize;
+
+	const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+	int escapeIndex;
+	
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned boxBoxOverlap = 0;
+	unsigned rayBoxOverlap = 0;
+
+	btScalar lambda_max = 1.0;
+
+#ifdef RAYAABB2
+	btVector3 rayDirection = (rayTarget-raySource);
+	rayDirection.normalize ();
+	lambda_max = rayDirection.dot(rayTarget-raySource);
+	///what about division by zero? --> just set rayDirection[i] to 1.0
+	rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
+	rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
+	rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2];
+	unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+	/* Quick pruning by quantized box */
+	btVector3 rayAabbMin = raySource;
+	btVector3 rayAabbMax = raySource;
+	rayAabbMin.setMin(rayTarget);
+	rayAabbMax.setMax(rayTarget);
+
+	/* Add box cast extents to bounding box */
+	rayAabbMin += aabbMin;
+	rayAabbMax += aabbMax;
+
+	unsigned short int quantizedQueryAabbMin[3];
+	unsigned short int quantizedQueryAabbMax[3];
+	quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+	quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+	while (curIndex < endNodeIndex)
+	{
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+		//some code snippet to debugDraw aabb, to visually analyze bvh structure
+		static int drawPatch = 0;
+		//need some global access to a debugDrawer
+		extern btIDebugDraw* debugDrawerPtr;
+		if (curIndex==drawPatch)
+		{
+			btVector3 aabbMin,aabbMax;
+			aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+			aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+			btVector3	color(1,0,0);
+			debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+		}
+#endif//VISUALLY_ANALYZE_BVH
+
+		//catch bugs in tree data
+		btAssert (walkIterations < subTreeSize);
+
+		walkIterations++;
+		//PCK: unsigned instead of bool
+		// only interested if this is closer than any previous hit
+		btScalar param = 1.0;
+		rayBoxOverlap = 0;
+		boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+		isLeafNode = rootNode->isLeafNode();
+		if (boxBoxOverlap)
+		{
+			btVector3 bounds[2];
+			bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+			bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+			/* Add box cast extents */
+			bounds[0] -= aabbMax;
+			bounds[1] -= aabbMin;
+			btVector3 normal;
+#if 0
+			bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+			bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+			if (ra2 != ra)
+			{
+				printf("functions don't match\n");
+			}
+#endif
+#ifdef RAYAABB2
+			///careful with this check: need to check division by zero (above) and fix the unQuantize method
+			///thanks Joerg/hiker for the reproduction case!
+			///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+			//BT_PROFILE("btRayAabb2");
+			rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+			
+#else
+			rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+		}
+		
+		if (isLeafNode && rayBoxOverlap)
+		{
+			nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+		}
+		
+		//PCK: unsigned instead of bool
+		if ((rayBoxOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->getEscapeIndex();
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+void	btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+{
+	btAssert(m_useQuantization);
+	
+	int curIndex = startNodeIndex;
+	int walkIterations = 0;
+	int subTreeSize = endNodeIndex - startNodeIndex;
+	(void)subTreeSize;
+
+	const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+	int escapeIndex;
+	
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap;
+
+	while (curIndex < endNodeIndex)
+	{
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+		//some code snippet to debugDraw aabb, to visually analyze bvh structure
+		static int drawPatch = 0;
+		//need some global access to a debugDrawer
+		extern btIDebugDraw* debugDrawerPtr;
+		if (curIndex==drawPatch)
+		{
+			btVector3 aabbMin,aabbMax;
+			aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+			aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+			btVector3	color(1,0,0);
+			debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+		}
+#endif//VISUALLY_ANALYZE_BVH
+
+		//catch bugs in tree data
+		btAssert (walkIterations < subTreeSize);
+
+		walkIterations++;
+		//PCK: unsigned instead of bool
+		aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+		isLeafNode = rootNode->isLeafNode();
+		
+		if (isLeafNode && aabbOverlap)
+		{
+			nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+		} 
+		
+		//PCK: unsigned instead of bool
+		if ((aabbOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->getEscapeIndex();
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+//This traversal can be called from Playstation 3 SPU
+void	btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+	btAssert(m_useQuantization);
+
+	int i;
+
+
+	for (i=0;i<this->m_SubtreeHeaders.size();i++)
+	{
+		const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+		//PCK: unsigned instead of bool
+		unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+		if (overlap != 0)
+		{
+			walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
+				subtree.m_rootNodeIndex,
+				subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+		}
+	}
+}
+
+
+void	btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+	reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0));
+}
+
+
+void	btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	//always use stackless
+
+	if (m_useQuantization)
+	{
+		walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+	}
+	else
+	{
+		walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+	}
+	/*
+	{
+		//recursive traversal
+		btVector3 qaabbMin = raySource;
+		btVector3 qaabbMax = raySource;
+		qaabbMin.setMin(rayTarget);
+		qaabbMax.setMax(rayTarget);
+		qaabbMin += aabbMin;
+		qaabbMax += aabbMax;
+		reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+	}
+	*/
+
+}
+
+
+void	btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
+{
+	if (m_useQuantization)
+	{
+			btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+			m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+			m_quantizedLeafNodes[splitIndex] = tmp;
+	} else
+	{
+			btOptimizedBvhNode tmp = m_leafNodes[i];
+			m_leafNodes[i] = m_leafNodes[splitIndex];
+			m_leafNodes[splitIndex] = tmp;
+	}
+}
+
+void	btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+	if (m_useQuantization)
+	{
+		m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+	} else
+	{
+		m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+	}
+}
+
+//PCK: include
+#include <new>
+
+#if 0
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+#endif
+
+
+unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
+{
+	// I changed this to 0 since the extra padding is not needed or used.
+	return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize() const
+{
+	unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
+	baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+	if (m_useQuantization)
+	{
+		return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
+	}
+	return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
+}
+
+bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+{
+	btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+/*	if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+	{
+		///check alignedment for buffer?
+		btAssert(0);
+		return false;
+	}
+*/
+
+	btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
+
+	// construct the class so the virtual function table, etc will be set up
+	// Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+	new (targetBvh) btQuantizedBvh;
+
+	if (i_swapEndian)
+	{
+		targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
+
+
+		btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
+		btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
+		btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+
+		targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
+		targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
+	}
+	else
+	{
+		targetBvh->m_curNodeIndex = m_curNodeIndex;
+		targetBvh->m_bvhAabbMin = m_bvhAabbMin;
+		targetBvh->m_bvhAabbMax = m_bvhAabbMax;
+		targetBvh->m_bvhQuantization = m_bvhQuantization;
+		targetBvh->m_traversalMode = m_traversalMode;
+		targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
+	}
+
+	targetBvh->m_useQuantization = m_useQuantization;
+
+	unsigned char *nodeData = (unsigned char *)targetBvh;
+	nodeData += sizeof(btQuantizedBvh);
+	
+	unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+	
+	int nodeCount = m_curNodeIndex;
+
+	if (m_useQuantization)
+	{
+		targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+			}
+		}
+		else
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+	
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
+
+
+			}
+		}
+		nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+
+		// this clears the pointer in the member variable it doesn't really do anything to the data
+		// it does call the destructor on the contained objects, but they are all classes with no destructor defined
+		// so the memory (which is not freed) is left alone
+		targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
+	}
+	else
+	{
+		targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+				btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+				targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+				targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+				targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
+			}
+		}
+		else
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
+				targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
+
+				targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
+				targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
+				targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
+			}
+		}
+		nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+
+		// this clears the pointer in the member variable it doesn't really do anything to the data
+		// it does call the destructor on the contained objects, but they are all classes with no destructor defined
+		// so the memory (which is not freed) is left alone
+		targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
+	}
+
+	sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+
+	// Now serialize the subtree headers
+	targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
+	if (i_swapEndian)
+	{
+		for (int i = 0; i < m_subtreeHeaderCount; i++)
+		{
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+			targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
+		}
+	}
+	else
+	{
+		for (int i = 0; i < m_subtreeHeaderCount; i++)
+		{
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
+			targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
+
+			// need to clear padding in destination buffer
+			targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
+			targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
+			targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
+		}
+	}
+	nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+
+	// this clears the pointer in the member variable it doesn't really do anything to the data
+	// it does call the destructor on the contained objects, but they are all classes with no destructor defined
+	// so the memory (which is not freed) is left alone
+	targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
+
+	// this wipes the virtual function table pointer at the start of the buffer for the class
+	*((void**)o_alignedDataBuffer) = NULL;
+
+	return true;
+}
+
+btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+	if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+	{
+		return NULL;
+	}
+	btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+
+	if (i_swapEndian)
+	{
+		bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
+
+		btUnSwapVector3Endian(bvh->m_bvhAabbMin);
+		btUnSwapVector3Endian(bvh->m_bvhAabbMax);
+		btUnSwapVector3Endian(bvh->m_bvhQuantization);
+
+		bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
+		bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
+	}
+
+	unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+	btAssert(calculatedBufSize <= i_dataBufferSize);
+
+	if (calculatedBufSize > i_dataBufferSize)
+	{
+		return NULL;
+	}
+
+	unsigned char *nodeData = (unsigned char *)bvh;
+	nodeData += sizeof(btQuantizedBvh);
+	
+	unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+	
+	int nodeCount = bvh->m_curNodeIndex;
+
+	// Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
+	// Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+	new (bvh) btQuantizedBvh(*bvh, false);
+
+	if (bvh->m_useQuantization)
+	{
+		bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+			}
+		}
+		nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+	}
+	else
+	{
+		bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+				btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+				
+				bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+				bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+				bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+			}
+		}
+		nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+	}
+
+	sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+
+	// Now serialize the subtree headers
+	bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
+	if (i_swapEndian)
+	{
+		for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
+		{
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+			bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+			bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+		}
+	}
+
+	return bvh;
+}
+
+// Constructor that prevents btVector3's default constructor from being called
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
+m_bvhAabbMin(self.m_bvhAabbMin),
+m_bvhAabbMax(self.m_bvhAabbMax),
+m_bvhQuantization(self.m_bvhQuantization),
+m_bulletVersion(BT_BULLET_VERSION)
+{
+
+}
+
+void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
+{
+	m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
+	m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
+	m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
+
+	m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
+	m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0;
+	
+	{
+		int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
+		m_contiguousNodes.resize(numElem);
+
+		if (numElem)
+		{
+			btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
+
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
+				m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
+				m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+				m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+				m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+			}
+		}
+	}
+
+	{
+		int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
+		m_quantizedContiguousNodes.resize(numElem);
+		
+		if (numElem)
+		{
+			btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+			}
+		}
+	}
+
+	m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
+	
+	{
+		int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
+		m_SubtreeHeaders.resize(numElem);
+		if (numElem)
+		{
+			btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+				m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+				m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+				m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+			}
+		}
+	}
+}
+
+void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData)
+{
+	m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
+	m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
+	m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
+
+	m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
+	m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0;
+	
+	{
+		int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
+		m_contiguousNodes.resize(numElem);
+
+		if (numElem)
+		{
+			btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
+
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
+				m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
+				m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+				m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+				m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+			}
+		}
+	}
+
+	{
+		int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
+		m_quantizedContiguousNodes.resize(numElem);
+		
+		if (numElem)
+		{
+			btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+			}
+		}
+	}
+
+	m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
+	
+	{
+		int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
+		m_SubtreeHeaders.resize(numElem);
+		if (numElem)
+		{
+			btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+				m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+				m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+				m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+			}
+		}
+	}
+
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
+	
+	m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
+	m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
+	m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
+
+	quantizedData->m_curNodeIndex = m_curNodeIndex;
+	quantizedData->m_useQuantization = m_useQuantization;
+	
+	quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
+	quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*) (m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
+	if (quantizedData->m_contiguousNodesPtr)
+	{
+		int sz = sizeof(btOptimizedBvhNodeData);
+		int numElem = m_contiguousNodes.size();
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
+			m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
+			memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
+			memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
+			memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
+		}
+		serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]);
+	}
+
+	quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
+//	printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
+	quantizedData->m_quantizedContiguousNodesPtr =(btQuantizedBvhNodeData*) (m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
+	if (quantizedData->m_quantizedContiguousNodesPtr)
+	{
+		int sz = sizeof(btQuantizedBvhNodeData);
+		int numElem = m_quantizedContiguousNodes.size();
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
+			memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
+			memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1];
+			memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2];
+			memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0];
+			memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
+			memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
+		}
+		serializer->finalizeChunk(chunk,"btQuantizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_quantizedContiguousNodes[0]);
+	}
+
+	quantizedData->m_traversalMode = int(m_traversalMode);
+	quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
+
+	quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*) (m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
+	if (quantizedData->m_subTreeInfoPtr)
+	{
+		int sz = sizeof(btBvhSubtreeInfoData);
+		int numElem = m_SubtreeHeaders.size();
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
+			memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
+			memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2];
+			memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0];
+			memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1];
+			memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2];
+
+			memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
+			memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
+		}
+		serializer->finalizeChunk(chunk,"btBvhSubtreeInfoData",BT_ARRAY_CODE,(void*)&m_SubtreeHeaders[0]);
+	}
+	return btQuantizedBvhDataName;
+}
+
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h	(revision 11817)
@@ -0,0 +1,579 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_QUANTIZED_BVH_H
+#define BT_QUANTIZED_BVH_H
+
+class btSerializer;
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include <stdio.h>
+#include <stdlib.h>
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btQuantizedBvhData btQuantizedBvhDoubleData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
+#define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
+#else
+#define btQuantizedBvhData btQuantizedBvhFloatData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
+#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
+#endif
+
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES  2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+ATTRIBUTE_ALIGNED16	(struct) btQuantizedBvhNode
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	//12 bytes
+	unsigned short int	m_quantizedAabbMin[3];
+	unsigned short int	m_quantizedAabbMax[3];
+	//4 bytes
+	int	m_escapeIndexOrTriangleIndex;
+
+	bool isLeafNode() const
+	{
+		//skipindex is negative (internal node), triangleindex >=0 (leafnode)
+		return (m_escapeIndexOrTriangleIndex >= 0);
+	}
+	int getEscapeIndex() const
+	{
+		btAssert(!isLeafNode());
+		return -m_escapeIndexOrTriangleIndex;
+	}
+	int	getTriangleIndex() const
+	{
+		btAssert(isLeafNode());
+		// Get only the lower bits where the triangle index is stored
+		return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
+	}
+	int	getPartId() const
+	{
+		btAssert(isLeafNode());
+		// Get only the highest bits where the part index is stored
+		return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+	}
+}
+;
+
+/// btOptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	//32 bytes
+	btVector3	m_aabbMinOrg;
+	btVector3	m_aabbMaxOrg;
+
+	//4
+	int	m_escapeIndex;
+
+	//8
+	//for child nodes
+	int	m_subPart;
+	int	m_triangleIndex;
+	int	m_padding[5];//bad, due to alignment
+
+
+};
+
+
+///btBvhSubtreeInfo provides info to gather a subtree of limited size
+ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
+{
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	//12 bytes
+	unsigned short int	m_quantizedAabbMin[3];
+	unsigned short int	m_quantizedAabbMax[3];
+	//4 bytes, points to the root of the subtree
+	int			m_rootNodeIndex;
+	//4 bytes
+	int			m_subtreeSize;
+	int			m_padding[3];
+
+	btBvhSubtreeInfo()
+	{
+		//memset(&m_padding[0], 0, sizeof(m_padding));
+	}
+
+
+	void	setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
+	{
+		m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
+		m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
+		m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
+		m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
+		m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
+		m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
+	}
+}
+;
+
+
+class btNodeOverlapCallback
+{
+public:
+	virtual ~btNodeOverlapCallback() {};
+
+	virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+
+///for code readability:
+typedef btAlignedObjectArray<btOptimizedBvhNode>	NodeArray;
+typedef btAlignedObjectArray<btQuantizedBvhNode>	QuantizedNodeArray;
+typedef btAlignedObjectArray<btBvhSubtreeInfo>		BvhSubtreeInfoArray;
+
+
+///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
+///It is recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+{
+public:
+	enum btTraversalMode
+	{
+		TRAVERSAL_STACKLESS = 0,
+		TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+		TRAVERSAL_RECURSIVE
+	};
+
+protected:
+
+
+	btVector3			m_bvhAabbMin;
+	btVector3			m_bvhAabbMax;
+	btVector3			m_bvhQuantization;
+
+	int					m_bulletVersion;	//for serialization versioning. It could also be used to detect endianess.
+
+	int					m_curNodeIndex;
+	//quantization data
+	bool				m_useQuantization;
+
+
+
+	NodeArray			m_leafNodes;
+	NodeArray			m_contiguousNodes;
+	QuantizedNodeArray	m_quantizedLeafNodes;
+	QuantizedNodeArray	m_quantizedContiguousNodes;
+	
+	btTraversalMode	m_traversalMode;
+	BvhSubtreeInfoArray		m_SubtreeHeaders;
+
+	//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
+	mutable int m_subtreeHeaderCount;
+
+	
+
+
+
+	///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
+	///this might be refactored into a virtual, it is usually not calculated at run-time
+	void	setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
+	{
+		if (m_useQuantization)
+		{
+			quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+		} else
+		{
+			m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+		}
+	}
+	void	setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+	{
+		if (m_useQuantization)
+		{
+			quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+		} else
+		{
+			m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+		}
+	}
+
+	btVector3 getAabbMin(int nodeIndex) const
+	{
+		if (m_useQuantization)
+		{
+			return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+		}
+		//non-quantized
+		return m_leafNodes[nodeIndex].m_aabbMinOrg;
+
+	}
+	btVector3 getAabbMax(int nodeIndex) const
+	{
+		if (m_useQuantization)
+		{
+			return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
+		} 
+		//non-quantized
+		return m_leafNodes[nodeIndex].m_aabbMaxOrg;
+		
+	}
+
+	
+	void	setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+	{
+		if (m_useQuantization)
+		{
+			m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
+		} 
+		else
+		{
+			m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
+		}
+
+	}
+
+	void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) 
+	{
+		if (m_useQuantization)
+		{
+			unsigned short int quantizedAabbMin[3];
+			unsigned short int quantizedAabbMax[3];
+			quantize(quantizedAabbMin,newAabbMin,0);
+			quantize(quantizedAabbMax,newAabbMax,1);
+			for (int i=0;i<3;i++)
+			{
+				if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
+					m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
+
+				if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
+					m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
+
+			}
+		} else
+		{
+			//non-quantized
+			m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
+			m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);		
+		}
+	}
+
+	void	swapLeafNodes(int firstIndex,int secondIndex);
+
+	void	assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+
+protected:
+
+	
+
+	void	buildTree	(int startIndex,int endIndex);
+
+	int	calcSplittingAxis(int startIndex,int endIndex);
+
+	int	sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
+	
+	void	walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	void	walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+	void	walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
+	void	walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+
+	///tree traversal designed for small-memory processors like PS3 SPU
+	void	walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+	///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+	void	walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+	///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+	void	walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
+	
+
+
+
+	void	updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+
+public:
+	
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btQuantizedBvh();
+
+	virtual ~btQuantizedBvh();
+
+	
+	///***************************************** expert/internal use only *************************
+	void	setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+	QuantizedNodeArray&	getLeafNodeArray() {			return	m_quantizedLeafNodes;	}
+	///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+	void	buildInternal();
+	///***************************************** expert/internal use only *************************
+
+	void	reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+	void	reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+	void	reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+		SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+	{
+
+		btAssert(m_useQuantization);
+
+		btAssert(point.getX() <= m_bvhAabbMax.getX());
+		btAssert(point.getY() <= m_bvhAabbMax.getY());
+		btAssert(point.getZ() <= m_bvhAabbMax.getZ());
+
+		btAssert(point.getX() >= m_bvhAabbMin.getX());
+		btAssert(point.getY() >= m_bvhAabbMin.getY());
+		btAssert(point.getZ() >= m_bvhAabbMin.getZ());
+
+		btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+		///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+		///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+		///@todo: double-check this
+		if (isMax)
+		{
+			out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
+			out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
+			out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
+		} else
+		{
+			out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+			out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+			out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+		}
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+		btVector3 newPoint = unQuantize(out);
+		if (isMax)
+		{
+			if (newPoint.getX() < point.getX())
+			{
+				printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+			}
+			if (newPoint.getY() < point.getY())
+			{
+				printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+			}
+			if (newPoint.getZ() < point.getZ())
+			{
+
+				printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+			}
+		} else
+		{
+			if (newPoint.getX() > point.getX())
+			{
+				printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+			}
+			if (newPoint.getY() > point.getY())
+			{
+				printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+			}
+			if (newPoint.getZ() > point.getZ())
+			{
+				printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+			}
+		}
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+	}
+
+
+	SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+	{
+
+		btAssert(m_useQuantization);
+
+		btVector3 clampedPoint(point2);
+		clampedPoint.setMax(m_bvhAabbMin);
+		clampedPoint.setMin(m_bvhAabbMax);
+
+		quantize(out,clampedPoint,isMax);
+
+	}
+	
+	SIMD_FORCE_INLINE btVector3	unQuantize(const unsigned short* vecIn) const
+	{
+			btVector3	vecOut;
+			vecOut.setValue(
+			(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+			(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+			(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
+			vecOut += m_bvhAabbMin;
+			return vecOut;
+	}
+
+	///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
+	void	setTraversalMode(btTraversalMode	traversalMode)
+	{
+		m_traversalMode = traversalMode;
+	}
+
+
+	SIMD_FORCE_INLINE QuantizedNodeArray&	getQuantizedNodeArray()
+	{	
+		return	m_quantizedContiguousNodes;
+	}
+
+
+	SIMD_FORCE_INLINE BvhSubtreeInfoArray&	getSubtreeInfoArray()
+	{
+		return m_SubtreeHeaders;
+	}
+
+////////////////////////////////////////////////////////////////////
+
+	/////Calculate space needed to store BVH for serialization
+	unsigned calculateSerializeBufferSize() const;
+
+	/// Data buffer MUST be 16 byte aligned
+	virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+
+	///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+	static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+	static unsigned int getAlignmentSerializationPadding();
+//////////////////////////////////////////////////////////////////////
+
+	
+	virtual	int	calculateSerializeBufferSizeNew() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	virtual	void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
+
+	virtual	void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
+
+
+////////////////////////////////////////////////////////////////////
+
+	SIMD_FORCE_INLINE bool isQuantized()
+	{
+		return m_useQuantization;
+	}
+
+private:
+	// Special "copy" constructor that allows for in-place deserialization
+	// Prevents btVector3's default constructor from being called, but doesn't inialize much else
+	// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
+	btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+struct	btBvhSubtreeInfoData
+{
+	int			m_rootNodeIndex;
+	int			m_subtreeSize;
+	unsigned short m_quantizedAabbMin[3];
+	unsigned short m_quantizedAabbMax[3];
+};
+
+struct btOptimizedBvhNodeFloatData
+{
+	btVector3FloatData	m_aabbMinOrg;
+	btVector3FloatData	m_aabbMaxOrg;
+	int	m_escapeIndex;
+	int	m_subPart;
+	int	m_triangleIndex;
+	char m_pad[4];
+};
+
+struct btOptimizedBvhNodeDoubleData
+{
+	btVector3DoubleData	m_aabbMinOrg;
+	btVector3DoubleData	m_aabbMaxOrg;
+	int	m_escapeIndex;
+	int	m_subPart;
+	int	m_triangleIndex;
+	char	m_pad[4];
+};
+
+
+struct btQuantizedBvhNodeData
+{
+	unsigned short m_quantizedAabbMin[3];
+	unsigned short m_quantizedAabbMax[3];
+	int	m_escapeIndexOrTriangleIndex;
+};
+
+struct	btQuantizedBvhFloatData
+{
+	btVector3FloatData			m_bvhAabbMin;
+	btVector3FloatData			m_bvhAabbMax;
+	btVector3FloatData			m_bvhQuantization;
+	int					m_curNodeIndex;
+	int					m_useQuantization;
+	int					m_numContiguousLeafNodes;
+	int					m_numQuantizedContiguousNodes;
+	btOptimizedBvhNodeFloatData	*m_contiguousNodesPtr;
+	btQuantizedBvhNodeData		*m_quantizedContiguousNodesPtr;
+	btBvhSubtreeInfoData	*m_subTreeInfoPtr;
+	int					m_traversalMode;
+	int					m_numSubtreeHeaders;
+	
+};
+
+struct	btQuantizedBvhDoubleData
+{
+	btVector3DoubleData			m_bvhAabbMin;
+	btVector3DoubleData			m_bvhAabbMax;
+	btVector3DoubleData			m_bvhQuantization;
+	int							m_curNodeIndex;
+	int							m_useQuantization;
+	int							m_numContiguousLeafNodes;
+	int							m_numQuantizedContiguousNodes;
+	btOptimizedBvhNodeDoubleData	*m_contiguousNodesPtr;
+	btQuantizedBvhNodeData			*m_quantizedContiguousNodesPtr;
+
+	int							m_traversalMode;
+	int							m_numSubtreeHeaders;
+	btBvhSubtreeInfoData		*m_subTreeInfoPtr;
+};
+
+
+SIMD_FORCE_INLINE	int	btQuantizedBvh::calculateSerializeBufferSizeNew() const
+{
+	return sizeof(btQuantizedBvhData);
+}
+
+
+
+#endif //BT_QUANTIZED_BVH_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp	(revision 11817)
@@ -0,0 +1,349 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <new>
+
+extern int gOverlappingPairs;
+
+void	btSimpleBroadphase::validate()
+{
+	for (int i=0;i<m_numHandles;i++)
+	{
+		for (int j=i+1;j<m_numHandles;j++)
+		{
+			btAssert(&m_pHandles[i] != &m_pHandles[j]);
+		}
+	}
+	
+}
+
+btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
+	:m_pairCache(overlappingPairCache),
+	m_ownsPairCache(false),
+	m_invalidPair(0)
+{
+
+	if (!overlappingPairCache)
+	{
+		void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+		m_pairCache = new (mem)btHashedOverlappingPairCache();
+		m_ownsPairCache = true;
+	}
+
+	// allocate handles buffer and put all handles on free list
+	m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
+	m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
+	m_maxHandles = maxProxies;
+	m_numHandles = 0;
+	m_firstFreeHandle = 0;
+	m_LastHandleIndex = -1;
+	
+
+	{
+		for (int i = m_firstFreeHandle; i < maxProxies; i++)
+		{
+			m_pHandles[i].SetNextFree(i + 1);
+			m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
+		}
+		m_pHandles[maxProxies - 1].SetNextFree(0);
+	
+	}
+
+}
+
+btSimpleBroadphase::~btSimpleBroadphase()
+{
+	btAlignedFree(m_pHandlesRawPtr);
+
+	if (m_ownsPairCache)
+	{
+		m_pairCache->~btOverlappingPairCache();
+		btAlignedFree(m_pairCache);
+	}
+}
+
+
+btBroadphaseProxy*	btSimpleBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy)
+{
+	if (m_numHandles >= m_maxHandles)
+	{
+		btAssert(0);
+		return 0; //should never happen, but don't let the game crash ;-)
+	}
+	btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
+
+	int newHandleIndex = allocHandle();
+	btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
+
+	return proxy;
+}
+
+class	RemovingOverlapCallback : public btOverlapCallback
+{
+protected:
+	virtual bool	processOverlap(btBroadphasePair& pair)
+	{
+		(void)pair;
+		btAssert(0);
+		return false;
+	}
+};
+
+class RemovePairContainingProxy
+{
+
+	btBroadphaseProxy*	m_targetProxy;
+	public:
+	virtual ~RemovePairContainingProxy()
+	{
+	}
+protected:
+	virtual bool processOverlap(btBroadphasePair& pair)
+	{
+		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0);
+		btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1);
+
+		return ((m_targetProxy == proxy0 || m_targetProxy == proxy1));
+	};
+};
+
+void	btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
+{
+		
+		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
+		freeHandle(proxy0);
+
+		m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
+
+		//validate();
+		
+}
+
+void	btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+	aabbMin = sbp->m_aabbMin;
+	aabbMax = sbp->m_aabbMax;
+}
+
+void	btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
+{
+	btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+	sbp->m_aabbMin = aabbMin;
+	sbp->m_aabbMax = aabbMax;
+}
+
+void	btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	for (int i=0; i <= m_LastHandleIndex; i++)
+	{
+		btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+		if(!proxy->m_clientObject)
+		{
+			continue;
+		}
+		rayCallback.process(proxy);
+	}
+}
+
+
+void	btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+	for (int i=0; i <= m_LastHandleIndex; i++)
+	{
+		btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+		if(!proxy->m_clientObject)
+		{
+			continue;
+		}
+		if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax))
+		{
+			callback.process(proxy);
+		}
+	}
+}
+
+
+
+	
+
+
+
+bool	btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
+{
+	return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] && 
+		   proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
+		   proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
+
+}
+
+
+
+//then remove non-overlapping ones
+class CheckOverlapCallback : public btOverlapCallback
+{
+public:
+	virtual bool processOverlap(btBroadphasePair& pair)
+	{
+		return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
+	}
+};
+
+void	btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+	//first check for new overlapping pairs
+	int i,j;
+	if (m_numHandles >= 0)
+	{
+		int new_largest_index = -1;
+		for (i=0; i <= m_LastHandleIndex; i++)
+		{
+			btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
+			if(!proxy0->m_clientObject)
+			{
+				continue;
+			}
+			new_largest_index = i;
+			for (j=i+1; j <= m_LastHandleIndex; j++)
+			{
+				btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
+				btAssert(proxy0 != proxy1);
+				if(!proxy1->m_clientObject)
+				{
+					continue;
+				}
+
+				btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+				btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+
+				if (aabbOverlap(p0,p1))
+				{
+					if ( !m_pairCache->findPair(proxy0,proxy1))
+					{
+						m_pairCache->addOverlappingPair(proxy0,proxy1);
+					}
+				} else
+				{
+					if (!m_pairCache->hasDeferredRemoval())
+					{
+						if ( m_pairCache->findPair(proxy0,proxy1))
+						{
+							m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+						}
+					}
+				}
+			}
+		}
+
+		m_LastHandleIndex = new_largest_index;
+
+		if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
+		{
+
+			btBroadphasePairArray&	overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+			//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+			overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+			overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+			m_invalidPair = 0;
+
+
+			btBroadphasePair previousPair;
+			previousPair.m_pProxy0 = 0;
+			previousPair.m_pProxy1 = 0;
+			previousPair.m_algorithm = 0;
+
+
+			for (i=0;i<overlappingPairArray.size();i++)
+			{
+
+				btBroadphasePair& pair = overlappingPairArray[i];
+
+				bool isDuplicate = (pair == previousPair);
+
+				previousPair = pair;
+
+				bool needsRemoval = false;
+
+				if (!isDuplicate)
+				{
+					bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+					if (hasOverlap)
+					{
+						needsRemoval = false;//callback->processOverlap(pair);
+					} else
+					{
+						needsRemoval = true;
+					}
+				} else
+				{
+					//remove duplicate
+					needsRemoval = true;
+					//should have no algorithm
+					btAssert(!pair.m_algorithm);
+				}
+
+				if (needsRemoval)
+				{
+					m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+					//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+					//		m_overlappingPairArray.pop_back();
+					pair.m_pProxy0 = 0;
+					pair.m_pProxy1 = 0;
+					m_invalidPair++;
+					gOverlappingPairs--;
+				} 
+
+			}
+
+			///if you don't like to skip the invalid pairs in the array, execute following code:
+#define CLEAN_INVALID_PAIRS 1
+#ifdef CLEAN_INVALID_PAIRS
+
+			//perform a sort, to sort 'invalid' pairs to the end
+			overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+			overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+			m_invalidPair = 0;
+#endif//CLEAN_INVALID_PAIRS
+
+		}
+	}
+}
+
+
+bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+	btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+	return aabbOverlap(p0,p1);
+}
+
+void	btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
+{
+	//not yet
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h	(revision 11817)
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLE_BROADPHASE_H
+#define BT_SIMPLE_BROADPHASE_H
+
+
+#include "btOverlappingPairCache.h"
+
+
+struct btSimpleBroadphaseProxy : public btBroadphaseProxy
+{
+	int			m_nextFree;
+	
+//	int			m_handleId;
+
+	
+	btSimpleBroadphaseProxy() {};
+
+	btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
+	:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy)
+	{
+		(void)shapeType;
+	}
+	
+	
+	SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
+	SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
+
+	
+
+
+};
+
+///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
+///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
+class btSimpleBroadphase : public btBroadphaseInterface
+{
+
+protected:
+
+	int		m_numHandles;						// number of active handles
+	int		m_maxHandles;						// max number of handles
+	int		m_LastHandleIndex;							
+	
+	btSimpleBroadphaseProxy* m_pHandles;						// handles pool
+
+	void* m_pHandlesRawPtr;
+	int		m_firstFreeHandle;		// free handles list
+	
+	int allocHandle()
+	{
+		btAssert(m_numHandles < m_maxHandles);
+		int freeHandle = m_firstFreeHandle;
+		m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
+		m_numHandles++;
+		if(freeHandle > m_LastHandleIndex)
+		{
+			m_LastHandleIndex = freeHandle;
+		}
+		return freeHandle;
+	}
+
+	void freeHandle(btSimpleBroadphaseProxy* proxy)
+	{
+		int handle = int(proxy-m_pHandles);
+		btAssert(handle >= 0 && handle < m_maxHandles);
+		if(handle == m_LastHandleIndex)
+		{
+			m_LastHandleIndex--;
+		}
+		proxy->SetNextFree(m_firstFreeHandle);
+		m_firstFreeHandle = handle;
+
+		proxy->m_clientObject = 0;
+
+		m_numHandles--;
+	}
+
+	btOverlappingPairCache*	m_pairCache;
+	bool	m_ownsPairCache;
+
+	int	m_invalidPair;
+
+	
+	
+	inline btSimpleBroadphaseProxy*	getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
+	{
+		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
+		return proxy0;
+	}
+
+	inline const btSimpleBroadphaseProxy*	getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
+	{
+		const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
+		return proxy0;
+	}
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher);
+
+
+	void	validate();
+
+protected:
+
+
+	
+
+public:
+	btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
+	virtual ~btSimpleBroadphase();
+
+
+		static bool	aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
+
+
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
+
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher);
+
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
+	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+		
+	btOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_pairCache;
+	}
+	const btOverlappingPairCache*	getOverlappingPairCache() const
+	{
+		return m_pairCache;
+	}
+
+	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+		aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+	}
+
+	virtual void	printStats()
+	{
+//		printf("btSimpleBroadphase.h\n");
+//		printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+	}
+};
+
+
+
+#endif //BT_SIMPLE_BROADPHASE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,187 @@
+ADD_SOURCE_FILES(BULLET_FILES
+
+	BroadphaseCollision/btAxisSweep3.cpp
+	BroadphaseCollision/btBroadphaseProxy.cpp
+	BroadphaseCollision/btCollisionAlgorithm.cpp
+	BroadphaseCollision/btDbvt.cpp
+	BroadphaseCollision/btDbvtBroadphase.cpp
+	BroadphaseCollision/btDispatcher.cpp
+	BroadphaseCollision/btMultiSapBroadphase.cpp
+	BroadphaseCollision/btOverlappingPairCache.cpp
+	BroadphaseCollision/btQuantizedBvh.cpp
+	BroadphaseCollision/btSimpleBroadphase.cpp
+
+	CollisionDispatch/btActivatingCollisionAlgorithm.cpp
+	CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+	CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
+	CollisionDispatch/btBoxBoxDetector.cpp
+	CollisionDispatch/btCollisionDispatcher.cpp
+	CollisionDispatch/btCollisionObject.cpp
+	CollisionDispatch/btCollisionWorld.cpp
+	CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+	CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+	CollisionDispatch/btConvexConvexAlgorithm.cpp
+	CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+	CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
+	CollisionDispatch/btDefaultCollisionConfiguration.cpp
+	CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+	CollisionDispatch/btGhostObject.cpp
+	CollisionDispatch/btInternalEdgeUtility.cpp
+	CollisionDispatch/btInternalEdgeUtility.h
+	CollisionDispatch/btManifoldResult.cpp
+	CollisionDispatch/btSimulationIslandManager.cpp
+	CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+	CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+	CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+	CollisionDispatch/btUnionFind.cpp
+	CollisionDispatch/SphereTriangleDetector.cpp
+
+	CollisionShapes/btBoxShape.cpp
+	CollisionShapes/btBox2dShape.cpp
+	CollisionShapes/btBvhTriangleMeshShape.cpp
+	CollisionShapes/btCapsuleShape.cpp
+	CollisionShapes/btCollisionShape.cpp
+	CollisionShapes/btCompoundShape.cpp
+	CollisionShapes/btConcaveShape.cpp
+	CollisionShapes/btConeShape.cpp
+	CollisionShapes/btConvexHullShape.cpp
+	CollisionShapes/btConvexInternalShape.cpp
+	CollisionShapes/btConvexPointCloudShape.cpp
+	CollisionShapes/btConvexPolyhedron.cpp
+	CollisionShapes/btConvexShape.cpp
+	CollisionShapes/btConvex2dShape.cpp
+	CollisionShapes/btConvexTriangleMeshShape.cpp
+	CollisionShapes/btCylinderShape.cpp
+	CollisionShapes/btEmptyShape.cpp
+	CollisionShapes/btHeightfieldTerrainShape.cpp
+	CollisionShapes/btMinkowskiSumShape.cpp
+	CollisionShapes/btMultimaterialTriangleMeshShape.cpp
+	CollisionShapes/btMultiSphereShape.cpp
+	CollisionShapes/btOptimizedBvh.cpp
+	CollisionShapes/btPolyhedralConvexShape.cpp
+	CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+	CollisionShapes/btShapeHull.cpp
+	CollisionShapes/btSphereShape.cpp
+	CollisionShapes/btStaticPlaneShape.cpp
+	CollisionShapes/btStridingMeshInterface.cpp
+	CollisionShapes/btTetrahedronShape.cpp
+	CollisionShapes/btTriangleBuffer.cpp
+	CollisionShapes/btTriangleCallback.cpp
+	CollisionShapes/btTriangleIndexVertexArray.cpp
+	CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
+	CollisionShapes/btTriangleMesh.cpp
+	CollisionShapes/btTriangleMeshShape.cpp
+	CollisionShapes/btUniformScalingShape.cpp
+
+	NarrowPhaseCollision/btContinuousConvexCollision.cpp
+	NarrowPhaseCollision/btConvexCast.cpp
+	NarrowPhaseCollision/btGjkConvexCast.cpp
+	NarrowPhaseCollision/btGjkEpa2.cpp
+	NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+	NarrowPhaseCollision/btGjkPairDetector.cpp
+	NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+	NarrowPhaseCollision/btPersistentManifold.cpp
+	NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+	NarrowPhaseCollision/btRaycastCallback.cpp
+	NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+	NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+
+
+	# Headers
+	BroadphaseCollision/btAxisSweep3.h
+	BroadphaseCollision/btBroadphaseInterface.h
+	BroadphaseCollision/btBroadphaseProxy.h
+	BroadphaseCollision/btCollisionAlgorithm.h
+	BroadphaseCollision/btDbvt.h
+	BroadphaseCollision/btDbvtBroadphase.h
+	BroadphaseCollision/btDispatcher.h
+	BroadphaseCollision/btMultiSapBroadphase.h
+	BroadphaseCollision/btOverlappingPairCache.h
+	BroadphaseCollision/btOverlappingPairCallback.h
+	BroadphaseCollision/btQuantizedBvh.h
+	BroadphaseCollision/btSimpleBroadphase.h
+
+	CollisionDispatch/btActivatingCollisionAlgorithm.h
+	CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+	CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
+	CollisionDispatch/btBoxBoxDetector.h
+	CollisionDispatch/btCollisionConfiguration.h
+	CollisionDispatch/btCollisionCreateFunc.h
+	CollisionDispatch/btCollisionDispatcher.h
+	CollisionDispatch/btCollisionObject.h
+	CollisionDispatch/btCollisionWorld.h
+	CollisionDispatch/btCompoundCollisionAlgorithm.h
+	CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+	CollisionDispatch/btConvexConvexAlgorithm.h
+	CollisionDispatch/btConvex2dConvex2dAlgorithm.h
+	CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+	CollisionDispatch/btDefaultCollisionConfiguration.h
+	CollisionDispatch/btEmptyCollisionAlgorithm.h
+	CollisionDispatch/btGhostObject.h
+	CollisionDispatch/btManifoldResult.h
+	CollisionDispatch/btSimulationIslandManager.h
+	CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+	CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+	CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
+	CollisionDispatch/btUnionFind.h
+	CollisionDispatch/SphereTriangleDetector.h
+
+	CollisionShapes/btBoxShape.h
+	CollisionShapes/btBox2dShape.h
+	CollisionShapes/btBvhTriangleMeshShape.h
+	CollisionShapes/btCapsuleShape.h
+	CollisionShapes/btCollisionMargin.h
+	CollisionShapes/btCollisionShape.h
+	CollisionShapes/btCompoundShape.h
+	CollisionShapes/btConcaveShape.h
+	CollisionShapes/btConeShape.h
+	CollisionShapes/btConvexHullShape.h
+	CollisionShapes/btConvexInternalShape.h
+	CollisionShapes/btConvexPointCloudShape.h
+	CollisionShapes/btConvexPolyhedron.h
+	CollisionShapes/btConvexShape.h
+	CollisionShapes/btConvex2dShape.h
+	CollisionShapes/btConvexTriangleMeshShape.h
+	CollisionShapes/btCylinderShape.h
+	CollisionShapes/btEmptyShape.h
+	CollisionShapes/btHeightfieldTerrainShape.h
+	CollisionShapes/btMaterial.h
+	CollisionShapes/btMinkowskiSumShape.h
+	CollisionShapes/btMultimaterialTriangleMeshShape.h
+	CollisionShapes/btMultiSphereShape.h
+	CollisionShapes/btOptimizedBvh.h
+	CollisionShapes/btPolyhedralConvexShape.h
+	CollisionShapes/btScaledBvhTriangleMeshShape.h
+	CollisionShapes/btShapeHull.h
+	CollisionShapes/btSphereShape.h
+	CollisionShapes/btStaticPlaneShape.h
+	CollisionShapes/btStridingMeshInterface.h
+	CollisionShapes/btTetrahedronShape.h
+	CollisionShapes/btTriangleBuffer.h
+	CollisionShapes/btTriangleCallback.h
+	CollisionShapes/btTriangleIndexVertexArray.h
+	CollisionShapes/btTriangleIndexVertexMaterialArray.h
+	CollisionShapes/btTriangleInfoMap.h
+	CollisionShapes/btTriangleMesh.h
+	CollisionShapes/btTriangleMeshShape.h
+	CollisionShapes/btTriangleShape.h
+	CollisionShapes/btUniformScalingShape.h
+
+	NarrowPhaseCollision/btContinuousConvexCollision.h
+	NarrowPhaseCollision/btConvexCast.h
+	NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
+	NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
+	NarrowPhaseCollision/btGjkConvexCast.h
+	NarrowPhaseCollision/btGjkEpa2.h
+	NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
+	NarrowPhaseCollision/btGjkPairDetector.h
+	NarrowPhaseCollision/btManifoldPoint.h
+	NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
+	NarrowPhaseCollision/btPersistentManifold.h
+	NarrowPhaseCollision/btPointCollector.h
+	NarrowPhaseCollision/btRaycastCallback.h
+	NarrowPhaseCollision/btSimplexSolverInterface.h
+	NarrowPhaseCollision/btSubSimplexConvexCast.h
+	NarrowPhaseCollision/btVoronoiSimplexSolver.h
+	NarrowPhaseCollision/btPolyhedralContactClipping.h
+)
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp	(revision 11817)
@@ -0,0 +1,201 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btScalar.h"
+#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
+:m_sphere(sphere),
+m_triangle(triangle),
+m_contactBreakingThreshold(contactBreakingThreshold)
+{
+
+}
+
+void	SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+{
+
+	(void)debugDraw;
+	const btTransform& transformA = input.m_transformA;
+	const btTransform& transformB = input.m_transformB;
+
+	btVector3 point,normal;
+	btScalar timeOfImpact = btScalar(1.);
+	btScalar depth = btScalar(0.);
+//	output.m_distance = btScalar(BT_LARGE_FLOAT);
+	//move sphere into triangle space
+	btTransform	sphereInTr = transformB.inverseTimes(transformA);
+
+	if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
+	{
+		if (swapResults)
+		{
+			btVector3 normalOnB = transformB.getBasis()*normal;
+			btVector3 normalOnA = -normalOnB;
+			btVector3 pointOnA = transformB*point+normalOnB*depth;
+			output.addContactPoint(normalOnA,pointOnA,depth);
+		} else
+		{
+			output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+		}
+	}
+
+}
+
+
+
+// See also geometrictools.com
+// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
+
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
+	btVector3 diff = p - from;
+	btVector3 v = to - from;
+	btScalar t = v.dot(diff);
+	
+	if (t > 0) {
+		btScalar dotVV = v.dot(v);
+		if (t < dotVV) {
+			t /= dotVV;
+			diff -= t*v;
+		} else {
+			t = 1;
+			diff -= v;
+		}
+	} else
+		t = 0;
+
+	nearest = from + t*v;
+	return diff.dot(diff);	
+}
+
+bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal)  {
+	btVector3 lp(p);
+	btVector3 lnormal(normal);
+	
+	return pointInTriangle(vertices, lnormal, &lp);
+}
+
+bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
+{
+
+	const btVector3* vertices = &m_triangle->getVertexPtr(0);
+	
+	btScalar radius = m_sphere->getRadius();
+	btScalar radiusWithThreshold = radius + contactBreakingThreshold;
+
+	btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
+	normal.normalize();
+	btVector3 p1ToCentre = sphereCenter - vertices[0];
+	btScalar distanceFromPlane = p1ToCentre.dot(normal);
+
+	if (distanceFromPlane < btScalar(0.))
+	{
+		//triangle facing the other way
+		distanceFromPlane *= btScalar(-1.);
+		normal *= btScalar(-1.);
+	}
+
+	bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
+	
+	// Check for contact / intersection
+	bool hasContact = false;
+	btVector3 contactPoint;
+	if (isInsideContactPlane) {
+		if (facecontains(sphereCenter,vertices,normal)) {
+			// Inside the contact wedge - touches a point on the shell plane
+			hasContact = true;
+			contactPoint = sphereCenter - normal*distanceFromPlane;
+		} else {
+			// Could be inside one of the contact capsules
+			btScalar contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
+			btVector3 nearestOnEdge;
+			for (int i = 0; i < m_triangle->getNumEdges(); i++) {
+				
+				btVector3 pa;
+				btVector3 pb;
+				
+				m_triangle->getEdge(i,pa,pb);
+
+				btScalar distanceSqr = SegmentSqrDistance(pa,pb,sphereCenter, nearestOnEdge);
+				if (distanceSqr < contactCapsuleRadiusSqr) {
+					// Yep, we're inside a capsule
+					hasContact = true;
+					contactPoint = nearestOnEdge;
+				}
+				
+			}
+		}
+	}
+
+	if (hasContact) {
+		btVector3 contactToCentre = sphereCenter - contactPoint;
+		btScalar distanceSqr = contactToCentre.length2();
+
+		if (distanceSqr < radiusWithThreshold*radiusWithThreshold)
+		{
+			if (distanceSqr>SIMD_EPSILON)
+			{
+				btScalar distance = btSqrt(distanceSqr);
+				resultNormal = contactToCentre;
+				resultNormal.normalize();
+				point = contactPoint;
+				depth = -(radius-distance);
+			} else
+			{
+				btScalar distance = 0.f;
+				resultNormal = normal;
+				point = contactPoint;
+				depth = -radius;
+			}
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+
+bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
+{
+	const btVector3* p1 = &vertices[0];
+	const btVector3* p2 = &vertices[1];
+	const btVector3* p3 = &vertices[2];
+
+	btVector3 edge1( *p2 - *p1 );
+	btVector3 edge2( *p3 - *p2 );
+	btVector3 edge3( *p1 - *p3 );
+
+	btVector3 p1_to_p( *p - *p1 );
+	btVector3 p2_to_p( *p - *p2 );
+	btVector3 p3_to_p( *p - *p3 );
+
+	btVector3 edge1_normal( edge1.cross(normal));
+	btVector3 edge2_normal( edge2.cross(normal));
+	btVector3 edge3_normal( edge3.cross(normal));
+	
+	btScalar r1, r2, r3;
+	r1 = edge1_normal.dot( p1_to_p );
+	r2 = edge2_normal.dot( p2_to_p );
+	r3 = edge3_normal.dot( p3_to_p );
+	if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
+	     ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
+		return true;
+	return false;
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_TRIANGLE_DETECTOR_H
+#define BT_SPHERE_TRIANGLE_DETECTOR_H
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+
+class btSphereShape;
+class btTriangleShape;
+
+
+
+/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
+struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
+{
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+	SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold);
+
+	virtual ~SphereTriangleDetector() {};
+
+	bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar	contactBreakingThreshold);
+
+private:
+
+	
+	bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
+	bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
+
+	btSphereShape* m_sphere;
+	btTriangleShape* m_triangle;
+	btScalar	m_contactBreakingThreshold;
+	
+};
+#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "btCollisionDispatcher.h"
+#include "btCollisionObject.h"
+
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
+:btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+}
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1)
+:btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+//	if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
+//	{
+//		m_colObj0 = colObj0;
+//		m_colObj1 = colObj1;
+//		
+//		m_colObj0->activate();
+//		m_colObj1->activate();
+//	}
+}
+
+btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
+{
+//		m_colObj0->activate();
+//		m_colObj1->activate();
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,36 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H
+#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
+class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
+{
+//	btCollisionObject* m_colObj0;
+//	btCollisionObject* m_colObj1;
+
+public:
+
+	btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
+
+	btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1);
+
+	virtual ~btActivatingCollisionAlgorithm();
+
+};
+#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,435 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library.
+///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross
+
+#include "btBox2dBox2dCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBox2dShape.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btActivatingCollisionAlgorithm(ci,obj0,obj1),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+		m_ownManifold = true;
+	}
+}
+
+btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
+{
+	
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+	
+}
+
+
+void b2CollidePolygons(btManifoldResult* manifold,  const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
+
+//#include <stdio.h>
+void btBox2dBox2dCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject*	col0 = body0;
+	btCollisionObject*	col1 = body1;
+	btBox2dShape* box0 = (btBox2dShape*)col0->getCollisionShape();
+	btBox2dShape* box1 = (btBox2dShape*)col1->getCollisionShape();
+
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	b2CollidePolygons(resultOut,box0,col0->getWorldTransform(),box1,col1->getWorldTransform());
+
+	//  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+
+}
+
+btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+	//not yet
+	return 1.f;
+}
+
+
+struct ClipVertex
+{
+	btVector3 v;
+	int id;
+	//b2ContactID id;
+	//b2ContactID id;
+};
+
+#define b2Dot(a,b) (a).dot(b)
+#define b2Mul(a,b) (a)*(b)
+#define b2MulT(a,b) (a).transpose()*(b)
+#define b2Cross(a,b) (a).cross(b)
+#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f)
+
+int b2_maxManifoldPoints =2;
+
+static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
+					  const btVector3& normal, btScalar offset)
+{
+	// Start with no output points
+	int numOut = 0;
+
+	// Calculate the distance of end points to the line
+	btScalar distance0 = b2Dot(normal, vIn[0].v) - offset;
+	btScalar distance1 = b2Dot(normal, vIn[1].v) - offset;
+
+	// If the points are behind the plane
+	if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
+	if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];
+
+	// If the points are on different sides of the plane
+	if (distance0 * distance1 < 0.0f)
+	{
+		// Find intersection point of edge and plane
+		btScalar interp = distance0 / (distance0 - distance1);
+		vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
+		if (distance0 > 0.0f)
+		{
+			vOut[numOut].id = vIn[0].id;
+		}
+		else
+		{
+			vOut[numOut].id = vIn[1].id;
+		}
+		++numOut;
+	}
+
+	return numOut;
+}
+
+// Find the separation between poly1 and poly2 for a give edge normal on poly1.
+static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+							  const btBox2dShape* poly2, const btTransform& xf2)
+{
+	const btVector3* vertices1 = poly1->getVertices();
+	const btVector3* normals1 = poly1->getNormals();
+
+	int count2 = poly2->getVertexCount();
+	const btVector3* vertices2 = poly2->getVertices();
+
+	btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+	// Convert normal from poly1's frame into poly2's frame.
+	btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]);
+	btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World);
+
+	// Find support vertex on poly2 for -normal.
+	int index = 0;
+	btScalar minDot = BT_LARGE_FLOAT;
+
+	for (int i = 0; i < count2; ++i)
+	{
+		btScalar dot = b2Dot(vertices2[i], normal1);
+		if (dot < minDot)
+		{
+			minDot = dot;
+			index = i;
+		}
+	}
+
+	btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
+	btVector3 v2 = b2Mul(xf2, vertices2[index]);
+	btScalar separation = b2Dot(v2 - v1, normal1World);
+	return separation;
+}
+
+// Find the max separation between poly1 and poly2 using edge normals from poly1.
+static btScalar FindMaxSeparation(int* edgeIndex,
+								 const btBox2dShape* poly1, const btTransform& xf1,
+								 const btBox2dShape* poly2, const btTransform& xf2)
+{
+	int count1 = poly1->getVertexCount();
+	const btVector3* normals1 = poly1->getNormals();
+
+	// Vector pointing from the centroid of poly1 to the centroid of poly2.
+	btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid());
+	btVector3 dLocal1 = b2MulT(xf1.getBasis(), d);
+
+	// Find edge normal on poly1 that has the largest projection onto d.
+	int edge = 0;
+	btScalar maxDot = -BT_LARGE_FLOAT;
+	for (int i = 0; i < count1; ++i)
+	{
+		btScalar dot = b2Dot(normals1[i], dLocal1);
+		if (dot > maxDot)
+		{
+			maxDot = dot;
+			edge = i;
+		}
+	}
+
+	// Get the separation for the edge normal.
+	btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+	if (s > 0.0f)
+	{
+		return s;
+	}
+
+	// Check the separation for the previous edge normal.
+	int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
+	btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
+	if (sPrev > 0.0f)
+	{
+		return sPrev;
+	}
+
+	// Check the separation for the next edge normal.
+	int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
+	btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
+	if (sNext > 0.0f)
+	{
+		return sNext;
+	}
+
+	// Find the best edge and the search direction.
+	int bestEdge;
+	btScalar bestSeparation;
+	int increment;
+	if (sPrev > s && sPrev > sNext)
+	{
+		increment = -1;
+		bestEdge = prevEdge;
+		bestSeparation = sPrev;
+	}
+	else if (sNext > s)
+	{
+		increment = 1;
+		bestEdge = nextEdge;
+		bestSeparation = sNext;
+	}
+	else
+	{
+		*edgeIndex = edge;
+		return s;
+	}
+
+	// Perform a local search for the best edge normal.
+	for ( ; ; )
+	{
+		if (increment == -1)
+			edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
+		else
+			edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
+
+		s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+		if (s > 0.0f)
+		{
+			return s;
+		}
+
+		if (s > bestSeparation)
+		{
+			bestEdge = edge;
+			bestSeparation = s;
+		}
+		else
+		{
+			break;
+		}
+	}
+
+	*edgeIndex = bestEdge;
+	return bestSeparation;
+}
+
+static void FindIncidentEdge(ClipVertex c[2],
+							 const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+							 const btBox2dShape* poly2, const btTransform& xf2)
+{
+	const btVector3* normals1 = poly1->getNormals();
+
+	int count2 = poly2->getVertexCount();
+	const btVector3* vertices2 = poly2->getVertices();
+	const btVector3* normals2 = poly2->getNormals();
+
+	btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+	// Get the normal of the reference edge in poly2's frame.
+	btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1]));
+
+	// Find the incident edge on poly2.
+	int index = 0;
+	btScalar minDot = BT_LARGE_FLOAT;
+	for (int i = 0; i < count2; ++i)
+	{
+		btScalar dot = b2Dot(normal1, normals2[i]);
+		if (dot < minDot)
+		{
+			minDot = dot;
+			index = i;
+		}
+	}
+
+	// Build the clip vertices for the incident edge.
+	int i1 = index;
+	int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
+
+	c[0].v = b2Mul(xf2, vertices2[i1]);
+//	c[0].id.features.referenceEdge = (unsigned char)edge1;
+//	c[0].id.features.incidentEdge = (unsigned char)i1;
+//	c[0].id.features.incidentVertex = 0;
+
+	c[1].v = b2Mul(xf2, vertices2[i2]);
+//	c[1].id.features.referenceEdge = (unsigned char)edge1;
+//	c[1].id.features.incidentEdge = (unsigned char)i2;
+//	c[1].id.features.incidentVertex = 1;
+}
+
+// Find edge normal of max separation on A - return if separating axis is found
+// Find edge normal of max separation on B - return if separation axis is found
+// Choose reference edge as min(minA, minB)
+// Find incident edge
+// Clip
+
+// The normal points from 1 to 2
+void b2CollidePolygons(btManifoldResult* manifold,
+					  const btBox2dShape* polyA, const btTransform& xfA,
+					  const btBox2dShape* polyB, const btTransform& xfB)
+{
+
+	int edgeA = 0;
+	btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
+	if (separationA > 0.0f)
+		return;
+
+	int edgeB = 0;
+	btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);
+	if (separationB > 0.0f)
+		return;
+
+	const btBox2dShape* poly1;	// reference poly
+	const btBox2dShape* poly2;	// incident poly
+	btTransform xf1, xf2;
+	int edge1;		// reference edge
+	unsigned char flip;
+	const btScalar k_relativeTol = 0.98f;
+	const btScalar k_absoluteTol = 0.001f;
+
+	// TODO_ERIN use "radius" of poly for absolute tolerance.
+	if (separationB > k_relativeTol * separationA + k_absoluteTol)
+	{
+		poly1 = polyB;
+		poly2 = polyA;
+		xf1 = xfB;
+		xf2 = xfA;
+		edge1 = edgeB;
+		flip = 1;
+	}
+	else
+	{
+		poly1 = polyA;
+		poly2 = polyB;
+		xf1 = xfA;
+		xf2 = xfB;
+		edge1 = edgeA;
+		flip = 0;
+	}
+
+	ClipVertex incidentEdge[2];
+	FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
+
+	int count1 = poly1->getVertexCount();
+	const btVector3* vertices1 = poly1->getVertices();
+
+	btVector3 v11 = vertices1[edge1];
+	btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
+
+	btVector3 dv = v12 - v11;
+	btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
+	sideNormal.normalize();
+	btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
+	
+	
+	v11 = b2Mul(xf1, v11);
+	v12 = b2Mul(xf1, v12);
+
+	btScalar frontOffset = b2Dot(frontNormal, v11);
+	btScalar sideOffset1 = -b2Dot(sideNormal, v11);
+	btScalar sideOffset2 = b2Dot(sideNormal, v12);
+
+	// Clip incident edge against extruded edge1 side edges.
+	ClipVertex clipPoints1[2];
+	clipPoints1[0].v.setValue(0,0,0);
+	clipPoints1[1].v.setValue(0,0,0);
+
+	ClipVertex clipPoints2[2];
+	clipPoints2[0].v.setValue(0,0,0);
+	clipPoints2[1].v.setValue(0,0,0);
+
+
+	int np;
+
+	// Clip to box side 1
+	np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
+
+	if (np < 2)
+		return;
+
+	// Clip to negative box side 1
+	np = ClipSegmentToLine(clipPoints2, clipPoints1,  sideNormal, sideOffset2);
+
+	if (np < 2)
+	{
+		return;
+	}
+
+	// Now clipPoints2 contains the clipped points.
+	btVector3 manifoldNormal = flip ? -frontNormal : frontNormal;
+
+	int pointCount = 0;
+	for (int i = 0; i < b2_maxManifoldPoints; ++i)
+	{
+		btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
+
+		if (separation <= 0.0f)
+		{
+			
+			//b2ManifoldPoint* cp = manifold->points + pointCount;
+			//btScalar separation = separation;
+			//cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
+			//cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
+
+			manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation);
+
+//			cp->id = clipPoints2[i].id;
+//			cp->id.features.flip = flip;
+			++pointCount;
+		}
+	}
+
+//	manifold->pointCount = pointCount;}
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	
+public:
+	btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btBox2dBox2dCollisionAlgorithm();
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
+			void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+			return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0,body1);
+		}
+	};
+
+};
+
+#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btBoxBoxDetector.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btActivatingCollisionAlgorithm(ci,obj0,obj1),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+		m_ownManifold = true;
+	}
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject*	col0 = body0;
+	btCollisionObject*	col1 = body1;
+	btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
+	btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
+
+
+
+	/// report a contact. internally this will be kept persistent, and contact reduction is done
+	resultOut->setPersistentManifold(m_manifoldPtr);
+#ifndef USE_PERSISTENT_CONTACTS	
+	m_manifoldPtr->clearManifold();
+#endif //USE_PERSISTENT_CONTACTS
+
+	btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+	input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+	input.m_transformA = body0->getWorldTransform();
+	input.m_transformB = body1->getWorldTransform();
+
+	btBoxBoxDetector detector(box0,box1);
+	detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+#ifdef USE_PERSISTENT_CONTACTS
+	//  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+#endif //USE_PERSISTENT_CONTACTS
+
+}
+
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+	//not yet
+	return 1.f;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BOX_BOX__COLLISION_ALGORITHM_H
+#define BT_BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	
+public:
+	btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btBoxBoxCollisionAlgorithm();
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+			void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+			return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
+		}
+	};
+
+};
+
+#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp	(revision 11817)
@@ -0,0 +1,718 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org
+ Bullet Continuous Collision Detection and Physics Library
+ Bullet is Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///ODE box-box collision detection is adapted to work with Bullet
+
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
+#include <float.h>
+#include <string.h>
+
+btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
+: m_box1(box1),
+m_box2(box2)
+{
+
+}
+
+
+// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
+// generate contact points. this returns 0 if there is no contact otherwise
+// it returns the number of contacts generated.
+// `normal' returns the contact normal.
+// `depth' returns the maximum penetration depth along that normal.
+// `return_code' returns a number indicating the type of contact that was
+// detected:
+//        1,2,3 = box 2 intersects with a face of box 1
+//        4,5,6 = box 1 intersects with a face of box 2
+//        7..15 = edge-edge contact
+// `maxc' is the maximum number of contacts allowed to be generated, i.e.
+// the size of the `contact' array.
+// `contact' and `skip' are the contact array information provided to the
+// collision functions. this function only fills in the position and depth
+// fields.
+struct dContactGeom;
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dInfinity FLT_MAX
+
+
+/*PURE_INLINE btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
+*/
+static btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
+static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
+static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
+#define dMULTIPLYOP1_331(A,op,B,C) \
+{\
+  (A)[0] op dDOT41((B),(C)); \
+  (A)[1] op dDOT41((B+1),(C)); \
+  (A)[2] op dDOT41((B+2),(C)); \
+}
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+{ \
+  (A)[0] op dDOT((B),(C)); \
+  (A)[1] op dDOT((B+4),(C)); \
+  (A)[2] op dDOT((B+8),(C)); \
+} 
+
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+
+typedef btScalar dMatrix3[4*3];
+
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+			   const btVector3& pb, const btVector3& ub,
+			   btScalar *alpha, btScalar *beta);
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+			   const btVector3& pb, const btVector3& ub,
+			   btScalar *alpha, btScalar *beta)
+{
+  btVector3 p;
+  p[0] = pb[0] - pa[0];
+  p[1] = pb[1] - pa[1];
+  p[2] = pb[2] - pa[2];
+  btScalar uaub = dDOT(ua,ub);
+  btScalar q1 =  dDOT(ua,p);
+  btScalar q2 = -dDOT(ub,p);
+  btScalar d = 1-uaub*uaub;
+  if (d <= btScalar(0.0001f)) {
+    // @@@ this needs to be made more robust
+    *alpha = 0;
+    *beta  = 0;
+  }
+  else {
+    d = 1.f/d;
+    *alpha = (q1 + uaub*q2)*d;
+    *beta  = (uaub*q1 + q2)*d;
+  }
+}
+
+
+
+// find all the intersection points between the 2D rectangle with vertices
+// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
+// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
+//
+// the intersection points are returned as x,y pairs in the 'ret' array.
+// the number of intersection points is returned by the function (this will
+// be in the range 0 to 8).
+
+static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+{
+  // q (and r) contain nq (and nr) coordinate points for the current (and
+  // chopped) polygons
+  int nq=4,nr=0;
+  btScalar buffer[16];
+  btScalar *q = p;
+  btScalar *r = ret;
+  for (int dir=0; dir <= 1; dir++) {
+    // direction notation: xy[0] = x axis, xy[1] = y axis
+    for (int sign=-1; sign <= 1; sign += 2) {
+      // chop q along the line xy[dir] = sign*h[dir]
+      btScalar *pq = q;
+      btScalar *pr = r;
+      nr = 0;
+      for (int i=nq; i > 0; i--) {
+	// go through all points in q and all lines between adjacent points
+	if (sign*pq[dir] < h[dir]) {
+	  // this point is inside the chopping line
+	  pr[0] = pq[0];
+	  pr[1] = pq[1];
+	  pr += 2;
+	  nr++;
+	  if (nr & 8) {
+	    q = r;
+	    goto done;
+	  }
+	}
+	btScalar *nextq = (i > 1) ? pq+2 : q;
+	if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
+	  // this line crosses the chopping line
+	  pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
+	    (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
+	  pr[dir] = sign*h[dir];
+	  pr += 2;
+	  nr++;
+	  if (nr & 8) {
+	    q = r;
+	    goto done;
+	  }
+	}
+	pq += 2;
+      }
+      q = r;
+      r = (q==ret) ? buffer : ret;
+      nq = nr;
+    }
+  }
+ done:
+  if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
+  return nr;
+}
+
+
+#define M__PI 3.14159265f
+
+// given n points in the plane (array p, of size 2*n), generate m points that
+// best represent the whole set. the definition of 'best' here is not
+// predetermined - the idea is to select points that give good box-box
+// collision detection behavior. the chosen point indexes are returned in the
+// array iret (of size m). 'i0' is always the first entry in the array.
+// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
+// in the range [0..n-1].
+
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+{
+  // compute the centroid of the polygon in cx,cy
+  int i,j;
+  btScalar a,cx,cy,q;
+  if (n==1) {
+    cx = p[0];
+    cy = p[1];
+  }
+  else if (n==2) {
+    cx = btScalar(0.5)*(p[0] + p[2]);
+    cy = btScalar(0.5)*(p[1] + p[3]);
+  }
+  else {
+    a = 0;
+    cx = 0;
+    cy = 0;
+    for (i=0; i<(n-1); i++) {
+      q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
+      a += q;
+      cx += q*(p[i*2]+p[i*2+2]);
+      cy += q*(p[i*2+1]+p[i*2+3]);
+    }
+    q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
+	if (btFabs(a+q) > SIMD_EPSILON)
+	{
+		a = 1.f/(btScalar(3.0)*(a+q));
+	} else
+	{
+		a=BT_LARGE_FLOAT;
+	}
+    cx = a*(cx + q*(p[n*2-2]+p[0]));
+    cy = a*(cy + q*(p[n*2-1]+p[1]));
+  }
+
+  // compute the angle of each point w.r.t. the centroid
+  btScalar A[8];
+  for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
+
+  // search for points that have angles closest to A[i0] + i*(2*pi/m).
+  int avail[8];
+  for (i=0; i<n; i++) avail[i] = 1;
+  avail[i0] = 0;
+  iret[0] = i0;
+  iret++;
+  for (j=1; j<m; j++) {
+    a = btScalar(j)*(2*M__PI/m) + A[i0];
+    if (a > M__PI) a -= 2*M__PI;
+    btScalar maxdiff=1e9,diff;
+
+    *iret = i0;			// iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
+
+    for (i=0; i<n; i++) {
+      if (avail[i]) {
+	diff = btFabs (A[i]-a);
+	if (diff > M__PI) diff = 2*M__PI - diff;
+	if (diff < maxdiff) {
+	  maxdiff = diff;
+	  *iret = i;
+	}
+      }
+    }
+#if defined(DEBUG) || defined (_DEBUG)
+    btAssert (*iret != i0);	// ensure iret got set
+#endif
+    avail[*iret] = 0;
+    iret++;
+  }
+}
+
+
+
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+	     const btVector3& side1, const btVector3& p2,
+	     const dMatrix3 R2, const btVector3& side2,
+	     btVector3& normal, btScalar *depth, int *return_code,
+		 int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+	     const btVector3& side1, const btVector3& p2,
+	     const dMatrix3 R2, const btVector3& side2,
+	     btVector3& normal, btScalar *depth, int *return_code,
+		 int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
+{
+  const btScalar fudge_factor = btScalar(1.05);
+  btVector3 p,pp,normalC(0.f,0.f,0.f);
+  const btScalar *normalR = 0;
+  btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
+    Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
+  int i,j,invert_normal,code;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p = p2 - p1;
+  dMULTIPLY1_331 (pp,R1,p);		// get pp = p relative to body 1
+
+  // get side lengths / 2
+  A[0] = side1[0]*btScalar(0.5);
+  A[1] = side1[1]*btScalar(0.5);
+  A[2] = side1[2]*btScalar(0.5);
+  B[0] = side2[0]*btScalar(0.5);
+  B[1] = side2[1]*btScalar(0.5);
+  B[2] = side2[2]*btScalar(0.5);
+
+  // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+  R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+  R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+  R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+
+  Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
+  Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
+  Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
+
+  // for all 15 possible separating axes:
+  //   * see if the axis separates the boxes. if so, return 0.
+  //   * find the depth of the penetration along the separating axis (s2)
+  //   * if this is the largest depth so far, record it.
+  // the normal vector will be set to the separating axis with the smallest
+  // depth. note: normalR is set to point to a column of R1 or R2 if that is
+  // the smallest depth normal so far. otherwise normalR is 0 and normalC is
+  // set to a vector relative to body 1. invert_normal is 1 if the sign of
+  // the normal should be flipped.
+
+#define TST(expr1,expr2,norm,cc) \
+  s2 = btFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  if (s2 > s) { \
+    s = s2; \
+    normalR = norm; \
+    invert_normal = ((expr1) < 0); \
+    code = (cc); \
+  }
+
+  s = -dInfinity;
+  invert_normal = 0;
+  code = 0;
+
+  // separating axis = u1,u2,u3
+  TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
+  TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
+  TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
+
+  // separating axis = v1,v2,v3
+  TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
+  TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
+  TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
+
+  // note: cross product axes need to be scaled when s is computed.
+  // normal (n1,n2,n3) is relative to box 1.
+#undef TST
+#define TST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = btFabs(expr1) - (expr2); \
+  if (s2 > SIMD_EPSILON) return 0; \
+  l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+  if (l > SIMD_EPSILON) { \
+    s2 /= l; \
+    if (s2*fudge_factor > s) { \
+      s = s2; \
+      normalR = 0; \
+      normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+      invert_normal = ((expr1) < 0); \
+      code = (cc); \
+    } \
+  }
+
+  btScalar fudge2 (1.0e-5f);
+
+  Q11 += fudge2;
+  Q12 += fudge2;
+  Q13 += fudge2;
+
+  Q21 += fudge2;
+  Q22 += fudge2;
+  Q23 += fudge2;
+
+  Q31 += fudge2;
+  Q32 += fudge2;
+  Q33 += fudge2;
+
+  // separating axis = u1 x (v1,v2,v3)
+  TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
+  TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
+  TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
+
+  // separating axis = u2 x (v1,v2,v3)
+  TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
+  TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
+  TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
+
+  // separating axis = u3 x (v1,v2,v3)
+  TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
+  TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
+  TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
+
+#undef TST
+
+  if (!code) return 0;
+
+  // if we get to this point, the boxes interpenetrate. compute the normal
+  // in global coordinates.
+  if (normalR) {
+    normal[0] = normalR[0];
+    normal[1] = normalR[4];
+    normal[2] = normalR[8];
+  }
+  else {
+    dMULTIPLY0_331 (normal,R1,normalC);
+  }
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+  *depth = -s;
+
+  // compute contact point(s)
+
+  if (code > 6) {
+    // an edge from box 1 touches an edge from box 2.
+    // find a point pa on the intersecting edge of box 1
+    btVector3 pa;
+    btScalar sign;
+    for (i=0; i<3; i++) pa[i] = p1[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
+      for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
+    }
+
+    // find a point pb on the intersecting edge of box 2
+    btVector3 pb;
+    for (i=0; i<3; i++) pb[i] = p2[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+      for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+    }
+
+    btScalar alpha,beta;
+    btVector3 ua,ub;
+    for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
+    for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
+
+    dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
+    for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
+    for (i=0; i<3; i++) pb[i] += ub[i]*beta;
+
+	{
+		
+		//contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+		//contact[0].depth = *depth;
+		btVector3 pointInWorld;
+
+#ifdef USE_CENTER_POINT
+	    for (i=0; i<3; i++) 
+			pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
+		output.addContactPoint(-normal,pointInWorld,-*depth);
+#else
+		output.addContactPoint(-normal,pb,-*depth);
+
+#endif //
+		*return_code = code;
+	}
+    return 1;
+  }
+
+  // okay, we have a face-something intersection (because the separating
+  // axis is perpendicular to a face). define face 'a' to be the reference
+  // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
+  // the incident face (the closest face of the other box).
+
+  const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
+  if (code <= 3) {
+    Ra = R1;
+    Rb = R2;
+    pa = p1;
+    pb = p2;
+    Sa = A;
+    Sb = B;
+  }
+  else {
+    Ra = R2;
+    Rb = R1;
+    pa = p2;
+    pb = p1;
+    Sa = B;
+    Sb = A;
+  }
+
+  // nr = normal vector of reference face dotted with axes of incident box.
+  // anr = absolute values of nr.
+  btVector3 normal2,nr,anr;
+  if (code <= 3) {
+    normal2[0] = normal[0];
+    normal2[1] = normal[1];
+    normal2[2] = normal[2];
+  }
+  else {
+    normal2[0] = -normal[0];
+    normal2[1] = -normal[1];
+    normal2[2] = -normal[2];
+  }
+  dMULTIPLY1_331 (nr,Rb,normal2);
+  anr[0] = btFabs (nr[0]);
+  anr[1] = btFabs (nr[1]);
+  anr[2] = btFabs (nr[2]);
+
+  // find the largest compontent of anr: this corresponds to the normal
+  // for the indident face. the other axis numbers of the indicent face
+  // are stored in a1,a2.
+  int lanr,a1,a2;
+  if (anr[1] > anr[0]) {
+    if (anr[1] > anr[2]) {
+      a1 = 0;
+      lanr = 1;
+      a2 = 2;
+    }
+    else {
+      a1 = 0;
+      a2 = 1;
+      lanr = 2;
+    }
+  }
+  else {
+    if (anr[0] > anr[2]) {
+      lanr = 0;
+      a1 = 1;
+      a2 = 2;
+    }
+    else {
+      a1 = 0;
+      a2 = 1;
+      lanr = 2;
+    }
+  }
+
+  // compute center point of incident face, in reference-face coordinates
+  btVector3 center;
+  if (nr[lanr] < 0) {
+    for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
+  }
+  else {
+    for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
+  }
+
+  // find the normal and non-normal axis numbers of the reference box
+  int codeN,code1,code2;
+  if (code <= 3) codeN = code-1; else codeN = code-4;
+  if (codeN==0) {
+    code1 = 1;
+    code2 = 2;
+  }
+  else if (codeN==1) {
+    code1 = 0;
+    code2 = 2;
+  }
+  else {
+    code1 = 0;
+    code2 = 1;
+  }
+
+  // find the four corners of the incident face, in reference-face coordinates
+  btScalar quad[8];	// 2D coordinate of incident face (x,y pairs)
+  btScalar c1,c2,m11,m12,m21,m22;
+  c1 = dDOT14 (center,Ra+code1);
+  c2 = dDOT14 (center,Ra+code2);
+  // optimize this? - we have already computed this data above, but it is not
+  // stored in an easy-to-index format. for now it's quicker just to recompute
+  // the four dot products.
+  m11 = dDOT44 (Ra+code1,Rb+a1);
+  m12 = dDOT44 (Ra+code1,Rb+a2);
+  m21 = dDOT44 (Ra+code2,Rb+a1);
+  m22 = dDOT44 (Ra+code2,Rb+a2);
+  {
+    btScalar k1 = m11*Sb[a1];
+    btScalar k2 = m21*Sb[a1];
+    btScalar k3 = m12*Sb[a2];
+    btScalar k4 = m22*Sb[a2];
+    quad[0] = c1 - k1 - k3;
+    quad[1] = c2 - k2 - k4;
+    quad[2] = c1 - k1 + k3;
+    quad[3] = c2 - k2 + k4;
+    quad[4] = c1 + k1 + k3;
+    quad[5] = c2 + k2 + k4;
+    quad[6] = c1 + k1 - k3;
+    quad[7] = c2 + k2 - k4;
+  }
+
+  // find the size of the reference face
+  btScalar rect[2];
+  rect[0] = Sa[code1];
+  rect[1] = Sa[code2];
+
+  // intersect the incident and reference faces
+  btScalar ret[16];
+  int n = intersectRectQuad2 (rect,quad,ret);
+  if (n < 1) return 0;		// this should never happen
+
+  // convert the intersection points into reference-face coordinates,
+  // and compute the contact position and depth for each point. only keep
+  // those points that have a positive (penetrating) depth. delete points in
+  // the 'ret' array as necessary so that 'point' and 'ret' correspond.
+  btScalar point[3*8];		// penetrating contact points
+  btScalar dep[8];			// depths for those points
+  btScalar det1 = 1.f/(m11*m22 - m12*m21);
+  m11 *= det1;
+  m12 *= det1;
+  m21 *= det1;
+  m22 *= det1;
+  int cnum = 0;			// number of penetrating contact points found
+  for (j=0; j < n; j++) {
+    btScalar k1 =  m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+    btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
+    for (i=0; i<3; i++) point[cnum*3+i] =
+			  center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
+    dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
+    if (dep[cnum] >= 0) {
+      ret[cnum*2] = ret[j*2];
+      ret[cnum*2+1] = ret[j*2+1];
+      cnum++;
+    }
+  }
+  if (cnum < 1) return 0;	// this should never happen
+
+  // we can't generate more contacts than we actually have
+  if (maxc > cnum) maxc = cnum;
+  if (maxc < 1) maxc = 1;
+
+  if (cnum <= maxc) {
+
+	  if (code<4) 
+	  {
+    // we have less contacts than we need, so we use them all
+    for (j=0; j < cnum; j++) 
+	{
+		btVector3 pointInWorld;
+		for (i=0; i<3; i++) 
+			pointInWorld[i] = point[j*3+i] + pa[i];
+		output.addContactPoint(-normal,pointInWorld,-dep[j]);
+
+    }
+	  } else
+	  {
+		  // we have less contacts than we need, so we use them all
+		for (j=0; j < cnum; j++) 
+		{
+			btVector3 pointInWorld;
+			for (i=0; i<3; i++) 
+				pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j];
+				//pointInWorld[i] = point[j*3+i] + pa[i];
+			output.addContactPoint(-normal,pointInWorld,-dep[j]);
+		}
+	  }
+  }
+  else {
+    // we have more contacts than are wanted, some of them must be culled.
+    // find the deepest point, it is always the first contact.
+    int i1 = 0;
+    btScalar maxdepth = dep[0];
+    for (i=1; i<cnum; i++) {
+      if (dep[i] > maxdepth) {
+	maxdepth = dep[i];
+	i1 = i;
+      }
+    }
+
+    int iret[8];
+    cullPoints2 (cnum,ret,maxc,i1,iret);
+
+    for (j=0; j < maxc; j++) {
+//      dContactGeom *con = CONTACT(contact,skip*j);
+  //    for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
+    //  con->depth = dep[iret[j]];
+
+		btVector3 posInWorld;
+		for (i=0; i<3; i++) 
+			posInWorld[i] = point[iret[j]*3+i] + pa[i];
+		if (code<4) 
+	   {
+			output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
+		} else
+		{
+			output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]);
+		}
+    }
+    cnum = maxc;
+  }
+
+  *return_code = code;
+  return cnum;
+}
+
+void	btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+{
+	
+	const btTransform& transformA = input.m_transformA;
+	const btTransform& transformB = input.m_transformB;
+	
+	int skip = 0;
+	dContactGeom *contact = 0;
+
+	dMatrix3 R1;
+	dMatrix3 R2;
+
+	for (int j=0;j<3;j++)
+	{
+		R1[0+4*j] = transformA.getBasis()[j].x();
+		R2[0+4*j] = transformB.getBasis()[j].x();
+
+		R1[1+4*j] = transformA.getBasis()[j].y();
+		R2[1+4*j] = transformB.getBasis()[j].y();
+
+
+		R1[2+4*j] = transformA.getBasis()[j].z();
+		R2[2+4*j] = transformB.getBasis()[j].z();
+
+	}
+
+	
+
+	btVector3 normal;
+	btScalar depth;
+	int return_code;
+	int maxc = 4;
+
+
+	dBoxBox2 (transformA.getOrigin(), 
+	R1,
+	2.f*m_box1->getHalfExtentsWithMargin(),
+	transformB.getOrigin(),
+	R2, 
+	2.f*m_box2->getHalfExtentsWithMargin(),
+	normal, &depth, &return_code,
+	maxc, contact, skip,
+	output
+	);
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h	(revision 11817)
@@ -0,0 +1,44 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved.  Email: russ@q12.org   Web: www.q12.org
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_BOX_BOX_DETECTOR_H
+#define BT_BOX_BOX_DETECTOR_H
+
+
+class btBoxShape;
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+/// btBoxBoxDetector wraps the ODE box-box collision detector
+/// re-distributed under the Zlib license with permission from Russell L. Smith
+struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
+{
+	btBoxShape* m_box1;
+	btBoxShape* m_box2;
+
+public:
+
+	btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
+
+	virtual ~btBoxBoxDetector() {};
+
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+};
+
+#endif //BT_BOX_BOX_DETECTOR_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h	(revision 11817)
@@ -0,0 +1,48 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_CONFIGURATION
+#define BT_COLLISION_CONFIGURATION
+
+struct btCollisionAlgorithmCreateFunc;
+
+class btStackAlloc;
+class btPoolAllocator;
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator size, default collision algorithms and persistent manifold pool size
+///@todo: describe the meaning
+class	btCollisionConfiguration
+{
+
+public:
+
+	virtual ~btCollisionConfiguration()
+	{
+	}
+
+	///memory pools
+	virtual btPoolAllocator* getPersistentManifoldPool() = 0;
+
+	virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
+
+	virtual btStackAlloc*	getStackAllocator() = 0;
+
+	virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+
+};
+
+#endif //BT_COLLISION_CONFIGURATION
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h	(revision 11817)
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_CREATE_FUNC
+#define BT_COLLISION_CREATE_FUNC
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btCollisionAlgorithm;
+class btCollisionObject;
+
+struct btCollisionAlgorithmConstructionInfo;
+
+///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
+struct btCollisionAlgorithmCreateFunc
+{
+	bool m_swapped;
+	
+	btCollisionAlgorithmCreateFunc()
+		:m_swapped(false)
+	{
+	}
+	virtual ~btCollisionAlgorithmCreateFunc(){};
+
+	virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1)
+	{
+		
+		(void)body0;
+		(void)body1;
+		return 0;
+	}
+};
+#endif //BT_COLLISION_CREATE_FUNC
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp	(revision 11817)
@@ -0,0 +1,310 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btCollisionDispatcher.h"
+
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+
+int gNumManifold = 0;
+
+#ifdef BT_DEBUG
+#include <stdio.h>
+#endif
+
+
+btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): 
+m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
+	m_collisionConfiguration(collisionConfiguration)
+{
+	int i;
+
+	setNearCallback(defaultNearCallback);
+	
+	m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
+
+	m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
+
+	for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
+	{
+		for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
+		{
+			m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
+			btAssert(m_doubleDispatch[i][j]);
+		}
+	}
+	
+	
+}
+
+
+void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
+{
+	m_doubleDispatch[proxyType0][proxyType1] = createFunc;
+}
+
+btCollisionDispatcher::~btCollisionDispatcher()
+{
+}
+
+btPersistentManifold*	btCollisionDispatcher::getNewManifold(void* b0,void* b1) 
+{ 
+	gNumManifold++;
+	
+	//btAssert(gNumManifold < 65535);
+	
+
+	btCollisionObject* body0 = (btCollisionObject*)b0;
+	btCollisionObject* body1 = (btCollisionObject*)b1;
+
+	//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+	
+	btScalar contactBreakingThreshold =  (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? 
+		btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+		: gContactBreakingThreshold ;
+
+	btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
+		
+	void* mem = 0;
+	
+	if (m_persistentManifoldPoolAllocator->getFreeCount())
+	{
+		mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+	} else
+	{
+		//we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
+		if ((m_dispatcherFlags&CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION)==0)
+		{
+			mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
+		} else
+		{
+			btAssert(0);
+			//make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
+			return 0;
+		}
+	}
+	btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
+	manifold->m_index1a = m_manifoldsPtr.size();
+	m_manifoldsPtr.push_back(manifold);
+
+	return manifold;
+}
+
+void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
+{
+	manifold->clearManifold();
+}
+
+	
+void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
+{
+	
+	gNumManifold--;
+
+	//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
+	clearManifold(manifold);
+
+	int findIndex = manifold->m_index1a;
+	btAssert(findIndex < m_manifoldsPtr.size());
+	m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
+	m_manifoldsPtr[findIndex]->m_index1a = findIndex;
+	m_manifoldsPtr.pop_back();
+
+	manifold->~btPersistentManifold();
+	if (m_persistentManifoldPoolAllocator->validPtr(manifold))
+	{
+		m_persistentManifoldPoolAllocator->freeMemory(manifold);
+	} else
+	{
+		btAlignedFree(manifold);
+	}
+	
+}
+
+	
+
+btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
+{
+	
+	btCollisionAlgorithmConstructionInfo ci;
+
+	ci.m_dispatcher1 = this;
+	ci.m_manifold = sharedManifold;
+	btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
+
+	return algo;
+}
+
+
+
+
+bool	btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
+{
+	//here you can do filtering
+	bool hasResponse = 
+		(body0->hasContactResponse() && body1->hasContactResponse());
+	//no response between two static/kinematic bodies:
+	hasResponse = hasResponse &&
+		((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
+	return hasResponse;
+}
+
+bool	btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
+{
+	btAssert(body0);
+	btAssert(body1);
+
+	bool needsCollision = true;
+
+#ifdef BT_DEBUG
+	if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
+	{
+		//broadphase filtering already deals with this
+		if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
+		{
+			m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
+			printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+		}
+	}
+#endif //BT_DEBUG
+
+	if ((!body0->isActive()) && (!body1->isActive()))
+		needsCollision = false;
+	else if (!body0->checkCollideWith(body1))
+		needsCollision = false;
+	
+	return needsCollision ;
+
+}
+
+
+
+///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
+///this is useful for the collision dispatcher.
+class btCollisionPairCallback : public btOverlapCallback
+{
+	const btDispatcherInfo& m_dispatchInfo;
+	btCollisionDispatcher*	m_dispatcher;
+
+public:
+
+	btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher*	dispatcher)
+	:m_dispatchInfo(dispatchInfo),
+	m_dispatcher(dispatcher)
+	{
+	}
+
+	/*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
+	{
+		m_dispatchInfo = other.m_dispatchInfo;
+		m_dispatcher = other.m_dispatcher;
+		return *this;
+	}
+	*/
+
+
+	virtual ~btCollisionPairCallback() {}
+
+
+	virtual bool	processOverlap(btBroadphasePair& pair)
+	{
+		(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
+
+		return false;
+	}
+};
+
+
+
+void	btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) 
+{
+	//m_blockedForChanges = true;
+
+	btCollisionPairCallback	collisionCallback(dispatchInfo,this);
+
+	pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
+
+	//m_blockedForChanges = false;
+
+}
+
+
+
+
+//by default, Bullet will use this near callback
+void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
+{
+		btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+		btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+		if (dispatcher.needsCollision(colObj0,colObj1))
+		{
+			//dispatcher will keep algorithms persistent in the collision pair
+			if (!collisionPair.m_algorithm)
+			{
+				collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
+			}
+
+			if (collisionPair.m_algorithm)
+			{
+				btManifoldResult contactPointResult(colObj0,colObj1);
+				
+				if (dispatchInfo.m_dispatchFunc == 		btDispatcherInfo::DISPATCH_DISCRETE)
+				{
+					//discrete collision detection query
+					collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
+				} else
+				{
+					//continuous collision detection query, time of impact (toi)
+					btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
+					if (dispatchInfo.m_timeOfImpact > toi)
+						dispatchInfo.m_timeOfImpact = toi;
+
+				}
+			}
+		}
+
+}
+
+
+void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
+{
+	if (m_collisionAlgorithmPoolAllocator->getFreeCount())
+	{
+		return m_collisionAlgorithmPoolAllocator->allocate(size);
+	}
+	
+	//warn user for overflow?
+	return	btAlignedAlloc(static_cast<size_t>(size), 16);
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+	if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+	{
+		m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
+	} else
+	{
+		btAlignedFree(ptr);
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h	(revision 11817)
@@ -0,0 +1,173 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION__DISPATCHER_H
+#define BT_COLLISION__DISPATCHER_H
+
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+class btIDebugDraw;
+class btOverlappingPairCache;
+class btPoolAllocator;
+class btCollisionConfiguration;
+
+#include "btCollisionCreateFunc.h"
+
+#define USE_DISPATCH_REGISTRY_ARRAY 1
+
+class btCollisionDispatcher;
+///user can override this nearcallback for collision filtering and more finegrained control over collision detection
+typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+
+///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
+///Time of Impact, Closest Points and Penetration Depth.
+class btCollisionDispatcher : public btDispatcher
+{
+
+protected:
+
+	int		m_dispatcherFlags;
+
+	btAlignedObjectArray<btPersistentManifold*>	m_manifoldsPtr;
+
+	btManifoldResult	m_defaultManifoldResult;
+
+	btNearCallback		m_nearCallback;
+	
+	btPoolAllocator*	m_collisionAlgorithmPoolAllocator;
+
+	btPoolAllocator*	m_persistentManifoldPoolAllocator;
+
+	btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
+
+	btCollisionConfiguration*	m_collisionConfiguration;
+
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	enum DispatcherFlags
+	{
+		CD_STATIC_STATIC_REPORTED = 1,
+		CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2,
+		CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
+	};
+
+	int	getDispatcherFlags() const
+	{
+		return m_dispatcherFlags;
+	}
+
+	void	setDispatcherFlags(int flags)
+	{
+		m_dispatcherFlags = flags;
+	}
+
+	///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
+	void	registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
+
+	int	getNumManifolds() const
+	{ 
+		return int( m_manifoldsPtr.size());
+	}
+
+	btPersistentManifold**	getInternalManifoldPointer()
+	{
+		return &m_manifoldsPtr[0];
+	}
+
+	 btPersistentManifold* getManifoldByIndexInternal(int index)
+	{
+		return m_manifoldsPtr[index];
+	}
+
+	 const btPersistentManifold* getManifoldByIndexInternal(int index) const
+	{
+		return m_manifoldsPtr[index];
+	}
+
+	btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
+
+	virtual ~btCollisionDispatcher();
+
+	virtual btPersistentManifold*	getNewManifold(void* b0,void* b1);
+	
+	virtual void releaseManifold(btPersistentManifold* manifold);
+
+
+	virtual void clearManifold(btPersistentManifold* manifold);
+
+			
+	btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
+		
+	virtual bool	needsCollision(btCollisionObject* body0,btCollisionObject* body1);
+	
+	virtual bool	needsResponse(btCollisionObject* body0,btCollisionObject* body1);
+	
+	virtual void	dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
+
+	void	setNearCallback(btNearCallback	nearCallback)
+	{
+		m_nearCallback = nearCallback; 
+	}
+
+	btNearCallback	getNearCallback() const
+	{
+		return m_nearCallback;
+	}
+
+	//by default, Bullet will use this near callback
+	static void  defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+	virtual	void* allocateCollisionAlgorithm(int size);
+
+	virtual	void freeCollisionAlgorithm(void* ptr);
+
+	btCollisionConfiguration*	getCollisionConfiguration()
+	{
+		return m_collisionConfiguration;
+	}
+
+	const btCollisionConfiguration*	getCollisionConfiguration() const
+	{
+		return m_collisionConfiguration;
+	}
+
+	void	setCollisionConfiguration(btCollisionConfiguration* config)
+	{
+		m_collisionConfiguration = config;
+	}
+
+	virtual	btPoolAllocator*	getInternalManifoldPool()
+	{
+		return m_persistentManifoldPoolAllocator;
+	}
+
+	virtual	const btPoolAllocator*	getInternalManifoldPool() const
+	{
+		return m_persistentManifoldPoolAllocator;
+	}
+
+};
+
+#endif //BT_COLLISION__DISPATCHER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btCollisionObject.h"
+#include "LinearMath/btSerializer.h"
+
+btCollisionObject::btCollisionObject()
+	:	m_anisotropicFriction(1.f,1.f,1.f),
+	m_hasAnisotropicFriction(false),
+	m_contactProcessingThreshold(BT_LARGE_FLOAT),
+		m_broadphaseHandle(0),
+		m_collisionShape(0),
+		m_extensionPointer(0),
+		m_rootCollisionShape(0),
+		m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+		m_islandTag1(-1),
+		m_companionId(-1),
+		m_activationState1(1),
+		m_deactivationTime(btScalar(0.)),
+		m_friction(btScalar(0.5)),
+		m_restitution(btScalar(0.)),
+		m_internalType(CO_COLLISION_OBJECT),
+		m_userObjectPointer(0),
+		m_hitFraction(btScalar(1.)),
+		m_ccdSweptSphereRadius(btScalar(0.)),
+		m_ccdMotionThreshold(btScalar(0.)),
+		m_checkCollideWith(false)
+{
+	m_worldTransform.setIdentity();
+}
+
+btCollisionObject::~btCollisionObject()
+{
+}
+
+void btCollisionObject::setActivationState(int newState) 
+{ 
+	if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
+		m_activationState1 = newState;
+}
+
+void btCollisionObject::forceActivationState(int newState)
+{
+	m_activationState1 = newState;
+}
+
+void btCollisionObject::activate(bool forceActivation)
+{
+	if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
+	{
+		setActivationState(ACTIVE_TAG);
+		m_deactivationTime = btScalar(0.);
+	}
+}
+
+const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+	btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
+
+	m_worldTransform.serialize(dataOut->m_worldTransform);
+	m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform);
+	m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity);
+	m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity);
+	m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction);
+	dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction;
+	dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
+	dataOut->m_broadphaseHandle = 0;
+	dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
+	dataOut->m_rootCollisionShape = 0;//@todo
+	dataOut->m_collisionFlags = m_collisionFlags;
+	dataOut->m_islandTag1 = m_islandTag1;
+	dataOut->m_companionId = m_companionId;
+	dataOut->m_activationState1 = m_activationState1;
+	dataOut->m_activationState1 = m_activationState1;
+	dataOut->m_deactivationTime = m_deactivationTime;
+	dataOut->m_friction = m_friction;
+	dataOut->m_restitution = m_restitution;
+	dataOut->m_internalType = m_internalType;
+	
+	char* name = (char*) serializer->findNameForPointer(this);
+	dataOut->m_name = (char*)serializer->getUniquePointer(name);
+	if (dataOut->m_name)
+	{
+		serializer->serializeName(name);
+	}
+	dataOut->m_hitFraction = m_hitFraction;
+	dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
+	dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
+	dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
+	dataOut->m_checkCollideWith = m_checkCollideWith;
+
+	return btCollisionObjectDataName;
+}
+
+
+void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
+{
+	int len = calculateSerializeBufferSize();
+	btChunk* chunk = serializer->allocate(len,1);
+	const char* structType = serialize(chunk->m_oldPtr, serializer);
+	serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h	(revision 11817)
@@ -0,0 +1,524 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_OBJECT_H
+#define BT_COLLISION_OBJECT_H
+
+#include "LinearMath/btTransform.h"
+
+//island management, m_activationState1
+#define ACTIVE_TAG 1
+#define ISLAND_SLEEPING 2
+#define WANTS_DEACTIVATION 3
+#define DISABLE_DEACTIVATION 4
+#define DISABLE_SIMULATION 5
+
+struct	btBroadphaseProxy;
+class	btCollisionShape;
+struct btCollisionShapeData;
+#include "LinearMath/btMotionState.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btCollisionObjectData btCollisionObjectDoubleData
+#define btCollisionObjectDataName "btCollisionObjectDoubleData"
+#else
+#define btCollisionObjectData btCollisionObjectFloatData
+#define btCollisionObjectDataName "btCollisionObjectFloatData"
+#endif
+
+
+/// btCollisionObject can be used to manage collision detection objects. 
+/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
+/// They can be added to the btCollisionWorld.
+ATTRIBUTE_ALIGNED16(class)	btCollisionObject
+{
+
+protected:
+
+	btTransform	m_worldTransform;
+
+	///m_interpolationWorldTransform is used for CCD and interpolation
+	///it can be either previous or future (predicted) transform
+	btTransform	m_interpolationWorldTransform;
+	//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) 
+	//without destroying the continuous interpolated motion (which uses this interpolation velocities)
+	btVector3	m_interpolationLinearVelocity;
+	btVector3	m_interpolationAngularVelocity;
+	
+	btVector3	m_anisotropicFriction;
+	int			m_hasAnisotropicFriction;
+	btScalar	m_contactProcessingThreshold;	
+
+	btBroadphaseProxy*		m_broadphaseHandle;
+	btCollisionShape*		m_collisionShape;
+	///m_extensionPointer is used by some internal low-level Bullet extensions.
+	void*					m_extensionPointer;
+	
+	///m_rootCollisionShape is temporarily used to store the original collision shape
+	///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
+	///If it is NULL, the m_collisionShape is not temporarily replaced.
+	btCollisionShape*		m_rootCollisionShape;
+
+	int				m_collisionFlags;
+
+	int				m_islandTag1;
+	int				m_companionId;
+
+	int				m_activationState1;
+	btScalar			m_deactivationTime;
+
+	btScalar		m_friction;
+	btScalar		m_restitution;
+
+	///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
+	///do not assign your own m_internalType unless you write a new dynamics object class.
+	int				m_internalType;
+
+	///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
+	void*			m_userObjectPointer;
+
+	///time of impact calculation
+	btScalar		m_hitFraction; 
+	
+	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+	btScalar		m_ccdSweptSphereRadius;
+
+	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+	btScalar		m_ccdMotionThreshold;
+	
+	/// If some object should have elaborate collision filtering by sub-classes
+	int			m_checkCollideWith;
+
+	virtual bool	checkCollideWithOverride(btCollisionObject* /* co */)
+	{
+		return true;
+	}
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	enum CollisionFlags
+	{
+		CF_STATIC_OBJECT= 1,
+		CF_KINEMATIC_OBJECT= 2,
+		CF_NO_CONTACT_RESPONSE = 4,
+		CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
+		CF_CHARACTER_OBJECT = 16,
+		CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
+		CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing
+	};
+
+	enum	CollisionObjectTypes
+	{
+		CO_COLLISION_OBJECT =1,
+		CO_RIGID_BODY=2,
+		///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
+		///It is useful for collision sensors, explosion objects, character controller etc.
+		CO_GHOST_OBJECT=4,
+		CO_SOFT_BODY=8,
+		CO_HF_FLUID=16,
+		CO_USER_TYPE=32
+	};
+
+	SIMD_FORCE_INLINE bool mergesSimulationIslands() const
+	{
+		///static objects, kinematic and object without contact response don't merge islands
+		return  ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
+	}
+
+	const btVector3& getAnisotropicFriction() const
+	{
+		return m_anisotropicFriction;
+	}
+	void	setAnisotropicFriction(const btVector3& anisotropicFriction)
+	{
+		m_anisotropicFriction = anisotropicFriction;
+		m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
+	}
+	bool	hasAnisotropicFriction() const
+	{
+		return m_hasAnisotropicFriction!=0;
+	}
+
+	///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
+	///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
+	void	setContactProcessingThreshold( btScalar contactProcessingThreshold)
+	{
+		m_contactProcessingThreshold = contactProcessingThreshold;
+	}
+	btScalar	getContactProcessingThreshold() const
+	{
+		return m_contactProcessingThreshold;
+	}
+
+	SIMD_FORCE_INLINE bool		isStaticObject() const {
+		return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
+	}
+
+	SIMD_FORCE_INLINE bool		isKinematicObject() const
+	{
+		return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
+	}
+
+	SIMD_FORCE_INLINE bool		isStaticOrKinematicObject() const
+	{
+		return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
+	}
+
+	SIMD_FORCE_INLINE bool		hasContactResponse() const {
+		return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
+	}
+
+	
+	btCollisionObject();
+
+	virtual ~btCollisionObject();
+
+	virtual void	setCollisionShape(btCollisionShape* collisionShape)
+	{
+		m_collisionShape = collisionShape;
+		m_rootCollisionShape = collisionShape;
+	}
+
+	SIMD_FORCE_INLINE const btCollisionShape*	getCollisionShape() const
+	{
+		return m_collisionShape;
+	}
+
+	SIMD_FORCE_INLINE btCollisionShape*	getCollisionShape()
+	{
+		return m_collisionShape;
+	}
+
+	SIMD_FORCE_INLINE const btCollisionShape*	getRootCollisionShape() const
+	{
+		return m_rootCollisionShape;
+	}
+
+	SIMD_FORCE_INLINE btCollisionShape*	getRootCollisionShape()
+	{
+		return m_rootCollisionShape;
+	}
+
+	///Avoid using this internal API call
+	///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape.
+	void	internalSetTemporaryCollisionShape(btCollisionShape* collisionShape)
+	{
+		m_collisionShape = collisionShape;
+	}
+
+	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions. 
+	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+	void*		internalGetExtensionPointer() const
+	{
+		return m_extensionPointer;
+	}
+	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
+	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+	void	internalSetExtensionPointer(void* pointer)
+	{
+		m_extensionPointer = pointer;
+	}
+
+	SIMD_FORCE_INLINE	int	getActivationState() const { return m_activationState1;}
+	
+	void setActivationState(int newState);
+
+	void	setDeactivationTime(btScalar time)
+	{
+		m_deactivationTime = time;
+	}
+	btScalar	getDeactivationTime() const
+	{
+		return m_deactivationTime;
+	}
+
+	void forceActivationState(int newState);
+
+	void	activate(bool forceActivation = false);
+
+	SIMD_FORCE_INLINE bool isActive() const
+	{
+		return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
+	}
+
+	void	setRestitution(btScalar rest)
+	{
+		m_restitution = rest;
+	}
+	btScalar	getRestitution() const
+	{
+		return m_restitution;
+	}
+	void	setFriction(btScalar frict)
+	{
+		m_friction = frict;
+	}
+	btScalar	getFriction() const
+	{
+		return m_friction;
+	}
+
+	///reserved for Bullet internal usage
+	int	getInternalType() const
+	{
+		return m_internalType;
+	}
+
+	btTransform&	getWorldTransform()
+	{
+		return m_worldTransform;
+	}
+
+	const btTransform&	getWorldTransform() const
+	{
+		return m_worldTransform;
+	}
+
+	void	setWorldTransform(const btTransform& worldTrans)
+	{
+		m_worldTransform = worldTrans;
+	}
+
+
+	SIMD_FORCE_INLINE btBroadphaseProxy*	getBroadphaseHandle()
+	{
+		return m_broadphaseHandle;
+	}
+
+	SIMD_FORCE_INLINE const btBroadphaseProxy*	getBroadphaseHandle() const
+	{
+		return m_broadphaseHandle;
+	}
+
+	void	setBroadphaseHandle(btBroadphaseProxy* handle)
+	{
+		m_broadphaseHandle = handle;
+	}
+
+
+	const btTransform&	getInterpolationWorldTransform() const
+	{
+		return m_interpolationWorldTransform;
+	}
+
+	btTransform&	getInterpolationWorldTransform()
+	{
+		return m_interpolationWorldTransform;
+	}
+
+	void	setInterpolationWorldTransform(const btTransform&	trans)
+	{
+		m_interpolationWorldTransform = trans;
+	}
+
+	void	setInterpolationLinearVelocity(const btVector3& linvel)
+	{
+		m_interpolationLinearVelocity = linvel;
+	}
+
+	void	setInterpolationAngularVelocity(const btVector3& angvel)
+	{
+		m_interpolationAngularVelocity = angvel;
+	}
+
+	const btVector3&	getInterpolationLinearVelocity() const
+	{
+		return m_interpolationLinearVelocity;
+	}
+
+	const btVector3&	getInterpolationAngularVelocity() const
+	{
+		return m_interpolationAngularVelocity;
+	}
+
+	SIMD_FORCE_INLINE int getIslandTag() const
+	{
+		return	m_islandTag1;
+	}
+
+	void	setIslandTag(int tag)
+	{
+		m_islandTag1 = tag;
+	}
+
+	SIMD_FORCE_INLINE int getCompanionId() const
+	{
+		return	m_companionId;
+	}
+
+	void	setCompanionId(int id)
+	{
+		m_companionId = id;
+	}
+
+	SIMD_FORCE_INLINE btScalar			getHitFraction() const
+	{
+		return m_hitFraction; 
+	}
+
+	void	setHitFraction(btScalar hitFraction)
+	{
+		m_hitFraction = hitFraction;
+	}
+
+	
+	SIMD_FORCE_INLINE int	getCollisionFlags() const
+	{
+		return m_collisionFlags;
+	}
+
+	void	setCollisionFlags(int flags)
+	{
+		m_collisionFlags = flags;
+	}
+	
+	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+	btScalar			getCcdSweptSphereRadius() const
+	{
+		return m_ccdSweptSphereRadius;
+	}
+
+	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+	void	setCcdSweptSphereRadius(btScalar radius)
+	{
+		m_ccdSweptSphereRadius = radius;
+	}
+
+	btScalar 	getCcdMotionThreshold() const
+	{
+		return m_ccdMotionThreshold;
+	}
+
+	btScalar 	getCcdSquareMotionThreshold() const
+	{
+		return m_ccdMotionThreshold*m_ccdMotionThreshold;
+	}
+
+
+
+	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+	void	setCcdMotionThreshold(btScalar ccdMotionThreshold)
+	{
+		m_ccdMotionThreshold = ccdMotionThreshold;
+	}
+
+	///users can point to their objects, userPointer is not used by Bullet
+	void*	getUserPointer() const
+	{
+		return m_userObjectPointer;
+	}
+	
+	///users can point to their objects, userPointer is not used by Bullet
+	void	setUserPointer(void* userPointer)
+	{
+		m_userObjectPointer = userPointer;
+	}
+
+
+	inline bool checkCollideWith(btCollisionObject* co)
+	{
+		if (m_checkCollideWith)
+			return checkCollideWithOverride(co);
+
+		return true;
+	}
+
+	virtual	int	calculateSerializeBufferSize()	const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, class btSerializer* serializer) const;
+
+	virtual void serializeSingleObject(class btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCollisionObjectDoubleData
+{
+	void					*m_broadphaseHandle;
+	void					*m_collisionShape;
+	btCollisionShapeData	*m_rootCollisionShape;
+	char					*m_name;
+
+	btTransformDoubleData	m_worldTransform;
+	btTransformDoubleData	m_interpolationWorldTransform;
+	btVector3DoubleData		m_interpolationLinearVelocity;
+	btVector3DoubleData		m_interpolationAngularVelocity;
+	btVector3DoubleData		m_anisotropicFriction;
+	double					m_contactProcessingThreshold;	
+	double					m_deactivationTime;
+	double					m_friction;
+	double					m_restitution;
+	double					m_hitFraction; 
+	double					m_ccdSweptSphereRadius;
+	double					m_ccdMotionThreshold;
+
+	int						m_hasAnisotropicFriction;
+	int						m_collisionFlags;
+	int						m_islandTag1;
+	int						m_companionId;
+	int						m_activationState1;
+	int						m_internalType;
+	int						m_checkCollideWith;
+
+	char	m_padding[4];
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCollisionObjectFloatData
+{
+	void					*m_broadphaseHandle;
+	void					*m_collisionShape;
+	btCollisionShapeData	*m_rootCollisionShape;
+	char					*m_name;
+
+	btTransformFloatData	m_worldTransform;
+	btTransformFloatData	m_interpolationWorldTransform;
+	btVector3FloatData		m_interpolationLinearVelocity;
+	btVector3FloatData		m_interpolationAngularVelocity;
+	btVector3FloatData		m_anisotropicFriction;
+	float					m_contactProcessingThreshold;	
+	float					m_deactivationTime;
+	float					m_friction;
+	float					m_restitution;
+	float					m_hitFraction; 
+	float					m_ccdSweptSphereRadius;
+	float					m_ccdMotionThreshold;
+
+	int						m_hasAnisotropicFriction;
+	int						m_collisionFlags;
+	int						m_islandTag1;
+	int						m_companionId;
+	int						m_activationState1;
+	int						m_internalType;
+	int						m_checkCollideWith;
+};
+
+
+
+SIMD_FORCE_INLINE	int	btCollisionObject::calculateSerializeBufferSize() const
+{
+	return sizeof(btCollisionObjectData);
+}
+
+
+
+#endif //BT_COLLISION_OBJECT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp	(revision 11817)
@@ -0,0 +1,1513 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionWorld.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btSerializer.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+
+//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+
+
+//#define USE_BRUTEFORCE_RAYBROADPHASE 1
+//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation'  or 'updateAabbs' before using a rayTest
+//#define RECALCULATE_AABB_RAYCAST 1
+
+//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+
+
+///for debug drawing
+
+//for debug rendering
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+
+
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
+:m_dispatcher1(dispatcher),
+m_broadphasePairCache(pairCache),
+m_debugDrawer(0),
+m_forceUpdateAllAabbs(true)
+{
+	m_stackAlloc = collisionConfiguration->getStackAllocator();
+	m_dispatchInfo.m_stackAllocator = m_stackAlloc;
+}
+
+
+btCollisionWorld::~btCollisionWorld()
+{
+
+	//clean up remaining objects
+	int i;
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* collisionObject= m_collisionObjects[i];
+
+		btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
+		if (bp)
+		{
+			//
+			// only clear the cached algorithms
+			//
+			getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+			getBroadphase()->destroyProxy(bp,m_dispatcher1);
+			collisionObject->setBroadphaseHandle(0);
+		}
+	}
+
+
+}
+
+
+
+
+
+
+
+
+
+
+void	btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
+{
+
+	btAssert(collisionObject);
+
+	//check that the object isn't already added
+	btAssert( m_collisionObjects.findLinearSearch(collisionObject)  == m_collisionObjects.size());
+
+	m_collisionObjects.push_back(collisionObject);
+
+	//calculate new AABB
+	btTransform trans = collisionObject->getWorldTransform();
+
+	btVector3	minAabb;
+	btVector3	maxAabb;
+	collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
+
+	int type = collisionObject->getCollisionShape()->getShapeType();
+	collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
+		minAabb,
+		maxAabb,
+		type,
+		collisionObject,
+		collisionFilterGroup,
+		collisionFilterMask,
+		m_dispatcher1,0
+		))	;
+
+
+
+
+
+}
+
+
+
+void	btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
+{
+	btVector3 minAabb,maxAabb;
+	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+	//need to increase the aabb for contact thresholds
+	btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+	minAabb -= contactThreshold;
+	maxAabb += contactThreshold;
+
+	if(getDispatchInfo().m_useContinuous && colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
+	{
+		btVector3 minAabb2,maxAabb2;
+		colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
+		minAabb2 -= contactThreshold;
+		maxAabb2 += contactThreshold;
+		minAabb.setMin(minAabb2);
+		maxAabb.setMax(maxAabb2);
+	}
+
+	btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
+
+	//moving objects should be moderately sized, probably something wrong if not
+	if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
+	{
+		bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+	} else
+	{
+		//something went wrong, investigate
+		//this assert is unwanted in 3D modelers (danger of loosing work)
+		colObj->setActivationState(DISABLE_SIMULATION);
+
+		static bool reportMe = true;
+		if (reportMe && m_debugDrawer)
+		{
+			reportMe = false;
+			m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
+			m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
+			m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
+			m_debugDrawer->reportErrorWarning("Thanks.\n");
+		}
+	}
+}
+
+void	btCollisionWorld::updateAabbs()
+{
+	BT_PROFILE("updateAabbs");
+
+	btTransform predictedTrans;
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+
+		//only update aabb of active objects
+		if (m_forceUpdateAllAabbs || colObj->isActive())
+		{
+			updateSingleAabb(colObj);
+		}
+	}
+}
+
+
+
+void	btCollisionWorld::performDiscreteCollisionDetection()
+{
+	BT_PROFILE("performDiscreteCollisionDetection");
+
+	btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+	updateAabbs();
+
+	{
+		BT_PROFILE("calculateOverlappingPairs");
+		m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+	}
+
+
+	btDispatcher* dispatcher = getDispatcher();
+	{
+		BT_PROFILE("dispatchAllCollisionPairs");
+		if (dispatcher)
+			dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+	}
+
+}
+
+
+
+void	btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+
+
+	//bool removeFromBroadphase = false;
+
+	{
+
+		btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
+		if (bp)
+		{
+			//
+			// only clear the cached algorithms
+			//
+			getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+			getBroadphase()->destroyProxy(bp,m_dispatcher1);
+			collisionObject->setBroadphaseHandle(0);
+		}
+	}
+
+
+	//swapremove
+	m_collisionObjects.remove(collisionObject);
+
+}
+
+
+
+void	btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+										btCollisionObject* collisionObject,
+										const btCollisionShape* collisionShape,
+										const btTransform& colObjWorldTransform,
+										RayResultCallback& resultCallback)
+{
+	btSphereShape pointShape(btScalar(0.0));
+	pointShape.setMargin(0.f);
+	const btConvexShape* castShape = &pointShape;
+
+	if (collisionShape->isConvex())
+	{
+		//		BT_PROFILE("rayTestConvex");
+		btConvexCast::CastResult castResult;
+		castResult.m_fraction = resultCallback.m_closestHitFraction;
+
+		btConvexShape* convexShape = (btConvexShape*) collisionShape;
+		btVoronoiSimplexSolver	simplexSolver;
+#define USE_SUBSIMPLEX_CONVEX_CAST 1
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+		btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
+#else
+		//btGjkConvexCast	convexCaster(castShape,convexShape,&simplexSolver);
+		//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
+		if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+		{
+			//add hit
+			if (castResult.m_normal.length2() > btScalar(0.0001))
+			{
+				if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+				{
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+					//rotate normal into worldspace
+					castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+
+					castResult.m_normal.normalize();
+					btCollisionWorld::LocalRayResult localRayResult
+						(
+						collisionObject,
+						0,
+						castResult.m_normal,
+						castResult.m_fraction
+						);
+
+					bool normalInWorldSpace = true;
+					resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
+
+				}
+			}
+		}
+	} else {
+		if (collisionShape->isConcave())
+		{
+			//			BT_PROFILE("rayTestConcave");
+			if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+			{
+				///optimized version for btBvhTriangleMeshShape
+				btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+				btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+				btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+				//ConvexCast::CastResult
+				struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+				{
+					btCollisionWorld::RayResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btTriangleMeshShape*	m_triangleMesh;
+
+					btTransform m_colObjWorldTransform;
+
+					BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+						btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape*	triangleMesh,const btTransform& colObjWorldTransform):
+					//@BP Mod
+					btTriangleRaycastCallback(from,to, resultCallback->m_flags),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh),
+						m_colObjWorldTransform(colObjWorldTransform)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+
+						btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+						btCollisionWorld::LocalRayResult rayResult
+							(m_collisionObject,
+							&shapeInfo,
+							hitNormalWorld,
+							hitFraction);
+
+						bool	normalInWorldSpace = true;
+						return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+					}
+
+				};
+
+				BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh,colObjWorldTransform);
+				rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+				triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
+			} else
+			{
+				//generic (slower) case
+				btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
+
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+
+				btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+				btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+				//ConvexCast::CastResult
+
+				struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+				{
+					btCollisionWorld::RayResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btConcaveShape*	m_triangleMesh;
+
+					btTransform m_colObjWorldTransform;
+
+					BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+						btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape*	triangleMesh, const btTransform& colObjWorldTransform):
+					//@BP Mod
+					btTriangleRaycastCallback(from,to, resultCallback->m_flags),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh),
+						m_colObjWorldTransform(colObjWorldTransform)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+
+						btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+						btCollisionWorld::LocalRayResult rayResult
+							(m_collisionObject,
+							&shapeInfo,
+							hitNormalWorld,
+							hitFraction);
+
+						bool	normalInWorldSpace = true;
+						return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+					}
+
+				};
+
+
+				BridgeTriangleRaycastCallback	rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
+				rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+
+				btVector3 rayAabbMinLocal = rayFromLocal;
+				rayAabbMinLocal.setMin(rayToLocal);
+				btVector3 rayAabbMaxLocal = rayFromLocal;
+				rayAabbMaxLocal.setMax(rayToLocal);
+
+				concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
+			}
+		} else {
+			//			BT_PROFILE("rayTestCompound");
+			if (collisionShape->isCompound())
+			{
+				struct LocalInfoAdder2 : public RayResultCallback
+				{
+					RayResultCallback* m_userCallback;
+					int m_i;
+					
+					LocalInfoAdder2 (int i, RayResultCallback *user)
+						: m_userCallback(user), m_i(i)
+					{ 
+						m_closestHitFraction = m_userCallback->m_closestHitFraction;
+					}
+					virtual bool needsCollision(btBroadphaseProxy* p) const
+					{
+						return m_userCallback->needsCollision(p);
+					}
+
+					virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b)
+					{
+						btCollisionWorld::LocalShapeInfo shapeInfo;
+						shapeInfo.m_shapePart = -1;
+						shapeInfo.m_triangleIndex = m_i;
+						if (r.m_localShapeInfo == NULL)
+							r.m_localShapeInfo = &shapeInfo;
+
+						const btScalar result = m_userCallback->addSingleResult(r, b);
+						m_closestHitFraction = m_userCallback->m_closestHitFraction;
+						return result;
+					}
+				};
+				
+				struct RayTester : btDbvt::ICollide
+				{
+					btCollisionObject* m_collisionObject;
+					const btCompoundShape* m_compoundShape;
+					const btTransform& m_colObjWorldTransform;
+					const btTransform& m_rayFromTrans;
+					const btTransform& m_rayToTrans;
+					RayResultCallback& m_resultCallback;
+					
+					RayTester(btCollisionObject* collisionObject,
+							const btCompoundShape* compoundShape,
+							const btTransform& colObjWorldTransform,
+							const btTransform& rayFromTrans,
+							const btTransform& rayToTrans,
+							RayResultCallback& resultCallback):
+						m_collisionObject(collisionObject),
+						m_compoundShape(compoundShape),
+						m_colObjWorldTransform(colObjWorldTransform),
+						m_rayFromTrans(rayFromTrans),
+						m_rayToTrans(rayToTrans),
+						m_resultCallback(resultCallback)
+					{
+						
+					}
+					
+					void Process(int i)
+					{
+						const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
+						const btTransform& childTrans = m_compoundShape->getChildTransform(i);
+						btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
+						
+						// replace collision shape so that callback can determine the triangle
+						btCollisionShape* saveCollisionShape = m_collisionObject->getCollisionShape();
+						m_collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+
+						LocalInfoAdder2 my_cb(i, &m_resultCallback);
+
+						rayTestSingle(
+							m_rayFromTrans,
+							m_rayToTrans,
+							m_collisionObject,
+							childCollisionShape,
+							childWorldTrans,
+							my_cb);
+						
+						// restore
+						m_collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
+					}
+					
+					void Process(const btDbvtNode* leaf)
+					{
+						Process(leaf->dataAsInt);
+					}
+				};
+				
+				const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+				const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
+
+
+				RayTester rayCB(
+					collisionObject,
+					compoundShape,
+					colObjWorldTransform,
+					rayFromTrans,
+					rayToTrans,
+					resultCallback);
+#ifndef	DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+				if (dbvt)
+				{
+					btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
+					btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
+					btDbvt::rayTest(dbvt->m_root, localRayFrom , localRayTo, rayCB);
+				}
+				else
+#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
+				{
+					for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
+					{
+						rayCB.Process(i);
+					}	
+				}
+			}
+		}
+	}
+}
+
+void	btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+											btCollisionObject* collisionObject,
+											const btCollisionShape* collisionShape,
+											const btTransform& colObjWorldTransform,
+											ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+	if (collisionShape->isConvex())
+	{
+		//BT_PROFILE("convexSweepConvex");
+		btConvexCast::CastResult castResult;
+		castResult.m_allowedPenetration = allowedPenetration;
+		castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//??
+
+		btConvexShape* convexShape = (btConvexShape*) collisionShape;
+		btVoronoiSimplexSolver	simplexSolver;
+		btGjkEpaPenetrationDepthSolver	gjkEpaPenetrationSolver;
+
+		btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
+		//btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
+		//btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
+
+		btConvexCast* castPtr = &convexCaster1;
+
+
+
+		if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+		{
+			//add hit
+			if (castResult.m_normal.length2() > btScalar(0.0001))
+			{
+				if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+				{
+					castResult.m_normal.normalize();
+					btCollisionWorld::LocalConvexResult localConvexResult
+						(
+						collisionObject,
+						0,
+						castResult.m_normal,
+						castResult.m_hitPoint,
+						castResult.m_fraction
+						);
+
+					bool normalInWorldSpace = true;
+					resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+
+				}
+			}
+		}
+	} else {
+		if (collisionShape->isConcave())
+		{
+			if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+			{
+				//BT_PROFILE("convexSweepbtBvhTriangleMesh");
+				btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+				btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+				btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+				// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+				btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+				//ConvexCast::CastResult
+				struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+				{
+					btCollisionWorld::ConvexResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btTriangleMeshShape*	m_triangleMesh;
+
+					BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+						btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape*	triangleMesh, const btTransform& triangleToWorld):
+					btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+						if (hitFraction <= m_resultCallback->m_closestHitFraction)
+						{
+
+							btCollisionWorld::LocalConvexResult convexResult
+								(m_collisionObject,
+								&shapeInfo,
+								hitNormalLocal,
+								hitPointLocal,
+								hitFraction);
+
+							bool	normalInWorldSpace = true;
+
+
+							return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+						}
+						return hitFraction;
+					}
+
+				};
+
+				BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+				tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+				tccb.m_allowedPenetration = allowedPenetration;
+				btVector3 boxMinLocal, boxMaxLocal;
+				castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+				triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
+			} else
+			{
+				if (collisionShape->getShapeType()==STATIC_PLANE_PROXYTYPE)
+				{
+					btConvexCast::CastResult castResult;
+					castResult.m_allowedPenetration = allowedPenetration;
+					castResult.m_fraction = resultCallback.m_closestHitFraction;
+					btStaticPlaneShape* planeShape = (btStaticPlaneShape*) collisionShape;
+					btContinuousConvexCollision convexCaster1(castShape,planeShape);
+					btConvexCast* castPtr = &convexCaster1;
+
+					if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+					{
+						//add hit
+						if (castResult.m_normal.length2() > btScalar(0.0001))
+						{
+							if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+							{
+								castResult.m_normal.normalize();
+								btCollisionWorld::LocalConvexResult localConvexResult
+									(
+									collisionObject,
+									0,
+									castResult.m_normal,
+									castResult.m_hitPoint,
+									castResult.m_fraction
+									);
+
+								bool normalInWorldSpace = true;
+								resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+							}
+						}
+					}
+
+				} else
+				{
+					//BT_PROFILE("convexSweepConcave");
+					btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
+					btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+					btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+					btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+					// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+					btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+					//ConvexCast::CastResult
+					struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+					{
+						btCollisionWorld::ConvexResultCallback* m_resultCallback;
+						btCollisionObject*	m_collisionObject;
+						btConcaveShape*	m_triangleMesh;
+
+						BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+							btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape*	triangleMesh, const btTransform& triangleToWorld):
+						btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+							m_resultCallback(resultCallback),
+							m_collisionObject(collisionObject),
+							m_triangleMesh(triangleMesh)
+						{
+						}
+
+
+						virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+						{
+							btCollisionWorld::LocalShapeInfo	shapeInfo;
+							shapeInfo.m_shapePart = partId;
+							shapeInfo.m_triangleIndex = triangleIndex;
+							if (hitFraction <= m_resultCallback->m_closestHitFraction)
+							{
+
+								btCollisionWorld::LocalConvexResult convexResult
+									(m_collisionObject,
+									&shapeInfo,
+									hitNormalLocal,
+									hitPointLocal,
+									hitFraction);
+
+								bool	normalInWorldSpace = false;
+
+								return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+							}
+							return hitFraction;
+						}
+
+					};
+
+					BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
+					tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+					tccb.m_allowedPenetration = allowedPenetration;
+					btVector3 boxMinLocal, boxMaxLocal;
+					castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+
+					btVector3 rayAabbMinLocal = convexFromLocal;
+					rayAabbMinLocal.setMin(convexToLocal);
+					btVector3 rayAabbMaxLocal = convexFromLocal;
+					rayAabbMaxLocal.setMax(convexToLocal);
+					rayAabbMinLocal += boxMinLocal;
+					rayAabbMaxLocal += boxMaxLocal;
+					concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
+				}
+			}
+		} else {
+			///@todo : use AABB tree or other BVH acceleration structure!
+			if (collisionShape->isCompound())
+			{
+				BT_PROFILE("convexSweepCompound");
+				const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+				int i=0;
+				for (i=0;i<compoundShape->getNumChildShapes();i++)
+				{
+					btTransform childTrans = compoundShape->getChildTransform(i);
+					const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+					btTransform childWorldTrans = colObjWorldTransform * childTrans;
+					// replace collision shape so that callback can determine the triangle
+					btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
+					collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+                    struct	LocalInfoAdder : public ConvexResultCallback {
+                            ConvexResultCallback* m_userCallback;
+							int m_i;
+
+                            LocalInfoAdder (int i, ConvexResultCallback *user)
+								: m_userCallback(user), m_i(i)
+							{
+								m_closestHitFraction = m_userCallback->m_closestHitFraction;
+							}
+							virtual bool needsCollision(btBroadphaseProxy* p) const
+							{
+								return m_userCallback->needsCollision(p);
+							}
+                            virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult&	r,	bool b)
+                            {
+                                    btCollisionWorld::LocalShapeInfo	shapeInfo;
+                                    shapeInfo.m_shapePart = -1;
+                                    shapeInfo.m_triangleIndex = m_i;
+                                    if (r.m_localShapeInfo == NULL)
+                                        r.m_localShapeInfo = &shapeInfo;
+									const btScalar result = m_userCallback->addSingleResult(r, b);
+									m_closestHitFraction = m_userCallback->m_closestHitFraction;
+									return result;
+                                    
+                            }
+                    };
+
+                    LocalInfoAdder my_cb(i, &resultCallback);
+					
+
+					objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+						collisionObject,
+						childCollisionShape,
+						childWorldTrans,
+						my_cb, allowedPenetration);
+					// restore
+					collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
+				}
+			}
+		}
+	}
+}
+
+
+struct btSingleRayCallback : public btBroadphaseRayCallback
+{
+
+	btVector3	m_rayFromWorld;
+	btVector3	m_rayToWorld;
+	btTransform	m_rayFromTrans;
+	btTransform	m_rayToTrans;
+	btVector3	m_hitNormal;
+
+	const btCollisionWorld*	m_world;
+	btCollisionWorld::RayResultCallback&	m_resultCallback;
+
+	btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
+		:m_rayFromWorld(rayFromWorld),
+		m_rayToWorld(rayToWorld),
+		m_world(world),
+		m_resultCallback(resultCallback)
+	{
+		m_rayFromTrans.setIdentity();
+		m_rayFromTrans.setOrigin(m_rayFromWorld);
+		m_rayToTrans.setIdentity();
+		m_rayToTrans.setOrigin(m_rayToWorld);
+
+		btVector3 rayDir = (rayToWorld-rayFromWorld);
+
+		rayDir.normalize ();
+		///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+		m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+		m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+		m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+		m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+		m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+		m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+		m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
+
+	}
+
+
+
+	virtual bool	process(const btBroadphaseProxy* proxy)
+	{
+		///terminate further ray tests, once the closestHitFraction reached zero
+		if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+			return false;
+
+		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+		//only perform raycast if filterMask matches
+		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
+		{
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+			//getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+			const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+			const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+			//btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+			//culling already done by broadphase
+			//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+			{
+				m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
+					collisionObject,
+					collisionObject->getCollisionShape(),
+					collisionObject->getWorldTransform(),
+					m_resultCallback);
+			}
+		}
+		return true;
+	}
+};
+
+void	btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+	//BT_PROFILE("rayTest");
+	/// use the broadphase to accelerate the search for objects, based on their aabb
+	/// and for each object with ray-aabb overlap, perform an exact ray test
+	btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+	m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+#else
+	for (int i=0;i<this->getNumCollisionObjects();i++)
+	{
+		rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+	}	
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+
+}
+
+
+struct btSingleSweepCallback : public btBroadphaseRayCallback
+{
+
+	btTransform	m_convexFromTrans;
+	btTransform	m_convexToTrans;
+	btVector3	m_hitNormal;
+	const btCollisionWorld*	m_world;
+	btCollisionWorld::ConvexResultCallback&	m_resultCallback;
+	btScalar	m_allowedCcdPenetration;
+	const btConvexShape* m_castShape;
+
+
+	btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration)
+		:m_convexFromTrans(convexFromTrans),
+		m_convexToTrans(convexToTrans),
+		m_world(world),
+		m_resultCallback(resultCallback),
+		m_allowedCcdPenetration(allowedPenetration),
+		m_castShape(castShape)
+	{
+		btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin());
+		btVector3 rayDir = unnormalizedRayDir.normalized();
+		///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+		m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+		m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+		m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+		m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+		m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+		m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+		m_lambda_max = rayDir.dot(unnormalizedRayDir);
+
+	}
+
+	virtual bool	process(const btBroadphaseProxy* proxy)
+	{
+		///terminate further convex sweep tests, once the closestHitFraction reached zero
+		if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+			return false;
+
+		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+		//only perform raycast if filterMask matches
+		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans,
+				collisionObject,
+				collisionObject->getCollisionShape(),
+				collisionObject->getWorldTransform(),
+				m_resultCallback,
+				m_allowedCcdPenetration);
+		}
+
+		return true;
+	}
+};
+
+
+
+void	btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+
+	BT_PROFILE("convexSweepTest");
+	/// use the broadphase to accelerate the search for objects, based on their aabb
+	/// and for each object with ray-aabb overlap, perform an exact ray test
+	/// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
+
+
+
+	btTransform	convexFromTrans,convexToTrans;
+	convexFromTrans = convexFromWorld;
+	convexToTrans = convexToWorld;
+	btVector3 castShapeAabbMin, castShapeAabbMax;
+	/* Compute AABB that encompasses angular movement */
+	{
+		btVector3 linVel, angVel;
+		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+		btVector3 zeroLinVel;
+		zeroLinVel.setValue(0,0,0);
+		btTransform R;
+		R.setIdentity ();
+		R.setRotation (convexFromTrans.getRotation());
+		castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+	}
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+
+	btSingleSweepCallback	convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration);
+
+	m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax);
+
+#else
+	/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+	// do a ray-shape query using convexCaster (CCD)
+	int i;
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject*	collisionObject= m_collisionObjects[i];
+		//only perform raycast if filterMask matches
+		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+			AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+			btVector3 hitNormal;
+			if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+			{
+				objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+					collisionObject,
+					collisionObject->getCollisionShape(),
+					collisionObject->getWorldTransform(),
+					resultCallback,
+					allowedCcdPenetration);
+			}
+		}
+	}
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+
+
+struct btBridgedManifoldResult : public btManifoldResult
+{
+
+	btCollisionWorld::ContactResultCallback&	m_resultCallback;
+
+	btBridgedManifoldResult( btCollisionObject* obj0,btCollisionObject* obj1,btCollisionWorld::ContactResultCallback& resultCallback )
+		:btManifoldResult(obj0,obj1),
+		m_resultCallback(resultCallback)
+	{
+	}
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+	{
+		bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+		btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+		btVector3 localA;
+		btVector3 localB;
+		if (isSwapped)
+		{
+			localA = m_rootTransB.invXform(pointA );
+			localB = m_rootTransA.invXform(pointInWorld);
+		} else
+		{
+			localA = m_rootTransA.invXform(pointA );
+			localB = m_rootTransB.invXform(pointInWorld);
+		}
+		
+		btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+		newPt.m_positionWorldOnA = pointA;
+		newPt.m_positionWorldOnB = pointInWorld;
+		
+	   //BP mod, store contact triangles.
+		if (isSwapped)
+		{
+			newPt.m_partId0 = m_partId1;
+			newPt.m_partId1 = m_partId0;
+			newPt.m_index0  = m_index1;
+			newPt.m_index1  = m_index0;
+		} else
+		{
+			newPt.m_partId0 = m_partId0;
+			newPt.m_partId1 = m_partId1;
+			newPt.m_index0  = m_index0;
+			newPt.m_index1  = m_index1;
+		}
+
+		//experimental feature info, for per-triangle material etc.
+		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
+		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
+		m_resultCallback.addSingleResult(newPt,obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);
+
+	}
+	
+};
+
+
+
+struct btSingleContactCallback : public btBroadphaseAabbCallback
+{
+
+	btCollisionObject* m_collisionObject;
+	btCollisionWorld*	m_world;
+	btCollisionWorld::ContactResultCallback&	m_resultCallback;
+	
+	
+	btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
+		:m_collisionObject(collisionObject),
+		m_world(world),
+		m_resultCallback(resultCallback)
+	{
+	}
+
+	virtual bool	process(const btBroadphaseProxy* proxy)
+	{
+		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
+		if (collisionObject == m_collisionObject)
+			return true;
+
+		//only perform raycast if filterMask matches
+		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
+		{
+			btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(m_collisionObject,collisionObject);
+			if (algorithm)
+			{
+				btBridgedManifoldResult contactPointResult(m_collisionObject,collisionObject, m_resultCallback);
+				//discrete collision detection query
+				algorithm->processCollision(m_collisionObject,collisionObject, m_world->getDispatchInfo(),&contactPointResult);
+
+				algorithm->~btCollisionAlgorithm();
+				m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
+			}
+		}
+		return true;
+	}
+};
+
+
+///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
+///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+void	btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback)
+{
+	btVector3 aabbMin,aabbMax;
+	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax);
+	btSingleContactCallback	contactCB(colObj,this,resultCallback);
+	
+	m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB);
+}
+
+
+///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+///it reports one or more contact points (including the one with deepest penetration)
+void	btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
+{
+	btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(colObjA,colObjB);
+	if (algorithm)
+	{
+		btBridgedManifoldResult contactPointResult(colObjA,colObjB, resultCallback);
+		//discrete collision detection query
+		algorithm->processCollision(colObjA,colObjB, getDispatchInfo(),&contactPointResult);
+
+		algorithm->~btCollisionAlgorithm();
+		getDispatcher()->freeCollisionAlgorithm(algorithm);
+	}
+
+}
+
+
+
+
+class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
+{
+	btIDebugDraw*	m_debugDrawer;
+	btVector3	m_color;
+	btTransform	m_worldTrans;
+
+public:
+
+	DebugDrawcallback(btIDebugDraw*	debugDrawer,const btTransform& worldTrans,const btVector3& color) :
+	  m_debugDrawer(debugDrawer),
+		  m_color(color),
+		  m_worldTrans(worldTrans)
+	  {
+	  }
+
+	  virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+	  {
+		  processTriangle(triangle,partId,triangleIndex);
+	  }
+
+	  virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
+	  {
+		  (void)partId;
+		  (void)triangleIndex;
+
+		  btVector3 wv0,wv1,wv2;
+		  wv0 = m_worldTrans*triangle[0];
+		  wv1 = m_worldTrans*triangle[1];
+		  wv2 = m_worldTrans*triangle[2];
+		  btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.);
+
+		  btVector3 normal = (wv1-wv0).cross(wv2-wv0);
+		  normal.normalize();
+		  btVector3 normalColor(1,1,0);
+		  m_debugDrawer->drawLine(center,center+normal,normalColor);
+
+
+
+		 
+		  m_debugDrawer->drawLine(wv0,wv1,m_color);
+		  m_debugDrawer->drawLine(wv1,wv2,m_color);
+		  m_debugDrawer->drawLine(wv2,wv0,m_color);
+	  }
+};
+
+
+void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
+{
+	// Draw a small simplex at the center of the object
+	getDebugDrawer()->drawTransform(worldTransform,1);
+
+	if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+	{
+		const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
+		for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
+		{
+			btTransform childTrans = compoundShape->getChildTransform(i);
+			const btCollisionShape* colShape = compoundShape->getChildShape(i);
+			debugDrawObject(worldTransform*childTrans,colShape,color);
+		}
+
+	} else
+	{
+		switch (shape->getShapeType())
+		{
+
+		case BOX_SHAPE_PROXYTYPE:
+			{
+				const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
+				btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
+				getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
+				break;
+			}
+
+		case SPHERE_SHAPE_PROXYTYPE:
+			{
+				const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
+				btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
+
+				getDebugDrawer()->drawSphere(radius, worldTransform, color);
+				break;
+			}
+		case MULTI_SPHERE_SHAPE_PROXYTYPE:
+			{
+				const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
+
+				btTransform childTransform;
+				childTransform.setIdentity();
+
+				for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
+				{
+					childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
+					getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
+				}
+
+				break;
+			}
+		case CAPSULE_SHAPE_PROXYTYPE:
+			{
+				const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
+
+				btScalar radius = capsuleShape->getRadius();
+				btScalar halfHeight = capsuleShape->getHalfHeight();
+
+				int upAxis = capsuleShape->getUpAxis();
+				getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
+				break;
+			}
+		case CONE_SHAPE_PROXYTYPE:
+			{
+				const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
+				btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
+				btScalar height = coneShape->getHeight();//+coneShape->getMargin();
+
+				int upAxis= coneShape->getConeUpIndex();
+				getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
+				break;
+
+			}
+		case CYLINDER_SHAPE_PROXYTYPE:
+			{
+				const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
+				int upAxis = cylinder->getUpAxis();
+				btScalar radius = cylinder->getRadius();
+				btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
+				getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
+				break;
+			}
+
+		case STATIC_PLANE_PROXYTYPE:
+			{
+				const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+				btScalar planeConst = staticPlaneShape->getPlaneConstant();
+				const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+				getDebugDrawer()->drawPlane(planeNormal, planeConst,worldTransform, color);
+				break;
+
+			}
+		default:
+			{
+
+				if (shape->isConcave())
+				{
+					btConcaveShape* concaveMesh = (btConcaveShape*) shape;
+
+					///@todo pass camera, for some culling? no -> we are not a graphics lib
+					btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+					btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+					DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+					concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
+
+				}
+
+				if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
+				{
+					btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
+					//todo: pass camera for some culling			
+					btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+					btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+					//DebugDrawcallback drawCallback;
+					DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+					convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
+				}
+
+
+				/// for polyhedral shapes
+				if (shape->isPolyhedral())
+				{
+					btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
+
+					int i;
+					if (polyshape->getConvexPolyhedron())
+					{
+						const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
+						for (i=0;i<poly->m_faces.size();i++)
+						{
+							btVector3 centroid(0,0,0);
+							int numVerts = poly->m_faces[i].m_indices.size();
+							if (numVerts)
+							{
+								int lastV = poly->m_faces[i].m_indices[numVerts-1];
+								for (int v=0;v<poly->m_faces[i].m_indices.size();v++)
+								{
+									int curVert = poly->m_faces[i].m_indices[v];
+									centroid+=poly->m_vertices[curVert];
+									getDebugDrawer()->drawLine(worldTransform*poly->m_vertices[lastV],worldTransform*poly->m_vertices[curVert],color);
+									lastV = curVert;
+								}
+							}
+							centroid*= 1./btScalar(numVerts);
+
+							btVector3 normalColor(1,1,0);
+							btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]);
+							getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor);
+							
+							
+						}
+
+						
+					} else
+					{
+						for (i=0;i<polyshape->getNumEdges();i++)
+						{
+							btVector3 a,b;
+							polyshape->getEdge(i,a,b);
+							btVector3 wa = worldTransform * a;
+							btVector3 wb = worldTransform * b;
+							getDebugDrawer()->drawLine(wa,wb,color);
+						}
+					}
+
+
+				}
+			}
+		}
+	}
+}
+
+
+void	btCollisionWorld::debugDrawWorld()
+{
+	if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
+	{
+		int numManifolds = getDispatcher()->getNumManifolds();
+		btVector3 color(0,0,0);
+		for (int i=0;i<numManifolds;i++)
+		{
+			btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
+			//btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+			//btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+
+			int numContacts = contactManifold->getNumContacts();
+			for (int j=0;j<numContacts;j++)
+			{
+				btManifoldPoint& cp = contactManifold->getContactPoint(j);
+				getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
+			}
+		}
+	}
+
+	if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
+	{
+		int i;
+
+		for (  i=0;i<m_collisionObjects.size();i++)
+		{
+			btCollisionObject* colObj = m_collisionObjects[i];
+			if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0)
+			{
+				if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)
+				{
+					btVector3 color(btScalar(1.),btScalar(1.),btScalar(1.));
+					switch(colObj->getActivationState())
+					{
+					case  ACTIVE_TAG:
+						color = btVector3(btScalar(1.),btScalar(1.),btScalar(1.)); break;
+					case ISLAND_SLEEPING:
+						color =  btVector3(btScalar(0.),btScalar(1.),btScalar(0.));break;
+					case WANTS_DEACTIVATION:
+						color = btVector3(btScalar(0.),btScalar(1.),btScalar(1.));break;
+					case DISABLE_DEACTIVATION:
+						color = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));break;
+					case DISABLE_SIMULATION:
+						color = btVector3(btScalar(1.),btScalar(1.),btScalar(0.));break;
+					default:
+						{
+							color = btVector3(btScalar(1),btScalar(0.),btScalar(0.));
+						}
+					};
+
+					debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
+				}
+				if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+				{
+					btVector3 minAabb,maxAabb;
+					btVector3 colorvec(1,0,0);
+					colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+					btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+					minAabb -= contactThreshold;
+					maxAabb += contactThreshold;
+
+					btVector3 minAabb2,maxAabb2;
+
+					if(colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
+					{
+						colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(),minAabb2,maxAabb2);
+						minAabb2 -= contactThreshold;
+						maxAabb2 += contactThreshold;
+						minAabb.setMin(minAabb2);
+						maxAabb.setMax(maxAabb2);
+					}
+
+					m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
+				}
+			}
+
+		}
+	}
+}
+
+
+void	btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
+{
+	int i;
+	//serialize all collision objects
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
+		{
+			colObj->serializeSingleObject(serializer);
+		}
+	}
+
+	///keep track of shapes already serialized
+	btHashMap<btHashPtr,btCollisionShape*>	serializedShapes;
+
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btCollisionShape* shape = colObj->getCollisionShape();
+
+		if (!serializedShapes.find(shape))
+		{
+			serializedShapes.insert(shape,shape);
+			shape->serializeSingleShape(serializer);
+		}
+	}
+
+}
+
+
+void	btCollisionWorld::serialize(btSerializer* serializer)
+{
+
+	serializer->startSerialization();
+	
+	serializeCollisionObjects(serializer);
+	
+	serializer->finishSerialization();
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h	(revision 11817)
@@ -0,0 +1,509 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://bulletphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/**
+ * @mainpage Bullet Documentation
+ *
+ * @section intro_sec Introduction
+ * Bullet Collision Detection & Physics SDK
+ *
+ * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
+ *
+ * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution.
+ * There is the Physics Forum for feedback and general Collision Detection and Physics discussions.
+ * Please visit http://www.bulletphysics.com
+ *
+ * @section install_sec Installation
+ *
+ * @subsection step1 Step 1: Download
+ * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list
+ *
+ * @subsection step2 Step 2: Building
+ * Bullet main build system for all platforms is cmake, you can download http://www.cmake.org
+ * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles.
+ * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles.
+ * You can also use cmake in the command-line. Here are some examples for various platforms:
+ * cmake . -G "Visual Studio 9 2008"
+ * cmake . -G Xcode
+ * cmake . -G "Unix Makefiles"
+ * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make.
+ * 
+ * @subsection step3 Step 3: Testing demos
+ * Try to run and experiment with BasicDemo executable as a starting point.
+ * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation.
+ * The Dependencies can be seen in this documentation under Directories
+ * 
+ * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation
+ * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform.
+ * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld.
+ * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras)
+ * Bullet Collision Detection can also be used without the Dynamics/Extras.
+ * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo.
+ * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation.
+ * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector.
+ *
+ * @section copyright Copyright
+ * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
+ * 
+ */
+ 
+ 
+
+#ifndef BT_COLLISION_WORLD_H
+#define BT_COLLISION_WORLD_H
+
+class btStackAlloc;
+class btCollisionShape;
+class btConvexShape;
+class btBroadphaseInterface;
+class btSerializer;
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btCollisionObject.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///CollisionWorld is interface and container for the collision detection
+class btCollisionWorld
+{
+
+	
+protected:
+
+	btAlignedObjectArray<btCollisionObject*>	m_collisionObjects;
+	
+	btDispatcher*	m_dispatcher1;
+
+	btDispatcherInfo	m_dispatchInfo;
+
+	btStackAlloc*	m_stackAlloc;
+
+	btBroadphaseInterface*	m_broadphasePairCache;
+
+	btIDebugDraw*	m_debugDrawer;
+
+	///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
+	///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
+	bool m_forceUpdateAllAabbs;
+
+	void	serializeCollisionObjects(btSerializer* serializer);
+
+public:
+
+	//this constructor doesn't own the dispatcher and paircache/broadphase
+	btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
+
+	virtual ~btCollisionWorld();
+
+	void	setBroadphase(btBroadphaseInterface*	pairCache)
+	{
+		m_broadphasePairCache = pairCache;
+	}
+
+	const btBroadphaseInterface*	getBroadphase() const
+	{
+		return m_broadphasePairCache;
+	}
+
+	btBroadphaseInterface*	getBroadphase()
+	{
+		return m_broadphasePairCache;
+	}
+
+	btOverlappingPairCache*	getPairCache()
+	{
+		return m_broadphasePairCache->getOverlappingPairCache();
+	}
+
+
+	btDispatcher*	getDispatcher()
+	{
+		return m_dispatcher1;
+	}
+
+	const btDispatcher*	getDispatcher() const
+	{
+		return m_dispatcher1;
+	}
+
+	void	updateSingleAabb(btCollisionObject* colObj);
+
+	virtual void	updateAabbs();
+	
+	virtual void	setDebugDrawer(btIDebugDraw*	debugDrawer)
+	{
+			m_debugDrawer = debugDrawer;
+	}
+
+	virtual btIDebugDraw*	getDebugDrawer()
+	{
+		return m_debugDrawer;
+	}
+
+	virtual void	debugDrawWorld();
+
+	virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
+
+
+	///LocalShapeInfo gives extra information for complex shapes
+	///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
+	struct	LocalShapeInfo
+	{
+		int	m_shapePart;
+		int	m_triangleIndex;
+		
+		//const btCollisionShape*	m_shapeTemp;
+		//const btTransform*	m_shapeLocalTransform;
+	};
+
+	struct	LocalRayResult
+	{
+		LocalRayResult(btCollisionObject*	collisionObject, 
+			LocalShapeInfo*	localShapeInfo,
+			const btVector3&		hitNormalLocal,
+			btScalar hitFraction)
+		:m_collisionObject(collisionObject),
+		m_localShapeInfo(localShapeInfo),
+		m_hitNormalLocal(hitNormalLocal),
+		m_hitFraction(hitFraction)
+		{
+		}
+
+		btCollisionObject*		m_collisionObject;
+		LocalShapeInfo*			m_localShapeInfo;
+		btVector3				m_hitNormalLocal;
+		btScalar				m_hitFraction;
+
+	};
+
+	///RayResultCallback is used to report new raycast results
+	struct	RayResultCallback
+	{
+		btScalar	m_closestHitFraction;
+		btCollisionObject*		m_collisionObject;
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+      //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback
+      unsigned int m_flags;
+
+		virtual ~RayResultCallback()
+		{
+		}
+		bool	hasHit() const
+		{
+			return (m_collisionObject != 0);
+		}
+
+		RayResultCallback()
+			:m_closestHitFraction(btScalar(1.)),
+			m_collisionObject(0),
+			m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+			m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+         //@BP Mod
+         m_flags(0)
+		{
+		}
+
+		virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+		{
+			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			return collides;
+		}
+
+
+		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
+	};
+
+	struct	ClosestRayResultCallback : public RayResultCallback
+	{
+		ClosestRayResultCallback(const btVector3&	rayFromWorld,const btVector3&	rayToWorld)
+		:m_rayFromWorld(rayFromWorld),
+		m_rayToWorld(rayToWorld)
+		{
+		}
+
+		btVector3	m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
+		btVector3	m_rayToWorld;
+
+		btVector3	m_hitNormalWorld;
+		btVector3	m_hitPointWorld;
+			
+		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+		{
+			//caller already does the filter on the m_closestHitFraction
+			btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
+			
+			m_closestHitFraction = rayResult.m_hitFraction;
+			m_collisionObject = rayResult.m_collisionObject;
+			if (normalInWorldSpace)
+			{
+				m_hitNormalWorld = rayResult.m_hitNormalLocal;
+			} else
+			{
+				///need to transform normal into worldspace
+				m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+			}
+			m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+			return rayResult.m_hitFraction;
+		}
+	};
+
+	struct	AllHitsRayResultCallback : public RayResultCallback
+	{
+		AllHitsRayResultCallback(const btVector3&	rayFromWorld,const btVector3&	rayToWorld)
+		:m_rayFromWorld(rayFromWorld),
+		m_rayToWorld(rayToWorld)
+		{
+		}
+
+		btAlignedObjectArray<btCollisionObject*>		m_collisionObjects;
+
+		btVector3	m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
+		btVector3	m_rayToWorld;
+
+		btAlignedObjectArray<btVector3>	m_hitNormalWorld;
+		btAlignedObjectArray<btVector3>	m_hitPointWorld;
+		btAlignedObjectArray<btScalar> m_hitFractions;
+			
+		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+		{
+			m_collisionObject = rayResult.m_collisionObject;
+			m_collisionObjects.push_back(rayResult.m_collisionObject);
+			btVector3 hitNormalWorld;
+			if (normalInWorldSpace)
+			{
+				hitNormalWorld = rayResult.m_hitNormalLocal;
+			} else
+			{
+				///need to transform normal into worldspace
+				hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+			}
+			m_hitNormalWorld.push_back(hitNormalWorld);
+			btVector3 hitPointWorld;
+			hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+			m_hitPointWorld.push_back(hitPointWorld);
+			m_hitFractions.push_back(rayResult.m_hitFraction);
+			return m_closestHitFraction;
+		}
+	};
+
+
+	struct LocalConvexResult
+	{
+		LocalConvexResult(btCollisionObject*	hitCollisionObject, 
+			LocalShapeInfo*	localShapeInfo,
+			const btVector3&		hitNormalLocal,
+			const btVector3&		hitPointLocal,
+			btScalar hitFraction
+			)
+		:m_hitCollisionObject(hitCollisionObject),
+		m_localShapeInfo(localShapeInfo),
+		m_hitNormalLocal(hitNormalLocal),
+		m_hitPointLocal(hitPointLocal),
+		m_hitFraction(hitFraction)
+		{
+		}
+
+		btCollisionObject*		m_hitCollisionObject;
+		LocalShapeInfo*			m_localShapeInfo;
+		btVector3				m_hitNormalLocal;
+		btVector3				m_hitPointLocal;
+		btScalar				m_hitFraction;
+	};
+
+	///RayResultCallback is used to report new raycast results
+	struct	ConvexResultCallback
+	{
+		btScalar	m_closestHitFraction;
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+		
+		ConvexResultCallback()
+			:m_closestHitFraction(btScalar(1.)),
+			m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+			m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+		{
+		}
+
+		virtual ~ConvexResultCallback()
+		{
+		}
+		
+		bool	hasHit() const
+		{
+			return (m_closestHitFraction < btScalar(1.));
+		}
+
+		
+
+		virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+		{
+			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			return collides;
+		}
+
+		virtual	btScalar	addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
+	};
+
+	struct	ClosestConvexResultCallback : public ConvexResultCallback
+	{
+		ClosestConvexResultCallback(const btVector3&	convexFromWorld,const btVector3&	convexToWorld)
+		:m_convexFromWorld(convexFromWorld),
+		m_convexToWorld(convexToWorld),
+		m_hitCollisionObject(0)
+		{
+		}
+
+		btVector3	m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
+		btVector3	m_convexToWorld;
+
+		btVector3	m_hitNormalWorld;
+		btVector3	m_hitPointWorld;
+		btCollisionObject*	m_hitCollisionObject;
+		
+		virtual	btScalar	addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
+		{
+//caller already does the filter on the m_closestHitFraction
+			btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
+						
+			m_closestHitFraction = convexResult.m_hitFraction;
+			m_hitCollisionObject = convexResult.m_hitCollisionObject;
+			if (normalInWorldSpace)
+			{
+				m_hitNormalWorld = convexResult.m_hitNormalLocal;
+			} else
+			{
+				///need to transform normal into worldspace
+				m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+			}
+			m_hitPointWorld = convexResult.m_hitPointLocal;
+			return convexResult.m_hitFraction;
+		}
+	};
+
+	///ContactResultCallback is used to report contact points
+	struct	ContactResultCallback
+	{
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+		
+		ContactResultCallback()
+			:m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+			m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+		{
+		}
+
+		virtual ~ContactResultCallback()
+		{
+		}
+		
+		virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+		{
+			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			return collides;
+		}
+
+		virtual	btScalar	addSingleResult(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) = 0;
+	};
+
+
+
+	int	getNumCollisionObjects() const
+	{
+		return int(m_collisionObjects.size());
+	}
+
+	/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
+	/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
+	virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; 
+
+	/// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
+	/// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
+	void    convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback,  btScalar allowedCcdPenetration = btScalar(0.)) const;
+
+	///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
+	///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+	void	contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
+
+	///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+	///it reports one or more contact points (including the one with deepest penetration)
+	void	contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
+
+
+	/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
+	/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
+	/// This allows more customization.
+	static void	rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+					  btCollisionObject* collisionObject,
+					  const btCollisionShape* collisionShape,
+					  const btTransform& colObjWorldTransform,
+					  RayResultCallback& resultCallback);
+
+	/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
+	static void	objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
+					  btCollisionObject* collisionObject,
+					  const btCollisionShape* collisionShape,
+					  const btTransform& colObjWorldTransform,
+					  ConvexResultCallback& resultCallback, btScalar	allowedPenetration);
+
+	virtual void	addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
+
+	btCollisionObjectArray& getCollisionObjectArray()
+	{
+		return m_collisionObjects;
+	}
+
+	const btCollisionObjectArray& getCollisionObjectArray() const
+	{
+		return m_collisionObjects;
+	}
+
+
+	virtual void	removeCollisionObject(btCollisionObject* collisionObject);
+
+	virtual void	performDiscreteCollisionDetection();
+
+	btDispatcherInfo& getDispatchInfo()
+	{
+		return m_dispatchInfo;
+	}
+
+	const btDispatcherInfo& getDispatchInfo() const
+	{
+		return m_dispatchInfo;
+	}
+	
+	bool	getForceUpdateAllAabbs() const
+	{
+		return m_forceUpdateAllAabbs;
+	}
+	void setForceUpdateAllAabbs( bool forceUpdateAllAabbs)
+	{
+		m_forceUpdateAllAabbs = forceUpdateAllAabbs;
+	}
+
+	///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
+	virtual	void	serialize(btSerializer* serializer);
+
+};
+
+
+#endif //BT_COLLISION_WORLD_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,353 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btManifoldResult.h"
+
+btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
+:btActivatingCollisionAlgorithm(ci,body0,body1),
+m_isSwapped(isSwapped),
+m_sharedManifold(ci.m_manifold)
+{
+	m_ownsManifold = false;
+
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btAssert (colObj->getCollisionShape()->isCompound());
+	
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+	m_compoundShapeRevision = compoundShape->getUpdateRevision();
+	
+	preallocateChildAlgorithms(body0,body1);
+}
+
+void	btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
+{
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+	btAssert (colObj->getCollisionShape()->isCompound());
+	
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+	int numChildren = compoundShape->getNumChildShapes();
+	int i;
+	
+	m_childCollisionAlgorithms.resize(numChildren);
+	for (i=0;i<numChildren;i++)
+	{
+		if (compoundShape->getDynamicAabbTree())
+		{
+			m_childCollisionAlgorithms[i] = 0;
+		} else
+		{
+			btCollisionShape* tmpShape = colObj->getCollisionShape();
+			btCollisionShape* childShape = compoundShape->getChildShape(i);
+			colObj->internalSetTemporaryCollisionShape( childShape );
+			m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
+			colObj->internalSetTemporaryCollisionShape( tmpShape );
+		}
+	}
+}
+
+void	btCompoundCollisionAlgorithm::removeChildAlgorithms()
+{
+	int numChildren = m_childCollisionAlgorithms.size();
+	int i;
+	for (i=0;i<numChildren;i++)
+	{
+		if (m_childCollisionAlgorithms[i])
+		{
+			m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+			m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+		}
+	}
+}
+
+btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
+{
+	removeChildAlgorithms();
+}
+
+
+
+
+struct	btCompoundLeafCallback : btDbvt::ICollide
+{
+
+public:
+
+	btCollisionObject* m_compoundColObj;
+	btCollisionObject* m_otherObj;
+	btDispatcher* m_dispatcher;
+	const btDispatcherInfo& m_dispatchInfo;
+	btManifoldResult*	m_resultOut;
+	btCollisionAlgorithm**	m_childCollisionAlgorithms;
+	btPersistentManifold*	m_sharedManifold;
+
+
+
+
+	btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult*	resultOut,btCollisionAlgorithm**	childCollisionAlgorithms,btPersistentManifold*	sharedManifold)
+		:m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
+		m_childCollisionAlgorithms(childCollisionAlgorithms),
+		m_sharedManifold(sharedManifold)
+	{
+
+	}
+
+
+	void	ProcessChildShape(btCollisionShape* childShape,int index)
+	{
+		btAssert(index>=0);
+		btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
+		btAssert(index<compoundShape->getNumChildShapes());
+
+
+		//backup
+		btTransform	orgTrans = m_compoundColObj->getWorldTransform();
+		btTransform	orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
+		const btTransform& childTrans = compoundShape->getChildTransform(index);
+		btTransform	newChildWorldTrans = orgTrans*childTrans ;
+
+		//perform an AABB check first
+		btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
+		childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+		m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
+
+		if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+		{
+
+			m_compoundColObj->setWorldTransform( newChildWorldTrans);
+			m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
+
+			//the contactpoint is still projected back using the original inverted worldtrans
+			btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
+			m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
+
+			if (!m_childCollisionAlgorithms[index])
+				m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
+
+			///detect swapping case
+			if (m_resultOut->getBody0Internal() == m_compoundColObj)
+			{
+				m_resultOut->setShapeIdentifiersA(-1,index);
+			} else
+			{
+				m_resultOut->setShapeIdentifiersB(-1,index);
+			}
+
+			m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
+			if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+			{
+				btVector3 worldAabbMin,worldAabbMax;
+				m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
+				m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
+			}
+			
+			//revert back transform
+			m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
+			m_compoundColObj->setWorldTransform(  orgTrans );
+			m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
+		}
+	}
+	void		Process(const btDbvtNode* leaf)
+	{
+		int index = leaf->dataAsInt;
+
+		btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
+		btCollisionShape* childShape = compoundShape->getChildShape(index);
+		if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+		{
+			btVector3 worldAabbMin,worldAabbMax;
+			btTransform	orgTrans = m_compoundColObj->getWorldTransform();
+			btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
+			m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
+		}
+		ProcessChildShape(childShape,index);
+
+	}
+};
+
+
+
+
+
+
+void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+
+	
+
+	btAssert (colObj->getCollisionShape()->isCompound());
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+	///btCompoundShape might have changed:
+	////make sure the internal child collision algorithm caches are still valid
+	if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
+	{
+		///clear and update all
+		removeChildAlgorithms();
+		
+		preallocateChildAlgorithms(body0,body1);
+	}
+
+
+	btDbvt* tree = compoundShape->getDynamicAabbTree();
+	//use a dynamic aabb tree to cull potential child-overlaps
+	btCompoundLeafCallback  callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
+
+	///we need to refresh all contact manifolds
+	///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
+	///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
+	{
+		int i;
+		btManifoldArray manifoldArray;
+		for (i=0;i<m_childCollisionAlgorithms.size();i++)
+		{
+			if (m_childCollisionAlgorithms[i])
+			{
+				m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+				for (int m=0;m<manifoldArray.size();m++)
+				{
+					if (manifoldArray[m]->getNumContacts())
+					{
+						resultOut->setPersistentManifold(manifoldArray[m]);
+						resultOut->refreshContactPoints();
+						resultOut->setPersistentManifold(0);//??necessary?
+					}
+				}
+				manifoldArray.resize(0);
+			}
+		}
+	}
+
+	if (tree)
+	{
+
+		btVector3 localAabbMin,localAabbMax;
+		btTransform otherInCompoundSpace;
+		otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
+		otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
+
+		const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+		//process all children, that overlap with  the given AABB bounds
+		tree->collideTV(tree->m_root,bounds,callback);
+
+	} else
+	{
+		//iterate over all children, perform an AABB check inside ProcessChildShape
+		int numChildren = m_childCollisionAlgorithms.size();
+		int i;
+		for (i=0;i<numChildren;i++)
+		{
+			callback.ProcessChildShape(compoundShape->getChildShape(i),i);
+		}
+	}
+
+	{
+				//iterate over all children, perform an AABB check inside ProcessChildShape
+		int numChildren = m_childCollisionAlgorithms.size();
+		int i;
+		btManifoldArray	manifoldArray;
+        btCollisionShape* childShape = 0;
+        btTransform	orgTrans;
+        btTransform	orgInterpolationTrans;
+        btTransform	newChildWorldTrans;
+        btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;        
+        
+		for (i=0;i<numChildren;i++)
+		{
+			if (m_childCollisionAlgorithms[i])
+			{
+				childShape = compoundShape->getChildShape(i);
+			//if not longer overlapping, remove the algorithm
+                orgTrans = colObj->getWorldTransform();
+                orgInterpolationTrans = colObj->getInterpolationWorldTransform();
+				const btTransform& childTrans = compoundShape->getChildTransform(i);
+                newChildWorldTrans = orgTrans*childTrans ;
+
+				//perform an AABB check first
+				childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+				otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
+
+				if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+				{
+					m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+					m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+					m_childCollisionAlgorithms[i] = 0;
+				}
+			}
+		}
+	}
+}
+
+btScalar	btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+
+	btAssert (colObj->getCollisionShape()->isCompound());
+	
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+	//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
+	//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
+	//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
+	//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
+	//then use each overlapping node AABB against Tree0
+	//and vise versa.
+
+	btScalar hitFraction = btScalar(1.);
+
+	int numChildren = m_childCollisionAlgorithms.size();
+	int i;
+    btTransform	orgTrans;
+    btScalar frac;
+	for (i=0;i<numChildren;i++)
+	{
+		//temporarily exchange parent btCollisionShape with childShape, and recurse
+		btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+		//backup
+        orgTrans = colObj->getWorldTransform();
+	
+		const btTransform& childTrans = compoundShape->getChildTransform(i);
+		//btTransform	newChildWorldTrans = orgTrans*childTrans ;
+		colObj->setWorldTransform( orgTrans*childTrans );
+
+		btCollisionShape* tmpShape = colObj->getCollisionShape();
+		colObj->internalSetTemporaryCollisionShape( childShape );
+        frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
+		if (frac<hitFraction)
+		{
+			hitFraction = frac;
+		}
+		//revert back
+		colObj->internalSetTemporaryCollisionShape( tmpShape);
+		colObj->setWorldTransform( orgTrans);
+	}
+	return hitFraction;
+
+}
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COMPOUND_COLLISION_ALGORITHM_H
+#define BT_COMPOUND_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+class btCollisionObject;
+
+/// btCompoundCollisionAlgorithm  supports collision between CompoundCollisionShapes and other collision shapes
+class btCompoundCollisionAlgorithm  : public btActivatingCollisionAlgorithm
+{
+	btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
+	bool m_isSwapped;
+
+	class btPersistentManifold*	m_sharedManifold;
+	bool					m_ownsManifold;
+
+	int	m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
+	
+	void	removeChildAlgorithms();
+	
+	void	preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1);
+
+public:
+
+	btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+	virtual ~btCompoundCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		int i;
+		for (i=0;i<m_childCollisionAlgorithms.size();i++)
+		{
+			if (m_childCollisionAlgorithms[i])
+				m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+		}
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+			return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
+		}
+	};
+
+	struct SwappedCreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+			return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
+		}
+	};
+
+};
+
+#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,247 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvex2dConvex2dAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+
+
+btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+{
+	m_numPerturbationIterations = 0;
+	m_minimumPointsPerturbationThreshold = 3;
+	m_simplexSolver = simplexSolver;
+	m_pdSolver = pdSolver;
+}
+
+btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc() 
+{ 
+}
+
+btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0,body1),
+m_simplexSolver(simplexSolver),
+m_pdSolver(pdSolver),
+m_ownManifold (false),
+m_manifoldPtr(mf),
+m_lowLevelOfDetail(false),
+ m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+	(void)body0;
+	(void)body1;
+}
+
+
+
+
+btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void	btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+	m_lowLevelOfDetail = useLowLevel;
+}
+
+
+
+extern btScalar gContactBreakingThreshold;
+
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+	if (!m_manifoldPtr)
+	{
+		//swapped?
+		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+		m_ownManifold = true;
+	}
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	//comment-out next line to test multi-contact generation
+	//resultOut->getPersistentManifold()->clearManifold();
+
+
+	btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
+	btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
+
+	btVector3  normalOnB;
+	btVector3  pointOnBWorld;
+
+	{
+
+
+		btGjkPairDetector::ClosestPointInput input;
+
+		btGjkPairDetector	gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
+		//TODO: if (dispatchInfo.m_useContinuous)
+		gjkPairDetector.setMinkowskiA(min0);
+		gjkPairDetector.setMinkowskiB(min1);
+
+		{
+			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
+			input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+		}
+
+		input.m_stackAlloc = dispatchInfo.m_stackAllocator;
+		input.m_transformA = body0->getWorldTransform();
+		input.m_transformB = body1->getWorldTransform();
+
+		gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+		btVector3 v0,v1;
+		btVector3 sepNormalWorldSpace;
+
+	}
+
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+
+}
+
+
+
+
+btScalar	btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+
+	///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+	///col0->m_worldTransform,
+	btScalar resultFraction = btScalar(1.);
+
+
+	btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+	btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+
+	if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+		squareMot1 < col1->getCcdSquareMotionThreshold())
+		return resultFraction;
+
+
+	//An adhoc way of testing the Continuous Collision Detection algorithms
+	//One object is approximated as a sphere, to simplify things
+	//Starting in penetration should report no time of impact
+	//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+	//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+
+	/// Convex0 against sphere for Convex1
+	{
+		btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+		btSphereShape	sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+
+			//store result.m_fraction in both bodies
+
+			if (col0->getHitFraction()> result.m_fraction)
+				col0->setHitFraction( result.m_fraction );
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+
+
+
+
+	}
+
+	/// Sphere (for convex0) against Convex1
+	{
+		btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+		btSphereShape	sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+
+			//store result.m_fraction in both bodies
+
+			if (col0->getHitFraction()	> result.m_fraction)
+				col0->setHitFraction( result.m_fraction);
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+	}
+
+	return resultFraction;
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+
+class btConvexPenetrationDepthSolver;
+
+
+///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
+///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
+class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
+{
+	btSimplexSolverInterface*		m_simplexSolver;
+	btConvexPenetrationDepthSolver* m_pdSolver;
+
+	
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool			m_lowLevelOfDetail;
+	
+	int m_numPerturbationIterations;
+	int m_minimumPointsPerturbationThreshold;
+
+public:
+
+	btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+
+	virtual ~btConvex2dConvex2dAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		///should we use m_ownManifold to avoid adding duplicates?
+		if (m_manifoldPtr && m_ownManifold)
+			manifoldArray.push_back(m_manifoldPtr);
+	}
+
+
+	void	setLowLevelOfDetail(bool useLowLevel);
+
+
+	const btPersistentManifold*	getManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+
+		btConvexPenetrationDepthSolver*		m_pdSolver;
+		btSimplexSolverInterface*			m_simplexSolver;
+		int m_numPerturbationIterations;
+		int m_minimumPointsPerturbationThreshold;
+
+		CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+		
+		virtual ~CreateFunc();
+
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
+			return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+		}
+	};
+
+
+};
+
+#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,312 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+
+btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,body0,body1),
+m_isSwapped(isSwapped),
+m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
+{
+}
+
+btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
+{
+}
+
+void	btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&	manifoldArray)
+{
+	if (m_btConvexTriangleCallback.m_manifoldPtr)
+	{
+		manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
+	}
+}
+
+
+btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher*  dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
+	  m_dispatcher(dispatcher),
+	m_dispatchInfoPtr(0)
+{
+	m_convexBody = isSwapped? body1:body0;
+	m_triBody = isSwapped? body0:body1;
+	
+	  //
+	  // create the manifold from the dispatcher 'manifold pool'
+	  //
+	  m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
+
+  	  clearCache();
+}
+
+btConvexTriangleCallback::~btConvexTriangleCallback()
+{
+	clearCache();
+	m_dispatcher->releaseManifold( m_manifoldPtr );
+  
+}
+  
+
+void	btConvexTriangleCallback::clearCache()
+{
+	m_dispatcher->clearManifold(m_manifoldPtr);
+}
+
+
+
+void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+ 
+	//just for debugging purposes
+	//printf("triangle %d",m_triangleCount++);
+
+
+	//aabb filter is already applied!	
+
+	btCollisionAlgorithmConstructionInfo ci;
+	ci.m_dispatcher1 = m_dispatcher;
+
+	btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
+
+
+#if 0	
+	///debug drawing of the overlapping triangles
+	if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
+	{
+		btVector3 color(1,1,0);
+		btTransform& tr = ob->getWorldTransform();
+		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
+		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
+		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
+	}
+#endif
+	
+	if (m_convexBody->getCollisionShape()->isConvex())
+	{
+		btTriangleShape tm(triangle[0],triangle[1],triangle[2]);	
+		tm.setMargin(m_collisionMarginTriangle);
+		
+		btCollisionShape* tmpShape = ob->getCollisionShape();
+		ob->internalSetTemporaryCollisionShape( &tm );
+
+		btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
+
+		if (m_resultOut->getBody0Internal() == m_triBody)
+		{
+			m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
+		}
+		else
+		{
+			m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
+		}
+	
+		colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+		colAlgo->~btCollisionAlgorithm();
+		ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+		ob->internalSetTemporaryCollisionShape( tmpShape);
+	}
+
+
+}
+
+
+
+void	btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	m_dispatchInfoPtr = &dispatchInfo;
+	m_collisionMarginTriangle = collisionMarginTriangle;
+	m_resultOut = resultOut;
+
+	//recalc aabbs
+	btTransform convexInTriangleSpace;
+	convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform();
+	btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
+	//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
+	convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
+	btScalar extraMargin = collisionMarginTriangle;
+	btVector3 extra(extraMargin,extraMargin,extraMargin);
+
+	m_aabbMax += extra;
+	m_aabbMin -= extra;
+	
+}
+
+void btConvexConcaveCollisionAlgorithm::clearCache()
+{
+	m_btConvexTriangleCallback.clearCache();
+
+}
+
+void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	
+	
+	btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
+	btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+	if (triBody->getCollisionShape()->isConcave())
+	{
+
+
+		btCollisionObject*	triOb = triBody;
+		btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
+		
+		if (convexBody->getCollisionShape()->isConvex())
+		{
+			btScalar collisionMarginTriangle = concaveShape->getMargin();
+					
+			resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+			m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
+
+			//Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
+			//m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+
+			m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
+
+			concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
+			
+			resultOut->refreshContactPoints();
+	
+		}
+	
+	}
+
+}
+
+
+btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
+	btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+
+	//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
+
+	//only perform CCD above a certain threshold, this prevents blocking on the long run
+	//because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
+	btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
+	if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
+	{
+		return btScalar(1.);
+	}
+
+	//const btVector3& from = convexbody->m_worldTransform.getOrigin();
+	//btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
+	//todo: only do if the motion exceeds the 'radius'
+
+	btTransform triInv = triBody->getWorldTransform().inverse();
+	btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
+	btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
+
+	struct LocalTriangleSphereCastCallback	: public btTriangleCallback
+	{
+		btTransform m_ccdSphereFromTrans;
+		btTransform m_ccdSphereToTrans;
+		btTransform	m_meshTransform;
+
+		btScalar	m_ccdSphereRadius;
+		btScalar	m_hitFraction;
+	
+
+		LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
+			:m_ccdSphereFromTrans(from),
+			m_ccdSphereToTrans(to),
+			m_ccdSphereRadius(ccdSphereRadius),
+			m_hitFraction(hitFraction)
+		{			
+		}
+		
+		
+		virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+		{
+			(void)partId;
+			(void)triangleIndex;
+			//do a swept sphere for now
+			btTransform ident;
+			ident.setIdentity();
+			btConvexCast::CastResult castResult;
+			castResult.m_fraction = m_hitFraction;
+			btSphereShape	pointShape(m_ccdSphereRadius);
+			btTriangleShape	triShape(triangle[0],triangle[1],triangle[2]);
+			btVoronoiSimplexSolver	simplexSolver;
+			btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
+			//GjkConvexCast	convexCaster(&pointShape,convexShape,&simplexSolver);
+			//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
+			//local space?
+
+			if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
+				ident,ident,castResult))
+			{
+				if (m_hitFraction > castResult.m_fraction)
+					m_hitFraction = castResult.m_fraction;
+			}
+
+		}
+
+	};
+
+
+	
+
+	
+	if (triBody->getCollisionShape()->isConcave())
+	{
+		btVector3 rayAabbMin = convexFromLocal.getOrigin();
+		rayAabbMin.setMin(convexToLocal.getOrigin());
+		btVector3 rayAabbMax = convexFromLocal.getOrigin();
+		rayAabbMax.setMax(convexToLocal.getOrigin());
+		btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
+		rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+		rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+
+		btScalar curHitFraction = btScalar(1.); //is this available?
+		LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
+			convexbody->getCcdSweptSphereRadius(),curHitFraction);
+
+		raycastCallback.m_hitFraction = convexbody->getHitFraction();
+
+		btCollisionObject* concavebody = triBody;
+
+		btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
+		
+		if (triangleMesh)
+		{
+			triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
+		}
+	
+
+
+		if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
+		{
+			convexbody->setHitFraction( raycastCallback.m_hitFraction);
+			return raycastCallback.m_hitFraction;
+		}
+	}
+
+	return btScalar(1.);
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+
+///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
+class btConvexTriangleCallback : public btTriangleCallback
+{
+	btCollisionObject* m_convexBody;
+	btCollisionObject* m_triBody;
+
+	btVector3	m_aabbMin;
+	btVector3	m_aabbMax ;
+
+
+	btManifoldResult* m_resultOut;
+	btDispatcher*	m_dispatcher;
+	const btDispatcherInfo* m_dispatchInfoPtr;
+	btScalar m_collisionMarginTriangle;
+	
+public:
+int	m_triangleCount;
+	
+	btPersistentManifold*	m_manifoldPtr;
+
+	btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+	void	setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual ~btConvexTriangleCallback();
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+	
+	void clearCache();
+
+	SIMD_FORCE_INLINE const btVector3& getAabbMin() const
+	{
+		return m_aabbMin;
+	}
+	SIMD_FORCE_INLINE const btVector3& getAabbMax() const
+	{
+		return m_aabbMax;
+	}
+
+};
+
+
+
+
+/// btConvexConcaveCollisionAlgorithm  supports collision between convex shapes and (concave) trianges meshes.
+class btConvexConcaveCollisionAlgorithm  : public btActivatingCollisionAlgorithm
+{
+
+	bool	m_isSwapped;
+
+	btConvexTriangleCallback m_btConvexTriangleCallback;
+
+
+
+public:
+
+	btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+	virtual ~btConvexConcaveCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray);
+	
+	void	clearCache();
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+			return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
+		}
+	};
+
+	struct SwappedCreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+			return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
+		}
+	};
+
+};
+
+#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,679 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
+///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
+///with reproduction case
+//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
+
+#include "btConvexConvexAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
+
+
+///////////
+
+
+
+static SIMD_FORCE_INLINE void segmentsClosestPoints(
+	btVector3& ptsVector,
+	btVector3& offsetA,
+	btVector3& offsetB,
+	btScalar& tA, btScalar& tB,
+	const btVector3& translation,
+	const btVector3& dirA, btScalar hlenA,
+	const btVector3& dirB, btScalar hlenB )
+{
+	// compute the parameters of the closest points on each line segment
+
+	btScalar dirA_dot_dirB = btDot(dirA,dirB);
+	btScalar dirA_dot_trans = btDot(dirA,translation);
+	btScalar dirB_dot_trans = btDot(dirB,translation);
+
+	btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+	if ( denom == 0.0f ) {
+		tA = 0.0f;
+	} else {
+		tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
+		if ( tA < -hlenA )
+			tA = -hlenA;
+		else if ( tA > hlenA )
+			tA = hlenA;
+	}
+
+	tB = tA * dirA_dot_dirB - dirB_dot_trans;
+
+	if ( tB < -hlenB ) {
+		tB = -hlenB;
+		tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+		if ( tA < -hlenA )
+			tA = -hlenA;
+		else if ( tA > hlenA )
+			tA = hlenA;
+	} else if ( tB > hlenB ) {
+		tB = hlenB;
+		tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+		if ( tA < -hlenA )
+			tA = -hlenA;
+		else if ( tA > hlenA )
+			tA = hlenA;
+	}
+
+	// compute the closest points relative to segment centers.
+
+	offsetA = dirA * tA;
+	offsetB = dirB * tB;
+
+	ptsVector = translation - offsetA + offsetB;
+}
+
+
+static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
+	btVector3& normalOnB,
+	btVector3& pointOnB,
+	btScalar capsuleLengthA,
+	btScalar	capsuleRadiusA,
+	btScalar capsuleLengthB,
+	btScalar	capsuleRadiusB,
+	int capsuleAxisA,
+	int capsuleAxisB,
+	const btTransform& transformA,
+	const btTransform& transformB,
+	btScalar distanceThreshold )
+{
+	btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
+	btVector3 translationA = transformA.getOrigin();
+	btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
+	btVector3 translationB = transformB.getOrigin();
+
+	// translation between centers
+
+	btVector3 translation = translationB - translationA;
+
+	// compute the closest points of the capsule line segments
+
+	btVector3 ptsVector;           // the vector between the closest points
+	
+	btVector3 offsetA, offsetB;    // offsets from segment centers to their closest points
+	btScalar tA, tB;              // parameters on line segment
+
+	segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
+						   directionA, capsuleLengthA, directionB, capsuleLengthB );
+
+	btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
+
+	if ( distance > distanceThreshold )
+		return distance;
+
+	btScalar lenSqr = ptsVector.length2();
+	if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		//degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
+		btVector3 q;
+		btPlaneSpace1(directionA,normalOnB,q);
+	} else
+	{
+		// compute the contact normal
+		normalOnB = ptsVector*-btRecipSqrt(lenSqr);
+	}
+	pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
+
+	return distance;
+}
+
+
+
+
+
+
+
+//////////
+
+
+
+
+
+btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+{
+	m_numPerturbationIterations = 0;
+	m_minimumPointsPerturbationThreshold = 3;
+	m_simplexSolver = simplexSolver;
+	m_pdSolver = pdSolver;
+}
+
+btConvexConvexAlgorithm::CreateFunc::~CreateFunc() 
+{ 
+}
+
+btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0,body1),
+m_simplexSolver(simplexSolver),
+m_pdSolver(pdSolver),
+m_ownManifold (false),
+m_manifoldPtr(mf),
+m_lowLevelOfDetail(false),
+#ifdef USE_SEPDISTANCE_UTIL2
+m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
+			  (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
+#endif
+m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+	(void)body0;
+	(void)body1;
+}
+
+
+
+
+btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void	btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+	m_lowLevelOfDetail = useLowLevel;
+}
+
+
+struct btPerturbedContactResult : public btManifoldResult
+{
+	btManifoldResult* m_originalManifoldResult;
+	btTransform m_transformA;
+	btTransform m_transformB;
+	btTransform	m_unPerturbedTransform;
+	bool	m_perturbA;
+	btIDebugDraw*	m_debugDrawer;
+
+
+	btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer)
+		:m_originalManifoldResult(originalResult),
+		m_transformA(transformA),
+		m_transformB(transformB),
+		m_unPerturbedTransform(unPerturbedTransform),
+		m_perturbA(perturbA),
+		m_debugDrawer(debugDrawer)
+	{
+	}
+	virtual ~ btPerturbedContactResult()
+	{
+	}
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth)
+	{
+		btVector3 endPt,startPt;
+		btScalar newDepth;
+		btVector3 newNormal;
+
+		if (m_perturbA)
+		{
+			btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth;
+			endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg);
+			newDepth = (endPt -  pointInWorld).dot(normalOnBInWorld);
+			startPt = endPt+normalOnBInWorld*newDepth;
+		} else
+		{
+			endPt = pointInWorld + normalOnBInWorld*orgDepth;
+			startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld);
+			newDepth = (endPt -  startPt).dot(normalOnBInWorld);
+			
+		}
+
+//#define DEBUG_CONTACTS 1
+#ifdef DEBUG_CONTACTS
+		m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0));
+		m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0));
+		m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1));
+#endif //DEBUG_CONTACTS
+
+		
+		m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth);
+	}
+
+};
+
+extern btScalar gContactBreakingThreshold;
+
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+	if (!m_manifoldPtr)
+	{
+		//swapped?
+		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+		m_ownManifold = true;
+	}
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	//comment-out next line to test multi-contact generation
+	//resultOut->getPersistentManifold()->clearManifold();
+	
+
+	btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
+	btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
+
+	btVector3  normalOnB;
+		btVector3  pointOnBWorld;
+#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+	if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
+	{
+		btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
+		btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
+		btVector3 localScalingA = capsuleA->getLocalScaling();
+		btVector3 localScalingB = capsuleB->getLocalScaling();
+		
+		btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+		btScalar dist = capsuleCapsuleDistance(normalOnB,	pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
+			capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
+			body0->getWorldTransform(),body1->getWorldTransform(),threshold);
+
+		if (dist<threshold)
+		{
+			btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
+			resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);	
+		}
+		resultOut->refreshContactPoints();
+		return;
+	}
+#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+
+
+
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+	{
+		m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
+	}
+
+	if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
+#endif //USE_SEPDISTANCE_UTIL2
+
+	{
+
+	
+	btGjkPairDetector::ClosestPointInput input;
+
+	btGjkPairDetector	gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
+	//TODO: if (dispatchInfo.m_useContinuous)
+	gjkPairDetector.setMinkowskiA(min0);
+	gjkPairDetector.setMinkowskiB(min1);
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+	{
+		input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+	} else
+#endif //USE_SEPDISTANCE_UTIL2
+	{
+		//if (dispatchInfo.m_convexMaxDistanceUseCPT)
+		//{
+		//	input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
+		//} else
+		//{
+		input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
+//		}
+
+		input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+	}
+
+	input.m_stackAlloc = dispatchInfo.m_stackAllocator;
+	input.m_transformA = body0->getWorldTransform();
+	input.m_transformB = body1->getWorldTransform();
+
+
+
+	
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	btScalar sepDist = 0.f;
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+	{
+		sepDist = gjkPairDetector.getCachedSeparatingDistance();
+		if (sepDist>SIMD_EPSILON)
+		{
+			sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
+			//now perturbe directions to get multiple contact points
+			
+		}
+	}
+#endif //USE_SEPDISTANCE_UTIL2
+
+	if (min0->isPolyhedral() && min1->isPolyhedral())
+	{
+
+
+		struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result
+		{
+			virtual void setShapeIdentifiersA(int partId0,int index0){}
+			virtual void setShapeIdentifiersB(int partId1,int index1){}
+			virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth) 
+			{
+			}
+		};
+		
+		btDummyResult dummy;
+
+
+		btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*) min0;
+		btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*) min1;
+		if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron())
+		{
+
+
+			gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
+			
+
+			btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+			btScalar minDist = 0.f;
+			btVector3 sepNormalWorldSpace;
+			bool foundSepAxis  = true;
+
+			if (dispatchInfo.m_enableSatConvex)
+			{
+				foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
+					*polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+					body0->getWorldTransform(), 
+					body1->getWorldTransform(),
+					sepNormalWorldSpace);
+			} else
+			{
+				sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
+				minDist = gjkPairDetector.getCachedSeparatingDistance();
+			}
+			if (foundSepAxis)
+			{
+//				printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
+
+				btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
+					body0->getWorldTransform(), 
+					body1->getWorldTransform(), minDist-threshold, threshold, *resultOut);
+ 				
+			}
+			if (m_ownManifold)
+			{
+				resultOut->refreshContactPoints();
+			}
+			return;
+
+		} else
+		{
+			//we can also deal with convex versus triangle (without connectivity data)
+			if (polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType()==TRIANGLE_SHAPE_PROXYTYPE)
+			{
+				gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
+		
+				btVector3 sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
+
+				btVertexArray vertices;
+				btTriangleShape* tri = (btTriangleShape*)polyhedronB;
+				vertices.push_back(	body1->getWorldTransform()*tri->m_vertices1[0]);
+				vertices.push_back(	body1->getWorldTransform()*tri->m_vertices1[1]);
+				vertices.push_back(	body1->getWorldTransform()*tri->m_vertices1[2]);
+
+				btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+				btScalar minDist = gjkPairDetector.getCachedSeparatingDistance();
+				btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), 
+					body0->getWorldTransform(), vertices, minDist-threshold, threshold, *resultOut);
+				
+				
+				if (m_ownManifold)
+				{
+					resultOut->refreshContactPoints();
+				}
+				
+				return;
+			}
+			
+		}
+
+
+	}
+	
+	gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+	//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+	
+	//perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
+	if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
+	{
+		
+		int i;
+		btVector3 v0,v1;
+		btVector3 sepNormalWorldSpace;
+	
+		sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
+		btPlaneSpace1(sepNormalWorldSpace,v0,v1);
+
+
+		bool perturbeA = true;
+		const btScalar angleLimit = 0.125f * SIMD_PI;
+		btScalar perturbeAngle;
+		btScalar radiusA = min0->getAngularMotionDisc();
+		btScalar radiusB = min1->getAngularMotionDisc();
+		if (radiusA < radiusB)
+		{
+			perturbeAngle = gContactBreakingThreshold /radiusA;
+			perturbeA = true;
+		} else
+		{
+			perturbeAngle = gContactBreakingThreshold / radiusB;
+			perturbeA = false;
+		}
+		if ( perturbeAngle > angleLimit ) 
+				perturbeAngle = angleLimit;
+
+		btTransform unPerturbedTransform;
+		if (perturbeA)
+		{
+			unPerturbedTransform = input.m_transformA;
+		} else
+		{
+			unPerturbedTransform = input.m_transformB;
+		}
+		
+		for ( i=0;i<m_numPerturbationIterations;i++)
+		{
+			if (v0.length2()>SIMD_EPSILON)
+			{
+			btQuaternion perturbeRot(v0,perturbeAngle);
+			btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
+			btQuaternion rotq(sepNormalWorldSpace,iterationAngle);
+			
+			
+			if (perturbeA)
+			{
+				input.m_transformA.setBasis(  btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis());
+				input.m_transformB = body1->getWorldTransform();
+#ifdef DEBUG_CONTACTS
+				dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
+#endif //DEBUG_CONTACTS
+			} else
+			{
+				input.m_transformA = body0->getWorldTransform();
+				input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis());
+#ifdef DEBUG_CONTACTS
+				dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
+#endif
+			}
+			
+			btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
+			gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
+			}
+			
+		}
+	}
+
+	
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
+	{
+		m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
+	}
+#endif //USE_SEPDISTANCE_UTIL2
+
+
+	}
+
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+
+}
+
+
+
+bool disableCcd = false;
+btScalar	btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+    
+	///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+	///col0->m_worldTransform,
+	btScalar resultFraction = btScalar(1.);
+
+
+	btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+	btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+    
+	if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+		squareMot1 < col1->getCcdSquareMotionThreshold())
+		return resultFraction;
+
+	if (disableCcd)
+		return btScalar(1.);
+
+
+	//An adhoc way of testing the Continuous Collision Detection algorithms
+	//One object is approximated as a sphere, to simplify things
+	//Starting in penetration should report no time of impact
+	//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+	//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+		
+	/// Convex0 against sphere for Convex1
+	{
+		btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+		btSphereShape	sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+		
+			//store result.m_fraction in both bodies
+		
+			if (col0->getHitFraction()> result.m_fraction)
+				col0->setHitFraction( result.m_fraction );
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+		
+		
+
+
+	}
+
+	/// Sphere (for convex0) against Convex1
+	{
+		btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+		btSphereShape	sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+		
+			//store result.m_fraction in both bodies
+		
+			if (col0->getHitFraction()	> result.m_fraction)
+				col0->setHitFraction( result.m_fraction);
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+	}
+	
+	return resultFraction;
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_CONVEX_ALGORITHM_H
+#define BT_CONVEX_CONVEX_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+
+class btConvexPenetrationDepthSolver;
+
+///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise
+///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions.
+///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util
+///for certain pairs that have a small size ratio
+
+//#define USE_SEPDISTANCE_UTIL2 1
+
+///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects.
+///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal.
+///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888
+class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
+{
+#ifdef USE_SEPDISTANCE_UTIL2
+	btConvexSeparatingDistanceUtil	m_sepDistance;
+#endif
+	btSimplexSolverInterface*		m_simplexSolver;
+	btConvexPenetrationDepthSolver* m_pdSolver;
+
+	
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool			m_lowLevelOfDetail;
+	
+	int m_numPerturbationIterations;
+	int m_minimumPointsPerturbationThreshold;
+
+
+	///cache separating vector to speedup collision detection
+	
+
+public:
+
+	btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+
+	virtual ~btConvexConvexAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		///should we use m_ownManifold to avoid adding duplicates?
+		if (m_manifoldPtr && m_ownManifold)
+			manifoldArray.push_back(m_manifoldPtr);
+	}
+
+
+	void	setLowLevelOfDetail(bool useLowLevel);
+
+
+	const btPersistentManifold*	getManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+
+		btConvexPenetrationDepthSolver*		m_pdSolver;
+		btSimplexSolverInterface*			m_simplexSolver;
+		int m_numPerturbationIterations;
+		int m_minimumPointsPerturbationThreshold;
+
+		CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+		
+		virtual ~CreateFunc();
+
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
+			return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+		}
+	};
+
+
+};
+
+#endif //BT_CONVEX_CONVEX_ALGORITHM_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,155 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexPlaneCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+//#include <stdio.h>
+
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped),
+m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+	btCollisionObject* convexObj = m_isSwapped? col1 : col0;
+	btCollisionObject* planeObj = m_isSwapped? col0 : col1;
+
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
+		m_ownManifold = true;
+	}
+}
+
+
+btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+    btCollisionObject* convexObj = m_isSwapped? body1 : body0;
+	btCollisionObject* planeObj = m_isSwapped? body0: body1;
+
+	btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
+	btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+
+    bool hasCollision = false;
+	const btVector3& planeNormal = planeShape->getPlaneNormal();
+	const btScalar& planeConstant = planeShape->getPlaneConstant();
+	
+	btTransform convexWorldTransform = convexObj->getWorldTransform();
+	btTransform convexInPlaneTrans;
+	convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform;
+	//now perturbe the convex-world transform
+	convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
+	btTransform planeInConvex;
+	planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform();
+	
+	btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+
+	btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+	btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+	btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+	btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
+
+	hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+	resultOut->setPersistentManifold(m_manifoldPtr);
+	if (hasCollision)
+	{
+		/// report a contact. internally this will be kept persistent, and contact reduction is done
+		btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
+		btVector3 pOnB = vtxInPlaneWorld;
+		resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+	}
+}
+
+
+void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)dispatchInfo;
+	if (!m_manifoldPtr)
+		return;
+
+    btCollisionObject* convexObj = m_isSwapped? body1 : body0;
+	btCollisionObject* planeObj = m_isSwapped? body0: body1;
+
+	btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
+	btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+
+    
+	const btVector3& planeNormal = planeShape->getPlaneNormal();
+	//const btScalar& planeConstant = planeShape->getPlaneConstant();
+
+	//first perform a collision query with the non-perturbated collision objects
+	{
+		btQuaternion rotq(0,0,0,1);
+		collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut);
+	}
+
+	if (resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
+	{
+		btVector3 v0,v1;
+		btPlaneSpace1(planeNormal,v0,v1);
+		//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+
+		const btScalar angleLimit = 0.125f * SIMD_PI;
+		btScalar perturbeAngle;
+		btScalar radius = convexShape->getAngularMotionDisc();
+		perturbeAngle = gContactBreakingThreshold / radius;
+		if ( perturbeAngle > angleLimit ) 
+				perturbeAngle = angleLimit;
+
+		btQuaternion perturbeRot(v0,perturbeAngle);
+		for (int i=0;i<m_numPerturbationIterations;i++)
+		{
+			btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
+			btQuaternion rotq(planeNormal,iterationAngle);
+			collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut);
+		}
+	}
+
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr->getNumContacts())
+		{
+			resultOut->refreshContactPoints();
+		}
+	}
+}
+
+btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	(void)col0;
+	(void)col1;
+
+	//not yet
+	return btScalar(1.);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
+#define BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
+{
+	bool		m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool		m_isSwapped;
+	int			m_numPerturbationIterations;
+	int			m_minimumPointsPerturbationThreshold;
+
+public:
+
+	btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
+
+	virtual ~btConvexPlaneCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		int	m_numPerturbationIterations;
+		int m_minimumPointsPerturbationThreshold;
+			
+		CreateFunc() 
+			: m_numPerturbationIterations(1),
+			m_minimumPointsPerturbationThreshold(1)
+		{
+		}
+		
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
+			if (!m_swapped)
+			{
+				return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+			} else
+			{
+				return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+			}
+		}
+	};
+
+};
+
+#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp	(revision 11817)
@@ -0,0 +1,298 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDefaultCollisionConfiguration.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btPoolAllocator.h"
+
+
+
+
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc*	stackAlloc,btPoolAllocator*	persistentManifoldPool,btPoolAllocator*	collisionAlgorithmPool)
+{
+
+	void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
+	m_simplexSolver = new (mem)btVoronoiSimplexSolver();
+
+	if (constructionInfo.m_useEpaPenetrationAlgorithm)
+	{
+		mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
+		m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
+	}else
+	{
+		mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
+		m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
+	}
+	
+	//default CreationFunctions, filling the m_doubleDispatch table
+	mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
+	m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
+	mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+	m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+	m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
+	mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
+	m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
+	m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
+	mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
+	m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
+	
+	mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
+	m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+	m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+	m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
+	m_boxSphereCF->m_swapped = true;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+	mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+	m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+	m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+	m_triangleSphereCF->m_swapped = true;
+	
+	mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
+	m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
+
+	//convex versus plane
+	mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+	m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+	m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+	m_planeConvexCF->m_swapped = true;
+	
+	///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+	int maxSize = sizeof(btConvexConvexAlgorithm);
+	int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
+	int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
+	int sl = sizeof(btConvexSeparatingDistanceUtil);
+	sl = sizeof(btGjkPairDetector);
+	int	collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize);
+	collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
+	collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
+
+	if (constructionInfo.m_stackAlloc)
+	{
+		m_ownsStackAllocator = false;
+		this->m_stackAlloc = constructionInfo.m_stackAlloc;
+	} else
+	{
+		m_ownsStackAllocator = true;
+		void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
+		m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
+	}
+		
+	if (constructionInfo.m_persistentManifoldPool)
+	{
+		m_ownsPersistentManifoldPool = false;
+		m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
+	} else
+	{
+		m_ownsPersistentManifoldPool = true;
+		void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+		m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
+	}
+	
+	if (constructionInfo.m_collisionAlgorithmPool)
+	{
+		m_ownsCollisionAlgorithmPool = false;
+		m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
+	} else
+	{
+		m_ownsCollisionAlgorithmPool = true;
+		void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+		m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+	}
+
+
+}
+
+btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
+{
+	if (m_ownsStackAllocator)
+	{
+		m_stackAlloc->destroy();
+		m_stackAlloc->~btStackAlloc();
+		btAlignedFree(m_stackAlloc);
+	}
+	if (m_ownsCollisionAlgorithmPool)
+	{
+		m_collisionAlgorithmPool->~btPoolAllocator();
+		btAlignedFree(m_collisionAlgorithmPool);
+	}
+	if (m_ownsPersistentManifoldPool)
+	{
+		m_persistentManifoldPool->~btPoolAllocator();
+		btAlignedFree(m_persistentManifoldPool);
+	}
+
+	m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree(	m_convexConvexCreateFunc);
+
+	m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_convexConcaveCreateFunc);
+	m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_swappedConvexConcaveCreateFunc);
+
+	m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_compoundCreateFunc);
+
+	m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_swappedCompoundCreateFunc);
+
+	m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_emptyCreateFunc);
+
+	m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_sphereSphereCF);
+
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_sphereBoxCF);
+	m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_boxSphereCF);
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+	m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_sphereTriangleCF);
+	m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_triangleSphereCF);
+	m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_boxBoxCF);
+
+	m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_convexPlaneCF);
+	m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_planeConvexCF);
+
+	m_simplexSolver->~btVoronoiSimplexSolver();
+	btAlignedFree(m_simplexSolver);
+
+	m_pdSolver->~btConvexPenetrationDepthSolver();
+	
+	btAlignedFree(m_pdSolver);
+
+
+}
+
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+
+
+	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+	{
+		return	m_sphereSphereCF;
+	}
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
+	{
+		return	m_sphereBoxCF;
+	}
+
+	if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+	{
+		return	m_boxSphereCF;
+	}
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+
+	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
+	{
+		return	m_sphereTriangleCF;
+	}
+
+	if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE  ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+	{
+		return	m_triangleSphereCF;
+	} 
+
+	if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+	{
+		return m_boxBoxCF;
+	}
+	
+	if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
+	{
+		return m_convexPlaneCF;
+	}
+
+	if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
+	{
+		return m_planeConvexCF;
+	}
+	
+
+
+	if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
+	{
+		return m_convexConvexCreateFunc;
+	}
+
+	if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
+	{
+		return m_convexConcaveCreateFunc;
+	}
+
+	if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
+	{
+		return m_swappedConvexConcaveCreateFunc;
+	}
+
+	if (btBroadphaseProxy::isCompound(proxyType0))
+	{
+		return m_compoundCreateFunc;
+	} else
+	{
+		if (btBroadphaseProxy::isCompound(proxyType1))
+		{
+			return m_swappedCompoundCreateFunc;
+		}
+	}
+
+	//failed to find an algorithm
+	return m_emptyCreateFunc;
+}
+
+void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+{
+	btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc;
+	convexConvex->m_numPerturbationIterations = numPerturbationIterations;
+	convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
+#define BT_DEFAULT_COLLISION_CONFIGURATION
+
+#include "btCollisionConfiguration.h"
+class btVoronoiSimplexSolver;
+class btConvexPenetrationDepthSolver;
+
+struct	btDefaultCollisionConstructionInfo
+{
+	btStackAlloc*		m_stackAlloc;
+	btPoolAllocator*	m_persistentManifoldPool;
+	btPoolAllocator*	m_collisionAlgorithmPool;
+	int					m_defaultMaxPersistentManifoldPoolSize;
+	int					m_defaultMaxCollisionAlgorithmPoolSize;
+	int					m_customCollisionAlgorithmMaxElementSize;
+	int					m_defaultStackAllocatorSize;
+	int					m_useEpaPenetrationAlgorithm;
+
+	btDefaultCollisionConstructionInfo()
+		:m_stackAlloc(0),
+		m_persistentManifoldPool(0),
+		m_collisionAlgorithmPool(0),
+		m_defaultMaxPersistentManifoldPoolSize(4096),
+		m_defaultMaxCollisionAlgorithmPoolSize(4096),
+		m_customCollisionAlgorithmMaxElementSize(0),
+		m_defaultStackAllocatorSize(0),
+		m_useEpaPenetrationAlgorithm(true)
+	{
+	}
+};
+
+
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator, pool memory allocators
+///@todo: describe the meaning
+class	btDefaultCollisionConfiguration : public btCollisionConfiguration
+{
+
+protected:
+
+	int	m_persistentManifoldPoolSize;
+	
+	btStackAlloc*	m_stackAlloc;
+	bool	m_ownsStackAllocator;
+
+	btPoolAllocator*	m_persistentManifoldPool;
+	bool	m_ownsPersistentManifoldPool;
+
+
+	btPoolAllocator*	m_collisionAlgorithmPool;
+	bool	m_ownsCollisionAlgorithmPool;
+
+	//default simplex/penetration depth solvers
+	btVoronoiSimplexSolver*	m_simplexSolver;
+	btConvexPenetrationDepthSolver*	m_pdSolver;
+	
+	//default CreationFunctions, filling the m_doubleDispatch table
+	btCollisionAlgorithmCreateFunc*	m_convexConvexCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_convexConcaveCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_swappedConvexConcaveCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_compoundCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_swappedCompoundCreateFunc;
+	btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+	btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
+	btCollisionAlgorithmCreateFunc* m_boxSphereCF;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+	btCollisionAlgorithmCreateFunc* m_boxBoxCF;
+	btCollisionAlgorithmCreateFunc*	m_sphereTriangleCF;
+	btCollisionAlgorithmCreateFunc*	m_triangleSphereCF;
+	btCollisionAlgorithmCreateFunc*	m_planeConvexCF;
+	btCollisionAlgorithmCreateFunc*	m_convexPlaneCF;
+	
+public:
+
+
+	btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+	virtual ~btDefaultCollisionConfiguration();
+
+		///memory pools
+	virtual btPoolAllocator* getPersistentManifoldPool()
+	{
+		return m_persistentManifoldPool;
+	}
+
+	virtual btPoolAllocator* getCollisionAlgorithmPool()
+	{
+		return m_collisionAlgorithmPool;
+	}
+
+	virtual btStackAlloc*	getStackAllocator()
+	{
+		return m_stackAlloc;
+	}
+
+	virtual	btVoronoiSimplexSolver*	getSimplexSolver()
+	{
+		return m_simplexSolver;
+	}
+
+
+	virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+	///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
+	///By default, this feature is disabled for best performance.
+	///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature.
+	///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled
+	///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
+	///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
+	///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
+	void	setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
+
+};
+
+#endif //BT_DEFAULT_COLLISION_CONFIGURATION
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,34 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btEmptyCollisionAlgorithm.h"
+
+
+
+btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+	: btCollisionAlgorithm(ci)
+{
+}
+
+void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+{
+}
+
+btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+{
+	return btScalar(1.);
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_EMPTY_ALGORITH
+#define BT_EMPTY_ALGORITH
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+#define ATTRIBUTE_ALIGNED(a)
+
+///EmptyAlgorithm is a stub for unsupported collision pairs.
+///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
+class btEmptyAlgorithm : public btCollisionAlgorithm
+{
+
+public:
+	
+	btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			(void)body0;
+			(void)body1;
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
+			return new(mem) btEmptyAlgorithm(ci);
+		}
+	};
+
+} ATTRIBUTE_ALIGNED(16);
+
+#endif //BT_EMPTY_ALGORITH
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp	(revision 11817)
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGhostObject.h"
+#include "btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+btGhostObject::btGhostObject()
+{
+	m_internalType = CO_GHOST_OBJECT;
+}
+
+btGhostObject::~btGhostObject()
+{
+	///btGhostObject should have been removed from the world, so no overlapping objects
+	btAssert(!m_overlappingObjects.size());
+}
+
+
+void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+{
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btAssert(otherObject);
+	///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index==m_overlappingObjects.size())
+	{
+		//not found
+		m_overlappingObjects.push_back(otherObject);
+	}
+}
+
+void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
+{
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btAssert(otherObject);
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index<m_overlappingObjects.size())
+	{
+		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+		m_overlappingObjects.pop_back();
+	}
+}
+
+
+btPairCachingGhostObject::btPairCachingGhostObject()
+{
+	m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+}
+
+btPairCachingGhostObject::~btPairCachingGhostObject()
+{
+	m_hashPairCache->~btHashedOverlappingPairCache();
+	btAlignedFree( m_hashPairCache );
+}
+
+void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+{
+	btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
+	btAssert(actualThisProxy);
+
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btAssert(otherObject);
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index==m_overlappingObjects.size())
+	{
+		m_overlappingObjects.push_back(otherObject);
+		m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
+	}
+}
+
+void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
+{
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
+	btAssert(actualThisProxy);
+
+	btAssert(otherObject);
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index<m_overlappingObjects.size())
+	{
+		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+		m_overlappingObjects.pop_back();
+		m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
+	}
+}
+
+
+void	btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+	btTransform	convexFromTrans,convexToTrans;
+	convexFromTrans = convexFromWorld;
+	convexToTrans = convexToWorld;
+	btVector3 castShapeAabbMin, castShapeAabbMax;
+	/* Compute AABB that encompasses angular movement */
+	{
+		btVector3 linVel, angVel;
+		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+		btTransform R;
+		R.setIdentity ();
+		R.setRotation (convexFromTrans.getRotation());
+		castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+	}
+
+	/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+	// do a ray-shape query using convexCaster (CCD)
+	int i;
+	for (i=0;i<m_overlappingObjects.size();i++)
+	{
+		btCollisionObject*	collisionObject= m_overlappingObjects[i];
+		//only perform raycast if filterMask matches
+		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+			AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+			btVector3 hitNormal;
+			if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+			{
+				btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+					collisionObject,
+						collisionObject->getCollisionShape(),
+						collisionObject->getWorldTransform(),
+						resultCallback,
+						allowedCcdPenetration);
+			}
+		}
+	}
+
+}
+
+void	btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+	btTransform rayFromTrans;
+	rayFromTrans.setIdentity();
+	rayFromTrans.setOrigin(rayFromWorld);
+	btTransform  rayToTrans;
+	rayToTrans.setIdentity();
+	rayToTrans.setOrigin(rayToWorld);
+
+
+	int i;
+	for (i=0;i<m_overlappingObjects.size();i++)
+	{
+		btCollisionObject*	collisionObject= m_overlappingObjects[i];
+		//only perform raycast if filterMask matches
+		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
+		{
+			btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
+							collisionObject,
+								collisionObject->getCollisionShape(),
+								collisionObject->getWorldTransform(),
+								resultCallback);
+		}
+	}
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btGhostObject.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btGhostObject.h	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GHOST_OBJECT_H
+#define BT_GHOST_OBJECT_H
+
+
+#include "btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "btCollisionWorld.h"
+
+class btConvexShape;
+
+class btDispatcher;
+
+///The btGhostObject can keep track of all objects that are overlapping
+///By default, this overlap is based on the AABB
+///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
+///We plan on adding rayTest and other queries for the btGhostObject
+ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
+{
+protected:
+
+	btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
+
+public:
+
+	btGhostObject();
+
+	virtual ~btGhostObject();
+
+	void	convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
+
+	void	rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; 
+
+	///this method is mainly for expert/internal use only.
+	virtual void	addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+	///this method is mainly for expert/internal use only.
+	virtual void	removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+
+	int	getNumOverlappingObjects() const
+	{
+		return m_overlappingObjects.size();
+	}
+
+	btCollisionObject*	getOverlappingObject(int index)
+	{
+		return m_overlappingObjects[index];
+	}
+
+	const btCollisionObject*	getOverlappingObject(int index) const
+	{
+		return m_overlappingObjects[index];
+	}
+
+	btAlignedObjectArray<btCollisionObject*>&	getOverlappingPairs()
+	{
+		return m_overlappingObjects;
+	}
+
+	const btAlignedObjectArray<btCollisionObject*>	getOverlappingPairs() const
+	{
+		return m_overlappingObjects;
+	}
+
+	//
+	// internal cast
+	//
+
+	static const btGhostObject*	upcast(const btCollisionObject* colObj)
+	{
+		if (colObj->getInternalType()==CO_GHOST_OBJECT)
+			return (const btGhostObject*)colObj;
+		return 0;
+	}
+	static btGhostObject*			upcast(btCollisionObject* colObj)
+	{
+		if (colObj->getInternalType()==CO_GHOST_OBJECT)
+			return (btGhostObject*)colObj;
+		return 0;
+	}
+
+};
+
+class	btPairCachingGhostObject : public btGhostObject
+{
+	btHashedOverlappingPairCache*	m_hashPairCache;
+
+public:
+
+	btPairCachingGhostObject();
+
+	virtual ~btPairCachingGhostObject();
+
+	///this method is mainly for expert/internal use only.
+	virtual void	addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+
+	virtual void	removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+
+	btHashedOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_hashPairCache;
+	}
+
+};
+
+
+
+///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
+class btGhostPairCallback : public btOverlappingPairCallback
+{
+	
+public:
+	btGhostPairCallback()
+	{
+	}
+
+	virtual ~btGhostPairCallback()
+	{
+		
+	}
+
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+	{
+		btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
+		btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
+		btGhostObject* ghost0 = 		btGhostObject::upcast(colObj0);
+		btGhostObject* ghost1 = 		btGhostObject::upcast(colObj1);
+		if (ghost0)
+			ghost0->addOverlappingObjectInternal(proxy1, proxy0);
+		if (ghost1)
+			ghost1->addOverlappingObjectInternal(proxy0, proxy1);
+		return 0;
+	}
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+	{
+		btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
+		btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
+		btGhostObject* ghost0 = 		btGhostObject::upcast(colObj0);
+		btGhostObject* ghost1 = 		btGhostObject::upcast(colObj1);
+		if (ghost0)
+			ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
+		if (ghost1)
+			ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
+		return 0;
+	}
+
+	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+	{
+		btAssert(0);
+		//need to keep track of all ghost objects and call them here
+		//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
+	}
+
+	
+
+};
+
+#endif
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp	(revision 11817)
@@ -0,0 +1,842 @@
+#include "btInternalEdgeUtility.h"
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+//#define DEBUG_INTERNAL_EDGE
+
+#ifdef DEBUG_INTERNAL_EDGE
+#include <stdio.h>
+#endif //DEBUG_INTERNAL_EDGE
+
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+static btIDebugDraw* gDebugDrawer = 0;
+
+void	btSetDebugDrawer(btIDebugDraw* debugDrawer)
+{
+	gDebugDrawer = debugDrawer;
+}
+
+static void    btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color)
+{
+	if (gDebugDrawer)
+		gDebugDrawer->drawLine(from,to,color);
+}
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+static int	btGetHash(int partId, int triangleIndex)
+{
+	int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+	return hash;
+}
+
+
+
+static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB)
+{
+	const btVector3 refAxis0  = edgeA;
+	const btVector3 refAxis1  = normalA;
+	const btVector3 swingAxis = normalB;
+	btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+	return  angle;
+}
+
+
+struct btConnectivityProcessor : public btTriangleCallback
+{
+	int				m_partIdA;
+	int				m_triangleIndexA;
+	btVector3*		m_triangleVerticesA;
+	btTriangleInfoMap*	m_triangleInfoMap;
+
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+	{
+		//skip self-collisions
+		if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
+			return;
+
+		//skip duplicates (disabled for now)
+		//if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
+		//	return;
+
+		//search for shared vertices and edges
+		int numshared = 0;
+		int sharedVertsA[3]={-1,-1,-1};
+		int sharedVertsB[3]={-1,-1,-1};
+
+		///skip degenerate triangles
+		btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2();
+		if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
+			return;
+
+
+		btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2();
+		///skip degenerate triangles
+		if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold)
+			return;
+
+#if 0
+		printf("triangle A[0]	=	(%f,%f,%f)\ntriangle A[1]	=	(%f,%f,%f)\ntriangle A[2]	=	(%f,%f,%f)\n",
+			m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
+			m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
+			m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
+
+		printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
+		printf("triangle B[0]	=	(%f,%f,%f)\ntriangle B[1]	=	(%f,%f,%f)\ntriangle B[2]	=	(%f,%f,%f)\n",
+			triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
+			triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
+			triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
+#endif
+
+		for (int i=0;i<3;i++)
+		{
+			for (int j=0;j<3;j++)
+			{
+				if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
+				{
+					sharedVertsA[numshared] = i;
+					sharedVertsB[numshared] = j;
+					numshared++;
+					///degenerate case
+					if(numshared >= 3)
+						return;
+				}
+			}
+			///degenerate case
+			if(numshared >= 3)
+				return;
+		}
+		switch (numshared)
+		{
+		case 0:
+			{
+				break;
+			}
+		case 1:
+			{
+				//shared vertex
+				break;
+			}
+		case 2:
+			{
+				//shared edge
+				//we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
+				if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
+				{
+					sharedVertsA[0] = 2;
+					sharedVertsA[1] = 0;
+					int tmp = sharedVertsB[1];
+					sharedVertsB[1] = sharedVertsB[0];
+					sharedVertsB[0] = tmp;
+				}
+
+				int hash = btGetHash(m_partIdA,m_triangleIndexA);
+
+				btTriangleInfo* info = m_triangleInfoMap->find(hash);
+				if (!info)
+				{
+					btTriangleInfo tmp;
+					m_triangleInfoMap->insert(hash,tmp);
+					info = m_triangleInfoMap->find(hash);
+				}
+
+				int sumvertsA = sharedVertsA[0]+sharedVertsA[1];
+				int otherIndexA = 3-sumvertsA;
+
+				
+				btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]);
+
+				btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]);
+				int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]);
+
+				btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]);
+				//btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
+
+				btVector3 normalA;
+				btVector3 normalB;
+				tA.calcNormal(normalA);
+				tB.calcNormal(normalB);
+				edge.normalize();
+				btVector3 edgeCrossA = edge.cross(normalA).normalize();
+
+				{
+					btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]];
+					if (edgeCrossA.dot(tmp) < 0)
+					{
+						edgeCrossA*=-1;
+					}
+				}
+
+				btVector3 edgeCrossB = edge.cross(normalB).normalize();
+
+				{
+					btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]];
+					if (edgeCrossB.dot(tmp) < 0)
+					{
+						edgeCrossB*=-1;
+					}
+				}
+
+				btScalar	angle2 = 0;
+				btScalar	ang4 = 0.f;
+
+
+				btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
+				btScalar len2 = calculatedEdge.length2();
+
+				btScalar correctedAngle(0);
+				btVector3 calculatedNormalB = normalA;
+				bool isConvex = false;
+
+				if (len2<m_triangleInfoMap->m_planarEpsilon)
+				{
+					angle2 = 0.f;
+					ang4 = 0.f;
+				} else
+				{
+
+					calculatedEdge.normalize();
+					btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
+					calculatedNormalA.normalize();
+					angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB);
+					ang4 = SIMD_PI-angle2;
+					btScalar dotA = normalA.dot(edgeCrossB);
+					///@todo: check if we need some epsilon, due to floating point imprecision
+					isConvex = (dotA<0.);
+
+					correctedAngle = isConvex ? ang4 : -ang4;
+					btQuaternion orn2(calculatedEdge,-correctedAngle);
+					calculatedNormalB = btMatrix3x3(orn2)*normalA;
+
+
+				}
+
+				
+
+				
+							
+				//alternatively use 
+				//btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
+
+
+				switch (sumvertsA)
+				{
+				case 1:
+					{
+						btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1];
+						btQuaternion orn(edge,-correctedAngle);
+						btVector3 computedNormalB = quatRotate(orn,normalA);
+						btScalar bla = computedNormalB.dot(normalB);
+						if (bla<0)
+						{
+							computedNormalB*=-1;
+							info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
+						}
+#ifdef DEBUG_INTERNAL_EDGE
+						if ((computedNormalB-normalB).length()>0.0001)
+						{
+							printf("warning: normals not identical\n");
+						}
+#endif//DEBUG_INTERNAL_EDGE
+
+						info->m_edgeV0V1Angle = -correctedAngle;
+
+						if (isConvex)
+							info->m_flags |= TRI_INFO_V0V1_CONVEX;
+						break;
+					}
+				case 2:
+					{
+						btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0];
+						btQuaternion orn(edge,-correctedAngle);
+						btVector3 computedNormalB = quatRotate(orn,normalA);
+						if (computedNormalB.dot(normalB)<0)
+						{
+							computedNormalB*=-1;
+							info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
+						}
+
+#ifdef DEBUG_INTERNAL_EDGE
+						if ((computedNormalB-normalB).length()>0.0001)
+						{
+							printf("warning: normals not identical\n");
+						}
+#endif //DEBUG_INTERNAL_EDGE
+						info->m_edgeV2V0Angle = -correctedAngle;
+						if (isConvex)
+							info->m_flags |= TRI_INFO_V2V0_CONVEX;
+						break;	
+					}
+				case 3:
+					{
+						btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2];
+						btQuaternion orn(edge,-correctedAngle);
+						btVector3 computedNormalB = quatRotate(orn,normalA);
+						if (computedNormalB.dot(normalB)<0)
+						{
+							info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
+							computedNormalB*=-1;
+						}
+#ifdef DEBUG_INTERNAL_EDGE
+						if ((computedNormalB-normalB).length()>0.0001)
+						{
+							printf("warning: normals not identical\n");
+						}
+#endif //DEBUG_INTERNAL_EDGE
+						info->m_edgeV1V2Angle = -correctedAngle;
+
+						if (isConvex)
+							info->m_flags |= TRI_INFO_V1V2_CONVEX;
+						break;
+					}
+				}
+
+				break;
+			}
+		default:
+			{
+				//				printf("warning: duplicate triangle\n");
+			}
+
+		}
+	}
+};
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap)
+{
+	//the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+	if (trimeshShape->getTriangleInfoMap())
+		return;
+
+	trimeshShape->setTriangleInfoMap(triangleInfoMap);
+
+	btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
+	const btVector3& meshScaling = meshInterface->getScaling();
+
+	for (int partId = 0; partId< meshInterface->getNumSubParts();partId++)
+	{
+		const unsigned char *vertexbase = 0;
+		int numverts = 0;
+		PHY_ScalarType type = PHY_INTEGER;
+		int stride = 0;
+		const unsigned char *indexbase = 0;
+		int indexstride = 0;
+		int numfaces = 0;
+		PHY_ScalarType indicestype = PHY_INTEGER;
+		//PHY_ScalarType indexType=0;
+
+		btVector3 triangleVerts[3];
+		meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,	type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
+		btVector3 aabbMin,aabbMax;
+
+		for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
+		{
+			unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
+
+			for (int j=2;j>=0;j--)
+			{
+
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+					triangleVerts[j] = btVector3(
+						graphicsbase[0]*meshScaling.getX(),
+						graphicsbase[1]*meshScaling.getY(),
+						graphicsbase[2]*meshScaling.getZ());
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+					triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+				}
+			}
+			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+			aabbMin.setMin(triangleVerts[0]);
+			aabbMax.setMax(triangleVerts[0]);
+			aabbMin.setMin(triangleVerts[1]);
+			aabbMax.setMax(triangleVerts[1]);
+			aabbMin.setMin(triangleVerts[2]);
+			aabbMax.setMax(triangleVerts[2]);
+
+			btConnectivityProcessor connectivityProcessor;
+			connectivityProcessor.m_partIdA = partId;
+			connectivityProcessor.m_triangleIndexA = triangleIndex;
+			connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
+			connectivityProcessor.m_triangleInfoMap  = triangleInfoMap;
+
+			trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax);
+		}
+
+	}
+
+}
+
+
+
+
+// Given a point and a line segment (defined by two points), compute the closest point
+// in the line.  Cap the point at the endpoints of the line segment.
+void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
+{
+	btVector3 lineDelta     = line1 - line0;
+
+	// Handle degenerate lines
+	if ( lineDelta.fuzzyZero())
+	{
+		nearestPoint = line0;
+	}
+	else
+	{
+		btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
+
+		// Clamp the point to conform to the segment's endpoints
+		if ( delta < 0 )
+			delta = 0;
+		else if ( delta > 1 )
+			delta = 1;
+
+		nearestPoint = line0 + lineDelta*delta;
+	}
+}
+
+
+
+
+bool	btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal)
+{
+	btVector3 tri_normal = tri_normal_org;
+	//we only have a local triangle normal, not a local contact normal -> only normal in world space...
+	//either compute the current angle all in local space, or all in world space
+
+	btVector3 edgeCross = edge.cross(tri_normal).normalize();
+	btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB);
+
+	if (correctedEdgeAngle<0)
+	{
+		if (curAngle < correctedEdgeAngle)
+		{
+			btScalar diffAngle = correctedEdgeAngle-curAngle;
+			btQuaternion rotation(edge,diffAngle );
+			clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+			return true;
+		}
+	}
+
+	if (correctedEdgeAngle>=0)
+	{
+		if (curAngle > correctedEdgeAngle)
+		{
+			btScalar diffAngle = correctedEdgeAngle-curAngle;
+			btQuaternion rotation(edge,diffAngle );
+			clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+			return true;
+		}
+	}
+	return false;
+}
+
+
+
+/// Changes a btManifoldPoint collision normal to the normal from the mesh.
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* colObj0,const btCollisionObject* colObj1, int partId0, int index0, int normalAdjustFlags)
+{
+	//btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
+	if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
+		return;
+
+	btBvhTriangleMeshShape* trimesh = 0;
+	
+	if( colObj0->getRootCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE )
+	   trimesh = ((btScaledBvhTriangleMeshShape*)colObj0->getRootCollisionShape())->getChildShape();
+   else	   
+	   trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape();
+	   
+   	btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap();
+	if (!triangleInfoMapPtr)
+		return;
+
+	int hash = btGetHash(partId0,index0);
+
+
+	btTriangleInfo* info = triangleInfoMapPtr->find(hash);
+	if (!info)
+		return;
+
+	btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f;
+	
+	const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0->getCollisionShape());
+	btVector3 v0,v1,v2;
+	tri_shape->getVertex(0,v0);
+	tri_shape->getVertex(1,v1);
+	tri_shape->getVertex(2,v2);
+
+	btVector3 center = (v0+v1+v2)*btScalar(1./3.);
+
+	btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0);
+	btVector3 tri_normal;
+	tri_shape->calcNormal(tri_normal);
+
+	//btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
+	btVector3 nearest;
+	btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest);
+
+	btVector3 contact = cp.m_localPointB;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+	const btTransform& tr = colObj0->getWorldTransform();
+	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+
+	bool isNearEdge = false;
+
+	int numConcaveEdgeHits = 0;
+	int numConvexEdgeHits = 0;
+
+	btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+	localContactNormalOnB.normalize();//is this necessary?
+	
+	// Get closest edge
+	int      bestedge=-1;
+	float    disttobestedge=BT_LARGE_FLOAT;
+	//
+	// Edge 0 -> 1
+	if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+	{	
+	   btVector3 nearest;
+	   btNearestPointInLineSegment( cp.m_localPointB, v0, v1, nearest );
+	   float     len=(contact-nearest).length();
+	   //
+	   if( len < disttobestedge )
+	   {
+	      bestedge=0;
+	      disttobestedge=len;
+      }	      
+   }	   
+	// Edge 1 -> 2
+	if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+	{	
+	   btVector3 nearest;
+	   btNearestPointInLineSegment( cp.m_localPointB, v1, v2, nearest );
+	   float     len=(contact-nearest).length();
+	   //
+	   if( len < disttobestedge )
+	   {
+	      bestedge=1;
+	      disttobestedge=len;
+      }	      
+   }	   
+	// Edge 2 -> 0
+	if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+	{	
+	   btVector3 nearest;
+	   btNearestPointInLineSegment( cp.m_localPointB, v2, v0, nearest );
+	   float     len=(contact-nearest).length();
+	   //
+	   if( len < disttobestedge )
+	   {
+	      bestedge=2;
+	      disttobestedge=len;
+      }	      
+   }   	      	
+	
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+   btVector3 upfix=tri_normal * btVector3(0.1f,0.1f,0.1f);
+   btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red );
+#endif   
+	if (btFabs(info->m_edgeV0V1Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+	{
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif
+		btScalar len = (contact-nearest).length();
+		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+		if( bestedge==0 )
+		{
+			btVector3 edge(v0-v1);
+			isNearEdge = true;
+
+			if (info->m_edgeV0V1Angle==btScalar(0))
+			{
+				numConcaveEdgeHits++;
+			} else
+			{
+
+				bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
+				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+				btVector3 nA = swapFactor * tri_normal;
+
+				btQuaternion orn(edge,info->m_edgeV0V1Angle);
+				btVector3 computedNormalB = quatRotate(orn,tri_normal);
+				if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
+					computedNormalB*=-1;
+				btVector3 nB = swapFactor*computedNormalB;
+
+				btScalar	NdotA = localContactNormalOnB.dot(nA);
+				btScalar	NdotB = localContactNormalOnB.dot(nB);
+				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+#ifdef DEBUG_INTERNAL_EDGE
+				{
+					
+					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+				}
+#endif //DEBUG_INTERNAL_EDGE
+
+
+				if (backFacingNormal)
+				{
+					numConcaveEdgeHits++;
+				}
+				else
+				{
+					numConvexEdgeHits++;
+					btVector3 clampedLocalNormal;
+					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal);
+					if (isClamped)
+					{
+						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+						{
+							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+							cp.m_normalWorldOnB = newNormal;
+							// Reproject collision point along normal. (what about cp.m_distance1?)
+							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+							
+						}
+					}
+				}
+			}
+		}
+	}
+
+	btNearestPointInLineSegment(contact,v1,v2,nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+   btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix , green );
+#endif   
+
+	if (btFabs(info->m_edgeV1V2Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+	{
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+
+		btScalar len = (contact-nearest).length();
+		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+		if( bestedge==1 )
+		{
+			isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+			btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+			btVector3 edge(v1-v2);
+
+			isNearEdge = true;
+
+			if (info->m_edgeV1V2Angle == btScalar(0))
+			{
+				numConcaveEdgeHits++;
+			} else
+			{
+				bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0;
+				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+				btVector3 nA = swapFactor * tri_normal;
+				
+				btQuaternion orn(edge,info->m_edgeV1V2Angle);
+				btVector3 computedNormalB = quatRotate(orn,tri_normal);
+				if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
+					computedNormalB*=-1;
+				btVector3 nB = swapFactor*computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+				{
+					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+				}
+#endif //DEBUG_INTERNAL_EDGE
+
+
+				btScalar	NdotA = localContactNormalOnB.dot(nA);
+				btScalar	NdotB = localContactNormalOnB.dot(nB);
+				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+				if (backFacingNormal)
+				{
+					numConcaveEdgeHits++;
+				}
+				else
+				{
+					numConvexEdgeHits++;
+					btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+					btVector3 clampedLocalNormal;
+					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal);
+					if (isClamped)
+					{
+						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+						{
+							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+							cp.m_normalWorldOnB = newNormal;
+							// Reproject collision point along normal.
+							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	btNearestPointInLineSegment(contact,v2,v0,nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+   btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix , blue );
+#endif   
+
+	if (btFabs(info->m_edgeV2V0Angle)< triangleInfoMapPtr->m_maxEdgeAngleThreshold)
+	{
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+		btScalar len = (contact-nearest).length();
+		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+		if( bestedge==2 )
+		{
+			isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+			btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+			btVector3 edge(v2-v0);
+
+			if (info->m_edgeV2V0Angle==btScalar(0))
+			{
+				numConcaveEdgeHits++;
+			} else
+			{
+
+				bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0;
+				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+				btVector3 nA = swapFactor * tri_normal;
+				btQuaternion orn(edge,info->m_edgeV2V0Angle);
+				btVector3 computedNormalB = quatRotate(orn,tri_normal);
+				if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
+					computedNormalB*=-1;
+				btVector3 nB = swapFactor*computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+				{
+					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+				}
+#endif //DEBUG_INTERNAL_EDGE
+
+				btScalar	NdotA = localContactNormalOnB.dot(nA);
+				btScalar	NdotB = localContactNormalOnB.dot(nB);
+				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+				if (backFacingNormal)
+				{
+					numConcaveEdgeHits++;
+				}
+				else
+				{
+					numConvexEdgeHits++;
+					//				printf("hitting convex edge\n");
+
+
+					btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+					btVector3 clampedLocalNormal;
+					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal);
+					if (isClamped)
+					{
+						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+						{
+							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+							cp.m_normalWorldOnB = newNormal;
+							// Reproject collision point along normal.
+							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+						}
+					}
+				} 
+			}
+			
+
+		}
+	}
+
+#ifdef DEBUG_INTERNAL_EDGE
+	{
+		btVector3 color(0,1,1);
+		btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color);
+	}
+#endif //DEBUG_INTERNAL_EDGE
+
+	if (isNearEdge)
+	{
+
+		if (numConcaveEdgeHits>0)
+		{
+			if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0)
+			{
+				//fix tri_normal so it pointing the same direction as the current local contact normal
+				if (tri_normal.dot(localContactNormalOnB) < 0)
+				{
+					tri_normal *= -1;
+				}
+				cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal;
+			} else
+			{
+				btVector3 newNormal = tri_normal *frontFacing;
+				//if the tri_normal is pointing opposite direction as the current local contact normal, skip it
+				btScalar d = newNormal.dot(localContactNormalOnB) ;
+				if (d< 0)
+				{
+					return;
+				}
+				//modify the normal to be the triangle normal (or backfacing normal)
+				cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *newNormal;
+			}
+						
+			// Reproject collision point along normal.
+			cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+			cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+		}
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h	(revision 11817)
@@ -0,0 +1,46 @@
+
+#ifndef BT_INTERNAL_EDGE_UTILITY_H
+#define BT_INTERNAL_EDGE_UTILITY_H
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btVector3.h"
+
+#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h"
+
+///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges.
+///See also http://code.google.com/p/bullet/issues/detail?id=27
+
+class btBvhTriangleMeshShape;
+class btCollisionObject;
+class btManifoldPoint;
+class btIDebugDraw;
+
+
+
+enum btInternalEdgeAdjustFlags
+{
+	BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
+	BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
+	BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
+};
+
+
+///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
+void	btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap);
+
+
+///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
+///If this info map is missing, or the triangle is not store in this map, nothing will be done
+void	btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* trimeshColObj0,const btCollisionObject* otherColObj1, int partId0, int index0, int normalAdjustFlags = 0);
+
+///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
+///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
+//#define BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+void	btSetDebugDrawer(btIDebugDraw* debugDrawer);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+#endif //BT_INTERNAL_EDGE_UTILITY_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+
+///This is to allow MaterialCombiner/Custom Friction/Restitution values
+ContactAddedCallback		gContactAddedCallback=0;
+
+///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
+inline btScalar	calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+	btScalar friction = body0->getFriction() * body1->getFriction();
+
+	const btScalar MAX_FRICTION  = btScalar(10.);
+	if (friction < -MAX_FRICTION)
+		friction = -MAX_FRICTION;
+	if (friction > MAX_FRICTION)
+		friction = MAX_FRICTION;
+	return friction;
+
+}
+
+inline btScalar	calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+	return body0->getRestitution() * body1->getRestitution();
+}
+
+
+
+btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1)
+		:m_manifoldPtr(0),
+		m_body0(body0),
+		m_body1(body1)
+#ifdef DEBUG_PART_INDEX
+		,m_partId0(-1),
+	m_partId1(-1),
+	m_index0(-1),
+	m_index1(-1)
+#endif //DEBUG_PART_INDEX
+{
+	m_rootTransA = body0->getWorldTransform();
+	m_rootTransB = body1->getWorldTransform();
+}
+
+
+void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+{
+	btAssert(m_manifoldPtr);
+	//order in manifold needs to match
+
+//	if (depth > m_manifoldPtr->getContactBreakingThreshold())
+	if (depth > m_manifoldPtr->getContactProcessingThreshold())
+		return;
+
+	bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+
+	btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+
+	btVector3 localA;
+	btVector3 localB;
+	
+	if (isSwapped)
+	{
+		localA = m_rootTransB.invXform(pointA );
+		localB = m_rootTransA.invXform(pointInWorld);
+	} else
+	{
+		localA = m_rootTransA.invXform(pointA );
+		localB = m_rootTransB.invXform(pointInWorld);
+	}
+
+	btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+	newPt.m_positionWorldOnA = pointA;
+	newPt.m_positionWorldOnB = pointInWorld;
+	
+	int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
+
+	newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
+	newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
+
+   //BP mod, store contact triangles.
+	if (isSwapped)
+	{
+		newPt.m_partId0 = m_partId1;
+		newPt.m_partId1 = m_partId0;
+		newPt.m_index0  = m_index1;
+		newPt.m_index1  = m_index0;
+	} else
+	{
+		newPt.m_partId0 = m_partId0;
+		newPt.m_partId1 = m_partId1;
+		newPt.m_index0  = m_index0;
+		newPt.m_index1  = m_index1;
+	}
+	//printf("depth=%f\n",depth);
+	///@todo, check this for any side effects
+	if (insertIndex >= 0)
+	{
+		//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
+		m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
+	} else
+	{
+		insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
+	}
+	
+	//User can override friction and/or restitution
+	if (gContactAddedCallback &&
+		//and if either of the two bodies requires custom material
+		 ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
+		   (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
+	{
+		//experimental feature info, for per-triangle material etc.
+		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
+		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
+		(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);
+	}
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_MANIFOLD_RESULT_H
+#define BT_MANIFOLD_RESULT_H
+
+class btCollisionObject;
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btManifoldPoint;
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+#include "LinearMath/btTransform.h"
+
+typedef bool (*ContactAddedCallback)(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
+extern ContactAddedCallback		gContactAddedCallback;
+
+//#define DEBUG_PART_INDEX 1
+
+
+///btManifoldResult is a helper class to manage  contact results.
+class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
+{
+protected:
+
+	btPersistentManifold* m_manifoldPtr;
+
+	//we need this for compounds
+	btTransform	m_rootTransA;
+	btTransform	m_rootTransB;
+
+	btCollisionObject* m_body0;
+	btCollisionObject* m_body1;
+	int	m_partId0;
+	int m_partId1;
+	int m_index0;
+	int m_index1;
+	
+
+public:
+
+	btManifoldResult()
+#ifdef DEBUG_PART_INDEX
+		:
+	m_partId0(-1),
+	m_partId1(-1),
+	m_index0(-1),
+	m_index1(-1)
+#endif //DEBUG_PART_INDEX
+	{
+	}
+
+	btManifoldResult(btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btManifoldResult() {};
+
+	void	setPersistentManifold(btPersistentManifold* manifoldPtr)
+	{
+		m_manifoldPtr = manifoldPtr;
+	}
+
+	const btPersistentManifold*	getPersistentManifold() const
+	{
+		return m_manifoldPtr;
+	}
+	btPersistentManifold*	getPersistentManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+	virtual void setShapeIdentifiersA(int partId0,int index0)
+	{
+		m_partId0=partId0;
+		m_index0=index0;
+	}
+
+	virtual void setShapeIdentifiersB(	int partId1,int index1)
+	{
+		m_partId1=partId1;
+		m_index1=index1;
+	}
+
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
+
+	SIMD_FORCE_INLINE	void refreshContactPoints()
+	{
+		btAssert(m_manifoldPtr);
+		if (!m_manifoldPtr->getNumContacts())
+			return;
+
+		bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+
+		if (isSwapped)
+		{
+			m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
+		} else
+		{
+			m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
+		}
+	}
+
+	const btCollisionObject* getBody0Internal() const
+	{
+		return m_body0;
+	}
+
+	const btCollisionObject* getBody1Internal() const
+	{
+		return m_body1;
+	}
+	
+};
+
+#endif //BT_MANIFOLD_RESULT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp	(revision 11817)
@@ -0,0 +1,443 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "LinearMath/btScalar.h"
+#include "btSimulationIslandManager.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+
+btSimulationIslandManager::btSimulationIslandManager():
+m_splitIslands(true)
+{
+}
+
+btSimulationIslandManager::~btSimulationIslandManager()
+{
+}
+
+
+void btSimulationIslandManager::initUnionFind(int n)
+{
+		m_unionFind.reset(n);
+}
+		
+
+void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
+{
+	
+	{
+		btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
+		const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
+		btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
+		
+		for (int i=0;i<numOverlappingPairs;i++)
+		{
+			const btBroadphasePair& collisionPair = pairPtr[i];
+			btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+			btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+			if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
+				((colObj1) && ((colObj1)->mergesSimulationIslands())))
+			{
+
+				m_unionFind.unite((colObj0)->getIslandTag(),
+					(colObj1)->getIslandTag());
+			}
+		}
+	}
+}
+
+#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void   btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+{
+
+	// put the index into m_controllers into m_tag   
+	int index = 0;
+	{
+
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+		{
+			btCollisionObject*   collisionObject= colWorld->getCollisionObjectArray()[i];
+			//Adding filtering here
+			if (!collisionObject->isStaticOrKinematicObject())
+			{
+				collisionObject->setIslandTag(index++);
+			}
+			collisionObject->setCompanionId(-1);
+			collisionObject->setHitFraction(btScalar(1.));
+		}
+	}
+	// do the union find
+
+	initUnionFind( index );
+
+	findUnions(dispatcher,colWorld);
+}
+
+void   btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+	// put the islandId ('find' value) into m_tag   
+	{
+		int index = 0;
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+		{
+			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+			if (!collisionObject->isStaticOrKinematicObject())
+			{
+				collisionObject->setIslandTag( m_unionFind.find(index) );
+				//Set the correct object offset in Collision Object Array
+				m_unionFind.getElement(index).m_sz = i;
+				collisionObject->setCompanionId(-1);
+				index++;
+			} else
+			{
+				collisionObject->setIslandTag(-1);
+				collisionObject->setCompanionId(-2);
+			}
+		}
+	}
+}
+
+
+#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void	btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+{
+
+	initUnionFind( int (colWorld->getCollisionObjectArray().size()));
+
+	// put the index into m_controllers into m_tag	
+	{
+
+		int index = 0;
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+		{
+			btCollisionObject*	collisionObject= colWorld->getCollisionObjectArray()[i];
+			collisionObject->setIslandTag(index);
+			collisionObject->setCompanionId(-1);
+			collisionObject->setHitFraction(btScalar(1.));
+			index++;
+
+		}
+	}
+	// do the union find
+
+	findUnions(dispatcher,colWorld);
+}
+
+void	btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+	// put the islandId ('find' value) into m_tag	
+	{
+
+
+		int index = 0;
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+		{
+			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+			if (!collisionObject->isStaticOrKinematicObject())
+			{
+				collisionObject->setIslandTag( m_unionFind.find(index) );
+				collisionObject->setCompanionId(-1);
+			} else
+			{
+				collisionObject->setIslandTag(-1);
+				collisionObject->setCompanionId(-2);
+			}
+			index++;
+		}
+	}
+}
+
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+
+inline	int	getIslandId(const btPersistentManifold* lhs)
+{
+	int islandId;
+	const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
+	const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
+	islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
+	return islandId;
+
+}
+
+
+
+/// function object that routes calls to operator<
+class btPersistentManifoldSortPredicate
+{
+	public:
+
+		SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
+		{
+			return getIslandId(lhs) < getIslandId(rhs);
+		}
+};
+
+
+void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
+{
+
+	BT_PROFILE("islandUnionFindAndQuickSort");
+	
+	btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+	m_islandmanifold.resize(0);
+
+	//we are going to sort the unionfind array, and store the element id in the size
+	//afterwards, we clean unionfind, to make sure no-one uses it anymore
+	
+	getUnionFind().sortIslands();
+	int numElem = getUnionFind().getNumElements();
+
+	int endIslandIndex=1;
+	int startIslandIndex;
+
+
+	//update the sleeping state for bodies, if all are sleeping
+	for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+	{
+		int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+		for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+		{
+		}
+
+		//int numSleeping = 0;
+
+		bool allSleeping = true;
+
+		int idx;
+		for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+		{
+			int i = getUnionFind().getElement(idx).m_sz;
+
+			btCollisionObject* colObj0 = collisionObjects[i];
+			if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+			{
+//				printf("error in island management\n");
+			}
+
+			btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+			if (colObj0->getIslandTag() == islandId)
+			{
+				if (colObj0->getActivationState()== ACTIVE_TAG)
+				{
+					allSleeping = false;
+				}
+				if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
+				{
+					allSleeping = false;
+				}
+			}
+		}
+			
+
+		if (allSleeping)
+		{
+			int idx;
+			for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+			{
+				int i = getUnionFind().getElement(idx).m_sz;
+				btCollisionObject* colObj0 = collisionObjects[i];
+				if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+				{
+//					printf("error in island management\n");
+				}
+
+				btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+				if (colObj0->getIslandTag() == islandId)
+				{
+					colObj0->setActivationState( ISLAND_SLEEPING );
+				}
+			}
+		} else
+		{
+
+			int idx;
+			for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+			{
+				int i = getUnionFind().getElement(idx).m_sz;
+
+				btCollisionObject* colObj0 = collisionObjects[i];
+				if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+				{
+//					printf("error in island management\n");
+				}
+
+				btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+				if (colObj0->getIslandTag() == islandId)
+				{
+					if ( colObj0->getActivationState() == ISLAND_SLEEPING)
+					{
+						colObj0->setActivationState( WANTS_DEACTIVATION);
+						colObj0->setDeactivationTime(0.f);
+					}
+				}
+			}
+		}
+	}
+
+	
+	int i;
+	int maxNumManifolds = dispatcher->getNumManifolds();
+
+//#define SPLIT_ISLANDS 1
+//#ifdef SPLIT_ISLANDS
+
+	
+//#endif //SPLIT_ISLANDS
+
+	
+	for (i=0;i<maxNumManifolds ;i++)
+	{
+		 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+		 
+		 btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
+		 btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
+		
+		 ///@todo: check sleeping conditions!
+		 if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+			((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+		{
+		
+			//kinematic objects don't merge islands, but wake up all connected objects
+			if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+			{
+				colObj1->activate();
+			}
+			if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+			{
+				colObj0->activate();
+			}
+			if(m_splitIslands)
+			{ 
+				//filtering for response
+				if (dispatcher->needsResponse(colObj0,colObj1))
+					m_islandmanifold.push_back(manifold);
+			}
+		}
+	}
+}
+
+
+
+///@todo: this is random access, it can be walked 'cache friendly'!
+void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
+{
+	btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+	buildIslands(dispatcher,collisionWorld);
+
+	int endIslandIndex=1;
+	int startIslandIndex;
+	int numElem = getUnionFind().getNumElements();
+
+	BT_PROFILE("processIslands");
+
+	if(!m_splitIslands)
+	{
+		btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
+		int maxNumManifolds = dispatcher->getNumManifolds();
+		callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
+	}
+	else
+	{
+		// Sort manifolds, based on islands
+		// Sort the vector using predicate and std::sort
+		//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
+
+		int numManifolds = int (m_islandmanifold.size());
+
+		//we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
+		m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
+
+		//now process all active islands (sets of manifolds for now)
+
+		int startManifoldIndex = 0;
+		int endManifoldIndex = 1;
+
+		//int islandId;
+
+		
+
+	//	printf("Start Islands\n");
+
+		//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
+		for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+		{
+			int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+
+
+			   bool islandSleeping = true;
+	                
+					for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+					{
+							int i = getUnionFind().getElement(endIslandIndex).m_sz;
+							btCollisionObject* colObj0 = collisionObjects[i];
+							m_islandBodies.push_back(colObj0);
+							if (colObj0->isActive())
+									islandSleeping = false;
+					}
+	                
+
+			//find the accompanying contact manifold for this islandId
+			int numIslandManifolds = 0;
+			btPersistentManifold** startManifold = 0;
+
+			if (startManifoldIndex<numManifolds)
+			{
+				int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
+				if (curIslandId == islandId)
+				{
+					startManifold = &m_islandmanifold[startManifoldIndex];
+				
+					for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
+					{
+
+					}
+					/// Process the actual simulation, only if not sleeping/deactivated
+					numIslandManifolds = endManifoldIndex-startManifoldIndex;
+				}
+
+			}
+
+			if (!islandSleeping)
+			{
+				callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
+	//			printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
+			}
+			
+			if (numIslandManifolds)
+			{
+				startManifoldIndex = endManifoldIndex;
+			}
+
+			m_islandBodies.resize(0);
+		}
+	} // else if(!splitIslands) 
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMULATION_ISLAND_MANAGER_H
+#define BT_SIMULATION_ISLAND_MANAGER_H
+
+#include "BulletCollision/CollisionDispatch/btUnionFind.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btCollisionObject.h"
+
+class btCollisionObject;
+class btCollisionWorld;
+class btDispatcher;
+class btPersistentManifold;
+
+
+///SimulationIslandManager creates and handles simulation islands, using btUnionFind
+class btSimulationIslandManager
+{
+	btUnionFind m_unionFind;
+
+	btAlignedObjectArray<btPersistentManifold*>  m_islandmanifold;
+	btAlignedObjectArray<btCollisionObject* >  m_islandBodies;
+	
+	bool m_splitIslands;
+	
+public:
+	btSimulationIslandManager();
+	virtual ~btSimulationIslandManager();
+
+
+	void initUnionFind(int n);	
+	
+		
+	btUnionFind& getUnionFind() { return m_unionFind;}
+
+	virtual	void	updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
+	virtual	void	storeIslandActivationState(btCollisionWorld* world);
+
+
+	void	findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+	
+
+	struct	IslandCallback
+	{
+		virtual ~IslandCallback() {};
+
+		virtual	void	ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold**	manifolds,int numManifolds, int islandId) = 0;
+	};
+
+	void	buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback);
+
+	void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+	bool getSplitIslands()
+	{
+		return m_splitIslands;
+	}
+	void setSplitIslands(bool doSplitIslands)
+	{
+		m_splitIslands = doSplitIslands;
+	}
+
+};
+
+#endif //BT_SIMULATION_ISLAND_MANAGER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,260 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+//#include <stdio.h>
+
+btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,col0,col1),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+	btCollisionObject* sphereObj = m_isSwapped? col1 : col0;
+	btCollisionObject* boxObj = m_isSwapped? col0 : col1;
+	
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
+		m_ownManifold = true;
+	}
+}
+
+
+btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+
+
+void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)dispatchInfo;
+	(void)resultOut;
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
+	btCollisionObject* boxObj = m_isSwapped? body0 : body1;
+
+
+	btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
+
+	btVector3 normalOnSurfaceB;
+	btVector3 pOnBox,pOnSphere;
+	btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin();
+	btScalar radius = sphere0->getRadius();
+	
+	btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
+
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	if (dist < SIMD_EPSILON)
+	{
+		btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
+
+		/// report a contact. internally this will be kept persistent, and contact reduction is done
+
+		resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
+		
+	}
+
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr->getNumContacts())
+		{
+			resultOut->refreshContactPoints();
+		}
+	}
+
+}
+
+btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	(void)col0;
+	(void)col1;
+
+	//not yet
+	return btScalar(1.);
+}
+
+
+btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius ) 
+{
+
+	btScalar margins;
+	btVector3 bounds[2];
+	btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
+	
+	bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
+	bounds[1] = boxShape->getHalfExtentsWithoutMargin();
+
+	margins = boxShape->getMargin();//also add sphereShape margin?
+
+	const btTransform&	m44T = boxObj->getWorldTransform();
+
+	btVector3	boundsVec[2];
+	btScalar	fPenetration;
+
+	boundsVec[0] = bounds[0];
+	boundsVec[1] = bounds[1];
+
+	btVector3	marginsVec( margins, margins, margins );
+
+	// add margins
+	bounds[0] += marginsVec;
+	bounds[1] -= marginsVec;
+
+	/////////////////////////////////////////////////
+
+	btVector3	tmp, prel, n[6], normal, v3P;
+	btScalar   fSep = btScalar(10000000.0), fSepThis;
+
+	n[0].setValue( btScalar(-1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[1].setValue(  btScalar(0.0), btScalar(-1.0),  btScalar(0.0) );
+	n[2].setValue(  btScalar(0.0),  btScalar(0.0), btScalar(-1.0) );
+	n[3].setValue(  btScalar(1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[4].setValue(  btScalar(0.0),  btScalar(1.0),  btScalar(0.0) );
+	n[5].setValue(  btScalar(0.0),  btScalar(0.0),  btScalar(1.0) );
+
+	// convert  point in local space
+	prel = m44T.invXform( sphereCenter);
+	
+	bool	bFound = false;
+
+	v3P = prel;
+
+	for (int i=0;i<6;i++)
+	{
+		int j = i<3? 0:1;
+		if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) )
+		{
+			v3P = v3P - n[i]*fSepThis;		
+			bFound = true;
+		}
+	}
+	
+	//
+
+	if ( bFound )
+	{
+		bounds[0] = boundsVec[0];
+		bounds[1] = boundsVec[1];
+
+		normal = (prel - v3P).normalize();
+		pointOnBox = v3P + normal*margins;
+		v3PointOnSphere = prel - normal*fRadius;
+
+		if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) )
+		{
+			return btScalar(1.0);
+		}
+
+		// transform back in world space
+		tmp = m44T( pointOnBox);
+		pointOnBox    = tmp;
+		tmp  = m44T( v3PointOnSphere);		
+		v3PointOnSphere = tmp;
+		btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2();
+		
+		//if this fails, fallback into deeper penetration case, below
+		if (fSeps2 > SIMD_EPSILON)
+		{
+			fSep = - btSqrt(fSeps2);
+			normal = (pointOnBox-v3PointOnSphere);
+			normal *= btScalar(1.)/fSep;
+		}
+
+		return fSep;
+	}
+
+	//////////////////////////////////////////////////
+	// Deep penetration case
+
+	fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] );
+
+	bounds[0] = boundsVec[0];
+	bounds[1] = boundsVec[1];
+
+	if ( fPenetration <= btScalar(0.0) )
+		return (fPenetration-margins);
+	else
+		return btScalar(1.0);
+}
+
+btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax) 
+{
+
+	btVector3 bounds[2];
+
+	bounds[0] = aabbMin;
+	bounds[1] = aabbMax;
+
+	btVector3	p0, tmp, prel, n[6], normal;
+	btScalar   fSep = btScalar(-10000000.0), fSepThis;
+
+	// set p0 and normal to a default value to shup up GCC
+	p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+	normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+
+	n[0].setValue( btScalar(-1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[1].setValue(  btScalar(0.0), btScalar(-1.0),  btScalar(0.0) );
+	n[2].setValue(  btScalar(0.0),  btScalar(0.0), btScalar(-1.0) );
+	n[3].setValue(  btScalar(1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[4].setValue(  btScalar(0.0),  btScalar(1.0),  btScalar(0.0) );
+	n[5].setValue(  btScalar(0.0),  btScalar(0.0),  btScalar(1.0) );
+
+	const btTransform&	m44T = boxObj->getWorldTransform();
+
+	// convert  point in local space
+	prel = m44T.invXform( sphereCenter);
+
+	///////////
+
+	for (int i=0;i<6;i++)
+	{
+		int j = i<3 ? 0:1;
+		if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) )	return btScalar(1.0);
+		if ( fSepThis > fSep )
+		{
+			p0 = bounds[j];	normal = (btVector3&)n[i];
+			fSep = fSepThis;
+		}
+	}
+
+	pointOnBox = prel - normal*(normal.dot((prel-p0)));
+	v3PointOnSphere = pointOnBox + normal*fSep;
+
+	// transform back in world space
+	tmp  = m44T( pointOnBox);		
+	pointOnBox    = tmp;
+	tmp  = m44T( v3PointOnSphere);		v3PointOnSphere = tmp;
+	normal = (pointOnBox-v3PointOnSphere).normalize();
+
+	return fSep;
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool	m_isSwapped;
+	
+public:
+
+	btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+
+	virtual ~btSphereBoxCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+	btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
+
+	btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
+	
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
+			if (!m_swapped)
+			{
+				return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
+			} else
+			{
+				return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
+			}
+		}
+	};
+
+};
+
+#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereSphereCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1)
+: btActivatingCollisionAlgorithm(ci,col0,col1),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+	if (!m_manifoldPtr)
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
+		m_ownManifold = true;
+	}
+}
+
+btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)dispatchInfo;
+
+	if (!m_manifoldPtr)
+		return;
+
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
+	btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
+
+	btVector3 diff = col0->getWorldTransform().getOrigin()-  col1->getWorldTransform().getOrigin();
+	btScalar len = diff.length();
+	btScalar radius0 = sphere0->getRadius();
+	btScalar radius1 = sphere1->getRadius();
+
+#ifdef CLEAR_MANIFOLD
+	m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
+#endif
+
+	///iff distance positive, don't generate a new contact
+	if ( len > (radius0+radius1))
+	{
+#ifndef CLEAR_MANIFOLD
+		resultOut->refreshContactPoints();
+#endif //CLEAR_MANIFOLD
+		return;
+	}
+	///distance (negative means penetration)
+	btScalar dist = len - (radius0+radius1);
+
+	btVector3 normalOnSurfaceB(1,0,0);
+	if (len > SIMD_EPSILON)
+	{
+		normalOnSurfaceB = diff / len;
+	}
+
+	///point on A (worldspace)
+	///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
+	///point on B (worldspace)
+	btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
+
+	/// report a contact. internally this will be kept persistent, and contact reduction is done
+	
+	
+	resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
+
+#ifndef CLEAR_MANIFOLD
+	resultOut->refreshContactPoints();
+#endif //CLEAR_MANIFOLD
+
+}
+
+btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)col0;
+	(void)col1;
+	(void)dispatchInfo;
+	(void)resultOut;
+
+	//not yet
+	return btScalar(1.);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+class btPersistentManifold;
+
+/// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	
+public:
+	btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+	
+	virtual ~btSphereSphereCollisionAlgorithm();
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
+			return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
+		}
+	};
+
+};
+
+#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "SphereTriangleDetector.h"
+
+
+btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped)
+: btActivatingCollisionAlgorithm(ci,col0,col1),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_swapped(swapped)
+{
+	if (!m_manifoldPtr)
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
+		m_ownManifold = true;
+	}
+}
+
+btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject* sphereObj = m_swapped? col1 : col0;
+	btCollisionObject* triObj = m_swapped? col0 : col1;
+
+	btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
+	btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
+	
+	/// report a contact. internally this will be kept persistent, and contact reduction is done
+	resultOut->setPersistentManifold(m_manifoldPtr);
+	SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold());
+	
+	btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+	input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
+	input.m_transformA = sphereObj->getWorldTransform();
+	input.m_transformB = triObj->getWorldTransform();
+
+	bool swapResults = m_swapped;
+
+	detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
+
+	if (m_ownManifold)
+		resultOut->refreshContactPoints();
+	
+}
+
+btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	(void)col0;
+	(void)col1;
+
+	//not yet
+	return btScalar(1.);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+/// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool	m_swapped;
+	
+public:
+	btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped);
+
+	btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+	
+	virtual ~btSphereTriangleCollisionAlgorithm();
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
+
+			return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
+		}
+	};
+
+};
+
+#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btUnionFind.h"
+
+
+
+btUnionFind::~btUnionFind()
+{
+	Free();
+
+}
+
+btUnionFind::btUnionFind()
+{ 
+
+}
+
+void	btUnionFind::allocate(int N)
+{
+	m_elements.resize(N);
+}
+void	btUnionFind::Free()
+{
+	m_elements.clear();
+}
+
+
+void	btUnionFind::reset(int N)
+{
+	allocate(N);
+
+	for (int i = 0; i < N; i++) 
+	{ 
+		m_elements[i].m_id = i; m_elements[i].m_sz = 1; 
+	} 
+}
+
+
+class btUnionFindElementSortPredicate
+{
+	public:
+
+		bool operator() ( const btElement& lhs, const btElement& rhs )
+		{
+			return lhs.m_id < rhs.m_id;
+		}
+};
+
+///this is a special operation, destroying the content of btUnionFind.
+///it sorts the elements, based on island id, in order to make it easy to iterate over islands
+void	btUnionFind::sortIslands()
+{
+
+	//first store the original body index, and islandId
+	int numElements = m_elements.size();
+	
+	for (int i=0;i<numElements;i++)
+	{
+		m_elements[i].m_id = find(i);
+#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+		m_elements[i].m_sz = i;
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+	}
+	
+	 // Sort the vector using predicate and std::sort
+	  //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
+	  m_elements.quickSort(btUnionFindElementSortPredicate());
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btUnionFind.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionDispatch/btUnionFind.h	(revision 11817)
@@ -0,0 +1,129 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_UNION_FIND_H
+#define BT_UNION_FIND_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#define USE_PATH_COMPRESSION 1
+
+///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
+#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
+
+struct	btElement
+{
+	int	m_id;
+	int	m_sz;
+};
+
+///UnionFind calculates connected subsets
+// Implements weighted Quick Union with path compression
+// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
+class btUnionFind
+  {
+    private:
+		btAlignedObjectArray<btElement>	m_elements;
+
+    public:
+	  
+		btUnionFind();
+		~btUnionFind();
+
+	
+		//this is a special operation, destroying the content of btUnionFind.
+		//it sorts the elements, based on island id, in order to make it easy to iterate over islands
+		void	sortIslands();
+
+	  void	reset(int N);
+
+	  SIMD_FORCE_INLINE int	getNumElements() const
+	  {
+		  return int(m_elements.size());
+	  }
+	  SIMD_FORCE_INLINE bool  isRoot(int x) const
+	  {
+		  return (x == m_elements[x].m_id);
+	  }
+
+	  btElement&	getElement(int index)
+	  {
+		  return m_elements[index];
+	  }
+	  const btElement& getElement(int index) const
+	  {
+		  return m_elements[index];
+	  }
+   
+	  void	allocate(int N);
+	  void	Free();
+
+
+
+
+	  int find(int p, int q)
+		{ 
+			return (find(p) == find(q)); 
+		}
+
+		void unite(int p, int q)
+		{
+			int i = find(p), j = find(q);
+			if (i == j) 
+				return;
+
+#ifndef USE_PATH_COMPRESSION
+			//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
+			if (m_elements[i].m_sz < m_elements[j].m_sz)
+			{ 
+				m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; 
+			}
+			else 
+			{ 
+				m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz; 
+			}
+#else
+			m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; 
+#endif //USE_PATH_COMPRESSION
+		}
+
+		int find(int x)
+		{ 
+			//btAssert(x < m_N);
+			//btAssert(x >= 0);
+
+			while (x != m_elements[x].m_id) 
+			{
+		//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
+	
+		#ifdef USE_PATH_COMPRESSION
+				const btElement* elementPtr = &m_elements[m_elements[x].m_id];
+				m_elements[x].m_id = elementPtr->m_id;
+				x = elementPtr->m_id;			
+		#else//
+				x = m_elements[x].m_id;
+		#endif		
+				//btAssert(x < m_N);
+				//btAssert(x >= 0);
+
+			}
+			return x; 
+		}
+
+
+  };
+
+
+#endif //BT_UNION_FIND_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBox2dShape.h"
+
+
+//{ 
+
+
+void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+
+void	btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//btScalar margin = btScalar(0.);
+	btVector3 halfExtents = getHalfExtentsWithMargin();
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBox2dShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBox2dShape.h	(revision 11817)
@@ -0,0 +1,363 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OBB_BOX_2D_SHAPE_H
+#define BT_OBB_BOX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
+class btBox2dShape: public btPolyhedralConvexShape
+{
+
+	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+	btVector3 m_centroid;
+	btVector3 m_vertices[4];
+	btVector3 m_normals[4];
+
+public:
+
+	btVector3 getHalfExtentsWithMargin() const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		return halfExtents;
+	}
+	
+	const btVector3& getHalfExtentsWithoutMargin() const
+	{
+		return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+	}
+	
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	SIMD_FORCE_INLINE  btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+	
+		for (int i=0;i<numVectors;i++)
+		{
+			const btVector3& vec = vectors[i];
+			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+				btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+				btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); 
+		}
+
+	}
+
+
+	btBox2dShape( const btVector3& boxHalfExtents) 
+		: btPolyhedralConvexShape(),
+		m_centroid(0,0,0)
+	{
+		m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
+		m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
+		m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+		m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+
+		m_normals[0].setValue(0,-1,0);
+		m_normals[1].setValue(1,0,0);
+		m_normals[2].setValue(0,1,0);
+		m_normals[3].setValue(-1,0,0);
+
+		m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+	};
+
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+
+
+
+	int	getVertexCount() const
+	{
+		return 4;
+	}
+
+	virtual int getNumVertices()const
+	{
+		return 4;
+	}
+
+	const btVector3* getVertices() const
+	{
+		return &m_vertices[0];
+	}
+
+	const btVector3* getNormals() const
+	{
+		return &m_normals[0];
+	}
+
+
+
+
+
+
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+	{
+		//this plane might not be aligned...
+		btVector4 plane ;
+		getPlaneEquation(plane,i);
+		planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+		planeSupport = localGetSupportingVertex(-planeNormal);
+	}
+
+
+	const btVector3& getCentroid() const
+	{
+		return m_centroid;
+	}
+	
+	virtual int getNumPlanes() const
+	{
+		return 6;
+	}	
+	
+	
+
+	virtual int getNumEdges() const
+	{
+		return 12;
+	}
+
+
+	virtual void getVertex(int i,btVector3& vtx) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		vtx = btVector3(
+				halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
+				halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
+				halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+	}
+	
+
+	virtual void	getPlaneEquation(btVector4& plane,int i) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		switch (i)
+		{
+		case 0:
+			plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 1:
+			plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 2:
+			plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 3:
+			plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 4:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
+			break;
+		case 5:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+	
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+	//virtual void getEdge(int i,Edge& edge) const
+	{
+		int edgeVert0 = 0;
+		int edgeVert1 = 0;
+
+		switch (i)
+		{
+		case 0:
+				edgeVert0 = 0;
+				edgeVert1 = 1;
+			break;
+		case 1:
+				edgeVert0 = 0;
+				edgeVert1 = 2;
+			break;
+		case 2:
+			edgeVert0 = 1;
+			edgeVert1 = 3;
+
+			break;
+		case 3:
+			edgeVert0 = 2;
+			edgeVert1 = 3;
+			break;
+		case 4:
+			edgeVert0 = 0;
+			edgeVert1 = 4;
+			break;
+		case 5:
+			edgeVert0 = 1;
+			edgeVert1 = 5;
+
+			break;
+		case 6:
+			edgeVert0 = 2;
+			edgeVert1 = 6;
+			break;
+		case 7:
+			edgeVert0 = 3;
+			edgeVert1 = 7;
+			break;
+		case 8:
+			edgeVert0 = 4;
+			edgeVert1 = 5;
+			break;
+		case 9:
+			edgeVert0 = 4;
+			edgeVert1 = 6;
+			break;
+		case 10:
+			edgeVert0 = 5;
+			edgeVert1 = 7;
+			break;
+		case 11:
+			edgeVert0 = 6;
+			edgeVert1 = 7;
+			break;
+		default:
+			btAssert(0);
+
+		}
+
+		getVertex(edgeVert0,pa );
+		getVertex(edgeVert1,pb );
+	}
+
+
+
+
+	
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		//btScalar minDist = 2*tolerance;
+		
+		bool result =	(pt.x() <= (halfExtents.x()+tolerance)) &&
+						(pt.x() >= (-halfExtents.x()-tolerance)) &&
+						(pt.y() <= (halfExtents.y()+tolerance)) &&
+						(pt.y() >= (-halfExtents.y()-tolerance)) &&
+						(pt.z() <= (halfExtents.z()+tolerance)) &&
+						(pt.z() >= (-halfExtents.z()-tolerance));
+		
+		return result;
+	}
+
+
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "Box2d";
+	}
+
+	virtual int		getNumPreferredPenetrationDirections() const
+	{
+		return 6;
+	}
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+	{
+		switch (index)
+		{
+		case 0:
+			penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
+			break;
+		case 1:
+			penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
+			break;
+		case 2:
+			penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
+			break;
+		case 3:
+			penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
+			break;
+		case 4:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
+			break;
+		case 5:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+};
+
+#endif //BT_OBB_BOX_2D_SHAPE_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp	(revision 11817)
@@ -0,0 +1,41 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "btBoxShape.h"
+
+
+//{ 
+
+
+void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+
+void	btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//btScalar margin = btScalar(0.);
+	btVector3 halfExtents = getHalfExtentsWithMargin();
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBoxShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBoxShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBoxShape.h	(revision 11817)
@@ -0,0 +1,318 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OBB_BOX_MINKOWSKI_H
+#define BT_OBB_BOX_MINKOWSKI_H
+
+#include "btPolyhedralConvexShape.h"
+#include "btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
+class btBoxShape: public btPolyhedralConvexShape
+{
+
+	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+
+public:
+
+	btVector3 getHalfExtentsWithMargin() const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		return halfExtents;
+	}
+	
+	const btVector3& getHalfExtentsWithoutMargin() const
+	{
+		return m_implicitShapeDimensions;//scaling is included, margin is not
+	}
+	
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	SIMD_FORCE_INLINE  btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+	
+		for (int i=0;i<numVectors;i++)
+		{
+			const btVector3& vec = vectors[i];
+			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+				btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+				btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); 
+		}
+
+	}
+
+
+	btBoxShape( const btVector3& boxHalfExtents) 
+		: btPolyhedralConvexShape()
+	{
+		m_shapeType = BOX_SHAPE_PROXYTYPE;
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+	};
+
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+	{
+		//this plane might not be aligned...
+		btVector4 plane ;
+		getPlaneEquation(plane,i);
+		planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+		planeSupport = localGetSupportingVertex(-planeNormal);
+	}
+
+	
+	virtual int getNumPlanes() const
+	{
+		return 6;
+	}	
+	
+	virtual int	getNumVertices() const 
+	{
+		return 8;
+	}
+
+	virtual int getNumEdges() const
+	{
+		return 12;
+	}
+
+
+	virtual void getVertex(int i,btVector3& vtx) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithMargin();
+
+		vtx = btVector3(
+				halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
+				halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
+				halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+	}
+	
+
+	virtual void	getPlaneEquation(btVector4& plane,int i) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		switch (i)
+		{
+		case 0:
+			plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 1:
+			plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 2:
+			plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 3:
+			plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 4:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
+			break;
+		case 5:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+	
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+	//virtual void getEdge(int i,Edge& edge) const
+	{
+		int edgeVert0 = 0;
+		int edgeVert1 = 0;
+
+		switch (i)
+		{
+		case 0:
+				edgeVert0 = 0;
+				edgeVert1 = 1;
+			break;
+		case 1:
+				edgeVert0 = 0;
+				edgeVert1 = 2;
+			break;
+		case 2:
+			edgeVert0 = 1;
+			edgeVert1 = 3;
+
+			break;
+		case 3:
+			edgeVert0 = 2;
+			edgeVert1 = 3;
+			break;
+		case 4:
+			edgeVert0 = 0;
+			edgeVert1 = 4;
+			break;
+		case 5:
+			edgeVert0 = 1;
+			edgeVert1 = 5;
+
+			break;
+		case 6:
+			edgeVert0 = 2;
+			edgeVert1 = 6;
+			break;
+		case 7:
+			edgeVert0 = 3;
+			edgeVert1 = 7;
+			break;
+		case 8:
+			edgeVert0 = 4;
+			edgeVert1 = 5;
+			break;
+		case 9:
+			edgeVert0 = 4;
+			edgeVert1 = 6;
+			break;
+		case 10:
+			edgeVert0 = 5;
+			edgeVert1 = 7;
+			break;
+		case 11:
+			edgeVert0 = 6;
+			edgeVert1 = 7;
+			break;
+		default:
+			btAssert(0);
+
+		}
+
+		getVertex(edgeVert0,pa );
+		getVertex(edgeVert1,pb );
+	}
+
+
+
+
+	
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		//btScalar minDist = 2*tolerance;
+		
+		bool result =	(pt.x() <= (halfExtents.x()+tolerance)) &&
+						(pt.x() >= (-halfExtents.x()-tolerance)) &&
+						(pt.y() <= (halfExtents.y()+tolerance)) &&
+						(pt.y() >= (-halfExtents.y()-tolerance)) &&
+						(pt.z() <= (halfExtents.z()+tolerance)) &&
+						(pt.z() >= (-halfExtents.z()-tolerance));
+		
+		return result;
+	}
+
+
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "Box";
+	}
+
+	virtual int		getNumPreferredPenetrationDirections() const
+	{
+		return 6;
+	}
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+	{
+		switch (index)
+		{
+		case 0:
+			penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
+			break;
+		case 1:
+			penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
+			break;
+		case 2:
+			penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
+			break;
+		case 3:
+			penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
+			break;
+		case 4:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
+			break;
+		case 5:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+};
+
+
+#endif //BT_OBB_BOX_MINKOWSKI_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp	(revision 11817)
@@ -0,0 +1,466 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#define DISABLE_BVH
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+#include "LinearMath/btSerializer.h"
+
+///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
+///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_triangleInfoMap(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
+{
+	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	//construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+	if (buildBvh)
+	{
+		buildOptimizedBvh();
+	}
+
+#endif //DISABLE_BVH
+
+}
+
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_triangleInfoMap(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
+{
+	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	//construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+	if (buildBvh)
+	{
+		void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+		m_bvh = new (mem) btOptimizedBvh();
+		
+		m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+		m_ownsBvh = true;
+	}
+
+#endif //DISABLE_BVH
+
+}
+
+void	btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
+	
+	m_localAabbMin.setMin(aabbMin);
+	m_localAabbMax.setMax(aabbMax);
+}
+
+
+void	btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
+	
+	recalcLocalAabb();
+}
+
+btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
+{
+	if (m_ownsBvh)
+	{
+		m_bvh->~btOptimizedBvh();
+		btAlignedFree(m_bvh);
+	}
+}
+
+void	btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
+{
+	struct	MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btStridingMeshInterface*	m_meshInterface;
+		btTriangleCallback* m_callback;
+
+		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+			:m_meshInterface(meshInterface),
+			m_callback(callback)
+		{
+		}
+				
+		virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+		{
+			btVector3 m_triangle[3];
+			const unsigned char *vertexbase;
+			int numverts;
+			PHY_ScalarType type;
+			int stride;
+			const unsigned char *indexbase;
+			int indexstride;
+			int numfaces;
+			PHY_ScalarType indicestype;
+
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,
+				numverts,
+				type,
+				stride,
+				&indexbase,
+				indexstride,
+				numfaces,
+				indicestype,
+				nodeSubPart);
+
+			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+	
+			const btVector3& meshScaling = m_meshInterface->getScaling();
+			for (int j=2;j>=0;j--)
+			{
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+				
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());		
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());		
+				}
+			}
+
+			/* Perform ray vs. triangle collision here */
+			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+		}
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface);
+
+	m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
+}
+
+void	btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+	struct	MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btStridingMeshInterface*	m_meshInterface;
+		btTriangleCallback* m_callback;
+
+		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+			:m_meshInterface(meshInterface),
+			m_callback(callback)
+		{
+		}
+				
+		virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+		{
+			btVector3 m_triangle[3];
+			const unsigned char *vertexbase;
+			int numverts;
+			PHY_ScalarType type;
+			int stride;
+			const unsigned char *indexbase;
+			int indexstride;
+			int numfaces;
+			PHY_ScalarType indicestype;
+
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,
+				numverts,
+				type,
+				stride,
+				&indexbase,
+				indexstride,
+				numfaces,
+				indicestype,
+				nodeSubPart);
+
+			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+	
+			const btVector3& meshScaling = m_meshInterface->getScaling();
+			for (int j=2;j>=0;j--)
+			{
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+
+					m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());		
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());		
+				}
+			}
+
+			/* Perform ray vs. triangle collision here */
+			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+		}
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface);
+
+	m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
+}
+
+//perform bvh tree traversal and report overlapping triangles to 'callback'
+void	btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+#ifdef DISABLE_BVH
+	//brute force traverse all triangles
+	btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
+#else
+
+	//first get all the nodes
+
+	
+	struct	MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btStridingMeshInterface*	m_meshInterface;
+		btTriangleCallback*		m_callback;
+		btVector3				m_triangle[3];
+
+
+		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+			:m_meshInterface(meshInterface),
+			m_callback(callback)
+		{
+		}
+				
+		virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+		{
+			const unsigned char *vertexbase;
+			int numverts;
+			PHY_ScalarType type;
+			int stride;
+			const unsigned char *indexbase;
+			int indexstride;
+			int numfaces;
+			PHY_ScalarType indicestype;
+			
+
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,
+				numverts,
+				type,
+				stride,
+				&indexbase,
+				indexstride,
+				numfaces,
+				indicestype,
+				nodeSubPart);
+
+			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT||indicestype==PHY_UCHAR);
+	
+			const btVector3& meshScaling = m_meshInterface->getScaling();
+			for (int j=2;j>=0;j--)
+			{
+				
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:indicestype==PHY_INTEGER?gfxbase[j]:((unsigned char*)gfxbase)[j];
+
+
+#ifdef DEBUG_TRIANGLE_MESH
+				printf("%d ,",graphicsindex);
+#endif //DEBUG_TRIANGLE_MESH
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(
+																		graphicsbase[0]*meshScaling.getX(),
+																		graphicsbase[1]*meshScaling.getY(),
+																		graphicsbase[2]*meshScaling.getZ());
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+
+					m_triangle[j] = btVector3(
+						btScalar(graphicsbase[0])*meshScaling.getX(),
+						btScalar(graphicsbase[1])*meshScaling.getY(),
+						btScalar(graphicsbase[2])*meshScaling.getZ());
+				}
+#ifdef DEBUG_TRIANGLE_MESH
+				printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
+#endif //DEBUG_TRIANGLE_MESH
+			}
+
+			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+		}
+
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface);
+
+	m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+
+
+#endif//DISABLE_BVH
+
+
+}
+
+void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+   if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+   {
+      btTriangleMeshShape::setLocalScaling(scaling);
+	  buildOptimizedBvh();
+   }
+}
+
+void   btBvhTriangleMeshShape::buildOptimizedBvh()
+{
+	if (m_ownsBvh)
+	{
+		m_bvh->~btOptimizedBvh();
+		btAlignedFree(m_bvh);
+	}
+	///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
+	void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+	m_bvh = new(mem) btOptimizedBvh();
+	//rebuild the bvh...
+	m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
+	m_ownsBvh = true;
+}
+
+void   btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
+{
+   btAssert(!m_bvh);
+   btAssert(!m_ownsBvh);
+
+   m_bvh = bvh;
+   m_ownsBvh = false;
+   // update the scaling without rebuilding the bvh
+   if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+   {
+      btTriangleMeshShape::setLocalScaling(scaling);
+   }
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
+
+	btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
+
+	m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
+
+	trimeshData->m_collisionMargin = float(m_collisionMargin);
+
+	
+
+	if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
+	{
+		void* chunk = serializer->findPointer(m_bvh);
+		if (chunk)
+		{
+#ifdef BT_USE_DOUBLE_PRECISION
+			trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
+			trimeshData->m_quantizedFloatBvh = 0;
+#else
+			trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)chunk;
+			trimeshData->m_quantizedDoubleBvh= 0;
+#endif //BT_USE_DOUBLE_PRECISION
+		} else
+		{
+
+#ifdef BT_USE_DOUBLE_PRECISION
+			trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+			trimeshData->m_quantizedFloatBvh = 0;
+#else
+			trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+			trimeshData->m_quantizedDoubleBvh= 0;
+#endif //BT_USE_DOUBLE_PRECISION
+	
+			int sz = m_bvh->calculateSerializeBufferSizeNew();
+			btChunk* chunk = serializer->allocate(sz,1);
+			const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+			serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
+		}
+	} else
+	{
+		trimeshData->m_quantizedFloatBvh = 0;
+		trimeshData->m_quantizedDoubleBvh = 0;
+	}
+
+	
+
+	if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
+	{
+		void* chunk = serializer->findPointer(m_triangleInfoMap);
+		if (chunk)
+		{
+			trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
+		} else
+		{
+			trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
+			int sz = m_triangleInfoMap->calculateSerializeBufferSize();
+			btChunk* chunk = serializer->allocate(sz,1);
+			const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+			serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
+		}
+	} else
+	{
+		trimeshData->m_triangleInfoMap = 0;
+	}
+
+	return "btTriangleMeshShapeData";
+}
+
+void	btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
+{
+	if (m_bvh)
+	{
+		int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
+		btChunk* chunk = serializer->allocate(len,1);
+		const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+		serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
+	}
+}
+
+void	btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
+{
+	if (m_triangleInfoMap)
+	{
+		int len = m_triangleInfoMap->calculateSerializeBufferSize();
+		btChunk* chunk = serializer->allocate(len,1);
+		const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+		serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
+	}
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h	(revision 11817)
@@ -0,0 +1,139 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BVH_TRIANGLE_MESH_SHAPE_H
+#define BT_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "btTriangleMeshShape.h"
+#include "btOptimizedBvh.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "btTriangleInfoMap.h"
+
+///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage.
+///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
+///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
+///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
+ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
+{
+
+	btOptimizedBvh*	m_bvh;
+	btTriangleInfoMap*	m_triangleInfoMap;
+
+	bool m_useQuantizedAabbCompression;
+	bool m_ownsBvh;
+	bool m_pad[11];////need padding due to alignment
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	
+	btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
+
+	///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+	btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
+	
+	virtual ~btBvhTriangleMeshShape();
+
+	bool getOwnsBvh () const
+	{
+		return m_ownsBvh;
+	}
+
+
+	
+	void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
+	void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	void	refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+
+	///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
+	void	partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+
+	//debugging
+	virtual const char*	getName()const {return "BVHTRIANGLEMESH";}
+
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	
+	btOptimizedBvh*	getOptimizedBvh()
+	{
+		return m_bvh;
+	}
+
+	void	setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
+
+	void    buildOptimizedBvh();
+
+	bool	usesQuantizedAabbCompression() const
+	{
+		return	m_useQuantizedAabbCompression;
+	}
+
+	void	setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap)
+	{
+		m_triangleInfoMap = triangleInfoMap;
+	}
+
+	const btTriangleInfoMap*	getTriangleInfoMap() const
+	{
+		return m_triangleInfoMap;
+	}
+	
+	btTriangleInfoMap*	getTriangleInfoMap()
+	{
+		return m_triangleInfoMap;
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	virtual void	serializeSingleBvh(btSerializer* serializer) const;
+
+	virtual void	serializeSingleTriangleInfoMap(btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btTriangleMeshShapeData
+{
+	btCollisionShapeData	m_collisionShapeData;
+
+	btStridingMeshInterfaceData m_meshInterface;
+
+	btQuantizedBvhFloatData		*m_quantizedFloatBvh;
+	btQuantizedBvhDoubleData	*m_quantizedDoubleBvh;
+
+	btTriangleInfoMapData	*m_triangleInfoMap;
+	
+	float	m_collisionMargin;
+
+	char m_pad3[4];
+	
+};
+
+
+SIMD_FORCE_INLINE	int	btBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btTriangleMeshShapeData);
+}
+
+
+
+#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp	(revision 11817)
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btCapsuleShape.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+
+btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
+{
+	m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
+	m_upAxis = 1;
+	m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
+}
+
+ 
+ btVector3	btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+
+	btVector3 supVec(0,0,0);
+
+	btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	btVector3 vtx;
+	btScalar newDot;
+	
+	btScalar radius = getRadius();
+
+
+	{
+		btVector3 pos(0,0,0);
+		pos[getUpAxis()] = getHalfHeight();
+
+		vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+	{
+		btVector3 pos(0,0,0);
+		pos[getUpAxis()] = -getHalfHeight();
+
+		vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+
+	return supVec;
+
+}
+
+ void	btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+
+	
+	btScalar radius = getRadius();
+
+	for (int j=0;j<numVectors;j++)
+	{
+		btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+		const btVector3& vec = vectors[j];
+
+		btVector3 vtx;
+		btScalar newDot;
+		{
+			btVector3 pos(0,0,0);
+			pos[getUpAxis()] = getHalfHeight();
+			vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supportVerticesOut[j] = vtx;
+			}
+		}
+		{
+			btVector3 pos(0,0,0);
+			pos[getUpAxis()] = -getHalfHeight();
+			vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supportVerticesOut[j] = vtx;
+			}
+		}
+		
+	}
+}
+
+
+void	btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//as an approximation, take the inertia of the box that bounds the spheres
+
+	btTransform ident;
+	ident.setIdentity();
+
+	
+	btScalar radius = getRadius();
+
+	btVector3 halfExtents(radius,radius,radius);
+	halfExtents[getUpAxis()]+=getHalfHeight();
+
+	btScalar margin = CONVEX_DISTANCE_MARGIN;
+
+	btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
+	btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
+	btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(.08333333);
+
+	inertia[0] = scaledmass * (y2+z2);
+	inertia[1] = scaledmass * (x2+z2);
+	inertia[2] = scaledmass * (x2+y2);
+
+}
+
+btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
+{
+	m_upAxis = 0;
+	m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
+}
+
+
+
+
+
+
+btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
+{
+	m_upAxis = 2;
+	m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h	(revision 11817)
@@ -0,0 +1,173 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CAPSULE_SHAPE_H
+#define BT_CAPSULE_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
+///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
+class btCapsuleShape : public btConvexInternalShape
+{
+protected:
+	int	m_upAxis;
+
+protected:
+	///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
+	btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
+
+public:
+	btCapsuleShape(btScalar radius,btScalar height);
+
+	///CollisionShape Interface
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	/// btConvexShape Interface
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+
+	virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+	{
+			btVector3 halfExtents(getRadius(),getRadius(),getRadius());
+			halfExtents[m_upAxis] = getRadius() + getHalfHeight();
+			halfExtents += btVector3(getMargin(),getMargin(),getMargin());
+			btMatrix3x3 abs_b = t.getBasis().absolute();  
+			btVector3 center = t.getOrigin();
+			btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));		  
+			
+			aabbMin = center - extent;
+			aabbMax = center + extent;
+	}
+
+	virtual const char*	getName()const 
+	{
+		return "CapsuleShape";
+	}
+
+	int	getUpAxis() const
+	{
+		return m_upAxis;
+	}
+
+	btScalar	getRadius() const
+	{
+		int radiusAxis = (m_upAxis+2)%3;
+		return m_implicitShapeDimensions[radiusAxis];
+	}
+
+	btScalar	getHalfHeight() const
+	{
+		return m_implicitShapeDimensions[m_upAxis];
+	}
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///btCapsuleShapeX represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeX : public btCapsuleShape
+{
+public:
+
+	btCapsuleShapeX(btScalar radius,btScalar height);
+		
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "CapsuleX";
+	}
+
+	
+
+};
+
+///btCapsuleShapeZ represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeZ : public btCapsuleShape
+{
+public:
+	btCapsuleShapeZ(btScalar radius,btScalar height);
+
+		//debugging
+	virtual const char*	getName()const
+	{
+		return "CapsuleZ";
+	}
+
+	
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCapsuleShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	int	m_upAxis;
+
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btCapsuleShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCapsuleShapeData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer;
+	
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+	shapeData->m_upAxis = m_upAxis;
+	
+	return "btCapsuleShapeData";
+}
+
+#endif //BT_CAPSULE_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h	(revision 11817)
@@ -0,0 +1,26 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_MARGIN_H
+#define BT_COLLISION_MARGIN_H
+
+//used by Gjk and some other algorithms
+
+#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01)
+
+
+
+#endif //BT_COLLISION_MARGIN_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp	(revision 11817)
@@ -0,0 +1,119 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "LinearMath/btSerializer.h"
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C" 
+{
+void btBulletCollisionProbe ();
+
+void btBulletCollisionProbe () {}
+}
+
+
+
+void	btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const
+{
+	btTransform tr;
+	tr.setIdentity();
+	btVector3 aabbMin,aabbMax;
+
+	getAabb(tr,aabbMin,aabbMax);
+
+	radius = (aabbMax-aabbMin).length()*btScalar(0.5);
+	center = (aabbMin+aabbMax)*btScalar(0.5);
+}
+
+
+btScalar	btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
+{
+	return getAngularMotionDisc() * defaultContactThreshold;
+}
+
+btScalar	btCollisionShape::getAngularMotionDisc() const
+{
+	///@todo cache this value, to improve performance
+	btVector3	center;
+	btScalar disc;
+	getBoundingSphere(center,disc);
+	disc += (center).length();
+	return disc;
+}
+
+void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
+{
+	//start with static aabb
+	getAabb(curTrans,temporalAabbMin,temporalAabbMax);
+
+	btScalar temporalAabbMaxx = temporalAabbMax.getX();
+	btScalar temporalAabbMaxy = temporalAabbMax.getY();
+	btScalar temporalAabbMaxz = temporalAabbMax.getZ();
+	btScalar temporalAabbMinx = temporalAabbMin.getX();
+	btScalar temporalAabbMiny = temporalAabbMin.getY();
+	btScalar temporalAabbMinz = temporalAabbMin.getZ();
+
+	// add linear motion
+	btVector3 linMotion = linvel*timeStep;
+	///@todo: simd would have a vector max/min operation, instead of per-element access
+	if (linMotion.x() > btScalar(0.))
+		temporalAabbMaxx += linMotion.x(); 
+	else
+		temporalAabbMinx += linMotion.x();
+	if (linMotion.y() > btScalar(0.))
+		temporalAabbMaxy += linMotion.y(); 
+	else
+		temporalAabbMiny += linMotion.y();
+	if (linMotion.z() > btScalar(0.))
+		temporalAabbMaxz += linMotion.z(); 
+	else
+		temporalAabbMinz += linMotion.z();
+
+	//add conservative angular motion
+	btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
+	btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
+	temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
+	temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
+
+	temporalAabbMin -= angularMotion3d;
+	temporalAabbMax += angularMotion3d;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer;
+	char* name = (char*) serializer->findNameForPointer(this);
+	shapeData->m_name = (char*)serializer->getUniquePointer(name);
+	if (shapeData->m_name)
+	{
+		serializer->serializeName(name);
+	}
+	shapeData->m_shapeType = m_shapeType;
+	//shapeData->m_padding//??
+	return "btCollisionShapeData";
+}
+
+void	btCollisionShape::serializeSingleShape(btSerializer* serializer) const
+{
+	int len = calculateSerializeBufferSize();
+	btChunk* chunk = serializer->allocate(len,1);
+	const char* structType = serialize(chunk->m_oldPtr, serializer);
+	serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCollisionShape.h	(revision 11817)
@@ -0,0 +1,150 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_SHAPE_H
+#define BT_COLLISION_SHAPE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
+class btSerializer;
+
+
+///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
+class btCollisionShape
+{
+protected:
+	int m_shapeType;
+	void* m_userPointer;
+
+public:
+
+	btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0)
+	{
+	}
+
+	virtual ~btCollisionShape()
+	{
+	}
+
+	///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	virtual void	getBoundingSphere(btVector3& center,btScalar& radius) const;
+
+	///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations.
+	virtual btScalar	getAngularMotionDisc() const;
+
+	virtual btScalar	getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
+
+
+	///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
+	///result is conservative
+	void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
+
+
+
+	SIMD_FORCE_INLINE bool	isPolyhedral() const
+	{
+		return btBroadphaseProxy::isPolyhedral(getShapeType());
+	}
+
+	SIMD_FORCE_INLINE bool	isConvex2d() const
+	{
+		return btBroadphaseProxy::isConvex2d(getShapeType());
+	}
+
+	SIMD_FORCE_INLINE bool	isConvex() const
+	{
+		return btBroadphaseProxy::isConvex(getShapeType());
+	}
+	SIMD_FORCE_INLINE bool	isNonMoving() const
+	{
+		return btBroadphaseProxy::isNonMoving(getShapeType());
+	}
+	SIMD_FORCE_INLINE bool	isConcave() const
+	{
+		return btBroadphaseProxy::isConcave(getShapeType());
+	}
+	SIMD_FORCE_INLINE bool	isCompound() const
+	{
+		return btBroadphaseProxy::isCompound(getShapeType());
+	}
+
+	SIMD_FORCE_INLINE bool	isSoftBody() const
+	{
+		return btBroadphaseProxy::isSoftBody(getShapeType());
+	}
+
+	///isInfinite is used to catch simulation error (aabb check)
+	SIMD_FORCE_INLINE bool isInfinite() const
+	{
+		return btBroadphaseProxy::isInfinite(getShapeType());
+	}
+
+#ifndef __SPU__
+	virtual void	setLocalScaling(const btVector3& scaling) =0;
+	virtual const btVector3& getLocalScaling() const =0;
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
+
+
+//debugging support
+	virtual const char*	getName()const =0 ;
+#endif //__SPU__
+
+	
+	int		getShapeType() const { return m_shapeType; }
+	virtual void	setMargin(btScalar margin) = 0;
+	virtual btScalar	getMargin() const = 0;
+
+	
+	///optional user data pointer
+	void	setUserPointer(void*  userPtr)
+	{
+		m_userPointer = userPtr;
+	}
+
+	void*	getUserPointer() const
+	{
+		return m_userPointer;
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	virtual void	serializeSingleShape(btSerializer* serializer) const;
+
+};	
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCollisionShapeData
+{
+	char	*m_name;
+	int		m_shapeType;
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btCollisionShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCollisionShapeData);
+}
+
+
+
+#endif //BT_COLLISION_SHAPE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp	(revision 11817)
@@ -0,0 +1,356 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCompoundShape.h"
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btSerializer.h"
+
+btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
+: m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)),
+m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)),
+m_dynamicAabbTree(0),
+m_updateRevision(1),
+m_collisionMargin(btScalar(0.)),
+m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+{
+	m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
+
+	if (enableDynamicAabbTree)
+	{
+		void* mem = btAlignedAlloc(sizeof(btDbvt),16);
+		m_dynamicAabbTree = new(mem) btDbvt();
+		btAssert(mem==m_dynamicAabbTree);
+	}
+}
+
+
+btCompoundShape::~btCompoundShape()
+{
+	if (m_dynamicAabbTree)
+	{
+		m_dynamicAabbTree->~btDbvt();
+		btAlignedFree(m_dynamicAabbTree);
+	}
+}
+
+void	btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+{
+	m_updateRevision++;
+	//m_childTransforms.push_back(localTransform);
+	//m_childShapes.push_back(shape);
+	btCompoundShapeChild child;
+	child.m_node = 0;
+	child.m_transform = localTransform;
+	child.m_childShape = shape;
+	child.m_childShapeType = shape->getShapeType();
+	child.m_childMargin = shape->getMargin();
+
+	
+	//extend the local aabbMin/aabbMax
+	btVector3 localAabbMin,localAabbMax;
+	shape->getAabb(localTransform,localAabbMin,localAabbMax);
+	for (int i=0;i<3;i++)
+	{
+		if (m_localAabbMin[i] > localAabbMin[i])
+		{
+			m_localAabbMin[i] = localAabbMin[i];
+		}
+		if (m_localAabbMax[i] < localAabbMax[i])
+		{
+			m_localAabbMax[i] = localAabbMax[i];
+		}
+
+	}
+	if (m_dynamicAabbTree)
+	{
+		const btDbvtVolume	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+		int index = m_children.size();
+		child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
+	}
+
+	m_children.push_back(child);
+
+}
+
+void	btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform,bool shouldRecalculateLocalAabb)
+{
+	m_children[childIndex].m_transform = newChildTransform;
+
+	if (m_dynamicAabbTree)
+	{
+		///update the dynamic aabb tree
+		btVector3 localAabbMin,localAabbMax;
+		m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
+		ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+		//int index = m_children.size()-1;
+		m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
+	}
+
+	if (shouldRecalculateLocalAabb)
+	{
+		recalculateLocalAabb();
+	}
+}
+
+void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
+{
+	m_updateRevision++;
+	btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
+	if (m_dynamicAabbTree)
+	{
+		m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
+	}
+	m_children.swap(childShapeIndex,m_children.size()-1);
+    if (m_dynamicAabbTree) 
+		m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
+	m_children.pop_back();
+
+}
+
+
+
+void btCompoundShape::removeChildShape(btCollisionShape* shape)
+{
+	m_updateRevision++;
+	// Find the children containing the shape specified, and remove those children.
+	//note: there might be multiple children using the same shape!
+	for(int i = m_children.size()-1; i >= 0 ; i--)
+	{
+		if(m_children[i].m_childShape == shape)
+		{
+			removeChildShapeByIndex(i);
+		}
+	}
+
+
+
+	recalculateLocalAabb();
+}
+
+void btCompoundShape::recalculateLocalAabb()
+{
+	// Recalculate the local aabb
+	// Brute force, it iterates over all the shapes left.
+
+	m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+	//extend the local aabbMin/aabbMax
+	for (int j = 0; j < m_children.size(); j++)
+	{
+		btVector3 localAabbMin,localAabbMax;
+		m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
+		for (int i=0;i<3;i++)
+		{
+			if (m_localAabbMin[i] > localAabbMin[i])
+				m_localAabbMin[i] = localAabbMin[i];
+			if (m_localAabbMax[i] < localAabbMax[i])
+				m_localAabbMax[i] = localAabbMax[i];
+		}
+	}
+}
+
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
+	btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
+	
+	//avoid an illegal AABB when there are no children
+	if (!m_children.size())
+	{
+		localHalfExtents.setValue(0,0,0);
+		localCenter.setValue(0,0,0);
+	}
+	localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
+		
+
+	btMatrix3x3 abs_b = trans.getBasis().absolute();  
+
+	btVector3 center = trans(localCenter);
+
+	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+		abs_b[1].dot(localHalfExtents),
+		abs_b[2].dot(localHalfExtents));
+	aabbMin = center-extent;
+	aabbMax = center+extent;
+	
+}
+
+void	btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//approximation: take the inertia from the aabb for now
+	btTransform ident;
+	ident.setIdentity();
+	btVector3 aabbMin,aabbMax;
+	getAabb(ident,aabbMin,aabbMax);
+
+	btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
+	inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
+	inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
+
+}
+
+
+
+
+void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
+{
+	int n = m_children.size();
+
+	btScalar totalMass = 0;
+	btVector3 center(0, 0, 0);
+	int k;
+
+	for (k = 0; k < n; k++)
+	{
+		btAssert(masses[k]>0);
+		center += m_children[k].m_transform.getOrigin() * masses[k];
+		totalMass += masses[k];
+	}
+
+	btAssert(totalMass>0);
+
+	center /= totalMass;
+	principal.setOrigin(center);
+
+	btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
+	for ( k = 0; k < n; k++)
+	{
+		btVector3 i;
+		m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
+
+		const btTransform& t = m_children[k].m_transform;
+		btVector3 o = t.getOrigin() - center;
+
+		//compute inertia tensor in coordinate system of compound shape
+		btMatrix3x3 j = t.getBasis().transpose();
+		j[0] *= i[0];
+		j[1] *= i[1];
+		j[2] *= i[2];
+		j = t.getBasis() * j;
+
+		//add inertia tensor
+		tensor[0] += j[0];
+		tensor[1] += j[1];
+		tensor[2] += j[2];
+
+		//compute inertia tensor of pointmass at o
+		btScalar o2 = o.length2();
+		j[0].setValue(o2, 0, 0);
+		j[1].setValue(0, o2, 0);
+		j[2].setValue(0, 0, o2);
+		j[0] += o * -o.x(); 
+		j[1] += o * -o.y(); 
+		j[2] += o * -o.z();
+
+		//add inertia tensor of pointmass
+		tensor[0] += masses[k] * j[0];
+		tensor[1] += masses[k] * j[1];
+		tensor[2] += masses[k] * j[2];
+	}
+
+	tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+	inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
+}
+
+
+
+void btCompoundShape::setLocalScaling(const btVector3& scaling)
+{
+
+	for(int i = 0; i < m_children.size(); i++)
+	{
+		btTransform childTrans = getChildTransform(i);
+		btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
+//		childScale = childScale * (childTrans.getBasis() * scaling);
+		childScale = childScale * scaling / m_localScaling;
+		m_children[i].m_childShape->setLocalScaling(childScale);
+		childTrans.setOrigin((childTrans.getOrigin())*scaling);
+		updateChildTransform(i, childTrans,false);
+	}
+	
+	m_localScaling = scaling;
+	recalculateLocalAabb();
+
+}
+
+
+void btCompoundShape::createAabbTreeFromChildren()
+{
+    if ( !m_dynamicAabbTree )
+    {
+        void* mem = btAlignedAlloc(sizeof(btDbvt),16);
+        m_dynamicAabbTree = new(mem) btDbvt();
+        btAssert(mem==m_dynamicAabbTree);
+
+        for ( int index = 0; index < m_children.size(); index++ )
+        {
+            btCompoundShapeChild &child = m_children[index];
+
+            //extend the local aabbMin/aabbMax
+            btVector3 localAabbMin,localAabbMax;
+            child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax);
+
+            const btDbvtVolume  bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+            child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
+        }
+    }
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+	btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
+	btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+	shapeData->m_collisionMargin = float(m_collisionMargin);
+	shapeData->m_numChildShapes = m_children.size();
+	shapeData->m_childShapePtr = 0;
+	if (shapeData->m_numChildShapes)
+	{
+		btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
+		btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
+		shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
+
+		for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
+		{
+			memPtr->m_childMargin = float(m_children[i].m_childMargin);
+			memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
+			//don't serialize shapes that already have been serialized
+			if (!serializer->findPointer(m_children[i].m_childShape))
+			{
+				btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
+				const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
+				serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
+			} 
+
+			memPtr->m_childShapeType = m_children[i].m_childShapeType;
+			m_children[i].m_transform.serializeFloat(memPtr->m_transform);
+		}
+		serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
+	}
+	return "btCompoundShapeData";
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCompoundShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCompoundShape.h	(revision 11817)
@@ -0,0 +1,212 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COMPOUND_SHAPE_H
+#define BT_COMPOUND_SHAPE_H
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//class btOptimizedBvh;
+struct btDbvt;
+
+ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btTransform			m_transform;
+	btCollisionShape*	m_childShape;
+	int					m_childShapeType;
+	btScalar			m_childMargin;
+	struct btDbvtNode*	m_node;
+};
+
+SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
+{
+	return  ( c1.m_transform      == c2.m_transform &&
+		c1.m_childShape     == c2.m_childShape &&
+		c1.m_childShapeType == c2.m_childShapeType &&
+		c1.m_childMargin    == c2.m_childMargin );
+}
+
+/// The btCompoundShape allows to store multiple other btCollisionShapes
+/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
+/// It has an (optional) dynamic aabb tree to accelerate early rejection tests. 
+/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25
+/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape)
+ATTRIBUTE_ALIGNED16(class) btCompoundShape	: public btCollisionShape
+{
+	btAlignedObjectArray<btCompoundShapeChild> m_children;
+	btVector3						m_localAabbMin;
+	btVector3						m_localAabbMax;
+
+	btDbvt*							m_dynamicAabbTree;
+
+	///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
+	int								m_updateRevision;
+
+	btScalar	m_collisionMargin;
+
+protected:
+	btVector3	m_localScaling;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btCompoundShape(bool enableDynamicAabbTree = true);
+
+	virtual ~btCompoundShape();
+
+	void	addChildShape(const btTransform& localTransform,btCollisionShape* shape);
+
+	/// Remove all children shapes that contain the specified shape
+	virtual void removeChildShape(btCollisionShape* shape);
+
+	void removeChildShapeByIndex(int childShapeindex);
+
+
+	int		getNumChildShapes() const
+	{
+		return int (m_children.size());
+	}
+
+	btCollisionShape* getChildShape(int index)
+	{
+		return m_children[index].m_childShape;
+	}
+	const btCollisionShape* getChildShape(int index) const
+	{
+		return m_children[index].m_childShape;
+	}
+
+	btTransform&	getChildTransform(int index)
+	{
+		return m_children[index].m_transform;
+	}
+	const btTransform&	getChildTransform(int index) const
+	{
+		return m_children[index].m_transform;
+	}
+
+	///set a new transform for a child, and update internal data structures (local aabb and dynamic tree)
+	void	updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true);
+
+
+	btCompoundShapeChild* getChildList()
+	{
+		return &m_children[0];
+	}
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	virtual	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	/** Re-calculate the local Aabb. Is called at the end of removeChildShapes. 
+	Use this yourself if you modify the children or their transforms. */
+	virtual void recalculateLocalAabb(); 
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual const btVector3& getLocalScaling() const 
+	{
+		return m_localScaling;
+	}
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setMargin(btScalar margin)
+	{
+		m_collisionMargin = margin;
+	}
+	virtual btScalar	getMargin() const
+	{
+		return m_collisionMargin;
+	}
+	virtual const char*	getName()const
+	{
+		return "Compound";
+	}
+
+	const btDbvt*	getDynamicAabbTree() const
+	{
+		return m_dynamicAabbTree;
+	}
+	
+	btDbvt*	getDynamicAabbTree()
+	{
+		return m_dynamicAabbTree;
+	}
+
+	void createAabbTreeFromChildren();
+
+	///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+	///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
+	///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
+	///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+	///of the collision object by the principal transform.
+	void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
+
+	int	getUpdateRevision() const
+	{
+		return m_updateRevision;
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCompoundShapeChildData
+{
+	btTransformFloatData	m_transform;
+	btCollisionShapeData	*m_childShape;
+	int						m_childShapeType;
+	float					m_childMargin;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCompoundShapeData
+{
+	btCollisionShapeData		m_collisionShapeData;
+
+	btCompoundShapeChildData	*m_childShapePtr;
+
+	int							m_numChildShapes;
+
+	float	m_collisionMargin;
+
+};
+
+
+SIMD_FORCE_INLINE	int	btCompoundShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCompoundShapeData);
+}
+
+
+
+
+
+
+
+#endif //BT_COMPOUND_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp	(revision 11817)
@@ -0,0 +1,27 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConcaveShape.h"
+
+btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
+{
+
+}
+
+btConcaveShape::~btConcaveShape()
+{
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConcaveShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConcaveShape.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONCAVE_SHAPE_H
+#define BT_CONCAVE_SHAPE_H
+
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "btTriangleCallback.h"
+
+/// PHY_ScalarType enumerates possible scalar types.
+/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use
+typedef enum PHY_ScalarType {
+	PHY_FLOAT,
+	PHY_DOUBLE,
+	PHY_INTEGER,
+	PHY_SHORT,
+	PHY_FIXEDPOINT88,
+	PHY_UCHAR
+} PHY_ScalarType;
+
+///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
+///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
+class btConcaveShape : public btCollisionShape
+{
+protected:
+	btScalar m_collisionMargin;
+
+public:
+	btConcaveShape();
+
+	virtual ~btConcaveShape();
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0;
+
+	virtual btScalar getMargin() const {
+		return m_collisionMargin;
+	}
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		m_collisionMargin = collisionMargin;
+	}
+
+
+
+};
+
+#endif //BT_CONCAVE_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConeShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConeShape.cpp	(revision 11817)
@@ -0,0 +1,143 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConeShape.h"
+
+
+
+btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (),
+m_radius (radius),
+m_height(height)
+{
+	m_shapeType = CONE_SHAPE_PROXYTYPE;
+	setConeUpIndex(1);
+	btVector3 halfExtents;
+	m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+}
+
+btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height):
+btConeShape(radius,height)
+{
+	setConeUpIndex(2);
+}
+
+btConeShapeX::btConeShapeX (btScalar radius,btScalar height):
+btConeShape(radius,height)
+{
+	setConeUpIndex(0);
+}
+
+///choose upAxis index
+void	btConeShape::setConeUpIndex(int upIndex)
+{
+	switch (upIndex)
+	{
+	case 0:
+			m_coneIndices[0] = 1;
+			m_coneIndices[1] = 0;
+			m_coneIndices[2] = 2;
+		break;
+	case 1:
+			m_coneIndices[0] = 0;
+			m_coneIndices[1] = 1;
+			m_coneIndices[2] = 2;
+		break;
+	case 2:
+			m_coneIndices[0] = 0;
+			m_coneIndices[1] = 2;
+			m_coneIndices[2] = 1;
+		break;
+	default:
+		btAssert(0);
+	};
+}
+
+btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
+{
+	
+	btScalar halfHeight = m_height * btScalar(0.5);
+
+ if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
+ {
+	btVector3 tmp;
+
+	tmp[m_coneIndices[0]] = btScalar(0.);
+	tmp[m_coneIndices[1]] = halfHeight;
+	tmp[m_coneIndices[2]] = btScalar(0.);
+	return tmp;
+ }
+  else {
+    btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
+    if (s > SIMD_EPSILON) {
+      btScalar d = m_radius / s;
+	  btVector3 tmp;
+	  tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
+	  tmp[m_coneIndices[1]] = -halfHeight;
+	  tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
+	  return tmp;
+    }
+    else  {
+		btVector3 tmp;
+		tmp[m_coneIndices[0]] = btScalar(0.);
+		tmp[m_coneIndices[1]] = -halfHeight;
+		tmp[m_coneIndices[2]] = btScalar(0.);
+		return tmp;
+	}
+  }
+
+}
+
+btVector3	btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+		return coneLocalSupport(vec);
+}
+
+void	btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		const btVector3& vec = vectors[i];
+		supportVerticesOut[i] = coneLocalSupport(vec);
+	}
+}
+
+
+btVector3	btConeShape::localGetSupportingVertex(const btVector3& vec)  const
+{
+	btVector3 supVertex = coneLocalSupport(vec);
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+void	btConeShape::setLocalScaling(const btVector3& scaling)
+{
+	int axis = m_coneIndices[1];
+	int r1 = m_coneIndices[0];
+	int r2 = m_coneIndices[2];
+	m_height *= scaling[axis] / m_localScaling[axis];
+	m_radius *= (scaling[r1] / m_localScaling[r1] + scaling[r2] / m_localScaling[r2]) / 2;
+	m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+	btConvexInternalShape::setLocalScaling(scaling);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConeShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConeShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConeShape.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONE_MINKOWSKI_H
+#define BT_CONE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
+class btConeShape : public btConvexInternalShape
+
+{
+
+	btScalar m_sinAngle;
+	btScalar m_radius;
+	btScalar m_height;
+	int		m_coneIndices[3];
+	btVector3 coneLocalSupport(const btVector3& v) const;
+
+
+public:
+	btConeShape (btScalar radius,btScalar height);
+	
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	btScalar getRadius() const { return m_radius;}
+	btScalar getHeight() const { return m_height;}
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const
+	{
+		btTransform identity;
+		identity.setIdentity();
+		btVector3 aabbMin,aabbMax;
+		getAabb(identity,aabbMin,aabbMax);
+
+		btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+		btScalar margin = getMargin();
+
+		btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+		btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+		btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+		const btScalar x2 = lx*lx;
+		const btScalar y2 = ly*ly;
+		const btScalar z2 = lz*lz;
+		const btScalar scaledmass = mass * btScalar(0.08333333);
+
+		inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+//		inertia.x() = scaledmass * (y2+z2);
+//		inertia.y() = scaledmass * (x2+z2);
+//		inertia.z() = scaledmass * (x2+y2);
+	}
+
+
+		virtual const char*	getName()const 
+		{
+			return "Cone";
+		}
+		
+		///choose upAxis index
+		void	setConeUpIndex(int upIndex);
+		
+		int	getConeUpIndex() const
+		{
+			return m_coneIndices[1];
+		}
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+};
+
+///btConeShape implements a Cone shape, around the X axis
+class btConeShapeX : public btConeShape
+{
+	public:
+		btConeShapeX(btScalar radius,btScalar height);
+};
+
+///btConeShapeZ implements a Cone shape, around the Z axis
+class btConeShapeZ : public btConeShape
+{
+	public:
+		btConeShapeZ(btScalar radius,btScalar height);
+};
+#endif //BT_CONE_MINKOWSKI_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvex2dShape.h"
+
+btConvex2dShape::btConvex2dShape(	btConvexShape* convexChildShape):
+btConvexShape (), m_childConvexShape(convexChildShape)
+{
+	m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE;
+}
+	
+btConvex2dShape::~btConvex2dShape()
+{
+}
+
+	
+
+btVector3	btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+}
+
+void	btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+}
+
+
+btVector3	btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	return m_childConvexShape->localGetSupportingVertex(vec);
+}
+
+
+void	btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+	m_childConvexShape->calculateLocalInertia(mass,inertia);
+}
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	m_childConvexShape->getAabb(t,aabbMin,aabbMax);
+}
+
+void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax);
+}
+
+void	btConvex2dShape::setLocalScaling(const btVector3& scaling) 
+{
+	m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btConvex2dShape::getLocalScaling() const
+{
+	return m_childConvexShape->getLocalScaling();
+}
+
+void	btConvex2dShape::setMargin(btScalar margin)
+{
+	m_childConvexShape->setMargin(margin);
+}
+btScalar	btConvex2dShape::getMargin() const
+{
+	return m_childConvexShape->getMargin();
+}
+
+int		btConvex2dShape::getNumPreferredPenetrationDirections() const
+{
+	return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+	
+void	btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+	m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_2D_SHAPE_H
+#define BT_CONVEX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0.
+///For 2d boxes, the btBox2dShape is recommended.
+class btConvex2dShape : public btConvexShape
+{
+	btConvexShape*	m_childConvexShape;
+
+	public:
+	
+	btConvex2dShape(	btConvexShape* convexChildShape);
+	
+	virtual ~btConvex2dShape();
+	
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	btConvexShape*	getChildShape() 
+	{
+		return m_childConvexShape;
+	}
+
+	const btConvexShape*	getChildShape() const
+	{
+		return m_childConvexShape;
+	}
+
+	virtual const char*	getName()const 
+	{
+		return "Convex2dShape";
+	}
+	
+
+
+	///////////////////////////
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling) ;
+	virtual const btVector3& getLocalScaling() const ;
+
+	virtual void	setMargin(btScalar margin);
+	virtual btScalar	getMargin() const;
+
+	virtual int		getNumPreferredPenetrationDirections() const;
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+
+
+};
+
+#endif //BT_CONVEX_2D_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp	(revision 11817)
@@ -0,0 +1,211 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+
+btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape ()
+{
+	m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
+	m_unscaledPoints.resize(numPoints);
+
+	unsigned char* pointsAddress = (unsigned char*)points;
+
+	for (int i=0;i<numPoints;i++)
+	{
+		btScalar* point = (btScalar*)pointsAddress;
+		m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
+		pointsAddress += stride;
+	}
+
+	recalcLocalAabb();
+
+}
+
+
+
+void btConvexHullShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+	recalcLocalAabb();
+}
+
+void btConvexHullShape::addPoint(const btVector3& point)
+{
+	m_unscaledPoints.push_back(point);
+	recalcLocalAabb();
+
+}
+
+btVector3	btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+
+	for (int i=0;i<m_unscaledPoints.size();i++)
+	{
+		btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
+
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+	return supVec;
+}
+
+void	btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	btScalar newDot;
+	//use 'w' component of supportVerticesOut?
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+		}
+	}
+	for (int i=0;i<m_unscaledPoints.size();i++)
+	{
+		btVector3 vtx = getScaledPoint(i);
+
+		for (int j=0;j<numVectors;j++)
+		{
+			const btVector3& vec = vectors[j];
+			
+			newDot = vec.dot(vtx);
+			if (newDot > supportVerticesOut[j][3])
+			{
+				//WARNING: don't swap next lines, the w component would get overwritten!
+				supportVerticesOut[j] = vtx;
+				supportVerticesOut[j][3] = newDot;
+			}
+		}
+	}
+
+
+
+}
+	
+
+
+btVector3	btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int	btConvexHullShape::getNumVertices() const
+{
+	return m_unscaledPoints.size();
+}
+
+int btConvexHullShape::getNumEdges() const
+{
+	return m_unscaledPoints.size();
+}
+
+void btConvexHullShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+
+	int index0 = i%m_unscaledPoints.size();
+	int index1 = (i+1)%m_unscaledPoints.size();
+	pa = getScaledPoint(index0);
+	pb = getScaledPoint(index1);
+}
+
+void btConvexHullShape::getVertex(int i,btVector3& vtx) const
+{
+	vtx = getScaledPoint(i);
+}
+
+int	btConvexHullShape::getNumPlanes() const
+{
+	return 0;
+}
+
+void btConvexHullShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+
+	btAssert(0);
+}
+
+//not yet
+bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const
+{
+	btAssert(0);
+	return false;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	//int szc = sizeof(btConvexHullShapeData);
+	btConvexHullShapeData* shapeData = (btConvexHullShapeData*) dataBuffer;
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+	int numElem = m_unscaledPoints.size();
+	shapeData->m_numUnscaledPoints = numElem;
+#ifdef BT_USE_DOUBLE_PRECISION
+	shapeData->m_unscaledPointsFloatPtr = 0;
+	shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]):  0;
+#else
+	shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]):  0;
+	shapeData->m_unscaledPointsDoublePtr = 0;
+#endif
+	
+	if (numElem)
+	{
+		int sz = sizeof(btVector3Data);
+	//	int sz2 = sizeof(btVector3DoubleData);
+	//	int sz3 = sizeof(btVector3FloatData);
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			m_unscaledPoints[i].serialize(*memPtr);
+		}
+		serializer->finalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]);
+	}
+	
+	return "btConvexHullShapeData";
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_HULL_SHAPE_H
+#define BT_CONVEX_HULL_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+///The btConvexHullShape implements an implicit convex hull of an array of vertices.
+///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
+ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape
+{
+	btAlignedObjectArray<btVector3>	m_unscaledPoints;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	
+	///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
+	///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
+	///btConvexHullShape make an internal copy of the points.
+	btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3));
+
+	void addPoint(const btVector3& point);
+
+	
+	btVector3* getUnscaledPoints()
+	{
+		return &m_unscaledPoints[0];
+	}
+
+	const btVector3* getUnscaledPoints() const
+	{
+		return &m_unscaledPoints[0];
+	}
+
+	///getPoints is obsolete, please use getUnscaledPoints
+	const btVector3* getPoints() const
+	{
+		return getUnscaledPoints();
+	}
+
+	
+
+
+	SIMD_FORCE_INLINE	btVector3 getScaledPoint(int i) const
+	{
+		return m_unscaledPoints[i] * m_localScaling;
+	}
+
+	SIMD_FORCE_INLINE	int getNumPoints() const 
+	{
+		return m_unscaledPoints.size();
+	}
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+
+
+	//debugging
+	virtual const char*	getName()const {return "Convex";}
+
+	
+	virtual int	getNumVertices() const;
+	virtual int getNumEdges() const;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	virtual void getVertex(int i,btVector3& vtx) const;
+	virtual int	getNumPlanes() const;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+	///in case we receive negative scaling
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btConvexHullShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	btVector3FloatData	*m_unscaledPointsFloatPtr;
+	btVector3DoubleData	*m_unscaledPointsDoublePtr;
+
+	int		m_numUnscaledPoints;
+	char m_padding3[4];
+
+};
+
+
+SIMD_FORCE_INLINE	int	btConvexHullShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btConvexHullShapeData);
+}
+
+
+#endif //BT_CONVEX_HULL_SHAPE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp	(revision 11817)
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConvexInternalShape.h"
+
+
+
+btConvexInternalShape::btConvexInternalShape()
+: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
+m_collisionMargin(CONVEX_DISTANCE_MARGIN)
+{
+}
+
+
+void	btConvexInternalShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling.absolute();
+}
+
+
+
+void	btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
+{
+#ifndef __SPU__
+	//use localGetSupportingVertexWithoutMargin?
+	btScalar margin = getMargin();
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+
+		btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
+
+		btVector3 tmp = trans(sv);
+		maxAabb[i] = tmp[i]+margin;
+		vec[i] = btScalar(-1.);
+		tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
+		minAabb[i] = tmp[i]-margin;
+	}
+#endif
+}
+
+
+
+btVector3	btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
+{
+#ifndef __SPU__
+
+	 btVector3	supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+
+#else
+	btAssert(0);
+	return btVector3(0,0,0);
+#endif //__SPU__
+
+ }
+
+
+btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape()
+	:	btConvexInternalShape(),
+m_localAabbMin(1,1,1),
+m_localAabbMax(-1,-1,-1),
+m_isLocalAabbValid(false)
+{
+}
+
+
+void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+}
+
+void	btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+	btConvexInternalShape::setLocalScaling(scaling);
+	recalcLocalAabb();
+}
+
+
+void	btConvexInternalAabbCachingShape::recalcLocalAabb()
+{
+	m_isLocalAabbValid = true;
+	
+	#if 1
+	static const btVector3 _directions[] =
+	{
+		btVector3( 1.,  0.,  0.),
+		btVector3( 0.,  1.,  0.),
+		btVector3( 0.,  0.,  1.),
+		btVector3( -1., 0.,  0.),
+		btVector3( 0., -1.,  0.),
+		btVector3( 0.,  0., -1.)
+	};
+	
+	btVector3 _supporting[] =
+	{
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.)
+	};
+	
+	batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+	
+	for ( int i = 0; i < 3; ++i )
+	{
+		m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+		m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+	}
+	
+	#else
+
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 tmp = localGetSupportingVertex(vec);
+		m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+		vec[i] = btScalar(-1.);
+		tmp = localGetSupportingVertex(vec);
+		m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+	}
+	#endif
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h	(revision 11817)
@@ -0,0 +1,202 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_INTERNAL_SHAPE_H
+#define BT_CONVEX_INTERNAL_SHAPE_H
+
+#include "btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+
+///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
+class btConvexInternalShape : public btConvexShape
+{
+
+	protected:
+
+	//local scaling. collisionMargin is not scaled !
+	btVector3	m_localScaling;
+
+	btVector3	m_implicitShapeDimensions;
+	
+	btScalar	m_collisionMargin;
+
+	btScalar	m_padding;
+
+	btConvexInternalShape();
+
+public:
+
+	
+
+	virtual ~btConvexInternalShape()
+	{
+
+	}
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+
+	const btVector3& getImplicitShapeDimensions() const
+	{
+		return m_implicitShapeDimensions;
+	}
+
+	///warning: use setImplicitShapeDimensions with care
+	///changing a collision shape while the body is in the world is not recommended,
+	///it is best to remove the body from the world, then make the change, and re-add it
+	///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs'
+	void	setImplicitShapeDimensions(const btVector3& dimensions)
+	{
+		m_implicitShapeDimensions = dimensions;
+	}
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		getAabbSlow(t,aabbMin,aabbMax);
+	}
+
+
+	
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const 
+	{
+		return m_localScaling;
+	}
+
+	const btVector3& getLocalScalingNV() const 
+	{
+		return m_localScaling;
+	}
+
+	virtual void	setMargin(btScalar margin)
+	{
+		m_collisionMargin = margin;
+	}
+	virtual btScalar	getMargin() const
+	{
+		return m_collisionMargin;
+	}
+
+	btScalar	getMarginNV() const
+	{
+		return m_collisionMargin;
+	}
+
+	virtual int		getNumPreferredPenetrationDirections() const
+	{
+		return 0;
+	}
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+	{
+		(void)penetrationVector;
+		(void)index;
+		btAssert(0);
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btConvexInternalShapeData
+{
+	btCollisionShapeData	m_collisionShapeData;
+
+	btVector3FloatData	m_localScaling;
+
+	btVector3FloatData	m_implicitShapeDimensions;
+	
+	float			m_collisionMargin;
+
+	int	m_padding;
+
+};
+
+
+
+SIMD_FORCE_INLINE	int	btConvexInternalShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btConvexInternalShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer;
+	btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+	m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions);
+	m_localScaling.serializeFloat(shapeData->m_localScaling);
+	shapeData->m_collisionMargin = float(m_collisionMargin);
+
+	return "btConvexInternalShapeData";
+}
+
+
+
+
+///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations
+class btConvexInternalAabbCachingShape : public btConvexInternalShape
+{
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	bool		m_isLocalAabbValid;
+	
+protected:
+					
+	btConvexInternalAabbCachingShape();
+	
+	void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+	{
+		m_isLocalAabbValid = true;
+		m_localAabbMin = aabbMin;
+		m_localAabbMax = aabbMax;
+	}
+
+	inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+	{
+		btAssert(m_isLocalAabbValid);
+		aabbMin = m_localAabbMin;
+		aabbMax = m_localAabbMax;
+	}
+
+	inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+	{
+
+		//lazy evaluation of local aabb
+		btAssert(m_isLocalAabbValid);
+		btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+	}
+		
+public:
+		
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	void	recalcLocalAabb();
+
+};
+
+#endif //BT_CONVEX_INTERNAL_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp	(revision 11817)
@@ -0,0 +1,157 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexPointCloudShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+	recalcLocalAabb();
+}
+
+#ifndef __SPU__
+btVector3	btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+
+	for (int i=0;i<m_numPoints;i++)
+	{
+		btVector3 vtx = getScaledPoint(i);
+
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+	return supVec;
+}
+
+void	btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	btScalar newDot;
+	//use 'w' component of supportVerticesOut?
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+		}
+	}
+	for (int i=0;i<m_numPoints;i++)
+	{
+		btVector3 vtx = getScaledPoint(i);
+
+		for (int j=0;j<numVectors;j++)
+		{
+			const btVector3& vec = vectors[j];
+			
+			newDot = vec.dot(vtx);
+			if (newDot > supportVerticesOut[j][3])
+			{
+				//WARNING: don't swap next lines, the w component would get overwritten!
+				supportVerticesOut[j] = vtx;
+				supportVerticesOut[j][3] = newDot;
+			}
+		}
+	}
+
+
+
+}
+	
+
+
+btVector3	btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+#endif
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int	btConvexPointCloudShape::getNumVertices() const
+{
+	return m_numPoints;
+}
+
+int btConvexPointCloudShape::getNumEdges() const
+{
+	return 0;
+}
+
+void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+	btAssert (0);
+}
+
+void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const
+{
+	vtx = m_unscaledPoints[i]*m_localScaling;
+}
+
+int	btConvexPointCloudShape::getNumPlanes() const
+{
+	return 0;
+}
+
+void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+
+	btAssert(0);
+}
+
+//not yet
+bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const
+{
+	btAssert(0);
+	return false;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H
+#define BT_CONVEX_POINT_CLOUD_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
+ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
+{
+	btVector3* m_unscaledPoints;
+	int m_numPoints;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btConvexPointCloudShape()
+	{
+		m_localScaling.setValue(1.f,1.f,1.f);
+		m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+		m_unscaledPoints = 0;
+		m_numPoints = 0;
+	}
+
+	btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true)
+	{
+		m_localScaling = localScaling;
+		m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+		m_unscaledPoints = points;
+		m_numPoints = numPoints;
+
+		if (computeAabb)
+			recalcLocalAabb();
+	}
+
+	void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f))
+	{
+		m_unscaledPoints = points;
+		m_numPoints = numPoints;
+		m_localScaling = localScaling;
+
+		if (computeAabb)
+			recalcLocalAabb();
+	}
+
+	SIMD_FORCE_INLINE	btVector3* getUnscaledPoints()
+	{
+		return m_unscaledPoints;
+	}
+
+	SIMD_FORCE_INLINE	const btVector3* getUnscaledPoints() const
+	{
+		return m_unscaledPoints;
+	}
+
+	SIMD_FORCE_INLINE	int getNumPoints() const 
+	{
+		return m_numPoints;
+	}
+
+	SIMD_FORCE_INLINE	btVector3	getScaledPoint( int index) const
+	{
+		return m_unscaledPoints[index] * m_localScaling;
+	}
+
+#ifndef __SPU__
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+#endif
+
+
+	//debugging
+	virtual const char*	getName()const {return "ConvexPointCloud";}
+
+	virtual int	getNumVertices() const;
+	virtual int getNumEdges() const;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	virtual void getVertex(int i,btVector3& vtx) const;
+	virtual int	getNumPlanes() const;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+	///in case we receive negative scaling
+	virtual void	setLocalScaling(const btVector3& scaling);
+};
+
+
+#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp	(revision 11817)
@@ -0,0 +1,185 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+///This file was written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btHashMap.h"
+
+btConvexPolyhedron::btConvexPolyhedron()
+{
+
+}
+btConvexPolyhedron::~btConvexPolyhedron()
+{
+
+}
+
+
+inline bool IsAlmostZero(const btVector3& v)
+{
+	if(fabsf(v.x())>1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6)	return false;
+	return true;
+}
+
+struct btInternalVertexPair
+{
+	btInternalVertexPair(short int v0,short int v1)
+		:m_v0(v0),
+		m_v1(v1)
+	{
+		if (m_v1>m_v0)
+			btSwap(m_v0,m_v1);
+	}
+	short int m_v0;
+	short int m_v1;
+	int getHash() const
+	{
+		return m_v0+(m_v1<<16);
+	}
+	bool equals(const btInternalVertexPair& other) const
+	{
+		return m_v0==other.m_v0 && m_v1==other.m_v1;
+	}
+};
+
+struct btInternalEdge
+{
+	btInternalEdge()
+		:m_face0(-1),
+		m_face1(-1)
+	{
+	}
+	short int m_face0;
+	short int m_face1;
+};
+
+//
+
+void	btConvexPolyhedron::initialize()
+{
+	btHashMap<btInternalVertexPair,btInternalEdge> edges;
+
+	float TotalArea = 0.0f;
+	
+	m_localCenter.setValue(0, 0, 0);
+	for(int i=0;i<m_faces.size();i++)
+	{
+		int numVertices = m_faces[i].m_indices.size();
+		int NbTris = numVertices;
+		for(int j=0;j<NbTris;j++)
+		{
+			int k = (j+1)%numVertices;
+			btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+			btInternalEdge* edptr = edges.find(vp);
+			btVector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0];
+			edge.normalize();
+
+			bool found = false;
+
+			for (int p=0;p<m_uniqueEdges.size();p++)
+			{
+				
+				if (IsAlmostZero(m_uniqueEdges[p]-edge) || 
+					IsAlmostZero(m_uniqueEdges[p]+edge))
+				{
+					found = true;
+					break;
+				}
+			}
+
+			if (!found)
+			{
+				m_uniqueEdges.push_back(edge);
+			}
+
+			if (edptr)
+			{
+				btAssert(edptr->m_face0>=0);
+				btAssert(edptr->m_face1<0);
+				edptr->m_face1 = i;
+			} else
+			{
+				btInternalEdge ed;
+				ed.m_face0 = i;
+				edges.insert(vp,ed);
+			}
+		}
+	}
+
+	for(int i=0;i<m_faces.size();i++)
+	{
+		int numVertices = m_faces[i].m_indices.size();
+		m_faces[i].m_connectedFaces.resize(numVertices);
+
+		for(int j=0;j<numVertices;j++)
+		{
+			int k = (j+1)%numVertices;
+			btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+			btInternalEdge* edptr = edges.find(vp);
+			btAssert(edptr);
+			btAssert(edptr->m_face0>=0);
+			btAssert(edptr->m_face1>=0);
+
+			int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0;
+			m_faces[i].m_connectedFaces[j] = connectedFace;
+		}
+	}
+
+	for(int i=0;i<m_faces.size();i++)
+	{
+		int numVertices = m_faces[i].m_indices.size();
+		int NbTris = numVertices-2;
+		
+		const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
+		for(int j=1;j<=NbTris;j++)
+		{
+			int k = (j+1)%numVertices;
+			const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
+			const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
+			float Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
+			btVector3 Center = (p0+p1+p2)/3.0f;
+			m_localCenter += Area * Center;
+			TotalArea += Area;
+		}
+	}
+	m_localCenter /= TotalArea;
+
+}
+
+
+void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, float& min, float& max) const
+{
+	min = FLT_MAX;
+	max = -FLT_MAX;
+	int numVerts = m_vertices.size();
+	for(int i=0;i<numVerts;i++)
+	{
+		btVector3 pt = trans * m_vertices[i];
+		float dp = pt.dot(dir);
+		if(dp < min)	min = dp;
+		if(dp > max)	max = dp;
+	}
+	if(min>max)
+	{
+		float tmp = min;
+		min = max;
+		max = tmp;
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+///This file was written by Erwin Coumans
+
+
+#ifndef _BT_POLYHEDRAL_FEATURES_H
+#define _BT_POLYHEDRAL_FEATURES_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+struct btFace
+{
+	btAlignedObjectArray<int>	m_indices;
+	btAlignedObjectArray<int>	m_connectedFaces;
+	float	m_plane[4];
+};
+
+
+class btConvexPolyhedron
+{
+	public:
+	btConvexPolyhedron();
+	virtual	~btConvexPolyhedron();
+
+	btAlignedObjectArray<btVector3>	m_vertices;
+	btAlignedObjectArray<btFace>	m_faces;
+	btAlignedObjectArray<btVector3> m_uniqueEdges;
+	btVector3		m_localCenter;
+
+	void	initialize();
+
+	void project(const btTransform& trans, const btVector3& dir, float& min, float& max) const;
+};
+
+	
+#endif //_BT_POLYHEDRAL_FEATURES_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp	(revision 11817)
@@ -0,0 +1,429 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexShape.h"
+#include "btTriangleShape.h"
+#include "btSphereShape.h"
+#include "btCylinderShape.h"
+#include "btCapsuleShape.h"
+#include "btConvexHullShape.h"
+#include "btConvexPointCloudShape.h"
+
+///not supported on IBM SDK, until we fix the alignment of btVector3
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+#include <spu_intrinsics.h>
+static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
+{
+    vec_float4 result;
+    result = spu_mul( vec0, vec1 );
+    result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
+    return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
+}
+#endif //__SPU__
+
+btConvexShape::btConvexShape ()
+{
+}
+
+btConvexShape::~btConvexShape()
+{
+
+}
+
+
+
+static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
+{	
+
+	btVector3 vec = localDirOrg * localScaling;
+
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+
+	btVector3 localDir = vec;
+
+	vec_float4 v_distMax = {-FLT_MAX,0,0,0};
+	vec_int4 v_idxMax = {-999,0,0,0};
+	int v=0;
+	int numverts = numPoints;
+
+	for(;v<(int)numverts-4;v+=4) {
+		vec_float4 p0 = vec_dot3(points[v  ].get128(),localDir.get128());
+		vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
+		vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
+		vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
+		const vec_int4 i0 = {v  ,0,0,0};
+		const vec_int4 i1 = {v+1,0,0,0};
+		const vec_int4 i2 = {v+2,0,0,0};
+		const vec_int4 i3 = {v+3,0,0,0};
+		vec_uint4  retGt01 = spu_cmpgt(p0,p1);
+		vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
+		vec_int4   imax01 = spu_sel(i1,i0,retGt01);
+		vec_uint4  retGt23 = spu_cmpgt(p2,p3);
+		vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
+		vec_int4   imax23 = spu_sel(i3,i2,retGt23);
+		vec_uint4  retGt0123 = spu_cmpgt(pmax01,pmax23);
+		vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
+		vec_int4   imax0123 = spu_sel(imax23,imax01,retGt0123);
+		vec_uint4  retGtMax = spu_cmpgt(v_distMax,pmax0123);
+		v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
+		v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
+	}
+	for(;v<(int)numverts;v++) {
+		vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
+		const vec_int4 i = {v,0,0,0};
+		vec_uint4  retGtMax = spu_cmpgt(v_distMax,p);
+		v_distMax = spu_sel(p,v_distMax,retGtMax);
+		v_idxMax = spu_sel(i,v_idxMax,retGtMax);
+	}
+	int ptIndex = spu_extract(v_idxMax,0);
+	const btVector3& supVec= points[ptIndex] * localScaling;
+	return supVec;
+#else
+
+	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+	int ptIndex = -1;
+
+	for (int i=0;i<numPoints;i++)
+	{
+
+		newDot = vec.dot(points[i]);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			ptIndex = i;
+		}
+	}
+	btAssert(ptIndex >= 0);
+	btVector3 supVec = points[ptIndex] * localScaling;
+	return supVec;
+#endif //__SPU__
+}
+
+btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const
+{
+	switch (m_shapeType)
+	{
+    case SPHERE_SHAPE_PROXYTYPE:
+	{
+		return btVector3(0,0,0);
+    }
+	case BOX_SHAPE_PROXYTYPE:
+	{
+		btBoxShape* convexShape = (btBoxShape*)this;
+		const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
+
+		return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
+	}
+	case TRIANGLE_SHAPE_PROXYTYPE:
+	{
+		btTriangleShape* triangleShape = (btTriangleShape*)this;
+		btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
+		btVector3* vertices = &triangleShape->m_vertices1[0];
+		btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2]));
+		btVector3 sup = vertices[dots.maxAxis()];
+		return btVector3(sup.getX(),sup.getY(),sup.getZ());
+	}
+	case CYLINDER_SHAPE_PROXYTYPE:
+	{
+		btCylinderShape* cylShape = (btCylinderShape*)this;
+		//mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
+
+		btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
+		btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
+		int cylinderUpAxis = cylShape->getUpAxis();
+		int XX(1),YY(0),ZZ(2);
+
+		switch (cylinderUpAxis)
+		{
+		case 0:
+		{
+			XX = 1;
+			YY = 0;
+			ZZ = 2;
+		}
+		break;
+		case 1:
+		{
+			XX = 0;
+			YY = 1;
+			ZZ = 2;	
+		}
+		break;
+		case 2:
+		{
+			XX = 0;
+			YY = 2;
+			ZZ = 1;
+			
+		}
+		break;
+		default:
+			btAssert(0);
+		break;
+		};
+
+		btScalar radius = halfExtents[XX];
+		btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+		btVector3 tmp;
+		btScalar d ;
+
+		btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+		if (s != btScalar(0.0))
+		{
+			d = radius / s;  
+			tmp[XX] = v[XX] * d;
+			tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+			tmp[ZZ] = v[ZZ] * d;
+			return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+		} else {
+			tmp[XX] = radius;
+			tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+			tmp[ZZ] = btScalar(0.0);
+			return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+		}
+	}
+	case CAPSULE_SHAPE_PROXYTYPE:
+	{
+		btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
+
+		btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+		btScalar halfHeight = capsuleShape->getHalfHeight();
+		int capsuleUpAxis = capsuleShape->getUpAxis();
+
+		btScalar radius = capsuleShape->getRadius();
+		btVector3 supVec(0,0,0);
+
+		btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+		btVector3 vec = vec0;
+		btScalar lenSqr = vec.length2();
+		if (lenSqr < btScalar(0.0001))
+		{
+			vec.setValue(1,0,0);
+		} else
+		{
+			btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+			vec *= rlen;
+		}
+		btVector3 vtx;
+		btScalar newDot;
+		{
+			btVector3 pos(0,0,0);
+			pos[capsuleUpAxis] = halfHeight;
+
+			//vtx = pos +vec*(radius);
+			vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV();
+			newDot = vec.dot(vtx);
+			
+
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supVec = vtx;
+			}
+		}
+		{
+			btVector3 pos(0,0,0);
+			pos[capsuleUpAxis] = -halfHeight;
+
+			//vtx = pos +vec*(radius);
+			vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV();
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supVec = vtx;
+			}
+		}
+		return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());	
+	}
+	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+	{
+		btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
+		btVector3* points = convexPointCloudShape->getUnscaledPoints ();
+		int numPoints = convexPointCloudShape->getNumPoints ();
+		return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
+	}
+	case CONVEX_HULL_SHAPE_PROXYTYPE:
+	{
+		btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
+		btVector3* points = convexHullShape->getUnscaledPoints();
+		int numPoints = convexHullShape->getNumPoints ();
+		return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
+	}
+    default:
+#ifndef __SPU__
+		return this->localGetSupportingVertexWithoutMargin (localDir);
+#else
+		btAssert (0);
+#endif
+	}
+
+	// should never reach here
+	btAssert (0);
+	return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
+}
+
+btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const
+{
+	btVector3 localDirNorm = localDir;
+	if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+	}
+	localDirNorm.normalize ();
+
+	return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
+}
+
+/* TODO: This should be bumped up to btCollisionShape () */
+btScalar btConvexShape::getMarginNonVirtual () const
+{
+	switch (m_shapeType)
+	{
+    case SPHERE_SHAPE_PROXYTYPE:
+	{
+		btSphereShape* sphereShape = (btSphereShape*)this;
+		return sphereShape->getRadius ();
+	}
+	case BOX_SHAPE_PROXYTYPE:
+	{
+		btBoxShape* convexShape = (btBoxShape*)this;
+		return convexShape->getMarginNV ();
+	}
+	case TRIANGLE_SHAPE_PROXYTYPE:
+	{
+		btTriangleShape* triangleShape = (btTriangleShape*)this;
+		return triangleShape->getMarginNV ();
+	}
+	case CYLINDER_SHAPE_PROXYTYPE:
+	{
+		btCylinderShape* cylShape = (btCylinderShape*)this;
+		return cylShape->getMarginNV();
+	}
+	case CAPSULE_SHAPE_PROXYTYPE:
+	{
+		btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+		return capsuleShape->getMarginNV();
+	}
+	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+	/* fall through */
+	case CONVEX_HULL_SHAPE_PROXYTYPE:
+	{
+		btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
+		return convexHullShape->getMarginNV();
+	}
+    default:
+#ifndef __SPU__
+		return this->getMargin ();
+#else
+		btAssert (0);
+#endif
+	}
+
+	// should never reach here
+	btAssert (0);
+	return btScalar(0.0f);
+}
+#ifndef __SPU__
+void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+	switch (m_shapeType)
+	{
+    case SPHERE_SHAPE_PROXYTYPE:
+	{
+		btSphereShape* sphereShape = (btSphereShape*)this;
+		btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
+		btScalar margin = radius + sphereShape->getMarginNonVirtual();
+		const btVector3& center = t.getOrigin();
+		btVector3 extent(margin,margin,margin);
+		aabbMin = center - extent;
+		aabbMax = center + extent;
+    }
+	break;
+	case CYLINDER_SHAPE_PROXYTYPE:
+	/* fall through */
+	case BOX_SHAPE_PROXYTYPE:
+	{
+		btBoxShape* convexShape = (btBoxShape*)this;
+		btScalar margin=convexShape->getMarginNonVirtual();
+		btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+		halfExtents += btVector3(margin,margin,margin);
+		btMatrix3x3 abs_b = t.getBasis().absolute();  
+		btVector3 center = t.getOrigin();
+		btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
+		
+		aabbMin = center - extent;
+		aabbMax = center + extent;
+		break;
+	}
+	case TRIANGLE_SHAPE_PROXYTYPE:
+	{
+		btTriangleShape* triangleShape = (btTriangleShape*)this;
+		btScalar margin = triangleShape->getMarginNonVirtual();
+		for (int i=0;i<3;i++)
+		{
+			btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+			vec[i] = btScalar(1.);
+
+			btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis());
+
+			btVector3 tmp = t(sv);
+			aabbMax[i] = tmp[i]+margin;
+			vec[i] = btScalar(-1.);
+			tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()));
+			aabbMin[i] = tmp[i]-margin;
+		}	
+	}
+	break;
+	case CAPSULE_SHAPE_PROXYTYPE:
+	{
+		btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+		btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
+		int m_upAxis = capsuleShape->getUpAxis();
+		halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
+		halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual());
+		btMatrix3x3 abs_b = t.getBasis().absolute();  
+		btVector3 center = t.getOrigin();
+		btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));		  	
+		aabbMin = center - extent;
+		aabbMax = center + extent;
+	}
+	break;
+	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+	case CONVEX_HULL_SHAPE_PROXYTYPE:
+	{
+		btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
+		btScalar margin = convexHullShape->getMarginNonVirtual();
+		convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
+	}
+	break;
+    default:
+#ifndef __SPU__
+		this->getAabb (t, aabbMin, aabbMax);
+#else
+		btAssert (0);
+#endif
+	break;
+	}
+
+	// should never reach here
+	btAssert (0);
+}
+
+#endif //__SPU__
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexShape.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_SHAPE_INTERFACE1
+#define BT_CONVEX_SHAPE_INTERFACE1
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
+
+/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
+/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
+ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape
+{
+
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btConvexShape ();
+
+	virtual ~btConvexShape();
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const = 0;
+
+	////////
+	#ifndef __SPU__
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0;
+	#endif //#ifndef __SPU__
+
+	btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const;
+	btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const;
+	btScalar getMarginNonVirtual () const;
+	void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+	
+	//notice that the vectors should be unit length
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	virtual void	setLocalScaling(const btVector3& scaling) =0;
+	virtual const btVector3& getLocalScaling() const =0;
+
+	virtual void	setMargin(btScalar margin)=0;
+
+	virtual btScalar	getMargin() const=0;
+
+	virtual int		getNumPreferredPenetrationDirections() const=0;
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
+
+
+	
+	
+};
+
+
+
+#endif //BT_CONVEX_SHAPE_INTERFACE1
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp	(revision 11817)
@@ -0,0 +1,315 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+
+
+btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
+: btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
+{
+	m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
+	if ( calcAabb )
+		recalcLocalAabb();
+}
+
+
+
+
+///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
+///but then we are duplicating
+class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
+{
+
+	btVector3 m_supportVertexLocal;
+public:
+
+	btScalar m_maxDot;
+	btVector3 m_supportVecLocal;
+
+	LocalSupportVertexCallback(const btVector3& supportVecLocal)
+		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
+		m_maxDot(btScalar(-BT_LARGE_FLOAT)),
+                m_supportVecLocal(supportVecLocal)
+	{
+	}
+
+	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+	{
+		(void)triangleIndex;
+		(void)partId;
+
+		for (int i=0;i<3;i++)
+		{
+			btScalar dot = m_supportVecLocal.dot(triangle[i]);
+			if (dot > m_maxDot)
+			{
+				m_maxDot = dot;
+				m_supportVertexLocal = triangle[i];
+			}
+		}
+	}
+	
+	btVector3	GetSupportVertexLocal()
+	{
+		return m_supportVertexLocal;
+	}
+
+};
+
+
+
+
+
+btVector3	btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	LocalSupportVertexCallback	supportCallback(vec);
+	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+	supVec = supportCallback.GetSupportVertexLocal();
+
+	return supVec;
+}
+
+void	btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	//use 'w' component of supportVerticesOut?
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+		}
+	}
+	
+	///@todo: could do the batch inside the callback!
+
+
+	for (int j=0;j<numVectors;j++)
+	{
+		const btVector3& vec = vectors[j];
+		LocalSupportVertexCallback	supportCallback(vec);
+		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+		m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+		supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
+	}
+	
+}
+	
+
+
+btVector3	btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
+int	btConvexTriangleMeshShape::getNumVertices() const
+{
+	//cache this?
+	return 0;
+	
+}
+
+int btConvexTriangleMeshShape::getNumEdges() const
+{
+	return 0;
+}
+
+void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
+{
+	btAssert(0);	
+}
+
+void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
+{
+	btAssert(0);
+}
+
+int	btConvexTriangleMeshShape::getNumPlanes() const
+{
+	return 0;
+}
+
+void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int  ) const
+{
+	btAssert(0);
+}
+
+//not yet
+bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
+{
+	btAssert(0);
+	return false;
+}
+
+
+
+void	btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+	m_stridingMesh->setScaling(scaling);
+	
+	recalcLocalAabb();
+	
+}
+
+
+const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
+{
+	return m_stridingMesh->getScaling();
+}
+
+void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
+{
+   class CenterCallback: public btInternalTriangleIndexCallback
+   {
+      bool first;
+      btVector3 ref;
+      btVector3 sum;
+      btScalar volume;
+
+   public:
+
+      CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
+      {
+      }
+
+      virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+      {
+         (void) triangleIndex;
+         (void) partId;
+         if (first)
+         {
+            ref = triangle[0];
+            first = false;
+         }
+         else
+         {
+            btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
+            sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
+            volume += vol;
+         }
+      }
+      
+      btVector3 getCenter()
+      {
+         return (volume > 0) ? sum / volume : ref;
+      }
+
+      btScalar getVolume()
+      {
+         return volume * btScalar(1. / 6);
+      }
+
+   };
+
+   class InertiaCallback: public btInternalTriangleIndexCallback
+   {
+      btMatrix3x3 sum;
+      btVector3 center;
+
+   public:
+
+      InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
+      {
+      }
+
+      virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+      {
+         (void) triangleIndex;
+         (void) partId;
+         btMatrix3x3 i;
+         btVector3 a = triangle[0] - center;
+         btVector3 b = triangle[1] - center;
+         btVector3 c = triangle[2] - center;
+         btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
+         for (int j = 0; j < 3; j++)
+         {
+            for (int k = 0; k <= j; k++)
+            {
+               i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+                  + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
+            }
+         }
+         btScalar i00 = -i[0][0];
+         btScalar i11 = -i[1][1];
+         btScalar i22 = -i[2][2];
+         i[0][0] = i11 + i22; 
+         i[1][1] = i22 + i00; 
+         i[2][2] = i00 + i11;
+         sum[0] += i[0];
+         sum[1] += i[1];
+         sum[2] += i[2];
+      }
+      
+      btMatrix3x3& getInertia()
+      {
+         return sum;
+      }
+
+   };
+
+   CenterCallback centerCallback;
+   btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+   m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
+   btVector3 center = centerCallback.getCenter();
+   principal.setOrigin(center);
+   volume = centerCallback.getVolume();
+
+   InertiaCallback inertiaCallback(center);
+   m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
+
+   btMatrix3x3& i = inertiaCallback.getInertia();
+   i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+   inertia.setValue(i[0][0], i[1][1], i[2][2]);
+   inertia /= volume;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_CONVEX_TRIANGLEMESH_SHAPE_H
+#define BT_CONVEX_TRIANGLEMESH_SHAPE_H
+
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
+/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
+class btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
+{
+
+	class btStridingMeshInterface*	m_stridingMesh;
+
+public:
+	btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
+
+	class btStridingMeshInterface*	getMeshInterface()
+	{
+		return m_stridingMesh;
+	}
+	const class btStridingMeshInterface* getMeshInterface() const
+	{
+		return m_stridingMesh;
+	}
+	
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	//debugging
+	virtual const char*	getName()const {return "ConvexTrimesh";}
+	
+	virtual int	getNumVertices() const;
+	virtual int getNumEdges() const;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	virtual void getVertex(int i,btVector3& vtx) const;
+	virtual int	getNumPlanes() const;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+	
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+
+	///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+	///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
+	///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
+	///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+	///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
+	void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const;
+
+};
+
+
+
+#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp	(revision 11817)
@@ -0,0 +1,279 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCylinderShape.h"
+
+btCylinderShape::btCylinderShape (const btVector3& halfExtents)
+:btConvexInternalShape(),
+m_upAxis(1)
+{
+	btVector3 margin(getMargin(),getMargin(),getMargin());
+	m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
+	m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
+}
+
+
+btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents)
+:btCylinderShape(halfExtents)
+{
+	m_upAxis = 0;
+
+}
+
+
+btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents)
+:btCylinderShape(halfExtents)
+{
+	m_upAxis = 2;
+
+}
+
+void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+void	btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility
+//#define USE_BOX_INERTIA_APPROXIMATION 1
+#ifndef USE_BOX_INERTIA_APPROXIMATION
+
+	/*
+	cylinder is defined as following:
+	*
+	* - principle axis aligned along y by default, radius in x, z-value not used
+	* - for btCylinderShapeX: principle axis aligned along x, radius in y direction, z-value not used
+	* - for btCylinderShapeZ: principle axis aligned along z, radius in x direction, y-value not used
+	*
+	*/
+
+	btScalar radius2;	// square of cylinder radius
+	btScalar height2;	// square of cylinder height
+	btVector3 halfExtents = getHalfExtentsWithMargin();	// get cylinder dimension
+	btScalar div12 = mass / 12.f;
+	btScalar div4 = mass / 4.f;
+	btScalar div2 = mass / 2.f;
+	int idxRadius, idxHeight;
+
+	switch (m_upAxis)	// get indices of radius and height of cylinder
+	{
+		case 0:		// cylinder is aligned along x
+			idxRadius = 1;
+			idxHeight = 0;
+			break;
+		case 2:		// cylinder is aligned along z
+			idxRadius = 0;
+			idxHeight = 2;
+			break;
+		default:	// cylinder is aligned along y
+			idxRadius = 0;
+			idxHeight = 1;
+	}
+
+	// calculate squares
+	radius2 = halfExtents[idxRadius] * halfExtents[idxRadius];
+	height2 = btScalar(4.) * halfExtents[idxHeight] * halfExtents[idxHeight];
+
+	// calculate tensor terms
+	btScalar t1 = div12 * height2 + div4 * radius2;
+	btScalar t2 = div2 * radius2;
+
+	switch (m_upAxis)	// set diagonal elements of inertia tensor
+	{
+		case 0:		// cylinder is aligned along x
+			inertia.setValue(t2,t1,t1);
+			break;
+		case 2:		// cylinder is aligned along z
+			inertia.setValue(t1,t1,t2);
+			break;
+		default:	// cylinder is aligned along y
+			inertia.setValue(t1,t2,t1);
+	}
+#else //USE_BOX_INERTIA_APPROXIMATION
+	//approximation of box shape
+	btVector3 halfExtents = getHalfExtentsWithMargin();
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+#endif //USE_BOX_INERTIA_APPROXIMATION
+}
+
+
+SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) 
+{
+const int cylinderUpAxis = 0;
+const int XX = 1;
+const int YY = 0;
+const int ZZ = 2;
+
+	//mapping depends on how cylinder local orientation is
+	// extents of the cylinder is: X,Y is for radius, and Z for height
+
+
+	btScalar radius = halfExtents[XX];
+	btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+    btVector3 tmp;
+	btScalar d ;
+
+    btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+    if (s != btScalar(0.0))
+	{
+        d = radius / s;  
+		tmp[XX] = v[XX] * d;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = v[ZZ] * d;
+		return tmp;
+	}
+    else
+	{
+	    tmp[XX] = radius;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = btScalar(0.0);
+		return tmp;
+    }
+
+
+}
+
+
+
+
+
+
+inline  btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v) 
+{
+
+const int cylinderUpAxis = 1;
+const int XX = 0;
+const int YY = 1;
+const int ZZ = 2;
+
+
+	btScalar radius = halfExtents[XX];
+	btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+    btVector3 tmp;
+	btScalar d ;
+
+    btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+    if (s != btScalar(0.0))
+	{
+        d = radius / s;  
+		tmp[XX] = v[XX] * d;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = v[ZZ] * d;
+		return tmp;
+	}
+    else
+	{
+	    tmp[XX] = radius;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = btScalar(0.0);
+		return tmp;
+    }
+
+}
+
+inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v) 
+{
+const int cylinderUpAxis = 2;
+const int XX = 0;
+const int YY = 2;
+const int ZZ = 1;
+
+	//mapping depends on how cylinder local orientation is
+	// extents of the cylinder is: X,Y is for radius, and Z for height
+
+
+	btScalar radius = halfExtents[XX];
+	btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+    btVector3 tmp;
+	btScalar d ;
+
+    btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+    if (s != btScalar(0.0))
+	{
+        d = radius / s;  
+		tmp[XX] = v[XX] * d;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = v[ZZ] * d;
+		return tmp;
+	}
+    else
+	{
+	    tmp[XX] = radius;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = btScalar(0.0);
+		return tmp;
+    }
+
+
+}
+
+btVector3	btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec);
+}
+
+
+btVector3	btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec);
+}
+btVector3	btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec);
+}
+
+void	btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
+	}
+}
+
+void	btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
+	}
+}
+
+
+
+
+void	btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
+	}
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCylinderShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btCylinderShape.h	(revision 11817)
@@ -0,0 +1,200 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CYLINDER_MINKOWSKI_H
+#define BT_CYLINDER_MINKOWSKI_H
+
+#include "btBoxShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btVector3.h"
+
+/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
+class btCylinderShape : public btConvexInternalShape
+
+{
+
+protected:
+
+	int	m_upAxis;
+
+public:
+
+	btVector3 getHalfExtentsWithMargin() const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		return halfExtents;
+	}
+	
+	const btVector3& getHalfExtentsWithoutMargin() const
+	{
+		return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+	}
+
+	btCylinderShape (const btVector3& halfExtents);
+	
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const
+	{
+
+		btVector3 supVertex;
+		supVertex = localGetSupportingVertexWithoutMargin(vec);
+		
+		if ( getMargin()!=btScalar(0.) )
+		{
+			btVector3 vecnorm = vec;
+			if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+			{
+				vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+			} 
+			vecnorm.normalize();
+			supVertex+= getMargin() * vecnorm;
+		}
+		return supVertex;
+	}
+
+
+	//use box inertia
+	//	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+	int	getUpAxis() const
+	{
+		return m_upAxis;
+	}
+
+	virtual btScalar getRadius() const
+	{
+		return getHalfExtentsWithMargin().getX();
+	}
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "CylinderY";
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+class btCylinderShapeX : public btCylinderShape
+{
+public:
+	btCylinderShapeX (const btVector3& halfExtents);
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+		//debugging
+	virtual const char*	getName()const
+	{
+		return "CylinderX";
+	}
+
+	virtual btScalar getRadius() const
+	{
+		return getHalfExtentsWithMargin().getY();
+	}
+
+};
+
+class btCylinderShapeZ : public btCylinderShape
+{
+public:
+	btCylinderShapeZ (const btVector3& halfExtents);
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+		//debugging
+	virtual const char*	getName()const
+	{
+		return "CylinderZ";
+	}
+
+	virtual btScalar getRadius() const
+	{
+		return getHalfExtentsWithMargin().getX();
+	}
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCylinderShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	int	m_upAxis;
+
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btCylinderShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCylinderShapeData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btCylinderShapeData* shapeData = (btCylinderShapeData*) dataBuffer;
+	
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+	shapeData->m_upAxis = m_upAxis;
+	
+	return "btCylinderShapeData";
+}
+
+
+
+#endif //BT_CYLINDER_MINKOWSKI_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btEmptyShape.h"
+
+
+#include "btCollisionShape.h"
+
+
+btEmptyShape::btEmptyShape() : btConcaveShape ()
+{
+	m_shapeType = EMPTY_SHAPE_PROXYTYPE;
+}
+
+
+btEmptyShape::~btEmptyShape()
+{
+}
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 margin(getMargin(),getMargin(),getMargin());
+
+	aabbMin = t.getOrigin() - margin;
+
+	aabbMax = t.getOrigin() + margin;
+
+}
+
+void	btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
+{
+	btAssert(0);
+}
+
+	
+	
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btEmptyShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btEmptyShape.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_EMPTY_SHAPE_H
+#define BT_EMPTY_SHAPE_H
+
+#include "btConcaveShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+
+
+
+
+/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
+/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
+class btEmptyShape	: public btConcaveShape
+{
+public:
+	btEmptyShape();
+
+	virtual ~btEmptyShape();
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		m_localScaling = scaling;
+	}
+	virtual const btVector3& getLocalScaling() const 
+	{
+		return m_localScaling;
+	}
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+	
+	virtual const char*	getName()const
+	{
+		return "Empty";
+	}
+
+	virtual void processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const
+	{
+	}
+
+protected:
+	btVector3	m_localScaling;
+
+};
+
+
+
+#endif //BT_EMPTY_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp	(revision 11817)
@@ -0,0 +1,411 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btHeightfieldTerrainShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape
+(
+int heightStickWidth, int heightStickLength, void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+	initialize(heightStickWidth, heightStickLength, heightfieldData,
+	           heightScale, minHeight, maxHeight, upAxis, hdt,
+	           flipQuadEdges);
+}
+
+
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
+{
+	// legacy constructor: support only float or unsigned char,
+	// 	and min height is zero
+	PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
+	btScalar minHeight = 0.0;
+
+	// previously, height = uchar * maxHeight / 65535.
+	// So to preserve legacy behavior, heightScale = maxHeight / 65535
+	btScalar heightScale = maxHeight / 65535;
+
+	initialize(heightStickWidth, heightStickLength, heightfieldData,
+	           heightScale, minHeight, maxHeight, upAxis, hdt,
+	           flipQuadEdges);
+}
+
+
+
+void btHeightfieldTerrainShape::initialize
+(
+int heightStickWidth, int heightStickLength, void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+	// validation
+	btAssert(heightStickWidth > 1 && "bad width");
+	btAssert(heightStickLength > 1 && "bad length");
+	btAssert(heightfieldData && "null heightfield data");
+	// btAssert(heightScale) -- do we care?  Trust caller here
+	btAssert(minHeight <= maxHeight && "bad min/max height");
+	btAssert(upAxis >= 0 && upAxis < 3 &&
+	    "bad upAxis--should be in range [0,2]");
+	btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT &&
+	    "Bad height data type enum");
+
+	// initialize member variables
+	m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
+	m_heightStickWidth = heightStickWidth;
+	m_heightStickLength = heightStickLength;
+	m_minHeight = minHeight;
+	m_maxHeight = maxHeight;
+	m_width = (btScalar) (heightStickWidth - 1);
+	m_length = (btScalar) (heightStickLength - 1);
+	m_heightScale = heightScale;
+	m_heightfieldDataUnknown = heightfieldData;
+	m_heightDataType = hdt;
+	m_flipQuadEdges = flipQuadEdges;
+	m_useDiamondSubdivision = false;
+	m_upAxis = upAxis;
+	m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
+
+	// determine min/max axis-aligned bounding box (aabb) values
+	switch (m_upAxis)
+	{
+	case 0:
+		{
+			m_localAabbMin.setValue(m_minHeight, 0, 0);
+			m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
+			break;
+		}
+	case 1:
+		{
+			m_localAabbMin.setValue(0, m_minHeight, 0);
+			m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
+			break;
+		};
+	case 2:
+		{
+			m_localAabbMin.setValue(0, 0, m_minHeight);
+			m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
+			break;
+		}
+	default:
+		{
+			//need to get valid m_upAxis
+			btAssert(0 && "Bad m_upAxis");
+		}
+	}
+
+	// remember origin (defined as exact middle of aabb)
+	m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
+}
+
+
+
+btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
+{
+}
+
+
+
+void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
+
+	btVector3 localOrigin(0, 0, 0);
+	localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
+	localOrigin *= m_localScaling;
+
+	btMatrix3x3 abs_b = t.getBasis().absolute();  
+	btVector3 center = t.getOrigin();
+	btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
+		   abs_b[1].dot(halfExtents),
+		  abs_b[2].dot(halfExtents));
+	extent += btVector3(getMargin(),getMargin(),getMargin());
+
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+}
+
+
+/// This returns the "raw" (user's initial) height, not the actual height.
+/// The actual height needs to be adjusted to be relative to the center
+///   of the heightfield's AABB.
+btScalar
+btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
+{
+	btScalar val = 0.f;
+	switch (m_heightDataType)
+	{
+	case PHY_FLOAT:
+		{
+			val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
+			break;
+		}
+
+	case PHY_UCHAR:
+		{
+			unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
+			val = heightFieldValue * m_heightScale;
+			break;
+		}
+
+	case PHY_SHORT:
+		{
+			short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
+			val = hfValue * m_heightScale;
+			break;
+		}
+
+	default:
+		{
+			btAssert(!"Bad m_heightDataType");
+		}
+	}
+
+	return val;
+}
+
+
+
+
+/// this returns the vertex in bullet-local coordinates
+void	btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
+{
+	btAssert(x>=0);
+	btAssert(y>=0);
+	btAssert(x<m_heightStickWidth);
+	btAssert(y<m_heightStickLength);
+
+	btScalar	height = getRawHeightFieldValue(x,y);
+
+	switch (m_upAxis)
+	{
+	case 0:
+		{
+		vertex.setValue(
+			height - m_localOrigin.getX(),
+			(-m_width/btScalar(2.0)) + x,
+			(-m_length/btScalar(2.0) ) + y
+			);
+			break;
+		}
+	case 1:
+		{
+			vertex.setValue(
+			(-m_width/btScalar(2.0)) + x,
+			height - m_localOrigin.getY(),
+			(-m_length/btScalar(2.0)) + y
+			);
+			break;
+		};
+	case 2:
+		{
+			vertex.setValue(
+			(-m_width/btScalar(2.0)) + x,
+			(-m_length/btScalar(2.0)) + y,
+			height - m_localOrigin.getZ()
+			);
+			break;
+		}
+	default:
+		{
+			//need to get valid m_upAxis
+			btAssert(0);
+		}
+	}
+
+	vertex*=m_localScaling;
+}
+
+
+
+static inline int
+getQuantized
+(
+btScalar x
+)
+{
+	if (x < 0.0) {
+		return (int) (x - 0.5);
+	}
+	return (int) (x + 0.5);
+}
+
+
+
+/// given input vector, return quantized version
+/**
+  This routine is basically determining the gridpoint indices for a given
+  input vector, answering the question: "which gridpoint is closest to the
+  provided point?".
+
+  "with clamp" means that we restrict the point to be in the heightfield's
+  axis-aligned bounding box.
+ */
+void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
+{
+	btVector3 clampedPoint(point);
+	clampedPoint.setMax(m_localAabbMin);
+	clampedPoint.setMin(m_localAabbMax);
+
+	out[0] = getQuantized(clampedPoint.getX());
+	out[1] = getQuantized(clampedPoint.getY());
+	out[2] = getQuantized(clampedPoint.getZ());
+		
+}
+
+
+
+/// process all triangles within the provided axis-aligned bounding box
+/**
+  basic algorithm:
+    - convert input aabb to local coordinates (scale down and shift for local origin)
+    - convert input aabb to a range of heightfield grid points (quantize)
+    - iterate over all triangles in that subset of the grid
+ */
+void	btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	// scale down the input aabb's so they are in local (non-scaled) coordinates
+	btVector3	localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+	btVector3	localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+
+	// account for local origin
+	localAabbMin += m_localOrigin;
+	localAabbMax += m_localOrigin;
+
+	//quantize the aabbMin and aabbMax, and adjust the start/end ranges
+	int	quantizedAabbMin[3];
+	int	quantizedAabbMax[3];
+	quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
+	quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
+	
+	// expand the min/max quantized values
+	// this is to catch the case where the input aabb falls between grid points!
+	for (int i = 0; i < 3; ++i) {
+		quantizedAabbMin[i]--;
+		quantizedAabbMax[i]++;
+	}	
+
+	int startX=0;
+	int endX=m_heightStickWidth-1;
+	int startJ=0;
+	int endJ=m_heightStickLength-1;
+
+	switch (m_upAxis)
+	{
+	case 0:
+		{
+			if (quantizedAabbMin[1]>startX)
+				startX = quantizedAabbMin[1];
+			if (quantizedAabbMax[1]<endX)
+				endX = quantizedAabbMax[1];
+			if (quantizedAabbMin[2]>startJ)
+				startJ = quantizedAabbMin[2];
+			if (quantizedAabbMax[2]<endJ)
+				endJ = quantizedAabbMax[2];
+			break;
+		}
+	case 1:
+		{
+			if (quantizedAabbMin[0]>startX)
+				startX = quantizedAabbMin[0];
+			if (quantizedAabbMax[0]<endX)
+				endX = quantizedAabbMax[0];
+			if (quantizedAabbMin[2]>startJ)
+				startJ = quantizedAabbMin[2];
+			if (quantizedAabbMax[2]<endJ)
+				endJ = quantizedAabbMax[2];
+			break;
+		};
+	case 2:
+		{
+			if (quantizedAabbMin[0]>startX)
+				startX = quantizedAabbMin[0];
+			if (quantizedAabbMax[0]<endX)
+				endX = quantizedAabbMax[0];
+			if (quantizedAabbMin[1]>startJ)
+				startJ = quantizedAabbMin[1];
+			if (quantizedAabbMax[1]<endJ)
+				endJ = quantizedAabbMax[1];
+			break;
+		}
+	default:
+		{
+			//need to get valid m_upAxis
+			btAssert(0);
+		}
+	}
+
+	
+  
+
+	for(int j=startJ; j<endJ; j++)
+	{
+		for(int x=startX; x<endX; x++)
+		{
+			btVector3 vertices[3];
+			if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
+			{
+        //first triangle
+        getVertex(x,j,vertices[0]);
+        getVertex(x+1,j,vertices[1]);
+        getVertex(x+1,j+1,vertices[2]);
+        callback->processTriangle(vertices,x,j);
+        //second triangle
+        getVertex(x,j,vertices[0]);
+        getVertex(x+1,j+1,vertices[1]);
+        getVertex(x,j+1,vertices[2]);
+        callback->processTriangle(vertices,x,j);				
+			} else
+			{
+        //first triangle
+        getVertex(x,j,vertices[0]);
+        getVertex(x,j+1,vertices[1]);
+        getVertex(x+1,j,vertices[2]);
+        callback->processTriangle(vertices,x,j);
+        //second triangle
+        getVertex(x+1,j,vertices[0]);
+        getVertex(x,j+1,vertices[1]);
+        getVertex(x+1,j+1,vertices[2]);
+        callback->processTriangle(vertices,x,j);
+			}
+		}
+	}
+
+	
+
+}
+
+void	btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
+{
+	//moving concave objects not supported
+	
+	inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void	btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+}
+const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
+{
+	return m_localScaling;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h	(revision 11817)
@@ -0,0 +1,161 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_HEIGHTFIELD_TERRAIN_SHAPE_H
+#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H
+
+#include "btConcaveShape.h"
+
+///btHeightfieldTerrainShape simulates a 2D heightfield terrain
+/**
+  The caller is responsible for maintaining the heightfield array; this
+  class does not make a copy.
+
+  The heightfield can be dynamic so long as the min/max height values
+  capture the extremes (heights must always be in that range).
+
+  The local origin of the heightfield is assumed to be the exact
+  center (as determined by width and length and height, with each
+  axis multiplied by the localScaling).
+
+  \b NOTE: be careful with coordinates.  If you have a heightfield with a local
+  min height of -100m, and a max height of +500m, you may be tempted to place it
+  at the origin (0,0) and expect the heights in world coordinates to be
+  -100 to +500 meters.
+  Actually, the heights will be -300 to +300m, because bullet will re-center
+  the heightfield based on its AABB (which is determined by the min/max
+  heights).  So keep in mind that once you create a btHeightfieldTerrainShape
+  object, the heights will be adjusted relative to the center of the AABB.  This
+  is different to the behavior of many rendering engines, but is useful for
+  physics engines.
+
+  Most (but not all) rendering and heightfield libraries assume upAxis = 1
+  (that is, the y-axis is "up").  This class allows any of the 3 coordinates
+  to be "up".  Make sure your choice of axis is consistent with your rendering
+  system.
+
+  The heightfield heights are determined from the data type used for the
+  heightfieldData array.  
+
+   - PHY_UCHAR: height at a point is the uchar value at the
+       grid point, multipled by heightScale.  uchar isn't recommended
+       because of its inability to deal with negative values, and
+       low resolution (8-bit).
+
+   - PHY_SHORT: height at a point is the short int value at that grid
+       point, multipled by heightScale.
+
+   - PHY_FLOAT: height at a point is the float value at that grid
+       point.  heightScale is ignored when using the float heightfield
+       data type.
+
+  Whatever the caller specifies as minHeight and maxHeight will be honored.
+  The class will not inspect the heightfield to discover the actual minimum
+  or maximum heights.  These values are used to determine the heightfield's
+  axis-aligned bounding box, multiplied by localScaling.
+
+  For usage and testing see the TerrainDemo.
+ */
+class btHeightfieldTerrainShape : public btConcaveShape
+{
+protected:
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	btVector3	m_localOrigin;
+
+	///terrain data
+	int	m_heightStickWidth;
+	int m_heightStickLength;
+	btScalar	m_minHeight;
+	btScalar	m_maxHeight;
+	btScalar m_width;
+	btScalar m_length;
+	btScalar m_heightScale;
+	union
+	{
+		unsigned char*	m_heightfieldDataUnsignedChar;
+		short*		m_heightfieldDataShort;
+		btScalar*			m_heightfieldDataFloat;
+		void*			m_heightfieldDataUnknown;
+	};
+
+	PHY_ScalarType	m_heightDataType;	
+	bool	m_flipQuadEdges;
+  bool  m_useDiamondSubdivision;
+
+	int	m_upAxis;
+	
+	btVector3	m_localScaling;
+
+	virtual btScalar	getRawHeightFieldValue(int x,int y) const;
+	void		quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
+	void		getVertex(int x,int y,btVector3& vertex) const;
+
+
+
+	/// protected initialization
+	/**
+	  Handles the work of constructors so that public constructors can be
+	  backwards-compatible without a lot of copy/paste.
+	 */
+	void initialize(int heightStickWidth, int heightStickLength,
+	                void* heightfieldData, btScalar heightScale,
+	                btScalar minHeight, btScalar maxHeight, int upAxis,
+	                PHY_ScalarType heightDataType, bool flipQuadEdges);
+
+public:
+	/// preferred constructor
+	/**
+	  This constructor supports a range of heightfield
+	  data types, and allows for a non-zero minimum height value.
+	  heightScale is needed for any integer-based heightfield data types.
+	 */
+	btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,
+	                          void* heightfieldData, btScalar heightScale,
+	                          btScalar minHeight, btScalar maxHeight,
+	                          int upAxis, PHY_ScalarType heightDataType,
+	                          bool flipQuadEdges);
+
+	/// legacy constructor
+	/**
+	  The legacy constructor assumes the heightfield has a minimum height
+	  of zero.  Only unsigned char or floats are supported.  For legacy
+	  compatibility reasons, heightScale is calculated as maxHeight / 65535 
+	  (and is only used when useFloatData = false).
+ 	 */
+	btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
+
+	virtual ~btHeightfieldTerrainShape();
+
+
+	void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	
+	virtual const btVector3& getLocalScaling() const;
+	
+	//debugging
+	virtual const char*	getName()const {return "HEIGHTFIELD";}
+
+};
+
+#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMaterial.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMaterial.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMaterial.h	(revision 11817)
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BT_MATERIAL_H
+#define BT_MATERIAL_H
+
+// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
+class btMaterial
+{
+    // public members so that materials can change due to world events
+public:
+    btScalar m_friction;
+    btScalar m_restitution;
+    int pad[2];
+
+    btMaterial(){}
+    btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
+};
+
+#endif // BT_MATERIAL_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btMinkowskiSumShape.h"
+
+
+btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB)
+: btConvexInternalShape (),
+m_shapeA(shapeA),
+m_shapeB(shapeB)
+{
+	m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE;
+	m_transA.setIdentity();
+	m_transB.setIdentity();
+}
+
+btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis()));
+	btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis()));
+	return  supVertexA - supVertexB;
+}
+
+void	btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	///@todo: could make recursive use of batching. probably this shape is not used frequently.
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
+	}
+
+}
+
+
+
+btScalar	btMinkowskiSumShape::getMargin() const
+{
+	return m_shapeA->getMargin() + m_shapeB->getMargin();
+}
+
+
+void	btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	(void)mass;
+	btAssert(0);
+	inertia.setValue(0,0,0);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MINKOWSKI_SUM_SHAPE_H
+#define BT_MINKOWSKI_SUM_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
+class btMinkowskiSumShape : public btConvexInternalShape
+{
+
+	btTransform	m_transA;
+	btTransform	m_transB;
+	const btConvexShape*	m_shapeA;
+	const btConvexShape*	m_shapeB;
+
+public:
+
+	btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB);
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	void	setTransformA(const btTransform&	transA) { m_transA = transA;}
+	void	setTransformB(const btTransform&	transB) { m_transB = transB;}
+
+	const btTransform& getTransformA()const  { return m_transA;}
+	const btTransform& GetTransformB()const  { return m_transB;}
+
+
+	virtual btScalar	getMargin() const;
+
+	const btConvexShape*	getShapeA() const { return m_shapeA;}
+	const btConvexShape*	getShapeB() const { return m_shapeB;}
+
+	virtual const char*	getName()const 
+	{
+		return "MinkowskiSum";
+	}
+};
+
+#endif //BT_MINKOWSKI_SUM_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp	(revision 11817)
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+
+btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres)
+:btConvexInternalAabbCachingShape ()
+{
+	m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE;
+	//btScalar startMargin = btScalar(BT_LARGE_FLOAT);
+
+	m_localPositionArray.resize(numSpheres);
+	m_radiArray.resize(numSpheres);
+	for (int i=0;i<numSpheres;i++)
+	{
+		m_localPositionArray[i] = positions[i];
+		m_radiArray[i] = radi[i];
+		
+	}
+
+	recalcLocalAabb();
+
+}
+
+ 
+ btVector3	btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	int i;
+	btVector3 supVec(0,0,0);
+
+	btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	btVector3 vtx;
+	btScalar newDot;
+
+	const btVector3* pos = &m_localPositionArray[0];
+	const btScalar* rad = &m_radiArray[0];
+	int numSpheres = m_localPositionArray.size();
+
+	for (i=0;i<numSpheres;i++)
+	{
+		vtx = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
+		pos++;
+		rad++;
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+
+	return supVec;
+
+}
+
+ void	btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+
+	for (int j=0;j<numVectors;j++)
+	{
+		btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+		const btVector3& vec = vectors[j];
+
+		btVector3 vtx;
+		btScalar newDot;
+
+		const btVector3* pos = &m_localPositionArray[0];
+		const btScalar* rad = &m_radiArray[0];
+		int numSpheres = m_localPositionArray.size();
+		for (int i=0;i<numSpheres;i++)
+		{
+			vtx = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
+			pos++;
+			rad++;
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supportVerticesOut[j] = vtx;
+			}
+		}
+	}
+}
+
+
+
+
+
+
+
+
+void	btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//as an approximation, take the inertia of the box that bounds the spheres
+
+	btVector3 localAabbMin,localAabbMax;
+	getCachedLocalAabb(localAabbMin,localAabbMax);
+	btVector3 halfExtents = (localAabbMax-localAabbMin)*btScalar(0.5);
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*) dataBuffer;
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+	int numElem = m_localPositionArray.size();
+	shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]):  0;
+	
+	shapeData->m_localPositionArraySize = numElem;
+	if (numElem)
+	{
+		btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius),numElem);
+		btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			m_localPositionArray[i].serializeFloat(memPtr->m_pos);
+			memPtr->m_radius = float(m_radiArray[i]);
+		}
+		serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]);
+	}
+	
+	return "btMultiSphereShapeData";
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h	(revision 11817)
@@ -0,0 +1,99 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MULTI_SPHERE_MINKOWSKI_H
+#define BT_MULTI_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAabbUtil2.h"
+
+
+
+///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
+///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius
+class btMultiSphereShape : public btConvexInternalAabbCachingShape
+{
+	
+	btAlignedObjectArray<btVector3> m_localPositionArray;
+	btAlignedObjectArray<btScalar>  m_radiArray;
+	
+public:
+	btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres);
+
+	///CollisionShape Interface
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	/// btConvexShape Interface
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	int	getSphereCount() const
+	{
+		return m_localPositionArray.size();
+	}
+
+	const btVector3&	getSpherePosition(int index) const
+	{
+		return m_localPositionArray[index];
+	}
+
+	btScalar	getSphereRadius(int index) const
+	{
+		return m_radiArray[index];
+	}
+
+
+	virtual const char*	getName()const 
+	{
+		return "MultiSphere";
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+
+struct	btPositionAndRadius
+{
+	btVector3FloatData	m_pos;
+	float		m_radius;
+};
+
+struct	btMultiSphereShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	btPositionAndRadius	*m_localPositionArrayPtr;
+	int				m_localPositionArraySize;
+	char	m_padding[4];
+};
+
+
+
+SIMD_FORCE_INLINE	int	btMultiSphereShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btMultiSphereShapeData);
+}
+
+
+
+#endif //BT_MULTI_SPHERE_MINKOWSKI_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp	(revision 11817)
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
+//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+
+
+///Obtains the material for a specific triangle
+const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
+{
+    const unsigned char * materialBase = 0;
+    int numMaterials;
+    PHY_ScalarType materialType;
+    int materialStride;
+    const unsigned char * triangleMaterialBase = 0;
+    int numTriangles;
+    int triangleMaterialStride;
+    PHY_ScalarType triangleType;
+
+    ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
+        &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
+
+    // return the pointer to the place with the friction for the triangle
+    // TODO: This depends on whether it's a moving mesh or not
+    // BUG IN GIMPACT
+    //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
+    int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
+    btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
+    return (matVal);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#define BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+
+#include "btBvhTriangleMeshShape.h"
+#include "btMaterial.h"
+
+///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
+ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
+{
+    btAlignedObjectArray <btMaterial*> m_materialList;
+    int ** m_triangleMaterials;
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+    btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
+        btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+        {
+            m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+            const unsigned char *vertexbase;
+            int numverts;
+            PHY_ScalarType type;
+            int stride;
+            const unsigned char *indexbase;
+            int indexstride;
+            int numfaces;
+            PHY_ScalarType indicestype;
+
+            //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+            for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+            {
+                m_meshInterface->getLockedReadOnlyVertexIndexBase(
+                    &vertexbase,
+                    numverts,
+                    type,
+                    stride,
+                    &indexbase,
+                    indexstride,
+                    numfaces,
+                    indicestype,
+                    i);
+                //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
+            }
+        }
+
+	///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+	btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
+        btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
+        {
+            m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+            const unsigned char *vertexbase;
+            int numverts;
+            PHY_ScalarType type;
+            int stride;
+            const unsigned char *indexbase;
+            int indexstride;
+            int numfaces;
+            PHY_ScalarType indicestype;
+
+            //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+            for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+            {
+                m_meshInterface->getLockedReadOnlyVertexIndexBase(
+                    &vertexbase,
+                    numverts,
+                    type,
+                    stride,
+                    &indexbase,
+                    indexstride,
+                    numfaces,
+                    indicestype,
+                    i);
+                //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
+            }
+        }
+	
+    virtual ~btMultimaterialTriangleMeshShape()
+    {
+/*
+        for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
+        {
+            btAlignedFree(m_materialValues[i]);
+            m_materialLookup[i] = NULL;
+        }
+        btAlignedFree(m_materialValues);
+        m_materialLookup = NULL;
+*/
+    }
+	//debugging
+	virtual const char*	getName()const {return "MULTIMATERIALTRIANGLEMESH";}
+
+    ///Obtains the material for a specific triangle
+    const btMaterial * getMaterialProperties(int partID, int triIndex);
+
+}
+;
+
+#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp	(revision 11817)
@@ -0,0 +1,391 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btOptimizedBvh.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+btOptimizedBvh::btOptimizedBvh()
+{ 
+}
+
+btOptimizedBvh::~btOptimizedBvh()
+{
+}
+
+
+void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
+{
+	m_useQuantization = useQuantizedAabbCompression;
+
+
+	// NodeArray	triangleNodes;
+
+	struct	NodeTriangleCallback : public btInternalTriangleIndexCallback
+	{
+
+		NodeArray&	m_triangleNodes;
+
+		NodeTriangleCallback& operator=(NodeTriangleCallback& other)
+		{
+			m_triangleNodes = other.m_triangleNodes;
+			return *this;
+		}
+		
+		NodeTriangleCallback(NodeArray&	triangleNodes)
+			:m_triangleNodes(triangleNodes)
+		{
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+		{
+			btOptimizedBvhNode node;
+			btVector3	aabbMin,aabbMax;
+			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+			aabbMin.setMin(triangle[0]);
+			aabbMax.setMax(triangle[0]);
+			aabbMin.setMin(triangle[1]);
+			aabbMax.setMax(triangle[1]);
+			aabbMin.setMin(triangle[2]);
+			aabbMax.setMax(triangle[2]);
+
+			//with quantization?
+			node.m_aabbMinOrg = aabbMin;
+			node.m_aabbMaxOrg = aabbMax;
+
+			node.m_escapeIndex = -1;
+	
+			//for child nodes
+			node.m_subPart = partId;
+			node.m_triangleIndex = triangleIndex;
+			m_triangleNodes.push_back(node);
+		}
+	};
+	struct	QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
+	{
+		QuantizedNodeArray&	m_triangleNodes;
+		const btQuantizedBvh* m_optimizedTree; // for quantization
+
+		QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
+		{
+			m_triangleNodes = other.m_triangleNodes;
+			m_optimizedTree = other.m_optimizedTree;
+			return *this;
+		}
+
+		QuantizedNodeTriangleCallback(QuantizedNodeArray&	triangleNodes,const btQuantizedBvh* tree)
+			:m_triangleNodes(triangleNodes),m_optimizedTree(tree)
+		{
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+		{
+			// The partId and triangle index must fit in the same (positive) integer
+			btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
+			btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
+			//negative indices are reserved for escapeIndex
+			btAssert(triangleIndex>=0);
+
+			btQuantizedBvhNode node;
+			btVector3	aabbMin,aabbMax;
+			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+			aabbMin.setMin(triangle[0]);
+			aabbMax.setMax(triangle[0]);
+			aabbMin.setMin(triangle[1]);
+			aabbMax.setMax(triangle[1]);
+			aabbMin.setMin(triangle[2]);
+			aabbMax.setMax(triangle[2]);
+
+			//PCK: add these checks for zero dimensions of aabb
+			const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
+			const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
+			if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
+			{
+				aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
+				aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
+			}
+			if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
+			{
+				aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
+				aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
+			}
+			if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
+			{
+				aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
+				aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
+			}
+
+			m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+			m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+
+			node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+
+			m_triangleNodes.push_back(node);
+		}
+	};
+	
+
+
+	int numLeafNodes = 0;
+
+	
+	if (m_useQuantization)
+	{
+
+		//initialize quantization values
+		setQuantizationValues(bvhAabbMin,bvhAabbMax);
+
+		QuantizedNodeTriangleCallback	callback(m_quantizedLeafNodes,this);
+
+	
+		triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
+
+		//now we have an array of leafnodes in m_leafNodes
+		numLeafNodes = m_quantizedLeafNodes.size();
+
+
+		m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+
+	} else
+	{
+		NodeTriangleCallback	callback(m_leafNodes);
+
+		btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+		triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
+
+		//now we have an array of leafnodes in m_leafNodes
+		numLeafNodes = m_leafNodes.size();
+
+		m_contiguousNodes.resize(2*numLeafNodes);
+	}
+
+	m_curNodeIndex = 0;
+
+	buildTree(0,numLeafNodes);
+
+	///if the entire tree is small then subtree size, we need to create a header info for the tree
+	if(m_useQuantization && !m_SubtreeHeaders.size())
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+		subtree.m_rootNodeIndex = 0;
+		subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+	}
+
+	//PCK: update the copy of the size
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+	//PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+	m_quantizedLeafNodes.clear();
+	m_leafNodes.clear();
+}
+
+
+
+
+void	btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	if (m_useQuantization)
+	{
+
+		setQuantizationValues(aabbMin,aabbMax);
+
+		updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+
+		///now update all subtree headers
+
+		int i;
+		for (i=0;i<m_SubtreeHeaders.size();i++)
+		{
+			btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+			subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+		}
+
+	} else
+	{
+
+	}
+}
+
+
+
+
+void	btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	//incrementally initialize quantization values
+	btAssert(m_useQuantization);
+
+	btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
+	btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
+	btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
+
+	btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
+	btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
+	btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
+
+	///we should update all quantization values, using updateBvhNodes(meshInterface);
+	///but we only update chunks that overlap the given aabb
+	
+	unsigned short	quantizedQueryAabbMin[3];
+	unsigned short	quantizedQueryAabbMax[3];
+
+	quantize(&quantizedQueryAabbMin[0],aabbMin,0);
+	quantize(&quantizedQueryAabbMax[0],aabbMax,1);
+
+	int i;
+	for (i=0;i<this->m_SubtreeHeaders.size();i++)
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+		//PCK: unsigned instead of bool
+		unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+		if (overlap != 0)
+		{
+			updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
+
+			subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+		}
+	}
+	
+}
+
+void	btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
+{
+	(void)index;
+
+	btAssert(m_useQuantization);
+
+	int curNodeSubPart=-1;
+
+	//get access info to trianglemesh data
+		const unsigned char *vertexbase = 0;
+		int numverts = 0;
+		PHY_ScalarType type = PHY_INTEGER;
+		int stride = 0;
+		const unsigned char *indexbase = 0;
+		int indexstride = 0;
+		int numfaces = 0;
+		PHY_ScalarType indicestype = PHY_INTEGER;
+
+		btVector3	triangleVerts[3];
+		btVector3	aabbMin,aabbMax;
+		const btVector3& meshScaling = meshInterface->getScaling();
+		
+		int i;
+		for (i=endNode-1;i>=firstNode;i--)
+		{
+
+
+			btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+			if (curNode.isLeafNode())
+			{
+				//recalc aabb from triangle data
+				int nodeSubPart = curNode.getPartId();
+				int nodeTriangleIndex = curNode.getTriangleIndex();
+				if (nodeSubPart != curNodeSubPart)
+				{
+					if (curNodeSubPart >= 0)
+						meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+					meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,	type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
+
+					curNodeSubPart = nodeSubPart;
+					btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+				}
+				//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
+
+				unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+				
+				
+				for (int j=2;j>=0;j--)
+				{
+					
+					int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+					if (type == PHY_FLOAT)
+					{
+						float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+						triangleVerts[j] = btVector3(
+							graphicsbase[0]*meshScaling.getX(),
+							graphicsbase[1]*meshScaling.getY(),
+							graphicsbase[2]*meshScaling.getZ());
+					}
+					else
+					{
+						double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+						triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+					}
+				}
+
+
+				
+				aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+				aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+				aabbMin.setMin(triangleVerts[0]);
+				aabbMax.setMax(triangleVerts[0]);
+				aabbMin.setMin(triangleVerts[1]);
+				aabbMax.setMax(triangleVerts[1]);
+				aabbMin.setMin(triangleVerts[2]);
+				aabbMax.setMax(triangleVerts[2]);
+
+				quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
+				quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
+				
+			} else
+			{
+				//combine aabb from both children
+
+				btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
+				
+				btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
+					&m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
+				
+
+				{
+					for (int i=0;i<3;i++)
+					{
+						curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+						if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
+							curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
+
+						curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+						if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+							curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
+					}
+				}
+			}
+
+		}
+
+		if (curNodeSubPart >= 0)
+			meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+
+		
+}
+
+///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+	btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+	
+	//we don't add additional data so just do a static upcast
+	return static_cast<btOptimizedBvh*>(bvh);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Contains contributions from Disney Studio's
+
+#ifndef BT_OPTIMIZED_BVH_H
+#define BT_OPTIMIZED_BVH_H
+
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
+
+class btStridingMeshInterface;
+
+
+///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
+ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh
+{
+	
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+protected:
+
+public:
+
+	btOptimizedBvh();
+
+	virtual ~btOptimizedBvh();
+
+	void	build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
+
+	void	refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax);
+
+	void	refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
+
+	void	updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+
+	/// Data buffer MUST be 16 byte aligned
+	virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+	{
+		return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+
+	}
+
+	///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+	static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+
+};
+
+
+#endif //BT_OPTIMIZED_BVH_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp	(revision 11817)
@@ -0,0 +1,338 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btConvexHullComputer.h"
+#include <new>
+
+btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(),
+m_polyhedron(0)
+{
+
+}
+
+btPolyhedralConvexShape::~btPolyhedralConvexShape()
+{
+	if (m_polyhedron)
+	{
+		btAlignedFree(m_polyhedron);
+	}
+}
+
+bool	btPolyhedralConvexShape::initializePolyhedralFeatures()
+{
+	if (m_polyhedron)
+		btAlignedFree(m_polyhedron);
+	
+	void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16);
+	m_polyhedron = new (mem) btConvexPolyhedron;
+
+	btAlignedObjectArray<btVector3> tmpVertices;
+	for (int i=0;i<getNumVertices();i++)
+	{
+		btVector3& newVertex = tmpVertices.expand();
+		getVertex(i,newVertex);
+	}
+
+	btConvexHullComputer conv;
+	conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
+
+	
+
+	btAlignedObjectArray<btVector3> faceNormals;
+	int numFaces = conv.faces.size();
+	faceNormals.resize(numFaces);
+	btConvexHullComputer* convexUtil = &conv;
+
+	
+	
+	m_polyhedron->m_faces.resize(numFaces);
+	int numVertices = convexUtil->vertices.size();
+	m_polyhedron->m_vertices.resize(numVertices);
+	for (int p=0;p<numVertices;p++)
+	{
+		m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
+	}
+
+	for (int i=0;i<numFaces;i++)
+	{
+		int face = convexUtil->faces[i];
+		//printf("face=%d\n",face);
+		const btConvexHullComputer::Edge*  firstEdge = &convexUtil->edges[face];
+		const btConvexHullComputer::Edge*  edge = firstEdge;
+
+		btVector3 edges[3];
+		int numEdges = 0;
+		//compute face normals
+
+		btScalar maxCross2 = 0.f;
+		int chosenEdge = -1;
+
+		do
+		{
+			
+			int src = edge->getSourceVertex();
+			m_polyhedron->m_faces[i].m_indices.push_back(src);
+			int targ = edge->getTargetVertex();
+			btVector3 wa = convexUtil->vertices[src];
+
+			btVector3 wb = convexUtil->vertices[targ];
+			btVector3 newEdge = wb-wa;
+			newEdge.normalize();
+			if (numEdges<2)
+				edges[numEdges++] = newEdge;
+
+			edge = edge->getNextEdgeOfFace();
+		} while (edge!=firstEdge);
+
+		btScalar planeEq = 1e30f;
+
+		
+		if (numEdges==2)
+		{
+			faceNormals[i] = edges[0].cross(edges[1]);
+			faceNormals[i].normalize();
+			m_polyhedron->m_faces[i].m_plane[0] = -faceNormals[i].getX();
+			m_polyhedron->m_faces[i].m_plane[1] = -faceNormals[i].getY();
+			m_polyhedron->m_faces[i].m_plane[2] = -faceNormals[i].getZ();
+			m_polyhedron->m_faces[i].m_plane[3] = planeEq;
+
+		}
+		else
+		{
+			btAssert(0);//degenerate?
+			faceNormals[i].setZero();
+		}
+
+		for (int v=0;v<m_polyhedron->m_faces[i].m_indices.size();v++)
+		{
+			btScalar eq = m_polyhedron->m_vertices[m_polyhedron->m_faces[i].m_indices[v]].dot(faceNormals[i]);
+			if (planeEq>eq)
+			{
+				planeEq=eq;
+			}
+		}
+		m_polyhedron->m_faces[i].m_plane[3] = planeEq;
+	}
+
+
+	if (m_polyhedron->m_faces.size() && conv.vertices.size())
+	{
+
+		for (int f=0;f<m_polyhedron->m_faces.size();f++)
+		{
+			
+			btVector3 planeNormal(m_polyhedron->m_faces[f].m_plane[0],m_polyhedron->m_faces[f].m_plane[1],m_polyhedron->m_faces[f].m_plane[2]);
+			btScalar planeEq = m_polyhedron->m_faces[f].m_plane[3];
+
+			btVector3 supVec = localGetSupportingVertex(-planeNormal);
+
+			if (supVec.dot(planeNormal)<planeEq)
+			{
+				m_polyhedron->m_faces[f].m_plane[0] *= -1;
+				m_polyhedron->m_faces[f].m_plane[1] *= -1;
+				m_polyhedron->m_faces[f].m_plane[2] *= -1;
+				m_polyhedron->m_faces[f].m_plane[3] *= -1;
+				int numVerts = m_polyhedron->m_faces[f].m_indices.size();
+				for (int v=0;v<numVerts/2;v++)
+				{
+					btSwap(m_polyhedron->m_faces[f].m_indices[v],m_polyhedron->m_faces[f].m_indices[numVerts-1-v]);
+				}
+			}
+		}
+	}
+
+	
+
+	m_polyhedron->initialize();
+
+	return true;
+}
+
+
+btVector3	btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+
+
+	btVector3 supVec(0,0,0);
+#ifndef __SPU__
+	int i;
+	btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	btVector3 vtx;
+	btScalar newDot;
+
+	for (i=0;i<getNumVertices();i++)
+	{
+		getVertex(i,vtx);
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+
+	
+#endif //__SPU__
+	return supVec;
+}
+
+
+
+void	btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+#ifndef __SPU__
+	int i;
+
+	btVector3 vtx;
+	btScalar newDot;
+
+	for (i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+	}
+
+	for (int j=0;j<numVectors;j++)
+	{
+	
+		const btVector3& vec = vectors[j];
+
+		for (i=0;i<getNumVertices();i++)
+		{
+			getVertex(i,vtx);
+			newDot = vec.dot(vtx);
+			if (newDot > supportVerticesOut[j][3])
+			{
+				//WARNING: don't swap next lines, the w component would get overwritten!
+				supportVerticesOut[j] = vtx;
+				supportVerticesOut[j][3] = newDot;
+			}
+		}
+	}
+#endif //__SPU__
+}
+
+
+
+void	btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+#ifndef __SPU__
+	//not yet, return box inertia
+
+	btScalar margin = getMargin();
+
+	btTransform ident;
+	ident.setIdentity();
+	btVector3 aabbMin,aabbMax;
+	getAabb(ident,aabbMin,aabbMax);
+	btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+	btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+	btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+	btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(0.08333333);
+
+	inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+#endif //__SPU__
+}
+
+
+
+void	btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+	btConvexInternalShape::setLocalScaling(scaling);
+	recalcLocalAabb();
+}
+
+btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape()
+:btPolyhedralConvexShape(),
+m_localAabbMin(1,1,1),
+m_localAabbMax(-1,-1,-1),
+m_isLocalAabbValid(false)
+{
+}
+
+void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+}
+
+void	btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
+{
+	m_isLocalAabbValid = true;
+	
+	#if 1
+	static const btVector3 _directions[] =
+	{
+		btVector3( 1.,  0.,  0.),
+		btVector3( 0.,  1.,  0.),
+		btVector3( 0.,  0.,  1.),
+		btVector3( -1., 0.,  0.),
+		btVector3( 0., -1.,  0.),
+		btVector3( 0.,  0., -1.)
+	};
+	
+	btVector3 _supporting[] =
+	{
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.)
+	};
+	
+	batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+	
+	for ( int i = 0; i < 3; ++i )
+	{
+		m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+		m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+	}
+	
+	#else
+
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 tmp = localGetSupportingVertex(vec);
+		m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+		vec[i] = btScalar(-1.);
+		tmp = localGetSupportingVertex(vec);
+		m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+	}
+	#endif
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_POLYHEDRAL_CONVEX_SHAPE_H
+#define BT_POLYHEDRAL_CONVEX_SHAPE_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "btConvexInternalShape.h"
+class btConvexPolyhedron;
+
+
+///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
+class btPolyhedralConvexShape : public btConvexInternalShape
+{
+	
+
+protected:
+	
+	btConvexPolyhedron* m_polyhedron;
+
+public:
+
+	btPolyhedralConvexShape();
+
+	virtual ~btPolyhedralConvexShape();
+
+	///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
+	virtual bool	initializePolyhedralFeatures();
+
+	const btConvexPolyhedron*	getConvexPolyhedron() const
+	{
+		return m_polyhedron;
+	}
+
+	//brute force implementations
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+	
+	
+	virtual int	getNumVertices() const = 0 ;
+	virtual int getNumEdges() const = 0;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const = 0;
+	virtual void getVertex(int i,btVector3& vtx) const = 0;
+	virtual int	getNumPlanes() const = 0;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const = 0;
+//	virtual int getIndex(int i) const = 0 ; 
+
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const = 0;
+	
+};
+
+
+///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape
+class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape
+{
+
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	bool		m_isLocalAabbValid;
+		
+protected:
+
+	void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+	{
+		m_isLocalAabbValid = true;
+		m_localAabbMin = aabbMin;
+		m_localAabbMax = aabbMax;
+	}
+
+	inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+	{
+		btAssert(m_isLocalAabbValid);
+		aabbMin = m_localAabbMin;
+		aabbMax = m_localAabbMax;
+	}
+
+public:
+
+	btPolyhedralConvexAabbCachingShape();
+	
+	inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+	{
+
+		//lazy evaluation of local aabb
+		btAssert(m_isLocalAabbValid);
+		btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+	}
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	void	recalcLocalAabb();
+
+};
+
+#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btScaledBvhTriangleMeshShape.h"
+
+btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling)
+:m_localScaling(localScaling),m_bvhTriMeshShape(childShape)
+{
+	m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+}
+
+btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
+{
+}
+
+
+class btScaledTriangleCallback : public btTriangleCallback
+{
+	btTriangleCallback* m_originalCallback;
+
+	btVector3	m_localScaling;
+
+public:
+
+	btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling)
+		:m_originalCallback(originalCallback),
+		m_localScaling(localScaling)
+	{
+	}
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+	{
+		btVector3 newTriangle[3];
+		newTriangle[0] = triangle[0]*m_localScaling;
+		newTriangle[1] = triangle[1]*m_localScaling;
+		newTriangle[2] = triangle[2]*m_localScaling;
+		m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
+	}
+};
+
+void	btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	btScaledTriangleCallback scaledCallback(callback,m_localScaling);
+	
+	btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
+	btVector3 scaledAabbMin,scaledAabbMax;
+
+	///support negative scaling
+	scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+	scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+	scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+	scaledAabbMin[3] = 0.f;
+	
+	scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+	scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+	scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+	scaledAabbMax[3] = 0.f;
+	
+	
+	m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
+}
+
+
+void	btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
+	btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
+
+	btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
+	btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
+
+	localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+	localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+	localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+	localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+	localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+	localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+
+	btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+	btScalar margin = m_bvhTriMeshShape->getMargin();
+	localHalfExtents += btVector3(margin,margin,margin);
+	btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+	
+	btMatrix3x3 abs_b = trans.getBasis().absolute();  
+
+	btVector3 center = trans(localCenter);
+
+	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+		   abs_b[1].dot(localHalfExtents),
+		  abs_b[2].dot(localHalfExtents));
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+
+}
+
+void	btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+}
+
+const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
+{
+	return m_localScaling;
+}
+
+void	btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	///don't make this a movable object!
+//	btAssert(0);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+
+
+///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
+///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
+ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
+{
+	
+	
+	btVector3	m_localScaling;
+
+	btBvhTriangleMeshShape*	m_bvhTriMeshShape;
+
+public:
+
+
+	btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
+
+	virtual ~btScaledBvhTriangleMeshShape();
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	btBvhTriangleMeshShape*	getChildShape()
+	{
+		return m_bvhTriMeshShape;
+	}
+
+	const btBvhTriangleMeshShape*	getChildShape() const
+	{
+		return m_bvhTriMeshShape;
+	}
+
+	//debugging
+	virtual const char*	getName()const {return "SCALEDBVHTRIANGLEMESH";}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btScaledTriangleMeshShapeData
+{
+	btTriangleMeshShapeData	m_trimeshShapeData;
+
+	btVector3FloatData	m_localScaling;
+};
+
+
+SIMD_FORCE_INLINE	int	btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btScaledTriangleMeshShapeData);
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*) dataBuffer;
+	m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData,serializer);
+	scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	m_localScaling.serializeFloat(scaledMeshData->m_localScaling);
+	return "btScaledTriangleMeshShapeData";
+}
+
+
+#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp	(revision 11817)
@@ -0,0 +1,170 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//btShapeHull was implemented by John McCutchan.
+
+
+#include "btShapeHull.h"
+#include "LinearMath/btConvexHull.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+btShapeHull::btShapeHull (const btConvexShape* shape)
+{
+	m_shape = shape;
+	m_vertices.clear ();
+	m_indices.clear();
+	m_numIndices = 0;
+}
+
+btShapeHull::~btShapeHull ()
+{
+	m_indices.clear();	
+	m_vertices.clear ();
+}
+
+bool
+btShapeHull::buildHull (btScalar /*margin*/)
+{
+	int numSampleDirections = NUM_UNITSPHERE_POINTS;
+	{
+		int numPDA = m_shape->getNumPreferredPenetrationDirections();
+		if (numPDA)
+		{
+			for (int i=0;i<numPDA;i++)
+			{
+				btVector3 norm;
+				m_shape->getPreferredPenetrationDirection(i,norm);
+				getUnitSpherePoints()[numSampleDirections] = norm;
+				numSampleDirections++;
+			}
+		}
+	}
+
+	btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	int i;
+	for (i = 0; i < numSampleDirections; i++)
+	{
+		supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints()[i]);
+	}
+
+	HullDesc hd;
+	hd.mFlags = QF_TRIANGLES;
+	hd.mVcount = static_cast<unsigned int>(numSampleDirections);
+
+#ifdef BT_USE_DOUBLE_PRECISION
+	hd.mVertices = &supportPoints[0];
+	hd.mVertexStride = sizeof(btVector3);
+#else
+	hd.mVertices = &supportPoints[0];
+	hd.mVertexStride = sizeof (btVector3);
+#endif
+
+	HullLibrary hl;
+	HullResult hr;
+	if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
+	{
+		return false;
+	}
+
+	m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
+
+
+	for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
+	{
+		m_vertices[i] = hr.m_OutputVertices[i];
+	}
+	m_numIndices = hr.mNumIndices;
+	m_indices.resize(static_cast<int>(m_numIndices));
+	for (i = 0; i < static_cast<int>(m_numIndices); i++)
+	{
+		m_indices[i] = hr.m_Indices[i];
+	}
+
+	// free temporary hull result that we just copied
+	hl.ReleaseResult (hr);
+
+	return true;
+}
+
+int
+btShapeHull::numTriangles () const
+{
+	return static_cast<int>(m_numIndices / 3);
+}
+
+int
+btShapeHull::numVertices () const
+{
+	return m_vertices.size ();
+}
+
+int
+btShapeHull::numIndices () const
+{
+	return static_cast<int>(m_numIndices);
+}
+
+
+btVector3* btShapeHull::getUnitSpherePoints()
+{
+	static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = 
+	{
+		btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
+		btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
+		btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
+		btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
+		btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
+		btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
+		btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
+		btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
+		btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
+		btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
+		btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
+		btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
+		btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
+		btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
+		btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
+		btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
+		btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
+		btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
+		btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
+		btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
+		btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
+		btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
+		btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
+		btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
+		btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+		btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
+		btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+		btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
+		btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
+		btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+		btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
+		btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+		btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
+		btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
+		btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
+		btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
+		btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
+		btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
+		btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
+		btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
+		btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
+		btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
+	};
+	return sUnitSpherePoints;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btShapeHull.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btShapeHull.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btShapeHull.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btShapeHull implemented by John McCutchan.
+
+#ifndef BT_SHAPE_HULL_H
+#define BT_SHAPE_HULL_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+
+///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
+///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
+///It approximates the convex hull using the supporting vertex of 42 directions.
+class btShapeHull
+{
+protected:
+
+	btAlignedObjectArray<btVector3> m_vertices;
+	btAlignedObjectArray<unsigned int> m_indices;
+	unsigned int m_numIndices;
+	const btConvexShape* m_shape;
+
+	static btVector3* getUnitSpherePoints();
+
+public:
+	btShapeHull (const btConvexShape* shape);
+	~btShapeHull ();
+
+	bool buildHull (btScalar margin);
+
+	int numTriangles () const;
+	int numVertices () const;
+	int numIndices () const;
+
+	const btVector3* getVertexPointer() const
+	{
+		return &m_vertices[0];
+	}
+	const unsigned int* getIndexPointer() const
+	{
+		return &m_indices[0];
+	}
+};
+
+#endif //BT_SHAPE_HULL_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+btVector3	btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	(void)vec;
+	return btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void	btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	(void)vectors;
+
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i].setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	}
+}
+
+
+btVector3	btSphereShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex;
+	supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	btVector3 vecnorm = vec;
+	if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+	} 
+	vecnorm.normalize();
+	supVertex+= getMargin() * vecnorm;
+	return supVertex;
+}
+
+
+//broken due to scaling
+void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	const btVector3& center = t.getOrigin();
+	btVector3 extent(getMargin(),getMargin(),getMargin());
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+}
+
+
+
+void	btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
+	inertia.setValue(elem,elem,elem);
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btSphereShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btSphereShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btSphereShape.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_SPHERE_MINKOWSKI_H
+#define BT_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
+ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape
+
+{
+	
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btSphereShape (btScalar radius) : btConvexInternalShape ()
+	{
+		m_shapeType = SPHERE_SHAPE_PROXYTYPE;
+		m_implicitShapeDimensions.setX(radius);
+		m_collisionMargin = radius;
+	}
+	
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	//notice that the vectors should be unit length
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+	btScalar	getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();}
+
+	void	setUnscaledRadius(btScalar	radius)
+	{
+		m_implicitShapeDimensions.setX(radius);
+		btConvexInternalShape::setMargin(radius);
+	}
+
+	//debugging
+	virtual const char*	getName()const {return "SPHERE";}
+
+	virtual void	setMargin(btScalar margin)
+	{
+		btConvexInternalShape::setMargin(margin);
+	}
+	virtual btScalar	getMargin() const
+	{
+		//to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case
+		//this means, non-uniform scaling is not supported anymore
+		return getRadius();
+	}
+
+
+};
+
+
+#endif //BT_SPHERE_MINKOWSKI_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btStaticPlaneShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+
+btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
+: btConcaveShape (), m_planeNormal(planeNormal.normalized()),
+m_planeConstant(planeConstant),
+m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.))
+{
+	m_shapeType = STATIC_PLANE_PROXYTYPE;
+	//	btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
+}
+
+
+btStaticPlaneShape::~btStaticPlaneShape()
+{
+}
+
+
+
+void btStaticPlaneShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	(void)t;
+	/*
+	btVector3 infvec (btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+	btVector3 center = m_planeNormal*m_planeConstant;
+	aabbMin = center + infvec*m_planeNormal;
+	aabbMax = aabbMin;
+	aabbMin.setMin(center - infvec*m_planeNormal);
+	aabbMax.setMax(center - infvec*m_planeNormal); 
+	*/
+
+	aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+	aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+}
+
+
+
+
+void	btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+	btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+	btScalar radius = halfExtents.length();
+	btVector3 center = (aabbMax + aabbMin) * btScalar(0.5);
+	
+	//this is where the triangles are generated, given AABB and plane equation (normal/constant)
+
+	btVector3 tangentDir0,tangentDir1;
+
+	//tangentDir0/tangentDir1 can be precalculated
+	btPlaneSpace1(m_planeNormal,tangentDir0,tangentDir1);
+
+	btVector3 supVertex0,supVertex1;
+
+	btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant)*m_planeNormal;
+	
+	btVector3 triangle[3];
+	triangle[0] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+	triangle[1] = projectedCenter + tangentDir0*radius - tangentDir1*radius;
+	triangle[2] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+
+	callback->processTriangle(triangle,0,0);
+
+	triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+	triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius;
+	triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+
+	callback->processTriangle(triangle,0,1);
+
+}
+
+void	btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	(void)mass;
+
+	//moving concave objects not supported
+	
+	inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void	btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+}
+const btVector3& btStaticPlaneShape::getLocalScaling() const
+{
+	return m_localScaling;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_STATIC_PLANE_SHAPE_H
+#define BT_STATIC_PLANE_SHAPE_H
+
+#include "btConcaveShape.h"
+
+
+///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
+ATTRIBUTE_ALIGNED16(class) btStaticPlaneShape : public btConcaveShape
+{
+protected:
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	
+	btVector3	m_planeNormal;
+	btScalar      m_planeConstant;
+	btVector3	m_localScaling;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+
+	virtual ~btStaticPlaneShape();
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+	
+	const btVector3&	getPlaneNormal() const
+	{
+		return	m_planeNormal;
+	}
+
+	const btScalar&	getPlaneConstant() const
+	{
+		return	m_planeConstant;
+	}
+
+	//debugging
+	virtual const char*	getName()const {return "STATICPLANE";}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btStaticPlaneShapeData
+{
+	btCollisionShapeData	m_collisionShapeData;
+
+	btVector3FloatData	m_localScaling;
+	btVector3FloatData	m_planeNormal;
+	float			m_planeConstant;
+	char	m_pad[4];
+};
+
+
+SIMD_FORCE_INLINE	int	btStaticPlaneShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btStaticPlaneShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) dataBuffer;
+	btCollisionShape::serialize(&planeData->m_collisionShapeData,serializer);
+
+	m_localScaling.serializeFloat(planeData->m_localScaling);
+	m_planeNormal.serializeFloat(planeData->m_planeNormal);
+	planeData->m_planeConstant = float(m_planeConstant);
+		
+	return "btStaticPlaneShapeData";
+}
+
+
+#endif //BT_STATIC_PLANE_SHAPE_H
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp	(revision 11817)
@@ -0,0 +1,379 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btSerializer.h"
+
+btStridingMeshInterface::~btStridingMeshInterface()
+{
+
+}
+
+
+void	btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	(void)aabbMin;
+	(void)aabbMax;
+	int numtotalphysicsverts = 0;
+	int part,graphicssubparts = getNumSubParts();
+	const unsigned char * vertexbase;
+	const unsigned char * indexbase;
+	int indexstride;
+	PHY_ScalarType type;
+	PHY_ScalarType gfxindextype;
+	int stride,numverts,numtriangles;
+	int gfxindex;
+	btVector3 triangle[3];
+
+	btVector3 meshScaling = getScaling();
+
+	///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+	for (part=0;part<graphicssubparts ;part++)
+	{
+		getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+		numtotalphysicsverts+=numtriangles*3; //upper bound
+
+		///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
+		///so disable this feature by default
+		///see patch http://code.google.com/p/bullet/issues/detail?id=213
+
+		switch (type)
+		{
+		case PHY_FLOAT:
+		 {
+
+			 float* graphicsbase;
+
+			 switch (gfxindextype)
+			 {
+			 case PHY_INTEGER:
+				 {
+					 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+					 {
+						 unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+						 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+						 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+						 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+						 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+					 }
+					 break;
+				 }
+			 case PHY_SHORT:
+				 {
+					 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+					 {
+						 unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+						 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+						 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+						 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+						 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+					 }
+					 break;
+				 }
+			case PHY_UCHAR:
+				 {
+					 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+					 {
+						 unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+						 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+						 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+						 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+						 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+					 }
+					 break;
+				 }
+			 default:
+				 btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+			 }
+			 break;
+		 }
+
+		case PHY_DOUBLE:
+			{
+				double* graphicsbase;
+
+				switch (gfxindextype)
+				{
+				case PHY_INTEGER:
+					{
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+							graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+							triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+							triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+							triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+						}
+						break;
+					}
+				case PHY_SHORT:
+					{
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+							graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+							triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+							triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+							triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+						}
+						break;
+					}
+				case PHY_UCHAR:
+					{
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+							graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+							triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+							triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+							triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+						}
+						break;
+					}
+				default:
+					btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+				}
+				break;
+			}
+		default:
+			btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+		}
+
+		unLockReadOnlyVertexBase(part);
+	}
+}
+
+void	btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax)
+{
+
+	struct	AabbCalculationCallback : public btInternalTriangleIndexCallback
+	{
+		btVector3	m_aabbMin;
+		btVector3	m_aabbMax;
+
+		AabbCalculationCallback()
+		{
+			m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+		{
+			(void)partId;
+			(void)triangleIndex;
+
+			m_aabbMin.setMin(triangle[0]);
+			m_aabbMax.setMax(triangle[0]);
+			m_aabbMin.setMin(triangle[1]);
+			m_aabbMax.setMax(triangle[1]);
+			m_aabbMin.setMin(triangle[2]);
+			m_aabbMax.setMax(triangle[2]);
+		}
+	};
+
+	//first calculate the total aabb for all triangles
+	AabbCalculationCallback	aabbCallback;
+	aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+	aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
+
+	aabbMin = aabbCallback.m_aabbMin;
+	aabbMax = aabbCallback.m_aabbMax;
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer;
+
+	trimeshData->m_numMeshParts = getNumSubParts();
+
+	//void* uniquePtr = 0;
+
+	trimeshData->m_meshPartsPtr = 0;
+
+	if (trimeshData->m_numMeshParts)
+	{
+		btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts);
+		btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
+		trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr);
+
+
+	//	int numtotalphysicsverts = 0;
+		int part,graphicssubparts = getNumSubParts();
+		const unsigned char * vertexbase;
+		const unsigned char * indexbase;
+		int indexstride;
+		PHY_ScalarType type;
+		PHY_ScalarType gfxindextype;
+		int stride,numverts,numtriangles;
+		int gfxindex;
+	//	btVector3 triangle[3];
+
+		btVector3 meshScaling = getScaling();
+
+		///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+		for (part=0;part<graphicssubparts ;part++,memPtr++)
+		{
+			getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+			memPtr->m_numTriangles = numtriangles;//indices = 3*numtriangles
+			memPtr->m_numVertices = numverts;
+			memPtr->m_indices16 = 0;
+			memPtr->m_indices32 = 0;
+			memPtr->m_3indices16 = 0;
+			memPtr->m_vertices3f = 0;
+			memPtr->m_vertices3d = 0;
+
+			switch (gfxindextype)
+			{
+			case PHY_INTEGER:
+				{
+					int numindices = numtriangles*3;
+				
+					if (numindices)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices);
+						btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
+						memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+							tmpIndices[gfxindex*3].m_value = tri_indices[0];
+							tmpIndices[gfxindex*3+1].m_value = tri_indices[1];
+							tmpIndices[gfxindex*3+2].m_value = tri_indices[2];
+						}
+						serializer->finalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+			case PHY_SHORT:
+				{
+					if (numtriangles)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles);
+						btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
+						memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices);
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+							tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+							tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+							tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+						}
+						serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+				case PHY_UCHAR:
+				{
+					if (numtriangles)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData),numtriangles);
+						btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr;
+						memPtr->m_3indices8 = (btCharIndexTripletData*) serializer->getUniquePointer(tmpIndices);
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned char* tri_indices= (unsigned char*)(indexbase+gfxindex*indexstride);
+							tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+							tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+							tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+						}
+						serializer->finalizeChunk(chunk,"btCharIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+			default:
+				{
+					btAssert(0);
+					//unknown index type
+				}
+			}
+
+			switch (type)
+			{
+			case PHY_FLOAT:
+			 {
+				 float* graphicsbase;
+
+				 if (numverts)
+				 {
+					 btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts);
+					 btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr;
+					 memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices);
+					 for (int i=0;i<numverts;i++)
+					 {
+						 graphicsbase = (float*)(vertexbase+i*stride);
+						 tmpVertices[i].m_floats[0] = graphicsbase[0];
+						 tmpVertices[i].m_floats[1] = graphicsbase[1];
+						 tmpVertices[i].m_floats[2] = graphicsbase[2];
+					 }
+					 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+				 }
+				 break;
+				}
+
+			case PHY_DOUBLE:
+				{
+					if (numverts)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts);
+						btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr;
+						memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices);
+						for (int i=0;i<numverts;i++)
+					 {
+						 double* graphicsbase = (double*)(vertexbase+i*stride);//for now convert to float, might leave it at double
+						 tmpVertices[i].m_floats[0] = graphicsbase[0];
+						 tmpVertices[i].m_floats[1] = graphicsbase[1];
+						 tmpVertices[i].m_floats[2] = graphicsbase[2];
+					 }
+						serializer->finalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+
+			default:
+				btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+			}
+
+			unLockReadOnlyVertexBase(part);
+		}
+
+		serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr);
+	}
+
+
+	m_scaling.serializeFloat(trimeshData->m_scaling);
+	return "btStridingMeshInterfaceData";
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h	(revision 11817)
@@ -0,0 +1,162 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_STRIDING_MESHINTERFACE_H
+#define BT_STRIDING_MESHINTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "btTriangleCallback.h"
+#include "btConcaveShape.h"
+
+
+
+
+
+///	The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
+/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
+/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
+class  btStridingMeshInterface
+{
+	protected:
+	
+		btVector3 m_scaling;
+
+	public:
+		btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.))
+		{
+
+		}
+
+		virtual ~btStridingMeshInterface();
+
+
+
+		virtual void	InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+		///brute force method to calculate aabb
+		void	calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
+
+		/// get read and write access to a subpart of a triangle mesh
+		/// this subpart has a continuous array of vertices and indices
+		/// in this way the mesh can be handled as chunks of memory with striding
+		/// very similar to OpenGL vertexarray support
+		/// make a call to unLockVertexBase when the read and write access is finished	
+		virtual void	getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
+		
+		virtual void	getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
+	
+		/// unLockVertexBase finishes the access to a subpart of the triangle mesh
+		/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+		virtual void	unLockVertexBase(int subpart)=0;
+
+		virtual void	unLockReadOnlyVertexBase(int subpart) const=0;
+
+
+		/// getNumSubParts returns the number of seperate subparts
+		/// each subpart has a continuous array of vertices and indices
+		virtual int		getNumSubParts() const=0;
+
+		virtual void	preallocateVertices(int numverts)=0;
+		virtual void	preallocateIndices(int numindices)=0;
+
+		virtual bool	hasPremadeAabb() const { return false; }
+		virtual void	setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+                {
+                        (void) aabbMin;
+                        (void) aabbMax;
+                }
+		virtual void	getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+        {
+            (void) aabbMin;
+            (void) aabbMax;
+        }
+
+		const btVector3&	getScaling() const {
+			return m_scaling;
+		}
+		void	setScaling(const btVector3& scaling)
+		{
+			m_scaling = scaling;
+		}
+
+		virtual	int	calculateSerializeBufferSize() const;
+
+		///fills the dataBuffer and returns the struct name (and 0 on failure)
+		virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+struct	btIntIndexData
+{
+	int	m_value;
+};
+
+struct	btShortIntIndexData
+{
+	short m_value;
+	char m_pad[2];
+};
+
+struct	btShortIntIndexTripletData
+{
+	short	m_values[3];
+	char	m_pad[2];
+};
+
+struct	btCharIndexTripletData
+{
+	unsigned char m_values[3];
+	char	m_pad;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btMeshPartData
+{
+	btVector3FloatData			*m_vertices3f;
+	btVector3DoubleData			*m_vertices3d;
+
+	btIntIndexData				*m_indices32;
+	btShortIntIndexTripletData	*m_3indices16;
+	btCharIndexTripletData		*m_3indices8;
+
+	btShortIntIndexData			*m_indices16;//backwards compatibility
+
+	int                     m_numTriangles;//length of m_indices = m_numTriangles
+	int                     m_numVertices;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btStridingMeshInterfaceData
+{
+	btMeshPartData	*m_meshPartsPtr;
+	btVector3FloatData	m_scaling;
+	int	m_numMeshParts;
+	char m_padding[4];
+};
+
+
+
+
+SIMD_FORCE_INLINE	int	btStridingMeshInterface::calculateSerializeBufferSize() const
+{
+	return sizeof(btStridingMeshInterfaceData);
+}
+
+
+
+#endif //BT_STRIDING_MESHINTERFACE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp	(revision 11817)
@@ -0,0 +1,218 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTetrahedronShape.h"
+#include "LinearMath/btMatrix3x3.h"
+
+btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+	addVertex(pt1);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+	addVertex(pt1);
+	addVertex(pt2);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+	addVertex(pt1);
+	addVertex(pt2);
+	addVertex(pt3);
+}
+
+
+void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+#if 1
+	btPolyhedralConvexAabbCachingShape::getAabb(t,aabbMin,aabbMax);
+#else
+	aabbMin.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+	aabbMax.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+
+	//just transform the vertices in worldspace, and take their AABB
+	for (int i=0;i<m_numVertices;i++)
+	{
+		btVector3 worldVertex = t(m_vertices[i]);
+		aabbMin.setMin(worldVertex);
+		aabbMax.setMax(worldVertex);
+	}
+#endif
+}
+
+
+
+
+
+void btBU_Simplex1to4::addVertex(const btVector3& pt)
+{
+	m_vertices[m_numVertices++] = pt;
+	recalcLocalAabb();
+}
+
+
+int	btBU_Simplex1to4::getNumVertices() const
+{
+	return m_numVertices;
+}
+
+int btBU_Simplex1to4::getNumEdges() const
+{
+	//euler formula, F-E+V = 2, so E = F+V-2
+
+	switch (m_numVertices)
+	{
+	case 0:
+		return 0;
+	case 1: return 0;
+	case 2: return 1;
+	case 3: return 3;
+	case 4: return 6;
+
+
+	}
+
+	return 0;
+}
+
+void btBU_Simplex1to4::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+	
+    switch (m_numVertices)
+	{
+
+	case 2: 
+		pa = m_vertices[0];
+		pb = m_vertices[1];
+		break;
+	case 3:  
+		switch (i)
+		{
+		case 0:
+			pa = m_vertices[0];
+			pb = m_vertices[1];
+			break;
+		case 1:
+			pa = m_vertices[1];
+			pb = m_vertices[2];
+			break;
+		case 2:
+			pa = m_vertices[2];
+			pb = m_vertices[0];
+			break;
+
+		}
+		break;
+	case 4: 
+		switch (i)
+		{
+		case 0:
+			pa = m_vertices[0];
+			pb = m_vertices[1];
+			break;
+		case 1:
+			pa = m_vertices[1];
+			pb = m_vertices[2];
+			break;
+		case 2:
+			pa = m_vertices[2];
+			pb = m_vertices[0];
+			break;
+		case 3:
+			pa = m_vertices[0];
+			pb = m_vertices[3];
+			break;
+		case 4:
+			pa = m_vertices[1];
+			pb = m_vertices[3];
+			break;
+		case 5:
+			pa = m_vertices[2];
+			pb = m_vertices[3];
+			break;
+		}
+
+	}
+
+
+
+
+}
+
+void btBU_Simplex1to4::getVertex(int i,btVector3& vtx) const
+{
+	vtx = m_vertices[i];
+}
+
+int	btBU_Simplex1to4::getNumPlanes() const
+{
+	switch (m_numVertices)
+	{
+	case 0:
+			return 0;
+	case 1:
+			return 0;
+	case 2:
+			return 0;
+	case 3:
+			return 2;
+	case 4:
+			return 4;
+	default:
+		{
+		}
+	}
+	return 0;
+}
+
+
+void btBU_Simplex1to4::getPlane(btVector3&, btVector3& ,int ) const
+{
+	
+}
+
+int btBU_Simplex1to4::getIndex(int ) const
+{
+	return 0;
+}
+
+bool btBU_Simplex1to4::isInside(const btVector3& ,btScalar ) const
+{
+	return false;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLEX_1TO4_SHAPE
+#define BT_SIMPLEX_1TO4_SHAPE
+
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+
+
+///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
+class btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
+{
+protected:
+
+	int	m_numVertices;
+	btVector3	m_vertices[4];
+
+public:
+	btBU_Simplex1to4();
+
+	btBU_Simplex1to4(const btVector3& pt0);
+	btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1);
+	btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2);
+	btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3);
+
+    
+	void	reset()
+	{
+		m_numVertices = 0;
+	}
+	
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	void addVertex(const btVector3& pt);
+
+	//PolyhedralConvexShape interface
+
+	virtual int	getNumVertices() const;
+
+	virtual int getNumEdges() const;
+
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	
+	virtual void getVertex(int i,btVector3& vtx) const;
+
+	virtual int	getNumPlanes() const;
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const;
+
+	virtual int getIndex(int i) const;
+
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+
+	///getName is for debugging
+	virtual const char*	getName()const { return "btBU_Simplex1to4";}
+
+};
+
+#endif //BT_SIMPLEX_1TO4_SHAPE
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp	(revision 11817)
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleBuffer.h"
+
+
+
+
+
+
+
+void btTriangleBuffer::processTriangle(btVector3* triangle,int partId,int  triangleIndex)
+{
+		btTriangle	tri;
+		tri.m_vertex0 = triangle[0];
+		tri.m_vertex1 = triangle[1];
+		tri.m_vertex2 = triangle[2];
+		tri.m_partId = partId;
+		tri.m_triangleIndex = triangleIndex;
+			
+		m_triangleBuffer.push_back(tri);
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_BUFFER_H
+#define BT_TRIANGLE_BUFFER_H
+
+#include "btTriangleCallback.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct	btTriangle
+{
+	btVector3	m_vertex0;
+	btVector3	m_vertex1;
+	btVector3	m_vertex2;
+	int	m_partId;
+	int	m_triangleIndex;
+};
+
+///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
+///Example usage of this class:
+///			btTriangleBuffer	triBuf;
+///			concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
+///			for (int i=0;i<triBuf.getNumTriangles();i++)
+///			{
+///				const btTriangle& tri = triBuf.getTriangle(i);
+///				//do something useful here with the triangle
+///			}
+class btTriangleBuffer : public btTriangleCallback
+{
+
+	btAlignedObjectArray<btTriangle>	m_triangleBuffer;
+	
+public:
+
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+	
+	int	getNumTriangles() const
+	{
+		return int(m_triangleBuffer.size());
+	}
+	
+	const btTriangle&	getTriangle(int index) const
+	{
+		return m_triangleBuffer[index];
+	}
+
+	void	clearBuffer()
+	{
+		m_triangleBuffer.clear();
+	}
+	
+};
+
+
+#endif //BT_TRIANGLE_BUFFER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp	(revision 11817)
@@ -0,0 +1,28 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleCallback.h"
+
+btTriangleCallback::~btTriangleCallback()
+{
+
+}
+
+
+btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback()
+{
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_CALLBACK_H
+#define BT_TRIANGLE_CALLBACK_H
+
+#include "LinearMath/btVector3.h"
+
+
+///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
+///This callback is called by processAllTriangles for all btConcaveShape derived class, such as  btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
+class btTriangleCallback
+{
+public:
+
+	virtual ~btTriangleCallback();
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+class btInternalTriangleIndexCallback
+{
+public:
+
+	virtual ~btInternalTriangleIndexCallback();
+	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex) = 0;
+};
+
+
+
+#endif //BT_TRIANGLE_CALLBACK_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleIndexVertexArray.h"
+
+btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride)
+: m_hasAabb(0)
+{
+	btIndexedMesh mesh;
+
+	mesh.m_numTriangles = numTriangles;
+	mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
+	mesh.m_triangleIndexStride = triangleIndexStride;
+	mesh.m_numVertices = numVertices;
+	mesh.m_vertexBase = (const unsigned char *)vertexBase;
+	mesh.m_vertexStride = vertexStride;
+
+	addIndexedMesh(mesh);
+
+}
+
+btTriangleIndexVertexArray::~btTriangleIndexVertexArray()
+{
+
+}
+
+void	btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
+{
+	btAssert(subpart< getNumSubParts() );
+
+	btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+	numverts = mesh.m_numVertices;
+	(*vertexbase) = (unsigned char *) mesh.m_vertexBase;
+
+   type = mesh.m_vertexType;
+
+	vertexStride = mesh.m_vertexStride;
+
+	numfaces = mesh.m_numTriangles;
+
+	(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
+	indexstride = mesh.m_triangleIndexStride;
+	indicestype = mesh.m_indexType;
+}
+
+void	btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
+{
+	const btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+	numverts = mesh.m_numVertices;
+	(*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
+
+   type = mesh.m_vertexType;
+   
+	vertexStride = mesh.m_vertexStride;
+
+	numfaces = mesh.m_numTriangles;
+	(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
+	indexstride = mesh.m_triangleIndexStride;
+	indicestype = mesh.m_indexType;
+}
+
+bool	btTriangleIndexVertexArray::hasPremadeAabb() const
+{
+	return (m_hasAabb == 1);
+}
+
+
+void	btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+{
+	m_aabbMin = aabbMin;
+	m_aabbMax = aabbMax;
+	m_hasAabb = 1; // this is intentionally an int see notes in header
+}
+
+void	btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+{
+	*aabbMin = m_aabbMin;
+	*aabbMax = m_aabbMax;
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h	(revision 11817)
@@ -0,0 +1,131 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btScalar.h"
+
+
+///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
+///Instead of the number of indices, we pass the number of triangles.
+ATTRIBUTE_ALIGNED16( struct)	btIndexedMesh
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+   int                     m_numTriangles;
+   const unsigned char *   m_triangleIndexBase;
+   int                     m_triangleIndexStride;
+   int                     m_numVertices;
+   const unsigned char *   m_vertexBase;
+   int                     m_vertexStride;
+
+   // The index type is set when adding an indexed mesh to the
+   // btTriangleIndexVertexArray, do not set it manually
+   PHY_ScalarType m_indexType;
+
+   // The vertex type has a default type similar to Bullet's precision mode (float or double)
+   // but can be set manually if you for example run Bullet with double precision but have
+   // mesh data in single precision..
+   PHY_ScalarType m_vertexType;
+
+
+   btIndexedMesh()
+	   :m_indexType(PHY_INTEGER),
+#ifdef BT_USE_DOUBLE_PRECISION
+      m_vertexType(PHY_DOUBLE)
+#else // BT_USE_DOUBLE_PRECISION
+      m_vertexType(PHY_FLOAT)
+#endif // BT_USE_DOUBLE_PRECISION
+      {
+      }
+}
+;
+
+
+typedef btAlignedObjectArray<btIndexedMesh>	IndexedMeshArray;
+
+///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
+///Additional meshes can be added using addIndexedMesh
+///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
+///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray.
+ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface
+{
+protected:
+	IndexedMeshArray	m_indexedMeshes;
+	int m_pad[2];
+	mutable int m_hasAabb; // using int instead of bool to maintain alignment
+	mutable btVector3 m_aabbMin;
+	mutable btVector3 m_aabbMax;
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btTriangleIndexVertexArray() : m_hasAabb(0)
+	{
+	}
+
+	virtual ~btTriangleIndexVertexArray();
+
+	//just to be backwards compatible
+	btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
+	
+	void	addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+	{
+		m_indexedMeshes.push_back(mesh);
+		m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
+	}
+	
+	
+	virtual void	getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
+
+	virtual void	getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
+
+	/// unLockVertexBase finishes the access to a subpart of the triangle mesh
+	/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+	virtual void	unLockVertexBase(int subpart) {(void)subpart;}
+
+	virtual void	unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
+
+	/// getNumSubParts returns the number of seperate subparts
+	/// each subpart has a continuous array of vertices and indices
+	virtual int		getNumSubParts() const { 
+		return (int)m_indexedMeshes.size();
+	}
+
+	IndexedMeshArray&	getIndexedMeshArray()
+	{
+		return m_indexedMeshes;
+	}
+
+	const IndexedMeshArray&	getIndexedMeshArray() const
+	{
+		return m_indexedMeshes;
+	}
+
+	virtual void	preallocateVertices(int numverts){(void) numverts;}
+	virtual void	preallocateIndices(int numindices){(void) numindices;}
+
+	virtual bool	hasPremadeAabb() const;
+	virtual void	setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const;
+	virtual void	getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const;
+
+}
+;
+
+#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was created by Alex Silverman
+
+#include "btTriangleIndexVertexMaterialArray.h"
+
+btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+                                   int numVertices,btScalar* vertexBase,int vertexStride,
+                                   int numMaterials, unsigned char* materialBase, int materialStride,
+                                   int* triangleMaterialsBase, int materialIndexStride) :
+btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
+{
+    btMaterialProperties mat;
+
+    mat.m_numMaterials = numMaterials;
+    mat.m_materialBase = materialBase;
+    mat.m_materialStride = materialStride;
+#ifdef BT_USE_DOUBLE_PRECISION
+    mat.m_materialType = PHY_DOUBLE;
+#else
+    mat.m_materialType = PHY_FLOAT;
+#endif
+
+    mat.m_numTriangles = numTriangles;
+    mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
+    mat.m_triangleMaterialStride = materialIndexStride;
+    mat.m_triangleType = PHY_INTEGER;
+
+    addMaterialProperties(mat);
+}
+
+
+void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+                                   unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+    btAssert(subpart< getNumSubParts() );
+
+    btMaterialProperties& mats = m_materials[subpart];
+
+    numMaterials = mats.m_numMaterials;
+    (*materialBase) = (unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+    materialType = PHY_DOUBLE;
+#else
+    materialType = PHY_FLOAT;
+#endif
+    materialStride = mats.m_materialStride;
+
+    numTriangles = mats.m_numTriangles;
+    (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
+    triangleMaterialStride = mats.m_triangleMaterialStride;
+    triangleType = mats.m_triangleType;
+}
+
+void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+                                           const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+    btMaterialProperties& mats = m_materials[subpart];
+
+    numMaterials = mats.m_numMaterials;
+    (*materialBase) = (const unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+    materialType = PHY_DOUBLE;
+#else
+    materialType = PHY_FLOAT;
+#endif
+    materialStride = mats.m_materialStride;
+
+    numTriangles = mats.m_numTriangles;
+    (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
+    triangleMaterialStride = mats.m_triangleMaterialStride;
+    triangleType = mats.m_triangleType;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was created by Alex Silverman
+
+#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btTriangleIndexVertexArray.h"
+
+
+ATTRIBUTE_ALIGNED16( struct)	btMaterialProperties
+{
+    ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
+    int m_numMaterials;
+    const unsigned char * m_materialBase;
+    int m_materialStride;
+    PHY_ScalarType m_materialType;
+    ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
+    ///                           padding the structure, it can be reproduced at no real cost
+    ///m_triangleMaterials =====> 1 integer value makes up one entry
+    ///                           eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
+    int m_numTriangles; 
+    const unsigned char * m_triangleMaterialsBase;
+    int m_triangleMaterialStride;
+    ///m_triangleType <========== Automatically set in addMaterialProperties
+    PHY_ScalarType m_triangleType;
+};
+
+typedef btAlignedObjectArray<btMaterialProperties>	MaterialArray;
+
+///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
+///The addition of a material array allows for the utilization of the partID and
+///triangleIndex that are returned in the ContactAddedCallback.  As with
+///TriangleIndexVertexArray, no duplicate is made of the material data, so it
+///is the users responsibility to maintain the array during the lifetime of the
+///TriangleIndexVertexMaterialArray.
+ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
+{
+protected:
+    MaterialArray       m_materials;
+		
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+    btTriangleIndexVertexMaterialArray()
+	{
+	}
+
+    btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+        int numVertices,btScalar* vertexBase,int vertexStride,
+        int numMaterials, unsigned char* materialBase, int materialStride,
+        int* triangleMaterialsBase, int materialIndexStride);
+
+    virtual ~btTriangleIndexVertexMaterialArray() {}
+
+    void	addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
+    {
+        m_materials.push_back(mat);
+        m_materials[m_materials.size()-1].m_triangleType = triangleType;
+    }
+
+    virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+        unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
+
+    virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+        const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
+
+}
+;
+
+#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h	(revision 11817)
@@ -0,0 +1,240 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2010 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_TRIANGLE_INFO_MAP_H
+#define _BT_TRIANGLE_INFO_MAP_H
+
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btSerializer.h"
+
+
+///for btTriangleInfo m_flags
+#define TRI_INFO_V0V1_CONVEX 1
+#define TRI_INFO_V1V2_CONVEX 2
+#define TRI_INFO_V2V0_CONVEX 4
+
+#define TRI_INFO_V0V1_SWAP_NORMALB 8
+#define TRI_INFO_V1V2_SWAP_NORMALB 16
+#define TRI_INFO_V2V0_SWAP_NORMALB 32
+
+
+///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
+///it can be generated using 
+struct	btTriangleInfo
+{
+	btTriangleInfo()
+	{
+		m_edgeV0V1Angle = SIMD_2_PI;
+		m_edgeV1V2Angle = SIMD_2_PI;
+		m_edgeV2V0Angle = SIMD_2_PI;
+		m_flags=0;
+	}
+
+	int			m_flags;
+
+	btScalar	m_edgeV0V1Angle;
+	btScalar	m_edgeV1V2Angle;
+	btScalar	m_edgeV2V0Angle;
+
+};
+
+typedef btHashMap<btHashInt,btTriangleInfo> btInternalTriangleInfoMap;
+
+
+///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
+struct	btTriangleInfoMap : public btInternalTriangleInfoMap
+{
+	btScalar	m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product
+	btScalar	m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
+	btScalar	m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
+	btScalar	m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
+	btScalar	m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
+	btScalar	m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
+	
+	
+	btTriangleInfoMap()
+	{
+		m_convexEpsilon = 0.00f;
+		m_planarEpsilon = 0.0001f;
+		m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001);
+		m_edgeDistanceThreshold = btScalar(0.1);
+		m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001);
+		m_maxEdgeAngleThreshold = SIMD_2_PI;
+	}
+	virtual ~btTriangleInfoMap() {}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	void	deSerialize(struct btTriangleInfoMapData& data);
+
+};
+
+struct	btTriangleInfoData
+{
+	int			m_flags;
+	float	m_edgeV0V1Angle;
+	float	m_edgeV1V2Angle;
+	float	m_edgeV2V0Angle;
+};
+
+struct	btTriangleInfoMapData
+{
+	int					*m_hashTablePtr;
+	int					*m_nextPtr;
+	btTriangleInfoData	*m_valueArrayPtr;
+	int					*m_keyArrayPtr;
+
+	float	m_convexEpsilon;
+	float	m_planarEpsilon;
+	float	m_equalVertexThreshold; 
+	float	m_edgeDistanceThreshold;
+	float	m_zeroAreaThreshold;
+
+	int		m_nextSize;
+	int		m_hashTableSize;
+	int		m_numValues;
+	int		m_numKeys;
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btTriangleInfoMap::calculateSerializeBufferSize() const
+{
+	return sizeof(btTriangleInfoMapData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer;
+	tmapData->m_convexEpsilon = m_convexEpsilon;
+	tmapData->m_planarEpsilon = m_planarEpsilon;
+	tmapData->m_equalVertexThreshold = m_equalVertexThreshold;
+	tmapData->m_edgeDistanceThreshold = m_edgeDistanceThreshold;
+	tmapData->m_zeroAreaThreshold = m_zeroAreaThreshold;
+	
+	tmapData->m_hashTableSize = m_hashTable.size();
+
+	tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
+	if (tmapData->m_hashTablePtr)
+	{ 
+		//serialize an int buffer
+		int sz = sizeof(int);
+		int numElem = tmapData->m_hashTableSize;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		int* memPtr = (int*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			*memPtr = m_hashTable[i];
+		}
+		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]);
+
+	}
+
+	tmapData->m_nextSize = m_next.size();
+	tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0;
+	if (tmapData->m_nextPtr)
+	{
+		int sz = sizeof(int);
+		int numElem = tmapData->m_nextSize;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		int* memPtr = (int*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			*memPtr = m_next[i];
+		}
+		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]);
+	}
+	
+	tmapData->m_numValues = m_valueArray.size();
+	tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0;
+	if (tmapData->m_valueArrayPtr)
+	{
+		int sz = sizeof(btTriangleInfoData);
+		int numElem = tmapData->m_numValues;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			memPtr->m_edgeV0V1Angle = m_valueArray[i].m_edgeV0V1Angle;
+			memPtr->m_edgeV1V2Angle = m_valueArray[i].m_edgeV1V2Angle;
+			memPtr->m_edgeV2V0Angle = m_valueArray[i].m_edgeV2V0Angle;
+			memPtr->m_flags = m_valueArray[i].m_flags;
+		}
+		serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]);
+	}
+	
+	tmapData->m_numKeys = m_keyArray.size();
+	tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
+	if (tmapData->m_keyArrayPtr)
+	{
+		int sz = sizeof(int);
+		int numElem = tmapData->m_numValues;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		int* memPtr = (int*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			*memPtr = m_keyArray[i].getUid1();
+		}
+		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]);
+
+	}
+	return "btTriangleInfoMapData";
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	void	btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData )
+{
+
+
+	m_convexEpsilon = tmapData.m_convexEpsilon;
+	m_planarEpsilon = tmapData.m_planarEpsilon;
+	m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
+	m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
+	m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
+	m_hashTable.resize(tmapData.m_hashTableSize);
+	int i =0;
+	for (i=0;i<tmapData.m_hashTableSize;i++)
+	{
+		m_hashTable[i] = tmapData.m_hashTablePtr[i];
+	}
+	m_next.resize(tmapData.m_nextSize);
+	for (i=0;i<tmapData.m_nextSize;i++)
+	{
+		m_next[i] = tmapData.m_nextPtr[i];
+	}
+	m_valueArray.resize(tmapData.m_numValues);
+	for (i=0;i<tmapData.m_numValues;i++)
+	{
+		m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
+		m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
+		m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
+		m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
+	}
+	
+	m_keyArray.resize(tmapData.m_numKeys,btHashInt(0));
+	for (i=0;i<tmapData.m_numKeys;i++)
+	{
+		m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
+	}
+}
+
+
+#endif //_BT_TRIANGLE_INFO_MAP_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp	(revision 11817)
@@ -0,0 +1,140 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btTriangleMesh.h"
+
+
+
+btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices)
+:m_use32bitIndices(use32bitIndices),
+m_use4componentVertices(use4componentVertices),
+m_weldingThreshold(0.0)
+{
+	btIndexedMesh meshIndex;
+	meshIndex.m_numTriangles = 0;
+	meshIndex.m_numVertices = 0;
+	meshIndex.m_indexType = PHY_INTEGER;
+	meshIndex.m_triangleIndexBase = 0;
+	meshIndex.m_triangleIndexStride = 3*sizeof(int);
+	meshIndex.m_vertexBase = 0;
+	meshIndex.m_vertexStride = sizeof(btVector3);
+	m_indexedMeshes.push_back(meshIndex);
+
+	if (m_use32bitIndices)
+	{
+		m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3;
+		m_indexedMeshes[0].m_triangleIndexBase = 0;
+		m_indexedMeshes[0].m_indexType = PHY_INTEGER;
+		m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int);
+	} else
+	{
+		m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3;
+		m_indexedMeshes[0].m_triangleIndexBase = 0;
+		m_indexedMeshes[0].m_indexType = PHY_SHORT;
+		m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int);
+	}
+
+	if (m_use4componentVertices)
+	{
+		m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
+		m_indexedMeshes[0].m_vertexBase = 0;
+		m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
+	} else
+	{
+		m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3;
+		m_indexedMeshes[0].m_vertexBase = 0;
+		m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar);
+	}
+
+
+}
+
+void	btTriangleMesh::addIndex(int index)
+{
+	if (m_use32bitIndices)
+	{
+		m_32bitIndices.push_back(index);
+		m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
+	} else
+	{
+		m_16bitIndices.push_back(index);
+		m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
+	}
+}
+
+
+int	btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
+{
+	//return index of new/existing vertex
+	///@todo: could use acceleration structure for this
+	if (m_use4componentVertices)
+	{
+		if (removeDuplicateVertices)
+			{
+			for (int i=0;i< m_4componentVertices.size();i++)
+			{
+				if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold)
+				{
+					return i;
+				}
+			}
+		}
+		m_indexedMeshes[0].m_numVertices++;
+		m_4componentVertices.push_back(vertex);
+		m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
+
+		return m_4componentVertices.size()-1;
+		
+	} else
+	{
+		
+		if (removeDuplicateVertices)
+		{
+			for (int i=0;i< m_3componentVertices.size();i+=3)
+			{
+				btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]);
+				if ((vtx-vertex).length2() <= m_weldingThreshold)
+				{
+					return i/3;
+				}
+			}
+	}
+		m_3componentVertices.push_back((float)vertex.getX());
+		m_3componentVertices.push_back((float)vertex.getY());
+		m_3componentVertices.push_back((float)vertex.getZ());
+		m_indexedMeshes[0].m_numVertices++;
+		m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
+		return (m_3componentVertices.size()/3)-1;
+	}
+
+}
+		
+void	btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2,bool removeDuplicateVertices)
+{
+	m_indexedMeshes[0].m_numTriangles++;
+	addIndex(findOrAddVertex(vertex0,removeDuplicateVertices));
+	addIndex(findOrAddVertex(vertex1,removeDuplicateVertices));
+	addIndex(findOrAddVertex(vertex2,removeDuplicateVertices));
+}
+
+int btTriangleMesh::getNumTriangles() const
+{
+	if (m_use32bitIndices)
+	{
+		return m_32bitIndices.size() / 3;
+	}
+	return m_16bitIndices.size() / 3;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_MESH_H
+#define BT_TRIANGLE_MESH_H
+
+#include "btTriangleIndexVertexArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape.
+///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices.
+///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface.
+///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
+class btTriangleMesh : public btTriangleIndexVertexArray
+{
+	btAlignedObjectArray<btVector3>	m_4componentVertices;
+	btAlignedObjectArray<float>		m_3componentVertices;
+
+	btAlignedObjectArray<unsigned int>		m_32bitIndices;
+	btAlignedObjectArray<unsigned short int>		m_16bitIndices;
+	bool	m_use32bitIndices;
+	bool	m_use4componentVertices;
+	
+
+	public:
+		btScalar	m_weldingThreshold;
+
+		btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true);
+
+		bool	getUse32bitIndices() const
+		{
+			return m_use32bitIndices;
+		}
+
+		bool	getUse4componentVertices() const
+		{
+			return m_use4componentVertices;
+		}
+		///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
+		///In general it is better to directly use btTriangleIndexVertexArray instead.
+		void	addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false);
+		
+		int getNumTriangles() const;
+
+		virtual void	preallocateVertices(int numverts){(void) numverts;}
+		virtual void	preallocateIndices(int numindices){(void) numindices;}
+
+		///findOrAddVertex is an internal method, use addTriangle instead
+		int		findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
+		///addIndex is an internal method, use addTriangle instead
+		void	addIndex(int index);
+		
+};
+
+#endif //BT_TRIANGLE_MESH_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp	(revision 11817)
@@ -0,0 +1,211 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleMeshShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btQuaternion.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+
+btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
+: btConcaveShape (), m_meshInterface(meshInterface)
+{
+	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	if(meshInterface->hasPremadeAabb())
+	{
+		meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
+	}
+	else
+	{
+		recalcLocalAabb();
+	}
+}
+
+
+btTriangleMeshShape::~btTriangleMeshShape()
+{
+		
+}
+
+
+
+
+void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+	btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
+	localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
+	btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
+	
+	btMatrix3x3 abs_b = trans.getBasis().absolute();  
+
+	btVector3 center = trans(localCenter);
+
+	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+		   abs_b[1].dot(localHalfExtents),
+		  abs_b[2].dot(localHalfExtents));
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+
+
+}
+
+void	btTriangleMeshShape::recalcLocalAabb()
+{
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 tmp = localGetSupportingVertex(vec);
+		m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+		vec[i] = btScalar(-1.);
+		tmp = localGetSupportingVertex(vec);
+		m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+	}
+}
+
+
+
+class SupportVertexCallback : public btTriangleCallback
+{
+
+	btVector3 m_supportVertexLocal;
+public:
+
+	btTransform	m_worldTrans;
+	btScalar m_maxDot;
+	btVector3 m_supportVecLocal;
+
+	SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans)
+		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-BT_LARGE_FLOAT))
+		
+	{
+		m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
+	}
+
+	virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex)
+	{
+		(void)partId;
+		(void)triangleIndex;
+		for (int i=0;i<3;i++)
+		{
+			btScalar dot = m_supportVecLocal.dot(triangle[i]);
+			if (dot > m_maxDot)
+			{
+				m_maxDot = dot;
+				m_supportVertexLocal = triangle[i];
+			}
+		}
+	}
+
+	btVector3 GetSupportVertexWorldSpace()
+	{
+		return m_worldTrans(m_supportVertexLocal);
+	}
+
+	btVector3	GetSupportVertexLocal()
+	{
+		return m_supportVertexLocal;
+	}
+
+};
+
+	
+void btTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+	m_meshInterface->setScaling(scaling);
+	recalcLocalAabb();
+}
+
+const btVector3& btTriangleMeshShape::getLocalScaling() const
+{
+	return m_meshInterface->getScaling();
+}
+
+
+
+
+
+
+//#define DEBUG_TRIANGLE_MESH
+
+
+
+void	btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+		struct FilteredCallback : public btInternalTriangleIndexCallback
+	{
+		btTriangleCallback* m_callback;
+		btVector3 m_aabbMin;
+		btVector3 m_aabbMax;
+
+		FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax)
+			:m_callback(callback),
+			m_aabbMin(aabbMin),
+			m_aabbMax(aabbMax)
+		{
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+		{
+			if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax))
+			{
+				//check aabb in triangle-space, before doing this
+				m_callback->processTriangle(triangle,partId,triangleIndex);
+			}
+			
+		}
+
+	};
+
+	FilteredCallback filterCallback(callback,aabbMin,aabbMax);
+
+	m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax);
+}
+
+
+
+
+
+void	btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	(void)mass;
+	//moving concave objects not supported
+	btAssert(0);
+	inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+
+btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
+{
+	btVector3 supportVertex;
+
+	btTransform ident;
+	ident.setIdentity();
+
+	SupportVertexCallback supportCallback(vec,ident);
+
+	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	
+	processAllTriangles(&supportCallback,-aabbMax,aabbMax);
+		
+	supportVertex = supportCallback.GetSupportVertexLocal();
+
+	return supportVertex;
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_MESH_SHAPE_H
+#define BT_TRIANGLE_MESH_SHAPE_H
+
+#include "btConcaveShape.h"
+#include "btStridingMeshInterface.h"
+
+
+///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
+class btTriangleMeshShape : public btConcaveShape
+{
+protected:
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	btStridingMeshInterface* m_meshInterface;
+
+	///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
+	///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
+	btTriangleMeshShape(btStridingMeshInterface* meshInterface);
+
+public:
+
+	virtual ~btTriangleMeshShape();
+
+	virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+	{
+		btAssert(0);
+		return localGetSupportingVertex(vec);
+	}
+
+	void	recalcLocalAabb();
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+	
+	btStridingMeshInterface* getMeshInterface()
+	{
+		return m_meshInterface;
+	}
+
+	const btStridingMeshInterface* getMeshInterface() const
+	{
+		return m_meshInterface;
+	}
+
+	const btVector3& getLocalAabbMin() const
+	{
+		return m_localAabbMin;
+	}
+	const btVector3& getLocalAabbMax() const
+	{
+		return m_localAabbMax;
+	}
+
+
+
+	//debugging
+	virtual const char*	getName()const {return "TRIANGLEMESH";}
+
+	
+
+};
+
+
+
+
+#endif //BT_TRIANGLE_MESH_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btTriangleShape.h	(revision 11817)
@@ -0,0 +1,182 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_OBB_TRIANGLE_MINKOWSKI_H
+#define BT_OBB_TRIANGLE_MINKOWSKI_H
+
+#include "btConvexShape.h"
+#include "btBoxShape.h"
+
+ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape
+{
+
+
+public:
+
+	btVector3	m_vertices1[3];
+
+	virtual int getNumVertices() const
+	{
+		return 3;
+	}
+
+	btVector3& getVertexPtr(int index)
+	{
+		return m_vertices1[index];
+	}
+
+	const btVector3& getVertexPtr(int index) const
+	{
+		return m_vertices1[index];
+	}
+	virtual void getVertex(int index,btVector3& vert) const
+	{
+		vert = m_vertices1[index];
+	}
+
+	virtual int getNumEdges() const
+	{
+		return 3;
+	}
+	
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+	{
+		getVertex(i,pa);
+		getVertex((i+1)%3,pb);
+	}
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const 
+	{
+//		btAssert(0);
+		getAabbSlow(t,aabbMin,aabbMax);
+	}
+
+	btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const 
+	{
+		btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
+	  	return m_vertices1[dots.maxAxis()];
+
+	}
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			const btVector3& dir = vectors[i];
+			btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
+  			supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
+		}
+
+	}
+
+	btTriangleShape() : btPolyhedralConvexShape ()
+    {
+		m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+	}
+
+	btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) : btPolyhedralConvexShape ()
+    {
+		m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+        m_vertices1[0] = p0;
+        m_vertices1[1] = p1;
+        m_vertices1[2] = p2;
+    }
+
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const
+	{
+		getPlaneEquation(i,planeNormal,planeSupport);
+	}
+
+	virtual int	getNumPlanes() const
+	{
+		return 1;
+	}
+
+	void calcNormal(btVector3& normal) const
+	{
+		normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+		normal.normalize();
+	}
+
+	virtual void getPlaneEquation(int i, btVector3& planeNormal,btVector3& planeSupport) const
+	{
+		(void)i;
+		calcNormal(planeNormal);
+		planeSupport = m_vertices1[0];
+	}
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const
+	{
+		(void)mass;
+		btAssert(0);
+		inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	}
+
+		virtual	bool isInside(const btVector3& pt,btScalar tolerance) const
+	{
+		btVector3 normal;
+		calcNormal(normal);
+		//distance to plane
+		btScalar dist = pt.dot(normal);
+		btScalar planeconst = m_vertices1[0].dot(normal);
+		dist -= planeconst;
+		if (dist >= -tolerance && dist <= tolerance)
+		{
+			//inside check on edge-planes
+			int i;
+			for (i=0;i<3;i++)
+			{
+				btVector3 pa,pb;
+				getEdge(i,pa,pb);
+				btVector3 edge = pb-pa;
+				btVector3 edgeNormal = edge.cross(normal);
+				edgeNormal.normalize();
+				btScalar dist = pt.dot( edgeNormal);
+				btScalar edgeConst = pa.dot(edgeNormal);
+				dist -= edgeConst;
+				if (dist < -tolerance)
+					return false;
+			}
+			
+			return true;
+		}
+
+		return false;
+	}
+		//debugging
+		virtual const char*	getName()const
+		{
+			return "Triangle";
+		}
+
+		virtual int		getNumPreferredPenetrationDirections() const
+		{
+			return 2;
+		}
+		
+		virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+		{
+			calcNormal(penetrationVector);
+			if (index)
+				penetrationVector *= btScalar(-1.);
+		}
+
+
+};
+
+#endif //BT_OBB_TRIANGLE_MINKOWSKI_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp	(revision 11817)
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btUniformScalingShape.h"
+
+btUniformScalingShape::btUniformScalingShape(	btConvexShape* convexChildShape,btScalar uniformScalingFactor):
+btConvexShape (), m_childConvexShape(convexChildShape),
+m_uniformScalingFactor(uniformScalingFactor)
+{
+	m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE;
+}
+	
+btUniformScalingShape::~btUniformScalingShape()
+{
+}
+	
+
+btVector3	btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	btVector3 tmpVertex;
+	tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+	return tmpVertex*m_uniformScalingFactor;
+}
+
+void	btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+	int i;
+	for (i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
+	}
+}
+
+
+btVector3	btUniformScalingShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 tmpVertex;
+	tmpVertex = m_childConvexShape->localGetSupportingVertex(vec);
+	return tmpVertex*m_uniformScalingFactor;
+}
+
+
+void	btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+	///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+	btVector3 tmpInertia;
+	m_childConvexShape->calculateLocalInertia(mass,tmpInertia);
+	inertia = tmpInertia * m_uniformScalingFactor;
+}
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btUniformScalingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	getAabbSlow(trans,aabbMin,aabbMax);
+
+}
+
+void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+#if 1
+	btVector3 _directions[] =
+	{
+		btVector3( 1.,  0.,  0.),
+		btVector3( 0.,  1.,  0.),
+		btVector3( 0.,  0.,  1.),
+		btVector3( -1., 0.,  0.),
+		btVector3( 0., -1.,  0.),
+		btVector3( 0.,  0., -1.)
+	};
+	
+	btVector3 _supporting[] =
+	{
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.)
+	};
+
+	for (int i=0;i<6;i++)
+	{
+		_directions[i] = _directions[i]*t.getBasis();
+	}
+	
+	batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+	
+	btVector3 aabbMin1(0,0,0),aabbMax1(0,0,0);
+
+	for ( int i = 0; i < 3; ++i )
+	{
+		aabbMax1[i] = t(_supporting[i])[i];
+		aabbMin1[i] = t(_supporting[i + 3])[i];
+	}
+	btVector3 marginVec(getMargin(),getMargin(),getMargin());
+	aabbMin = aabbMin1-marginVec;
+	aabbMax = aabbMax1+marginVec;
+	
+#else
+
+	btScalar margin = getMargin();
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 sv = localGetSupportingVertex(vec*t.getBasis());
+		btVector3 tmp = t(sv);
+		aabbMax[i] = tmp[i]+margin;
+		vec[i] = btScalar(-1.);
+		sv = localGetSupportingVertex(vec*t.getBasis());
+		tmp = t(sv);
+		aabbMin[i] = tmp[i]-margin;
+	}
+
+#endif
+}
+
+void	btUniformScalingShape::setLocalScaling(const btVector3& scaling) 
+{
+	m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btUniformScalingShape::getLocalScaling() const
+{
+	return m_childConvexShape->getLocalScaling();
+}
+
+void	btUniformScalingShape::setMargin(btScalar margin)
+{
+	m_childConvexShape->setMargin(margin);
+}
+btScalar	btUniformScalingShape::getMargin() const
+{
+	return m_childConvexShape->getMargin() * m_uniformScalingFactor;
+}
+
+int		btUniformScalingShape::getNumPreferredPenetrationDirections() const
+{
+	return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+	
+void	btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+	m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_UNIFORM_SCALING_SHAPE_H
+#define BT_UNIFORM_SCALING_SHAPE_H
+
+#include "btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
+///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
+class btUniformScalingShape : public btConvexShape
+{
+	btConvexShape*	m_childConvexShape;
+
+	btScalar	m_uniformScalingFactor;
+	
+	public:
+	
+	btUniformScalingShape(	btConvexShape* convexChildShape, btScalar uniformScalingFactor);
+	
+	virtual ~btUniformScalingShape();
+	
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	btScalar	getUniformScalingFactor() const
+	{
+		return m_uniformScalingFactor;
+	}
+
+	btConvexShape*	getChildShape() 
+	{
+		return m_childConvexShape;
+	}
+
+	const btConvexShape*	getChildShape() const
+	{
+		return m_childConvexShape;
+	}
+
+	virtual const char*	getName()const 
+	{
+		return "UniformScalingShape";
+	}
+	
+
+
+	///////////////////////////
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling) ;
+	virtual const btVector3& getLocalScaling() const ;
+
+	virtual void	setMargin(btScalar margin);
+	virtual btScalar	getMargin() const;
+
+	virtual int		getNumPreferredPenetrationDirections() const;
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+
+
+};
+
+#endif //BT_UNIFORM_SCALING_SHAPE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp	(revision 11817)
@@ -0,0 +1,243 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btContinuousConvexCollision.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+
+
+btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape*	convexA,const btConvexShape*	convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
+:m_simplexSolver(simplexSolver),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_convexA(convexA),m_convexB1(convexB),m_planeShape(0)
+{
+}
+
+
+btContinuousConvexCollision::btContinuousConvexCollision( const btConvexShape*	convexA,const btStaticPlaneShape*	plane)
+:m_simplexSolver(0),
+m_penetrationDepthSolver(0),
+m_convexA(convexA),m_convexB1(0),m_planeShape(plane)
+{
+}
+
+
+/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
+/// You don't want your game ever to lock-up.
+#define MAX_ITERATIONS 64
+
+void btContinuousConvexCollision::computeClosestPoints( const btTransform& transA, const btTransform& transB,btPointCollector& pointCollector)
+{
+	if (m_convexB1)
+	{
+		m_simplexSolver->reset();
+		btGjkPairDetector gjk(m_convexA,m_convexB1,m_convexA->getShapeType(),m_convexB1->getShapeType(),m_convexA->getMargin(),m_convexB1->getMargin(),m_simplexSolver,m_penetrationDepthSolver);		
+		btGjkPairDetector::ClosestPointInput input;
+		input.m_transformA = transA;
+		input.m_transformB = transB;
+		gjk.getClosestPoints(input,pointCollector,0);
+	} else
+	{
+		//convex versus plane
+		const btConvexShape* convexShape = m_convexA;
+		const btStaticPlaneShape* planeShape = m_planeShape;
+		
+		bool hasCollision = false;
+		const btVector3& planeNormal = planeShape->getPlaneNormal();
+		const btScalar& planeConstant = planeShape->getPlaneConstant();
+		
+		btTransform convexWorldTransform = transA;
+		btTransform convexInPlaneTrans;
+		convexInPlaneTrans= transB.inverse() * convexWorldTransform;
+		btTransform planeInConvex;
+		planeInConvex= convexWorldTransform.inverse() * transB;
+		
+		btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+
+		btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+		btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+		btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+		btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
+		btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
+
+		pointCollector.addContactPoint(
+			normalOnSurfaceB,
+			vtxInPlaneWorld,
+			distance);
+	}
+}
+
+bool	btContinuousConvexCollision::calcTimeOfImpact(
+				const btTransform& fromA,
+				const btTransform& toA,
+				const btTransform& fromB,
+				const btTransform& toB,
+				CastResult& result)
+{
+
+
+	/// compute linear and angular velocity for this interval, to interpolate
+	btVector3 linVelA,angVelA,linVelB,angVelB;
+	btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
+	btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
+
+
+	btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
+	btScalar boundingRadiusB = m_convexB1?m_convexB1->getAngularMotionDisc():0.f;
+
+	btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
+	btVector3 relLinVel = (linVelB-linVelA);
+
+	btScalar relLinVelocLength = (linVelB-linVelA).length();
+	
+	if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
+		return false;
+
+
+
+	btScalar lambda = btScalar(0.);
+	btVector3 v(1,0,0);
+
+	int maxIter = MAX_ITERATIONS;
+
+	btVector3 n;
+	n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	bool hasResult = false;
+	btVector3 c;
+
+	btScalar lastLambda = lambda;
+	//btScalar epsilon = btScalar(0.001);
+
+	int numIter = 0;
+	//first solution, using GJK
+
+
+	btScalar radius = 0.001f;
+//	result.drawCoordSystem(sphereTr);
+
+	btPointCollector	pointCollector1;
+
+	{
+	
+		computeClosestPoints(fromA,fromB,pointCollector1);
+
+		hasResult = pointCollector1.m_hasResult;
+		c = pointCollector1.m_pointInWorld;
+	}
+
+	if (hasResult)
+	{
+		btScalar dist;
+		dist = pointCollector1.m_distance + result.m_allowedPenetration;
+		n = pointCollector1.m_normalOnBInWorld;
+		btScalar projectedLinearVelocity = relLinVel.dot(n);
+		if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+			return false;
+
+		//not close enough
+		while (dist > radius)
+		{
+			if (result.m_debugDrawer)
+			{
+				result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1));
+			}
+			btScalar dLambda = btScalar(0.);
+
+			projectedLinearVelocity = relLinVel.dot(n);
+
+			
+			//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+			if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+				return false;
+			
+			dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
+
+			
+			
+			lambda = lambda + dLambda;
+
+			if (lambda > btScalar(1.))
+				return false;
+
+			if (lambda < btScalar(0.))
+				return false;
+
+
+			//todo: next check with relative epsilon
+			if (lambda <= lastLambda)
+			{
+				return false;
+				//n.setValue(0,0,0);
+				break;
+			}
+			lastLambda = lambda;
+
+			
+
+			//interpolate to next lambda
+			btTransform interpolatedTransA,interpolatedTransB,relativeTrans;
+
+			btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
+			btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
+			relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
+
+			if (result.m_debugDrawer)
+			{
+				result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0));
+			}
+
+			result.DebugDraw( lambda );
+
+			btPointCollector	pointCollector;
+			computeClosestPoints(interpolatedTransA,interpolatedTransB,pointCollector);
+
+			if (pointCollector.m_hasResult)
+			{
+				dist = pointCollector.m_distance+result.m_allowedPenetration;
+				c = pointCollector.m_pointInWorld;		
+				n = pointCollector.m_normalOnBInWorld;
+			} else
+			{
+				result.reportFailure(-1, numIter);
+				return false;
+			}
+
+			numIter++;
+			if (numIter > maxIter)
+			{
+				result.reportFailure(-2, numIter);
+				return false;
+			}
+		}
+	
+		result.m_fraction = lambda;
+		result.m_normal = n;
+		result.m_hitPoint = c;
+		return true;
+	}
+
+	return false;
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+class btConvexShape;
+class btStaticPlaneShape;
+
+/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
+/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
+/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent.
+/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops
+class btContinuousConvexCollision : public btConvexCast
+{
+	btSimplexSolverInterface* m_simplexSolver;
+	btConvexPenetrationDepthSolver*	m_penetrationDepthSolver;
+	const btConvexShape*	m_convexA;
+	//second object is either a convex or a plane (code sharing)
+	const btConvexShape*	m_convexB1;
+	const btStaticPlaneShape*	m_planeShape;
+
+	void computeClosestPoints( const btTransform& transA, const btTransform& transB,struct btPointCollector& pointCollector);
+
+public:
+
+	btContinuousConvexCollision (const btConvexShape*	shapeA,const btConvexShape*	shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
+
+	btContinuousConvexCollision(const btConvexShape*	shapeA,const btStaticPlaneShape*	plane );
+
+	virtual bool	calcTimeOfImpact(
+				const btTransform& fromA,
+				const btTransform& toA,
+				const btTransform& fromB,
+				const btTransform& toB,
+				CastResult& result);
+
+
+};
+
+
+#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp	(revision 11817)
@@ -0,0 +1,20 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexCast.h"
+
+btConvexCast::~btConvexCast()
+{
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_CONVEX_CAST_H
+#define BT_CONVEX_CAST_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"
+class btMinkowskiSumShape;
+#include "LinearMath/btIDebugDraw.h"
+
+/// btConvexCast is an interface for Casting
+class btConvexCast
+{
+public:
+
+
+	virtual ~btConvexCast();
+
+	///RayResult stores the closest result
+	/// alternatively, add a callback method to decide about closest/all results
+	struct	CastResult
+	{
+		//virtual bool	addRayResult(const btVector3& normal,btScalar	fraction) = 0;
+				
+		virtual void	DebugDraw(btScalar	fraction) {(void)fraction;}
+		virtual void	drawCoordSystem(const btTransform& trans) {(void)trans;}
+		virtual void	reportFailure(int errNo, int numIterations) {(void)errNo;(void)numIterations;}
+		CastResult()
+			:m_fraction(btScalar(BT_LARGE_FLOAT)),
+			m_debugDrawer(0),
+			m_allowedPenetration(btScalar(0))
+		{
+		}
+
+
+		virtual ~CastResult() {};
+
+		btTransform	m_hitTransformA;
+		btTransform	m_hitTransformB;
+		btVector3	m_normal;
+		btVector3   m_hitPoint;
+		btScalar	m_fraction; //input and output
+		btIDebugDraw* m_debugDrawer;
+		btScalar	m_allowedPenetration;
+
+	};
+
+
+	/// cast a convex against another convex object
+	virtual bool	calcTimeOfImpact(
+					const btTransform& fromA,
+					const btTransform& toA,
+					const btTransform& fromB,
+					const btTransform& toB,
+					CastResult& result) = 0;
+};
+
+#endif //BT_CONVEX_CAST_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_CONVEX_PENETRATION_DEPTH_H
+#define BT_CONVEX_PENETRATION_DEPTH_H
+
+class btStackAlloc;
+class btVector3;
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+class btTransform;
+
+///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
+class btConvexPenetrationDepthSolver
+{
+public:	
+	
+	virtual ~btConvexPenetrationDepthSolver() {};
+	virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+		const btConvexShape* convexA,const btConvexShape* convexB,
+					const btTransform& transA,const btTransform& transB,
+				btVector3& v, btVector3& pa, btVector3& pb,
+				class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
+				) = 0;
+
+
+};
+#endif //BT_CONVEX_PENETRATION_DEPTH_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+class btStackAlloc;
+
+/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations
+/// This interface allows to query for closest points and penetration depth between two (convex) objects
+/// the closest point is on the second object (B), and the normal points from the surface on B towards A.
+/// distance is between closest points on B and closest point on A. So you can calculate closest point on A
+/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
+struct btDiscreteCollisionDetectorInterface
+{
+	
+	struct Result
+	{
+	
+		virtual ~Result(){}	
+
+		///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
+		virtual void setShapeIdentifiersA(int partId0,int index0)=0;
+		virtual void setShapeIdentifiersB(int partId1,int index1)=0;
+		virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0;
+	};
+
+	struct ClosestPointInput
+	{
+		ClosestPointInput()
+			:m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT)),
+			m_stackAlloc(0)
+		{
+		}
+
+		btTransform m_transformA;
+		btTransform m_transformB;
+		btScalar	m_maximumDistanceSquared;
+		btStackAlloc* m_stackAlloc;
+	};
+
+	virtual ~btDiscreteCollisionDetectorInterface() {};
+
+	//
+	// give either closest points (distance > 0) or penetration (distance)
+	// the normal always points from B towards A
+	//
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0;
+
+};
+
+struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
+{
+		btVector3	m_normalOnSurfaceB;
+		btVector3	m_closestPointInB;
+		btScalar	m_distance; //negative means penetration !
+
+		btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
+		{
+
+		}
+		virtual ~btStorageResult() {};
+
+		virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+		{
+			if (depth < m_distance)
+			{
+				m_normalOnSurfaceB = normalOnBInWorld;
+				m_closestPointInB = pointInWorld;
+				m_distance = depth;
+			}
+		}
+};
+
+#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp	(revision 11817)
@@ -0,0 +1,176 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btGjkConvexCast.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
+
+btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
+:m_simplexSolver(simplexSolver),
+m_convexA(convexA),
+m_convexB(convexB)
+{
+}
+
+bool	btGjkConvexCast::calcTimeOfImpact(
+					const btTransform& fromA,
+					const btTransform& toA,
+					const btTransform& fromB,
+					const btTransform& toB,
+					CastResult& result)
+{
+
+
+	m_simplexSolver->reset();
+
+	/// compute linear velocity for this interval, to interpolate
+	//assume no rotation/angular velocity, assert here?
+	btVector3 linVelA,linVelB;
+	linVelA = toA.getOrigin()-fromA.getOrigin();
+	linVelB = toB.getOrigin()-fromB.getOrigin();
+
+	btScalar radius = btScalar(0.001);
+	btScalar lambda = btScalar(0.);
+	btVector3 v(1,0,0);
+
+	int maxIter = MAX_ITERATIONS;
+
+	btVector3 n;
+	n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	bool hasResult = false;
+	btVector3 c;
+	btVector3 r = (linVelA-linVelB);
+
+	btScalar lastLambda = lambda;
+	//btScalar epsilon = btScalar(0.001);
+
+	int numIter = 0;
+	//first solution, using GJK
+
+
+	btTransform identityTrans;
+	identityTrans.setIdentity();
+
+
+//	result.drawCoordSystem(sphereTr);
+
+	btPointCollector	pointCollector;
+
+		
+	btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver);		
+	btGjkPairDetector::ClosestPointInput input;
+
+	//we don't use margins during CCD
+	//	gjk.setIgnoreMargin(true);
+
+	input.m_transformA = fromA;
+	input.m_transformB = fromB;
+	gjk.getClosestPoints(input,pointCollector,0);
+
+	hasResult = pointCollector.m_hasResult;
+	c = pointCollector.m_pointInWorld;
+
+	if (hasResult)
+	{
+		btScalar dist;
+		dist = pointCollector.m_distance;
+		n = pointCollector.m_normalOnBInWorld;
+
+	
+
+		//not close enough
+		while (dist > radius)
+		{
+			numIter++;
+			if (numIter > maxIter)
+			{
+				return false; //todo: report a failure
+			}
+			btScalar dLambda = btScalar(0.);
+
+			btScalar projectedLinearVelocity = r.dot(n);
+			
+			dLambda = dist / (projectedLinearVelocity);
+
+			lambda = lambda - dLambda;
+
+			if (lambda > btScalar(1.))
+				return false;
+
+			if (lambda < btScalar(0.))
+				return false;
+
+			//todo: next check with relative epsilon
+			if (lambda <= lastLambda)
+			{
+				return false;
+				//n.setValue(0,0,0);
+				break;
+			}
+			lastLambda = lambda;
+
+			//interpolate to next lambda
+			result.DebugDraw( lambda );
+			input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+			input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+			
+			gjk.getClosestPoints(input,pointCollector,0);
+			if (pointCollector.m_hasResult)
+			{
+				if (pointCollector.m_distance < btScalar(0.))
+				{
+					result.m_fraction = lastLambda;
+					n = pointCollector.m_normalOnBInWorld;
+					result.m_normal=n;
+					result.m_hitPoint = pointCollector.m_pointInWorld;
+					return true;
+				}
+				c = pointCollector.m_pointInWorld;		
+				n = pointCollector.m_normalOnBInWorld;
+				dist = pointCollector.m_distance;
+			} else
+			{
+				//??
+				return false;
+			}
+
+		}
+
+		//is n normalized?
+		//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+		if (n.dot(r)>=-result.m_allowedPenetration)
+			return false;
+
+		result.m_fraction = lambda;
+		result.m_normal = n;
+		result.m_hitPoint = c;
+		return true;
+	}
+
+	return false;
+
+
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GJK_CONVEX_CAST_H
+#define BT_GJK_CONVEX_CAST_H
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btVector3.h"
+#include "btConvexCast.h"
+class btConvexShape;
+class btMinkowskiSumShape;
+#include "btSimplexSolverInterface.h"
+
+///GjkConvexCast performs a raycast on a convex object using support mapping.
+class btGjkConvexCast : public btConvexCast
+{
+	btSimplexSolverInterface*	m_simplexSolver;
+	const btConvexShape*	m_convexA;
+	const btConvexShape*	m_convexB;
+
+public:
+
+	btGjkConvexCast(const btConvexShape*	convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver);
+
+	/// cast a convex against another convex object
+	virtual bool	calcTimeOfImpact(
+					const btTransform& fromA,
+					const btTransform& toA,
+					const btTransform& fromB,
+					const btTransform& toB,
+					CastResult& result);
+
+};
+
+#endif //BT_GJK_CONVEX_CAST_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp	(revision 11817)
@@ -0,0 +1,989 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkEpa2.h"
+
+#if defined(DEBUG) || defined (_DEBUG)
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif //__SPU__
+#endif
+
+namespace gjkepa2_impl
+{
+
+	// Config
+
+	/* GJK	*/ 
+#define GJK_MAX_ITERATIONS	128
+#define GJK_ACCURARY		((btScalar)0.0001)
+#define GJK_MIN_DISTANCE	((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS	((btScalar)0.0001)
+#define GJK_SIMPLEX2_EPS	((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS	((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS	((btScalar)0.0)
+
+	/* EPA	*/ 
+#define EPA_MAX_VERTICES	64
+#define EPA_MAX_FACES		(EPA_MAX_VERTICES*2)
+#define EPA_MAX_ITERATIONS	255
+#define EPA_ACCURACY		((btScalar)0.0001)
+#define EPA_FALLBACK		(10*EPA_ACCURACY)
+#define EPA_PLANE_EPS		((btScalar)0.00001)
+#define EPA_INSIDE_EPS		((btScalar)0.01)
+
+
+	// Shorthands
+	typedef unsigned int	U;
+	typedef unsigned char	U1;
+
+	// MinkowskiDiff
+	struct	MinkowskiDiff
+	{
+		const btConvexShape*	m_shapes[2];
+		btMatrix3x3				m_toshape1;
+		btTransform				m_toshape0;
+#ifdef __SPU__
+		bool					m_enableMargin;
+#else
+		btVector3				(btConvexShape::*Ls)(const btVector3&) const;
+#endif//__SPU__
+		
+
+		MinkowskiDiff()
+		{
+
+		}
+#ifdef __SPU__
+			void					EnableMargin(bool enable)
+		{
+			m_enableMargin = enable;
+		}	
+		inline btVector3		Support0(const btVector3& d) const
+		{
+			if (m_enableMargin)
+			{
+				return m_shapes[0]->localGetSupportVertexNonVirtual(d);
+			} else
+			{
+				return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
+			}
+		}
+		inline btVector3		Support1(const btVector3& d) const
+		{
+			if (m_enableMargin)
+			{
+				return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d));
+			} else
+			{
+				return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d));
+			}
+		}
+#else
+		void					EnableMargin(bool enable)
+		{
+			if(enable)
+				Ls=&btConvexShape::localGetSupportVertexNonVirtual;
+			else
+				Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
+		}	
+		inline btVector3		Support0(const btVector3& d) const
+		{
+			return(((m_shapes[0])->*(Ls))(d));
+		}
+		inline btVector3		Support1(const btVector3& d) const
+		{
+			return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
+		}
+#endif //__SPU__
+
+		inline btVector3		Support(const btVector3& d) const
+		{
+			return(Support0(d)-Support1(-d));
+		}
+		btVector3				Support(const btVector3& d,U index) const
+		{
+			if(index)
+				return(Support1(d));
+			else
+				return(Support0(d));
+		}
+	};
+
+	typedef	MinkowskiDiff	tShape;
+
+
+	// GJK
+	struct	GJK
+	{
+		/* Types		*/ 
+		struct	sSV
+		{
+			btVector3	d,w;
+		};
+		struct	sSimplex
+		{
+			sSV*		c[4];
+			btScalar	p[4];
+			U			rank;
+		};
+		struct	eStatus	{ enum _ {
+			Valid,
+			Inside,
+			Failed		};};
+			/* Fields		*/ 
+			tShape			m_shape;
+			btVector3		m_ray;
+			btScalar		m_distance;
+			sSimplex		m_simplices[2];
+			sSV				m_store[4];
+			sSV*			m_free[4];
+			U				m_nfree;
+			U				m_current;
+			sSimplex*		m_simplex;
+			eStatus::_		m_status;
+			/* Methods		*/ 
+			GJK()
+			{
+				Initialize();
+			}
+			void				Initialize()
+			{
+				m_ray		=	btVector3(0,0,0);
+				m_nfree		=	0;
+				m_status	=	eStatus::Failed;
+				m_current	=	0;
+				m_distance	=	0;
+			}
+			eStatus::_			Evaluate(const tShape& shapearg,const btVector3& guess)
+			{
+				U			iterations=0;
+				btScalar	sqdist=0;
+				btScalar	alpha=0;
+				btVector3	lastw[4];
+				U			clastw=0;
+				/* Initialize solver		*/ 
+				m_free[0]			=	&m_store[0];
+				m_free[1]			=	&m_store[1];
+				m_free[2]			=	&m_store[2];
+				m_free[3]			=	&m_store[3];
+				m_nfree				=	4;
+				m_current			=	0;
+				m_status			=	eStatus::Valid;
+				m_shape				=	shapearg;
+				m_distance			=	0;
+				/* Initialize simplex		*/ 
+				m_simplices[0].rank	=	0;
+				m_ray				=	guess;
+				const btScalar	sqrl=	m_ray.length2();
+				appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
+				m_simplices[0].p[0]	=	1;
+				m_ray				=	m_simplices[0].c[0]->w;	
+				sqdist				=	sqrl;
+				lastw[0]			=
+					lastw[1]			=
+					lastw[2]			=
+					lastw[3]			=	m_ray;
+				/* Loop						*/ 
+				do	{
+					const U		next=1-m_current;
+					sSimplex&	cs=m_simplices[m_current];
+					sSimplex&	ns=m_simplices[next];
+					/* Check zero							*/ 
+					const btScalar	rl=m_ray.length();
+					if(rl<GJK_MIN_DISTANCE)
+					{/* Touching or inside				*/ 
+						m_status=eStatus::Inside;
+						break;
+					}
+					/* Append new vertice in -'v' direction	*/ 
+					appendvertice(cs,-m_ray);
+					const btVector3&	w=cs.c[cs.rank-1]->w;
+					bool				found=false;
+					for(U i=0;i<4;++i)
+					{
+						if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
+						{ found=true;break; }
+					}
+					if(found)
+					{/* Return old simplex				*/ 
+						removevertice(m_simplices[m_current]);
+						break;
+					}
+					else
+					{/* Update lastw					*/ 
+						lastw[clastw=(clastw+1)&3]=w;
+					}
+					/* Check for termination				*/ 
+					const btScalar	omega=btDot(m_ray,w)/rl;
+					alpha=btMax(omega,alpha);
+					if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
+					{/* Return old simplex				*/ 
+						removevertice(m_simplices[m_current]);
+						break;
+					}		
+					/* Reduce simplex						*/ 
+					btScalar	weights[4];
+					U			mask=0;
+					switch(cs.rank)
+					{
+					case	2:	sqdist=projectorigin(	cs.c[0]->w,
+									cs.c[1]->w,
+									weights,mask);break;
+					case	3:	sqdist=projectorigin(	cs.c[0]->w,
+									cs.c[1]->w,
+									cs.c[2]->w,
+									weights,mask);break;
+					case	4:	sqdist=projectorigin(	cs.c[0]->w,
+									cs.c[1]->w,
+									cs.c[2]->w,
+									cs.c[3]->w,
+									weights,mask);break;
+					}
+					if(sqdist>=0)
+					{/* Valid	*/ 
+						ns.rank		=	0;
+						m_ray		=	btVector3(0,0,0);
+						m_current	=	next;
+						for(U i=0,ni=cs.rank;i<ni;++i)
+						{
+							if(mask&(1<<i))
+							{
+								ns.c[ns.rank]		=	cs.c[i];
+								ns.p[ns.rank++]		=	weights[i];
+								m_ray				+=	cs.c[i]->w*weights[i];
+							}
+							else
+							{
+								m_free[m_nfree++]	=	cs.c[i];
+							}
+						}
+						if(mask==15) m_status=eStatus::Inside;
+					}
+					else
+					{/* Return old simplex				*/ 
+						removevertice(m_simplices[m_current]);
+						break;
+					}
+					m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
+				} while(m_status==eStatus::Valid);
+				m_simplex=&m_simplices[m_current];
+				switch(m_status)
+				{
+				case	eStatus::Valid:		m_distance=m_ray.length();break;
+				case	eStatus::Inside:	m_distance=0;break;
+				default:
+					{
+					}
+				}	
+				return(m_status);
+			}
+			bool					EncloseOrigin()
+			{
+				switch(m_simplex->rank)
+				{
+				case	1:
+					{
+						for(U i=0;i<3;++i)
+						{
+							btVector3		axis=btVector3(0,0,0);
+							axis[i]=1;
+							appendvertice(*m_simplex, axis);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+							appendvertice(*m_simplex,-axis);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+						}
+					}
+					break;
+				case	2:
+					{
+						const btVector3	d=m_simplex->c[1]->w-m_simplex->c[0]->w;
+						for(U i=0;i<3;++i)
+						{
+							btVector3		axis=btVector3(0,0,0);
+							axis[i]=1;
+							const btVector3	p=btCross(d,axis);
+							if(p.length2()>0)
+							{
+								appendvertice(*m_simplex, p);
+								if(EncloseOrigin())	return(true);
+								removevertice(*m_simplex);
+								appendvertice(*m_simplex,-p);
+								if(EncloseOrigin())	return(true);
+								removevertice(*m_simplex);
+							}
+						}
+					}
+					break;
+				case	3:
+					{
+						const btVector3	n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
+							m_simplex->c[2]->w-m_simplex->c[0]->w);
+						if(n.length2()>0)
+						{
+							appendvertice(*m_simplex,n);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+							appendvertice(*m_simplex,-n);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+						}
+					}
+					break;
+				case	4:
+					{
+						if(btFabs(det(	m_simplex->c[0]->w-m_simplex->c[3]->w,
+							m_simplex->c[1]->w-m_simplex->c[3]->w,
+							m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
+							return(true);
+					}
+					break;
+				}
+				return(false);
+			}
+			/* Internals	*/ 
+			void				getsupport(const btVector3& d,sSV& sv) const
+			{
+				sv.d	=	d/d.length();
+				sv.w	=	m_shape.Support(sv.d);
+			}
+			void				removevertice(sSimplex& simplex)
+			{
+				m_free[m_nfree++]=simplex.c[--simplex.rank];
+			}
+			void				appendvertice(sSimplex& simplex,const btVector3& v)
+			{
+				simplex.p[simplex.rank]=0;
+				simplex.c[simplex.rank]=m_free[--m_nfree];
+				getsupport(v,*simplex.c[simplex.rank++]);
+			}
+			static btScalar		det(const btVector3& a,const btVector3& b,const btVector3& c)
+			{
+				return(	a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
+					a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
+					a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
+			}
+			static btScalar		projectorigin(	const btVector3& a,
+				const btVector3& b,
+				btScalar* w,U& m)
+			{
+				const btVector3	d=b-a;
+				const btScalar	l=d.length2();
+				if(l>GJK_SIMPLEX2_EPS)
+				{
+					const btScalar	t(l>0?-btDot(a,d)/l:0);
+					if(t>=1)		{ w[0]=0;w[1]=1;m=2;return(b.length2()); }
+					else if(t<=0)	{ w[0]=1;w[1]=0;m=1;return(a.length2()); }
+					else			{ w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
+				}
+				return(-1);
+			}
+			static btScalar		projectorigin(	const btVector3& a,
+				const btVector3& b,
+				const btVector3& c,
+				btScalar* w,U& m)
+			{
+				static const U		imd3[]={1,2,0};
+				const btVector3*	vt[]={&a,&b,&c};
+				const btVector3		dl[]={a-b,b-c,c-a};
+				const btVector3		n=btCross(dl[0],dl[1]);
+				const btScalar		l=n.length2();
+				if(l>GJK_SIMPLEX3_EPS)
+				{
+					btScalar	mindist=-1;
+					btScalar	subw[2]={0.f,0.f};
+					U			subm(0);
+					for(U i=0;i<3;++i)
+					{
+						if(btDot(*vt[i],btCross(dl[i],n))>0)
+						{
+							const U			j=imd3[i];
+							const btScalar	subd(projectorigin(*vt[i],*vt[j],subw,subm));
+							if((mindist<0)||(subd<mindist))
+							{
+								mindist		=	subd;
+								m			=	static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
+								w[i]		=	subw[0];
+								w[j]		=	subw[1];
+								w[imd3[j]]	=	0;				
+							}
+						}
+					}
+					if(mindist<0)
+					{
+						const btScalar	d=btDot(a,n);	
+						const btScalar	s=btSqrt(l);
+						const btVector3	p=n*(d/l);
+						mindist	=	p.length2();
+						m		=	7;
+						w[0]	=	(btCross(dl[1],b-p)).length()/s;
+						w[1]	=	(btCross(dl[2],c-p)).length()/s;
+						w[2]	=	1-(w[0]+w[1]);
+					}
+					return(mindist);
+				}
+				return(-1);
+			}
+			static btScalar		projectorigin(	const btVector3& a,
+				const btVector3& b,
+				const btVector3& c,
+				const btVector3& d,
+				btScalar* w,U& m)
+			{
+				static const U		imd3[]={1,2,0};
+				const btVector3*	vt[]={&a,&b,&c,&d};
+				const btVector3		dl[]={a-d,b-d,c-d};
+				const btScalar		vl=det(dl[0],dl[1],dl[2]);
+				const bool			ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
+				if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
+				{
+					btScalar	mindist=-1;
+					btScalar	subw[3]={0.f,0.f,0.f};
+					U			subm(0);
+					for(U i=0;i<3;++i)
+					{
+						const U			j=imd3[i];
+						const btScalar	s=vl*btDot(d,btCross(dl[i],dl[j]));
+						if(s>0)
+						{
+							const btScalar	subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
+							if((mindist<0)||(subd<mindist))
+							{
+								mindist		=	subd;
+								m			=	static_cast<U>((subm&1?1<<i:0)+
+									(subm&2?1<<j:0)+
+									(subm&4?8:0));
+								w[i]		=	subw[0];
+								w[j]		=	subw[1];
+								w[imd3[j]]	=	0;
+								w[3]		=	subw[2];
+							}
+						}
+					}
+					if(mindist<0)
+					{
+						mindist	=	0;
+						m		=	15;
+						w[0]	=	det(c,b,d)/vl;
+						w[1]	=	det(a,c,d)/vl;
+						w[2]	=	det(b,a,d)/vl;
+						w[3]	=	1-(w[0]+w[1]+w[2]);
+					}
+					return(mindist);
+				}
+				return(-1);
+			}
+	};
+
+	// EPA
+	struct	EPA
+	{
+		/* Types		*/ 
+		typedef	GJK::sSV	sSV;
+		struct	sFace
+		{
+			btVector3	n;
+			btScalar	d;
+			btScalar	p;
+			sSV*		c[3];
+			sFace*		f[3];
+			sFace*		l[2];
+			U1			e[3];
+			U1			pass;
+		};
+		struct	sList
+		{
+			sFace*		root;
+			U			count;
+			sList() : root(0),count(0)	{}
+		};
+		struct	sHorizon
+		{
+			sFace*		cf;
+			sFace*		ff;
+			U			nf;
+			sHorizon() : cf(0),ff(0),nf(0)	{}
+		};
+		struct	eStatus { enum _ {
+			Valid,
+			Touching,
+			Degenerated,
+			NonConvex,
+			InvalidHull,		
+			OutOfFaces,
+			OutOfVertices,
+			AccuraryReached,
+			FallBack,
+			Failed		};};
+			/* Fields		*/ 
+			eStatus::_		m_status;
+			GJK::sSimplex	m_result;
+			btVector3		m_normal;
+			btScalar		m_depth;
+			sSV				m_sv_store[EPA_MAX_VERTICES];
+			sFace			m_fc_store[EPA_MAX_FACES];
+			U				m_nextsv;
+			sList			m_hull;
+			sList			m_stock;
+			/* Methods		*/ 
+			EPA()
+			{
+				Initialize();	
+			}
+
+
+			static inline void		bind(sFace* fa,U ea,sFace* fb,U eb)
+			{
+				fa->e[ea]=(U1)eb;fa->f[ea]=fb;
+				fb->e[eb]=(U1)ea;fb->f[eb]=fa;
+			}
+			static inline void		append(sList& list,sFace* face)
+			{
+				face->l[0]	=	0;
+				face->l[1]	=	list.root;
+				if(list.root) list.root->l[0]=face;
+				list.root	=	face;
+				++list.count;
+			}
+			static inline void		remove(sList& list,sFace* face)
+			{
+				if(face->l[1]) face->l[1]->l[0]=face->l[0];
+				if(face->l[0]) face->l[0]->l[1]=face->l[1];
+				if(face==list.root) list.root=face->l[1];
+				--list.count;
+			}
+
+
+			void				Initialize()
+			{
+				m_status	=	eStatus::Failed;
+				m_normal	=	btVector3(0,0,0);
+				m_depth		=	0;
+				m_nextsv	=	0;
+				for(U i=0;i<EPA_MAX_FACES;++i)
+				{
+					append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
+				}
+			}
+			eStatus::_			Evaluate(GJK& gjk,const btVector3& guess)
+			{
+				GJK::sSimplex&	simplex=*gjk.m_simplex;
+				if((simplex.rank>1)&&gjk.EncloseOrigin())
+				{
+
+					/* Clean up				*/ 
+					while(m_hull.root)
+					{
+						sFace*	f = m_hull.root;
+						remove(m_hull,f);
+						append(m_stock,f);
+					}
+					m_status	=	eStatus::Valid;
+					m_nextsv	=	0;
+					/* Orient simplex		*/ 
+					if(gjk.det(	simplex.c[0]->w-simplex.c[3]->w,
+						simplex.c[1]->w-simplex.c[3]->w,
+						simplex.c[2]->w-simplex.c[3]->w)<0)
+					{
+						btSwap(simplex.c[0],simplex.c[1]);
+						btSwap(simplex.p[0],simplex.p[1]);
+					}
+					/* Build initial hull	*/ 
+					sFace*	tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
+						newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
+						newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
+						newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
+					if(m_hull.count==4)
+					{
+						sFace*		best=findbest();
+						sFace		outer=*best;
+						U			pass=0;
+						U			iterations=0;
+						bind(tetra[0],0,tetra[1],0);
+						bind(tetra[0],1,tetra[2],0);
+						bind(tetra[0],2,tetra[3],0);
+						bind(tetra[1],1,tetra[3],2);
+						bind(tetra[1],2,tetra[2],1);
+						bind(tetra[2],2,tetra[3],1);
+						m_status=eStatus::Valid;
+						for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+						{
+							if(m_nextsv<EPA_MAX_VERTICES)
+							{	
+								sHorizon		horizon;
+								sSV*			w=&m_sv_store[m_nextsv++];
+								bool			valid=true;					
+								best->pass	=	(U1)(++pass);
+								gjk.getsupport(best->n,*w);
+								const btScalar	wdist=btDot(best->n,w->w)-best->d;
+								if(wdist>EPA_ACCURACY)
+								{
+									for(U j=0;(j<3)&&valid;++j)
+									{
+										valid&=expand(	pass,w,
+											best->f[j],best->e[j],
+											horizon);
+									}
+									if(valid&&(horizon.nf>=3))
+									{
+										bind(horizon.cf,1,horizon.ff,2);
+										remove(m_hull,best);
+										append(m_stock,best);
+										best=findbest();
+										if(best->p>=outer.p) outer=*best;
+									} else { m_status=eStatus::InvalidHull;break; }
+								} else { m_status=eStatus::AccuraryReached;break; }
+							} else { m_status=eStatus::OutOfVertices;break; }
+						}
+						const btVector3	projection=outer.n*outer.d;
+						m_normal	=	outer.n;
+						m_depth		=	outer.d;
+						m_result.rank	=	3;
+						m_result.c[0]	=	outer.c[0];
+						m_result.c[1]	=	outer.c[1];
+						m_result.c[2]	=	outer.c[2];
+						m_result.p[0]	=	btCross(	outer.c[1]->w-projection,
+							outer.c[2]->w-projection).length();
+						m_result.p[1]	=	btCross(	outer.c[2]->w-projection,
+							outer.c[0]->w-projection).length();
+						m_result.p[2]	=	btCross(	outer.c[0]->w-projection,
+							outer.c[1]->w-projection).length();
+						const btScalar	sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
+						m_result.p[0]	/=	sum;
+						m_result.p[1]	/=	sum;
+						m_result.p[2]	/=	sum;
+						return(m_status);
+					}
+				}
+				/* Fallback		*/ 
+				m_status	=	eStatus::FallBack;
+				m_normal	=	-guess;
+				const btScalar	nl=m_normal.length();
+				if(nl>0)
+					m_normal	=	m_normal/nl;
+				else
+					m_normal	=	btVector3(1,0,0);
+				m_depth	=	0;
+				m_result.rank=1;
+				m_result.c[0]=simplex.c[0];
+				m_result.p[0]=1;	
+				return(m_status);
+			}
+			sFace*				newface(sSV* a,sSV* b,sSV* c,bool forced)
+			{
+				if(m_stock.root)
+				{
+					sFace*	face=m_stock.root;
+					remove(m_stock,face);
+					append(m_hull,face);
+					face->pass	=	0;
+					face->c[0]	=	a;
+					face->c[1]	=	b;
+					face->c[2]	=	c;
+					face->n		=	btCross(b->w-a->w,c->w-a->w);
+					const btScalar	l=face->n.length();
+					const bool		v=l>EPA_ACCURACY;
+					face->p		=	btMin(btMin(
+						btDot(a->w,btCross(face->n,a->w-b->w)),
+						btDot(b->w,btCross(face->n,b->w-c->w))),
+						btDot(c->w,btCross(face->n,c->w-a->w)))	/
+						(v?l:1);
+					face->p		=	face->p>=-EPA_INSIDE_EPS?0:face->p;
+					if(v)
+					{
+						face->d		=	btDot(a->w,face->n)/l;
+						face->n		/=	l;
+						if(forced||(face->d>=-EPA_PLANE_EPS))
+						{
+							return(face);
+						} else m_status=eStatus::NonConvex;
+					} else m_status=eStatus::Degenerated;
+					remove(m_hull,face);
+					append(m_stock,face);
+					return(0);
+				}
+				m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
+				return(0);
+			}
+			sFace*				findbest()
+			{
+				sFace*		minf=m_hull.root;
+				btScalar	mind=minf->d*minf->d;
+				btScalar	maxp=minf->p;
+				for(sFace* f=minf->l[1];f;f=f->l[1])
+				{
+					const btScalar	sqd=f->d*f->d;
+					if((f->p>=maxp)&&(sqd<mind))
+					{
+						minf=f;
+						mind=sqd;
+						maxp=f->p;
+					}
+				}
+				return(minf);
+			}
+			bool				expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
+			{
+				static const U	i1m3[]={1,2,0};
+				static const U	i2m3[]={2,0,1};
+				if(f->pass!=pass)
+				{
+					const U	e1=i1m3[e];
+					if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
+					{
+						sFace*	nf=newface(f->c[e1],f->c[e],w,false);
+						if(nf)
+						{
+							bind(nf,0,f,e);
+							if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
+							horizon.cf=nf;
+							++horizon.nf;
+							return(true);
+						}
+					}
+					else
+					{
+						const U	e2=i2m3[e];
+						f->pass		=	(U1)pass;
+						if(	expand(pass,w,f->f[e1],f->e[e1],horizon)&&
+							expand(pass,w,f->f[e2],f->e[e2],horizon))
+						{
+							remove(m_hull,f);
+							append(m_stock,f);
+							return(true);
+						}
+					}
+				}
+				return(false);
+			}
+
+	};
+
+	//
+	static void	Initialize(	const btConvexShape* shape0,const btTransform& wtrs0,
+		const btConvexShape* shape1,const btTransform& wtrs1,
+		btGjkEpaSolver2::sResults& results,
+		tShape& shape,
+		bool withmargins)
+	{
+		/* Results		*/ 
+		results.witnesses[0]	=
+			results.witnesses[1]	=	btVector3(0,0,0);
+		results.status			=	btGjkEpaSolver2::sResults::Separated;
+		/* Shape		*/ 
+		shape.m_shapes[0]		=	shape0;
+		shape.m_shapes[1]		=	shape1;
+		shape.m_toshape1		=	wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
+		shape.m_toshape0		=	wtrs0.inverseTimes(wtrs1);
+		shape.EnableMargin(withmargins);
+	}
+
+}
+
+//
+// Api
+//
+
+using namespace	gjkepa2_impl;
+
+//
+int			btGjkEpaSolver2::StackSizeRequirement()
+{
+	return(sizeof(GJK)+sizeof(EPA));
+}
+
+//
+bool		btGjkEpaSolver2::Distance(	const btConvexShape*	shape0,
+									  const btTransform&		wtrs0,
+									  const btConvexShape*	shape1,
+									  const btTransform&		wtrs1,
+									  const btVector3&		guess,
+									  sResults&				results)
+{
+	tShape			shape;
+	Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+	GJK				gjk;
+	GJK::eStatus::_	gjk_status=gjk.Evaluate(shape,guess);
+	if(gjk_status==GJK::eStatus::Valid)
+	{
+		btVector3	w0=btVector3(0,0,0);
+		btVector3	w1=btVector3(0,0,0);
+		for(U i=0;i<gjk.m_simplex->rank;++i)
+		{
+			const btScalar	p=gjk.m_simplex->p[i];
+			w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+			w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+		}
+		results.witnesses[0]	=	wtrs0*w0;
+		results.witnesses[1]	=	wtrs0*w1;
+		results.normal			=	w0-w1;
+		results.distance		=	results.normal.length();
+		results.normal			/=	results.distance>GJK_MIN_DISTANCE?results.distance:1;
+		return(true);
+	}
+	else
+	{
+		results.status	=	gjk_status==GJK::eStatus::Inside?
+			sResults::Penetrating	:
+		sResults::GJK_Failed	;
+		return(false);
+	}
+}
+
+//
+bool	btGjkEpaSolver2::Penetration(	const btConvexShape*	shape0,
+									 const btTransform&		wtrs0,
+									 const btConvexShape*	shape1,
+									 const btTransform&		wtrs1,
+									 const btVector3&		guess,
+									 sResults&				results,
+									 bool					usemargins)
+{
+	tShape			shape;
+	Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
+	GJK				gjk;	
+	GJK::eStatus::_	gjk_status=gjk.Evaluate(shape,-guess);
+	switch(gjk_status)
+	{
+	case	GJK::eStatus::Inside:
+		{
+			EPA				epa;
+			EPA::eStatus::_	epa_status=epa.Evaluate(gjk,-guess);
+			if(epa_status!=EPA::eStatus::Failed)
+			{
+				btVector3	w0=btVector3(0,0,0);
+				for(U i=0;i<epa.m_result.rank;++i)
+				{
+					w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
+				}
+				results.status			=	sResults::Penetrating;
+				results.witnesses[0]	=	wtrs0*w0;
+				results.witnesses[1]	=	wtrs0*(w0-epa.m_normal*epa.m_depth);
+				results.normal			=	-epa.m_normal;
+				results.distance		=	-epa.m_depth;
+				return(true);
+			} else results.status=sResults::EPA_Failed;
+		}
+		break;
+	case	GJK::eStatus::Failed:
+		results.status=sResults::GJK_Failed;
+		break;
+		default:
+					{
+					}
+	}
+	return(false);
+}
+
+#ifndef __SPU__
+//
+btScalar	btGjkEpaSolver2::SignedDistance(const btVector3& position,
+											btScalar margin,
+											const btConvexShape* shape0,
+											const btTransform& wtrs0,
+											sResults& results)
+{
+	tShape			shape;
+	btSphereShape	shape1(margin);
+	btTransform		wtrs1(btQuaternion(0,0,0,1),position);
+	Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
+	GJK				gjk;	
+	GJK::eStatus::_	gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
+	if(gjk_status==GJK::eStatus::Valid)
+	{
+		btVector3	w0=btVector3(0,0,0);
+		btVector3	w1=btVector3(0,0,0);
+		for(U i=0;i<gjk.m_simplex->rank;++i)
+		{
+			const btScalar	p=gjk.m_simplex->p[i];
+			w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+			w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+		}
+		results.witnesses[0]	=	wtrs0*w0;
+		results.witnesses[1]	=	wtrs0*w1;
+		const btVector3	delta=	results.witnesses[1]-
+			results.witnesses[0];
+		const btScalar	margin=	shape0->getMarginNonVirtual()+
+			shape1.getMarginNonVirtual();
+		const btScalar	length=	delta.length();	
+		results.normal			=	delta/length;
+		results.witnesses[0]	+=	results.normal*margin;
+		return(length-margin);
+	}
+	else
+	{
+		if(gjk_status==GJK::eStatus::Inside)
+		{
+			if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
+			{
+				const btVector3	delta=	results.witnesses[0]-
+					results.witnesses[1];
+				const btScalar	length=	delta.length();
+				if (length >= SIMD_EPSILON)
+					results.normal	=	delta/length;			
+				return(-length);
+			}
+		}	
+	}
+	return(SIMD_INFINITY);
+}
+
+//
+bool	btGjkEpaSolver2::SignedDistance(const btConvexShape*	shape0,
+										const btTransform&		wtrs0,
+										const btConvexShape*	shape1,
+										const btTransform&		wtrs1,
+										const btVector3&		guess,
+										sResults&				results)
+{
+	if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
+		return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+	else
+		return(true);
+}
+#endif //__SPU__
+
+/* Symbols cleanup		*/ 
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURARY
+#undef GJK_MIN_DISTANCE
+#undef GJK_DUPLICATED_EPS
+#undef GJK_SIMPLEX2_EPS
+#undef GJK_SIMPLEX3_EPS
+#undef GJK_SIMPLEX4_EPS
+
+#undef EPA_MAX_VERTICES
+#undef EPA_MAX_FACES
+#undef EPA_MAX_ITERATIONS
+#undef EPA_ACCURACY
+#undef EPA_FALLBACK
+#undef EPA_PLANE_EPS
+#undef EPA_INSIDE_EPS
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#ifndef BT_GJK_EPA2_H
+#define BT_GJK_EPA2_H
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+///btGjkEpaSolver contributed under zlib by Nathanael Presson
+struct	btGjkEpaSolver2
+{
+struct	sResults
+	{
+	enum eStatus
+		{
+		Separated,		/* Shapes doesnt penetrate												*/ 
+		Penetrating,	/* Shapes are penetrating												*/ 
+		GJK_Failed,		/* GJK phase fail, no big issue, shapes are probably just 'touching'	*/ 
+		EPA_Failed		/* EPA phase fail, bigger problem, need to save parameters, and debug	*/ 
+		}		status;
+	btVector3	witnesses[2];
+	btVector3	normal;
+	btScalar	distance;
+	};
+
+static int		StackSizeRequirement();
+
+static bool		Distance(	const btConvexShape* shape0,const btTransform& wtrs0,
+							const btConvexShape* shape1,const btTransform& wtrs1,
+							const btVector3& guess,
+							sResults& results);
+
+static bool		Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
+							const btConvexShape* shape1,const btTransform& wtrs1,
+							const btVector3& guess,
+							sResults& results,
+							bool usemargins=true);
+#ifndef __SPU__
+static btScalar	SignedDistance(	const btVector3& position,
+								btScalar margin,
+								const btConvexShape* shape,
+								const btTransform& wtrs,
+								sResults& results);
+							
+static bool		SignedDistance(	const btConvexShape* shape0,const btTransform& wtrs0,
+								const btConvexShape* shape1,const btTransform& wtrs1,
+								const btVector3& guess,
+								sResults& results);
+#endif //__SPU__
+
+};
+
+#endif //BT_GJK_EPA2_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+EPA Copyright (c) Ricardo Padrela 2006
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "btGjkEpaPenetrationDepthSolver.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver,
+											  const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+											  const btTransform& transformA, const btTransform& transformB,
+											  btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+											  class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc )
+{
+
+	(void)debugDraw;
+	(void)v;
+	(void)simplexSolver;
+
+//	const btScalar				radialmargin(btScalar(0.));
+	
+	btVector3	guessVector(transformA.getOrigin()-transformB.getOrigin());
+	btGjkEpaSolver2::sResults	results;
+	
+
+	if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
+								pConvexB,transformB,
+								guessVector,results))
+	
+		{
+	//	debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
+		//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
+		wWitnessOnA = results.witnesses[0];
+		wWitnessOnB = results.witnesses[1];
+		v = results.normal;
+		return true;		
+		} else
+	{
+		if(btGjkEpaSolver2::Distance(pConvexA,transformA,pConvexB,transformB,guessVector,results))
+		{
+			wWitnessOnA = results.witnesses[0];
+			wWitnessOnB = results.witnesses[1];
+			v = results.normal;
+			return false;
+		}
+	}
+
+	return false;
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h	(revision 11817)
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+EPA Copyright (c) Ricardo Padrela 2006 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H
+#define BT_GJP_EPA_PENETRATION_DEPTH_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to
+///calculate the penetration depth between two convex shapes.
+class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+	public :
+
+		btGjkEpaPenetrationDepthSolver()
+		{
+		}
+
+		bool			calcPenDepth( btSimplexSolverInterface& simplexSolver,
+									  const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+									  const btTransform& transformA, const btTransform& transformB,
+									  btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+									  class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc );
+
+	private :
+
+};
+
+#endif	// BT_GJP_EPA_PENETRATION_DEPTH_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp	(revision 11817)
@@ -0,0 +1,457 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+
+
+
+#if defined(DEBUG) || defined (_DEBUG)
+//#define TEST_NON_VIRTUAL 1
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+//#define DEBUG_SPU_COLLISION_DETECTION 1
+#endif //__SPU__
+#endif
+
+//must be above the machine epsilon
+#define REL_ERROR2 btScalar(1.0e-6)
+
+//temp globals, to improve GJK/EPA/penetration calculations
+int gNumDeepPenetrationChecks = 0;
+int gNumGjkChecks = 0;
+
+
+btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver)
+:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_simplexSolver(simplexSolver),
+m_minkowskiA(objectA),
+m_minkowskiB(objectB),
+m_shapeTypeA(objectA->getShapeType()),
+m_shapeTypeB(objectB->getShapeType()),
+m_marginA(objectA->getMargin()),
+m_marginB(objectB->getMargin()),
+m_ignoreMargin(false),
+m_lastUsedMethod(-1),
+m_catchDegeneracies(1)
+{
+}
+btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver)
+:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_simplexSolver(simplexSolver),
+m_minkowskiA(objectA),
+m_minkowskiB(objectB),
+m_shapeTypeA(shapeTypeA),
+m_shapeTypeB(shapeTypeB),
+m_marginA(marginA),
+m_marginB(marginB),
+m_ignoreMargin(false),
+m_lastUsedMethod(-1),
+m_catchDegeneracies(1)
+{
+}
+
+void	btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+{
+	(void)swapResults;
+
+	getClosestPointsNonVirtual(input,output,debugDraw);
+}
+
+#ifdef __SPU__
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+#else
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+#endif
+{
+	m_cachedSeparatingDistance = 0.f;
+
+	btScalar distance=btScalar(0.);
+	btVector3	normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 pointOnA,pointOnB;
+	btTransform	localTransA = input.m_transformA;
+	btTransform localTransB = input.m_transformB;
+	btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
+	localTransA.getOrigin() -= positionOffset;
+	localTransB.getOrigin() -= positionOffset;
+
+	bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
+
+	btScalar marginA = m_marginA;
+	btScalar marginB = m_marginB;
+
+	gNumGjkChecks++;
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+	spu_printf("inside gjk\n");
+#endif
+	//for CCD we don't use margins
+	if (m_ignoreMargin)
+	{
+		marginA = btScalar(0.);
+		marginB = btScalar(0.);
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("ignoring margin\n");
+#endif
+	}
+
+	m_curIter = 0;
+	int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN?
+	m_cachedSeparatingAxis.setValue(0,1,0);
+
+	bool isValid = false;
+	bool checkSimplex = false;
+	bool checkPenetration = true;
+	m_degenerateSimplex = 0;
+
+	m_lastUsedMethod = -1;
+
+	{
+		btScalar squaredDistance = BT_LARGE_FLOAT;
+		btScalar delta = btScalar(0.);
+		
+		btScalar margin = marginA + marginB;
+		
+		
+
+		m_simplexSolver->reset();
+		
+		for ( ; ; )
+		//while (true)
+		{
+
+			btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis();
+			btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis();
+
+#if 1
+
+			btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+			btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+
+//			btVector3 pInA  = localGetSupportingVertexWithoutMargin(m_shapeTypeA, m_minkowskiA, seperatingAxisInA,input.m_convexVertexData[0]);//, &featureIndexA);
+//			btVector3 qInB  = localGetSupportingVertexWithoutMargin(m_shapeTypeB, m_minkowskiB, seperatingAxisInB,input.m_convexVertexData[1]);//, &featureIndexB);
+
+#else
+#ifdef __SPU__
+			btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+			btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+#else
+			btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
+			btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
+#ifdef TEST_NON_VIRTUAL
+			btVector3 pInAv = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
+			btVector3 qInBv = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
+			btAssert((pInAv-pInA).length() < 0.0001);
+			btAssert((qInBv-qInB).length() < 0.0001);
+#endif //
+#endif //__SPU__
+#endif
+
+
+			btVector3  pWorld = localTransA(pInA);	
+			btVector3  qWorld = localTransB(qInB);
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("got local supporting vertices\n");
+#endif
+
+			if (check2d)
+			{
+				pWorld[2] = 0.f;
+				qWorld[2] = 0.f;
+			}
+
+			btVector3 w	= pWorld - qWorld;
+			delta = m_cachedSeparatingAxis.dot(w);
+
+			// potential exit, they don't overlap
+			if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) 
+			{
+				m_degenerateSimplex = 10;
+				checkSimplex=true;
+				//checkPenetration = false;
+				break;
+			}
+
+			//exit 0: the new point is already in the simplex, or we didn't come any closer
+			if (m_simplexSolver->inSimplex(w))
+			{
+				m_degenerateSimplex = 1;
+				checkSimplex = true;
+				break;
+			}
+			// are we getting any closer ?
+			btScalar f0 = squaredDistance - delta;
+			btScalar f1 = squaredDistance * REL_ERROR2;
+
+			if (f0 <= f1)
+			{
+				if (f0 <= btScalar(0.))
+				{
+					m_degenerateSimplex = 2;
+				} else
+				{
+					m_degenerateSimplex = 11;
+				}
+				checkSimplex = true;
+				break;
+			}
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("addVertex 1\n");
+#endif
+			//add current vertex to simplex
+			m_simplexSolver->addVertex(w, pWorld, qWorld);
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("addVertex 2\n");
+#endif
+			btVector3 newCachedSeparatingAxis;
+
+			//calculate the closest point to the origin (update vector v)
+			if (!m_simplexSolver->closest(newCachedSeparatingAxis))
+			{
+				m_degenerateSimplex = 3;
+				checkSimplex = true;
+				break;
+			}
+
+			if(newCachedSeparatingAxis.length2()<REL_ERROR2)
+            {
+				m_cachedSeparatingAxis = newCachedSeparatingAxis;
+                m_degenerateSimplex = 6;
+                checkSimplex = true;
+                break;
+            }
+
+			btScalar previousSquaredDistance = squaredDistance;
+			squaredDistance = newCachedSeparatingAxis.length2();
+#if 0
+///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
+			if (squaredDistance>previousSquaredDistance)
+			{
+				m_degenerateSimplex = 7;
+				squaredDistance = previousSquaredDistance;
+                checkSimplex = false;
+                break;
+			}
+#endif //
+			
+
+			//redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+			//are we getting any closer ?
+			if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) 
+			{ 
+//				m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+				checkSimplex = true;
+				m_degenerateSimplex = 12;
+				
+				break;
+			}
+
+			m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+			  //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject   
+              if (m_curIter++ > gGjkMaxIter)   
+              {   
+                      #if defined(DEBUG) || defined (_DEBUG) || defined (DEBUG_SPU_COLLISION_DETECTION)
+
+                              printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);   
+                              printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",   
+                              m_cachedSeparatingAxis.getX(),   
+                              m_cachedSeparatingAxis.getY(),   
+                              m_cachedSeparatingAxis.getZ(),   
+                              squaredDistance,   
+                              m_minkowskiA->getShapeType(),   
+                              m_minkowskiB->getShapeType());   
+
+                      #endif   
+                      break;   
+
+              } 
+
+
+			bool check = (!m_simplexSolver->fullSimplex());
+			//bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+			if (!check)
+			{
+				//do we need this backup_closest here ?
+//				m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+				m_degenerateSimplex = 13;
+				break;
+			}
+		}
+
+		if (checkSimplex)
+		{
+			m_simplexSolver->compute_points(pointOnA, pointOnB);
+			normalInB = m_cachedSeparatingAxis;
+			btScalar lenSqr =m_cachedSeparatingAxis.length2();
+			
+			//valid normal
+			if (lenSqr < 0.0001)
+			{
+				m_degenerateSimplex = 5;
+			} 
+			if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
+			{
+				btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+				normalInB *= rlen; //normalize
+				btScalar s = btSqrt(squaredDistance);
+			
+				btAssert(s > btScalar(0.0));
+				pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+				pointOnB += m_cachedSeparatingAxis * (marginB / s);
+				distance = ((btScalar(1.)/rlen) - margin);
+				isValid = true;
+				
+				m_lastUsedMethod = 1;
+			} else
+			{
+				m_lastUsedMethod = 2;
+			}
+		}
+
+		bool catchDegeneratePenetrationCase = 
+			(m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01));
+
+		//if (checkPenetration && !isValid)
+		if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
+		{
+			//penetration case
+
+			//if there is no way to handle penetrations, bail out
+			if (m_penetrationDepthSolver)
+			{
+				// Penetration depth case.
+				btVector3 tmpPointOnA,tmpPointOnB;
+				
+				gNumDeepPenetrationChecks++;
+				m_cachedSeparatingAxis.setZero();
+
+				bool isValid2 = m_penetrationDepthSolver->calcPenDepth( 
+					*m_simplexSolver, 
+					m_minkowskiA,m_minkowskiB,
+					localTransA,localTransB,
+					m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
+					debugDraw,input.m_stackAlloc
+					);
+
+
+				if (isValid2)
+				{
+					btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
+					btScalar lenSqr = tmpNormalInB.length2();
+					if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+					{
+						tmpNormalInB = m_cachedSeparatingAxis;
+						lenSqr = m_cachedSeparatingAxis.length2();
+					}
+
+					if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+					{
+						tmpNormalInB /= btSqrt(lenSqr);
+						btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
+						//only replace valid penetrations when the result is deeper (check)
+						if (!isValid || (distance2 < distance))
+						{
+							distance = distance2;
+							pointOnA = tmpPointOnA;
+							pointOnB = tmpPointOnB;
+							normalInB = tmpNormalInB;
+							isValid = true;
+							m_lastUsedMethod = 3;
+						} else
+						{
+							m_lastUsedMethod = 8;
+						}
+					} else
+					{
+						m_lastUsedMethod = 9;
+					}
+				} else
+
+				{
+					///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+					///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+					///reports a valid positive distance. Use the results of the second GJK instead of failing.
+					///thanks to Jacob.Langford for the reproduction case
+					///http://code.google.com/p/bullet/issues/detail?id=250
+
+				
+					if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+					{
+						btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
+						//only replace valid distances when the distance is less
+						if (!isValid || (distance2 < distance))
+						{
+							distance = distance2;
+							pointOnA = tmpPointOnA;
+							pointOnB = tmpPointOnB;
+							pointOnA -= m_cachedSeparatingAxis * marginA ;
+							pointOnB += m_cachedSeparatingAxis * marginB ;
+							normalInB = m_cachedSeparatingAxis;
+							normalInB.normalize();
+							isValid = true;
+							m_lastUsedMethod = 6;
+						} else
+						{
+							m_lastUsedMethod = 5;
+						}
+					}
+				}
+				
+			}
+
+		}
+	}
+
+	
+
+	if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared)))
+	{
+#if 0
+///some debugging
+//		if (check2d)
+		{
+			printf("n = %2.3f,%2.3f,%2.3f. ",normalInB[0],normalInB[1],normalInB[2]);
+			printf("distance = %2.3f exit=%d deg=%d\n",distance,m_lastUsedMethod,m_degenerateSimplex);
+		}
+#endif 
+
+		m_cachedSeparatingAxis = normalInB;
+		m_cachedSeparatingDistance = distance;
+
+		output.addContactPoint(
+			normalInB,
+			pointOnB+positionOffset,
+			distance);
+
+	}
+
+
+}
+
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+
+#ifndef BT_GJK_PAIR_DETECTOR_H
+#define BT_GJK_PAIR_DETECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+class btConvexShape;
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+
+/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
+class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
+{
+	
+
+	btVector3	m_cachedSeparatingAxis;
+	btConvexPenetrationDepthSolver*	m_penetrationDepthSolver;
+	btSimplexSolverInterface* m_simplexSolver;
+	const btConvexShape* m_minkowskiA;
+	const btConvexShape* m_minkowskiB;
+	int	m_shapeTypeA;
+	int m_shapeTypeB;
+	btScalar	m_marginA;
+	btScalar	m_marginB;
+
+	bool		m_ignoreMargin;
+	btScalar	m_cachedSeparatingDistance;
+	
+
+public:
+
+	//some debugging to fix degeneracy problems
+	int			m_lastUsedMethod;
+	int			m_curIter;
+	int			m_degenerateSimplex;
+	int			m_catchDegeneracies;
+
+
+	btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver);
+	btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver);
+	virtual ~btGjkPairDetector() {};
+
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+	void	getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
+	
+
+	void setMinkowskiA(btConvexShape* minkA)
+	{
+		m_minkowskiA = minkA;
+	}
+
+	void setMinkowskiB(btConvexShape* minkB)
+	{
+		m_minkowskiB = minkB;
+	}
+	void setCachedSeperatingAxis(const btVector3& seperatingAxis)
+	{
+		m_cachedSeparatingAxis = seperatingAxis;
+	}
+
+	const btVector3& getCachedSeparatingAxis() const
+	{
+		return m_cachedSeparatingAxis;
+	}
+	btScalar	getCachedSeparatingDistance() const
+	{
+		return m_cachedSeparatingDistance;
+	}
+
+	void	setPenetrationDepthSolver(btConvexPenetrationDepthSolver*	penetrationDepthSolver)
+	{
+		m_penetrationDepthSolver = penetrationDepthSolver;
+	}
+
+	///don't use setIgnoreMargin, it's for Bullet's internal use
+	void	setIgnoreMargin(bool ignoreMargin)
+	{
+		m_ignoreMargin = ignoreMargin;
+	}
+
+
+};
+
+#endif //BT_GJK_PAIR_DETECTOR_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MANIFOLD_CONTACT_POINT_H
+#define BT_MANIFOLD_CONTACT_POINT_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransformUtil.h"
+
+#ifdef PFX_USE_FREE_VECTORMATH
+	#include "physics_effects/base_level/solver/pfx_constraint_row.h"
+typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow;
+#else
+	// Don't change following order of parameters
+	ATTRIBUTE_ALIGNED16(struct) btConstraintRow {
+		btScalar m_normal[3];
+		btScalar m_rhs;
+		btScalar m_jacDiagInv;
+		btScalar m_lowerLimit;
+		btScalar m_upperLimit;
+		btScalar m_accumImpulse;
+	};
+	typedef btConstraintRow PfxConstraintRow;
+#endif //PFX_USE_FREE_VECTORMATH
+
+
+
+/// ManifoldContactPoint collects and maintains persistent contactpoints.
+/// used to improve stability and performance of rigidbody dynamics response.
+class btManifoldPoint
+	{
+		public:
+			btManifoldPoint()
+				:m_userPersistentData(0),
+				m_appliedImpulse(0.f),
+				m_lateralFrictionInitialized(false),
+				m_appliedImpulseLateral1(0.f),
+				m_appliedImpulseLateral2(0.f),
+				m_contactMotion1(0.f),
+				m_contactMotion2(0.f),
+				m_contactCFM1(0.f),
+				m_contactCFM2(0.f),
+				m_lifeTime(0)
+			{
+			}
+
+			btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB, 
+					const btVector3 &normal, 
+					btScalar distance ) :
+					m_localPointA( pointA ), 
+					m_localPointB( pointB ), 
+					m_normalWorldOnB( normal ), 
+					m_distance1( distance ),
+					m_combinedFriction(btScalar(0.)),
+					m_combinedRestitution(btScalar(0.)),
+					m_userPersistentData(0),
+					m_appliedImpulse(0.f),
+					m_lateralFrictionInitialized(false),
+					m_appliedImpulseLateral1(0.f),
+					m_appliedImpulseLateral2(0.f),
+					m_contactMotion1(0.f),
+					m_contactMotion2(0.f),
+					m_contactCFM1(0.f),
+					m_contactCFM2(0.f),
+					m_lifeTime(0)
+			{
+				mConstraintRow[0].m_accumImpulse = 0.f;
+				mConstraintRow[1].m_accumImpulse = 0.f;
+				mConstraintRow[2].m_accumImpulse = 0.f;
+			}
+
+			
+
+			btVector3 m_localPointA;			
+			btVector3 m_localPointB;			
+			btVector3	m_positionWorldOnB;
+			///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
+			btVector3	m_positionWorldOnA;
+			btVector3 m_normalWorldOnB;
+		
+			btScalar	m_distance1;
+			btScalar	m_combinedFriction;
+			btScalar	m_combinedRestitution;
+
+         //BP mod, store contact triangles.
+         int	   m_partId0;
+         int      m_partId1;
+         int      m_index0;
+         int      m_index1;
+				
+			mutable void*	m_userPersistentData;
+			btScalar		m_appliedImpulse;
+
+			bool			m_lateralFrictionInitialized;
+			btScalar		m_appliedImpulseLateral1;
+			btScalar		m_appliedImpulseLateral2;
+			btScalar		m_contactMotion1;
+			btScalar		m_contactMotion2;
+			btScalar		m_contactCFM1;
+			btScalar		m_contactCFM2;
+
+			int				m_lifeTime;//lifetime of the contactpoint in frames
+			
+			btVector3		m_lateralFrictionDir1;
+			btVector3		m_lateralFrictionDir2;
+
+
+
+			btConstraintRow mConstraintRow[3];
+
+
+			btScalar getDistance() const
+			{
+				return m_distance1;
+			}
+			int	getLifeTime() const
+			{
+				return m_lifeTime;
+			}
+
+			const btVector3& getPositionWorldOnA() const {
+				return m_positionWorldOnA;
+//				return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
+			}
+
+			const btVector3& getPositionWorldOnB() const
+			{
+				return m_positionWorldOnB;
+			}
+
+			void	setDistance(btScalar dist)
+			{
+				m_distance1 = dist;
+			}
+			
+			///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
+			btScalar	getAppliedImpulse() const
+			{
+				return m_appliedImpulse;
+			}
+
+			
+
+	};
+
+#endif //BT_MANIFOLD_CONTACT_POINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp	(revision 11817)
@@ -0,0 +1,362 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+
+bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
+												   const btConvexShape* convexA,const btConvexShape* convexB,
+												   const btTransform& transA,const btTransform& transB,
+												   btVector3& v, btVector3& pa, btVector3& pb,
+												   class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
+												   )
+{
+
+	(void)stackAlloc;
+	(void)v;
+	
+	bool check2d= convexA->isConvex2d() && convexB->isConvex2d();
+
+	struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
+	{
+
+		btIntermediateResult():m_hasResult(false)
+		{
+		}
+		
+		btVector3 m_normalOnBInWorld;
+		btVector3 m_pointInWorld;
+		btScalar m_depth;
+		bool	m_hasResult;
+
+		virtual void setShapeIdentifiersA(int partId0,int index0)
+		{
+			(void)partId0;
+			(void)index0;
+		}
+		virtual void setShapeIdentifiersB(int partId1,int index1)
+		{
+			(void)partId1;
+			(void)index1;
+		}
+		void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+		{
+			m_normalOnBInWorld = normalOnBInWorld;
+			m_pointInWorld = pointInWorld;
+			m_depth = depth;
+			m_hasResult = true;
+		}
+	};
+
+	//just take fixed number of orientation, and sample the penetration depth in that direction
+	btScalar minProj = btScalar(BT_LARGE_FLOAT);
+	btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
+	btVector3 minA,minB;
+	btVector3 seperatingAxisInA,seperatingAxisInB;
+	btVector3 pInA,qInB,pWorld,qWorld,w;
+
+#ifndef __SPU__
+#define USE_BATCHED_SUPPORT 1
+#endif
+#ifdef USE_BATCHED_SUPPORT
+
+	btVector3	supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	btVector3	supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	btVector3	seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	btVector3	seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	int i;
+
+	int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+	for (i=0;i<numSampleDirections;i++)
+	{
+		btVector3 norm = getPenetrationDirections()[i];
+		seperatingAxisInABatch[i] =  (-norm) * transA.getBasis() ;
+		seperatingAxisInBBatch[i] =  norm   * transB.getBasis() ;
+	}
+
+	{
+		int numPDA = convexA->getNumPreferredPenetrationDirections();
+		if (numPDA)
+		{
+			for (int i=0;i<numPDA;i++)
+			{
+				btVector3 norm;
+				convexA->getPreferredPenetrationDirection(i,norm);
+				norm  = transA.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+				seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+				numSampleDirections++;
+			}
+		}
+	}
+
+	{
+		int numPDB = convexB->getNumPreferredPenetrationDirections();
+		if (numPDB)
+		{
+			for (int i=0;i<numPDB;i++)
+			{
+				btVector3 norm;
+				convexB->getPreferredPenetrationDirection(i,norm);
+				norm  = transB.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+				seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+				numSampleDirections++;
+			}
+		}
+	}
+
+
+
+
+	convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections);
+	convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections);
+
+	for (i=0;i<numSampleDirections;i++)
+	{
+		btVector3 norm = getPenetrationDirections()[i];
+		if (check2d)
+		{
+			norm[2] = 0.f;
+		}
+		if (norm.length2()>0.01)
+		{
+
+			seperatingAxisInA = seperatingAxisInABatch[i];
+			seperatingAxisInB = seperatingAxisInBBatch[i];
+
+			pInA = supportVerticesABatch[i];
+			qInB = supportVerticesBBatch[i];
+
+			pWorld = transA(pInA);	
+			qWorld = transB(qInB);
+			if (check2d)
+			{
+				pWorld[2] = 0.f;
+				qWorld[2] = 0.f;
+			}
+
+			w	= qWorld - pWorld;
+			btScalar delta = norm.dot(w);
+			//find smallest delta
+			if (delta < minProj)
+			{
+				minProj = delta;
+				minNorm = norm;
+				minA = pWorld;
+				minB = qWorld;
+			}
+		}
+	}	
+#else
+
+	int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+#ifndef __SPU__
+	{
+		int numPDA = convexA->getNumPreferredPenetrationDirections();
+		if (numPDA)
+		{
+			for (int i=0;i<numPDA;i++)
+			{
+				btVector3 norm;
+				convexA->getPreferredPenetrationDirection(i,norm);
+				norm  = transA.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				numSampleDirections++;
+			}
+		}
+	}
+
+	{
+		int numPDB = convexB->getNumPreferredPenetrationDirections();
+		if (numPDB)
+		{
+			for (int i=0;i<numPDB;i++)
+			{
+				btVector3 norm;
+				convexB->getPreferredPenetrationDirection(i,norm);
+				norm  = transB.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				numSampleDirections++;
+			}
+		}
+	}
+#endif // __SPU__
+
+	for (int i=0;i<numSampleDirections;i++)
+	{
+		const btVector3& norm = getPenetrationDirections()[i];
+		seperatingAxisInA = (-norm)* transA.getBasis();
+		seperatingAxisInB = norm* transB.getBasis();
+		pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+		qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+		pWorld = transA(pInA);	
+		qWorld = transB(qInB);
+		w	= qWorld - pWorld;
+		btScalar delta = norm.dot(w);
+		//find smallest delta
+		if (delta < minProj)
+		{
+			minProj = delta;
+			minNorm = norm;
+			minA = pWorld;
+			minB = qWorld;
+		}
+	}
+#endif //USE_BATCHED_SUPPORT
+
+	//add the margins
+
+	minA += minNorm*convexA->getMarginNonVirtual();
+	minB -= minNorm*convexB->getMarginNonVirtual();
+	//no penetration
+	if (minProj < btScalar(0.))
+		return false;
+
+	btScalar extraSeparation = 0.5f;///scale dependent
+	minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
+
+
+
+
+
+//#define DEBUG_DRAW 1
+#ifdef DEBUG_DRAW
+	if (debugDraw)
+	{
+		btVector3 color(0,1,0);
+		debugDraw->drawLine(minA,minB,color);
+		color = btVector3 (1,1,1);
+		btVector3 vec = minB-minA;
+		btScalar prj2 = minNorm.dot(vec);
+		debugDraw->drawLine(minA,minA+(minNorm*minProj),color);
+
+	}
+#endif //DEBUG_DRAW
+
+	
+
+	btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
+
+	btScalar offsetDist = minProj;
+	btVector3 offset = minNorm * offsetDist;
+	
+
+
+	btGjkPairDetector::ClosestPointInput input;
+		
+	btVector3 newOrg = transA.getOrigin() + offset;
+
+	btTransform displacedTrans = transA;
+	displacedTrans.setOrigin(newOrg);
+
+	input.m_transformA = displacedTrans;
+	input.m_transformB = transB;
+	input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj;
+	
+	btIntermediateResult res;
+	gjkdet.setCachedSeperatingAxis(-minNorm);
+	gjkdet.getClosestPoints(input,res,debugDraw);
+
+	btScalar correctedMinNorm = minProj - res.m_depth;
+
+
+	//the penetration depth is over-estimated, relax it
+	btScalar penetration_relaxation= btScalar(1.);
+	minNorm*=penetration_relaxation;
+	
+
+	if (res.m_hasResult)
+	{
+
+		pa = res.m_pointInWorld - minNorm * correctedMinNorm;
+		pb = res.m_pointInWorld;
+		v = minNorm;
+		
+#ifdef DEBUG_DRAW
+		if (debugDraw)
+		{
+			btVector3 color(1,0,0);
+			debugDraw->drawLine(pa,pb,color);
+		}
+#endif//DEBUG_DRAW
+
+
+	}
+	return res.m_hasResult;
+}
+
+btVector3*	btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
+{
+	static btVector3	sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = 
+	{
+	btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
+	btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
+	btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
+	btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
+	btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
+	btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
+	btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
+	btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
+	btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
+	btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
+	btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
+	btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
+	btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
+	btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
+	btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
+	btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
+	btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
+	btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
+	btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
+	btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
+	btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
+	btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
+	btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
+	btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
+	btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+	btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
+	btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+	btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
+	btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
+	btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+	btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
+	btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+	btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
+	btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
+	btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
+	btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
+	btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
+	btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
+	btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
+	btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
+	btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
+	btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
+	};
+
+	return sPenetrationDirections;
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
+///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
+class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+protected:
+
+	static btVector3*	getPenetrationDirections();
+
+public:
+
+	virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+	const btConvexShape* convexA,const btConvexShape* convexB,
+				const btTransform& transA,const btTransform& transB,
+			btVector3& v, btVector3& pa, btVector3& pb,
+			class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
+			);
+};
+
+#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp	(revision 11817)
@@ -0,0 +1,260 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btPersistentManifold.h"
+#include "LinearMath/btTransform.h"
+
+
+btScalar					gContactBreakingThreshold = btScalar(0.02);
+ContactDestroyedCallback	gContactDestroyedCallback = 0;
+ContactProcessedCallback	gContactProcessedCallback = 0;
+
+
+
+btPersistentManifold::btPersistentManifold()
+:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+m_body0(0),
+m_body1(0),
+m_cachedPoints (0),
+m_index1a(0)
+{
+}
+
+
+
+
+#ifdef DEBUG_PERSISTENCY
+#include <stdio.h>
+void	btPersistentManifold::DebugPersistency()
+{
+	int i;
+	printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
+	for (i=0;i<m_cachedPoints;i++)
+	{
+		printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
+	}
+}
+#endif //DEBUG_PERSISTENCY
+
+void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
+{
+
+	void* oldPtr = pt.m_userPersistentData;
+	if (oldPtr)
+	{
+#ifdef DEBUG_PERSISTENCY
+		int i;
+		int occurance = 0;
+		for (i=0;i<m_cachedPoints;i++)
+		{
+			if (m_pointCache[i].m_userPersistentData == oldPtr)
+			{
+				occurance++;
+				if (occurance>1)
+					printf("error in clearUserCache\n");
+			}
+		}
+		btAssert(occurance<=0);
+#endif //DEBUG_PERSISTENCY
+
+		if (pt.m_userPersistentData && gContactDestroyedCallback)
+		{
+			(*gContactDestroyedCallback)(pt.m_userPersistentData);
+			pt.m_userPersistentData = 0;
+		}
+		
+#ifdef DEBUG_PERSISTENCY
+		DebugPersistency();
+#endif
+	}
+
+	
+}
+
+
+int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) 
+{
+
+		//calculate 4 possible cases areas, and take biggest area
+		//also need to keep 'deepest'
+		
+		int maxPenetrationIndex = -1;
+#define KEEP_DEEPEST_POINT 1
+#ifdef KEEP_DEEPEST_POINT
+		btScalar maxPenetration = pt.getDistance();
+		for (int i=0;i<4;i++)
+		{
+			if (m_pointCache[i].getDistance() < maxPenetration)
+			{
+				maxPenetrationIndex = i;
+				maxPenetration = m_pointCache[i].getDistance();
+			}
+		}
+#endif //KEEP_DEEPEST_POINT
+		
+		btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
+		if (maxPenetrationIndex != 0)
+		{
+			btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
+			btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+			btVector3 cross = a0.cross(b0);
+			res0 = cross.length2();
+		}
+		if (maxPenetrationIndex != 1)
+		{
+			btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+			btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+			btVector3 cross = a1.cross(b1);
+			res1 = cross.length2();
+		}
+
+		if (maxPenetrationIndex != 2)
+		{
+			btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+			btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+			btVector3 cross = a2.cross(b2);
+			res2 = cross.length2();
+		}
+
+		if (maxPenetrationIndex != 3)
+		{
+			btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+			btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+			btVector3 cross = a3.cross(b3);
+			res3 = cross.length2();
+		}
+
+		btVector4 maxvec(res0,res1,res2,res3);
+		int biggestarea = maxvec.closestAxis4();
+		return biggestarea;
+}
+
+
+int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
+{
+	btScalar shortestDist =  getContactBreakingThreshold() * getContactBreakingThreshold();
+	int size = getNumContacts();
+	int nearestPoint = -1;
+	for( int i = 0; i < size; i++ )
+	{
+		const btManifoldPoint &mp = m_pointCache[i];
+
+		btVector3 diffA =  mp.m_localPointA- newPoint.m_localPointA;
+		const btScalar distToManiPoint = diffA.dot(diffA);
+		if( distToManiPoint < shortestDist )
+		{
+			shortestDist = distToManiPoint;
+			nearestPoint = i;
+		}
+	}
+	return nearestPoint;
+}
+
+int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint)
+{
+	btAssert(validContactDistance(newPoint));
+
+	int insertIndex = getNumContacts();
+	if (insertIndex == MANIFOLD_CACHE_SIZE)
+	{
+#if MANIFOLD_CACHE_SIZE >= 4
+		//sort cache so best points come first, based on area
+		insertIndex = sortCachedPoints(newPoint);
+#else
+		insertIndex = 0;
+#endif
+		clearUserCache(m_pointCache[insertIndex]);
+		
+	} else
+	{
+		m_cachedPoints++;
+
+		
+	}
+	if (insertIndex<0)
+		insertIndex=0;
+
+	btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
+	m_pointCache[insertIndex] = newPoint;
+	return insertIndex;
+}
+
+btScalar	btPersistentManifold::getContactBreakingThreshold() const
+{
+	return m_contactBreakingThreshold;
+}
+
+
+
+void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
+{
+	int i;
+#ifdef DEBUG_PERSISTENCY
+	printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
+		trA.getOrigin().getX(),
+		trA.getOrigin().getY(),
+		trA.getOrigin().getZ(),
+		trB.getOrigin().getX(),
+		trB.getOrigin().getY(),
+		trB.getOrigin().getZ());
+#endif //DEBUG_PERSISTENCY
+	/// first refresh worldspace positions and distance
+	for (i=getNumContacts()-1;i>=0;i--)
+	{
+		btManifoldPoint &manifoldPoint = m_pointCache[i];
+		manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
+		manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
+		manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA -  manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
+		manifoldPoint.m_lifeTime++;
+	}
+
+	/// then 
+	btScalar distance2d;
+	btVector3 projectedDifference,projectedPoint;
+	for (i=getNumContacts()-1;i>=0;i--)
+	{
+		
+		btManifoldPoint &manifoldPoint = m_pointCache[i];
+		//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+		if (!validContactDistance(manifoldPoint))
+		{
+			removeContactPoint(i);
+		} else
+		{
+			//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+			projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
+			projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
+			distance2d = projectedDifference.dot(projectedDifference);
+			if (distance2d  > getContactBreakingThreshold()*getContactBreakingThreshold() )
+			{
+				removeContactPoint(i);
+			} else
+			{
+				//contact point processed callback
+				if (gContactProcessedCallback)
+					(*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
+			}
+		}
+	}
+#ifdef DEBUG_PERSISTENCY
+	DebugPersistency();
+#endif //
+}
+
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h	(revision 11817)
@@ -0,0 +1,232 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_PERSISTENT_MANIFOLD_H
+#define BT_PERSISTENT_MANIFOLD_H
+
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btManifoldPoint.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+struct btCollisionResult;
+
+///maximum contact breaking and merging threshold
+extern btScalar gContactBreakingThreshold;
+
+typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
+typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
+extern ContactDestroyedCallback	gContactDestroyedCallback;
+extern ContactProcessedCallback gContactProcessedCallback;
+
+//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
+enum btContactManifoldTypes
+{
+	MIN_CONTACT_MANIFOLD_TYPE = 1024,
+	BT_PERSISTENT_MANIFOLD_TYPE
+};
+
+#define MANIFOLD_CACHE_SIZE 4
+
+///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
+///Those contact points are created by the collision narrow phase.
+///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
+///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
+///reduces the cache to 4 points, when more then 4 points are added, using following rules:
+///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
+///note that some pairs of objects might have more then one contact manifold.
+
+
+ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
+//ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
+{
+
+	btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
+
+	/// this two body pointers can point to the physics rigidbody class.
+	/// void* will allow any rigidbody class
+	void* m_body0;
+	void* m_body1;
+
+	int	m_cachedPoints;
+
+	btScalar	m_contactBreakingThreshold;
+	btScalar	m_contactProcessingThreshold;
+
+	
+	/// sort cached points so most isolated points come first
+	int	sortCachedPoints(const btManifoldPoint& pt);
+
+	int		findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt);
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	int	m_companionIdA;
+	int	m_companionIdB;
+
+	int m_index1a;
+
+	btPersistentManifold();
+
+	btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
+		: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+	m_body0(body0),m_body1(body1),m_cachedPoints(0),
+		m_contactBreakingThreshold(contactBreakingThreshold),
+		m_contactProcessingThreshold(contactProcessingThreshold)
+	{
+	}
+
+	SIMD_FORCE_INLINE void* getBody0() { return m_body0;}
+	SIMD_FORCE_INLINE void* getBody1() { return m_body1;}
+
+	SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;}
+	SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;}
+
+	void	setBodies(void* body0,void* body1)
+	{
+		m_body0 = body0;
+		m_body1 = body1;
+	}
+
+	void clearUserCache(btManifoldPoint& pt);
+
+#ifdef DEBUG_PERSISTENCY
+	void	DebugPersistency();
+#endif //
+	
+	SIMD_FORCE_INLINE int	getNumContacts() const { return m_cachedPoints;}
+
+	SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
+	{
+		btAssert(index < m_cachedPoints);
+		return m_pointCache[index];
+	}
+
+	SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
+	{
+		btAssert(index < m_cachedPoints);
+		return m_pointCache[index];
+	}
+
+	///@todo: get this margin from the current physics / collision environment
+	btScalar	getContactBreakingThreshold() const;
+
+	btScalar	getContactProcessingThreshold() const
+	{
+		return m_contactProcessingThreshold;
+	}
+	
+	int getCacheEntry(const btManifoldPoint& newPoint) const;
+
+	int addManifoldPoint( const btManifoldPoint& newPoint);
+
+	void removeContactPoint (int index)
+	{
+		clearUserCache(m_pointCache[index]);
+
+		int lastUsedIndex = getNumContacts() - 1;
+//		m_pointCache[index] = m_pointCache[lastUsedIndex];
+		if(index != lastUsedIndex) 
+		{
+			m_pointCache[index] = m_pointCache[lastUsedIndex]; 
+			//get rid of duplicated userPersistentData pointer
+			m_pointCache[lastUsedIndex].m_userPersistentData = 0;
+			m_pointCache[lastUsedIndex].mConstraintRow[0].m_accumImpulse = 0.f;
+			m_pointCache[lastUsedIndex].mConstraintRow[1].m_accumImpulse = 0.f;
+			m_pointCache[lastUsedIndex].mConstraintRow[2].m_accumImpulse = 0.f;
+
+			m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+			m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false;
+			m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
+			m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
+			m_pointCache[lastUsedIndex].m_lifeTime = 0;
+		}
+
+		btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
+		m_cachedPoints--;
+	}
+	void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex)
+	{
+		btAssert(validContactDistance(newPoint));
+
+#define MAINTAIN_PERSISTENCY 1
+#ifdef MAINTAIN_PERSISTENCY
+		int	lifeTime = m_pointCache[insertIndex].getLifeTime();
+		btScalar	appliedImpulse = m_pointCache[insertIndex].mConstraintRow[0].m_accumImpulse;
+		btScalar	appliedLateralImpulse1 = m_pointCache[insertIndex].mConstraintRow[1].m_accumImpulse;
+		btScalar	appliedLateralImpulse2 = m_pointCache[insertIndex].mConstraintRow[2].m_accumImpulse;
+//		bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized;
+		
+		
+			
+		btAssert(lifeTime>=0);
+		void* cache = m_pointCache[insertIndex].m_userPersistentData;
+		
+		m_pointCache[insertIndex] = newPoint;
+
+		m_pointCache[insertIndex].m_userPersistentData = cache;
+		m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+		m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
+		m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
+		
+		m_pointCache[insertIndex].mConstraintRow[0].m_accumImpulse =  appliedImpulse;
+		m_pointCache[insertIndex].mConstraintRow[1].m_accumImpulse = appliedLateralImpulse1;
+		m_pointCache[insertIndex].mConstraintRow[2].m_accumImpulse = appliedLateralImpulse2;
+
+
+		m_pointCache[insertIndex].m_lifeTime = lifeTime;
+#else
+		clearUserCache(m_pointCache[insertIndex]);
+		m_pointCache[insertIndex] = newPoint;
+	
+#endif
+	}
+
+	bool validContactDistance(const btManifoldPoint& pt) const
+	{
+		if (pt.m_lifeTime >1)
+		{
+			return pt.m_distance1 <= getContactBreakingThreshold();
+		}
+		return pt.m_distance1 <= getContactProcessingThreshold();
+	
+	}
+	/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+	void	refreshContactPoints(  const btTransform& trA,const btTransform& trB);
+
+	
+	SIMD_FORCE_INLINE	void	clearManifold()
+	{
+		int i;
+		for (i=0;i<m_cachedPoints;i++)
+		{
+			clearUserCache(m_pointCache[i]);
+		}
+		m_cachedPoints = 0;
+	}
+
+
+
+}
+;
+
+
+
+
+
+#endif //BT_PERSISTENT_MANIFOLD_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_POINT_COLLECTOR_H
+#define BT_POINT_COLLECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+
+
+
+struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
+{
+	
+	
+	btVector3 m_normalOnBInWorld;
+	btVector3 m_pointInWorld;
+	btScalar	m_distance;//negative means penetration
+
+	bool	m_hasResult;
+
+	btPointCollector () 
+		: m_distance(btScalar(BT_LARGE_FLOAT)),m_hasResult(false)
+	{
+	}
+
+	virtual void setShapeIdentifiersA(int partId0,int index0)
+	{
+		(void)partId0;
+		(void)index0;
+			
+	}
+	virtual void setShapeIdentifiersB(int partId1,int index1)
+	{
+		(void)partId1;
+		(void)index1;
+	}
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+	{
+		if (depth< m_distance)
+		{
+			m_hasResult = true;
+			m_normalOnBInWorld = normalOnBInWorld;
+			m_pointInWorld = pointInWorld;
+			//negative means penetration
+			m_distance = depth;
+		}
+	}
+};
+
+#endif //BT_POINT_COLLECTOR_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp	(revision 11817)
@@ -0,0 +1,360 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+///This file was written by Erwin Coumans
+///Separating axis rest based on work from Pierre Terdiman, see
+///And contact clipping based on work from Simon Hobbs
+
+
+#include "btPolyhedralContactClipping.h"
+#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
+
+#include <float.h> //for FLT_MAX
+
+
+// Clips a face to the back of a plane
+void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS)
+{
+	
+	int ve;
+	btScalar ds, de;
+	int numVerts = pVtxIn.size();
+	if (numVerts < 2)
+		return;
+
+	btVector3 firstVertex=pVtxIn[pVtxIn.size()-1];
+	btVector3 endVertex = pVtxIn[0];
+	
+	ds = planeNormalWS.dot(firstVertex)+planeEqWS;
+
+	for (ve = 0; ve < numVerts; ve++)
+	{
+		endVertex=pVtxIn[ve];
+
+		de = planeNormalWS.dot(endVertex)+planeEqWS;
+
+		if (ds<0)
+		{
+			if (de<0)
+			{
+				// Start < 0, end < 0, so output endVertex
+				ppVtxOut.push_back(endVertex);
+			}
+			else
+			{
+				// Start < 0, end >= 0, so output intersection
+				ppVtxOut.push_back( 	firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
+			}
+		}
+		else
+		{
+			if (de<0)
+			{
+				// Start >= 0, end < 0 so output intersection and end
+				ppVtxOut.push_back(firstVertex.lerp(endVertex,btScalar(ds * 1.f/(ds - de))));
+				ppVtxOut.push_back(endVertex);
+			}
+		}
+		firstVertex = endVertex;
+		ds = de;
+	}
+}
+#include <stdio.h>
+
+
+static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, float& depth)
+{
+	float Min0,Max0;
+	float Min1,Max1;
+	hullA.project(transA,sep_axis, Min0, Max0);
+	hullB.project(transB, sep_axis, Min1, Max1);
+
+	if(Max0<Min1 || Max1<Min0)
+		return false;
+
+	float d0 = Max0 - Min1;
+	assert(d0>=0.0f);
+	float d1 = Max1 - Min0;
+	assert(d1>=0.0f);
+	depth = d0<d1 ? d0:d1;
+	return true;
+}
+
+
+
+static int gActualSATPairTests=0;
+
+inline bool IsAlmostZero(const btVector3& v)
+{
+	if(fabsf(v.x())>1e-6 || fabsf(v.y())>1e-6 || fabsf(v.z())>1e-6)	return false;
+	return true;
+}
+
+
+bool btPolyhedralContactClipping::findSeparatingAxis(	const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep)
+{
+	gActualSATPairTests++;
+
+#ifdef TEST_INTERNAL_OBJECTS
+	const btVector3 c0 = transA * hullA.mLocalCenter;
+	const btVector3 c1 = transB * hullB.mLocalCenter;
+	const btVector3 DeltaC2 = c0 - c1;
+#endif
+
+	float dmin = FLT_MAX;
+	int curPlaneTests=0;
+
+	int numFacesA = hullA.m_faces.size();
+	// Test normals from hullA
+	for(int i=0;i<numFacesA;i++)
+	{
+		const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
+		const btVector3 faceANormalWS = transA.getBasis() * Normal;
+
+		curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+		gExpectedNbTests++;
+		if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, faceANormalWS, hullA, hullB, dmin))
+			continue;
+		gActualNbTests++;
+#endif
+
+		float d;
+		if(!TestSepAxis( hullA, hullB, transA,transB, faceANormalWS, d))
+			return false;
+
+		if(d<dmin)
+		{
+			dmin = d;
+			sep = faceANormalWS;
+		}
+	}
+
+	int numFacesB = hullB.m_faces.size();
+	// Test normals from hullB
+	for(int i=0;i<numFacesB;i++)
+	{
+		const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
+		const btVector3 WorldNormal = transB.getBasis() * Normal;
+
+		curPlaneTests++;
+#ifdef TEST_INTERNAL_OBJECTS
+		gExpectedNbTests++;
+		if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, WorldNormal, hullA, hullB, dmin))
+			continue;
+		gActualNbTests++;
+#endif
+
+		float d;
+		if(!TestSepAxis(hullA, hullB,transA,transB, WorldNormal,d))
+			return false;
+
+		if(d<dmin)
+		{
+			dmin = d;
+			sep = WorldNormal;
+		}
+	}
+
+	btVector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
+
+	int curEdgeEdge = 0;
+	// Test edges
+	for(int e0=0;e0<hullA.m_uniqueEdges.size();e0++)
+	{
+		const btVector3 edge0 = hullA.m_uniqueEdges[e0];
+		const btVector3 WorldEdge0 = transA.getBasis() * edge0;
+		for(int e1=0;e1<hullB.m_uniqueEdges.size();e1++)
+		{
+			const btVector3 edge1 = hullB.m_uniqueEdges[e1];
+			const btVector3 WorldEdge1 = transB.getBasis() * edge1;
+
+			btVector3 Cross = WorldEdge0.cross(WorldEdge1);
+			curEdgeEdge++;
+			if(!IsAlmostZero(Cross))
+			{
+				Cross = Cross.normalize();
+
+#ifdef TEST_INTERNAL_OBJECTS
+				gExpectedNbTests++;
+				if(gUseInternalObject && !TestInternalObjects(transA,transB,DeltaC2, Cross, hullA, hullB, dmin))
+					continue;
+				gActualNbTests++;
+#endif
+
+				float dist;
+				if(!TestSepAxis( hullA, hullB, transA,transB, Cross, dist))
+					return false;
+
+				if(dist<dmin)
+				{
+					dmin = dist;
+					sep = Cross;
+				}
+			}
+		}
+
+	}
+
+	const btVector3 deltaC = transB.getOrigin() - transA.getOrigin();
+	if((deltaC.dot(sep))>0.0f)
+		sep = -sep;
+
+	return true;
+}
+
+void	btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA,  const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+	btVertexArray worldVertsB2;
+	btVertexArray* pVtxIn = &worldVertsB1;
+	btVertexArray* pVtxOut = &worldVertsB2;
+	pVtxOut->reserve(pVtxIn->size());
+
+	int closestFaceA=-1;
+	{
+		btScalar dmin = FLT_MAX;
+		for(int face=0;face<hullA.m_faces.size();face++)
+		{
+			const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
+			const btVector3 faceANormalWS = transA.getBasis() * Normal;
+		
+			btScalar d = faceANormalWS.dot(separatingNormal);
+			if (d < dmin)
+			{
+				dmin = d;
+				closestFaceA = face;
+			}
+		}
+	}
+	if (closestFaceA<0)
+		return;
+
+	const btFace& polyA = hullA.m_faces[closestFaceA];
+
+		// clip polygon to back of planes of all faces of hull A that are adjacent to witness face
+	int numContacts = pVtxIn->size();
+	int numVerticesA = polyA.m_indices.size();
+	for(int e0=0;e0<numVerticesA;e0++)
+	{
+		/*const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
+		const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0+1)%numVerticesA]];
+		const btVector3 edge0 = a - b;
+		const btVector3 WorldEdge0 = transA.getBasis() * edge0;
+		*/
+
+		int otherFace = polyA.m_connectedFaces[e0];
+		btVector3 localPlaneNormal (hullA.m_faces[otherFace].m_plane[0],hullA.m_faces[otherFace].m_plane[1],hullA.m_faces[otherFace].m_plane[2]);
+		btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
+
+		btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
+		btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
+		//clip face
+
+		clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
+		btSwap(pVtxIn,pVtxOut);
+		pVtxOut->resize(0);
+	}
+
+
+
+//#define ONLY_REPORT_DEEPEST_POINT
+
+	btVector3 point;
+	
+
+	// only keep points that are behind the witness face
+	{
+		btVector3 localPlaneNormal (polyA.m_plane[0],polyA.m_plane[1],polyA.m_plane[2]);
+		btScalar localPlaneEq = polyA.m_plane[3];
+		btVector3 planeNormalWS = transA.getBasis()*localPlaneNormal;
+		btScalar planeEqWS=localPlaneEq-planeNormalWS.dot(transA.getOrigin());
+		for (int i=0;i<pVtxIn->size();i++)
+		{
+			
+			btScalar depth = planeNormalWS.dot(pVtxIn->at(i))+planeEqWS;
+			if (depth <=maxDist && depth >=minDist)
+			{
+				btVector3 point = pVtxIn->at(i);
+#ifdef ONLY_REPORT_DEEPEST_POINT
+				curMaxDist = depth;
+#else
+#if 0
+				if (depth<-3)
+				{
+					printf("error in btPolyhedralContactClipping depth = %f\n", depth);
+					printf("likely wrong separatingNormal passed in\n");
+				} 
+#endif				
+				resultOut.addContactPoint(separatingNormal,point,depth);
+#endif
+			}
+		}
+	}
+#ifdef ONLY_REPORT_DEEPEST_POINT
+	if (curMaxDist<maxDist)
+	{
+		resultOut.addContactPoint(separatingNormal,point,curMaxDist);
+	}
+#endif //ONLY_REPORT_DEEPEST_POINT
+
+}
+
+void	btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut)
+{
+
+	btScalar curMaxDist=maxDist;
+	int closestFaceB=-1;
+
+	{
+		btScalar dmax = -FLT_MAX;
+		for(int face=0;face<hullB.m_faces.size();face++)
+		{
+			const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
+			const btVector3 WorldNormal = transB.getBasis() * Normal;
+
+			btScalar d = WorldNormal.dot(separatingNormal);
+			if (d > dmax)
+			{
+				dmax = d;
+				closestFaceB = face;
+			}
+		}
+	}
+
+
+
+	if (closestFaceB<0)
+	{
+		return;
+	}
+
+
+
+	// setup initial clip face (minimizing face from hull B)
+	btVertexArray worldVertsB1;
+	{
+		const btFace& polyB = hullB.m_faces[closestFaceB];
+		const int numVertices = polyB.m_indices.size();
+		for(int e0=0;e0<numVertices;e0++)
+		{
+			const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
+			worldVertsB1.push_back(transB*b);
+		}
+	}
+
+	clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut);
+
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2011 Advanced Micro Devices, Inc.  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+///This file was written by Erwin Coumans
+
+
+#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H
+#define BT_POLYHEDRAL_CONTACT_CLIPPING_H
+
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "btDiscreteCollisionDetectorInterface.h"
+
+class btConvexPolyhedron;
+
+typedef btAlignedObjectArray<btVector3> btVertexArray;
+
+// Clips a face to the back of a plane
+struct btPolyhedralContactClipping
+{
+	static void clipHullAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
+	static void	clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA,  const btTransform& transA, btVertexArray& worldVertsB1, const btScalar minDist, btScalar maxDist,btDiscreteCollisionDetectorInterface::Result& resultOut);
+
+	static bool findSeparatingAxis(	const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, btVector3& sep);
+
+	///the clipFace method is used internally
+	static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS,btScalar planeEqWS);
+
+};
+
+#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp	(revision 11817)
@@ -0,0 +1,177 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#include <stdio.h>
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "btRaycastCallback.h"
+
+btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags)
+	:
+	m_from(from),
+	m_to(to),
+   //@BP Mod
+   m_flags(flags),
+	m_hitFraction(btScalar(1.))
+{
+
+}
+
+
+
+void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+	const btVector3 &vert0=triangle[0];
+	const btVector3 &vert1=triangle[1];
+	const btVector3 &vert2=triangle[2];
+
+	btVector3 v10; v10 = vert1 - vert0 ;
+	btVector3 v20; v20 = vert2 - vert0 ;
+
+	btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
+	
+	const btScalar dist = vert0.dot(triangleNormal);
+	btScalar dist_a = triangleNormal.dot(m_from) ;
+	dist_a-= dist;
+	btScalar dist_b = triangleNormal.dot(m_to);
+	dist_b -= dist;
+
+	if ( dist_a * dist_b >= btScalar(0.0) )
+	{
+		return ; // same sign
+	}
+   //@BP Mod - Backface filtering
+   if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0)))
+   {
+      // Backface, skip check
+      return;
+   }
+	
+	const btScalar proj_length=dist_a-dist_b;
+	const btScalar distance = (dist_a)/(proj_length);
+	// Now we have the intersection point on the plane, we'll see if it's inside the triangle
+	// Add an epsilon as a tolerance for the raycast,
+	// in case the ray hits exacly on the edge of the triangle.
+	// It must be scaled for the triangle size.
+	
+	if(distance < m_hitFraction)
+	{
+		
+
+		btScalar edge_tolerance =triangleNormal.length2();		
+		edge_tolerance *= btScalar(-0.0001);
+		btVector3 point; point.setInterpolate3( m_from, m_to, distance);
+		{
+			btVector3 v0p; v0p = vert0 - point;
+			btVector3 v1p; v1p = vert1 - point;
+			btVector3 cp0; cp0 = v0p.cross( v1p );
+
+			if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) 
+			{
+						
+
+				btVector3 v2p; v2p = vert2 -  point;
+				btVector3 cp1;
+				cp1 = v1p.cross( v2p);
+				if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) 
+				{
+					btVector3 cp2;
+					cp2 = v2p.cross(v0p);
+					
+					if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) 
+					{
+                  //@BP Mod
+                  // Triangle normal isn't normalized
+				      triangleNormal.normalize();
+
+                  //@BP Mod - Allow for unflipped normal when raycasting against backfaces
+                  if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0)))
+						{
+							m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
+						}
+						else
+						{
+                     m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+
+btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
+{
+	m_convexShape = convexShape;
+	m_convexShapeFrom = convexShapeFrom;
+	m_convexShapeTo = convexShapeTo;
+	m_triangleToWorld = triangleToWorld;
+	m_hitFraction = 1.0f;
+	m_triangleCollisionMargin = triangleCollisionMargin;
+	m_allowedPenetration = 0.f;
+}
+
+void
+btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
+{
+	btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
+    triangleShape.setMargin(m_triangleCollisionMargin);
+
+	btVoronoiSimplexSolver	simplexSolver;
+	btGjkEpaPenetrationDepthSolver	gjkEpaPenetrationSolver;
+
+//#define  USE_SUBSIMPLEX_CONVEX_CAST 1
+//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+	btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
+#else
+	//btGjkConvexCast	convexCaster(m_convexShape,&triangleShape,&simplexSolver);
+	btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+	
+	btConvexCast::CastResult castResult;
+	castResult.m_fraction = btScalar(1.);
+	castResult.m_allowedPenetration = m_allowedPenetration;
+	if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
+	{
+		//add hit
+		if (castResult.m_normal.length2() > btScalar(0.0001))
+		{					
+			if (castResult.m_fraction < m_hitFraction)
+			{
+/* btContinuousConvexCast's normal is already in world space */
+/*
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+				//rotate normal into worldspace
+				castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+*/
+				castResult.m_normal.normalize();
+
+				reportHit (castResult.m_normal,
+							castResult.m_hitPoint,
+							castResult.m_fraction,
+							partId,
+							triangleIndex);
+			}
+		}
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_RAYCAST_TRI_CALLBACK_H
+#define BT_RAYCAST_TRI_CALLBACK_H
+
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "LinearMath/btTransform.h"
+struct btBroadphaseProxy;
+class btConvexShape;
+
+class  btTriangleRaycastCallback: public btTriangleCallback
+{
+public:
+
+	//input
+	btVector3 m_from;
+	btVector3 m_to;
+
+   //@BP Mod - allow backface filtering and unflipped normals
+   enum EFlags
+   {
+      kF_None                 = 0,
+      kF_FilterBackfaces      = 1 << 0,
+      kF_KeepUnflippedNormal  = 1 << 1,   // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
+
+      kF_Terminator        = 0xFFFFFFFF
+   };
+   unsigned int m_flags;
+
+	btScalar	m_hitFraction;
+
+	btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0);
+	
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+	virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0;
+	
+};
+
+class btTriangleConvexcastCallback : public btTriangleCallback
+{
+public:
+	const btConvexShape* m_convexShape;
+	btTransform m_convexShapeFrom;
+	btTransform m_convexShapeTo;
+	btTransform m_triangleToWorld;
+	btScalar m_hitFraction;
+	btScalar m_triangleCollisionMargin;
+	btScalar m_allowedPenetration;
+
+	btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
+
+	virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
+
+	virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
+};
+
+#endif //BT_RAYCAST_TRI_CALLBACK_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H
+#define BT_SIMPLEX_SOLVER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+
+#define NO_VIRTUAL_INTERFACE 1
+#ifdef NO_VIRTUAL_INTERFACE
+#include "btVoronoiSimplexSolver.h"
+#define btSimplexSolverInterface btVoronoiSimplexSolver
+#else
+
+/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices
+/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on
+/// voronoi regions or barycentric coordinates
+class btSimplexSolverInterface
+{
+	public:
+		virtual ~btSimplexSolverInterface() {};
+
+	virtual void reset() = 0;
+
+	virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
+	
+	virtual bool closest(btVector3& v) = 0;
+
+	virtual btScalar maxVertex() = 0;
+
+	virtual bool fullSimplex() const = 0;
+
+	virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0;
+
+	virtual bool inSimplex(const btVector3& w) = 0;
+	
+	virtual void backup_closest(btVector3& v) = 0;
+
+	virtual bool emptySimplex() const = 0;
+
+	virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
+
+	virtual int numVertices() const =0;
+
+
+};
+#endif
+#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp	(revision 11817)
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
+:m_simplexSolver(simplexSolver),
+m_convexA(convexA),m_convexB(convexB)
+{
+}
+
+///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
+///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
+bool	btSubsimplexConvexCast::calcTimeOfImpact(
+		const btTransform& fromA,
+		const btTransform& toA,
+		const btTransform& fromB,
+		const btTransform& toB,
+		CastResult& result)
+{
+
+	m_simplexSolver->reset();
+
+	btVector3 linVelA,linVelB;
+	linVelA = toA.getOrigin()-fromA.getOrigin();
+	linVelB = toB.getOrigin()-fromB.getOrigin();
+
+	btScalar lambda = btScalar(0.);
+
+	btTransform interpolatedTransA = fromA;
+	btTransform interpolatedTransB = fromB;
+
+	///take relative motion
+	btVector3 r = (linVelA-linVelB);
+	btVector3 v;
+	
+	btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis()));
+	btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis()));
+	v = supVertexA-supVertexB;
+	int maxIter = MAX_ITERATIONS;
+
+	btVector3 n;
+	n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	bool hasResult = false;
+	btVector3 c;
+
+	btScalar lastLambda = lambda;
+
+
+	btScalar dist2 = v.length2();
+#ifdef BT_USE_DOUBLE_PRECISION
+	btScalar epsilon = btScalar(0.0001);
+#else
+	btScalar epsilon = btScalar(0.0001);
+#endif //BT_USE_DOUBLE_PRECISION
+	btVector3	w,p;
+	btScalar VdotR;
+	
+	while ( (dist2 > epsilon) && maxIter--)
+	{
+		supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis()));
+		supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis()));
+		w = supVertexA-supVertexB;
+
+		btScalar VdotW = v.dot(w);
+
+		if (lambda > btScalar(1.0))
+		{
+			return false;
+		}
+
+		if ( VdotW > btScalar(0.))
+		{
+			VdotR = v.dot(r);
+
+			if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
+				return false;
+			else
+			{
+				lambda = lambda - VdotW / VdotR;
+				//interpolate to next lambda
+				//	x = s + lambda * r;
+				interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+				interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+				//m_simplexSolver->reset();
+				//check next line
+				 w = supVertexA-supVertexB;
+				lastLambda = lambda;
+				n = v;
+				hasResult = true;
+			}
+		} 
+		///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
+		if (!m_simplexSolver->inSimplex(w))
+			m_simplexSolver->addVertex( w, supVertexA , supVertexB);
+
+		if (m_simplexSolver->closest(v))
+		{
+			dist2 = v.length2();
+			hasResult = true;
+			//todo: check this normal for validity
+			//n=v;
+			//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
+			//printf("DIST2=%f\n",dist2);
+			//printf("numverts = %i\n",m_simplexSolver->numVertices());
+		} else
+		{
+			dist2 = btScalar(0.);
+		} 
+	}
+
+	//int numiter = MAX_ITERATIONS - maxIter;
+//	printf("number of iterations: %d", numiter);
+	
+	//don't report a time of impact when moving 'away' from the hitnormal
+	
+
+	result.m_fraction = lambda;
+	if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON))
+		result.m_normal = n.normalized();
+	else
+		result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+
+	//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+	if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
+		return false;
+
+	btVector3 hitA,hitB;
+	m_simplexSolver->compute_points(hitA,hitB);
+	result.m_hitPoint=hitB;
+	return true;
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H
+#define BT_SUBSIMPLEX_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+
+/// btSubsimplexConvexCast implements Gino van den Bergens' paper
+///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
+/// GJK based Ray Cast, optimized version
+/// Objects should not start in overlap, otherwise results are not defined.
+class btSubsimplexConvexCast : public btConvexCast
+{
+	btSimplexSolverInterface* m_simplexSolver;
+	const btConvexShape*	m_convexA;
+	const btConvexShape*	m_convexB;
+
+public:
+
+	btSubsimplexConvexCast (const btConvexShape*	shapeA,const btConvexShape*	shapeB,btSimplexSolverInterface* simplexSolver);
+
+	//virtual ~btSubsimplexConvexCast();
+	///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
+	///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
+	virtual bool	calcTimeOfImpact(
+			const btTransform& fromA,
+			const btTransform& toA,
+			const btTransform& fromB,
+			const btTransform& toB,
+			CastResult& result);
+
+};
+
+#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp	(revision 11817)
@@ -0,0 +1,609 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+	
+	Elsevier CDROM license agreements grants nonexclusive license to use the software
+	for any purpose, commercial or non-commercial as long as the following credit is included
+	identifying the original source of the software:
+
+	Parts of the source are "from the book Real-Time Collision Detection by
+	Christer Ericson, published by Morgan Kaufmann Publishers,
+	(c) 2005 Elsevier Inc."
+		
+*/
+
+
+#include "btVoronoiSimplexSolver.h"
+
+#define VERTA  0
+#define VERTB  1
+#define VERTC  2
+#define VERTD  3
+
+#define CATCH_DEGENERATE_TETRAHEDRON 1
+void	btVoronoiSimplexSolver::removeVertex(int index)
+{
+	
+	btAssert(m_numVertices>0);
+	m_numVertices--;
+	m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
+	m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
+	m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
+}
+
+void	btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
+{
+	if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
+		removeVertex(3);
+
+	if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
+		removeVertex(2);
+
+	if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
+		removeVertex(1);
+	
+	if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
+		removeVertex(0);
+
+}
+
+
+
+
+
+//clear the simplex, remove all the vertices
+void btVoronoiSimplexSolver::reset()
+{
+	m_cachedValidClosest = false;
+	m_numVertices = 0;
+	m_needsUpdate = true;
+	m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	m_cachedBC.reset();
+}
+
+
+
+	//add a vertex
+void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
+{
+	m_lastW = w;
+	m_needsUpdate = true;
+
+	m_simplexVectorW[m_numVertices] = w;
+	m_simplexPointsP[m_numVertices] = p;
+	m_simplexPointsQ[m_numVertices] = q;
+
+	m_numVertices++;
+}
+
+bool	btVoronoiSimplexSolver::updateClosestVectorAndPoints()
+{
+	
+	if (m_needsUpdate)
+	{
+		m_cachedBC.reset();
+
+		m_needsUpdate = false;
+
+		switch (numVertices())
+		{
+		case 0:
+				m_cachedValidClosest = false;
+				break;
+		case 1:
+			{
+				m_cachedP1 = m_simplexPointsP[0];
+				m_cachedP2 = m_simplexPointsQ[0];
+				m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
+				m_cachedBC.reset();
+				m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.));
+				m_cachedValidClosest = m_cachedBC.isValid();
+				break;
+			};
+		case 2:
+			{
+			//closest point origin from line segment
+					const btVector3& from = m_simplexVectorW[0];
+					const btVector3& to = m_simplexVectorW[1];
+					btVector3 nearest;
+
+					btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+					btVector3 diff = p - from;
+					btVector3 v = to - from;
+					btScalar t = v.dot(diff);
+					
+					if (t > 0) {
+						btScalar dotVV = v.dot(v);
+						if (t < dotVV) {
+							t /= dotVV;
+							diff -= t*v;
+							m_cachedBC.m_usedVertices.usedVertexA = true;
+							m_cachedBC.m_usedVertices.usedVertexB = true;
+						} else {
+							t = 1;
+							diff -= v;
+							//reduce to 1 point
+							m_cachedBC.m_usedVertices.usedVertexB = true;
+						}
+					} else
+					{
+						t = 0;
+						//reduce to 1 point
+						m_cachedBC.m_usedVertices.usedVertexA = true;
+					}
+					m_cachedBC.setBarycentricCoordinates(1-t,t);
+					nearest = from + t*v;
+
+					m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+					m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+					m_cachedV = m_cachedP1 - m_cachedP2;
+					
+					reduceVertices(m_cachedBC.m_usedVertices);
+
+					m_cachedValidClosest = m_cachedBC.isValid();
+					break;
+			}
+		case 3: 
+			{ 
+				//closest point origin from triangle 
+				btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); 
+
+				const btVector3& a = m_simplexVectorW[0]; 
+				const btVector3& b = m_simplexVectorW[1]; 
+				const btVector3& c = m_simplexVectorW[2]; 
+
+				closestPtPointTriangle(p,a,b,c,m_cachedBC); 
+				m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + 
+				m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + 
+				m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2]; 
+
+				m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + 
+				m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + 
+				m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2]; 
+
+				m_cachedV = m_cachedP1-m_cachedP2; 
+
+				reduceVertices (m_cachedBC.m_usedVertices); 
+				m_cachedValidClosest = m_cachedBC.isValid(); 
+
+				break; 
+			}
+		case 4:
+			{
+
+				
+				btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+				
+				const btVector3& a = m_simplexVectorW[0];
+				const btVector3& b = m_simplexVectorW[1];
+				const btVector3& c = m_simplexVectorW[2];
+				const btVector3& d = m_simplexVectorW[3];
+
+				bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
+
+				if (hasSeperation)
+				{
+
+					m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+						m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+						m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+						m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+
+					m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+						m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+						m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+						m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+
+					m_cachedV = m_cachedP1-m_cachedP2;
+					reduceVertices (m_cachedBC.m_usedVertices);
+				} else
+				{
+//					printf("sub distance got penetration\n");
+
+					if (m_cachedBC.m_degenerate)
+					{
+						m_cachedValidClosest = false;
+					} else
+					{
+						m_cachedValidClosest = true;
+						//degenerate case == false, penetration = true + zero
+						m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+					}
+					break;
+				}
+
+				m_cachedValidClosest = m_cachedBC.isValid();
+
+				//closest point origin from tetrahedron
+				break;
+			}
+		default:
+			{
+				m_cachedValidClosest = false;
+			}
+		};
+	}
+
+	return m_cachedValidClosest;
+
+}
+
+//return/calculate the closest vertex
+bool btVoronoiSimplexSolver::closest(btVector3& v)
+{
+	bool succes = updateClosestVectorAndPoints();
+	v = m_cachedV;
+	return succes;
+}
+
+
+
+btScalar btVoronoiSimplexSolver::maxVertex()
+{
+	int i, numverts = numVertices();
+	btScalar maxV = btScalar(0.);
+	for (i=0;i<numverts;i++)
+	{
+		btScalar curLen2 = m_simplexVectorW[i].length2();
+		if (maxV < curLen2)
+			maxV = curLen2;
+	}
+	return maxV;
+}
+
+
+
+	//return the current simplex
+int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const
+{
+	int i;
+	for (i=0;i<numVertices();i++)
+	{
+		yBuf[i] = m_simplexVectorW[i];
+		pBuf[i] = m_simplexPointsP[i];
+		qBuf[i] = m_simplexPointsQ[i];
+	}
+	return numVertices();
+}
+
+
+
+
+bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
+{
+	bool found = false;
+	int i, numverts = numVertices();
+	//btScalar maxV = btScalar(0.);
+	
+	//w is in the current (reduced) simplex
+	for (i=0;i<numverts;i++)
+	{
+#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
+		if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+#else
+		if (m_simplexVectorW[i] == w)
+#endif
+			found = true;
+	}
+
+	//check in case lastW is already removed
+	if (w == m_lastW)
+		return true;
+    	
+	return found;
+}
+
+void btVoronoiSimplexSolver::backup_closest(btVector3& v) 
+{
+	v = m_cachedV;
+}
+
+
+bool btVoronoiSimplexSolver::emptySimplex() const 
+{
+	return (numVertices() == 0);
+
+}
+
+void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2) 
+{
+	updateClosestVectorAndPoints();
+	p1 = m_cachedP1;
+	p2 = m_cachedP2;
+
+}
+
+
+
+
+bool	btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result)
+{
+	result.m_usedVertices.reset();
+
+    // Check if P in vertex region outside A
+    btVector3 ab = b - a;
+    btVector3 ac = c - a;
+    btVector3 ap = p - a;
+    btScalar d1 = ab.dot(ap);
+    btScalar d2 = ac.dot(ap);
+    if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0)) 
+	{
+		result.m_closestPointOnSimplex = a;
+		result.m_usedVertices.usedVertexA = true;
+		result.setBarycentricCoordinates(1,0,0);
+		return true;// a; // barycentric coordinates (1,0,0)
+	}
+
+    // Check if P in vertex region outside B
+    btVector3 bp = p - b;
+    btScalar d3 = ab.dot(bp);
+    btScalar d4 = ac.dot(bp);
+    if (d3 >= btScalar(0.0) && d4 <= d3) 
+	{
+		result.m_closestPointOnSimplex = b;
+		result.m_usedVertices.usedVertexB = true;
+		result.setBarycentricCoordinates(0,1,0);
+
+		return true; // b; // barycentric coordinates (0,1,0)
+	}
+    // Check if P in edge region of AB, if so return projection of P onto AB
+    btScalar vc = d1*d4 - d3*d2;
+    if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) {
+        btScalar v = d1 / (d1 - d3);
+		result.m_closestPointOnSimplex = a + v * ab;
+		result.m_usedVertices.usedVertexA = true;
+		result.m_usedVertices.usedVertexB = true;
+		result.setBarycentricCoordinates(1-v,v,0);
+		return true;
+        //return a + v * ab; // barycentric coordinates (1-v,v,0)
+    }
+
+    // Check if P in vertex region outside C
+    btVector3 cp = p - c;
+    btScalar d5 = ab.dot(cp);
+    btScalar d6 = ac.dot(cp);
+    if (d6 >= btScalar(0.0) && d5 <= d6) 
+	{
+		result.m_closestPointOnSimplex = c;
+		result.m_usedVertices.usedVertexC = true;
+		result.setBarycentricCoordinates(0,0,1);
+		return true;//c; // barycentric coordinates (0,0,1)
+	}
+
+    // Check if P in edge region of AC, if so return projection of P onto AC
+    btScalar vb = d5*d2 - d1*d6;
+    if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) {
+        btScalar w = d2 / (d2 - d6);
+		result.m_closestPointOnSimplex = a + w * ac;
+		result.m_usedVertices.usedVertexA = true;
+		result.m_usedVertices.usedVertexC = true;
+		result.setBarycentricCoordinates(1-w,0,w);
+		return true;
+        //return a + w * ac; // barycentric coordinates (1-w,0,w)
+    }
+
+    // Check if P in edge region of BC, if so return projection of P onto BC
+    btScalar va = d3*d6 - d5*d4;
+    if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) {
+        btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+		
+		result.m_closestPointOnSimplex = b + w * (c - b);
+		result.m_usedVertices.usedVertexB = true;
+		result.m_usedVertices.usedVertexC = true;
+		result.setBarycentricCoordinates(0,1-w,w);
+		return true;		
+       // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+    }
+
+    // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+    btScalar denom = btScalar(1.0) / (va + vb + vc);
+    btScalar v = vb * denom;
+    btScalar w = vc * denom;
+    
+	result.m_closestPointOnSimplex = a + ab * v + ac * w;
+	result.m_usedVertices.usedVertexA = true;
+	result.m_usedVertices.usedVertexB = true;
+	result.m_usedVertices.usedVertexC = true;
+	result.setBarycentricCoordinates(1-v-w,v,w);
+	
+	return true;
+//	return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
+
+}
+
+
+
+
+
+/// Test if point p and d lie on opposite sides of plane through abc
+int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
+{
+	btVector3 normal = (b-a).cross(c-a);
+
+    btScalar signp = (p - a).dot(normal); // [AP AB AC]
+    btScalar signd = (d - a).dot( normal); // [AD AB AC]
+
+#ifdef CATCH_DEGENERATE_TETRAHEDRON
+#ifdef BT_USE_DOUBLE_PRECISION
+if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
+	{
+		return -1;
+	}
+#else
+	if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
+	{
+//		printf("affine dependent/degenerate\n");//
+		return -1;
+	}
+#endif
+
+#endif
+	// Points on opposite sides if expression signs are opposite
+    return signp * signd < btScalar(0.);
+}
+
+
+bool	btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
+{
+	btSubSimplexClosestResult tempResult;
+
+    // Start out assuming point inside all halfspaces, so closest to itself
+	finalResult.m_closestPointOnSimplex = p;
+	finalResult.m_usedVertices.reset();
+    finalResult.m_usedVertices.usedVertexA = true;
+	finalResult.m_usedVertices.usedVertexB = true;
+	finalResult.m_usedVertices.usedVertexC = true;
+	finalResult.m_usedVertices.usedVertexD = true;
+
+    int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+	int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
+  	int	pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+	int	pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
+
+   if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+   {
+	   finalResult.m_degenerate = true;
+	   return false;
+   }
+
+   if (!pointOutsideABC  && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+	 {
+		 return false;
+	 }
+
+
+    btScalar bestSqDist = FLT_MAX;
+    // If point outside face abc then compute closest point on abc
+	if (pointOutsideABC) 
+	{
+        closestPtPointTriangle(p, a, b, c,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		
+        btScalar sqDist = (q - p).dot( q - p);
+        // Update best closest point if (squared) distance is less than current best
+        if (sqDist < bestSqDist) {
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			//convert result bitmask!
+			finalResult.m_usedVertices.reset();
+			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
+			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+			finalResult.setBarycentricCoordinates(
+					tempResult.m_barycentricCoords[VERTA],
+					tempResult.m_barycentricCoords[VERTB],
+					tempResult.m_barycentricCoords[VERTC],
+					0
+			);
+
+		}
+    }
+  
+
+	// Repeat test for face acd
+	if (pointOutsideACD) 
+	{
+        closestPtPointTriangle(p, a, c, d,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		//convert result bitmask!
+
+        btScalar sqDist = (q - p).dot( q - p);
+        if (sqDist < bestSqDist) 
+		{
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			finalResult.m_usedVertices.reset();
+			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+
+			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
+			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
+			finalResult.setBarycentricCoordinates(
+					tempResult.m_barycentricCoords[VERTA],
+					0,
+					tempResult.m_barycentricCoords[VERTB],
+					tempResult.m_barycentricCoords[VERTC]
+			);
+
+		}
+    }
+    // Repeat test for face adb
+
+	
+	if (pointOutsideADB)
+	{
+		closestPtPointTriangle(p, a, d, b,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		//convert result bitmask!
+
+        btScalar sqDist = (q - p).dot( q - p);
+        if (sqDist < bestSqDist) 
+		{
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			finalResult.m_usedVertices.reset();
+			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
+			
+			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+			finalResult.setBarycentricCoordinates(
+					tempResult.m_barycentricCoords[VERTA],
+					tempResult.m_barycentricCoords[VERTC],
+					0,
+					tempResult.m_barycentricCoords[VERTB]
+			);
+
+		}
+    }
+    // Repeat test for face bdc
+    
+
+	if (pointOutsideBDC)
+	{
+        closestPtPointTriangle(p, b, d, c,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		//convert result bitmask!
+        btScalar sqDist = (q - p).dot( q - p);
+        if (sqDist < bestSqDist) 
+		{
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			finalResult.m_usedVertices.reset();
+			//
+			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
+			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+
+			finalResult.setBarycentricCoordinates(
+					0,
+					tempResult.m_barycentricCoords[VERTA],
+					tempResult.m_barycentricCoords[VERTC],
+					tempResult.m_barycentricCoords[VERTB]
+			);
+
+		}
+    }
+
+	//help! we ended up full !
+	
+	if (finalResult.m_usedVertices.usedVertexA &&
+		finalResult.m_usedVertices.usedVertexB &&
+		finalResult.m_usedVertices.usedVertexC &&
+		finalResult.m_usedVertices.usedVertexD) 
+	{
+		return true;
+	}
+
+    return true;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h	(revision 11817)
@@ -0,0 +1,179 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_VORONOI_SIMPLEX_SOLVER_H
+#define BT_VORONOI_SIMPLEX_SOLVER_H
+
+#include "btSimplexSolverInterface.h"
+
+
+
+#define VORONOI_SIMPLEX_MAX_VERTS 5
+
+///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
+#define BT_USE_EQUAL_VERTEX_THRESHOLD
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
+
+
+struct btUsageBitfield{
+	btUsageBitfield()
+	{
+		reset();
+	}
+
+	void reset()
+	{
+		usedVertexA = false;
+		usedVertexB = false;
+		usedVertexC = false;
+		usedVertexD = false;
+	}
+	unsigned short usedVertexA	: 1;
+	unsigned short usedVertexB	: 1;
+	unsigned short usedVertexC	: 1;
+	unsigned short usedVertexD	: 1;
+	unsigned short unused1		: 1;
+	unsigned short unused2		: 1;
+	unsigned short unused3		: 1;
+	unsigned short unused4		: 1;
+};
+
+
+struct	btSubSimplexClosestResult
+{
+	btVector3	m_closestPointOnSimplex;
+	//MASK for m_usedVertices
+	//stores the simplex vertex-usage, using the MASK, 
+	// if m_usedVertices & MASK then the related vertex is used
+	btUsageBitfield	m_usedVertices;
+	btScalar	m_barycentricCoords[4];
+	bool m_degenerate;
+
+	void	reset()
+	{
+		m_degenerate = false;
+		setBarycentricCoordinates();
+		m_usedVertices.reset();
+	}
+	bool	isValid()
+	{
+		bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
+			(m_barycentricCoords[1] >= btScalar(0.)) &&
+			(m_barycentricCoords[2] >= btScalar(0.)) &&
+			(m_barycentricCoords[3] >= btScalar(0.));
+
+
+		return valid;
+	}
+	void	setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.))
+	{
+		m_barycentricCoords[0] = a;
+		m_barycentricCoords[1] = b;
+		m_barycentricCoords[2] = c;
+		m_barycentricCoords[3] = d;
+	}
+
+};
+
+/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
+/// Can be used with GJK, as an alternative to Johnson distance algorithm.
+#ifdef NO_VIRTUAL_INTERFACE
+class btVoronoiSimplexSolver
+#else
+class btVoronoiSimplexSolver : public btSimplexSolverInterface
+#endif
+{
+public:
+
+	int	m_numVertices;
+
+	btVector3	m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+	btVector3	m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+	btVector3	m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+
+	
+
+	btVector3	m_cachedP1;
+	btVector3	m_cachedP2;
+	btVector3	m_cachedV;
+	btVector3	m_lastW;
+	
+	btScalar	m_equalVertexThreshold;
+	bool		m_cachedValidClosest;
+
+
+	btSubSimplexClosestResult m_cachedBC;
+
+	bool	m_needsUpdate;
+	
+	void	removeVertex(int index);
+	void	reduceVertices (const btUsageBitfield& usedVerts);
+	bool	updateClosestVectorAndPoints();
+
+	bool	closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
+	int		pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
+	bool	closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result);
+
+public:
+
+	btVoronoiSimplexSolver()
+		:  m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+	{
+	}
+	 void reset();
+
+	 void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
+
+	 void	setEqualVertexThreshold(btScalar threshold)
+	 {
+		 m_equalVertexThreshold = threshold;
+	 }
+
+	 btScalar	getEqualVertexThreshold() const
+	 {
+		 return m_equalVertexThreshold;
+	 }
+
+	 bool closest(btVector3& v);
+
+	 btScalar maxVertex();
+
+	 bool fullSimplex() const
+	 {
+		 return (m_numVertices == 4);
+	 }
+
+	 int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const;
+
+	 bool inSimplex(const btVector3& w);
+	
+	 void backup_closest(btVector3& v) ;
+
+	 bool emptySimplex() const ;
+
+	 void compute_points(btVector3& p1, btVector3& p2) ;
+
+	 int numVertices() const 
+	 {
+		 return m_numVertices;
+	 }
+
+
+};
+
+#endif //BT_VORONOI_SIMPLEX_SOLVER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,57 @@
+ADD_SOURCE_FILES(BULLET_FILES
+
+	Character/btKinematicCharacterController.cpp
+
+	ConstraintSolver/btConeTwistConstraint.cpp
+	ConstraintSolver/btContactConstraint.cpp
+	ConstraintSolver/btGeneric6DofConstraint.cpp
+	ConstraintSolver/btGeneric6DofSpringConstraint.cpp
+	ConstraintSolver/btHinge2Constraint.cpp
+	ConstraintSolver/btHingeConstraint.cpp
+	ConstraintSolver/btPoint2PointConstraint.cpp
+	ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+	ConstraintSolver/btSliderConstraint.cpp
+	ConstraintSolver/btSolve2LinearConstraint.cpp
+	ConstraintSolver/btTypedConstraint.cpp
+	ConstraintSolver/btUniversalConstraint.cpp
+
+	Dynamics/btContinuousDynamicsWorld.cpp
+	Dynamics/btDiscreteDynamicsWorld.cpp
+	Dynamics/btRigidBody.cpp
+	Dynamics/btSimpleDynamicsWorld.cpp
+	Dynamics/Bullet-C-API.cpp
+	Vehicle/btRaycastVehicle.cpp
+	Vehicle/btWheelInfo.cpp
+
+	# Headers
+	ConstraintSolver/btConeTwistConstraint.h
+	ConstraintSolver/btConstraintSolver.h
+	ConstraintSolver/btContactConstraint.h
+	ConstraintSolver/btContactSolverInfo.h
+	ConstraintSolver/btGeneric6DofConstraint.h
+	ConstraintSolver/btGeneric6DofSpringConstraint.h
+	ConstraintSolver/btHinge2Constraint.h
+	ConstraintSolver/btHingeConstraint.h
+	ConstraintSolver/btJacobianEntry.h
+	ConstraintSolver/btPoint2PointConstraint.h
+	ConstraintSolver/btSequentialImpulseConstraintSolver.h
+	ConstraintSolver/btSliderConstraint.h
+	ConstraintSolver/btSolve2LinearConstraint.h
+	ConstraintSolver/btSolverBody.h
+	ConstraintSolver/btSolverConstraint.h
+	ConstraintSolver/btTypedConstraint.h
+	ConstraintSolver/btUniversalConstraint.h
+	Dynamics/btActionInterface.h
+	Dynamics/btContinuousDynamicsWorld.h
+	Dynamics/btDiscreteDynamicsWorld.h
+	Dynamics/btDynamicsWorld.h
+	Dynamics/btSimpleDynamicsWorld.h
+	Dynamics/btRigidBody.h
+
+	Vehicle/btRaycastVehicle.h
+	Vehicle/btVehicleRaycaster.h
+	Vehicle/btWheelInfo.h
+
+	Character/btCharacterControllerInterface.h
+	Character/btKinematicCharacterController.h
+)
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btCharacterControllerInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btCharacterControllerInterface.h	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CHARACTER_CONTROLLER_INTERFACE_H
+#define BT_CHARACTER_CONTROLLER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+
+class btCollisionShape;
+class btRigidBody;
+class btCollisionWorld;
+
+class btCharacterControllerInterface : public btActionInterface
+{
+public:
+	btCharacterControllerInterface () {};
+	virtual ~btCharacterControllerInterface () {};
+	
+	virtual void	setWalkDirection(const btVector3& walkDirection) = 0;
+	virtual void	setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
+	virtual void	reset () = 0;
+	virtual void	warp (const btVector3& origin) = 0;
+
+	virtual void	preStep ( btCollisionWorld* collisionWorld) = 0;
+	virtual void	playerStep (btCollisionWorld* collisionWorld, btScalar dt) = 0;
+	virtual bool	canJump () const = 0;
+	virtual void	jump () = 0;
+
+	virtual bool	onGround () const = 0;
+};
+
+#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp	(revision 11817)
@@ -0,0 +1,641 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btGhostObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "btKinematicCharacterController.h"
+
+
+// static helper method
+static btVector3
+getNormalizedVector(const btVector3& v)
+{
+	btVector3 n = v.normalized();
+	if (n.length() < SIMD_EPSILON) {
+		n.setValue(0, 0, 0);
+	}
+	return n;
+}
+
+
+///@todo Interact with dynamic objects,
+///Ride kinematicly animated platforms properly
+///More realistic (or maybe just a config option) falling
+/// -> Should integrate falling velocity manually and use that in stepDown()
+///Support jumping
+///Support ducking
+class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
+{
+public:
+	btKinematicClosestNotMeRayResultCallback (btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
+	{
+		m_me = me;
+	}
+
+	virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace)
+	{
+		if (rayResult.m_collisionObject == m_me)
+			return 1.0;
+
+		return ClosestRayResultCallback::addSingleResult (rayResult, normalInWorldSpace);
+	}
+protected:
+	btCollisionObject* m_me;
+};
+
+class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+public:
+	btKinematicClosestNotMeConvexResultCallback (btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
+	: btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
+	, m_me(me)
+	, m_up(up)
+	, m_minSlopeDot(minSlopeDot)
+	{
+	}
+
+	virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+	{
+		if (convexResult.m_hitCollisionObject == m_me)
+			return btScalar(1.0);
+
+		btVector3 hitNormalWorld;
+		if (normalInWorldSpace)
+		{
+			hitNormalWorld = convexResult.m_hitNormalLocal;
+		} else
+		{
+			///need to transform normal into worldspace
+			hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+		}
+
+		btScalar dotUp = m_up.dot(hitNormalWorld);
+		if (dotUp < m_minSlopeDot) {
+			return btScalar(1.0);
+		}
+
+		return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+	}
+protected:
+	btCollisionObject* m_me;
+	const btVector3 m_up;
+	btScalar m_minSlopeDot;
+};
+
+/*
+ * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
+ *
+ * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
+ */
+btVector3 btKinematicCharacterController::computeReflectionDirection (const btVector3& direction, const btVector3& normal)
+{
+	return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
+}
+
+/*
+ * Returns the portion of 'direction' that is parallel to 'normal'
+ */
+btVector3 btKinematicCharacterController::parallelComponent (const btVector3& direction, const btVector3& normal)
+{
+	btScalar magnitude = direction.dot(normal);
+	return normal * magnitude;
+}
+
+/*
+ * Returns the portion of 'direction' that is perpindicular to 'normal'
+ */
+btVector3 btKinematicCharacterController::perpindicularComponent (const btVector3& direction, const btVector3& normal)
+{
+	return direction - parallelComponent(direction, normal);
+}
+
+btKinematicCharacterController::btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis)
+{
+	m_upAxis = upAxis;
+	m_addedMargin = 0.02;
+	m_walkDirection.setValue(0,0,0);
+	m_useGhostObjectSweepTest = true;
+	m_ghostObject = ghostObject;
+	m_stepHeight = stepHeight;
+	m_turnAngle = btScalar(0.0);
+	m_convexShape=convexShape;	
+	m_useWalkDirection = true;	// use walk direction by default, legacy behavior
+	m_velocityTimeInterval = 0.0;
+	m_verticalVelocity = 0.0;
+	m_verticalOffset = 0.0;
+	m_gravity = 9.8 * 3 ; // 3G acceleration.
+	m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
+	m_jumpSpeed = 10.0; // ?
+	m_wasOnGround = false;
+	m_wasJumping = false;
+	setMaxSlope(btRadians(45.0));
+}
+
+btKinematicCharacterController::~btKinematicCharacterController ()
+{
+}
+
+btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
+{
+	return m_ghostObject;
+}
+
+bool btKinematicCharacterController::recoverFromPenetration ( btCollisionWorld* collisionWorld)
+{
+
+	bool penetration = false;
+
+	collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
+
+	m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+	
+	btScalar maxPen = btScalar(0.0);
+	for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
+	{
+		m_manifoldArray.resize(0);
+
+		btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
+		
+		if (collisionPair->m_algorithm)
+			collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
+
+		
+		for (int j=0;j<m_manifoldArray.size();j++)
+		{
+			btPersistentManifold* manifold = m_manifoldArray[j];
+			btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
+			for (int p=0;p<manifold->getNumContacts();p++)
+			{
+				const btManifoldPoint&pt = manifold->getContactPoint(p);
+
+				btScalar dist = pt.getDistance();
+
+				if (dist < 0.0)
+				{
+					if (dist < maxPen)
+					{
+						maxPen = dist;
+						m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
+
+					}
+					m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
+					penetration = true;
+				} else {
+					//printf("touching %f\n", dist);
+				}
+			}
+			
+			//manifold->clearManifold();
+		}
+	}
+	btTransform newTrans = m_ghostObject->getWorldTransform();
+	newTrans.setOrigin(m_currentPosition);
+	m_ghostObject->setWorldTransform(newTrans);
+//	printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
+	return penetration;
+}
+
+void btKinematicCharacterController::stepUp ( btCollisionWorld* world)
+{
+	// phase 1: up
+	btTransform start, end;
+	m_targetPosition = m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_stepHeight + (m_verticalOffset > 0.f?m_verticalOffset:0.f));
+
+	start.setIdentity ();
+	end.setIdentity ();
+
+	/* FIXME: Handle penetration properly */
+	start.setOrigin (m_currentPosition + getUpAxisDirections()[m_upAxis] * (m_convexShape->getMargin() + m_addedMargin));
+	end.setOrigin (m_targetPosition);
+
+	btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, -getUpAxisDirections()[m_upAxis], btScalar(0.7071));
+	callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+	callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+	
+	if (m_useGhostObjectSweepTest)
+	{
+		m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
+	}
+	else
+	{
+		world->convexSweepTest (m_convexShape, start, end, callback);
+	}
+	
+	if (callback.hasHit())
+	{
+		// Only modify the position if the hit was a slope and not a wall or ceiling.
+		if(callback.m_hitNormalWorld.dot(getUpAxisDirections()[m_upAxis]) > 0.0)
+		{
+			// we moved up only a fraction of the step height
+			m_currentStepOffset = m_stepHeight * callback.m_closestHitFraction;
+			m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+		}
+		m_verticalVelocity = 0.0;
+		m_verticalOffset = 0.0;
+	} else {
+		m_currentStepOffset = m_stepHeight;
+		m_currentPosition = m_targetPosition;
+	}
+}
+
+void btKinematicCharacterController::updateTargetPositionBasedOnCollision (const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
+{
+	btVector3 movementDirection = m_targetPosition - m_currentPosition;
+	btScalar movementLength = movementDirection.length();
+	if (movementLength>SIMD_EPSILON)
+	{
+		movementDirection.normalize();
+
+		btVector3 reflectDir = computeReflectionDirection (movementDirection, hitNormal);
+		reflectDir.normalize();
+
+		btVector3 parallelDir, perpindicularDir;
+
+		parallelDir = parallelComponent (reflectDir, hitNormal);
+		perpindicularDir = perpindicularComponent (reflectDir, hitNormal);
+
+		m_targetPosition = m_currentPosition;
+		if (0)//tangentMag != 0.0)
+		{
+			btVector3 parComponent = parallelDir * btScalar (tangentMag*movementLength);
+//			printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
+			m_targetPosition +=  parComponent;
+		}
+
+		if (normalMag != 0.0)
+		{
+			btVector3 perpComponent = perpindicularDir * btScalar (normalMag*movementLength);
+//			printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
+			m_targetPosition += perpComponent;
+		}
+	} else
+	{
+//		printf("movementLength don't normalize a zero vector\n");
+	}
+}
+
+void btKinematicCharacterController::stepForwardAndStrafe ( btCollisionWorld* collisionWorld, const btVector3& walkMove)
+{
+	// printf("m_normalizedDirection=%f,%f,%f\n",
+	// 	m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
+	// phase 2: forward and strafe
+	btTransform start, end;
+	m_targetPosition = m_currentPosition + walkMove;
+
+	start.setIdentity ();
+	end.setIdentity ();
+	
+	btScalar fraction = 1.0;
+	btScalar distance2 = (m_currentPosition-m_targetPosition).length2();
+//	printf("distance2=%f\n",distance2);
+
+	if (m_touchingContact)
+	{
+		if (m_normalizedDirection.dot(m_touchingNormal) > btScalar(0.0))
+		{
+			updateTargetPositionBasedOnCollision (m_touchingNormal);
+		}
+	}
+
+	int maxIter = 10;
+
+	while (fraction > btScalar(0.01) && maxIter-- > 0)
+	{
+		start.setOrigin (m_currentPosition);
+		end.setOrigin (m_targetPosition);
+		btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
+
+		btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, sweepDirNegative, btScalar(0.0));
+		callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+		callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+
+
+		btScalar margin = m_convexShape->getMargin();
+		m_convexShape->setMargin(margin + m_addedMargin);
+
+
+		if (m_useGhostObjectSweepTest)
+		{
+			m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+		} else
+		{
+			collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+		}
+		
+		m_convexShape->setMargin(margin);
+
+		
+		fraction -= callback.m_closestHitFraction;
+
+		if (callback.hasHit())
+		{	
+			// we moved only a fraction
+			btScalar hitDistance;
+			hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
+
+//			m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+
+			updateTargetPositionBasedOnCollision (callback.m_hitNormalWorld);
+			btVector3 currentDir = m_targetPosition - m_currentPosition;
+			distance2 = currentDir.length2();
+			if (distance2 > SIMD_EPSILON)
+			{
+				currentDir.normalize();
+				/* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
+				if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
+				{
+					break;
+				}
+			} else
+			{
+//				printf("currentDir: don't normalize a zero vector\n");
+				break;
+			}
+
+		} else {
+			// we moved whole way
+			m_currentPosition = m_targetPosition;
+		}
+
+	//	if (callback.m_closestHitFraction == 0.f)
+	//		break;
+
+	}
+}
+
+void btKinematicCharacterController::stepDown ( btCollisionWorld* collisionWorld, btScalar dt)
+{
+	btTransform start, end;
+
+	// phase 3: down
+	/*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
+	btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + additionalDownStep);
+	btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
+	btVector3 gravity_drop = getUpAxisDirections()[m_upAxis] * downVelocity; 
+	m_targetPosition -= (step_drop + gravity_drop);*/
+
+	btScalar downVelocity = (m_verticalVelocity<0.f?-m_verticalVelocity:0.f) * dt;
+	if(downVelocity > 0.0 && downVelocity < m_stepHeight
+		&& (m_wasOnGround || !m_wasJumping))
+	{
+		downVelocity = m_stepHeight;
+	}
+
+	btVector3 step_drop = getUpAxisDirections()[m_upAxis] * (m_currentStepOffset + downVelocity);
+	m_targetPosition -= step_drop;
+
+	start.setIdentity ();
+	end.setIdentity ();
+
+	start.setOrigin (m_currentPosition);
+	end.setOrigin (m_targetPosition);
+
+	btKinematicClosestNotMeConvexResultCallback callback (m_ghostObject, getUpAxisDirections()[m_upAxis], m_maxSlopeCosine);
+	callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
+	callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
+	
+	if (m_useGhostObjectSweepTest)
+	{
+		m_ghostObject->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+	} else
+	{
+		collisionWorld->convexSweepTest (m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
+	}
+
+	if (callback.hasHit())
+	{
+		// we dropped a fraction of the height -> hit floor
+		m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
+		m_verticalVelocity = 0.0;
+		m_verticalOffset = 0.0;
+		m_wasJumping = false;
+	} else {
+		// we dropped the full height
+		
+		m_currentPosition = m_targetPosition;
+	}
+}
+
+
+
+void btKinematicCharacterController::setWalkDirection
+(
+const btVector3& walkDirection
+)
+{
+	m_useWalkDirection = true;
+	m_walkDirection = walkDirection;
+	m_normalizedDirection = getNormalizedVector(m_walkDirection);
+}
+
+
+
+void btKinematicCharacterController::setVelocityForTimeInterval
+(
+const btVector3& velocity,
+btScalar timeInterval
+)
+{
+//	printf("setVelocity!\n");
+//	printf("  interval: %f\n", timeInterval);
+//	printf("  velocity: (%f, %f, %f)\n",
+//		 velocity.x(), velocity.y(), velocity.z());
+
+	m_useWalkDirection = false;
+	m_walkDirection = velocity;
+	m_normalizedDirection = getNormalizedVector(m_walkDirection);
+	m_velocityTimeInterval = timeInterval;
+}
+
+
+
+void btKinematicCharacterController::reset ()
+{
+}
+
+void btKinematicCharacterController::warp (const btVector3& origin)
+{
+	btTransform xform;
+	xform.setIdentity();
+	xform.setOrigin (origin);
+	m_ghostObject->setWorldTransform (xform);
+}
+
+
+void btKinematicCharacterController::preStep (  btCollisionWorld* collisionWorld)
+{
+	
+	int numPenetrationLoops = 0;
+	m_touchingContact = false;
+	while (recoverFromPenetration (collisionWorld))
+	{
+		numPenetrationLoops++;
+		m_touchingContact = true;
+		if (numPenetrationLoops > 4)
+		{
+			//printf("character could not recover from penetration = %d\n", numPenetrationLoops);
+			break;
+		}
+	}
+
+	m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
+	m_targetPosition = m_currentPosition;
+//	printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
+
+	
+}
+
+#include <stdio.h>
+
+void btKinematicCharacterController::playerStep (  btCollisionWorld* collisionWorld, btScalar dt)
+{
+//	printf("playerStep(): ");
+//	printf("  dt = %f", dt);
+
+	// quick check...
+	if (!m_useWalkDirection && m_velocityTimeInterval <= 0.0) {
+//		printf("\n");
+		return;		// no motion
+	}
+
+	m_wasOnGround = onGround();
+
+	// Update fall velocity.
+	m_verticalVelocity -= m_gravity * dt;
+	if(m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
+	{
+		m_verticalVelocity = m_jumpSpeed;
+	}
+	if(m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
+	{
+		m_verticalVelocity = -btFabs(m_fallSpeed);
+	}
+	m_verticalOffset = m_verticalVelocity * dt;
+
+
+	btTransform xform;
+	xform = m_ghostObject->getWorldTransform ();
+
+//	printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
+//	printf("walkSpeed=%f\n",walkSpeed);
+
+	stepUp (collisionWorld);
+	if (m_useWalkDirection) {
+		stepForwardAndStrafe (collisionWorld, m_walkDirection);
+	} else {
+		//printf("  time: %f", m_velocityTimeInterval);
+		// still have some time left for moving!
+		btScalar dtMoving =
+			(dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
+		m_velocityTimeInterval -= dt;
+
+		// how far will we move while we are moving?
+		btVector3 move = m_walkDirection * dtMoving;
+
+		//printf("  dtMoving: %f", dtMoving);
+
+		// okay, step
+		stepForwardAndStrafe(collisionWorld, move);
+	}
+	stepDown (collisionWorld, dt);
+
+	// printf("\n");
+
+	xform.setOrigin (m_currentPosition);
+	m_ghostObject->setWorldTransform (xform);
+}
+
+void btKinematicCharacterController::setFallSpeed (btScalar fallSpeed)
+{
+	m_fallSpeed = fallSpeed;
+}
+
+void btKinematicCharacterController::setJumpSpeed (btScalar jumpSpeed)
+{
+	m_jumpSpeed = jumpSpeed;
+}
+
+void btKinematicCharacterController::setMaxJumpHeight (btScalar maxJumpHeight)
+{
+	m_maxJumpHeight = maxJumpHeight;
+}
+
+bool btKinematicCharacterController::canJump () const
+{
+	return onGround();
+}
+
+void btKinematicCharacterController::jump ()
+{
+	if (!canJump())
+		return;
+
+	m_verticalVelocity = m_jumpSpeed;
+	m_wasJumping = true;
+
+#if 0
+	currently no jumping.
+	btTransform xform;
+	m_rigidBody->getMotionState()->getWorldTransform (xform);
+	btVector3 up = xform.getBasis()[1];
+	up.normalize ();
+	btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
+	m_rigidBody->applyCentralImpulse (up * magnitude);
+#endif
+}
+
+void btKinematicCharacterController::setGravity(btScalar gravity)
+{
+	m_gravity = gravity;
+}
+
+btScalar btKinematicCharacterController::getGravity() const
+{
+	return m_gravity;
+}
+
+void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians)
+{
+	m_maxSlopeRadians = slopeRadians;
+	m_maxSlopeCosine = btCos(slopeRadians);
+}
+
+btScalar btKinematicCharacterController::getMaxSlope() const
+{
+	return m_maxSlopeRadians;
+}
+
+bool btKinematicCharacterController::onGround () const
+{
+	return m_verticalVelocity == 0.0 && m_verticalOffset == 0.0;
+}
+
+
+btVector3* btKinematicCharacterController::getUpAxisDirections()
+{
+	static btVector3 sUpAxisDirection[3] = { btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f) };
+	
+	return sUpAxisDirection;
+}
+
+void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
+{
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Character/btKinematicCharacterController.h	(revision 11817)
@@ -0,0 +1,162 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H
+#define BT_KINEMATIC_CHARACTER_CONTROLLER_H
+
+#include "LinearMath/btVector3.h"
+
+#include "btCharacterControllerInterface.h"
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+
+class btCollisionShape;
+class btRigidBody;
+class btCollisionWorld;
+class btCollisionDispatcher;
+class btPairCachingGhostObject;
+
+///btKinematicCharacterController is an object that supports a sliding motion in a world.
+///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
+///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
+class btKinematicCharacterController : public btCharacterControllerInterface
+{
+protected:
+
+	btScalar m_halfHeight;
+	
+	btPairCachingGhostObject* m_ghostObject;
+	btConvexShape*	m_convexShape;//is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
+	
+	btScalar m_verticalVelocity;
+	btScalar m_verticalOffset;
+	btScalar m_fallSpeed;
+	btScalar m_jumpSpeed;
+	btScalar m_maxJumpHeight;
+	btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
+	btScalar m_maxSlopeCosine;  // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
+	btScalar m_gravity;
+
+	btScalar m_turnAngle;
+	
+	btScalar m_stepHeight;
+
+	btScalar	m_addedMargin;//@todo: remove this and fix the code
+
+	///this is the desired walk direction, set by the user
+	btVector3	m_walkDirection;
+	btVector3	m_normalizedDirection;
+
+	//some internal variables
+	btVector3 m_currentPosition;
+	btScalar  m_currentStepOffset;
+	btVector3 m_targetPosition;
+
+	///keep track of the contact manifolds
+	btManifoldArray	m_manifoldArray;
+
+	bool m_touchingContact;
+	btVector3 m_touchingNormal;
+
+	bool  m_wasOnGround;
+	bool  m_wasJumping;
+	bool	m_useGhostObjectSweepTest;
+	bool	m_useWalkDirection;
+	btScalar	m_velocityTimeInterval;
+	int m_upAxis;
+
+	static btVector3* getUpAxisDirections();
+
+	btVector3 computeReflectionDirection (const btVector3& direction, const btVector3& normal);
+	btVector3 parallelComponent (const btVector3& direction, const btVector3& normal);
+	btVector3 perpindicularComponent (const btVector3& direction, const btVector3& normal);
+
+	bool recoverFromPenetration ( btCollisionWorld* collisionWorld);
+	void stepUp (btCollisionWorld* collisionWorld);
+	void updateTargetPositionBasedOnCollision (const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
+	void stepForwardAndStrafe (btCollisionWorld* collisionWorld, const btVector3& walkMove);
+	void stepDown (btCollisionWorld* collisionWorld, btScalar dt);
+public:
+	btKinematicCharacterController (btPairCachingGhostObject* ghostObject,btConvexShape* convexShape,btScalar stepHeight, int upAxis = 1);
+	~btKinematicCharacterController ();
+	
+
+	///btActionInterface interface
+	virtual void updateAction( btCollisionWorld* collisionWorld,btScalar deltaTime)
+	{
+		preStep ( collisionWorld);
+		playerStep (collisionWorld, deltaTime);
+	}
+	
+	///btActionInterface interface
+	void	debugDraw(btIDebugDraw* debugDrawer);
+
+	void setUpAxis (int axis)
+	{
+		if (axis < 0)
+			axis = 0;
+		if (axis > 2)
+			axis = 2;
+		m_upAxis = axis;
+	}
+
+	/// This should probably be called setPositionIncrementPerSimulatorStep.
+	/// This is neither a direction nor a velocity, but the amount to
+	///	increment the position each simulation iteration, regardless
+	///	of dt.
+	/// This call will reset any velocity set by setVelocityForTimeInterval().
+	virtual void	setWalkDirection(const btVector3& walkDirection);
+
+	/// Caller provides a velocity with which the character should move for
+	///	the given time period.  After the time period, velocity is reset
+	///	to zero.
+	/// This call will reset any walk direction set by setWalkDirection().
+	/// Negative time intervals will result in no motion.
+	virtual void setVelocityForTimeInterval(const btVector3& velocity,
+				btScalar timeInterval);
+
+	void reset ();
+	void warp (const btVector3& origin);
+
+	void preStep (  btCollisionWorld* collisionWorld);
+	void playerStep ( btCollisionWorld* collisionWorld, btScalar dt);
+
+	void setFallSpeed (btScalar fallSpeed);
+	void setJumpSpeed (btScalar jumpSpeed);
+	void setMaxJumpHeight (btScalar maxJumpHeight);
+	bool canJump () const;
+
+	void jump ();
+
+	void setGravity(btScalar gravity);
+	btScalar getGravity() const;
+
+	/// The max slope determines the maximum angle that the controller can walk up.
+	/// The slope angle is measured in radians.
+	void setMaxSlope(btScalar slopeRadians);
+	btScalar getMaxSlope() const;
+
+	btPairCachingGhostObject* getGhostObject();
+	void	setUseGhostSweepTest(bool useGhostObjectSweepTest)
+	{
+		m_useGhostObjectSweepTest = useGhostObjectSweepTest;
+	}
+
+	bool onGround () const;
+};
+
+#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp	(revision 11817)
@@ -0,0 +1,1127 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Written by: Marcus Hennix
+*/
+
+
+#include "btConeTwistConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
+#include <new>
+
+
+
+//#define CONETWIST_USE_OBSOLETE_SOLVER true
+#define CONETWIST_USE_OBSOLETE_SOLVER false
+#define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
+
+
+SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
+{
+	btVector3 vec = axis * invInertiaWorld;
+	return axis.dot(vec);
+}
+
+
+
+
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB, 
+											 const btTransform& rbAFrame,const btTransform& rbBFrame)
+											 :btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
+											 m_angularOnly(false),
+											 m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+{
+	init();
+}
+
+btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame)
+											:btTypedConstraint(CONETWIST_CONSTRAINT_TYPE,rbA),m_rbAFrame(rbAFrame),
+											 m_angularOnly(false),
+											 m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
+{
+	m_rbBFrame = m_rbAFrame;
+	init();	
+}
+
+
+void btConeTwistConstraint::init()
+{
+	m_angularOnly = false;
+	m_solveTwistLimit = false;
+	m_solveSwingLimit = false;
+	m_bMotorEnabled = false;
+	m_maxMotorImpulse = btScalar(-1);
+
+	setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
+	m_damping = btScalar(0.01);
+	m_fixThresh = CONETWIST_DEF_FIX_THRESH;
+	m_flags = 0;
+	m_linCFM = btScalar(0.f);
+	m_linERP = btScalar(0.7f);
+	m_angCFM = btScalar(0.f);
+}
+
+
+void btConeTwistConstraint::getInfo1 (btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	} 
+	else
+	{
+		info->m_numConstraintRows = 3;
+		info->nub = 3;
+		calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+		if(m_solveSwingLimit)
+		{
+			info->m_numConstraintRows++;
+			info->nub--;
+			if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+			{
+				info->m_numConstraintRows++;
+				info->nub--;
+			}
+		}
+		if(m_solveTwistLimit)
+		{
+			info->m_numConstraintRows++;
+			info->nub--;
+		}
+	}
+}
+
+void btConeTwistConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+{
+	//always reserve 6 rows: object transform is not available on SPU
+	info->m_numConstraintRows = 6;
+	info->nub = 0;
+		
+}
+	
+
+void btConeTwistConstraint::getInfo2 (btConstraintInfo2* info)
+{
+	getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+}
+
+void btConeTwistConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
+{
+	calcAngleInfo2(transA,transB,invInertiaWorldA,invInertiaWorldB);
+	
+	btAssert(!m_useSolveConstraintObsolete);
+    // set jacobian
+    info->m_J1linearAxis[0] = 1;
+    info->m_J1linearAxis[info->rowskip+1] = 1;
+    info->m_J1linearAxis[2*info->rowskip+2] = 1;
+	btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
+	{
+		btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+		btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
+		btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip);
+		btVector3 a1neg = -a1;
+		a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+	}
+	btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
+	{
+		btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+		btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
+		btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
+		a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+	}
+    // set right hand side
+	btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp;
+    btScalar k = info->fps * linERP;
+    int j;
+	for (j=0; j<3; j++)
+    {
+        info->m_constraintError[j*info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
+		info->m_lowerLimit[j*info->rowskip] = -SIMD_INFINITY;
+		info->m_upperLimit[j*info->rowskip] = SIMD_INFINITY;
+		if(m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
+		{
+			info->cfm[j*info->rowskip] = m_linCFM;
+		}
+    }
+	int row = 3;
+    int srow = row * info->rowskip;
+	btVector3 ax1;
+	// angular limits
+	if(m_solveSwingLimit)
+	{
+		btScalar *J1 = info->m_J1angularAxis;
+		btScalar *J2 = info->m_J2angularAxis;
+		if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+		{
+			btTransform trA = transA*m_rbAFrame;
+			btVector3 p = trA.getBasis().getColumn(1);
+			btVector3 q = trA.getBasis().getColumn(2);
+			int srow1 = srow + info->rowskip;
+			J1[srow+0] = p[0];
+			J1[srow+1] = p[1];
+			J1[srow+2] = p[2];
+			J1[srow1+0] = q[0];
+			J1[srow1+1] = q[1];
+			J1[srow1+2] = q[2];
+			J2[srow+0] = -p[0];
+			J2[srow+1] = -p[1];
+			J2[srow+2] = -p[2];
+			J2[srow1+0] = -q[0];
+			J2[srow1+1] = -q[1];
+			J2[srow1+2] = -q[2];
+			btScalar fact = info->fps * m_relaxationFactor;
+			info->m_constraintError[srow] =   fact * m_swingAxis.dot(p);
+			info->m_constraintError[srow1] =  fact * m_swingAxis.dot(q);
+			info->m_lowerLimit[srow] = -SIMD_INFINITY;
+			info->m_upperLimit[srow] = SIMD_INFINITY;
+			info->m_lowerLimit[srow1] = -SIMD_INFINITY;
+			info->m_upperLimit[srow1] = SIMD_INFINITY;
+			srow = srow1 + info->rowskip;
+		}
+		else
+		{
+			ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor;
+			J1[srow+0] = ax1[0];
+			J1[srow+1] = ax1[1];
+			J1[srow+2] = ax1[2];
+			J2[srow+0] = -ax1[0];
+			J2[srow+1] = -ax1[1];
+			J2[srow+2] = -ax1[2];
+			btScalar k = info->fps * m_biasFactor;
+
+			info->m_constraintError[srow] = k * m_swingCorrection;
+			if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+			{
+				info->cfm[srow] = m_angCFM;
+			}
+			// m_swingCorrection is always positive or 0
+			info->m_lowerLimit[srow] = 0;
+			info->m_upperLimit[srow] = SIMD_INFINITY;
+			srow += info->rowskip;
+		}
+	}
+	if(m_solveTwistLimit)
+	{
+		ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor;
+		btScalar *J1 = info->m_J1angularAxis;
+		btScalar *J2 = info->m_J2angularAxis;
+		J1[srow+0] = ax1[0];
+		J1[srow+1] = ax1[1];
+		J1[srow+2] = ax1[2];
+		J2[srow+0] = -ax1[0];
+		J2[srow+1] = -ax1[1];
+		J2[srow+2] = -ax1[2];
+		btScalar k = info->fps * m_biasFactor;
+		info->m_constraintError[srow] = k * m_twistCorrection;
+		if(m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
+		{
+			info->cfm[srow] = m_angCFM;
+		}
+		if(m_twistSpan > 0.0f)
+		{
+
+			if(m_twistCorrection > 0.0f)
+			{
+				info->m_lowerLimit[srow] = 0;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			} 
+			else
+			{
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = 0;
+			} 
+		}
+		else
+		{
+			info->m_lowerLimit[srow] = -SIMD_INFINITY;
+			info->m_upperLimit[srow] = SIMD_INFINITY;
+		}
+		srow += info->rowskip;
+	}
+}
+	
+
+
+void	btConeTwistConstraint::buildJacobian()
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		m_appliedImpulse = btScalar(0.);
+		m_accTwistLimitImpulse = btScalar(0.);
+		m_accSwingLimitImpulse = btScalar(0.);
+		m_accMotorImpulse = btVector3(0.,0.,0.);
+
+		if (!m_angularOnly)
+		{
+			btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
+			btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+			btVector3 relPos = pivotBInW - pivotAInW;
+
+			btVector3 normal[3];
+			if (relPos.length2() > SIMD_EPSILON)
+			{
+				normal[0] = relPos.normalized();
+			}
+			else
+			{
+				normal[0].setValue(btScalar(1.0),0,0);
+			}
+
+			btPlaneSpace1(normal[0], normal[1], normal[2]);
+
+			for (int i=0;i<3;i++)
+			{
+				new (&m_jac[i]) btJacobianEntry(
+				m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+				m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+				pivotAInW - m_rbA.getCenterOfMassPosition(),
+				pivotBInW - m_rbB.getCenterOfMassPosition(),
+				normal[i],
+				m_rbA.getInvInertiaDiagLocal(),
+				m_rbA.getInvMass(),
+				m_rbB.getInvInertiaDiagLocal(),
+				m_rbB.getInvMass());
+			}
+		}
+
+		calcAngleInfo2(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getInvInertiaTensorWorld(),m_rbB.getInvInertiaTensorWorld());
+	}
+}
+
+
+
+void	btConeTwistConstraint::solveConstraintObsolete(btRigidBody& bodyA,btRigidBody& bodyB,btScalar	timeStep)
+{
+	#ifndef __SPU__
+	if (m_useSolveConstraintObsolete)
+	{
+		btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
+		btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+
+		btScalar tau = btScalar(0.3);
+
+		//linear part
+		if (!m_angularOnly)
+		{
+			btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition(); 
+			btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+
+			btVector3 vel1;
+			bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1);
+			btVector3 vel2;
+			bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2);
+			btVector3 vel = vel1 - vel2;
+
+			for (int i=0;i<3;i++)
+			{		
+				const btVector3& normal = m_jac[i].m_linearJointAxis;
+				btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
+
+				btScalar rel_vel;
+				rel_vel = normal.dot(vel);
+				//positional error (zeroth order error)
+				btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
+				btScalar impulse = depth*tau/timeStep  * jacDiagABInv -  rel_vel * jacDiagABInv;
+				m_appliedImpulse += impulse;
+				
+				btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
+				btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
+				bodyA.internalApplyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse);
+				bodyB.internalApplyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse);
+		
+			}
+		}
+
+		// apply motor
+		if (m_bMotorEnabled)
+		{
+			// compute current and predicted transforms
+			btTransform trACur = m_rbA.getCenterOfMassTransform();
+			btTransform trBCur = m_rbB.getCenterOfMassTransform();
+			btVector3 omegaA; bodyA.internalGetAngularVelocity(omegaA);
+			btVector3 omegaB; bodyB.internalGetAngularVelocity(omegaB);
+			btTransform trAPred; trAPred.setIdentity(); 
+			btVector3 zerovec(0,0,0);
+			btTransformUtil::integrateTransform(
+				trACur, zerovec, omegaA, timeStep, trAPred);
+			btTransform trBPred; trBPred.setIdentity(); 
+			btTransformUtil::integrateTransform(
+				trBCur, zerovec, omegaB, timeStep, trBPred);
+
+			// compute desired transforms in world
+			btTransform trPose(m_qTarget);
+			btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse();
+			btTransform trADes = trBPred * trABDes;
+			btTransform trBDes = trAPred * trABDes.inverse();
+
+			// compute desired omegas in world
+			btVector3 omegaADes, omegaBDes;
+			
+			btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes);
+			btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes);
+
+			// compute delta omegas
+			btVector3 dOmegaA = omegaADes - omegaA;
+			btVector3 dOmegaB = omegaBDes - omegaB;
+
+			// compute weighted avg axis of dOmega (weighting based on inertias)
+			btVector3 axisA, axisB;
+			btScalar kAxisAInv = 0, kAxisBInv = 0;
+
+			if (dOmegaA.length2() > SIMD_EPSILON)
+			{
+				axisA = dOmegaA.normalized();
+				kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA);
+			}
+
+			if (dOmegaB.length2() > SIMD_EPSILON)
+			{
+				axisB = dOmegaB.normalized();
+				kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB);
+			}
+
+			btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB;
+
+			static bool bDoTorque = true;
+			if (bDoTorque && avgAxis.length2() > SIMD_EPSILON)
+			{
+				avgAxis.normalize();
+				kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis);
+				kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis);
+				btScalar kInvCombined = kAxisAInv + kAxisBInv;
+
+				btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) /
+									(kInvCombined * kInvCombined);
+
+				if (m_maxMotorImpulse >= 0)
+				{
+					btScalar fMaxImpulse = m_maxMotorImpulse;
+					if (m_bNormalizedMotorStrength)
+						fMaxImpulse = fMaxImpulse/kAxisAInv;
+
+					btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse;
+					btScalar  newUnclampedMag = newUnclampedAccImpulse.length();
+					if (newUnclampedMag > fMaxImpulse)
+					{
+						newUnclampedAccImpulse.normalize();
+						newUnclampedAccImpulse *= fMaxImpulse;
+						impulse = newUnclampedAccImpulse - m_accMotorImpulse;
+					}
+					m_accMotorImpulse += impulse;
+				}
+
+				btScalar  impulseMag  = impulse.length();
+				btVector3 impulseAxis =  impulse / impulseMag;
+
+				bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag);
+				bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag);
+
+			}
+		}
+		else if (m_damping > SIMD_EPSILON) // no motor: do a little damping
+		{
+			btVector3 angVelA; bodyA.internalGetAngularVelocity(angVelA);
+			btVector3 angVelB; bodyB.internalGetAngularVelocity(angVelB);
+			btVector3 relVel = angVelB - angVelA;
+			if (relVel.length2() > SIMD_EPSILON)
+			{
+				btVector3 relVelAxis = relVel.normalized();
+				btScalar m_kDamping =  btScalar(1.) /
+					(getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
+					 getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
+				btVector3 impulse = m_damping * m_kDamping * relVel;
+
+				btScalar  impulseMag  = impulse.length();
+				btVector3 impulseAxis = impulse / impulseMag;
+				bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*impulseAxis, impulseMag);
+				bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*impulseAxis, -impulseMag);
+			}
+		}
+
+		// joint limits
+		{
+			///solve angular part
+			btVector3 angVelA;
+			bodyA.internalGetAngularVelocity(angVelA);
+			btVector3 angVelB;
+			bodyB.internalGetAngularVelocity(angVelB);
+
+			// solve swing limit
+			if (m_solveSwingLimit)
+			{
+				btScalar amplitude = m_swingLimitRatio * m_swingCorrection*m_biasFactor/timeStep;
+				btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis);
+				if (relSwingVel > 0)
+					amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor;
+				btScalar impulseMag = amplitude * m_kSwing;
+
+				// Clamp the accumulated impulse
+				btScalar temp = m_accSwingLimitImpulse;
+				m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0) );
+				impulseMag = m_accSwingLimitImpulse - temp;
+
+				btVector3 impulse = m_swingAxis * impulseMag;
+
+				// don't let cone response affect twist
+				// (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit)
+				{
+					btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA;
+					btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple;
+					impulse = impulseNoTwistCouple;
+				}
+
+				impulseMag = impulse.length();
+				btVector3 noTwistSwingAxis = impulse / impulseMag;
+
+				bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*noTwistSwingAxis, impulseMag);
+				bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*noTwistSwingAxis, -impulseMag);
+			}
+
+
+			// solve twist limit
+			if (m_solveTwistLimit)
+			{
+				btScalar amplitude = m_twistLimitRatio * m_twistCorrection*m_biasFactor/timeStep;
+				btScalar relTwistVel = (angVelB - angVelA).dot( m_twistAxis );
+				if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important)
+					amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor;
+				btScalar impulseMag = amplitude * m_kTwist;
+
+				// Clamp the accumulated impulse
+				btScalar temp = m_accTwistLimitImpulse;
+				m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0) );
+				impulseMag = m_accTwistLimitImpulse - temp;
+
+				btVector3 impulse = m_twistAxis * impulseMag;
+
+				bodyA.internalApplyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*m_twistAxis,impulseMag);
+				bodyB.internalApplyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*m_twistAxis,-impulseMag);
+			}		
+		}
+	}
+#else
+btAssert(0);
+#endif //__SPU__
+}
+
+
+
+
+void	btConeTwistConstraint::updateRHS(btScalar	timeStep)
+{
+	(void)timeStep;
+
+}
+
+
+#ifndef __SPU__
+void btConeTwistConstraint::calcAngleInfo()
+{
+	m_swingCorrection = btScalar(0.);
+	m_twistLimitSign = btScalar(0.);
+	m_solveTwistLimit = false;
+	m_solveSwingLimit = false;
+
+	btVector3 b1Axis1,b1Axis2,b1Axis3;
+	btVector3 b2Axis1,b2Axis2;
+
+	b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0);
+	b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0);
+
+	btScalar swing1=btScalar(0.),swing2 = btScalar(0.);
+
+	btScalar swx=btScalar(0.),swy = btScalar(0.);
+	btScalar thresh = btScalar(10.);
+	btScalar fact;
+
+	// Get Frame into world space
+	if (m_swingSpan1 >= btScalar(0.05f))
+	{
+		b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1);
+		swx = b2Axis1.dot(b1Axis1);
+		swy = b2Axis1.dot(b1Axis2);
+		swing1  = btAtan2Fast(swy, swx);
+		fact = (swy*swy + swx*swx) * thresh * thresh;
+		fact = fact / (fact + btScalar(1.0));
+		swing1 *= fact; 
+	}
+
+	if (m_swingSpan2 >= btScalar(0.05f))
+	{
+		b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);			
+		swx = b2Axis1.dot(b1Axis1);
+		swy = b2Axis1.dot(b1Axis3);
+		swing2  = btAtan2Fast(swy, swx);
+		fact = (swy*swy + swx*swx) * thresh * thresh;
+		fact = fact / (fact + btScalar(1.0));
+		swing2 *= fact; 
+	}
+
+	btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1);		
+	btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2*m_swingSpan2);	
+	btScalar EllipseAngle = btFabs(swing1*swing1)* RMaxAngle1Sq + btFabs(swing2*swing2) * RMaxAngle2Sq;
+
+	if (EllipseAngle > 1.0f)
+	{
+		m_swingCorrection = EllipseAngle-1.0f;
+		m_solveSwingLimit = true;
+		// Calculate necessary axis & factors
+		m_swingAxis = b2Axis1.cross(b1Axis2* b2Axis1.dot(b1Axis2) + b1Axis3* b2Axis1.dot(b1Axis3));
+		m_swingAxis.normalize();
+		btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
+		m_swingAxis *= swingAxisSign;
+	}
+
+	// Twist limits
+	if (m_twistSpan >= btScalar(0.))
+	{
+		btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1);
+		btQuaternion rotationArc = shortestArcQuat(b2Axis1,b1Axis1);
+		btVector3 TwistRef = quatRotate(rotationArc,b2Axis2); 
+		btScalar twist = btAtan2Fast( TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2) );
+		m_twistAngle = twist;
+
+//		btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
+		btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.);
+		if (twist <= -m_twistSpan*lockedFreeFactor)
+		{
+			m_twistCorrection = -(twist + m_twistSpan);
+			m_solveTwistLimit = true;
+			m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
+			m_twistAxis.normalize();
+			m_twistAxis *= -1.0f;
+		}
+		else if (twist >  m_twistSpan*lockedFreeFactor)
+		{
+			m_twistCorrection = (twist - m_twistSpan);
+			m_solveTwistLimit = true;
+			m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
+			m_twistAxis.normalize();
+		}
+	}
+}
+#endif //__SPU__
+
+static btVector3 vTwist(1,0,0); // twist axis in constraint's space
+
+
+
+void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB)
+{
+	m_swingCorrection = btScalar(0.);
+	m_twistLimitSign = btScalar(0.);
+	m_solveTwistLimit = false;
+	m_solveSwingLimit = false;
+	// compute rotation of A wrt B (in constraint space)
+	if (m_bMotorEnabled && (!m_useSolveConstraintObsolete))
+	{	// it is assumed that setMotorTarget() was alredy called 
+		// and motor target m_qTarget is within constraint limits
+		// TODO : split rotation to pure swing and pure twist
+		// compute desired transforms in world
+		btTransform trPose(m_qTarget);
+		btTransform trA = transA * m_rbAFrame;
+		btTransform trB = transB * m_rbBFrame;
+		btTransform trDeltaAB = trB * trPose * trA.inverse();
+		btQuaternion qDeltaAB = trDeltaAB.getRotation();
+		btVector3 swingAxis = 	btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
+		m_swingAxis = swingAxis;
+		m_swingAxis.normalize();
+		m_swingCorrection = qDeltaAB.getAngle();
+		if(!btFuzzyZero(m_swingCorrection))
+		{
+			m_solveSwingLimit = true;
+		}
+		return;
+	}
+
+
+	{
+		// compute rotation of A wrt B (in constraint space)
+		btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
+		btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation();
+		btQuaternion qAB = qB.inverse() * qA;
+		// split rotation into cone and twist
+		// (all this is done from B's perspective. Maybe I should be averaging axes...)
+		btVector3 vConeNoTwist = quatRotate(qAB, vTwist); vConeNoTwist.normalize();
+		btQuaternion qABCone  = shortestArcQuat(vTwist, vConeNoTwist); qABCone.normalize();
+		btQuaternion qABTwist = qABCone.inverse() * qAB; qABTwist.normalize();
+
+		if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh)
+		{
+			btScalar swingAngle, swingLimit = 0; btVector3 swingAxis;
+			computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit);
+
+			if (swingAngle > swingLimit * m_limitSoftness)
+			{
+				m_solveSwingLimit = true;
+
+				// compute limit ratio: 0->1, where
+				// 0 == beginning of soft limit
+				// 1 == hard/real limit
+				m_swingLimitRatio = 1.f;
+				if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON)
+				{
+					m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness)/
+										(swingLimit - swingLimit * m_limitSoftness);
+				}				
+
+				// swing correction tries to get back to soft limit
+				m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness);
+
+				// adjustment of swing axis (based on ellipse normal)
+				adjustSwingAxisToUseEllipseNormal(swingAxis);
+
+				// Calculate necessary axis & factors		
+				m_swingAxis = quatRotate(qB, -swingAxis);
+
+				m_twistAxisA.setValue(0,0,0);
+
+				m_kSwing =  btScalar(1.) /
+					(computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldA) +
+					 computeAngularImpulseDenominator(m_swingAxis,invInertiaWorldB));
+			}
+		}
+		else
+		{
+			// you haven't set any limits;
+			// or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?)
+			// anyway, we have either hinge or fixed joint
+			btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+			btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+			btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2);
+			btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0);
+			btVector3 target;
+			btScalar x = ivB.dot(ivA);
+			btScalar y = ivB.dot(jvA);
+			btScalar z = ivB.dot(kvA);
+			if((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
+			{ // fixed. We'll need to add one more row to constraint
+				if((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
+				{
+					m_solveSwingLimit = true;
+					m_swingAxis = -ivB.cross(ivA);
+				}
+			}
+			else
+			{
+				if(m_swingSpan1 < m_fixThresh)
+				{ // hinge around Y axis
+					if(!(btFuzzyZero(y)))
+					{
+						m_solveSwingLimit = true;
+						if(m_swingSpan2 >= m_fixThresh)
+						{
+							y = btScalar(0.f);
+							btScalar span2 = btAtan2(z, x);
+							if(span2 > m_swingSpan2)
+							{
+								x = btCos(m_swingSpan2);
+								z = btSin(m_swingSpan2);
+							}
+							else if(span2 < -m_swingSpan2)
+							{
+								x =  btCos(m_swingSpan2);
+								z = -btSin(m_swingSpan2);
+							}
+						}
+					}
+				}
+				else
+				{ // hinge around Z axis
+					if(!btFuzzyZero(z))
+					{
+						m_solveSwingLimit = true;
+						if(m_swingSpan1 >= m_fixThresh)
+						{
+							z = btScalar(0.f);
+							btScalar span1 = btAtan2(y, x);
+							if(span1 > m_swingSpan1)
+							{
+								x = btCos(m_swingSpan1);
+								y = btSin(m_swingSpan1);
+							}
+							else if(span1 < -m_swingSpan1)
+							{
+								x =  btCos(m_swingSpan1);
+								y = -btSin(m_swingSpan1);
+							}
+						}
+					}
+				}
+				target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0];
+				target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1];
+				target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2];
+				target.normalize();
+				m_swingAxis = -ivB.cross(target);
+				m_swingCorrection = m_swingAxis.length();
+				m_swingAxis.normalize();
+			}
+		}
+
+		if (m_twistSpan >= btScalar(0.f))
+		{
+			btVector3 twistAxis;
+			computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis);
+
+			if (m_twistAngle > m_twistSpan*m_limitSoftness)
+			{
+				m_solveTwistLimit = true;
+
+				m_twistLimitRatio = 1.f;
+				if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON)
+				{
+					m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness)/
+										(m_twistSpan  - m_twistSpan * m_limitSoftness);
+				}
+
+				// twist correction tries to get back to soft limit
+				m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness);
+
+				m_twistAxis = quatRotate(qB, -twistAxis);
+
+				m_kTwist = btScalar(1.) /
+					(computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldA) +
+					 computeAngularImpulseDenominator(m_twistAxis,invInertiaWorldB));
+			}
+
+			if (m_solveSwingLimit)
+				m_twistAxisA = quatRotate(qA, -twistAxis);
+		}
+		else
+		{
+			m_twistAngle = btScalar(0.f);
+		}
+	}
+}
+
+
+
+// given a cone rotation in constraint space, (pre: twist must already be removed)
+// this method computes its corresponding swing angle and axis.
+// more interestingly, it computes the cone/swing limit (angle) for this cone "pose".
+void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
+												 btScalar& swingAngle, // out
+												 btVector3& vSwingAxis, // out
+												 btScalar& swingLimit) // out
+{
+	swingAngle = qCone.getAngle();
+	if (swingAngle > SIMD_EPSILON)
+	{
+		vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z());
+		vSwingAxis.normalize();
+		if (fabs(vSwingAxis.x()) > SIMD_EPSILON)
+		{
+			// non-zero twist?! this should never happen.
+			int wtf = 0; wtf = wtf;
+		}
+
+		// Compute limit for given swing. tricky:
+		// Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
+		// (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
+
+		// For starters, compute the direction from center to surface of ellipse.
+		// This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis.
+		// (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.)
+		btScalar xEllipse =  vSwingAxis.y();
+		btScalar yEllipse = -vSwingAxis.z();
+
+		// Now, we use the slope of the vector (using x/yEllipse) and find the length
+		// of the line that intersects the ellipse:
+		//  x^2   y^2
+		//  --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
+		//  a^2   b^2
+		// Do the math and it should be clear.
+
+		swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
+		if (fabs(xEllipse) > SIMD_EPSILON)
+		{
+			btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);
+			btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
+			norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
+			btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
+			swingLimit = sqrt(swingLimit2);
+		}
+
+		// test!
+		/*swingLimit = m_swingSpan2;
+		if (fabs(vSwingAxis.z()) > SIMD_EPSILON)
+		{
+		btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2;
+		btScalar sinphi = m_swingSpan2 / sqrt(mag_2);
+		btScalar phi = asin(sinphi);
+		btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z()));
+		btScalar alpha = 3.14159f - theta - phi;
+		btScalar sinalpha = sin(alpha);
+		swingLimit = m_swingSpan1 * sinphi/sinalpha;
+		}*/
+	}
+	else if (swingAngle < 0)
+	{
+		// this should never happen!
+		int wtf = 0; wtf = wtf;
+	}
+}
+
+btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
+{
+	// compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone)
+	btScalar xEllipse = btCos(fAngleInRadians);
+	btScalar yEllipse = btSin(fAngleInRadians);
+
+	// Use the slope of the vector (using x/yEllipse) and find the length
+	// of the line that intersects the ellipse:
+	//  x^2   y^2
+	//  --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
+	//  a^2   b^2
+	// Do the math and it should be clear.
+
+	float swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
+	if (fabs(xEllipse) > SIMD_EPSILON)
+	{
+		btScalar surfaceSlope2 = (yEllipse*yEllipse)/(xEllipse*xEllipse);
+		btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
+		norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
+		btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
+		swingLimit = sqrt(swingLimit2);
+	}
+
+	// convert into point in constraint space:
+	// note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively
+	btVector3 vSwingAxis(0, xEllipse, -yEllipse);
+	btQuaternion qSwing(vSwingAxis, swingLimit);
+	btVector3 vPointInConstraintSpace(fLength,0,0);
+	return quatRotate(qSwing, vPointInConstraintSpace);
+}
+
+// given a twist rotation in constraint space, (pre: cone must already be removed)
+// this method computes its corresponding angle and axis.
+void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
+												  btScalar& twistAngle, // out
+												  btVector3& vTwistAxis) // out
+{
+	btQuaternion qMinTwist = qTwist;
+	twistAngle = qTwist.getAngle();
+
+	if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
+	{
+		qMinTwist = operator-(qTwist);
+		twistAngle = qMinTwist.getAngle();
+	}
+	if (twistAngle < 0)
+	{
+		// this should never happen
+		int wtf = 0; wtf = wtf;			
+	}
+
+	vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
+	if (twistAngle > SIMD_EPSILON)
+		vTwistAxis.normalize();
+}
+
+
+void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const
+{
+	// the swing axis is computed as the "twist-free" cone rotation,
+	// but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2).
+	// so, if we're outside the limits, the closest way back inside the cone isn't 
+	// along the vector back to the center. better (and more stable) to use the ellipse normal.
+
+	// convert swing axis to direction from center to surface of ellipse
+	// (ie. rotate 2D vector by PI/2)
+	btScalar y = -vSwingAxis.z();
+	btScalar z =  vSwingAxis.y();
+
+	// do the math...
+	if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0.
+	{
+		// compute gradient/normal of ellipse surface at current "point"
+		btScalar grad = y/z;
+		grad *= m_swingSpan2 / m_swingSpan1;
+
+		// adjust y/z to represent normal at point (instead of vector to point)
+		if (y > 0)
+			y =  fabs(grad * z);
+		else
+			y = -fabs(grad * z);
+
+		// convert ellipse direction back to swing axis
+		vSwingAxis.setZ(-y);
+		vSwingAxis.setY( z);
+		vSwingAxis.normalize();
+	}
+}
+
+
+
+void btConeTwistConstraint::setMotorTarget(const btQuaternion &q)
+{
+	btTransform trACur = m_rbA.getCenterOfMassTransform();
+	btTransform trBCur = m_rbB.getCenterOfMassTransform();
+	btTransform trABCur = trBCur.inverse() * trACur;
+	btQuaternion qABCur = trABCur.getRotation();
+	btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
+	btQuaternion qConstraintCur = trConstraintCur.getRotation();
+
+	btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
+	setMotorTargetInConstraintSpace(qConstraint);
+}
+
+
+void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion &q)
+{
+	m_qTarget = q;
+
+	// clamp motor target to within limits
+	{
+		btScalar softness = 1.f;//m_limitSoftness;
+
+		// split into twist and cone
+		btVector3 vTwisted = quatRotate(m_qTarget, vTwist);
+		btQuaternion qTargetCone  = shortestArcQuat(vTwist, vTwisted); qTargetCone.normalize();
+		btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget; qTargetTwist.normalize();
+
+		// clamp cone
+		if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f))
+		{
+			btScalar swingAngle, swingLimit; btVector3 swingAxis;
+			computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit);
+
+			if (fabs(swingAngle) > SIMD_EPSILON)
+			{
+				if (swingAngle > swingLimit*softness)
+					swingAngle = swingLimit*softness;
+				else if (swingAngle < -swingLimit*softness)
+					swingAngle = -swingLimit*softness;
+				qTargetCone = btQuaternion(swingAxis, swingAngle);
+			}
+		}
+
+		// clamp twist
+		if (m_twistSpan >= btScalar(0.05f))
+		{
+			btScalar twistAngle; btVector3 twistAxis;
+			computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis);
+
+			if (fabs(twistAngle) > SIMD_EPSILON)
+			{
+				// eddy todo: limitSoftness used here???
+				if (twistAngle > m_twistSpan*softness)
+					twistAngle = m_twistSpan*softness;
+				else if (twistAngle < -m_twistSpan*softness)
+					twistAngle = -m_twistSpan*softness;
+				qTargetTwist = btQuaternion(twistAxis, twistAngle);
+			}
+		}
+
+		m_qTarget = qTargetCone * qTargetTwist;
+	}
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+///If no axis is provided, it uses the default axis for this constraint.
+void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
+{
+	switch(num)
+	{
+		case BT_CONSTRAINT_ERP :
+		case BT_CONSTRAINT_STOP_ERP :
+			if((axis >= 0) && (axis < 3)) 
+			{
+				m_linERP = value;
+				m_flags |= BT_CONETWIST_FLAGS_LIN_ERP;
+			}
+			else
+			{
+				m_biasFactor = value;
+			}
+			break;
+		case BT_CONSTRAINT_CFM :
+		case BT_CONSTRAINT_STOP_CFM :
+			if((axis >= 0) && (axis < 3)) 
+			{
+				m_linCFM = value;
+				m_flags |= BT_CONETWIST_FLAGS_LIN_CFM;
+			}
+			else
+			{
+				m_angCFM = value;
+				m_flags |= BT_CONETWIST_FLAGS_ANG_CFM;
+			}
+			break;
+		default:
+			btAssertConstrParams(0);
+			break;
+	}
+}
+
+///return the local value of parameter
+btScalar btConeTwistConstraint::getParam(int num, int axis) const 
+{
+	btScalar retVal = 0;
+	switch(num)
+	{
+		case BT_CONSTRAINT_ERP :
+		case BT_CONSTRAINT_STOP_ERP :
+			if((axis >= 0) && (axis < 3)) 
+			{
+				btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP);
+				retVal = m_linERP;
+			}
+			else if((axis >= 3) && (axis < 6)) 
+			{
+				retVal = m_biasFactor;
+			}
+			else
+			{
+				btAssertConstrParams(0);
+			}
+			break;
+		case BT_CONSTRAINT_CFM :
+		case BT_CONSTRAINT_STOP_CFM :
+			if((axis >= 0) && (axis < 3)) 
+			{
+				btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM);
+				retVal = m_linCFM;
+			}
+			else if((axis >= 3) && (axis < 6)) 
+			{
+				btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM);
+				retVal = m_angCFM;
+			}
+			else
+			{
+				btAssertConstrParams(0);
+			}
+			break;
+		default : 
+			btAssertConstrParams(0);
+	}
+	return retVal;
+}
+
+
+void btConeTwistConstraint::setFrames(const btTransform & frameA, const btTransform & frameB)
+{
+	m_rbAFrame = frameA;
+	m_rbBFrame = frameB;
+	buildJacobian();
+	//calculateTransforms();
+}
+
+ 
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h	(revision 11817)
@@ -0,0 +1,346 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Written by: Marcus Hennix
+*/
+
+
+
+/*
+Overview:
+
+btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc).
+It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint".
+It divides the 3 rotational DOFs into swing (movement within a cone) and twist.
+Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape.
+(Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.)
+
+In the contraint's frame of reference:
+twist is along the x-axis,
+and swing 1 and 2 are along the z and y axes respectively.
+*/
+
+
+
+#ifndef BT_CONETWISTCONSTRAINT_H
+#define BT_CONETWISTCONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+enum btConeTwistFlags
+{
+	BT_CONETWIST_FLAGS_LIN_CFM = 1,
+	BT_CONETWIST_FLAGS_LIN_ERP = 2,
+	BT_CONETWIST_FLAGS_ANG_CFM = 4
+};
+
+///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
+class btConeTwistConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+	btJacobianEntry	m_jac[3]; //3 orthogonal linear constraints
+
+	btTransform m_rbAFrame; 
+	btTransform m_rbBFrame;
+
+	btScalar	m_limitSoftness;
+	btScalar	m_biasFactor;
+	btScalar	m_relaxationFactor;
+
+	btScalar	m_damping;
+
+	btScalar	m_swingSpan1;
+	btScalar	m_swingSpan2;
+	btScalar	m_twistSpan;
+
+	btScalar	m_fixThresh;
+
+	btVector3   m_swingAxis;
+	btVector3	m_twistAxis;
+
+	btScalar	m_kSwing;
+	btScalar	m_kTwist;
+
+	btScalar	m_twistLimitSign;
+	btScalar	m_swingCorrection;
+	btScalar	m_twistCorrection;
+
+	btScalar	m_twistAngle;
+
+	btScalar	m_accSwingLimitImpulse;
+	btScalar	m_accTwistLimitImpulse;
+
+	bool		m_angularOnly;
+	bool		m_solveTwistLimit;
+	bool		m_solveSwingLimit;
+
+	bool	m_useSolveConstraintObsolete;
+
+	// not yet used...
+	btScalar	m_swingLimitRatio;
+	btScalar	m_twistLimitRatio;
+	btVector3   m_twistAxisA;
+
+	// motor
+	bool		 m_bMotorEnabled;
+	bool		 m_bNormalizedMotorStrength;
+	btQuaternion m_qTarget;
+	btScalar	 m_maxMotorImpulse;
+	btVector3	 m_accMotorImpulse;
+	
+	// parameters
+	int			m_flags;
+	btScalar	m_linCFM;
+	btScalar	m_linERP;
+	btScalar	m_angCFM;
+	
+protected:
+
+	void init();
+
+	void computeConeLimitInfo(const btQuaternion& qCone, // in
+		btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
+
+	void computeTwistLimitInfo(const btQuaternion& qTwist, // in
+		btScalar& twistAngle, btVector3& vTwistAxis); // all outs
+
+	void adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const;
+
+
+public:
+
+	btConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
+	
+	btConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
+
+	virtual void	buildJacobian();
+
+	virtual void getInfo1 (btConstraintInfo1* info);
+
+	void	getInfo1NonVirtual(btConstraintInfo1* info);
+	
+	virtual void getInfo2 (btConstraintInfo2* info);
+	
+	void	getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
+
+	virtual	void	solveConstraintObsolete(btRigidBody& bodyA,btRigidBody& bodyB,btScalar	timeStep);
+
+	void	updateRHS(btScalar	timeStep);
+
+
+	const btRigidBody& getRigidBodyA() const
+	{
+		return m_rbA;
+	}
+	const btRigidBody& getRigidBodyB() const
+	{
+		return m_rbB;
+	}
+
+	void	setAngularOnly(bool angularOnly)
+	{
+		m_angularOnly = angularOnly;
+	}
+
+	void	setLimit(int limitIndex,btScalar limitValue)
+	{
+		switch (limitIndex)
+		{
+		case 3:
+			{
+				m_twistSpan = limitValue;
+				break;
+			}
+		case 4:
+			{
+				m_swingSpan2 = limitValue;
+				break;
+			}
+		case 5:
+			{
+				m_swingSpan1 = limitValue;
+				break;
+			}
+		default:
+			{
+			}
+		};
+	}
+
+	// setLimit(), a few notes:
+	// _softness:
+	//		0->1, recommend ~0.8->1.
+	//		describes % of limits where movement is free.
+	//		beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached.
+	// _biasFactor:
+	//		0->1?, recommend 0.3 +/-0.3 or so.
+	//		strength with which constraint resists zeroth order (angular, not angular velocity) limit violation.
+	// __relaxationFactor:
+	//		0->1, recommend to stay near 1.
+	//		the lower the value, the less the constraint will fight velocities which violate the angular limits.
+	void	setLimit(btScalar _swingSpan1,btScalar _swingSpan2,btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+	{
+		m_swingSpan1 = _swingSpan1;
+		m_swingSpan2 = _swingSpan2;
+		m_twistSpan  = _twistSpan;
+
+		m_limitSoftness =  _softness;
+		m_biasFactor = _biasFactor;
+		m_relaxationFactor = _relaxationFactor;
+	}
+
+	const btTransform& getAFrame() { return m_rbAFrame; };	
+	const btTransform& getBFrame() { return m_rbBFrame; };
+
+	inline int getSolveTwistLimit()
+	{
+		return m_solveTwistLimit;
+	}
+
+	inline int getSolveSwingLimit()
+	{
+		return m_solveTwistLimit;
+	}
+
+	inline btScalar getTwistLimitSign()
+	{
+		return m_twistLimitSign;
+	}
+
+	void calcAngleInfo();
+	void calcAngleInfo2(const btTransform& transA, const btTransform& transB,const btMatrix3x3& invInertiaWorldA,const btMatrix3x3& invInertiaWorldB);
+
+	inline btScalar getSwingSpan1()
+	{
+		return m_swingSpan1;
+	}
+	inline btScalar getSwingSpan2()
+	{
+		return m_swingSpan2;
+	}
+	inline btScalar getTwistSpan()
+	{
+		return m_twistSpan;
+	}
+	inline btScalar getTwistAngle()
+	{
+		return m_twistAngle;
+	}
+	bool isPastSwingLimit() { return m_solveSwingLimit; }
+
+	void setDamping(btScalar damping) { m_damping = damping; }
+
+	void enableMotor(bool b) { m_bMotorEnabled = b; }
+	void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = false; }
+	void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; m_bNormalizedMotorStrength = true; }
+
+	btScalar getFixThresh() { return m_fixThresh; }
+	void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
+
+	// setMotorTarget:
+	// q: the desired rotation of bodyA wrt bodyB.
+	// note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
+	// note: don't forget to enableMotor()
+	void setMotorTarget(const btQuaternion &q);
+
+	// same as above, but q is the desired rotation of frameA wrt frameB in constraint space
+	void setMotorTargetInConstraintSpace(const btQuaternion &q);
+
+	btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+	virtual	void setParam(int num, btScalar value, int axis = -1);
+
+	virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
+
+	const btTransform& getFrameOffsetA() const
+	{
+		return m_rbAFrame;
+	}
+
+	const btTransform& getFrameOffsetB() const
+	{
+		return m_rbBFrame;
+	}
+
+
+	///return the local value of parameter
+	virtual	btScalar getParam(int num, int axis = -1) const;
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btConeTwistConstraintData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btTransformFloatData m_rbAFrame;
+	btTransformFloatData m_rbBFrame;
+
+	//limits
+	float	m_swingSpan1;
+	float	m_swingSpan2;
+	float	m_twistSpan;
+	float	m_limitSoftness;
+	float	m_biasFactor;
+	float	m_relaxationFactor;
+
+	float	m_damping;
+		
+	char m_pad[4];
+
+};
+	
+
+
+SIMD_FORCE_INLINE int	btConeTwistConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btConeTwistConstraintData);
+
+}
+
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE const char*	btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btConeTwistConstraintData* cone = (btConeTwistConstraintData*) dataBuffer;
+	btTypedConstraint::serialize(&cone->m_typeConstraintData,serializer);
+
+	m_rbAFrame.serializeFloat(cone->m_rbAFrame);
+	m_rbBFrame.serializeFloat(cone->m_rbBFrame);
+	
+	cone->m_swingSpan1 = float(m_swingSpan1);
+	cone->m_swingSpan2 = float(m_swingSpan2);
+	cone->m_twistSpan = float(m_twistSpan);
+	cone->m_limitSoftness = float(m_limitSoftness);
+	cone->m_biasFactor = float(m_biasFactor);
+	cone->m_relaxationFactor = float(m_relaxationFactor);
+	cone->m_damping = float(m_damping);
+
+	return "btConeTwistConstraintData";
+}
+
+
+#endif //BT_CONETWISTCONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONSTRAINT_SOLVER_H
+#define BT_CONSTRAINT_SOLVER_H
+
+#include "LinearMath/btScalar.h"
+
+class btPersistentManifold;
+class btRigidBody;
+class btCollisionObject;
+class btTypedConstraint;
+struct btContactSolverInfo;
+struct btBroadphaseProxy;
+class btIDebugDraw;
+class btStackAlloc;
+class	btDispatcher;
+/// btConstraintSolver provides solver interface
+class btConstraintSolver
+{
+
+public:
+
+	virtual ~btConstraintSolver() {}
+	
+	virtual void prepareSolve (int /* numBodies */, int /* numManifolds */) {;}
+
+	///solve a group of constraints
+	virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints, const btContactSolverInfo& info,class btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher) = 0;
+
+	virtual void allSolved (const btContactSolverInfo& /* info */,class btIDebugDraw* /* debugDrawer */, btStackAlloc* /* stackAlloc */) {;}
+
+	///clear internal cached data and reset random seed
+	virtual	void	reset() = 0;
+};
+
+
+
+
+#endif //BT_CONSTRAINT_SOLVER_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp	(revision 11817)
@@ -0,0 +1,178 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btContactConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+
+
+btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB)
+:btTypedConstraint(CONTACT_CONSTRAINT_TYPE,rbA,rbB),
+	m_contactManifold(*contactManifold)
+{
+
+}
+
+btContactConstraint::~btContactConstraint()
+{
+
+}
+
+void	btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
+{
+	m_contactManifold = *contactManifold;
+}
+
+void btContactConstraint::getInfo1 (btConstraintInfo1* info)
+{
+
+}
+
+void btContactConstraint::getInfo2 (btConstraintInfo2* info)
+{
+
+}
+
+void	btContactConstraint::buildJacobian()
+{
+
+}
+
+
+
+
+
+#include "btContactConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+
+
+//response  between two dynamic objects without friction, assuming 0 penetration depth
+btScalar resolveSingleCollision(
+        btRigidBody* body1,
+        btCollisionObject* colObj2,
+		const btVector3& contactPositionWorld,
+		const btVector3& contactNormalOnB,
+        const btContactSolverInfo& solverInfo,
+		btScalar distance)
+{
+	btRigidBody* body2 = btRigidBody::upcast(colObj2);
+    
+	
+    const btVector3& normal = contactNormalOnB;
+
+    btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin(); 
+    btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin();
+    
+    btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1);
+	btVector3 vel2 = body2? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+    btVector3 vel = vel1 - vel2;
+    btScalar rel_vel;
+    rel_vel = normal.dot(vel);
+    
+    btScalar combinedRestitution = body1->getRestitution() * colObj2->getRestitution();
+    btScalar restitution = combinedRestitution* -rel_vel;
+
+    btScalar positionalError = solverInfo.m_erp *-distance /solverInfo.m_timeStep ;
+    btScalar velocityError = -(1.0f + restitution) * rel_vel;// * damping;
+	btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld,normal);
+	btScalar denom1 = body2? body2->computeImpulseDenominator(contactPositionWorld,normal) : 0.f;
+	btScalar relaxation = 1.f;
+	btScalar jacDiagABInv = relaxation/(denom0+denom1);
+
+    btScalar penetrationImpulse = positionalError * jacDiagABInv;
+    btScalar velocityImpulse = velocityError * jacDiagABInv;
+
+    btScalar normalImpulse = penetrationImpulse+velocityImpulse;
+    normalImpulse = 0.f > normalImpulse ? 0.f: normalImpulse;
+
+	body1->applyImpulse(normal*(normalImpulse), rel_pos1);
+    if (body2)
+		body2->applyImpulse(-normal*(normalImpulse), rel_pos2);
+    
+    return normalImpulse;
+}
+
+
+//bilateral constraint between two dynamic objects
+void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
+                      btRigidBody& body2, const btVector3& pos2,
+                      btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep)
+{
+	(void)timeStep;
+	(void)distance;
+
+
+	btScalar normalLenSqr = normal.length2();
+	btAssert(btFabs(normalLenSqr) < btScalar(1.1));
+	if (normalLenSqr > btScalar(1.1))
+	{
+		impulse = btScalar(0.);
+		return;
+	}
+	btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition(); 
+	btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
+	//this jacobian entry could be re-used for all iterations
+	
+	btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
+	btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
+	btVector3 vel = vel1 - vel2;
+	
+
+	   btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
+		body2.getCenterOfMassTransform().getBasis().transpose(),
+		rel_pos1,rel_pos2,normal,body1.getInvInertiaDiagLocal(),body1.getInvMass(),
+		body2.getInvInertiaDiagLocal(),body2.getInvMass());
+
+	btScalar jacDiagAB = jac.getDiagonal();
+	btScalar jacDiagABInv = btScalar(1.) / jacDiagAB;
+	
+	  btScalar rel_vel = jac.getRelativeVelocity(
+		body1.getLinearVelocity(),
+		body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(),
+		body2.getLinearVelocity(),
+		body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity()); 
+	btScalar a;
+	a=jacDiagABInv;
+
+
+	rel_vel = normal.dot(vel);
+	
+	//todo: move this into proper structure
+	btScalar contactDamping = btScalar(0.2);
+
+#ifdef ONLY_USE_LINEAR_MASS
+	btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass());
+	impulse = - contactDamping * rel_vel * massTerm;
+#else	
+	btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
+	impulse = velocityImpulse;
+#endif
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONTACT_CONSTRAINT_H
+#define BT_CONTACT_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface
+ATTRIBUTE_ALIGNED128(class) btContactConstraint : public btTypedConstraint
+{
+protected:
+
+	btPersistentManifold m_contactManifold;
+
+public:
+
+
+	btContactConstraint(btPersistentManifold* contactManifold,btRigidBody& rbA,btRigidBody& rbB);
+
+	void	setContactManifold(btPersistentManifold* contactManifold);
+
+	btPersistentManifold* getContactManifold()
+	{
+		return &m_contactManifold;
+	}
+
+	const btPersistentManifold* getContactManifold() const
+	{
+		return &m_contactManifold;
+	}
+
+	virtual ~btContactConstraint();
+
+	virtual void getInfo1 (btConstraintInfo1* info);
+
+	virtual void getInfo2 (btConstraintInfo2* info);
+
+	///obsolete methods
+	virtual void	buildJacobian();
+
+
+};
+
+///very basic collision resolution without friction
+btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld,const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo,btScalar distance);
+
+
+///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects
+void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
+                      btRigidBody& body2, const btVector3& pos2,
+                      btScalar distance, const btVector3& normal,btScalar& impulse ,btScalar timeStep);
+
+
+
+#endif //BT_CONTACT_CONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONTACT_SOLVER_INFO
+#define BT_CONTACT_SOLVER_INFO
+
+enum	btSolverMode
+{
+	SOLVER_RANDMIZE_ORDER = 1,
+	SOLVER_FRICTION_SEPARATE = 2,
+	SOLVER_USE_WARMSTARTING = 4,
+	SOLVER_USE_FRICTION_WARMSTARTING = 8,
+	SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
+	SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
+	SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
+	SOLVER_CACHE_FRIENDLY = 128,
+	SOLVER_SIMD = 256,	//enabled for Windows, the solver innerloop is branchless SIMD, 40% faster than FPU/scalar version
+	SOLVER_CUDA = 512	//will be open sourced during Game Developers Conference 2009. Much faster.
+};
+
+struct btContactSolverInfoData
+{
+	
+
+	btScalar	m_tau;
+	btScalar	m_damping;//global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
+	btScalar	m_friction;
+	btScalar	m_timeStep;
+	btScalar	m_restitution;
+	int		m_numIterations;
+	btScalar	m_maxErrorReduction;
+	btScalar	m_sor;
+	btScalar	m_erp;//used as Baumgarte factor
+	btScalar	m_erp2;//used in Split Impulse
+	btScalar	m_globalCfm;//constraint force mixing
+	int			m_splitImpulse;
+	btScalar	m_splitImpulsePenetrationThreshold;
+	btScalar	m_linearSlop;
+	btScalar	m_warmstartingFactor;
+
+	int			m_solverMode;
+	int	m_restingContactRestitutionThreshold;
+	int			m_minimumSolverBatchSize;
+
+
+};
+
+struct btContactSolverInfo : public btContactSolverInfoData
+{
+
+	
+
+	inline btContactSolverInfo()
+	{
+		m_tau = btScalar(0.6);
+		m_damping = btScalar(1.0);
+		m_friction = btScalar(0.3);
+		m_restitution = btScalar(0.);
+		m_maxErrorReduction = btScalar(20.);
+		m_numIterations = 10;
+		m_erp = btScalar(0.2);
+		m_erp2 = btScalar(0.1);
+		m_globalCfm = btScalar(0.);
+		m_sor = btScalar(1.);
+		m_splitImpulse = false;
+		m_splitImpulsePenetrationThreshold = -0.02f;
+		m_linearSlop = btScalar(0.0);
+		m_warmstartingFactor=btScalar(0.85);
+		m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD;// | SOLVER_RANDMIZE_ORDER;
+		m_restingContactRestitutionThreshold = 2;//resting contact lifetime threshold to disable restitution
+		m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
+	}
+};
+
+#endif //BT_CONTACT_SOLVER_INFO
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp	(revision 11817)
@@ -0,0 +1,1070 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+2007-09-09
+Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+#include "btGeneric6DofConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+
+
+#define D6_USE_OBSOLETE_METHOD false
+#define D6_USE_FRAME_OFFSET true
+
+
+
+
+
+
+btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+: btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB)
+, m_frameInA(frameInA)
+, m_frameInB(frameInB),
+m_useLinearReferenceFrameA(useLinearReferenceFrameA),
+m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+m_flags(0),
+m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
+{
+	calculateTransforms();
+}
+
+
+
+btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
+        : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
+		m_frameInB(frameInB),
+		m_useLinearReferenceFrameA(useLinearReferenceFrameB),
+		m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
+		m_flags(0),
+		m_useSolveConstraintObsolete(false)
+{
+	///not providing rigidbody A means implicitly using worldspace for body A
+	m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+	calculateTransforms();
+}
+
+
+
+
+#define GENERIC_D6_DISABLE_WARMSTARTING 1
+
+
+
+btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
+btScalar btGetMatrixElem(const btMatrix3x3& mat, int index)
+{
+	int i = index%3;
+	int j = index/3;
+	return mat[i][j];
+}
+
+
+
+///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
+bool	matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz);
+bool	matrixToEulerXYZ(const btMatrix3x3& mat,btVector3& xyz)
+{
+	//	// rot =  cy*cz          -cy*sz           sy
+	//	//        cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
+	//	//       -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
+	//
+
+	btScalar fi = btGetMatrixElem(mat,2);
+	if (fi < btScalar(1.0f))
+	{
+		if (fi > btScalar(-1.0f))
+		{
+			xyz[0] = btAtan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
+			xyz[1] = btAsin(btGetMatrixElem(mat,2));
+			xyz[2] = btAtan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
+			return true;
+		}
+		else
+		{
+			// WARNING.  Not unique.  XA - ZA = -atan2(r10,r11)
+			xyz[0] = -btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+			xyz[1] = -SIMD_HALF_PI;
+			xyz[2] = btScalar(0.0);
+			return false;
+		}
+	}
+	else
+	{
+		// WARNING.  Not unique.  XAngle + ZAngle = atan2(r10,r11)
+		xyz[0] = btAtan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
+		xyz[1] = SIMD_HALF_PI;
+		xyz[2] = 0.0;
+	}
+	return false;
+}
+
+//////////////////////////// btRotationalLimitMotor ////////////////////////////////////
+
+int btRotationalLimitMotor::testLimitValue(btScalar test_value)
+{
+	if(m_loLimit>m_hiLimit)
+	{
+		m_currentLimit = 0;//Free from violation
+		return 0;
+	}
+	if (test_value < m_loLimit)
+	{
+		m_currentLimit = 1;//low limit violation
+		m_currentLimitError =  test_value - m_loLimit;
+		return 1;
+	}
+	else if (test_value> m_hiLimit)
+	{
+		m_currentLimit = 2;//High limit violation
+		m_currentLimitError = test_value - m_hiLimit;
+		return 2;
+	};
+
+	m_currentLimit = 0;//Free from violation
+	return 0;
+
+}
+
+
+
+btScalar btRotationalLimitMotor::solveAngularLimits(
+	btScalar timeStep,btVector3& axis,btScalar jacDiagABInv,
+	btRigidBody * body0, btRigidBody * body1 )
+{
+	if (needApplyTorques()==false) return 0.0f;
+
+	btScalar target_velocity = m_targetVelocity;
+	btScalar maxMotorForce = m_maxMotorForce;
+
+	//current error correction
+	if (m_currentLimit!=0)
+	{
+		target_velocity = -m_stopERP*m_currentLimitError/(timeStep);
+		maxMotorForce = m_maxLimitForce;
+	}
+
+	maxMotorForce *= timeStep;
+
+	// current velocity difference
+
+	btVector3 angVelA;
+	body0->internalGetAngularVelocity(angVelA);
+	btVector3 angVelB;
+	body1->internalGetAngularVelocity(angVelB);
+
+	btVector3 vel_diff;
+	vel_diff = angVelA-angVelB;
+
+
+
+	btScalar rel_vel = axis.dot(vel_diff);
+
+	// correction velocity
+	btScalar motor_relvel = m_limitSoftness*(target_velocity  - m_damping*rel_vel);
+
+
+	if ( motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON  )
+	{
+		return 0.0f;//no need for applying force
+	}
+
+
+	// correction impulse
+	btScalar unclippedMotorImpulse = (1+m_bounce)*motor_relvel*jacDiagABInv;
+
+	// clip correction impulse
+	btScalar clippedMotorImpulse;
+
+	///@todo: should clip against accumulated impulse
+	if (unclippedMotorImpulse>0.0f)
+	{
+		clippedMotorImpulse =  unclippedMotorImpulse > maxMotorForce? maxMotorForce: unclippedMotorImpulse;
+	}
+	else
+	{
+		clippedMotorImpulse =  unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce: unclippedMotorImpulse;
+	}
+
+
+	// sort with accumulated impulses
+	btScalar	lo = btScalar(-BT_LARGE_FLOAT);
+	btScalar	hi = btScalar(BT_LARGE_FLOAT);
+
+	btScalar oldaccumImpulse = m_accumulatedImpulse;
+	btScalar sum = oldaccumImpulse + clippedMotorImpulse;
+	m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
+
+	clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse;
+
+	btVector3 motorImp = clippedMotorImpulse * axis;
+
+	//body0->applyTorqueImpulse(motorImp);
+	//body1->applyTorqueImpulse(-motorImp);
+
+	body0->internalApplyImpulse(btVector3(0,0,0), body0->getInvInertiaTensorWorld()*axis,clippedMotorImpulse);
+	body1->internalApplyImpulse(btVector3(0,0,0), body1->getInvInertiaTensorWorld()*axis,-clippedMotorImpulse);
+
+
+	return clippedMotorImpulse;
+
+
+}
+
+//////////////////////////// End btRotationalLimitMotor ////////////////////////////////////
+
+
+
+
+//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
+
+
+int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value)
+{
+	btScalar loLimit = m_lowerLimit[limitIndex];
+	btScalar hiLimit = m_upperLimit[limitIndex];
+	if(loLimit > hiLimit)
+	{
+		m_currentLimit[limitIndex] = 0;//Free from violation
+		m_currentLimitError[limitIndex] = btScalar(0.f);
+		return 0;
+	}
+
+	if (test_value < loLimit)
+	{
+		m_currentLimit[limitIndex] = 2;//low limit violation
+		m_currentLimitError[limitIndex] =  test_value - loLimit;
+		return 2;
+	}
+	else if (test_value> hiLimit)
+	{
+		m_currentLimit[limitIndex] = 1;//High limit violation
+		m_currentLimitError[limitIndex] = test_value - hiLimit;
+		return 1;
+	};
+
+	m_currentLimit[limitIndex] = 0;//Free from violation
+	m_currentLimitError[limitIndex] = btScalar(0.f);
+	return 0;
+}
+
+
+
+btScalar btTranslationalLimitMotor::solveLinearAxis(
+	btScalar timeStep,
+	btScalar jacDiagABInv,
+	btRigidBody& body1,const btVector3 &pointInA,
+	btRigidBody& body2,const btVector3 &pointInB,
+	int limit_index,
+	const btVector3 & axis_normal_on_a,
+	const btVector3 & anchorPos)
+{
+
+	///find relative velocity
+	//    btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition();
+	//    btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition();
+	btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition();
+	btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition();
+
+	btVector3 vel1;
+	body1.internalGetVelocityInLocalPointObsolete(rel_pos1,vel1);
+	btVector3 vel2;
+	body2.internalGetVelocityInLocalPointObsolete(rel_pos2,vel2);
+	btVector3 vel = vel1 - vel2;
+
+	btScalar rel_vel = axis_normal_on_a.dot(vel);
+
+
+
+	/// apply displacement correction
+
+	//positional error (zeroth order error)
+	btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a);
+	btScalar	lo = btScalar(-BT_LARGE_FLOAT);
+	btScalar	hi = btScalar(BT_LARGE_FLOAT);
+
+	btScalar minLimit = m_lowerLimit[limit_index];
+	btScalar maxLimit = m_upperLimit[limit_index];
+
+	//handle the limits
+	if (minLimit < maxLimit)
+	{
+		{
+			if (depth > maxLimit)
+			{
+				depth -= maxLimit;
+				lo = btScalar(0.);
+
+			}
+			else
+			{
+				if (depth < minLimit)
+				{
+					depth -= minLimit;
+					hi = btScalar(0.);
+				}
+				else
+				{
+					return 0.0f;
+				}
+			}
+		}
+	}
+
+	btScalar normalImpulse= m_limitSoftness*(m_restitution*depth/timeStep - m_damping*rel_vel) * jacDiagABInv;
+
+
+
+
+	btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index];
+	btScalar sum = oldNormalImpulse + normalImpulse;
+	m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
+	normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
+
+	btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
+	//body1.applyImpulse( impulse_vector, rel_pos1);
+	//body2.applyImpulse(-impulse_vector, rel_pos2);
+
+	btVector3 ftorqueAxis1 = rel_pos1.cross(axis_normal_on_a);
+	btVector3 ftorqueAxis2 = rel_pos2.cross(axis_normal_on_a);
+	body1.internalApplyImpulse(axis_normal_on_a*body1.getInvMass(), body1.getInvInertiaTensorWorld()*ftorqueAxis1,normalImpulse);
+	body2.internalApplyImpulse(axis_normal_on_a*body2.getInvMass(), body2.getInvInertiaTensorWorld()*ftorqueAxis2,-normalImpulse);
+
+
+
+
+	return normalImpulse;
+}
+
+//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
+
+void btGeneric6DofConstraint::calculateAngleInfo()
+{
+	btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse()*m_calculatedTransformB.getBasis();
+	matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+	// in euler angle mode we do not actually constrain the angular velocity
+	// along the axes axis[0] and axis[2] (although we do use axis[1]) :
+	//
+	//    to get			constrain w2-w1 along		...not
+	//    ------			---------------------		------
+	//    d(angle[0])/dt = 0	ax[1] x ax[2]			ax[0]
+	//    d(angle[1])/dt = 0	ax[1]
+	//    d(angle[2])/dt = 0	ax[0] x ax[1]			ax[2]
+	//
+	// constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
+	// to prove the result for angle[0], write the expression for angle[0] from
+	// GetInfo1 then take the derivative. to prove this for angle[2] it is
+	// easier to take the euler rate expression for d(angle[2])/dt with respect
+	// to the components of w and set that to 0.
+	btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
+	btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
+
+	m_calculatedAxis[1] = axis2.cross(axis0);
+	m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
+	m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
+
+	m_calculatedAxis[0].normalize();
+	m_calculatedAxis[1].normalize();
+	m_calculatedAxis[2].normalize();
+
+}
+
+void btGeneric6DofConstraint::calculateTransforms()
+{
+	calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+{
+	m_calculatedTransformA = transA * m_frameInA;
+	m_calculatedTransformB = transB * m_frameInB;
+	calculateLinearInfo();
+	calculateAngleInfo();
+	if(m_useOffsetForConstraintFrame)
+	{	//  get weight factors depending on masses
+		btScalar miA = getRigidBodyA().getInvMass();
+		btScalar miB = getRigidBodyB().getInvMass();
+		m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+		btScalar miS = miA + miB;
+		if(miS > btScalar(0.f))
+		{
+			m_factA = miB / miS;
+		}
+		else 
+		{
+			m_factA = btScalar(0.5f);
+		}
+		m_factB = btScalar(1.0f) - m_factA;
+	}
+}
+
+
+
+void btGeneric6DofConstraint::buildLinearJacobian(
+	btJacobianEntry & jacLinear,const btVector3 & normalWorld,
+	const btVector3 & pivotAInW,const btVector3 & pivotBInW)
+{
+	new (&jacLinear) btJacobianEntry(
+        m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+        m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+        pivotAInW - m_rbA.getCenterOfMassPosition(),
+        pivotBInW - m_rbB.getCenterOfMassPosition(),
+        normalWorld,
+        m_rbA.getInvInertiaDiagLocal(),
+        m_rbA.getInvMass(),
+        m_rbB.getInvInertiaDiagLocal(),
+        m_rbB.getInvMass());
+}
+
+
+
+void btGeneric6DofConstraint::buildAngularJacobian(
+	btJacobianEntry & jacAngular,const btVector3 & jointAxisW)
+{
+	 new (&jacAngular)	btJacobianEntry(jointAxisW,
+                                      m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+                                      m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+                                      m_rbA.getInvInertiaDiagLocal(),
+                                      m_rbB.getInvInertiaDiagLocal());
+
+}
+
+
+
+bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
+{
+	btScalar angle = m_calculatedAxisAngleDiff[axis_index];
+	angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
+	m_angularLimits[axis_index].m_currentPosition = angle;
+	//test limits
+	m_angularLimits[axis_index].testLimitValue(angle);
+	return m_angularLimits[axis_index].needApplyTorques();
+}
+
+
+
+void btGeneric6DofConstraint::buildJacobian()
+{
+#ifndef __SPU__
+	if (m_useSolveConstraintObsolete)
+	{
+
+		// Clear accumulated impulses for the next simulation step
+		m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+		int i;
+		for(i = 0; i < 3; i++)
+		{
+			m_angularLimits[i].m_accumulatedImpulse = btScalar(0.);
+		}
+		//calculates transform
+		calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+
+		//  const btVector3& pivotAInW = m_calculatedTransformA.getOrigin();
+		//  const btVector3& pivotBInW = m_calculatedTransformB.getOrigin();
+		calcAnchorPos();
+		btVector3 pivotAInW = m_AnchorPos;
+		btVector3 pivotBInW = m_AnchorPos;
+
+		// not used here
+		//    btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
+		//    btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
+
+		btVector3 normalWorld;
+		//linear part
+		for (i=0;i<3;i++)
+		{
+			if (m_linearLimits.isLimited(i))
+			{
+				if (m_useLinearReferenceFrameA)
+					normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+				else
+					normalWorld = m_calculatedTransformB.getBasis().getColumn(i);
+
+				buildLinearJacobian(
+					m_jacLinear[i],normalWorld ,
+					pivotAInW,pivotBInW);
+
+			}
+		}
+
+		// angular part
+		for (i=0;i<3;i++)
+		{
+			//calculates error angle
+			if (testAngularLimitMotor(i))
+			{
+				normalWorld = this->getAxis(i);
+				// Create angular atom
+				buildAngularJacobian(m_jacAng[i],normalWorld);
+			}
+		}
+
+	}
+#endif //__SPU__
+
+}
+
+
+void btGeneric6DofConstraint::getInfo1 (btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	} else
+	{
+		//prepare constraint
+		calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+		info->m_numConstraintRows = 0;
+		info->nub = 6;
+		int i;
+		//test linear limits
+		for(i = 0; i < 3; i++)
+		{
+			if(m_linearLimits.needApplyForce(i))
+			{
+				info->m_numConstraintRows++;
+				info->nub--;
+			}
+		}
+		//test angular limits
+		for (i=0;i<3 ;i++ )
+		{
+			if(testAngularLimitMotor(i))
+			{
+				info->m_numConstraintRows++;
+				info->nub--;
+			}
+		}
+	}
+}
+
+void btGeneric6DofConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	} else
+	{
+		//pre-allocate all 6
+		info->m_numConstraintRows = 6;
+		info->nub = 0;
+	}
+}
+
+
+void btGeneric6DofConstraint::getInfo2 (btConstraintInfo2* info)
+{
+	btAssert(!m_useSolveConstraintObsolete);
+
+	const btTransform& transA = m_rbA.getCenterOfMassTransform();
+	const btTransform& transB = m_rbB.getCenterOfMassTransform();
+	const btVector3& linVelA = m_rbA.getLinearVelocity();
+	const btVector3& linVelB = m_rbB.getLinearVelocity();
+	const btVector3& angVelA = m_rbA.getAngularVelocity();
+	const btVector3& angVelB = m_rbB.getAngularVelocity();
+
+	if(m_useOffsetForConstraintFrame)
+	{ // for stability better to solve angular limits first
+		int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+		setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+	}
+	else
+	{ // leave old version for compatibility
+		int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
+		setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+	}
+
+}
+
+
+void btGeneric6DofConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+	
+	btAssert(!m_useSolveConstraintObsolete);
+	//prepare constraint
+	calculateTransforms(transA,transB);
+
+	int i;
+	for (i=0;i<3 ;i++ )
+	{
+		testAngularLimitMotor(i);
+	}
+
+	if(m_useOffsetForConstraintFrame)
+	{ // for stability better to solve angular limits first
+		int row = setAngularLimits(info, 0,transA,transB,linVelA,linVelB,angVelA,angVelB);
+		setLinearLimits(info, row, transA,transB,linVelA,linVelB,angVelA,angVelB);
+	}
+	else
+	{ // leave old version for compatibility
+		int row = setLinearLimits(info, 0, transA,transB,linVelA,linVelB,angVelA,angVelB);
+		setAngularLimits(info, row,transA,transB,linVelA,linVelB,angVelA,angVelB);
+	}
+}
+
+
+
+int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+//	int row = 0;
+	//solve linear limits
+	btRotationalLimitMotor limot;
+	for (int i=0;i<3 ;i++ )
+	{
+		if(m_linearLimits.needApplyForce(i))
+		{ // re-use rotational motor code
+			limot.m_bounce = btScalar(0.f);
+			limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
+			limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
+			limot.m_currentLimitError  = m_linearLimits.m_currentLimitError[i];
+			limot.m_damping  = m_linearLimits.m_damping;
+			limot.m_enableMotor  = m_linearLimits.m_enableMotor[i];
+			limot.m_hiLimit  = m_linearLimits.m_upperLimit[i];
+			limot.m_limitSoftness  = m_linearLimits.m_limitSoftness;
+			limot.m_loLimit  = m_linearLimits.m_lowerLimit[i];
+			limot.m_maxLimitForce  = btScalar(0.f);
+			limot.m_maxMotorForce  = m_linearLimits.m_maxMotorForce[i];
+			limot.m_targetVelocity  = m_linearLimits.m_targetVelocity[i];
+			btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
+			int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT);
+			limot.m_normalCFM	= (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
+			limot.m_stopCFM		= (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
+			limot.m_stopERP		= (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
+			if(m_useOffsetForConstraintFrame)
+			{
+				int indx1 = (i + 1) % 3;
+				int indx2 = (i + 2) % 3;
+				int rotAllowed = 1; // rotations around orthos to current axis
+				if(m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
+				{
+					rotAllowed = 0;
+				}
+				row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0, rotAllowed);
+			}
+			else
+			{
+				row += get_limit_motor_info2(&limot, transA,transB,linVelA,linVelB,angVelA,angVelB, info, row, axis, 0);
+			}
+		}
+	}
+	return row;
+}
+
+
+
+int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2 *info, int row_offset, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB)
+{
+	btGeneric6DofConstraint * d6constraint = this;
+	int row = row_offset;
+	//solve angular limits
+	for (int i=0;i<3 ;i++ )
+	{
+		if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
+		{
+			btVector3 axis = d6constraint->getAxis(i);
+			int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT);
+			if(!(flags & BT_6DOF_FLAGS_CFM_NORM))
+			{
+				m_angularLimits[i].m_normalCFM = info->cfm[0];
+			}
+			if(!(flags & BT_6DOF_FLAGS_CFM_STOP))
+			{
+				m_angularLimits[i].m_stopCFM = info->cfm[0];
+			}
+			if(!(flags & BT_6DOF_FLAGS_ERP_STOP))
+			{
+				m_angularLimits[i].m_stopERP = info->erp;
+			}
+			row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
+												transA,transB,linVelA,linVelB,angVelA,angVelB, info,row,axis,1);
+		}
+	}
+
+	return row;
+}
+
+
+
+
+void	btGeneric6DofConstraint::updateRHS(btScalar	timeStep)
+{
+	(void)timeStep;
+
+}
+
+
+void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
+{
+	m_frameInA = frameA;
+	m_frameInB = frameB;
+	buildJacobian();
+	calculateTransforms();
+}
+
+
+
+btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const
+{
+	return m_calculatedAxis[axis_index];
+}
+
+
+btScalar	btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
+{
+	return m_calculatedLinearDiff[axisIndex];
+}
+
+
+btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const
+{
+	return m_calculatedAxisAngleDiff[axisIndex];
+}
+
+
+
+void btGeneric6DofConstraint::calcAnchorPos(void)
+{
+	btScalar imA = m_rbA.getInvMass();
+	btScalar imB = m_rbB.getInvMass();
+	btScalar weight;
+	if(imB == btScalar(0.0))
+	{
+		weight = btScalar(1.0);
+	}
+	else
+	{
+		weight = imA / (imA + imB);
+	}
+	const btVector3& pA = m_calculatedTransformA.getOrigin();
+	const btVector3& pB = m_calculatedTransformB.getOrigin();
+	m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight);
+	return;
+}
+
+
+
+void btGeneric6DofConstraint::calculateLinearInfo()
+{
+	m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
+	m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
+	for(int i = 0; i < 3; i++)
+	{
+		m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
+		m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
+	}
+}
+
+
+
+int btGeneric6DofConstraint::get_limit_motor_info2(
+	btRotationalLimitMotor * limot,
+	const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
+	btConstraintInfo2 *info, int row, btVector3& ax1, int rotational,int rotAllowed)
+{
+    int srow = row * info->rowskip;
+    int powered = limot->m_enableMotor;
+    int limit = limot->m_currentLimit;
+    if (powered || limit)
+    {   // if the joint is powered, or has joint limits, add in the extra row
+        btScalar *J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
+        btScalar *J2 = rotational ? info->m_J2angularAxis : 0;
+        J1[srow+0] = ax1[0];
+        J1[srow+1] = ax1[1];
+        J1[srow+2] = ax1[2];
+        if(rotational)
+        {
+            J2[srow+0] = -ax1[0];
+            J2[srow+1] = -ax1[1];
+            J2[srow+2] = -ax1[2];
+        }
+        if((!rotational))
+        {
+			if (m_useOffsetForConstraintFrame)
+			{
+				btVector3 tmpA, tmpB, relA, relB;
+				// get vector from bodyB to frameB in WCS
+				relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+				// get its projection to constraint axis
+				btVector3 projB = ax1 * relB.dot(ax1);
+				// get vector directed from bodyB to constraint axis (and orthogonal to it)
+				btVector3 orthoB = relB - projB;
+				// same for bodyA
+				relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
+				btVector3 projA = ax1 * relA.dot(ax1);
+				btVector3 orthoA = relA - projA;
+				// get desired offset between frames A and B along constraint axis
+				btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
+				// desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
+				btVector3 totalDist = projA + ax1 * desiredOffs - projB;
+				// get offset vectors relA and relB
+				relA = orthoA + totalDist * m_factA;
+				relB = orthoB - totalDist * m_factB;
+				tmpA = relA.cross(ax1);
+				tmpB = relB.cross(ax1);
+				if(m_hasStaticBody && (!rotAllowed))
+				{
+					tmpA *= m_factA;
+					tmpB *= m_factB;
+				}
+				int i;
+				for (i=0; i<3; i++) info->m_J1angularAxis[srow+i] = tmpA[i];
+				for (i=0; i<3; i++) info->m_J2angularAxis[srow+i] = -tmpB[i];
+			} else
+			{
+				btVector3 ltd;	// Linear Torque Decoupling vector
+				btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
+				ltd = c.cross(ax1);
+				info->m_J1angularAxis[srow+0] = ltd[0];
+				info->m_J1angularAxis[srow+1] = ltd[1];
+				info->m_J1angularAxis[srow+2] = ltd[2];
+
+				c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
+				ltd = -c.cross(ax1);
+				info->m_J2angularAxis[srow+0] = ltd[0];
+				info->m_J2angularAxis[srow+1] = ltd[1];
+				info->m_J2angularAxis[srow+2] = ltd[2];
+			}
+        }
+        // if we're limited low and high simultaneously, the joint motor is
+        // ineffective
+        if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0;
+        info->m_constraintError[srow] = btScalar(0.f);
+        if (powered)
+        {
+			info->cfm[srow] = limot->m_normalCFM;
+            if(!limit)
+            {
+				btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
+
+				btScalar mot_fact = getMotorFactor(	limot->m_currentPosition, 
+													limot->m_loLimit,
+													limot->m_hiLimit, 
+													tag_vel, 
+													info->fps * limot->m_stopERP);
+				info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
+                info->m_lowerLimit[srow] = -limot->m_maxMotorForce;
+                info->m_upperLimit[srow] = limot->m_maxMotorForce;
+            }
+        }
+        if(limit)
+        {
+            btScalar k = info->fps * limot->m_stopERP;
+			if(!rotational)
+			{
+				info->m_constraintError[srow] += k * limot->m_currentLimitError;
+			}
+			else
+			{
+				info->m_constraintError[srow] += -k * limot->m_currentLimitError;
+			}
+			info->cfm[srow] = limot->m_stopCFM;
+            if (limot->m_loLimit == limot->m_hiLimit)
+            {   // limited low and high simultaneously
+                info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                info->m_upperLimit[srow] = SIMD_INFINITY;
+            }
+            else
+            {
+                if (limit == 1)
+                {
+                    info->m_lowerLimit[srow] = 0;
+                    info->m_upperLimit[srow] = SIMD_INFINITY;
+                }
+                else
+                {
+                    info->m_lowerLimit[srow] = -SIMD_INFINITY;
+                    info->m_upperLimit[srow] = 0;
+                }
+                // deal with bounce
+                if (limot->m_bounce > 0)
+                {
+                    // calculate joint velocity
+                    btScalar vel;
+                    if (rotational)
+                    {
+                        vel = angVelA.dot(ax1);
+//make sure that if no body -> angVelB == zero vec
+//                        if (body1)
+                            vel -= angVelB.dot(ax1);
+                    }
+                    else
+                    {
+                        vel = linVelA.dot(ax1);
+//make sure that if no body -> angVelB == zero vec
+//                        if (body1)
+                            vel -= linVelB.dot(ax1);
+                    }
+                    // only apply bounce if the velocity is incoming, and if the
+                    // resulting c[] exceeds what we already have.
+                    if (limit == 1)
+                    {
+                        if (vel < 0)
+                        {
+                            btScalar newc = -limot->m_bounce* vel;
+                            if (newc > info->m_constraintError[srow]) 
+								info->m_constraintError[srow] = newc;
+                        }
+                    }
+                    else
+                    {
+                        if (vel > 0)
+                        {
+                            btScalar newc = -limot->m_bounce * vel;
+                            if (newc < info->m_constraintError[srow]) 
+								info->m_constraintError[srow] = newc;
+                        }
+                    }
+                }
+            }
+        }
+        return 1;
+    }
+    else return 0;
+}
+
+
+
+
+
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
+{
+	if((axis >= 0) && (axis < 3))
+	{
+		switch(num)
+		{
+			case BT_CONSTRAINT_STOP_ERP : 
+				m_linearLimits.m_stopERP[axis] = value;
+				m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+				break;
+			case BT_CONSTRAINT_STOP_CFM : 
+				m_linearLimits.m_stopCFM[axis] = value;
+				m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+				break;
+			case BT_CONSTRAINT_CFM : 
+				m_linearLimits.m_normalCFM[axis] = value;
+				m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+				break;
+			default : 
+				btAssertConstrParams(0);
+		}
+	}
+	else if((axis >=3) && (axis < 6))
+	{
+		switch(num)
+		{
+			case BT_CONSTRAINT_STOP_ERP : 
+				m_angularLimits[axis - 3].m_stopERP = value;
+				m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+				break;
+			case BT_CONSTRAINT_STOP_CFM : 
+				m_angularLimits[axis - 3].m_stopCFM = value;
+				m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+				break;
+			case BT_CONSTRAINT_CFM : 
+				m_angularLimits[axis - 3].m_normalCFM = value;
+				m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
+				break;
+			default : 
+				btAssertConstrParams(0);
+		}
+	}
+	else
+	{
+		btAssertConstrParams(0);
+	}
+}
+
+	///return the local value of parameter
+btScalar btGeneric6DofConstraint::getParam(int num, int axis) const 
+{
+	btScalar retVal = 0;
+	if((axis >= 0) && (axis < 3))
+	{
+		switch(num)
+		{
+			case BT_CONSTRAINT_STOP_ERP : 
+				btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+				retVal = m_linearLimits.m_stopERP[axis];
+				break;
+			case BT_CONSTRAINT_STOP_CFM : 
+				btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+				retVal = m_linearLimits.m_stopCFM[axis];
+				break;
+			case BT_CONSTRAINT_CFM : 
+				btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+				retVal = m_linearLimits.m_normalCFM[axis];
+				break;
+			default : 
+				btAssertConstrParams(0);
+		}
+	}
+	else if((axis >=3) && (axis < 6))
+	{
+		switch(num)
+		{
+			case BT_CONSTRAINT_STOP_ERP : 
+				btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+				retVal = m_angularLimits[axis - 3].m_stopERP;
+				break;
+			case BT_CONSTRAINT_STOP_CFM : 
+				btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+				retVal = m_angularLimits[axis - 3].m_stopCFM;
+				break;
+			case BT_CONSTRAINT_CFM : 
+				btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
+				retVal = m_angularLimits[axis - 3].m_normalCFM;
+				break;
+			default : 
+				btAssertConstrParams(0);
+		}
+	}
+	else
+	{
+		btAssertConstrParams(0);
+	}
+	return retVal;
+}
+
+ 
+
+void btGeneric6DofConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+	btVector3 zAxis = axis1.normalized();
+	btVector3 yAxis = axis2.normalized();
+	btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+	
+	btTransform frameInW;
+	frameInW.setIdentity();
+	frameInW.getBasis().setValue(	xAxis[0], yAxis[0], zAxis[0],	
+	                                xAxis[1], yAxis[1], zAxis[1],
+	                               xAxis[2], yAxis[2], zAxis[2]);
+	
+	// now get constraint frame in local coordinate systems
+	m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+	m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+	
+	calculateTransforms();
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h	(revision 11817)
@@ -0,0 +1,614 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
+/// Added support for generic constraint solver through getInfo1/getInfo2 methods
+
+/*
+2007-09-09
+btGeneric6DofConstraint Refactored by Francisco Le?n
+email: projectileman@yahoo.com
+http://gimpact.sf.net
+*/
+
+
+#ifndef BT_GENERIC_6DOF_CONSTRAINT_H
+#define BT_GENERIC_6DOF_CONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+
+
+
+//! Rotation Limit structure for generic joints
+class btRotationalLimitMotor
+{
+public:
+    //! limit_parameters
+    //!@{
+    btScalar m_loLimit;//!< joint limit
+    btScalar m_hiLimit;//!< joint limit
+    btScalar m_targetVelocity;//!< target motor velocity
+    btScalar m_maxMotorForce;//!< max force on motor
+    btScalar m_maxLimitForce;//!< max force on limit
+    btScalar m_damping;//!< Damping.
+    btScalar m_limitSoftness;//! Relaxation factor
+    btScalar m_normalCFM;//!< Constraint force mixing factor
+    btScalar m_stopERP;//!< Error tolerance factor when joint is at limit
+    btScalar m_stopCFM;//!< Constraint force mixing factor when joint is at limit
+    btScalar m_bounce;//!< restitution factor
+    bool m_enableMotor;
+
+    //!@}
+
+    //! temp_variables
+    //!@{
+    btScalar m_currentLimitError;//!  How much is violated this limit
+    btScalar m_currentPosition;     //!  current value of angle 
+    int m_currentLimit;//!< 0=free, 1=at lo limit, 2=at hi limit
+    btScalar m_accumulatedImpulse;
+    //!@}
+
+    btRotationalLimitMotor()
+    {
+    	m_accumulatedImpulse = 0.f;
+        m_targetVelocity = 0;
+        m_maxMotorForce = 0.1f;
+        m_maxLimitForce = 300.0f;
+        m_loLimit = 1.0f;
+        m_hiLimit = -1.0f;
+		m_normalCFM = 0.f;
+		m_stopERP = 0.2f;
+		m_stopCFM = 0.f;
+        m_bounce = 0.0f;
+        m_damping = 1.0f;
+        m_limitSoftness = 0.5f;
+        m_currentLimit = 0;
+        m_currentLimitError = 0;
+        m_enableMotor = false;
+    }
+
+    btRotationalLimitMotor(const btRotationalLimitMotor & limot)
+    {
+        m_targetVelocity = limot.m_targetVelocity;
+        m_maxMotorForce = limot.m_maxMotorForce;
+        m_limitSoftness = limot.m_limitSoftness;
+        m_loLimit = limot.m_loLimit;
+        m_hiLimit = limot.m_hiLimit;
+		m_normalCFM = limot.m_normalCFM;
+		m_stopERP = limot.m_stopERP;
+		m_stopCFM =	limot.m_stopCFM;
+        m_bounce = limot.m_bounce;
+        m_currentLimit = limot.m_currentLimit;
+        m_currentLimitError = limot.m_currentLimitError;
+        m_enableMotor = limot.m_enableMotor;
+    }
+
+
+
+	//! Is limited
+    bool isLimited()
+    {
+    	if(m_loLimit > m_hiLimit) return false;
+    	return true;
+    }
+
+	//! Need apply correction
+    bool needApplyTorques()
+    {
+    	if(m_currentLimit == 0 && m_enableMotor == false) return false;
+    	return true;
+    }
+
+	//! calculates  error
+	/*!
+	calculates m_currentLimit and m_currentLimitError.
+	*/
+	int testLimitValue(btScalar test_value);
+
+	//! apply the correction impulses for two bodies
+    btScalar solveAngularLimits(btScalar timeStep,btVector3& axis, btScalar jacDiagABInv,btRigidBody * body0, btRigidBody * body1);
+
+};
+
+
+
+class btTranslationalLimitMotor
+{
+public:
+	btVector3 m_lowerLimit;//!< the constraint lower limits
+    btVector3 m_upperLimit;//!< the constraint upper limits
+    btVector3 m_accumulatedImpulse;
+    //! Linear_Limit_parameters
+    //!@{
+    btScalar	m_limitSoftness;//!< Softness for linear limit
+    btScalar	m_damping;//!< Damping for linear limit
+    btScalar	m_restitution;//! Bounce parameter for linear limit
+	btVector3	m_normalCFM;//!< Constraint force mixing factor
+    btVector3	m_stopERP;//!< Error tolerance factor when joint is at limit
+	btVector3	m_stopCFM;//!< Constraint force mixing factor when joint is at limit
+    //!@}
+	bool		m_enableMotor[3];
+    btVector3	m_targetVelocity;//!< target motor velocity
+    btVector3	m_maxMotorForce;//!< max force on motor
+    btVector3	m_currentLimitError;//!  How much is violated this limit
+    btVector3	m_currentLinearDiff;//!  Current relative offset of constraint frames
+    int			m_currentLimit[3];//!< 0=free, 1=at lower limit, 2=at upper limit
+
+    btTranslationalLimitMotor()
+    {
+    	m_lowerLimit.setValue(0.f,0.f,0.f);
+    	m_upperLimit.setValue(0.f,0.f,0.f);
+    	m_accumulatedImpulse.setValue(0.f,0.f,0.f);
+		m_normalCFM.setValue(0.f, 0.f, 0.f);
+		m_stopERP.setValue(0.2f, 0.2f, 0.2f);
+		m_stopCFM.setValue(0.f, 0.f, 0.f);
+
+    	m_limitSoftness = 0.7f;
+    	m_damping = btScalar(1.0f);
+    	m_restitution = btScalar(0.5f);
+		for(int i=0; i < 3; i++) 
+		{
+			m_enableMotor[i] = false;
+			m_targetVelocity[i] = btScalar(0.f);
+			m_maxMotorForce[i] = btScalar(0.f);
+		}
+    }
+
+    btTranslationalLimitMotor(const btTranslationalLimitMotor & other )
+    {
+    	m_lowerLimit = other.m_lowerLimit;
+    	m_upperLimit = other.m_upperLimit;
+    	m_accumulatedImpulse = other.m_accumulatedImpulse;
+
+    	m_limitSoftness = other.m_limitSoftness ;
+    	m_damping = other.m_damping;
+    	m_restitution = other.m_restitution;
+		m_normalCFM = other.m_normalCFM;
+		m_stopERP = other.m_stopERP;
+		m_stopCFM = other.m_stopCFM;
+
+		for(int i=0; i < 3; i++) 
+		{
+			m_enableMotor[i] = other.m_enableMotor[i];
+			m_targetVelocity[i] = other.m_targetVelocity[i];
+			m_maxMotorForce[i] = other.m_maxMotorForce[i];
+		}
+    }
+
+    //! Test limit
+	/*!
+    - free means upper < lower,
+    - locked means upper == lower
+    - limited means upper > lower
+    - limitIndex: first 3 are linear, next 3 are angular
+    */
+    inline bool	isLimited(int limitIndex)
+    {
+       return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
+    }
+    inline bool needApplyForce(int limitIndex)
+    {
+    	if(m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
+    	return true;
+    }
+	int testLimitValue(int limitIndex, btScalar test_value);
+
+
+    btScalar solveLinearAxis(
+    	btScalar timeStep,
+        btScalar jacDiagABInv,
+        btRigidBody& body1,const btVector3 &pointInA,
+        btRigidBody& body2,const btVector3 &pointInB,
+        int limit_index,
+        const btVector3 & axis_normal_on_a,
+		const btVector3 & anchorPos);
+
+
+};
+
+enum bt6DofFlags
+{
+	BT_6DOF_FLAGS_CFM_NORM = 1,
+	BT_6DOF_FLAGS_CFM_STOP = 2,
+	BT_6DOF_FLAGS_ERP_STOP = 4
+};
+#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
+
+
+/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/*!
+btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'.
+currently this limit supports rotational motors<br>
+<ul>
+<li> For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method.
+At this moment translational motors are not supported. May be in the future. </li>
+
+<li> For Angular limits, use the btRotationalLimitMotor structure for configuring the limit.
+This is accessible through btGeneric6DofConstraint.getLimitMotor method,
+This brings support for limit parameters and motors. </li>
+
+<li> Angulars limits have these possible ranges:
+<table border=1 >
+<tr>
+	<td><b>AXIS</b></td>
+	<td><b>MIN ANGLE</b></td>
+	<td><b>MAX ANGLE</b></td>
+</tr><tr>
+	<td>X</td>
+	<td>-PI</td>
+	<td>PI</td>
+</tr><tr>
+	<td>Y</td>
+	<td>-PI/2</td>
+	<td>PI/2</td>
+</tr><tr>
+	<td>Z</td>
+	<td>-PI</td>
+	<td>PI</td>
+</tr>
+</table>
+</li>
+</ul>
+
+*/
+class btGeneric6DofConstraint : public btTypedConstraint
+{
+protected:
+
+	//! relative_frames
+    //!@{
+	btTransform	m_frameInA;//!< the constraint space w.r.t body A
+    btTransform	m_frameInB;//!< the constraint space w.r.t body B
+    //!@}
+
+    //! Jacobians
+    //!@{
+    btJacobianEntry	m_jacLinear[3];//!< 3 orthogonal linear constraints
+    btJacobianEntry	m_jacAng[3];//!< 3 orthogonal angular constraints
+    //!@}
+
+	//! Linear_Limit_parameters
+    //!@{
+    btTranslationalLimitMotor m_linearLimits;
+    //!@}
+
+
+    //! hinge_parameters
+    //!@{
+    btRotationalLimitMotor m_angularLimits[3];
+	//!@}
+
+
+protected:
+    //! temporal variables
+    //!@{
+    btScalar m_timeStep;
+    btTransform m_calculatedTransformA;
+    btTransform m_calculatedTransformB;
+    btVector3 m_calculatedAxisAngleDiff;
+    btVector3 m_calculatedAxis[3];
+    btVector3 m_calculatedLinearDiff;
+	btScalar	m_factA;
+	btScalar	m_factB;
+	bool		m_hasStaticBody;
+    
+	btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
+
+    bool	m_useLinearReferenceFrameA;
+	bool	m_useOffsetForConstraintFrame;
+    
+	int		m_flags;
+
+    //!@}
+
+    btGeneric6DofConstraint&	operator=(btGeneric6DofConstraint&	other)
+    {
+        btAssert(0);
+        (void) other;
+        return *this;
+    }
+
+
+	int setAngularLimits(btConstraintInfo2 *info, int row_offset,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+	int setLinearLimits(btConstraintInfo2 *info, int row, const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+    void buildLinearJacobian(
+        btJacobianEntry & jacLinear,const btVector3 & normalWorld,
+        const btVector3 & pivotAInW,const btVector3 & pivotBInW);
+
+    void buildAngularJacobian(btJacobianEntry & jacAngular,const btVector3 & jointAxisW);
+
+	// tests linear limits
+	void calculateLinearInfo();
+
+	//! calcs the euler angles between the two bodies.
+    void calculateAngleInfo();
+
+
+
+public:
+
+	///for backwards compatibility during the transition to 'getInfo/getInfo2'
+	bool		m_useSolveConstraintObsolete;
+
+    btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+    btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+    
+	//! Calcs global transform of the offsets
+	/*!
+	Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
+	\sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo
+	*/
+    void calculateTransforms(const btTransform& transA,const btTransform& transB);
+
+	void calculateTransforms();
+
+	//! Gets the global transform of the offset for body A
+    /*!
+    \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
+    */
+    const btTransform & getCalculatedTransformA() const
+    {
+    	return m_calculatedTransformA;
+    }
+
+    //! Gets the global transform of the offset for body B
+    /*!
+    \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
+    */
+    const btTransform & getCalculatedTransformB() const
+    {
+    	return m_calculatedTransformB;
+    }
+
+    const btTransform & getFrameOffsetA() const
+    {
+    	return m_frameInA;
+    }
+
+    const btTransform & getFrameOffsetB() const
+    {
+    	return m_frameInB;
+    }
+
+
+    btTransform & getFrameOffsetA()
+    {
+    	return m_frameInA;
+    }
+
+    btTransform & getFrameOffsetB()
+    {
+    	return m_frameInB;
+    }
+
+
+	//! performs Jacobian calculation, and also calculates angle differences and axis
+    virtual void	buildJacobian();
+
+	virtual void getInfo1 (btConstraintInfo1* info);
+
+	void getInfo1NonVirtual (btConstraintInfo1* info);
+
+	virtual void getInfo2 (btConstraintInfo2* info);
+
+	void getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB);
+
+
+    void	updateRHS(btScalar	timeStep);
+
+	//! Get the rotation axis in global coordinates
+	/*!
+	\pre btGeneric6DofConstraint.buildJacobian must be called previously.
+	*/
+    btVector3 getAxis(int axis_index) const;
+
+    //! Get the relative Euler angle
+    /*!
+	\pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+	*/
+    btScalar getAngle(int axis_index) const;
+
+	//! Get the relative position of the constraint pivot
+    /*!
+	\pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+	*/
+	btScalar getRelativePivotPosition(int axis_index) const;
+
+	void setFrames(const btTransform & frameA, const btTransform & frameB);
+
+	//! Test angular limit.
+	/*!
+	Calculates angular correction and returns true if limit needs to be corrected.
+	\pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
+	*/
+    bool testAngularLimitMotor(int axis_index);
+
+    void	setLinearLowerLimit(const btVector3& linearLower)
+    {
+    	m_linearLimits.m_lowerLimit = linearLower;
+    }
+
+	void	getLinearLowerLimit(btVector3& linearLower)
+	{
+		linearLower = m_linearLimits.m_lowerLimit;
+	}
+
+	void	setLinearUpperLimit(const btVector3& linearUpper)
+	{
+		m_linearLimits.m_upperLimit = linearUpper;
+	}
+
+	void	getLinearUpperLimit(btVector3& linearUpper)
+	{
+		linearUpper = m_linearLimits.m_upperLimit;
+	}
+
+    void	setAngularLowerLimit(const btVector3& angularLower)
+    {
+		for(int i = 0; i < 3; i++) 
+			m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
+    }
+
+	void	getAngularLowerLimit(btVector3& angularLower)
+	{
+		for(int i = 0; i < 3; i++) 
+			angularLower[i] = m_angularLimits[i].m_loLimit;
+	}
+
+    void	setAngularUpperLimit(const btVector3& angularUpper)
+    {
+		for(int i = 0; i < 3; i++)
+			m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
+    }
+
+	void	getAngularUpperLimit(btVector3& angularUpper)
+	{
+		for(int i = 0; i < 3; i++)
+			angularUpper[i] = m_angularLimits[i].m_hiLimit;
+	}
+
+	//! Retrieves the angular limit informacion
+    btRotationalLimitMotor * getRotationalLimitMotor(int index)
+    {
+    	return &m_angularLimits[index];
+    }
+
+    //! Retrieves the  limit informacion
+    btTranslationalLimitMotor * getTranslationalLimitMotor()
+    {
+    	return &m_linearLimits;
+    }
+
+    //first 3 are linear, next 3 are angular
+    void setLimit(int axis, btScalar lo, btScalar hi)
+    {
+    	if(axis<3)
+    	{
+    		m_linearLimits.m_lowerLimit[axis] = lo;
+    		m_linearLimits.m_upperLimit[axis] = hi;
+    	}
+    	else
+    	{
+			lo = btNormalizeAngle(lo);
+			hi = btNormalizeAngle(hi);
+    		m_angularLimits[axis-3].m_loLimit = lo;
+    		m_angularLimits[axis-3].m_hiLimit = hi;
+    	}
+    }
+
+	//! Test limit
+	/*!
+    - free means upper < lower,
+    - locked means upper == lower
+    - limited means upper > lower
+    - limitIndex: first 3 are linear, next 3 are angular
+    */
+    bool	isLimited(int limitIndex)
+    {
+    	if(limitIndex<3)
+    	{
+			return m_linearLimits.isLimited(limitIndex);
+
+    	}
+        return m_angularLimits[limitIndex-3].isLimited();
+    }
+
+	virtual void calcAnchorPos(void); // overridable
+
+	int get_limit_motor_info2(	btRotationalLimitMotor * limot,
+								const btTransform& transA,const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB,const btVector3& angVelA,const btVector3& angVelB,
+								btConstraintInfo2 *info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
+
+	// access for UseFrameOffset
+	bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+	void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+	virtual	void setParam(int num, btScalar value, int axis = -1);
+	///return the local value of parameter
+	virtual	btScalar getParam(int num, int axis = -1) const;
+
+	void setAxis( const btVector3& axis1, const btVector3& axis2);
+
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btGeneric6DofConstraintData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+	btTransformFloatData m_rbBFrame;
+	
+	btVector3FloatData	m_linearUpperLimit;
+	btVector3FloatData	m_linearLowerLimit;
+
+	btVector3FloatData	m_angularUpperLimit;
+	btVector3FloatData	m_angularLowerLimit;
+	
+	int	m_useLinearReferenceFrameA;
+	int m_useOffsetForConstraintFrame;
+};
+
+SIMD_FORCE_INLINE	int	btGeneric6DofConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btGeneric6DofConstraintData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+	btGeneric6DofConstraintData* dof = (btGeneric6DofConstraintData*)dataBuffer;
+	btTypedConstraint::serialize(&dof->m_typeConstraintData,serializer);
+
+	m_frameInA.serializeFloat(dof->m_rbAFrame);
+	m_frameInB.serializeFloat(dof->m_rbBFrame);
+
+		
+	int i;
+	for (i=0;i<3;i++)
+	{
+		dof->m_angularLowerLimit.m_floats[i] =  float(m_angularLimits[i].m_loLimit);
+		dof->m_angularUpperLimit.m_floats[i] =  float(m_angularLimits[i].m_hiLimit);
+		dof->m_linearLowerLimit.m_floats[i] = float(m_linearLimits.m_lowerLimit[i]);
+		dof->m_linearUpperLimit.m_floats[i] = float(m_linearLimits.m_upperLimit[i]);
+	}
+	
+	dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA? 1 : 0;
+	dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0;
+
+	return "btGeneric6DofConstraintData";
+}
+
+
+
+
+
+#endif //BT_GENERIC_6DOF_CONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp	(revision 11817)
@@ -0,0 +1,172 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGeneric6DofSpringConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+
+btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA)
+	: btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA)
+{
+	m_objectType = D6_SPRING_CONSTRAINT_TYPE;
+
+	for(int i = 0; i < 6; i++)
+	{
+		m_springEnabled[i] = false;
+		m_equilibriumPoint[i] = btScalar(0.f);
+		m_springStiffness[i] = btScalar(0.f);
+		m_springDamping[i] = btScalar(1.f);
+	}
+}
+
+
+void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff)
+{
+	btAssert((index >= 0) && (index < 6));
+	m_springEnabled[index] = onOff;
+	if(index < 3)
+	{
+		m_linearLimits.m_enableMotor[index] = onOff;
+	}
+	else
+	{
+		m_angularLimits[index - 3].m_enableMotor = onOff;
+	}
+}
+
+
+
+void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness)
+{
+	btAssert((index >= 0) && (index < 6));
+	m_springStiffness[index] = stiffness;
+}
+
+
+void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping)
+{
+	btAssert((index >= 0) && (index < 6));
+	m_springDamping[index] = damping;
+}
+
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint()
+{
+	calculateTransforms();
+	int i;
+
+	for( i = 0; i < 3; i++)
+	{
+		m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
+	}
+	for(i = 0; i < 3; i++)
+	{
+		m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i];
+	}
+}
+
+
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index)
+{
+	btAssert((index >= 0) && (index < 6));
+	calculateTransforms();
+	if(index < 3)
+	{
+		m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
+	}
+	else
+	{
+		m_equilibriumPoint[index] = m_calculatedAxisAngleDiff[index - 3];
+	}
+}
+
+void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val)
+{
+	btAssert((index >= 0) && (index < 6));
+	m_equilibriumPoint[index] = val;
+}
+
+
+void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info)
+{
+	// it is assumed that calculateTransforms() have been called before this call
+	int i;
+	btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
+	for(i = 0; i < 3; i++)
+	{
+		if(m_springEnabled[i])
+		{
+			// get current position of constraint
+			btScalar currPos = m_calculatedLinearDiff[i];
+			// calculate difference
+			btScalar delta = currPos - m_equilibriumPoint[i];
+			// spring force is (delta * m_stiffness) according to Hooke's Law
+			btScalar force = delta * m_springStiffness[i];
+			btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations);
+			m_linearLimits.m_targetVelocity[i] =  velFactor * force;
+			m_linearLimits.m_maxMotorForce[i] =  btFabs(force) / info->fps;
+		}
+	}
+	for(i = 0; i < 3; i++)
+	{
+		if(m_springEnabled[i + 3])
+		{
+			// get current position of constraint
+			btScalar currPos = m_calculatedAxisAngleDiff[i];
+			// calculate difference
+			btScalar delta = currPos - m_equilibriumPoint[i+3];
+			// spring force is (-delta * m_stiffness) according to Hooke's Law
+			btScalar force = -delta * m_springStiffness[i+3];
+			btScalar velFactor = info->fps * m_springDamping[i+3] / btScalar(info->m_numIterations);
+			m_angularLimits[i].m_targetVelocity = velFactor * force;
+			m_angularLimits[i].m_maxMotorForce = btFabs(force) / info->fps;
+		}
+	}
+}
+
+
+void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info)
+{
+	// this will be called by constraint solver at the constraint setup stage
+	// set current motor parameters
+	internalUpdateSprings(info);
+	// do the rest of job for constraint setup
+	btGeneric6DofConstraint::getInfo2(info);
+}
+
+
+void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+	btVector3 zAxis = axis1.normalized();
+	btVector3 yAxis = axis2.normalized();
+	btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+	btTransform frameInW;
+	frameInW.setIdentity();
+	frameInW.getBasis().setValue(	xAxis[0], yAxis[0], zAxis[0],	
+                                xAxis[1], yAxis[1], zAxis[1],
+                                xAxis[2], yAxis[2], zAxis[2]);
+
+	// now get constraint frame in local coordinate systems
+	m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+	m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+  calculateTransforms();
+}
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
+#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
+
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofConstraint.h"
+
+
+/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF
+
+/// DOF index used in enableSpring() and setStiffness() means:
+/// 0 : translation X
+/// 1 : translation Y
+/// 2 : translation Z
+/// 3 : rotation X (3rd Euler rotational around new position of X axis, range [-PI+epsilon, PI-epsilon] )
+/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] )
+/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] )
+
+class btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
+{
+protected:
+	bool		m_springEnabled[6];
+	btScalar	m_equilibriumPoint[6];
+	btScalar	m_springStiffness[6];
+	btScalar	m_springDamping[6]; // between 0 and 1 (1 == no damping)
+	void internalUpdateSprings(btConstraintInfo2* info);
+public: 
+    btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+	void enableSpring(int index, bool onOff);
+	void setStiffness(int index, btScalar stiffness);
+	void setDamping(int index, btScalar damping);
+	void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
+	void setEquilibriumPoint(int index);  // set the current constraint position/orientation as an equilibrium point for given DOF
+	void setEquilibriumPoint(int index, btScalar val);
+
+	virtual void setAxis( const btVector3& axis1, const btVector3& axis2);
+
+	virtual void getInfo2 (btConstraintInfo2* info);
+
+	virtual	int	calculateSerializeBufferSize() const;
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btGeneric6DofSpringConstraintData
+{
+	btGeneric6DofConstraintData	m_6dofData;
+	
+	int			m_springEnabled[6];
+	float		m_equilibriumPoint[6];
+	float		m_springStiffness[6];
+	float		m_springDamping[6];
+};
+
+SIMD_FORCE_INLINE	int	btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btGeneric6DofSpringConstraintData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btGeneric6DofSpringConstraintData* dof = (btGeneric6DofSpringConstraintData*)dataBuffer;
+	btGeneric6DofConstraint::serialize(&dof->m_6dofData,serializer);
+
+	int i;
+	for (i=0;i<6;i++)
+	{
+		dof->m_equilibriumPoint[i] = m_equilibriumPoint[i];
+		dof->m_springDamping[i] = m_springDamping[i];
+		dof->m_springEnabled[i] = m_springEnabled[i]? 1 : 0;
+		dof->m_springStiffness[i] = m_springStiffness[i];
+	}
+	return "btGeneric6DofConstraintData";
+}
+
+#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btHinge2Constraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+
+
+// constructor
+// anchor, axis1 and axis2 are in world coordinate system
+// axis1 must be orthogonal to axis2
+btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2)
+: btGeneric6DofSpringConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
+ m_anchor(anchor),
+ m_axis1(axis1),
+ m_axis2(axis2)
+{
+	// build frame basis
+	// 6DOF constraint uses Euler angles and to define limits
+	// it is assumed that rotational order is :
+	// Z - first, allowed limits are (-PI,PI);
+	// new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number 
+	// used to prevent constraint from instability on poles;
+	// new position of X, allowed limits are (-PI,PI);
+	// So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
+	// Build the frame in world coordinate system first
+	btVector3 zAxis = axis1.normalize();
+	btVector3 xAxis = axis2.normalize();
+	btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system
+	btTransform frameInW;
+	frameInW.setIdentity();
+	frameInW.getBasis().setValue(	xAxis[0], yAxis[0], zAxis[0],	
+									xAxis[1], yAxis[1], zAxis[1],
+									xAxis[2], yAxis[2], zAxis[2]);
+	frameInW.setOrigin(anchor);
+	// now get constraint frame in local coordinate systems
+	m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
+	m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
+	// sei limits
+	setLinearLowerLimit(btVector3(0.f, 0.f, -1.f));
+	setLinearUpperLimit(btVector3(0.f, 0.f,  1.f));
+	// like front wheels of a car
+	setAngularLowerLimit(btVector3(1.f,  0.f, -SIMD_HALF_PI * 0.5f)); 
+	setAngularUpperLimit(btVector3(-1.f, 0.f,  SIMD_HALF_PI * 0.5f));
+	// enable suspension
+	enableSpring(2, true);
+	setStiffness(2, SIMD_PI * SIMD_PI * 4.f); // period 1 sec for 1 kilogramm weel :-)
+	setDamping(2, 0.01f);
+	setEquilibriumPoint();
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_HINGE2_CONSTRAINT_H
+#define BT_HINGE2_CONSTRAINT_H
+
+
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofSpringConstraint.h"
+
+
+
+// Constraint similar to ODE Hinge2 Joint
+// has 3 degrees of frredom:
+// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2)
+// 1 translational (along axis Z) with suspension spring
+
+class btHinge2Constraint : public btGeneric6DofSpringConstraint
+{
+protected:
+	btVector3	m_anchor;
+	btVector3	m_axis1;
+	btVector3	m_axis2;
+public:
+	// constructor
+	// anchor, axis1 and axis2 are in world coordinate system
+	// axis1 must be orthogonal to axis2
+    btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2);
+	// access
+	const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
+	const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
+	const btVector3& getAxis1() { return m_axis1; }
+	const btVector3& getAxis2() { return m_axis2; }
+	btScalar getAngle1() { return getAngle(2); }
+	btScalar getAngle2() { return getAngle(0); }
+	// limits
+	void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); }
+	void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3( 1.f, 0.f, ang1min)); }
+};
+
+
+
+#endif // BT_HINGE2_CONSTRAINT_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp	(revision 11817)
@@ -0,0 +1,1033 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btHingeConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMinMax.h"
+#include <new>
+#include "btSolverBody.h"
+
+
+
+//#define HINGE_USE_OBSOLETE_SOLVER false
+#define HINGE_USE_OBSOLETE_SOLVER false
+
+#define HINGE_USE_FRAME_OFFSET true
+
+#ifndef __SPU__
+
+
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
+									 const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA)
+									 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),
+									 m_angularOnly(false),
+									 m_enableAngularMotor(false),
+									 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+									 m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+									 m_useReferenceFrameA(useReferenceFrameA),
+									 m_flags(0)
+#ifdef _BT_USE_CENTER_LIMIT_
+									,m_limit()
+#endif
+{
+	m_rbAFrame.getOrigin() = pivotInA;
+	
+	// since no frame is given, assume this to be zero angle and just pick rb transform axis
+	btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0);
+
+	btVector3 rbAxisA2;
+	btScalar projection = axisInA.dot(rbAxisA1);
+	if (projection >= 1.0f - SIMD_EPSILON) {
+		rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
+		rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
+	} else if (projection <= -1.0f + SIMD_EPSILON) {
+		rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
+		rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);      
+	} else {
+		rbAxisA2 = axisInA.cross(rbAxisA1);
+		rbAxisA1 = rbAxisA2.cross(axisInA);
+	}
+
+	m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
+									rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
+									rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+
+	btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
+	btVector3 rbAxisB1 =  quatRotate(rotationArc,rbAxisA1);
+	btVector3 rbAxisB2 =  axisInB.cross(rbAxisB1);	
+	
+	m_rbBFrame.getOrigin() = pivotInB;
+	m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
+									rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
+									rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+	
+#ifndef	_BT_USE_CENTER_LIMIT_
+	//start with free
+	m_lowerLimit = btScalar(1.0f);
+	m_upperLimit = btScalar(-1.0f);
+	m_biasFactor = 0.3f;
+	m_relaxationFactor = 1.0f;
+	m_limitSoftness = 0.9f;
+	m_solveLimit = false;
+#endif
+	m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA)
+:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false), 
+m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+m_useReferenceFrameA(useReferenceFrameA),
+m_flags(0)
+#ifdef	_BT_USE_CENTER_LIMIT_
+,m_limit()
+#endif
+{
+
+	// since no frame is given, assume this to be zero angle and just pick rb transform axis
+	// fixed axis in worldspace
+	btVector3 rbAxisA1, rbAxisA2;
+	btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
+
+	m_rbAFrame.getOrigin() = pivotInA;
+	m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
+									rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
+									rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+
+	btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
+
+	btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
+	btVector3 rbAxisB1 =  quatRotate(rotationArc,rbAxisA1);
+	btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
+
+
+	m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA);
+	m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
+									rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
+									rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+	
+#ifndef	_BT_USE_CENTER_LIMIT_
+	//start with free
+	m_lowerLimit = btScalar(1.0f);
+	m_upperLimit = btScalar(-1.0f);
+	m_biasFactor = 0.3f;
+	m_relaxationFactor = 1.0f;
+	m_limitSoftness = 0.9f;
+	m_solveLimit = false;
+#endif
+	m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, 
+								     const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
+:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
+m_angularOnly(false),
+m_enableAngularMotor(false),
+m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+m_useReferenceFrameA(useReferenceFrameA),
+m_flags(0)
+#ifdef	_BT_USE_CENTER_LIMIT_
+,m_limit()
+#endif
+{
+#ifndef	_BT_USE_CENTER_LIMIT_
+	//start with free
+	m_lowerLimit = btScalar(1.0f);
+	m_upperLimit = btScalar(-1.0f);
+	m_biasFactor = 0.3f;
+	m_relaxationFactor = 1.0f;
+	m_limitSoftness = 0.9f;
+	m_solveLimit = false;
+#endif
+	m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}			
+
+
+
+btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
+:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
+m_angularOnly(false),
+m_enableAngularMotor(false),
+m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
+m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
+m_useReferenceFrameA(useReferenceFrameA),
+m_flags(0)
+#ifdef	_BT_USE_CENTER_LIMIT_
+,m_limit()
+#endif
+{
+	///not providing rigidbody B means implicitly using worldspace for body B
+
+	m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
+#ifndef	_BT_USE_CENTER_LIMIT_
+	//start with free
+	m_lowerLimit = btScalar(1.0f);
+	m_upperLimit = btScalar(-1.0f);
+	m_biasFactor = 0.3f;
+	m_relaxationFactor = 1.0f;
+	m_limitSoftness = 0.9f;
+	m_solveLimit = false;
+#endif
+	m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
+}
+
+
+
+void	btHingeConstraint::buildJacobian()
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		m_appliedImpulse = btScalar(0.);
+		m_accMotorImpulse = btScalar(0.);
+
+		if (!m_angularOnly)
+		{
+			btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
+			btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
+			btVector3 relPos = pivotBInW - pivotAInW;
+
+			btVector3 normal[3];
+			if (relPos.length2() > SIMD_EPSILON)
+			{
+				normal[0] = relPos.normalized();
+			}
+			else
+			{
+				normal[0].setValue(btScalar(1.0),0,0);
+			}
+
+			btPlaneSpace1(normal[0], normal[1], normal[2]);
+
+			for (int i=0;i<3;i++)
+			{
+				new (&m_jac[i]) btJacobianEntry(
+				m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+				m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+				pivotAInW - m_rbA.getCenterOfMassPosition(),
+				pivotBInW - m_rbB.getCenterOfMassPosition(),
+				normal[i],
+				m_rbA.getInvInertiaDiagLocal(),
+				m_rbA.getInvMass(),
+				m_rbB.getInvInertiaDiagLocal(),
+				m_rbB.getInvMass());
+			}
+		}
+
+		//calculate two perpendicular jointAxis, orthogonal to hingeAxis
+		//these two jointAxis require equal angular velocities for both bodies
+
+		//this is unused for now, it's a todo
+		btVector3 jointAxis0local;
+		btVector3 jointAxis1local;
+		
+		btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local);
+
+		btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
+		btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
+		btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
+			
+		new (&m_jacAng[0])	btJacobianEntry(jointAxis0,
+			m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbA.getInvInertiaDiagLocal(),
+			m_rbB.getInvInertiaDiagLocal());
+
+		new (&m_jacAng[1])	btJacobianEntry(jointAxis1,
+			m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbA.getInvInertiaDiagLocal(),
+			m_rbB.getInvInertiaDiagLocal());
+
+		new (&m_jacAng[2])	btJacobianEntry(hingeAxisWorld,
+			m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbA.getInvInertiaDiagLocal(),
+			m_rbB.getInvInertiaDiagLocal());
+
+			// clear accumulator
+			m_accLimitImpulse = btScalar(0.);
+
+			// test angular limit
+			testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+
+		//Compute K = J*W*J' for hinge axis
+		btVector3 axisA =  getRigidBodyA().getCenterOfMassTransform().getBasis() *  m_rbAFrame.getBasis().getColumn(2);
+		m_kHinge =   1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
+							 getRigidBodyB().computeAngularImpulseDenominator(axisA));
+
+	}
+}
+
+
+#endif //__SPU__
+
+
+void btHingeConstraint::getInfo1(btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	}
+	else
+	{
+		info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
+		info->nub = 1; 
+		//always add the row, to avoid computation (data is not available yet)
+		//prepare constraint
+		testLimit(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+		if(getSolveLimit() || getEnableAngularMotor())
+		{
+			info->m_numConstraintRows++; // limit 3rd anguar as well
+			info->nub--; 
+		}
+
+	}
+}
+
+void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	}
+	else
+	{
+		//always add the 'limit' row, to avoid computation (data is not available yet)
+		info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
+		info->nub = 0; 
+	}
+}
+
+void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
+{
+	if(m_useOffsetForConstraintFrame)
+	{
+		getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
+	}
+	else
+	{
+		getInfo2Internal(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(),m_rbA.getAngularVelocity(),m_rbB.getAngularVelocity());
+	}
+}
+
+
+void	btHingeConstraint::getInfo2NonVirtual (btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+{
+	///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now
+	testLimit(transA,transB);
+
+	getInfo2Internal(info,transA,transB,angVelA,angVelB);
+}
+
+
+void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+{
+
+	btAssert(!m_useSolveConstraintObsolete);
+	int i, skip = info->rowskip;
+	// transforms in world space
+	btTransform trA = transA*m_rbAFrame;
+	btTransform trB = transB*m_rbBFrame;
+	// pivot point
+	btVector3 pivotAInW = trA.getOrigin();
+	btVector3 pivotBInW = trB.getOrigin();
+#if 0
+	if (0)
+	{
+		for (i=0;i<6;i++)
+		{
+			info->m_J1linearAxis[i*skip]=0;
+			info->m_J1linearAxis[i*skip+1]=0;
+			info->m_J1linearAxis[i*skip+2]=0;
+
+			info->m_J1angularAxis[i*skip]=0;
+			info->m_J1angularAxis[i*skip+1]=0;
+			info->m_J1angularAxis[i*skip+2]=0;
+
+			info->m_J2angularAxis[i*skip]=0;
+			info->m_J2angularAxis[i*skip+1]=0;
+			info->m_J2angularAxis[i*skip+2]=0;
+
+			info->m_constraintError[i*skip]=0.f;
+		}
+	}
+#endif //#if 0
+	// linear (all fixed)
+
+	if (!m_angularOnly)
+	{
+		info->m_J1linearAxis[0] = 1;
+		info->m_J1linearAxis[skip + 1] = 1;
+		info->m_J1linearAxis[2 * skip + 2] = 1;
+	}	
+
+
+
+
+	btVector3 a1 = pivotAInW - transA.getOrigin();
+	{
+		btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+		btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
+		btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
+		btVector3 a1neg = -a1;
+		a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+	}
+	btVector3 a2 = pivotBInW - transB.getOrigin();
+	{
+		btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+		btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
+		btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
+		a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+	}
+	// linear RHS
+    btScalar k = info->fps * info->erp;
+	if (!m_angularOnly)
+	{
+		for(i = 0; i < 3; i++)
+		{
+			info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
+		}
+	}
+	// make rotations around X and Y equal
+	// the hinge axis should be the only unconstrained
+	// rotational axis, the angular velocity of the two bodies perpendicular to
+	// the hinge axis should be equal. thus the constraint equations are
+	//    p*w1 - p*w2 = 0
+	//    q*w1 - q*w2 = 0
+	// where p and q are unit vectors normal to the hinge axis, and w1 and w2
+	// are the angular velocity vectors of the two bodies.
+	// get hinge axis (Z)
+	btVector3 ax1 = trA.getBasis().getColumn(2);
+	// get 2 orthos to hinge axis (X, Y)
+	btVector3 p = trA.getBasis().getColumn(0);
+	btVector3 q = trA.getBasis().getColumn(1);
+	// set the two hinge angular rows 
+    int s3 = 3 * info->rowskip;
+    int s4 = 4 * info->rowskip;
+
+	info->m_J1angularAxis[s3 + 0] = p[0];
+	info->m_J1angularAxis[s3 + 1] = p[1];
+	info->m_J1angularAxis[s3 + 2] = p[2];
+	info->m_J1angularAxis[s4 + 0] = q[0];
+	info->m_J1angularAxis[s4 + 1] = q[1];
+	info->m_J1angularAxis[s4 + 2] = q[2];
+
+	info->m_J2angularAxis[s3 + 0] = -p[0];
+	info->m_J2angularAxis[s3 + 1] = -p[1];
+	info->m_J2angularAxis[s3 + 2] = -p[2];
+	info->m_J2angularAxis[s4 + 0] = -q[0];
+	info->m_J2angularAxis[s4 + 1] = -q[1];
+	info->m_J2angularAxis[s4 + 2] = -q[2];
+    // compute the right hand side of the constraint equation. set relative
+    // body velocities along p and q to bring the hinge back into alignment.
+    // if ax1,ax2 are the unit length hinge axes as computed from body1 and
+    // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
+    // if `theta' is the angle between ax1 and ax2, we need an angular velocity
+    // along u to cover angle erp*theta in one step :
+    //   |angular_velocity| = angle/time = erp*theta / stepsize
+    //                      = (erp*fps) * theta
+    //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+    //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+    // ...as ax1 and ax2 are unit length. if theta is smallish,
+    // theta ~= sin(theta), so
+    //    angular_velocity  = (erp*fps) * (ax1 x ax2)
+    // ax1 x ax2 is in the plane space of ax1, so we project the angular
+    // velocity to p and q to find the right hand side.
+    btVector3 ax2 = trB.getBasis().getColumn(2);
+	btVector3 u = ax1.cross(ax2);
+	info->m_constraintError[s3] = k * u.dot(p);
+	info->m_constraintError[s4] = k * u.dot(q);
+	// check angular limits
+	int nrow = 4; // last filled row
+	int srow;
+	btScalar limit_err = btScalar(0.0);
+	int limit = 0;
+	if(getSolveLimit())
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	limit_err = m_limit.getCorrection() * m_referenceSign;
+#else
+	limit_err = m_correction * m_referenceSign;
+#endif
+	limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+
+	}
+	// if the hinge has joint limits or motor, add in the extra row
+	int powered = 0;
+	if(getEnableAngularMotor())
+	{
+		powered = 1;
+	}
+	if(limit || powered) 
+	{
+		nrow++;
+		srow = nrow * info->rowskip;
+		info->m_J1angularAxis[srow+0] = ax1[0];
+		info->m_J1angularAxis[srow+1] = ax1[1];
+		info->m_J1angularAxis[srow+2] = ax1[2];
+
+		info->m_J2angularAxis[srow+0] = -ax1[0];
+		info->m_J2angularAxis[srow+1] = -ax1[1];
+		info->m_J2angularAxis[srow+2] = -ax1[2];
+
+		btScalar lostop = getLowerLimit();
+		btScalar histop = getUpperLimit();
+		if(limit && (lostop == histop))
+		{  // the joint motor is ineffective
+			powered = 0;
+		}
+		info->m_constraintError[srow] = btScalar(0.0f);
+		btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp;
+		if(powered)
+		{
+			if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
+			{
+				info->cfm[srow] = m_normalCFM;
+			}
+			btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
+			info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
+			info->m_lowerLimit[srow] = - m_maxMotorImpulse;
+			info->m_upperLimit[srow] =   m_maxMotorImpulse;
+		}
+		if(limit)
+		{
+			k = info->fps * currERP;
+			info->m_constraintError[srow] += k * limit_err;
+			if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
+			{
+				info->cfm[srow] = m_stopCFM;
+			}
+			if(lostop == histop) 
+			{
+				// limited low and high simultaneously
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else if(limit == 1) 
+			{ // low limit
+				info->m_lowerLimit[srow] = 0;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else 
+			{ // high limit
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = 0;
+			}
+			// bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+#ifdef	_BT_USE_CENTER_LIMIT_
+			btScalar bounce = m_limit.getRelaxationFactor();
+#else
+			btScalar bounce = m_relaxationFactor;
+#endif
+			if(bounce > btScalar(0.0))
+			{
+				btScalar vel = angVelA.dot(ax1);
+				vel -= angVelB.dot(ax1);
+				// only apply bounce if the velocity is incoming, and if the
+				// resulting c[] exceeds what we already have.
+				if(limit == 1)
+				{	// low limit
+					if(vel < 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc > info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+				else
+				{	// high limit - all those computations are reversed
+					if(vel > 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc < info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+			}
+#ifdef	_BT_USE_CENTER_LIMIT_
+			info->m_constraintError[srow] *= m_limit.getBiasFactor();
+#else
+			info->m_constraintError[srow] *= m_biasFactor;
+#endif
+		} // if(limit)
+	} // if angular limit or powered
+}
+
+
+void btHingeConstraint::setFrames(const btTransform & frameA, const btTransform & frameB)
+{
+	m_rbAFrame = frameA;
+	m_rbBFrame = frameB;
+	buildJacobian();
+}
+
+
+void	btHingeConstraint::updateRHS(btScalar	timeStep)
+{
+	(void)timeStep;
+
+}
+
+
+btScalar btHingeConstraint::getHingeAngle()
+{
+	return getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+btScalar btHingeConstraint::getHingeAngle(const btTransform& transA,const btTransform& transB)
+{
+	const btVector3 refAxis0  = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
+	const btVector3 refAxis1  = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
+	const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
+//	btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+	btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+	return m_referenceSign * angle;
+}
+
+
+
+void btHingeConstraint::testLimit(const btTransform& transA,const btTransform& transB)
+{
+	// Compute limit information
+	m_hingeAngle = getHingeAngle(transA,transB);
+#ifdef	_BT_USE_CENTER_LIMIT_
+	m_limit.test(m_hingeAngle);
+#else
+	m_correction = btScalar(0.);
+	m_limitSign = btScalar(0.);
+	m_solveLimit = false;
+	if (m_lowerLimit <= m_upperLimit)
+	{
+		m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit);
+		if (m_hingeAngle <= m_lowerLimit)
+		{
+			m_correction = (m_lowerLimit - m_hingeAngle);
+			m_limitSign = 1.0f;
+			m_solveLimit = true;
+		} 
+		else if (m_hingeAngle >= m_upperLimit)
+		{
+			m_correction = m_upperLimit - m_hingeAngle;
+			m_limitSign = -1.0f;
+			m_solveLimit = true;
+		}
+	}
+#endif
+	return;
+}
+
+
+static btVector3 vHinge(0, 0, btScalar(1));
+
+void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
+{
+	// convert target from body to constraint space
+	btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation();
+	qConstraint.normalize();
+
+	// extract "pure" hinge component
+	btVector3 vNoHinge = quatRotate(qConstraint, vHinge); vNoHinge.normalize();
+	btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
+	btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
+	qHinge.normalize();
+
+	// compute angular target, clamped to limits
+	btScalar targetAngle = qHinge.getAngle();
+	if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate.
+	{
+		qHinge = operator-(qHinge);
+		targetAngle = qHinge.getAngle();
+	}
+	if (qHinge.getZ() < 0)
+		targetAngle = -targetAngle;
+
+	setMotorTarget(targetAngle, dt);
+}
+
+void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
+{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	m_limit.fit(targetAngle);
+#else
+	if (m_lowerLimit < m_upperLimit)
+	{
+		if (targetAngle < m_lowerLimit)
+			targetAngle = m_lowerLimit;
+		else if (targetAngle > m_upperLimit)
+			targetAngle = m_upperLimit;
+	}
+#endif
+	// compute angular velocity
+	btScalar curAngle  = getHingeAngle(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+	btScalar dAngle = targetAngle - curAngle;
+	m_motorTargetVelocity = dAngle / dt;
+}
+
+
+
+void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB)
+{
+	btAssert(!m_useSolveConstraintObsolete);
+	int i, s = info->rowskip;
+	// transforms in world space
+	btTransform trA = transA*m_rbAFrame;
+	btTransform trB = transB*m_rbBFrame;
+	// pivot point
+	btVector3 pivotAInW = trA.getOrigin();
+	btVector3 pivotBInW = trB.getOrigin();
+#if 1
+	// difference between frames in WCS
+	btVector3 ofs = trB.getOrigin() - trA.getOrigin();
+	// now get weight factors depending on masses
+	btScalar miA = getRigidBodyA().getInvMass();
+	btScalar miB = getRigidBodyB().getInvMass();
+	bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+	btScalar miS = miA + miB;
+	btScalar factA, factB;
+	if(miS > btScalar(0.f))
+	{
+		factA = miB / miS;
+	}
+	else 
+	{
+		factA = btScalar(0.5f);
+	}
+	factB = btScalar(1.0f) - factA;
+	// get the desired direction of hinge axis
+	// as weighted sum of Z-orthos of frameA and frameB in WCS
+	btVector3 ax1A = trA.getBasis().getColumn(2);
+	btVector3 ax1B = trB.getBasis().getColumn(2);
+	btVector3 ax1 = ax1A * factA + ax1B * factB;
+	ax1.normalize();
+	// fill first 3 rows 
+	// we want: velA + wA x relA == velB + wB x relB
+	btTransform bodyA_trans = transA;
+	btTransform bodyB_trans = transB;
+	int s0 = 0;
+	int s1 = s;
+	int s2 = s * 2;
+	int nrow = 2; // last filled row
+	btVector3 tmpA, tmpB, relA, relB, p, q;
+	// get vector from bodyB to frameB in WCS
+	relB = trB.getOrigin() - bodyB_trans.getOrigin();
+	// get its projection to hinge axis
+	btVector3 projB = ax1 * relB.dot(ax1);
+	// get vector directed from bodyB to hinge axis (and orthogonal to it)
+	btVector3 orthoB = relB - projB;
+	// same for bodyA
+	relA = trA.getOrigin() - bodyA_trans.getOrigin();
+	btVector3 projA = ax1 * relA.dot(ax1);
+	btVector3 orthoA = relA - projA;
+	btVector3 totalDist = projA - projB;
+	// get offset vectors relA and relB
+	relA = orthoA + totalDist * factA;
+	relB = orthoB - totalDist * factB;
+	// now choose average ortho to hinge axis
+	p = orthoB * factA + orthoA * factB;
+	btScalar len2 = p.length2();
+	if(len2 > SIMD_EPSILON)
+	{
+		p /= btSqrt(len2);
+	}
+	else
+	{
+		p = trA.getBasis().getColumn(1);
+	}
+	// make one more ortho
+	q = ax1.cross(p);
+	// fill three rows
+	tmpA = relA.cross(p);
+	tmpB = relB.cross(p);
+    for (i=0; i<3; i++) info->m_J1angularAxis[s0+i] = tmpA[i];
+    for (i=0; i<3; i++) info->m_J2angularAxis[s0+i] = -tmpB[i];
+	tmpA = relA.cross(q);
+	tmpB = relB.cross(q);
+	if(hasStaticBody && getSolveLimit())
+	{ // to make constraint between static and dynamic objects more rigid
+		// remove wA (or wB) from equation if angular limit is hit
+		tmpB *= factB;
+		tmpA *= factA;
+	}
+	for (i=0; i<3; i++) info->m_J1angularAxis[s1+i] = tmpA[i];
+    for (i=0; i<3; i++) info->m_J2angularAxis[s1+i] = -tmpB[i];
+	tmpA = relA.cross(ax1);
+	tmpB = relB.cross(ax1);
+	if(hasStaticBody)
+	{ // to make constraint between static and dynamic objects more rigid
+		// remove wA (or wB) from equation
+		tmpB *= factB;
+		tmpA *= factA;
+	}
+	for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
+    for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
+
+	btScalar k = info->fps * info->erp;
+
+	if (!m_angularOnly)
+	{
+		for (i=0; i<3; i++) info->m_J1linearAxis[s0+i] = p[i];
+		for (i=0; i<3; i++) info->m_J1linearAxis[s1+i] = q[i];
+		for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = ax1[i];
+	
+	// compute three elements of right hand side
+	
+		btScalar rhs = k * p.dot(ofs);
+		info->m_constraintError[s0] = rhs;
+		rhs = k * q.dot(ofs);
+		info->m_constraintError[s1] = rhs;
+		rhs = k * ax1.dot(ofs);
+		info->m_constraintError[s2] = rhs;
+	}
+	// the hinge axis should be the only unconstrained
+	// rotational axis, the angular velocity of the two bodies perpendicular to
+	// the hinge axis should be equal. thus the constraint equations are
+	//    p*w1 - p*w2 = 0
+	//    q*w1 - q*w2 = 0
+	// where p and q are unit vectors normal to the hinge axis, and w1 and w2
+	// are the angular velocity vectors of the two bodies.
+	int s3 = 3 * s;
+	int s4 = 4 * s;
+	info->m_J1angularAxis[s3 + 0] = p[0];
+	info->m_J1angularAxis[s3 + 1] = p[1];
+	info->m_J1angularAxis[s3 + 2] = p[2];
+	info->m_J1angularAxis[s4 + 0] = q[0];
+	info->m_J1angularAxis[s4 + 1] = q[1];
+	info->m_J1angularAxis[s4 + 2] = q[2];
+
+	info->m_J2angularAxis[s3 + 0] = -p[0];
+	info->m_J2angularAxis[s3 + 1] = -p[1];
+	info->m_J2angularAxis[s3 + 2] = -p[2];
+	info->m_J2angularAxis[s4 + 0] = -q[0];
+	info->m_J2angularAxis[s4 + 1] = -q[1];
+	info->m_J2angularAxis[s4 + 2] = -q[2];
+	// compute the right hand side of the constraint equation. set relative
+	// body velocities along p and q to bring the hinge back into alignment.
+	// if ax1A,ax1B are the unit length hinge axes as computed from bodyA and
+	// bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
+	// if "theta" is the angle between ax1 and ax2, we need an angular velocity
+	// along u to cover angle erp*theta in one step :
+	//   |angular_velocity| = angle/time = erp*theta / stepsize
+	//                      = (erp*fps) * theta
+	//    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+	//                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+	// ...as ax1 and ax2 are unit length. if theta is smallish,
+	// theta ~= sin(theta), so
+	//    angular_velocity  = (erp*fps) * (ax1 x ax2)
+	// ax1 x ax2 is in the plane space of ax1, so we project the angular
+	// velocity to p and q to find the right hand side.
+	k = info->fps * info->erp;
+	btVector3 u = ax1A.cross(ax1B);
+	info->m_constraintError[s3] = k * u.dot(p);
+	info->m_constraintError[s4] = k * u.dot(q);
+#endif
+	// check angular limits
+	nrow = 4; // last filled row
+	int srow;
+	btScalar limit_err = btScalar(0.0);
+	int limit = 0;
+	if(getSolveLimit())
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	limit_err = m_limit.getCorrection() * m_referenceSign;
+#else
+	limit_err = m_correction * m_referenceSign;
+#endif
+	limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+
+	}
+	// if the hinge has joint limits or motor, add in the extra row
+	int powered = 0;
+	if(getEnableAngularMotor())
+	{
+		powered = 1;
+	}
+	if(limit || powered) 
+	{
+		nrow++;
+		srow = nrow * info->rowskip;
+		info->m_J1angularAxis[srow+0] = ax1[0];
+		info->m_J1angularAxis[srow+1] = ax1[1];
+		info->m_J1angularAxis[srow+2] = ax1[2];
+
+		info->m_J2angularAxis[srow+0] = -ax1[0];
+		info->m_J2angularAxis[srow+1] = -ax1[1];
+		info->m_J2angularAxis[srow+2] = -ax1[2];
+
+		btScalar lostop = getLowerLimit();
+		btScalar histop = getUpperLimit();
+		if(limit && (lostop == histop))
+		{  // the joint motor is ineffective
+			powered = 0;
+		}
+		info->m_constraintError[srow] = btScalar(0.0f);
+		btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : info->erp;
+		if(powered)
+		{
+			if(m_flags & BT_HINGE_FLAGS_CFM_NORM)
+			{
+				info->cfm[srow] = m_normalCFM;
+			}
+			btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
+			info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
+			info->m_lowerLimit[srow] = - m_maxMotorImpulse;
+			info->m_upperLimit[srow] =   m_maxMotorImpulse;
+		}
+		if(limit)
+		{
+			k = info->fps * currERP;
+			info->m_constraintError[srow] += k * limit_err;
+			if(m_flags & BT_HINGE_FLAGS_CFM_STOP)
+			{
+				info->cfm[srow] = m_stopCFM;
+			}
+			if(lostop == histop) 
+			{
+				// limited low and high simultaneously
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else if(limit == 1) 
+			{ // low limit
+				info->m_lowerLimit[srow] = 0;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else 
+			{ // high limit
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = 0;
+			}
+			// bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+#ifdef	_BT_USE_CENTER_LIMIT_
+			btScalar bounce = m_limit.getRelaxationFactor();
+#else
+			btScalar bounce = m_relaxationFactor;
+#endif
+			if(bounce > btScalar(0.0))
+			{
+				btScalar vel = angVelA.dot(ax1);
+				vel -= angVelB.dot(ax1);
+				// only apply bounce if the velocity is incoming, and if the
+				// resulting c[] exceeds what we already have.
+				if(limit == 1)
+				{	// low limit
+					if(vel < 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc > info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+				else
+				{	// high limit - all those computations are reversed
+					if(vel > 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc < info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+			}
+#ifdef	_BT_USE_CENTER_LIMIT_
+			info->m_constraintError[srow] *= m_limit.getBiasFactor();
+#else
+			info->m_constraintError[srow] *= m_biasFactor;
+#endif
+		} // if(limit)
+	} // if angular limit or powered
+}
+
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+///If no axis is provided, it uses the default axis for this constraint.
+void btHingeConstraint::setParam(int num, btScalar value, int axis)
+{
+	if((axis == -1) || (axis == 5))
+	{
+		switch(num)
+		{	
+			case BT_CONSTRAINT_STOP_ERP :
+				m_stopERP = value;
+				m_flags |= BT_HINGE_FLAGS_ERP_STOP;
+				break;
+			case BT_CONSTRAINT_STOP_CFM :
+				m_stopCFM = value;
+				m_flags |= BT_HINGE_FLAGS_CFM_STOP;
+				break;
+			case BT_CONSTRAINT_CFM :
+				m_normalCFM = value;
+				m_flags |= BT_HINGE_FLAGS_CFM_NORM;
+				break;
+			default : 
+				btAssertConstrParams(0);
+		}
+	}
+	else
+	{
+		btAssertConstrParams(0);
+	}
+}
+
+///return the local value of parameter
+btScalar btHingeConstraint::getParam(int num, int axis) const 
+{
+	btScalar retVal = 0;
+	if((axis == -1) || (axis == 5))
+	{
+		switch(num)
+		{	
+			case BT_CONSTRAINT_STOP_ERP :
+				btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
+				retVal = m_stopERP;
+				break;
+			case BT_CONSTRAINT_STOP_CFM :
+				btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
+				retVal = m_stopCFM;
+				break;
+			case BT_CONSTRAINT_CFM :
+				btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
+				retVal = m_normalCFM;
+				break;
+			default : 
+				btAssertConstrParams(0);
+		}
+	}
+	else
+	{
+		btAssertConstrParams(0);
+	}
+	return retVal;
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h	(revision 11817)
@@ -0,0 +1,381 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */
+
+#ifndef BT_HINGECONSTRAINT_H
+#define BT_HINGECONSTRAINT_H
+
+#define _BT_USE_CENTER_LIMIT_ 1
+
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btHingeConstraintData	btHingeConstraintDoubleData
+#define btHingeConstraintDataName	"btHingeConstraintDoubleData"
+#else
+#define btHingeConstraintData	btHingeConstraintFloatData
+#define btHingeConstraintDataName	"btHingeConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+enum btHingeFlags
+{
+	BT_HINGE_FLAGS_CFM_STOP = 1,
+	BT_HINGE_FLAGS_ERP_STOP = 2,
+	BT_HINGE_FLAGS_CFM_NORM = 4
+};
+
+
+/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
+/// axis defines the orientation of the hinge axis
+ATTRIBUTE_ALIGNED16(class) btHingeConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+	btJacobianEntry	m_jac[3]; //3 orthogonal linear constraints
+	btJacobianEntry	m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
+
+	btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+	btTransform m_rbBFrame;
+
+	btScalar	m_motorTargetVelocity;
+	btScalar	m_maxMotorImpulse;
+
+
+#ifdef	_BT_USE_CENTER_LIMIT_
+	btAngularLimit	m_limit;
+#else
+	btScalar	m_lowerLimit;	
+	btScalar	m_upperLimit;	
+	btScalar	m_limitSign;
+	btScalar	m_correction;
+
+	btScalar	m_limitSoftness; 
+	btScalar	m_biasFactor; 
+	btScalar	m_relaxationFactor; 
+
+	bool		m_solveLimit;
+#endif
+
+	btScalar	m_kHinge;
+
+
+	btScalar	m_accLimitImpulse;
+	btScalar	m_hingeAngle;
+	btScalar	m_referenceSign;
+
+	bool		m_angularOnly;
+	bool		m_enableAngularMotor;
+	bool		m_useSolveConstraintObsolete;
+	bool		m_useOffsetForConstraintFrame;
+	bool		m_useReferenceFrameA;
+
+	btScalar	m_accMotorImpulse;
+
+	int			m_flags;
+	btScalar	m_normalCFM;
+	btScalar	m_stopCFM;
+	btScalar	m_stopERP;
+
+	
+public:
+
+	btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB, const btVector3& axisInA,const btVector3& axisInB, bool useReferenceFrameA = false);
+
+	btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,const btVector3& axisInA, bool useReferenceFrameA = false);
+	
+	btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
+
+	btHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA = false);
+
+
+	virtual void	buildJacobian();
+
+	virtual void getInfo1 (btConstraintInfo1* info);
+
+	void getInfo1NonVirtual(btConstraintInfo1* info);
+
+	virtual void getInfo2 (btConstraintInfo2* info);
+
+	void	getInfo2NonVirtual(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+
+	void	getInfo2Internal(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+	void	getInfo2InternalUsingFrameOffset(btConstraintInfo2* info,const btTransform& transA,const btTransform& transB,const btVector3& angVelA,const btVector3& angVelB);
+		
+
+	void	updateRHS(btScalar	timeStep);
+
+	const btRigidBody& getRigidBodyA() const
+	{
+		return m_rbA;
+	}
+	const btRigidBody& getRigidBodyB() const
+	{
+		return m_rbB;
+	}
+
+	btRigidBody& getRigidBodyA()	
+	{		
+		return m_rbA;	
+	}	
+
+	btRigidBody& getRigidBodyB()	
+	{		
+		return m_rbB;	
+	}
+
+	btTransform& getFrameOffsetA()
+	{
+	return m_rbAFrame;
+	}
+
+	btTransform& getFrameOffsetB()
+	{
+		return m_rbBFrame;
+	}
+
+	void setFrames(const btTransform& frameA, const btTransform& frameB);
+	
+	void	setAngularOnly(bool angularOnly)
+	{
+		m_angularOnly = angularOnly;
+	}
+
+	void	enableAngularMotor(bool enableMotor,btScalar targetVelocity,btScalar maxMotorImpulse)
+	{
+		m_enableAngularMotor  = enableMotor;
+		m_motorTargetVelocity = targetVelocity;
+		m_maxMotorImpulse = maxMotorImpulse;
+	}
+
+	// extra motor API, including ability to set a target rotation (as opposed to angular velocity)
+	// note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to
+	//       maintain a given angular target.
+	void enableMotor(bool enableMotor) 	{ m_enableAngularMotor = enableMotor; }
+	void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; }
+	void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B.
+	void setMotorTarget(btScalar targetAngle, btScalar dt);
+
+
+	void	setLimit(btScalar low,btScalar high,btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+		m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor);
+#else
+		m_lowerLimit = btNormalizeAngle(low);
+		m_upperLimit = btNormalizeAngle(high);
+		m_limitSoftness =  _softness;
+		m_biasFactor = _biasFactor;
+		m_relaxationFactor = _relaxationFactor;
+#endif
+	}
+
+	void	setAxis(btVector3& axisInA)
+	{
+		btVector3 rbAxisA1, rbAxisA2;
+		btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
+		btVector3 pivotInA = m_rbAFrame.getOrigin();
+//		m_rbAFrame.getOrigin() = pivotInA;
+		m_rbAFrame.getBasis().setValue( rbAxisA1.getX(),rbAxisA2.getX(),axisInA.getX(),
+										rbAxisA1.getY(),rbAxisA2.getY(),axisInA.getY(),
+										rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
+
+		btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA;
+
+		btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
+		btVector3 rbAxisB1 =  quatRotate(rotationArc,rbAxisA1);
+		btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
+
+		m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA));
+
+		m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
+										rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
+										rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
+		m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis();
+
+	}
+
+	btScalar	getLowerLimit() const
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	return m_limit.getLow();
+#else
+	return m_lowerLimit;
+#endif
+	}
+
+	btScalar	getUpperLimit() const
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	return m_limit.getHigh();
+#else		
+	return m_upperLimit;
+#endif
+	}
+
+
+	btScalar getHingeAngle();
+
+	btScalar getHingeAngle(const btTransform& transA,const btTransform& transB);
+
+	void testLimit(const btTransform& transA,const btTransform& transB);
+
+
+	const btTransform& getAFrame() const { return m_rbAFrame; };	
+	const btTransform& getBFrame() const { return m_rbBFrame; };
+
+	btTransform& getAFrame() { return m_rbAFrame; };	
+	btTransform& getBFrame() { return m_rbBFrame; };
+
+	inline int getSolveLimit()
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	return m_limit.isLimit();
+#else
+	return m_solveLimit;
+#endif
+	}
+
+	inline btScalar getLimitSign()
+	{
+#ifdef	_BT_USE_CENTER_LIMIT_
+	return m_limit.getSign();
+#else
+		return m_limitSign;
+#endif
+	}
+
+	inline bool getAngularOnly() 
+	{ 
+		return m_angularOnly; 
+	}
+	inline bool getEnableAngularMotor() 
+	{ 
+		return m_enableAngularMotor; 
+	}
+	inline btScalar getMotorTargetVelosity() 
+	{ 
+		return m_motorTargetVelocity; 
+	}
+	inline btScalar getMaxMotorImpulse() 
+	{ 
+		return m_maxMotorImpulse; 
+	}
+	// access for UseFrameOffset
+	bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+	void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+	virtual	void	setParam(int num, btScalar value, int axis = -1);
+	///return the local value of parameter
+	virtual	btScalar getParam(int num, int axis = -1) const;
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btHingeConstraintDoubleData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+	btTransformDoubleData m_rbBFrame;
+	int			m_useReferenceFrameA;
+	int			m_angularOnly;
+	int			m_enableAngularMotor;
+	float	m_motorTargetVelocity;
+	float	m_maxMotorImpulse;
+
+	float	m_lowerLimit;
+	float	m_upperLimit;
+	float	m_limitSoftness;
+	float	m_biasFactor;
+	float	m_relaxationFactor;
+
+};
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btHingeConstraintFloatData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+	btTransformFloatData m_rbBFrame;
+	int			m_useReferenceFrameA;
+	int			m_angularOnly;
+	
+	int			m_enableAngularMotor;
+	float	m_motorTargetVelocity;
+	float	m_maxMotorImpulse;
+
+	float	m_lowerLimit;
+	float	m_upperLimit;
+	float	m_limitSoftness;
+	float	m_biasFactor;
+	float	m_relaxationFactor;
+
+};
+
+
+
+SIMD_FORCE_INLINE	int	btHingeConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btHingeConstraintData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer;
+	btTypedConstraint::serialize(&hingeData->m_typeConstraintData,serializer);
+
+	m_rbAFrame.serialize(hingeData->m_rbAFrame);
+	m_rbBFrame.serialize(hingeData->m_rbBFrame);
+
+	hingeData->m_angularOnly = m_angularOnly;
+	hingeData->m_enableAngularMotor = m_enableAngularMotor;
+	hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse);
+	hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity);
+	hingeData->m_useReferenceFrameA = m_useReferenceFrameA;
+#ifdef	_BT_USE_CENTER_LIMIT_
+	hingeData->m_lowerLimit = float(m_limit.getLow());
+	hingeData->m_upperLimit = float(m_limit.getHigh());
+	hingeData->m_limitSoftness = float(m_limit.getSoftness());
+	hingeData->m_biasFactor = float(m_limit.getBiasFactor());
+	hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor());
+#else
+	hingeData->m_lowerLimit = float(m_lowerLimit);
+	hingeData->m_upperLimit = float(m_upperLimit);
+	hingeData->m_limitSoftness = float(m_limitSoftness);
+	hingeData->m_biasFactor = float(m_biasFactor);
+	hingeData->m_relaxationFactor = float(m_relaxationFactor);
+#endif
+
+	return btHingeConstraintDataName;
+}
+
+#endif //BT_HINGECONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h	(revision 11817)
@@ -0,0 +1,156 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_JACOBIAN_ENTRY_H
+#define BT_JACOBIAN_ENTRY_H
+
+#include "LinearMath/btVector3.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+
+//notes:
+// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
+// which makes the btJacobianEntry memory layout 16 bytes
+// if you only are interested in angular part, just feed massInvA and massInvB zero
+
+/// Jacobian entry is an abstraction that allows to describe constraints
+/// it can be used in combination with a constraint solver
+/// Can be used to relate the effect of an impulse to the constraint error
+ATTRIBUTE_ALIGNED16(class) btJacobianEntry
+{
+public:
+	btJacobianEntry() {};
+	//constraint between two different rigidbodies
+	btJacobianEntry(
+		const btMatrix3x3& world2A,
+		const btMatrix3x3& world2B,
+		const btVector3& rel_pos1,const btVector3& rel_pos2,
+		const btVector3& jointAxis,
+		const btVector3& inertiaInvA, 
+		const btScalar massInvA,
+		const btVector3& inertiaInvB,
+		const btScalar massInvB)
+		:m_linearJointAxis(jointAxis)
+	{
+		m_aJ = world2A*(rel_pos1.cross(m_linearJointAxis));
+		m_bJ = world2B*(rel_pos2.cross(-m_linearJointAxis));
+		m_0MinvJt	= inertiaInvA * m_aJ;
+		m_1MinvJt = inertiaInvB * m_bJ;
+		m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
+
+		btAssert(m_Adiag > btScalar(0.0));
+	}
+
+	//angular constraint between two different rigidbodies
+	btJacobianEntry(const btVector3& jointAxis,
+		const btMatrix3x3& world2A,
+		const btMatrix3x3& world2B,
+		const btVector3& inertiaInvA,
+		const btVector3& inertiaInvB)
+		:m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.)))
+	{
+		m_aJ= world2A*jointAxis;
+		m_bJ = world2B*-jointAxis;
+		m_0MinvJt	= inertiaInvA * m_aJ;
+		m_1MinvJt = inertiaInvB * m_bJ;
+		m_Adiag =  m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+		btAssert(m_Adiag > btScalar(0.0));
+	}
+
+	//angular constraint between two different rigidbodies
+	btJacobianEntry(const btVector3& axisInA,
+		const btVector3& axisInB,
+		const btVector3& inertiaInvA,
+		const btVector3& inertiaInvB)
+		: m_linearJointAxis(btVector3(btScalar(0.),btScalar(0.),btScalar(0.)))
+		, m_aJ(axisInA)
+		, m_bJ(-axisInB)
+	{
+		m_0MinvJt	= inertiaInvA * m_aJ;
+		m_1MinvJt = inertiaInvB * m_bJ;
+		m_Adiag =  m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
+
+		btAssert(m_Adiag > btScalar(0.0));
+	}
+
+	//constraint on one rigidbody
+	btJacobianEntry(
+		const btMatrix3x3& world2A,
+		const btVector3& rel_pos1,const btVector3& rel_pos2,
+		const btVector3& jointAxis,
+		const btVector3& inertiaInvA, 
+		const btScalar massInvA)
+		:m_linearJointAxis(jointAxis)
+	{
+		m_aJ= world2A*(rel_pos1.cross(jointAxis));
+		m_bJ = world2A*(rel_pos2.cross(-jointAxis));
+		m_0MinvJt	= inertiaInvA * m_aJ;
+		m_1MinvJt = btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+		m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
+
+		btAssert(m_Adiag > btScalar(0.0));
+	}
+
+	btScalar	getDiagonal() const { return m_Adiag; }
+
+	// for two constraints on the same rigidbody (for example vehicle friction)
+	btScalar	getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const
+	{
+		const btJacobianEntry& jacA = *this;
+		btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
+		btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
+		return lin + ang;
+	}
+
+	
+
+	// for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
+	btScalar	getNonDiagonal(const btJacobianEntry& jacB,const btScalar massInvA,const btScalar massInvB) const
+	{
+		const btJacobianEntry& jacA = *this;
+		btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
+		btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
+		btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
+		btVector3 lin0 = massInvA * lin ;
+		btVector3 lin1 = massInvB * lin;
+		btVector3 sum = ang0+ang1+lin0+lin1;
+		return sum[0]+sum[1]+sum[2];
+	}
+
+	btScalar getRelativeVelocity(const btVector3& linvelA,const btVector3& angvelA,const btVector3& linvelB,const btVector3& angvelB)
+	{
+		btVector3 linrel = linvelA - linvelB;
+		btVector3 angvela  = angvelA * m_aJ;
+		btVector3 angvelb  = angvelB * m_bJ;
+		linrel *= m_linearJointAxis;
+		angvela += angvelb;
+		angvela += linrel;
+		btScalar rel_vel2 = angvela[0]+angvela[1]+angvela[2];
+		return rel_vel2 + SIMD_EPSILON;
+	}
+//private:
+
+	btVector3	m_linearJointAxis;
+	btVector3	m_aJ;
+	btVector3	m_bJ;
+	btVector3	m_0MinvJt;
+	btVector3	m_1MinvJt;
+	//Optimization: can be stored in the w/last component of one of the vectors
+	btScalar	m_Adiag;
+
+};
+
+#endif //BT_JACOBIAN_ENTRY_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp	(revision 11817)
@@ -0,0 +1,230 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btPoint2PointConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include <new>
+
+
+
+
+
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB)
+:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA,rbB),m_pivotInA(pivotInA),m_pivotInB(pivotInB),
+m_flags(0),
+m_useSolveConstraintObsolete(false)
+{
+
+}
+
+
+btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA)
+:btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)),
+m_flags(0),
+m_useSolveConstraintObsolete(false)
+{
+	
+}
+
+void	btPoint2PointConstraint::buildJacobian()
+{
+
+	///we need it for both methods
+	{
+		m_appliedImpulse = btScalar(0.);
+
+		btVector3	normal(0,0,0);
+
+		for (int i=0;i<3;i++)
+		{
+			normal[i] = 1;
+			new (&m_jac[i]) btJacobianEntry(
+			m_rbA.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbB.getCenterOfMassTransform().getBasis().transpose(),
+			m_rbA.getCenterOfMassTransform()*m_pivotInA - m_rbA.getCenterOfMassPosition(),
+			m_rbB.getCenterOfMassTransform()*m_pivotInB - m_rbB.getCenterOfMassPosition(),
+			normal,
+			m_rbA.getInvInertiaDiagLocal(),
+			m_rbA.getInvMass(),
+			m_rbB.getInvInertiaDiagLocal(),
+			m_rbB.getInvMass());
+		normal[i] = 0;
+		}
+	}
+
+
+}
+
+void btPoint2PointConstraint::getInfo1 (btConstraintInfo1* info)
+{
+	getInfo1NonVirtual(info);
+}
+
+void btPoint2PointConstraint::getInfo1NonVirtual (btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	} else
+	{
+		info->m_numConstraintRows = 3;
+		info->nub = 3;
+	}
+}
+
+
+
+
+void btPoint2PointConstraint::getInfo2 (btConstraintInfo2* info)
+{
+	getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+void btPoint2PointConstraint::getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
+{
+	btAssert(!m_useSolveConstraintObsolete);
+
+	 //retrieve matrices
+
+	// anchor points in global coordinates with respect to body PORs.
+   
+    // set jacobian
+    info->m_J1linearAxis[0] = 1;
+	info->m_J1linearAxis[info->rowskip+1] = 1;
+	info->m_J1linearAxis[2*info->rowskip+2] = 1;
+
+	btVector3 a1 = body0_trans.getBasis()*getPivotInA();
+	{
+		btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
+		btVector3* angular1 = (btVector3*)(info->m_J1angularAxis+info->rowskip);
+		btVector3* angular2 = (btVector3*)(info->m_J1angularAxis+2*info->rowskip);
+		btVector3 a1neg = -a1;
+		a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
+	}
+    
+	/*info->m_J2linearAxis[0] = -1;
+    info->m_J2linearAxis[s+1] = -1;
+    info->m_J2linearAxis[2*s+2] = -1;
+	*/
+	
+	btVector3 a2 = body1_trans.getBasis()*getPivotInB();
+   
+	{
+		btVector3 a2n = -a2;
+		btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
+		btVector3* angular1 = (btVector3*)(info->m_J2angularAxis+info->rowskip);
+		btVector3* angular2 = (btVector3*)(info->m_J2angularAxis+2*info->rowskip);
+		a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
+	}
+    
+
+
+    // set right hand side
+	btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp;
+    btScalar k = info->fps * currERP;
+    int j;
+	for (j=0; j<3; j++)
+    {
+        info->m_constraintError[j*info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
+		//printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
+    }
+	if(m_flags & BT_P2P_FLAGS_CFM)
+	{
+		for (j=0; j<3; j++)
+		{
+			info->cfm[j*info->rowskip] = m_cfm;
+		}
+	}
+
+	btScalar impulseClamp = m_setting.m_impulseClamp;//
+	for (j=0; j<3; j++)
+    {
+		if (m_setting.m_impulseClamp > 0)
+		{
+			info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
+			info->m_upperLimit[j*info->rowskip] = impulseClamp;
+		}
+	}
+	info->m_damping = m_setting.m_damping;
+	
+}
+
+
+
+void	btPoint2PointConstraint::updateRHS(btScalar	timeStep)
+{
+	(void)timeStep;
+
+}
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+///If no axis is provided, it uses the default axis for this constraint.
+void btPoint2PointConstraint::setParam(int num, btScalar value, int axis)
+{
+	if(axis != -1)
+	{
+		btAssertConstrParams(0);
+	}
+	else
+	{
+		switch(num)
+		{
+			case BT_CONSTRAINT_ERP :
+			case BT_CONSTRAINT_STOP_ERP :
+				m_erp = value; 
+				m_flags |= BT_P2P_FLAGS_ERP;
+				break;
+			case BT_CONSTRAINT_CFM :
+			case BT_CONSTRAINT_STOP_CFM :
+				m_cfm = value; 
+				m_flags |= BT_P2P_FLAGS_CFM;
+				break;
+			default: 
+				btAssertConstrParams(0);
+		}
+	}
+}
+
+///return the local value of parameter
+btScalar btPoint2PointConstraint::getParam(int num, int axis) const 
+{
+	btScalar retVal(SIMD_INFINITY);
+	if(axis != -1)
+	{
+		btAssertConstrParams(0);
+	}
+	else
+	{
+		switch(num)
+		{
+			case BT_CONSTRAINT_ERP :
+			case BT_CONSTRAINT_STOP_ERP :
+				btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP);
+				retVal = m_erp; 
+				break;
+			case BT_CONSTRAINT_CFM :
+			case BT_CONSTRAINT_STOP_CFM :
+				btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM);
+				retVal = m_cfm; 
+				break;
+			default: 
+				btAssertConstrParams(0);
+		}
+	}
+	return retVal;
+}
+	
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h	(revision 11817)
@@ -0,0 +1,161 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_POINT2POINTCONSTRAINT_H
+#define BT_POINT2POINTCONSTRAINT_H
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+class btRigidBody;
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btPoint2PointConstraintData	btPoint2PointConstraintDoubleData
+#define btPoint2PointConstraintDataName	"btPoint2PointConstraintDoubleData"
+#else
+#define btPoint2PointConstraintData	btPoint2PointConstraintFloatData
+#define btPoint2PointConstraintDataName	"btPoint2PointConstraintFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+struct	btConstraintSetting
+{
+	btConstraintSetting()	:
+		m_tau(btScalar(0.3)),
+		m_damping(btScalar(1.)),
+		m_impulseClamp(btScalar(0.))
+	{
+	}
+	btScalar		m_tau;
+	btScalar		m_damping;
+	btScalar		m_impulseClamp;
+};
+
+enum btPoint2PointFlags
+{
+	BT_P2P_FLAGS_ERP = 1,
+	BT_P2P_FLAGS_CFM = 2
+};
+
+/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
+ATTRIBUTE_ALIGNED16(class) btPoint2PointConstraint : public btTypedConstraint
+{
+#ifdef IN_PARALLELL_SOLVER
+public:
+#endif
+	btJacobianEntry	m_jac[3]; //3 orthogonal linear constraints
+	
+	btVector3	m_pivotInA;
+	btVector3	m_pivotInB;
+	
+	int			m_flags;
+	btScalar	m_erp;
+	btScalar	m_cfm;
+	
+public:
+
+	///for backwards compatibility during the transition to 'getInfo/getInfo2'
+	bool		m_useSolveConstraintObsolete;
+
+	btConstraintSetting	m_setting;
+
+	btPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB);
+
+	btPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA);
+
+
+	virtual void	buildJacobian();
+
+	virtual void getInfo1 (btConstraintInfo1* info);
+
+	void getInfo1NonVirtual (btConstraintInfo1* info);
+
+	virtual void getInfo2 (btConstraintInfo2* info);
+
+	void getInfo2NonVirtual (btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans);
+
+	void	updateRHS(btScalar	timeStep);
+
+	void	setPivotA(const btVector3& pivotA)
+	{
+		m_pivotInA = pivotA;
+	}
+
+	void	setPivotB(const btVector3& pivotB)
+	{
+		m_pivotInB = pivotB;
+	}
+
+	const btVector3& getPivotInA() const
+	{
+		return m_pivotInA;
+	}
+
+	const btVector3& getPivotInB() const
+	{
+		return m_pivotInB;
+	}
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+	virtual	void	setParam(int num, btScalar value, int axis = -1);
+	///return the local value of parameter
+	virtual	btScalar getParam(int num, int axis = -1) const;
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btPoint2PointConstraintFloatData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btVector3FloatData	m_pivotInA;
+	btVector3FloatData	m_pivotInB;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btPoint2PointConstraintDoubleData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btVector3DoubleData	m_pivotInA;
+	btVector3DoubleData	m_pivotInB;
+};
+
+
+SIMD_FORCE_INLINE	int	btPoint2PointConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btPoint2PointConstraintData);
+
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btPoint2PointConstraintData* p2pData = (btPoint2PointConstraintData*)dataBuffer;
+
+	btTypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer);
+	m_pivotInA.serialize(p2pData->m_pivotInA);
+	m_pivotInB.serialize(p2pData->m_pivotInB);
+
+	return btPoint2PointConstraintDataName;
+}
+
+#endif //BT_POINT2POINTCONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp	(revision 11817)
@@ -0,0 +1,1239 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#define COMPUTE_IMPULSE_DENOM 1
+//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
+
+#include "btSequentialImpulseConstraintSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "btContactConstraint.h"
+#include "btSolve2LinearConstraint.h"
+#include "btContactSolverInfo.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "btJacobianEntry.h"
+#include "LinearMath/btMinMax.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include <new>
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btQuickprof.h"
+#include "btSolverBody.h"
+#include "btSolverConstraint.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include <string.h> //for memset
+
+int		gNumSplitImpulseRecoveries = 0;
+
+btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
+:m_btSeed2(0)
+{
+
+}
+
+btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
+{
+}
+
+#ifdef USE_SIMD
+#include <emmintrin.h>
+#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e,e,e,e))
+static inline __m128 btSimdDot3( __m128 vec0, __m128 vec1 )
+{
+	__m128 result = _mm_mul_ps( vec0, vec1);
+	return _mm_add_ps( btVecSplat( result, 0 ), _mm_add_ps( btVecSplat( result, 1 ), btVecSplat( result, 2 ) ) );
+}
+#endif//USE_SIMD
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+{
+#ifdef USE_SIMD
+	__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+	__m128	lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+	__m128	upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+	__m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
+	__m128 deltaVel1Dotn	=	_mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
+	__m128 deltaVel2Dotn	=	_mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
+	deltaImpulse	=	_mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+	deltaImpulse	=	_mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+	btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+	btSimdScalar resultLowerLess,resultUpperLess;
+	resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+	resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+	__m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+	deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+	c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+	__m128 upperMinApplied = _mm_sub_ps(upperLimit1,cpAppliedImp);
+	deltaImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied) );
+	c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1) );
+	__m128	linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
+	__m128	linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+	__m128 impulseMagnitude = deltaImpulse;
+	body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+	body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+	body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+	body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+#else
+	resolveSingleConstraintRowGeneric(body1,body2,c);
+#endif
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+{
+	btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
+	const btScalar deltaVel1Dotn	=	c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) 	+ c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+	const btScalar deltaVel2Dotn	=	-c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+//	const btScalar delta_rel_vel	=	deltaVel1Dotn-deltaVel2Dotn;
+	deltaImpulse	-=	deltaVel1Dotn*c.m_jacDiagABInv;
+	deltaImpulse	-=	deltaVel2Dotn*c.m_jacDiagABInv;
+
+	const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+	if (sum < c.m_lowerLimit)
+	{
+		deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+		c.m_appliedImpulse = c.m_lowerLimit;
+	}
+	else if (sum > c.m_upperLimit) 
+	{
+		deltaImpulse = c.m_upperLimit-c.m_appliedImpulse;
+		c.m_appliedImpulse = c.m_upperLimit;
+	}
+	else
+	{
+		c.m_appliedImpulse = sum;
+	}
+		body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+		body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+}
+
+ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+{
+#ifdef USE_SIMD
+	__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
+	__m128	lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+	__m128	upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+	__m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse),_mm_set1_ps(c.m_cfm)));
+	__m128 deltaVel1Dotn	=	_mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetDeltaAngularVelocity().mVec128));
+	__m128 deltaVel2Dotn	=	_mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetDeltaAngularVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetDeltaLinearVelocity().mVec128));
+	deltaImpulse	=	_mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+	deltaImpulse	=	_mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+	btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+	btSimdScalar resultLowerLess,resultUpperLess;
+	resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+	resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+	__m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+	deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+	c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+	__m128	linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
+	__m128	linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+	__m128 impulseMagnitude = deltaImpulse;
+	body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+	body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+	body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+	body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+#else
+	resolveSingleConstraintRowLowerLimit(body1,body2,c);
+#endif
+}
+
+// Project Gauss Seidel or the equivalent Sequential Impulse
+ void btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+{
+	btScalar deltaImpulse = c.m_rhs-btScalar(c.m_appliedImpulse)*c.m_cfm;
+	const btScalar deltaVel1Dotn	=	c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) 	+ c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
+	const btScalar deltaVel2Dotn	=	-c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
+
+	deltaImpulse	-=	deltaVel1Dotn*c.m_jacDiagABInv;
+	deltaImpulse	-=	deltaVel2Dotn*c.m_jacDiagABInv;
+	const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
+	if (sum < c.m_lowerLimit)
+	{
+		deltaImpulse = c.m_lowerLimit-c.m_appliedImpulse;
+		c.m_appliedImpulse = c.m_lowerLimit;
+	}
+	else
+	{
+		c.m_appliedImpulse = sum;
+	}
+	body1.internalApplyImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+	body2.internalApplyImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+}
+
+
+void	btSequentialImpulseConstraintSolver::resolveSplitPenetrationImpulseCacheFriendly(
+        btRigidBody& body1,
+        btRigidBody& body2,
+        const btSolverConstraint& c)
+{
+		if (c.m_rhsPenetration)
+        {
+			gNumSplitImpulseRecoveries++;
+			btScalar deltaImpulse = c.m_rhsPenetration-btScalar(c.m_appliedPushImpulse)*c.m_cfm;
+			const btScalar deltaVel1Dotn	=	c.m_contactNormal.dot(body1.internalGetPushVelocity()) 	+ c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
+			const btScalar deltaVel2Dotn	=	-c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
+
+			deltaImpulse	-=	deltaVel1Dotn*c.m_jacDiagABInv;
+			deltaImpulse	-=	deltaVel2Dotn*c.m_jacDiagABInv;
+			const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
+			if (sum < c.m_lowerLimit)
+			{
+				deltaImpulse = c.m_lowerLimit-c.m_appliedPushImpulse;
+				c.m_appliedPushImpulse = c.m_lowerLimit;
+			}
+			else
+			{
+				c.m_appliedPushImpulse = sum;
+			}
+			body1.internalApplyPushImpulse(c.m_contactNormal*body1.internalGetInvMass(),c.m_angularComponentA,deltaImpulse);
+			body2.internalApplyPushImpulse(-c.m_contactNormal*body2.internalGetInvMass(),c.m_angularComponentB,deltaImpulse);
+        }
+}
+
+ void btSequentialImpulseConstraintSolver::resolveSplitPenetrationSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& c)
+{
+#ifdef USE_SIMD
+	if (!c.m_rhsPenetration)
+		return;
+
+	gNumSplitImpulseRecoveries++;
+
+	__m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
+	__m128	lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
+	__m128	upperLimit1 = _mm_set1_ps(c.m_upperLimit);
+	__m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse),_mm_set1_ps(c.m_cfm)));
+	__m128 deltaVel1Dotn	=	_mm_add_ps(btSimdDot3(c.m_contactNormal.mVec128,body1.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128,body1.internalGetTurnVelocity().mVec128));
+	__m128 deltaVel2Dotn	=	_mm_sub_ps(btSimdDot3(c.m_relpos2CrossNormal.mVec128,body2.internalGetTurnVelocity().mVec128),btSimdDot3((c.m_contactNormal).mVec128,body2.internalGetPushVelocity().mVec128));
+	deltaImpulse	=	_mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel1Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+	deltaImpulse	=	_mm_sub_ps(deltaImpulse,_mm_mul_ps(deltaVel2Dotn,_mm_set1_ps(c.m_jacDiagABInv)));
+	btSimdScalar sum = _mm_add_ps(cpAppliedImp,deltaImpulse);
+	btSimdScalar resultLowerLess,resultUpperLess;
+	resultLowerLess = _mm_cmplt_ps(sum,lowerLimit1);
+	resultUpperLess = _mm_cmplt_ps(sum,upperLimit1);
+	__m128 lowMinApplied = _mm_sub_ps(lowerLimit1,cpAppliedImp);
+	deltaImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse) );
+	c.m_appliedImpulse = _mm_or_ps( _mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum) );
+	__m128	linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128,body1.internalGetInvMass().mVec128);
+	__m128	linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128,body2.internalGetInvMass().mVec128);
+	__m128 impulseMagnitude = deltaImpulse;
+	body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentA,impulseMagnitude));
+	body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentA.mVec128,impulseMagnitude));
+	body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128,_mm_mul_ps(linearComponentB,impulseMagnitude));
+	body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128 ,_mm_mul_ps(c.m_angularComponentB.mVec128,impulseMagnitude));
+#else
+	resolveSplitPenetrationImpulseCacheFriendly(body1,body2,c);
+#endif
+}
+
+
+
+unsigned long btSequentialImpulseConstraintSolver::btRand2()
+{
+	m_btSeed2 = (1664525L*m_btSeed2 + 1013904223L) & 0xffffffff;
+	return m_btSeed2;
+}
+
+
+
+//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
+int btSequentialImpulseConstraintSolver::btRandInt2 (int n)
+{
+	// seems good; xor-fold and modulus
+	const unsigned long un = static_cast<unsigned long>(n);
+	unsigned long r = btRand2();
+
+	// note: probably more aggressive than it needs to be -- might be
+	//       able to get away without one or two of the innermost branches.
+	if (un <= 0x00010000UL) {
+		r ^= (r >> 16);
+		if (un <= 0x00000100UL) {
+			r ^= (r >> 8);
+			if (un <= 0x00000010UL) {
+				r ^= (r >> 4);
+				if (un <= 0x00000004UL) {
+					r ^= (r >> 2);
+					if (un <= 0x00000002UL) {
+						r ^= (r >> 1);
+					}
+				}
+			}
+		}
+	}
+
+	return (int) (r % un);
+}
+
+
+#if 0
+void	btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject)
+{
+	btRigidBody* rb = collisionObject? btRigidBody::upcast(collisionObject) : 0;
+
+	solverBody->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+	solverBody->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+	solverBody->internalGetPushVelocity().setValue(0.f,0.f,0.f);
+	solverBody->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
+
+	if (rb)
+	{
+		solverBody->internalGetInvMass() = btVector3(rb->getInvMass(),rb->getInvMass(),rb->getInvMass())*rb->getLinearFactor();
+		solverBody->m_originalBody = rb;
+		solverBody->m_angularFactor = rb->getAngularFactor();
+	} else
+	{
+		solverBody->internalGetInvMass().setValue(0,0,0);
+		solverBody->m_originalBody = 0;
+		solverBody->m_angularFactor.setValue(1,1,1);
+	}
+}
+#endif
+
+
+
+
+
+btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution)
+{
+	btScalar rest = restitution * -rel_vel;
+	return rest;
+}
+
+
+
+void	applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection);
+void	applyAnisotropicFriction(btCollisionObject* colObj,btVector3& frictionDirection)
+{
+	if (colObj && colObj->hasAnisotropicFriction())
+	{
+		// transform to local coordinates
+		btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
+		const btVector3& friction_scaling = colObj->getAnisotropicFriction();
+		//apply anisotropic friction
+		loc_lateral *= friction_scaling;
+		// ... and transform it back to global coordinates
+		frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
+	}
+}
+
+
+void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+{
+
+
+	btRigidBody* body0=btRigidBody::upcast(colObj0);
+	btRigidBody* body1=btRigidBody::upcast(colObj1);
+
+	solverConstraint.m_contactNormal = normalAxis;
+
+	solverConstraint.m_solverBodyA = body0 ? body0 : &getFixedBody();
+	solverConstraint.m_solverBodyB = body1 ? body1 : &getFixedBody();
+
+	solverConstraint.m_friction = cp.m_combinedFriction;
+	solverConstraint.m_originalContactPoint = 0;
+
+	solverConstraint.m_appliedImpulse = 0.f;
+	solverConstraint.m_appliedPushImpulse = 0.f;
+
+	{
+		btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
+		solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
+		solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld()*ftorqueAxis1*body0->getAngularFactor() : btVector3(0,0,0);
+	}
+	{
+		btVector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
+		solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
+		solverConstraint.m_angularComponentB = body1 ? body1->getInvInertiaTensorWorld()*ftorqueAxis1*body1->getAngularFactor() : btVector3(0,0,0);
+	}
+
+#ifdef COMPUTE_IMPULSE_DENOM
+	btScalar denom0 = rb0->computeImpulseDenominator(pos1,solverConstraint.m_contactNormal);
+	btScalar denom1 = rb1->computeImpulseDenominator(pos2,solverConstraint.m_contactNormal);
+#else
+	btVector3 vec;
+	btScalar denom0 = 0.f;
+	btScalar denom1 = 0.f;
+	if (body0)
+	{
+		vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+		denom0 = body0->getInvMass() + normalAxis.dot(vec);
+	}
+	if (body1)
+	{
+		vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+		denom1 = body1->getInvMass() + normalAxis.dot(vec);
+	}
+
+
+#endif //COMPUTE_IMPULSE_DENOM
+	btScalar denom = relaxation/(denom0+denom1);
+	solverConstraint.m_jacDiagABInv = denom;
+
+#ifdef _USE_JACOBIAN
+	solverConstraint.m_jac =  btJacobianEntry (
+		rel_pos1,rel_pos2,solverConstraint.m_contactNormal,
+		body0->getInvInertiaDiagLocal(),
+		body0->getInvMass(),
+		body1->getInvInertiaDiagLocal(),
+		body1->getInvMass());
+#endif //_USE_JACOBIAN
+
+
+	{
+		btScalar rel_vel;
+		btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0?body0->getLinearVelocity():btVector3(0,0,0)) 
+			+ solverConstraint.m_relpos1CrossNormal.dot(body0?body0->getAngularVelocity():btVector3(0,0,0));
+		btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1?body1->getLinearVelocity():btVector3(0,0,0)) 
+			+ solverConstraint.m_relpos2CrossNormal.dot(body1?body1->getAngularVelocity():btVector3(0,0,0));
+
+		rel_vel = vel1Dotn+vel2Dotn;
+
+//		btScalar positionalError = 0.f;
+
+		btSimdScalar velocityError =  desiredVelocity - rel_vel;
+		btSimdScalar	velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
+		solverConstraint.m_rhs = velocityImpulse;
+		solverConstraint.m_cfm = cfmSlip;
+		solverConstraint.m_lowerLimit = 0;
+		solverConstraint.m_upperLimit = 1e10f;
+	}
+}
+
+
+
+btSolverConstraint&	btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
+{
+	btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
+	solverConstraint.m_frictionIndex = frictionIndex;
+	setupFrictionConstraint(solverConstraint, normalAxis, solverBodyA, solverBodyB, cp, rel_pos1, rel_pos2, 
+							colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
+	return solverConstraint;
+}
+
+int	btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body)
+{
+#if 0
+	int solverBodyIdA = -1;
+
+	if (body.getCompanionId() >= 0)
+	{
+		//body has already been converted
+		solverBodyIdA = body.getCompanionId();
+	} else
+	{
+		btRigidBody* rb = btRigidBody::upcast(&body);
+		if (rb && rb->getInvMass())
+		{
+			solverBodyIdA = m_tmpSolverBodyPool.size();
+			btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
+			initSolverBody(&solverBody,&body);
+			body.setCompanionId(solverBodyIdA);
+		} else
+		{
+			return 0;//assume first one is a fixed solver body
+		}
+	}
+	return solverBodyIdA;
+#endif
+	return 0;
+}
+#include <stdio.h>
+
+
+void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint, 
+																 btCollisionObject* colObj0, btCollisionObject* colObj1,
+																 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
+																 btVector3& vel, btScalar& rel_vel, btScalar& relaxation,
+																 btVector3& rel_pos1, btVector3& rel_pos2)
+{
+			btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+			btRigidBody* rb1 = btRigidBody::upcast(colObj1);
+
+			const btVector3& pos1 = cp.getPositionWorldOnA();
+			const btVector3& pos2 = cp.getPositionWorldOnB();
+
+//			btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); 
+//			btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+			rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin(); 
+			rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
+
+			relaxation = 1.f;
+
+			btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
+			solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld()*torqueAxis0*rb0->getAngularFactor() : btVector3(0,0,0);
+			btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);		
+			solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld()*-torqueAxis1*rb1->getAngularFactor() : btVector3(0,0,0);
+
+				{
+#ifdef COMPUTE_IMPULSE_DENOM
+					btScalar denom0 = rb0->computeImpulseDenominator(pos1,cp.m_normalWorldOnB);
+					btScalar denom1 = rb1->computeImpulseDenominator(pos2,cp.m_normalWorldOnB);
+#else							
+					btVector3 vec;
+					btScalar denom0 = 0.f;
+					btScalar denom1 = 0.f;
+					if (rb0)
+					{
+						vec = ( solverConstraint.m_angularComponentA).cross(rel_pos1);
+						denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+					}
+					if (rb1)
+					{
+						vec = ( -solverConstraint.m_angularComponentB).cross(rel_pos2);
+						denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
+					}
+#endif //COMPUTE_IMPULSE_DENOM		
+
+					btScalar denom = relaxation/(denom0+denom1);
+					solverConstraint.m_jacDiagABInv = denom;
+				}
+
+				solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
+				solverConstraint.m_relpos1CrossNormal = rel_pos1.cross(cp.m_normalWorldOnB);
+				solverConstraint.m_relpos2CrossNormal = rel_pos2.cross(-cp.m_normalWorldOnB);
+
+
+
+
+			btVector3 vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0,0,0);
+			btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
+			vel  = vel1 - vel2;
+			rel_vel = cp.m_normalWorldOnB.dot(vel);
+
+				btScalar penetration = cp.getDistance()+infoGlobal.m_linearSlop;
+
+
+				solverConstraint.m_friction = cp.m_combinedFriction;
+
+				btScalar restitution = 0.f;
+				
+				if (cp.m_lifeTime>infoGlobal.m_restingContactRestitutionThreshold)
+				{
+					restitution = 0.f;
+				} else
+				{
+					restitution =  restitutionCurve(rel_vel, cp.m_combinedRestitution);
+					if (restitution <= btScalar(0.))
+					{
+						restitution = 0.f;
+					};
+				}
+
+
+				///warm starting (or zero if disabled)
+				if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+				{
+					solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
+					if (rb0)
+						rb0->internalApplyImpulse(solverConstraint.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),solverConstraint.m_angularComponentA,solverConstraint.m_appliedImpulse);
+					if (rb1)
+						rb1->internalApplyImpulse(solverConstraint.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-solverConstraint.m_angularComponentB,-(btScalar)solverConstraint.m_appliedImpulse);
+				} else
+				{
+					solverConstraint.m_appliedImpulse = 0.f;
+				}
+
+				solverConstraint.m_appliedPushImpulse = 0.f;
+
+				{
+					btScalar rel_vel;
+					btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0?rb0->getLinearVelocity():btVector3(0,0,0)) 
+						+ solverConstraint.m_relpos1CrossNormal.dot(rb0?rb0->getAngularVelocity():btVector3(0,0,0));
+					btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1?rb1->getLinearVelocity():btVector3(0,0,0)) 
+						+ solverConstraint.m_relpos2CrossNormal.dot(rb1?rb1->getAngularVelocity():btVector3(0,0,0));
+
+					rel_vel = vel1Dotn+vel2Dotn;
+
+					btScalar positionalError = 0.f;
+					btScalar	velocityError = restitution - rel_vel;// * damping;
+
+					if (penetration>0)
+					{
+						positionalError = 0;
+						velocityError -= penetration / infoGlobal.m_timeStep;
+					} else
+					{
+						positionalError = -penetration * infoGlobal.m_erp/infoGlobal.m_timeStep;
+					}
+
+					btScalar  penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+					btScalar velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+					if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
+					{
+						//combine position and velocity into rhs
+						solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+						solverConstraint.m_rhsPenetration = 0.f;
+					} else
+					{
+						//split position and velocity into rhs and m_rhsPenetration
+						solverConstraint.m_rhs = velocityImpulse;
+						solverConstraint.m_rhsPenetration = penetrationImpulse;
+					}
+					solverConstraint.m_cfm = 0.f;
+					solverConstraint.m_lowerLimit = 0;
+					solverConstraint.m_upperLimit = 1e10f;
+				}
+
+
+
+
+}
+
+
+
+void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, 
+																		btRigidBody* rb0, btRigidBody* rb1, 
+																 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
+{
+					if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING)
+					{
+						{
+							btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+							if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+							{
+								frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
+								if (rb0)
+									rb0->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb0->getInvMass()*rb0->getLinearFactor(),frictionConstraint1.m_angularComponentA,frictionConstraint1.m_appliedImpulse);
+								if (rb1)
+									rb1->internalApplyImpulse(frictionConstraint1.m_contactNormal*rb1->getInvMass()*rb1->getLinearFactor(),-frictionConstraint1.m_angularComponentB,-(btScalar)frictionConstraint1.m_appliedImpulse);
+							} else
+							{
+								frictionConstraint1.m_appliedImpulse = 0.f;
+							}
+						}
+
+						if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+						{
+							btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+							if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
+							{
+								frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
+								if (rb0)
+									rb0->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb0->getInvMass(),frictionConstraint2.m_angularComponentA,frictionConstraint2.m_appliedImpulse);
+								if (rb1)
+									rb1->internalApplyImpulse(frictionConstraint2.m_contactNormal*rb1->getInvMass(),-frictionConstraint2.m_angularComponentB,-(btScalar)frictionConstraint2.m_appliedImpulse);
+							} else
+							{
+								frictionConstraint2.m_appliedImpulse = 0.f;
+							}
+						}
+					} else
+					{
+						btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
+						frictionConstraint1.m_appliedImpulse = 0.f;
+						if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+						{
+							btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex+1];
+							frictionConstraint2.m_appliedImpulse = 0.f;
+						}
+					}
+}
+
+
+
+
+void	btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal)
+{
+	btCollisionObject* colObj0=0,*colObj1=0;
+
+	colObj0 = (btCollisionObject*)manifold->getBody0();
+	colObj1 = (btCollisionObject*)manifold->getBody1();
+
+
+	btRigidBody* solverBodyA = btRigidBody::upcast(colObj0);
+	btRigidBody* solverBodyB = btRigidBody::upcast(colObj1);
+
+	///avoid collision response between two static objects
+	if ((!solverBodyA || !solverBodyA->getInvMass()) && (!solverBodyB || !solverBodyB->getInvMass()))
+		return;
+
+	for (int j=0;j<manifold->getNumContacts();j++)
+	{
+
+		btManifoldPoint& cp = manifold->getContactPoint(j);
+
+		if (cp.getDistance() <= manifold->getContactProcessingThreshold())
+		{
+			btVector3 rel_pos1;
+			btVector3 rel_pos2;
+			btScalar relaxation;
+			btScalar rel_vel;
+			btVector3 vel;
+
+			int frictionIndex = m_tmpSolverContactConstraintPool.size();
+			btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
+			btRigidBody* rb0 = btRigidBody::upcast(colObj0);
+			btRigidBody* rb1 = btRigidBody::upcast(colObj1);
+			solverConstraint.m_solverBodyA = rb0? rb0 : &getFixedBody();
+			solverConstraint.m_solverBodyB = rb1? rb1 : &getFixedBody();
+			solverConstraint.m_originalContactPoint = &cp;
+
+			setupContactConstraint(solverConstraint, colObj0, colObj1, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
+
+//			const btVector3& pos1 = cp.getPositionWorldOnA();
+//			const btVector3& pos2 = cp.getPositionWorldOnB();
+
+			/////setup the friction constraints
+
+			solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
+
+			if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized)
+			{
+				cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
+				btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
+				if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
+				{
+					cp.m_lateralFrictionDir1 /= btSqrt(lat_rel_vel);
+					if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+					{
+						cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
+						cp.m_lateralFrictionDir2.normalize();//??
+						applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
+						applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
+						addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+					}
+
+					applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
+					applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
+					addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+					cp.m_lateralFrictionInitialized = true;
+				} else
+				{
+					//re-calculate friction direction every frame, todo: check if this is really needed
+					btPlaneSpace1(cp.m_normalWorldOnB,cp.m_lateralFrictionDir1,cp.m_lateralFrictionDir2);
+					if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+					{
+						applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2);
+						applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2);
+						addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+					}
+
+					applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1);
+					applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1);
+					addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
+
+					cp.m_lateralFrictionInitialized = true;
+				}
+
+			} else
+			{
+				addFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation,cp.m_contactMotion1, cp.m_contactCFM1);
+				if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
+					addFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyA,solverBodyB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
+			}
+			
+			setFrictionConstraintImpulse( solverConstraint, rb0, rb1, cp, infoGlobal);
+
+		}
+	}
+}
+
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
+{
+	BT_PROFILE("solveGroupCacheFriendlySetup");
+	(void)stackAlloc;
+	(void)debugDrawer;
+
+
+	if (!(numConstraints + numManifolds))
+	{
+		//		printf("empty\n");
+		return 0.f;
+	}
+
+	if (infoGlobal.m_splitImpulse)
+	{
+		for (int i = 0; i < numBodies; i++)
+		{
+			btRigidBody* body = btRigidBody::upcast(bodies[i]);
+			if (body)
+			{	
+				body->internalGetDeltaLinearVelocity().setZero();
+				body->internalGetDeltaAngularVelocity().setZero();
+				body->internalGetPushVelocity().setZero();
+				body->internalGetTurnVelocity().setZero();
+			}
+		}
+	}
+	else
+	{
+		for (int i = 0; i < numBodies; i++)
+		{
+			btRigidBody* body = btRigidBody::upcast(bodies[i]);
+			if (body)
+			{	
+				body->internalGetDeltaLinearVelocity().setZero();
+				body->internalGetDeltaAngularVelocity().setZero();
+			}
+		}
+	}
+
+	if (1)
+	{
+		int j;
+		for (j=0;j<numConstraints;j++)
+		{
+			btTypedConstraint* constraint = constraints[j];
+			constraint->buildJacobian();
+			constraint->internalSetAppliedImpulse(0.0f);
+		}
+	}
+	//btRigidBody* rb0=0,*rb1=0;
+
+	//if (1)
+	{
+		{
+
+			int totalNumRows = 0;
+			int i;
+			
+			m_tmpConstraintSizesPool.resize(numConstraints);
+			//calculate the total number of contraint rows
+			for (i=0;i<numConstraints;i++)
+			{
+				btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+				if (constraints[i]->isEnabled())
+				{
+					constraints[i]->getInfo1(&info1);
+				} else
+				{
+					info1.m_numConstraintRows = 0;
+					info1.nub = 0;
+				}
+				totalNumRows += info1.m_numConstraintRows;
+			}
+			m_tmpSolverNonContactConstraintPool.resize(totalNumRows);
+
+			
+			///setup the btSolverConstraints
+			int currentRow = 0;
+
+			for (i=0;i<numConstraints;i++)
+			{
+				const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
+				
+				if (info1.m_numConstraintRows)
+				{
+					btAssert(currentRow<totalNumRows);
+
+					btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
+					btTypedConstraint* constraint = constraints[i];
+
+
+					btRigidBody& rbA = constraint->getRigidBodyA();
+					btRigidBody& rbB = constraint->getRigidBodyB();
+
+					
+					int j;
+					for ( j=0;j<info1.m_numConstraintRows;j++)
+					{
+						memset(&currentConstraintRow[j],0,sizeof(btSolverConstraint));
+						currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
+						currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
+						currentConstraintRow[j].m_appliedImpulse = 0.f;
+						currentConstraintRow[j].m_appliedPushImpulse = 0.f;
+						currentConstraintRow[j].m_solverBodyA = &rbA;
+						currentConstraintRow[j].m_solverBodyB = &rbB;
+					}
+
+					rbA.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+					rbA.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+					rbB.internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
+					rbB.internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
+
+
+
+					btTypedConstraint::btConstraintInfo2 info2;
+					info2.fps = 1.f/infoGlobal.m_timeStep;
+					info2.erp = infoGlobal.m_erp;
+					info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
+					info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
+					info2.m_J2linearAxis = 0;
+					info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
+					info2.rowskip = sizeof(btSolverConstraint)/sizeof(btScalar);//check this
+					///the size of btSolverConstraint needs be a multiple of btScalar
+					btAssert(info2.rowskip*sizeof(btScalar)== sizeof(btSolverConstraint));
+					info2.m_constraintError = &currentConstraintRow->m_rhs;
+					currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
+					info2.m_damping = infoGlobal.m_damping;
+					info2.cfm = &currentConstraintRow->m_cfm;
+					info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
+					info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
+					info2.m_numIterations = infoGlobal.m_numIterations;
+					constraints[i]->getInfo2(&info2);
+
+					if (currentConstraintRow->m_upperLimit>constraints[i]->getBreakingImpulseThreshold())
+					{
+						currentConstraintRow->m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
+					}
+
+					if (currentConstraintRow->m_lowerLimit<-constraints[i]->getBreakingImpulseThreshold())
+					{
+						currentConstraintRow->m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
+					}
+
+
+
+					///finalize the constraint setup
+					for ( j=0;j<info1.m_numConstraintRows;j++)
+					{
+						btSolverConstraint& solverConstraint = currentConstraintRow[j];
+						solverConstraint.m_originalContactPoint = constraint;
+
+						{
+							const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
+							solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld()*ftorqueAxis1*constraint->getRigidBodyA().getAngularFactor();
+						}
+						{
+							const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
+							solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld()*ftorqueAxis2*constraint->getRigidBodyB().getAngularFactor();
+						}
+
+						{
+							btVector3 iMJlA = solverConstraint.m_contactNormal*rbA.getInvMass();
+							btVector3 iMJaA = rbA.getInvInertiaTensorWorld()*solverConstraint.m_relpos1CrossNormal;
+							btVector3 iMJlB = solverConstraint.m_contactNormal*rbB.getInvMass();//sign of normal?
+							btVector3 iMJaB = rbB.getInvInertiaTensorWorld()*solverConstraint.m_relpos2CrossNormal;
+
+							btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
+							sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
+							sum += iMJlB.dot(solverConstraint.m_contactNormal);
+							sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
+
+							solverConstraint.m_jacDiagABInv = btScalar(1.)/sum;
+						}
+
+
+						///fix rhs
+						///todo: add force/torque accelerators
+						{
+							btScalar rel_vel;
+							btScalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.getLinearVelocity()) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity());
+							btScalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.getLinearVelocity()) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity());
+
+							rel_vel = vel1Dotn+vel2Dotn;
+
+							btScalar restitution = 0.f;
+							btScalar positionalError = solverConstraint.m_rhs;//already filled in by getConstraintInfo2
+							btScalar	velocityError = restitution - rel_vel * info2.m_damping;
+							btScalar	penetrationImpulse = positionalError*solverConstraint.m_jacDiagABInv;
+							btScalar	velocityImpulse = velocityError *solverConstraint.m_jacDiagABInv;
+							solverConstraint.m_rhs = penetrationImpulse+velocityImpulse;
+							solverConstraint.m_appliedImpulse = 0.f;
+
+						}
+					}
+				}
+				currentRow+=m_tmpConstraintSizesPool[i].m_numConstraintRows;
+			}
+		}
+
+		{
+			int i;
+			btPersistentManifold* manifold = 0;
+//			btCollisionObject* colObj0=0,*colObj1=0;
+
+
+			for (i=0;i<numManifolds;i++)
+			{
+				manifold = manifoldPtr[i];
+				convertContact(manifold,infoGlobal);
+			}
+		}
+	}
+
+	btContactSolverInfo info = infoGlobal;
+
+
+
+	int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+	int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+	///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
+	m_orderTmpConstraintPool.resize(numConstraintPool);
+	m_orderFrictionConstraintPool.resize(numFrictionPool);
+	{
+		int i;
+		for (i=0;i<numConstraintPool;i++)
+		{
+			m_orderTmpConstraintPool[i] = i;
+		}
+		for (i=0;i<numFrictionPool;i++)
+		{
+			m_orderFrictionConstraintPool[i] = i;
+		}
+	}
+
+	return 0.f;
+
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */,int /*numBodies*/,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
+{
+
+	int numConstraintPool = m_tmpSolverContactConstraintPool.size();
+	int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
+
+	int j;
+
+	if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
+	{
+		if ((iteration & 7) == 0) {
+			for (j=0; j<numConstraintPool; ++j) {
+				int tmp = m_orderTmpConstraintPool[j];
+				int swapi = btRandInt2(j+1);
+				m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
+				m_orderTmpConstraintPool[swapi] = tmp;
+			}
+
+			for (j=0; j<numFrictionPool; ++j) {
+				int tmp = m_orderFrictionConstraintPool[j];
+				int swapi = btRandInt2(j+1);
+				m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
+				m_orderFrictionConstraintPool[swapi] = tmp;
+			}
+		}
+	}
+
+	if (infoGlobal.m_solverMode & SOLVER_SIMD)
+	{
+		///solve all joint constraints, using SIMD, if available
+		for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+		{
+			btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
+			resolveSingleConstraintRowGenericSIMD(*constraint.m_solverBodyA,*constraint.m_solverBodyB,constraint);
+		}
+
+		for (j=0;j<numConstraints;j++)
+		{
+			constraints[j]->solveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
+		}
+
+		///solve all contact constraints using SIMD, if available
+		int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+		for (j=0;j<numPoolConstraints;j++)
+		{
+			const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+			resolveSingleConstraintRowLowerLimitSIMD(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+
+		}
+		///solve all friction constraints, using SIMD, if available
+		int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+		for (j=0;j<numFrictionPoolConstraints;j++)
+		{
+			btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+			btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+			if (totalImpulse>btScalar(0))
+			{
+				solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+				solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+				resolveSingleConstraintRowGenericSIMD(*solveManifold.m_solverBodyA,	*solveManifold.m_solverBodyB,solveManifold);
+			}
+		}
+	} else
+	{
+
+		///solve all joint constraints
+		for (j=0;j<m_tmpSolverNonContactConstraintPool.size();j++)
+		{
+			btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
+			resolveSingleConstraintRowGeneric(*constraint.m_solverBodyA,*constraint.m_solverBodyB,constraint);
+		}
+
+		for (j=0;j<numConstraints;j++)
+		{
+			constraints[j]->solveConstraintObsolete(constraints[j]->getRigidBodyA(),constraints[j]->getRigidBodyB(),infoGlobal.m_timeStep);
+		}
+		///solve all contact constraints
+		int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+		for (j=0;j<numPoolConstraints;j++)
+		{
+			const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+			resolveSingleConstraintRowLowerLimit(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+		}
+		///solve all friction constraints
+		int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
+		for (j=0;j<numFrictionPoolConstraints;j++)
+		{
+			btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
+			btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+
+			if (totalImpulse>btScalar(0))
+			{
+				solveManifold.m_lowerLimit = -(solveManifold.m_friction*totalImpulse);
+				solveManifold.m_upperLimit = solveManifold.m_friction*totalImpulse;
+
+				resolveSingleConstraintRowGeneric(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+			}
+		}
+	}
+	return 0.f;
+}
+
+
+void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
+{
+	int iteration;
+	if (infoGlobal.m_splitImpulse)
+	{
+		if (infoGlobal.m_solverMode & SOLVER_SIMD)
+		{
+			for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+			{
+				{
+					int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+					int j;
+					for (j=0;j<numPoolConstraints;j++)
+					{
+						const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+						resolveSplitPenetrationSIMD(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+					}
+				}
+			}
+		}
+		else
+		{
+			for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+			{
+				{
+					int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+					int j;
+					for (j=0;j<numPoolConstraints;j++)
+					{
+						const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
+
+						resolveSplitPenetrationImpulseCacheFriendly(*solveManifold.m_solverBodyA,*solveManifold.m_solverBodyB,solveManifold);
+					}
+				}
+			}
+		}
+	}
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc)
+{
+	BT_PROFILE("solveGroupCacheFriendlyIterations");
+
+	
+	//should traverse the contacts random order...
+	int iteration;
+	{
+		solveGroupCacheFriendlySplitImpulseIterations(bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
+
+		for ( iteration = 0;iteration<infoGlobal.m_numIterations;iteration++)
+		{			
+			solveSingleIteration(iteration, bodies ,numBodies,manifoldPtr, numManifolds,constraints,numConstraints,infoGlobal,debugDrawer,stackAlloc);
+		}
+		
+	}
+	return 0.f;
+}
+
+btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/,btTypedConstraint** /*constraints*/,int /* numConstraints*/,const btContactSolverInfo& infoGlobal,btIDebugDraw* /*debugDrawer*/,btStackAlloc* /*stackAlloc*/)
+{
+	int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
+	int i,j;
+
+	for (j=0;j<numPoolConstraints;j++)
+	{
+
+		const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
+		btManifoldPoint* pt = (btManifoldPoint*) solveManifold.m_originalContactPoint;
+		btAssert(pt);
+		pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
+		if (infoGlobal.m_solverMode & SOLVER_USE_FRICTION_WARMSTARTING)
+		{
+			pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
+			pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex+1].m_appliedImpulse;
+		}
+
+		//do a callback here?
+	}
+
+	numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
+	for (j=0;j<numPoolConstraints;j++)
+	{
+		const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
+		btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
+		constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
+		if (solverConstr.m_appliedImpulse>constr->getBreakingImpulseThreshold())
+		{
+			constr->setEnabled(false);
+		}
+	}
+
+
+	if (infoGlobal.m_splitImpulse)
+	{		
+		for ( i=0;i<numBodies;i++)
+		{
+			btRigidBody* body = btRigidBody::upcast(bodies[i]);
+			if (body)
+				body->internalWritebackVelocity(infoGlobal.m_timeStep);
+		}
+	} else
+	{
+		for ( i=0;i<numBodies;i++)
+		{
+			btRigidBody* body = btRigidBody::upcast(bodies[i]);
+			if (body)
+				body->internalWritebackVelocity();
+		}
+	}
+
+
+	m_tmpSolverContactConstraintPool.resize(0);
+	m_tmpSolverNonContactConstraintPool.resize(0);
+	m_tmpSolverContactFrictionConstraintPool.resize(0);
+
+	return 0.f;
+}
+
+
+
+/// btSequentialImpulseConstraintSolver Sequentially applies impulses
+btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/)
+{
+
+	BT_PROFILE("solveGroup");
+	//you need to provide at least some bodies
+	btAssert(bodies);
+	btAssert(numBodies);
+
+	solveGroupCacheFriendlySetup( bodies, numBodies, manifoldPtr,  numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
+
+	solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr,  numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
+
+	solveGroupCacheFriendlyFinish(bodies, numBodies, manifoldPtr,  numManifolds,constraints, numConstraints,infoGlobal,debugDrawer, stackAlloc);
+	
+	return 0.f;
+}
+
+void	btSequentialImpulseConstraintSolver::reset()
+{
+	m_btSeed2 = 0;
+}
+
+btRigidBody& btSequentialImpulseConstraintSolver::getFixedBody()
+{
+	static btRigidBody s_fixed(0, 0,0);
+	s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+	return s_fixed;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+
+#include "btConstraintSolver.h"
+class btIDebugDraw;
+#include "btContactConstraint.h"
+#include "btSolverBody.h"
+#include "btSolverConstraint.h"
+#include "btTypedConstraint.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+
+///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
+class btSequentialImpulseConstraintSolver : public btConstraintSolver
+{
+protected:
+
+	btConstraintArray			m_tmpSolverContactConstraintPool;
+	btConstraintArray			m_tmpSolverNonContactConstraintPool;
+	btConstraintArray			m_tmpSolverContactFrictionConstraintPool;
+	btAlignedObjectArray<int>	m_orderTmpConstraintPool;
+	btAlignedObjectArray<int>	m_orderFrictionConstraintPool;
+	btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool;
+
+	void setupFrictionConstraint(	btSolverConstraint& solverConstraint, const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyIdB,
+									btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,
+									btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, 
+									btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+
+	btSolverConstraint&	addFrictionConstraint(const btVector3& normalAxis,btRigidBody* solverBodyA,btRigidBody* solverBodyB,int frictionIndex,btManifoldPoint& cp,const btVector3& rel_pos1,const btVector3& rel_pos2,btCollisionObject* colObj0,btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity=0., btScalar cfmSlip=0.);
+	
+	void setupContactConstraint(btSolverConstraint& solverConstraint, btCollisionObject* colObj0, btCollisionObject* colObj1, btManifoldPoint& cp, 
+								const btContactSolverInfo& infoGlobal, btVector3& vel, btScalar& rel_vel, btScalar& relaxation, 
+								btVector3& rel_pos1, btVector3& rel_pos2);
+
+	void setFrictionConstraintImpulse( btSolverConstraint& solverConstraint, btRigidBody* rb0, btRigidBody* rb1, 
+										 btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
+
+	///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
+	unsigned long	m_btSeed2;
+
+//	void	initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject);
+	btScalar restitutionCurve(btScalar rel_vel, btScalar restitution);
+
+	void	convertContact(btPersistentManifold* manifold,const btContactSolverInfo& infoGlobal);
+
+
+	void	resolveSplitPenetrationSIMD(
+        btRigidBody& body1,
+        btRigidBody& body2,
+        const btSolverConstraint& contactConstraint);
+
+	void	resolveSplitPenetrationImpulseCacheFriendly(
+        btRigidBody& body1,
+        btRigidBody& body2,
+        const btSolverConstraint& contactConstraint);
+
+	//internal method
+	int	getOrInitSolverBody(btCollisionObject& body);
+
+	void	resolveSingleConstraintRowGeneric(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+
+	void	resolveSingleConstraintRowGenericSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+	
+	void	resolveSingleConstraintRowLowerLimit(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+	
+	void	resolveSingleConstraintRowLowerLimitSIMD(btRigidBody& body1,btRigidBody& body2,const btSolverConstraint& contactConstraint);
+		
+protected:
+	static btRigidBody& getFixedBody();
+	
+	virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
+	virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
+	btScalar solveSingleIteration(int iteration, btCollisionObject** bodies ,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
+
+	virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
+	virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc);
+
+
+public:
+
+	
+	btSequentialImpulseConstraintSolver();
+	virtual ~btSequentialImpulseConstraintSolver();
+
+	virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btStackAlloc* stackAlloc,btDispatcher* dispatcher);
+	
+
+	
+	///clear internal cached data and reset random seed
+	virtual	void	reset();
+	
+	unsigned long btRand2();
+
+	int btRandInt2 (int n);
+
+	void	setRandSeed(unsigned long seed)
+	{
+		m_btSeed2 = seed;
+	}
+	unsigned long	getRandSeed() const
+	{
+		return m_btSeed2;
+	}
+
+};
+
+#ifndef BT_PREFER_SIMD
+typedef btSequentialImpulseConstraintSolver btSequentialImpulseConstraintSolverPrefered;
+#endif
+
+
+#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp	(revision 11817)
@@ -0,0 +1,857 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Added by Roman Ponomarev (rponom@gmail.com)
+April 04, 2008
+*/
+
+
+
+#include "btSliderConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+#include <new>
+
+#define USE_OFFSET_FOR_CONSTANT_FRAME true
+
+void btSliderConstraint::initParams()
+{
+    m_lowerLinLimit = btScalar(1.0);
+    m_upperLinLimit = btScalar(-1.0);
+    m_lowerAngLimit = btScalar(0.);
+    m_upperAngLimit = btScalar(0.);
+	m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+	m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+	m_dampingDirLin = btScalar(0.);
+	m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM;
+	m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+	m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+	m_dampingDirAng = btScalar(0.);
+	m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM;
+	m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+	m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+	m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+	m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM;
+	m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+	m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+	m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+	m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM;
+	m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+	m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+	m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
+	m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM;
+	m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
+	m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
+	m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
+	m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM;
+
+	m_poweredLinMotor = false;
+    m_targetLinMotorVelocity = btScalar(0.);
+    m_maxLinMotorForce = btScalar(0.);
+	m_accumulatedLinMotorImpulse = btScalar(0.0);
+
+	m_poweredAngMotor = false;
+    m_targetAngMotorVelocity = btScalar(0.);
+    m_maxAngMotorForce = btScalar(0.);
+	m_accumulatedAngMotorImpulse = btScalar(0.0);
+
+	m_flags = 0;
+	m_flags = 0;
+
+	m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
+
+	calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+}
+
+
+
+
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
+        : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
+		m_useSolveConstraintObsolete(false),
+		m_frameInA(frameInA),
+        m_frameInB(frameInB),
+		m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+	initParams();
+}
+
+
+
+btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
+        : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
+		m_useSolveConstraintObsolete(false),
+		m_frameInB(frameInB),
+		m_useLinearReferenceFrameA(useLinearReferenceFrameA)
+{
+	///not providing rigidbody A means implicitly using worldspace for body A
+	m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
+//	m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
+
+	initParams();
+}
+
+
+
+
+
+
+void btSliderConstraint::getInfo1(btConstraintInfo1* info)
+{
+	if (m_useSolveConstraintObsolete)
+	{
+		info->m_numConstraintRows = 0;
+		info->nub = 0;
+	}
+	else
+	{
+		info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
+		info->nub = 2; 
+		//prepare constraint
+		calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+		testAngLimits();
+		testLinLimits();
+		if(getSolveLinLimit() || getPoweredLinMotor())
+		{
+			info->m_numConstraintRows++; // limit 3rd linear as well
+			info->nub--; 
+		}
+		if(getSolveAngLimit() || getPoweredAngMotor())
+		{
+			info->m_numConstraintRows++; // limit 3rd angular as well
+			info->nub--; 
+		}
+	}
+}
+
+void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
+{
+
+	info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
+	info->nub = 0; 
+}
+
+void btSliderConstraint::getInfo2(btConstraintInfo2* info)
+{
+	getInfo2NonVirtual(info,m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(),m_rbB.getLinearVelocity(), m_rbA.getInvMass(),m_rbB.getInvMass());
+}
+
+
+
+
+
+
+
+void btSliderConstraint::calculateTransforms(const btTransform& transA,const btTransform& transB)
+{
+	if(m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
+	{
+		m_calculatedTransformA = transA * m_frameInA;
+		m_calculatedTransformB = transB * m_frameInB;
+	}
+	else
+	{
+		m_calculatedTransformA = transB * m_frameInB;
+		m_calculatedTransformB = transA * m_frameInA;
+	}
+	m_realPivotAInW = m_calculatedTransformA.getOrigin();
+	m_realPivotBInW = m_calculatedTransformB.getOrigin();
+	m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
+	if(m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
+	{
+		m_delta = m_realPivotBInW - m_realPivotAInW;
+	}
+	else
+	{
+		m_delta = m_realPivotAInW - m_realPivotBInW;
+	}
+	m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
+    btVector3 normalWorld;
+    int i;
+    //linear part
+    for(i = 0; i < 3; i++)
+    {
+		normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
+		m_depth[i] = m_delta.dot(normalWorld);
+    }
+}
+ 
+
+
+void btSliderConstraint::testLinLimits(void)
+{
+	m_solveLinLim = false;
+	m_linPos = m_depth[0];
+	if(m_lowerLinLimit <= m_upperLinLimit)
+	{
+		if(m_depth[0] > m_upperLinLimit)
+		{
+			m_depth[0] -= m_upperLinLimit;
+			m_solveLinLim = true;
+		}
+		else if(m_depth[0] < m_lowerLinLimit)
+		{
+			m_depth[0] -= m_lowerLinLimit;
+			m_solveLinLim = true;
+		}
+		else
+		{
+			m_depth[0] = btScalar(0.);
+		}
+	}
+	else
+	{
+		m_depth[0] = btScalar(0.);
+	}
+}
+
+
+
+void btSliderConstraint::testAngLimits(void)
+{
+	m_angDepth = btScalar(0.);
+	m_solveAngLim = false;
+	if(m_lowerAngLimit <= m_upperAngLimit)
+	{
+		const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
+		const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
+		const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
+//		btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));  
+		btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));  
+		rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
+		m_angPos = rot;
+		if(rot < m_lowerAngLimit)
+		{
+			m_angDepth = rot - m_lowerAngLimit;
+			m_solveAngLim = true;
+		} 
+		else if(rot > m_upperAngLimit)
+		{
+			m_angDepth = rot - m_upperAngLimit;
+			m_solveAngLim = true;
+		}
+	}
+}
+
+btVector3 btSliderConstraint::getAncorInA(void)
+{
+	btVector3 ancorInA;
+	ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
+	ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
+	return ancorInA;
+}
+
+
+
+btVector3 btSliderConstraint::getAncorInB(void)
+{
+	btVector3 ancorInB;
+	ancorInB = m_frameInB.getOrigin();
+	return ancorInB;
+}
+
+
+void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA,const btTransform& transB, const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass  )
+{
+	const btTransform& trA = getCalculatedTransformA();
+	const btTransform& trB = getCalculatedTransformB();
+	
+	btAssert(!m_useSolveConstraintObsolete);
+	int i, s = info->rowskip;
+	
+	btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
+	
+	// difference between frames in WCS
+	btVector3 ofs = trB.getOrigin() - trA.getOrigin();
+	// now get weight factors depending on masses
+	btScalar miA = rbAinvMass;
+	btScalar miB = rbBinvMass;
+	bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
+	btScalar miS = miA + miB;
+	btScalar factA, factB;
+	if(miS > btScalar(0.f))
+	{
+		factA = miB / miS;
+	}
+	else 
+	{
+		factA = btScalar(0.5f);
+	}
+	factB = btScalar(1.0f) - factA;
+	btVector3 ax1, p, q;
+	btVector3 ax1A = trA.getBasis().getColumn(0);
+	btVector3 ax1B = trB.getBasis().getColumn(0);
+	if(m_useOffsetForConstraintFrame)
+	{
+		// get the desired direction of slider axis
+		// as weighted sum of X-orthos of frameA and frameB in WCS
+		ax1 = ax1A * factA + ax1B * factB;
+		ax1.normalize();
+		// construct two orthos to slider axis
+		btPlaneSpace1 (ax1, p, q);
+	}
+	else
+	{ // old way - use frameA
+		ax1 = trA.getBasis().getColumn(0);
+		// get 2 orthos to slider axis (Y, Z)
+		p = trA.getBasis().getColumn(1);
+		q = trA.getBasis().getColumn(2);
+	}
+	// make rotations around these orthos equal
+	// the slider axis should be the only unconstrained
+	// rotational axis, the angular velocity of the two bodies perpendicular to
+	// the slider axis should be equal. thus the constraint equations are
+	//    p*w1 - p*w2 = 0
+	//    q*w1 - q*w2 = 0
+	// where p and q are unit vectors normal to the slider axis, and w1 and w2
+	// are the angular velocity vectors of the two bodies.
+	info->m_J1angularAxis[0] = p[0];
+	info->m_J1angularAxis[1] = p[1];
+	info->m_J1angularAxis[2] = p[2];
+	info->m_J1angularAxis[s+0] = q[0];
+	info->m_J1angularAxis[s+1] = q[1];
+	info->m_J1angularAxis[s+2] = q[2];
+
+	info->m_J2angularAxis[0] = -p[0];
+	info->m_J2angularAxis[1] = -p[1];
+	info->m_J2angularAxis[2] = -p[2];
+	info->m_J2angularAxis[s+0] = -q[0];
+	info->m_J2angularAxis[s+1] = -q[1];
+	info->m_J2angularAxis[s+2] = -q[2];
+	// compute the right hand side of the constraint equation. set relative
+	// body velocities along p and q to bring the slider back into alignment.
+	// if ax1A,ax1B are the unit length slider axes as computed from bodyA and
+	// bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
+	// if "theta" is the angle between ax1 and ax2, we need an angular velocity
+	// along u to cover angle erp*theta in one step :
+	//   |angular_velocity| = angle/time = erp*theta / stepsize
+	//                      = (erp*fps) * theta
+	//    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
+	//                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
+	// ...as ax1 and ax2 are unit length. if theta is smallish,
+	// theta ~= sin(theta), so
+	//    angular_velocity  = (erp*fps) * (ax1 x ax2)
+	// ax1 x ax2 is in the plane space of ax1, so we project the angular
+	// velocity to p and q to find the right hand side.
+//	btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
+	btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
+	btScalar k = info->fps * currERP;
+
+	btVector3 u = ax1A.cross(ax1B);
+	info->m_constraintError[0] = k * u.dot(p);
+	info->m_constraintError[s] = k * u.dot(q);
+	if(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
+	{
+		info->cfm[0] = m_cfmOrthoAng;
+		info->cfm[s] = m_cfmOrthoAng;
+	}
+
+	int nrow = 1; // last filled row
+	int srow;
+	btScalar limit_err;
+	int limit;
+	int powered;
+
+	// next two rows. 
+	// we want: velA + wA x relA == velB + wB x relB ... but this would
+	// result in three equations, so we project along two orthos to the slider axis
+
+	btTransform bodyA_trans = transA;
+	btTransform bodyB_trans = transB;
+	nrow++;
+	int s2 = nrow * s;
+	nrow++;
+	int s3 = nrow * s;
+	btVector3 tmpA(0,0,0), tmpB(0,0,0), relA(0,0,0), relB(0,0,0), c(0,0,0);
+	if(m_useOffsetForConstraintFrame)
+	{
+		// get vector from bodyB to frameB in WCS
+		relB = trB.getOrigin() - bodyB_trans.getOrigin();
+		// get its projection to slider axis
+		btVector3 projB = ax1 * relB.dot(ax1);
+		// get vector directed from bodyB to slider axis (and orthogonal to it)
+		btVector3 orthoB = relB - projB;
+		// same for bodyA
+		relA = trA.getOrigin() - bodyA_trans.getOrigin();
+		btVector3 projA = ax1 * relA.dot(ax1);
+		btVector3 orthoA = relA - projA;
+		// get desired offset between frames A and B along slider axis
+		btScalar sliderOffs = m_linPos - m_depth[0];
+		// desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
+		btVector3 totalDist = projA + ax1 * sliderOffs - projB;
+		// get offset vectors relA and relB
+		relA = orthoA + totalDist * factA;
+		relB = orthoB - totalDist * factB;
+		// now choose average ortho to slider axis
+		p = orthoB * factA + orthoA * factB;
+		btScalar len2 = p.length2();
+		if(len2 > SIMD_EPSILON)
+		{
+			p /= btSqrt(len2);
+		}
+		else
+		{
+			p = trA.getBasis().getColumn(1);
+		}
+		// make one more ortho
+		q = ax1.cross(p);
+		// fill two rows
+		tmpA = relA.cross(p);
+		tmpB = relB.cross(p);
+		for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = tmpA[i];
+		for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = -tmpB[i];
+		tmpA = relA.cross(q);
+		tmpB = relB.cross(q);
+		if(hasStaticBody && getSolveAngLimit())
+		{ // to make constraint between static and dynamic objects more rigid
+			// remove wA (or wB) from equation if angular limit is hit
+			tmpB *= factB;
+			tmpA *= factA;
+		}
+		for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = tmpA[i];
+		for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = -tmpB[i];
+		for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
+		for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
+	}
+	else
+	{	// old way - maybe incorrect if bodies are not on the slider axis
+		// see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
+		c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
+		btVector3 tmp = c.cross(p);
+		for (i=0; i<3; i++) info->m_J1angularAxis[s2+i] = factA*tmp[i];
+		for (i=0; i<3; i++) info->m_J2angularAxis[s2+i] = factB*tmp[i];
+		tmp = c.cross(q);
+		for (i=0; i<3; i++) info->m_J1angularAxis[s3+i] = factA*tmp[i];
+		for (i=0; i<3; i++) info->m_J2angularAxis[s3+i] = factB*tmp[i];
+
+		for (i=0; i<3; i++) info->m_J1linearAxis[s2+i] = p[i];
+		for (i=0; i<3; i++) info->m_J1linearAxis[s3+i] = q[i];
+	}
+	// compute two elements of right hand side
+
+	//	k = info->fps * info->erp * getSoftnessOrthoLin();
+	currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
+	k = info->fps * currERP;
+
+	btScalar rhs = k * p.dot(ofs);
+	info->m_constraintError[s2] = rhs;
+	rhs = k * q.dot(ofs);
+	info->m_constraintError[s3] = rhs;
+	if(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
+	{
+		info->cfm[s2] = m_cfmOrthoLin;
+		info->cfm[s3] = m_cfmOrthoLin;
+	}
+
+
+	// check linear limits
+	limit_err = btScalar(0.0);
+	limit = 0;
+	if(getSolveLinLimit())
+	{
+		limit_err = getLinDepth() *  signFact;
+		limit = (limit_err > btScalar(0.0)) ? 2 : 1;
+	}
+	powered = 0;
+	if(getPoweredLinMotor())
+	{
+		powered = 1;
+	}
+	// if the slider has joint limits or motor, add in the extra row
+	if (limit || powered) 
+	{
+		nrow++;
+		srow = nrow * info->rowskip;
+		info->m_J1linearAxis[srow+0] = ax1[0];
+		info->m_J1linearAxis[srow+1] = ax1[1];
+		info->m_J1linearAxis[srow+2] = ax1[2];
+		// linear torque decoupling step:
+		//
+		// we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
+		// do not create a torque couple. in other words, the points that the
+		// constraint force is applied at must lie along the same ax1 axis.
+		// a torque couple will result in limited slider-jointed free
+		// bodies from gaining angular momentum.
+		if(m_useOffsetForConstraintFrame)
+		{
+			// this is needed only when bodyA and bodyB are both dynamic.
+			if(!hasStaticBody)
+			{
+				tmpA = relA.cross(ax1);
+				tmpB = relB.cross(ax1);
+				info->m_J1angularAxis[srow+0] = tmpA[0];
+				info->m_J1angularAxis[srow+1] = tmpA[1];
+				info->m_J1angularAxis[srow+2] = tmpA[2];
+				info->m_J2angularAxis[srow+0] = -tmpB[0];
+				info->m_J2angularAxis[srow+1] = -tmpB[1];
+				info->m_J2angularAxis[srow+2] = -tmpB[2];
+			}
+		}
+		else
+		{ // The old way. May be incorrect if bodies are not on the slider axis
+			btVector3 ltd;	// Linear Torque Decoupling vector (a torque)
+			ltd = c.cross(ax1);
+			info->m_J1angularAxis[srow+0] = factA*ltd[0];
+			info->m_J1angularAxis[srow+1] = factA*ltd[1];
+			info->m_J1angularAxis[srow+2] = factA*ltd[2];
+			info->m_J2angularAxis[srow+0] = factB*ltd[0];
+			info->m_J2angularAxis[srow+1] = factB*ltd[1];
+			info->m_J2angularAxis[srow+2] = factB*ltd[2];
+		}
+		// right-hand part
+		btScalar lostop = getLowerLinLimit();
+		btScalar histop = getUpperLinLimit();
+		if(limit && (lostop == histop))
+		{  // the joint motor is ineffective
+			powered = 0;
+		}
+		info->m_constraintError[srow] = 0.;
+		info->m_lowerLimit[srow] = 0.;
+		info->m_upperLimit[srow] = 0.;
+		currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
+		if(powered)
+		{
+			if(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
+			{
+				info->cfm[srow] = m_cfmDirLin;
+			}
+			btScalar tag_vel = getTargetLinMotorVelocity();
+			btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
+			info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
+			info->m_lowerLimit[srow] += -getMaxLinMotorForce() * info->fps;
+			info->m_upperLimit[srow] += getMaxLinMotorForce() * info->fps;
+		}
+		if(limit)
+		{
+			k = info->fps * currERP;
+			info->m_constraintError[srow] += k * limit_err;
+			if(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
+			{
+				info->cfm[srow] = m_cfmLimLin;
+			}
+			if(lostop == histop) 
+			{	// limited low and high simultaneously
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else if(limit == 1) 
+			{ // low limit
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = 0;
+			}
+			else 
+			{ // high limit
+				info->m_lowerLimit[srow] = 0;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			// bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
+			btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
+			if(bounce > btScalar(0.0))
+			{
+				btScalar vel = linVelA.dot(ax1);
+				vel -= linVelB.dot(ax1);
+				vel *= signFact;
+				// only apply bounce if the velocity is incoming, and if the
+				// resulting c[] exceeds what we already have.
+				if(limit == 1)
+				{	// low limit
+					if(vel < 0)
+					{
+						btScalar newc = -bounce * vel;
+						if (newc > info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+				else
+				{ // high limit - all those computations are reversed
+					if(vel > 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc < info->m_constraintError[srow]) 
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+			}
+			info->m_constraintError[srow] *= getSoftnessLimLin();
+		} // if(limit)
+	} // if linear limit
+	// check angular limits
+	limit_err = btScalar(0.0);
+	limit = 0;
+	if(getSolveAngLimit())
+	{
+		limit_err = getAngDepth();
+		limit = (limit_err > btScalar(0.0)) ? 1 : 2;
+	}
+	// if the slider has joint limits, add in the extra row
+	powered = 0;
+	if(getPoweredAngMotor())
+	{
+		powered = 1;
+	}
+	if(limit || powered) 
+	{
+		nrow++;
+		srow = nrow * info->rowskip;
+		info->m_J1angularAxis[srow+0] = ax1[0];
+		info->m_J1angularAxis[srow+1] = ax1[1];
+		info->m_J1angularAxis[srow+2] = ax1[2];
+
+		info->m_J2angularAxis[srow+0] = -ax1[0];
+		info->m_J2angularAxis[srow+1] = -ax1[1];
+		info->m_J2angularAxis[srow+2] = -ax1[2];
+
+		btScalar lostop = getLowerAngLimit();
+		btScalar histop = getUpperAngLimit();
+		if(limit && (lostop == histop))
+		{  // the joint motor is ineffective
+			powered = 0;
+		}
+		currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
+		if(powered)
+		{
+			if(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
+			{
+				info->cfm[srow] = m_cfmDirAng;
+			}
+			btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
+			info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
+			info->m_lowerLimit[srow] = -getMaxAngMotorForce() * info->fps;
+			info->m_upperLimit[srow] = getMaxAngMotorForce() * info->fps;
+		}
+		if(limit)
+		{
+			k = info->fps * currERP;
+			info->m_constraintError[srow] += k * limit_err;
+			if(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
+			{
+				info->cfm[srow] = m_cfmLimAng;
+			}
+			if(lostop == histop) 
+			{
+				// limited low and high simultaneously
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else if(limit == 1) 
+			{ // low limit
+				info->m_lowerLimit[srow] = 0;
+				info->m_upperLimit[srow] = SIMD_INFINITY;
+			}
+			else 
+			{ // high limit
+				info->m_lowerLimit[srow] = -SIMD_INFINITY;
+				info->m_upperLimit[srow] = 0;
+			}
+			// bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
+			btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
+			if(bounce > btScalar(0.0))
+			{
+				btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
+				vel -= m_rbB.getAngularVelocity().dot(ax1);
+				// only apply bounce if the velocity is incoming, and if the
+				// resulting c[] exceeds what we already have.
+				if(limit == 1)
+				{	// low limit
+					if(vel < 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc > info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+				else
+				{	// high limit - all those computations are reversed
+					if(vel > 0)
+					{
+						btScalar newc = -bounce * vel;
+						if(newc < info->m_constraintError[srow])
+						{
+							info->m_constraintError[srow] = newc;
+						}
+					}
+				}
+			}
+			info->m_constraintError[srow] *= getSoftnessLimAng();
+		} // if(limit)
+	} // if angular limit or powered
+}
+
+
+///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+///If no axis is provided, it uses the default axis for this constraint.
+void btSliderConstraint::setParam(int num, btScalar value, int axis)
+{
+	switch(num)
+	{
+	case BT_CONSTRAINT_STOP_ERP :
+		if(axis < 1)
+		{
+			m_softnessLimLin = value;
+			m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
+		}
+		else if(axis < 3)
+		{
+			m_softnessOrthoLin = value;
+			m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
+		}
+		else if(axis == 3)
+		{
+			m_softnessLimAng = value;
+			m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
+		}
+		else if(axis < 6)
+		{
+			m_softnessOrthoAng = value;
+			m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
+		}
+		else
+		{
+			btAssertConstrParams(0);
+		}
+		break;
+	case BT_CONSTRAINT_CFM :
+		if(axis < 1)
+		{
+			m_cfmDirLin = value;
+			m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
+		}
+		else if(axis == 3)
+		{
+			m_cfmDirAng = value;
+			m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
+		}
+		else
+		{
+			btAssertConstrParams(0);
+		}
+		break;
+	case BT_CONSTRAINT_STOP_CFM :
+		if(axis < 1)
+		{
+			m_cfmLimLin = value;
+			m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
+		}
+		else if(axis < 3)
+		{
+			m_cfmOrthoLin = value;
+			m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
+		}
+		else if(axis == 3)
+		{
+			m_cfmLimAng = value;
+			m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
+		}
+		else if(axis < 6)
+		{
+			m_cfmOrthoAng = value;
+			m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
+		}
+		else
+		{
+			btAssertConstrParams(0);
+		}
+		break;
+	}
+}
+
+///return the local value of parameter
+btScalar btSliderConstraint::getParam(int num, int axis) const 
+{
+	btScalar retVal(SIMD_INFINITY);
+	switch(num)
+	{
+	case BT_CONSTRAINT_STOP_ERP :
+		if(axis < 1)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
+			retVal = m_softnessLimLin;
+		}
+		else if(axis < 3)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
+			retVal = m_softnessOrthoLin;
+		}
+		else if(axis == 3)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
+			retVal = m_softnessLimAng;
+		}
+		else if(axis < 6)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
+			retVal = m_softnessOrthoAng;
+		}
+		else
+		{
+			btAssertConstrParams(0);
+		}
+		break;
+	case BT_CONSTRAINT_CFM :
+		if(axis < 1)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
+			retVal = m_cfmDirLin;
+		}
+		else if(axis == 3)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
+			retVal = m_cfmDirAng;
+		}
+		else
+		{
+			btAssertConstrParams(0);
+		}
+		break;
+	case BT_CONSTRAINT_STOP_CFM :
+		if(axis < 1)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
+			retVal = m_cfmLimLin;
+		}
+		else if(axis < 3)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
+			retVal = m_cfmOrthoLin;
+		}
+		else if(axis == 3)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
+			retVal = m_cfmLimAng;
+		}
+		else if(axis < 6)
+		{
+			btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
+			retVal = m_cfmOrthoAng;
+		}
+		else
+		{
+			btAssertConstrParams(0);
+		}
+		break;
+	}
+	return retVal;
+}
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h	(revision 11817)
@@ -0,0 +1,333 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+Added by Roman Ponomarev (rponom@gmail.com)
+April 04, 2008
+
+TODO:
+ - add clamping od accumulated impulse to improve stability
+ - add conversion for ODE constraint solver
+*/
+
+#ifndef BT_SLIDER_CONSTRAINT_H
+#define BT_SLIDER_CONSTRAINT_H
+
+
+
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+#include "btTypedConstraint.h"
+
+
+
+class btRigidBody;
+
+
+
+#define SLIDER_CONSTRAINT_DEF_SOFTNESS		(btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_DAMPING		(btScalar(1.0))
+#define SLIDER_CONSTRAINT_DEF_RESTITUTION	(btScalar(0.7))
+#define SLIDER_CONSTRAINT_DEF_CFM			(btScalar(0.f))
+
+
+enum btSliderFlags
+{
+	BT_SLIDER_FLAGS_CFM_DIRLIN = (1 << 0),
+	BT_SLIDER_FLAGS_ERP_DIRLIN = (1 << 1),
+	BT_SLIDER_FLAGS_CFM_DIRANG = (1 << 2),
+	BT_SLIDER_FLAGS_ERP_DIRANG = (1 << 3),
+	BT_SLIDER_FLAGS_CFM_ORTLIN = (1 << 4),
+	BT_SLIDER_FLAGS_ERP_ORTLIN = (1 << 5),
+	BT_SLIDER_FLAGS_CFM_ORTANG = (1 << 6),
+	BT_SLIDER_FLAGS_ERP_ORTANG = (1 << 7),
+	BT_SLIDER_FLAGS_CFM_LIMLIN = (1 << 8),
+	BT_SLIDER_FLAGS_ERP_LIMLIN = (1 << 9),
+	BT_SLIDER_FLAGS_CFM_LIMANG = (1 << 10),
+	BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11)
+};
+
+
+class btSliderConstraint : public btTypedConstraint
+{
+protected:
+	///for backwards compatibility during the transition to 'getInfo/getInfo2'
+	bool		m_useSolveConstraintObsolete;
+	bool		m_useOffsetForConstraintFrame;
+	btTransform	m_frameInA;
+    btTransform	m_frameInB;
+	// use frameA fo define limits, if true
+	bool m_useLinearReferenceFrameA;
+	// linear limits
+	btScalar m_lowerLinLimit;
+	btScalar m_upperLinLimit;
+	// angular limits
+	btScalar m_lowerAngLimit;
+	btScalar m_upperAngLimit;
+	// softness, restitution and damping for different cases
+	// DirLin - moving inside linear limits
+	// LimLin - hitting linear limit
+	// DirAng - moving inside angular limits
+	// LimAng - hitting angular limit
+	// OrthoLin, OrthoAng - against constraint axis
+	btScalar m_softnessDirLin;
+	btScalar m_restitutionDirLin;
+	btScalar m_dampingDirLin;
+	btScalar m_cfmDirLin;
+
+	btScalar m_softnessDirAng;
+	btScalar m_restitutionDirAng;
+	btScalar m_dampingDirAng;
+	btScalar m_cfmDirAng;
+
+	btScalar m_softnessLimLin;
+	btScalar m_restitutionLimLin;
+	btScalar m_dampingLimLin;
+	btScalar m_cfmLimLin;
+
+	btScalar m_softnessLimAng;
+	btScalar m_restitutionLimAng;
+	btScalar m_dampingLimAng;
+	btScalar m_cfmLimAng;
+
+	btScalar m_softnessOrthoLin;
+	btScalar m_restitutionOrthoLin;
+	btScalar m_dampingOrthoLin;
+	btScalar m_cfmOrthoLin;
+
+	btScalar m_softnessOrthoAng;
+	btScalar m_restitutionOrthoAng;
+	btScalar m_dampingOrthoAng;
+	btScalar m_cfmOrthoAng;
+	
+	// for interlal use
+	bool m_solveLinLim;
+	bool m_solveAngLim;
+
+	int m_flags;
+
+	btJacobianEntry	m_jacLin[3];
+	btScalar		m_jacLinDiagABInv[3];
+
+    btJacobianEntry	m_jacAng[3];
+
+	btScalar m_timeStep;
+    btTransform m_calculatedTransformA;
+    btTransform m_calculatedTransformB;
+
+	btVector3 m_sliderAxis;
+	btVector3 m_realPivotAInW;
+	btVector3 m_realPivotBInW;
+	btVector3 m_projPivotInW;
+	btVector3 m_delta;
+	btVector3 m_depth;
+	btVector3 m_relPosA;
+	btVector3 m_relPosB;
+
+	btScalar m_linPos;
+	btScalar m_angPos;
+
+	btScalar m_angDepth;
+	btScalar m_kAngle;
+
+	bool	 m_poweredLinMotor;
+    btScalar m_targetLinMotorVelocity;
+    btScalar m_maxLinMotorForce;
+    btScalar m_accumulatedLinMotorImpulse;
+	
+	bool	 m_poweredAngMotor;
+    btScalar m_targetAngMotorVelocity;
+    btScalar m_maxAngMotorForce;
+    btScalar m_accumulatedAngMotorImpulse;
+
+	//------------------------    
+	void initParams();
+public:
+	// constructors
+    btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+    btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
+
+	// overrides
+
+    virtual void getInfo1 (btConstraintInfo1* info);
+
+	void getInfo1NonVirtual(btConstraintInfo1* info);
+	
+	virtual void getInfo2 (btConstraintInfo2* info);
+
+	void getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB,const btVector3& linVelA,const btVector3& linVelB, btScalar rbAinvMass,btScalar rbBinvMass);
+
+
+	// access
+    const btRigidBody& getRigidBodyA() const { return m_rbA; }
+    const btRigidBody& getRigidBodyB() const { return m_rbB; }
+    const btTransform & getCalculatedTransformA() const { return m_calculatedTransformA; }
+    const btTransform & getCalculatedTransformB() const { return m_calculatedTransformB; }
+    const btTransform & getFrameOffsetA() const { return m_frameInA; }
+    const btTransform & getFrameOffsetB() const { return m_frameInB; }
+    btTransform & getFrameOffsetA() { return m_frameInA; }
+    btTransform & getFrameOffsetB() { return m_frameInB; }
+    btScalar getLowerLinLimit() { return m_lowerLinLimit; }
+    void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
+    btScalar getUpperLinLimit() { return m_upperLinLimit; }
+    void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
+    btScalar getLowerAngLimit() { return m_lowerAngLimit; }
+    void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); }
+    btScalar getUpperAngLimit() { return m_upperAngLimit; }
+    void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); }
+	bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
+	btScalar getSoftnessDirLin() { return m_softnessDirLin; }
+	btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
+	btScalar getDampingDirLin() { return m_dampingDirLin ; }
+	btScalar getSoftnessDirAng() { return m_softnessDirAng; }
+	btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
+	btScalar getDampingDirAng() { return m_dampingDirAng; }
+	btScalar getSoftnessLimLin() { return m_softnessLimLin; }
+	btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
+	btScalar getDampingLimLin() { return m_dampingLimLin; }
+	btScalar getSoftnessLimAng() { return m_softnessLimAng; }
+	btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
+	btScalar getDampingLimAng() { return m_dampingLimAng; }
+	btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
+	btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
+	btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
+	btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
+	btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
+	btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
+	void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
+	void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
+	void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
+	void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
+	void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
+	void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
+	void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
+	void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
+	void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
+	void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
+	void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
+	void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
+	void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
+	void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
+	void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
+	void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
+	void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
+	void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
+	void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
+	bool getPoweredLinMotor() { return m_poweredLinMotor; }
+	void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
+	btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
+	void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
+	btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
+	void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
+	bool getPoweredAngMotor() { return m_poweredAngMotor; }
+	void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
+	btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
+	void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
+	btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
+
+	btScalar getLinearPos() const { return m_linPos; }
+	btScalar getAngularPos() const { return m_angPos; }
+	
+	
+
+	// access for ODE solver
+	bool getSolveLinLimit() { return m_solveLinLim; }
+	btScalar getLinDepth() { return m_depth[0]; }
+	bool getSolveAngLimit() { return m_solveAngLim; }
+	btScalar getAngDepth() { return m_angDepth; }
+	// shared code used by ODE solver
+	void	calculateTransforms(const btTransform& transA,const btTransform& transB);
+	void	testLinLimits();
+	void	testAngLimits();
+	// access for PE Solver
+	btVector3 getAncorInA();
+	btVector3 getAncorInB();
+	// access for UseFrameOffset
+	bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
+	void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
+
+	void setFrames(const btTransform& frameA, const btTransform& frameB) 
+	{ 
+		m_frameInA=frameA; 
+		m_frameInB=frameB;
+		calculateTransforms(m_rbA.getCenterOfMassTransform(),m_rbB.getCenterOfMassTransform());
+		buildJacobian();
+	} 
+
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+	virtual	void	setParam(int num, btScalar value, int axis = -1);
+	///return the local value of parameter
+	virtual	btScalar getParam(int num, int axis = -1) const;
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btSliderConstraintData
+{
+	btTypedConstraintData	m_typeConstraintData;
+	btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
+	btTransformFloatData m_rbBFrame;
+	
+	float	m_linearUpperLimit;
+	float	m_linearLowerLimit;
+
+	float	m_angularUpperLimit;
+	float	m_angularLowerLimit;
+
+	int	m_useLinearReferenceFrameA;
+	int m_useOffsetForConstraintFrame;
+
+};
+
+
+SIMD_FORCE_INLINE		int	btSliderConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btSliderConstraintData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+	btSliderConstraintData* sliderData = (btSliderConstraintData*) dataBuffer;
+	btTypedConstraint::serialize(&sliderData->m_typeConstraintData,serializer);
+
+	m_frameInA.serializeFloat(sliderData->m_rbAFrame);
+	m_frameInB.serializeFloat(sliderData->m_rbBFrame);
+
+	sliderData->m_linearUpperLimit = float(m_upperLinLimit);
+	sliderData->m_linearLowerLimit = float(m_lowerLinLimit);
+
+	sliderData->m_angularUpperLimit = float(m_upperAngLimit);
+	sliderData->m_angularLowerLimit = float(m_lowerAngLimit);
+
+	sliderData->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA;
+	sliderData->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame;
+
+	return "btSliderConstraintData";
+}
+
+
+
+#endif //BT_SLIDER_CONSTRAINT_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp	(revision 11817)
@@ -0,0 +1,255 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btSolve2LinearConstraint.h"
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btVector3.h"
+#include "btJacobianEntry.h"
+
+
+void btSolve2LinearConstraint::resolveUnilateralPairConstraint(
+												   btRigidBody* body1,
+		btRigidBody* body2,
+
+						const btMatrix3x3& world2A,
+						const btMatrix3x3& world2B,
+						
+						const btVector3& invInertiaADiag,
+						const btScalar invMassA,
+						const btVector3& linvelA,const btVector3& angvelA,
+						const btVector3& rel_posA1,
+						const btVector3& invInertiaBDiag,
+						const btScalar invMassB,
+						const btVector3& linvelB,const btVector3& angvelB,
+						const btVector3& rel_posA2,
+
+					  btScalar depthA, const btVector3& normalA, 
+					  const btVector3& rel_posB1,const btVector3& rel_posB2,
+					  btScalar depthB, const btVector3& normalB, 
+					  btScalar& imp0,btScalar& imp1)
+{
+	(void)linvelA;
+	(void)linvelB;
+	(void)angvelB;
+	(void)angvelA;
+
+
+
+	imp0 = btScalar(0.);
+	imp1 = btScalar(0.);
+
+	btScalar len = btFabs(normalA.length()) - btScalar(1.);
+	if (btFabs(len) >= SIMD_EPSILON)
+		return;
+
+	btAssert(len < SIMD_EPSILON);
+
+
+	//this jacobian entry could be re-used for all iterations
+	btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
+		invInertiaBDiag,invMassB);
+	btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
+		invInertiaBDiag,invMassB);
+	
+	//const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+	//const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+
+	const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
+	const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
+
+//	btScalar penetrationImpulse = (depth*contactTau*timeCorrection)  * massTerm;//jacDiagABInv
+	btScalar massTerm = btScalar(1.) / (invMassA + invMassB);
+
+
+	// calculate rhs (or error) terms
+	const btScalar dv0 = depthA  * m_tau * massTerm - vel0 * m_damping;
+	const btScalar dv1 = depthB  * m_tau * massTerm - vel1 * m_damping;
+
+
+	// dC/dv * dv = -C
+	
+	// jacobian * impulse = -error
+	//
+
+	//impulse = jacobianInverse * -error
+
+	// inverting 2x2 symmetric system (offdiagonal are equal!)
+	// 
+
+
+	btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
+	btScalar	invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
+	
+	//imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+	//imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+	imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+	imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+	//[a b]								  [d -c]
+	//[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
+
+	//[jA nD] * [imp0] = [dv0]
+	//[nD jB]   [imp1]   [dv1]
+
+}
+
+
+
+void btSolve2LinearConstraint::resolveBilateralPairConstraint(
+						btRigidBody* body1,
+						btRigidBody* body2,
+						const btMatrix3x3& world2A,
+						const btMatrix3x3& world2B,
+						
+						const btVector3& invInertiaADiag,
+						const btScalar invMassA,
+						const btVector3& linvelA,const btVector3& angvelA,
+						const btVector3& rel_posA1,
+						const btVector3& invInertiaBDiag,
+						const btScalar invMassB,
+						const btVector3& linvelB,const btVector3& angvelB,
+						const btVector3& rel_posA2,
+
+					  btScalar depthA, const btVector3& normalA, 
+					  const btVector3& rel_posB1,const btVector3& rel_posB2,
+					  btScalar depthB, const btVector3& normalB, 
+					  btScalar& imp0,btScalar& imp1)
+{
+
+	(void)linvelA;
+	(void)linvelB;
+	(void)angvelA;
+	(void)angvelB;
+
+
+
+	imp0 = btScalar(0.);
+	imp1 = btScalar(0.);
+
+	btScalar len = btFabs(normalA.length()) - btScalar(1.);
+	if (btFabs(len) >= SIMD_EPSILON)
+		return;
+
+	btAssert(len < SIMD_EPSILON);
+
+
+	//this jacobian entry could be re-used for all iterations
+	btJacobianEntry jacA(world2A,world2B,rel_posA1,rel_posA2,normalA,invInertiaADiag,invMassA,
+		invInertiaBDiag,invMassB);
+	btJacobianEntry jacB(world2A,world2B,rel_posB1,rel_posB2,normalB,invInertiaADiag,invMassA,
+		invInertiaBDiag,invMassB);
+	
+	//const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+	//const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
+
+	const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1)-body2->getVelocityInLocalPoint(rel_posA1));
+	const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1)-body2->getVelocityInLocalPoint(rel_posB1));
+
+	// calculate rhs (or error) terms
+	const btScalar dv0 = depthA  * m_tau - vel0 * m_damping;
+	const btScalar dv1 = depthB  * m_tau - vel1 * m_damping;
+
+	// dC/dv * dv = -C
+	
+	// jacobian * impulse = -error
+	//
+
+	//impulse = jacobianInverse * -error
+
+	// inverting 2x2 symmetric system (offdiagonal are equal!)
+	// 
+
+
+	btScalar nonDiag = jacA.getNonDiagonal(jacB,invMassA,invMassB);
+	btScalar	invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag );
+	
+	//imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+	//imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+	imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
+	imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
+
+	//[a b]								  [d -c]
+	//[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
+
+	//[jA nD] * [imp0] = [dv0]
+	//[nD jB]   [imp1]   [dv1]
+
+	if ( imp0 > btScalar(0.0))
+	{
+		if ( imp1 > btScalar(0.0) )
+		{
+			//both positive
+		}
+		else
+		{
+			imp1 = btScalar(0.);
+
+			// now imp0>0 imp1<0
+			imp0 = dv0 / jacA.getDiagonal();
+			if ( imp0 > btScalar(0.0) )
+			{
+			} else
+			{
+				imp0 = btScalar(0.);
+			}
+		}
+	}
+	else
+	{
+		imp0 = btScalar(0.);
+
+		imp1 = dv1 / jacB.getDiagonal();
+		if ( imp1 <= btScalar(0.0) )
+		{
+			imp1 = btScalar(0.);
+			// now imp0>0 imp1<0
+			imp0 = dv0 / jacA.getDiagonal();
+			if ( imp0 > btScalar(0.0) )
+			{
+			} else
+			{
+				imp0 = btScalar(0.);
+			}
+		} else
+		{
+		}
+	}
+}
+
+
+/*
+void btSolve2LinearConstraint::resolveAngularConstraint(	const btMatrix3x3& invInertiaAWS,
+											const btScalar invMassA,
+											const btVector3& linvelA,const btVector3& angvelA,
+											const btVector3& rel_posA1,
+											const btMatrix3x3& invInertiaBWS,
+											const btScalar invMassB,
+											const btVector3& linvelB,const btVector3& angvelB,
+											const btVector3& rel_posA2,
+
+											btScalar depthA, const btVector3& normalA, 
+											const btVector3& rel_posB1,const btVector3& rel_posB2,
+											btScalar depthB, const btVector3& normalB, 
+											btScalar& imp0,btScalar& imp1)
+{
+
+}
+*/
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVE_2LINEAR_CONSTRAINT_H
+#define BT_SOLVE_2LINEAR_CONSTRAINT_H
+
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btVector3.h"
+
+
+class btRigidBody;
+
+
+
+/// constraint class used for lateral tyre friction.
+class	btSolve2LinearConstraint
+{
+	btScalar	m_tau;
+	btScalar	m_damping;
+
+public:
+
+	btSolve2LinearConstraint(btScalar tau,btScalar damping)
+	{
+		m_tau = tau;
+		m_damping = damping;
+	}
+	//
+	// solve unilateral constraint (equality, direct method)
+	//
+	void resolveUnilateralPairConstraint(		
+														   btRigidBody* body0,
+		btRigidBody* body1,
+
+		const btMatrix3x3& world2A,
+						const btMatrix3x3& world2B,
+						
+						const btVector3& invInertiaADiag,
+						const btScalar invMassA,
+						const btVector3& linvelA,const btVector3& angvelA,
+						const btVector3& rel_posA1,
+						const btVector3& invInertiaBDiag,
+						const btScalar invMassB,
+						const btVector3& linvelB,const btVector3& angvelB,
+						const btVector3& rel_posA2,
+
+					  btScalar depthA, const btVector3& normalA, 
+					  const btVector3& rel_posB1,const btVector3& rel_posB2,
+					  btScalar depthB, const btVector3& normalB, 
+					  btScalar& imp0,btScalar& imp1);
+
+
+	//
+	// solving 2x2 lcp problem (inequality, direct solution )
+	//
+	void resolveBilateralPairConstraint(
+			btRigidBody* body0,
+						btRigidBody* body1,
+		const btMatrix3x3& world2A,
+						const btMatrix3x3& world2B,
+						
+						const btVector3& invInertiaADiag,
+						const btScalar invMassA,
+						const btVector3& linvelA,const btVector3& angvelA,
+						const btVector3& rel_posA1,
+						const btVector3& invInertiaBDiag,
+						const btScalar invMassB,
+						const btVector3& linvelB,const btVector3& angvelB,
+						const btVector3& rel_posA2,
+
+					  btScalar depthA, const btVector3& normalA, 
+					  const btVector3& rel_posB1,const btVector3& rel_posB2,
+					  btScalar depthB, const btVector3& normalB, 
+					  btScalar& imp0,btScalar& imp1);
+
+/*
+	void resolveAngularConstraint(	const btMatrix3x3& invInertiaAWS,
+						const btScalar invMassA,
+						const btVector3& linvelA,const btVector3& angvelA,
+						const btVector3& rel_posA1,
+						const btMatrix3x3& invInertiaBWS,
+						const btScalar invMassB,
+						const btVector3& linvelB,const btVector3& angvelB,
+						const btVector3& rel_posA2,
+
+					  btScalar depthA, const btVector3& normalA, 
+					  const btVector3& rel_posB1,const btVector3& rel_posB2,
+					  btScalar depthB, const btVector3& normalB, 
+					  btScalar& imp0,btScalar& imp1);
+
+*/
+
+};
+
+#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h	(revision 11817)
@@ -0,0 +1,191 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVER_BODY_H
+#define BT_SOLVER_BODY_H
+
+class	btRigidBody;
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btTransformUtil.h"
+
+///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
+#ifdef BT_USE_SSE
+#define USE_SIMD 1
+#endif //
+
+
+#ifdef USE_SIMD
+
+struct	btSimdScalar
+{
+	SIMD_FORCE_INLINE	btSimdScalar()
+	{
+
+	}
+
+	SIMD_FORCE_INLINE	btSimdScalar(float	fl)
+	:m_vec128 (_mm_set1_ps(fl))
+	{
+	}
+
+	SIMD_FORCE_INLINE	btSimdScalar(__m128 v128)
+		:m_vec128(v128)
+	{
+	}
+	union
+	{
+		__m128		m_vec128;
+		float		m_floats[4];
+		int			m_ints[4];
+		btScalar	m_unusedPadding;
+	};
+	SIMD_FORCE_INLINE	__m128	get128()
+	{
+		return m_vec128;
+	}
+
+	SIMD_FORCE_INLINE	const __m128	get128() const
+	{
+		return m_vec128;
+	}
+
+	SIMD_FORCE_INLINE	void	set128(__m128 v128)
+	{
+		m_vec128 = v128;
+	}
+
+	SIMD_FORCE_INLINE	operator       __m128()       
+	{ 
+		return m_vec128; 
+	}
+	SIMD_FORCE_INLINE	operator const __m128() const 
+	{ 
+		return m_vec128; 
+	}
+	
+	SIMD_FORCE_INLINE	operator float() const 
+	{ 
+		return m_floats[0]; 
+	}
+
+};
+
+///@brief Return the elementwise product of two btSimdScalar
+SIMD_FORCE_INLINE btSimdScalar 
+operator*(const btSimdScalar& v1, const btSimdScalar& v2) 
+{
+	return btSimdScalar(_mm_mul_ps(v1.get128(),v2.get128()));
+}
+
+///@brief Return the elementwise product of two btSimdScalar
+SIMD_FORCE_INLINE btSimdScalar 
+operator+(const btSimdScalar& v1, const btSimdScalar& v2) 
+{
+	return btSimdScalar(_mm_add_ps(v1.get128(),v2.get128()));
+}
+
+
+#else
+#define btSimdScalar btScalar
+#endif
+
+///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
+ATTRIBUTE_ALIGNED64 (struct)	btSolverBodyObsolete
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+	btVector3		m_deltaLinearVelocity;
+	btVector3		m_deltaAngularVelocity;
+	btVector3		m_angularFactor;
+	btVector3		m_invMass;
+	btRigidBody*	m_originalBody;
+	btVector3		m_pushVelocity;
+	btVector3		m_turnVelocity;
+
+	
+	SIMD_FORCE_INLINE void	getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+	{
+		if (m_originalBody)
+			velocity = m_originalBody->getLinearVelocity()+m_deltaLinearVelocity + (m_originalBody->getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
+		else
+			velocity.setValue(0,0,0);
+	}
+
+	SIMD_FORCE_INLINE void	getAngularVelocity(btVector3& angVel) const
+	{
+		if (m_originalBody)
+			angVel = m_originalBody->getAngularVelocity()+m_deltaAngularVelocity;
+		else
+			angVel.setValue(0,0,0);
+	}
+
+
+	//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+	SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+	{
+		//if (m_invMass)
+		{
+			m_deltaLinearVelocity += linearComponent*impulseMagnitude;
+			m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+		}
+	}
+
+	SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
+	{
+		if (m_originalBody)
+		{
+			m_pushVelocity += linearComponent*impulseMagnitude;
+			m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+		}
+	}
+	
+	void	writebackVelocity()
+	{
+		if (m_originalBody)
+		{
+			m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity);
+			m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
+			
+			//m_originalBody->setCompanionId(-1);
+		}
+	}
+
+
+	void	writebackVelocity(btScalar timeStep)
+	{
+        (void) timeStep;
+		if (m_originalBody)
+		{
+			m_originalBody->setLinearVelocity(m_originalBody->getLinearVelocity()+ m_deltaLinearVelocity);
+			m_originalBody->setAngularVelocity(m_originalBody->getAngularVelocity()+m_deltaAngularVelocity);
+			
+			//correct the position/orientation based on push/turn recovery
+			btTransform newTransform;
+			btTransformUtil::integrateTransform(m_originalBody->getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
+			m_originalBody->setWorldTransform(newTransform);
+			
+			//m_originalBody->setCompanionId(-1);
+		}
+	}
+	
+
+
+};
+
+#endif //BT_SOLVER_BODY_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SOLVER_CONSTRAINT_H
+#define BT_SOLVER_CONSTRAINT_H
+
+class	btRigidBody;
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btJacobianEntry.h"
+
+//#define NO_FRICTION_TANGENTIALS 1
+#include "btSolverBody.h"
+
+
+///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
+ATTRIBUTE_ALIGNED64 (struct)	btSolverConstraint
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btVector3		m_relpos1CrossNormal;
+	btVector3		m_contactNormal;
+
+	btVector3		m_relpos2CrossNormal;
+	//btVector3		m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
+
+	btVector3		m_angularComponentA;
+	btVector3		m_angularComponentB;
+	
+	mutable btSimdScalar	m_appliedPushImpulse;
+	mutable btSimdScalar	m_appliedImpulse;
+	
+	
+	btScalar	m_friction;
+	btScalar	m_jacDiagABInv;
+	union
+	{
+		int	m_numConsecutiveRowsPerKernel;
+		btScalar	m_unusedPadding0;
+	};
+
+	union
+	{
+		int			m_frictionIndex;
+		btScalar	m_unusedPadding1;
+	};
+	union
+	{
+		btRigidBody*	m_solverBodyA;
+		int				m_companionIdA;
+	};
+	union
+	{
+		btRigidBody*	m_solverBodyB;
+		int				m_companionIdB;
+	};
+	
+	union
+	{
+		void*		m_originalContactPoint;
+		btScalar	m_unusedPadding4;
+	};
+
+	btScalar		m_rhs;
+	btScalar		m_cfm;
+	btScalar		m_lowerLimit;
+	btScalar		m_upperLimit;
+
+	btScalar		m_rhsPenetration;
+
+	enum		btSolverConstraintType
+	{
+		BT_SOLVER_CONTACT_1D = 0,
+		BT_SOLVER_FRICTION_1D
+	};
+};
+
+typedef btAlignedObjectArray<btSolverConstraint>	btConstraintArray;
+
+
+#endif //BT_SOLVER_CONSTRAINT_H
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp	(revision 11817)
@@ -0,0 +1,214 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btTypedConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btSerializer.h"
+
+
+#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.3f)
+
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
+:btTypedObject(type),
+m_userConstraintType(-1),
+m_userConstraintId(-1),
+m_needsFeedback(false),
+m_rbA(rbA),
+m_rbB(getFixedBody()),
+m_appliedImpulse(btScalar(0.)),
+m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+m_breakingImpulseThreshold(SIMD_INFINITY),
+m_isEnabled(true)
+{
+}
+
+
+btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB)
+:btTypedObject(type),
+m_userConstraintType(-1),
+m_userConstraintId(-1),
+m_needsFeedback(false),
+m_rbA(rbA),
+m_rbB(rbB),
+m_appliedImpulse(btScalar(0.)),
+m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
+m_breakingImpulseThreshold(SIMD_INFINITY),
+m_isEnabled(true)
+{
+}
+
+
+
+
+btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact)
+{
+	if(lowLim > uppLim)
+	{
+		return btScalar(1.0f);
+	}
+	else if(lowLim == uppLim)
+	{
+		return btScalar(0.0f);
+	}
+	btScalar lim_fact = btScalar(1.0f);
+	btScalar delta_max = vel / timeFact;
+	if(delta_max < btScalar(0.0f))
+	{
+		if((pos >= lowLim) && (pos < (lowLim - delta_max)))
+		{
+			lim_fact = (lowLim - pos) / delta_max;
+		}
+		else if(pos  < lowLim)
+		{
+			lim_fact = btScalar(0.0f);
+		}
+		else
+		{
+			lim_fact = btScalar(1.0f);
+		}
+	}
+	else if(delta_max > btScalar(0.0f))
+	{
+		if((pos <= uppLim) && (pos > (uppLim - delta_max)))
+		{
+			lim_fact = (uppLim - pos) / delta_max;
+		}
+		else if(pos  > uppLim)
+		{
+			lim_fact = btScalar(0.0f);
+		}
+		else
+		{
+			lim_fact = btScalar(1.0f);
+		}
+	}
+	else
+	{
+			lim_fact = btScalar(0.0f);
+	}
+	return lim_fact;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btTypedConstraintData* tcd = (btTypedConstraintData*) dataBuffer;
+
+	tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA);
+	tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB);
+	char* name = (char*) serializer->findNameForPointer(this);
+	tcd->m_name = (char*)serializer->getUniquePointer(name);
+	if (tcd->m_name)
+	{
+		serializer->serializeName(name);
+	}
+
+	tcd->m_objectType = m_objectType;
+	tcd->m_needsFeedback = m_needsFeedback;
+	tcd->m_userConstraintId =m_userConstraintId;
+	tcd->m_userConstraintType =m_userConstraintType;
+
+	tcd->m_appliedImpulse = float(m_appliedImpulse);
+	tcd->m_dbgDrawSize = float(m_dbgDrawSize );
+
+	tcd->m_disableCollisionsBetweenLinkedBodies = false;
+
+	int i;
+	for (i=0;i<m_rbA.getNumConstraintRefs();i++)
+		if (m_rbA.getConstraintRef(i) == this)
+			tcd->m_disableCollisionsBetweenLinkedBodies = true;
+	for (i=0;i<m_rbB.getNumConstraintRefs();i++)
+		if (m_rbB.getConstraintRef(i) == this)
+			tcd->m_disableCollisionsBetweenLinkedBodies = true;
+
+	return "btTypedConstraintData";
+}
+
+btRigidBody& btTypedConstraint::getFixedBody()
+{
+	static btRigidBody s_fixed(0, 0,0);
+	s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+	return s_fixed;
+}
+
+
+void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor)
+{
+	m_halfRange = (high - low) / 2.0f;
+	m_center = btNormalizeAngle(low + m_halfRange);
+	m_softness =  _softness;
+	m_biasFactor = _biasFactor;
+	m_relaxationFactor = _relaxationFactor;
+}
+
+void btAngularLimit::test(const btScalar angle)
+{
+	m_correction = 0.0f;
+	m_sign = 0.0f;
+	m_solveLimit = false;
+
+	if (m_halfRange >= 0.0f)
+	{
+		btScalar deviation = btNormalizeAngle(angle - m_center);
+		if (deviation < -m_halfRange)
+		{
+			m_solveLimit = true;
+			m_correction = - (deviation + m_halfRange);
+			m_sign = +1.0f;
+		}
+		else if (deviation > m_halfRange)
+		{
+			m_solveLimit = true;
+			m_correction = m_halfRange - deviation;
+			m_sign = -1.0f;
+		}
+	}
+}
+
+
+btScalar btAngularLimit::getError() const
+{
+	return m_correction * m_sign;
+}
+
+void btAngularLimit::fit(btScalar& angle) const
+{
+	if (m_halfRange > 0.0f)
+	{
+		btScalar relativeAngle = btNormalizeAngle(angle - m_center);
+		if (!btEqual(relativeAngle, m_halfRange))
+		{
+			if (relativeAngle > 0.0f)
+			{
+				angle = getHigh();
+			}
+			else
+			{
+				angle = getLow();
+			}
+		}
+	}
+}
+
+btScalar btAngularLimit::getLow() const
+{
+	return btNormalizeAngle(m_center - m_halfRange);
+}
+
+btScalar btAngularLimit::getHigh() const
+{
+	return btNormalizeAngle(m_center + m_halfRange);
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h	(revision 11817)
@@ -0,0 +1,436 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2010 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TYPED_CONSTRAINT_H
+#define BT_TYPED_CONSTRAINT_H
+
+class btRigidBody;
+#include "LinearMath/btScalar.h"
+#include "btSolverConstraint.h"
+
+class btSerializer;
+
+//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
+enum btTypedConstraintType
+{
+	POINT2POINT_CONSTRAINT_TYPE=3,
+	HINGE_CONSTRAINT_TYPE,
+	CONETWIST_CONSTRAINT_TYPE,
+	D6_CONSTRAINT_TYPE,
+	SLIDER_CONSTRAINT_TYPE,
+	CONTACT_CONSTRAINT_TYPE,
+	D6_SPRING_CONSTRAINT_TYPE,
+	MAX_CONSTRAINT_TYPE
+};
+
+
+enum btConstraintParams
+{
+	BT_CONSTRAINT_ERP=1,
+	BT_CONSTRAINT_STOP_ERP,
+	BT_CONSTRAINT_CFM,
+	BT_CONSTRAINT_STOP_CFM
+};
+
+#if 1
+	#define btAssertConstrParams(_par) btAssert(_par) 
+#else
+	#define btAssertConstrParams(_par)
+#endif
+
+
+///TypedConstraint is the baseclass for Bullet constraints and vehicles
+class btTypedConstraint : public btTypedObject
+{
+	int	m_userConstraintType;
+
+	union
+	{
+		int	m_userConstraintId;
+		void* m_userConstraintPtr;
+	};
+
+	btScalar	m_breakingImpulseThreshold;
+	bool		m_isEnabled;
+
+
+	bool m_needsFeedback;
+
+	btTypedConstraint&	operator=(btTypedConstraint&	other)
+	{
+		btAssert(0);
+		(void) other;
+		return *this;
+	}
+
+protected:
+	btRigidBody&	m_rbA;
+	btRigidBody&	m_rbB;
+	btScalar	m_appliedImpulse;
+	btScalar	m_dbgDrawSize;
+
+	///internal method used by the constraint solver, don't use them directly
+	btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
+	
+	static btRigidBody& getFixedBody();
+
+public:
+
+	virtual ~btTypedConstraint() {};
+	btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA);
+	btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA,btRigidBody& rbB);
+
+	struct btConstraintInfo1 {
+		int m_numConstraintRows,nub;
+	};
+
+	struct btConstraintInfo2 {
+		// integrator parameters: frames per second (1/stepsize), default error
+		// reduction parameter (0..1).
+		btScalar fps,erp;
+
+		// for the first and second body, pointers to two (linear and angular)
+		// n*3 jacobian sub matrices, stored by rows. these matrices will have
+		// been initialized to 0 on entry. if the second body is zero then the
+		// J2xx pointers may be 0.
+		btScalar *m_J1linearAxis,*m_J1angularAxis,*m_J2linearAxis,*m_J2angularAxis;
+
+		// elements to jump from one row to the next in J's
+		int rowskip;
+
+		// right hand sides of the equation J*v = c + cfm * lambda. cfm is the
+		// "constraint force mixing" vector. c is set to zero on entry, cfm is
+		// set to a constant value (typically very small or zero) value on entry.
+		btScalar *m_constraintError,*cfm;
+
+		// lo and hi limits for variables (set to -/+ infinity on entry).
+		btScalar *m_lowerLimit,*m_upperLimit;
+
+		// findex vector for variables. see the LCP solver interface for a
+		// description of what this does. this is set to -1 on entry.
+		// note that the returned indexes are relative to the first index of
+		// the constraint.
+		int *findex;
+		// number of solver iterations
+		int m_numIterations;
+
+		//damping of the velocity
+		btScalar	m_damping;
+	};
+
+	///internal method used by the constraint solver, don't use them directly
+	virtual void	buildJacobian() {};
+
+	///internal method used by the constraint solver, don't use them directly
+	virtual	void	setupSolverConstraint(btConstraintArray& ca, int solverBodyA,int solverBodyB, btScalar timeStep)
+	{
+        (void)ca;
+        (void)solverBodyA;
+        (void)solverBodyB;
+        (void)timeStep;
+	}
+	
+	///internal method used by the constraint solver, don't use them directly
+	virtual void getInfo1 (btConstraintInfo1* info)=0;
+
+	///internal method used by the constraint solver, don't use them directly
+	virtual void getInfo2 (btConstraintInfo2* info)=0;
+
+	///internal method used by the constraint solver, don't use them directly
+	void	internalSetAppliedImpulse(btScalar appliedImpulse)
+	{
+		m_appliedImpulse = appliedImpulse;
+	}
+	///internal method used by the constraint solver, don't use them directly
+	btScalar	internalGetAppliedImpulse()
+	{
+		return m_appliedImpulse;
+	}
+
+
+	btScalar	getBreakingImpulseThreshold() const
+	{
+		return 	m_breakingImpulseThreshold;
+	}
+
+	void	setBreakingImpulseThreshold(btScalar threshold)
+	{
+		m_breakingImpulseThreshold = threshold;
+	}
+
+	bool	isEnabled() const
+	{
+		return m_isEnabled;
+	}
+
+	void	setEnabled(bool enabled)
+	{
+		m_isEnabled=enabled;
+	}
+
+
+	///internal method used by the constraint solver, don't use them directly
+	virtual	void	solveConstraintObsolete(btRigidBody& /*bodyA*/,btRigidBody& /*bodyB*/,btScalar	/*timeStep*/) {};
+
+	
+	const btRigidBody& getRigidBodyA() const
+	{
+		return m_rbA;
+	}
+	const btRigidBody& getRigidBodyB() const
+	{
+		return m_rbB;
+	}
+
+	btRigidBody& getRigidBodyA() 
+	{
+		return m_rbA;
+	}
+	btRigidBody& getRigidBodyB()
+	{
+		return m_rbB;
+	}
+
+	int getUserConstraintType() const
+	{
+		return m_userConstraintType ;
+	}
+
+	void	setUserConstraintType(int userConstraintType)
+	{
+		m_userConstraintType = userConstraintType;
+	};
+
+	void	setUserConstraintId(int uid)
+	{
+		m_userConstraintId = uid;
+	}
+
+	int getUserConstraintId() const
+	{
+		return m_userConstraintId;
+	}
+
+	void	setUserConstraintPtr(void* ptr)
+	{
+		m_userConstraintPtr = ptr;
+	}
+
+	void*	getUserConstraintPtr()
+	{
+		return m_userConstraintPtr;
+	}
+
+	int getUid() const
+	{
+		return m_userConstraintId;   
+	} 
+
+	bool	needsFeedback() const
+	{
+		return m_needsFeedback;
+	}
+
+	///enableFeedback will allow to read the applied linear and angular impulse
+	///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
+	void	enableFeedback(bool needsFeedback)
+	{
+		m_needsFeedback = needsFeedback;
+	}
+
+	///getAppliedImpulse is an estimated total applied impulse. 
+	///This feedback could be used to determine breaking constraints or playing sounds.
+	btScalar	getAppliedImpulse() const
+	{
+		btAssert(m_needsFeedback);
+		return m_appliedImpulse;
+	}
+
+	btTypedConstraintType getConstraintType () const
+	{
+		return btTypedConstraintType(m_objectType);
+	}
+	
+	void setDbgDrawSize(btScalar dbgDrawSize)
+	{
+		m_dbgDrawSize = dbgDrawSize;
+	}
+	btScalar getDbgDrawSize()
+	{
+		return m_dbgDrawSize;
+	}
+
+	///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5). 
+	///If no axis is provided, it uses the default axis for this constraint.
+	virtual	void	setParam(int num, btScalar value, int axis = -1) = 0;
+
+	///return the local value of parameter
+	virtual	btScalar getParam(int num, int axis = -1) const = 0;
+	
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits 
+// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI])
+SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
+{
+	if(angleLowerLimitInRadians >= angleUpperLimitInRadians)
+	{
+		return angleInRadians;
+	}
+	else if(angleInRadians < angleLowerLimitInRadians)
+	{
+		btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians));
+		btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians));
+		return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI);
+	}
+	else if(angleInRadians > angleUpperLimitInRadians)
+	{
+		btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians));
+		btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians));
+		return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians;
+	}
+	else
+	{
+		return angleInRadians;
+	}
+}
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btTypedConstraintData
+{
+	btRigidBodyData		*m_rbA;
+	btRigidBodyData		*m_rbB;
+	char	*m_name;
+
+	int	m_objectType;
+	int	m_userConstraintType;
+	int	m_userConstraintId;
+	int	m_needsFeedback;
+
+	float	m_appliedImpulse;
+	float	m_dbgDrawSize;
+
+	int	m_disableCollisionsBetweenLinkedBodies;
+	char	m_pad4[4];
+	
+};
+
+SIMD_FORCE_INLINE	int	btTypedConstraint::calculateSerializeBufferSize() const
+{
+	return sizeof(btTypedConstraintData);
+}
+
+
+
+class btAngularLimit
+{
+private:
+	btScalar 
+		m_center,
+		m_halfRange,
+		m_softness,
+		m_biasFactor,
+		m_relaxationFactor,
+		m_correction,
+		m_sign;
+
+	bool
+		m_solveLimit;
+
+public:
+	/// Default constructor initializes limit as inactive, allowing free constraint movement
+	btAngularLimit()
+		:m_center(0.0f),
+		m_halfRange(-1.0f),
+		m_softness(0.9f),
+		m_biasFactor(0.3f),
+		m_relaxationFactor(1.0f),
+		m_correction(0.0f),
+		m_sign(0.0f),
+		m_solveLimit(false)
+	{}
+
+	/// Sets all limit's parameters.
+	/// When low > high limit becomes inactive.
+	/// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
+	void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f);
+
+	/// Checks conastaint angle against limit. If limit is active and the angle violates the limit
+	/// correction is calculated.
+	void test(const btScalar angle);
+
+	/// Returns limit's softness
+	inline btScalar getSoftness() const
+	{
+		return m_softness;
+	}
+
+	/// Returns limit's bias factor
+	inline btScalar getBiasFactor() const
+	{
+		return m_biasFactor;
+	}
+
+	/// Returns limit's relaxation factor
+	inline btScalar getRelaxationFactor() const
+	{
+		return m_relaxationFactor;
+	}
+
+	/// Returns correction value evaluated when test() was invoked 
+	inline btScalar getCorrection() const
+	{
+		return m_correction;
+	}
+
+	/// Returns sign value evaluated when test() was invoked 
+	inline btScalar getSign() const
+	{
+		return m_sign;
+	}
+
+	/// Gives half of the distance between min and max limit angle
+	inline btScalar getHalfRange() const
+	{
+		return m_halfRange;
+	}
+
+	/// Returns true when the last test() invocation recognized limit violation
+	inline bool isLimit() const
+	{
+		return m_solveLimit;
+	}
+
+	/// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
+	/// returned is modified so it equals to the limit closest to given angle.
+	void fit(btScalar& angle) const;
+
+	/// Returns correction value multiplied by sign value
+	btScalar getError() const;
+
+	btScalar getLow() const;
+
+	btScalar getHigh() const;
+
+};
+
+
+
+#endif //BT_TYPED_CONSTRAINT_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btUniversalConstraint.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "LinearMath/btTransformUtil.h"
+
+
+
+#define UNIV_EPS btScalar(0.01f)
+
+
+// constructor
+// anchor, axis1 and axis2 are in world coordinate system
+// axis1 must be orthogonal to axis2
+btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2)
+: btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
+ m_anchor(anchor),
+ m_axis1(axis1),
+ m_axis2(axis2)
+{
+	// build frame basis
+	// 6DOF constraint uses Euler angles and to define limits
+	// it is assumed that rotational order is :
+	// Z - first, allowed limits are (-PI,PI);
+	// new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number 
+	// used to prevent constraint from instability on poles;
+	// new position of X, allowed limits are (-PI,PI);
+	// So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
+	// Build the frame in world coordinate system first
+	btVector3 zAxis = axis1.normalize();
+	btVector3 yAxis = axis2.normalize();
+	btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+	btTransform frameInW;
+	frameInW.setIdentity();
+	frameInW.getBasis().setValue(	xAxis[0], yAxis[0], zAxis[0],	
+									xAxis[1], yAxis[1], zAxis[1],
+									xAxis[2], yAxis[2], zAxis[2]);
+	frameInW.setOrigin(anchor);
+	// now get constraint frame in local coordinate systems
+	m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
+	m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
+	// sei limits
+	setLinearLowerLimit(btVector3(0., 0., 0.));
+	setLinearUpperLimit(btVector3(0., 0., 0.));
+	setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS));
+	setAngularUpperLimit(btVector3(0.f,  SIMD_HALF_PI - UNIV_EPS,  SIMD_PI - UNIV_EPS));
+}
+
+void btUniversalConstraint::setAxis(const btVector3& axis1,const btVector3& axis2)
+{
+  m_axis1 = axis1;
+  m_axis2 = axis2;
+
+	btVector3 zAxis = axis1.normalized();
+	btVector3 yAxis = axis2.normalized();
+	btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
+
+	btTransform frameInW;
+	frameInW.setIdentity();
+	frameInW.getBasis().setValue(	xAxis[0], yAxis[0], zAxis[0],	
+                                xAxis[1], yAxis[1], zAxis[1],
+                                xAxis[2], yAxis[2], zAxis[2]);
+	frameInW.setOrigin(m_anchor);
+
+	// now get constraint frame in local coordinate systems
+	m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
+	m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
+
+  calculateTransforms();
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
+Copyright (C) 2006, 2007 Sony Computer Entertainment Inc. 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_UNIVERSAL_CONSTRAINT_H
+#define BT_UNIVERSAL_CONSTRAINT_H
+
+
+
+#include "LinearMath/btVector3.h"
+#include "btTypedConstraint.h"
+#include "btGeneric6DofConstraint.h"
+
+
+
+/// Constraint similar to ODE Universal Joint
+/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1)
+/// and Y (axis 2)
+/// Description from ODE manual : 
+/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular. 
+/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal."
+
+class btUniversalConstraint : public btGeneric6DofConstraint
+{
+protected:
+	btVector3	m_anchor;
+	btVector3	m_axis1;
+	btVector3	m_axis2;
+public:
+	// constructor
+	// anchor, axis1 and axis2 are in world coordinate system
+	// axis1 must be orthogonal to axis2
+    btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2);
+	// access
+	const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
+	const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
+	const btVector3& getAxis1() { return m_axis1; }
+	const btVector3& getAxis2() { return m_axis2; }
+	btScalar getAngle1() { return getAngle(2); }
+	btScalar getAngle2() { return getAngle(1); }
+	// limits
+	void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); }
+	void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); }
+
+	void setAxis( const btVector3& axis1, const btVector3& axis2);
+};
+
+
+
+#endif // BT_UNIVERSAL_CONSTRAINT_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/Bullet-C-API.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/Bullet-C-API.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/Bullet-C-API.cpp	(revision 11817)
@@ -0,0 +1,405 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+	Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
+	Work in progress, functionality will be added on demand.
+
+	If possible, use the richer Bullet C++ API, by including <src/btBulletDynamicsCommon.h>
+*/
+
+#include "Bullet-C-Api.h"
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"	
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+
+/*
+	Create and Delete a Physics SDK	
+*/
+
+struct	btPhysicsSdk
+{
+
+//	btDispatcher*				m_dispatcher;
+//	btOverlappingPairCache*		m_pairCache;
+//	btConstraintSolver*			m_constraintSolver
+
+	btVector3	m_worldAabbMin;
+	btVector3	m_worldAabbMax;
+
+
+	//todo: version, hardware/optimization settings etc?
+	btPhysicsSdk()
+		:m_worldAabbMin(-1000,-1000,-1000),
+		m_worldAabbMax(1000,1000,1000)
+	{
+
+	}
+
+	
+};
+
+plPhysicsSdkHandle	plNewBulletSdk()
+{
+	void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16);
+	return (plPhysicsSdkHandle)new (mem)btPhysicsSdk;
+}
+
+void		plDeletePhysicsSdk(plPhysicsSdkHandle	physicsSdk)
+{
+	btPhysicsSdk* phys = reinterpret_cast<btPhysicsSdk*>(physicsSdk);
+	btAlignedFree(phys);	
+}
+
+
+/* Dynamics World */
+plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle)
+{
+	btPhysicsSdk* physicsSdk = reinterpret_cast<btPhysicsSdk*>(physicsSdkHandle);
+	void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16);
+	btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration();
+	mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16);
+	btDispatcher*				dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration);
+	mem = btAlignedAlloc(sizeof(btAxisSweep3),16);
+	btBroadphaseInterface*		pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax);
+	mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+	btConstraintSolver*			constraintSolver = new(mem) btSequentialImpulseConstraintSolver();
+
+	mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16);
+	return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration);
+}
+void           plDeleteDynamicsWorld(plDynamicsWorldHandle world)
+{
+	//todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAlignedFree(dynamicsWorld);
+}
+
+void	plStepSimulation(plDynamicsWorldHandle world,	plReal	timeStep)
+{
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAssert(dynamicsWorld);
+	dynamicsWorld->stepSimulation(timeStep);
+}
+
+void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object)
+{
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAssert(dynamicsWorld);
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+
+	dynamicsWorld->addRigidBody(body);
+}
+
+void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object)
+{
+	btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+	btAssert(dynamicsWorld);
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+
+	dynamicsWorld->removeRigidBody(body);
+}
+
+/* Rigid Body  */
+
+plRigidBodyHandle plCreateRigidBody(	void* user_data,  float mass, plCollisionShapeHandle cshape )
+{
+	btTransform trans;
+	trans.setIdentity();
+	btVector3 localInertia(0,0,0);
+	btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+	btAssert(shape);
+	if (mass)
+	{
+		shape->calculateLocalInertia(mass,localInertia);
+	}
+	void* mem = btAlignedAlloc(sizeof(btRigidBody),16);
+	btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia);
+	btRigidBody* body = new (mem)btRigidBody(rbci);
+	body->setWorldTransform(trans);
+	body->setUserPointer(user_data);
+	return (plRigidBodyHandle) body;
+}
+
+void plDeleteRigidBody(plRigidBodyHandle cbody)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody);
+	btAssert(body);
+	btAlignedFree( body);
+}
+
+
+/* Collision Shape definition */
+
+plCollisionShapeHandle plNewSphereShape(plReal radius)
+{
+	void* mem = btAlignedAlloc(sizeof(btSphereShape),16);
+	return (plCollisionShapeHandle) new (mem)btSphereShape(radius);
+	
+}
+	
+plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z)
+{
+	void* mem = btAlignedAlloc(sizeof(btBoxShape),16);
+	return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z));
+}
+
+plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height)
+{
+	//capsule is convex hull of 2 spheres, so use btMultiSphereShape
+	
+	const int numSpheres = 2;
+	btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)};
+	btScalar radi[numSpheres] = {radius,radius};
+	void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16);
+	return (plCollisionShapeHandle) new (mem)btMultiSphereShape(positions,radi,numSpheres);
+}
+plCollisionShapeHandle plNewConeShape(plReal radius, plReal height)
+{
+	void* mem = btAlignedAlloc(sizeof(btConeShape),16);
+	return (plCollisionShapeHandle) new (mem)btConeShape(radius,height);
+}
+
+plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height)
+{
+	void* mem = btAlignedAlloc(sizeof(btCylinderShape),16);
+	return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius));
+}
+
+/* Convex Meshes */
+plCollisionShapeHandle plNewConvexHullShape()
+{
+	void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16);
+	return (plCollisionShapeHandle) new (mem)btConvexHullShape();
+}
+
+
+/* Concave static triangle meshes */
+plMeshInterfaceHandle		   plNewMeshInterface()
+{
+	return 0;
+}
+
+plCollisionShapeHandle plNewCompoundShape()
+{
+	void* mem = btAlignedAlloc(sizeof(btCompoundShape),16);
+	return (plCollisionShapeHandle) new (mem)btCompoundShape();
+}
+
+void	plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn)
+{
+	btCollisionShape* colShape = reinterpret_cast<btCollisionShape*>(compoundShapeHandle);
+	btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
+	btCompoundShape* compoundShape = reinterpret_cast<btCompoundShape*>(colShape);
+	btCollisionShape* childShape = reinterpret_cast<btCollisionShape*>(childShapeHandle);
+	btTransform	localTrans;
+	localTrans.setIdentity();
+	localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2]));
+	localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3]));
+	compoundShape->addChildShape(localTrans,childShape);
+}
+
+void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient)
+{
+	btQuaternion orn;
+	orn.setEuler(yaw,pitch,roll);
+	orient[0] = orn.getX();
+	orient[1] = orn.getY();
+	orient[2] = orn.getZ();
+	orient[3] = orn.getW();
+
+}
+
+
+//	extern  void		plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
+//	extern  plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+
+
+void		plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z)
+{
+	btCollisionShape* colShape = reinterpret_cast<btCollisionShape*>( cshape);
+	(void)colShape;
+	btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE);
+	btConvexHullShape* convexHullShape = reinterpret_cast<btConvexHullShape*>( cshape);
+	convexHullShape->addPoint(btVector3(x,y,z));
+
+}
+
+void plDeleteShape(plCollisionShapeHandle cshape)
+{
+	btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+	btAssert(shape);
+	btAlignedFree(shape);
+}
+void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling)
+{
+	btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+	btAssert(shape);
+	btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]);
+	shape->setLocalScaling(scaling);	
+}
+
+
+
+void plSetPosition(plRigidBodyHandle object, const plVector3 position)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	btVector3 pos(position[0],position[1],position[2]);
+	btTransform worldTrans = body->getWorldTransform();
+	worldTrans.setOrigin(pos);
+	body->setWorldTransform(worldTrans);
+}
+
+void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]);
+	btTransform worldTrans = body->getWorldTransform();
+	worldTrans.setRotation(orn);
+	body->setWorldTransform(worldTrans);
+}
+
+void	plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	btTransform& worldTrans = body->getWorldTransform();
+	worldTrans.setFromOpenGLMatrix(matrix);
+}
+
+void	plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	body->getWorldTransform().getOpenGLMatrix(matrix);
+
+}
+
+void	plGetPosition(plRigidBodyHandle object,plVector3 position)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	const btVector3& pos = body->getWorldTransform().getOrigin();
+	position[0] = pos.getX();
+	position[1] = pos.getY();
+	position[2] = pos.getZ();
+}
+
+void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation)
+{
+	btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+	btAssert(body);
+	const btQuaternion& orn = body->getWorldTransform().getRotation();
+	orientation[0] = orn.getX();
+	orientation[1] = orn.getY();
+	orientation[2] = orn.getZ();
+	orientation[3] = orn.getW();
+}
+
+
+
+//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal);
+
+//	extern  plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal);
+
+double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3])
+{
+	btVector3 vp(p1[0], p1[1], p1[2]);
+	btTriangleShape trishapeA(vp, 
+				  btVector3(p2[0], p2[1], p2[2]), 
+				  btVector3(p3[0], p3[1], p3[2]));
+	trishapeA.setMargin(0.000001f);
+	btVector3 vq(q1[0], q1[1], q1[2]);
+	btTriangleShape trishapeB(vq, 
+				  btVector3(q2[0], q2[1], q2[2]), 
+				  btVector3(q3[0], q3[1], q3[2]));
+	trishapeB.setMargin(0.000001f);
+	
+	// btVoronoiSimplexSolver sGjkSimplexSolver;
+	// btGjkEpaPenetrationDepthSolver penSolverPtr;	
+	
+	static btSimplexSolverInterface sGjkSimplexSolver;
+	sGjkSimplexSolver.reset();
+	
+	static btGjkEpaPenetrationDepthSolver Solver0;
+	static btMinkowskiPenetrationDepthSolver Solver1;
+		
+	btConvexPenetrationDepthSolver* Solver = NULL;
+	
+	Solver = &Solver1;	
+		
+	btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver);
+	
+	convexConvex.m_catchDegeneracies = 1;
+	
+	// btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,0);
+	
+	btPointCollector gjkOutput;
+	btGjkPairDetector::ClosestPointInput input;
+	
+		
+	btTransform tr;
+	tr.setIdentity();
+	
+	input.m_transformA = tr;
+	input.m_transformB = tr;
+	
+	convexConvex.getClosestPoints(input, gjkOutput, 0);
+	
+	
+	if (gjkOutput.m_hasResult)
+	{
+		
+		pb[0] = pa[0] = gjkOutput.m_pointInWorld[0];
+		pb[1] = pa[1] = gjkOutput.m_pointInWorld[1];
+		pb[2] = pa[2] = gjkOutput.m_pointInWorld[2];
+
+		pb[0]+= gjkOutput.m_normalOnBInWorld[0] * gjkOutput.m_distance;
+		pb[1]+= gjkOutput.m_normalOnBInWorld[1] * gjkOutput.m_distance;
+		pb[2]+= gjkOutput.m_normalOnBInWorld[2] * gjkOutput.m_distance;
+		
+		normal[0] = gjkOutput.m_normalOnBInWorld[0];
+		normal[1] = gjkOutput.m_normalOnBInWorld[1];
+		normal[2] = gjkOutput.m_normalOnBInWorld[2];
+
+		return gjkOutput.m_distance;
+	}
+	return -1.0f;	
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btActionInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btActionInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btActionInterface.h	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_ACTION_INTERFACE_H
+#define _BT_ACTION_INTERFACE_H
+
+class btIDebugDraw;
+class btCollisionWorld;
+
+#include "LinearMath/btScalar.h"
+#include "btRigidBody.h"
+
+///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld
+class btActionInterface
+{
+protected:
+
+	static btRigidBody& getFixedBody();
+	
+	
+public:
+
+	virtual ~btActionInterface()
+	{
+	}
+
+	virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0;
+
+	virtual void debugDraw(btIDebugDraw* debugDrawer) = 0;
+
+};
+
+#endif //_BT_ACTION_INTERFACE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp	(revision 11817)
@@ -0,0 +1,196 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btContinuousDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+
+
+
+#include <stdio.h>
+
+btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
+{
+}
+
+btContinuousDynamicsWorld::~btContinuousDynamicsWorld()
+{
+}
+
+	
+void	btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
+{
+	
+	startProfiling(timeStep);
+	
+	if(0 != m_internalPreTickCallback) {
+		(*m_internalPreTickCallback)(this, timeStep);
+	}
+
+
+	///update aabbs information
+	updateAabbs();
+	//static int frame=0;
+//	printf("frame %d\n",frame++);
+
+	///apply gravity, predict motion
+	predictUnconstraintMotion(timeStep);
+
+	btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+	dispatchInfo.m_timeStep = timeStep;
+	dispatchInfo.m_stepCount = 0;
+	dispatchInfo.m_debugDraw = getDebugDrawer();
+
+	///perform collision detection
+	performDiscreteCollisionDetection();
+
+	calculateSimulationIslands();
+
+	
+	getSolverInfo().m_timeStep = timeStep;
+	
+
+
+	///solve contact and other joint constraints
+	solveConstraints(getSolverInfo());
+	
+	///CallbackTriggers();
+	calculateTimeOfImpacts(timeStep);
+
+	btScalar toi = dispatchInfo.m_timeOfImpact;
+//	if (toi < 1.f)
+//		printf("toi = %f\n",toi);
+	if (toi < 0.f)
+		printf("toi = %f\n",toi);
+
+
+	///integrate transforms
+	integrateTransforms(timeStep * toi);
+
+	///update vehicle simulation
+	updateActions(timeStep);
+
+	updateActivationState( timeStep );
+	
+	if(0 != m_internalTickCallback) {
+		(*m_internalTickCallback)(this, timeStep);
+	}
+}
+
+void	btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep)
+{
+		///these should be 'temporal' aabbs!
+		updateTemporalAabbs(timeStep);
+		
+		///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually.
+		///so we handle the case moving versus static properly, and we cheat for moving versus moving
+		btScalar toi = 1.f;
+		
+	
+		btDispatcherInfo& dispatchInfo = getDispatchInfo();
+		dispatchInfo.m_timeStep = timeStep;
+		dispatchInfo.m_timeOfImpact = 1.f;
+		dispatchInfo.m_stepCount = 0;
+		dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS;
+
+		///calculate time of impact for overlapping pairs
+
+
+		btDispatcher* dispatcher = getDispatcher();
+		if (dispatcher)
+			dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+
+		toi = dispatchInfo.m_timeOfImpact;
+
+		dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;
+
+}
+
+void	btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
+{
+
+	btVector3 temporalAabbMin,temporalAabbMax;
+
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body)
+		{
+			body->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax);
+			const btVector3& linvel = body->getLinearVelocity();
+
+			//make the AABB temporal
+			btScalar temporalAabbMaxx = temporalAabbMax.getX();
+			btScalar temporalAabbMaxy = temporalAabbMax.getY();
+			btScalar temporalAabbMaxz = temporalAabbMax.getZ();
+			btScalar temporalAabbMinx = temporalAabbMin.getX();
+			btScalar temporalAabbMiny = temporalAabbMin.getY();
+			btScalar temporalAabbMinz = temporalAabbMin.getZ();
+
+			// add linear motion
+			btVector3 linMotion = linvel*timeStep;
+		
+			if (linMotion.x() > 0.f)
+				temporalAabbMaxx += linMotion.x(); 
+			else
+				temporalAabbMinx += linMotion.x();
+			if (linMotion.y() > 0.f)
+				temporalAabbMaxy += linMotion.y(); 
+			else
+				temporalAabbMiny += linMotion.y();
+			if (linMotion.z() > 0.f)
+				temporalAabbMaxz += linMotion.z(); 
+			else
+				temporalAabbMinz += linMotion.z();
+
+			//add conservative angular motion
+			btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep;
+			btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
+			temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
+			temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
+
+			temporalAabbMin -= angularMotion3d;
+			temporalAabbMax += angularMotion3d;
+
+			m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1);
+		}
+	}
+
+	//update aabb (of all moved objects)
+
+	m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+	
+
+
+}
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H
+#define BT_CONTINUOUS_DYNAMICS_WORLD_H
+
+#include "btDiscreteDynamicsWorld.h"
+
+///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld.
+///This copes with fast moving objects that otherwise would tunnel/miss collisions.
+///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead.
+class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld
+{
+
+	void	updateTemporalAabbs(btScalar timeStep);
+
+	public:
+
+		btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+		virtual ~btContinuousDynamicsWorld();
+		
+		///time stepping with calculation of time of impact for selected fast moving objects
+		virtual void	internalSingleStepSimulation( btScalar timeStep);
+
+		virtual void	calculateTimeOfImpacts(btScalar timeStep);
+
+		virtual btDynamicsWorldType	getWorldType() const
+		{
+			return BT_CONTINUOUS_DYNAMICS_WORLD;
+		}
+
+};
+
+#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp	(revision 11817)
@@ -0,0 +1,1348 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btDiscreteDynamicsWorld.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btMotionState.h"
+
+#include "LinearMath/btSerializer.h"
+
+#if 0
+btAlignedObjectArray<btVector3> debugContacts;
+btAlignedObjectArray<btVector3> debugNormals;
+int startHit=2;
+int firstHit=startHit;
+#endif
+
+
+
+btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_constraintSolver(constraintSolver),
+m_gravity(0,-10,0),
+m_localTime(0),
+m_synchronizeAllMotionStates(false),
+m_profileTimings(0)
+{
+	if (!m_constraintSolver)
+	{
+		void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+		m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
+		m_ownsConstraintSolver = true;
+	} else
+	{
+		m_ownsConstraintSolver = false;
+	}
+
+	{
+		void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
+		m_islandManager = new (mem) btSimulationIslandManager();
+	}
+
+	m_ownsIslandManager = true;
+}
+
+
+btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
+{
+	//only delete it when we created it
+	if (m_ownsIslandManager)
+	{
+		m_islandManager->~btSimulationIslandManager();
+		btAlignedFree( m_islandManager);
+	}
+	if (m_ownsConstraintSolver)
+	{
+
+		m_constraintSolver->~btConstraintSolver();
+		btAlignedFree(m_constraintSolver);
+	}
+}
+
+void	btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
+{
+///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
+///to switch status _after_ adding kinematic objects to the world
+///fix it for Bullet 3.x release
+	for (int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body && body->getActivationState() != ISLAND_SLEEPING)
+		{
+			if (body->isKinematicObject())
+			{
+				//to calculate velocities next frame
+				body->saveKinematicState(timeStep);
+			}
+		}
+	}
+
+}
+
+void	btDiscreteDynamicsWorld::debugDrawWorld()
+{
+	BT_PROFILE("debugDrawWorld");
+
+	btCollisionWorld::debugDrawWorld();
+
+	bool drawConstraints = false;
+	if (getDebugDrawer())
+	{
+		int mode = getDebugDrawer()->getDebugMode();
+		if(mode  & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+		{
+			drawConstraints = true;
+		}
+	}
+	if(drawConstraints)
+	{
+		for(int i = getNumConstraints()-1; i>=0 ;i--)
+		{
+			btTypedConstraint* constraint = getConstraint(i);
+			debugDrawConstraint(constraint);
+		}
+	}
+
+
+
+	if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
+	{
+		int i;
+
+		if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
+		{
+			for (i=0;i<m_actions.size();i++)
+			{
+				m_actions[i]->debugDraw(m_debugDrawer);
+			}
+		}
+	}
+}
+
+void	btDiscreteDynamicsWorld::clearForces()
+{
+	///@todo: iterate over awake simulation islands!
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		//need to check if next line is ok
+		//it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
+		body->clearForces();
+	}
+}	
+
+///apply gravity, call this once per timestep
+void	btDiscreteDynamicsWorld::applyGravity()
+{
+	///@todo: iterate over awake simulation islands!
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		if (body->isActive())
+		{
+			body->applyGravity();
+		}
+	}
+}
+
+
+void	btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
+{
+	btAssert(body);
+
+	if (body->getMotionState() && !body->isStaticOrKinematicObject())
+	{
+		//we need to call the update at least once, even for sleeping objects
+		//otherwise the 'graphics' transform never updates properly
+		///@todo: add 'dirty' flag
+		//if (body->getActivationState() != ISLAND_SLEEPING)
+		{
+			btTransform interpolatedTransform;
+			btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
+				body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform);
+			body->getMotionState()->setWorldTransform(interpolatedTransform);
+		}
+	}
+}
+
+
+void	btDiscreteDynamicsWorld::synchronizeMotionStates()
+{
+	BT_PROFILE("synchronizeMotionStates");
+	if (m_synchronizeAllMotionStates)
+	{
+		//iterate  over all collision objects
+		for ( int i=0;i<m_collisionObjects.size();i++)
+		{
+			btCollisionObject* colObj = m_collisionObjects[i];
+			btRigidBody* body = btRigidBody::upcast(colObj);
+			if (body)
+				synchronizeSingleMotionState(body);
+		}
+	} else
+	{
+		//iterate over all active rigid bodies
+		for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+		{
+			btRigidBody* body = m_nonStaticRigidBodies[i];
+			if (body->isActive())
+				synchronizeSingleMotionState(body);
+		}
+	}
+}
+
+
+int	btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+{
+	startProfiling(timeStep);
+
+	BT_PROFILE("stepSimulation");
+
+	int numSimulationSubSteps = 0;
+
+	if (maxSubSteps)
+	{
+		//fixed timestep with interpolation
+		m_localTime += timeStep;
+		if (m_localTime >= fixedTimeStep)
+		{
+			numSimulationSubSteps = int( m_localTime / fixedTimeStep);
+			m_localTime -= numSimulationSubSteps * fixedTimeStep;
+		}
+	} else
+	{
+		//variable timestep
+		fixedTimeStep = timeStep;
+		m_localTime = timeStep;
+		if (btFuzzyZero(timeStep))
+		{
+			numSimulationSubSteps = 0;
+			maxSubSteps = 0;
+		} else
+		{
+			numSimulationSubSteps = 1;
+			maxSubSteps = 1;
+		}
+	}
+
+	//process some debugging flags
+	if (getDebugDrawer())
+	{
+		btIDebugDraw* debugDrawer = getDebugDrawer ();
+		gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
+	}
+	if (numSimulationSubSteps)
+	{
+
+		//clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
+		int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
+
+		saveKinematicState(fixedTimeStep*clampedSimulationSteps);
+
+		applyGravity();
+
+		
+
+		for (int i=0;i<clampedSimulationSteps;i++)
+		{
+			internalSingleStepSimulation(fixedTimeStep);
+			synchronizeMotionStates();
+		}
+
+	} else
+	{
+		synchronizeMotionStates();
+	}
+
+	clearForces();
+
+#ifndef BT_NO_PROFILE
+	CProfileManager::Increment_Frame_Counter();
+#endif //BT_NO_PROFILE
+	
+	return numSimulationSubSteps;
+}
+
+void	btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+	
+	BT_PROFILE("internalSingleStepSimulation");
+
+	if(0 != m_internalPreTickCallback) {
+		(*m_internalPreTickCallback)(this, timeStep);
+	}	
+
+	///apply gravity, predict motion
+	predictUnconstraintMotion(timeStep);
+
+	btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+	dispatchInfo.m_timeStep = timeStep;
+	dispatchInfo.m_stepCount = 0;
+	dispatchInfo.m_debugDraw = getDebugDrawer();
+
+
+	///perform collision detection
+	performDiscreteCollisionDetection();
+
+	if (getDispatchInfo().m_useContinuous)
+		addSpeculativeContacts(timeStep);
+
+
+	calculateSimulationIslands();
+
+	
+	getSolverInfo().m_timeStep = timeStep;
+	
+
+
+	///solve contact and other joint constraints
+	solveConstraints(getSolverInfo());
+	
+	///CallbackTriggers();
+
+	///integrate transforms
+	integrateTransforms(timeStep);
+
+	///update vehicle simulation
+	updateActions(timeStep);
+	
+	updateActivationState( timeStep );
+
+	if(0 != m_internalTickCallback) {
+		(*m_internalTickCallback)(this, timeStep);
+	}	
+}
+
+void	btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
+{
+	m_gravity = gravity;
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+		{
+			body->setGravity(gravity);
+		}
+	}
+}
+
+btVector3 btDiscreteDynamicsWorld::getGravity () const
+{
+	return m_gravity;
+}
+
+void	btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
+{
+	btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
+}
+
+void	btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+	btRigidBody* body = btRigidBody::upcast(collisionObject);
+	if (body)
+		removeRigidBody(body);
+	else
+		btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+void	btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+	m_nonStaticRigidBodies.remove(body);
+	btCollisionWorld::removeCollisionObject(body);
+}
+
+
+void	btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+	if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+	{
+		body->setGravity(m_gravity);
+	}
+
+	if (body->getCollisionShape())
+	{
+		if (!body->isStaticObject())
+		{
+			m_nonStaticRigidBodies.push_back(body);
+		} else
+		{
+			body->setActivationState(ISLAND_SLEEPING);
+		}
+
+		bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
+		short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter);
+		short collisionFilterMask = isDynamic? 	short(btBroadphaseProxy::AllFilter) : 	short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+		addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
+	}
+}
+
+void	btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
+{
+	if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+	{
+		body->setGravity(m_gravity);
+	}
+
+	if (body->getCollisionShape())
+	{
+		if (!body->isStaticObject())
+		{
+			m_nonStaticRigidBodies.push_back(body);
+		}
+		 else
+		{
+			body->setActivationState(ISLAND_SLEEPING);
+		}
+		addCollisionObject(body,group,mask);
+	}
+}
+
+
+void	btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
+{
+	BT_PROFILE("updateActions");
+	
+	for ( int i=0;i<m_actions.size();i++)
+	{
+		m_actions[i]->updateAction( this, timeStep);
+	}
+}
+	
+	
+void	btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+	BT_PROFILE("updateActivationState");
+
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		if (body)
+		{
+			body->updateDeactivation(timeStep);
+
+			if (body->wantsSleeping())
+			{
+				if (body->isStaticOrKinematicObject())
+				{
+					body->setActivationState(ISLAND_SLEEPING);
+				} else
+				{
+					if (body->getActivationState() == ACTIVE_TAG)
+						body->setActivationState( WANTS_DEACTIVATION );
+					if (body->getActivationState() == ISLAND_SLEEPING) 
+					{
+						body->setAngularVelocity(btVector3(0,0,0));
+						body->setLinearVelocity(btVector3(0,0,0));
+					}
+
+				}
+			} else
+			{
+				if (body->getActivationState() != DISABLE_DEACTIVATION)
+					body->setActivationState( ACTIVE_TAG );
+			}
+		}
+	}
+}
+
+void	btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
+{
+	m_constraints.push_back(constraint);
+	if (disableCollisionsBetweenLinkedBodies)
+	{
+		constraint->getRigidBodyA().addConstraintRef(constraint);
+		constraint->getRigidBodyB().addConstraintRef(constraint);
+	}
+}
+
+void	btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
+{
+	m_constraints.remove(constraint);
+	constraint->getRigidBodyA().removeConstraintRef(constraint);
+	constraint->getRigidBodyB().removeConstraintRef(constraint);
+}
+
+void	btDiscreteDynamicsWorld::addAction(btActionInterface* action)
+{
+	m_actions.push_back(action);
+}
+
+void	btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
+{
+	m_actions.remove(action);
+}
+
+
+void	btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
+{
+	addAction(vehicle);
+}
+
+void	btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
+{
+	removeAction(vehicle);
+}
+
+void	btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
+{
+	addAction(character);
+}
+
+void	btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
+{
+	removeAction(character);
+}
+
+
+SIMD_FORCE_INLINE	int	btGetConstraintIslandId(const btTypedConstraint* lhs)
+{
+	int islandId;
+	
+	const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+	const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+	islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
+	return islandId;
+
+}
+
+
+class btSortConstraintOnIslandPredicate
+{
+	public:
+
+		bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs )
+		{
+			int rIslandId0,lIslandId0;
+			rIslandId0 = btGetConstraintIslandId(rhs);
+			lIslandId0 = btGetConstraintIslandId(lhs);
+			return lIslandId0 < rIslandId0;
+		}
+};
+
+
+
+void	btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+{
+	BT_PROFILE("solveConstraints");
+	
+	struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+	{
+
+		btContactSolverInfo&	m_solverInfo;
+		btConstraintSolver*		m_solver;
+		btTypedConstraint**		m_sortedConstraints;
+		int						m_numConstraints;
+		btIDebugDraw*			m_debugDrawer;
+		btStackAlloc*			m_stackAlloc;
+		btDispatcher*			m_dispatcher;
+		
+		btAlignedObjectArray<btCollisionObject*> m_bodies;
+		btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+		btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+
+		InplaceSolverIslandCallback(
+			btContactSolverInfo& solverInfo,
+			btConstraintSolver*	solver,
+			btTypedConstraint** sortedConstraints,
+			int	numConstraints,
+			btIDebugDraw*	debugDrawer,
+			btStackAlloc*			stackAlloc,
+			btDispatcher* dispatcher)
+			:m_solverInfo(solverInfo),
+			m_solver(solver),
+			m_sortedConstraints(sortedConstraints),
+			m_numConstraints(numConstraints),
+			m_debugDrawer(debugDrawer),
+			m_stackAlloc(stackAlloc),
+			m_dispatcher(dispatcher)
+		{
+
+		}
+
+
+		InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
+		{
+			btAssert(0);
+			(void)other;
+			return *this;
+		}
+		virtual	void	ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold**	manifolds,int numManifolds, int islandId)
+		{
+			if (islandId<0)
+			{
+				if (numManifolds + m_numConstraints)
+				{
+					///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+					m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+				}
+			} else
+			{
+					//also add all non-contact constraints/joints for this island
+				btTypedConstraint** startConstraint = 0;
+				int numCurConstraints = 0;
+				int i;
+				
+				//find the first constraint for this island
+				for (i=0;i<m_numConstraints;i++)
+				{
+					if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+					{
+						startConstraint = &m_sortedConstraints[i];
+						break;
+					}
+				}
+				//count the number of constraints in this island
+				for (;i<m_numConstraints;i++)
+				{
+					if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+					{
+						numCurConstraints++;
+					}
+				}
+
+				if (m_solverInfo.m_minimumSolverBatchSize<=1)
+				{
+					///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive
+					if (numManifolds + numCurConstraints)
+					{
+						m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+					}
+				} else
+				{
+					
+					for (i=0;i<numBodies;i++)
+						m_bodies.push_back(bodies[i]);
+					for (i=0;i<numManifolds;i++)
+						m_manifolds.push_back(manifolds[i]);
+					for (i=0;i<numCurConstraints;i++)
+						m_constraints.push_back(startConstraint[i]);
+					if ((m_constraints.size()+m_manifolds.size())>m_solverInfo.m_minimumSolverBatchSize)
+					{
+						processConstraints();
+					} else
+					{
+						//printf("deferred\n");
+					}
+				}
+			}
+		}
+		void	processConstraints()
+		{
+			if (m_manifolds.size() + m_constraints.size()>0)
+			{
+				m_solver->solveGroup( &m_bodies[0],m_bodies.size(), &m_manifolds[0], m_manifolds.size(), &m_constraints[0], m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+			}
+			m_bodies.resize(0);
+			m_manifolds.resize(0);
+			m_constraints.resize(0);
+
+		}
+
+	};
+
+	
+
+	//sorted version of all btTypedConstraint, based on islandId
+	btAlignedObjectArray<btTypedConstraint*>	sortedConstraints;
+	sortedConstraints.resize( m_constraints.size());
+	int i; 
+	for (i=0;i<getNumConstraints();i++)
+	{
+		sortedConstraints[i] = m_constraints[i];
+	}
+
+//	btAssert(0);
+		
+	
+
+	sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
+	
+	btTypedConstraint** constraintsPtr = getNumConstraints() ? &sortedConstraints[0] : 0;
+	
+	InplaceSolverIslandCallback	solverCallback(	solverInfo,	m_constraintSolver, constraintsPtr,sortedConstraints.size(),	m_debugDrawer,m_stackAlloc,m_dispatcher1);
+	
+	m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+	
+	/// solve all the constraints for this island
+	m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),&solverCallback);
+
+	solverCallback.processConstraints();
+
+	m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc);
+}
+
+
+
+
+void	btDiscreteDynamicsWorld::calculateSimulationIslands()
+{
+	BT_PROFILE("calculateSimulationIslands");
+
+	getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
+
+	{
+		int i;
+		int numConstraints = int(m_constraints.size());
+		for (i=0;i< numConstraints ; i++ )
+		{
+			btTypedConstraint* constraint = m_constraints[i];
+
+			const btRigidBody* colObj0 = &constraint->getRigidBodyA();
+			const btRigidBody* colObj1 = &constraint->getRigidBodyB();
+
+			if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+				((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+			{
+				if (colObj0->isActive() || colObj1->isActive())
+				{
+
+					getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
+						(colObj1)->getIslandTag());
+				}
+			}
+		}
+	}
+
+	//Store the island id in each body
+	getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
+
+	
+}
+
+
+
+
+class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+public:
+
+	btCollisionObject* m_me;
+	btScalar m_allowedPenetration;
+	btOverlappingPairCache* m_pairCache;
+	btDispatcher* m_dispatcher;
+
+public:
+	btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : 
+	  btCollisionWorld::ClosestConvexResultCallback(fromA,toA),
+		m_me(me),
+		m_allowedPenetration(0.0f),
+		m_pairCache(pairCache),
+		m_dispatcher(dispatcher)
+	{
+	}
+
+	virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+	{
+		if (convexResult.m_hitCollisionObject == m_me)
+			return 1.0f;
+
+		//ignore result if there is no contact response
+		if(!convexResult.m_hitCollisionObject->hasContactResponse())
+			return 1.0f;
+
+		btVector3 linVelA,linVelB;
+		linVelA = m_convexToWorld-m_convexFromWorld;
+		linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
+
+		btVector3 relativeVelocity = (linVelA-linVelB);
+		//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+		if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration)
+			return 1.f;
+
+		return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+	}
+
+	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+	{
+		//don't collide with itself
+		if (proxy0->m_clientObject == m_me)
+			return false;
+
+		///don't do CCD when the collision filters are not matching
+		if (!ClosestConvexResultCallback::needsCollision(proxy0))
+			return false;
+
+		btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+
+		//call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
+		if (m_dispatcher->needsResponse(m_me,otherObj))
+		{
+#if 0
+			///don't do CCD when there are already contact points (touching contact/penetration)
+			btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+			btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
+			if (collisionPair)
+			{
+				if (collisionPair->m_algorithm)
+				{
+					manifoldArray.resize(0);
+					collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
+					for (int j=0;j<manifoldArray.size();j++)
+					{
+						btPersistentManifold* manifold = manifoldArray[j];
+						if (manifold->getNumContacts()>0)
+							return false;
+					}
+				}
+			}
+#endif
+			return true;
+		}
+
+		return false;
+	}
+
+
+};
+
+///internal debugging variable. this value shouldn't be too high
+int gNumClampedCcdMotions=0;
+
+void	btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+	BT_PROFILE("integrateTransforms");
+	btTransform predictedTrans;
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		body->setHitFraction(1.f);
+
+		if (body->isActive() && (!body->isStaticOrKinematicObject()))
+		{
+
+			body->predictIntegratedTransform(timeStep, predictedTrans);
+			
+			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+
+			
+
+			if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+			{
+				BT_PROFILE("CCD motion clamping");
+				if (body->getCollisionShape()->isConvex())
+				{
+					gNumClampedCcdMotions++;
+#ifdef USE_STATIC_ONLY
+					class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
+					{
+					public:
+
+						StaticOnlyCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) : 
+						  btClosestNotMeConvexResultCallback(me,fromA,toA,pairCache,dispatcher)
+						{
+						}
+
+					  	virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+						{
+							btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+							if (!otherObj->isStaticOrKinematicObject())
+								return false;
+							return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
+						}
+					};
+
+					StaticOnlyCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#else
+					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+#endif
+					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+					sweepResults.m_allowedPenetration=getDispatchInfo().m_allowedCcdPenetration;
+
+					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
+					btTransform modifiedPredictedTrans = predictedTrans;
+					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+					{
+						
+						//printf("clamped integration to hit fraction = %f\n",fraction);
+						body->setHitFraction(sweepResults.m_closestHitFraction);
+						body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
+						body->setHitFraction(0.f);
+						body->proceedToTransform( predictedTrans);
+
+#if 0
+						btVector3 linVel = body->getLinearVelocity();
+
+						btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
+						btScalar maxSpeedSqr = maxSpeed*maxSpeed;
+						if (linVel.length2()>maxSpeedSqr)
+						{
+							linVel.normalize();
+							linVel*= maxSpeed;
+							body->setLinearVelocity(linVel);
+							btScalar ms2 = body->getLinearVelocity().length2();
+							body->predictIntegratedTransform(timeStep, predictedTrans);
+
+							btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+							btScalar smt = body->getCcdSquareMotionThreshold();
+							printf("sm2=%f\n",sm2);
+						}
+#else
+						//response  between two dynamic objects without friction, assuming 0 penetration depth
+						btScalar appliedImpulse = 0.f;
+						btScalar depth = 0.f;
+						appliedImpulse = resolveSingleCollision(body,sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
+						
+
+#endif
+
+        				continue;
+					}
+				}
+			}
+			
+
+			body->proceedToTransform( predictedTrans);
+		}
+	}
+}
+
+void	btDiscreteDynamicsWorld::addSpeculativeContacts(btScalar timeStep)
+{
+	BT_PROFILE("addSpeculativeContacts");
+	btTransform predictedTrans;
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		body->setHitFraction(1.f);
+
+		if (body->isActive() && (!body->isStaticOrKinematicObject()))
+		{
+			body->predictIntegratedTransform(timeStep, predictedTrans);
+			btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+
+			if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+			{
+				BT_PROFILE("search speculative contacts");
+				if (body->getCollisionShape()->isConvex())
+				{
+					gNumClampedCcdMotions++;
+					
+					btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+					//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+					btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+
+					sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+					sweepResults.m_collisionFilterMask  = body->getBroadphaseProxy()->m_collisionFilterMask;
+					btTransform modifiedPredictedTrans;
+					modifiedPredictedTrans = predictedTrans;
+					modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
+
+					convexSweepTest(&tmpSphere,body->getWorldTransform(),modifiedPredictedTrans,sweepResults);
+					if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+					{
+						btBroadphaseProxy* proxy0 = body->getBroadphaseHandle();
+						btBroadphaseProxy* proxy1 = sweepResults.m_hitCollisionObject->getBroadphaseHandle();
+						btBroadphasePair* pair = sweepResults.m_pairCache->findPair(proxy0,proxy1);
+						if (pair)
+						{
+							if (pair->m_algorithm)
+							{
+								btManifoldArray contacts;
+								pair->m_algorithm->getAllContactManifolds(contacts);
+								if (contacts.size())
+								{
+									btManifoldResult result(body,sweepResults.m_hitCollisionObject);
+									result.setPersistentManifold(contacts[0]);
+
+									btVector3 vec = (modifiedPredictedTrans.getOrigin()-body->getWorldTransform().getOrigin());
+									vec*=sweepResults.m_closestHitFraction;
+									
+									btScalar lenSqr = vec.length2();
+									btScalar depth = 0.f;
+									btVector3 pointWorld = sweepResults.m_hitPointWorld;
+									if (lenSqr>SIMD_EPSILON)
+									{
+										depth = btSqrt(lenSqr);
+										pointWorld -= vec;
+										vec /= depth;
+									}
+
+									if (contacts[0]->getBody0()==body)
+									{
+										result.addContactPoint(sweepResults.m_hitNormalWorld,pointWorld,depth);
+#if 0
+										debugContacts.push_back(sweepResults.m_hitPointWorld);//sweepResults.m_hitPointWorld);
+										debugNormals.push_back(sweepResults.m_hitNormalWorld);
+#endif
+									} else
+									{
+										//swapped
+										result.addContactPoint(-sweepResults.m_hitNormalWorld,pointWorld,depth);
+										//sweepResults.m_hitPointWorld,depth);
+										
+#if 0
+										if (1)//firstHit==1)
+										{
+											firstHit=0;
+											debugNormals.push_back(sweepResults.m_hitNormalWorld);
+											debugContacts.push_back(pointWorld);//sweepResults.m_hitPointWorld);
+											debugNormals.push_back(sweepResults.m_hitNormalWorld);
+											debugContacts.push_back(sweepResults.m_hitPointWorld);
+										}
+										firstHit--;
+#endif
+									}
+								}
+
+							} else
+							{
+								//no algorithm, use dispatcher to create one
+
+							}
+
+
+						} else
+						{
+							//add an overlapping pair
+							//printf("pair missing\n");
+
+						}
+					}
+				}
+			}
+			
+		}
+	}
+}
+
+
+
+
+
+void	btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+	BT_PROFILE("predictUnconstraintMotion");
+	for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+	{
+		btRigidBody* body = m_nonStaticRigidBodies[i];
+		if (!body->isStaticOrKinematicObject())
+		{
+			body->integrateVelocities( timeStep);
+			//damping
+			body->applyDamping(timeStep);
+
+			body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+		}
+	}
+}
+
+
+void	btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
+{
+	(void)timeStep;
+
+#ifndef BT_NO_PROFILE
+	CProfileManager::Reset();
+#endif //BT_NO_PROFILE
+
+}
+
+
+
+
+	
+
+void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
+{
+	bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
+	bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
+	btScalar dbgDrawSize = constraint->getDbgDrawSize();
+	if(dbgDrawSize <= btScalar(0.f))
+	{
+		return;
+	}
+
+	switch(constraint->getConstraintType())
+	{
+		case POINT2POINT_CONSTRAINT_TYPE:
+			{
+				btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
+				btTransform tr;
+				tr.setIdentity();
+				btVector3 pivot = p2pC->getPivotInA();
+				pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot; 
+				tr.setOrigin(pivot);
+				getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				// that ideally should draw the same frame	
+				pivot = p2pC->getPivotInB();
+				pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot; 
+				tr.setOrigin(pivot);
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+			}
+			break;
+		case HINGE_CONSTRAINT_TYPE:
+			{
+				btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
+				btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				btScalar minAng = pHinge->getLowerLimit();
+				btScalar maxAng = pHinge->getUpperLimit();
+				if(minAng == maxAng)
+				{
+					break;
+				}
+				bool drawSect = true;
+				if(minAng > maxAng)
+				{
+					minAng = btScalar(0.f);
+					maxAng = SIMD_2_PI;
+					drawSect = false;
+				}
+				if(drawLimits) 
+				{
+					btVector3& center = tr.getOrigin();
+					btVector3 normal = tr.getBasis().getColumn(2);
+					btVector3 axis = tr.getBasis().getColumn(0);
+					getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect);
+				}
+			}
+			break;
+		case CONETWIST_CONSTRAINT_TYPE:
+			{
+				btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
+				btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				if(drawLimits)
+				{
+					//const btScalar length = btScalar(5);
+					const btScalar length = dbgDrawSize;
+					static int nSegments = 8*4;
+					btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments);
+					btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
+					pPrev = tr * pPrev;
+					for (int i=0; i<nSegments; i++)
+					{
+						fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
+						btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
+						pCur = tr * pCur;
+						getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
+
+						if (i%(nSegments/8) == 0)
+							getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
+
+						pPrev = pCur;
+					}						
+					btScalar tws = pCT->getTwistSpan();
+					btScalar twa = pCT->getTwistAngle();
+					bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
+					if(useFrameB)
+					{
+						tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+					}
+					else
+					{
+						tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+					}
+					btVector3 pivot = tr.getOrigin();
+					btVector3 normal = tr.getBasis().getColumn(0);
+					btVector3 axis1 = tr.getBasis().getColumn(1);
+					getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true);
+
+				}
+			}
+			break;
+		case D6_SPRING_CONSTRAINT_TYPE:
+		case D6_CONSTRAINT_TYPE:
+			{
+				btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
+				btTransform tr = p6DOF->getCalculatedTransformA();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				tr = p6DOF->getCalculatedTransformB();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				if(drawLimits) 
+				{
+					tr = p6DOF->getCalculatedTransformA();
+					const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+					btVector3 up = tr.getBasis().getColumn(2);
+					btVector3 axis = tr.getBasis().getColumn(0);
+					btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+					btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+					btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+					btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+					getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0));
+					axis = tr.getBasis().getColumn(1);
+					btScalar ay = p6DOF->getAngle(1);
+					btScalar az = p6DOF->getAngle(2);
+					btScalar cy = btCos(ay);
+					btScalar sy = btSin(ay);
+					btScalar cz = btCos(az);
+					btScalar sz = btSin(az);
+					btVector3 ref;
+					ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
+					ref[1] = -sz*axis[0] + cz*axis[1];
+					ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
+					tr = p6DOF->getCalculatedTransformB();
+					btVector3 normal = -tr.getBasis().getColumn(0);
+					btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+					btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+					if(minFi > maxFi)
+					{
+						getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
+					}
+					else if(minFi < maxFi)
+					{
+						getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
+					}
+					tr = p6DOF->getCalculatedTransformA();
+					btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+					btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+					getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0));
+				}
+			}
+			break;
+		case SLIDER_CONSTRAINT_TYPE:
+			{
+				btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
+				btTransform tr = pSlider->getCalculatedTransformA();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				tr = pSlider->getCalculatedTransformB();
+				if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+				if(drawLimits)
+				{
+					btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
+					btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
+					btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
+					getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
+					btVector3 normal = tr.getBasis().getColumn(0);
+					btVector3 axis = tr.getBasis().getColumn(1);
+					btScalar a_min = pSlider->getLowerAngLimit();
+					btScalar a_max = pSlider->getUpperAngLimit();
+					const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
+					getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
+				}
+			}
+			break;
+		default : 
+			break;
+	}
+	return;
+}
+
+
+
+
+
+void	btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+	if (m_ownsConstraintSolver)
+	{
+		btAlignedFree( m_constraintSolver);
+	}
+	m_ownsConstraintSolver = false;
+	m_constraintSolver = solver;
+}
+
+btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
+{
+	return m_constraintSolver;
+}
+
+
+int		btDiscreteDynamicsWorld::getNumConstraints() const
+{
+	return int(m_constraints.size());
+}
+btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
+{
+	return m_constraints[index];
+}
+const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
+{
+	return m_constraints[index];
+}
+
+
+
+void	btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
+{
+	int i;
+	//serialize all collision objects
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
+		{
+			int len = colObj->calculateSerializeBufferSize();
+			btChunk* chunk = serializer->allocate(len,1);
+			const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+			serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
+		}
+	}
+
+	for (i=0;i<m_constraints.size();i++)
+	{
+		btTypedConstraint* constraint = m_constraints[i];
+		int size = constraint->calculateSerializeBufferSize();
+		btChunk* chunk = serializer->allocate(size,1);
+		const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
+		serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
+	}
+}
+
+
+void	btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
+{
+
+	serializer->startSerialization();
+
+	serializeRigidBodies(serializer);
+
+	serializeCollisionObjects(serializer);
+
+	serializer->finishSerialization();
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h	(revision 11817)
@@ -0,0 +1,202 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
+#define BT_DISCRETE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+class btSimulationIslandManager;
+class btTypedConstraint;
+class btActionInterface;
+
+class btIDebugDraw;
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+///btDiscreteDynamicsWorld provides discrete rigid body simulation
+///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
+class btDiscreteDynamicsWorld : public btDynamicsWorld
+{
+protected:
+
+	btConstraintSolver*	m_constraintSolver;
+
+	btSimulationIslandManager*	m_islandManager;
+
+	btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+	btAlignedObjectArray<btRigidBody*> m_nonStaticRigidBodies;
+
+	btVector3	m_gravity;
+
+	//for variable timesteps
+	btScalar	m_localTime;
+	//for variable timesteps
+
+	bool	m_ownsIslandManager;
+	bool	m_ownsConstraintSolver;
+	bool	m_synchronizeAllMotionStates;
+
+	btAlignedObjectArray<btActionInterface*>	m_actions;
+	
+	int	m_profileTimings;
+
+	virtual void	predictUnconstraintMotion(btScalar timeStep);
+	
+	virtual void	integrateTransforms(btScalar timeStep);
+		
+	virtual void	addSpeculativeContacts(btScalar timeStep);
+
+	virtual void	calculateSimulationIslands();
+
+	virtual void	solveConstraints(btContactSolverInfo& solverInfo);
+	
+	void	updateActivationState(btScalar timeStep);
+
+	void	updateActions(btScalar timeStep);
+
+	void	startProfiling(btScalar timeStep);
+
+	virtual void	internalSingleStepSimulation( btScalar timeStep);
+
+
+	virtual void	saveKinematicState(btScalar timeStep);
+
+	void	serializeRigidBodies(btSerializer* serializer);
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+
+	///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
+	btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+	virtual ~btDiscreteDynamicsWorld();
+
+	///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
+	virtual int	stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+
+
+	virtual void	synchronizeMotionStates();
+
+	///this can be useful to synchronize a single rigid body -> graphics object
+	void	synchronizeSingleMotionState(btRigidBody* body);
+
+	virtual void	addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
+
+	virtual void	removeConstraint(btTypedConstraint* constraint);
+
+	virtual void	addAction(btActionInterface*);
+
+	virtual void	removeAction(btActionInterface*);
+	
+	btSimulationIslandManager*	getSimulationIslandManager()
+	{
+		return m_islandManager;
+	}
+
+	const btSimulationIslandManager*	getSimulationIslandManager() const 
+	{
+		return m_islandManager;
+	}
+
+	btCollisionWorld*	getCollisionWorld()
+	{
+		return this;
+	}
+
+	virtual void	setGravity(const btVector3& gravity);
+
+	virtual btVector3 getGravity () const;
+
+	virtual void	addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+	virtual void	addRigidBody(btRigidBody* body);
+
+	virtual void	addRigidBody(btRigidBody* body, short group, short mask);
+
+	virtual void	removeRigidBody(btRigidBody* body);
+
+	///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+	virtual void	removeCollisionObject(btCollisionObject* collisionObject);
+
+
+	void	debugDrawConstraint(btTypedConstraint* constraint);
+
+	virtual void	debugDrawWorld();
+
+	virtual void	setConstraintSolver(btConstraintSolver* solver);
+
+	virtual btConstraintSolver* getConstraintSolver();
+	
+	virtual	int		getNumConstraints() const;
+
+	virtual btTypedConstraint* getConstraint(int index)	;
+
+	virtual const btTypedConstraint* getConstraint(int index) const;
+
+	
+	virtual btDynamicsWorldType	getWorldType() const
+	{
+		return BT_DISCRETE_DYNAMICS_WORLD;
+	}
+	
+	///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
+	virtual void	clearForces();
+
+	///apply gravity, call this once per timestep
+	virtual void	applyGravity();
+
+	virtual void	setNumTasks(int numTasks)
+	{
+        (void) numTasks;
+	}
+
+	///obsolete, use updateActions instead
+	virtual void updateVehicles(btScalar timeStep)
+	{
+		updateActions(timeStep);
+	}
+
+	///obsolete, use addAction instead
+	virtual void	addVehicle(btActionInterface* vehicle);
+	///obsolete, use removeAction instead
+	virtual void	removeVehicle(btActionInterface* vehicle);
+	///obsolete, use addAction instead
+	virtual void	addCharacter(btActionInterface* character);
+	///obsolete, use removeAction instead
+	virtual void	removeCharacter(btActionInterface* character);
+
+	void	setSynchronizeAllMotionStates(bool synchronizeAll)
+	{
+		m_synchronizeAllMotionStates = synchronizeAll;
+	}
+	bool getSynchronizeAllMotionStates() const
+	{
+		return m_synchronizeAllMotionStates;
+	}
+
+	///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
+	virtual	void	serialize(btSerializer* serializer);
+
+};
+
+#endif //BT_DISCRETE_DYNAMICS_WORLD_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h	(revision 11817)
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DYNAMICS_WORLD_H
+#define BT_DYNAMICS_WORLD_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+class btTypedConstraint;
+class btActionInterface;
+class btConstraintSolver;
+class btDynamicsWorld;
+
+
+/// Type for the callback for each tick
+typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
+
+enum btDynamicsWorldType
+{
+	BT_SIMPLE_DYNAMICS_WORLD=1,
+	BT_DISCRETE_DYNAMICS_WORLD=2,
+	BT_CONTINUOUS_DYNAMICS_WORLD=3,
+	BT_SOFT_RIGID_DYNAMICS_WORLD=4
+};
+
+///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
+class btDynamicsWorld : public btCollisionWorld
+{
+
+protected:
+		btInternalTickCallback m_internalTickCallback;
+		btInternalTickCallback m_internalPreTickCallback;
+		void*	m_worldUserInfo;
+
+		btContactSolverInfo	m_solverInfo;
+
+public:
+		
+
+		btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
+		:btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0)
+		{
+		}
+
+		virtual ~btDynamicsWorld()
+		{
+		}
+		
+		///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
+		///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
+		///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
+		///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
+		virtual int		stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
+			
+		virtual void	debugDrawWorld() = 0;
+				
+		virtual void	addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false) 
+		{ 
+			(void)constraint; (void)disableCollisionsBetweenLinkedBodies;
+		}
+
+		virtual void	removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
+
+		virtual void	addAction(btActionInterface* action) = 0;
+
+		virtual void	removeAction(btActionInterface* action) = 0;
+
+		//once a rigidbody is added to the dynamics world, it will get this gravity assigned
+		//existing rigidbodies in the world get gravity assigned too, during this method
+		virtual void	setGravity(const btVector3& gravity) = 0;
+		virtual btVector3 getGravity () const = 0;
+
+		virtual void	synchronizeMotionStates() = 0;
+
+		virtual void	addRigidBody(btRigidBody* body) = 0;
+
+		virtual void	addRigidBody(btRigidBody* body, short group, short mask) = 0;
+
+		virtual void	removeRigidBody(btRigidBody* body) = 0;
+
+		virtual void	setConstraintSolver(btConstraintSolver* solver) = 0;
+
+		virtual btConstraintSolver* getConstraintSolver() = 0;
+		
+		virtual	int		getNumConstraints() const {	return 0;		}
+		
+		virtual btTypedConstraint* getConstraint(int index)		{	(void)index;		return 0;		}
+		
+		virtual const btTypedConstraint* getConstraint(int index) const	{	(void)index;	return 0;	}
+
+		virtual btDynamicsWorldType	getWorldType() const=0;
+
+		virtual void	clearForces() = 0;
+
+		/// Set the callback for when an internal tick (simulation substep) happens, optional user info
+		void setInternalTickCallback(btInternalTickCallback cb,	void* worldUserInfo=0,bool isPreTick=false) 
+		{ 
+			if (isPreTick)
+			{
+				m_internalPreTickCallback = cb;
+			} else
+			{
+				m_internalTickCallback = cb; 
+			}
+			m_worldUserInfo = worldUserInfo;
+		}
+
+		void	setWorldUserInfo(void* worldUserInfo)
+		{
+			m_worldUserInfo = worldUserInfo;
+		}
+
+		void*	getWorldUserInfo() const
+		{
+			return m_worldUserInfo;
+		}
+
+		btContactSolverInfo& getSolverInfo()
+		{
+			return m_solverInfo;
+		}
+
+
+		///obsolete, use addAction instead.
+		virtual void	addVehicle(btActionInterface* vehicle) {(void)vehicle;}
+		///obsolete, use removeAction instead
+		virtual void	removeVehicle(btActionInterface* vehicle) {(void)vehicle;}
+		///obsolete, use addAction instead.
+		virtual void	addCharacter(btActionInterface* character) {(void)character;}
+		///obsolete, use removeAction instead
+		virtual void	removeCharacter(btActionInterface* character) {(void)character;}
+
+
+};
+
+#endif //BT_DYNAMICS_WORLD_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btRigidBody.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btRigidBody.cpp	(revision 11817)
@@ -0,0 +1,402 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btRigidBody.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMotionState.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "LinearMath/btSerializer.h"
+
+//'temporarily' global variables
+btScalar	gDeactivationTime = btScalar(2.);
+bool	gDisableDeactivation = false;
+static int uniqueId = 0;
+
+
+btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+	setupRigidBody(constructionInfo);
+}
+
+btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
+{
+	btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
+	setupRigidBody(cinfo);
+}
+
+void	btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+
+	m_internalType=CO_RIGID_BODY;
+
+	m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	m_angularFactor.setValue(1,1,1);
+	m_linearFactor.setValue(1,1,1);
+	m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
+    setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
+
+	m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
+	m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
+	m_optionalMotionState = constructionInfo.m_motionState;
+	m_contactSolverType = 0;
+	m_frictionSolverType = 0;
+	m_additionalDamping = constructionInfo.m_additionalDamping;
+	m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
+	m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
+	m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
+	m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
+
+	if (m_optionalMotionState)
+	{
+		m_optionalMotionState->getWorldTransform(m_worldTransform);
+	} else
+	{
+		m_worldTransform = constructionInfo.m_startWorldTransform;
+	}
+
+	m_interpolationWorldTransform = m_worldTransform;
+	m_interpolationLinearVelocity.setValue(0,0,0);
+	m_interpolationAngularVelocity.setValue(0,0,0);
+	
+	//moved to btCollisionObject
+	m_friction = constructionInfo.m_friction;
+	m_restitution = constructionInfo.m_restitution;
+
+	setCollisionShape( constructionInfo.m_collisionShape );
+	m_debugBodyId = uniqueId++;
+	
+	setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
+	updateInertiaTensor();
+
+	m_rigidbodyFlags = 0;
+
+
+	m_deltaLinearVelocity.setZero();
+	m_deltaAngularVelocity.setZero();
+	m_invMass = m_inverseMass*m_linearFactor;
+	m_pushVelocity.setZero();
+	m_turnVelocity.setZero();
+
+	
+
+}
+
+
+void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform) 
+{
+	btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
+}
+
+void			btRigidBody::saveKinematicState(btScalar timeStep)
+{
+	//todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
+	if (timeStep != btScalar(0.))
+	{
+		//if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
+		if (getMotionState())
+			getMotionState()->getWorldTransform(m_worldTransform);
+		btVector3 linVel,angVel;
+		
+		btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity);
+		m_interpolationLinearVelocity = m_linearVelocity;
+		m_interpolationAngularVelocity = m_angularVelocity;
+		m_interpolationWorldTransform = m_worldTransform;
+		//printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
+	}
+}
+	
+void	btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+	getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax);
+}
+
+
+
+
+void btRigidBody::setGravity(const btVector3& acceleration) 
+{
+	if (m_inverseMass != btScalar(0.0))
+	{
+		m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
+	}
+	m_gravity_acceleration = acceleration;
+}
+
+
+
+
+
+
+void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
+{
+	m_linearDamping = btClamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+	m_angularDamping = btClamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+}
+
+
+
+
+///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
+void			btRigidBody::applyDamping(btScalar timeStep)
+{
+	//On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
+	//todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
+
+//#define USE_OLD_DAMPING_METHOD 1
+#ifdef USE_OLD_DAMPING_METHOD
+	m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+	m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#else
+	m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep);
+	m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep);
+#endif
+
+	if (m_additionalDamping)
+	{
+		//Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+		//Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+		if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
+			(m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
+		{
+			m_angularVelocity *= m_additionalDampingFactor;
+			m_linearVelocity *= m_additionalDampingFactor;
+		}
+	
+
+		btScalar speed = m_linearVelocity.length();
+		if (speed < m_linearDamping)
+		{
+			btScalar dampVel = btScalar(0.005);
+			if (speed > dampVel)
+			{
+				btVector3 dir = m_linearVelocity.normalized();
+				m_linearVelocity -=  dir * dampVel;
+			} else
+			{
+				m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+			}
+		}
+
+		btScalar angSpeed = m_angularVelocity.length();
+		if (angSpeed < m_angularDamping)
+		{
+			btScalar angDampVel = btScalar(0.005);
+			if (angSpeed > angDampVel)
+			{
+				btVector3 dir = m_angularVelocity.normalized();
+				m_angularVelocity -=  dir * angDampVel;
+			} else
+			{
+				m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+			}
+		}
+	}
+}
+
+
+void btRigidBody::applyGravity()
+{
+	if (isStaticOrKinematicObject())
+		return;
+	
+	applyCentralForce(m_gravity);	
+
+}
+
+void btRigidBody::proceedToTransform(const btTransform& newTrans)
+{
+	setCenterOfMassTransform( newTrans );
+}
+	
+
+void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
+{
+	if (mass == btScalar(0.))
+	{
+		m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
+		m_inverseMass = btScalar(0.);
+	} else
+	{
+		m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
+		m_inverseMass = btScalar(1.0) / mass;
+	}
+
+	//Fg = m * a
+	m_gravity = mass * m_gravity_acceleration;
+	
+	m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0),
+				   inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0),
+				   inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0));
+
+	m_invMass = m_linearFactor*m_inverseMass;
+}
+
+	
+
+void btRigidBody::updateInertiaTensor() 
+{
+	m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
+}
+
+
+void btRigidBody::integrateVelocities(btScalar step) 
+{
+	if (isStaticOrKinematicObject())
+		return;
+
+	m_linearVelocity += m_totalForce * (m_inverseMass * step);
+	m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
+
+#define MAX_ANGVEL SIMD_HALF_PI
+	/// clamp angular velocity. collision calculations will fail on higher angular velocities	
+	btScalar angvel = m_angularVelocity.length();
+	if (angvel*step > MAX_ANGVEL)
+	{
+		m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
+	}
+
+}
+
+btQuaternion btRigidBody::getOrientation() const
+{
+		btQuaternion orn;
+		m_worldTransform.getBasis().getRotation(orn);
+		return orn;
+}
+	
+	
+void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
+{
+
+	if (isStaticOrKinematicObject())
+	{
+		m_interpolationWorldTransform = m_worldTransform;
+	} else
+	{
+		m_interpolationWorldTransform = xform;
+	}
+	m_interpolationLinearVelocity = getLinearVelocity();
+	m_interpolationAngularVelocity = getAngularVelocity();
+	m_worldTransform = xform;
+	updateInertiaTensor();
+}
+
+
+bool btRigidBody::checkCollideWithOverride(btCollisionObject* co)
+{
+	btRigidBody* otherRb = btRigidBody::upcast(co);
+	if (!otherRb)
+		return true;
+
+	for (int i = 0; i < m_constraintRefs.size(); ++i)
+	{
+		btTypedConstraint* c = m_constraintRefs[i];
+		if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb)
+			return false;
+	}
+
+	return true;
+}
+
+void	btRigidBody::internalWritebackVelocity(btScalar timeStep)
+{
+    (void) timeStep;
+	if (m_inverseMass)
+	{
+		setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
+		setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
+		
+		//correct the position/orientation based on push/turn recovery
+		btTransform newTransform;
+		btTransformUtil::integrateTransform(getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
+		setWorldTransform(newTransform);
+		//m_originalBody->setCompanionId(-1);
+	}
+//	m_deltaLinearVelocity.setZero();
+//	m_deltaAngularVelocity .setZero();
+//	m_pushVelocity.setZero();
+//	m_turnVelocity.setZero();
+}
+
+
+
+void btRigidBody::addConstraintRef(btTypedConstraint* c)
+{
+	int index = m_constraintRefs.findLinearSearch(c);
+	if (index == m_constraintRefs.size())
+		m_constraintRefs.push_back(c); 
+
+	m_checkCollideWith = true;
+}
+
+void btRigidBody::removeConstraintRef(btTypedConstraint* c)
+{
+	m_constraintRefs.remove(c);
+	m_checkCollideWith = m_constraintRefs.size() > 0;
+}
+
+int	btRigidBody::calculateSerializeBufferSize()	const
+{
+	int sz = sizeof(btRigidBodyData);
+	return sz;
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+	btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer;
+
+	btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
+
+	m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
+	m_linearVelocity.serialize(rbd->m_linearVelocity);
+	m_angularVelocity.serialize(rbd->m_angularVelocity);
+	rbd->m_inverseMass = m_inverseMass;
+	m_angularFactor.serialize(rbd->m_angularFactor);
+	m_linearFactor.serialize(rbd->m_linearFactor);
+	m_gravity.serialize(rbd->m_gravity);
+	m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
+	m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
+	m_totalForce.serialize(rbd->m_totalForce);
+	m_totalTorque.serialize(rbd->m_totalTorque);
+	rbd->m_linearDamping = m_linearDamping;
+	rbd->m_angularDamping = m_angularDamping;
+	rbd->m_additionalDamping = m_additionalDamping;
+	rbd->m_additionalDampingFactor = m_additionalDampingFactor;
+	rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
+	rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
+	rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
+	rbd->m_linearSleepingThreshold=m_linearSleepingThreshold;
+	rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
+
+	return btRigidBodyDataName;
+}
+
+
+
+void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
+{
+	btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1);
+	const char* structType = serialize(chunk->m_oldPtr, serializer);
+	serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this);
+}
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btRigidBody.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btRigidBody.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btRigidBody.h	(revision 11817)
@@ -0,0 +1,691 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_RIGIDBODY_H
+#define BT_RIGIDBODY_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+class btCollisionShape;
+class btMotionState;
+class btTypedConstraint;
+
+
+extern btScalar gDeactivationTime;
+extern bool gDisableDeactivation;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btRigidBodyData	btRigidBodyDoubleData
+#define btRigidBodyDataName	"btRigidBodyDoubleData"
+#else
+#define btRigidBodyData	btRigidBodyFloatData
+#define btRigidBodyDataName	"btRigidBodyFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+enum	btRigidBodyFlags
+{
+	BT_DISABLE_WORLD_GRAVITY = 1
+};
+
+
+///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
+///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
+///There are 3 types of rigid bodies: 
+///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
+///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
+///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
+///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
+///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
+class btRigidBody  : public btCollisionObject
+{
+
+	btMatrix3x3	m_invInertiaTensorWorld;
+	btVector3		m_linearVelocity;
+	btVector3		m_angularVelocity;
+	btScalar		m_inverseMass;
+	btVector3		m_linearFactor;
+
+	btVector3		m_gravity;	
+	btVector3		m_gravity_acceleration;
+	btVector3		m_invInertiaLocal;
+	btVector3		m_totalForce;
+	btVector3		m_totalTorque;
+	
+	btScalar		m_linearDamping;
+	btScalar		m_angularDamping;
+
+	bool			m_additionalDamping;
+	btScalar		m_additionalDampingFactor;
+	btScalar		m_additionalLinearDampingThresholdSqr;
+	btScalar		m_additionalAngularDampingThresholdSqr;
+	btScalar		m_additionalAngularDampingFactor;
+
+
+	btScalar		m_linearSleepingThreshold;
+	btScalar		m_angularSleepingThreshold;
+
+	//m_optionalMotionState allows to automatic synchronize the world transform for active objects
+	btMotionState*	m_optionalMotionState;
+
+	//keep track of typed constraints referencing this rigid body
+	btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
+
+	int				m_rigidbodyFlags;
+	
+	int				m_debugBodyId;
+	
+
+protected:
+
+	ATTRIBUTE_ALIGNED64(btVector3		m_deltaLinearVelocity);
+	btVector3		m_deltaAngularVelocity;
+	btVector3		m_angularFactor;
+	btVector3		m_invMass;
+	btVector3		m_pushVelocity;
+	btVector3		m_turnVelocity;
+
+
+public:
+
+
+	///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
+	///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
+	///You can use the motion state to synchronize the world transform between physics and graphics objects. 
+	///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
+	///m_startWorldTransform is only used when you don't provide a motion state.
+	struct	btRigidBodyConstructionInfo
+	{
+		btScalar			m_mass;
+
+		///When a motionState is provided, the rigid body will initialize its world transform from the motion state
+		///In this case, m_startWorldTransform is ignored.
+		btMotionState*		m_motionState;
+		btTransform	m_startWorldTransform;
+
+		btCollisionShape*	m_collisionShape;
+		btVector3			m_localInertia;
+		btScalar			m_linearDamping;
+		btScalar			m_angularDamping;
+
+		///best simulation results when friction is non-zero
+		btScalar			m_friction;
+		///best simulation results using zero restitution.
+		btScalar			m_restitution;
+
+		btScalar			m_linearSleepingThreshold;
+		btScalar			m_angularSleepingThreshold;
+
+		//Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+		//Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+		bool				m_additionalDamping;
+		btScalar			m_additionalDampingFactor;
+		btScalar			m_additionalLinearDampingThresholdSqr;
+		btScalar			m_additionalAngularDampingThresholdSqr;
+		btScalar			m_additionalAngularDampingFactor;
+
+		btRigidBodyConstructionInfo(	btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
+		m_mass(mass),
+			m_motionState(motionState),
+			m_collisionShape(collisionShape),
+			m_localInertia(localInertia),
+			m_linearDamping(btScalar(0.)),
+			m_angularDamping(btScalar(0.)),
+			m_friction(btScalar(0.5)),
+			m_restitution(btScalar(0.)),
+			m_linearSleepingThreshold(btScalar(0.8)),
+			m_angularSleepingThreshold(btScalar(1.f)),
+			m_additionalDamping(false),
+			m_additionalDampingFactor(btScalar(0.005)),
+			m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
+			m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
+			m_additionalAngularDampingFactor(btScalar(0.01))
+		{
+			m_startWorldTransform.setIdentity();
+		}
+	};
+
+	///btRigidBody constructor using construction info
+	btRigidBody(	const btRigidBodyConstructionInfo& constructionInfo);
+
+	///btRigidBody constructor for backwards compatibility. 
+	///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
+	btRigidBody(	btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
+
+
+	virtual ~btRigidBody()
+        { 
+                //No constraints should point to this rigidbody
+		//Remove constraints from the dynamics world before you delete the related rigidbodies. 
+                btAssert(m_constraintRefs.size()==0); 
+        }
+
+protected:
+
+	///setupRigidBody is only used internally by the constructor
+	void	setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
+
+public:
+
+	void			proceedToTransform(const btTransform& newTrans); 
+	
+	///to keep collision detection and dynamics separate we don't store a rigidbody pointer
+	///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
+	static const btRigidBody*	upcast(const btCollisionObject* colObj)
+	{
+		if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
+			return (const btRigidBody*)colObj;
+		return 0;
+	}
+	static btRigidBody*	upcast(btCollisionObject* colObj)
+	{
+		if (colObj->getInternalType()&btCollisionObject::CO_RIGID_BODY)
+			return (btRigidBody*)colObj;
+		return 0;
+	}
+	
+	/// continuous collision detection needs prediction
+	void			predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ;
+	
+	void			saveKinematicState(btScalar step);
+	
+	void			applyGravity();
+	
+	void			setGravity(const btVector3& acceleration);  
+
+	const btVector3&	getGravity() const
+	{
+		return m_gravity_acceleration;
+	}
+
+	void			setDamping(btScalar lin_damping, btScalar ang_damping);
+
+	btScalar getLinearDamping() const
+	{
+		return m_linearDamping;
+	}
+
+	btScalar getAngularDamping() const
+	{
+		return m_angularDamping;
+	}
+
+	btScalar getLinearSleepingThreshold() const
+	{
+		return m_linearSleepingThreshold;
+	}
+
+	btScalar getAngularSleepingThreshold() const
+	{
+		return m_angularSleepingThreshold;
+	}
+
+	void			applyDamping(btScalar timeStep);
+
+	SIMD_FORCE_INLINE const btCollisionShape*	getCollisionShape() const {
+		return m_collisionShape;
+	}
+
+	SIMD_FORCE_INLINE btCollisionShape*	getCollisionShape() {
+			return m_collisionShape;
+	}
+	
+	void			setMassProps(btScalar mass, const btVector3& inertia);
+	
+	const btVector3& getLinearFactor() const
+	{
+		return m_linearFactor;
+	}
+	void setLinearFactor(const btVector3& linearFactor)
+	{
+		m_linearFactor = linearFactor;
+		m_invMass = m_linearFactor*m_inverseMass;
+	}
+	btScalar		getInvMass() const { return m_inverseMass; }
+	const btMatrix3x3& getInvInertiaTensorWorld() const { 
+		return m_invInertiaTensorWorld; 
+	}
+		
+	void			integrateVelocities(btScalar step);
+
+	void			setCenterOfMassTransform(const btTransform& xform);
+
+	void			applyCentralForce(const btVector3& force)
+	{
+		m_totalForce += force*m_linearFactor;
+	}
+
+	const btVector3& getTotalForce() const
+	{
+		return m_totalForce;
+	};
+
+	const btVector3& getTotalTorque() const
+	{
+		return m_totalTorque;
+	};
+    
+	const btVector3& getInvInertiaDiagLocal() const
+	{
+		return m_invInertiaLocal;
+	};
+
+	void	setInvInertiaDiagLocal(const btVector3& diagInvInertia)
+	{
+		m_invInertiaLocal = diagInvInertia;
+	}
+
+	void	setSleepingThresholds(btScalar linear,btScalar angular)
+	{
+		m_linearSleepingThreshold = linear;
+		m_angularSleepingThreshold = angular;
+	}
+
+	void	applyTorque(const btVector3& torque)
+	{
+		m_totalTorque += torque*m_angularFactor;
+	}
+	
+	void	applyForce(const btVector3& force, const btVector3& rel_pos) 
+	{
+		applyCentralForce(force);
+		applyTorque(rel_pos.cross(force*m_linearFactor));
+	}
+	
+	void applyCentralImpulse(const btVector3& impulse)
+	{
+		m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
+	}
+	
+  	void applyTorqueImpulse(const btVector3& torque)
+	{
+			m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+	}
+	
+	void applyImpulse(const btVector3& impulse, const btVector3& rel_pos) 
+	{
+		if (m_inverseMass != btScalar(0.))
+		{
+			applyCentralImpulse(impulse);
+			if (m_angularFactor)
+			{
+				applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
+			}
+		}
+	}
+
+	void clearForces() 
+	{
+		m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+		m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	}
+	
+	void updateInertiaTensor();    
+	
+	const btVector3&     getCenterOfMassPosition() const { 
+		return m_worldTransform.getOrigin(); 
+	}
+	btQuaternion getOrientation() const;
+	
+	const btTransform&  getCenterOfMassTransform() const { 
+		return m_worldTransform; 
+	}
+	const btVector3&   getLinearVelocity() const { 
+		return m_linearVelocity; 
+	}
+	const btVector3&    getAngularVelocity() const { 
+		return m_angularVelocity; 
+	}
+	
+
+	inline void setLinearVelocity(const btVector3& lin_vel)
+	{ 
+		m_linearVelocity = lin_vel; 
+	}
+
+	inline void setAngularVelocity(const btVector3& ang_vel) 
+	{ 
+		m_angularVelocity = ang_vel; 
+	}
+
+	btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
+	{
+		//we also calculate lin/ang velocity for kinematic objects
+		return m_linearVelocity + m_angularVelocity.cross(rel_pos);
+
+		//for kinematic objects, we could also use use:
+		//		return 	(m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
+	}
+
+	void translate(const btVector3& v) 
+	{
+		m_worldTransform.getOrigin() += v; 
+	}
+
+	
+	void	getAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+
+
+	
+	SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
+	{
+		btVector3 r0 = pos - getCenterOfMassPosition();
+
+		btVector3 c0 = (r0).cross(normal);
+
+		btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
+
+		return m_inverseMass + normal.dot(vec);
+
+	}
+
+	SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
+	{
+		btVector3 vec = axis * getInvInertiaTensorWorld();
+		return axis.dot(vec);
+	}
+
+	SIMD_FORCE_INLINE void	updateDeactivation(btScalar timeStep)
+	{
+		if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+			return;
+
+		if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
+			(getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
+		{
+			m_deactivationTime += timeStep;
+		} else
+		{
+			m_deactivationTime=btScalar(0.);
+			setActivationState(0);
+		}
+
+	}
+
+	SIMD_FORCE_INLINE bool	wantsSleeping()
+	{
+
+		if (getActivationState() == DISABLE_DEACTIVATION)
+			return false;
+
+		//disable deactivation
+		if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
+			return false;
+
+		if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+			return true;
+
+		if (m_deactivationTime> gDeactivationTime)
+		{
+			return true;
+		}
+		return false;
+	}
+
+
+	
+	const btBroadphaseProxy*	getBroadphaseProxy() const
+	{
+		return m_broadphaseHandle;
+	}
+	btBroadphaseProxy*	getBroadphaseProxy() 
+	{
+		return m_broadphaseHandle;
+	}
+	void	setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
+	{
+		m_broadphaseHandle = broadphaseProxy;
+	}
+
+	//btMotionState allows to automatic synchronize the world transform for active objects
+	btMotionState*	getMotionState()
+	{
+		return m_optionalMotionState;
+	}
+	const btMotionState*	getMotionState() const
+	{
+		return m_optionalMotionState;
+	}
+	void	setMotionState(btMotionState* motionState)
+	{
+		m_optionalMotionState = motionState;
+		if (m_optionalMotionState)
+			motionState->getWorldTransform(m_worldTransform);
+	}
+
+	//for experimental overriding of friction/contact solver func
+	int	m_contactSolverType;
+	int	m_frictionSolverType;
+
+	void	setAngularFactor(const btVector3& angFac)
+	{
+		m_angularFactor = angFac;
+	}
+
+	void	setAngularFactor(btScalar angFac)
+	{
+		m_angularFactor.setValue(angFac,angFac,angFac);
+	}
+	const btVector3&	getAngularFactor() const
+	{
+		return m_angularFactor;
+	}
+
+	//is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
+	bool	isInWorld() const
+	{
+		return (getBroadphaseProxy() != 0);
+	}
+
+	virtual bool checkCollideWithOverride(btCollisionObject* co);
+
+	void addConstraintRef(btTypedConstraint* c);
+	void removeConstraintRef(btTypedConstraint* c);
+
+	btTypedConstraint* getConstraintRef(int index)
+	{
+		return m_constraintRefs[index];
+	}
+
+	int getNumConstraintRefs() const
+	{
+		return m_constraintRefs.size();
+	}
+
+	void	setFlags(int flags)
+	{
+		m_rigidbodyFlags = flags;
+	}
+
+	int getFlags() const
+	{
+		return m_rigidbodyFlags;
+	}
+
+	const btVector3& getDeltaLinearVelocity() const
+	{
+		return m_deltaLinearVelocity;
+	}
+
+	const btVector3& getDeltaAngularVelocity() const
+	{
+		return m_deltaAngularVelocity;
+	}
+
+	const btVector3& getPushVelocity() const 
+	{
+		return m_pushVelocity;
+	}
+
+	const btVector3& getTurnVelocity() const 
+	{
+		return m_turnVelocity;
+	}
+
+
+	////////////////////////////////////////////////
+	///some internal methods, don't use them
+		
+	btVector3& internalGetDeltaLinearVelocity()
+	{
+		return m_deltaLinearVelocity;
+	}
+
+	btVector3& internalGetDeltaAngularVelocity()
+	{
+		return m_deltaAngularVelocity;
+	}
+
+	const btVector3& internalGetAngularFactor() const
+	{
+		return m_angularFactor;
+	}
+
+	const btVector3& internalGetInvMass() const
+	{
+		return m_invMass;
+	}
+	
+	btVector3& internalGetPushVelocity()
+	{
+		return m_pushVelocity;
+	}
+
+	btVector3& internalGetTurnVelocity()
+	{
+		return m_turnVelocity;
+	}
+
+	SIMD_FORCE_INLINE void	internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+	{
+		velocity = getLinearVelocity()+m_deltaLinearVelocity + (getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
+	}
+
+	SIMD_FORCE_INLINE void	internalGetAngularVelocity(btVector3& angVel) const
+	{
+		angVel = getAngularVelocity()+m_deltaAngularVelocity;
+	}
+
+
+	//Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+	SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+	{
+		if (m_inverseMass)
+		{
+			m_deltaLinearVelocity += linearComponent*impulseMagnitude;
+			m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+		}
+	}
+
+	SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
+	{
+		if (m_inverseMass)
+		{
+			m_pushVelocity += linearComponent*impulseMagnitude;
+			m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+		}
+	}
+	
+	void	internalWritebackVelocity()
+	{
+		if (m_inverseMass)
+		{
+			setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
+			setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
+			//m_deltaLinearVelocity.setZero();
+			//m_deltaAngularVelocity .setZero();
+			//m_originalBody->setCompanionId(-1);
+		}
+	}
+
+
+	void	internalWritebackVelocity(btScalar timeStep);
+
+	
+
+	///////////////////////////////////////////////
+
+	virtual	int	calculateSerializeBufferSize()	const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer,  class btSerializer* serializer) const;
+
+	virtual void serializeSingleObject(class btSerializer* serializer) const;
+
+};
+
+//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btRigidBodyFloatData
+{
+	btCollisionObjectFloatData	m_collisionObjectData;
+	btMatrix3x3FloatData		m_invInertiaTensorWorld;
+	btVector3FloatData		m_linearVelocity;
+	btVector3FloatData		m_angularVelocity;
+	btVector3FloatData		m_angularFactor;
+	btVector3FloatData		m_linearFactor;
+	btVector3FloatData		m_gravity;	
+	btVector3FloatData		m_gravity_acceleration;
+	btVector3FloatData		m_invInertiaLocal;
+	btVector3FloatData		m_totalForce;
+	btVector3FloatData		m_totalTorque;
+	float					m_inverseMass;
+	float					m_linearDamping;
+	float					m_angularDamping;
+	float					m_additionalDampingFactor;
+	float					m_additionalLinearDampingThresholdSqr;
+	float					m_additionalAngularDampingThresholdSqr;
+	float					m_additionalAngularDampingFactor;
+	float					m_linearSleepingThreshold;
+	float					m_angularSleepingThreshold;
+	int						m_additionalDamping;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btRigidBodyDoubleData
+{
+	btCollisionObjectDoubleData	m_collisionObjectData;
+	btMatrix3x3DoubleData		m_invInertiaTensorWorld;
+	btVector3DoubleData		m_linearVelocity;
+	btVector3DoubleData		m_angularVelocity;
+	btVector3DoubleData		m_angularFactor;
+	btVector3DoubleData		m_linearFactor;
+	btVector3DoubleData		m_gravity;	
+	btVector3DoubleData		m_gravity_acceleration;
+	btVector3DoubleData		m_invInertiaLocal;
+	btVector3DoubleData		m_totalForce;
+	btVector3DoubleData		m_totalTorque;
+	double					m_inverseMass;
+	double					m_linearDamping;
+	double					m_angularDamping;
+	double					m_additionalDampingFactor;
+	double					m_additionalLinearDampingThresholdSqr;
+	double					m_additionalAngularDampingThresholdSqr;
+	double					m_additionalAngularDampingFactor;
+	double					m_linearSleepingThreshold;
+	double					m_angularSleepingThreshold;
+	int						m_additionalDamping;
+	char	m_padding[4];
+};
+
+
+
+#endif //BT_RIGIDBODY_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp	(revision 11817)
@@ -0,0 +1,280 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleDynamicsWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C" 
+{
+	void btBulletDynamicsProbe ();
+	void btBulletDynamicsProbe () {}
+}
+
+
+
+
+btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_constraintSolver(constraintSolver),
+m_ownsConstraintSolver(false),
+m_gravity(0,0,-10)
+{
+
+}
+
+
+btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
+{
+	if (m_ownsConstraintSolver)
+		btAlignedFree( m_constraintSolver);
+}
+
+int		btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+{
+	(void)fixedTimeStep;
+	(void)maxSubSteps;
+
+
+	///apply gravity, predict motion
+	predictUnconstraintMotion(timeStep);
+
+	btDispatcherInfo&	dispatchInfo = getDispatchInfo();
+	dispatchInfo.m_timeStep = timeStep;
+	dispatchInfo.m_stepCount = 0;
+	dispatchInfo.m_debugDraw = getDebugDrawer();
+
+	///perform collision detection
+	performDiscreteCollisionDetection();
+
+	///solve contact constraints
+	int numManifolds = m_dispatcher1->getNumManifolds();
+	if (numManifolds)
+	{
+		btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
+		
+		btContactSolverInfo infoGlobal;
+		infoGlobal.m_timeStep = timeStep;
+		m_constraintSolver->prepareSolve(0,numManifolds);
+		m_constraintSolver->solveGroup(&getCollisionObjectArray()[0],getNumCollisionObjects(),manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1);
+		m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc);
+	}
+
+	///integrate transforms
+	integrateTransforms(timeStep);
+		
+	updateAabbs();
+
+	synchronizeMotionStates();
+
+	clearForces();
+
+	return 1;
+
+}
+
+void	btSimpleDynamicsWorld::clearForces()
+{
+	///@todo: iterate over awake simulation islands!
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body)
+		{
+			body->clearForces();
+		}
+	}
+}	
+
+
+void	btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
+{
+	m_gravity = gravity;
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body)
+		{
+			body->setGravity(gravity);
+		}
+	}
+}
+
+btVector3 btSimpleDynamicsWorld::getGravity () const
+{
+	return m_gravity;
+}
+
+void	btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+	btCollisionWorld::removeCollisionObject(body);
+}
+
+void	btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+	btRigidBody* body = btRigidBody::upcast(collisionObject);
+	if (body)
+		removeRigidBody(body);
+	else
+		btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+
+void	btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+	body->setGravity(m_gravity);
+
+	if (body->getCollisionShape())
+	{
+		addCollisionObject(body);
+	}
+}
+
+void	btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
+{
+	body->setGravity(m_gravity);
+
+	if (body->getCollisionShape())
+	{
+		addCollisionObject(body,group,mask);
+	}
+}
+
+
+void	btSimpleDynamicsWorld::debugDrawWorld()
+{
+
+}
+				
+void	btSimpleDynamicsWorld::addAction(btActionInterface* action)
+{
+
+}
+
+void	btSimpleDynamicsWorld::removeAction(btActionInterface* action)
+{
+
+}
+
+
+void	btSimpleDynamicsWorld::updateAabbs()
+{
+	btTransform predictedTrans;
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body)
+		{
+			if (body->isActive() && (!body->isStaticObject()))
+			{
+				btVector3 minAabb,maxAabb;
+				colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+				btBroadphaseInterface* bp = getBroadphase();
+				bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+			}
+		}
+	}
+}
+
+void	btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+	btTransform predictedTrans;
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body)
+		{
+			if (body->isActive() && (!body->isStaticObject()))
+			{
+				body->predictIntegratedTransform(timeStep, predictedTrans);
+				body->proceedToTransform( predictedTrans);
+			}
+		}
+	}
+}
+
+
+
+void	btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body)
+		{
+			if (!body->isStaticObject())
+			{
+				if (body->isActive())
+				{
+					body->applyGravity();
+					body->integrateVelocities( timeStep);
+					body->applyDamping(timeStep);
+					body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+				}
+			}
+		}
+	}
+}
+
+
+void	btSimpleDynamicsWorld::synchronizeMotionStates()
+{
+	///@todo: iterate over awake simulation islands!
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btRigidBody* body = btRigidBody::upcast(colObj);
+		if (body && body->getMotionState())
+		{
+			if (body->getActivationState() != ISLAND_SLEEPING)
+			{
+				body->getMotionState()->setWorldTransform(body->getWorldTransform());
+			}
+		}
+	}
+
+}
+
+
+void	btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+	if (m_ownsConstraintSolver)
+	{
+		btAlignedFree(m_constraintSolver);
+	}
+	m_ownsConstraintSolver = false;
+	m_constraintSolver = solver;
+}
+
+btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
+{
+	return m_constraintSolver;
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SIMPLE_DYNAMICS_WORLD_H
+#define BT_SIMPLE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+
+///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds.
+///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished).
+class btSimpleDynamicsWorld : public btDynamicsWorld
+{
+protected:
+
+	btConstraintSolver*	m_constraintSolver;
+
+	bool	m_ownsConstraintSolver;
+
+	void	predictUnconstraintMotion(btScalar timeStep);
+	
+	void	integrateTransforms(btScalar timeStep);
+		
+	btVector3	m_gravity;
+	
+public:
+
+
+
+	///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
+	btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+	virtual ~btSimpleDynamicsWorld();
+		
+	///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
+	virtual int	stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+
+	virtual void	setGravity(const btVector3& gravity);
+
+	virtual btVector3 getGravity () const;
+
+	virtual void	addRigidBody(btRigidBody* body);
+
+	virtual void	addRigidBody(btRigidBody* body, short group, short mask);
+
+	virtual void	removeRigidBody(btRigidBody* body);
+
+	virtual void	debugDrawWorld();
+				
+	virtual void	addAction(btActionInterface* action);
+
+	virtual void	removeAction(btActionInterface* action);
+
+	///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+	virtual void	removeCollisionObject(btCollisionObject* collisionObject);
+	
+	virtual void	updateAabbs();
+
+	virtual void	synchronizeMotionStates();
+
+	virtual void	setConstraintSolver(btConstraintSolver* solver);
+
+	virtual btConstraintSolver* getConstraintSolver();
+
+	virtual btDynamicsWorldType	getWorldType() const
+	{
+		return BT_SIMPLE_DYNAMICS_WORLD;
+	}
+
+	virtual void	clearForces();
+
+};
+
+#endif //BT_SIMPLE_DYNAMICS_WORLD_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp	(revision 11817)
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+
+#include "LinearMath/btVector3.h"
+#include "btRaycastVehicle.h"
+
+#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
+#include "LinearMath/btQuaternion.h"
+#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
+#include "btVehicleRaycaster.h"
+#include "btWheelInfo.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
+
+#define ROLLING_INFLUENCE_FIX
+
+
+btRigidBody& btActionInterface::getFixedBody()
+{
+	static btRigidBody s_fixed(0, 0,0);
+	s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+	return s_fixed;
+}
+
+btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis,	btVehicleRaycaster* raycaster )
+:m_vehicleRaycaster(raycaster),
+m_pitchControl(btScalar(0.))
+{
+	m_chassisBody = chassis;
+	m_indexRightAxis = 0;
+	m_indexUpAxis = 2;
+	m_indexForwardAxis = 1;
+	defaultInit(tuning);
+}
+
+
+void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
+{
+	(void)tuning;
+	m_currentVehicleSpeedKmHour = btScalar(0.);
+	m_steeringValue = btScalar(0.);
+	
+}
+
+	
+
+btRaycastVehicle::~btRaycastVehicle()
+{
+}
+
+
+//
+// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
+//
+btWheelInfo&	btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel)
+{
+
+	btWheelInfoConstructionInfo ci;
+
+	ci.m_chassisConnectionCS = connectionPointCS;
+	ci.m_wheelDirectionCS = wheelDirectionCS0;
+	ci.m_wheelAxleCS = wheelAxleCS;
+	ci.m_suspensionRestLength = suspensionRestLength;
+	ci.m_wheelRadius = wheelRadius;
+	ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
+	ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
+	ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
+	ci.m_frictionSlip = tuning.m_frictionSlip;
+	ci.m_bIsFrontWheel = isFrontWheel;
+	ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
+	ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
+
+	m_wheelInfo.push_back( btWheelInfo(ci));
+	
+	btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1];
+	
+	updateWheelTransformsWS( wheel , false );
+	updateWheelTransform(getNumWheels()-1,false);
+	return wheel;
+}
+
+
+
+
+const btTransform&	btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const
+{
+	btAssert(wheelIndex < getNumWheels());
+	const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
+	return wheel.m_worldTransform;
+
+}
+
+void	btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform)
+{
+	
+	btWheelInfo& wheel = m_wheelInfo[ wheelIndex ];
+	updateWheelTransformsWS(wheel,interpolatedTransform);
+	btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
+	const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
+	btVector3 fwd = up.cross(right);
+	fwd = fwd.normalize();
+//	up = right.cross(fwd);
+//	up.normalize();
+
+	//rotate around steering over de wheelAxleWS
+	btScalar steering = wheel.m_steering;
+	
+	btQuaternion steeringOrn(up,steering);//wheel.m_steering);
+	btMatrix3x3 steeringMat(steeringOrn);
+
+	btQuaternion rotatingOrn(right,-wheel.m_rotation);
+	btMatrix3x3 rotatingMat(rotatingOrn);
+
+	btMatrix3x3 basis2(
+		right[0],fwd[0],up[0],
+		right[1],fwd[1],up[1],
+		right[2],fwd[2],up[2]
+	);
+	
+	wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
+	wheel.m_worldTransform.setOrigin(
+		wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
+	);
+}
+
+void btRaycastVehicle::resetSuspension()
+{
+
+	int i;
+	for (i=0;i<m_wheelInfo.size();	i++)
+	{
+			btWheelInfo& wheel = m_wheelInfo[i];
+			wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+			wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+			
+			wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
+			//wheel_info.setContactFriction(btScalar(0.0));
+			wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+	}
+}
+
+void	btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform)
+{
+	wheel.m_raycastInfo.m_isInContact = false;
+
+	btTransform chassisTrans = getChassisWorldTransform();
+	if (interpolatedTransform && (getRigidBody()->getMotionState()))
+	{
+		getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
+	}
+
+	wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS );
+	wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() *  wheel.m_wheelDirectionCS ;
+	wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
+}
+
+btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
+{
+	updateWheelTransformsWS( wheel,false);
+
+	
+	btScalar depth = -1;
+	
+	btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius;
+
+	btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
+	const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
+	wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
+	const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
+
+	btScalar param = btScalar(0.);
+	
+	btVehicleRaycaster::btVehicleRaycasterResult	rayResults;
+
+	btAssert(m_vehicleRaycaster);
+
+	void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
+
+	wheel.m_raycastInfo.m_groundObject = 0;
+
+	if (object)
+	{
+		param = rayResults.m_distFraction;
+		depth = raylen * rayResults.m_distFraction;
+		wheel.m_raycastInfo.m_contactNormalWS  = rayResults.m_hitNormalInWorld;
+		wheel.m_raycastInfo.m_isInContact = true;
+		
+		wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!;
+		//wheel.m_raycastInfo.m_groundObject = object;
+
+
+		btScalar hitDistance = param*raylen;
+		wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
+		//clamp on max suspension travel
+
+		btScalar  minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+		btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
+		if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
+		{
+			wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
+		}
+		if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
+		{
+			wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
+		}
+
+		wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
+
+		btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
+
+		btVector3 chassis_velocity_at_contactPoint;
+		btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
+
+		chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
+
+		btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
+
+		if ( denominator >= btScalar(-0.1))
+		{
+			wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+			wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+		}
+		else
+		{
+			btScalar inv = btScalar(-1.) / denominator;
+			wheel.m_suspensionRelativeVelocity = projVel * inv;
+			wheel.m_clippedInvContactDotSuspension = inv;
+		}
+			
+	} else
+	{
+		//put wheel info as in rest position
+		wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
+		wheel.m_suspensionRelativeVelocity = btScalar(0.0);
+		wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
+		wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
+	}
+
+	return depth;
+}
+
+
+const btTransform& btRaycastVehicle::getChassisWorldTransform() const
+{
+	/*if (getRigidBody()->getMotionState())
+	{
+		btTransform chassisWorldTrans;
+		getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans);
+		return chassisWorldTrans;
+	}
+	*/
+
+	
+	return getRigidBody()->getCenterOfMassTransform();
+}
+
+
+void btRaycastVehicle::updateVehicle( btScalar step )
+{
+	{
+		for (int i=0;i<getNumWheels();i++)
+		{
+			updateWheelTransform(i,false);
+		}
+	}
+
+
+	m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
+	
+	const btTransform& chassisTrans = getChassisWorldTransform();
+
+	btVector3 forwardW (
+		chassisTrans.getBasis()[0][m_indexForwardAxis],
+		chassisTrans.getBasis()[1][m_indexForwardAxis],
+		chassisTrans.getBasis()[2][m_indexForwardAxis]);
+
+	if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
+	{
+		m_currentVehicleSpeedKmHour *= btScalar(-1.);
+	}
+
+	//
+	// simulate suspension
+	//
+	
+	int i=0;
+	for (i=0;i<m_wheelInfo.size();i++)
+	{
+		btScalar depth; 
+		depth = rayCast( m_wheelInfo[i]);
+	}
+
+	updateSuspension(step);
+
+	
+	for (i=0;i<m_wheelInfo.size();i++)
+	{
+		//apply suspension force
+		btWheelInfo& wheel = m_wheelInfo[i];
+		
+		btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
+		
+		if (suspensionForce > wheel.m_maxSuspensionForce)
+		{
+			suspensionForce = wheel.m_maxSuspensionForce;
+		}
+		btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
+		btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
+		
+		getRigidBody()->applyImpulse(impulse, relpos);
+	
+	}
+	
+
+	
+	updateFriction( step);
+
+	
+	for (i=0;i<m_wheelInfo.size();i++)
+	{
+		btWheelInfo& wheel = m_wheelInfo[i];
+		btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
+		btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );
+
+		if (wheel.m_raycastInfo.m_isInContact)
+		{
+			const btTransform&	chassisWorldTransform = getChassisWorldTransform();
+
+			btVector3 fwd (
+				chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
+				chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
+				chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
+
+			btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
+			fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
+
+			btScalar proj2 = fwd.dot(vel);
+			
+			wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
+			wheel.m_rotation += wheel.m_deltaRotation;
+
+		} else
+		{
+			wheel.m_rotation += wheel.m_deltaRotation;
+		}
+		
+		wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
+
+	}
+
+
+
+}
+
+
+void	btRaycastVehicle::setSteeringValue(btScalar steering,int wheel)
+{
+	btAssert(wheel>=0 && wheel < getNumWheels());
+
+	btWheelInfo& wheelInfo = getWheelInfo(wheel);
+	wheelInfo.m_steering = steering;
+}
+
+
+
+btScalar	btRaycastVehicle::getSteeringValue(int wheel) const
+{
+	return getWheelInfo(wheel).m_steering;
+}
+
+
+void	btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
+{
+	btAssert(wheel>=0 && wheel < getNumWheels());
+	btWheelInfo& wheelInfo = getWheelInfo(wheel);
+	wheelInfo.m_engineForce = force;
+}
+
+
+const btWheelInfo&	btRaycastVehicle::getWheelInfo(int index) const
+{
+	btAssert((index >= 0) && (index < 	getNumWheels()));
+	
+	return m_wheelInfo[index];
+}
+
+btWheelInfo&	btRaycastVehicle::getWheelInfo(int index) 
+{
+	btAssert((index >= 0) && (index < 	getNumWheels()));
+	
+	return m_wheelInfo[index];
+}
+
+void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex)
+{
+	btAssert((wheelIndex >= 0) && (wheelIndex < 	getNumWheels()));
+	getWheelInfo(wheelIndex).m_brake = brake;
+}
+
+
+void	btRaycastVehicle::updateSuspension(btScalar deltaTime)
+{
+	(void)deltaTime;
+
+	btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
+	
+	for (int w_it=0; w_it<getNumWheels(); w_it++)
+	{
+		btWheelInfo &wheel_info = m_wheelInfo[w_it];
+		
+		if ( wheel_info.m_raycastInfo.m_isInContact )
+		{
+			btScalar force;
+			//	Spring
+			{
+				btScalar	susp_length			= wheel_info.getSuspensionRestLength();
+				btScalar	current_length = wheel_info.m_raycastInfo.m_suspensionLength;
+
+				btScalar length_diff = (susp_length - current_length);
+
+				force = wheel_info.m_suspensionStiffness
+					* length_diff * wheel_info.m_clippedInvContactDotSuspension;
+			}
+		
+			// Damper
+			{
+				btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
+				{
+					btScalar	susp_damping;
+					if ( projected_rel_vel < btScalar(0.0) )
+					{
+						susp_damping = wheel_info.m_wheelsDampingCompression;
+					}
+					else
+					{
+						susp_damping = wheel_info.m_wheelsDampingRelaxation;
+					}
+					force -= susp_damping * projected_rel_vel;
+				}
+			}
+
+			// RESULT
+			wheel_info.m_wheelsSuspensionForce = force * chassisMass;
+			if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
+			{
+				wheel_info.m_wheelsSuspensionForce = btScalar(0.);
+			}
+		}
+		else
+		{
+			wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
+		}
+	}
+
+}
+
+
+struct btWheelContactPoint
+{
+	btRigidBody* m_body0;
+	btRigidBody* m_body1;
+	btVector3	m_frictionPositionWorld;
+	btVector3	m_frictionDirectionWorld;
+	btScalar	m_jacDiagABInv;
+	btScalar	m_maxImpulse;
+
+
+	btWheelContactPoint(btRigidBody* body0,btRigidBody* body1,const btVector3& frictionPosWorld,const btVector3& frictionDirectionWorld, btScalar maxImpulse)
+		:m_body0(body0),
+		m_body1(body1),
+		m_frictionPositionWorld(frictionPosWorld),
+		m_frictionDirectionWorld(frictionDirectionWorld),
+		m_maxImpulse(maxImpulse)
+	{
+		btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
+		btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
+		btScalar	relaxation = 1.f;
+		m_jacDiagABInv = relaxation/(denom0+denom1);
+	}
+
+
+
+};
+
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint);
+btScalar calcRollingFriction(btWheelContactPoint& contactPoint)
+{
+
+	btScalar j1=0.f;
+
+	const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
+
+	btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); 
+	btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
+	
+	btScalar maxImpulse  = contactPoint.m_maxImpulse;
+	
+	btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
+	btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
+	btVector3 vel = vel1 - vel2;
+
+	btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
+
+	// calculate j that moves us to zero relative velocity
+	j1 = -vrel * contactPoint.m_jacDiagABInv;
+	btSetMin(j1, maxImpulse);
+	btSetMax(j1, -maxImpulse);
+
+	return j1;
+}
+
+
+
+
+btScalar sideFrictionStiffness2 = btScalar(1.0);
+void	btRaycastVehicle::updateFriction(btScalar	timeStep)
+{
+
+		//calculate the impulse, so that the wheels don't move sidewards
+		int numWheel = getNumWheels();
+		if (!numWheel)
+			return;
+
+		m_forwardWS.resize(numWheel);
+		m_axle.resize(numWheel);
+		m_forwardImpulse.resize(numWheel);
+		m_sideImpulse.resize(numWheel);
+		
+		int numWheelsOnGround = 0;
+	
+
+		//collapse all those loops into one!
+		for (int i=0;i<getNumWheels();i++)
+		{
+			btWheelInfo& wheelInfo = m_wheelInfo[i];
+			class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+			if (groundObject)
+				numWheelsOnGround++;
+			m_sideImpulse[i] = btScalar(0.);
+			m_forwardImpulse[i] = btScalar(0.);
+
+		}
+	
+		{
+	
+			for (int i=0;i<getNumWheels();i++)
+			{
+
+				btWheelInfo& wheelInfo = m_wheelInfo[i];
+					
+				class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+
+				if (groundObject)
+				{
+
+					const btTransform& wheelTrans = getWheelTransformWS( i );
+
+					btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
+					m_axle[i] = btVector3(	
+						wheelBasis0[0][m_indexRightAxis],
+						wheelBasis0[1][m_indexRightAxis],
+						wheelBasis0[2][m_indexRightAxis]);
+					
+					const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
+					btScalar proj = m_axle[i].dot(surfNormalWS);
+					m_axle[i] -= surfNormalWS * proj;
+					m_axle[i] = m_axle[i].normalize();
+					
+					m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
+					m_forwardWS[i].normalize();
+
+				
+					resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
+							  *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
+							  btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
+
+					m_sideImpulse[i] *= sideFrictionStiffness2;
+						
+				}
+				
+
+			}
+		}
+
+	btScalar sideFactor = btScalar(1.);
+	btScalar fwdFactor = 0.5;
+
+	bool sliding = false;
+	{
+		for (int wheel =0;wheel <getNumWheels();wheel++)
+		{
+			btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+			class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
+
+			btScalar	rollingFriction = 0.f;
+
+			if (groundObject)
+			{
+				if (wheelInfo.m_engineForce != 0.f)
+				{
+					rollingFriction = wheelInfo.m_engineForce* timeStep;
+				} else
+				{
+					btScalar defaultRollingFrictionImpulse = 0.f;
+					btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
+					btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
+					rollingFriction = calcRollingFriction(contactPt);
+				}
+			}
+
+			//switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
+			
+
+
+
+			m_forwardImpulse[wheel] = btScalar(0.);
+			m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
+
+			if (groundObject)
+			{
+				m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
+				
+				btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
+				btScalar maximpSide = maximp;
+
+				btScalar maximpSquared = maximp * maximpSide;
+			
+
+				m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
+
+				btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
+				btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
+				
+				btScalar impulseSquared = (x*x + y*y);
+
+				if (impulseSquared > maximpSquared)
+				{
+					sliding = true;
+					
+					btScalar factor = maximp / btSqrt(impulseSquared);
+					
+					m_wheelInfo[wheel].m_skidInfo *= factor;
+				}
+			} 
+
+		}
+	}
+
+	
+
+
+		if (sliding)
+		{
+			for (int wheel = 0;wheel < getNumWheels(); wheel++)
+			{
+				if (m_sideImpulse[wheel] != btScalar(0.))
+				{
+					if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
+					{
+						m_forwardImpulse[wheel] *=	m_wheelInfo[wheel].m_skidInfo;
+						m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
+					}
+				}
+			}
+		}
+
+		// apply the impulses
+		{
+			for (int wheel = 0;wheel<getNumWheels() ; wheel++)
+			{
+				btWheelInfo& wheelInfo = m_wheelInfo[wheel];
+
+				btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS - 
+						m_chassisBody->getCenterOfMassPosition();
+
+				if (m_forwardImpulse[wheel] != btScalar(0.))
+				{
+					m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
+				}
+				if (m_sideImpulse[wheel] != btScalar(0.))
+				{
+					class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
+
+					btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - 
+						groundObject->getCenterOfMassPosition();
+
+					
+					btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
+
+#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
+					btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
+					rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence));
+#else
+					rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
+#endif
+					m_chassisBody->applyImpulse(sideImp,rel_pos);
+
+					//apply friction impulse on the ground
+					groundObject->applyImpulse(-sideImp,rel_pos2);
+				}
+			}
+		}
+
+	
+}
+
+
+
+void	btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
+{
+
+	for (int v=0;v<this->getNumWheels();v++)
+	{
+		btVector3 wheelColor(0,1,1);
+		if (getWheelInfo(v).m_raycastInfo.m_isInContact)
+		{
+			wheelColor.setValue(0,0,1);
+		} else
+		{
+			wheelColor.setValue(1,0,1);
+		}
+
+		btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
+
+		btVector3 axle = btVector3(	
+			getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
+			getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
+			getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
+
+		//debug wheels (cylinders)
+		debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
+		debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
+
+	}
+}
+
+
+void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
+{
+//	RayResultCallback& resultCallback;
+
+	btCollisionWorld::ClosestRayResultCallback rayCallback(from,to);
+
+	m_dynamicsWorld->rayTest(from, to, rayCallback);
+
+	if (rayCallback.hasHit())
+	{
+		
+		btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
+        if (body && body->hasContactResponse())
+		{
+			result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
+			result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
+			result.m_hitNormalInWorld.normalize();
+			result.m_distFraction = rayCallback.m_closestHitFraction;
+			return body;
+		}
+	}
+	return 0;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h	(revision 11817)
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_RAYCASTVEHICLE_H
+#define BT_RAYCASTVEHICLE_H
+
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "btVehicleRaycaster.h"
+class btDynamicsWorld;
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+
+class btVehicleTuning;
+
+///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
+class btRaycastVehicle : public btActionInterface
+{
+
+		btAlignedObjectArray<btVector3>	m_forwardWS;
+		btAlignedObjectArray<btVector3>	m_axle;
+		btAlignedObjectArray<btScalar>	m_forwardImpulse;
+		btAlignedObjectArray<btScalar>	m_sideImpulse;
+	
+		///backwards compatibility
+		int	m_userConstraintType;
+		int	m_userConstraintId;
+
+public:
+	class btVehicleTuning
+		{
+			public:
+
+			btVehicleTuning()
+				:m_suspensionStiffness(btScalar(5.88)),
+				m_suspensionCompression(btScalar(0.83)),
+				m_suspensionDamping(btScalar(0.88)),
+				m_maxSuspensionTravelCm(btScalar(500.)),
+				m_frictionSlip(btScalar(10.5)),
+				m_maxSuspensionForce(btScalar(6000.))
+			{
+			}
+			btScalar	m_suspensionStiffness;
+			btScalar	m_suspensionCompression;
+			btScalar	m_suspensionDamping;
+			btScalar	m_maxSuspensionTravelCm;
+			btScalar	m_frictionSlip;
+			btScalar	m_maxSuspensionForce;
+
+		};
+private:
+
+	btScalar	m_tau;
+	btScalar	m_damping;
+	btVehicleRaycaster*	m_vehicleRaycaster;
+	btScalar		m_pitchControl;
+	btScalar	m_steeringValue; 
+	btScalar m_currentVehicleSpeedKmHour;
+
+	btRigidBody* m_chassisBody;
+
+	int m_indexRightAxis;
+	int m_indexUpAxis;
+	int	m_indexForwardAxis;
+
+	void defaultInit(const btVehicleTuning& tuning);
+
+public:
+
+	//constructor to create a car from an existing rigidbody
+	btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis,	btVehicleRaycaster* raycaster );
+
+	virtual ~btRaycastVehicle() ;
+
+
+	///btActionInterface interface
+	virtual void updateAction( btCollisionWorld* collisionWorld, btScalar step)
+	{
+        (void) collisionWorld;
+		updateVehicle(step);
+	}
+	
+
+	///btActionInterface interface
+	void	debugDraw(btIDebugDraw* debugDrawer);
+			
+	const btTransform& getChassisWorldTransform() const;
+	
+	btScalar rayCast(btWheelInfo& wheel);
+
+	virtual void updateVehicle(btScalar step);
+	
+	
+	void resetSuspension();
+
+	btScalar	getSteeringValue(int wheel) const;
+
+	void	setSteeringValue(btScalar steering,int wheel);
+
+
+	void	applyEngineForce(btScalar force, int wheel);
+
+	const btTransform&	getWheelTransformWS( int wheelIndex ) const;
+
+	void	updateWheelTransform( int wheelIndex, bool interpolatedTransform = true );
+	
+//	void	setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
+
+	btWheelInfo&	addWheel( const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS,btScalar suspensionRestLength,btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel);
+
+	inline int		getNumWheels() const {
+		return int (m_wheelInfo.size());
+	}
+	
+	btAlignedObjectArray<btWheelInfo>	m_wheelInfo;
+
+
+	const btWheelInfo&	getWheelInfo(int index) const;
+
+	btWheelInfo&	getWheelInfo(int index);
+
+	void	updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform = true);
+
+	
+	void setBrake(btScalar brake,int wheelIndex);
+
+	void	setPitchControl(btScalar pitch)
+	{
+		m_pitchControl = pitch;
+	}
+	
+	void	updateSuspension(btScalar deltaTime);
+
+	virtual void	updateFriction(btScalar	timeStep);
+
+
+
+	inline btRigidBody* getRigidBody()
+	{
+		return m_chassisBody;
+	}
+
+	const btRigidBody* getRigidBody() const
+	{
+		return m_chassisBody;
+	}
+
+	inline int	getRightAxis() const
+	{
+		return m_indexRightAxis;
+	}
+	inline int getUpAxis() const
+	{
+		return m_indexUpAxis;
+	}
+
+	inline int getForwardAxis() const
+	{
+		return m_indexForwardAxis;
+	}
+
+	
+	///Worldspace forward vector
+	btVector3 getForwardVector() const
+	{
+		const btTransform& chassisTrans = getChassisWorldTransform(); 
+
+		btVector3 forwardW ( 
+			  chassisTrans.getBasis()[0][m_indexForwardAxis], 
+			  chassisTrans.getBasis()[1][m_indexForwardAxis], 
+			  chassisTrans.getBasis()[2][m_indexForwardAxis]); 
+
+		return forwardW;
+	}
+
+	///Velocity of vehicle (positive if velocity vector has same direction as foward vector)
+	btScalar	getCurrentSpeedKmHour() const
+	{
+		return m_currentVehicleSpeedKmHour;
+	}
+
+	virtual void	setCoordinateSystem(int rightIndex,int upIndex,int forwardIndex)
+	{
+		m_indexRightAxis = rightIndex;
+		m_indexUpAxis = upIndex;
+		m_indexForwardAxis = forwardIndex;
+	}
+
+
+	///backwards compatibility
+	int getUserConstraintType() const
+	{
+		return m_userConstraintType ;
+	}
+
+	void	setUserConstraintType(int userConstraintType)
+	{
+		m_userConstraintType = userConstraintType;
+	};
+
+	void	setUserConstraintId(int uid)
+	{
+		m_userConstraintId = uid;
+	}
+
+	int getUserConstraintId() const
+	{
+		return m_userConstraintId;
+	}
+
+};
+
+class btDefaultVehicleRaycaster : public btVehicleRaycaster
+{
+	btDynamicsWorld*	m_dynamicsWorld;
+public:
+	btDefaultVehicleRaycaster(btDynamicsWorld* world)
+		:m_dynamicsWorld(world)
+	{
+	}
+
+	virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result);
+
+};
+
+
+#endif //BT_RAYCASTVEHICLE_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h	(revision 11817)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_VEHICLE_RAYCASTER_H
+#define BT_VEHICLE_RAYCASTER_H
+
+#include "LinearMath/btVector3.h"
+
+/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting
+struct btVehicleRaycaster
+{
+virtual ~btVehicleRaycaster()
+{
+}
+	struct btVehicleRaycasterResult
+	{
+		btVehicleRaycasterResult() :m_distFraction(btScalar(-1.)){};
+		btVector3	m_hitPointInWorld;
+		btVector3	m_hitNormalInWorld;
+		btScalar	m_distFraction;
+	};
+
+	virtual void* castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) = 0;
+
+};
+
+#endif //BT_VEHICLE_RAYCASTER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#include "btWheelInfo.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
+
+
+btScalar btWheelInfo::getSuspensionRestLength() const
+{
+
+	return m_suspensionRestLength1;
+
+}
+
+void	btWheelInfo::updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo)
+{
+	(void)raycastInfo;
+
+	
+	if (m_raycastInfo.m_isInContact)
+
+	{
+		btScalar	project= m_raycastInfo.m_contactNormalWS.dot( m_raycastInfo.m_wheelDirectionWS );
+		btVector3	 chassis_velocity_at_contactPoint;
+		btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
+		chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint( relpos );
+		btScalar projVel = m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
+		if ( project >= btScalar(-0.1))
+		{
+			m_suspensionRelativeVelocity = btScalar(0.0);
+			m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
+		}
+		else
+		{
+			btScalar inv = btScalar(-1.) / project;
+			m_suspensionRelativeVelocity = projVel * inv;
+			m_clippedInvContactDotSuspension = inv;
+		}
+		
+	}
+
+	else	// Not in contact : position wheel in a nice (rest length) position
+	{
+		m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
+		m_suspensionRelativeVelocity = btScalar(0.0);
+		m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
+		m_clippedInvContactDotSuspension = btScalar(1.0);
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btWheelInfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btWheelInfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletDynamics/Vehicle/btWheelInfo.h	(revision 11817)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies.
+ * Erwin Coumans makes no representations about the suitability 
+ * of this software for any purpose.  
+ * It is provided "as is" without express or implied warranty.
+*/
+#ifndef BT_WHEEL_INFO_H
+#define BT_WHEEL_INFO_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+
+class btRigidBody;
+
+struct btWheelInfoConstructionInfo
+{
+	btVector3	m_chassisConnectionCS;
+	btVector3	m_wheelDirectionCS;
+	btVector3	m_wheelAxleCS;
+	btScalar	m_suspensionRestLength;
+	btScalar	m_maxSuspensionTravelCm;
+	btScalar	m_wheelRadius;
+	
+	btScalar		m_suspensionStiffness;
+	btScalar		m_wheelsDampingCompression;
+	btScalar		m_wheelsDampingRelaxation;
+	btScalar		m_frictionSlip;
+	btScalar		m_maxSuspensionForce;
+	bool m_bIsFrontWheel;
+	
+};
+
+/// btWheelInfo contains information per wheel about friction and suspension.
+struct btWheelInfo
+{
+	struct RaycastInfo
+	{
+		//set by raycaster
+		btVector3	m_contactNormalWS;//contactnormal
+		btVector3	m_contactPointWS;//raycast hitpoint
+		btScalar	m_suspensionLength;
+		btVector3	m_hardPointWS;//raycast starting point
+		btVector3	m_wheelDirectionWS; //direction in worldspace
+		btVector3	m_wheelAxleWS; // axle in worldspace
+		bool		m_isInContact;
+		void*		m_groundObject; //could be general void* ptr
+	};
+
+	RaycastInfo	m_raycastInfo;
+
+	btTransform	m_worldTransform;
+	
+	btVector3	m_chassisConnectionPointCS; //const
+	btVector3	m_wheelDirectionCS;//const
+	btVector3	m_wheelAxleCS; // const or modified by steering
+	btScalar	m_suspensionRestLength1;//const
+	btScalar	m_maxSuspensionTravelCm;
+	btScalar getSuspensionRestLength() const;
+	btScalar	m_wheelsRadius;//const
+	btScalar	m_suspensionStiffness;//const
+	btScalar	m_wheelsDampingCompression;//const
+	btScalar	m_wheelsDampingRelaxation;//const
+	btScalar	m_frictionSlip;
+	btScalar	m_steering;
+	btScalar	m_rotation;
+	btScalar	m_deltaRotation;
+	btScalar	m_rollInfluence;
+	btScalar	m_maxSuspensionForce;
+
+	btScalar	m_engineForce;
+
+	btScalar	m_brake;
+	
+	bool m_bIsFrontWheel;
+	
+	void*		m_clientInfo;//can be used to store pointer to sync transforms...
+
+	btWheelInfo(btWheelInfoConstructionInfo& ci)
+
+	{
+
+		m_suspensionRestLength1 = ci.m_suspensionRestLength;
+		m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm;
+
+		m_wheelsRadius = ci.m_wheelRadius;
+		m_suspensionStiffness = ci.m_suspensionStiffness;
+		m_wheelsDampingCompression = ci.m_wheelsDampingCompression;
+		m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation;
+		m_chassisConnectionPointCS = ci.m_chassisConnectionCS;
+		m_wheelDirectionCS = ci.m_wheelDirectionCS;
+		m_wheelAxleCS = ci.m_wheelAxleCS;
+		m_frictionSlip = ci.m_frictionSlip;
+		m_steering = btScalar(0.);
+		m_engineForce = btScalar(0.);
+		m_rotation = btScalar(0.);
+		m_deltaRotation = btScalar(0.);
+		m_brake = btScalar(0.);
+		m_rollInfluence = btScalar(0.1);
+		m_bIsFrontWheel = ci.m_bIsFrontWheel;
+		m_maxSuspensionForce = ci.m_maxSuspensionForce;
+
+	}
+
+	void	updateWheel(const btRigidBody& chassis,RaycastInfo& raycastInfo);
+
+	btScalar	m_clippedInvContactDotSuspension;
+	btScalar	m_suspensionRelativeVelocity;
+	//calculated by suspension
+	btScalar	m_wheelsSuspensionForce;
+	btScalar	m_skidInfo;
+
+};
+
+#endif //BT_WHEEL_INFO_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/BulletLicense.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/BulletLicense.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/BulletLicense.txt	(revision 11817)
@@ -0,0 +1,18 @@
+/*
+Copyright (c) 2003-2010 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+Free for commercial use, please report projects in the forum at http://www.bulletphysics.org
+
+In case you want to display a Bullet logo in your software: you can download the Bullet logo in various vector formats and high resolution at the download section in http://bullet.googlecode.com
Index: /code/branches/RacingBots_FS18/src/external/bullet/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,38 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(BULLET_FILES
+  btBulletCollisionCommon.h
+  btBulletDynamicsCommon.h
+  Bullet-C-Api.h
+)
+ADD_SUBDIRECTORY(BulletCollision)
+ADD_SUBDIRECTORY(BulletDynamics)
+ADD_SUBDIRECTORY(LinearMath)
+
+ORXONOX_ADD_LIBRARY(bullet_orxonox
+  ORXONOX_EXTERNAL
+  NO_DLL_INTERFACE
+  VERSION
+    2.78
+  EXCLUDE_FROM_BUILD_UNITS
+    BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+  SOURCE_FILES
+    ${BULLET_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/external/bullet/ChangeLog
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/ChangeLog	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/ChangeLog	(revision 11817)
@@ -0,0 +1,779 @@
+Bullet Continuous Collision Detection and Physics Library
+Primary author and maintainer: Erwin Coumans
+
+This ChangeLog is incomplete, for an up-to-date list of all fixed issues see http://bullet.googlecode.com
+using http://tinyurl.com/yabmjjj
+
+2011 April 8
+	- Bullet 2.78 release 2383
+	- Added FractureDemo
+	- Added Separatinx Axis Test and Polyhedral Clipping support (See InternalEdgeDemo)
+	- Added speculative contacts as CCD response method (See CcdPhysicsDemo)
+	- OpenCL and DirectCompute cloth as basic support for capsule collision
+
+2010 September 7
+	- autotools now uses CamelCase naming for libraryes just like cmake:
+	libbulletdynamics -> libBulletDynamics, libbulletmath -> libLinearMath
+
+2010 July 21
+	- Preparing for Bullet 2.77 release, around revision r2135
+	- Added an OpenCL particle demo, running on NVidia, AMD and MiniCL
+	Thanks to NVidia for the original particle demo from their OpenCL SDK
+	- Added GPU deformable object solvers for OpenCL and DirectCompute, and a DirectX 11 cloth demo
+	Thanks to AMD
+	- Create a separate library for MiniCL, 
+	MiniCL is a rudimentary OpenCL wrapper that allows to compile OpenCL kernels for multi-core CPU, using Win32 Threads or Posix
+	- Moved vectormath into Bullet/src, and added a SSE implementation
+	- Added a btParallelConstraintSolver, mainly for PlayStation 3 Cell SPUs (although it runs fine on CPU too)
+
+2010 March 6
+	- Dynamica Maya plugin (and COLLADA support) is moved to http://dynamica.googlecode.com
+
+2010 February
+	- Bullet 2.76 release, revision 2010
+	- support for the .bullet binary file format
+	- btInternalEdgeUtility to adjust unwanted collisions against internal triangle edges
+	- Improved Maya Dynamica plugin with better constraint authoring and .bullet file export
+
+
+2009 September 17
+	- Minor update to Bullet 2.75 release, revision 1776
+	- Support for btConvex2dShape, check out Bullet/Demos/Box2dDemo
+	- Fixes in build systems
+	- Minor fix in btGjkPairDetector
+	- Initialize world transform for btCollisionShape in constructor
+
+
+2009 September 6
+	- Bullet 2.75 release
+	- Added SPH fluid simulation in Extras, not integrated with rigid body / soft body yet
+	Thanks to Rama Hoetzlein to make this contribution available under the ZLib license
+	- add special capsule-capsule collider code in btConvexConvexCollisionAlgorithm, to speed up capsule-ragdolls
+	- soft body improvement: faster building of bending constraints
+	- soft body improvement: allow to disable/enable cluster self-collision
+	- soft body fix: 'exploding' soft bodies when using cluster collision
+	- fix some degenerate cases in continuous convex cast, could impact ray cast/convex cast
+	Thanks to Jacob Langford for the report and reproduction cases, see http://code.google.com/p/bullet/issues/detail?id=250&can=1&start=200
+	- re-enabled split impulse
+	- added btHinge2Constraint, btUniversalConstraint, btGeneric6DofSpringConstraint
+	- demonstrate 2D physics with 2D/3D object interaction
+	
+
+2008 December 2
+	- Fix contact refresh issues with btCompoundShape, introduced with btDbvt acceleration structure in btCompoundCollisionAlgorithm
+	- Made btSequentialImpulseConstraintSolver 100% compatible with ODE quickstep
+	constraints can use 'solveConstraint' method or 'getInfo/getInfo2'
+
+2008 November 30
+	- Add highly optimized SIMD branchless PGS/SI solver innerloop 
+
+2008 November 12
+	- Add compound shape export to BulletColladaConverter
+	Thanks to JamesH for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=12&t=2840
+	- Fix compiler build for Visual Studio 6
+	Thanks to JoF for the report: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2841
+
+2008 November 11
+	- Add CProfileManager::dumpAll() to dump performance statistics to console using printf.
+	- Add support for interaction between btSoftBody and btCollisionObject/btGhostObject
+
+2008 November 8
+	- Fix PosixThreadSupport
+	- Add improved btHeightfieldTerrainShape support and new Demos/TerrainDemo
+	Thanks to tomva, http://code.google.com/p/bullet/issues/detail?id=63&can=1
+	- Moved kinematic character controller from Demos/CharacterDemo into src/BulletDynamics/Character/btKinematicCharacterController.cpp
+
+2008 November 6
+	- reduced default memory pool allocation from 40Mb to 3Mb. This should be more suitable for all platforms, including iPhone
+	- improved CUDA broadphase
+	- IBM Cell SDK 3.x support, fix ibmsdk Makefiles
+	- improved CMake support with 'install' and 'framework option
+	
+2008 November 4
+	- add btAxisSweep::resetPool to avoid non-determinism due to shuffled linked list
+	Thanks to Ole for the contribution, 
+
+2008 October 30
+	- disabled btTriangleMesh duplicate search by default, it is extremely slow
+	- added Extras/IFF binary chunk serialization library as preparation for in-game native platform serialization (planned COLLADA DOM -> IFF converter)
+
+2008 October 20
+	- added SCE Physics Effects box-box collision detection for SPU/BulletMultiThreaded version
+	See Bullet/src/BulletMultiThreaded/SpuNarrowPhaseCollisionTask/boxBoxDistance.cpp
+	Thanks to Sony Computer Entertainment Japan, SCEI for the contribution
+
+2008 October 17
+	- Added btGhostObject support, this helps character controller, explosions, triggers and other local spatial queries
+
+2008 October 10
+	- Moved aabb to btBroadphaseProxy, improves rayTest dramatically. Further raytest improvements using the broadphase acceleration structures are planned
+	- Moved BulletMultiThreaded from Extras to /src/BulletMultiThreaded for better integration
+
+
+2008 October 3
+	- Add support for autoconf automake
+	./autogen.sh and ./configure will create both Makefile and Jamfile. CMake and autogenerated Visual Studio projectfiles remain supported too.
+	- Improved ColladaConverter: plane shape export, and callback for shape construction to allow deletion of memory
+	
+2008 Sept 30
+	- Improved Soft Body support, fixed issues related to soft body colliding against concave triangle meshes
+	- Shared more code between regular version and SPU/BulletMultiThreaded, in particular GJK/EPA
+
+2008 Sept 28
+	- Fixed rotation issues in Dynamic Maya Plugin
+
+2008 Sept 11
+	- Enable CCD motion clamping for btDiscreteDynamicsWorld, to avoid tunneling. A more advanced solution will be implemented in btContinuousDynamicsWorld.
+
+2008 Sept 7
+	- Add btScaledBvhTriangleMeshShape, to allow re-use of btBvhTriangleMeshShape of different sizes, without copying of the BVH data.
+
+2008 Sept 5
+	- Enabled Demos/ForkLiftDemo
+	Thanks Roman Ponomarev.
+
+2008 Sept 4
+	- Added btCudaBroadphase in Extras/CUDA: some research into accelerating Bullet using CUDA.
+	Thanks to the particle demo from the NVidia CUDA SDK.
+	
+2008 Sept 3
+	- Several bug fixes and contributions related to inertia tensor, memory leaks etc.
+	Thanks to Ole K.
+
+2008 Sept 1
+	- Updated CDTestFramework, with latest version of OPCODE Array SAP. See Extras/CDTestFramework
+	Thanks to Pierre Terdiman for the update
+
+2008 August 25
+	- Walt Disney Studios contributes their in-house Maya Plugin for simulating Bullet physics, with options for other engines such as PhysBam or PhysX.
+	Thanks to Nicola Candussi and Arthur Shek
+	
+2008 August 14
+	- Improved performance for btDbvtBroadphase, based on dual dynamic AABB trees (one for static, one for dynamic objects, where objects can move from one to the other tree)
+	Thanks to Nathanael Presson again, for all his work.
+	
+2008 July 31
+	- Added Havok .hkx to COLLADA Physics .dae converter patch+information
+	- Fix btSubsimplexConvexCast
+	Thanks to Nacho, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2422)
+	- Fix in rendering, GL_STENCIL
+	- btTriangleIndexVertexArray indices should be unsigned int/unsigned short int,
+	- Made InternalProcessAllTriangles virtual, thanks to
+	Both thank to Fullmetalcoder, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2401
+	- clamp impulse for btPoint2PointConstraint
+	Thanks to Martijn Reuvers, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2418
+	- Free memory of bvh, pass in scaling factor (optional)
+	Thanks to Roy Eltham, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=2375
+
+2008 July 27
+
+btDbvtBroadphase:
+	- Fixed a performance issues reported by 'reltham'
+	- Added btDbvtBroadphase::optimize() for people who want good performances right
+away or don't do dynamics.
+	- fixed compilation issues when DBVT_BP_PROFILE was set.
+btSoftBody:
+	- Fixed singular matrix issues related to polar decomposition (flat meshes).
+DemoApplication:
+	- Shadows (enable/disable through 'g' or DemoApplication::setShadows(bool)).
+	- Texture can be enable/disable through 'u'
+CDFramework:
+	- fixed compilation issues.
+	All thanks to Nathanael Presson
+
+2008 July 10
+	- Added btMultimaterialTriangleMeshShape and MultiMaterialDemo
+	Thanks to Alex Silverman for the contribution
+
+2008 June 30
+	- Added initial support for kinematic character controller
+	Thanks to John McCutchan
+
+2008 April 14
+	- Added ray cast support for Soft Bodies
+	Thanks to Nathanael Presson for the contribution
+	
+2008 April 9
+	- Cleanup of Stan Melax ConvexHull, removed Extras/ConvexHull, moved sources into LinearMath/BulletCollision
+
+2008 April 4
+	- Added btSliderConstraint and demo
+	Thanks Roman Ponomarev
+	
+2008 April 3
+	- Fixed btMinkowskiSumShape, and added hitpoint to btSubsimplexConvexCast
+
+2008 April 2
+	- Added Extras/CdTestFrameWork
+	Thanks Pierre Terdiman
+
+2008 April 1
+	- Added posix thread (pthread) support
+	Thanks Enrico
+
+2008 March 30
+	- Added Soft Body, cloth, rope and deformable volumes, including demos and interaction
+	Thanks Nathanael Presson for this great contribution
+	
+	2008 March 17
+	- Improved BulletColladaConverter
+	Thanks John McCutchan
+
+2008 March 15
+	- btMultiSapBroadphase in a working state. Needs more optimizations to be fully useable.
+	- Allow btOptimizedBvh to be used for arbitrary objects, not just triangles
+	- added quicksort to btAlignedObjectArray
+	- removed btTypedUserInfo, added btHashMap
+
+2008 March 30
+	- Moved quickstep solver and boxbox into Bullet/src folder
+	Thanks Russell L. Smith for permission to redistribute Open Dynamics Engine quickstep and box-box under the ZLib license	
+
+2008 Feb 27
+	- Added initial version for Character Control Demo
+	- Applied fixes to IBM Cell SDK 3.0 build makefiles
+	Thanks Jochen and mojo for reporting/providing patch: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1922
+
+2008 Feb 8
+	- Bugfixes in ConvexCast support against the world.
+	Thanks to Isgmasa for reporting/providing fix: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1823
+
+2008 Feb 6
+	- Added btCapsuleShapeX and btCapsuleShapeZ for capsules around X and Z axis (default capsule is around Y)
+	
+2008 Feb 3
+	- Added btTypedUserInfo, useful for serialization
+
+2008 Jan 31
+	- Add support for 16 and 32-bit indices for SPU / BulletMultiThreaded version.
+
+2008 Jan 29
+	- Added COLLADA Physics export/serialization/snapshot from any Bullet btDynamicsWorld. Saving the physics world into a text .xml file is useful for debugging etc.
+
+2008 Jan 23
+	- Added Stan Melax Convex Hull utility library in Extras/ConvexHull. This is useful to render non-polyhedral convex objects, and to simplify convex polyhedra.
+	
+2008 Jan 14
+	- Add support for batch raycasting on SPU / BulletMultiThreaded
+	
+2007 Dec 16
+	- Added btRigidBodyConstructionInfo, to make it easier to set individual setting (and leave other untouched) during rigid body construction.
+	Thanks Vangelis Kokkevis for pointing this out.
+	- Fixed memoryleak in the ConstraintDemo and Raytracer demo.
+	- Fixed issue with clearing forces/gravity at the end of the stepSimulation, instead of during internalSingleStepSimulation.
+	Thanks chunky for pointing this out: http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1780
+	- Disabled additional damping in rigid body by default, but enable it in most demos. Set btRigidBodyConstructionInfo m_additionalDamping to true to enable this.
+	- Removed obsolete QUICKPROF BEGIN/END_PROFILE, and enabled BT_PROFILE. Profiling is enabled by default (see Bullet/Demos/OpenGL/DemoApplication.cpp how to use this).
+	User can switch off profiling by enabling define BT_NO_PROFILE in Bullet/src/btQuickprof.h.
+
+2007 Dec 14
+	- Added Hello World and BulletMultiThreaded demos
+	- Add portable version of BulletMultiThreaded, through SequentialThreadSupport (non-parallel but sharing the same code-path)
+	- Add Cmake support for AllBulletDemos
+	
+
+2007 Dec 11
+	- Moved the 'btRigidBody::clearForce' to the end of the stepSimulation, instead of in each substep.
+	See discussion http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1601
+	- Added btConvexPlaneCollisionAlgorithm, makes planes perform better, and prevents tunneling
+	Thanks Andy O'Neil for reporting the performance/functionality issue
+	- Fixes for IBM Cell SDK 3.0
+	Thanks to Jochen Roth for the patch.
+
+2007 Dec 10
+	- Fixes in btHeightfieldTerrainShape
+	Thanks to Jay Lee for the patch.
+
+2007	Dec 9
+	- Only update aabb of active objects
+	Thanks Peter Tchernev for reporting (http://bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1764 )
+	- Added workaround to compile libxml under Visual Studio 2008 Beta 2
+	- Make glui compile under MSVC 9.0 beta (vsnprintf is already defined)
+
+2007 Dec 6
+	- Added DynamicControlDemo, showing dynamic control through constraint motors
+		Thanks to Eddy Boxerman
+	- Add support for generic concave shapes for convex cast.
+	- Added convex cast query to collision world.
+	- Added workaround for OpenGL bug in Mac OS X 10.5.0 (Leopard)
+	- Added concave raycast demo
+		All above thanks to John McCutchan (JMC)
+	- Fixed issues that prevent Linux version to compile. 
+	Thanks to Enrico for reporting and patch, see
+	- Fixed misleading name 'numTriangleIndices' into 'numTriangles'
+	Thanks Sean Tasker for reporting:
+
+2007 Nov 28:
+	- Added raycast against trianglemesh. Will be extended to object cast soon.
+	Thanks John McCutchan (JMC)
+	- make getNumPoints const correct, add const getPoints(). 
+	Thanks Dirk Gregorius
+	- Bugfix: allow btCollisionObjects (non-btRigidBody) to interact properly with btRigidBody for cache-friendly btSequentialImpulseConstraintSolver.
+	Thanks Andy O'Neil for pointing this out.
+	- Bugfix: don't fail if spheres have identical center, use arbitrary separating normal (1,0,0)
+	Thanks Sean Tasker for reporting! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1681
+
+
+2007, November 20
+	- Added hierarchical profiling
+	- Fixed memory leak in btMultiSapBroadphase,
+	- Fixed hash function (typo, should use 2 proxies)
+	Thanks to Stephen (shatcher) for reporting and fixes! http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1696
+
+2007 Nov 11
+	- Fixed parallel solver (BulletMultiThreaded) friction issue
+	- Terminate Win32 Threads when closing the CcdPhysicsDemo (when USE_PARALLEL_SOLVER/USE_PARALLEL_DISPATCHER is defined)
+
+2007 Nov 6
+	- Added support for 16-bit indices for triangle meshes
+	- Added support for multiple mesh parts using btBvhTriangleMeshShape.
+	Thanks to Tim Johansson
+	
+2007 Oct 22
+	- All memory allocations go through btAlignedAlloc/btAlignedFree. User can override this to verify memory leaks
+	- added a few more demos to AllBulletDemos
+	- fix for one of the constructors of btHingeConstraint
+	Thanks Marcus Hennix
+	
+2007 Oct 20
+	- included glui, a GLUT/OpenGL based toolkit for some graphical user elements
+	Removed dynamic_cast from glui, to allow linkage without rtti
+	- added Box2D framework using glui, allowing all demos to run within one executable
+	Thanks Erin Catto for the FrameWork skeleton (http://www.box2d.org)
+
+2007 Ocy 17
+	- Allow user to pass in their own memory (stack and pool) allocators, through collisionConfiguration. See demos how to use this
+
+2007 Oct 14
+	- Included working version of Cell SPU parallel optimized version for Libspe2 SPU task scheduler.
+	This version compiles and runs on Playstation 3 Linux and IBM CellBlade, see BulletSpuOptimized.pdf for build instructions
+	(Official Playstation 3 developers can request a SPURS version through Sony PS3 Devnet.)
+	Thanks to IBM 'Extreme Blue' project for the contribution
+	http://www-913.ibm.com/employment/us/extremeblue/ 
+	Thanks Minh Cuong Tran, Benjamin Hoeferlin, Frederick Roth and Martina Huellmann
+	for various contributions to get this initial Libspe2 parallel version up and running.
+
+2007 Oct 13
+	- made 'btCollisionShape::calculateLocalInertia' const
+	Thanks to cgripeos, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1514
+	- applied a large patch to remove warnings
+	Thanks to Enrico, see http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1568
+	- removed SSE includes, added #incude <string.h> for memset in Extras/quickstep, thanks Eternl Knight
+
+2007 Oct 11
+	- added Hashed Overlapping Pair Cache, recommended by Pierre Terdiman. It works like a charm, thanks Pierre and Erin Catto (code from Box2D)
+	- modified some margins inside btBoxShape, btCylinderShape and btSphereShape
+	- added cone debug rendering (for cones with x, y and z up-axis)
+	- added improvements for optional Extra/quickstep, thanks to Remotion
+	- some performance improvements for Bullet constraint solver
+
+2007 Sept 28
+	- upgraded GIMPACT to version 0.3
+	Thanks to Francisco Leon
+
+2007 Sept 27
+	- added contribution from IBM Extreme Blue project for Libspe2 support. This allow to execute BulletMultiThreaded on Cell SPU under PS3 Linux and Cell Blade. See http://www-913.ibm.com/employment/us/extremeblue
+	Thanks to Minh Cuong Tran, Frederick Roth, Martina Heullmann and Benjamin Hoeferlin.
+
+2007 Sept 13
+	- Improved btGenericD6Constraint. It can be used to create ragdolls (similar to the new btConeTwistConstraint). See GenericJointDemo
+	- Added support for Bullet constraints in the optional Extras/quickstep ODE solver. See CcdPhysicsDemo, enable #COMPARE_WITH_QUICKSTEP and add libquickstep to the dependencies.
+	For both patches/improvements thanks Francisco Leon/projectileman
+		
+2007 Sept 10
+	- removed union from btQuadWordStorage, it caused issues under certain version of gcc/Linux
+
+2007 Sept 10
+	- Reverted constraint solver, due to some issues. Need to review the recent memory allocation changes.
+	- Fixed issue with kinematic objects rotating at low speed: quaternion was de-normalized, passing value > 1 into acosf returns #IND00 invalid values
+	- 16 byte memory alignment for BVH serialization
+	- memory cleanup for btPoolAllocator
+
+2007 Sept 9
+	- Added serialization for BVH/btBvhTriangleMeshShape, including endian swapping. See ConcaveDemo for an example.
+	Thanks to Phil Knight for the contribution.
+	- Fixed issues related to stack allocator/compound collision algorithm
+	Thanks Proctoid, http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=18&t=1460
+	- Increase some default memory pool settings, and added a fallback for the constraints solver to use heap memory
+	- Removed accidential testing code in btScalar.h related to operator new.	
+	- Enable btAxis3Sweep and bt32BitAxis3Sweep to be linked in at the same time, using template
+	
+2007 Sept 7
+	- Replaced several dynamic memory allocations by stack allocation and pool allocations
+	- Added branch-free quantized aabb bounding box overlap check, works better on Playstation 3 and XBox 360
+	Thanks to Phil Knight. Also see www.cellperformance.com for related articles
+	- Collision algorithms and settings for the memory/stack allocator can be done using btDefaultCollisionConfiguration
+	This is an API change. See demos how to modify existing implementations with a one-liner.
+	- Register several collision algorithms by default (sphere-sphere, sphere-box, sphere-triangle)
+	- Use other traveral method for BVH by default, this improves triangle mesh collision performance.
+	
+2007 Aug 31
+	- fixed MSVC 6 build
+	Thanks Proctoid, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1375
+	- fixed double precision build issues
+	Thanks Alex Silverman, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1434
+
+2007 Aug 24
+	- fixed bug in btMatrix3x3::transposeTimes(const btMatrix3x3& m) const. Luckily it wasn't used in core parts of the library (yet).
+	Thanks to Jay Lee
+	
+2007 Aug 15
+	- fixed bug in Extras/GIMPACT 0.2 related to moving triangle meshes
+	Thanks Thomas, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1368
+
+2007 Aug 14
+	- added parallel constraint solver. Works on Playstation 3 Cell SPU and multi core (Win Threads on PC and XBox 360).
+	  See Extras/BulletMultiThreaded for SpuSolverTask subfolder and SpuParallelSolver.cpp
+	  Thanks Marten Svanfeldt (Starbreeze Studios)	
+	- fixed some bugs related to parallel collision detection (Extras/BulletMultiThreaded)
+	  Thanks Marten Svanfeldt (Starbreeze Studios)	
+	
+2007 Aug 2
+	- added compound and concave-convex (swapped) case for BulletMultiThreaded collision detection, thanks to Marten Svanfeldt
+	- refactored broadphase and overlapping pair cache. This allows performance improvement by combining multiple broadphases. This helps add/remove of large batches of objects and large worlds. See also Pierre Terdiman forum topic:
+	http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
+
+
+2007 July 27
+	- added Ragdoll Demo
+		Thanks to Marten Svanfeldt (Starbreeze Studios)
+
+	- added Vector Math library for SIMD 3D graphics linear algebra (vector, matrix, quaternion)
+		See Bullet/Extras/vectormathlibrary
+		Supports SIMD SSE, PowerPC PPU and Cell SPU (including PS3 Linux and CellBlade), as well as generic portable scalar version
+		Will be used to improve BulletMultiThreaded performance
+		Open Sourced by Sony Computer Entertainment Inc. under the new BSD license
+	- added SIMD math library
+		4-way SIMD for common math functions like atan2f4, cosf4, floorf4, fabsf4, rsqrtf4 etc. Used by Vector Math library under PPU and SPU.
+		Supports PowerPC (PPU) and Cell SPU, including PS3 Linux and CellBlade.
+		See Bullet/Extras/simdmathlibrary
+		Open sourced by Sony Computer Entertainment Inc. under the new BSD license
+
+	
+2007 July 25
+	- added several patches: per-rigidbody sleeping threshold. added Assert to prevent deletion of rigidbody while constraints are still pointing at it
+		Thanks to Marten Svanfeldt (Starbreeze Studios)
+	
+2007 July 13
+	- fixed relative #include paths again. We can't use "../" relative paths: some compilers choke on it (it causes extreme long paths)
+		Within the libraries, we always need to start with "BulletCollision/" or "BulletDynamics/ or "LinearMath/"
+
+2007 July 10
+	- Updated Bullet User Manual
+
+2007 July 5
+	- added btConeTwistConstraint, especially useful for ragdolls. See Demos/RagdollDemo
+		Thanks to Marten Svanfeldt (Starbreeze Studios)
+
+2007 June 29
+	- btHeightfieldTerrainShape: Added heightfield support, with customizations
+	- Upgraded to GIMPACT 0.2, see Extras/GIMPACT and MovingConcaveDemo
+	- Several patches from Marten Svanfeldt (Starbreeze Studios)
+		Improved collision filtering (in broadphase and rigidbody)
+		Improved debug rendering
+		Allow to set collision filter group/mask in addRigidBody
+		
+		
+2007 June 15
+	- Changed btAlignedObjectArray to call copy constructor/replacement new for duplication, rather then assignment operator (operator=).
+
+2007 June 11
+	- Added multi-threading. Originally for Playstation 3 Cell SPU, but the same code can run using Win32 Threads using fake DMA transfers (memcpy)
+		Libspe2 support for Cell Blade / PS3 Linux is upcoming
+		See Extras/BulletMultiThreaded. Usage: replace btCollisionDispatcher by btSpuGatheringCollisionDispatcher
+
+	- Added managed Bullet library, entirely rewritten in C# for Windows and XBox 360 XNA
+		See Extras/BulletX
+		Thanks to KleMiX, aka Vsevolod Klementjev
+
+2007 May 31
+	- sign-bit went wrong in case of 32-bit broadphase, causing quantization problems. 
+		Thanks DevO for reporting.
+
+2007 May 23
+	- Fixed quantization problem for planar triangle meshes in btOptimizedBvh
+		Thanks Phil Knight for reporting and helping to fix this bug.
+		
+2007 May 20
+	- btAxisSweep3: Fixed a bug in btAxisSweep3 (sweep and prune) related to object removal. Only showed up when at least one btStaticPlaneShape was inserted.
+		Thanks tbp for more details on reproducing case.
+	- btAxisSweep3: Fixed issue with full 32bit precision btAxisSweep3 (define BP_USE_FIXEDPOINT_INT_32), it used only 0xffff/65536 for quantization instead of full integer space (0xffffffff)
+	- btRaycastVehicle: Added 'getForwardVector' and getCurrentSpeedKmHour utility functions
+	- Fixed local scaling issues (btConvexTriangleMeshShape, btBvhTriangleMeshShape, removed scaling from btMatrix3x3). 
+		Thanks Volker for reporting!
+	- Added second filename search, so that starting BspDemo and ConvexDecompositionDemo from within Visual Studio (without setting the starting path) still works
+
+2007 April 22
+	- Added braking functionality to btRaycastVehicle
+	- Removed tons of warnings, under MSVC 2005 compilation in -W4
+	
+2007 March 21
+	- Fixed issues: comma at end of enum causes errors for some compilers
+	- Fixed initialization bug in LocalRayResult (	m_localShapeInfo(localShapeInfo) )
+	
+2007 March 20
+	- Added refit tree to quantized stackless tree, and updated ConcaveDemo as example.
+	
+2007 March 17
+	- Added constraint solver optimizations, avoiding cross products during iterations, and gather rigidbody/constraint info in contiguous memory (btSolverBody/btSolverConstraint)
+	- These optimizations don't give large benefit yet, but it has good potential. Turned on by default. Can be switched off using solver->setSolverMode(SOLVER_RANDMIZE_ORDER).
+	- Enabled anti-jitter for rigid bodies. This is experimental, and can be switched off by setting a global (it is experimental so no proper interface) gJitterVelocityDampingFactor = 1.0;
+	- Fixed bug in islandmanifold.heapSort(btPersistentManifoldSortPredicate()); , thanks Noehrgel for reporting this (affected Sun Solaris)
+	
+2007 March 12
+	- Added compile-time toggle between on 16-bit and 32-bit fixed-point SAP broadphase. 
+		This allows the number of bodies to exceed 32767
+	- Enable useQuantizedAabbCompression on btTriangleMesh, see ColladaDemo
+	
+2007 March 8
+	- Fixed bug in constraint/island sorting (caused by replacing STL by dedicated btAlignedObjectArray with heapSort)
+		Thanks Clemens Unterkofler for pointing this out!
+
+2007 March 6
+	- removed STL from the Bullet library: replace std::vector by btAlignedObjectArray. Also removed the std::set for overlapping pair set, and turned it into an overlapping pair array. The SAP only adds objects, never removed. Removal is postponed for during traversal of overlapping pairs (duplicates and non-overlapping pairs are removed during that traversal).
+	- added heap sort and binary search/linear search to btAlignedObjectArray
+	- fixed wrong cast, thanks Hamstray, http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1015
+
+
+2007 Feb 25
+	- Improved performance of convex collision shapes, cache local AABB instead of recomputation. This fixes issue with very slow performance in larger .bsp levels
+	
+2007 Feb 24
+	- Added compressed/quantized AABB tree, 16 bytes per node, while supporting 32-bit (triangle) indices. 
+	  Should be faster and smaller then original version (quantized aabb check is done in integer space)
+		Original aabb tree nodes are still supported. They are 44 bytes, with full floating point precision and additional subPart index.
+	- added meter-unit scaling support in ColladaConverter.cpp
+
+2007 Feb 21
+	- Build system: updated bullet.pc.in library names
+	- Updated EPA comparison integration (missing parameter)
+	
+2007 Jan 04
+	- fixed optimized AABB tree building: in some cases the tree building fails due to unbalanced trees, which generated stack overflow
+	
+2006 Dec 15
+	- added contribution to allow double precision collision detection/dynamics. Define BT_USE_DOUBLE_PRECISION in your project and libraries that include Bullet
+
+2006 Dec 14
+	- merged contact and non-contact constraint solving into one loop, will improve stability of jointed bodies during collisions
+	- added first draft for hingeConstraint motor
+	
+2006 Dec 8, Erwin Coumans
+	- preparation for SIMD: added btAlignedAllocator and btAlignedObjectArray, to replace stl std::vector, same interface, but compatible with 16 byte alignment
+	- cleaned up dependencies in autogenerated msvc projectfiles
+	- aligned btVector3 on 16 bytes boundary, under win32. see if developers will come up with problems
+
+2006 Dec 04, Erwin Coumans
+	Added btNearCallback. This is similar to Open Dynamics Engine (ODE) dNearCallback, but important differences:
+	- contact points are persistent (lifetime more then one frame, for warmstarting/incremental contact point management)
+	- continuous collision detection, time of impact
+	Added btRigidBody::isInWorld(), returns true if btRigidBody is inside a btCollisionWorld/btDynamicsWorld derived class
+	Added angularFactor to btRigidbody, this helps some character control (no angular impulse applied)
+
+
+2006 Nov 28
+	Moved StackAlloc from EPA into LinearMath/btStackAlloc
+	renamed internal class ConcaveShape into btConcaveShape
+	added btHeightfieldTerrainShape (not completed yet)
+		
+2006 Nov 15 Nathanael Presson
+	Added EPA penetration depth algorithm, Expanding Polytope Algorithm
+	Added Pierre Terdiman penetration depth comparison/test DEMO
+	Fixed Bullet's Minkowski sampling penetration depth solver
+	Contributed by Nathanael Presson
+	
+2006 Nov 11 Francisco León Nájera
+	Added GIMPACT trimesh collision detection: concave versus concave,
+	Contributed by Francisco León Nájera
+
+2006 Nov 2
+	Minor refactoring: btCollisionObject changes from struct into class, added accessor methods
+	Force use of btMotionState to synchronize graphics transform, disabled old btRigidBody constructor that accepts btTransform
+	Renamed treshold into threshold throughout the code
+	
+2006 Oct 30
+	Enable decoupling of physics and graphics framerate using interpolation and internal fixed timestep, based on btMotionState
+	Enabled raycast vehicle demo (still needs tuning)
+	Refresh contact points, even when they are already persistent.
+	Fixed debugDraw colors (thanks pc0de for reporting)
+	Use Dispatcher in ConcaveConvexCollisionAlgorithm (so it uses the registered collision algorithm, not hardcoded convexconcave)
+	Improved performance of constraint solver by precalculating the cross product/impulse arm
+	Added collision comparison code: ODE box-box, also sphere-triangle
+	Added safety check into GJK, and an assert for AABB's that are very large
+	Fixed kinematic support (deriving velocities for animated objects)
+	Updated comparison/optional quickstep solver in Extras
+	UserCollisionAlgorithm demonstrates btTriangleMesh usage (easier trimesh compared to index array version)
+	Removed scaling from btTransform (we only want to deal with rigid transforms)
+	
+2006 Oct 4
+	Fixed minor leak in btOptimizeBVH
+	Cleanup of btRigidBody construction
+	added getW() in btQuaternion
+	assert when setLinearVelocity is called on btRigidBody
+	renamed projectfile library from collada-dom to colladadom (to make VC6 happy)
+	
+2006 Sept 27
+	Big Refactoring: renamed and moved files, create a replacement for CcdPhysicsEnvironment/CcdPhysicsController.
+	All Bullet classes in LinearMath, BulletCollision and BulletDynamics start with bt, and methods start with lowercase.
+	Moved classes into src folder, which is the only include folder needed.
+	Added 2 headerfiles in src: btBulletCollisionCommon.h and btBulletDynamicsCommon.h
+
+2006 Sept 23
+	Fixed 2 bugs, causing crashes when removing objects. Should do better unit-testing. UnionFind and 3D SAP were involved.
+	
+2006 Sept 19
+	Allow programmable friction and contact solver model. User can register their own functions for several interaction types.
+	Improved performance, and removed hardcoded maximum overlaps (switched from C-array to stl::set)
+	
+2006 Sept 16
+	Added Bullet 2.0  User Manual
+	Allow registration of custom user collision algorithms
+
+2006 Sept 10
+	Started cleaning up demos
+	
+2006 Sept 4
+	Fixed concave collision bug (caused instability/missing collisions in meshes/compounds)
+	Fixed memoryleak in OptimizedBvh, added RayTestSingle to CollisionWorld
+	Prepared for VehicleDemo
+	Increased Performance (island generation for sleeping objects took too much time)
+	Better COLLADA 1.4.1 physics conformance in ColladaDemo
+
+2006 August 11
+	Added Quake BspDemo
+	Improved CCD for compound and non-convex objects
+
+2006 August 10
+	Added per-triangle material (friction/restitution) support for non-convex meshes. See ConcaveDemo for usage.
+
+2006 August 9
+	Added CMake support (see http://cmake.org)
+	This can autogenerate makefiles, projectfiles cross platform (including MacOS X Xcode )
+	Just run cmake . in the root folder and it will autogenerate build files
+	
+2006 July 26 Erwin Coumans
+	Upgraded to COLLADA-DOM 1.4.1, latest SVN version
+	ColladaDemo can export snapshots to .dae
+	
+2006 July 24 Erwin Coumans
+	Added Compound CollisionShape support
+	(this is still low performance -> requires stackless tree-versus-tree traversal for better performance)
+
+2006 July 15 Erwin Coumans
+	Added initial support for Parallel execution (collision detection, constraint solving)
+	See ParallelPhysicsEnvironment in Extras\PhysicsInterface\CcdPhysics
+	
+2006 July 10 Erwin Coumans
+	Added MacOS X support (some build issues mainly)
+		
+2006 July 5 Erwin Coumans
+	Improved COLLADA 1.4 physics import, both COLLADA-DOM and FCollada
+
+2006 June 29 Erwin Coumans
+	Refactoring of the broadphase
+	Moved some optional files to Extras: Algebraic ccd and EPA, quickstep
+	Moved the limits on bodies/overlap to 32k and 65k
+	
+2006 June 25 Erwin Coumans
+	Added basic Collision Filtering, during broadphase
+	Allow adding meshes to the TriangleIndexVertexArray,
+	(input for TriangleMeshShape) 
+	Preparation for CompoundShape
+
+2006 June 19 Erwin Coumans
+	Added support for COLLADA Physics Import.
+	Both jam and Visual Studio can compile ColladaDemo
+
+2006 June 18 Dirk Gregorius <dirk@dirkgregorius.de>
+	Started implementing Generic6DOF joint and setup basic interface
+
+
+2006 June 17 Frank Richter <resqu@gmx.ch>
+	Bumped version in configure.ac to 1.5.6 (assuming that "1.5f" is
+	  the next version released).
+	Updated files in mk/autoconf and mk/jam with copies from CS; fixes a 
+	  GLU detection issue on MinGW.
+	Set msvc/bullet_ico.ico as the default application icon.
+	Disabled exceptions for gcc builds.
+	Applied a patch from Michael D. Adams to fix a warning with gcc.
+2006 jUNE 16 Erwin Coumans
+	Constraints now merge simulation islands.
+
+2006 May 24
+	Improved GJK accuracy, fixed GjkConvexCast issue, thanks to ~MyXa~ for reporting
+	
+2006 May 19
+	Added restitution support
+	Moved out Friction and Dynamics info from ManifoldPoint (removed logical dependency)
+	Added a void* m_userPersistentData in ManifoldPoint.
+	Added a ContactDestroyedCallback, to allow user to handle destruction of m_userPersistentData
+
+2006 May 13
+	Fixed some bugs in friction / jacobian calculations. Reported by Dirk Gregorius. Thanks!
+
+2006 May 9
+	Fixed raycasting filtering
+	Moved repository to SVN at https://svn.sourceforge.net/svnroot/bullet
+		
+2006 April 27
+	Moved raycasting to CollisionWorld, to make it more generic
+	Added basic CCD option in the CcdCollisionDemo
+	Fixed 'noResponse' mode, for triggering rigidbodies (useful for Artificial Intelligence queries)
+	Improved Bullet/ODE sample (in Extras)
+		
+2006 April 10
+	Separating Axis Test (SAT) convex hull collision detector, contribution by Simon Hobbs
+	Added SIMD SSE Math classes (for above SAT)
+	Added Mouse picking in CcdPhysicsDemo
+	Improved penetration depth estimation in MinkowskiPenetrationDepthSolver, both accuracy and performance
+	Added Hinge constraint
+	Added quickprof profiling (see http://sourceforge.net/projects/quickprof )
+		
+2006 March 21 Frank Richter <resqu@gmx.ch>
+	Removed VC manifest files.
+	Removed superfluous "grpplugins" projects.
+
+2006 March 20 Erwin Coumans
+	Clamped the acculumated impulse rather then intermediate impulse (within the iteration)
+	Use the persistent contacts for reusing the impulse
+	Separated friction and normal solving for better stability
+	Decreased the default number of iterations of the constraint solver from 10 to 4
+
+2006 March 19 Frank Richter <resqu@gmx.ch>
+	Removed a couple of CSisms from the VC projects.
+	Fixed VC include & lib paths to go to the Addtional* options
+	  instead the command line arguments.
+	Added pkgconfig support.
+
+2006 March 14 Frank Richter <resqu@gmx.ch>
+	Added support for shipped GLUT on MinGW.
+	Fixed GLUT support on MinGW.
+
+2006 March 13 Frank Richter <resqu@gmx.ch>
+	Bolted on Jam-based build system.
+	Generated VC project files.
+	Fixed GCC warnings.
+	Fixed Linux build issues.
+
+2006 March 13
+Added 3D Sweep and Prune Broadphase Collision Detection, Contribution from Simon Hobbs.
+
+2006 March 2
+	Minor change in license to ZLib/LibPNG
+	This makes it legally a bit easier to deploy on Playstation 3
+	Prepared for more generic constraints, added ConstraintsDemo
+
+2006 Feb 23
+	Rearranged files and dependencies to allow for easier standalone Collision Detection without Bullet Dynamics.
+	See Demos/CollisionInterfaceDemo and Extras/ode/ode/test/test_BulletGjk.cpp for examples how to use.
+
+2005 August 6
+	Bullet 0.2 release with demos, sources, doxygen, draft manual
+
+2005 June 1
+	First public release of Bullet
+	
+
+... todo: add history
+
+2003 Initial version (continuous collision detection)
Index: /code/branches/RacingBots_FS18/src/external/bullet/LICENSE
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LICENSE	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LICENSE	(revision 11817)
@@ -0,0 +1,19 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+All files in the Bullet/src folder are under this Zlib license.
+Optional Extras/GIMPACT and Extras/GIMPACTBullet is also under ZLib license. Other optional external libraries in  Extras/Demos have own license,see respective files.
+
+This means Bullet can freely be used in any software, including commercial and console software. A Playstation 3 optimized version is available through Sony.
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,35 @@
+ADD_SOURCE_FILES(BULLET_FILES
+
+	btAlignedAllocator.cpp
+	btConvexHull.cpp
+	btConvexHullComputer.cpp
+	btGeometryUtil.cpp
+	btQuickprof.cpp
+	btSerializer.cpp
+
+	# Headers
+	btAabbUtil2.h
+	btAlignedAllocator.h
+	btAlignedObjectArray.h
+	btConvexHull.h
+	btConvexHullComputer.h
+	btDefaultMotionState.h
+	btGeometryUtil.h
+	btHashMap.h
+	btIDebugDraw.h
+	btList.h
+	btMatrix3x3.h
+	btMinMax.h
+	btMotionState.h
+	btPoolAllocator.h
+	btQuadWord.h
+	btQuaternion.h
+	btQuickprof.h
+	btRandom.h
+	btScalar.h
+	btSerializer.h
+	btStackAlloc.h
+	btTransform.h
+	btTransformUtil.h
+	btVector3.h
+)
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAabbUtil2.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAabbUtil2.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAabbUtil2.h	(revision 11817)
@@ -0,0 +1,236 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_AABB_UTIL2
+#define BT_AABB_UTIL2
+
+#include "btTransform.h"
+#include "btVector3.h"
+#include "btMinMax.h"
+
+
+
+SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
+								   btVector3& aabbMax,
+								   const btVector3& expansionMin,
+								   const btVector3& expansionMax)
+{
+	aabbMin = aabbMin + expansionMin;
+	aabbMax = aabbMax + expansionMax;
+}
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
+								const btVector3 &point)
+{
+	bool overlap = true;
+	overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
+	overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
+	overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
+	return overlap;
+}
+
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
+								const btVector3 &aabbMin2, const btVector3 &aabbMax2)
+{
+	bool overlap = true;
+	overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+	overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+	overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+	return overlap;
+}
+
+/// conservative test for overlap between triangle and aabb
+SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices,
+									const btVector3 &aabbMin, const btVector3 &aabbMax)
+{
+	const btVector3 &p1 = vertices[0];
+	const btVector3 &p2 = vertices[1];
+	const btVector3 &p3 = vertices[2];
+
+	if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
+	if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
+
+	if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
+	if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
+  
+	if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
+	if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
+	return true;
+}
+
+
+SIMD_FORCE_INLINE int	btOutcode(const btVector3& p,const btVector3& halfExtent) 
+{
+	return (p.getX()  < -halfExtent.getX() ? 0x01 : 0x0) |    
+		   (p.getX() >  halfExtent.getX() ? 0x08 : 0x0) |
+		   (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |    
+		   (p.getY() >  halfExtent.getY() ? 0x10 : 0x0) |
+		   (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |    
+		   (p.getZ() >  halfExtent.getZ() ? 0x20 : 0x0);
+}
+
+
+
+SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
+								  const btVector3& rayInvDirection,
+								  const unsigned int raySign[3],
+								  const btVector3 bounds[2],
+								  btScalar& tmin,
+								  btScalar lambda_min,
+								  btScalar lambda_max)
+{
+	btScalar tmax, tymin, tymax, tzmin, tzmax;
+	tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+	tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+	tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+	tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+
+	if ( (tmin > tymax) || (tymin > tmax) )
+		return false;
+
+	if (tymin > tmin)
+		tmin = tymin;
+
+	if (tymax < tmax)
+		tmax = tymax;
+
+	tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+	tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+
+	if ( (tmin > tzmax) || (tzmin > tmax) )
+		return false;
+	if (tzmin > tmin)
+		tmin = tzmin;
+	if (tzmax < tmax)
+		tmax = tzmax;
+	return ( (tmin < lambda_max) && (tmax > lambda_min) );
+}
+
+SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, 
+								 const btVector3& rayTo, 
+								 const btVector3& aabbMin, 
+								 const btVector3& aabbMax,
+					  btScalar& param, btVector3& normal) 
+{
+	btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5);
+	btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5);
+	btVector3	source = rayFrom - aabbCenter;
+	btVector3	target = rayTo - aabbCenter;
+	int	sourceOutcode = btOutcode(source,aabbHalfExtent);
+	int targetOutcode = btOutcode(target,aabbHalfExtent);
+	if ((sourceOutcode & targetOutcode) == 0x0)
+	{
+		btScalar lambda_enter = btScalar(0.0);
+		btScalar lambda_exit  = param;
+		btVector3 r = target - source;
+		int i;
+		btScalar	normSign = 1;
+		btVector3	hitNormal(0,0,0);
+		int bit=1;
+
+		for (int j=0;j<2;j++)
+		{
+			for (i = 0; i != 3; ++i)
+			{
+				if (sourceOutcode & bit)
+				{
+					btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+					if (lambda_enter <= lambda)
+					{
+						lambda_enter = lambda;
+						hitNormal.setValue(0,0,0);
+						hitNormal[i] = normSign;
+					}
+				}
+				else if (targetOutcode & bit) 
+				{
+					btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+					btSetMin(lambda_exit, lambda);
+				}
+				bit<<=1;
+			}
+			normSign = btScalar(-1.);
+		}
+		if (lambda_enter <= lambda_exit)
+		{
+			param = lambda_enter;
+			normal = hitNormal;
+			return true;
+		}
+	}
+	return false;
+}
+
+
+
+SIMD_FORCE_INLINE	void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+{
+	btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
+	btMatrix3x3 abs_b = t.getBasis().absolute();  
+	btVector3 center = t.getOrigin();
+	btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin),
+		   abs_b[1].dot(halfExtentsWithMargin),
+		  abs_b[2].dot(halfExtentsWithMargin));
+	aabbMinOut = center - extent;
+	aabbMaxOut = center + extent;
+}
+
+
+SIMD_FORCE_INLINE	void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+{
+		btAssert(localAabbMin.getX() <= localAabbMax.getX());
+		btAssert(localAabbMin.getY() <= localAabbMax.getY());
+		btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
+		btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+		localHalfExtents+=btVector3(margin,margin,margin);
+
+		btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+		btMatrix3x3 abs_b = trans.getBasis().absolute();  
+		btVector3 center = trans(localCenter);
+		btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+			   abs_b[1].dot(localHalfExtents),
+			  abs_b[2].dot(localHalfExtents));
+		aabbMinOut = center-extent;
+		aabbMaxOut = center+extent;
+}
+
+#define USE_BANCHLESS 1
+#ifdef USE_BANCHLESS
+	//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+	SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+	{		
+		return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+			& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+			& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+			1, 0));
+	}
+#else
+	SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+	{
+		bool overlap = true;
+		overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+		overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+		overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+		return overlap;
+	}
+#endif //USE_BANCHLESS
+
+#endif //BT_AABB_UTIL2
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedAllocator.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedAllocator.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedAllocator.cpp	(revision 11817)
@@ -0,0 +1,182 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btAlignedAllocator.h"
+
+int gNumAlignedAllocs = 0;
+int gNumAlignedFree = 0;
+int gTotalBytesAlignedAllocs = 0;//detect memory leaks
+
+static void *btAllocDefault(size_t size)
+{
+	return malloc(size);
+}
+
+static void btFreeDefault(void *ptr)
+{
+	free(ptr);
+}
+
+static btAllocFunc *sAllocFunc = btAllocDefault;
+static btFreeFunc *sFreeFunc = btFreeDefault;
+
+
+
+#if defined (BT_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void *btAlignedAllocDefault(size_t size, int alignment)
+{
+	return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void btAlignedFreeDefault(void *ptr)
+{
+	_aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+	return memalign(alignment, size);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+	free(ptr);
+}
+#else
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+  void *ret;
+  char *real;
+  unsigned long offset;
+
+  real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1));
+  if (real) {
+    offset = (alignment - (unsigned long long)(real + sizeof(void *))) & (alignment-1);
+    ret = (void *)((real + sizeof(void *)) + offset);
+    *((void **)(ret)-1) = (void *)(real);
+  } else {
+    ret = (void *)(real);
+  }
+  return (ret);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+  void* real;
+
+  if (ptr) {
+    real = *((void **)(ptr)-1);
+    sFreeFunc(real);
+  }
+}
+#endif
+
+
+static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
+static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
+
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
+{
+  sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+  sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
+}
+
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
+{
+  sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+  sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
+}
+
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+void*   btAlignedAllocInternal  (size_t size, int alignment,int line,char* filename)
+{
+ void *ret;
+ char *real;
+ unsigned long offset;
+
+ gTotalBytesAlignedAllocs += size;
+ gNumAlignedAllocs++;
+
+ 
+ real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1));
+ if (real) {
+   offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) &
+(alignment-1);
+   ret = (void *)((real + 2*sizeof(void *)) + offset);
+   *((void **)(ret)-1) = (void *)(real);
+       *((int*)(ret)-2) = size;
+
+ } else {
+   ret = (void *)(real);//??
+ }
+
+ printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size);
+
+ int* ptr = (int*)ret;
+ *ptr = 12;
+ return (ret);
+}
+
+void    btAlignedFreeInternal   (void* ptr,int line,char* filename)
+{
+
+ void* real;
+ gNumAlignedFree++;
+
+ if (ptr) {
+   real = *((void **)(ptr)-1);
+       int size = *((int*)(ptr)-2);
+       gTotalBytesAlignedAllocs -= size;
+
+	   printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size);
+
+   sFreeFunc(real);
+ } else
+ {
+	 printf("NULL ptr\n");
+ }
+}
+
+#else //BT_DEBUG_MEMORY_ALLOCATIONS
+
+void*	btAlignedAllocInternal	(size_t size, int alignment)
+{
+	gNumAlignedAllocs++;
+	void* ptr;
+	ptr = sAlignedAllocFunc(size, alignment);
+//	printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+	return ptr;
+}
+
+void	btAlignedFreeInternal	(void* ptr)
+{
+	if (!ptr)
+	{
+		return;
+	}
+
+	gNumAlignedFree++;
+//	printf("btAlignedFreeInternal %x\n",ptr);
+	sAlignedFreeFunc(ptr);
+}
+
+#endif //BT_DEBUG_MEMORY_ALLOCATIONS
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedAllocator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedAllocator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedAllocator.h	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_ALIGNED_ALLOCATOR
+#define BT_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "btScalar.h"
+//#define BT_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+#define btAlignedAlloc(a,b) \
+		btAlignedAllocInternal(a,b,__LINE__,__FILE__)
+
+#define btAlignedFree(ptr) \
+		btAlignedFreeInternal(ptr,__LINE__,__FILE__)
+
+void*	btAlignedAllocInternal	(size_t size, int alignment,int line,char* filename);
+
+void	btAlignedFreeInternal	(void* ptr,int line,char* filename);
+
+#else
+	void*	btAlignedAllocInternal	(size_t size, int alignment);
+	void	btAlignedFreeInternal	(void* ptr);
+
+	#define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment)
+	#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
+
+#endif
+typedef int	size_type;
+
+typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
+typedef void (btAlignedFreeFunc)(void *memblock);
+typedef void *(btAllocFunc)(size_t size);
+typedef void (btFreeFunc)(void *memblock);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
+///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
+
+
+///The btAlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
+template < typename T , unsigned Alignment >
+class btAlignedAllocator {
+	
+	typedef btAlignedAllocator< T , Alignment > self_type;
+	
+public:
+
+	//just going down a list:
+	btAlignedAllocator() {}
+	/*
+	btAlignedAllocator( const self_type & ) {}
+	*/
+
+	template < typename Other >
+	btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {}
+
+	typedef const T*         const_pointer;
+	typedef const T&         const_reference;
+	typedef T*               pointer;
+	typedef T&               reference;
+	typedef T                value_type;
+
+	pointer       address   ( reference        ref ) const                           { return &ref; }
+	const_pointer address   ( const_reference  ref ) const                           { return &ref; }
+	pointer       allocate  ( size_type        n   , const_pointer *      hint = 0 ) {
+		(void)hint;
+		return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment ));
+	}
+	void          construct ( pointer          ptr , const value_type &   value    ) { new (ptr) value_type( value ); }
+	void          deallocate( pointer          ptr ) {
+		btAlignedFree( reinterpret_cast< void * >( ptr ) );
+	}
+	void          destroy   ( pointer          ptr )                                 { ptr->~value_type(); }
+	
+
+	template < typename O > struct rebind {
+		typedef btAlignedAllocator< O , Alignment > other;
+	};
+	template < typename O >
+	self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; }
+
+	friend bool operator==( const self_type & , const self_type & ) { return true; }
+};
+
+
+
+#endif //BT_ALIGNED_ALLOCATOR
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedObjectArray.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedObjectArray.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btAlignedObjectArray.h	(revision 11817)
@@ -0,0 +1,471 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_OBJECT_ARRAY__
+#define BT_OBJECT_ARRAY__
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btAlignedAllocator.h"
+
+///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
+///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define BT_USE_PLACEMENT_NEW 1
+//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+
+#ifdef BT_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif //BT_USE_MEMCPY
+
+#ifdef BT_USE_PLACEMENT_NEW
+#include <new> //for placement new
+#endif //BT_USE_PLACEMENT_NEW
+
+
+///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
+template <typename T> 
+//template <class T> 
+class btAlignedObjectArray
+{
+	btAlignedAllocator<T , 16>	m_allocator;
+
+	int					m_size;
+	int					m_capacity;
+	T*					m_data;
+	//PCK: added this line
+	bool				m_ownsMemory;
+
+	protected:
+		SIMD_FORCE_INLINE	int	allocSize(int size)
+		{
+			return (size ? size*2 : 1);
+		}
+		SIMD_FORCE_INLINE	void	copy(int start,int end, T* dest) const
+		{
+			int i;
+			for (i=start;i<end;++i)
+#ifdef BT_USE_PLACEMENT_NEW
+				new (&dest[i]) T(m_data[i]);
+#else
+				dest[i] = m_data[i];
+#endif //BT_USE_PLACEMENT_NEW
+		}
+
+		SIMD_FORCE_INLINE	void	init()
+		{
+			//PCK: added this line
+			m_ownsMemory = true;
+			m_data = 0;
+			m_size = 0;
+			m_capacity = 0;
+		}
+		SIMD_FORCE_INLINE	void	destroy(int first,int last)
+		{
+			int i;
+			for (i=first; i<last;i++)
+			{
+				m_data[i].~T();
+			}
+		}
+
+		SIMD_FORCE_INLINE	void* allocate(int size)
+		{
+			if (size)
+				return m_allocator.allocate(size);
+			return 0;
+		}
+
+		SIMD_FORCE_INLINE	void	deallocate()
+		{
+			if(m_data)	{
+				//PCK: enclosed the deallocation in this block
+				if (m_ownsMemory)
+				{
+					m_allocator.deallocate(m_data);
+				}
+				m_data = 0;
+			}
+		}
+
+	
+
+
+	public:
+		
+		btAlignedObjectArray()
+		{
+			init();
+		}
+
+		~btAlignedObjectArray()
+		{
+			clear();
+		}
+
+		///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
+		btAlignedObjectArray(const btAlignedObjectArray& otherArray)
+		{
+			init();
+
+			int otherSize = otherArray.size();
+			resize (otherSize);
+			otherArray.copy(0, otherSize, m_data);
+		}
+
+		
+		
+		/// return the number of elements in the array
+		SIMD_FORCE_INLINE	int size() const
+		{	
+			return m_size;
+		}
+		
+		SIMD_FORCE_INLINE const T& at(int n) const
+		{
+			return m_data[n];
+		}
+
+		SIMD_FORCE_INLINE T& at(int n)
+		{
+			return m_data[n];
+		}
+
+		SIMD_FORCE_INLINE const T& operator[](int n) const
+		{
+			return m_data[n];
+		}
+
+		SIMD_FORCE_INLINE T& operator[](int n)
+		{
+			return m_data[n];
+		}
+		
+
+		///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+		SIMD_FORCE_INLINE	void	clear()
+		{
+			destroy(0,size());
+			
+			deallocate();
+			
+			init();
+		}
+
+		SIMD_FORCE_INLINE	void	pop_back()
+		{
+			m_size--;
+			m_data[m_size].~T();
+		}
+
+		///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+		///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+		SIMD_FORCE_INLINE	void	resize(int newsize, const T& fillData=T())
+		{
+			int curSize = size();
+
+			if (newsize < curSize)
+			{
+				for(int i = newsize; i < curSize; i++)
+				{
+					m_data[i].~T();
+				}
+			} else
+			{
+				if (newsize > size())
+				{
+					reserve(newsize);
+				}
+#ifdef BT_USE_PLACEMENT_NEW
+				for (int i=curSize;i<newsize;i++)
+				{
+					new ( &m_data[i]) T(fillData);
+				}
+#endif //BT_USE_PLACEMENT_NEW
+
+			}
+
+			m_size = newsize;
+		}
+	
+		SIMD_FORCE_INLINE	T&  expandNonInitializing( )
+		{	
+			int sz = size();
+			if( sz == capacity() )
+			{
+				reserve( allocSize(size()) );
+			}
+			m_size++;
+
+			return m_data[sz];		
+		}
+
+
+		SIMD_FORCE_INLINE	T&  expand( const T& fillValue=T())
+		{	
+			int sz = size();
+			if( sz == capacity() )
+			{
+				reserve( allocSize(size()) );
+			}
+			m_size++;
+#ifdef BT_USE_PLACEMENT_NEW
+			new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+#endif
+
+			return m_data[sz];		
+		}
+
+
+		SIMD_FORCE_INLINE	void push_back(const T& _Val)
+		{	
+			int sz = size();
+			if( sz == capacity() )
+			{
+				reserve( allocSize(size()) );
+			}
+			
+#ifdef BT_USE_PLACEMENT_NEW
+			new ( &m_data[m_size] ) T(_Val);
+#else
+			m_data[size()] = _Val;			
+#endif //BT_USE_PLACEMENT_NEW
+
+			m_size++;
+		}
+
+	
+		/// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+		SIMD_FORCE_INLINE	int capacity() const
+		{	
+			return m_capacity;
+		}
+		
+		SIMD_FORCE_INLINE	void reserve(int _Count)
+		{	// determine new minimum length of allocated storage
+			if (capacity() < _Count)
+			{	// not enough room, reallocate
+				T*	s = (T*)allocate(_Count);
+
+				copy(0, size(), s);
+
+				destroy(0,size());
+
+				deallocate();
+				
+				//PCK: added this line
+				m_ownsMemory = true;
+
+				m_data = s;
+				
+				m_capacity = _Count;
+
+			}
+		}
+
+
+		class less
+		{
+			public:
+
+				bool operator() ( const T& a, const T& b )
+				{
+					return ( a < b );
+				}
+		};
+	
+		template <typename L>
+		void quickSortInternal(L CompareFunc,int lo, int hi)
+		{
+		//  lo is the lower index, hi is the upper index
+		//  of the region of array a that is to be sorted
+			int i=lo, j=hi;
+			T x=m_data[(lo+hi)/2];
+
+			//  partition
+			do
+			{    
+				while (CompareFunc(m_data[i],x)) 
+					i++; 
+				while (CompareFunc(x,m_data[j])) 
+					j--;
+				if (i<=j)
+				{
+					swap(i,j);
+					i++; j--;
+				}
+			} while (i<=j);
+
+			//  recursion
+			if (lo<j) 
+				quickSortInternal( CompareFunc, lo, j);
+			if (i<hi) 
+				quickSortInternal( CompareFunc, i, hi);
+		}
+
+
+		template <typename L>
+		void quickSort(L CompareFunc)
+		{
+			//don't sort 0 or 1 elements
+			if (size()>1)
+			{
+				quickSortInternal(CompareFunc,0,size()-1);
+			}
+		}
+
+
+		///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+		template <typename L>
+		void downHeap(T *pArr, int k, int n,L CompareFunc)
+		{
+			/*  PRE: a[k+1..N] is a heap */
+			/* POST:  a[k..N]  is a heap */
+			
+			T temp = pArr[k - 1];
+			/* k has child(s) */
+			while (k <= n/2) 
+			{
+				int child = 2*k;
+				
+				if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
+				{
+					child++;
+				}
+				/* pick larger child */
+				if (CompareFunc(temp , pArr[child - 1]))
+				{
+					/* move child up */
+					pArr[k - 1] = pArr[child - 1];
+					k = child;
+				}
+				else
+				{
+					break;
+				}
+			}
+			pArr[k - 1] = temp;
+		} /*downHeap*/
+
+		void	swap(int index0,int index1)
+		{
+#ifdef BT_USE_MEMCPY
+			char	temp[sizeof(T)];
+			memcpy(temp,&m_data[index0],sizeof(T));
+			memcpy(&m_data[index0],&m_data[index1],sizeof(T));
+			memcpy(&m_data[index1],temp,sizeof(T));
+#else
+			T temp = m_data[index0];
+			m_data[index0] = m_data[index1];
+			m_data[index1] = temp;
+#endif //BT_USE_PLACEMENT_NEW
+
+		}
+
+	template <typename L>
+	void heapSort(L CompareFunc)
+	{
+		/* sort a[0..N-1],  N.B. 0 to N-1 */
+		int k;
+		int n = m_size;
+		for (k = n/2; k > 0; k--) 
+		{
+			downHeap(m_data, k, n, CompareFunc);
+		}
+
+		/* a[1..N] is now a heap */
+		while ( n>=1 ) 
+		{
+			swap(0,n-1); /* largest of a[0..n-1] */
+
+
+			n = n - 1;
+			/* restore a[1..i-1] heap */
+			downHeap(m_data, 1, n, CompareFunc);
+		} 
+	}
+
+	///non-recursive binary search, assumes sorted array
+	int	findBinarySearch(const T& key) const
+	{
+		int first = 0;
+		int last = size()-1;
+
+		//assume sorted array
+		while (first <= last) {
+			int mid = (first + last) / 2;  // compute mid point.
+			if (key > m_data[mid]) 
+				first = mid + 1;  // repeat search in top half.
+			else if (key < m_data[mid]) 
+				last = mid - 1; // repeat search in bottom half.
+			else
+				return mid;     // found it. return position /////
+		}
+		return size();    // failed to find key
+	}
+
+
+	int	findLinearSearch(const T& key) const
+	{
+		int index=size();
+		int i;
+
+		for (i=0;i<size();i++)
+		{
+			if (m_data[i] == key)
+			{
+				index = i;
+				break;
+			}
+		}
+		return index;
+	}
+
+	void	remove(const T& key)
+	{
+
+		int findIndex = findLinearSearch(key);
+		if (findIndex<size())
+		{
+			swap( findIndex,size()-1);
+			pop_back();
+		}
+	}
+
+	//PCK: whole function
+	void initializeFromBuffer(void *buffer, int size, int capacity)
+	{
+		clear();
+		m_ownsMemory = false;
+		m_data = (T*)buffer;
+		m_size = size;
+		m_capacity = capacity;
+	}
+
+	void copyFromArray(const btAlignedObjectArray& otherArray)
+	{
+		int otherSize = otherArray.size();
+		resize (otherSize);
+		otherArray.copy(0, otherSize, m_data);
+	}
+
+};
+
+#endif //BT_OBJECT_ARRAY__
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHull.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHull.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHull.cpp	(revision 11817)
@@ -0,0 +1,1174 @@
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2003-2006 Stan Melax http://www.melax.com/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <string.h>
+
+#include "btConvexHull.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+
+
+template <class T>
+void Swap(T &a,T &b)
+{
+	T tmp = a;
+	a=b;
+	b=tmp;
+}
+
+
+//----------------------------------
+
+class int3  
+{
+public:
+	int x,y,z;
+	int3(){};
+	int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
+	const int& operator[](int i) const {return (&x)[i];}
+	int& operator[](int i) {return (&x)[i];}
+};
+
+
+//------- btPlane ----------
+
+
+inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);}
+inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
+inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); }
+
+
+//--------- Utility Functions ------
+
+btVector3  PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
+btVector3  PlaneProject(const btPlane &plane, const btVector3 &point);
+
+btVector3  ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2);
+btVector3  ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2)
+{
+	btVector3 N1 = p0.normal;
+	btVector3 N2 = p1.normal;
+	btVector3 N3 = p2.normal;
+
+	btVector3 n2n3; n2n3 = N2.cross(N3);
+	btVector3 n3n1; n3n1 = N3.cross(N1);
+	btVector3 n1n2; n1n2 = N1.cross(N2);
+
+	btScalar quotient = (N1.dot(n2n3));
+
+	btAssert(btFabs(quotient) > btScalar(0.000001));
+	
+	quotient = btScalar(-1.) / quotient;
+	n2n3 *= p0.dist;
+	n3n1 *= p1.dist;
+	n1n2 *= p2.dist;
+	btVector3 potentialVertex = n2n3;
+	potentialVertex += n3n1;
+	potentialVertex += n1n2;
+	potentialVertex *= quotient;
+
+	btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ());
+	return result;
+
+}
+
+btScalar   DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL);
+btVector3  TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
+btVector3  NormalOf(const btVector3 *vert, const int n);
+
+
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
+{
+	// returns the point where the line p0-p1 intersects the plane n&d
+				static btVector3 dif;
+		dif = p1-p0;
+				btScalar dn= btDot(plane.normal,dif);
+				btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn;
+				return p0 + (dif*t);
+}
+
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
+{
+	return point - plane.normal * (btDot(point,plane.normal)+plane.dist);
+}
+
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
+{
+	// return the normal of the triangle
+	// inscribed by v0, v1, and v2
+	btVector3 cp=btCross(v1-v0,v2-v1);
+	btScalar m=cp.length();
+	if(m==0) return btVector3(1,0,0);
+	return cp*(btScalar(1.0)/m);
+}
+
+
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
+{
+	static btVector3 cp;
+	cp = btCross(udir,vdir).normalized();
+
+	btScalar distu = -btDot(cp,ustart);
+	btScalar distv = -btDot(cp,vstart);
+	btScalar dist = (btScalar)fabs(distu-distv);
+	if(upoint) 
+		{
+		btPlane plane;
+		plane.normal = btCross(vdir,cp).normalized();
+		plane.dist = -btDot(plane.normal,vstart);
+		*upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
+	}
+	if(vpoint) 
+		{
+		btPlane plane;
+		plane.normal = btCross(udir,cp).normalized();
+		plane.dist = -btDot(plane.normal,ustart);
+		*vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
+	}
+	return dist;
+}
+
+
+
+
+
+
+
+#define COPLANAR   (0)
+#define UNDER      (1)
+#define OVER       (2)
+#define SPLIT      (OVER|UNDER)
+#define PAPERWIDTH (btScalar(0.001))
+
+btScalar planetestepsilon = PAPERWIDTH;
+
+
+
+typedef ConvexH::HalfEdge HalfEdge;
+
+ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
+{
+	vertices.resize(vertices_size);
+	edges.resize(edges_size);
+	facets.resize(facets_size);
+}
+
+
+int PlaneTest(const btPlane &p, const btVector3 &v);
+int PlaneTest(const btPlane &p, const btVector3 &v) {
+	btScalar a  = btDot(v,p.normal)+p.dist;
+	int   flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
+	return flag;
+}
+
+int SplitTest(ConvexH &convex,const btPlane &plane);
+int SplitTest(ConvexH &convex,const btPlane &plane) {
+	int flag=0;
+	for(int i=0;i<convex.vertices.size();i++) {
+		flag |= PlaneTest(plane,convex.vertices[i]);
+	}
+	return flag;
+}
+
+class VertFlag
+{
+public:
+	unsigned char planetest;
+	unsigned char junk;
+	unsigned char undermap;
+	unsigned char overmap;
+};
+class EdgeFlag 
+{
+public:
+	unsigned char planetest;
+	unsigned char fixes;
+	short undermap;
+	short overmap;
+};
+class PlaneFlag
+{
+public:
+	unsigned char undermap;
+	unsigned char overmap;
+};
+class Coplanar{
+public:
+	unsigned short ea;
+	unsigned char v0;
+	unsigned char v1;
+};
+
+
+
+
+
+
+
+
+template<class T>
+int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+{
+	btAssert(count);
+	int m=-1;
+	for(int i=0;i<count;i++) 
+		if(allow[i])
+		{
+			if(m==-1 || btDot(p[i],dir)>btDot(p[m],dir))
+				m=i;
+		}
+	btAssert(m!=-1);
+	return m;
+} 
+
+btVector3 orth(const btVector3 &v);
+btVector3 orth(const btVector3 &v)
+{
+	btVector3 a=btCross(v,btVector3(0,0,1));
+	btVector3 b=btCross(v,btVector3(0,1,0));
+	if (a.length() > b.length())
+	{
+		return a.normalized();
+	} else {
+		return b.normalized();
+	}
+}
+
+
+template<class T>
+int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+{
+	int m=-1;
+	while(m==-1)
+	{
+		m = maxdirfiltered(p,count,dir,allow);
+		if(allow[m]==3) return m;
+		T u = orth(dir);
+		T v = btCross(u,dir);
+		int ma=-1;
+		for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0))
+		{
+			btScalar s = btSin(SIMD_RADS_PER_DEG*(x));
+			btScalar c = btCos(SIMD_RADS_PER_DEG*(x));
+			int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
+			if(ma==m && mb==m)
+			{
+				allow[m]=3;
+				return m;
+			}
+			if(ma!=-1 && ma!=mb)  // Yuck - this is really ugly
+			{
+				int mc = ma;
+				for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0))
+				{
+					btScalar s = btSin(SIMD_RADS_PER_DEG*(xx));
+					btScalar c = btCos(SIMD_RADS_PER_DEG*(xx));
+					int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
+					if(mc==m && md==m)
+					{
+						allow[m]=3;
+						return m;
+					}
+					mc=md;
+				}
+			}
+			ma=mb;
+		}
+		allow[m]=0;
+		m=-1;
+	}
+	btAssert(0);
+	return m;
+} 
+
+
+
+
+int operator ==(const int3 &a,const int3 &b);
+int operator ==(const int3 &a,const int3 &b) 
+{
+	for(int i=0;i<3;i++) 
+	{
+		if(a[i]!=b[i]) return 0;
+	}
+	return 1;
+}
+
+
+int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon);
+int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) 
+{
+	btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
+	return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
+}
+int hasedge(const int3 &t, int a,int b);
+int hasedge(const int3 &t, int a,int b)
+{
+	for(int i=0;i<3;i++)
+	{
+		int i1= (i+1)%3;
+		if(t[i]==a && t[i1]==b) return 1;
+	}
+	return 0;
+}
+int hasvert(const int3 &t, int v);
+int hasvert(const int3 &t, int v)
+{
+	return (t[0]==v || t[1]==v || t[2]==v) ;
+}
+int shareedge(const int3 &a,const int3 &b);
+int shareedge(const int3 &a,const int3 &b)
+{
+	int i;
+	for(i=0;i<3;i++)
+	{
+		int i1= (i+1)%3;
+		if(hasedge(a,b[i1],b[i])) return 1;
+	}
+	return 0;
+}
+
+class btHullTriangle;
+
+
+
+class btHullTriangle : public int3
+{
+public:
+	int3 n;
+	int id;
+	int vmax;
+	btScalar rise;
+	btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
+	{
+		vmax=-1;
+		rise = btScalar(0.0);
+	}
+	~btHullTriangle()
+	{
+	}
+	int &neib(int a,int b);
+};
+
+
+int &btHullTriangle::neib(int a,int b)
+{
+	static int er=-1;
+	int i;
+	for(i=0;i<3;i++) 
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		if((*this)[i]==a && (*this)[i1]==b) return n[i2];
+		if((*this)[i]==b && (*this)[i1]==a) return n[i2];
+	}
+	btAssert(0);
+	return er;
+}
+void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t)
+{
+	int i;
+	for(i=0;i<3;i++) 
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		int a = (*s)[i1];
+		int b = (*s)[i2];
+		btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id);
+		btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id);
+		m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
+		m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
+	}
+}
+
+void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t)
+{
+	b2bfix(s,t);
+	deAllocateTriangle(s);
+
+	deAllocateTriangle(t);
+}
+
+void HullLibrary::checkit(btHullTriangle *t)
+{
+	(void)t;
+
+	int i;
+	btAssert(m_tris[t->id]==t);
+	for(i=0;i<3;i++)
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		int a = (*t)[i1];
+		int b = (*t)[i2];
+
+		// release compile fix
+		(void)i1;
+		(void)i2;
+		(void)a;
+		(void)b;
+
+		btAssert(a!=b);
+		btAssert( m_tris[t->n[i]]->neib(b,a) == t->id);
+	}
+}
+
+btHullTriangle*	HullLibrary::allocateTriangle(int a,int b,int c)
+{
+	void* mem = btAlignedAlloc(sizeof(btHullTriangle),16);
+	btHullTriangle* tr = new (mem)btHullTriangle(a,b,c);
+	tr->id = m_tris.size();
+	m_tris.push_back(tr);
+
+	return tr;
+}
+
+void	HullLibrary::deAllocateTriangle(btHullTriangle* tri)
+{
+	btAssert(m_tris[tri->id]==tri);
+	m_tris[tri->id]=NULL;
+	tri->~btHullTriangle();
+	btAlignedFree(tri);
+}
+
+
+void HullLibrary::extrude(btHullTriangle *t0,int v)
+{
+	int3 t= *t0;
+	int n = m_tris.size();
+	btHullTriangle* ta = allocateTriangle(v,t[1],t[2]);
+	ta->n = int3(t0->n[0],n+1,n+2);
+	m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
+	btHullTriangle* tb = allocateTriangle(v,t[2],t[0]);
+	tb->n = int3(t0->n[1],n+2,n+0);
+	m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
+	btHullTriangle* tc = allocateTriangle(v,t[0],t[1]);
+	tc->n = int3(t0->n[2],n+0,n+1);
+	m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
+	checkit(ta);
+	checkit(tb);
+	checkit(tc);
+	if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]);
+	if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]);
+	if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]);
+	deAllocateTriangle(t0);
+
+}
+
+btHullTriangle* HullLibrary::extrudable(btScalar epsilon)
+{
+	int i;
+	btHullTriangle *t=NULL;
+	for(i=0;i<m_tris.size();i++)
+	{
+		if(!t || (m_tris[i] && t->rise<m_tris[i]->rise))
+		{
+			t = m_tris[i];
+		}
+	}
+	return (t->rise >epsilon)?t:NULL ;
+}
+
+
+
+
+int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow)
+{
+	btVector3 basis[3];
+	basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) );      
+	int p0 = maxdirsterid(verts,verts_count, basis[0],allow);   
+	int	p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
+	basis[0] = verts[p0]-verts[p1];
+	if(p0==p1 || basis[0]==btVector3(0,0,0)) 
+		return int4(-1,-1,-1,-1);
+	basis[1] = btCross(btVector3(     btScalar(1),btScalar(0.02), btScalar(0)),basis[0]);
+	basis[2] = btCross(btVector3(btScalar(-0.02),     btScalar(1), btScalar(0)),basis[0]);
+	if (basis[1].length() > basis[2].length())
+	{
+		basis[1].normalize();
+	} else {
+		basis[1] = basis[2];
+		basis[1].normalize ();
+	}
+	int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
+	if(p2 == p0 || p2 == p1)
+	{
+		p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
+	}
+	if(p2 == p0 || p2 == p1) 
+		return int4(-1,-1,-1,-1);
+	basis[1] = verts[p2] - verts[p0];
+	basis[2] = btCross(basis[1],basis[0]).normalized();
+	int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
+	if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
+	if(p3==p0||p3==p1||p3==p2) 
+		return int4(-1,-1,-1,-1);
+	btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
+	if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);}
+	return int4(p0,p1,p2,p3);
+}
+
+int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
+{
+	if(verts_count <4) return 0;
+	if(vlimit==0) vlimit=1000000000;
+	int j;
+	btVector3 bmin(*verts),bmax(*verts);
+	btAlignedObjectArray<int> isextreme;
+	isextreme.reserve(verts_count);
+	btAlignedObjectArray<int> allow;
+	allow.reserve(verts_count);
+
+	for(j=0;j<verts_count;j++) 
+	{
+		allow.push_back(1);
+		isextreme.push_back(0);
+		bmin.setMin (verts[j]);
+		bmax.setMax (verts[j]);
+	}
+	btScalar epsilon = (bmax-bmin).length() * btScalar(0.001);
+	btAssert (epsilon != 0.0);
+
+
+	int4 p = FindSimplex(verts,verts_count,allow);
+	if(p.x==-1) return 0; // simplex failed
+
+
+
+	btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0);  // a valid interior point
+	btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
+	btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
+	btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
+	btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
+	isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
+	checkit(t0);checkit(t1);checkit(t2);checkit(t3);
+
+	for(j=0;j<m_tris.size();j++)
+	{
+		btHullTriangle *t=m_tris[j];
+		btAssert(t);
+		btAssert(t->vmax<0);
+		btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+		t->vmax = maxdirsterid(verts,verts_count,n,allow);
+		t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+	}
+	btHullTriangle *te;
+	vlimit-=4;
+	while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
+	{
+		int3 ti=*te;
+		int v=te->vmax;
+		btAssert(v != -1);
+		btAssert(!isextreme[v]);  // wtf we've already done this vertex
+		isextreme[v]=1;
+		//if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
+		j=m_tris.size();
+		while(j--) {
+			if(!m_tris[j]) continue;
+			int3 t=*m_tris[j];
+			if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) 
+			{
+				extrude(m_tris[j],v);
+			}
+		}
+		// now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
+		j=m_tris.size();
+		while(j--)
+		{
+			if(!m_tris[j]) continue;
+			if(!hasvert(*m_tris[j],v)) break;
+			int3 nt=*m_tris[j];
+			if(above(verts,nt,center,btScalar(0.01)*epsilon)  || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) )
+			{
+				btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
+				btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j);
+				extrude(nb,v);
+				j=m_tris.size(); 
+			}
+		} 
+		j=m_tris.size();
+		while(j--)
+		{
+			btHullTriangle *t=m_tris[j];
+			if(!t) continue;
+			if(t->vmax>=0) break;
+			btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+			t->vmax = maxdirsterid(verts,verts_count,n,allow);
+			if(isextreme[t->vmax]) 
+			{
+				t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
+			}
+			else
+			{
+				t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+			}
+		}
+		vlimit --;
+	}
+	return 1;
+}
+
+int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) 
+{
+	int rc=calchullgen(verts,verts_count,  vlimit) ;
+	if(!rc) return 0;
+	btAlignedObjectArray<int> ts;
+	int i;
+
+	for(i=0;i<m_tris.size();i++)
+	{
+		if(m_tris[i])
+		{
+			for(int j=0;j<3;j++)
+				ts.push_back((*m_tris[i])[j]);
+			deAllocateTriangle(m_tris[i]);
+		}
+	}
+	tris_count = ts.size()/3;
+	tris_out.resize(ts.size());
+	
+	for (i=0;i<ts.size();i++)
+	{
+		tris_out[i] = static_cast<unsigned int>(ts[i]);
+	}
+	m_tris.resize(0);
+
+	return 1;
+}
+
+
+
+
+
+bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit)
+{
+	
+	int    tris_count;
+	int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast<int>(vlimit) );
+	if(!ret) return false;
+	result.mIndexCount = (unsigned int) (tris_count*3);
+	result.mFaceCount  = (unsigned int) tris_count;
+	result.mVertices   = (btVector3*) vertices;
+	result.mVcount     = (unsigned int) vcount;
+	return true;
+
+}
+
+
+void ReleaseHull(PHullResult &result);
+void ReleaseHull(PHullResult &result)
+{
+	if ( result.m_Indices.size() )
+	{
+		result.m_Indices.clear();
+	}
+
+	result.mVcount = 0;
+	result.mIndexCount = 0;
+	result.mVertices = 0;
+}
+
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib header
+//*********************************************************************
+//*********************************************************************
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib implementation
+//*********************************************************************
+//*********************************************************************
+
+HullError HullLibrary::CreateConvexHull(const HullDesc       &desc,           // describes the input request
+																					HullResult           &result)         // contains the resulst
+{
+	HullError ret = QE_FAIL;
+
+
+	PHullResult hr;
+
+	unsigned int vcount = desc.mVcount;
+	if ( vcount < 8 ) vcount = 8;
+
+	btAlignedObjectArray<btVector3> vertexSource;
+	vertexSource.resize(static_cast<int>(vcount));
+
+	btVector3 scale;
+
+	unsigned int ovcount;
+
+	bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
+
+	if ( ok )
+	{
+
+
+//		if ( 1 ) // scale vertices back to their original size.
+		{
+			for (unsigned int i=0; i<ovcount; i++)
+			{
+				btVector3& v = vertexSource[static_cast<int>(i)];
+				v[0]*=scale[0];
+				v[1]*=scale[1];
+				v[2]*=scale[2];
+			}
+		}
+
+		ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices);
+
+		if ( ok )
+		{
+
+			// re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
+			btAlignedObjectArray<btVector3>	vertexScratch;
+			vertexScratch.resize(static_cast<int>(hr.mVcount));
+
+			BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount );
+
+			ret = QE_OK;
+
+			if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
+			{
+				result.mPolygons          = false;
+				result.mNumOutputVertices = ovcount;
+				result.m_OutputVertices.resize(static_cast<int>(ovcount));
+				result.mNumFaces          = hr.mFaceCount;
+				result.mNumIndices        = hr.mIndexCount;
+
+				result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
+
+				memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+
+  			if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+				{
+
+					const unsigned int *source = &hr.m_Indices[0];
+					unsigned int *dest   = &result.m_Indices[0];
+
+					for (unsigned int i=0; i<hr.mFaceCount; i++)
+					{
+						dest[0] = source[2];
+						dest[1] = source[1];
+						dest[2] = source[0];
+						dest+=3;
+						source+=3;
+					}
+
+				}
+				else
+				{
+					memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int)*hr.mIndexCount);
+				}
+			}
+			else
+			{
+				result.mPolygons          = true;
+				result.mNumOutputVertices = ovcount;
+				result.m_OutputVertices.resize(static_cast<int>(ovcount));
+				result.mNumFaces          = hr.mFaceCount;
+				result.mNumIndices        = hr.mIndexCount+hr.mFaceCount;
+				result.m_Indices.resize(static_cast<int>(result.mNumIndices));
+				memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+
+//				if ( 1 )
+				{
+					const unsigned int *source = &hr.m_Indices[0];
+					unsigned int *dest   = &result.m_Indices[0];
+					for (unsigned int i=0; i<hr.mFaceCount; i++)
+					{
+						dest[0] = 3;
+						if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+						{
+							dest[1] = source[2];
+							dest[2] = source[1];
+							dest[3] = source[0];
+						}
+						else
+						{
+							dest[1] = source[0];
+							dest[2] = source[1];
+							dest[3] = source[2];
+						}
+
+						dest+=4;
+						source+=3;
+					}
+				}
+			}
+			ReleaseHull(hr);
+		}
+	}
+
+	return ret;
+}
+
+
+
+HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
+{
+	if ( result.m_OutputVertices.size())
+	{
+		result.mNumOutputVertices=0;
+		result.m_OutputVertices.clear();
+	}
+	if ( result.m_Indices.size() )
+	{
+		result.mNumIndices=0;
+		result.m_Indices.clear();
+	}
+	return QE_OK;
+}
+
+
+static void addPoint(unsigned int &vcount,btVector3 *p,btScalar x,btScalar y,btScalar z)
+{
+	// XXX, might be broken
+	btVector3& dest = p[vcount];
+	dest[0] = x;
+	dest[1] = y;
+	dest[2] = z;
+	vcount++;
+}
+
+btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2);
+btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2)
+{
+
+	btScalar dx = px - p2[0];
+	btScalar dy = py - p2[1];
+	btScalar dz = pz - p2[2];
+
+	return dx*dx+dy*dy+dz*dz;
+}
+
+
+
+bool  HullLibrary::CleanupVertices(unsigned int svcount,
+				   const btVector3 *svertices,
+				   unsigned int stride,
+				   unsigned int &vcount,       // output number of vertices
+				   btVector3 *vertices,                 // location to store the results.
+				   btScalar  normalepsilon,
+				   btVector3& scale)
+{
+	if ( svcount == 0 ) return false;
+
+	m_vertexIndexMapping.resize(0);
+
+
+#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
+
+	vcount = 0;
+
+	btScalar recip[3]={0.f,0.f,0.f};
+
+	if ( scale )
+	{
+		scale[0] = 1;
+		scale[1] = 1;
+		scale[2] = 1;
+	}
+
+	btScalar bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
+	btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+	const char *vtx = (const char *) svertices;
+
+//	if ( 1 )
+	{
+		for (unsigned int i=0; i<svcount; i++)
+		{
+			const btScalar *p = (const btScalar *) vtx;
+
+			vtx+=stride;
+
+			for (int j=0; j<3; j++)
+			{
+				if ( p[j] < bmin[j] ) bmin[j] = p[j];
+				if ( p[j] > bmax[j] ) bmax[j] = p[j];
+			}
+		}
+	}
+
+	btScalar dx = bmax[0] - bmin[0];
+	btScalar dy = bmax[1] - bmin[1];
+	btScalar dz = bmax[2] - bmin[2];
+
+	btVector3 center;
+
+	center[0] = dx*btScalar(0.5) + bmin[0];
+	center[1] = dy*btScalar(0.5) + bmin[1];
+	center[2] = dz*btScalar(0.5) + bmin[2];
+
+	if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
+	{
+
+		btScalar len = FLT_MAX;
+
+		if ( dx > EPSILON && dx < len ) len = dx;
+		if ( dy > EPSILON && dy < len ) len = dy;
+		if ( dz > EPSILON && dz < len ) len = dz;
+
+		if ( len == FLT_MAX )
+		{
+			dx = dy = dz = btScalar(0.01); // one centimeter
+		}
+		else
+		{
+			if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+			if ( dy < EPSILON ) dy = len * btScalar(0.05);
+			if ( dz < EPSILON ) dz = len * btScalar(0.05);
+		}
+
+		btScalar x1 = center[0] - dx;
+		btScalar x2 = center[0] + dx;
+
+		btScalar y1 = center[1] - dy;
+		btScalar y2 = center[1] + dy;
+
+		btScalar z1 = center[2] - dz;
+		btScalar z2 = center[2] + dz;
+
+		addPoint(vcount,vertices,x1,y1,z1);
+		addPoint(vcount,vertices,x2,y1,z1);
+		addPoint(vcount,vertices,x2,y2,z1);
+		addPoint(vcount,vertices,x1,y2,z1);
+		addPoint(vcount,vertices,x1,y1,z2);
+		addPoint(vcount,vertices,x2,y1,z2);
+		addPoint(vcount,vertices,x2,y2,z2);
+		addPoint(vcount,vertices,x1,y2,z2);
+
+		return true; // return cube
+
+
+	}
+	else
+	{
+		if ( scale )
+		{
+			scale[0] = dx;
+			scale[1] = dy;
+			scale[2] = dz;
+
+			recip[0] = 1 / dx;
+			recip[1] = 1 / dy;
+			recip[2] = 1 / dz;
+
+			center[0]*=recip[0];
+			center[1]*=recip[1];
+			center[2]*=recip[2];
+
+		}
+
+	}
+
+
+
+	vtx = (const char *) svertices;
+
+	for (unsigned int i=0; i<svcount; i++)
+	{
+		const btVector3 *p = (const btVector3 *)vtx;
+		vtx+=stride;
+
+		btScalar px = p->getX();
+		btScalar py = p->getY();
+		btScalar pz = p->getZ();
+
+		if ( scale )
+		{
+			px = px*recip[0]; // normalize
+			py = py*recip[1]; // normalize
+			pz = pz*recip[2]; // normalize
+		}
+
+//		if ( 1 )
+		{
+			unsigned int j;
+
+			for (j=0; j<vcount; j++)
+			{
+				/// XXX might be broken
+				btVector3& v = vertices[j];
+
+				btScalar x = v[0];
+				btScalar y = v[1];
+				btScalar z = v[2];
+
+				btScalar dx = btFabs(x - px );
+				btScalar dy = btFabs(y - py );
+				btScalar dz = btFabs(z - pz );
+
+				if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
+				{
+					// ok, it is close enough to the old one
+					// now let us see if it is further from the center of the point cloud than the one we already recorded.
+					// in which case we keep this one instead.
+
+					btScalar dist1 = GetDist(px,py,pz,center);
+					btScalar dist2 = GetDist(v[0],v[1],v[2],center);
+
+					if ( dist1 > dist2 )
+					{
+						v[0] = px;
+						v[1] = py;
+						v[2] = pz;
+						
+					}
+
+					break;
+				}
+			}
+
+			if ( j == vcount )
+			{
+				btVector3& dest = vertices[vcount];
+				dest[0] = px;
+				dest[1] = py;
+				dest[2] = pz;
+				vcount++;
+			}
+			m_vertexIndexMapping.push_back(j);
+		}
+	}
+
+	// ok..now make sure we didn't prune so many vertices it is now invalid.
+//	if ( 1 )
+	{
+		btScalar bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
+		btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+		for (unsigned int i=0; i<vcount; i++)
+		{
+			const btVector3& p = vertices[i];
+			for (int j=0; j<3; j++)
+			{
+				if ( p[j] < bmin[j] ) bmin[j] = p[j];
+				if ( p[j] > bmax[j] ) bmax[j] = p[j];
+			}
+		}
+
+		btScalar dx = bmax[0] - bmin[0];
+		btScalar dy = bmax[1] - bmin[1];
+		btScalar dz = bmax[2] - bmin[2];
+
+		if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
+		{
+			btScalar cx = dx*btScalar(0.5) + bmin[0];
+			btScalar cy = dy*btScalar(0.5) + bmin[1];
+			btScalar cz = dz*btScalar(0.5) + bmin[2];
+
+			btScalar len = FLT_MAX;
+
+			if ( dx >= EPSILON && dx < len ) len = dx;
+			if ( dy >= EPSILON && dy < len ) len = dy;
+			if ( dz >= EPSILON && dz < len ) len = dz;
+
+			if ( len == FLT_MAX )
+			{
+				dx = dy = dz = btScalar(0.01); // one centimeter
+			}
+			else
+			{
+				if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+				if ( dy < EPSILON ) dy = len * btScalar(0.05);
+				if ( dz < EPSILON ) dz = len * btScalar(0.05);
+			}
+
+			btScalar x1 = cx - dx;
+			btScalar x2 = cx + dx;
+
+			btScalar y1 = cy - dy;
+			btScalar y2 = cy + dy;
+
+			btScalar z1 = cz - dz;
+			btScalar z2 = cz + dz;
+
+			vcount = 0; // add box
+
+			addPoint(vcount,vertices,x1,y1,z1);
+			addPoint(vcount,vertices,x2,y1,z1);
+			addPoint(vcount,vertices,x2,y2,z1);
+			addPoint(vcount,vertices,x1,y2,z1);
+			addPoint(vcount,vertices,x1,y1,z2);
+			addPoint(vcount,vertices,x2,y1,z2);
+			addPoint(vcount,vertices,x2,y2,z2);
+			addPoint(vcount,vertices,x1,y2,z2);
+
+			return true;
+		}
+	}
+
+	return true;
+}
+
+void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
+{
+	btAlignedObjectArray<int>tmpIndices;
+	tmpIndices.resize(m_vertexIndexMapping.size());
+	int i;
+
+	for (i=0;i<m_vertexIndexMapping.size();i++)
+	{
+		tmpIndices[i] = m_vertexIndexMapping[i];
+	}
+
+	TUIntArray usedIndices;
+	usedIndices.resize(static_cast<int>(vcount));
+	memset(&usedIndices[0],0,sizeof(unsigned int)*vcount);
+
+	ocount = 0;
+
+	for (i=0; i<int (indexcount); i++)
+	{
+		unsigned int v = indices[i]; // original array index
+
+		btAssert( v >= 0 && v < vcount );
+
+		if ( usedIndices[static_cast<int>(v)] ) // if already remapped
+		{
+			indices[i] = usedIndices[static_cast<int>(v)]-1; // index to new array
+		}
+		else
+		{
+
+			indices[i] = ocount;      // new index mapping
+
+			overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
+			overts[ocount][1] = verts[v][1];
+			overts[ocount][2] = verts[v][2];
+
+			for (int k=0;k<m_vertexIndexMapping.size();k++)
+			{
+				if (tmpIndices[k]==int(v))
+					m_vertexIndexMapping[k]=ocount;
+			}
+
+			ocount++; // increment output vert count
+
+			btAssert( ocount >=0 && ocount <= vcount );
+
+			usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
+
+		
+		}
+	}
+
+	
+}
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHull.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHull.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHull.h	(revision 11817)
@@ -0,0 +1,241 @@
+
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2008 Stan Melax http://www.melax.com/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
+
+#ifndef BT_CD_HULL_H
+#define BT_CD_HULL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<unsigned int> TUIntArray;
+
+class HullResult
+{
+public:
+	HullResult(void)
+	{
+		mPolygons = true;
+		mNumOutputVertices = 0;
+		mNumFaces = 0;
+		mNumIndices = 0;
+	}
+	bool                    mPolygons;                  // true if indices represents polygons, false indices are triangles
+	unsigned int            mNumOutputVertices;         // number of vertices in the output hull
+	btAlignedObjectArray<btVector3>	m_OutputVertices;            // array of vertices
+	unsigned int            mNumFaces;                  // the number of faces produced
+	unsigned int            mNumIndices;                // the total number of indices
+	btAlignedObjectArray<unsigned int>    m_Indices;                   // pointer to indices.
+
+// If triangles, then indices are array indexes into the vertex list.
+// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
+};
+
+enum HullFlag
+{
+	QF_TRIANGLES         = (1<<0),             // report results as triangles, not polygons.
+	QF_REVERSE_ORDER     = (1<<1),             // reverse order of the triangle indices.
+	QF_DEFAULT           = QF_TRIANGLES
+};
+
+
+class HullDesc
+{
+public:
+	HullDesc(void)
+	{
+		mFlags          = QF_DEFAULT;
+		mVcount         = 0;
+		mVertices       = 0;
+		mVertexStride   = sizeof(btVector3);
+		mNormalEpsilon  = 0.001f;
+		mMaxVertices	= 4096; // maximum number of points to be considered for a convex hull.
+		mMaxFaces	= 4096;
+	};
+
+	HullDesc(HullFlag flag,
+		 unsigned int vcount,
+		 const btVector3 *vertices,
+		 unsigned int stride = sizeof(btVector3))
+	{
+		mFlags          = flag;
+		mVcount         = vcount;
+		mVertices       = vertices;
+		mVertexStride   = stride;
+		mNormalEpsilon  = btScalar(0.001);
+		mMaxVertices    = 4096;
+	}
+
+	bool HasHullFlag(HullFlag flag) const
+	{
+		if ( mFlags & flag ) return true;
+		return false;
+	}
+
+	void SetHullFlag(HullFlag flag)
+	{
+		mFlags|=flag;
+	}
+
+	void ClearHullFlag(HullFlag flag)
+	{
+		mFlags&=~flag;
+	}
+
+	unsigned int      mFlags;           // flags to use when generating the convex hull.
+	unsigned int      mVcount;          // number of vertices in the input point cloud
+	const btVector3  *mVertices;        // the array of vertices.
+	unsigned int      mVertexStride;    // the stride of each vertex, in bytes.
+	btScalar             mNormalEpsilon;   // the epsilon for removing duplicates.  This is a normalized value, if normalized bit is on.
+	unsigned int      mMaxVertices;     // maximum number of vertices to be considered for the hull!
+	unsigned int      mMaxFaces;
+};
+
+enum HullError
+{
+	QE_OK,            // success!
+	QE_FAIL           // failed.
+};
+
+class btPlane
+{
+	public:
+	btVector3	normal;
+	btScalar	dist;   // distance below origin - the D from plane equasion Ax+By+Cz+D=0
+			btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
+			btPlane():normal(),dist(0){}
+	
+};
+
+
+
+class ConvexH 
+{
+  public:
+	class HalfEdge
+	{
+	  public:
+		short ea;         // the other half of the edge (index into edges list)
+		unsigned char v;  // the vertex at the start of this edge (index into vertices list)
+		unsigned char p;  // the facet on which this edge lies (index into facets list)
+		HalfEdge(){}
+		HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
+	};
+	ConvexH()
+	{
+	}
+	~ConvexH()
+	{
+	}
+	btAlignedObjectArray<btVector3> vertices;
+	btAlignedObjectArray<HalfEdge> edges;
+	btAlignedObjectArray<btPlane>  facets;
+	ConvexH(int vertices_size,int edges_size,int facets_size);
+};
+
+
+class int4
+{
+public:
+	int x,y,z,w;
+	int4(){};
+	int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
+	const int& operator[](int i) const {return (&x)[i];}
+	int& operator[](int i) {return (&x)[i];}
+};
+
+class PHullResult
+{
+public:
+
+	PHullResult(void)
+	{
+		mVcount = 0;
+		mIndexCount = 0;
+		mFaceCount = 0;
+		mVertices = 0;
+	}
+
+	unsigned int mVcount;
+	unsigned int mIndexCount;
+	unsigned int mFaceCount;
+	btVector3*   mVertices;
+	TUIntArray m_Indices;
+};
+
+
+
+///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
+///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
+class HullLibrary
+{
+
+	btAlignedObjectArray<class btHullTriangle*> m_tris;
+
+public:
+
+	btAlignedObjectArray<int> m_vertexIndexMapping;
+
+
+	HullError CreateConvexHull(const HullDesc& desc, // describes the input request
+				   HullResult&     result);        // contains the resulst
+	HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
+
+private:
+
+	bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
+
+	class btHullTriangle*	allocateTriangle(int a,int b,int c);
+	void	deAllocateTriangle(btHullTriangle*);
+	void b2bfix(btHullTriangle* s,btHullTriangle*t);
+
+	void removeb2b(btHullTriangle* s,btHullTriangle*t);
+
+	void checkit(btHullTriangle *t);
+
+	btHullTriangle* extrudable(btScalar epsilon);
+
+	int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
+
+	int calchullgen(btVector3 *verts,int verts_count, int vlimit);
+
+	int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
+
+	class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
+
+	void extrude(class btHullTriangle* t0,int v);
+
+	ConvexH* test_cube();
+
+	//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. 
+	//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
+	//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
+	//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
+	void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
+
+	bool CleanupVertices(unsigned int svcount,
+			     const btVector3* svertices,
+			     unsigned int stride,
+			     unsigned int &vcount, // output number of vertices
+			     btVector3* vertices, // location to store the results.
+			     btScalar  normalepsilon,
+			     btVector3& scale);
+};
+
+
+#endif //BT_CD_HULL_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHullComputer.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHullComputer.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHullComputer.cpp	(revision 11817)
@@ -0,0 +1,2749 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <string.h>
+
+#include "btConvexHullComputer.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+#ifdef __GNUC__
+	#include <stdint.h>
+#elif defined(_MSC_VER)
+	typedef __int32 int32_t;
+	typedef __int64 int64_t;
+	typedef unsigned __int32 uint32_t;
+	typedef unsigned __int64 uint64_t;
+#else
+	typedef int int32_t;
+	typedef long long int int64_t;
+	typedef unsigned int uint32_t;
+	typedef unsigned long long int uint64_t;
+#endif
+
+
+//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
+//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL))  // || (defined(__ICL) && defined(_M_X64))   bug in Intel compiler, disable inline assembly
+//	#define USE_X86_64_ASM
+//#endif
+
+
+//#define DEBUG_CONVEX_HULL
+//#define SHOW_ITERATIONS
+
+#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
+	#include <stdio.h>
+#endif
+
+// Convex hull implementation based on Preparata and Hong
+// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullInternal
+{
+	public:
+		
+		class Point64
+		{
+			public:
+				int64_t x;
+				int64_t y;
+				int64_t z;
+				
+				Point64(int64_t x, int64_t y, int64_t z): x(x), y(y), z(z)
+				{
+				}
+
+				bool isZero()
+				{
+					return (x == 0) && (y == 0) && (z == 0);
+				}
+
+				int64_t dot(const Point64& b) const
+				{
+					return x * b.x + y * b.y + z * b.z;
+				}
+		};
+		
+		class Point32
+		{
+			public:
+				int32_t x;
+				int32_t y;
+				int32_t z;
+				int index;
+				
+				Point32()
+				{
+				}
+				
+				Point32(int32_t x, int32_t y, int32_t z): x(x), y(y), z(z), index(-1)
+				{
+				}
+				
+				bool operator==(const Point32& b) const
+				{
+					return (x == b.x) && (y == b.y) && (z == b.z);
+				}
+
+				bool operator!=(const Point32& b) const
+				{
+					return (x != b.x) || (y != b.y) || (z != b.z);
+				}
+
+				bool isZero()
+				{
+					return (x == 0) && (y == 0) && (z == 0);
+				}
+
+				Point64 cross(const Point32& b) const
+				{
+					return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+				}
+
+				Point64 cross(const Point64& b) const
+				{
+					return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
+				}
+
+				int64_t dot(const Point32& b) const
+				{
+					return x * b.x + y * b.y + z * b.z;
+				}
+
+				int64_t dot(const Point64& b) const
+				{
+					return x * b.x + y * b.y + z * b.z;
+				}
+
+				Point32 operator+(const Point32& b) const
+				{
+					return Point32(x + b.x, y + b.y, z + b.z);
+				}
+
+				Point32 operator-(const Point32& b) const
+				{
+					return Point32(x - b.x, y - b.y, z - b.z);
+				}
+		};
+
+		class Int128
+		{
+			public:
+				uint64_t low;
+				uint64_t high;
+
+				Int128()
+				{
+				}
+
+				Int128(uint64_t low, uint64_t high): low(low), high(high)
+				{
+				}
+
+				Int128(uint64_t low): low(low), high(0)
+				{
+				}
+
+				Int128(int64_t value): low(value), high((value >= 0) ? 0 : (uint64_t) -1LL)
+				{
+				}
+
+				static Int128 mul(int64_t a, int64_t b);
+
+				static Int128 mul(uint64_t a, uint64_t b);
+
+				Int128 operator-() const
+				{
+					return Int128((uint64_t) -(int64_t)low, ~high + (low == 0));
+				}
+
+				Int128 operator+(const Int128& b) const
+				{
+#ifdef USE_X86_64_ASM
+					Int128 result;
+					__asm__ ("addq %[bl], %[rl]\n\t"
+									 "adcq %[bh], %[rh]\n\t"
+									 : [rl] "=r" (result.low), [rh] "=r" (result.high)
+									 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+									 : "cc" );
+					return result;
+#else
+					uint64_t lo = low + b.low;
+					return Int128(lo, high + b.high + (lo < low));
+#endif
+				}
+
+				Int128 operator-(const Int128& b) const
+				{
+#ifdef USE_X86_64_ASM
+					Int128 result;
+					__asm__ ("subq %[bl], %[rl]\n\t"
+									 "sbbq %[bh], %[rh]\n\t"
+									 : [rl] "=r" (result.low), [rh] "=r" (result.high)
+									 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+									 : "cc" );
+					return result;
+#else
+					return *this + -b;
+#endif
+				}
+
+				Int128& operator+=(const Int128& b)
+				{
+#ifdef USE_X86_64_ASM
+					__asm__ ("addq %[bl], %[rl]\n\t"
+									 "adcq %[bh], %[rh]\n\t"
+									 : [rl] "=r" (low), [rh] "=r" (high)
+									 : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
+									 : "cc" );
+#else
+					uint64_t lo = low + b.low;
+					if (lo < low)
+					{
+						++high;
+					}
+					low = lo;
+					high += b.high;
+#endif
+					return *this;
+				}
+
+				Int128& operator++()
+				{
+					if (++low == 0)
+					{
+						++high;
+					}
+					return *this;
+				}
+
+				Int128 operator*(int64_t b) const;
+
+				btScalar toScalar() const
+				{
+					return ((int64_t) high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
+						: -(-*this).toScalar();
+				}
+
+				int getSign() const
+				{
+					return ((int64_t) high < 0) ? -1 : (high || low) ? 1 : 0;
+				}
+
+				bool operator<(const Int128& b) const
+				{
+					return (high < b.high) || ((high == b.high) && (low < b.low));
+				}
+
+				int ucmp(const Int128&b) const
+				{
+					if (high < b.high)
+					{
+						return -1;
+					}
+					if (high > b.high)
+					{
+						return 1;
+					}
+					if (low < b.low)
+					{
+						return -1;
+					}
+					if (low > b.low)
+					{
+						return 1;
+					}
+					return 0;
+				}
+		};
+
+
+		class Rational64
+		{
+			private:
+				uint64_t numerator;
+				uint64_t denominator;
+				int sign;
+				
+			public:
+				Rational64(int64_t numerator, int64_t denominator)
+				{
+					if (numerator > 0)
+					{
+						sign = 1;
+						this->numerator = (uint64_t) numerator;
+					}
+					else if (numerator < 0)
+					{
+						sign = -1;
+						this->numerator = (uint64_t) -numerator;
+					}
+					else
+					{
+						sign = 0;
+						this->numerator = 0;
+					}
+					if (denominator > 0)
+					{
+						this->denominator = (uint64_t) denominator;
+					}
+					else if (denominator < 0)
+					{
+						sign = -sign;
+						this->denominator = (uint64_t) -denominator;
+					}
+					else
+					{
+						this->denominator = 0;
+					}
+				}
+				
+				bool isNegativeInfinity() const
+				{
+					return (sign < 0) && (denominator == 0);
+				}
+				
+				bool isNaN() const
+				{
+					return (sign == 0) && (denominator == 0);
+				}
+				
+				int compare(const Rational64& b) const;
+				
+				btScalar toScalar() const
+				{
+					return sign * ((denominator == 0) ? SIMD_INFINITY : (btScalar) numerator / denominator);
+				}
+		};
+
+
+		class Rational128
+		{
+			private:
+				Int128 numerator;
+				Int128 denominator;
+				int sign;
+				bool isInt64;
+
+			public:
+				Rational128(int64_t value)
+				{
+					if (value > 0)
+					{
+						sign = 1;
+						this->numerator = value;
+					}
+					else if (value < 0)
+					{
+						sign = -1;
+						this->numerator = -value;
+					}
+					else
+					{
+						sign = 0;
+						this->numerator = (uint64_t) 0;
+					}
+					this->denominator = (uint64_t) 1;
+					isInt64 = true;
+				}
+
+				Rational128(const Int128& numerator, const Int128& denominator)
+				{
+					sign = numerator.getSign();
+					if (sign >= 0)
+					{
+						this->numerator = numerator;
+					}
+					else
+					{
+						this->numerator = -numerator;
+					}
+					int dsign = denominator.getSign();
+					if (dsign >= 0)
+					{
+						this->denominator = denominator;
+					}
+					else
+					{
+						sign = -sign;
+						this->denominator = -denominator;
+					}
+					isInt64 = false;
+				}
+
+				int compare(const Rational128& b) const;
+
+				int compare(int64_t b) const;
+
+				btScalar toScalar() const
+				{
+					return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
+				}
+		};
+
+		class PointR128
+		{
+			public:
+				Int128 x;
+				Int128 y;
+				Int128 z;
+				Int128 denominator;
+
+				PointR128()
+				{
+				}
+
+				PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator): x(x), y(y), z(z), denominator(denominator)
+				{
+				}
+
+				btScalar xvalue() const
+				{
+					return x.toScalar() / denominator.toScalar();
+				}
+
+				btScalar yvalue() const
+				{
+					return y.toScalar() / denominator.toScalar();
+				}
+
+				btScalar zvalue() const
+				{
+					return z.toScalar() / denominator.toScalar();
+				}
+		};
+
+
+		class Edge;
+		class Face;
+
+		class Vertex
+		{
+			public:
+				Vertex* next;
+				Vertex* prev;
+				Edge* edges;
+				Face* firstNearbyFace;
+				Face* lastNearbyFace;
+				PointR128 point128;
+				Point32 point;
+				int copy;
+				
+				Vertex(): next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
+				{
+				}
+
+#ifdef DEBUG_CONVEX_HULL
+				void print()
+				{
+					printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
+				}
+
+				void printGraph();
+#endif
+
+				Point32 operator-(const Vertex& b) const
+				{
+					return point - b.point;
+				}
+
+				Rational128 dot(const Point64& b) const
+				{
+					return (point.index >= 0) ? Rational128(point.dot(b))
+						: Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
+				}
+
+				btScalar xvalue() const
+				{
+					return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
+				}
+
+				btScalar yvalue() const
+				{
+					return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
+				}
+
+				btScalar zvalue() const
+				{
+					return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
+				}
+
+				void receiveNearbyFaces(Vertex* src)
+				{
+					if (lastNearbyFace)
+					{
+						lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
+					}
+					else
+					{
+						firstNearbyFace = src->firstNearbyFace;
+					}
+					if (src->lastNearbyFace)
+					{
+						lastNearbyFace = src->lastNearbyFace;
+					}
+					for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
+					{
+						btAssert(f->nearbyVertex == src);
+						f->nearbyVertex = this;
+					}
+					src->firstNearbyFace = NULL;
+					src->lastNearbyFace = NULL;
+				}
+		};
+
+
+		class Edge
+		{
+			public:
+				Edge* next;
+				Edge* prev;
+				Edge* reverse;
+				Vertex* target;
+				Face* face;
+				int copy;
+
+				~Edge()
+				{
+					next = NULL;
+					prev = NULL;
+					reverse = NULL;
+					target = NULL;
+					face = NULL;
+				}
+
+				void link(Edge* n)
+				{
+					btAssert(reverse->target == n->reverse->target);
+					next = n;
+					n->prev = this;
+				}
+
+#ifdef DEBUG_CONVEX_HULL
+				void print()
+				{
+					printf("E%p : %d -> %d,  n=%p p=%p   (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
+								 reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
+				}
+#endif
+		};
+
+		class Face
+		{
+			public:
+				Face* next;
+				Vertex* nearbyVertex;
+				Face* nextWithSameNearbyVertex;
+				Point32 origin;
+				Point32 dir0;
+				Point32 dir1;
+
+				Face(): next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
+				{
+				}
+
+				void init(Vertex* a, Vertex* b, Vertex* c)
+				{
+					nearbyVertex = a;
+					origin = a->point;
+					dir0 = *b - *a;
+					dir1 = *c - *a;
+					if (a->lastNearbyFace)
+					{
+						a->lastNearbyFace->nextWithSameNearbyVertex = this;
+					}
+					else
+					{
+						a->firstNearbyFace = this;
+					}
+					a->lastNearbyFace = this;
+				}
+
+				Point64 getNormal()
+				{
+					return dir0.cross(dir1);
+				}
+		};
+
+		template<typename UWord, typename UHWord> class DMul
+		{
+			private:
+				static uint32_t high(uint64_t value)
+				{
+					return (uint32_t) (value >> 32);
+				}
+				
+				static uint32_t low(uint64_t value)
+				{
+					return (uint32_t) value;
+				}
+				
+				static uint64_t mul(uint32_t a, uint32_t b)
+				{
+					return (uint64_t) a * (uint64_t) b;
+				}
+				
+				static void shlHalf(uint64_t& value)
+				{
+					value <<= 32;
+				}
+				
+				static uint64_t high(Int128 value)
+				{
+					return value.high;
+				}
+				
+				static uint64_t low(Int128 value)
+				{
+					return value.low;
+				}
+				
+				static Int128 mul(uint64_t a, uint64_t b)
+				{
+					return Int128::mul(a, b);
+				}
+				
+				static void shlHalf(Int128& value)
+				{
+					value.high = value.low;
+					value.low = 0;
+				}
+				
+			public:
+				
+				static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
+				{
+					UWord p00 = mul(low(a), low(b));
+					UWord p01 = mul(low(a), high(b));
+					UWord p10 = mul(high(a), low(b));
+					UWord p11 = mul(high(a), high(b));
+					UWord p0110 = UWord(low(p01)) + UWord(low(p10));
+					p11 += high(p01);
+					p11 += high(p10);
+					p11 += high(p0110);
+					shlHalf(p0110);
+					p00 += p0110;
+					if (p00 < p0110)
+					{
+						++p11;
+					}
+					resLow = p00;
+					resHigh = p11;
+				}
+		};
+	
+	private:
+
+		class IntermediateHull
+		{
+			public:
+				Vertex* minXy;
+				Vertex* maxXy;
+				Vertex* minYx;
+				Vertex* maxYx;
+				
+				IntermediateHull(): minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
+				{
+				}
+				
+				void print();
+		};
+	
+		enum Orientation {NONE, CLOCKWISE, COUNTER_CLOCKWISE};
+
+		template <typename T> class PoolArray
+		{
+			private:
+				T* array;
+				int size;
+
+			public:
+				PoolArray<T>* next;
+
+				PoolArray(int size): size(size), next(NULL)
+				{
+					array = (T*) btAlignedAlloc(sizeof(T) * size, 16);
+				}
+
+				~PoolArray()
+				{
+					btAlignedFree(array);
+				}
+
+				T* init()
+				{
+					T* o = array;
+					for (int i = 0; i < size; i++, o++)
+					{
+						o->next = (i+1 < size) ? o + 1 : NULL;
+					}
+					return array;
+				}
+		};
+
+		template <typename T> class Pool
+		{
+			private:
+				PoolArray<T>* arrays;
+				PoolArray<T>* nextArray;
+				T* freeObjects;
+				int arraySize;
+
+			public:
+				Pool(): arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
+				{
+				}
+
+				~Pool()
+				{
+					while (arrays)
+					{
+						PoolArray<T>* p = arrays;
+						arrays = p->next;
+						p->~PoolArray<T>();
+						btAlignedFree(p);
+					}
+				}
+
+				void reset()
+				{
+					nextArray = arrays;
+					freeObjects = NULL;
+				}
+
+				void setArraySize(int arraySize)
+				{
+					this->arraySize = arraySize;
+				}
+
+				T* newObject()
+				{
+					T* o = freeObjects;
+					if (!o)
+					{
+						PoolArray<T>* p = nextArray;
+						if (p)
+						{
+							nextArray = p->next;
+						}
+						else
+						{
+							p = new(btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
+							p->next = arrays;
+							arrays = p;
+						}
+						o = p->init();
+					}
+					freeObjects = o->next;
+					return new(o) T();
+				};
+
+				void freeObject(T* object)
+				{
+					object->~T();
+					object->next = freeObjects;
+					freeObjects = object;
+				}
+		};
+
+		btVector3 scaling;
+		btVector3 center;
+		Pool<Vertex> vertexPool;
+		Pool<Edge> edgePool;
+		Pool<Face> facePool;
+		btAlignedObjectArray<Vertex*> originalVertices;
+		int mergeStamp;
+		int minAxis;
+		int medAxis;
+		int maxAxis;
+		int usedEdgePairs;
+		int maxUsedEdgePairs;
+
+		static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
+		Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
+		void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
+
+		Edge* newEdgePair(Vertex* from, Vertex* to);
+
+		void removeEdgePair(Edge* edge)
+		{
+			Edge* n = edge->next;
+			Edge* r = edge->reverse;
+
+			btAssert(edge->target && r->target);
+
+			if (n != edge)
+			{
+				n->prev = edge->prev;
+				edge->prev->next = n;
+				r->target->edges = n;
+			}
+			else
+			{
+				r->target->edges = NULL;
+			}
+			
+			n = r->next;
+			
+			if (n != r)
+			{
+				n->prev = r->prev;
+				r->prev->next = n;
+				edge->target->edges = n;
+			}
+			else
+			{
+				edge->target->edges = NULL;
+			}
+
+			edgePool.freeObject(edge);
+			edgePool.freeObject(r);
+			usedEdgePairs--;
+		}
+		
+		void computeInternal(int start, int end, IntermediateHull& result);
+		
+		bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
+		
+		void merge(IntermediateHull& h0, IntermediateHull& h1);
+
+		btVector3 toBtVector(const Point32& v);
+
+		btVector3 getBtNormal(Face* face);
+
+		bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
+
+	public:
+		Vertex* vertexList;
+
+		void compute(const void* coords, bool doubleCoords, int stride, int count);
+
+		btVector3 getCoordinates(const Vertex* v);
+
+		btScalar shrink(btScalar amount, btScalar clampAmount);
+};
+
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
+{
+	bool negative = (int64_t) high < 0;
+	Int128 a = negative ? -*this : *this;
+	if (b < 0)
+	{
+		negative = !negative;
+		b = -b;
+	}
+	Int128 result = mul(a.low, (uint64_t) b);
+	result.high += a.high * (uint64_t) b;
+	return negative ? -result : result;
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
+{
+	Int128 result;
+	
+#ifdef USE_X86_64_ASM
+	__asm__ ("imulq %[b]"
+					 : "=a" (result.low), "=d" (result.high)
+					 : "0"(a), [b] "r"(b)
+					 : "cc" );
+	return result;
+	
+#else
+	bool negative = a < 0;
+	if (negative)
+	{
+		a = -a;
+	}
+	if (b < 0)
+	{
+		negative = !negative;
+		b = -b;
+	}
+	DMul<uint64_t, uint32_t>::mul((uint64_t) a, (uint64_t) b, result.low, result.high);
+	return negative ? -result : result;
+#endif
+}
+
+btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b)
+{
+	Int128 result;
+
+#ifdef USE_X86_64_ASM
+	__asm__ ("mulq %[b]"
+					 : "=a" (result.low), "=d" (result.high)
+					 : "0"(a), [b] "r"(b)
+					 : "cc" );
+
+#else
+	DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
+#endif
+
+	return result;
+}
+
+int btConvexHullInternal::Rational64::compare(const Rational64& b) const
+{
+	if (sign != b.sign)
+	{
+		return sign - b.sign;
+	}
+	else if (sign == 0)
+	{
+		return 0;
+	}
+
+	//	return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
+
+#ifdef USE_X86_64_ASM
+
+	int result;
+	int64_t tmp;
+	int64_t dummy;
+	__asm__ ("mulq %[bn]\n\t"
+					 "movq %%rax, %[tmp]\n\t"
+					 "movq %%rdx, %%rbx\n\t"
+					 "movq %[tn], %%rax\n\t"
+					 "mulq %[bd]\n\t"
+					 "subq %[tmp], %%rax\n\t"
+					 "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
+					 "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
+					 "orq %%rdx, %%rax\n\t"
+					 "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
+					 "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
+					 "shll $16, %%ebx\n\t" // ebx has same sign as difference
+					 : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
+					 : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
+					 : "%rdx", "cc" );
+	return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
+																// if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
+								: 0;
+
+#else
+
+	return sign * Int128::mul(numerator, b.denominator).ucmp(Int128::mul(denominator, b.numerator));
+
+#endif
+}
+
+int btConvexHullInternal::Rational128::compare(const Rational128& b) const
+{
+	if (sign != b.sign)
+	{
+		return sign - b.sign;
+	}
+	else if (sign == 0)
+	{
+		return 0;
+	}
+	if (isInt64)
+	{
+		return -b.compare(sign * (int64_t) numerator.low);
+	}
+
+	Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
+	DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
+	DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
+
+	int cmp = nbdHigh.ucmp(dbnHigh);
+	if (cmp)
+	{
+		return cmp * sign;
+	}
+	return nbdLow.ucmp(dbnLow) * sign;
+}
+
+int btConvexHullInternal::Rational128::compare(int64_t b) const
+{
+	if (isInt64)
+	{
+		int64_t a = sign * (int64_t) numerator.low;
+		return (a > b) ? 1 : (a < b) ? -1 : 0;
+	}
+	if (b > 0)
+	{
+		if (sign <= 0)
+		{
+			return -1;
+		}
+	}
+	else if (b < 0)
+	{
+		if (sign >= 0)
+		{
+			return 1;
+		}
+		b = -b;
+	}
+	else
+	{
+		return sign;
+	}
+
+	return numerator.ucmp(denominator * b) * sign;
+}
+
+
+btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
+{
+	btAssert(from && to);
+	Edge* e = edgePool.newObject();
+	Edge* r = edgePool.newObject();
+	e->reverse = r;
+	r->reverse = e;
+	e->copy = mergeStamp;
+	r->copy = mergeStamp;
+	e->target = to;
+	r->target = from;
+	e->face = NULL;
+	r->face = NULL;
+	usedEdgePairs++;
+	if (usedEdgePairs > maxUsedEdgePairs)
+	{
+		maxUsedEdgePairs = usedEdgePairs;
+	}
+	return e;
+}
+
+bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
+{
+	Vertex* v0 = h0.maxYx;
+	Vertex* v1 = h1.minYx;
+	if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
+	{
+		btAssert(v0->point.z < v1->point.z);
+		Vertex* v1p = v1->prev;
+		if (v1p == v1)
+		{
+			c0 = v0;
+			if (v1->edges)
+			{
+				btAssert(v1->edges->next == v1->edges);
+				v1 = v1->edges->target;
+				btAssert(v1->edges->next == v1->edges);
+			}
+			c1 = v1;
+			return false;
+		}
+		Vertex* v1n = v1->next;
+		v1p->next = v1n;
+		v1n->prev = v1p;
+		if (v1 == h1.minXy)
+		{
+			if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
+			{
+				h1.minXy = v1n;
+			}
+			else
+			{
+				h1.minXy = v1p;
+			}
+		}
+		if (v1 == h1.maxXy)
+		{
+			if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
+			{
+				h1.maxXy = v1n;
+			}
+			else
+			{
+				h1.maxXy = v1p;
+			}
+		}
+	}
+	
+	v0 = h0.maxXy;
+	v1 = h1.maxXy;
+	Vertex* v00 = NULL;
+	Vertex* v10 = NULL;
+	int32_t sign = 1;
+
+	for (int side = 0; side <= 1; side++)
+	{		
+		int32_t dx = (v1->point.x - v0->point.x) * sign;
+		if (dx > 0)
+		{
+			while (true)
+			{
+				int32_t dy = v1->point.y - v0->point.y;
+
+				Vertex* w0 = side ? v0->next : v0->prev;
+				if (w0 != v0)
+				{
+					int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+					int32_t dy0 = w0->point.y - v0->point.y;
+					if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
+					{
+						v0 = w0;
+						dx = (v1->point.x - v0->point.x) * sign;
+						continue;
+					}
+				}
+
+				Vertex* w1 = side ? v1->next : v1->prev;
+				if (w1 != v1)
+				{
+					int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+					int32_t dy1 = w1->point.y - v1->point.y;
+					int32_t dxn = (w1->point.x - v0->point.x) * sign;
+					if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
+					{
+						v1 = w1;
+						dx = dxn;
+						continue;
+					}
+				}
+
+				break;
+			}
+		}
+		else if (dx < 0)
+		{
+			while (true)
+			{
+				int32_t dy = v1->point.y - v0->point.y;
+				
+				Vertex* w1 = side ? v1->prev : v1->next;
+				if (w1 != v1)
+				{
+					int32_t dx1 = (w1->point.x - v1->point.x) * sign;
+					int32_t dy1 = w1->point.y - v1->point.y;
+					if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
+					{
+						v1 = w1;
+						dx = (v1->point.x - v0->point.x) * sign;
+						continue;
+					}
+				}
+				
+				Vertex* w0 = side ? v0->prev : v0->next;
+				if (w0 != v0)
+				{
+					int32_t dx0 = (w0->point.x - v0->point.x) * sign;
+					int32_t dy0 = w0->point.y - v0->point.y;
+					int32_t dxn = (v1->point.x - w0->point.x) * sign;
+					if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
+					{
+						v0 = w0;
+						dx = dxn;
+						continue;
+					}
+				}
+				
+				break;
+			}
+		}
+		else
+		{
+			int32_t x = v0->point.x;
+			int32_t y0 = v0->point.y;
+			Vertex* w0 = v0;
+			Vertex* t;
+			while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
+			{
+				w0 = t;
+				y0 = t->point.y;
+			}
+			v0 = w0;
+
+			int32_t y1 = v1->point.y;
+			Vertex* w1 = v1;
+			while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
+			{
+				w1 = t;
+				y1 = t->point.y;
+			}
+			v1 = w1;
+		}
+		
+		if (side == 0)
+		{
+			v00 = v0;
+			v10 = v1;
+
+			v0 = h0.minXy;
+			v1 = h1.minXy;
+			sign = -1;
+		}
+	}
+
+	v0->prev = v1;
+	v1->next = v0;
+
+	v00->next = v10;
+	v10->prev = v00;
+
+	if (h1.minXy->point.x < h0.minXy->point.x)
+	{
+		h0.minXy = h1.minXy;
+	}
+	if (h1.maxXy->point.x >= h0.maxXy->point.x)
+	{
+		h0.maxXy = h1.maxXy;
+	}
+	
+	h0.maxYx = h1.maxYx;
+
+	c0 = v00;
+	c1 = v10;
+
+	return true;
+}
+
+void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
+{
+	int n = end - start;
+	switch (n)
+	{
+		case 0:
+			result.minXy = NULL;
+			result.maxXy = NULL;
+			result.minYx = NULL;
+			result.maxYx = NULL;
+			return;
+		case 2:
+		{
+			Vertex* v = originalVertices[start];
+			Vertex* w = v + 1;
+			if (v->point != w->point)
+			{
+				int32_t dx = v->point.x - w->point.x;
+				int32_t dy = v->point.y - w->point.y;
+
+				if ((dx == 0) && (dy == 0))
+				{
+					if (v->point.z > w->point.z)
+					{
+						Vertex* t = w;
+						w = v;
+						v = t;
+					}
+					btAssert(v->point.z < w->point.z);
+					v->next = v;
+					v->prev = v;
+					result.minXy = v;
+					result.maxXy = v;
+					result.minYx = v;
+					result.maxYx = v;
+				}
+				else
+				{
+					v->next = w;
+					v->prev = w;
+					w->next = v;
+					w->prev = v;
+
+					if ((dx < 0) || ((dx == 0) && (dy < 0)))
+					{
+						result.minXy = v;
+						result.maxXy = w;
+					}
+					else
+					{
+						result.minXy = w;
+						result.maxXy = v;
+					}
+
+					if ((dy < 0) || ((dy == 0) && (dx < 0)))
+					{
+						result.minYx = v;
+						result.maxYx = w;
+					}
+					else
+					{
+						result.minYx = w;
+						result.maxYx = v;
+					}
+				}
+
+				Edge* e = newEdgePair(v, w);
+				e->link(e);
+				v->edges = e;
+
+				e = e->reverse;
+				e->link(e);
+				w->edges = e;
+
+				return;
+			}
+		}
+		// lint -fallthrough
+		case 1:
+		{
+			Vertex* v = originalVertices[start];
+			v->edges = NULL;
+			v->next = v;
+			v->prev = v;
+
+			result.minXy = v;
+			result.maxXy = v;
+			result.minYx = v;
+			result.maxYx = v;
+
+			return;
+		}
+	}
+
+	int split0 = start + n / 2;
+	Point32 p = originalVertices[split0-1]->point;
+	int split1 = split0;
+	while ((split1 < end) && (originalVertices[split1]->point == p))
+	{
+		split1++;
+	}
+	computeInternal(start, split0, result);
+	IntermediateHull hull1;
+	computeInternal(split1, end, hull1);
+#ifdef DEBUG_CONVEX_HULL
+	printf("\n\nMerge\n");
+	result.print();
+	hull1.print();
+#endif
+	merge(result, hull1);
+#ifdef DEBUG_CONVEX_HULL
+	printf("\n  Result\n");
+	result.print();
+#endif
+}
+
+#ifdef DEBUG_CONVEX_HULL
+void btConvexHullInternal::IntermediateHull::print()
+{
+	printf("    Hull\n");
+	for (Vertex* v = minXy; v; )
+	{
+		printf("      ");
+		v->print();
+		if (v == maxXy)
+		{
+			printf(" maxXy");
+		}
+		if (v == minYx)
+		{
+			printf(" minYx");
+		}
+		if (v == maxYx)
+		{
+			printf(" maxYx");
+		}
+		if (v->next->prev != v)
+		{
+			printf(" Inconsistency");
+		}
+		printf("\n");
+		v = v->next;
+		if (v == minXy)
+		{
+			break;
+		}
+	}
+	if (minXy)
+	{		
+		minXy->copy = (minXy->copy == -1) ? -2 : -1;
+		minXy->printGraph();
+	}
+}
+
+void btConvexHullInternal::Vertex::printGraph()
+{
+	print();
+	printf("\nEdges\n");
+	Edge* e = edges;
+	if (e)
+	{
+		do
+		{
+			e->print();
+			printf("\n");
+			e = e->next;
+		} while (e != edges);
+		do
+		{
+			Vertex* v = e->target;
+			if (v->copy != copy)
+			{
+				v->copy = copy;
+				v->printGraph();
+			}
+			e = e->next;
+		} while (e != edges);
+	}
+}
+#endif
+
+btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
+{
+	btAssert(prev->reverse->target == next->reverse->target);
+	if (prev->next == next)
+	{
+		if (prev->prev == next)
+		{
+			Point64 n = t.cross(s);
+			Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
+			btAssert(!m.isZero());
+			int64_t dot = n.dot(m);
+			btAssert(dot != 0);
+			return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
+		}
+		return COUNTER_CLOCKWISE;
+	}
+	else if (prev->prev == next)
+	{
+		return CLOCKWISE;
+	}
+	else
+	{
+		return NONE;
+	}
+}
+
+btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
+{
+	Edge* minEdge = NULL;
+
+#ifdef DEBUG_CONVEX_HULL
+	printf("find max edge for %d\n", start->point.index);
+#endif
+	Edge* e = start->edges;
+	if (e)
+	{
+		do
+		{
+			if (e->copy > mergeStamp)
+			{
+				Point32 t = *e->target - *start;
+				Rational64 cot(t.dot(sxrxs), t.dot(rxs));
+#ifdef DEBUG_CONVEX_HULL
+				printf("      Angle is %f (%d) for ", (float) btAtan(cot.toScalar()), (int) cot.isNaN());
+				e->print();
+#endif
+				if (cot.isNaN())
+				{
+					btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
+				}
+				else
+				{
+					int cmp;
+					if (minEdge == NULL)
+					{
+						minCot = cot;
+						minEdge = e;
+					}
+					else if ((cmp = cot.compare(minCot)) < 0)
+					{
+						minCot = cot;
+						minEdge = e;
+					}
+					else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
+					{
+						minEdge = e;
+					}
+				}
+#ifdef DEBUG_CONVEX_HULL
+				printf("\n");
+#endif
+			}
+			e = e->next;
+		} while (e != start->edges);
+	}
+	return minEdge;
+}
+
+void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
+{
+	Edge* start0 = e0;
+	Edge* start1 = e1;
+	Point32 et0 = start0 ? start0->target->point : c0->point;
+	Point32 et1 = start1 ? start1->target->point : c1->point;
+	Point32 s = c1->point - c0->point;
+	Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
+	int64_t dist = c0->point.dot(normal);
+	btAssert(!start1 || (start1->target->point.dot(normal) == dist));
+	Point64 perp = s.cross(normal);
+	btAssert(!perp.isZero());
+	
+#ifdef DEBUG_CONVEX_HULL
+	printf("   Advancing %d %d  (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
+#endif
+
+	int64_t maxDot0 = et0.dot(perp);
+	if (e0)
+	{
+		while (e0->target != stop0)
+		{
+			Edge* e = e0->reverse->prev;
+			if (e->target->point.dot(normal) < dist)
+			{
+				break;
+			}
+			btAssert(e->target->point.dot(normal) == dist);
+			if (e->copy == mergeStamp)
+			{
+				break;
+			}
+			int64_t dot = e->target->point.dot(perp);
+			if (dot <= maxDot0)
+			{
+				break;
+			}
+			maxDot0 = dot;
+			e0 = e;
+			et0 = e->target->point;
+		}
+	}
+	
+	int64_t maxDot1 = et1.dot(perp);
+	if (e1)
+	{
+		while (e1->target != stop1)
+		{
+			Edge* e = e1->reverse->next;
+			if (e->target->point.dot(normal) < dist)
+			{
+				break;
+			}
+			btAssert(e->target->point.dot(normal) == dist);
+			if (e->copy == mergeStamp)
+			{
+				break;
+			}
+			int64_t dot = e->target->point.dot(perp);
+			if (dot <= maxDot1)
+			{
+				break;
+			}
+			maxDot1 = dot;
+			e1 = e;
+			et1 = e->target->point;
+		}
+	}
+
+#ifdef DEBUG_CONVEX_HULL
+	printf("   Starting at %d %d\n", et0.index, et1.index);
+#endif
+
+	int64_t dx = maxDot1 - maxDot0;
+	if (dx > 0)
+	{
+		while (true)
+		{
+			int64_t dy = (et1 - et0).dot(s);
+			
+			if (e0 && (e0->target != stop0))
+			{
+				Edge* f0 = e0->next->reverse;
+				if (f0->copy > mergeStamp)
+				{
+					int64_t dx0 = (f0->target->point - et0).dot(perp);
+					int64_t dy0 = (f0->target->point - et0).dot(s);
+					if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
+					{
+						et0 = f0->target->point;
+						dx = (et1 - et0).dot(perp);
+						e0 = (e0 == start0) ? NULL : f0;
+						continue;
+					}
+				}
+			}
+			
+			if (e1 && (e1->target != stop1))
+			{
+				Edge* f1 = e1->reverse->next;
+				if (f1->copy > mergeStamp)
+				{
+					Point32 d1 = f1->target->point - et1;
+					if (d1.dot(normal) == 0)
+					{
+						int64_t dx1 = d1.dot(perp);
+						int64_t dy1 = d1.dot(s);
+						int64_t dxn = (f1->target->point - et0).dot(perp);
+						if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
+						{
+							e1 = f1;
+							et1 = e1->target->point;
+							dx = dxn;
+							continue;
+						}
+					}
+					else
+					{
+						btAssert((e1 == start1) && (d1.dot(normal) < 0));
+					}
+				}
+			}
+
+			break;
+		}
+	}
+	else if (dx < 0)
+	{
+		while (true)
+		{
+			int64_t dy = (et1 - et0).dot(s);
+			
+			if (e1 && (e1->target != stop1))
+			{
+				Edge* f1 = e1->prev->reverse;
+				if (f1->copy > mergeStamp)
+				{
+					int64_t dx1 = (f1->target->point - et1).dot(perp);
+					int64_t dy1 = (f1->target->point - et1).dot(s);
+					if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
+					{
+						et1 = f1->target->point;
+						dx = (et1 - et0).dot(perp);
+						e1 = (e1 == start1) ? NULL : f1;
+						continue;
+					}
+				}
+			}
+			
+			if (e0 && (e0->target != stop0))
+			{
+				Edge* f0 = e0->reverse->prev;
+				if (f0->copy > mergeStamp)
+				{
+					Point32 d0 = f0->target->point - et0;
+					if (d0.dot(normal) == 0)
+					{
+						int64_t dx0 = d0.dot(perp);
+						int64_t dy0 = d0.dot(s);
+						int64_t dxn = (et1 - f0->target->point).dot(perp);
+						if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
+						{
+							e0 = f0;
+							et0 = e0->target->point;
+							dx = dxn;
+							continue;
+						}
+					}
+					else
+					{
+						btAssert((e0 == start0) && (d0.dot(normal) < 0));
+					}
+				}
+			}
+
+			break;
+		}
+	}
+#ifdef DEBUG_CONVEX_HULL
+	printf("   Advanced edges to %d %d\n", et0.index, et1.index);
+#endif
+}
+
+
+void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
+{
+	if (!h1.maxXy)
+	{
+		return;
+	}
+	if (!h0.maxXy)
+	{
+		h0 = h1;
+		return;
+	}
+	
+	mergeStamp--;
+
+	Vertex* c0 = NULL;
+	Edge* toPrev0 = NULL;
+	Edge* firstNew0 = NULL;
+	Edge* pendingHead0 = NULL;
+	Edge* pendingTail0 = NULL;
+	Vertex* c1 = NULL;
+	Edge* toPrev1 = NULL;
+	Edge* firstNew1 = NULL;
+	Edge* pendingHead1 = NULL;
+	Edge* pendingTail1 = NULL;
+	Point32 prevPoint;
+
+	if (mergeProjection(h0, h1, c0, c1))
+	{
+		Point32 s = *c1 - *c0;
+		Point64 normal = Point32(0, 0, -1).cross(s);
+		Point64 t = s.cross(normal);
+		btAssert(!t.isZero());
+
+		Edge* e = c0->edges;
+		Edge* start0 = NULL;
+		if (e)
+		{
+			do
+			{
+				int64_t dot = (*e->target - *c0).dot(normal);
+				btAssert(dot <= 0);
+				if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
+				{
+					if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
+					{
+						start0 = e;
+					}
+				}
+				e = e->next;
+			} while (e != c0->edges);
+		}
+		
+		e = c1->edges;
+		Edge* start1 = NULL;
+		if (e)
+		{
+			do
+			{
+				int64_t dot = (*e->target - *c1).dot(normal);
+				btAssert(dot <= 0);
+				if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
+				{
+					if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
+					{
+						start1 = e;
+					}
+				}
+				e = e->next;
+			} while (e != c1->edges);
+		}
+
+		if (start0 || start1)
+		{
+			findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
+			if (start0)
+			{
+				c0 = start0->target;
+			}
+			if (start1)
+			{
+				c1 = start1->target;
+			}
+		}
+
+		prevPoint = c1->point;
+		prevPoint.z++;
+	}
+	else
+	{
+		prevPoint = c1->point;
+		prevPoint.x++;
+	}
+
+	Vertex* first0 = c0;
+	Vertex* first1 = c1;
+	bool firstRun = true;
+
+	while (true)
+	{
+		Point32 s = *c1 - *c0;
+		Point32 r = prevPoint - c0->point;
+		Point64 rxs = r.cross(s);
+		Point64 sxrxs = s.cross(rxs);
+		
+#ifdef DEBUG_CONVEX_HULL
+		printf("\n  Checking %d %d\n", c0->point.index, c1->point.index);
+#endif
+		Rational64 minCot0(0, 0);
+		Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
+		Rational64 minCot1(0, 0);
+		Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
+		if (!min0 && !min1)
+		{
+			Edge* e = newEdgePair(c0, c1);
+			e->link(e);
+			c0->edges = e;
+
+			e = e->reverse;
+			e->link(e);
+			c1->edges = e;
+			return;
+		}
+		else
+		{
+			int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
+#ifdef DEBUG_CONVEX_HULL
+			printf("    -> Result %d\n", cmp);
+#endif
+			if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
+			{
+				Edge* e = newEdgePair(c0, c1);
+				if (pendingTail0)
+				{
+					pendingTail0->prev = e;
+				}
+				else
+				{
+					pendingHead0 = e;
+				}
+				e->next = pendingTail0;
+				pendingTail0 = e;
+
+				e = e->reverse;
+				if (pendingTail1)
+				{
+					pendingTail1->next = e;
+				}
+				else
+				{
+					pendingHead1 = e;
+				}
+				e->prev = pendingTail1;
+				pendingTail1 = e;
+			}
+			
+			Edge* e0 = min0;
+			Edge* e1 = min1;
+
+#ifdef DEBUG_CONVEX_HULL
+			printf("   Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
+#endif
+
+			if (cmp == 0)
+			{
+				findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
+			}
+
+			if ((cmp >= 0) && e1)
+			{
+				if (toPrev1)
+				{
+					for (Edge* e = toPrev1->next, *n = NULL; e != min1; e = n)
+					{
+						n = e->next;
+						removeEdgePair(e);
+					}
+				}
+
+				if (pendingTail1)
+				{
+					if (toPrev1)
+					{
+						toPrev1->link(pendingHead1);
+					}
+					else
+					{
+						min1->prev->link(pendingHead1);
+						firstNew1 = pendingHead1;
+					}
+					pendingTail1->link(min1);
+					pendingHead1 = NULL;
+					pendingTail1 = NULL;
+				}
+				else if (!toPrev1)
+				{
+					firstNew1 = min1;
+				}
+
+				prevPoint = c1->point;
+				c1 = e1->target;
+				toPrev1 = e1->reverse;
+			}
+
+			if ((cmp <= 0) && e0)
+			{
+				if (toPrev0)
+				{
+					for (Edge* e = toPrev0->prev, *n = NULL; e != min0; e = n)
+					{
+						n = e->prev;
+						removeEdgePair(e);
+					}
+				}
+
+				if (pendingTail0)
+				{
+					if (toPrev0)
+					{
+						pendingHead0->link(toPrev0);
+					}
+					else
+					{
+						pendingHead0->link(min0->next);
+						firstNew0 = pendingHead0;
+					}
+					min0->link(pendingTail0);
+					pendingHead0 = NULL;
+					pendingTail0 = NULL;
+				}
+				else if (!toPrev0)
+				{
+					firstNew0 = min0;
+				}
+
+				prevPoint = c0->point;
+				c0 = e0->target;
+				toPrev0 = e0->reverse;
+			}
+		}
+
+		if ((c0 == first0) && (c1 == first1))
+		{
+			if (toPrev0 == NULL)
+			{
+				pendingHead0->link(pendingTail0);
+				c0->edges = pendingTail0;
+			}
+			else
+			{
+				for (Edge* e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
+				{
+					n = e->prev;
+					removeEdgePair(e);
+				}
+				if (pendingTail0)
+				{
+					pendingHead0->link(toPrev0);
+					firstNew0->link(pendingTail0);
+				}
+			}
+
+			if (toPrev1 == NULL)
+			{
+				pendingTail1->link(pendingHead1);
+				c1->edges = pendingTail1;
+			}
+			else
+			{
+				for (Edge* e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
+				{
+					n = e->next;
+					removeEdgePair(e);
+				}
+				if (pendingTail1)
+				{
+					toPrev1->link(pendingHead1);
+					pendingTail1->link(firstNew1);
+				}
+			}
+			
+			return;
+		}
+
+		firstRun = false;
+	}
+}
+
+
+static bool pointCmp(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q)
+{
+	return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
+}
+
+void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
+{
+	btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
+	const char* ptr = (const char*) coords;
+	if (doubleCoords)
+	{
+		for (int i = 0; i < count; i++)
+		{
+			const double* v = (const double*) ptr;
+			btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
+			ptr += stride;
+			min.setMin(p);
+			max.setMax(p);
+		}
+	}
+	else
+	{
+		for (int i = 0; i < count; i++)
+		{
+			const float* v = (const float*) ptr;
+			btVector3 p(v[0], v[1], v[2]);
+			ptr += stride;
+			min.setMin(p);
+			max.setMax(p);
+		}
+	}
+
+	btVector3 s = max - min;
+	maxAxis = s.maxAxis();
+	minAxis = s.minAxis();
+	if (minAxis == maxAxis)
+	{
+		minAxis = (maxAxis + 1) % 3;
+	}
+	medAxis = 3 - maxAxis - minAxis;
+
+	s /= btScalar(10216);
+
+	scaling = s;
+	if (s[0] > 0)
+	{
+		s[0] = btScalar(1) / s[0];
+	}
+	if (s[1] > 0)
+	{
+		s[1] = btScalar(1) / s[1];
+	}
+	if (s[2] > 0)
+	{
+		s[2] = btScalar(1) / s[2];
+	}
+
+	center = (min + max) * btScalar(0.5);
+
+	btAlignedObjectArray<Point32> points;
+	points.resize(count);
+	ptr = (const char*) coords;
+	if (doubleCoords)
+	{
+		for (int i = 0; i < count; i++)
+		{
+			const double* v = (const double*) ptr;
+			btVector3 p((btScalar) v[0], (btScalar) v[1], (btScalar) v[2]);
+			ptr += stride;
+			p = (p - center) * s;
+			points[i].x = (int32_t) p[medAxis];
+			points[i].y = (int32_t) p[maxAxis];
+			points[i].z = (int32_t) p[minAxis];
+			points[i].index = i;
+		}
+	}
+	else
+	{
+		for (int i = 0; i < count; i++)
+		{
+			const float* v = (const float*) ptr;
+			btVector3 p(v[0], v[1], v[2]);
+			ptr += stride;
+			p = (p - center) * s;
+			points[i].x = (int32_t) p[medAxis];
+			points[i].y = (int32_t) p[maxAxis];
+			points[i].z = (int32_t) p[minAxis];
+			points[i].index = i;
+		}
+	}
+	points.quickSort(pointCmp);
+
+	vertexPool.reset();
+	vertexPool.setArraySize(count);
+	originalVertices.resize(count);
+	for (int i = 0; i < count; i++)
+	{
+		Vertex* v = vertexPool.newObject();
+		v->edges = NULL;
+		v->point = points[i];
+		v->copy = -1;
+		originalVertices[i] = v;
+	}
+
+	points.clear();
+
+	edgePool.reset();
+	edgePool.setArraySize(6 * count);
+
+	usedEdgePairs = 0;
+	maxUsedEdgePairs = 0;
+
+	mergeStamp = -3;
+
+	IntermediateHull hull;
+	computeInternal(0, count, hull);
+	vertexList = hull.minXy;
+#ifdef DEBUG_CONVEX_HULL
+	printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
+#endif
+}
+
+btVector3 btConvexHullInternal::toBtVector(const Point32& v)
+{
+	btVector3 p;
+	p[medAxis] = btScalar(v.x);
+	p[maxAxis] = btScalar(v.y);
+	p[minAxis] = btScalar(v.z);
+	return p * scaling;
+}
+
+btVector3 btConvexHullInternal::getBtNormal(Face* face)
+{
+	btVector3 normal = toBtVector(face->dir0).cross(toBtVector(face->dir1));
+	normal /= ((medAxis + 1 == maxAxis) || (medAxis - 2 == maxAxis)) ? normal.length() : -normal.length();
+	return normal;
+}
+
+btVector3 btConvexHullInternal::getCoordinates(const Vertex* v)
+{
+	btVector3 p;
+	p[medAxis] = v->xvalue();
+	p[maxAxis] = v->yvalue();
+	p[minAxis] = v->zvalue();
+	return p * scaling + center;
+}
+
+btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
+{
+	if (!vertexList)
+	{
+		return 0;
+	}
+	int stamp = --mergeStamp;
+	btAlignedObjectArray<Vertex*> stack;
+	vertexList->copy = stamp;
+	stack.push_back(vertexList);
+	btAlignedObjectArray<Face*> faces;
+
+	Point32 ref = vertexList->point;
+	Int128 hullCenterX(0, 0);
+	Int128 hullCenterY(0, 0);
+	Int128 hullCenterZ(0, 0);
+	Int128 volume(0, 0);
+
+	while (stack.size() > 0)
+	{
+		Vertex* v = stack[stack.size() - 1];
+		stack.pop_back();
+		Edge* e = v->edges;
+		if (e)
+		{
+			do
+			{
+				if (e->target->copy != stamp)
+				{
+					e->target->copy = stamp;
+					stack.push_back(e->target);
+				}
+				if (e->copy != stamp)
+				{
+					Face* face = facePool.newObject();
+					face->init(e->target, e->reverse->prev->target, v);
+					faces.push_back(face);
+					Edge* f = e;
+
+					Vertex* a = NULL;
+					Vertex* b = NULL;
+					do
+					{
+						if (a && b)
+						{
+							int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
+							btAssert(vol >= 0);
+							Point32 c = v->point + a->point + b->point + ref;
+							hullCenterX += vol * c.x;
+							hullCenterY += vol * c.y;
+							hullCenterZ += vol * c.z;
+							volume += vol;
+						}
+
+						btAssert(f->copy != stamp);
+						f->copy = stamp;
+						f->face = face;
+
+						a = b;
+						b = f->target;
+
+						f = f->reverse->prev;
+					} while (f != e);
+				}
+				e = e->next;
+			} while (e != v->edges);
+		}
+	}
+
+	if (volume.getSign() <= 0)
+	{
+		return 0;
+	}
+
+	btVector3 hullCenter;
+	hullCenter[medAxis] = hullCenterX.toScalar();
+	hullCenter[maxAxis] = hullCenterY.toScalar();
+	hullCenter[minAxis] = hullCenterZ.toScalar();
+	hullCenter /= 4 * volume.toScalar();
+	hullCenter *= scaling;
+
+	int faceCount = faces.size();
+
+	if (clampAmount > 0)
+	{
+		btScalar minDist = SIMD_INFINITY;
+		for (int i = 0; i < faceCount; i++)
+		{
+			btVector3 normal = getBtNormal(faces[i]);
+			btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
+			if (dist < minDist)
+			{
+				minDist = dist;
+			}
+		}
+		
+		if (minDist <= 0)
+		{
+			return 0;
+		}
+
+		amount = btMin(amount, minDist * clampAmount);
+	}
+
+	unsigned int seed = 243703;
+	for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
+	{
+		btSwap(faces[i], faces[seed % faceCount]);
+	}
+
+	for (int i = 0; i < faceCount; i++)
+	{
+		if (!shiftFace(faces[i], amount, stack))
+		{
+			return -amount;
+		}
+	}
+
+	return amount;
+}
+
+bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack)
+{
+	btVector3 origShift = getBtNormal(face) * -amount;
+	if (scaling[0] > 0)
+	{
+		origShift[0] /= scaling[0];
+	}
+	if (scaling[1] > 0)
+	{
+		origShift[1] /= scaling[1];
+	}
+	if (scaling[2] > 0)
+	{
+		origShift[2] /= scaling[2];
+	}
+	Point32 shift((int32_t) origShift[medAxis], (int32_t) origShift[maxAxis], (int32_t) origShift[minAxis]);
+	if (shift.isZero())
+	{
+		return true;
+	}
+	Point64 normal = face->getNormal();
+#ifdef DEBUG_CONVEX_HULL
+	printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
+				 face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
+#endif
+	int64_t origDot = face->origin.dot(normal);
+	Point32 shiftedOrigin = face->origin + shift;
+	int64_t shiftedDot = shiftedOrigin.dot(normal);
+	btAssert(shiftedDot <= origDot);
+	if (shiftedDot >= origDot)
+	{
+		return false;
+	}
+
+	Edge* intersection = NULL;
+
+	Edge* startEdge = face->nearbyVertex->edges;
+#ifdef DEBUG_CONVEX_HULL
+	printf("Start edge is ");
+	startEdge->print();
+	printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
+#endif
+	Rational128 optDot = face->nearbyVertex->dot(normal);
+	int cmp = optDot.compare(shiftedDot);
+#ifdef SHOW_ITERATIONS
+	int n = 0;
+#endif
+	if (cmp >= 0)
+	{
+		Edge* e = startEdge;
+		do
+		{
+#ifdef SHOW_ITERATIONS
+			n++;
+#endif
+			Rational128 dot = e->target->dot(normal);
+			btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+			printf("Moving downwards, edge is ");
+			e->print();
+			printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+#endif
+			if (dot.compare(optDot) < 0)
+			{
+				int c = dot.compare(shiftedDot);
+				optDot = dot;
+				e = e->reverse;
+				startEdge = e;
+				if (c < 0)
+				{
+					intersection = e;
+					break;
+				}
+				cmp = c;
+			}
+			e = e->prev;
+		} while (e != startEdge);
+
+		if (!intersection)
+		{
+			return false;
+		}
+	}
+	else
+	{
+		Edge* e = startEdge;
+		do
+		{
+#ifdef SHOW_ITERATIONS
+			n++;
+#endif
+			Rational128 dot = e->target->dot(normal);
+			btAssert(dot.compare(origDot) <= 0);
+#ifdef DEBUG_CONVEX_HULL
+			printf("Moving upwards, edge is ");
+			e->print();
+			printf(", dot is %f (%f %lld)\n", (float) dot.toScalar(), (float) optDot.toScalar(), shiftedDot);
+#endif
+			if (dot.compare(optDot) > 0)
+			{
+				cmp = dot.compare(shiftedDot);
+				if (cmp >= 0)
+				{
+					intersection = e;
+					break;
+				}
+				optDot = dot;
+				e = e->reverse;
+				startEdge = e;
+			}
+			e = e->prev;
+		} while (e != startEdge);
+		
+		if (!intersection)
+		{
+			return true;
+		}
+	}
+
+#ifdef SHOW_ITERATIONS
+	printf("Needed %d iterations to find initial intersection\n", n);
+#endif
+
+	if (cmp == 0)
+	{
+		Edge* e = intersection->reverse->next;
+#ifdef SHOW_ITERATIONS
+		n = 0;
+#endif
+		while (e->target->dot(normal).compare(shiftedDot) <= 0)
+		{
+#ifdef SHOW_ITERATIONS
+			n++;
+#endif
+			e = e->next;
+			if (e == intersection->reverse)
+			{
+				return true;
+			}
+#ifdef DEBUG_CONVEX_HULL
+			printf("Checking for outwards edge, current edge is ");
+			e->print();
+			printf("\n");
+#endif
+		}
+#ifdef SHOW_ITERATIONS
+		printf("Needed %d iterations to check for complete containment\n", n);
+#endif
+	}
+	
+	Edge* firstIntersection = NULL;
+	Edge* faceEdge = NULL;
+	Edge* firstFaceEdge = NULL;
+
+#ifdef SHOW_ITERATIONS
+	int m = 0;
+#endif
+	while (true)
+	{
+#ifdef SHOW_ITERATIONS
+		m++;
+#endif
+#ifdef DEBUG_CONVEX_HULL
+		printf("Intersecting edge is ");
+		intersection->print();
+		printf("\n");
+#endif
+		if (cmp == 0)
+		{
+			Edge* e = intersection->reverse->next;
+			startEdge = e;
+#ifdef SHOW_ITERATIONS
+			n = 0;
+#endif
+			while (true)
+			{
+#ifdef SHOW_ITERATIONS
+				n++;
+#endif
+				if (e->target->dot(normal).compare(shiftedDot) >= 0)
+				{
+					break;
+				}
+				intersection = e->reverse;
+				e = e->next;
+				if (e == startEdge)
+				{
+					return true;
+				}
+			}
+#ifdef SHOW_ITERATIONS
+			printf("Needed %d iterations to advance intersection\n", n);
+#endif
+		}
+
+#ifdef DEBUG_CONVEX_HULL
+		printf("Advanced intersecting edge to ");
+		intersection->print();
+		printf(", cmp = %d\n", cmp);
+#endif
+
+		if (!firstIntersection)
+		{
+			firstIntersection = intersection;
+		}
+		else if (intersection == firstIntersection)
+		{
+			break;
+		}
+
+		int prevCmp = cmp;
+		Edge* prevIntersection = intersection;
+		Edge* prevFaceEdge = faceEdge;
+
+		Edge* e = intersection->reverse;
+#ifdef SHOW_ITERATIONS
+		n = 0;
+#endif
+		while (true)
+		{
+#ifdef SHOW_ITERATIONS
+			n++;
+#endif
+			e = e->reverse->prev;
+			btAssert(e != intersection->reverse);
+			cmp = e->target->dot(normal).compare(shiftedDot);
+#ifdef DEBUG_CONVEX_HULL
+			printf("Testing edge ");
+			e->print();
+			printf(" -> cmp = %d\n", cmp);
+#endif
+			if (cmp >= 0)
+			{
+				intersection = e;
+				break;
+			}
+		}
+#ifdef SHOW_ITERATIONS
+		printf("Needed %d iterations to find other intersection of face\n", n);
+#endif
+
+		if (cmp > 0)
+		{
+			Vertex* removed = intersection->target;
+			e = intersection->reverse;
+			if (e->prev == e)
+			{
+				removed->edges = NULL;
+			}
+			else
+			{
+				removed->edges = e->prev;
+				e->prev->link(e->next);
+				e->link(e);
+			}
+#ifdef DEBUG_CONVEX_HULL
+			printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+			
+			Point64 n0 = intersection->face->getNormal();
+			Point64 n1 = intersection->reverse->face->getNormal();
+			int64_t m00 = face->dir0.dot(n0);
+			int64_t m01 = face->dir1.dot(n0);
+			int64_t m10 = face->dir0.dot(n1);
+			int64_t m11 = face->dir1.dot(n1);
+			int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
+			int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
+			Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
+			btAssert(det.getSign() != 0);
+			Vertex* v = vertexPool.newObject();
+			v->point.index = -1;
+			v->copy = -1;
+			v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01)
+															+ Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
+															Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01)
+															+ Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
+															Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01)
+															+ Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
+															det);
+			v->point.x = (int32_t) v->point128.xvalue();
+			v->point.y = (int32_t) v->point128.yvalue();
+			v->point.z = (int32_t) v->point128.zvalue();
+			intersection->target = v;
+			v->edges = e;
+
+			stack.push_back(v);
+			stack.push_back(removed);
+			stack.push_back(NULL);
+		}
+
+		if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
+		{
+			faceEdge = newEdgePair(prevIntersection->target, intersection->target);
+			if (prevCmp == 0)
+			{
+				faceEdge->link(prevIntersection->reverse->next);
+			}
+			if ((prevCmp == 0) || prevFaceEdge)
+			{
+				prevIntersection->reverse->link(faceEdge);
+			}
+			if (cmp == 0)
+			{
+				intersection->reverse->prev->link(faceEdge->reverse);
+			}
+			faceEdge->reverse->link(intersection->reverse);
+		}
+		else
+		{
+			faceEdge = prevIntersection->reverse->next;
+		}
+
+		if (prevFaceEdge)
+		{
+			if (prevCmp > 0)
+			{
+				faceEdge->link(prevFaceEdge->reverse);
+			}
+			else if (faceEdge != prevFaceEdge->reverse)
+			{
+				stack.push_back(prevFaceEdge->target);
+				while (faceEdge->next != prevFaceEdge->reverse)
+				{
+					Vertex* removed = faceEdge->next->target;
+					removeEdgePair(faceEdge->next);
+					stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+					printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+				}
+				stack.push_back(NULL);
+			}
+		}
+		faceEdge->face = face;
+		faceEdge->reverse->face = intersection->face;
+
+		if (!firstFaceEdge)
+		{
+			firstFaceEdge = faceEdge;
+		}
+	}
+#ifdef SHOW_ITERATIONS
+	printf("Needed %d iterations to process all intersections\n", m);
+#endif
+
+	if (cmp > 0)
+	{
+		firstFaceEdge->reverse->target = faceEdge->target;
+		firstIntersection->reverse->link(firstFaceEdge);
+		firstFaceEdge->link(faceEdge->reverse);
+	}
+	else if (firstFaceEdge != faceEdge->reverse)
+	{
+		stack.push_back(faceEdge->target);
+		while (firstFaceEdge->next != faceEdge->reverse)
+		{
+			Vertex* removed = firstFaceEdge->next->target;
+			removeEdgePair(firstFaceEdge->next);
+			stack.push_back(removed);
+#ifdef DEBUG_CONVEX_HULL
+			printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
+#endif
+		}
+		stack.push_back(NULL);
+	}
+
+	btAssert(stack.size() > 0);
+	vertexList = stack[0];
+
+#ifdef DEBUG_CONVEX_HULL
+	printf("Removing part\n");
+#endif
+#ifdef SHOW_ITERATIONS
+	n = 0;
+#endif
+	int pos = 0;
+	while (pos < stack.size())
+	{
+		int end = stack.size();
+		while (pos < end)
+		{
+			Vertex* kept = stack[pos++];
+#ifdef DEBUG_CONVEX_HULL
+			kept->print();
+#endif
+			bool deeper = false;
+			Vertex* removed;
+			while ((removed = stack[pos++]) != NULL)
+			{
+#ifdef SHOW_ITERATIONS
+				n++;
+#endif
+				kept->receiveNearbyFaces(removed);
+				while (removed->edges)
+				{
+					if (!deeper)
+					{
+						deeper = true;
+						stack.push_back(kept);
+					}
+					stack.push_back(removed->edges->target);
+					removeEdgePair(removed->edges);
+				}
+			}
+			if (deeper)
+			{
+				stack.push_back(NULL);
+			}
+		}
+	}
+#ifdef SHOW_ITERATIONS
+	printf("Needed %d iterations to remove part\n", n);
+#endif
+
+	stack.resize(0);
+	face->origin = shiftedOrigin;
+
+	return true;
+}
+
+
+static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
+{
+	int index = vertex->copy;
+	if (index < 0)
+	{
+		index = vertices.size();
+		vertex->copy = index;
+		vertices.push_back(vertex);
+#ifdef DEBUG_CONVEX_HULL
+		printf("Vertex %d gets index *%d\n", vertex->point.index, index);
+#endif
+	}
+	return index;
+}
+
+btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+{
+	if (count <= 0)
+	{
+		vertices.clear();
+		edges.clear();
+		faces.clear();
+		return 0;
+	}
+
+	btConvexHullInternal hull;
+	hull.compute(coords, doubleCoords, stride, count);
+
+	btScalar shift = 0;
+	if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
+	{
+		vertices.clear();
+		edges.clear();
+		faces.clear();
+		return shift;
+	}
+
+	vertices.resize(0);
+	edges.resize(0);
+	faces.resize(0);
+
+	btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices;
+	getVertexCopy(hull.vertexList, oldVertices);
+	int copied = 0;
+	while (copied < oldVertices.size())
+	{
+		btConvexHullInternal::Vertex* v = oldVertices[copied];
+		vertices.push_back(hull.getCoordinates(v));
+		btConvexHullInternal::Edge* firstEdge = v->edges;
+		if (firstEdge)
+		{
+			int firstCopy = -1;
+			int prevCopy = -1;
+			btConvexHullInternal::Edge* e = firstEdge;
+			do
+			{
+				if (e->copy < 0)
+				{
+					int s = edges.size();
+					edges.push_back(Edge());
+					edges.push_back(Edge());
+					Edge* c = &edges[s];
+					Edge* r = &edges[s + 1];
+					e->copy = s;
+					e->reverse->copy = s + 1;
+					c->reverse = 1;
+					r->reverse = -1;
+					c->targetVertex = getVertexCopy(e->target, oldVertices);
+					r->targetVertex = copied;
+#ifdef DEBUG_CONVEX_HULL
+					printf("      CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
+#endif
+				}
+				if (prevCopy >= 0)
+				{
+					edges[e->copy].next = prevCopy - e->copy;
+				}
+				else
+				{
+					firstCopy = e->copy;
+				}
+				prevCopy = e->copy;
+				e = e->next;
+			} while (e != firstEdge);
+			edges[firstCopy].next = prevCopy - firstCopy;
+		}
+		copied++;
+	}
+
+	for (int i = 0; i < copied; i++)
+	{
+		btConvexHullInternal::Vertex* v = oldVertices[i];
+		btConvexHullInternal::Edge* firstEdge = v->edges;
+		if (firstEdge)
+		{
+			btConvexHullInternal::Edge* e = firstEdge;
+			do
+			{
+				if (e->copy >= 0)
+				{
+#ifdef DEBUG_CONVEX_HULL
+					printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
+#endif
+					faces.push_back(e->copy);
+					btConvexHullInternal::Edge* f = e;
+					do
+					{
+#ifdef DEBUG_CONVEX_HULL
+						printf("   Face *%d\n", edges[f->copy].getTargetVertex());
+#endif
+						f->copy = -1;
+						f = f->reverse->prev;
+					} while (f != e);
+				}
+				e = e->next;
+			} while (e != firstEdge);
+		}
+	}
+
+	return shift;
+}
+
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHullComputer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHullComputer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btConvexHullComputer.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_HULL_COMPUTER_H
+#define BT_CONVEX_HULL_COMPUTER_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+/// Convex hull implementation based on Preparata and Hong
+/// See http://code.google.com/p/bullet/issues/detail?id=275
+/// Ole Kniemeyer, MAXON Computer GmbH
+class btConvexHullComputer
+{
+	private:
+		btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
+
+	public:
+
+		class Edge
+		{
+			private:
+				int next;
+				int reverse;
+				int targetVertex;
+
+				friend class btConvexHullComputer;
+
+			public:
+				int getSourceVertex() const
+				{
+					return (this + reverse)->targetVertex;
+				}
+
+				int getTargetVertex() const
+				{
+					return targetVertex;
+				}
+
+				const Edge* getNextEdgeOfVertex() const // counter-clockwise list of all edges of a vertex
+				{
+					return this + next;
+				}
+
+				const Edge* getNextEdgeOfFace() const // clockwise list of all edges of a face
+				{
+					return (this + reverse)->getNextEdgeOfVertex();
+				}
+
+				const Edge* getReverseEdge() const
+				{
+					return this + reverse;
+				}
+		};
+
+
+		// Vertices of the output hull
+		btAlignedObjectArray<btVector3> vertices;
+
+		// Edges of the output hull
+		btAlignedObjectArray<Edge> edges;
+
+		// Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
+		btAlignedObjectArray<int> faces;
+
+		/*
+		Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
+		between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
+		by that amount (each face is moved by "shrink" length units towards the center along its normal).
+		If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
+		is the minimum distance of a face to the center of the convex hull.
+
+		The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
+		that the resulting convex hull is empty.
+
+		The output convex hull can be found in the member variables "vertices", "edges", "faces".
+		*/
+		btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+		{
+			return compute(coords, false, stride, count, shrink, shrinkClamp);
+		}
+
+		// same as above, but double precision
+		btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
+		{
+			return compute(coords, true, stride, count, shrink, shrinkClamp);
+		}
+};
+
+
+#endif //BT_CONVEX_HULL_COMPUTER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btDefaultMotionState.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btDefaultMotionState.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btDefaultMotionState.h	(revision 11817)
@@ -0,0 +1,40 @@
+#ifndef BT_DEFAULT_MOTION_STATE_H
+#define BT_DEFAULT_MOTION_STATE_H
+
+#include "btMotionState.h"
+
+///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
+struct	btDefaultMotionState : public btMotionState
+{
+	btTransform m_graphicsWorldTrans;
+	btTransform	m_centerOfMassOffset;
+	btTransform m_startWorldTrans;
+	void*		m_userPointer;
+
+	btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
+		: m_graphicsWorldTrans(startTrans),
+		m_centerOfMassOffset(centerOfMassOffset),
+		m_startWorldTrans(startTrans),
+		m_userPointer(0)
+
+	{
+	}
+
+	///synchronizes world transform from user to physics
+	virtual void	getWorldTransform(btTransform& centerOfMassWorldTrans ) const 
+	{
+			centerOfMassWorldTrans = 	m_centerOfMassOffset.inverse() * m_graphicsWorldTrans ;
+	}
+
+	///synchronizes world transform from physics to user
+	///Bullet only calls the update of worldtransform for active objects
+	virtual void	setWorldTransform(const btTransform& centerOfMassWorldTrans)
+	{
+			m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset ;
+	}
+
+	
+
+};
+
+#endif //BT_DEFAULT_MOTION_STATE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btGeometryUtil.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btGeometryUtil.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btGeometryUtil.cpp	(revision 11817)
@@ -0,0 +1,185 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btGeometryUtil.h"
+
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C"
+{	
+	void btBulletMathProbe ();
+
+	void btBulletMathProbe () {}
+}
+
+
+bool	btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar	margin)
+{
+	int numbrushes = planeEquations.size();
+	for (int i=0;i<numbrushes;i++)
+	{
+		const btVector3& N1 = planeEquations[i];
+		btScalar dist = btScalar(N1.dot(point))+btScalar(N1[3])-margin;
+		if (dist>btScalar(0.))
+		{
+			return false;
+		}
+	}
+	return true;
+		
+}
+
+
+bool	btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar	margin)
+{
+	int numvertices = vertices.size();
+	for (int i=0;i<numvertices;i++)
+	{
+		const btVector3& N1 = vertices[i];
+		btScalar dist = btScalar(planeNormal.dot(N1))+btScalar(planeNormal[3])-margin;
+		if (dist>btScalar(0.))
+		{
+			return false;
+		}
+	}
+	return true;
+}
+
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
+
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
+{
+	int numbrushes = planeEquations.size();
+	for (int i=0;i<numbrushes;i++)
+	{
+		const btVector3& N1 = planeEquations[i];
+		if (planeEquation.dot(N1) > btScalar(0.999))
+		{
+			return false;
+		} 
+	}
+	return true;
+}
+
+void	btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut )
+{
+		const int numvertices = vertices.size();
+	// brute force:
+	for (int i=0;i<numvertices;i++)
+	{
+		const btVector3& N1 = vertices[i];
+		
+
+		for (int j=i+1;j<numvertices;j++)
+		{
+			const btVector3& N2 = vertices[j];
+				
+			for (int k=j+1;k<numvertices;k++)
+			{
+
+				const btVector3& N3 = vertices[k];
+
+				btVector3 planeEquation,edge0,edge1;
+				edge0 = N2-N1;
+				edge1 = N3-N1;
+				btScalar normalSign = btScalar(1.);
+				for (int ww=0;ww<2;ww++)
+				{
+					planeEquation = normalSign * edge0.cross(edge1);
+					if (planeEquation.length2() > btScalar(0.0001))
+					{
+						planeEquation.normalize();
+						if (notExist(planeEquation,planeEquationsOut))
+						{
+							planeEquation[3] = -planeEquation.dot(N1);
+							
+								//check if inside, and replace supportingVertexOut if needed
+								if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01)))
+								{
+									planeEquationsOut.push_back(planeEquation);
+								}
+						}
+					}
+					normalSign = btScalar(-1.);
+				}
+			
+			}
+		}
+	}
+
+}
+
+void	btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut )
+{
+	const int numbrushes = planeEquations.size();
+	// brute force:
+	for (int i=0;i<numbrushes;i++)
+	{
+		const btVector3& N1 = planeEquations[i];
+		
+
+		for (int j=i+1;j<numbrushes;j++)
+		{
+			const btVector3& N2 = planeEquations[j];
+				
+			for (int k=j+1;k<numbrushes;k++)
+			{
+
+				const btVector3& N3 = planeEquations[k];
+
+				btVector3 n2n3; n2n3 = N2.cross(N3);
+				btVector3 n3n1; n3n1 = N3.cross(N1);
+				btVector3 n1n2; n1n2 = N1.cross(N2);
+				
+				if ( ( n2n3.length2() > btScalar(0.0001) ) &&
+					 ( n3n1.length2() > btScalar(0.0001) ) &&
+					 ( n1n2.length2() > btScalar(0.0001) ) )
+				{
+					//point P out of 3 plane equations:
+
+					//	d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )  
+					//P =  -------------------------------------------------------------------------  
+					//   N1 . ( N2 * N3 )  
+
+
+					btScalar quotient = (N1.dot(n2n3));
+					if (btFabs(quotient) > btScalar(0.000001))
+					{
+						quotient = btScalar(-1.) / quotient;
+						n2n3 *= N1[3];
+						n3n1 *= N2[3];
+						n1n2 *= N3[3];
+						btVector3 potentialVertex = n2n3;
+						potentialVertex += n3n1;
+						potentialVertex += n1n2;
+						potentialVertex *= quotient;
+
+						//check if inside, and replace supportingVertexOut if needed
+						if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01)))
+						{
+							verticesOut.push_back(potentialVertex);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btGeometryUtil.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btGeometryUtil.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btGeometryUtil.h	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_GEOMETRY_UTIL_H
+#define BT_GEOMETRY_UTIL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
+class btGeometryUtil
+{
+	public:
+	
+	
+		static void	getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut );
+
+		static void	getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut );
+	
+		static bool	isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar	margin);
+		
+		static bool	isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar	margin);
+
+		static bool	areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar	margin);
+
+};
+
+
+#endif //BT_GEOMETRY_UTIL_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btHashMap.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btHashMap.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btHashMap.h	(revision 11817)
@@ -0,0 +1,450 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_HASH_MAP_H
+#define BT_HASH_MAP_H
+
+#include "btAlignedObjectArray.h"
+
+///very basic hashable string implementation, compatible with btHashMap
+struct btHashString
+{
+	const char* m_string;
+	unsigned int	m_hash;
+
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		return m_hash;
+	}
+
+	btHashString(const char* name)
+		:m_string(name)
+	{
+		/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
+		static const unsigned int  InitialFNV = 2166136261u;
+		static const unsigned int FNVMultiple = 16777619u;
+
+		/* Fowler / Noll / Vo (FNV) Hash */
+		unsigned int hash = InitialFNV;
+		
+		for(int i = 0; m_string[i]; i++)
+		{
+			hash = hash ^ (m_string[i]);       /* xor  the low 8 bits */
+			hash = hash * FNVMultiple;  /* multiply by the magic number */
+		}
+		m_hash = hash;
+	}
+
+	int portableStringCompare(const char* src,	const char* dst) const
+	{
+			int ret = 0 ;
+
+			while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+					++src, ++dst;
+
+			if ( ret < 0 )
+					ret = -1 ;
+			else if ( ret > 0 )
+					ret = 1 ;
+
+			return( ret );
+	}
+
+	bool equals(const btHashString& other) const
+	{
+		return (m_string == other.m_string) ||
+			(0==portableStringCompare(m_string,other.m_string));
+
+	}
+
+};
+
+const int BT_HASH_NULL=0xffffffff;
+
+
+class btHashInt
+{
+	int	m_uid;
+public:
+	btHashInt(int uid)	:m_uid(uid)
+	{
+	}
+
+	int	getUid1() const
+	{
+		return m_uid;
+	}
+
+	void	setUid1(int uid)
+	{
+		m_uid = uid;
+	}
+
+	bool equals(const btHashInt& other) const
+	{
+		return getUid1() == other.getUid1();
+	}
+	//to our success
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		int key = m_uid;
+		// Thomas Wang's hash
+		key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+		return key;
+	}
+};
+
+
+
+class btHashPtr
+{
+
+	union
+	{
+		const void*	m_pointer;
+		int	m_hashValues[2];
+	};
+
+public:
+
+	btHashPtr(const void* ptr)
+		:m_pointer(ptr)
+	{
+	}
+
+	const void*	getPointer() const
+	{
+		return m_pointer;
+	}
+
+	bool equals(const btHashPtr& other) const
+	{
+		return getPointer() == other.getPointer();
+	}
+
+	//to our success
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		const bool VOID_IS_8 = ((sizeof(void*)==8));
+		
+		int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
+	
+		// Thomas Wang's hash
+		key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+		return key;
+	}
+
+	
+};
+
+
+template <class Value>
+class btHashKeyPtr
+{
+        int     m_uid;
+public:
+
+        btHashKeyPtr(int uid)    :m_uid(uid)
+        {
+        }
+
+        int     getUid1() const
+        {
+                return m_uid;
+        }
+
+        bool equals(const btHashKeyPtr<Value>& other) const
+        {
+                return getUid1() == other.getUid1();
+        }
+
+        //to our success
+        SIMD_FORCE_INLINE       unsigned int getHash()const
+        {
+                int key = m_uid;
+                // Thomas Wang's hash
+                key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+                return key;
+        }
+
+        
+};
+
+
+template <class Value>
+class btHashKey
+{
+	int	m_uid;
+public:
+
+	btHashKey(int uid)	:m_uid(uid)
+	{
+	}
+
+	int	getUid1() const
+	{
+		return m_uid;
+	}
+
+	bool equals(const btHashKey<Value>& other) const
+	{
+		return getUid1() == other.getUid1();
+	}
+	//to our success
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		int key = m_uid;
+		// Thomas Wang's hash
+		key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+		return key;
+	}
+};
+
+
+///The btHashMap template class implements a generic and lightweight hashmap.
+///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
+template <class Key, class Value>
+class btHashMap
+{
+
+protected:
+	btAlignedObjectArray<int>		m_hashTable;
+	btAlignedObjectArray<int>		m_next;
+	
+	btAlignedObjectArray<Value>		m_valueArray;
+	btAlignedObjectArray<Key>		m_keyArray;
+
+	void	growTables(const Key& /*key*/)
+	{
+		int newCapacity = m_valueArray.capacity();
+
+		if (m_hashTable.size() < newCapacity)
+		{
+			//grow hashtable and next table
+			int curHashtableSize = m_hashTable.size();
+
+			m_hashTable.resize(newCapacity);
+			m_next.resize(newCapacity);
+
+			int i;
+
+			for (i= 0; i < newCapacity; ++i)
+			{
+				m_hashTable[i] = BT_HASH_NULL;
+			}
+			for (i = 0; i < newCapacity; ++i)
+			{
+				m_next[i] = BT_HASH_NULL;
+			}
+
+			for(i=0;i<curHashtableSize;i++)
+			{
+				//const Value& value = m_valueArray[i];
+				//const Key& key = m_keyArray[i];
+
+				int	hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1);	// New hash value with new mask
+				m_next[i] = m_hashTable[hashValue];
+				m_hashTable[hashValue] = i;
+			}
+
+
+		}
+	}
+
+	public:
+
+	void insert(const Key& key, const Value& value) {
+		int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+		//replace value if the key is already there
+		int index = findIndex(key);
+		if (index != BT_HASH_NULL)
+		{
+			m_valueArray[index]=value;
+			return;
+		}
+
+		int count = m_valueArray.size();
+		int oldCapacity = m_valueArray.capacity();
+		m_valueArray.push_back(value);
+		m_keyArray.push_back(key);
+
+		int newCapacity = m_valueArray.capacity();
+		if (oldCapacity < newCapacity)
+		{
+			growTables(key);
+			//hash with new capacity
+			hash = key.getHash() & (m_valueArray.capacity()-1);
+		}
+		m_next[count] = m_hashTable[hash];
+		m_hashTable[hash] = count;
+	}
+
+	void remove(const Key& key) {
+
+		int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+		int pairIndex = findIndex(key);
+		
+		if (pairIndex ==BT_HASH_NULL)
+		{
+			return;
+		}
+
+		// Remove the pair from the hash table.
+		int index = m_hashTable[hash];
+		btAssert(index != BT_HASH_NULL);
+
+		int previous = BT_HASH_NULL;
+		while (index != pairIndex)
+		{
+			previous = index;
+			index = m_next[index];
+		}
+
+		if (previous != BT_HASH_NULL)
+		{
+			btAssert(m_next[previous] == pairIndex);
+			m_next[previous] = m_next[pairIndex];
+		}
+		else
+		{
+			m_hashTable[hash] = m_next[pairIndex];
+		}
+
+		// We now move the last pair into spot of the
+		// pair being removed. We need to fix the hash
+		// table indices to support the move.
+
+		int lastPairIndex = m_valueArray.size() - 1;
+
+		// If the removed pair is the last pair, we are done.
+		if (lastPairIndex == pairIndex)
+		{
+			m_valueArray.pop_back();
+			m_keyArray.pop_back();
+			return;
+		}
+
+		// Remove the last pair from the hash table.
+		int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
+
+		index = m_hashTable[lastHash];
+		btAssert(index != BT_HASH_NULL);
+
+		previous = BT_HASH_NULL;
+		while (index != lastPairIndex)
+		{
+			previous = index;
+			index = m_next[index];
+		}
+
+		if (previous != BT_HASH_NULL)
+		{
+			btAssert(m_next[previous] == lastPairIndex);
+			m_next[previous] = m_next[lastPairIndex];
+		}
+		else
+		{
+			m_hashTable[lastHash] = m_next[lastPairIndex];
+		}
+
+		// Copy the last pair into the remove pair's spot.
+		m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
+		m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
+
+		// Insert the last pair into the hash table
+		m_next[pairIndex] = m_hashTable[lastHash];
+		m_hashTable[lastHash] = pairIndex;
+
+		m_valueArray.pop_back();
+		m_keyArray.pop_back();
+
+	}
+
+
+	int size() const
+	{
+		return m_valueArray.size();
+	}
+
+	const Value* getAtIndex(int index) const
+	{
+		btAssert(index < m_valueArray.size());
+
+		return &m_valueArray[index];
+	}
+
+	Value* getAtIndex(int index)
+	{
+		btAssert(index < m_valueArray.size());
+
+		return &m_valueArray[index];
+	}
+
+	Value* operator[](const Key& key) {
+		return find(key);
+	}
+
+	const Value*	find(const Key& key) const
+	{
+		int index = findIndex(key);
+		if (index == BT_HASH_NULL)
+		{
+			return NULL;
+		}
+		return &m_valueArray[index];
+	}
+
+	Value*	find(const Key& key)
+	{
+		int index = findIndex(key);
+		if (index == BT_HASH_NULL)
+		{
+			return NULL;
+		}
+		return &m_valueArray[index];
+	}
+
+
+	int	findIndex(const Key& key) const
+	{
+		unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+		if (hash >= (unsigned int)m_hashTable.size())
+		{
+			return BT_HASH_NULL;
+		}
+
+		int index = m_hashTable[hash];
+		while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
+		{
+			index = m_next[index];
+		}
+		return index;
+	}
+
+	void	clear()
+	{
+		m_hashTable.clear();
+		m_next.clear();
+		m_valueArray.clear();
+		m_keyArray.clear();
+	}
+
+};
+
+#endif //BT_HASH_MAP_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btIDebugDraw.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btIDebugDraw.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btIDebugDraw.h	(revision 11817)
@@ -0,0 +1,417 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_IDEBUG_DRAW__H
+#define BT_IDEBUG_DRAW__H
+
+#include "btVector3.h"
+#include "btTransform.h"
+
+
+///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
+///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
+///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
+///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
+class	btIDebugDraw
+{
+	public:
+
+	enum	DebugDrawModes
+	{
+		DBG_NoDebug=0,
+		DBG_DrawWireframe = 1,
+		DBG_DrawAabb=2,
+		DBG_DrawFeaturesText=4,
+		DBG_DrawContactPoints=8,
+		DBG_NoDeactivation=16,
+		DBG_NoHelpText = 32,
+		DBG_DrawText=64,
+		DBG_ProfileTimings = 128,
+		DBG_EnableSatComparison = 256,
+		DBG_DisableBulletLCP = 512,
+		DBG_EnableCCD = 1024,
+		DBG_DrawConstraints = (1 << 11),
+		DBG_DrawConstraintLimits = (1 << 12),
+		DBG_FastWireframe = (1<<13),
+		DBG_MAX_DEBUG_DRAW_MODE
+	};
+
+	virtual ~btIDebugDraw() {};
+
+	virtual void	drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
+		
+	virtual void    drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
+	{
+        (void) toColor;
+		drawLine (from, to, fromColor);
+	}
+
+	virtual void	drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
+	{
+		btVector3 start = transform.getOrigin();
+
+		const btVector3 xoffs = transform.getBasis() * btVector3(radius,0,0);
+		const btVector3 yoffs = transform.getBasis() * btVector3(0,radius,0);
+		const btVector3 zoffs = transform.getBasis() * btVector3(0,0,radius);
+
+		// XY 
+		drawLine(start-xoffs, start+yoffs, color);
+		drawLine(start+yoffs, start+xoffs, color);
+		drawLine(start+xoffs, start-yoffs, color);
+		drawLine(start-yoffs, start-xoffs, color);
+
+		// XZ
+		drawLine(start-xoffs, start+zoffs, color);
+		drawLine(start+zoffs, start+xoffs, color);
+		drawLine(start+xoffs, start-zoffs, color);
+		drawLine(start-zoffs, start-xoffs, color);
+
+		// YZ
+		drawLine(start-yoffs, start+zoffs, color);
+		drawLine(start+zoffs, start+yoffs, color);
+		drawLine(start+yoffs, start-zoffs, color);
+		drawLine(start-zoffs, start-yoffs, color);
+	}
+	
+	virtual void	drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
+	{
+		btTransform tr;
+		tr.setIdentity();
+		tr.setOrigin(p);
+		drawSphere(radius,tr,color);
+	}
+	
+	virtual	void	drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
+	{
+		drawTriangle(v0,v1,v2,color,alpha);
+	}
+	virtual	void	drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
+	{
+		drawLine(v0,v1,color);
+		drawLine(v1,v2,color);
+		drawLine(v2,v0,color);
+	}
+
+	virtual void	drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0;
+
+	virtual void	reportErrorWarning(const char* warningString) = 0;
+
+	virtual void	draw3dText(const btVector3& location,const char* textString) = 0;
+	
+	virtual void	setDebugMode(int debugMode) =0;
+	
+	virtual int		getDebugMode() const = 0;
+
+	virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color)
+	{
+
+		btVector3 halfExtents = (to-from)* 0.5f;
+		btVector3 center = (to+from) *0.5f;
+		int i,j;
+
+		btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
+		for (i=0;i<4;i++)
+		{
+			for (j=0;j<3;j++)
+			{
+				pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],		
+					edgecoord[2]*halfExtents[2]);
+				pa+=center;
+
+				int othercoord = j%3;
+				edgecoord[othercoord]*=-1.f;
+				pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],	
+					edgecoord[2]*halfExtents[2]);
+				pb+=center;
+
+				drawLine(pa,pb,color);
+			}
+			edgecoord = btVector3(-1.f,-1.f,-1.f);
+			if (i<3)
+				edgecoord[i]*=-1.f;
+		}
+	}
+	virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
+	{
+		btVector3 start = transform.getOrigin();
+		drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0));
+		drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0));
+		drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f));
+	}
+
+	virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, 
+				const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
+	{
+		const btVector3& vx = axis;
+		btVector3 vy = normal.cross(axis);
+		btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+		int nSteps = (int)((maxAngle - minAngle) / step);
+		if(!nSteps) nSteps = 1;
+		btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
+		if(drawSect)
+		{
+			drawLine(center, prev, color);
+		}
+		for(int i = 1; i <= nSteps; i++)
+		{
+			btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
+			btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
+			drawLine(prev, next, color);
+			prev = next;
+		}
+		if(drawSect)
+		{
+			drawLine(center, prev, color);
+		}
+	}
+	virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius, 
+		btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f))
+	{
+		btVector3 vA[74];
+		btVector3 vB[74];
+		btVector3 *pvA = vA, *pvB = vB, *pT;
+		btVector3 npole = center + up * radius;
+		btVector3 spole = center - up * radius;
+		btVector3 arcStart;
+		btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+		const btVector3& kv = up;
+		const btVector3& iv = axis;
+		btVector3 jv = kv.cross(iv);
+		bool drawN = false;
+		bool drawS = false;
+		if(minTh <= -SIMD_HALF_PI)
+		{
+			minTh = -SIMD_HALF_PI + step;
+			drawN = true;
+		}
+		if(maxTh >= SIMD_HALF_PI)
+		{
+			maxTh = SIMD_HALF_PI - step;
+			drawS = true;
+		}
+		if(minTh > maxTh)
+		{
+			minTh = -SIMD_HALF_PI + step;
+			maxTh =  SIMD_HALF_PI - step;
+			drawN = drawS = true;
+		}
+		int n_hor = (int)((maxTh - minTh) / step) + 1;
+		if(n_hor < 2) n_hor = 2;
+		btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
+		bool isClosed = false;
+		if(minPs > maxPs)
+		{
+			minPs = -SIMD_PI + step;
+			maxPs =  SIMD_PI;
+			isClosed = true;
+		}
+		else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
+		{
+			isClosed = true;
+		}
+		else
+		{
+			isClosed = false;
+		}
+		int n_vert = (int)((maxPs - minPs) / step) + 1;
+		if(n_vert < 2) n_vert = 2;
+		btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
+		for(int i = 0; i < n_hor; i++)
+		{
+			btScalar th = minTh + btScalar(i) * step_h;
+			btScalar sth = radius * btSin(th);
+			btScalar cth = radius * btCos(th);
+			for(int j = 0; j < n_vert; j++)
+			{
+				btScalar psi = minPs + btScalar(j) * step_v;
+				btScalar sps = btSin(psi);
+				btScalar cps = btCos(psi);
+				pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
+				if(i)
+				{
+					drawLine(pvA[j], pvB[j], color);
+				}
+				else if(drawS)
+				{
+					drawLine(spole, pvB[j], color);
+				}
+				if(j)
+				{
+					drawLine(pvB[j-1], pvB[j], color);
+				}
+				else
+				{
+					arcStart = pvB[j];
+				}
+				if((i == (n_hor - 1)) && drawN)
+				{
+					drawLine(npole, pvB[j], color);
+				}
+				if(isClosed)
+				{
+					if(j == (n_vert-1))
+					{
+						drawLine(arcStart, pvB[j], color);
+					}
+				}
+				else
+				{
+					if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1))))
+					{
+						drawLine(center, pvB[j], color);
+					}
+				}
+			}
+			pT = pvA; pvA = pvB; pvB = pT;
+		}
+	}
+	
+	virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
+	{
+		drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+		drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+		drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+		drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+		drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+	}
+	virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
+	{
+		drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+	}
+
+	virtual void drawCapsule(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+	{
+		btVector3 capStart(0.f,0.f,0.f);
+		capStart[upAxis] = -halfHeight;
+
+		btVector3 capEnd(0.f,0.f,0.f);
+		capEnd[upAxis] = halfHeight;
+
+		// Draw the ends
+		{
+
+			btTransform childTransform = transform;
+			childTransform.getOrigin() = transform * capStart;
+			drawSphere(radius, childTransform, color);
+		}
+
+		{
+			btTransform childTransform = transform;
+			childTransform.getOrigin() = transform * capEnd;
+			drawSphere(radius, childTransform, color);
+		}
+
+		// Draw some additional lines
+		btVector3 start = transform.getOrigin();
+
+		capStart[(upAxis+1)%3] = radius;
+		capEnd[(upAxis+1)%3] = radius;
+		drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+		capStart[(upAxis+1)%3] = -radius;
+		capEnd[(upAxis+1)%3] = -radius;
+		drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+
+		capStart[(upAxis+1)%3] = 0.f;
+		capEnd[(upAxis+1)%3] = 0.f;
+
+		capStart[(upAxis+2)%3] = radius;
+		capEnd[(upAxis+2)%3] = radius;
+		drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+		capStart[(upAxis+2)%3] = -radius;
+		capEnd[(upAxis+2)%3] = -radius;
+		drawLine(start+transform.getBasis() * capStart,start+transform.getBasis() * capEnd, color);
+	}
+
+	virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+	{
+		btVector3 start = transform.getOrigin();
+		btVector3	offsetHeight(0,0,0);
+		offsetHeight[upAxis] = halfHeight;
+		btVector3	offsetRadius(0,0,0);
+		offsetRadius[(upAxis+1)%3] = radius;
+		drawLine(start+transform.getBasis() * (offsetHeight+offsetRadius),start+transform.getBasis() * (-offsetHeight+offsetRadius),color);
+		drawLine(start+transform.getBasis() * (offsetHeight-offsetRadius),start+transform.getBasis() * (-offsetHeight-offsetRadius),color);
+
+		// Drawing top and bottom caps of the cylinder
+		btVector3 yaxis(0,0,0);
+		yaxis[upAxis] = btScalar(1.0);
+		btVector3 xaxis(0,0,0);
+		xaxis[(upAxis+1)%3] = btScalar(1.0);
+		drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+		drawArc(start+transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+	}
+
+	virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
+	{
+
+		btVector3 start = transform.getOrigin();
+
+		btVector3	offsetHeight(0,0,0);
+		offsetHeight[upAxis] = height * btScalar(0.5);
+		btVector3	offsetRadius(0,0,0);
+		offsetRadius[(upAxis+1)%3] = radius;
+		btVector3	offset2Radius(0,0,0);
+		offset2Radius[(upAxis+2)%3] = radius;
+
+		drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offsetRadius),color);
+		drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offsetRadius),color);
+		drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight+offset2Radius),color);
+		drawLine(start+transform.getBasis() * (offsetHeight),start+transform.getBasis() * (-offsetHeight-offset2Radius),color);
+
+		// Drawing the base of the cone
+		btVector3 yaxis(0,0,0);
+		yaxis[upAxis] = btScalar(1.0);
+		btVector3 xaxis(0,0,0);
+		xaxis[(upAxis+1)%3] = btScalar(1.0);
+		drawArc(start-transform.getBasis()*(offsetHeight),transform.getBasis()*yaxis,transform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0);
+	}
+
+	virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color)
+	{
+		btVector3 planeOrigin = planeNormal * planeConst;
+		btVector3 vec0,vec1;
+		btPlaneSpace1(planeNormal,vec0,vec1);
+		btScalar vecLen = 100.f;
+		btVector3 pt0 = planeOrigin + vec0*vecLen;
+		btVector3 pt1 = planeOrigin - vec0*vecLen;
+		btVector3 pt2 = planeOrigin + vec1*vecLen;
+		btVector3 pt3 = planeOrigin - vec1*vecLen;
+		drawLine(transform*pt0,transform*pt1,color);
+		drawLine(transform*pt2,transform*pt3,color);
+	}
+};
+
+
+#endif //BT_IDEBUG_DRAW__H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btList.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btList.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btList.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEN_LIST_H
+#define BT_GEN_LIST_H
+
+class btGEN_Link {
+public:
+    btGEN_Link() : m_next(0), m_prev(0) {}
+    btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
+    
+    btGEN_Link *getNext() const { return m_next; }  
+    btGEN_Link *getPrev() const { return m_prev; }  
+
+    bool isHead() const { return m_prev == 0; }
+    bool isTail() const { return m_next == 0; }
+
+    void insertBefore(btGEN_Link *link) {
+        m_next         = link;
+        m_prev         = link->m_prev;
+        m_next->m_prev = this;
+        m_prev->m_next = this;
+    } 
+
+    void insertAfter(btGEN_Link *link) {
+        m_next         = link->m_next;
+        m_prev         = link;
+        m_next->m_prev = this;
+        m_prev->m_next = this;
+    } 
+
+    void remove() { 
+        m_next->m_prev = m_prev; 
+        m_prev->m_next = m_next;
+    }
+
+private:  
+    btGEN_Link  *m_next;
+    btGEN_Link  *m_prev;
+};
+
+class btGEN_List {
+public:
+    btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+
+    btGEN_Link *getHead() const { return m_head.getNext(); } 
+    btGEN_Link *getTail() const { return m_tail.getPrev(); } 
+
+    void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
+    void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
+    
+private:
+    btGEN_Link m_head;
+    btGEN_Link m_tail;
+};
+
+#endif //BT_GEN_LIST_H
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMatrix3x3.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMatrix3x3.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMatrix3x3.h	(revision 11817)
@@ -0,0 +1,771 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef	BT_MATRIX3x3_H
+#define BT_MATRIX3x3_H
+
+#include "btVector3.h"
+#include "btQuaternion.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btMatrix3x3Data	btMatrix3x3DoubleData 
+#else
+#define btMatrix3x3Data	btMatrix3x3FloatData
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
+* Make sure to only include a pure orthogonal matrix without scaling. */
+class btMatrix3x3 {
+
+	///Data storage for the matrix, each vector is a row of the matrix
+	btVector3 m_el[3];
+
+public:
+	/** @brief No initializaion constructor */
+	btMatrix3x3 () {}
+
+	//		explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
+
+	/**@brief Constructor from Quaternion */
+	explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
+	/*
+	template <typename btScalar>
+	Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{ 
+	setEulerYPR(yaw, pitch, roll);
+	}
+	*/
+	/** @brief Constructor with row major formatting */
+	btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+		const btScalar& yx, const btScalar& yy, const btScalar& yz,
+		const btScalar& zx, const btScalar& zy, const btScalar& zz)
+	{ 
+		setValue(xx, xy, xz, 
+			yx, yy, yz, 
+			zx, zy, zz);
+	}
+	/** @brief Copy constructor */
+	SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
+	{
+		m_el[0] = other.m_el[0];
+		m_el[1] = other.m_el[1];
+		m_el[2] = other.m_el[2];
+	}
+	/** @brief Assignment Operator */
+	SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
+	{
+		m_el[0] = other.m_el[0];
+		m_el[1] = other.m_el[1];
+		m_el[2] = other.m_el[2];
+		return *this;
+	}
+
+	/** @brief Get a column of the matrix as a vector 
+	*  @param i Column number 0 indexed */
+	SIMD_FORCE_INLINE btVector3 getColumn(int i) const
+	{
+		return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
+	}
+
+
+	/** @brief Get a row of the matrix as a vector 
+	*  @param i Row number 0 indexed */
+	SIMD_FORCE_INLINE const btVector3& getRow(int i) const
+	{
+		btFullAssert(0 <= i && i < 3);
+		return m_el[i];
+	}
+
+	/** @brief Get a mutable reference to a row of the matrix as a vector 
+	*  @param i Row number 0 indexed */
+	SIMD_FORCE_INLINE btVector3&  operator[](int i)
+	{ 
+		btFullAssert(0 <= i && i < 3);
+		return m_el[i]; 
+	}
+
+	/** @brief Get a const reference to a row of the matrix as a vector 
+	*  @param i Row number 0 indexed */
+	SIMD_FORCE_INLINE const btVector3& operator[](int i) const
+	{
+		btFullAssert(0 <= i && i < 3);
+		return m_el[i]; 
+	}
+
+	/** @brief Multiply by the target matrix on the right
+	*  @param m Rotation matrix to be applied 
+	* Equivilant to this = this * m */
+	btMatrix3x3& operator*=(const btMatrix3x3& m); 
+
+	/** @brief Adds by the target matrix on the right
+	*  @param m matrix to be applied 
+	* Equivilant to this = this + m */
+	btMatrix3x3& operator+=(const btMatrix3x3& m); 
+
+	/** @brief Substractss by the target matrix on the right
+	*  @param m matrix to be applied 
+	* Equivilant to this = this - m */
+	btMatrix3x3& operator-=(const btMatrix3x3& m); 
+
+	/** @brief Set from the rotational part of a 4x4 OpenGL matrix
+	*  @param m A pointer to the beginning of the array of scalars*/
+	void setFromOpenGLSubMatrix(const btScalar *m)
+	{
+		m_el[0].setValue(m[0],m[4],m[8]);
+		m_el[1].setValue(m[1],m[5],m[9]);
+		m_el[2].setValue(m[2],m[6],m[10]);
+
+	}
+	/** @brief Set the values of the matrix explicitly (row major)
+	*  @param xx Top left
+	*  @param xy Top Middle
+	*  @param xz Top Right
+	*  @param yx Middle Left
+	*  @param yy Middle Middle
+	*  @param yz Middle Right
+	*  @param zx Bottom Left
+	*  @param zy Bottom Middle
+	*  @param zz Bottom Right*/
+	void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, 
+		const btScalar& yx, const btScalar& yy, const btScalar& yz, 
+		const btScalar& zx, const btScalar& zy, const btScalar& zz)
+	{
+		m_el[0].setValue(xx,xy,xz);
+		m_el[1].setValue(yx,yy,yz);
+		m_el[2].setValue(zx,zy,zz);
+	}
+
+	/** @brief Set the matrix from a quaternion
+	*  @param q The Quaternion to match */  
+	void setRotation(const btQuaternion& q) 
+	{
+		btScalar d = q.length2();
+		btFullAssert(d != btScalar(0.0));
+		btScalar s = btScalar(2.0) / d;
+		btScalar xs = q.x() * s,   ys = q.y() * s,   zs = q.z() * s;
+		btScalar wx = q.w() * xs,  wy = q.w() * ys,  wz = q.w() * zs;
+		btScalar xx = q.x() * xs,  xy = q.x() * ys,  xz = q.x() * zs;
+		btScalar yy = q.y() * ys,  yz = q.y() * zs,  zz = q.z() * zs;
+		setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
+			xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
+			xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
+	}
+
+
+	/** @brief Set the matrix from euler angles using YPR around YXZ respectively
+	*  @param yaw Yaw about Y axis
+	*  @param pitch Pitch about X axis
+	*  @param roll Roll about Z axis 
+	*/
+	void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) 
+	{
+		setEulerZYX(roll, pitch, yaw);
+	}
+
+	/** @brief Set the matrix from euler angles YPR around ZYX axes
+	* @param eulerX Roll about X axis
+	* @param eulerY Pitch around Y axis
+	* @param eulerZ Yaw aboud Z axis
+	* 
+	* These angles are used to produce a rotation matrix. The euler
+	* angles are applied in ZYX order. I.e a vector is first rotated 
+	* about X then Y and then Z
+	**/
+	void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { 
+		///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
+		btScalar ci ( btCos(eulerX)); 
+		btScalar cj ( btCos(eulerY)); 
+		btScalar ch ( btCos(eulerZ)); 
+		btScalar si ( btSin(eulerX)); 
+		btScalar sj ( btSin(eulerY)); 
+		btScalar sh ( btSin(eulerZ)); 
+		btScalar cc = ci * ch; 
+		btScalar cs = ci * sh; 
+		btScalar sc = si * ch; 
+		btScalar ss = si * sh;
+
+		setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+			cj * sh, sj * ss + cc, sj * cs - sc, 
+			-sj,      cj * si,      cj * ci);
+	}
+
+	/**@brief Set the matrix to the identity */
+	void setIdentity()
+	{ 
+		setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(1.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(0.0), btScalar(1.0)); 
+	}
+
+	static const btMatrix3x3&	getIdentity()
+	{
+		static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(1.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(0.0), btScalar(1.0));
+		return identityMatrix;
+	}
+
+	/**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
+	* @param m The array to be filled */
+	void getOpenGLSubMatrix(btScalar *m) const 
+	{
+		m[0]  = btScalar(m_el[0].x()); 
+		m[1]  = btScalar(m_el[1].x());
+		m[2]  = btScalar(m_el[2].x());
+		m[3]  = btScalar(0.0); 
+		m[4]  = btScalar(m_el[0].y());
+		m[5]  = btScalar(m_el[1].y());
+		m[6]  = btScalar(m_el[2].y());
+		m[7]  = btScalar(0.0); 
+		m[8]  = btScalar(m_el[0].z()); 
+		m[9]  = btScalar(m_el[1].z());
+		m[10] = btScalar(m_el[2].z());
+		m[11] = btScalar(0.0); 
+	}
+
+	/**@brief Get the matrix represented as a quaternion 
+	* @param q The quaternion which will be set */
+	void getRotation(btQuaternion& q) const
+	{
+		btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+		btScalar temp[4];
+
+		if (trace > btScalar(0.0)) 
+		{
+			btScalar s = btSqrt(trace + btScalar(1.0));
+			temp[3]=(s * btScalar(0.5));
+			s = btScalar(0.5) / s;
+
+			temp[0]=((m_el[2].y() - m_el[1].z()) * s);
+			temp[1]=((m_el[0].z() - m_el[2].x()) * s);
+			temp[2]=((m_el[1].x() - m_el[0].y()) * s);
+		} 
+		else 
+		{
+			int i = m_el[0].x() < m_el[1].y() ? 
+				(m_el[1].y() < m_el[2].z() ? 2 : 1) :
+				(m_el[0].x() < m_el[2].z() ? 2 : 0); 
+			int j = (i + 1) % 3;  
+			int k = (i + 2) % 3;
+
+			btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
+			temp[i] = s * btScalar(0.5);
+			s = btScalar(0.5) / s;
+
+			temp[3] = (m_el[k][j] - m_el[j][k]) * s;
+			temp[j] = (m_el[j][i] + m_el[i][j]) * s;
+			temp[k] = (m_el[k][i] + m_el[i][k]) * s;
+		}
+		q.setValue(temp[0],temp[1],temp[2],temp[3]);
+	}
+
+	/**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
+	* @param yaw Yaw around Y axis
+	* @param pitch Pitch around X axis
+	* @param roll around Z axis */	
+	void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const
+	{
+
+		// first use the normal calculus
+		yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
+		pitch = btScalar(btAsin(-m_el[2].x()));
+		roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
+
+		// on pitch = +/-HalfPI
+		if (btFabs(pitch)==SIMD_HALF_PI)
+		{
+			if (yaw>0)
+				yaw-=SIMD_PI;
+			else
+				yaw+=SIMD_PI;
+
+			if (roll>0)
+				roll-=SIMD_PI;
+			else
+				roll+=SIMD_PI;
+		}
+	};
+
+
+	/**@brief Get the matrix represented as euler angles around ZYX
+	* @param yaw Yaw around X axis
+	* @param pitch Pitch around Y axis
+	* @param roll around X axis 
+	* @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/	
+	void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
+	{
+		struct Euler
+		{
+			btScalar yaw;
+			btScalar pitch;
+			btScalar roll;
+		};
+
+		Euler euler_out;
+		Euler euler_out2; //second solution
+		//get the pointer to the raw data
+
+		// Check that pitch is not at a singularity
+		if (btFabs(m_el[2].x()) >= 1)
+		{
+			euler_out.yaw = 0;
+			euler_out2.yaw = 0;
+
+			// From difference of angles formula
+			btScalar delta = btAtan2(m_el[0].x(),m_el[0].z());
+			if (m_el[2].x() > 0)  //gimbal locked up
+			{
+				euler_out.pitch = SIMD_PI / btScalar(2.0);
+				euler_out2.pitch = SIMD_PI / btScalar(2.0);
+				euler_out.roll = euler_out.pitch + delta;
+				euler_out2.roll = euler_out.pitch + delta;
+			}
+			else // gimbal locked down
+			{
+				euler_out.pitch = -SIMD_PI / btScalar(2.0);
+				euler_out2.pitch = -SIMD_PI / btScalar(2.0);
+				euler_out.roll = -euler_out.pitch + delta;
+				euler_out2.roll = -euler_out.pitch + delta;
+			}
+		}
+		else
+		{
+			euler_out.pitch = - btAsin(m_el[2].x());
+			euler_out2.pitch = SIMD_PI - euler_out.pitch;
+
+			euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch), 
+				m_el[2].z()/btCos(euler_out.pitch));
+			euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch), 
+				m_el[2].z()/btCos(euler_out2.pitch));
+
+			euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch), 
+				m_el[0].x()/btCos(euler_out.pitch));
+			euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch), 
+				m_el[0].x()/btCos(euler_out2.pitch));
+		}
+
+		if (solution_number == 1)
+		{ 
+			yaw = euler_out.yaw; 
+			pitch = euler_out.pitch;
+			roll = euler_out.roll;
+		}
+		else
+		{ 
+			yaw = euler_out2.yaw; 
+			pitch = euler_out2.pitch;
+			roll = euler_out2.roll;
+		}
+	}
+
+	/**@brief Create a scaled copy of the matrix 
+	* @param s Scaling vector The elements of the vector will scale each column */
+
+	btMatrix3x3 scaled(const btVector3& s) const
+	{
+		return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
+			m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
+			m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
+	}
+
+	/**@brief Return the determinant of the matrix */
+	btScalar            determinant() const;
+	/**@brief Return the adjoint of the matrix */
+	btMatrix3x3 adjoint() const;
+	/**@brief Return the matrix with all values non negative */
+	btMatrix3x3 absolute() const;
+	/**@brief Return the transpose of the matrix */
+	btMatrix3x3 transpose() const;
+	/**@brief Return the inverse of the matrix */
+	btMatrix3x3 inverse() const; 
+
+	btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
+	btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
+
+	SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const 
+	{
+		return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
+	}
+	SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const 
+	{
+		return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
+	}
+	SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const 
+	{
+		return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
+	}
+
+
+	/**@brief diagonalizes this matrix by the Jacobi method.
+	* @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
+	* coordinate system, i.e., old_this = rot * new_this * rot^T. 
+	* @param threshold See iteration
+	* @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied 
+	* by the sum of the absolute values of the diagonal, or when maxSteps have been executed. 
+	* 
+	* Note that this matrix is assumed to be symmetric. 
+	*/
+	void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps)
+	{
+		rot.setIdentity();
+		for (int step = maxSteps; step > 0; step--)
+		{
+			// find off-diagonal element [p][q] with largest magnitude
+			int p = 0;
+			int q = 1;
+			int r = 2;
+			btScalar max = btFabs(m_el[0][1]);
+			btScalar v = btFabs(m_el[0][2]);
+			if (v > max)
+			{
+				q = 2;
+				r = 1;
+				max = v;
+			}
+			v = btFabs(m_el[1][2]);
+			if (v > max)
+			{
+				p = 1;
+				q = 2;
+				r = 0;
+				max = v;
+			}
+
+			btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2]));
+			if (max <= t)
+			{
+				if (max <= SIMD_EPSILON * t)
+				{
+					return;
+				}
+				step = 1;
+			}
+
+			// compute Jacobi rotation J which leads to a zero for element [p][q] 
+			btScalar mpq = m_el[p][q];
+			btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
+			btScalar theta2 = theta * theta;
+			btScalar cos;
+			btScalar sin;
+			if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
+			{
+				t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
+					: 1 / (theta - btSqrt(1 + theta2));
+				cos = 1 / btSqrt(1 + t * t);
+				sin = cos * t;
+			}
+			else
+			{
+				// approximation for large theta-value, i.e., a nearly diagonal matrix
+				t = 1 / (theta * (2 + btScalar(0.5) / theta2));
+				cos = 1 - btScalar(0.5) * t * t;
+				sin = cos * t;
+			}
+
+			// apply rotation to matrix (this = J^T * this * J)
+			m_el[p][q] = m_el[q][p] = 0;
+			m_el[p][p] -= t * mpq;
+			m_el[q][q] += t * mpq;
+			btScalar mrp = m_el[r][p];
+			btScalar mrq = m_el[r][q];
+			m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
+			m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
+
+			// apply rotation to rot (rot = rot * J)
+			for (int i = 0; i < 3; i++)
+			{
+				btVector3& row = rot[i];
+				mrp = row[p];
+				mrq = row[q];
+				row[p] = cos * mrp - sin * mrq;
+				row[q] = cos * mrq + sin * mrp;
+			}
+		}
+	}
+
+
+
+
+	/**@brief Calculate the matrix cofactor 
+	* @param r1 The first row to use for calculating the cofactor
+	* @param c1 The first column to use for calculating the cofactor
+	* @param r1 The second row to use for calculating the cofactor
+	* @param c1 The second column to use for calculating the cofactor
+	* See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
+	*/
+	btScalar cofac(int r1, int c1, int r2, int c2) const 
+	{
+		return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+	}
+
+	void	serialize(struct	btMatrix3x3Data& dataOut) const;
+
+	void	serializeFloat(struct	btMatrix3x3FloatData& dataOut) const;
+
+	void	deSerialize(const struct	btMatrix3x3Data& dataIn);
+
+	void	deSerializeFloat(const struct	btMatrix3x3FloatData& dataIn);
+
+	void	deSerializeDouble(const struct	btMatrix3x3DoubleData& dataIn);
+
+};
+
+
+SIMD_FORCE_INLINE btMatrix3x3& 
+btMatrix3x3::operator*=(const btMatrix3x3& m)
+{
+	setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+		m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
+		m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+	return *this;
+}
+
+SIMD_FORCE_INLINE btMatrix3x3& 
+btMatrix3x3::operator+=(const btMatrix3x3& m)
+{
+	setValue(
+		m_el[0][0]+m.m_el[0][0], 
+		m_el[0][1]+m.m_el[0][1],
+		m_el[0][2]+m.m_el[0][2],
+		m_el[1][0]+m.m_el[1][0], 
+		m_el[1][1]+m.m_el[1][1],
+		m_el[1][2]+m.m_el[1][2],
+		m_el[2][0]+m.m_el[2][0], 
+		m_el[2][1]+m.m_el[2][1],
+		m_el[2][2]+m.m_el[2][2]);
+	return *this;
+}
+
+SIMD_FORCE_INLINE btMatrix3x3
+operator*(const btMatrix3x3& m, const btScalar & k)
+{
+	return btMatrix3x3(
+		m[0].x()*k,m[0].y()*k,m[0].z()*k,
+		m[1].x()*k,m[1].y()*k,m[1].z()*k,
+		m[2].x()*k,m[2].y()*k,m[2].z()*k);
+}
+
+ SIMD_FORCE_INLINE btMatrix3x3 
+operator+(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+	return btMatrix3x3(
+	m1[0][0]+m2[0][0], 
+	m1[0][1]+m2[0][1],
+	m1[0][2]+m2[0][2],
+	m1[1][0]+m2[1][0], 
+	m1[1][1]+m2[1][1],
+	m1[1][2]+m2[1][2],
+	m1[2][0]+m2[2][0], 
+	m1[2][1]+m2[2][1],
+	m1[2][2]+m2[2][2]);
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+operator-(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+	return btMatrix3x3(
+	m1[0][0]-m2[0][0], 
+	m1[0][1]-m2[0][1],
+	m1[0][2]-m2[0][2],
+	m1[1][0]-m2[1][0], 
+	m1[1][1]-m2[1][1],
+	m1[1][2]-m2[1][2],
+	m1[2][0]-m2[2][0], 
+	m1[2][1]-m2[2][1],
+	m1[2][2]-m2[2][2]);
+}
+
+
+SIMD_FORCE_INLINE btMatrix3x3& 
+btMatrix3x3::operator-=(const btMatrix3x3& m)
+{
+	setValue(
+	m_el[0][0]-m.m_el[0][0], 
+	m_el[0][1]-m.m_el[0][1],
+	m_el[0][2]-m.m_el[0][2],
+	m_el[1][0]-m.m_el[1][0], 
+	m_el[1][1]-m.m_el[1][1],
+	m_el[1][2]-m.m_el[1][2],
+	m_el[2][0]-m.m_el[2][0], 
+	m_el[2][1]-m.m_el[2][1],
+	m_el[2][2]-m.m_el[2][2]);
+	return *this;
+}
+
+
+SIMD_FORCE_INLINE btScalar 
+btMatrix3x3::determinant() const
+{ 
+	return btTriple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::absolute() const
+{
+	return btMatrix3x3(
+		btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
+		btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
+		btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::transpose() const 
+{
+	return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
+		m_el[0].y(), m_el[1].y(), m_el[2].y(),
+		m_el[0].z(), m_el[1].z(), m_el[2].z());
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::adjoint() const 
+{
+	return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+		cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+		cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::inverse() const
+{
+	btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+	btScalar det = (*this)[0].dot(co);
+	btFullAssert(det != btScalar(0.0));
+	btScalar s = btScalar(1.0) / det;
+	return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+		co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+		co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
+{
+	return btMatrix3x3(
+		m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
+		m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
+		m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
+		m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
+		m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
+		m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
+		m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
+		m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
+		m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
+{
+	return btMatrix3x3(
+		m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+		m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+		m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+
+}
+
+SIMD_FORCE_INLINE btVector3 
+operator*(const btMatrix3x3& m, const btVector3& v) 
+{
+	return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+}
+
+
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btMatrix3x3& m)
+{
+	return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+	return btMatrix3x3(
+		m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
+		m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
+		m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+}
+
+/*
+SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) {
+return btMatrix3x3(
+m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+*/
+
+/**@brief Equality operator between two matrices
+* It will test all elements are equal.  */
+SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+	return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+		m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
+		m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+}
+
+///for serialization
+struct	btMatrix3x3FloatData
+{
+	btVector3FloatData m_el[3];
+};
+
+///for serialization
+struct	btMatrix3x3DoubleData
+{
+	btVector3DoubleData m_el[3];
+};
+
+
+	
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::serialize(struct	btMatrix3x3Data& dataOut) const
+{
+	for (int i=0;i<3;i++)
+		m_el[i].serialize(dataOut.m_el[i]);
+}
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::serializeFloat(struct	btMatrix3x3FloatData& dataOut) const
+{
+	for (int i=0;i<3;i++)
+		m_el[i].serializeFloat(dataOut.m_el[i]);
+}
+
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::deSerialize(const struct	btMatrix3x3Data& dataIn)
+{
+	for (int i=0;i<3;i++)
+		m_el[i].deSerialize(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::deSerializeFloat(const struct	btMatrix3x3FloatData& dataIn)
+{
+	for (int i=0;i<3;i++)
+		m_el[i].deSerializeFloat(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::deSerializeDouble(const struct	btMatrix3x3DoubleData& dataIn)
+{
+	for (int i=0;i<3;i++)
+		m_el[i].deSerializeDouble(dataIn.m_el[i]);
+}
+
+#endif //BT_MATRIX3x3_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMinMax.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMinMax.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMinMax.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEN_MINMAX_H
+#define BT_GEN_MINMAX_H
+
+#include "LinearMath/btScalar.h"
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) 
+{
+  return a < b ? a : b ;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) 
+{
+  return  a > b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub) 
+{
+	return a < lb ? lb : (ub < a ? ub : a); 
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) 
+{
+    if (b < a) 
+	{
+		a = b;
+	}
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) 
+{
+    if (a < b) 
+	{
+		a = b;
+	}
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) 
+{
+	if (a < lb) 
+	{
+		a = lb; 
+	}
+	else if (ub < a) 
+	{
+		a = ub;
+	}
+}
+
+#endif //BT_GEN_MINMAX_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMotionState.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMotionState.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btMotionState.h	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MOTIONSTATE_H
+#define BT_MOTIONSTATE_H
+
+#include "btTransform.h"
+
+///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
+///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
+class	btMotionState
+{
+	public:
+		
+		virtual ~btMotionState()
+		{
+			
+		}
+		
+		virtual void	getWorldTransform(btTransform& worldTrans ) const =0;
+
+		//Bullet only calls the update of worldtransform for active objects
+		virtual void	setWorldTransform(const btTransform& worldTrans)=0;
+		
+	
+};
+
+#endif //BT_MOTIONSTATE_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btPoolAllocator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btPoolAllocator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btPoolAllocator.h	(revision 11817)
@@ -0,0 +1,121 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef _BT_POOL_ALLOCATOR_H
+#define _BT_POOL_ALLOCATOR_H
+
+#include "btScalar.h"
+#include "btAlignedAllocator.h"
+
+///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
+class btPoolAllocator
+{
+	int				m_elemSize;
+	int				m_maxElements;
+	int				m_freeCount;
+	void*			m_firstFree;
+	unsigned char*	m_pool;
+
+public:
+
+	btPoolAllocator(int elemSize, int maxElements)
+		:m_elemSize(elemSize),
+		m_maxElements(maxElements)
+	{
+		m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
+
+		unsigned char* p = m_pool;
+        m_firstFree = p;
+        m_freeCount = m_maxElements;
+        int count = m_maxElements;
+        while (--count) {
+            *(void**)p = (p + m_elemSize);
+            p += m_elemSize;
+        }
+        *(void**)p = 0;
+    }
+
+	~btPoolAllocator()
+	{
+		btAlignedFree( m_pool);
+	}
+
+	int	getFreeCount() const
+	{
+		return m_freeCount;
+	}
+
+	int getUsedCount() const
+	{
+		return m_maxElements - m_freeCount;
+	}
+
+	int getMaxCount() const
+	{
+		return m_maxElements;
+	}
+
+	void*	allocate(int size)
+	{
+		// release mode fix
+		(void)size;
+		btAssert(!size || size<=m_elemSize);
+		btAssert(m_freeCount>0);
+        void* result = m_firstFree;
+        m_firstFree = *(void**)m_firstFree;
+        --m_freeCount;
+        return result;
+	}
+
+	bool validPtr(void* ptr)
+	{
+		if (ptr) {
+			if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
+	void	freeMemory(void* ptr)
+	{
+		 if (ptr) {
+            btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+            *(void**)ptr = m_firstFree;
+            m_firstFree = ptr;
+            ++m_freeCount;
+        }
+	}
+
+	int	getElementSize() const
+	{
+		return m_elemSize;
+	}
+
+	unsigned char*	getPoolAddress()
+	{
+		return m_pool;
+	}
+
+	const unsigned char*	getPoolAddress() const
+	{
+		return m_pool;
+	}
+
+};
+
+#endif //_BT_POOL_ALLOCATOR_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuadWord.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuadWord.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuadWord.h	(revision 11817)
@@ -0,0 +1,180 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_SIMD_QUADWORD_H
+#define BT_SIMD_QUADWORD_H
+
+#include "btScalar.h"
+#include "btMinMax.h"
+
+
+#if defined (__CELLOS_LV2) && defined (__SPU__)
+#include <altivec.h>
+#endif
+
+/**@brief The btQuadWord class is base class for btVector3 and btQuaternion. 
+ * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
+ */
+#ifndef USE_LIBSPE2
+ATTRIBUTE_ALIGNED16(class) btQuadWord
+#else
+class btQuadWord
+#endif
+{
+protected:
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+	union {
+		vec_float4 mVec128;
+		btScalar	m_floats[4];
+	};
+public:
+	vec_float4	get128() const
+	{
+		return mVec128;
+	}
+protected:
+#else //__CELLOS_LV2__ __SPU__
+	btScalar	m_floats[4];
+#endif //__CELLOS_LV2__ __SPU__
+
+	public:
+  
+
+  /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+  /**@brief Set the x value */
+		SIMD_FORCE_INLINE void	setX(btScalar x) { m_floats[0] = x;};
+  /**@brief Set the y value */
+		SIMD_FORCE_INLINE void	setY(btScalar y) { m_floats[1] = y;};
+  /**@brief Set the z value */
+		SIMD_FORCE_INLINE void	setZ(btScalar z) { m_floats[2] = z;};
+  /**@brief Set the w value */
+		SIMD_FORCE_INLINE void	setW(btScalar w) { m_floats[3] = w;};
+  /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+  /**@brief Return the w value */
+		SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+	//SIMD_FORCE_INLINE btScalar&       operator[](int i)       { return (&m_floats[0])[i];	}      
+	//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+	///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+	SIMD_FORCE_INLINE	operator       btScalar *()       { return &m_floats[0]; }
+	SIMD_FORCE_INLINE	operator const btScalar *() const { return &m_floats[0]; }
+
+	SIMD_FORCE_INLINE	bool	operator==(const btQuadWord& other) const
+	{
+		return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
+	}
+
+	SIMD_FORCE_INLINE	bool	operator!=(const btQuadWord& other) const
+	{
+		return !(*this == other);
+	}
+
+  /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+		SIMD_FORCE_INLINE void 	setValue(const btScalar& x, const btScalar& y, const btScalar& z)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3] = 0.f;
+		}
+
+/*		void getValue(btScalar *m) const 
+		{
+			m[0] = m_floats[0];
+			m[1] = m_floats[1];
+			m[2] = m_floats[2];
+		}
+*/
+/**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+		SIMD_FORCE_INLINE void	setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3]=w;
+		}
+  /**@brief No initialization constructor */
+		SIMD_FORCE_INLINE btQuadWord()
+		//	:m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
+		{
+		}
+ 
+  /**@brief Three argument constructor (zeros w)
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+		SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z)		
+		{
+			m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = 0.0f;
+		}
+
+/**@brief Initializing constructor
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+		SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 
+		{
+			m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = w;
+		}
+
+  /**@brief Set each element to the max of the current values and the values of another btQuadWord
+   * @param other The other btQuadWord to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMax(const btQuadWord& other)
+		{
+			btSetMax(m_floats[0], other.m_floats[0]);
+			btSetMax(m_floats[1], other.m_floats[1]);
+			btSetMax(m_floats[2], other.m_floats[2]);
+			btSetMax(m_floats[3], other.m_floats[3]);
+		}
+  /**@brief Set each element to the min of the current values and the values of another btQuadWord
+   * @param other The other btQuadWord to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMin(const btQuadWord& other)
+		{
+			btSetMin(m_floats[0], other.m_floats[0]);
+			btSetMin(m_floats[1], other.m_floats[1]);
+			btSetMin(m_floats[2], other.m_floats[2]);
+			btSetMin(m_floats[3], other.m_floats[3]);
+		}
+
+
+
+};
+
+#endif //BT_SIMD_QUADWORD_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuaternion.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuaternion.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuaternion.h	(revision 11817)
@@ -0,0 +1,433 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_SIMD__QUATERNION_H_
+#define BT_SIMD__QUATERNION_H_
+
+
+#include "btVector3.h"
+#include "btQuadWord.h"
+
+/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
+class btQuaternion : public btQuadWord {
+public:
+  /**@brief No initialization constructor */
+	btQuaternion() {}
+
+	//		template <typename btScalar>
+	//		explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
+  /**@brief Constructor from scalars */
+	btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) 
+		: btQuadWord(x, y, z, w) 
+	{}
+  /**@brief Axis angle Constructor
+   * @param axis The axis which the rotation is around
+   * @param angle The magnitude of the rotation around the angle (Radians) */
+	btQuaternion(const btVector3& axis, const btScalar& angle) 
+	{ 
+		setRotation(axis, angle); 
+	}
+  /**@brief Constructor from Euler angles
+   * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
+   * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
+   * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
+	btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{ 
+#ifndef BT_EULER_DEFAULT_ZYX
+		setEuler(yaw, pitch, roll); 
+#else
+		setEulerZYX(yaw, pitch, roll); 
+#endif 
+	}
+  /**@brief Set the rotation using axis angle notation 
+   * @param axis The axis around which to rotate
+   * @param angle The magnitude of the rotation in Radians */
+	void setRotation(const btVector3& axis, const btScalar& angle)
+	{
+		btScalar d = axis.length();
+		btAssert(d != btScalar(0.0));
+		btScalar s = btSin(angle * btScalar(0.5)) / d;
+		setValue(axis.x() * s, axis.y() * s, axis.z() * s, 
+			btCos(angle * btScalar(0.5)));
+	}
+  /**@brief Set the quaternion using Euler angles
+   * @param yaw Angle around Y
+   * @param pitch Angle around X
+   * @param roll Angle around Z */
+	void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{
+		btScalar halfYaw = btScalar(yaw) * btScalar(0.5);  
+		btScalar halfPitch = btScalar(pitch) * btScalar(0.5);  
+		btScalar halfRoll = btScalar(roll) * btScalar(0.5);  
+		btScalar cosYaw = btCos(halfYaw);
+		btScalar sinYaw = btSin(halfYaw);
+		btScalar cosPitch = btCos(halfPitch);
+		btScalar sinPitch = btSin(halfPitch);
+		btScalar cosRoll = btCos(halfRoll);
+		btScalar sinRoll = btSin(halfRoll);
+		setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+			cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+			sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+			cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+	}
+  /**@brief Set the quaternion using euler angles 
+   * @param yaw Angle around Z
+   * @param pitch Angle around Y
+   * @param roll Angle around X */
+	void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{
+		btScalar halfYaw = btScalar(yaw) * btScalar(0.5);  
+		btScalar halfPitch = btScalar(pitch) * btScalar(0.5);  
+		btScalar halfRoll = btScalar(roll) * btScalar(0.5);  
+		btScalar cosYaw = btCos(halfYaw);
+		btScalar sinYaw = btSin(halfYaw);
+		btScalar cosPitch = btCos(halfPitch);
+		btScalar sinPitch = btSin(halfPitch);
+		btScalar cosRoll = btCos(halfRoll);
+		btScalar sinRoll = btSin(halfRoll);
+		setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
+                         cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
+                         cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
+                         cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
+	}
+  /**@brief Add two quaternions
+   * @param q The quaternion to add to this one */
+	SIMD_FORCE_INLINE	btQuaternion& operator+=(const btQuaternion& q)
+	{
+		m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3];
+		return *this;
+	}
+
+  /**@brief Subtract out a quaternion
+   * @param q The quaternion to subtract from this one */
+	btQuaternion& operator-=(const btQuaternion& q) 
+	{
+		m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3];
+		return *this;
+	}
+
+  /**@brief Scale this quaternion
+   * @param s The scalar to scale by */
+	btQuaternion& operator*=(const btScalar& s)
+	{
+		m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s;
+		return *this;
+	}
+
+  /**@brief Multiply this quaternion by q on the right
+   * @param q The other quaternion 
+   * Equivilant to this = this * q */
+	btQuaternion& operator*=(const btQuaternion& q)
+	{
+		setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
+			m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
+			m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
+			m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
+		return *this;
+	}
+  /**@brief Return the dot product between this quaternion and another
+   * @param q The other quaternion */
+	btScalar dot(const btQuaternion& q) const
+	{
+		return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3];
+	}
+
+  /**@brief Return the length squared of the quaternion */
+	btScalar length2() const
+	{
+		return dot(*this);
+	}
+
+  /**@brief Return the length of the quaternion */
+	btScalar length() const
+	{
+		return btSqrt(length2());
+	}
+
+  /**@brief Normalize the quaternion 
+   * Such that x^2 + y^2 + z^2 +w^2 = 1 */
+	btQuaternion& normalize() 
+	{
+		return *this /= length();
+	}
+
+  /**@brief Return a scaled version of this quaternion
+   * @param s The scale factor */
+	SIMD_FORCE_INLINE btQuaternion
+	operator*(const btScalar& s) const
+	{
+		return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
+	}
+
+
+  /**@brief Return an inversely scaled versionof this quaternion
+   * @param s The inverse scale factor */
+	btQuaternion operator/(const btScalar& s) const
+	{
+		btAssert(s != btScalar(0.0));
+		return *this * (btScalar(1.0) / s);
+	}
+
+  /**@brief Inversely scale this quaternion
+   * @param s The scale factor */
+	btQuaternion& operator/=(const btScalar& s) 
+	{
+		btAssert(s != btScalar(0.0));
+		return *this *= btScalar(1.0) / s;
+	}
+
+  /**@brief Return a normalized version of this quaternion */
+	btQuaternion normalized() const 
+	{
+		return *this / length();
+	} 
+  /**@brief Return the angle between this quaternion and the other 
+   * @param q The other quaternion */
+	btScalar angle(const btQuaternion& q) const 
+	{
+		btScalar s = btSqrt(length2() * q.length2());
+		btAssert(s != btScalar(0.0));
+		return btAcos(dot(q) / s);
+	}
+  /**@brief Return the angle of rotation represented by this quaternion */
+	btScalar getAngle() const 
+	{
+		btScalar s = btScalar(2.) * btAcos(m_floats[3]);
+		return s;
+	}
+
+	/**@brief Return the axis of the rotation represented by this quaternion */
+	btVector3 getAxis() const
+	{
+		btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.));
+		if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
+			return btVector3(1.0, 0.0, 0.0);  // Arbitrary
+		btScalar s = btSqrt(s_squared);
+		return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s);
+	}
+
+	/**@brief Return the inverse of this quaternion */
+	btQuaternion inverse() const
+	{
+		return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+	}
+
+  /**@brief Return the sum of this quaternion and the other 
+   * @param q2 The other quaternion */
+	SIMD_FORCE_INLINE btQuaternion
+	operator+(const btQuaternion& q2) const
+	{
+		const btQuaternion& q1 = *this;
+		return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
+	}
+
+  /**@brief Return the difference between this quaternion and the other 
+   * @param q2 The other quaternion */
+	SIMD_FORCE_INLINE btQuaternion
+	operator-(const btQuaternion& q2) const
+	{
+		const btQuaternion& q1 = *this;
+		return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
+	}
+
+  /**@brief Return the negative of this quaternion 
+   * This simply negates each element */
+	SIMD_FORCE_INLINE btQuaternion operator-() const
+	{
+		const btQuaternion& q2 = *this;
+		return btQuaternion( - q2.x(), - q2.y(),  - q2.z(),  - q2.m_floats[3]);
+	}
+  /**@todo document this and it's use */
+	SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const 
+	{
+		btQuaternion diff,sum;
+		diff = *this - qd;
+		sum = *this + qd;
+		if( diff.dot(diff) > sum.dot(sum) )
+			return qd;
+		return (-qd);
+	}
+
+	/**@todo document this and it's use */
+	SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const 
+	{
+		btQuaternion diff,sum;
+		diff = *this - qd;
+		sum = *this + qd;
+		if( diff.dot(diff) < sum.dot(sum) )
+			return qd;
+		return (-qd);
+	}
+
+
+  /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+   * @param q The other quaternion to interpolate with 
+   * @param t The ratio between this and q to interpolate.  If t = 0 the result is this, if t=1 the result is q.
+   * Slerp interpolates assuming constant velocity.  */
+	btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
+	{
+		btScalar theta = angle(q);
+		if (theta != btScalar(0.0))
+		{
+			btScalar d = btScalar(1.0) / btSin(theta);
+			btScalar s0 = btSin((btScalar(1.0) - t) * theta);
+			btScalar s1 = btSin(t * theta);   
+                        if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+                          return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d,
+                                              (m_floats[1] * s0 + -q.y() * s1) * d,
+                                              (m_floats[2] * s0 + -q.z() * s1) * d,
+                                              (m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
+                        else
+                          return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d,
+                                              (m_floats[1] * s0 + q.y() * s1) * d,
+                                              (m_floats[2] * s0 + q.z() * s1) * d,
+                                              (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
+                        
+		}
+		else
+		{
+			return *this;
+		}
+	}
+
+	static const btQuaternion&	getIdentity()
+	{
+		static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
+		return identityQuat;
+	}
+
+	SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
+
+	
+};
+
+
+/**@brief Return the negative of a quaternion */
+SIMD_FORCE_INLINE btQuaternion
+operator-(const btQuaternion& q)
+{
+	return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w());
+}
+
+
+
+/**@brief Return the product of two quaternions */
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q1, const btQuaternion& q2) {
+	return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
+		q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
+		q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
+		q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); 
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q, const btVector3& w)
+{
+	return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
+		q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
+		q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
+		-q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); 
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btVector3& w, const btQuaternion& q)
+{
+	return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+		w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
+		w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
+		-w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); 
+}
+
+/**@brief Calculate the dot product between two quaternions */
+SIMD_FORCE_INLINE btScalar 
+dot(const btQuaternion& q1, const btQuaternion& q2) 
+{ 
+	return q1.dot(q2); 
+}
+
+
+/**@brief Return the length of a quaternion */
+SIMD_FORCE_INLINE btScalar
+length(const btQuaternion& q) 
+{ 
+	return q.length(); 
+}
+
+/**@brief Return the angle between two quaternions*/
+SIMD_FORCE_INLINE btScalar
+angle(const btQuaternion& q1, const btQuaternion& q2) 
+{ 
+	return q1.angle(q2); 
+}
+
+/**@brief Return the inverse of a quaternion*/
+SIMD_FORCE_INLINE btQuaternion
+inverse(const btQuaternion& q) 
+{
+	return q.inverse();
+}
+
+/**@brief Return the result of spherical linear interpolation betwen two quaternions 
+ * @param q1 The first quaternion
+ * @param q2 The second quaternion 
+ * @param t The ration between q1 and q2.  t = 0 return q1, t=1 returns q2 
+ * Slerp assumes constant velocity between positions. */
+SIMD_FORCE_INLINE btQuaternion
+slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) 
+{
+	return q1.slerp(q2, t);
+}
+
+SIMD_FORCE_INLINE btVector3 
+quatRotate(const btQuaternion& rotation, const btVector3& v) 
+{
+	btQuaternion q = rotation * v;
+	q *= rotation.inverse();
+	return btVector3(q.getX(),q.getY(),q.getZ());
+}
+
+SIMD_FORCE_INLINE btQuaternion 
+shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
+{
+	btVector3 c = v0.cross(v1);
+	btScalar  d = v0.dot(v1);
+
+	if (d < -1.0 + SIMD_EPSILON)
+	{
+		btVector3 n,unused;
+		btPlaneSpace1(v0,n,unused);
+		return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
+	}
+
+	btScalar  s = btSqrt((1.0f + d) * 2.0f);
+	btScalar rs = 1.0f / s;
+
+	return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
+}
+
+SIMD_FORCE_INLINE btQuaternion 
+shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
+{
+	v0.normalize();
+	v1.normalize();
+	return shortestArcQuat(v0,v1);
+}
+
+#endif //BT_SIMD__QUATERNION_H_
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuickprof.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuickprof.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuickprof.cpp	(revision 11817)
@@ -0,0 +1,565 @@
+/*
+
+***************************************************************************************************
+**
+** profile.cpp
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in 
+// Ogre (www.ogre3d.org).
+
+#include "btQuickprof.h"
+
+#ifndef BT_NO_PROFILE
+
+
+static btClock gProfileClock;
+
+
+#ifdef __CELLOS_LV2__
+#include <sys/sys_time.h>
+#include <sys/time_util.h>
+#include <stdio.h>
+#endif
+
+#if defined (SUNOS) || defined (__SUNOS__) 
+#include <stdio.h> 
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+#define BT_USE_WINDOWS_TIMERS
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOMCX
+#define NOIME 
+
+#ifdef _XBOX
+	#include <Xtl.h>
+#else //_XBOX
+	#include <windows.h>
+#endif //_XBOX
+
+#include <time.h>
+
+
+#else //_WIN32
+#include <sys/time.h>
+#endif //_WIN32
+
+#define mymin(a,b) (a > b ? a : b)
+
+struct btClockData
+{
+
+#ifdef BT_USE_WINDOWS_TIMERS
+	LARGE_INTEGER mClockFrequency;
+	DWORD mStartTick;
+	LONGLONG mPrevElapsedTime;
+	LARGE_INTEGER mStartTime;
+#else
+#ifdef __CELLOS_LV2__
+	uint64_t	mStartTime;
+#else
+	struct timeval mStartTime;
+#endif
+#endif //__CELLOS_LV2__
+
+};
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+btClock::btClock()
+{
+	m_data = new btClockData;
+#ifdef BT_USE_WINDOWS_TIMERS
+	QueryPerformanceFrequency(&m_data->mClockFrequency);
+#endif
+	reset();
+}
+
+btClock::~btClock()
+{
+	delete m_data;
+}
+
+btClock::btClock(const btClock& other)
+{
+	m_data = new btClockData;
+	*m_data = *other.m_data;
+}
+
+btClock& btClock::operator=(const btClock& other)
+{
+	*m_data = *other.m_data;
+	return *this;
+}
+
+
+	/// Resets the initial reference time.
+void btClock::reset()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+	QueryPerformanceCounter(&m_data->mStartTime);
+	m_data->mStartTick = GetTickCount();
+	m_data->mPrevElapsedTime = 0;
+#else
+#ifdef __CELLOS_LV2__
+
+	typedef uint64_t  ClockSize;
+	ClockSize newTime;
+	//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+	SYS_TIMEBASE_GET( newTime );
+	m_data->mStartTime = newTime;
+#else
+	gettimeofday(&m_data->mStartTime, 0);
+#endif
+#endif
+}
+
+/// Returns the time in ms since the last call to reset or since 
+/// the btClock was created.
+unsigned long int btClock::getTimeMilliseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+	LARGE_INTEGER currentTime;
+	QueryPerformanceCounter(&currentTime);
+	LONGLONG elapsedTime = currentTime.QuadPart - 
+		m_data->mStartTime.QuadPart;
+		// Compute the number of millisecond ticks elapsed.
+	unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
+		m_data->mClockFrequency.QuadPart);
+		// Check for unexpected leaps in the Win32 performance counter.  
+	// (This is caused by unexpected data across the PCI to ISA 
+		// bridge, aka south bridge.  See Microsoft KB274323.)
+		unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
+		signed long msecOff = (signed long)(msecTicks - elapsedTicks);
+		if (msecOff < -100 || msecOff > 100)
+		{
+			// Adjust the starting time forwards.
+			LONGLONG msecAdjustment = mymin(msecOff * 
+				m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 
+				m_data->mPrevElapsedTime);
+			m_data->mStartTime.QuadPart += msecAdjustment;
+			elapsedTime -= msecAdjustment;
+
+			// Recompute the number of millisecond ticks elapsed.
+			msecTicks = (unsigned long)(1000 * elapsedTime / 
+				m_data->mClockFrequency.QuadPart);
+		}
+
+		// Store the current elapsed time for adjustments next time.
+		m_data->mPrevElapsedTime = elapsedTime;
+
+		return msecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+		uint64_t freq=sys_time_get_timebase_frequency();
+		double dFreq=((double) freq) / 1000.0;
+		typedef uint64_t  ClockSize;
+		ClockSize newTime;
+		SYS_TIMEBASE_GET( newTime );
+		//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+
+		return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+		struct timeval currentTime;
+		gettimeofday(&currentTime, 0);
+		return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + 
+			(currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
+#endif //__CELLOS_LV2__
+#endif
+}
+
+	/// Returns the time in us since the last call to reset or since 
+	/// the Clock was created.
+unsigned long int btClock::getTimeMicroseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+		LARGE_INTEGER currentTime;
+		QueryPerformanceCounter(&currentTime);
+		LONGLONG elapsedTime = currentTime.QuadPart - 
+			m_data->mStartTime.QuadPart;
+
+		// Compute the number of millisecond ticks elapsed.
+		unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
+			m_data->mClockFrequency.QuadPart);
+
+		// Check for unexpected leaps in the Win32 performance counter.  
+		// (This is caused by unexpected data across the PCI to ISA 
+		// bridge, aka south bridge.  See Microsoft KB274323.)
+		unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
+		signed long msecOff = (signed long)(msecTicks - elapsedTicks);
+		if (msecOff < -100 || msecOff > 100)
+		{
+			// Adjust the starting time forwards.
+			LONGLONG msecAdjustment = mymin(msecOff * 
+				m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 
+				m_data->mPrevElapsedTime);
+			m_data->mStartTime.QuadPart += msecAdjustment;
+			elapsedTime -= msecAdjustment;
+		}
+
+		// Store the current elapsed time for adjustments next time.
+		m_data->mPrevElapsedTime = elapsedTime;
+
+		// Convert to microseconds.
+		unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / 
+			m_data->mClockFrequency.QuadPart);
+
+		return usecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+		uint64_t freq=sys_time_get_timebase_frequency();
+		double dFreq=((double) freq)/ 1000000.0;
+		typedef uint64_t  ClockSize;
+		ClockSize newTime;
+		//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+		SYS_TIMEBASE_GET( newTime );
+
+		return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+		struct timeval currentTime;
+		gettimeofday(&currentTime, 0);
+		return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + 
+			(currentTime.tv_usec - m_data->mStartTime.tv_usec);
+#endif//__CELLOS_LV2__
+#endif 
+}
+
+
+
+
+
+inline void Profile_Get_Ticks(unsigned long int * ticks)
+{
+	*ticks = gProfileClock.getTimeMicroseconds();
+}
+
+inline float Profile_Get_Tick_Rate(void)
+{
+//	return 1000000.f;
+	return 1000.f;
+
+}
+
+
+
+/***************************************************************************************************
+**
+** CProfileNode
+**
+***************************************************************************************************/
+
+/***********************************************************************************************
+ * INPUT:                                                                                      *
+ * name - pointer to a static string which is the name of this profile node                    *
+ * parent - parent pointer                                                                     *
+ *                                                                                             *
+ * WARNINGS:                                                                                   *
+ * The name is assumed to be a static pointer, only the pointer is stored and compared for     *
+ * efficiency reasons.                                                                         *
+ *=============================================================================================*/
+CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
+	Name( name ),
+	TotalCalls( 0 ),
+	TotalTime( 0 ),
+	StartTime( 0 ),
+	RecursionCounter( 0 ),
+	Parent( parent ),
+	Child( NULL ),
+	Sibling( NULL )
+{
+	Reset();
+}
+
+
+void	CProfileNode::CleanupMemory()
+{
+	delete ( Child);
+	Child = NULL;
+	delete ( Sibling);
+	Sibling = NULL;
+}
+
+CProfileNode::~CProfileNode( void )
+{
+	delete ( Child);
+	delete ( Sibling);
+}
+
+
+/***********************************************************************************************
+ * INPUT:                                                                                      *
+ * name - static string pointer to the name of the node we are searching for                   *
+ *                                                                                             *
+ * WARNINGS:                                                                                   *
+ * All profile names are assumed to be static strings so this function uses pointer compares   *
+ * to find the named node.                                                                     *
+ *=============================================================================================*/
+CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
+{
+	// Try to find this sub node
+	CProfileNode * child = Child;
+	while ( child ) {
+		if ( child->Name == name ) {
+			return child;
+		}
+		child = child->Sibling;
+	}
+
+	// We didn't find it, so add it
+	
+	CProfileNode * node = new CProfileNode( name, this );
+	node->Sibling = Child;
+	Child = node;
+	return node;
+}
+
+
+void	CProfileNode::Reset( void )
+{
+	TotalCalls = 0;
+	TotalTime = 0.0f;
+	
+
+	if ( Child ) {
+		Child->Reset();
+	}
+	if ( Sibling ) {
+		Sibling->Reset();
+	}
+}
+
+
+void	CProfileNode::Call( void )
+{
+	TotalCalls++;
+	if (RecursionCounter++ == 0) {
+		Profile_Get_Ticks(&StartTime);
+	}
+}
+
+
+bool	CProfileNode::Return( void )
+{
+	if ( --RecursionCounter == 0 && TotalCalls != 0 ) { 
+		unsigned long int time;
+		Profile_Get_Ticks(&time);
+		time-=StartTime;
+		TotalTime += (float)time / Profile_Get_Tick_Rate();
+	}
+	return ( RecursionCounter == 0 );
+}
+
+
+/***************************************************************************************************
+**
+** CProfileIterator
+**
+***************************************************************************************************/
+CProfileIterator::CProfileIterator( CProfileNode * start )
+{
+	CurrentParent = start;
+	CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void	CProfileIterator::First(void)
+{
+	CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void	CProfileIterator::Next(void)
+{
+	CurrentChild = CurrentChild->Get_Sibling();
+}
+
+
+bool	CProfileIterator::Is_Done(void)
+{
+	return CurrentChild == NULL;
+}
+
+
+void	CProfileIterator::Enter_Child( int index )
+{
+	CurrentChild = CurrentParent->Get_Child();
+	while ( (CurrentChild != NULL) && (index != 0) ) {
+		index--;
+		CurrentChild = CurrentChild->Get_Sibling();
+	}
+
+	if ( CurrentChild != NULL ) {
+		CurrentParent = CurrentChild;
+		CurrentChild = CurrentParent->Get_Child();
+	}
+}
+
+
+void	CProfileIterator::Enter_Parent( void )
+{
+	if ( CurrentParent->Get_Parent() != NULL ) {
+		CurrentParent = CurrentParent->Get_Parent();
+	}
+	CurrentChild = CurrentParent->Get_Child();
+}
+
+
+/***************************************************************************************************
+**
+** CProfileManager
+**
+***************************************************************************************************/
+
+CProfileNode	CProfileManager::Root( "Root", NULL );
+CProfileNode *	CProfileManager::CurrentNode = &CProfileManager::Root;
+int				CProfileManager::FrameCounter = 0;
+unsigned long int			CProfileManager::ResetTime = 0;
+
+
+/***********************************************************************************************
+ * CProfileManager::Start_Profile -- Begin a named profile                                    *
+ *                                                                                             *
+ * Steps one level deeper into the tree, if a child already exists with the specified name     *
+ * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
+ *                                                                                             *
+ * INPUT:                                                                                      *
+ * name - name of this profiling record                                                        *
+ *                                                                                             *
+ * WARNINGS:                                                                                   *
+ * The string used is assumed to be a static string; pointer compares are used throughout      *
+ * the profiling code for efficiency.                                                          *
+ *=============================================================================================*/
+void	CProfileManager::Start_Profile( const char * name )
+{
+	if (name != CurrentNode->Get_Name()) {
+		CurrentNode = CurrentNode->Get_Sub_Node( name );
+	} 
+	
+	CurrentNode->Call();
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Stop_Profile -- Stop timing and record the results.                       *
+ *=============================================================================================*/
+void	CProfileManager::Stop_Profile( void )
+{
+	// Return will indicate whether we should back up to our parent (we may
+	// be profiling a recursive function)
+	if (CurrentNode->Return()) {
+		CurrentNode = CurrentNode->Get_Parent();
+	}
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Reset -- Reset the contents of the profiling system                       *
+ *                                                                                             *
+ *    This resets everything except for the tree structure.  All of the timing data is reset.  *
+ *=============================================================================================*/
+void	CProfileManager::Reset( void )
+{ 
+	gProfileClock.reset();
+	Root.Reset();
+    Root.Call();
+	FrameCounter = 0;
+	Profile_Get_Ticks(&ResetTime);
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Increment_Frame_Counter -- Increment the frame counter                    *
+ *=============================================================================================*/
+void CProfileManager::Increment_Frame_Counter( void )
+{
+	FrameCounter++;
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset         *
+ *=============================================================================================*/
+float CProfileManager::Get_Time_Since_Reset( void )
+{
+	unsigned long int time;
+	Profile_Get_Ticks(&time);
+	time -= ResetTime;
+	return (float)time / Profile_Get_Tick_Rate();
+}
+
+#include <stdio.h>
+
+void	CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
+{
+	profileIterator->First();
+	if (profileIterator->Is_Done())
+		return;
+
+	float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
+	int i;
+	int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
+	for (i=0;i<spacing;i++)	printf(".");
+	printf("----------------------------------\n");
+	for (i=0;i<spacing;i++)	printf(".");
+	printf("Profiling: %s (total running time: %.3f ms) ---\n",	profileIterator->Get_Current_Parent_Name(), parent_time );
+	float totalTime = 0.f;
+
+	
+	int numChildren = 0;
+	
+	for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
+	{
+		numChildren++;
+		float current_total_time = profileIterator->Get_Current_Total_Time();
+		accumulated_time += current_total_time;
+		float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
+		{
+			int i;	for (i=0;i<spacing;i++)	printf(".");
+		}
+		printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
+		totalTime += current_total_time;
+		//recurse into children
+	}
+
+	if (parent_time < accumulated_time)
+	{
+		printf("what's wrong\n");
+	}
+	for (i=0;i<spacing;i++)	printf(".");
+	printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
+	
+	for (i=0;i<numChildren;i++)
+	{
+		profileIterator->Enter_Child(i);
+		dumpRecursive(profileIterator,spacing+3);
+		profileIterator->Enter_Parent();
+	}
+}
+
+
+
+void	CProfileManager::dumpAll()
+{
+	CProfileIterator* profileIterator = 0;
+	profileIterator = CProfileManager::Get_Iterator();
+
+	dumpRecursive(profileIterator,0);
+
+	CProfileManager::Release_Iterator(profileIterator);
+}
+
+
+
+
+#endif //BT_NO_PROFILE
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuickprof.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuickprof.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btQuickprof.h	(revision 11817)
@@ -0,0 +1,196 @@
+
+/***************************************************************************************************
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in 
+// Ogre (www.ogre3d.org).
+
+
+
+#ifndef BT_QUICK_PROF_H
+#define BT_QUICK_PROF_H
+
+//To disable built-in profiling, please comment out next line
+//#define BT_NO_PROFILE 1
+#ifndef BT_NO_PROFILE
+#include <stdio.h>//@todo remove this, backwards compatibility
+#include "btScalar.h"
+#include "btAlignedAllocator.h"
+#include <new>
+
+
+
+
+
+#define USE_BT_CLOCK 1
+
+#ifdef USE_BT_CLOCK
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+class btClock
+{
+public:
+	btClock();
+
+	btClock(const btClock& other);
+	btClock& operator=(const btClock& other);
+
+	~btClock();
+
+	/// Resets the initial reference time.
+	void reset();
+
+	/// Returns the time in ms since the last call to reset or since 
+	/// the btClock was created.
+	unsigned long int getTimeMilliseconds();
+
+	/// Returns the time in us since the last call to reset or since 
+	/// the Clock was created.
+	unsigned long int getTimeMicroseconds();
+private:
+	struct btClockData* m_data;
+};
+
+#endif //USE_BT_CLOCK
+
+
+
+
+///A node in the Profile Hierarchy Tree
+class	CProfileNode {
+
+public:
+	CProfileNode( const char * name, CProfileNode * parent );
+	~CProfileNode( void );
+
+	CProfileNode * Get_Sub_Node( const char * name );
+
+	CProfileNode * Get_Parent( void )		{ return Parent; }
+	CProfileNode * Get_Sibling( void )		{ return Sibling; }
+	CProfileNode * Get_Child( void )			{ return Child; }
+
+	void				CleanupMemory();
+	void				Reset( void );
+	void				Call( void );
+	bool				Return( void );
+
+	const char *	Get_Name( void )				{ return Name; }
+	int				Get_Total_Calls( void )		{ return TotalCalls; }
+	float				Get_Total_Time( void )		{ return TotalTime; }
+
+protected:
+
+	const char *	Name;
+	int				TotalCalls;
+	float				TotalTime;
+	unsigned long int			StartTime;
+	int				RecursionCounter;
+
+	CProfileNode *	Parent;
+	CProfileNode *	Child;
+	CProfileNode *	Sibling;
+};
+
+///An iterator to navigate through the tree
+class CProfileIterator
+{
+public:
+	// Access all the children of the current parent
+	void				First(void);
+	void				Next(void);
+	bool				Is_Done(void);
+	bool                Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
+
+	void				Enter_Child( int index );		// Make the given child the new parent
+	void				Enter_Largest_Child( void );	// Make the largest child the new parent
+	void				Enter_Parent( void );			// Make the current parent's parent the new parent
+
+	// Access the current child
+	const char *	Get_Current_Name( void )			{ return CurrentChild->Get_Name(); }
+	int				Get_Current_Total_Calls( void )	{ return CurrentChild->Get_Total_Calls(); }
+	float				Get_Current_Total_Time( void )	{ return CurrentChild->Get_Total_Time(); }
+
+	// Access the current parent
+	const char *	Get_Current_Parent_Name( void )			{ return CurrentParent->Get_Name(); }
+	int				Get_Current_Parent_Total_Calls( void )	{ return CurrentParent->Get_Total_Calls(); }
+	float				Get_Current_Parent_Total_Time( void )	{ return CurrentParent->Get_Total_Time(); }
+
+protected:
+
+	CProfileNode *	CurrentParent;
+	CProfileNode *	CurrentChild;
+
+	CProfileIterator( CProfileNode * start );
+	friend	class		CProfileManager;
+};
+
+
+///The Manager for the Profile system
+class	CProfileManager {
+public:
+	static	void						Start_Profile( const char * name );
+	static	void						Stop_Profile( void );
+
+	static	void						CleanupMemory(void)
+	{
+		Root.CleanupMemory();
+	}
+
+	static	void						Reset( void );
+	static	void						Increment_Frame_Counter( void );
+	static	int						Get_Frame_Count_Since_Reset( void )		{ return FrameCounter; }
+	static	float						Get_Time_Since_Reset( void );
+
+	static	CProfileIterator *	Get_Iterator( void )	
+	{ 
+		
+		return new CProfileIterator( &Root ); 
+	}
+	static	void						Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
+
+	static void	dumpRecursive(CProfileIterator* profileIterator, int spacing);
+
+	static void	dumpAll();
+
+private:
+	static	CProfileNode			Root;
+	static	CProfileNode *			CurrentNode;
+	static	int						FrameCounter;
+	static	unsigned long int					ResetTime;
+};
+
+
+///ProfileSampleClass is a simple way to profile a function's scope
+///Use the BT_PROFILE macro at the start of scope to time
+class	CProfileSample {
+public:
+	CProfileSample( const char * name )
+	{ 
+		CProfileManager::Start_Profile( name ); 
+	}
+
+	~CProfileSample( void )					
+	{ 
+		CProfileManager::Stop_Profile(); 
+	}
+};
+
+
+#define	BT_PROFILE( name )			CProfileSample __profile( name )
+
+#else
+
+#define	BT_PROFILE( name )
+
+#endif //#ifndef BT_NO_PROFILE
+
+
+
+#endif //BT_QUICK_PROF_H
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btRandom.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btRandom.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btRandom.h	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_GEN_RANDOM_H
+#define BT_GEN_RANDOM_H
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define GEN_RAND_MAX UINT_MAX
+
+SIMD_FORCE_INLINE void         GEN_srand(unsigned int seed) { init_genrand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand()                   { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define GEN_RAND_MAX RAND_MAX
+
+SIMD_FORCE_INLINE void         GEN_srand(unsigned int seed) { srand(seed); } 
+SIMD_FORCE_INLINE unsigned int GEN_rand()                   { return rand(); }
+
+#endif
+
+#endif //BT_GEN_RANDOM_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btScalar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btScalar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btScalar.h	(revision 11817)
@@ -0,0 +1,522 @@
+/*
+Copyright (c) 2003-2009 Erwin Coumans  http://bullet.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_SCALAR_H
+#define BT_SCALAR_H
+
+#ifdef BT_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+
+#include <math.h>
+#include <stdlib.h>//size_t for MSVC 6.0
+#include <float.h>
+
+/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
+#define BT_BULLET_VERSION 278
+
+inline int	btGetVersion()
+{
+	return BT_BULLET_VERSION;
+}
+
+#if defined(DEBUG) || defined (_DEBUG)
+#define BT_DEBUG
+#endif
+
+
+#ifdef _WIN32
+
+		#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+
+			#define SIMD_FORCE_INLINE inline
+			#define ATTRIBUTE_ALIGNED16(a) a
+			#define ATTRIBUTE_ALIGNED64(a) a
+			#define ATTRIBUTE_ALIGNED128(a) a
+		#else
+			//#define BT_HAS_ALIGNED_ALLOCATOR
+			#pragma warning(disable : 4324) // disable padding warning
+//			#pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+//			#pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+//			#pragma warning(disable:4786) // Disable the "debug name too long" warning
+
+			#define SIMD_FORCE_INLINE __forceinline
+			#define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+			#define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+			#define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
+		#ifdef _XBOX
+			#define BT_USE_VMX128
+
+			#include <ppcintrinsics.h>
+ 			#define BT_HAVE_NATIVE_FSEL
+ 			#define btFsel(a,b,c) __fsel((a),(b),(c))
+		#else
+
+#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
+			#define BT_USE_SSE
+			#include <emmintrin.h>
+#endif
+
+		#endif//_XBOX
+
+		#endif //__MINGW32__
+
+		#include <assert.h>
+#ifdef BT_DEBUG
+		#define btAssert assert
+#else
+		#define btAssert(x)
+#endif
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+
+		#define btLikely(_c)  _c
+		#define btUnlikely(_c) _c
+
+#else
+	
+#if defined	(__CELLOS_LV2__)
+		#define SIMD_FORCE_INLINE inline __attribute__((always_inline))
+		#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+		#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+		#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+		#ifndef assert
+		#include <assert.h>
+		#endif
+#ifdef BT_DEBUG
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+	#define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
+#else
+	#define btAssert assert
+#endif
+	
+#else
+		#define btAssert(x)
+#endif
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+
+		#define btLikely(_c)  _c
+		#define btUnlikely(_c) _c
+
+#else
+
+#ifdef USE_LIBSPE2
+
+		#define SIMD_FORCE_INLINE __inline
+		#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+		#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+		#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+		#ifndef assert
+		#include <assert.h>
+		#endif
+#ifdef BT_DEBUG
+		#define btAssert assert
+#else
+		#define btAssert(x)
+#endif
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+
+
+		#define btLikely(_c)   __builtin_expect((_c), 1)
+		#define btUnlikely(_c) __builtin_expect((_c), 0)
+		
+
+#else
+	//non-windows systems
+
+#if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION)))
+	#define BT_USE_SSE
+	#include <emmintrin.h>
+
+	#define SIMD_FORCE_INLINE inline
+///@todo: check out alignment methods for other platforms/compilers
+	#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+	#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+	#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+	#ifndef assert
+	#include <assert.h>
+	#endif
+
+	#if defined(DEBUG) || defined (_DEBUG)
+		#define btAssert assert
+	#else
+		#define btAssert(x)
+	#endif
+
+	//btFullAssert is optional, slows down a lot
+	#define btFullAssert(x)
+	#define btLikely(_c)  _c
+	#define btUnlikely(_c) _c
+
+#else
+
+		#define SIMD_FORCE_INLINE inline
+		///@todo: check out alignment methods for other platforms/compilers
+		///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+		///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+		///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+		#define ATTRIBUTE_ALIGNED16(a) a
+		#define ATTRIBUTE_ALIGNED64(a) a
+		#define ATTRIBUTE_ALIGNED128(a) a
+		#ifndef assert
+		#include <assert.h>
+		#endif
+
+#if defined(DEBUG) || defined (_DEBUG)
+		#define btAssert assert
+#else
+		#define btAssert(x)
+#endif
+
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+		#define btLikely(_c)  _c
+		#define btUnlikely(_c) _c
+#endif //__APPLE__ 
+
+#endif // LIBSPE2
+
+#endif	//__CELLOS_LV2__
+#endif
+
+
+///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+#if defined(BT_USE_DOUBLE_PRECISION)
+typedef double btScalar;
+//this number could be bigger in double precision
+#define BT_LARGE_FLOAT 1e30
+#else
+typedef float btScalar;
+//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
+#define BT_LARGE_FLOAT 1e18f
+#endif
+
+
+
+#define BT_DECLARE_ALIGNED_ALLOCATOR() \
+   SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
+   SIMD_FORCE_INLINE void  operator delete(void* ptr)         { btAlignedFree(ptr); }   \
+   SIMD_FORCE_INLINE void* operator new(size_t, void* ptr)   { return ptr; }   \
+   SIMD_FORCE_INLINE void  operator delete(void*, void*)      { }   \
+   SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
+   SIMD_FORCE_INLINE void  operator delete[](void* ptr)         { btAlignedFree(ptr); }   \
+   SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr)   { return ptr; }   \
+   SIMD_FORCE_INLINE void  operator delete[](void*, void*)      { }   \
+
+
+
+#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
+		
+SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); }
+SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
+SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
+SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
+SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
+SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (x<btScalar(-1))	x=btScalar(-1); if (x>btScalar(1))	x=btScalar(1); return acos(x); }
+SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (x<btScalar(-1))	x=btScalar(-1); if (x>btScalar(1))	x=btScalar(1); return asin(x); }
+SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
+SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
+SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
+SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
+SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
+SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); }
+
+#else
+		
+SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 
+{ 
+#ifdef USE_APPROXIMATION
+    double x, z, tempf;
+    unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
+
+	tempf = y;
+	*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
+	x =  tempf;
+	z =  y*btScalar(0.5);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);         /* iteration formula     */
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	return x*y;
+#else
+	return sqrtf(y); 
+#endif
+}
+SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
+SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
+SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
+SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
+SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 
+	if (x<btScalar(-1))	
+		x=btScalar(-1); 
+	if (x>btScalar(1))	
+		x=btScalar(1);
+	return acosf(x); 
+}
+SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { 
+	if (x<btScalar(-1))	
+		x=btScalar(-1); 
+	if (x>btScalar(1))	
+		x=btScalar(1);
+	return asinf(x); 
+}
+SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
+SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
+SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
+SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
+SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); }
+SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); }
+	
+#endif
+
+#define SIMD_2_PI         btScalar(6.283185307179586232)
+#define SIMD_PI           (SIMD_2_PI * btScalar(0.5))
+#define SIMD_HALF_PI      (SIMD_2_PI * btScalar(0.25))
+#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
+#define SIMD_DEGS_PER_RAD  (btScalar(360.0) / SIMD_2_PI)
+#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
+
+#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x))))		/* reciprocal square root */
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define SIMD_EPSILON      DBL_EPSILON
+#define SIMD_INFINITY     DBL_MAX
+#else
+#define SIMD_EPSILON      FLT_EPSILON
+#define SIMD_INFINITY     FLT_MAX
+#endif
+
+SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 
+{
+	btScalar coeff_1 = SIMD_PI / 4.0f;
+	btScalar coeff_2 = 3.0f * coeff_1;
+	btScalar abs_y = btFabs(y);
+	btScalar angle;
+	if (x >= 0.0f) {
+		btScalar r = (x - abs_y) / (x + abs_y);
+		angle = coeff_1 - coeff_1 * r;
+	} else {
+		btScalar r = (x + abs_y) / (abs_y - x);
+		angle = coeff_2 - coeff_1 * r;
+	}
+	return (y < 0.0f) ? -angle : angle;
+}
+
+SIMD_FORCE_INLINE bool      btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
+
+SIMD_FORCE_INLINE bool	btEqual(btScalar a, btScalar eps) {
+	return (((a) <= eps) && !((a) < -eps));
+}
+SIMD_FORCE_INLINE bool	btGreaterEqual (btScalar a, btScalar eps) {
+	return (!((a) <= eps));
+}
+
+
+SIMD_FORCE_INLINE int       btIsNegative(btScalar x) {
+    return x < btScalar(0.0) ? 1 : 0;
+}
+
+SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
+SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
+
+#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifndef btFsel
+SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
+{
+	return a >= 0 ? b : c;
+}
+#endif
+#define btFsels(a,b,c) (btScalar)btFsel(a,b,c)
+
+
+SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
+{
+   long int i = 1;
+   const char *p = (const char *) &i;
+   if (p[0] == 1)  // Lowest address contains the least significant byte
+	   return true;
+   else
+	   return false;
+}
+
+
+
+///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
+///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
+SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 
+{
+    // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+    // Rely on positive value or'ed with its negative having sign bit on
+    // and zero value or'ed with its negative (which is still zero) having sign bit off 
+    // Use arithmetic shift right, shifting the sign bit through all 32 bits
+    unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+    unsigned testEqz = ~testNz;
+    return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 
+}
+SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
+{
+    unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+    unsigned testEqz = ~testNz; 
+    return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
+{
+#ifdef BT_HAVE_NATIVE_FSEL
+    return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+#else
+    return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 
+#endif
+}
+
+template<typename T> SIMD_FORCE_INLINE void btSwap(T& a, T& b)
+{
+	T tmp = a;
+	a = b;
+	b = tmp;
+}
+
+
+//PCK: endian swapping functions
+SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
+{
+	return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8)  | ((val & 0x000000ff) << 24));
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
+{
+	return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
+}
+
+SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
+{
+	return btSwapEndian((unsigned)val);
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
+{
+	return btSwapEndian((unsigned short) val);
+}
+
+///btSwapFloat uses using char pointers to swap the endianness
+////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
+///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. 
+///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. 
+///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. 
+///so instead of returning a float/double, we return integer/long long integer
+SIMD_FORCE_INLINE unsigned int  btSwapEndianFloat(float d)
+{
+    unsigned int a = 0;
+    unsigned char *dst = (unsigned char *)&a;
+    unsigned char *src = (unsigned char *)&d;
+
+    dst[0] = src[3];
+    dst[1] = src[2];
+    dst[2] = src[1];
+    dst[3] = src[0];
+    return a;
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 
+{
+    float d = 0.0f;
+    unsigned char *src = (unsigned char *)&a;
+    unsigned char *dst = (unsigned char *)&d;
+
+    dst[0] = src[3];
+    dst[1] = src[2];
+    dst[2] = src[1];
+    dst[3] = src[0];
+
+    return d;
+}
+
+
+// swap using char pointers
+SIMD_FORCE_INLINE void  btSwapEndianDouble(double d, unsigned char* dst)
+{
+    unsigned char *src = (unsigned char *)&d;
+
+    dst[0] = src[7];
+    dst[1] = src[6];
+    dst[2] = src[5];
+    dst[3] = src[4];
+    dst[4] = src[3];
+    dst[5] = src[2];
+    dst[6] = src[1];
+    dst[7] = src[0];
+
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 
+{
+    double d = 0.0;
+    unsigned char *dst = (unsigned char *)&d;
+
+    dst[0] = src[7];
+    dst[1] = src[6];
+    dst[2] = src[5];
+    dst[3] = src[4];
+    dst[4] = src[3];
+    dst[5] = src[2];
+    dst[6] = src[1];
+    dst[7] = src[0];
+
+	return d;
+}
+
+// returns normalized value in range [-SIMD_PI, SIMD_PI]
+SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) 
+{
+	angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
+	if(angleInRadians < -SIMD_PI)
+	{
+		return angleInRadians + SIMD_2_PI;
+	}
+	else if(angleInRadians > SIMD_PI)
+	{
+		return angleInRadians - SIMD_2_PI;
+	}
+	else
+	{
+		return angleInRadians;
+	}
+}
+
+///rudimentary class to provide type info
+struct btTypedObject
+{
+	btTypedObject(int objectType)
+		:m_objectType(objectType)
+	{
+	}
+	int	m_objectType;
+	inline int getObjectType() const
+	{
+		return m_objectType;
+	}
+};
+#endif //BT_SCALAR_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btSerializer.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btSerializer.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btSerializer.cpp	(revision 11817)
@@ -0,0 +1,832 @@
+unsigned char sBulletDNAstr[]= {
+83,68,78,65,78,65,77,69,42,1,0,0,109,95,115,105,122,101,0,109,
+95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
+99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
+108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
+115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
+116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
+93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
+95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
+116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
+65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
+101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
+105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
+95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
+114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
+95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
+120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
+118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
+97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
+0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
+101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
+111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
+95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
+111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
+117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
+122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
+114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
+109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
+109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
+97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
+100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
+83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
+108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
+95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
+108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
+0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
+95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
+105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
+83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
+115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
+97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
+109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
+97,108,117,101,115,91,51,93,0,109,95,112,97,100,0,42,109,95,118,101,
+114,116,105,99,101,115,51,102,0,42,109,95,118,101,114,116,105,99,101,115,
+51,100,0,42,109,95,105,110,100,105,99,101,115,51,50,0,42,109,95,51,
+105,110,100,105,99,101,115,49,54,0,42,109,95,51,105,110,100,105,99,101,
+115,56,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,117,
+109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,116,
+105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,114,
+0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,104,
+80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,99,
+101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,66,
+118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,108,
+101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,111,
+77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,105,109,
+101,115,104,83,104,97,112,101,68,97,116,97,0,109,95,116,114,97,110,115,
+102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,0,109,
+95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,99,104,
+105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,83,104,
+97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,104,97,
+112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,103,115,
+0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,95,101,
+100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,101,86,
+50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,98,108,
+101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,95,118,
+97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,121,65,
+114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,115,105,
+108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,110,0,
+109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,104,111,
+108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,104,114,
+101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,104,114,
+101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,109,95,
+104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,109,86,
+97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,103,105,
+109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,115,99,
+97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,0,42,
+109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,117,98,
+108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,100,80,
+111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,93,0,
+42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,101,0,
+42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,42,109,
+95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
+109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,95,105,
+110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,114,97,
+110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,116,105,
+111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,95,105,
+110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,114,86,
+101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,112,105,
+99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,116,80,
+114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,109,
+95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,109,95,
+102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,116,105,
+111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,95,99,
+99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,115,0,
+109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,108,100,
+0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,114,105,
+99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,108,97,
+103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,99,111,
+109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,116,105,
+111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,108,84,
+121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,87,105,
+116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,99,116,
+68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,101,110,
+115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,101,108,
+111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,111,99,
+105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,114,0,
+109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,114,97,
+118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,101,108,
+101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,105,97,
+76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,0,109,
+95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,101,114,
+115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,112,105,
+110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,103,0,
+109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,103,70,
+97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,76,105,
+110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,
+83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,
+108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,83,
+113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,108,
+97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,108,105,
+110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,111,108,
+100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,103,84,
+104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,110,97,
+108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,116,114,
+97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,65,0,
+42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,101,0,
+109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,112,101,
+0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,100,0,
+109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,97,112,
+112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114,
+97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108,
+105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66,
+111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,116,121,
+112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,
+105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,
+95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,
+0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,
+65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,
+97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,
+111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,
+95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,
+111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,
+105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,
+95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,
+116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,
+97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,
+119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,
+95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,
+108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,
+110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,
+110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,
+115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,
+109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,
+110,115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,
+68,97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,
+91,54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,
+110,116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,
+101,115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,
+110,103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,
+101,115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,
+115,115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,
+0,42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,
+105,111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,
+111,110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,
+109,117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,
+108,0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,
+110,111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,
+116,76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,
+95,110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,
+115,116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,
+101,73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,
+108,117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,
+109,95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,
+100,66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,
+97,101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,
+101,0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,
+101,115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,
+110,97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,
+77,97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,
+72,97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,
+110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,
+67,111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,
+99,104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,
+105,103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,
+109,95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,
+72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,
+108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,
+116,82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,
+83,112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,
+108,117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,
+95,115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,
+108,115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,
+0,109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,
+105,116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,
+116,105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,
+102,116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,
+101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,
+95,115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,
+109,95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,
+116,115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,
+110,117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,
+109,95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,
+109,0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,
+118,105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,
+108,115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,
+95,102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,
+100,105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,
+109,70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,
+115,0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,
+115,115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,
+115,101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,
+100,97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,
+95,97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,
+0,109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,
+109,112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,
+111,110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,
+110,116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,
+100,101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,
+95,98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,
+102,115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,
+115,112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,
+80,111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,
+121,112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,
+105,110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,
+109,97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,
+109,95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,
+116,101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,
+115,0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,
+110,116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,
+95,110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,
+0,109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,
+117,109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,
+101,114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,
+110,102,105,103,0,0,0,0,84,89,80,69,72,0,0,0,99,104,97,114,
+0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,
+105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,
+0,100,111,117,98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,
+65,114,114,97,121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,
+109,0,76,105,115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,
+70,108,111,97,116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,
+111,117,98,108,101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,
+51,70,108,111,97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,
+120,51,68,111,117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,
+102,111,114,109,70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,
+115,102,111,114,109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,
+104,83,117,98,116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,
+112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,
+68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,
+111,100,101,68,111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,
+116,105,122,101,100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,
+117,97,110,116,105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,
+0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,
+101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,
+112,101,68,97,116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,
+83,104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,
+116,101,114,110,97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,
+115,105,116,105,111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,
+108,116,105,83,112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,
+116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,
+116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,
+116,73,110,116,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,
+0,98,116,67,104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,
+97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,
+116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,
+99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,
+104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,
+101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,
+100,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,
+116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,
+105,108,100,68,97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,
+97,112,101,68,97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,
+97,112,101,68,97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,
+112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,
+111,68,97,116,97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,
+104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,
+108,83,104,97,112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,
+111,110,79,98,106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,
+116,67,111,108,108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,
+116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,
+97,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,
+117,98,108,101,68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,
+116,73,110,102,111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,
+97,105,110,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,
+68,97,116,97,0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,
+110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,
+80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,
+116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,
+111,110,115,116,114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,
+98,116,72,105,110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,
+97,116,68,97,116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,
+110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,
+105,99,54,68,111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,
+0,98,116,71,101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,
+67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,
+100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,
+102,116,66,111,100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,
+111,102,116,66,111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,
+66,111,100,121,76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,
+121,70,97,99,101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,
+116,114,97,68,97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,
+104,111,114,68,97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,
+105,103,68,97,116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,
+97,116,97,0,83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,
+97,116,97,0,98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,
+97,116,97,0,98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,
+97,116,97,0,84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,
+4,0,4,0,8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0,
+96,0,64,0,-128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0,
+52,0,52,0,20,0,64,0,4,0,4,0,8,0,4,0,32,0,28,0,
+60,0,56,0,76,0,76,0,24,0,60,0,60,0,16,0,64,0,68,0,
+-56,1,-8,0,-32,1,-104,3,8,0,44,0,0,0,76,0,108,0,84,1,
+-44,0,-52,0,-12,0,84,1,-60,0,16,0,100,0,20,0,36,0,100,0,
+92,0,104,0,-64,0,92,1,104,0,-92,1,83,84,82,67,61,0,0,0,
+10,0,3,0,4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,
+10,0,3,0,10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,
+9,0,7,0,13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,
+15,0,1,0,13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,
+15,0,10,0,13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,
+19,0,4,0,4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,
+20,0,6,0,13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,
+4,0,20,0,0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,
+4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,
+2,0,14,0,2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,
+13,0,24,0,13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,
+4,0,29,0,20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,
+4,0,34,0,24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,
+4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,
+22,0,31,0,4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,
+0,0,35,0,4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,
+13,0,39,0,13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,
+25,0,38,0,13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,
+28,0,2,0,13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,
+28,0,48,0,4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,
+31,0,2,0,2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,
+0,0,51,0,33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,
+13,0,54,0,14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,
+31,0,59,0,4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,
+13,0,63,0,4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,
+35,0,65,0,23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,
+0,0,69,0,38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,
+17,0,71,0,25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,
+25,0,38,0,39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,
+27,0,47,0,4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,
+4,0,77,0,0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,
+7,0,80,0,7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,
+43,0,84,0,4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,
+7,0,89,0,7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,
+4,0,94,0,0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,
+13,0,39,0,7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,
+13,0,96,0,14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,
+9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,
+18,0,104,0,14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,
+8,0,109,0,8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,
+8,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,
+4,0,119,0,4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,
+9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,
+17,0,104,0,13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,
+7,0,109,0,7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,
+7,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,
+4,0,119,0,4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,
+15,0,123,0,13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,
+13,0,-128,0,13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,
+7,0,-123,0,7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,
+7,0,-118,0,7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,
+49,0,22,0,46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,
+14,0,126,0,14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,
+14,0,-125,0,14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,
+8,0,-120,0,8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,
+8,0,-115,0,4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,
+4,0,-112,0,51,0,11,0,52,0,-111,0,52,0,-110,0,0,0,35,0,
+4,0,-109,0,4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,
+7,0,-104,0,4,0,-103,0,0,0,-102,0,53,0,3,0,51,0,-101,0,
+13,0,-100,0,13,0,-99,0,54,0,3,0,51,0,-101,0,14,0,-100,0,
+14,0,-99,0,55,0,13,0,51,0,-101,0,18,0,-98,0,18,0,-97,0,
+4,0,-96,0,4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0,
+7,0,-91,0,7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,
+56,0,13,0,51,0,-101,0,17,0,-98,0,17,0,-97,0,4,0,-96,0,
+4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0,
+7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,57,0,11,0,
+51,0,-101,0,17,0,-98,0,17,0,-97,0,7,0,-86,0,7,0,-85,0,
+7,0,-84,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-83,0,
+0,0,21,0,58,0,9,0,51,0,-101,0,17,0,-98,0,17,0,-97,0,
+13,0,-82,0,13,0,-81,0,13,0,-80,0,13,0,-79,0,4,0,-78,0,
+4,0,-77,0,59,0,5,0,58,0,-76,0,4,0,-75,0,7,0,-74,0,
+7,0,-73,0,7,0,-72,0,60,0,9,0,51,0,-101,0,17,0,-98,0,
+17,0,-97,0,7,0,-82,0,7,0,-81,0,7,0,-80,0,7,0,-79,0,
+4,0,-78,0,4,0,-77,0,61,0,4,0,7,0,-71,0,7,0,-70,0,
+7,0,-69,0,4,0,78,0,62,0,10,0,61,0,-68,0,13,0,-67,0,
+13,0,-66,0,13,0,-65,0,13,0,-64,0,13,0,-63,0,7,0,-123,0,
+7,0,-62,0,4,0,-61,0,4,0,53,0,63,0,4,0,61,0,-68,0,
+4,0,-60,0,7,0,-59,0,4,0,-58,0,64,0,4,0,13,0,-63,0,
+61,0,-68,0,4,0,-57,0,7,0,-56,0,65,0,7,0,13,0,-55,0,
+61,0,-68,0,4,0,-54,0,7,0,-53,0,7,0,-52,0,7,0,-51,0,
+4,0,53,0,66,0,6,0,15,0,-50,0,13,0,-52,0,13,0,-49,0,
+52,0,-48,0,4,0,-47,0,7,0,-51,0,67,0,26,0,4,0,-46,0,
+7,0,-45,0,7,0,-83,0,7,0,-44,0,7,0,-43,0,7,0,-42,0,
+7,0,-41,0,7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,
+7,0,-36,0,7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,
+7,0,-31,0,7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,
+4,0,-26,0,4,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,116,0,
+68,0,12,0,15,0,-22,0,15,0,-21,0,15,0,-20,0,13,0,-19,0,
+13,0,-18,0,7,0,-17,0,4,0,-16,0,4,0,-15,0,4,0,-14,0,
+4,0,-13,0,7,0,-53,0,4,0,53,0,69,0,27,0,17,0,-12,0,
+15,0,-11,0,15,0,-10,0,13,0,-19,0,13,0,-9,0,13,0,-8,0,
+13,0,-7,0,13,0,-6,0,13,0,-5,0,4,0,-4,0,7,0,-3,0,
+4,0,-2,0,4,0,-1,0,4,0,0,1,7,0,1,1,7,0,2,1,
+4,0,3,1,4,0,4,1,7,0,5,1,7,0,6,1,7,0,7,1,
+7,0,8,1,7,0,9,1,7,0,10,1,4,0,11,1,4,0,12,1,
+4,0,13,1,70,0,12,0,9,0,14,1,9,0,15,1,13,0,16,1,
+7,0,17,1,7,0,18,1,7,0,19,1,4,0,20,1,13,0,21,1,
+4,0,22,1,4,0,23,1,4,0,24,1,4,0,53,0,71,0,19,0,
+47,0,122,0,68,0,25,1,61,0,26,1,62,0,27,1,63,0,28,1,
+64,0,29,1,65,0,30,1,66,0,31,1,69,0,32,1,70,0,33,1,
+4,0,34,1,4,0,-1,0,4,0,35,1,4,0,36,1,4,0,37,1,
+4,0,38,1,4,0,39,1,4,0,40,1,67,0,41,1,};
+int sBulletDNAlen= sizeof(sBulletDNAstr);
+unsigned char sBulletDNAstr64[]= {
+83,68,78,65,78,65,77,69,42,1,0,0,109,95,115,105,122,101,0,109,
+95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
+99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
+108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
+115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
+116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
+93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
+95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
+116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
+65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
+101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
+105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
+95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
+114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
+95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
+120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
+118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
+97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
+0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
+101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
+111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
+95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
+111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
+117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
+122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
+114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
+109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
+109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
+97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
+100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
+83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
+108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
+95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
+108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
+0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
+95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
+105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
+83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
+115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
+97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
+109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
+97,108,117,101,115,91,51,93,0,109,95,112,97,100,0,42,109,95,118,101,
+114,116,105,99,101,115,51,102,0,42,109,95,118,101,114,116,105,99,101,115,
+51,100,0,42,109,95,105,110,100,105,99,101,115,51,50,0,42,109,95,51,
+105,110,100,105,99,101,115,49,54,0,42,109,95,51,105,110,100,105,99,101,
+115,56,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,117,
+109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,116,
+105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,114,
+0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,104,
+80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,99,
+101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,66,
+118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,108,
+101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,111,
+77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,105,109,
+101,115,104,83,104,97,112,101,68,97,116,97,0,109,95,116,114,97,110,115,
+102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,0,109,
+95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,99,104,
+105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,83,104,
+97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,104,97,
+112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,103,115,
+0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,95,101,
+100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,101,86,
+50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,98,108,
+101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,95,118,
+97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,121,65,
+114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,115,105,
+108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,110,0,
+109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,104,111,
+108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,104,114,
+101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,104,114,
+101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,109,95,
+104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,109,86,
+97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,103,105,
+109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,115,99,
+97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,0,42,
+109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,117,98,
+108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,100,80,
+111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,93,0,
+42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,101,0,
+42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,42,109,
+95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
+109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,95,105,
+110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,114,97,
+110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,116,105,
+111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,95,105,
+110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,114,86,
+101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,112,105,
+99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,116,80,
+114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,0,109,
+95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,109,95,
+102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,116,105,
+111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,95,99,
+99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,115,0,
+109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,108,100,
+0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,114,105,
+99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,108,97,
+103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,99,111,
+109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,116,105,
+111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,108,84,
+121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,87,105,
+116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,99,116,
+68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,101,110,
+115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,101,108,
+111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,111,99,
+105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,114,0,
+109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,114,97,
+118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,101,108,
+101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,105,97,
+76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,0,109,
+95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,101,114,
+115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,112,105,
+110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,103,0,
+109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,103,70,
+97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,76,105,
+110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,
+83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,
+108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,100,83,
+113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,117,108,
+97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,108,105,
+110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,111,108,
+100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,103,84,
+104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,110,97,
+108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,116,114,
+97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,65,0,
+42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,101,0,
+109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,112,101,
+0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,100,0,
+109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,97,112,
+112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,68,114,
+97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,108,108,
+105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,100,66,
+111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,116,121,
+112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,95,112,
+105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,0,109,
+95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,109,101,
+0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,109,101,
+65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,101,110,
+97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,95,109,
+111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,0,109,
+95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,95,108,
+111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,105,109,
+105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,0,109,
+95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,120,97,
+116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,83,112,
+97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,95,116,
+119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,0,109,
+95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,
+108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,97,
+110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,95,97,
+110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,95,117,
+115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,114,97,
+109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,67,111,
+110,115,116,114,97,105,110,116,70,114,97,109,101,0,109,95,54,100,111,102,
+68,97,116,97,0,109,95,115,112,114,105,110,103,69,110,97,98,108,101,100,
+91,54,93,0,109,95,101,113,117,105,108,105,98,114,105,117,109,80,111,105,
+110,116,91,54,93,0,109,95,115,112,114,105,110,103,83,116,105,102,102,110,
+101,115,115,91,54,93,0,109,95,115,112,114,105,110,103,68,97,109,112,105,
+110,103,91,54,93,0,109,95,108,105,110,101,97,114,83,116,105,102,102,110,
+101,115,115,0,109,95,97,110,103,117,108,97,114,83,116,105,102,102,110,101,
+115,115,0,109,95,118,111,108,117,109,101,83,116,105,102,102,110,101,115,115,
+0,42,109,95,109,97,116,101,114,105,97,108,0,109,95,112,111,115,105,116,
+105,111,110,0,109,95,112,114,101,118,105,111,117,115,80,111,115,105,116,105,
+111,110,0,109,95,118,101,108,111,99,105,116,121,0,109,95,97,99,99,117,
+109,117,108,97,116,101,100,70,111,114,99,101,0,109,95,110,111,114,109,97,
+108,0,109,95,97,114,101,97,0,109,95,97,116,116,97,99,104,0,109,95,
+110,111,100,101,73,110,100,105,99,101,115,91,50,93,0,109,95,114,101,115,
+116,76,101,110,103,116,104,0,109,95,98,98,101,110,100,105,110,103,0,109,
+95,110,111,100,101,73,110,100,105,99,101,115,91,51,93,0,109,95,114,101,
+115,116,65,114,101,97,0,109,95,99,48,91,52,93,0,109,95,110,111,100,
+101,73,110,100,105,99,101,115,91,52,93,0,109,95,114,101,115,116,86,111,
+108,117,109,101,0,109,95,99,49,0,109,95,99,50,0,109,95,99,48,0,
+109,95,108,111,99,97,108,70,114,97,109,101,0,42,109,95,114,105,103,105,
+100,66,111,100,121,0,109,95,110,111,100,101,73,110,100,101,120,0,109,95,
+97,101,114,111,77,111,100,101,108,0,109,95,98,97,117,109,103,97,114,116,
+101,0,109,95,100,114,97,103,0,109,95,108,105,102,116,0,109,95,112,114,
+101,115,115,117,114,101,0,109,95,118,111,108,117,109,101,0,109,95,100,121,
+110,97,109,105,99,70,114,105,99,116,105,111,110,0,109,95,112,111,115,101,
+77,97,116,99,104,0,109,95,114,105,103,105,100,67,111,110,116,97,99,116,
+72,97,114,100,110,101,115,115,0,109,95,107,105,110,101,116,105,99,67,111,
+110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,
+67,111,110,116,97,99,116,72,97,114,100,110,101,115,115,0,109,95,97,110,
+99,104,111,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,82,
+105,103,105,100,67,108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,
+109,95,115,111,102,116,75,105,110,101,116,105,99,67,108,117,115,116,101,114,
+72,97,114,100,110,101,115,115,0,109,95,115,111,102,116,83,111,102,116,67,
+108,117,115,116,101,114,72,97,114,100,110,101,115,115,0,109,95,115,111,102,
+116,82,105,103,105,100,67,108,117,115,116,101,114,73,109,112,117,108,115,101,
+83,112,108,105,116,0,109,95,115,111,102,116,75,105,110,101,116,105,99,67,
+108,117,115,116,101,114,73,109,112,117,108,115,101,83,112,108,105,116,0,109,
+95,115,111,102,116,83,111,102,116,67,108,117,115,116,101,114,73,109,112,117,
+108,115,101,83,112,108,105,116,0,109,95,109,97,120,86,111,108,117,109,101,
+0,109,95,116,105,109,101,83,99,97,108,101,0,109,95,118,101,108,111,99,
+105,116,121,73,116,101,114,97,116,105,111,110,115,0,109,95,112,111,115,105,
+116,105,111,110,73,116,101,114,97,116,105,111,110,115,0,109,95,100,114,105,
+102,116,73,116,101,114,97,116,105,111,110,115,0,109,95,99,108,117,115,116,
+101,114,73,116,101,114,97,116,105,111,110,115,0,109,95,114,111,116,0,109,
+95,115,99,97,108,101,0,109,95,97,113,113,0,109,95,99,111,109,0,42,
+109,95,112,111,115,105,116,105,111,110,115,0,42,109,95,119,101,105,103,104,
+116,115,0,109,95,110,117,109,80,111,115,105,116,105,111,110,115,0,109,95,
+110,117,109,87,101,105,103,116,115,0,109,95,98,118,111,108,117,109,101,0,
+109,95,98,102,114,97,109,101,0,109,95,102,114,97,109,101,120,102,111,114,
+109,0,109,95,108,111,99,105,105,0,109,95,105,110,118,119,105,0,109,95,
+118,105,109,112,117,108,115,101,115,91,50,93,0,109,95,100,105,109,112,117,
+108,115,101,115,91,50,93,0,109,95,108,118,0,109,95,97,118,0,42,109,
+95,102,114,97,109,101,114,101,102,115,0,42,109,95,110,111,100,101,73,110,
+100,105,99,101,115,0,42,109,95,109,97,115,115,101,115,0,109,95,110,117,
+109,70,114,97,109,101,82,101,102,115,0,109,95,110,117,109,78,111,100,101,
+115,0,109,95,110,117,109,77,97,115,115,101,115,0,109,95,105,100,109,97,
+115,115,0,109,95,105,109,97,115,115,0,109,95,110,118,105,109,112,117,108,
+115,101,115,0,109,95,110,100,105,109,112,117,108,115,101,115,0,109,95,110,
+100,97,109,112,105,110,103,0,109,95,108,100,97,109,112,105,110,103,0,109,
+95,97,100,97,109,112,105,110,103,0,109,95,109,97,116,99,104,105,110,103,
+0,109,95,109,97,120,83,101,108,102,67,111,108,108,105,115,105,111,110,73,
+109,112,117,108,115,101,0,109,95,115,101,108,102,67,111,108,108,105,115,105,
+111,110,73,109,112,117,108,115,101,70,97,99,116,111,114,0,109,95,99,111,
+110,116,97,105,110,115,65,110,99,104,111,114,0,109,95,99,111,108,108,105,
+100,101,0,109,95,99,108,117,115,116,101,114,73,110,100,101,120,0,42,109,
+95,98,111,100,121,65,0,42,109,95,98,111,100,121,66,0,109,95,114,101,
+102,115,91,50,93,0,109,95,99,102,109,0,109,95,101,114,112,0,109,95,
+115,112,108,105,116,0,109,95,100,101,108,101,116,101,0,109,95,114,101,108,
+80,111,115,105,116,105,111,110,91,50,93,0,109,95,98,111,100,121,65,116,
+121,112,101,0,109,95,98,111,100,121,66,116,121,112,101,0,109,95,106,111,
+105,110,116,84,121,112,101,0,42,109,95,112,111,115,101,0,42,42,109,95,
+109,97,116,101,114,105,97,108,115,0,42,109,95,110,111,100,101,115,0,42,
+109,95,108,105,110,107,115,0,42,109,95,102,97,99,101,115,0,42,109,95,
+116,101,116,114,97,104,101,100,114,97,0,42,109,95,97,110,99,104,111,114,
+115,0,42,109,95,99,108,117,115,116,101,114,115,0,42,109,95,106,111,105,
+110,116,115,0,109,95,110,117,109,77,97,116,101,114,105,97,108,115,0,109,
+95,110,117,109,76,105,110,107,115,0,109,95,110,117,109,70,97,99,101,115,
+0,109,95,110,117,109,84,101,116,114,97,104,101,100,114,97,0,109,95,110,
+117,109,65,110,99,104,111,114,115,0,109,95,110,117,109,67,108,117,115,116,
+101,114,115,0,109,95,110,117,109,74,111,105,110,116,115,0,109,95,99,111,
+110,102,105,103,0,0,0,0,84,89,80,69,72,0,0,0,99,104,97,114,
+0,117,99,104,97,114,0,115,104,111,114,116,0,117,115,104,111,114,116,0,
+105,110,116,0,108,111,110,103,0,117,108,111,110,103,0,102,108,111,97,116,
+0,100,111,117,98,108,101,0,118,111,105,100,0,80,111,105,110,116,101,114,
+65,114,114,97,121,0,98,116,80,104,121,115,105,99,115,83,121,115,116,101,
+109,0,76,105,115,116,66,97,115,101,0,98,116,86,101,99,116,111,114,51,
+70,108,111,97,116,68,97,116,97,0,98,116,86,101,99,116,111,114,51,68,
+111,117,98,108,101,68,97,116,97,0,98,116,77,97,116,114,105,120,51,120,
+51,70,108,111,97,116,68,97,116,97,0,98,116,77,97,116,114,105,120,51,
+120,51,68,111,117,98,108,101,68,97,116,97,0,98,116,84,114,97,110,115,
+102,111,114,109,70,108,111,97,116,68,97,116,97,0,98,116,84,114,97,110,
+115,102,111,114,109,68,111,117,98,108,101,68,97,116,97,0,98,116,66,118,
+104,83,117,98,116,114,101,101,73,110,102,111,68,97,116,97,0,98,116,79,
+112,116,105,109,105,122,101,100,66,118,104,78,111,100,101,70,108,111,97,116,
+68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,
+111,100,101,68,111,117,98,108,101,68,97,116,97,0,98,116,81,117,97,110,
+116,105,122,101,100,66,118,104,78,111,100,101,68,97,116,97,0,98,116,81,
+117,97,110,116,105,122,101,100,66,118,104,70,108,111,97,116,68,97,116,97,
+0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,68,111,117,98,108,
+101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,83,104,97,
+112,101,68,97,116,97,0,98,116,83,116,97,116,105,99,80,108,97,110,101,
+83,104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,73,110,
+116,101,114,110,97,108,83,104,97,112,101,68,97,116,97,0,98,116,80,111,
+115,105,116,105,111,110,65,110,100,82,97,100,105,117,115,0,98,116,77,117,
+108,116,105,83,112,104,101,114,101,83,104,97,112,101,68,97,116,97,0,98,
+116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,
+116,73,110,116,73,110,100,101,120,68,97,116,97,0,98,116,83,104,111,114,
+116,73,110,116,73,110,100,101,120,84,114,105,112,108,101,116,68,97,116,97,
+0,98,116,67,104,97,114,73,110,100,101,120,84,114,105,112,108,101,116,68,
+97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,97,116,97,0,98,
+116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,116,101,114,102,97,
+99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,77,101,115,
+104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,
+101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,83,99,97,108,101,
+100,84,114,105,97,110,103,108,101,77,101,115,104,83,104,97,112,101,68,97,
+116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,
+105,108,100,68,97,116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,
+97,112,101,68,97,116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,
+97,112,101,68,97,116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,
+112,101,68,97,116,97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,
+111,68,97,116,97,0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,
+104,97,112,101,68,97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,
+108,83,104,97,112,101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,
+111,110,79,98,106,101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,
+116,67,111,108,108,105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,
+116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,
+97,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,
+117,98,108,101,68,97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,
+116,73,110,102,111,49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,
+97,105,110,116,68,97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,
+68,97,116,97,0,98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,
+110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,
+80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,
+116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,
+111,110,115,116,114,97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,
+98,116,72,105,110,103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,
+97,116,68,97,116,97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,
+110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,
+105,99,54,68,111,102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,
+0,98,116,71,101,110,101,114,105,99,54,68,111,102,83,112,114,105,110,103,
+67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,105,
+100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,83,111,
+102,116,66,111,100,121,77,97,116,101,114,105,97,108,68,97,116,97,0,83,
+111,102,116,66,111,100,121,78,111,100,101,68,97,116,97,0,83,111,102,116,
+66,111,100,121,76,105,110,107,68,97,116,97,0,83,111,102,116,66,111,100,
+121,70,97,99,101,68,97,116,97,0,83,111,102,116,66,111,100,121,84,101,
+116,114,97,68,97,116,97,0,83,111,102,116,82,105,103,105,100,65,110,99,
+104,111,114,68,97,116,97,0,83,111,102,116,66,111,100,121,67,111,110,102,
+105,103,68,97,116,97,0,83,111,102,116,66,111,100,121,80,111,115,101,68,
+97,116,97,0,83,111,102,116,66,111,100,121,67,108,117,115,116,101,114,68,
+97,116,97,0,98,116,83,111,102,116,66,111,100,121,74,111,105,110,116,68,
+97,116,97,0,98,116,83,111,102,116,66,111,100,121,70,108,111,97,116,68,
+97,116,97,0,84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,
+4,0,4,0,8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0,
+96,0,64,0,-128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0,
+56,0,56,0,20,0,72,0,4,0,4,0,8,0,4,0,56,0,32,0,
+80,0,72,0,96,0,80,0,32,0,64,0,64,0,16,0,72,0,80,0,
+-40,1,8,1,-16,1,-88,3,8,0,56,0,0,0,88,0,120,0,96,1,
+-32,0,-40,0,0,1,96,1,-48,0,16,0,104,0,24,0,40,0,104,0,
+96,0,104,0,-56,0,104,1,112,0,-40,1,83,84,82,67,61,0,0,0,
+10,0,3,0,4,0,0,0,4,0,1,0,9,0,2,0,11,0,3,0,
+10,0,3,0,10,0,4,0,10,0,5,0,12,0,2,0,9,0,6,0,
+9,0,7,0,13,0,1,0,7,0,8,0,14,0,1,0,8,0,8,0,
+15,0,1,0,13,0,9,0,16,0,1,0,14,0,9,0,17,0,2,0,
+15,0,10,0,13,0,11,0,18,0,2,0,16,0,10,0,14,0,11,0,
+19,0,4,0,4,0,12,0,4,0,13,0,2,0,14,0,2,0,15,0,
+20,0,6,0,13,0,16,0,13,0,17,0,4,0,18,0,4,0,19,0,
+4,0,20,0,0,0,21,0,21,0,6,0,14,0,16,0,14,0,17,0,
+4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,22,0,3,0,
+2,0,14,0,2,0,15,0,4,0,22,0,23,0,12,0,13,0,23,0,
+13,0,24,0,13,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,
+4,0,29,0,20,0,30,0,22,0,31,0,19,0,32,0,4,0,33,0,
+4,0,34,0,24,0,12,0,14,0,23,0,14,0,24,0,14,0,25,0,
+4,0,26,0,4,0,27,0,4,0,28,0,4,0,29,0,21,0,30,0,
+22,0,31,0,4,0,33,0,4,0,34,0,19,0,32,0,25,0,3,0,
+0,0,35,0,4,0,36,0,0,0,37,0,26,0,5,0,25,0,38,0,
+13,0,39,0,13,0,40,0,7,0,41,0,0,0,21,0,27,0,5,0,
+25,0,38,0,13,0,39,0,13,0,42,0,7,0,43,0,4,0,44,0,
+28,0,2,0,13,0,45,0,7,0,46,0,29,0,4,0,27,0,47,0,
+28,0,48,0,4,0,49,0,0,0,37,0,30,0,1,0,4,0,50,0,
+31,0,2,0,2,0,50,0,0,0,51,0,32,0,2,0,2,0,52,0,
+0,0,51,0,33,0,2,0,0,0,52,0,0,0,53,0,34,0,8,0,
+13,0,54,0,14,0,55,0,30,0,56,0,32,0,57,0,33,0,58,0,
+31,0,59,0,4,0,60,0,4,0,61,0,35,0,4,0,34,0,62,0,
+13,0,63,0,4,0,64,0,0,0,37,0,36,0,7,0,25,0,38,0,
+35,0,65,0,23,0,66,0,24,0,67,0,37,0,68,0,7,0,43,0,
+0,0,69,0,38,0,2,0,36,0,70,0,13,0,39,0,39,0,4,0,
+17,0,71,0,25,0,72,0,4,0,73,0,7,0,74,0,40,0,4,0,
+25,0,38,0,39,0,75,0,4,0,76,0,7,0,43,0,41,0,3,0,
+27,0,47,0,4,0,77,0,0,0,37,0,42,0,3,0,27,0,47,0,
+4,0,77,0,0,0,37,0,43,0,4,0,4,0,78,0,7,0,79,0,
+7,0,80,0,7,0,81,0,37,0,14,0,4,0,82,0,4,0,83,0,
+43,0,84,0,4,0,85,0,7,0,86,0,7,0,87,0,7,0,88,0,
+7,0,89,0,7,0,90,0,4,0,91,0,4,0,92,0,4,0,93,0,
+4,0,94,0,0,0,37,0,44,0,5,0,25,0,38,0,35,0,65,0,
+13,0,39,0,7,0,43,0,4,0,95,0,45,0,5,0,27,0,47,0,
+13,0,96,0,14,0,97,0,4,0,98,0,0,0,99,0,46,0,24,0,
+9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,18,0,103,0,
+18,0,104,0,14,0,105,0,14,0,106,0,14,0,107,0,8,0,108,0,
+8,0,109,0,8,0,110,0,8,0,111,0,8,0,112,0,8,0,113,0,
+8,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,
+4,0,119,0,4,0,120,0,4,0,121,0,0,0,37,0,47,0,23,0,
+9,0,100,0,9,0,101,0,25,0,102,0,0,0,35,0,17,0,103,0,
+17,0,104,0,13,0,105,0,13,0,106,0,13,0,107,0,7,0,108,0,
+7,0,109,0,7,0,110,0,7,0,111,0,7,0,112,0,7,0,113,0,
+7,0,114,0,4,0,115,0,4,0,116,0,4,0,117,0,4,0,118,0,
+4,0,119,0,4,0,120,0,4,0,121,0,48,0,21,0,47,0,122,0,
+15,0,123,0,13,0,124,0,13,0,125,0,13,0,126,0,13,0,127,0,
+13,0,-128,0,13,0,-127,0,13,0,-126,0,13,0,-125,0,13,0,-124,0,
+7,0,-123,0,7,0,-122,0,7,0,-121,0,7,0,-120,0,7,0,-119,0,
+7,0,-118,0,7,0,-117,0,7,0,-116,0,7,0,-115,0,4,0,-114,0,
+49,0,22,0,46,0,122,0,16,0,123,0,14,0,124,0,14,0,125,0,
+14,0,126,0,14,0,127,0,14,0,-128,0,14,0,-127,0,14,0,-126,0,
+14,0,-125,0,14,0,-124,0,8,0,-123,0,8,0,-122,0,8,0,-121,0,
+8,0,-120,0,8,0,-119,0,8,0,-118,0,8,0,-117,0,8,0,-116,0,
+8,0,-115,0,4,0,-114,0,0,0,37,0,50,0,2,0,4,0,-113,0,
+4,0,-112,0,51,0,11,0,52,0,-111,0,52,0,-110,0,0,0,35,0,
+4,0,-109,0,4,0,-108,0,4,0,-107,0,4,0,-106,0,7,0,-105,0,
+7,0,-104,0,4,0,-103,0,0,0,-102,0,53,0,3,0,51,0,-101,0,
+13,0,-100,0,13,0,-99,0,54,0,3,0,51,0,-101,0,14,0,-100,0,
+14,0,-99,0,55,0,13,0,51,0,-101,0,18,0,-98,0,18,0,-97,0,
+4,0,-96,0,4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0,
+7,0,-91,0,7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,
+56,0,13,0,51,0,-101,0,17,0,-98,0,17,0,-97,0,4,0,-96,0,
+4,0,-95,0,4,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0,
+7,0,-90,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,57,0,11,0,
+51,0,-101,0,17,0,-98,0,17,0,-97,0,7,0,-86,0,7,0,-85,0,
+7,0,-84,0,7,0,-89,0,7,0,-88,0,7,0,-87,0,7,0,-83,0,
+0,0,21,0,58,0,9,0,51,0,-101,0,17,0,-98,0,17,0,-97,0,
+13,0,-82,0,13,0,-81,0,13,0,-80,0,13,0,-79,0,4,0,-78,0,
+4,0,-77,0,59,0,5,0,58,0,-76,0,4,0,-75,0,7,0,-74,0,
+7,0,-73,0,7,0,-72,0,60,0,9,0,51,0,-101,0,17,0,-98,0,
+17,0,-97,0,7,0,-82,0,7,0,-81,0,7,0,-80,0,7,0,-79,0,
+4,0,-78,0,4,0,-77,0,61,0,4,0,7,0,-71,0,7,0,-70,0,
+7,0,-69,0,4,0,78,0,62,0,10,0,61,0,-68,0,13,0,-67,0,
+13,0,-66,0,13,0,-65,0,13,0,-64,0,13,0,-63,0,7,0,-123,0,
+7,0,-62,0,4,0,-61,0,4,0,53,0,63,0,4,0,61,0,-68,0,
+4,0,-60,0,7,0,-59,0,4,0,-58,0,64,0,4,0,13,0,-63,0,
+61,0,-68,0,4,0,-57,0,7,0,-56,0,65,0,7,0,13,0,-55,0,
+61,0,-68,0,4,0,-54,0,7,0,-53,0,7,0,-52,0,7,0,-51,0,
+4,0,53,0,66,0,6,0,15,0,-50,0,13,0,-52,0,13,0,-49,0,
+52,0,-48,0,4,0,-47,0,7,0,-51,0,67,0,26,0,4,0,-46,0,
+7,0,-45,0,7,0,-83,0,7,0,-44,0,7,0,-43,0,7,0,-42,0,
+7,0,-41,0,7,0,-40,0,7,0,-39,0,7,0,-38,0,7,0,-37,0,
+7,0,-36,0,7,0,-35,0,7,0,-34,0,7,0,-33,0,7,0,-32,0,
+7,0,-31,0,7,0,-30,0,7,0,-29,0,7,0,-28,0,7,0,-27,0,
+4,0,-26,0,4,0,-25,0,4,0,-24,0,4,0,-23,0,4,0,116,0,
+68,0,12,0,15,0,-22,0,15,0,-21,0,15,0,-20,0,13,0,-19,0,
+13,0,-18,0,7,0,-17,0,4,0,-16,0,4,0,-15,0,4,0,-14,0,
+4,0,-13,0,7,0,-53,0,4,0,53,0,69,0,27,0,17,0,-12,0,
+15,0,-11,0,15,0,-10,0,13,0,-19,0,13,0,-9,0,13,0,-8,0,
+13,0,-7,0,13,0,-6,0,13,0,-5,0,4,0,-4,0,7,0,-3,0,
+4,0,-2,0,4,0,-1,0,4,0,0,1,7,0,1,1,7,0,2,1,
+4,0,3,1,4,0,4,1,7,0,5,1,7,0,6,1,7,0,7,1,
+7,0,8,1,7,0,9,1,7,0,10,1,4,0,11,1,4,0,12,1,
+4,0,13,1,70,0,12,0,9,0,14,1,9,0,15,1,13,0,16,1,
+7,0,17,1,7,0,18,1,7,0,19,1,4,0,20,1,13,0,21,1,
+4,0,22,1,4,0,23,1,4,0,24,1,4,0,53,0,71,0,19,0,
+47,0,122,0,68,0,25,1,61,0,26,1,62,0,27,1,63,0,28,1,
+64,0,29,1,65,0,30,1,66,0,31,1,69,0,32,1,70,0,33,1,
+4,0,34,1,4,0,-1,0,4,0,35,1,4,0,36,1,4,0,37,1,
+4,0,38,1,4,0,39,1,4,0,40,1,67,0,41,1,};
+int sBulletDNAlen64= sizeof(sBulletDNAstr64);
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btSerializer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btSerializer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btSerializer.h	(revision 11817)
@@ -0,0 +1,655 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SERIALIZER_H
+#define BT_SERIALIZER_H
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btStackAlloc.h"
+#include "btHashMap.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+
+///only the 32bit versions for now
+extern unsigned char sBulletDNAstr[];
+extern int sBulletDNAlen;
+extern unsigned char sBulletDNAstr64[];
+extern int sBulletDNAlen64;
+
+SIMD_FORCE_INLINE	int btStrLen(const char* str) 
+{
+    if (!str) 
+		return(0);
+	int len = 0;
+    
+	while (*str != 0)
+	{
+        str++;
+        len++;
+    }
+
+    return len;
+}
+
+
+class btChunk
+{
+public:
+	int		m_chunkCode;
+	int		m_length;
+	void	*m_oldPtr;
+	int		m_dna_nr;
+	int		m_number;
+};
+
+enum	btSerializationFlags
+{
+	BT_SERIALIZE_NO_BVH = 1,
+	BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
+	BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
+};
+
+class	btSerializer
+{
+
+public:
+
+	virtual ~btSerializer() {}
+
+	virtual	const unsigned char*		getBufferPointer() const = 0;
+
+	virtual	int		getCurrentBufferSize() const = 0;
+
+	virtual	btChunk*	allocate(size_t size, int numElements) = 0;
+
+	virtual	void	finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
+
+	virtual	 void*	findPointer(void* oldPtr)  = 0;
+
+	virtual	void*	getUniquePointer(void*oldPtr) = 0;
+
+	virtual	void	startSerialization() = 0;
+	
+	virtual	void	finishSerialization() = 0;
+
+	virtual	const char*	findNameForPointer(const void* ptr) const = 0;
+
+	virtual	void	registerNameForPointer(const void* ptr, const char* name) = 0;
+
+	virtual void	serializeName(const char* ptr) = 0;
+
+	virtual int		getSerializationFlags() const = 0;
+
+	virtual void	setSerializationFlags(int flags) = 0;
+
+
+};
+
+
+
+#define BT_HEADER_LENGTH 12
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#	define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+#	define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+#define BT_SOFTBODY_CODE		MAKE_ID('S','B','D','Y')
+#define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
+#define BT_RIGIDBODY_CODE		MAKE_ID('R','B','D','Y')
+#define BT_CONSTRAINT_CODE		MAKE_ID('C','O','N','S')
+#define BT_BOXSHAPE_CODE		MAKE_ID('B','O','X','S')
+#define BT_QUANTIZED_BVH_CODE	MAKE_ID('Q','B','V','H')
+#define BT_TRIANLGE_INFO_MAP	MAKE_ID('T','M','A','P')
+#define BT_SHAPE_CODE			MAKE_ID('S','H','A','P')
+#define BT_ARRAY_CODE			MAKE_ID('A','R','A','Y')
+#define BT_SBMATERIAL_CODE		MAKE_ID('S','B','M','T')
+#define BT_SBNODE_CODE			MAKE_ID('S','B','N','D')
+#define BT_DNA_CODE				MAKE_ID('D','N','A','1')
+
+
+struct	btPointerUid
+{
+	union
+	{
+		void*	m_ptr;
+		int		m_uniqueIds[2];
+	};
+};
+
+///The btDefaultSerializer is the main Bullet serialization class.
+///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
+class btDefaultSerializer	:	public btSerializer
+{
+
+
+	btAlignedObjectArray<char*>			mTypes;
+	btAlignedObjectArray<short*>			mStructs;
+	btAlignedObjectArray<short>			mTlens;
+	btHashMap<btHashInt, int>			mStructReverse;
+	btHashMap<btHashString,int>	mTypeLookup;
+
+	
+	btHashMap<btHashPtr,void*>	m_chunkP;
+	
+	btHashMap<btHashPtr,const char*>	m_nameMap;
+
+	btHashMap<btHashPtr,btPointerUid>	m_uniquePointers;
+	int	m_uniqueIdGenerator;
+
+	int					m_totalSize;
+	unsigned char*		m_buffer;
+	int					m_currentSize;
+	void*				m_dna;
+	int					m_dnaLength;
+
+	int					m_serializationFlags;
+
+
+	btAlignedObjectArray<btChunk*>	m_chunkPtrs;
+	
+protected:
+
+	virtual	void*	findPointer(void* oldPtr) 
+	{
+		void** ptr = m_chunkP.find(oldPtr);
+		if (ptr && *ptr)
+			return *ptr;
+		return 0;
+	}
+
+	
+
+
+
+		void	writeDNA()
+		{
+			btChunk* dnaChunk = allocate(m_dnaLength,1);
+			memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
+			finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
+		}
+
+		int getReverseType(const char *type) const
+		{
+
+			btHashString key(type);
+			const int* valuePtr = mTypeLookup.find(key);
+			if (valuePtr)
+				return *valuePtr;
+			
+			return -1;
+		}
+
+		void initDNA(const char* bdnaOrg,int dnalen)
+		{
+			///was already initialized
+			if (m_dna)
+				return;
+
+			int littleEndian= 1;
+			littleEndian= ((char*)&littleEndian)[0];
+			
+
+			m_dna = btAlignedAlloc(dnalen,16);
+			memcpy(m_dna,bdnaOrg,dnalen);
+			m_dnaLength = dnalen;
+
+			int *intPtr=0;
+			short *shtPtr=0;
+			char *cp = 0;int dataLen =0;long nr=0;
+			intPtr = (int*)m_dna;
+
+			/*
+				SDNA (4 bytes) (magic number)
+				NAME (4 bytes)
+				<nr> (4 bytes) amount of names (int)
+				<string>
+				<string>
+			*/
+
+			if (strncmp((const char*)m_dna, "SDNA", 4)==0)
+			{
+				// skip ++ NAME
+				intPtr++; intPtr++;
+			}
+
+			// Parse names
+			if (!littleEndian)
+				*intPtr = btSwapEndian(*intPtr);
+				
+			dataLen = *intPtr;
+			
+			intPtr++;
+
+			cp = (char*)intPtr;
+			int i;
+			for ( i=0; i<dataLen; i++)
+			{
+				
+				while (*cp)cp++;
+				cp++;
+			}
+			{
+				nr= (long long)cp;
+			//	long mask=3;
+				nr= ((nr+3)&~3)-nr;
+				while (nr--)
+				{
+					cp++;
+				}
+			}
+
+			/*
+				TYPE (4 bytes)
+				<nr> amount of types (int)
+				<string>
+				<string>
+			*/
+
+			intPtr = (int*)cp;
+			assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+			if (!littleEndian)
+				*intPtr =  btSwapEndian(*intPtr);
+			
+			dataLen = *intPtr;
+			intPtr++;
+
+			
+			cp = (char*)intPtr;
+			for (i=0; i<dataLen; i++)
+			{
+				mTypes.push_back(cp);
+				while (*cp)cp++;
+				cp++;
+			}
+
+		{
+				nr= (long long)cp;
+			//	long mask=3;
+				nr= ((nr+3)&~3)-nr;
+				while (nr--)
+				{
+					cp++;
+				}
+			}
+
+
+			/*
+				TLEN (4 bytes)
+				<len> (short) the lengths of types
+				<len>
+			*/
+
+			// Parse type lens
+			intPtr = (int*)cp;
+			assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+			dataLen = (int)mTypes.size();
+
+			shtPtr = (short*)intPtr;
+			for (i=0; i<dataLen; i++, shtPtr++)
+			{
+				if (!littleEndian)
+					shtPtr[0] = btSwapEndian(shtPtr[0]);
+				mTlens.push_back(shtPtr[0]);
+			}
+
+			if (dataLen & 1) shtPtr++;
+
+			/*
+				STRC (4 bytes)
+				<nr> amount of structs (int)
+				<typenr>
+				<nr_of_elems>
+				<typenr>
+				<namenr>
+				<typenr>
+				<namenr>
+			*/
+
+			intPtr = (int*)shtPtr;
+			cp = (char*)intPtr;
+			assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+
+			if (!littleEndian)
+				*intPtr = btSwapEndian(*intPtr);
+			dataLen = *intPtr ; 
+			intPtr++;
+
+
+			shtPtr = (short*)intPtr;
+			for (i=0; i<dataLen; i++)
+			{
+				mStructs.push_back (shtPtr);
+				
+				if (!littleEndian)
+				{
+					shtPtr[0]= btSwapEndian(shtPtr[0]);
+					shtPtr[1]= btSwapEndian(shtPtr[1]);
+
+					int len = shtPtr[1];
+					shtPtr+= 2;
+
+					for (int a=0; a<len; a++, shtPtr+=2)
+					{
+							shtPtr[0]= btSwapEndian(shtPtr[0]);
+							shtPtr[1]= btSwapEndian(shtPtr[1]);
+					}
+
+				} else
+				{
+					shtPtr+= (2*shtPtr[1])+2;
+				}
+			}
+
+			// build reverse lookups
+			for (i=0; i<(int)mStructs.size(); i++)
+			{
+				short *strc = mStructs.at(i);
+				mStructReverse.insert(strc[0], i);
+				mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
+			}
+		}
+
+public:	
+	
+
+	
+
+		btDefaultSerializer(int totalSize=0)
+			:m_totalSize(totalSize),
+			m_currentSize(0),
+			m_dna(0),
+			m_dnaLength(0),
+			m_serializationFlags(0)
+		{
+			m_buffer = m_totalSize?(unsigned char*)btAlignedAlloc(totalSize,16):0;
+			
+			const bool VOID_IS_8 = ((sizeof(void*)==8));
+
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+			if (VOID_IS_8)
+			{
+#if _WIN64
+				initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+#else
+				btAssert(0);
+#endif
+			} else
+			{
+#ifndef _WIN64
+				initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+#else
+				btAssert(0);
+#endif
+			}
+	
+#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+			if (VOID_IS_8)
+			{
+				initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+			} else
+			{
+				initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+			}
+#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+	
+		}
+
+		virtual ~btDefaultSerializer() 
+		{
+			if (m_buffer)
+				btAlignedFree(m_buffer);
+			if (m_dna)
+				btAlignedFree(m_dna);
+		}
+
+		void	writeHeader(unsigned char* buffer) const
+		{
+			
+
+#ifdef  BT_USE_DOUBLE_PRECISION
+			memcpy(buffer, "BULLETd", 7);
+#else
+			memcpy(buffer, "BULLETf", 7);
+#endif //BT_USE_DOUBLE_PRECISION
+	
+			int littleEndian= 1;
+			littleEndian= ((char*)&littleEndian)[0];
+
+			if (sizeof(void*)==8)
+			{
+				buffer[7] = '-';
+			} else
+			{
+				buffer[7] = '_';
+			}
+
+			if (littleEndian)
+			{
+				buffer[8]='v';				
+			} else
+			{
+				buffer[8]='V';
+			}
+
+
+			buffer[9] = '2';
+			buffer[10] = '7';
+			buffer[11] = '8';
+
+		}
+
+		virtual	void	startSerialization()
+		{
+			m_uniqueIdGenerator= 1;
+			if (m_totalSize)
+			{
+				unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
+				writeHeader(buffer);
+			}
+			
+		}
+
+		virtual	void	finishSerialization()
+		{
+			writeDNA();
+
+			//if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
+			int mysize = 0;
+			if (!m_totalSize)
+			{
+				if (m_buffer)
+					btAlignedFree(m_buffer);
+
+				m_currentSize += BT_HEADER_LENGTH;
+				m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize,16);
+
+				unsigned char* currentPtr = m_buffer;
+				writeHeader(m_buffer);
+				currentPtr += BT_HEADER_LENGTH;
+				mysize+=BT_HEADER_LENGTH;
+				for (int i=0;i<	m_chunkPtrs.size();i++)
+				{
+					int curLength = sizeof(btChunk)+m_chunkPtrs[i]->m_length;
+					memcpy(currentPtr,m_chunkPtrs[i], curLength);
+					btAlignedFree(m_chunkPtrs[i]);
+					currentPtr+=curLength;
+					mysize+=curLength;
+				}
+			}
+
+			mTypes.clear();
+			mStructs.clear();
+			mTlens.clear();
+			mStructReverse.clear();
+			mTypeLookup.clear();
+			m_chunkP.clear();
+			m_nameMap.clear();
+			m_uniquePointers.clear();
+			m_chunkPtrs.clear();
+		}
+
+		virtual	void*	getUniquePointer(void*oldPtr)
+		{
+			if (!oldPtr)
+				return 0;
+
+			btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
+			if (uptr)
+			{
+				return uptr->m_ptr;
+			}
+			m_uniqueIdGenerator++;
+			
+			btPointerUid uid;
+			uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+			uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+			m_uniquePointers.insert(oldPtr,uid);
+			return uid.m_ptr;
+
+		}
+
+		virtual	const unsigned char*		getBufferPointer() const
+		{
+			return m_buffer;
+		}
+
+		virtual	int					getCurrentBufferSize() const
+		{
+			return	m_currentSize;
+		}
+
+		virtual	void	finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
+		{
+			if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+			{
+				btAssert(!findPointer(oldPtr));
+			}
+
+			chunk->m_dna_nr = getReverseType(structType);
+			
+			chunk->m_chunkCode = chunkCode;
+			
+			void* uniquePtr = getUniquePointer(oldPtr);
+			
+			m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
+			chunk->m_oldPtr = uniquePtr;//oldPtr;
+			
+		}
+
+		
+		virtual unsigned char* internalAlloc(size_t size)
+		{
+			unsigned char* ptr = 0;
+
+			if (m_totalSize)
+			{
+				ptr = m_buffer+m_currentSize;
+				m_currentSize += int(size);
+				btAssert(m_currentSize<m_totalSize);
+			} else
+			{
+				ptr = (unsigned char*)btAlignedAlloc(size,16);
+				m_currentSize += int(size);
+			}
+			return ptr;
+		}
+
+		
+
+		virtual	btChunk*	allocate(size_t size, int numElements)
+		{
+
+			unsigned char* ptr = internalAlloc(int(size)*numElements+sizeof(btChunk));
+
+			unsigned char* data = ptr + sizeof(btChunk);
+			
+			btChunk* chunk = (btChunk*)ptr;
+			chunk->m_chunkCode = 0;
+			chunk->m_oldPtr = data;
+			chunk->m_length = int(size)*numElements;
+			chunk->m_number = numElements;
+			
+			m_chunkPtrs.push_back(chunk);
+			
+
+			return chunk;
+		}
+
+		virtual	const char*	findNameForPointer(const void* ptr) const
+		{
+			const char*const * namePtr = m_nameMap.find(ptr);
+			if (namePtr && *namePtr)
+				return *namePtr;
+			return 0;
+
+		}
+
+		virtual	void	registerNameForPointer(const void* ptr, const char* name)
+		{
+			m_nameMap.insert(ptr,name);
+		}
+
+		virtual void	serializeName(const char* name)
+		{
+			if (name)
+			{
+				//don't serialize name twice
+				if (findPointer((void*)name))
+					return;
+
+				int len = btStrLen(name);
+				if (len)
+				{
+
+					int newLen = len+1;
+					int padding = ((newLen+3)&~3)-newLen;
+					newLen += padding;
+
+					//serialize name string now
+					btChunk* chunk = allocate(sizeof(char),newLen);
+					char* destinationName = (char*)chunk->m_oldPtr;
+					for (int i=0;i<len;i++)
+					{
+						destinationName[i] = name[i];
+					}
+					destinationName[len] = 0;
+					finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
+				}
+			}
+		}
+
+		virtual int		getSerializationFlags() const
+		{
+			return m_serializationFlags;
+		}
+
+		virtual void	setSerializationFlags(int flags)
+		{
+			m_serializationFlags = flags;
+		}
+
+};
+
+
+#endif //BT_SERIALIZER_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btStackAlloc.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btStackAlloc.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btStackAlloc.h	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
+Nov.2006
+*/
+
+#ifndef BT_STACK_ALLOC
+#define BT_STACK_ALLOC
+
+#include "btScalar.h" //for btAssert
+#include "btAlignedAllocator.h"
+
+///The btBlock class is an internal structure for the btStackAlloc memory allocator.
+struct btBlock
+{
+	btBlock*			previous;
+	unsigned char*		address;
+};
+
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
+class btStackAlloc
+{
+public:
+
+	btStackAlloc(unsigned int size)	{ ctor();create(size); }
+	~btStackAlloc()		{ destroy(); }
+	
+	inline void		create(unsigned int size)
+	{
+		destroy();
+		data		=  (unsigned char*) btAlignedAlloc(size,16);
+		totalsize	=	size;
+	}
+	inline void		destroy()
+	{
+		btAssert(usedsize==0);
+		//Raise(L"StackAlloc is still in use");
+
+		if(usedsize==0)
+		{
+			if(!ischild && data)		
+				btAlignedFree(data);
+
+			data				=	0;
+			usedsize			=	0;
+		}
+		
+	}
+
+	int	getAvailableMemory() const
+	{
+		return static_cast<int>(totalsize - usedsize);
+	}
+
+	unsigned char*			allocate(unsigned int size)
+	{
+		const unsigned int	nus(usedsize+size);
+		if(nus<totalsize)
+		{
+			usedsize=nus;
+			return(data+(usedsize-size));
+		}
+		btAssert(0);
+		//&& (L"Not enough memory"));
+		
+		return(0);
+	}
+	SIMD_FORCE_INLINE btBlock*		beginBlock()
+	{
+		btBlock*	pb = (btBlock*)allocate(sizeof(btBlock));
+		pb->previous	=	current;
+		pb->address		=	data+usedsize;
+		current			=	pb;
+		return(pb);
+	}
+	SIMD_FORCE_INLINE void		endBlock(btBlock* block)
+	{
+		btAssert(block==current);
+		//Raise(L"Unmatched blocks");
+		if(block==current)
+		{
+			current		=	block->previous;
+			usedsize	=	(unsigned int)((block->address-data)-sizeof(btBlock));
+		}
+	}
+
+private:
+	void		ctor()
+	{
+		data		=	0;
+		totalsize	=	0;
+		usedsize	=	0;
+		current		=	0;
+		ischild		=	false;
+	}
+	unsigned char*		data;
+	unsigned int		totalsize;
+	unsigned int		usedsize;
+	btBlock*	current;
+	bool		ischild;
+};
+
+#endif //BT_STACK_ALLOC
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btTransform.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btTransform.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btTransform.h	(revision 11817)
@@ -0,0 +1,307 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_TRANSFORM_H
+#define BT_TRANSFORM_H
+
+
+#include "btMatrix3x3.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btTransformData btTransformDoubleData
+#else
+#define btTransformData btTransformFloatData
+#endif
+
+
+
+
+/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
+ *It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
+class btTransform {
+	
+  ///Storage for the rotation
+	btMatrix3x3 m_basis;
+  ///Storage for the translation
+	btVector3   m_origin;
+
+public:
+	
+  /**@brief No initialization constructor */
+	btTransform() {}
+  /**@brief Constructor from btQuaternion (optional btVector3 )
+   * @param q Rotation from quaternion 
+   * @param c Translation from Vector (default 0,0,0) */
+	explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, 
+		const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) 
+		: m_basis(q),
+		m_origin(c)
+	{}
+
+  /**@brief Constructor from btMatrix3x3 (optional btVector3)
+   * @param b Rotation from Matrix 
+   * @param c Translation from Vector default (0,0,0)*/
+	explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, 
+		const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+		: m_basis(b),
+		m_origin(c)
+	{}
+  /**@brief Copy constructor */
+	SIMD_FORCE_INLINE btTransform (const btTransform& other)
+		: m_basis(other.m_basis),
+		m_origin(other.m_origin)
+	{
+	}
+  /**@brief Assignment Operator */
+	SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
+	{
+		m_basis = other.m_basis;
+		m_origin = other.m_origin;
+		return *this;
+	}
+
+
+  /**@brief Set the current transform as the value of the product of two transforms
+   * @param t1 Transform 1
+   * @param t2 Transform 2
+   * This = Transform1 * Transform2 */
+		SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) {
+			m_basis = t1.m_basis * t2.m_basis;
+			m_origin = t1(t2.m_origin);
+		}
+
+/*		void multInverseLeft(const btTransform& t1, const btTransform& t2) {
+			btVector3 v = t2.m_origin - t1.m_origin;
+			m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
+			m_origin = v * t1.m_basis;
+		}
+		*/
+
+/**@brief Return the transform of the vector */
+	SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
+	{
+		return btVector3(m_basis[0].dot(x) + m_origin.x(), 
+			m_basis[1].dot(x) + m_origin.y(), 
+			m_basis[2].dot(x) + m_origin.z());
+	}
+
+  /**@brief Return the transform of the vector */
+	SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
+	{
+		return (*this)(x);
+	}
+
+  /**@brief Return the transform of the btQuaternion */
+	SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
+	{
+		return getRotation() * q;
+	}
+
+  /**@brief Return the basis matrix for the rotation */
+	SIMD_FORCE_INLINE btMatrix3x3&       getBasis()          { return m_basis; }
+  /**@brief Return the basis matrix for the rotation */
+	SIMD_FORCE_INLINE const btMatrix3x3& getBasis()    const { return m_basis; }
+
+  /**@brief Return the origin vector translation */
+	SIMD_FORCE_INLINE btVector3&         getOrigin()         { return m_origin; }
+  /**@brief Return the origin vector translation */
+	SIMD_FORCE_INLINE const btVector3&   getOrigin()   const { return m_origin; }
+
+  /**@brief Return a quaternion representing the rotation */
+	btQuaternion getRotation() const { 
+		btQuaternion q;
+		m_basis.getRotation(q);
+		return q;
+	}
+	
+	
+  /**@brief Set from an array 
+   * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+	void setFromOpenGLMatrix(const btScalar *m)
+	{
+		m_basis.setFromOpenGLSubMatrix(m);
+		m_origin.setValue(m[12],m[13],m[14]);
+	}
+
+  /**@brief Fill an array representation
+   * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+	void getOpenGLMatrix(btScalar *m) const 
+	{
+		m_basis.getOpenGLSubMatrix(m);
+		m[12] = m_origin.x();
+		m[13] = m_origin.y();
+		m[14] = m_origin.z();
+		m[15] = btScalar(1.0);
+	}
+
+  /**@brief Set the translational element
+   * @param origin The vector to set the translation to */
+	SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) 
+	{ 
+		m_origin = origin;
+	}
+
+	SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
+
+
+  /**@brief Set the rotational element by btMatrix3x3 */
+	SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
+	{ 
+		m_basis = basis;
+	}
+
+  /**@brief Set the rotational element by btQuaternion */
+	SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
+	{
+		m_basis.setRotation(q);
+	}
+
+
+  /**@brief Set this transformation to the identity */
+	void setIdentity()
+	{
+		m_basis.setIdentity();
+		m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	}
+
+  /**@brief Multiply this Transform by another(this = this * another) 
+   * @param t The other transform */
+	btTransform& operator*=(const btTransform& t) 
+	{
+		m_origin += m_basis * t.m_origin;
+		m_basis *= t.m_basis;
+		return *this;
+	}
+
+  /**@brief Return the inverse of this transform */
+	btTransform inverse() const
+	{ 
+		btMatrix3x3 inv = m_basis.transpose();
+		return btTransform(inv, inv * -m_origin);
+	}
+
+  /**@brief Return the inverse of this transform times the other transform
+   * @param t The other transform 
+   * return this.inverse() * the other */
+	btTransform inverseTimes(const btTransform& t) const;  
+
+  /**@brief Return the product of this transform and the other */
+	btTransform operator*(const btTransform& t) const;
+
+  /**@brief Return an identity transform */
+	static const btTransform&	getIdentity()
+	{
+		static const btTransform identityTransform(btMatrix3x3::getIdentity());
+		return identityTransform;
+	}
+
+	void	serialize(struct	btTransformData& dataOut) const;
+
+	void	serializeFloat(struct	btTransformFloatData& dataOut) const;
+
+	void	deSerialize(const struct	btTransformData& dataIn);
+
+	void	deSerializeDouble(const struct	btTransformDoubleData& dataIn);
+
+	void	deSerializeFloat(const struct	btTransformFloatData& dataIn);
+
+};
+
+
+SIMD_FORCE_INLINE btVector3
+btTransform::invXform(const btVector3& inVec) const
+{
+	btVector3 v = inVec - m_origin;
+	return (m_basis.transpose() * v);
+}
+
+SIMD_FORCE_INLINE btTransform 
+btTransform::inverseTimes(const btTransform& t) const  
+{
+	btVector3 v = t.getOrigin() - m_origin;
+		return btTransform(m_basis.transposeTimes(t.m_basis),
+			v * m_basis);
+}
+
+SIMD_FORCE_INLINE btTransform 
+btTransform::operator*(const btTransform& t) const
+{
+	return btTransform(m_basis * t.m_basis, 
+		(*this)(t.m_origin));
+}
+
+/**@brief Test if two transforms have all elements equal */
+SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
+{
+   return ( t1.getBasis()  == t2.getBasis() &&
+            t1.getOrigin() == t2.getOrigin() );
+}
+
+
+///for serialization
+struct	btTransformFloatData
+{
+	btMatrix3x3FloatData	m_basis;
+	btVector3FloatData	m_origin;
+};
+
+struct	btTransformDoubleData
+{
+	btMatrix3x3DoubleData	m_basis;
+	btVector3DoubleData	m_origin;
+};
+
+
+
+SIMD_FORCE_INLINE	void	btTransform::serialize(btTransformData& dataOut) const
+{
+	m_basis.serialize(dataOut.m_basis);
+	m_origin.serialize(dataOut.m_origin);
+}
+
+SIMD_FORCE_INLINE	void	btTransform::serializeFloat(btTransformFloatData& dataOut) const
+{
+	m_basis.serializeFloat(dataOut.m_basis);
+	m_origin.serializeFloat(dataOut.m_origin);
+}
+
+
+SIMD_FORCE_INLINE	void	btTransform::deSerialize(const btTransformData& dataIn)
+{
+	m_basis.deSerialize(dataIn.m_basis);
+	m_origin.deSerialize(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE	void	btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
+{
+	m_basis.deSerializeFloat(dataIn.m_basis);
+	m_origin.deSerializeFloat(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE	void	btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
+{
+	m_basis.deSerializeDouble(dataIn.m_basis);
+	m_origin.deSerializeDouble(dataIn.m_origin);
+}
+
+
+#endif //BT_TRANSFORM_H
+
+
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btTransformUtil.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btTransformUtil.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btTransformUtil.h	(revision 11817)
@@ -0,0 +1,228 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_TRANSFORM_UTIL_H
+#define BT_TRANSFORM_UTIL_H
+
+#include "btTransform.h"
+#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
+
+
+
+
+SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
+{
+	return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
+      supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
+      supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); 
+}
+
+
+
+
+
+
+/// Utils related to temporal transforms
+class btTransformUtil
+{
+
+public:
+
+	static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
+	{
+		predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
+//	#define QUATERNION_DERIVATIVE
+	#ifdef QUATERNION_DERIVATIVE
+		btQuaternion predictedOrn = curTrans.getRotation();
+		predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
+		predictedOrn.normalize();
+	#else
+		//Exponential map
+		//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
+		btVector3 axis;
+		btScalar	fAngle = angvel.length(); 
+		//limit the angular motion
+		if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
+		{
+			fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
+		}
+
+		if ( fAngle < btScalar(0.001) )
+		{
+			// use Taylor's expansions of sync function
+			axis   = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
+		}
+		else
+		{
+			// sync(fAngle) = sin(c*fAngle)/t
+			axis   = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
+		}
+		btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
+		btQuaternion orn0 = curTrans.getRotation();
+
+		btQuaternion predictedOrn = dorn * orn0;
+		predictedOrn.normalize();
+	#endif
+		predictedTransform.setRotation(predictedOrn);
+	}
+
+	static void	calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+	{
+		linVel = (pos1 - pos0) / timeStep;
+		btVector3 axis;
+		btScalar  angle;
+		if (orn0 != orn1)
+		{
+			calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
+			angVel = axis * angle / timeStep;
+		} else
+		{
+			angVel.setValue(0,0,0);
+		}
+	}
+
+	static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
+	{
+		btQuaternion orn1 = orn0.nearest(orn1a);
+		btQuaternion dorn = orn1 * orn0.inverse();
+		angle = dorn.getAngle();
+		axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+		axis[3] = btScalar(0.);
+		//check for axis length
+		btScalar len = axis.length2();
+		if (len < SIMD_EPSILON*SIMD_EPSILON)
+			axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+		else
+			axis /= btSqrt(len);
+	}
+
+	static void	calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+	{
+		linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
+		btVector3 axis;
+		btScalar  angle;
+		calculateDiffAxisAngle(transform0,transform1,axis,angle);
+		angVel = axis * angle / timeStep;
+	}
+
+	static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
+	{
+		btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
+		btQuaternion dorn;
+		dmat.getRotation(dorn);
+
+		///floating point inaccuracy can lead to w component > 1..., which breaks 
+		dorn.normalize();
+		
+		angle = dorn.getAngle();
+		axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+		axis[3] = btScalar(0.);
+		//check for axis length
+		btScalar len = axis.length2();
+		if (len < SIMD_EPSILON*SIMD_EPSILON)
+			axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+		else
+			axis /= btSqrt(len);
+	}
+
+};
+
+
+///The btConvexSeparatingDistanceUtil can help speed up convex collision detection 
+///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
+class	btConvexSeparatingDistanceUtil
+{
+	btQuaternion	m_ornA;
+	btQuaternion	m_ornB;
+	btVector3	m_posA;
+	btVector3	m_posB;
+	
+	btVector3	m_separatingNormal;
+
+	btScalar	m_boundingRadiusA;
+	btScalar	m_boundingRadiusB;
+	btScalar	m_separatingDistance;
+
+public:
+
+	btConvexSeparatingDistanceUtil(btScalar	boundingRadiusA,btScalar	boundingRadiusB)
+		:m_boundingRadiusA(boundingRadiusA),
+		m_boundingRadiusB(boundingRadiusB),
+		m_separatingDistance(0.f)
+	{
+	}
+
+	btScalar	getConservativeSeparatingDistance()
+	{
+		return m_separatingDistance;
+	}
+
+	void	updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
+	{
+		const btVector3& toPosA = transA.getOrigin();
+		const btVector3& toPosB = transB.getOrigin();
+		btQuaternion toOrnA = transA.getRotation();
+		btQuaternion toOrnB = transB.getRotation();
+
+		if (m_separatingDistance>0.f)
+		{
+			
+
+			btVector3 linVelA,angVelA,linVelB,angVelB;
+			btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
+			btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
+			btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
+			btVector3 relLinVel = (linVelB-linVelA);
+			btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
+			if (relLinVelocLength<0.f)
+			{
+				relLinVelocLength = 0.f;
+			}
+	
+			btScalar	projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
+			m_separatingDistance -= projectedMotion;
+		}
+	
+		m_posA = toPosA;
+		m_posB = toPosB;
+		m_ornA = toOrnA;
+		m_ornB = toOrnB;
+	}
+
+	void	initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
+	{
+		m_separatingDistance = separatingDistance;
+
+		if (m_separatingDistance>0.f)
+		{
+			m_separatingNormal = separatingVector;
+			
+			const btVector3& toPosA = transA.getOrigin();
+			const btVector3& toPosB = transB.getOrigin();
+			btQuaternion toOrnA = transA.getRotation();
+			btQuaternion toOrnB = transB.getRotation();
+			m_posA = toPosA;
+			m_posB = toPosB;
+			m_ornA = toOrnA;
+			m_ornB = toOrnB;
+		}
+	}
+
+};
+
+
+#endif //BT_TRANSFORM_UTIL_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btVector3.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btVector3.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/LinearMath/btVector3.h	(revision 11817)
@@ -0,0 +1,766 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef BT_VECTOR3_H
+#define BT_VECTOR3_H
+
+
+#include "btScalar.h"
+#include "btMinMax.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btVector3Data btVector3DoubleData
+#define btVector3DataName "btVector3DoubleData"
+#else
+#define btVector3Data btVector3FloatData
+#define btVector3DataName "btVector3FloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+
+/**@brief btVector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+ATTRIBUTE_ALIGNED16(class) btVector3
+{
+public:
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+		btScalar	m_floats[4];
+public:
+	SIMD_FORCE_INLINE const vec_float4&	get128() const
+	{
+		return *((const vec_float4*)&m_floats[0]);
+	}
+public:
+#else //__CELLOS_LV2__ __SPU__
+#ifdef BT_USE_SSE // _WIN32
+	union {
+		__m128 mVec128;
+		btScalar	m_floats[4];
+	};
+	SIMD_FORCE_INLINE	__m128	get128() const
+	{
+		return mVec128;
+	}
+	SIMD_FORCE_INLINE	void	set128(__m128 v128)
+	{
+		mVec128 = v128;
+	}
+#else
+	btScalar	m_floats[4];
+#endif
+#endif //__CELLOS_LV2__ __SPU__
+
+	public:
+
+  /**@brief No initialization constructor */
+	SIMD_FORCE_INLINE btVector3() {}
+
+ 
+	
+  /**@brief Constructor from scalars 
+   * @param x X value
+   * @param y Y value 
+   * @param z Z value 
+   */
+	SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
+	{
+		m_floats[0] = x;
+		m_floats[1] = y;
+		m_floats[2] = z;
+		m_floats[3] = btScalar(0.);
+	}
+
+	
+/**@brief Add a vector to this one 
+ * @param The vector to add to this one */
+	SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
+	{
+
+		m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2];
+		return *this;
+	}
+
+
+  /**@brief Subtract a vector from this one
+   * @param The vector to subtract */
+	SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) 
+	{
+		m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2];
+		return *this;
+	}
+  /**@brief Scale the vector
+   * @param s Scale factor */
+	SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
+	{
+		m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s;
+		return *this;
+	}
+
+  /**@brief Inversely scale the vector 
+   * @param s Scale factor to divide by */
+	SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) 
+	{
+		btFullAssert(s != btScalar(0.0));
+		return *this *= btScalar(1.0) / s;
+	}
+
+  /**@brief Return the dot product
+   * @param v The other vector in the dot product */
+	SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
+	{
+		return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2];
+	}
+
+  /**@brief Return the length of the vector squared */
+	SIMD_FORCE_INLINE btScalar length2() const
+	{
+		return dot(*this);
+	}
+
+  /**@brief Return the length of the vector */
+	SIMD_FORCE_INLINE btScalar length() const
+	{
+		return btSqrt(length2());
+	}
+
+  /**@brief Return the distance squared between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+	SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
+
+  /**@brief Return the distance between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+	SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
+
+	SIMD_FORCE_INLINE btVector3& safeNormalize() 
+	{
+		btVector3 absVec = this->absolute();
+		int maxIndex = absVec.maxAxis();
+		if (absVec[maxIndex]>0)
+		{
+			*this /= absVec[maxIndex];
+			return *this /= length();
+		}
+		setValue(1,0,0);
+		return *this;
+	}
+
+  /**@brief Normalize this vector 
+   * x^2 + y^2 + z^2 = 1 */
+	SIMD_FORCE_INLINE btVector3& normalize() 
+	{
+		return *this /= length();
+	}
+
+  /**@brief Return a normalized version of this vector */
+	SIMD_FORCE_INLINE btVector3 normalized() const;
+
+  /**@brief Return a rotated version of this vector
+   * @param wAxis The axis to rotate about 
+   * @param angle The angle to rotate by */
+	SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const;
+
+  /**@brief Return the angle between this and another vector
+   * @param v The other vector */
+	SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const 
+	{
+		btScalar s = btSqrt(length2() * v.length2());
+		btFullAssert(s != btScalar(0.0));
+		return btAcos(dot(v) / s);
+	}
+  /**@brief Return a vector will the absolute values of each element */
+	SIMD_FORCE_INLINE btVector3 absolute() const 
+	{
+		return btVector3(
+			btFabs(m_floats[0]), 
+			btFabs(m_floats[1]), 
+			btFabs(m_floats[2]));
+	}
+  /**@brief Return the cross product between this and another vector 
+   * @param v The other vector */
+	SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
+	{
+		return btVector3(
+			m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1],
+			m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+			m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+	}
+
+	SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
+	{
+		return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + 
+			m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + 
+			m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+	}
+
+  /**@brief Return the axis with the smallest value 
+   * Note return values are 0,1,2 for x, y, or z */
+	SIMD_FORCE_INLINE int minAxis() const
+	{
+		return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
+	}
+
+  /**@brief Return the axis with the largest value 
+   * Note return values are 0,1,2 for x, y, or z */
+	SIMD_FORCE_INLINE int maxAxis() const 
+	{
+		return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
+	}
+
+	SIMD_FORCE_INLINE int furthestAxis() const
+	{
+		return absolute().minAxis();
+	}
+
+	SIMD_FORCE_INLINE int closestAxis() const 
+	{
+		return absolute().maxAxis();
+	}
+
+	SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
+	{
+		btScalar s = btScalar(1.0) - rt;
+		m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+		m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+		m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+		//don't do the unused w component
+		//		m_co[3] = s * v0[3] + rt * v1[3];
+	}
+
+  /**@brief Return the linear interpolation between this and another vector 
+   * @param v The other vector 
+   * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+	SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const 
+	{
+		return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+			m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+			m_floats[2] + (v.m_floats[2] -m_floats[2]) * t);
+	}
+
+  /**@brief Elementwise multiply this vector by the other 
+   * @param v The other vector */
+	SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
+	{
+		m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2];
+		return *this;
+	}
+
+	 /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+  /**@brief Set the x value */
+		SIMD_FORCE_INLINE void	setX(btScalar x) { m_floats[0] = x;};
+  /**@brief Set the y value */
+		SIMD_FORCE_INLINE void	setY(btScalar y) { m_floats[1] = y;};
+  /**@brief Set the z value */
+		SIMD_FORCE_INLINE void	setZ(btScalar z) {m_floats[2] = z;};
+  /**@brief Set the w value */
+		SIMD_FORCE_INLINE void	setW(btScalar w) { m_floats[3] = w;};
+  /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+  /**@brief Return the w value */
+		SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+	//SIMD_FORCE_INLINE btScalar&       operator[](int i)       { return (&m_floats[0])[i];	}      
+	//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+	///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+	SIMD_FORCE_INLINE	operator       btScalar *()       { return &m_floats[0]; }
+	SIMD_FORCE_INLINE	operator const btScalar *() const { return &m_floats[0]; }
+
+	SIMD_FORCE_INLINE	bool	operator==(const btVector3& other) const
+	{
+		return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
+	}
+
+	SIMD_FORCE_INLINE	bool	operator!=(const btVector3& other) const
+	{
+		return !(*this == other);
+	}
+
+	 /**@brief Set each element to the max of the current values and the values of another btVector3
+   * @param other The other btVector3 to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMax(const btVector3& other)
+		{
+			btSetMax(m_floats[0], other.m_floats[0]);
+			btSetMax(m_floats[1], other.m_floats[1]);
+			btSetMax(m_floats[2], other.m_floats[2]);
+			btSetMax(m_floats[3], other.w());
+		}
+  /**@brief Set each element to the min of the current values and the values of another btVector3
+   * @param other The other btVector3 to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMin(const btVector3& other)
+		{
+			btSetMin(m_floats[0], other.m_floats[0]);
+			btSetMin(m_floats[1], other.m_floats[1]);
+			btSetMin(m_floats[2], other.m_floats[2]);
+			btSetMin(m_floats[3], other.w());
+		}
+
+		SIMD_FORCE_INLINE void 	setValue(const btScalar& x, const btScalar& y, const btScalar& z)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3] = btScalar(0.);
+		}
+
+		void	getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
+		{
+			v0->setValue(0.		,-z()		,y());
+			v1->setValue(z()	,0.			,-x());
+			v2->setValue(-y()	,x()	,0.);
+		}
+
+		void	setZero()
+		{
+			setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+		}
+
+		SIMD_FORCE_INLINE bool isZero() const 
+		{
+			return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
+		}
+
+		SIMD_FORCE_INLINE bool fuzzyZero() const 
+		{
+			return length2() < SIMD_EPSILON;
+		}
+
+		SIMD_FORCE_INLINE	void	serialize(struct	btVector3Data& dataOut) const;
+
+		SIMD_FORCE_INLINE	void	deSerialize(const struct	btVector3Data& dataIn);
+
+		SIMD_FORCE_INLINE	void	serializeFloat(struct	btVector3FloatData& dataOut) const;
+
+		SIMD_FORCE_INLINE	void	deSerializeFloat(const struct	btVector3FloatData& dataIn);
+
+		SIMD_FORCE_INLINE	void	serializeDouble(struct	btVector3DoubleData& dataOut) const;
+
+		SIMD_FORCE_INLINE	void	deSerializeDouble(const struct	btVector3DoubleData& dataIn);
+
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+SIMD_FORCE_INLINE btVector3 
+operator+(const btVector3& v1, const btVector3& v2) 
+{
+	return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]);
+}
+
+/**@brief Return the elementwise product of two vectors */
+SIMD_FORCE_INLINE btVector3 
+operator*(const btVector3& v1, const btVector3& v2) 
+{
+	return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]);
+}
+
+/**@brief Return the difference between two vectors */
+SIMD_FORCE_INLINE btVector3 
+operator-(const btVector3& v1, const btVector3& v2)
+{
+	return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]);
+}
+/**@brief Return the negative of the vector */
+SIMD_FORCE_INLINE btVector3 
+operator-(const btVector3& v)
+{
+	return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3 
+operator*(const btVector3& v, const btScalar& s)
+{
+	return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3 
+operator*(const btScalar& s, const btVector3& v)
+{ 
+	return v * s; 
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v, const btScalar& s)
+{
+	btFullAssert(s != btScalar(0.0));
+	return v * (btScalar(1.0) / s);
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v1, const btVector3& v2)
+{
+	return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]);
+}
+
+/**@brief Return the dot product between two vectors */
+SIMD_FORCE_INLINE btScalar 
+btDot(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.dot(v2); 
+}
+
+
+/**@brief Return the distance squared between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance2(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.distance2(v2); 
+}
+
+
+/**@brief Return the distance between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.distance(v2); 
+}
+
+/**@brief Return the angle between two vectors */
+SIMD_FORCE_INLINE btScalar
+btAngle(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.angle(v2); 
+}
+
+/**@brief Return the cross product of two vectors */
+SIMD_FORCE_INLINE btVector3 
+btCross(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.cross(v2); 
+}
+
+SIMD_FORCE_INLINE btScalar
+btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
+{
+	return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector 
+ * @param v2 The other vector 
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+SIMD_FORCE_INLINE btVector3 
+lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
+{
+	return v1.lerp(v2, t);
+}
+
+
+
+SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
+{
+	return (v - *this).length2();
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
+{
+	return (v - *this).length();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
+{
+	return *this / length();
+} 
+
+SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) const
+{
+	// wAxis must be a unit lenght vector
+
+	btVector3 o = wAxis * wAxis.dot( *this );
+	btVector3 x = *this - o;
+	btVector3 y;
+
+	y = wAxis.cross( *this );
+
+	return ( o + x * btCos( angle ) + y * btSin( angle ) );
+}
+
+class btVector4 : public btVector3
+{
+public:
+
+	SIMD_FORCE_INLINE btVector4() {}
+
+
+	SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 
+		: btVector3(x,y,z)
+	{
+		m_floats[3] = w;
+	}
+
+
+	SIMD_FORCE_INLINE btVector4 absolute4() const 
+	{
+		return btVector4(
+			btFabs(m_floats[0]), 
+			btFabs(m_floats[1]), 
+			btFabs(m_floats[2]),
+			btFabs(m_floats[3]));
+	}
+
+
+
+	btScalar	getW() const { return m_floats[3];}
+
+
+		SIMD_FORCE_INLINE int maxAxis4() const
+	{
+		int maxIndex = -1;
+		btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
+		if (m_floats[0] > maxVal)
+		{
+			maxIndex = 0;
+			maxVal = m_floats[0];
+		}
+		if (m_floats[1] > maxVal)
+		{
+			maxIndex = 1;
+			maxVal = m_floats[1];
+		}
+		if (m_floats[2] > maxVal)
+		{
+			maxIndex = 2;
+			maxVal =m_floats[2];
+		}
+		if (m_floats[3] > maxVal)
+		{
+			maxIndex = 3;
+			maxVal = m_floats[3];
+		}
+		
+		
+		
+
+		return maxIndex;
+
+	}
+
+
+	SIMD_FORCE_INLINE int minAxis4() const
+	{
+		int minIndex = -1;
+		btScalar minVal = btScalar(BT_LARGE_FLOAT);
+		if (m_floats[0] < minVal)
+		{
+			minIndex = 0;
+			minVal = m_floats[0];
+		}
+		if (m_floats[1] < minVal)
+		{
+			minIndex = 1;
+			minVal = m_floats[1];
+		}
+		if (m_floats[2] < minVal)
+		{
+			minIndex = 2;
+			minVal =m_floats[2];
+		}
+		if (m_floats[3] < minVal)
+		{
+			minIndex = 3;
+			minVal = m_floats[3];
+		}
+		
+		return minIndex;
+
+	}
+
+
+	SIMD_FORCE_INLINE int closestAxis4() const 
+	{
+		return absolute4().maxAxis4();
+	}
+
+	
+ 
+
+  /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+		
+
+/*		void getValue(btScalar *m) const 
+		{
+			m[0] = m_floats[0];
+			m[1] = m_floats[1];
+			m[2] =m_floats[2];
+		}
+*/
+/**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+		SIMD_FORCE_INLINE void	setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3]=w;
+		}
+
+
+};
+
+
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void	btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
+{
+	#ifdef BT_USE_DOUBLE_PRECISION
+	unsigned char* dest = (unsigned char*) &destVal;
+	unsigned char* src  = (unsigned char*) &sourceVal;
+	dest[0] = src[7];
+    dest[1] = src[6];
+    dest[2] = src[5];
+    dest[3] = src[4];
+    dest[4] = src[3];
+    dest[5] = src[2];
+    dest[6] = src[1];
+    dest[7] = src[0];
+#else
+	unsigned char* dest = (unsigned char*) &destVal;
+	unsigned char* src  = (unsigned char*) &sourceVal;
+	dest[0] = src[3];
+    dest[1] = src[2];
+    dest[2] = src[1];
+    dest[3] = src[0];
+#endif //BT_USE_DOUBLE_PRECISION
+}
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void	btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
+{
+	for (int i=0;i<4;i++)
+	{
+		btSwapScalarEndian(sourceVec[i],destVec[i]);
+	}
+
+}
+
+///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void	btUnSwapVector3Endian(btVector3& vector)
+{
+
+	btVector3	swappedVec;
+	for (int i=0;i<4;i++)
+	{
+		btSwapScalarEndian(vector[i],swappedVec[i]);
+	}
+	vector = swappedVec;
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q)
+{
+  if (btFabs(n[2]) > SIMDSQRT12) {
+    // choose p in y-z plane
+    btScalar a = n[1]*n[1] + n[2]*n[2];
+    btScalar k = btRecipSqrt (a);
+    p[0] = 0;
+	p[1] = -n[2]*k;
+	p[2] = n[1]*k;
+    // set q = n x p
+    q[0] = a*k;
+	q[1] = -n[0]*p[2];
+	q[2] = n[0]*p[1];
+  }
+  else {
+    // choose p in x-y plane
+    btScalar a = n[0]*n[0] + n[1]*n[1];
+    btScalar k = btRecipSqrt (a);
+    p[0] = -n[1]*k;
+	p[1] = n[0]*k;
+	p[2] = 0;
+    // set q = n x p
+    q[0] = -n[2]*p[1];
+	q[1] = n[2]*p[0];
+	q[2] = a*k;
+  }
+}
+
+
+struct	btVector3FloatData
+{
+	float	m_floats[4];
+};
+
+struct	btVector3DoubleData
+{
+	double	m_floats[4];
+
+};
+
+SIMD_FORCE_INLINE	void	btVector3::serializeFloat(struct	btVector3FloatData& dataOut) const
+{
+	///could also do a memcpy, check if it is worth it
+	for (int i=0;i<4;i++)
+		dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void	btVector3::deSerializeFloat(const struct	btVector3FloatData& dataIn)
+{
+	for (int i=0;i<4;i++)
+		m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE	void	btVector3::serializeDouble(struct	btVector3DoubleData& dataOut) const
+{
+	///could also do a memcpy, check if it is worth it
+	for (int i=0;i<4;i++)
+		dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void	btVector3::deSerializeDouble(const struct	btVector3DoubleData& dataIn)
+{
+	for (int i=0;i<4;i++)
+		m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE	void	btVector3::serialize(struct	btVector3Data& dataOut) const
+{
+	///could also do a memcpy, check if it is worth it
+	for (int i=0;i<4;i++)
+		dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void	btVector3::deSerialize(const struct	btVector3Data& dataIn)
+{
+	for (int i=0;i<4;i++)
+		m_floats[i] = dataIn.m_floats[i];
+}
+
+
+#endif //BT_VECTOR3_H
Index: /code/branches/RacingBots_FS18/src/external/bullet/NEWS
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/NEWS	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/NEWS	(revision 11817)
@@ -0,0 +1,4 @@
+
+For news, visit the Bullet Physics forums at
+http://www.bulletphysics.org
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/README	(revision 11817)
@@ -0,0 +1,6 @@
+
+Bullet is a 3D Collision Detection and Rigid Body Dynamics Library for games and animation.
+Free for commercial use, including Playstation 3, open source under the ZLib License.
+
+See the Bullet_User_Manual.pdf for more info and visit the Bullet Physics Forum at
+http://bulletphysics.org
Index: /code/branches/RacingBots_FS18/src/external/bullet/VERSION
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/VERSION	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/VERSION	(revision 11817)
@@ -0,0 +1,1 @@
+2.78
Index: /code/branches/RacingBots_FS18/src/external/bullet/btBulletCollisionCommon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/btBulletCollisionCommon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/btBulletCollisionCommon.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_COLLISION_COMMON_H
+#define BULLET_COLLISION_COMMON_H
+
+///Common headerfile includes for Bullet Collision Detection
+
+///Bullet's btCollisionWorld and btCollisionObject definitions
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+///Collision Shapes
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "BulletCollision/CollisionShapes/btEmptyShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
+
+///Narrowphase Collision Detector
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+
+//btSphereBoxCollisionAlgorithm is broken, use gjk for now
+//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+///Dispatching and generation of collision pairs (broadphase)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
+#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
+
+///Math library & Utils
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+
+#endif //BULLET_COLLISION_COMMON_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/btBulletDynamicsCommon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/btBulletDynamicsCommon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/btBulletDynamicsCommon.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_DYNAMICS_COMMON_H
+#define BULLET_DYNAMICS_COMMON_H
+
+///Common headerfile includes for Bullet Dynamics, including Collision Detection
+#include "btBulletCollisionCommon.h"
+
+#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
+#include "BulletDynamics/Dynamics/btContinuousDynamicsWorld.h"
+
+#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h"
+
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+
+
+///Vehicle simulation, with wheel contact simulated by raycasts
+#include "BulletDynamics/Vehicle/btRaycastVehicle.h"
+
+
+
+
+
+
+#endif //BULLET_DYNAMICS_COMMON_H
+
Index: /code/branches/RacingBots_FS18/src/external/bullet/changes_orxonox.diff
===================================================================
--- /code/branches/RacingBots_FS18/src/external/bullet/changes_orxonox.diff	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/bullet/changes_orxonox.diff	(revision 11817)
@@ -0,0 +1,1 @@
+
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/CHANGES
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/CHANGES	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/CHANGES	(revision 11817)
@@ -0,0 +1,46 @@
+This file contains the history of changes in the C++/Tcl library.
+
+---
+The version 1.1.3 differs from 1.1.2 in the following ways:
+
+- A bug in the initialization of interpreter object was fixed.
+
+---
+The version 1.1.2 differs from 1.1.1 in the following ways:
+
+- Copyright was updated to cover 2006.
+
+- Information was added to docs about the usage of the Boost library.
+
+- Few bug fixes were applied to allow empty parameter lists with variadic
+  functions.
+
+---
+The version 1.1.1 differs from 1.1.0 in the following ways:
+
+- Explicit instantiations of some templates were moved to proper namespace.
+
+
+---
+The version 1.1.0 differs from 1.0.0 in the following ways:
+
+- CHANGES file was added.
+
+- LICENSE file was added with clear description of the license terms.
+
+- Copyright was updated to cover 2005.
+
+- Small patch was added to make the code compile on g++ 3.2.
+
+- New assign method was added that accepts Tcl_Obj.
+
+- Overload of interpreter::eval was added that accepts istream& parameter.
+  This allows to evaluate the contents of arbitrary stream
+  (for example, a file).
+
+- Support for package definitions was added.
+
+- Support for const class member functions was added.
+
+- Support for variadic free functions, constructors and class methods
+  was added.
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,43 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET(CPPTCL_FILES
+  cpptcl.h
+  cpptcl.cc
+
+  details/callbacks.h
+  details/callbacks_v.h
+  details/constructors.h
+  details/conversions.h
+  details/dispatchers.h
+  details/metahelpers.h
+  details/methods.h
+  details/methods_v.h
+)
+
+ORXONOX_ADD_LIBRARY(cpptcl_orxonox
+  ORXONOX_EXTERNAL
+  NO_DLL_INTERFACE
+  VERSION
+    1.1.3
+  LINK_LIBRARIES
+    ${TCL_LIBRARY}
+  SOURCE_FILES
+    ${CPPTCL_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/CREDITS
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/CREDITS	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/CREDITS	(revision 11817)
@@ -0,0 +1,11 @@
+I would like to thank you very much for your contributions:
+
+---
+Alexey Pakhunov provided patches with various bugfixes and enhancements.
+His patches were used in the 1.1.2 release.
+
+---
+Christoph Pesch provided a small patch for the g++ 3.2 compiler.
+
+After the 1.1.0 release, Christoph provided also a patch for newer g++ 3.4.3.
+(included in 1.1.1)
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/LICENSE
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/LICENSE	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/LICENSE	(revision 11817)
@@ -0,0 +1,39 @@
+Each source file contains the following notice:
+
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+The above is the shortest license I have found.
+I have copied this wording from one of the source files of the Boost library.
+
+Just to explain the above terms:
+
+1. The library is free (like in "freedom").
+
+2. You can use it for any purpose you wish. You can even sell it.
+
+3. You can modify the source files. If you do this, please feel free to add
+   your own copyright notices wherever you want, if you want.
+   You may also add more restrictive license terms.
+   You only have to keep the above notice unchanged in all source files.
+
+4. You can combine this library or its modified version with other software.
+   The license claims nothing that would affect the resulting work.
+   See point 3. if you need to make any modifications.
+
+5. You can compile this library or its modified version to the binary form.
+   The license does not affect the compiled result in any way.
+   In particular, you do not need to (but you still can) display the above
+   copyright notice to the final user, and you do not need to (but you still
+   can) inform the final user that your product was prepared with the help
+   of this library.
+
+6. Do not sue me for my (and your) mistakes and errors.
+
+As you see, this license is very permissive.
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/README	(revision 11817)
@@ -0,0 +1,32 @@
+C++/Tcl - a C++ library for interoperability between C++ and Tcl.
+
+Copyright (C) 2004-2006, Maciej Sobczak
+
+---
+
+You should see the following directories here:
+
+- doc      - contains a short documentation for the library
+- examples - some simple examples to show C++/Tcl basics
+- test     - tests used for development - use them for regression testing
+             if you want to modify the library
+- details  - some additional code used by the library (not for client use)
+
+In addition, the following files may be of interest to you:
+
+- README   - this file
+- LICENSE  - explanation of the license terms
+- CHANGES  - the history of changes
+
+
+The C++/Tcl itself consists of these files:
+- cpptcl.h   - to be included in your own files
+- cpptcl.cc  - to be compiled and linked with your code
+
+
+In order to compile the tests and the examples you may need to change the
+compiler options to fit your particular environment (different paths to the
+Tcl headers and libs, another compiler, etc.)
+
+
+Anyway - have fun! :-)
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/changes_orxonox.diff
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/changes_orxonox.diff	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/changes_orxonox.diff	(revision 11817)
@@ -0,0 +1,91 @@
+--- cpptcl.cc	Fri Apr 22 12:18:47 2011
++++ cpptcl.cc	Fri Apr 22 12:20:02 2011
+@@ -16,7 +16,8 @@
+ using namespace Tcl;
+ using namespace Tcl::details;
+ using namespace std;
+-using namespace boost;
++// boost::shared_ptr conflicts with the new std::shared_ptr
++//using namespace boost;
+ 
+ 
+ result::result(Tcl_Interp *interp) : interp_(interp) {}
+@@ -166,7 +167,7 @@
+ {
+ 
+ // map of polymorphic callbacks
+-typedef map<string, shared_ptr<callback_base> > callback_interp_map;
++typedef map<string, boost::shared_ptr<callback_base> > callback_interp_map;
+ typedef map<Tcl_Interp *, callback_interp_map> callback_map;
+ 
+ callback_map callbacks;
+@@ -179,7 +180,7 @@
+ policies_map call_policies;
+ 
+ // map of object handlers
+-typedef map<string, shared_ptr<class_handler_base> > class_interp_map;
++typedef map<string, boost::shared_ptr<class_handler_base> > class_interp_map;
+ typedef map<Tcl_Interp *, class_interp_map> class_handlers_map;
+ 
+ class_handlers_map class_handlers;
+@@ -320,7 +321,7 @@
+ 
+           post_process_policies(interp, pol, objv, false);
+      }
+-     catch (exception const &e)
++     catch (std::exception const &e)
+      {
+           Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
+           return TCL_ERROR;
+@@ -363,7 +364,7 @@
+ 
+           post_process_policies(interp, pol, objv, true);
+      }
+-     catch (exception const &e)
++     catch (std::exception const &e)
+      {
+           Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
+           return TCL_ERROR;
+@@ -430,7 +431,7 @@
+                Tcl_GetString(Tcl_GetObjResult(interp)),
+                object_handler, static_cast<ClientData>(chb), 0);
+      }
+-     catch (exception const &e)
++     catch (std::exception const &e)
+      {
+           Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
+           return TCL_ERROR;
+@@ -490,7 +491,7 @@
+ }
+ 
+ void class_handler_base::register_method(string const &name,
+-     shared_ptr<object_cmd_base> ocb, policies const &p)
++     boost::shared_ptr<object_cmd_base> ocb, policies const &p)
+ {
+      methods_[name] = ocb;
+      policies_[name] = p;
+@@ -989,7 +990,7 @@
+ }
+ 
+ void interpreter::add_function(string const &name,
+-     shared_ptr<callback_base> cb, policies const &p)
++     boost::shared_ptr<callback_base> cb, policies const &p)
+ {
+      Tcl_CreateObjCommand(interp_, name.c_str(),
+           callback_handler, 0, 0);
+@@ -999,13 +1000,13 @@
+ }
+ 
+ void interpreter::add_class(string const &name,
+-     shared_ptr<class_handler_base> chb)
++     boost::shared_ptr<class_handler_base> chb)
+ {
+      class_handlers[interp_][name] = chb;
+ }
+ 
+ void interpreter::add_constructor(string const &name,
+-     shared_ptr<class_handler_base> chb, shared_ptr<callback_base> cb,
++     boost::shared_ptr<class_handler_base> chb, boost::shared_ptr<callback_base> cb,
+      policies const &p)
+ {
+      Tcl_CreateObjCommand(interp_, name.c_str(),
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/cpptcl.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/cpptcl.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/cpptcl.cc	(revision 11817)
@@ -0,0 +1,1081 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+#include "cpptcl.h"
+#include <map>
+#include <sstream>
+#include <iterator>
+
+
+using namespace Tcl;
+using namespace Tcl::details;
+using namespace std;
+
+result::result(Tcl_Interp *interp) : interp_(interp) {}
+
+result::operator bool() const
+{
+     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
+     
+     int val, cc;
+     cc = Tcl_GetBooleanFromObj(interp_, obj, &val);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+     
+     return static_cast<bool>(val);
+}
+
+result::operator double() const
+{
+     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
+     
+     double val;
+     int cc = Tcl_GetDoubleFromObj(interp_, obj, &val);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+     
+     return val;
+}
+
+result::operator int() const
+{
+     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
+     
+     int val, cc;
+     cc = Tcl_GetIntFromObj(interp_, obj, &val);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+     
+     return val;
+}
+
+result::operator long() const
+{
+     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
+     
+     long val;
+     int cc;
+     cc = Tcl_GetLongFromObj(interp_, obj, &val);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+     
+     return val;
+}
+
+result::operator string() const
+{
+     Tcl_Obj *obj = Tcl_GetObjResult(interp_);
+     return Tcl_GetString(obj);
+}
+
+result::operator object() const
+{
+     return object(Tcl_GetObjResult(interp_));
+}
+
+
+void details::set_result(Tcl_Interp *interp, bool b)
+{
+     Tcl_SetObjResult(interp, Tcl_NewBooleanObj(b));
+}
+
+void details::set_result(Tcl_Interp *interp, int i)
+{
+     Tcl_SetObjResult(interp, Tcl_NewIntObj(i));
+}
+
+void details::set_result(Tcl_Interp *interp, long i)
+{
+     Tcl_SetObjResult(interp, Tcl_NewLongObj(i));
+}
+
+void details::set_result(Tcl_Interp *interp, double d)
+{
+     Tcl_SetObjResult(interp, Tcl_NewDoubleObj(d));
+}
+
+void details::set_result(Tcl_Interp *interp, string const &s)
+{
+     Tcl_SetObjResult(interp,
+          Tcl_NewStringObj(s.data(), static_cast<int>(s.size())));
+}
+
+void details::set_result(Tcl_Interp *interp, void *p)
+{
+     ostringstream ss;
+     ss << 'p' << p;
+     string s(ss.str());
+
+     Tcl_SetObjResult(interp,
+          Tcl_NewStringObj(s.data(), static_cast<int>(s.size())));
+}
+
+void details::set_result(Tcl_Interp *interp, object const &o)
+{
+     Tcl_SetObjResult(interp, o.get_object());
+}
+
+
+void details::check_params_no(int objc, int required)
+{
+     if (objc < required)
+     {
+          throw tcl_error("Too few arguments.");
+     }
+}
+
+object details::get_var_params(Tcl_Interp *interp,
+     int objc, Tcl_Obj * CONST objv[],
+     int from, policies const &pol)
+{
+     object o;
+     if (pol.variadic_)
+     {
+          check_params_no(objc, from);
+          o.assign(objv + from, objv + objc);
+     }
+     else
+     {
+          check_params_no(objc, from + 1);
+          o.assign(objv[from]);
+     }
+
+     o.set_interp(interp);
+
+     return o;
+}
+
+
+namespace // anonymous
+{
+
+// map of polymorphic callbacks
+typedef map<string, std::shared_ptr<callback_base> > callback_interp_map;
+typedef map<Tcl_Interp *, callback_interp_map> callback_map;
+
+callback_map callbacks;
+callback_map constructors;
+
+// map of call policies
+typedef map<string, policies> policies_interp_map;
+typedef map<Tcl_Interp *, policies_interp_map> policies_map;
+
+policies_map call_policies;
+
+// map of object handlers
+typedef map<string, std::shared_ptr<class_handler_base> > class_interp_map;
+typedef map<Tcl_Interp *, class_interp_map> class_handlers_map;
+
+class_handlers_map class_handlers;
+
+
+// helper for finding call policies - returns true when found
+bool find_policies(Tcl_Interp *interp, string const &cmdName,
+     policies_interp_map::iterator &piti)
+{
+     policies_map::iterator pit = call_policies.find(interp);
+     if (pit == call_policies.end())
+     {
+          return false;
+     }
+     
+     piti = pit->second.find(cmdName);
+     return piti != pit->second.end();
+}
+
+extern "C"
+int object_handler(ClientData cd, Tcl_Interp *interp,
+     int objc, Tcl_Obj * CONST objv[]);
+
+// helper function for post-processing call policies
+// for both free functions (isMethod == false)
+// and class methods (isMethod == true)
+void post_process_policies(Tcl_Interp *interp, policies &pol,
+     Tcl_Obj * CONST objv[], bool isMethod)
+{
+     // check if it is a factory
+     if (!pol.factory_.empty())
+     {
+          class_handlers_map::iterator it = class_handlers.find(interp);
+          if (it == class_handlers.end())
+          {
+               throw tcl_error(
+                    "Factory was registered for unknown class.");
+          }
+
+          class_interp_map::iterator oit = it->second.find(pol.factory_);
+          if (oit == it->second.end())
+          {
+               throw tcl_error(
+                    "Factory was registered for unknown class.");
+          }
+
+          class_handler_base *chb = oit->second.get();
+
+          // register a new command for the object returned
+          // by this factory function
+          // if everything went OK, the result is the address of the
+          // new object in the 'pXXX' form
+          // - the new command will be created with this name
+
+          Tcl_CreateObjCommand(interp,
+               Tcl_GetString(Tcl_GetObjResult(interp)),
+               object_handler, static_cast<ClientData>(chb), 0);
+     }
+
+     // process all declared sinks
+     // - unregister all object commands that envelopes the pointers
+     for (vector<int>::iterator s = pol.sinks_.begin();
+          s != pol.sinks_.end(); ++s)
+     {
+          if (isMethod == false)
+          {
+               // example: if there is a declared sink at parameter 3,
+               // and the Tcl command was:
+               // % fun par1 par2 PAR3 par4
+               // then the index 3 correctly points into the objv array
+
+               int index = *s;
+               Tcl_DeleteCommand(interp, Tcl_GetString(objv[index]));
+          }
+          else
+          {
+               // example: if there is a declared sink at parameter 3,
+               // and the Tcl command was:
+               // % $p method par1 par2 PAR3 par4
+               // then the index 3 needs to be incremented
+               // in order correctly point into the 4th index of objv array
+
+               int index = *s + 1;
+               Tcl_DeleteCommand(interp, Tcl_GetString(objv[index]));
+          }
+     }
+}
+
+// actual functions handling various callbacks
+
+// generic callback handler
+extern "C"
+int callback_handler(ClientData, Tcl_Interp *interp,
+     int objc, Tcl_Obj * CONST objv[])
+{
+     callback_map::iterator it = callbacks.find(interp);
+     if (it == callbacks.end())
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke non-existent callback (wrong interpreter?)",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+     
+     string cmdName(Tcl_GetString(objv[0]));
+     callback_interp_map::iterator iti = it->second.find(cmdName);
+     if (iti == it->second.end())
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke non-existent callback (wrong cmd name?)",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+     
+     policies_map::iterator pit = call_policies.find(interp);
+     if (pit == call_policies.end())
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke callback with no known policies",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+     
+     policies_interp_map::iterator piti;
+     if (find_policies(interp, cmdName, piti) == false)
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke callback with no known policies",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+
+     policies &pol = piti->second;
+     
+     try
+     {
+          iti->second->invoke(interp, objc, objv, pol);
+
+          post_process_policies(interp, pol, objv, false);
+     }
+     catch (std::exception const &e)
+     {
+          Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
+          return TCL_ERROR;
+     }
+     catch (...)
+     {
+          Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
+          return TCL_ERROR;
+     }
+     
+     return TCL_OK;
+}
+
+// generic "object" command handler
+extern "C"
+int object_handler(ClientData cd, Tcl_Interp *interp,
+     int objc, Tcl_Obj * CONST objv[])
+{
+     // here, client data points to the singleton object
+     // which is responsible for managing commands for
+     // objects of a given type
+
+     class_handler_base *chb = reinterpret_cast<class_handler_base*>(cd);
+
+     // the command name has the form 'pXXX' where XXX is the address
+     // of the "this" object
+
+     string const str(Tcl_GetString(objv[0]));
+     istringstream ss(str);
+     char dummy;
+     void *p;
+     ss >> dummy >> p;
+
+     try
+     {
+          string methodName(Tcl_GetString(objv[1]));
+          policies &pol = chb->get_policies(methodName);
+
+          chb->invoke(p, interp, objc, objv, pol);
+
+          post_process_policies(interp, pol, objv, true);
+     }
+     catch (std::exception const &e)
+     {
+          Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
+          return TCL_ERROR;
+     }
+     catch (...)
+     {
+          Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
+          return TCL_ERROR;
+     }
+
+     return TCL_OK;
+}
+
+// generic "constructor" command
+extern "C"
+int constructor_handler(ClientData cd, Tcl_Interp *interp,
+     int objc, Tcl_Obj * CONST objv[])
+{
+     // here, client data points to the singleton object
+     // which is responsible for managing commands for
+     // objects of a given type
+
+     class_handler_base *chb = reinterpret_cast<class_handler_base*>(cd);
+
+     callback_map::iterator it = constructors.find(interp);
+     if (it == constructors.end())
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke non-existent callback (wrong interpreter?)",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+     
+     string className(Tcl_GetString(objv[0]));
+     callback_interp_map::iterator iti = it->second.find(className);
+     if (iti == it->second.end())
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke non-existent callback (wrong class name?)",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+     
+     policies_interp_map::iterator piti;
+     if (find_policies(interp, className, piti) == false)
+     {
+          Tcl_SetResult(interp,
+               "Trying to invoke callback with no known policies",
+               TCL_STATIC);
+          return TCL_ERROR;
+     }
+
+     policies &pol = piti->second;
+
+     try
+     {
+          iti->second->invoke(interp, objc, objv, pol);
+
+          // if everything went OK, the result is the address of the
+          // new object in the 'pXXX' form
+          // - we can create a new command with this name
+
+          Tcl_CreateObjCommand(interp,
+               Tcl_GetString(Tcl_GetObjResult(interp)),
+               object_handler, static_cast<ClientData>(chb), 0);
+     }
+     catch (std::exception const &e)
+     {
+          Tcl_SetResult(interp, const_cast<char*>(e.what()), TCL_VOLATILE);
+          return TCL_ERROR;
+     }
+     catch (...)
+     {
+          Tcl_SetResult(interp, "Unknown error.", TCL_STATIC);
+          return TCL_ERROR;
+     }
+
+     return TCL_OK;
+}
+
+} // namespace anonymous
+
+Tcl::details::no_init_type Tcl::no_init;
+
+
+policies & policies::factory(string const &name)
+{
+     factory_ = name;
+     return *this;
+}
+
+policies & policies::sink(int index)
+{
+     sinks_.push_back(index);
+     return *this;
+}
+
+policies & policies::variadic()
+{
+     variadic_ = true;
+     return *this;
+}
+
+policies Tcl::factory(string const &name)
+{
+     return policies().factory(name);
+}
+
+policies Tcl::sink(int index)
+{
+     return policies().sink(index);
+}
+
+policies Tcl::variadic()
+{
+     return policies().variadic();
+}
+
+
+class_handler_base::class_handler_base()
+{
+     // default policies for the -delete command
+     policies_["-delete"] = policies();
+}
+
+void class_handler_base::register_method(string const &name,
+     std::shared_ptr<object_cmd_base> ocb, policies const &p)
+{
+     methods_[name] = ocb;
+     policies_[name] = p;
+}
+
+policies & class_handler_base::get_policies(string const &name)
+{
+     policies_map_type::iterator it = policies_.find(name);
+     if (it == policies_.end())
+     {
+          throw tcl_error("Trying to use non-existent policy: " + name);
+     }
+
+     return it->second;
+}
+
+
+object::object()
+     : interp_(0)
+{
+     obj_ = Tcl_NewObj();
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(bool b)
+     : interp_(0)
+{
+     obj_ = Tcl_NewBooleanObj(b);
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(char const *buf, size_t size)
+     : interp_(0)
+{
+     obj_ = Tcl_NewByteArrayObj(
+          reinterpret_cast<unsigned char const *>(buf),
+          static_cast<int>(size));
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(double d)
+     : interp_(0)
+{
+     obj_ = Tcl_NewDoubleObj(d);
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(int i)
+     : interp_(0)
+{
+     obj_ = Tcl_NewIntObj(i);
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(long l)
+     : interp_(0)
+{
+     obj_ = Tcl_NewLongObj(l);
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(char const *s)
+     : interp_(0)
+{
+     obj_ = Tcl_NewStringObj(s, -1);
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(string const &s)
+     : interp_(0)
+{
+     obj_ = Tcl_NewStringObj(s.data(), static_cast<int>(s.size()));
+     Tcl_IncrRefCount(obj_);
+}
+
+object::object(Tcl_Obj *o, bool shared)
+     : interp_(0)
+{
+     init(o, shared);
+}
+
+object::object(object const &other, bool shared)
+     : interp_(other.get_interp())
+{
+     init(other.obj_, shared);
+}
+
+void object::init(Tcl_Obj *o, bool shared)
+{
+     if (shared)
+     {
+          obj_ = o;
+     }
+     else
+     {
+          obj_ = Tcl_DuplicateObj(o);
+     }
+     Tcl_IncrRefCount(obj_);
+}
+
+object::~object()
+{
+     Tcl_DecrRefCount(obj_);
+}
+
+object & object::assign(bool b)
+{
+     Tcl_SetBooleanObj(obj_, b);
+     return *this;
+}
+
+object & object::resize(size_t size)
+{
+     Tcl_SetByteArrayLength(obj_, static_cast<int>(size));
+     return *this;
+}
+
+object & object::assign(char const *buf, size_t size)
+{
+     Tcl_SetByteArrayObj(obj_,
+          reinterpret_cast<unsigned char const *>(buf),
+          static_cast<int>(size));
+     return *this;
+}
+
+object & object::assign(double d)
+{
+     Tcl_SetDoubleObj(obj_, d);
+     return *this;
+}
+
+object & object::assign(int i)
+{
+     Tcl_SetIntObj(obj_, i);
+     return *this;
+}
+
+object & object::assign(long l)
+{
+     Tcl_SetLongObj(obj_, l);
+     return *this;
+}
+
+object & object::assign(char const *s)
+{
+     Tcl_SetStringObj(obj_, s, -1);
+     return *this;
+}
+
+object & object::assign(string const &s)
+{
+     Tcl_SetStringObj(obj_, s.data(), static_cast<int>(s.size()));
+     return *this;
+}
+
+object & object::assign(object const &other)
+{
+     object(other).swap(*this);
+     return *this;
+}
+
+object & object::assign(Tcl_Obj *o)
+{
+     object(o).swap(*this);
+     return *this;
+}
+
+object & object::swap(object &other)
+{
+     std::swap(obj_, other.obj_);
+     std::swap(interp_, other.interp_);
+     return *this;
+}
+
+template <>
+bool object::get<bool>(interpreter &i) const
+{
+     int retVal;
+     int res = Tcl_GetBooleanFromObj(i.get(), obj_, &retVal);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return static_cast<bool>(retVal);
+}
+
+template <>
+vector<char> object::get<vector<char> >(interpreter &) const
+{
+     size_t size;
+     char const *buf = get(size);
+     return vector<char>(buf, buf + size);
+}
+
+template <>
+double object::get<double>(interpreter &i) const
+{
+     double retVal;
+     int res = Tcl_GetDoubleFromObj(i.get(), obj_, &retVal);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return retVal;
+}
+
+template <>
+int object::get<int>(interpreter &i) const
+{
+     int retVal;
+
+     int res = Tcl_GetIntFromObj(i.get(), obj_, &retVal);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return retVal;
+}
+
+template <>
+long object::get<long>(interpreter &i) const
+{
+     long retVal;
+     int res = Tcl_GetLongFromObj(i.get(), obj_, &retVal);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return retVal;
+}
+
+template <>
+char const * object::get<char const *>(interpreter &) const
+{
+     return get();
+}
+
+template <>
+string object::get<string>(interpreter &) const
+{
+     int len;
+     char const *buf = Tcl_GetStringFromObj(obj_, &len);
+     return string(buf, buf + len);
+}
+
+char const * object::get() const
+{
+     return Tcl_GetString(obj_);
+}
+
+char const * object::get(size_t &size) const
+{
+     int len;
+     unsigned char *buf = Tcl_GetByteArrayFromObj(obj_, &len);
+     size = len;
+     return const_cast<char const *>(reinterpret_cast<char *>(buf));
+}
+
+size_t object::length(interpreter &i) const
+{
+     int len;
+     int res = Tcl_ListObjLength(i.get(), obj_, &len);
+
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return static_cast<size_t>(len);
+}
+
+object object::at(interpreter &i, size_t index) const
+{
+     Tcl_Obj *o;
+     int res = Tcl_ListObjIndex(i.get(), obj_, static_cast<int>(index), &o);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+     if (o == NULL)
+     {
+          throw tcl_error("Index out of range.");
+     }
+
+     return object(o);
+}
+
+object & object::append(interpreter &i, object const &o)
+{
+     int res = Tcl_ListObjAppendElement(i.get(), obj_, o.obj_);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return *this;
+}
+
+object & object::append_list(interpreter &i, object const &o)
+{
+     int res = Tcl_ListObjAppendList(i.get(), obj_, o.obj_);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return *this;
+}
+
+object & object::replace(interpreter &i, size_t index, size_t count,
+     object const &o)
+{
+     int res = Tcl_ListObjReplace(i.get(), obj_,
+          static_cast<int>(index), static_cast<int>(count),
+          1, &(o.obj_));
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return *this;
+}
+
+object & object::replace_list(interpreter &i, size_t index, size_t count,
+     object const &o)
+{
+     int objc;
+     Tcl_Obj **objv;
+
+     int res = Tcl_ListObjGetElements(i.get(), o.obj_, &objc, &objv);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     res = Tcl_ListObjReplace(i.get(), obj_,
+          static_cast<int>(index), static_cast<int>(count),
+          objc, objv);
+     if (res != TCL_OK)
+     {
+          throw tcl_error(i.get());
+     }
+
+     return *this;
+}
+
+void object::set_interp(Tcl_Interp *interp)
+{
+     interp_ = interp;
+}
+
+Tcl_Interp * object::get_interp() const
+{
+     return interp_;
+}
+
+
+interpreter::interpreter()
+{
+     interp_ =  Tcl_CreateInterp();
+     owner_ = true;
+}
+
+interpreter::interpreter(Tcl_Interp *interp, bool owner)
+{
+     interp_ =  interp;
+     owner_ = owner;
+}
+
+interpreter::~interpreter()
+{
+     if (owner_)
+     {
+          // clear all callback info belonging to this interpreter
+          clear_definitions(interp_);
+
+          Tcl_DeleteInterp(interp_);
+     }
+}
+
+void interpreter::make_safe()
+{
+     int cc = Tcl_MakeSafe(interp_);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+}
+
+result interpreter::eval(string const &script)
+{
+     int cc = Tcl_Eval(interp_, script.c_str());
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+ 
+     return result(interp_);
+}
+
+result interpreter::eval(istream &s)
+{
+     string str(
+          istreambuf_iterator<char>(s.rdbuf()),
+          istreambuf_iterator<char>()
+     );
+     return eval(str);
+}
+
+result interpreter::eval(object const &o)
+{
+     int cc = Tcl_EvalObjEx(interp_, o.get_object(), 0);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+ 
+     return result(interp_);
+}
+
+void interpreter::pkg_provide(string const &name, string const &version)
+{
+     int cc = Tcl_PkgProvide(interp_, name.c_str(), version.c_str());
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+}
+
+void interpreter::create_alias(string const &cmd,
+     interpreter &targetInterp, string const &targetCmd)
+{
+     int cc = Tcl_CreateAlias(interp_, cmd.c_str(),
+          targetInterp.interp_, targetCmd.c_str(), 0, 0);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+}
+
+void interpreter::clear_definitions(Tcl_Interp *interp)
+{
+     // delete all callbacks that were registered for given interpreter
+
+     {
+          callback_map::iterator it = callbacks.find(interp);
+          if (it == callbacks.end())
+          {
+               // no callbacks defined for this interpreter
+               return;
+          }
+
+          callback_interp_map &imap = it->second;
+          for (callback_interp_map::iterator it2 = imap.begin();
+               it2 != imap.end(); ++it2)
+          {
+               Tcl_DeleteCommand(interp, it2->first.c_str());
+          }
+
+          callbacks.erase(interp);
+     }
+
+     // delete all constructors
+
+     {
+          callback_map::iterator it = constructors.find(interp);
+          if (it == constructors.end())
+          {
+               // no callbacks defined for this interpreter
+               return;
+          }
+
+          callback_interp_map &imap = it->second;
+          for (callback_interp_map::iterator it2 = imap.begin();
+               it2 != imap.end(); ++it2)
+          {
+               Tcl_DeleteCommand(interp, it2->first.c_str());
+          }
+
+          callbacks.erase(interp);
+     }
+
+     // delete all call policies
+
+     call_policies.erase(interp);
+
+     // delete all object handlers
+     // (we have to assume that all living objects were destroyed,
+     // otherwise Bad Things will happen)
+
+     class_handlers.erase(interp);
+}
+
+void interpreter::add_function(string const &name,
+     std::shared_ptr<callback_base> cb, policies const &p)
+{
+     Tcl_CreateObjCommand(interp_, name.c_str(),
+          callback_handler, 0, 0);
+     
+     callbacks[interp_][name] = cb;
+     call_policies[interp_][name] = p;
+}
+
+void interpreter::add_class(string const &name,
+     std::shared_ptr<class_handler_base> chb)
+{
+     class_handlers[interp_][name] = chb;
+}
+
+void interpreter::add_constructor(string const &name,
+     std::shared_ptr<class_handler_base> chb, std::shared_ptr<callback_base> cb,
+     policies const &p)
+{
+     Tcl_CreateObjCommand(interp_, name.c_str(),
+          constructor_handler, static_cast<ClientData>(chb.get()), 0);
+
+     constructors[interp_][name] = cb;
+     call_policies[interp_][name] = p;
+}
+
+
+int tcl_cast<int>::from(Tcl_Interp *interp, Tcl_Obj *obj)
+{
+     int res;
+     int cc = Tcl_GetIntFromObj(interp, obj, &res);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp);
+     }
+     
+     return res;
+}
+
+long tcl_cast<long>::from(Tcl_Interp *interp, Tcl_Obj *obj)
+{
+     long res;
+     int cc = Tcl_GetLongFromObj(interp, obj, &res);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp);
+     }
+     
+     return res;
+}
+
+bool tcl_cast<bool>::from(Tcl_Interp *interp, Tcl_Obj *obj)
+{
+     int res;
+     int cc = Tcl_GetBooleanFromObj(interp, obj, &res);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp);
+     }
+     
+     return res != 0;
+}
+
+double tcl_cast<double>::from(Tcl_Interp *interp, Tcl_Obj *obj)
+{
+     double res;
+     int cc = Tcl_GetDoubleFromObj(interp, obj, &res);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp);
+     }
+     
+     return res;
+}
+
+string tcl_cast<string>::from(Tcl_Interp *, Tcl_Obj *obj)
+{
+     return Tcl_GetString(obj);
+}
+
+char const * tcl_cast<char const *>::from(Tcl_Interp *, Tcl_Obj *obj)
+{
+     return Tcl_GetString(obj);
+}
+
+object tcl_cast<object>::from(Tcl_Interp *interp, Tcl_Obj *obj)
+{
+     object o(obj);
+     o.set_interp(interp);
+
+     return o;
+}
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/cpptcl.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/cpptcl.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/cpptcl.h	(revision 11817)
@@ -0,0 +1,870 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+#ifndef CPPTCL_INCLUDED
+#define CPPTCL_INCLUDED
+
+#include <tcl.h>
+#include <string>
+#include <stdexcept>
+#include <sstream>
+#include <map>
+#include <vector>
+#include <memory>
+#include <functional>
+
+namespace Tcl
+{
+namespace arg = std::placeholders;
+
+// exception class used for reporting all Tcl errors
+
+class tcl_error : public std::runtime_error
+{
+public:
+     explicit tcl_error(std::string const &msg)
+          : std::runtime_error(msg) {}
+     explicit tcl_error(Tcl_Interp *interp)
+          : std::runtime_error(Tcl_GetString(Tcl_GetObjResult(interp))) {}
+};
+
+// call policies
+
+struct policies
+{
+     policies() : variadic_(false) {}
+
+     policies & factory(std::string const &name);
+
+     // note: this is additive
+     policies & sink(int index);
+
+     policies & variadic();
+
+     std::string factory_;
+     std::vector<int> sinks_;
+     bool variadic_;
+};
+
+// syntax short-cuts
+policies factory(std::string const &name);
+policies sink(int index);
+policies variadic();
+
+
+class interpreter;
+class object;
+
+namespace details
+{
+
+// wrapper for the evaluation result
+class result
+{
+public:
+     result(Tcl_Interp *interp);
+     
+     operator bool() const;
+     operator double() const;
+     operator int() const;
+     operator long() const;
+     operator std::string() const;
+     operator object() const;
+
+private:
+     Tcl_Interp *interp_;
+};
+
+// helper functions used to set the result value
+
+void set_result(Tcl_Interp *interp, bool b);
+void set_result(Tcl_Interp *interp, int i);
+void set_result(Tcl_Interp *interp, long i);
+void set_result(Tcl_Interp *interp, double d);
+void set_result(Tcl_Interp *interp, std::string const &s);
+void set_result(Tcl_Interp *interp, void *p);
+void set_result(Tcl_Interp *interp, object const &o);
+
+// helper functor for converting Tcl objects to the given type
+#include "details/conversions.h"
+
+// dispatchers able to capture (or ignore) the result
+#include "details/dispatchers.h"
+
+// helper for checking for required number of parameters
+// (throws tcl_error when not met)
+void check_params_no(int objc, int required);
+
+// helper for gathering optional params in variadic functions
+object get_var_params(Tcl_Interp *interp,
+     int objc, Tcl_Obj * CONST objv[],
+     int from, policies const &pol);
+
+// the callback_base is used to store callback handlers in a polynorphic map
+class callback_base
+{
+public:
+     virtual ~callback_base() {}
+
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol) = 0;
+};
+
+
+// base class for object command handlers
+// and for class handlers
+class object_cmd_base
+{
+public:
+     // destructor not needed, but exists to shut up the compiler warnings
+     virtual ~object_cmd_base() {}
+
+     virtual void invoke(void *p, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol) = 0;
+};
+
+// base class for all class handlers, still abstract
+class class_handler_base : public object_cmd_base
+{
+public:
+     typedef std::map<std::string, policies> policies_map_type;
+
+     class_handler_base();
+
+     void register_method(std::string const &name,
+          std::shared_ptr<object_cmd_base> ocb, policies const &p);
+
+     policies & get_policies(std::string const &name);
+
+protected:
+     typedef std::map<
+          std::string,
+          std::shared_ptr<object_cmd_base>
+          > method_map_type;
+
+     // a map of methods for the given class
+     method_map_type methods_;
+
+     policies_map_type policies_;
+};
+
+// class handler - responsible for executing class methods
+template <class C>
+class class_handler : public class_handler_base
+{
+public:
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C * p = static_cast<C*>(pv);
+
+          if (objc < 2)
+          {
+               throw tcl_error("Too few arguments.");
+          }
+          
+          std::string methodName(Tcl_GetString(objv[1]));
+
+          if (methodName == "-delete")
+          {
+               Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
+               delete p;
+               return;
+          }
+
+          // dispatch on the method name
+
+          method_map_type::iterator it = methods_.find(methodName);
+          if (it == methods_.end())
+          {
+               throw tcl_error("Method " + methodName + " not found.");
+          }
+
+          it->second->invoke(pv, interp, objc, objv, pol);
+     }
+};
+
+
+// factory functions for creating class objects
+#include "details/constructors.h"
+
+// actual callback envelopes
+#include "details/callbacks.h"
+
+// actual method envelopes
+#include "details/methods.h"
+
+// helper meta function for figuring appropriate constructor callback
+#include "details/metahelpers.h"
+
+
+// this class is used to provide the "def" interface for defining
+// class member functions
+
+template <class C>
+class class_definer
+{
+public:
+     class_definer(std::shared_ptr<class_handler<C> > ch) : ch_(ch) {}
+
+     template <typename R>
+     class_definer & def(std::string const &name, R (C::*f)(),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method0<C, R>(f)), p);
+          return *this;
+     }
+
+     template <typename R>
+     class_definer & def(std::string const &name, R (C::*f)() const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method0<C, R>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1>
+     class_definer & def(std::string const &name, R (C::*f)(T1),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method1<C, R, T1>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1>
+     class_definer & def(std::string const &name, R (C::*f)(T1) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method1<C, R, T1>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2>
+     class_definer & def(std::string const &name, R (C::*f)(T1, T2),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method2<C, R, T1, T2>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2>
+     class_definer & def(std::string const &name, R (C::*f)(T1, T2) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method2<C, R, T1, T2>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3>
+     class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method3<C, R, T1, T2, T3>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3>
+     class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method3<C, R, T1, T2, T3>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4>
+     class_definer & def(std::string const &name, R (C::*f)(T1, T2, T3, T4),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method4<C, R, T1, T2, T3, T4>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method4<C, R, T1, T2, T3, T4>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5), policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method5<C, R, T1, T2, T3, T4, T5>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5) const, policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method5<C, R, T1, T2, T3, T4, T5>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6), policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method6<C, R, T1, T2, T3, T4, T5, T6>(f)),
+               p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method6<C, R, T1, T2, T3, T4, T5, T6>(f)),
+               p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6, T7),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method7<C, R,
+                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6, T7) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method7<C, R,
+                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method8<C, R,
+                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method8<C, R,
+                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, typename T9>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9),
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method9<C, R,
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
+          return *this;
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, typename T9>
+     class_definer & def(std::string const &name,
+          R (C::*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const,
+          policies const &p = policies())
+     {
+          ch_->register_method(name,
+               std::shared_ptr<details::object_cmd_base>(
+                    new details::method9<C, R,
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
+          return *this;
+     }
+
+private:
+     std::shared_ptr<class_handler<C> > ch_;
+};
+
+} // namespace details
+
+
+// init type for defining class constructors
+template <typename T1 = void, typename T2 = void, typename T3 = void,
+          typename T4 = void, typename T5 = void, typename T6 = void,
+          typename T7 = void, typename T8 = void, typename T9 = void>
+class init {};
+
+// no_init type and object - to define classes without constructors
+namespace details
+{
+     struct no_init_type {};
+} // namespace details
+extern details::no_init_type no_init;
+
+
+// interpreter wrapper
+class interpreter
+{
+public:
+     interpreter();
+     interpreter(Tcl_Interp *, bool owner = true);
+     ~interpreter();
+     
+     void make_safe();
+     
+     Tcl_Interp * get() const { return interp_; }
+
+     // free function definitions     
+     
+     template <typename R>
+     void def(std::string const &name, R (*f)(),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback0<R>(f)), p);
+     }
+
+     template <typename R, typename T1>
+     void def(std::string const &name, R (*f)(T1),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback1<R, T1>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2>
+     void def(std::string const &name, R (*f)(T1, T2),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback2<R, T1, T2>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3>
+     void def(std::string const &name, R (*f)(T1, T2, T3),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback3<R, T1, T2, T3>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3, typename T4>
+     void def(std::string const &name, R (*f)(T1, T2, T3, T4),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback4<R, T1, T2, T3, T4>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3,
+          typename T4, typename T5>
+     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback5<R, T1, T2, T3, T4, T5>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3,
+          typename T4, typename T5, typename T6>
+     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback6<R, T1, T2, T3, T4, T5, T6>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3,
+          typename T4, typename T5, typename T6, typename T7>
+     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback7<R,
+                    T1, T2, T3, T4, T5, T6, T7>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3,
+          typename T4, typename T5, typename T6, typename T7, typename T8>
+     void def(std::string const &name, R (*f)(T1, T2, T3, T4, T5, T6, T7, T8),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback8<R,
+                    T1, T2, T3, T4, T5, T6, T7, T8>(f)), p);
+     }
+
+     template <typename R, typename T1, typename T2, typename T3,
+          typename T4, typename T5, typename T6, typename T7, typename T8,
+          typename T9>
+     void def(std::string const &name,
+          R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9),
+          policies const &p = policies())
+     {
+          add_function(name,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback9<R,
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(f)), p);
+     }
+
+
+     // class definitions
+
+     template <class C>
+     details::class_definer<C> class_(std::string const &name)
+     {
+          std::shared_ptr<details::class_handler<C> > ch(
+               new details::class_handler<C>());
+
+          add_class(name, ch);
+
+          add_constructor(name, ch,
+               std::shared_ptr<details::callback_base>(
+                    new details::callback0<C*>(&details::construct<
+                         C, void, void, void, void, void, void, void,
+                         void, void>::doit)));
+
+          return details::class_definer<C>(ch);
+     }
+
+     template <class C, typename T1, typename T2, typename T3, typename T4,
+               typename T5, typename T6, typename T7, typename T8,
+               typename T9>
+     details::class_definer<C> class_(std::string const &name,
+          init<T1, T2, T3, T4, T5, T6, T7, T8, T9> const &,
+          policies const &p = policies())
+     {
+          typedef typename details::get_callback_type_for_construct<
+               C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type
+               callback_type;
+
+          std::shared_ptr<details::class_handler<C> > ch(
+               new details::class_handler<C>());
+
+          add_class(name, ch);
+
+          add_constructor(name, ch,
+               std::shared_ptr<details::callback_base>(
+                    new callback_type(&details::construct<
+                         C, T1, T2, T3, T4, T5, T6, T7, T8, T9>::doit)), p);
+
+          return details::class_definer<C>(ch);
+     }
+
+     template <class C>
+     details::class_definer<C> class_(
+          std::string const &name, details::no_init_type const &)
+     {
+          std::shared_ptr<details::class_handler<C> > ch(
+               new details::class_handler<C>());
+
+          add_class(name, ch);
+
+          return details::class_definer<C>(ch);
+     }
+
+     // free script evaluation     
+     details::result eval(std::string const &script);
+     details::result eval(std::istream &s);
+
+     details::result eval(object const &o);
+
+     // the InputIterator should give object& or Tcl_Obj* when dereferenced
+     template <class InputIterator>
+     details::result eval(InputIterator first, InputIterator last);
+
+     // create alias from the *this interpreter to the target interpreter
+     void create_alias(std::string const &cmd,
+          interpreter &targetInterp, std::string const &targetCmd);
+
+     // register a package info (useful when defining packages)
+     void pkg_provide(std::string const &name, std::string const &version);
+
+     // helper for cleaning up callbacks in non-managed interpreters
+     static void clear_definitions(Tcl_Interp *);
+
+private:
+
+     // copy not supported
+     interpreter(const interpreter &);
+     void operator=(const interpreter &);
+
+     void add_function(std::string const &name,
+          std::shared_ptr<details::callback_base> cb,
+          policies const &p = policies());
+
+     void add_class(std::string const &name,
+          std::shared_ptr<details::class_handler_base> chb);
+
+     void add_constructor(std::string const &name,
+          std::shared_ptr<details::class_handler_base> chb,
+          std::shared_ptr<details::callback_base> cb,
+          policies const &p = policies());
+
+     Tcl_Interp *interp_;
+     bool owner_;
+};
+
+
+// object wrapper
+class object
+{
+public:
+
+     // constructors
+
+     object();
+
+     explicit object(bool b);
+     object(char const *buf, size_t size); // byte array
+     explicit object(double b);
+     explicit object(int i);
+
+     // list creation
+     // the InputIterator should give object& or Tcl_Obj* when dereferenced
+     template <class InputIterator>
+     object(InputIterator first, InputIterator last)
+          : interp_(0)
+     {
+          std::vector<Tcl_Obj*> v;
+          fill_vector(v, first, last);
+          obj_ = Tcl_NewListObj(static_cast<int>(v.size()),
+               v.empty() ? NULL : &v[0]);
+          Tcl_IncrRefCount(obj_);
+     }
+
+     explicit object(long i);
+     explicit object(char const *s);        // string construction
+     explicit object(std::string const &s); // string construction
+
+     explicit object(Tcl_Obj *o, bool shared = false);
+
+     object(object const &other, bool shared = false);
+     ~object();
+
+     // assignment
+
+     object & assign(bool b);
+     object & resize(size_t size);                  // byte array resize
+     object & assign(char const *buf, size_t size); // byte array assignment
+     object & assign(double d);
+     object & assign(int i);
+
+     // list assignment
+     // the InputIterator should give Tcl_Obj* or object& when dereferenced
+     template <class InputIterator>
+     object & assign(InputIterator first, InputIterator last)
+     {
+          std::vector<Tcl_Obj*> v;
+          fill_vector(v, first, last);
+          Tcl_SetListObj(obj_, static_cast<int>(v.size()),
+               v.empty() ? NULL : &v[0]);
+          return *this;
+     }
+
+     object & assign(long l);
+     object & assign(char const *s);        // string assignment
+     object & assign(std::string const &s); // string assignment
+     object & assign(object const &o);
+     object & assign(Tcl_Obj *o);
+
+     object & operator=(bool b)               { return assign(b); }
+     object & operator=(double d)             { return assign(d); }
+     object & operator=(int i)                { return assign(i); }
+     object & operator=(long l)               { return assign(l); }
+     object & operator=(char const *s)        { return assign(s); }
+     object & operator=(std::string const &s) { return assign(s); }
+
+     object & operator=(object const &o)      { return assign(o); }
+     object & swap(object &other);
+
+     // (logically) non-modifying members
+
+     template <typename T>
+     T get(interpreter &i) const;
+
+     char const * get() const;             // string get
+     char const * get(size_t &size) const; // byte array get
+
+     size_t length(interpreter &i) const;  // returns list length
+     object at(interpreter &i, size_t index) const;
+
+     Tcl_Obj * get_object() const { return obj_; }
+
+     // modifying members
+
+     object & append(interpreter &i, object const &o);
+     object & append_list(interpreter &i, object const &o);
+
+     // list replace
+     // the InputIterator should give Tcl_Obj* or object& when dereferenced
+     template <class InputIterator>
+     object & replace(interpreter &i, size_t index, size_t count,
+          InputIterator first, InputIterator last)
+     {
+          std::vector<Tcl_Obj*> v;
+          fill_vector(v, first, last);
+          int res = Tcl_ListObjReplace(i.get(), obj_,
+               static_cast<int>(index), static_cast<int>(count),
+               static_cast<int>(v.size()), v.empty() ? NULL : &v[0]);
+          if (res != TCL_OK)
+          {
+               throw tcl_error(i.get());
+          }
+
+          return *this;
+     }
+
+     object & replace(interpreter &i, size_t index, size_t count,
+          object const &o);
+     object & replace_list(interpreter &i, size_t index, size_t count,
+          object const &o);
+
+     // helper functions for piggy-backing interpreter info
+     void set_interp(Tcl_Interp *interp);
+     Tcl_Interp * get_interp() const;
+
+     // helper function, also used from interpreter::eval
+     template <class InputIterator>
+     static void fill_vector(std::vector<Tcl_Obj*> &v,
+          InputIterator first, InputIterator last)
+     {
+          for (; first != last; ++first)
+          {
+               object o(*first, true);
+               v.push_back(o.obj_);
+          }
+     }
+
+private:
+
+     // helper function used from copy constructors
+     void init(Tcl_Obj *o, bool shared);
+
+     Tcl_Obj *obj_;
+     Tcl_Interp *interp_;
+};
+
+// available specializations for object::get
+template <> bool         object::get<bool>(interpreter &i) const;
+template <> double       object::get<double>(interpreter &i) const;
+template <> int          object::get<int>(interpreter &i) const;
+template <> long         object::get<long>(interpreter &i) const;
+template <> char const * object::get<char const *>(interpreter &i) const;
+template <> std::string  object::get<std::string>(interpreter &i) const;
+template <>
+std::vector<char> object::get<std::vector<char> >(interpreter &i) const;
+
+// the InputIterator should give object& or Tcl_Obj* when dereferenced
+template <class InputIterator>
+details::result interpreter::eval(InputIterator first, InputIterator last)
+{
+     std::vector<Tcl_Obj*> v;
+     object::fill_vector(v, first, last);
+     int cc = Tcl_EvalObjv(interp_,
+          static_cast<int>(v.size()), v.empty() ? NULL : &v[0], 0);
+     if (cc != TCL_OK)
+     {
+          throw tcl_error(interp_);
+     }
+ 
+     return details::result(interp_);
+}
+
+namespace details
+{
+
+// additional callback envelopes for variadic functions
+#include "details/callbacks_v.h"
+
+// additional method envelopes for variadic methods
+#include "details/methods_v.h"
+
+} // namespace details
+
+} // namespace Tcl
+
+
+// macro for defining loadable module entry point
+// - used for extending Tcl interpreter
+
+#define CPPTCL_MODULE(name, i) void name##_cpptcl_Init(Tcl::interpreter &i); \
+     extern "C" int name##_Init(Tcl_Interp *interp) \
+     { \
+          Tcl::interpreter i(interp, false); \
+          name##_cpptcl_Init(i); \
+          return TCL_OK; \
+     } \
+     void name##_cpptcl_Init(Tcl::interpreter &i)
+
+
+#endif // CPPTCL_INCLUDED
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/callbacks.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/callbacks.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/callbacks.h	(revision 11817)
@@ -0,0 +1,273 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+template <typename R>
+class callback0 : public callback_base
+{
+     typedef R (*functor_type)();
+     
+public:
+     callback0(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int, Tcl_Obj * CONST [],
+          policies const &)
+     {
+          dispatch<R>::do_dispatch(interp, f_);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1>
+class callback1 : public callback_base
+{
+     typedef R (*functor_type)(T1);
+     
+public:
+     callback1(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 2);
+          
+          dispatch<R>::template do_dispatch<T1>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2>
+class callback2 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2);
+     
+public:
+     callback2(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 3);
+          
+          dispatch<R>::template do_dispatch<T1, T2>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3>
+class callback3 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3);
+     
+public:
+     callback3(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 4);
+          
+          dispatch<R>::template do_dispatch<T1, T2, T3>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4>
+class callback4 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3, T4);
+     
+public:
+     callback4(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 5);
+          
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5>
+class callback5 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3, T4, T5);
+     
+public:
+     callback5(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 6);
+          
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6>
+class callback6 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6);
+     
+public:
+     callback6(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 7);
+          
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6, typename T7>
+class callback7 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7);
+     
+public:
+     callback7(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 8);
+          
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]),
+               tcl_cast<T7>::from(interp, objv[7]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6, typename T7, typename T8>
+class callback8 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8);
+     
+public:
+     callback8(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 9);
+          
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7, T8>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]),
+               tcl_cast<T7>::from(interp, objv[7]),
+               tcl_cast<T8>::from(interp, objv[8]));
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6, typename T7, typename T8, typename T9>
+class callback9 : public callback_base
+{
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9);
+     
+public:
+     callback9(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &)
+     {
+          check_params_no(objc, 10);
+          
+          dispatch<R>::template do_dispatch<
+               T1, T2, T3, T4, T5, T6, T7, T8, T9>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]),
+               tcl_cast<T7>::from(interp, objv[7]),
+               tcl_cast<T8>::from(interp, objv[8]),
+               tcl_cast<T9>::from(interp, objv[9]));
+     }
+
+private:
+     functor_type f_;
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/callbacks_v.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/callbacks_v.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/callbacks_v.h	(revision 11817)
@@ -0,0 +1,267 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+template <typename R>
+class callback1<R, object const &> : public callback_base
+{
+     typedef object const & T1;
+     typedef R (*functor_type)(T1);
+     enum { var_start = 1 };
+     
+public:
+     callback1(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t1 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1>(interp, f_,
+               t1);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1>
+class callback2<R, T1, object const &> : public callback_base
+{
+     typedef object const & T2;
+     typedef R (*functor_type)(T1, T2);
+     enum { var_start = 2 };
+     
+public:
+     callback2(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t2 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               t2);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2>
+class callback3<R, T1, T2, object const &> : public callback_base
+{
+     typedef object const & T3;
+     typedef R (*functor_type)(T1, T2, T3);
+     enum { var_start = 3 };
+     
+public:
+     callback3(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t3 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2, T3>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               t3);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3>
+class callback4<R, T1, T2, T3, object const &> : public callback_base
+{
+     typedef object const & T4;
+     typedef R (*functor_type)(T1, T2, T3, T4);
+     enum { var_start = 4 };
+     
+public:
+     callback4(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t4 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4>(interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               t4);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4>
+class callback5<R, T1, T2, T3, T4, object const &> : public callback_base
+{
+     typedef object const & T5;
+     typedef R (*functor_type)(T1, T2, T3, T4, T5);
+     enum { var_start = 5 };
+     
+public:
+     callback5(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t5 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               t5);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5>
+class callback6<R, T1, T2, T3, T4, T5, object const &> : public callback_base
+{
+     typedef object const & T6;
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6);
+     enum { var_start = 6 };
+     
+public:
+     callback6(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t6 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               t6);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6>
+class callback7<R, T1, T2, T3, T4, T5, T6, object const &>
+     : public callback_base
+{
+     typedef object const & T7;
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7);
+     enum { var_start = 7 };
+     
+public:
+     callback7(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t7 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]),
+               t7);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6, typename T7>
+class callback8<R, T1, T2, T3, T4, T5, T6, T7, object const &>
+     : public callback_base
+{
+     typedef object const & T8;
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8);
+     enum { var_start = 8 };
+     
+public:
+     callback8(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t8 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7, T8>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]),
+               tcl_cast<T7>::from(interp, objv[7]),
+               t8);
+     }
+
+private:
+     functor_type f_;
+};
+
+template <typename R, typename T1, typename T2, typename T3, typename T4,
+     typename T5, typename T6, typename T7, typename T8>
+class callback9<R, T1, T2, T3, T4, T5, T6, T7, T8, object const &>
+     : public callback_base
+{
+     typedef object const & T9;
+     typedef R (*functor_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9);
+     enum { var_start = 9 };
+     
+public:
+     callback9(functor_type f) : f_(f) {}
+     
+     virtual void invoke(Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[],
+          policies const &pol)
+     {
+          object t9 = get_var_params(interp, objc, objv, var_start, pol);
+          dispatch<R>::template do_dispatch<
+               T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+               interp, f_,
+               tcl_cast<T1>::from(interp, objv[1]),
+               tcl_cast<T2>::from(interp, objv[2]),
+               tcl_cast<T3>::from(interp, objv[3]),
+               tcl_cast<T4>::from(interp, objv[4]),
+               tcl_cast<T5>::from(interp, objv[5]),
+               tcl_cast<T6>::from(interp, objv[6]),
+               tcl_cast<T7>::from(interp, objv[7]),
+               tcl_cast<T8>::from(interp, objv[8]),
+               t9);
+     }
+
+private:
+     functor_type f_;
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/constructors.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/constructors.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/constructors.h	(revision 11817)
@@ -0,0 +1,88 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, typename T9>
+struct construct
+{
+     static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7,
+          T8 t8, T9 t9)
+     { return new C(t1, t2, t3, t4, t5, t6, t7, t8, t9); }
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8>
+struct construct<C, T1, T2, T3, T4, T5, T6, T7, T8, void>
+{
+     static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
+     { return new C(t1, t2, t3, t4, t5, t6, t7, t8); }
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7>
+struct construct<C, T1, T2, T3, T4, T5, T6, T7, void, void>
+{
+     static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
+     { return new C(t1, t2, t3, t4, t5, t6, t7); }
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6>
+struct construct<C, T1, T2, T3, T4, T5, T6, void, void, void>
+{
+     static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
+     { return new C(t1, t2, t3, t4, t5, t6); }
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5>
+struct construct<C, T1, T2, T3, T4, T5, void, void, void, void>
+{
+     static C * doit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
+     { return new C(t1, t2, t3, t4, t5); }
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4>
+struct construct<C, T1, T2, T3, T4, void, void, void, void, void>
+{
+     static C * doit(T1 t1, T2 t2, T3 t3, T4 t4)
+     { return new C(t1, t2, t3, t4); }
+};
+
+template <class C, typename T1, typename T2, typename T3>
+struct construct<C, T1, T2, T3, void, void, void, void, void, void>
+{
+     static C * doit(T1 t1, T2 t2, T3 t3)
+     { return new C(t1, t2, t3); }
+};
+
+template <class C, typename T1, typename T2>
+struct construct<C, T1, T2, void, void, void, void, void, void, void>
+{
+     static C * doit(T1 t1, T2 t2)
+     { return new C(t1, t2); }
+};
+
+template <class C, typename T1>
+struct construct<C, T1, void, void, void, void, void, void, void, void>
+{
+     static C * doit(T1 t1)
+     { return new C(t1); }
+};
+
+template <class C>
+struct construct<C, void, void, void, void, void,
+                 void, void, void, void>
+{
+     static C * doit()
+     { return new C(); }
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/conversions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/conversions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/conversions.h	(revision 11817)
@@ -0,0 +1,101 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+// helper functor for converting Tcl objects to the given type
+// (it is a struct instead of function,
+// because I need to partially specialize it)
+
+template <typename T>
+struct tcl_cast;
+
+template <typename T>
+struct tcl_cast<T*>
+{
+     static T * from(Tcl_Interp *, Tcl_Obj *obj)
+     {
+          std::string s(Tcl_GetString(obj));
+          if (s.size() == 0)
+          {
+               throw tcl_error("Expected pointer value, got empty string.");
+          }
+
+          if (s[0] != 'p')
+          {
+               throw tcl_error("Expected pointer value.");
+          }
+
+          std::istringstream ss(s);
+          char dummy;
+          void *p;
+          ss >> dummy >> p;
+
+          return static_cast<T*>(p);
+     }
+};
+
+// the following partial specialization is to strip reference
+// (it returns a temporary object of the underlying type, which
+// can be bound to the const-ref parameter of the actual function)
+
+template <typename T>
+struct tcl_cast<T const &>
+{
+     static T from(Tcl_Interp *interp, Tcl_Obj *obj)
+     {
+          return tcl_cast<T>::from(interp, obj);
+     }
+};
+
+
+// the following specializations are implemented
+
+template <>
+struct tcl_cast<int>
+{
+     static int from(Tcl_Interp *, Tcl_Obj *);
+};
+
+template <>
+struct tcl_cast<long>
+{
+     static long from(Tcl_Interp *, Tcl_Obj *);
+};
+
+template <>
+struct tcl_cast<bool>
+{
+     static bool from(Tcl_Interp *, Tcl_Obj *);
+};
+
+template <>
+struct tcl_cast<double>
+{
+     static double from(Tcl_Interp *, Tcl_Obj *);
+};
+
+template <>
+struct tcl_cast<std::string>
+{
+     static std::string from(Tcl_Interp *, Tcl_Obj *);
+};
+
+template <>
+struct tcl_cast<char const *>
+{
+     static char const * from(Tcl_Interp *, Tcl_Obj *);
+};
+
+template <>
+struct tcl_cast<object>
+{
+     static object from(Tcl_Interp *, Tcl_Obj *);
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/dispatchers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/dispatchers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/dispatchers.h	(revision 11817)
@@ -0,0 +1,181 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+// the dispatch class is used to execute the callback functor and to
+// capture its return value
+// further dispatch<void> specialization ignores the res
+
+template <typename R>
+struct dispatch
+{
+     template <class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f)
+     {
+          R res = f();
+          set_result(interp, res);
+     }
+
+     template <typename T1, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f, T1 t1)
+     {
+          R res = f(t1);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f, T1 t1, T2 t2)
+     {
+          R res = f(t1, t2);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3)
+     {
+          R res = f(t1, t2, t3);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4)
+     {
+          R res = f(t1, t2, t3, t4);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
+     {
+          R res = f(t1, t2, t3, t4, t5);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
+     {
+          R res = f(t1, t2, t3, t4, t5, t6);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
+     {
+          R res = f(t1, t2, t3, t4, t5, t6, t7);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
+     {
+          R res = f(t1, t2, t3, t4, t5, t6, t7, t8);
+          set_result(interp, res);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, typename T9,
+          class Functor>
+     static void do_dispatch(Tcl_Interp *interp, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
+     {
+          R res = f(t1, t2, t3, t4, t5, t6, t7, t8, t9);
+          set_result(interp, res);
+     }
+};
+
+template <>
+struct dispatch<void>
+{
+     template <class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f)
+     {
+          f();
+     }
+
+     template <typename T1, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f, T1 t1)
+     {
+          f(t1);
+     }
+
+     template <typename T1, typename T2, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f, T1 t1, T2 t2)
+     {
+          f(t1, t2);
+     }
+
+     template <typename T1, typename T2, typename T3, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3)
+     {
+          f(t1, t2, t3);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4)
+     {
+          f(t1, t2, t3, t4);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
+     {
+          f(t1, t2, t3, t4, t5);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
+     {
+          f(t1, t2, t3, t4, t5, t6);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
+     {
+          f(t1, t2, t3, t4, t5, t6, t7);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
+     {
+          f(t1, t2, t3, t4, t5, t6, t7, t8);
+     }
+
+     template <typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8, typename T9,
+          class Functor>
+     static void do_dispatch(Tcl_Interp *, Functor f,
+          T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9)
+     {
+          f(t1, t2, t3, t4, t5, t6, t7, t8, t9);
+     }
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/metahelpers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/metahelpers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/metahelpers.h	(revision 11817)
@@ -0,0 +1,86 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8,
+          typename T9>
+struct get_callback_type_for_construct
+{
+     typedef callback9<C*, T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7, typename T8>
+struct get_callback_type_for_construct<
+     C, T1, T2, T3, T4, T5, T6, T7, T8, void>
+{
+     typedef callback8<C*, T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6, typename T7>
+struct get_callback_type_for_construct<
+     C, T1, T2, T3, T4, T5, T6, T7, void, void>
+{
+     typedef callback7<C*, T1, T2, T3, T4, T5, T6, T7> type;
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5, typename T6>
+struct get_callback_type_for_construct<
+     C, T1, T2, T3, T4, T5, T6, void, void, void>
+{
+     typedef callback6<C*, T1, T2, T3, T4, T5, T6> type;
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4,
+          typename T5>
+struct get_callback_type_for_construct<
+     C, T1, T2, T3, T4, T5, void, void, void, void>
+{
+     typedef callback5<C*, T1, T2, T3, T4, T5> type;
+};
+
+template <class C, typename T1, typename T2, typename T3, typename T4>
+struct get_callback_type_for_construct<
+     C, T1, T2, T3, T4, void, void, void, void, void>
+{
+     typedef callback4<C*, T1, T2, T3, T4> type;
+};
+
+template <class C, typename T1, typename T2, typename T3>
+struct get_callback_type_for_construct<
+     C, T1, T2, T3, void, void, void, void, void, void>
+{
+     typedef callback3<C*, T1, T2, T3> type;
+};
+
+template <class C, typename T1, typename T2>
+struct get_callback_type_for_construct<
+     C, T1, T2, void, void, void, void, void, void, void>
+{
+     typedef callback2<C*, T1, T2> type;
+};
+
+template <class C, typename T1>
+struct get_callback_type_for_construct<
+     C, T1, void, void, void, void, void, void, void, void>
+{
+     typedef callback1<C*, T1> type;
+};
+
+template <class C>
+struct get_callback_type_for_construct<
+     C, void, void, void, void, void, void, void, void, void>
+{
+     typedef callback0<C*> type;
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/methods.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/methods.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/methods.h	(revision 11817)
@@ -0,0 +1,452 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+template <class C, typename R>
+class method0 : public object_cmd_base
+{
+     typedef R (C::*mem_type)();
+     typedef R (C::*cmem_type)() const;
+     
+public:
+     method0(mem_type f) : f_(f), cmem_(false) {}
+     method0(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int, Tcl_Obj * CONST [], policies const &)
+     {
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::do_dispatch(interp, std::bind(cf_, p));
+          }
+          else
+          {
+               dispatch<R>::do_dispatch(interp, std::bind(f_, p));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1>
+class method1 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1);
+     typedef R (C::*cmem_type)(T1) const;
+     
+public:
+     method1(mem_type f) : f_(f), cmem_(false) {}
+     method1(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 3);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1>(
+                    interp, std::bind(cf_, p, arg::_1),
+                    tcl_cast<T1>::from(interp, objv[2]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1>(
+                    interp, std::bind(f_, p, arg::_1),
+                    tcl_cast<T1>::from(interp, objv[2]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2>
+class method2 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2);
+     typedef R (C::*cmem_type)(T1, T2) const;
+     
+public:
+     method2(mem_type f) : f_(f), cmem_(false) {}
+     method2(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 4);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3>
+class method3 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3);
+     typedef R (C::*cmem_type)(T1, T2, T3) const;
+     
+public:
+     method3(mem_type f) : f_(f), cmem_(false) {}
+     method3(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 5);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4>
+class method4 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3, T4);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4) const;
+     
+public:
+     method4(mem_type f) : f_(f), cmem_(false) {}
+     method4(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 6);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5>
+class method5 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5) const;
+     
+public:
+     method5(mem_type f) : f_(f), cmem_(false) {}
+     method5(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 7);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6>
+class method6 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6) const;
+     
+public:
+     method6(mem_type f) : f_(f), cmem_(false) {}
+     method6(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 8);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6, typename T7>
+class method7 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7) const;
+     
+public:
+     method7(mem_type f) : f_(f), cmem_(false) {}
+     method7(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 9);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6, typename T7, typename T8>
+class method8 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8) const;
+     
+public:
+     method8(mem_type f) : f_(f), cmem_(false) {}
+     method8(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 10);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8>(
+                    interp, std::bind(cf_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    tcl_cast<T8>::from(interp, objv[9]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8>(
+                    interp, std::bind(f_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    tcl_cast<T8>::from(interp, objv[9]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6, typename T7, typename T8,
+     typename T9>
+class method9 : public object_cmd_base
+{
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const;
+     
+public:
+     method9(mem_type f) : f_(f), cmem_(false) {}
+     method9(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &)
+     {
+          check_params_no(objc, 11);
+          
+          C *p = static_cast<C*>(pv);
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+                    interp, std::bind(cf_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8, arg::_9),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    tcl_cast<T8>::from(interp, objv[9]),
+                    tcl_cast<T9>::from(interp, objv[10]));
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+                    interp, std::bind(f_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8, arg::_9),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    tcl_cast<T8>::from(interp, objv[9]),
+                    tcl_cast<T9>::from(interp, objv[10]));
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
Index: /code/branches/RacingBots_FS18/src/external/cpptcl/details/methods_v.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/cpptcl/details/methods_v.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/cpptcl/details/methods_v.h	(revision 11817)
@@ -0,0 +1,451 @@
+//
+// Copyright (C) 2004-2006, Maciej Sobczak
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+
+// Note: this file is not supposed to be a stand-alone header
+
+
+template <class C, typename R>
+class method1<C, R, object const &> : public object_cmd_base
+{
+     typedef object const & T1;
+     typedef R (C::*mem_type)(T1);
+     typedef R (C::*cmem_type)(T1) const;
+     enum { var_start = 2 };
+     
+public:
+     method1(mem_type f) : f_(f), cmem_(false) {}
+     method1(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t1 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1>(
+                    interp, std::bind(cf_, p, arg::_1),
+                    t1);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1>(
+                    interp, std::bind(f_, p, arg::_1),
+                    t1);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1>
+class method2<C, R, T1, object const &> : public object_cmd_base
+{
+     typedef object const & T2;
+     typedef R (C::*mem_type)(T1, T2);
+     typedef R (C::*cmem_type)(T1, T2) const;
+     enum { var_start = 3 };
+     
+public:
+     method2(mem_type f) : f_(f), cmem_(false) {}
+     method2(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t2 = get_var_params(interp, objc, objv, var_start, pol);
+          
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    t2);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    t2);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2>
+class method3<C, R, T1, T2, object const &> : public object_cmd_base
+{
+     typedef object const & T3;
+     typedef R (C::*mem_type)(T1, T2, T3);
+     typedef R (C::*cmem_type)(T1, T2, T3) const;
+     enum { var_start = 4 };
+     
+public:
+     method3(mem_type f) : f_(f), cmem_(false) {}
+     method3(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t3 = get_var_params(interp, objc, objv, var_start, pol);
+          
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    t3);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    t3);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3>
+class method4<C, R, T1, T2, T3, object const &> : public object_cmd_base
+{
+     typedef object const & T4;
+     typedef R (C::*mem_type)(T1, T2, T3, T4);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4) const;
+     enum { var_start = 5 };
+     
+public:
+     method4(mem_type f) : f_(f), cmem_(false) {}
+     method4(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t4 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    t4);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    t4);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4>
+class method5<C, R, T1, T2, T3, T4, object const &> : public object_cmd_base
+{
+     typedef object const & T5;
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5) const;
+     enum { var_start = 6 };
+     
+public:
+     method5(mem_type f) : f_(f), cmem_(false) {}
+     method5(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t5 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    t5);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    t5);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5>
+class method6<C, R, T1, T2, T3, T4, T5, object const &>
+     : public object_cmd_base
+{
+     typedef object const & T6;
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6) const;
+     enum { var_start = 7 };
+     
+public:
+     method6(mem_type f) : f_(f), cmem_(false) {}
+     method6(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t6 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    t6);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    t6);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6>
+class method7<C, R, T1, T2, T3, T4, T5, T6, object const &>
+     : public object_cmd_base
+{
+     typedef object const & T7;
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7) const;
+     enum { var_start = 8 };
+     
+public:
+     method7(mem_type f) : f_(f), cmem_(false) {}
+     method7(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t7 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7>(
+                    interp, std::bind(cf_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    t7);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<T1, T2, T3, T4, T5, T6, T7>(
+                    interp, std::bind(f_, p, arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    t7);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6, typename T7>
+class method8<C, R, T1, T2, T3, T4, T5, T6, T7, object const &>
+     : public object_cmd_base
+{
+     typedef object const & T8;
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8) const;
+     enum { var_start = 9 };
+     
+public:
+     method8(mem_type f) : f_(f), cmem_(false) {}
+     method8(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t8 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8>(
+                    interp, std::bind(cf_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    t8);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8>(
+                    interp, std::bind(f_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    t8);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
+
+template <class C, typename R, typename T1, typename T2, typename T3,
+     typename T4, typename T5, typename T6, typename T7, typename T8>
+class method9<C, R, T1, T2, T3, T4, T5, T6, T7, T8, object const &>
+     : public object_cmd_base
+{
+     typedef object const & T9;
+     typedef R (C::*mem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9);
+     typedef R (C::*cmem_type)(T1, T2, T3, T4, T5, T6, T7, T8, T9) const;
+     enum { var_start = 10 };
+     
+public:
+     method9(mem_type f) : f_(f), cmem_(false) {}
+     method9(cmem_type f) : cf_(f), cmem_(true) {}
+     
+     virtual void invoke(void *pv, Tcl_Interp *interp,
+          int objc, Tcl_Obj * CONST objv[], policies const &pol)
+     {
+          C *p = static_cast<C*>(pv);
+
+          object t9 = get_var_params(interp, objc, objv, var_start, pol);
+
+          if (cmem_)
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+                    interp, std::bind(cf_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8, arg::_9),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    tcl_cast<T8>::from(interp, objv[9]),
+                    t9);
+          }
+          else
+          {
+               dispatch<R>::template do_dispatch<
+                    T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+                    interp, std::bind(f_, p,
+                         arg::_1, arg::_2, arg::_3, arg::_4, arg::_5, arg::_6, arg::_7, arg::_8, arg::_9),
+                    tcl_cast<T1>::from(interp, objv[2]),
+                    tcl_cast<T2>::from(interp, objv[3]),
+                    tcl_cast<T3>::from(interp, objv[4]),
+                    tcl_cast<T4>::from(interp, objv[5]),
+                    tcl_cast<T5>::from(interp, objv[6]),
+                    tcl_cast<T6>::from(interp, objv[7]),
+                    tcl_cast<T7>::from(interp, objv[8]),
+                    tcl_cast<T8>::from(interp, objv[9]),
+                    t9);
+          }
+     }
+
+private:
+     mem_type f_;
+     cmem_type cf_;
+     bool cmem_;
+};
Index: /code/branches/RacingBots_FS18/src/external/enet/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,50 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(ENET_FILES
+    callbacks.h
+    enet.h
+    list.h
+    protocol.h
+    time.h
+    types.h
+    unix.h
+    utility.h
+    win32.h
+
+    callbacks.c
+    compress.c
+    host.c
+    list.c
+    packet.c
+    peer.c
+    protocol.c
+    unix.c
+    win32.c
+)
+
+ADD_COMPILER_FLAGS("-DHAS_POLL -DHAS_FCNTL -DHAS_MSGHDR_FLAGS -DHAS_SOCKLEN_T")
+
+ORXONOX_ADD_LIBRARY(enet_orxonox
+    ORXONOX_EXTERNAL
+    VERSION         1.3.1
+    DEFINE_SYMBOL   "ENET_BUILDING_LIB"
+    LINK_LIBS_WIN32 odbc32 odbccp32 winmm ws2_32
+    SOURCE_FILES    ${ENET_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/external/enet/ChangeLog
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/ChangeLog	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/ChangeLog	(revision 11817)
@@ -0,0 +1,92 @@
+ENet 1.3.1 (February 10, 2011):
+
+* fixed bug in tracking of reliable data in transit
+* reliable data window size now scales with the throttle
+* fixed bug in fragment length calculation when checksums are used
+
+ENet 1.3.0 (June 5, 2010):
+
+* enet_host_create() now requires the channel limit to be specified as
+a parameter
+* enet_host_connect() now accepts a data parameter which is supplied 
+to the receiving receiving host in the event data field for a connect event
+* added an adaptive order-2 PPM range coder as a built-in compressor option
+which can be set with enet_host_compress_with_range_coder()
+* added support for packet compression configurable with a callback
+* improved session number handling to not rely on the packet checksum
+field, saving 4 bytes per packet unless the checksum option is used
+* removed the dependence on the rand callback for session number handling
+
+Caveats: This version is not protocol compatible with the 1.2 series or 
+earlier. The enet_host_connect and enet_host_create API functions require
+supplying additional parameters.
+
+ENet 1.2.2 (June 5, 2010):
+
+* checksum functionality is now enabled by setting a checksum callback
+inside ENetHost instead of being a configure script option
+* added totalSentData, totalSentPackets, totalReceivedData, and
+totalReceivedPackets counters inside ENetHost for getting usage
+statistics
+* added enet_host_channel_limit() for limiting the maximum number of
+channels allowed by connected peers
+* now uses dispatch queues for event dispatch rather than potentially
+unscalable array walking
+* added no_memory callback that is called when a malloc attempt fails,
+such that if no_memory returns rather than aborts (the default behavior),
+then the error is propagated to the return value of the API calls
+* now uses packed attribute for protocol structures on platforms with 
+strange alignment rules
+* improved autoconf build system contributed by Nathan Brink allowing 
+for easier building as a shared library
+
+Caveats: If you were using the compile-time option that enabled checksums,
+make sure to set the checksum callback inside ENetHost to enet_crc32 to
+regain the old behavior. The ENetCallbacks structure has added new fields,
+so make sure to clear the structure to zero before use if 
+using enet_initialize_with_callbacks().
+
+ENet 1.2.1 (November 12, 2009):
+
+* fixed bug that could cause disconnect events to be dropped
+* added thin wrapper around select() for portable usage
+* added ENET_SOCKOPT_REUSEADDR socket option
+* factored enet_socket_bind()/enet_socket_listen() out of enet_socket_create()
+* added contributed Code::Blocks build file
+
+ENet 1.2 (February 12, 2008):
+
+* fixed bug in VERIFY_CONNECT acknowledgement that could cause connect
+attempts to occasionally timeout
+* fixed acknowledgements to check both the outgoing and sent queues
+when removing acknowledged packets
+* fixed accidental bit rot in the MSVC project file
+* revised sequence number overflow handling to address some possible
+disconnect bugs
+* added enet_host_check_events() for getting only local queued events
+* factored out socket option setting into enet_socket_set_option() so
+that socket options are now set separately from enet_socket_create()
+
+Caveats: While this release is superficially protocol compatible with 1.1,
+differences in the sequence number overflow handling can potentially cause
+random disconnects.
+
+ENet 1.1 (June 6, 2007):
+
+* optional CRC32 just in case someone needs a stronger checksum than UDP 
+provides (--enable-crc32 configure option)
+* the size of packet headers are half the size they used to be (so less 
+overhead when sending small packets)
+* enet_peer_disconnect_later() that waits till all queued outgoing 
+packets get sent before issuing an actual disconnect
+* freeCallback field in individual packets for notification of when a 
+packet is about to be freed
+* ENET_PACKET_FLAG_NO_ALLOCATE for supplying pre-allocated data to a 
+packet (can be used in concert with freeCallback to support some custom 
+allocation schemes that the normal memory allocation callbacks would 
+normally not allow)
+* enet_address_get_host_ip() for printing address numbers
+* promoted the enet_socket_*() functions to be part of the API now
+* a few stability/crash fixes
+
+
Index: /code/branches/RacingBots_FS18/src/external/enet/Doxyfile
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/Doxyfile	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/Doxyfile	(revision 11817)
@@ -0,0 +1,993 @@
+# Doxyfile 1.2.18
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = enet
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with english messages), Korean, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these class will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = NO
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH        = 
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower case letters. If set to YES upper case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments  will behave just like the Qt-style comments (thus requiring an 
+# explict @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# reimplements.
+
+INHERIT_DOCS           = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consist of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
+# only. Doxygen will then generate output that is more tailored for C. 
+# For instance some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = . include/enet docs
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl
+
+FILE_PATTERNS          = *.c *.h *.dox
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = Tests
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output dir.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non empty doxygen will try to run 
+# the html help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the Html help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, 
+# or Internet explorer 4.0+). Note that for large projects the tree generation 
+# can take a very long time. In such cases it is better to disable this feature. 
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimised for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assigments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_XML           = NO
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED             = FORCE_DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superceded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yield more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermedate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
+
+# The CGI_NAME tag should be the name of the CGI script that 
+# starts the search engine (doxysearch) with the correct parameters. 
+# A script with this name will be generated by doxygen.
+
+CGI_NAME               = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the 
+# cgi binaries are located. See the documentation of your http daemon for 
+# details.
+
+CGI_URL                = 
+
+# The DOC_URL tag should be the absolute URL to the directory where the 
+# documentation is located. If left blank the absolute path to the 
+# documentation, with file:// prepended to it, will be used.
+
+DOC_URL                = 
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the 
+# documentation is located. If left blank the directory on the local machine 
+# will be used.
+
+DOC_ABSPATH            = 
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
+# is installed.
+
+BIN_ABSPATH            = /usr/local/bin/
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# documentation generated for other projects. This allows doxysearch to search 
+# the documentation for these projects as well.
+
+EXT_DOC_PATHS          = 
Index: /code/branches/RacingBots_FS18/src/external/enet/LICENSE
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/LICENSE	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/LICENSE	(revision 11817)
@@ -0,0 +1,7 @@
+Copyright (c) 2002-2011 Lee Salzman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Index: /code/branches/RacingBots_FS18/src/external/enet/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/README	(revision 11817)
@@ -0,0 +1,15 @@
+Please visit the ENet homepage at http://enet.bespin.org for installation
+and usage instructions.
+
+If you obtained this package from CVS, the quick description on how to build
+is:
+
+# Generate the build system.
+
+autoreconf -vfi
+
+# Compile and install the library.
+
+./configure && make && make install
+
+
Index: /code/branches/RacingBots_FS18/src/external/enet/VERSION
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/VERSION	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/VERSION	(revision 11817)
@@ -0,0 +1,2 @@
+ENet 1.3.1 fetched from CVS with last revision from
+Thu Feb 10 02:54:08 2011 +0000
Index: /code/branches/RacingBots_FS18/src/external/enet/callbacks.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/callbacks.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/callbacks.c	(revision 11817)
@@ -0,0 +1,47 @@
+/** 
+ @file callbacks.c
+ @brief ENet callback functions
+*/
+#define ENET_BUILDING_LIB 1
+#include "enet/enet.h"
+
+static ENetCallbacks callbacks = { malloc, free, abort };
+
+int
+enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits)
+{
+   if (version < ENET_VERSION_CREATE (1, 3, 0))
+     return -1;
+
+   if (inits -> malloc != NULL || inits -> free != NULL)
+   {
+      if (inits -> malloc == NULL || inits -> free == NULL)
+        return -1;
+
+      callbacks.malloc = inits -> malloc;
+      callbacks.free = inits -> free;
+   }
+      
+   if (inits -> no_memory != NULL)
+     callbacks.no_memory = inits -> no_memory;
+
+   return enet_initialize ();
+}
+           
+void *
+enet_malloc (size_t size)
+{
+   void * memory = callbacks.malloc (size);
+
+   if (memory == NULL)
+     callbacks.no_memory ();
+
+   return memory;
+}
+
+void
+enet_free (void * memory)
+{
+   callbacks.free (memory);
+}
+
Index: /code/branches/RacingBots_FS18/src/external/enet/callbacks.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/callbacks.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/callbacks.h	(revision 11817)
@@ -0,0 +1,27 @@
+/** 
+ @file  callbacks.h
+ @brief ENet callbacks
+*/
+#ifndef __ENET_CALLBACKS_H__
+#define __ENET_CALLBACKS_H__
+
+#include <stdlib.h>
+
+typedef struct _ENetCallbacks
+{
+    void * (ENET_CALLBACK * malloc) (size_t size);
+    void (ENET_CALLBACK * free) (void * memory);
+    void (ENET_CALLBACK * no_memory) (void);
+} ENetCallbacks;
+
+/** @defgroup callbacks ENet internal callbacks
+    @{
+    @ingroup private
+*/
+extern void * enet_malloc (size_t);
+extern void   enet_free (void *);
+
+/** @} */
+
+#endif /* __ENET_CALLBACKS_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/compress.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/compress.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/compress.c	(revision 11817)
@@ -0,0 +1,654 @@
+/** 
+ @file compress.c
+ @brief An adaptive order-2 PPM range coder
+*/
+#define ENET_BUILDING_LIB 1
+#include <string.h>
+#include "enet/enet.h"
+
+typedef struct _ENetSymbol
+{
+    /* binary indexed tree of symbols */
+    enet_uint8 value;
+    enet_uint8 count;
+    enet_uint16 under;
+    enet_uint16 left, right;
+
+    /* context defined by this symbol */
+    enet_uint16 symbols;
+    enet_uint16 escapes;
+    enet_uint16 total;
+    enet_uint16 parent; 
+} ENetSymbol;
+
+/* adaptation constants tuned aggressively for small packet sizes rather than large file compression */
+enum
+{
+    ENET_RANGE_CODER_TOP    = 1<<24,
+    ENET_RANGE_CODER_BOTTOM = 1<<16,
+
+    ENET_CONTEXT_SYMBOL_DELTA = 3,
+    ENET_CONTEXT_SYMBOL_MINIMUM = 1,
+    ENET_CONTEXT_ESCAPE_MINIMUM = 1,
+
+    ENET_SUBCONTEXT_ORDER = 2,
+    ENET_SUBCONTEXT_SYMBOL_DELTA = 2,
+    ENET_SUBCONTEXT_ESCAPE_DELTA = 5
+};
+
+/* context exclusion roughly halves compression speed, so disable for now */
+#undef ENET_CONTEXT_EXCLUSION
+
+typedef struct _ENetRangeCoder
+{
+    /* only allocate enough symbols for reasonable MTUs, would need to be larger for large file compression */
+    ENetSymbol symbols[4096];
+} ENetRangeCoder;
+
+void *
+enet_range_coder_create (void)
+{
+    ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc (sizeof (ENetRangeCoder));
+    if (rangeCoder == NULL)
+      return NULL;
+
+    return rangeCoder;
+}
+
+void
+enet_range_coder_destroy (void * context)
+{
+    ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
+    if (rangeCoder == NULL)
+      return;
+
+    enet_free (rangeCoder);
+}
+
+#define ENET_SYMBOL_CREATE(symbol, value_, count_) \
+{ \
+    symbol = & rangeCoder -> symbols [nextSymbol ++]; \
+    symbol -> value = value_; \
+    symbol -> count = count_; \
+    symbol -> under = count_; \
+    symbol -> left = 0; \
+    symbol -> right = 0; \
+    symbol -> symbols = 0; \
+    symbol -> escapes = 0; \
+    symbol -> total = 0; \
+    symbol -> parent = 0; \
+}
+
+#define ENET_CONTEXT_CREATE(context, escapes_, minimum) \
+{ \
+    ENET_SYMBOL_CREATE (context, 0, 0); \
+    (context) -> escapes = escapes_; \
+    (context) -> total = escapes_ + 256*minimum; \
+    (context) -> symbols = 0; \
+}
+
+static enet_uint16
+enet_symbol_rescale (ENetSymbol * symbol)
+{
+    enet_uint16 total = 0;
+    for (;;)
+    {
+        symbol -> count -= symbol->count >> 1;
+        symbol -> under = symbol -> count;
+        if (symbol -> left)
+          symbol -> under += enet_symbol_rescale (symbol + symbol -> left);
+        total += symbol -> under;
+        if (! symbol -> right) break;
+        symbol += symbol -> right;
+    } 
+    return total;
+}
+
+#define ENET_CONTEXT_RESCALE(context, minimum) \
+{ \
+    (context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \
+    (context) -> escapes -= (context) -> escapes >> 1; \
+    (context) -> total += (context) -> escapes + 256*minimum; \
+}
+
+#define ENET_RANGE_CODER_OUTPUT(value) \
+{ \
+    if (outData >= outEnd) \
+      return 0; \
+    * outData ++ = value; \
+}
+
+#define ENET_RANGE_CODER_ENCODE(under, count, total) \
+{ \
+    encodeRange /= (total); \
+    encodeLow += (under) * encodeRange; \
+    encodeRange *= (count); \
+    for (;;) \
+    { \
+        if((encodeLow ^ (encodeLow + encodeRange)) >= ENET_RANGE_CODER_TOP) \
+        { \
+            if(encodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
+            encodeRange = -encodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
+        } \
+        ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
+        encodeRange <<= 8; \
+        encodeLow <<= 8; \
+    } \
+}
+
+#define ENET_RANGE_CODER_FLUSH \
+{ \
+    while (encodeLow) \
+    { \
+        ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
+        encodeLow <<= 8; \
+    } \
+}
+
+#define ENET_RANGE_CODER_FREE_SYMBOLS \
+{ \
+    if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER ) \
+    { \
+        nextSymbol = 0; \
+        ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \
+        predicted = 0; \
+        order = 0; \
+    } \
+}
+
+#define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update, minimum) \
+{ \
+    under_ = value*minimum; \
+    count_ = minimum; \
+    if (! (context) -> symbols) \
+    { \
+        ENET_SYMBOL_CREATE (symbol_, value_, update); \
+        (context) -> symbols = symbol_ - (context); \
+    } \
+    else \
+    { \
+        ENetSymbol * node = (context) + (context) -> symbols; \
+        for (;;) \
+        { \
+            if (value_ < node -> value) \
+            { \
+                node -> under += update; \
+                if (node -> left) { node += node -> left; continue; } \
+                ENET_SYMBOL_CREATE (symbol_, value_, update); \
+                node -> left = symbol_ - node; \
+            } \
+            else \
+            if (value_ > node -> value) \
+            { \
+                under_ += node -> under; \
+                if (node -> right) { node += node -> right; continue; } \
+                ENET_SYMBOL_CREATE (symbol_, value_, update); \
+                node -> right = symbol_ - node; \
+            } \
+            else \
+            { \
+                count_ += node -> count; \
+                under_ += node -> under - node -> count; \
+                node -> under += update; \
+                node -> count += update; \
+                symbol_ = node; \
+            } \
+            break; \
+        } \
+    } \
+}
+
+#ifdef ENET_CONTEXT_EXCLUSION
+static const ENetSymbol emptyContext = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+#define ENET_CONTEXT_WALK(context, body) \
+{ \
+    const ENetSymbol * node = (context) + (context) -> symbols; \
+    const ENetSymbol * stack [256]; \
+    size_t stackSize = 0; \
+    while (node -> left) \
+    { \
+        stack [stackSize ++] = node; \
+        node += node -> left; \
+    } \
+    for (;;) \
+    { \
+        body; \
+        if (node -> right) \
+        { \
+            node += node -> right; \
+            while (node -> left) \
+            { \
+                stack [stackSize ++] = node; \
+                node += node -> left; \
+            } \
+        } \
+        else \
+        if (stackSize <= 0) \
+            break; \
+        else \
+            node = stack [-- stackSize]; \
+    } \
+}
+
+#define ENET_CONTEXT_ENCODE_EXCLUDE(context, value_, under, total, minimum) \
+ENET_CONTEXT_WALK(context, { \
+    if (node -> value != value_) \
+    { \
+        enet_uint16 parentCount = rangeCoder -> symbols [node -> parent].count + minimum; \
+        if (node -> value < value_) \
+          under -= parentCount; \
+        total -= parentCount; \
+    } \
+})
+#endif
+
+size_t
+enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit)
+{
+    ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
+    enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
+    const enet_uint8 * inData, * inEnd;
+    enet_uint32 encodeLow = 0, encodeRange = ~0;
+    ENetSymbol * root;
+    enet_uint16 predicted = 0;
+    size_t order = 0, nextSymbol = 0;
+
+    if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0)
+      return 0;
+
+    inData = (const enet_uint8 *) inBuffers -> data;
+    inEnd = & inData [inBuffers -> dataLength];
+    inBuffers ++;
+    inBufferCount --;
+
+    ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
+
+    for (;;)
+    {
+        ENetSymbol * subcontext, * symbol;
+#ifdef ENET_CONTEXT_EXCLUSION
+        const ENetSymbol * childContext = & emptyContext;
+#endif
+        enet_uint8 value;
+        enet_uint16 count, under, * parent = & predicted, total;
+        if (inData >= inEnd)
+        {
+            if (inBufferCount <= 0)
+              break;
+            inData = (const enet_uint8 *) inBuffers -> data;
+            inEnd = & inData [inBuffers -> dataLength];
+            inBuffers ++;
+            inBufferCount --;
+        }
+        value = * inData ++;
+    
+        for (subcontext = & rangeCoder -> symbols [predicted]; 
+             subcontext != root; 
+#ifdef ENET_CONTEXT_EXCLUSION
+             childContext = subcontext, 
+#endif
+                subcontext = & rangeCoder -> symbols [subcontext -> parent])
+        {
+            ENET_CONTEXT_ENCODE (subcontext, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
+            * parent = symbol - rangeCoder -> symbols;
+            parent = & symbol -> parent;
+            total = subcontext -> total;
+#ifdef ENET_CONTEXT_EXCLUSION
+            if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
+              ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, 0);
+#endif
+            if (count > 0)
+            {
+                ENET_RANGE_CODER_ENCODE (subcontext -> escapes + under, count, total);
+            }
+            else
+            {
+                if (subcontext -> escapes > 0 && subcontext -> escapes < total) 
+                    ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, total); 
+                subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
+                subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
+            }
+            subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
+            if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
+              ENET_CONTEXT_RESCALE (subcontext, 0);
+            if (count > 0) goto nextInput;
+        }
+
+        ENET_CONTEXT_ENCODE (root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM);
+        * parent = symbol - rangeCoder -> symbols;
+        parent = & symbol -> parent;
+        total = root -> total;
+#ifdef ENET_CONTEXT_EXCLUSION
+        if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
+          ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, ENET_CONTEXT_SYMBOL_MINIMUM); 
+#endif
+        ENET_RANGE_CODER_ENCODE (root -> escapes + under, count, total);
+        root -> total += ENET_CONTEXT_SYMBOL_DELTA; 
+        if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
+          ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
+
+    nextInput:
+        if (order >= ENET_SUBCONTEXT_ORDER) 
+          predicted = rangeCoder -> symbols [predicted].parent;
+        else 
+          order ++;
+        ENET_RANGE_CODER_FREE_SYMBOLS;
+    }
+
+    ENET_RANGE_CODER_FLUSH;
+
+    return (size_t) (outData - outStart);
+}
+
+#define ENET_RANGE_CODER_SEED \
+{ \
+    if (inData < inEnd) decodeCode |= * inData ++ << 24; \
+    if (inData < inEnd) decodeCode |= * inData ++ << 16; \
+    if (inData < inEnd) decodeCode |= * inData ++ << 8; \
+    if (inData < inEnd) decodeCode |= * inData ++; \
+}
+
+#define ENET_RANGE_CODER_READ(total) ((decodeCode - decodeLow) / (decodeRange /= (total)))
+
+#define ENET_RANGE_CODER_DECODE(under, count, total) \
+{ \
+    decodeLow += (under) * decodeRange; \
+    decodeRange *= (count); \
+    for (;;) \
+    { \
+        if((decodeLow ^ (decodeLow + decodeRange)) >= ENET_RANGE_CODER_TOP) \
+        { \
+            if(decodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
+            decodeRange = -decodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
+        } \
+        decodeCode <<= 8; \
+        if (inData < inEnd) \
+          decodeCode |= * inData ++; \
+        decodeRange <<= 8; \
+        decodeLow <<= 8; \
+    } \
+}
+
+#define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, createRoot, visitNode, createRight, createLeft) \
+{ \
+    under_ = 0; \
+    count_ = minimum; \
+    if (! (context) -> symbols) \
+    { \
+        createRoot; \
+    } \
+    else \
+    { \
+        ENetSymbol * node = (context) + (context) -> symbols; \
+        for (;;) \
+        { \
+            enet_uint16 after = under_ + node -> under + (node -> value + 1)*minimum, before = node -> count + minimum; \
+            visitNode; \
+            if (code >= after) \
+            { \
+                under_ += node -> under; \
+                if (node -> right) { node += node -> right; continue; } \
+                createRight; \
+            } \
+            else \
+            if (code < after - before) \
+            { \
+                node -> under += update; \
+                if (node -> left) { node += node -> left; continue; } \
+                createLeft; \
+            } \
+            else \
+            { \
+                value_ = node -> value; \
+                count_ += node -> count; \
+                under_ = after - before; \
+                node -> under += update; \
+                node -> count += update; \
+                symbol_ = node; \
+            } \
+            break; \
+        } \
+    } \
+}
+
+#define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
+ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, return 0, exclude (node -> value, after, before), return 0, return 0)
+
+#define ENET_CONTEXT_ROOT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
+ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, \
+    { \
+        value_ = code / minimum; \
+        under_ = code - code%minimum; \
+        ENET_SYMBOL_CREATE (symbol_, value_, update); \
+        (context) -> symbols = symbol_ - (context); \
+    }, \
+    exclude (node -> value, after, before), \
+    { \
+        value_ = node->value + 1 + (code - after)/minimum; \
+        under_ = code - (code - after)%minimum; \
+        ENET_SYMBOL_CREATE (symbol_, value_, update); \
+        node -> right = symbol_ - node; \
+    }, \
+    { \
+        value_ = node->value - 1 - (after - before - code - 1)/minimum; \
+        under_ = code - (after - before - code - 1)%minimum; \
+        ENET_SYMBOL_CREATE (symbol_, value_, update); \
+        node -> left = symbol_ - node; \
+    }) \
+
+#ifdef ENET_CONTEXT_EXCLUSION
+typedef struct _ENetExclude
+{
+    enet_uint8 value;
+    enet_uint16 under;
+} ENetExclude;
+
+#define ENET_CONTEXT_DECODE_EXCLUDE(context, total, minimum) \
+{ \
+    enet_uint16 under = 0; \
+    nextExclude = excludes; \
+    ENET_CONTEXT_WALK (context, { \
+        under += rangeCoder -> symbols [node -> parent].count + minimum; \
+        nextExclude -> value = node -> value; \
+        nextExclude -> under = under; \
+        nextExclude ++; \
+    }); \
+    total -= under; \
+}
+
+#define ENET_CONTEXT_EXCLUDED(value_, after, before) \
+{ \
+    size_t low = 0, high = nextExclude - excludes; \
+    for(;;) \
+    { \
+        size_t mid = (low + high) >> 1; \
+        const ENetExclude * exclude = & excludes [mid]; \
+        if (value_ < exclude -> value) \
+        { \
+            if (low + 1 < high) \
+            { \
+                high = mid; \
+                continue; \
+            } \
+            if (exclude > excludes) \
+              after -= exclude [-1].under; \
+        } \
+        else \
+        { \
+            if (value_ > exclude -> value) \
+            { \
+                if (low + 1 < high) \
+                { \
+                    low = mid; \
+                    continue; \
+                } \
+            } \
+            else \
+              before = 0; \
+            after -= exclude -> under; \
+        } \
+        break; \
+    } \
+}
+#endif
+
+#define ENET_CONTEXT_NOT_EXCLUDED(value_, after, before)
+
+size_t
+enet_range_coder_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit)
+{
+    ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
+    enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
+    const enet_uint8 * inEnd = & inData [inLimit];
+    enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0;
+    ENetSymbol * root;
+    enet_uint16 predicted = 0;
+    size_t order = 0, nextSymbol = 0;
+#ifdef ENET_CONTEXT_EXCLUSION
+    ENetExclude excludes [256];
+    ENetExclude * nextExclude = excludes;
+#endif
+  
+    if (rangeCoder == NULL || inLimit <= 0)
+      return 0;
+
+    ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
+
+    ENET_RANGE_CODER_SEED;
+
+    for (;;)
+    {
+        ENetSymbol * subcontext, * symbol, * patch;
+#ifdef ENET_CONTEXT_EXCLUSION
+        const ENetSymbol * childContext = & emptyContext;
+#endif
+        enet_uint8 value = 0;
+        enet_uint16 code, under, count, bottom, * parent = & predicted, total;
+
+        for (subcontext = & rangeCoder -> symbols [predicted];
+             subcontext != root;
+#ifdef ENET_CONTEXT_EXCLUSION
+             childContext = subcontext, 
+#endif
+                subcontext = & rangeCoder -> symbols [subcontext -> parent])
+        {
+            if (subcontext -> escapes <= 0)
+              continue;
+            total = subcontext -> total;
+#ifdef ENET_CONTEXT_EXCLUSION
+            if (childContext -> total > 0) 
+              ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, 0); 
+#endif
+            if (subcontext -> escapes >= total)
+              continue;
+            code = ENET_RANGE_CODER_READ (total);
+            if (code < subcontext -> escapes) 
+            {
+                ENET_RANGE_CODER_DECODE (0, subcontext -> escapes, total); 
+                continue;
+            }
+            code -= subcontext -> escapes;
+#ifdef ENET_CONTEXT_EXCLUSION
+            if (childContext -> total > 0)
+            {
+                ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_EXCLUDED); 
+            }
+            else
+#endif
+            {
+                ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_NOT_EXCLUDED); 
+            }
+            bottom = symbol - rangeCoder -> symbols;
+            ENET_RANGE_CODER_DECODE (subcontext -> escapes + under, count, total);
+            subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
+            if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
+              ENET_CONTEXT_RESCALE (subcontext, 0);
+            goto patchContexts;
+        }
+
+        total = root -> total;
+#ifdef ENET_CONTEXT_EXCLUSION
+        if (childContext -> total > 0)
+          ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, ENET_CONTEXT_SYMBOL_MINIMUM);  
+#endif
+        code = ENET_RANGE_CODER_READ (total);
+        if (code < root -> escapes)
+        {
+            ENET_RANGE_CODER_DECODE (0, root -> escapes, total);
+            break;
+        }
+        code -= root -> escapes;
+#ifdef ENET_CONTEXT_EXCLUSION
+        if (childContext -> total > 0)
+        {
+            ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_EXCLUDED); 
+        }
+        else
+#endif
+        {
+            ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_NOT_EXCLUDED); 
+        }
+        bottom = symbol - rangeCoder -> symbols;
+        ENET_RANGE_CODER_DECODE (root -> escapes + under, count, total);
+        root -> total += ENET_CONTEXT_SYMBOL_DELTA;
+        if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
+          ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
+
+    patchContexts:
+        for (patch = & rangeCoder -> symbols [predicted];
+             patch != subcontext;
+             patch = & rangeCoder -> symbols [patch -> parent])
+        {
+            ENET_CONTEXT_ENCODE (patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
+            * parent = symbol - rangeCoder -> symbols;
+            parent = & symbol -> parent;
+            if (count <= 0)
+            {
+                patch -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
+                patch -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
+            }
+            patch -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; 
+            if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || patch -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
+              ENET_CONTEXT_RESCALE (patch, 0);
+        }
+        * parent = bottom;
+
+        ENET_RANGE_CODER_OUTPUT (value);
+
+        if (order >= ENET_SUBCONTEXT_ORDER)
+          predicted = rangeCoder -> symbols [predicted].parent;
+        else
+          order ++;
+        ENET_RANGE_CODER_FREE_SYMBOLS;
+    }
+                        
+    return (size_t) (outData - outStart);
+}
+
+/** @defgroup host ENet host functions
+    @{
+*/
+
+/** Sets the packet compressor the host should use to the default range coder.
+    @param host host to enable the range coder for
+    @returns 0 on success, < 0 on failure
+*/
+int
+enet_host_compress_with_range_coder (ENetHost * host)
+{
+    ENetCompressor compressor;
+    memset (& compressor, 0, sizeof (compressor));
+    compressor.context = enet_range_coder_create();
+    if (compressor.context == NULL)
+      return -1;
+    compressor.compress = enet_range_coder_compress;
+    compressor.decompress = enet_range_coder_decompress;
+    compressor.destroy = enet_range_coder_destroy;
+    enet_host_compress (host, & compressor);
+    return 0;
+}
+    
+/** @} */
+    
+     
Index: /code/branches/RacingBots_FS18/src/external/enet/docs/FAQ.dox
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/docs/FAQ.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/docs/FAQ.dox	(revision 11817)
@@ -0,0 +1,24 @@
+/**
+ @page FAQ Frequently Answered Questions
+
+@section Q1 Is ENet thread safe?
+
+ENet does not use any significant global variables, the vast majority
+of state is encapsulated in the ENetHost structure.  As such, as long
+as the application guards access to this structure, then ENet should
+operate fine in a multithreaded environment.
+   
+@section Q2 Isn't ENet just re-inventing TCP?!  What's the point?
+
+In a perfect world, that would be true.  But as many have found, using
+TCP either in lieu of or in conjunction with UDP can lead to all kinds
+of nightmares.  TCP is a good, solid protocol, however it simply isn't
+up to the task of real-time games.  Too much of TCP's implementation
+dictates a policy that isn't practical for games.  If you want to use
+TCP, then do so -- this library is for people that either don't want
+to use TCP or have tried and ended up being discouraged with the
+performance.
+
+*/
+
+
Index: /code/branches/RacingBots_FS18/src/external/enet/docs/design.dox
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/docs/design.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/docs/design.dox	(revision 11817)
@@ -0,0 +1,126 @@
+/**
+@page Features Features and Architecture
+
+ENet evolved specifically as a UDP networking layer for the
+multiplayer first person shooter Cube. Cube necessitated low latency
+communcation with data sent out very frequently, so TCP was an
+unsuitable choice due to its high latency and stream orientation. UDP,
+however, lacks many sometimes necessary features from TCP such as
+reliability, sequencing, unrestricted packet sizes, and connection
+management. So UDP by itself was not suitable as a network protocol
+either. No suitable freely available networking libraries existed at
+the time of ENet's creation to fill this niche.
+
+UDP and TCP could have been used together in Cube to benefit somewhat
+from both of their features, however, the resulting combinations of
+protocols still leaves much to be desired. TCP lacks multiple streams
+of communication without resorting to opening many sockets and
+complicates delineation of packets due to its buffering behavior. UDP
+lacks sequencing, connection management, management of bandwidth
+resources, and imposes limitations on the size of packets. A
+significant investment is required to integrate these two protocols,
+and the end result is worse off in features and performance than the
+uniform protocol presented by ENet.
+
+ENet thus attempts to address these issues and provide a single,
+uniform protocol layered over UDP to the developer with the best
+features of UDP and TCP as well as some useful features neither
+provide, with a much cleaner integration than any resulting from a
+mixture of UDP and TCP.
+
+@section CM Connection Management
+
+ENet provides a simple connection interface over which to communicate
+with a foreign host. The liveness of the connection is actively
+monitored by pinging the foreign host at frequent intervals, and also
+monitors the network conditions from the local host to the foreign
+host such as the mean round trip time and packet loss in this fashion.
+
+@section Sequencing Sequencing
+    
+Rather than a single byte stream that complicates the delineation of
+packets, ENet presents connections as multiple, properly sequenced
+packet streams that simplify the transfer of various types of data.
+
+ENet provides sequencing for all packets by assigning to each sent
+packet a sequence number that is incremented as packets are sent. ENet
+guarentees that no packet with a higher sequence number will be
+delivered before a packet with a lower sequence number, thus ensuring
+packets are delivered exactly in the order they are sent.
+
+For unreliable packets, ENet will simply discard the lower sequence
+number packet if a packet with a higher sequence number has already
+been delivered. This allows the packets to be dispatched immediately
+as they arrive, and reduce latency of unreliable packets to an
+absolute minimum.  For reliable packets, if a higher sequence number
+packet arrives, but the preceding packets in the sequence have not yet
+arrived, ENet will stall delivery of the higher sequence number
+packets until its predecessors have arrived.
+
+@section Channels Channels
+
+Since ENet will stall delivery of reliable packets to ensure proper
+sequencing, and consequently any packets of higher sequence number
+whether reliable or unreliable, in the event the reliable packet's
+predecessors have not yet arrived, this can introduce latency into the
+delivery of other packets which may not need to be as strictly ordered
+with respect to the packet that stalled their delivery.
+
+To combat this latency and reduce the ordering restrictions on
+packets, ENet provides multiple channels of communication over a given
+connection.  Each channel is independently sequenced, and so the
+delivery status of a packet in one channel will not stall the delivery
+of other packets in another channel.
+
+@section Reliability Reliability
+
+ENet provides optional reliability of packet delivery by ensuring the
+foreign host acknowledges receipt of all reliable packets. ENet will
+attempt to resend the packet up to a reasonable amount of times, if no
+acknowledgement of the packet's receipt happens within a specified
+timeout. Retry timeouts are progressive and become more lenient with
+every failed attempt to allow for temporary turbulence in network
+conditions.
+
+@section FaR Fragmentation and Reassembly
+
+ENet will send and deliver packets regardless of size. Large packets
+are fragmented into many smaller packets of suitable size, and
+reassembled on the foreign host to recover the original packet for
+delivery. The process is entirely transparent to the developer.
+
+@section Aggregation Aggregation
+
+ENet aggregates all protocol commands, including acknowledgements and
+packet transfer, into larger protocol packets to ensure the proper
+utilization of the connection and to limit the opportunities for
+packet loss that might otherwise result in further delivery latency.
+
+@section Adaptability Adaptability
+
+ENet provides an in-flight data window for reliable packets to ensure
+connections are not overwhelmed by volumes of packets. It also
+provides a static bandwidth allocation mechanism to ensure the total
+volume of packets sent and received to a host don't exceed the host's
+capabilities. Further, ENet also provides a dynamic throttle that
+responds to deviations from normal network connections to rectify
+various types of network congestion by further limiting the volume of
+packets sent.
+
+@section Portability Portability
+    
+ENet works on Windows and any other Unix or Unix-like platform
+providing a BSD sockets interface. The library has a small and stable
+code base that can easily be extended to support other platforms and
+integrates easily.  ENet makes no assumptions about the underlying
+platform's endianess or word size.
+
+@section Freedom Freedom
+
+ENet demands no royalties and doesn't carry a viral license that would
+restrict you in how you might use it in your programs. ENet is
+licensed under a short-and-sweet MIT-style license, which gives you
+the freedom to do anything you want with it (well, almost anything).
+
+*/
+
Index: /code/branches/RacingBots_FS18/src/external/enet/docs/install.dox
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/docs/install.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/docs/install.dox	(revision 11817)
@@ -0,0 +1,60 @@
+/**
+@page Installation Installation
+
+ENet should be trivially simple to integrate with most applications.
+First, make sure you download the latest source distribution here @ref
+SourceDistro.
+
+@section Unix Unix-like Operating Systems
+
+If you are using an ENet release, then you should simply be able to build it
+by doing the following:
+
+./configure && make && make install
+
+If you obtained the package from CVS, you must have automake and autoconf
+available to generate the build system first by doing the following command
+before using the above mentioned build procedure:
+
+autoreconf -vfi
+
+
+@subsection SolarisBSD Solaris and BSD
+
+When building ENet under Solaris, you must specify the -lsocket and
+-lnsl parameters to your compiler to ensure that the sockets library
+is linked in.
+
+@section Windows Microsoft Windows
+
+There is an included MSVC 6 project (enet.dsp) which you may use to
+build a suitable library file. Alternatively, you may simply drag all 
+the ENet source files into your main project.
+
+You will have to link to the Winsock2 libraries, so make sure to add
+ws2_32.lib and winmm.lib to your library list (Project Settings | Link |
+Object/library modules).
+
+@subsection enet.dsp Building with the included enet.dsp
+
+Load the included enet.dsp. MSVC may ask you to convert it if you
+are on a newer version of MSVC - just allow the conversion and save
+the resulting project as "enet" or similar. After you build this
+project, it will output an "enet.lib" file to either the "Debug/"
+or "Release/" directory, depending on which configuration you have
+selected to build. By default, it should produce "Debug/enet.lib".
+
+You may then copy the resulting "enet.lib" file and the header files
+found in the "include/" directory to your other projects and add it to 
+their library lists. Make sure to also link against "ws2_32.lib" and
+"winmm.lib" as described above.
+
+@subsection DLL DLL
+
+If you wish to build ENet as a DLL you must first define ENET_DLL
+within the project (Project Settings | C/C++ | Preprocessor |
+Preprocessor definitions) or, more invasively, simply define ENET_DLL
+at the top of enet.h.
+
+*/
+
Index: /code/branches/RacingBots_FS18/src/external/enet/docs/license.dox
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/docs/license.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/docs/license.dox	(revision 11817)
@@ -0,0 +1,26 @@
+/**
+ @page License License
+ 
+Copyright (c) 2002-2010 Lee Salzman
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
Index: /code/branches/RacingBots_FS18/src/external/enet/docs/mainpage.dox
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/docs/mainpage.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/docs/mainpage.dox	(revision 11817)
@@ -0,0 +1,75 @@
+/** @page enet
+ <center>http://enet.bespin.org</center>
+ <hr>
+
+ENet's purpose is to provide a relatively thin, simple and robust
+network communication layer on top of UDP (User Datagram Protocol).
+The primary feature it provides is optional reliable, in-order
+delivery of packets.
+
+ENet omits certain higher level networking features such as authentication, 
+lobbying, server discovery, encryption, or other similar tasks that are
+particularly application specific so that the library remains flexible,
+portable, and easily embeddable.
+
+@ref Features
+
+@ref SourceDistro
+
+@ref Installation
+
+@ref Tutorial
+
+@ref MailingList
+
+@ref IRCChannel
+
+@ref FAQ
+
+@ref License
+
+ */
+
+/**
+@page SourceDistro Source Distribution
+
+You can retrieve the source to ENet by downloading it in either .tar.gz form
+or accessing the cvs distribution directly.
+
+The most recent stable release (1.3.0) can be downloaded <a href="http://enet.bespin.org/download/enet-1.3.0.tar.gz">here</a>. 
+The last release that is protocol compatible with the 1.2 series or earlier (1.2.2) can be downloaded <a href="http://enet.bespin.org/download/enet-1.2.2.tar.gz">here</a> 
+
+To access ENet via anonymous CVS, you must use the CVSROOT
+:pserver:anonymous\@bespin.org:/var/lib/cvs/enet with an empty
+password.
+
+@code
+	$ cvs -z3 -d :pserver:anonymous@bespin.org:/var/lib/cvs/enet login
+@endcode
+	Hit the return key when prompted for a password.
+@code
+	$ cvs -z3 -d :pserver:anonymous@bespin.org:/var/lib/cvs/enet co -l .
+	$ cvs -z3 co enet
+@endcode
+
+This will create a CVS directory in the current directory, and with
+the second command will proceed to check the enet module out of CVS.
+Any problems with CVS access or request for write access should be
+sent via email to @ref MailingList.
+
+*/
+
+/**
+@page MailingList ENet Mailing List
+
+The <a href="http://lists.cubik.org/mailman/listinfo/enet-discuss">enet-discuss</a> list is for discussion of ENet, including bug reports or feature requests.
+
+*/
+
+/**
+@page IRCChannel ENet IRC Channel
+
+Join the \#enet channel on the freenode IRC network (irc.freenode.net) for real-time discussion about the ENet library.
+
+*/
+
Index: /code/branches/RacingBots_FS18/src/external/enet/docs/tutorial.dox
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/docs/tutorial.dox	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/docs/tutorial.dox	(revision 11817)
@@ -0,0 +1,357 @@
+/**
+@page Tutorial Tutorial
+
+@ref Initialization
+
+@ref CreateServer
+
+@ref CreateClient
+
+@ref ManageHost
+
+@ref SendingPacket
+
+@ref Disconnecting
+
+@ref Connecting
+
+@section Initialization Initialization
+
+You should include the file <enet/enet.h> when using ENet. Do not
+include <enet.h> without the directory prefix, as this may cause
+file name conflicts on some systems.
+
+Before using ENet, you must call enet_initialize() to initialize the
+library. Upon program exit, you should call enet_deinitialize() so
+that the library may clean up any used resources.
+
+@code
+#include <enet/enet.h>
+
+int 
+main (int argc, char ** argv) 
+{
+    if (enet_initialize () != 0)
+    {
+        fprintf (stderr, "An error occurred while initializing ENet.\n");
+        return EXIT_FAILURE;
+    }
+    atexit (enet_deinitialize);
+    ...
+    ...
+    ...
+}
+@endcode
+        
+@section CreateServer Creating an ENet server
+
+Servers in ENet are constructed with enet_host_create(). You must
+specify an address on which to receive data and new connections, as
+well as the maximum allowable numbers of connected peers. You may
+optionally specify the incoming and outgoing bandwidth of the server
+in bytes per second so that ENet may try to statically manage
+bandwidth resources among connected peers in addition to its dynamic
+throttling algorithm; specifying 0 for these two options will cause
+ENet to rely entirely upon its dynamic throttling algorithm to manage
+bandwidth.
+
+When done with a host, the host may be destroyed with
+enet_host_destroy().  All connected peers to the host will be reset,
+and the resources used by the host will be freed.
+
+@code
+    ENetAddress address;
+    ENetHost * server;
+
+    /* Bind the server to the default localhost.     */
+    /* A specific host address can be specified by   */
+    /* enet_address_set_host (& address, "x.x.x.x"); */
+
+    address.host = ENET_HOST_ANY;
+    /* Bind the server to port 1234. */
+    address.port = 1234;
+
+    server = enet_host_create (& address /* the address to bind the server host to */, 
+                                 32      /* allow up to 32 clients and/or outgoing connections */,
+                                  2      /* allow up to 2 channels to be used, 0 and 1 */,
+                                  0      /* assume any amount of incoming bandwidth */,
+                                  0      /* assume any amount of outgoing bandwidth */);
+    if (server == NULL)
+    {
+        fprintf (stderr, 
+                 "An error occurred while trying to create an ENet server host.\n");
+        exit (EXIT_FAILURE);
+    }
+    ...
+    ...
+    ...
+    enet_host_destroy(server);
+@endcode
+
+@section CreateClient Creating an ENet client
+
+Clients in ENet are similarly constructed with enet_host_create() when
+no address is specified to bind the host to. Bandwidth may be
+specified for the client host as in the above example. The peer count
+controls the maximum number of connections to other server hosts that
+may be simultaneously open.
+
+@code
+    ENetHost * client;
+
+    client = enet_host_create (NULL /* create a client host */,
+                1 /* only allow 1 outgoing connection */,
+                2 /* allow up 2 channels to be used, 0 and 1 */,
+                57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */,
+                14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */);
+
+    if (client == NULL)
+    {
+        fprintf (stderr, 
+                 "An error occurred while trying to create an ENet client host.\n");
+        exit (EXIT_FAILURE);
+    }
+    ...
+    ...
+    ...
+    enet_host_destroy(client);
+@endcode
+
+@section ManageHost Managing an ENet host
+
+ENet uses a polled event model to notify the programmer of significant
+events. ENet hosts are polled for events with enet_host_service(),
+where an optional timeout value in milliseconds may be specified to
+control how long ENet will poll; if a timeout of 0 is specified,
+enet_host_service() will return immediately if there are no events to
+dispatch. enet_host_service() will return 1 if an event was dispatched
+within the specified timeout.
+
+Currently there are only four types of significant events in ENet:
+
+An event of type ENET_EVENT_TYPE_NONE is returned if no event occurred
+within the specified time limit. enet_host_service() will return 0
+with this event.
+
+An event of type ENET_EVENT_TYPE_CONNECT is returned when either a new client
+host has connected to the server host or when an attempt to establish a 
+connection with a foreign host has succeeded. Only the "peer" field of the 
+event structure is valid for this event and contains the newly connected peer.
+
+An event of type ENET_EVENT_TYPE_RECEIVE is returned when a packet is received
+from a connected peer. The "peer" field contains the peer the packet was 
+received from, "channelID" is the channel on which the packet was sent, and 
+"packet" is the packet that was sent. The packet contained in the "packet" 
+field must be destroyed with enet_packet_destroy() when you are done 
+inspecting its contents.
+
+An event of type ENET_EVENT_TYPE_DISCONNECT is returned when a connected peer
+has either explicitly disconnected or timed out. Only the "peer" field of the
+event structure is valid for this event and contains the peer that 
+disconnected. Only the "data" field of the peer is still valid on a 
+disconnect event and must be explicitly reset.
+
+@code
+    ENetEvent event;
+    
+    /* Wait up to 1000 milliseconds for an event. */
+    while (enet_host_service (client, & event, 1000) > 0)
+    {
+        switch (event.type)
+        {
+        case ENET_EVENT_TYPE_CONNECT:
+            printf ("A new client connected from %x:%u.\n", 
+                    event.peer -> address.host,
+                    event.peer -> address.port);
+
+            /* Store any relevant client information here. */
+            event.peer -> data = "Client information";
+
+            break;
+
+        case ENET_EVENT_TYPE_RECEIVE:
+            printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
+                    event.packet -> dataLength,
+                    event.packet -> data,
+                    event.peer -> data,
+                    event.channelID);
+
+            /* Clean up the packet now that we're done using it. */
+            enet_packet_destroy (event.packet);
+            
+            break;
+           
+        case ENET_EVENT_TYPE_DISCONNECT:
+            printf ("%s disconected.\n", event.peer -> data);
+
+            /* Reset the peer's client information. */
+
+            event.peer -> data = NULL;
+        }
+    }
+    ...
+    ...
+    ...
+@endcode
+
+@section SendingPacket Sending a packet to an ENet peer            
+
+Packets in ENet are created with enet_packet_create(), where the size
+of the packet must be specified. Optionally, initial data may be
+specified to copy into the packet.
+
+Certain flags may also be supplied to enet_packet_create() to control
+various packet features:
+
+ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable
+delivery.  A reliable packet is guarenteed to be delivered, and a
+number of retry attempts will be made until an acknowledgement is
+received from the foreign host the packet is sent to. If a certain
+number of retry attempts is reached without any acknowledgement, ENet
+will assume the peer has disconnected and forcefully reset the
+connection. If this flag is not specified, the packet is assumed an
+unreliable packet, and no retry attempts will be made nor
+acknowledgements generated.
+
+A packet may be resized (extended or truncated) with
+enet_packet_resize().
+
+A packet is sent to a foreign host with
+enet_peer_send(). enet_peer_send() accepts a channel id over which to
+send the packet to a given peer. Once the packet is handed over to
+ENet with enet_peer_send(), ENet will handle its deallocation and
+enet_packet_destroy() should not be used upon it.
+
+One may also use enet_host_broadcast() to send a packet to all
+connected peers on a given host over a specified channel id, as with
+enet_peer_send().
+
+Queued packets will be sent on a call to enet_host_service().
+Alternatively, enet_host_flush() will send out queued packets without
+dispatching any events.
+
+@code
+    /* Create a reliable packet of size 7 containing "packet\0" */
+    ENetPacket * packet = enet_packet_create ("packet", 
+                                              strlen ("packet") + 1, 
+                                              ENET_PACKET_FLAG_RELIABLE);
+
+    /* Extend the packet so and append the string "foo", so it now */
+    /* contains "packetfoo\0"                                      */
+    enet_packet_resize (packet, strlen ("packetfoo") + 1);
+    strcpy (& packet -> data [strlen ("packet")], "foo");
+    
+    /* Send the packet to the peer over channel id 0. */
+    /* One could also broadcast the packet by         */
+    /* enet_host_broadcast (host, 0, packet);         */
+    enet_peer_send (peer, 0, packet);
+    ...
+    ...
+    ...
+    /* One could just use enet_host_service() instead. */
+    enet_host_flush (host);
+@endcode
+
+@section Disconnecting Disconnecting an ENet peer
+
+Peers may be gently disconnected with enet_peer_disconnect(). A
+disconnect request will be sent to the foreign host, and ENet will
+wait for an acknowledgement from the foreign host before finally
+disconnecting. An event of type ENET_EVENT_TYPE_DISCONNECT will be
+generated once the disconnection succeeds. Normally timeouts apply to
+the disconnect acknowledgement, and so if no acknowledgement is
+received after a length of time the peer will be forcefully
+disconnected.
+
+enet_peer_reset() will forcefully disconnect a peer. The foreign host
+will get no notification of a disconnect and will time out on the
+foreign host. No event is generated.
+
+@code
+    ENetEvent event;
+    
+    enet_peer_disconnect (peer, 0);
+
+    /* Allow up to 3 seconds for the disconnect to succeed
+     * and drop any packets received packets.
+     */
+    while (enet_host_service (client, & event, 3000) > 0)
+    {
+        switch (event.type)
+        {
+        case ENET_EVENT_TYPE_RECEIVE:
+            enet_packet_destroy (event.packet);
+            break;
+
+        case ENET_EVENT_TYPE_DISCONNECT:
+            puts ("Disconnection succeeded.");
+            return;
+        ...
+        ...
+        ...
+        }
+    }
+    
+    /* We've arrived here, so the disconnect attempt didn't */
+    /* succeed yet.  Force the connection down.             */
+    enet_peer_reset (peer);
+    ...
+    ...
+    ...
+@endcode
+
+@section Connecting Connecting to an ENet host
+
+A connection to a foreign host is initiated with enet_host_connect().
+It accepts the address of a foreign host to connect to, and the number
+of channels that should be allocated for communication. If N channels
+are allocated for use, their channel ids will be numbered 0 through
+N-1.  A peer representing the connection attempt is returned, or NULL
+if there were no available peers over which to initiate the
+connection. When the connection attempt succeeds, an event of type
+ENET_EVENT_TYPE_CONNECT will be generated. If the connection attempt
+times out or otherwise fails, an event of type
+ENET_EVENT_TYPE_DISCONNECT will be generated.
+
+@code
+    ENetAddress address;
+    ENetEvent event;
+    ENetPeer *peer;
+
+    /* Connect to some.server.net:1234. */
+    enet_address_set_host (& address, "some.server.net");
+    address.port = 1234;
+
+    /* Initiate the connection, allocating the two channels 0 and 1. */
+    peer = enet_host_connect (client, & address, 2, 0);    
+    
+    if (peer == NULL)
+    {
+       fprintf (stderr, 
+                "No available peers for initiating an ENet connection.\n");
+       exit (EXIT_FAILURE);
+    }
+    
+    /* Wait up to 5 seconds for the connection attempt to succeed. */
+    if (enet_host_service (client, & event, 5000) > 0 &&
+        event.type == ENET_EVENT_TYPE_CONNECT)
+    {
+        puts ("Connection to some.server.net:1234 succeeded.");
+        ...
+        ...
+        ...
+    }
+    else
+    {
+        /* Either the 5 seconds are up or a disconnect event was */
+        /* received. Reset the peer in the event the 5 seconds   */
+        /* had run out without any significant event.            */
+        enet_peer_reset (peer);
+
+        puts ("Connection to some.server.net:1234 failed.");
+    }
+    ...
+    ...
+    ...
+@endcode
+*/
Index: /code/branches/RacingBots_FS18/src/external/enet/enet.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/enet.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/enet.h	(revision 11817)
@@ -0,0 +1,576 @@
+/** 
+ @file  enet.h
+ @brief ENet public header file
+*/
+#ifndef __ENET_ENET_H__
+#define __ENET_ENET_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdlib.h>
+
+#ifdef WIN32
+#include "enet/win32.h"
+#else
+#include "enet/unix.h"
+#endif
+
+#include "enet/types.h"
+#include "enet/protocol.h"
+#include "enet/list.h"
+#include "enet/callbacks.h"
+
+#define ENET_VERSION_MAJOR 1
+#define ENET_VERSION_MINOR 3
+#define ENET_VERSION_PATCH 1
+#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
+#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH)
+
+typedef enet_uint32 ENetVersion;
+
+typedef enum _ENetSocketType
+{
+   ENET_SOCKET_TYPE_STREAM   = 1,
+   ENET_SOCKET_TYPE_DATAGRAM = 2
+} ENetSocketType;
+
+typedef enum _ENetSocketWait
+{
+   ENET_SOCKET_WAIT_NONE    = 0,
+   ENET_SOCKET_WAIT_SEND    = (1 << 0),
+   ENET_SOCKET_WAIT_RECEIVE = (1 << 1)
+} ENetSocketWait;
+
+typedef enum _ENetSocketOption
+{
+   ENET_SOCKOPT_NONBLOCK  = 1,
+   ENET_SOCKOPT_BROADCAST = 2,
+   ENET_SOCKOPT_RCVBUF    = 3,
+   ENET_SOCKOPT_SNDBUF    = 4,
+   ENET_SOCKOPT_REUSEADDR = 5
+} ENetSocketOption;
+
+typedef struct _ENetHostAddress
+{
+   enet_uint8 addr[16];
+} ENetHostAddress;
+
+#define ENET_HOST_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }                         /**< specifies the default server host (macro for variable initialization) */
+static const ENetHostAddress ENET_HOST_ANY = ENET_HOST_ANY_INIT;                           /**< specifies the default server host (global constant variable) */
+#define ENET_IPV4MAPPED_PREFIX_INIT { { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 } }          /**< specifies the IPv4-mapped IPv6 prefix (macro for variable initialization) */
+static const ENetHostAddress ENET_IPV4MAPPED_PREFIX = ENET_IPV4MAPPED_PREFIX_INIT;         /**< specifies the IPv4-mapped IPv6 prefix (global constant variable) */
+#define ENET_HOST_BROADCAST_INIT { { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff } } /**< specifies a IPv4 subnet-wide broadcast (macro for variable initialization) */
+static const ENetHostAddress ENET_HOST_BROADCAST = ENET_HOST_BROADCAST_INIT;               /**< specifies a IPv4 subnet-wide broadcast (global constant variable) */
+enum {
+    ENET_IPV4MAPPED_PREFIX_LEN = 12,                                                       /**< specifies the length of the IPv4-mapped IPv6 prefix */
+    ENET_PORT_ANY              = 0                                                         /**< specifies that a port should be automatically chosen */
+};
+
+/**
+ * Portable internet address structure. 
+ *
+ * The host must be specified in network byte-order, and the port must be in host 
+ * byte-order. The constant ENET_HOST_ANY may be used to specify the default 
+ * server host. The constant ENET_HOST_BROADCAST may be used to specify the
+ * broadcast address (255.255.255.255).  This makes sense for enet_host_connect,
+ * but not for enet_host_create.  Once a server responds to a broadcast, the
+ * address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
+ */
+typedef struct _ENetAddress
+{
+   ENetHostAddress host;
+#ifdef WIN32
+   u_long scopeID;
+#else
+   uint32_t scopeID;
+#endif
+   enet_uint16 port;
+} ENetAddress;
+
+/**
+ * The address family type.
+ */
+typedef enum _ENetAddressFamily
+{
+    ENET_NO_ADDRESS_FAMILY = 0,
+    ENET_IPV4 = (1 << 0),
+    ENET_IPV6 = (1 << 1)
+} ENetAddressFamily;
+
+/**
+ * Packet flag bit constants.
+ *
+ * The host must be specified in network byte-order, and the port must be in
+ * host byte-order. The constant ENET_HOST_ANY may be used to specify the
+ * default server host.
+ 
+   @sa ENetPacket
+*/
+typedef enum _ENetPacketFlag
+{
+   /** packet must be received by the target peer and resend attempts should be
+     * made until the packet is delivered */
+   ENET_PACKET_FLAG_RELIABLE    = (1 << 0),
+   /** packet will not be sequenced with other packets
+     * not supported for reliable packets
+     */
+   ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
+   /** packet will not allocate data, and user must supply it instead */
+   ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2)
+} ENetPacketFlag;
+
+struct _ENetPacket;
+typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
+
+/**
+ * ENet packet structure.
+ *
+ * An ENet data packet that may be sent to or received from a peer. The shown 
+ * fields should only be read and never modified. The data field contains the 
+ * allocated data for the packet. The dataLength fields specifies the length 
+ * of the allocated data.  The flags field is either 0 (specifying no flags), 
+ * or a bitwise-or of any combination of the following flags:
+ *
+ *    ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
+ *    and resend attempts should be made until the packet is delivered
+ *
+ *    ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets 
+ *    (not supported for reliable packets)
+ *
+ *    ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
+ 
+   @sa ENetPacketFlag
+ */
+typedef struct _ENetPacket
+{
+   size_t                   referenceCount;  /**< internal use only */
+   enet_uint32              flags;           /**< bitwise-or of ENetPacketFlag constants */
+   enet_uint8 *             data;            /**< allocated data for packet */
+   size_t                   dataLength;      /**< length of data */
+   ENetPacketFreeCallback   freeCallback;    /**< function to be called when the packet is no longer in use */
+} ENetPacket;
+
+typedef struct _ENetAcknowledgement
+{
+   ENetListNode acknowledgementList;
+   enet_uint32  sentTime;
+   ENetProtocol command;
+} ENetAcknowledgement;
+
+typedef struct _ENetOutgoingCommand
+{
+   ENetListNode outgoingCommandList;
+   enet_uint16  reliableSequenceNumber;
+   enet_uint16  unreliableSequenceNumber;
+   enet_uint32  sentTime;
+   enet_uint32  roundTripTimeout;
+   enet_uint32  roundTripTimeoutLimit;
+   enet_uint32  fragmentOffset;
+   enet_uint16  fragmentLength;
+   enet_uint16  sendAttempts;
+   ENetProtocol command;
+   ENetPacket * packet;
+} ENetOutgoingCommand;
+
+typedef struct _ENetIncomingCommand
+{  
+   ENetListNode     incomingCommandList;
+   enet_uint16      reliableSequenceNumber;
+   enet_uint16      unreliableSequenceNumber;
+   ENetProtocol     command;
+   enet_uint32      fragmentCount;
+   enet_uint32      fragmentsRemaining;
+   enet_uint32 *    fragments;
+   ENetPacket *     packet;
+} ENetIncomingCommand;
+
+typedef enum _ENetPeerState
+{
+   ENET_PEER_STATE_DISCONNECTED                = 0,
+   ENET_PEER_STATE_CONNECTING                  = 1,
+   ENET_PEER_STATE_ACKNOWLEDGING_CONNECT       = 2,
+   ENET_PEER_STATE_CONNECTION_PENDING          = 3,
+   ENET_PEER_STATE_CONNECTION_SUCCEEDED        = 4,
+   ENET_PEER_STATE_CONNECTED                   = 5,
+   ENET_PEER_STATE_DISCONNECT_LATER            = 6,
+   ENET_PEER_STATE_DISCONNECTING               = 7,
+   ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT    = 8,
+   ENET_PEER_STATE_ZOMBIE                      = 9 
+} ENetPeerState;
+
+#ifndef ENET_BUFFER_MAXIMUM
+#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
+#endif
+
+enum
+{
+   ENET_HOST_RECEIVE_BUFFER_SIZE          = 256 * 1024,
+   ENET_HOST_SEND_BUFFER_SIZE             = 256 * 1024,
+   ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL  = 1000,
+   ENET_HOST_DEFAULT_MTU                  = 1400,
+
+   ENET_PEER_DEFAULT_ROUND_TRIP_TIME      = 500,
+   ENET_PEER_DEFAULT_PACKET_THROTTLE      = 32,
+   ENET_PEER_PACKET_THROTTLE_SCALE        = 32,
+   ENET_PEER_PACKET_THROTTLE_COUNTER      = 7, 
+   ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
+   ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
+   ENET_PEER_PACKET_THROTTLE_INTERVAL     = 5000,
+   ENET_PEER_PACKET_LOSS_SCALE            = (1 << 16),
+   ENET_PEER_PACKET_LOSS_INTERVAL         = 10000,
+   ENET_PEER_WINDOW_SIZE_SCALE            = 64 * 1024,
+   ENET_PEER_TIMEOUT_LIMIT                = 32,
+   ENET_PEER_TIMEOUT_MINIMUM              = 5000,
+   ENET_PEER_TIMEOUT_MAXIMUM              = 30000,
+   ENET_PEER_PING_INTERVAL                = 500,
+   ENET_PEER_UNSEQUENCED_WINDOWS          = 64,
+   ENET_PEER_UNSEQUENCED_WINDOW_SIZE      = 1024,
+   ENET_PEER_FREE_UNSEQUENCED_WINDOWS     = 32,
+   ENET_PEER_RELIABLE_WINDOWS             = 16,
+   ENET_PEER_RELIABLE_WINDOW_SIZE         = 0x1000,
+   ENET_PEER_FREE_RELIABLE_WINDOWS        = 8
+};
+
+typedef struct _ENetChannel
+{
+   enet_uint16  outgoingReliableSequenceNumber;
+   enet_uint16  outgoingUnreliableSequenceNumber;
+   enet_uint16  usedReliableWindows;
+   enet_uint16  reliableWindows [ENET_PEER_RELIABLE_WINDOWS];
+   enet_uint16  incomingReliableSequenceNumber;
+   ENetList     incomingReliableCommands;
+   ENetList     incomingUnreliableCommands;
+} ENetChannel;
+
+/**
+ * An ENet peer which data packets may be sent or received from. 
+ *
+ * No fields should be modified unless otherwise specified. 
+ */
+typedef struct _ENetPeer
+{ 
+   ENetListNode  dispatchList;
+   struct _ENetHost * host;
+   enet_uint16   outgoingPeerID;
+   enet_uint16   incomingPeerID;
+   enet_uint32   connectID;
+   enet_uint8    outgoingSessionID;
+   enet_uint8    incomingSessionID;
+   ENetAddress   address;            /**< Internet address of the peer */
+   void *        data;               /**< Application private data, may be freely modified */
+   ENetPeerState state;
+   ENetChannel * channels;
+   size_t        channelCount;       /**< Number of channels allocated for communication with peer */
+   enet_uint32   incomingBandwidth;  /**< Downstream bandwidth of the client in bytes/second */
+   enet_uint32   outgoingBandwidth;  /**< Upstream bandwidth of the client in bytes/second */
+   enet_uint32   incomingBandwidthThrottleEpoch;
+   enet_uint32   outgoingBandwidthThrottleEpoch;
+   enet_uint32   incomingDataTotal;
+   enet_uint32   outgoingDataTotal;
+   enet_uint32   lastSendTime;
+   enet_uint32   lastReceiveTime;
+   enet_uint32   nextTimeout;
+   enet_uint32   earliestTimeout;
+   enet_uint32   packetLossEpoch;
+   enet_uint32   packetsSent;
+   enet_uint32   packetsLost;
+   enet_uint32   packetLoss;          /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
+   enet_uint32   packetLossVariance;
+   enet_uint32   packetThrottle;
+   enet_uint32   packetThrottleLimit;
+   enet_uint32   packetThrottleCounter;
+   enet_uint32   packetThrottleEpoch;
+   enet_uint32   packetThrottleAcceleration;
+   enet_uint32   packetThrottleDeceleration;
+   enet_uint32   packetThrottleInterval;
+   enet_uint32   lastRoundTripTime;
+   enet_uint32   lowestRoundTripTime;
+   enet_uint32   lastRoundTripTimeVariance;
+   enet_uint32   highestRoundTripTimeVariance;
+   enet_uint32   roundTripTime;            /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
+   enet_uint32   roundTripTimeVariance;
+   enet_uint32   mtu;
+   enet_uint32   windowSize;
+   enet_uint32   reliableDataInTransit;
+   enet_uint16   outgoingReliableSequenceNumber;
+   ENetList      acknowledgements;
+   ENetList      sentReliableCommands;
+   ENetList      sentUnreliableCommands;
+   ENetList      outgoingReliableCommands;
+   ENetList      outgoingUnreliableCommands;
+   ENetList      dispatchedCommands;
+   int           needsDispatch;
+   enet_uint16   incomingUnsequencedGroup;
+   enet_uint16   outgoingUnsequencedGroup;
+   enet_uint32   unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; 
+   enet_uint32   eventData;
+} ENetPeer;
+
+/** An ENet packet compressor for compressing UDP packets before socket sends or receives.
+ */
+typedef struct _ENetCompressor
+{
+   /** Context data for the compressor. Must be non-NULL. */
+   void * context;
+   /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
+   size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit);
+   /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
+   size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit);
+   /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */
+   void (ENET_CALLBACK * destroy) (void * context);
+} ENetCompressor;
+
+/** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */
+typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount);
+ 
+/** An ENet host for communicating with peers.
+  *
+  * No fields should be modified unless otherwise stated.
+
+    @sa enet_host_create()
+    @sa enet_host_destroy()
+    @sa enet_host_connect()
+    @sa enet_host_service()
+    @sa enet_host_flush()
+    @sa enet_host_broadcast()
+    @sa enet_host_compress()
+    @sa enet_host_compress_with_range_coder()
+    @sa enet_host_channel_limit()
+    @sa enet_host_bandwidth_limit()
+    @sa enet_host_bandwidth_throttle()
+  */
+typedef struct _ENetHost
+{
+   ENetSocket           socket4;
+   ENetSocket           socket6;
+   ENetAddress          address;                     /**< Internet address of the host */
+   enet_uint32          incomingBandwidth;           /**< downstream bandwidth of the host */
+   enet_uint32          outgoingBandwidth;           /**< upstream bandwidth of the host */
+   enet_uint32          bandwidthThrottleEpoch;
+   enet_uint32          mtu;
+   enet_uint32          randomSeed;
+   int                  recalculateBandwidthLimits;
+   ENetPeer *           peers;                       /**< array of peers allocated for this host */
+   size_t               peerCount;                   /**< number of peers allocated for this host */
+   size_t               channelLimit;                /**< maximum number of channels allowed for connected peers */
+   enet_uint32          serviceTime;
+   ENetList             dispatchQueue;
+   int                  continueSending;
+   size_t               packetSize;
+   enet_uint16          headerFlags;
+   ENetProtocol         commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
+   size_t               commandCount;
+   ENetBuffer           buffers [ENET_BUFFER_MAXIMUM];
+   size_t               bufferCount;
+   ENetChecksumCallback checksum;                    /**< callback the user can set to enable packet checksums for this host */
+   ENetCompressor       compressor;
+   enet_uint8           packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
+   ENetAddress          receivedAddress;
+   enet_uint8 *         receivedData;
+   size_t               receivedDataLength;
+   enet_uint32          totalSentData;               /**< total data sent, user should reset to 0 as needed to prevent overflow */
+   enet_uint32          totalSentPackets;            /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */
+   enet_uint32          totalReceivedData;           /**< total data received, user should reset to 0 as needed to prevent overflow */
+   enet_uint32          totalReceivedPackets;        /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
+} ENetHost;
+
+/**
+ * An ENet event type, as specified in @ref ENetEvent.
+ */
+typedef enum _ENetEventType
+{
+   /** no event occurred within the specified time limit */
+   ENET_EVENT_TYPE_NONE       = 0,  
+
+   /** a connection request initiated by enet_host_connect has completed.  
+     * The peer field contains the peer which successfully connected. 
+     */
+   ENET_EVENT_TYPE_CONNECT    = 1,  
+
+   /** a peer has disconnected.  This event is generated on a successful 
+     * completion of a disconnect initiated by enet_pper_disconnect, if 
+     * a peer has timed out, or if a connection request intialized by 
+     * enet_host_connect has timed out.  The peer field contains the peer 
+     * which disconnected. The data field contains user supplied data 
+     * describing the disconnection, or 0, if none is available.
+     */
+   ENET_EVENT_TYPE_DISCONNECT = 2,  
+
+   /** a packet has been received from a peer.  The peer field specifies the
+     * peer which sent the packet.  The channelID field specifies the channel
+     * number upon which the packet was received.  The packet field contains
+     * the packet that was received; this packet must be destroyed with
+     * enet_packet_destroy after use.
+     */
+   ENET_EVENT_TYPE_RECEIVE    = 3
+} ENetEventType;
+
+/**
+ * An ENet event as returned by enet_host_service().
+   
+   @sa enet_host_service
+ */
+typedef struct _ENetEvent 
+{
+   ENetEventType        type;      /**< type of the event */
+   ENetPeer *           peer;      /**< peer that generated a connect, disconnect or receive event */
+   enet_uint8           channelID; /**< channel on the peer that generated the event, if appropriate */
+   enet_uint32          data;      /**< data associated with the event, if appropriate */
+   ENetPacket *         packet;    /**< packet associated with the event, if appropriate */
+} ENetEvent;
+
+/** @defgroup global ENet global functions
+    @{ 
+*/
+
+/** 
+  Initializes ENet globally.  Must be called prior to using any functions in
+  ENet.
+  @returns 0 on success, < 0 on failure
+*/
+ENET_API int enet_initialize (void);
+
+/** 
+  Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored.
+
+  @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
+  @param inits user-overriden callbacks where any NULL callbacks will use ENet's defaults
+  @returns 0 on success, < 0 on failure
+*/
+ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
+
+/** 
+  Shuts down ENet globally.  Should be called when a program that has
+  initialized ENet exits.
+*/
+ENET_API void enet_deinitialize (void);
+
+/** @} */
+
+/** @defgroup private ENet private implementation functions */
+
+/**
+  Returns the wall-time in milliseconds.  Its initial value is unspecified
+  unless otherwise set.
+  */
+ENET_API enet_uint32 enet_time_get (void);
+/**
+  Sets the current wall-time in milliseconds.
+  */
+ENET_API void enet_time_set (enet_uint32);
+
+/** @defgroup socket ENet socket functions
+    @{
+*/
+ENET_API ENetSocket enet_socket_create (ENetSocketType, ENetAddressFamily);
+ENET_API int        enet_socket_bind (ENetSocket, const ENetAddress *, ENetAddressFamily);
+ENET_API int        enet_socket_listen (ENetSocket, int);
+ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *, ENetAddressFamily);
+ENET_API int        enet_socket_connect (ENetSocket, const ENetAddress *, ENetAddressFamily);
+ENET_API int        enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t, ENetAddressFamily);
+ENET_API int        enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t, ENetAddressFamily);
+ENET_API int        enet_socket_wait (ENetSocket, ENetSocket, enet_uint32 *, enet_uint32);
+ENET_API int        enet_socket_set_option (ENetSocket, ENetSocketOption, int);
+ENET_API void       enet_socket_destroy (ENetSocket);
+ENET_API int        enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
+
+/** @} */
+
+/** @defgroup Address ENet address functions
+    @{
+*/
+/** Attempts to resolve the host named by the parameter hostName and sets
+    the host field in the address parameter if successful.
+    @param address destination to store resolved address
+    @param hostName host name to lookup
+    @retval 0 on success
+    @retval < 0 on failure
+    @returns the address of the given hostName in address on success
+*/
+ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
+
+/** Gives the printable form of the ip address specified in the address parameter.
+    @param address    address printed
+    @param hostName   destination for name, must not be NULL
+    @param nameLength maximum length of hostName.
+    @returns the null-terminated name of the host in hostName on success
+    @retval 0 on success
+    @retval < 0 on failure
+*/
+ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
+
+/** Attempts to do a reverse lookup of the host field in the address parameter.
+    @param address    address used for reverse lookup
+    @param hostName   destination for name, must not be NULL
+    @param nameLength maximum length of hostName.
+    @returns the null-terminated name of the host in hostName on success
+    @retval 0 on success
+    @retval < 0 on failure
+*/
+ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
+
+/** Maps an IPv4 Address to an IPv6 address.
+    @param address IPv4 address in network byte order
+    @returns the IPv4-mapped IPv6 address in network byte order
+*/
+ENET_API ENetHostAddress enet_address_map4 (enet_uint32 address);
+
+/** Returns the Address family of an (IPv4-mapped) IPv6 address.
+    @param address IPv6 address
+    @returns address family
+*/
+ENET_API ENetAddressFamily enet_get_address_family (const ENetAddress * address);
+
+/** @} */
+
+ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
+ENET_API void         enet_packet_destroy (ENetPacket *);
+ENET_API int          enet_packet_resize  (ENetPacket *, size_t);
+extern enet_uint32    enet_crc32 (const ENetBuffer *, size_t);
+                
+ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
+ENET_API void       enet_host_destroy (ENetHost *);
+ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
+ENET_API int        enet_host_check_events (ENetHost *, ENetEvent *);
+ENET_API int        enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
+ENET_API void       enet_host_flush (ENetHost *);
+ENET_API void       enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
+ENET_API void       enet_host_compress (ENetHost *, const ENetCompressor *);
+ENET_API int        enet_host_compress_with_range_coder (ENetHost * host);
+ENET_API void       enet_host_channel_limit (ENetHost *, size_t);
+ENET_API void       enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
+extern   void       enet_host_bandwidth_throttle (ENetHost *);
+
+ENET_API int                 enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
+ENET_API ENetPacket *        enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
+ENET_API void                enet_peer_ping (ENetPeer *);
+ENET_API void                enet_peer_reset (ENetPeer *);
+ENET_API void                enet_peer_disconnect (ENetPeer *, enet_uint32);
+ENET_API void                enet_peer_disconnect_now (ENetPeer *, enet_uint32);
+ENET_API void                enet_peer_disconnect_later (ENetPeer *, enet_uint32);
+ENET_API void                enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
+extern int                   enet_peer_throttle (ENetPeer *, enet_uint32);
+extern void                  enet_peer_reset_queues (ENetPeer *);
+extern void                  enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
+extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
+extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32);
+extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
+extern void                  enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
+extern void                  enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
+
+ENET_API void * enet_range_coder_create (void);
+ENET_API void   enet_range_coder_destroy (void *);
+ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
+ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);
+   
+extern size_t enet_protocol_command_size (enet_uint8);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ENET_ENET_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/host.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/host.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/host.c	(revision 11817)
@@ -0,0 +1,508 @@
+/** 
+ @file host.c
+ @brief ENet host management functions
+*/
+#define ENET_BUILDING_LIB 1
+#include <string.h>
+#include <time.h>
+#include "enet/enet.h"
+
+static ENetSocket
+enet_socket_create_bind (const ENetAddress * address, ENetAddressFamily family)
+{
+    ENetSocket socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM, family);
+    if (socket == ENET_SOCKET_NULL)
+        return ENET_SOCKET_NULL;
+
+    /* This is not a conditional bind anymore,
+     * because WSARecvFrom returned WSAEINVAL on the IPv6 socket.
+     * TODO: Check for it's consequences. */
+    if (enet_socket_bind (socket, address, family) < 0)
+    {
+        enet_socket_destroy (socket);
+        return ENET_SOCKET_NULL;
+    }
+
+    enet_socket_set_option (socket, ENET_SOCKOPT_NONBLOCK, 1);
+    enet_socket_set_option (socket, ENET_SOCKOPT_BROADCAST, 1);
+    enet_socket_set_option (socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
+    enet_socket_set_option (socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
+
+    return socket;
+}
+
+/** @defgroup host ENet host functions
+    @{
+*/
+
+/** Creates a host for communicating to peers.  
+
+    @param address   the address at which other peers may connect to this host.  If NULL, then no peers may connect to the host.
+    @param peerCount the maximum number of peers that should be allocated for the host.
+    @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
+    @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
+    @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
+
+    @returns the host on success and NULL on failure
+
+    @remarks ENet will strategically drop packets on specific sides of a connection between hosts
+    to ensure the host's bandwidth is not overwhelmed.  The bandwidth parameters also determine
+    the window size of a connection which limits the amount of reliable packets that may be in transit
+    at any given time.
+*/
+ENetHost *
+enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
+{
+    ENetHost * host;
+    ENetPeer * currentPeer;
+    int family;
+
+    if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
+      return NULL;
+
+    host = (ENetHost *) enet_malloc (sizeof (ENetHost));
+    if (host == NULL)
+      return NULL;
+
+    host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
+    if (host -> peers == NULL)
+    {
+       enet_free (host);
+
+       return NULL;
+    }
+    memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
+
+    family = (address == NULL || !memcmp (& address -> host, & ENET_HOST_ANY, sizeof (ENetHostAddress))) ?
+        ENET_IPV4 | ENET_IPV6 :
+        enet_get_address_family (address);
+
+    host -> socket4 = (family & ENET_IPV4) ?
+      enet_socket_create_bind (address, ENET_IPV4) :
+      ENET_SOCKET_NULL;
+    host -> socket6 = (family & ENET_IPV6) ?
+      enet_socket_create_bind (address, ENET_IPV6) :
+      ENET_SOCKET_NULL;
+
+    if (host -> socket4 == ENET_SOCKET_NULL && host -> socket6 == ENET_SOCKET_NULL)
+    {
+        enet_free (host -> peers);
+        enet_free (host);
+        return NULL;
+    }
+
+    if (address != NULL)
+      host -> address = * address;
+
+    if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
+      channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
+    else
+    if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
+      channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
+
+    host -> randomSeed = (enet_uint32) time(NULL) + (enet_uint32) (size_t) host;
+    host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16);
+    host -> channelLimit = channelLimit;
+    host -> incomingBandwidth = incomingBandwidth;
+    host -> outgoingBandwidth = outgoingBandwidth;
+    host -> bandwidthThrottleEpoch = 0;
+    host -> recalculateBandwidthLimits = 0;
+    host -> mtu = ENET_HOST_DEFAULT_MTU;
+    host -> peerCount = peerCount;
+    host -> commandCount = 0;
+    host -> bufferCount = 0;
+    host -> checksum = NULL;
+    host -> receivedAddress.host = ENET_HOST_ANY;
+    host -> receivedAddress.port = 0;
+    host -> receivedData = NULL;
+    host -> receivedDataLength = 0;
+     
+    host -> totalSentData = 0;
+    host -> totalSentPackets = 0;
+    host -> totalReceivedData = 0;
+    host -> totalReceivedPackets = 0;
+
+    host -> compressor.context = NULL;
+    host -> compressor.compress = NULL;
+    host -> compressor.decompress = NULL;
+    host -> compressor.destroy = NULL;
+
+    enet_list_clear (& host -> dispatchQueue);
+
+    for (currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+       currentPeer -> host = host;
+       currentPeer -> incomingPeerID = currentPeer - host -> peers;
+       currentPeer -> outgoingSessionID = currentPeer -> incomingSessionID = 0xFF;
+       currentPeer -> data = NULL;
+
+       enet_list_clear (& currentPeer -> acknowledgements);
+       enet_list_clear (& currentPeer -> sentReliableCommands);
+       enet_list_clear (& currentPeer -> sentUnreliableCommands);
+       enet_list_clear (& currentPeer -> outgoingReliableCommands);
+       enet_list_clear (& currentPeer -> outgoingUnreliableCommands);
+       enet_list_clear (& currentPeer -> dispatchedCommands);
+
+       enet_peer_reset (currentPeer);
+    }
+
+    return host;
+}
+
+/** Destroys the host and all resources associated with it.
+    @param host pointer to the host to destroy
+*/
+void
+enet_host_destroy (ENetHost * host)
+{
+    ENetPeer * currentPeer;
+
+    if (host -> socket4 != ENET_SOCKET_NULL)
+      enet_socket_destroy (host -> socket4);
+    if (host -> socket6 != ENET_SOCKET_NULL)
+      enet_socket_destroy (host -> socket6);
+
+    for (currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+       enet_peer_reset (currentPeer);
+    }
+
+    if (host -> compressor.context != NULL && host -> compressor.destroy)
+      (* host -> compressor.destroy) (host -> compressor.context);
+
+    enet_free (host -> peers);
+    enet_free (host);
+}
+
+/** Initiates a connection to a foreign host.
+    @param host host seeking the connection
+    @param address destination for the connection
+    @param channelCount number of channels to allocate
+    @param data user data supplied to the receiving host 
+    @returns a peer representing the foreign host on success, NULL on failure
+    @remarks The peer returned will have not completed the connection until enet_host_service()
+    notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
+*/
+ENetPeer *
+enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount, enet_uint32 data)
+{
+    ENetPeer * currentPeer;
+    ENetChannel * channel;
+    ENetProtocol command;
+
+    if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
+      channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
+    else
+    if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
+      channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
+
+    for (currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+       if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
+         break;
+    }
+
+    if (currentPeer >= & host -> peers [host -> peerCount])
+      return NULL;
+
+    currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
+    if (currentPeer -> channels == NULL)
+      return NULL;
+    currentPeer -> channelCount = channelCount;
+    currentPeer -> state = ENET_PEER_STATE_CONNECTING;
+    currentPeer -> address = * address;
+    currentPeer -> connectID = ++ host -> randomSeed;
+
+    if (host -> outgoingBandwidth == 0)
+      currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+    else
+      currentPeer -> windowSize = (host -> outgoingBandwidth /
+                                    ENET_PEER_WINDOW_SIZE_SCALE) * 
+                                      ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+
+    if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
+      currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+    else
+    if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
+      currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+         
+    for (channel = currentPeer -> channels;
+         channel < & currentPeer -> channels [channelCount];
+         ++ channel)
+    {
+        channel -> outgoingReliableSequenceNumber = 0;
+        channel -> outgoingUnreliableSequenceNumber = 0;
+        channel -> incomingReliableSequenceNumber = 0;
+
+        enet_list_clear (& channel -> incomingReliableCommands);
+        enet_list_clear (& channel -> incomingUnreliableCommands);
+
+        channel -> usedReliableWindows = 0;
+        memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
+    }
+        
+    command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+    command.header.channelID = 0xFF;
+    command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
+    command.connect.incomingSessionID = currentPeer -> incomingSessionID;
+    command.connect.outgoingSessionID = currentPeer -> outgoingSessionID;
+    command.connect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu);
+    command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
+    command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
+    command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
+    command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
+    command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
+    command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
+    command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
+    command.connect.connectID = currentPeer -> connectID;
+    command.connect.data = ENET_HOST_TO_NET_32 (data);
+ 
+    enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
+
+    return currentPeer;
+}
+
+/** Queues a packet to be sent to all peers associated with the host.
+    @param host host on which to broadcast the packet
+    @param channelID channel on which to broadcast
+    @param packet packet to broadcast
+*/
+void
+enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
+{
+    ENetPeer * currentPeer;
+
+    for (currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+       if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
+         continue;
+
+       enet_peer_send (currentPeer, channelID, packet);
+    }
+
+    if (packet -> referenceCount == 0)
+      enet_packet_destroy (packet);
+}
+
+/** Sets the packet compressor the host should use to compress and decompress packets.
+    @param host host to enable or disable compression for
+    @param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
+*/
+void
+enet_host_compress (ENetHost * host, const ENetCompressor * compressor)
+{
+    if (host -> compressor.context != NULL && host -> compressor.destroy)
+      (* host -> compressor.destroy) (host -> compressor.context);
+
+    if (compressor)
+      host -> compressor = * compressor;
+    else
+      host -> compressor.context = NULL;
+}
+
+/** Limits the maximum allowed channels of future incoming connections.
+    @param host host to limit
+    @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
+*/
+void
+enet_host_channel_limit (ENetHost * host, size_t channelLimit)
+{
+    if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
+      channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
+    else
+    if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
+      channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
+
+    host -> channelLimit = channelLimit;
+}
+
+
+/** Adjusts the bandwidth limits of a host.
+    @param host host to adjust
+    @param incomingBandwidth new incoming bandwidth
+    @param outgoingBandwidth new outgoing bandwidth
+    @remarks the incoming and outgoing bandwidth parameters are identical in function to those
+    specified in enet_host_create().
+*/
+void
+enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
+{
+    host -> incomingBandwidth = incomingBandwidth;
+    host -> outgoingBandwidth = outgoingBandwidth;
+    host -> recalculateBandwidthLimits = 1;
+}
+
+void
+enet_host_bandwidth_throttle (ENetHost * host)
+{
+    enet_uint32 timeCurrent = enet_time_get (),
+           elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
+           peersTotal = 0,
+           dataTotal = 0,
+           peersRemaining,
+           bandwidth,
+           throttle = 0,
+           bandwidthLimit = 0;
+    int needsAdjustment;
+    ENetPeer * peer;
+    ENetProtocol command;
+
+    if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
+      return;
+
+    for (peer = host -> peers;
+         peer < & host -> peers [host -> peerCount];
+         ++ peer)
+    {
+        if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
+          continue;
+
+        ++ peersTotal;
+        dataTotal += peer -> outgoingDataTotal;
+    }
+
+    if (peersTotal == 0)
+      return;
+
+    peersRemaining = peersTotal;
+    needsAdjustment = 1;
+
+    if (host -> outgoingBandwidth == 0)
+      bandwidth = ~0;
+    else
+      bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
+
+    while (peersRemaining > 0 && needsAdjustment != 0)
+    {
+        needsAdjustment = 0;
+        
+        if (dataTotal < bandwidth)
+          throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
+        else
+          throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
+
+        for (peer = host -> peers;
+             peer < & host -> peers [host -> peerCount];
+             ++ peer)
+        {
+            enet_uint32 peerBandwidth;
+            
+            if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
+                peer -> incomingBandwidth == 0 ||
+                peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
+              continue;
+
+            peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
+            if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
+              continue;
+
+            peer -> packetThrottleLimit = (peerBandwidth * 
+                                            ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
+            
+            if (peer -> packetThrottleLimit == 0)
+              peer -> packetThrottleLimit = 1;
+            
+            if (peer -> packetThrottle > peer -> packetThrottleLimit)
+              peer -> packetThrottle = peer -> packetThrottleLimit;
+
+            peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
+
+            
+            needsAdjustment = 1;
+            -- peersRemaining;
+            bandwidth -= peerBandwidth;
+            dataTotal -= peerBandwidth;
+        }
+    }
+
+    if (peersRemaining > 0)
+    for (peer = host -> peers;
+         peer < & host -> peers [host -> peerCount];
+         ++ peer)
+    {
+        if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
+            peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
+          continue;
+
+        peer -> packetThrottleLimit = throttle;
+
+        if (peer -> packetThrottle > peer -> packetThrottleLimit)
+          peer -> packetThrottle = peer -> packetThrottleLimit;
+    }
+    
+    if (host -> recalculateBandwidthLimits)
+    {
+       host -> recalculateBandwidthLimits = 0;
+
+       peersRemaining = peersTotal;
+       bandwidth = host -> incomingBandwidth;
+       needsAdjustment = 1;
+
+       if (bandwidth == 0)
+         bandwidthLimit = 0;
+       else
+       while (peersRemaining > 0 && needsAdjustment != 0)
+       {
+           needsAdjustment = 0;
+           bandwidthLimit = bandwidth / peersRemaining;
+
+           for (peer = host -> peers;
+                peer < & host -> peers [host -> peerCount];
+                ++ peer)
+           {
+               if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
+                   peer -> incomingBandwidthThrottleEpoch == timeCurrent)
+                 continue;
+
+               if (peer -> outgoingBandwidth > 0 &&
+                   peer -> outgoingBandwidth >= bandwidthLimit)
+                 continue;
+
+               peer -> incomingBandwidthThrottleEpoch = timeCurrent;
+ 
+               needsAdjustment = 1;
+               -- peersRemaining;
+               bandwidth -= peer -> outgoingBandwidth;
+           }
+       }
+
+       for (peer = host -> peers;
+            peer < & host -> peers [host -> peerCount];
+            ++ peer)
+       {
+           if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
+             continue;
+
+           command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+           command.header.channelID = 0xFF;
+           command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
+
+           if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
+             command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
+           else
+             command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
+
+           enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
+       } 
+    }
+
+    host -> bandwidthThrottleEpoch = timeCurrent;
+
+    for (peer = host -> peers;
+         peer < & host -> peers [host -> peerCount];
+         ++ peer)
+    {
+        peer -> incomingDataTotal = 0;
+        peer -> outgoingDataTotal = 0;
+    }
+}
+    
+/** @} */
Index: /code/branches/RacingBots_FS18/src/external/enet/libenet.pc.in
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/libenet.pc.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/libenet.pc.in	(revision 11817)
@@ -0,0 +1,10 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE_NAME@
+Description: Low-latency UDP networking library supporting optional reliability
+Version: @PACKAGE_VERSION@
+Cflags: -I${includedir}
+Libs: -L${libdir} -lenet
Index: /code/branches/RacingBots_FS18/src/external/enet/list.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/list.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/list.c	(revision 11817)
@@ -0,0 +1,75 @@
+/** 
+ @file list.c
+ @brief ENet linked list functions
+*/
+#define ENET_BUILDING_LIB 1
+#include "enet/enet.h"
+
+/** 
+    @defgroup list ENet linked list utility functions
+    @ingroup private
+    @{
+*/
+void
+enet_list_clear (ENetList * list)
+{
+   list -> sentinel.next = & list -> sentinel;
+   list -> sentinel.previous = & list -> sentinel;
+}
+
+ENetListIterator
+enet_list_insert (ENetListIterator position, void * data)
+{
+   ENetListIterator result = (ENetListIterator) data;
+
+   result -> previous = position -> previous;
+   result -> next = position;
+
+   result -> previous -> next = result;
+   position -> previous = result;
+
+   return result;
+}
+
+void *
+enet_list_remove (ENetListIterator position)
+{
+   position -> previous -> next = position -> next;
+   position -> next -> previous = position -> previous;
+
+   return position;
+}
+
+ENetListIterator
+enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast)
+{
+   ENetListIterator first = (ENetListIterator) dataFirst,
+                    last = (ENetListIterator) dataLast;
+
+   first -> previous -> next = last -> next;
+   last -> next -> previous = first -> previous;
+
+   first -> previous = position -> previous;
+   last -> next = position;
+
+   first -> previous -> next = first;
+   position -> previous = last;
+    
+   return first;
+}
+
+size_t
+enet_list_size (ENetList * list)
+{
+   size_t size = 0;
+   ENetListIterator position;
+
+   for (position = enet_list_begin (list);
+        position != enet_list_end (list);
+        position = enet_list_next (position))
+     ++ size;
+   
+   return size;
+}
+
+/** @} */
Index: /code/branches/RacingBots_FS18/src/external/enet/list.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/list.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/list.h	(revision 11817)
@@ -0,0 +1,43 @@
+/** 
+ @file  list.h
+ @brief ENet list management 
+*/
+#ifndef __ENET_LIST_H__
+#define __ENET_LIST_H__
+
+#include <stdlib.h>
+
+typedef struct _ENetListNode
+{
+   struct _ENetListNode * next;
+   struct _ENetListNode * previous;
+} ENetListNode;
+
+typedef ENetListNode * ENetListIterator;
+
+typedef struct _ENetList
+{
+   ENetListNode sentinel;
+} ENetList;
+
+extern void enet_list_clear (ENetList *);
+
+extern ENetListIterator enet_list_insert (ENetListIterator, void *);
+extern void * enet_list_remove (ENetListIterator);
+extern ENetListIterator enet_list_move (ENetListIterator, void *, void *);
+
+extern size_t enet_list_size (ENetList *);
+
+#define enet_list_begin(list) ((list) -> sentinel.next)
+#define enet_list_end(list) (& (list) -> sentinel)
+
+#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
+
+#define enet_list_next(iterator) ((iterator) -> next)
+#define enet_list_previous(iterator) ((iterator) -> previous)
+
+#define enet_list_front(list) ((void *) (list) -> sentinel.next)
+#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
+
+#endif /* __ENET_LIST_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/packet.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/packet.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/packet.c	(revision 11817)
@@ -0,0 +1,157 @@
+/** 
+ @file  packet.c
+ @brief ENet packet management functions
+*/
+#include <string.h>
+#define ENET_BUILDING_LIB 1
+#include "enet/enet.h"
+
+/** @defgroup Packet ENet packet functions 
+    @{ 
+*/
+
+/** Creates a packet that may be sent to a peer.
+    @param dataContents initial contents of the packet's data; the packet's data will remain uninitialized if dataContents is NULL.
+    @param dataLength   size of the data allocated for this packet
+    @param flags        flags for this packet as described for the ENetPacket structure.
+    @returns the packet on success, NULL on failure
+*/
+ENetPacket *
+enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags)
+{
+    ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket));
+    if (packet == NULL)
+      return NULL;
+
+    if (flags & ENET_PACKET_FLAG_NO_ALLOCATE)
+      packet -> data = (enet_uint8 *) data;
+    else
+    {
+       packet -> data = (enet_uint8 *) enet_malloc (dataLength);
+       if (packet -> data == NULL)
+       {
+          enet_free (packet);
+          return NULL;
+       }
+
+       if (data != NULL)
+         memcpy (packet -> data, data, dataLength);
+    }
+
+    packet -> referenceCount = 0;
+    packet -> flags = flags;
+    packet -> dataLength = dataLength;
+    packet -> freeCallback = NULL;
+
+    return packet;
+}
+
+/** Destroys the packet and deallocates its data.
+    @param packet packet to be destroyed
+*/
+void
+enet_packet_destroy (ENetPacket * packet)
+{
+    if (packet -> freeCallback != NULL)
+      (* packet -> freeCallback) (packet);
+    if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
+      enet_free (packet -> data);
+    enet_free (packet);
+}
+
+/** Attempts to resize the data in the packet to length specified in the 
+    dataLength parameter 
+    @param packet packet to resize
+    @param dataLength new size for the packet data
+    @returns 0 on success, < 0 on failure
+*/
+int
+enet_packet_resize (ENetPacket * packet, size_t dataLength)
+{
+    enet_uint8 * newData;
+   
+    if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
+    {
+       packet -> dataLength = dataLength;
+
+       return 0;
+    }
+
+    newData = (enet_uint8 *) enet_malloc (dataLength);
+    if (newData == NULL)
+      return -1;
+
+    memcpy (newData, packet -> data, packet -> dataLength);
+    enet_free (packet -> data);
+    
+    packet -> data = newData;
+    packet -> dataLength = dataLength;
+
+    return 0;
+}
+
+static int initializedCRC32 = 0;
+static enet_uint32 crcTable [256];
+
+static enet_uint32 
+reflect_crc (int val, int bits)
+{
+    int result = 0, bit;
+
+    for (bit = 0; bit < bits; bit ++)
+    {
+        if(val & 1) result |= 1 << (bits - 1 - bit); 
+        val >>= 1;
+    }
+
+    return result;
+}
+
+static void 
+initialize_crc32 ()
+{
+    int byte;
+
+    for (byte = 0; byte < 256; ++ byte)
+    {
+        enet_uint32 crc = reflect_crc (byte, 8) << 24;
+        int offset;
+
+        for(offset = 0; offset < 8; ++ offset)
+        {
+            if (crc & 0x80000000)
+                crc = (crc << 1) ^ 0x04c11db7;
+            else
+                crc <<= 1;
+        }
+
+        crcTable [byte] = reflect_crc (crc, 32);
+    }
+
+    initializedCRC32 = 1;
+}
+    
+enet_uint32
+enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
+{
+    enet_uint32 crc = 0xFFFFFFFF;
+    
+    if (! initializedCRC32) initialize_crc32 ();
+
+    while (bufferCount -- > 0)
+    {
+        const enet_uint8 * data = (const enet_uint8 *) buffers -> data,
+                         * dataEnd = & data [buffers -> dataLength];
+
+        while (data < dataEnd)
+        {
+            crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];        
+        }
+
+        ++ buffers;
+    }
+
+    return ENET_HOST_TO_NET_32 (~ crc);
+}
+
+/** @} */
Index: /code/branches/RacingBots_FS18/src/external/enet/patches/0001-Add-IPv6-support-to-Enet.patch
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/patches/0001-Add-IPv6-support-to-Enet.patch	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/patches/0001-Add-IPv6-support-to-Enet.patch	(revision 11817)
@@ -0,0 +1,1307 @@
+From 7a7274dad3f90d206e91c0712ea0d2599850b24e Mon Sep 17 00:00:00 2001
+From: Adrian Friedli <adi@koalatux.ch>
+Date: Thu, 2 Sep 2010 14:26:42 +0200
+Subject: [PATCH] Add IPv6 support to Enet
+
+---
+ host.c               |   57 +++++++---
+ include/enet/enet.h  |   64 ++++++++---
+ include/enet/win32.h |    4 +
+ protocol.c           |   73 ++++++++++--
+ unix.c               |  312 ++++++++++++++++++++++++++++++--------------------
+ win32.c              |  247 ++++++++++++++++++++++++++--------------
+ 6 files changed, 507 insertions(+), 250 deletions(-)
+ mode change 100755 => 100644 Doxyfile
+ mode change 100755 => 100644 docs/FAQ.dox
+ mode change 100755 => 100644 docs/design.dox
+ mode change 100755 => 100644 docs/install.dox
+ mode change 100755 => 100644 docs/license.dox
+ mode change 100755 => 100644 docs/mainpage.dox
+ mode change 100755 => 100644 docs/tutorial.dox
+ mode change 100755 => 100644 enet.dsp
+
+diff --git a/Doxyfile b/Doxyfile
+old mode 100755
+new mode 100644
+diff --git a/docs/FAQ.dox b/docs/FAQ.dox
+old mode 100755
+new mode 100644
+diff --git a/docs/design.dox b/docs/design.dox
+old mode 100755
+new mode 100644
+diff --git a/docs/install.dox b/docs/install.dox
+old mode 100755
+new mode 100644
+diff --git a/docs/license.dox b/docs/license.dox
+old mode 100755
+new mode 100644
+diff --git a/docs/mainpage.dox b/docs/mainpage.dox
+old mode 100755
+new mode 100644
+diff --git a/docs/tutorial.dox b/docs/tutorial.dox
+old mode 100755
+new mode 100644
+diff --git a/enet.dsp b/enet.dsp
+old mode 100755
+new mode 100644
+diff --git a/host.c b/host.c
+index 8bb2433..a9d157b 100644
+--- a/host.c
++++ b/host.c
+@@ -7,6 +7,30 @@
+ #include <time.h>
+ #include "enet/enet.h"
+ 
++static ENetSocket
++enet_socket_create_bind (const ENetAddress * address, ENetAddressFamily family)
++{
++    ENetSocket socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM, family);
++    if (socket == ENET_SOCKET_NULL)
++        return ENET_SOCKET_NULL;
++
++    /* This is not a conditional bind anymore,
++     * because WSARecvFrom returned WSAEINVAL on the IPv6 socket.
++     * TODO: Check for it's consequences. */
++    if (enet_socket_bind (socket, address, family) < 0)
++    {
++        enet_socket_destroy (socket);
++        return ENET_SOCKET_NULL;
++    }
++
++    enet_socket_set_option (socket, ENET_SOCKOPT_NONBLOCK, 1);
++    enet_socket_set_option (socket, ENET_SOCKOPT_BROADCAST, 1);
++    enet_socket_set_option (socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
++    enet_socket_set_option (socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
++
++    return socket;
++}
++
+ /** @defgroup host ENet host functions
+     @{
+ */
+@@ -31,6 +55,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
+ {
+     ENetHost * host;
+     ENetPeer * currentPeer;
++    int family;
+ 
+     if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
+       return NULL;
+@@ -48,23 +73,24 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
+     }
+     memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
+ 
+-    host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
+-    if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
+-    {
+-       if (host -> socket != ENET_SOCKET_NULL)
+-         enet_socket_destroy (host -> socket);
++    family = (address == NULL || !memcmp (& address -> host, & ENET_HOST_ANY, sizeof (ENetHostAddress))) ?
++        ENET_IPV4 | ENET_IPV6 :
++        enet_get_address_family (address);
+ 
+-       enet_free (host -> peers);
+-       enet_free (host);
++    host -> socket4 = (family & ENET_IPV4) ?
++      enet_socket_create_bind (address, ENET_IPV4) :
++      ENET_SOCKET_NULL;
++    host -> socket6 = (family & ENET_IPV6) ?
++      enet_socket_create_bind (address, ENET_IPV6) :
++      ENET_SOCKET_NULL;
+ 
+-       return NULL;
++    if (host -> socket4 == ENET_SOCKET_NULL && host -> socket6 == ENET_SOCKET_NULL)
++    {
++        enet_free (host -> peers);
++        enet_free (host);
++        return NULL;
+     }
+ 
+-    enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
+-    enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
+-    enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
+-    enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
+-
+     if (address != NULL)
+       host -> address = * address;
+ 
+@@ -133,7 +159,10 @@ enet_host_destroy (ENetHost * host)
+ {
+     ENetPeer * currentPeer;
+ 
+-    enet_socket_destroy (host -> socket);
++    if (host -> socket4 != ENET_SOCKET_NULL)
++      enet_socket_destroy (host -> socket4);
++    if (host -> socket6 != ENET_SOCKET_NULL)
++      enet_socket_destroy (host -> socket6);
+ 
+     for (currentPeer = host -> peers;
+          currentPeer < & host -> peers [host -> peerCount];
+diff --git a/include/enet/enet.h b/include/enet/enet.h
+index b572590..8351166 100644
+--- a/include/enet/enet.h
++++ b/include/enet/enet.h
+@@ -53,12 +53,20 @@ typedef enum _ENetSocketOption
+    ENET_SOCKOPT_REUSEADDR = 5
+ } ENetSocketOption;
+ 
+-enum
++typedef struct _ENetHostAddress
+ {
+-   ENET_HOST_ANY       = 0,            /**< specifies the default server host */
+-   ENET_HOST_BROADCAST = 0xFFFFFFFF,   /**< specifies a subnet-wide broadcast */
+-
+-   ENET_PORT_ANY       = 0             /**< specifies that a port should be automatically chosen */
++   enet_uint8 addr[16];
++} ENetHostAddress;
++
++#define ENET_HOST_ANY_INIT { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } }                         /**< specifies the default server host (macro for variable initialization) */
++static const ENetHostAddress ENET_HOST_ANY = ENET_HOST_ANY_INIT;                           /**< specifies the default server host (global constant variable) */
++#define ENET_IPV4MAPPED_PREFIX_INIT { { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 } }          /**< specifies the IPv4-mapped IPv6 prefix (macro for variable initialization) */
++static const ENetHostAddress ENET_IPV4MAPPED_PREFIX = ENET_IPV4MAPPED_PREFIX_INIT;         /**< specifies the IPv4-mapped IPv6 prefix (global constant variable) */
++#define ENET_HOST_BROADCAST_INIT { { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff } } /**< specifies a IPv4 subnet-wide broadcast (macro for variable initialization) */
++static const ENetHostAddress ENET_HOST_BROADCAST = ENET_HOST_BROADCAST_INIT;               /**< specifies a IPv4 subnet-wide broadcast (global constant variable) */
++enum {
++    ENET_IPV4MAPPED_PREFIX_LEN = 12,                                                       /**< specifies the length of the IPv4-mapped IPv6 prefix */
++    ENET_PORT_ANY              = 0                                                         /**< specifies that a port should be automatically chosen */
+ };
+ 
+ /**
+@@ -73,11 +81,26 @@ enum
+  */
+ typedef struct _ENetAddress
+ {
+-   enet_uint32 host;
++   ENetHostAddress host;
++#ifdef WIN32
++   u_long scopeID;
++#else
++   uint32_t scopeID;
++#endif
+    enet_uint16 port;
+ } ENetAddress;
+ 
+ /**
++ * The address family type.
++ */
++typedef enum _ENetAddressFamily
++{
++    ENET_NO_ADDRESS_FAMILY = 0,
++    ENET_IPV4 = (1 << 0),
++    ENET_IPV6 = (1 << 1)
++} ENetAddressFamily;
++
++/**
+  * Packet flag bit constants.
+  *
+  * The host must be specified in network byte-order, and the port must be in
+@@ -321,7 +344,8 @@ typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * b
+   */
+ typedef struct _ENetHost
+ {
+-   ENetSocket           socket;
++   ENetSocket           socket4;
++   ENetSocket           socket6;
+    ENetAddress          address;                     /**< Internet address of the host */
+    enet_uint32          incomingBandwidth;           /**< downstream bandwidth of the host */
+    enet_uint32          outgoingBandwidth;           /**< upstream bandwidth of the host */
+@@ -441,14 +465,14 @@ ENET_API void enet_time_set (enet_uint32);
+ /** @defgroup socket ENet socket functions
+     @{
+ */
+-ENET_API ENetSocket enet_socket_create (ENetSocketType);
+-ENET_API int        enet_socket_bind (ENetSocket, const ENetAddress *);
++ENET_API ENetSocket enet_socket_create (ENetSocketType, ENetAddressFamily);
++ENET_API int        enet_socket_bind (ENetSocket, const ENetAddress *, ENetAddressFamily);
+ ENET_API int        enet_socket_listen (ENetSocket, int);
+-ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
+-ENET_API int        enet_socket_connect (ENetSocket, const ENetAddress *);
+-ENET_API int        enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
+-ENET_API int        enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
+-ENET_API int        enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
++ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *, ENetAddressFamily);
++ENET_API int        enet_socket_connect (ENetSocket, const ENetAddress *, ENetAddressFamily);
++ENET_API int        enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t, ENetAddressFamily);
++ENET_API int        enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t, ENetAddressFamily);
++ENET_API int        enet_socket_wait (ENetSocket, ENetSocket, enet_uint32 *, enet_uint32);
+ ENET_API int        enet_socket_set_option (ENetSocket, ENetSocketOption, int);
+ ENET_API void       enet_socket_destroy (ENetSocket);
+ ENET_API int        enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
+@@ -488,6 +512,18 @@ ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostN
+ */
+ ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
+ 
++/** Maps an IPv4 Address to an IPv6 address.
++    @param address IPv4 address in network byte order
++    @returns the IPv4-mapped IPv6 address in network byte order
++*/
++ENET_API ENetHostAddress enet_address_map4 (enet_uint32 address);
++
++/** Returns the Address family of an (IPv4-mapped) IPv6 address.
++    @param address IPv6 address
++    @returns address family
++*/
++ENET_API ENetAddressFamily enet_get_address_family (const ENetAddress * address);
++
+ /** @} */
+ 
+ ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
+diff --git a/include/enet/win32.h b/include/enet/win32.h
+index 0e1cf0c..6145851 100644
+--- a/include/enet/win32.h
++++ b/include/enet/win32.h
+@@ -53,6 +53,10 @@ typedef fd_set ENetSocketSet;
+ #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset))
+ #define ENET_SOCKETSET_CHECK(sockset, socket)  FD_ISSET (socket, & (sockset))
+ 
++#ifndef AI_ADDRCONFIG
++#define AI_ADDRCONFIG 0x0400 /* AI_ADDRCONFIG is not defined everywhere */
++#endif
++
+ #endif /* __ENET_WIN32_H__ */
+ 
+ 
+diff --git a/protocol.c b/protocol.c
+index 2237ba8..7205d1b 100644
+--- a/protocol.c
++++ b/protocol.c
+@@ -25,6 +25,22 @@ static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
+     sizeof (ENetProtocolThrottleConfigure),
+ };
+ 
++ENetHostAddress
++enet_address_map4 (enet_uint32 address)
++{
++    ENetHostAddress addr = ENET_IPV4MAPPED_PREFIX_INIT;
++    ((enet_uint32 *)addr.addr)[3] = address;
++    return addr;
++}
++
++ENetAddressFamily
++enet_get_address_family (const ENetAddress * address)
++{
++    if (!memcmp(& address->host, & ENET_IPV4MAPPED_PREFIX, ENET_IPV4MAPPED_PREFIX_LEN))
++        return ENET_IPV4;
++    return ENET_IPV6;
++}
++
+ size_t
+ enet_protocol_command_size (enet_uint8 commandNumber)
+ {
+@@ -266,9 +282,9 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
+          ++ currentPeer)
+     {
+         if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
+-            currentPeer -> address.host == host -> receivedAddress.host &&
+             currentPeer -> address.port == host -> receivedAddress.port &&
+-            currentPeer -> connectID == command -> connect.connectID)
++            currentPeer -> connectID == command -> connect.connectID &&
++            !memcmp(& currentPeer -> address.host, & host -> receivedAddress.host, sizeof (ENetHostAddress)))
+           return NULL;
+     }
+ 
+@@ -852,10 +868,11 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+ 
+        if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
+            peer -> state == ENET_PEER_STATE_ZOMBIE ||
+-           (host -> receivedAddress.host != peer -> address.host &&
+-             peer -> address.host != ENET_HOST_BROADCAST) ||
+            (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
+-            sessionID != peer -> incomingSessionID))
++            sessionID != peer -> incomingSessionID) ||
++           ( memcmp(& peer -> address.host, & host -> receivedAddress.host, sizeof (ENetHostAddress)) &&
++             memcmp(& peer -> address.host, & ENET_HOST_BROADCAST, sizeof (ENetHostAddress)) &&
++             peer -> address.host.addr[0] != 0xff ) )
+          return 0;
+     }
+  
+@@ -895,8 +912,7 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+        
+     if (peer != NULL)
+     {
+-       peer -> address.host = host -> receivedAddress.host;
+-       peer -> address.port = host -> receivedAddress.port;
++       peer -> address = host -> receivedAddress;
+        peer -> incomingDataTotal += host -> receivedDataLength;
+     }
+     
+@@ -1025,7 +1041,7 @@ commandError:
+ }
+  
+ static int
+-enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
++enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event, ENetAddressFamily family)
+ {
+     for (;;)
+     {
+@@ -1035,10 +1051,11 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
+        buffer.data = host -> packetData [0];
+        buffer.dataLength = sizeof (host -> packetData [0]);
+ 
+-       receivedLength = enet_socket_receive (host -> socket,
++       receivedLength = enet_socket_receive (family == ENET_IPV4 ? host -> socket4 : host -> socket6,
+                                              & host -> receivedAddress,
+                                              & buffer,
+-                                             1);
++                                             1,
++                                             family);
+ 
+        if (receivedLength < 0)
+          return -1;
+@@ -1046,6 +1063,9 @@ enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
+        if (receivedLength == 0)
+          return 0;
+ 
++       if (enet_get_address_family (& host -> receivedAddress) != family)
++         return -1;
++
+        host -> receivedData = host -> packetData [0];
+        host -> receivedDataLength = receivedLength;
+       
+@@ -1397,6 +1417,9 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
+          currentPeer < & host -> peers [host -> peerCount];
+          ++ currentPeer)
+     {
++        ENetAddressFamily family;
++        ENetSocket socket;
++
+         if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
+             currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
+           continue;
+@@ -1520,7 +1543,15 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
+ 
+         currentPeer -> lastSendTime = host -> serviceTime;
+ 
+-        sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
++        family = enet_get_address_family (& currentPeer -> address);
++        socket = family == ENET_IPV4 ? host -> socket4 : host -> socket6;
++        if (socket == ENET_SOCKET_NULL)
++          return -1;
++        sentLength = enet_socket_send (socket,
++                                           & currentPeer -> address,
++                                           host -> buffers,
++                                           host -> bufferCount,
++                                           family);
+ 
+         enet_protocol_remove_sent_unreliable_commands (currentPeer);
+ 
+@@ -1631,7 +1662,23 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
+           break;
+        }
+ 
+-       switch (enet_protocol_receive_incoming_commands (host, event))
++       if (host -> socket4 != ENET_SOCKET_NULL)
++         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV4))
++       {
++       case 1:
++          return 1;
++
++       case -1:
++          perror ("Error receiving incoming packets");
++
++          return -1;
++
++       default:
++          break;
++       }
++
++       if (host -> socket6 != ENET_SOCKET_NULL)
++         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV6))
+        {
+        case 1:
+           return 1;
+@@ -1683,7 +1730,7 @@ enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
+ 
+        waitCondition = ENET_SOCKET_WAIT_RECEIVE;
+ 
+-       if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
++       if (enet_socket_wait (host -> socket4, host -> socket6, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
+          return -1;
+        
+        host -> serviceTime = enet_time_get ();
+diff --git a/unix.c b/unix.c
+index 6971541..992ecd3 100644
+--- a/unix.c
++++ b/unix.c
+@@ -71,122 +71,161 @@ enet_time_set (enet_uint32 newTimeBase)
+     timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
+ }
+ 
+-int
+-enet_address_set_host (ENetAddress * address, const char * name)
++static enet_uint16
++enet_af (ENetAddressFamily family)
+ {
+-    struct hostent * hostEntry = NULL;
+-#ifdef HAS_GETHOSTBYNAME_R
+-    struct hostent hostData;
+-    char buffer [2048];
+-    int errnum;
+-
+-#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+-    gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
+-#else
+-    hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
+-#endif
+-#else
+-    hostEntry = gethostbyname (name);
+-#endif
++    if (family == ENET_IPV4)
++        return AF_INET;
++    if (family == ENET_IPV6)
++        return AF_INET6;
++    return 0;
++}
++
++static socklen_t
++enet_sa_size (ENetAddressFamily family)
++{
++    if (family == ENET_IPV4)
++        return sizeof (struct sockaddr_in);
++    if (family == ENET_IPV6)
++        return sizeof (struct sockaddr_in6);
++    return 0;
++}
+ 
+-    if (hostEntry == NULL ||
+-        hostEntry -> h_addrtype != AF_INET)
++static ENetAddressFamily
++enet_address_set_address (ENetAddress * address, const struct sockaddr * sin)
++{
++    memset (address, 0, sizeof (ENetAddress));
++    if (sin -> sa_family == AF_INET)
+     {
+-#ifdef HAS_INET_PTON
+-        if (! inet_pton (AF_INET, name, & address -> host))
+-#else
+-        if (! inet_aton (name, (struct in_addr *) & address -> host))
+-#endif
+-            return -1;
+-        return 0;
++        address -> host = enet_address_map4 ((((struct sockaddr_in *) sin) -> sin_addr.s_addr));
++        /* address -> scopeID = 0; */
++        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in *) sin) -> sin_port);
++        return ENET_IPV4;
+     }
+-
+-    address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
+-
+-    return 0;
++    if (sin -> sa_family == AF_INET6)
++    {
++        address -> host = * (ENetHostAddress *) & ((struct sockaddr_in6 *) sin) -> sin6_addr;
++        address -> scopeID = ((struct sockaddr_in6 *) sin) -> sin6_scope_id;
++        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in6 *) sin) -> sin6_port);
++        return ENET_IPV6;
++    }
++    return ENET_NO_ADDRESS_FAMILY;
+ }
+ 
+-int
+-enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
++static int
++enet_address_set_sin (struct sockaddr * sin, const ENetAddress * address, ENetAddressFamily family)
+ {
+-#ifdef HAS_INET_NTOP
+-    if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
+-#else
+-    char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
+-    if (addr != NULL)
+-        strncpy (name, addr, nameLength);
+-    else
+-#endif
+-        return -1;
+-    return 0;
++    memset (sin, 0, enet_sa_size(family));
++    if (family == ENET_IPV4 &&
++      (enet_get_address_family (address) == ENET_IPV4 ||
++      !memcmp (& address -> host, & ENET_HOST_ANY, sizeof(ENetHostAddress))))
++    {
++        ((struct sockaddr_in *) sin) -> sin_family = AF_INET;
++        ((struct sockaddr_in *) sin) -> sin_addr = * (struct in_addr *) & address -> host.addr[12];
++        ((struct sockaddr_in *) sin) -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
++        return 0;
++    }
++    else if (family == ENET_IPV6)
++    {
++        ((struct sockaddr_in6 *) sin) -> sin6_family = AF_INET6;
++        ((struct sockaddr_in6 *) sin) -> sin6_addr = * (struct in6_addr *) & address -> host;
++        ((struct sockaddr_in6 *) sin) -> sin6_scope_id = address -> scopeID;
++        ((struct sockaddr_in6 *) sin) -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
++        return 0;
++    }
++    return -1;
+ }
+ 
+ int
+-enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
++enet_address_set_host (ENetAddress * address, const char * name)
+ {
+-    struct in_addr in;
+-    struct hostent * hostEntry = NULL;
+-#ifdef HAS_GETHOSTBYADDR_R
+-    struct hostent hostData;
+-    char buffer [2048];
+-    int errnum;
++    enet_uint16 port = address -> port;
++    struct addrinfo hints;
++    struct addrinfo * result;
++    struct addrinfo * res;
+ 
+-    in.s_addr = address -> host;
++    memset(& hints, 0, sizeof (hints));
++    hints.ai_flags = AI_ADDRCONFIG;
++    hints.ai_family = AF_UNSPEC;
+ 
+-#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+-    gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
+-#else
+-    hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
+-#endif
+-#else
+-    in.s_addr = address -> host;
++    if ( getaddrinfo(name, NULL, &hints, &result) )
++        return -1;
+ 
+-    hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
+-#endif
++    for (res = result; res != NULL; res = res -> ai_next)
++    {
++        if ( enet_address_set_address(address, res -> ai_addr) != ENET_NO_ADDRESS_FAMILY )
++            break;
++    }
+ 
+-    if (hostEntry == NULL)
+-      return enet_address_get_host_ip (address, name, nameLength);
++    address -> port = port;
++    freeaddrinfo(result);
++    if (res == NULL) return -1;
+ 
+-    strncpy (name, hostEntry -> h_name, nameLength);
++    return 0;
++}
++
++static int
++enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags)
++{
++    struct sockaddr_storage sin;
++    enet_address_set_sin((struct sockaddr *) & sin, address, ENET_IPV6);
++
++    if ( getnameinfo((struct sockaddr *) & sin, enet_sa_size (ENET_IPV6), name, nameLength, NULL, 0, flags))
++        return -1;
+ 
+     return 0;
+ }
+ 
+ int
+-enet_socket_bind (ENetSocket socket, const ENetAddress * address)
++enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
+ {
+-    struct sockaddr_in sin;
++    return enet_address_get_host_x(address, name, nameLength, NI_NUMERICHOST);
++}
+ 
+-    memset (& sin, 0, sizeof (struct sockaddr_in));
++int
++enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
++{
++    return enet_address_get_host_x(address, name, nameLength, 0);
++}
+ 
+-    sin.sin_family = AF_INET;
++int
++enet_socket_bind (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
++{
++    struct sockaddr_storage sin;
+ 
+     if (address != NULL)
+     {
+-       sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
+-       sin.sin_addr.s_addr = address -> host;
++        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+     }
+     else
+     {
+-       sin.sin_port = 0;
+-       sin.sin_addr.s_addr = INADDR_ANY;
++        ENetAddress address_ = { ENET_HOST_ANY_INIT, 0, 0 };
++        enet_address_set_sin((struct sockaddr *) & sin, & address_, family);
+     }
+ 
+-    return bind (socket,
+-                 (struct sockaddr *) & sin,
+-                 sizeof (struct sockaddr_in)); 
++    return bind (socket, (struct sockaddr *) & sin, enet_sa_size(family));
+ }
+ 
+-int 
++int
+ enet_socket_listen (ENetSocket socket, int backlog)
+ {
+     return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
+ }
+ 
+ ENetSocket
+-enet_socket_create (ENetSocketType type)
++enet_socket_create (ENetSocketType type, ENetAddressFamily family)
+ {
+-    return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
++    ENetSocket sock = socket (enet_af (family), type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
++
++#ifdef IPV6_V6ONLY
++    if (family == ENET_IPV6)
++    {
++        int value = 1;
++        setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, & value, sizeof (int));
++    }
++#endif /* IPV6_V6ONLY */
++
++    return sock;
+ }
+ 
+ int
+@@ -226,42 +265,36 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
+ }
+ 
+ int
+-enet_socket_connect (ENetSocket socket, const ENetAddress * address)
++enet_socket_connect (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
+ {
+-    struct sockaddr_in sin;
+-
+-    memset (& sin, 0, sizeof (struct sockaddr_in));
++    struct sockaddr_storage sin;
++    enet_address_set_sin((struct sockaddr *) & sin, address, family);
+ 
+-    sin.sin_family = AF_INET;
+-    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
+-    sin.sin_addr.s_addr = address -> host;
+-
+-    return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
++    return connect (socket, (struct sockaddr *) & sin, enet_sa_size (family));
+ }
+ 
+ ENetSocket
+-enet_socket_accept (ENetSocket socket, ENetAddress * address)
++enet_socket_accept (ENetSocket socket, ENetAddress * address, ENetAddressFamily family)
+ {
+     int result;
+-    struct sockaddr_in sin;
+-    socklen_t sinLength = sizeof (struct sockaddr_in);
++    struct sockaddr_storage sin;
++    socklen_t sinLength = enet_sa_size (family);
+ 
+     result = accept (socket, 
+-                     address != NULL ? (struct sockaddr *) & sin : NULL, 
++                     address != NULL ? (struct sockaddr *) & sin : NULL,
+                      address != NULL ? & sinLength : NULL);
+-    
++
+     if (result == -1)
+       return ENET_SOCKET_NULL;
+ 
+     if (address != NULL)
+     {
+-        address -> host = (enet_uint32) sin.sin_addr.s_addr;
+-        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
++        enet_address_set_address(address, (struct sockaddr *) & sin);
+     }
+ 
+     return result;
+-} 
+-    
++}
++
+ void
+ enet_socket_destroy (ENetSocket socket)
+ {
+@@ -272,24 +305,20 @@ int
+ enet_socket_send (ENetSocket socket,
+                   const ENetAddress * address,
+                   const ENetBuffer * buffers,
+-                  size_t bufferCount)
++                  size_t bufferCount,
++                  ENetAddressFamily family)
+ {
+     struct msghdr msgHdr;
+-    struct sockaddr_in sin;
++    struct sockaddr_storage sin;
+     int sentLength;
+ 
+     memset (& msgHdr, 0, sizeof (struct msghdr));
+ 
+     if (address != NULL)
+     {
+-        memset (& sin, 0, sizeof (struct sockaddr_in));
+-
+-        sin.sin_family = AF_INET;
+-        sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
+-        sin.sin_addr.s_addr = address -> host;
+-
++        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+         msgHdr.msg_name = & sin;
+-        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
++        msgHdr.msg_namelen = enet_sa_size (family);
+     }
+ 
+     msgHdr.msg_iov = (struct iovec *) buffers;
+@@ -312,10 +341,11 @@ int
+ enet_socket_receive (ENetSocket socket,
+                      ENetAddress * address,
+                      ENetBuffer * buffers,
+-                     size_t bufferCount)
++                     size_t bufferCount,
++                     ENetAddressFamily family)
+ {
+     struct msghdr msgHdr;
+-    struct sockaddr_in sin;
++    struct sockaddr_storage sin;
+     int recvLength;
+ 
+     memset (& msgHdr, 0, sizeof (struct msghdr));
+@@ -323,7 +353,7 @@ enet_socket_receive (ENetSocket socket,
+     if (address != NULL)
+     {
+         msgHdr.msg_name = & sin;
+-        msgHdr.msg_namelen = sizeof (struct sockaddr_in);
++        msgHdr.msg_namelen = enet_sa_size (family);
+     }
+ 
+     msgHdr.msg_iov = (struct iovec *) buffers;
+@@ -346,8 +376,7 @@ enet_socket_receive (ENetSocket socket,
+ 
+     if (address != NULL)
+     {
+-        address -> host = (enet_uint32) sin.sin_addr.s_addr;
+-        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
++        enet_address_set_address(address, (struct sockaddr *) & sin);
+     }
+ 
+     return recvLength;
+@@ -365,22 +394,38 @@ enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocket
+ }
+ 
+ int
+-enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
++enet_socket_wait (ENetSocket socket4, ENetSocket socket6, enet_uint32 * condition, enet_uint32 timeout)
+ {
+ #ifdef HAS_POLL
+-    struct pollfd pollSocket;
++    struct pollfd pollSocket[2];
+     int pollCount;
+-    
+-    pollSocket.fd = socket;
+-    pollSocket.events = 0;
++
++    pollSocket[0].fd = socket4;
++    pollSocket[1].fd = socket6;
++    pollSocket[0].events = 0;
++    pollSocket[1].events = 0;
++    /* pollSocket[0].revents = 0; */
++    pollSocket[1].revents = 0;
++
++    if (pollSocket[0].fd == ENET_SOCKET_NULL)
++    {
++        pollSocket[0].fd = pollSocket[1].fd;
++        pollSocket[1].fd = ENET_SOCKET_NULL;
++    }
+ 
+     if (* condition & ENET_SOCKET_WAIT_SEND)
+-      pollSocket.events |= POLLOUT;
++    {
++        pollSocket[0].events |= POLLOUT;
++        pollSocket[1].events |= POLLOUT;
++    }
+ 
+     if (* condition & ENET_SOCKET_WAIT_RECEIVE)
+-      pollSocket.events |= POLLIN;
++    {
++        pollSocket[0].events |= POLLIN;
++        pollSocket[1].events |= POLLIN;
++    }
+ 
+-    pollCount = poll (& pollSocket, 1, timeout);
++    pollCount = poll (pollSocket, pollSocket[1].fd != ENET_SOCKET_NULL ? 2 : 1, timeout);
+ 
+     if (pollCount < 0)
+       return -1;
+@@ -390,10 +435,10 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
+     if (pollCount == 0)
+       return 0;
+ 
+-    if (pollSocket.revents & POLLOUT)
++    if ((pollSocket[0].revents | pollSocket[1].revents) & POLLOUT)
+       * condition |= ENET_SOCKET_WAIT_SEND;
+     
+-    if (pollSocket.revents & POLLIN)
++    if ((pollSocket[0].revents | pollSocket[1].revents) & POLLIN)
+       * condition |= ENET_SOCKET_WAIT_RECEIVE;
+ 
+     return 0;
+@@ -401,6 +446,7 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
+     fd_set readSet, writeSet;
+     struct timeval timeVal;
+     int selectCount;
++    ENetSocket maxSocket;
+ 
+     timeVal.tv_sec = timeout / 1000;
+     timeVal.tv_usec = (timeout % 1000) * 1000;
+@@ -409,12 +455,28 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
+     FD_ZERO (& writeSet);
+ 
+     if (* condition & ENET_SOCKET_WAIT_SEND)
+-      FD_SET (socket, & writeSet);
++    {
++        if (socket4 != ENET_SOCKET_NULL)
++            FD_SET (socket4, & writeSet);
++        if (socket6 != ENET_SOCKET_NULL)
++            FD_SET (socket6, & writeSet);
++    }
+ 
+     if (* condition & ENET_SOCKET_WAIT_RECEIVE)
+-      FD_SET (socket, & readSet);
++    {
++        if (socket4 != ENET_SOCKET_NULL)
++            FD_SET (socket4, & readSet);
++        if (socket6 != ENET_SOCKET_NULL)
++            FD_SET (socket6, & readSet);
++    }
++
++    maxSocket = 0;
++    if (socket4 != ENET_SOCKET_NULL)
++        maxSocket = socket4;
++    if (socket6 != ENET_SOCKET_NULL && socket6 > maxSocket)
++        maxSocket = socket6;
+ 
+-    selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
++    selectCount = select (maxSocket + 1, & readSet, & writeSet, NULL, & timeVal);
+ 
+     if (selectCount < 0)
+       return -1;
+@@ -424,11 +486,13 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
+     if (selectCount == 0)
+       return 0;
+ 
+-    if (FD_ISSET (socket, & writeSet))
+-      * condition |= ENET_SOCKET_WAIT_SEND;
++    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & writeSet)) ||
++        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & writeSet)) )
++        * condition |= ENET_SOCKET_WAIT_SEND;
+ 
+-    if (FD_ISSET (socket, & readSet))
+-      * condition |= ENET_SOCKET_WAIT_RECEIVE;
++    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & readSet)) ||
++        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & readSet)) )
++        * condition |= ENET_SOCKET_WAIT_RECEIVE;
+ 
+     return 0;
+ #endif
+diff --git a/win32.c b/win32.c
+index e1fae23..15b9888 100644
+--- a/win32.c
++++ b/win32.c
+@@ -4,23 +4,27 @@
+ */
+ #ifdef WIN32
+ 
++#define _WIN32_WINNT 0x0501
++
+ #include <time.h>
++
+ #define ENET_BUILDING_LIB 1
+ #include "enet/enet.h"
++#include <ws2tcpip.h>
+ 
+ static enet_uint32 timeBase = 0;
+ 
+ int
+ enet_initialize (void)
+ {
+-    WORD versionRequested = MAKEWORD (1, 1);
++    WORD versionRequested = MAKEWORD (2, 2);
+     WSADATA wsaData;
+    
+     if (WSAStartup (versionRequested, & wsaData))
+        return -1;
+ 
+-    if (LOBYTE (wsaData.wVersion) != 1||
+-        HIBYTE (wsaData.wVersion) != 1)
++    if (LOBYTE (wsaData.wVersion) != 2||
++        HIBYTE (wsaData.wVersion) != 2)
+     {
+        WSACleanup ();
+        
+@@ -52,77 +56,139 @@ enet_time_set (enet_uint32 newTimeBase)
+     timeBase = (enet_uint32) timeGetTime () - newTimeBase;
+ }
+ 
+-int
+-enet_address_set_host (ENetAddress * address, const char * name)
++static enet_uint16
++enet_af (ENetAddressFamily family)
+ {
+-    struct hostent * hostEntry;
++    if (family == ENET_IPV4)
++        return AF_INET;
++    if (family == ENET_IPV6)
++        return AF_INET6;
++    return 0;
++}
+ 
+-    hostEntry = gethostbyname (name);
+-    if (hostEntry == NULL ||
+-        hostEntry -> h_addrtype != AF_INET)
++static socklen_t
++enet_sa_size (ENetAddressFamily family)
++{
++    if (family == ENET_IPV4)
++        return sizeof (struct sockaddr_in);
++    if (family == ENET_IPV6)
++        return sizeof (struct sockaddr_in6);
++    return 0;
++}
++
++static ENetAddressFamily
++enet_address_set_address (ENetAddress * address, const struct sockaddr * sin)
++{
++    memset (address, 0, sizeof (ENetAddress));
++    if (sin -> sa_family == AF_INET)
+     {
+-        unsigned long host = inet_addr (name);
+-        if (host == INADDR_NONE)
+-            return -1;
+-        address -> host = host;
+-        return 0;
++        address -> host = enet_address_map4 ((((struct sockaddr_in *) sin) -> sin_addr.s_addr));
++        /* address -> scopeID = 0; */
++        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in *) sin) -> sin_port);
++        return ENET_IPV4;
+     }
++    if (sin -> sa_family == AF_INET6)
++    {
++        address -> host = * (ENetHostAddress *) & ((struct sockaddr_in6 *) sin) -> sin6_addr;
++        address -> scopeID = ((struct sockaddr_in6 *) sin) -> sin6_scope_id;
++        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in6 *) sin) -> sin6_port);
++        return ENET_IPV6;
++    }
++    return ENET_NO_ADDRESS_FAMILY;
++}
+ 
+-    address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
+-
+-    return 0;
++static int
++enet_address_set_sin (struct sockaddr * sin, const ENetAddress * address, ENetAddressFamily family)
++{
++    memset (sin, 0, enet_sa_size(family));
++    if (family == ENET_IPV4 &&
++      (enet_get_address_family (address) == ENET_IPV4 ||
++      !memcmp (& address -> host, & ENET_HOST_ANY, sizeof(ENetHostAddress))))
++    {
++        ((struct sockaddr_in *) sin) -> sin_family = AF_INET;
++        ((struct sockaddr_in *) sin) -> sin_addr = * (struct in_addr *) & address -> host.addr[12];
++        ((struct sockaddr_in *) sin) -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
++        return 0;
++    }
++    else if (family == ENET_IPV6)
++    {
++        ((struct sockaddr_in6 *) sin) -> sin6_family = AF_INET6;
++        ((struct sockaddr_in6 *) sin) -> sin6_addr = * (struct in6_addr *) & address -> host;
++        ((struct sockaddr_in6 *) sin) -> sin6_scope_id = address -> scopeID;
++        ((struct sockaddr_in6 *) sin) -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
++        return 0;
++    }
++    return -1;
+ }
+ 
+ int
+-enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
++enet_address_set_host (ENetAddress * address, const char * name)
+ {
+-    char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
+-    if (addr == NULL)
++    enet_uint16 port = address -> port;
++    struct addrinfo hints;
++    struct addrinfo * result;
++    struct addrinfo * res;
++
++    memset(& hints, 0, sizeof (hints));
++    hints.ai_flags = AI_ADDRCONFIG;
++    hints.ai_family = AF_UNSPEC;
++
++    if ( getaddrinfo(name, NULL, &hints, &result) )
+         return -1;
+-    strncpy (name, addr, nameLength);
++
++    for (res = result; res != NULL; res = res -> ai_next)
++    {
++        if ( enet_address_set_address(address, res -> ai_addr) != ENET_NO_ADDRESS_FAMILY )
++            break;
++    }
++
++    address -> port = port;
++    freeaddrinfo(result);
++    if (res == NULL) return -1;
++
+     return 0;
+ }
+ 
+-int
+-enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
++static int
++enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags)
+ {
+-    struct in_addr in;
+-    struct hostent * hostEntry;
+-    
+-    in.s_addr = address -> host;
+-    
+-    hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
+-    if (hostEntry == NULL)
+-      return enet_address_get_host_ip (address, name, nameLength);
++    struct sockaddr_storage sin;
++    enet_address_set_sin((struct sockaddr *) & sin, address, ENET_IPV6);
+ 
+-    strncpy (name, hostEntry -> h_name, nameLength);
++    if ( getnameinfo((struct sockaddr *) & sin, enet_sa_size (ENET_IPV6), name, nameLength, NULL, 0, flags))
++        return -1;
+ 
+     return 0;
+ }
+ 
+ int
+-enet_socket_bind (ENetSocket socket, const ENetAddress * address)
++enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
+ {
+-    struct sockaddr_in sin;
++    return enet_address_get_host_x(address, name, nameLength, NI_NUMERICHOST);
++}
+ 
+-    memset (& sin, 0, sizeof (struct sockaddr_in));
++int
++enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
++{
++    return enet_address_get_host_x(address, name, nameLength, 0);
++}
+ 
+-    sin.sin_family = AF_INET;
++int
++enet_socket_bind (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
++{
++    struct sockaddr_storage sin;
+ 
+     if (address != NULL)
+     {
+-       sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
+-       sin.sin_addr.s_addr = address -> host;
++        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+     }
+     else
+     {
+-       sin.sin_port = 0;
+-       sin.sin_addr.s_addr = INADDR_ANY;
++        ENetAddress address_ = { ENET_HOST_ANY_INIT, 0, 0 };
++        enet_address_set_sin((struct sockaddr *) & sin, & address_, family);
+     }
+ 
+-    return bind (socket,
+-                 (struct sockaddr *) & sin,
+-                 sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
++    return bind (socket, (struct sockaddr *) & sin, enet_sa_size(family)) == SOCKET_ERROR ? -1 : 0;
+ }
+ 
+ int
+@@ -132,9 +198,10 @@ enet_socket_listen (ENetSocket socket, int backlog)
+ }
+ 
+ ENetSocket
+-enet_socket_create (ENetSocketType type)
++enet_socket_create (ENetSocketType type, ENetAddressFamily family)
+ {
+-    return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
++    ENetSocket sock = socket (enet_af (family), type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
++    return sock;
+ }
+ 
+ int
+@@ -173,28 +240,23 @@ enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
+ }
+ 
+ int
+-enet_socket_connect (ENetSocket socket, const ENetAddress * address)
++enet_socket_connect (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
+ {
+-    struct sockaddr_in sin;
+-
+-    memset (& sin, 0, sizeof (struct sockaddr_in));
++    struct sockaddr_storage sin;
++    enet_address_set_sin((struct sockaddr *) & sin, address, family);
+ 
+-    sin.sin_family = AF_INET;
+-    sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
+-    sin.sin_addr.s_addr = address -> host;
+-
+-    return connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
++    return connect (socket, (struct sockaddr *) & sin, enet_sa_size (family)) == SOCKET_ERROR ? -1 : 0;
+ }
+ 
+ ENetSocket
+-enet_socket_accept (ENetSocket socket, ENetAddress * address)
++enet_socket_accept (ENetSocket socket, ENetAddress * address, ENetAddressFamily family)
+ {
+     SOCKET result;
+-    struct sockaddr_in sin;
+-    int sinLength = sizeof (struct sockaddr_in);
++    struct sockaddr_storage sin;
++    socklen_t sinLength = enet_sa_size (family);
+ 
+     result = accept (socket, 
+-                     address != NULL ? (struct sockaddr *) & sin : NULL, 
++                     address != NULL ? (struct sockaddr *) & sin : NULL,
+                      address != NULL ? & sinLength : NULL);
+ 
+     if (result == INVALID_SOCKET)
+@@ -202,8 +264,7 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address)
+ 
+     if (address != NULL)
+     {
+-        address -> host = (enet_uint32) sin.sin_addr.s_addr;
+-        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
++        enet_address_set_address(address, (struct sockaddr *) & sin);
+     }
+ 
+     return result;
+@@ -219,18 +280,15 @@ int
+ enet_socket_send (ENetSocket socket,
+                   const ENetAddress * address,
+                   const ENetBuffer * buffers,
+-                  size_t bufferCount)
++                  size_t bufferCount,
++                  ENetAddressFamily family)
+ {
+-    struct sockaddr_in sin;
++    struct sockaddr_storage sin;
+     DWORD sentLength;
+ 
+     if (address != NULL)
+     {
+-        memset (& sin, 0, sizeof (struct sockaddr_in));
+-
+-        sin.sin_family = AF_INET;
+-        sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
+-        sin.sin_addr.s_addr = address -> host;
++        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+     }
+ 
+     if (WSASendTo (socket, 
+@@ -239,7 +297,7 @@ enet_socket_send (ENetSocket socket,
+                    & sentLength,
+                    0,
+                    address != NULL ? (struct sockaddr *) & sin : 0,
+-                   address != NULL ? sizeof (struct sockaddr_in) : 0,
++                   address != NULL ? enet_sa_size (family) : 0,
+                    NULL,
+                    NULL) == SOCKET_ERROR)
+     {
+@@ -256,12 +314,13 @@ int
+ enet_socket_receive (ENetSocket socket,
+                      ENetAddress * address,
+                      ENetBuffer * buffers,
+-                     size_t bufferCount)
++                     size_t bufferCount,
++                     ENetAddressFamily family)
+ {
+-    INT sinLength = sizeof (struct sockaddr_in);
++    INT sinLength = enet_sa_size (family);
+     DWORD flags = 0,
+           recvLength;
+-    struct sockaddr_in sin;
++    struct sockaddr_storage sin;
+ 
+     if (WSARecvFrom (socket,
+                      (LPWSABUF) buffers,
+@@ -288,8 +347,7 @@ enet_socket_receive (ENetSocket socket,
+ 
+     if (address != NULL)
+     {
+-        address -> host = (enet_uint32) sin.sin_addr.s_addr;
+-        address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
++        enet_address_set_address(address, (struct sockaddr *) & sin);
+     }
+ 
+     return (int) recvLength;
+@@ -307,25 +365,42 @@ enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocket
+ }
+ 
+ int
+-enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
++enet_socket_wait (ENetSocket socket4, ENetSocket socket6, enet_uint32 * condition, enet_uint32 timeout)
+ {
+     fd_set readSet, writeSet;
+     struct timeval timeVal;
+     int selectCount;
+-    
++    ENetSocket maxSocket;
++
+     timeVal.tv_sec = timeout / 1000;
+     timeVal.tv_usec = (timeout % 1000) * 1000;
+-    
++
+     FD_ZERO (& readSet);
+     FD_ZERO (& writeSet);
+ 
+     if (* condition & ENET_SOCKET_WAIT_SEND)
+-      FD_SET (socket, & writeSet);
++    {
++        if (socket4 != ENET_SOCKET_NULL)
++            FD_SET (socket4, & writeSet);
++        if (socket6 != ENET_SOCKET_NULL)
++            FD_SET (socket6, & writeSet);
++    }
+ 
+     if (* condition & ENET_SOCKET_WAIT_RECEIVE)
+-      FD_SET (socket, & readSet);
++    {
++        if (socket4 != ENET_SOCKET_NULL)
++            FD_SET (socket4, & readSet);
++        if (socket6 != ENET_SOCKET_NULL)
++            FD_SET (socket6, & readSet);
++    }
+ 
+-    selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
++    maxSocket = 0;
++    if (socket4 != ENET_SOCKET_NULL)
++        maxSocket = socket4;
++    if (socket6 != ENET_SOCKET_NULL && socket6 > maxSocket)
++        maxSocket = socket6;
++
++    selectCount = select (maxSocket + 1, & readSet, & writeSet, NULL, & timeVal);
+ 
+     if (selectCount < 0)
+       return -1;
+@@ -335,14 +410,16 @@ enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeou
+     if (selectCount == 0)
+       return 0;
+ 
+-    if (FD_ISSET (socket, & writeSet))
+-      * condition |= ENET_SOCKET_WAIT_SEND;
+-    
+-    if (FD_ISSET (socket, & readSet))
+-      * condition |= ENET_SOCKET_WAIT_RECEIVE;
++    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & writeSet)) ||
++        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & writeSet)) )
++        * condition |= ENET_SOCKET_WAIT_SEND;
++
++    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & readSet)) ||
++        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & readSet)) )
++        * condition |= ENET_SOCKET_WAIT_RECEIVE;
+ 
+     return 0;
+-} 
++}
+ 
+ #endif
+ 
+-- 
+1.7.4.1
+
Index: /code/branches/RacingBots_FS18/src/external/enet/peer.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/peer.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/peer.c	(revision 11817)
@@ -0,0 +1,818 @@
+/** 
+ @file  peer.c
+ @brief ENet peer management functions
+*/
+#include <string.h>
+#define ENET_BUILDING_LIB 1
+#include "enet/enet.h"
+
+/** @defgroup peer ENet peer functions 
+    @{
+*/
+
+/** Configures throttle parameter for a peer.
+
+    Unreliable packets are dropped by ENet in response to the varying conditions
+    of the Internet connection to the peer.  The throttle represents a probability
+    that an unreliable packet should not be dropped and thus sent by ENet to the peer.
+    The lowest mean round trip time from the sending of a reliable packet to the
+    receipt of its acknowledgement is measured over an amount of time specified by
+    the interval parameter in milliseconds.  If a measured round trip time happens to
+    be significantly less than the mean round trip time measured over the interval, 
+    then the throttle probability is increased to allow more traffic by an amount
+    specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
+    constant.  If a measured round trip time happens to be significantly greater than
+    the mean round trip time measured over the interval, then the throttle probability
+    is decreased to limit traffic by an amount specified in the deceleration parameter, which
+    is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant.  When the throttle has
+    a value of ENET_PEER_PACKET_THROTTLE_SCALE, on unreliable packets are dropped by 
+    ENet, and so 100% of all unreliable packets will be sent.  When the throttle has a
+    value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
+    packets will be sent.  Intermediate values for the throttle represent intermediate
+    probabilities between 0% and 100% of unreliable packets being sent.  The bandwidth
+    limits of the local and foreign hosts are taken into account to determine a 
+    sensible limit for the throttle probability above which it should not raise even in
+    the best of conditions.
+
+    @param peer peer to configure 
+    @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
+    @param acceleration rate at which to increase the throttle probability as mean RTT declines
+    @param deceleration rate at which to decrease the throttle probability as mean RTT increases
+*/
+void
+enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
+{
+    ENetProtocol command;
+
+    peer -> packetThrottleInterval = interval;
+    peer -> packetThrottleAcceleration = acceleration;
+    peer -> packetThrottleDeceleration = deceleration;
+
+    command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+    command.header.channelID = 0xFF;
+
+    command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
+    command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
+    command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
+
+    enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
+}
+
+int
+enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
+{
+    if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
+    {
+        peer -> packetThrottle = peer -> packetThrottleLimit;
+    }
+    else
+    if (rtt < peer -> lastRoundTripTime)
+    {
+        peer -> packetThrottle += peer -> packetThrottleAcceleration;
+
+        if (peer -> packetThrottle > peer -> packetThrottleLimit)
+          peer -> packetThrottle = peer -> packetThrottleLimit;
+
+        return 1;
+    }
+    else
+    if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
+    {
+        if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
+          peer -> packetThrottle -= peer -> packetThrottleDeceleration;
+        else
+          peer -> packetThrottle = 0;
+
+        return -1;
+    }
+
+    return 0;
+}
+
+/** Queues a packet to be sent.
+    @param peer destination for the packet
+    @param channelID channel on which to send
+    @param packet packet to send
+    @retval 0 on success
+    @retval < 0 on failure
+*/
+int
+enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
+{
+   ENetChannel * channel = & peer -> channels [channelID];
+   ENetProtocol command;
+   size_t fragmentLength;
+
+   if (peer -> state != ENET_PEER_STATE_CONNECTED ||
+       channelID >= peer -> channelCount)
+     return -1;
+
+   fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
+   if (peer -> host -> checksum != NULL)
+     fragmentLength -= sizeof(enet_uint32);
+
+   if (packet -> dataLength > fragmentLength)
+   {
+      enet_uint16 startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
+      enet_uint32 fragmentCount = ENET_HOST_TO_NET_32 ((packet -> dataLength + fragmentLength - 1) / fragmentLength),
+             fragmentNumber,
+             fragmentOffset;
+      ENetList fragments;
+      ENetOutgoingCommand * fragment;
+
+      enet_list_clear (& fragments);
+
+      for (fragmentNumber = 0,
+             fragmentOffset = 0;
+           fragmentOffset < packet -> dataLength;
+           ++ fragmentNumber,
+             fragmentOffset += fragmentLength)
+      {
+         if (packet -> dataLength - fragmentOffset < fragmentLength)
+           fragmentLength = packet -> dataLength - fragmentOffset;
+
+         fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
+         if (fragment == NULL)
+         {
+            while (! enet_list_empty (& fragments))
+            {
+               fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
+               
+               enet_free (fragment);
+            }
+            
+            return -1;
+         }
+         
+         fragment -> fragmentOffset = fragmentOffset;
+         fragment -> fragmentLength = fragmentLength;
+         fragment -> packet = packet;
+         fragment -> command.header.command = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+         fragment -> command.header.channelID = channelID;
+         fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber;
+         fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
+         fragment -> command.sendFragment.fragmentCount = fragmentCount;
+         fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
+         fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
+         fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
+        
+         enet_list_insert (enet_list_end (& fragments), fragment);
+      }
+
+      packet -> referenceCount += fragmentNumber;
+
+      while (! enet_list_empty (& fragments))
+      {
+         fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
+ 
+         enet_peer_setup_outgoing_command (peer, fragment);
+      }
+
+      return 0;
+   }
+
+   command.header.channelID = channelID;
+
+   if (packet -> flags & ENET_PACKET_FLAG_RELIABLE)
+   {
+      command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+      command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
+   }
+   else
+   if (packet -> flags & ENET_PACKET_FLAG_UNSEQUENCED)
+   {
+      command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
+      command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup + 1);
+      command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
+   }
+   else 
+   if (channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
+   {
+      command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+      command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
+   }
+   else
+   {
+      command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
+      command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
+      command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
+   }
+
+   if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL)
+     return -1;
+
+   return 0;
+}
+
+/** Attempts to dequeue any incoming queued packet.
+    @param peer peer to dequeue packets from
+    @param channelID holds the channel ID of the channel the packet was received on success
+    @returns a pointer to the packet, or NULL if there are no available incoming queued packets
+*/
+ENetPacket *
+enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID)
+{
+   ENetIncomingCommand * incomingCommand;
+   ENetPacket * packet;
+   
+   if (enet_list_empty (& peer -> dispatchedCommands))
+     return NULL;
+
+   incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands));
+
+   if (channelID != NULL)
+     * channelID = incomingCommand -> command.header.channelID;
+
+   packet = incomingCommand -> packet;
+
+   -- packet -> referenceCount;
+
+   if (incomingCommand -> fragments != NULL)
+     enet_free (incomingCommand -> fragments);
+
+   enet_free (incomingCommand);
+
+   return packet;
+}
+
+static void
+enet_peer_reset_outgoing_commands (ENetList * queue)
+{
+    ENetOutgoingCommand * outgoingCommand;
+
+    while (! enet_list_empty (queue))
+    {
+       outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
+
+       if (outgoingCommand -> packet != NULL)
+       {
+          -- outgoingCommand -> packet -> referenceCount;
+
+          if (outgoingCommand -> packet -> referenceCount == 0)
+            enet_packet_destroy (outgoingCommand -> packet);
+       }
+
+       enet_free (outgoingCommand);
+    }
+}
+
+static void
+enet_peer_reset_incoming_commands (ENetList * queue)
+{
+    ENetIncomingCommand * incomingCommand;
+
+    while (! enet_list_empty (queue))
+    {
+       incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (queue));
+
+       if (incomingCommand -> packet != NULL)
+       {
+          -- incomingCommand -> packet -> referenceCount;
+
+          if (incomingCommand -> packet -> referenceCount == 0)
+            enet_packet_destroy (incomingCommand -> packet);
+       }
+
+       if (incomingCommand -> fragments != NULL)
+         enet_free (incomingCommand -> fragments);
+
+       enet_free (incomingCommand);
+    }
+}
+
+void
+enet_peer_reset_queues (ENetPeer * peer)
+{
+    ENetChannel * channel;
+
+    if (peer -> needsDispatch)
+    {
+       enet_list_remove (& peer -> dispatchList);
+
+       peer -> needsDispatch = 0;
+    }
+
+    while (! enet_list_empty (& peer -> acknowledgements))
+      enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
+
+    enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
+    enet_peer_reset_outgoing_commands (& peer -> sentUnreliableCommands);
+    enet_peer_reset_outgoing_commands (& peer -> outgoingReliableCommands);
+    enet_peer_reset_outgoing_commands (& peer -> outgoingUnreliableCommands);
+    enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
+
+    if (peer -> channels != NULL && peer -> channelCount > 0)
+    {
+        for (channel = peer -> channels;
+             channel < & peer -> channels [peer -> channelCount];
+             ++ channel)
+        {
+            enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
+            enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
+        }
+
+        enet_free (peer -> channels);
+    }
+
+    peer -> channels = NULL;
+    peer -> channelCount = 0;
+}
+
+/** Forcefully disconnects a peer.
+    @param peer peer to forcefully disconnect
+    @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
+    on its connection to the local host.
+*/
+void
+enet_peer_reset (ENetPeer * peer)
+{
+    peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
+    peer -> connectID = 0;
+
+    peer -> state = ENET_PEER_STATE_DISCONNECTED;
+
+    peer -> incomingBandwidth = 0;
+    peer -> outgoingBandwidth = 0;
+    peer -> incomingBandwidthThrottleEpoch = 0;
+    peer -> outgoingBandwidthThrottleEpoch = 0;
+    peer -> incomingDataTotal = 0;
+    peer -> outgoingDataTotal = 0;
+    peer -> lastSendTime = 0;
+    peer -> lastReceiveTime = 0;
+    peer -> nextTimeout = 0;
+    peer -> earliestTimeout = 0;
+    peer -> packetLossEpoch = 0;
+    peer -> packetsSent = 0;
+    peer -> packetsLost = 0;
+    peer -> packetLoss = 0;
+    peer -> packetLossVariance = 0;
+    peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
+    peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
+    peer -> packetThrottleCounter = 0;
+    peer -> packetThrottleEpoch = 0;
+    peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
+    peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
+    peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
+    peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
+    peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
+    peer -> lastRoundTripTimeVariance = 0;
+    peer -> highestRoundTripTimeVariance = 0;
+    peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
+    peer -> roundTripTimeVariance = 0;
+    peer -> mtu = peer -> host -> mtu;
+    peer -> reliableDataInTransit = 0;
+    peer -> outgoingReliableSequenceNumber = 0;
+    peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+    peer -> incomingUnsequencedGroup = 0;
+    peer -> outgoingUnsequencedGroup = 0;
+    peer -> eventData = 0;
+
+    memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
+    
+    enet_peer_reset_queues (peer);
+}
+
+/** Sends a ping request to a peer.
+    @param peer destination for the ping request
+    @remarks ping requests factor into the mean round trip time as designated by the 
+    roundTripTime field in the ENetPeer structure.  Enet automatically pings all connected
+    peers at regular intervals, however, this function may be called to ensure more
+    frequent ping requests.
+*/
+void
+enet_peer_ping (ENetPeer * peer)
+{
+    ENetProtocol command;
+
+    if (peer -> state != ENET_PEER_STATE_CONNECTED)
+      return;
+
+    command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+    command.header.channelID = 0xFF;
+   
+    enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
+}
+
+/** Force an immediate disconnection from a peer.
+    @param peer peer to disconnect
+    @param data data describing the disconnection
+    @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
+    guarenteed to receive the disconnect notification, and is reset immediately upon
+    return from this function.
+*/
+void
+enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
+{
+    ENetProtocol command;
+
+    if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
+      return;
+
+    if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
+        peer -> state != ENET_PEER_STATE_DISCONNECTING)
+    {
+        enet_peer_reset_queues (peer);
+
+        command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
+        command.header.channelID = 0xFF;
+        command.disconnect.data = ENET_HOST_TO_NET_32 (data);
+
+        enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
+
+        enet_host_flush (peer -> host);
+    }
+
+    enet_peer_reset (peer);
+}
+
+/** Request a disconnection from a peer.
+    @param peer peer to request a disconnection
+    @param data data describing the disconnection
+    @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
+    once the disconnection is complete.
+*/
+void
+enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
+{
+    ENetProtocol command;
+
+    if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
+        peer -> state == ENET_PEER_STATE_DISCONNECTED ||
+        peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
+        peer -> state == ENET_PEER_STATE_ZOMBIE)
+      return;
+
+    enet_peer_reset_queues (peer);
+
+    command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
+    command.header.channelID = 0xFF;
+    command.disconnect.data = ENET_HOST_TO_NET_32 (data);
+
+    if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
+      command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+    else
+      command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;      
+    
+    enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
+
+    if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
+      peer -> state = ENET_PEER_STATE_DISCONNECTING;
+    else
+    {
+        enet_host_flush (peer -> host);
+        enet_peer_reset (peer);
+    }
+}
+
+/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
+    @param peer peer to request a disconnection
+    @param data data describing the disconnection
+    @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
+    once the disconnection is complete.
+*/
+void
+enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
+{   
+    if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) && 
+        ! (enet_list_empty (& peer -> outgoingReliableCommands) &&
+           enet_list_empty (& peer -> outgoingUnreliableCommands) && 
+           enet_list_empty (& peer -> sentReliableCommands)))
+    {
+        peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
+        peer -> eventData = data;
+    }
+    else
+      enet_peer_disconnect (peer, data);
+}
+
+ENetAcknowledgement *
+enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime)
+{
+    ENetAcknowledgement * acknowledgement;
+
+    if (command -> header.channelID < peer -> channelCount)
+    {
+        ENetChannel * channel = & peer -> channels [command -> header.channelID];
+        enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
+                    currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+
+        if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
+           reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
+
+        if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS)
+          return NULL;
+    }
+
+    acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
+    if (acknowledgement == NULL)
+      return NULL;
+
+    peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
+
+    acknowledgement -> sentTime = sentTime;
+    acknowledgement -> command = * command;
+    
+    enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
+    
+    return acknowledgement;
+}
+
+void
+enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
+{
+    ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
+
+    peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
+
+    if (outgoingCommand -> command.header.channelID == 0xFF)
+    {
+       ++ peer -> outgoingReliableSequenceNumber;
+
+       outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
+       outgoingCommand -> unreliableSequenceNumber = 0;
+    }
+    else
+    if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
+    {
+       ++ channel -> outgoingReliableSequenceNumber;
+       channel -> outgoingUnreliableSequenceNumber = 0;
+
+       outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
+       outgoingCommand -> unreliableSequenceNumber = 0;
+    }
+    else
+    if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
+    {
+       ++ peer -> outgoingUnsequencedGroup;
+
+       outgoingCommand -> reliableSequenceNumber = 0;
+       outgoingCommand -> unreliableSequenceNumber = 0;
+    }
+    else
+    {
+       ++ channel -> outgoingUnreliableSequenceNumber;
+        
+       outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
+       outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
+    }
+   
+    outgoingCommand -> sendAttempts = 0;
+    outgoingCommand -> sentTime = 0;
+    outgoingCommand -> roundTripTimeout = 0;
+    outgoingCommand -> roundTripTimeoutLimit = 0;
+    outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
+
+    if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
+      enet_list_insert (enet_list_end (& peer -> outgoingReliableCommands), outgoingCommand);
+    else
+      enet_list_insert (enet_list_end (& peer -> outgoingUnreliableCommands), outgoingCommand);
+}
+
+ENetOutgoingCommand *
+enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
+{
+    ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
+    if (outgoingCommand == NULL)
+      return NULL;
+
+    outgoingCommand -> command = * command;
+    outgoingCommand -> fragmentOffset = offset;
+    outgoingCommand -> fragmentLength = length;
+    outgoingCommand -> packet = packet;
+    if (packet != NULL)
+      ++ packet -> referenceCount;
+
+    enet_peer_setup_outgoing_command (peer, outgoingCommand);
+
+    return outgoingCommand;
+}
+
+void
+enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel)
+{
+    ENetListIterator currentCommand;
+
+    for (currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands);
+         currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
+         currentCommand = enet_list_next (currentCommand))
+    {
+       ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
+
+       if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE &&
+           incomingCommand -> reliableSequenceNumber != channel -> incomingReliableSequenceNumber)
+         break;
+    }
+
+    if (currentCommand == enet_list_begin (& channel -> incomingUnreliableCommands))
+      return;
+
+    enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingUnreliableCommands), enet_list_previous (currentCommand));
+
+    if (! peer -> needsDispatch)
+    {
+       enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
+
+       peer -> needsDispatch = 1;
+    }
+}
+
+void
+enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel)
+{
+    ENetListIterator currentCommand;
+
+    for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands);
+         currentCommand != enet_list_end (& channel -> incomingReliableCommands);
+         currentCommand = enet_list_next (currentCommand))
+    {
+       ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
+         
+       if (incomingCommand -> fragmentsRemaining > 0 ||
+           incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1))
+         break;
+
+       channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
+
+       if (incomingCommand -> fragmentCount > 0)
+         channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
+    } 
+
+    if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands))
+      return;
+
+    enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
+
+    if (! peer -> needsDispatch)
+    {
+       enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
+
+       peer -> needsDispatch = 1;
+    }
+
+    enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
+}
+
+ENetIncomingCommand *
+enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 fragmentCount)
+{
+    static ENetIncomingCommand dummyCommand;
+
+    ENetChannel * channel = & peer -> channels [command -> header.channelID];
+    enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber;
+    enet_uint16 reliableWindow, currentWindow;
+    ENetIncomingCommand * incomingCommand;
+    ENetListIterator currentCommand;
+
+    if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
+      goto freePacket;
+
+    if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
+    {
+        reliableSequenceNumber = command -> header.reliableSequenceNumber;
+        reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+        currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+
+        if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
+           reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
+
+        if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
+          goto freePacket;
+    }
+                    
+    switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
+    {
+    case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
+    case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
+       if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
+           goto freePacket;
+       
+       for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
+            currentCommand != enet_list_end (& channel -> incomingReliableCommands);
+            currentCommand = enet_list_previous (currentCommand))
+       {
+          incomingCommand = (ENetIncomingCommand *) currentCommand;
+
+          if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
+          {
+             if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
+               continue;
+          }
+          else
+          if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
+            break;
+
+          if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber)
+          {
+             if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
+               break;
+
+             goto freePacket;
+          }
+       }
+       break;
+
+    case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
+       unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber);
+
+       for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
+            currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
+            currentCommand = enet_list_previous (currentCommand))
+       {
+          incomingCommand = (ENetIncomingCommand *) currentCommand;
+
+          if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE)
+            continue;
+
+          if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
+          {
+             if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
+               continue;
+          }
+          else
+          if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
+            break;
+
+          if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
+            break;
+
+          if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
+            continue;
+
+          if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
+          {
+             if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
+               break;
+
+             goto freePacket;
+          }
+       }
+       break;
+
+    case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
+       currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
+       break;
+
+    default:
+       goto freePacket;
+    }
+
+    incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
+    if (incomingCommand == NULL)
+      goto notifyError;
+
+    incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
+    incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF;
+    incomingCommand -> command = * command;
+    incomingCommand -> fragmentCount = fragmentCount;
+    incomingCommand -> fragmentsRemaining = fragmentCount;
+    incomingCommand -> packet = packet;
+    incomingCommand -> fragments = NULL;
+    
+    if (fragmentCount > 0)
+    { 
+       incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
+       if (incomingCommand -> fragments == NULL)
+       {
+          enet_free (incomingCommand);
+
+          goto notifyError;
+       }
+       memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
+    }
+
+    if (packet != NULL)
+      ++ packet -> referenceCount;
+
+    enet_list_insert (enet_list_next (currentCommand), incomingCommand);
+
+    switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
+    {
+    case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
+    case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
+       enet_peer_dispatch_incoming_reliable_commands (peer, channel);
+       break;
+
+    default:
+       enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
+       break;
+    }
+
+    return incomingCommand;
+
+freePacket:
+    if (fragmentCount > 0)
+      goto notifyError;
+
+    if (packet != NULL && packet -> referenceCount == 0)
+      enet_packet_destroy (packet);
+
+    return & dummyCommand;
+
+notifyError:
+    if (packet != NULL && packet -> referenceCount == 0)
+      enet_packet_destroy (packet);
+
+    return NULL;
+}
+
+/** @} */
Index: /code/branches/RacingBots_FS18/src/external/enet/protocol.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/protocol.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/protocol.c	(revision 11817)
@@ -0,0 +1,1741 @@
+/** 
+ @file  protocol.c
+ @brief ENet protocol functions
+*/
+#include <stdio.h>
+#include <string.h>
+#define ENET_BUILDING_LIB 1
+#include "enet/utility.h"
+#include "enet/time.h"
+#include "enet/enet.h"
+
+static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
+{
+    0,
+    sizeof (ENetProtocolAcknowledge),
+    sizeof (ENetProtocolConnect),
+    sizeof (ENetProtocolVerifyConnect),
+    sizeof (ENetProtocolDisconnect),
+    sizeof (ENetProtocolPing),
+    sizeof (ENetProtocolSendReliable),
+    sizeof (ENetProtocolSendUnreliable),
+    sizeof (ENetProtocolSendFragment),
+    sizeof (ENetProtocolSendUnsequenced),
+    sizeof (ENetProtocolBandwidthLimit),
+    sizeof (ENetProtocolThrottleConfigure),
+};
+
+ENetHostAddress
+enet_address_map4 (enet_uint32 address)
+{
+    ENetHostAddress addr = ENET_IPV4MAPPED_PREFIX_INIT;
+    ((enet_uint32 *)addr.addr)[3] = address;
+    return addr;
+}
+
+ENetAddressFamily
+enet_get_address_family (const ENetAddress * address)
+{
+    if (!memcmp(& address->host, & ENET_IPV4MAPPED_PREFIX, ENET_IPV4MAPPED_PREFIX_LEN))
+        return ENET_IPV4;
+    return ENET_IPV6;
+}
+
+size_t
+enet_protocol_command_size (enet_uint8 commandNumber)
+{
+    return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
+}
+
+static int
+enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
+{
+    while (! enet_list_empty (& host -> dispatchQueue))
+    {
+       ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
+
+       peer -> needsDispatch = 0;
+
+       switch (peer -> state)
+       {
+       case ENET_PEER_STATE_CONNECTION_PENDING:
+       case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
+           peer -> state = ENET_PEER_STATE_CONNECTED;
+
+           event -> type = ENET_EVENT_TYPE_CONNECT;
+           event -> peer = peer;
+           event -> data = peer -> eventData;
+
+           return 1;
+           
+       case ENET_PEER_STATE_ZOMBIE:
+           host -> recalculateBandwidthLimits = 1;
+
+           event -> type = ENET_EVENT_TYPE_DISCONNECT;
+           event -> peer = peer;
+           event -> data = peer -> eventData;
+
+           enet_peer_reset (peer);
+
+           return 1;
+
+       case ENET_PEER_STATE_CONNECTED:
+           if (enet_list_empty (& peer -> dispatchedCommands))
+             continue;
+
+           event -> packet = enet_peer_receive (peer, & event -> channelID);
+           if (event -> packet == NULL)
+             continue;
+             
+           event -> type = ENET_EVENT_TYPE_RECEIVE;
+           event -> peer = peer;
+
+           if (! enet_list_empty (& peer -> dispatchedCommands))
+           {
+              peer -> needsDispatch = 1;
+         
+              enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
+           }
+
+           return 1;
+       }
+    }
+
+    return 0;
+}
+
+static void
+enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
+{
+    peer -> state = state;
+
+    if (! peer -> needsDispatch)
+    {
+       enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
+
+       peer -> needsDispatch = 1;
+    }    
+}
+    
+static void
+enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
+{
+    host -> recalculateBandwidthLimits = 1;
+
+    if (event != NULL)
+    {
+        peer -> state = ENET_PEER_STATE_CONNECTED;
+
+        event -> type = ENET_EVENT_TYPE_CONNECT;
+        event -> peer = peer;
+        event -> data = peer -> eventData;
+    }
+    else 
+        enet_protocol_dispatch_state (host, peer, peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING);
+}
+
+static void
+enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
+{
+    if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING)
+       host -> recalculateBandwidthLimits = 1;
+
+    if (peer -> state != ENET_PEER_STATE_CONNECTING && peer -> state < ENET_PEER_STATE_CONNECTION_SUCCEEDED)
+        enet_peer_reset (peer);
+    else
+    if (event != NULL)
+    {
+        event -> type = ENET_EVENT_TYPE_DISCONNECT;
+        event -> peer = peer;
+        event -> data = 0;
+
+        enet_peer_reset (peer);
+    }
+    else 
+    {
+        peer -> eventData = 0;
+
+        enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
+    }
+}
+
+static void
+enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
+{
+    ENetOutgoingCommand * outgoingCommand;
+
+    while (! enet_list_empty (& peer -> sentUnreliableCommands))
+    {
+        outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
+        
+        enet_list_remove (& outgoingCommand -> outgoingCommandList);
+
+        if (outgoingCommand -> packet != NULL)
+        {
+           -- outgoingCommand -> packet -> referenceCount;
+
+           if (outgoingCommand -> packet -> referenceCount == 0)
+             enet_packet_destroy (outgoingCommand -> packet);
+        }
+
+        enet_free (outgoingCommand);
+    }
+}
+
+static ENetProtocolCommand
+enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
+{
+    ENetOutgoingCommand * outgoingCommand;
+    ENetListIterator currentCommand;
+    ENetProtocolCommand commandNumber;
+    int wasSent = 1;
+
+    for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
+         currentCommand != enet_list_end (& peer -> sentReliableCommands);
+         currentCommand = enet_list_next (currentCommand))
+    {
+       outgoingCommand = (ENetOutgoingCommand *) currentCommand;
+        
+       if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
+           outgoingCommand -> command.header.channelID == channelID)
+         break;
+    }
+
+    if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
+    {
+       for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
+            currentCommand != enet_list_end (& peer -> outgoingReliableCommands);
+            currentCommand = enet_list_next (currentCommand))
+       {
+          outgoingCommand = (ENetOutgoingCommand *) currentCommand;
+
+          if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
+
+          if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
+              outgoingCommand -> command.header.channelID == channelID)
+            break;
+       }
+
+       if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands))
+         return ENET_PROTOCOL_COMMAND_NONE;
+
+       wasSent = 0;
+    }
+
+    if (channelID < peer -> channelCount)
+    {
+       ENetChannel * channel = & peer -> channels [channelID];
+       enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+       if (channel -> reliableWindows [reliableWindow] > 0)
+       {
+          -- channel -> reliableWindows [reliableWindow];
+          if (! channel -> reliableWindows [reliableWindow])
+            channel -> usedReliableWindows &= ~ (1 << reliableWindow);
+       }
+    }
+
+    commandNumber = (ENetProtocolCommand) (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK);
+    
+    enet_list_remove (& outgoingCommand -> outgoingCommandList);
+
+    if (outgoingCommand -> packet != NULL)
+    {
+       if (wasSent)
+         peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
+
+       -- outgoingCommand -> packet -> referenceCount;
+
+       if (outgoingCommand -> packet -> referenceCount == 0)
+         enet_packet_destroy (outgoingCommand -> packet);
+    }
+
+    enet_free (outgoingCommand);
+
+    if (enet_list_empty (& peer -> sentReliableCommands))
+      return commandNumber;
+    
+    outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands);
+    
+    peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
+
+    return commandNumber;
+} 
+
+static ENetPeer *
+enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENetProtocol * command)
+{
+    enet_uint8 incomingSessionID, outgoingSessionID;
+    enet_uint32 mtu, windowSize;
+    ENetChannel * channel;
+    size_t channelCount;
+    ENetPeer * currentPeer;
+    ENetProtocol verifyCommand;
+
+    channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount);
+
+    if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT ||
+        channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
+      return NULL;
+
+    for (currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+        if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
+            currentPeer -> address.port == host -> receivedAddress.port &&
+            currentPeer -> connectID == command -> connect.connectID &&
+            !memcmp(& currentPeer -> address.host, & host -> receivedAddress.host, sizeof (ENetHostAddress)))
+          return NULL;
+    }
+
+    for (currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+        if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
+          break;
+    }
+
+    if (currentPeer >= & host -> peers [host -> peerCount])
+      return NULL;
+
+    if (channelCount > host -> channelLimit)
+      channelCount = host -> channelLimit;
+    currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
+    if (currentPeer -> channels == NULL)
+      return NULL;
+    currentPeer -> channelCount = channelCount;
+    currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
+    currentPeer -> connectID = command -> connect.connectID;
+    currentPeer -> address = host -> receivedAddress;
+    currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
+    currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
+    currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
+    currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval);
+    currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration);
+    currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration);
+    currentPeer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data);
+
+    incomingSessionID = command -> connect.incomingSessionID == 0xFF ? currentPeer -> outgoingSessionID : command -> connect.incomingSessionID;
+    incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
+    if (incomingSessionID == currentPeer -> outgoingSessionID)
+      incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
+    currentPeer -> outgoingSessionID = incomingSessionID;
+
+    outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? currentPeer -> incomingSessionID : command -> connect.outgoingSessionID;
+    outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
+    if (outgoingSessionID == currentPeer -> incomingSessionID)
+      outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
+    currentPeer -> incomingSessionID = outgoingSessionID;
+
+    for (channel = currentPeer -> channels;
+         channel < & currentPeer -> channels [channelCount];
+         ++ channel)
+    {
+        channel -> outgoingReliableSequenceNumber = 0;
+        channel -> outgoingUnreliableSequenceNumber = 0;
+        channel -> incomingReliableSequenceNumber = 0;
+
+        enet_list_clear (& channel -> incomingReliableCommands);
+        enet_list_clear (& channel -> incomingUnreliableCommands);
+
+        channel -> usedReliableWindows = 0;
+        memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
+    }
+
+    mtu = ENET_NET_TO_HOST_32 (command -> connect.mtu);
+
+    if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
+      mtu = ENET_PROTOCOL_MINIMUM_MTU;
+    else
+    if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
+      mtu = ENET_PROTOCOL_MAXIMUM_MTU;
+
+    currentPeer -> mtu = mtu;
+
+    if (host -> outgoingBandwidth == 0 &&
+        currentPeer -> incomingBandwidth == 0)
+      currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+    else
+    if (host -> outgoingBandwidth == 0 ||
+        currentPeer -> incomingBandwidth == 0)
+      currentPeer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
+                                    ENET_PEER_WINDOW_SIZE_SCALE) *
+                                      ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+    else
+      currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
+                                    ENET_PEER_WINDOW_SIZE_SCALE) * 
+                                      ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+
+    if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
+      currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+    else
+    if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
+      currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+
+    if (host -> incomingBandwidth == 0)
+      windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+    else
+      windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) *
+                     ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+
+    if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize))
+      windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize);
+
+    if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
+      windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+    else
+    if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
+      windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+
+    verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
+    verifyCommand.header.channelID = 0xFF;
+    verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
+    verifyCommand.verifyConnect.incomingSessionID = incomingSessionID;
+    verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID;
+    verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
+    verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize);
+    verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
+    verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
+    verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
+    verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
+    verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
+    verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
+    verifyCommand.verifyConnect.connectID = currentPeer -> connectID;
+
+    enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0);
+
+    return currentPeer;
+}
+
+static int
+enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
+{
+    ENetPacket * packet;
+    size_t dataLength;
+
+    if (command -> header.channelID >= peer -> channelCount ||
+        (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
+      return -1;
+
+    dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength);
+    * currentData += dataLength;
+    if (* currentData > & host -> receivedData [host -> receivedDataLength])
+      return -1;
+
+    packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable),
+                                 dataLength,
+                                 ENET_PACKET_FLAG_RELIABLE);
+    if (packet == NULL ||
+        enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL)
+      return -1;
+
+    return 0;
+}
+
+static int
+enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
+{
+    ENetPacket * packet;
+    enet_uint32 unsequencedGroup, index;
+    size_t dataLength;
+
+    if (command -> header.channelID >= peer -> channelCount ||
+        (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
+      return -1;
+
+    dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength);
+    * currentData += dataLength;
+    if (* currentData > & host -> receivedData [host -> receivedDataLength])
+      return -1; 
+
+    unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup);
+    index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE;
+   
+    if (unsequencedGroup < peer -> incomingUnsequencedGroup)
+      unsequencedGroup += 0x10000;
+
+    if (unsequencedGroup >= (enet_uint32) peer -> incomingUnsequencedGroup + ENET_PEER_FREE_UNSEQUENCED_WINDOWS * ENET_PEER_UNSEQUENCED_WINDOW_SIZE)
+      return 0;
+
+    unsequencedGroup &= 0xFFFF;
+
+    if (unsequencedGroup - index != peer -> incomingUnsequencedGroup)
+    {
+        peer -> incomingUnsequencedGroup = unsequencedGroup - index;
+
+        memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
+    }
+    else
+    if (peer -> unsequencedWindow [index / 32] & (1 << (index % 32)))
+      return 0;
+      
+    packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced),
+                                 dataLength,
+                                 ENET_PACKET_FLAG_UNSEQUENCED);
+    if (packet == NULL ||
+        enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL)
+      return -1;
+   
+    peer -> unsequencedWindow [index / 32] |= 1 << (index % 32);
+ 
+    return 0;
+}
+
+static int
+enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
+{
+    ENetPacket * packet;
+    size_t dataLength;
+
+    if (command -> header.channelID >= peer -> channelCount ||
+        (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
+      return -1;
+
+    dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength);
+    * currentData += dataLength;
+    if (* currentData > & host -> receivedData [host -> receivedDataLength])
+      return -1;
+
+    packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable),
+                                 dataLength,
+                                 0);
+    if (packet == NULL ||
+        enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL)
+      return -1;
+
+    return 0;
+}
+
+static int
+enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
+{
+    enet_uint32 fragmentNumber,
+           fragmentCount,
+           fragmentOffset,
+           fragmentLength,
+           startSequenceNumber,
+           totalLength;
+    ENetChannel * channel;
+    enet_uint16 startWindow, currentWindow;
+    ENetListIterator currentCommand;
+    ENetIncomingCommand * startCommand = NULL;
+
+    if (command -> header.channelID >= peer -> channelCount ||
+        (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
+      return -1;
+
+    fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
+    * currentData += fragmentLength;
+    if (* currentData > & host -> receivedData [host -> receivedDataLength])
+      return -1;
+
+    channel = & peer -> channels [command -> header.channelID];
+    startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
+    startWindow = startSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+    currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+
+    if (startSequenceNumber < channel -> incomingReliableSequenceNumber)
+      startWindow += ENET_PEER_RELIABLE_WINDOWS;
+
+    if (startWindow < currentWindow || startWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
+      return 0;
+
+    fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
+    fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
+    fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
+    totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
+    
+    if (fragmentOffset >= totalLength ||
+        fragmentOffset + fragmentLength > totalLength ||
+        fragmentNumber >= fragmentCount)
+      return -1;
+ 
+    for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
+         currentCommand != enet_list_end (& channel -> incomingReliableCommands);
+         currentCommand = enet_list_previous (currentCommand))
+    {
+       ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
+
+       if (startSequenceNumber >= channel -> incomingReliableSequenceNumber)
+       {
+          if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
+            continue;
+       }
+       else
+       if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
+         break;
+
+       if (incomingCommand -> reliableSequenceNumber <= startSequenceNumber)
+       {
+          if (incomingCommand -> reliableSequenceNumber < startSequenceNumber)
+            break;
+        
+          if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_FRAGMENT ||
+              totalLength != incomingCommand -> packet -> dataLength ||
+              fragmentCount != incomingCommand -> fragmentCount)
+            return -1;
+
+          startCommand = incomingCommand;
+          break;
+       }
+    }
+ 
+    if (startCommand == NULL)
+    {
+       ENetProtocol hostCommand = * command;
+       ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE);
+       if (packet == NULL)
+         return -1;
+
+       hostCommand.header.reliableSequenceNumber = startSequenceNumber;
+       hostCommand.sendFragment.startSequenceNumber = startSequenceNumber;
+       hostCommand.sendFragment.dataLength = fragmentLength;
+       hostCommand.sendFragment.fragmentNumber = fragmentNumber;
+       hostCommand.sendFragment.fragmentCount = fragmentCount;
+       hostCommand.sendFragment.fragmentOffset = fragmentOffset;
+       hostCommand.sendFragment.totalLength = totalLength;
+
+       startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount);
+       if (startCommand == NULL)
+         return -1;
+    }
+    
+    if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
+    {
+       -- startCommand -> fragmentsRemaining;
+
+       startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
+
+       if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
+         fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
+
+       memcpy (startCommand -> packet -> data + fragmentOffset,
+               (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
+               fragmentLength);
+
+        if (startCommand -> fragmentsRemaining <= 0)
+          enet_peer_dispatch_incoming_reliable_commands (peer, channel);
+    }
+
+    return 0;
+}
+
+static int
+enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
+{
+    return 0;
+}
+
+static int
+enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
+{
+    peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
+    peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
+
+    if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0)
+      peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+    else
+      peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
+                             ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+
+    if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
+      peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+    else
+    if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
+      peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+
+    return 0;
+}
+
+static int
+enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
+{
+    peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
+    peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
+    peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
+
+    return 0;
+}
+
+static int
+enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
+{
+    if (peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT)
+      return 0;
+
+    enet_peer_reset_queues (peer);
+
+    if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED)
+        enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
+    else
+    if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
+    {
+        if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1;
+
+        enet_peer_reset (peer);
+    }
+    else
+    if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
+      peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT;
+    else
+      enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
+
+    if (peer -> state != ENET_PEER_STATE_DISCONNECTED)
+      peer -> eventData = ENET_NET_TO_HOST_32 (command -> disconnect.data);
+
+    return 0;
+}
+
+static int
+enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
+{
+    enet_uint32 roundTripTime,
+           receivedSentTime,
+           receivedReliableSequenceNumber;
+    ENetProtocolCommand commandNumber;
+
+    receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime);
+    receivedSentTime |= host -> serviceTime & 0xFFFF0000;
+    if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000))
+        receivedSentTime -= 0x10000;
+
+    if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
+      return 0;
+
+    peer -> lastReceiveTime = host -> serviceTime;
+    peer -> earliestTimeout = 0;
+
+    roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
+
+    enet_peer_throttle (peer, roundTripTime);
+
+    peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
+
+    if (roundTripTime >= peer -> roundTripTime)
+    {
+       peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
+       peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
+    }
+    else
+    {
+       peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
+       peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
+    }
+
+    if (peer -> roundTripTime < peer -> lowestRoundTripTime)
+      peer -> lowestRoundTripTime = peer -> roundTripTime;
+
+    if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance) 
+      peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
+
+    if (peer -> packetThrottleEpoch == 0 ||
+        ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
+    {
+        peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
+        peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
+        peer -> lowestRoundTripTime = peer -> roundTripTime;
+        peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
+        peer -> packetThrottleEpoch = host -> serviceTime;
+    }
+
+    receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
+
+    commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
+
+    switch (peer -> state)
+    {
+    case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
+       if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
+         return -1;
+
+       enet_protocol_notify_connect (host, peer, event);
+       break;
+
+    case ENET_PEER_STATE_DISCONNECTING:
+       if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
+         return -1;
+
+       enet_protocol_notify_disconnect (host, peer, event);
+       break;
+
+    case ENET_PEER_STATE_DISCONNECT_LATER:
+       if (enet_list_empty (& peer -> outgoingReliableCommands) &&
+           enet_list_empty (& peer -> outgoingUnreliableCommands) &&   
+           enet_list_empty (& peer -> sentReliableCommands))
+         enet_peer_disconnect (peer, peer -> eventData);
+       break;
+    }
+   
+    return 0;
+}
+
+static int
+enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
+{
+    enet_uint32 mtu, windowSize;
+    size_t channelCount;
+
+    if (peer -> state != ENET_PEER_STATE_CONNECTING)
+      return 0;
+
+    channelCount = ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount);
+
+    if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT ||
+        ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
+        ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
+        ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration ||
+        command -> verifyConnect.connectID != peer -> connectID)
+    {
+        peer -> eventData = 0;
+
+        enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
+
+        return -1;
+    }
+
+    enet_protocol_remove_sent_reliable_command (peer, 1, 0xFF);
+    
+    if (channelCount < peer -> channelCount)
+      peer -> channelCount = channelCount;
+
+    peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
+    peer -> incomingSessionID = command -> verifyConnect.incomingSessionID;
+    peer -> outgoingSessionID = command -> verifyConnect.outgoingSessionID;
+
+    mtu = ENET_NET_TO_HOST_32 (command -> verifyConnect.mtu);
+
+    if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
+      mtu = ENET_PROTOCOL_MINIMUM_MTU;
+    else 
+    if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
+      mtu = ENET_PROTOCOL_MAXIMUM_MTU;
+
+    if (mtu < peer -> mtu)
+      peer -> mtu = mtu;
+
+    windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
+
+    if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
+      windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
+
+    if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
+      windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
+
+    if (windowSize < peer -> windowSize)
+      peer -> windowSize = windowSize;
+
+    peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
+    peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
+
+    enet_protocol_notify_connect (host, peer, event);
+    return 0;
+}
+
+static int
+enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
+{
+    ENetProtocolHeader * header;
+    ENetProtocol * command;
+    ENetPeer * peer;
+    enet_uint8 * currentData;
+    size_t headerSize;
+    enet_uint16 peerID, flags;
+    enet_uint8 sessionID;
+
+    if (host -> receivedDataLength < (size_t) & ((ENetProtocolHeader *) 0) -> sentTime)
+      return 0;
+
+    header = (ENetProtocolHeader *) host -> receivedData;
+
+    peerID = ENET_NET_TO_HOST_16 (header -> peerID);
+    sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT;
+    flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK;
+    peerID &= ~ (ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK);
+
+    headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime);
+    if (host -> checksum != NULL)
+      headerSize += sizeof (enet_uint32);
+
+    if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID)
+      peer = NULL;
+    else
+    if (peerID >= host -> peerCount)
+      return 0;
+    else
+    {
+       peer = & host -> peers [peerID];
+
+       if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
+           peer -> state == ENET_PEER_STATE_ZOMBIE ||
+           (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
+            sessionID != peer -> incomingSessionID) ||
+           ( memcmp(& peer -> address.host, & host -> receivedAddress.host, sizeof (ENetHostAddress)) &&
+             memcmp(& peer -> address.host, & ENET_HOST_BROADCAST, sizeof (ENetHostAddress)) &&
+             peer -> address.host.addr[0] != 0xff ) )
+         return 0;
+    }
+ 
+    if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED)
+    {
+        size_t originalSize;
+        if (host -> compressor.context == NULL || host -> compressor.decompress == NULL)
+          return 0;
+
+        originalSize = host -> compressor.decompress (host -> compressor.context,
+                                    host -> receivedData + headerSize, 
+                                    host -> receivedDataLength - headerSize, 
+                                    host -> packetData [1] + headerSize, 
+                                    sizeof (host -> packetData [1]) - headerSize);
+        if (originalSize <= 0 || originalSize > sizeof (host -> packetData [1]) - headerSize)
+          return 0;
+
+        memcpy (host -> packetData [1], header, headerSize);
+        host -> receivedData = host -> packetData [1];
+        host -> receivedDataLength = headerSize + originalSize;
+    }
+
+    if (host -> checksum != NULL)
+    {
+        enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)],
+                    desiredChecksum = * checksum;
+        ENetBuffer buffer;
+
+        * checksum = peer != NULL ? peer -> connectID : 0;
+
+        buffer.data = host -> receivedData;
+        buffer.dataLength = host -> receivedDataLength;
+
+        if (host -> checksum (& buffer, 1) != desiredChecksum)
+          return 0;
+    }
+       
+    if (peer != NULL)
+    {
+       peer -> address = host -> receivedAddress;
+       peer -> incomingDataTotal += host -> receivedDataLength;
+    }
+    
+    currentData = host -> receivedData + headerSize;
+  
+    while (currentData < & host -> receivedData [host -> receivedDataLength])
+    {
+       enet_uint8 commandNumber;
+       size_t commandSize;
+
+       command = (ENetProtocol *) currentData;
+
+       if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
+         break;
+
+       commandNumber = command -> header.command & ENET_PROTOCOL_COMMAND_MASK;
+       if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT) 
+         break;
+       
+       commandSize = commandSizes [commandNumber];
+       if (commandSize == 0 || currentData + commandSize > & host -> receivedData [host -> receivedDataLength])
+         break;
+
+       currentData += commandSize;
+
+       if (peer == NULL && commandNumber != ENET_PROTOCOL_COMMAND_CONNECT)
+         break;
+         
+       command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber);
+
+       switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
+       {
+       case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
+          if (enet_protocol_handle_acknowledge (host, event, peer, command))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_CONNECT:
+          peer = enet_protocol_handle_connect (host, header, command);
+          if (peer == NULL)
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
+          if (enet_protocol_handle_verify_connect (host, event, peer, command))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_DISCONNECT:
+          if (enet_protocol_handle_disconnect (host, peer, command))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_PING:
+          if (enet_protocol_handle_ping (host, peer, command))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
+          if (enet_protocol_handle_send_reliable (host, peer, command, & currentData))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
+          if (enet_protocol_handle_send_unreliable (host, peer, command, & currentData))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
+          if (enet_protocol_handle_send_unsequenced (host, peer, command, & currentData))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
+          if (enet_protocol_handle_send_fragment (host, peer, command, & currentData))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
+          if (enet_protocol_handle_bandwidth_limit (host, peer, command))
+            goto commandError;
+          break;
+
+       case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
+          if (enet_protocol_handle_throttle_configure (host, peer, command))
+            goto commandError;
+          break;
+
+       default:
+          goto commandError;
+       }
+
+       if (peer != NULL &&
+           (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0)
+       {
+           enet_uint16 sentTime;
+
+           if (! (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME))
+             break;
+
+           sentTime = ENET_NET_TO_HOST_16 (header -> sentTime);
+
+           switch (peer -> state)
+           {
+           case ENET_PEER_STATE_DISCONNECTING:
+           case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
+              break;
+
+           case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
+              if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
+                enet_peer_queue_acknowledgement (peer, command, sentTime);
+              break;
+
+           default:   
+              enet_peer_queue_acknowledgement (peer, command, sentTime);        
+              break;
+           }
+       }
+    }
+
+commandError:
+    if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
+      return 1;
+
+    return 0;
+}
+ 
+static int
+enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event, ENetAddressFamily family)
+{
+    for (;;)
+    {
+       int receivedLength;
+       ENetBuffer buffer;
+
+       buffer.data = host -> packetData [0];
+       buffer.dataLength = sizeof (host -> packetData [0]);
+
+       receivedLength = enet_socket_receive (family == ENET_IPV4 ? host -> socket4 : host -> socket6,
+                                             & host -> receivedAddress,
+                                             & buffer,
+                                             1,
+                                             family);
+
+       if (receivedLength < 0)
+         return -1;
+
+       if (receivedLength == 0)
+         return 0;
+
+       if (enet_get_address_family (& host -> receivedAddress) != family)
+         return -1;
+
+       host -> receivedData = host -> packetData [0];
+       host -> receivedDataLength = receivedLength;
+      
+       host -> totalReceivedData += receivedLength;
+       host -> totalReceivedPackets ++;
+ 
+       switch (enet_protocol_handle_incoming_commands (host, event))
+       {
+       case 1:
+          return 1;
+       
+       case -1:
+          return -1;
+
+       default:
+          break;
+       }
+    }
+
+    return -1;
+}
+
+static void
+enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
+{
+    ENetProtocol * command = & host -> commands [host -> commandCount];
+    ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
+    ENetAcknowledgement * acknowledgement;
+    ENetListIterator currentAcknowledgement;
+  
+    currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
+         
+    while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
+    {
+       if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
+           buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
+           peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
+       {
+          host -> continueSending = 1;
+
+          break;
+       }
+
+       acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
+ 
+       currentAcknowledgement = enet_list_next (currentAcknowledgement);
+
+       buffer -> data = command;
+       buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
+
+       host -> packetSize += buffer -> dataLength;
+ 
+       command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
+       command -> header.channelID = acknowledgement -> command.header.channelID;
+       command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber);
+       command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime);
+  
+       if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
+         enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
+
+       enet_list_remove (& acknowledgement -> acknowledgementList);
+       enet_free (acknowledgement);
+
+       ++ command;
+       ++ buffer;
+    }
+
+    host -> commandCount = command - host -> commands;
+    host -> bufferCount = buffer - host -> buffers;
+}
+
+static void
+enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
+{
+    ENetProtocol * command = & host -> commands [host -> commandCount];
+    ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
+    ENetOutgoingCommand * outgoingCommand;
+    ENetListIterator currentCommand;
+
+    currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
+    
+    while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
+    {
+       size_t commandSize;
+
+       outgoingCommand = (ENetOutgoingCommand *) currentCommand;
+       commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
+
+       if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
+           buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
+           peer -> mtu - host -> packetSize < commandSize ||
+           (outgoingCommand -> packet != NULL &&
+             peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> packet -> dataLength))
+       {
+          host -> continueSending = 1;
+
+          break;
+       }
+
+       currentCommand = enet_list_next (currentCommand);
+
+       if (outgoingCommand -> packet != NULL)
+       {
+          peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
+          peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
+          
+          if (peer -> packetThrottleCounter > peer -> packetThrottle)
+          {
+             -- outgoingCommand -> packet -> referenceCount;
+
+             if (outgoingCommand -> packet -> referenceCount == 0)
+               enet_packet_destroy (outgoingCommand -> packet);
+         
+             enet_list_remove (& outgoingCommand -> outgoingCommandList);
+             enet_free (outgoingCommand);
+           
+             continue;
+          }
+       }
+
+       buffer -> data = command;
+       buffer -> dataLength = commandSize;
+      
+       host -> packetSize += buffer -> dataLength;
+
+       * command = outgoingCommand -> command;
+       
+       enet_list_remove (& outgoingCommand -> outgoingCommandList);
+
+       if (outgoingCommand -> packet != NULL)
+       {
+          ++ buffer;
+          
+          buffer -> data = outgoingCommand -> packet -> data;
+          buffer -> dataLength = outgoingCommand -> packet -> dataLength;
+
+          host -> packetSize += buffer -> dataLength;
+
+          enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
+       }
+       else
+         enet_free (outgoingCommand);
+
+       ++ command;
+       ++ buffer;
+    } 
+
+    host -> commandCount = command - host -> commands;
+    host -> bufferCount = buffer - host -> buffers;
+
+    if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && 
+        enet_list_empty (& peer -> outgoingReliableCommands) &&
+        enet_list_empty (& peer -> outgoingUnreliableCommands) && 
+        enet_list_empty (& peer -> sentReliableCommands))
+      enet_peer_disconnect (peer, peer -> eventData);
+}
+
+static int
+enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
+{
+    ENetOutgoingCommand * outgoingCommand;
+    ENetListIterator currentCommand, insertPosition;
+
+    currentCommand = enet_list_begin (& peer -> sentReliableCommands);
+    insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
+
+    while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
+    {
+       outgoingCommand = (ENetOutgoingCommand *) currentCommand;
+
+       currentCommand = enet_list_next (currentCommand);
+
+       if (ENET_TIME_DIFFERENCE (host -> serviceTime, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
+         continue;
+
+       if (peer -> earliestTimeout == 0 ||
+           ENET_TIME_LESS (outgoingCommand -> sentTime, peer -> earliestTimeout))
+         peer -> earliestTimeout = outgoingCommand -> sentTime;
+
+       if (peer -> earliestTimeout != 0 &&
+             (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MAXIMUM ||
+               (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
+                 ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MINIMUM)))
+       {
+          enet_protocol_notify_disconnect (host, peer, event);
+
+          return 1;
+       }
+
+       if (outgoingCommand -> packet != NULL)
+         peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
+          
+       ++ peer -> packetsLost;
+
+       outgoingCommand -> roundTripTimeout *= 2;
+
+       enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
+
+       if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
+           ! enet_list_empty (& peer -> sentReliableCommands))
+       {
+          outgoingCommand = (ENetOutgoingCommand *) currentCommand;
+
+          peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
+       }
+    }
+    
+    return 0;
+}
+
+static int
+enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
+{
+    ENetProtocol * command = & host -> commands [host -> commandCount];
+    ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
+    ENetOutgoingCommand * outgoingCommand;
+    ENetListIterator currentCommand;
+    ENetChannel *channel;
+    enet_uint16 reliableWindow;
+    size_t commandSize;
+    int windowExceeded = 0, windowWrap = 0, canPing = 1;
+
+    currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
+    
+    while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
+    {
+       outgoingCommand = (ENetOutgoingCommand *) currentCommand;
+
+       channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
+       reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
+       if (channel != NULL)
+       {
+           if (! windowWrap &&      
+               outgoingCommand -> sendAttempts < 1 && 
+               ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
+               (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
+                 channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) | 
+                   (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOW_SIZE - reliableWindow)))))
+             windowWrap = 1;
+          if (windowWrap)
+          {
+             currentCommand = enet_list_next (currentCommand);
+ 
+             continue;
+          }
+       }
+ 
+       if (outgoingCommand -> packet != NULL)
+       {
+          if (! windowExceeded)
+          {
+             enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
+             
+             if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
+               windowExceeded = 1;
+          }
+          if (windowExceeded)
+          {
+             currentCommand = enet_list_next (currentCommand);
+
+             continue;
+          }
+       }
+
+       canPing = 0;
+
+       commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
+       if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
+           buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
+           peer -> mtu - host -> packetSize < commandSize ||
+           (outgoingCommand -> packet != NULL && 
+             (enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
+       {
+          host -> continueSending = 1;
+          
+          break;
+       }
+
+       currentCommand = enet_list_next (currentCommand);
+
+       if (channel != NULL && outgoingCommand -> sendAttempts < 1)
+       {
+          channel -> usedReliableWindows |= 1 << reliableWindow;
+          ++ channel -> reliableWindows [reliableWindow];
+       }
+
+       ++ outgoingCommand -> sendAttempts;
+ 
+       if (outgoingCommand -> roundTripTimeout == 0)
+       {
+          outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
+          outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout;
+       }
+
+       if (enet_list_empty (& peer -> sentReliableCommands))
+         peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
+
+       enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
+                         enet_list_remove (& outgoingCommand -> outgoingCommandList));
+
+       outgoingCommand -> sentTime = host -> serviceTime;
+
+       buffer -> data = command;
+       buffer -> dataLength = commandSize;
+
+       host -> packetSize += buffer -> dataLength;
+       host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
+
+       * command = outgoingCommand -> command;
+
+       if (outgoingCommand -> packet != NULL)
+       {
+          ++ buffer;
+          
+          buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
+          buffer -> dataLength = outgoingCommand -> fragmentLength;
+
+          host -> packetSize += outgoingCommand -> fragmentLength;
+
+          peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
+       }
+
+       ++ peer -> packetsSent;
+        
+       ++ command;
+       ++ buffer;
+    }
+
+    host -> commandCount = command - host -> commands;
+    host -> bufferCount = buffer - host -> buffers;
+
+    return canPing;
+}
+
+static int
+enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
+{
+    enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
+    ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
+    ENetPeer * currentPeer;
+    int sentLength;
+    size_t shouldCompress = 0;
+ 
+    host -> continueSending = 1;
+
+    while (host -> continueSending)
+    for (host -> continueSending = 0,
+           currentPeer = host -> peers;
+         currentPeer < & host -> peers [host -> peerCount];
+         ++ currentPeer)
+    {
+        ENetAddressFamily family;
+        ENetSocket socket;
+
+        if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
+            currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
+          continue;
+
+        host -> headerFlags = 0;
+        host -> commandCount = 0;
+        host -> bufferCount = 1;
+        host -> packetSize = sizeof (ENetProtocolHeader);
+
+        if (! enet_list_empty (& currentPeer -> acknowledgements))
+          enet_protocol_send_acknowledgements (host, currentPeer);
+
+        if (checkForTimeouts != 0 &&
+            ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
+            ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) &&
+            enet_protocol_check_timeouts (host, currentPeer, event) == 1)
+          return 1;
+
+        if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) ||
+              enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) &&
+            enet_list_empty (& currentPeer -> sentReliableCommands) &&
+            ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL &&
+            currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
+        { 
+            enet_peer_ping (currentPeer);
+            enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
+        }
+                      
+        if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
+          enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
+
+        if (host -> commandCount == 0)
+          continue;
+
+        if (currentPeer -> packetLossEpoch == 0)
+          currentPeer -> packetLossEpoch = host -> serviceTime;
+        else
+        if (ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
+            currentPeer -> packetsSent > 0)
+        {
+           enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
+
+#ifdef ENET_DEBUG
+#ifdef WIN32
+           printf (
+#else
+           fprintf (stderr, 
+#endif
+                    "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
+#endif
+          
+           currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
+
+           if (packetLoss >= currentPeer -> packetLoss)
+           {
+              currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
+              currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
+           }
+           else
+           {
+              currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
+              currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
+           }
+
+           currentPeer -> packetLossEpoch = host -> serviceTime;
+           currentPeer -> packetsSent = 0;
+           currentPeer -> packetsLost = 0;
+        }
+
+        host -> buffers -> data = headerData;
+        if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
+        {
+            header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF);
+
+            host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
+        }
+        else
+          host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
+
+        shouldCompress = 0;
+        if (host -> compressor.context != NULL && host -> compressor.compress != NULL)
+        {
+            size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader),
+                   compressedSize = host -> compressor.compress (host -> compressor.context,
+                                        & host -> buffers [1], host -> bufferCount - 1,
+                                        originalSize,
+                                        host -> packetData [1],
+                                        originalSize);
+            if (compressedSize > 0 && compressedSize < originalSize)
+            {
+                host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
+                shouldCompress = compressedSize;
+#ifdef ENET_DEBUG_COMPRESS
+#ifdef WIN32
+           printf (
+#else
+           fprintf (stderr,
+#endif
+                    "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
+#endif
+            }
+        }
+
+        if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID)
+          host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
+        header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
+        if (host -> checksum != NULL)
+        {
+            enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength];
+            * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0;
+            host -> buffers -> dataLength += sizeof (enet_uint32);
+            * checksum = host -> checksum (host -> buffers, host -> bufferCount);
+        }
+
+        if (shouldCompress > 0)
+        {
+            host -> buffers [1].data = host -> packetData [1];
+            host -> buffers [1].dataLength = shouldCompress;
+            host -> bufferCount = 2;
+        }
+
+        currentPeer -> lastSendTime = host -> serviceTime;
+
+        family = enet_get_address_family (& currentPeer -> address);
+        socket = family == ENET_IPV4 ? host -> socket4 : host -> socket6;
+        if (socket == ENET_SOCKET_NULL)
+          return -1;
+        sentLength = enet_socket_send (socket,
+                                           & currentPeer -> address,
+                                           host -> buffers,
+                                           host -> bufferCount,
+                                           family);
+
+        enet_protocol_remove_sent_unreliable_commands (currentPeer);
+
+        if (sentLength < 0)
+          return -1;
+
+        host -> totalSentData += sentLength;
+        host -> totalSentPackets ++;
+    }
+   
+    return 0;
+}
+
+/** Sends any queued packets on the host specified to its designated peers.
+
+    @param host   host to flush
+    @remarks this function need only be used in circumstances where one wishes to send queued packets earlier than in a call to enet_host_service().
+    @ingroup host
+*/
+void
+enet_host_flush (ENetHost * host)
+{
+    host -> serviceTime = enet_time_get ();
+
+    enet_protocol_send_outgoing_commands (host, NULL, 0);
+}
+
+/** Checks for any queued events on the host and dispatches one if available.
+
+    @param host    host to check for events
+    @param event   an event structure where event details will be placed if available
+    @retval > 0 if an event was dispatched
+    @retval 0 if no events are available
+    @retval < 0 on failure
+    @ingroup host
+*/
+int
+enet_host_check_events (ENetHost * host, ENetEvent * event)
+{
+    if (event == NULL) return -1;
+
+    event -> type = ENET_EVENT_TYPE_NONE;
+    event -> peer = NULL;
+    event -> packet = NULL;
+
+    return enet_protocol_dispatch_incoming_commands (host, event);
+}
+
+/** Waits for events on the host specified and shuttles packets between
+    the host and its peers.
+
+    @param host    host to service
+    @param event   an event structure where event details will be placed if one occurs
+                   if event == NULL then no events will be delivered
+    @param timeout number of milliseconds that ENet should wait for events
+    @retval > 0 if an event occurred within the specified time limit
+    @retval 0 if no event occurred
+    @retval < 0 on failure
+    @remarks enet_host_service should be called fairly regularly for adequate performance
+    @ingroup host
+*/
+int
+enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
+{
+    enet_uint32 waitCondition;
+
+    if (event != NULL)
+    {
+        event -> type = ENET_EVENT_TYPE_NONE;
+        event -> peer = NULL;
+        event -> packet = NULL;
+
+        switch (enet_protocol_dispatch_incoming_commands (host, event))
+        {
+        case 1:
+            return 1;
+
+        case -1:
+            perror ("Error dispatching incoming packets");
+
+            return -1;
+
+        default:
+            break;
+        }
+    }
+
+    host -> serviceTime = enet_time_get ();
+    
+    timeout += host -> serviceTime;
+
+    do
+    {
+       if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
+         enet_host_bandwidth_throttle (host);
+
+       switch (enet_protocol_send_outgoing_commands (host, event, 1))
+       {
+       case 1:
+          return 1;
+
+       case -1:
+          perror ("Error sending outgoing packets");
+
+          return -1;
+
+       default:
+          break;
+       }
+
+       if (host -> socket4 != ENET_SOCKET_NULL)
+         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV4))
+       {
+       case 1:
+          return 1;
+
+       case -1:
+          perror ("Error receiving incoming packets");
+
+          return -1;
+
+       default:
+          break;
+       }
+
+       if (host -> socket6 != ENET_SOCKET_NULL)
+         switch (enet_protocol_receive_incoming_commands (host, event, ENET_IPV6))
+       {
+       case 1:
+          return 1;
+
+       case -1:
+          perror ("Error receiving incoming packets");
+
+          return -1;
+
+       default:
+          break;
+       }
+
+       switch (enet_protocol_send_outgoing_commands (host, event, 1))
+       {
+       case 1:
+          return 1;
+
+       case -1:
+          perror ("Error sending outgoing packets");
+
+          return -1;
+
+       default:
+          break;
+       }
+
+       if (event != NULL)
+       {
+          switch (enet_protocol_dispatch_incoming_commands (host, event))
+          {
+          case 1:
+             return 1;
+
+          case -1:
+             perror ("Error dispatching incoming packets");
+
+             return -1;
+
+          default:
+             break;
+          }
+       }
+
+       host -> serviceTime = enet_time_get ();
+
+       if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
+         return 0;
+
+       waitCondition = ENET_SOCKET_WAIT_RECEIVE;
+
+       if (enet_socket_wait (host -> socket4, host -> socket6, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
+         return -1;
+       
+       host -> serviceTime = enet_time_get ();
+    } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
+
+    return 0; 
+}
+
Index: /code/branches/RacingBots_FS18/src/external/enet/protocol.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/protocol.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/protocol.h	(revision 11817)
@@ -0,0 +1,196 @@
+/** 
+ @file  protocol.h
+ @brief ENet protocol
+*/
+#ifndef __ENET_PROTOCOL_H__
+#define __ENET_PROTOCOL_H__
+
+#include "enet/types.h"
+
+enum
+{
+   ENET_PROTOCOL_MINIMUM_MTU             = 576,
+   ENET_PROTOCOL_MAXIMUM_MTU             = 4096,
+   ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
+   ENET_PROTOCOL_MINIMUM_WINDOW_SIZE     = 4096,
+   ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE     = 32768,
+   ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT   = 1,
+   ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT   = 255,
+   ENET_PROTOCOL_MAXIMUM_PEER_ID         = 0xFFF
+};
+
+typedef enum _ENetProtocolCommand
+{
+   ENET_PROTOCOL_COMMAND_NONE               = 0,
+   ENET_PROTOCOL_COMMAND_ACKNOWLEDGE        = 1,
+   ENET_PROTOCOL_COMMAND_CONNECT            = 2,
+   ENET_PROTOCOL_COMMAND_VERIFY_CONNECT     = 3,
+   ENET_PROTOCOL_COMMAND_DISCONNECT         = 4,
+   ENET_PROTOCOL_COMMAND_PING               = 5,
+   ENET_PROTOCOL_COMMAND_SEND_RELIABLE      = 6,
+   ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE    = 7,
+   ENET_PROTOCOL_COMMAND_SEND_FRAGMENT      = 8,
+   ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED   = 9,
+   ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT    = 10,
+   ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
+   ENET_PROTOCOL_COMMAND_COUNT              = 12,
+
+   ENET_PROTOCOL_COMMAND_MASK               = 0x0F
+} ENetProtocolCommand;
+
+typedef enum _ENetProtocolFlag
+{
+   ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
+   ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
+
+   ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
+   ENET_PROTOCOL_HEADER_FLAG_SENT_TIME  = (1 << 15),
+   ENET_PROTOCOL_HEADER_FLAG_MASK       = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
+
+   ENET_PROTOCOL_HEADER_SESSION_MASK    = (3 << 12),
+   ENET_PROTOCOL_HEADER_SESSION_SHIFT   = 12
+} ENetProtocolFlag;
+
+#ifdef _MSC_VER_
+#pragma pack(push, 1)
+#define ENET_PACKED
+#elif defined(__GNUC__)
+#define ENET_PACKED __attribute__ ((packed))
+#else
+#define ENET_PACKED
+#endif
+
+typedef struct _ENetProtocolHeader
+{
+   enet_uint16 peerID;
+   enet_uint16 sentTime;
+} ENET_PACKED ENetProtocolHeader;
+
+typedef struct _ENetProtocolCommandHeader
+{
+   enet_uint8 command;
+   enet_uint8 channelID;
+   enet_uint16 reliableSequenceNumber;
+} ENET_PACKED ENetProtocolCommandHeader;
+
+typedef struct _ENetProtocolAcknowledge
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 receivedReliableSequenceNumber;
+   enet_uint16 receivedSentTime;
+} ENET_PACKED ENetProtocolAcknowledge;
+
+typedef struct _ENetProtocolConnect
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 outgoingPeerID;
+   enet_uint8  incomingSessionID;
+   enet_uint8  outgoingSessionID;
+   enet_uint32 mtu;
+   enet_uint32 windowSize;
+   enet_uint32 channelCount;
+   enet_uint32 incomingBandwidth;
+   enet_uint32 outgoingBandwidth;
+   enet_uint32 packetThrottleInterval;
+   enet_uint32 packetThrottleAcceleration;
+   enet_uint32 packetThrottleDeceleration;
+   enet_uint32 connectID;
+   enet_uint32 data;
+} ENET_PACKED ENetProtocolConnect;
+
+typedef struct _ENetProtocolVerifyConnect
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 outgoingPeerID;
+   enet_uint8  incomingSessionID;
+   enet_uint8  outgoingSessionID;
+   enet_uint32 mtu;
+   enet_uint32 windowSize;
+   enet_uint32 channelCount;
+   enet_uint32 incomingBandwidth;
+   enet_uint32 outgoingBandwidth;
+   enet_uint32 packetThrottleInterval;
+   enet_uint32 packetThrottleAcceleration;
+   enet_uint32 packetThrottleDeceleration;
+   enet_uint32 connectID;
+} ENET_PACKED ENetProtocolVerifyConnect;
+
+typedef struct _ENetProtocolBandwidthLimit
+{
+   ENetProtocolCommandHeader header;
+   enet_uint32 incomingBandwidth;
+   enet_uint32 outgoingBandwidth;
+} ENET_PACKED ENetProtocolBandwidthLimit;
+
+typedef struct _ENetProtocolThrottleConfigure
+{
+   ENetProtocolCommandHeader header;
+   enet_uint32 packetThrottleInterval;
+   enet_uint32 packetThrottleAcceleration;
+   enet_uint32 packetThrottleDeceleration;
+} ENET_PACKED ENetProtocolThrottleConfigure;
+
+typedef struct _ENetProtocolDisconnect
+{
+   ENetProtocolCommandHeader header;
+   enet_uint32 data;
+} ENET_PACKED ENetProtocolDisconnect;
+
+typedef struct _ENetProtocolPing
+{
+   ENetProtocolCommandHeader header;
+} ENET_PACKED ENetProtocolPing;
+
+typedef struct _ENetProtocolSendReliable
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 dataLength;
+} ENET_PACKED ENetProtocolSendReliable;
+
+typedef struct _ENetProtocolSendUnreliable
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 unreliableSequenceNumber;
+   enet_uint16 dataLength;
+} ENET_PACKED ENetProtocolSendUnreliable;
+
+typedef struct _ENetProtocolSendUnsequenced
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 unsequencedGroup;
+   enet_uint16 dataLength;
+} ENET_PACKED ENetProtocolSendUnsequenced;
+
+typedef struct _ENetProtocolSendFragment
+{
+   ENetProtocolCommandHeader header;
+   enet_uint16 startSequenceNumber;
+   enet_uint16 dataLength;
+   enet_uint32 fragmentCount;
+   enet_uint32 fragmentNumber;
+   enet_uint32 totalLength;
+   enet_uint32 fragmentOffset;
+} ENET_PACKED ENetProtocolSendFragment;
+
+typedef union _ENetProtocol
+{
+   ENetProtocolCommandHeader header;
+   ENetProtocolAcknowledge acknowledge;
+   ENetProtocolConnect connect;
+   ENetProtocolVerifyConnect verifyConnect;
+   ENetProtocolDisconnect disconnect;
+   ENetProtocolPing ping;
+   ENetProtocolSendReliable sendReliable;
+   ENetProtocolSendUnreliable sendUnreliable;
+   ENetProtocolSendUnsequenced sendUnsequenced;
+   ENetProtocolSendFragment sendFragment;
+   ENetProtocolBandwidthLimit bandwidthLimit;
+   ENetProtocolThrottleConfigure throttleConfigure;
+} ENET_PACKED ENetProtocol;
+
+#ifdef _MSC_VER_
+#pragma pack(pop)
+#endif
+
+#endif /* __ENET_PROTOCOL_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/time.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/time.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/time.h	(revision 11817)
@@ -0,0 +1,18 @@
+/** 
+ @file  time.h
+ @brief ENet time constants and macros
+*/
+#ifndef __ENET_TIME_H__
+#define __ENET_TIME_H__
+
+#define ENET_TIME_OVERFLOW 86400000
+
+#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
+#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
+#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
+#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
+
+#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
+
+#endif /* __ENET_TIME_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/types.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/types.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/types.h	(revision 11817)
@@ -0,0 +1,13 @@
+/** 
+ @file  types.h
+ @brief type definitions for ENet
+*/
+#ifndef __ENET_TYPES_H__
+#define __ENET_TYPES_H__
+
+typedef unsigned char enet_uint8;       /**< unsigned 8-bit type  */
+typedef unsigned short enet_uint16;     /**< unsigned 16-bit type */
+typedef unsigned int enet_uint32;      /**< unsigned 32-bit type */
+
+#endif /* __ENET_TYPES_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/unix.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/unix.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/unix.c	(revision 11817)
@@ -0,0 +1,502 @@
+/** 
+ @file  unix.c
+ @brief ENet Unix system specific functions
+*/
+#ifndef WIN32
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#define ENET_BUILDING_LIB 1
+#include "enet/enet.h"
+
+#ifdef HAS_FCNTL
+#include <fcntl.h>
+#endif
+
+#ifdef __APPLE__
+#undef HAS_POLL
+#endif
+
+#ifdef HAS_POLL
+#include <sys/poll.h>
+#endif
+
+#ifndef HAS_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+static enet_uint32 timeBase = 0;
+
+int
+enet_initialize (void)
+{
+    return 0;
+}
+
+void
+enet_deinitialize (void)
+{
+}
+
+enet_uint32
+enet_time_get (void)
+{
+    struct timeval timeVal;
+
+    gettimeofday (& timeVal, NULL);
+
+    return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
+}
+
+void
+enet_time_set (enet_uint32 newTimeBase)
+{
+    struct timeval timeVal;
+
+    gettimeofday (& timeVal, NULL);
+    
+    timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
+}
+
+static enet_uint16
+enet_af (ENetAddressFamily family)
+{
+    if (family == ENET_IPV4)
+        return AF_INET;
+    if (family == ENET_IPV6)
+        return AF_INET6;
+    return 0;
+}
+
+static socklen_t
+enet_sa_size (ENetAddressFamily family)
+{
+    if (family == ENET_IPV4)
+        return sizeof (struct sockaddr_in);
+    if (family == ENET_IPV6)
+        return sizeof (struct sockaddr_in6);
+    return 0;
+}
+
+static ENetAddressFamily
+enet_address_set_address (ENetAddress * address, const struct sockaddr * sin)
+{
+    memset (address, 0, sizeof (ENetAddress));
+    if (sin -> sa_family == AF_INET)
+    {
+        address -> host = enet_address_map4 ((((struct sockaddr_in *) sin) -> sin_addr.s_addr));
+        /* address -> scopeID = 0; */
+        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in *) sin) -> sin_port);
+        return ENET_IPV4;
+    }
+    if (sin -> sa_family == AF_INET6)
+    {
+        address -> host = * (ENetHostAddress *) & ((struct sockaddr_in6 *) sin) -> sin6_addr;
+        address -> scopeID = ((struct sockaddr_in6 *) sin) -> sin6_scope_id;
+        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in6 *) sin) -> sin6_port);
+        return ENET_IPV6;
+    }
+    return ENET_NO_ADDRESS_FAMILY;
+}
+
+static int
+enet_address_set_sin (struct sockaddr * sin, const ENetAddress * address, ENetAddressFamily family)
+{
+    memset (sin, 0, enet_sa_size(family));
+    if (family == ENET_IPV4 &&
+      (enet_get_address_family (address) == ENET_IPV4 ||
+      !memcmp (& address -> host, & ENET_HOST_ANY, sizeof(ENetHostAddress))))
+    {
+        ((struct sockaddr_in *) sin) -> sin_family = AF_INET;
+        ((struct sockaddr_in *) sin) -> sin_addr = * (struct in_addr *) & address -> host.addr[12];
+        ((struct sockaddr_in *) sin) -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
+        return 0;
+    }
+    else if (family == ENET_IPV6)
+    {
+        ((struct sockaddr_in6 *) sin) -> sin6_family = AF_INET6;
+        ((struct sockaddr_in6 *) sin) -> sin6_addr = * (struct in6_addr *) & address -> host;
+        ((struct sockaddr_in6 *) sin) -> sin6_scope_id = address -> scopeID;
+        ((struct sockaddr_in6 *) sin) -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
+        return 0;
+    }
+    return -1;
+}
+
+int
+enet_address_set_host (ENetAddress * address, const char * name)
+{
+    enet_uint16 port = address -> port;
+    struct addrinfo hints;
+    struct addrinfo * result;
+    struct addrinfo * res;
+
+    memset(& hints, 0, sizeof (hints));
+    hints.ai_flags = AI_ADDRCONFIG;
+    hints.ai_family = AF_UNSPEC;
+
+    if ( getaddrinfo(name, NULL, &hints, &result) )
+        return -1;
+
+    for (res = result; res != NULL; res = res -> ai_next)
+    {
+        if ( enet_address_set_address(address, res -> ai_addr) != ENET_NO_ADDRESS_FAMILY )
+            break;
+    }
+
+    address -> port = port;
+    freeaddrinfo(result);
+    if (res == NULL) return -1;
+
+    return 0;
+}
+
+static int
+enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags)
+{
+    struct sockaddr_storage sin;
+    enet_address_set_sin((struct sockaddr *) & sin, address, ENET_IPV6);
+
+    if ( getnameinfo((struct sockaddr *) & sin, enet_sa_size (ENET_IPV6), name, nameLength, NULL, 0, flags))
+        return -1;
+
+    return 0;
+}
+
+int
+enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
+{
+    return enet_address_get_host_x(address, name, nameLength, NI_NUMERICHOST);
+}
+
+int
+enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
+{
+    return enet_address_get_host_x(address, name, nameLength, 0);
+}
+
+int
+enet_socket_bind (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
+{
+    struct sockaddr_storage sin;
+
+    if (address != NULL)
+    {
+        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+    }
+    else
+    {
+        ENetAddress address_ = { ENET_HOST_ANY_INIT, 0, 0 };
+        enet_address_set_sin((struct sockaddr *) & sin, & address_, family);
+    }
+
+    return bind (socket, (struct sockaddr *) & sin, enet_sa_size(family));
+}
+
+int
+enet_socket_listen (ENetSocket socket, int backlog)
+{
+    return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
+}
+
+ENetSocket
+enet_socket_create (ENetSocketType type, ENetAddressFamily family)
+{
+    ENetSocket sock = socket (enet_af (family), type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
+
+#ifdef IPV6_V6ONLY
+    if (family == ENET_IPV6)
+    {
+        int value = 1;
+        setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, & value, sizeof (int));
+    }
+#endif /* IPV6_V6ONLY */
+
+    return sock;
+}
+
+int
+enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
+{
+    int result = -1;
+    switch (option)
+    {
+        case ENET_SOCKOPT_NONBLOCK:
+#ifdef HAS_FCNTL
+            result = fcntl (socket, F_SETFL, O_NONBLOCK | fcntl (socket, F_GETFL));
+#else
+            result = ioctl (socket, FIONBIO, & value);
+#endif
+            break;
+
+        case ENET_SOCKOPT_BROADCAST:
+            result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
+            break;
+
+        case ENET_SOCKOPT_REUSEADDR:
+            result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
+            break;
+
+        case ENET_SOCKOPT_RCVBUF:
+            result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
+            break;
+
+        case ENET_SOCKOPT_SNDBUF:
+            result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
+            break;
+
+        default:
+            break;
+    }
+    return result == -1 ? -1 : 0;
+}
+
+int
+enet_socket_connect (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
+{
+    struct sockaddr_storage sin;
+    enet_address_set_sin((struct sockaddr *) & sin, address, family);
+
+    return connect (socket, (struct sockaddr *) & sin, enet_sa_size (family));
+}
+
+ENetSocket
+enet_socket_accept (ENetSocket socket, ENetAddress * address, ENetAddressFamily family)
+{
+    int result;
+    struct sockaddr_storage sin;
+    socklen_t sinLength = enet_sa_size (family);
+
+    result = accept (socket, 
+                     address != NULL ? (struct sockaddr *) & sin : NULL,
+                     address != NULL ? & sinLength : NULL);
+
+    if (result == -1)
+      return ENET_SOCKET_NULL;
+
+    if (address != NULL)
+    {
+        enet_address_set_address(address, (struct sockaddr *) & sin);
+    }
+
+    return result;
+}
+
+void
+enet_socket_destroy (ENetSocket socket)
+{
+    close (socket);
+}
+
+int
+enet_socket_send (ENetSocket socket,
+                  const ENetAddress * address,
+                  const ENetBuffer * buffers,
+                  size_t bufferCount,
+                  ENetAddressFamily family)
+{
+    struct msghdr msgHdr;
+    struct sockaddr_storage sin;
+    int sentLength;
+
+    memset (& msgHdr, 0, sizeof (struct msghdr));
+
+    if (address != NULL)
+    {
+        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+        msgHdr.msg_name = & sin;
+        msgHdr.msg_namelen = enet_sa_size (family);
+    }
+
+    msgHdr.msg_iov = (struct iovec *) buffers;
+    msgHdr.msg_iovlen = bufferCount;
+
+    sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
+    
+    if (sentLength == -1)
+    {
+       if (errno == EWOULDBLOCK)
+         return 0;
+
+       return -1;
+    }
+
+    return sentLength;
+}
+
+int
+enet_socket_receive (ENetSocket socket,
+                     ENetAddress * address,
+                     ENetBuffer * buffers,
+                     size_t bufferCount,
+                     ENetAddressFamily family)
+{
+    struct msghdr msgHdr;
+    struct sockaddr_storage sin;
+    int recvLength;
+
+    memset (& msgHdr, 0, sizeof (struct msghdr));
+
+    if (address != NULL)
+    {
+        msgHdr.msg_name = & sin;
+        msgHdr.msg_namelen = enet_sa_size (family);
+    }
+
+    msgHdr.msg_iov = (struct iovec *) buffers;
+    msgHdr.msg_iovlen = bufferCount;
+
+    recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
+
+    if (recvLength == -1)
+    {
+       if (errno == EWOULDBLOCK)
+         return 0;
+
+       return -1;
+    }
+
+#ifdef HAS_MSGHDR_FLAGS
+    if (msgHdr.msg_flags & MSG_TRUNC)
+      return -1;
+#endif
+
+    if (address != NULL)
+    {
+        enet_address_set_address(address, (struct sockaddr *) & sin);
+    }
+
+    return recvLength;
+}
+
+int
+enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
+{
+    struct timeval timeVal;
+
+    timeVal.tv_sec = timeout / 1000;
+    timeVal.tv_usec = (timeout % 1000) * 1000;
+
+    return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
+}
+
+int
+enet_socket_wait (ENetSocket socket4, ENetSocket socket6, enet_uint32 * condition, enet_uint32 timeout)
+{
+#ifdef HAS_POLL
+    struct pollfd pollSocket[2];
+    int pollCount;
+
+    pollSocket[0].fd = socket4;
+    pollSocket[1].fd = socket6;
+    pollSocket[0].events = 0;
+    pollSocket[1].events = 0;
+    /* pollSocket[0].revents = 0; */
+    pollSocket[1].revents = 0;
+
+    if (pollSocket[0].fd == ENET_SOCKET_NULL)
+    {
+        pollSocket[0].fd = pollSocket[1].fd;
+        pollSocket[1].fd = ENET_SOCKET_NULL;
+    }
+
+    if (* condition & ENET_SOCKET_WAIT_SEND)
+    {
+        pollSocket[0].events |= POLLOUT;
+        pollSocket[1].events |= POLLOUT;
+    }
+
+    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
+    {
+        pollSocket[0].events |= POLLIN;
+        pollSocket[1].events |= POLLIN;
+    }
+
+    pollCount = poll (pollSocket, pollSocket[1].fd != ENET_SOCKET_NULL ? 2 : 1, timeout);
+
+    if (pollCount < 0)
+      return -1;
+
+    * condition = ENET_SOCKET_WAIT_NONE;
+
+    if (pollCount == 0)
+      return 0;
+
+    if ((pollSocket[0].revents | pollSocket[1].revents) & POLLOUT)
+      * condition |= ENET_SOCKET_WAIT_SEND;
+    
+    if ((pollSocket[0].revents | pollSocket[1].revents) & POLLIN)
+      * condition |= ENET_SOCKET_WAIT_RECEIVE;
+
+    return 0;
+#else
+    fd_set readSet, writeSet;
+    struct timeval timeVal;
+    int selectCount;
+    ENetSocket maxSocket;
+
+    timeVal.tv_sec = timeout / 1000;
+    timeVal.tv_usec = (timeout % 1000) * 1000;
+
+    FD_ZERO (& readSet);
+    FD_ZERO (& writeSet);
+
+    if (* condition & ENET_SOCKET_WAIT_SEND)
+    {
+        if (socket4 != ENET_SOCKET_NULL)
+            FD_SET (socket4, & writeSet);
+        if (socket6 != ENET_SOCKET_NULL)
+            FD_SET (socket6, & writeSet);
+    }
+
+    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
+    {
+        if (socket4 != ENET_SOCKET_NULL)
+            FD_SET (socket4, & readSet);
+        if (socket6 != ENET_SOCKET_NULL)
+            FD_SET (socket6, & readSet);
+    }
+
+    maxSocket = 0;
+    if (socket4 != ENET_SOCKET_NULL)
+        maxSocket = socket4;
+    if (socket6 != ENET_SOCKET_NULL && socket6 > maxSocket)
+        maxSocket = socket6;
+
+    selectCount = select (maxSocket + 1, & readSet, & writeSet, NULL, & timeVal);
+
+    if (selectCount < 0)
+      return -1;
+
+    * condition = ENET_SOCKET_WAIT_NONE;
+
+    if (selectCount == 0)
+      return 0;
+
+    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & writeSet)) ||
+        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & writeSet)) )
+        * condition |= ENET_SOCKET_WAIT_SEND;
+
+    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & readSet)) ||
+        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & readSet)) )
+        * condition |= ENET_SOCKET_WAIT_RECEIVE;
+
+    return 0;
+#endif
+}
+
+#endif
+
Index: /code/branches/RacingBots_FS18/src/external/enet/unix.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/unix.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/unix.h	(revision 11817)
@@ -0,0 +1,45 @@
+/** 
+ @file  unix.h
+ @brief ENet Unix header
+*/
+#ifndef __ENET_UNIX_H__
+#define __ENET_UNIX_H__
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+typedef int ENetSocket;
+
+enum
+{
+    ENET_SOCKET_NULL = -1
+};
+
+#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
+#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
+
+#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
+#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
+
+typedef struct
+{
+    void * data;
+    size_t dataLength;
+} ENetBuffer;
+
+#define ENET_CALLBACK
+
+#define ENET_API extern
+
+typedef fd_set ENetSocketSet;
+
+#define ENET_SOCKETSET_EMPTY(sockset)          FD_ZERO (& (sockset))
+#define ENET_SOCKETSET_ADD(sockset, socket)    FD_SET (socket, & (sockset))
+#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset))
+#define ENET_SOCKETSET_CHECK(sockset, socket)  FD_ISSET (socket, & (sockset))
+    
+#endif /* __ENET_UNIX_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/utility.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/utility.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/utility.h	(revision 11817)
@@ -0,0 +1,12 @@
+/** 
+ @file  utility.h
+ @brief ENet utility header
+*/
+#ifndef __ENET_UTILITY_H__
+#define __ENET_UTILITY_H__
+
+#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
+#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+#endif /* __ENET_UTILITY_H__ */
+
Index: /code/branches/RacingBots_FS18/src/external/enet/win32.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/win32.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/win32.c	(revision 11817)
@@ -0,0 +1,422 @@
+/** 
+ @file  win32.c
+ @brief ENet Win32 system specific functions
+*/
+#ifdef WIN32
+
+#include <time.h>
+#define ENET_BUILDING_LIB 1
+#include "enet/enet.h"
+#include <ws2tcpip.h>
+
+static enet_uint32 timeBase = 0;
+
+int
+enet_initialize (void)
+{
+    WORD versionRequested = MAKEWORD (2, 2);
+    WSADATA wsaData;
+   
+    if (WSAStartup (versionRequested, & wsaData))
+       return -1;
+
+    if (LOBYTE (wsaData.wVersion) != 2||
+        HIBYTE (wsaData.wVersion) != 2)
+    {
+       WSACleanup ();
+       
+       return -1;
+    }
+
+    timeBeginPeriod (1);
+
+    return 0;
+}
+
+void
+enet_deinitialize (void)
+{
+    timeEndPeriod (1);
+
+    WSACleanup ();
+}
+
+enet_uint32
+enet_time_get (void)
+{
+    return (enet_uint32) timeGetTime () - timeBase;
+}
+
+void
+enet_time_set (enet_uint32 newTimeBase)
+{
+    timeBase = (enet_uint32) timeGetTime () - newTimeBase;
+}
+
+static enet_uint16
+enet_af (ENetAddressFamily family)
+{
+    if (family == ENET_IPV4)
+        return AF_INET;
+    if (family == ENET_IPV6)
+        return AF_INET6;
+    return 0;
+}
+
+static socklen_t
+enet_sa_size (ENetAddressFamily family)
+{
+    if (family == ENET_IPV4)
+        return sizeof (struct sockaddr_in);
+    if (family == ENET_IPV6)
+        return sizeof (struct sockaddr_in6);
+    return 0;
+}
+
+static ENetAddressFamily
+enet_address_set_address (ENetAddress * address, const struct sockaddr * sin)
+{
+    memset (address, 0, sizeof (ENetAddress));
+    if (sin -> sa_family == AF_INET)
+    {
+        address -> host = enet_address_map4 ((((struct sockaddr_in *) sin) -> sin_addr.s_addr));
+        /* address -> scopeID = 0; */
+        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in *) sin) -> sin_port);
+        return ENET_IPV4;
+    }
+    if (sin -> sa_family == AF_INET6)
+    {
+        address -> host = * (ENetHostAddress *) & ((struct sockaddr_in6 *) sin) -> sin6_addr;
+        address -> scopeID = ((struct sockaddr_in6 *) sin) -> sin6_scope_id;
+        address -> port = ENET_NET_TO_HOST_16 (((struct sockaddr_in6 *) sin) -> sin6_port);
+        return ENET_IPV6;
+    }
+    return ENET_NO_ADDRESS_FAMILY;
+}
+
+static int
+enet_address_set_sin (struct sockaddr * sin, const ENetAddress * address, ENetAddressFamily family)
+{
+    memset (sin, 0, enet_sa_size(family));
+    if (family == ENET_IPV4 &&
+      (enet_get_address_family (address) == ENET_IPV4 ||
+      !memcmp (& address -> host, & ENET_HOST_ANY, sizeof(ENetHostAddress))))
+    {
+        ((struct sockaddr_in *) sin) -> sin_family = AF_INET;
+        ((struct sockaddr_in *) sin) -> sin_addr = * (struct in_addr *) & address -> host.addr[12];
+        ((struct sockaddr_in *) sin) -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
+        return 0;
+    }
+    else if (family == ENET_IPV6)
+    {
+        ((struct sockaddr_in6 *) sin) -> sin6_family = AF_INET6;
+        ((struct sockaddr_in6 *) sin) -> sin6_addr = * (struct in6_addr *) & address -> host;
+        ((struct sockaddr_in6 *) sin) -> sin6_scope_id = address -> scopeID;
+        ((struct sockaddr_in6 *) sin) -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
+        return 0;
+    }
+    return -1;
+}
+
+int
+enet_address_set_host (ENetAddress * address, const char * name)
+{
+    enet_uint16 port = address -> port;
+    struct addrinfo hints;
+    struct addrinfo * result;
+    struct addrinfo * res;
+
+    memset(& hints, 0, sizeof (hints));
+    hints.ai_flags = AI_ADDRCONFIG;
+    hints.ai_family = AF_UNSPEC;
+
+    if ( getaddrinfo(name, NULL, &hints, &result) )
+        return -1;
+
+    for (res = result; res != NULL; res = res -> ai_next)
+    {
+        if ( enet_address_set_address(address, res -> ai_addr) != ENET_NO_ADDRESS_FAMILY )
+            break;
+    }
+
+    address -> port = port;
+    freeaddrinfo(result);
+    if (res == NULL) return -1;
+
+    return 0;
+}
+
+static int
+enet_address_get_host_x (const ENetAddress * address, char * name, size_t nameLength, int flags)
+{
+    struct sockaddr_storage sin;
+    enet_address_set_sin((struct sockaddr *) & sin, address, ENET_IPV6);
+
+    if ( getnameinfo((struct sockaddr *) & sin, enet_sa_size (ENET_IPV6), name, nameLength, NULL, 0, flags))
+        return -1;
+
+    return 0;
+}
+
+int
+enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
+{
+    return enet_address_get_host_x(address, name, nameLength, NI_NUMERICHOST);
+}
+
+int
+enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
+{
+    return enet_address_get_host_x(address, name, nameLength, 0);
+}
+
+int
+enet_socket_bind (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
+{
+    struct sockaddr_storage sin;
+
+    if (address != NULL)
+    {
+        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+    }
+    else
+    {
+        ENetAddress address_ = { ENET_HOST_ANY_INIT, 0, 0 };
+        enet_address_set_sin((struct sockaddr *) & sin, & address_, family);
+    }
+
+    return bind (socket, (struct sockaddr *) & sin, enet_sa_size(family)) == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+enet_socket_listen (ENetSocket socket, int backlog)
+{
+    return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
+}
+
+ENetSocket
+enet_socket_create (ENetSocketType type, ENetAddressFamily family)
+{
+    ENetSocket sock = socket (enet_af (family), type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
+    return sock;
+}
+
+int
+enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
+{
+    int result = SOCKET_ERROR;
+    switch (option)
+    {
+        case ENET_SOCKOPT_NONBLOCK:
+        {
+            u_long nonBlocking = (u_long) value;
+            result = ioctlsocket (socket, FIONBIO, & nonBlocking);
+            break;
+        }
+
+        case ENET_SOCKOPT_BROADCAST:
+            result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
+            break;
+
+        case ENET_SOCKOPT_REUSEADDR:
+            result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
+            break;
+
+        case ENET_SOCKOPT_RCVBUF:
+            result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
+            break;
+
+        case ENET_SOCKOPT_SNDBUF:
+            result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
+            break;
+
+        default:
+            break;
+    }
+    return result == SOCKET_ERROR ? -1 : 0;
+}
+
+int
+enet_socket_connect (ENetSocket socket, const ENetAddress * address, ENetAddressFamily family)
+{
+    struct sockaddr_storage sin;
+    enet_address_set_sin((struct sockaddr *) & sin, address, family);
+
+    return connect (socket, (struct sockaddr *) & sin, enet_sa_size (family)) == SOCKET_ERROR ? -1 : 0;
+}
+
+ENetSocket
+enet_socket_accept (ENetSocket socket, ENetAddress * address, ENetAddressFamily family)
+{
+    SOCKET result;
+    struct sockaddr_storage sin;
+    socklen_t sinLength = enet_sa_size (family);
+
+    result = accept (socket, 
+                     address != NULL ? (struct sockaddr *) & sin : NULL,
+                     address != NULL ? & sinLength : NULL);
+
+    if (result == INVALID_SOCKET)
+      return ENET_SOCKET_NULL;
+
+    if (address != NULL)
+    {
+        enet_address_set_address(address, (struct sockaddr *) & sin);
+    }
+
+    return result;
+}
+
+void
+enet_socket_destroy (ENetSocket socket)
+{
+    closesocket (socket);
+}
+
+int
+enet_socket_send (ENetSocket socket,
+                  const ENetAddress * address,
+                  const ENetBuffer * buffers,
+                  size_t bufferCount,
+                  ENetAddressFamily family)
+{
+    struct sockaddr_storage sin;
+    DWORD sentLength;
+
+    if (address != NULL)
+    {
+        enet_address_set_sin((struct sockaddr *) & sin, address, family);
+    }
+
+    if (WSASendTo (socket, 
+                   (LPWSABUF) buffers,
+                   (DWORD) bufferCount,
+                   & sentLength,
+                   0,
+                   address != NULL ? (struct sockaddr *) & sin : 0,
+                   address != NULL ? enet_sa_size (family) : 0,
+                   NULL,
+                   NULL) == SOCKET_ERROR)
+    {
+       if (WSAGetLastError () == WSAEWOULDBLOCK)
+         return 0;
+
+       return -1;
+    }
+
+    return (int) sentLength;
+}
+
+int
+enet_socket_receive (ENetSocket socket,
+                     ENetAddress * address,
+                     ENetBuffer * buffers,
+                     size_t bufferCount,
+                     ENetAddressFamily family)
+{
+    INT sinLength = enet_sa_size (family);
+    DWORD flags = 0,
+          recvLength;
+    struct sockaddr_storage sin;
+
+    if (WSARecvFrom (socket,
+                     (LPWSABUF) buffers,
+                     (DWORD) bufferCount,
+                     & recvLength,
+                     & flags,
+                     address != NULL ? (struct sockaddr *) & sin : NULL,
+                     address != NULL ? & sinLength : NULL,
+                     NULL,
+                     NULL) == SOCKET_ERROR)
+    {
+       switch (WSAGetLastError ())
+       {
+       case WSAEWOULDBLOCK:
+       case WSAECONNRESET:
+          return 0;
+       }
+
+       return -1;
+    }
+
+    if (flags & MSG_PARTIAL)
+      return -1;
+
+    if (address != NULL)
+    {
+        enet_address_set_address(address, (struct sockaddr *) & sin);
+    }
+
+    return (int) recvLength;
+}
+
+int
+enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
+{
+    struct timeval timeVal;
+
+    timeVal.tv_sec = timeout / 1000;
+    timeVal.tv_usec = (timeout % 1000) * 1000;
+
+    return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
+}
+
+int
+enet_socket_wait (ENetSocket socket4, ENetSocket socket6, enet_uint32 * condition, enet_uint32 timeout)
+{
+    fd_set readSet, writeSet;
+    struct timeval timeVal;
+    int selectCount;
+    ENetSocket maxSocket;
+
+    timeVal.tv_sec = timeout / 1000;
+    timeVal.tv_usec = (timeout % 1000) * 1000;
+
+    FD_ZERO (& readSet);
+    FD_ZERO (& writeSet);
+
+    if (* condition & ENET_SOCKET_WAIT_SEND)
+    {
+        if (socket4 != ENET_SOCKET_NULL)
+            FD_SET (socket4, & writeSet);
+        if (socket6 != ENET_SOCKET_NULL)
+            FD_SET (socket6, & writeSet);
+    }
+
+    if (* condition & ENET_SOCKET_WAIT_RECEIVE)
+    {
+        if (socket4 != ENET_SOCKET_NULL)
+            FD_SET (socket4, & readSet);
+        if (socket6 != ENET_SOCKET_NULL)
+            FD_SET (socket6, & readSet);
+    }
+
+    maxSocket = 0;
+    if (socket4 != ENET_SOCKET_NULL)
+        maxSocket = socket4;
+    if (socket6 != ENET_SOCKET_NULL && socket6 > maxSocket)
+        maxSocket = socket6;
+
+    selectCount = select (maxSocket + 1, & readSet, & writeSet, NULL, & timeVal);
+
+    if (selectCount < 0)
+      return -1;
+
+    * condition = ENET_SOCKET_WAIT_NONE;
+
+    if (selectCount == 0)
+      return 0;
+
+    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & writeSet)) ||
+        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & writeSet)) )
+        * condition |= ENET_SOCKET_WAIT_SEND;
+
+    if ( (socket4 != ENET_SOCKET_NULL && FD_ISSET (socket4, & readSet)) ||
+        (socket6 != ENET_SOCKET_NULL && FD_ISSET (socket6, & readSet)) )
+        * condition |= ENET_SOCKET_WAIT_RECEIVE;
+
+    return 0;
+}
+
+#endif
+
Index: /code/branches/RacingBots_FS18/src/external/enet/win32.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/enet/win32.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/enet/win32.h	(revision 11817)
@@ -0,0 +1,62 @@
+/** 
+ @file  win32.h
+ @brief ENet Win32 header
+*/
+#ifndef __ENET_WIN32_H__
+#define __ENET_WIN32_H__
+
+#ifdef ENET_BUILDING_LIB
+#pragma warning (disable: 4996) // 'strncpy' was declared deprecated
+#pragma warning (disable: 4267) // size_t to int conversion
+#pragma warning (disable: 4244) // 64bit to 32bit int
+#pragma warning (disable: 4018) // signed/unsigned mismatch
+#endif
+
+#include <stdlib.h>
+#include <winsock2.h>
+
+typedef SOCKET ENetSocket;
+
+enum
+{
+    ENET_SOCKET_NULL = INVALID_SOCKET
+};
+
+#define ENET_HOST_TO_NET_16(value) (htons (value))
+#define ENET_HOST_TO_NET_32(value) (htonl (value))
+
+#define ENET_NET_TO_HOST_16(value) (ntohs (value))
+#define ENET_NET_TO_HOST_32(value) (ntohl (value))
+
+typedef struct
+{
+    size_t dataLength;
+    void * data;
+} ENetBuffer;
+
+#define ENET_CALLBACK __cdecl
+
+#if defined ENET_DLL
+#if defined ENET_BUILDING_LIB
+#define ENET_API __declspec( dllexport )
+#else
+#define ENET_API __declspec( dllimport )
+#endif /* ENET_BUILDING_LIB */
+#else /* !ENET_DLL */
+#define ENET_API extern
+#endif /* ENET_DLL */
+
+typedef fd_set ENetSocketSet;
+
+#define ENET_SOCKETSET_EMPTY(sockset)          FD_ZERO (& (sockset))
+#define ENET_SOCKETSET_ADD(sockset, socket)    FD_SET (socket, & (sockset))
+#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLEAR (socket, & (sockset))
+#define ENET_SOCKETSET_CHECK(sockset, socket)  FD_ISSET (socket, & (sockset))
+
+#ifndef AI_ADDRCONFIG
+#define AI_ADDRCONFIG 0x0400 /* AI_ADDRCONFIG is not defined everywhere */
+#endif
+
+#endif /* __ENET_WIN32_H__ */
+
+
Index: /code/branches/RacingBots_FS18/src/external/gmock/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,40 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(GMOCK_FILES
+    src/gmock-all.cc
+    include/gmock/gmock.h
+)
+
+INCLUDE_DIRECTORIES(
+    .
+    include
+    ../gtest/include
+)
+
+ORXONOX_ADD_LIBRARY(gmock_orxonox
+    ORXONOX_EXTERNAL
+    VERSION         1.6.0
+    EXCLUDE_FROM_ALL
+    NO_INSTALL
+    LINK_LIBRARIES  gtest_orxonox
+    SOURCE_FILES    ${GMOCK_FILES}
+)
+
+SET(GMOCK_MAIN "${CMAKE_CURRENT_SOURCE_DIR}/src/gmock_main.cc" CACHE INTERNAL "gmock main() function")
Index: /code/branches/RacingBots_FS18/src/external/gmock/CONTRIBUTORS
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/CONTRIBUTORS	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/CONTRIBUTORS	(revision 11817)
@@ -0,0 +1,40 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Mocking Framework project.  People
+# who commit code to the project are encouraged to add their names
+# here.  Please keep the list sorted by first names.
+
+Benoit Sigoure <tsuna@google.com>
+Bogdan Piloca <boo@google.com>
+Chandler Carruth <chandlerc@google.com>
+Dave MacLachlan <dmaclach@gmail.com>
+David Anderson <danderson@google.com>
+Dean Sturtevant
+Gene Volovich <gv@cite.com>
+Hal Burch <gmock@hburch.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jim Keller <jimkeller@google.com>
+Joe Walnes <joe@truemesh.com>
+Jon Wray <jwray@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kostya Serebryany <kcc@google.com>
+Lev Makhlis
+Manuel Klimek <klimek@google.com>
+Mario Tanev <radix@google.com>
+Mark Paskin
+Markus Heule <markus.heule@gmail.com>
+Matthew Simmons <simmonmt@acm.org>
+Mike Bland <mbland@google.com>
+Neal Norwitz <nnorwitz@gmail.com>
+Nermin Ozkiranartli <nermin@google.com>
+Owen Carlsen <ocarlsen@google.com>
+Paneendra Ba <paneendra@google.com>
+Paul Menage <menage@google.com>
+Piotr Kaminski <piotrk@google.com>
+Russ Rufer <russ@pentad.com>
+Sverre Sundsdal <sundsdal@gmail.com>
+Takeshi Yoshino <tyoshino@google.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Wolfgang Klier <wklier@google.com>
+Zhanyong Wan <wan@google.com>
Index: /code/branches/RacingBots_FS18/src/external/gmock/COPYING
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/COPYING	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/COPYING	(revision 11817)
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: /code/branches/RacingBots_FS18/src/external/gmock/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/README	(revision 11817)
@@ -0,0 +1,354 @@
+Google C++ Mocking Framework
+============================
+
+http://code.google.com/p/googlemock/
+
+Overview
+--------
+
+Google's framework for writing and using C++ mock classes on a variety
+of platforms (Linux, Mac OS X, Windows, Windows CE, Symbian, etc).
+Inspired by jMock, EasyMock, and Hamcrest, and designed with C++'s
+specifics in mind, it can help you derive better designs of your
+system and write better tests.
+
+Google Mock:
+
+- provides a declarative syntax for defining mocks,
+- can easily define partial (hybrid) mocks, which are a cross of real
+  and mock objects,
+- handles functions of arbitrary types and overloaded functions,
+- comes with a rich set of matchers for validating function arguments,
+- uses an intuitive syntax for controlling the behavior of a mock,
+- does automatic verification of expectations (no record-and-replay
+  needed),
+- allows arbitrary (partial) ordering constraints on
+  function calls to be expressed,
+- lets a user extend it by defining new matchers and actions.
+- does not use exceptions, and
+- is easy to learn and use.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development.  There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available.  Please
+join us!
+
+Please note that code under scripts/generator/ is from the cppclean
+project (http://code.google.com/p/cppclean/) and under the Apache
+License, which is different from Google Mock's license.
+
+Requirements for End Users
+--------------------------
+
+Google Mock is implemented on top of the Google Test C++ testing
+framework (http://code.google.com/p/googletest/), and includes the
+latter as part of the SVN repositary and distribution package.  You
+must use the bundled version of Google Test when using Google Mock, or
+you may get compiler/linker errors.
+
+You can also easily configure Google Mock to work with another testing
+framework of your choice; although it will still need Google Test as
+an internal dependency.  Please read
+http://code.google.com/p/googlemock/wiki/ForDummies#Using_Google_Mock_with_Any_Testing_Framework
+for how to do it.
+
+Google Mock depends on advanced C++ features and thus requires a more
+modern compiler.  The following are needed to use Google Mock:
+
+### Linux Requirements ###
+
+These are the base requirements to build and use Google Mock from a source
+package (as described below):
+
+  * GNU-compatible Make or "gmake"
+  * POSIX-standard shell
+  * POSIX(-2) Regular Expressions (regex.h)
+  * C++98-standard-compliant compiler (e.g. GCC 3.4 or newer)
+
+### Windows Requirements ###
+
+  * Microsoft Visual C++ 8.0 SP1 or newer
+
+### Mac OS X Requirements ###
+
+  * Mac OS X 10.4 Tiger or newer
+  * Developer Tools Installed
+
+Requirements for Contributors
+-----------------------------
+
+We welcome patches.  If you plan to contribute a patch, you need to
+build Google Mock and its own tests from an SVN checkout (described
+below), which has further requirements:
+
+  * Automake version 1.9 or newer
+  * Autoconf version 2.59 or newer
+  * Libtool / Libtoolize
+  * Python version 2.3 or newer (for running some of the tests and
+    re-generating certain source files from templates)
+
+Getting the Source
+------------------
+
+There are two primary ways of getting Google Mock's source code: you
+can download a stable source release in your preferred archive format,
+or directly check out the source from our Subversion (SVN) repositary.
+The SVN checkout requires a few extra steps and some extra software
+packages on your system, but lets you track development and make
+patches much more easily, so we highly encourage it.
+
+### Source Package ###
+
+Google Mock is released in versioned source packages which can be
+downloaded from the download page [1].  Several different archive
+formats are provided, but the only difference is the tools needed to
+extract their contents, and the size of the resulting file.  Download
+whichever you are most comfortable with.
+
+  [1] http://code.google.com/p/googlemock/downloads/list
+
+Once downloaded expand the archive using whichever tools you prefer
+for that type.  This will always result in a new directory with the
+name "gmock-X.Y.Z" which contains all of the source code.  Here are
+some examples on Linux:
+
+  tar -xvzf gmock-X.Y.Z.tar.gz
+  tar -xvjf gmock-X.Y.Z.tar.bz2
+  unzip gmock-X.Y.Z.zip
+
+### SVN Checkout ###
+
+To check out the main branch (also known as the "trunk") of Google
+Mock, run the following Subversion command:
+
+  svn checkout http://googlemock.googlecode.com/svn/trunk/ gmock-svn
+
+If you are using a *nix system and plan to use the GNU Autotools build
+system to build Google Mock (described below), you'll need to
+configure it now.  Otherwise you are done with getting the source
+files.
+
+To prepare the Autotools build system, enter the target directory of
+the checkout command you used ('gmock-svn') and proceed with the
+following command:
+
+  autoreconf -fvi
+
+Once you have completed this step, you are ready to build the library.
+Note that you should only need to complete this step once.  The
+subsequent 'make' invocations will automatically re-generate the bits
+of the build system that need to be changed.
+
+If your system uses older versions of the autotools, the above command
+will fail.  You may need to explicitly specify a version to use.  For
+instance, if you have both GNU Automake 1.4 and 1.9 installed and
+'automake' would invoke the 1.4, use instead:
+
+  AUTOMAKE=automake-1.9 ACLOCAL=aclocal-1.9 autoreconf -fvi
+
+Make sure you're using the same version of automake and aclocal.
+
+Setting up the Build
+--------------------
+
+To build Google Mock and your tests that use it, you need to tell your
+build system where to find its headers and source files.  The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+### Generic Build Instructions ###
+
+This section shows how you can integrate Google Mock into your
+existing build system.
+
+Suppose you put Google Mock in directory ${GMOCK_DIR} and Google Test
+in ${GTEST_DIR} (the latter is ${GMOCK_DIR}/gtest by default).  To
+build Google Mock, create a library build target (or a project as
+called by Visual Studio and Xcode) to compile
+
+  ${GTEST_DIR}/src/gtest-all.cc and ${GMOCK_DIR}/src/gmock-all.cc
+
+with
+
+  ${GTEST_DIR}/include, ${GTEST_DIR}, ${GMOCK_DIR}/include, and ${GMOCK_DIR}
+
+in the header search path.  Assuming a Linux-like system and gcc,
+something like the following will do:
+
+  g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I${GMOCK_DIR}/include \
+      -I${GMOCK_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
+  g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -I${GMOCK_DIR}/include \
+      -I${GMOCK_DIR} -c ${GMOCK_DIR}/src/gmock-all.cc
+  ar -rv libgmock.a gtest-all.o gmock-all.o
+
+Next, you should compile your test source file with
+${GTEST_DIR}/include and ${GMOCK_DIR}/include in the header search
+path, and link it with gmock and any other necessary libraries:
+
+  g++ -I${GTEST_DIR}/include -I${GMOCK_DIR}/include \
+      path/to/your_test.cc libgmock.a -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Mock on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin).  It doesn't try to build Google
+Mock's own tests.  Instead, it just builds the Google Mock library and
+a sample test.  You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+  cd ${GMOCK_DIR}/make
+  make
+  ./gmock_test
+
+If you see errors, try to tweak the contents of make/Makefile to make
+them go away.  There are instructions in make/Makefile on how to do
+it.
+
+### Windows ###
+
+The msvc/2005 directory contains VC++ 2005 projects and the msvc/2010
+directory contains VC++ 2010 projects for building Google Mock and
+selected tests.
+
+Change to the appropriate directory and run "msbuild gmock.sln" to
+build the library and tests (or open the gmock.sln in the MSVC IDE).
+If you want to create your own project to use with Google Mock, you'll
+have to configure it to use the gmock_config propety sheet.  For that:
+
+ * Open the Property Manager window (View | Other Windows | Property Manager)
+ * Right-click on your project and select "Add Existing Property Sheet..."
+ * Navigate to gmock_config.vsprops or gmock_config.props and select it.
+ * In Project Properties | Configuration Properties | General | Additional
+   Include Directories, type <path to Google Mock>/include.
+
+Tweaking Google Mock
+--------------------
+
+Google Mock can be used in diverse environments.  The default
+configuration may not work (or may not work well) out of the box in
+some environments.  However, you can easily tweak Google Mock by
+defining control macros on the compiler command line.  Generally,
+these macros are named like GTEST_XYZ and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below.  For a complete list,
+see file ${GTEST_DIR}/include/gtest/internal/gtest-port.h.
+
+### Choosing a TR1 Tuple Library ###
+
+Google Mock uses the C++ Technical Report 1 (TR1) tuple library
+heavily.  Unfortunately TR1 tuple is not yet widely available with all
+compilers.  The good news is that Google Test 1.4.0+ implements a
+subset of TR1 tuple that's enough for Google Mock's need.  Google Mock
+will automatically use that implementation when the compiler doesn't
+provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+and Google Mock use.  However, if your project already uses TR1 tuple,
+you need to tell Google Test and Google Mock to use the same TR1 tuple
+library the rest of your project uses, or the two tuple
+implementations will clash.  To do that, add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test, Google Mock, and
+your tests.  If you want to force Google Test and Google Mock to use
+their own tuple library, just add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you want to use Boost's TR1 tuple library with Google Mock, please
+refer to the Boost website (http://www.boost.org/) for how to obtain
+it and set it up.
+
+### Tweaking Google Test ###
+
+Most of Google Test's control macros apply to Google Mock as well.
+Please see file ${GTEST_DIR}/README for how to tweak them.
+
+Upgrading from an Earlier Version
+---------------------------------
+
+We strive to keep Google Mock releases backward compatible.
+Sometimes, though, we have to make some breaking changes for the
+users' long-term benefits.  This section describes what you'll need to
+do if you are upgrading from an earlier version of Google Mock.
+
+### Upgrading from 1.1.0 or Earlier ###
+
+You may need to explicitly enable or disable Google Test's own TR1
+tuple library.  See the instructions in section "Choosing a TR1 Tuple
+Library".
+
+### Upgrading from 1.4.0 or Earlier ###
+
+On platforms where the pthread library is available, Google Test and
+Google Mock use it in order to be thread-safe.  For this to work, you
+may need to tweak your compiler and/or linker flags.  Please see the
+"Multi-threaded Tests" section in file ${GTEST_DIR}/README for what
+you may need to do.
+
+If you have custom matchers defined using MatcherInterface or
+MakePolymorphicMatcher(), you'll need to update their definitions to
+use the new matcher API [2].  Matchers defined using MATCHER() or
+MATCHER_P*() aren't affected.
+
+  [2] http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Monomorphic_Matchers,
+      http://code.google.com/p/googlemock/wiki/CookBook#Writing_New_Polymorphic_Matchers
+
+Developing Google Mock
+----------------------
+
+This section discusses how to make your own changes to Google Mock.
+
+### Testing Google Mock Itself ###
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you'll need Autotools.  First, make sure you have followed
+the instructions in section "SVN Checkout" to configure Google Mock.
+Then, create a build output directory and enter it.  Next,
+
+  ${GMOCK_DIR}/configure  # Standard GNU configure script, --help for more info
+
+Once you have successfully configured Google Mock, the build steps are
+standard for GNU-style OSS packages.
+
+  make        # Standard makefile following GNU conventions
+  make check  # Builds and runs all tests - all should pass.
+
+Note that when building your project against Google Mock, you are building
+against Google Test as well.  There is no need to configure Google Test
+separately.
+
+### Regenerating Source Files ###
+
+Some of Google Mock's source files are generated from templates (not
+in the C++ sense) using a script.  A template file is named FOO.pump,
+where FOO is the name of the file it will generate.  For example, the
+file include/gmock/gmock-generated-actions.h.pump is used to generate
+gmock-generated-actions.h in the same directory.
+
+Normally you don't need to worry about regenerating the source files,
+unless you need to modify them.  In that case, you should modify the
+corresponding .pump files instead and run the 'pump' script (for Pump
+is Useful for Meta Programming) to regenerate them.  You can find
+pump.py in the ${GTEST_DIR}/scripts/ directory.  Read the Pump manual
+[3] for how to use it.
+
+  [3] http://code.google.com/p/googletest/wiki/PumpManual.
+
+### Contributing a Patch ###
+
+We welcome patches.  Please read the Google Mock developer's guide [4]
+for how you can contribute.  In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+  [4] http://code.google.com/p/googlemock/wiki/DevGuide
+
+Happy testing!
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-actions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-actions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-actions.h	(revision 11817)
@@ -0,0 +1,1076 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
+
+#include <algorithm>
+#include <string>
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+// To implement an action Foo, define:
+//   1. a class FooAction that implements the ActionInterface interface, and
+//   2. a factory function that creates an Action object from a
+//      const FooAction*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Action objects can now be copied like plain values.
+
+namespace internal {
+
+template <typename F1, typename F2>
+class ActionAdaptor;
+
+// BuiltInDefaultValue<T>::Get() returns the "built-in" default
+// value for type T, which is NULL when T is a pointer type, 0 when T
+// is a numeric type, false when T is bool, or "" when T is string or
+// std::string.  For any other type T, this value is undefined and the
+// function will abort the process.
+template <typename T>
+class BuiltInDefaultValue {
+ public:
+  // This function returns true iff type T has a built-in default value.
+  static bool Exists() { return false; }
+  static T Get() {
+    Assert(false, __FILE__, __LINE__,
+           "Default action undefined for the function return type.");
+    return internal::Invalid<T>();
+    // The above statement will never be reached, but is required in
+    // order for this function to compile.
+  }
+};
+
+// This partial specialization says that we use the same built-in
+// default value for T and const T.
+template <typename T>
+class BuiltInDefaultValue<const T> {
+ public:
+  static bool Exists() { return BuiltInDefaultValue<T>::Exists(); }
+  static T Get() { return BuiltInDefaultValue<T>::Get(); }
+};
+
+// This partial specialization defines the default values for pointer
+// types.
+template <typename T>
+class BuiltInDefaultValue<T*> {
+ public:
+  static bool Exists() { return true; }
+  static T* Get() { return NULL; }
+};
+
+// The following specializations define the default values for
+// specific types we care about.
+#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \
+  template <> \
+  class BuiltInDefaultValue<type> { \
+   public: \
+    static bool Exists() { return true; } \
+    static type Get() { return value; } \
+  }
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, );  // NOLINT
+#if GTEST_HAS_GLOBAL_STRING
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::string, "");
+#endif  // GTEST_HAS_GLOBAL_STRING
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, "");
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0');
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0');
+
+// There's no need for a default action for signed wchar_t, as that
+// type is the same as wchar_t for gcc, and invalid for MSVC.
+//
+// There's also no need for a default action for unsigned wchar_t, as
+// that type is the same as unsigned int for gcc, and invalid for
+// MSVC.
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U);  // NOLINT
+#endif
+
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL);  // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L);     // NOLINT
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0);
+GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0);
+
+#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_
+
+}  // namespace internal
+
+// When an unexpected function call is encountered, Google Mock will
+// let it return a default value if the user has specified one for its
+// return type, or if the return type has a built-in default value;
+// otherwise Google Mock won't know what value to return and will have
+// to abort the process.
+//
+// The DefaultValue<T> class allows a user to specify the
+// default value for a type T that is both copyable and publicly
+// destructible (i.e. anything that can be used as a function return
+// type).  The usage is:
+//
+//   // Sets the default value for type T to be foo.
+//   DefaultValue<T>::Set(foo);
+template <typename T>
+class DefaultValue {
+ public:
+  // Sets the default value for type T; requires T to be
+  // copy-constructable and have a public destructor.
+  static void Set(T x) {
+    delete value_;
+    value_ = new T(x);
+  }
+
+  // Unsets the default value for type T.
+  static void Clear() {
+    delete value_;
+    value_ = NULL;
+  }
+
+  // Returns true iff the user has set the default value for type T.
+  static bool IsSet() { return value_ != NULL; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T>::Exists();
+  }
+
+  // Returns the default value for type T if the user has set one;
+  // otherwise returns the built-in default value if there is one;
+  // otherwise aborts the process.
+  static T Get() {
+    return value_ == NULL ?
+        internal::BuiltInDefaultValue<T>::Get() : *value_;
+  }
+ private:
+  static const T* value_;
+};
+
+// This partial specialization allows a user to set default values for
+// reference types.
+template <typename T>
+class DefaultValue<T&> {
+ public:
+  // Sets the default value for type T&.
+  static void Set(T& x) {  // NOLINT
+    address_ = &x;
+  }
+
+  // Unsets the default value for type T&.
+  static void Clear() {
+    address_ = NULL;
+  }
+
+  // Returns true iff the user has set the default value for type T&.
+  static bool IsSet() { return address_ != NULL; }
+
+  // Returns true if T has a default return value set by the user or there
+  // exists a built-in default value.
+  static bool Exists() {
+    return IsSet() || internal::BuiltInDefaultValue<T&>::Exists();
+  }
+
+  // Returns the default value for type T& if the user has set one;
+  // otherwise returns the built-in default value if there is one;
+  // otherwise aborts the process.
+  static T& Get() {
+    return address_ == NULL ?
+        internal::BuiltInDefaultValue<T&>::Get() : *address_;
+  }
+ private:
+  static T* address_;
+};
+
+// This specialization allows DefaultValue<void>::Get() to
+// compile.
+template <>
+class DefaultValue<void> {
+ public:
+  static bool Exists() { return true; }
+  static void Get() {}
+};
+
+// Points to the user-set default value for type T.
+template <typename T>
+const T* DefaultValue<T>::value_ = NULL;
+
+// Points to the user-set default value for type T&.
+template <typename T>
+T* DefaultValue<T&>::address_ = NULL;
+
+// Implement this interface to define an action for function type F.
+template <typename F>
+class ActionInterface {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  ActionInterface() {}
+  virtual ~ActionInterface() {}
+
+  // Performs the action.  This method is not const, as in general an
+  // action can have side effects and be stateful.  For example, a
+  // get-the-next-element-from-the-collection action will need to
+  // remember the current element.
+  virtual Result Perform(const ArgumentTuple& args) = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface);
+};
+
+// An Action<F> is a copyable and IMMUTABLE (except by assignment)
+// object that represents an action to be taken when a mock function
+// of type F is called.  The implementation of Action<T> is just a
+// linked_ptr to const ActionInterface<T>, so copying is fairly cheap.
+// Don't inherit from Action!
+//
+// You can view an object implementing ActionInterface<F> as a
+// concrete action (including its current state), and an Action<F>
+// object as a handle to it.
+template <typename F>
+class Action {
+ public:
+  typedef typename internal::Function<F>::Result Result;
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  // Constructs a null Action.  Needed for storing Action objects in
+  // STL containers.
+  Action() : impl_(NULL) {}
+
+  // Constructs an Action from its implementation.  A NULL impl is
+  // used to represent the "do-default" action.
+  explicit Action(ActionInterface<F>* impl) : impl_(impl) {}
+
+  // Copy constructor.
+  Action(const Action& action) : impl_(action.impl_) {}
+
+  // This constructor allows us to turn an Action<Func> object into an
+  // Action<F>, as long as F's arguments can be implicitly converted
+  // to Func's and Func's return type can be implicitly converted to
+  // F's.
+  template <typename Func>
+  explicit Action(const Action<Func>& action);
+
+  // Returns true iff this is the DoDefault() action.
+  bool IsDoDefault() const { return impl_.get() == NULL; }
+
+  // Performs the action.  Note that this method is const even though
+  // the corresponding method in ActionInterface is not.  The reason
+  // is that a const Action<F> means that it cannot be re-bound to
+  // another concrete action, not that the concrete action it binds to
+  // cannot change state.  (Think of the difference between a const
+  // pointer and a pointer to const.)
+  Result Perform(const ArgumentTuple& args) const {
+    internal::Assert(
+        !IsDoDefault(), __FILE__, __LINE__,
+        "You are using DoDefault() inside a composite action like "
+        "DoAll() or WithArgs().  This is not supported for technical "
+        "reasons.  Please instead spell out the default action, or "
+        "assign the default action to an Action variable and use "
+        "the variable in various places.");
+    return impl_->Perform(args);
+  }
+
+ private:
+  template <typename F1, typename F2>
+  friend class internal::ActionAdaptor;
+
+  internal::linked_ptr<ActionInterface<F> > impl_;
+};
+
+// The PolymorphicAction class template makes it easy to implement a
+// polymorphic action (i.e. an action that can be used in mock
+// functions of than one type, e.g. Return()).
+//
+// To define a polymorphic action, a user first provides a COPYABLE
+// implementation class that has a Perform() method template:
+//
+//   class FooAction {
+//    public:
+//     template <typename Result, typename ArgumentTuple>
+//     Result Perform(const ArgumentTuple& args) const {
+//       // Processes the arguments and returns a result, using
+//       // tr1::get<N>(args) to get the N-th (0-based) argument in the tuple.
+//     }
+//     ...
+//   };
+//
+// Then the user creates the polymorphic action using
+// MakePolymorphicAction(object) where object has type FooAction.  See
+// the definition of Return(void) and SetArgumentPointee<N>(value) for
+// complete examples.
+template <typename Impl>
+class PolymorphicAction {
+ public:
+  explicit PolymorphicAction(const Impl& impl) : impl_(impl) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new MonomorphicImpl<F>(impl_));
+  }
+
+ private:
+  template <typename F>
+  class MonomorphicImpl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return impl_.template Perform<Result>(args);
+    }
+
+   private:
+    Impl impl_;
+
+    GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
+  };
+
+  Impl impl_;
+
+  GTEST_DISALLOW_ASSIGN_(PolymorphicAction);
+};
+
+// Creates an Action from its implementation and returns it.  The
+// created Action object owns the implementation.
+template <typename F>
+Action<F> MakeAction(ActionInterface<F>* impl) {
+  return Action<F>(impl);
+}
+
+// Creates a polymorphic action from its implementation.  This is
+// easier to use than the PolymorphicAction<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicAction(foo);
+// vs
+//   PolymorphicAction<TypeOfFoo>(foo);
+template <typename Impl>
+inline PolymorphicAction<Impl> MakePolymorphicAction(const Impl& impl) {
+  return PolymorphicAction<Impl>(impl);
+}
+
+namespace internal {
+
+// Allows an Action<F2> object to pose as an Action<F1>, as long as F2
+// and F1 are compatible.
+template <typename F1, typename F2>
+class ActionAdaptor : public ActionInterface<F1> {
+ public:
+  typedef typename internal::Function<F1>::Result Result;
+  typedef typename internal::Function<F1>::ArgumentTuple ArgumentTuple;
+
+  explicit ActionAdaptor(const Action<F2>& from) : impl_(from.impl_) {}
+
+  virtual Result Perform(const ArgumentTuple& args) {
+    return impl_->Perform(args);
+  }
+
+ private:
+  const internal::linked_ptr<ActionInterface<F2> > impl_;
+
+  GTEST_DISALLOW_ASSIGN_(ActionAdaptor);
+};
+
+// Implements the polymorphic Return(x) action, which can be used in
+// any function that returns the type of x, regardless of the argument
+// types.
+//
+// Note: The value passed into Return must be converted into
+// Function<F>::Result when this action is cast to Action<F> rather than
+// when that action is performed. This is important in scenarios like
+//
+// MOCK_METHOD1(Method, T(U));
+// ...
+// {
+//   Foo foo;
+//   X x(&foo);
+//   EXPECT_CALL(mock, Method(_)).WillOnce(Return(x));
+// }
+//
+// In the example above the variable x holds reference to foo which leaves
+// scope and gets destroyed.  If copying X just copies a reference to foo,
+// that copy will be left with a hanging reference.  If conversion to T
+// makes a copy of foo, the above code is safe. To support that scenario, we
+// need to make sure that the type conversion happens inside the EXPECT_CALL
+// statement, and conversion of the result of Return to Action<T(U)> is a
+// good place for that.
+//
+template <typename R>
+class ReturnAction {
+ public:
+  // Constructs a ReturnAction object from the value to be returned.
+  // 'value' is passed by value instead of by const reference in order
+  // to allow Return("string literal") to compile.
+  explicit ReturnAction(R value) : value_(value) {}
+
+  // This template type conversion operator allows Return(x) to be
+  // used in ANY function that returns x's type.
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename Function<F>::Result Result;
+    GTEST_COMPILE_ASSERT_(
+        !internal::is_reference<Result>::value,
+        use_ReturnRef_instead_of_Return_to_return_a_reference);
+    return Action<F>(new Impl<F>(value_));
+  }
+
+ private:
+  // Implements the Return(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    // The implicit cast is necessary when Result has more than one
+    // single-argument constructor (e.g. Result is std::vector<int>) and R
+    // has a type conversion operator template.  In that case, value_(value)
+    // won't compile as the compiler doesn't known which constructor of
+    // Result to call.  ImplicitCast_ forces the compiler to convert R to
+    // Result without considering explicit constructors, thus resolving the
+    // ambiguity. value_ is then initialized using its copy constructor.
+    explicit Impl(R value)
+        : value_(::testing::internal::ImplicitCast_<Result>(value)) {}
+
+    virtual Result Perform(const ArgumentTuple&) { return value_; }
+
+   private:
+    GTEST_COMPILE_ASSERT_(!internal::is_reference<Result>::value,
+                          Result_cannot_be_a_reference_type);
+    Result value_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  R value_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnAction);
+};
+
+// Implements the ReturnNull() action.
+class ReturnNullAction {
+ public:
+  // Allows ReturnNull() to be used in any pointer-returning function.
+  template <typename Result, typename ArgumentTuple>
+  static Result Perform(const ArgumentTuple&) {
+    GTEST_COMPILE_ASSERT_(internal::is_pointer<Result>::value,
+                          ReturnNull_can_be_used_to_return_a_pointer_only);
+    return NULL;
+  }
+};
+
+// Implements the Return() action.
+class ReturnVoidAction {
+ public:
+  // Allows Return() to be used in any void-returning function.
+  template <typename Result, typename ArgumentTuple>
+  static void Perform(const ArgumentTuple&) {
+    CompileAssertTypesEqual<void, Result>();
+  }
+};
+
+// Implements the polymorphic ReturnRef(x) action, which can be used
+// in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefAction {
+ public:
+  // Constructs a ReturnRefAction object from the reference to be returned.
+  explicit ReturnRefAction(T& ref) : ref_(ref) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRef(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRef(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    GTEST_COMPILE_ASSERT_(internal::is_reference<Result>::value,
+                          use_Return_instead_of_ReturnRef_to_return_a_value);
+    return Action<F>(new Impl<F>(ref_));
+  }
+
+ private:
+  // Implements the ReturnRef(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(T& ref) : ref_(ref) {}  // NOLINT
+
+    virtual Result Perform(const ArgumentTuple&) {
+      return ref_;
+    }
+
+   private:
+    T& ref_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  T& ref_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnRefAction);
+};
+
+// Implements the polymorphic ReturnRefOfCopy(x) action, which can be
+// used in any function that returns a reference to the type of x,
+// regardless of the argument types.
+template <typename T>
+class ReturnRefOfCopyAction {
+ public:
+  // Constructs a ReturnRefOfCopyAction object from the reference to
+  // be returned.
+  explicit ReturnRefOfCopyAction(const T& value) : value_(value) {}  // NOLINT
+
+  // This template type conversion operator allows ReturnRefOfCopy(x) to be
+  // used in ANY function that returns a reference to x's type.
+  template <typename F>
+  operator Action<F>() const {
+    typedef typename Function<F>::Result Result;
+    // Asserts that the function return type is a reference.  This
+    // catches the user error of using ReturnRefOfCopy(x) when Return(x)
+    // should be used, and generates some helpful error message.
+    GTEST_COMPILE_ASSERT_(
+        internal::is_reference<Result>::value,
+        use_Return_instead_of_ReturnRefOfCopy_to_return_a_value);
+    return Action<F>(new Impl<F>(value_));
+  }
+
+ private:
+  // Implements the ReturnRefOfCopy(x) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const T& value) : value_(value) {}  // NOLINT
+
+    virtual Result Perform(const ArgumentTuple&) {
+      return value_;
+    }
+
+   private:
+    T value_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const T value_;
+
+  GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction);
+};
+
+// Implements the polymorphic DoDefault() action.
+class DoDefaultAction {
+ public:
+  // This template type conversion operator allows DoDefault() to be
+  // used in any function.
+  template <typename F>
+  operator Action<F>() const { return Action<F>(NULL); }
+};
+
+// Implements the Assign action to set a given pointer referent to a
+// particular value.
+template <typename T1, typename T2>
+class AssignAction {
+ public:
+  AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& /* args */) const {
+    *ptr_ = value_;
+  }
+
+ private:
+  T1* const ptr_;
+  const T2 value_;
+
+  GTEST_DISALLOW_ASSIGN_(AssignAction);
+};
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetErrnoAndReturn action to simulate return from
+// various system calls and libc functions.
+template <typename T>
+class SetErrnoAndReturnAction {
+ public:
+  SetErrnoAndReturnAction(int errno_value, T result)
+      : errno_(errno_value),
+        result_(result) {}
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& /* args */) const {
+    errno = errno_;
+    return result_;
+  }
+
+ private:
+  const int errno_;
+  const T result_;
+
+  GTEST_DISALLOW_ASSIGN_(SetErrnoAndReturnAction);
+};
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Implements the SetArgumentPointee<N>(x) action for any function
+// whose N-th argument (0-based) is a pointer to x's type.  The
+// template parameter kIsProto is true iff type A is ProtocolMessage,
+// proto2::Message, or a sub-class of those.
+template <size_t N, typename A, bool kIsProto>
+class SetArgumentPointeeAction {
+ public:
+  // Constructs an action that sets the variable pointed to by the
+  // N-th function argument to 'value'.
+  explicit SetArgumentPointeeAction(const A& value) : value_(value) {}
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& args) const {
+    CompileAssertTypesEqual<void, Result>();
+    *::std::tr1::get<N>(args) = value_;
+  }
+
+ private:
+  const A value_;
+
+  GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
+};
+
+template <size_t N, typename Proto>
+class SetArgumentPointeeAction<N, Proto, true> {
+ public:
+  // Constructs an action that sets the variable pointed to by the
+  // N-th function argument to 'proto'.  Both ProtocolMessage and
+  // proto2::Message have the CopyFrom() method, so the same
+  // implementation works for both.
+  explicit SetArgumentPointeeAction(const Proto& proto) : proto_(new Proto) {
+    proto_->CopyFrom(proto);
+  }
+
+  template <typename Result, typename ArgumentTuple>
+  void Perform(const ArgumentTuple& args) const {
+    CompileAssertTypesEqual<void, Result>();
+    ::std::tr1::get<N>(args)->CopyFrom(*proto_);
+  }
+
+ private:
+  const internal::linked_ptr<Proto> proto_;
+
+  GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction);
+};
+
+// Implements the InvokeWithoutArgs(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  InvokeWithoutArgs(f) can be used as an
+// Action<F> as long as f's type is compatible with F (i.e. f can be
+// assigned to a tr1::function<F>).
+template <typename FunctionImpl>
+class InvokeWithoutArgsAction {
+ public:
+  // The c'tor makes a copy of function_impl (either a function
+  // pointer or a functor).
+  explicit InvokeWithoutArgsAction(FunctionImpl function_impl)
+      : function_impl_(function_impl) {}
+
+  // Allows InvokeWithoutArgs(f) to be used as any action whose type is
+  // compatible with f.
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple&) { return function_impl_(); }
+
+ private:
+  FunctionImpl function_impl_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeWithoutArgsAction);
+};
+
+// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+class InvokeMethodWithoutArgsAction {
+ public:
+  InvokeMethodWithoutArgsAction(Class* obj_ptr, MethodPtr method_ptr)
+      : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple&) const {
+    return (obj_ptr_->*method_ptr_)();
+  }
+
+ private:
+  Class* const obj_ptr_;
+  const MethodPtr method_ptr_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction);
+};
+
+// Implements the IgnoreResult(action) action.
+template <typename A>
+class IgnoreResultAction {
+ public:
+  explicit IgnoreResultAction(const A& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const {
+    // Assert statement belongs here because this is the best place to verify
+    // conditions on F. It produces the clearest error messages
+    // in most compilers.
+    // Impl really belongs in this scope as a local class but can't
+    // because MSVC produces duplicate symbols in different translation units
+    // in this case. Until MS fixes that bug we put Impl into the class scope
+    // and put the typedef both here (for use in assert statement) and
+    // in the Impl class. But both definitions must be the same.
+    typedef typename internal::Function<F>::Result Result;
+
+    // Asserts at compile time that F returns void.
+    CompileAssertTypesEqual<void, Result>();
+
+    return Action<F>(new Impl<F>(action_));
+  }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename internal::Function<F>::Result Result;
+    typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const A& action) : action_(action) {}
+
+    virtual void Perform(const ArgumentTuple& args) {
+      // Performs the action and ignores its result.
+      action_.Perform(args);
+    }
+
+   private:
+    // Type OriginalFunction is the same as F except that its return
+    // type is IgnoredValue.
+    typedef typename internal::Function<F>::MakeResultIgnoredValue
+        OriginalFunction;
+
+    const Action<OriginalFunction> action_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const A action_;
+
+  GTEST_DISALLOW_ASSIGN_(IgnoreResultAction);
+};
+
+// A ReferenceWrapper<T> object represents a reference to type T,
+// which can be either const or not.  It can be explicitly converted
+// from, and implicitly converted to, a T&.  Unlike a reference,
+// ReferenceWrapper<T> can be copied and can survive template type
+// inference.  This is used to support by-reference arguments in the
+// InvokeArgument<N>(...) action.  The idea was from "reference
+// wrappers" in tr1, which we don't have in our source tree yet.
+template <typename T>
+class ReferenceWrapper {
+ public:
+  // Constructs a ReferenceWrapper<T> object from a T&.
+  explicit ReferenceWrapper(T& l_value) : pointer_(&l_value) {}  // NOLINT
+
+  // Allows a ReferenceWrapper<T> object to be implicitly converted to
+  // a T&.
+  operator T&() const { return *pointer_; }
+ private:
+  T* pointer_;
+};
+
+// Allows the expression ByRef(x) to be printed as a reference to x.
+template <typename T>
+void PrintTo(const ReferenceWrapper<T>& ref, ::std::ostream* os) {
+  T& value = ref;
+  UniversalPrinter<T&>::Print(value, os);
+}
+
+// Does two actions sequentially.  Used for implementing the DoAll(a1,
+// a2, ...) action.
+template <typename Action1, typename Action2>
+class DoBothAction {
+ public:
+  DoBothAction(Action1 action1, Action2 action2)
+      : action1_(action1), action2_(action2) {}
+
+  // This template type conversion operator allows DoAll(a1, ..., a_n)
+  // to be used in ANY function of compatible type.
+  template <typename F>
+  operator Action<F>() const {
+    return Action<F>(new Impl<F>(action1_, action2_));
+  }
+
+ private:
+  // Implements the DoAll(...) action for a particular function type F.
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+    typedef typename Function<F>::MakeResultVoid VoidResult;
+
+    Impl(const Action<VoidResult>& action1, const Action<F>& action2)
+        : action1_(action1), action2_(action2) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      action1_.Perform(args);
+      return action2_.Perform(args);
+    }
+
+   private:
+    const Action<VoidResult> action1_;
+    const Action<F> action2_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  Action1 action1_;
+  Action2 action2_;
+
+  GTEST_DISALLOW_ASSIGN_(DoBothAction);
+};
+
+}  // namespace internal
+
+// An Unused object can be implicitly constructed from ANY value.
+// This is handy when defining actions that ignore some or all of the
+// mock function arguments.  For example, given
+//
+//   MOCK_METHOD3(Foo, double(const string& label, double x, double y));
+//   MOCK_METHOD3(Bar, double(int index, double x, double y));
+//
+// instead of
+//
+//   double DistanceToOriginWithLabel(const string& label, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   double DistanceToOriginWithIndex(int index, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXEPCT_CALL(mock, Foo("abc", _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithLabel));
+//   EXEPCT_CALL(mock, Bar(5, _, _))
+//       .WillOnce(Invoke(DistanceToOriginWithIndex));
+//
+// you could write
+//
+//   // We can declare any uninteresting argument as Unused.
+//   double DistanceToOrigin(Unused, double x, double y) {
+//     return sqrt(x*x + y*y);
+//   }
+//   ...
+//   EXEPCT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin));
+//   EXEPCT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin));
+typedef internal::IgnoredValue Unused;
+
+// This constructor allows us to turn an Action<From> object into an
+// Action<To>, as long as To's arguments can be implicitly converted
+// to From's and From's return type cann be implicitly converted to
+// To's.
+template <typename To>
+template <typename From>
+Action<To>::Action(const Action<From>& from)
+    : impl_(new internal::ActionAdaptor<To, From>(from)) {}
+
+// Creates an action that returns 'value'.  'value' is passed by value
+// instead of const reference - otherwise Return("string literal")
+// will trigger a compiler error about using array as initializer.
+template <typename R>
+internal::ReturnAction<R> Return(R value) {
+  return internal::ReturnAction<R>(value);
+}
+
+// Creates an action that returns NULL.
+inline PolymorphicAction<internal::ReturnNullAction> ReturnNull() {
+  return MakePolymorphicAction(internal::ReturnNullAction());
+}
+
+// Creates an action that returns from a void function.
+inline PolymorphicAction<internal::ReturnVoidAction> Return() {
+  return MakePolymorphicAction(internal::ReturnVoidAction());
+}
+
+// Creates an action that returns the reference to a variable.
+template <typename R>
+inline internal::ReturnRefAction<R> ReturnRef(R& x) {  // NOLINT
+  return internal::ReturnRefAction<R>(x);
+}
+
+// Creates an action that returns the reference to a copy of the
+// argument.  The copy is created when the action is constructed and
+// lives as long as the action.
+template <typename R>
+inline internal::ReturnRefOfCopyAction<R> ReturnRefOfCopy(const R& x) {
+  return internal::ReturnRefOfCopyAction<R>(x);
+}
+
+// Creates an action that does the default action for the give mock function.
+inline internal::DoDefaultAction DoDefault() {
+  return internal::DoDefaultAction();
+}
+
+// Creates an action that sets the variable pointed by the N-th
+// (0-based) function argument to 'value'.
+template <size_t N, typename T>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<
+    N, T, internal::IsAProtocolMessage<T>::value> >
+SetArgPointee(const T& x) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, T, internal::IsAProtocolMessage<T>::value>(x));
+}
+
+#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN)
+// This overload allows SetArgPointee() to accept a string literal.
+// GCC prior to the version 4.0 and Symbian C++ compiler cannot distinguish
+// this overload from the templated version and emit a compile error.
+template <size_t N>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<N, const char*, false> >
+SetArgPointee(const char* p) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, const char*, false>(p));
+}
+
+template <size_t N>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<N, const wchar_t*, false> >
+SetArgPointee(const wchar_t* p) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, const wchar_t*, false>(p));
+}
+#endif
+
+// The following version is DEPRECATED.
+template <size_t N, typename T>
+PolymorphicAction<
+  internal::SetArgumentPointeeAction<
+    N, T, internal::IsAProtocolMessage<T>::value> >
+SetArgumentPointee(const T& x) {
+  return MakePolymorphicAction(internal::SetArgumentPointeeAction<
+      N, T, internal::IsAProtocolMessage<T>::value>(x));
+}
+
+// Creates an action that sets a pointer referent to a given value.
+template <typename T1, typename T2>
+PolymorphicAction<internal::AssignAction<T1, T2> > Assign(T1* ptr, T2 val) {
+  return MakePolymorphicAction(internal::AssignAction<T1, T2>(ptr, val));
+}
+
+#if !GTEST_OS_WINDOWS_MOBILE
+
+// Creates an action that sets errno and returns the appropriate error.
+template <typename T>
+PolymorphicAction<internal::SetErrnoAndReturnAction<T> >
+SetErrnoAndReturn(int errval, T result) {
+  return MakePolymorphicAction(
+      internal::SetErrnoAndReturnAction<T>(errval, result));
+}
+
+#endif  // !GTEST_OS_WINDOWS_MOBILE
+
+// Various overloads for InvokeWithoutArgs().
+
+// Creates an action that invokes 'function_impl' with no argument.
+template <typename FunctionImpl>
+PolymorphicAction<internal::InvokeWithoutArgsAction<FunctionImpl> >
+InvokeWithoutArgs(FunctionImpl function_impl) {
+  return MakePolymorphicAction(
+      internal::InvokeWithoutArgsAction<FunctionImpl>(function_impl));
+}
+
+// Creates an action that invokes the given method on the given object
+// with no argument.
+template <class Class, typename MethodPtr>
+PolymorphicAction<internal::InvokeMethodWithoutArgsAction<Class, MethodPtr> >
+InvokeWithoutArgs(Class* obj_ptr, MethodPtr method_ptr) {
+  return MakePolymorphicAction(
+      internal::InvokeMethodWithoutArgsAction<Class, MethodPtr>(
+          obj_ptr, method_ptr));
+}
+
+// Creates an action that performs an_action and throws away its
+// result.  In other words, it changes the return type of an_action to
+// void.  an_action MUST NOT return void, or the code won't compile.
+template <typename A>
+inline internal::IgnoreResultAction<A> IgnoreResult(const A& an_action) {
+  return internal::IgnoreResultAction<A>(an_action);
+}
+
+// Creates a reference wrapper for the given L-value.  If necessary,
+// you can explicitly specify the type of the reference.  For example,
+// suppose 'derived' is an object of type Derived, ByRef(derived)
+// would wrap a Derived&.  If you want to wrap a const Base& instead,
+// where Base is a base class of Derived, just write:
+//
+//   ByRef<const Base>(derived)
+template <typename T>
+inline internal::ReferenceWrapper<T> ByRef(T& l_value) {  // NOLINT
+  return internal::ReferenceWrapper<T>(l_value);
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-cardinalities.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-cardinalities.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-cardinalities.h	(revision 11817)
@@ -0,0 +1,146 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used cardinalities.  More
+// cardinalities can be defined by the user implementing the
+// CardinalityInterface interface if necessary.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
+
+#include <limits.h>
+#include <ostream>  // NOLINT
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// To implement a cardinality Foo, define:
+//   1. a class FooCardinality that implements the
+//      CardinalityInterface interface, and
+//   2. a factory function that creates a Cardinality object from a
+//      const FooCardinality*.
+//
+// The two-level delegation design follows that of Matcher, providing
+// consistency for extension developers.  It also eases ownership
+// management as Cardinality objects can now be copied like plain values.
+
+// The implementation of a cardinality.
+class CardinalityInterface {
+ public:
+  virtual ~CardinalityInterface() {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return 0; }
+  virtual int ConservativeUpperBound() const { return INT_MAX; }
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  virtual bool IsSatisfiedByCallCount(int call_count) const = 0;
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  virtual bool IsSaturatedByCallCount(int call_count) const = 0;
+
+  // Describes self to an ostream.
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+};
+
+// A Cardinality is a copyable and IMMUTABLE (except by assignment)
+// object that specifies how many times a mock function is expected to
+// be called.  The implementation of Cardinality is just a linked_ptr
+// to const CardinalityInterface, so copying is fairly cheap.
+// Don't inherit from Cardinality!
+class Cardinality {
+ public:
+  // Constructs a null cardinality.  Needed for storing Cardinality
+  // objects in STL containers.
+  Cardinality() {}
+
+  // Constructs a Cardinality from its implementation.
+  explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {}
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); }
+  int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); }
+
+  // Returns true iff call_count calls will satisfy this cardinality.
+  bool IsSatisfiedByCallCount(int call_count) const {
+    return impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Returns true iff call_count calls will saturate this cardinality.
+  bool IsSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count);
+  }
+
+  // Returns true iff call_count calls will over-saturate this
+  // cardinality, i.e. exceed the maximum number of allowed calls.
+  bool IsOverSaturatedByCallCount(int call_count) const {
+    return impl_->IsSaturatedByCallCount(call_count) &&
+        !impl_->IsSatisfiedByCallCount(call_count);
+  }
+
+  // Describes self to an ostream
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the given actual call count to an ostream.
+  static void DescribeActualCallCountTo(int actual_call_count,
+                                        ::std::ostream* os);
+ private:
+  internal::linked_ptr<const CardinalityInterface> impl_;
+};
+
+// Creates a cardinality that allows at least n calls.
+Cardinality AtLeast(int n);
+
+// Creates a cardinality that allows at most n calls.
+Cardinality AtMost(int n);
+
+// Creates a cardinality that allows any number of calls.
+Cardinality AnyNumber();
+
+// Creates a cardinality that allows between min and max calls.
+Cardinality Between(int min, int max);
+
+// Creates a cardinality that allows exactly n calls.
+Cardinality Exactly(int n);
+
+// Creates a cardinality from its implementation.
+inline Cardinality MakeCardinality(const CardinalityInterface* c) {
+  return Cardinality(c);
+}
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-actions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-actions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-actions.h	(revision 11817)
@@ -0,0 +1,2419 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic actions.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
+
+#include "gmock/gmock-actions.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+namespace internal {
+
+// InvokeHelper<F> knows how to unpack an N-tuple and invoke an N-ary
+// function or method with the unpacked values, where F is a function
+// type that takes N arguments.
+template <typename Result, typename ArgumentTuple>
+class InvokeHelper;
+
+template <typename R>
+class InvokeHelper<R, ::std::tr1::tuple<> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<>&) {
+    return function();
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<>&) {
+    return (obj_ptr->*method_ptr)();
+  }
+};
+
+template <typename R, typename A1>
+class InvokeHelper<R, ::std::tr1::tuple<A1> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2,
+      A3>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3,
+      A4>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6,
+                            A7>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7, A8>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7,
+                            A8>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args), get<7>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7, A8, A9>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8,
+                            A9>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args), get<7>(args),
+        get<8>(args));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+class InvokeHelper<R, ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+    A10> > {
+ public:
+  template <typename Function>
+  static R Invoke(Function function, const ::std::tr1::tuple<A1, A2, A3, A4,
+      A5, A6, A7, A8, A9, A10>& args) {
+    using ::std::tr1::get;
+    return function(get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        get<9>(args));
+  }
+
+  template <class Class, typename MethodPtr>
+  static R InvokeMethod(Class* obj_ptr,
+                        MethodPtr method_ptr,
+                        const ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8,
+                            A9, A10>& args) {
+    using ::std::tr1::get;
+    return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), get<2>(args),
+        get<3>(args), get<4>(args), get<5>(args), get<6>(args), get<7>(args),
+        get<8>(args), get<9>(args));
+  }
+};
+
+// CallableHelper has static methods for invoking "callables",
+// i.e. function pointers and functors.  It uses overloading to
+// provide a uniform interface for invoking different kinds of
+// callables.  In particular, you can use:
+//
+//   CallableHelper<R>::Call(callable, a1, a2, ..., an)
+//
+// to invoke an n-ary callable, where R is its return type.  If an
+// argument, say a2, needs to be passed by reference, you should write
+// ByRef(a2) instead of a2 in the above expression.
+template <typename R>
+class CallableHelper {
+ public:
+  // Calls a nullary callable.
+  template <typename Function>
+  static R Call(Function function) { return function(); }
+
+  // Calls a unary callable.
+
+  // We deliberately pass a1 by value instead of const reference here
+  // in case it is a C-string literal.  If we had declared the
+  // parameter as 'const A1& a1' and write Call(function, "Hi"), the
+  // compiler would've thought A1 is 'char[3]', which causes trouble
+  // when you need to copy a value of type A1.  By declaring the
+  // parameter as 'A1 a1', the compiler will correctly infer that A1
+  // is 'const char*' when it sees Call(function, "Hi").
+  //
+  // Since this function is defined inline, the compiler can get rid
+  // of the copying of the arguments.  Therefore the performance won't
+  // be hurt.
+  template <typename Function, typename A1>
+  static R Call(Function function, A1 a1) { return function(a1); }
+
+  // Calls a binary callable.
+  template <typename Function, typename A1, typename A2>
+  static R Call(Function function, A1 a1, A2 a2) {
+    return function(a1, a2);
+  }
+
+  // Calls a ternary callable.
+  template <typename Function, typename A1, typename A2, typename A3>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3) {
+    return function(a1, a2, a3);
+  }
+
+  // Calls a 4-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4) {
+    return function(a1, a2, a3, a4);
+  }
+
+  // Calls a 5-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+    return function(a1, a2, a3, a4, a5);
+  }
+
+  // Calls a 6-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+    return function(a1, a2, a3, a4, a5, a6);
+  }
+
+  // Calls a 7-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7) {
+    return function(a1, a2, a3, a4, a5, a6, a7);
+  }
+
+  // Calls a 8-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7, typename A8>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7, A8 a8) {
+    return function(a1, a2, a3, a4, a5, a6, a7, a8);
+  }
+
+  // Calls a 9-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7, typename A8,
+      typename A9>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7, A8 a8, A9 a9) {
+    return function(a1, a2, a3, a4, a5, a6, a7, a8, a9);
+  }
+
+  // Calls a 10-ary callable.
+  template <typename Function, typename A1, typename A2, typename A3,
+      typename A4, typename A5, typename A6, typename A7, typename A8,
+      typename A9, typename A10>
+  static R Call(Function function, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6,
+      A7 a7, A8 a8, A9 a9, A10 a10) {
+    return function(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
+  }
+
+};  // class CallableHelper
+
+// An INTERNAL macro for extracting the type of a tuple field.  It's
+// subject to change without notice - DO NOT USE IN USER CODE!
+#define GMOCK_FIELD_(Tuple, N) \
+    typename ::std::tr1::tuple_element<N, Tuple>::type
+
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::type is the
+// type of an n-ary function whose i-th (1-based) argument type is the
+// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple
+// type, and whose return type is Result.  For example,
+//   SelectArgs<int, ::std::tr1::tuple<bool, char, double, long>, 0, 3>::type
+// is int(bool, long).
+//
+// SelectArgs<Result, ArgumentTuple, k1, k2, ..., k_n>::Select(args)
+// returns the selected fields (k1, k2, ..., k_n) of args as a tuple.
+// For example,
+//   SelectArgs<int, ::std::tr1::tuple<bool, char, double>, 2, 0>::Select(
+//       ::std::tr1::make_tuple(true, 'a', 2.5))
+// returns ::std::tr1::tuple (2.5, true).
+//
+// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be
+// in the range [0, 10].  Duplicates are allowed and they don't have
+// to be in an ascending or descending order.
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8, int k9, int k10>
+class SelectArgs {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9),
+      GMOCK_FIELD_(ArgumentTuple, k10));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args), get<k9>(args), get<k10>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple>
+class SelectArgs<Result, ArgumentTuple,
+                 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type();
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& /* args */) {
+    using ::std::tr1::get;
+    return SelectedArgs();
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, -1, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, -1, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, -1, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, k8, -1, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args));
+  }
+};
+
+template <typename Result, typename ArgumentTuple, int k1, int k2, int k3,
+    int k4, int k5, int k6, int k7, int k8, int k9>
+class SelectArgs<Result, ArgumentTuple,
+                 k1, k2, k3, k4, k5, k6, k7, k8, k9, -1> {
+ public:
+  typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1),
+      GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3),
+      GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5),
+      GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7),
+      GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9));
+  typedef typename Function<type>::ArgumentTuple SelectedArgs;
+  static SelectedArgs Select(const ArgumentTuple& args) {
+    using ::std::tr1::get;
+    return SelectedArgs(get<k1>(args), get<k2>(args), get<k3>(args),
+        get<k4>(args), get<k5>(args), get<k6>(args), get<k7>(args),
+        get<k8>(args), get<k9>(args));
+  }
+};
+
+#undef GMOCK_FIELD_
+
+// Implements the WithArgs action.
+template <typename InnerAction, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1, int k10 = -1>
+class WithArgsAction {
+ public:
+  explicit WithArgsAction(const InnerAction& action) : action_(action) {}
+
+  template <typename F>
+  operator Action<F>() const { return MakeAction(new Impl<F>(action_)); }
+
+ private:
+  template <typename F>
+  class Impl : public ActionInterface<F> {
+   public:
+    typedef typename Function<F>::Result Result;
+    typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+
+    explicit Impl(const InnerAction& action) : action_(action) {}
+
+    virtual Result Perform(const ArgumentTuple& args) {
+      return action_.Perform(SelectArgs<Result, ArgumentTuple, k1, k2, k3, k4,
+          k5, k6, k7, k8, k9, k10>::Select(args));
+    }
+
+   private:
+    typedef typename SelectArgs<Result, ArgumentTuple,
+        k1, k2, k3, k4, k5, k6, k7, k8, k9, k10>::type InnerFunctionType;
+
+    Action<InnerFunctionType> action_;
+  };
+
+  const InnerAction action_;
+
+  GTEST_DISALLOW_ASSIGN_(WithArgsAction);
+};
+
+// A macro from the ACTION* family (defined later in this file)
+// defines an action that can be used in a mock function.  Typically,
+// these actions only care about a subset of the arguments of the mock
+// function.  For example, if such an action only uses the second
+// argument, it can be used in any mock function that takes >= 2
+// arguments where the type of the second argument is compatible.
+//
+// Therefore, the action implementation must be prepared to take more
+// arguments than it needs.  The ExcessiveArg type is used to
+// represent those excessive arguments.  In order to keep the compiler
+// error messages tractable, we define it in the testing namespace
+// instead of testing::internal.  However, this is an INTERNAL TYPE
+// and subject to change without notice, so a user MUST NOT USE THIS
+// TYPE DIRECTLY.
+struct ExcessiveArg {};
+
+// A helper class needed for implementing the ACTION* macros.
+template <typename Result, class Impl>
+class ActionHelper {
+ public:
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<>(args, ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0>(args, get<0>(args),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1>(args, get<0>(args),
+        get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2>(args, get<0>(args),
+        get<1>(args), get<2>(args), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2,
+      A3>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3>(args, get<0>(args),
+        get<1>(args), get<2>(args), get<3>(args), ExcessiveArg(),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3,
+      A4>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        get<5>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6>(args,
+        get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args),
+        get<5>(args), get<6>(args), ExcessiveArg(), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6,
+        A7>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), ExcessiveArg(),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7, typename A8>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7, A8>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7,
+        A8>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        ExcessiveArg());
+  }
+
+  template <typename A0, typename A1, typename A2, typename A3, typename A4,
+      typename A5, typename A6, typename A7, typename A8, typename A9>
+  static Result Perform(Impl* impl, const ::std::tr1::tuple<A0, A1, A2, A3, A4,
+      A5, A6, A7, A8, A9>& args) {
+    using ::std::tr1::get;
+    return impl->template gmock_PerformImpl<A0, A1, A2, A3, A4, A5, A6, A7, A8,
+        A9>(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args),
+        get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args),
+        get<9>(args));
+  }
+};
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// WithArgs<N1, N2, ..., Nk>(an_action) creates an action that passes
+// the selected arguments of the mock function to an_action and
+// performs it.  It serves as an adaptor between actions with
+// different argument lists.  C++ doesn't support default arguments for
+// function templates, so we have to overload it.
+template <int k1, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1>(action);
+}
+
+template <int k1, int k2, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2>(action);
+}
+
+template <int k1, int k2, int k3, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3>(action);
+}
+
+template <int k1, int k2, int k3, int k4, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
+    typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6,
+      k7>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7,
+      k8>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8, k9>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9>(action);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, int k10, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+    k9, k10>
+WithArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9, k10>(action);
+}
+
+// Creates an action that does actions a1, a2, ..., sequentially in
+// each invocation.
+template <typename Action1, typename Action2>
+inline internal::DoBothAction<Action1, Action2>
+DoAll(Action1 a1, Action2 a2) {
+  return internal::DoBothAction<Action1, Action2>(a1, a2);
+}
+
+template <typename Action1, typename Action2, typename Action3>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    Action3> >
+DoAll(Action1 a1, Action2 a2, Action3 a3) {
+  return DoAll(a1, DoAll(a2, a3));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, Action4> > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4) {
+  return DoAll(a1, DoAll(a2, a3, a4));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    Action5> > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, Action6> > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    Action7> > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, Action8> > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8, typename Action9>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
+    Action9> > > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8, Action9 a9) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9));
+}
+
+template <typename Action1, typename Action2, typename Action3,
+    typename Action4, typename Action5, typename Action6, typename Action7,
+    typename Action8, typename Action9, typename Action10>
+inline internal::DoBothAction<Action1, internal::DoBothAction<Action2,
+    internal::DoBothAction<Action3, internal::DoBothAction<Action4,
+    internal::DoBothAction<Action5, internal::DoBothAction<Action6,
+    internal::DoBothAction<Action7, internal::DoBothAction<Action8,
+    internal::DoBothAction<Action9, Action10> > > > > > > > >
+DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6,
+    Action7 a7, Action8 a8, Action9 a9, Action10 a10) {
+  return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9, a10));
+}
+
+}  // namespace testing
+
+// The ACTION* family of macros can be used in a namespace scope to
+// define custom actions easily.  The syntax:
+//
+//   ACTION(name) { statements; }
+//
+// will define an action with the given name that executes the
+// statements.  The value returned by the statements will be used as
+// the return value of the action.  Inside the statements, you can
+// refer to the K-th (0-based) argument of the mock function by
+// 'argK', and refer to its type by 'argK_type'.  For example:
+//
+//   ACTION(IncrementArg1) {
+//     arg1_type temp = arg1;
+//     return ++(*temp);
+//   }
+//
+// allows you to write
+//
+//   ...WillOnce(IncrementArg1());
+//
+// You can also refer to the entire argument tuple and its type by
+// 'args' and 'args_type', and refer to the mock function type and its
+// return type by 'function_type' and 'return_type'.
+//
+// Note that you don't need to specify the types of the mock function
+// arguments.  However rest assured that your code is still type-safe:
+// you'll get a compiler error if *arg1 doesn't support the ++
+// operator, or if the type of ++(*arg1) isn't compatible with the
+// mock function's return type, for example.
+//
+// Sometimes you'll want to parameterize the action.   For that you can use
+// another macro:
+//
+//   ACTION_P(name, param_name) { statements; }
+//
+// For example:
+//
+//   ACTION_P(Add, n) { return arg0 + n; }
+//
+// will allow you to write:
+//
+//   ...WillOnce(Add(5));
+//
+// Note that you don't need to provide the type of the parameter
+// either.  If you need to reference the type of a parameter named
+// 'foo', you can write 'foo_type'.  For example, in the body of
+// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type
+// of 'n'.
+//
+// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support
+// multi-parameter actions.
+//
+// For the purpose of typing, you can view
+//
+//   ACTION_Pk(Foo, p1, ..., pk) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooActionPk<p1_type, ..., pk_type> Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// In particular, you can provide the template type arguments
+// explicitly when invoking Foo(), as in Foo<long, bool>(5, false);
+// although usually you can rely on the compiler to infer the types
+// for you automatically.  You can assign the result of expression
+// Foo(p1, ..., pk) to a variable of type FooActionPk<p1_type, ...,
+// pk_type>.  This can be useful when composing actions.
+//
+// You can also overload actions with different numbers of parameters:
+//
+//   ACTION_P(Plus, a) { ... }
+//   ACTION_P2(Plus, a, b) { ... }
+//
+// While it's tempting to always use the ACTION* macros when defining
+// a new action, you should also consider implementing ActionInterface
+// or using MakePolymorphicAction() instead, especially if you need to
+// use the action a lot.  While these approaches require more work,
+// they give you more control on the types of the mock function
+// arguments and the action parameters, which in general leads to
+// better compiler error messages that pay off in the long run.  They
+// also allow overloading actions based on parameter types (as opposed
+// to just based on the number of parameters).
+//
+// CAVEAT:
+//
+// ACTION*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using ACTION*() inside
+// a function.
+//
+// MORE INFORMATION:
+//
+// To learn more about using these macros, please search for 'ACTION'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+// An internal macro needed for implementing ACTION*().
+#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\
+    const args_type& args GTEST_ATTRIBUTE_UNUSED_,\
+    arg0_type arg0 GTEST_ATTRIBUTE_UNUSED_,\
+    arg1_type arg1 GTEST_ATTRIBUTE_UNUSED_,\
+    arg2_type arg2 GTEST_ATTRIBUTE_UNUSED_,\
+    arg3_type arg3 GTEST_ATTRIBUTE_UNUSED_,\
+    arg4_type arg4 GTEST_ATTRIBUTE_UNUSED_,\
+    arg5_type arg5 GTEST_ATTRIBUTE_UNUSED_,\
+    arg6_type arg6 GTEST_ATTRIBUTE_UNUSED_,\
+    arg7_type arg7 GTEST_ATTRIBUTE_UNUSED_,\
+    arg8_type arg8 GTEST_ATTRIBUTE_UNUSED_,\
+    arg9_type arg9 GTEST_ATTRIBUTE_UNUSED_
+
+// Sometimes you want to give an action explicit template parameters
+// that cannot be inferred from its value parameters.  ACTION() and
+// ACTION_P*() don't support that.  ACTION_TEMPLATE() remedies that
+// and can be viewed as an extension to ACTION() and ACTION_P*().
+//
+// The syntax:
+//
+//   ACTION_TEMPLATE(ActionName,
+//                   HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m),
+//                   AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; }
+//
+// defines an action template that takes m explicit template
+// parameters and n value parameters.  name_i is the name of the i-th
+// template parameter, and kind_i specifies whether it's a typename,
+// an integral constant, or a template.  p_i is the name of the i-th
+// value parameter.
+//
+// Example:
+//
+//   // DuplicateArg<k, T>(output) converts the k-th argument of the mock
+//   // function to type T and copies it to *output.
+//   ACTION_TEMPLATE(DuplicateArg,
+//                   HAS_2_TEMPLATE_PARAMS(int, k, typename, T),
+//                   AND_1_VALUE_PARAMS(output)) {
+//     *output = T(std::tr1::get<k>(args));
+//   }
+//   ...
+//     int n;
+//     EXPECT_CALL(mock, Foo(_, _))
+//         .WillOnce(DuplicateArg<1, unsigned char>(&n));
+//
+// To create an instance of an action template, write:
+//
+//   ActionName<t1, ..., t_m>(v1, ..., v_n)
+//
+// where the ts are the template arguments and the vs are the value
+// arguments.  The value argument types are inferred by the compiler.
+// If you want to explicitly specify the value argument types, you can
+// provide additional template arguments:
+//
+//   ActionName<t1, ..., t_m, u1, ..., u_k>(v1, ..., v_n)
+//
+// where u_i is the desired type of v_i.
+//
+// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the
+// number of value parameters, but not on the number of template
+// parameters.  Without the restriction, the meaning of the following
+// is unclear:
+//
+//   OverloadedAction<int, bool>(x);
+//
+// Are we using a single-template-parameter action where 'bool' refers
+// to the type of x, or are we using a two-template-parameter action
+// where the compiler is asked to infer the type of x?
+//
+// Implementation notes:
+//
+// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and
+// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for
+// implementing ACTION_TEMPLATE.  The main trick we use is to create
+// new macro invocations when expanding a macro.  For example, we have
+//
+//   #define ACTION_TEMPLATE(name, template_params, value_params)
+//       ... GMOCK_INTERNAL_DECL_##template_params ...
+//
+// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...)
+// to expand to
+//
+//       ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ...
+//
+// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the
+// preprocessor will continue to expand it to
+//
+//       ... typename T ...
+//
+// This technique conforms to the C++ standard and is portable.  It
+// allows us to implement action templates using O(N) code, where N is
+// the maximum number of template/value parameters supported.  Without
+// using it, we'd have to devote O(N^2) amount of code to implement all
+// combinations of m and n.
+
+// Declares the template parameters.
+#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0
+#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1) kind0 name0, kind1 name1
+#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2) kind0 name0, kind1 name1, kind2 name2
+#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3) kind0 name0, kind1 name1, kind2 name2, \
+    kind3 name3
+#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4) kind0 name0, kind1 name1, \
+    kind2 name2, kind3 name3, kind4 name4
+#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5) kind0 name0, \
+    kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5
+#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6) kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \
+    kind5 name5, kind6 name6
+#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7) kind0 name0, kind1 name1, kind2 name2, kind3 name3, \
+    kind4 name4, kind5 name5, kind6 name6, kind7 name7
+#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7, kind8, name8) kind0 name0, kind1 name1, kind2 name2, \
+    kind3 name3, kind4 name4, kind5 name5, kind6 name6, kind7 name7, \
+    kind8 name8
+#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6, kind7, name7, kind8, name8, kind9, name9) kind0 name0, \
+    kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5, \
+    kind6 name6, kind7 name7, kind8 name8, kind9 name9
+
+// Lists the template parameters.
+#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0
+#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1) name0, name1
+#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2) name0, name1, name2
+#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3) name0, name1, name2, name3
+#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4) name0, name1, name2, name3, \
+    name4
+#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5) name0, name1, \
+    name2, name3, name4, name5
+#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6) name0, name1, name2, name3, name4, name5, name6
+#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7) name0, name1, name2, name3, name4, name5, name6, name7
+#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \
+    kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \
+    kind7, name7, kind8, name8) name0, name1, name2, name3, name4, name5, \
+    name6, name7, name8
+#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \
+    name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \
+    name6, kind7, name7, kind8, name8, kind9, name9) name0, name1, name2, \
+    name3, name4, name5, name6, name7, name8, name9
+
+// Declares the types of value parameters.
+#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) , \
+    typename p0##_type, typename p1##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , \
+    typename p0##_type, typename p1##_type, typename p2##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \
+    typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type, typename p7##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8) , typename p0##_type, typename p1##_type, typename p2##_type, \
+    typename p3##_type, typename p4##_type, typename p5##_type, \
+    typename p6##_type, typename p7##_type, typename p8##_type
+#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8, p9) , typename p0##_type, typename p1##_type, \
+    typename p2##_type, typename p3##_type, typename p4##_type, \
+    typename p5##_type, typename p6##_type, typename p7##_type, \
+    typename p8##_type, typename p9##_type
+
+// Initializes the value parameters.
+#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS()\
+    ()
+#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0)\
+    (p0##_type gmock_p0) : p0(gmock_p0)
+#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1)\
+    (p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), p1(gmock_p1)
+#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2)
+#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3)
+#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4)
+#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5)
+#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6)
+#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7)
+#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8)
+#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9)\
+    (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+        p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+        p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+        p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8), p9(gmock_p9)
+
+// Declares the fields for storing the value parameters.
+#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0;
+#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0; \
+    p1##_type p1;
+#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0; \
+    p1##_type p1; p2##_type p2;
+#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0; \
+    p1##_type p1; p2##_type p2; p3##_type p3;
+#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \
+    p4) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4;
+#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \
+    p5) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5;
+#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5; p6##_type p6;
+#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \
+    p5##_type p5; p6##_type p6; p7##_type p7;
+#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \
+    p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8;
+#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \
+    p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; \
+    p9##_type p9;
+
+// Lists the value parameters.
+#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0
+#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1
+#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2
+#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3
+#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) p0, p1, \
+    p2, p3, p4
+#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) p0, \
+    p1, p2, p3, p4, p5
+#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0, p1, p2, p3, p4, p5, p6
+#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0, p1, p2, p3, p4, p5, p6, p7
+#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0, p1, p2, p3, p4, p5, p6, p7, p8
+#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0, p1, p2, p3, p4, p5, p6, p7, p8, p9
+
+// Lists the value parameter types.
+#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) , p0##_type, \
+    p1##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , p0##_type, \
+    p1##_type, p2##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \
+    p0##_type, p1##_type, p2##_type, p3##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \
+    p0##_type, p1##_type, p2##_type, p3##_type, p4##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \
+    p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \
+    p6##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type, p8##_type
+#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6, p7, p8, p9) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+    p5##_type, p6##_type, p7##_type, p8##_type, p9##_type
+
+// Declares the value parameters.
+#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0
+#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0, \
+    p1##_type p1
+#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0, \
+    p1##_type p1, p2##_type p2
+#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0, \
+    p1##_type p1, p2##_type p2, p3##_type p3
+#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \
+    p4) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4
+#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \
+    p5) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5
+#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \
+    p6) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5, p6##_type p6
+#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \
+    p5##_type p5, p6##_type p6, p7##_type p7
+#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+    p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8
+#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+    p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+    p9##_type p9
+
+// The suffix of the class template implementing the action template.
+#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS()
+#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P
+#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2
+#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3
+#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4
+#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5
+#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6
+#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7
+#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7) P8
+#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8) P9
+#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \
+    p7, p8, p9) P10
+
+// The name of the class template implementing the action template.
+#define GMOCK_ACTION_CLASS_(name, value_params)\
+    GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params)
+
+#define ACTION_TEMPLATE(name, template_params, value_params)\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  class GMOCK_ACTION_CLASS_(name, value_params) {\
+   public:\
+    GMOCK_ACTION_CLASS_(name, value_params)\
+        GMOCK_INTERNAL_INIT_##value_params {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      GMOCK_INTERNAL_DEFN_##value_params\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(\
+          new gmock_Impl<F>(GMOCK_INTERNAL_LIST_##value_params));\
+    }\
+    GMOCK_INTERNAL_DEFN_##value_params\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\
+  };\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  inline GMOCK_ACTION_CLASS_(name, value_params)<\
+      GMOCK_INTERNAL_LIST_##template_params\
+      GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\
+          GMOCK_INTERNAL_DECL_##value_params) {\
+    return GMOCK_ACTION_CLASS_(name, value_params)<\
+        GMOCK_INTERNAL_LIST_##template_params\
+        GMOCK_INTERNAL_LIST_TYPE_##value_params>(\
+            GMOCK_INTERNAL_LIST_##value_params);\
+  }\
+  template <GMOCK_INTERNAL_DECL_##template_params\
+            GMOCK_INTERNAL_DECL_TYPE_##value_params>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type,\
+      typename arg3_type, typename arg4_type, typename arg5_type,\
+      typename arg6_type, typename arg7_type, typename arg8_type,\
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      GMOCK_ACTION_CLASS_(name, value_params)<\
+          GMOCK_INTERNAL_LIST_##template_params\
+          GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl<F>::\
+              gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION(name)\
+  class name##Action {\
+   public:\
+    name##Action() {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl() {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>());\
+    }\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##Action);\
+  };\
+  inline name##Action name() {\
+    return name##Action();\
+  }\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##Action::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P(name, p0)\
+  template <typename p0##_type>\
+  class name##ActionP {\
+   public:\
+    name##ActionP(p0##_type gmock_p0) : p0(gmock_p0) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      explicit gmock_Impl(p0##_type gmock_p0) : p0(gmock_p0) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0));\
+    }\
+    p0##_type p0;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP);\
+  };\
+  template <typename p0##_type>\
+  inline name##ActionP<p0##_type> name(p0##_type p0) {\
+    return name##ActionP<p0##_type>(p0);\
+  }\
+  template <typename p0##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP<p0##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P2(name, p0, p1)\
+  template <typename p0##_type, typename p1##_type>\
+  class name##ActionP2 {\
+   public:\
+    name##ActionP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+        p1(gmock_p1) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+          p1(gmock_p1) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP2);\
+  };\
+  template <typename p0##_type, typename p1##_type>\
+  inline name##ActionP2<p0##_type, p1##_type> name(p0##_type p0, \
+      p1##_type p1) {\
+    return name##ActionP2<p0##_type, p1##_type>(p0, p1);\
+  }\
+  template <typename p0##_type, typename p1##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP2<p0##_type, p1##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P3(name, p0, p1, p2)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  class name##ActionP3 {\
+   public:\
+    name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \
+          p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP3);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  inline name##ActionP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2) {\
+    return name##ActionP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP3<p0##_type, p1##_type, \
+          p2##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P4(name, p0, p1, p2, p3)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  class name##ActionP4 {\
+   public:\
+    name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP4);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  inline name##ActionP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3) {\
+    return name##ActionP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, p1, \
+        p2, p3);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP4<p0##_type, p1##_type, p2##_type, \
+          p3##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P5(name, p0, p1, p2, p3, p4)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  class name##ActionP5 {\
+   public:\
+    name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, \
+        p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), \
+          p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP5);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  inline name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4) {\
+    return name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type>(p0, p1, p2, p3, p4);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+          p4##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  class name##ActionP6 {\
+   public:\
+    name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, \
+          p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP6);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  inline name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3, p4##_type p4, p5##_type p5) {\
+    return name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  class name##ActionP7 {\
+   public:\
+    name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \
+        p6(gmock_p6) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP7);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  inline name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
+      p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6) {\
+    return name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  class name##ActionP8 {\
+   public:\
+    name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, \
+        p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), \
+          p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), \
+          p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP8);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  inline name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6, p7##_type p7) {\
+    return name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
+        p6, p7);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, \
+          p7##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  class name##ActionP9 {\
+   public:\
+    name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, \
+          p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+          p7(gmock_p7), p8(gmock_p8) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7, p8));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP9);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  inline name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, \
+      p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
+      p8##_type p8) {\
+    return name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
+        p3, p4, p5, p6, p7, p8);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, p7##_type, \
+          p8##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  class name##ActionP10 {\
+   public:\
+    name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\
+    template <typename F>\
+    class gmock_Impl : public ::testing::ActionInterface<F> {\
+     public:\
+      typedef F function_type;\
+      typedef typename ::testing::internal::Function<F>::Result return_type;\
+      typedef typename ::testing::internal::Function<F>::ArgumentTuple\
+          args_type;\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+          p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+          p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+          p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\
+      virtual return_type Perform(const args_type& args) {\
+        return ::testing::internal::ActionHelper<return_type, gmock_Impl>::\
+            Perform(this, args);\
+      }\
+      template <typename arg0_type, typename arg1_type, typename arg2_type, \
+          typename arg3_type, typename arg4_type, typename arg5_type, \
+          typename arg6_type, typename arg7_type, typename arg8_type, \
+          typename arg9_type>\
+      return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \
+          arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \
+          arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \
+          arg9_type arg9) const;\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+      p9##_type p9;\
+     private:\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename F> operator ::testing::Action<F>() const {\
+      return ::testing::Action<F>(new gmock_Impl<F>(p0, p1, p2, p3, p4, p5, \
+          p6, p7, p8, p9));\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+    p9##_type p9;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##ActionP10);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  inline name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+      p9##_type p9) {\
+    return name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
+        p1, p2, p3, p4, p5, p6, p7, p8, p9);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  template <typename F>\
+  template <typename arg0_type, typename arg1_type, typename arg2_type, \
+      typename arg3_type, typename arg4_type, typename arg5_type, \
+      typename arg6_type, typename arg7_type, typename arg8_type, \
+      typename arg9_type>\
+  typename ::testing::internal::Function<F>::Result\
+      name##ActionP10<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+          p5##_type, p6##_type, p7##_type, p8##_type, \
+          p9##_type>::gmock_Impl<F>::gmock_PerformImpl(\
+          GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const
+
+// TODO(wan@google.com): move the following to a different .h file
+// such that we don't have to run 'pump' every time the code is
+// updated.
+namespace testing {
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Various overloads for InvokeArgument<N>().
+//
+// The InvokeArgument<N>(a1, a2, ..., a_k) action invokes the N-th
+// (0-based) argument, which must be a k-ary callable, of the mock
+// function, with arguments a1, a2, ..., a_k.
+//
+// Notes:
+//
+//   1. The arguments are passed by value by default.  If you need to
+//   pass an argument by reference, wrap it inside ByRef().  For
+//   example,
+//
+//     InvokeArgument<1>(5, string("Hello"), ByRef(foo))
+//
+//   passes 5 and string("Hello") by value, and passes foo by
+//   reference.
+//
+//   2. If the callable takes an argument by reference but ByRef() is
+//   not used, it will receive the reference to a copy of the value,
+//   instead of the original value.  For example, when the 0-th
+//   argument of the mock function takes a const string&, the action
+//
+//     InvokeArgument<0>(string("Hello"))
+//
+//   makes a copy of the temporary string("Hello") object and passes a
+//   reference of the copy, instead of the original temporary object,
+//   to the callable.  This makes it easy for a user to define an
+//   InvokeArgument action from temporary values and have it performed
+//   later.
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args));
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(p0)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_2_VALUE_PARAMS(p0, p1)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_3_VALUE_PARAMS(p0, p1, p2)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+ACTION_TEMPLATE(InvokeArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
+  return internal::CallableHelper<return_type>::Call(
+      ::std::tr1::get<k>(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+// Various overloads for ReturnNew<T>().
+//
+// The ReturnNew<T>(a1, a2, ..., a_k) action returns a pointer to a new
+// instance of type T, constructed on the heap with constructor arguments
+// a1, a2, ..., and a_k. The caller assumes ownership of the returned value.
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_0_VALUE_PARAMS()) {
+  return new T();
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_1_VALUE_PARAMS(p0)) {
+  return new T(p0);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_2_VALUE_PARAMS(p0, p1)) {
+  return new T(p0, p1);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_3_VALUE_PARAMS(p0, p1, p2)) {
+  return new T(p0, p1, p2);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_4_VALUE_PARAMS(p0, p1, p2, p3)) {
+  return new T(p0, p1, p2, p3);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) {
+  return new T(p0, p1, p2, p3, p4);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) {
+  return new T(p0, p1, p2, p3, p4, p5);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+ACTION_TEMPLATE(ReturnNew,
+                HAS_1_TEMPLATE_PARAMS(typename, T),
+                AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) {
+  return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-function-mockers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-function-mockers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-function-mockers.h	(revision 11817)
@@ -0,0 +1,929 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-function-mockers.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements function mockers of various arities.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+namespace testing {
+namespace internal {
+
+template <typename F>
+class FunctionMockerBase;
+
+// Note: class FunctionMocker really belongs to the ::testing
+// namespace.  However if we define it in ::testing, MSVC will
+// complain when classes in ::testing::internal declare it as a
+// friend class template.  To workaround this compiler bug, we define
+// FunctionMocker in ::testing::internal and import it into ::testing.
+template <typename F>
+class FunctionMocker;
+
+template <typename R>
+class FunctionMocker<R()> : public
+    internal::FunctionMockerBase<R()> {
+ public:
+  typedef R F();
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With() {
+    return this->current_spec();
+  }
+
+  R Invoke() {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple());
+  }
+};
+
+template <typename R, typename A1>
+class FunctionMocker<R(A1)> : public
+    internal::FunctionMockerBase<R(A1)> {
+ public:
+  typedef R F(A1);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1));
+  }
+};
+
+template <typename R, typename A1, typename A2>
+class FunctionMocker<R(A1, A2)> : public
+    internal::FunctionMockerBase<R(A1, A2)> {
+ public:
+  typedef R F(A1, A2);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+class FunctionMocker<R(A1, A2, A3)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3)> {
+ public:
+  typedef R F(A1, A2, A3);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class FunctionMocker<R(A1, A2, A3, A4)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4)> {
+ public:
+  typedef R F(A1, A2, A3, A4);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+class FunctionMocker<R(A1, A2, A3, A4, A5)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4,
+        m5));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
+      const Matcher<A9>& m9) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8, m9));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9));
+  }
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+class FunctionMocker<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> : public
+    internal::FunctionMockerBase<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
+ public:
+  typedef R F(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+
+  MockSpec<F>& With(const Matcher<A1>& m1, const Matcher<A2>& m2,
+      const Matcher<A3>& m3, const Matcher<A4>& m4, const Matcher<A5>& m5,
+      const Matcher<A6>& m6, const Matcher<A7>& m7, const Matcher<A8>& m8,
+      const Matcher<A9>& m9, const Matcher<A10>& m10) {
+    this->current_spec().SetMatchers(::std::tr1::make_tuple(m1, m2, m3, m4, m5,
+        m6, m7, m8, m9, m10));
+    return this->current_spec();
+  }
+
+  R Invoke(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9,
+      A10 a10) {
+    // Even though gcc and MSVC don't enforce it, 'this->' is required
+    // by the C++ standard [14.6.4] here, as the base class type is
+    // dependent on the template argument (and thus shouldn't be
+    // looked into when resolving InvokeWith).
+    return this->InvokeWith(ArgumentTuple(a1, a2, a3, a4, a5, a6, a7, a8, a9,
+        a10));
+  }
+};
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the FunctionMocker class template
+// is meant to be defined in the ::testing namespace.  The following
+// line is just a trick for working around a bug in MSVC 8.0, which
+// cannot handle it if we define FunctionMocker in ::testing.
+using internal::FunctionMocker;
+
+// The result type of function type F.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_RESULT_(tn, F) tn ::testing::internal::Function<F>::Result
+
+// The type of argument N of function type F.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_ARG_(tn, F, N) tn ::testing::internal::Function<F>::Argument##N
+
+// The matcher type for argument N of function type F.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MATCHER_(tn, F, N) const ::testing::Matcher<GMOCK_ARG_(tn, F, N)>&
+
+// The variable for mocking the given method.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_MOCKER_(arity, constness, Method) \
+    GTEST_CONCAT_TOKEN_(gmock##constness##arity##_##Method##_, __LINE__)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD0_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method() constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 0, \
+        this_method_does_not_take_0_arguments); \
+    GMOCK_MOCKER_(0, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(0, constness, Method).Invoke(); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method() constness { \
+    GMOCK_MOCKER_(0, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(0, constness, Method).With(); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(0, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD1_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 1, \
+        this_method_does_not_take_1_argument); \
+    GMOCK_MOCKER_(1, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(1, constness, Method).Invoke(gmock_a1); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1) constness { \
+    GMOCK_MOCKER_(1, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(1, constness, Method).With(gmock_a1); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(1, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD2_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 2, \
+        this_method_does_not_take_2_arguments); \
+    GMOCK_MOCKER_(2, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(2, constness, Method).Invoke(gmock_a1, gmock_a2); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2) constness { \
+    GMOCK_MOCKER_(2, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(2, constness, Method).With(gmock_a1, gmock_a2); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(2, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD3_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 3, \
+        this_method_does_not_take_3_arguments); \
+    GMOCK_MOCKER_(3, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(3, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3) constness { \
+    GMOCK_MOCKER_(3, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(3, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(3, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD4_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 4, \
+        this_method_does_not_take_4_arguments); \
+    GMOCK_MOCKER_(4, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(4, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4) constness { \
+    GMOCK_MOCKER_(4, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(4, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(4, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD5_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 5, \
+        this_method_does_not_take_5_arguments); \
+    GMOCK_MOCKER_(5, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(5, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5) constness { \
+    GMOCK_MOCKER_(5, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(5, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(5, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD6_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 6, \
+        this_method_does_not_take_6_arguments); \
+    GMOCK_MOCKER_(6, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(6, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6) constness { \
+    GMOCK_MOCKER_(6, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(6, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(6, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD7_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 7, \
+        this_method_does_not_take_7_arguments); \
+    GMOCK_MOCKER_(7, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(7, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7) constness { \
+    GMOCK_MOCKER_(7, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(7, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(7, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD8_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7, \
+                                 GMOCK_ARG_(tn, F, 8) gmock_a8) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 8, \
+        this_method_does_not_take_8_arguments); \
+    GMOCK_MOCKER_(8, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(8, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
+                     GMOCK_MATCHER_(tn, F, 8) gmock_a8) constness { \
+    GMOCK_MOCKER_(8, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(8, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(8, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD9_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7, \
+                                 GMOCK_ARG_(tn, F, 8) gmock_a8, \
+                                 GMOCK_ARG_(tn, F, 9) gmock_a9) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 9, \
+        this_method_does_not_take_9_arguments); \
+    GMOCK_MOCKER_(9, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(9, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
+                     GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
+                     GMOCK_MATCHER_(tn, F, 9) gmock_a9) constness { \
+    GMOCK_MOCKER_(9, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(9, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, \
+        gmock_a9); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(9, constness, Method)
+
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define GMOCK_METHOD10_(tn, constness, ct, Method, F) \
+  GMOCK_RESULT_(tn, F) ct Method(GMOCK_ARG_(tn, F, 1) gmock_a1, \
+                                 GMOCK_ARG_(tn, F, 2) gmock_a2, \
+                                 GMOCK_ARG_(tn, F, 3) gmock_a3, \
+                                 GMOCK_ARG_(tn, F, 4) gmock_a4, \
+                                 GMOCK_ARG_(tn, F, 5) gmock_a5, \
+                                 GMOCK_ARG_(tn, F, 6) gmock_a6, \
+                                 GMOCK_ARG_(tn, F, 7) gmock_a7, \
+                                 GMOCK_ARG_(tn, F, 8) gmock_a8, \
+                                 GMOCK_ARG_(tn, F, 9) gmock_a9, \
+                                 GMOCK_ARG_(tn, F, 10) gmock_a10) constness { \
+    GTEST_COMPILE_ASSERT_(::std::tr1::tuple_size< \
+        tn ::testing::internal::Function<F>::ArgumentTuple>::value == 10, \
+        this_method_does_not_take_10_arguments); \
+    GMOCK_MOCKER_(10, constness, Method).SetOwnerAndName(this, #Method); \
+    return GMOCK_MOCKER_(10, constness, Method).Invoke(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+        gmock_a10); \
+  } \
+  ::testing::MockSpec<F>& \
+      gmock_##Method(GMOCK_MATCHER_(tn, F, 1) gmock_a1, \
+                     GMOCK_MATCHER_(tn, F, 2) gmock_a2, \
+                     GMOCK_MATCHER_(tn, F, 3) gmock_a3, \
+                     GMOCK_MATCHER_(tn, F, 4) gmock_a4, \
+                     GMOCK_MATCHER_(tn, F, 5) gmock_a5, \
+                     GMOCK_MATCHER_(tn, F, 6) gmock_a6, \
+                     GMOCK_MATCHER_(tn, F, 7) gmock_a7, \
+                     GMOCK_MATCHER_(tn, F, 8) gmock_a8, \
+                     GMOCK_MATCHER_(tn, F, 9) gmock_a9, \
+                     GMOCK_MATCHER_(tn, F, 10) gmock_a10) constness { \
+    GMOCK_MOCKER_(10, constness, Method).RegisterOwner(this); \
+    return GMOCK_MOCKER_(10, constness, Method).With(gmock_a1, gmock_a2, \
+        gmock_a3, gmock_a4, gmock_a5, gmock_a6, gmock_a7, gmock_a8, gmock_a9, \
+        gmock_a10); \
+  } \
+  mutable ::testing::FunctionMocker<F> GMOCK_MOCKER_(10, constness, Method)
+
+#define MOCK_METHOD0(m, F) GMOCK_METHOD0_(, , , m, F)
+#define MOCK_METHOD1(m, F) GMOCK_METHOD1_(, , , m, F)
+#define MOCK_METHOD2(m, F) GMOCK_METHOD2_(, , , m, F)
+#define MOCK_METHOD3(m, F) GMOCK_METHOD3_(, , , m, F)
+#define MOCK_METHOD4(m, F) GMOCK_METHOD4_(, , , m, F)
+#define MOCK_METHOD5(m, F) GMOCK_METHOD5_(, , , m, F)
+#define MOCK_METHOD6(m, F) GMOCK_METHOD6_(, , , m, F)
+#define MOCK_METHOD7(m, F) GMOCK_METHOD7_(, , , m, F)
+#define MOCK_METHOD8(m, F) GMOCK_METHOD8_(, , , m, F)
+#define MOCK_METHOD9(m, F) GMOCK_METHOD9_(, , , m, F)
+#define MOCK_METHOD10(m, F) GMOCK_METHOD10_(, , , m, F)
+
+#define MOCK_CONST_METHOD0(m, F) GMOCK_METHOD0_(, const, , m, F)
+#define MOCK_CONST_METHOD1(m, F) GMOCK_METHOD1_(, const, , m, F)
+#define MOCK_CONST_METHOD2(m, F) GMOCK_METHOD2_(, const, , m, F)
+#define MOCK_CONST_METHOD3(m, F) GMOCK_METHOD3_(, const, , m, F)
+#define MOCK_CONST_METHOD4(m, F) GMOCK_METHOD4_(, const, , m, F)
+#define MOCK_CONST_METHOD5(m, F) GMOCK_METHOD5_(, const, , m, F)
+#define MOCK_CONST_METHOD6(m, F) GMOCK_METHOD6_(, const, , m, F)
+#define MOCK_CONST_METHOD7(m, F) GMOCK_METHOD7_(, const, , m, F)
+#define MOCK_CONST_METHOD8(m, F) GMOCK_METHOD8_(, const, , m, F)
+#define MOCK_CONST_METHOD9(m, F) GMOCK_METHOD9_(, const, , m, F)
+#define MOCK_CONST_METHOD10(m, F) GMOCK_METHOD10_(, const, , m, F)
+
+#define MOCK_METHOD0_T(m, F) GMOCK_METHOD0_(typename, , , m, F)
+#define MOCK_METHOD1_T(m, F) GMOCK_METHOD1_(typename, , , m, F)
+#define MOCK_METHOD2_T(m, F) GMOCK_METHOD2_(typename, , , m, F)
+#define MOCK_METHOD3_T(m, F) GMOCK_METHOD3_(typename, , , m, F)
+#define MOCK_METHOD4_T(m, F) GMOCK_METHOD4_(typename, , , m, F)
+#define MOCK_METHOD5_T(m, F) GMOCK_METHOD5_(typename, , , m, F)
+#define MOCK_METHOD6_T(m, F) GMOCK_METHOD6_(typename, , , m, F)
+#define MOCK_METHOD7_T(m, F) GMOCK_METHOD7_(typename, , , m, F)
+#define MOCK_METHOD8_T(m, F) GMOCK_METHOD8_(typename, , , m, F)
+#define MOCK_METHOD9_T(m, F) GMOCK_METHOD9_(typename, , , m, F)
+#define MOCK_METHOD10_T(m, F) GMOCK_METHOD10_(typename, , , m, F)
+
+#define MOCK_CONST_METHOD0_T(m, F) GMOCK_METHOD0_(typename, const, , m, F)
+#define MOCK_CONST_METHOD1_T(m, F) GMOCK_METHOD1_(typename, const, , m, F)
+#define MOCK_CONST_METHOD2_T(m, F) GMOCK_METHOD2_(typename, const, , m, F)
+#define MOCK_CONST_METHOD3_T(m, F) GMOCK_METHOD3_(typename, const, , m, F)
+#define MOCK_CONST_METHOD4_T(m, F) GMOCK_METHOD4_(typename, const, , m, F)
+#define MOCK_CONST_METHOD5_T(m, F) GMOCK_METHOD5_(typename, const, , m, F)
+#define MOCK_CONST_METHOD6_T(m, F) GMOCK_METHOD6_(typename, const, , m, F)
+#define MOCK_CONST_METHOD7_T(m, F) GMOCK_METHOD7_(typename, const, , m, F)
+#define MOCK_CONST_METHOD8_T(m, F) GMOCK_METHOD8_(typename, const, , m, F)
+#define MOCK_CONST_METHOD9_T(m, F) GMOCK_METHOD9_(typename, const, , m, F)
+#define MOCK_CONST_METHOD10_T(m, F) GMOCK_METHOD10_(typename, const, , m, F)
+
+#define MOCK_METHOD0_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD0_(, , ct, m, F)
+#define MOCK_METHOD1_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD1_(, , ct, m, F)
+#define MOCK_METHOD2_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD2_(, , ct, m, F)
+#define MOCK_METHOD3_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD3_(, , ct, m, F)
+#define MOCK_METHOD4_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD4_(, , ct, m, F)
+#define MOCK_METHOD5_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD5_(, , ct, m, F)
+#define MOCK_METHOD6_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD6_(, , ct, m, F)
+#define MOCK_METHOD7_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD7_(, , ct, m, F)
+#define MOCK_METHOD8_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD8_(, , ct, m, F)
+#define MOCK_METHOD9_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD9_(, , ct, m, F)
+#define MOCK_METHOD10_WITH_CALLTYPE(ct, m, F) GMOCK_METHOD10_(, , ct, m, F)
+
+#define MOCK_CONST_METHOD0_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD0_(, const, ct, m, F)
+#define MOCK_CONST_METHOD1_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD1_(, const, ct, m, F)
+#define MOCK_CONST_METHOD2_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD2_(, const, ct, m, F)
+#define MOCK_CONST_METHOD3_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD3_(, const, ct, m, F)
+#define MOCK_CONST_METHOD4_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD4_(, const, ct, m, F)
+#define MOCK_CONST_METHOD5_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD5_(, const, ct, m, F)
+#define MOCK_CONST_METHOD6_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD6_(, const, ct, m, F)
+#define MOCK_CONST_METHOD7_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD7_(, const, ct, m, F)
+#define MOCK_CONST_METHOD8_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD8_(, const, ct, m, F)
+#define MOCK_CONST_METHOD9_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD9_(, const, ct, m, F)
+#define MOCK_CONST_METHOD10_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD10_(, const, ct, m, F)
+
+#define MOCK_METHOD0_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD0_(typename, , ct, m, F)
+#define MOCK_METHOD1_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD1_(typename, , ct, m, F)
+#define MOCK_METHOD2_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD2_(typename, , ct, m, F)
+#define MOCK_METHOD3_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD3_(typename, , ct, m, F)
+#define MOCK_METHOD4_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD4_(typename, , ct, m, F)
+#define MOCK_METHOD5_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD5_(typename, , ct, m, F)
+#define MOCK_METHOD6_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD6_(typename, , ct, m, F)
+#define MOCK_METHOD7_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD7_(typename, , ct, m, F)
+#define MOCK_METHOD8_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD8_(typename, , ct, m, F)
+#define MOCK_METHOD9_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD9_(typename, , ct, m, F)
+#define MOCK_METHOD10_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD10_(typename, , ct, m, F)
+
+#define MOCK_CONST_METHOD0_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD0_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD1_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD1_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD2_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD2_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD3_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD3_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD4_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD4_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD5_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD5_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD6_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD6_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD7_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD7_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD8_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD8_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD9_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD9_(typename, const, ct, m, F)
+#define MOCK_CONST_METHOD10_T_WITH_CALLTYPE(ct, m, F) \
+    GMOCK_METHOD10_(typename, const, ct, m, F)
+
+// A MockFunction<F> class has one mock method whose type is F.  It is
+// useful when you just want your test code to emit some messages and
+// have Google Mock verify the right messages are sent (and perhaps at
+// the right times).  For example, if you are exercising code:
+//
+//   Foo(1);
+//   Foo(2);
+//   Foo(3);
+//
+// and want to verify that Foo(1) and Foo(3) both invoke
+// mock.Bar("a"), but Foo(2) doesn't invoke anything, you can write:
+//
+// TEST(FooTest, InvokesBarCorrectly) {
+//   MyMock mock;
+//   MockFunction<void(string check_point_name)> check;
+//   {
+//     InSequence s;
+//
+//     EXPECT_CALL(mock, Bar("a"));
+//     EXPECT_CALL(check, Call("1"));
+//     EXPECT_CALL(check, Call("2"));
+//     EXPECT_CALL(mock, Bar("a"));
+//   }
+//   Foo(1);
+//   check.Call("1");
+//   Foo(2);
+//   check.Call("2");
+//   Foo(3);
+// }
+//
+// The expectation spec says that the first Bar("a") must happen
+// before check point "1", the second Bar("a") must happen after check
+// point "2", and nothing should happen between the two check
+// points. The explicit check points make it easy to tell which
+// Bar("a") is called by which call to Foo().
+template <typename F>
+class MockFunction;
+
+template <typename R>
+class MockFunction<R()> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD0_T(Call, R());
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0>
+class MockFunction<R(A0)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD1_T(Call, R(A0));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1>
+class MockFunction<R(A0, A1)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD2_T(Call, R(A0, A1));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2>
+class MockFunction<R(A0, A1, A2)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD3_T(Call, R(A0, A1, A2));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3>
+class MockFunction<R(A0, A1, A2, A3)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD4_T(Call, R(A0, A1, A2, A3));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4>
+class MockFunction<R(A0, A1, A2, A3, A4)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD5_T(Call, R(A0, A1, A2, A3, A4));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5>
+class MockFunction<R(A0, A1, A2, A3, A4, A5)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD6_T(Call, R(A0, A1, A2, A3, A4, A5));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD7_T(Call, R(A0, A1, A2, A3, A4, A5, A6));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD8_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD9_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+template <typename R, typename A0, typename A1, typename A2, typename A3,
+    typename A4, typename A5, typename A6, typename A7, typename A8,
+    typename A9>
+class MockFunction<R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+ public:
+  MockFunction() {}
+
+  MOCK_METHOD10_T(Call, R(A0, A1, A2, A3, A4, A5, A6, A7, A8, A9));
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MockFunction);
+};
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-matchers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-matchers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-matchers.h	(revision 11817)
@@ -0,0 +1,2054 @@
+// This file was GENERATED by command:
+//     pump.py gmock-generated-matchers.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used variadic matchers.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include "gmock/gmock-matchers.h"
+
+namespace testing {
+namespace internal {
+
+// The type of the i-th (0-based) field of Tuple.
+#define GMOCK_FIELD_TYPE_(Tuple, i) \
+    typename ::std::tr1::tuple_element<i, Tuple>::type
+
+// TupleFields<Tuple, k0, ..., kn> is for selecting fields from a
+// tuple of type Tuple.  It has two members:
+//
+//   type: a tuple type whose i-th field is the ki-th field of Tuple.
+//   GetSelectedFields(t): returns fields k0, ..., and kn of t as a tuple.
+//
+// For example, in class TupleFields<tuple<bool, char, int>, 2, 0>, we have:
+//
+//   type is tuple<int, bool>, and
+//   GetSelectedFields(make_tuple(true, 'a', 42)) is (42, true).
+
+template <class Tuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1>
+class TupleFields;
+
+// This generic version is used when there are 10 selectors.
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7, int k8, int k9>
+class TupleFields {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8),
+      GMOCK_FIELD_TYPE_(Tuple, k9)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t), get<k9>(t));
+  }
+};
+
+// The following specialization is used for 0 ~ 9 selectors.
+
+template <class Tuple>
+class TupleFields<Tuple, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<> type;
+  static type GetSelectedFields(const Tuple& /* t */) {
+    using ::std::tr1::get;
+    return type();
+  }
+};
+
+template <class Tuple, int k0>
+class TupleFields<Tuple, k0, -1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1>
+class TupleFields<Tuple, k0, k1, -1, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2>
+class TupleFields<Tuple, k0, k1, k2, -1, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3>
+class TupleFields<Tuple, k0, k1, k2, k3, -1, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, -1, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, -1, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, -1, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, -1, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t));
+  }
+};
+
+template <class Tuple, int k0, int k1, int k2, int k3, int k4, int k5, int k6,
+    int k7, int k8>
+class TupleFields<Tuple, k0, k1, k2, k3, k4, k5, k6, k7, k8, -1> {
+ public:
+  typedef ::std::tr1::tuple<GMOCK_FIELD_TYPE_(Tuple, k0),
+      GMOCK_FIELD_TYPE_(Tuple, k1), GMOCK_FIELD_TYPE_(Tuple, k2),
+      GMOCK_FIELD_TYPE_(Tuple, k3), GMOCK_FIELD_TYPE_(Tuple, k4),
+      GMOCK_FIELD_TYPE_(Tuple, k5), GMOCK_FIELD_TYPE_(Tuple, k6),
+      GMOCK_FIELD_TYPE_(Tuple, k7), GMOCK_FIELD_TYPE_(Tuple, k8)> type;
+  static type GetSelectedFields(const Tuple& t) {
+    using ::std::tr1::get;
+    return type(get<k0>(t), get<k1>(t), get<k2>(t), get<k3>(t), get<k4>(t),
+        get<k5>(t), get<k6>(t), get<k7>(t), get<k8>(t));
+  }
+};
+
+#undef GMOCK_FIELD_TYPE_
+
+// Implements the Args() matcher.
+template <class ArgsTuple, int k0 = -1, int k1 = -1, int k2 = -1, int k3 = -1,
+    int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1, int k8 = -1,
+    int k9 = -1>
+class ArgsMatcherImpl : public MatcherInterface<ArgsTuple> {
+ public:
+  // ArgsTuple may have top-level const or reference modifiers.
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(ArgsTuple) RawArgsTuple;
+  typedef typename internal::TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5,
+      k6, k7, k8, k9>::type SelectedArgs;
+  typedef Matcher<const SelectedArgs&> MonomorphicInnerMatcher;
+
+  template <typename InnerMatcher>
+  explicit ArgsMatcherImpl(const InnerMatcher& inner_matcher)
+      : inner_matcher_(SafeMatcherCast<const SelectedArgs&>(inner_matcher)) {}
+
+  virtual bool MatchAndExplain(ArgsTuple args,
+                               MatchResultListener* listener) const {
+    const SelectedArgs& selected_args = GetSelectedArgs(args);
+    if (!listener->IsInterested())
+      return inner_matcher_.Matches(selected_args);
+
+    PrintIndices(listener->stream());
+    *listener << "are " << PrintToString(selected_args);
+
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(selected_args,
+                                                      &inner_listener);
+    PrintIfNotEmpty(inner_listener.str(), listener->stream());
+    return match;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "are a tuple ";
+    PrintIndices(os);
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+ private:
+  static SelectedArgs GetSelectedArgs(ArgsTuple args) {
+    return TupleFields<RawArgsTuple, k0, k1, k2, k3, k4, k5, k6, k7, k8,
+        k9>::GetSelectedFields(args);
+  }
+
+  // Prints the indices of the selected fields.
+  static void PrintIndices(::std::ostream* os) {
+    *os << "whose fields (";
+    const int indices[10] = { k0, k1, k2, k3, k4, k5, k6, k7, k8, k9 };
+    for (int i = 0; i < 10; i++) {
+      if (indices[i] < 0)
+        break;
+
+      if (i >= 1)
+        *os << ", ";
+
+      *os << "#" << indices[i];
+    }
+    *os << ") ";
+  }
+
+  const MonomorphicInnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcherImpl);
+};
+
+template <class InnerMatcher, int k0 = -1, int k1 = -1, int k2 = -1,
+    int k3 = -1, int k4 = -1, int k5 = -1, int k6 = -1, int k7 = -1,
+    int k8 = -1, int k9 = -1>
+class ArgsMatcher {
+ public:
+  explicit ArgsMatcher(const InnerMatcher& inner_matcher)
+      : inner_matcher_(inner_matcher) {}
+
+  template <typename ArgsTuple>
+  operator Matcher<ArgsTuple>() const {
+    return MakeMatcher(new ArgsMatcherImpl<ArgsTuple, k0, k1, k2, k3, k4, k5,
+        k6, k7, k8, k9>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ArgsMatcher);
+};
+
+// Implements ElementsAre() of 1-10 arguments.
+
+template <typename T1>
+class ElementsAreMatcher1 {
+ public:
+  explicit ElementsAreMatcher1(const T1& e1) : e1_(e1) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    // Nokia's Symbian Compiler has a nasty bug where the object put
+    // in a one-element local array is not destructed when the array
+    // goes out of scope.  This leads to obvious badness as we've
+    // added the linked_ptr in it to our other linked_ptrs list.
+    // Hence we implement ElementsAreMatcher1 specially to avoid using
+    // a local array.
+    const Matcher<const Element&> matcher =
+        MatcherCast<const Element&>(e1_);
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(&matcher, 1));
+  }
+
+ private:
+  const T1& e1_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher1);
+};
+
+template <typename T1, typename T2>
+class ElementsAreMatcher2 {
+ public:
+  ElementsAreMatcher2(const T1& e1, const T2& e2) : e1_(e1), e2_(e2) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 2));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher2);
+};
+
+template <typename T1, typename T2, typename T3>
+class ElementsAreMatcher3 {
+ public:
+  ElementsAreMatcher3(const T1& e1, const T2& e2, const T3& e3) : e1_(e1),
+      e2_(e2), e3_(e3) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 3));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher3);
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ElementsAreMatcher4 {
+ public:
+  ElementsAreMatcher4(const T1& e1, const T2& e2, const T3& e3,
+      const T4& e4) : e1_(e1), e2_(e2), e3_(e3), e4_(e4) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 4));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher4);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ElementsAreMatcher5 {
+ public:
+  ElementsAreMatcher5(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5) : e1_(e1), e2_(e2), e3_(e3), e4_(e4), e5_(e5) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 5));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher5);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ElementsAreMatcher6 {
+ public:
+  ElementsAreMatcher6(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6) : e1_(e1), e2_(e2), e3_(e3), e4_(e4),
+      e5_(e5), e6_(e6) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 6));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher6);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ElementsAreMatcher7 {
+ public:
+  ElementsAreMatcher7(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7) : e1_(e1), e2_(e2), e3_(e3),
+      e4_(e4), e5_(e5), e6_(e6), e7_(e7) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 7));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher7);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ElementsAreMatcher8 {
+ public:
+  ElementsAreMatcher8(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7, const T8& e8) : e1_(e1),
+      e2_(e2), e3_(e3), e4_(e4), e5_(e5), e6_(e6), e7_(e7), e8_(e8) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+      MatcherCast<const Element&>(e8_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 8));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+  const T8& e8_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher8);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ElementsAreMatcher9 {
+ public:
+  ElementsAreMatcher9(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7, const T8& e8,
+      const T9& e9) : e1_(e1), e2_(e2), e3_(e3), e4_(e4), e5_(e5), e6_(e6),
+      e7_(e7), e8_(e8), e9_(e9) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+      MatcherCast<const Element&>(e8_),
+      MatcherCast<const Element&>(e9_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 9));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+  const T8& e8_;
+  const T9& e9_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher9);
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ElementsAreMatcher10 {
+ public:
+  ElementsAreMatcher10(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+      const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9,
+      const T10& e10) : e1_(e1), e2_(e2), e3_(e3), e4_(e4), e5_(e5), e6_(e6),
+      e7_(e7), e8_(e8), e9_(e9), e10_(e10) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&> matchers[] = {
+      MatcherCast<const Element&>(e1_),
+      MatcherCast<const Element&>(e2_),
+      MatcherCast<const Element&>(e3_),
+      MatcherCast<const Element&>(e4_),
+      MatcherCast<const Element&>(e5_),
+      MatcherCast<const Element&>(e6_),
+      MatcherCast<const Element&>(e7_),
+      MatcherCast<const Element&>(e8_),
+      MatcherCast<const Element&>(e9_),
+      MatcherCast<const Element&>(e10_),
+    };
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 10));
+  }
+
+ private:
+  const T1& e1_;
+  const T2& e2_;
+  const T3& e3_;
+  const T4& e4_;
+  const T5& e5_;
+  const T6& e6_;
+  const T7& e7_;
+  const T8& e8_;
+  const T9& e9_;
+  const T10& e10_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher10);
+};
+
+}  // namespace internal
+
+// Args<N1, N2, ..., Nk>(a_matcher) matches a tuple if the selected
+// fields of it matches a_matcher.  C++ doesn't support default
+// arguments for function templates, so we have to overload it.
+template <typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher>(matcher);
+}
+
+template <int k1, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1>(matcher);
+}
+
+template <int k1, int k2, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2>(matcher);
+}
+
+template <int k1, int k2, int k3, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7,
+    typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6,
+      k7>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7,
+      k8>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9>(matcher);
+}
+
+template <int k1, int k2, int k3, int k4, int k5, int k6, int k7, int k8,
+    int k9, int k10, typename InnerMatcher>
+inline internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8, k9,
+    k10>
+Args(const InnerMatcher& matcher) {
+  return internal::ArgsMatcher<InnerMatcher, k1, k2, k3, k4, k5, k6, k7, k8,
+      k9, k10>(matcher);
+}
+
+// ElementsAre(e0, e1, ..., e_n) matches an STL-style container with
+// (n + 1) elements, where the i-th element in the container must
+// match the i-th argument in the list.  Each argument of
+// ElementsAre() can be either a value or a matcher.  We support up to
+// 10 arguments.
+//
+// NOTE: Since ElementsAre() cares about the order of the elements, it
+// must not be used with containers whose elements's order is
+// undefined (e.g. hash_map).
+
+inline internal::ElementsAreMatcher0 ElementsAre() {
+  return internal::ElementsAreMatcher0();
+}
+
+template <typename T1>
+inline internal::ElementsAreMatcher1<T1> ElementsAre(const T1& e1) {
+  return internal::ElementsAreMatcher1<T1>(e1);
+}
+
+template <typename T1, typename T2>
+inline internal::ElementsAreMatcher2<T1, T2> ElementsAre(const T1& e1,
+    const T2& e2) {
+  return internal::ElementsAreMatcher2<T1, T2>(e1, e2);
+}
+
+template <typename T1, typename T2, typename T3>
+inline internal::ElementsAreMatcher3<T1, T2, T3> ElementsAre(const T1& e1,
+    const T2& e2, const T3& e3) {
+  return internal::ElementsAreMatcher3<T1, T2, T3>(e1, e2, e3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline internal::ElementsAreMatcher4<T1, T2, T3, T4> ElementsAre(const T1& e1,
+    const T2& e2, const T3& e3, const T4& e4) {
+  return internal::ElementsAreMatcher4<T1, T2, T3, T4>(e1, e2, e3, e4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline internal::ElementsAreMatcher5<T1, T2, T3, T4,
+    T5> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5) {
+  return internal::ElementsAreMatcher5<T1, T2, T3, T4, T5>(e1, e2, e3, e4, e5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+inline internal::ElementsAreMatcher6<T1, T2, T3, T4, T5,
+    T6> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6) {
+  return internal::ElementsAreMatcher6<T1, T2, T3, T4, T5, T6>(e1, e2, e3, e4,
+      e5, e6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+inline internal::ElementsAreMatcher7<T1, T2, T3, T4, T5, T6,
+    T7> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7) {
+  return internal::ElementsAreMatcher7<T1, T2, T3, T4, T5, T6, T7>(e1, e2, e3,
+      e4, e5, e6, e7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+inline internal::ElementsAreMatcher8<T1, T2, T3, T4, T5, T6, T7,
+    T8> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8) {
+  return internal::ElementsAreMatcher8<T1, T2, T3, T4, T5, T6, T7, T8>(e1, e2,
+      e3, e4, e5, e6, e7, e8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+inline internal::ElementsAreMatcher9<T1, T2, T3, T4, T5, T6, T7, T8,
+    T9> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9) {
+  return internal::ElementsAreMatcher9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(e1,
+      e2, e3, e4, e5, e6, e7, e8, e9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+inline internal::ElementsAreMatcher10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+    T10> ElementsAre(const T1& e1, const T2& e2, const T3& e3, const T4& e4,
+    const T5& e5, const T6& e6, const T7& e7, const T8& e8, const T9& e9,
+    const T10& e10) {
+  return internal::ElementsAreMatcher10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+      T10>(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);
+}
+
+// ElementsAreArray(array) and ElementAreArray(array, count) are like
+// ElementsAre(), except that they take an array of values or
+// matchers.  The former form infers the size of 'array', which must
+// be a static C-style array.  In the latter form, 'array' can either
+// be a static array or a pointer to a dynamically created array.
+
+template <typename T>
+inline internal::ElementsAreArrayMatcher<T> ElementsAreArray(
+    const T* first, size_t count) {
+  return internal::ElementsAreArrayMatcher<T>(first, count);
+}
+
+template <typename T, size_t N>
+inline internal::ElementsAreArrayMatcher<T>
+ElementsAreArray(const T (&array)[N]) {
+  return internal::ElementsAreArrayMatcher<T>(array, N);
+}
+
+// AllOf(m1, m2, ..., mk) matches any value that matches all of the given
+// sub-matchers.  AllOf is called fully qualified to prevent ADL from firing.
+
+template <typename Matcher1, typename Matcher2>
+inline internal::BothOfMatcher<Matcher1, Matcher2>
+AllOf(Matcher1 m1, Matcher2 m2) {
+  return internal::BothOfMatcher<Matcher1, Matcher2>(m1, m2);
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    Matcher3> >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, Matcher4> > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    Matcher5> > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, Matcher6> > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    Matcher7> > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    internal::BothOfMatcher<Matcher7, Matcher8> > > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7, m8));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    internal::BothOfMatcher<Matcher7, internal::BothOfMatcher<Matcher8,
+    Matcher9> > > > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7, m8, m9));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9, typename Matcher10>
+inline internal::BothOfMatcher<Matcher1, internal::BothOfMatcher<Matcher2,
+    internal::BothOfMatcher<Matcher3, internal::BothOfMatcher<Matcher4,
+    internal::BothOfMatcher<Matcher5, internal::BothOfMatcher<Matcher6,
+    internal::BothOfMatcher<Matcher7, internal::BothOfMatcher<Matcher8,
+    internal::BothOfMatcher<Matcher9, Matcher10> > > > > > > > >
+AllOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9, Matcher10 m10) {
+  return ::testing::AllOf(m1, ::testing::AllOf(m2, m3, m4, m5, m6, m7, m8, m9,
+      m10));
+}
+
+// AnyOf(m1, m2, ..., mk) matches any value that matches any of the given
+// sub-matchers.  AnyOf is called fully qualified to prevent ADL from firing.
+
+template <typename Matcher1, typename Matcher2>
+inline internal::EitherOfMatcher<Matcher1, Matcher2>
+AnyOf(Matcher1 m1, Matcher2 m2) {
+  return internal::EitherOfMatcher<Matcher1, Matcher2>(m1, m2);
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    Matcher3> >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, Matcher4> > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    Matcher5> > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, Matcher6> > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    Matcher7> > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    internal::EitherOfMatcher<Matcher7, Matcher8> > > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7, m8));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    internal::EitherOfMatcher<Matcher7, internal::EitherOfMatcher<Matcher8,
+    Matcher9> > > > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7, m8, m9));
+}
+
+template <typename Matcher1, typename Matcher2, typename Matcher3,
+    typename Matcher4, typename Matcher5, typename Matcher6, typename Matcher7,
+    typename Matcher8, typename Matcher9, typename Matcher10>
+inline internal::EitherOfMatcher<Matcher1, internal::EitherOfMatcher<Matcher2,
+    internal::EitherOfMatcher<Matcher3, internal::EitherOfMatcher<Matcher4,
+    internal::EitherOfMatcher<Matcher5, internal::EitherOfMatcher<Matcher6,
+    internal::EitherOfMatcher<Matcher7, internal::EitherOfMatcher<Matcher8,
+    internal::EitherOfMatcher<Matcher9, Matcher10> > > > > > > > >
+AnyOf(Matcher1 m1, Matcher2 m2, Matcher3 m3, Matcher4 m4, Matcher5 m5,
+    Matcher6 m6, Matcher7 m7, Matcher8 m8, Matcher9 m9, Matcher10 m10) {
+  return ::testing::AnyOf(m1, ::testing::AnyOf(m2, m3, m4, m5, m6, m7, m8, m9,
+      m10));
+}
+
+}  // namespace testing
+
+
+// The MATCHER* family of macros can be used in a namespace scope to
+// define custom matchers easily.
+//
+// Basic Usage
+// ===========
+//
+// The syntax
+//
+//   MATCHER(name, description_string) { statements; }
+//
+// defines a matcher with the given name that executes the statements,
+// which must return a bool to indicate if the match succeeds.  Inside
+// the statements, you can refer to the value being matched by 'arg',
+// and refer to its type by 'arg_type'.
+//
+// The description string documents what the matcher does, and is used
+// to generate the failure message when the match fails.  Since a
+// MATCHER() is usually defined in a header file shared by multiple
+// C++ source files, we require the description to be a C-string
+// literal to avoid possible side effects.  It can be empty, in which
+// case we'll use the sequence of words in the matcher name as the
+// description.
+//
+// For example:
+//
+//   MATCHER(IsEven, "") { return (arg % 2) == 0; }
+//
+// allows you to write
+//
+//   // Expects mock_foo.Bar(n) to be called where n is even.
+//   EXPECT_CALL(mock_foo, Bar(IsEven()));
+//
+// or,
+//
+//   // Verifies that the value of some_expression is even.
+//   EXPECT_THAT(some_expression, IsEven());
+//
+// If the above assertion fails, it will print something like:
+//
+//   Value of: some_expression
+//   Expected: is even
+//     Actual: 7
+//
+// where the description "is even" is automatically calculated from the
+// matcher name IsEven.
+//
+// Argument Type
+// =============
+//
+// Note that the type of the value being matched (arg_type) is
+// determined by the context in which you use the matcher and is
+// supplied to you by the compiler, so you don't need to worry about
+// declaring it (nor can you).  This allows the matcher to be
+// polymorphic.  For example, IsEven() can be used to match any type
+// where the value of "(arg % 2) == 0" can be implicitly converted to
+// a bool.  In the "Bar(IsEven())" example above, if method Bar()
+// takes an int, 'arg_type' will be int; if it takes an unsigned long,
+// 'arg_type' will be unsigned long; and so on.
+//
+// Parameterizing Matchers
+// =======================
+//
+// Sometimes you'll want to parameterize the matcher.  For that you
+// can use another macro:
+//
+//   MATCHER_P(name, param_name, description_string) { statements; }
+//
+// For example:
+//
+//   MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; }
+//
+// will allow you to write:
+//
+//   EXPECT_THAT(Blah("a"), HasAbsoluteValue(n));
+//
+// which may lead to this message (assuming n is 10):
+//
+//   Value of: Blah("a")
+//   Expected: has absolute value 10
+//     Actual: -9
+//
+// Note that both the matcher description and its parameter are
+// printed, making the message human-friendly.
+//
+// In the matcher definition body, you can write 'foo_type' to
+// reference the type of a parameter named 'foo'.  For example, in the
+// body of MATCHER_P(HasAbsoluteValue, value) above, you can write
+// 'value_type' to refer to the type of 'value'.
+//
+// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P10 to
+// support multi-parameter matchers.
+//
+// Describing Parameterized Matchers
+// =================================
+//
+// The last argument to MATCHER*() is a string-typed expression.  The
+// expression can reference all of the matcher's parameters and a
+// special bool-typed variable named 'negation'.  When 'negation' is
+// false, the expression should evaluate to the matcher's description;
+// otherwise it should evaluate to the description of the negation of
+// the matcher.  For example,
+//
+//   using testing::PrintToString;
+//
+//   MATCHER_P2(InClosedRange, low, hi,
+//       string(negation ? "is not" : "is") + " in range [" +
+//       PrintToString(low) + ", " + PrintToString(hi) + "]") {
+//     return low <= arg && arg <= hi;
+//   }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: is in range [4, 6]
+//   ...
+//   Expected: is not in range [2, 4]
+//
+// If you specify "" as the description, the failure message will
+// contain the sequence of words in the matcher name followed by the
+// parameter values printed as a tuple.  For example,
+//
+//   MATCHER_P2(InClosedRange, low, hi, "") { ... }
+//   ...
+//   EXPECT_THAT(3, InClosedRange(4, 6));
+//   EXPECT_THAT(3, Not(InClosedRange(2, 4)));
+//
+// would generate two failures that contain the text:
+//
+//   Expected: in closed range (4, 6)
+//   ...
+//   Expected: not (in closed range (2, 4))
+//
+// Types of Matcher Parameters
+// ===========================
+//
+// For the purpose of typing, you can view
+//
+//   MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... }
+//
+// as shorthand for
+//
+//   template <typename p1_type, ..., typename pk_type>
+//   FooMatcherPk<p1_type, ..., pk_type>
+//   Foo(p1_type p1, ..., pk_type pk) { ... }
+//
+// When you write Foo(v1, ..., vk), the compiler infers the types of
+// the parameters v1, ..., and vk for you.  If you are not happy with
+// the result of the type inference, you can specify the types by
+// explicitly instantiating the template, as in Foo<long, bool>(5,
+// false).  As said earlier, you don't get to (or need to) specify
+// 'arg_type' as that's determined by the context in which the matcher
+// is used.  You can assign the result of expression Foo(p1, ..., pk)
+// to a variable of type FooMatcherPk<p1_type, ..., pk_type>.  This
+// can be useful when composing matchers.
+//
+// While you can instantiate a matcher template with reference types,
+// passing the parameters by pointer usually makes your code more
+// readable.  If, however, you still want to pass a parameter by
+// reference, be aware that in the failure message generated by the
+// matcher you will see the value of the referenced object but not its
+// address.
+//
+// Explaining Match Results
+// ========================
+//
+// Sometimes the matcher description alone isn't enough to explain why
+// the match has failed or succeeded.  For example, when expecting a
+// long string, it can be very helpful to also print the diff between
+// the expected string and the actual one.  To achieve that, you can
+// optionally stream additional information to a special variable
+// named result_listener, whose type is a pointer to class
+// MatchResultListener:
+//
+//   MATCHER_P(EqualsLongString, str, "") {
+//     if (arg == str) return true;
+//
+//     *result_listener << "the difference: "
+///                     << DiffStrings(str, arg);
+//     return false;
+//   }
+//
+// Overloading Matchers
+// ====================
+//
+// You can overload matchers with different numbers of parameters:
+//
+//   MATCHER_P(Blah, a, description_string1) { ... }
+//   MATCHER_P2(Blah, a, b, description_string2) { ... }
+//
+// Caveats
+// =======
+//
+// When defining a new matcher, you should also consider implementing
+// MatcherInterface or using MakePolymorphicMatcher().  These
+// approaches require more work than the MATCHER* macros, but also
+// give you more control on the types of the value being matched and
+// the matcher parameters, which may leads to better compiler error
+// messages when the matcher is used wrong.  They also allow
+// overloading matchers based on parameter types (as opposed to just
+// based on the number of parameters).
+//
+// MATCHER*() can only be used in a namespace scope.  The reason is
+// that C++ doesn't yet allow function-local types to be used to
+// instantiate templates.  The up-coming C++0x standard will fix this.
+// Once that's done, we'll consider supporting using MATCHER*() inside
+// a function.
+//
+// More Information
+// ================
+//
+// To learn more about using these macros, please search for 'MATCHER'
+// on http://code.google.com/p/googlemock/wiki/CookBook.
+
+#define MATCHER(name, description)\
+  class name##Matcher {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl()\
+           {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<>()));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>());\
+    }\
+    name##Matcher() {\
+    }\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##Matcher);\
+  };\
+  inline name##Matcher name() {\
+    return name##Matcher();\
+  }\
+  template <typename arg_type>\
+  bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P(name, p0, description)\
+  template <typename p0##_type>\
+  class name##MatcherP {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      explicit gmock_Impl(p0##_type gmock_p0)\
+           : p0(gmock_p0) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type>(p0)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0));\
+    }\
+    name##MatcherP(p0##_type gmock_p0) : p0(gmock_p0) {\
+    }\
+    p0##_type p0;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP);\
+  };\
+  template <typename p0##_type>\
+  inline name##MatcherP<p0##_type> name(p0##_type p0) {\
+    return name##MatcherP<p0##_type>(p0);\
+  }\
+  template <typename p0##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP<p0##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P2(name, p0, p1, description)\
+  template <typename p0##_type, typename p1##_type>\
+  class name##MatcherP2 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1)\
+           : p0(gmock_p0), p1(gmock_p1) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type>(p0, p1)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1));\
+    }\
+    name##MatcherP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \
+        p1(gmock_p1) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP2);\
+  };\
+  template <typename p0##_type, typename p1##_type>\
+  inline name##MatcherP2<p0##_type, p1##_type> name(p0##_type p0, \
+      p1##_type p1) {\
+    return name##MatcherP2<p0##_type, p1##_type>(p0, p1);\
+  }\
+  template <typename p0##_type, typename p1##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP2<p0##_type, \
+      p1##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P3(name, p0, p1, p2, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  class name##MatcherP3 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type>(p0, p1, \
+                    p2)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2));\
+    }\
+    name##MatcherP3(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP3);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  inline name##MatcherP3<p0##_type, p1##_type, p2##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2) {\
+    return name##MatcherP3<p0##_type, p1##_type, p2##_type>(p0, p1, p2);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP3<p0##_type, p1##_type, \
+      p2##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P4(name, p0, p1, p2, p3, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  class name##MatcherP4 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, \
+                    p3##_type>(p0, p1, p2, p3)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3));\
+    }\
+    name##MatcherP4(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP4);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  inline name##MatcherP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3) {\
+    return name##MatcherP4<p0##_type, p1##_type, p2##_type, p3##_type>(p0, \
+        p1, p2, p3);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP4<p0##_type, p1##_type, p2##_type, \
+      p3##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P5(name, p0, p1, p2, p3, p4, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  class name##MatcherP5 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type>(p0, p1, p2, p3, p4)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4));\
+    }\
+    name##MatcherP5(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, \
+        p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP5);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  inline name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4) {\
+    return name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type>(p0, p1, p2, p3, p4);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP5<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  class name##MatcherP6 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5));\
+    }\
+    name##MatcherP6(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP6);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  inline name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, \
+      p3##_type p3, p4##_type p4, p5##_type p5) {\
+    return name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type>(p0, p1, p2, p3, p4, p5);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP6<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  class name##MatcherP7 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, \
+                    p6)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6));\
+    }\
+    name##MatcherP7(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \
+        p6(gmock_p6) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP7);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  inline name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type> name(p0##_type p0, p1##_type p1, \
+      p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6) {\
+    return name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type>(p0, p1, p2, p3, p4, p5, p6);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP7<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  class name##MatcherP8 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, \
+                    p3, p4, p5, p6, p7)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7));\
+    }\
+    name##MatcherP8(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, \
+        p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP8);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  inline name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type> name(p0##_type p0, \
+      p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \
+      p6##_type p6, p7##_type p7) {\
+    return name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type>(p0, p1, p2, p3, p4, p5, \
+        p6, p7);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP8<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type, \
+      p7##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  class name##MatcherP9 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+               p8(gmock_p8) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type, \
+                    p8##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8));\
+    }\
+    name##MatcherP9(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \
+        p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+        p8(gmock_p8) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP9);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  inline name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, \
+      p8##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \
+      p8##_type p8) {\
+    return name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type>(p0, p1, p2, \
+        p3, p4, p5, p6, p7, p8);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP9<p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \
+      p5##_type, p6##_type, p7##_type, \
+      p8##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description)\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  class name##MatcherP10 {\
+   public:\
+    template <typename arg_type>\
+    class gmock_Impl : public ::testing::MatcherInterface<arg_type> {\
+     public:\
+      gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \
+          p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \
+          p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \
+          p9##_type gmock_p9)\
+           : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), \
+               p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \
+               p8(gmock_p8), p9(gmock_p9) {}\
+      virtual bool MatchAndExplain(\
+          arg_type arg, ::testing::MatchResultListener* result_listener) const;\
+      virtual void DescribeTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(false);\
+      }\
+      virtual void DescribeNegationTo(::std::ostream* gmock_os) const {\
+        *gmock_os << FormatDescription(true);\
+      }\
+      p0##_type p0;\
+      p1##_type p1;\
+      p2##_type p2;\
+      p3##_type p3;\
+      p4##_type p4;\
+      p5##_type p5;\
+      p6##_type p6;\
+      p7##_type p7;\
+      p8##_type p8;\
+      p9##_type p9;\
+     private:\
+      ::testing::internal::string FormatDescription(bool negation) const {\
+        const ::testing::internal::string gmock_description = (description);\
+        if (!gmock_description.empty())\
+          return gmock_description;\
+        return ::testing::internal::FormatMatcherDescription(\
+            negation, #name,\
+            ::testing::internal::UniversalTersePrintTupleFieldsToStrings(\
+                ::std::tr1::tuple<p0##_type, p1##_type, p2##_type, p3##_type, \
+                    p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+                    p9##_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)));\
+      }\
+      GTEST_DISALLOW_ASSIGN_(gmock_Impl);\
+    };\
+    template <typename arg_type>\
+    operator ::testing::Matcher<arg_type>() const {\
+      return ::testing::Matcher<arg_type>(\
+          new gmock_Impl<arg_type>(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9));\
+    }\
+    name##MatcherP10(p0##_type gmock_p0, p1##_type gmock_p1, \
+        p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \
+        p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \
+        p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \
+        p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \
+        p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {\
+    }\
+    p0##_type p0;\
+    p1##_type p1;\
+    p2##_type p2;\
+    p3##_type p3;\
+    p4##_type p4;\
+    p5##_type p5;\
+    p6##_type p6;\
+    p7##_type p7;\
+    p8##_type p8;\
+    p9##_type p9;\
+   private:\
+    GTEST_DISALLOW_ASSIGN_(name##MatcherP10);\
+  };\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  inline name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type> name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \
+      p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \
+      p9##_type p9) {\
+    return name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+        p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, p9##_type>(p0, \
+        p1, p2, p3, p4, p5, p6, p7, p8, p9);\
+  }\
+  template <typename p0##_type, typename p1##_type, typename p2##_type, \
+      typename p3##_type, typename p4##_type, typename p5##_type, \
+      typename p6##_type, typename p7##_type, typename p8##_type, \
+      typename p9##_type>\
+  template <typename arg_type>\
+  bool name##MatcherP10<p0##_type, p1##_type, p2##_type, p3##_type, \
+      p4##_type, p5##_type, p6##_type, p7##_type, p8##_type, \
+      p9##_type>::gmock_Impl<arg_type>::MatchAndExplain(\
+      arg_type arg,\
+      ::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_)\
+          const
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_MATCHERS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-nice-strict.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-nice-strict.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-generated-nice-strict.h	(revision 11817)
@@ -0,0 +1,274 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements class templates NiceMock and StrictMock.
+//
+// Given a mock class MockFoo that is created using Google Mock,
+// NiceMock<MockFoo> is a subclass of MockFoo that allows
+// uninteresting calls (i.e. calls to mock methods that have no
+// EXPECT_CALL specs), and StrictMock<MockFoo> is a subclass of
+// MockFoo that treats all uninteresting calls as errors.
+//
+// NiceMock and StrictMock "inherits" the constructors of their
+// respective base class, with up-to 10 arguments.  Therefore you can
+// write NiceMock<MockFoo>(5, "a") to construct a nice mock where
+// MockFoo has a constructor that accepts (int, const char*), for
+// example.
+//
+// A known limitation is that NiceMock<MockFoo> and
+// StrictMock<MockFoo> only works for mock methods defined using the
+// MOCK_METHOD* family of macros DIRECTLY in the MockFoo class.  If a
+// mock method is defined in a base class of MockFoo, the "nice" or
+// "strict" modifier may not affect it, depending on the compiler.  In
+// particular, nesting NiceMock and StrictMock is NOT supported.
+//
+// Another known limitation is that the constructors of the base mock
+// cannot have arguments passed by non-const reference, which are
+// banned by the Google C++ style guide anyway.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
+
+#include "gmock/gmock-spec-builders.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <class MockClass>
+class NiceMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  NiceMock() {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  // C++ doesn't (yet) allow inheritance of constructors, so we have
+  // to define it for each arity.
+  template <typename A1>
+  explicit NiceMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  NiceMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  NiceMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::AllowUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~NiceMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(NiceMock);
+};
+
+template <class MockClass>
+class StrictMock : public MockClass {
+ public:
+  // We don't factor out the constructor body to a common method, as
+  // we have to avoid a possible clash with members of MockClass.
+  StrictMock() {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1>
+  explicit StrictMock(const A1& a1) : MockClass(a1) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+  template <typename A1, typename A2>
+  StrictMock(const A1& a1, const A2& a2) : MockClass(a1, a2) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3) : MockClass(a1, a2, a3) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3,
+      const A4& a4) : MockClass(a1, a2, a3, a4) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5) : MockClass(a1, a2, a3, a4, a5) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6) : MockClass(a1, a2, a3, a4, a5, a6) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7) : MockClass(a1, a2, a3, a4, a5,
+      a6, a7) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8) : MockClass(a1,
+      a2, a3, a4, a5, a6, a7, a8) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8,
+      const A9& a9) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  template <typename A1, typename A2, typename A3, typename A4, typename A5,
+      typename A6, typename A7, typename A8, typename A9, typename A10>
+  StrictMock(const A1& a1, const A2& a2, const A3& a3, const A4& a4,
+      const A5& a5, const A6& a6, const A7& a7, const A8& a8, const A9& a9,
+      const A10& a10) : MockClass(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) {
+    ::testing::Mock::FailUninterestingCalls(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+  virtual ~StrictMock() {
+    ::testing::Mock::UnregisterCallReaction(
+        internal::ImplicitCast_<MockClass*>(this));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StrictMock);
+};
+
+// The following specializations catch some (relatively more common)
+// user errors of nesting nice and strict mocks.  They do NOT catch
+// all possible errors.
+
+// These specializations are declared but not defined, as NiceMock and
+// StrictMock cannot be nested.
+template <typename MockClass>
+class NiceMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class NiceMock<StrictMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<NiceMock<MockClass> >;
+template <typename MockClass>
+class StrictMock<StrictMock<MockClass> >;
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_NICE_STRICT_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-matchers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-matchers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-matchers.h	(revision 11817)
@@ -0,0 +1,3066 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some commonly used argument matchers.  More
+// matchers can be defined by the user implementing the
+// MatcherInterface<T> interface if necessary.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
+
+#include <algorithm>
+#include <limits>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// To implement a matcher Foo for type T, define:
+//   1. a class FooMatcherImpl that implements the
+//      MatcherInterface<T> interface, and
+//   2. a factory function that creates a Matcher<T> object from a
+//      FooMatcherImpl*.
+//
+// The two-level delegation design makes it possible to allow a user
+// to write "v" instead of "Eq(v)" where a Matcher is expected, which
+// is impossible if we pass matchers by pointers.  It also eases
+// ownership management as Matcher objects can now be copied like
+// plain values.
+
+// MatchResultListener is an abstract class.  Its << operator can be
+// used by a matcher to explain why a value matches or doesn't match.
+//
+// TODO(wan@google.com): add method
+//   bool InterestedInWhy(bool result) const;
+// to indicate whether the listener is interested in why the match
+// result is 'result'.
+class MatchResultListener {
+ public:
+  // Creates a listener object with the given underlying ostream.  The
+  // listener does not own the ostream.
+  explicit MatchResultListener(::std::ostream* os) : stream_(os) {}
+  virtual ~MatchResultListener() = 0;  // Makes this class abstract.
+
+  // Streams x to the underlying ostream; does nothing if the ostream
+  // is NULL.
+  template <typename T>
+  MatchResultListener& operator<<(const T& x) {
+    if (stream_ != NULL)
+      *stream_ << x;
+    return *this;
+  }
+
+  // Returns the underlying ostream.
+  ::std::ostream* stream() { return stream_; }
+
+  // Returns true iff the listener is interested in an explanation of
+  // the match result.  A matcher's MatchAndExplain() method can use
+  // this information to avoid generating the explanation when no one
+  // intends to hear it.
+  bool IsInterested() const { return stream_ != NULL; }
+
+ private:
+  ::std::ostream* const stream_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener);
+};
+
+inline MatchResultListener::~MatchResultListener() {
+}
+
+// The implementation of a matcher.
+template <typename T>
+class MatcherInterface {
+ public:
+  virtual ~MatcherInterface() {}
+
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener', in the form of a non-restrictive relative
+  // clause ("which ...", "whose ...", etc) that describes x.  For
+  // example, the MatchAndExplain() method of the Pointee(...) matcher
+  // should generate an explanation like "which points to ...".
+  //
+  // You should override this method when defining a new matcher.
+  //
+  // It's the responsibility of the caller (Google Mock) to guarantee
+  // that 'listener' is not NULL.  This helps to simplify a matcher's
+  // implementation when it doesn't care about the performance, as it
+  // can talk to 'listener' without checking its validity first.
+  // However, in order to implement dummy listeners efficiently,
+  // listener->stream() may be NULL.
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0;
+
+  // Describes this matcher to an ostream.  The function should print
+  // a verb phrase that describes the property a value matching this
+  // matcher should have.  The subject of the verb phrase is the value
+  // being matched.  For example, the DescribeTo() method of the Gt(7)
+  // matcher prints "is greater than 7".
+  virtual void DescribeTo(::std::ostream* os) const = 0;
+
+  // Describes the negation of this matcher to an ostream.  For
+  // example, if the description of this matcher is "is greater than
+  // 7", the negated description could be "is not greater than 7".
+  // You are not required to override this when implementing
+  // MatcherInterface, but it is highly advised so that your matcher
+  // can produce good error messages.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "not (";
+    DescribeTo(os);
+    *os << ")";
+  }
+};
+
+namespace internal {
+
+// A match result listener that ignores the explanation.
+class DummyMatchResultListener : public MatchResultListener {
+ public:
+  DummyMatchResultListener() : MatchResultListener(NULL) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener);
+};
+
+// A match result listener that forwards the explanation to a given
+// ostream.  The difference between this and MatchResultListener is
+// that the former is concrete.
+class StreamMatchResultListener : public MatchResultListener {
+ public:
+  explicit StreamMatchResultListener(::std::ostream* os)
+      : MatchResultListener(os) {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener);
+};
+
+// A match result listener that stores the explanation in a string.
+class StringMatchResultListener : public MatchResultListener {
+ public:
+  StringMatchResultListener() : MatchResultListener(&ss_) {}
+
+  // Returns the explanation heard so far.
+  internal::string str() const { return ss_.str(); }
+
+ private:
+  ::std::stringstream ss_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener);
+};
+
+// An internal class for implementing Matcher<T>, which will derive
+// from it.  We put functionalities common to all Matcher<T>
+// specializations here to avoid code duplication.
+template <typename T>
+class MatcherBase {
+ public:
+  // Returns true iff the matcher matches x; also explains the match
+  // result to 'listener'.
+  bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    return impl_->MatchAndExplain(x, listener);
+  }
+
+  // Returns true iff this matcher matches x.
+  bool Matches(T x) const {
+    DummyMatchResultListener dummy;
+    return MatchAndExplain(x, &dummy);
+  }
+
+  // Describes this matcher to an ostream.
+  void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); }
+
+  // Describes the negation of this matcher to an ostream.
+  void DescribeNegationTo(::std::ostream* os) const {
+    impl_->DescribeNegationTo(os);
+  }
+
+  // Explains why x matches, or doesn't match, the matcher.
+  void ExplainMatchResultTo(T x, ::std::ostream* os) const {
+    StreamMatchResultListener listener(os);
+    MatchAndExplain(x, &listener);
+  }
+
+ protected:
+  MatcherBase() {}
+
+  // Constructs a matcher from its implementation.
+  explicit MatcherBase(const MatcherInterface<T>* impl)
+      : impl_(impl) {}
+
+  virtual ~MatcherBase() {}
+
+ private:
+  // shared_ptr (util/gtl/shared_ptr.h) and linked_ptr have similar
+  // interfaces.  The former dynamically allocates a chunk of memory
+  // to hold the reference count, while the latter tracks all
+  // references using a circular linked list without allocating
+  // memory.  It has been observed that linked_ptr performs better in
+  // typical scenarios.  However, shared_ptr can out-perform
+  // linked_ptr when there are many more uses of the copy constructor
+  // than the default constructor.
+  //
+  // If performance becomes a problem, we should see if using
+  // shared_ptr helps.
+  ::testing::internal::linked_ptr<const MatcherInterface<T> > impl_;
+};
+
+}  // namespace internal
+
+// A Matcher<T> is a copyable and IMMUTABLE (except by assignment)
+// object that can check whether a value of type T matches.  The
+// implementation of Matcher<T> is just a linked_ptr to const
+// MatcherInterface<T>, so copying is fairly cheap.  Don't inherit
+// from Matcher!
+template <typename T>
+class Matcher : public internal::MatcherBase<T> {
+ public:
+  // Constructs a null matcher.  Needed for storing Matcher objects in STL
+  // containers.  A default-constructed matcher is not yet initialized.  You
+  // cannot use it until a valid value has been assigned to it.
+  Matcher() {}
+
+  // Constructs a matcher from its implementation.
+  explicit Matcher(const MatcherInterface<T>* impl)
+      : internal::MatcherBase<T>(impl) {}
+
+  // Implicit constructor here allows people to write
+  // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes
+  Matcher(T value);  // NOLINT
+};
+
+// The following two specializations allow the user to write str
+// instead of Eq(str) and "foo" instead of Eq("foo") when a string
+// matcher is expected.
+template <>
+class Matcher<const internal::string&>
+    : public internal::MatcherBase<const internal::string&> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<const internal::string&>* impl)
+      : internal::MatcherBase<const internal::string&>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+template <>
+class Matcher<internal::string>
+    : public internal::MatcherBase<internal::string> {
+ public:
+  Matcher() {}
+
+  explicit Matcher(const MatcherInterface<internal::string>* impl)
+      : internal::MatcherBase<internal::string>(impl) {}
+
+  // Allows the user to write str instead of Eq(str) sometimes, where
+  // str is a string object.
+  Matcher(const internal::string& s);  // NOLINT
+
+  // Allows the user to write "foo" instead of Eq("foo") sometimes.
+  Matcher(const char* s);  // NOLINT
+};
+
+// The PolymorphicMatcher class template makes it easy to implement a
+// polymorphic matcher (i.e. a matcher that can match values of more
+// than one type, e.g. Eq(n) and NotNull()).
+//
+// To define a polymorphic matcher, a user should provide an Impl
+// class that has a DescribeTo() method and a DescribeNegationTo()
+// method, and define a member function (or member function template)
+//
+//   bool MatchAndExplain(const Value& value,
+//                        MatchResultListener* listener) const;
+//
+// See the definition of NotNull() for a complete example.
+template <class Impl>
+class PolymorphicMatcher {
+ public:
+  explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
+
+  // Returns a mutable reference to the underlying matcher
+  // implementation object.
+  Impl& mutable_impl() { return impl_; }
+
+  // Returns an immutable reference to the underlying matcher
+  // implementation object.
+  const Impl& impl() const { return impl_; }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new MonomorphicImpl<T>(impl_));
+  }
+
+ private:
+  template <typename T>
+  class MonomorphicImpl : public MatcherInterface<T> {
+   public:
+    explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      impl_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      impl_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return impl_.MatchAndExplain(x, listener);
+    }
+
+   private:
+    const Impl impl_;
+
+    GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
+  };
+
+  Impl impl_;
+
+  GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher);
+};
+
+// Creates a matcher from its implementation.  This is easier to use
+// than the Matcher<T> constructor as it doesn't require you to
+// explicitly write the template argument, e.g.
+//
+//   MakeMatcher(foo);
+// vs
+//   Matcher<const string&>(foo);
+template <typename T>
+inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
+  return Matcher<T>(impl);
+};
+
+// Creates a polymorphic matcher from its implementation.  This is
+// easier to use than the PolymorphicMatcher<Impl> constructor as it
+// doesn't require you to explicitly write the template argument, e.g.
+//
+//   MakePolymorphicMatcher(foo);
+// vs
+//   PolymorphicMatcher<TypeOfFoo>(foo);
+template <class Impl>
+inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
+  return PolymorphicMatcher<Impl>(impl);
+}
+
+// In order to be safe and clear, casting between different matcher
+// types is done explicitly via MatcherCast<T>(m), which takes a
+// matcher m and returns a Matcher<T>.  It compiles only when T can be
+// statically converted to the argument type of m.
+template <typename T, typename M>
+Matcher<T> MatcherCast(M m);
+
+// Implements SafeMatcherCast().
+//
+// We use an intermediate class to do the actual safe casting as Nokia's
+// Symbian compiler cannot decide between
+// template <T, M> ... (M) and
+// template <T, U> ... (const Matcher<U>&)
+// for function templates but can for member function templates.
+template <typename T>
+class SafeMatcherCastImpl {
+ public:
+  // This overload handles polymorphic matchers only since monomorphic
+  // matchers are handled by the next one.
+  template <typename M>
+  static inline Matcher<T> Cast(M polymorphic_matcher) {
+    return Matcher<T>(polymorphic_matcher);
+  }
+
+  // This overload handles monomorphic matchers.
+  //
+  // In general, if type T can be implicitly converted to type U, we can
+  // safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is
+  // contravariant): just keep a copy of the original Matcher<U>, convert the
+  // argument from type T to U, and then pass it to the underlying Matcher<U>.
+  // The only exception is when U is a reference and T is not, as the
+  // underlying Matcher<U> may be interested in the argument's address, which
+  // is not preserved in the conversion from T to U.
+  template <typename U>
+  static inline Matcher<T> Cast(const Matcher<U>& matcher) {
+    // Enforce that T can be implicitly converted to U.
+    GTEST_COMPILE_ASSERT_((internal::ImplicitlyConvertible<T, U>::value),
+                          T_must_be_implicitly_convertible_to_U);
+    // Enforce that we are not converting a non-reference type T to a reference
+    // type U.
+    GTEST_COMPILE_ASSERT_(
+        internal::is_reference<T>::value || !internal::is_reference<U>::value,
+        cannot_convert_non_referentce_arg_to_reference);
+    // In case both T and U are arithmetic types, enforce that the
+    // conversion is not lossy.
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT;
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU;
+    const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther;
+    const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther;
+    GTEST_COMPILE_ASSERT_(
+        kTIsOther || kUIsOther ||
+        (internal::LosslessArithmeticConvertible<RawT, RawU>::value),
+        conversion_of_arithmetic_types_must_be_lossless);
+    return MatcherCast<T>(matcher);
+  }
+};
+
+template <typename T, typename M>
+inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher) {
+  return SafeMatcherCastImpl<T>::Cast(polymorphic_matcher);
+}
+
+// A<T>() returns a matcher that matches any value of type T.
+template <typename T>
+Matcher<T> A();
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// If the explanation is not empty, prints it to the ostream.
+inline void PrintIfNotEmpty(const internal::string& explanation,
+                            std::ostream* os) {
+  if (explanation != "" && os != NULL) {
+    *os << ", " << explanation;
+  }
+}
+
+// Returns true if the given type name is easy to read by a human.
+// This is used to decide whether printing the type of a value might
+// be helpful.
+inline bool IsReadableTypeName(const string& type_name) {
+  // We consider a type name readable if it's short or doesn't contain
+  // a template or function type.
+  return (type_name.length() <= 20 ||
+          type_name.find_first_of("<(") == string::npos);
+}
+
+// Matches the value against the given matcher, prints the value and explains
+// the match result to the listener. Returns the match result.
+// 'listener' must not be NULL.
+// Value cannot be passed by const reference, because some matchers take a
+// non-const argument.
+template <typename Value, typename T>
+bool MatchPrintAndExplain(Value& value, const Matcher<T>& matcher,
+                          MatchResultListener* listener) {
+  if (!listener->IsInterested()) {
+    // If the listener is not interested, we do not need to construct the
+    // inner explanation.
+    return matcher.Matches(value);
+  }
+
+  StringMatchResultListener inner_listener;
+  const bool match = matcher.MatchAndExplain(value, &inner_listener);
+
+  UniversalPrint(value, listener->stream());
+#if GTEST_HAS_RTTI
+  const string& type_name = GetTypeName<Value>();
+  if (IsReadableTypeName(type_name))
+    *listener->stream() << " (of type " << type_name << ")";
+#endif
+  PrintIfNotEmpty(inner_listener.str(), listener->stream());
+
+  return match;
+}
+
+// An internal helper class for doing compile-time loop on a tuple's
+// fields.
+template <size_t N>
+class TuplePrefix {
+ public:
+  // TuplePrefix<N>::Matches(matcher_tuple, value_tuple) returns true
+  // iff the first N fields of matcher_tuple matches the first N
+  // fields of value_tuple, respectively.
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& matcher_tuple,
+                      const ValueTuple& value_tuple) {
+    using ::std::tr1::get;
+    return TuplePrefix<N - 1>::Matches(matcher_tuple, value_tuple)
+        && get<N - 1>(matcher_tuple).Matches(get<N - 1>(value_tuple));
+  }
+
+  // TuplePrefix<N>::ExplainMatchFailuresTo(matchers, values, os)
+  // describes failures in matching the first N fields of matchers
+  // against the first N fields of values.  If there is no failure,
+  // nothing will be streamed to os.
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& matchers,
+                                     const ValueTuple& values,
+                                     ::std::ostream* os) {
+    using ::std::tr1::tuple_element;
+    using ::std::tr1::get;
+
+    // First, describes failures in the first N - 1 fields.
+    TuplePrefix<N - 1>::ExplainMatchFailuresTo(matchers, values, os);
+
+    // Then describes the failure (if any) in the (N - 1)-th (0-based)
+    // field.
+    typename tuple_element<N - 1, MatcherTuple>::type matcher =
+        get<N - 1>(matchers);
+    typedef typename tuple_element<N - 1, ValueTuple>::type Value;
+    Value value = get<N - 1>(values);
+    StringMatchResultListener listener;
+    if (!matcher.MatchAndExplain(value, &listener)) {
+      // TODO(wan): include in the message the name of the parameter
+      // as used in MOCK_METHOD*() when possible.
+      *os << "  Expected arg #" << N - 1 << ": ";
+      get<N - 1>(matchers).DescribeTo(os);
+      *os << "\n           Actual: ";
+      // We remove the reference in type Value to prevent the
+      // universal printer from printing the address of value, which
+      // isn't interesting to the user most of the time.  The
+      // matcher's MatchAndExplain() method handles the case when
+      // the address is interesting.
+      internal::UniversalPrint(value, os);
+      PrintIfNotEmpty(listener.str(), os);
+      *os << "\n";
+    }
+  }
+};
+
+// The base case.
+template <>
+class TuplePrefix<0> {
+ public:
+  template <typename MatcherTuple, typename ValueTuple>
+  static bool Matches(const MatcherTuple& /* matcher_tuple */,
+                      const ValueTuple& /* value_tuple */) {
+    return true;
+  }
+
+  template <typename MatcherTuple, typename ValueTuple>
+  static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */,
+                                     const ValueTuple& /* values */,
+                                     ::std::ostream* /* os */) {}
+};
+
+// TupleMatches(matcher_tuple, value_tuple) returns true iff all
+// matchers in matcher_tuple match the corresponding fields in
+// value_tuple.  It is a compiler error if matcher_tuple and
+// value_tuple have different number of fields or incompatible field
+// types.
+template <typename MatcherTuple, typename ValueTuple>
+bool TupleMatches(const MatcherTuple& matcher_tuple,
+                  const ValueTuple& value_tuple) {
+  using ::std::tr1::tuple_size;
+  // Makes sure that matcher_tuple and value_tuple have the same
+  // number of fields.
+  GTEST_COMPILE_ASSERT_(tuple_size<MatcherTuple>::value ==
+                        tuple_size<ValueTuple>::value,
+                        matcher_and_value_have_different_numbers_of_fields);
+  return TuplePrefix<tuple_size<ValueTuple>::value>::
+      Matches(matcher_tuple, value_tuple);
+}
+
+// Describes failures in matching matchers against values.  If there
+// is no failure, nothing will be streamed to os.
+template <typename MatcherTuple, typename ValueTuple>
+void ExplainMatchFailureTupleTo(const MatcherTuple& matchers,
+                                const ValueTuple& values,
+                                ::std::ostream* os) {
+  using ::std::tr1::tuple_size;
+  TuplePrefix<tuple_size<MatcherTuple>::value>::ExplainMatchFailuresTo(
+      matchers, values, os);
+}
+
+// The MatcherCastImpl class template is a helper for implementing
+// MatcherCast().  We need this helper in order to partially
+// specialize the implementation of MatcherCast() (C++ allows
+// class/struct templates to be partially specialized, but not
+// function templates.).
+
+// This general version is used when MatcherCast()'s argument is a
+// polymorphic matcher (i.e. something that can be converted to a
+// Matcher but is not one yet; for example, Eq(value)).
+template <typename T, typename M>
+class MatcherCastImpl {
+ public:
+  static Matcher<T> Cast(M polymorphic_matcher) {
+    return Matcher<T>(polymorphic_matcher);
+  }
+};
+
+// This more specialized version is used when MatcherCast()'s argument
+// is already a Matcher.  This only compiles when type T can be
+// statically converted to type U.
+template <typename T, typename U>
+class MatcherCastImpl<T, Matcher<U> > {
+ public:
+  static Matcher<T> Cast(const Matcher<U>& source_matcher) {
+    return Matcher<T>(new Impl(source_matcher));
+  }
+
+ private:
+  class Impl : public MatcherInterface<T> {
+   public:
+    explicit Impl(const Matcher<U>& source_matcher)
+        : source_matcher_(source_matcher) {}
+
+    // We delegate the matching logic to the source matcher.
+    virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+      return source_matcher_.MatchAndExplain(static_cast<U>(x), listener);
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      source_matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      source_matcher_.DescribeNegationTo(os);
+    }
+
+   private:
+    const Matcher<U> source_matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+};
+
+// This even more specialized version is used for efficiently casting
+// a matcher to its own type.
+template <typename T>
+class MatcherCastImpl<T, Matcher<T> > {
+ public:
+  static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; }
+};
+
+// Implements A<T>().
+template <typename T>
+class AnyMatcherImpl : public MatcherInterface<T> {
+ public:
+  virtual bool MatchAndExplain(
+      T /* x */, MatchResultListener* /* listener */) const { return true; }
+  virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; }
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    // This is mostly for completeness' safe, as it's not very useful
+    // to write Not(A<bool>()).  However we cannot completely rule out
+    // such a possibility, and it doesn't hurt to be prepared.
+    *os << "never matches";
+  }
+};
+
+// Implements _, a matcher that matches any value of any
+// type.  This is a polymorphic matcher, so we need a template type
+// conversion operator to make it appearing as a Matcher<T> for any
+// type T.
+class AnythingMatcher {
+ public:
+  template <typename T>
+  operator Matcher<T>() const { return A<T>(); }
+};
+
+// Implements a matcher that compares a given value with a
+// pre-supplied value using one of the ==, <=, <, etc, operators.  The
+// two values being compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq(5) can be
+// used to match an int, a short, a double, etc).  Therefore we use
+// a template type conversion operator in the implementation.
+//
+// We define this as a macro in order to eliminate duplicated source
+// code.
+//
+// The following template definition assumes that the Rhs parameter is
+// a "bare" type (i.e. neither 'const T' nor 'T&').
+#define GMOCK_IMPLEMENT_COMPARISON_MATCHER_( \
+    name, op, relation, negated_relation) \
+  template <typename Rhs> class name##Matcher { \
+   public: \
+    explicit name##Matcher(const Rhs& rhs) : rhs_(rhs) {} \
+    template <typename Lhs> \
+    operator Matcher<Lhs>() const { \
+      return MakeMatcher(new Impl<Lhs>(rhs_)); \
+    } \
+   private: \
+    template <typename Lhs> \
+    class Impl : public MatcherInterface<Lhs> { \
+     public: \
+      explicit Impl(const Rhs& rhs) : rhs_(rhs) {} \
+      virtual bool MatchAndExplain(\
+          Lhs lhs, MatchResultListener* /* listener */) const { \
+        return lhs op rhs_; \
+      } \
+      virtual void DescribeTo(::std::ostream* os) const { \
+        *os << relation  " "; \
+        UniversalPrint(rhs_, os); \
+      } \
+      virtual void DescribeNegationTo(::std::ostream* os) const { \
+        *os << negated_relation  " "; \
+        UniversalPrint(rhs_, os); \
+      } \
+     private: \
+      Rhs rhs_; \
+      GTEST_DISALLOW_ASSIGN_(Impl); \
+    }; \
+    Rhs rhs_; \
+    GTEST_DISALLOW_ASSIGN_(name##Matcher); \
+  }
+
+// Implements Eq(v), Ge(v), Gt(v), Le(v), Lt(v), and Ne(v)
+// respectively.
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Eq, ==, "is equal to", "isn't equal to");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Ge, >=, "is >=", "isn't >=");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Gt, >, "is >", "isn't >");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Le, <=, "is <=", "isn't <=");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Lt, <, "is <", "isn't <");
+GMOCK_IMPLEMENT_COMPARISON_MATCHER_(Ne, !=, "isn't equal to", "is equal to");
+
+#undef GMOCK_IMPLEMENT_COMPARISON_MATCHER_
+
+// Implements the polymorphic IsNull() matcher, which matches any raw or smart
+// pointer that is NULL.
+class IsNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+    return GetRawPointer(p) == NULL;
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "is NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "isn't NULL";
+  }
+};
+
+// Implements the polymorphic NotNull() matcher, which matches any raw or smart
+// pointer that is not NULL.
+class NotNullMatcher {
+ public:
+  template <typename Pointer>
+  bool MatchAndExplain(const Pointer& p,
+                       MatchResultListener* /* listener */) const {
+    return GetRawPointer(p) != NULL;
+  }
+
+  void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is NULL";
+  }
+};
+
+// Ref(variable) matches any argument that is a reference to
+// 'variable'.  This matcher is polymorphic as it can match any
+// super type of the type of 'variable'.
+//
+// The RefMatcher template class implements Ref(variable).  It can
+// only be instantiated with a reference type.  This prevents a user
+// from mistakenly using Ref(x) to match a non-reference function
+// argument.  For example, the following will righteously cause a
+// compiler error:
+//
+//   int n;
+//   Matcher<int> m1 = Ref(n);   // This won't compile.
+//   Matcher<int&> m2 = Ref(n);  // This will compile.
+template <typename T>
+class RefMatcher;
+
+template <typename T>
+class RefMatcher<T&> {
+  // Google Mock is a generic framework and thus needs to support
+  // mocking any function types, including those that take non-const
+  // reference arguments.  Therefore the template parameter T (and
+  // Super below) can be instantiated to either a const type or a
+  // non-const type.
+ public:
+  // RefMatcher() takes a T& instead of const T&, as we want the
+  // compiler to catch using Ref(const_value) as a matcher for a
+  // non-const reference.
+  explicit RefMatcher(T& x) : object_(x) {}  // NOLINT
+
+  template <typename Super>
+  operator Matcher<Super&>() const {
+    // By passing object_ (type T&) to Impl(), which expects a Super&,
+    // we make sure that Super is a super type of T.  In particular,
+    // this catches using Ref(const_value) as a matcher for a
+    // non-const reference, as you cannot implicitly convert a const
+    // reference to a non-const reference.
+    return MakeMatcher(new Impl<Super>(object_));
+  }
+
+ private:
+  template <typename Super>
+  class Impl : public MatcherInterface<Super&> {
+   public:
+    explicit Impl(Super& x) : object_(x) {}  // NOLINT
+
+    // MatchAndExplain() takes a Super& (as opposed to const Super&)
+    // in order to match the interface MatcherInterface<Super&>.
+    virtual bool MatchAndExplain(
+        Super& x, MatchResultListener* listener) const {
+      *listener << "which is located @" << static_cast<const void*>(&x);
+      return &x == &object_;
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "references the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "does not reference the variable ";
+      UniversalPrinter<Super&>::Print(object_, os);
+    }
+
+   private:
+    const Super& object_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  T& object_;
+
+  GTEST_DISALLOW_ASSIGN_(RefMatcher);
+};
+
+// Polymorphic helper functions for narrow and wide string matchers.
+inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) {
+  return String::CaseInsensitiveCStringEquals(lhs, rhs);
+}
+
+inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs,
+                                         const wchar_t* rhs) {
+  return String::CaseInsensitiveWideCStringEquals(lhs, rhs);
+}
+
+// String comparison for narrow or wide strings that can have embedded NUL
+// characters.
+template <typename StringType>
+bool CaseInsensitiveStringEquals(const StringType& s1,
+                                 const StringType& s2) {
+  // Are the heads equal?
+  if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) {
+    return false;
+  }
+
+  // Skip the equal heads.
+  const typename StringType::value_type nul = 0;
+  const size_t i1 = s1.find(nul), i2 = s2.find(nul);
+
+  // Are we at the end of either s1 or s2?
+  if (i1 == StringType::npos || i2 == StringType::npos) {
+    return i1 == i2;
+  }
+
+  // Are the tails equal?
+  return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1));
+}
+
+// String matchers.
+
+// Implements equality-based string matchers like StrEq, StrCaseNe, and etc.
+template <typename StringType>
+class StrEqualityMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  StrEqualityMatcher(const StringType& str, bool expect_eq,
+                     bool case_sensitive)
+      : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {}
+
+  // When expect_eq_ is true, returns true iff s is equal to string_;
+  // otherwise returns true iff s is not equal to string_.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    if (s == NULL) {
+      return !expect_eq_;
+    }
+    return MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    const bool eq = case_sensitive_ ? s == string_ :
+        CaseInsensitiveStringEquals(s, string_);
+    return expect_eq_ == eq;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    DescribeToHelper(expect_eq_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    DescribeToHelper(!expect_eq_, os);
+  }
+
+ private:
+  void DescribeToHelper(bool expect_eq, ::std::ostream* os) const {
+    *os << (expect_eq ? "is " : "isn't ");
+    *os << "equal to ";
+    if (!case_sensitive_) {
+      *os << "(ignoring case) ";
+    }
+    UniversalPrint(string_, os);
+  }
+
+  const StringType string_;
+  const bool expect_eq_;
+  const bool case_sensitive_;
+
+  GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher);
+};
+
+// Implements the polymorphic HasSubstr(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class HasSubstrMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  explicit HasSubstrMatcher(const StringType& substring)
+      : substring_(substring) {}
+
+  // These overloaded methods allow HasSubstr(substring) to be used as a
+  // Matcher<T> as long as T can be converted to string.  Returns true
+  // iff s contains substring_ as a substring.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    return s.find(substring_) != StringType::npos;
+  }
+
+  // Describes what this matcher matches.
+  void DescribeTo(::std::ostream* os) const {
+    *os << "has substring ";
+    UniversalPrint(substring_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has no substring ";
+    UniversalPrint(substring_, os);
+  }
+
+ private:
+  const StringType substring_;
+
+  GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher);
+};
+
+// Implements the polymorphic StartsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class StartsWithMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) {
+  }
+
+  // These overloaded methods allow StartsWith(prefix) to be used as a
+  // Matcher<T> as long as T can be converted to string.  Returns true
+  // iff s starts with prefix_.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    return s.length() >= prefix_.length() &&
+        s.substr(0, prefix_.length()) == prefix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "starts with ";
+    UniversalPrint(prefix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't start with ";
+    UniversalPrint(prefix_, os);
+  }
+
+ private:
+  const StringType prefix_;
+
+  GTEST_DISALLOW_ASSIGN_(StartsWithMatcher);
+};
+
+// Implements the polymorphic EndsWith(substring) matcher, which
+// can be used as a Matcher<T> as long as T can be converted to a
+// string.
+template <typename StringType>
+class EndsWithMatcher {
+ public:
+  typedef typename StringType::const_pointer ConstCharPointer;
+
+  explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {}
+
+  // These overloaded methods allow EndsWith(suffix) to be used as a
+  // Matcher<T> as long as T can be converted to string.  Returns true
+  // iff s ends with suffix_.
+  bool MatchAndExplain(ConstCharPointer s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(StringType(s), listener);
+  }
+
+  bool MatchAndExplain(const StringType& s,
+                       MatchResultListener* /* listener */) const {
+    return s.length() >= suffix_.length() &&
+        s.substr(s.length() - suffix_.length()) == suffix_;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "ends with ";
+    UniversalPrint(suffix_, os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't end with ";
+    UniversalPrint(suffix_, os);
+  }
+
+ private:
+  const StringType suffix_;
+
+  GTEST_DISALLOW_ASSIGN_(EndsWithMatcher);
+};
+
+// Implements polymorphic matchers MatchesRegex(regex) and
+// ContainsRegex(regex), which can be used as a Matcher<T> as long as
+// T can be converted to a string.
+class MatchesRegexMatcher {
+ public:
+  MatchesRegexMatcher(const RE* regex, bool full_match)
+      : regex_(regex), full_match_(full_match) {}
+
+  // These overloaded methods allow MatchesRegex(regex) to be used as
+  // a Matcher<T> as long as T can be converted to string.  Returns
+  // true iff s matches regular expression regex.  When full_match_ is
+  // true, a full match is done; otherwise a partial match is done.
+  bool MatchAndExplain(const char* s,
+                       MatchResultListener* listener) const {
+    return s != NULL && MatchAndExplain(internal::string(s), listener);
+  }
+
+  bool MatchAndExplain(const internal::string& s,
+                       MatchResultListener* /* listener */) const {
+    return full_match_ ? RE::FullMatch(s, *regex_) :
+        RE::PartialMatch(s, *regex_);
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << (full_match_ ? "matches" : "contains")
+        << " regular expression ";
+    UniversalPrinter<internal::string>::Print(regex_->pattern(), os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't " << (full_match_ ? "match" : "contain")
+        << " regular expression ";
+    UniversalPrinter<internal::string>::Print(regex_->pattern(), os);
+  }
+
+ private:
+  const internal::linked_ptr<const RE> regex_;
+  const bool full_match_;
+
+  GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher);
+};
+
+// Implements a matcher that compares the two fields of a 2-tuple
+// using one of the ==, <=, <, etc, operators.  The two fields being
+// compared don't have to have the same type.
+//
+// The matcher defined here is polymorphic (for example, Eq() can be
+// used to match a tuple<int, short>, a tuple<const long&, double>,
+// etc).  Therefore we use a template type conversion operator in the
+// implementation.
+//
+// We define this as a macro in order to eliminate duplicated source
+// code.
+#define GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(name, op, relation) \
+  class name##2Matcher { \
+   public: \
+    template <typename T1, typename T2> \
+    operator Matcher< ::std::tr1::tuple<T1, T2> >() const { \
+      return MakeMatcher(new Impl< ::std::tr1::tuple<T1, T2> >); \
+    } \
+    template <typename T1, typename T2> \
+    operator Matcher<const ::std::tr1::tuple<T1, T2>&>() const { \
+      return MakeMatcher(new Impl<const ::std::tr1::tuple<T1, T2>&>); \
+    } \
+   private: \
+    template <typename Tuple> \
+    class Impl : public MatcherInterface<Tuple> { \
+     public: \
+      virtual bool MatchAndExplain( \
+          Tuple args, \
+          MatchResultListener* /* listener */) const { \
+        return ::std::tr1::get<0>(args) op ::std::tr1::get<1>(args); \
+      } \
+      virtual void DescribeTo(::std::ostream* os) const { \
+        *os << "are " relation;                                 \
+      } \
+      virtual void DescribeNegationTo(::std::ostream* os) const { \
+        *os << "aren't " relation; \
+      } \
+    }; \
+  }
+
+// Implements Eq(), Ge(), Gt(), Le(), Lt(), and Ne() respectively.
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Eq, ==, "an equal pair");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Ge, >=, "a pair where the first >= the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Gt, >, "a pair where the first > the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Le, <=, "a pair where the first <= the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(
+    Lt, <, "a pair where the first < the second");
+GMOCK_IMPLEMENT_COMPARISON2_MATCHER_(Ne, !=, "an unequal pair");
+
+#undef GMOCK_IMPLEMENT_COMPARISON2_MATCHER_
+
+// Implements the Not(...) matcher for a particular argument type T.
+// We do not nest it inside the NotMatcher class template, as that
+// will prevent different instantiations of NotMatcher from sharing
+// the same NotMatcherImpl<T> class.
+template <typename T>
+class NotMatcherImpl : public MatcherInterface<T> {
+ public:
+  explicit NotMatcherImpl(const Matcher<T>& matcher)
+      : matcher_(matcher) {}
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    return !matcher_.MatchAndExplain(x, listener);
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    matcher_.DescribeNegationTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<T> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(NotMatcherImpl);
+};
+
+// Implements the Not(m) matcher, which matches a value that doesn't
+// match matcher m.
+template <typename InnerMatcher>
+class NotMatcher {
+ public:
+  explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {}
+
+  // This template type conversion operator allows Not(m) to be used
+  // to match any type m can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_)));
+  }
+
+ private:
+  InnerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(NotMatcher);
+};
+
+// Implements the AllOf(m1, m2) matcher for a particular argument type
+// T. We do not nest it inside the BothOfMatcher class template, as
+// that will prevent different instantiations of BothOfMatcher from
+// sharing the same BothOfMatcherImpl<T> class.
+template <typename T>
+class BothOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  BothOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") and (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeNegationTo(os);
+    *os << ") or (";
+    matcher2_.DescribeNegationTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    // If either matcher1_ or matcher2_ doesn't match x, we only need
+    // to explain why one of them fails.
+    StringMatchResultListener listener1;
+    if (!matcher1_.MatchAndExplain(x, &listener1)) {
+      *listener << listener1.str();
+      return false;
+    }
+
+    StringMatchResultListener listener2;
+    if (!matcher2_.MatchAndExplain(x, &listener2)) {
+      *listener << listener2.str();
+      return false;
+    }
+
+    // Otherwise we need to explain why *both* of them match.
+    const internal::string s1 = listener1.str();
+    const internal::string s2 = listener2.str();
+
+    if (s1 == "") {
+      *listener << s2;
+    } else {
+      *listener << s1;
+      if (s2 != "") {
+        *listener << ", and " << s2;
+      }
+    }
+    return true;
+  }
+
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(BothOfMatcherImpl);
+};
+
+// Used for implementing the AllOf(m_1, ..., m_n) matcher, which
+// matches a value that matches all of the matchers m_1, ..., and m_n.
+template <typename Matcher1, typename Matcher2>
+class BothOfMatcher {
+ public:
+  BothOfMatcher(Matcher1 matcher1, Matcher2 matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  // This template type conversion operator allows a
+  // BothOfMatcher<Matcher1, Matcher2> object to match any type that
+  // both Matcher1 and Matcher2 can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new BothOfMatcherImpl<T>(SafeMatcherCast<T>(matcher1_),
+                                               SafeMatcherCast<T>(matcher2_)));
+  }
+
+ private:
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(BothOfMatcher);
+};
+
+// Implements the AnyOf(m1, m2) matcher for a particular argument type
+// T.  We do not nest it inside the AnyOfMatcher class template, as
+// that will prevent different instantiations of AnyOfMatcher from
+// sharing the same EitherOfMatcherImpl<T> class.
+template <typename T>
+class EitherOfMatcherImpl : public MatcherInterface<T> {
+ public:
+  EitherOfMatcherImpl(const Matcher<T>& matcher1, const Matcher<T>& matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeTo(os);
+    *os << ") or (";
+    matcher2_.DescribeTo(os);
+    *os << ")";
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "(";
+    matcher1_.DescribeNegationTo(os);
+    *os << ") and (";
+    matcher2_.DescribeNegationTo(os);
+    *os << ")";
+  }
+
+  virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
+    // If either matcher1_ or matcher2_ matches x, we just need to
+    // explain why *one* of them matches.
+    StringMatchResultListener listener1;
+    if (matcher1_.MatchAndExplain(x, &listener1)) {
+      *listener << listener1.str();
+      return true;
+    }
+
+    StringMatchResultListener listener2;
+    if (matcher2_.MatchAndExplain(x, &listener2)) {
+      *listener << listener2.str();
+      return true;
+    }
+
+    // Otherwise we need to explain why *both* of them fail.
+    const internal::string s1 = listener1.str();
+    const internal::string s2 = listener2.str();
+
+    if (s1 == "") {
+      *listener << s2;
+    } else {
+      *listener << s1;
+      if (s2 != "") {
+        *listener << ", and " << s2;
+      }
+    }
+    return false;
+  }
+
+ private:
+  const Matcher<T> matcher1_;
+  const Matcher<T> matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(EitherOfMatcherImpl);
+};
+
+// Used for implementing the AnyOf(m_1, ..., m_n) matcher, which
+// matches a value that matches at least one of the matchers m_1, ...,
+// and m_n.
+template <typename Matcher1, typename Matcher2>
+class EitherOfMatcher {
+ public:
+  EitherOfMatcher(Matcher1 matcher1, Matcher2 matcher2)
+      : matcher1_(matcher1), matcher2_(matcher2) {}
+
+  // This template type conversion operator allows a
+  // EitherOfMatcher<Matcher1, Matcher2> object to match any type that
+  // both Matcher1 and Matcher2 can match.
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new EitherOfMatcherImpl<T>(
+        SafeMatcherCast<T>(matcher1_), SafeMatcherCast<T>(matcher2_)));
+  }
+
+ private:
+  Matcher1 matcher1_;
+  Matcher2 matcher2_;
+
+  GTEST_DISALLOW_ASSIGN_(EitherOfMatcher);
+};
+
+// Used for implementing Truly(pred), which turns a predicate into a
+// matcher.
+template <typename Predicate>
+class TrulyMatcher {
+ public:
+  explicit TrulyMatcher(Predicate pred) : predicate_(pred) {}
+
+  // This method template allows Truly(pred) to be used as a matcher
+  // for type T where T is the argument type of predicate 'pred'.  The
+  // argument is passed by reference as the predicate may be
+  // interested in the address of the argument.
+  template <typename T>
+  bool MatchAndExplain(T& x,  // NOLINT
+                       MatchResultListener* /* listener */) const {
+    // Without the if-statement, MSVC sometimes warns about converting
+    // a value to bool (warning 4800).
+    //
+    // We cannot write 'return !!predicate_(x);' as that doesn't work
+    // when predicate_(x) returns a class convertible to bool but
+    // having no operator!().
+    if (predicate_(x))
+      return true;
+    return false;
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "satisfies the given predicate";
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't satisfy the given predicate";
+  }
+
+ private:
+  Predicate predicate_;
+
+  GTEST_DISALLOW_ASSIGN_(TrulyMatcher);
+};
+
+// Used for implementing Matches(matcher), which turns a matcher into
+// a predicate.
+template <typename M>
+class MatcherAsPredicate {
+ public:
+  explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {}
+
+  // This template operator() allows Matches(m) to be used as a
+  // predicate on type T where m is a matcher on type T.
+  //
+  // The argument x is passed by reference instead of by value, as
+  // some matcher may be interested in its address (e.g. as in
+  // Matches(Ref(n))(x)).
+  template <typename T>
+  bool operator()(const T& x) const {
+    // We let matcher_ commit to a particular type here instead of
+    // when the MatcherAsPredicate object was constructed.  This
+    // allows us to write Matches(m) where m is a polymorphic matcher
+    // (e.g. Eq(5)).
+    //
+    // If we write Matcher<T>(matcher_).Matches(x) here, it won't
+    // compile when matcher_ has type Matcher<const T&>; if we write
+    // Matcher<const T&>(matcher_).Matches(x) here, it won't compile
+    // when matcher_ has type Matcher<T>; if we just write
+    // matcher_.Matches(x), it won't compile when matcher_ is
+    // polymorphic, e.g. Eq(5).
+    //
+    // MatcherCast<const T&>() is necessary for making the code work
+    // in all of the above situations.
+    return MatcherCast<const T&>(matcher_).Matches(x);
+  }
+
+ private:
+  M matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(MatcherAsPredicate);
+};
+
+// For implementing ASSERT_THAT() and EXPECT_THAT().  The template
+// argument M must be a type that can be converted to a matcher.
+template <typename M>
+class PredicateFormatterFromMatcher {
+ public:
+  explicit PredicateFormatterFromMatcher(const M& m) : matcher_(m) {}
+
+  // This template () operator allows a PredicateFormatterFromMatcher
+  // object to act as a predicate-formatter suitable for using with
+  // Google Test's EXPECT_PRED_FORMAT1() macro.
+  template <typename T>
+  AssertionResult operator()(const char* value_text, const T& x) const {
+    // We convert matcher_ to a Matcher<const T&> *now* instead of
+    // when the PredicateFormatterFromMatcher object was constructed,
+    // as matcher_ may be polymorphic (e.g. NotNull()) and we won't
+    // know which type to instantiate it to until we actually see the
+    // type of x here.
+    //
+    // We write MatcherCast<const T&>(matcher_) instead of
+    // Matcher<const T&>(matcher_), as the latter won't compile when
+    // matcher_ has type Matcher<T> (e.g. An<int>()).
+    const Matcher<const T&> matcher = MatcherCast<const T&>(matcher_);
+    StringMatchResultListener listener;
+    if (MatchPrintAndExplain(x, matcher, &listener))
+      return AssertionSuccess();
+
+    ::std::stringstream ss;
+    ss << "Value of: " << value_text << "\n"
+       << "Expected: ";
+    matcher.DescribeTo(&ss);
+    ss << "\n  Actual: " << listener.str();
+    return AssertionFailure() << ss.str();
+  }
+
+ private:
+  const M matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PredicateFormatterFromMatcher);
+};
+
+// A helper function for converting a matcher to a predicate-formatter
+// without the user needing to explicitly write the type.  This is
+// used for implementing ASSERT_THAT() and EXPECT_THAT().
+template <typename M>
+inline PredicateFormatterFromMatcher<M>
+MakePredicateFormatterFromMatcher(const M& matcher) {
+  return PredicateFormatterFromMatcher<M>(matcher);
+}
+
+// Implements the polymorphic floating point equality matcher, which
+// matches two float values using ULP-based approximation.  The
+// template is meant to be instantiated with FloatType being either
+// float or double.
+template <typename FloatType>
+class FloatingEqMatcher {
+ public:
+  // Constructor for FloatingEqMatcher.
+  // The matcher's input will be compared with rhs.  The matcher treats two
+  // NANs as equal if nan_eq_nan is true.  Otherwise, under IEEE standards,
+  // equality comparisons between NANs will always return false.
+  FloatingEqMatcher(FloatType rhs, bool nan_eq_nan) :
+    rhs_(rhs), nan_eq_nan_(nan_eq_nan) {}
+
+  // Implements floating point equality matcher as a Matcher<T>.
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(FloatType rhs, bool nan_eq_nan) :
+      rhs_(rhs), nan_eq_nan_(nan_eq_nan) {}
+
+    virtual bool MatchAndExplain(T value,
+                                 MatchResultListener* /* listener */) const {
+      const FloatingPoint<FloatType> lhs(value), rhs(rhs_);
+
+      // Compares NaNs first, if nan_eq_nan_ is true.
+      if (nan_eq_nan_ && lhs.is_nan()) {
+        return rhs.is_nan();
+      }
+
+      return lhs.AlmostEquals(rhs);
+    }
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      // os->precision() returns the previously set precision, which we
+      // store to restore the ostream to its original configuration
+      // after outputting.
+      const ::std::streamsize old_precision = os->precision(
+          ::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(rhs_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "is NaN";
+        } else {
+          *os << "never matches";
+        }
+      } else {
+        *os << "is approximately " << rhs_;
+      }
+      os->precision(old_precision);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      // As before, get original precision.
+      const ::std::streamsize old_precision = os->precision(
+          ::std::numeric_limits<FloatType>::digits10 + 2);
+      if (FloatingPoint<FloatType>(rhs_).is_nan()) {
+        if (nan_eq_nan_) {
+          *os << "isn't NaN";
+        } else {
+          *os << "is anything";
+        }
+      } else {
+        *os << "isn't approximately " << rhs_;
+      }
+      // Restore original precision.
+      os->precision(old_precision);
+    }
+
+   private:
+    const FloatType rhs_;
+    const bool nan_eq_nan_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  // The following 3 type conversion operators allow FloatEq(rhs) and
+  // NanSensitiveFloatEq(rhs) to be used as a Matcher<float>, a
+  // Matcher<const float&>, or a Matcher<float&>, but nothing else.
+  // (While Google's C++ coding style doesn't allow arguments passed
+  // by non-const reference, we may see them in code not conforming to
+  // the style.  Therefore Google Mock needs to support them.)
+  operator Matcher<FloatType>() const {
+    return MakeMatcher(new Impl<FloatType>(rhs_, nan_eq_nan_));
+  }
+
+  operator Matcher<const FloatType&>() const {
+    return MakeMatcher(new Impl<const FloatType&>(rhs_, nan_eq_nan_));
+  }
+
+  operator Matcher<FloatType&>() const {
+    return MakeMatcher(new Impl<FloatType&>(rhs_, nan_eq_nan_));
+  }
+ private:
+  const FloatType rhs_;
+  const bool nan_eq_nan_;
+
+  GTEST_DISALLOW_ASSIGN_(FloatingEqMatcher);
+};
+
+// Implements the Pointee(m) matcher for matching a pointer whose
+// pointee matches matcher m.  The pointer can be either raw or smart.
+template <typename InnerMatcher>
+class PointeeMatcher {
+ public:
+  explicit PointeeMatcher(const InnerMatcher& matcher) : matcher_(matcher) {}
+
+  // This type conversion operator template allows Pointee(m) to be
+  // used as a matcher for any pointer type whose pointee type is
+  // compatible with the inner matcher, where type Pointer can be
+  // either a raw pointer or a smart pointer.
+  //
+  // The reason we do this instead of relying on
+  // MakePolymorphicMatcher() is that the latter is not flexible
+  // enough for implementing the DescribeTo() method of Pointee().
+  template <typename Pointer>
+  operator Matcher<Pointer>() const {
+    return MakeMatcher(new Impl<Pointer>(matcher_));
+  }
+
+ private:
+  // The monomorphic implementation that works for a particular pointer type.
+  template <typename Pointer>
+  class Impl : public MatcherInterface<Pointer> {
+   public:
+    typedef typename PointeeOf<GTEST_REMOVE_CONST_(  // NOLINT
+        GTEST_REMOVE_REFERENCE_(Pointer))>::type Pointee;
+
+    explicit Impl(const InnerMatcher& matcher)
+        : matcher_(MatcherCast<const Pointee&>(matcher)) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "points to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "does not point to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual bool MatchAndExplain(Pointer pointer,
+                                 MatchResultListener* listener) const {
+      if (GetRawPointer(pointer) == NULL)
+        return false;
+
+      *listener << "which points to ";
+      return MatchPrintAndExplain(*pointer, matcher_, listener);
+    }
+
+   private:
+    const Matcher<const Pointee&> matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+  const InnerMatcher matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PointeeMatcher);
+};
+
+// Implements the Field() matcher for matching a field (i.e. member
+// variable) of an object.
+template <typename Class, typename FieldType>
+class FieldMatcher {
+ public:
+  FieldMatcher(FieldType Class::*field,
+               const Matcher<const FieldType&>& matcher)
+      : field_(field), matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object whose given field ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object whose given field ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T& value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename ::testing::internal::
+            is_pointer<GTEST_REMOVE_CONST_(T)>::type(),
+        value, listener);
+  }
+
+ private:
+  // The first argument of MatchAndExplainImpl() is needed to help
+  // Symbian's C++ compiler choose which overload to use.  Its type is
+  // true_type iff the Field() matcher is used to match a pointer.
+  bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << "whose given field is ";
+    return MatchPrintAndExplain(obj.*field_, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == NULL)
+      return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a field, it must be a class/struct/union type and
+    // thus cannot be a pointer.  Therefore we pass false_type() as
+    // the first argument.
+    return MatchAndExplainImpl(false_type(), *p, listener);
+  }
+
+  const FieldType Class::*field_;
+  const Matcher<const FieldType&> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(FieldMatcher);
+};
+
+// Implements the Property() matcher for matching a property
+// (i.e. return value of a getter method) of an object.
+template <typename Class, typename PropertyType>
+class PropertyMatcher {
+ public:
+  // The property may have a reference type, so 'const PropertyType&'
+  // may cause double references and fail to compile.  That's why we
+  // need GTEST_REFERENCE_TO_CONST, which works regardless of
+  // PropertyType being a reference or not.
+  typedef GTEST_REFERENCE_TO_CONST_(PropertyType) RefToConstProperty;
+
+  PropertyMatcher(PropertyType (Class::*property)() const,
+                  const Matcher<RefToConstProperty>& matcher)
+      : property_(property), matcher_(matcher) {}
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "is an object whose given property ";
+    matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "is an object whose given property ";
+    matcher_.DescribeNegationTo(os);
+  }
+
+  template <typename T>
+  bool MatchAndExplain(const T&value, MatchResultListener* listener) const {
+    return MatchAndExplainImpl(
+        typename ::testing::internal::
+            is_pointer<GTEST_REMOVE_CONST_(T)>::type(),
+        value, listener);
+  }
+
+ private:
+  // The first argument of MatchAndExplainImpl() is needed to help
+  // Symbian's C++ compiler choose which overload to use.  Its type is
+  // true_type iff the Property() matcher is used to match a pointer.
+  bool MatchAndExplainImpl(false_type /* is_not_pointer */, const Class& obj,
+                           MatchResultListener* listener) const {
+    *listener << "whose given property is ";
+    // Cannot pass the return value (for example, int) to MatchPrintAndExplain,
+    // which takes a non-const reference as argument.
+    RefToConstProperty result = (obj.*property_)();
+    return MatchPrintAndExplain(result, matcher_, listener);
+  }
+
+  bool MatchAndExplainImpl(true_type /* is_pointer */, const Class* p,
+                           MatchResultListener* listener) const {
+    if (p == NULL)
+      return false;
+
+    *listener << "which points to an object ";
+    // Since *p has a property method, it must be a class/struct/union
+    // type and thus cannot be a pointer.  Therefore we pass
+    // false_type() as the first argument.
+    return MatchAndExplainImpl(false_type(), *p, listener);
+  }
+
+  PropertyType (Class::*property_)() const;
+  const Matcher<RefToConstProperty> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PropertyMatcher);
+};
+
+// Type traits specifying various features of different functors for ResultOf.
+// The default template specifies features for functor objects.
+// Functor classes have to typedef argument_type and result_type
+// to be compatible with ResultOf.
+template <typename Functor>
+struct CallableTraits {
+  typedef typename Functor::result_type ResultType;
+  typedef Functor StorageType;
+
+  static void CheckIsValid(Functor /* functor */) {}
+  template <typename T>
+  static ResultType Invoke(Functor f, T arg) { return f(arg); }
+};
+
+// Specialization for function pointers.
+template <typename ArgType, typename ResType>
+struct CallableTraits<ResType(*)(ArgType)> {
+  typedef ResType ResultType;
+  typedef ResType(*StorageType)(ArgType);
+
+  static void CheckIsValid(ResType(*f)(ArgType)) {
+    GTEST_CHECK_(f != NULL)
+        << "NULL function pointer is passed into ResultOf().";
+  }
+  template <typename T>
+  static ResType Invoke(ResType(*f)(ArgType), T arg) {
+    return (*f)(arg);
+  }
+};
+
+// Implements the ResultOf() matcher for matching a return value of a
+// unary function of an object.
+template <typename Callable>
+class ResultOfMatcher {
+ public:
+  typedef typename CallableTraits<Callable>::ResultType ResultType;
+
+  ResultOfMatcher(Callable callable, const Matcher<ResultType>& matcher)
+      : callable_(callable), matcher_(matcher) {
+    CallableTraits<Callable>::CheckIsValid(callable_);
+  }
+
+  template <typename T>
+  operator Matcher<T>() const {
+    return Matcher<T>(new Impl<T>(callable_, matcher_));
+  }
+
+ private:
+  typedef typename CallableTraits<Callable>::StorageType CallableStorageType;
+
+  template <typename T>
+  class Impl : public MatcherInterface<T> {
+   public:
+    Impl(CallableStorageType callable, const Matcher<ResultType>& matcher)
+        : callable_(callable), matcher_(matcher) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "is mapped by the given callable to a value that ";
+      matcher_.DescribeTo(os);
+    }
+
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "is mapped by the given callable to a value that ";
+      matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(T obj, MatchResultListener* listener) const {
+      *listener << "which is mapped by the given callable to ";
+      // Cannot pass the return value (for example, int) to
+      // MatchPrintAndExplain, which takes a non-const reference as argument.
+      ResultType result =
+          CallableTraits<Callable>::template Invoke<T>(callable_, obj);
+      return MatchPrintAndExplain(result, matcher_, listener);
+    }
+
+   private:
+    // Functors often define operator() as non-const method even though
+    // they are actualy stateless. But we need to use them even when
+    // 'this' is a const pointer. It's the user's responsibility not to
+    // use stateful callables with ResultOf(), which does't guarantee
+    // how many times the callable will be invoked.
+    mutable CallableStorageType callable_;
+    const Matcher<ResultType> matcher_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };  // class Impl
+
+  const CallableStorageType callable_;
+  const Matcher<ResultType> matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ResultOfMatcher);
+};
+
+// Implements an equality matcher for any STL-style container whose elements
+// support ==. This matcher is like Eq(), but its failure explanations provide
+// more detailed information that is useful when the container is used as a set.
+// The failure message reports elements that are in one of the operands but not
+// the other. The failure messages do not report duplicate or out-of-order
+// elements in the containers (which don't properly matter to sets, but can
+// occur if the containers are vectors or lists, for example).
+//
+// Uses the container's const_iterator, value_type, operator ==,
+// begin(), and end().
+template <typename Container>
+class ContainerEqMatcher {
+ public:
+  typedef internal::StlContainerView<Container> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+
+  // We make a copy of rhs in case the elements in it are modified
+  // after this matcher is created.
+  explicit ContainerEqMatcher(const Container& rhs) : rhs_(View::Copy(rhs)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    (void)testing::StaticAssertTypeEq<Container,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>();
+  }
+
+  void DescribeTo(::std::ostream* os) const {
+    *os << "equals ";
+    UniversalPrint(rhs_, os);
+  }
+  void DescribeNegationTo(::std::ostream* os) const {
+    *os << "does not equal ";
+    UniversalPrint(rhs_, os);
+  }
+
+  template <typename LhsContainer>
+  bool MatchAndExplain(const LhsContainer& lhs,
+                       MatchResultListener* listener) const {
+    // GTEST_REMOVE_CONST_() is needed to work around an MSVC 8.0 bug
+    // that causes LhsContainer to be a const type sometimes.
+    typedef internal::StlContainerView<GTEST_REMOVE_CONST_(LhsContainer)>
+        LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    StlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+    if (lhs_stl_container == rhs_)
+      return true;
+
+    ::std::ostream* const os = listener->stream();
+    if (os != NULL) {
+      // Something is different. Check for extra values first.
+      bool printed_header = false;
+      for (typename LhsStlContainer::const_iterator it =
+               lhs_stl_container.begin();
+           it != lhs_stl_container.end(); ++it) {
+        if (internal::ArrayAwareFind(rhs_.begin(), rhs_.end(), *it) ==
+            rhs_.end()) {
+          if (printed_header) {
+            *os << ", ";
+          } else {
+            *os << "which has these unexpected elements: ";
+            printed_header = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+
+      // Now check for missing values.
+      bool printed_header2 = false;
+      for (typename StlContainer::const_iterator it = rhs_.begin();
+           it != rhs_.end(); ++it) {
+        if (internal::ArrayAwareFind(
+                lhs_stl_container.begin(), lhs_stl_container.end(), *it) ==
+            lhs_stl_container.end()) {
+          if (printed_header2) {
+            *os << ", ";
+          } else {
+            *os << (printed_header ? ",\nand" : "which")
+                << " doesn't have these expected elements: ";
+            printed_header2 = true;
+          }
+          UniversalPrint(*it, os);
+        }
+      }
+    }
+
+    return false;
+  }
+
+ private:
+  const StlContainer rhs_;
+
+  GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher);
+};
+
+// Implements Pointwise(tuple_matcher, rhs_container).  tuple_matcher
+// must be able to be safely cast to Matcher<tuple<const T1&, const
+// T2&> >, where T1 and T2 are the types of elements in the LHS
+// container and the RHS container respectively.
+template <typename TupleMatcher, typename RhsContainer>
+class PointwiseMatcher {
+ public:
+  typedef internal::StlContainerView<RhsContainer> RhsView;
+  typedef typename RhsView::type RhsStlContainer;
+  typedef typename RhsStlContainer::value_type RhsValue;
+
+  // Like ContainerEq, we make a copy of rhs in case the elements in
+  // it are modified after this matcher is created.
+  PointwiseMatcher(const TupleMatcher& tuple_matcher, const RhsContainer& rhs)
+      : tuple_matcher_(tuple_matcher), rhs_(RhsView::Copy(rhs)) {
+    // Makes sure the user doesn't instantiate this class template
+    // with a const or reference type.
+    (void)testing::StaticAssertTypeEq<RhsContainer,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>();
+  }
+
+  template <typename LhsContainer>
+  operator Matcher<LhsContainer>() const {
+    return MakeMatcher(new Impl<LhsContainer>(tuple_matcher_, rhs_));
+  }
+
+  template <typename LhsContainer>
+  class Impl : public MatcherInterface<LhsContainer> {
+   public:
+    typedef internal::StlContainerView<
+         GTEST_REMOVE_REFERENCE_AND_CONST_(LhsContainer)> LhsView;
+    typedef typename LhsView::type LhsStlContainer;
+    typedef typename LhsView::const_reference LhsStlContainerReference;
+    typedef typename LhsStlContainer::value_type LhsValue;
+    // We pass the LHS value and the RHS value to the inner matcher by
+    // reference, as they may be expensive to copy.  We must use tuple
+    // instead of pair here, as a pair cannot hold references (C++ 98,
+    // 20.2.2 [lib.pairs]).
+    typedef std::tr1::tuple<const LhsValue&, const RhsValue&> InnerMatcherArg;
+
+    Impl(const TupleMatcher& tuple_matcher, const RhsStlContainer& rhs)
+        // mono_tuple_matcher_ holds a monomorphic version of the tuple matcher.
+        : mono_tuple_matcher_(SafeMatcherCast<InnerMatcherArg>(tuple_matcher)),
+          rhs_(rhs) {}
+
+    virtual void DescribeTo(::std::ostream* os) const {
+      *os << "contains " << rhs_.size()
+          << " values, where each value and its corresponding value in ";
+      UniversalPrinter<RhsStlContainer>::Print(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeTo(os);
+    }
+    virtual void DescribeNegationTo(::std::ostream* os) const {
+      *os << "doesn't contain exactly " << rhs_.size()
+          << " values, or contains a value x at some index i"
+          << " where x and the i-th value of ";
+      UniversalPrint(rhs_, os);
+      *os << " ";
+      mono_tuple_matcher_.DescribeNegationTo(os);
+    }
+
+    virtual bool MatchAndExplain(LhsContainer lhs,
+                                 MatchResultListener* listener) const {
+      LhsStlContainerReference lhs_stl_container = LhsView::ConstReference(lhs);
+      const size_t actual_size = lhs_stl_container.size();
+      if (actual_size != rhs_.size()) {
+        *listener << "which contains " << actual_size << " values";
+        return false;
+      }
+
+      typename LhsStlContainer::const_iterator left = lhs_stl_container.begin();
+      typename RhsStlContainer::const_iterator right = rhs_.begin();
+      for (size_t i = 0; i != actual_size; ++i, ++left, ++right) {
+        const InnerMatcherArg value_pair(*left, *right);
+
+        if (listener->IsInterested()) {
+          StringMatchResultListener inner_listener;
+          if (!mono_tuple_matcher_.MatchAndExplain(
+                  value_pair, &inner_listener)) {
+            *listener << "where the value pair (";
+            UniversalPrint(*left, listener->stream());
+            *listener << ", ";
+            UniversalPrint(*right, listener->stream());
+            *listener << ") at index #" << i << " don't match";
+            PrintIfNotEmpty(inner_listener.str(), listener->stream());
+            return false;
+          }
+        } else {
+          if (!mono_tuple_matcher_.Matches(value_pair))
+            return false;
+        }
+      }
+
+      return true;
+    }
+
+   private:
+    const Matcher<InnerMatcherArg> mono_tuple_matcher_;
+    const RhsStlContainer rhs_;
+
+    GTEST_DISALLOW_ASSIGN_(Impl);
+  };
+
+ private:
+  const TupleMatcher tuple_matcher_;
+  const RhsStlContainer rhs_;
+
+  GTEST_DISALLOW_ASSIGN_(PointwiseMatcher);
+};
+
+// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl.
+template <typename Container>
+class QuantifierMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  template <typename InnerMatcher>
+  explicit QuantifierMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+           testing::SafeMatcherCast<const Element&>(inner_matcher)) {}
+
+  // Checks whether:
+  // * All elements in the container match, if all_elements_should_match.
+  // * Any element in the container matches, if !all_elements_should_match.
+  bool MatchAndExplainImpl(bool all_elements_should_match,
+                           Container container,
+                           MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    size_t i = 0;
+    for (typename StlContainer::const_iterator it = stl_container.begin();
+         it != stl_container.end(); ++it, ++i) {
+      StringMatchResultListener inner_listener;
+      const bool matches = inner_matcher_.MatchAndExplain(*it, &inner_listener);
+
+      if (matches != all_elements_should_match) {
+        *listener << "whose element #" << i
+                  << (matches ? " matches" : " doesn't match");
+        PrintIfNotEmpty(inner_listener.str(), listener->stream());
+        return !all_elements_should_match;
+      }
+    }
+    return all_elements_should_match;
+  }
+
+ protected:
+  const Matcher<const Element&> inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(QuantifierMatcherImpl);
+};
+
+// Implements Contains(element_matcher) for the given argument type Container.
+// Symmetric to EachMatcherImpl.
+template <typename Container>
+class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit ContainsMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "contains at least one element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't contain any element that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    return this->MatchAndExplainImpl(false, container, listener);
+  }
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(ContainsMatcherImpl);
+};
+
+// Implements Each(element_matcher) for the given argument type Container.
+// Symmetric to ContainsMatcherImpl.
+template <typename Container>
+class EachMatcherImpl : public QuantifierMatcherImpl<Container> {
+ public:
+  template <typename InnerMatcher>
+  explicit EachMatcherImpl(InnerMatcher inner_matcher)
+      : QuantifierMatcherImpl<Container>(inner_matcher) {}
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "only contains elements that ";
+    this->inner_matcher_.DescribeTo(os);
+  }
+
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "contains some element that ";
+    this->inner_matcher_.DescribeNegationTo(os);
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    return this->MatchAndExplainImpl(true, container, listener);
+  }
+
+ private:
+  GTEST_DISALLOW_ASSIGN_(EachMatcherImpl);
+};
+
+// Implements polymorphic Contains(element_matcher).
+template <typename M>
+class ContainsMatcher {
+ public:
+  explicit ContainsMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new ContainsMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(ContainsMatcher);
+};
+
+// Implements polymorphic Each(element_matcher).
+template <typename M>
+class EachMatcher {
+ public:
+  explicit EachMatcher(M m) : inner_matcher_(m) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    return MakeMatcher(new EachMatcherImpl<Container>(inner_matcher_));
+  }
+
+ private:
+  const M inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(EachMatcher);
+};
+
+// Implements Key(inner_matcher) for the given argument pair type.
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename PairType>
+class KeyMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type KeyType;
+
+  template <typename InnerMatcher>
+  explicit KeyMatcherImpl(InnerMatcher inner_matcher)
+      : inner_matcher_(
+          testing::SafeMatcherCast<const KeyType&>(inner_matcher)) {
+  }
+
+  // Returns true iff 'key_value.first' (the key) matches the inner matcher.
+  virtual bool MatchAndExplain(PairType key_value,
+                               MatchResultListener* listener) const {
+    StringMatchResultListener inner_listener;
+    const bool match = inner_matcher_.MatchAndExplain(key_value.first,
+                                                      &inner_listener);
+    const internal::string explanation = inner_listener.str();
+    if (explanation != "") {
+      *listener << "whose first field is a value " << explanation;
+    }
+    return match;
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "doesn't have a key that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+ private:
+  const Matcher<const KeyType&> inner_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(KeyMatcherImpl);
+};
+
+// Implements polymorphic Key(matcher_for_key).
+template <typename M>
+class KeyMatcher {
+ public:
+  explicit KeyMatcher(M m) : matcher_for_key_(m) {}
+
+  template <typename PairType>
+  operator Matcher<PairType>() const {
+    return MakeMatcher(new KeyMatcherImpl<PairType>(matcher_for_key_));
+  }
+
+ private:
+  const M matcher_for_key_;
+
+  GTEST_DISALLOW_ASSIGN_(KeyMatcher);
+};
+
+// Implements Pair(first_matcher, second_matcher) for the given argument pair
+// type with its two matchers. See Pair() function below.
+template <typename PairType>
+class PairMatcherImpl : public MatcherInterface<PairType> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType;
+  typedef typename RawPairType::first_type FirstType;
+  typedef typename RawPairType::second_type SecondType;
+
+  template <typename FirstMatcher, typename SecondMatcher>
+  PairMatcherImpl(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(
+            testing::SafeMatcherCast<const FirstType&>(first_matcher)),
+        second_matcher_(
+            testing::SafeMatcherCast<const SecondType&>(second_matcher)) {
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    *os << "has a first field that ";
+    first_matcher_.DescribeTo(os);
+    *os << ", and has a second field that ";
+    second_matcher_.DescribeTo(os);
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    *os << "has a first field that ";
+    first_matcher_.DescribeNegationTo(os);
+    *os << ", or has a second field that ";
+    second_matcher_.DescribeNegationTo(os);
+  }
+
+  // Returns true iff 'a_pair.first' matches first_matcher and 'a_pair.second'
+  // matches second_matcher.
+  virtual bool MatchAndExplain(PairType a_pair,
+                               MatchResultListener* listener) const {
+    if (!listener->IsInterested()) {
+      // If the listener is not interested, we don't need to construct the
+      // explanation.
+      return first_matcher_.Matches(a_pair.first) &&
+             second_matcher_.Matches(a_pair.second);
+    }
+    StringMatchResultListener first_inner_listener;
+    if (!first_matcher_.MatchAndExplain(a_pair.first,
+                                        &first_inner_listener)) {
+      *listener << "whose first field does not match";
+      PrintIfNotEmpty(first_inner_listener.str(), listener->stream());
+      return false;
+    }
+    StringMatchResultListener second_inner_listener;
+    if (!second_matcher_.MatchAndExplain(a_pair.second,
+                                         &second_inner_listener)) {
+      *listener << "whose second field does not match";
+      PrintIfNotEmpty(second_inner_listener.str(), listener->stream());
+      return false;
+    }
+    ExplainSuccess(first_inner_listener.str(), second_inner_listener.str(),
+                   listener);
+    return true;
+  }
+
+ private:
+  void ExplainSuccess(const internal::string& first_explanation,
+                      const internal::string& second_explanation,
+                      MatchResultListener* listener) const {
+    *listener << "whose both fields match";
+    if (first_explanation != "") {
+      *listener << ", where the first field is a value " << first_explanation;
+    }
+    if (second_explanation != "") {
+      *listener << ", ";
+      if (first_explanation != "") {
+        *listener << "and ";
+      } else {
+        *listener << "where ";
+      }
+      *listener << "the second field is a value " << second_explanation;
+    }
+  }
+
+  const Matcher<const FirstType&> first_matcher_;
+  const Matcher<const SecondType&> second_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PairMatcherImpl);
+};
+
+// Implements polymorphic Pair(first_matcher, second_matcher).
+template <typename FirstMatcher, typename SecondMatcher>
+class PairMatcher {
+ public:
+  PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher)
+      : first_matcher_(first_matcher), second_matcher_(second_matcher) {}
+
+  template <typename PairType>
+  operator Matcher<PairType> () const {
+    return MakeMatcher(
+        new PairMatcherImpl<PairType>(
+            first_matcher_, second_matcher_));
+  }
+
+ private:
+  const FirstMatcher first_matcher_;
+  const SecondMatcher second_matcher_;
+
+  GTEST_DISALLOW_ASSIGN_(PairMatcher);
+};
+
+// Implements ElementsAre() and ElementsAreArray().
+template <typename Container>
+class ElementsAreMatcherImpl : public MatcherInterface<Container> {
+ public:
+  typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+  typedef internal::StlContainerView<RawContainer> View;
+  typedef typename View::type StlContainer;
+  typedef typename View::const_reference StlContainerReference;
+  typedef typename StlContainer::value_type Element;
+
+  // Constructs the matcher from a sequence of element values or
+  // element matchers.
+  template <typename InputIter>
+  ElementsAreMatcherImpl(InputIter first, size_t a_count) {
+    matchers_.reserve(a_count);
+    InputIter it = first;
+    for (size_t i = 0; i != a_count; ++i, ++it) {
+      matchers_.push_back(MatcherCast<const Element&>(*it));
+    }
+  }
+
+  // Describes what this matcher does.
+  virtual void DescribeTo(::std::ostream* os) const {
+    if (count() == 0) {
+      *os << "is empty";
+    } else if (count() == 1) {
+      *os << "has 1 element that ";
+      matchers_[0].DescribeTo(os);
+    } else {
+      *os << "has " << Elements(count()) << " where\n";
+      for (size_t i = 0; i != count(); ++i) {
+        *os << "element #" << i << " ";
+        matchers_[i].DescribeTo(os);
+        if (i + 1 < count()) {
+          *os << ",\n";
+        }
+      }
+    }
+  }
+
+  // Describes what the negation of this matcher does.
+  virtual void DescribeNegationTo(::std::ostream* os) const {
+    if (count() == 0) {
+      *os << "isn't empty";
+      return;
+    }
+
+    *os << "doesn't have " << Elements(count()) << ", or\n";
+    for (size_t i = 0; i != count(); ++i) {
+      *os << "element #" << i << " ";
+      matchers_[i].DescribeNegationTo(os);
+      if (i + 1 < count()) {
+        *os << ", or\n";
+      }
+    }
+  }
+
+  virtual bool MatchAndExplain(Container container,
+                               MatchResultListener* listener) const {
+    StlContainerReference stl_container = View::ConstReference(container);
+    const size_t actual_count = stl_container.size();
+    if (actual_count != count()) {
+      // The element count doesn't match.  If the container is empty,
+      // there's no need to explain anything as Google Mock already
+      // prints the empty container.  Otherwise we just need to show
+      // how many elements there actually are.
+      if (actual_count != 0) {
+        *listener << "which has " << Elements(actual_count);
+      }
+      return false;
+    }
+
+    typename StlContainer::const_iterator it = stl_container.begin();
+    // explanations[i] is the explanation of the element at index i.
+    std::vector<internal::string> explanations(count());
+    for (size_t i = 0; i != count();  ++it, ++i) {
+      StringMatchResultListener s;
+      if (matchers_[i].MatchAndExplain(*it, &s)) {
+        explanations[i] = s.str();
+      } else {
+        // The container has the right size but the i-th element
+        // doesn't match its expectation.
+        *listener << "whose element #" << i << " doesn't match";
+        PrintIfNotEmpty(s.str(), listener->stream());
+        return false;
+      }
+    }
+
+    // Every element matches its expectation.  We need to explain why
+    // (the obvious ones can be skipped).
+    bool reason_printed = false;
+    for (size_t i = 0; i != count(); ++i) {
+      const internal::string& s = explanations[i];
+      if (!s.empty()) {
+        if (reason_printed) {
+          *listener << ",\nand ";
+        }
+        *listener << "whose element #" << i << " matches, " << s;
+        reason_printed = true;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  static Message Elements(size_t count) {
+    return Message() << count << (count == 1 ? " element" : " elements");
+  }
+
+  size_t count() const { return matchers_.size(); }
+  std::vector<Matcher<const Element&> > matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreMatcherImpl);
+};
+
+// Implements ElementsAre() of 0 arguments.
+class ElementsAreMatcher0 {
+ public:
+  ElementsAreMatcher0() {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    const Matcher<const Element&>* const matchers = NULL;
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(matchers, 0));
+  }
+};
+
+// Implements ElementsAreArray().
+template <typename T>
+class ElementsAreArrayMatcher {
+ public:
+  ElementsAreArrayMatcher(const T* first, size_t count) :
+      first_(first), count_(count) {}
+
+  template <typename Container>
+  operator Matcher<Container>() const {
+    typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer;
+    typedef typename internal::StlContainerView<RawContainer>::type::value_type
+        Element;
+
+    return MakeMatcher(new ElementsAreMatcherImpl<Container>(first_, count_));
+  }
+
+ private:
+  const T* const first_;
+  const size_t count_;
+
+  GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher);
+};
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+string FormatMatcherDescription(bool negation, const char* matcher_name,
+                                const Strings& param_values);
+
+}  // namespace internal
+
+// Implements MatcherCast().
+template <typename T, typename M>
+inline Matcher<T> MatcherCast(M matcher) {
+  return internal::MatcherCastImpl<T, M>::Cast(matcher);
+}
+
+// _ is a matcher that matches anything of any type.
+//
+// This definition is fine as:
+//
+//   1. The C++ standard permits using the name _ in a namespace that
+//      is not the global namespace or ::std.
+//   2. The AnythingMatcher class has no data member or constructor,
+//      so it's OK to create global variables of this type.
+//   3. c-style has approved of using _ in this case.
+const internal::AnythingMatcher _ = {};
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> A() { return MakeMatcher(new internal::AnyMatcherImpl<T>()); }
+
+// Creates a matcher that matches any value of the given type T.
+template <typename T>
+inline Matcher<T> An() { return A<T>(); }
+
+// Creates a polymorphic matcher that matches anything equal to x.
+// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
+// wouldn't compile.
+template <typename T>
+inline internal::EqMatcher<T> Eq(T x) { return internal::EqMatcher<T>(x); }
+
+// Constructs a Matcher<T> from a 'value' of type T.  The constructed
+// matcher matches any value that's equal to 'value'.
+template <typename T>
+Matcher<T>::Matcher(T value) { *this = Eq(value); }
+
+// Creates a monomorphic matcher that matches anything with type Lhs
+// and equal to rhs.  A user may need to use this instead of Eq(...)
+// in order to resolve an overloading ambiguity.
+//
+// TypedEq<T>(x) is just a convenient short-hand for Matcher<T>(Eq(x))
+// or Matcher<T>(x), but more readable than the latter.
+//
+// We could define similar monomorphic matchers for other comparison
+// operations (e.g. TypedLt, TypedGe, and etc), but decided not to do
+// it yet as those are used much less than Eq() in practice.  A user
+// can always write Matcher<T>(Lt(5)) to be explicit about the type,
+// for example.
+template <typename Lhs, typename Rhs>
+inline Matcher<Lhs> TypedEq(const Rhs& rhs) { return Eq(rhs); }
+
+// Creates a polymorphic matcher that matches anything >= x.
+template <typename Rhs>
+inline internal::GeMatcher<Rhs> Ge(Rhs x) {
+  return internal::GeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything > x.
+template <typename Rhs>
+inline internal::GtMatcher<Rhs> Gt(Rhs x) {
+  return internal::GtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything <= x.
+template <typename Rhs>
+inline internal::LeMatcher<Rhs> Le(Rhs x) {
+  return internal::LeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything < x.
+template <typename Rhs>
+inline internal::LtMatcher<Rhs> Lt(Rhs x) {
+  return internal::LtMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches anything != x.
+template <typename Rhs>
+inline internal::NeMatcher<Rhs> Ne(Rhs x) {
+  return internal::NeMatcher<Rhs>(x);
+}
+
+// Creates a polymorphic matcher that matches any NULL pointer.
+inline PolymorphicMatcher<internal::IsNullMatcher > IsNull() {
+  return MakePolymorphicMatcher(internal::IsNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any non-NULL pointer.
+// This is convenient as Not(NULL) doesn't compile (the compiler
+// thinks that that expression is comparing a pointer with an integer).
+inline PolymorphicMatcher<internal::NotNullMatcher > NotNull() {
+  return MakePolymorphicMatcher(internal::NotNullMatcher());
+}
+
+// Creates a polymorphic matcher that matches any argument that
+// references variable x.
+template <typename T>
+inline internal::RefMatcher<T&> Ref(T& x) {  // NOLINT
+  return internal::RefMatcher<T&>(x);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, false);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) {
+  return internal::FloatingEqMatcher<double>(rhs, true);
+}
+
+// Creates a matcher that matches any float argument approximately
+// equal to rhs, where two NANs are considered unequal.
+inline internal::FloatingEqMatcher<float> FloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, false);
+}
+
+// Creates a matcher that matches any double argument approximately
+// equal to rhs, including NaN values when rhs is NaN.
+inline internal::FloatingEqMatcher<float> NanSensitiveFloatEq(float rhs) {
+  return internal::FloatingEqMatcher<float>(rhs, true);
+}
+
+// Creates a matcher that matches a pointer (raw or smart) that points
+// to a value that matches inner_matcher.
+template <typename InnerMatcher>
+inline internal::PointeeMatcher<InnerMatcher> Pointee(
+    const InnerMatcher& inner_matcher) {
+  return internal::PointeeMatcher<InnerMatcher>(inner_matcher);
+}
+
+// Creates a matcher that matches an object whose given field matches
+// 'matcher'.  For example,
+//   Field(&Foo::number, Ge(5))
+// matches a Foo object x iff x.number >= 5.
+template <typename Class, typename FieldType, typename FieldMatcher>
+inline PolymorphicMatcher<
+  internal::FieldMatcher<Class, FieldType> > Field(
+    FieldType Class::*field, const FieldMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::FieldMatcher<Class, FieldType>(
+          field, MatcherCast<const FieldType&>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Field(&Foo::bar, m)
+  // to compile where bar is an int32 and m is a matcher for int64.
+}
+
+// Creates a matcher that matches an object whose given property
+// matches 'matcher'.  For example,
+//   Property(&Foo::str, StartsWith("hi"))
+// matches a Foo object x iff x.str() starts with "hi".
+template <typename Class, typename PropertyType, typename PropertyMatcher>
+inline PolymorphicMatcher<
+  internal::PropertyMatcher<Class, PropertyType> > Property(
+    PropertyType (Class::*property)() const, const PropertyMatcher& matcher) {
+  return MakePolymorphicMatcher(
+      internal::PropertyMatcher<Class, PropertyType>(
+          property,
+          MatcherCast<GTEST_REFERENCE_TO_CONST_(PropertyType)>(matcher)));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   Property(&Foo::bar, m)
+  // to compile where bar() returns an int32 and m is a matcher for int64.
+}
+
+// Creates a matcher that matches an object iff the result of applying
+// a callable to x matches 'matcher'.
+// For example,
+//   ResultOf(f, StartsWith("hi"))
+// matches a Foo object x iff f(x) starts with "hi".
+// callable parameter can be a function, function pointer, or a functor.
+// Callable has to satisfy the following conditions:
+//   * It is required to keep no state affecting the results of
+//     the calls on it and make no assumptions about how many calls
+//     will be made. Any state it keeps must be protected from the
+//     concurrent access.
+//   * If it is a function object, it has to define type result_type.
+//     We recommend deriving your functor classes from std::unary_function.
+template <typename Callable, typename ResultOfMatcher>
+internal::ResultOfMatcher<Callable> ResultOf(
+    Callable callable, const ResultOfMatcher& matcher) {
+  return internal::ResultOfMatcher<Callable>(
+          callable,
+          MatcherCast<typename internal::CallableTraits<Callable>::ResultType>(
+              matcher));
+  // The call to MatcherCast() is required for supporting inner
+  // matchers of compatible types.  For example, it allows
+  //   ResultOf(Function, m)
+  // to compile where Function() returns an int32 and m is a matcher for int64.
+}
+
+// String matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrEq(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrNe(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrCaseEq(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::string> >
+    StrCaseNe(const internal::string& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::string>(
+      str, false, false));
+}
+
+// Creates a matcher that matches any string, std::string, or C string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::string> >
+    HasSubstr(const internal::string& substring) {
+  return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::string>(
+      substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<internal::string> >
+    StartsWith(const internal::string& prefix) {
+  return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::string>(
+      prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<internal::string> >
+    EndsWith(const internal::string& suffix) {
+  return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::string>(
+      suffix));
+}
+
+// Matches a string that fully matches regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
+}
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
+    const internal::string& regex) {
+  return MatchesRegex(new internal::RE(regex));
+}
+
+// Matches a string that contains regular expression 'regex'.
+// The matcher takes ownership of 'regex'.
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::RE* regex) {
+  return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
+}
+inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
+    const internal::string& regex) {
+  return ContainsRegex(new internal::RE(regex));
+}
+
+#if GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
+// Wide string matchers.
+
+// Matches a string equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrEq(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, true, true));
+}
+
+// Matches a string not equal to str.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrNe(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, false, true));
+}
+
+// Matches a string equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrCaseEq(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, true, false));
+}
+
+// Matches a string not equal to str, ignoring case.
+inline PolymorphicMatcher<internal::StrEqualityMatcher<internal::wstring> >
+    StrCaseNe(const internal::wstring& str) {
+  return MakePolymorphicMatcher(internal::StrEqualityMatcher<internal::wstring>(
+      str, false, false));
+}
+
+// Creates a matcher that matches any wstring, std::wstring, or C wide string
+// that contains the given substring.
+inline PolymorphicMatcher<internal::HasSubstrMatcher<internal::wstring> >
+    HasSubstr(const internal::wstring& substring) {
+  return MakePolymorphicMatcher(internal::HasSubstrMatcher<internal::wstring>(
+      substring));
+}
+
+// Matches a string that starts with 'prefix' (case-sensitive).
+inline PolymorphicMatcher<internal::StartsWithMatcher<internal::wstring> >
+    StartsWith(const internal::wstring& prefix) {
+  return MakePolymorphicMatcher(internal::StartsWithMatcher<internal::wstring>(
+      prefix));
+}
+
+// Matches a string that ends with 'suffix' (case-sensitive).
+inline PolymorphicMatcher<internal::EndsWithMatcher<internal::wstring> >
+    EndsWith(const internal::wstring& suffix) {
+  return MakePolymorphicMatcher(internal::EndsWithMatcher<internal::wstring>(
+      suffix));
+}
+
+#endif  // GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field == the second field.
+inline internal::Eq2Matcher Eq() { return internal::Eq2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field >= the second field.
+inline internal::Ge2Matcher Ge() { return internal::Ge2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field > the second field.
+inline internal::Gt2Matcher Gt() { return internal::Gt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field <= the second field.
+inline internal::Le2Matcher Le() { return internal::Le2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field < the second field.
+inline internal::Lt2Matcher Lt() { return internal::Lt2Matcher(); }
+
+// Creates a polymorphic matcher that matches a 2-tuple where the
+// first field != the second field.
+inline internal::Ne2Matcher Ne() { return internal::Ne2Matcher(); }
+
+// Creates a matcher that matches any value of type T that m doesn't
+// match.
+template <typename InnerMatcher>
+inline internal::NotMatcher<InnerMatcher> Not(InnerMatcher m) {
+  return internal::NotMatcher<InnerMatcher>(m);
+}
+
+// Returns a matcher that matches anything that satisfies the given
+// predicate.  The predicate can be any unary function or functor
+// whose return type can be implicitly converted to bool.
+template <typename Predicate>
+inline PolymorphicMatcher<internal::TrulyMatcher<Predicate> >
+Truly(Predicate pred) {
+  return MakePolymorphicMatcher(internal::TrulyMatcher<Predicate>(pred));
+}
+
+// Returns a matcher that matches an equal container.
+// This matcher behaves like Eq(), but in the event of mismatch lists the
+// values that are included in one container but not the other. (Duplicate
+// values and order differences are not explained.)
+template <typename Container>
+inline PolymorphicMatcher<internal::ContainerEqMatcher<  // NOLINT
+                            GTEST_REMOVE_CONST_(Container)> >
+    ContainerEq(const Container& rhs) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes.
+  typedef GTEST_REMOVE_CONST_(Container) RawContainer;
+  return MakePolymorphicMatcher(
+      internal::ContainerEqMatcher<RawContainer>(rhs));
+}
+
+// Matches an STL-style container or a native array that contains the
+// same number of elements as in rhs, where its i-th element and rhs's
+// i-th element (as a pair) satisfy the given pair matcher, for all i.
+// TupleMatcher must be able to be safely cast to Matcher<tuple<const
+// T1&, const T2&> >, where T1 and T2 are the types of elements in the
+// LHS container and the RHS container respectively.
+template <typename TupleMatcher, typename Container>
+inline internal::PointwiseMatcher<TupleMatcher,
+                                  GTEST_REMOVE_CONST_(Container)>
+Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) {
+  // This following line is for working around a bug in MSVC 8.0,
+  // which causes Container to be a const type sometimes.
+  typedef GTEST_REMOVE_CONST_(Container) RawContainer;
+  return internal::PointwiseMatcher<TupleMatcher, RawContainer>(
+      tuple_matcher, rhs);
+}
+
+// Matches an STL-style container or a native array that contains at
+// least one element matching the given value or matcher.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   page_ids.insert(3);
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Contains(1));
+//   EXPECT_THAT(page_ids, Contains(Gt(2)));
+//   EXPECT_THAT(page_ids, Not(Contains(4)));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   EXPECT_THAT(page_lengths,
+//               Contains(::std::pair<const int, size_t>(1, 100)));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Contains(Eq(::std::string("tom"))));
+template <typename M>
+inline internal::ContainsMatcher<M> Contains(M matcher) {
+  return internal::ContainsMatcher<M>(matcher);
+}
+
+// Matches an STL-style container or a native array that contains only
+// elements matching the given value or matcher.
+//
+// Each(m) is semantically equivalent to Not(Contains(Not(m))). Only
+// the messages are different.
+//
+// Examples:
+//   ::std::set<int> page_ids;
+//   // Each(m) matches an empty container, regardless of what m is.
+//   EXPECT_THAT(page_ids, Each(Eq(1)));
+//   EXPECT_THAT(page_ids, Each(Eq(77)));
+//
+//   page_ids.insert(3);
+//   EXPECT_THAT(page_ids, Each(Gt(0)));
+//   EXPECT_THAT(page_ids, Not(Each(Gt(4))));
+//   page_ids.insert(1);
+//   EXPECT_THAT(page_ids, Not(Each(Lt(2))));
+//
+//   ::std::map<int, size_t> page_lengths;
+//   page_lengths[1] = 100;
+//   page_lengths[2] = 200;
+//   page_lengths[3] = 300;
+//   EXPECT_THAT(page_lengths, Not(Each(Pair(1, 100))));
+//   EXPECT_THAT(page_lengths, Each(Key(Le(3))));
+//
+//   const char* user_ids[] = { "joe", "mike", "tom" };
+//   EXPECT_THAT(user_ids, Not(Each(Eq(::std::string("tom")))));
+template <typename M>
+inline internal::EachMatcher<M> Each(M matcher) {
+  return internal::EachMatcher<M>(matcher);
+}
+
+// Key(inner_matcher) matches an std::pair whose 'first' field matches
+// inner_matcher.  For example, Contains(Key(Ge(5))) can be used to match an
+// std::map that contains at least one element whose key is >= 5.
+template <typename M>
+inline internal::KeyMatcher<M> Key(M inner_matcher) {
+  return internal::KeyMatcher<M>(inner_matcher);
+}
+
+// Pair(first_matcher, second_matcher) matches a std::pair whose 'first' field
+// matches first_matcher and whose 'second' field matches second_matcher.  For
+// example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used
+// to match a std::map<int, string> that contains exactly one element whose key
+// is >= 5 and whose value equals "foo".
+template <typename FirstMatcher, typename SecondMatcher>
+inline internal::PairMatcher<FirstMatcher, SecondMatcher>
+Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) {
+  return internal::PairMatcher<FirstMatcher, SecondMatcher>(
+      first_matcher, second_matcher);
+}
+
+// Returns a predicate that is satisfied by anything that matches the
+// given matcher.
+template <typename M>
+inline internal::MatcherAsPredicate<M> Matches(M matcher) {
+  return internal::MatcherAsPredicate<M>(matcher);
+}
+
+// Returns true iff the value matches the matcher.
+template <typename T, typename M>
+inline bool Value(const T& value, M matcher) {
+  return testing::Matches(matcher)(value);
+}
+
+// Matches the value against the given matcher and explains the match
+// result to listener.
+template <typename T, typename M>
+inline bool ExplainMatchResult(
+    M matcher, const T& value, MatchResultListener* listener) {
+  return SafeMatcherCast<const T&>(matcher).MatchAndExplain(value, listener);
+}
+
+// AllArgs(m) is a synonym of m.  This is useful in
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(AllArgs(Eq()));
+//
+// which is easier to read than
+//
+//   EXPECT_CALL(foo, Bar(_, _)).With(Eq());
+template <typename InnerMatcher>
+inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; }
+
+// These macros allow using matchers to check values in Google Test
+// tests.  ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
+// succeed iff the value matches the matcher.  If the assertion fails,
+// the value and the description of the matcher will be printed.
+#define ASSERT_THAT(value, matcher) ASSERT_PRED_FORMAT1(\
+    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+#define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\
+    ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value)
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-more-actions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-more-actions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-more-actions.h	(revision 11817)
@@ -0,0 +1,233 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements some actions that depend on gmock-generated-actions.h.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
+
+#include <algorithm>
+
+#include "gmock/gmock-generated-actions.h"
+
+namespace testing {
+namespace internal {
+
+// Implements the Invoke(f) action.  The template argument
+// FunctionImpl is the implementation type of f, which can be either a
+// function pointer or a functor.  Invoke(f) can be used as an
+// Action<F> as long as f's type is compatible with F (i.e. f can be
+// assigned to a tr1::function<F>).
+template <typename FunctionImpl>
+class InvokeAction {
+ public:
+  // The c'tor makes a copy of function_impl (either a function
+  // pointer or a functor).
+  explicit InvokeAction(FunctionImpl function_impl)
+      : function_impl_(function_impl) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) {
+    return InvokeHelper<Result, ArgumentTuple>::Invoke(function_impl_, args);
+  }
+
+ private:
+  FunctionImpl function_impl_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeAction);
+};
+
+// Implements the Invoke(object_ptr, &Class::Method) action.
+template <class Class, typename MethodPtr>
+class InvokeMethodAction {
+ public:
+  InvokeMethodAction(Class* obj_ptr, MethodPtr method_ptr)
+      : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {}
+
+  template <typename Result, typename ArgumentTuple>
+  Result Perform(const ArgumentTuple& args) const {
+    return InvokeHelper<Result, ArgumentTuple>::InvokeMethod(
+        obj_ptr_, method_ptr_, args);
+  }
+
+ private:
+  Class* const obj_ptr_;
+  const MethodPtr method_ptr_;
+
+  GTEST_DISALLOW_ASSIGN_(InvokeMethodAction);
+};
+
+}  // namespace internal
+
+// Various overloads for Invoke().
+
+// Creates an action that invokes 'function_impl' with the mock
+// function's arguments.
+template <typename FunctionImpl>
+PolymorphicAction<internal::InvokeAction<FunctionImpl> > Invoke(
+    FunctionImpl function_impl) {
+  return MakePolymorphicAction(
+      internal::InvokeAction<FunctionImpl>(function_impl));
+}
+
+// Creates an action that invokes the given method on the given object
+// with the mock function's arguments.
+template <class Class, typename MethodPtr>
+PolymorphicAction<internal::InvokeMethodAction<Class, MethodPtr> > Invoke(
+    Class* obj_ptr, MethodPtr method_ptr) {
+  return MakePolymorphicAction(
+      internal::InvokeMethodAction<Class, MethodPtr>(obj_ptr, method_ptr));
+}
+
+// WithoutArgs(inner_action) can be used in a mock function with a
+// non-empty argument list to perform inner_action, which takes no
+// argument.  In other words, it adapts an action accepting no
+// argument to one that accepts (and ignores) arguments.
+template <typename InnerAction>
+inline internal::WithArgsAction<InnerAction>
+WithoutArgs(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction>(action);
+}
+
+// WithArg<k>(an_action) creates an action that passes the k-th
+// (0-based) argument of the mock function to an_action and performs
+// it.  It adapts an action accepting one argument to one that accepts
+// multiple arguments.  For convenience, we also provide
+// WithArgs<k>(an_action) (defined below) as a synonym.
+template <int k, typename InnerAction>
+inline internal::WithArgsAction<InnerAction, k>
+WithArg(const InnerAction& action) {
+  return internal::WithArgsAction<InnerAction, k>(action);
+}
+
+// The ACTION*() macros trigger warning C4100 (unreferenced formal
+// parameter) in MSVC with -W4.  Unfortunately they cannot be fixed in
+// the macro definition, as the warnings are generated when the macro
+// is expanded and macro expansion cannot contain #pragma.  Therefore
+// we suppress them here.
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable:4100)
+#endif
+
+// Action ReturnArg<k>() returns the k-th argument of the mock function.
+ACTION_TEMPLATE(ReturnArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  return std::tr1::get<k>(args);
+}
+
+// Action SaveArg<k>(pointer) saves the k-th (0-based) argument of the
+// mock function to *pointer.
+ACTION_TEMPLATE(SaveArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = ::std::tr1::get<k>(args);
+}
+
+// Action SaveArgPointee<k>(pointer) saves the value pointed to
+// by the k-th (0-based) argument of the mock function to *pointer.
+ACTION_TEMPLATE(SaveArgPointee,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(pointer)) {
+  *pointer = *::std::tr1::get<k>(args);
+}
+
+// Action SetArgReferee<k>(value) assigns 'value' to the variable
+// referenced by the k-th (0-based) argument of the mock function.
+ACTION_TEMPLATE(SetArgReferee,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_1_VALUE_PARAMS(value)) {
+  typedef typename ::std::tr1::tuple_element<k, args_type>::type argk_type;
+  // Ensures that argument #k is a reference.  If you get a compiler
+  // error on the next line, you are using SetArgReferee<k>(value) in
+  // a mock function whose k-th (0-based) argument is not a reference.
+  GTEST_COMPILE_ASSERT_(internal::is_reference<argk_type>::value,
+                        SetArgReferee_must_be_used_with_a_reference_argument);
+  ::std::tr1::get<k>(args) = value;
+}
+
+// Action SetArrayArgument<k>(first, last) copies the elements in
+// source range [first, last) to the array pointed to by the k-th
+// (0-based) argument, which can be either a pointer or an
+// iterator. The action does not take ownership of the elements in the
+// source range.
+ACTION_TEMPLATE(SetArrayArgument,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_2_VALUE_PARAMS(first, last)) {
+  // Microsoft compiler deprecates ::std::copy, so we want to suppress warning
+  // 4996 (Function call with parameters that may be unsafe) there.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996.
+#endif
+  ::std::copy(first, last, ::std::tr1::get<k>(args));
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif
+}
+
+// Action DeleteArg<k>() deletes the k-th (0-based) argument of the mock
+// function.
+ACTION_TEMPLATE(DeleteArg,
+                HAS_1_TEMPLATE_PARAMS(int, k),
+                AND_0_VALUE_PARAMS()) {
+  delete ::std::tr1::get<k>(args);
+}
+
+// This action returns the value pointed to by 'pointer'.
+ACTION_P(ReturnPointee, pointer) { return *pointer; }
+
+// Action Throw(exception) can be used in a mock function of any type
+// to throw the given exception.  Any copyable value can be thrown.
+#if GTEST_HAS_EXCEPTIONS
+
+// Suppresses the 'unreachable code' warning that VC generates in opt modes.
+# ifdef _MSC_VER
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4702)  // Temporarily disables warning 4702.
+# endif
+ACTION_P(Throw, exception) { throw exception; }
+# ifdef _MSC_VER
+#  pragma warning(pop)           // Restores the warning state.
+# endif
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_MORE_ACTIONS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-spec-builders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-spec-builders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock-spec-builders.h	(revision 11817)
@@ -0,0 +1,1749 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the ON_CALL() and EXPECT_CALL() macros.
+//
+// A user can use the ON_CALL() macro to specify the default action of
+// a mock method.  The syntax is:
+//
+//   ON_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matcher)
+//       .WillByDefault(action);
+//
+//  where the .With() clause is optional.
+//
+// A user can use the EXPECT_CALL() macro to specify an expectation on
+// a mock method.  The syntax is:
+//
+//   EXPECT_CALL(mock_object, Method(argument-matchers))
+//       .With(multi-argument-matchers)
+//       .Times(cardinality)
+//       .InSequence(sequences)
+//       .After(expectations)
+//       .WillOnce(action)
+//       .WillRepeatedly(action)
+//       .RetiresOnSaturation();
+//
+// where all clauses are optional, and .InSequence()/.After()/
+// .WillOnce() can appear any number of times.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
+
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// An abstract handle of an expectation.
+class Expectation;
+
+// A set of expectation handles.
+class ExpectationSet;
+
+// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
+// and MUST NOT BE USED IN USER CODE!!!
+namespace internal {
+
+// Implements a mock function.
+template <typename F> class FunctionMocker;
+
+// Base class for expectations.
+class ExpectationBase;
+
+// Implements an expectation.
+template <typename F> class TypedExpectation;
+
+// Helper class for testing the Expectation class template.
+class ExpectationTester;
+
+// Base class for function mockers.
+template <typename F> class FunctionMockerBase;
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+//
+// The reason we don't use more fine-grained protection is: when a
+// mock function Foo() is called, it needs to consult its expectations
+// to see which one should be picked.  If another thread is allowed to
+// call a mock function (either Foo() or a different one) at the same
+// time, it could affect the "retired" attributes of Foo()'s
+// expectations when InSequence() is used, and thus affect which
+// expectation gets picked.  Therefore, we sequence all mock function
+// calls to ensure the integrity of the mock objects' states.
+GTEST_DECLARE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Untyped base class for ActionResultHolder<R>.
+class UntypedActionResultHolderBase;
+
+// Abstract base class of FunctionMockerBase.  This is the
+// type-agnostic part of the function mocker interface.  Its pure
+// virtual methods are implemented by FunctionMockerBase.
+class UntypedFunctionMockerBase {
+ public:
+  UntypedFunctionMockerBase();
+  virtual ~UntypedFunctionMockerBase();
+
+  // Verifies that all expectations on this mock function have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  // L >= g_gmock_mutex
+  bool VerifyAndClearExpectationsLocked();
+
+  // Clears the ON_CALL()s set on this mock function.
+  // L >= g_gmock_mutex
+  virtual void ClearDefaultActionsLocked() = 0;
+
+  // In all of the following Untyped* functions, it's the caller's
+  // responsibility to guarantee the correctness of the arguments'
+  // types.
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,
+      const string& call_description) const = 0;
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action,
+      const void* untyped_args) const = 0;
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  // L < g_gmock_mutex
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const = 0;
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  // L < g_gmock_mutex
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) = 0;
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const = 0;
+
+  // Sets the mock object this mock method belongs to, and registers
+  // this information in the global mock registry.  Will be called
+  // whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+  // method.
+  // TODO(wan@google.com): rename to SetAndRegisterOwner().
+  // L < g_gmock_mutex
+  void RegisterOwner(const void* mock_obj);
+
+  // Sets the mock object this mock method belongs to, and sets the
+  // name of the mock function.  Will be called upon each invocation
+  // of this mock function.
+  // L < g_gmock_mutex
+  void SetOwnerAndName(const void* mock_obj, const char* name);
+
+  // Returns the mock object this mock method belongs to.  Must be
+  // called after RegisterOwner() or SetOwnerAndName() has been
+  // called.
+  // L < g_gmock_mutex
+  const void* MockObject() const;
+
+  // Returns the name of this mock method.  Must be called after
+  // SetOwnerAndName() has been called.
+  // L < g_gmock_mutex
+  const char* Name() const;
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.  The caller is responsible for deleting the
+  // result.
+  // L < g_gmock_mutex
+  const UntypedActionResultHolderBase* UntypedInvokeWith(
+      const void* untyped_args);
+
+ protected:
+  typedef std::vector<const void*> UntypedOnCallSpecs;
+
+  typedef std::vector<internal::linked_ptr<ExpectationBase> >
+  UntypedExpectations;
+
+  // Returns an Expectation object that references and co-owns exp,
+  // which must be an expectation on this mock function.
+  Expectation GetHandleOf(ExpectationBase* exp);
+
+  // Address of the mock object this mock method belongs to.  Only
+  // valid after this mock method has been called or
+  // ON_CALL/EXPECT_CALL has been invoked on it.
+  const void* mock_obj_;  // Protected by g_gmock_mutex.
+
+  // Name of the function being mocked.  Only valid after this mock
+  // method has been called.
+  const char* name_;  // Protected by g_gmock_mutex.
+
+  // All default action specs for this function mocker.
+  UntypedOnCallSpecs untyped_on_call_specs_;
+
+  // All expectations for this function mocker.
+  UntypedExpectations untyped_expectations_;
+};  // class UntypedFunctionMockerBase
+
+// Untyped base class for OnCallSpec<F>.
+class UntypedOnCallSpecBase {
+ public:
+  // The arguments are the location of the ON_CALL() statement.
+  UntypedOnCallSpecBase(const char* a_file, int a_line)
+      : file_(a_file), line_(a_line), last_clause_(kNone) {}
+
+  // Where in the source file was the default action spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+
+ protected:
+  // Gives each clause in the ON_CALL() statement a name.
+  enum Clause {
+    // Do not change the order of the enum members!  The run-time
+    // syntax checking relies on it.
+    kNone,
+    kWith,
+    kWillByDefault
+  };
+
+  // Asserts that the ON_CALL() statement has a certain property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the ON_CALL() statement has a certain property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  const char* file_;
+  int line_;
+
+  // The last clause in the ON_CALL() statement as seen so far.
+  // Initially kNone and changes as the statement is parsed.
+  Clause last_clause_;
+};  // class UntypedOnCallSpecBase
+
+// This template class implements an ON_CALL spec.
+template <typename F>
+class OnCallSpec : public UntypedOnCallSpecBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  // Constructs an OnCallSpec object from the information inside
+  // the parenthesis of an ON_CALL() statement.
+  OnCallSpec(const char* a_file, int a_line,
+             const ArgumentMatcherTuple& matchers)
+      : UntypedOnCallSpecBase(a_file, a_line),
+        matchers_(matchers),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()) {
+  }
+
+  // Implements the .With() clause.
+  OnCallSpec& With(const Matcher<const ArgumentTuple&>& m) {
+    // Makes sure this is called at most once.
+    ExpectSpecProperty(last_clause_ < kWith,
+                       ".With() cannot appear "
+                       "more than once in an ON_CALL().");
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    return *this;
+  }
+
+  // Implements the .WillByDefault() clause.
+  OnCallSpec& WillByDefault(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ < kWillByDefault,
+                       ".WillByDefault() must appear "
+                       "exactly once in an ON_CALL().");
+    last_clause_ = kWillByDefault;
+
+    ExpectSpecProperty(!action.IsDoDefault(),
+                       "DoDefault() cannot be used in ON_CALL().");
+    action_ = action;
+    return *this;
+  }
+
+  // Returns true iff the given arguments match the matchers.
+  bool Matches(const ArgumentTuple& args) const {
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns the action specified by the user.
+  const Action<F>& GetAction() const {
+    AssertSpecProperty(last_clause_ == kWillByDefault,
+                       ".WillByDefault() must appear exactly "
+                       "once in an ON_CALL().");
+    return action_;
+  }
+
+ private:
+  // The information in statement
+  //
+  //   ON_CALL(mock_object, Method(matchers))
+  //       .With(multi-argument-matcher)
+  //       .WillByDefault(action);
+  //
+  // is recorded in the data members like this:
+  //
+  //   source file that contains the statement => file_
+  //   line number of the statement            => line_
+  //   matchers                                => matchers_
+  //   multi-argument-matcher                  => extra_matcher_
+  //   action                                  => action_
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> action_;
+};  // class OnCallSpec
+
+// Possible reactions on uninteresting calls.  TODO(wan@google.com):
+// rename the enum values to the kFoo style.
+enum CallReaction {
+  ALLOW,
+  WARN,
+  FAIL
+};
+
+}  // namespace internal
+
+// Utilities for manipulating mock objects.
+class Mock {
+ public:
+  // The following public methods can be called concurrently.
+
+  // Tells Google Mock to ignore mock_obj when checking for leaked
+  // mock objects.
+  static void AllowLeak(const void* mock_obj);
+
+  // Verifies and clears all expectations on the given mock object.
+  // If the expectations aren't satisfied, generates one or more
+  // Google Test non-fatal failures and returns false.
+  static bool VerifyAndClearExpectations(void* mock_obj);
+
+  // Verifies all expectations on the given mock object and clears its
+  // default actions and expectations.  Returns true iff the
+  // verification was successful.
+  static bool VerifyAndClear(void* mock_obj);
+ private:
+  friend class internal::UntypedFunctionMockerBase;
+
+  // Needed for a function mocker to register itself (so that we know
+  // how to clear a mock object).
+  template <typename F>
+  friend class internal::FunctionMockerBase;
+
+  template <typename M>
+  friend class NiceMock;
+
+  template <typename M>
+  friend class StrictMock;
+
+  // Tells Google Mock to allow uninteresting calls on the given mock
+  // object.
+  // L < g_gmock_mutex
+  static void AllowUninterestingCalls(const void* mock_obj);
+
+  // Tells Google Mock to warn the user about uninteresting calls on
+  // the given mock object.
+  // L < g_gmock_mutex
+  static void WarnUninterestingCalls(const void* mock_obj);
+
+  // Tells Google Mock to fail uninteresting calls on the given mock
+  // object.
+  // L < g_gmock_mutex
+  static void FailUninterestingCalls(const void* mock_obj);
+
+  // Tells Google Mock the given mock object is being destroyed and
+  // its entry in the call-reaction table should be removed.
+  // L < g_gmock_mutex
+  static void UnregisterCallReaction(const void* mock_obj);
+
+  // Returns the reaction Google Mock will have on uninteresting calls
+  // made on the given mock object.
+  // L < g_gmock_mutex
+  static internal::CallReaction GetReactionOnUninterestingCalls(
+      const void* mock_obj);
+
+  // Verifies that all expectations on the given mock object have been
+  // satisfied.  Reports one or more Google Test non-fatal failures
+  // and returns false if not.
+  // L >= g_gmock_mutex
+  static bool VerifyAndClearExpectationsLocked(void* mock_obj);
+
+  // Clears all ON_CALL()s set on the given mock object.
+  // L >= g_gmock_mutex
+  static void ClearDefaultActionsLocked(void* mock_obj);
+
+  // Registers a mock object and a mock method it owns.
+  // L < g_gmock_mutex
+  static void Register(const void* mock_obj,
+                       internal::UntypedFunctionMockerBase* mocker);
+
+  // Tells Google Mock where in the source code mock_obj is used in an
+  // ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+  // information helps the user identify which object it is.
+  // L < g_gmock_mutex
+  static void RegisterUseByOnCallOrExpectCall(
+      const void* mock_obj, const char* file, int line);
+
+  // Unregisters a mock method; removes the owning mock object from
+  // the registry when the last mock method associated with it has
+  // been unregistered.  This is called only in the destructor of
+  // FunctionMockerBase.
+  // L >= g_gmock_mutex
+  static void UnregisterLocked(internal::UntypedFunctionMockerBase* mocker);
+};  // class Mock
+
+// An abstract handle of an expectation.  Useful in the .After()
+// clause of EXPECT_CALL() for setting the (partial) order of
+// expectations.  The syntax:
+//
+//   Expectation e1 = EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(e1)...;
+//
+// sets two expectations where the latter can only be matched after
+// the former has been satisfied.
+//
+// Notes:
+//   - This class is copyable and has value semantics.
+//   - Constness is shallow: a const Expectation object itself cannot
+//     be modified, but the mutable methods of the ExpectationBase
+//     object it references can be called via expectation_base().
+//   - The constructors and destructor are defined out-of-line because
+//     the Symbian WINSCW compiler wants to otherwise instantiate them
+//     when it sees this class definition, at which point it doesn't have
+//     ExpectationBase available yet, leading to incorrect destruction
+//     in the linked_ptr (or compilation errors if using a checking
+//     linked_ptr).
+class Expectation {
+ public:
+  // Constructs a null object that doesn't reference any expectation.
+  Expectation();
+
+  ~Expectation();
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   Expectation e = EXPECT_CALL(...);
+  // syntax.
+  //
+  // A TypedExpectation object stores its pre-requisites as
+  // Expectation objects, and needs to call the non-const Retire()
+  // method on the ExpectationBase objects they reference.  Therefore
+  // Expectation must receive a *non-const* reference to the
+  // ExpectationBase object.
+  Expectation(internal::ExpectationBase& exp);  // NOLINT
+
+  // The compiler-generated copy ctor and operator= work exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true iff rhs references the same expectation as this object does.
+  bool operator==(const Expectation& rhs) const {
+    return expectation_base_ == rhs.expectation_base_;
+  }
+
+  bool operator!=(const Expectation& rhs) const { return !(*this == rhs); }
+
+ private:
+  friend class ExpectationSet;
+  friend class Sequence;
+  friend class ::testing::internal::ExpectationBase;
+  friend class ::testing::internal::UntypedFunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::FunctionMockerBase;
+
+  template <typename F>
+  friend class ::testing::internal::TypedExpectation;
+
+  // This comparator is needed for putting Expectation objects into a set.
+  class Less {
+   public:
+    bool operator()(const Expectation& lhs, const Expectation& rhs) const {
+      return lhs.expectation_base_.get() < rhs.expectation_base_.get();
+    }
+  };
+
+  typedef ::std::set<Expectation, Less> Set;
+
+  Expectation(
+      const internal::linked_ptr<internal::ExpectationBase>& expectation_base);
+
+  // Returns the expectation this object references.
+  const internal::linked_ptr<internal::ExpectationBase>&
+  expectation_base() const {
+    return expectation_base_;
+  }
+
+  // A linked_ptr that co-owns the expectation this handle references.
+  internal::linked_ptr<internal::ExpectationBase> expectation_base_;
+};
+
+// A set of expectation handles.  Useful in the .After() clause of
+// EXPECT_CALL() for setting the (partial) order of expectations.  The
+// syntax:
+//
+//   ExpectationSet es;
+//   es += EXPECT_CALL(...)...;
+//   es += EXPECT_CALL(...)...;
+//   EXPECT_CALL(...).After(es)...;
+//
+// sets three expectations where the last one can only be matched
+// after the first two have both been satisfied.
+//
+// This class is copyable and has value semantics.
+class ExpectationSet {
+ public:
+  // A bidirectional iterator that can read a const element in the set.
+  typedef Expectation::Set::const_iterator const_iterator;
+
+  // An object stored in the set.  This is an alias of Expectation.
+  typedef Expectation::Set::value_type value_type;
+
+  // Constructs an empty set.
+  ExpectationSet() {}
+
+  // This single-argument ctor must not be explicit, in order to support the
+  //   ExpectationSet es = EXPECT_CALL(...);
+  // syntax.
+  ExpectationSet(internal::ExpectationBase& exp) {  // NOLINT
+    *this += Expectation(exp);
+  }
+
+  // This single-argument ctor implements implicit conversion from
+  // Expectation and thus must not be explicit.  This allows either an
+  // Expectation or an ExpectationSet to be used in .After().
+  ExpectationSet(const Expectation& e) {  // NOLINT
+    *this += e;
+  }
+
+  // The compiler-generator ctor and operator= works exactly as
+  // intended, so we don't need to define our own.
+
+  // Returns true iff rhs contains the same set of Expectation objects
+  // as this does.
+  bool operator==(const ExpectationSet& rhs) const {
+    return expectations_ == rhs.expectations_;
+  }
+
+  bool operator!=(const ExpectationSet& rhs) const { return !(*this == rhs); }
+
+  // Implements the syntax
+  //   expectation_set += EXPECT_CALL(...);
+  ExpectationSet& operator+=(const Expectation& e) {
+    expectations_.insert(e);
+    return *this;
+  }
+
+  int size() const { return static_cast<int>(expectations_.size()); }
+
+  const_iterator begin() const { return expectations_.begin(); }
+  const_iterator end() const { return expectations_.end(); }
+
+ private:
+  Expectation::Set expectations_;
+};
+
+
+// Sequence objects are used by a user to specify the relative order
+// in which the expectations should match.  They are copyable (we rely
+// on the compiler-defined copy constructor and assignment operator).
+class Sequence {
+ public:
+  // Constructs an empty sequence.
+  Sequence() : last_expectation_(new Expectation) {}
+
+  // Adds an expectation to this sequence.  The caller must ensure
+  // that no other thread is accessing this Sequence object.
+  void AddExpectation(const Expectation& expectation) const;
+
+ private:
+  // The last expectation in this sequence.  We use a linked_ptr here
+  // because Sequence objects are copyable and we want the copies to
+  // be aliases.  The linked_ptr allows the copies to co-own and share
+  // the same Expectation object.
+  internal::linked_ptr<Expectation> last_expectation_;
+};  // class Sequence
+
+// An object of this type causes all EXPECT_CALL() statements
+// encountered in its scope to be put in an anonymous sequence.  The
+// work is done in the constructor and destructor.  You should only
+// create an InSequence object on the stack.
+//
+// The sole purpose for this class is to support easy definition of
+// sequential expectations, e.g.
+//
+//   {
+//     InSequence dummy;  // The name of the object doesn't matter.
+//
+//     // The following expectations must match in the order they appear.
+//     EXPECT_CALL(a, Bar())...;
+//     EXPECT_CALL(a, Baz())...;
+//     ...
+//     EXPECT_CALL(b, Xyz())...;
+//   }
+//
+// You can create InSequence objects in multiple threads, as long as
+// they are used to affect different mock objects.  The idea is that
+// each thread can create and set up its own mocks as if it's the only
+// thread.  However, for clarity of your tests we recommend you to set
+// up mocks in the main thread unless you have a good reason not to do
+// so.
+class InSequence {
+ public:
+  InSequence();
+  ~InSequence();
+ private:
+  bool sequence_created_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InSequence);  // NOLINT
+} GTEST_ATTRIBUTE_UNUSED_;
+
+namespace internal {
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+extern ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Base class for implementing expectations.
+//
+// There are two reasons for having a type-agnostic base class for
+// Expectation:
+//
+//   1. We need to store collections of expectations of different
+//   types (e.g. all pre-requisites of a particular expectation, all
+//   expectations in a sequence).  Therefore these expectation objects
+//   must share a common base class.
+//
+//   2. We can avoid binary code bloat by moving methods not depending
+//   on the template argument of Expectation to the base class.
+//
+// This class is internal and mustn't be used by user code directly.
+class ExpectationBase {
+ public:
+  // source_text is the EXPECT_CALL(...) source that created this Expectation.
+  ExpectationBase(const char* file, int line, const string& source_text);
+
+  virtual ~ExpectationBase();
+
+  // Where in the source file was the expectation spec defined?
+  const char* file() const { return file_; }
+  int line() const { return line_; }
+  const char* source_text() const { return source_text_.c_str(); }
+  // Returns the cardinality specified in the expectation spec.
+  const Cardinality& cardinality() const { return cardinality_; }
+
+  // Describes the source file location of this expectation.
+  void DescribeLocationTo(::std::ostream* os) const {
+    *os << FormatFileLocation(file(), line()) << " ";
+  }
+
+  // Describes how many times a function call matching this
+  // expectation has occurred.
+  // L >= g_gmock_mutex
+  void DescribeCallCountTo(::std::ostream* os) const;
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) = 0;
+
+ protected:
+  friend class ::testing::Expectation;
+  friend class UntypedFunctionMockerBase;
+
+  enum Clause {
+    // Don't change the order of the enum members!
+    kNone,
+    kWith,
+    kTimes,
+    kInSequence,
+    kAfter,
+    kWillOnce,
+    kWillRepeatedly,
+    kRetiresOnSaturation
+  };
+
+  typedef std::vector<const void*> UntypedActions;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() = 0;
+
+  // Asserts that the EXPECT_CALL() statement has the given property.
+  void AssertSpecProperty(bool property, const string& failure_message) const {
+    Assert(property, file_, line_, failure_message);
+  }
+
+  // Expects that the EXPECT_CALL() statement has the given property.
+  void ExpectSpecProperty(bool property, const string& failure_message) const {
+    Expect(property, file_, line_, failure_message);
+  }
+
+  // Explicitly specifies the cardinality of this expectation.  Used
+  // by the subclasses to implement the .Times() clause.
+  void SpecifyCardinality(const Cardinality& cardinality);
+
+  // Returns true iff the user specified the cardinality explicitly
+  // using a .Times().
+  bool cardinality_specified() const { return cardinality_specified_; }
+
+  // Sets the cardinality of this expectation spec.
+  void set_cardinality(const Cardinality& a_cardinality) {
+    cardinality_ = a_cardinality;
+  }
+
+  // The following group of methods should only be called after the
+  // EXPECT_CALL() statement, and only when g_gmock_mutex is held by
+  // the current thread.
+
+  // Retires all pre-requisites of this expectation.
+  // L >= g_gmock_mutex
+  void RetireAllPreRequisites();
+
+  // Returns true iff this expectation is retired.
+  // L >= g_gmock_mutex
+  bool is_retired() const {
+    g_gmock_mutex.AssertHeld();
+    return retired_;
+  }
+
+  // Retires this expectation.
+  // L >= g_gmock_mutex
+  void Retire() {
+    g_gmock_mutex.AssertHeld();
+    retired_ = true;
+  }
+
+  // Returns true iff this expectation is satisfied.
+  // L >= g_gmock_mutex
+  bool IsSatisfied() const {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSatisfiedByCallCount(call_count_);
+  }
+
+  // Returns true iff this expectation is saturated.
+  // L >= g_gmock_mutex
+  bool IsSaturated() const {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true iff this expectation is over-saturated.
+  // L >= g_gmock_mutex
+  bool IsOverSaturated() const {
+    g_gmock_mutex.AssertHeld();
+    return cardinality().IsOverSaturatedByCallCount(call_count_);
+  }
+
+  // Returns true iff all pre-requisites of this expectation are satisfied.
+  // L >= g_gmock_mutex
+  bool AllPrerequisitesAreSatisfied() const;
+
+  // Adds unsatisfied pre-requisites of this expectation to 'result'.
+  // L >= g_gmock_mutex
+  void FindUnsatisfiedPrerequisites(ExpectationSet* result) const;
+
+  // Returns the number this expectation has been invoked.
+  // L >= g_gmock_mutex
+  int call_count() const {
+    g_gmock_mutex.AssertHeld();
+    return call_count_;
+  }
+
+  // Increments the number this expectation has been invoked.
+  // L >= g_gmock_mutex
+  void IncrementCallCount() {
+    g_gmock_mutex.AssertHeld();
+    call_count_++;
+  }
+
+  // Checks the action count (i.e. the number of WillOnce() and
+  // WillRepeatedly() clauses) against the cardinality if this hasn't
+  // been done before.  Prints a warning if there are too many or too
+  // few actions.
+  // L < mutex_
+  void CheckActionCountIfNotDone() const;
+
+  friend class ::testing::Sequence;
+  friend class ::testing::internal::ExpectationTester;
+
+  template <typename Function>
+  friend class TypedExpectation;
+
+  // Implements the .Times() clause.
+  void UntypedTimes(const Cardinality& a_cardinality);
+
+  // This group of fields are part of the spec and won't change after
+  // an EXPECT_CALL() statement finishes.
+  const char* file_;          // The file that contains the expectation.
+  int line_;                  // The line number of the expectation.
+  const string source_text_;  // The EXPECT_CALL(...) source text.
+  // True iff the cardinality is specified explicitly.
+  bool cardinality_specified_;
+  Cardinality cardinality_;            // The cardinality of the expectation.
+  // The immediate pre-requisites (i.e. expectations that must be
+  // satisfied before this expectation can be matched) of this
+  // expectation.  We use linked_ptr in the set because we want an
+  // Expectation object to be co-owned by its FunctionMocker and its
+  // successors.  This allows multiple mock objects to be deleted at
+  // different times.
+  ExpectationSet immediate_prerequisites_;
+
+  // This group of fields are the current state of the expectation,
+  // and can change as the mock function is called.
+  int call_count_;  // How many times this expectation has been invoked.
+  bool retired_;    // True iff this expectation has retired.
+  UntypedActions untyped_actions_;
+  bool extra_matcher_specified_;
+  bool repeated_action_specified_;  // True if a WillRepeatedly() was specified.
+  bool retires_on_saturation_;
+  Clause last_clause_;
+  mutable bool action_count_checked_;  // Under mutex_.
+  mutable Mutex mutex_;  // Protects action_count_checked_.
+
+  GTEST_DISALLOW_ASSIGN_(ExpectationBase);
+};  // class ExpectationBase
+
+// Impements an expectation for the given function type.
+template <typename F>
+class TypedExpectation : public ExpectationBase {
+ public:
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+  typedef typename Function<F>::Result Result;
+
+  TypedExpectation(FunctionMockerBase<F>* owner,
+                   const char* a_file, int a_line, const string& a_source_text,
+                   const ArgumentMatcherTuple& m)
+      : ExpectationBase(a_file, a_line, a_source_text),
+        owner_(owner),
+        matchers_(m),
+        // By default, extra_matcher_ should match anything.  However,
+        // we cannot initialize it with _ as that triggers a compiler
+        // bug in Symbian's C++ compiler (cannot decide between two
+        // overloaded constructors of Matcher<const ArgumentTuple&>).
+        extra_matcher_(A<const ArgumentTuple&>()),
+        repeated_action_(DoDefault()) {}
+
+  virtual ~TypedExpectation() {
+    // Check the validity of the action count if it hasn't been done
+    // yet (for example, if the expectation was never used).
+    CheckActionCountIfNotDone();
+    for (UntypedActions::const_iterator it = untyped_actions_.begin();
+         it != untyped_actions_.end(); ++it) {
+      delete static_cast<const Action<F>*>(*it);
+    }
+  }
+
+  // Implements the .With() clause.
+  TypedExpectation& With(const Matcher<const ArgumentTuple&>& m) {
+    if (last_clause_ == kWith) {
+      ExpectSpecProperty(false,
+                         ".With() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWith,
+                         ".With() must be the first "
+                         "clause in an EXPECT_CALL().");
+    }
+    last_clause_ = kWith;
+
+    extra_matcher_ = m;
+    extra_matcher_specified_ = true;
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(const Cardinality& a_cardinality) {
+    ExpectationBase::UntypedTimes(a_cardinality);
+    return *this;
+  }
+
+  // Implements the .Times() clause.
+  TypedExpectation& Times(int n) {
+    return Times(Exactly(n));
+  }
+
+  // Implements the .InSequence() clause.
+  TypedExpectation& InSequence(const Sequence& s) {
+    ExpectSpecProperty(last_clause_ <= kInSequence,
+                       ".InSequence() cannot appear after .After(),"
+                       " .WillOnce(), .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kInSequence;
+
+    s.AddExpectation(GetHandle());
+    return *this;
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2) {
+    return InSequence(s1).InSequence(s2);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3) {
+    return InSequence(s1, s2).InSequence(s3);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4) {
+    return InSequence(s1, s2, s3).InSequence(s4);
+  }
+  TypedExpectation& InSequence(const Sequence& s1, const Sequence& s2,
+                               const Sequence& s3, const Sequence& s4,
+                               const Sequence& s5) {
+    return InSequence(s1, s2, s3, s4).InSequence(s5);
+  }
+
+  // Implements that .After() clause.
+  TypedExpectation& After(const ExpectationSet& s) {
+    ExpectSpecProperty(last_clause_ <= kAfter,
+                       ".After() cannot appear after .WillOnce(),"
+                       " .WillRepeatedly(), or "
+                       ".RetiresOnSaturation().");
+    last_clause_ = kAfter;
+
+    for (ExpectationSet::const_iterator it = s.begin(); it != s.end(); ++it) {
+      immediate_prerequisites_ += *it;
+    }
+    return *this;
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2) {
+    return After(s1).After(s2);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3) {
+    return After(s1, s2).After(s3);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4) {
+    return After(s1, s2, s3).After(s4);
+  }
+  TypedExpectation& After(const ExpectationSet& s1, const ExpectationSet& s2,
+                          const ExpectationSet& s3, const ExpectationSet& s4,
+                          const ExpectationSet& s5) {
+    return After(s1, s2, s3, s4).After(s5);
+  }
+
+  // Implements the .WillOnce() clause.
+  TypedExpectation& WillOnce(const Action<F>& action) {
+    ExpectSpecProperty(last_clause_ <= kWillOnce,
+                       ".WillOnce() cannot appear after "
+                       ".WillRepeatedly() or .RetiresOnSaturation().");
+    last_clause_ = kWillOnce;
+
+    untyped_actions_.push_back(new Action<F>(action));
+    if (!cardinality_specified()) {
+      set_cardinality(Exactly(static_cast<int>(untyped_actions_.size())));
+    }
+    return *this;
+  }
+
+  // Implements the .WillRepeatedly() clause.
+  TypedExpectation& WillRepeatedly(const Action<F>& action) {
+    if (last_clause_ == kWillRepeatedly) {
+      ExpectSpecProperty(false,
+                         ".WillRepeatedly() cannot appear "
+                         "more than once in an EXPECT_CALL().");
+    } else {
+      ExpectSpecProperty(last_clause_ < kWillRepeatedly,
+                         ".WillRepeatedly() cannot appear "
+                         "after .RetiresOnSaturation().");
+    }
+    last_clause_ = kWillRepeatedly;
+    repeated_action_specified_ = true;
+
+    repeated_action_ = action;
+    if (!cardinality_specified()) {
+      set_cardinality(AtLeast(static_cast<int>(untyped_actions_.size())));
+    }
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Implements the .RetiresOnSaturation() clause.
+  TypedExpectation& RetiresOnSaturation() {
+    ExpectSpecProperty(last_clause_ < kRetiresOnSaturation,
+                       ".RetiresOnSaturation() cannot appear "
+                       "more than once.");
+    last_clause_ = kRetiresOnSaturation;
+    retires_on_saturation_ = true;
+
+    // Now that no more action clauses can be specified, we check
+    // whether their count makes sense.
+    CheckActionCountIfNotDone();
+    return *this;
+  }
+
+  // Returns the matchers for the arguments as specified inside the
+  // EXPECT_CALL() macro.
+  const ArgumentMatcherTuple& matchers() const {
+    return matchers_;
+  }
+
+  // Returns the matcher specified by the .With() clause.
+  const Matcher<const ArgumentTuple&>& extra_matcher() const {
+    return extra_matcher_;
+  }
+
+  // Returns the action specified by the .WillRepeatedly() clause.
+  const Action<F>& repeated_action() const { return repeated_action_; }
+
+  // If this mock method has an extra matcher (i.e. .With(matcher)),
+  // describes it to the ostream.
+  virtual void MaybeDescribeExtraMatcherTo(::std::ostream* os) {
+    if (extra_matcher_specified_) {
+      *os << "    Expected args: ";
+      extra_matcher_.DescribeTo(os);
+      *os << "\n";
+    }
+  }
+
+ private:
+  template <typename Function>
+  friend class FunctionMockerBase;
+
+  // Returns an Expectation object that references and co-owns this
+  // expectation.
+  virtual Expectation GetHandle() {
+    return owner_->GetHandleOf(this);
+  }
+
+  // The following methods will be called only after the EXPECT_CALL()
+  // statement finishes and when the current thread holds
+  // g_gmock_mutex.
+
+  // Returns true iff this expectation matches the given arguments.
+  // L >= g_gmock_mutex
+  bool Matches(const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+    return TupleMatches(matchers_, args) && extra_matcher_.Matches(args);
+  }
+
+  // Returns true iff this expectation should handle the given arguments.
+  // L >= g_gmock_mutex
+  bool ShouldHandleArguments(const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+
+    // In case the action count wasn't checked when the expectation
+    // was defined (e.g. if this expectation has no WillRepeatedly()
+    // or RetiresOnSaturation() clause), we check it when the
+    // expectation is used for the first time.
+    CheckActionCountIfNotDone();
+    return !is_retired() && AllPrerequisitesAreSatisfied() && Matches(args);
+  }
+
+  // Describes the result of matching the arguments against this
+  // expectation to the given ostream.
+  // L >= g_gmock_mutex
+  void ExplainMatchResultTo(const ArgumentTuple& args,
+                            ::std::ostream* os) const {
+    g_gmock_mutex.AssertHeld();
+
+    if (is_retired()) {
+      *os << "         Expected: the expectation is active\n"
+          << "           Actual: it is retired\n";
+    } else if (!Matches(args)) {
+      if (!TupleMatches(matchers_, args)) {
+        ExplainMatchFailureTupleTo(matchers_, args, os);
+      }
+      StringMatchResultListener listener;
+      if (!extra_matcher_.MatchAndExplain(args, &listener)) {
+        *os << "    Expected args: ";
+        extra_matcher_.DescribeTo(os);
+        *os << "\n           Actual: don't match";
+
+        internal::PrintIfNotEmpty(listener.str(), os);
+        *os << "\n";
+      }
+    } else if (!AllPrerequisitesAreSatisfied()) {
+      *os << "         Expected: all pre-requisites are satisfied\n"
+          << "           Actual: the following immediate pre-requisites "
+          << "are not satisfied:\n";
+      ExpectationSet unsatisfied_prereqs;
+      FindUnsatisfiedPrerequisites(&unsatisfied_prereqs);
+      int i = 0;
+      for (ExpectationSet::const_iterator it = unsatisfied_prereqs.begin();
+           it != unsatisfied_prereqs.end(); ++it) {
+        it->expectation_base()->DescribeLocationTo(os);
+        *os << "pre-requisite #" << i++ << "\n";
+      }
+      *os << "                   (end of pre-requisites)\n";
+    } else {
+      // This line is here just for completeness' sake.  It will never
+      // be executed as currently the ExplainMatchResultTo() function
+      // is called only when the mock function call does NOT match the
+      // expectation.
+      *os << "The call matches the expectation.\n";
+    }
+  }
+
+  // Returns the action that should be taken for the current invocation.
+  // L >= g_gmock_mutex
+  const Action<F>& GetCurrentAction(const FunctionMockerBase<F>* mocker,
+                                    const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+    const int count = call_count();
+    Assert(count >= 1, __FILE__, __LINE__,
+           "call_count() is <= 0 when GetCurrentAction() is "
+           "called - this should never happen.");
+
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    if (action_count > 0 && !repeated_action_specified_ &&
+        count > action_count) {
+      // If there is at least one WillOnce() and no WillRepeatedly(),
+      // we warn the user when the WillOnce() clauses ran out.
+      ::std::stringstream ss;
+      DescribeLocationTo(&ss);
+      ss << "Actions ran out in " << source_text() << "...\n"
+         << "Called " << count << " times, but only "
+         << action_count << " WillOnce()"
+         << (action_count == 1 ? " is" : "s are") << " specified - ";
+      mocker->DescribeDefaultActionTo(args, &ss);
+      Log(WARNING, ss.str(), 1);
+    }
+
+    return count <= action_count ?
+        *static_cast<const Action<F>*>(untyped_actions_[count - 1]) :
+        repeated_action();
+  }
+
+  // Given the arguments of a mock function call, if the call will
+  // over-saturate this expectation, returns the default action;
+  // otherwise, returns the next action in this expectation.  Also
+  // describes *what* happened to 'what', and explains *why* Google
+  // Mock does it to 'why'.  This method is not const as it calls
+  // IncrementCallCount().  A return value of NULL means the default
+  // action.
+  // L >= g_gmock_mutex
+  const Action<F>* GetActionForArguments(const FunctionMockerBase<F>* mocker,
+                                         const ArgumentTuple& args,
+                                         ::std::ostream* what,
+                                         ::std::ostream* why) {
+    g_gmock_mutex.AssertHeld();
+    if (IsSaturated()) {
+      // We have an excessive call.
+      IncrementCallCount();
+      *what << "Mock function called more times than expected - ";
+      mocker->DescribeDefaultActionTo(args, what);
+      DescribeCallCountTo(why);
+
+      // TODO(wan@google.com): allow the user to control whether
+      // unexpected calls should fail immediately or continue using a
+      // flag --gmock_unexpected_calls_are_fatal.
+      return NULL;
+    }
+
+    IncrementCallCount();
+    RetireAllPreRequisites();
+
+    if (retires_on_saturation_ && IsSaturated()) {
+      Retire();
+    }
+
+    // Must be done after IncrementCount()!
+    *what << "Mock function call matches " << source_text() <<"...\n";
+    return &(GetCurrentAction(mocker, args));
+  }
+
+  // All the fields below won't change once the EXPECT_CALL()
+  // statement finishes.
+  FunctionMockerBase<F>* const owner_;
+  ArgumentMatcherTuple matchers_;
+  Matcher<const ArgumentTuple&> extra_matcher_;
+  Action<F> repeated_action_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TypedExpectation);
+};  // class TypedExpectation
+
+// A MockSpec object is used by ON_CALL() or EXPECT_CALL() for
+// specifying the default behavior of, or expectation on, a mock
+// function.
+
+// Note: class MockSpec really belongs to the ::testing namespace.
+// However if we define it in ::testing, MSVC will complain when
+// classes in ::testing::internal declare it as a friend class
+// template.  To workaround this compiler bug, we define MockSpec in
+// ::testing::internal and import it into ::testing.
+
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+                     const char* file, int line,
+                     const string& message);
+
+template <typename F>
+class MockSpec {
+ public:
+  typedef typename internal::Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename internal::Function<F>::ArgumentMatcherTuple
+      ArgumentMatcherTuple;
+
+  // Constructs a MockSpec object, given the function mocker object
+  // that the spec is associated with.
+  explicit MockSpec(internal::FunctionMockerBase<F>* function_mocker)
+      : function_mocker_(function_mocker) {}
+
+  // Adds a new default action spec to the function mocker and returns
+  // the newly created spec.
+  internal::OnCallSpec<F>& InternalDefaultActionSetAt(
+      const char* file, int line, const char* obj, const char* call) {
+    LogWithLocation(internal::INFO, file, line,
+        string("ON_CALL(") + obj + ", " + call + ") invoked");
+    return function_mocker_->AddNewOnCallSpec(file, line, matchers_);
+  }
+
+  // Adds a new expectation spec to the function mocker and returns
+  // the newly created spec.
+  internal::TypedExpectation<F>& InternalExpectedAt(
+      const char* file, int line, const char* obj, const char* call) {
+    const string source_text(string("EXPECT_CALL(") + obj + ", " + call + ")");
+    LogWithLocation(internal::INFO, file, line, source_text + " invoked");
+    return function_mocker_->AddNewExpectation(
+        file, line, source_text, matchers_);
+  }
+
+ private:
+  template <typename Function>
+  friend class internal::FunctionMocker;
+
+  void SetMatchers(const ArgumentMatcherTuple& matchers) {
+    matchers_ = matchers;
+  }
+
+  // The function mocker that owns this spec.
+  internal::FunctionMockerBase<F>* const function_mocker_;
+  // The argument matchers specified in the spec.
+  ArgumentMatcherTuple matchers_;
+
+  GTEST_DISALLOW_ASSIGN_(MockSpec);
+};  // class MockSpec
+
+// MSVC warns about using 'this' in base member initializer list, so
+// we need to temporarily disable the warning.  We have to do it for
+// the entire class to suppress the warning, even though it's about
+// the constructor only.
+
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4355)  // Temporarily disables warning 4355.
+#endif  // _MSV_VER
+
+// C++ treats the void type specially.  For example, you cannot define
+// a void-typed variable or pass a void value to a function.
+// ActionResultHolder<T> holds a value of type T, where T must be a
+// copyable type or void (T doesn't need to be default-constructable).
+// It hides the syntactic difference between void and other types, and
+// is used to unify the code for invoking both void-returning and
+// non-void-returning mock functions.
+
+// Untyped base class for ActionResultHolder<T>.
+class UntypedActionResultHolderBase {
+ public:
+  virtual ~UntypedActionResultHolderBase() {}
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const = 0;
+};
+
+// This generic definition is used when T is not void.
+template <typename T>
+class ActionResultHolder : public UntypedActionResultHolderBase {
+ public:
+  explicit ActionResultHolder(T a_value) : value_(a_value) {}
+
+  // The compiler-generated copy constructor and assignment operator
+  // are exactly what we need, so we don't need to define them.
+
+  // Returns the held value and deletes this object.
+  T GetValueAndDelete() const {
+    T retval(value_);
+    delete this;
+    return retval;
+  }
+
+  // Prints the held value as an action's result to os.
+  virtual void PrintAsActionResult(::std::ostream* os) const {
+    *os << "\n          Returns: ";
+    // T may be a reference type, so we don't use UniversalPrint().
+    UniversalPrinter<T>::Print(value_, os);
+  }
+
+  // Performs the given mock function's default action and returns the
+  // result in a new-ed ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
+      const string& call_description) {
+    return new ActionResultHolder(
+        func_mocker->PerformDefaultAction(args, call_description));
+  }
+
+  // Performs the given action and returns the result in a new-ed
+  // ActionResultHolder.
+  template <typename F>
+  static ActionResultHolder*
+  PerformAction(const Action<F>& action,
+                const typename Function<F>::ArgumentTuple& args) {
+    return new ActionResultHolder(action.Perform(args));
+  }
+
+ private:
+  T value_;
+
+  // T could be a reference type, so = isn't supported.
+  GTEST_DISALLOW_ASSIGN_(ActionResultHolder);
+};
+
+// Specialization for T = void.
+template <>
+class ActionResultHolder<void> : public UntypedActionResultHolderBase {
+ public:
+  void GetValueAndDelete() const { delete this; }
+
+  virtual void PrintAsActionResult(::std::ostream* /* os */) const {}
+
+  // Performs the given mock function's default action and returns NULL;
+  template <typename F>
+  static ActionResultHolder* PerformDefaultAction(
+      const FunctionMockerBase<F>* func_mocker,
+      const typename Function<F>::ArgumentTuple& args,
+      const string& call_description) {
+    func_mocker->PerformDefaultAction(args, call_description);
+    return NULL;
+  }
+
+  // Performs the given action and returns NULL.
+  template <typename F>
+  static ActionResultHolder* PerformAction(
+      const Action<F>& action,
+      const typename Function<F>::ArgumentTuple& args) {
+    action.Perform(args);
+    return NULL;
+  }
+};
+
+// The base of the function mocker class for the given function type.
+// We put the methods in this class instead of its child to avoid code
+// bloat.
+template <typename F>
+class FunctionMockerBase : public UntypedFunctionMockerBase {
+ public:
+  typedef typename Function<F>::Result Result;
+  typedef typename Function<F>::ArgumentTuple ArgumentTuple;
+  typedef typename Function<F>::ArgumentMatcherTuple ArgumentMatcherTuple;
+
+  FunctionMockerBase() : current_spec_(this) {}
+
+  // The destructor verifies that all expectations on this mock
+  // function have been satisfied.  If not, it will report Google Test
+  // non-fatal failures for the violations.
+  // L < g_gmock_mutex
+  virtual ~FunctionMockerBase() {
+    MutexLock l(&g_gmock_mutex);
+    VerifyAndClearExpectationsLocked();
+    Mock::UnregisterLocked(this);
+    ClearDefaultActionsLocked();
+  }
+
+  // Returns the ON_CALL spec that matches this mock function with the
+  // given arguments; returns NULL if no matching ON_CALL is found.
+  // L = *
+  const OnCallSpec<F>* FindOnCallSpec(
+      const ArgumentTuple& args) const {
+    for (UntypedOnCallSpecs::const_reverse_iterator it
+             = untyped_on_call_specs_.rbegin();
+         it != untyped_on_call_specs_.rend(); ++it) {
+      const OnCallSpec<F>* spec = static_cast<const OnCallSpec<F>*>(*it);
+      if (spec->Matches(args))
+        return spec;
+    }
+
+    return NULL;
+  }
+
+  // Performs the default action of this mock function on the given arguments
+  // and returns the result. Asserts with a helpful call descrption if there is
+  // no valid return value. This method doesn't depend on the mutable state of
+  // this object, and thus can be called concurrently without locking.
+  // L = *
+  Result PerformDefaultAction(const ArgumentTuple& args,
+                              const string& call_description) const {
+    const OnCallSpec<F>* const spec =
+        this->FindOnCallSpec(args);
+    if (spec != NULL) {
+      return spec->GetAction().Perform(args);
+    }
+    Assert(DefaultValue<Result>::Exists(), "", -1,
+           call_description + "\n    The mock function has no default action "
+           "set, and its return type has no default value set.");
+    return DefaultValue<Result>::Get();
+  }
+
+  // Performs the default action with the given arguments and returns
+  // the action's result.  The call description string will be used in
+  // the error message to describe the call in the case the default
+  // action fails.  The caller is responsible for deleting the result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformDefaultAction(
+      const void* untyped_args,  // must point to an ArgumentTuple
+      const string& call_description) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformDefaultAction(this, args, call_description);
+  }
+
+  // Performs the given action with the given arguments and returns
+  // the action's result.  The caller is responsible for deleting the
+  // result.
+  // L = *
+  virtual UntypedActionResultHolderBase* UntypedPerformAction(
+      const void* untyped_action, const void* untyped_args) const {
+    // Make a copy of the action before performing it, in case the
+    // action deletes the mock object (and thus deletes itself).
+    const Action<F> action = *static_cast<const Action<F>*>(untyped_action);
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    return ResultHolder::PerformAction(action, args);
+  }
+
+  // Implements UntypedFunctionMockerBase::ClearDefaultActionsLocked():
+  // clears the ON_CALL()s set on this mock function.
+  // L >= g_gmock_mutex
+  virtual void ClearDefaultActionsLocked() {
+    g_gmock_mutex.AssertHeld();
+    for (UntypedOnCallSpecs::const_iterator it =
+             untyped_on_call_specs_.begin();
+         it != untyped_on_call_specs_.end(); ++it) {
+      delete static_cast<const OnCallSpec<F>*>(*it);
+    }
+    untyped_on_call_specs_.clear();
+  }
+
+ protected:
+  template <typename Function>
+  friend class MockSpec;
+
+  typedef ActionResultHolder<Result> ResultHolder;
+
+  // Returns the result of invoking this mock function with the given
+  // arguments.  This function can be safely called from multiple
+  // threads concurrently.
+  // L < g_gmock_mutex
+  Result InvokeWith(const ArgumentTuple& args) {
+    return static_cast<const ResultHolder*>(
+        this->UntypedInvokeWith(&args))->GetValueAndDelete();
+  }
+
+  // Adds and returns a default action spec for this mock function.
+  // L < g_gmock_mutex
+  OnCallSpec<F>& AddNewOnCallSpec(
+      const char* file, int line,
+      const ArgumentMatcherTuple& m) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    OnCallSpec<F>* const on_call_spec = new OnCallSpec<F>(file, line, m);
+    untyped_on_call_specs_.push_back(on_call_spec);
+    return *on_call_spec;
+  }
+
+  // Adds and returns an expectation spec for this mock function.
+  // L < g_gmock_mutex
+  TypedExpectation<F>& AddNewExpectation(
+      const char* file,
+      int line,
+      const string& source_text,
+      const ArgumentMatcherTuple& m) {
+    Mock::RegisterUseByOnCallOrExpectCall(MockObject(), file, line);
+    TypedExpectation<F>* const expectation =
+        new TypedExpectation<F>(this, file, line, source_text, m);
+    const linked_ptr<ExpectationBase> untyped_expectation(expectation);
+    untyped_expectations_.push_back(untyped_expectation);
+
+    // Adds this expectation into the implicit sequence if there is one.
+    Sequence* const implicit_sequence = g_gmock_implicit_sequence.get();
+    if (implicit_sequence != NULL) {
+      implicit_sequence->AddExpectation(Expectation(untyped_expectation));
+    }
+
+    return *expectation;
+  }
+
+  // The current spec (either default action spec or expectation spec)
+  // being described on this function mocker.
+  MockSpec<F>& current_spec() { return current_spec_; }
+
+ private:
+  template <typename Func> friend class TypedExpectation;
+
+  // Some utilities needed for implementing UntypedInvokeWith().
+
+  // Describes what default action will be performed for the given
+  // arguments.
+  // L = *
+  void DescribeDefaultActionTo(const ArgumentTuple& args,
+                               ::std::ostream* os) const {
+    const OnCallSpec<F>* const spec = FindOnCallSpec(args);
+
+    if (spec == NULL) {
+      *os << (internal::type_equals<Result, void>::value ?
+              "returning directly.\n" :
+              "returning default value.\n");
+    } else {
+      *os << "taking default action specified at:\n"
+          << FormatFileLocation(spec->file(), spec->line()) << "\n";
+    }
+  }
+
+  // Writes a message that the call is uninteresting (i.e. neither
+  // explicitly expected nor explicitly unexpected) to the given
+  // ostream.
+  // L < g_gmock_mutex
+  virtual void UntypedDescribeUninterestingCall(const void* untyped_args,
+                                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    *os << "Uninteresting mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    *os << "    Function call: " << Name();
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the given function arguments
+  // (or NULL is there's no match); when a match is found,
+  // untyped_action is set to point to the action that should be
+  // performed (or NULL if the action is "do default"), and
+  // is_excessive is modified to indicate whether the call exceeds the
+  // expected number.
+  //
+  // Critical section: We must find the matching expectation and the
+  // corresponding action that needs to be taken in an ATOMIC
+  // transaction.  Otherwise another thread may call this mock
+  // method in the middle and mess up the state.
+  //
+  // However, performing the action has to be left out of the critical
+  // section.  The reason is that we have no control on what the
+  // action does (it can invoke an arbitrary user function or even a
+  // mock function) and excessive locking could cause a dead lock.
+  // L < g_gmock_mutex
+  virtual const ExpectationBase* UntypedFindMatchingExpectation(
+      const void* untyped_args,
+      const void** untyped_action, bool* is_excessive,
+      ::std::ostream* what, ::std::ostream* why) {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    MutexLock l(&g_gmock_mutex);
+    TypedExpectation<F>* exp = this->FindMatchingExpectationLocked(args);
+    if (exp == NULL) {  // A match wasn't found.
+      this->FormatUnexpectedCallMessageLocked(args, what, why);
+      return NULL;
+    }
+
+    // This line must be done before calling GetActionForArguments(),
+    // which will increment the call count for *exp and thus affect
+    // its saturation status.
+    *is_excessive = exp->IsSaturated();
+    const Action<F>* action = exp->GetActionForArguments(this, args, what, why);
+    if (action != NULL && action->IsDoDefault())
+      action = NULL;  // Normalize "do default" to NULL.
+    *untyped_action = action;
+    return exp;
+  }
+
+  // Prints the given function arguments to the ostream.
+  virtual void UntypedPrintArgs(const void* untyped_args,
+                                ::std::ostream* os) const {
+    const ArgumentTuple& args =
+        *static_cast<const ArgumentTuple*>(untyped_args);
+    UniversalPrint(args, os);
+  }
+
+  // Returns the expectation that matches the arguments, or NULL if no
+  // expectation matches them.
+  // L >= g_gmock_mutex
+  TypedExpectation<F>* FindMatchingExpectationLocked(
+      const ArgumentTuple& args) const {
+    g_gmock_mutex.AssertHeld();
+    for (typename UntypedExpectations::const_reverse_iterator it =
+             untyped_expectations_.rbegin();
+         it != untyped_expectations_.rend(); ++it) {
+      TypedExpectation<F>* const exp =
+          static_cast<TypedExpectation<F>*>(it->get());
+      if (exp->ShouldHandleArguments(args)) {
+        return exp;
+      }
+    }
+    return NULL;
+  }
+
+  // Returns a message that the arguments don't match any expectation.
+  // L >= g_gmock_mutex
+  void FormatUnexpectedCallMessageLocked(const ArgumentTuple& args,
+                                         ::std::ostream* os,
+                                         ::std::ostream* why) const {
+    g_gmock_mutex.AssertHeld();
+    *os << "\nUnexpected mock function call - ";
+    DescribeDefaultActionTo(args, os);
+    PrintTriedExpectationsLocked(args, why);
+  }
+
+  // Prints a list of expectations that have been tried against the
+  // current mock function call.
+  // L >= g_gmock_mutex
+  void PrintTriedExpectationsLocked(const ArgumentTuple& args,
+                                    ::std::ostream* why) const {
+    g_gmock_mutex.AssertHeld();
+    const int count = static_cast<int>(untyped_expectations_.size());
+    *why << "Google Mock tried the following " << count << " "
+         << (count == 1 ? "expectation, but it didn't match" :
+             "expectations, but none matched")
+         << ":\n";
+    for (int i = 0; i < count; i++) {
+      TypedExpectation<F>* const expectation =
+          static_cast<TypedExpectation<F>*>(untyped_expectations_[i].get());
+      *why << "\n";
+      expectation->DescribeLocationTo(why);
+      if (count > 1) {
+        *why << "tried expectation #" << i << ": ";
+      }
+      *why << expectation->source_text() << "...\n";
+      expectation->ExplainMatchResultTo(args, why);
+      expectation->DescribeCallCountTo(why);
+    }
+  }
+
+  // The current spec (either default action spec or expectation spec)
+  // being described on this function mocker.
+  MockSpec<F> current_spec_;
+
+  // There is no generally useful and implementable semantics of
+  // copying a mock object, so copying a mock is usually a user error.
+  // Thus we disallow copying function mockers.  If the user really
+  // wants to copy a mock object, he should implement his own copy
+  // operation, for example:
+  //
+  //   class MockFoo : public Foo {
+  //    public:
+  //     // Defines a copy constructor explicitly.
+  //     MockFoo(const MockFoo& src) {}
+  //     ...
+  //   };
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(FunctionMockerBase);
+};  // class FunctionMockerBase
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif  // _MSV_VER
+
+// Implements methods of FunctionMockerBase.
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures and
+// returns false if not.
+// L >= g_gmock_mutex
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const string& msg);
+
+}  // namespace internal
+
+// The style guide prohibits "using" statements in a namespace scope
+// inside a header file.  However, the MockSpec class template is
+// meant to be defined in the ::testing namespace.  The following line
+// is just a trick for working around a bug in MSVC 8.0, which cannot
+// handle it if we define MockSpec in ::testing.
+using internal::MockSpec;
+
+// Const(x) is a convenient function for obtaining a const reference
+// to x.  This is useful for setting expectations on an overloaded
+// const mock method, e.g.
+//
+//   class MockFoo : public FooInterface {
+//    public:
+//     MOCK_METHOD0(Bar, int());
+//     MOCK_CONST_METHOD0(Bar, int&());
+//   };
+//
+//   MockFoo foo;
+//   // Expects a call to non-const MockFoo::Bar().
+//   EXPECT_CALL(foo, Bar());
+//   // Expects a call to const MockFoo::Bar().
+//   EXPECT_CALL(Const(foo), Bar());
+template <typename T>
+inline const T& Const(const T& x) { return x; }
+
+// Constructs an Expectation object that references and co-owns exp.
+inline Expectation::Expectation(internal::ExpectationBase& exp)  // NOLINT
+    : expectation_base_(exp.GetHandle().expectation_base()) {}
+
+}  // namespace testing
+
+// A separate macro is required to avoid compile errors when the name
+// of the method used in call is a result of macro expansion.
+// See CompilesWithMethodNameExpandedFromMacro tests in
+// internal/gmock-spec-builders_test.cc for more details.
+#define GMOCK_ON_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).InternalDefaultActionSetAt(__FILE__, __LINE__, \
+                                                    #obj, #call)
+#define ON_CALL(obj, call) GMOCK_ON_CALL_IMPL_(obj, call)
+
+#define GMOCK_EXPECT_CALL_IMPL_(obj, call) \
+    ((obj).gmock_##call).InternalExpectedAt(__FILE__, __LINE__, #obj, #call)
+#define EXPECT_CALL(obj, call) GMOCK_EXPECT_CALL_IMPL_(obj, call)
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/gmock.h	(revision 11817)
@@ -0,0 +1,93 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This is the main header file a user should include.
+
+#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_
+#define GMOCK_INCLUDE_GMOCK_GMOCK_H_
+
+// This file implements the following syntax:
+//
+//   ON_CALL(mock_object.Method(...))
+//     .With(...) ?
+//     .WillByDefault(...);
+//
+// where With() is optional and WillByDefault() must appear exactly
+// once.
+//
+//   EXPECT_CALL(mock_object.Method(...))
+//     .With(...) ?
+//     .Times(...) ?
+//     .InSequence(...) *
+//     .WillOnce(...) *
+//     .WillRepeatedly(...) ?
+//     .RetiresOnSaturation() ? ;
+//
+// where all clauses are optional and WillOnce() can be repeated.
+
+#include "gmock/gmock-actions.h"
+#include "gmock/gmock-cardinalities.h"
+#include "gmock/gmock-generated-actions.h"
+#include "gmock/gmock-generated-function-mockers.h"
+#include "gmock/gmock-generated-matchers.h"
+#include "gmock/gmock-more-actions.h"
+#include "gmock/gmock-generated-nice-strict.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/internal/gmock-internal-utils.h"
+
+namespace testing {
+
+// Declares Google Mock flags that we want a user to use programmatically.
+GMOCK_DECLARE_bool_(catch_leaked_mocks);
+GMOCK_DECLARE_string_(verbose);
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses the command line for the flags
+// that Google Mock recognizes.  Whenever a Google Mock flag is seen,
+// it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+void InitGoogleMock(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleMock(int* argc, wchar_t** argv);
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_GMOCK_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-generated-internal-utils.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-generated-internal-utils.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-generated-internal-utils.h	(revision 11817)
@@ -0,0 +1,277 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file contains template meta-programming utility classes needed
+// for implementing Google Mock.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
+
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+template <typename T>
+class Matcher;
+
+namespace internal {
+
+// An IgnoredValue object can be implicitly constructed from ANY value.
+// This is used in implementing the IgnoreResult(a) action.
+class IgnoredValue {
+ public:
+  // This constructor template allows any value to be implicitly
+  // converted to IgnoredValue.  The object has no data member and
+  // doesn't try to remember anything about the argument.  We
+  // deliberately omit the 'explicit' keyword in order to allow the
+  // conversion to be implicit.
+  template <typename T>
+  IgnoredValue(const T&) {}
+};
+
+// MatcherTuple<T>::type is a tuple type where each field is a Matcher
+// for the corresponding field in tuple type T.
+template <typename Tuple>
+struct MatcherTuple;
+
+template <>
+struct MatcherTuple< ::std::tr1::tuple<> > {
+  typedef ::std::tr1::tuple< > type;
+};
+
+template <typename A1>
+struct MatcherTuple< ::std::tr1::tuple<A1> > {
+  typedef ::std::tr1::tuple<Matcher<A1> > type;
+};
+
+template <typename A1, typename A2>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2> > type;
+};
+
+template <typename A1, typename A2, typename A3>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>,
+      Matcher<A4> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8, typename A9>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9> > type;
+};
+
+template <typename A1, typename A2, typename A3, typename A4, typename A5,
+    typename A6, typename A7, typename A8, typename A9, typename A10>
+struct MatcherTuple< ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+    A10> > {
+  typedef ::std::tr1::tuple<Matcher<A1>, Matcher<A2>, Matcher<A3>, Matcher<A4>,
+      Matcher<A5>, Matcher<A6>, Matcher<A7>, Matcher<A8>, Matcher<A9>,
+      Matcher<A10> > type;
+};
+
+// Template struct Function<F>, where F must be a function type, contains
+// the following typedefs:
+//
+//   Result:               the function's return type.
+//   ArgumentN:            the type of the N-th argument, where N starts with 1.
+//   ArgumentTuple:        the tuple type consisting of all parameters of F.
+//   ArgumentMatcherTuple: the tuple type consisting of Matchers for all
+//                         parameters of F.
+//   MakeResultVoid:       the function type obtained by substituting void
+//                         for the return type of F.
+//   MakeResultIgnoredValue:
+//                         the function type obtained by substituting Something
+//                         for the return type of F.
+template <typename F>
+struct Function;
+
+template <typename R>
+struct Function<R()> {
+  typedef R Result;
+  typedef ::std::tr1::tuple<> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid();
+  typedef IgnoredValue MakeResultIgnoredValue();
+};
+
+template <typename R, typename A1>
+struct Function<R(A1)>
+    : Function<R()> {
+  typedef A1 Argument1;
+  typedef ::std::tr1::tuple<A1> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1);
+  typedef IgnoredValue MakeResultIgnoredValue(A1);
+};
+
+template <typename R, typename A1, typename A2>
+struct Function<R(A1, A2)>
+    : Function<R(A1)> {
+  typedef A2 Argument2;
+  typedef ::std::tr1::tuple<A1, A2> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2);
+};
+
+template <typename R, typename A1, typename A2, typename A3>
+struct Function<R(A1, A2, A3)>
+    : Function<R(A1, A2)> {
+  typedef A3 Argument3;
+  typedef ::std::tr1::tuple<A1, A2, A3> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+struct Function<R(A1, A2, A3, A4)>
+    : Function<R(A1, A2, A3)> {
+  typedef A4 Argument4;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5>
+struct Function<R(A1, A2, A3, A4, A5)>
+    : Function<R(A1, A2, A3, A4)> {
+  typedef A5 Argument5;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6>
+struct Function<R(A1, A2, A3, A4, A5, A6)>
+    : Function<R(A1, A2, A3, A4, A5)> {
+  typedef A6 Argument6;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7)>
+    : Function<R(A1, A2, A3, A4, A5, A6)> {
+  typedef A7 Argument7;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7)> {
+  typedef A8 Argument8;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7, A8)> {
+  typedef A9 Argument9;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
+      A9);
+};
+
+template <typename R, typename A1, typename A2, typename A3, typename A4,
+    typename A5, typename A6, typename A7, typename A8, typename A9,
+    typename A10>
+struct Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)>
+    : Function<R(A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
+  typedef A10 Argument10;
+  typedef ::std::tr1::tuple<A1, A2, A3, A4, A5, A6, A7, A8, A9,
+      A10> ArgumentTuple;
+  typedef typename MatcherTuple<ArgumentTuple>::type ArgumentMatcherTuple;
+  typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10);
+  typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8,
+      A9, A10);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-internal-utils.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-internal-utils.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-internal-utils.h	(revision 11817)
@@ -0,0 +1,463 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
+
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+
+#include "gmock/internal/gmock-generated-internal-utils.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+string ConvertIdentifierNameToWords(const char* id_name);
+
+// PointeeOf<Pointer>::type is the type of a value pointed to by a
+// Pointer, which can be either a smart pointer or a raw pointer.  The
+// following default implementation is for the case where Pointer is a
+// smart pointer.
+template <typename Pointer>
+struct PointeeOf {
+  // Smart pointer classes define type element_type as the type of
+  // their pointees.
+  typedef typename Pointer::element_type type;
+};
+// This specialization is for the raw pointer case.
+template <typename T>
+struct PointeeOf<T*> { typedef T type; };  // NOLINT
+
+// GetRawPointer(p) returns the raw pointer underlying p when p is a
+// smart pointer, or returns p itself when p is already a raw pointer.
+// The following default implementation is for the smart pointer case.
+template <typename Pointer>
+inline typename Pointer::element_type* GetRawPointer(const Pointer& p) {
+  return p.get();
+}
+// This overloaded version is for the raw pointer case.
+template <typename Element>
+inline Element* GetRawPointer(Element* p) { return p; }
+
+// This comparator allows linked_ptr to be stored in sets.
+template <typename T>
+struct LinkedPtrLessThan {
+  bool operator()(const ::testing::internal::linked_ptr<T>& lhs,
+                  const ::testing::internal::linked_ptr<T>& rhs) const {
+    return lhs.get() < rhs.get();
+  }
+};
+
+// Symbian compilation can be done with wchar_t being either a native
+// type or a typedef.  Using Google Mock with OpenC without wchar_t
+// should require the definition of _STLP_NO_WCHAR_T.
+//
+// MSVC treats wchar_t as a native type usually, but treats it as the
+// same as unsigned short when the compiler option /Zc:wchar_t- is
+// specified.  It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t
+// is a native type.
+#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \
+    (defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED))
+// wchar_t is a typedef.
+#else
+# define GMOCK_WCHAR_T_IS_NATIVE_ 1
+#endif
+
+// signed wchar_t and unsigned wchar_t are NOT in the C++ standard.
+// Using them is a bad practice and not portable.  So DON'T use them.
+//
+// Still, Google Mock is designed to work even if the user uses signed
+// wchar_t or unsigned wchar_t (obviously, assuming the compiler
+// supports them).
+//
+// To gcc,
+//   wchar_t == signed wchar_t != unsigned wchar_t == unsigned int
+#ifdef __GNUC__
+// signed/unsigned wchar_t are valid types.
+# define GMOCK_HAS_SIGNED_WCHAR_T_ 1
+#endif
+
+// In what follows, we use the term "kind" to indicate whether a type
+// is bool, an integer type (excluding bool), a floating-point type,
+// or none of them.  This categorization is useful for determining
+// when a matcher argument type can be safely converted to another
+// type in the implementation of SafeMatcherCast.
+enum TypeKind {
+  kBool, kInteger, kFloatingPoint, kOther
+};
+
+// KindOf<T>::value is the kind of type T.
+template <typename T> struct KindOf {
+  enum { value = kOther };  // The default kind.
+};
+
+// This macro declares that the kind of 'type' is 'kind'.
+#define GMOCK_DECLARE_KIND_(type, kind) \
+  template <> struct KindOf<type> { enum { value = kind }; }
+
+GMOCK_DECLARE_KIND_(bool, kBool);
+
+// All standard integer types.
+GMOCK_DECLARE_KIND_(char, kInteger);
+GMOCK_DECLARE_KIND_(signed char, kInteger);
+GMOCK_DECLARE_KIND_(unsigned char, kInteger);
+GMOCK_DECLARE_KIND_(short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(unsigned short, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(int, kInteger);
+GMOCK_DECLARE_KIND_(unsigned int, kInteger);
+GMOCK_DECLARE_KIND_(long, kInteger);  // NOLINT
+GMOCK_DECLARE_KIND_(unsigned long, kInteger);  // NOLINT
+
+#if GMOCK_WCHAR_T_IS_NATIVE_
+GMOCK_DECLARE_KIND_(wchar_t, kInteger);
+#endif
+
+// Non-standard integer types.
+GMOCK_DECLARE_KIND_(Int64, kInteger);
+GMOCK_DECLARE_KIND_(UInt64, kInteger);
+
+// All standard floating-point types.
+GMOCK_DECLARE_KIND_(float, kFloatingPoint);
+GMOCK_DECLARE_KIND_(double, kFloatingPoint);
+GMOCK_DECLARE_KIND_(long double, kFloatingPoint);
+
+#undef GMOCK_DECLARE_KIND_
+
+// Evaluates to the kind of 'type'.
+#define GMOCK_KIND_OF_(type) \
+  static_cast< ::testing::internal::TypeKind>( \
+      ::testing::internal::KindOf<type>::value)
+
+// Evaluates to true iff integer type T is signed.
+#define GMOCK_IS_SIGNED_(T) (static_cast<T>(-1) < 0)
+
+// LosslessArithmeticConvertibleImpl<kFromKind, From, kToKind, To>::value
+// is true iff arithmetic type From can be losslessly converted to
+// arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types, kFromKind is the kind of
+// From, and kToKind is the kind of To; the value is
+// implementation-defined when the above pre-condition is violated.
+template <TypeKind kFromKind, typename From, TypeKind kToKind, typename To>
+struct LosslessArithmeticConvertibleImpl : public false_type {};
+
+// Converting bool to bool is lossless.
+template <>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kBool, bool>
+    : public true_type {};  // NOLINT
+
+// Converting bool to any integer type is lossless.
+template <typename To>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kInteger, To>
+    : public true_type {};  // NOLINT
+
+// Converting bool to any floating-point type is lossless.
+template <typename To>
+struct LosslessArithmeticConvertibleImpl<kBool, bool, kFloatingPoint, To>
+    : public true_type {};  // NOLINT
+
+// Converting an integer to bool is lossy.
+template <typename From>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kBool, bool>
+    : public false_type {};  // NOLINT
+
+// Converting an integer to another non-bool integer is lossless iff
+// the target type's range encloses the source type's range.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kInteger, To>
+    : public bool_constant<
+      // When converting from a smaller size to a larger size, we are
+      // fine as long as we are not converting from signed to unsigned.
+      ((sizeof(From) < sizeof(To)) &&
+       (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) ||
+      // When converting between the same size, the signedness must match.
+      ((sizeof(From) == sizeof(To)) &&
+       (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {};  // NOLINT
+
+#undef GMOCK_IS_SIGNED_
+
+// Converting an integer to a floating-point type may be lossy, since
+// the format of a floating-point number is implementation-defined.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kInteger, From, kFloatingPoint, To>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to bool is lossy.
+template <typename From>
+struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kBool, bool>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to an integer is lossy.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<kFloatingPoint, From, kInteger, To>
+    : public false_type {};  // NOLINT
+
+// Converting a floating-point to another floating-point is lossless
+// iff the target type is at least as big as the source type.
+template <typename From, typename To>
+struct LosslessArithmeticConvertibleImpl<
+  kFloatingPoint, From, kFloatingPoint, To>
+    : public bool_constant<sizeof(From) <= sizeof(To)> {};  // NOLINT
+
+// LosslessArithmeticConvertible<From, To>::value is true iff arithmetic
+// type From can be losslessly converted to arithmetic type To.
+//
+// It's the user's responsibility to ensure that both From and To are
+// raw (i.e. has no CV modifier, is not a pointer, and is not a
+// reference) built-in arithmetic types; the value is
+// implementation-defined when the above pre-condition is violated.
+template <typename From, typename To>
+struct LosslessArithmeticConvertible
+    : public LosslessArithmeticConvertibleImpl<
+  GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {};  // NOLINT
+
+// This interface knows how to report a Google Mock failure (either
+// non-fatal or fatal).
+class FailureReporterInterface {
+ public:
+  // The type of a failure (either non-fatal or fatal).
+  enum FailureType {
+    NONFATAL, FATAL
+  };
+
+  virtual ~FailureReporterInterface() {}
+
+  // Reports a failure that occurred at the given source file location.
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const string& message) = 0;
+};
+
+// Returns the failure reporter used by Google Mock.
+FailureReporterInterface* GetFailureReporter();
+
+// Asserts that condition is true; aborts the process with the given
+// message if condition is false.  We cannot use LOG(FATAL) or CHECK()
+// as Google Mock might be used to mock the log sink itself.  We
+// inline this function to prevent it from showing up in the stack
+// trace.
+inline void Assert(bool condition, const char* file, int line,
+                   const string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::FATAL,
+                                        file, line, msg);
+  }
+}
+inline void Assert(bool condition, const char* file, int line) {
+  Assert(condition, file, line, "Assertion failed.");
+}
+
+// Verifies that condition is true; generates a non-fatal failure if
+// condition is false.
+inline void Expect(bool condition, const char* file, int line,
+                   const string& msg) {
+  if (!condition) {
+    GetFailureReporter()->ReportFailure(FailureReporterInterface::NONFATAL,
+                                        file, line, msg);
+  }
+}
+inline void Expect(bool condition, const char* file, int line) {
+  Expect(condition, file, line, "Expectation failed.");
+}
+
+// Severity level of a log.
+enum LogSeverity {
+  INFO = 0,
+  WARNING = 1
+};
+
+// Valid values for the --gmock_verbose flag.
+
+// All logs (informational and warnings) are printed.
+const char kInfoVerbosity[] = "info";
+// Only warnings are printed.
+const char kWarningVerbosity[] = "warning";
+// No logs are printed.
+const char kErrorVerbosity[] = "error";
+
+// Returns true iff a log with the given severity is visible according
+// to the --gmock_verbose flag.
+bool LogIsVisible(LogSeverity severity);
+
+// Prints the given message to stdout iff 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+void Log(LogSeverity severity, const string& message, int stack_frames_to_skip);
+
+// TODO(wan@google.com): group all type utilities together.
+
+// Type traits.
+
+// is_reference<T>::value is non-zero iff T is a reference type.
+template <typename T> struct is_reference : public false_type {};
+template <typename T> struct is_reference<T&> : public true_type {};
+
+// type_equals<T1, T2>::value is non-zero iff T1 and T2 are the same type.
+template <typename T1, typename T2> struct type_equals : public false_type {};
+template <typename T> struct type_equals<T, T> : public true_type {};
+
+// remove_reference<T>::type removes the reference from type T, if any.
+template <typename T> struct remove_reference { typedef T type; };  // NOLINT
+template <typename T> struct remove_reference<T&> { typedef T type; }; // NOLINT
+
+// Invalid<T>() returns an invalid value of type T.  This is useful
+// when a value of type T is needed for compilation, but the statement
+// will not really be executed (or we don't care if the statement
+// crashes).
+template <typename T>
+inline T Invalid() {
+  return *static_cast<typename remove_reference<T>::type*>(NULL);
+}
+template <>
+inline void Invalid<void>() {}
+
+// Given a raw type (i.e. having no top-level reference or const
+// modifier) RawContainer that's either an STL-style container or a
+// native array, class StlContainerView<RawContainer> has the
+// following members:
+//
+//   - type is a type that provides an STL-style container view to
+//     (i.e. implements the STL container concept for) RawContainer;
+//   - const_reference is a type that provides a reference to a const
+//     RawContainer;
+//   - ConstReference(raw_container) returns a const reference to an STL-style
+//     container view to raw_container, which is a RawContainer.
+//   - Copy(raw_container) returns an STL-style container view of a
+//     copy of raw_container, which is a RawContainer.
+//
+// This generic version is used when RawContainer itself is already an
+// STL-style container.
+template <class RawContainer>
+class StlContainerView {
+ public:
+  typedef RawContainer type;
+  typedef const type& const_reference;
+
+  static const_reference ConstReference(const RawContainer& container) {
+    // Ensures that RawContainer is not a const type.
+    testing::StaticAssertTypeEq<RawContainer,
+        GTEST_REMOVE_CONST_(RawContainer)>();
+    return container;
+  }
+  static type Copy(const RawContainer& container) { return container; }
+};
+
+// This specialization is used when RawContainer is a native array type.
+template <typename Element, size_t N>
+class StlContainerView<Element[N]> {
+ public:
+  typedef GTEST_REMOVE_CONST_(Element) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  // NativeArray<T> can represent a native array either by value or by
+  // reference (selected by a constructor argument), so 'const type'
+  // can be used to reference a const native array.  We cannot
+  // 'typedef const type& const_reference' here, as that would mean
+  // ConstReference() has to return a reference to a local variable.
+  typedef const type const_reference;
+
+  static const_reference ConstReference(const Element (&array)[N]) {
+    // Ensures that Element is not a const type.
+    testing::StaticAssertTypeEq<Element, RawElement>();
+#if GTEST_OS_SYMBIAN
+    // The Nokia Symbian compiler confuses itself in template instantiation
+    // for this call without the cast to Element*:
+    // function call '[testing::internal::NativeArray<char *>].NativeArray(
+    //     {lval} const char *[4], long, testing::internal::RelationToSource)'
+    //     does not match
+    // 'testing::internal::NativeArray<char *>::NativeArray(
+    //     char *const *, unsigned int, testing::internal::RelationToSource)'
+    // (instantiating: 'testing::internal::ContainsMatcherImpl
+    //     <const char * (&)[4]>::Matches(const char * (&)[4]) const')
+    // (instantiating: 'testing::internal::StlContainerView<char *[4]>::
+    //     ConstReference(const char * (&)[4])')
+    // (and though the N parameter type is mismatched in the above explicit
+    // conversion of it doesn't help - only the conversion of the array).
+    return type(const_cast<Element*>(&array[0]), N, kReference);
+#else
+    return type(array, N, kReference);
+#endif  // GTEST_OS_SYMBIAN
+  }
+  static type Copy(const Element (&array)[N]) {
+#if GTEST_OS_SYMBIAN
+    return type(const_cast<Element*>(&array[0]), N, kCopy);
+#else
+    return type(array, N, kCopy);
+#endif  // GTEST_OS_SYMBIAN
+  }
+};
+
+// This specialization is used when RawContainer is a native array
+// represented as a (pointer, size) tuple.
+template <typename ElementPointer, typename Size>
+class StlContainerView< ::std::tr1::tuple<ElementPointer, Size> > {
+ public:
+  typedef GTEST_REMOVE_CONST_(
+      typename internal::PointeeOf<ElementPointer>::type) RawElement;
+  typedef internal::NativeArray<RawElement> type;
+  typedef const type const_reference;
+
+  static const_reference ConstReference(
+      const ::std::tr1::tuple<ElementPointer, Size>& array) {
+    using ::std::tr1::get;
+    return type(get<0>(array), get<1>(array), kReference);
+  }
+  static type Copy(const ::std::tr1::tuple<ElementPointer, Size>& array) {
+    using ::std::tr1::get;
+    return type(get<0>(array), get<1>(array), kCopy);
+  }
+};
+
+// The following specialization prevents the user from instantiating
+// StlContainer with a reference type.
+template <typename T> class StlContainerView<T&>;
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-port.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-port.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/include/gmock/internal/gmock-port.h	(revision 11817)
@@ -0,0 +1,78 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vadimb@google.com (Vadim Berman)
+//
+// Low-level types and utilities for porting Google Mock to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+
+#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
+
+#include <assert.h>
+#include <stdlib.h>
+#include <iostream>
+
+// Most of the types needed for porting Google Mock are also required
+// for Google Test and are defined in gtest-port.h.
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+
+// To avoid conditional compilation everywhere, we make it
+// gmock-port.h's responsibility to #include the header implementing
+// tr1/tuple.  gmock-port.h does this via gtest-port.h, which is
+// guaranteed to pull in the tuple header.
+
+// For MS Visual C++, check the compiler version. At least VS 2003 is
+// required to compile Google Mock.
+#if defined(_MSC_VER) && _MSC_VER < 1310
+# error "At least Visual C++ 2003 (7.1) is required to compile Google Mock."
+#endif
+
+// Macro for referencing flags.  This is public as we want the user to
+// use this syntax to reference Google Mock flags.
+#define GMOCK_FLAG(name) FLAGS_gmock_##name
+
+// Macros for declaring flags.
+#define GMOCK_DECLARE_bool_(name) extern bool GMOCK_FLAG(name)
+#define GMOCK_DECLARE_int32_(name) \
+    extern ::testing::internal::Int32 GMOCK_FLAG(name)
+#define GMOCK_DECLARE_string_(name) \
+    extern ::testing::internal::String GMOCK_FLAG(name)
+
+// Macros for defining flags.
+#define GMOCK_DEFINE_bool_(name, default_val, doc) \
+    bool GMOCK_FLAG(name) = (default_val)
+#define GMOCK_DEFINE_int32_(name, default_val, doc) \
+    ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val)
+#define GMOCK_DEFINE_string_(name, default_val, doc) \
+    ::testing::internal::String GMOCK_FLAG(name) = (default_val)
+
+#endif  // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-all.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-all.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-all.cc	(revision 11817)
@@ -0,0 +1,47 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Mocking Framework (Google Mock)
+//
+// This file #includes all Google Mock implementation .cc files.  The
+// purpose is to allow a user to build Google Mock by compiling this
+// file alone.
+
+// This line ensures that gmock.h can be compiled on its own, even
+// when it's fused.
+#include "gmock/gmock.h"
+
+// The following lines pull in the real gmock *.cc files.
+#include "src/gmock-cardinalities.cc"
+#include "src/gmock-internal-utils.cc"
+#include "src/gmock-matchers.cc"
+#include "src/gmock-spec-builders.cc"
+#include "src/gmock.cc"
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-cardinalities.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-cardinalities.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-cardinalities.cc	(revision 11817)
@@ -0,0 +1,155 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements cardinalities.
+
+#include "gmock/gmock-cardinalities.h"
+
+#include <limits.h>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include "gmock/internal/gmock-internal-utils.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+
+namespace {
+
+// Implements the Between(m, n) cardinality.
+class BetweenCardinalityImpl : public CardinalityInterface {
+ public:
+  BetweenCardinalityImpl(int min, int max)
+      : min_(min >= 0 ? min : 0),
+        max_(max >= min_ ? max : min_) {
+    std::stringstream ss;
+    if (min < 0) {
+      ss << "The invocation lower bound must be >= 0, "
+         << "but is actually " << min << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (max < 0) {
+      ss << "The invocation upper bound must be >= 0, "
+         << "but is actually " << max << ".";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    } else if (min > max) {
+      ss << "The invocation upper bound (" << max
+         << ") must be >= the invocation lower bound (" << min
+         << ").";
+      internal::Expect(false, __FILE__, __LINE__, ss.str());
+    }
+  }
+
+  // Conservative estimate on the lower/upper bound of the number of
+  // calls allowed.
+  virtual int ConservativeLowerBound() const { return min_; }
+  virtual int ConservativeUpperBound() const { return max_; }
+
+  virtual bool IsSatisfiedByCallCount(int call_count) const {
+    return min_ <= call_count && call_count <= max_ ;
+  }
+
+  virtual bool IsSaturatedByCallCount(int call_count) const {
+    return call_count >= max_;
+  }
+
+  virtual void DescribeTo(::std::ostream* os) const;
+ private:
+  const int min_;
+  const int max_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(BetweenCardinalityImpl);
+};
+
+// Formats "n times" in a human-friendly way.
+inline internal::string FormatTimes(int n) {
+  if (n == 1) {
+    return "once";
+  } else if (n == 2) {
+    return "twice";
+  } else {
+    std::stringstream ss;
+    ss << n << " times";
+    return ss.str();
+  }
+}
+
+// Describes the Between(m, n) cardinality in human-friendly text.
+void BetweenCardinalityImpl::DescribeTo(::std::ostream* os) const {
+  if (min_ == 0) {
+    if (max_ == 0) {
+      *os << "never called";
+    } else if (max_ == INT_MAX) {
+      *os << "called any number of times";
+    } else {
+      *os << "called at most " << FormatTimes(max_);
+    }
+  } else if (min_ == max_) {
+    *os << "called " << FormatTimes(min_);
+  } else if (max_ == INT_MAX) {
+    *os << "called at least " << FormatTimes(min_);
+  } else {
+    // 0 < min_ < max_ < INT_MAX
+    *os << "called between " << min_ << " and " << max_ << " times";
+  }
+}
+
+}  // Unnamed namespace
+
+// Describes the given call count to an ostream.
+void Cardinality::DescribeActualCallCountTo(int actual_call_count,
+                                            ::std::ostream* os) {
+  if (actual_call_count > 0) {
+    *os << "called " << FormatTimes(actual_call_count);
+  } else {
+    *os << "never called";
+  }
+}
+
+// Creates a cardinality that allows at least n calls.
+Cardinality AtLeast(int n) { return Between(n, INT_MAX); }
+
+// Creates a cardinality that allows at most n calls.
+Cardinality AtMost(int n) { return Between(0, n); }
+
+// Creates a cardinality that allows any number of calls.
+Cardinality AnyNumber() { return AtLeast(0); }
+
+// Creates a cardinality that allows between min and max calls.
+Cardinality Between(int min, int max) {
+  return Cardinality(new BetweenCardinalityImpl(min, max));
+}
+
+// Creates a cardinality that allows exactly n calls.
+Cardinality Exactly(int n) { return Between(n, n); }
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-internal-utils.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-internal-utils.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-internal-utils.cc	(revision 11817)
@@ -0,0 +1,173 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file defines some utilities useful for implementing Google
+// Mock.  They are subject to change without notice, so please DO NOT
+// USE THEM IN USER CODE.
+
+#include "gmock/internal/gmock-internal-utils.h"
+
+#include <ctype.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+// Converts an identifier name to a space-separated list of lower-case
+// words.  Each maximum substring of the form [A-Za-z][a-z]*|\d+ is
+// treated as one word.  For example, both "FooBar123" and
+// "foo_bar_123" are converted to "foo bar 123".
+string ConvertIdentifierNameToWords(const char* id_name) {
+  string result;
+  char prev_char = '\0';
+  for (const char* p = id_name; *p != '\0'; prev_char = *(p++)) {
+    // We don't care about the current locale as the input is
+    // guaranteed to be a valid C++ identifier name.
+    const bool starts_new_word = IsUpper(*p) ||
+        (!IsAlpha(prev_char) && IsLower(*p)) ||
+        (!IsDigit(prev_char) && IsDigit(*p));
+
+    if (IsAlNum(*p)) {
+      if (starts_new_word && result != "")
+        result += ' ';
+      result += ToLower(*p);
+    }
+  }
+  return result;
+}
+
+// This class reports Google Mock failures as Google Test failures.  A
+// user can define another class in a similar fashion if he intends to
+// use Google Mock with a testing framework other than Google Test.
+class GoogleTestFailureReporter : public FailureReporterInterface {
+ public:
+  virtual void ReportFailure(FailureType type, const char* file, int line,
+                             const string& message) {
+    AssertHelper(type == FATAL ?
+                 TestPartResult::kFatalFailure :
+                 TestPartResult::kNonFatalFailure,
+                 file,
+                 line,
+                 message.c_str()) = Message();
+    if (type == FATAL) {
+      posix::Abort();
+    }
+  }
+};
+
+// Returns the global failure reporter.  Will create a
+// GoogleTestFailureReporter and return it the first time called.
+FailureReporterInterface* GetFailureReporter() {
+  // Points to the global failure reporter used by Google Mock.  gcc
+  // guarantees that the following use of failure_reporter is
+  // thread-safe.  We may need to add additional synchronization to
+  // protect failure_reporter if we port Google Mock to other
+  // compilers.
+  static FailureReporterInterface* const failure_reporter =
+      new GoogleTestFailureReporter();
+  return failure_reporter;
+}
+
+// Protects global resources (stdout in particular) used by Log().
+static GTEST_DEFINE_STATIC_MUTEX_(g_log_mutex);
+
+// Returns true iff a log with the given severity is visible according
+// to the --gmock_verbose flag.
+bool LogIsVisible(LogSeverity severity) {
+  if (GMOCK_FLAG(verbose) == kInfoVerbosity) {
+    // Always show the log if --gmock_verbose=info.
+    return true;
+  } else if (GMOCK_FLAG(verbose) == kErrorVerbosity) {
+    // Always hide it if --gmock_verbose=error.
+    return false;
+  } else {
+    // If --gmock_verbose is neither "info" nor "error", we treat it
+    // as "warning" (its default value).
+    return severity == WARNING;
+  }
+}
+
+// Prints the given message to stdout iff 'severity' >= the level
+// specified by the --gmock_verbose flag.  If stack_frames_to_skip >=
+// 0, also prints the stack trace excluding the top
+// stack_frames_to_skip frames.  In opt mode, any positive
+// stack_frames_to_skip is treated as 0, since we don't know which
+// function calls will be inlined by the compiler and need to be
+// conservative.
+void Log(LogSeverity severity, const string& message,
+         int stack_frames_to_skip) {
+  if (!LogIsVisible(severity))
+    return;
+
+  // Ensures that logs from different threads don't interleave.
+  MutexLock l(&g_log_mutex);
+
+  // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is a
+  // macro.
+
+  if (severity == WARNING) {
+    // Prints a GMOCK WARNING marker to make the warnings easily searchable.
+    std::cout << "\nGMOCK WARNING:";
+  }
+  // Pre-pends a new-line to message if it doesn't start with one.
+  if (message.empty() || message[0] != '\n') {
+    std::cout << "\n";
+  }
+  std::cout << message;
+  if (stack_frames_to_skip >= 0) {
+#ifdef NDEBUG
+    // In opt mode, we have to be conservative and skip no stack frame.
+    const int actual_to_skip = 0;
+#else
+    // In dbg mode, we can do what the caller tell us to do (plus one
+    // for skipping this function's stack frame).
+    const int actual_to_skip = stack_frames_to_skip + 1;
+#endif  // NDEBUG
+
+    // Appends a new-line to message if it doesn't end with one.
+    if (!message.empty() && *message.rbegin() != '\n') {
+      std::cout << "\n";
+    }
+    std::cout << "Stack trace:\n"
+         << ::testing::internal::GetCurrentOsStackTraceExceptTop(
+             ::testing::UnitTest::GetInstance(), actual_to_skip);
+  }
+  std::cout << ::std::flush;
+}
+
+}  // namespace internal
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-matchers.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-matchers.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-matchers.cc	(revision 11817)
@@ -0,0 +1,101 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements Matcher<const string&>, Matcher<string>, and
+// utilities for defining matchers.
+
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock-generated-matchers.h"
+
+#include <string.h>
+#include <sstream>
+#include <string>
+
+namespace testing {
+
+// Constructs a matcher that matches a const string& whose value is
+// equal to s.
+Matcher<const internal::string&>::Matcher(const internal::string& s) {
+  *this = Eq(s);
+}
+
+// Constructs a matcher that matches a const string& whose value is
+// equal to s.
+Matcher<const internal::string&>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+// Constructs a matcher that matches a string whose value is equal to s.
+Matcher<internal::string>::Matcher(const internal::string& s) { *this = Eq(s); }
+
+// Constructs a matcher that matches a string whose value is equal to s.
+Matcher<internal::string>::Matcher(const char* s) {
+  *this = Eq(internal::string(s));
+}
+
+namespace internal {
+
+// Joins a vector of strings as if they are fields of a tuple; returns
+// the joined string.
+string JoinAsTuple(const Strings& fields) {
+  switch (fields.size()) {
+    case 0:
+      return "";
+    case 1:
+      return fields[0];
+    default:
+      string result = "(" + fields[0];
+      for (size_t i = 1; i < fields.size(); i++) {
+        result += ", ";
+        result += fields[i];
+      }
+      result += ")";
+      return result;
+  }
+}
+
+// Returns the description for a matcher defined using the MATCHER*()
+// macro where the user-supplied description string is "", if
+// 'negation' is false; otherwise returns the description of the
+// negation of the matcher.  'param_values' contains a list of strings
+// that are the print-out of the matcher's parameters.
+string FormatMatcherDescription(bool negation, const char* matcher_name,
+                                const Strings& param_values) {
+  string result = ConvertIdentifierNameToWords(matcher_name);
+  if (param_values.size() >= 1)
+    result += " " + JoinAsTuple(param_values);
+  return negation ? "not (" + result + ")" : result;
+}
+
+}  // namespace internal
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-spec-builders.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-spec-builders.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock-spec-builders.cc	(revision 11817)
@@ -0,0 +1,797 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Mock - a framework for writing C++ mock classes.
+//
+// This file implements the spec builder syntax (ON_CALL and
+// EXPECT_CALL).
+
+#include "gmock/gmock-spec-builders.h"
+
+#include <stdlib.h>
+#include <iostream>  // NOLINT
+#include <map>
+#include <set>
+#include <string>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#if GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC
+# include <unistd.h>  // NOLINT
+#endif
+
+namespace testing {
+namespace internal {
+
+// Protects the mock object registry (in class Mock), all function
+// mockers, and all expectations.
+GTEST_DEFINE_STATIC_MUTEX_(g_gmock_mutex);
+
+// Logs a message including file and line number information.
+void LogWithLocation(testing::internal::LogSeverity severity,
+                     const char* file, int line,
+                     const string& message) {
+  ::std::ostringstream s;
+  s << file << ":" << line << ": " << message << ::std::endl;
+  Log(severity, s.str(), 0);
+}
+
+// Constructs an ExpectationBase object.
+ExpectationBase::ExpectationBase(const char* a_file,
+                                 int a_line,
+                                 const string& a_source_text)
+    : file_(a_file),
+      line_(a_line),
+      source_text_(a_source_text),
+      cardinality_specified_(false),
+      cardinality_(Exactly(1)),
+      call_count_(0),
+      retired_(false),
+      extra_matcher_specified_(false),
+      repeated_action_specified_(false),
+      retires_on_saturation_(false),
+      last_clause_(kNone),
+      action_count_checked_(false) {}
+
+// Destructs an ExpectationBase object.
+ExpectationBase::~ExpectationBase() {}
+
+// Explicitly specifies the cardinality of this expectation.  Used by
+// the subclasses to implement the .Times() clause.
+void ExpectationBase::SpecifyCardinality(const Cardinality& a_cardinality) {
+  cardinality_specified_ = true;
+  cardinality_ = a_cardinality;
+}
+
+// Retires all pre-requisites of this expectation.
+void ExpectationBase::RetireAllPreRequisites() {
+  if (is_retired()) {
+    // We can take this short-cut as we never retire an expectation
+    // until we have retired all its pre-requisites.
+    return;
+  }
+
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    ExpectationBase* const prerequisite = it->expectation_base().get();
+    if (!prerequisite->is_retired()) {
+      prerequisite->RetireAllPreRequisites();
+      prerequisite->Retire();
+    }
+  }
+}
+
+// Returns true iff all pre-requisites of this expectation have been
+// satisfied.
+// L >= g_gmock_mutex
+bool ExpectationBase::AllPrerequisitesAreSatisfied() const {
+  g_gmock_mutex.AssertHeld();
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    if (!(it->expectation_base()->IsSatisfied()) ||
+        !(it->expectation_base()->AllPrerequisitesAreSatisfied()))
+      return false;
+  }
+  return true;
+}
+
+// Adds unsatisfied pre-requisites of this expectation to 'result'.
+// L >= g_gmock_mutex
+void ExpectationBase::FindUnsatisfiedPrerequisites(
+    ExpectationSet* result) const {
+  g_gmock_mutex.AssertHeld();
+  for (ExpectationSet::const_iterator it = immediate_prerequisites_.begin();
+       it != immediate_prerequisites_.end(); ++it) {
+    if (it->expectation_base()->IsSatisfied()) {
+      // If *it is satisfied and has a call count of 0, some of its
+      // pre-requisites may not be satisfied yet.
+      if (it->expectation_base()->call_count_ == 0) {
+        it->expectation_base()->FindUnsatisfiedPrerequisites(result);
+      }
+    } else {
+      // Now that we know *it is unsatisfied, we are not so interested
+      // in whether its pre-requisites are satisfied.  Therefore we
+      // don't recursively call FindUnsatisfiedPrerequisites() here.
+      *result += *it;
+    }
+  }
+}
+
+// Describes how many times a function call matching this
+// expectation has occurred.
+// L >= g_gmock_mutex
+void ExpectationBase::DescribeCallCountTo(::std::ostream* os) const {
+  g_gmock_mutex.AssertHeld();
+
+  // Describes how many times the function is expected to be called.
+  *os << "         Expected: to be ";
+  cardinality().DescribeTo(os);
+  *os << "\n           Actual: ";
+  Cardinality::DescribeActualCallCountTo(call_count(), os);
+
+  // Describes the state of the expectation (e.g. is it satisfied?
+  // is it active?).
+  *os << " - " << (IsOverSaturated() ? "over-saturated" :
+                   IsSaturated() ? "saturated" :
+                   IsSatisfied() ? "satisfied" : "unsatisfied")
+      << " and "
+      << (is_retired() ? "retired" : "active");
+}
+
+// Checks the action count (i.e. the number of WillOnce() and
+// WillRepeatedly() clauses) against the cardinality if this hasn't
+// been done before.  Prints a warning if there are too many or too
+// few actions.
+// L < mutex_
+void ExpectationBase::CheckActionCountIfNotDone() const {
+  bool should_check = false;
+  {
+    MutexLock l(&mutex_);
+    if (!action_count_checked_) {
+      action_count_checked_ = true;
+      should_check = true;
+    }
+  }
+
+  if (should_check) {
+    if (!cardinality_specified_) {
+      // The cardinality was inferred - no need to check the action
+      // count against it.
+      return;
+    }
+
+    // The cardinality was explicitly specified.
+    const int action_count = static_cast<int>(untyped_actions_.size());
+    const int upper_bound = cardinality().ConservativeUpperBound();
+    const int lower_bound = cardinality().ConservativeLowerBound();
+    bool too_many;  // True if there are too many actions, or false
+    // if there are too few.
+    if (action_count > upper_bound ||
+        (action_count == upper_bound && repeated_action_specified_)) {
+      too_many = true;
+    } else if (0 < action_count && action_count < lower_bound &&
+               !repeated_action_specified_) {
+      too_many = false;
+    } else {
+      return;
+    }
+
+    ::std::stringstream ss;
+    DescribeLocationTo(&ss);
+    ss << "Too " << (too_many ? "many" : "few")
+       << " actions specified in " << source_text() << "...\n"
+       << "Expected to be ";
+    cardinality().DescribeTo(&ss);
+    ss << ", but has " << (too_many ? "" : "only ")
+       << action_count << " WillOnce()"
+       << (action_count == 1 ? "" : "s");
+    if (repeated_action_specified_) {
+      ss << " and a WillRepeatedly()";
+    }
+    ss << ".";
+    Log(WARNING, ss.str(), -1);  // -1 means "don't print stack trace".
+  }
+}
+
+// Implements the .Times() clause.
+void ExpectationBase::UntypedTimes(const Cardinality& a_cardinality) {
+  if (last_clause_ == kTimes) {
+    ExpectSpecProperty(false,
+                       ".Times() cannot appear "
+                       "more than once in an EXPECT_CALL().");
+  } else {
+    ExpectSpecProperty(last_clause_ < kTimes,
+                       ".Times() cannot appear after "
+                       ".InSequence(), .WillOnce(), .WillRepeatedly(), "
+                       "or .RetiresOnSaturation().");
+  }
+  last_clause_ = kTimes;
+
+  SpecifyCardinality(a_cardinality);
+}
+
+// Points to the implicit sequence introduced by a living InSequence
+// object (if any) in the current thread or NULL.
+ThreadLocal<Sequence*> g_gmock_implicit_sequence;
+
+// Reports an uninteresting call (whose description is in msg) in the
+// manner specified by 'reaction'.
+void ReportUninterestingCall(CallReaction reaction, const string& msg) {
+  switch (reaction) {
+    case ALLOW:
+      Log(INFO, msg, 3);
+      break;
+    case WARN:
+      Log(WARNING, msg, 3);
+      break;
+    default:  // FAIL
+      Expect(false, NULL, -1, msg);
+  }
+}
+
+UntypedFunctionMockerBase::UntypedFunctionMockerBase()
+    : mock_obj_(NULL), name_("") {}
+
+UntypedFunctionMockerBase::~UntypedFunctionMockerBase() {}
+
+// Sets the mock object this mock method belongs to, and registers
+// this information in the global mock registry.  Will be called
+// whenever an EXPECT_CALL() or ON_CALL() is executed on this mock
+// method.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::RegisterOwner(const void* mock_obj) {
+  {
+    MutexLock l(&g_gmock_mutex);
+    mock_obj_ = mock_obj;
+  }
+  Mock::Register(mock_obj, this);
+}
+
+// Sets the mock object this mock method belongs to, and sets the name
+// of the mock function.  Will be called upon each invocation of this
+// mock function.
+// L < g_gmock_mutex
+void UntypedFunctionMockerBase::SetOwnerAndName(
+    const void* mock_obj, const char* name) {
+  // We protect name_ under g_gmock_mutex in case this mock function
+  // is called from two threads concurrently.
+  MutexLock l(&g_gmock_mutex);
+  mock_obj_ = mock_obj;
+  name_ = name;
+}
+
+// Returns the name of the function being mocked.  Must be called
+// after RegisterOwner() or SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const void* UntypedFunctionMockerBase::MockObject() const {
+  const void* mock_obj;
+  {
+    // We protect mock_obj_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(mock_obj_ != NULL, __FILE__, __LINE__,
+           "MockObject() must not be called before RegisterOwner() or "
+           "SetOwnerAndName() has been called.");
+    mock_obj = mock_obj_;
+  }
+  return mock_obj;
+}
+
+// Returns the name of this mock method.  Must be called after
+// SetOwnerAndName() has been called.
+// L < g_gmock_mutex
+const char* UntypedFunctionMockerBase::Name() const {
+  const char* name;
+  {
+    // We protect name_ under g_gmock_mutex in case this mock
+    // function is called from two threads concurrently.
+    MutexLock l(&g_gmock_mutex);
+    Assert(name_ != NULL, __FILE__, __LINE__,
+           "Name() must not be called before SetOwnerAndName() has "
+           "been called.");
+    name = name_;
+  }
+  return name;
+}
+
+// Calculates the result of invoking this mock function with the given
+// arguments, prints it, and returns it.  The caller is responsible
+// for deleting the result.
+// L < g_gmock_mutex
+const UntypedActionResultHolderBase*
+UntypedFunctionMockerBase::UntypedInvokeWith(const void* const untyped_args) {
+  if (untyped_expectations_.size() == 0) {
+    // No expectation is set on this mock method - we have an
+    // uninteresting call.
+
+    // We must get Google Mock's reaction on uninteresting calls
+    // made on this mock object BEFORE performing the action,
+    // because the action may DELETE the mock object and make the
+    // following expression meaningless.
+    const CallReaction reaction =
+        Mock::GetReactionOnUninterestingCalls(MockObject());
+
+    // True iff we need to print this call's arguments and return
+    // value.  This definition must be kept in sync with
+    // the behavior of ReportUninterestingCall().
+    const bool need_to_report_uninteresting_call =
+        // If the user allows this uninteresting call, we print it
+        // only when he wants informational messages.
+        reaction == ALLOW ? LogIsVisible(INFO) :
+        // If the user wants this to be a warning, we print it only
+        // when he wants to see warnings.
+        reaction == WARN ? LogIsVisible(WARNING) :
+        // Otherwise, the user wants this to be an error, and we
+        // should always print detailed information in the error.
+        true;
+
+    if (!need_to_report_uninteresting_call) {
+      // Perform the action without printing the call information.
+      return this->UntypedPerformDefaultAction(untyped_args, "");
+    }
+
+    // Warns about the uninteresting call.
+    ::std::stringstream ss;
+    this->UntypedDescribeUninterestingCall(untyped_args, &ss);
+
+    // Calculates the function result.
+    const UntypedActionResultHolderBase* const result =
+        this->UntypedPerformDefaultAction(untyped_args, ss.str());
+
+    // Prints the function result.
+    if (result != NULL)
+      result->PrintAsActionResult(&ss);
+
+    ReportUninterestingCall(reaction, ss.str());
+    return result;
+  }
+
+  bool is_excessive = false;
+  ::std::stringstream ss;
+  ::std::stringstream why;
+  ::std::stringstream loc;
+  const void* untyped_action = NULL;
+
+  // The UntypedFindMatchingExpectation() function acquires and
+  // releases g_gmock_mutex.
+  const ExpectationBase* const untyped_expectation =
+      this->UntypedFindMatchingExpectation(
+          untyped_args, &untyped_action, &is_excessive,
+          &ss, &why);
+  const bool found = untyped_expectation != NULL;
+
+  // True iff we need to print the call's arguments and return value.
+  // This definition must be kept in sync with the uses of Expect()
+  // and Log() in this function.
+  const bool need_to_report_call = !found || is_excessive || LogIsVisible(INFO);
+  if (!need_to_report_call) {
+    // Perform the action without printing the call information.
+    return
+        untyped_action == NULL ?
+        this->UntypedPerformDefaultAction(untyped_args, "") :
+        this->UntypedPerformAction(untyped_action, untyped_args);
+  }
+
+  ss << "    Function call: " << Name();
+  this->UntypedPrintArgs(untyped_args, &ss);
+
+  // In case the action deletes a piece of the expectation, we
+  // generate the message beforehand.
+  if (found && !is_excessive) {
+    untyped_expectation->DescribeLocationTo(&loc);
+  }
+
+  const UntypedActionResultHolderBase* const result =
+      untyped_action == NULL ?
+      this->UntypedPerformDefaultAction(untyped_args, ss.str()) :
+      this->UntypedPerformAction(untyped_action, untyped_args);
+  if (result != NULL)
+    result->PrintAsActionResult(&ss);
+  ss << "\n" << why.str();
+
+  if (!found) {
+    // No expectation matches this call - reports a failure.
+    Expect(false, NULL, -1, ss.str());
+  } else if (is_excessive) {
+    // We had an upper-bound violation and the failure message is in ss.
+    Expect(false, untyped_expectation->file(),
+           untyped_expectation->line(), ss.str());
+  } else {
+    // We had an expected call and the matching expectation is
+    // described in ss.
+    Log(INFO, loc.str() + ss.str(), 2);
+  }
+
+  return result;
+}
+
+// Returns an Expectation object that references and co-owns exp,
+// which must be an expectation on this mock function.
+Expectation UntypedFunctionMockerBase::GetHandleOf(ExpectationBase* exp) {
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    if (it->get() == exp) {
+      return Expectation(*it);
+    }
+  }
+
+  Assert(false, __FILE__, __LINE__, "Cannot find expectation.");
+  return Expectation();
+  // The above statement is just to make the code compile, and will
+  // never be executed.
+}
+
+// Verifies that all expectations on this mock function have been
+// satisfied.  Reports one or more Google Test non-fatal failures
+// and returns false if not.
+// L >= g_gmock_mutex
+bool UntypedFunctionMockerBase::VerifyAndClearExpectationsLocked() {
+  g_gmock_mutex.AssertHeld();
+  bool expectations_met = true;
+  for (UntypedExpectations::const_iterator it =
+           untyped_expectations_.begin();
+       it != untyped_expectations_.end(); ++it) {
+    ExpectationBase* const untyped_expectation = it->get();
+    if (untyped_expectation->IsOverSaturated()) {
+      // There was an upper-bound violation.  Since the error was
+      // already reported when it occurred, there is no need to do
+      // anything here.
+      expectations_met = false;
+    } else if (!untyped_expectation->IsSatisfied()) {
+      expectations_met = false;
+      ::std::stringstream ss;
+      ss  << "Actual function call count doesn't match "
+          << untyped_expectation->source_text() << "...\n";
+      // No need to show the source file location of the expectation
+      // in the description, as the Expect() call that follows already
+      // takes care of it.
+      untyped_expectation->MaybeDescribeExtraMatcherTo(&ss);
+      untyped_expectation->DescribeCallCountTo(&ss);
+      Expect(false, untyped_expectation->file(),
+             untyped_expectation->line(), ss.str());
+    }
+  }
+  untyped_expectations_.clear();
+  return expectations_met;
+}
+
+}  // namespace internal
+
+// Class Mock.
+
+namespace {
+
+typedef std::set<internal::UntypedFunctionMockerBase*> FunctionMockers;
+
+// The current state of a mock object.  Such information is needed for
+// detecting leaked mock objects and explicitly verifying a mock's
+// expectations.
+struct MockObjectState {
+  MockObjectState()
+      : first_used_file(NULL), first_used_line(-1), leakable(false) {}
+
+  // Where in the source file an ON_CALL or EXPECT_CALL is first
+  // invoked on this mock object.
+  const char* first_used_file;
+  int first_used_line;
+  ::std::string first_used_test_case;
+  ::std::string first_used_test;
+  bool leakable;  // true iff it's OK to leak the object.
+  FunctionMockers function_mockers;  // All registered methods of the object.
+};
+
+// A global registry holding the state of all mock objects that are
+// alive.  A mock object is added to this registry the first time
+// Mock::AllowLeak(), ON_CALL(), or EXPECT_CALL() is called on it.  It
+// is removed from the registry in the mock object's destructor.
+class MockObjectRegistry {
+ public:
+  // Maps a mock object (identified by its address) to its state.
+  typedef std::map<const void*, MockObjectState> StateMap;
+
+  // This destructor will be called when a program exits, after all
+  // tests in it have been run.  By then, there should be no mock
+  // object alive.  Therefore we report any living object as test
+  // failure, unless the user explicitly asked us to ignore it.
+  ~MockObjectRegistry() {
+    // "using ::std::cout;" doesn't work with Symbian's STLport, where cout is
+    // a macro.
+
+    if (!GMOCK_FLAG(catch_leaked_mocks))
+      return;
+
+    int leaked_count = 0;
+    for (StateMap::const_iterator it = states_.begin(); it != states_.end();
+         ++it) {
+      if (it->second.leakable)  // The user said it's fine to leak this object.
+        continue;
+
+      // TODO(wan@google.com): Print the type of the leaked object.
+      // This can help the user identify the leaked object.
+      std::cout << "\n";
+      const MockObjectState& state = it->second;
+      std::cout << internal::FormatFileLocation(state.first_used_file,
+                                                state.first_used_line);
+      std::cout << " ERROR: this mock object";
+      if (state.first_used_test != "") {
+        std::cout << " (used in test " << state.first_used_test_case << "."
+             << state.first_used_test << ")";
+      }
+      std::cout << " should be deleted but never is. Its address is @"
+           << it->first << ".";
+      leaked_count++;
+    }
+    if (leaked_count > 0) {
+      std::cout << "\nERROR: " << leaked_count
+           << " leaked mock " << (leaked_count == 1 ? "object" : "objects")
+           << " found at program exit.\n";
+      std::cout.flush();
+      ::std::cerr.flush();
+      // RUN_ALL_TESTS() has already returned when this destructor is
+      // called.  Therefore we cannot use the normal Google Test
+      // failure reporting mechanism.
+      _exit(1);  // We cannot call exit() as it is not reentrant and
+                 // may already have been called.
+    }
+  }
+
+  StateMap& states() { return states_; }
+ private:
+  StateMap states_;
+};
+
+// Protected by g_gmock_mutex.
+MockObjectRegistry g_mock_object_registry;
+
+// Maps a mock object to the reaction Google Mock should have when an
+// uninteresting method is called.  Protected by g_gmock_mutex.
+std::map<const void*, internal::CallReaction> g_uninteresting_call_reaction;
+
+// Sets the reaction Google Mock should have when an uninteresting
+// method of the given mock object is called.
+// L < g_gmock_mutex
+void SetReactionOnUninterestingCalls(const void* mock_obj,
+                                     internal::CallReaction reaction) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_uninteresting_call_reaction[mock_obj] = reaction;
+}
+
+}  // namespace
+
+// Tells Google Mock to allow uninteresting calls on the given mock
+// object.
+// L < g_gmock_mutex
+void Mock::AllowUninterestingCalls(const void* mock_obj) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::ALLOW);
+}
+
+// Tells Google Mock to warn the user about uninteresting calls on the
+// given mock object.
+// L < g_gmock_mutex
+void Mock::WarnUninterestingCalls(const void* mock_obj) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::WARN);
+}
+
+// Tells Google Mock to fail uninteresting calls on the given mock
+// object.
+// L < g_gmock_mutex
+void Mock::FailUninterestingCalls(const void* mock_obj) {
+  SetReactionOnUninterestingCalls(mock_obj, internal::FAIL);
+}
+
+// Tells Google Mock the given mock object is being destroyed and its
+// entry in the call-reaction table should be removed.
+// L < g_gmock_mutex
+void Mock::UnregisterCallReaction(const void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_uninteresting_call_reaction.erase(mock_obj);
+}
+
+// Returns the reaction Google Mock will have on uninteresting calls
+// made on the given mock object.
+// L < g_gmock_mutex
+internal::CallReaction Mock::GetReactionOnUninterestingCalls(
+    const void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return (g_uninteresting_call_reaction.count(mock_obj) == 0) ?
+      internal::WARN : g_uninteresting_call_reaction[mock_obj];
+}
+
+// Tells Google Mock to ignore mock_obj when checking for leaked mock
+// objects.
+// L < g_gmock_mutex
+void Mock::AllowLeak(const void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].leakable = true;
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+// L < g_gmock_mutex
+bool Mock::VerifyAndClearExpectations(void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies all expectations on the given mock object and clears its
+// default actions and expectations.  Returns true iff the
+// verification was successful.
+// L < g_gmock_mutex
+bool Mock::VerifyAndClear(void* mock_obj) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  ClearDefaultActionsLocked(mock_obj);
+  return VerifyAndClearExpectationsLocked(mock_obj);
+}
+
+// Verifies and clears all expectations on the given mock object.  If
+// the expectations aren't satisfied, generates one or more Google
+// Test non-fatal failures and returns false.
+// L >= g_gmock_mutex
+bool Mock::VerifyAndClearExpectationsLocked(void* mock_obj) {
+  internal::g_gmock_mutex.AssertHeld();
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No EXPECT_CALL() was set on the given mock object.
+    return true;
+  }
+
+  // Verifies and clears the expectations on each mock method in the
+  // given mock object.
+  bool expectations_met = true;
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    if (!(*it)->VerifyAndClearExpectationsLocked()) {
+      expectations_met = false;
+    }
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by ClearDefaultActionsLocked().
+  return expectations_met;
+}
+
+// Registers a mock object and a mock method it owns.
+// L < g_gmock_mutex
+void Mock::Register(const void* mock_obj,
+                    internal::UntypedFunctionMockerBase* mocker) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  g_mock_object_registry.states()[mock_obj].function_mockers.insert(mocker);
+}
+
+// Tells Google Mock where in the source code mock_obj is used in an
+// ON_CALL or EXPECT_CALL.  In case mock_obj is leaked, this
+// information helps the user identify which object it is.
+// L < g_gmock_mutex
+void Mock::RegisterUseByOnCallOrExpectCall(
+    const void* mock_obj, const char* file, int line) {
+  internal::MutexLock l(&internal::g_gmock_mutex);
+  MockObjectState& state = g_mock_object_registry.states()[mock_obj];
+  if (state.first_used_file == NULL) {
+    state.first_used_file = file;
+    state.first_used_line = line;
+    const TestInfo* const test_info =
+        UnitTest::GetInstance()->current_test_info();
+    if (test_info != NULL) {
+      // TODO(wan@google.com): record the test case name when the
+      // ON_CALL or EXPECT_CALL is invoked from SetUpTestCase() or
+      // TearDownTestCase().
+      state.first_used_test_case = test_info->test_case_name();
+      state.first_used_test = test_info->name();
+    }
+  }
+}
+
+// Unregisters a mock method; removes the owning mock object from the
+// registry when the last mock method associated with it has been
+// unregistered.  This is called only in the destructor of
+// FunctionMockerBase.
+// L >= g_gmock_mutex
+void Mock::UnregisterLocked(internal::UntypedFunctionMockerBase* mocker) {
+  internal::g_gmock_mutex.AssertHeld();
+  for (MockObjectRegistry::StateMap::iterator it =
+           g_mock_object_registry.states().begin();
+       it != g_mock_object_registry.states().end(); ++it) {
+    FunctionMockers& mockers = it->second.function_mockers;
+    if (mockers.erase(mocker) > 0) {
+      // mocker was in mockers and has been just removed.
+      if (mockers.empty()) {
+        g_mock_object_registry.states().erase(it);
+      }
+      return;
+    }
+  }
+}
+
+// Clears all ON_CALL()s set on the given mock object.
+// L >= g_gmock_mutex
+void Mock::ClearDefaultActionsLocked(void* mock_obj) {
+  internal::g_gmock_mutex.AssertHeld();
+
+  if (g_mock_object_registry.states().count(mock_obj) == 0) {
+    // No ON_CALL() was set on the given mock object.
+    return;
+  }
+
+  // Clears the default actions for each mock method in the given mock
+  // object.
+  FunctionMockers& mockers =
+      g_mock_object_registry.states()[mock_obj].function_mockers;
+  for (FunctionMockers::const_iterator it = mockers.begin();
+       it != mockers.end(); ++it) {
+    (*it)->ClearDefaultActionsLocked();
+  }
+
+  // We don't clear the content of mockers, as they may still be
+  // needed by VerifyAndClearExpectationsLocked().
+}
+
+Expectation::Expectation() {}
+
+Expectation::Expectation(
+    const internal::linked_ptr<internal::ExpectationBase>& an_expectation_base)
+    : expectation_base_(an_expectation_base) {}
+
+Expectation::~Expectation() {}
+
+// Adds an expectation to a sequence.
+void Sequence::AddExpectation(const Expectation& expectation) const {
+  if (*last_expectation_ != expectation) {
+    if (last_expectation_->expectation_base() != NULL) {
+      expectation.expectation_base()->immediate_prerequisites_
+          += *last_expectation_;
+    }
+    *last_expectation_ = expectation;
+  }
+}
+
+// Creates the implicit sequence if there isn't one.
+InSequence::InSequence() {
+  if (internal::g_gmock_implicit_sequence.get() == NULL) {
+    internal::g_gmock_implicit_sequence.set(new Sequence);
+    sequence_created_ = true;
+  } else {
+    sequence_created_ = false;
+  }
+}
+
+// Deletes the implicit sequence if it was created by the constructor
+// of this object.
+InSequence::~InSequence() {
+  if (sequence_created_) {
+    delete internal::g_gmock_implicit_sequence.get();
+    internal::g_gmock_implicit_sequence.set(NULL);
+  }
+}
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock.cc	(revision 11817)
@@ -0,0 +1,182 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gmock/gmock.h"
+#include "gmock/internal/gmock-port.h"
+
+namespace testing {
+
+// TODO(wan@google.com): support using environment variables to
+// control the flag values, like what Google Test does.
+
+GMOCK_DEFINE_bool_(catch_leaked_mocks, true,
+                   "true iff Google Mock should report leaked mock objects "
+                   "as failures.");
+
+GMOCK_DEFINE_string_(verbose, internal::kWarningVerbosity,
+                     "Controls how verbose Google Mock's output is."
+                     "  Valid values:\n"
+                     "  info    - prints all messages.\n"
+                     "  warning - prints warnings and errors.\n"
+                     "  error   - prints errors only.");
+
+namespace internal {
+
+// Parses a string as a command line flag.  The string should have the
+// format "--gmock_flag=value".  When def_optional is true, the
+// "=value" part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+static const char* ParseGoogleMockFlagValue(const char* str,
+                                            const char* flag,
+                                            bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--gmock_".
+  const String flag_str = String::Format("--gmock_%s", flag);
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a Google Mock bool flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseGoogleMockBoolFlag(const char* str, const char* flag,
+                                    bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for a Google Mock string flag, in the form of
+// "--gmock_flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+static bool ParseGoogleMockStringFlag(const char* str, const char* flag,
+                                      String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseGoogleMockFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// The internal implementation of InitGoogleMock().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleMockImpl(int* argc, CharType** argv) {
+  // Makes sure Google Test is initialized.  InitGoogleTest() is
+  // idempotent, so it's fine if the user has already called it.
+  InitGoogleTest(argc, argv);
+  if (*argc <= 0) return;
+
+  for (int i = 1; i != *argc; i++) {
+    const String arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    // Do we see a Google Mock flag?
+    if (ParseGoogleMockBoolFlag(arg, "catch_leaked_mocks",
+                                &GMOCK_FLAG(catch_leaked_mocks)) ||
+        ParseGoogleMockStringFlag(arg, "verbose", &GMOCK_FLAG(verbose))) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    }
+  }
+}
+
+}  // namespace internal
+
+// Initializes Google Mock.  This must be called before running the
+// tests.  In particular, it parses a command line for the flags that
+// Google Mock recognizes.  Whenever a Google Mock flag is seen, it is
+// removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Mock flag variables are
+// updated.
+//
+// Since Google Test is needed for Google Mock to work, this function
+// also initializes Google Test and parses its flags, if that hasn't
+// been done.
+void InitGoogleMock(int* argc, char** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleMock(int* argc, wchar_t** argv) {
+  internal::InitGoogleMockImpl(argc, argv);
+}
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gmock/src/gmock_main.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gmock/src/gmock_main.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gmock/src/gmock_main.cc	(revision 11817)
@@ -0,0 +1,54 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include <iostream>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+// MS C++ compiler/linker has a bug on Windows (not on Windows CE), which
+// causes a link error when _tmain is defined in a static library and UNICODE
+// is enabled. For this reason instead of _tmain, main function is used on
+// Windows. See the following link to track the current status of this bug:
+// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=394464  // NOLINT
+#if GTEST_OS_WINDOWS_MOBILE
+# include <tchar.h>  // NOLINT
+
+int _tmain(int argc, TCHAR** argv) {
+#else
+int main(int argc, char** argv) {
+#endif  // GTEST_OS_WINDOWS_MOBILE
+  std::cout << "Running main() from gmock_main.cc\n";
+  // Since Google Mock depends on Google Test, InitGoogleMock() is
+  // also responsible for initializing Google Test.  Therefore there's
+  // no need for calling testing::InitGoogleTest() separately.
+  testing::InitGoogleMock(&argc, argv);
+  return RUN_ALL_TESTS();
+}
Index: /code/branches/RacingBots_FS18/src/external/gtest/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,39 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(GTEST_FILES
+    src/gtest-all.cc
+    include/gtest/gtest.h
+)
+
+INCLUDE_DIRECTORIES(
+    .
+    include
+)
+
+ORXONOX_ADD_LIBRARY(gtest_orxonox
+    ORXONOX_EXTERNAL
+    VERSION         1.6.0
+    EXCLUDE_FROM_ALL
+    NO_INSTALL
+    LINK_LIBS_UNIX  pthread
+    SOURCE_FILES    ${GTEST_FILES}
+)
+
+SET(GTEST_MAIN "${CMAKE_CURRENT_SOURCE_DIR}/src/gtest_main.cc" CACHE INTERNAL "gtest main() function")
Index: /code/branches/RacingBots_FS18/src/external/gtest/CONTRIBUTORS
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/CONTRIBUTORS	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/CONTRIBUTORS	(revision 11817)
@@ -0,0 +1,37 @@
+# This file contains a list of people who've made non-trivial
+# contribution to the Google C++ Testing Framework project.  People
+# who commit code to the project are encouraged to add their names
+# here.  Please keep the list sorted by first names.
+
+Ajay Joshi <jaj@google.com>
+Balázs Dán <balazs.dan@gmail.com>
+Bharat Mediratta <bharat@menalto.com>
+Chandler Carruth <chandlerc@google.com>
+Chris Prince <cprince@google.com>
+Chris Taylor <taylorc@google.com>
+Dan Egnor <egnor@google.com>
+Eric Roman <eroman@chromium.org>
+Hady Zalek <hady.zalek@gmail.com>
+Jeffrey Yasskin <jyasskin@google.com>
+Jói Sigurðsson <joi@google.com>
+Keir Mierle <mierle@gmail.com>
+Keith Ray <keith.ray@gmail.com>
+Kenton Varda <kenton@google.com>
+Manuel Klimek <klimek@google.com>
+Markus Heule <markus.heule@gmail.com>
+Mika Raento <mikie@iki.fi>
+Miklós Fazekas <mfazekas@szemafor.com>
+Pasi Valminen <pasi.valminen@gmail.com>
+Patrick Hanna <phanna@google.com>
+Patrick Riley <pfr@google.com>
+Peter Kaminski <piotrk@google.com>
+Preston Jackson <preston.a.jackson@gmail.com>
+Rainer Klaffenboeck <rainer.klaffenboeck@dynatrace.com>
+Russ Cox <rsc@google.com>
+Russ Rufer <russ@pentad.com>
+Sean Mcafee <eefacm@gmail.com>
+Sigurður Ásgeirsson <siggi@google.com>
+Tracy Bialik <tracy@pentad.com>
+Vadim Berman <vadimb@google.com>
+Vlad Losev <vladl@google.com>
+Zhanyong Wan <wan@google.com>
Index: /code/branches/RacingBots_FS18/src/external/gtest/COPYING
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/COPYING	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/COPYING	(revision 11817)
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: /code/branches/RacingBots_FS18/src/external/gtest/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/README	(revision 11817)
@@ -0,0 +1,424 @@
+Google C++ Testing Framework
+============================
+
+http://code.google.com/p/googletest/
+
+Overview
+--------
+
+Google's framework for writing C++ tests on a variety of platforms
+(Linux, Mac OS X, Windows, Windows CE, Symbian, etc).  Based on the
+xUnit architecture.  Supports automatic test discovery, a rich set of
+assertions, user-defined assertions, death tests, fatal and non-fatal
+failures, various options for running the tests, and XML test report
+generation.
+
+Please see the project page above for more information as well as the
+mailing list for questions, discussions, and development.  There is
+also an IRC channel on OFTC (irc.oftc.net) #gtest available.  Please
+join us!
+
+Requirements for End Users
+--------------------------
+
+Google Test is designed to have fairly minimal requirements to build
+and use with your projects, but there are some.  Currently, we support
+Linux, Windows, Mac OS X, and Cygwin.  We will also make our best
+effort to support other platforms (e.g. Solaris, AIX, and z/OS).
+However, since core members of the Google Test project have no access
+to these platforms, Google Test may have outstanding issues there.  If
+you notice any problems on your platform, please notify
+googletestframework@googlegroups.com.  Patches for fixing them are
+even more welcome!
+
+### Linux Requirements ###
+
+These are the base requirements to build and use Google Test from a source
+package (as described below):
+  * GNU-compatible Make or gmake
+  * POSIX-standard shell
+  * POSIX(-2) Regular Expressions (regex.h)
+  * A C++98-standard-compliant compiler
+
+### Windows Requirements ###
+
+  * Microsoft Visual C++ 7.1 or newer
+
+### Cygwin Requirements ###
+
+  * Cygwin 1.5.25-14 or newer
+
+### Mac OS X Requirements ###
+
+  * Mac OS X 10.4 Tiger or newer
+  * Developer Tools Installed
+
+Also, you'll need CMake 2.6.4 or higher if you want to build the
+samples using the provided CMake script, regardless of the platform.
+
+Requirements for Contributors
+-----------------------------
+
+We welcome patches.  If you plan to contribute a patch, you need to
+build Google Test and its own tests from an SVN checkout (described
+below), which has further requirements:
+
+  * Python version 2.3 or newer (for running some of the tests and
+    re-generating certain source files from templates)
+  * CMake 2.6.4 or newer
+
+Getting the Source
+------------------
+
+There are two primary ways of getting Google Test's source code: you
+can download a stable source release in your preferred archive format,
+or directly check out the source from our Subversion (SVN) repositary.
+The SVN checkout requires a few extra steps and some extra software
+packages on your system, but lets you track the latest development and
+make patches much more easily, so we highly encourage it.
+
+### Source Package ###
+
+Google Test is released in versioned source packages which can be
+downloaded from the download page [1].  Several different archive
+formats are provided, but the only difference is the tools used to
+manipulate them, and the size of the resulting file.  Download
+whichever you are most comfortable with.
+
+  [1] http://code.google.com/p/googletest/downloads/list
+
+Once the package is downloaded, expand it using whichever tools you
+prefer for that type.  This will result in a new directory with the
+name "gtest-X.Y.Z" which contains all of the source code.  Here are
+some examples on Linux:
+
+  tar -xvzf gtest-X.Y.Z.tar.gz
+  tar -xvjf gtest-X.Y.Z.tar.bz2
+  unzip gtest-X.Y.Z.zip
+
+### SVN Checkout ###
+
+To check out the main branch (also known as the "trunk") of Google
+Test, run the following Subversion command:
+
+  svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
+
+Setting up the Build
+--------------------
+
+To build Google Test and your tests that use it, you need to tell your
+build system where to find its headers and source files.  The exact
+way to do it depends on which build system you use, and is usually
+straightforward.
+
+### Generic Build Instructions ###
+
+Suppose you put Google Test in directory ${GTEST_DIR}.  To build it,
+create a library build target (or a project as called by Visual Studio
+and Xcode) to compile
+
+  ${GTEST_DIR}/src/gtest-all.cc
+
+with
+
+  ${GTEST_DIR}/include and ${GTEST_DIR}
+
+in the header search path.  Assuming a Linux-like system and gcc,
+something like the following will do:
+
+  g++ -I${GTEST_DIR}/include -I${GTEST_DIR} -c ${GTEST_DIR}/src/gtest-all.cc
+  ar -rv libgtest.a gtest-all.o
+
+Next, you should compile your test source file with
+${GTEST_DIR}/include in the header search path, and link it with gtest
+and any other necessary libraries:
+
+  g++ -I${GTEST_DIR}/include path/to/your_test.cc libgtest.a -o your_test
+
+As an example, the make/ directory contains a Makefile that you can
+use to build Google Test on systems where GNU make is available
+(e.g. Linux, Mac OS X, and Cygwin).  It doesn't try to build Google
+Test's own tests.  Instead, it just builds the Google Test library and
+a sample test.  You can use it as a starting point for your own build
+script.
+
+If the default settings are correct for your environment, the
+following commands should succeed:
+
+  cd ${GTEST_DIR}/make
+  make
+  ./sample1_unittest
+
+If you see errors, try to tweak the contents of make/Makefile to make
+them go away.  There are instructions in make/Makefile on how to do
+it.
+
+### Using CMake ###
+
+Google Test comes with a CMake build script (CMakeLists.txt) that can
+be used on a wide range of platforms ("C" stands for cross-platofrm.).
+If you don't have CMake installed already, you can download it for
+free from http://www.cmake.org/.
+
+CMake works by generating native makefiles or build projects that can
+be used in the compiler environment of your choice.  The typical
+workflow starts with:
+
+  mkdir mybuild       # Create a directory to hold the build output.
+  cd mybuild
+  cmake ${GTEST_DIR}  # Generate native build scripts.
+
+If you want to build Google Test's samples, you should replace the
+last command with
+
+  cmake -Dgtest_build_samples=ON ${GTEST_DIR}
+
+If you are on a *nix system, you should now see a Makefile in the
+current directory.  Just type 'make' to build gtest.
+
+If you use Windows and have Vistual Studio installed, a gtest.sln file
+and several .vcproj files will be created.  You can then build them
+using Visual Studio.
+
+On Mac OS X with Xcode installed, a .xcodeproj file will be generated.
+
+### Legacy Build Scripts ###
+
+Before settling on CMake, we have been providing hand-maintained build
+projects/scripts for Visual Studio, Xcode, and Autotools.  While we
+continue to provide them for convenience, they are not actively
+maintained any more.  We highly recommend that you follow the
+instructions in the previous two sections to integrate Google Test
+with your existing build system.
+
+If you still need to use the legacy build scripts, here's how:
+
+The msvc\ folder contains two solutions with Visual C++ projects.
+Open the gtest.sln or gtest-md.sln file using Visual Studio, and you
+are ready to build Google Test the same way you build any Visual
+Studio project.  Files that have names ending with -md use DLL
+versions of Microsoft runtime libraries (the /MD or the /MDd compiler
+option).  Files without that suffix use static versions of the runtime
+libraries (the /MT or the /MTd option).  Please note that one must use
+the same option to compile both gtest and the test code.  If you use
+Visual Studio 2005 or above, we recommend the -md version as /MD is
+the default for new projects in these versions of Visual Studio.
+
+On Mac OS X, open the gtest.xcodeproj in the xcode/ folder using
+Xcode.  Build the "gtest" target.  The universal binary framework will
+end up in your selected build directory (selected in the Xcode
+"Preferences..." -> "Building" pane and defaults to xcode/build).
+Alternatively, at the command line, enter:
+
+  xcodebuild
+
+This will build the "Release" configuration of gtest.framework in your
+default build location.  See the "xcodebuild" man page for more
+information about building different configurations and building in
+different locations.
+
+Tweaking Google Test
+--------------------
+
+Google Test can be used in diverse environments.  The default
+configuration may not work (or may not work well) out of the box in
+some environments.  However, you can easily tweak Google Test by
+defining control macros on the compiler command line.  Generally,
+these macros are named like GTEST_XYZ and you define them to either 1
+or 0 to enable or disable a certain feature.
+
+We list the most frequently used macros below.  For a complete list,
+see file include/gtest/internal/gtest-port.h.
+
+### Choosing a TR1 Tuple Library ###
+
+Some Google Test features require the C++ Technical Report 1 (TR1)
+tuple library, which is not yet available with all compilers.  The
+good news is that Google Test implements a subset of TR1 tuple that's
+enough for its own need, and will automatically use this when the
+compiler doesn't provide TR1 tuple.
+
+Usually you don't need to care about which tuple library Google Test
+uses.  However, if your project already uses TR1 tuple, you need to
+tell Google Test to use the same TR1 tuple library the rest of your
+project uses, or the two tuple implementations will clash.  To do
+that, add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=0
+
+to the compiler flags while compiling Google Test and your tests.  If
+you want to force Google Test to use its own tuple library, just add
+
+  -DGTEST_USE_OWN_TR1_TUPLE=1
+
+to the compiler flags instead.
+
+If you don't want Google Test to use tuple at all, add
+
+  -DGTEST_HAS_TR1_TUPLE=0
+
+and all features using tuple will be disabled.
+
+### Multi-threaded Tests ###
+
+Google Test is thread-safe where the pthread library is available.
+After #include "gtest/gtest.h", you can check the GTEST_IS_THREADSAFE
+macro to see whether this is the case (yes if the macro is #defined to
+1, no if it's undefined.).
+
+If Google Test doesn't correctly detect whether pthread is available
+in your environment, you can force it with
+
+  -DGTEST_HAS_PTHREAD=1
+
+or
+
+  -DGTEST_HAS_PTHREAD=0
+
+When Google Test uses pthread, you may need to add flags to your
+compiler and/or linker to select the pthread library, or you'll get
+link errors.  If you use the CMake script or the deprecated Autotools
+script, this is taken care of for you.  If you use your own build
+script, you'll need to read your compiler and linker's manual to
+figure out what flags to add.
+
+### As a Shared Library (DLL) ###
+
+Google Test is compact, so most users can build and link it as a
+static library for the simplicity.  You can choose to use Google Test
+as a shared library (known as a DLL on Windows) if you prefer.
+
+To compile *gtest* as a shared library, add
+
+  -DGTEST_CREATE_SHARED_LIBRARY=1
+
+to the compiler flags.  You'll also need to tell the linker to produce
+a shared library instead - consult your linker's manual for how to do
+it.
+
+To compile your *tests* that use the gtest shared library, add
+
+  -DGTEST_LINKED_AS_SHARED_LIBRARY=1
+
+to the compiler flags.
+
+Note: while the above steps aren't technically necessary today when
+using some compilers (e.g. GCC), they may become necessary in the
+future, if we decide to improve the speed of loading the library (see
+http://gcc.gnu.org/wiki/Visibility for details).  Therefore you are
+recommended to always add the above flags when using Google Test as a
+shared library.  Otherwise a future release of Google Test may break
+your build script.
+
+### Avoiding Macro Name Clashes ###
+
+In C++, macros don't obey namespaces.  Therefore two libraries that
+both define a macro of the same name will clash if you #include both
+definitions.  In case a Google Test macro clashes with another
+library, you can force Google Test to rename its macro to avoid the
+conflict.
+
+Specifically, if both Google Test and some other code define macro
+FOO, you can add
+
+  -DGTEST_DONT_DEFINE_FOO=1
+
+to the compiler flags to tell Google Test to change the macro's name
+from FOO to GTEST_FOO.  Currently FOO can be FAIL, SUCCEED, or TEST.
+For example, with -DGTEST_DONT_DEFINE_TEST=1, you'll need to write
+
+  GTEST_TEST(SomeTest, DoesThis) { ... }
+
+instead of
+
+  TEST(SomeTest, DoesThis) { ... }
+
+in order to define a test.
+
+Upgrating from an Earlier Version
+---------------------------------
+
+We strive to keep Google Test releases backward compatible.
+Sometimes, though, we have to make some breaking changes for the
+users' long-term benefits.  This section describes what you'll need to
+do if you are upgrading from an earlier version of Google Test.
+
+### Upgrading from 1.3.0 or Earlier ###
+
+You may need to explicitly enable or disable Google Test's own TR1
+tuple library.  See the instructions in section "Choosing a TR1 Tuple
+Library".
+
+### Upgrading from 1.4.0 or Earlier ###
+
+The Autotools build script (configure + make) is no longer officially
+supportted.  You are encouraged to migrate to your own build system or
+use CMake.  If you still need to use Autotools, you can find
+instructions in the README file from Google Test 1.4.0.
+
+On platforms where the pthread library is available, Google Test uses
+it in order to be thread-safe.  See the "Multi-threaded Tests" section
+for what this means to your build script.
+
+If you use Microsoft Visual C++ 7.1 with exceptions disabled, Google
+Test will no longer compile.  This should affect very few people, as a
+large portion of STL (including <string>) doesn't compile in this mode
+anyway.  We decided to stop supporting it in order to greatly simplify
+Google Test's implementation.
+
+Developing Google Test
+----------------------
+
+This section discusses how to make your own changes to Google Test.
+
+### Testing Google Test Itself ###
+
+To make sure your changes work as intended and don't break existing
+functionality, you'll want to compile and run Google Test's own tests.
+For that you can use CMake:
+
+  mkdir mybuild
+  cd mybuild
+  cmake -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Make sure you have Python installed, as some of Google Test's tests
+are written in Python.  If the cmake command complains about not being
+able to find Python ("Could NOT find PythonInterp (missing:
+PYTHON_EXECUTABLE)"), try telling it explicitly where your Python
+executable can be found:
+
+  cmake -DPYTHON_EXECUTABLE=path/to/python -Dgtest_build_tests=ON ${GTEST_DIR}
+
+Next, you can build Google Test and all of its own tests.  On *nix,
+this is usually done by 'make'.  To run the tests, do
+
+  make test
+
+All tests should pass.
+
+### Regenerating Source Files ###
+
+Some of Google Test's source files are generated from templates (not
+in the C++ sense) using a script.  A template file is named FOO.pump,
+where FOO is the name of the file it will generate.  For example, the
+file include/gtest/internal/gtest-type-util.h.pump is used to generate
+gtest-type-util.h in the same directory.
+
+Normally you don't need to worry about regenerating the source files,
+unless you need to modify them.  In that case, you should modify the
+corresponding .pump files instead and run the pump.py Python script to
+regenerate them.  You can find pump.py in the scripts/ directory.
+Read the Pump manual [2] for how to use it.
+
+  [2] http://code.google.com/p/googletest/wiki/PumpManual
+
+### Contributing a Patch ###
+
+We welcome patches.  Please read the Google Test developer's guide [3]
+for how you can contribute.  In particular, make sure you have signed
+the Contributor License Agreement, or we won't be able to accept the
+patch.
+
+  [3] http://code.google.com/p/googletest/wiki/GoogleTestDevGuide
+
+Happy testing!
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-death-test.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-death-test.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-death-test.h	(revision 11817)
@@ -0,0 +1,283 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+#include "gtest/internal/gtest-death-test-internal.h"
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//         << "Failed to die on request " << i);
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  bool operator()(int exit_status) const;
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ExitedWithCode& other);
+
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  do { statement; } while (::testing::internal::AlwaysFalse())
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  do { statement; } while (::testing::internal::AlwaysFalse())
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-message.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-message.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-message.h	(revision 11817)
@@ -0,0 +1,230 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  // We allocate the stringstream separately because otherwise each use of
+  // ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+  // stack frame leading to huge stack frames in some cases; gcc does not reuse
+  // the stack space.
+  Message() : ss_(new ::std::stringstream) {
+    // By default, we want there to be enough precision when printing
+    // a double to a Message.
+    *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+  }
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+#if GTEST_OS_SYMBIAN
+  // Streams a value (either a pointer or not) to this object.
+  template <typename T>
+  inline Message& operator <<(const T& value) {
+    StreamHelper(typename internal::is_pointer<T>::type(), value);
+    return *this;
+  }
+#else
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    ::GTestStreamToHelper(ss_.get(), val);
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      ::GTestStreamToHelper(ss_.get(), pointer);
+    }
+    return *this;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str) {
+    return *this << internal::String::ShowWideCString(wide_c_str);
+  }
+  Message& operator <<(wchar_t* wide_c_str) {
+    return *this << internal::String::ShowWideCString(wide_c_str);
+  }
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::wstring& wstr);
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+  // Gets the text streamed to this object so far as a String.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::String GetString() const {
+    return internal::StringStreamToString(ss_.get());
+  }
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+  // These are needed as the Nokia Symbian Compiler cannot decide between
+  // const T& and const T* in a function template. The Nokia compiler _can_
+  // decide between class template specializations for T and T*, so a
+  // tr1::type_traits-like is_pointer works, and we can overload on that.
+  template <typename T>
+  inline void StreamHelper(internal::true_type /*dummy*/, T* pointer) {
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      ::GTestStreamToHelper(ss_.get(), pointer);
+    }
+  }
+  template <typename T>
+  inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
+    ::GTestStreamToHelper(ss_.get(), value);
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // We'll hold the text streamed to this object here.
+  const internal::scoped_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-param-test.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-param-test.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-param-test.h	(revision 11817)
@@ -0,0 +1,1421 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-param-util-generated.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+  return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+  return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+  return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5) {
+  return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6) {
+  return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7) {
+  return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+      v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+  return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+      v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+  return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+  return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+    T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11) {
+  return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+      T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+    T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12) {
+  return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+    T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13) {
+  return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+  return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+  return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16) {
+  return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17) {
+  return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18) {
+  return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+  return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+  return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+  return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22) {
+  return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23) {
+  return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24) {
+  return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+  return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+    T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26) {
+  return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+    T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27) {
+  return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+    T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28) {
+  return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29) {
+  return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+  return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+  return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32) {
+  return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33) {
+  return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34) {
+  return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+  return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+  return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37) {
+  return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38) {
+  return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+      v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38, T39 v39) {
+  return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+      v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+    T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+    T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+  return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+      v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+    T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+  return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+      v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+    T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42) {
+  return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+      v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+    T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43) {
+  return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+      v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43, T44 v44) {
+  return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+      v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+    T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+    T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+  return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+      v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+  return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+  return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+    T48 v48) {
+  return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+      v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+    T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+    T47 v47, T48 v48, T49 v49) {
+  return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+      v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+    T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+    T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+  return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+      v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple(bool, bool)> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+    const Generator1& g1, const Generator2& g2) {
+  return internal::CartesianProductHolder2<Generator1, Generator2>(
+      g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+  return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+      g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+    Generator4> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4) {
+  return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+      Generator4>(
+      g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+    Generator4, Generator5> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5) {
+  return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+      Generator4, Generator5>(
+      g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+  return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6>(
+      g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7) {
+  return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7>(
+      g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8) {
+  return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8>(
+      g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8,
+    Generator9> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+  return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9,
+    typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+    Generator10> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9,
+        const Generator10& g10) {
+  return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+      Generator10>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-printers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-printers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-printers.h	(revision 11817)
@@ -0,0 +1,796 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice.  DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+  kProtobuf,              // a protobuf type
+  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
+                          // (e.g. a named or unnamed enum type)
+  kOtherType              // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+  // This default version is called when kTypeKind is kOtherType.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+                         sizeof(value), os);
+  }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const ::testing::internal::string short_str = value.ShortDebugString();
+    const ::testing::internal::string pretty_str =
+        short_str.length() <= kProtobufOneLinerMaxLength ?
+        short_str : ("\n" + value.DebugString());
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const internal::BiggestInt kBigInt = value;
+    *os << kBigInt;
+  }
+};
+
+// Prints the given value to the given ostream.  If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed.  This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream.  If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+  TypeWithoutFormatter<T,
+      (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+       internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+       kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+  return os;
+}
+
+}  // namespace internal2
+}  // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+  // With the following statement, during unqualified name lookup,
+  // testing::internal2::operator<< appears as if it was declared in
+  // the nearest enclosing namespace that contains both
+  // ::testing_internal and ::testing::internal2, i.e. the global
+  // namespace.  For more details, refer to the C++ Standard section
+  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
+  // testing::internal2::operator<< in case T doesn't come with a <<
+  // operator.
+  //
+  // We cannot write 'using ::testing::internal2::operator<<;', which
+  // gcc 3.3 fails to compile due to a compiler bug.
+  using namespace ::testing::internal2;  // NOLINT
+
+  // Assuming T is defined in namespace foo, in the next statement,
+  // the compiler will consider all of:
+  //
+  //   1. foo::operator<< (thanks to Koenig look-up),
+  //   2. ::operator<< (as the current namespace is enclosed in ::),
+  //   3. testing::internal2::operator<< (thanks to the using statement above).
+  //
+  // The operator<< whose type matches T best will be picked.
+  //
+  // We deliberately allow #2 to be a candidate, as sometimes it's
+  // impossible to define #1 (e.g. when foo is ::std, defining
+  // anything in it is undefined behavior unless you are a compiler
+  // vendor.).
+  *os << value;
+}
+
+}  // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
+  const size_t kMaxCount = 32;  // The maximum number of elements to print.
+  *os << '{';
+  size_t count = 0;
+  for (typename C::const_iterator it = container.begin();
+       it != container.end(); ++it, ++count) {
+    if (count > 0) {
+      *os << ',';
+      if (count == kMaxCount) {  // Enough has been printed.
+        *os << " ...";
+        break;
+      }
+    }
+    *os << ' ';
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
+  }
+
+  if (count > 0) {
+    *os << ' ';
+  }
+  *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // C++ doesn't allow casting from a function pointer to any object
+    // pointer.
+    //
+    // IsTrue() silences warnings: "Condition is always true",
+    // "unreachable code".
+    if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.  However, we cannot cast it to const void* directly,
+      // even using reinterpret_cast, as earlier versions of gcc
+      // (e.g. 3.4.5) cannot compile the cast when p is a function
+      // pointer.  Casting to UInt64 first solves the problem.
+      *os << reinterpret_cast<const void*>(
+          reinterpret_cast<internal::UInt64>(p));
+    }
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
+  ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
+  //
+  // Note that we check for container types here, prior to we check
+  // for protocol message types in our operator<<.  The rationale is:
+  //
+  // For protocol messages, we want to give people a chance to
+  // override Google Mock's format by defining a PrintTo() or
+  // operator<<.  For STL containers, other formats can be
+  // incompatible with Google Mock's format for the container
+  // elements; therefore we check for container types here to ensure
+  // that our format is used.
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple.  Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities.  We support
+// tuples of up-to 10 fields.  The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+    const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+    ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    // TODO(wan@google.com): let the user control the threshold using a flag.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(const char* begin,
+                                    size_t len,
+                                    ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalPrint(value, os);
+}
+inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
+  if (str == NULL) {
+    *os << "NULL";
+  } else {
+    UniversalPrint(string(str), os);
+  }
+}
+inline void UniversalTersePrint(char* str, ::std::ostream* os) {
+  UniversalTersePrint(static_cast<const char*>(str), os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  UniversalPrinter<T>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields.  The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+  // Prints the first N fields of a tuple.
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+    *os << ", ";
+    UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+        ::Print(::std::tr1::get<N - 1>(t), os);
+  }
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+        Print(::std::tr1::get<0>(t), os);
+  }
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+  *os << "(";
+  TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+      PrintPrefixTo(t, os);
+  *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+      TersePrintPrefixToStrings(value, &result);
+  return result;
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrint(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-spi.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-spi.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-spi.h	(revision 11817)
@@ -0,0 +1,232 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include "gtest/gtest.h"
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  virtual ~ScopedFakeTestPartResultReporter();
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type,
+                       const string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS,\
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-test-part.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-test-part.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-test-part.h	(revision 11817)
@@ -0,0 +1,176 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure      // Failed and the test should be terminated.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type,
+                 const char* a_file_name,
+                 int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {
+  }
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const { return file_name_.c_str(); }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true iff the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true iff the test part failed.
+  bool failed() const { return type_ != kSuccess; }
+
+  // Returns true iff the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true iff the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static internal::String ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // NULL if the source file is unknown.
+  internal::String file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  internal::String summary_;  // The test failure summary.
+  internal::String message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  virtual ~HasNewFatalFailureHelper();
+  virtual void ReportTestPartResult(const TestPartResult& result);
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-typed-test.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-typed-test.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest-typed-test.h	(revision 11817)
@@ -0,0 +1,259 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  // Since we are inside a derived class template, C++ requires use to
+  // visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif  // 0
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+  typedef ::testing::internal::TypeList< Types >::type \
+      GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+  template <typename gtest_TypeParam_> \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+      : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTest< \
+          CaseName, \
+          ::testing::internal::TemplateSel< \
+              GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+          GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+              "", #CaseName, #TestName, 0); \
+  template <typename gtest_TypeParam_> \
+  void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in.  The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+  gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+  gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+  gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+  static ::testing::internal::TypedTestCasePState \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  template <typename gtest_TypeParam_> \
+  class TestName : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+          __FILE__, __LINE__, #CaseName, #TestName); \
+  } \
+  template <typename gtest_TypeParam_> \
+  void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+  } \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+          __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+  bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTestCase<CaseName, \
+          GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+          ::testing::internal::TypeList< Types >::type>::Register(\
+              #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest.h	(revision 11817)
@@ -0,0 +1,2155 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <vector>
+
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const String& message);
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared in gtest-internal.h but defined here, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  explicit AssertionResult(bool success) : success_(success) {}
+
+  // Returns true iff the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != NULL ?  message_->c_str() : "";
+  }
+  // TODO(vladl@google.com): Remove this after making sure no clients use it.
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == NULL)
+      message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  internal::scoped_ptr< ::std::string> message_;
+
+  GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { ... }
+//     virtual void TearDown() { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // Defines types for pointers to functions that set up and tear down
+  // a test case.
+  typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+  typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::SetUpTestCase() before running the first
+  // test in test case Foo.  Hence a sub-class can define its own
+  // SetUpTestCase() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestCase() {}
+
+  // Tears down the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::TearDownTestCase() after running the last
+  // test in test case Foo.  Hence a sub-class can define its own
+  // TearDownTestCase() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestCase() {}
+
+  // Returns true iff the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true iff the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true iff the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test.  Only the last value for a given
+  // key is remembered.
+  // These are public static so they can be called from utility functions
+  // that are not members of the test fixture.
+  // The arguments are const char* instead strings, as Google Test is used
+  // on platforms where string doesn't compile.
+  //
+  // Note that a driving consideration for these RecordProperty methods
+  // was to produce xml output suited to the Greenspan charting utility,
+  // which at present will only chart values that fit in a 32-bit int. It
+  // is the user's responsibility to restrict their values to 32-bit ints
+  // if they intend them to be used with Greenspan.
+  static void RecordProperty(const char* key, const char* value);
+  static void RecordProperty(const char* key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true iff the current test has the same fixture class as
+  // the first test in the current test case.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  // Uses a GTestFlagSaver to save and restore all Google Test flags.
+  const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+  // Often a user mis-spells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if a user declares void Setup() in his test
+  //   fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if a user calls it from his test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const char* a_key, const char* a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const char* new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  internal::String key_;
+  // The value supplied by the user.
+  internal::String value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true iff the test passed (i.e. no test part failed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test failed.
+  bool Failed() const;
+
+  // Returns true iff the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true iff the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test part result among all the results. i can range
+  // from 0 to test_property_count() - 1. If i is not in that range, aborts
+  // the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.
+  void RecordProperty(const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testcase tags.  Returns true if the property is valid.
+  // TODO(russr): Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properites_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test case name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test case name.
+  const char* test_case_name() const { return test_case_name_.c_str(); }
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != NULL)
+      return value_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if this test should run, that is if the test is not disabled
+  // (or it is disabled but the also_run_disabled_tests flag has been specified)
+  // and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test case Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestCase;
+  friend class internal::UnitTestImpl;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_case_name, const char* name,
+      const char* type_param,
+      const char* value_param,
+      internal::TypeId fixture_class_id,
+      Test::SetUpTestCaseFunc set_up_tc,
+      Test::TearDownTestCaseFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const char* test_case_name, const char* name,
+           const char* a_type_param,
+           const char* a_value_param,
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_case_name_;     // Test case name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const internal::scoped_ptr<const ::std::string> value_param_;
+  const internal::TypeId fixture_class_id_;   // ID of the test fixture class
+  bool should_run_;                 // True iff this test should run
+  bool is_disabled_;                // True iff this test is disabled
+  bool matches_filter_;             // True if this test matches the
+                                    // user-specified filter.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+  // Creates a TestCase with the given name.
+  //
+  // TestCase does NOT have a default constructor.  Always use this
+  // constructor to create a TestCase object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test case
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  TestCase(const char* name, const char* a_type_param,
+           Test::SetUpTestCaseFunc set_up_tc,
+           Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Destructor of TestCase.
+  virtual ~TestCase();
+
+  // Gets the name of the TestCase.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test case.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if any test in this test case should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test case.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests in this test case.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests in this test case.
+  int disabled_test_count() const;
+
+  // Get the number of tests in this test case that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test case.
+  int total_test_count() const;
+
+  // Returns true iff the test case passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test case failed.
+  bool Failed() const { return failed_test_count() > 0; }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestCase.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestCase.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test case.  Will delete the TestInfo upon
+  // destruction of the TestCase object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test case.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test case.
+  static void ClearTestCaseResult(TestCase* test_case) {
+    test_case->ClearResult();
+  }
+
+  // Runs every test in this TestCase.
+  void Run();
+
+  // Runs SetUpTestCase() for this TestCase.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestCase().
+  void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+  // Runs TearDownTestCase() for this TestCase.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestCase().
+  void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+  // Returns true iff test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true iff test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true iff test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test case.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test case.
+  internal::String name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test case.
+  Test::SetUpTestCaseFunc set_up_tc_;
+  // Pointer to the function that tears down the test case.
+  Test::TearDownTestCaseFunc tear_down_tc_;
+  // True iff any test in this test case should run.
+  bool should_run_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestCases.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {}
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {}
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestCase;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestCase object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestCase* current_test_case() const;
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const;
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns the ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry();
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const;
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const internal::String& message,
+                         const internal::String& os_stack_trace);
+
+  // Adds a TestProperty to the current TestResult object. If the result already
+  // contains a property with the same key, the value will be updated.
+  void RecordPropertyForCurrentTest(const char* key, const char* value);
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and funcions are friends as they need to access private
+  // members of UnitTest.
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::ScopedTrace;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const internal::String& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace();
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char*, and print it as a C string when it is compared against an
+// std::string object, for example.
+//
+// The default implementation ignores the type of the other operand.
+// Some specialized versions are used to handle formatting wide or
+// narrow C strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+String FormatForComparisonFailureMessage(const T1& value,
+                                         const T2& /* other_operand */) {
+  // C++Builder compiles this incorrectly if the namespace isn't explicitly
+  // given.
+  return ::testing::PrintToString(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            const T1& expected,
+                            const T2& actual) {
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4389)  // Temporarily disables warning on
+                               // signed/unsigned mismatch.
+#endif
+
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)          // Restores the warning state.
+#endif
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+                                       const char* actual_expression,
+                                       BiggestInt expected,
+                                       BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ.  The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal.  The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <typename T1, typename T2>
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 const T1& expected,
+                                 const T2& actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 BiggestInt expected,
+                                 BiggestInt actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+  // We define two overloaded versions of Compare().  The first
+  // version will be picked when the second argument to ASSERT_EQ() is
+  // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+  // EXPECT_EQ(false, a_bool).
+  template <typename T1, typename T2>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      const T1& expected,
+      const T2& actual,
+      // The following line prevents this overload from being considered if T2
+      // is not a pointer type.  We need this because ASSERT_EQ(NULL, my_ptr)
+      // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+      // to match the Secret* in the other overload, which would otherwise make
+      // this template match better.
+      typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // This version will be picked when the second argument to ASSERT_EQ() is a
+  // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+  template <typename T>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      // We used to have a second template parameter instead of Secret*.  That
+      // template parameter would deduce to 'long', making this a better match
+      // than the first overload even without the first overload's EnableIf.
+      // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+      // non-pointer argument" (even a deduced integral argument), so the old
+      // implementation caused warnings in user code.
+      Secret* /* expected (NULL) */,
+      T* actual) {
+    // We already know that 'expected' is a null pointer.
+    return CmpHelperEQ(expected_expression, actual_expression,
+                       static_cast<T*>(NULL), actual);
+  }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+    const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, < );
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, > );
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const char* expected,
+                                          const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                              const char* actual_expression,
+                                              const char* expected,
+                                              const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const wchar_t* expected,
+                                          const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+                                         const char* actual_expression,
+                                         RawType expected,
+                                         RawType actual) {
+  const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream expected_ss;
+  expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+              << expected;
+
+  ::std::stringstream actual_ss;
+  actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+            << actual;
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   StringStreamToString(&expected_ss),
+                   StringStreamToString(&actual_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char*        const file;
+    int                const line;
+    String             const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual ~FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void SetUp() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void TearDown {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor. This member function is non-static, even though it only
+  // references static data, to reduce the opportunity for incorrect uses
+  // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+  // uses a fixture whose parameter type is int.
+  const ParamType& GetParam() const { return *parameter_; }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+//
+// Examples:
+//
+//   EXPECT_TRUE(server.StatusIsOK());
+//   ASSERT_FALSE(server.HasPendingRequest(port))
+//       << "There are still pending requests " << "on port " << port;
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+#include "gtest/gtest_pred_impl.h"
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+//    * {ASSERT|EXPECT}_NE(v1, v2):           Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2):           Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2):           Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2):           Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2):           Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+//   {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(5, Foo());
+//   EXPECT_EQ(NULL, a_pointer);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define EXPECT_NE(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C String Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+  ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+  (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test".  For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+  GTEST_TEST_(test_case_name, test_name, \
+              ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+// Use this macro in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+
+#define RUN_ALL_TESTS()\
+  (::testing::UnitTest::GetInstance()->Run())
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest_pred_impl.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest_pred_impl.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest_pred_impl.h	(revision 11817)
@@ -0,0 +1,358 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ", "
+                            << e5 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4
+                            << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5),\
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest_prod.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest_prod.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/gtest_prod.h	(revision 11817)
@@ -0,0 +1,58 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void MyMethod();
+//   FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+//   // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-death-test-internal.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-death-test-internal.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-death-test-internal.h	(revision 11817)
@@ -0,0 +1,308 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, const RE* regex,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const String& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static String last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    const ::testing::internal::RE& gtest_regex = (regex); \
+    ::testing::internal::DeathTest* gtest_dt; \
+    if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+        __FILE__, __LINE__, &gtest_dt)) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+    } \
+    if (gtest_dt != NULL) { \
+      ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+          gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) { \
+        case ::testing::internal::DeathTest::OVERSEE_TEST: \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+          } \
+          break; \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+          ::testing::internal::DeathTest::ReturnSentinel \
+              gtest_sentinel(gtest_dt); \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+          break; \
+        } \
+        default: \
+          break; \
+      } \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+      fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const String& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  String file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  String file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter iff EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-filepath.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-filepath.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-filepath.h	(revision 11817)
@@ -0,0 +1,210 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const char* pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  explicit FilePath(const String& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  String ToString() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true iff the path is NULL or "".
+  bool IsEmpty() const { return c_str() == NULL || *c_str() == '\0'; }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  String pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-internal.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-internal.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-internal.h	(revision 11817)
@@ -0,0 +1,1226 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#include <ctype.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+// Google Test defines the testing::Message class to allow construction of
+// test messages via the << operator.  The idea is that anything
+// streamable to std::ostream can be streamed to a testing::Message.
+// This allows a user to use his own types in Google Test assertions by
+// overloading the << operator.
+//
+// util/gtl/stl_logging-inl.h overloads << for STL containers.  These
+// overloads cannot be defined in the std namespace, as that will be
+// undefined behavior.  Therefore, they are defined in the global
+// namespace instead.
+//
+// C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+// overloads are visible in either the std namespace or the global
+// namespace, but not other namespaces, including the testing
+// namespace which Google Test's Message class is in.
+//
+// To allow STL containers (and other types that has a << operator
+// defined in the global namespace) to be used in Google Test assertions,
+// testing::Message must access the custom << operator from the global
+// namespace.  Hence this helper function.
+//
+// Note: Jeffrey Yasskin suggested an alternative fix by "using
+// ::operator<<;" in the definition of Message's operator<<.  That fix
+// doesn't require a helper function, but unfortunately doesn't
+// compile with MSVC.
+template <typename T>
+inline void GTestStreamToHelper(std::ostream* os, const T& val) {
+  *os << val;
+}
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class ScopedTrace;                     // Implements scoped trace.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant).  Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler.  These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise.  Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal.  Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];  // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+    (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif  // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ String AppendUserMessage(const String& gtest_msg,
+                                    const Message& user_msg);
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+  ScopedTrace(const char* file, int line, const Message& message);
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+// The Symbian compiler has a bug that prevents it from selecting the
+// correct overload of FormatForComparisonFailureMessage (see below)
+// unless we pass the first argument by reference.  If we do that,
+// however, Visual Age C++ 10.1 generates a compiler error.  Therefore
+// we only apply the work-around for Symbian.
+#if defined(__SYMBIAN32__)
+# define GTEST_CREF_WORKAROUND_ const&
+#else
+# define GTEST_CREF_WORKAROUND_
+#endif
+
+// When this operand is a const char* or char*, if the other operand
+// is a ::std::string or ::string, we print this operand as a C string
+// rather than a pointer (we do the same for wide strings); otherwise
+// we print it as a pointer to be safe.
+
+// This internal macro is used to avoid duplicated code.
+#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
+inline String FormatForComparisonFailureMessage(\
+    operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+    const operand2_type& /*operand2*/) {\
+  return operand1_printer(str);\
+}\
+inline String FormatForComparisonFailureMessage(\
+    const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+    const operand2_type& /*operand2*/) {\
+  return operand1_printer(str);\
+}
+
+GTEST_FORMAT_IMPL_(::std::string, String::ShowCStringQuoted)
+#if GTEST_HAS_STD_WSTRING
+GTEST_FORMAT_IMPL_(::std::wstring, String::ShowWideCStringQuoted)
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_FORMAT_IMPL_(::string, String::ShowCStringQuoted)
+#endif  // GTEST_HAS_GLOBAL_STRING
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_FORMAT_IMPL_(::wstring, String::ShowWideCStringQuoted)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#undef GTEST_FORMAT_IMPL_
+
+// The next four overloads handle the case where the operand being
+// printed is a char/wchar_t pointer and the other operand is not a
+// string/wstring object.  In such cases, we just print the operand as
+// a pointer to be safe.
+#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType)                       \
+  template <typename T>                                             \
+  String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \
+                                           const T&) { \
+    return PrintToString(static_cast<const void*>(p));              \
+  }
+
+GTEST_FORMAT_CHAR_PTR_IMPL_(char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t)
+
+#undef GTEST_FORMAT_CHAR_PTR_IMPL_
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const String& expected_value,
+                                     const String& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ String GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
+  static const size_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true iff this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true iff this number is at most kMaxUlps ULP's away from
+  // rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param        the name of the test's type parameter, or NULL if
+//                     this is not  a typed or a type-parameterized test.
+//   value_param       text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name, const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+  TypedTestCasePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test case hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr, "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    defined_test_names_.insert(test_name);
+    return true;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(
+      const char* file, int line, const char* registered_tests);
+
+ private:
+  bool registered_;
+  ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == NULL) {
+    return NULL;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline String GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == NULL ? String(str) : String(str, comma - str);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names, int index) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
+                       case_name, index).c_str(),
+        GetPrefixUntilComma(test_names).c_str(),
+        GetTypeName<Type>().c_str(),
+        NULL,  // No value parameter.
+        GetTypeId<FixtureClass>(),
+        TestClass::SetUpTestCase,
+        TestClass::TearDownTestCase,
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+        ::Register(prefix, case_name, test_names, index + 1);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/, int /*index*/) {
+    return true;
+  }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names) {
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, case_name, test_names, 0);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+        ::Register(prefix, case_name, SkipComma(test_names));
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/) {
+    return true;
+  }
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ String GetCurrentOsStackTraceExceptTop(UnitTest* unit_test,
+                                                  int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const UInt32 kMaxRange = 1u << 31;
+
+  explicit Random(UInt32 seed) : state_(seed) {}
+
+  void Reseed(UInt32 seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  UInt32 Generate(UInt32 range);
+
+ private:
+  UInt32 state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; };  // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+    typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged.  This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; };  // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'.  The following specialization works around the bug.
+// However, it causes trouble with GCC and thus needs to be
+// conditionally compiled.
+#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+    typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+    GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+    typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary.  For example,
+// it transforms
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> const char&
+//   const char&  ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+    GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+  // We need the following helper functions only for their types.
+  // They have no implementations.
+
+  // MakeFrom() is an expression whose type is From.  We cannot simply
+  // use From(), as the type From may not have a public default
+  // constructor.
+  static From MakeFrom();
+
+  // These two functions are overloaded.  Given an expression
+  // Helper(x), the compiler will pick the first version if x can be
+  // implicitly converted to type To; otherwise it will pick the
+  // second version.
+  //
+  // The first version returns a value of size 1, and the second
+  // version returns a value of size 2.  Therefore, by checking the
+  // size of Helper(x), which can be done at compile time, we can tell
+  // which version of Helper() is used, and hence whether x can be
+  // implicitly converted to type To.
+  static char Helper(To);
+  static char (&Helper(...))[2];  // NOLINT
+
+  // We have to put the 'public' section after the 'private' section,
+  // or MSVC refuses to compile the code.
+ public:
+  // MSVC warns about implicitly converting from double to int for
+  // possible loss of data, so we need to temporarily disable the
+  // warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4244)  // Temporarily disables warning 4244.
+
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop)           // Restores the warning state.
+#elif defined(__BORLANDC__)
+  // C++Builder cannot use member overload resolution during template
+  // instantiation.  The simplest workaround is to use its C++0x type traits
+  // functions (C++Builder 2009 and above only).
+  static const bool value = __is_convertible(From, To);
+#else
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif  // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+    : public bool_constant<
+  ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+  ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator.  The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+                            typename C::iterator* /* it */ = NULL,
+                            typename C::const_iterator* /* const_it */ = NULL) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false.  To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };  // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+  kReference,  // The NativeArray references the native array.
+  kCopy        // The NativeArray makes a copy of the native array and
+               // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array.
+  NativeArray(const Element* array, size_t count, RelationToSource relation) {
+    Init(array, count, relation);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+  }
+
+  ~NativeArray() {
+    // Ensures that the user doesn't instantiate NativeArray with a
+    // const or reference type.
+    static_cast<void>(StaticAssertTypeEqHelper<Element,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+    if (relation_to_source_ == kCopy)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  // Initializes this object; makes a copy of the input array if
+  // 'relation' is kCopy.
+  void Init(const Element* array, size_t a_size, RelationToSource relation) {
+    if (relation == kReference) {
+      array_ = array;
+    } else {
+      Element* const copy = new Element[a_size];
+      CopyArray(array, a_size, copy);
+      array_ = copy;
+    }
+    size_ = a_size;
+    relation_to_source_ = relation;
+  }
+
+  const Element* array_;
+  size_t size_;
+  RelationToSource relation_to_source_;
+
+  GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+    bool gtest_caught_expected = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (expected_exception const&) { \
+      gtest_caught_expected = true; \
+    } \
+    catch (...) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws a different type."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+    if (!gtest_caught_expected) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws nothing."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+      fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail("Expected: " #statement " doesn't throw an exception.\n" \
+           "  Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+  virtual void TestBody();\
+  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+  ::test_info_ =\
+    ::testing::internal::MakeAndRegisterTestInfo(\
+        #test_case_name, #test_name, NULL, NULL, \
+        (parent_id), \
+        parent_class::SetUpTestCase, \
+        parent_class::TearDownTestCase, \
+        new ::testing::internal::TestFactoryImpl<\
+            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-linked_ptr.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-linked_ptr.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-linked_ptr.h	(revision 11817)
@@ -0,0 +1,233 @@
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking.  Every pointer to a
+// particular object is kept on a circular linked list.  When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+//   object is traversed.  This class is therefore NOT SUITABLE when there
+//   will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+//   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+//   will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+//   Unlike other linked_ptr implementations, in this implementation
+//   a linked_ptr object is thread-safe in the sense that:
+//     - it's safe to copy linked_ptr objects concurrently,
+//     - it's safe to copy *from* a linked_ptr and read its underlying
+//       raw pointer (e.g. via get()) concurrently, and
+//     - it's safe to write to two linked_ptrs that point to the same
+//       shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>.  It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+  // Create a new circle that includes only this instance.
+  void join_new() {
+    next_ = this;
+  }
+
+  // Many linked_ptr operations may change p.link_ for some linked_ptr
+  // variable p in the same circle as this object.  Therefore we need
+  // to prevent two such operations from occurring concurrently.
+  //
+  // Note that different types of linked_ptr objects can coexist in a
+  // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+  // linked_ptr<Derived2>).  Therefore we must use a single mutex to
+  // protect all linked_ptr objects.  This can create serious
+  // contention in production code, but is acceptable in a testing
+  // framework.
+
+  // Join an existing circle.
+  // L < g_linked_ptr_mutex
+  void join(linked_ptr_internal const* ptr) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    linked_ptr_internal const* p = ptr;
+    while (p->next_ != ptr) p = p->next_;
+    p->next_ = this;
+    next_ = ptr;
+  }
+
+  // Leave whatever circle we're part of.  Returns true if we were the
+  // last member of the circle.  Once this is done, you can join() another.
+  // L < g_linked_ptr_mutex
+  bool depart() {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    if (next_ == this) return true;
+    linked_ptr_internal const* p = next_;
+    while (p->next_ != this) p = p->next_;
+    p->next_ = next_;
+    return false;
+  }
+
+ private:
+  mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+  typedef T element_type;
+
+  // Take over ownership of a raw pointer.  This should happen as soon as
+  // possible after the object is created.
+  explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+  ~linked_ptr() { depart(); }
+
+  // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+  template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+  linked_ptr(linked_ptr const& ptr) {  // NOLINT
+    assert(&ptr != this);
+    copy(&ptr);
+  }
+
+  // Assignment releases the old value and acquires the new.
+  template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+    depart();
+    copy(&ptr);
+    return *this;
+  }
+
+  linked_ptr& operator=(linked_ptr const& ptr) {
+    if (&ptr != this) {
+      depart();
+      copy(&ptr);
+    }
+    return *this;
+  }
+
+  // Smart pointer members.
+  void reset(T* ptr = NULL) {
+    depart();
+    capture(ptr);
+  }
+  T* get() const { return value_; }
+  T* operator->() const { return value_; }
+  T& operator*() const { return *value_; }
+
+  bool operator==(T* p) const { return value_ == p; }
+  bool operator!=(T* p) const { return value_ != p; }
+  template <typename U>
+  bool operator==(linked_ptr<U> const& ptr) const {
+    return value_ == ptr.get();
+  }
+  template <typename U>
+  bool operator!=(linked_ptr<U> const& ptr) const {
+    return value_ != ptr.get();
+  }
+
+ private:
+  template <typename U>
+  friend class linked_ptr;
+
+  T* value_;
+  linked_ptr_internal link_;
+
+  void depart() {
+    if (link_.depart()) delete value_;
+  }
+
+  void capture(T* ptr) {
+    value_ = ptr;
+    link_.join_new();
+  }
+
+  template <typename U> void copy(linked_ptr<U> const* ptr) {
+    value_ = ptr->get();
+    if (value_)
+      link_.join(&ptr->link_);
+    else
+      link_.join_new();
+  }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+  return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+  return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+  return linked_ptr<T>(ptr);
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-param-util-generated.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-param-util-generated.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-param-util-generated.h	(revision 11817)
@@ -0,0 +1,4822 @@
+// This file was GENERATED by command:
+//     pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+  ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray2& other);
+
+  const T1 v1_;
+  const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+  ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray3& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+  ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray4& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+  ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray5& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ValueArray6 {
+ public:
+  ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray6& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ValueArray7 {
+ public:
+  ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray7& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+  ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+      T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray8& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+  ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+      T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray9& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+  ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray10& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+class ValueArray11 {
+ public:
+  ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray11& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+class ValueArray12 {
+ public:
+  ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray12& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+  ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray13& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+  ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray14& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+  ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray15& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+class ValueArray16 {
+ public:
+  ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray16& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+class ValueArray17 {
+ public:
+  ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+      T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray17& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+  ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray18& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+  ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray19& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+  ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray20& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+class ValueArray21 {
+ public:
+  ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray21& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+class ValueArray22 {
+ public:
+  ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray22& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+  ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_,
+        v23_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray23& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+  ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray24& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+  ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+      T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray25& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+class ValueArray26 {
+ public:
+  ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray26& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+class ValueArray27 {
+ public:
+  ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray27& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+  ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray28& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+  ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray29& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+  ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray30& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+class ValueArray31 {
+ public:
+  ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray31& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+class ValueArray32 {
+ public:
+  ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray32& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+  ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+      T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray33& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+  ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray34& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+  ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_,
+        v35_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray35& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+class ValueArray36 {
+ public:
+  ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray36& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+class ValueArray37 {
+ public:
+  ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray37& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+  ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray38& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+  ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray39& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+  ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray40& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+class ValueArray41 {
+ public:
+  ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+      T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray41& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+class ValueArray42 {
+ public:
+  ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray42& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+  ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+      v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray43& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+  ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+      v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+      v43_(v43), v44_(v44) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray44& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+  ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+      v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray45& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+class ValueArray46 {
+ public:
+  ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray46& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+class ValueArray47 {
+ public:
+  ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+      v47_(v47) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_,
+        v47_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray47& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+  ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+      v46_(v46), v47_(v47), v48_(v48) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray48& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+  ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+      T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_, v49_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray49& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+  ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+      T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {v1_, v2_, v3_, v4_, v5_, v6_, v7_, v8_, v9_, v10_, v11_,
+        v12_, v13_, v14_, v15_, v16_, v17_, v18_, v19_, v20_, v21_, v22_, v23_,
+        v24_, v25_, v26_, v27_, v28_, v29_, v30_, v31_, v32_, v33_, v34_, v35_,
+        v36_, v37_, v38_, v39_, v40_, v41_, v42_, v43_, v44_, v45_, v46_, v47_,
+        v48_, v49_, v50_};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray50& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+  const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+  CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2)
+      : g1_(g1), g2_(g2) {}
+  virtual ~CartesianProductGenerator2() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current2_;
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator2::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator2& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+};  // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+  CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  virtual ~CartesianProductGenerator3() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current3_;
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator3::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator3& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+};  // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+  CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  virtual ~CartesianProductGenerator4() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current4_;
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator4::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator4& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+};  // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+  CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  virtual ~CartesianProductGenerator5() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current5_;
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator5::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator5& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+};  // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class CartesianProductGenerator6
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+        T6> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+  CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  virtual ~CartesianProductGenerator6() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current6_;
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator6::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator6& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+};  // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class CartesianProductGenerator7
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+  CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  virtual ~CartesianProductGenerator7() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current7_;
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator7::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator7& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+};  // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+  CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  virtual ~CartesianProductGenerator8() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current8_;
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator8::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator8& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+};  // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+  CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  virtual ~CartesianProductGenerator9() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current9_;
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator9::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator9& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+};  // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9, T10> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+  CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+      const ParamGenerator<T10>& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  virtual ~CartesianProductGenerator10() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9,
+      const ParamGenerator<T10>& g10,
+      const typename ParamGenerator<T10>::iterator& current10)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+          begin10_(g10.begin()), end10_(g10.end()), current10_(current10)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current10_;
+      if (current10_ == end10_) {
+        current10_ = begin10_;
+        ++current9_;
+      }
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_ &&
+          current10_ == typed_other->current10_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_),
+        begin10_(other.begin10_),
+        end10_(other.end10_),
+        current10_(other.current10_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_, *current10_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_ ||
+          current10_ == end10_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    const typename ParamGenerator<T10>::iterator begin10_;
+    const typename ParamGenerator<T10>::iterator end10_;
+    typename ParamGenerator<T10>::iterator current10_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator10::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator10& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+  const ParamGenerator<T10> g10_;
+};  // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+      : g1_(g1), g2_(g2) {}
+  template <typename T1, typename T2>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+        new CartesianProductGenerator2<T1, T2>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder2& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+};  // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  template <typename T1, typename T2, typename T3>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+        new CartesianProductGenerator3<T1, T2, T3>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder3& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+};  // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  template <typename T1, typename T2, typename T3, typename T4>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+        new CartesianProductGenerator4<T1, T2, T3, T4>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder4& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+};  // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+        new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder5& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+};  // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+        new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder6& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+};  // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+      T7> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+        new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder7& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+};  // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+      T8> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+        new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder8& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+};  // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9> >(
+        new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder9& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+};  // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9, const Generator10& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9, typename T10>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9, T10> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9, T10> >(
+        new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+            T10>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_),
+        static_cast<ParamGenerator<T10> >(g10_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder10& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+  const Generator10 g10_;
+};  // class CartesianProductHolder10
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-param-util.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-param-util.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-param-util.h	(revision 11817)
@@ -0,0 +1,619 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+                                          const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  virtual ~RangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      value_ = value_ + step_;
+      index_++;
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const T* Current() const { return &value_; }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = i + step)
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  virtual ~ValuesInIteratorRangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, container_.begin());
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      ++iterator_;
+      value_.reset();
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    virtual const T* Current() const {
+      if (value_.get() == NULL)
+        value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of scoped_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable scoped_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  virtual Test* CreateTest() {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+  typedef typename TestCase::ParamType ParamType;
+
+  TestMetaFactory() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+    return new ParameterizedTestFactory<TestCase>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+  virtual ~ParameterizedTestCaseInfoBase() {}
+
+  // Base part of test case name for display purposes.
+  virtual const string& GetTestCaseName() const = 0;
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test case right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestCaseInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestCaseInstantiation().
+  typedef typename TestCase::ParamType ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+  explicit ParameterizedTestCaseInfo(const char* name)
+      : test_case_name_(name) {}
+
+  // Test case base name for display purposes.
+  virtual const string& GetTestCaseName() const { return test_case_name_; }
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_case_name is the base name of the test case (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test case base name and DoBar is test base name.
+  void AddTestPattern(const char* test_case_name,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory) {
+    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+                                                       test_base_name,
+                                                       meta_factory)));
+  }
+  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestCaseInstantiation(const string& instantiation_name,
+                               GeneratorCreationFunc* func,
+                               const char* /* file */,
+                               int /* line */) {
+    instantiations_.push_back(::std::make_pair(instantiation_name, func));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test case
+  // test cases right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more then once.
+  virtual void RegisterTests() {
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      linked_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const string& instantiation_name = gen_it->first;
+        ParamGenerator<ParamType> generator((*gen_it->second)());
+
+        Message test_case_name_stream;
+        if ( !instantiation_name.empty() )
+          test_case_name_stream << instantiation_name << "/";
+        test_case_name_stream << test_info->test_case_base_name;
+
+        int i = 0;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          Message test_name_stream;
+          test_name_stream << test_info->test_base_name << "/" << i;
+          MakeAndRegisterTestInfo(
+              test_case_name_stream.GetString().c_str(),
+              test_name_stream.GetString().c_str(),
+              NULL,  // No type parameter.
+              PrintToString(*param_it).c_str(),
+              GetTestCaseTypeId(),
+              TestCase::SetUpTestCase,
+              TestCase::TearDownTestCase,
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_case_base_name,
+             const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+        test_case_base_name(a_test_case_base_name),
+        test_base_name(a_test_base_name),
+        test_meta_factory(a_test_meta_factory) {}
+
+    const string test_case_base_name;
+    const string test_base_name;
+    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+  };
+  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+  // Keeps pairs of <Instantiation name, Sequence generator creation function>
+  // received from INSTANTIATE_TEST_CASE_P macros.
+  typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
+      InstantiationContainer;
+
+  const string test_case_name_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+};  // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+  ParameterizedTestCaseRegistry() {}
+  ~ParameterizedTestCaseRegistry() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test case.
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name,
+      const char* file,
+      int line) {
+    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      if ((*it)->GetTestCaseName() == test_case_name) {
+        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test case setup and tear-down in this case.
+          ReportInvalidTestCaseType(test_case_name,  file, line);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestCaseInfo<TestCase> >(*it);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == NULL) {
+      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+      test_case_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      (*it)->RegisterTests();
+    }
+  }
+
+ private:
+  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+  TestCaseInfoContainer test_case_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-port.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-port.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-port.h	(revision 11817)
@@ -0,0 +1,1775 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior.  If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::string, which is different to std::string).
+//   GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::wstring, which is different to std::wstring).
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_TR1_TUPLE      - Define it to 1/0 to indicate tr1::tuple
+//                              is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_USE_OWN_TR1_TUPLE  - Define it to 1/0 to indicate whether Google
+//                              Test's own tr1 tuple implementation should be
+//                              used.  Unused when the user sets
+//                              GTEST_HAS_TR1_TUPLE to 0.
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_SYMBIAN  - Symbian
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+//   GTEST_HAS_COMBINE      - the Combine() function (for value-parameterized
+//                            tests)
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_PARAM_TEST   - value-parameterized tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above two are mutually exclusive.
+//   GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                  - synchronization primitives.
+//   GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+//                         synchronization primitives have real implementations
+//                         and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+//   is_pointer     - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//   IteratorTraits - partial implementation of std::iterator_traits, which
+//                    is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+//   scoped_ptr     - as in TR2.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like
+//                    platforms, or a reduced regular exception syntax on
+//                    other platforms, including Windows.
+//
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   Int32, UInt32, Int64, UInt64, TimeInMillis
+//                  - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_FLAG()       - references a flag.
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetArgvs()         - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an Int32 environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#include <iostream>  // NOLINT
+#include <sstream>  // NOLINT
+#include <string>  // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# ifdef ANDROID
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif  // ANDROID
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#endif  // __CYGWIN__
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# if !GTEST_OS_NACL
+// TODO(vladl@google.com): Remove this condition when Native Client SDK adds
+// strings.h (tracked in
+// http://code.google.com/p/nativeclient/issues/detail?id=1175).
+#  include <strings.h>  // Native Client doesn't provide strings.h.
+# endif
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+#endif
+
+#if GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_HAS_POSIX_RE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif  // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
+//   is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+    (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+    (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#  ifdef _CPPRTTI  // MSVC defines this macro iff RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#  ifdef __GXX_RTTI
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines whether Google Test can use tr1/tuple.  You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+// The user didn't tell us not to do it, so we assume it's OK.
+# define GTEST_HAS_TR1_TUPLE 1
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already.  At this time, GCC 4.0.0+ and MSVC
+// 2010 are the only mainstream compilers that come with a TR1 tuple
+// implementation.  NVIDIA's CUDA NVCC compiler pretends to be GCC by
+// defining __GNUC__ and friends, but cannot compile GCC's tuple
+// implementation.  MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
+// Feature Pack download, which we cannot assume the user has.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
+    || _MSC_VER >= 1600
+#  define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+#  define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif  // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+# if GTEST_USE_OWN_TR1_TUPLE
+#  include "gtest/internal/gtest-tuple.h"
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+#  ifdef BOOST_HAS_TR1_TUPLE
+#   undef BOOST_HAS_TR1_TUPLE
+#  endif  // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+#  define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+#  include <tuple>
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header.  This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+#  if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled.  _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>.  Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+#   define _TR1_FUNCTIONAL 1
+#   include <tr1/tuple>
+#   undef _TR1_FUNCTIONAL  // Allows the user to #include
+                        // <tr1/functional> if he chooses to.
+#  else
+#   include <tr1/tuple>  // NOLINT
+#  endif  // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+#  include <tuple>  // NOLINT
+# endif  // GTEST_USE_OWN_TR1_TUPLE
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  define GTEST_HAS_CLONE 1
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+     GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector>  // NOLINT
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now.  Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled.  The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+    (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#else
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+  void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+  type(type const &);\
+  GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif  // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+class String;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                         content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+  typedef ::testing::internal::CompileAssert<(bool(expr))> \
+      msg[bool(expr) ? 1 : -1]
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//    #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+//                                      // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+  ~scoped_ptr() { reset(); }
+
+  T& operator*() const { return *ptr_; }
+  T* operator->() const { return ptr_; }
+  T* get() const { return ptr_; }
+
+  T* release() {
+    T* const ptr = ptr_;
+    ptr_ = NULL;
+    return ptr;
+  }
+
+  void reset(T* p = NULL) {
+    if (p != ptr_) {
+      if (IsTrue(sizeof(T) > 0)) {  // Makes sure T is a complete type.
+        delete ptr_;
+      }
+      ptr_ = p;
+    }
+  }
+ private:
+  T* ptr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  RE(const ::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true iff regular expression re matches
+  // the entire str.
+  // PartialMatch(str, re) returns true iff regular expression re
+  // matches a substring of str (including str itself).
+  //
+  // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+  // when str contains NUL characters.
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const ::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+
+  // We use a const char* instead of a string, as Google Test may be used
+  // where string is not available.  We also do not use Google Test's own
+  // String type here, in order to simplify dependencies between the
+  // files.
+  const char* pattern_;
+  bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+#endif
+
+  GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    const To to = NULL;
+    ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ String GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ String GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+extern ::std::vector<String> g_argvs;
+
+// GTEST_HAS_DEATH_TEST implies we have ::std::string.
+const ::std::vector<String>& GetArgvs();
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds.  This function is only for
+// testing Google Test's own constructs.  Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {}
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() { notified_ = true; }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    while(!notified_) {
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  volatile bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void (*UserThreadFunc)(T);
+
+  ThreadWithParam(
+      UserThreadFunc func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+      finished_ = true;
+    }
+  }
+
+  virtual void Run() {
+    if (thread_can_start_ != NULL)
+      thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  const UserThreadFunc func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true iff we know that the thread function has finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms. They
+// are used in conjunction with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the end
+//                            // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes.  Do not use MutexBase directly.  Instead, write
+// the following to define a static mutex:
+//
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // We don't protect writing to owner_ here, as it's the caller's
+    // responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    owner_ = 0;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(owner_ == pthread_self())
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  pthread_t owner_;  // The thread holding the mutex; 0 means no one holds it.
+};
+
+// Forward-declares a static mutex.
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+    owner_ = 0;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms.  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits.  Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies.  It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : key_(CreateKey()),
+                  default_() {}
+  explicit ThreadLocal(const T& value) : key_(CreateKey()),
+                                         default_(value) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != NULL) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = new ValueHolder(default_);
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  const T default_;  // The default value for each thread.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# define GTEST_IS_THREADSAFE 1
+
+#else  // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+# define GTEST_IS_THREADSAFE 0
+
+#endif  // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio.  The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects.  We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template.  These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+  typedef bool_constant<bool_value> type;
+  static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+  typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+  typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+  typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+#  else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+  return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // We are on Windows CE, which has no environment variables.
+  return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+  return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// The maximum number a BiggestInt can represent.  This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+    ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  // unsigned int has size 4 in both gcc and MSVC.
+  //
+  // As base/basictypes.h doesn't compile on Windows, we cannot use
+  // uint32, uint64, and etc here.
+  typedef int Int;
+  typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+
+#if GTEST_OS_WINDOWS
+  typedef __int64 Int;
+  typedef unsigned __int64 UInt;
+#else
+  typedef long long Int;  // NOLINT
+  typedef unsigned long long UInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::testing::internal::String GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::String GTEST_FLAG(name) = (default_val)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-string.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-string.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-string.h	(revision 11817)
@@ -0,0 +1,350 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include "gtest/internal/gtest-port.h"
+
+#include <string>
+
+namespace testing {
+namespace internal {
+
+// String - a UTF-8 string class.
+//
+// For historic reasons, we don't use std::string.
+//
+// TODO(wan@google.com): replace this class with std::string or
+// implement it in terms of the latter.
+//
+// Note that String can represent both NULL and the empty string,
+// while std::string cannot represent NULL.
+//
+// NULL and the empty string are considered different.  NULL is less
+// than anything (including the empty string) except itself.
+//
+// This class only provides minimum functionality necessary for
+// implementing Google Test.  We do not intend to implement a full-fledged
+// string class here.
+//
+// Since the purpose of this class is to provide a substitute for
+// std::string on platforms where it cannot be used, we define a copy
+// constructor and assignment operators such that we don't need
+// conditional compilation in a lot of places.
+//
+// In order to make the representation efficient, the d'tor of String
+// is not virtual.  Therefore DO NOT INHERIT FROM String.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Returns the input enclosed in double quotes if it's not NULL;
+  // otherwise returns "(null)".  For example, "\"Hello\"" is returned
+  // for input "Hello".
+  //
+  // This is useful for printing a C string in the syntax of a literal.
+  //
+  // Known issue: escape sequences are not handled yet.
+  static String ShowCStringQuoted(const char* c_str);
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true iff they have the same content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static String ShowWideCString(const wchar_t* wide_c_str);
+
+  // Similar to ShowWideCString(), except that this function encloses
+  // the converted string in double quotes.
+  static String ShowWideCStringQuoted(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true iff they have the same
+  // content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Formats a list of arguments to a String, using the same format
+  // spec string as for printf.
+  //
+  // We do not use the StringPrintf class as it is not universally
+  // available.
+  //
+  // The result is limited to 4096 characters (including the tailing
+  // 0).  If 4096 characters are not enough to format the input,
+  // "<buffer exceeded>" is returned.
+  static String Format(const char* format, ...);
+
+  // C'tors
+
+  // The default c'tor constructs a NULL string.
+  String() : c_str_(NULL), length_(0) {}
+
+  // Constructs a String by cloning a 0-terminated C string.
+  String(const char* a_c_str) {  // NOLINT
+    if (a_c_str == NULL) {
+      c_str_ = NULL;
+      length_ = 0;
+    } else {
+      ConstructNonNull(a_c_str, strlen(a_c_str));
+    }
+  }
+
+  // Constructs a String by copying a given number of chars from a
+  // buffer.  E.g. String("hello", 3) creates the string "hel",
+  // String("a\0bcd", 4) creates "a\0bc", String(NULL, 0) creates "",
+  // and String(NULL, 1) results in access violation.
+  String(const char* buffer, size_t a_length) {
+    ConstructNonNull(buffer, a_length);
+  }
+
+  // The copy c'tor creates a new copy of the string.  The two
+  // String objects do not share content.
+  String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
+
+  // D'tor.  String is intended to be a final class, so the d'tor
+  // doesn't need to be virtual.
+  ~String() { delete[] c_str_; }
+
+  // Allows a String to be implicitly converted to an ::std::string or
+  // ::string, and vice versa.  Converting a String containing a NULL
+  // pointer to ::std::string or ::string is undefined behavior.
+  // Converting a ::std::string or ::string containing an embedded NUL
+  // character to a String will result in the prefix up to the first
+  // NUL character.
+  String(const ::std::string& str) {
+    ConstructNonNull(str.c_str(), str.length());
+  }
+
+  operator ::std::string() const { return ::std::string(c_str(), length()); }
+
+#if GTEST_HAS_GLOBAL_STRING
+  String(const ::string& str) {
+    ConstructNonNull(str.c_str(), str.length());
+  }
+
+  operator ::string() const { return ::string(c_str(), length()); }
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  // Returns true iff this is an empty string (i.e. "").
+  bool empty() const { return (c_str() != NULL) && (length() == 0); }
+
+  // Compares this with another String.
+  // Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+  // if this is greater than rhs.
+  int Compare(const String& rhs) const;
+
+  // Returns true iff this String equals the given C string.  A NULL
+  // string and a non-NULL string are considered not equal.
+  bool operator==(const char* a_c_str) const { return Compare(a_c_str) == 0; }
+
+  // Returns true iff this String is less than the given String.  A
+  // NULL string is considered less than "".
+  bool operator<(const String& rhs) const { return Compare(rhs) < 0; }
+
+  // Returns true iff this String doesn't equal the given C string.  A NULL
+  // string and a non-NULL string are considered not equal.
+  bool operator!=(const char* a_c_str) const { return !(*this == a_c_str); }
+
+  // Returns true iff this String ends with the given suffix.  *Any*
+  // String is considered to end with a NULL or empty suffix.
+  bool EndsWith(const char* suffix) const;
+
+  // Returns true iff this String ends with the given suffix, not considering
+  // case. Any String is considered to end with a NULL or empty suffix.
+  bool EndsWithCaseInsensitive(const char* suffix) const;
+
+  // Returns the length of the encapsulated string, or 0 if the
+  // string is NULL.
+  size_t length() const { return length_; }
+
+  // Gets the 0-terminated C string this String object represents.
+  // The String object still owns the string.  Therefore the caller
+  // should NOT delete the return value.
+  const char* c_str() const { return c_str_; }
+
+  // Assigns a C string to this object.  Self-assignment works.
+  const String& operator=(const char* a_c_str) {
+    return *this = String(a_c_str);
+  }
+
+  // Assigns a String object to this object.  Self-assignment works.
+  const String& operator=(const String& rhs) {
+    if (this != &rhs) {
+      delete[] c_str_;
+      if (rhs.c_str() == NULL) {
+        c_str_ = NULL;
+        length_ = 0;
+      } else {
+        ConstructNonNull(rhs.c_str(), rhs.length());
+      }
+    }
+
+    return *this;
+  }
+
+ private:
+  // Constructs a non-NULL String from the given content.  This
+  // function can only be called when c_str_ has not been allocated.
+  // ConstructNonNull(NULL, 0) results in an empty string ("").
+  // ConstructNonNull(NULL, non_zero) is undefined behavior.
+  void ConstructNonNull(const char* buffer, size_t a_length) {
+    char* const str = new char[a_length + 1];
+    memcpy(str, buffer, a_length);
+    str[a_length] = '\0';
+    c_str_ = str;
+    length_ = a_length;
+  }
+
+  const char* c_str_;
+  size_t length_;
+};  // class String
+
+// Streams a String to an ostream.  Each '\0' character in the String
+// is replaced with "\\0".
+inline ::std::ostream& operator<<(::std::ostream& os, const String& str) {
+  if (str.c_str() == NULL) {
+    os << "(null)";
+  } else {
+    const char* const c_str = str.c_str();
+    for (size_t i = 0; i != str.length(); i++) {
+      if (c_str[i] == '\0') {
+        os << "\\0";
+      } else {
+        os << c_str[i];
+      }
+    }
+  }
+  return os;
+}
+
+// Gets the content of the stringstream's buffer as a String.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ String StringStreamToString(::std::stringstream* stream);
+
+// Converts a streamable value to a String.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+
+// Declared here but defined in gtest.h, so that it has access
+// to the definition of the Message class, required by the ARM
+// compiler.
+template <typename T>
+String StreamableToString(const T& streamable);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-tuple.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-tuple.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-tuple.h	(revision 11817)
@@ -0,0 +1,968 @@
+// This file was GENERATED by a script.  DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+    void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+    void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+    void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+    void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+    typename T3 = void, typename T4 = void, typename T5 = void,
+    typename T6 = void, typename T7 = void, typename T8 = void,
+    typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T)> { typedef T0 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T)> { typedef T1 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T)> { typedef T2 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T)> { typedef T3 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T)> { typedef T4 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T)> { typedef T5 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T)> { typedef T6 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T)> { typedef T7 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T)> { typedef T8 type; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T)> { typedef T9 type; };
+
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+  tuple(const tuple& t) : f0_(t.f0_) {}
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    return *this;
+  }
+
+  T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+      f1_(f1) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+      GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_) {}
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_) {}
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+      GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+      f9_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+      f9_(t.f9_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    f9_ = t.f9_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+  T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+  return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+  return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+  return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3) {
+  return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4) {
+  return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5) {
+  return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+  return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+  return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8) {
+  return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8, const T9& f9) {
+  return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T)> { static const int value = 0; };
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T)> { static const int value = 1; };
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T)> { static const int value = 2; };
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T)> { static const int value = 3; };
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T)> { static const int value = 4; };
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T)> { static const int value = 5; };
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T)> { static const int value = 6; };
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T)> { static const int value = 7; };
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T)> { static const int value = 8; };
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T)> { static const int value = 9; };
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T)> { static const int value = 10; };
+
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  Field(Tuple& t) { return t.f0_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  Field(Tuple& t) { return t.f1_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  Field(Tuple& t) { return t.f2_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  Field(Tuple& t) { return t.f3_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  Field(Tuple& t) { return t.f4_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  Field(Tuple& t) { return t.f5_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  Field(Tuple& t) { return t.f6_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  Field(Tuple& t) { return t.f7_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  Field(Tuple& t) { return t.f8_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  Field(Tuple& t) { return t.f9_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  ConstField(const Tuple& t) { return t.f9_; }
+};
+
+}  // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_10_TUPLE_(T)>::value,
+      tuple_size<GTEST_10_TUPLE_(U)>::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-type-util.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-type-util.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/include/gtest/internal/gtest-type-util.h	(revision 11817)
@@ -0,0 +1,3330 @@
+// This file was GENERATED by command:
+//     pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# ifdef __GLIBCXX__
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // __GLIBCXX__
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+String GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if defined(__GLIBCXX__) || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   ifdef __GLIBCXX__
+  using abi::__cxa_demangle;
+#   endif // __GLIBCXX__
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const String name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // __GLIBCXX__ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+  typedef T1 Head;
+  typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+  typedef T1 Head;
+  typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+  typedef T1 Head;
+  typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+  typedef T1 Head;
+  typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types6 {
+  typedef T1 Head;
+  typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types7 {
+  typedef T1 Head;
+  typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types8 {
+  typedef T1 Head;
+  typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+  typedef T1 Head;
+  typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+  typedef T1 Head;
+  typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types11 {
+  typedef T1 Head;
+  typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types12 {
+  typedef T1 Head;
+  typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types13 {
+  typedef T1 Head;
+  typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+  typedef T1 Head;
+  typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+  typedef T1 Head;
+  typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types16 {
+  typedef T1 Head;
+  typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types17 {
+  typedef T1 Head;
+  typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types18 {
+  typedef T1 Head;
+  typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+  typedef T1 Head;
+  typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+  typedef T1 Head;
+  typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types21 {
+  typedef T1 Head;
+  typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types22 {
+  typedef T1 Head;
+  typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types23 {
+  typedef T1 Head;
+  typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+  typedef T1 Head;
+  typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+  typedef T1 Head;
+  typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types26 {
+  typedef T1 Head;
+  typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types27 {
+  typedef T1 Head;
+  typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types28 {
+  typedef T1 Head;
+  typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+  typedef T1 Head;
+  typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+  typedef T1 Head;
+  typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types31 {
+  typedef T1 Head;
+  typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types32 {
+  typedef T1 Head;
+  typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types33 {
+  typedef T1 Head;
+  typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+  typedef T1 Head;
+  typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+  typedef T1 Head;
+  typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types36 {
+  typedef T1 Head;
+  typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types37 {
+  typedef T1 Head;
+  typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types38 {
+  typedef T1 Head;
+  typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+  typedef T1 Head;
+  typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+  typedef T1 Head;
+  typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types41 {
+  typedef T1 Head;
+  typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types42 {
+  typedef T1 Head;
+  typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types43 {
+  typedef T1 Head;
+  typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+  typedef T1 Head;
+  typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+  typedef T1 Head;
+  typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types46 {
+  typedef T1 Head;
+  typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types47 {
+  typedef T1 Head;
+  typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types48 {
+  typedef T1 Head;
+  typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+  typedef T1 Head;
+  typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+  typedef T1 Head;
+  typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+    typename T3 = internal::None, typename T4 = internal::None,
+    typename T5 = internal::None, typename T6 = internal::None,
+    typename T7 = internal::None, typename T8 = internal::None,
+    typename T9 = internal::None, typename T10 = internal::None,
+    typename T11 = internal::None, typename T12 = internal::None,
+    typename T13 = internal::None, typename T14 = internal::None,
+    typename T15 = internal::None, typename T16 = internal::None,
+    typename T17 = internal::None, typename T18 = internal::None,
+    typename T19 = internal::None, typename T20 = internal::None,
+    typename T21 = internal::None, typename T22 = internal::None,
+    typename T23 = internal::None, typename T24 = internal::None,
+    typename T25 = internal::None, typename T26 = internal::None,
+    typename T27 = internal::None, typename T28 = internal::None,
+    typename T29 = internal::None, typename T30 = internal::None,
+    typename T31 = internal::None, typename T32 = internal::None,
+    typename T33 = internal::None, typename T34 = internal::None,
+    typename T35 = internal::None, typename T36 = internal::None,
+    typename T37 = internal::None, typename T38 = internal::None,
+    typename T39 = internal::None, typename T40 = internal::None,
+    typename T41 = internal::None, typename T42 = internal::None,
+    typename T43 = internal::None, typename T44 = internal::None,
+    typename T45 = internal::None, typename T46 = internal::None,
+    typename T47 = internal::None, typename T48 = internal::None,
+    typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+  typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, internal::None, internal::None, internal::None> {
+  typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, internal::None, internal::None> {
+  typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, T49, internal::None> {
+  typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates4 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates7 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates10 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates13 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates16 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates19 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates22 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates25 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates28 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates31 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates34 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates37 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates40 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates43 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates46 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates49 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+    GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+    GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+    GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+    GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+    GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+    GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+    GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+    GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+    GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+    GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+    GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+    GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+    GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+    GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+    GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+    GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+    GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+    GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+    GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+    GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+    GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+    GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+    GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+    GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+  typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, NoneT, NoneT, NoneT> {
+  typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, NoneT, NoneT> {
+  typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, T49, NoneT> {
+  typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList { typedef Types1<T> type; };
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> > {
+  typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-all.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-all.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-all.cc	(revision 11817)
@@ -0,0 +1,48 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+#include "src/gtest.cc"
+#include "src/gtest-death-test.cc"
+#include "src/gtest-filepath.cc"
+#include "src/gtest-port.cc"
+#include "src/gtest-printers.cc"
+#include "src/gtest-test-part.cc"
+#include "src/gtest-typed-test.cc"
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-death-test.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-death-test.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-death-test.cc	(revision 11817)
@@ -0,0 +1,1234 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "colons.  This flag is specified if and only if the current "
+    "process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static String ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static String DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0)
+    msg << "couldn't detect the number of threads.";
+  else
+    msg << "detected " << thread_count << " threads.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const String& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != NULL) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort(::testing::internal::String::Format( \
+          "CHECK failed: File %s, line %d: %s", \
+          __FILE__, __LINE__, #expression)); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort(::testing::internal::String::Format( \
+          "CHECK failed: File %s, line %d: %s != -1", \
+          __FILE__, __LINE__, #expression)); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+String GetLastErrnoDescription() {
+    return String(errno == 0 ? "" : posix::StrError(errno));
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == NULL) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+                       const char* file, int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const String& message) {
+  last_death_test_message_ = message;
+}
+
+String DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, const RE* a_regex)
+      : statement_(a_statement),
+        regex_(a_regex),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason);
+  virtual bool Passed(bool status_ok);
+
+  const char* statement() const { return statement_; }
+  const RE* regex() const { return regex_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // The regular expression which test output must match.  DeathTestImpl
+  // doesn't own this object and should not attempt to delete it.
+  const RE* const regex_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   regex:    A regular expression object to be applied to
+//             the test's captured standard error output; the death test
+//             fails if it does not match.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met.  Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const String error_message = GetCapturedStderr();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+        if (matched) {
+          success = true;
+        } else {
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << regex()->pattern() << "\n"
+                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement,
+                   const RE* a_regex,
+                   const char* file,
+                   int line)
+      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {
+    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,    // The event will automatically reset to non-signaled state.
+      FALSE,   // The initial state is non-signalled.
+      NULL));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+  const String filter_flag = String::Format("--%s%s=%s.%s",
+                                            GTEST_FLAG_PREFIX_, kFilterFlag,
+                                            info->test_case_name(),
+                                            info->name());
+  const String internal_flag = String::Format(
+    "--%s%s=%s|%d|%d|%u|%Iu|%Iu",
+      GTEST_FLAG_PREFIX_,
+      kInternalRunDeathTestFlag,
+      file_, line_,
+      death_test_index,
+      static_cast<unsigned int>(::GetCurrentProcessId()),
+      // size_t has the same with as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      reinterpret_cast<size_t>(write_handle),
+      reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(
+      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+                                            executable_path,
+                                            _MAX_PATH));
+
+  String command_line = String::Format("%s %s \"%s\"",
+                                       ::GetCommandLineA(),
+                                       filter_flag.c_str(),
+                                       internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+      executable_path,
+      const_cast<char*>(command_line.c_str()),
+      NULL,   // Retuned process handle is not inheritable.
+      NULL,   // Retuned thread handle is not inheritable.
+      TRUE,   // Child inherits all inheritable handles (for write_handle_).
+      0x0,    // Default creation flags.
+      NULL,   // Inherit the parent's environment.
+      UnitTest::GetInstance()->original_working_dir(),
+      &startup_info,
+      &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+# else  // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, const RE* regex);
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+    : DeathTestImpl(a_statement, a_regex),
+      child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+      ForkingDeathTest(a_statement, a_regex) { }
+  virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, const RE* a_regex,
+                const char* file, int line) :
+      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+  virtual TestRole AssumeRole();
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() {
+    args_.push_back(NULL);
+  }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_MAC
+inline char** GetEnviron() {
+  // When Google Test is built as a framework on MacOS X, the environ variable
+  // is unavailable. Apple's documentation (man environ) recommends using
+  // _NSGetEnviron() instead.
+  return *_NSGetEnviron();
+}
+#  else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+#  endif  // GTEST_OS_MAC
+
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(String::Format("chdir(\"%s\") failed: %s",
+                                  original_dir,
+                                  GetLastErrnoDescription().c_str()));
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execve() as it's a direct system call.  We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execve() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execve(args->argv[0], args->argv, GetEnviron());
+  DeathTestAbort(String::Format("execve(%s, ...) in %s failed: %s",
+                                args->argv[0],
+                                original_dir,
+                                GetLastErrnoDescription().c_str()));
+  return EXIT_FAILURE;
+}
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
+bool StackLowerThanAddress(const void* ptr) {
+  int dummy;
+  return &dummy < ptr;
+}
+
+bool StackGrowsDown() {
+  int dummy;
+  return StackLowerThanAddress(&dummy);
+}
+
+// A threadsafe implementation of fork(2) for threadsafe-style death tests
+// that uses clone(2).  It dies with an error message if anything goes
+// wrong.
+static pid_t ExecDeathTestFork(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const size_t stack_size = getpagesize();
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+    void* const stack_top =
+        static_cast<char*>(stack) + (stack_grows_down ? stack_size : 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#  else
+  const bool use_fork = true;
+#  endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const String filter_flag =
+      String::Format("--%s%s=%s.%s",
+                     GTEST_FLAG_PREFIX_, kFilterFlag,
+                     info->test_case_name(), info->name());
+  const String internal_flag =
+      String::Format("--%s%s=%s|%d|%d|%d",
+                     GTEST_FLAG_PREFIX_, kInternalRunDeathTestFlag,
+                     file_, line_, death_test_index, pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvs());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestFork(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != NULL) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(String::Format(
+          "Death test count (%d) somehow exceeded expected maximum (%d)",
+          death_test_index, flag->index()));
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = NULL;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, regex, file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, regex, file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, regex);
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(String::Format(
+        "Unknown death test style \"%s\" encountered",
+        GTEST_FLAG(death_test_style).c_str()));
+    return false;
+  }
+
+  return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.  GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+                        ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort(String::Format("Unable to open parent process %u",
+                                  parent_process_id));
+  }
+
+  // TODO(vladl@google.com): Replace the following check with a
+  // compile-time assertion when available.
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort(String::Format(
+        "Unable to duplicate the pipe handle %Iu from the parent process %u",
+        write_handle_as_size_t, parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort(String::Format(
+        "Unable to duplicate the event handle %Iu from the parent process %u",
+        event_handle_as_size_t, parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort(String::Format(
+        "Unable to convert pipe handle %Iu to a file descriptor",
+        write_handle_as_size_t));
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort(String::Format(
+        "Bad --gtest_internal_run_death_test flag: %s",
+        GTEST_FLAG(internal_run_death_test).c_str()));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort(String::Format(
+        "Bad --gtest_internal_run_death_test flag: %s",
+        GTEST_FLAG(internal_run_death_test).c_str()));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-filepath.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-filepath.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-filepath.cc	(revision 11817)
@@ -0,0 +1,380 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
+// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/internal/gtest-string.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE doesn't have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  String dot_extension(String::Format(".%s", extension));
+  if (pathname_.EndsWithCaseInsensitive(dot_extension.c_str())) {
+    return FilePath(String(pathname_.c_str(), pathname_.length() - 4));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != NULL &&
+      (last_sep == NULL || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(String(last_sep + 1)) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  String dir;
+  if (last_sep) {
+    dir = String(c_str(), last_sep + 1 - c_str());
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  String file;
+  if (number == 0) {
+    file = String::Format("%s.%s", base_name.c_str(), extension);
+  } else {
+    file = String::Format("%s_%d.%s", base_name.c_str(), number, extension);
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(String::Format("%s%c%s", dir.c_str(), kPathSeparator,
+                                 relative_path.c_str()));
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat;
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat;
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  // TODO(wan@google.com): on Windows a network share like
+  // \\server\share can be a root directory, although it cannot be the
+  // current directory.  Handle this properly.
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(String(pathname_.c_str(), pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+  if (pathname_.c_str() == NULL) {
+    pathname_ = "";
+    return;
+  }
+  const char* src = pathname_.c_str();
+  char* const dest = new char[pathname_.length() + 1];
+  char* dest_ptr = dest;
+  memset(dest_ptr, 0, pathname_.length() + 1);
+
+  while (*src != '\0') {
+    *dest_ptr = *src;
+    if (!IsPathSeparator(*src)) {
+      src++;
+    } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+      if (*dest_ptr == kAlternatePathSeparator) {
+        *dest_ptr = kPathSeparator;
+      }
+#endif
+      while (IsPathSeparator(*src))
+        src++;
+    }
+    dest_ptr++;
+  }
+  *dest_ptr = '\0';
+  pathname_ = dest;
+  delete[] dest;
+}
+
+}  // namespace internal
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-internal-inl.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-internal-inl.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-internal-inl.h	(revision 11817)
@@ -0,0 +1,1038 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// A user is trying to include this from his code - just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif  // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "gtest/internal/gtest-port.h"
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+#include "gtest/gtest.h"  // NOLINT
+#include "gtest/gtest-spi.h"
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    print_time_ = GTEST_FLAG(print_time);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  String color_;
+  String death_test_style_;
+  bool death_test_use_fork_;
+  String filter_;
+  String internal_run_death_test_;
+  bool list_tests_;
+  String output_;
+  bool print_time_;
+  bool pretty_;
+  internal::Int32 random_seed_;
+  internal::Int32 repeat_;
+  bool shuffle_;
+  internal::Int32 stack_trace_depth_;
+  String stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+GTEST_API_ char* CodePointToUtf8(UInt32 code_point, char* str);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ String WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected = begin + random->Generate(range_width);
+    std::swap((*v)[selected], (*v)[last_in_range]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const char* key)
+      : key_(key) {}
+
+  // Returns true iff the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return String(test_property.key()).Compare(key_) == 0;
+  }
+
+ private:
+  String key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static String GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static String GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true iff the wildcard pattern matches the string.  The
+  // first ':' or '\0' character in pattern marks the end of it.
+  //
+  // This recursive algorithm isn't very efficient, but is clear and
+  // works well enough for matching test names, which are short.
+  static bool PatternMatchesString(const char *pattern, const char *str);
+
+  // Returns true iff the user-specified filter matches the test case
+  // name and the test name.
+  static bool FilterMatchesTest(const String &test_case_name,
+                                const String &test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const String& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as a String.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual String CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() : caller_frame_(NULL) {}
+  virtual String CurrentStackTrace(int max_depth, int skip_count);
+  virtual void UponLeavingGTest();
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  Mutex mutex_;  // protects all internal state
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to CurrentStackTrace() from within the user code.
+  void* caller_frame_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  String message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[i];
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i) {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[index];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as a String.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  String CurrentOsStackTraceExceptTop(int skip_count);
+
+  // Finds and returns a TestCase with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_case_name: name of the test case
+  //   type_param:     the name of the test's type parameter, or NULL if
+  //                   this is not a typed or a type-parameterized test.
+  //   set_up_tc:      pointer to the function that sets up the test case
+  //   tear_down_tc:   pointer to the function that tears down the test case
+  TestCase* GetTestCase(const char* test_case_name,
+                        const char* type_param,
+                        Test::SetUpTestCaseFunc set_up_tc,
+                        Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  //   test_info:    the TestInfo object
+  void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc,
+                   TestInfo* test_info) {
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+
+    GetTestCase(test_info->test_case_name(),
+                test_info->type_param(),
+                set_up_tc,
+                tear_down_tc)->AddTestInfo(test_info);
+  }
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Sets the TestCase object for the test that's currently running.
+  void set_current_test_case(TestCase* a_current_test_case) {
+    current_test_case_ = a_current_test_case;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_cases_, TestCase::ClearTestCaseResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestCase and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestCase* current_test_case() const { return current_test_case_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test cases, and the tests within each test case,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test cases and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestCases in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestCase*> test_cases_;
+
+  // Provides a level of indirection for the test case list to allow
+  // easy shuffling and restoring the test case order.  The i-th
+  // element of this vector is the index of the i-th test case in the
+  // shuffled order.
+  std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Index of the last death test case registered.  Initially -1.
+  int last_death_test_case_;
+
+  // This points to the TestCase for the currently running test.  It
+  // changes as Google Test goes through one test case after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestCase* current_test_case_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True iff PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ String GetLastErrnoDescription();
+
+# if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+  AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+  explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+  ~AutoHandle() { Reset(); }
+
+  HANDLE Get() const { return handle_; }
+  void Reset() { Reset(INVALID_HANDLE_VALUE); }
+  void Reset(HANDLE handle) {
+    if (handle != handle_) {
+      if (handle_ != INVALID_HANDLE_VALUE)
+        ::CloseHandle(handle_);
+      handle_ = handle;
+    }
+  }
+
+ private:
+  HANDLE handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+# endif  // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  // MSVC and C++ Builder define __int64 instead of the standard long long.
+  typedef unsigned __int64 BiggestConvertible;
+  const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+  typedef unsigned long long BiggestConvertible;  // NOLINT
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif  // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  // TODO(vladl@google.com): Convert this to compile time assertion when it is
+  // available.
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const TestProperty& property) {
+    test_result->RecordProperty(property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_SRC_GTEST_INTERNAL_INL_H_
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-port.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-port.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-port.cc	(revision 11817)
@@ -0,0 +1,746 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/internal/gtest-port.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+# include <io.h>
+# include <sys/stat.h>
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification.  Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+String FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == NULL) {
+    // TODO(wan@google.com): fix the source file location in the
+    // assertion failures to match where the regex is used in user
+    // code.
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True iff ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true iff regex matches a prefix of str.  regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true iff regex matches any substring of str.  regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == NULL || str == NULL)
+    return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = NULL;
+  if (regex != NULL) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const char* const file_name = file == NULL ? kUnknownFile : file;
+
+  if (line < 0) {
+    return String::Format("%s:", file_name).c_str();
+  }
+#ifdef _MSC_VER
+  return String::Format("%s(%d):", file_name, line).c_str();
+#else
+  return String::Format("%s:%d:", file_name, line).c_str();
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const char* const file_name = file == NULL ? kUnknownFile : file;
+
+  if (line < 0)
+    return file_name;
+  else
+    return String::Format("%s:%d", file_name, line).c_str();
+}
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif  // _MSC_VER
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the
+    // current directory, so we create the temporary file in the /tmp
+    // directory instead.
+    char name_template[] = "/tmp/captured_stream.XXXXXX";
+    const int captured_fd = mkstemp(name_template);
+    filename_ = name_template;
+# endif  // GTEST_OS_WINDOWS
+    fflush(NULL);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  String GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(NULL);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    const String content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  // Reads the entire content of a file as a String.
+  static String ReadEntireFile(FILE* file);
+
+  // Returns the size (in bytes) of a file.
+  static size_t GetFileSize(FILE* file);
+
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+String CapturedStream::ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const String content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif  // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+  if (*stream != NULL) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+String GetCapturedStream(CapturedStream** captured_stream) {
+  const String content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = NULL;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+String GetCapturedStdout() { return GetCapturedStream(&g_captured_stdout); }
+
+// Stops capturing stderr and returns the captured string.
+String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+::std::vector<String> g_argvs;
+
+// Returns the command line as a vector of strings.
+const ::std::vector<String>& GetArgvs() { return g_argvs; }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static String FlagToEnvVar(const char* flag) {
+  const String full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = NULL;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an Int32?
+  const Int32 result = static_cast<Int32>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an Int32.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == NULL ?
+      default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == NULL) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  Int32 result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+  const String env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == NULL ? default_value : value;
+}
+
+}  // namespace internal
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-printers.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-printers.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-printers.cc	(revision 11817)
@@ -0,0 +1,356 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+#if GTEST_OS_WINDOWS_MOBILE  // Windows CE does not define _snprintf_s.
+# define snprintf _snprintf
+#elif _MSC_VER >= 1400  // VC 8.0 and later deprecate snprintf and _snprintf.
+# define snprintf _snprintf_s
+#elif _MSC_VER
+# define snprintf _snprintf
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  // TODO(wan): let the user control the threshold using a flag.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+}  // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+}  // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+  return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  switch (static_cast<wchar_t>(c)) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        *os << String::Format("\\x%X", static_cast<UnsignedChar>(c));
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo<wchar_t>(c, os);
+  }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
+  return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
+}
+
+// Prints a wide or narrow character c and its code.  '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence.  The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << ((sizeof(c) > 1) ? "L'" : "'");
+  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << String::Format("%d", c).c_str();
+
+  // For more convenience, we print c's code again in hexidecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << String::Format(", 0x%X",
+                          static_cast<UnsignedChar>(c)).c_str();
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+  PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.
+// The array starts at *begin, the length is len, it may include '\0' characters
+// and may not be null-terminated.
+static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
+  *os << "\"";
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const char cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" \"";
+    }
+    is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  PrintCharsAsStringTo(begin, len, os);
+}
+
+// Prints the given array of wide characters to the ostream.
+// The array starts at *begin, the length is len, it may include L'\0'
+// characters and may not be null-terminated.
+static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
+                                     ostream* os) {
+  *os << "L\"";
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const wchar_t cur = begin[index];
+    if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" L\"";
+    }
+    is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, strlen(s), os);
+  }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintWideCharsAsStringTo(s, wcslen(s), os);
+  }
+}
+#endif  // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+  PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-test-part.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-test-part.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-test-part.cc	(revision 11817)
@@ -0,0 +1,110 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest-test-part.h"
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+internal::String TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == NULL ? internal::String(message) :
+      internal::String(message, stack_trace - message);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os
+      << result.file_name() << ":" << result.line_number() << ": "
+      << (result.type() == TestPartResult::kSuccess ? "Success" :
+          result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+          "Non-fatal failure") << ":\n"
+      << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-typed-test.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-typed-test.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest-typed-test.cc	(revision 11817)
@@ -0,0 +1,110 @@
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+    const char* file, int line, const char* registered_tests) {
+  typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+  registered_ = true;
+
+  // Skip initial whitespace in registered_tests since some
+  // preprocessors prefix stringizied literals with whitespace.
+  registered_tests = SkipSpaces(registered_tests);
+
+  Message errors;
+  ::std::set<String> tests;
+  for (const char* names = registered_tests; names != NULL;
+       names = SkipComma(names)) {
+    const String name = GetPrefixUntilComma(names);
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    bool found = false;
+    for (DefinedTestIter it = defined_test_names_.begin();
+         it != defined_test_names_.end();
+         ++it) {
+      if (name == *it) {
+        found = true;
+        break;
+      }
+    }
+
+    if (found) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test case.\n";
+    }
+  }
+
+  for (DefinedTestIter it = defined_test_names_.begin();
+       it != defined_test_names_.end();
+       ++it) {
+    if (tests.count(*it) == 0) {
+      errors << "You forgot to list test " << *it << ".\n";
+    }
+  }
+
+  const String& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest.cc	(revision 11817)
@@ -0,0 +1,4898 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+// TODO(kenton@google.com): There are other ways to get the time on
+//   Windows, like GetTickCount() or GetSystemTimeAsFileTime().  MinGW
+//   supports these.  consider using them instead.
+#  define GTEST_HAS_GETTIMEOFDAY_ 1
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h>  // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+}  // namespace internal
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    internal::BoolFromGTestEnv("break_on_failure", false),
+    "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+    catch_exceptions,
+    internal::BoolFromGTestEnv("catch_exceptions", true),
+    "True iff " GTEST_NAME_
+    " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to xterm, xterm-color, xterm-256color, linux or cygwin.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", kUniversalFilter),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output", ""),
+    "A format (currently must be \"xml\"), optionally followed "
+    "by a colon and an output file name or directory. A directory "
+    "is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    print_time,
+    internal::BoolFromGTestEnv("print_time", true),
+    "True iff " GTEST_NAME_
+    " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    show_internal_stack_frames, false,
+    "True iff " GTEST_NAME_ " should include internal stack frames when "
+    "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+    shuffle,
+    internal::BoolFromGTestEnv("shuffle", false),
+    "True iff " GTEST_NAME_
+    " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+  // These constants are the same as are used in glibc's rand(3).
+  state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test.  g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called.  We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+                               int (TestCase::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+  return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+String g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS
+  result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(g_executable_path));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+String UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL) return String("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == NULL) ?
+      String(gtest_output_flag) :
+      String(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+String UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL)
+    return String("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == NULL)
+    return String(internal::FilePath::ConcatPaths(
+               internal::FilePath(
+                   UnitTest::GetInstance()->original_working_dir()),
+               internal::FilePath(kDefaultOutputFile)).ToString() );
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    // TODO(wan@google.com): on Windows \some\path is not an absolute
+    // path (as its meaning depends on the current drive), yet the
+    // following logic for turning it into an absolute path is wrong.
+    // Fix it.
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.ToString();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.ToString();
+}
+
+// Returns true iff the wildcard pattern matches the string.  The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+                                           const char *str) {
+  switch (*pattern) {
+    case '\0':
+    case ':':  // Either ':' or '\0' marks the end of the pattern.
+      return *str == '\0';
+    case '?':  // Matches any single character.
+      return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+    case '*':  // Matches any string (possibly empty) of characters.
+      return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+          PatternMatchesString(pattern + 1, str);
+    default:  // Non-special character.  Matches itself.
+      return *pattern == *str &&
+          PatternMatchesString(pattern + 1, str + 1);
+  }
+}
+
+bool UnitTestOptions::MatchesFilter(const String& name, const char* filter) {
+  const char *cur_pattern = filter;
+  for (;;) {
+    if (PatternMatchesString(cur_pattern, name.c_str())) {
+      return true;
+    }
+
+    // Finds the next pattern in the filter.
+    cur_pattern = strchr(cur_pattern, ':');
+
+    // Returns if no more pattern can be found.
+    if (cur_pattern == NULL) {
+      return false;
+    }
+
+    // Skips the pattern separater (the ':' character).
+    cur_pattern++;
+  }
+}
+
+// TODO(keithray): move String function implementations to gtest-string.cc.
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const String &test_case_name,
+                                        const String &test_name) {
+  const String& full_name = String::Format("%s.%s",
+                                           test_case_name.c_str(),
+                                           test_name.c_str());
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  String positive;
+  String negative;
+  if (dash == NULL) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = String("");
+  } else {
+    positive = String(p, dash - p);  // Everything up to the dash
+    negative = String(dash+1);       // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+                              const char* /* type_expr */,
+                              const char* /* substr_expr */,
+                              const TestPartResultArray& results,
+                              TestPartResult::Type type,
+                              const string& substr) {
+  const String expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == NULL) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+    const TestPartResultArray* results,
+    TestPartResult::Type type,
+    const string& substr)
+    : results_(results),
+      type_(type),
+      substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+  return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+  return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+  return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+  return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+String UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  (void)skip_count;
+  return String("");
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+  // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+  // http://analogous.blogspot.com/2005/04/epoch.html
+  const TimeInMillis kJavaEpochToWinFileTimeDelta =
+    static_cast<TimeInMillis>(116444736UL) * 100000UL;
+  const DWORD kTenthMicrosInMilliSecond = 10000;
+
+  SYSTEMTIME now_systime;
+  FILETIME now_filetime;
+  ULARGE_INTEGER now_int64;
+  // TODO(kenton@google.com): Shouldn't this just use
+  //   GetSystemTimeAsFileTime()?
+  GetSystemTime(&now_systime);
+  if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+    now_int64.LowPart = now_filetime.dwLowDateTime;
+    now_int64.HighPart = now_filetime.dwHighDateTime;
+    now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+      kJavaEpochToWinFileTimeDelta;
+    return now_int64.QuadPart;
+  }
+  return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+  __timeb64 now;
+
+# ifdef _MSC_VER
+
+  // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+  // (deprecated function) there.
+  // TODO(kenton@google.com): Use GetTickCount()?  Or use
+  //   SystemTimeToFileTime()
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4996)  // Temporarily disables warning 4996.
+  _ftime64(&now);
+#  pragma warning(pop)           // Restores the warning state.
+# else
+
+  _ftime64(&now);
+
+# endif  // _MSC_VER
+
+  return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String
+
+// Returns the input enclosed in double quotes if it's not NULL;
+// otherwise returns "(null)".  For example, "\"Hello\"" is returned
+// for input "Hello".
+//
+// This is useful for printing a C string in the syntax of a literal.
+//
+// Known issue: escape sequences are not handled yet.
+String String::ShowCStringQuoted(const char* c_str) {
+  return c_str ? String::Format("\"%s\"", c_str) : String("(null)");
+}
+
+// Copies at most length characters from str into a newly-allocated
+// piece of memory of size length+1.  The memory is allocated with new[].
+// A terminating null byte is written to the memory, and a pointer to it
+// is returned.  If str is NULL, NULL is returned.
+static char* CloneString(const char* str, size_t length) {
+  if (str == NULL) {
+    return NULL;
+  } else {
+    char* const clone = new char[length + 1];
+    posix::StrNCpy(clone, str, length);
+    clone[length] = '\0';
+    return clone;
+  }
+}
+
+// Clones a 0-terminated C string, allocating memory using new.  The
+// caller is responsible for deleting[] the return value.  Returns the
+// cloned string, or NULL if the input is NULL.
+const char * String::CloneCString(const char* c_str) {
+  return (c_str == NULL) ?
+                    NULL : CloneString(c_str, strlen(c_str));
+}
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return NULL;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                          NULL, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return NULL;
+  const int ansi_length =
+      WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                          NULL, 0, NULL, NULL);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                      ansi, ansi_length, NULL, NULL);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if ( lhs == NULL ) return rhs == NULL;
+
+  if ( rhs == NULL ) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  // TODO(wan): consider allowing a testing::String object to
+  // contain '\0'.  This will make it behave more like std::string,
+  // and will allow ToUtf8String() to return the correct encoding
+  // for '\0' s.t. we can get rid of the conditional here (and in
+  // several other places).
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+}  // namespace internal
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != NULL ?
+               new ::std::string(*other.message_) :
+               static_cast< ::std::string*>(NULL)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != NULL)
+    negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+                          const char* actual_expression,
+                          const String& expected_value,
+                          const String& actual_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Value of: " << actual_expression;
+  if (actual_value != actual_expression) {
+    msg << "\n  Actual: " << actual_value;
+  }
+
+  msg << "\nExpected: " << expected_expression;
+  if (ignoring_case) {
+    msg << " (ignoring case)";
+  }
+  if (expected_value != expected_expression) {
+    msg << "\nWhich is: " << expected_value;
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+String GetBoolAssertionFailureMessage(const AssertionResult& assertion_result,
+                                      const char* expression_text,
+                                      const char* actual_predicate_value,
+                                      const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // TODO(wan): do not print the value of an expression if it's
+  // already a literal.
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            BiggestInt expected,
+                            BiggestInt actual) {
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments.  It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   BiggestInt val1, BiggestInt val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const char* expected,
+                               const char* actual) {
+  if (String::CStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowCStringQuoted(expected),
+                   String::ShowCStringQuoted(actual),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const char* expected,
+                                   const char* actual) {
+  if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowCStringQuoted(expected),
+                   String::ShowCStringQuoted(actual),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack.  NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;  // String::Format can't exceed this length.
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          hr,  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,  // buf size
+                                          NULL);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing cr-lf)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const String error_hex(String::Format("0x%08X ", hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+  const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// The output buffer str must containt at least 32 characters.
+// The function returns the address of the output buffer.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'.
+char* CodePointToUtf8(UInt32 code_point, char* str) {
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else if (code_point <= kMaxCodePoint4) {
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  } else {
+    // The longest string String::Format can produce when invoked
+    // with these parameters is 28 character long (not including
+    // the terminating nul character). We are asking for 32 character
+    // buffer just in case. This is also enough for strncpy to
+    // null-terminate the destination string.
+    posix::StrNCpy(
+        str, String::Format("(Invalid Unicode 0x%X)", code_point).c_str(), 32);
+    str[31] = '\0';  // Makes sure no change in the format to strncpy leaves
+                     // the result unterminated.
+  }
+  return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                    wchar_t second) {
+  const UInt32 mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2) ?
+      (((first & mask) << 10) | (second & mask)) + 0x10000 :
+      // This function should not be called when the condition is
+      // false, but we provide a sensible default in case it is.
+      static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+String WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    UInt32 unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<UInt32>(str[i]);
+    }
+
+    char buffer[32];  // CodePointToUtf8 requires a buffer this big.
+    stream << CodePointToUtf8(unicode_code_point, buffer);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to a String using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+String String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == NULL) return String("(null)");
+
+  return String(internal::WideStringToUtf8(wide_c_str, -1).c_str());
+}
+
+// Similar to ShowWideCString(), except that this function encloses
+// the converted string in double quotes.
+String String::ShowWideCStringQuoted(const wchar_t* wide_c_str) {
+  if (wide_c_str == NULL) return String("(null)");
+
+  return String::Format("L\"%s\"",
+                        String::ShowWideCString(wide_c_str).c_str());
+}
+
+// Compares two wide C strings.  Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const wchar_t* expected,
+                               const wchar_t* actual) {
+  if (String::WideCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   String::ShowWideCStringQuoted(expected),
+                   String::ShowWideCStringQuoted(actual),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << String::ShowWideCStringQuoted(s1)
+                            << " vs " << String::ShowWideCStringQuoted(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == NULL)
+    return rhs == NULL;
+  if (rhs == NULL)
+    return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(*lhs++);
+    right = towlower(*rhs++);
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Compares this with another String.
+// Returns < 0 if this is less than rhs, 0 if this is equal to rhs, or > 0
+// if this is greater than rhs.
+int String::Compare(const String & rhs) const {
+  const char* const lhs_c_str = c_str();
+  const char* const rhs_c_str = rhs.c_str();
+
+  if (lhs_c_str == NULL) {
+    return rhs_c_str == NULL ? 0 : -1;  // NULL < anything except NULL
+  } else if (rhs_c_str == NULL) {
+    return 1;
+  }
+
+  const size_t shorter_str_len =
+      length() <= rhs.length() ? length() : rhs.length();
+  for (size_t i = 0; i != shorter_str_len; i++) {
+    if (lhs_c_str[i] < rhs_c_str[i]) {
+      return -1;
+    } else if (lhs_c_str[i] > rhs_c_str[i]) {
+      return 1;
+    }
+  }
+  return (length() < rhs.length()) ? -1 :
+      (length() > rhs.length()) ? 1 : 0;
+}
+
+// Returns true iff this String ends with the given suffix.  *Any*
+// String is considered to end with a NULL or empty suffix.
+bool String::EndsWith(const char* suffix) const {
+  if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+  if (c_str() == NULL) return false;
+
+  const size_t this_len = strlen(c_str());
+  const size_t suffix_len = strlen(suffix);
+  return (this_len >= suffix_len) &&
+         CStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Returns true iff this String ends with the given suffix, ignoring case.
+// Any String is considered to end with a NULL or empty suffix.
+bool String::EndsWithCaseInsensitive(const char* suffix) const {
+  if (suffix == NULL || CStringEquals(suffix, "")) return true;
+
+  if (c_str() == NULL) return false;
+
+  const size_t this_len = strlen(c_str());
+  const size_t suffix_len = strlen(suffix);
+  return (this_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(c_str() + this_len - suffix_len, suffix);
+}
+
+// Formats a list of arguments to a String, using the same format
+// spec string as for printf.
+//
+// We do not use the StringPrintf class as it is not universally
+// available.
+//
+// The result is limited to 4096 characters (including the tailing 0).
+// If 4096 characters are not enough to format the input, or if
+// there's an error, "<formatting error or buffer exceeded>" is
+// returned.
+String String::Format(const char * format, ...) {
+  va_list args;
+  va_start(args, format);
+
+  char buffer[4096];
+  const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
+
+  // MSVC 8 deprecates vsnprintf(), so we want to suppress warning
+  // 4996 (deprecated function) there.
+#ifdef _MSC_VER  // We are using MSVC.
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996.
+
+  const int size = vsnprintf(buffer, kBufferSize, format, args);
+
+# pragma warning(pop)           // Restores the warning state.
+#else  // We are not using MSVC.
+  const int size = vsnprintf(buffer, kBufferSize, format, args);
+#endif  // _MSC_VER
+  va_end(args);
+
+  // vsnprintf()'s behavior is not portable.  When the buffer is not
+  // big enough, it returns a negative value in MSVC, and returns the
+  // needed buffer size on Linux.  When there is an output error, it
+  // always returns a negative value.  For simplicity, we lump the two
+  // error cases together.
+  if (size < 0 || size >= kBufferSize) {
+    return String("<formatting error or buffer exceeded>");
+  } else {
+    return String(buffer, size);
+  }
+}
+
+// Converts the buffer in a stringstream to a String, converting NUL
+// bytes to "\\0" along the way.
+String StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  // We need to use a helper stringstream to do this transformation
+  // because String doesn't support push_back().
+  ::std::stringstream helper;
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      helper << "\\0";  // Replaces NUL with "\\0";
+    } else {
+      helper.put(*ch);
+    }
+  }
+
+  return String(helper.str().c_str());
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+String AppendUserMessage(const String& gtest_msg,
+                         const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const String user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+
+  Message msg;
+  msg << gtest_msg << "\n" << user_msg_string;
+
+  return msg.GetString();
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0),
+      elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const TestProperty& test_property) {
+  if (!ValidateTestProperty(test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properites_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// Adds a failure if the key is a reserved attribute of Google Test
+// testcase tags.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const TestProperty& test_property) {
+  internal::String key(test_property.key());
+  if (key == "name" || key == "status" || key == "time" || key == "classname") {
+    ADD_FAILURE()
+        << "Reserved key used in RecordProperty(): "
+        << key
+        << " ('name', 'status', 'time', and 'classname' are reserved by "
+        << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+    : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+  delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, const char* value) {
+  UnitTest::GetInstance()->RecordPropertyForCurrentTest(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const char* key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const String& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      NULL,  // No info about the source file where the exception occurred.
+      -1,    // We have no info on which line caused the exception.
+      message,
+      String());  // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test case.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestCase* const test_case = impl->current_test_case();
+
+  // Info about the first test in the current test case.
+  const TestInfo* const first_test_info = test_case->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // The user mixed TEST and TEST_F in this test case - we'll tell
+      // him/her how to fix it.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test case is\n"
+          << "illegal.  In test case " << this_test_info->test_case_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // The user defined two fixture classes with the same name in
+      // two namespaces - we'll tell him/her how to fix it.
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class.  However, in test case "
+          << this_test_info->test_case_name() << ",\n"
+          << "you defined test " << first_test_name
+          << " and test " << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test cases.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+                                                   const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new internal::String(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+                                                  const char* location) {
+  Message message;
+  if (description != NULL) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled).  We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time.  Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure)
+      : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif  // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    internal::String* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const GoogleTestFailureException&) {  // NOLINT
+      // This exception doesn't originate in code under test. It makes no
+      // sense to report it as a test failure.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(NULL, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful.
+  if (!HasFatalFailure()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
+TestInfo::TestInfo(const char* a_test_case_name,
+                   const char* a_name,
+                   const char* a_type_param,
+                   const char* a_value_param,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_case_name_(a_test_case_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name, const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_case_name, name, type_param, value_param,
+                   fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+                               const char* file, int line) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test case " << test_case_name << ".\n"
+      << "All tests in the same test case must use the same test fixture\n"
+      << "class.  However, in test case " << test_case_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test cases.";
+
+  fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+          errors.GetString().c_str());
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+class TestNameIs {
+ public:
+  // Constructor.
+  //
+  // TestNameIs has NO default constructor.
+  explicit TestNameIs(const char* name)
+      : name_(name) {}
+
+  // Returns true iff the test name of test_info matches name_.
+  bool operator()(const TestInfo * test_info) const {
+    return test_info && internal::String(test_info->name()).Compare(name_) == 0;
+  }
+
+ private:
+  internal::String name_;
+};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    parameterized_tests_registered_ = true;
+  }
+#endif
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TimeInMillis start = internal::GetTimeInMillis();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test only if the test object was created and its
+  // constructor didn't generate a fatal failure.
+  if ((test != NULL) && !Test::HasFatalFailure()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  // Deletes the test object.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+  result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+int TestCase::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+//   name:         name of the test case
+//   a_type_param: the name of the test case's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test case.
+//   set_up_tc:    pointer to the function that sets up the test case
+//   tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+                   Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case.  Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_case(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  repeater->OnTestCaseStart(*this);
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+  const internal::TimeInMillis start = internal::GetTimeInMillis();
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+  }
+  elapsed_time_ = internal::GetTimeInMillis() - start;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+  repeater->OnTestCaseEnd(*this);
+  impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static internal::String FormatCountableNoun(int count,
+                                            const char * singular_form,
+                                            const char * plural_form) {
+  return internal::String::Format("%d %s", count,
+                                  count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static internal::String FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static internal::String FormatTestCaseCount(int test_case_count) {
+  return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+// Prints a TestPartResult to a String.
+static internal::String PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const internal::String& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+namespace internal {
+
+enum GTestColor {
+  COLOR_DEFAULT,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:    return FOREGROUND_RED;
+    case COLOR_GREEN:  return FOREGROUND_GREEN;
+    case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.  COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:     return "1";
+    case COLOR_GREEN:   return "2";
+    case COLOR_YELLOW:  return "3";
+    default:            return NULL;
+  };
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  const bool use_color = false;
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != NULL || value_param != NULL) {
+    printf(", where ");
+    if (type_param != NULL) {
+      printf("TypeParam = %s", type_param);
+      if (value_param != NULL)
+        printf(" and ");
+    }
+    if (value_param != NULL) {
+      printf("GetParam() = %s", value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char * test_case, const char * test) {
+    printf("%s.%s", test_case, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+
+  internal::String test_case_name_;
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!internal::String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: %s filter = %s\n", GTEST_NAME_, filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  test_case_name_ = test_case.name();
+  const internal::String counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case_name_.c_str());
+  if (test_case.type_param() == NULL) {
+    printf("\n");
+  } else {
+    printf(", where TypeParam = %s\n", test_case.type_param());
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(COLOR_GREEN,  "[ RUN      ] ");
+  PrintTestName(test_case_name_.c_str(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  // If the test part succeeded, we don't need to do anything.
+  if (result.type() == TestPartResult::kSuccess)
+    return;
+
+  // Print failure message from the assertion (e.g. expected this and got that).
+  PrintTestPartResult(result);
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(COLOR_GREEN, "[       OK ] ");
+  } else {
+    ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+  }
+  PrintTestName(test_case_name_.c_str(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  test_case_name_ = test_case.name();
+  const internal::String counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n",
+         counts.c_str(), test_case_name_.c_str(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  if (failed_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      if (!test_info.should_run() || test_info.result()->Passed()) {
+        continue;
+      }
+      ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+      printf("%s.%s", test_case.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(COLOR_GREEN,  "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  int num_failures = unit_test.failed_test_count();
+  if (!unit_test.Passed()) {
+    const int failed_test_count = unit_test.failed_test_count();
+    ColoredPrintf(COLOR_RED,  "[  FAILED  ] ");
+    printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+    PrintFailedTests(unit_test);
+    printf("\n%2d FAILED %s\n", num_failures,
+                        num_failures == 1 ? "TEST" : "TESTS");
+  }
+
+  int num_disabled = unit_test.disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (!num_failures) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(COLOR_YELLOW,
+                  "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled,
+                  num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  virtual ~TestEventRepeater();
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  virtual void OnTestProgramStart(const UnitTest& unit_test);
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + i);
+      return listener;
+    }
+  }
+
+  return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+      listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static String EscapeXml(const char* str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static string RemoveInvalidXmlCharacters(const string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static String EscapeXmlAttribute(const char* str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_case_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestCase object
+  static void PrintXmlTestCase(FILE* out, const TestCase& test_case);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(FILE* out, const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the String is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static String TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // The output file.
+  const String output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.c_str() == NULL || output_file_.empty()) {
+    fprintf(stderr, "XML output file may not be null\n");
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = NULL;
+  FilePath output_file(output_file_);
+  FilePath output_dir(output_file.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    xmlout = posix::FOpen(output_file_.c_str(), "w");
+  }
+  if (xmlout == NULL) {
+    // TODO(wan): report the reason of the failure.
+    //
+    // We don't do it for now as:
+    //
+    //   1. There is no urgent need for it.
+    //   2. It's a bit involved to make the errno variable thread-safe on
+    //      all three operating systems (Linux, Windows, and Mac OS).
+    //   3. To interpret the meaning of errno in a thread-safe way,
+    //      we need the strerror_r() function, which is not available on
+    //      Windows.
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            output_file_.c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  PrintXmlUnitTest(xmlout, unit_test);
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
+  Message m;
+
+  if (str != NULL) {
+    for (const char* src = str; *src; ++src) {
+      switch (*src) {
+        case '<':
+          m << "&lt;";
+          break;
+        case '>':
+          m << "&gt;";
+          break;
+        case '&':
+          m << "&amp;";
+          break;
+        case '\'':
+          if (is_attribute)
+            m << "&apos;";
+          else
+            m << '\'';
+          break;
+        case '"':
+          if (is_attribute)
+            m << "&quot;";
+          else
+            m << '"';
+          break;
+        default:
+          if (IsValidXmlCharacter(*src)) {
+            if (is_attribute && IsNormalizableWhitespace(*src))
+              m << String::Format("&#x%02X;", unsigned(*src));
+            else
+              m << *src;
+          }
+          break;
+      }
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) {
+  string output;
+  output.reserve(str.size());
+  for (string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestCase object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << ms/1000.0;
+  return ss.str();
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != NULL) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_case_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  *stream << "    <testcase name=\""
+          << EscapeXmlAttribute(test_info.name()).c_str() << "\"";
+
+  if (test_info.value_param() != NULL) {
+    *stream << " value_param=\"" << EscapeXmlAttribute(test_info.value_param())
+            << "\"";
+  }
+  if (test_info.type_param() != NULL) {
+    *stream << " type_param=\"" << EscapeXmlAttribute(test_info.type_param())
+            << "\"";
+  }
+
+  *stream << " status=\""
+          << (test_info.should_run() ? "run" : "notrun")
+          << "\" time=\""
+          << FormatTimeInMillisAsSeconds(result.elapsed_time())
+          << "\" classname=\"" << EscapeXmlAttribute(test_case_name).c_str()
+          << "\"" << TestPropertiesAsXmlAttributes(result).c_str();
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1)
+        *stream << ">\n";
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(part.summary()).c_str()
+              << "\" type=\"\">";
+      const string location = internal::FormatCompilerIndependentFileLocation(
+          part.file_name(), part.line_number());
+      const string message = location + "\n" + part.message();
+      OutputXmlCDataSection(stream,
+                            RemoveInvalidXmlCharacters(message).c_str());
+      *stream << "</failure>\n";
+    }
+  }
+
+  if (failures == 0)
+    *stream << " />\n";
+  else
+    *stream << "    </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
+                                                const TestCase& test_case) {
+  fprintf(out,
+          "  <testsuite name=\"%s\" tests=\"%d\" failures=\"%d\" "
+          "disabled=\"%d\" ",
+          EscapeXmlAttribute(test_case.name()).c_str(),
+          test_case.total_test_count(),
+          test_case.failed_test_count(),
+          test_case.disabled_test_count());
+  fprintf(out,
+          "errors=\"0\" time=\"%s\">\n",
+          FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
+  for (int i = 0; i < test_case.total_test_count(); ++i) {
+    ::std::stringstream stream;
+    OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
+    fprintf(out, "%s", StringStreamToString(&stream).c_str());
+  }
+  fprintf(out, "  </testsuite>\n");
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
+                                                const UnitTest& unit_test) {
+  fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+  fprintf(out,
+          "<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" "
+          "errors=\"0\" time=\"%s\" ",
+          unit_test.total_test_count(),
+          unit_test.failed_test_count(),
+          unit_test.disabled_test_count(),
+          FormatTimeInMillisAsSeconds(unit_test.elapsed_time()).c_str());
+  if (GTEST_FLAG(shuffle)) {
+    fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
+  }
+  fprintf(out, "name=\"AllTests\">\n");
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i)
+    PrintXmlTestCase(out, *unit_test.GetTestCase(i));
+  fprintf(out, "</testsuites>\n");
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static string UrlEncode(const char* str);
+
+  StreamingListener(const string& host, const string& port)
+      : sockfd_(-1), host_name_(host), port_num_(port) {
+    MakeConnection();
+    Send("gtest_streaming_protocol_version=1.0\n");
+  }
+
+  virtual ~StreamingListener() {
+    if (sockfd_ != -1)
+      CloseConnection();
+  }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) {
+    Send("event=TestProgramStart\n");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    Send(String::Format("event=TestProgramEnd&passed=%d\n",
+                        unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+    Send(String::Format("event=TestIterationStart&iteration=%d\n",
+                        iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+    Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
+                        unit_test.Passed(),
+                        StreamableToString(unit_test.elapsed_time()).c_str()));
+  }
+
+  void OnTestCaseStart(const TestCase& test_case) {
+    Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
+  }
+
+  void OnTestCaseEnd(const TestCase& test_case) {
+    Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
+                        test_case.Passed(),
+                        StreamableToString(test_case.elapsed_time()).c_str()));
+  }
+
+  void OnTestStart(const TestInfo& test_info) {
+    Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
+  }
+
+  void OnTestEnd(const TestInfo& test_info) {
+    Send(String::Format(
+        "event=TestEnd&passed=%d&elapsed_time=%sms\n",
+        (test_info.result())->Passed(),
+        StreamableToString((test_info.result())->elapsed_time()).c_str()));
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == NULL)
+      file_name = "";
+    Send(String::Format("event=TestPartResult&file=%s&line=%d&message=",
+                        UrlEncode(file_name).c_str(),
+                        test_part_result.line_number()));
+    Send(UrlEncode(test_part_result.message()) + "\n");
+  }
+
+ private:
+  // Creates a client socket and connects to the server.
+  void MakeConnection();
+
+  // Closes the socket.
+  void CloseConnection() {
+    GTEST_CHECK_(sockfd_ != -1)
+        << "CloseConnection() can be called only when there is a connection.";
+
+    close(sockfd_);
+    sockfd_ = -1;
+  }
+
+  // Sends a string to the socket.
+  void Send(const string& message) {
+    GTEST_CHECK_(sockfd_ != -1)
+        << "Send() can be called only when there is a connection.";
+
+    const int len = static_cast<int>(message.length());
+    if (write(sockfd_, message.c_str(), len) != len) {
+      GTEST_LOG_(WARNING)
+          << "stream_result_to: failed to stream to "
+          << host_name_ << ":" << port_num_;
+    }
+  }
+
+  int sockfd_;   // socket file descriptor
+  const string host_name_;
+  const string port_num_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+  string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append(String::Format("%%%02x", static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = NULL;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+// L < UnitTest::mutex_
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message) {
+  TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message = message.GetString();
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+// L < UnitTest::mutex_
+ScopedTrace::~ScopedTrace() {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as a String.  Parameters:
+//
+//   max_depth  - the maximum number of stack frames to be included
+//                in the trace.
+//   skip_count - the number of top frames to be skipped; doesn't count
+//                against max_depth.
+//
+// L < mutex_
+// We use "L < mutex_" to denote that the function may acquire mutex_.
+String OsStackTraceGetter::CurrentStackTrace(int, int) {
+  return String("");
+}
+
+// L < mutex_
+void OsStackTraceGetter::UponLeavingGTest() {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(NULL),
+      default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = NULL;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = NULL;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest * UnitTest::GetInstance() {
+  // When compiled with MSVC 7.1 in optimized mode, destroying the
+  // UnitTest object upon exiting the program messes up the exit code,
+  // causing successful tests to appear failed.  We have to use a
+  // different implementation in this case to bypass the compiler bug.
+  // This implementation makes the compiler happy, at the cost of
+  // leaking the UnitTest object.
+
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+  return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == NULL) {
+    return NULL;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+// L < mutex_
+void UnitTest::AddTestPartResult(TestPartResult::Type result_type,
+                                 const char* file_name,
+                                 int line_number,
+                                 const internal::String& message,
+                                 const internal::String& os_stack_trace) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+         i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result =
+    TestPartResult(result_type, file_name, line_number,
+                   msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#else
+      // Dereference NULL through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: Symbian doesn't implement abort() well, and some debuggers
+      // don't correctly trap abort().
+      *static_cast<volatile int*>(NULL) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Creates and adds a property to the current TestResult. If a property matching
+// the supplied value already exists, updates its value instead.
+void UnitTest::RecordPropertyForCurrentTest(const char* key,
+                                            const char* value) {
+  const TestProperty test_property(key, value);
+  impl_->current_test_result()->RecordProperty(test_property);
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH || GTEST_OS_WINDOWS_MINGW
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+
+# if !GTEST_OS_WINDOWS_MOBILE
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    //
+    // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+    // Users of prior VC versions shall suffer the agony and pain of
+    // clicking through the countless debug dialogs.
+    // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+    // debug mode when compiled with VC 7.1 or lower.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+# endif
+
+  }
+#endif  // GTEST_HAS_SEH
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestCase* UnitTest::current_test_case() const {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+// L < mutex_
+const TestInfo* UnitTest::current_test_info() const {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+// L < mutex_
+internal::ParameterizedTestCaseRegistry&
+    UnitTest::parameterized_test_registry() {
+  return impl_->parameterized_test_registry();
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+// L < mutex_
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+// L < mutex_
+void UnitTest::PopGTestTrace() {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+#ifdef _MSC_VER
+# pragma warning(push)                    // Saves the current warning state.
+# pragma warning(disable:4355)            // Temporarily disables warning 4355
+                                         // (using this in initializer).
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+# pragma warning(pop)                     // Restores the warning state again.
+#else
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+#endif  // _MSC_VER
+      global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+#endif  // GTEST_HAS_PARAM_TEST
+      last_death_test_case_(-1),
+      current_test_case_(NULL),
+      current_test_info_(NULL),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(NULL),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),  // Will be reseeded before first use.
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      internal_run_death_test_flag_(NULL),
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestCase.
+  ForEach(test_cases_, internal::Delete<TestCase>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != NULL)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const String& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+           output_format.c_str());
+    fflush(stdout);
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in String form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+             target.c_str());
+      fflush(stdout);
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+  }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+  // Constructor.
+  explicit TestCaseNameIs(const String& name)
+      : name_(name) {}
+
+  // Returns true iff the name of test_case matches name_.
+  bool operator()(const TestCase* test_case) const {
+    return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  String name_;
+};
+
+// Finds and returns a TestCase with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_case_name: name of the test case
+//   type_param:     the name of the test case's type parameter, or NULL if
+//                   this is not a typed or a type-parameterized test case.
+//   set_up_tc:      pointer to the function that sets up the test case
+//   tear_down_tc:   pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+                                    const char* type_param,
+                                    Test::SetUpTestCaseFunc set_up_tc,
+                                    Test::TearDownTestCaseFunc tear_down_tc) {
+  // Can we find a TestCase with the given name?
+  const std::vector<TestCase*>::const_iterator test_case =
+      std::find_if(test_cases_.begin(), test_cases_.end(),
+                   TestCaseNameIs(test_case_name));
+
+  if (test_case != test_cases_.end())
+    return *test_case;
+
+  // No.  Let's create one.
+  TestCase* const new_test_case =
+      new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test case?
+  if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
+                                               kDeathTestCaseFilter)) {
+    // Yes.  Inserts the test case after the last death test case
+    // defined so far.  This only works when the test cases haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_case_;
+    test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+                       new_test_case);
+  } else {
+    // No.  Appends to the end of the list.
+    test_cases_.push_back(new_test_case);
+  }
+
+  test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+  return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // Makes sure InitGoogleTest() was called.
+  if (!GTestIsInitialized()) {
+    printf("%s",
+           "\nThis test program did NOT call ::testing::InitGoogleTest "
+           "before calling RUN_ALL_TESTS().  Please fix it.\n");
+    return false;
+  }
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True iff we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True iff at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool forever = repeat < 0;
+  for (int i = 0; forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    const TimeInMillis start = GetTimeInMillis();
+
+    // Shuffles test cases and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(random_seed_);
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test case if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure during global
+      // set-up.
+      if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_case_count();
+             test_index++) {
+          GetMutableTestCase(test_index)->Run();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = GetTimeInMillis() - start;
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != NULL) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == NULL) {
+      ColoredPrintf(COLOR_RED,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == NULL) {
+    return default_val;
+  }
+
+  Int32 result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    TestCase* const test_case = test_cases_[i];
+    const String &test_case_name = test_case->name();
+    test_case->set_should_run(false);
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_case->test_info_list()[j];
+      const String test_name(test_info->name());
+      // A test is disabled if test case name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                                   kDisableTestFilter) ||
+          internal::UnitTestOptions::MatchesFilter(test_name,
+                                                   kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+                                                       test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_selected = is_runnable &&
+          (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+           ShouldRunTestOnShard(total_shards, shard_index,
+                                num_runnable_tests));
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_case->set_should_run(test_case->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    const TestCase* const test_case = test_cases_[i];
+    bool printed_test_case_name = false;
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      const TestInfo* const test_info =
+          test_case->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_case_name) {
+          printed_test_case_name = true;
+          printf("%s.\n", test_case->name());
+        }
+        printf("  %s\n", test_info->name());
+      }
+    }
+  }
+  fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == NULL) {
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+  return current_test_info_ ?
+      &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test cases.
+  ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+  // Shuffles the non-death test cases.
+  ShuffleRange(random(), last_death_test_case_ + 1,
+               static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+  // Shuffles the tests inside each test case.
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    test_cases_[i]->ShuffleTests(random());
+  }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    // Unshuffles the tests in each test case.
+    test_cases_[i]->UnshuffleTests();
+    // Resets the index of each test case.
+    test_case_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as a String.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+String GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                       int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+                           const char* flag,
+                           bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const String flag_str = String::Format("--%s%s", GTEST_FLAG_PREFIX_, flag);
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, String* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = COLOR_DEFAULT;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == NULL) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", String(str, p - str).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = COLOR_DEFAULT;
+    } else if (ch == 'R') {
+      color = COLOR_RED;
+    } else if (ch == 'G') {
+      color = COLOR_GREEN;
+    } else if (ch == 'Y') {
+      color = COLOR_YELLOW;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+"      List the names of all tests instead of running them. The name of\n"
+"      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+"  @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+"      Run only the tests whose name matches one of the positive patterns but\n"
+"      none of the negative patterns. '?' matches any single character; '*'\n"
+"      matches any substring; ':' separates two patterns.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+"      Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+"      Run the tests repeatedly; use a negative count to repeat forever.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+"      Randomize tests' orders on every iteration.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+"      Random number seed to use for shuffling test orders (between 1 and\n"
+"      99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+"      Enable/disable colored output. The default is @Gauto@D.\n"
+"  -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+"      Don't print the elapsed time of each test.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+    GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+"      Generate an XML report in the given directory or with the given file\n"
+"      name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+"  @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+"      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+"      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+"      Turn assertion failures into debugger break-points.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+"      Turn assertion failures into C++ exceptions.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+"      Do not report exceptions as test failures. Instead, allow them\n"
+"      to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const String arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    // Do we see a Google Test flag?
+    if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                      &GTEST_FLAG(also_run_disabled_tests)) ||
+        ParseBoolFlag(arg, kBreakOnFailureFlag,
+                      &GTEST_FLAG(break_on_failure)) ||
+        ParseBoolFlag(arg, kCatchExceptionsFlag,
+                      &GTEST_FLAG(catch_exceptions)) ||
+        ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+        ParseStringFlag(arg, kDeathTestStyleFlag,
+                        &GTEST_FLAG(death_test_style)) ||
+        ParseBoolFlag(arg, kDeathTestUseFork,
+                      &GTEST_FLAG(death_test_use_fork)) ||
+        ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+        ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                        &GTEST_FLAG(internal_run_death_test)) ||
+        ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+        ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+        ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+        ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+        ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+        ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+        ParseInt32Flag(arg, kStackTraceDepthFlag,
+                       &GTEST_FLAG(stack_trace_depth)) ||
+        ParseStringFlag(arg, kStreamResultToFlag,
+                        &GTEST_FLAG(stream_result_to)) ||
+        ParseBoolFlag(arg, kThrowOnFailureFlag,
+                      &GTEST_FLAG(throw_on_failure))
+        ) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  g_init_gtest_count++;
+
+  // We don't want to run the initialization code twice.
+  if (g_init_gtest_count != 1) return;
+
+  if (*argc <= 0) return;
+
+  internal::g_executable_path = internal::StreamableToString(argv[0]);
+
+#if GTEST_HAS_DEATH_TEST
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+}  // namespace testing
Index: /code/branches/RacingBots_FS18/src/external/gtest/src/gtest_main.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/external/gtest/src/gtest_main.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/gtest/src/gtest_main.cc	(revision 11817)
@@ -0,0 +1,39 @@
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+
+GTEST_API_ int main(int argc, char **argv) {
+  std::cout << "Running main() from gtest_main.cc\n";
+
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
Index: /code/branches/RacingBots_FS18/src/external/loki/CHANGES
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/CHANGES	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/CHANGES	(revision 11817)
@@ -0,0 +1,446 @@
+_____________________________________
+
+Version 0.1.7
+January 2009
+_____________________________________
+
+General:
+    - Fixed makefiles for GNU/kFreeBSD, GNU/hurd. (lf)
+    - Fixed build errors with gcc 4.3 pre-release. (lf)
+    - Fixed compiler error that occurs when using 64 bit pointers. (rs)
+    - Added support for Code::Blocks and MSVC 9. (rs, pk)
+    - Added more unit tests (rs)
+    - Several other bug fixes (rs, pk)
+
+Checker:
+    - Added for this release. (rs)
+    - Added test project. (rs)
+
+CheckReturn:
+    - Added for this release. (rs, pk)
+    - Added test project. (rs + pk)
+
+flex_string:
+    - Fixed bugs in several functions and storage policies. (aa, rs, jfg)
+
+LevelMutex:
+    - Added for this release. (rs)
+    - Added unit tests for LevelMutex. (rs)
+
+SafeBits:
+    - Added for this release. (rs, fp)
+    - Added unit tests for SafeBits. (rs, fp)
+
+SmartPtr:
+    - Fixed double-delete race condition. (rs)
+
+StrongPtr:
+    - Fixed destructor so cleanup is only done once. (rs)
+    - Fixed test by using class level locking. (lf)
+
+Threads:
+    - Add possibility to enable recursive mutex support for pthread (pk)
+    - Added more atomic functions.  (rs)
+
+Type Traits:
+    - Added 64 bit support. (cg)
+
+CVS commits by:
+	Andrei Alexandrescu (aa)
+	Guillaume Chatelet (cg)
+	Lukas Fittl (lf)
+	Peter Kümmel (pk)
+	Rich Sposato (rs)
+
+Contributions by:
+	Andrei Alexandrescu (aa)
+	Jean-Francois Bastien (jfb)
+	Guillaume Chatelet (cg)
+	Lukas Fittl (lf)
+	Fedor Pikus (fp)
+	Peter Kümmel (pk)
+	Rich Sposato (rs)
+
+_____________________________________
+
+Version 0.1.6
+February 25, 2007
+_____________________________________
+
+General:
+    - CacheFactory added by Guillaume Chatelet
+    - Factory documentation improved by Guillaume Chatelet
+    - migrated to subversion (pk)
+    - Mac linker errors fixed (lf)
+    - Makefiles can now be called from sub directories (lf)
+    - Makefiles know includes and recompile if they are changed (linux, macosx) (lf)
+    - Build all tests except SingletonDll with the static library (linux, macosx) (lf)
+    - use standard conforming naming, SUN's compiler needs it (pk)
+    - add Loki:: to LOKI_ macros
+    - several bug fixes.
+
+AbstractFactory:
+    - remove injected friends. (thanks to Sigoure Benoit, pk)
+   
+AssocVector:
+    - remove injected friends. (thanks to Sigoure Benoit, pk)
+    
+LockingPtr:
+    - constructor added which gets a std::pair of pointers 
+      to the object and the mutex (pk)
+    
+Pimpl:
+    - ImplT/PimplT/RimplT renamed to a more readable version: ImplOf (pk)
+
+Register:
+    - also produce a informative LOKI_CHECK_CLASS_IN_LIST error message with GCC (pk)
+
+SafeFormat:
+    - add writing to ostream, by Tom Browder (pk)
+    - add unsigned long version for Windows, (Thanks to ShenLei, pk)
+    
+Sequence:
+    - Also compiles with Aix
+    - switched to recursive implementation
+    
+Singleton
+    - example: move instantiation to the source file 
+      fixes linker error with gcc 4.0.1 on the mac, 
+      (Thanks to Idar Tollefsen and Sam Miller, pk)
+    - 64 bit linker error fixed (lf)
+
+SmallObj:
+    - compiler errors on SUN fixed (pk)    
+    - more documentation (rs)
+    - more tests (rs)
+    - AIX fixed, (thanks to Dieter Rosch, pk)
+  
+StrongPtr:
+    - Added typedef so LockableTwoRefCounts uses thread-safe allocator. (rs)
+    - AIX fixed, (thanks to Dieter Rosch, pk)
+    - linker error when using threads fixed (pk)
+  
+Threads:
+    - reentrance support added to the pthread mutex (Thanks to Shen Lei, pk)
+      
+
+CVS commits by Guillaume Chatelet (gc), Lukas Fittl (lf), Peter Kümmel (pk), Rich Sposato (rs)
+      
+
+_____________________________________
+
+Version 0.1.5
+June 19, 2006
+_____________________________________
+
+General:
+    - operator== added to Functor, initiated by Eric Beyeler (pk)
+    - new Strong/Weak smart pointer added. (rs)
+    - loki.spec (Thanks to Regis Desgroppes and Andreas Scherer, pk)
+    - build shared lib also on mac osx (Thanks to Sam Miller, lf)
+    - added MinGW .dev files for the library (rs)
+    - some makefile improvements (Thanks to Sam Miller, lf)
+    - adding an XCode build project (kx)
+    
+    
+flex_string:
+    - compare bug fixed in flex_string_shell.h (Thanks to David A. Capello, pk)
+    
+Function:
+    - test is doesn't need boost any more (pk)
+    - wrong default parameter fixed (pk)
+    
+OrderedStatic:
+    - undef all min/max macros (Thanks to Shen Lei, pk)
+    
+Singleton:
+    - Singleton<> moved into correct namespace (Thanks to Sam Miller, pk)
+    
+SmartPtr:
+    - patch for RedHat 9: undefined uintptr_t (Thanks to Regis Desgroppes, pk)
+    - more tests (rs)
+    - bugs 1452805 and 1451835 fixed (rs)
+    - addded HeapStorage policy as mentioned in Feature Request 1441024 (rs)
+    - added MinGW test project for SmartPtr (rs)
+    
+
+CVS commits by Rich Sposato (rs), Lukas Fittl (lf),
+Christopher Knox (kx), and Peter Kümmel (pk)
+
+
+
+_____________________________________
+
+Version 0.1.4
+March 8, 2006
+_____________________________________
+
+General:
+    - helper templates for Pimpl/Rimpl implementations added (pk)
+    - improved Makefiles (lf)
+    - improved make.msvc.bat files (pk)
+    - cvs LOG keywords added (rs)
+    - removed old c style casts (lf)
+    - more warning enabled on gcc (lf)
+    - new header added: ConstPolicy.h (rs,pk)
+    - new header added: RefToValue.h (rs,pk)
+    - standard RPM specification file for integrated installation 
+      on OpenSUSE Linux added (Thanks to Andreas Scherer, pk)
+    - using Loki as shared library is now possible (pk,lf)
+    - Register.h added (pk)
+    
+    
+Function:
+    - guard including (pk)
+    - test stsic functions (pk)
+    - test LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT  (pk)
+    
+Functor:
+    - Added explicit call to base copy-constructor (rs)  
+    - Changed base class from SmallObject to SmallValueObject. (Thanks to Sam Miller, rs)
+    - add possibility to disable inheritance from SmallValueObject: LOKI_FUNCTOR_IS_NOT_A_SMALLOBJECT (pk)
+    
+ScopeGuard:
+    - naming conflict with SmartPtr removed (rs,pk)
+    - ByRef moved to RefByVale (rs,pk)
+  
+Singleton:
+    - support of allocators with a standard interface added (Thanks to Miguel A. Figueroa-Villanueva, pk)
+    - convenience template Singleton added for shared libraries (Thanks to Marcus Lindblom, pk)
+    - example added which shows how to use Singletons with shared libraries added (Thanks to Marcus Lindblom, pk)
+
+SmartPtr:
+    - supports propagating constness by additional policy (rs,pk)
+    - ArrayStorage policy added (Thanks to Sam Miller, pk)
+    - fix in RefCounted for Mac OSX gcc 4.0.0 (Thanks to Sam Miller, pk)
+    - RefCounted ported to 64 bit (pk)
+    - add mutex policy (pk)
+    - new test code (rs)
+    - RecjectNullStrict const member function added (Thanks to Sam Miller, pk)
+    - Moved a monolithic RefLinkedBase class from header file to new source file. (rs)
+    - ByRef moved to RefToVale (rs,pk)
+    - Fixed bug 1425890.  Last SmartPtr in linked chain NULLs its prev & next
+      pointers to prevent infinite recursion.  Added asserts. (rs)
+    - Bug fix: infinite recursion in SmartPtr destructor (rs)
+    
+LockingPtr:
+    - wrong return types fixed (rs)
+    - add mutex policy (rs,pk)
+    - supports now propagating constness (pk,rs)
+    - macro switch LOKI_DEFAULT_CONSTNESS added for propagating constness (pk)
+    - multi threaded example added 
+    
+SafeFormat:
+    - definition moved to src/SafeFormat.cpp, it's now part of the library
+    
+Singleton:
+    - add mutex policy (pk)
+
+SmallObj:
+    - add mutex policy (pk)
+    - Added check for memory leak inside destructor. (Thanks to Kwak Jae Hyuk, rs)
+
+Threads:
+    - Mutex added (rs,pk)
+    - use Loki::Mutex instead of win32/posix mutexes in threading classes (rs,pk)
+
+
+CVS commits by Rich Sposato (rs), Lukas Fittl (lf)
+and Peter Kümmel (pk)
+
+
+
+_____________________________________
+
+Version 0.1.3
+January 9, 2006
+_____________________________________
+
+General:
+    - LockPtr added (rs)
+    - ScopeGuard added (pk,rs)
+    - improved Makefiles (lf,pk)
+    - several gcc fixes and removed warnings by Lukas Fittl (lf)
+    - tested on 64-bit Linux (pk)
+    - MS Visual C++ 2005 project files added (pk)
+    - now also the ms toolkit 2003 generates a library (pk)
+
+OrderedStatic:
+    - point operator added (pk)
+
+SafeFormat:
+    - moved into namespace Loki (pk)
+    - 64 bit problems fixed (Thanks to Zak Kipling)
+    - ported to 64-bit Windows, not tested (pk)
+    - Printf/SPrintfing of std::strings added (pk)
+    - all warnings removed gcc and msvc (pk)
+    - use snprintf for "%p"
+    - test program: speed comparison added (pk)
+
+SmallObject:
+    - added functions to check for memory corruption (rs)
+    - more fine tuning (rs)
+    - warnings removed (pk)
+    
+TypeTraits:
+    - bug 1388477 fixed (pk)
+    
+flex_string:
+    - fixed compare bug by updating (Thanks to Justin Matthews, pk)
+    - fixed seg faults on Linux and Windows (pk)
+    - improved error reporting of the test program (pk)
+    
+SmartPtr:
+    - make object level locking possible (Thanks to Ryan Smith, pk)
+    
+BindFirst:
+    - store Functor arguments by value (bug 1383566) (pk)
+    
+Visitor:
+    - add support for visiting constant member functions (pk)
+    - example added (pk)
+    
+ScopeGuard:
+    - example added (pk)
+    
+    
+CVS commits by Rich Sposato (rs), Lukas Fittl (lf)
+and Peter Kümmel (pk)
+
+
+_____________________________________
+
+Version 0.1.2
+November 16, 2005
+_____________________________________
+
+General:
+    - changes to compile under Linux (Thanks to David Lawrence, pk)
+    - more doxygen documentation, modules added (rs, pk)
+
+SmartPtr:
+    - three year old bugs 626407 and 541846 fixed: 
+      Assertion with SmartPtr<T, LinkedRef> (pk)
+      SmartPtr and COMRefCounted (Thanks to James Mclaren, pk)
+
+Typelists:
+    - it's now possible to completely disable the 
+      LOKI_TYPELIST_  macros (pk)
+    - marco definitions moved to a separate file (pk)
+
+Factory:
+    - Factory now protects its private data (pk)
+    - new method to get the keys: 
+      std::vector<IdType> RegisteredIds() (pk)
+    
+Functor:
+    - TR1 methods added: empty() and clear() (pk)
+    
+Function:
+    - boost/TR1 like Function template with 
+      improved member function pointer usage (pk)
+    - tested with boost's function_test.cpp 
+
+Sequence:
+    - small change in usage: use e.g. Functor<void,Seq<bool &> > 
+      instead of Functor<void,Seq<bool &>::Type > 
+
+SmallObjects:
+    - comparison of new/malloc/std::allocator/boost::object_pool (rs, pk)
+    - #undef LOKI_SMALL_OBJECT_USE_NEW_ARRAY when using a ms compiler (pk)
+    - new lifetimes in namespace LongevityLifetime to manage dependencies: 
+      DieAsSmallObjectParent and DieAsSmallObjectClient (pk)
+    - no memory leaks when using SmallObjects (pk)
+    - new default lifetime is DieAsSmallObjectParent (pk)
+
+Threads:
+    - threads on POSIX systems (Thanks to Ilya Volvovski ,pk)
+    - small regression test program (pk)
+
+Singleton:
+    - new lifetime: FollowIntoDeath (pk)
+    - new namespace LongevityLifetime with lifetimes DieLast, DieFirst,
+      DieDirectlyBeforeLast, and function SingletonFixedLongevity (pk)
+    - new implementation for SetLongevity (pk)
+    - example programs (pk)
+    
+    
+CVS commits by Rich Sposato (rs) and Peter Kümmel (pk)
+
+
+
+_____________________________________
+
+Version 0.1.1
+October 17, 2005
+_____________________________________
+
+Singleton: 
+    - wrong ordered longevity fixed (Thanks to Kwak Jae Hyuk, pk)
+    - less warnings with msvc (Thanks to  John Bates, pk)
+    - new policy, DeletableSingleton, from Curtis Krauskopf, 
+      see also CUJ article 'Creating Dynamic Singletons & the Loki Library',(pk)
+    
+AssocVector:
+    - hinted insert does now preserve ordering (Thanks to Christopher Twigg, pk)
+    - additional 'hinted insert' test for Regression test by Christopher Twigg (pk)
+    - fix name look up (Thanks to Markus Werle, pk)
+
+SmallObj:
+     - several improvements (rs)
+     - more documentation (rs)
+     - improved SmallBench (rs, pk)
+
+Longevity:
+    - example added (pk)
+    - additional example similar to that of the book, by Curtis Krauskopf (pk)
+    
+OrderedStatic:
+    - a proposal to solve the 'static initialization ordered fiasco' problem (pk)
+
+Sequence:
+    - a proposal to replace the LOKI_TYPELIST_XX macros with a template implementation (pk)
+    - e.g.: LOKI_TYPELIST_1(int) becomes Seq<int>::Type 
+      inspired by the functional language OPAL (pk)
+            
+            
+CVS commits by Rich Sposato (rs) and Peter Kümmel (pk)
+
+
+
+_____________________________________
+
+Version 0.1.0
+September 29, 2005
+_____________________________________
+
+General:
+    - version numbering started 
+    - new directory structure 
+    - Andrei's yasli, flex_string, and SafePrint added  (pk)
+    - all macros now in the LOKI "namespace", e.g.: 
+      TYPLELIST_1 -> LOKI_TYPELIST_1  (rs, pk)
+    - Makefiles added: tested with gcc 3.4 (mingw, cygwin),
+      msvc 8.0, and the toolkit  (pk)
+    - added some documentation (rs)
+    - several bug fixes (pk)
+    - added a cvs-list to sourceforge where you can see all changes (pk)
+    
+SmallObjects:
+    - new implementation (rs)
+    
+Factory:
+    - works now with parameters (pk)
+    - regression test added (Thanks to Kalle Rutanen, pk)
+    
+TypeTraits: 
+    - isMemberPointer, isFunction added (Thanks to Kalle Rutanen, pk)
+    - regression test added (Thanks to Kalle Rutanen, pk)
+    
+Threading: 
+    - new macros for better thread support (win32):
+      LOKI_CLASS_LEVEL_THREADING and LOKI_OBJECT_LEVEL_THREADING (pk)
+
+
+CVS commits by Rich Sposato (rs) and Peter Kümmel (pk)
+
Index: /code/branches/RacingBots_FS18/src/external/loki/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,29 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET(LOKI_FILES
+  NullType.h
+  RefToValue.h
+  ScopeGuard.h
+  static_check.h
+  TypeManip.h
+  TypeTraits.h
+)
+
+ADD_CUSTOM_TARGET(loki_orxonox SOURCES ${LOKI_FILES})
Index: /code/branches/RacingBots_FS18/src/external/loki/NullType.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/NullType.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/NullType.h	(revision 11817)
@@ -0,0 +1,34 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
+//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any 
+//     purpose is hereby granted without fee, provided that the above copyright 
+//     notice appear in all copies and that both that copyright notice and this 
+//     permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the 
+//     suitability of this software for any purpose. It is provided "as is" 
+//     without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_NULLTYPE_INC_
+#define LOKI_NULLTYPE_INC_
+
+// $Id: NullType.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class NullType
+// Used as a placeholder for "no type here"
+// Useful as an end marker in typelists 
+////////////////////////////////////////////////////////////////////////////////
+
+    class NullType {};
+    
+}   // namespace Loki
+
+
+#endif // end file guardian
Index: /code/branches/RacingBots_FS18/src/external/loki/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/README	(revision 11817)
@@ -0,0 +1,63 @@
+Last update: Novmber 16, 2005
+
+Directions:
+
+To use Loki, simply extract the files from the archive, 
+give your compiler access to their include path:
+
+- if you have a standard conforming compiler use "loki/include/loki" 
+  or "loki/include" for "#include <loki/HeaderFile.h>" usage
+
+- if you have a non-conforming compiler use "loki/include/noncc/loki" 
+  or "loki/include/noncc" for "#include <loki/HeaderFile.h>" usage. 
+  The noncc files are declared as 'deprecated' and will be removed in
+  future. They are also not updated with the new features of Loki 
+  and bugfixes (unless YOU do it).
+
+
+If you use the small object allocator directly or indirectly 
+(through the Functor class) you must add src/SmallObj.cpp to your 
+project/makefile.
+
+If you use Singletons with longevity you must add 
+src/Singleton.cpp to your project/makefile.
+
+If you use OrderedStatic.h with you must add 
+src/OrderedSataic.cpp to your project/makefile.
+
+Or use the library generated by make.msvc.bat, make.mingw.bat,
+or make.
+
+
+Compatibility:
+
+Supported Compilers:
+Gcc v3.4
+Gcc v4.0
+Gcc v4.1
+Microsoft Visual C++ v7.1
+Microsoft Visual C++ v8.0
+
+by special noncc files:
+Borland C++ Builder v6.0
+Microsoft Visual C++ v6.0
+Microsoft Visual C++ v7.0
+see also readme.txt files
+
+
+Mostly Supported:
+CodeWarrior 6.0
+
+CodeWarrior has a problem with the Conversion template (see TypeManip.h) 
+and, though it compiles it, it doesn't provide correct results. 
+Consequently, the DerivedToFront algorithm in Typelist.h does not function. 
+This affects the static dispatcher in Multimethods.h. As a fix, you must 
+order the types (putting the most derived ones in the front) when providing 
+the typelist argument to StaticDispatcher.
+
+
+
+More info:
+
+Andrei's page  : http://erdani.org 
+Soureforge page: http://sourceforge.net/projects/loki-lib/
Index: /code/branches/RacingBots_FS18/src/external/loki/RefToValue.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/RefToValue.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/RefToValue.h	(revision 11817)
@@ -0,0 +1,70 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2006 Richard Sposato
+// Copyright (c) 2006 Peter Kümmel
+// Permission to use, copy, modify, distribute and sell this software for any 
+//     purpose is hereby granted without fee, provided that the above copyright 
+//     notice appear in all copies and that both that copyright notice and this 
+//     permission notice appear in supporting documentation.
+// The authors make no representations about the 
+//     suitability of this software for any purpose. It is provided "as is" 
+//     without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_REFTOVALUE_INC_
+#define LOKI_REFTOVALUE_INC_
+
+// $Id: RefToValue.h 751 2006-10-17 19:50:37Z syntheticpp $
+
+
+namespace Loki
+{
+
+    ////////////////////////////////////////////////////////////////////////////////
+    ///  \class RefToValue
+    ///
+    ///  \ingroup SmartPointerGroup 
+    ///  Transports a reference as a value
+    ///  Serves to implement the Colvin/Gibbons trick for SmartPtr/ScopeGuard
+    ////////////////////////////////////////////////////////////////////////////////
+
+    template <class T>
+    class RefToValue
+    {   
+    public:
+    
+        RefToValue(T& ref) : ref_(ref) 
+        {}
+
+        RefToValue(const RefToValue& rhs) : ref_(rhs.ref_)
+        {}
+
+        operator T& () const 
+        {
+            return ref_;
+        }
+
+    private:
+        // Disable - not implemented
+        RefToValue();
+        RefToValue& operator=(const RefToValue&);
+        
+        T& ref_;
+    };
+
+
+    ////////////////////////////////////////////////////////////////////////////////
+    ///  \ingroup ExceptionGroup 
+    ///  RefToValue creator.
+    ////////////////////////////////////////////////////////////////////////////////
+
+    template <class T>
+    inline RefToValue<T> ByRef(T& t)
+    {
+        return RefToValue<T>(t);
+    }    
+    
+}
+
+
+#endif // end file guardian
+
Index: /code/branches/RacingBots_FS18/src/external/loki/ScopeGuard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/ScopeGuard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/ScopeGuard.h	(revision 11817)
@@ -0,0 +1,670 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2000 Andrei Alexandrescu
+// Copyright (c) 2000 Petru Marginean
+// Copyright (c) 2005 Joshua Lehrer
+//
+// Permission to use, copy, modify, distribute and sell this software for any 
+//     purpose is hereby granted without fee, provided that the above copyright 
+//     notice appear in all copies and that both that copyright notice and this 
+//     permission notice appear in supporting documentation.
+// The author makes no representations about the 
+//     suitability of this software for any purpose. It is provided "as is" 
+//     without express or implied warranty.
+//
+// Changes by Orxonox (Reto Grieder)
+//     Moved one protected variable to the public section to allow the use of
+//     the ScopeGuard in a class definition.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_SCOPEGUARD_INC_
+#define LOKI_SCOPEGUARD_INC_
+
+// $Id: ScopeGuard.h 799 2006-12-20 00:37:13Z rich_sposato $
+
+
+#include <loki/RefToValue.h>
+
+/// \defgroup ExceptionGroup Exception-safe code
+
+namespace Loki
+{
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImplBase
+    /// \ingroup ExceptionGroup
+    ///
+    /// Base class used by all ScopeGuard implementations.  All commonly used
+    /// functions are in this class (e.g. - Dismiss and SafeExecute).
+    ///
+    /// See Andrei's and Petru Marginean's CUJ article
+    /// http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm
+    ///
+    /// Changes to the original code by Joshua Lehrer:
+    /// http://www.lehrerfamily.com/scopeguard.html
+    ////////////////////////////////////////////////////////////////
+
+    class ScopeGuardImplBase
+    {
+        /// Copy-assignment operator is not implemented and private.
+        ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
+
+    protected:
+
+        ~ScopeGuardImplBase()
+        {}
+
+        /// Copy-constructor takes over responsibility from other ScopeGuard.
+        ScopeGuardImplBase(const ScopeGuardImplBase& other) throw() 
+            : dismissed_(other.dismissed_)
+        {
+            other.Dismiss();
+        }
+
+        template <typename J>
+        static void SafeExecute(J& j) throw() 
+        {
+            if (!j.dismissed_)
+                try
+                {
+                    j.Execute();
+                }
+                catch(...)
+                {}
+        }
+        
+        mutable bool dismissed_;
+
+    public:
+        ScopeGuardImplBase() throw() : dismissed_(false) 
+        {}
+
+        void Dismiss() const throw() 
+        {
+            dismissed_ = true;
+        }
+    };
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \typedef typedef const ScopeGuardImplBase& ScopeGuard
+    /// \ingroup ExceptionGroup
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    typedef const ScopeGuardImplBase& ScopeGuard;
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImpl0
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a standalone function or class static function
+    /// with no parameters.  ScopeGuard ignores any value returned from the
+    /// call within the Execute function.
+    ///
+    /// This class has a single standalone helper function, MakeGuard which
+    /// creates and returns a ScopeGuard.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <typename F>
+    class ScopeGuardImpl0 : public ScopeGuardImplBase
+    {
+    public:
+        static ScopeGuardImpl0<F> MakeGuard(F fun)
+        {
+            return ScopeGuardImpl0<F>(fun);
+        }
+
+        ~ScopeGuardImpl0() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute() 
+        {
+            fun_();
+        }
+
+        ScopeGuardImpl0(F fun) : fun_(fun) 
+        {}
+
+    protected:
+        F fun_;
+    };
+
+    template <typename F> 
+    inline ScopeGuardImpl0<F> MakeGuard(F fun)
+    {
+        return ScopeGuardImpl0<F>::MakeGuard(fun);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImpl1
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a standalone function or class static function
+    /// with one parameter.  Each parameter is copied by value - use
+    /// ::Loki::ByRef if you must use a reference instead.  ScopeGuard ignores
+    /// any value returned from the call within the Execute function.
+    ///
+    /// This class has a single standalone helper function, MakeGuard which
+    /// creates and returns a ScopeGuard.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <typename F, typename P1>
+    class ScopeGuardImpl1 : public ScopeGuardImplBase
+    {
+    public:
+        static ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
+        {
+            return ScopeGuardImpl1<F, P1>(fun, p1);
+        }
+
+        ~ScopeGuardImpl1() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute()
+        {
+            fun_(p1_);
+        }
+
+        ScopeGuardImpl1(F fun, P1 p1) : fun_(fun), p1_(p1) 
+        {}
+
+    protected:
+        F fun_;
+        const P1 p1_;
+    };
+
+    template <typename F, typename P1> 
+    inline ScopeGuardImpl1<F, P1> MakeGuard(F fun, P1 p1)
+    {
+        return ScopeGuardImpl1<F, P1>::MakeGuard(fun, p1);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImpl2
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a standalone function or class static function
+    /// with two parameters.  Each parameter is copied by value - use
+    /// ::Loki::ByRef if you must use a reference instead.  ScopeGuard ignores
+    /// any value returned from the call within the Execute function.
+    ///
+    /// This class has a single standalone helper function, MakeGuard which
+    /// creates and returns a ScopeGuard.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <typename F, typename P1, typename P2>
+    class ScopeGuardImpl2: public ScopeGuardImplBase
+    {
+    public:
+        static ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
+        {
+            return ScopeGuardImpl2<F, P1, P2>(fun, p1, p2);
+        }
+
+        ~ScopeGuardImpl2() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute()
+        {
+            fun_(p1_, p2_);
+        }
+
+        ScopeGuardImpl2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2) 
+        {}
+
+    protected:
+        F fun_;
+        const P1 p1_;
+        const P2 p2_;
+    };
+
+    template <typename F, typename P1, typename P2>
+    inline ScopeGuardImpl2<F, P1, P2> MakeGuard(F fun, P1 p1, P2 p2)
+    {
+        return ScopeGuardImpl2<F, P1, P2>::MakeGuard(fun, p1, p2);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImpl3
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a standalone function or class static function
+    /// with three parameters.  Each parameter is copied by value - use
+    /// ::Loki::ByRef if you must use a reference instead.  ScopeGuard ignores
+    /// any value returned from the call within the Execute function.
+    ///
+    /// This class has a single standalone helper function, MakeGuard which
+    /// creates and returns a ScopeGuard.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <typename F, typename P1, typename P2, typename P3>
+    class ScopeGuardImpl3 : public ScopeGuardImplBase
+    {
+    public:
+        static ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
+        {
+            return ScopeGuardImpl3<F, P1, P2, P3>(fun, p1, p2, p3);
+        }
+
+        ~ScopeGuardImpl3() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute()
+        {
+            fun_(p1_, p2_, p3_);
+        }
+
+        ScopeGuardImpl3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3) 
+        {}
+
+    protected:
+        F fun_;
+        const P1 p1_;
+        const P2 p2_;
+        const P3 p3_;
+    };
+
+    template <typename F, typename P1, typename P2, typename P3>
+    inline ScopeGuardImpl3<F, P1, P2, P3> MakeGuard(F fun, P1 p1, P2 p2, P3 p3)
+    {
+        return ScopeGuardImpl3<F, P1, P2, P3>::MakeGuard(fun, p1, p2, p3);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImpl4
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a standalone function or class static function
+    /// with four parameters.  Each parameter is copied by value - use
+    /// ::Loki::ByRef if you must use a reference instead.  ScopeGuard ignores
+    /// any value returned from the call within the Execute function.
+    ///
+    /// This class has a single standalone helper function, MakeGuard which
+    /// creates and returns a ScopeGuard.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template < typename F, typename P1, typename P2, typename P3, typename P4 >
+    class ScopeGuardImpl4 : public ScopeGuardImplBase
+    {
+    public:
+        static ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard(
+            F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
+        {
+            return ScopeGuardImpl4< F, P1, P2, P3, P4 >( fun, p1, p2, p3, p4 );
+        }
+
+        ~ScopeGuardImpl4() throw() 
+        {
+            SafeExecute( *this );
+        }
+
+        void Execute()
+        {
+            fun_( p1_, p2_, p3_, p4_ );
+        }
+
+        ScopeGuardImpl4( F fun, P1 p1, P2 p2, P3 p3, P4 p4 ) :
+             fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 )
+        {}
+
+    protected:
+        F fun_;
+        const P1 p1_;
+        const P2 p2_;
+        const P3 p3_;
+        const P4 p4_;
+    };
+
+    template < typename F, typename P1, typename P2, typename P3, typename P4 >
+    inline ScopeGuardImpl4< F, P1, P2, P3, P4 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4 )
+    {
+        return ScopeGuardImpl4< F, P1, P2, P3, P4 >::MakeGuard( fun, p1, p2, p3, p4 );
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ScopeGuardImpl5
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a standalone function or class static function
+    /// with five parameters.  Each parameter is copied by value - use
+    /// ::Loki::ByRef if you must use a reference instead.  ScopeGuard ignores
+    /// any value returned from the call within the Execute function.
+    ///
+    /// This class has a single standalone helper function, MakeGuard which
+    /// creates and returns a ScopeGuard.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
+    class ScopeGuardImpl5 : public ScopeGuardImplBase
+    {
+    public:
+        static ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard(
+            F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
+        {
+            return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >( fun, p1, p2, p3, p4, p5 );
+        }
+
+        ~ScopeGuardImpl5() throw() 
+        {
+            SafeExecute( *this );
+        }
+
+        void Execute()
+        {
+            fun_( p1_, p2_, p3_, p4_, p5_ );
+        }
+
+        ScopeGuardImpl5( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 ) :
+             fun_( fun ), p1_( p1 ), p2_( p2 ), p3_( p3 ), p4_( p4 ), p5_( p5 )
+        {}
+
+    protected:
+        F fun_;
+        const P1 p1_;
+        const P2 p2_;
+        const P3 p3_;
+        const P4 p4_;
+        const P5 p5_;
+    };
+
+    template < typename F, typename P1, typename P2, typename P3, typename P4, typename P5 >
+    inline ScopeGuardImpl5< F, P1, P2, P3, P4, P5 > MakeGuard( F fun, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5 )
+    {
+        return ScopeGuardImpl5< F, P1, P2, P3, P4, P5 >::MakeGuard( fun, p1, p2, p3, p4, p5 );
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ObjScopeGuardImpl0
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a class per-instance member function with no
+    /// parameters.  ScopeGuard ignores any value returned from the call within
+    /// the Execute function.
+    ///
+    /// This class has 3 standalone helper functions which create a ScopeGuard.
+    /// One is MakeObjGuard, which is deprecated but provided for older code.
+    /// The other two are MakeGuard overloads, one which takes a pointer to an
+    /// object, and the other which takes a reference.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <class Obj, typename MemFun>
+    class ObjScopeGuardImpl0 : public ScopeGuardImplBase
+    {
+    public:
+        static ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
+        {
+            return ObjScopeGuardImpl0<Obj, MemFun>(obj, memFun);
+        }
+
+        ~ObjScopeGuardImpl0() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute() 
+        {
+            (obj_.*memFun_)();
+        }
+
+        ObjScopeGuardImpl0(Obj& obj, MemFun memFun) : obj_(obj), memFun_(memFun) 
+        {}
+
+    protected:
+        Obj& obj_;
+        MemFun memFun_;
+    };
+
+    template <class Obj, typename MemFun>
+    inline ObjScopeGuardImpl0<Obj, MemFun> MakeObjGuard(Obj& obj, MemFun memFun)
+    {
+        return ObjScopeGuardImpl0<Obj, MemFun>::MakeObjGuard(obj, memFun);
+    }
+
+    template <typename Ret, class Obj1, class Obj2>
+    inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 &obj) 
+    {
+      return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(obj,memFun);
+    }
+
+    template <typename Ret, class Obj1, class Obj2>
+    inline ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()> MakeGuard(Ret(Obj2::*memFun)(), Obj1 *obj) 
+    {
+      return ObjScopeGuardImpl0<Obj1,Ret(Obj2::*)()>::MakeObjGuard(*obj,memFun);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ObjScopeGuardImpl1
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a class per-instance member function with one
+    /// parameter.  The parameter is copied by value - use ::Loki::ByRef if you
+    /// must use a reference instead.  ScopeGuard ignores any value returned
+    /// from the call within the Execute function.
+    ///
+    /// This class has 3 standalone helper functions which create a ScopeGuard.
+    /// One is MakeObjGuard, which is deprecated but provided for older code.
+    /// The other two are MakeGuard overloads, one which takes a pointer to an
+    /// object, and the other which takes a reference.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <class Obj, typename MemFun, typename P1>
+    class ObjScopeGuardImpl1 : public ScopeGuardImplBase
+    {
+    public:
+        static ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
+        {
+            return ObjScopeGuardImpl1<Obj, MemFun, P1>(obj, memFun, p1);
+        }
+
+        ~ObjScopeGuardImpl1() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute() 
+        {
+            (obj_.*memFun_)(p1_);
+        }
+
+        ObjScopeGuardImpl1(Obj& obj, MemFun memFun, P1 p1) : obj_(obj), memFun_(memFun), p1_(p1) 
+        {}
+        
+    protected:
+        Obj& obj_;
+        MemFun memFun_;
+        const P1 p1_;
+    };
+
+    template <class Obj, typename MemFun, typename P1>
+    inline ObjScopeGuardImpl1<Obj, MemFun, P1> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1)
+    {
+        return ObjScopeGuardImpl1<Obj, MemFun, P1>::MakeObjGuard(obj, memFun, p1);
+    }
+
+    template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
+    inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 &obj, P1b p1) 
+    {
+      return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(obj,memFun,p1);
+    }
+
+    template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b>
+    inline ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b> MakeGuard(Ret(Obj2::*memFun)(P1a), Obj1 *obj, P1b p1) 
+    {
+      return ObjScopeGuardImpl1<Obj1,Ret(Obj2::*)(P1a),P1b>::MakeObjGuard(*obj,memFun,p1);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ObjScopeGuardImpl2
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a class per-instance member function with two
+    /// parameters.  Each parameter is copied by value - use ::Loki::ByRef if you
+    /// must use a reference instead.  ScopeGuard ignores any value returned
+    /// from the call within the Execute function.
+    ///
+    /// This class has 3 standalone helper functions which create a ScopeGuard.
+    /// One is MakeObjGuard, which is deprecated but provided for older code.
+    /// The other two are MakeGuard overloads, one which takes a pointer to an
+    /// object, and the other which takes a reference.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template <class Obj, typename MemFun, typename P1, typename P2>
+    class ObjScopeGuardImpl2 : public ScopeGuardImplBase
+    {
+    public:
+        static ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
+        {
+            return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
+        }
+
+        ~ObjScopeGuardImpl2() throw() 
+        {
+            SafeExecute(*this);
+        }
+
+        void Execute() 
+        {
+            (obj_.*memFun_)(p1_, p2_);
+        }
+
+        ObjScopeGuardImpl2(Obj& obj, MemFun memFun, P1 p1, P2 p2) : obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) 
+        {}
+
+    protected:
+        Obj& obj_;
+        MemFun memFun_;
+        const P1 p1_;
+        const P2 p2_;
+    };
+
+    template <class Obj, typename MemFun, typename P1, typename P2>
+    inline ObjScopeGuardImpl2<Obj, MemFun, P1, P2> MakeObjGuard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
+    {
+        return ObjScopeGuardImpl2<Obj, MemFun, P1, P2>::MakeObjGuard(obj, memFun, p1, p2);
+    }
+
+    template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
+    inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 &obj, P1b p1, P2b p2) 
+    {
+      return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(obj,memFun,p1,p2);
+    }
+
+    template <typename Ret, class Obj1, class Obj2, typename P1a, typename P1b, typename P2a, typename P2b>
+    inline ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b> MakeGuard(Ret(Obj2::*memFun)(P1a,P2a), Obj1 *obj, P1b p1, P2b p2) 
+    {
+      return ObjScopeGuardImpl2<Obj1,Ret(Obj2::*)(P1a,P2a),P1b,P2b>::MakeObjGuard(*obj,memFun,p1,p2);
+    }
+
+    ////////////////////////////////////////////////////////////////
+    ///
+    /// \class ObjScopeGuardImpl3
+    /// \ingroup ExceptionGroup
+    ///
+    /// Implementation class for a class per-instance member function with three
+    /// parameters.  Each parameter is copied by value - use ::Loki::ByRef if you
+    /// must use a reference instead.  ScopeGuard ignores any value returned
+    /// from the call within the Execute function.
+    ///
+    /// This class has 3 standalone helper functions which create a ScopeGuard.
+    /// One is MakeObjGuard, which is deprecated but provided for older code.
+    /// The other two are MakeGuard overloads, one which takes a pointer to an
+    /// object, and the other which takes a reference.
+    ///
+    ////////////////////////////////////////////////////////////////
+
+    template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
+    class ObjScopeGuardImpl3 : public ScopeGuardImplBase
+    {
+    public:
+        static ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
+            Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
+        {
+            return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >( obj, memFun, p1, p2, p3 );
+        }
+
+        ~ObjScopeGuardImpl3() throw() 
+        {
+            SafeExecute( *this );
+        }
+
+        void Execute() 
+        {
+            ( obj_.*memFun_ )( p1_, p2_, p3_ );
+        }
+
+        ObjScopeGuardImpl3( Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 ) :
+             obj_( obj ), memFun_( memFun ), p1_( p1 ), p2_( p2 ), p3_( p3 )
+        {}
+
+    protected:
+        Obj& obj_;
+        MemFun memFun_;
+        const P1 p1_;
+        const P2 p2_;
+        const P3 p3_;
+    };
+
+    template < class Obj, typename MemFun, typename P1, typename P2, typename P3 >
+    inline ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 > MakeObjGuard(
+        Obj & obj, MemFun memFun, P1 p1, P2 p2, P3 p3 )
+    {
+        return ObjScopeGuardImpl3< Obj, MemFun, P1, P2, P3 >::MakeObjGuard(
+            obj, memFun, p1, p2, p3 );
+    }
+
+    template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
+        typename P2a, typename P2b, typename P3a, typename P3b >
+    inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+        MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 & obj, P1b p1, P2b p2, P3b p3 )
+    {
+      return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+          ::MakeObjGuard( obj, memFun, p1, p2, p3 );
+    }
+
+    template < typename Ret, class Obj1, class Obj2, typename P1a, typename P1b,
+        typename P2a, typename P2b, typename P3a, typename P3b >
+    inline ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+        MakeGuard( Ret( Obj2::*memFun )( P1a, P2a, P3a ), Obj1 * obj, P1b p1, P2b p2, P3b p3 )
+    {
+      return ObjScopeGuardImpl3< Obj1, Ret( Obj2::* )( P1a, P2a, P3a ), P1b, P2b, P3b >
+          ::MakeObjGuard( *obj, memFun, p1, p2, p3 );
+    }
+
+} // namespace Loki
+
+#define LOKI_CONCATENATE_DIRECT(s1, s2)  s1##s2
+#define LOKI_CONCATENATE(s1, s2)         LOKI_CONCATENATE_DIRECT(s1, s2)
+#define LOKI_ANONYMOUS_VARIABLE(str)     LOKI_CONCATENATE(str, __LINE__)
+
+#define LOKI_ON_BLOCK_EXIT      ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeGuard
+#define LOKI_ON_BLOCK_EXIT_OBJ  ::Loki::ScopeGuard LOKI_ANONYMOUS_VARIABLE(scopeGuard) = ::Loki::MakeObjGuard
+
+#endif // end file guardian
+
Index: /code/branches/RacingBots_FS18/src/external/loki/TypeManip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/TypeManip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/TypeManip.h	(revision 11817)
@@ -0,0 +1,98 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
+//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any 
+//     purpose is hereby granted without fee, provided that the above copyright 
+//     notice appear in all copies and that both that copyright notice and this 
+//     permission notice appear in supporting documentation.
+// The author or Addison-Welsey Longman make no representations about the 
+//     suitability of this software for any purpose. It is provided "as is" 
+//     without express or implied warranty.
+//
+// Changes by Orxonox (Reto Grieder)
+//     Removed templates we didn't need
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_TYPEMANIP_INC_
+#define LOKI_TYPEMANIP_INC_
+
+// $Id: TypeManip.h 749 2006-10-17 19:49:26Z syntheticpp $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template Int2Type
+// Converts each integral constant into a unique type
+// Invocation: Int2Type<v> where v is a compile-time constant integral
+// Defines 'value', an enum that evaluates to v
+////////////////////////////////////////////////////////////////////////////////
+
+    template <int v>
+    struct Int2Type
+    {
+        enum { value = v };
+    };
+    
+////////////////////////////////////////////////////////////////////////////////
+// class template Type2Type
+// Converts each type into a unique, insipid type
+// Invocation Type2Type<T> where T is a type
+// Defines the type OriginalType which maps back to T
+////////////////////////////////////////////////////////////////////////////////
+
+    template <typename T>
+    struct Type2Type
+    {
+        typedef T OriginalType;
+    };
+    
+////////////////////////////////////////////////////////////////////////////////
+// class template Select
+// Selects one of two types based upon a boolean constant
+// Invocation: Select<flag, T, U>::Result
+// where:
+// flag is a compile-time boolean constant
+// T and U are types
+// Result evaluates to T if flag is true, and to U otherwise.
+////////////////////////////////////////////////////////////////////////////////
+
+    template <bool flag, typename T, typename U>
+    struct Select
+    {
+        typedef T Result;
+    };
+    template <typename T, typename U>
+    struct Select<false, T, U>
+    {
+        typedef U Result;
+    };
+    
+////////////////////////////////////////////////////////////////////////////////
+// class template IsSameType
+// Return true iff two given types are the same
+// Invocation: SameType<T, U>::value
+// where:
+// T and U are types
+// Result evaluates to true iff U == T (types equal)
+////////////////////////////////////////////////////////////////////////////////
+
+    template <typename T, typename U>
+    struct IsSameType
+    {
+        enum { value = false };
+    };
+    
+    template <typename T>
+    struct IsSameType<T,T>
+    {
+        enum { value = true };
+    };
+
+}   // namespace Loki
+
+
+#endif // end file guardian
+
Index: /code/branches/RacingBots_FS18/src/external/loki/TypeTraits.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/TypeTraits.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/TypeTraits.h	(revision 11817)
@@ -0,0 +1,279 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
+//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any
+//     purpose is hereby granted without fee, provided that the above copyright
+//     notice appear in all copies and that both that copyright notice and this
+//     permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the
+//     suitability of this software for any purpose. It is provided "as is"
+//     without express or implied warranty.
+//
+// Changes by Orxonox (Reto Grieder)
+//     Removed all stdInt, etc. type traits and function pointer traits
+//     and added UnqualifiedReferredType.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_TYPETRAITS_INC_
+#define LOKI_TYPETRAITS_INC_
+
+// $Id: TypeTraits.h 1069 2010-04-19 03:09:59Z rich_sposato $
+
+
+#include <loki/NullType.h>
+
+#if (defined _MSC_VER) && (_MSC_VER < 1400)
+#include <string>
+#endif
+
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4180 ) //qualifier applied to function type has no meaning; ignored
+#endif
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// class template IsCustomUnsignedInt
+// Offers a means to integrate nonstandard built-in unsigned integral types
+// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
+//     class template defined below.
+// Invocation: IsCustomUnsignedInt<T> where T is any type
+// Defines 'value', an enum that is 1 iff T is a custom built-in unsigned
+//     integral type
+// Specialize this class template for nonstandard unsigned integral types
+//     and define value = 1 in those specializations
+////////////////////////////////////////////////////////////////////////////////
+
+    template <typename T>
+    struct IsCustomUnsignedInt
+    {
+        enum { value = 0 };
+    };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template IsCustomSignedInt
+// Offers a means to integrate nonstandard built-in unsigned integral types
+// (such as unsigned __int64 or unsigned long long int) with the TypeTraits
+//     class template defined below.
+// Invocation: IsCustomSignedInt<T> where T is any type
+// Defines 'value', an enum that is 1 iff T is a custom built-in signed
+//     integral type
+// Specialize this class template for nonstandard unsigned integral types
+//     and define value = 1 in those specializations
+////////////////////////////////////////////////////////////////////////////////
+
+    template <typename T>
+    struct IsCustomSignedInt
+    {
+        enum { value = 0 };
+    };
+
+////////////////////////////////////////////////////////////////////////////////
+// class template IsCustomFloat
+// Offers a means to integrate nonstandard floating point types with the
+//     TypeTraits class template defined below.
+// Invocation: IsCustomFloat<T> where T is any type
+// Defines 'value', an enum that is 1 iff T is a custom built-in
+//     floating point type
+// Specialize this class template for nonstandard unsigned integral types
+//     and define value = 1 in those specializations
+////////////////////////////////////////////////////////////////////////////////
+
+    template <typename T>
+    struct IsCustomFloat
+    {
+        enum { value = 0 };
+    };
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper types for class template TypeTraits defined below
+////////////////////////////////////////////////////////////////////////////////
+
+    namespace Private
+    {
+        template <typename U> struct AddPointer
+        {
+            typedef U* Result;
+        };
+
+        template <typename U> struct AddPointer<U&>
+        {
+            typedef U* Result;
+        };
+
+        template <class U> struct AddReference
+        {
+            typedef U & Result;
+        };
+
+        template <class U> struct AddReference<U &>
+        {
+            typedef U & Result;
+        };
+
+        template <> struct AddReference<void>
+        {
+            typedef NullType Result;
+        };
+
+        template <class U> struct AddParameterType
+        {
+            typedef const U & Result;
+        };
+
+        template <class U> struct AddParameterType<U &>
+        {
+            typedef U & Result;
+        };
+
+        template <> struct AddParameterType<void>
+        {
+            typedef NullType Result;
+        };
+    }// namespace Private
+
+////////////////////////////////////////////////////////////////////////////////
+// class template TypeTraits
+//
+// Figures out at compile time various properties of any given type
+// Invocations (T is a type, TypeTraits<T>::Property):
+//
+// - isPointer       : returns true if T is a pointer type
+// - PointeeType     : returns the type to which T points if T is a pointer
+//                     type, NullType otherwise
+// - isReference     : returns true if T is a reference type
+// - ReferredType    : returns the type to which T refers if T is a reference
+//                     type, NullType otherwise
+// - ParameterType   : returns the optimal type to be used as a parameter for
+//                     functions that take Ts
+// - isConst         : returns true if T is a const-qualified type
+// - NonConstType    : Type with removed 'const' qualifier from T, if any
+// - isVolatile      : returns true if T is a volatile-qualified type
+// - NonVolatileType : Type with removed 'volatile' qualifier from T, if any
+// - UnqualifiedType : Type with removed 'const' and 'volatile' qualifiers from
+//                     T, if any
+// - ParameterType   : returns the optimal type to be used as a parameter
+//                       for functions that take 'const T's
+//
+////////////////////////////////////////////////////////////////////////////////
+
+    template <typename T>
+    class TypeTraits
+    {
+    private:
+
+        template <class U> struct ReferenceTraits
+        {
+            enum { result = false };
+            typedef U ReferredType;
+        };
+
+        template <class U> struct ReferenceTraits<U&>
+        {
+            enum { result = true };
+            typedef U ReferredType;
+        };
+
+        template <class U> struct PointerTraits
+        {
+            enum { result = false };
+            typedef NullType PointeeType;
+        };
+
+        template <class U> struct PointerTraits<U*>
+        {
+            enum { result = true };
+            typedef U PointeeType;
+        };
+
+        template <class U> struct PointerTraits<U*&>
+        {
+            enum { result = true };
+            typedef U PointeeType;
+        };
+
+        template <class U> struct PToMTraits
+        {
+            enum { result = false };
+        };
+
+        template <class U, class V> struct PToMTraits<U V::*>
+        {
+            enum { result = true };
+        };
+
+        template <class U, class V> struct PToMTraits<U V::*&>
+        {
+            enum { result = true };
+        };
+
+        template <class U> struct UnConst
+        {
+            typedef U Result;
+            enum { isConst = 0 };
+        };
+
+        template <class U> struct UnConst<const U>
+        {
+            typedef U Result;
+            enum { isConst = 1 };
+        };
+
+        template <class U> struct UnConst<const U&>
+        {
+            typedef U& Result;
+            enum { isConst = 1 };
+        };
+
+        template <class U> struct UnVolatile
+        {
+            typedef U Result;
+            enum { isVolatile = 0 };
+        };
+
+        template <class U> struct UnVolatile<volatile U>
+        {
+            typedef U Result;
+            enum { isVolatile = 1 };
+        };
+
+        template <class U> struct UnVolatile<volatile U&>
+        {
+            typedef U& Result;
+            enum { isVolatile = 1 };
+        };
+
+    public:
+        typedef typename UnConst<T>::Result
+            NonConstType;
+        typedef typename UnVolatile<T>::Result
+            NonVolatileType;
+        typedef typename UnVolatile<typename UnConst<T>::Result>::Result
+            UnqualifiedType;
+        typedef typename PointerTraits<UnqualifiedType>::PointeeType
+            PointeeType;
+        typedef typename ReferenceTraits<T>::ReferredType
+            ReferredType;
+        typedef typename ReferenceTraits<typename UnVolatile<typename UnConst<T>::Result>::Result>::ReferredType
+            UnqualifiedReferredType;
+
+        enum { isConst          = UnConst<T>::isConst };
+        enum { isVolatile       = UnVolatile<T>::isVolatile };
+        enum { isReference      = ReferenceTraits<UnqualifiedType>::result };
+        enum { isPointer        = PointerTraits<
+                                        typename ReferenceTraits<UnqualifiedType>::ReferredType >::result};
+
+    };
+}
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif // _MSC_VER
+
+
+#endif // end file guardian
+
Index: /code/branches/RacingBots_FS18/src/external/loki/changes_orxonox.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/changes_orxonox.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/changes_orxonox.txt	(revision 11817)
@@ -0,0 +1,7 @@
+Many changes have been applied, mostly cutting out unneeded parts of the source.
+There is one actual code change in ScopeGuard.h (see file).
+
+Moreover the files in this folder only represent a small portion of the Loki library.
+
+VERSION:
+The files are based on revision 1069 of the official Loki Subversion repository.
Index: /code/branches/RacingBots_FS18/src/external/loki/static_check.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/loki/static_check.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/loki/static_check.h	(revision 11817)
@@ -0,0 +1,45 @@
+////////////////////////////////////////////////////////////////////////////////
+// The Loki Library
+// Copyright (c) 2001 by Andrei Alexandrescu
+// This code accompanies the book:
+// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
+//     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
+// Permission to use, copy, modify, distribute and sell this software for any 
+//     purpose is hereby granted without fee, provided that the above copyright 
+//     notice appear in all copies and that both that copyright notice and this 
+//     permission notice appear in supporting documentation.
+// The author or Addison-Wesley Longman make no representations about the 
+//     suitability of this software for any purpose. It is provided "as is" 
+//     without express or implied warranty.
+////////////////////////////////////////////////////////////////////////////////
+#ifndef LOKI_STATIC_CHECK_INC_
+#define LOKI_STATIC_CHECK_INC_
+
+// $Id: static_check.h 982 2009-01-31 07:51:27Z rich_sposato $
+
+
+namespace Loki
+{
+////////////////////////////////////////////////////////////////////////////////
+// Helper structure for the STATIC_CHECK macro
+////////////////////////////////////////////////////////////////////////////////
+
+    template<int> struct CompileTimeError;
+    template<> struct CompileTimeError<true> {};
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// macro LOKI_STATIC_CHECK
+// Invocation: LOKI_STATIC_CHECK(expr, id)
+// where:
+// expr is a compile-time integral or pointer expression
+// id is a C++ identifier that does not need to be defined
+// If expr is zero, id will appear in a compile-time error message.
+////////////////////////////////////////////////////////////////////////////////
+
+#define LOKI_STATIC_CHECK(expr, msg) \
+    { Loki::CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } 
+
+
+#endif // end file guardian
+
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/AUTHORS
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/AUTHORS	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/AUTHORS	(revision 11817)
@@ -0,0 +1,106 @@
+AUTHORS
+=======
+
+OGRE Team 
+---------
+Steve Streeting	(sinbad)              
+Thomas Muldowney (temas)
+James O'Sullivan (_mental_)
+Wladimir J. van der Laan (miathan6/wumpus)
+
+Feature Contributors
+--------------------
+The following list includes developers who have contributed features to OGRE:
+
+Contributor                             Subject Areas 
+-----------                             --------------------------------------
+Adrian Cearnau (cearny)               : Codecs, dynamic library loading
+Jon Anderson (janders)                : octree plugin
+Martin Persson                        : Nature plugin
+Jesse Rusak (jder) 	  				  : Mac OSX port
+Etienne Mallard (earthquakeproof)	  : 3D Studio Model Exporter
+Banania								  : ditto
+Paolo Gavocanov (cTh) 				  : Initial D3D9 port, Meshviewer, 
+                                        3D Studio Scene Exporter
+Ivica Aracic (macross/bytelord)       : Ogre4J, Maya exporter, .scene format
+Jeff Leigh							  : Sky enhancements, debug overlay
+Jose A Milan (jamilan/spoke)          : Paging landscape plugin
+Tuan Kuranes (kuranes)                : ditto
+Stephan Kaiser (psyclonist)           : OgreFsrad, OgreLMTS, .scene format
+Philippe Culet                        : Attaching objects to bones
+Jon L. Griffeth (silent3)             : GUI enhancements
+Dan Sonnemann (oberleutnantdan)       : Timers
+Amit Mathew                           : Profiler
+Dennis Verbeek                        : Lightwave exporter
+David Whittaker                       : Displacement mapping terrain
+Chris Groskopf (staringmonkey)        : OgreTok
+Jeff Doyle (nfz)                      : ATI_fragment_shader compiler, 
+                                        paging landscape
+Patrick Kooman                        : Overlay editor
+Doug Wolanick (icetec)                : DotSceneOctree exporter & plugin
+John Van Vliet (granite/fifty1)       : Maya exporter
+Marcin Zukowski (eru)                 : Demo_CubeMapping and Demo_Water
+Jens Hoffmann                         : Blender exporter
+Michael Reimpell                      : Blender exporter
+Sam le Pirate                         : BMP support
+Attila Tajti (attis)                  : Wings3D exporter
+? (Firestorm)                         : Particle scale and rotate affectors
+Lee Sandberg                          : Hardware occlusion query support
+Phillip Castaneda (pjcast)            : External texture sources / dynamic
+										textures
+Henry Goffin (qsilver)				  : Ultra-fast scaling code in 
+										OgreImageResampler.h
+Federico Di Gregorio (fog)			  : Debian packaging
+
+Others
+------
+The following people have been notable in their support of OGRE through the
+fixing of bugs, testing patches, and various other miscellaneous contributions:
+
+Timo Keller (norondion) 
+Kai-Peter Backman
+Daniel Wessl?n
+Benny Kramek (wolfman8k) 
+Riku Nurminen (rakkis)
+Christopher John Gilbert (thegilb)
+Martin Pollard (xmp)
+Nikita Mikros (santanopoulos)
+Chris Heald (antiarc)
+Michael Casaday
+Evgeni Popov
+Chris McGuirk (leedgitar)
+Te'ja (thiveertm)
+Keith Jackson
+G Nikolakis
+Genva
+Christian Lindequist Larsen (DWORD)
+Chris Heald (Antiarc)
+Green Eyed Monster (monster)
+
+
+
+
+If we've forgotten you in the above list, please contact us!
+
+See Readme.html in the Docs folder for more details, in particular information on the media supplied with the demos.
+
+-----
+
+Copyright 1999-2004 The OGRE Team.
+
+This file is part of OGRE (Object-Oriented Graphics Rendering Engine).
+
+OGRE is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+OGRE 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 Lesser General Public License
+along with OGRE; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,39 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(OCR_FILES
+  OgreCEGUIRenderer.h
+  OgreCEGUIResourceProvider.h
+  OgreCEGUITexture.h
+
+  OgreCEGUIRenderer.cpp
+  OgreCEGUIResourceProvider.cpp
+  OgreCEGUITexture.cpp
+)
+
+ORXONOX_ADD_LIBRARY(ogreceguirenderer_orxonox
+  ORXONOX_EXTERNAL
+  DEFINE_SYMBOL
+    "OGRE_GUIRENDERER_EXPORTS"
+  LINK_LIBRARIES
+    ${OGRE_LIBRARY}
+    ${CEGUI_LIBRARY}
+  SOURCE_FILES
+    ${OCR_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/COPYING
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/COPYING	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/COPYING	(revision 11817)
@@ -0,0 +1,514 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIRenderer.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIRenderer.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIRenderer.cpp	(revision 11817)
@@ -0,0 +1,792 @@
+/************************************************************************
+	filename: 	OgreCEGUIRenderer.cpp
+	created:	11/5/2004
+	author:		Paul D Turner
+	
+	purpose:	Implementation of Renderer class for Ogre engine
+*************************************************************************/
+/*************************************************************************
+    Crazy Eddie's GUI System (http://www.cegui.org.uk)
+    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*************************************************************************/
+
+// Workaround for GCC 4.6
+#include <cstddef>
+
+#include <CEGUIImagesetManager.h>
+#include <CEGUIImageset.h>
+#include <CEGUIImage.h>
+#include <CEGUIExceptions.h>
+#include <CEGUISystem.h>
+
+#include "OgreCEGUIRenderer.h"
+#include "OgreCEGUITexture.h"
+#include "OgreCEGUIResourceProvider.h"
+
+#include <OgreRenderSystem.h>
+#include <OgreRoot.h>
+#include <OgreHardwareBufferManager.h>
+#include <OgreRenderWindow.h>
+
+// Start of CEGUI namespace section
+namespace CEGUI
+{
+/*************************************************************************
+	Constants definitions
+*************************************************************************/
+const size_t	OgreCEGUIRenderer::VERTEX_PER_QUAD			= 6;
+const size_t	OgreCEGUIRenderer::VERTEX_PER_TRIANGLE		= 3;
+const size_t	OgreCEGUIRenderer::VERTEXBUFFER_INITIAL_CAPACITY	= 256;
+const size_t    OgreCEGUIRenderer::UNDERUSED_FRAME_THRESHOLD = 50000; // halfs buffer every 8 minutes on 100fps
+
+/*************************************************************************
+	Utility function to create a render operation and vertex buffer to render quads
+*************************************************************************/
+static void createQuadRenderOp(Ogre::RenderOperation &d_render_op, 
+    Ogre::HardwareVertexBufferSharedPtr &d_buffer, size_t nquads)
+{
+    using namespace Ogre;
+    // Create and initialise the Ogre specific parts required for use in rendering later.
+	d_render_op.vertexData = new VertexData;
+	d_render_op.vertexData->vertexStart = 0;
+
+	// setup vertex declaration for the vertex format we use
+	VertexDeclaration* vd = d_render_op.vertexData->vertexDeclaration;
+	size_t vd_offset = 0;
+	vd->addElement(0, vd_offset, VET_FLOAT3, VES_POSITION);
+	vd_offset += VertexElement::getTypeSize(VET_FLOAT3);
+	vd->addElement(0, vd_offset, VET_COLOUR, VES_DIFFUSE);
+	vd_offset += VertexElement::getTypeSize(VET_COLOUR);
+	vd->addElement(0, vd_offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
+
+	// create hardware vertex buffer
+	d_buffer = HardwareBufferManager::getSingleton().createVertexBuffer(vd->getVertexSize(0), nquads,  
+        HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE, false);
+
+	// bind vertex buffer
+	d_render_op.vertexData->vertexBufferBinding->setBinding(0, d_buffer);
+
+	// complete render operation basic initialisation
+	d_render_op.operationType = RenderOperation::OT_TRIANGLE_LIST;
+	d_render_op.useIndexes = false;
+}
+
+static void destroyQuadRenderOp(Ogre::RenderOperation &d_render_op, 
+    Ogre::HardwareVertexBufferSharedPtr &d_buffer)
+{
+    delete d_render_op.vertexData;
+    d_render_op.vertexData = 0;
+    d_buffer.setNull();
+}
+
+/*************************************************************************
+	Constructor
+*************************************************************************/
+OgreCEGUIRenderer::OgreCEGUIRenderer(Ogre::RenderWindow* window, Ogre::uint8 queue_id, bool post_queue, uint max_quads)
+{
+	constructor_impl(window, queue_id, post_queue, max_quads);
+}
+
+
+/*************************************************************************
+	Constructor (specifying scene manager)
+*************************************************************************/
+OgreCEGUIRenderer::OgreCEGUIRenderer(Ogre::RenderWindow* window, Ogre::uint8 queue_id, bool post_queue, uint max_quads, Ogre::SceneManager* scene_manager)
+{
+	constructor_impl(window, queue_id, post_queue, max_quads);
+
+	// hook into ogre rendering system
+	setTargetSceneManager(scene_manager);
+}
+
+
+/*************************************************************************
+	Destructor
+*************************************************************************/
+OgreCEGUIRenderer::~OgreCEGUIRenderer(void)
+{
+	setTargetSceneManager(NULL);
+
+	if (d_ourlistener)
+	{
+		delete d_ourlistener;
+	}
+
+	// cleanup vertex data we allocated in constructor
+	destroyQuadRenderOp(d_render_op, d_buffer);
+    destroyQuadRenderOp(d_direct_render_op, d_direct_buffer);
+
+	destroyAllTextures();
+}
+
+
+/*************************************************************************
+	add's a quad to the list to be rendered
+*************************************************************************/
+void OgreCEGUIRenderer::addQuad(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
+{
+	// if not queueing, render directly (as in, right now!). This is used for the mouse cursor.
+	if (!d_queueing)
+	{
+		renderQuadDirect(dest_rect, z, tex, texture_rect, colours, quad_split_mode);
+	}
+	else
+	{
+		d_sorted = false;
+		QuadInfo quad;
+		
+		// set quad position, flipping y co-ordinates, and applying appropriate texel origin offset
+		quad.position.d_left	= dest_rect.d_left;
+		quad.position.d_right	= dest_rect.d_right;
+		quad.position.d_top		= d_display_area.getHeight() - dest_rect.d_top;
+		quad.position.d_bottom	= d_display_area.getHeight() - dest_rect.d_bottom;
+		quad.position.offset(d_texelOffset);
+
+		// convert quad co-ordinates for a -1 to 1 co-ordinate system.
+		quad.position.d_left	/= (d_display_area.getWidth() * 0.5f);
+		quad.position.d_right	/= (d_display_area.getWidth() * 0.5f);
+		quad.position.d_top		/= (d_display_area.getHeight() * 0.5f);
+		quad.position.d_bottom	/= (d_display_area.getHeight() * 0.5f);
+		quad.position.offset(Point(-1.0f, -1.0f));
+
+		quad.z				= -1 + z;
+		quad.texture		= ((OgreCEGUITexture*)tex)->getOgreTexture();
+		quad.texPosition	= texture_rect;
+
+		// covert colours for ogre, note that top / bottom are switched.
+		quad.topLeftCol		= colourToOgre(colours.d_bottom_left);
+		quad.topRightCol	= colourToOgre(colours.d_bottom_right);
+		quad.bottomLeftCol	= colourToOgre(colours.d_top_left);
+		quad.bottomRightCol	= colourToOgre(colours.d_top_right);
+		
+		// set quad split mode
+		quad.splitMode = quad_split_mode;
+
+		d_quadlist.insert(quad);
+	}
+}
+
+
+
+/*************************************************************************
+perform final rendering for all queued renderable quads.
+*************************************************************************/
+void OgreCEGUIRenderer::doRender(void)
+{
+    // Render if overlays enabled and the quad list is not empty
+	if (d_render_sys->_getViewport()->getOverlaysEnabled() && !d_quadlist.empty())
+	{
+        /// Quad list needs to be sorted and thus the vertex buffer rebuilt. If not, we can
+        /// reuse the vertex buffer resulting in a nice speed gain.
+        if(!d_sorted)
+        {
+            sortQuads();
+            /// Resize vertex buffer if it is too small
+            size_t size = d_buffer->getNumVertices();
+            size_t requestedSize = d_quadlist.size()*VERTEX_PER_QUAD;
+            if(size < requestedSize)
+            {
+                /// Double buffer size until smaller than requested size
+                while(size < requestedSize)
+                    size = size * 2;
+                /// Reallocate the buffer
+                destroyQuadRenderOp(d_render_op, d_buffer);
+                createQuadRenderOp(d_render_op, d_buffer, size);
+            }
+            else if(requestedSize < size/2 && d_underused_framecount >= UNDERUSED_FRAME_THRESHOLD)
+            {
+                /// Resize vertex buffer if it has been to big for too long
+                size = size / 2;
+                destroyQuadRenderOp(d_render_op, d_buffer);
+                createQuadRenderOp(d_render_op, d_buffer, size);
+                /// Reset underused framecount so it takes another UNDERUSED_FRAME_THRESHOLD to half again
+                d_underused_framecount = 0;
+            }
+            /// Fill the buffer
+            QuadVertex*	buffmem;
+            buffmem = (QuadVertex*)d_buffer->lock(Ogre::HardwareVertexBuffer::HBL_DISCARD);
+            // iterate over each quad in the list
+            for (QuadList::iterator i = d_quadlist.begin(); i != d_quadlist.end(); ++i)
+            {
+                const QuadInfo& quad = (*i);
+                // setup Vertex 1...
+                buffmem->x = quad.position.d_left;
+                buffmem->y = quad.position.d_bottom;
+                buffmem->z = quad.z;
+                buffmem->diffuse = quad.topLeftCol;
+                buffmem->tu1 = quad.texPosition.d_left;
+                buffmem->tv1 = quad.texPosition.d_bottom;
+                ++buffmem;
+    
+                // setup Vertex 2...
+                
+                // top-left to bottom-right diagonal
+                if (quad.splitMode == TopLeftToBottomRight)
+                {
+                    buffmem->x = quad.position.d_right;
+                    buffmem->y = quad.position.d_bottom;
+                    buffmem->z = quad.z;
+                    buffmem->diffuse = quad.topRightCol;
+                    buffmem->tu1 = quad.texPosition.d_right;
+                    buffmem->tv1 = quad.texPosition.d_bottom;
+                }
+                // bottom-left to top-right diagonal
+                else
+                {
+                    buffmem->x = quad.position.d_right;
+                    buffmem->y = quad.position.d_top;
+                    buffmem->z = quad.z;
+                    buffmem->diffuse = quad.bottomRightCol;
+                    buffmem->tu1 = quad.texPosition.d_right;
+                    buffmem->tv1 = quad.texPosition.d_top;
+                }
+                ++buffmem;
+    
+                // setup Vertex 3...
+                buffmem->x = quad.position.d_left;
+                buffmem->y = quad.position.d_top;
+                buffmem->z = quad.z;
+                buffmem->diffuse = quad.bottomLeftCol;
+                buffmem->tu1 = quad.texPosition.d_left;
+                buffmem->tv1 = quad.texPosition.d_top;
+                ++buffmem;
+    
+                // setup Vertex 4...
+                buffmem->x = quad.position.d_right;
+                buffmem->y = quad.position.d_bottom;
+                buffmem->z = quad.z;
+                buffmem->diffuse = quad.topRightCol;
+                buffmem->tu1 = quad.texPosition.d_right;
+                buffmem->tv1 = quad.texPosition.d_bottom;
+                ++buffmem;
+    
+                // setup Vertex 5...
+                buffmem->x = quad.position.d_right;
+                buffmem->y = quad.position.d_top;
+                buffmem->z = quad.z;
+                buffmem->diffuse = quad.bottomRightCol;
+                buffmem->tu1 = quad.texPosition.d_right;
+                buffmem->tv1 = quad.texPosition.d_top;
+                ++buffmem;
+    
+                // setup Vertex 6...
+                
+                // top-left to bottom-right diagonal
+                if (quad.splitMode == TopLeftToBottomRight)
+                {
+                    buffmem->x = quad.position.d_left;
+                    buffmem->y = quad.position.d_top;
+                    buffmem->z = quad.z;
+                    buffmem->diffuse = quad.bottomLeftCol;
+                    buffmem->tu1 = quad.texPosition.d_left;
+                    buffmem->tv1 = quad.texPosition.d_top;
+                }
+                // bottom-left to top-right diagonal
+                else
+                {
+                    buffmem->x = quad.position.d_left;
+                    buffmem->y = quad.position.d_bottom;
+                    buffmem->z = quad.z;
+                    buffmem->diffuse = quad.topLeftCol;
+                    buffmem->tu1 = quad.texPosition.d_left;
+                    buffmem->tv1 = quad.texPosition.d_bottom;
+                }
+                ++buffmem;
+            }
+    
+            // ensure we leave the buffer in the unlocked state
+            d_buffer->unlock();
+        }
+        
+        /// Render the buffer
+        d_bufferPos = 0;
+		bool first = true;
+
+        // Iterate over each quad in the list and render it
+        QuadList::iterator i = d_quadlist.begin();
+        while(i != d_quadlist.end())
+        {
+            
+            d_currTexture = i->texture;
+            d_render_op.vertexData->vertexStart = d_bufferPos;
+            for (; i != d_quadlist.end(); ++i)
+            {
+                const QuadInfo& quad = (*i);
+                if (d_currTexture != quad.texture)
+				{
+                    /// If it has a different texture, render this quad in next operation
+					/// also need to reset render states
+					first = true;
+		            break;
+				}
+                d_bufferPos += VERTEX_PER_QUAD;
+            }
+            d_render_op.vertexData->vertexCount = d_bufferPos - d_render_op.vertexData->vertexStart;
+            /// Set texture, and do the render
+            d_render_sys->_setTexture(0, true, d_currTexture);
+			if (first)
+			{
+				initRenderStates();
+				first = false;
+			}
+            d_render_sys->_render(d_render_op);
+        }
+
+	}
+    /// Count frames to check if utilization of vertex buffer was below half the capacity for 500,000 frames
+    if(d_bufferPos < d_buffer->getNumVertices()/2)
+       d_underused_framecount++;
+    else
+       d_underused_framecount = 0;
+}
+
+
+/*************************************************************************
+	clear the queue
+*************************************************************************/
+void OgreCEGUIRenderer::clearRenderList(void)
+{
+	d_sorted = true;
+	d_quadlist.clear();
+}
+
+
+/*************************************************************************
+	create an empty texture
+*************************************************************************/
+Texture* OgreCEGUIRenderer::createTexture(void)
+{
+	OgreCEGUITexture* tex = new OgreCEGUITexture(this);
+	d_texturelist.push_back(tex);
+	return tex;
+}
+
+
+/*************************************************************************
+	create a texture and load it with the specified file.
+*************************************************************************/
+Texture* OgreCEGUIRenderer::createTexture(const String& filename, const String& resourceGroup)
+{
+	OgreCEGUITexture* tex = (OgreCEGUITexture*)createTexture();
+	tex->loadFromFile(filename, resourceGroup);
+
+	return tex;
+}
+
+
+/*************************************************************************
+	create a texture and set it to the specified size
+*************************************************************************/
+Texture* OgreCEGUIRenderer::createTexture(float size)
+{
+	OgreCEGUITexture* tex = (OgreCEGUITexture*)createTexture();
+	tex->setOgreTextureSize((uint)size);
+
+	return tex;
+}
+
+
+/*************************************************************************
+	destroy the given texture
+*************************************************************************/
+void OgreCEGUIRenderer::destroyTexture(Texture* texture)
+{
+	if (texture != NULL)
+	{
+		OgreCEGUITexture* tex = (OgreCEGUITexture*)texture;
+
+		d_texturelist.remove(tex);
+		delete tex;
+	}
+}
+
+
+/*************************************************************************
+	destroy all textures still active
+*************************************************************************/
+void OgreCEGUIRenderer::destroyAllTextures(void)
+{
+	while (!d_texturelist.empty())
+	{
+		destroyTexture(*(d_texturelist.begin()));
+	}
+}
+
+
+/*************************************************************************
+	setup states etc	
+*************************************************************************/
+void OgreCEGUIRenderer::initRenderStates(void)
+{
+	using namespace Ogre;
+
+	// set-up matrices
+	d_render_sys->_setWorldMatrix(Matrix4::IDENTITY);
+	d_render_sys->_setViewMatrix(Matrix4::IDENTITY);
+	d_render_sys->_setProjectionMatrix(Matrix4::IDENTITY);
+
+	// initialise render settings
+	d_render_sys->setLightingEnabled(false);
+	d_render_sys->_setDepthBufferParams(false, false);
+	d_render_sys->_setDepthBias(0, 0);
+	d_render_sys->_setCullingMode(CULL_NONE);
+	d_render_sys->_setFog(FOG_NONE);
+	d_render_sys->_setColourBufferWriteEnabled(true, true, true, true);
+	d_render_sys->unbindGpuProgram(GPT_FRAGMENT_PROGRAM);
+	d_render_sys->unbindGpuProgram(GPT_VERTEX_PROGRAM);
+	d_render_sys->setShadingType(SO_GOURAUD);
+	d_render_sys->_setPolygonMode(PM_SOLID);
+
+	// initialise texture settings
+	d_render_sys->_setTextureCoordCalculation(0, TEXCALC_NONE);
+	d_render_sys->_setTextureCoordSet(0, 0);
+	d_render_sys->_setTextureUnitFiltering(0, FO_LINEAR, FO_LINEAR, FO_POINT);
+	d_render_sys->_setTextureAddressingMode(0, d_uvwAddressMode);
+	d_render_sys->_setTextureMatrix(0, Matrix4::IDENTITY);
+	d_render_sys->_setAlphaRejectSettings(CMPF_ALWAYS_PASS, 0, false);
+	d_render_sys->_setTextureBlendMode(0, d_colourBlendMode);
+	d_render_sys->_setTextureBlendMode(0, d_alphaBlendMode);
+	d_render_sys->_disableTextureUnitsFrom(1);
+
+	// enable alpha blending
+	d_render_sys->_setSceneBlending(SBF_SOURCE_ALPHA, SBF_ONE_MINUS_SOURCE_ALPHA);
+}
+
+
+ 
+/*************************************************************************
+	sort quads list according to texture	
+*************************************************************************/
+void OgreCEGUIRenderer::sortQuads(void)
+{
+	if (!d_sorted)
+	{
+		d_sorted = true;
+	}
+
+}
+
+/*************************************************************************
+render a quad directly to the display
+*************************************************************************/
+void OgreCEGUIRenderer::renderQuadDirect(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode)
+{
+	if (d_render_sys->_getViewport()->getOverlaysEnabled())
+	{
+		z = -1 + z;
+
+		Rect final_rect;
+
+		// set quad position, flipping y co-ordinates, and applying appropriate texel origin offset
+		final_rect.d_left	= dest_rect.d_left;
+		final_rect.d_right	= dest_rect.d_right;
+		final_rect.d_top	= d_display_area.getHeight() - dest_rect.d_top;
+		final_rect.d_bottom	= d_display_area.getHeight() - dest_rect.d_bottom;
+		final_rect.offset(d_texelOffset);
+
+		// convert quad co-ordinates for a -1 to 1 co-ordinate system.
+		final_rect.d_left	/= (d_display_area.getWidth() * 0.5f);
+		final_rect.d_right	/= (d_display_area.getWidth() * 0.5f);
+		final_rect.d_top	/= (d_display_area.getHeight() * 0.5f);
+		final_rect.d_bottom	/= (d_display_area.getHeight() * 0.5f);
+		final_rect.offset(Point(-1.0f, -1.0f));
+
+		// convert colours for ogre, note that top / bottom are switched.
+        uint32 topLeftCol	= colourToOgre(colours.d_bottom_left);
+        uint32 topRightCol	= colourToOgre(colours.d_bottom_right);
+        uint32 bottomLeftCol	= colourToOgre(colours.d_top_left);
+        uint32 bottomRightCol= colourToOgre(colours.d_top_right);
+
+		QuadVertex*	buffmem = (QuadVertex*)d_direct_buffer->lock(Ogre::HardwareVertexBuffer::HBL_DISCARD);
+
+		// setup Vertex 1...
+		buffmem->x	= final_rect.d_left;
+		buffmem->y	= final_rect. d_bottom;
+		buffmem->z	= z;
+		buffmem->diffuse = topLeftCol;
+		buffmem->tu1	= texture_rect.d_left;
+		buffmem->tv1	= texture_rect.d_bottom;
+		++buffmem;
+
+		// setup Vertex 2...
+		
+		// top-left to bottom-right diagonal
+		if (quad_split_mode == TopLeftToBottomRight)
+		{
+			buffmem->x	= final_rect.d_right;
+			buffmem->y = final_rect.d_bottom;
+			buffmem->z	= z;
+			buffmem->diffuse = topRightCol;
+			buffmem->tu1	= texture_rect.d_right;
+			buffmem->tv1	= texture_rect.d_bottom;
+			++buffmem;
+		}
+		// bottom-left to top-right diagonal
+		else
+		{
+			buffmem->x	= final_rect.d_right;
+			buffmem->y = final_rect.d_top;
+			buffmem->z	= z;
+			buffmem->diffuse = bottomRightCol;
+			buffmem->tu1	= texture_rect.d_right;
+			buffmem->tv1	= texture_rect.d_top;
+			++buffmem;
+		}
+
+		// setup Vertex 3...
+		buffmem->x	= final_rect.d_left;
+		buffmem->y	= final_rect.d_top;
+		buffmem->z	= z;
+		buffmem->diffuse = bottomLeftCol;
+		buffmem->tu1	= texture_rect.d_left;
+		buffmem->tv1	= texture_rect.d_top;
+		++buffmem;
+
+		// setup Vertex 4...
+		buffmem->x	= final_rect.d_right;
+		buffmem->y	= final_rect.d_bottom;
+		buffmem->z	= z;
+		buffmem->diffuse = topRightCol;
+		buffmem->tu1	= texture_rect.d_right;
+		buffmem->tv1	= texture_rect.d_bottom;
+		++buffmem;
+
+		// setup Vertex 5...
+		buffmem->x	= final_rect.d_right;
+		buffmem->y	= final_rect.d_top;
+		buffmem->z	= z;
+		buffmem->diffuse = bottomRightCol;
+		buffmem->tu1	= texture_rect.d_right;
+		buffmem->tv1	= texture_rect.d_top;
+		++buffmem;
+
+		// setup Vertex 6...
+		
+		// top-left to bottom-right diagonal
+		if (quad_split_mode == TopLeftToBottomRight)
+		{
+			buffmem->x	= final_rect.d_left;
+			buffmem->y = final_rect.d_top;
+			buffmem->z	= z;
+			buffmem->diffuse = bottomLeftCol;
+			buffmem->tu1	= texture_rect.d_left;
+			buffmem->tv1	= texture_rect.d_top;
+		}
+		// bottom-left to top-right diagonal
+		else
+		{
+			buffmem->x	= final_rect.d_left;
+			buffmem->y = final_rect.d_bottom;
+			buffmem->z	= z;
+			buffmem->diffuse = topLeftCol;
+			buffmem->tu1	= texture_rect.d_left;
+			buffmem->tv1	= texture_rect.d_bottom;
+		}
+
+		d_direct_buffer->unlock();
+
+        //
+		// perform rendering...
+		//
+		d_render_sys->_setTexture(0, true, ((OgreCEGUITexture*)tex)->getOgreTexture()->getName());
+		initRenderStates();
+		d_direct_render_op.vertexData->vertexCount = VERTEX_PER_QUAD;
+		d_render_sys->_render(d_direct_render_op);
+	}
+
+}
+
+/*************************************************************************
+	convert ARGB colour value to whatever the Ogre render system is
+	expecting.	
+*************************************************************************/
+uint32 OgreCEGUIRenderer::colourToOgre(const colour& col) const
+{
+	Ogre::ColourValue cv(col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha());
+
+    uint32 final;
+	d_render_sys->convertColourValue(cv, &final);
+
+	return final;
+}
+
+
+/*************************************************************************
+	Set the scene manager to be used for rendering the GUI.	
+*************************************************************************/
+void OgreCEGUIRenderer::setTargetSceneManager(Ogre::SceneManager* scene_manager)
+{
+	// unhook from current scene manager.
+	if (d_sceneMngr != NULL)
+	{
+		d_sceneMngr->removeRenderQueueListener(d_ourlistener);
+		d_sceneMngr = NULL;
+	}
+
+	// hook new scene manager if that is not NULL
+	if (scene_manager != NULL)
+	{
+		d_sceneMngr = scene_manager;
+		d_sceneMngr->addRenderQueueListener(d_ourlistener);
+	}
+
+}
+
+
+/*************************************************************************
+	Set the target render queue for GUI rendering.	
+*************************************************************************/
+void OgreCEGUIRenderer::setTargetRenderQueue(Ogre::uint8 queue_id, bool post_queue)
+{
+	d_queue_id		= queue_id;
+	d_post_queue	= post_queue;
+
+	if (d_ourlistener != NULL)
+	{
+		d_ourlistener->setTargetRenderQueue(queue_id);
+		d_ourlistener->setPostRenderQueue(post_queue);
+	}
+
+}
+
+
+/*************************************************************************
+	perform main work of the constructor
+*************************************************************************/
+void OgreCEGUIRenderer::constructor_impl(Ogre::RenderWindow* window, Ogre::uint8 queue_id, bool post_queue, uint max_quads)
+{
+	using namespace Ogre;
+
+	// initialise the renderer fields
+	d_queueing		= true;
+	d_queue_id		= queue_id;
+	d_currTexture.isNull();
+	d_post_queue	= post_queue;
+	d_sceneMngr		= NULL;
+	d_bufferPos		= 0;
+	d_sorted		= true;
+	d_ogre_root		= Root::getSingletonPtr();
+	d_render_sys	= d_ogre_root->getRenderSystem();
+    // set ID string
+    d_identifierString = "CEGUI::OgreRenderer - Official Ogre based renderer module for CEGUI";
+
+	// Create and initialise the Ogre specific parts required for use in rendering later.
+    // Main GUI
+    createQuadRenderOp(d_render_op, d_buffer, VERTEXBUFFER_INITIAL_CAPACITY);
+    d_underused_framecount = 0;
+
+    // Mouse cursor
+    createQuadRenderOp(d_direct_render_op, d_direct_buffer, VERTEX_PER_QUAD);
+
+	// Discover display settings and setup d_display_area
+	d_display_area.d_left	= 0;
+	d_display_area.d_top	= 0;
+	d_display_area.d_right	= window->getWidth();
+	d_display_area.d_bottom	= window->getHeight();
+
+	// initialise required texel offset
+	d_texelOffset = Point((float)d_render_sys->getHorizontalTexelOffset(), -(float)d_render_sys->getVerticalTexelOffset());
+
+	// create listener which will handler the rendering side of things for us.
+	d_ourlistener = new CEGUIRQListener(this, queue_id, post_queue);
+
+	// Initialise blending modes to be used.
+	d_colourBlendMode.blendType	= Ogre::LBT_COLOUR;
+	d_colourBlendMode.source1	= Ogre::LBS_TEXTURE;
+	d_colourBlendMode.source2	= Ogre::LBS_DIFFUSE;
+	d_colourBlendMode.operation	= Ogre::LBX_MODULATE;
+
+	d_alphaBlendMode.blendType	= Ogre::LBT_ALPHA;
+	d_alphaBlendMode.source1	= Ogre::LBS_TEXTURE;
+	d_alphaBlendMode.source2	= Ogre::LBS_DIFFUSE;
+	d_alphaBlendMode.operation	= Ogre::LBX_MODULATE;
+
+	d_uvwAddressMode.u = Ogre::TextureUnitState::TAM_CLAMP;
+	d_uvwAddressMode.v = Ogre::TextureUnitState::TAM_CLAMP;
+	d_uvwAddressMode.w = Ogre::TextureUnitState::TAM_CLAMP;
+}
+
+
+/*************************************************************************
+	Create a texture from an existing Ogre::TexturePtr object	
+*************************************************************************/
+Texture* OgreCEGUIRenderer::createTexture(Ogre::TexturePtr& texture)
+{
+	OgreCEGUITexture* t = (OgreCEGUITexture*)createTexture();
+
+	if (!texture.isNull())
+	{
+		t->setOgreTexture(texture);
+	}
+
+	return t;
+
+}
+
+/*************************************************************************
+	Create a resource provider object
+*************************************************************************/
+ResourceProvider* OgreCEGUIRenderer::createResourceProvider(void)
+{
+    d_resourceProvider = new OgreCEGUIResourceProvider();
+    return d_resourceProvider;
+}
+
+/*************************************************************************
+Set the size of the display in pixels.	
+*************************************************************************/
+void OgreCEGUIRenderer::setDisplaySize(const Size& sz)
+{
+	if (d_display_area.getSize() != sz)
+	{
+		d_display_area.setSize(sz);
+
+		EventArgs args;
+		fireEvent(EventDisplaySizeChanged, args, EventNamespace);
+	}
+
+}
+
+/*************************************************************************
+	Callback from Ogre invoked before other stuff in our target queue
+	is rendered
+*************************************************************************/
+void CEGUIRQListener::renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, 
+										 bool& skipThisQueue)
+{
+	if ((!d_post_queue) && (d_queue_id == id))
+	{
+		CEGUI::System::getSingleton().renderGUI();
+	}
+
+}
+
+
+/*************************************************************************
+Callback from Ogre invoked after other stuff in our target queue
+is rendered
+*************************************************************************/
+void CEGUIRQListener::renderQueueEnded(Ogre::uint8 id, const Ogre::String& invocation, bool& repeatThisQueue)
+{
+	if ((d_post_queue) && (d_queue_id == id))
+	{
+		CEGUI::System::getSingleton().renderGUI();
+	}
+
+}
+
+} // End of  CEGUI namespace section
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIRenderer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIRenderer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIRenderer.h	(revision 11817)
@@ -0,0 +1,464 @@
+/************************************************************************
+	filename: 	OgreCEGUIRenderer.h
+	created:	11/5/2004
+	author:		Paul D Turner
+
+	purpose:	Interface for main Ogre GUI renderer class
+*************************************************************************/
+/*************************************************************************
+    Crazy Eddie's GUI System (http://www.cegui.org.uk)
+    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*************************************************************************/
+/*************************************************************************
+	This file contains code that is specific to Ogre (http://www.ogre3d.org)
+*************************************************************************/
+#ifndef _OgreCEGUIRenderer_h_
+#define _OgreCEGUIRenderer_h_
+
+#include <CEGUIBase.h>
+#include <CEGUIRenderer.h>
+#include <CEGUITexture.h>
+
+#include <OgreRenderQueueListener.h>
+#include <OgreSceneManagerEnumerator.h>
+#include <OgreTextureUnitState.h>
+
+#if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && !defined(OGRE_GUIRENDERER_STATIC_LIB)
+#   ifdef OGRE_GUIRENDERER_EXPORTS
+#       define OGRE_GUIRENDERER_API __declspec(dllexport)
+#   else
+#       if defined(__MINGW32__)
+#           define OGRE_GUIRENDERER_API
+#       else
+#           define OGRE_GUIRENDERER_API __declspec(dllimport)
+#       endif
+#   endif
+#elif defined ( OGRE_GCC_VISIBILITY )
+#    define OGRE_GUIRENDERER_API  __attribute__ ((visibility("default")))
+#else
+#    define OGRE_GUIRENDERER_API
+#endif
+
+
+// Start of CEGUI namespace section
+namespace CEGUI
+{
+/*************************************************************************
+	Forward refs
+*************************************************************************/
+class OgreCEGUITexture;
+class OgreCEGUIRenderer;
+
+
+/*!
+\brief
+	RenderQueueListener based class used to hook into the ogre rendering system
+*/
+class _OgrePrivate CEGUIRQListener : public Ogre::RenderQueueListener
+{
+public:
+	CEGUIRQListener(OgreCEGUIRenderer* renderer, Ogre::uint8 queue_id, bool post_queue)
+	{
+		d_renderer		= renderer;
+		d_queue_id		= queue_id;
+		d_post_queue	= post_queue;
+	}
+
+	virtual ~CEGUIRQListener() {}
+
+	virtual void	renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue);
+	virtual void	renderQueueEnded(Ogre::uint8 id, const Ogre::String& invocation, bool& repeatThisQueue);
+
+	// methods for adjusting target queue settings
+	void	setTargetRenderQueue(Ogre::uint8 queue_id)		{d_queue_id = queue_id;}
+	void	setPostRenderQueue(bool post_queue)		{d_post_queue = post_queue;}
+
+private:
+	/*************************************************************************
+		Implementation Data
+	*************************************************************************/
+	OgreCEGUIRenderer*				d_renderer;		//!< CEGUI renderer object for Ogre.
+	Ogre::uint8	d_queue_id;		//!< ID of the queue that we are hooked into
+	bool						d_post_queue;	//!< true if we render after everything else in our queue.
+};
+
+
+/*!
+\brief
+	Renderer class to interface with Ogre engine.
+*/
+class OGRE_GUIRENDERER_API OgreCEGUIRenderer : public Renderer
+{
+public:
+	/*!
+	\brief
+		Constructor for renderer class that uses Ogre for rendering. Note that if
+		you use this option you must call setTargetSceneManager before rendering.
+
+	\param window
+		Pointer to an Ogre::RenderWindow object.
+
+	\param queue_id
+		Ogre::uint8 value that specifies where the GUI should appear in the ogre rendering output.
+
+	\param post_queue
+		set to true to have GUI rendered after render queue \a queue_id, or false to have the GUI rendered before render queue
+		\a queue_id.
+
+	\param max_quads
+		Obsolete.  Set to 0.
+
+	*/
+	OgreCEGUIRenderer(Ogre::RenderWindow* window,
+		Ogre::uint8 queue_id = Ogre::RENDER_QUEUE_OVERLAY,
+		bool post_queue = false, uint max_quads = 0);
+
+
+	/*!
+	\brief
+		Constructor for renderer class that uses Ogre for rendering.
+
+	\param window
+		Pointer to an Ogre::RenderWindow object.
+
+	\param queue_id
+		Ogre::uint8 value that specifies where the GUI should appear in the ogre rendering output.
+
+	\param post_queue
+		set to true to have GUI rendered after render queue \a queue_id, or false to have the GUI rendered before render queue
+		\a queue_id.
+
+	\param max_quads
+		Obsolete.  Set to 0.
+
+	\param scene_manager
+		Pointer to an Ogre::SceneManager object that is to be used for GUI rendering.
+	*/
+	OgreCEGUIRenderer(Ogre::RenderWindow* window, Ogre::uint8 queue_id, bool post_queue, uint max_quads, Ogre::SceneManager* scene_manager);
+
+
+	/*!
+	\brief
+		Destructor for Ogre renderer.
+	*/
+	virtual ~OgreCEGUIRenderer(void);
+
+
+
+	// add's a quad to the list to be rendered
+	virtual	void	addQuad(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode);
+
+	// perform final rendering for all queued renderable quads.
+	virtual	void	doRender(void);
+
+	// clear the queue
+	virtual	void	clearRenderList(void);
+
+
+	/*!
+	\brief
+		Enable or disable the queueing of quads from this point on.
+
+		This only affects queueing.  If queueing is turned off, any calls to addQuad will cause the quad to be rendered directly.  Note that
+		disabling queueing will not cause currently queued quads to be rendered, nor is the queue cleared - at any time the queue can still
+		be drawn by calling doRender, and the list can be cleared by calling clearRenderList.  Re-enabling the queue causes subsequent quads
+		to be added as if queueing had never been disabled.
+
+	\param setting
+		true to enable queueing, or false to disable queueing (see notes above).
+
+	\return
+		Nothing
+	*/
+	virtual void	setQueueingEnabled(bool setting)		{d_queueing = setting;}
+
+
+	// create an empty texture
+	virtual	Texture*	createTexture(void);
+
+	// create a texture and load it with the specified file.
+	virtual	Texture*	createTexture(const String& filename, const String& resourceGroup = "General");
+
+	// create a texture and set it to the specified size
+	virtual	Texture*	createTexture(float size);
+
+    // create an OGRE resource provider.
+    virtual ResourceProvider* createResourceProvider(void);
+
+	// destroy the given texture
+	virtual	void		destroyTexture(Texture* texture);
+
+	// destroy all textures still active
+	virtual void		destroyAllTextures(void);
+
+
+	/*!
+	\brief
+		Return whether queueing is enabled.
+
+	\return
+		true if queueing is enabled, false if queueing is disabled.
+	*/
+	virtual bool	isQueueingEnabled(void) const	{return d_queueing;}
+
+
+	/*!
+	\brief
+	Return the current width of the display in pixels
+
+	\return
+	float value equal to the current width of the display in pixels.
+	*/
+	virtual float	getWidth(void) const		{return d_display_area.getWidth();}
+
+
+	/*!
+	\brief
+	Return the current height of the display in pixels
+
+	\return
+	float value equal to the current height of the display in pixels.
+	*/
+	virtual float	getHeight(void) const		{return d_display_area.getHeight();}
+
+
+	/*!
+	\brief
+	Return the size of the display in pixels
+
+	\return
+	Size object describing the dimensions of the current display.
+	*/
+	virtual Size	getSize(void) const			{return d_display_area.getSize();}
+
+
+	/*!
+	\brief
+	Return a Rect describing the screen
+
+	\return
+	A Rect object that describes the screen area.  Typically, the top-left values are always 0, and the size of the area described is
+	equal to the screen resolution.
+	*/
+	virtual Rect	getRect(void) const			{return d_display_area;}
+
+
+	/*!
+	\brief
+		Return the maximum texture size available
+
+	\return
+		Size of the maximum supported texture in pixels (textures are always assumed to be square)
+	*/
+	virtual	uint	getMaxTextureSize(void) const		{return 2048;}		// TODO: Change to proper value
+
+
+	/*!
+	\brief
+		Return the horizontal display resolution dpi
+
+	\return
+		horizontal resolution of the display in dpi.
+	*/
+	virtual	uint	getHorzScreenDPI(void) const	{return 96;}
+
+
+	/*!
+	\brief
+		Return the vertical display resolution dpi
+
+	\return
+		vertical resolution of the display in dpi.
+	*/
+	virtual	uint	getVertScreenDPI(void) const	{return 96;}
+
+
+	/*!
+	\brief
+		Set the scene manager to be used for rendering the GUI.
+
+		The GUI system will be unhooked from the current scene manager and attached to what ever
+		is specified here.
+
+	\param scene_manager
+		Pointer to an Ogre::SceneManager object that is the new target Ogre::SceneManager to be
+		used for GUI rendering.
+
+	\return
+		Nothing.
+	*/
+	void	setTargetSceneManager(Ogre::SceneManager* scene_manager);
+
+
+	/*!
+	\brief
+		Set the target render queue for GUI rendering.
+
+	\param queue_id
+		Ogre::uint8 value specifying the render queue that the GUI system should attach to.
+
+	\param post_queue
+		- true to specify that the GUI should render after everything else in render queue \a queue_id.
+		- false to specify the GUI should render before everything else in render queue \a queue_id.
+
+	\return
+		Nothing.
+	*/
+	void	setTargetRenderQueue(Ogre::uint8 queue_id, bool post_queue);
+
+
+	/*!
+	\brief
+		Create a texture from an existing Ogre::TexturePtr object.
+
+	\note
+		If you want to use an Ogre::RenderTexture (for putting rendered output onto Gui elements or other
+		advanced techniques), you can get the Ogre::TexturePtr to be used by calling Ogre::TextureManager::getByName()
+		passing the name returned from Ogre::RenderTexture::getName() (and casting the result as necessary).
+
+	\param texture
+		pointer to an Ogre::TexturePtr object to be used as the basis for the new CEGUI::Texture
+
+	\return
+		Pointer to the newly created CEGUI::TexturePtr object.
+	*/
+	Texture*	createTexture(Ogre::TexturePtr& texture);
+
+
+	/*!
+	\brief
+	Set the size of the display in pixels.
+
+	You do not have to call this method under normal operation as the system
+	will automatically extract the size from the current view port.
+
+	\note
+	This method will cause the EventDisplaySizeChanged event to fire if the
+	display size has changed.
+
+	\param sz
+	Size object describing the size of the display.
+
+	\return
+	Nothing.
+	*/
+	void	setDisplaySize(const Size& sz);
+
+
+private:
+	/************************************************************************
+		Implementation Constants
+	************************************************************************/
+	static const size_t    VERTEX_PER_QUAD;						 //!< number of vertices per quad
+	static const size_t    VERTEX_PER_TRIANGLE;					 //!< number of vertices for a triangle
+    static const size_t    VERTEXBUFFER_INITIAL_CAPACITY;		 //!< initial capacity of the allocated vertex buffer
+    static const size_t    UNDERUSED_FRAME_THRESHOLD;            //!< number of frames to wait before shrinking buffer
+
+	/*************************************************************************
+	    Implementation Structs & classes
+	*************************************************************************/
+	/*!
+	\brief
+		structure used for all vertices.
+	*/
+	struct QuadVertex {
+		float x, y, z;			//!< The position for the vertex.
+		Ogre::RGBA diffuse;		//!< colour of the vertex
+		float tu1, tv1;			//!< texture coordinates
+	};
+
+	/*!
+	\brief
+		structure holding details about a quad to be drawn
+	*/
+	struct QuadInfo
+	{
+		Ogre::TexturePtr		texture;
+		Rect				position;
+		float				z;
+		Rect				texPosition;
+        uint32		        topLeftCol;
+        uint32		        topRightCol;
+        uint32		        bottomLeftCol;
+        uint32		        bottomRightCol;
+
+        QuadSplitMode		splitMode;
+
+		bool operator<(const QuadInfo& other) const
+		{
+			// this is intentionally reversed.
+			return z > other.z;
+		}
+	};
+
+
+	/*************************************************************************
+	    Implementation Methods
+	*************************************************************************/
+	// setup states etc
+	void	initRenderStates(void);
+
+	// sort quads list according to texture
+	void	sortQuads(void);
+
+	// render a quad directly to the display
+	void	renderQuadDirect(const Rect& dest_rect, float z, const Texture* tex, const Rect& texture_rect, const ColourRect& colours, QuadSplitMode quad_split_mode);
+
+	// convert colour value to whatever the Ogre render system is expecting.
+    uint32    colourToOgre(const colour& col) const;
+
+	// perform main work of the constructor.  This does everything except the final hook into the render system.
+	void	constructor_impl(Ogre::RenderWindow* window, Ogre::uint8 queue_id, bool post_queue, uint max_quads);
+
+
+	/*************************************************************************
+	    Implementation Data
+	*************************************************************************/
+	Rect				d_display_area;
+
+	typedef std::multiset<QuadInfo>		QuadList;
+	QuadList d_quadlist;
+	bool	 d_queueing;		//!< setting for queueing control.
+
+	// Ogre specific bits.
+	Ogre::Root*					d_ogre_root;		//!< pointer to the Ogre root object that we attach to
+	Ogre::RenderSystem*			d_render_sys;		//!< Pointer to the render system for Ogre.
+	Ogre::uint8	d_queue_id;			//!< ID of the queue that we are hooked into
+	Ogre::TexturePtr			d_currTexture;		//!< currently set texture;
+	Ogre::RenderOperation		d_render_op;		//!< Ogre render operation we use to do our stuff.
+	Ogre::HardwareVertexBufferSharedPtr	d_buffer;	//!< vertex buffer to queue sprite rendering
+    size_t d_underused_framecount;                  //!< Number of frames elapsed since buffer utilization was above half the capacity
+    Ogre::RenderOperation		d_direct_render_op;		//!< Renderop for cursor
+	Ogre::HardwareVertexBufferSharedPtr	d_direct_buffer;	//!< Renderop for cursor
+	Ogre::SceneManager*			d_sceneMngr;		//!< The scene manager we are hooked into.
+	Ogre::LayerBlendModeEx		d_colourBlendMode;	//!< Controls colour blending mode used.
+	Ogre::LayerBlendModeEx		d_alphaBlendMode;	//!< Controls alpha blending mode used.
+	Ogre::TextureUnitState::UVWAddressingMode d_uvwAddressMode;
+
+	CEGUIRQListener*			d_ourlistener;
+	bool						d_post_queue;		//!< true if we render after everything else in our queue.
+	size_t						d_bufferPos;		//!< index into buffer where next vertex should be put.
+	bool						d_sorted;			//!< true when data in quad list is sorted.
+	Point						d_texelOffset;		//!< Offset required for proper texel mapping.
+
+	std::list<OgreCEGUITexture*> d_texturelist;		//!< List used to track textures.
+};
+
+} // End of  CEGUI namespace section
+
+
+#endif	// end of guard _OgreCEGUIRenderer_h_
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIResourceProvider.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIResourceProvider.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIResourceProvider.cpp	(revision 11817)
@@ -0,0 +1,101 @@
+/************************************************************************
+	filename: 	OgreCEGUIResourceProvider.cpp
+	created:	8/7/2004
+	author:		James '_mental_' O'Sullivan
+
+	purpose:	Implements the Resource Provider common functionality
+*************************************************************************/
+/*************************************************************************
+    Crazy Eddie's GUI System (http://www.cegui.org.uk)
+    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*************************************************************************/
+
+// Workaround for GCC 4.6
+#include <cstddef>
+
+#include "OgreCEGUIResourceProvider.h"
+
+#include <CEGUIExceptions.h>
+#include <OgreArchiveManager.h>
+
+
+// Start of CEGUI namespace section
+namespace CEGUI
+{
+    OgreCEGUIResourceProvider::OgreCEGUIResourceProvider() : ResourceProvider()
+    {
+        // set deafult resource group for Ogre
+        d_defaultResourceGroup = Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME.c_str();
+    }
+
+//    void OgreResourceProvider::loadInputSourceContainer(const String& filename, InputSourceContainer& output)
+//   {
+//        Ogre::DataStreamPtr input = Ogre::ResourceGroupManager::getSingleton().openResource(filename.c_str());
+//
+//		if (input.isNull())
+//		{
+//			throw InvalidRequestException((utf8*)
+//				"Scheme::Scheme - Filename supplied for Scheme loading must be valid");
+//		}
+//
+//       XERCES_CPP_NAMESPACE_USE
+//        size_t buffsz = input->size();
+//        unsigned char* mem = reinterpret_cast<unsigned char*>(XMLPlatformUtils::fgArrayMemoryManager->allocate(buffsz));
+//        memcpy(mem, input.getPointer()->getAsString().c_str(), buffsz);
+//        InputSource* mInputSource = new MemBufInputSource(mem, buffsz, filename.c_str(), true);
+//        input.setNull();
+//
+//       output.setData(mInputSource);
+//    }
+
+    void OgreCEGUIResourceProvider::loadRawDataContainer(const String& filename, RawDataContainer& output,  const String& resourceGroup)
+    {
+        String orpGroup;
+        if (resourceGroup.empty())
+            orpGroup = d_defaultResourceGroup.empty() ? Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME.c_str() : d_defaultResourceGroup;
+        else
+            orpGroup = resourceGroup;
+
+        Ogre::DataStreamPtr input =
+            Ogre::ResourceGroupManager::getSingleton().openResource(filename.c_str(), orpGroup.c_str());
+
+		if (input.isNull())
+		{
+            throw InvalidRequestException((utf8*)
+                "OgreCEGUIResourceProvider::loadRawDataContainer - Unable to open resource file '" + filename + (utf8*)"' in resource group '" + orpGroup + (utf8*)"'.");
+        }
+
+		Ogre::String buf = input->getAsString();
+		const size_t memBuffSize = buf.length();
+
+        unsigned char* mem = new unsigned char[memBuffSize];
+        memcpy(mem, buf.c_str(), memBuffSize);
+
+        output.setData(mem);
+        output.setSize(memBuffSize);
+    }
+
+	void OgreCEGUIResourceProvider::unloadRawDataContainer(RawDataContainer& data)
+	{
+		if (data.getDataPtr())
+		{
+			delete[] data.getDataPtr();
+			data.setData(0);
+			data.setSize(0);
+		}
+	}
+} // End of  CEGUI namespace section
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIResourceProvider.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIResourceProvider.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUIResourceProvider.h	(revision 11817)
@@ -0,0 +1,52 @@
+/************************************************************************
+	filename: 	CEGUIOgreResourceProvider.h
+	created:	8/7/2004
+	author:		James '_mental_' O'Sullivan
+	
+	purpose:	Defines abstract base class for CEGUIData objects
+*************************************************************************/
+/*************************************************************************
+    Crazy Eddie's GUI System (http://www.cegui.org.uk)
+    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*************************************************************************/
+#ifndef _OgreCEGUIResourceProvider_h_
+#define _OgreCEGUIResourceProvider_h_
+
+#include <CEGUIResourceProvider.h>
+#include "OgreCEGUIRenderer.h"
+
+// Start of CEGUI namespace section
+namespace CEGUI
+{
+class _OgrePrivate OgreCEGUIResourceProvider : public ResourceProvider
+{
+public:
+	/*************************************************************************
+		Construction and Destruction
+	*************************************************************************/
+	OgreCEGUIResourceProvider();
+
+	~OgreCEGUIResourceProvider(void) {}
+
+//    void loadInputSourceContainer(const String& filename, InputSourceContainer& output);
+    void loadRawDataContainer(const String& filename, RawDataContainer& output, const String& resourceGroup);
+    void unloadRawDataContainer(RawDataContainer& output);
+};
+
+} // End of  CEGUI namespace section
+
+#endif	// end of guard _OgreCEGUIResourceProvider_h_
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUITexture.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUITexture.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUITexture.cpp	(revision 11817)
@@ -0,0 +1,271 @@
+/************************************************************************
+	filename: 	OgreCEGUITexture.cpp
+	created:	11/5/2004
+	author:		Paul D Turner
+	
+	purpose:	Implementation of Texture using Ogre engine
+*************************************************************************/
+/*************************************************************************
+    Crazy Eddie's GUI System (http://www.cegui.org.uk)
+    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*************************************************************************/
+
+// Workaround for GCC 4.6
+#include <cstddef>
+
+#include <CEGUISystem.h>
+#include <CEGUIExceptions.h>
+#include "OgreCEGUITexture.h"
+#include "OgreCEGUIRenderer.h"
+
+#include <OgreTextureManager.h>
+
+// Start of CEGUI namespace section
+namespace CEGUI
+{
+/*************************************************************************
+	Static data definition / initialisation
+*************************************************************************/
+uint32 OgreCEGUITexture::d_texturenumber		= 0;
+
+
+/*************************************************************************
+	Constructor
+*************************************************************************/
+OgreCEGUITexture::OgreCEGUITexture(Renderer* owner) :
+	Texture(owner)
+{
+	d_ogre_texture.setNull();
+	d_isLinked = false;
+}
+
+
+/*************************************************************************
+	Destructor
+*************************************************************************/
+OgreCEGUITexture::~OgreCEGUITexture(void)
+{
+	freeOgreTexture();
+}
+
+
+/*************************************************************************
+	Loads the specified image file into the texture.  The texture is
+	resized as required to hold the image.	
+*************************************************************************/
+void OgreCEGUITexture::loadFromFile(const String& filename, const String& resourceGroup)
+{
+	using namespace Ogre;
+
+	// unload old ogre texture
+	freeOgreTexture();
+
+	// create / load a new ogre texture from the specified image
+	try
+	{
+		TextureManager& textureManager = TextureManager::getSingleton();
+
+		// see if texture already exists
+		Ogre::TexturePtr ogreTexture = (Ogre::TexturePtr)textureManager.getByName(filename.c_str());
+
+		if (!ogreTexture.isNull())
+		{
+			// texture already exists, so create a 'linked' texture (ensures texture is not destroyed twice)
+			d_ogre_texture = ogreTexture;
+			d_isLinked = true;
+		}
+		// texture does not already exist, so load it in
+		else
+		{
+            String orpGroup;
+            if (resourceGroup.empty())
+            {
+                const String& defGrp = CEGUI::System::getSingleton().getResourceProvider()->getDefaultResourceGroup();
+                orpGroup = defGrp.empty() ? Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME.c_str() : defGrp;
+            }
+            else
+            {
+                orpGroup = resourceGroup;
+            }
+
+			d_ogre_texture = TextureManager::getSingleton().load(filename.c_str(), orpGroup.c_str(), TEX_TYPE_2D, 0, 1.0f);
+			d_isLinked = false;
+		}
+
+	}
+	catch(Ogre::Exception e)
+	{
+		throw RendererException((utf8*)"Failed to create Texture object from file '" + filename + "'. Additional Information:\n" + e.getFullDescription().c_str());
+	}
+
+	// if we got a pointer cache some details
+	if (!d_ogre_texture.isNull())
+	{
+		d_width		= d_ogre_texture->getWidth();
+		d_height	= d_ogre_texture->getHeight();
+	}
+	// no texture from image so throw.
+	else
+	{
+		throw RendererException((utf8*)"Failed to create Texture object from file '" + filename + "'.  Ogre returned a NULL pointer.");
+	}
+
+}
+
+
+/*************************************************************************
+	Loads (copies) an image in memory into the texture.  The texture is
+	resized as required to hold the image.	
+*************************************************************************/
+
+void _byteSwap(unsigned char* b, int n)
+{
+    register int i = 0;
+    register int j = n-1;
+    while (i<j)
+    {
+        std::swap(b[i], b[j]);
+        i++, j--;
+    }
+}
+#define byteSwap(x) _byteSwap((unsigned char*) &x,sizeof(x))
+
+void OgreCEGUITexture::loadFromMemory(const void* buffPtr, uint buffWidth, uint buffHeight, PixelFormat pixelFormat)
+{
+	using namespace Ogre;
+
+	// get rid of old texture
+	freeOgreTexture();
+
+	// wrap input buffer with an Ogre DataChunk
+    uint32 bytesize = ((buffWidth * sizeof(uint32)) * buffHeight);
+
+#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
+    uint32* swappedBuffer = new uint32[bytesize/4];
+    memcpy(swappedBuffer, buffPtr, bytesize);
+
+    for (int i=0; i < bytesize/4; i++)
+        byteSwap(swappedBuffer[i]);
+
+    DataStreamPtr odc(new MemoryDataStream(static_cast<void*>(swappedBuffer), bytesize, false));
+#else
+	DataStreamPtr odc(new MemoryDataStream(const_cast<void*>(buffPtr), bytesize, false));
+#endif
+
+	// get pixel type for the target texture - the elements here might look wrong, but is just
+	// differences in definition (at the core level, between GL and D3D).
+	Ogre::PixelFormat targetFmt =
+		(pixelFormat == PF_RGBA) ? Ogre::PF_A8R8G8B8 : Ogre::PF_R8G8B8;
+
+	// try to create a Ogre::Texture from the input data
+	d_ogre_texture = TextureManager::getSingleton().loadRawData(getUniqueName(), "General", odc, buffWidth, buffHeight, targetFmt , TEX_TYPE_2D, 0, 1.0f);
+
+	// if we got a pointer cache some details
+	if (!d_ogre_texture.isNull())
+	{
+		d_width		= d_ogre_texture->getWidth();
+		d_height	= d_ogre_texture->getHeight();
+	}
+	// no texture from memory so throw.
+	else
+	{
+		throw RendererException((utf8*)"Failed to create Texture object from memory:  Ogre returned a NULL Ogre::Texture pointer.");
+	}
+
+}
+
+
+/*************************************************************************
+	set the size of the internal Ogre texture.  Previous Ogre texture
+	is lost.	
+*************************************************************************/
+void OgreCEGUITexture::setOgreTextureSize(uint size)
+{
+	using namespace Ogre;
+
+	// unload any current Ogre::Texture
+	freeOgreTexture();
+
+	// Try to create an empty texture of the given size
+	d_ogre_texture = TextureManager::getSingleton().createManual(getUniqueName(), "General", TEX_TYPE_2D, size, size, 0, PF_A8R8G8B8, TU_DEFAULT);
+
+	// if we got a pointer cache some details
+	if (!d_ogre_texture.isNull())
+	{
+		d_width		= d_ogre_texture->getWidth();
+		d_height	= d_ogre_texture->getHeight();
+	}
+	// no texture so throw.
+	else
+	{
+		throw RendererException((utf8*)"Failed to create texture of specified size: Ogre::Texture creation failed.");
+	}
+
+}
+
+
+/*************************************************************************
+	safely free Ogre::Texture texture (can be called multiple times with
+	no ill effect)
+*************************************************************************/
+void OgreCEGUITexture::freeOgreTexture(void)
+{
+	if ((!d_ogre_texture.isNull()) && !d_isLinked)
+	{
+		Ogre::TextureManager::getSingleton().remove(d_ogre_texture->getHandle());
+	}
+	d_ogre_texture.setNull();
+}
+
+
+/*************************************************************************
+	return a Ogre::string that contains a unique name.	
+*************************************************************************/
+Ogre::String OgreCEGUITexture::getUniqueName(void)
+{
+	Ogre::String str;
+
+#ifdef CEGUI_USEOLDOGRESTRING
+	str << "_cegui_ogre_" << d_texturenumber;
+#else
+	Ogre::StringUtil::StrStreamType strstream;
+	strstream << "_cegui_ogre_" << d_texturenumber;
+	str = strstream.str();
+#endif
+
+	++d_texturenumber;
+
+	return str;
+}
+
+
+/*************************************************************************
+	Set the internal Ogre::Texture object.
+*************************************************************************/
+void OgreCEGUITexture::setOgreTexture(Ogre::TexturePtr& texture)
+{
+	freeOgreTexture();
+
+	d_ogre_texture = texture;
+	d_width	 = d_ogre_texture->getWidth();
+	d_height = d_ogre_texture->getHeight();
+	d_isLinked = true;
+}
+
+
+} // End of  CEGUI namespace section
+
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUITexture.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUITexture.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/OgreCEGUITexture.h	(revision 11817)
@@ -0,0 +1,179 @@
+/************************************************************************
+	filename: 	OgreCEGUITexture.h
+	created:	11/5/2004
+	author:		Paul D Turner
+	
+	purpose:	Interface to Texture implemented via Ogre engine
+*************************************************************************/
+/*************************************************************************
+    Crazy Eddie's GUI System (http://www.cegui.org.uk)
+    Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library 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
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*************************************************************************/
+#ifndef _OgreCEGUITexture_h_
+#define _OgreCEGUITexture_h_
+
+#include <CEGUIBase.h>
+#include <CEGUIRenderer.h>
+#include <CEGUITexture.h>
+#include "OgreCEGUIRenderer.h"
+
+// Start of CEGUI namespace section
+namespace CEGUI
+{
+/*!
+\brief
+	Texture class that is created by OgreCEGUIRenderer objects
+*/
+class _OgrePrivate OgreCEGUITexture : public Texture
+{
+private:
+	/*************************************************************************
+		Friends (to allow construction and destruction)
+	*************************************************************************/
+	friend	Texture* OgreCEGUIRenderer::createTexture(void);
+	friend	Texture* OgreCEGUIRenderer::createTexture(const String& filename, const String& resourceGroup);
+	friend	Texture* OgreCEGUIRenderer::createTexture(float size);
+	friend	void	 OgreCEGUIRenderer::destroyTexture(Texture* texture);
+
+
+	/*************************************************************************
+		Construction & Destruction (by Renderer object only)
+	*************************************************************************/
+	OgreCEGUITexture(Renderer* owner);
+	virtual ~OgreCEGUITexture(void);
+
+public:
+	/*!
+	\brief
+		Returns the current pixel width of the texture
+
+	\return
+		ushort value that is the current width of the texture in pixels
+	*/
+	virtual	ushort	getWidth(void) const		{return d_width;}
+
+
+	/*!
+	\brief
+		Returns the current pixel height of the texture
+
+	\return
+		ushort value that is the current height of the texture in pixels
+	*/
+	virtual	ushort	getHeight(void) const		{return d_height;}
+
+
+	/*!
+	\brief
+		Loads the specified image file into the texture.  The texture is resized as required to hold the image.
+
+	\param filename
+		The filename of the image file that is to be loaded into the texture
+
+	\return
+		Nothing.
+	*/
+	virtual void	loadFromFile(const String& filename, const String& resourceGroup);
+
+
+	/*!
+	\brief
+		Loads (copies) an image in memory into the texture.  The texture is resized as required to hold the image.
+	
+	\param buffPtr
+		Pointer to the buffer containing the image data
+	
+	\param buffWidth
+		Width of the buffer (in pixels as specified by \a pixelFormat )
+	
+	\param buffHeight
+		Height of the buffer (in pixels as specified by \a pixelFormat )
+	
+	\param pixelFormat
+	PixelFormat value describing the format contained in \a buffPtr
+	
+	\return
+		Nothing.
+	*/
+	virtual void	loadFromMemory(const void* buffPtr, uint buffWidth, uint buffHeight, PixelFormat pixelFormat);
+
+
+	/*!
+	\brief
+		Return a pointer to the internal Ogre::Texture object
+
+	\return
+		Pointer to the Ogre::Texture object currently being used by this Texture object
+	*/
+	Ogre::TexturePtr	getOgreTexture(void) const		{return d_ogre_texture;}
+
+
+	/*!
+	\brief
+		set the size of the internal Ogre texture.  Previous Ogre texture is lost.
+
+	\param size
+		pixel size of the new internal texture.  This will be rounded up to a power of 2.
+
+	\return
+		Nothing.
+	*/
+	void	setOgreTextureSize(uint size);
+
+
+	/*!
+	\brief
+		Set the internal Ogre::TexturePtr object.
+
+	\param texture
+		Reference to an Ogre::TexturePtr object that is to be used by this Texture object.
+
+	\return
+		Nothing.
+	*/
+	void	setOgreTexture(Ogre::TexturePtr& texture);
+
+
+private:
+	/*************************************************************************
+		Implementation Functions
+	*************************************************************************/
+	// safely free Ogre::Texture texture (can be called multiple times with no ill effect)
+	void	freeOgreTexture(void);
+
+	// return a Ogre::string that contains a unique name.
+	Ogre::String	getUniqueName(void);
+
+
+	/*************************************************************************
+		Implementation Data
+	*************************************************************************/
+	static	uint32          d_texturenumber;	//!< Counter used to provide unique texture names.
+
+	Ogre::TexturePtr		d_ogre_texture;		//!< The 'real' texture.
+
+	ushort					d_width;			//!< cached width of the texture
+	ushort					d_height;			//!< cached height of the texture
+
+	bool	d_isLinked;		//!< True if we are linked to a texture we did not actually create.
+};
+
+
+} // End of  CEGUI namespace section
+
+
+#endif	// end of guard _OgreCEGUITexture_h_
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/VERSION
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/VERSION	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/VERSION	(revision 11817)
@@ -0,0 +1,22 @@
+This library is part of the OGRE v1.6.5 source.
+
+-----
+
+Copyright 1999-2004 The OGRE Team.
+
+This file is part of OGRE (Object-Oriented Graphics Rendering Engine).
+
+OGRE is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+OGRE 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 Lesser General Public License
+along with OGRE; see the file COPYING.  If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
Index: /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/changes_orxonox.diff
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/changes_orxonox.diff	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ogreceguirenderer/changes_orxonox.diff	(revision 11817)
@@ -0,0 +1,104 @@
+--- OgreCEGUIRenderer.cpp	Sun Dec 27 10:40:24 2009
++++ OgreCEGUIRenderer.cpp	Sat Apr 30 17:21:29 2011
+@@ -24,12 +24,15 @@
+     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *************************************************************************/
+ 
+-#include <CEGUI/CEGUIImagesetManager.h>
+-#include <CEGUI/CEGUIImageset.h>
+-#include <CEGUI/CEGUIImage.h>
+-#include <CEGUI/CEGUIExceptions.h>
+-#include <CEGUI/CEGUISystem.h>
++// Workaround for GCC 4.6
++#include <cstddef>
+ 
++#include <CEGUIImagesetManager.h>
++#include <CEGUIImageset.h>
++#include <CEGUIImage.h>
++#include <CEGUIExceptions.h>
++#include <CEGUISystem.h>
++
+ #include "OgreCEGUIRenderer.h"
+ #include "OgreCEGUITexture.h"
+ #include "OgreCEGUIResourceProvider.h"
+--- OgreCEGUIRenderer.h	Wed Jan 28 21:14:09 2009
++++ OgreCEGUIRenderer.h	Wed Jan 28 21:06:46 2009
+@@ -29,15 +29,15 @@
+ #ifndef _OgreCEGUIRenderer_h_
+ #define _OgreCEGUIRenderer_h_
+ 
+-#include <CEGUI/CEGUIBase.h>
+-#include <CEGUI/CEGUIRenderer.h>
+-#include <CEGUI/CEGUITexture.h>
++#include <CEGUIBase.h>
++#include <CEGUIRenderer.h>
++#include <CEGUITexture.h>
+ 
+ #include <OgreRenderQueueListener.h>
+ #include <OgreSceneManagerEnumerator.h>
+ #include <OgreTextureUnitState.h>
+
+-#if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && !defined(OGRE_STATIC_LIB)
++#if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && !defined(OGRE_GUIRENDERER_STATIC_LIB)
+ #   ifdef OGRE_GUIRENDERER_EXPORTS
+ #       define OGRE_GUIRENDERER_API __declspec(dllexport)
+ #   else
+--- OgreCEGUIResourceProvider.cpp	Sun Dec 27 10:40:24 2009
++++ OgreCEGUIResourceProvider.cpp	Sat Apr 30 17:21:40 2011
+@@ -23,9 +23,13 @@
+     License along with this library; if not, write to the Free Software
+     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *************************************************************************/
++
++// Workaround for GCC 4.6
++#include <cstddef>
++
+ #include "OgreCEGUIResourceProvider.h"
+ 
+-#include <CEGUI/CEGUIExceptions.h>
++#include <CEGUIExceptions.h>
+ #include <OgreArchiveManager.h>
+ 
+ 
+--- OgreCEGUIResourceProvider.h	Wed Jan 28 21:14:09 2009
++++ OgreCEGUIResourceProvider.h	Wed Jan 28 21:06:51 2009
+@@ -26,7 +26,7 @@
+ #ifndef _OgreCEGUIResourceProvider_h_
+ #define _OgreCEGUIResourceProvider_h_
+ 
+-#include <CEGUI/CEGUIResourceProvider.h>
++#include <CEGUIResourceProvider.h>
+ #include "OgreCEGUIRenderer.h"
+ 
+ // Start of CEGUI namespace section
+--- OgreCEGUITexture.cpp	Sun Dec 27 10:40:24 2009
++++ OgreCEGUITexture.cpp	Sat Apr 30 17:21:52 2011
+@@ -24,8 +24,11 @@
+     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *************************************************************************/
+ 
+-#include <CEGUI/CEGUISystem.h>
+-#include <CEGUI/CEGUIExceptions.h>
++// Workaround for GCC 4.6
++#include <cstddef>
++
++#include <CEGUISystem.h>
++#include <CEGUIExceptions.h>
+ #include "OgreCEGUITexture.h"
+ #include "OgreCEGUIRenderer.h"
+ 
+--- OgreCEGUITexture.h	Wed Jan 28 21:14:09 2009
++++ OgreCEGUITexture.h	Wed Jan 28 21:07:06 2009
+@@ -26,9 +26,9 @@
+ #ifndef _OgreCEGUITexture_h_
+ #define _OgreCEGUITexture_h_
+ 
+-#include <CEGUI/CEGUIBase.h>
+-#include <CEGUI/CEGUIRenderer.h>
+-#include <CEGUI/CEGUITexture.h>
++#include <CEGUIBase.h>
++#include <CEGUIRenderer.h>
++#include <CEGUITexture.h>
+ #include "OgreCEGUIRenderer.h"
+ 
+ // Start of CEGUI namespace section
Index: /code/branches/RacingBots_FS18/src/external/ois/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,76 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(OIS_FILES
+  OIS.h
+  OISConfig.h
+  OISEffect.h
+  OISEvents.h
+  OISException.h
+  OISFactoryCreator.h
+  OISForceFeedback.h
+  OISInputManager.h
+  OISInterface.h
+  OISJoyStick.h
+  OISKeyboard.h
+  OISMouse.h
+  OISMultiTouch.h
+  OISObject.h
+  OISPrereqs.h
+
+  OISEffect.cpp
+  OISException.cpp
+  OISForceFeedback.cpp
+  OISInputManager.cpp
+  OISJoyStick.cpp
+  OISKeyboard.cpp
+  OISObject.cpp
+)
+
+IF(WIN32)
+  ADD_SUBDIRECTORY(win32)
+ELSEIF(APPLE)
+  ADD_SUBDIRECTORY(mac)
+ELSEIF(UNIX)
+  ADD_SUBDIRECTORY(linux)
+ENDIF()
+
+# Apple has problems with OIS and build units
+IF(APPLE)
+  SET(USE_BUILD_UNITS NO_BUILD_UNITS)
+ENDIF()
+
+ORXONOX_ADD_LIBRARY(ois_orxonox
+  ORXONOX_EXTERNAL
+  DEFINE_SYMBOL
+    "OIS_NONCLIENT_BUILD"
+  VERSION
+    1.3
+  LINK_LIBS_WIN32
+    ${DIRECTX_LIBRARIES}
+    ${WMI_LIBRARY}
+  LINK_LIBS_APPLE
+    /System/Library/Frameworks/IOKit.framework
+    /System/Library/Frameworks/Carbon.framework
+  LINK_LIBS_LINUX
+    X11
+  ${USE_BUILD_UNITS}
+  SOURCE_FILES
+    ${OIS_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/external/ois/OIS.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OIS.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OIS.h	(revision 11817)
@@ -0,0 +1,41 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_OISALL_H
+#define OIS_OISALL_H
+
+#include "OISPrereqs.h"
+#include "OISObject.h"
+#include "OISMouse.h"
+#include "OISKeyboard.h"
+#include "OISJoyStick.h"
+#include "OISMultiTouch.h"
+#include "OISInputManager.h"
+#include "OISFactoryCreator.h"
+#include "OISException.h"
+#include "OISEvents.h"
+
+#include "OISEffect.h"
+#include "OISInterface.h"
+#include "OISForceFeedback.h"
+
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISConfig.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISConfig.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISConfig.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_CONFIG_HEADER
+#define OIS_CONFIG_HEADER
+
+//----------------------------------------------------------------------------//
+//* This file contains defines for building certain parts of this Lib
+//*	This file is not meant for External inclusion. However, you can edit this 
+//* file before a build to effect what features are used internally
+//----------------------------------------------------------------------------//
+
+/** 
+@remarks
+	These lines have no bearing on internal build of OIS. This is here for
+	external build settings. Meaning, changing this does not require a
+	rebuild of OIS. This just affects VC dll import settings, as the DLL
+	build already defines this during its build for setting dll exports.
+	The undefine here is here just incase you decide to only use
+	DLL, and want to set it permently and recompile OIS too.. Avoid redefinition
+	from DLL build of OIS.
+
+	So, if wanting to link against DLL version, just uncomment these lines.
+*/
+//#ifdef OIS_DYNAMIC_LIB
+//#  undef OIS_DYNAMIC_LIB
+//#endif
+//#define OIS_DYNAMIC_LIB
+
+/**
+@remarks
+	Build in support for LIRC / WinLIRC - remote control support.
+	Requires Boost::asio
+@notes
+	Experimental - Supports connecting and enumerating. Control does not
+	yet return state or events
+*/
+//#define OIS_LIRC_SUPPORT
+
+/**
+@remarks
+	Build in support for PC Nintendo WiiMote Win32 HID interface.
+	Requires Boost::threads
+@notes
+	Useable, but not quite finished - supports rumble, all buttons, & main orientation axis.
+	Still needs Nunchuck, IR, and LED/Battery support.
+*/
+//#define OIS_WIN32_WIIMOTE_SUPPORT
+
+/**
+@remarks
+	Build in support for Win32 XInput (Xbox 360 Controller)
+*/
+//#define OIS_WIN32_XINPUT_SUPPORT
+
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISEffect.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISEffect.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISEffect.cpp	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISEffect.h"
+#include "OISException.h"
+
+using namespace OIS;
+
+//VC7.1 had a problem with these not getting included.. 
+//Perhaps a case of a crazy extreme optimizer :/ (moved to header)
+//const unsigned int Effect::OIS_INFINITE = 0xFFFFFFFF;
+
+//------------------------------------------------------------------------------//
+static const char* pszEForceString[] = 
+  { "UnknownForce",
+    "ConstantForce", 
+    "RampForce", 
+    "PeriodicForce", 
+    "ConditionalForce", 
+    "CustomForce" };
+
+const char* Effect::getForceTypeName(Effect::EForce eValue)
+{
+  return (eValue >= 0 && eValue < _ForcesNumber) ? pszEForceString[eValue] : "<Bad force type>";
+}
+
+static const char* pszETypeString[] = 
+  { "Unknown",
+    "Constant",
+    "Ramp",
+    "Square", "Triangle", "Sine", "SawToothUp", "SawToothDown",
+    "Friction", "Damper", "Inertia", "Spring",
+    "Custom" };
+
+const char* Effect::getEffectTypeName(Effect::EType eValue)
+{
+  return (eValue >= 0 && eValue < _TypesNumber) ? pszETypeString[eValue] : "<Bad effect type>";
+}
+
+static const char* pszEDirectionString[] = 
+  { "NorthWest", "North", "NorthEast", "East", "SouthEast", "South", "SouthWest", "West"};
+
+const char* Effect::getDirectionName(Effect::EDirection eValue)
+{
+  return (eValue >= 0 && eValue < _DirectionsNumber) ? pszEDirectionString[eValue] : "<Bad direction>";
+}
+
+//------------------------------------------------------------------------------//
+Effect::Effect() : 
+	force(UnknownForce), 
+	type(Unknown),
+	effect(0),
+	axes(1)
+{
+}
+
+//------------------------------------------------------------------------------//
+Effect::Effect(EForce ef, EType et) : 
+	force(ef), 
+	type(et),
+	direction(North), 
+	trigger_button(-1),
+	trigger_interval(0),
+	replay_length(Effect::OIS_INFINITE),
+	replay_delay(0),
+	_handle(-1),
+	axes(1)
+{
+	effect = 0;
+
+	switch( ef )
+	{
+	case ConstantForce:    effect = new ConstantEffect(); break;
+	case RampForce:	       effect = new RampEffect(); break;
+	case PeriodicForce:    effect = new PeriodicEffect(); break;
+	case ConditionalForce: effect = new ConditionalEffect(); break;
+	default: break;
+	}
+}
+
+//------------------------------------------------------------------------------//
+Effect::~Effect()
+{
+	delete effect;
+}
+
+//------------------------------------------------------------------------------//
+ForceEffect* Effect::getForceEffect() const
+{
+	//If no effect was created in constructor, then we raise an error here
+	if( effect == 0 )
+		OIS_EXCEPT( E_NotSupported, "Requested ForceEffect is null!" );
+
+	return effect;
+}
+
+//------------------------------------------------------------------------------//
+void Effect::setNumAxes(short nAxes)
+{
+	//Can only be set before a handle was assigned (effect created)
+	if( _handle != -1 )
+        axes = nAxes;
+}
+
+//------------------------------------------------------------------------------//
+short Effect::getNumAxes() const
+{
+	return axes;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/OISEffect.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISEffect.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISEffect.h	(revision 11817)
@@ -0,0 +1,278 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Effect_H
+#define OIS_Effect_H
+
+#include "OISPrereqs.h"
+
+namespace OIS
+{
+	//Predeclare some Effect Property structs
+	class ForceEffect;
+	class ConstantEffect;
+	class RampEffect;
+	class PeriodicEffect;
+	class ConditionalEffect;
+
+	/**
+		Force Feedback is a relatively complex set of properties to upload to a device.
+		The best place for information on the different properties, effects, etc is in
+		the DX Documentation and MSDN - there are even pretty graphs ther =)
+		As this class is modeled on the the DX interface you can apply that same
+		knowledge to creating effects via this class on any OS supported by OIS.
+
+		In anycase, this is the main class you will be using. There is *absolutely* no
+		need to instance any of the supporting ForceEffect classes yourself.
+	*/
+	class _OISExport Effect
+	{
+		/**
+			hidden so this class cannot be instanced with default constructor
+		*/
+		Effect();
+	public:
+		//! Type of force
+		enum EForce
+		{
+			UnknownForce = 0,
+			ConstantForce,
+			RampForce,
+			PeriodicForce,
+			ConditionalForce,
+			CustomForce,
+			_ForcesNumber // Always keep in last position.
+		};
+
+		static const char* getForceTypeName(EForce eValue);
+
+		//! Type of effect
+		enum EType
+		{
+			//Type ----- Pairs with force:
+			Unknown = 0, //UnknownForce
+			Constant,    //ConstantForce
+			Ramp,        //RampForce
+			Square,      //PeriodicForce
+			Triangle,    //PeriodicForce
+            Sine,        //PeriodicForce
+			SawToothUp,  //PeriodicForce
+			SawToothDown,//PeriodicForce
+			Friction,    //ConditionalForce
+			Damper,      //ConditionalForce
+			Inertia,     //ConditionalForce
+			Spring,      //ConditionalForce
+			Custom,      //CustomForce
+			_TypesNumber // Always keep in last position.
+		};
+
+		static const char* getEffectTypeName(EType eValue);
+
+		//! Direction of the Force
+		enum EDirection
+		{
+			NorthWest,
+			North,
+			NorthEast,
+			East,
+			SouthEast,
+			South,
+			SouthWest,
+			West,
+			_DirectionsNumber // Always keep in last position.
+		};
+
+		static const char* getDirectionName(EDirection eValue);
+
+		/**
+			This constructor allows you to set the force type and effect.
+		*/
+		Effect(EForce ef, EType et);
+		virtual ~Effect();
+
+		const EForce force;
+		const EType type;
+
+		//Infinite Time
+		static const unsigned int OIS_INFINITE = 0xFFFFFFFF;
+
+		//-------------------------------------------------------------------//
+		//--- Set these variables before uploading or modifying an effect ---//
+
+		//Direction to apply to the force - affects two axes+ effects
+		EDirection direction;
+
+		//Number of button triggering an effect (-1 means no trigger)
+		short trigger_button;
+
+		//Time to wait before an effect can be re-triggered (microseconds)
+		unsigned int trigger_interval;
+
+		//Duration of an effect (microseconds)
+		unsigned int replay_length;
+
+		//Time to wait before to start playing an effect (microseconds)
+		unsigned int replay_delay;
+
+		//Get the specific Force Effect. This should be cast depending on the EForce
+		ForceEffect* getForceEffect() const;
+
+		/**
+		@remarks
+			Set the number of Axes to use before the initial creation of the effect.
+			Can only be done prior to creation! Use the FF interface to determine
+			how many axes can be used (are availiable)
+		*/
+		void setNumAxes(short nAxes);
+
+		/**
+		@remarks
+			Returns the number of axes used in this effect
+		*/
+		short getNumAxes() const;
+
+		//------------- Library Internal -------------------------------------//
+		/**
+			set internally.. do not change or you will not be able to upload/stop
+			this effect any more. It will become lost. It is mutable so even
+			with const reference it can/will be changed by this lib
+		*/
+		mutable int _handle;
+	protected:
+		ForceEffect* effect; //Properties depend on EForce
+		short axes;          //Number of axes to use in effect
+	};
+
+	//-----------------------------------------------------------------------------//
+	/**
+		Base class of all effect property classes
+	*/
+	class _OISExport ForceEffect
+	{
+	public:
+		virtual ~ForceEffect() {}
+	};
+
+	//-----------------------------------------------------------------------------//
+	/**
+		An optional envelope to be applied to the start/end of an effect. If any of
+		these values are nonzero, then the envelope will be used in setting up the
+		effect.
+	*/
+	class _OISExport Envelope : public ForceEffect
+	{
+	public:
+		Envelope() : attackLength(0), attackLevel(0), fadeLength(0), fadeLevel(0) {}
+#if defined(OIS_MSVC_COMPILER)
+  #pragma warning (push)
+  #pragma warning (disable : 4800)
+#endif
+		bool isUsed() const { return attackLength | attackLevel | fadeLength | fadeLevel; }
+#if defined(OIS_MSVC_COMPILER)
+  #pragma warning (pop)
+#endif
+
+		// Duration of the attack (microseconds)
+		unsigned int attackLength;
+
+		// Absolute level at the beginning of the attack (0 to 10K)
+		// (automatically signed when necessary by FF core according to effect level sign)
+		unsigned short attackLevel;
+
+		// Duration of fade (microseconds)
+		unsigned int fadeLength;
+
+		// Absolute level at the end of fade (0 to 10K)
+		// (automatically signed when necessary by FF core according to effect level sign)
+		unsigned short fadeLevel;
+	};
+
+	//-----------------------------------------------------------------------------//
+	/**
+		Use this class when dealing with Force type of Constant
+	*/
+	class _OISExport ConstantEffect : public ForceEffect
+	{
+	public:
+		ConstantEffect() : level(5000) {}
+
+		class Envelope envelope; //Optional envolope
+		signed short level;       //-10K to +10k
+	};
+
+	//-----------------------------------------------------------------------------//
+	/**
+		Use this class when dealing with Force type of Ramp
+	*/
+	class _OISExport RampEffect : public ForceEffect
+	{
+	public:
+		RampEffect() : startLevel(0), endLevel(0) {}
+
+        class Envelope envelope; //Optional envelope
+		signed short startLevel;  //-10K to +10k
+		signed short endLevel;    //-10K to +10k
+	};
+
+	//-----------------------------------------------------------------------------//
+	/**
+		Use this class when dealing with Force type of Periodic
+	*/
+	class _OISExport PeriodicEffect : public ForceEffect
+	{
+	public:
+		PeriodicEffect() : magnitude(0), offset(0), phase(0), period(0) {}
+
+		class Envelope envelope;  //Optional Envelope
+
+		unsigned short magnitude;  //0 to 10,0000
+		signed short   offset;
+		unsigned short phase;      //Position at which playback begins 0 to 35,999
+		unsigned int   period;     //Period of effect (microseconds)
+	};
+
+	//-----------------------------------------------------------------------------//
+	/**
+		Use this class when dealing with Force type of Condional
+	*/
+	class _OISExport ConditionalEffect : public ForceEffect
+	{
+	public:
+		ConditionalEffect() :
+            rightCoeff(0), leftCoeff(0), rightSaturation(0), leftSaturation(0),
+			deadband(0), center(0) {}
+
+		signed short   rightCoeff;      //-10k to +10k (Positive Coeff)
+		signed short   leftCoeff;       //-10k to +10k (Negative Coeff)
+
+		unsigned short rightSaturation; //0 to 10k (Pos Saturation)
+		unsigned short leftSaturation;  //0 to 10k (Neg Saturation)
+
+		//Region around center in which the condition is not active, in the range
+		//from 0 through 10,000
+		unsigned short deadband;
+
+		//(Offset in DX) -10k and 10k
+		signed short center;
+	};
+}
+#endif //OIS_Effect_H
Index: /code/branches/RacingBots_FS18/src/external/ois/OISEvents.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISEvents.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISEvents.h	(revision 11817)
@@ -0,0 +1,43 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _OIS_EVENTHEADERS_
+#define _OIS_EVENTHEADERS_
+#include "OISPrereqs.h"
+
+namespace OIS
+{
+	/**
+		Base class of all events
+	*/
+	class _OISExport EventArg
+	{
+	public:
+		EventArg( Object* obj ) : device(obj) {}
+		virtual ~EventArg() {}
+
+		//! Pointer to the Input Device
+		const Object* device;
+	};
+}
+
+#endif //_OIS_EVENTHEADERS_
Index: /code/branches/RacingBots_FS18/src/external/ois/OISException.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISException.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISException.cpp	(revision 11817)
@@ -0,0 +1,32 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISException.h"
+
+using namespace OIS;
+
+//----------------------------------------------------------------------------//
+const char* Exception::what() const throw()
+{
+	return eText;
+}
+
Index: /code/branches/RacingBots_FS18/src/external/ois/OISException.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISException.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISException.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _OIS_EXCEPTION_HEADER_
+#define _OIS_EXCEPTION_HEADER_
+#include "OISPrereqs.h"
+#include <exception>
+
+namespace OIS
+{
+	//! Simple enum's for dealing with exceptions
+    enum OIS_ERROR
+	{
+		E_InputDisconnected,
+		E_InputDeviceNonExistant,
+		E_InputDeviceNotSupported,
+		E_DeviceFull,
+		E_NotSupported,
+		E_NotImplemented,
+		E_Duplicate,
+		E_InvalidParam,
+		E_General
+	};
+
+	/**
+	@remarks
+		Class for handling OIS exceptions. Much cleaner than checking every method for reurn value.
+		Inherits from std::exception so you can simply log those messages if you want to be generic.
+		Also note that this has a source file now since OSX was not finding the OIS::Exception symbol
+		which would cause program abortion with now correponding exception type.
+	*/
+	class _OISExport Exception : public std::exception
+	{
+		//! Hidden default
+		Exception() : eType(E_General), eLine(0), eFile(0) {}
+	public:
+		//! Creates exception object
+		Exception( OIS_ERROR err, const char* str, int line, const char *file )
+			: eType(err), eLine(line), eFile(file), eText(str) {}
+
+		~Exception() throw() {}
+
+		virtual const char* what() const throw();
+
+		//! The type of exception raised
+		const OIS_ERROR eType;
+		//! The line number it occurred on
+		const int eLine;
+		//! The source file
+		const char* eFile;
+		//! A message passed along when the exception was raised
+		const char* eText;
+	};
+}
+
+//! Use this macro to handle exceptions easily
+#define OIS_EXCEPT( err, str ) throw( OIS::Exception(err, str, __LINE__, __FILE__) )
+
+#endif //_OIS_EXCEPTION_HEADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/OISFactoryCreator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISFactoryCreator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISFactoryCreator.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_FactoryCreator_H
+#define OIS_FactoryCreator_H
+
+#include "OISPrereqs.h"
+
+namespace OIS
+{
+	/**
+		Interface for creating devices - all devices ultimately get enumerated/created via a factory.
+		A factory can create multiple types of objects.
+	*/
+	class _OISExport FactoryCreator
+	{
+	public:
+		/**
+			@remarks Virtual Destructor
+		*/
+		virtual ~FactoryCreator() {};
+
+		/**
+			@remarks Return a list of all unused devices the factory maintains
+		*/
+		virtual DeviceList freeDeviceList() = 0;
+
+		/**
+			@remarks Number of total devices of requested type
+			@param iType Type of devices to check
+		*/
+		virtual int totalDevices(Type iType) = 0;
+
+		/**
+			@remarks Number of free devices of requested type
+			@param iType Type of devices to check
+		*/
+		virtual int freeDevices(Type iType) = 0;
+
+		/**
+			@remarks Does a Type exist with the given vendor name
+			@param iType Type to check
+			@param vendor Vendor name to test
+		*/
+		virtual bool vendorExist(Type iType, const std::string & vendor) = 0;
+
+		/**
+			@remarks Creates the object
+			@param iType Type to create
+			@param bufferMode True to setup for buffered events
+			@param vendor Create a device with the vendor name, "" means vendor name is unimportant
+		*/
+		virtual Object* createObject(InputManager* creator, Type iType, bool bufferMode, const std::string & vendor = "") = 0;
+
+		/**
+			@remarks Destroys object
+			@param obj Object to destroy
+		*/
+		virtual void destroyObject(Object* obj) = 0;
+	};
+}
+#endif //OIS_FactoryCreator_H
Index: /code/branches/RacingBots_FS18/src/external/ois/OISForceFeedback.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISForceFeedback.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISForceFeedback.cpp	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISForceFeedback.h"
+#include "OISException.h"
+
+using namespace OIS;
+
+//-------------------------------------------------------------//
+ForceFeedback::ForceFeedback() : mSetGainSupport(false), mSetAutoCenterSupport(false)
+{
+}
+
+//-------------------------------------------------------------//
+void ForceFeedback::_addEffectTypes( Effect::EForce force, Effect::EType type )
+{
+	if( force <= Effect::UnknownForce || force >= Effect::_ForcesNumber
+		|| type <= Effect::Unknown || type >= Effect::_TypesNumber )
+		OIS_EXCEPT( E_General, "Can't add unknown effect Force/Type to the supported list" );
+
+	mSupportedEffects.insert(std::pair<Effect::EForce, Effect::EType>(force, type));
+}
+
+//-------------------------------------------------------------//
+void ForceFeedback::_setGainSupport( bool on )
+{
+	mSetGainSupport = on;
+}
+
+//-------------------------------------------------------------//
+void ForceFeedback::_setAutoCenterSupport( bool on )
+{
+	mSetAutoCenterSupport = on;
+}
+
+//-------------------------------------------------------------//
+const ForceFeedback::SupportedEffectList& ForceFeedback::getSupportedEffects() const
+{
+	return mSupportedEffects;
+}
+
+//-------------------------------------------------------------//
+bool ForceFeedback::supportsEffect(Effect::EForce force, Effect::EType type) const
+{
+    const std::pair<SupportedEffectList::const_iterator, SupportedEffectList::const_iterator> 
+	    iterRange = mSupportedEffects.equal_range(force);
+	SupportedEffectList::const_iterator iter;
+	for (iter = iterRange.first; iter != iterRange.second; iter++)
+	{
+	  if ((*iter).second == type)
+		return true;
+	}
+
+	return false;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/OISForceFeedback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISForceFeedback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISForceFeedback.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_ForceFeedBack_H
+#define OIS_ForceFeedBack_H
+
+#include "OISPrereqs.h"
+#include "OISInterface.h"
+#include "OISEffect.h"
+
+namespace OIS
+{
+	/**
+		Interface class for dealing with Force Feedback devices
+	*/
+	class _OISExport ForceFeedback : public Interface
+	{
+	public:
+		ForceFeedback();
+		virtual ~ForceFeedback() {}
+
+		/**
+		@remarks
+			This is like setting the master volume of an audio device.
+			Individual effects have gain levels; however, this affects all
+			effects at once.
+			Note: If the device does not support master gain setting, nothing is done
+		@param level
+			A value between 0.0 and 1.0 represent the percentage of gain. 1.0
+			being the highest possible force level (means no scaling).
+		*/
+		virtual void setMasterGain( float level ) = 0;
+		
+		/**
+		@remarks
+			If using Force Feedback effects, this should be turned off
+			before uploading any effects. Auto centering is the motor moving
+			the joystick back to center. DirectInput only has an on/off setting,
+			whereas linux has levels.. Though, we go with DI's on/off mode only
+			Note: If the device does not support auto-centering, nothing is done
+		@param auto_on
+			true to turn auto centering on, false to turn off.
+		*/
+		virtual void setAutoCenterMode( bool auto_on ) = 0;
+
+		/**
+		@remarks
+			Creates and Plays the effect immediately. If the device is full
+			of effects, it will fail to be uploaded. You will know this by
+			an invalid Effect Handle
+		*/
+		virtual void upload( const Effect* effect ) = 0;
+
+		/**
+		@remarks
+			Modifies an effect that is currently playing
+		*/
+		virtual void modify( const Effect* effect ) = 0;
+
+		/**
+		@remarks
+			Remove the effect from the device
+		*/
+		virtual void remove( const Effect* effect ) = 0;
+
+		/**
+		@remarks
+			Get the number of supported Axes for FF usage
+		*/
+        virtual short getFFAxesNumber() = 0;
+
+		/**
+		@remarks
+			Get the current load (%, in [0, 100] of the FF device memory 
+		*/
+		virtual unsigned short getFFMemoryLoad() = 0;
+
+		typedef std::multimap<Effect::EForce, Effect::EType> SupportedEffectList;
+		/**
+		@remarks
+			Get a list of all supported effects
+		*/
+		const SupportedEffectList& getSupportedEffects() const;
+
+		/**
+		@remarks
+			Tell if a given force / effect type pair is supported
+		*/
+		bool supportsEffect(Effect::EForce force, Effect::EType type) const;
+
+		void _addEffectTypes( Effect::EForce force, Effect::EType type );
+		void _setGainSupport( bool on );
+		void _setAutoCenterSupport( bool on );
+
+	protected:
+		SupportedEffectList mSupportedEffects;
+		bool mSetGainSupport;
+		bool mSetAutoCenterSupport;
+	};
+}
+#endif //OIS_ForceFeedBack_H
Index: /code/branches/RacingBots_FS18/src/external/ois/OISInputManager.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISInputManager.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISInputManager.cpp	(revision 11817)
@@ -0,0 +1,290 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISInputManager.h"
+#include "OISException.h"
+#include "OISFactoryCreator.h"
+#include "OISObject.h"
+#include <sstream>
+#include <algorithm>
+
+//Bring in correct Header / InputManager for current build platform
+#if defined OIS_SDL_PLATFORM
+#  include "SDL/SDLInputManager.h"
+#elif defined OIS_WIN32_PLATFORM
+#  include "win32/Win32InputManager.h"
+#elif defined OIS_LINUX_PLATFORM
+#  include "linux/LinuxInputManager.h"
+#elif defined OIS_APPLE_PLATFORM
+#  include "mac/MacInputManager.h"
+#elif defined OIS_IPHONE_PLATFORM
+#  include "iphone/iPhoneInputManager.h"
+#elif defined OIS_XBOX_PLATFORM
+#  include "xbox/XBoxInputManager.h"
+#endif
+
+//Bring in extra controls
+#if defined OIS_LIRC_SUPPORT
+#  include "extras/LIRC/OISLIRCFactoryCreator.h"
+#endif
+#if defined OIS_WIN32_WIIMOTE_SUPPORT
+#  include "win32/extras/WiiMote/OISWiiMoteFactoryCreator.h"
+#endif
+
+
+using namespace OIS;
+
+//----------------------------------------------------------------------------//
+InputManager::InputManager(const std::string& name) :
+	m_VersionName(OIS_VERSION_NAME),
+	mInputSystemName(name),
+	m_lircSupport(0),
+	m_wiiMoteSupport(0)
+{
+    mFactories.clear();
+    mFactoryObjects.clear();
+}
+
+//----------------------------------------------------------------------------//
+InputManager::~InputManager()
+{
+#if defined OIS_LIRC_SUPPORT
+	delete m_lircSupport;
+#endif
+
+#if defined OIS_WIN32_WIIMOTE_SUPPORT
+	delete m_wiiMoteSupport;
+#endif
+}
+
+//----------------------------------------------------------------------------//
+unsigned int InputManager::getVersionNumber()
+{
+	return OIS_VERSION;
+}
+
+//----------------------------------------------------------------------------//
+const std::string &InputManager::getVersionName()
+{
+	return m_VersionName;
+}
+
+//----------------------------------------------------------------------------//
+InputManager* InputManager::createInputSystem( std::size_t windowhandle )
+{
+	ParamList pl;
+	std::ostringstream wnd;
+	wnd << windowhandle;
+	pl.insert(std::make_pair( std::string("WINDOW"), wnd.str() ));
+
+	return createInputSystem( pl );
+}
+
+//----------------------------------------------------------------------------//
+InputManager* InputManager::createInputSystem( ParamList &paramList )
+{
+	InputManager* im = 0;
+
+#if defined OIS_SDL_PLATFORM
+	im = new SDLInputManager();
+#elif defined OIS_WIN32_PLATFORM
+	im = new Win32InputManager();
+#elif defined OIS_XBOX_PLATFORM
+	im = new XBoxInputManager();
+#elif defined OIS_LINUX_PLATFORM
+	im = new LinuxInputManager();
+#elif defined OIS_APPLE_PLATFORM
+	im = new MacInputManager();
+#elif defined OIS_IPHONE_PLATFORM
+	im = new iPhoneInputManager();
+#else
+	OIS_EXCEPT(E_General, "No platform library.. check build platform defines!");
+#endif 
+
+	try
+	{
+		im->_initialize(paramList);
+	}
+	catch(...)
+	{
+		delete im;
+		throw; //rethrow
+	}
+
+	return im;
+}
+
+//----------------------------------------------------------------------------//
+void InputManager::destroyInputSystem(InputManager* manager)
+{
+	if( manager == 0 )
+		return;
+
+	//Cleanup before deleting...
+	for( FactoryCreatedObject::iterator i = manager->mFactoryObjects.begin(); 
+		i != manager->mFactoryObjects.end(); ++i )
+	{
+		i->second->destroyObject( i->first );
+	}
+
+	manager->mFactoryObjects.clear();
+	delete manager;
+}
+
+//--------------------------------------------------------------------------------//
+const std::string& InputManager::inputSystemName()
+{
+	return mInputSystemName;
+}
+
+//--------------------------------------------------------------------------------//
+int InputManager::getNumberOfDevices( Type iType )
+{
+	//Count up all the factories devices
+	int factoyObjects = 0;
+	FactoryList::iterator i = mFactories.begin(), e = mFactories.end();
+	for( ; i != e; ++i )
+		factoyObjects += (*i)->totalDevices(iType);
+
+	return factoyObjects;
+}
+
+//----------------------------------------------------------------------------//
+DeviceList InputManager::listFreeDevices()
+{
+	DeviceList list;
+	FactoryList::iterator i = mFactories.begin(), e = mFactories.end();
+	for( ; i != e; ++i )
+	{
+		DeviceList temp = (*i)->freeDeviceList();
+		list.insert(temp.begin(), temp.end());
+	}
+
+	return list;
+}
+
+//----------------------------------------------------------------------------//
+Object* InputManager::createInputObject( Type iType, bool bufferMode, const std::string &vendor )
+{
+	Object* obj = 0;
+	FactoryList::iterator i = mFactories.begin(), e = mFactories.end();
+	for( ; i != e; ++i)
+	{
+		if( (*i)->freeDevices(iType) > 0 )
+		{
+			if( vendor == "" || (*i)->vendorExist(iType, vendor) )
+			{
+				obj = (*i)->createObject(this, iType, bufferMode, vendor);
+				mFactoryObjects[obj] = (*i);
+				break;
+			}
+		}
+	}
+
+	if(!obj)
+		OIS_EXCEPT(E_InputDeviceNonExistant, "No devices match requested type.");
+
+	try
+	{	//Intialize device
+		obj->_initialize();
+	}
+	catch(...)
+	{	//Somekind of error, cleanup and rethrow
+		destroyInputObject(obj);
+		throw;
+	}
+
+	return obj;
+}
+
+//----------------------------------------------------------------------------//
+void InputManager::destroyInputObject( Object* obj )
+{
+	if( obj == 0 )
+		return;
+
+	FactoryCreatedObject::iterator i = mFactoryObjects.find(obj);
+	if( i != mFactoryObjects.end() )
+	{
+		i->second->destroyObject(obj);
+		mFactoryObjects.erase(i);
+	}
+	else
+	{
+		OIS_EXCEPT(E_General, "Object creator not known.");
+	}
+}
+
+//----------------------------------------------------------------------------//
+void InputManager::addFactoryCreator( FactoryCreator* factory )
+{
+	if(factory != 0)
+		mFactories.push_back(factory);
+}
+
+//----------------------------------------------------------------------------//
+void InputManager::removeFactoryCreator( FactoryCreator* factory )
+{
+	if(factory != 0)
+	{
+		//First, destroy all devices created with the factory
+		for( FactoryCreatedObject::iterator i = mFactoryObjects.begin(); i != mFactoryObjects.end(); ++i )
+		{
+			if( i->second == factory )
+			{
+				i->second->destroyObject(i->first);
+				mFactoryObjects.erase(i++);
+			}
+		}
+
+		//Now, remove the factory itself
+		FactoryList::iterator fact = std::find(mFactories.begin(), mFactories.end(), factory);
+		if( fact != mFactories.end() )
+			mFactories.erase(fact);
+	}
+}
+
+//----------------------------------------------------------------------------//
+void InputManager::enableAddOnFactory(AddOnFactories factory)
+{
+#if defined OIS_LIRC_SUPPORT
+	if( factory == AddOn_LIRC || factory == AddOn_All )
+	{
+		if( m_lircSupport == 0 )
+		{
+			m_lircSupport = new LIRCFactoryCreator();
+			addFactoryCreator(m_lircSupport);
+		}
+	}
+#endif
+
+#if defined OIS_WIN32_WIIMOTE_SUPPORT
+	if( factory == AddOn_WiiMote || factory == AddOn_All )
+	{
+		if( m_wiiMoteSupport == 0 )
+		{
+			m_wiiMoteSupport = new WiiMoteFactoryCreator();
+			addFactoryCreator(m_wiiMoteSupport);
+		}
+	}
+#endif
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/OISInputManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISInputManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISInputManager.h	(revision 11817)
@@ -0,0 +1,205 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_InputManager_H
+#define OIS_InputManager_H
+
+#include "OISPrereqs.h"
+
+namespace OIS
+{
+	//Forward declare a couple of classes we might use later
+	class LIRCFactoryCreator;
+	class WiiMoteFactoryCreator;
+
+	/**
+		Base Manager class. No longer a Singleton; so feel free to create as many InputManager's as you have
+		windows.
+	*/
+	class _OISExport InputManager
+	{
+	public:
+		/**
+		@remarks
+			Returns version number (useful in DLL/SO libs)
+		@returns
+			Bits: 1-8 Patch number, 9-16 Minor version, 17-32 Major version
+		*/
+		static unsigned int getVersionNumber();
+
+		/**
+		@remarks
+			Returns version string (useful in DLL/SO libs)
+		@returns
+			Version name
+		*/
+		const std::string &getVersionName();
+
+		/**
+		@remarks
+			Creates appropriate input system dependent on platform. 
+		@param winHandle
+			Contains OS specific window handle (such as HWND or X11 Window)
+		@returns
+			A pointer to the created manager, or raises Exception
+		*/
+		static InputManager* createInputSystem( std::size_t winHandle );
+
+		/**
+		@remarks
+			Creates appropriate input system dependent on platform. 
+		@param paramList
+			ParamList contains OS specific info (such as HWND and HINSTANCE for window apps),
+			and access mode.
+		@returns
+			A pointer to the created manager, or raises Exception
+		*/
+		static InputManager* createInputSystem( ParamList &paramList );
+
+		/**
+		@remarks
+			Destroys the InputManager
+		@param manager
+			Manager to destroy
+		*/
+		static void destroyInputSystem(InputManager* manager);
+
+		/**
+		@remarks Gets the name of the current platform input system
+		*/
+		const std::string& inputSystemName();
+
+		/**
+		@remarks
+			Returns the number of the specified OIS::Type devices discovered by OIS
+		@param iType
+			Type that you are interested in
+		*/
+		int getNumberOfDevices( Type iType );
+
+		/**
+		@remarks
+			Lists all unused devices
+		@returns
+			DeviceList which contains Type and vendor of device
+		*/
+		DeviceList listFreeDevices();
+
+		/**
+		@remarks
+			Tries to create an object with the specified vendor. If you have no
+			preference of vendor, leave vender as default (""). Raises exception on failure
+		*/
+		Object* createInputObject( Type iType, bool bufferMode, const std::string &vendor = "");
+
+		/**
+		@remarks Destroys Input Object
+		*/
+		void destroyInputObject( Object* obj );
+
+		/**
+		@remarks
+			Add a custom object factory to allow for user controls.
+		@param factory
+			Factory instance to add
+		@notes
+			Make sure you do not delete the factory before devices created from
+			the factory are destroyed (either by calling RemoveFactoryCreator, or shutting down
+			the input system). Order should be something like the following:
+				* Create Input System
+				* Create Factory Instance
+				* AddFactoryCreator(factory)
+				* Create a device from the InputManager (device created by factory)
+				* One of the follwoing:
+					* removeFactoryCreator(factory)
+					* inputManager->destroyInputObject(obj)
+				* destroyInputSystem(inputManager)
+				* destroy Factory Instance
+			You can safely delete the factory instance once you have removed it or shut down the
+			input manager.
+		*/
+		void addFactoryCreator( FactoryCreator* factory );
+
+		/**
+		@remarks
+			Remove a previously added object factory
+		@param factory
+			Factory object to remove.
+		@notes
+			Removing a factory will automatically destroy any Objects created from the factory
+		*/
+		void removeFactoryCreator( FactoryCreator* factory );
+
+		//! All generic devices OIS supports internally (if they are compiled in)
+		enum AddOnFactories
+		{
+			AddOn_All = 0,		//All Devices
+			AddOn_LIRC = 1,		//PC Linux Infrared Remote Control
+			AddOn_WiiMote = 2	//PC WiiMote Support
+		};
+
+		/**
+		@remarks
+			Enable an addon FactoryCreator extension. By default, none are activated.
+			If the desired support was not compiled in, this has no effect. Calling
+			multiple times has no effect. Once activated, there is no way to deactivate -
+			simply destroy and recreate input manager.
+		*/
+		void enableAddOnFactory(AddOnFactories factory);
+
+	protected:
+		/**
+		@remarks
+			Called from createInputSystem, gives derived input class a chance to setup after it is created
+		*/
+		virtual void _initialize(ParamList &paramList) = 0;
+
+		/**
+		@remarks
+			Derived classes must provide input system name
+		*/
+		InputManager(const std::string& name);
+
+		/**
+		@remarks
+			Virtual Destructor - this base class will clean up all devices still opened in mFactoryObjects list
+		*/
+		virtual ~InputManager();
+
+		//! OIS Version name
+		const std::string m_VersionName;
+
+		//! FactoryCreator list	
+		FactoryList mFactories;
+
+		//! Factory created objects - useful so we can find creator to send destruction request to
+		FactoryCreatedObject mFactoryObjects;
+
+		//! Name of the input system
+		const std::string mInputSystemName;
+
+		//! Extra factory (not enabled by default)
+		LIRCFactoryCreator *m_lircSupport;
+		WiiMoteFactoryCreator *m_wiiMoteSupport;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISInterface.h	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Interface_H
+#define OIS_Interface_H
+
+#include "OISPrereqs.h"
+
+namespace OIS
+{
+	/**
+		An Object's interface is a way to gain write access to devices which support
+		it. For example, force feedack.
+	*/
+	class _OISExport Interface
+	{
+	public:
+		virtual ~Interface() {};
+
+		//! Type of Interface
+		enum IType
+		{
+			ForceFeedback,
+			Reserved
+		};
+	};
+}
+#endif //OIS_Interface_H
Index: /code/branches/RacingBots_FS18/src/external/ois/OISJoyStick.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISJoyStick.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISJoyStick.cpp	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISJoyStick.h"
+
+using namespace OIS;
+
+//----------------------------------------------------------------------------//
+JoyStick::JoyStick(const std::string &vendor, bool buffered, int devID, InputManager* creator) :
+	Object(vendor, OISJoyStick, buffered, devID, creator),
+	mSliders(0),
+	mPOVs(0),
+	mListener(0),
+	mVector3Sensitivity(OIS_JOYSTICK_VECTOR3_DEFAULT)
+{
+}
+
+//----------------------------------------------------------------------------//
+int JoyStick::getNumberOfComponents(ComponentType cType) const
+{
+	switch( cType )
+	{
+	case OIS_Button:	return (int)mState.mButtons.size();
+	case OIS_Axis:		return (int)mState.mAxes.size();
+	case OIS_Slider:	return mSliders;
+	case OIS_POV:		return mPOVs;
+	case OIS_Vector3:	return (int)mState.mVectors.size();
+	default:			return 0;
+	}
+}
+
+//----------------------------------------------------------------------------//
+void JoyStick::setVector3Sensitivity(float degrees)
+{
+	mVector3Sensitivity = degrees;
+}
+
+//----------------------------------------------------------------------------//
+float JoyStick::getVector3Sensitivity() const
+{
+	return mVector3Sensitivity;
+}
+
+//----------------------------------------------------------------------------//
+void JoyStick::setEventCallback( JoyStickListener *joyListener )
+{
+	mListener = joyListener;
+}
+
+//----------------------------------------------------------------------------//
+JoyStickListener* JoyStick::getEventCallback() const
+{
+	return mListener;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/OISJoyStick.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISJoyStick.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISJoyStick.h	(revision 11817)
@@ -0,0 +1,228 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Joystick_H
+#define OIS_Joystick_H
+#include "OISObject.h"
+#include "OISEvents.h"
+
+namespace OIS
+{
+	/** @remarks default sensitivity for vector3 component of joystick */
+	#define OIS_JOYSTICK_VECTOR3_DEFAULT 2.28f
+
+	//! POV / HAT Joystick component
+	class _OISExport Pov : public Component
+	{
+	public:
+		Pov() : Component(OIS_POV), direction(0) {}
+
+		static const int Centered  = 0x00000000;
+		static const int North     = 0x00000001;
+		static const int South     = 0x00000010;
+		static const int East      = 0x00000100;
+		static const int West      = 0x00001000;
+		static const int NorthEast = 0x00000101;
+		static const int SouthEast = 0x00000110;
+		static const int NorthWest = 0x00001001;
+		static const int SouthWest = 0x00001010;
+
+		int direction;
+	};
+
+	//! A sliding axis - only used in Win32 Right Now
+	class _OISExport Slider : public Component
+	{
+	public:
+		Slider() : Component(OIS_Slider), abX(0), abY(0) {};
+		//! true if pushed, false otherwise
+		int abX, abY;
+	};
+
+	/**
+		Represents the state of the joystick
+		All members are valid for both buffered and non buffered mode
+		Sticks with zero values are not present on the device
+	*/
+	class _OISExport JoyStickState
+	{
+	public:
+		//! Constructor
+		JoyStickState() { clear(); }
+
+		//! Represents all the buttons (uses a bitset)
+		std::vector<bool> mButtons;
+
+		//! Represents all the single axes on the device
+		std::vector<Axis> mAxes;
+
+		//! Represents the value of a POV. Maximum of 4
+		Pov mPOV[4];
+
+		//! Represent the max sliders
+		Slider mSliders[4];
+
+		//! Represents all Vector type controls the device exports
+		std::vector<Vector3> mVectors;
+
+		//! internal method to reset all variables to initial values
+		void clear()
+		{
+			for( std::vector<bool>::iterator i = mButtons.begin(), e = mButtons.end(); i != e; ++i )
+			{
+				(*i) = false;
+			}
+
+			for( std::vector<Axis>::iterator i = mAxes.begin(), e = mAxes.end(); i != e; ++i )
+			{
+				i->absOnly = true; //Currently, joysticks only report Absolute values
+				i->clear();
+			}
+
+			for( std::vector<Vector3>::iterator i = mVectors.begin(), e = mVectors.end(); i != e; ++i )
+			{
+				i->clear();
+			}
+
+			for( int i = 0; i < 4; ++i )
+			{
+				mPOV[i].direction = Pov::Centered;
+				mSliders[i].abX = mSliders[i].abY = 0;
+			}
+		}
+	};
+
+	/** Specialised for joystick events */
+	class _OISExport JoyStickEvent : public EventArg
+	{
+	public:
+		JoyStickEvent( Object* obj, const JoyStickState &st ) : EventArg(obj), state(st) {}
+		virtual ~JoyStickEvent() {}
+
+		const JoyStickState &state;
+	};
+
+	/**
+		To recieve buffered joystick input, derive a class from this, and implement the
+		methods here. Then set the call back to your JoyStick instance with JoyStick::setEventCallback
+		Each JoyStick instance can use the same callback class, as a devID number will be provided
+		to differentiate between connected joysticks. Of course, each can have a seperate
+		callback instead.
+	*/
+	class _OISExport JoyStickListener
+	{
+	public:
+		virtual ~JoyStickListener() {}
+		/** @remarks Joystick button down event */
+		virtual bool buttonPressed( const JoyStickEvent &arg, int button ) = 0;
+		
+		/** @remarks Joystick button up event */
+		virtual bool buttonReleased( const JoyStickEvent &arg, int button ) = 0;
+
+		/** @remarks Joystick axis moved event */
+		virtual bool axisMoved( const JoyStickEvent &arg, int axis ) = 0;
+
+		//-- Not so common control events, so are not required --//
+		//! Joystick Event, and sliderID
+		virtual bool sliderMoved( const JoyStickEvent &, int index) {return true;}
+		
+		//! Joystick Event, and povID
+		virtual bool povMoved( const JoyStickEvent &arg, int index) {return true;}
+
+		//! Joystick Event, and Vector3ID
+		virtual bool vector3Moved( const JoyStickEvent &arg, int index) {return true;}
+	};
+
+	/**
+		Joystick base class. To be implemented by specific system (ie. DirectX joystick)
+		This class is useful as you remain OS independent using this common interface.
+	*/
+	class _OISExport JoyStick : public Object
+	{
+	public:
+		virtual ~JoyStick() {}
+
+		/**
+		@remarks
+			Returns the number of requested components
+		@param cType
+			The ComponentType you are interested in knowing about
+		*/
+		int getNumberOfComponents(ComponentType cType) const;
+
+		/**
+		@remarks
+			Sets a cutoff limit for changes in the Vector3 component for movement to 
+			be ignored. Helps reduce much event traffic for frequent small/sensitive
+			changes
+		@param degrees
+			The degree under which Vector3 events should be discarded
+		*/
+		void setVector3Sensitivity(float degrees = OIS_JOYSTICK_VECTOR3_DEFAULT);
+
+		/**
+		@remarks
+			Returns the sensitivity cutoff for Vector3 Component
+		*/
+		float getVector3Sensitivity() const;
+
+		/**
+		@remarks
+			Register/unregister a JoyStick Listener - Only one allowed for simplicity. If broadcasting
+			is neccessary, just broadcast from the callback you registered.
+		@param joyListener
+			Send a pointer to a class derived from JoyStickListener or 0 to clear the callback
+		*/
+		virtual void setEventCallback( JoyStickListener *joyListener );
+
+		/** @remarks Returns currently set callback.. or null */
+		JoyStickListener* getEventCallback() const;
+
+		/** @remarks Returns the state of the joystick - is valid for both buffered and non buffered mode */
+		const JoyStickState& getJoyStickState() const { return mState; }
+
+		//! The minimal axis value
+		static const int MIN_AXIS = -32768;
+
+		//! The maximum axis value
+		static const int MAX_AXIS = 32767;
+
+	protected:
+		JoyStick(const std::string &vendor, bool buffered, int devID, InputManager* creator);
+
+		//! Number of sliders
+		int mSliders;
+
+		//! Number of POVs
+		int mPOVs;
+
+		//! The JoyStickState structure (contains all component values)
+		JoyStickState mState;
+
+		//! The callback listener
+		JoyStickListener *mListener;
+
+		//! Adjustment factor for orientation vector accuracy
+		float mVector3Sensitivity;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISKeyboard.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISKeyboard.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISKeyboard.cpp	(revision 11817)
@@ -0,0 +1,45 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISKeyboard.h"
+#include "OISException.h"
+
+using namespace OIS;
+
+//----------------------------------------------------------------------//
+void Keyboard::setTextTranslation( TextTranslationMode mode )
+{
+	mTextMode = mode;
+}
+
+//----------------------------------------------------------------------//
+bool Keyboard::isModifierDown( Modifier mod ) const
+{
+#if defined(OIS_MSVC_COMPILER)
+  #pragma warning (push)
+  #pragma warning (disable : 4800)
+#endif
+	return (mModifiers & mod);
+#if defined(OIS_MSVC_COMPILER)
+  #pragma warning (pop)
+#endif
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/OISKeyboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISKeyboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISKeyboard.h	(revision 11817)
@@ -0,0 +1,312 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Keyboard_H
+#define OIS_Keyboard_H
+#include "OISObject.h"
+#include "OISEvents.h"
+
+namespace OIS
+{
+	//! Keyboard scan codes
+	enum KeyCode
+	{
+		KC_UNASSIGNED  = 0x00,
+		KC_ESCAPE      = 0x01,
+		KC_1           = 0x02,
+		KC_2           = 0x03,
+		KC_3           = 0x04,
+		KC_4           = 0x05,
+		KC_5           = 0x06,
+		KC_6           = 0x07,
+		KC_7           = 0x08,
+		KC_8           = 0x09,
+		KC_9           = 0x0A,
+		KC_0           = 0x0B,
+		KC_MINUS       = 0x0C,    // - on main keyboard
+		KC_EQUALS      = 0x0D,
+		KC_BACK        = 0x0E,    // backspace
+		KC_TAB         = 0x0F,
+		KC_Q           = 0x10,
+		KC_W           = 0x11,
+		KC_E           = 0x12,
+		KC_R           = 0x13,
+		KC_T           = 0x14,
+		KC_Y           = 0x15,
+		KC_U           = 0x16,
+		KC_I           = 0x17,
+		KC_O           = 0x18,
+		KC_P           = 0x19,
+		KC_LBRACKET    = 0x1A,
+		KC_RBRACKET    = 0x1B,
+		KC_RETURN      = 0x1C,    // Enter on main keyboard
+		KC_LCONTROL    = 0x1D,
+		KC_A           = 0x1E,
+		KC_S           = 0x1F,
+		KC_D           = 0x20,
+		KC_F           = 0x21,
+		KC_G           = 0x22,
+		KC_H           = 0x23,
+		KC_J           = 0x24,
+		KC_K           = 0x25,
+		KC_L           = 0x26,
+		KC_SEMICOLON   = 0x27,
+		KC_APOSTROPHE  = 0x28,
+		KC_GRAVE       = 0x29,    // accent
+		KC_LSHIFT      = 0x2A,
+		KC_BACKSLASH   = 0x2B,
+		KC_Z           = 0x2C,
+		KC_X           = 0x2D,
+		KC_C           = 0x2E,
+		KC_V           = 0x2F,
+		KC_B           = 0x30,
+		KC_N           = 0x31,
+		KC_M           = 0x32,
+		KC_COMMA       = 0x33,
+		KC_PERIOD      = 0x34,    // . on main keyboard
+		KC_SLASH       = 0x35,    // / on main keyboard
+		KC_RSHIFT      = 0x36,
+		KC_MULTIPLY    = 0x37,    // * on numeric keypad
+		KC_LMENU       = 0x38,    // left Alt
+		KC_SPACE       = 0x39,
+		KC_CAPITAL     = 0x3A,
+		KC_F1          = 0x3B,
+		KC_F2          = 0x3C,
+		KC_F3          = 0x3D,
+		KC_F4          = 0x3E,
+		KC_F5          = 0x3F,
+		KC_F6          = 0x40,
+		KC_F7          = 0x41,
+		KC_F8          = 0x42,
+		KC_F9          = 0x43,
+		KC_F10         = 0x44,
+		KC_NUMLOCK     = 0x45,
+		KC_SCROLL      = 0x46,    // Scroll Lock
+		KC_NUMPAD7     = 0x47,
+		KC_NUMPAD8     = 0x48,
+		KC_NUMPAD9     = 0x49,
+		KC_SUBTRACT    = 0x4A,    // - on numeric keypad
+		KC_NUMPAD4     = 0x4B,
+		KC_NUMPAD5     = 0x4C,
+		KC_NUMPAD6     = 0x4D,
+		KC_ADD         = 0x4E,    // + on numeric keypad
+		KC_NUMPAD1     = 0x4F,
+		KC_NUMPAD2     = 0x50,
+		KC_NUMPAD3     = 0x51,
+		KC_NUMPAD0     = 0x52,
+		KC_DECIMAL     = 0x53,    // . on numeric keypad
+		KC_OEM_102     = 0x56,    // < > | on UK/Germany keyboards
+		KC_F11         = 0x57,
+		KC_F12         = 0x58,
+		KC_F13         = 0x64,    //                     (NEC PC98)
+		KC_F14         = 0x65,    //                     (NEC PC98)
+		KC_F15         = 0x66,    //                     (NEC PC98)
+		KC_KANA        = 0x70,    // (Japanese keyboard)
+		KC_ABNT_C1     = 0x73,    // / ? on Portugese (Brazilian) keyboards
+		KC_CONVERT     = 0x79,    // (Japanese keyboard)
+		KC_NOCONVERT   = 0x7B,    // (Japanese keyboard)
+		KC_YEN         = 0x7D,    // (Japanese keyboard)
+		KC_ABNT_C2     = 0x7E,    // Numpad . on Portugese (Brazilian) keyboards
+		KC_NUMPADEQUALS= 0x8D,    // = on numeric keypad (NEC PC98)
+		KC_PREVTRACK   = 0x90,    // Previous Track (KC_CIRCUMFLEX on Japanese keyboard)
+		KC_AT          = 0x91,    //                     (NEC PC98)
+		KC_COLON       = 0x92,    //                     (NEC PC98)
+		KC_UNDERLINE   = 0x93,    //                     (NEC PC98)
+		KC_KANJI       = 0x94,    // (Japanese keyboard)
+		KC_STOP        = 0x95,    //                     (NEC PC98)
+		KC_AX          = 0x96,    //                     (Japan AX)
+		KC_UNLABELED   = 0x97,    //                        (J3100)
+		KC_NEXTTRACK   = 0x99,    // Next Track
+		KC_NUMPADENTER = 0x9C,    // Enter on numeric keypad
+		KC_RCONTROL    = 0x9D,
+		KC_MUTE        = 0xA0,    // Mute
+		KC_CALCULATOR  = 0xA1,    // Calculator
+		KC_PLAYPAUSE   = 0xA2,    // Play / Pause
+		KC_MEDIASTOP   = 0xA4,    // Media Stop
+		KC_VOLUMEDOWN  = 0xAE,    // Volume -
+		KC_VOLUMEUP    = 0xB0,    // Volume +
+		KC_WEBHOME     = 0xB2,    // Web home
+		KC_NUMPADCOMMA = 0xB3,    // , on numeric keypad (NEC PC98)
+		KC_DIVIDE      = 0xB5,    // / on numeric keypad
+		KC_SYSRQ       = 0xB7,
+		KC_RMENU       = 0xB8,    // right Alt
+		KC_PAUSE       = 0xC5,    // Pause
+		KC_HOME        = 0xC7,    // Home on arrow keypad
+		KC_UP          = 0xC8,    // UpArrow on arrow keypad
+		KC_PGUP        = 0xC9,    // PgUp on arrow keypad
+		KC_LEFT        = 0xCB,    // LeftArrow on arrow keypad
+		KC_RIGHT       = 0xCD,    // RightArrow on arrow keypad
+		KC_END         = 0xCF,    // End on arrow keypad
+		KC_DOWN        = 0xD0,    // DownArrow on arrow keypad
+		KC_PGDOWN      = 0xD1,    // PgDn on arrow keypad
+		KC_INSERT      = 0xD2,    // Insert on arrow keypad
+		KC_DELETE      = 0xD3,    // Delete on arrow keypad
+		KC_LWIN        = 0xDB,    // Left Windows key
+		KC_RWIN        = 0xDC,    // Right Windows key
+		KC_APPS        = 0xDD,    // AppMenu key
+		KC_POWER       = 0xDE,    // System Power
+		KC_SLEEP       = 0xDF,    // System Sleep
+		KC_WAKE        = 0xE3,    // System Wake
+		KC_WEBSEARCH   = 0xE5,    // Web Search
+		KC_WEBFAVORITES= 0xE6,    // Web Favorites
+		KC_WEBREFRESH  = 0xE7,    // Web Refresh
+		KC_WEBSTOP     = 0xE8,    // Web Stop
+		KC_WEBFORWARD  = 0xE9,    // Web Forward
+		KC_WEBBACK     = 0xEA,    // Web Back
+		KC_MYCOMPUTER  = 0xEB,    // My Computer
+		KC_MAIL        = 0xEC,    // Mail
+		KC_MEDIASELECT = 0xED     // Media Select
+	};
+
+	/**
+		Specialised for key events
+	*/
+	class _OISExport KeyEvent : public EventArg
+	{
+	public:
+		KeyEvent(Object* obj, KeyCode kc, unsigned int txt) : EventArg(obj), key(kc), text(txt) {}
+		virtual ~KeyEvent() {}
+
+		//! KeyCode of event
+		const KeyCode key;
+		//! Text character, depends on current TextTranslationMode
+		unsigned int text;
+	};
+
+	/**
+		To recieve buffered keyboard input, derive a class from this, and implement the
+		methods here. Then set the call back to your Keyboard instance with Keyboard::setEventCallback
+	*/
+	class _OISExport KeyListener
+	{
+	public:
+		virtual ~KeyListener() {}
+		virtual bool keyPressed(const KeyEvent &arg) = 0;
+		virtual bool keyReleased(const KeyEvent &arg) = 0;		
+	};
+
+	/**
+		Keyboard base class. To be implemented by specific system (ie. DirectX Keyboard)
+		This class is useful as you remain OS independent using this common interface.
+	*/
+	class _OISExport Keyboard : public Object
+	{
+	public:
+		virtual ~Keyboard() {};
+		
+		/**
+		@remarks
+			Returns true if key is donwn
+		@param key
+			A KeyCode to check
+		*/
+		virtual bool isKeyDown(KeyCode key) const = 0;
+
+		/**
+		@remarks
+			Register/unregister a Keyboard Listener - Only one allowed for simplicity. If broadcasting
+			is neccessary, just broadcast from the callback you registered.
+		@param keyListener
+			Send a pointer to a class derived from KeyListener or 0 to clear the callback
+		*/
+		virtual void setEventCallback(KeyListener *keyListener) { mListener = keyListener;}
+
+		/**
+		@remarks
+			Returns currently set callback.. or 0
+		*/
+		KeyListener* getEventCallback() const {return mListener;}
+
+		//! TextTranslation Mode
+		enum TextTranslationMode
+		{
+			Off,
+			Unicode,
+			Ascii
+		};
+
+		/**
+		@remarks
+			Enable extra processing to translate KC_*** to an
+			actual text character based off of locale. Different 
+			managers may implement none or all. Check the 
+			translation mode after setting to be sure
+		@param mode
+			Off, Unicode, Ascii
+		*/
+		virtual void setTextTranslation(TextTranslationMode mode);
+
+		/**
+		@remarks
+			Returns current translation mode
+		*/
+		TextTranslationMode getTextTranslation() const {return mTextMode;}
+		
+		/**
+		@remarks
+			Translates KeyCode to string representation.
+			For example, KC_ENTER will be "Enter" - Locale
+			specific of course.
+		@param kc
+			KeyCode to convert
+		@returns
+			The string as determined from the current locale
+		*/
+		virtual const std::string& getAsString(KeyCode kc) = 0;
+
+		//! Enum of bit position of modifer
+		enum Modifier
+		{
+			Shift = 0x0000001,
+			Ctrl  = 0x0000010,
+			Alt   = 0x0000100
+		};
+
+		/**
+		@remarks
+			Check modifier status
+		*/
+		bool isModifierDown(Modifier mod) const;
+
+		/**
+		@remarks
+			Copies the state of the keys into the sent buffer
+			(in the form of 1 is down and 0 is up)
+		*/
+		virtual void copyKeyStates(char keys[256]) const = 0;
+		
+	protected:
+		Keyboard(const std::string &vendor, bool buffered, int devID, InputManager* creator)
+			: Object(vendor, OISKeyboard, buffered, devID, creator),
+			mModifiers(0), mListener(0), mTextMode(Unicode) {}
+
+		//! Bit field that holds status of Alt, Ctrl, Shift
+		unsigned int mModifiers;
+
+		//! Used for buffered/actionmapping callback
+		KeyListener *mListener;
+
+		//! The current translation mode
+		TextTranslationMode mTextMode;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISMouse.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISMouse.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISMouse.h	(revision 11817)
@@ -0,0 +1,138 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Mouse_H
+#define OIS_Mouse_H
+#include "OISObject.h"
+#include "OISEvents.h"
+
+namespace OIS
+{
+	//! Button ID for mouse devices
+	enum MouseButtonID
+	{
+		MB_Left = 0, MB_Right, MB_Middle,
+		MB_Button3, MB_Button4,	MB_Button5, MB_Button6,	MB_Button7
+	};
+
+	/**
+		Represents the state of the mouse
+		All members are valid for both buffered and non buffered mode
+	*/
+	class _OISExport MouseState
+	{
+	public:
+		MouseState() : width(50), height(50), buttons(0) {};
+
+		/** Represents the height/width of your display area.. used if mouse clipping
+		or mouse grabbed in case of X11 - defaults to 50.. Make sure to set this
+		and change when your size changes.. */
+		mutable int width, height;
+
+		//! X Axis component
+		Axis X;
+
+		//! Y Axis Component
+		Axis Y;
+
+		//! Z Axis Component
+		Axis Z;
+
+		//! represents all buttons - bit position indicates button down
+		int buttons;
+
+		//! Button down test
+		inline bool buttonDown( MouseButtonID button ) const
+		{
+			return ((buttons & ( 1L << button )) == 0) ? false : true;
+		}
+
+		//! Clear all the values
+		void clear()
+		{
+			X.clear();
+			Y.clear();
+			Z.clear();
+			buttons = 0;
+		}
+	};
+
+	/** Specialised for mouse events */
+	class _OISExport MouseEvent : public EventArg
+	{
+	public:
+		MouseEvent( Object *obj, const MouseState &ms )	: EventArg(obj), state(ms) {}
+		virtual ~MouseEvent() {}
+
+		//! The state of the mouse - including buttons and axes
+		const MouseState &state;
+	};
+
+	/**
+		To recieve buffered mouse input, derive a class from this, and implement the
+		methods here. Then set the call back to your Mouse instance with Mouse::setEventCallback
+	*/
+	class _OISExport MouseListener
+	{
+	public:
+		virtual ~MouseListener() {}
+		virtual bool mouseMoved( const MouseEvent &arg ) = 0;
+		virtual bool mousePressed( const MouseEvent &arg, MouseButtonID id ) = 0;
+		virtual bool mouseReleased( const MouseEvent &arg, MouseButtonID id ) = 0;
+	};
+
+	/**
+		Mouse base class. To be implemented by specific system (ie. DirectX Mouse)
+		This class is useful as you remain OS independent using this common interface.
+	*/
+	class _OISExport Mouse : public Object
+	{
+	public:
+		virtual ~Mouse() {}
+
+		/**
+		@remarks
+			Register/unregister a Mouse Listener - Only one allowed for simplicity. If broadcasting
+			is neccessary, just broadcast from the callback you registered.
+		@param mouseListener
+			Send a pointer to a class derived from MouseListener or 0 to clear the callback
+		*/
+		virtual void setEventCallback( MouseListener *mouseListener ) {mListener = mouseListener;}
+
+		/** @remarks Returns currently set callback.. or 0 */
+		MouseListener* getEventCallback() const {return mListener;}
+
+		/** @remarks Returns the state of the mouse - is valid for both buffered and non buffered mode */
+		const MouseState& getMouseState() const { return mState; }
+
+	protected:
+		Mouse(const std::string &vendor, bool buffered, int devID, InputManager* creator)
+			: Object(vendor, OISMouse, buffered, devID, creator), mListener(0) {}
+
+		//! The state of the mouse
+		MouseState mState;
+
+		//! Used for buffered/actionmapping callback
+		MouseListener *mListener;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISMultiTouch.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISMultiTouch.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISMultiTouch.h	(revision 11817)
@@ -0,0 +1,169 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_MultiTouch_H
+#define OIS_MultiTouch_H
+#include "OISObject.h"
+#include "OISEvents.h"
+
+#include <set>
+#include <vector>
+
+#define OIS_MAX_NUM_TOUCHES 4   // 4 finger touches are probably the highest we'll ever get
+
+namespace OIS
+{
+	/**
+		Represents the state of the multi-touch device
+		All members are valid for both buffered and non buffered mode
+	*/
+    
+	//! Touch Event type
+	enum MultiTypeEventTypeID
+	{
+		MT_None = 0, MT_Pressed, MT_Released, MT_Moved, MT_Cancelled
+	};
+
+	class _OISExport MultiTouchState
+	{
+	public:
+		MultiTouchState() : width(50), height(50), touchType(MT_None) {};
+
+		/** Represents the height/width of your display area.. used if touch clipping
+		or touch grabbed in case of X11 - defaults to 50.. Make sure to set this
+		and change when your size changes.. */
+		mutable int width, height;
+
+		//! X Axis component
+		Axis X;
+
+		//! Y Axis Component
+		Axis Y;
+
+		//! Z Axis Component
+		Axis Z;
+
+        int touchType;
+
+        inline bool touchIsType( MultiTypeEventTypeID touch ) const
+		{
+			return ((touchType & ( 1L << touch )) == 0) ? false : true;
+		}
+        
+		//! Clear all the values
+		void clear()
+		{
+			X.clear();
+			Y.clear();
+			Z.clear();
+            touchType = MT_None;
+		}
+	};
+
+	/** Specialised for multi-touch events */
+	class _OISExport MultiTouchEvent : public EventArg
+	{
+	public:
+		MultiTouchEvent( Object *obj, const MultiTouchState &ms ) : EventArg(obj), state(ms) {}
+		virtual ~MultiTouchEvent() {}
+
+		//! The state of the touch - including axes
+		const MultiTouchState &state;
+	};
+
+	/**
+		To receive buffered touch input, derive a class from this, and implement the
+		methods here. Then set the call back to your MultiTouch instance with MultiTouch::setEventCallback
+	*/
+	class _OISExport MultiTouchListener
+	{
+	public:
+		virtual ~MultiTouchListener() {}
+		virtual bool touchMoved( const MultiTouchEvent &arg ) = 0;
+		virtual bool touchPressed( const MultiTouchEvent &arg ) = 0;
+		virtual bool touchReleased( const MultiTouchEvent &arg ) = 0;
+		virtual bool touchCancelled( const MultiTouchEvent &arg ) = 0;
+	};
+
+	/**
+		MultiTouch base class. To be implemented by specific system (ie. iPhone UITouch)
+		This class is useful as you remain OS independent using this common interface.
+	*/
+	class _OISExport MultiTouch : public Object
+	{
+	public:
+		virtual ~MultiTouch() {}
+
+		/**
+		@remarks
+			Register/unregister a MultiTouch Listener - Only one allowed for simplicity. If broadcasting
+			is necessary, just broadcast from the callback you registered.
+		@param touchListener
+			Send a pointer to a class derived from MultiTouchListener or 0 to clear the callback
+		*/
+		virtual void setEventCallback( MultiTouchListener *touchListener ) {mListener = touchListener;}
+
+		/** @remarks Returns currently set callback.. or 0 */
+		MultiTouchListener* getEventCallback() {return mListener;}
+
+		/** @remarks Clear out the set of input states.  Should be called after input has been processed by the application */
+        void clearStates(void) { mStates.clear(); }
+
+		/** @remarks Returns the state of the touch - is valid for both buffered and non buffered mode */
+		std::vector<MultiTouchState> getMultiTouchStates() const { return mStates; }
+        
+        /** @remarks Returns the first n touch states.  Useful if you know your app only needs to 
+                process n touches.  The return value is a vector to allow random access */
+        const std::vector<MultiTouchState> getFirstNTouchStates(int n) {
+            std::vector<MultiTouchState> states;
+            for( unsigned int i = 0; i < mStates.size(); i++ ) {
+                if(!(mStates[i].touchIsType(MT_None))) {
+                    states.push_back(mStates[i]);
+                }
+            }
+            return states;
+        }
+
+        /** @remarks Returns the first n touch states.  Useful if you know your app only needs to 
+         process n touches.  The return value is a vector to allow random access */
+        const std::vector<MultiTouchState> getMultiTouchStatesOfType(MultiTypeEventTypeID type) {
+            std::vector<MultiTouchState> states;
+            for( unsigned int i = 0; i < mStates.size(); i++ ) {
+                if(mStates[i].touchIsType(type)) {
+                    states.push_back(mStates[i]);
+                }
+            }
+            return states;
+        }
+        
+	protected:
+		MultiTouch(const std::string &vendor, bool buffered, int devID, InputManager* creator)
+			: Object(vendor, OISMultiTouch, buffered, devID, creator), mListener(0) {}
+
+		//! The state of the touch device, implemented in a vector to store the state from each finger touch
+        std::vector<MultiTouchState> mStates;
+
+		//! Used for buffered/actionmapping callback
+		MultiTouchListener *mListener;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISObject.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISObject.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISObject.cpp	(revision 11817)
@@ -0,0 +1,23 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+//#include "OISObject.h"
Index: /code/branches/RacingBots_FS18/src/external/ois/OISObject.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISObject.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISObject.h	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Object_H
+#define OIS_Object_H
+
+#include "OISPrereqs.h"
+#include "OISInterface.h"
+
+namespace OIS
+{
+	/**	The base class of all input types. */
+	class _OISExport Object
+	{
+	public:
+		virtual ~Object() {}
+
+		/**	@remarks Get the type of device	*/
+		Type type() const { return mType; }
+
+		/**	@remarks Get the vender string name	*/
+		const std::string& vendor() const { return mVendor; }
+
+		/**	@remarks Get buffered mode - true is buffered, false otherwise */
+		virtual bool buffered() const { return mBuffered; }
+
+		/** @remarks Returns this input object's creator */
+		InputManager* getCreator() const { return mCreator; }
+
+		/** @remarks Sets buffered mode	*/
+		virtual void setBuffered(bool buffered) = 0;
+
+		/**	@remarks Used for updating call once per frame before checking state or to update events */
+		virtual void capture() = 0;
+
+		/**	@remarks This may/may not) differentiate the different controllers based on (for instance) a port number (useful for console InputManagers) */
+		virtual int getID() const {return mDevID;}
+
+		/**
+		@remarks
+			If available, get an interface to write to some devices.
+			Examples include, turning on and off LEDs, ForceFeedback, etc
+		@param type
+			The type of interface you are looking for
+		*/
+		virtual Interface* queryInterface(Interface::IType type) = 0;
+
+		/**	@remarks Internal... Do not call this directly. */
+		virtual void _initialize() = 0;
+
+	protected:
+		Object(const std::string &vendor, Type iType, bool buffered,
+			   int devID, InputManager* creator) :
+					mVendor(vendor),
+					mType(iType),
+					mBuffered(buffered),
+					mDevID(devID),
+					mCreator(creator) {}
+
+		//! Vendor name if applicable/known
+		std::string mVendor;
+
+		//! Type of controller object
+		Type mType;
+
+		//! Buffered flag
+		bool mBuffered;
+
+		//! Not fully implemented yet
+		int mDevID;
+
+		//! The creator who created this object
+		InputManager* mCreator;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/OISPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/OISPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/OISPrereqs.h	(revision 11817)
@@ -0,0 +1,226 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Prereqs_H
+#define OIS_Prereqs_H
+//----------------------------------------------------------------------------//
+// This Header File contains: forward declared classes
+//  * Forward Declarations of all public API classes
+//  * Several typedef's used around the library
+//  * Base class component types
+//  * Preprocessor definitons
+//----------------------------------------------------------------------------//
+
+//-------------- Common STL Containers ---------------------------------------//
+#include <vector>
+#include <string>
+#include <map>
+#include "OISConfig.h"
+
+// Default is blank for most OS's
+#define _OISExport
+
+//-------------- Determine Compiler ---------------------------------
+#if defined( _MSC_VER )
+#	define OIS_MSVC_COMPILER
+#elif defined( __GNUC__ )
+#	if defined( __WIN32__ ) || defined( _WIN32 )
+#		define OIS_MINGW_COMPILER
+#	else
+#		define OIS_GCC_COMPILER
+#	endif
+#elif defined( __BORLANDC__ )
+#	define OIS_BORLAND_COMPILER
+#else
+#	error No Recognized Compiler!
+#endif
+
+// --------------- Determine Operating System Platform ---------------
+#if defined( __WIN32__ ) || defined( _WIN32 ) // Windows 2000, XP, ETC
+#	if defined ( _XBOX )
+#		define OIS_XBOX_PLATFORM
+#	else
+#		define OIS_WIN32_PLATFORM
+#		if !defined( OIS_STATIC_LIB )
+#			undef _OISExport
+			//Ignorable Dll interface warning...
+#           if !defined(OIS_MINGW_COMPILER)
+#			    pragma warning (disable : 4251)
+#           endif
+#			if defined( OIS_NONCLIENT_BUILD )
+#				define _OISExport __declspec( dllexport )
+#			else
+#               if defined(OIS_MINGW_COMPILER)
+#                   define _OISExport
+#               else
+#				    define _OISExport __declspec( dllimport )
+#               endif
+#			endif
+#		endif
+#	endif
+#elif defined( __APPLE_CC__ ) // Apple OS X
+    // Device                                       Simulator
+#   if __IPHONE_OS_VERSION_MIN_REQUIRED >= 20201 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 20000
+//#   if __IPHONE_OS_VERSION_MIN_REQUIRED >= 30000 || __IPHONE_OS_VERSION_MIN_REQUIRED >= 30000
+#       define OIS_IPHONE_PLATFORM
+#   else
+#       define OIS_APPLE_PLATFORM
+#   endif
+#   undef _OISExport
+#   define _OISExport __attribute__((visibility("default")))
+#else //Probably Linux
+#	define OIS_LINUX_PLATFORM
+#endif
+
+//Is Processor 32 or 64 bits...
+#if defined(__x86_64__)
+#	define OIS_ARCH_64
+#else
+#	define OIS_ARCH_32
+#endif
+
+//-------------- Common Classes, Enums, and Typdef's -------------------------//
+#define OIS_VERSION_MAJOR 1
+#define OIS_VERSION_MINOR 3
+#define OIS_VERSION_PATCH 0
+#define OIS_VERSION_NAME "1.3.0"
+
+#define OIS_VERSION ((OIS_VERSION_MAJOR << 16) | (OIS_VERSION_MINOR << 8) | OIS_VERSION_PATCH)
+
+namespace OIS
+{
+	//Forward Declarations
+	class InputManager;
+	class FactoryCreator;
+	class Object;
+	class Keyboard;
+	class Mouse;
+	class JoyStick;
+    class MultiTouch;
+	class KeyListener;
+	class MouseListener;
+    class MultiTouchListener;
+	class JoyStickListener;
+	class Interface;
+	class ForceFeedback;
+	class Effect;
+	class Exception;
+
+	//! Way to send OS nuetral parameters.. ie OS Window handles, modes, flags
+	typedef std::multimap<std::string, std::string> ParamList;
+
+	//! List of FactoryCreator's
+	typedef std::vector<FactoryCreator*> FactoryList;
+
+	//! Map of FactoryCreator created Objects
+	typedef std::map<Object*, FactoryCreator*> FactoryCreatedObject;
+
+	//! Each Input class has a General Type variable, a form of RTTI
+    enum Type
+	{
+		OISUnknown       = 0,
+		OISKeyboard      = 1,
+		OISMouse         = 2,
+		OISJoyStick      = 3,
+		OISTablet        = 4,
+		OISMultiTouch    = 5
+	};
+
+	//! Map of device objects connected and their respective vendors
+	typedef std::multimap<Type, std::string> DeviceList;
+
+	//--------     Shared common components    ------------------------//
+
+	//! Base type for all device components (button, axis, etc)
+    enum ComponentType
+	{
+		OIS_Unknown = 0,
+		OIS_Button  = 1, //ie. Key, mouse button, joy button, etc
+		OIS_Axis    = 2, //ie. A joystick or mouse axis
+		OIS_Slider  = 3, //
+		OIS_POV     = 4, //ie. Arrow direction keys
+		OIS_Vector3 = 5  //ie. WiiMote orientation
+	};
+
+	//! Base of all device components (button, axis, etc)
+	class _OISExport Component
+	{
+	public:
+		Component() : cType(OIS_Unknown) {};
+		Component(ComponentType type) : cType(type) {};
+		//! Indicates what type of coponent this is
+		ComponentType cType;
+	};
+
+	//! Button can be a keyboard key, mouse button, etc
+	class _OISExport Button : public Component
+	{
+	public:
+		Button() : Component(OIS_Button), pushed(false) {}
+		Button(bool bPushed) : Component(OIS_Button), pushed(bPushed) {}
+		//! true if pushed, false otherwise
+		bool pushed;
+	};
+
+	//! Axis component
+	class _OISExport Axis : public Component
+	{
+	public:
+		Axis() : Component(OIS_Axis), abs(0), rel(0), absOnly(false) {};
+
+		//! Absoulte and Relative value components
+		int abs, rel;
+
+		//! Indicates if this Axis only supports Absoulte (ie JoyStick)
+		bool absOnly;
+
+		//! Used internally by OIS
+		void clear()
+		{
+			abs = rel = 0;
+		}
+	};
+
+	//! A 3D Vector component (perhaps an orientation, as in the WiiMote)
+	class _OISExport Vector3 : public Component
+	{
+	public:
+		Vector3() {}
+		Vector3(float _x, float _y, float _z) : Component(OIS_Vector3), x(_x), y(_y), z(_z) {};
+		
+		//! X component of vector
+		float x;
+		
+		//! Y component of vector
+		float y;
+
+		//! Z component of vector
+		float z;
+
+		void clear()
+		{
+			x = y = z = 0.0f;
+		}
+	};
+}
+
+#endif //end if prereq header defined
Index: /code/branches/RacingBots_FS18/src/external/ois/ReadMe.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/ReadMe.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/ReadMe.txt	(revision 11817)
@@ -0,0 +1,76 @@
+======================================================================================
+================ LICENSE =============================================================
+======================================================================================
+
+The zlib/libpng License
+
+Copyright (c) 2005-2010 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no 
+event will the authors be held liable for any damages arising from the use of this 
+software.
+
+Permission is granted to anyone to use this software for any purpose, including 
+commercial applications, and to alter it and redistribute it freely, subject to the 
+following restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated 
+		but is not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+
+
+======================================================================================
+================ LICENSE EXPLAINED ===================================================
+======================================================================================
+In case the license was not clear enough... Basically, you can link with this lib 
+which puts no restrictions on what you have to license your code as. You can modify 
+this lib, and not have release your changes. Though, as explained above, <bold> 
+Altered source versions must be plainly marked as such, and must not be misrepresented
+as being the original software </bold>
+
+This is to allow users the greatest flexibility in what you can use this lib for.
+
+======================================================================================
+================ INFO ================================================================
+======================================================================================
+
+Cross Platform Object Oriented Input Lib System. Meant to be very robust and 
+compatiable with many systems and operating systems
+
+Win32/
+	Contains Visual Studio .Net Solution Files
+	Contains CodeBlocks project files for OIS
+	
+	---- Dependencies ------------------------------------------------------
+	DirectInput 8
+
+
+Linux/
+	---- Dependencies ------------------------------------------------------
+	X11
+        Newer Linux Kernel (2.6+ ?) for Event API
+
+	Steps to build on Linux:
+	./bootstrap
+	./configure
+	./make && make install
+
+	---- Configure build options --------------------------------------------
+	./configure --help              --- List all configure options
+
+
+LinuxCB/
+        Contains CodeBlock files for building OIS and Demos with codeblocks
+        This project file looks for Ogre and other dependencies in /usr/local/lib
+        and /usr/local/include. If installed elsewhere, modify the project
+        settings. It also installs libOIS to ~/libs
+
+Mac/
+	XCode-2.2/
+		Working, mostly complete OSX vackend.
Index: /code/branches/RacingBots_FS18/src/external/ois/VERSION
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/VERSION	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/VERSION	(revision 11817)
@@ -0,0 +1,2 @@
+OIS SVN v1.3 branch updated on 2011/02/20 (revision 32)
+https://wgois.svn.sourceforge.net/svnroot/wgois/ois/branches/v1-3/
Index: /code/branches/RacingBots_FS18/src/external/ois/changes_orxonox.diff
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/changes_orxonox.diff	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/changes_orxonox.diff	(revision 11817)
@@ -0,0 +1,111 @@
+--- OISPrereqs.h	(revision 7141)
++++ OISPrereqs.h	(working copy)
+@@ -60,7 +60,7 @@
+ #		define OIS_XBOX_PLATFORM
+ #	else
+ #		define OIS_WIN32_PLATFORM
+-#		if defined( OIS_DYNAMIC_LIB )
++#		if !defined( OIS_STATIC_LIB )
+ #			undef _OISExport
+ 			//Ignorable Dll interface warning...
+ #           if !defined(OIS_MINGW_COMPILER)
+
+
+--- linux/EventHelpers.cpp	(revision 5668)
++++ linux/EventHelpers.cpp	(working copy)
+@@ -35,6 +35,20 @@
+ # include <iostream>
+ #endif
+ 
++// Fixes for missing macros in input.h
++#ifndef FF_EFFECT_MIN
++#define FF_EFFECT_MIN FF_RUMBLE
++#endif
++#ifndef FF_EFFECT_MAX
++#define FF_EFFECT_MAX FF_RAMP
++#endif
++#ifndef FF_WAVEFORM_MIN
++#define FF_WAVEFORM_MIN FF_SQUARE
++#endif
++#ifndef FF_WAVEFORM_MAX
++#define FF_WAVEFORM_MAX FF_CUSTOM
++#endif
++
+ using namespace std;
+ using namespace OIS;
+ 
+
+--- win32/Win32ForceFeedback.cpp
++++ win32/Win32ForceFeedback.cpp
+@@ -25,7 +25,7 @@
+ #include <math.h>
+ 
+ // 0 = No trace; 1 = Important traces; 2 = Debug traces
+-#define OIS_WIN32_JOYFF_DEBUG 1
++#define OIS_WIN32_JOYFF_DEBUG 0
+ 
+ #if (defined (_DEBUG) || defined(OIS_WIN32_JOYFF_DEBUG))
+   #include <iostream>
+
+
+--- win32/Win32JoyStick.cpp
++++ win32/Win32JoyStick.cpp
+@@ -26,6 +26,14 @@
+ #include "OISEvents.h"
+ #include "OISException.h"
+ 
++// (Orxonox): Required for MinGW to compile properly
++#ifdef __MINGW32__
++#  include <oaidl.h>
++#  ifndef __MINGW_EXTENSION
++#    define __MINGW_EXTENSION __extension__
++#  endif
++#endif
++
+ #include <cassert>
+ #include <wbemidl.h>
+ #include <oleauto.h>
+@@ -39,6 +47,11 @@
+    }
+ #endif
+ 
++// (Orxonox): MinGW doesn't have swscanf_s
++#ifdef __MINGW32__
++#	define swscanf_s swscanf
++#endif
++
+ #ifdef OIS_WIN32_XINPUT_SUPPORT
+ #	pragma comment(lib, "xinput.lib")
+ #endif
+@@ -583,7 +596,12 @@
+     bool bCleanupCOM = SUCCEEDED(hr);
+ 
+     // Create WMI
++    // (Orxonox): Fix for MinGW
++#ifdef __MINGW32__
++    hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pIWbemLocator);
++#else
+     hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
++#endif
+     if( FAILED(hr) || pIWbemLocator == NULL )
+         goto LCleanup;
+ 
+
+--- mac/MacHIDManager.cpp
++++ mac/MacHIDManager.cpp
+@@ -406,6 +406,7 @@
+ 			switch(iType)
+ 			{
+ 				case OISJoyStick:
++                {
+ 					int totalDevs = totalDevices(iType);
+ 					int freeDevs = freeDevices(iType);
+ 					int devID = totalDevs - freeDevs;
+@@ -413,6 +414,7 @@
+ 					obj = new MacJoyStick((*it)->combinedKey, bufferMode, *it, creator, devID);
+ 					(*it)->inUse = true;
+ 					return obj;
++                }
+ 				case OISTablet:
+ 					//Create MacTablet
+ 					break;
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,16 @@
+ADD_SOURCE_FILES(OIS_FILES
+  EventHelpers.h
+  LinuxForceFeedback.h
+  LinuxInputManager.h
+  LinuxJoyStickEvents.h
+  LinuxKeyboard.h
+  LinuxMouse.h
+  LinuxPrereqs.h
+
+  EventHelpers.cpp
+  LinuxForceFeedback.cpp
+  LinuxInputManager.cpp
+  LinuxJoyStickEvents.cpp
+  LinuxKeyboard.cpp
+  LinuxMouse.cpp
+)
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/EventHelpers.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/EventHelpers.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/EventHelpers.cpp	(revision 11817)
@@ -0,0 +1,391 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "linux/EventHelpers.h"
+#include "linux/LinuxPrereqs.h"
+#include "linux/LinuxForceFeedback.h"
+#include "OISException.h"
+#include "OISJoyStick.h"
+
+#include <linux/input.h>
+#include <cstring>
+
+//#define OIS_LINUX_JOY_DEBUG
+
+#ifdef OIS_LINUX_JOY_DEBUG
+# include <iostream>
+#endif
+
+// Fixes for missing macros in input.h
+#ifndef FF_EFFECT_MIN
+#define FF_EFFECT_MIN FF_RUMBLE
+#endif
+#ifndef FF_EFFECT_MAX
+#define FF_EFFECT_MAX FF_RAMP
+#endif
+#ifndef FF_WAVEFORM_MIN
+#define FF_WAVEFORM_MIN FF_SQUARE
+#endif
+#ifndef FF_WAVEFORM_MAX
+#define FF_WAVEFORM_MAX FF_CUSTOM
+#endif
+
+using namespace std;
+using namespace OIS;
+
+class DeviceComponentInfo
+{
+public:
+	vector<int> buttons, relAxes, absAxes, hats;
+};
+
+bool inline isBitSet(unsigned char bits[], unsigned int bit)
+{
+  return (bits[(bit)/(sizeof(unsigned char)*8)] >> ((bit)%(sizeof(unsigned char)*8))) & 1;
+}
+
+//-----------------------------------------------------------------------------//
+DeviceComponentInfo getComponentInfo( int deviceID )
+{
+	unsigned char ev_bits[1 + EV_MAX/8/sizeof(unsigned char)];
+	memset( ev_bits, 0, sizeof(ev_bits) );
+
+	//Read "all" (hence 0) components of the device
+#ifdef OIS_LINUX_JOY_DEBUG
+	cout << "EventUtils::getComponentInfo(" << deviceID 
+		 << ") : Reading device events features" << endl;
+#endif
+	if (ioctl(deviceID, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) == -1)
+		OIS_EXCEPT( E_General, "Could not read device events features");
+
+	DeviceComponentInfo components;
+
+	for (int i = 0; i < EV_MAX; i++)
+	{
+		if( isBitSet(ev_bits, i) )
+		{
+		    // Absolute axis.
+		    if(i == EV_ABS)
+			{
+			    unsigned char abs_bits[1 + ABS_MAX/8/sizeof(unsigned char)];
+			    memset( abs_bits, 0, sizeof(abs_bits) );
+
+#ifdef OIS_LINUX_JOY_DEBUG
+				cout << "EventUtils::getComponentInfo(" << deviceID 
+					 << ") : Reading device absolute axis features" << endl;
+#endif
+
+				if (ioctl(deviceID, EVIOCGBIT(i, sizeof(abs_bits)), abs_bits) == -1)
+				    OIS_EXCEPT( E_General, "Could not read device absolute axis features");
+
+				for (int j = 0; j < ABS_MAX; j++)
+				{
+				    if( isBitSet(abs_bits, j) )
+					{
+						//input_absinfo abInfo;
+						//ioctl( fd, EVIOCGABS(j), abInfo );
+						if( j >= ABS_HAT0X && j <= ABS_HAT3Y )
+						{
+							components.hats.push_back(j);
+						}
+						else
+						{
+							components.absAxes.push_back(j);
+							//input_absinfo absinfo;
+							//ioctl(deviceID, EVIOCGABS(j), &absinfo);
+							//We cannot actually change these values :|
+							//absinfo.minimum = JoyStick::MIN_AXIS;
+							//absinfo.maximum = JoyStick::MAX_AXIS;
+							//ioctl(deviceID, EVIOCSABS(j), &absinfo);
+						}
+					}
+				}
+			}
+			else if(i == EV_REL)
+			{
+			    unsigned char rel_bits[1 + REL_MAX/8/sizeof(unsigned char)];
+				memset( rel_bits, 0, sizeof(rel_bits) );
+				
+#ifdef OIS_LINUX_JOY_DEBUG
+				cout << "EventUtils::getComponentInfo(" << deviceID 
+					 << ") : Reading device relative axis features" << endl;
+#endif
+
+				if (ioctl(deviceID, EVIOCGBIT(i, sizeof(rel_bits)), rel_bits) == -1)
+				    OIS_EXCEPT( E_General, "Could not read device relative axis features");
+				
+				for (int j = 0; j < REL_MAX; j++)
+				{
+				    if( isBitSet(rel_bits, j) )
+					{
+					    components.relAxes.push_back(j);
+					}
+				}
+			}
+			else if(i == EV_KEY)
+			{
+			    unsigned char key_bits[1 + KEY_MAX/8/sizeof(unsigned char)];
+				memset( key_bits, 0, sizeof(key_bits) );
+				
+#ifdef OIS_LINUX_JOY_DEBUG
+				cout << "EventUtils::getComponentInfo(" << deviceID 
+					 << ") : Reading device buttons features" << endl;
+#endif
+
+				if (ioctl(deviceID, EVIOCGBIT(i, sizeof(key_bits)), key_bits) == -1)
+				    OIS_EXCEPT( E_General, "Could not read device buttons features");
+				
+				for (int j = 0; j < KEY_MAX; j++)
+				{
+				    if( isBitSet(key_bits, j) )
+					{
+					    components.buttons.push_back(j);
+					}
+				}
+			}
+		}
+	}
+
+	return components;
+}
+
+//-----------------------------------------------------------------------------//
+bool EventUtils::isJoyStick( int deviceID, JoyStickInfo &js )
+{
+	if( deviceID == -1 ) 
+		OIS_EXCEPT( E_General, "Error with File Descriptor" );
+
+	DeviceComponentInfo info = getComponentInfo( deviceID );
+
+	int buttons = 0;
+	bool joyButtonFound = false;
+	js.button_map.clear();
+
+	#ifdef OIS_LINUX_JOY_DEBUG
+	cout << endl << "Displaying ButtonMapping Status:" << endl;
+	#endif
+	for(vector<int>::iterator i = info.buttons.begin(), e = info.buttons.end(); i != e; ++i )
+	{
+		//Check to ensure we find at least one joy only button
+		if( (*i >= BTN_JOYSTICK && *i < BTN_GAMEPAD)  
+			|| (*i >= BTN_GAMEPAD && *i < BTN_DIGI)
+			|| (*i >= BTN_WHEEL && *i < KEY_OK) )
+			joyButtonFound = true;
+
+		js.button_map[*i] = buttons++;
+
+		#ifdef OIS_LINUX_JOY_DEBUG
+		  cout << "Button Mapping ID (hex): " << hex << *i 
+			   << " OIS Button Num: " << dec << buttons-1 << endl;
+		#endif
+	}
+	#ifdef OIS_LINUX_JOY_DEBUG
+	cout << endl;
+	#endif
+
+	//Joy Buttons found, so it must be a joystick or pad
+	if( joyButtonFound )
+	{
+		js.joyFileD = deviceID;
+		js.vendor = getName(deviceID);
+		js.buttons = buttons;
+		js.axes = info.relAxes.size() + info.absAxes.size();
+		js.hats = info.hats.size();
+		#ifdef OIS_LINUX_JOY_DEBUG
+		  cout << endl << "Device name:" << js.vendor << endl;
+		  cout << "Device unique Id:" << getUniqueId(deviceID) << endl;
+		  cout << "Device physical location:" << getPhysicalLocation(deviceID) << endl;
+		#endif
+
+		//Map the Axes
+		#ifdef OIS_LINUX_JOY_DEBUG
+		  cout << endl << "Displaying AxisMapping Status:" << endl;
+		#endif
+		int axes = 0;
+		for(vector<int>::iterator i = info.absAxes.begin(), e = info.absAxes.end(); i != e; ++i )
+		{
+			js.axis_map[*i] = axes;
+
+#ifdef OIS_LINUX_JOY_DEBUG
+			cout << "EventUtils::isJoyStick(" << deviceID 
+					  << ") : Reading device absolute axis #" << *i << " features" << endl;
+#endif
+
+			input_absinfo absinfo;
+			if (ioctl(deviceID, EVIOCGABS(*i), &absinfo) == -1)
+				OIS_EXCEPT( E_General, "Could not read device absolute axis features");
+			js.axis_range[axes] = Range(absinfo.minimum, absinfo.maximum);
+
+			#ifdef OIS_LINUX_JOY_DEBUG
+			  cout << "Axis Mapping ID (hex): " << hex << *i 
+				   << " OIS Axis Num: " << dec << axes << endl;
+			#endif
+
+			++axes;
+		}
+	}
+
+	return joyButtonFound;
+}
+
+//-----------------------------------------------------------------------------//
+string EventUtils::getName( int deviceID )
+{
+#ifdef OIS_LINUX_JOY_DEBUG
+	cout << "EventUtils::getName(" << deviceID 
+		 << ") : Reading device name" << endl;
+#endif
+
+	char name[OIS_DEVICE_NAME];
+	if (ioctl(deviceID, EVIOCGNAME(OIS_DEVICE_NAME), name) == -1)
+		OIS_EXCEPT( E_General, "Could not read device name");
+	return string(name);
+}
+
+//-----------------------------------------------------------------------------//
+string EventUtils::getUniqueId( int deviceID )
+{
+#ifdef OIS_LINUX_JOY_DEBUG
+	cout << "EventUtils::getUniqueId(" << deviceID 
+		 << ") : Reading device unique Id" << endl;
+#endif
+
+#define OIS_DEVICE_UNIQUE_ID 128
+	char uId[OIS_DEVICE_UNIQUE_ID];
+	if (ioctl(deviceID, EVIOCGUNIQ(OIS_DEVICE_UNIQUE_ID), uId) == -1)
+		OIS_EXCEPT( E_General, "Could not read device unique Id");
+	return string(uId);
+}
+
+//-----------------------------------------------------------------------------//
+string EventUtils::getPhysicalLocation( int deviceID )
+{
+#ifdef OIS_LINUX_JOY_DEBUG
+	cout << "EventUtils::getPhysicalLocation(" << deviceID 
+		 << ") : Reading device physical location" << endl;
+#endif
+
+#define OIS_DEVICE_PHYSICAL_LOCATION 128
+	char physLoc[OIS_DEVICE_PHYSICAL_LOCATION];
+	if (ioctl(deviceID, EVIOCGPHYS(OIS_DEVICE_PHYSICAL_LOCATION), physLoc) == -1)
+		OIS_EXCEPT( E_General, "Could not read device physical location");
+	return string(physLoc);
+}
+
+//-----------------------------------------------------------------------------//
+void EventUtils::enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff )
+{
+	//Linux Event to OIS Event Mappings
+	map<int, Effect::EType> typeMap;
+	typeMap[FF_CONSTANT] = Effect::Constant;
+	typeMap[FF_RAMP]     = Effect::Ramp;
+	typeMap[FF_SPRING]   = Effect::Spring;
+	typeMap[FF_FRICTION] = Effect::Friction;
+	typeMap[FF_SQUARE]   = Effect::Square;
+	typeMap[FF_TRIANGLE] = Effect::Triangle;
+	typeMap[FF_SINE]     = Effect::Sine;
+	typeMap[FF_SAW_UP]   = Effect::SawToothUp;
+	typeMap[FF_SAW_DOWN] = Effect::SawToothDown;
+	typeMap[FF_DAMPER]   = Effect::Damper;
+	typeMap[FF_INERTIA]  = Effect::Inertia;
+	typeMap[FF_CUSTOM]   = Effect::Custom;
+
+	map<int, Effect::EForce> forceMap;
+	forceMap[FF_CONSTANT] = Effect::ConstantForce;
+	forceMap[FF_RAMP]     = Effect::RampForce;
+	forceMap[FF_SPRING]   = Effect::ConditionalForce;
+	forceMap[FF_FRICTION] = Effect::ConditionalForce;
+	forceMap[FF_SQUARE]   = Effect::PeriodicForce;
+	forceMap[FF_TRIANGLE] = Effect::PeriodicForce;
+	forceMap[FF_SINE]     = Effect::PeriodicForce;
+	forceMap[FF_SAW_UP]   = Effect::PeriodicForce;
+	forceMap[FF_SAW_DOWN] = Effect::PeriodicForce;
+	forceMap[FF_DAMPER]   = Effect::ConditionalForce;
+	forceMap[FF_INERTIA]  = Effect::ConditionalForce;
+	forceMap[FF_CUSTOM]   = Effect::CustomForce;
+
+	//Remove any previously existing memory and create fresh
+	removeForceFeedback( ff );
+	*ff = new LinuxForceFeedback(deviceID);
+
+	//Read overall force feedback features
+	unsigned char ff_bits[1 + FF_MAX/8/sizeof(unsigned char)];
+	memset(ff_bits, 0, sizeof(ff_bits));
+
+#ifdef OIS_LINUX_JOY_DEBUG
+	cout << "EventUtils::enumerateForceFeedback(" << deviceID 
+		 << ") : Reading device force feedback features" << endl;
+#endif
+
+	if (ioctl(deviceID, EVIOCGBIT(EV_FF, sizeof(ff_bits)), ff_bits) == -1)
+		OIS_EXCEPT( E_General, "Could not read device force feedback features");
+
+
+    #ifdef OIS_LINUX_JOY_DEBUG
+	cout << "FF bits: " << hex;
+	for (int i = 0; i < sizeof(ff_bits); i++)
+		cout << (int)ff_bits[i];
+	cout << endl << dec;
+    #endif
+
+	//FF Axes
+	//if( isBitSet(ff_bits, ABS_X) ) //X Axis
+	//if( isBitSet(ff_bits, ABS_Y) ) //Y Axis
+	//if( isBitSet(ff_bits, ABS_WHEEL) ) //Wheel
+
+	//FF Effects
+	for( int effect = FF_EFFECT_MIN; effect <= FF_WAVEFORM_MAX; effect++ )
+	{
+		// The RUMBLE force type is ignored, as periodic force one is more powerfull.
+		// The PERIODIC force type is processed later, for each associated periodic effect type.
+		if (effect == FF_RUMBLE || effect == FF_PERIODIC)
+			continue;
+
+		if(isBitSet(ff_bits, effect))
+		{
+			#ifdef OIS_LINUX_JOY_DEBUG
+		    cout << "  Effect Type: " << Effect::getEffectTypeName(typeMap[effect]) << endl;
+			#endif
+
+			(*ff)->_addEffectTypes( forceMap[effect], typeMap[effect] );
+		}
+	}
+
+	//FF device properties
+	if (isBitSet(ff_bits, FF_GAIN))
+		(*ff)->_setGainSupport(true);
+		
+	if (isBitSet(ff_bits, FF_AUTOCENTER))
+		(*ff)->_setAutoCenterSupport(true);
+
+	//Check to see if any effects were added, else destroy the pointer
+	const ForceFeedback::SupportedEffectList &list = (*ff)->getSupportedEffects();
+	if( list.size() == 0 )
+		removeForceFeedback( ff );
+}
+
+//-----------------------------------------------------------------------------//
+void EventUtils::removeForceFeedback( LinuxForceFeedback** ff )
+{
+	delete *ff;
+	*ff = 0;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/EventHelpers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/EventHelpers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/EventHelpers.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _LINUX_OISEVENT_HEADER_
+#define _LINUX_OISEVENT_HEADER_
+
+#include "linux/LinuxPrereqs.h"
+
+#define OIS_MAX_DEVICES 32
+#define OIS_DEVICE_NAME 128
+
+namespace OIS
+{
+	class EventUtils
+	{
+	public:
+		static bool isJoyStick( int deviceID, JoyStickInfo &js );
+		static bool isMouse( int ) {return false;}
+		static bool isKeyboard( int ) {return false;}
+
+		//Double pointer is so that we can set the value of the sent pointer
+		static void enumerateForceFeedback( int deviceID, LinuxForceFeedback** ff );
+		static void removeForceFeedback( LinuxForceFeedback** ff );
+
+		static std::string getName( int deviceID );
+		static std::string getUniqueId( int deviceID );
+		static std::string getPhysicalLocation( int deviceID );
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxForceFeedback.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxForceFeedback.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxForceFeedback.cpp	(revision 11817)
@@ -0,0 +1,560 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "linux/LinuxForceFeedback.h"
+#include "OISException.h"
+
+#include <cstdlib>
+#include <errno.h>
+#include <memory.h>
+#include <unistd.h>
+
+using namespace OIS;
+
+// 0 = No trace; 1 = Important traces; 2 = Debug traces
+#define OIS_LINUX_JOYFF_DEBUG 1
+
+#ifdef OIS_LINUX_JOYFF_DEBUG
+# include <iostream>
+  using namespace std;
+#endif
+
+//--------------------------------------------------------------//
+LinuxForceFeedback::LinuxForceFeedback(int deviceID) :
+	ForceFeedback(), mJoyStick(deviceID)
+{
+}
+
+//--------------------------------------------------------------//
+LinuxForceFeedback::~LinuxForceFeedback()
+{
+	// Unload all effects.
+	for(EffectList::iterator i = mEffectList.begin(); i != mEffectList.end(); ++i )
+	{
+		struct ff_effect *linEffect = i->second;
+		if( linEffect )
+			_unload(linEffect->id);
+	}
+
+	mEffectList.clear();
+}
+
+//--------------------------------------------------------------//
+unsigned short LinuxForceFeedback::getFFMemoryLoad()
+{
+	int nEffects = -1;
+	if (ioctl(mJoyStick, EVIOCGEFFECTS, &nEffects) == -1)
+		OIS_EXCEPT(E_General, "Unknown error reading max number of uploaded effects.");
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "LinuxForceFeedback("<< mJoyStick  
+		 << ") : Read device max number of uploaded effects : " << nEffects << endl;
+#endif
+
+	return (unsigned short int)(nEffects > 0 ? 100.0*mEffectList.size()/nEffects : 100);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::setMasterGain(float value)
+{
+	if (!mSetGainSupport)
+	{
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+		cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain " 
+			 << "is not supported by the device" << endl;
+#endif
+		return;
+	}
+
+	struct input_event event;
+
+	memset(&event, 0, sizeof(event));
+	event.type = EV_FF;
+	event.code = FF_GAIN;
+	if (value < 0.0)
+		value = 0.0;
+	else if (value > 1.0)
+		value = 1.0;
+	event.value = (__s32)(value * 0xFFFFUL);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+	cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting master gain to " 
+		 << value << " => " << event.value << endl;
+#endif
+
+	if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
+		OIS_EXCEPT(E_General, "Unknown error changing master gain.");
+	}
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::setAutoCenterMode(bool enabled)
+{
+	if (!mSetAutoCenterSupport)
+	{
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+		cout << "LinuxForceFeedback("<< mJoyStick << ") : Setting auto-center mode " 
+			 << "is not supported by the device" << endl;
+#endif
+		return;
+	}
+
+	struct input_event event;
+
+	memset(&event, 0, sizeof(event));
+	event.type = EV_FF;
+	event.code = FF_AUTOCENTER;
+	event.value = (__s32)(enabled*0xFFFFFFFFUL);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 0)
+	cout << "LinuxForceFeedback("<< mJoyStick << ") : Toggling auto-center to " 
+		 << enabled << " => 0x" << hex << event.value << dec << endl;
+#endif
+
+	if (write(mJoyStick, &event, sizeof(event)) != sizeof(event)) {
+		OIS_EXCEPT(E_General, "Unknown error toggling auto-center.");
+	}
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::upload( const Effect* effect )
+{
+	switch( effect->force )
+	{
+		case OIS::Effect::ConstantForce: 
+			_updateConstantEffect(effect);	
+			break;
+		case OIS::Effect::ConditionalForce: 
+			_updateConditionalEffect(effect);
+			break;
+		case OIS::Effect::PeriodicForce: 
+			_updatePeriodicEffect(effect);
+			break;
+		case OIS::Effect::RampForce: 
+			_updateRampEffect(effect);	
+			break;
+		case OIS::Effect::CustomForce: 
+			//_updateCustomEffect(effect);
+			//break;
+		default: 
+			OIS_EXCEPT(E_NotImplemented, "Requested force not implemented yet, sorry!"); 
+			break;
+	}
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::modify( const Effect* effect )
+{
+	upload(effect);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::remove( const Effect* effect )
+{
+	//Get the effect - if it exists
+	EffectList::iterator i = mEffectList.find(effect->_handle);
+	if( i != mEffectList.end() )
+	{
+		struct ff_effect *linEffect = i->second;
+		if( linEffect )
+		{
+			_stop(effect->_handle);
+
+			_unload(effect->_handle);
+
+			free(linEffect);
+
+			mEffectList.erase(i);
+		}
+		else
+			mEffectList.erase(i);
+	}
+}
+
+//--------------------------------------------------------------//
+// To Signed16/Unsigned15 safe conversions
+#define MaxUnsigned15Value 0x7FFF
+#define toUnsigned15(value) \
+	(__u16)((value) < 0 ? 0 : ((value) > MaxUnsigned15Value ? MaxUnsigned15Value : (value)))
+
+#define MaxSigned16Value  0x7FFF
+#define MinSigned16Value -0x7FFF
+#define toSigned16(value) \
+  (__s16)((value) < MinSigned16Value ? MinSigned16Value : ((value) > MaxSigned16Value ? MaxSigned16Value : (value)))
+
+// OIS to Linux duration
+#define LinuxInfiniteDuration 0xFFFF
+#define OISDurationUnitMS 1000 // OIS duration unit (microseconds), expressed in milliseconds (theLinux duration unit)
+
+// linux/input.h : All duration values are expressed in ms. Values above 32767 ms (0x7fff)
+//                 should not be used and have unspecified results.
+#define LinuxDuration(oisDuration) ((oisDuration) == Effect::OIS_INFINITE ? LinuxInfiniteDuration \
+									: toUnsigned15((oisDuration)/OISDurationUnitMS))
+
+
+// OIS to Linux levels
+#define OISMaxLevel 10000
+#define LinuxMaxLevel 0x7FFF
+
+// linux/input.h : Valid range for the attack and fade levels is 0x0000 - 0x7fff
+#define LinuxPositiveLevel(oisLevel) toUnsigned15(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
+
+#define LinuxSignedLevel(oisLevel) toSigned16(LinuxMaxLevel*(long)(oisLevel)/OISMaxLevel)
+
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_setCommonProperties(struct ff_effect *event, 
+											  struct ff_envelope *ffenvelope, 
+											  const Effect* effect, const Envelope *envelope )
+{
+	memset(event, 0, sizeof(struct ff_effect));
+
+	if (envelope && ffenvelope && envelope->isUsed()) {
+		ffenvelope->attack_length = LinuxDuration(envelope->attackLength);
+		ffenvelope->attack_level = LinuxPositiveLevel(envelope->attackLevel);
+		ffenvelope->fade_length = LinuxDuration(envelope->fadeLength);
+		ffenvelope->fade_level = LinuxPositiveLevel(envelope->fadeLevel);
+	}
+	
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << endl;
+	if (envelope && ffenvelope)
+	{
+		cout << "  Enveloppe :" << endl
+			 << "    AttackLen : " << envelope->attackLength
+			 << " => " << ffenvelope->attack_length << endl 
+			 << "    AttackLvl : " << envelope->attackLevel
+			 << " => " << ffenvelope->attack_level << endl 
+			 << "    FadeLen   : " << envelope->fadeLength
+			 << " => " << ffenvelope->fade_length << endl
+			 << "    FadeLvl   : " << envelope->fadeLevel
+			 << " => " << ffenvelope->fade_level << endl;
+	}
+#endif
+	
+	event->direction = (__u16)(1 + (effect->direction*45.0+135.0)*0xFFFFUL/360.0);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  Direction : " << Effect::getDirectionName(effect->direction)
+		 << " => 0x" << hex << event->direction << dec << endl;
+#endif
+
+	// TODO trigger_button 0 vs. -1
+	event->trigger.button = effect->trigger_button; // < 0 ? 0 : effect->trigger_button;
+	event->trigger.interval = LinuxDuration(effect->trigger_interval);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  Trigger :" << endl
+		 << "    Button   : " << effect->trigger_button 
+		 << " => " << event->trigger.button << endl
+		 << "    Interval : " << effect->trigger_interval 
+		 << " => " << event->trigger.interval << endl;
+#endif
+
+	event->replay.length = LinuxDuration(effect->replay_length);
+	event->replay.delay = LinuxDuration(effect->replay_delay);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  Replay :" << endl
+		 << "    Length : " << effect->replay_length 
+		 << " => " << event->replay.length << endl
+		 << "    Delay  : " << effect->replay_delay 
+		 << " => " << event->replay.delay << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updateConstantEffect( const Effect* eff )
+{
+	struct ff_effect event;
+
+	ConstantEffect *effect = static_cast<ConstantEffect*>(eff->getForceEffect());
+
+	_setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
+
+	event.type = FF_CONSTANT;
+	event.id = -1;
+
+	event.u.constant.level = LinuxSignedLevel(effect->level);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  Level : " << effect->level
+		 << " => " << event.u.constant.level << endl;
+#endif
+
+	_upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updateRampEffect( const Effect* eff )
+{
+	struct ff_effect event;
+
+	RampEffect *effect = static_cast<RampEffect*>(eff->getForceEffect());
+
+	_setCommonProperties(&event, &event.u.constant.envelope, eff, &effect->envelope);
+
+	event.type = FF_RAMP;
+	event.id = -1;
+
+	event.u.ramp.start_level = LinuxSignedLevel(effect->startLevel);
+	event.u.ramp.end_level = LinuxSignedLevel(effect->endLevel);
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  StartLevel : " << effect->startLevel
+		 << " => " << event.u.ramp.start_level << endl
+		 << "  EndLevel   : " << effect->endLevel
+		 << " => " << event.u.ramp.end_level << endl;
+#endif
+
+	_upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updatePeriodicEffect( const Effect* eff )
+{
+	struct ff_effect event;
+
+	PeriodicEffect *effect = static_cast<PeriodicEffect*>(eff->getForceEffect());
+
+	_setCommonProperties(&event, &event.u.periodic.envelope, eff, &effect->envelope);
+
+	event.type = FF_PERIODIC;
+	event.id = -1;
+
+	switch( eff->type )
+	{
+		case OIS::Effect::Square:
+			event.u.periodic.waveform = FF_SQUARE;
+			break;
+		case OIS::Effect::Triangle:
+			event.u.periodic.waveform = FF_TRIANGLE;
+			break;
+		case OIS::Effect::Sine:
+			event.u.periodic.waveform = FF_SINE;
+			break;
+		case OIS::Effect::SawToothUp:
+			event.u.periodic.waveform = FF_SAW_UP;
+			break;
+		case OIS::Effect::SawToothDown:
+			event.u.periodic.waveform = FF_SAW_DOWN;
+			break;
+		// Note: No support for Custom periodic force effect for the moment
+		//case OIS::Effect::Custom:
+			//event.u.periodic.waveform = FF_CUSTOM;
+			//break;
+		default:
+			OIS_EXCEPT(E_General, "No such available effect for Periodic force!"); 
+			break;
+	}
+
+	event.u.periodic.period    = LinuxDuration(effect->period);
+	event.u.periodic.magnitude = LinuxPositiveLevel(effect->magnitude);
+	event.u.periodic.offset    = LinuxPositiveLevel(effect->offset);
+	event.u.periodic.phase     = (__u16)(effect->phase*event.u.periodic.period/36000.0); // ?????
+
+	// Note: No support for Custom periodic force effect for the moment
+	event.u.periodic.custom_len = 0;
+	event.u.periodic.custom_data = 0;
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  Magnitude : " << effect->magnitude
+		 << " => " << event.u.periodic.magnitude << endl
+		 << "  Period    : " << effect->period
+		 << " => " << event.u.periodic.period  << endl
+		 << "  Offset    : " << effect->offset
+		 << " => " << event.u.periodic.offset << endl
+		 << "  Phase     : " << effect->phase
+		 << " => " << event.u.periodic.phase << endl;
+#endif
+
+	_upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_updateConditionalEffect( const Effect* eff )
+{
+	struct ff_effect event;
+
+	ConditionalEffect *effect = static_cast<ConditionalEffect*>(eff->getForceEffect());
+
+	_setCommonProperties(&event, NULL, eff, NULL);
+
+	switch( eff->type )
+	{
+		case OIS::Effect::Friction:
+			event.type = FF_FRICTION; 
+			break;
+		case OIS::Effect::Damper:
+			event.type = FF_DAMPER; 
+			break;
+		case OIS::Effect::Inertia:
+			event.type = FF_INERTIA; 
+			break;
+		case OIS::Effect::Spring:
+			event.type = FF_SPRING;
+			break;
+		default:
+			OIS_EXCEPT(E_General, "No such available effect for Conditional force!"); 
+			break;
+	}
+
+	event.id = -1;
+
+	event.u.condition[0].right_saturation = LinuxSignedLevel(effect->rightSaturation);
+	event.u.condition[0].left_saturation  = LinuxSignedLevel(effect->leftSaturation);
+	event.u.condition[0].right_coeff      = LinuxSignedLevel(effect->rightCoeff);
+	event.u.condition[0].left_coeff       = LinuxSignedLevel(effect->leftCoeff);
+	event.u.condition[0].deadband         = LinuxPositiveLevel(effect->deadband);// Unit ?? 
+	event.u.condition[0].center           = LinuxSignedLevel(effect->center); // Unit ?? TODO ?
+
+	// TODO support for second condition
+	event.u.condition[1] = event.u.condition[0];
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "  Condition[0] : " << endl
+		 << "    RightSaturation  : " << effect->rightSaturation
+		 << " => " << event.u.condition[0].right_saturation << endl
+		 << "    LeftSaturation   : " << effect->leftSaturation
+		 << " => " << event.u.condition[0]. left_saturation << endl
+		 << "    RightCoefficient : " << effect->rightCoeff
+		 << " => " << event.u.condition[0].right_coeff << endl
+		 << "    LeftCoefficient : " << effect->leftCoeff
+		 << " => " << event.u.condition[0].left_coeff << endl
+		 << "    DeadBand        : " << effect->deadband
+		 << " => " << event.u.condition[0].deadband  << endl
+		 << "    Center          : " << effect->center
+		 << " => " << event.u.condition[0].center << endl;
+	cout << "  Condition[1] : Not implemented" << endl;
+#endif
+	_upload(&event, eff);
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_upload( struct ff_effect* ffeffect, const Effect* effect)
+{
+	struct ff_effect *linEffect = 0;
+
+	//Get the effect - if it exists
+	EffectList::iterator i = mEffectList.find(effect->_handle);
+	//It has been created already
+	if( i != mEffectList.end() )
+		linEffect = i->second;
+
+	if( linEffect == 0 )
+	{
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+		cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Adding new effect : " 
+			 << Effect::getEffectTypeName(effect->type) << endl;
+#endif
+
+		//This effect has not yet been created, so create it in the device
+		if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
+			// TODO device full check
+			// OIS_EXCEPT(E_DeviceFull, "Remove an effect before adding more!");
+			OIS_EXCEPT(E_General, "Unknown error creating effect (may be the device is full)->..");
+		}
+
+		// Save returned effect handle
+		effect->_handle = ffeffect->id;
+
+		// Save a copy of the uploaded effect for later simple modifications
+		linEffect = (struct ff_effect *)calloc(1, sizeof(struct ff_effect));
+		memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
+
+		mEffectList[effect->_handle] = linEffect;
+
+		// Start playing the effect.
+		_start(effect->_handle);
+	}
+	else
+	{
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+		cout << endl << "LinuxForceFeedback("<< mJoyStick << ") : Replacing effect : " 
+			 << Effect::getEffectTypeName(effect->type) << endl;
+#endif
+
+		// Keep same id/handle, as this is just an update in the device.
+		ffeffect->id = effect->_handle;
+
+		// Update effect in the device.
+		if (ioctl(mJoyStick, EVIOCSFF, ffeffect) == -1) {
+			OIS_EXCEPT(E_General, "Unknown error updating an effect->..");
+		}
+
+		// Update local linEffect for next time.
+		memcpy(linEffect, ffeffect, sizeof(struct ff_effect));
+	}
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << "LinuxForceFeedback("<< mJoyStick 
+		 << ") : Effect handle : " << effect->_handle << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_stop( int handle) {
+	struct input_event stop;
+
+	stop.type = EV_FF;
+	stop.code = handle;
+	stop.value = 0;
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << endl << "LinuxForceFeedback("<< mJoyStick 
+		 << ") : Stopping effect with handle " << handle << endl;
+#endif
+
+	if (write(mJoyStick, &stop, sizeof(stop)) != sizeof(stop)) {
+		OIS_EXCEPT(E_General, "Unknown error stopping effect->..");
+	}
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_start( int handle) {
+	struct input_event play;
+
+	play.type = EV_FF;
+	play.code = handle;
+	play.value = 1; // Play once.
+
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << endl << "LinuxForceFeedback("<< mJoyStick 
+		 << ") : Starting effect with handle " << handle << endl;
+#endif
+
+	if (write(mJoyStick, &play, sizeof(play)) != sizeof(play)) {
+		OIS_EXCEPT(E_General, "Unknown error playing effect->..");
+	}
+}
+
+//--------------------------------------------------------------//
+void LinuxForceFeedback::_unload( int handle)
+{
+#if (OIS_LINUX_JOYFF_DEBUG > 1)
+	cout << endl << "LinuxForceFeedback("<< mJoyStick 
+		 << ") : Removing effect with handle " << handle << endl;
+#endif
+
+	if (ioctl(mJoyStick, EVIOCRMFF, handle) == -1) {
+		OIS_EXCEPT(E_General, "Unknown error removing effect->..");
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxForceFeedback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxForceFeedback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxForceFeedback.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_LinuxForceFeedBack_H
+#define OIS_LinuxForceFeedBack_H
+
+#include "linux/LinuxPrereqs.h"
+#include "OISForceFeedback.h"
+#include <linux/input.h>
+
+namespace OIS
+{
+	class LinuxForceFeedback : public ForceFeedback
+	{
+	public:
+		LinuxForceFeedback(int deviceID);
+		~LinuxForceFeedback();
+
+		/** @copydoc ForceFeedback::setMasterGain */
+		void setMasterGain(float);
+		
+		/** @copydoc ForceFeedback::setAutoCenterMode */
+		void setAutoCenterMode(bool);
+
+		/** @copydoc ForceFeedback::upload */
+		void upload( const Effect* effect );
+
+		/** @copydoc ForceFeedback::modify */
+		void modify( const Effect* effect );
+
+		/** @copydoc ForceFeedback::remove */
+		void remove( const Effect* effect );
+
+		/** FF is not yet implemented fully on Linux.. just return -1 for now. todo, xxx */
+		short int getFFAxesNumber() { return -1; }
+
+		/** @copydoc ForceFeedback::getFFMemoryLoad */
+		unsigned short getFFMemoryLoad();
+
+	protected:
+
+		//Sets the common properties to all effects
+		void _setCommonProperties(struct ff_effect *event, struct ff_envelope *ffenvelope, 
+								  const Effect* effect, const Envelope *envelope );
+
+		//Specific Effect Settings
+		void _updateConstantEffect( const Effect* effect );
+		void _updateRampEffect( const Effect* effect );
+		void _updatePeriodicEffect( const Effect* effect );
+		void _updateConditionalEffect( const Effect* effect );
+		//void _updateCustomEffect( const Effect* effect );
+
+		void _upload( struct ff_effect* ffeffect, const Effect* effect);
+		void _stop( int handle);
+		void _start( int handle);
+		void _unload( int handle);
+
+		// Map of currently uploaded effects (handle => effect)
+		typedef std::map<int, struct ff_effect *> EffectList;
+		EffectList mEffectList;
+
+		// Joystick device (file) descriptor.
+		int mJoyStick;
+	};
+}
+#endif //OIS_LinuxForceFeedBack_H
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxInputManager.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxInputManager.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxInputManager.cpp	(revision 11817)
@@ -0,0 +1,212 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "linux/LinuxInputManager.h"
+#include "linux/LinuxKeyboard.h"
+#include "linux/LinuxJoyStickEvents.h"
+#include "linux/LinuxMouse.h"
+#include "OISException.h"
+#include <cstdlib>
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------//
+LinuxInputManager::LinuxInputManager() : InputManager("X11InputManager")
+{
+	window = 0;
+
+	//Default settings
+	grabMouse = true;
+	grabKeyboard = true;
+	hideMouse = true;
+	mGrabs = true;
+	keyboardUsed = mouseUsed = false;
+
+	//Setup our internal factories
+	mFactories.push_back(this);
+}
+
+//--------------------------------------------------------------------------------//
+LinuxInputManager::~LinuxInputManager()
+{
+	//Close all joysticks
+	LinuxJoyStick::_clearJoys(unusedJoyStickList);
+}
+
+//--------------------------------------------------------------------------------//
+void LinuxInputManager::_initialize( ParamList &paramList )
+{
+	_parseConfigSettings( paramList );
+
+	//Enumerate all devices attached
+	_enumerateDevices();
+}
+
+//--------------------------------------------------------------------------------//
+void LinuxInputManager::_parseConfigSettings( ParamList &paramList )
+{
+	ParamList::iterator i = paramList.find("WINDOW");
+	if( i == paramList.end() ) 
+		OIS_EXCEPT( E_InvalidParam, "LinuxInputManager >> No WINDOW!" );
+
+	//TODO 64 bit proof this little conversion xxx wip
+	window  = strtoul(i->second.c_str(), 0, 10);
+
+	//--------- Keyboard Settings ------------//
+	i = paramList.find("x11_keyboard_grab");
+	if( i != paramList.end() )
+		if( i->second == "false" )
+			grabKeyboard = false;
+
+	//--------- Mouse Settings ------------//
+	i = paramList.find("x11_mouse_grab");
+	if( i != paramList.end() )
+		if( i->second == "false" )
+			grabMouse = false;
+
+	i = paramList.find("x11_mouse_hide");
+	if( i != paramList.end() )
+		if( i->second == "false" )
+			hideMouse = false;
+}
+
+//--------------------------------------------------------------------------------//
+void LinuxInputManager::_enumerateDevices()
+{
+	//Enumerate all attached devices
+	unusedJoyStickList = LinuxJoyStick::_scanJoys();
+	joySticks = unusedJoyStickList.size();
+}
+
+//----------------------------------------------------------------------------//
+DeviceList LinuxInputManager::freeDeviceList()
+{
+	DeviceList ret;
+
+	if( keyboardUsed == false )
+		ret.insert(std::make_pair(OISKeyboard, mInputSystemName));
+
+	if( mouseUsed == false )
+		ret.insert(std::make_pair(OISMouse, mInputSystemName));
+
+	for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i)
+		ret.insert(std::make_pair(OISJoyStick, i->vendor));
+
+	return ret;
+}
+
+//----------------------------------------------------------------------------//
+int LinuxInputManager::totalDevices(Type iType)
+{
+	switch(iType)
+	{
+	case OISKeyboard: return 1;
+	case OISMouse: return 1;
+	case OISJoyStick: return joySticks;
+	default: return 0;
+	}
+}
+
+//----------------------------------------------------------------------------//
+int LinuxInputManager::freeDevices(Type iType)
+{
+	switch(iType)
+	{
+	case OISKeyboard: return keyboardUsed ? 0 : 1;
+	case OISMouse: return mouseUsed ? 0 : 1;
+	case OISJoyStick: return (int)unusedJoyStickList.size();
+	default: return 0;
+	}
+}
+
+//----------------------------------------------------------------------------//
+bool LinuxInputManager::vendorExist(Type iType, const std::string & vendor)
+{
+	if( (iType == OISKeyboard || iType == OISMouse) && vendor == mInputSystemName )
+	{
+		return true;
+	}
+	else if( iType == OISJoyStick )
+	{
+		for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i)
+			if(i->vendor == vendor)
+				return true;
+	}
+
+	return false;
+}
+
+//----------------------------------------------------------------------------//
+Object* LinuxInputManager::createObject(InputManager *creator, Type iType, bool bufferMode, const std::string & vendor)
+{
+	Object *obj = 0;
+
+	switch(iType)
+	{
+	case OISKeyboard:
+	{
+		if( keyboardUsed == false )
+			obj = new LinuxKeyboard(this, bufferMode, grabKeyboard);
+		break;
+	}
+	case OISMouse:
+	{
+		if( mouseUsed == false )
+			obj = new LinuxMouse(this, bufferMode, grabMouse, hideMouse);
+		break;
+	}
+	case OISJoyStick:
+	{
+		for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i)
+		{
+			if(vendor == "" || i->vendor == vendor)
+			{
+				obj = new LinuxJoyStick(this, bufferMode, *i);
+				unusedJoyStickList.erase(i);
+				break;
+			}
+		}
+		break;
+	}
+	default:
+		break;
+	}
+
+	if( obj == 0 )
+		OIS_EXCEPT(E_InputDeviceNonExistant, "No devices match requested type.");
+
+	return obj;
+}
+
+//----------------------------------------------------------------------------//
+void LinuxInputManager::destroyObject( Object* obj )
+{
+	if( obj )
+	{
+		if( obj->type() == OISJoyStick )
+		{
+			unusedJoyStickList.push_back( ((LinuxJoyStick*)obj)->_getJoyInfo() );
+		}
+
+		delete obj;
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxInputManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxInputManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxInputManager.h	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_LinuxInputManager_H
+#define OIS_LinuxInputManager_H
+
+#include "linux/LinuxPrereqs.h"
+#include "OISFactoryCreator.h"
+#include "OISInputManager.h"
+#include <X11/Xlib.h>
+
+namespace OIS
+{
+	/**
+		Linux X11 InputManager specialization - Using lowlevel joys
+	*/
+	class LinuxInputManager : public InputManager, public FactoryCreator
+	{
+	public:
+		LinuxInputManager();
+		virtual ~LinuxInputManager();
+
+		//InputManager Overrides
+		/** @copydoc InputManager::_initialize */
+		void _initialize( ParamList &paramList );
+
+		//FactoryCreator Overrides
+		/** @copydoc FactoryCreator::deviceList */
+		DeviceList freeDeviceList();
+
+		/** @copydoc FactoryCreator::totalDevices */
+		int totalDevices(Type iType);
+
+		/** @copydoc FactoryCreator::freeDevices */
+		int freeDevices(Type iType);
+
+		/** @copydoc FactoryCreator::vendorExist */
+		bool vendorExist(Type iType, const std::string & vendor);
+
+		/** @copydoc FactoryCreator::createObject */
+		Object* createObject(InputManager *creator, Type iType, bool bufferMode, const std::string & vendor = "");
+
+		/** @copydoc FactoryCreator::destroyObject */
+		void destroyObject(Object* obj);
+
+		//Internal Items
+		//! Method for retrieving the XWindow Handle
+		Window _getWindow() {return window;}
+
+		//! Internal method for checking if regrabbing is needed
+		void _setGrabState(bool grab) {mGrabs = grab;}
+		bool _getGrabState() {return mGrabs;}
+
+		//! Internal method, used for flaggin keyboard as available/unavailable for creation
+		void _setKeyboardUsed(bool used) {keyboardUsed = used; }
+
+		//! Internal method, used for flaggin mouse as available/unavailable for creation
+		void _setMouseUsed(bool used) { mouseUsed = used; }
+		
+	protected:
+		//! internal class method for dealing with param list
+		void _parseConfigSettings( ParamList &paramList );
+		//! internal class method for finding attached devices
+		void _enumerateDevices();
+
+		//! List of unused joysticks ready to be used
+		JoyStickInfoList unusedJoyStickList;
+		//! Number of joysticks found
+		char joySticks;
+
+		//! Used to know if we used up keyboard
+		bool keyboardUsed;
+
+		//! Used to know if we used up mouse
+		bool mouseUsed;
+
+		//! X11 Stuff
+		Window window;
+		
+		/// Keyboard, Mouse Settings
+		bool grabMouse, grabKeyboard;
+		bool mGrabs;
+		bool hideMouse;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxJoyStickEvents.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxJoyStickEvents.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxJoyStickEvents.cpp	(revision 11817)
@@ -0,0 +1,305 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "OISConfig.h"
+
+#include "linux/LinuxJoyStickEvents.h"
+#include "linux/LinuxInputManager.h"
+#include "linux/LinuxForceFeedback.h"
+#include "linux/EventHelpers.h"
+
+#include "OISEvents.h"
+#include "OISException.h"
+
+#include <fcntl.h>        //Needed to Open a file descriptor
+#include <cassert>	
+#include <linux/input.h>
+#include <unistd.h>
+
+#include <sstream>
+# include <iostream>
+using namespace std;
+
+using namespace OIS;
+
+//#define OIS_LINUX_JOY_DEBUG
+
+//-------------------------------------------------------------------//
+LinuxJoyStick::LinuxJoyStick(InputManager* creator, bool buffered, const JoyStickInfo& js)
+	: JoyStick(js.vendor, buffered, js.devId, creator)
+{
+	mJoyStick = js.joyFileD;
+
+	mState.mAxes.clear();
+	mState.mAxes.resize(js.axes);
+	mState.mButtons.clear();
+	mState.mButtons.resize(js.buttons);
+
+	mPOVs = js.hats;
+
+	mButtonMap = js.button_map;
+	mAxisMap = js.axis_map;
+	mRanges = js.axis_range;
+
+	ff_effect = 0;
+}
+
+//-------------------------------------------------------------------//
+LinuxJoyStick::~LinuxJoyStick()
+{
+	EventUtils::removeForceFeedback( &ff_effect );
+}
+
+//-------------------------------------------------------------------//
+void LinuxJoyStick::_initialize()
+{
+	//Clear old joy state
+	mState.mAxes.resize(mAxisMap.size());
+	mState.clear();
+
+	//This will create and new us a force feedback structure if it exists
+	EventUtils::enumerateForceFeedback( mJoyStick, &ff_effect );
+
+	if( mJoyStick == -1 )
+		OIS_EXCEPT(E_InputDeviceNonExistant, "LinuxJoyStick::_initialize() >> JoyStick Not Found!");
+}
+
+//-------------------------------------------------------------------//
+void LinuxJoyStick::capture()
+{
+	static const short POV_MASK[8] = {0,0,1,1,2,2,3,3};
+
+	//Used to determine if an axis has been changed and needs an event
+	bool axisMoved[32] = {false, false, false, false, false, false, false, false, false, false, false, false, false,
+						  false, false, false, false, false, false, false, false, false, false, false, false, false,
+						  false, false, false, false, false, false};
+
+	//We are in non blocking mode - we just read once, and try to fill up buffer
+	input_event js[JOY_BUFFERSIZE];
+	while(true)
+	{
+		int ret = read(mJoyStick, &js, sizeof(struct input_event) * JOY_BUFFERSIZE);
+        if( ret < 0 )
+			break;
+
+		//Determine how many whole events re read up
+		ret /= sizeof(struct input_event);
+		for(int i = 0; i < ret; ++i)
+		{
+			switch(js[i].type)
+			{
+			case EV_KEY:  //Button
+			{
+				int button = mButtonMap[js[i].code];
+
+				#ifdef OIS_LINUX_JOY_DEBUG
+				  cout << "\nButton Code: " << js[i].code << ", OIS Value: " << button << endl;
+				#endif
+
+				//Check to see whether push or released event...
+				if(js[i].value)
+				{
+					mState.mButtons[button] = true;
+					if( mBuffered && mListener )
+						if(!mListener->buttonPressed(JoyStickEvent(this,mState), button)) return;
+				}
+				else
+				{
+					mState.mButtons[button] = false;
+					if( mBuffered && mListener )
+						if(!mListener->buttonReleased(JoyStickEvent(this,mState), button)) return;
+				}
+				break;
+			}
+
+			case EV_ABS:  //Absolute Axis
+			{
+				//A Stick (BrakeDefine is the highest possible Axis)
+				if( js[i].code <= ABS_BRAKE )
+				{
+					int axis = mAxisMap[js[i].code];
+					assert( axis < 32 && "Too many axes (Max supported is 32). Report this to OIS forums!" );
+
+					axisMoved[axis] = true;
+
+					//check for rescaling:
+					if( mRanges[axis].min == JoyStick::MIN_AXIS && mRanges[axis].max != JoyStick::MAX_AXIS )
+					{	//Scale is perfect
+						mState.mAxes[axis].abs = js[i].value;
+					}
+					else
+					{	//Rescale
+						float proportion = (float)(js[i].value-mRanges[axis].max)/(float)(mRanges[axis].min-mRanges[axis].max);
+						mState.mAxes[axis].abs = (int)(32767.0f - (65535.0f * proportion));
+					}
+				}
+				else if( js[i].code <= ABS_HAT3Y ) //A POV - Max four POVs allowed
+				{
+					//Normalise the POV to between 0-7
+					//Even is X Axis, Odd is Y Axis
+					unsigned char LinuxPovNumber = js[i].code - 16;
+					short OIS_POVIndex = POV_MASK[LinuxPovNumber];
+
+					//Handle X Axis first (Even) (left right)
+					if((LinuxPovNumber & 0x0001) == 0)
+					{
+						//Why do this? Because, we use a bit field, and when this axis is east,
+						//it can't possibly be west too. So clear out the two X axes, then refil
+						//it in with the new direction bit.
+						//Clear the East/West Bit Flags first
+						mState.mPOV[OIS_POVIndex].direction &= 0x11110011;
+						if( js[i].value == -1 )	//Left
+							mState.mPOV[OIS_POVIndex].direction |= Pov::West;
+						else if( js[i].value == 1 ) //Right
+							mState.mPOV[OIS_POVIndex].direction |= Pov::East;
+					}
+					//Handle Y Axis (Odd) (up down)
+					else
+					{
+						//Clear the North/South Bit Flags first
+						mState.mPOV[OIS_POVIndex].direction &= 0x11111100;
+						if( js[i].value == -1 )	//Up
+							mState.mPOV[OIS_POVIndex].direction |= Pov::North;
+						else if( js[i].value == 1 ) //Down
+							mState.mPOV[OIS_POVIndex].direction |= Pov::South;
+					}
+
+					if( mBuffered && mListener )
+						if( mListener->povMoved( JoyStickEvent(this,mState), OIS_POVIndex) == false )
+							return;
+				}
+				break;
+			}
+
+			
+			case EV_REL: //Relative Axes (Do any joystick actually have a relative axis?)
+	#ifdef OIS_LINUX_JOY_DEBUG
+				cout << "\nWarning: Relatives axes not supported yet" << endl;
+	#endif
+				break;
+			default: break;
+			}
+		}
+	}
+
+	//All axes and POVs are combined into one movement per pair per captured frame
+	if( mBuffered && mListener )
+	{
+		for( int i = 0; i < 32; ++i )
+			if( axisMoved[i] )
+				if( mListener->axisMoved( JoyStickEvent(this,mState), i) == false )
+					return;
+	}
+}
+
+//-------------------------------------------------------------------//
+void LinuxJoyStick::setBuffered(bool buffered)
+{
+	if( buffered != mBuffered )
+	{
+		mBuffered = buffered;
+		_initialize();
+	}
+}
+
+//-------------------------------------------------------------------//
+JoyStickInfo LinuxJoyStick::_getJoyInfo()
+{
+	JoyStickInfo js;
+
+	js.devId = mDevID;
+	js.joyFileD = mJoyStick;
+	js.vendor = mVendor;
+	js.axes = (int)mState.mAxes.size();
+	js.buttons = (int)mState.mButtons.size();
+	js.hats = mPOVs;
+	js.button_map = mButtonMap;
+	js.axis_map = mAxisMap;
+	js.axis_range = mRanges;
+
+	return js;
+}
+
+//-------------------------------------------------------------------//
+JoyStickInfoList LinuxJoyStick::_scanJoys()
+{
+	JoyStickInfoList joys;
+
+	//Search through all of the event devices.. and identify which ones are joysticks
+	//xxx move this to InputManager, as it can also scan all other events
+	for(int i = 0; i < 64; ++i )
+	{
+		stringstream s;
+		s << "/dev/input/event" << i;
+		int fd = open( s.str().c_str(), O_RDWR |O_NONBLOCK );
+		if(fd == -1)
+			continue;
+
+        #ifdef OIS_LINUX_JOY_DEBUG
+		  cout << "Opening " << s.str() << "..." << endl;
+        #endif
+		try
+		{
+			JoyStickInfo js;
+			if( EventUtils::isJoyStick(fd, js) )
+			{
+				joys.push_back(js);
+                #ifdef OIS_LINUX_JOY_DEBUG
+                  cout << "=> Joystick added to list." << endl;
+                #endif
+			}
+			else
+			{
+                #ifdef OIS_LINUX_JOY_DEBUG
+                  cout << "=> Not a joystick." << endl;
+                #endif
+				close(fd);
+			}
+		}
+		catch(...)
+		{
+            #ifdef OIS_LINUX_JOY_DEBUG
+              cout << "Exception caught!!" << endl;
+            #endif
+			close(fd);
+		}
+	}
+
+	return joys;
+}
+
+//-------------------------------------------------------------------//
+void LinuxJoyStick::_clearJoys(JoyStickInfoList &joys)
+{
+	for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
+		close(i->joyFileD);
+	joys.clear();
+}
+
+//-------------------------------------------------------------------//
+Interface* LinuxJoyStick::queryInterface(Interface::IType type)
+{
+	if( ff_effect && type == Interface::ForceFeedback )
+		return ff_effect;
+
+	return 0;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxJoyStickEvents.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxJoyStickEvents.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxJoyStickEvents.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _LINUX_JOYSTICK_H_EADER_
+#define _LINUX_JOYSTICK_H_EADER_
+
+#include "linux/LinuxPrereqs.h"
+#include "OISJoyStick.h"
+
+namespace OIS
+{
+	/**
+		Linux specialization of JoyStick class.. This version is favored over the other.. and has the
+		*possibility* of Force Feedback.. notice I say possibility, i make no gaurantees under linux,
+		as FF support is sketchy at best AFAIK.
+	*/
+	class LinuxJoyStick : public JoyStick
+	{
+	public:
+		LinuxJoyStick(InputManager* creator, bool buffered, const JoyStickInfo& js);
+		virtual ~LinuxJoyStick();
+
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+
+		/** @copydoc Object::capture */
+		virtual void capture();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType type);
+
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+
+		/**
+		@remarks
+			For internal use only... Returns a structure to the manager, to make the device
+			availiable for use again
+		*/
+		JoyStickInfo _getJoyInfo();
+
+		static JoyStickInfoList _scanJoys();
+		static void _clearJoys(JoyStickInfoList &joys);
+	protected:
+
+		int mJoyStick;
+		LinuxForceFeedback* ff_effect;
+		std::map <int, int> mButtonMap;
+		std::map <int, int> mAxisMap;
+		std::map <int, Range> mRanges;
+	};
+}
+#endif //_LINUX_JOYSTICK_H_EADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxKeyboard.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxKeyboard.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxKeyboard.cpp	(revision 11817)
@@ -0,0 +1,431 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "linux/LinuxInputManager.h"
+#include "linux/LinuxKeyboard.h"
+#include "OISException.h"
+#include "OISEvents.h"
+
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+#include <cstring>
+
+using namespace OIS;
+#include <iostream>
+//-------------------------------------------------------------------//
+LinuxKeyboard::LinuxKeyboard(InputManager* creator, bool buffered, bool grab)
+	: Keyboard(creator->inputSystemName(), buffered, 0, creator)
+{
+	setlocale(LC_CTYPE, ""); //Set the locale to (hopefully) the users LANG UTF-8 Env var
+
+	display = 0;
+	window = 0;
+
+	grabKeyboard = grab;
+	keyFocusLost = false;
+
+	//X Key Map to KeyCode
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_1, KC_1));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_2, KC_2));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_3, KC_3));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_4, KC_4));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_5, KC_5));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_6, KC_6));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_7, KC_7));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_8, KC_8));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_9, KC_9));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_0, KC_0));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_BackSpace, KC_BACK));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_minus, KC_MINUS));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_equal, KC_EQUALS));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_space, KC_SPACE));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_comma, KC_COMMA));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_period, KC_PERIOD));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_backslash, KC_BACKSLASH));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_slash, KC_SLASH));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketleft, KC_LBRACKET));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_bracketright, KC_RBRACKET));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Escape,KC_ESCAPE));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Caps_Lock, KC_CAPITAL));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Tab, KC_TAB));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Return, KC_RETURN));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_L, KC_LCONTROL));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Control_R, KC_RCONTROL));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_colon, KC_COLON));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_semicolon, KC_SEMICOLON));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_apostrophe, KC_APOSTROPHE));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_grave, KC_GRAVE));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_b, KC_B));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_a, KC_A));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_c, KC_C));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_d, KC_D));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_e, KC_E));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_f, KC_F));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_g, KC_G));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_h, KC_H));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_i, KC_I));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_j, KC_J));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_k, KC_K));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_l, KC_L));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_m, KC_M));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_n, KC_N));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_o, KC_O));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_p, KC_P));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_q, KC_Q));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_r, KC_R));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_s, KC_S));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_t, KC_T));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_u, KC_U));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_v, KC_V));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_w, KC_W));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_x, KC_X));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_y, KC_Y));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_z, KC_Z));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F1, KC_F1));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F2, KC_F2));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F3, KC_F3));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F4, KC_F4));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F5, KC_F5));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F6, KC_F6));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F7, KC_F7));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F8, KC_F8));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F9, KC_F9));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F10, KC_F10));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F11, KC_F11));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F12, KC_F12));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F13, KC_F13));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F14, KC_F14));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_F15, KC_F15));
+
+	//Keypad
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_0, KC_NUMPAD0));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_1, KC_NUMPAD1));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_2, KC_NUMPAD2));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_3, KC_NUMPAD3));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_4, KC_NUMPAD4));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_5, KC_NUMPAD5));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_6, KC_NUMPAD6));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_7, KC_NUMPAD7));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_8, KC_NUMPAD8));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_9, KC_NUMPAD9));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Add, KC_ADD));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Subtract, KC_SUBTRACT));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Decimal, KC_DECIMAL));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Equal, KC_NUMPADEQUALS));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Divide, KC_DIVIDE));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Multiply, KC_MULTIPLY));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Enter, KC_NUMPADENTER));
+
+	//Keypad with numlock off
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Home, KC_NUMPAD7));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Up, KC_NUMPAD8));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Up, KC_NUMPAD9));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Left, KC_NUMPAD4));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Begin, KC_NUMPAD5));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Right, KC_NUMPAD6));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_End, KC_NUMPAD1));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Down, KC_NUMPAD2));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Page_Down, KC_NUMPAD3));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Insert, KC_NUMPAD0));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_KP_Delete, KC_DECIMAL));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Up, KC_UP));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Down, KC_DOWN));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Left, KC_LEFT));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Right, KC_RIGHT));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Up, KC_PGUP));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Page_Down, KC_PGDOWN));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Home, KC_HOME));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_End, KC_END));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Num_Lock, KC_NUMLOCK));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Print, KC_SYSRQ));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Scroll_Lock, KC_SCROLL));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Pause, KC_PAUSE));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_R, KC_RSHIFT));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Shift_L, KC_LSHIFT));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_R, KC_RMENU));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Alt_L, KC_LMENU));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Insert, KC_INSERT));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Delete, KC_DELETE));
+
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_L, KC_LWIN));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Super_R, KC_RWIN));
+	keyConversion.insert(XtoOIS_KeyMap::value_type(XK_Menu, KC_APPS));
+
+	static_cast<LinuxInputManager*>(mCreator)->_setKeyboardUsed(true);
+}
+
+//-------------------------------------------------------------------//
+void LinuxKeyboard::_initialize()
+{
+	//Clear our keyboard state buffer
+	memset( &KeyBuffer, 0, 256 );
+	mModifiers = 0;
+
+	if( display ) XCloseDisplay(display);
+	display = 0;
+	window = static_cast<LinuxInputManager*>(mCreator)->_getWindow();
+
+	//Create our local X mListener connection
+	if( !(display = XOpenDisplay(0)) )
+		OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize >> Error opening X!");
+
+	//Set it to recieve Input events
+	if( XSelectInput(display, window, KeyPressMask | KeyReleaseMask) == BadWindow )
+		OIS_EXCEPT(E_General, "LinuxKeyboard::_initialize: X error!");
+
+	if( grabKeyboard )
+		XGrabKeyboard(display,window,True,GrabModeAsync,GrabModeAsync,CurrentTime);
+
+	keyFocusLost = false;
+}
+
+//-------------------------------------------------------------------//
+LinuxKeyboard::~LinuxKeyboard()
+{
+	if( display )
+	{
+		if( grabKeyboard )
+			XUngrabKeyboard(display, CurrentTime);
+
+		XCloseDisplay(display);
+	}
+
+	static_cast<LinuxInputManager*>(mCreator)->_setKeyboardUsed(true);
+}
+
+//-------------------------------------------------------------------//
+unsigned int UTF8ToUTF32(unsigned char* buf)
+{
+	unsigned char &FirstChar = buf[0];
+
+	if(FirstChar < 128)
+		return FirstChar;
+
+	unsigned int val = 0;
+	unsigned int len = 0;
+
+	if((FirstChar & 0xE0) == 0xC0) //2 Chars
+	{
+		len = 2;
+		val = FirstChar & 0x1F;
+	}
+	else if((FirstChar & 0xF0) == 0xE0) //3 Chars
+	{
+		len = 3;
+		val = FirstChar & 0x0F;
+	}
+	else if((FirstChar & 0xF8) == 0xF0) //4 Chars
+	{
+		len = 4;
+		val = FirstChar & 0x07;
+	}
+	else if((FirstChar & 0xFC) == 0xF8) //5 Chars
+	{
+		len = 5;
+		val = FirstChar & 0x03;
+	}
+	else // if((FirstChar & 0xFE) == 0xFC) //6 Chars
+	{
+		len = 6;
+		val = FirstChar & 0x01;
+	}
+
+	for(int i = 1; i < len; i++)
+		val = (val << 6) | (buf[i] & 0x3F);
+
+	return val;
+}
+
+//-------------------------------------------------------------------//
+bool LinuxKeyboard::isKeyDown( KeyCode key ) const
+{
+	return (KeyBuffer[key]);
+}
+
+//-------------------------------------------------------------------//
+void LinuxKeyboard::capture()
+{
+	KeySym key;
+	XEvent event;
+	LinuxInputManager* linMan = static_cast<LinuxInputManager*>(mCreator);
+
+	while( XPending(display) > 0 )
+	{
+		XNextEvent(display, &event);
+
+		if(KeyPress == event.type)
+		{
+			unsigned int character = 0;
+
+			if(mTextMode != Off)
+			{
+				unsigned char buffer[6] = {0,0,0,0,0,0};
+				XLookupString(&event.xkey, (char*)buffer, 6, &key, 0);
+
+				if( mTextMode == Unicode )
+					character = UTF8ToUTF32(buffer);
+				else if( mTextMode == Ascii)
+					character = buffer[0];
+			}
+
+			//Mask out the modifier states X11 sets and read again
+			event.xkey.state &= ~ShiftMask;
+			event.xkey.state &= ~LockMask;
+			XLookupString(&event.xkey, 0, 0,&key, 0);
+
+			_injectKeyDown(key, character);
+
+			//Just printing out some debugging info.. to verify all chars are mapped
+			//std::cout << "KEY PRESSED X=" << event.xkey.keycode;
+			//std::cout << "\n KeySym=" << key << std::endl;
+
+			//Check for Alt-Tab
+			if( event.xkey.state & Mod1Mask && key == XK_Tab )
+				linMan->_setGrabState(false);
+		}
+		else if(KeyRelease == event.type)
+		{
+			if(!_isKeyRepeat(event))
+			{
+				//Mask out the modifier states X sets.. or we will get improper values
+				event.xkey.state &= ~ShiftMask;
+				event.xkey.state &= ~LockMask;
+
+				XLookupString(&event.xkey,NULL,0,&key,NULL);
+				_injectKeyUp(key);
+			}
+		}
+	}
+
+	//If grabbing mode is on.. Handle focus lost/gained via Alt-Tab and mouse clicks
+	if( grabKeyboard )
+	{
+		if( linMan->_getGrabState() == false )
+		{
+			// are no longer grabbing
+			if( keyFocusLost == false )
+			{
+				//UnGrab KeyBoard
+				XUngrabKeyboard(display, CurrentTime);
+				keyFocusLost = true;
+			}
+		}
+		else
+		{
+			//We are grabbing - and regained focus
+			if( keyFocusLost == true )
+			{
+				//ReGrab KeyBoard
+				XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+				keyFocusLost = false;
+			}
+		}
+	}
+}
+
+//-------------------------------------------------------------------//
+void LinuxKeyboard::setBuffered(bool buffered)
+{
+	mBuffered = buffered;
+}
+
+//-------------------------------------------------------------------//
+bool LinuxKeyboard::_injectKeyDown( KeySym key, int text )
+{
+	KeyCode kc = keyConversion[key];
+	KeyBuffer[kc] = 1;
+
+	//Turn on modifier flags
+	if( kc == KC_LCONTROL || kc == KC_RCONTROL)
+		mModifiers |= Ctrl;
+	else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
+		mModifiers |= Shift;
+	else if( kc == KC_LMENU || kc == KC_RMENU )
+		mModifiers |= Alt;
+
+	if( mBuffered && mListener )
+		return mListener->keyPressed(KeyEvent(this,kc,text));
+
+	return true;
+}
+
+//-------------------------------------------------------------------//
+bool LinuxKeyboard::_injectKeyUp( KeySym key )
+{
+	KeyCode kc = keyConversion[key];
+	KeyBuffer[kc] = 0;
+
+	//Turn off modifier flags
+	if( kc == KC_LCONTROL || kc == KC_RCONTROL)
+		mModifiers &= ~Ctrl;
+	else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
+		mModifiers &= ~Shift;
+	else if( kc == KC_LMENU || kc == KC_RMENU )
+		mModifiers &= ~Alt;
+
+	if( mBuffered && mListener )
+		return mListener->keyReleased(KeyEvent(this, kc, 0));
+
+	return true;
+}
+
+//-------------------------------------------------------------------//
+const std::string& LinuxKeyboard::getAsString( KeyCode kc )
+{
+	mGetString = "Unknown";
+	char *temp = 0;
+
+	XtoOIS_KeyMap::iterator i = keyConversion.begin(),
+				e = keyConversion.end();
+
+	for( ; i != e; ++i )
+	{
+		if( i->second == kc )
+		{
+			temp = XKeysymToString(i->first);
+			if( temp )
+				mGetString = temp;
+			break;
+		}
+	}
+
+	return mGetString;
+}
+
+//-------------------------------------------------------------------//
+void LinuxKeyboard::copyKeyStates( char keys[256] ) const
+{
+	memcpy( keys, KeyBuffer, 256 );
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxKeyboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxKeyboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxKeyboard.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _LINUX_KEYBOARD_H_EADER_
+#define _LINUX_KEYBOARD_H_EADER_
+
+#include "linux/LinuxPrereqs.h"
+#include "OISKeyboard.h"
+#include <X11/Xlib.h>
+
+namespace OIS
+{
+	/** Linux implementation of Keyboard object - uses x11 */
+	class LinuxKeyboard : public Keyboard
+	{
+	public:
+		LinuxKeyboard(InputManager* creator, bool buffered, bool grab);
+		virtual ~LinuxKeyboard();
+
+		/** @copydoc Keyboard::isKeyDown */
+		virtual bool isKeyDown( KeyCode key ) const;
+
+		/** @copydoc Keyboard::getAsString */
+		virtual const std::string& getAsString( KeyCode kc );
+
+		/** @copydoc Keyboard::copyKeyStates */
+		virtual void copyKeyStates( char keys[256] ) const;
+
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+
+		/** @copydoc Object::capture */
+		virtual void capture();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType) {return 0;}
+
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+
+	protected:
+		inline bool _isKeyRepeat(XEvent &event)
+		{
+			//When a key is repeated, there will be two events: released, followed by another immediate pressed. So check to see if another pressed is present	
+			if(!XPending(display))
+				return false;
+
+			XEvent e;
+			XPeekEvent(display, &e);
+			if(e.type == KeyPress && e.xkey.keycode == event.xkey.keycode && (e.xkey.time - event.xkey.time) < 2)
+			{
+				XNextEvent(display, &e);
+				return true;
+			}
+
+			return false;
+		}
+
+		bool _injectKeyDown( KeySym key, int text );
+		bool _injectKeyUp( KeySym key );
+
+		//! 1:1 Conversion Map between X Key Events and OIS KeyCodes
+		typedef std::map<KeySym, KeyCode> XtoOIS_KeyMap;
+		XtoOIS_KeyMap keyConversion;
+
+		//! Depressed Key List
+		char KeyBuffer[256];
+
+		//! X11 Stuff
+		Window window;
+		Display *display;
+		bool grabKeyboard;
+		bool keyFocusLost;
+
+		std::string mGetString;
+	};
+}
+
+#endif //_LINUX_KEYBOARD_H_EADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxMouse.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxMouse.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxMouse.cpp	(revision 11817)
@@ -0,0 +1,272 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered friosom any source distribution.
+*/
+#include "linux/LinuxMouse.h"
+#include "linux/LinuxInputManager.h"
+#include "OISException.h"
+#include "OISEvents.h"
+
+using namespace OIS;
+
+//-------------------------------------------------------------------//
+LinuxMouse::LinuxMouse(InputManager* creator, bool buffered, bool grab, bool hide)
+	: Mouse(creator->inputSystemName(), buffered, 0, creator)
+{
+	display = 0;
+	window = 0;
+	cursor = 0;
+
+	grabMouse = grab;
+	hideMouse = hide;
+
+	static_cast<LinuxInputManager*>(mCreator)->_setMouseUsed(true);
+}
+
+//-------------------------------------------------------------------//
+void LinuxMouse::_initialize()
+{
+	//Clear old state
+	mState.clear();
+	mMoved  = false;
+	mWarped = false;
+
+	//6 is just some random value... hardly ever would anyone have a window smaller than 6
+	oldXMouseX = oldXMouseY = 6;
+	oldXMouseZ = 0;
+
+	if( display ) XCloseDisplay(display);
+	display = 0;
+	window = static_cast<LinuxInputManager*>(mCreator)->_getWindow();
+
+	//Create our local X mListener connection
+	if( !(display = XOpenDisplay(0)) )
+		OIS_EXCEPT(E_General, "LinuxMouse::_initialize >> Error opening X!");
+
+	//Set it to recieve Mouse Input events
+	if( XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask | PointerMotionMask) == BadWindow )
+		OIS_EXCEPT(E_General, "LinuxMouse::_initialize >> X error!");
+
+	//Warp mouse inside window
+	XWarpPointer(display,None,window,0,0,0,0, 6,6);
+
+	//Create a blank cursor:
+	Pixmap bm_no;
+	XColor black, dummy;
+	Colormap colormap;
+	static char no_data[] = { 0,0,0,0,0,0,0,0 };
+
+	colormap = DefaultColormap( display, DefaultScreen(display) );
+	XAllocNamedColor( display, colormap, "black", &black, &dummy );
+	bm_no = XCreateBitmapFromData( display, window, no_data, 8, 8 );
+	cursor = XCreatePixmapCursor( display, bm_no, bm_no, &black, &black, 0, 0 );
+
+	grab( grabMouse );
+	hide( hideMouse );
+
+	mouseFocusLost = false;
+}
+
+//-------------------------------------------------------------------//
+LinuxMouse::~LinuxMouse()
+{
+	if( display )
+	{
+		grab(false);
+		hide(false);
+		XFreeCursor(display, cursor);
+		XCloseDisplay(display);
+	}
+
+	static_cast<LinuxInputManager*>(mCreator)->_setMouseUsed(false);
+}
+
+//-------------------------------------------------------------------//
+void LinuxMouse::setBuffered(bool buffered)
+{
+	mBuffered = buffered;
+}
+
+//-------------------------------------------------------------------//
+void LinuxMouse::capture()
+{
+	//Clear out last frames values
+	mState.X.rel = 0;
+	mState.Y.rel = 0;
+	mState.Z.rel = 0;
+
+	_processXEvents();
+
+	mWarped = false;
+
+	if( mMoved == true )
+	{
+		if( mBuffered && mListener )
+			mListener->mouseMoved( MouseEvent( this, mState ) );
+
+		mMoved = false;
+	}
+
+	//Check for losing/gaining mouse grab focus (alt-tab, etc)
+	if( grabMouse )
+	{
+		if( static_cast<LinuxInputManager*>(mCreator)->_getGrabState() )
+		{
+			if( mouseFocusLost )	//We just regained mouse grab focus
+			{
+				grab( true );
+				hide( hideMouse );
+				mouseFocusLost = false;
+			}
+		}
+		else
+		{
+			if( mouseFocusLost == false )	//We just lost mouse grab focus
+			{
+				grab( false );
+				hide( false );
+				mouseFocusLost = true;
+			}
+		}
+	}
+}
+
+//-------------------------------------------------------------------//
+void LinuxMouse::_processXEvents()
+{
+	//X11 Button Events: 1=left 2=middle 3=right; Our Bit Postion: 1=Left 2=Right 3=Middle
+	char mask[4] = {0,1,4,2};
+	XEvent event;
+
+	//Poll x11 for events mouse events
+	while( XPending(display) > 0 ) 
+	{
+		XNextEvent(display, &event);
+
+		if( event.type == MotionNotify )
+		{	//Mouse moved
+			//Ignore out of bounds mouse if we just warped
+			if( mWarped )
+			{
+				if(event.xmotion.x < 5 || event.xmotion.x > mState.width - 5 ||
+				   event.xmotion.y < 5 || event.xmotion.y > mState.height - 5)
+					continue;
+			}
+
+			//Compute this frames Relative X & Y motion
+			int dx = event.xmotion.x - oldXMouseX;
+			int dy = event.xmotion.y - oldXMouseY;
+		
+			//Store old values for next time to compute relative motion
+			oldXMouseX = event.xmotion.x;
+			oldXMouseY = event.xmotion.y;
+
+			mState.X.abs += dx;
+			mState.Y.abs += dy;
+			mState.X.rel += dx;
+			mState.Y.rel += dy;
+
+			//Check to see if we are grabbing the mouse to the window (requires clipping and warping)
+			if( grabMouse )
+			{
+				if( mState.X.abs < 0 )
+					mState.X.abs = 0;
+				else if( mState.X.abs > mState.width )
+					mState.X.abs = mState.width;
+
+				if( mState.Y.abs < 0 )
+					mState.Y.abs = 0;
+				else if( mState.Y.abs > mState.height )
+					mState.Y.abs = mState.height;
+
+				if( mouseFocusLost == false )
+				{
+					//Keep mouse in window (fudge factor)
+					if(event.xmotion.x < 5 || event.xmotion.x > mState.width - 5 ||
+					   event.xmotion.y < 5 || event.xmotion.y > mState.height - 5 )
+					{
+						oldXMouseX = mState.width >> 1;  //center x
+						oldXMouseY = mState.height >> 1; //center y
+						XWarpPointer(display, None, window, 0, 0, 0, 0, oldXMouseX, oldXMouseY);
+						mWarped = true;
+					}
+				}
+			}
+			mMoved = true;
+		}
+		else if( event.type == ButtonPress )
+		{	//Button down
+			static_cast<LinuxInputManager*>(mCreator)->_setGrabState(true);
+
+			if( event.xbutton.button < 4 )
+			{
+				mState.buttons |= mask[event.xbutton.button];
+				if( mBuffered && mListener )
+					if( mListener->mousePressed( MouseEvent( this, mState ),
+						(MouseButtonID)(mask[event.xbutton.button] >> 1)) == false )
+						return;
+			}
+		}
+		else if( event.type == ButtonRelease )
+		{	//Button up
+			if( event.xbutton.button < 4 )
+			{
+				mState.buttons &= ~mask[event.xbutton.button];
+				if( mBuffered && mListener )
+					if( mListener->mouseReleased( MouseEvent( this, mState ),
+						(MouseButtonID)(mask[event.xbutton.button] >> 1)) == false )
+						return;
+			}
+			//The Z axis gets pushed/released pair message (this is up)
+			else if( event.xbutton.button == 4 )
+			{
+				mState.Z.rel += 120;
+				mState.Z.abs += 120;
+				mMoved = true;
+			}
+			//The Z axis gets pushed/released pair message (this is down)
+			else if( event.xbutton.button == 5 )
+			{
+				mState.Z.rel -= 120;
+				mState.Z.abs -= 120;
+				mMoved = true;
+			}
+		}
+	}
+}
+
+//-------------------------------------------------------------------//
+void LinuxMouse::grab(bool grab)
+{
+	if( grab )
+		XGrabPointer(display, window, True, 0, GrabModeAsync, GrabModeAsync, window, None, CurrentTime);
+	else
+		XUngrabPointer(display, CurrentTime);
+}
+
+//-------------------------------------------------------------------//
+void LinuxMouse::hide(bool hide)
+{
+	if( hide )
+		XDefineCursor(display, window, cursor);
+	else
+		XUndefineCursor(display, window);
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxMouse.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxMouse.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxMouse.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _LINUX_MOUSE_H_EADER_
+#define _LINUX_MOUSE_H_EADER_
+
+#include "linux/LinuxPrereqs.h"
+#include "OISMouse.h"
+#include <X11/Xlib.h>
+
+namespace OIS
+{
+	class LinuxMouse : public Mouse
+	{
+	public:
+		LinuxMouse(InputManager* creator, bool buffered, bool grab, bool hide);
+		virtual ~LinuxMouse();
+
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+
+		/**
+		@remarks
+			Note: Calling this will also update the keyboard (X11 updates in a single
+			event queue). Updates State and/or raises event for buffered mode..
+		*/
+		virtual void capture();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType) {return 0;}
+
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+
+		void grab(bool grab);
+		void hide(bool hide);
+
+	protected:
+		void _processXEvents();
+
+		bool mMoved, mWarped;
+
+		//Since X11 provides us with absolute values, we need to keep track of relative values
+		long oldXMouseX, oldXMouseY, oldXMouseZ;
+
+		Window window;		//The X Window
+		Display *display;	//The X display
+		Cursor cursor;		//A blank cursor
+
+		bool grabMouse;		//Are we grabbing the mouse to the window?
+		bool hideMouse;		//Are we hiding OS mouse?
+		bool mouseFocusLost;//Has the mouse just lost focus?
+	};
+}
+
+#endif //_LINUX_MOUSE_H_EADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/linux/LinuxPrereqs.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _LINUX_INPUTSYSTEM_PREREQS_H
+#define _LINUX_INPUTSYSTEM_PREREQS_H
+
+//Bring in any auto generated config files
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "OISPrereqs.h"
+
+//! Max number of elements to collect from buffered input
+#define JOY_BUFFERSIZE 64
+
+namespace OIS
+{
+	class LinuxInputManager;
+	class LinuxKeyboard;
+	class LinuxJoyStick;
+	class LinuxMouse;
+	
+	class LinuxForceFeedback;
+
+	class Range
+	{
+	public:
+		Range() {};
+		Range(int _min, int _max) : min(_min), max(_max) {};
+		int min, max;
+	};
+
+	class JoyStickInfo
+	{
+	public:
+		JoyStickInfo(): devId(-1),joyFileD(-1),version(0),axes(0),buttons(0),hats(0) {}
+		//! Device number (/dev/input/j#) or /dev/input/event#
+		int devId;
+		//! File descriptor
+		int joyFileD;
+		//! Driver version
+		int version;
+		//! Joy vendor
+		std::string vendor;
+		//! Number of axes
+		unsigned char axes;
+		//! Number of buttons
+		unsigned char buttons;
+		//! Number of hats
+		unsigned char hats;
+		//! Maps Linux button values to OIS buttons values
+		std::map<int, int> button_map;
+		//! Maps Linux axis values to OIS axis
+		std::map<int, int> axis_map;
+		//! Maps OIS axis values to it's range
+		std::map<int, Range> axis_range;
+	};
+
+	typedef std::vector< JoyStickInfo > JoyStickInfoList;
+}
+
+#endif //_LINUX_INPUTSYSTEM_PREREQS_H
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,16 @@
+ADD_SOURCE_FILES(OIS_FILES
+  MacHelpers.h
+  MacHIDManager.h
+  MacInputManager.h
+  MacJoyStick.h
+  MacKeyboard.h
+  MacMouse.h
+  MacPrereqs.h
+
+  MacHelpers.cpp
+  MacHIDManager.cpp
+  MacInputManager.cpp
+  MacJoyStick.cpp
+  MacKeyboard.cpp
+  MacMouse.cpp
+)
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacHIDManager.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacHIDManager.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacHIDManager.cpp	(revision 11817)
@@ -0,0 +1,434 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Phillip Castaneda
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+#include "mac/MacHIDManager.h"
+#include "mac/MacJoyStick.h"
+#include "OISException.h"
+#include "OISObject.h"
+
+#include <iostream>
+using namespace std;
+
+using namespace OIS;
+
+//------------------------------------------------------------------------------------------------------//
+//------------------------------------------------------------------------------------------------------//
+template<typename T>
+T getDictionaryItemAsRef(CFDictionaryRef dict, const char* keyName)
+{
+	return CFDictionaryGetValue(dict, OIS_CFString(keyName));
+}
+
+template<>
+CFArrayRef getDictionaryItemAsRef(CFDictionaryRef dict, const char* keyName)
+{
+	CFTypeRef temp = CFDictionaryGetValue(dict, OIS_CFString(keyName));
+	
+	if(temp && CFGetTypeID(temp) == CFArrayGetTypeID())
+		return (CFArrayRef)temp;
+	else
+		return 0;
+}
+
+template<>
+CFStringRef getDictionaryItemAsRef(CFDictionaryRef dict, const char* keyName)
+{
+	CFTypeRef temp = CFDictionaryGetValue(dict, OIS_CFString(keyName));
+	
+	if(temp && CFGetTypeID(temp) == CFStringGetTypeID())
+		return (CFStringRef)temp;
+	else
+		return 0;
+}
+
+template<>
+CFNumberRef getDictionaryItemAsRef(CFDictionaryRef dict, const char* keyName)
+{
+	CFTypeRef temp = CFDictionaryGetValue(dict, OIS_CFString(keyName));
+	
+	if(temp && CFGetTypeID(temp) == CFNumberGetTypeID())
+		return (CFNumberRef)temp;
+	else
+		return 0;
+}
+
+//------------------------------------------------------------------------------------------------------//
+//------------------------------------------------------------------------------------------------------//
+template<typename T>
+T getArrayItemAsRef(CFArrayRef array, CFIndex idx)
+{
+	return CFArrayGetValueAtIndex(array, idx);
+}
+
+template<>
+CFDictionaryRef getArrayItemAsRef(CFArrayRef array, CFIndex idx)
+{
+	CFTypeRef temp = CFArrayGetValueAtIndex(array, idx);
+	
+	if(temp && CFGetTypeID(temp) == CFDictionaryGetTypeID())
+		return (CFDictionaryRef)temp;
+	else
+		return 0;
+}
+
+//------------------------------------------------------------------------------------------------------//
+int getInt32(CFNumberRef ref)
+{
+	int r = 0;
+	if (r) 
+		CFNumberGetValue(ref, kCFNumberIntType, &r);
+	return r;
+}
+
+//--------------------------------------------------------------------------------//
+MacHIDManager::MacHIDManager()
+{
+}
+
+//--------------------------------------------------------------------------------//
+MacHIDManager::~MacHIDManager()
+{
+}
+
+//------------------------------------------------------------------------------------------------------//
+void MacHIDManager::initialize()
+{
+	//Make the search more specific by adding usage flags
+	int usage = kHIDUsage_GD_Joystick;
+	int page = kHIDPage_GenericDesktop;
+	
+	io_iterator_t iterator = lookUpDevices(usage, page);
+	
+	if(iterator)
+		iterateAndOpenDevices(iterator);
+	
+	//Doesn't support multiple usage flags, iterate twice
+	usage = kHIDUsage_GD_GamePad;
+	iterator = lookUpDevices(usage, page);
+	
+	if(iterator)
+		iterateAndOpenDevices(iterator);
+}
+
+//------------------------------------------------------------------------------------------------------//
+io_iterator_t MacHIDManager::lookUpDevices(int usage, int page)
+{
+	CFMutableDictionaryRef deviceLookupMap = IOServiceMatching(kIOHIDDeviceKey);
+	if(!deviceLookupMap)
+		OIS_EXCEPT(E_General, "Could not setup HID device search parameters");
+	
+	CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
+	CFNumberRef pageRef  = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page);
+	
+	CFDictionarySetValue(deviceLookupMap, CFSTR(kIOHIDPrimaryUsageKey), usageRef);
+	CFDictionarySetValue(deviceLookupMap, CFSTR(kIOHIDPrimaryUsagePageKey), pageRef);
+	
+	//IOServiceGetMatchingServices consumes the map so we do not have to release it ourself
+	io_iterator_t iterator = 0;
+	IOReturn result = IOServiceGetMatchingServices(kIOMasterPortDefault, deviceLookupMap, &iterator);
+	
+	CFRelease(usageRef);
+	CFRelease(pageRef);
+	
+	if(result == kIOReturnSuccess)
+	{
+		return iterator;
+	}
+	//TODO: Throw exception instead?
+	else
+	{
+		return 0;
+	}
+}
+
+//------------------------------------------------------------------------------------------------------//
+void MacHIDManager::iterateAndOpenDevices(io_iterator_t iterator)
+{
+	io_object_t hidDevice = 0;
+	while ((hidDevice = IOIteratorNext(iterator)) !=0)
+	{
+		//Get the current registry items property map
+		CFMutableDictionaryRef propertyMap = 0;
+		if (IORegistryEntryCreateCFProperties(hidDevice, &propertyMap, kCFAllocatorDefault, kNilOptions) == KERN_SUCCESS && propertyMap)
+		{
+			//Go through device to find all needed info
+			HidInfo* hid = enumerateDeviceProperties(propertyMap);
+			
+			if(hid)
+			{
+				//todo - we need to hold an open interface so we do not have to enumerate again later
+				//should be able to watch for device removals also
+				
+				// Testing opening / closing interface
+				IOCFPlugInInterface **pluginInterface = NULL;
+				SInt32 score = 0;
+				if (IOCreatePlugInInterfaceForService(hidDevice, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &pluginInterface, &score) == kIOReturnSuccess)
+				{
+					IOHIDDeviceInterface **interface;
+					
+					HRESULT pluginResult = (*pluginInterface)->QueryInterface(pluginInterface, CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), (void **)&(interface));
+					
+					if(pluginResult != S_OK)
+						OIS_EXCEPT(E_General, "Not able to create plugin interface");
+					
+					IODestroyPlugInInterface(pluginInterface);
+					
+					hid->interface = interface;
+					
+					//Check for duplicates - some devices have multiple usage
+					if(std::find(mDeviceList.begin(), mDeviceList.end(), hid) == mDeviceList.end())
+						mDeviceList.push_back(hid);
+				}
+			}
+		}
+	}
+	
+	IOObjectRelease(iterator);
+}
+
+//------------------------------------------------------------------------------------------------------//
+HidInfo* MacHIDManager::enumerateDeviceProperties(CFMutableDictionaryRef propertyMap)
+{
+	HidInfo* info = new HidInfo();
+	
+	info->type = OISJoyStick;
+	
+	CFStringRef str = getDictionaryItemAsRef<CFStringRef>(propertyMap, kIOHIDManufacturerKey);
+	if (str)
+		info->vendor = CFStringGetCStringPtr(str, CFStringGetSystemEncoding());
+	
+	str = getDictionaryItemAsRef<CFStringRef>(propertyMap, kIOHIDProductKey);
+	if (str)
+		info->productKey = CFStringGetCStringPtr(str, CFStringGetSystemEncoding());
+	
+	info->combinedKey = info->vendor + " " + info->productKey;
+	
+	//Go through all items in this device (i.e. buttons, hats, sticks, axes, etc)
+	CFArrayRef array = getDictionaryItemAsRef<CFArrayRef>(propertyMap, kIOHIDElementKey);
+	if (array)
+		for (int i = 0; i < CFArrayGetCount(array); i++)
+			parseDeviceProperties(getArrayItemAsRef<CFDictionaryRef>(array, i));
+	
+	return info;
+}
+
+//------------------------------------------------------------------------------------------------------//
+void MacHIDManager::parseDeviceProperties(CFDictionaryRef properties)
+{
+	if(!properties)
+		return;
+	
+	CFArrayRef array = getDictionaryItemAsRef<CFArrayRef>(properties, kIOHIDElementKey);
+	if (array)
+	{
+		for (int i = 0; i < CFArrayGetCount(array); i++)
+		{
+			CFDictionaryRef element = getArrayItemAsRef<CFDictionaryRef>(array, i);
+			if (element)
+			{
+				if(getInt32(getDictionaryItemAsRef<CFNumberRef>(element, kIOHIDElementTypeKey)) == kIOHIDElementTypeCollection) 
+				{	//Check if we need to recurse further intoi another collection
+					if(getInt32(getDictionaryItemAsRef<CFNumberRef>(element, kIOHIDElementUsagePageKey)) == kHIDPage_GenericDesktop)
+						parseDeviceProperties(element);
+				}
+				else
+				{
+					switch(getInt32(getDictionaryItemAsRef<CFNumberRef>(element, kIOHIDElementUsagePageKey)))
+					{
+						case kHIDPage_GenericDesktop:
+							switch(getInt32(getDictionaryItemAsRef<CFNumberRef>(element, kIOHIDElementUsageKey)))
+						{
+							case kHIDUsage_GD_Pointer:
+								cout << "\tkHIDUsage_GD_Pointer\n";
+								parseDevicePropertiesGroup(element);
+								break;
+							case kHIDUsage_GD_X:
+							case kHIDUsage_GD_Y:
+							case kHIDUsage_GD_Z:
+							case kHIDUsage_GD_Rx:
+							case kHIDUsage_GD_Ry:
+							case kHIDUsage_GD_Rz:
+								cout << "\tAxis\n";
+								break;
+							case kHIDUsage_GD_Slider:
+							case kHIDUsage_GD_Dial:
+							case kHIDUsage_GD_Wheel:
+								cout << "\tUnsupported kHIDUsage_GD_Wheel\n";
+								break;
+							case kHIDUsage_GD_Hatswitch:
+								cout << "\tUnsupported - kHIDUsage_GD_Hatswitch\n";
+								break;
+						}
+							break;
+						case kHIDPage_Button:
+							cout << "\tkHIDPage_Button\n";
+							break;
+					}
+				}
+			}
+		}
+	}
+}
+
+//------------------------------------------------------------------------------------------------------//
+void MacHIDManager::parseDevicePropertiesGroup(CFDictionaryRef properties)
+{
+	if(!properties)
+		return;
+	
+	CFArrayRef array = getDictionaryItemAsRef<CFArrayRef>(properties, kIOHIDElementKey);
+	if(array)
+	{
+		for (int i = 0; i < CFArrayGetCount(array); i++)
+		{
+			CFDictionaryRef element = getArrayItemAsRef<CFDictionaryRef>(array, i);
+			if (element)
+			{
+				switch(getInt32(getDictionaryItemAsRef<CFNumberRef>(element, kIOHIDElementUsagePageKey)))
+				{
+					case kHIDPage_GenericDesktop:
+						switch(getInt32(getDictionaryItemAsRef<CFNumberRef>(element, kIOHIDElementUsageKey)))
+					{
+						case kHIDUsage_GD_X:
+						case kHIDUsage_GD_Y:
+						case kHIDUsage_GD_Z:
+						case kHIDUsage_GD_Rx:
+						case kHIDUsage_GD_Ry:
+						case kHIDUsage_GD_Rz:
+							cout << "\t\tAxis\n";
+							break;
+						case kHIDUsage_GD_Slider:
+						case kHIDUsage_GD_Dial:
+						case kHIDUsage_GD_Wheel:
+							cout << "\tUnsupported - kHIDUsage_GD_Wheel\n";
+							break;
+						case kHIDUsage_GD_Hatswitch:
+							cout << "\tUnsupported - kHIDUsage_GD_Hatswitch\n";
+							break;
+					}
+						break;
+					case kHIDPage_Button:
+						break;
+				}
+			}
+		}
+	}
+}
+
+//--------------------------------------------------------------------------------//
+DeviceList MacHIDManager::freeDeviceList()
+{
+	DeviceList ret;
+	HidInfoList::iterator it = mDeviceList.begin(), end = mDeviceList.end();
+	for(; it != end; ++it)
+	{
+		if((*it)->inUse == false)
+			ret.insert(std::make_pair((*it)->type, (*it)->combinedKey));
+	}
+	
+	return ret;
+}
+
+//--------------------------------------------------------------------------------//
+int MacHIDManager::totalDevices(Type iType)
+{
+	int ret = 0;
+	HidInfoList::iterator it = mDeviceList.begin(), end = mDeviceList.end();
+	
+	for(; it != end; ++it)
+	{
+		if((*it)->type == iType)
+			ret++;
+	}
+	
+	return ret;
+}
+
+//--------------------------------------------------------------------------------//
+int MacHIDManager::freeDevices(Type iType)
+{
+	int ret = 0;
+	HidInfoList::iterator it = mDeviceList.begin(), end = mDeviceList.end();
+	
+	for(; it != end; ++it)
+	{
+		if((*it)->inUse == false && (*it)->type == iType)
+			ret++;
+	}
+	
+	return ret;
+}
+
+//--------------------------------------------------------------------------------//
+bool MacHIDManager::vendorExist(Type iType, const std::string & vendor)
+{
+	HidInfoList::iterator it = mDeviceList.begin(), end = mDeviceList.end();
+	
+	for(; it != end; ++it)
+	{
+		if((*it)->type == iType && (*it)->combinedKey == vendor)
+			return true;
+	}
+	
+	return false;
+}
+
+//--------------------------------------------------------------------------------//
+Object* MacHIDManager::createObject(InputManager* creator, Type iType, bool bufferMode, 
+									const std::string & vendor)
+{
+	Object *obj = 0;
+	
+	HidInfoList::iterator it = mDeviceList.begin(), end = mDeviceList.end();
+	for(; it != end; ++it)
+	{
+		if((*it)->inUse == false && (*it)->type == iType && (vendor == "" || (*it)->combinedKey == vendor))
+		{
+			switch(iType)
+			{
+				case OISJoyStick:
+                {
+					int totalDevs = totalDevices(iType);
+					int freeDevs = freeDevices(iType);
+					int devID = totalDevs - freeDevs;
+					
+					obj = new MacJoyStick((*it)->combinedKey, bufferMode, *it, creator, devID);
+					(*it)->inUse = true;
+					return obj;
+                }
+				case OISTablet:
+					//Create MacTablet
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	
+	return obj;
+}
+
+//--------------------------------------------------------------------------------//
+void MacHIDManager::destroyObject(Object* obj)
+{
+	delete obj;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacHIDManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacHIDManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacHIDManager.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2007 Phillip
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_MacHIDManager_Header
+#define OIS_MacHIDManager_Header
+
+#include "OISPrereqs.h"
+#include "mac/MacPrereqs.h"
+#include "OISFactoryCreator.h"
+
+#import <CoreFoundation/CFString.h>
+#import <IOKit/IOKitLib.h>
+#import <IOKit/IOCFPlugIn.h>
+#import <IOKit/hid/IOHIDLib.h>
+#import <IOKit/hid/IOHIDKeys.h>
+#import <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
+
+namespace OIS
+{
+	//Information needed to create Mac HID Devices
+	class HidInfo
+	{
+	public:
+		HidInfo() : type(OISUnknown), numButtons(0), numHats(0), numAxes(0), inUse(false), interface(0)
+		{
+		}
+
+		//Useful tracking information
+		Type type;
+		std::string vendor;
+		std::string productKey;
+		std::string combinedKey;
+
+		//Retain some count information for recreating devices without having to reparse
+		int numButtons;
+		int numHats;
+		int numAxes;
+		bool inUse;
+
+		//Used for opening a read/write/tracking interface to device
+		IOHIDDeviceInterface **interface;
+	};
+
+	typedef std::vector<HidInfo*> HidInfoList;
+		
+	class MacHIDManager : public FactoryCreator
+	{
+	public:
+		MacHIDManager();
+		~MacHIDManager();
+
+		void initialize();
+		
+		void iterateAndOpenDevices(io_iterator_t iterator);
+		io_iterator_t lookUpDevices(int usage, int page);
+
+		//FactoryCreator Overrides
+		/** @copydoc FactoryCreator::deviceList */
+		DeviceList freeDeviceList();
+
+		/** @copydoc FactoryCreator::totalDevices */
+		int totalDevices(Type iType);
+
+		/** @copydoc FactoryCreator::freeDevices */
+		int freeDevices(Type iType);
+
+		/** @copydoc FactoryCreator::vendorExist */
+		bool vendorExist(Type iType, const std::string & vendor);
+
+		/** @copydoc FactoryCreator::createObject */
+		Object* createObject(InputManager* creator, Type iType, bool bufferMode, const std::string & vendor = "");
+
+		/** @copydoc FactoryCreator::destroyObject */
+		void destroyObject(Object* obj);
+
+	private:
+		HidInfo* enumerateDeviceProperties(CFMutableDictionaryRef propertyMap);
+		void parseDeviceProperties(CFDictionaryRef properties);
+		void parseDevicePropertiesGroup(CFDictionaryRef properties);
+
+		HidInfoList mDeviceList;		
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacHelpers.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacHelpers.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacHelpers.cpp	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "mac/MacHelpers.h"
+#include "mac/MacKeyboard.h"
+#include "mac/MacMouse.h"
+#include "OISException.h"
+
+#include <Carbon/Carbon.h>
+
+using namespace OIS;
+    
+//-------------------------------------------------------------------//
+OSStatus KeyDownWrapper( EventHandlerCallRef nextHandler,
+                        EventRef               theEvent,
+                        void*                  callClass )
+{
+    // TODO find a better way. This cast isn't very safe
+    if (callClass != NULL) {
+        ((MacKeyboard*)callClass)->_keyDownCallback( theEvent );
+        
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );
+    }
+    else {
+        OIS_EXCEPT(E_General, "KeyDownWrapper >> Being called by something other than our event handler!");
+        return noErr;
+    }
+}
+
+
+//-------------------------------------------------------------------//
+OSStatus KeyUpWrapper( EventHandlerCallRef nextHandler,
+                       EventRef               theEvent,
+                       void*                  callClass )
+{
+    if (callClass != NULL) {
+        ((MacKeyboard*)callClass)->_keyUpCallback( theEvent );
+        
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );
+    }
+    else {
+        OIS_EXCEPT(E_General, "KeyUpWrapper >> Being called by something other than our event handler!");
+        return noErr;
+    }
+}
+
+
+//-------------------------------------------------------------------//
+OSStatus KeyModWrapper( EventHandlerCallRef nextHandler,
+                        EventRef               theEvent,
+                        void*                  callClass )
+{
+    if (callClass != NULL) {
+        ((MacKeyboard*)callClass)->_modChangeCallback( theEvent );
+        
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );
+        
+    }
+    else {
+        OIS_EXCEPT(E_General, "KeyModWrapper >> Being called by something other than our event handler!");
+        return noErr;
+    }
+}
+
+/*
+//-------------------------------------------------------------------//
+OSStatus MouseMoveWrapper( EventHandlerCallRef nextHandler,
+                           EventRef            theEvent,
+                           void*               callClass )
+{
+    if (callClass != NULL) {
+        ((MacMouse*)callClass)->_mouseMoveCallback( theEvent );
+        
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );
+        
+    }
+    else {
+        OIS_EXCEPT(E_General, "MouseMoveWrapper >> Being called by something other than our event handler!");
+        return noErr;
+    }
+}
+
+
+//-------------------------------------------------------------------//
+OSStatus MouseScrollWrapper( EventHandlerCallRef nextHandler,
+                             EventRef            theEvent,
+                             void*               callClass )
+{
+    if (callClass != NULL) {
+        ((MacMouse*)callClass)->_mouseScrollCallback( theEvent );
+        
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );
+        
+    }
+    else {
+        OIS_EXCEPT(E_General, "MouseScrollWrapper >> Being called by something other than our event handler!");
+        return noErr;
+    }
+}
+
+
+//-------------------------------------------------------------------//
+OSStatus MouseButtonWrapper( EventHandlerCallRef nextHandler,
+                             EventRef            theEvent,
+                             void*               callClass )
+{
+    if (callClass != NULL) {
+        ((MacMouse*)callClass)->_mouseButtonCallback( theEvent );
+        
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );
+        
+    }
+    else {
+        OIS_EXCEPT(E_General, "MouseButtonWrapper >> Being called by something other than our event handler!");
+        return noErr;
+    }
+}
+*/
+
+//-------------------------------------------------------------------//
+OSStatus MouseWrapper( EventHandlerCallRef nextHandler, EventRef theEvent, void* callClass )
+{
+    if (callClass != NULL)
+	{
+        ((MacMouse*)callClass)->_mouseCallback( theEvent );
+
+        // propagate the event down the chain
+        return CallNextEventHandler( nextHandler, theEvent );        
+    }
+    else
+        OIS_EXCEPT(E_General, "MouseWrapper >> Being called by something other than our event handler!");
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacHelpers.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacHelpers.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacHelpers.h	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_MacHelpers_H
+#define OIS_MacHelpers_H
+
+#include "mac/MacPrereqs.h"
+#include "OISEvents.h"
+#include "OISKeyboard.h"
+#include "OISMouse.h"
+
+#include <Carbon/Carbon.h>
+
+// This is a hack needed to get the event handler working. 
+// The carbon lib expects a "OSStatus (*)(EventHandlerCallRef, EventRef, void*)",
+// so I cannot give it a class member function (unless it is static which is pointless)
+// Instead, I just pass the class* through the last paramter that gets passed to the
+// callback every time an event occurs. Then I dereference it and call the member function.
+OSStatus KeyDownWrapper( EventHandlerCallRef nextHandler, EventRef theEvent, void* callClass );
+
+OSStatus KeyUpWrapper( EventHandlerCallRef nextHandler, EventRef theEvent, void* callClass );
+
+OSStatus KeyModWrapper( EventHandlerCallRef nextHandler, EventRef theEvent, void* callClass );
+
+OSStatus MouseWrapper( EventHandlerCallRef nextHandler, EventRef theEvent, void* callClass );
+
+
+// This is needed for keeping an event stack for keyboard and mouse
+namespace OIS
+{
+    
+    // used in the eventStack to store the type
+    enum Mac_EventType { MAC_KEYUP = 0,
+                         MAC_KEYDOWN = 1,
+                         MAC_KEYREPEAT,
+                         MAC_MOUSEDOWN,
+                         MAC_MOUSEUP,
+                         MAC_MOUSEMOVED,
+                         MAC_MOUSESCROLL};
+    typedef enum Mac_EventType MacEventType;
+    
+    
+    // only used by MacKeyboard
+    typedef class Mac_KeyStackEvent
+    {
+        friend class MacKeyboard;
+        
+        
+    private:
+        Mac_KeyStackEvent( KeyEvent event, MacEventType type ) : Event(event), Type(type) {}
+        
+        MacEventType Type;
+        KeyEvent Event;
+    } MacKeyStackEvent;
+ 
+    
+
+    // only used by MacMouse
+    typedef class Mac_MouseStackEvent
+    {
+        friend class MacMouse;
+        
+    private:
+        Mac_MouseStackEvent( MouseEvent event, MacEventType type,  MouseButtonID button) : Event(event), Type(type), Button(button) {}
+        
+        MacEventType Type;
+        MouseEvent Event;
+		MouseButtonID Button;
+        
+    } MacMouseStackEvent;
+        
+}
+
+
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacInputManager.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacInputManager.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacInputManager.cpp	(revision 11817)
@@ -0,0 +1,206 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "mac/MacInputManager.h"
+#include "mac/MacKeyboard.h"
+#include "mac/MacMouse.h"
+#include "mac/MacHIDManager.h"
+#include "OISException.h"
+
+#include <Carbon/Carbon.h>
+
+#include <iostream>
+using namespace std;
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------//
+MacInputManager::MacInputManager() : InputManager("Mac OSX Input Manager")
+{
+    mHideMouse = true;
+    mUseRepeat = false;
+    mEventTargetRef = NULL;
+	mWindow = NULL;
+
+	keyboardUsed = mouseUsed = false;
+
+	//Setup our internal factories
+	mFactories.push_back(this);
+
+	mHIDManager = new MacHIDManager();
+	mFactories.push_back(mHIDManager);
+}
+
+//--------------------------------------------------------------------------------//
+MacInputManager::~MacInputManager()
+{
+	delete mHIDManager;
+}
+
+//--------------------------------------------------------------------------------//
+void MacInputManager::_initialize( ParamList &paramList )
+{
+	_parseConfigSettings( paramList );
+    
+	//Enumerate all devices attached
+	_enumerateDevices();
+	
+	mHIDManager->initialize();
+}
+
+//--------------------------------------------------------------------------------//
+void MacInputManager::_parseConfigSettings( ParamList &paramList )
+{
+    // Some carbon apps are running in a window, however full screen apps
+	// do not have a window, so we need to account for that too.
+	ParamList::iterator i = paramList.find("WINDOW");
+	if(i != paramList.end())
+	{
+		mWindow = (WindowRef)strtoul(i->second.c_str(), 0, 10);
+		if(mWindow == 0)
+		{
+			mWindow = NULL;
+			mEventTargetRef = GetApplicationEventTarget();
+		}
+		else
+		{
+			//mEventTargetRef = GetWindowEventTarget(mWindow);
+			mEventTargetRef = GetApplicationEventTarget();
+		}
+    }
+	else
+	{
+		// else get the main active window.. user might not have access to it through some
+		// graphics libraries, if that fails then try at the application level.
+		mWindow = ActiveNonFloatingWindow();
+		if(mWindow == NULL)
+		{
+			mEventTargetRef = GetApplicationEventTarget();
+		}
+		else
+		{
+			//mEventTargetRef = GetWindowEventTarget(mWindow);
+			mEventTargetRef = GetApplicationEventTarget();
+		}
+	}
+	
+	if(mEventTargetRef == NULL)
+		OIS_EXCEPT( E_General, "MacInputManager::_parseConfigSettings >> Unable to find a window or event target" );
+    
+    // Keyboard
+    if(paramList.find("MacAutoRepeatOn") != paramList.end())
+	{
+        if(paramList.find("MacAutoRepeatOn")->second == "true")
+		{
+            mUseRepeat = true;
+        }
+    }
+}
+
+//--------------------------------------------------------------------------------//
+void MacInputManager::_enumerateDevices()
+{
+}
+
+//--------------------------------------------------------------------------------//
+DeviceList MacInputManager::freeDeviceList()
+{
+	DeviceList ret;
+
+	if( keyboardUsed == false )
+		ret.insert(std::make_pair(OISKeyboard, mInputSystemName));
+
+	if( mouseUsed == false )
+		ret.insert(std::make_pair(OISMouse, mInputSystemName));
+
+	return ret;
+}
+
+//--------------------------------------------------------------------------------//
+int MacInputManager::totalDevices(Type iType)
+{
+	switch(iType)
+	{
+	case OISKeyboard: return 1;
+	case OISMouse: return 1;
+	default: return 0;
+	}
+}
+
+//--------------------------------------------------------------------------------//
+int MacInputManager::freeDevices(Type iType)
+{
+	switch(iType)
+	{
+	case OISKeyboard: return keyboardUsed ? 0 : 1;
+	case OISMouse: return mouseUsed ? 0 : 1;
+	default: return 0;
+	}
+}
+
+//--------------------------------------------------------------------------------//
+bool MacInputManager::vendorExist(Type iType, const std::string & vendor)
+{
+	if( (iType == OISKeyboard || iType == OISMouse) && vendor == mInputSystemName )
+		return true;
+
+	return false;
+}
+
+//--------------------------------------------------------------------------------//
+Object* MacInputManager::createObject(InputManager* creator, Type iType, bool bufferMode, 
+									  const std::string & vendor)
+{
+	Object *obj = 0;
+
+	switch(iType)
+	{
+	case OISKeyboard: 
+	{
+		if( keyboardUsed == false )
+			obj = new MacKeyboard(this, bufferMode, mUseRepeat);
+		break;
+	}
+	case OISMouse:
+	{
+		if( mouseUsed == false )
+			obj = new MacMouse(this, bufferMode);
+		break;
+	}
+	default:
+	{
+		obj = mHIDManager->createObject(creator, iType, bufferMode, vendor);
+		break;
+	}
+	}
+
+	if( obj == 0 )
+		OIS_EXCEPT(E_InputDeviceNonExistant, "No devices match requested type.");
+
+	return obj;
+}
+
+//--------------------------------------------------------------------------------//
+void MacInputManager::destroyObject(Object* obj)
+{
+	delete obj;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacInputManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacInputManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacInputManager.h	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_MacInputManager_H
+#define OIS_MacInputManager_H
+
+#include "OISInputManager.h"
+#include "OISFactoryCreator.h"
+#include "mac/MacPrereqs.h"
+#include <Carbon/Carbon.h>
+
+namespace OIS
+{
+    
+    class MacInputManager : public InputManager, public FactoryCreator
+    {
+    public:
+        MacInputManager();
+        virtual ~MacInputManager();
+        
+		//InputManager Overrides
+		/** @copydoc InputManager::_initialize */
+		void _initialize( ParamList &paramList );
+
+		//FactoryCreator Overrides
+		/** @copydoc FactoryCreator::deviceList */
+		DeviceList freeDeviceList();
+
+		/** @copydoc FactoryCreator::totalDevices */
+		int totalDevices(Type iType);
+
+		/** @copydoc FactoryCreator::freeDevices */
+		int freeDevices(Type iType);
+
+		/** @copydoc FactoryCreator::vendorExist */
+		bool vendorExist(Type iType, const std::string & vendor);
+
+		/** @copydoc FactoryCreator::createObject */
+		Object* createObject(InputManager* creator, Type iType, bool bufferMode, const std::string & vendor = "");
+
+		/** @copydoc FactoryCreator::destroyObject */
+		void destroyObject(Object* obj);
+
+		//Internal Items
+		//! Internal method, used for flaggin keyboard as available/unavailable for creation
+		void _setKeyboardUsed(bool used) {keyboardUsed = used; }
+
+		//! Internal method, used for flaggin mouse as available/unavailable for creation
+		void _setMouseUsed(bool used) { mouseUsed = used; }
+        
+        //! methodfor getting the event target
+        EventTargetRef _getEventTarget() {return mEventTargetRef;}
+        
+        //! method for getting window
+        WindowRef _getWindow() {return mWindow;}
+        
+    protected:        
+        void _parseConfigSettings( ParamList& paramList );
+        
+        void _enumerateDevices();
+        
+        static const std::string iName;
+        
+        // Mac stuff
+		EventTargetRef mEventTargetRef;
+		WindowRef mWindow;
+        
+        // settings
+        bool mHideMouse;
+        bool mUseRepeat;
+
+		//! Used to know if we used up keyboard
+		bool keyboardUsed;
+
+		//! Used to know if we used up mouse
+		bool mouseUsed;
+		
+		//! HID Manager class handling devices other than keyboard/mouse
+		MacHIDManager *mHIDManager;
+    };
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacJoyStick.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacJoyStick.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacJoyStick.cpp	(revision 11817)
@@ -0,0 +1,325 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that
+ you wrote the original software. If you use this software in a product,
+ an acknowledgment in the product documentation would be appreciated but is
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#include "mac/MacJoyStick.h"
+#include "mac/MacHIDManager.h"
+#include "mac/MacInputManager.h"
+#include "OISEvents.h"
+#include "OISException.h"
+
+#include <cassert>
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------------------------//
+MacJoyStick::MacJoyStick(const std::string &vendor, bool buffered, HidInfo* info, InputManager* creator, int devID) : 
+JoyStick(vendor, buffered, devID, creator), mInfo(info)
+{
+	
+}
+
+//--------------------------------------------------------------------------------------------------//
+MacJoyStick::~MacJoyStick()
+{
+	//TODO: check if the queue has been started first?
+	//(*mQueue)->stop(mQueue); 
+	(*mQueue)->dispose(mQueue); 
+	(*mQueue)->Release(mQueue); 
+	
+	
+	//TODO: check if the interface has been opened first?
+	(*mInfo->interface)->close(mInfo->interface);
+	(*mInfo->interface)->Release(mInfo->interface); 
+}
+
+//--------------------------------------------------------------------------------------------------//
+void MacJoyStick::_initialize()
+{
+	assert(mInfo && "Given HidInfo invalid");
+	assert(mInfo->interface && "Joystick interface invalid");
+	
+	//TODO: Is this necessary?
+	//Clear old state
+	mState.mAxes.clear();
+	
+	if ((*mInfo->interface)->open(mInfo->interface, 0) != KERN_SUCCESS)
+		OIS_EXCEPT(E_General, "MacJoyStick::_initialize() >> Could not initialize joy device!");
+	
+	mState.clear();
+	
+	_enumerateCookies();
+	
+	mState.mButtons.resize(mInfo->numButtons);
+	mState.mAxes.resize(mInfo->numAxes);
+	
+	mQueue = _createQueue();
+}
+
+class FindAxisCookie : public std::unary_function<std::pair<IOHIDElementCookie, AxisInfo>&, bool>
+{
+public:
+	FindAxisCookie(IOHIDElementCookie cookie) : m_Cookie(cookie) {}
+	bool operator()(const std::pair<IOHIDElementCookie, AxisInfo>& pair) const
+	{
+		return pair.first == m_Cookie;
+	}
+private:
+	IOHIDElementCookie m_Cookie;
+};
+
+//--------------------------------------------------------------------------------------------------//
+void MacJoyStick::capture()
+{
+	assert(mQueue && "Queue must be initialized before calling MacJoyStick::capture()");
+	
+	AbsoluteTime zeroTime = {0,0}; 
+	
+	IOHIDEventStruct event; 
+	IOReturn result = (*mQueue)->getNextEvent(mQueue, &event, zeroTime, 0); 
+	while(result == kIOReturnSuccess)
+	{
+		switch(event.type)
+		{
+			case kIOHIDElementTypeInput_Button:
+			{
+				std::vector<IOHIDElementCookie>::iterator buttonIt = std::find(mCookies.buttonCookies.begin(), mCookies.buttonCookies.end(), event.elementCookie);
+				int button = std::distance(mCookies.buttonCookies.begin(), buttonIt);
+				mState.mButtons[button] = (event.value == 1);
+				
+				if(mBuffered && mListener)
+				{
+					if(event.value == 0)
+						mListener->buttonPressed(JoyStickEvent(this, mState), button);
+					else if(event.value == 1)
+						mListener->buttonReleased(JoyStickEvent(this, mState), button);
+				}
+				break;
+			}
+			case kIOHIDElementTypeInput_Misc:
+				//TODO: It's an axis! - kind of - for gamepads - or should this be a pov?
+			case kIOHIDElementTypeInput_Axis:
+				std::map<IOHIDElementCookie, AxisInfo>::iterator axisIt = std::find_if(mCookies.axisCookies.begin(), mCookies.axisCookies.end(), FindAxisCookie(event.elementCookie));
+				int axis = std::distance(mCookies.axisCookies.begin(), axisIt);
+				
+				//Copied from LinuxJoyStickEvents.cpp, line 149
+				const AxisInfo& axisInfo = axisIt->second;
+				float proportion = (float) (event.value - axisInfo.max) / (float) (axisInfo.min - axisInfo.max);
+				mState.mAxes[axis].abs = -JoyStick::MIN_AXIS - (JoyStick::MAX_AXIS * 2 * proportion);
+				
+				if(mBuffered && mListener) mListener->axisMoved(JoyStickEvent(this, mState), axis);
+				break;
+		}
+		
+		result = (*mQueue)->getNextEvent(mQueue, &event, zeroTime, 0);
+	}
+}
+
+//--------------------------------------------------------------------------------------------------//
+void MacJoyStick::setBuffered(bool buffered)
+{
+	mBuffered = buffered;
+}
+
+//--------------------------------------------------------------------------------------------------//
+Interface* MacJoyStick::queryInterface(Interface::IType type)
+{
+	//Thought about using covariant return type here.. however,
+	//some devices may allow LED light changing, or other interface stuff
+	
+	//f( ff_device && type == Interface::ForceFeedback )
+	//return ff_device;
+	//else
+	return 0;
+}
+
+//--------------------------------------------------------------------------------------------------//
+void MacJoyStick::_enumerateCookies()
+{
+	assert(mInfo && "Given HidInfo invalid");
+	assert(mInfo->interface && "Joystick interface invalid");
+	
+	CFTypeRef                               object; 
+	long                                    number; 
+	IOHIDElementCookie                      cookie; 
+	long                                    usage; 
+	long                                    usagePage;
+	int										min;
+	int										max;
+
+	CFDictionaryRef                         element; 
+	
+	// Copy all elements, since we're grabbing most of the elements 
+	// for this device anyway, and thus, it's faster to iterate them 
+	// ourselves. When grabbing only one or two elements, a matching 
+	// dictionary should be passed in here instead of NULL. 
+	CFArrayRef elements; 
+	IOReturn success = reinterpret_cast<IOHIDDeviceInterface122*>(*mInfo->interface)->copyMatchingElements(mInfo->interface, NULL, &elements); 
+	
+	if (success == kIOReturnSuccess)
+	{ 
+		const CFIndex numOfElements = CFArrayGetCount(elements);
+		for (CFIndex i = 0; i < numOfElements; ++i) 
+		{ 
+			element = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(elements, i));
+			
+			//Get cookie 
+			object = (CFDictionaryGetValue(element, 
+										   CFSTR(kIOHIDElementCookieKey))); 
+			if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) 
+				continue; 
+			if(!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, 
+								 &number)) 
+				continue; 
+			cookie = (IOHIDElementCookie) number; 
+			
+			//Get usage 
+			object = CFDictionaryGetValue(element, 
+										  CFSTR(kIOHIDElementUsageKey)); 
+			if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) 
+				continue; 
+			if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, 
+								  &number)) 
+				continue; 
+			usage = number; 
+			
+			//Get min
+			object = CFDictionaryGetValue(element,
+										  CFSTR(kIOHIDElementMinKey)); // kIOHIDElementMinKey or kIOHIDElementScaledMinKey?, no idea ...
+			if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID())
+				continue;
+			if (!CFNumberGetValue((CFNumberRef) object, kCFNumberIntType,
+								  &number))
+				continue;
+			min = number;
+			
+			//Get max
+			object = CFDictionaryGetValue(element,
+										  CFSTR(kIOHIDElementMaxKey)); // kIOHIDElementMaxKey or kIOHIDElementScaledMaxKey?, no idea ...
+			if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID())
+				continue;
+			if (!CFNumberGetValue((CFNumberRef) object, kCFNumberIntType,
+								  &number))
+				continue;
+			max = number;			
+			
+			//Get usage page 
+			object = CFDictionaryGetValue(element, 
+										  CFSTR(kIOHIDElementUsagePageKey)); 
+			
+			if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) 
+				continue; 
+			
+			if (!CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, 
+								  &number)) 
+				continue; 
+			
+			usagePage = number;
+			switch(usagePage)
+			{
+				case kHIDPage_GenericDesktop:
+					switch(usage)
+				{
+					case kHIDUsage_GD_Pointer:
+						break;
+					case kHIDUsage_GD_X:
+					case kHIDUsage_GD_Y:
+					case kHIDUsage_GD_Z:
+					case kHIDUsage_GD_Rx:
+					case kHIDUsage_GD_Ry:
+					case kHIDUsage_GD_Rz:
+						mCookies.axisCookies.insert(std::make_pair(cookie, AxisInfo(min, max)));
+						break;
+					case kHIDUsage_GD_Slider:
+					case kHIDUsage_GD_Dial:
+					case kHIDUsage_GD_Wheel:
+						break;
+					case kHIDUsage_GD_Hatswitch:
+						break;
+				}
+					break;
+				case kHIDPage_Button:
+					mCookies.buttonCookies.push_back(cookie);
+					break;
+			}		
+		}
+		
+		mInfo->numButtons = mCookies.buttonCookies.size();
+		mInfo->numAxes = mCookies.axisCookies.size();
+
+	} 
+	else 
+	{ 
+		OIS_EXCEPT(E_General, "JoyStick elements could not be copied: copyMatchingElements failed with error: " + success); 
+	}
+	
+}
+
+//--------------------------------------------------------------------------------------------------//
+IOHIDQueueInterface** MacJoyStick::_createQueue(unsigned int depth)
+{	
+	assert(mInfo && "Given HidInfo invalid");
+	assert(mInfo->interface && "Joystick interface invalid");
+	
+	IOHIDQueueInterface** queue = (*mInfo->interface)->allocQueue(mInfo->interface); 
+	
+	if (queue) 
+	{		
+		//create the queue 
+		IOReturn result = (*queue)->create(queue, 0, depth); 
+		
+		if(result == kIOReturnSuccess)
+		{		
+			//add elements to the queue
+			std::map<IOHIDElementCookie, AxisInfo>::iterator axisIt = mCookies.axisCookies.begin();
+			for(; axisIt != mCookies.axisCookies.end(); ++axisIt)
+			{
+				result = (*queue)->addElement(queue, axisIt->first, 0);
+			}
+			
+			std::vector<IOHIDElementCookie>::iterator buttonIt = mCookies.buttonCookies.begin();
+			for(; buttonIt != mCookies.buttonCookies.end(); ++buttonIt)
+			{
+				result = (*queue)->addElement(queue, (*buttonIt), 0);
+			}
+
+			//start data delivery to queue 
+			result = (*queue)->start(queue); 
+			if(result == kIOReturnSuccess)
+			{
+				return queue;
+			}
+			else
+			{
+				OIS_EXCEPT(E_General, "Queue could not be started.");
+			}
+		}
+		else
+		{
+			OIS_EXCEPT(E_General, "Queue could not be created.");
+		}
+	}
+	else
+	{
+		OIS_EXCEPT(E_General, "Queue allocation failed.");
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacJoyStick.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacJoyStick.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacJoyStick.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that
+ you wrote the original software. If you use this software in a product,
+ an acknowledgment in the product documentation would be appreciated but is
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+ */
+#ifndef MAC_Joystick_H
+#define MAC_Joystick_H
+#include "OISJoyStick.h"
+#include "mac/MacPrereqs.h"
+#include "mac/MacHIDManager.h"
+
+namespace OIS
+{
+	struct AxisInfo
+	{
+		int min;
+		int max;
+		
+		AxisInfo(int min, int max)
+			: min(min), max(max) {}
+	};
+	
+	typedef struct cookie_struct 
+	{ 
+		std::map<IOHIDElementCookie, AxisInfo> axisCookies; 			
+		std::vector<IOHIDElementCookie> buttonCookies; 
+	} cookie_struct_t; 
+	
+	//class HidDeviceInfo
+	
+	class MacJoyStick : public JoyStick
+	{
+	public:
+		MacJoyStick(const std::string& vendor, bool buffered, HidInfo* info, InputManager* creator, int devID);
+		
+		virtual ~MacJoyStick();
+		
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+		
+		/** @copydoc Object::capture */
+		virtual void capture();
+		
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType type);
+		
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+		
+		void _enumerateCookies();
+		
+		IOHIDQueueInterface** _createQueue(unsigned int depth = 8);
+	protected:
+		HidInfo* mInfo;
+		cookie_struct_t mCookies;
+		IOHIDQueueInterface** mQueue;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacKeyboard.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacKeyboard.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacKeyboard.cpp	(revision 11817)
@@ -0,0 +1,459 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "mac/MacKeyboard.h"
+#include "mac/MacInputManager.h"
+#include "mac/MacHelpers.h"
+#include "OISException.h"
+#include "OISEvents.h"
+
+#include <Carbon/Carbon.h>
+
+#include <list>
+#include <string>
+
+const EventTypeSpec DownSpec[] = {{kEventClassKeyboard, kEventRawKeyDown},	//non - repeats
+							{kEventClassKeyboard, kEventRawKeyRepeat}}; //repeats
+const EventTypeSpec UpSpec = {kEventClassKeyboard, kEventRawKeyUp},
+			  ModSpec = {kEventClassKeyboard, kEventRawKeyModifiersChanged};
+
+const EventTypeSpec AllSpecs[] = {{kEventClassKeyboard, kEventRawKeyDown},
+						  {kEventClassKeyboard, kEventRawKeyRepeat},
+						  {kEventClassKeyboard, kEventRawKeyUp},
+						  {kEventClassKeyboard, kEventRawKeyModifiersChanged}};
+
+using namespace OIS;
+
+//-------------------------------------------------------------------//
+MacKeyboard::MacKeyboard( InputManager* creator, bool buffered, bool repeat )
+	: Keyboard(creator->inputSystemName(), buffered, 0, creator)
+{
+	keyDownEventRef = NULL;
+	keyUpEventRef = NULL;
+	keyModEventRef = NULL;
+	
+	useRepeat = repeat;
+
+	// Get a so-called "Univeral procedure pointer" for our callback
+	keyDownUPP = NewEventHandlerUPP( KeyDownWrapper );
+	keyUpUPP   = NewEventHandlerUPP( KeyUpWrapper );
+	keyModUPP  = NewEventHandlerUPP( KeyModWrapper );
+	
+	// populate the conversion map
+	populateKeyConversion();
+
+	static_cast<MacInputManager*>(mCreator)->_setKeyboardUsed(true);
+}
+
+//-------------------------------------------------------------------//
+MacKeyboard::~MacKeyboard()
+{
+	// Remove our handlers so that this instance doesn't get called
+	// after it is deleted
+	if (keyDownEventRef != NULL)
+		RemoveEventHandler(keyDownEventRef);
+		
+	if (keyUpEventRef != NULL)
+		RemoveEventHandler(keyUpEventRef);
+	
+	if (keyModEventRef != NULL)
+		RemoveEventHandler(keyModEventRef);
+	
+	// dispose of our UPPs
+	DisposeEventHandlerUPP(keyDownUPP);
+	DisposeEventHandlerUPP(keyUpUPP);
+	DisposeEventHandlerUPP(keyModUPP);
+
+	//Free the input managers keyboard
+	static_cast<MacInputManager*>(mCreator)->_setKeyboardUsed(false);
+}
+
+//-------------------------------------------------------------------//
+void MacKeyboard::_initialize()
+{
+	EventTargetRef event = ((MacInputManager*)mCreator)->_getEventTarget();
+
+	memset( &KeyBuffer, 0, 256 );
+	mModifiers = 0;
+	prevModMask = 0;
+	
+	// just in case this gets called after the first time.. better safe
+	if (keyDownEventRef != NULL)
+		RemoveEventHandler(keyDownEventRef);
+		
+	if (keyUpEventRef != NULL)
+		RemoveEventHandler(keyUpEventRef);
+		
+	if (keyModEventRef != NULL)
+		RemoveEventHandler(keyModEventRef);
+   
+	keyDownEventRef = NULL;
+	keyUpEventRef = NULL;
+	keyModEventRef = NULL;
+
+	OSStatus status;
+	// send both elements of downspec array... second index is for repeat events
+	if ( useRepeat )
+		status = InstallEventHandler( event, keyDownUPP, 2, DownSpec, this, &keyDownEventRef );
+	else
+		status = InstallEventHandler( event, keyDownUPP, 1, DownSpec, this, &keyDownEventRef );
+		
+	if (status != noErr)
+		OIS_EXCEPT( E_General, "MacKeyboard::_initialize >> Error loading KeyDown event handler" );
+
+	if (InstallEventHandler( event, keyUpUPP, 1, &UpSpec, this, &keyUpEventRef ) != noErr)
+		OIS_EXCEPT( E_General, "MacKeyboard::_initialize >> Error loading KeyUp event handler" );
+
+	if (InstallEventHandler( event, keyModUPP, 1, &ModSpec, this, &keyModEventRef ) != noErr )
+		OIS_EXCEPT( E_General, "MacKeyboard::_initialize >> Error loading Keymods event handler" );
+}
+
+//-------------------------------------------------------------------//
+bool MacKeyboard::isKeyDown( KeyCode key ) const
+{
+	return (bool)KeyBuffer[key];
+}
+
+
+//-------------------------------------------------------------------//
+void MacKeyboard::capture()
+{
+	// if not buffered just return, we update the unbuffered automatically
+	if ( !mBuffered || !mListener )
+		return;
+	
+	//If the mListener returns false, that means that we are probably deleted...
+	//send no more events and just leave as the this pointer is invalid now...
+	bool ret = true;
+	
+	// run through our event stack
+	eventStack::iterator cur_it;
+	
+	for (cur_it = pendingEvents.begin(); cur_it != pendingEvents.end(); cur_it++)
+	{
+		
+		if ( (*cur_it).Type == MAC_KEYDOWN || (*cur_it).Type == MAC_KEYREPEAT)
+			mListener->keyPressed( (*cur_it).Event );
+		else if ( (*cur_it).Type == MAC_KEYUP )
+			mListener->keyReleased( (*cur_it).Event );
+	}
+	
+	pendingEvents.clear();
+}
+
+
+//-------------------------------------------------------------------//
+std::string& MacKeyboard::getAsString( KeyCode key )
+{
+	getString = "";
+	
+	return getString;
+}
+
+//-------------------------------------------------------------------//
+void MacKeyboard::setBuffered( bool buffered )
+{
+	mBuffered = buffered;
+}
+
+#include <iostream>
+//-------------------------------------------------------------------//
+void MacKeyboard::_keyDownCallback( EventRef theEvent )
+{
+	
+	UInt32 virtualKey;
+	OSStatus status;
+	
+	unsigned int time = (unsigned int)GetEventTime(theEvent);
+	
+	status = GetEventParameter(theEvent,
+					'kcod',			// get it in virtual keycode
+					typeUInt32, NULL,	// desired return type
+					sizeof(UInt32), NULL, 	// bufsize
+					&virtualKey );
+	
+	KeyCode kc = keyConversion[virtualKey];
+
+	// record what kind of text we should pass the KeyEvent
+	UniChar text[10];
+	char macChar;
+	
+	if (mTextMode == Unicode)
+	{
+		//get string size
+		UInt32 stringsize;
+		status = GetEventParameter( theEvent, 'kuni', typeUnicodeText, NULL, sizeof(UniChar) * 10, &stringsize, &text );
+		
+		if(stringsize > 0)
+		{
+			// for each unicode char, send an event
+			stringsize--; // no termination char
+			for ( int i = 0; i < stringsize; i++ )
+			{
+				injectEvent( kc, time, MAC_KEYDOWN, (unsigned int)text[i] );
+			}
+		}
+	} 
+	else if (mTextMode == Ascii)
+	{
+		 
+		status = GetEventParameter( theEvent, 'kchr', typeChar, NULL, sizeof(char), NULL, &macChar );
+		injectEvent( kc, time, MAC_KEYDOWN, (unsigned int)macChar );
+	}
+	else
+	{
+		injectEvent( kc, time, MAC_KEYDOWN );
+	}
+}
+
+//-------------------------------------------------------------------//
+void MacKeyboard::_keyUpCallback( EventRef theEvent )
+{
+	UInt32 virtualKey;
+	
+	OSStatus status;
+	status = GetEventParameter( theEvent, kEventParamKeyCode, typeUInt32,
+								NULL, sizeof(UInt32), NULL, &virtualKey );
+	
+	KeyCode kc = keyConversion[virtualKey];
+	injectEvent( kc, (int)GetEventTime(theEvent), MAC_KEYUP );
+	
+}
+
+//-------------------------------------------------------------------//
+void MacKeyboard::_modChangeCallback( EventRef theEvent )
+{
+	UInt32 mods;
+	
+	OSStatus status;
+	status = GetEventParameter( theEvent, kEventParamKeyModifiers,
+								typeUInt32, NULL, sizeof(UInt32), NULL, &mods );
+	
+	// find the changed bit
+	UInt32 change = prevModMask ^ mods;
+	MacEventType newstate = ((change & prevModMask) > 0) ? MAC_KEYUP : MAC_KEYDOWN;
+	unsigned int time = (int)GetEventTime( theEvent );
+	
+	//cout << "preMask: " << hex << prevModMask << endl;
+	//cout << "ModMask: " << hex << mods << endl;
+	//cout << "Change:  " << hex << (change & prevModMask) << endl << endl;
+	
+	// TODO test modifiers on a full keyboard to check if different mask for left/right
+	switch (change)
+	{
+		case (shiftKey): // shift
+			mModifiers &= (newstate == MAC_KEYDOWN) ? Shift : ~Shift;
+			injectEvent( KC_LSHIFT, time, newstate );
+			//injectEvent( KC_RSHIFT, time, newstate );
+			break;
+			
+		case (optionKey): // option (alt)
+			mModifiers &= (newstate == MAC_KEYDOWN) ? Alt : -Alt;
+			//injectEvent( KC_RMENU, time, newstate );
+			injectEvent( KC_LMENU, time, newstate );
+			break;
+			
+		case (controlKey): // Ctrl
+			mModifiers += (newstate == MAC_KEYDOWN) ? Ctrl : -Ctrl;
+			//injectEvent( KC_RCONTROL, time, newstate );
+			injectEvent( KC_LCONTROL, time, newstate );
+			break;
+	
+		case (cmdKey): // apple
+			//injectEvent( KC_RWIN, time, newstate );
+			injectEvent( KC_LWIN, time, newstate );
+			break;
+	
+		case (kEventKeyModifierFnMask): // fn key
+			injectEvent( KC_APPS, time, newstate );
+			break;
+			
+		case (kEventKeyModifierNumLockMask): // numlock
+			injectEvent( KC_NUMLOCK, time, newstate );
+			break;
+			
+		case (alphaLock): // caps lock
+			injectEvent( KC_CAPITAL, time, newstate );
+			break;
+	}
+	
+	prevModMask = mods;
+}
+
+//-------------------------------------------------------------------//
+void MacKeyboard::injectEvent( KeyCode kc, unsigned int time, MacEventType type, unsigned int txt )
+{
+	// set to 1 if this is either a keydown or repeat
+	KeyBuffer[kc] = ( type == MAC_KEYUP ) ? 0 : 1;
+	
+	if ( mBuffered && mListener )
+		pendingEvents.push_back( MacKeyStackEvent( KeyEvent(this, kc, txt), type) );
+}
+
+
+//-------------------------------------------------------------------//
+void MacKeyboard::copyKeyStates( char keys[256] ) const
+{
+	memcpy( keys, KeyBuffer, 256 );
+}
+
+
+
+//-------------------------------------------------------------------//
+void MacKeyboard::populateKeyConversion()
+{
+	// TODO finish the key mapping
+	
+	// Virtual Key Map to KeyCode
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x12, KC_1));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x13, KC_2));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x14, KC_3));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x15, KC_4));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x17, KC_5));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x16, KC_6));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1A, KC_7));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1C, KC_8));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x19, KC_9));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1D, KC_0));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x33, KC_BACK));  // might be wrong
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1B, KC_MINUS));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x18, KC_EQUALS));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x31, KC_SPACE));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2B, KC_COMMA));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2F, KC_PERIOD));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2A, KC_BACKSLASH));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2C, KC_SLASH));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x21, KC_LBRACKET));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1E, KC_RBRACKET));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x35, KC_ESCAPE));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x39, KC_CAPITAL));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x30, KC_TAB));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x24, KC_RETURN));  // double check return/enter
+	
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_colon, KC_COLON));	 // no colon?
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x29, KC_SEMICOLON));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x27, KC_APOSTROPHE));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x32, KC_GRAVE));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0B, KC_B));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x00, KC_A));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x08, KC_C));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x02, KC_D));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0E, KC_E));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x03, KC_F));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x05, KC_G));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x04, KC_H));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x22, KC_I));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x26, KC_J));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x28, KC_K));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x25, KC_L));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2E, KC_M));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x2D, KC_N));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x1F, KC_O));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x23, KC_P));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0C, KC_Q));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0F, KC_R));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x01, KC_S));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x11, KC_T));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x20, KC_U));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x09, KC_V));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x0D, KC_W));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x07, KC_X));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x10, KC_Y));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x06, KC_Z));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7A, KC_F1));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x78, KC_F2));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x63, KC_F3));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x76, KC_F4));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x60, KC_F5));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x61, KC_F6));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x62, KC_F7));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x64, KC_F8));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x65, KC_F9));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x6D, KC_F10));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x67, KC_F11));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x6F, KC_F12));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x69, KC_F13));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x6B, KC_F14));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x71, KC_F15));
+	
+	//Keypad
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x52, KC_NUMPAD0));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x53, KC_NUMPAD1));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x54, KC_NUMPAD2));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x55, KC_NUMPAD3));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x56, KC_NUMPAD4));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x57, KC_NUMPAD5));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x58, KC_NUMPAD6));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x59, KC_NUMPAD7));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x5B, KC_NUMPAD8));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x5C, KC_NUMPAD9));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x45, KC_ADD));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x4E, KC_SUBTRACT));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x41, KC_DECIMAL));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x51, KC_NUMPADEQUALS));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x4B, KC_DIVIDE));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x43, KC_MULTIPLY));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x4C, KC_NUMPADENTER));
+	
+	//Keypad with numlock off
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x73, KC_NUMPAD7));  // not sure of these
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Up, KC_NUMPAD8)); // check on a non-laptop
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Page_Up, KC_NUMPAD9));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Left, KC_NUMPAD4));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Begin, KC_NUMPAD5));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Right, KC_NUMPAD6));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_End, KC_NUMPAD1));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Down, KC_NUMPAD2));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Page_Down, KC_NUMPAD3));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Insert, KC_NUMPAD0));
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_KP_Delete, KC_DECIMAL));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7E, KC_UP));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7D, KC_DOWN));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7B, KC_LEFT));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x7C, KC_RIGHT));
+	
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x74, KC_PGUP));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x79, KC_PGDOWN));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x73, KC_HOME));
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x77, KC_END));
+	
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Print, KC_SYSRQ));		// ??
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Scroll_Lock, KC_SCROLL)); // ??
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Pause, KC_PAUSE));		// ??
+	
+	
+	//keyConversion.insert(VirtualtoOIS_KeyMap::value_type(XK_Insert, KC_INSERT));	  // ??
+	keyConversion.insert(VirtualtoOIS_KeyMap::value_type(0x75, KC_DELETE)); // del under help key?
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacKeyboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacKeyboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacKeyboard.h	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_MacKeyboard_H
+#define OIS_MacKeyboard_H
+
+#include "OISKeyboard.h"
+#include "mac/MacHelpers.h"
+#include "mac/MacPrereqs.h"
+
+#include <Carbon/Carbon.h>
+
+namespace OIS
+{
+    
+    class MacKeyboard : public Keyboard
+    {
+    public:
+        MacKeyboard( InputManager* creator, bool buffered, bool repeat );
+        virtual ~MacKeyboard();
+        
+        // Sets buffered mode
+        virtual void setBuffered( bool buffered );
+        
+        // unbuffered keydown check
+        virtual bool isKeyDown( KeyCode key ) const;
+        
+        // This will send listener events if buffered is on.
+        // Note that in the mac implementation, unbuffered input is
+        // automatically updated without calling this.
+        virtual void capture();
+        
+        // Copies the current key buffer
+        virtual void copyKeyStates( char keys[256] ) const;
+        
+        // Returns a description of the given key
+        virtual std::string& getAsString( KeyCode key );
+        
+        virtual Interface* queryInterface( Interface::IType type ) { return 0; }
+        
+        
+        // Public but reserved for internal use:
+        virtual void _initialize();
+        void _keyDownCallback( EventRef theEvent );
+        void _keyUpCallback( EventRef theEvent );
+        void _modChangeCallback( EventRef theEvent );
+        
+
+    protected:
+        // just to get this out of the way
+        void populateKeyConversion();
+        
+        // updates the keybuffer and optionally the eventStack
+        void injectEvent(KeyCode kc, unsigned int time, MacEventType type, unsigned int txt = 0 );
+                
+        typedef std::map<UInt32, KeyCode> VirtualtoOIS_KeyMap;
+        VirtualtoOIS_KeyMap keyConversion;
+        
+        std::string getString;
+        
+        char KeyBuffer[256];
+        UInt32 prevModMask;
+        
+        
+        // "universal procedure pointers" - required reference for callbacks
+        EventHandlerUPP keyDownUPP;
+        EventHandlerUPP keyUpUPP;
+        EventHandlerUPP keyModUPP;
+        
+        // so we can delete the handlers on destruction
+        EventHandlerRef keyDownEventRef;
+        EventHandlerRef keyUpEventRef;
+        EventHandlerRef keyModEventRef;
+        
+        // buffered events, fifo stack
+        typedef std::list<MacKeyStackEvent> eventStack;
+        eventStack pendingEvents;
+        
+        bool useRepeat;
+        
+    };
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacMouse.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacMouse.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacMouse.cpp	(revision 11817)
@@ -0,0 +1,346 @@
+#include "mac/MacMouse.h"
+#include "mac/MacInputManager.h"
+#include "mac/MacHelpers.h"
+#include "OISException.h"
+#include "OISEvents.h"
+
+#include <Carbon/Carbon.h>
+
+#include <list>
+
+#include <iostream>
+
+using namespace OIS;
+
+//Events we subscribe to and remove from queue
+const EventTypeSpec mouseEvents[] = {
+	{ kEventClassMouse, kEventMouseDown },
+	{ kEventClassMouse, kEventMouseUp },
+	{ kEventClassMouse, kEventMouseMoved },
+	{ kEventClassMouse, kEventMouseDragged },
+	{ kEventClassMouse, kEventMouseWheelMoved }		
+};
+
+const EventTypeSpec WinFocusAcquired [] = {{kEventClassApplication, kEventAppDeactivated}};
+
+//-------------------------------------------------------------------//
+MacMouse::MacMouse( InputManager* creator, bool buffered )
+	: Mouse(creator->inputSystemName(), buffered, 0, creator), mNeedsToRegainFocus( false )
+{
+    mouseEventRef = NULL;
+	mWindowFocusHandler = NULL;
+
+    // Get a "Univeral procedure pointer" for our callback
+    mouseUPP = NewEventHandlerUPP(MouseWrapper);
+	mWindowFocusListener = NewEventHandlerUPP(WindowFocusChanged);
+
+	static_cast<MacInputManager*>(mCreator)->_setMouseUsed(true);
+}
+
+MacMouse::~MacMouse()
+{
+    if(mouseEventRef != NULL)
+		RemoveEventHandler(mouseEventRef);
+
+	if(mWindowFocusHandler != NULL)
+		RemoveEventHandler(mWindowFocusHandler);
+	
+	DisposeEventHandlerUPP(mouseUPP);
+	DisposeEventHandlerUPP(mWindowFocusListener);
+	
+	// Restore Mouse
+	CGAssociateMouseAndMouseCursorPosition(TRUE);
+	CGDisplayShowCursor(kCGDirectMainDisplay);
+
+	static_cast<MacInputManager*>(mCreator)->_setMouseUsed(false);
+}
+
+void MacMouse::_initialize()
+{
+	mState.clear();
+	mTempState.clear();
+	mMouseWarped = false;
+	
+	// Hide OS Mouse
+ 	CGDisplayHideCursor(kCGDirectMainDisplay);
+
+	MacInputManager* im = static_cast<MacInputManager*>(mCreator);
+	WindowRef win = im->_getWindow();
+	
+	if(win)
+	{
+		Rect clipRect = {0.0f, 0.0f, 0.0f, 0.0f};
+		GetWindowBounds(win, kWindowContentRgn, &clipRect);
+		
+		CGPoint warpPoint;
+		warpPoint.x = ((clipRect.right - clipRect.left) / 2) + clipRect.left;
+		warpPoint.y = ((clipRect.bottom - clipRect.top) / 2) + clipRect.top;
+		CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); //Place at display origin
+		
+		mMouseWarped = true;
+	}
+
+	//Now that mouse is warped, start listening for events
+	EventTargetRef event = ((MacInputManager*)mCreator)->_getEventTarget();
+    
+	if(mouseEventRef != NULL)
+		RemoveEventHandler(mouseEventRef);
+		
+	if(mWindowFocusHandler != NULL)
+		RemoveEventHandler(mWindowFocusHandler);
+
+	mouseEventRef = mWindowFocusHandler = NULL;
+
+	if(InstallEventHandler(event, mouseUPP, GetEventTypeCount(mouseEvents), mouseEvents, this, &mouseEventRef) != noErr)
+		OIS_EXCEPT( E_General, "MacMouse::_initialize >> Error loading Mouse event handler" );
+
+	if(InstallEventHandler(event, mWindowFocusListener, GetEventTypeCount(WinFocusAcquired), WinFocusAcquired, this, &mWindowFocusHandler) != noErr)
+		OIS_EXCEPT( E_General, "MacMouse::_initialize >> Error loading Mouse event handler" );		
+
+	//Lock OS Mouse movement
+	mNeedsToRegainFocus = false;
+	CGAssociateMouseAndMouseCursorPosition(FALSE);
+}
+
+OSStatus MacMouse::WindowFocusChanged(EventHandlerCallRef nextHandler, EventRef event, void* macMouse)
+{
+	//std::cout << "Window Focus Changed\n";
+
+	MacMouse* _this = static_cast<MacMouse*>(macMouse);
+    if (_this)
+	{
+		_this->mNeedsToRegainFocus = true;
+		CGAssociateMouseAndMouseCursorPosition(TRUE);
+
+        // propagate the event down the chain
+        return CallNextEventHandler(nextHandler, event);
+    }
+    else
+        OIS_EXCEPT(E_General, "MouseWrapper >> Being called by something other than our event handler!");
+}
+
+void MacMouse::setBuffered( bool buffered )
+{
+	mBuffered = buffered;
+}
+
+void MacMouse::capture()
+{
+	mState.X.rel = 0;
+	mState.Y.rel = 0;
+	mState.Z.rel = 0;
+	    
+	if(mTempState.X.rel || mTempState.Y.rel || mTempState.Z.rel)
+	{
+		//printf("%i %i %i\n\n", mTempState.X.rel, mTempState.Y.rel, mTempState.Z.rel);
+
+		//Set new relative motion values
+		mState.X.rel = mTempState.X.rel;
+		mState.Y.rel = mTempState.Y.rel;
+		mState.Z.rel = mTempState.Z.rel;
+		
+		//Update absolute position
+		mState.X.abs += mTempState.X.rel;
+		mState.Y.abs += mTempState.Y.rel;
+		
+		if(mState.X.abs > mState.width)
+			mState.X.abs = mState.width;
+		else if(mState.X.abs < 0)
+			mState.X.abs = 0;
+
+		if(mState.Y.abs > mState.height)
+			mState.Y.abs = mState.height;
+		else if(mState.Y.abs < 0)
+			mState.Y.abs = 0;
+			
+		mState.Z.abs += mTempState.Z.rel;
+		
+		//Fire off event
+		if(mListener && mBuffered)
+			mListener->mouseMoved(MouseEvent(this, mState));
+	}
+
+	mTempState.clear();
+}
+
+void MacMouse::_mouseCallback( EventRef theEvent )
+{
+	OSStatus result = eventNotHandledErr;
+    UInt32 kind = GetEventKind (theEvent);
+
+	switch(kind)
+	{
+		case kEventMouseDragged:
+		case kEventMouseMoved:
+		{
+			//HIPoint location = {0.0f, 0.0f};
+			HIPoint delta = {0.0f, 0.0f};
+			//Rect clipRect = {0.0f, 0.0f, 0.0f, 0.0f};
+			
+			if(mNeedsToRegainFocus)
+				break;
+
+			// Capture the parameters
+			// TODO: Look into HIViewNewTrackingArea
+			//GetEventParameter(theEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &location);
+			GetEventParameter(theEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(HIPoint), NULL, &delta);
+			
+			// Mouse X and Y are the position on the screen, 
+			// startng from top-left at 0,0 caps at full monitor resolution
+			
+			// If we have a window we need to return adjusted coordinates
+			// If not, just use raw coordinates - only do this if showing OS mouse
+			//MacInputManager* im = static_cast<MacInputManager*>(mCreator);
+			//WindowRef win = im->_getWindow();
+			
+			//if(win != NULL)
+			//{
+			//	GetWindowBounds(win, kWindowContentRgn, &clipRect);
+			//}
+            //else
+            //{
+            //    clipRect.right = mState.width;
+            //    clipRect.bottom = mState.height;
+            //}
+                
+            // clip the mouse, absolute positioning
+            //if (location.x <= clipRect.left)
+			//	mState.X.abs = 0;
+			//else if(location.x >= clipRect.right)
+			//	mState.X.abs = clipRect.right - clipRect.left;
+			//else
+			//	mState.X.abs = location.x - clipRect.left;
+			
+			//if (location.y <= clipRect.top)
+			//	mState.Y.abs = 0;
+			//else if(location.y >= clipRect.bottom)
+			//	mState.Y.abs = clipRect.bottom - clipRect.top;
+			//else
+			//	mState.Y.abs = location.y - clipRect.top;
+			
+			// relative positioning
+			if(!mMouseWarped)
+			{
+				mTempState.X.rel += delta.x;
+				mTempState.Y.rel += delta.y;
+			}
+			
+			mMouseWarped = false;
+
+			break;
+		}
+		case kEventMouseDown:
+		{
+			EventMouseButton button = 0;
+			int mouseButton = 3;
+			UInt32 modifiers = 0;
+			
+			if(mNeedsToRegainFocus)
+				break;
+
+			// Capture parameters
+			GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &button);
+			GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
+			
+			if((button == kEventMouseButtonTertiary) || ((button == kEventMouseButtonPrimary) && (modifiers & optionKey)))
+			{
+				mouseButton = 2;
+				mState.buttons |= 1 << mouseButton;
+			}
+            else if((button == kEventMouseButtonSecondary) || ((button == kEventMouseButtonPrimary) && (modifiers & controlKey)))
+            {	
+                mouseButton = 1;
+                mState.buttons |= 1 << mouseButton;
+            }
+            else if(button == kEventMouseButtonPrimary)
+            {
+                mouseButton = 0;
+                mState.buttons |= 1 << mouseButton;
+            }
+
+            if( mListener && mBuffered )
+                mListener->mousePressed( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
+
+            break;
+		}
+		case kEventMouseUp:
+		{
+			EventMouseButton button = 0;
+			int mouseButton = 3;
+			UInt32 modifiers = 0;
+			
+			if(mNeedsToRegainFocus)
+			{
+				mNeedsToRegainFocus = false;
+				CGAssociateMouseAndMouseCursorPosition(false);
+				
+				MacInputManager* im = static_cast<MacInputManager*>(mCreator);
+				WindowRef win = im->_getWindow();
+				
+				if(win)
+				{
+					Rect clipRect = {0.0f, 0.0f, 0.0f, 0.0f};
+					GetWindowBounds(win, kWindowContentRgn, &clipRect);
+					
+					CGPoint warpPoint;
+					warpPoint.x = ((clipRect.right - clipRect.left) / 2) + clipRect.left;
+					warpPoint.y = ((clipRect.bottom - clipRect.top) / 2) + clipRect.top;
+					CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, warpPoint); //Place at display origin
+					
+					CGDisplayHideCursor(kCGDirectMainDisplay);
+					
+					mMouseWarped = true;
+				}
+				
+				//Once we regain focus, we do not really know what state all the buttons are in - for now, set to not pressed. todo, check current status
+				//compare against old status, and send off any needed events
+				mState.buttons = 0;
+				
+				break;
+			}
+			
+			// Capture parameters
+			GetEventParameter(theEvent, kEventParamMouseButton, typeMouseButton, NULL, sizeof(EventMouseButton), NULL, &button);
+			GetEventParameter(theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
+			
+			if ((button == kEventMouseButtonTertiary) || ((button == kEventMouseButtonPrimary) && (modifiers & optionKey)))
+			{
+				mouseButton = 2;
+				mState.buttons &= ~(1 << mouseButton);
+			}
+            else if ((button == kEventMouseButtonSecondary) || ((button == kEventMouseButtonPrimary) && (modifiers & controlKey)))
+            {	
+                mouseButton = 1;
+                mState.buttons &= ~(1 << mouseButton);
+            }
+            else if (button == kEventMouseButtonPrimary)
+            {
+                mouseButton = 0;
+                mState.buttons &= ~(1 << mouseButton);
+            }
+
+            if( mListener && mBuffered )
+                mListener->mouseReleased( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
+
+            break;
+		}
+		case kEventMouseWheelMoved:
+		{
+			SInt32 wheelDelta = 0;
+			EventMouseWheelAxis	wheelAxis = 0; 
+
+			// Capture parameters
+			GetEventParameter(theEvent, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(EventMouseWheelAxis), NULL, &wheelAxis);
+			GetEventParameter(theEvent, kEventParamMouseWheelDelta, typeSInt32, NULL, sizeof(SInt32), NULL, &wheelDelta);
+			
+			// If the Y axis of the wheel changed, then update the Z
+			// Does OIS care about the X wheel axis?
+			if(wheelAxis == kEventMouseWheelAxisY)
+				mTempState.Z.rel += (wheelDelta * 60);
+
+            break;
+		}
+		default:
+			break;
+	}    
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacMouse.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacMouse.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacMouse.h	(revision 11817)
@@ -0,0 +1,51 @@
+#ifndef OIS_MacMouse_H
+#define OIS_MacMouse_H
+
+#include "OISMouse.h"
+#include "mac/MacHelpers.h"
+#include "mac/MacPrereqs.h"
+
+#include <Carbon/Carbon.h>
+
+namespace OIS
+{
+	class MacMouse : public Mouse
+    {
+	public:
+		MacMouse( InputManager* creator, bool buffered );
+		virtual ~MacMouse();
+		
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+
+		/** @copydoc Object::capture */
+		virtual void capture();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType type) {return 0;}
+
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+        
+	public:
+        void _mouseCallback( EventRef theEvent );
+
+	protected:
+		static OSStatus WindowFocusChanged(EventHandlerCallRef nextHandler, EventRef event, void* macMouse);
+        
+        // "universal procedure pointers" - required reference for callbacks
+		EventHandlerUPP mouseUPP;
+		EventHandlerRef mouseEventRef;
+		
+		EventHandlerUPP mWindowFocusListener;
+		EventHandlerRef mWindowFocusHandler;
+		
+		bool mNeedsToRegainFocus;
+		bool mMouseWarped;
+		
+		MouseState mTempState;
+	};
+}
+
+
+#endif // OIS_MacMouse_H
Index: /code/branches/RacingBots_FS18/src/external/ois/mac/MacPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/mac/MacPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/mac/MacPrereqs.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ The zlib/libpng License
+ 
+ Copyright (c) 2006 Chris Snyder 
+ 
+ This software is provided 'as-is', without any express or implied warranty. In no event will
+ the authors be held liable for any damages arising from the use of this software.
+ 
+ Permission is granted to anyone to use this software for any purpose, including commercial 
+ applications, and to alter it and redistribute it freely, subject to the following
+ restrictions:
+ 
+ 1. The origin of this software must not be misrepresented; you must not claim that 
+ you wrote the original software. If you use this software in a product, 
+ an acknowledgment in the product documentation would be appreciated but is 
+ not required.
+ 
+ 2. Altered source versions must be plainly marked as such, and must not be 
+ misrepresented as being the original software.
+ 
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_MacPrereqs_H
+#define OIS_MacPrereqs_H
+
+#include <string>
+#include <list>
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace OIS
+{
+    class MacInputManager;
+	class MacHIDManager;
+	class MacMouse;
+    class MacKeyboard;
+
+	/** 
+		Simple wrapper class for CFString which will create a valid CFString and retain ownership until class instance is outof scope
+		To Access the CFStringRef instance, simply cast to void*, pass into a function expecting a void* CFStringRef object, or access via cf_str() method
+	*/
+	class OIS_CFString
+	{
+	public:
+		OIS_CFString() { m_StringRef = CFStringCreateWithCString(NULL, "", kCFStringEncodingUTF8); }
+		OIS_CFString(const char* c_str) { m_StringRef = CFStringCreateWithCString(NULL, c_str, kCFStringEncodingUTF8); }
+		OIS_CFString(const std::string &s_str) { m_StringRef = CFStringCreateWithCString(NULL, s_str.c_str(), kCFStringEncodingUTF8); }
+		~OIS_CFString() { CFRelease(m_StringRef); }
+
+		//Allow this class to be autoconverted to base class of StringRef (void*)
+		operator void*() { return (void*)m_StringRef; }
+		CFStringRef cf_str() { return m_StringRef; }
+	
+	private:
+		CFStringRef m_StringRef;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,14 @@
+ADD_SOURCE_FILES(OIS_FILES
+  Win32ForceFeedback.h
+  Win32InputManager.h
+  Win32JoyStick.h
+  Win32KeyBoard.h
+  Win32Mouse.h
+  Win32Prereqs.h
+
+  Win32ForceFeedback.cpp
+  Win32InputManager.cpp
+  Win32JoyStick.cpp
+  Win32KeyBoard.cpp
+  Win32Mouse.cpp
+)
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32ForceFeedback.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32ForceFeedback.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32ForceFeedback.cpp	(revision 11817)
@@ -0,0 +1,544 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "win32/Win32ForceFeedback.h"
+#include "OISException.h"
+#include <math.h>
+#include <cstddef>
+
+// 0 = No trace; 1 = Important traces; 2 = Debug traces
+#define OIS_WIN32_JOYFF_DEBUG 0
+
+#if (defined (_DEBUG) || defined(OIS_WIN32_JOYFF_DEBUG))
+  #include <iostream>
+  #include <sstream>
+  using namespace std;
+#endif
+
+using namespace OIS;
+
+//--------------------------------------------------------------//
+Win32ForceFeedback::Win32ForceFeedback(IDirectInputDevice8* pDIJoy, const DIDEVCAPS* pDIJoyCaps) :
+  mHandles(0), mJoyStick(pDIJoy), mFFAxes(0), mpDIJoyCaps(pDIJoyCaps)
+{
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+  cout << "FFSamplePeriod      : " << mpDIJoyCaps->dwFFSamplePeriod << " mu-s, "
+	   << "FFMinTimeResolution : " << mpDIJoyCaps->dwFFMinTimeResolution << " mu-s,"
+	   << "" << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+Win32ForceFeedback::~Win32ForceFeedback()
+{
+	//Get the effect - if it exists
+	for(EffectList::iterator i = mEffectList.begin(); i != mEffectList.end(); ++i )
+	{
+		LPDIRECTINPUTEFFECT dxEffect = i->second;
+		if( dxEffect )
+		{
+			dxEffect->Unload();
+			dxEffect->Release();
+		}
+	}
+
+	mEffectList.clear();
+}
+
+//--------------------------------------------------------------//
+short Win32ForceFeedback::getFFAxesNumber()
+{
+	return mFFAxes;
+}
+
+//--------------------------------------------------------------//
+unsigned short Win32ForceFeedback::getFFMemoryLoad()
+{
+    DIPROPDWORD dipdw;  // DIPROPDWORD contains a DIPROPHEADER structure. 
+	dipdw.diph.dwSize       = sizeof(DIPROPDWORD); 
+	dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); 
+	dipdw.diph.dwObj        = 0; // device property 
+	dipdw.diph.dwHow        = DIPH_DEVICE;
+	dipdw.dwData            = 0; // In case of any error.
+
+	const HRESULT hr = mJoyStick->GetProperty(DIPROP_FFLOAD, &dipdw.diph);
+	if(FAILED(hr))
+	{
+	    if (hr == DIERR_NOTEXCLUSIVEACQUIRED)
+		    OIS_EXCEPT(E_General, "Can't query FF memory load as device was not acquired in exclusive mode");
+		else
+		    OIS_EXCEPT(E_General, "Unknown error querying FF memory load ->..");
+	}
+
+	return (unsigned short)dipdw.dwData;
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::upload( const Effect* effect )
+{
+	switch( effect->force )
+	{
+		case OIS::Effect::ConstantForce: _updateConstantEffect(effect);	break;
+		case OIS::Effect::RampForce: _updateRampEffect(effect);	break;
+		case OIS::Effect::PeriodicForce: _updatePeriodicEffect(effect);	break;
+		case OIS::Effect::ConditionalForce:	_updateConditionalEffect(effect); break;
+		//case OIS::Effect::CustomForce: _updateCustomEffect(effect); break;
+		default: OIS_EXCEPT(E_NotImplemented, "Requested Force not Implemented yet, sorry!"); break;
+	}
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::modify( const Effect* eff )
+{
+	//Modifying is essentially the same as an upload, so, just reuse that function
+	upload(eff);
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::remove( const Effect* eff )
+{
+	//Get the effect - if it exists
+	EffectList::iterator i = mEffectList.find(eff->_handle);
+	if( i != mEffectList.end() )
+	{
+		LPDIRECTINPUTEFFECT dxEffect = i->second;
+		if( dxEffect )
+		{
+			dxEffect->Stop();
+			//We care about the return value - as the effect might not
+			//have been unlaoded
+			if( SUCCEEDED(dxEffect->Unload()) )
+			{
+			    dxEffect->Release();
+				mEffectList.erase(i);
+			}
+		}
+		else
+			mEffectList.erase(i);
+	}
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::setMasterGain( float level )
+{
+	//Between 0 - 10,000
+	int gain_level = (int)(10000.0f * level);
+
+	if( gain_level > 10000 )
+		gain_level = 10000;
+	else if( gain_level < 0 )
+		gain_level = 0;
+
+	DIPROPDWORD DIPropGain;
+	DIPropGain.diph.dwSize       = sizeof(DIPropGain);
+	DIPropGain.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+	DIPropGain.diph.dwObj        = 0;
+	DIPropGain.diph.dwHow        = DIPH_DEVICE;
+	DIPropGain.dwData            = gain_level;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+	cout << "Win32ForceFeedback("<< mJoyStick << ") : Setting master gain to " 
+		 << level << " => " << DIPropGain.dwData << endl;
+#endif
+
+	const HRESULT hr = mJoyStick->SetProperty(DIPROP_FFGAIN, &DIPropGain.diph);
+
+#if defined (_DEBUG)
+	if(FAILED(hr))
+	    cout << "Failed to change master gain" << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::setAutoCenterMode( bool auto_on )
+{
+	DIPROPDWORD DIPropAutoCenter;
+	DIPropAutoCenter.diph.dwSize       = sizeof(DIPropAutoCenter);
+	DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+	DIPropAutoCenter.diph.dwObj        = 0;
+	DIPropAutoCenter.diph.dwHow        = DIPH_DEVICE;
+	DIPropAutoCenter.dwData            = (auto_on ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF);
+
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+	cout << "Win32ForceFeedback("<< mJoyStick << ") : Setting auto-center mode to " 
+		 << auto_on << " => " << DIPropAutoCenter.dwData << endl;
+#endif
+
+	const HRESULT hr = mJoyStick->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
+
+#if defined (_DEBUG)
+	if(FAILED(hr))
+	    cout << "Failed to change auto-center mode" << endl;
+#endif
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_updateConstantEffect( const Effect* effect )
+{
+	ConstantEffect *eff = static_cast<ConstantEffect*>(effect->getForceEffect());
+
+	DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
+	LONG            rglDirection[2] = { 0, 0 };
+	DIENVELOPE      diEnvelope;
+	DICONSTANTFORCE cf;
+	DIEFFECT        diEffect;
+
+	//Currently only support 1 axis
+	//if( effect->getNumAxes() == 1 )
+	cf.lMagnitude = eff->level;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+	cout << "  Level : " << eff->level
+		 << " => " << cf.lMagnitude << endl;
+#endif
+
+	_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICONSTANTFORCE), &cf, effect, &eff->envelope);
+	_upload(GUID_ConstantForce, &diEffect, effect);
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_updateRampEffect( const Effect* effect )
+{
+	RampEffect *eff = static_cast<RampEffect*>(effect->getForceEffect());
+
+	DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
+	LONG            rglDirection[2] = { 0, 0 };
+	DIENVELOPE      diEnvelope;
+	DIRAMPFORCE     rf;
+	DIEFFECT        diEffect;
+
+	//Currently only support 1 axis
+	rf.lStart = eff->startLevel;
+	rf.lEnd = eff->endLevel;
+
+	_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DIRAMPFORCE), &rf, effect, &eff->envelope );
+	_upload(GUID_RampForce, &diEffect, effect);
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_updatePeriodicEffect( const Effect* effect )
+{
+	PeriodicEffect *eff = static_cast<PeriodicEffect*>(effect->getForceEffect());
+
+	DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
+	LONG            rglDirection[2] = { 0, 0 };
+	DIENVELOPE      diEnvelope;
+	DIPERIODIC      pf;
+	DIEFFECT        diEffect;
+
+	//Currently only support 1 axis
+	pf.dwMagnitude = eff->magnitude;
+	pf.lOffset = eff->offset;
+	pf.dwPhase = eff->phase;
+	pf.dwPeriod = eff->period;
+
+	_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DIPERIODIC), &pf, effect, &eff->envelope );
+
+	switch( effect->type )
+	{
+	case OIS::Effect::Square: _upload(GUID_Square, &diEffect, effect); break;
+	case OIS::Effect::Triangle: _upload(GUID_Triangle, &diEffect, effect); break;
+	case OIS::Effect::Sine: _upload(GUID_Sine, &diEffect, effect); break;
+	case OIS::Effect::SawToothUp: _upload(GUID_SawtoothUp, &diEffect, effect); break;
+	case OIS::Effect::SawToothDown:	_upload(GUID_SawtoothDown, &diEffect, effect); break;
+	default: break;
+	}
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_updateConditionalEffect( const Effect* effect )
+{
+	ConditionalEffect *eff = static_cast<ConditionalEffect*>(effect->getForceEffect());
+
+	DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
+	LONG            rglDirection[2] = { 0, 0 };
+	DIENVELOPE      diEnvelope;
+	DICONDITION     cf;
+	DIEFFECT        diEffect;
+
+	cf.lOffset = eff->deadband;
+	cf.lPositiveCoefficient = eff->rightCoeff;
+	cf.lNegativeCoefficient = eff->leftCoeff;
+	cf.dwPositiveSaturation = eff->rightSaturation;
+	cf.dwNegativeSaturation = eff->leftSaturation;
+	cf.lDeadBand = eff->deadband;
+
+	_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICONDITION), &cf, effect, 0 );
+
+	switch( effect->type )
+	{
+	case OIS::Effect::Friction:	_upload(GUID_Friction, &diEffect, effect); break;
+	case OIS::Effect::Damper: _upload(GUID_Damper, &diEffect, effect); break;
+	case OIS::Effect::Inertia: _upload(GUID_Inertia, &diEffect, effect); break;
+	case OIS::Effect::Spring: _upload(GUID_Spring, &diEffect, effect); break;
+	default: break;
+	}
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_updateCustomEffect( const Effect* /*effect*/ )
+{
+    //CustomEffect *eff = static_cast<CustomEffect*>(effect->getForceEffect());
+    //
+	//DWORD           rgdwAxes[2]     = { DIJOFS_X, DIJOFS_Y };
+	//LONG            rglDirection[2] = { 0, 0 };
+	//DIENVELOPE      diEnvelope;
+	//DICUSTOMFORCE cf;
+	//DIEFFECT        diEffect;
+	//cf.cChannels = 0;
+	//cf.dwSamplePeriod = 0;
+	//cf.cSamples = 0;
+	//cf.rglForceData = 0;
+	//_setCommonProperties(&diEffect, rgdwAxes, rglDirection, &diEnvelope, sizeof(DICUSTOMFORCE), &cf, effect, &eff->envelope);
+	//_upload(GUID_CustomForce, &diEffect, effect);
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_setCommonProperties(
+		DIEFFECT* diEffect, DWORD* rgdwAxes,
+		LONG* rglDirection, DIENVELOPE* diEnvelope, DWORD struct_size,
+		LPVOID struct_type, const Effect* effect, const Envelope* envelope )
+{
+	ZeroMemory(diEffect, sizeof(DIEFFECT));
+
+	diEffect->dwSize                  = sizeof(DIEFFECT);
+	diEffect->dwFlags                 = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
+	diEffect->dwGain                  = DI_FFNOMINALMAX;
+
+	diEffect->dwTriggerButton         = DIEB_NOTRIGGER; // effect->trigger_button; // TODO: Conversion
+	diEffect->dwTriggerRepeatInterval = effect->trigger_interval;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+	cout << "  Trigger :" << endl
+		 << "    Button   : " << effect->trigger_button 
+		 << " => " << diEffect->dwTriggerButton << endl
+		 << "    Interval : " << effect->trigger_interval 
+		 << " => " << diEffect->dwTriggerRepeatInterval << endl;
+#endif
+
+	diEffect->cAxes                   = 1; // effect->getNumAxes();
+	diEffect->rgdwAxes                = rgdwAxes;
+
+	diEffect->rglDirection            = rglDirection; // TODO: conversion from effect->direction
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+	cout << "  Direction : " << Effect::getDirectionName(effect->direction)
+		 << " => {";
+	for (int iDir=0; iDir < (int)diEffect->cAxes; iDir++)
+	  cout << " " << diEffect->rglDirection[iDir];
+	cout << "}" << endl;
+#endif
+
+	if (diEnvelope && envelope && envelope->isUsed())
+	{
+	    diEnvelope->dwSize = sizeof(DIENVELOPE);
+	    diEnvelope->dwAttackLevel = envelope->attackLevel;
+	    diEnvelope->dwAttackTime  = envelope->attackLength;
+	    diEnvelope->dwFadeLevel   = envelope->fadeLevel;
+	    diEnvelope->dwFadeTime    = envelope->fadeLength;
+	    diEffect->lpEnvelope = diEnvelope;
+	}
+	else
+	    diEffect->lpEnvelope = 0;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+	if (diEnvelope && envelope && envelope->isUsed())
+	{
+		cout << "  Enveloppe :" << endl
+			 << "    AttackLen : " << envelope->attackLength
+			 << " => " << diEnvelope->dwAttackTime << endl 
+			 << "    AttackLvl : " << envelope->attackLevel
+			 << " => " << diEnvelope->dwAttackLevel << endl 
+			 << "    FadeLen   : " << envelope->fadeLength
+			 << " => " << diEnvelope->dwFadeTime << endl
+			 << "    FadeLvl   : " << envelope->fadeLevel
+			 << " => " << diEnvelope->dwFadeLevel << endl;
+	}
+#endif
+
+	diEffect->dwSamplePeriod          = 0;
+	diEffect->dwDuration              = effect->replay_length;
+	diEffect->dwStartDelay            = effect->replay_delay;
+
+#if (OIS_WIN32_JOYFF_DEBUG > 1)
+	cout << "  Replay :" << endl
+		 << "    Length : " << effect->replay_length 
+		 << " => " << diEffect->dwDuration << endl
+		 << "    Delay  : " << effect->replay_delay 
+		 << " => " << diEffect->dwStartDelay << endl;
+#endif
+
+	diEffect->cbTypeSpecificParams    = struct_size;
+	diEffect->lpvTypeSpecificParams   = struct_type;
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_upload( GUID guid, DIEFFECT* diEffect, const Effect* effect)
+{
+	LPDIRECTINPUTEFFECT dxEffect = 0;
+
+	//Get the effect - if it exists
+	EffectList::iterator i = mEffectList.find(effect->_handle);
+	//It has been created already
+	if( i != mEffectList.end() )
+		dxEffect = i->second;
+	else //This effect has not yet been created - generate a handle
+		effect->_handle = mHandles++;
+
+	if( dxEffect == 0 )
+	{
+		//This effect has not yet been created, so create it
+		HRESULT hr = mJoyStick->CreateEffect(guid, diEffect, &dxEffect, NULL);
+		if(SUCCEEDED(hr))
+		{
+			mEffectList[effect->_handle] = dxEffect;
+			dxEffect->Start(INFINITE,0);
+		}
+		else if( hr == DIERR_DEVICEFULL )
+			OIS_EXCEPT(E_DeviceFull, "Remove an effect before adding more!");
+		else
+			OIS_EXCEPT(E_General, "Unknown error creating effect->..");
+	}
+	else
+	{
+		//ToDo -- Update the Effect
+		HRESULT hr = dxEffect->SetParameters( diEffect, DIEP_DIRECTION |
+			DIEP_DURATION | DIEP_ENVELOPE | DIEP_STARTDELAY | DIEP_TRIGGERBUTTON |
+			DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS | DIEP_START );
+
+		if(FAILED(hr)) OIS_EXCEPT(E_InvalidParam, "Error updating device!");
+	}
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_addEffectSupport( LPCDIEFFECTINFO pdei )
+{
+#if (OIS_WIN32_JOYFF_DEBUG > 0)
+    // Dump some usefull information about the effect type.
+    cout << "Adding support for '" << pdei->tszName << "' effect type" << endl;
+	cout << "  Supported static params: ";
+	if (pdei->dwStaticParams & DIEP_AXES) cout << " Axes";
+	if (pdei->dwStaticParams & DIEP_DIRECTION) cout << " Direction";
+	if (pdei->dwStaticParams & DIEP_DURATION) cout << " Duration";
+	if (pdei->dwStaticParams & DIEP_ENVELOPE) cout << " Envelope";
+	if (pdei->dwStaticParams & DIEP_GAIN) cout << " Gain";
+	if (pdei->dwStaticParams & DIEP_SAMPLEPERIOD) cout << " SamplePeriod";
+	if (pdei->dwStaticParams & DIEP_STARTDELAY) cout << " StartDelay";
+	if (pdei->dwStaticParams & DIEP_TRIGGERBUTTON) cout << " TriggerButton";
+	if (pdei->dwStaticParams & DIEP_TRIGGERREPEATINTERVAL) cout << " TriggerRepeatInterval";
+	if (pdei->dwStaticParams & DIEP_TYPESPECIFICPARAMS) cout << " TypeSpecificParams";
+	cout << endl;
+	cout << "  Supported dynamic params: ";
+	if (pdei->dwDynamicParams & DIEP_AXES) cout << " Axes";
+	if (pdei->dwDynamicParams & DIEP_DIRECTION) cout << " Direction";
+	if (pdei->dwDynamicParams & DIEP_DURATION) cout << " Duration";
+	if (pdei->dwDynamicParams & DIEP_ENVELOPE) cout << " Envelope";
+	if (pdei->dwDynamicParams & DIEP_GAIN) cout << " Gain";
+	if (pdei->dwDynamicParams & DIEP_SAMPLEPERIOD) cout << " SamplePeriod";
+	if (pdei->dwDynamicParams & DIEP_STARTDELAY) cout << " StartDelay";
+	if (pdei->dwDynamicParams & DIEP_TRIGGERBUTTON) cout << " TriggerButton";
+	if (pdei->dwDynamicParams & DIEP_TRIGGERREPEATINTERVAL) cout << " TriggerRepeatInterval";
+	if (pdei->dwDynamicParams & DIEP_TYPESPECIFICPARAMS) cout << " TypeSpecificParams";
+	cout << endl;
+	cout << "  More details about supported parameters support: ";
+	if (pdei->dwEffType & DIEFT_STARTDELAY) cout << " StartDelay";
+	if (pdei->dwEffType & DIEFT_FFATTACK) cout << " Attack";
+	if (pdei->dwEffType & DIEFT_FFFADE) cout << " Fade";
+	if (pdei->dwEffType & DIEFT_DEADBAND) cout << " DeadBand";
+	if (pdei->dwEffType & DIEFT_SATURATION) cout << " Saturation";
+	if (pdei->dwEffType & DIEFT_POSNEGSATURATION) cout << " PosNegaturation";
+	if (pdei->dwEffType & DIEFT_POSNEGCOEFFICIENTS) cout << " PosNegCoefficients";
+	if (pdei->dwEffType & DIEFT_HARDWARE) cout << " HardwareSpecific";
+	cout << endl;
+#endif
+
+    Effect::EForce eForce;
+	switch (DIEFT_GETTYPE(pdei->dwEffType))
+	{
+	    case DIEFT_CONSTANTFORCE:
+		    eForce = Effect::ConstantForce;
+			break;
+	    case DIEFT_RAMPFORCE:
+		    eForce = Effect::RampForce;
+			break;
+	    case DIEFT_PERIODIC:
+		    eForce = Effect::PeriodicForce;
+			break;
+	    case DIEFT_CONDITION:
+		    eForce = Effect::ConditionalForce;
+			break;
+	    case DIEFT_CUSTOMFORCE:
+		    eForce = Effect::CustomForce;
+			break;
+	    default:
+		    eForce = Effect::UnknownForce;
+#if defined (_DEBUG)
+			cout << "Win32ForceFeedback: DirectInput8 Effect type support not implemented: " 
+				 << "DIEFT_GETTYPE="<< (int)DIEFT_GETTYPE(pdei->dwEffType) << endl;
+#endif
+			return;
+	}
+
+	//Determine what the effect type is and how it corresponds to our OIS's Enums
+	//We could save the GUIDs too, however, we will just use the predefined ones later
+	if( pdei->guid == GUID_ConstantForce )
+		_addEffectTypes(eForce, Effect::Constant );
+	else if( pdei->guid == GUID_Triangle )
+		_addEffectTypes(eForce, Effect::Triangle );
+	else if( pdei->guid == GUID_Spring )
+		_addEffectTypes(eForce, Effect::Spring );
+	else if( pdei->guid == GUID_Friction )
+		_addEffectTypes(eForce, Effect::Friction );
+	else if( pdei->guid == GUID_Square )
+		_addEffectTypes(eForce, Effect::Square );
+	else if( pdei->guid == GUID_Sine )
+		_addEffectTypes(eForce, Effect::Sine );
+	else if( pdei->guid == GUID_SawtoothUp )
+		_addEffectTypes(eForce, Effect::SawToothUp );
+	else if( pdei->guid == GUID_SawtoothDown )
+		_addEffectTypes(eForce, Effect::SawToothDown );
+	else if( pdei->guid == GUID_Damper )
+		_addEffectTypes(eForce, Effect::Damper );
+	else if( pdei->guid == GUID_Inertia )
+		_addEffectTypes(eForce, Effect::Inertia );
+	else if( pdei->guid == GUID_CustomForce )
+		_addEffectTypes(eForce, Effect::Custom );
+	else if( pdei->guid == GUID_RampForce )
+		_addEffectTypes(eForce, Effect::Ramp );
+
+#if defined (_DEBUG)
+	//Only care about this for Debugging Purposes
+	//else
+	//{
+	//	std::ostringstream ss;
+	//	ss << "Win32ForceFeedback, DirectInput8 Effect not found. Reported as: "
+	//	   << pdei->tszName;
+	//	OIS_EXCEPT( E_General, ss.str().c_str());
+	//}
+#endif
+}
+
+//--------------------------------------------------------------//
+void Win32ForceFeedback::_addFFAxis()
+{
+	mFFAxes++;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32ForceFeedback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32ForceFeedback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32ForceFeedback.h	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Win32ForceFeedBack_H
+#define OIS_Win32ForceFeedBack_H
+
+#include "OISPrereqs.h"
+#include "OISForceFeedback.h"
+#include "win32/Win32Prereqs.h"
+
+namespace OIS
+{
+	class Win32ForceFeedback : public ForceFeedback
+	{
+		Win32ForceFeedback() {}
+	public:
+		Win32ForceFeedback(IDirectInputDevice8* pDIJoy, const DIDEVCAPS* pDIJoyCaps);
+		~Win32ForceFeedback();
+
+		/** @copydoc ForceFeedback::upload */
+		void upload( const Effect* effect );
+
+		/** @copydoc ForceFeedback::modify */
+		void modify( const Effect* effect );
+
+		/** @copydoc ForceFeedback::remove */
+		void remove( const Effect* effect );
+
+		/** @copydoc ForceFeedback::setMasterGain */
+		void setMasterGain( float level );
+		
+		/** @copydoc ForceFeedback::setAutoCenterMode */
+		void setAutoCenterMode( bool auto_on );
+
+		/** @copydoc ForceFeedback::getFFAxesNumber */
+		short getFFAxesNumber();
+
+		/** @copydoc ForceFeedback::getFFMemoryLoad */
+		unsigned short getFFMemoryLoad();
+
+		/**
+			@remarks
+			Internal use.. Used during enumeration to build a list of a devices
+			support effects.
+		*/
+		void _addEffectSupport( LPCDIEFFECTINFO pdei );
+
+		/**
+			@remarks
+			Internal use.. Used during axis enumeration to get number of FF axes
+			support effects.
+		*/
+		void _addFFAxis();
+
+	protected:
+
+		//Specific Effect Settings
+		void _updateConstantEffect( const Effect* effect );
+		void _updateRampEffect( const Effect* effect );
+		void _updatePeriodicEffect( const Effect* effect );
+		void _updateConditionalEffect( const Effect* effect );
+		void _updateCustomEffect( const Effect* effect );
+
+		//Sets the common properties to all effects
+		void _setCommonProperties( DIEFFECT* diEffect, DWORD* rgdwAxes,
+									LONG* rglDirection, DIENVELOPE* diEnvelope, DWORD struct_size, 
+									LPVOID struct_type, const Effect* effect, const Envelope* envelope );
+		//Actually do the upload
+		void _upload( GUID, DIEFFECT*, const Effect* );
+
+		// Map of currently uploaded effects (handle => effect)
+		typedef std::map<int,LPDIRECTINPUTEFFECT> EffectList;
+		EffectList mEffectList;
+
+		//Simple unique handle creation - allows for upto 2+ billion effects
+		//during the lifetime of application. Hopefully, that is enough.
+		int mHandles;
+
+		// Joystick device descriptor.
+		IDirectInputDevice8* mJoyStick;
+		
+		// Joystick capabilities.
+		const DIDEVCAPS* mpDIJoyCaps;
+
+		// Number of axis supporting FF.
+		short mFFAxes;
+	};
+}
+#endif //OIS_Win32ForceFeedBack_H
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32InputManager.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32InputManager.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32InputManager.cpp	(revision 11817)
@@ -0,0 +1,273 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "win32/Win32InputManager.h"
+#include "win32/Win32KeyBoard.h"
+#include "win32/Win32Mouse.h"
+#include "win32/Win32JoyStick.h"
+#include "OISException.h"
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------//
+Win32InputManager::Win32InputManager() : InputManager("Win32InputManager")
+{
+	hWnd = 0;
+	mDirectInput = 0;
+
+	kbSettings    = 0;
+	mouseSettings = 0;
+	joySettings   = 0;
+
+	joySticks = 0;
+	keyboardUsed = mouseUsed = false;
+
+	//Setup our internal factories
+	mFactories.push_back(this);
+}
+
+//--------------------------------------------------------------------------------//
+Win32InputManager::~Win32InputManager()
+{
+	if( mDirectInput )
+	{
+		mDirectInput->Release();
+		mDirectInput = 0;
+	}
+}
+
+//--------------------------------------------------------------------------------//
+void Win32InputManager::_initialize( ParamList &paramList )
+{
+	HINSTANCE hInst = 0;
+	HRESULT hr;
+
+	//TODO 64 bit proof this little conversion xxx wip
+	//First of all, get the Windows Handle and Instance
+	ParamList::iterator i = paramList.find("WINDOW");
+	if( i == paramList.end() ) 
+		OIS_EXCEPT( E_InvalidParam, "Win32InputManager::Win32InputManager >> No HWND found!" );
+
+	hWnd  = (HWND)strtoul(i->second.c_str(), 0, 10);
+
+	if( IsWindow(hWnd) == 0 )
+		OIS_EXCEPT( E_General, "Win32InputManager::Win32InputManager >> The sent HWND is not valid!");
+
+	hInst = GetModuleHandle(0);
+
+	//Create the device
+	hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mDirectInput, NULL );
+    if (FAILED(hr))	
+		OIS_EXCEPT( E_General, "Win32InputManager::Win32InputManager >> Not able to init DirectX8 Input!");
+
+	//Ok, now we have DirectInput, parse whatever extra settings were sent to us
+	_parseConfigSettings( paramList );
+
+	// Enumerate devices ...
+	_enumerateDevices();
+}
+
+//--------------------------------------------------------------------------------//
+void Win32InputManager::_parseConfigSettings( ParamList &paramList )
+{
+	//Here we pick up settings such as a device's cooperation mode
+	std::map<std::string, DWORD> temp;
+	temp["DISCL_BACKGROUND"]	= DISCL_BACKGROUND;
+	temp["DISCL_EXCLUSIVE"]		= DISCL_EXCLUSIVE;
+	temp["DISCL_FOREGROUND"]	= DISCL_FOREGROUND;
+	temp["DISCL_NONEXCLUSIVE"]	= DISCL_NONEXCLUSIVE;
+	temp["DISCL_NOWINKEY"]		= DISCL_NOWINKEY;
+
+	//Check for pairs: ie. ("w32_keyboard","DISCL_NOWINKEY")("w32_keyboard","DISCL_FOREGROUND")
+	ParamList::iterator i = paramList.begin(), e = paramList.end();
+	for( ; i != e; ++i ) 
+	{
+		if( i->first == "w32_keyboard" )
+				kbSettings |= temp[i->second];
+		else if( i->first == "w32_mouse" )
+				mouseSettings |= temp[i->second];
+		else if( i->first == "w32_joystick" )
+				joySettings |= temp[i->second];
+	}
+	if( kbSettings == 0 ) kbSettings = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY;
+	if( mouseSettings == 0 ) mouseSettings = DISCL_FOREGROUND | DISCL_EXCLUSIVE;
+	if( joySettings == 0 ) joySettings = DISCL_FOREGROUND | DISCL_EXCLUSIVE;
+}
+
+//--------------------------------------------------------------------------------//
+void Win32InputManager::_enumerateDevices()
+{
+	//Enumerate all attached devices
+	mDirectInput->EnumDevices(NULL, _DIEnumDevCallback, this, DIEDFL_ATTACHEDONLY);
+
+#ifdef OIS_WIN32_XINPUT_SUPPORT
+	//let's check how many possible XInput devices we may have (max 4)... 
+	for(int i = 0; i < 3; ++i)
+	{
+		XINPUT_STATE state;
+		if(XInputGetState(i, &state) != ERROR_DEVICE_NOT_CONNECTED)
+		{	//Once we found 1, just check our whole list against devices
+			Win32JoyStick::CheckXInputDevices(unusedJoyStickList);
+			break;
+		}
+	}
+#endif
+}
+
+//--------------------------------------------------------------------------------//
+BOOL CALLBACK Win32InputManager::_DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
+{
+	Win32InputManager *_this_ = static_cast<Win32InputManager*>(pvRef);
+
+	// Register only game devices (keyboard and mouse are managed differently).
+	if( GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_JOYSTICK ||
+		GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_GAMEPAD ||
+		GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_1STPERSON ||
+		GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_DRIVING ||
+		GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_FLIGHT)
+	{
+		JoyStickInfo jsInfo;
+		jsInfo.isXInput = false;
+		jsInfo.productGuid = lpddi->guidProduct;
+		jsInfo.deviceID = lpddi->guidInstance;
+		jsInfo.vendor = lpddi->tszInstanceName;
+		jsInfo.devId = _this_->joySticks;
+
+		_this_->joySticks++;
+		
+		_this_->unusedJoyStickList.push_back( jsInfo );
+	}
+
+	return DIENUM_CONTINUE;
+}
+
+//----------------------------------------------------------------------------//
+void Win32InputManager::_returnJoyStick(const JoyStickInfo& joystick)
+{
+	unusedJoyStickList.push_back(joystick);
+}
+
+//----------------------------------------------------------------------------//
+DeviceList Win32InputManager::freeDeviceList()
+{
+	DeviceList ret;
+
+	if( keyboardUsed == false )
+		ret.insert(std::make_pair(OISKeyboard, mInputSystemName));
+
+	if( mouseUsed == false )
+		ret.insert(std::make_pair(OISMouse, mInputSystemName));
+
+	for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i)
+		ret.insert(std::make_pair(OISJoyStick, i->vendor));
+
+	return ret;
+}
+
+//----------------------------------------------------------------------------//
+int Win32InputManager::totalDevices(Type iType)
+{
+	switch(iType)
+	{
+	case OISKeyboard: return 1;
+	case OISMouse: return 1;
+	case OISJoyStick: return joySticks;
+	default: return 0;
+	}
+}
+
+//----------------------------------------------------------------------------//
+int Win32InputManager::freeDevices(Type iType)
+{
+	switch(iType)
+	{
+	case OISKeyboard: return keyboardUsed ? 0 : 1;
+	case OISMouse: return mouseUsed ? 0 : 1;
+	case OISJoyStick: return (int)unusedJoyStickList.size();
+	default: return 0;
+	}
+}
+
+//----------------------------------------------------------------------------//
+bool Win32InputManager::vendorExist(Type iType, const std::string & vendor)
+{
+	if( (iType == OISKeyboard || iType == OISMouse) && vendor == mInputSystemName )
+	{
+		return true;
+	}
+	else if( iType == OISJoyStick )
+	{
+		for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i)
+			if(i->vendor == vendor)
+				return true;
+	}
+
+	return false;
+}
+
+//----------------------------------------------------------------------------//
+Object* Win32InputManager::createObject(InputManager* creator, Type iType, bool bufferMode, const std::string & vendor)
+{
+	Object *obj = 0;
+
+	switch(iType)
+	{
+	case OISKeyboard: 
+	{
+		if( keyboardUsed == false )
+			obj = new Win32Keyboard(this, mDirectInput, bufferMode, kbSettings);
+		break;
+	}
+	case OISMouse:
+	{
+		if( mouseUsed == false )
+			obj = new Win32Mouse(this, mDirectInput, bufferMode, mouseSettings);
+		break;
+	}
+	case OISJoyStick:
+	{
+		for(JoyStickInfoList::iterator i = unusedJoyStickList.begin(); i != unusedJoyStickList.end(); ++i)
+		{
+			if(vendor == "" || i->vendor == vendor)
+			{
+				obj = new Win32JoyStick(this, mDirectInput, bufferMode, joySettings, *i);
+				unusedJoyStickList.erase(i);
+				break;
+			}
+		}
+		break;
+	}
+	default:
+		break;
+	}
+
+	if( obj == 0 )
+		OIS_EXCEPT(E_InputDeviceNonExistant, "No devices match requested type.");
+
+	return obj;
+}
+
+//----------------------------------------------------------------------------//
+void Win32InputManager::destroyObject(Object* obj)
+{
+	delete obj;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32InputManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32InputManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32InputManager.h	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef OIS_Win32InputManager_H
+#define OIS_Win32InputManager_H
+
+#include "OISInputManager.h"
+#include "OISFactoryCreator.h"
+#include "win32/Win32Prereqs.h"
+
+namespace OIS
+{
+	/**	Win32InputManager specialization - Using DirectInput8 */
+	class Win32InputManager : public InputManager, public FactoryCreator
+	{
+	public:
+		Win32InputManager();
+		virtual ~Win32InputManager();
+
+		//InputManager Overrides
+		/** @copydoc InputManager::_initialize */
+		void _initialize( ParamList &paramList );
+
+		//FactoryCreator Overrides
+		/** @copydoc FactoryCreator::deviceList */
+		DeviceList freeDeviceList();
+
+		/** @copydoc FactoryCreator::totalDevices */
+		int totalDevices(Type iType);
+
+		/** @copydoc FactoryCreator::freeDevices */
+		int freeDevices(Type iType);
+
+		/** @copydoc FactoryCreator::vendorExist */
+		bool vendorExist(Type iType, const std::string & vendor);
+
+		/** @copydoc FactoryCreator::createObject */
+		Object* createObject(InputManager* creator, Type iType, bool bufferMode, const std::string & vendor = "");
+
+		/** @copydoc FactoryCreator::destroyObject */
+		void destroyObject(Object* obj);
+
+		//Internal Items
+		//! Internal method, used for flaggin keyboard as available/unavailable for creation
+		void _setKeyboardUsed(bool used) {keyboardUsed = used; }
+
+		//! Internal method, used for flaggin mouse as available/unavailable for creation
+		void _setMouseUsed(bool used) { mouseUsed = used; }
+		
+		//! Internal method, return unused joystick to queue
+		void _returnJoyStick(const JoyStickInfo& joystick);
+
+		//! Returns HWND needed by DirectInput Device Object
+		HWND getWindowHandle() { return hWnd; }
+
+	protected:
+		//! internal class method for dealing with param list
+		void _parseConfigSettings( ParamList &paramList );
+		
+		//! internal class method for finding attached devices
+		void _enumerateDevices();
+
+		//! Used during device enumeration
+		static BOOL CALLBACK _DIEnumDevCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
+
+		//! Keep a list of all joysticks enumerated, but not in use
+		JoyStickInfoList unusedJoyStickList;
+
+		//! The window handle we are using
+		HWND hWnd;
+
+		//! Direct Input Interface
+		IDirectInput8* mDirectInput;
+
+		//! Used for keyboard device settings
+		DWORD kbSettings;
+
+		//! Used for mouse device settings
+		DWORD mouseSettings;
+
+		//! Used for joystick device settings
+		DWORD joySettings;
+
+		//! Number of total joysticks (inuse or not)
+		char joySticks;
+
+		//! Used to know if we used up keyboard
+		bool keyboardUsed;
+
+		//! Used to know if we used up mouse
+		bool mouseUsed;
+	};
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32JoyStick.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32JoyStick.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32JoyStick.cpp	(revision 11817)
@@ -0,0 +1,702 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that
+		you wrote the original software. If you use this software in a product,
+		an acknowledgment in the product documentation would be appreciated but is
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "win32/Win32JoyStick.h"
+#include "win32/Win32InputManager.h"
+#include "win32/Win32ForceFeedback.h"
+#include "OISEvents.h"
+#include "OISException.h"
+
+// (Orxonox): Required for MinGW to compile properly
+#ifdef __MINGW32__
+#  include <oaidl.h>
+#  ifndef __MINGW_EXTENSION
+#    define __MINGW_EXTENSION __extension__
+#  endif
+#endif
+
+#include <cassert>
+#include <cstddef>
+#include <wbemidl.h>
+#include <oleauto.h>
+//#include <wmsstd.h>
+#ifndef SAFE_RELEASE
+#define SAFE_RELEASE(x) \
+   if(x != NULL)        \
+   {                    \
+      x->Release();     \
+      x = NULL;         \
+   }
+#endif
+
+// (Orxonox): MinGW doesn't have swscanf_s
+#ifdef __MINGW32__
+#	define swscanf_s swscanf
+#endif
+
+#ifdef OIS_WIN32_XINPUT_SUPPORT
+#	pragma comment(lib, "xinput.lib")
+#endif
+
+//DX Only defines macros for the JOYSTICK not JOYSTICK2, so fix it
+#undef DIJOFS_BUTTON
+#undef DIJOFS_POV
+
+#define DIJOFS_BUTTON(n)  (FIELD_OFFSET(DIJOYSTATE2, rgbButtons) + (n))
+#define DIJOFS_POV(n)     (FIELD_OFFSET(DIJOYSTATE2, rgdwPOV)+(n)*sizeof(DWORD))
+#define DIJOFS_SLIDER0(n) (FIELD_OFFSET(DIJOYSTATE2, rglSlider)+(n) * sizeof(LONG))
+#define DIJOFS_SLIDER1(n) (FIELD_OFFSET(DIJOYSTATE2, rglVSlider)+(n) * sizeof(LONG))
+#define DIJOFS_SLIDER2(n) (FIELD_OFFSET(DIJOYSTATE2, rglASlider)+(n) * sizeof(LONG))
+#define DIJOFS_SLIDER3(n) (FIELD_OFFSET(DIJOYSTATE2, rglFSlider)+(n) * sizeof(LONG))
+
+#define XINPUT_TRANSLATED_BUTTON_COUNT 12
+#define XINPUT_TRANSLATED_AXIS_COUNT 6
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------------------------//
+Win32JoyStick::Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info ) :
+	JoyStick(info.vendor, buffered, info.devId, creator),
+	mDirectInput(pDI),
+	coopSetting(coopSettings),
+	mJoyStick(0),
+	mJoyInfo(info),
+	mFfDevice(0)
+{
+}
+
+//--------------------------------------------------------------------------------------------------//
+Win32JoyStick::~Win32JoyStick()
+{
+	delete mFfDevice;
+
+	if(mJoyStick)
+	{
+		mJoyStick->Unacquire();
+		mJoyStick->Release();
+		mJoyStick = 0;
+	}
+
+	//Return joystick to pool
+	static_cast<Win32InputManager*>(mCreator)->_returnJoyStick(mJoyInfo);
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32JoyStick::_initialize()
+{
+    if (mJoyInfo.isXInput)
+    {
+        _enumerate();
+    }
+    else
+    {
+	    //Clear old state
+	    mState.mAxes.clear();
+
+	    delete mFfDevice;
+	    mFfDevice = 0;
+
+	    DIPROPDWORD dipdw;
+
+	    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
+	    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+	    dipdw.diph.dwObj        = 0;
+	    dipdw.diph.dwHow        = DIPH_DEVICE;
+	    dipdw.dwData            = JOYSTICK_DX_BUFFERSIZE;
+
+	    if(FAILED(mDirectInput->CreateDevice(mJoyInfo.deviceID, &mJoyStick, NULL)))
+		    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> Could not initialize joy device!");
+
+	    if(FAILED(mJoyStick->SetDataFormat(&c_dfDIJoystick2)))
+		    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> data format error!");
+
+	    HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
+
+	    if(FAILED(mJoyStick->SetCooperativeLevel( hwin, coopSetting)))
+		    OIS_EXCEPT( E_General, "Win32JoyStick::_initialize() >> failed to set cooperation level!");
+
+	    if( FAILED(mJoyStick->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) )
+		    OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set buffer size property" );
+
+	    //Enumerate all axes/buttons/sliders/etc before aquiring
+	    _enumerate();
+
+	    mState.clear();
+
+	    capture();
+    }
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32JoyStick::_enumerate()
+{
+    if (mJoyInfo.isXInput)
+    {
+        mPOVs = 1;
+
+        mState.mButtons.resize(XINPUT_TRANSLATED_BUTTON_COUNT);
+	    mState.mAxes.resize(XINPUT_TRANSLATED_AXIS_COUNT);
+    }
+    else
+    {
+		// Get joystick capabilities.
+		mDIJoyCaps.dwSize = sizeof(DIDEVCAPS);
+		if( FAILED(mJoyStick->GetCapabilities(&mDIJoyCaps)) )
+			OIS_EXCEPT( E_General, "Win32JoyStick::_enumerate >> Failed to get capabilities" );
+
+	    mPOVs = (short)mDIJoyCaps.dwPOVs;
+
+	    mState.mButtons.resize(mDIJoyCaps.dwButtons);
+	    mState.mAxes.resize(mDIJoyCaps.dwAxes);
+
+	    //Reset the axis mapping enumeration value
+	    _AxisNumber = 0;
+
+	    //Enumerate Force Feedback (if any)
+	    mJoyStick->EnumEffects(DIEnumEffectsCallback, this, DIEFT_ALL);
+
+	    //Enumerate and set axis constraints (and check FF Axes)
+	    mJoyStick->EnumObjects(DIEnumDeviceObjectsCallback, this, DIDFT_AXIS);
+    }
+}
+
+//--------------------------------------------------------------------------------------------------//
+BOOL CALLBACK Win32JoyStick::DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef)
+{
+	Win32JoyStick* _this = (Win32JoyStick*)pvRef;
+
+	//Setup mappings
+	DIPROPPOINTER diptr;
+	diptr.diph.dwSize       = sizeof(DIPROPPOINTER);
+	diptr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+	diptr.diph.dwHow        = DIPH_BYID;
+	diptr.diph.dwObj        = lpddoi->dwType;
+	//Add a magic number to recognise we set seomthing
+	diptr.uData             = 0x13130000 | _this->_AxisNumber;
+
+	//Check if axis is slider, if so, do not treat as regular axis
+	if(GUID_Slider == lpddoi->guidType)
+	{
+		++_this->mSliders;
+
+		//Decrease Axes, since this slider shows up in a different place
+		_this->mState.mAxes.pop_back();
+	}
+	else if (FAILED(_this->mJoyStick->SetProperty(DIPROP_APPDATA, &diptr.diph)))
+	{	//If for some reason we could not set needed user data, just ignore this axis
+		return DIENUM_CONTINUE;
+	}
+
+	//Increase for next time through
+	if(GUID_Slider != lpddoi->guidType)
+		_this->_AxisNumber += 1;
+
+	//Set range
+	DIPROPRANGE diprg;
+	diprg.diph.dwSize       = sizeof(DIPROPRANGE);
+	diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+	diprg.diph.dwHow        = DIPH_BYID;
+	diprg.diph.dwObj        = lpddoi->dwType;
+	diprg.lMin              = MIN_AXIS;
+	diprg.lMax              = MAX_AXIS;
+
+	if (FAILED(_this->mJoyStick->SetProperty(DIPROP_RANGE, &diprg.diph)))
+		OIS_EXCEPT( E_General, "Win32JoyStick::_DIEnumDeviceObjectsCallback >> Failed to set min/max range property" );
+
+	//Check if FF Axes, and if so, increment counter
+	if((lpddoi->dwFlags & DIDOI_FFACTUATOR) != 0 )
+	{
+		if( _this->mFfDevice )
+		{
+			_this->mFfDevice->_addFFAxis();
+		}
+	}
+
+	//Force the flags for gain and auto-center support to true,
+	//as DInput has no API to query the device for these capabilities
+	//(the only way to know is to try them ...)
+	if( _this->mFfDevice )
+	{
+	    _this->mFfDevice->_setGainSupport(true);
+	    _this->mFfDevice->_setAutoCenterSupport(true);
+	}
+
+	return DIENUM_CONTINUE;
+}
+
+//--------------------------------------------------------------------------------------------------//
+BOOL CALLBACK Win32JoyStick::DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef)
+{
+	Win32JoyStick* _this = (Win32JoyStick*)pvRef;
+
+	//Create the FF instance only after we know there is at least one effect type
+	if( _this->mFfDevice == 0 )
+		_this->mFfDevice = new Win32ForceFeedback(_this->mJoyStick, &_this->mDIJoyCaps);
+
+	_this->mFfDevice->_addEffectSupport(pdei);
+
+	return DIENUM_CONTINUE;
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32JoyStick::capture()
+{
+#ifdef OIS_WIN32_XINPUT_SUPPORT
+	//handle xbox controller differently
+    if (mJoyInfo.isXInput)
+	{
+		captureXInput();
+		return;
+	}
+#endif
+
+	//handle directinput based devices
+	DIDEVICEOBJECTDATA diBuff[JOYSTICK_DX_BUFFERSIZE];
+	DWORD entries = JOYSTICK_DX_BUFFERSIZE;
+
+	// Poll the device to read the current state
+	HRESULT hr = mJoyStick->Poll();
+	if( hr == DI_OK )
+		hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
+
+	if( hr != DI_OK )
+	{
+		hr = mJoyStick->Acquire();
+		while( hr == DIERR_INPUTLOST )
+			hr = mJoyStick->Acquire();
+
+		// Poll the device to read the current state
+		mJoyStick->Poll();
+		hr = mJoyStick->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
+		//Perhaps the user just tabbed away
+		if( FAILED(hr) )
+			return;
+	}
+
+	bool axisMoved[24] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,
+						  false,false,false,false,false,false,false,false};
+	bool sliderMoved[4] = {false,false,false,false};
+
+	//Loop through all the events
+	for(unsigned int i = 0; i < entries; ++i)
+	{
+		//This may seem outof order, but is in order of the way these variables
+		//are declared in the JoyStick State 2 structure.
+		switch(diBuff[i].dwOfs)
+		{
+		//------ slider -//
+		case DIJOFS_SLIDER0(0):
+			sliderMoved[0] = true;
+			mState.mSliders[0].abX = diBuff[i].dwData;
+			break;
+		case DIJOFS_SLIDER0(1):
+			sliderMoved[0] = true;
+			mState.mSliders[0].abY = diBuff[i].dwData;
+			break;
+		//----- Max 4 POVs Next ---------------//
+		case DIJOFS_POV(0):
+			if(!_changePOV(0,diBuff[i]))
+				return;
+			break;
+		case DIJOFS_POV(1):
+			if(!_changePOV(1,diBuff[i]))
+				return;
+			break;
+		case DIJOFS_POV(2):
+			if(!_changePOV(2,diBuff[i]))
+				return;
+			break;
+		case DIJOFS_POV(3):
+			if(!_changePOV(3,diBuff[i]))
+				return;
+			break;
+		case DIJOFS_SLIDER1(0):
+			sliderMoved[1] = true;
+			mState.mSliders[1].abX = diBuff[i].dwData;
+			break;
+		case DIJOFS_SLIDER1(1):
+			sliderMoved[1] = true;
+			mState.mSliders[1].abY = diBuff[i].dwData;
+			break;
+		case DIJOFS_SLIDER2(0):
+			sliderMoved[2] = true;
+			mState.mSliders[2].abX = diBuff[i].dwData;
+			break;
+		case DIJOFS_SLIDER2(1):
+			sliderMoved[2] = true;
+			mState.mSliders[2].abY = diBuff[i].dwData;
+			break;
+		case DIJOFS_SLIDER3(0):
+			sliderMoved[3] = true;
+			mState.mSliders[3].abX = diBuff[i].dwData;
+			break;
+		case DIJOFS_SLIDER3(1):
+			sliderMoved[3] = true;
+			mState.mSliders[3].abY = diBuff[i].dwData;
+			break;
+		//-----------------------------------------//
+		default:
+			//Handle Button Events Easily using the DX Offset Macros
+			if( diBuff[i].dwOfs >= DIJOFS_BUTTON(0) && diBuff[i].dwOfs < DIJOFS_BUTTON(128) )
+			{
+				if(!_doButtonClick((diBuff[i].dwOfs - DIJOFS_BUTTON(0)), diBuff[i]))
+					return;
+			}
+			else if((short)(diBuff[i].uAppData >> 16) == 0x1313)
+			{	//If it was nothing else, might be axis enumerated earlier (determined by magic number)
+				int axis = (int)(0x0000FFFF & diBuff[i].uAppData); //Mask out the high bit
+				assert( axis >= 0 && axis < (int)mState.mAxes.size() && "Axis out of range!");
+
+				if(axis >= 0 && axis < (int)mState.mAxes.size())
+				{
+					mState.mAxes[axis].abs = diBuff[i].dwData;
+					axisMoved[axis] = true;
+				}
+			}
+
+			break;
+		} //end case
+	} //end for
+
+	//Check to see if any of the axes values have changed.. if so send events
+	if( mBuffered && mListener && entries > 0 )
+	{
+		JoyStickEvent temp(this, mState);
+
+		//Update axes
+		for( int i = 0; i < 24; ++i )
+			if( axisMoved[i] )
+				if( mListener->axisMoved( temp, i ) == false )
+					return;
+
+		//Now update sliders
+		for( int i = 0; i < 4; ++i )
+			if( sliderMoved[i] )
+				if( mListener->sliderMoved( temp, i ) == false )
+					return;
+	}
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32JoyStick::captureXInput()
+{
+#ifdef OIS_WIN32_XINPUT_SUPPORT
+    XINPUT_STATE inputState;
+	if (XInputGetState((DWORD)mJoyInfo.xInputDev, &inputState) != ERROR_SUCCESS)
+        memset(&inputState, 0, sizeof(inputState));
+
+    //Sticks and triggers
+	int value;
+    bool axisMoved[XINPUT_TRANSLATED_AXIS_COUNT] = {false,false,false,false,false,false};
+
+	//LeftY
+	value = -(int)inputState.Gamepad.sThumbLY;
+	mState.mAxes[0].rel = value - mState.mAxes[0].abs;
+	mState.mAxes[0].abs = value;
+	if(mState.mAxes[0].rel != 0)
+        axisMoved[0] = true;
+
+	//LeftX
+    mState.mAxes[1].rel = inputState.Gamepad.sThumbLX - mState.mAxes[1].abs;
+    mState.mAxes[1].abs = inputState.Gamepad.sThumbLX;
+
+	if(mState.mAxes[1].rel != 0)
+        axisMoved[1] = true;
+
+	//RightY
+	value = -(int)inputState.Gamepad.sThumbRY;           
+    mState.mAxes[2].rel = value - mState.mAxes[2].abs;
+    mState.mAxes[2].abs = value;
+	if(mState.mAxes[2].rel != 0)
+        axisMoved[2] = true;
+
+	//RightX
+    mState.mAxes[3].rel = inputState.Gamepad.sThumbRX - mState.mAxes[3].abs;
+    mState.mAxes[3].abs = inputState.Gamepad.sThumbRX;
+	if(mState.mAxes[3].rel != 0)
+		axisMoved[3] = true;
+
+	//Left trigger
+    value = inputState.Gamepad.bLeftTrigger * 129;
+	if(value > JoyStick::MAX_AXIS)
+		value = JoyStick::MAX_AXIS;
+
+    mState.mAxes[4].rel = value - mState.mAxes[4].abs;
+    mState.mAxes[4].abs = value;
+	if(mState.mAxes[4].rel != 0)
+		axisMoved[4] = true;
+
+	//Right trigger
+    value = (int)inputState.Gamepad.bRightTrigger * 129;
+	if(value > JoyStick::MAX_AXIS)
+		value = JoyStick::MAX_AXIS;
+
+	mState.mAxes[5].rel = value - mState.mAxes[5].abs;
+    mState.mAxes[5].abs = value;
+	if(mState.mAxes[5].rel != 0)
+		axisMoved[5] = true;
+    
+    //POV
+    int previousPov = mState.mPOV[0].direction;        
+    int& pov = mState.mPOV[0].direction;
+    pov = Pov::Centered;        
+    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
+        pov |= Pov::North;
+    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
+        pov |= Pov::South;
+    if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
+        pov |= Pov::West;
+    else if (inputState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
+        pov |= Pov::East;
+    
+    //Buttons - The first 4 buttons don't need to be checked since they represent the dpad
+    bool previousButtons[XINPUT_TRANSLATED_BUTTON_COUNT];
+    std::copy(mState.mButtons.begin(), mState.mButtons.end(), previousButtons);
+    for (size_t i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
+        mState.mButtons[i] = (inputState.Gamepad.wButtons & (1 << (i + 4))) != 0;
+
+    //Send events
+    if (mBuffered && mListener)
+    {
+	    JoyStickEvent joystickEvent(this, mState);
+
+	    //Axes
+	    for (int i = 0; i < XINPUT_TRANSLATED_AXIS_COUNT; i++)
+        {
+		    if (axisMoved[i] && !mListener->axisMoved(joystickEvent, i))
+			    return;
+        }
+
+        //POV
+        if (previousPov != pov && !mListener->povMoved(joystickEvent, 0))
+            return;
+
+        //Buttons
+        for (int i = 0; i < XINPUT_TRANSLATED_BUTTON_COUNT; i++)
+        {
+            if (!previousButtons[i] && mState.mButtons[i])
+            {
+                if (!mListener->buttonPressed(joystickEvent, i))
+                    return;
+            }
+            else if (previousButtons[i] && !mState.mButtons[i])
+            {
+                if (!mListener->buttonReleased(joystickEvent, i))
+                    return;
+            }
+        }
+    }
+#endif
+}
+
+//--------------------------------------------------------------------------------------------------//
+bool Win32JoyStick::_doButtonClick( int button, DIDEVICEOBJECTDATA& di )
+{
+	if( di.dwData & 0x80 )
+	{
+		mState.mButtons[button] = true;
+		if( mBuffered && mListener )
+			return mListener->buttonPressed( JoyStickEvent( this, mState ), button );
+	}
+	else
+	{
+		mState.mButtons[button] = false;
+		if( mBuffered && mListener )
+			return mListener->buttonReleased( JoyStickEvent( this, mState ), button );
+	}
+
+	return true;
+}
+
+//--------------------------------------------------------------------------------------------------//
+bool Win32JoyStick::_changePOV( int pov, DIDEVICEOBJECTDATA& di )
+{
+	//Some drivers report a value of 65,535, instead of 1,
+	//for the center position
+	if(LOWORD(di.dwData) == 0xFFFF)
+	{
+		mState.mPOV[pov].direction = Pov::Centered;
+	}
+	else
+	{
+		switch(di.dwData)
+		{
+			case 0: mState.mPOV[pov].direction = Pov::North; break;
+			case 4500: mState.mPOV[pov].direction = Pov::NorthEast; break;
+			case 9000: mState.mPOV[pov].direction = Pov::East; break;
+			case 13500: mState.mPOV[pov].direction = Pov::SouthEast; break;
+			case 18000: mState.mPOV[pov].direction = Pov::South; break;
+			case 22500: mState.mPOV[pov].direction = Pov::SouthWest; break;
+			case 27000: mState.mPOV[pov].direction = Pov::West; break;
+			case 31500: mState.mPOV[pov].direction = Pov::NorthWest; break;
+		}
+	}
+
+	if( mBuffered && mListener )
+		return mListener->povMoved( JoyStickEvent( this, mState ), pov );
+
+	return true;
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32JoyStick::setBuffered(bool buffered)
+{
+	mBuffered = buffered;
+}
+
+//--------------------------------------------------------------------------------------------------//
+Interface* Win32JoyStick::queryInterface(Interface::IType type)
+{
+	if( mFfDevice && type == Interface::ForceFeedback )
+		return mFfDevice;
+	else
+		return 0;
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32JoyStick::CheckXInputDevices(JoyStickInfoList &joys)
+{
+    IWbemLocator*           pIWbemLocator  = NULL;
+    IEnumWbemClassObject*   pEnumDevices   = NULL;
+    IWbemClassObject*       pDevices[20]   = {0};
+    IWbemServices*          pIWbemServices = NULL;
+    BSTR                    bstrNamespace  = NULL;
+    BSTR                    bstrDeviceID   = NULL;
+    BSTR                    bstrClassName  = NULL;
+    DWORD                   uReturned      = 0;
+    bool                    bIsXinputDevice= false;
+	DWORD                   iDevice        = 0;
+	int                     xDevice        = 0;
+    VARIANT                 var;
+    HRESULT                 hr;
+
+	if(joys.size() == 0)
+		return;
+
+    // CoInit if needed
+    hr = CoInitialize(NULL);
+    bool bCleanupCOM = SUCCEEDED(hr);
+
+    // Create WMI
+    // (Orxonox): Fix for MinGW
+#ifdef __MINGW32__
+    hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pIWbemLocator);
+#else
+    hr = CoCreateInstance(__uuidof(WbemLocator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IWbemLocator), (LPVOID*)&pIWbemLocator);
+#endif
+    if( FAILED(hr) || pIWbemLocator == NULL )
+        goto LCleanup;
+
+    bstrNamespace = SysAllocString( L"\\\\.\\root\\cimv2" );
+	if( bstrNamespace == NULL )
+		goto LCleanup;
+
+    bstrClassName = SysAllocString( L"Win32_PNPEntity" );
+	if( bstrClassName == NULL )
+		goto LCleanup;
+
+    bstrDeviceID  = SysAllocString( L"DeviceID" );
+	if( bstrDeviceID == NULL )
+		goto LCleanup;
+    
+    // Connect to WMI 
+    hr = pIWbemLocator->ConnectServer( bstrNamespace, NULL, NULL, 0L, 0L, NULL, NULL, &pIWbemServices );
+    if( FAILED(hr) || pIWbemServices == NULL )
+        goto LCleanup;
+
+    // Switch security level to IMPERSONATE. 
+    CoSetProxyBlanket(pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );                    
+
+    hr = pIWbemServices->CreateInstanceEnum( bstrClassName, 0, NULL, &pEnumDevices ); 
+    if( FAILED(hr) || pEnumDevices == NULL )
+        goto LCleanup;
+
+    // Loop over all devices
+    for( ;; )
+    {
+        // Get 20 at a time
+        hr = pEnumDevices->Next(5000, 20, pDevices, &uReturned);
+        if( FAILED(hr) )
+            goto LCleanup;
+
+        if( uReturned == 0 )
+            break;
+
+        for(iDevice = 0; iDevice < uReturned; iDevice++)
+        {
+            // For each device, get its device ID
+            hr = pDevices[iDevice]->Get(bstrDeviceID, 0L, &var, NULL, NULL);
+            if(SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL)
+            {
+                // Check if the device ID contains "IG_".  If it does, then it's an XInput device - This information can not be found from DirectInput 
+                if(wcsstr(var.bstrVal, L"IG_"))
+                {
+                    // If it does, then get the VID/PID from var.bstrVal
+                    DWORD dwPid = 0, dwVid = 0;
+                    WCHAR* strVid = wcsstr( var.bstrVal, L"VID_" );
+                    if(strVid && swscanf_s( strVid, L"VID_%4X", &dwVid ) != 1)
+						dwVid = 0;
+
+                    WCHAR* strPid = wcsstr( var.bstrVal, L"PID_" );
+                    if(strPid && swscanf_s( strPid, L"PID_%4X", &dwPid ) != 1)
+                        dwPid = 0;
+
+                    // Compare the VID/PID to the DInput device
+                    DWORD dwVidPid = MAKELONG(dwVid, dwPid);
+					for(JoyStickInfoList::iterator i = joys.begin(); i != joys.end(); ++i)
+					{
+						if(dwVidPid == i->productGuid.Data1)
+						{
+							i->isXInput = true;
+							i->xInputDev = xDevice;
+						}
+					}
+
+					if(joys.size() == 0)
+						goto LCleanup;
+                }
+            }
+
+            SAFE_RELEASE(pDevices[iDevice]);
+        }
+    }
+
+LCleanup:
+    if(bstrNamespace)
+        SysFreeString(bstrNamespace);
+
+    if(bstrDeviceID)
+        SysFreeString(bstrDeviceID);
+
+    if(bstrClassName)
+        SysFreeString(bstrClassName);
+
+    for(iDevice=0; iDevice < 20; iDevice++)
+        SAFE_RELEASE(pDevices[iDevice]);
+
+    SAFE_RELEASE(pEnumDevices);
+    SAFE_RELEASE(pIWbemLocator);
+    SAFE_RELEASE(pIWbemServices);
+
+    if(bCleanupCOM)
+        CoUninitialize();
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32JoyStick.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32JoyStick.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32JoyStick.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _WIN32_JOYSTICK_H_EADER_
+#define _WIN32_JOYSTICK_H_EADER_
+
+#include "OISJoyStick.h"
+#include "win32/Win32Prereqs.h"
+
+namespace OIS
+{
+	class Win32JoyStick : public JoyStick
+	{
+	public:
+		Win32JoyStick( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings, const JoyStickInfo &info );
+		virtual ~Win32JoyStick();
+		
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+		
+		/** @copydoc Object::capture */
+		virtual void capture();
+
+		//! hanlde xinput
+		void captureXInput();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType type);
+
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+
+		/**
+		@remarks
+			Enum each PNP device using WMI and check each device ID to see if it contains 
+			"IG_" (ex. "VID_045E&PID_028E&IG_00").  If it does, then it's an XInput device
+			Unfortunately this information can not be found by just using DirectInput 
+		*/
+		static void CheckXInputDevices(JoyStickInfoList &joys);
+
+	protected:
+		//! Enumerates all things
+		void _enumerate();
+		//! Enumerate axis callback
+		static BOOL CALLBACK DIEnumDeviceObjectsCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef);
+		//! Enumerate Force Feedback callback
+		static BOOL CALLBACK DIEnumEffectsCallback(LPCDIEFFECTINFO pdei, LPVOID pvRef);
+
+		bool _doButtonClick( int button, DIDEVICEOBJECTDATA& di );
+		bool _changePOV( int pov, DIDEVICEOBJECTDATA& di );
+
+		IDirectInput8* mDirectInput;
+		IDirectInputDevice8* mJoyStick;
+		DIDEVCAPS mDIJoyCaps;
+		DWORD coopSetting;
+
+        JoyStickInfo mJoyInfo;
+
+		//! A force feedback device
+		Win32ForceFeedback* mFfDevice;
+
+		//! Mapping
+		int _AxisNumber;
+	};
+}
+
+#endif //_WIN32_JOYSTICK_H_EADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32KeyBoard.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32KeyBoard.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32KeyBoard.cpp	(revision 11817)
@@ -0,0 +1,333 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "win32/Win32InputManager.h"
+#include "win32/Win32KeyBoard.h"
+#include "OISException.h"
+#include "OISEvents.h"
+#include <sstream>
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------------------------//
+Win32Keyboard::Win32Keyboard( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings )
+	: Keyboard(creator->inputSystemName(), buffered, 0, creator)
+{
+	mKeyboard = 0;
+	mDirectInput = pDI;
+	coopSetting = coopSettings;
+
+	//Clear our keyboard state buffer
+	memset( &KeyBuffer, 0, 256 );
+	deadKey = '\0';
+	static_cast<Win32InputManager*>(mCreator)->_setKeyboardUsed(true);
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Keyboard::_initialize()
+{
+	mModifiers = 0;
+	deadKey = '\0';
+
+	if(FAILED(mDirectInput->CreateDevice(GUID_SysKeyboard, &mKeyboard, NULL)))
+		OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> Could not init device!");
+
+	if(FAILED(mKeyboard->SetDataFormat(&c_dfDIKeyboard)))
+		OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> format error!");
+
+	HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
+
+	if(FAILED(mKeyboard->SetCooperativeLevel( hwin, coopSetting)))
+		OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> coop error!");
+
+	if( mBuffered )
+	{
+		DIPROPDWORD dipdw;
+		dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
+		dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+		dipdw.diph.dwObj        = 0;
+		dipdw.diph.dwHow        = DIPH_DEVICE;
+		dipdw.dwData            = KEYBOARD_DX_BUFFERSIZE;
+
+		if (FAILED(mKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph )))
+			OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> buffer error!");
+	}
+
+	HRESULT hr = mKeyboard->Acquire();
+	if(FAILED(hr) && hr != DIERR_OTHERAPPHASPRIO)
+		OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> aquire error!");
+}
+
+//--------------------------------------------------------------------------------------------------//
+Win32Keyboard::~Win32Keyboard()
+{
+	if(mKeyboard)
+	{
+		mKeyboard->Unacquire();
+		mKeyboard->Release();
+		mKeyboard = 0;
+	}
+	static_cast<Win32InputManager*>(mCreator)->_setKeyboardUsed(false);
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Keyboard::capture()
+{
+	if( mBuffered )
+		_readBuffered();
+	else
+		_read();
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Keyboard::_readBuffered()
+{
+	DIDEVICEOBJECTDATA diBuff[KEYBOARD_DX_BUFFERSIZE];
+	DWORD entries = KEYBOARD_DX_BUFFERSIZE;
+	HRESULT hr;
+	//Only one keyboard allowed per app, so static is ok
+	static bool verifyAfterAltTab = false;
+
+	hr = mKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
+	if( hr != DI_OK )
+	{
+		hr = mKeyboard->Acquire();
+		if (hr == E_ACCESSDENIED)
+			verifyAfterAltTab = true;
+
+		while( hr == DIERR_INPUTLOST )
+			hr = mKeyboard->Acquire();
+
+		return;
+	}
+
+	if( FAILED(hr) )
+		OIS_EXCEPT( E_General, "Win32Keyboard::_readBuffered() >> Problem with Device!" );
+
+	//Update keyboard and modifier states.. And, if mListener, fire events
+	for(unsigned int i = 0; i < entries; ++i )
+	{
+		//If the listener returns false, that means that we are probably deleted...
+		//send no more events and just leave as the this pointer is invalid now...
+		bool ret = true;
+		KeyCode kc = (KeyCode)diBuff[ i ].dwOfs;
+			
+		//Store result in our keyBuffer too
+		KeyBuffer[kc] = static_cast<unsigned char>(diBuff[ i ].dwData);
+			
+		if( diBuff[ i ].dwData & 0x80 )
+		{
+			//Turn on modifier
+			if( kc == KC_LCONTROL || kc == KC_RCONTROL )
+				mModifiers |= Ctrl;
+			else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
+				mModifiers |= Shift;
+			else if( kc == KC_LMENU || kc == KC_RMENU )
+				mModifiers |= Alt;
+
+			if( mListener )
+				ret = mListener->keyPressed( KeyEvent( this, kc, _translateText(kc) ) );
+		}
+		else
+		{
+			//Turn off modifier
+			if( kc == KC_LCONTROL || kc == KC_RCONTROL )
+				mModifiers &= ~Ctrl;
+			else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
+				mModifiers &= ~Shift;
+			else if( kc == KC_LMENU || kc == KC_RMENU )
+				mModifiers &= ~Alt;
+
+			//Fire off event
+			if( mListener )
+				ret = mListener->keyReleased( KeyEvent( this, kc, 0 ) );
+		}
+
+		if(ret == false)
+			break;
+	}
+
+	// If a lost device/access denied was detected, recover gracefully with new events
+	if(verifyAfterAltTab)
+	{
+		bool ret = true;
+		
+		//Copy old buffer to temp location to compare against
+		unsigned char keyBufferCopy[256];
+		memcpy(keyBufferCopy, KeyBuffer, 256);
+
+		//Update new state
+		_read();
+
+		for (unsigned i = 0; i < 256; i++)
+		{
+			if (keyBufferCopy[i] != KeyBuffer[i])
+			{
+				if (mListener)
+				{
+					if (KeyBuffer[i])
+						ret = mListener->keyPressed( KeyEvent( this, (KeyCode)i, _translateText((KeyCode)i) ) );
+					else
+						ret = mListener->keyReleased( KeyEvent( this, (KeyCode)i, 0 ) );
+				}
+			}
+
+			//If user returned false from callback, return immediately
+			if(ret == false)
+				return;
+		}
+
+		verifyAfterAltTab = false;
+	}
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Keyboard::_read()
+{
+    HRESULT  hr = mKeyboard->GetDeviceState( sizeof(KeyBuffer), &KeyBuffer );
+
+	if( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED )
+	{
+		hr = mKeyboard->Acquire();
+		if (hr != DIERR_OTHERAPPHASPRIO)
+			mKeyboard->GetDeviceState(sizeof(KeyBuffer), &KeyBuffer);
+	}
+
+	//Set Shift, Ctrl, Alt
+	mModifiers = 0;
+	if( isKeyDown(KC_LCONTROL) || isKeyDown(KC_RCONTROL) )
+		mModifiers |= Ctrl;
+	if( isKeyDown(KC_LSHIFT) || isKeyDown(KC_RSHIFT) )
+		mModifiers |= Shift;
+	if( isKeyDown(KC_LMENU) || isKeyDown(KC_RMENU) )
+		mModifiers |= Alt;
+}
+
+//--------------------------------------------------------------------------------------------------//
+int Win32Keyboard::_translateText( KeyCode kc )
+{
+	if( mTextMode == Off )
+		return 0;
+
+	BYTE keyState[256];
+	HKL  layout = GetKeyboardLayout(0);
+	if( GetKeyboardState(keyState) == 0 )
+		return 0;
+
+	unsigned int vk = MapVirtualKeyEx(kc, 3, layout);
+	if( vk == 0 )
+		return 0;
+
+	WCHAR buff[3] = {0};
+	int ascii = ToUnicodeEx(vk, kc, keyState, buff, 3, 0, layout);
+
+	if(ascii == 1 && deadKey != '\0' )
+	{
+		// A dead key is stored and we have just converted a character key
+		// Combine the two into a single character
+		WCHAR wcBuff[3] = {buff[0], deadKey, '\0'};
+		WCHAR out[3];
+		
+		deadKey = '\0';
+		if(FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
+			return out[0];
+	}
+	else if (ascii == 1)
+	{	// We have a single character
+		deadKey = '\0';
+		return buff[0];
+	}
+	else if(ascii == 2)
+	{	// Convert a non-combining diacritical mark into a combining diacritical mark
+		// Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
+		// http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
+		switch(buff[0])	{
+		case 0x5E: // Circumflex accent: â
+			deadKey = 0x302; break;
+		case 0x60: // Grave accent: à
+			deadKey = 0x300; break;
+		case 0xA8: // Diaeresis: ü
+			deadKey = 0x308; break;
+		case 0xB4: // Acute accent: é
+			deadKey = 0x301; break;
+		case 0xB8: // Cedilla: ç
+			deadKey = 0x327; break;
+		default:
+			deadKey = buff[0]; break;
+		}
+	}
+
+	return 0;
+}
+
+//--------------------------------------------------------------------------------------------------//
+bool Win32Keyboard::isKeyDown( KeyCode key ) const
+{
+	return (KeyBuffer[key] & 0x80) != 0;
+}
+
+//--------------------------------------------------------------------------------------------------//
+const std::string& Win32Keyboard::getAsString(KeyCode kc)
+{
+	char temp[256];
+
+	DIPROPSTRING prop;
+	prop.diph.dwSize = sizeof(DIPROPSTRING);
+	prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+	prop.diph.dwObj = static_cast<DWORD>(kc);
+	prop.diph.dwHow = DIPH_BYOFFSET;
+
+	if (SUCCEEDED(mKeyboard->GetProperty(DIPROP_KEYNAME, &prop.diph)))
+	{
+		// convert the WCHAR in "wsz" to multibyte
+		if (WideCharToMultiByte(CP_ACP, 0, prop.wsz, -1, temp, sizeof(temp), NULL, NULL))
+			return mGetString.assign(temp);
+	}
+
+	std::stringstream ss;
+	ss << "Key_" << (int)kc;
+	return mGetString.assign(ss.str());
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Keyboard::copyKeyStates( char keys[256] ) const
+{
+	for(int i = 0; i < 256; ++i)
+		keys[i] = KeyBuffer[i] > 0; //Normalise the DX values (0x80)
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Keyboard::setBuffered(bool buffered)
+{
+	if( buffered != mBuffered )
+	{
+		if(mKeyboard)
+		{
+			mKeyboard->Unacquire();
+			mKeyboard->Release();
+			mKeyboard = 0;
+		}
+		
+		mBuffered = buffered;
+		_initialize();
+	}
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32KeyBoard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32KeyBoard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32KeyBoard.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _WIN32_KEYBOARD_H_EADER_
+#define _WIN32_KEYBOARD_H_EADER_
+
+#include "OISKeyboard.h"
+#include "win32/Win32Prereqs.h"
+
+namespace OIS
+{
+	class Win32Keyboard : public Keyboard
+	{
+	public:
+		/**
+		@remarks
+			Constructor
+		@param pDI
+			Valid DirectInput8 Interface
+		@param buffered
+			True for buffered input mode
+		@param coopSettings
+			A combination of DI Flags (see DX Help for info on input device settings)
+		*/
+		Win32Keyboard(InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings);
+		virtual ~Win32Keyboard();
+
+		/** @copydoc Keyboard::isKeyDown */
+		virtual bool isKeyDown(KeyCode key) const;
+		
+		/** @copydoc Keyboard::getAsString */
+		virtual const std::string& getAsString(KeyCode kc);
+
+		/** @copydoc Keyboard::copyKeyStates */
+		virtual void copyKeyStates(char keys[256]) const;
+
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+		
+		/** @copydoc Object::capture */
+		virtual void capture();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType type) {return 0;}
+		
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+	protected:
+		void _readBuffered();
+		void _read();
+
+		IDirectInput8* mDirectInput;
+		IDirectInputDevice8* mKeyboard;
+		DWORD coopSetting;
+
+		unsigned char KeyBuffer[256];
+		
+		//! Internal method for translating KeyCodes to Text
+		int _translateText( KeyCode kc );
+
+		//! Stored dead key from last translation
+		WCHAR deadKey;
+
+		//! used for getAsString
+		std::string mGetString;
+	};
+}
+#endif //_WIN32_KEYBOARD_H_EADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Mouse.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Mouse.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Mouse.cpp	(revision 11817)
@@ -0,0 +1,217 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#include "win32/Win32Mouse.h"
+#include "win32/Win32InputManager.h"
+#include "OISException.h"
+#include "OISEvents.h"
+#include <cstddef>
+
+using namespace OIS;
+
+//--------------------------------------------------------------------------------------------------//
+Win32Mouse::Win32Mouse( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings )
+	: Mouse(creator->inputSystemName(), buffered, 0, creator)
+{
+	mMouse = 0;
+	mDirectInput = pDI;
+	coopSetting = coopSettings;
+	mHwnd = 0;
+
+	static_cast<Win32InputManager*>(mCreator)->_setMouseUsed(true);
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Mouse::_initialize()
+{
+	DIPROPDWORD dipdw;
+
+	//Clear old state
+	mState.clear();
+
+    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
+    dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+    dipdw.diph.dwObj        = 0;
+    dipdw.diph.dwHow        = DIPH_DEVICE;
+	dipdw.dwData            = MOUSE_DX_BUFFERSIZE;
+	
+	if( FAILED(mDirectInput->CreateDevice(GUID_SysMouse, &mMouse, NULL)) )
+		OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to create device" );
+
+	if( FAILED(mMouse->SetDataFormat(&c_dfDIMouse2)) )
+		OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set format" );
+	
+	mHwnd = ((Win32InputManager*)mCreator)->getWindowHandle();
+
+	if( FAILED(mMouse->SetCooperativeLevel(mHwnd, coopSetting)) )
+		OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set coop level" );
+	
+	if( FAILED(mMouse->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph )) )
+		OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to set property" );
+
+	HRESULT hr = mMouse->Acquire();
+	if (FAILED(hr) && hr != DIERR_OTHERAPPHASPRIO)
+		OIS_EXCEPT( E_General, "Win32Mouse::Win32Mouse >> Failed to aquire mouse!" );
+}
+
+//--------------------------------------------------------------------------------------------------//
+Win32Mouse::~Win32Mouse()
+{
+	if (mMouse)
+	{
+		mMouse->Unacquire();
+		mMouse->Release();
+		mMouse = 0;
+	}
+
+	static_cast<Win32InputManager*>(mCreator)->_setMouseUsed(false);
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Mouse::capture()
+{
+	//Clear old relative values
+	mState.X.rel = mState.Y.rel = mState.Z.rel = 0;
+
+	DIDEVICEOBJECTDATA diBuff[MOUSE_DX_BUFFERSIZE];
+	DWORD entries = MOUSE_DX_BUFFERSIZE;
+
+	HRESULT hr = mMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
+	if( hr != DI_OK )
+	{
+		hr = mMouse->Acquire();
+		while( hr == DIERR_INPUTLOST ) 
+			hr = mMouse->Acquire();
+
+		hr = mMouse->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
+		
+		//Perhaps the user just tabbed away, and coop settings
+		//are nonexclusive..so just ignore
+		if( FAILED(hr) )
+			return;
+	}
+
+	bool axesMoved = false;
+	//Accumulate all axis movements for one axesMove message..
+	//Buttons are fired off as they are found
+	for(unsigned int i = 0; i < entries; ++i )
+	{
+		switch( diBuff[i].dwOfs )
+		{
+			case DIMOFS_BUTTON0:
+				if(!_doMouseClick(0, diBuff[i])) return;
+				break;
+			case DIMOFS_BUTTON1:
+				if(!_doMouseClick(1, diBuff[i])) return;
+				break;
+			case DIMOFS_BUTTON2:
+				if(!_doMouseClick(2, diBuff[i])) return;
+				break;
+			case DIMOFS_BUTTON3:
+				if(!_doMouseClick(3, diBuff[i])) return;
+				break;
+			case DIMOFS_BUTTON4:
+				if(!_doMouseClick(4, diBuff[i])) return;
+				break;	
+			case DIMOFS_BUTTON5:
+				if(!_doMouseClick(5, diBuff[i])) return;
+				break;
+			case DIMOFS_BUTTON6:
+				if(!_doMouseClick(6, diBuff[i])) return;
+				break;
+			case DIMOFS_BUTTON7:
+				if(!_doMouseClick(7, diBuff[i])) return;
+				break;
+			case DIMOFS_X:
+				mState.X.rel += diBuff[i].dwData;
+				axesMoved = true;
+				break;
+			case DIMOFS_Y:
+				mState.Y.rel += diBuff[i].dwData;
+				axesMoved = true;
+				break;
+			case DIMOFS_Z:
+				mState.Z.rel += diBuff[i].dwData;
+				axesMoved = true;
+				break;
+			default: break;
+		} //end switch
+	}//end for
+
+	if( axesMoved )
+	{
+		if( coopSetting & DISCL_NONEXCLUSIVE )
+		{
+			//DirectInput provides us with meaningless values, so correct that
+			POINT point;
+			GetCursorPos(&point);
+			ScreenToClient(mHwnd, &point);
+			mState.X.abs = point.x;
+			mState.Y.abs = point.y;
+		}
+		else
+		{
+			mState.X.abs +=  mState.X.rel;
+			mState.Y.abs +=  mState.Y.rel;
+		}
+		mState.Z.abs +=  mState.Z.rel;
+
+		//Clip values to window
+		if( mState.X.abs < 0 )
+			mState.X.abs = 0;
+		else if( mState.X.abs > mState.width )
+			mState.X.abs = mState.width;
+		if( mState.Y.abs < 0 )
+			mState.Y.abs = 0;
+		else if( mState.Y.abs > mState.height )
+			mState.Y.abs = mState.height;
+
+		//Do the move
+		if( mListener && mBuffered )
+			mListener->mouseMoved( MouseEvent( this, mState ) );
+	}
+}
+
+//--------------------------------------------------------------------------------------------------//
+bool Win32Mouse::_doMouseClick( int mouseButton, DIDEVICEOBJECTDATA& di )
+{
+	if( di.dwData & 0x80 )
+	{
+		mState.buttons |= 1 << mouseButton; //turn the bit flag on
+		if( mListener && mBuffered )
+			return mListener->mousePressed( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
+	}
+	else
+	{
+		mState.buttons &= ~(1 << mouseButton); //turn the bit flag off
+		if( mListener && mBuffered )
+			return mListener->mouseReleased( MouseEvent( this, mState ), (MouseButtonID)mouseButton );
+	}
+
+	return true;
+}
+
+//--------------------------------------------------------------------------------------------------//
+void Win32Mouse::setBuffered(bool buffered)
+{
+	mBuffered = buffered;
+}
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Mouse.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Mouse.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Mouse.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+	1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+	2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+	3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _WIN32_MOUSE_H_EADER_
+#define _WIN32_MOUSE_H_EADER_
+
+#include "OISMouse.h"
+#include "win32/Win32Prereqs.h"
+
+namespace OIS
+{
+	class Win32Mouse : public Mouse
+	{
+	public:
+		Win32Mouse( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings );
+		virtual ~Win32Mouse();
+		
+		/** @copydoc Object::setBuffered */
+		virtual void setBuffered(bool buffered);
+
+		/** @copydoc Object::capture */
+		virtual void capture();
+
+		/** @copydoc Object::queryInterface */
+		virtual Interface* queryInterface(Interface::IType type) {return 0;}
+
+		/** @copydoc Object::_initialize */
+		virtual void _initialize();
+
+	protected:
+		bool _doMouseClick( int mouseButton, DIDEVICEOBJECTDATA& di );
+
+		IDirectInput8* mDirectInput;
+		IDirectInputDevice8* mMouse;
+		DWORD coopSetting;
+		HWND mHwnd;
+	};
+}
+
+#endif //_WIN32_MOUSE_H_EADER_
Index: /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Prereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Prereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/ois/win32/Win32Prereqs.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+The zlib/libpng License
+
+Copyright (c) 2005-2007 Phillip Castaneda (pjcast -- www.wreckedgames.com)
+
+This software is provided 'as-is', without any express or implied warranty. In no event will
+the authors be held liable for any damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose, including commercial 
+applications, and to alter it and redistribute it freely, subject to the following
+restrictions:
+
+    1. The origin of this software must not be misrepresented; you must not claim that 
+		you wrote the original software. If you use this software in a product, 
+		an acknowledgment in the product documentation would be appreciated but is 
+		not required.
+
+    2. Altered source versions must be plainly marked as such, and must not be 
+		misrepresented as being the original software.
+
+    3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _WIN32_INPUTSYSTEM_PREREQS_H
+#define _WIN32_INPUTSYSTEM_PREREQS_H
+
+#define WIN32_LEAN_AND_MEAN
+#define DIRECTINPUT_VERSION 0x0800
+#include <windows.h>
+#include <dinput.h>
+
+#ifdef OIS_WIN32_XINPUT_SUPPORT
+#	include <XInput.h>
+#endif
+
+//Max number of elements to collect from buffered DirectInput
+#define KEYBOARD_DX_BUFFERSIZE 17
+#define MOUSE_DX_BUFFERSIZE 128
+#define JOYSTICK_DX_BUFFERSIZE 129
+
+//MinGW defines
+#if defined(OIS_MINGW_COMPILER)
+#	undef FIELD_OFFSET
+#	define FIELD_OFFSET offsetof
+#endif
+
+namespace OIS
+{
+	//Local Forward declarations
+	class Win32InputManager;
+	class Win32Keyboard;
+	class Win32JoyStick;
+	class Win32Mouse;
+	class Win32ForceFeedback;
+
+	//Information needed to create DirectInput joysticks
+	class JoyStickInfo
+	{
+	public:
+		int devId;
+		GUID deviceID;
+		GUID productGuid;
+		std::string vendor;
+        bool isXInput;
+		int xInputDev;
+	};
+
+	typedef std::vector<JoyStickInfo> JoyStickInfoList;
+}
+
+#endif //_WIN32_INPUTSYSTEM_PREREQS_H
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,38 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(TINYXML_FILES
+  ticpp.h
+  ticpprc.h
+  tinystr.h
+  tinyxml.h
+
+  ticpp.cpp
+  tinystr.cpp
+  tinyxml.cpp
+  tinyxmlerror.cpp
+  tinyxmlparser.cpp
+)
+
+ORXONOX_ADD_LIBRARY(tinyxml_orxonox
+  ORXONOX_EXTERNAL
+  NO_DLL_INTERFACE
+  SOURCE_FILES
+    ${TINYXML_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/VERSION
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/VERSION	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/VERSION	(revision 11817)
@@ -0,0 +1,2 @@
+TinyXML++ trunk checkout revision 122 (version 0.04a).
+Built with TinyXML 2.5.3.
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/changes.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/changes.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/changes.txt	(revision 11817)
@@ -0,0 +1,269 @@
+Changes in version 1.0.1:
+- Fixed comment tags which were outputing as '<?--' instead of 
+  the correct '<!--'.
+- Implemented the Next and Prev methods of the TiXmlAttribute class.
+- Renamed 'LastAttribtute' to 'LastAttribute'
+- Fixed bad pointer to 'isspace' that could occur while parsing text.
+- Errors finding beginning and end of tags no longer throw it into an
+  infinite loop. (Hopefully.)
+
+Changes in version 1.0.2
+- Minor documentation fixes.
+
+Changes in version 1.0.3
+- After nodes are added to a document, they return a pointer
+  to the new node instead of a bool for success.
+- Elements can be constructed with a value, which is the
+  element name. Every element must have a value or it will be
+  invalid, but the code changes to enforce this are not fully
+  in place.
+
+Changes in version 1.1.0
+- Added the	TiXmlAttributeSet class to pull the attributes into
+  a seperate container.
+- Moved the doubly liked list out of XmlBase. Now XmlBase only
+  requires the Print() function and defines some utility functions.
+- Moved errors into a seperate file. (With the idea of internationalization
+  to the other latin-1 languages.)
+- Added the "NodeType"
+- Fixed white space parsing in text to conform with the standard. 
+  Basically, all white space becomes just one space.
+- Added the TiXmlDeclaration class to read xml declarations.
+
+Changes in version 1.2.0
+- Removed the factory. The factory was not really in the spirit 
+  of small and simple, confused the code, and was of limited value.
+- Added FirstChildElement and NextSiblingElement, because they
+  are such common functions.
+- Re-wrote the example to test and demonstrate more functionality.
+
+Changes in version 1.2.1
+- Fixed a bug where comments couldn't be inside elements.
+- Loading now clears out existing XML rather than appending.
+- Added the "Clear" method on a node to delete all its children.
+
+Changes in version 1.2.2
+- Fixed TiXmlAttribute::Previous actually returning "next." Thanks
+  to Rickard Troedsson for the bug fix.
+
+Changes in version 1.2.3
+- Added the TIXML prefix to the error strings to resolve conflicts
+  with #defines in OS headers. Thanks to Steve Lhomme.
+- Fixed a delete buf that should be a delete [] buf. 
+  Thanks to Ephi Sinowitz.
+
+Changes in version 1.2.4
+- ReplaceChild() was almost guarenteed to fail. Should be fixed,
+  thanks to Joe Smith. Joe also pointed out that the Print() functions
+  should take stream references: I agree, and would like to overload
+  the Print() method to take either format, but I don't want to do 
+  this in a dot release.
+- Some compilers seem to need an extra <ctype.h> include. Thanks
+  to Steve Lhomme for that.
+
+Changes in version 2.0.0 BETA
+- Made the ToXXX() casts safe if 'this' is null. 
+  When "LoadFile" is called with a filename, the value will correctly get set.
+  Thanks to Brian Yoder.
+- Fixed bug where isalpha() and isalnum() would get called with a negative value for 
+  high ascii numbers. Thanks to Alesky Aksenov.
+- Fixed some errors codes that were not getting set.
+- Made methods "const" that were not.
+- Added a switch to enable or disable the ignoring of white space. ( TiXmlDocument::SetIgnoreWhiteSpace() )
+- Greater standardization and code re-use in the parser.
+- Added a stream out operator.
+- Added a stream in operator.
+- Entity support, of predefined entites. &#x entities are untouched by input or output.
+- Improved text out formatting.
+- Fixed ReplaceChild bug, thanks to Tao Chen.
+
+Changes in version 2.0.1
+- Fixed hanging on loading a 0 length file. Thanks to Jeff Scozzafava.
+- Fixed crashing on InsertBeforeChild and InsertAfterChild. Also possibility of bad links being
+  created by same function. Thanks to Frank De prins.
+- Added missing licence text. Thanks to Lars Willemsens.
+- Added <ctype.h> include, at the suggestion of Steve Walters.
+
+Changes in version 2.1.0
+- Yves Berquin brings us the STL switch. The forum on SourceForge, and various emails to
+  me, have long debated all out STL vs. no STL at all. And now you can have it both ways.
+  TinyXml will compile either way.
+
+Changes in version 2.1.1
+- Compilation warnings.
+
+Changes in version 2.1.2
+- Uneeded code is not compiled in the STL case.
+- Changed headers so that STL can be turned on or off in tinyxml.h
+
+Changes in version 2.1.3
+- Fixed non-const reference in API; now uses a pointer.
+- Copy constructor of TiXmlString not checking for assignment to self.
+- Nimrod Cohen found a truly evil bug in the STL implementation that occurs
+  when a string is converted to a c_str and then assigned to self. Search for
+  STL_STRING_BUG for a full description. I'm asserting this is a Microsoft STL
+  bug, since &string and string.c_str() should never be the same. Nevertheless,
+  the code works around it.
+- Urivan Saaib pointed out a compiler conflict, where the C headers define
+  the isblank macro, which was wiping out the TiXmlString::isblank() method.
+  The method was unused and has been removed.
+
+Changes in version 2.1.4
+- Reworked the entity code. Entities were not correctly surving round trip input and output.
+  Will now automatically create entities for high ascii in output.
+
+Changes in version 2.1.5
+- Bug fix by kylotan : infinite loop on some input (tinyxmlparser.cpp rev 1.27)
+- Contributed by Ivica Aracic (bytelord) : 1 new VC++ project to compile versions as static libraries (tinyxml_lib.dsp), 
+  and an example usage in xmltest.dsp
+  (Patch request ID 678605)
+- A suggestion by Ronald Fenner Jr (dormlock) to add #include <istream> and <ostream> for Apple's Project Builder 
+  (Patch request ID 697642)
+- A patch from ohommes that allows to parse correctly dots in element names and attribute names
+  (Patch request 602600 and kylotan 701728)
+- A patch from  hermitgeek ( James ) and wasteland for improper error reporting
+- Reviewed by Lee, with the following changes:
+	- Got sick of fighting the STL/non-STL thing in the windows build. Broke
+	  them out as seperate projects.
+	- I have too long not included the dsw. Added.
+	- TinyXmlText had a protected Print. Odd.
+	- Made LinkEndChild public, with docs and appropriate warnings.
+	- Updated the docs.
+
+2.2.0
+- Fixed an uninitialized pointer in the TiXmlAttributes
+- Fixed STL compilation problem in MinGW (and gcc 3?) - thanks Brian Yoder for finding this one
+- Fixed a syntax error in TiXmlDeclaration - thanks Brian Yoder
+- Fletcher Dunn proposed and submitted new error handling that tracked the row and column. Lee
+  modified it to not have performance impact.
+- General cleanup suggestions from Fletcher Dunn.
+- In error handling, general errors will no longer clear the error state of specific ones.
+- Fix error in documentation : comments starting with "<?--" instead of "<!--" (thanks ion_pulse)
+- Added the TiXmlHandle. An easy, safe way to browse XML DOMs with less code.
+- Added QueryAttribute calls which have better error messaging. (Proposed by Fletcher Dunn)
+- Nodes and attributes can now print themselves to strings. (Yves suggestion)
+- Fixed bug where entities with one character would confuse parser. (Thanks Roman)
+
+2.2.1
+- Additional testing (no more bugs found to be fixed in this release)
+- Significant performance improvement to the cursor code.
+
+2.3.0
+- User Data are now defined in TiXmlBase instead of TiXmlNode
+- Character Entities are now UCS-2
+- Character Entities can be decimal or hexadecimal
+- UTF-8 conversion.
+- Fixed many, many bugs.
+
+2.3.1
+- Fixed bug in handling nulls embedded in the input.
+- Make UTF-8 parser tolerant of bad text encoding.
+- Added encoding detection. 
+- Many fixes and input from John-Philip Leonard Johansson (JP) and Ellers, 
+  including UTF-8 feedback, bug reports, and patches. Thanks!
+- Added version # constants - a suggestion from JP and Ellers.
+- [ 979180 ] Missing ; in entity reference, fix from Rob Laveaux.
+- Copy constructors and assignment have been a long time coming. Thanks to
+  Fokke and JP.
+
+2.3.2
+- Made the IsAlpha and IsAlphaNum much more tolerant of non-UTF-8 encodings. Thanks
+  Volker Boerchers for finding the issue.
+- Ran the program though the magnificent Valgrind - http://valgrind.kde.org - to check
+  for memory errors. Fixed some minor issues.
+
+2.3.3
+- Fixed crash when test program was run from incorrect directory.
+- Fixed bug 1070717 - empty document not returned correctly - thanks Katsuhisa Yuasa.
+- Bug 1079301 resolved - deprecated stdlib calls. Thanks Adrian Boeing.
+- Bug 1035218 fixed - documentation errors. Xunji Luo
+- Other bug fixes have accumulated and been fixed on the way as well; my apologies to
+  authors not credited!
+- Big fix / addition is to correctly return const values. TinyXml could basically
+  remove const in a method like this: TiXmlElement* Foo() const, where the returned element
+  was a pointer to internal data. That is now: const TiXmlElement* Foo() const and
+  TiXmlElement* Foo().
+
+2.3.4
+- Fixed additional const errors, thanks Kent Gibson.
+- Correctly re-enable warnings after tinyxml header. Thanks Cory Nelson.
+- Variety of type cleanup and warning fixes. Thanks Warren Stevens.
+- Cleaned up unneeded constructor calls in TinyString - thanks to Geoff Carlton and
+  the discussion group on sourceforge.
+
+2.4.0
+- Improved string class, thanks Tyge Lovset (whose name gets mangled in English - sorry)
+- Type cast compiler warning, thanks Rob van den Bogaard
+- Added GetText() convenience function. Thanks Ilya Parniuk & Andrew Ellers for input.
+- Many thanks to marlonism for finding an infinite loop in bad xml.
+- A patch to cleanup warnings from Robert Gebis.
+- Added ValueStr() to get the value of a node as a string.
+- TiXmlText can now parse and output as CDATA
+- Additional string improvement from James (z2895)
+- Removed extraneous 'const', thanks David Aldrich
+- First pass at switching to the "safe" stdlib functions. Many people have suggested and
+  pushed on this, but Warren Stevens put together the first proposal.
+- TinyXml now will do EOL normalization before parsing, consistent with the W3C XML spec.
+- Documents loaded with the UTF-8 BOM will now save with the UTF-8 BOM. Good suggestion 
+  from 'instructor_'
+- Ellers submitted his very popular tutorials, which have been added to the distribution.
+
+2.4.1
+- Fixed CDATA output formatting
+- Fixed memory allocators in TinyString to work with overloaded new/delete
+
+2.4.2
+- solosnake pointed out that TIXML_LOG causes problems on an XBOX. The definition in the header
+  was superflous and was moved inside of DEBUG_PARSING
+
+2.4.3
+- Fixed a test bug that caused a crash in 'xmltest'. TinyXML was fine, but it isn't good
+  to ship with a broken test suite.
+- Started converting some functions to not cast between std::string and const char* 
+  quite as often.
+- Added FILE* versions of the document loads - good suggestion from Wade Brainerd
+- Empty documents might not always return the errors they should. [1398915] Thanks to igor v.
+- Added some asserts for multiply adding a node, regardng bug [1391937] suggested by Paco Arjonilla.
+
+2.4.4
+- Bug find thanks to andre-gross found a memory leak that occured when a document failed to load.
+- Bug find (and good analysis) by VirtualJim who found a case where attribute parsing 
+  should be throwing an error and wasn't.
+- Steve Hyatt suggested the QueryValueAttribute method, which is now implemented.
+- DavidA identified a chunk of dead code.
+- Andrew Baxter sent in some compiler warnings that were good clean up points.
+
+2.5
+- Added the Visit() API. Many thanks to both Andrew Ellerton and John-Philip for all their
+  work, code, suggestion, and just general pushing that it should be done.
+- Removed existing streaming code and use TiXmlPrinter instead.
+- [ tinyxml-Bugs-1527079 ] Compile error in tinystr.cpp fixed, thanks to Paul Suggs
+- [ tinyxml-Bugs-1522890 ] SaveFile has no error checks fixed, thanks to Ivan Dobrokotov
+- Ivan Dobrokotov also reported redundant memory allocation in the Attribute() method, which
+  upon investigation was a mess. The attribute should now be fixed for both const char* and 
+  std::string, and the return types match the input parameters.
+- Feature [ 1511105 ] Make TiXmlComment constructor accept a string / char*, implemented.
+  Thanks to Karl Itschen for the feedback.
+- [ 1480108 ] Stream parsing fails when CDATA contains tags was found by Tobias Grimm, who also
+  submitted a test case and patch. A significant bug in CDATA streaming (operator>>) has now
+  been fixed.
+
+2.5.2
+- Lieven, and others, pointed out a missing const-cast that upset the Open Watcom compiler.
+  Should now be fixed.
+- ErrorRow and ErrorCol should have been const, and weren't. Fixed thanks to Dmitry Polutov.
+
+2.5.3
+- zloe_zlo identified a missing string specialization for QueryValueAttribute() [ 1695429 ]. Worked
+  on this bug, but not sure how to fix it in a safe, cross-compiler way.
+- increased warning level to 4 and turned on detect 64 bit portability issues for VC2005.
+  May address [ 1677737 ] VS2005: /Wp64 warnings
+- grosheck identified several problems with the Document copy. Many thanks for [ 1660367 ]
+- Nice catch, and suggested fix, be Gilad Novik on the Printer dropping entities.
+  "[ 1600650 ] Bug when printing xml text" is now fixed.
+- A subtle fix from Nicos Gollan in the tinystring initializer: 
+  [ 1581449 ] Fix initialiser of TiXmlString::nullrep_
+- Great catch, although there isn't a submitter for the bug. [ 1475201 ] TinyXML parses entities in comments. 
+  Comments should not, in fact, parse entities. Fixed the code path and added tests.
+- We were not catching all the returns from ftell. Thanks to Bernard for catching that.
+  
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/changes_orxonox.diff
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/changes_orxonox.diff	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/changes_orxonox.diff	(revision 11817)
@@ -0,0 +1,35 @@
+--- ticpp.h
++++ ticpp.h
+@@ -38,9 +38,7 @@
+ @todo add TYPECOUNT support. See ticpp::NodeFactory.
+ @todo Add a quick reference
+ */
+-#ifndef TIXML_USE_TICPP
+-	#define TIXML_USE_TICPP
+-#endif
++#ifdef TIXML_USE_TICPP
+ 
+ #ifndef TICPP_INCLUDED
+ #define TICPP_INCLUDED
+@@ -1231,6 +1229,7 @@
+ 
+ 		T* m_tiXmlPointer;		/**< Internal pointer to the TiXml Class which is being wrapped */
+ 
++	public:
+ 		/**
+ 		@internal
+ 		Gets the internal TinyXML pointer.
+@@ -1242,6 +1241,7 @@
+ 			ValidatePointer();
+ 			return m_tiXmlPointer;
+ 		}
++	protected:
+ 
+ 		/**
+ 		@internal
+@@ -1903,3 +1903,5 @@
+ }
+ 
+ #endif	// TICPP_INCLUDED
++
++#endif // TIXML_USE_TICPP
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/readme.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/readme.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/readme.txt	(revision 11817)
@@ -0,0 +1,531 @@
+/** @mainpage
+
+<h1> TinyXML </h1>
+
+TinyXML is a simple, small, C++ XML parser that can be easily 
+integrated into other programs.
+
+<h2> What it does. </h2>
+	
+In brief, TinyXML parses an XML document, and builds from that a 
+Document Object Model (DOM) that can be read, modified, and saved.
+
+XML stands for "eXtensible Markup Language." It allows you to create 
+your own document markups. Where HTML does a very good job of marking 
+documents for browsers, XML allows you to define any kind of document 
+markup, for example a document that describes a "to do" list for an 
+organizer application. XML is a very structured and convenient format.
+All those random file formats created to store application data can 
+all be replaced with XML. One parser for everything.
+
+The best place for the complete, correct, and quite frankly hard to
+read spec is at <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>. An intro to XML
+(that I really like) can be found at 
+<a href="http://skew.org/xml/tutorial/">http://skew.org/xml/tutorial</a>.
+
+There are different ways to access and interact with XML data.
+TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed
+into a C++ objects that can be browsed and manipulated, and then 
+written to disk or another output stream. You can also construct an XML document 
+from scratch with C++ objects and write this to disk or another output
+stream.
+
+TinyXML is designed to be easy and fast to learn. It is two headers 
+and four cpp files. Simply add these to your project and off you go. 
+There is an example file - xmltest.cpp - to get you started. 
+
+TinyXML is released under the ZLib license, 
+so you can use it in open source or commercial code. The details
+of the license are at the top of every source file.
+
+TinyXML attempts to be a flexible parser, but with truly correct and
+compliant XML output. TinyXML should compile on any reasonably C++
+compliant system. It does not rely on exceptions or RTTI. It can be 
+compiled with or without STL support. TinyXML fully supports
+the UTF-8 encoding, and the first 64k character entities.
+
+
+<h2> What it doesn't do. </h2>
+
+TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs
+(eXtensible Stylesheet Language.) There are other parsers out there 
+(check out www.sourceforge.org, search for XML) that are much more fully
+featured. But they are also much bigger, take longer to set up in
+your project, have a higher learning curve, and often have a more
+restrictive license. If you are working with browsers or have more
+complete XML needs, TinyXML is not the parser for you.
+
+The following DTD syntax will not parse at this time in TinyXML:
+
+@verbatim
+	<!DOCTYPE Archiv [
+	 <!ELEMENT Comment (#PCDATA)>
+	]>
+@endverbatim
+
+because TinyXML sees this as a !DOCTYPE node with an illegally 
+embedded !ELEMENT node. This may be addressed in the future.
+
+<h2> Tutorials. </h2>
+
+For the impatient, here are some tutorials to get you going. A great way to get started, 
+but it is worth your time to read this (very short) manual completely.
+
+- @subpage ticppTutorial
+- @subpage tutorial0
+
+<h2> Code Status.  </h2>
+
+TinyXML is mature, tested code. It is very stable. If you find
+bugs, please file a bug report on the sourceforge web site
+(www.sourceforge.net/projects/tinyxml). We'll get them straightened 
+out as soon as possible.
+
+There are some areas of improvement; please check sourceforge if you are
+interested in working on TinyXML.
+
+<h2> Related Projects </h2>
+
+TinyXML projects you may find useful! (Descriptions provided by the projects.)
+
+<ul>
+<li> <b>TinyXPath</b> (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint 
+     XPath syntax decoder, written in C++.</li>
+<li> <b>@subpage ticpp</b> (http://code.google.com/p/ticpp/). TinyXML++ is a completely new 
+     interface to TinyXML that uses MANY of the C++ strengths. Templates, 
+	 exceptions, and much better error handling.</li>
+</ul>
+
+<h2> Features </h2>
+
+<h3> Using STL </h3>
+
+TinyXML can be compiled to use or not use STL. When using STL, TinyXML
+uses the std::string class, and fully supports std::istream, std::ostream,
+operator<<, and operator>>. Many API methods have both 'const char*' and
+'const std::string&' forms.
+
+When STL support is compiled out, no STL files are included whatsoever. All
+the string classes are implemented by TinyXML itself. API methods
+all use the 'const char*' form for input.
+
+Use the compile time #define:
+
+	TIXML_USE_STL
+
+to compile one version or the other. This can be passed by the compiler,
+or set as the first line of "tinyxml.h".
+
+Note: If compiling the test code in Linux, setting the environment
+variable TINYXML_USE_STL=YES/NO will control STL compilation. In the
+Windows project file, STL and non STL targets are provided. In your project,
+It's probably easiest to add the line "#define TIXML_USE_STL" as the first
+line of tinyxml.h.
+
+<h3> UTF-8 </h3>
+
+TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML
+also supports "legacy mode" - the encoding used before UTF-8 support and
+probably best described as "extended ascii".
+
+Normally, TinyXML will try to detect the correct encoding and use it. However,
+by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML
+can be forced to always use one encoding.
+
+TinyXML will assume Legacy Mode until one of the following occurs:
+<ol>
+	<li> If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf)
+		 begin the file or data stream, TinyXML will read it as UTF-8. </li>
+	<li> If the declaration tag is read, and it has an encoding="UTF-8", then
+		 TinyXML will read it as UTF-8. </li>
+	<li> If the declaration tag is read, and it has no encoding specified, then TinyXML will 
+		 read it as UTF-8. </li>
+	<li> If the declaration tag is read, and it has an encoding="something else", then TinyXML 
+		 will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's 
+		 not clear what that mode does exactly, but old content should keep working.</li>
+	<li> Until one of the above criteria is met, TinyXML runs in Legacy Mode.</li>
+</ol>
+
+What happens if the encoding is incorrectly set or detected? TinyXML will try
+to read and pass through text seen as improperly encoded. You may get some strange results or 
+mangled characters. You may want to force TinyXML to the correct mode.
+
+You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or
+LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all
+the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may 
+force it to TIXML_ENCODING_UTF8 with the same technique.
+
+For English users, using English XML, UTF-8 is the same as low-ASCII. You
+don't need to be aware of UTF-8 or change your code in any way. You can think
+of UTF-8 as a "superset" of ASCII.
+
+UTF-8 is not a double byte format - but it is a standard encoding of Unicode!
+TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time. 
+It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding
+of unicode. This is a source of confusion.
+
+For "high-ascii" languages - everything not English, pretty much - TinyXML can
+handle all languages, at the same time, as long as the XML is encoded
+in UTF-8. That can be a little tricky, older programs and operating systems
+tend to use the "default" or "traditional" code page. Many apps (and almost all
+modern ones) can output UTF-8, but older or stubborn (or just broken) ones
+still output text in the default code page. 
+
+For example, Japanese systems traditionally use SHIFT-JIS encoding. 
+Text encoded as SHIFT-JIS can not be read by TinyXML. 
+A good text editor can import SHIFT-JIS and then save as UTF-8.
+
+The <a href="http://skew.org/xml/tutorial/">Skew.org link</a> does a great
+job covering the encoding issue.
+
+The test file "utf8test.xml" is an XML containing English, Spanish, Russian,
+and Simplified Chinese. (Hopefully they are translated correctly). The file
+"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that
+if you don't have the correct fonts (Simplified Chinese or Russian) on your
+system, you won't see output that matches the GIF file even if you can parse
+it correctly. Also note that (at least on my Windows machine) console output
+is in a Western code page, so that Print() or printf() cannot correctly display
+the file. This is not a bug in TinyXML - just an OS issue. No data is lost or 
+destroyed by TinyXML. The console just doesn't render UTF-8.
+
+
+<h3> Entities </h3>
+TinyXML recognizes the pre-defined "character entities", meaning special
+characters. Namely:
+
+@verbatim
+	&amp;	&
+	&lt;	<
+	&gt;	>
+	&quot;	"
+	&apos;	'
+@endverbatim
+
+These are recognized when the XML document is read, and translated to there
+UTF-8 equivalents. For instance, text with the XML of:
+
+@verbatim
+	Far &amp; Away
+@endverbatim
+
+will have the Value() of "Far & Away" when queried from the TiXmlText object,
+and will be written back to the XML stream/file as an ampersand. Older versions
+of TinyXML "preserved" character entities, but the newer versions will translate
+them into characters.
+
+Additionally, any character can be specified by its Unicode code point:
+The syntax "&#xA0;" or "&#160;" are both to the non-breaking space characher.
+
+<h3> Printing </h3>
+TinyXML can print output in several different ways that all have strengths and limitations.
+
+- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout.
+	- "Pretty prints", but you don't have control over printing options.
+	- The output is streamed directly to the FILE object, so there is no memory overhead
+	  in the TinyXML code.
+	- used by Print() and SaveFile()
+
+- operator<<. Output to a c++ stream.
+	- Integrates with standart C++ iostreams.
+	- Outputs in "network printing" mode without line breaks. Good for network transmission
+	  and moving XML between C++ objects, but hard for a human to read.
+
+- TiXmlPrinter. Output to a std::string or memory buffer.
+	- API is less concise
+	- Future printing options will be put here.
+	- Printing may change slightly in future versions as it is refined and expanded.
+
+<h3> Streams </h3>
+With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well
+as C (FILE*) streams. There are some differences that you may need to be aware of.
+
+C style output:
+	- based on FILE*
+	- the Print() and SaveFile() methods
+
+	Generates formatted output, with plenty of white space, intended to be as 
+	human-readable as possible. They are very fast, and tolerant of ill formed 
+	XML documents. For example, an XML document that contains 2 root elements 
+	and 2 declarations, will still print.
+
+C style input:
+	- based on FILE*
+	- the Parse() and LoadFile() methods
+
+	A fast, tolerant read. Use whenever you don't need the C++ streams.
+
+C++ style output:
+	- based on std::ostream
+	- operator<<
+
+	Generates condensed output, intended for network transmission rather than
+	readability. Depending on your system's implementation of the ostream class,
+	these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML:
+	a document should contain the correct one root element. Additional root level
+	elements will not be streamed out.
+
+C++ style input:
+	- based on std::istream
+	- operator>>
+
+	Reads XML from a stream, making it useful for network transmission. The tricky
+	part is knowing when the XML document is complete, since there will almost
+	certainly be other data in the stream. TinyXML will assume the XML data is
+	complete after it reads the root element. Put another way, documents that
+	are ill-constructed with more than one root element will not read correctly.
+	Also note that operator>> is somewhat slower than Parse, due to both 
+	implementation of the STL and limitations of TinyXML.
+
+<h3> White space </h3>
+The world simply does not agree on whether white space should be kept, or condensed.
+For example, pretend the '_' is a space, and look at "Hello____world". HTML, and 
+at least some XML parsers, will interpret this as "Hello_world". They condense white
+space. Some XML parsers do not, and will leave it as "Hello____world". (Remember
+to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become
+Hello___world.
+
+It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the
+first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior.
+The default is to condense white space.
+
+If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool )
+before making any calls to Parse XML data, and I don't recommend changing it after
+it has been set.
+
+
+<h3> Handles </h3>
+
+Where browsing an XML document in a robust way, it is important to check
+for null returns from method calls. An error safe implementation can
+generate a lot of code like:
+
+@verbatim
+TiXmlElement* root = document.FirstChildElement( "Document" );
+if ( root )
+{
+	TiXmlElement* element = root->FirstChildElement( "Element" );
+	if ( element )
+	{
+		TiXmlElement* child = element->FirstChildElement( "Child" );
+		if ( child )
+		{
+			TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+			if ( child2 )
+			{
+				// Finally do something useful.
+@endverbatim
+
+Handles have been introduced to clean this up. Using the TiXmlHandle class,
+the previous code reduces to:
+
+@verbatim
+TiXmlHandle docHandle( &document );
+TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+if ( child2 )
+{
+	// do something useful
+@endverbatim
+
+Which is much easier to deal with. See TiXmlHandle for more information.
+
+
+<h3> Row and Column tracking </h3>
+Being able to track nodes and attributes back to their origin location
+in source files can be very important for some applications. Additionally,
+knowing where parsing errors occured in the original source can be very
+time saving.
+
+TinyXML can tracks the row and column origin of all nodes and attributes
+in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return
+the origin of the node in the source text. The correct tabs can be 
+configured in TiXmlDocument::SetTabSize().
+
+
+<h2> Using and Installing </h2>
+
+To Compile and Run xmltest:
+
+A Linux Makefile and a Windows Visual C++ .dsw file is provided. 
+Simply compile and run. It will write the file demotest.xml to your 
+disk and generate output on the screen. It also tests walking the
+DOM by printing out the number of nodes found using different 
+techniques.
+
+The Linux makefile is very generic and runs on many systems - it 
+is currently tested on mingw and
+MacOSX. You do not need to run 'make depend'. The dependecies have been
+hard coded.
+
+<h3>Windows project file for VC6</h3>
+<ul>
+<li>tinyxml:		tinyxml library, non-STL </li>
+<li>tinyxmlSTL:		tinyxml library, STL </li>
+<li>tinyXmlTest:	test app, non-STL </li>
+<li>tinyXmlTestSTL: test app, STL </li>
+</ul>
+
+<h3>Makefile</h3>
+At the top of the makefile you can set:
+
+PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in
+the makefile.
+
+In the tinyxml directory, type "make clean" then "make". The executable
+file 'xmltest' will be created.
+
+
+
+<h3>To Use in an Application:</h3>
+
+Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your
+project or make file. That's it! It should compile on any reasonably
+compliant C++ system. You do not need to enable exceptions or
+RTTI for TinyXML.
+
+
+<h2> How TinyXML works.  </h2>
+
+An example is probably the best way to go. Take:
+@verbatim
+	<?xml version="1.0" standalone=no>
+	<!-- Our to do list data -->
+	<ToDo>
+		<Item priority="1"> Go to the <bold>Toy store!</bold></Item>
+		<Item priority="2"> Do bills</Item>
+	</ToDo>
+@endverbatim
+
+Its not much of a To Do list, but it will do. To read this file 
+(say "demo.xml") you would create a document, and parse it in:
+@verbatim
+	TiXmlDocument doc( "demo.xml" );
+	doc.LoadFile();
+@endverbatim
+
+And its ready to go. Now lets look at some lines and how they 
+relate to the DOM.
+
+@verbatim
+<?xml version="1.0" standalone=no>
+@endverbatim
+
+	The first line is a declaration, and gets turned into the
+	TiXmlDeclaration class. It will be the first child of the
+	document node.
+	
+	This is the only directive/special tag parsed by by TinyXML.
+	Generally directive tags are stored in TiXmlUnknown so the 
+	commands wont be lost when it is saved back to disk.
+
+@verbatim
+<!-- Our to do list data -->
+@endverbatim
+
+	A comment. Will become a TiXmlComment object.
+
+@verbatim
+<ToDo>
+@endverbatim
+
+	The "ToDo" tag defines a TiXmlElement object. This one does not have 
+	any attributes, but does contain 2 other elements.
+
+@verbatim
+<Item priority="1"> 
+@endverbatim
+
+	Creates another TiXmlElement which is a child of the "ToDo" element. 
+	This element has 1 attribute, with the name "priority" and the value 
+	"1".
+
+@verbatim
+Go to the
+@endverbatim 
+
+	A TiXmlText. This is a leaf node and cannot contain other nodes. 
+	It is a child of the "Item" TiXmlElement.
+
+@verbatim
+<bold>
+@endverbatim
+
+	
+	Another TiXmlElement, this one a child of the "Item" element.
+
+Etc.
+
+Looking at the entire object tree, you end up with:
+@verbatim
+TiXmlDocument					"demo.xml"
+	TiXmlDeclaration			"version='1.0'" "standalone=no"
+	TiXmlComment				" Our to do list data"
+	TiXmlElement				"ToDo"
+		TiXmlElement			"Item" Attribtutes: priority = 1
+			TiXmlText			"Go to the "
+			TiXmlElement		"bold"
+				TiXmlText		"Toy store!"
+		TiXmlElement			"Item" Attributes: priority=2
+			TiXmlText			"Do bills"
+@endverbatim
+
+<h2> Documentation </h2>
+
+The documentation is build with Doxygen, using the 'dox' 
+configuration file.
+
+<h2> License </h2>
+
+TinyXML is released under the zlib license:
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must 
+not claim that you wrote the original software. If you use this 
+software in a product, an acknowledgment in the product documentation 
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and 
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source 
+distribution.
+
+<h2> References  </h2>
+
+The World Wide Web Consortium is the definitive standard body for 
+XML, and there web pages contain huge amounts of information. 
+
+The definitive spec: <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>
+
+I also recommend "XML Pocket Reference" by Robert Eckstein and published by 
+OReilly...the book that got the whole thing started.
+
+<h2> Contributors, Contacts, and a Brief History </h2>
+
+Thanks very much to everyone who sends suggestions, bugs, ideas, and 
+encouragement. It all helps, and makes this project fun. A special thanks
+to the contributors on the web pages that keep it lively.
+
+So many people have sent in bugs and ideas, that rather than list here 
+we try to give credit due in the "changes.txt" file.
+
+TinyXML was originally written by Lee Thomason. (Often the "I" still
+in the documentation.) Lee reviews changes and releases new versions,
+with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community.
+
+We appreciate your suggestions, and would love to know if you 
+use TinyXML. Hopefully you will enjoy it and find it useful. 
+Please post questions, comments, file bugs, or contact us at:
+
+www.sourceforge.net/projects/tinyxml
+
+Lee Thomason, Yves Berquin, Andrew Ellerton
+*/
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/ticpp.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/ticpp.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/ticpp.cpp	(revision 11817)
@@ -0,0 +1,1150 @@
+/*
+http://code.google.com/p/ticpp/
+Copyright (c) 2006 Ryan Pusztai, Ryan Mulder
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifdef TIXML_USE_TICPP
+
+#include "ticpp.h"
+#include "ticpprc.h"
+#include "tinyxml.h"
+#include <sstream>
+
+using namespace ticpp;
+
+// In the following Visitor functions, casting away const should be safe, as the object can only be referred to by a const &
+bool Visitor::VisitEnter( const TiXmlDocument& doc )
+{
+	return VisitEnter( Document( const_cast< TiXmlDocument* >( &doc ) ) );
+}
+
+bool Visitor::VisitExit( const TiXmlDocument& doc )
+{
+	return VisitEnter( Document( const_cast< TiXmlDocument* >( &doc ) ) );
+}
+
+bool Visitor::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
+{
+	if ( 0 != firstAttribute )
+	{
+		Attribute attribute( const_cast< TiXmlAttribute* >( firstAttribute ) );
+		return VisitEnter( Element( const_cast< TiXmlElement* >( &element ) ), &attribute );
+	}
+	else
+	{
+		return VisitEnter( Element( const_cast< TiXmlElement* >( &element ) ), 0 );
+	}
+}
+
+bool Visitor::VisitExit( const TiXmlElement& element )
+{
+	return VisitExit( Element( const_cast< TiXmlElement* >( &element ) ) );
+}
+
+bool Visitor::Visit( const TiXmlDeclaration& declaration )
+{
+	return Visit( Declaration( const_cast< TiXmlDeclaration* >( &declaration ) ) );
+}
+
+bool Visitor::Visit( const TiXmlStylesheetReference& stylesheet )
+{
+	return Visit( StylesheetReference( const_cast< TiXmlStylesheetReference* >( &stylesheet ) ) );
+}
+
+bool Visitor::Visit( const TiXmlText& text )
+{
+	return Visit( Text( const_cast< TiXmlText* >( &text ) ) );
+}
+
+bool Visitor::Visit( const TiXmlComment& comment )
+{
+	return Visit( Comment( const_cast< TiXmlComment* >( &comment ) ) );
+}
+
+Attribute::Attribute()
+{
+	SetTiXmlPointer( new TiXmlAttribute() );
+	m_impRC->InitRef();
+}
+
+Attribute::Attribute( TiXmlAttribute* attribute )
+{
+	SetTiXmlPointer( attribute );
+	m_impRC->IncRef();
+}
+
+Attribute::Attribute( const std::string& name, const std::string& value )
+{
+	SetTiXmlPointer( new TiXmlAttribute( name, value ) );
+	m_impRC->InitRef();
+}
+
+void Attribute::operator=( const Attribute& copy )
+{
+	// Dropping the reference to the old object
+	this->m_impRC->DecRef();
+
+	// Pointing to the new Object
+	SetTiXmlPointer( copy.m_tiXmlPointer );
+
+	// The internal tixml pointer changed in the above line
+	this->m_impRC->IncRef();
+}
+
+Attribute::Attribute( const Attribute& copy ) : Base()
+{
+	// Dropping the reference to the old object
+	this->m_impRC->DecRef();
+
+	// Pointing to the new Object
+	SetTiXmlPointer( copy.m_tiXmlPointer );
+
+	// The internal tixml pointer changed in the above line
+	this->m_impRC->IncRef();
+}
+
+Attribute::~Attribute()
+{
+	m_impRC->DecRef();
+}
+
+std::string Attribute::Value() const
+{
+	ValidatePointer();
+	return m_tiXmlPointer->ValueStr();
+}
+
+std::string Attribute::Name() const
+{
+	ValidatePointer();
+	return m_tiXmlPointer->Name();
+}
+
+Attribute* Attribute::Next( bool throwIfNoAttribute ) const
+{
+	ValidatePointer();
+	TiXmlAttribute* attribute = m_tiXmlPointer->Next();
+	if ( 0 == attribute )
+	{
+		if ( throwIfNoAttribute )
+		{
+			TICPPTHROW( "No more attributes found" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Attribute* temp = new Attribute( attribute );
+	attribute->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Attribute* Attribute::Previous( bool throwIfNoAttribute ) const
+{
+	ValidatePointer();
+	TiXmlAttribute* attribute = m_tiXmlPointer->Previous();
+	if ( 0 == attribute )
+	{
+		if ( throwIfNoAttribute )
+		{
+			TICPPTHROW( "No more attributes found" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Attribute* temp = new Attribute( attribute );
+	attribute->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+void Attribute::IterateNext( const std::string&, Attribute** next ) const
+{
+	*next = Next( false );
+}
+
+void Attribute::IteratePrevious( const std::string&, Attribute** previous ) const
+{
+	*previous = Previous( false );
+}
+
+void Attribute::Print( FILE* file, int depth ) const
+{
+	ValidatePointer();
+	m_tiXmlPointer->Print( file, depth );
+}
+
+void Attribute::SetTiXmlPointer( TiXmlAttribute* newPointer )
+{
+	m_tiXmlPointer = newPointer;
+	SetImpRC( newPointer );
+}
+
+//*****************************************************************************
+
+Node* Node::NodeFactory( TiXmlNode* tiXmlNode, bool throwIfNull, bool rememberSpawnedWrapper ) const
+{
+	if ( 0 == tiXmlNode )
+	{
+		if ( throwIfNull )
+		{
+			TICPPTHROW( "tiXmlNode is NULL" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Node* temp;
+	switch ( tiXmlNode->Type() )
+	{
+		case TiXmlNode::DOCUMENT:
+			temp = new Document( tiXmlNode->ToDocument() );
+			break;
+
+		case TiXmlNode::ELEMENT:
+			temp = new Element( tiXmlNode->ToElement() );
+			break;
+
+		case TiXmlNode::COMMENT:
+			temp = new Comment( tiXmlNode->ToComment() );
+			break;
+
+		case TiXmlNode::TEXT:
+			temp = new Text( tiXmlNode->ToText() );
+			break;
+
+		case TiXmlNode::DECLARATION:
+			temp = new Declaration( tiXmlNode->ToDeclaration() );
+			break;
+
+		case TiXmlNode::STYLESHEETREFERENCE:
+			temp = new StylesheetReference( tiXmlNode->ToStylesheetReference() );
+			break;
+
+		default:
+			TICPPTHROW( "Type is unsupported" )
+	}
+
+	if ( rememberSpawnedWrapper )
+	{
+		tiXmlNode->m_spawnedWrappers.push_back( temp );
+	}
+	return temp;
+}
+
+
+std::string Node::Value() const
+{
+	return GetTiXmlPointer()->ValueStr();
+}
+
+void Node::Clear()
+{
+	GetTiXmlPointer()->Clear();
+}
+
+Node* Node::Parent( bool throwIfNoParent ) const
+{
+	TiXmlNode* parent = GetTiXmlPointer()->Parent();
+	if ( ( 0 == parent ) && throwIfNoParent )
+	{
+		TICPPTHROW( "No parent exists" );
+	}
+
+	return NodeFactory( parent, false );
+}
+
+Node* Node::FirstChild( bool throwIfNoChildren ) const
+{
+	return FirstChild( "", throwIfNoChildren );
+}
+
+Node* Node::FirstChild( const std::string& value, bool throwIfNoChildren ) const
+{
+	return FirstChild( value.c_str(), throwIfNoChildren );
+}
+
+Node* Node::FirstChild( const char* value, bool throwIfNoChildren ) const
+{
+	TiXmlNode* childNode;
+	if ( 0 == strlen( value ) )
+	{
+		childNode = GetTiXmlPointer()->FirstChild();
+	}
+	else
+	{
+		childNode = GetTiXmlPointer()->FirstChild( value );
+	}
+
+	if ( ( 0 == childNode ) && throwIfNoChildren )
+	{
+		TICPPTHROW( "Child with the value of \"" << value << "\" not found" );
+	}
+
+	return NodeFactory( childNode, false );
+}
+
+Node* Node::LastChild( bool throwIfNoChildren ) const
+{
+	return LastChild( "", throwIfNoChildren );
+}
+
+Node* Node::LastChild( const std::string& value, bool throwIfNoChildren ) const
+{
+	return LastChild( value.c_str(), throwIfNoChildren );
+}
+
+Node* Node::LastChild( const char* value, bool throwIfNoChildren ) const
+{
+	TiXmlNode* childNode;
+	if ( 0 == strlen( value ) )
+	{
+		childNode = GetTiXmlPointer()->LastChild();
+	}
+	else
+	{
+		childNode = GetTiXmlPointer()->LastChild( value );
+	}
+
+	if ( ( 0 == childNode ) && throwIfNoChildren )
+	{
+		TICPPTHROW( "Child with the value of \"" << value << "\" not found" );
+	}
+
+	return NodeFactory( childNode, false );
+}
+
+Node* Node::IterateChildren ( Node* previous ) const
+{
+	TiXmlNode* pointer;
+	if ( 0 == previous )
+	{
+		pointer = GetTiXmlPointer()->IterateChildren( 0 );
+	}
+	else
+	{
+		pointer = GetTiXmlPointer()->IterateChildren( previous->GetTiXmlPointer() );
+	}
+
+	return NodeFactory( pointer, false );
+}
+
+Node* Node::IterateChildren( const std::string& value, Node* previous ) const
+{
+	TiXmlNode* pointer;
+	if ( 0 == previous )
+	{
+		pointer = GetTiXmlPointer()->IterateChildren( value, 0 );
+	}
+	else
+	{
+		pointer = GetTiXmlPointer()->IterateChildren( value, previous->GetTiXmlPointer() );
+	}
+
+	return NodeFactory( pointer, false );
+}
+
+Node* Node::InsertEndChild( const Node& addThis )
+{
+	if ( addThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		TICPPTHROW( "Node is a Document and can't be inserted" );
+	}
+
+	TiXmlNode* pointer = GetTiXmlPointer()->InsertEndChild( *addThis.GetTiXmlPointer() );
+	if ( 0 == pointer )
+	{
+		TICPPTHROW( "Node can't be inserted" );
+	}
+
+	return NodeFactory( pointer );
+}
+
+Node* Node::LinkEndChild( Node* childNode )
+{
+	if ( childNode->Type() == TiXmlNode::DOCUMENT )
+	{
+		TICPPTHROW( "Node is a Document and can't be linked" );
+	}
+
+	// Increment reference count when adding to the tree
+	childNode->m_impRC->IncRef();
+
+	if ( 0 == GetTiXmlPointer()->LinkEndChild( childNode->GetTiXmlPointer() ) )
+	{
+		TICPPTHROW( "Node can't be linked" );
+	}
+
+	return childNode;
+}
+
+Node* Node::InsertBeforeChild( Node* beforeThis, const Node& addThis )
+{
+	if ( addThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		TICPPTHROW( "Node is a Document and can't be inserted" );
+	}
+
+	// Increment reference count when adding to the tree
+	addThis.m_impRC->IncRef();
+
+	TiXmlNode* pointer = GetTiXmlPointer()->InsertBeforeChild( beforeThis->GetTiXmlPointer(), *addThis.GetTiXmlPointer() );
+	if ( 0 == pointer )
+	{
+		TICPPTHROW( "Node can't be inserted" );
+	}
+
+	return NodeFactory( pointer );
+}
+
+Node* Node::InsertAfterChild( Node* afterThis, const Node& addThis )
+{
+	if ( addThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		TICPPTHROW( "Node is a Document and can't be inserted" );
+	}
+
+	// Increment reference count when adding to the tree
+	addThis.m_impRC->IncRef();
+
+	TiXmlNode* pointer = GetTiXmlPointer()->InsertAfterChild( afterThis->GetTiXmlPointer(), *addThis.GetTiXmlPointer() );
+	if ( 0 == pointer )
+	{
+		TICPPTHROW( "Node can't be inserted" );
+	}
+
+	return NodeFactory( pointer );
+}
+
+Node* Node::ReplaceChild( Node* replaceThis, const Node& withThis )
+{
+	if ( withThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		TICPPTHROW( "Node is a Document and can't be inserted" );
+	}
+
+	// Increment reference count when adding to the tree
+	withThis.m_impRC->IncRef();
+
+	TiXmlNode* pointer = GetTiXmlPointer()->ReplaceChild( replaceThis->GetTiXmlPointer(), *withThis.GetTiXmlPointer() );
+	if ( 0 == pointer )
+	{
+		TICPPTHROW( "Node can't be inserted" );
+	}
+
+	return NodeFactory( pointer );
+}
+
+void Node::RemoveChild( Node* removeThis )
+{
+	if  ( !GetTiXmlPointer()->RemoveChild( removeThis->GetTiXmlPointer() ) )
+	{
+		TICPPTHROW( "Node to remove (" << removeThis->Value() << ") is not a child of this Node (" << Value() << ")" )
+	}
+}
+
+Node* Node::PreviousSibling( bool throwIfNoSiblings ) const
+{
+	return PreviousSibling( "", throwIfNoSiblings );
+}
+
+Node* Node::PreviousSibling( const std::string& value, bool throwIfNoSiblings ) const
+{
+	return PreviousSibling( value.c_str(), throwIfNoSiblings );
+}
+
+Node* Node::PreviousSibling( const char* value, bool throwIfNoSiblings ) const
+{
+	TiXmlNode* sibling;
+	if ( 0 == strlen( value ) )
+	{
+		sibling = GetTiXmlPointer()->PreviousSibling();
+	}
+	else
+	{
+		sibling = GetTiXmlPointer()->PreviousSibling( value );
+	}
+
+	if ( ( 0 == sibling ) && throwIfNoSiblings )
+	{
+		TICPPTHROW( "No Siblings found with value, '" << value << "', Prior to this Node (" << Value() << ")" )
+	}
+
+	return NodeFactory( sibling, false );
+}
+
+Node* Node::NextSibling( bool throwIfNoSiblings ) const
+{
+	return NextSibling( "", throwIfNoSiblings );
+}
+
+Node* Node::NextSibling( const std::string& value, bool throwIfNoSiblings ) const
+{
+	return NextSibling( value.c_str(), throwIfNoSiblings );
+}
+
+Node* Node::NextSibling( const char* value, bool throwIfNoSiblings ) const
+{
+	TiXmlNode* sibling;
+	if ( 0 == strlen( value ) )
+	{
+		sibling = GetTiXmlPointer()->NextSibling();
+	}
+	else
+	{
+		sibling = GetTiXmlPointer()->NextSibling( value );
+	}
+
+	if ( ( 0 == sibling ) && throwIfNoSiblings )
+	{
+		TICPPTHROW( "No Siblings found with value, '" << value << "', After this Node (" << Value() << ")" )
+	}
+
+	return NodeFactory( sibling, false );
+}
+
+Element* Node::NextSiblingElement( bool throwIfNoSiblings ) const
+{
+	return NextSiblingElement( "", throwIfNoSiblings );
+}
+
+Element* Node::NextSiblingElement( const std::string& value, bool throwIfNoSiblings ) const
+{
+	return NextSiblingElement( value.c_str(), throwIfNoSiblings );
+}
+
+Element* Node::NextSiblingElement( const char* value, bool throwIfNoSiblings ) const
+{
+	TiXmlElement* sibling;
+	if ( 0 == strlen( value ) )
+	{
+		sibling = GetTiXmlPointer()->NextSiblingElement();
+	}
+	else
+	{
+		sibling = GetTiXmlPointer()->NextSiblingElement( value );
+	}
+
+	if ( 0 == sibling )
+	{
+		if ( throwIfNoSiblings )
+		{
+			TICPPTHROW( "No Element Siblings found with value, '" << value << "', After this Node (" << Value() << ")" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Element* temp = new Element( sibling );
+	sibling->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Element* Node::FirstChildElement( bool throwIfNoChildren ) const
+{
+	return FirstChildElement( "", throwIfNoChildren );
+}
+
+Element* Node::FirstChildElement( const std::string& value, bool throwIfNoChildren ) const
+{
+	return FirstChildElement( value.c_str(), throwIfNoChildren );
+}
+
+Element* Node::FirstChildElement( const char* value, bool throwIfNoChildren ) const
+{
+	TiXmlElement* element;
+	if ( 0 == strlen( value ) )
+	{
+		element = GetTiXmlPointer()->FirstChildElement();
+	}
+	else
+	{
+		element = GetTiXmlPointer()->FirstChildElement( value );
+	}
+
+	if ( 0 == element )
+	{
+		if( throwIfNoChildren )
+		{
+			TICPPTHROW( "Element (" << Value() << ") does NOT contain a child with the value of '" << value << "'" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Element* temp = new Element( element );
+	element->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+int Node::Type() const
+{
+	return GetTiXmlPointer()->Type();
+}
+
+Document* Node::GetDocument( bool throwIfNoDocument ) const
+{
+	TiXmlDocument* doc = GetTiXmlPointer()->GetDocument();
+	if ( 0 == doc )
+	{
+		if( throwIfNoDocument )
+		{
+			TICPPTHROW( "This node (" << Value() << ") is not linked under a document" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+	Document* temp = new Document( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+bool Node::NoChildren() const
+{
+	return GetTiXmlPointer()->NoChildren();
+}
+
+Document* Node::ToDocument() const
+{
+	TiXmlDocument* doc = GetTiXmlPointer()->ToDocument();
+	if ( 0 == doc )
+	{
+		TICPPTHROW( "This node (" << Value() << ") is not a Document" )
+	}
+	Document* temp = new Document( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Element* Node::ToElement() const
+{
+	TiXmlElement* doc = GetTiXmlPointer()->ToElement();
+	if ( 0 == doc )
+	{
+		TICPPTHROW( "This node (" << Value() << ") is not a Element" )
+	}
+	Element* temp = new Element( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Comment* Node::ToComment() const
+{
+	TiXmlComment* doc = GetTiXmlPointer()->ToComment();
+	if ( 0 == doc )
+	{
+		TICPPTHROW( "This node (" << Value() << ") is not a Comment" )
+	}
+	Comment* temp = new Comment( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Text* Node::ToText() const
+{
+	TiXmlText* doc = GetTiXmlPointer()->ToText();
+	if ( 0 == doc )
+	{
+		TICPPTHROW( "This node (" << Value() << ") is not a Text" )
+	}
+	Text* temp = new Text( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Declaration* Node::ToDeclaration() const
+{
+	TiXmlDeclaration* doc = GetTiXmlPointer()->ToDeclaration();
+	if ( 0 == doc )
+	{
+		TICPPTHROW( "This node (" << Value() << ") is not a Declaration" )
+	}
+	Declaration* temp = new Declaration( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+StylesheetReference* Node::ToStylesheetReference() const
+{
+	TiXmlStylesheetReference* doc = GetTiXmlPointer()->ToStylesheetReference();
+	if ( 0 == doc )
+	{
+		TICPPTHROW( "This node (" << Value() << ") is not a StylesheetReference" )
+	}
+	StylesheetReference* temp = new StylesheetReference( doc );
+	doc->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+std::unique_ptr< Node > Node::Clone() const
+{
+	TiXmlNode* node = GetTiXmlPointer()->Clone();
+	if ( 0 == node )
+	{
+		TICPPTHROW( "Node could not be cloned" );
+	}
+	std::unique_ptr< Node > temp( NodeFactory( node, false, false ) );
+
+	// Take ownership of the memory from TiXml
+	temp->m_impRC->InitRef();
+
+	return temp;
+}
+
+bool Node::Accept( TiXmlVisitor* visitor ) const
+{
+	return GetTiXmlPointer()->Accept( visitor );
+}
+
+//*****************************************************************************
+
+Comment::Comment()
+: NodeImp< TiXmlComment >( new TiXmlComment() )
+{
+	m_impRC->InitRef();
+}
+
+Comment::Comment( TiXmlComment* comment )
+: NodeImp< TiXmlComment >( comment )
+{
+}
+
+Comment::Comment( const std::string& comment )
+: NodeImp< TiXmlComment >( new TiXmlComment() )
+{
+	m_impRC->InitRef();
+	m_tiXmlPointer->SetValue( comment );
+}
+
+//*****************************************************************************
+
+Text::Text()
+: NodeImp< TiXmlText >( new TiXmlText("") )
+{
+	m_impRC->InitRef();
+}
+
+
+Text::Text( const std::string& value )
+: NodeImp< TiXmlText >( new TiXmlText( value ) )
+{
+	m_impRC->InitRef();
+}
+
+Text::Text( TiXmlText* text )
+: NodeImp< TiXmlText >( text )
+{
+}
+
+
+//*****************************************************************************
+
+Document::Document()
+: NodeImp< TiXmlDocument >( new TiXmlDocument() )
+{
+	m_impRC->InitRef();
+}
+
+Document::Document( TiXmlDocument* document )
+: NodeImp< TiXmlDocument >( document )
+{
+}
+
+Document::Document( const char* documentName )
+: NodeImp< TiXmlDocument >( new TiXmlDocument( documentName ) )
+{
+	m_impRC->InitRef();
+}
+
+Document::Document( const std::string& documentName )
+: NodeImp< TiXmlDocument >( new TiXmlDocument( documentName ) )
+{
+	m_impRC->InitRef();
+}
+
+void Document::LoadFile( TiXmlEncoding encoding )
+{
+	if ( !m_tiXmlPointer->LoadFile( encoding ) )
+	{
+		TICPPTHROW( "Couldn't load " << m_tiXmlPointer->Value() );
+	}
+}
+
+void Document::SaveFile( void ) const
+{
+	if ( !m_tiXmlPointer->SaveFile() )
+	{
+		TICPPTHROW( "Couldn't save " << m_tiXmlPointer->Value() );
+	}
+}
+
+void Document::LoadFile( const std::string& filename, TiXmlEncoding encoding )
+{
+	if ( !m_tiXmlPointer->LoadFile( filename.c_str(), encoding ) )
+	{
+		TICPPTHROW( "Couldn't load " << filename );
+	}
+}
+
+void Document::LoadFile( const char* filename, TiXmlEncoding encoding )
+{
+	if ( !m_tiXmlPointer->LoadFile( filename, encoding ) )
+	{
+		TICPPTHROW( "Couldn't load " << filename );
+	}
+}
+
+void Document::SaveFile( const std::string& filename ) const
+{
+	if ( !m_tiXmlPointer->SaveFile( filename.c_str() ) )
+	{
+		TICPPTHROW( "Couldn't save " << filename );
+	}
+}
+
+void Document::Parse( const std::string& xml, bool throwIfParseError, TiXmlEncoding encoding )
+{
+	m_tiXmlPointer->Parse( xml.c_str(), 0, encoding );
+	if( throwIfParseError && m_tiXmlPointer->Error() )
+	{
+		TICPPTHROW( "Error parsing xml." );
+	}
+}
+
+//*****************************************************************************
+
+Element::Element()
+: NodeImp< TiXmlElement >( new TiXmlElement( "DefaultValueCausedByCreatingAnElementWithNoParameters" ) )
+{
+	m_impRC->InitRef();
+}
+
+Element::Element( const std::string& value )
+: NodeImp< TiXmlElement >( new TiXmlElement( value ) )
+{
+	m_impRC->InitRef();
+}
+
+Element::Element( const char* value )
+: NodeImp< TiXmlElement >( new TiXmlElement( value ) )
+{
+	m_impRC->InitRef();
+}
+
+Element::Element( TiXmlElement* element )
+: NodeImp< TiXmlElement >( element )
+{
+}
+
+Attribute* Element::FirstAttribute( bool throwIfNoAttributes ) const
+{
+	ValidatePointer();
+	TiXmlAttribute* attribute = m_tiXmlPointer->FirstAttribute();
+	if ( ( 0 == attribute ) && throwIfNoAttributes )
+	{
+		TICPPTHROW( "This Element (" << Value() << ") has no attributes" )
+	}
+
+	if ( 0 == attribute )
+	{
+		if( throwIfNoAttributes )
+		{
+			TICPPTHROW( "Element (" << Value() << ") has no attributes" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Attribute* temp = new Attribute( attribute );
+	attribute->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+Attribute* Element::LastAttribute( bool throwIfNoAttributes ) const
+{
+	ValidatePointer();
+	TiXmlAttribute* attribute = m_tiXmlPointer->LastAttribute();
+	if ( ( 0 == attribute ) && throwIfNoAttributes )
+	{
+		TICPPTHROW( "This Element (" << Value() << ") has no attributes" )
+	}
+
+	if ( 0 == attribute )
+	{
+		if( throwIfNoAttributes )
+		{
+			TICPPTHROW( "Element (" << Value() << ") has no attributes" )
+		}
+		else
+		{
+			return 0;
+		}
+	}
+
+	Attribute* temp = new Attribute( attribute );
+	attribute->m_spawnedWrappers.push_back( temp );
+
+	return temp;
+}
+
+std::string Element::GetAttributeOrDefault( const std::string& name, const std::string& defaultValue ) const
+{
+	std::string value;
+	if ( !GetAttributeImp( name, &value ) )
+	{
+		return defaultValue;
+	}
+	return value;
+}
+
+std::string Element::GetAttribute( const std::string& name ) const
+{
+	return GetAttributeOrDefault( name, std::string() );
+}
+
+bool Element::HasAttribute( const std::string& name ) const
+{
+	ValidatePointer();
+	return ( 0 != m_tiXmlPointer->Attribute( name.c_str() ) );
+}
+
+void Element::RemoveAttribute( const std::string& name )
+{
+	ValidatePointer();
+	m_tiXmlPointer->RemoveAttribute( name.c_str() );
+}
+
+bool Element::GetAttributeImp( const std::string& name, std::string* value ) const
+{
+	ValidatePointer();
+
+	// Get value from TinyXML, if the attribute exists
+	const char* retVal = m_tiXmlPointer->Attribute( name.c_str() );
+
+	// TinyXML returns NULL if the attribute doesn't exist
+	if ( 0 == retVal )
+	{
+		return false;
+	}
+	else
+	{
+		*value = retVal;
+		return true;
+	}
+}
+
+bool Element::GetTextImp( std::string* value ) const
+{
+	ValidatePointer();
+
+	// Get value from TinyXML, if the attribute exists
+	const char* retVal = m_tiXmlPointer->GetText();
+
+	// TinyXML returns NULL if the attribute doesn't exist
+	if ( 0 == retVal )
+	{
+		return false;
+	}
+	else
+	{
+		*value = retVal;
+		return true;
+	}
+}
+
+//*****************************************************************************
+
+Declaration::Declaration()
+: NodeImp< TiXmlDeclaration >( new TiXmlDeclaration() )
+{
+	m_impRC->InitRef();
+}
+
+Declaration::Declaration( TiXmlDeclaration* declaration )
+: NodeImp< TiXmlDeclaration >( declaration )
+{
+}
+
+Declaration::Declaration( const std::string& version, const std::string& encoding, const std::string& standalone )
+: NodeImp< TiXmlDeclaration >( new TiXmlDeclaration( version, encoding, standalone ) )
+{
+	m_impRC->InitRef();
+}
+
+std::string Declaration::Version() const
+{
+	return m_tiXmlPointer->Version();
+}
+
+std::string Declaration::Encoding() const
+{
+	return m_tiXmlPointer->Encoding();
+}
+
+std::string Declaration::Standalone() const
+{
+	return m_tiXmlPointer->Standalone();
+}
+
+//*****************************************************************************
+
+StylesheetReference::StylesheetReference()
+: NodeImp< TiXmlStylesheetReference >( new TiXmlStylesheetReference() )
+{
+	m_impRC->InitRef();
+}
+
+StylesheetReference::StylesheetReference( TiXmlStylesheetReference* stylesheetReference )
+: NodeImp< TiXmlStylesheetReference >( stylesheetReference )
+{
+}
+
+StylesheetReference::StylesheetReference( const std::string& type, const std::string& href )
+: NodeImp< TiXmlStylesheetReference >( new TiXmlStylesheetReference( type, href ) )
+{
+	m_impRC->InitRef();
+}
+
+std::string StylesheetReference::Type() const
+{
+	return m_tiXmlPointer->Type();
+}
+
+std::string StylesheetReference::Href() const
+{
+	return m_tiXmlPointer->Href();
+}
+
+//*****************************************************************************
+
+Exception::Exception(const std::string &details)
+:
+m_details( details )
+{
+
+}
+
+Exception::~Exception() throw()
+{
+}
+
+const char* Exception::what() const throw()
+{
+	return m_details.c_str();
+}
+
+//*****************************************************************************
+
+TiCppRC::TiCppRC()
+{
+	// Spawn reference counter for this object
+	m_tiRC = new TiCppRCImp( this );
+}
+
+void TiCppRC::DeleteSpawnedWrappers()
+{
+	std::vector< Base* >::reverse_iterator wrapper;
+	for ( wrapper = m_spawnedWrappers.rbegin(); wrapper != m_spawnedWrappers.rend(); ++wrapper )
+	{
+		delete *wrapper;
+	}
+	m_spawnedWrappers.clear();
+}
+		
+TiCppRC::~TiCppRC()
+{	
+	DeleteSpawnedWrappers();
+	
+	// Set pointer held by reference counter to NULL
+	this->m_tiRC->Nullify();
+
+	// Decrement reference - so reference counter will delete itself if necessary
+	this->m_tiRC->DecRef();
+}
+
+//*****************************************************************************
+
+TiCppRCImp::TiCppRCImp( TiCppRC* tiCppRC )
+	: m_count( 1 ), m_tiCppRC ( tiCppRC )
+{
+}
+
+void TiCppRCImp::IncRef()
+{
+	m_count++;
+}
+
+void TiCppRCImp::DecRef()
+{
+	m_count--;
+	if ( 0 == m_count )
+	{
+		delete m_tiCppRC;
+		delete this;
+	}
+}
+
+void TiCppRCImp::InitRef()
+{
+	m_count = 1;
+}
+
+void TiCppRCImp::Nullify()
+{
+	m_tiCppRC = 0;
+}
+
+TiCppRC* TiCppRCImp::Get()
+{
+	return m_tiCppRC;
+}
+
+bool TiCppRCImp::IsNull()
+{
+	return 0 == m_tiCppRC;
+}
+
+#endif // TIXML_USE_TICPP
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/ticpp.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/ticpp.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/ticpp.h	(revision 11817)
@@ -0,0 +1,1907 @@
+/*
+http://code.google.com/p/ticpp/
+Copyright (c) 2006 Ryan Pusztai, Ryan Mulder
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/**
+@copydoc ticpp
+@file
+@author		Ryan Pusztai
+@author		Ryan Mulder
+@date		04/11/2006
+
+@version	0.04a by edam@waxworlds.org: based Exception based on std::exception; added stream
+					<< and >> support; added Document::Parse(); bug fix; improved THROW() macro.
+@version	0.04 Added NodeImp class. Also made all the classes inherit from NodeImp.
+@version	0.03 Added Declaration class
+@version	0.02 Added Element class
+@version	0.01 Added Exception class, Document class
+
+@todo add UNKNOWN support. See ticpp::NodeFactory.
+@todo add TYPECOUNT support. See ticpp::NodeFactory.
+@todo Add a quick reference
+*/
+#ifdef TIXML_USE_TICPP
+
+#ifndef TICPP_INCLUDED
+#define TICPP_INCLUDED
+
+#include "tinyxml.h"
+#include <sstream>
+#include <vector>
+#include <memory>
+#include <exception>
+#include <typeinfo>
+
+/**
+@subpage ticpp is a TinyXML wrapper that uses a lot more C++ ideals.
+It throws exceptions, uses templates, is in its own name space, and
+<b>requires</b> STL (Standard Template Library). This is done to ease the use
+of getting values in and out of the xml.
+
+If you don't perfer to use some of the concepts just don't use it.
+It is just a wrapper that extends TinyXML. It doesn't actually change
+any of TinyXML.
+*/
+namespace ticpp
+{
+    /**
+	This is a ticpp exception class
+	*/
+	class Exception : public std::exception
+	{
+	public:
+		/**
+		Construct an exception with a message
+		*/
+		Exception( const std::string& details );
+		~Exception() throw();
+
+		/// Override std::exception::what() to return m_details
+		const char* what() const throw();
+
+		std::string m_details; /**< Exception Details */
+	};
+
+	/**
+	This allows you to stream your exceptions in.
+	It will take care of the conversion	and throwing the exception.
+	*/
+	#define TICPPTHROW( message ) 											\
+	{																		\
+		std::ostringstream full_message;									\
+		std::string file( __FILE__ );										\
+		file = file.substr( file.find_last_of( "\\/" ) + 1 );				\
+		full_message << message << " <" << file << "@" << __LINE__ << ">";	\
+		full_message << BuildDetailedErrorString();							\
+		throw Exception( full_message.str() );								\
+	}
+
+	// Forward Declarations for Visitor, and others.
+	class Document;
+	class Element;
+	class Declaration;
+	class StylesheetReference;
+	class Text;
+	class Comment;
+	class Attribute;
+
+	/** Wrapper around TiXmlVisitor */
+	class Visitor : public TiXmlVisitor
+	{
+	public:
+		// Overload the TiXmlVisitor functions, wrap objects, call ticpp::Visitor functions
+		/// @internal
+		virtual bool VisitEnter( const TiXmlDocument& doc );
+		/// @internal
+		virtual bool VisitExit( const TiXmlDocument& doc );
+		/// @internal
+		virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
+		/// @internal
+		virtual bool VisitExit( const TiXmlElement& element );
+		/// @internal
+		virtual bool Visit( const TiXmlDeclaration& declaration );
+		/// @internal
+		virtual bool Visit( const TiXmlStylesheetReference& stylesheet );
+		/// @internal
+		virtual bool Visit( const TiXmlText& text );
+		/// @internal
+		virtual bool Visit( const TiXmlComment& comment );
+
+	public:
+		/// Visit a document.
+		virtual bool VisitEnter( const Document& /*doc*/ )			{ return true; }
+		/// Visit a document.
+		virtual bool VisitExit( const Document& /*doc*/ )			{ return true; }
+
+		/// Visit an element.
+		virtual bool VisitEnter( const Element& /*element*/, const Attribute* /*firstAttribute*/ )	{ return true; }
+		/// Visit an element.
+		virtual bool VisitExit( const Element& /*element*/ )		{ return true; }
+
+		/// Visit a declaration
+		virtual bool Visit( const Declaration& /*declaration*/ )	{ return true; }
+		/// Visit a stylesheet reference
+		virtual bool Visit( const StylesheetReference& /*stylesheet*/ )	{ return true; }
+		/// Visit a text node
+		virtual bool Visit( const Text& /*text*/ )					{ return true; }
+		/// Visit a comment node
+		virtual bool Visit( const Comment& /*comment*/ )			{ return true; }
+	};
+
+	/** Wrapper around TiXmlBase */
+	class Base
+	{
+	public:
+
+		/**
+		Converts any class with a proper overload of the << opertor to a std::string
+		@param value The value to be converted
+		@throws Exception When value cannot be converted to a std::string
+		*/
+		template < class T >
+			std::string ToString( const T& value ) const
+		{
+			std::stringstream convert;
+			convert << value;
+			if ( convert.fail() )
+			{
+				TICPPTHROW( "Could not convert value to text" );
+			}
+			return convert.str();
+		}
+
+		std::string ToString( const std::string& value ) const
+		{
+			return value;
+		}
+
+		/**
+		Converts a std::string to any class with a proper overload of the >> opertor
+		@param temp			The string to be converted
+		@param out	[OUT]	The container for the returned value
+		@throws Exception When temp cannot be converted to the target type
+		*/
+		template < class T >
+			void FromString( const std::string& temp, T* out ) const
+		{
+			std::istringstream val( temp );
+			val >> *out;
+
+			if ( val.fail() )
+			{
+				TICPPTHROW( "Could not convert \"" << temp << "\" to target type" );
+			}
+		}
+
+		/**
+		Specialization for std::string
+		*/
+		void FromString( const std::string& temp, std::string* out ) const
+		{
+			*out = temp;
+		}
+
+		/**
+		Return the position, in the original source file, of this node or attribute.
+		Wrapper around TiXmlBase::Row()
+		*/
+		int Row() const
+		{
+			return GetBasePointer()->Row();
+		}
+
+		/**
+		Return the position, in the original source file, of this node or attribute.
+		Wrapper around TiXmlBase::Row()
+		*/
+		int Column() const
+		{
+			return GetBasePointer()->Column();
+		}
+
+		/**
+		Compare internal TiXml pointers to determine is both are wrappers around the same node
+		*/
+		bool operator == ( const Base& rhs ) const
+		{
+			return ( GetBasePointer() == rhs.GetBasePointer() );
+		}
+
+		/**
+		Compare internal TiXml pointers to determine is both are wrappers around the same node
+		*/
+		bool operator != ( const Base& rhs ) const
+		{
+			return ( GetBasePointer() != rhs.GetBasePointer() );
+		}
+
+		/**
+		Builds detailed error string using TiXmlDocument::Error() and others
+		*/
+		std::string BuildDetailedErrorString() const
+		{
+			std::ostringstream full_message;
+			#ifndef TICPP_NO_RTTI
+			TiXmlNode* node = dynamic_cast< TiXmlNode* >( GetBasePointer() );
+			if ( node != 0 )
+			{
+				TiXmlDocument* doc = node->GetDocument();
+				if ( doc != 0 )
+				{
+					if ( doc->Error() )
+					{
+						full_message 	<< "\nDescription: " << doc->ErrorDesc()
+										<< "\nFile: " << (strlen( doc->Value() ) > 0 ? doc->Value() : "<unnamed-file>")
+										<< "\nLine: " << doc->ErrorRow()
+										<< "\nColumn: " << doc->ErrorCol();
+					}
+				}
+			}
+			#endif
+			return full_message.str();
+		}
+
+		/**
+		Destructor
+		*/
+		virtual ~Base()
+		{
+		}
+
+	protected:
+		mutable TiCppRCImp* m_impRC;	/**< Holds status of internal TiXmlPointer - use this to determine if object has been deleted already */
+
+		/**
+		@internal
+		Updates the pointer to the reference counter to point at the counter in the new node.
+
+		@param node TiXmlBase containing the new reference counter
+		*/
+		void SetImpRC( TiXmlBase* node )
+		{
+			m_impRC = node->m_tiRC;
+		}
+
+		void ValidatePointer() const
+		{
+			if ( m_impRC->IsNull() )
+			{
+				TICPPTHROW( "Internal TiXml Pointer is NULL" );
+			}
+		}
+
+		/**
+		@internal
+		Get internal TiXmlBase*
+		*/
+		virtual TiXmlBase* GetBasePointer() const = 0;
+	};
+
+	/**
+	Wrapper around TiXmlAttribute
+	*/
+	class Attribute : public Base
+	{
+	private:
+		TiXmlAttribute* m_tiXmlPointer;
+		TiXmlBase* GetBasePointer() const
+		{
+			ValidatePointer();
+			return m_tiXmlPointer;
+		}
+
+	public:
+		/**
+		Construct an empty attribute.
+		*/
+		Attribute();
+
+		/**
+		Construct an attribute with @a name and @a value
+
+		@param name The name of the attribute
+		@param value The value of the attribute
+		*/
+		Attribute( const std::string& name, const std::string& value );
+
+		/**
+		@internal
+		Construct an attribute with the internal pointer
+
+		@param attribute The internal pointer
+		*/
+		Attribute( TiXmlAttribute* attribute );
+
+		/**
+		Get the value of this attribute
+		Uses Base::FromString to convert TiXmlAttribute::ValueStr from a std::string,
+		and puts it in the passed pointer.
+
+		@param value [OUT] A pointer to fill with the value
+		*/
+		template < class T >
+			void GetValue( T* value ) const
+		{
+			ValidatePointer();
+			FromString( m_tiXmlPointer->ValueStr(), value );
+		}
+
+		/**
+		Get the value of this attribute.
+		Simple wrapper for TiXmlAttribute::ValueStr.
+
+		@see GetValue
+		*/
+		std::string Value() const;
+
+		/**
+		Set the value of this node.
+		Uses Base::ToString to convert value to a std::string, then calls TiXmlAttribute::SetValue.
+
+		@param value The value to set
+		*/
+		template < class T >
+			void SetValue( const T& value )
+		{
+			ValidatePointer();
+			m_tiXmlPointer->SetValue( ToString( value ) );
+		}
+
+		/**
+		Get the value of this attribute
+		Uses Base::FromString to convert TiXmlAttribute::Name from a std::string,
+		and puts it in the passed pointer.
+
+		@param name [OUT] A pointer to fill with the name
+		*/
+		template < class T >
+			void GetName( T* name ) const
+		{
+			ValidatePointer();
+			FromString( m_tiXmlPointer->Name(), name );
+		}
+
+		/**
+		Get the value of this attribute.
+		Simple wrapper for TiXmlAttribute::Name.
+
+		@see GetName
+		*/
+		std::string Name() const;
+
+		/**
+		Set the value of this attribute.
+		Uses Base::ToString to convert @a name to a std::string, then calls TiXmlAttribute::SetName.
+
+		@param name The name to set
+		*/
+		template < class T >
+			void SetName( const T& name )
+		{
+			ValidatePointer();
+			m_tiXmlPointer->SetName( ToString( name ) );
+		}
+
+		/**
+		@internal
+		Updates the reference count for the old and new pointers.
+		*/
+		void operator=( const Attribute& copy );
+
+		/**
+		@internal
+		Updates the reference count for the old and new pointers.
+		*/
+		Attribute( const Attribute& copy );
+
+		/*
+		Decrements reference count.
+		*/
+		~Attribute();
+
+		/**
+		Get the next sibling attribute in the DOM.
+		*/
+		Attribute* Next( bool throwIfNoAttribute = true ) const;
+
+		/**
+		Get the previous sibling attribute in the DOM.
+		*/
+		Attribute* Previous( bool throwIfNoAttribute = true ) const;
+
+		/**
+		@internal
+		Just for Iterator<>
+
+		@param next [OUT] The pointer to the next valid attribute
+		@return true if there is a next attribute, false if not
+		*/
+		void IterateNext( const std::string&, Attribute** next ) const;
+
+		/**
+		@internal
+		Just for Iterator<>
+
+		@param previous [OUT] The pointer to the previous valid attribute
+		@return true if there is a previous attribute, false if not
+		*/
+		void IteratePrevious( const std::string&, Attribute** previous ) const;
+
+		/**
+		All TinyXml classes can print themselves to a filestream.
+		*/
+		virtual void Print( FILE* file, int depth ) const;
+
+	private:
+
+		/**
+		@internal
+		Sets the internal pointer.
+		Saves a copy of the pointer to the RC object.
+
+		@param newPointer TiXmlAttribute* to set.
+		*/
+		void SetTiXmlPointer( TiXmlAttribute* newPointer );
+	};
+
+	/**
+	Wrapper around TiXmlNode
+	*/
+	class Node : public Base
+	{
+	public:
+
+		/**
+		Get the value of this node
+		Uses Base::FromString to convert TiXmlNode::ValueStr from a std::string,
+		and puts it in the passed pointer.
+
+		@param value [OUT] A pointer to fill with the value
+		*/
+		template < class T >
+			void GetValue( T* value) const
+		{
+			FromString( GetTiXmlPointer()->ValueStr(), value );
+		}
+
+		/**
+		Get the value of this node.
+		Simple wrapper for TiXmlNode::ValueStr.
+
+		@see GetValue
+		*/
+		std::string Value() const;
+
+		/**
+		Set the value of this node.
+		Uses Base::ToString to convert value to a std::string, then calls TiXmlNode::SetValue.
+
+		@param value The value to set
+		*/
+		template < class T >
+			void SetValue( const T& value )
+		{
+			GetTiXmlPointer()->SetValue( ToString( value ) );
+		}
+
+		/**
+		Clear all Nodes below this.
+		Simple wrapper for TiXmlNode::Clear.
+		*/
+		void Clear();
+
+		/**
+		The Parent of this Node.
+		Simple wrapper for TiXmlNode::Parent.
+
+		@param throwIfNoParent [DEF] If true, throws when Parent = NULL.
+		@return The parent of this node, NULL if there is no Parent.
+		@throws Exception When throwIfNoParent is true, and TiXmlNode::Parent returns Null.
+		*/
+		Node* Parent( bool throwIfNoParent = true ) const;
+
+		/**
+		The first child of this node.
+
+		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no children.
+		@return Pointer to child, Null if no children and 'throwIfNoChildren' is false.
+		@throws Exception When throwIfNoChildren is true, and TiXmlNode::FirstChild returns Null.
+
+		@see TiXmlNode::FirstChild
+		*/
+		Node* FirstChild( bool throwIfNoChildren = true ) const;
+
+		/**
+		@internal
+		The first child of this node with the matching @a value.
+
+		@overload
+		@param value				Value to match.
+		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
+
+		@see FirstChild( bool throwIfNoChildren = true )
+		*/
+		Node* FirstChild( const char* value, bool throwIfNoChildren = true ) const;
+
+		/**
+		The first child of this node with the matching @a value.
+
+		@overload
+		@param value				Value to match.
+		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
+
+		@see FirstChild( const char* value, bool throwIfNoChildren = true )
+		*/
+		Node* FirstChild( const std::string& value, bool throwIfNoChildren = true ) const;
+
+		/**
+		The last child of this node.
+
+		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no children.
+		@return Pointer to child, Null if no children and 'throwIfNoChildren' is false.
+		@throws Exception When throwIfNoChildren is true, and TiXmlNode::LastChild returns Null.
+
+		@see TiXmlNode::LastChild
+		*/
+		Node* LastChild( bool throwIfNoChildren = true ) const;
+
+		/**
+		@internal
+		The last child of this node with the matching @a value.
+
+		@overload
+		@param value				Value to match.
+		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
+
+		@see LastChild( bool throwIfNoChildren = true )
+		*/
+		Node* LastChild( const char* value, bool throwIfNoChildren = true ) const;
+
+		/**
+		The last child of this node with the matching @a value.
+
+		@overload
+		@param value				Value to match.
+		@param throwIfNoChildren	[DEF] If true, will throw an exception if there are no children.
+
+		@see LastChild( const char* value, bool throwIfNoChildren = true )
+		*/
+		Node* LastChild( const std::string& value, bool throwIfNoChildren = true ) const;
+
+		/**
+		An alternate way to walk the children of a node.
+		Simple wrapper for TiXmlNode::IterateChildren.
+
+		@param previous The previous Node* that was returned from IterateChildren.
+		@return NULL When there are no more children.
+		*/
+		Node* IterateChildren( Node* previous ) const;
+
+		/**
+		This flavor of IterateChildren searches for children with a particular @a value.
+		Simple wrapper for TiXmlNode::IterateChildren.
+
+		@param value	The value you want to search for.
+		@param previous The previous Node* that was returned from IterateChildren.
+		@return NULL When there are no more children.
+		*/
+		Node* IterateChildren( const std::string& value, Node* previous ) const;
+
+		/**
+		Adds a child past the LastChild.
+		Throws if you try to insert a document.
+
+		@note This takes a copy of @a addThis so it is not as efficiant as LinkEndChild.
+		@param addThis Node to insert.
+		@throws Exception When TiXmlNode::InsertEndChild returns Null
+
+		@see LinkEndChild
+		@see TiXmlNode::InsertEndChild
+		*/
+		Node* InsertEndChild( const Node& addThis );
+
+		/**
+		Adds a child past the LastChild.
+		Throws if you try to link a document.
+
+		@param childNode Node to link.
+		@throws Exception When TiXmlNode::LinkEndChild returns Null.
+
+		@see InsertEndChild
+		@see TiXmlNode::LinkEndChild
+		*/
+		Node* LinkEndChild( Node* childNode );
+
+		/**
+		Adds a child before the specified child.
+		Throws if you try to insert a document.
+
+		@param beforeThis	Node that will have @a addThis linked before.
+		@param addThis		Node to insert before.
+		@throws Exception When TiXmlNode::InsertBeforeChild returns Null.
+
+		@see InsertAfterChild
+		@see TiXmlNode::InsertBeforeChild
+		*/
+		Node* InsertBeforeChild( Node* beforeThis, const Node& addThis );
+
+		/**
+		Adds a child after the specified child.
+		Throws if you try to insert a document.
+
+		@param afterThis	Node that will have @a addThis linked after.
+		@param addThis		Node to insert after.
+		@throws Exception When TiXmlNode::InsertAfterChild returns Null.
+
+		@see InsertBeforeChild
+		@see TiXmlNode::InsertAfterChild
+		*/
+		Node* InsertAfterChild( Node* afterThis, const Node& addThis );
+
+		/**
+		Replace a child of this node.
+		Throws if you try to replace with a document.
+
+		@param replaceThis	Node to replace.
+		@param withThis		Node that is replacing @a replaceThis.
+		@throws Exception When TiXmlNode::ReplaceChild returns Null.
+
+		@see TiXmlNode::ReplaceChild
+		*/
+		Node* ReplaceChild( Node* replaceThis, const Node& withThis );
+
+		/**
+		Delete a child of this node.
+
+		@param removeThis Node to delete.
+		@throws Exception When removeThis is not a child of this Node.
+
+		@see TiXmlNode::RemoveChild
+		*/
+		void RemoveChild( Node* removeThis );
+
+		/**
+		Navigate to a sibling node.
+		Wrapper around TiXmlNode::PreviousSibling.
+
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
+		@return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false.
+		@throws Exception When TiXmlNode::PreviousSibling returns Null and 'throwIfNoSiblings' is true.
+		*/
+		Node* PreviousSibling( bool throwIfNoSiblings = true ) const;
+
+		/**
+		Navigate to a sibling node with the given @a value.
+
+		@overload
+		@param value The value of the node to look for.
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
+
+		@see PreviousSibling( bool throwIfNoSiblings )
+		*/
+		Node* PreviousSibling( const std::string& value, bool throwIfNoSiblings = true ) const;
+
+		/**
+		@internal
+		Navigate to a sibling node with the given @a value.
+
+		@overload
+		@param value The value of the node to look for.
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
+
+		@see PreviousSibling( const std::string& value, bool throwIfNoSiblings )
+		*/
+		Node* PreviousSibling( const char* value, bool throwIfNoSiblings = true ) const;
+
+		/**
+		Navigate to a sibling node.
+		Wrapper around TiXmlNode::NextSibling.
+
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
+		@return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false.
+		@throws Exception When TiXmlNode::NextSibling returns Null and 'throwIfNoSiblings' is true.
+		*/
+		Node* NextSibling( bool throwIfNoSiblings = true ) const;
+
+		/**
+		Navigate to a sibling node with the given @a value.
+
+		@overload
+		@param value The value of the node to look for.
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
+
+		@see NextSibling( bool throwIfNoSiblings )
+		*/
+		Node* NextSibling( const std::string& value, bool throwIfNoSiblings = true ) const;
+
+		/**
+		@internal
+		Navigate to a sibling node with the given @a value.
+
+		@overload
+		@param value The value of the node to look for.
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no siblings.
+
+		@see NextSibling( const std::string& value, bool throwIfNoSiblings )
+		*/
+		Node* NextSibling( const char* value, bool throwIfNoSiblings = true ) const;
+
+		/**
+		@internal
+		Just for Iterator<>
+
+		@param value The value of nodes to iterate through
+		@param next [OUT] The pointer to the first valid node
+		*/
+		template < class T >
+			void IterateFirst( const std::string& value, T** first ) const
+		{
+			*first = 0;
+			for( Node* child = FirstChild( value, false ); child; child = child->NextSibling( value, false ) )
+			{
+				*first = dynamic_cast< T* >( child );
+				if ( 0 != *first )
+				{
+					return;
+				}
+			}
+		}
+
+		virtual	void IterateFirst( const std::string&, Attribute** ) const
+		{
+			TICPPTHROW( "Attributes can only be iterated with Elements." )
+		}
+
+		/**
+		@internal
+		Just for Iterator<>
+
+		@param value The value of nodes to iterate through
+		@param next [OUT] The pointer to the next valid node
+		*/
+		template < class T >
+			void IterateNext( const std::string& value, T** next ) const
+		{
+			Node* sibling = NextSibling( value, false );
+			*next = dynamic_cast< T* >( sibling );
+
+			while ( ( 0 != sibling ) && ( 0 == *next ) )
+			{
+				sibling = sibling->NextSibling( value, false );
+				*next = dynamic_cast< T* >( sibling );
+			}
+		}
+
+		/**
+		@internal
+		Just for Iterator<>
+
+		@param value The value of nodes to iterate through
+		@param previous [OUT] The pointer to the previous valid node
+		*/
+		template < class T >
+			void IteratePrevious( const std::string& value, T** previous  ) const
+		{
+			Node* sibling = PreviousSibling( value, false );
+			*previous = dynamic_cast< T* >( sibling );
+
+			while ( ( 0 != sibling ) && ( 0 == *previous ) )
+			{
+				sibling = sibling->PreviousSibling( value, false );
+				*previous = dynamic_cast< T* >( sibling );
+			}
+		}
+
+		/**
+		Navigate to a sibling element.
+		Wrapper around TiXmlNode::NextSibling.
+
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling element.
+		@return Pointer to sibling, Null if no siblings and 'throwIfNoSiblings' is false.
+		@throws Exception When TiXmlNode::NextSibling returns Null and 'throwIfNoSiblings' is true.
+		*/
+		Element* NextSiblingElement( bool throwIfNoSiblings = true ) const;
+
+		/**
+		Navigate to a sibling element with the given @a value.
+
+		@overload
+		@param value The value of the element to look for.
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling elements.
+		@see NextSiblingElement( bool throwIfNoSiblings )
+		*/
+		Element* NextSiblingElement( const std::string& value, bool throwIfNoSiblings = true ) const;
+
+		/**
+		@internal
+		Navigate to a sibling element with the given @a value.
+
+		@overload
+		@param value The value of the element to look for.
+		@param throwIfNoSiblings [DEF] If true, will throw an exception if there are no sibling elements.
+
+		@see NextSiblingElement( const std::string& value, bool throwIfNoSiblings )
+		*/
+		Element* NextSiblingElement( const char* value, bool throwIfNoSiblings = true ) const;
+
+		/**
+		The first child element of this node.
+
+		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children.
+		@return Pointer to child, Null if no element children and 'throwIfNoChildren' is false.
+		@throws Exception When throwIfNoChildren is true, and TiXmlNode::FirstChildElement returns Null.
+
+		@see TiXmlNode::FirstChildElement
+		*/
+		Element* FirstChildElement( bool throwIfNoChildren = true ) const;
+
+		/**
+		@internal
+		The first child element of this node with the matching @a value.
+
+		@overload
+		@param value Value to match.
+		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children.
+
+		@see FirstChildElement( bool throwIfNoChildren = true )
+		*/
+		Element* FirstChildElement( const char* value, bool throwIfNoChildren = true ) const;
+
+		/**
+		The first child element of this node with the matching @a value.
+
+		@overload
+		@param value Value to match.
+		@param throwIfNoChildren [DEF] If true, will throw an exception if there are no element children.
+
+		@see FirstChildElement( const char* value, bool throwIfNoChildren = true )
+		*/
+		Element* FirstChildElement( const std::string& value, bool throwIfNoChildren = true ) const;
+
+		/**
+		Query the type (as TiXmlNode::NodeType ) of this node.
+		*/
+		int Type() const;
+
+		/**
+		Return a pointer to the Document this node lives in.
+
+		@param throwIfNoDocument [DEF] If true, will throw an exception if this node is not linked under a Document.
+		@return A pointer to the Document this node lives in, NULL if not linked under a Document, and 'throwIfNoDocument' is false.
+		@throws Exception When this node is not linked under a Document and 'throwIfNoDocument' is true.
+		*/
+		Document* GetDocument( bool throwIfNoDocument = true ) const;
+
+		/**
+		Check if this node has no children.
+
+		@return true if this node has no children.
+		*/
+		bool NoChildren() const;
+
+		#ifndef TICPP_NO_RTTI
+		/**
+		Pointer conversion ( NOT OBJECT CONVERSION ) - replaces TiXmlNode::ToElement, TiXmlNode::ToDocument, TiXmlNode::ToComment, etc.
+
+		@throws Exception When the target is not an object of class T
+		@warning Some ancient compilers do not support explicit specification of member template arguments, which this depends on ( e.g. VC6 ).
+		*/
+		template < class T >
+			T* To() const
+		{
+			T* pointer = dynamic_cast< T* >( this );
+			if ( 0 == pointer )
+			{
+				std::string thisType = typeid( this ).name();
+				std::string targetType = typeid( T ).name();
+				std::string thatType = typeid( *this ).name();
+				TICPPTHROW( "The " << thisType.substr( 6 ) << " could not be casted to a " << targetType.substr( 6 )
+					<< " *, because the target object is not a " << targetType.substr( 6 ) << ". (It is a " << thatType.substr( 6 ) << ")" );
+			}
+			return pointer;
+		}
+		#endif
+
+		/**
+		Pointer conversion - replaces TiXmlNode::ToDocument.
+
+		@throws Exception When this node is not a Document.
+		*/
+		Document* ToDocument() const;
+
+		/**
+		Pointer conversion - replaces TiXmlNode::ToElement.
+
+		@throws Exception When this node is not a Element.
+		*/
+		Element* ToElement() const;
+
+		/**
+		Pointer conversion - replaces TiXmlNode::ToComment.
+
+		@throws Exception When this node is not a Comment.
+		*/
+		Comment* ToComment() const;
+
+		/**
+		Pointer conversion - replaces TiXmlNode::ToText.
+
+		@throws Exception When this node is not a Text.
+		*/
+		Text* ToText() const;
+
+		/**
+		Pointer conversion - replaces TiXmlNode::ToDeclaration.
+
+		@throws Exception When this node is not a Declaration.
+		*/
+		Declaration* ToDeclaration() const;
+
+		/**
+		Pointer conversion - replaces TiXmlNode::ToStylesheetReference.
+
+		@throws Exception When this node is not a StylesheetReference.
+		*/
+		StylesheetReference* ToStylesheetReference() const;
+
+		/**
+		Create an exact duplicate of this node and return it.
+
+		@note Using unique_ptr to manage the memory declared on the heap by TiXmlNode::Clone.
+		@code
+		// Now using clone
+		ticpp::Document doc( "C:\\Test.xml" );
+		ticpp::Node* sectionToClone;
+		sectionToClone = doc.FirstChild( "settings" );
+		std::unique_ptr< ticpp::Node > clonedNode = sectionToClone->Clone();
+		// Now you can use the clone.
+		ticpp::Node* node2 = clonedNode->FirstChildElement()->FirstChild();
+		...
+		// After the variable clonedNode goes out of scope it will automatically be cleaned up.
+		@endcode
+		@return Pointer the duplicate node.
+		*/
+		std::unique_ptr< Node > Clone() const;
+
+		/**
+		Accept a hierchical visit the nodes in the TinyXML DOM.
+		@return The boolean returned by the visitor.
+		*/
+		bool Accept( TiXmlVisitor* visitor ) const;
+
+		/**
+ 		Stream input operator.
+ 		*/
+ 		friend std::istream& operator >>( std::istream& in, Node& base )
+ 		{
+ 			in >> *base.GetTiXmlPointer();
+ 			return in;
+ 		}
+
+ 		/**
+ 		Stream output operator.
+ 		*/
+ 		friend std::ostream& operator <<( std::ostream& out, const Node& base )
+ 		{
+ 			out << *base.GetTiXmlPointer();
+ 			return out;
+ 		}
+
+	protected:
+		/**
+		@internal
+		Allows NodeImp to use Node*'s.
+		*/
+		virtual TiXmlNode* GetTiXmlPointer() const = 0;
+
+		TiXmlBase* GetBasePointer() const
+		{
+			return GetTiXmlPointer();
+		}
+
+		/**
+		@internal
+		Constructs the correct child of Node, based on the Type of the TiXmlNode*.
+		*/
+		Node* NodeFactory( TiXmlNode* tiXmlNode, bool throwIfNull = true, bool rememberSpawnedWrapper = true ) const;
+
+	};
+
+	/** Iterator for conveniently stepping through Nodes and Attributes.
+	TinyXML++ introduces iterators:
+	@code
+	ticpp::Iterator< ticpp::Node > child;
+	for ( child = child.begin( parent ); child != child.end(); child++ )
+	@endcode
+
+	Iterators have the added advantage of filtering by type:
+	@code
+	// Only iterates through Comment nodes
+	ticpp::Iterator< ticpp::Comment > child;
+	for ( child = child.begin( parent ); child != child.end(); child++ )
+	@endcode
+
+	@code
+	// Only iterates through Element nodes with value "ElementValue"
+	ticpp::Iterator< ticpp::Element > child( "ElementValue" );
+	for ( child = child.begin( parent ); child != child.end(); child++ )
+	@endcode
+
+	Finally, Iterators also work with Attributes
+	@code
+	ticpp::Iterator< ticpp::Attribute > attribute;
+	for ( attribute = attribute.begin( element ); attribute != attribute.end(); attribute++ )
+	@endcode
+	*/
+	template < class T = Node >
+		class Iterator
+	{
+	private:
+		T* m_p;					/**< Internal Pointer */
+		std::string m_value;	/**< Value for NextSibling  calls */
+
+	public:
+
+		/**
+		For for loop comparisons.
+		@param parent The parent of the nodes to iterate.
+		@return The first child of type T.
+		@code
+		ticpp::Iterator< ticpp::Node > child;
+		for ( child = child.begin( parent ); child != child.end(); child++ )
+		@endcode
+		*/
+		T* begin( const Node* parent ) const
+		{
+			T* pointer;
+			parent->IterateFirst( m_value, &pointer );
+			return pointer;
+		}
+
+		/**
+		For for loop comparisons.
+		@return NULL
+		@code
+		ticpp::Iterator< ticpp::Node > child;
+		for ( child = child.begin( parent ); child != child.end(); child++ )
+		@endcode
+		*/
+		T* end() const
+		{
+			return 0;
+		}
+
+		/** Constructor.
+		@param value If not empty, this iterator will only visit nodes with matching value.
+		@code
+		// Only iterates through Element nodes with value "ElementValue"
+		ticpp::Iterator< ticpp::Element > child( "ElementValue" );
+		for ( child = child.begin( parent ); child != child.end(); child++ )
+		@endcode
+		*/
+		Iterator( const std::string& value = "" )
+			: m_p( 0 ), m_value( value )
+		{
+		}
+
+		/// Constructor
+		Iterator( T* node, const std::string& value = "" )
+			: m_p( node ), m_value( value )
+		{
+		}
+
+		/// Constructor
+		Iterator( const Iterator& it )
+			: m_p( it.m_p ), m_value( it.m_value )
+		{
+		}
+
+		/**
+		Gets internal pointer.
+		@return The internal pointer.
+		*/
+		T* Get() const
+		{
+			return m_p;
+		}
+
+		/** Sets internal pointer */
+		Iterator& operator=( const Iterator& it )
+		{
+			m_p = it.m_p;
+			m_value = it.m_value;
+			return *this;
+		}
+
+		/** Sets internal pointer */
+		Iterator& operator=( T* p )
+		{
+			m_p = p;
+			return *this;
+		}
+
+		/** Sets internal pointer to the Next Sibling, or Iterator::END, if there are no more siblings */
+		Iterator& operator++()
+		{
+			m_p->IterateNext( m_value, &m_p );
+			return *this;
+		}
+
+		/** Sets internal pointer to the Next Sibling, or Iterator::END, if there are no more siblings */
+		Iterator operator++(int)
+		{
+			Iterator tmp(*this);
+			++(*this);
+			return tmp;
+		}
+
+		/** Sets internal pointer to the Previous Sibling, or Iterator::END, if there are no prior siblings */
+		Iterator& operator--()
+		{
+			m_p->IteratePrevious( m_value, &m_p );
+			return *this;
+		}
+
+		/** Sets internal pointer to the Previous Sibling, or Iterator::END, if there are no prior siblings */
+		Iterator operator--(int)
+		{
+			Iterator tmp(*this);
+			--(*this);
+			return tmp;
+		}
+
+		/** Compares internal pointer */
+		bool operator!=( const T* p ) const
+		{
+			if ( m_p == p )
+			{
+				return false;
+			}
+			if ( 0 == m_p || 0 == p )
+			{
+				return true;
+			}
+			return *m_p != *p;
+		}
+
+		/** Compares internal pointer */
+		bool operator!=( const Iterator& it ) const
+		{
+			return operator!=( it.m_p );
+		}
+
+		/** Compares internal pointer* */
+		bool operator==( T* p ) const
+		{
+			if ( m_p == p )
+			{
+				return true;
+			}
+			if ( 0 == m_p || 0 == p )
+			{
+				return false;
+			}
+			return *m_p == *p;
+		}
+
+		/** Compares internal pointer */
+		bool operator==( const Iterator& it ) const
+		{
+			return operator==( it.m_p );
+		}
+
+		/** So Iterator behaves like a STL iterator */
+		T* operator->() const
+		{
+			return m_p;
+		}
+
+		/** So Iterator behaves like a STL iterator */
+		T& operator*() const
+		{
+			return *m_p;
+		}
+	};
+
+	/** Implementation of Node wrapper */
+	template < class T >
+		class NodeImp : public Node
+	{
+	protected:
+
+		T* m_tiXmlPointer;		/**< Internal pointer to the TiXml Class which is being wrapped */
+
+	public:
+		/**
+		@internal
+		Gets the internal TinyXML pointer.
+
+		@returns The internal TiXmlNode*.
+		*/
+		TiXmlNode* GetTiXmlPointer() const
+		{
+			ValidatePointer();
+			return m_tiXmlPointer;
+		}
+	protected:
+
+		/**
+		@internal
+		Sets the internal pointer.
+		Saves a copy of the pointer to the RC object.
+
+		@param newPointer TiXmlNode* to set.
+		*/
+		void SetTiXmlPointer( T* newPointer )
+		{
+			m_tiXmlPointer = newPointer;
+			SetImpRC( newPointer );
+		}
+
+		/**
+		@internal
+		Constructor used by child classes.
+		*/
+		NodeImp( T* tiXmlPointer )
+		{
+			// Check for NULL pointers
+			if ( 0 == tiXmlPointer )
+			{
+				#ifdef TICPP_NO_RTTI
+					TICPPTHROW( "Can not create TinyXML objext" );
+				#else
+					TICPPTHROW( "Can not create a " << typeid( T ).name() );
+				#endif
+			}
+			SetTiXmlPointer( tiXmlPointer );
+			m_impRC->IncRef();
+		}
+
+		/**
+		@internal
+		Updates the reference count for the old and new pointers.
+		In addition, the spawnedWrappers must be cleared out before a new TiXml object is loaded in.
+		*/
+		virtual void operator=( const NodeImp<T>& copy )
+		{
+			// Dropping the reference to the old object
+			this->m_impRC->DecRef();
+
+			// Pointing to the new Object
+			SetTiXmlPointer( copy.m_tiXmlPointer );
+
+			// The internal tixml pointer changed in the above line
+			this->m_impRC->IncRef();
+		}
+
+		/**
+		@internal
+		Updates the reference count for the old and new pointers.
+		In addition, the spawnedWrappers must be cleared out before a new TiXml object is loaded in
+		*/
+		NodeImp( const NodeImp<T>& copy ) : Node( copy )
+		{
+			// Pointing to the new Object
+			SetTiXmlPointer( copy.m_tiXmlPointer );
+
+			// The internal tixml pointer changed in the above line
+			this->m_impRC->IncRef();
+		}
+
+	public:
+
+		/*
+		Deletes the spawned wrapper objects.
+		Decrements reference count.
+		*/
+		virtual ~NodeImp()
+		{
+			m_impRC->DecRef();
+		}
+	};
+
+	/** Wrapper around TiXmlComment */
+	class Comment : public NodeImp< TiXmlComment >
+	{
+	public:
+
+		/**
+		Constructor.
+		*/
+		Comment();
+
+		/**
+		Constructor.
+		*/
+		Comment( TiXmlComment* comment );
+
+		/**
+		Constructor.
+		*/
+		Comment( const std::string& comment );
+	};
+
+	/** Wrapper around TiXmlText */
+	class Text : public NodeImp< TiXmlText >
+	{
+	public:
+
+		/**
+		Constructor.
+		*/
+		Text();
+
+		/**
+		Constructor.
+		@overload
+		*/
+		Text( TiXmlText* text );
+
+		/**
+		Constructor.
+		@overload
+		*/
+		Text( const std::string& value );
+
+		/**
+		Streams value into a string and creates a Text with it.
+		Uses ToString to covert the parameter to a string.
+
+		@param value The value of the Text node.
+		@throws Exception
+
+		@see TiXmlText
+        */
+		template < class T >
+			Text( const T& value )
+				: NodeImp< TiXmlText >( new TiXmlText( ToString( value ) ) )
+		{
+			m_impRC->InitRef();
+		}
+	};
+
+	/** Wrapper around TiXmlDocument */
+	class Document : public NodeImp< TiXmlDocument >
+	{
+	public:
+		/**
+		Default	Constructor.
+		Create an empty document, that has no name.
+		*/
+		Document();
+
+		/**
+		Constructor.
+		*/
+		Document( TiXmlDocument* document );
+
+		/**
+		Constructor.
+		*/
+		Document( const char* documentName );
+
+		/**
+		 * Constructor.
+		 * Create a document with a name. The name of the document is also the filename of the xml.
+		 * @param documentName Name to set in the Document.
+		 * @note LoadFile() needs to be called to actually load the data from the file specified by documentName
+		 * 		 SaveFile() needs to be called to save data to file specified by documentName.
+		 */
+		Document( const std::string& documentName );
+
+		/**
+		Load a file using the current document value. Throws if load is unsuccessful.
+
+		@param encoding Sets the documents encoding.
+		@see TiXmlEncoding
+		@throws Exception
+		*/
+		void LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+		/**
+		Save a file using the current document value. Throws if it can't save the file.
+
+		@throws Exception
+		*/
+		void SaveFile() const;
+
+		/**
+		Load a file using the given filename. Throws if load is unsuccessful.
+
+		@param filename File to load.
+		@param encoding Sets the documents encoding.
+		@see TiXmlEncoding
+		@throws Exception
+		*/
+		void LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+		/**
+		@copydoc Document::LoadFile( const std::string&, TiXmlEncoding )
+		*/
+		void LoadFile( const char* filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+		/**
+		Save a file using the given filename. Throws if it can't save the file.
+
+		@param filename File to save.
+		@throws Exception
+		*/
+		void SaveFile( const std::string& filename ) const;
+
+		/**
+		Parse the given xml data.
+
+		@param xml Xml to parse.
+		@param throwIfParseError [DEF] If true, throws when there is a parse error.
+		@param encoding Sets the documents encoding.
+		@throws Exception
+		*/
+		void Parse( const std::string& xml, bool throwIfParseError = true, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	};
+
+	/** Wrapper around TiXmlElement */
+	class Element : public NodeImp< TiXmlElement >
+	{
+	public:
+		/**
+		Default Constructor.
+		*/
+		Element();
+
+		/**
+		Default	Constructor. Initializes all the variables.
+		@param value The value of the element.
+		*/
+		Element( const std::string& value );
+
+		/**
+		Default	Constructor. Initializes all the variables.
+		@param value The value of the element.
+		*/
+		Element( const char* value );
+
+		/**
+		Constructor.
+		*/
+		Element( TiXmlElement* element );
+
+		/**
+		Constructor that allows you to set the element text
+		@param value The value of the element.
+		@param text The text to set.
+		*/
+		template < class T >
+			Element( const std::string& value, const T& text )
+			: NodeImp< TiXmlElement >( new TiXmlElement( value ) )
+		{
+			m_impRC->InitRef();
+			SetText( text );
+		}
+
+		/**
+		Access the first attribute in this element.
+
+		@param throwIfNoAttributes [DEF] If true, throws when there are no attributes
+		@return The first attribute, NULL if there are none and @a throwIfNoAttributes is true
+		*/
+		Attribute* FirstAttribute( bool throwIfNoAttributes = true ) const;
+
+		/**
+		Access the last attribute in this element.
+
+		@param throwIfNoAttributes [DEF] If true, throws when there are no attributes
+		@return The last attribute, NULL if there are none and @a throwIfNoAttributes is true
+		*/
+		Attribute* LastAttribute( bool throwIfNoAttributes = true ) const;
+
+		/**
+		@internal
+		Just for Iterator<>
+
+		@param value The value of nodes to iterate through
+		@param next [OUT] The pointer to the first valid node
+		*/
+		void IterateFirst( const std::string&, Attribute** first ) const
+		{
+			*first = 0;
+			for( Attribute* child = FirstAttribute( false ); child; child = child->Next( false ) )
+			{
+				*first = dynamic_cast< Attribute* >( child );
+				if ( 0 != *first )
+				{
+					return;
+				}
+			}
+		}
+
+		/**
+		Sets an attribute of name to a given value.
+		The attribute will be created if it does not exist, or changed if it does.
+		Uses ToString to convert the @a value to a string, so there is no need to use any other SetAttribute methods.
+
+		@see GetAttribute
+		*/
+		template < class T >
+			void SetAttribute ( const std::string& name, const T& value )
+		{
+			ValidatePointer();
+			m_tiXmlPointer->SetAttribute( name, ToString( value ) );
+		}
+
+		/**
+		Gets the text of an Element.
+
+		@param throwIfNotFound	[DEF]	If true, will throw an exception if there is no text in this element
+		@note This only works if the Text is the FirstChild node
+		@throws Exception When there is no text and throwIfNotFound is true
+
+		@see GetText( T* value, bool throwIfNotFound = false )
+		@see GetTextOrDefault
+		@see GetTextOrDefault( T* value, const DefaultT& defaultValue )
+		@see TiXmlElement::GetText
+		*/
+		std::string GetText( bool throwIfNotFound = true ) const
+		{
+			// Get the element's text value as a std::string
+			std::string temp;
+			if ( !GetTextImp( &temp ) )
+			{
+				if ( throwIfNotFound )
+				{
+					TICPPTHROW( "Text does not exists in the current element" );
+				}
+			}
+
+			return temp;
+		}
+
+		/**
+		Gets the text of an Element, if it doesn't exist it will return the defaultValue.
+
+		@param defaultValue			What to put in 'value' if there is no text in this element
+		@note This only works if the Text is the FirstChild node
+
+		@see GetText
+		@see GetText( T* value, bool throwIfNotFound = false )
+		@see GetTextOrDefault( T* value, const DefaultT& defaultValue )
+		@see TiXmlElement::GetText
+		*/
+		std::string GetTextOrDefault( const std::string& defaultValue ) const
+		{
+			// Get the element's text value as a std::string
+			std::string temp;
+			if ( !GetTextImp( &temp ) )
+			{
+				return defaultValue;
+			}
+
+			return temp;
+		}
+
+		/**
+		Gets the text value of an Element, if it doesn't exist it will return the defaultValue.
+		Uses FromString to convert the string to the type of choice
+
+		@param value		[OUT]	The container for the returned value
+		@param defaultValue			What to put in 'value' if there is no text in this element
+		@note This is different than GetText() in that it will covert the text to what ever type you want.
+		@note This only works if the Text is the FirstChild node
+
+		@see GetText
+		@see GetText( T* value, bool throwIfNotFound = false )
+		@see GetTextOrDefault( const std::string& defaultValue )
+		@see TiXmlElement::GetText
+		*/
+		template < class T, class DefaultT >
+			void GetTextOrDefault( T* value, const DefaultT& defaultValue ) const
+		{
+			// Get the element's text value as a std::string
+			std::string temp;
+			if ( !GetTextImp( &temp ) )
+			{
+				// The text value does not exist - set value to the default
+				*value = defaultValue;
+				return;
+			}
+
+			// Stream the value from the string to T
+			FromString( temp, value );
+		}
+
+		/**
+		Gets the text of an Element.
+		Uses FromString to convert the string to the type of choice.
+
+		@param value			[OUT]	The container for the returned value
+		@param throwIfNotFound	[DEF]	If true, will throw an exception if there is no text in this element
+		@note This is different than GetText() in that it will covert the text to what ever type you want
+		@note This only works if the Text is the FirstChild node
+		@throws Exception When there is no text and throwIfNotFound is true
+
+		@see GetText
+		@see GetTextOrDefault
+		@see GetTextOrDefault( T* value, const DefaultT& defaultValue )
+		@see TiXmlElement::GetText
+		*/
+		template< class T >
+			void GetText( T* value, bool throwIfNotFound = true ) const
+		{
+			// Get the element's text value as a std::string
+			std::string temp;
+			if ( !GetTextImp( &temp ) )
+			{
+				if ( throwIfNotFound )
+				{
+					TICPPTHROW( "Text does not exists in the current element" );
+				}
+				else
+				{
+					return;
+				}
+			}
+
+			// Stream the value from the string to T
+			FromString( temp, value );
+		}
+
+		/**
+		Convenience function to set the text of an element.
+		Creates a Text node and inserts it as the first child.
+		Uses ToString to convert the parameter to a string.
+
+		@param value The text to set.
+		*/
+		template < class T >
+			void SetText( const T& value )
+		{
+			ValidatePointer();
+			std::string temp = ToString( value );
+
+			if ( m_tiXmlPointer->NoChildren() )
+			{
+				m_tiXmlPointer->LinkEndChild( new TiXmlText( temp ) );
+			}
+			else
+			{
+				if ( 0 == m_tiXmlPointer->GetText() )
+				{
+					m_tiXmlPointer->InsertBeforeChild( m_tiXmlPointer->FirstChild(), TiXmlText( temp ) );
+				}
+				else
+				{
+					// There already is text, so change it
+					m_tiXmlPointer->FirstChild()->SetValue( temp );
+				}
+			}
+		}
+
+		/**
+		Gets an attribute of @a name from an element, if it doesn't exist it will return the defaultValue.
+		Uses FromString to convert the string to the type of choice.
+
+		@param name			The name of the attribute you are querying.
+		@param value		[OUT] The container for the returned value.
+		@param defaultValue	What to put in @a value if there is no attribute in this element.
+		@throws Exception
+
+		@see GetAttribute
+		*/
+		template < class T, class DefaulT >
+			void GetAttributeOrDefault( const std::string& name, T* value, const DefaulT& defaultValue ) const
+		{
+			// Get the attribute's value as a std::string
+			std::string temp;
+			if ( !GetAttributeImp( name, &temp ) )
+			{
+				// The attribute does not exist - set value to the default
+				*value = defaultValue;
+				return;
+			}
+
+			// Stream the value from the string to T
+			FromString( temp, value );
+		}
+
+		/**
+		Gets an attribute of @a name from an element, if it doesn't exist it will return the defaultValue.
+
+		@param name			The name of the attribute you are querying.
+		@param defaultValue	What to put in @a value if there is no attribute in this element.
+
+		@see GetAttribute
+		*/
+		std::string GetAttributeOrDefault( const std::string& name, const std::string& defaultValue ) const;
+
+		/**
+		Returns an attribute of @a name from an element.
+		Uses FromString to convert the string to the type of choice.
+
+		@param name				The name of the attribute you are querying.
+		@param throwIfNotFound	[DEF]	If true, will throw an exception if the attribute doesn't exist
+		@throws Exception When the attribute doesn't exist and throwIfNotFound is true
+		@see GetAttributeOrDefault
+		*/
+		template < class T >
+			T GetAttribute( const std::string& name, bool throwIfNotFound = true ) const
+		{
+			// Get the attribute's value as a std::string
+			std::string temp;
+			T value;
+			if ( !GetAttributeImp( name, &temp ) )
+			{
+				if ( throwIfNotFound )
+				{
+					const std::string error( std::string( "Attribute '" ) + name + std::string( "' does not exist" ) );
+					TICPPTHROW( error );
+				}
+			}
+			else
+			{
+				// Stream the value from the string to T
+				FromString( temp, &value );
+			}
+
+			return value;
+		}
+
+		/**
+		Gets an attribute of @a name from an element.
+		Uses FromString to convert the string to the type of choice.
+
+		@param name				The name of the attribute you are querying.
+		@param value			[OUT]	The container for the returned value
+		@param throwIfNotFound	[DEF]	If true, will throw an exception if the attribute doesn't exist
+		@throws Exception When the attribute doesn't exist and throwIfNotFound is true
+
+		@see GetAttributeOrDefault
+		*/
+		template< class T >
+			void GetAttribute( const std::string& name, T* value, bool throwIfNotFound = true ) const
+		{
+			// Get the attribute's value as a std::string
+			std::string temp;
+			if ( !GetAttributeImp( name, &temp ) )
+			{
+				if ( throwIfNotFound )
+				{
+					const std::string error( std::string( "Attribute '" ) + name + std::string( "' does not exist" ) );
+					TICPPTHROW( error );
+				}
+				else
+				{
+					return;
+				}
+			}
+
+			// Stream the value from the string to T
+			FromString( temp, value );
+		}
+
+		/**
+		Gets an attribute of @a name from an element.
+		Returns an empty string if the attribute does not exist.
+
+		@param name	The name of the attribute you are querying.
+		@return The value of the attribute, or an empty string if it does not exist.
+
+		@see GetAttributeOrDefault
+		*/
+		std::string GetAttribute( const std::string& name ) const;
+
+		/**
+		Returns true, if attribute exists
+
+		@param name The name of the attribute you are checking.
+		@return Existence of attribute
+		*/
+		bool HasAttribute( const std::string& name ) const;
+
+		/**
+		Removes attribute from element.
+
+		@param name The name of the attribute to remove.
+		*/
+		void RemoveAttribute( const std::string& name );
+
+	private:
+
+		/**
+		@internal
+		Implimentation of the GetAttribute and GetAttributeOrDefault template methods.
+		*/
+		bool GetAttributeImp( const std::string& name, std::string* value ) const;
+
+		/**
+		@internal
+		Implimentation of the GetText, GetTextOrDefault, GetTextValue, and GetTextValueOrDefault template methods.
+		*/
+		bool GetTextImp( std::string* value ) const;
+	};
+
+	/** Wrapper around TiXmlDeclaration */
+	class Declaration : public NodeImp< TiXmlDeclaration >
+	{
+	public:
+		/**
+		Default	Constructor. Construct an empty declaration.
+		*/
+		Declaration();
+
+		/**
+		Constructor.
+		*/
+		Declaration( TiXmlDeclaration* declaration );
+
+		/**
+		Constructor.
+		*/
+		Declaration( const std::string& version, const std::string& encoding, const std::string& standalone );
+
+		/**
+		Version. Will return an empty string if none was found.
+		*/
+		std::string Version() const;
+
+		/**
+		Encoding. Will return an empty string if none was found.
+		*/
+		std::string Encoding() const;
+
+		/**
+		StandAlone. Is this a standalone document?
+		*/
+		std::string Standalone() const;
+	};
+
+	/** Wrapper around TiXmlStylesheetReference */
+	class StylesheetReference : public NodeImp< TiXmlStylesheetReference >
+	{
+	public:
+		/**
+		Default	Constructor. Construct an empty declaration.
+		*/
+		StylesheetReference();
+
+		/**
+		Constructor.
+		*/
+		StylesheetReference( TiXmlStylesheetReference* stylesheetReference );
+
+		/**
+		Constructor.
+		*/
+		StylesheetReference( const std::string& type, const std::string& href );
+
+		/**
+		Type. Will return an empty string if none was found.
+		*/
+		std::string Type() const;
+
+		/**
+		Href. Will return an empty string if none was found.
+		*/
+		std::string Href() const;
+	};
+}
+
+#endif	// TICPP_INCLUDED
+
+#endif // TIXML_USE_TICPP
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/ticpprc.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/ticpprc.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/ticpprc.h	(revision 11817)
@@ -0,0 +1,122 @@
+/*
+http://code.google.com/p/ticpp/
+Copyright (c) 2006 Ryan Pusztai, Ryan Mulder
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifdef TIXML_USE_TICPP
+
+#ifndef TICPPRC_INCLUDED
+#define TICPPRC_INCLUDED
+
+#include <vector>
+
+// Forward declare ticpp::Node, so it can be made a friend of TiCppRC
+namespace ticpp
+{
+	class Base;
+}
+
+// Forward declare TiCppRCImp so TiCppRC can hold a pointer to it
+class TiCppRCImp;
+
+/**
+Base class for reference counting functionality
+*/
+class TiCppRC
+{
+	// Allow ticpp::Node to directly modify reference count
+	friend class ticpp::Base;
+
+private:
+
+	TiCppRCImp* m_tiRC; /**< Pointer to reference counter */
+
+public:
+
+	/**
+	Constructor
+	Spawns new reference counter with a pointer to this
+	*/
+	TiCppRC();
+
+	/**
+	Destructor
+	Nullifies the pointer to this held by the reference counter
+	Decrements reference count
+	*/
+	virtual ~TiCppRC();
+	
+	std::vector< ticpp::Base* > m_spawnedWrappers; /**< Remember all wrappers that we've created with 'new' - ( e.g. NodeFactory, FirstChildElement, etc. )*/
+
+	/**
+	Delete all container objects we've spawned with 'new'.
+	*/
+	void DeleteSpawnedWrappers();
+};
+
+class TiCppRCImp
+{
+private:
+
+	int m_count;		/**< Holds reference count to me, and to the node I point to */
+
+	TiCppRC* m_tiCppRC;	/**< Holds pointer to an object inheriting TiCppRC */
+
+public:
+
+	/**
+	Initializes m_tiCppRC pointer, and set reference count to 1
+	*/
+	TiCppRCImp( TiCppRC* tiCppRC );
+
+	/**
+	Allows the TiCppRC object to set the pointer to itself ( m_tiCppRc ) to NULL when the TiCppRC object is deleted
+	*/
+	void Nullify();
+
+	/**
+	Increment Reference Count
+	*/
+	void IncRef();
+
+	/**
+	Decrement Reference Count
+	*/
+	void DecRef();
+
+	/**
+	Set Reference Count to 1 - dangerous! - Use only if you are sure of the consequences
+	*/
+	void InitRef();
+
+	/**
+	Get internal pointer to the TiCppRC object - not reference counted, use at your own risk
+	*/
+	TiCppRC* Get();
+
+	/**
+	Returns state of internal pointer - will be null if the object was deleted
+	*/
+	bool IsNull();
+};
+
+#endif // TICPP_INCLUDED
+
+#endif // TIXML_USE_TICPP
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/tinystr.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/tinystr.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/tinystr.cpp	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+/*
+ * THIS FILE WAS ALTERED BY Tyge Løvset, 7. April 2005.
+ */
+
+
+#ifndef TIXML_USE_STL
+
+#include "tinystr.h"
+
+// Error value for find primitive
+const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
+
+
+// Null rep.
+TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
+
+
+void TiXmlString::reserve (size_type cap)
+{
+	if (cap > capacity())
+	{
+		TiXmlString tmp;
+		tmp.init(length(), cap);
+		memcpy(tmp.start(), data(), length());
+		swap(tmp);
+	}
+}
+
+
+TiXmlString& TiXmlString::assign(const char* str, size_type len)
+{
+	size_type cap = capacity();
+	if (len > cap || cap > 3*(len + 8))
+	{
+		TiXmlString tmp;
+		tmp.init(len);
+		memcpy(tmp.start(), str, len);
+		swap(tmp);
+	}
+	else
+	{
+		memmove(start(), str, len);
+		set_size(len);
+	}
+	return *this;
+}
+
+
+TiXmlString& TiXmlString::append(const char* str, size_type len)
+{
+	size_type newsize = length() + len;
+	if (newsize > capacity())
+	{
+		reserve (newsize + capacity());
+	}
+	memmove(finish(), str, len);
+	set_size(newsize);
+	return *this;
+}
+
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
+{
+	TiXmlString tmp;
+	tmp.reserve(a.length() + b.length());
+	tmp += a;
+	tmp += b;
+	return tmp;
+}
+
+TiXmlString operator + (const TiXmlString & a, const char* b)
+{
+	TiXmlString tmp;
+	TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
+	tmp.reserve(a.length() + b_len);
+	tmp += a;
+	tmp.append(b, b_len);
+	return tmp;
+}
+
+TiXmlString operator + (const char* a, const TiXmlString & b)
+{
+	TiXmlString tmp;
+	TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
+	tmp.reserve(a_len + b.length());
+	tmp.append(a, a_len);
+	tmp += b;
+	return tmp;
+}
+
+
+#endif	// TIXML_USE_STL
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/tinystr.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/tinystr.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/tinystr.h	(revision 11817)
@@ -0,0 +1,319 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original file by Yves Berquin.
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+/*
+ * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005.
+ *
+ * - completely rewritten. compact, clean, and fast implementation.
+ * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems)
+ * - fixed reserve() to work as per specification.
+ * - fixed buggy compares operator==(), operator<(), and operator>()
+ * - fixed operator+=() to take a const ref argument, following spec.
+ * - added "copy" constructor with length, and most compare operators.
+ * - added swap(), clear(), size(), capacity(), operator+().
+ */
+
+#ifndef TIXML_USE_STL
+
+#ifndef TIXML_STRING_INCLUDED
+#define TIXML_STRING_INCLUDED
+
+#include <assert.h>
+#include <string.h>
+
+/*	The support for explicit isn't that universal, and it isn't really
+	required - it is used to check that the TiXmlString class isn't incorrectly
+	used. Be nice to old compilers and macro it here:
+*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
+	// Microsoft visual studio, version 6 and higher.
+	#define TIXML_EXPLICIT explicit
+#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+	// GCC version 3 and higher.s
+	#define TIXML_EXPLICIT explicit
+#else
+	#define TIXML_EXPLICIT
+#endif
+
+
+/*
+   TiXmlString is an emulation of a subset of the std::string template.
+   Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
+   Only the member functions relevant to the TinyXML project have been implemented.
+   The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
+   a string and there's no more room, we allocate a buffer twice as big as we need.
+*/
+class TiXmlString
+{
+  public :
+	// The size type used
+  	typedef size_t size_type;
+
+	// Error value for find primitive
+	static const size_type npos; // = -1;
+
+
+	// TiXmlString empty constructor
+	TiXmlString () : rep_(&nullrep_)
+	{
+	}
+
+	// TiXmlString copy constructor
+	TiXmlString ( const TiXmlString & copy) : rep_(0)
+	{
+		init(copy.length());
+		memcpy(start(), copy.data(), length());
+	}
+
+	// TiXmlString constructor, based on a string
+	TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
+	{
+		init( static_cast<size_type>( strlen(copy) ));
+		memcpy(start(), copy, length());
+	}
+
+	// TiXmlString constructor, based on a string
+	TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
+	{
+		init(len);
+		memcpy(start(), str, len);
+	}
+
+	// TiXmlString destructor
+	~TiXmlString ()
+	{
+		quit();
+	}
+
+	// = operator
+	TiXmlString& operator = (const char * copy)
+	{
+		return assign( copy, (size_type)strlen(copy));
+	}
+
+	// = operator
+	TiXmlString& operator = (const TiXmlString & copy)
+	{
+		return assign(copy.start(), copy.length());
+	}
+
+
+	// += operator. Maps to append
+	TiXmlString& operator += (const char * suffix)
+	{
+		return append(suffix, static_cast<size_type>( strlen(suffix) ));
+	}
+
+	// += operator. Maps to append
+	TiXmlString& operator += (char single)
+	{
+		return append(&single, 1);
+	}
+
+	// += operator. Maps to append
+	TiXmlString& operator += (const TiXmlString & suffix)
+	{
+		return append(suffix.data(), suffix.length());
+	}
+
+
+	// Convert a TiXmlString into a null-terminated char *
+	const char * c_str () const { return rep_->str; }
+
+	// Convert a TiXmlString into a char * (need not be null terminated).
+	const char * data () const { return rep_->str; }
+
+	// Return the length of a TiXmlString
+	size_type length () const { return rep_->size; }
+
+	// Alias for length()
+	size_type size () const { return rep_->size; }
+
+	// Checks if a TiXmlString is empty
+	bool empty () const { return rep_->size == 0; }
+
+	// Return capacity of string
+	size_type capacity () const { return rep_->capacity; }
+
+
+	// single char extraction
+	const char& at (size_type index) const
+	{
+		assert( index < length() );
+		return rep_->str[ index ];
+	}
+
+	// [] operator
+	char& operator [] (size_type index) const
+	{
+		assert( index < length() );
+		return rep_->str[ index ];
+	}
+
+	// find a char in a string. Return TiXmlString::npos if not found
+	size_type find (char lookup) const
+	{
+		return find(lookup, 0);
+	}
+
+	// find a char in a string from an offset. Return TiXmlString::npos if not found
+	size_type find (char tofind, size_type offset) const
+	{
+		if (offset >= length()) return npos;
+
+		for (const char* p = c_str() + offset; *p != '\0'; ++p)
+		{
+		   if (*p == tofind) return static_cast< size_type >( p - c_str() );
+		}
+		return npos;
+	}
+
+	void clear ()
+	{
+		//Lee:
+		//The original was just too strange, though correct:
+		//	TiXmlString().swap(*this);
+		//Instead use the quit & re-init:
+		quit();
+		init(0,0);
+	}
+
+	/*	Function to reserve a big amount of data when we know we'll need it. Be aware that this
+		function DOES NOT clear the content of the TiXmlString if any exists.
+	*/
+	void reserve (size_type cap);
+
+	TiXmlString& assign (const char* str, size_type len);
+
+	TiXmlString& append (const char* str, size_type len);
+
+	void swap (TiXmlString& other)
+	{
+		Rep* r = rep_;
+		rep_ = other.rep_;
+		other.rep_ = r;
+	}
+
+  private:
+
+	void init(size_type sz) { init(sz, sz); }
+	void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
+	char* start() const { return rep_->str; }
+	char* finish() const { return rep_->str + rep_->size; }
+
+	struct Rep
+	{
+		size_type size, capacity;
+		char str[1];
+	};
+
+	void init(size_type sz, size_type cap)
+	{
+		if (cap)
+		{
+			// Lee: the original form:
+			//	rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
+			// doesn't work in some cases of new being overloaded. Switching
+			// to the normal allocation, although use an 'int' for systems
+			// that are overly picky about structure alignment.
+			const size_type bytesNeeded = sizeof(Rep) + cap;
+			const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 
+			rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
+
+			rep_->str[ rep_->size = sz ] = '\0';
+			rep_->capacity = cap;
+		}
+		else
+		{
+			rep_ = &nullrep_;
+		}
+	}
+
+	void quit()
+	{
+		if (rep_ != &nullrep_)
+		{
+			// The rep_ is really an array of ints. (see the allocator, above).
+			// Cast it back before delete, so the compiler won't incorrectly call destructors.
+			delete [] ( reinterpret_cast<int*>( rep_ ) );
+		}
+	}
+
+	Rep * rep_;
+	static Rep nullrep_;
+
+} ;
+
+
+inline bool operator == (const TiXmlString & a, const TiXmlString & b)
+{
+	return    ( a.length() == b.length() )				// optimization on some platforms
+	       && ( strcmp(a.c_str(), b.c_str()) == 0 );	// actual compare
+}
+inline bool operator < (const TiXmlString & a, const TiXmlString & b)
+{
+	return strcmp(a.c_str(), b.c_str()) < 0;
+}
+
+inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
+inline bool operator >  (const TiXmlString & a, const TiXmlString & b) { return b < a; }
+inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
+inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
+
+inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
+inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
+inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
+inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
+TiXmlString operator + (const TiXmlString & a, const char* b);
+TiXmlString operator + (const char* a, const TiXmlString & b);
+
+
+/*
+   TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
+   Only the operators that we need for TinyXML have been developped.
+*/
+class TiXmlOutStream : public TiXmlString
+{
+public :
+
+	// TiXmlOutStream << operator.
+	TiXmlOutStream & operator << (const TiXmlString & in)
+	{
+		*this += in;
+		return *this;
+	}
+
+	// TiXmlOutStream << operator.
+	TiXmlOutStream & operator << (const char * in)
+	{
+		*this += in;
+		return *this;
+	}
+
+} ;
+
+#endif	// TIXML_STRING_INCLUDED
+#endif	// TIXML_USE_STL
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxml.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxml.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxml.cpp	(revision 11817)
@@ -0,0 +1,1969 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+#include "tinyxml.h"
+
+#include <ctype.h>
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+// Microsoft compiler security
+FILE* TiXmlFOpen( const char* filename, const char* mode )
+{
+	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		FILE* fp = 0;
+		errno_t err = fopen_s( &fp, filename, mode );
+		if ( !err && fp )
+			return fp;
+		return 0;
+	#else
+		return fopen( filename, mode );
+	#endif
+}
+
+void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+	int i=0;
+
+	while( i<(int)str.length() )
+	{
+		unsigned char c = (unsigned char) str[i];
+
+		if (    c == '&'
+		     && i < ( (int)str.length() - 2 )
+			 && str[i+1] == '#'
+			 && str[i+2] == 'x' )
+		{
+			// Hexadecimal character reference.
+			// Pass through unchanged.
+			// &#xA9;	-- copyright symbol, for example.
+			//
+			// The -1 is a bug fix from Rob Laveaux. It keeps
+			// an overflow from happening if there is no ';'.
+			// There are actually 2 ways to exit this loop -
+			// while fails (error case) and break (semicolon found).
+			// However, there is no mechanism (currently) for
+			// this function to return an error.
+			while ( i<(int)str.length()-1 )
+			{
+				outString->append( str.c_str() + i, 1 );
+				++i;
+				if ( str[i] == ';' )
+					break;
+			}
+		}
+		else if ( c == '&' )
+		{
+			outString->append( entity[0].str, entity[0].strLength );
+			++i;
+		}
+		else if ( c == '<' )
+		{
+			outString->append( entity[1].str, entity[1].strLength );
+			++i;
+		}
+		else if ( c == '>' )
+		{
+			outString->append( entity[2].str, entity[2].strLength );
+			++i;
+		}
+		else if ( c == '\"' )
+		{
+			outString->append( entity[3].str, entity[3].strLength );
+			++i;
+		}
+		else if ( c == '\'' )
+		{
+			outString->append( entity[4].str, entity[4].strLength );
+			++i;
+		}
+		else if ( c < 32 )
+		{
+			// Easy pass at non-alpha/numeric/symbol
+			// Below 32 is symbolic.
+			char buf[ 32 ];
+
+			#if defined(TIXML_SNPRINTF)
+				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
+			#else
+				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+			#endif
+
+			//*ME:	warning C4267: convert 'size_t' to 'int'
+			//*ME:	Int-Cast to make compiler happy ...
+			outString->append( buf, (int)strlen( buf ) );
+			++i;
+		}
+		else
+		{
+			//char realc = (char) c;
+			//outString->append( &realc, 1 );
+			*outString += (char) c;	// somewhat more efficient function call.
+			++i;
+		}
+	}
+}
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+	parent = 0;
+	type = _type;
+	firstChild = 0;
+	lastChild = 0;
+	prev = 0;
+	next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+	target->SetValue (value.c_str() );
+	target->userData = userData;
+}
+
+
+void TiXmlNode::Clear()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}
+
+	firstChild = 0;
+	lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+	assert( node->parent == 0 || node->parent == this );
+	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+	if ( node->Type() == TiXmlNode::DOCUMENT )
+	{
+		delete node;
+		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	node->parent = this;
+
+	node->prev = lastChild;
+	node->next = 0;
+
+	if ( lastChild )
+		lastChild->next = node;
+	else
+		firstChild = node;			// it was an empty list.
+
+	lastChild = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+	if ( addThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+
+	return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{
+	if ( !beforeThis || beforeThis->parent != this ) {
+		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->next = beforeThis;
+	node->prev = beforeThis->prev;
+	if ( beforeThis->prev )
+	{
+		beforeThis->prev->next = node;
+	}
+	else
+	{
+		assert( firstChild == beforeThis );
+		firstChild = node;
+	}
+	beforeThis->prev = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+	if ( !afterThis || afterThis->parent != this ) {
+		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::DOCUMENT )
+	{
+		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->prev = afterThis;
+	node->next = afterThis->next;
+	if ( afterThis->next )
+	{
+		afterThis->next->prev = node;
+	}
+	else
+	{
+		assert( lastChild == afterThis );
+		lastChild = node;
+	}
+	afterThis->next = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+	if ( replaceThis->parent != this )
+		return 0;
+
+	TiXmlNode* node = withThis.Clone();
+	if ( !node )
+		return 0;
+
+	node->next = replaceThis->next;
+	node->prev = replaceThis->prev;
+
+	if ( replaceThis->next )
+		replaceThis->next->prev = node;
+	else
+		lastChild = node;
+
+	if ( replaceThis->prev )
+		replaceThis->prev->next = node;
+	else
+		firstChild = node;
+
+	delete replaceThis;
+	node->parent = this;
+	return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+	if ( removeThis->parent != this )
+	{
+		assert( 0 );
+		return false;
+	}
+
+	if ( removeThis->next )
+		removeThis->next->prev = removeThis->prev;
+	else
+		lastChild = removeThis->prev;
+
+	if ( removeThis->prev )
+		removeThis->prev->next = removeThis->next;
+	else
+		firstChild = removeThis->next;
+
+	delete removeThis;
+	return true;
+}
+
+const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = firstChild; node; node = node->next )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = lastChild; node; node = node->prev )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
+{
+	if ( !previous )
+	{
+		return FirstChild();
+	}
+	else
+	{
+		assert( previous->parent == this );
+		return previous->NextSibling();
+	}
+}
+
+
+const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
+{
+	if ( !previous )
+	{
+		return FirstChild( val );
+	}
+	else
+	{
+		assert( previous->parent == this );
+		return previous->NextSibling( val );
+	}
+}
+
+
+const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = next; node; node = node->next )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
+{
+	const TiXmlNode* node;
+	for ( node = prev; node; node = node->prev )
+	{
+		if ( strcmp( node->Value(), _value ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+
+void TiXmlElement::RemoveAttribute( const char * name )
+{
+    #ifdef TIXML_USE_STL
+	TIXML_STRING str( name );
+	TiXmlAttribute* node = attributeSet.Find( str );
+	#else
+	TiXmlAttribute* node = attributeSet.Find( name );
+	#endif
+	if ( node )
+	{
+		attributeSet.Remove( node );
+		delete node;
+	}
+}
+
+const TiXmlElement* TiXmlNode::FirstChildElement() const
+{
+	const TiXmlNode* node;
+
+	for (	node = FirstChild();
+			node;
+			node = node->NextSibling() )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
+{
+	const TiXmlNode* node;
+
+	for (	node = FirstChild( _value );
+			node;
+			node = node->NextSibling( _value ) )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement() const
+{
+	const TiXmlNode* node;
+
+	for (	node = NextSibling();
+			node;
+			node = node->NextSibling() )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
+{
+	const TiXmlNode* node;
+
+	for (	node = NextSibling( _value );
+			node;
+			node = node->NextSibling( _value ) )
+	{
+		if ( node->ToElement() )
+			return node->ToElement();
+	}
+	return 0;
+}
+
+
+const TiXmlDocument* TiXmlNode::GetDocument() const
+{
+	const TiXmlNode* node;
+
+	for( node = this; node; node = node->parent )
+	{
+		if ( node->ToDocument() )
+			return node->ToDocument();
+	}
+	return 0;
+}
+
+
+TiXmlElement::TiXmlElement (const char * _value)
+	: TiXmlNode( TiXmlNode::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlElement::TiXmlElement( const std::string& _value )
+	: TiXmlNode( TiXmlNode::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	value = _value;
+}
+#endif
+
+
+TiXmlElement::TiXmlElement( const TiXmlElement& copy)
+	: TiXmlNode( TiXmlNode::ELEMENT )
+{
+	firstChild = lastChild = 0;
+	copy.CopyTo( this );
+}
+
+
+void TiXmlElement::operator=( const TiXmlElement& base )
+{
+	ClearThis();
+	base.CopyTo( this );
+}
+
+
+TiXmlElement::~TiXmlElement()
+{
+	ClearThis();
+}
+
+
+void TiXmlElement::ClearThis()
+{
+	Clear();
+	while( attributeSet.First() )
+	{
+		TiXmlAttribute* node = attributeSet.First();
+		attributeSet.Remove( node );
+		delete node;
+	}
+}
+
+
+const char* TiXmlElement::Attribute( const char* name ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+		return node->Value();
+	return 0;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+		return &node->ValueStr();
+	return 0;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, int* i ) const
+{
+	const char* s = Attribute( name );
+	if ( i )
+	{
+		if ( s ) {
+			*i = atoi( s );
+		}
+		else {
+			*i = 0;
+		}
+	}
+	return s;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
+{
+	const std::string* s = Attribute( name );
+	if ( i )
+	{
+		if ( s ) {
+			*i = atoi( s->c_str() );
+		}
+		else {
+			*i = 0;
+		}
+	}
+	return s;
+}
+#endif
+
+
+const char* TiXmlElement::Attribute( const char* name, double* d ) const
+{
+	const char* s = Attribute( name );
+	if ( d )
+	{
+		if ( s ) {
+			*d = atof( s );
+		}
+		else {
+			*d = 0;
+		}
+	}
+	return s;
+}
+
+
+#ifdef TIXML_USE_STL
+const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
+{
+	const std::string* s = Attribute( name );
+	if ( d )
+	{
+		if ( s ) {
+			*d = atof( s->c_str() );
+		}
+		else {
+			*d = 0;
+		}
+	}
+	return s;
+}
+#endif
+
+
+int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryIntValue( ival );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryIntValue( ival );
+}
+#endif
+
+
+int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryDoubleValue( dval );
+}
+
+
+#ifdef TIXML_USE_STL
+int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
+{
+	const TiXmlAttribute* node = attributeSet.Find( name );
+	if ( !node )
+		return TIXML_NO_ATTRIBUTE;
+	return node->QueryDoubleValue( dval );
+}
+#endif
+
+
+void TiXmlElement::SetAttribute( const char * name, int val )
+{
+	char buf[64];
+	#if defined(TIXML_SNPRINTF)
+		TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
+	#else
+		sprintf( buf, "%d", val );
+	#endif
+	SetAttribute( name, buf );
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, int val )
+{
+   std::ostringstream oss;
+   oss << val;
+   SetAttribute( name, oss.str() );
+}
+#endif
+
+
+void TiXmlElement::SetDoubleAttribute( const char * name, double val )
+{
+	char buf[256];
+	#if defined(TIXML_SNPRINTF)
+		TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
+	#else
+		sprintf( buf, "%f", val );
+	#endif
+	SetAttribute( name, buf );
+}
+
+
+void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
+{
+    #ifdef TIXML_USE_STL
+	TIXML_STRING _name( cname );
+	TIXML_STRING _value( cvalue );
+	#else
+	const char* _name = cname;
+	const char* _value = cvalue;
+	#endif
+
+	TiXmlAttribute* node = attributeSet.Find( _name );
+	if ( node )
+	{
+		node->SetValue( _value );
+		return;
+	}
+
+	TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
+	if ( attrib )
+	{
+		attributeSet.Add( attrib );
+	}
+	else
+	{
+		TiXmlDocument* document = GetDocument();
+		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	}
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
+{
+	TiXmlAttribute* node = attributeSet.Find( name );
+	if ( node )
+	{
+		node->SetValue( _value );
+		return;
+	}
+
+	TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
+	if ( attrib )
+	{
+		attributeSet.Add( attrib );
+	}
+	else
+	{
+		TiXmlDocument* document = GetDocument();
+		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	}
+}
+#endif
+
+
+void TiXmlElement::Print( FILE* cfile, int depth ) const
+{
+	int i;
+	assert( cfile );
+	for ( i=0; i<depth; i++ ) {
+		fprintf( cfile, "    " );
+	}
+
+	fprintf( cfile, "<%s", value.c_str() );
+
+	const TiXmlAttribute* attrib;
+	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
+	{
+		fprintf( cfile, " " );
+		attrib->Print( cfile, depth );
+	}
+
+	// There are 3 different formatting approaches:
+	// 1) An element without children is printed as a <foo /> node
+	// 2) An element with only a text child is printed as <foo> text </foo>
+	// 3) An element with children is printed on multiple lines.
+	TiXmlNode* node;
+	if ( !firstChild )
+	{
+		fprintf( cfile, " />" );
+	}
+	else if ( firstChild == lastChild && firstChild->ToText() )
+	{
+		fprintf( cfile, ">" );
+		firstChild->Print( cfile, depth + 1 );
+		fprintf( cfile, "</%s>", value.c_str() );
+	}
+	else
+	{
+		fprintf( cfile, ">" );
+
+		for ( node = firstChild; node; node=node->NextSibling() )
+		{
+			if ( !node->ToText() )
+			{
+				fprintf( cfile, "\n" );
+			}
+			node->Print( cfile, depth+1 );
+		}
+		fprintf( cfile, "\n" );
+		for( i=0; i<depth; ++i ) {
+			fprintf( cfile, "    " );
+		}
+		fprintf( cfile, "</%s>", value.c_str() );
+	}
+}
+
+
+void TiXmlElement::CopyTo( TiXmlElement* target ) const
+{
+	// superclass:
+	TiXmlNode::CopyTo( target );
+
+	// Element class:
+	// Clone the attributes, then clone the children.
+	const TiXmlAttribute* attribute = 0;
+	for(	attribute = attributeSet.First();
+	attribute;
+	attribute = attribute->Next() )
+	{
+		target->SetAttribute( attribute->Name(), attribute->Value() );
+	}
+
+	TiXmlNode* node = 0;
+	for ( node = firstChild; node; node = node->NextSibling() )
+	{
+		target->LinkEndChild( node->Clone() );
+	}
+}
+
+bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
+{
+	if ( visitor->VisitEnter( *this, attributeSet.First() ) )
+	{
+		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+		{
+			if ( !node->Accept( visitor ) )
+				break;
+		}
+	}
+	return visitor->VisitExit( *this );
+}
+
+
+TiXmlNode* TiXmlElement::Clone() const
+{
+	TiXmlElement* clone = new TiXmlElement( Value() );
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+const char* TiXmlElement::GetText() const
+{
+	const TiXmlNode* child = this->FirstChild();
+	if ( child ) {
+		const TiXmlText* childText = child->ToText();
+		if ( childText ) {
+			return childText->Value();
+		}
+	}
+	return 0;
+}
+
+
+TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+	ClearError();
+}
+
+TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+	value = documentName;
+	ClearError();
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	tabsize = 4;
+	useMicrosoftBOM = false;
+    value = documentName;
+	ClearError();
+}
+#endif
+
+
+TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
+{
+	copy.CopyTo( this );
+}
+
+
+void TiXmlDocument::operator=( const TiXmlDocument& copy )
+{
+	Clear();
+	copy.CopyTo( this );
+}
+
+
+bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
+{
+	// See STL_STRING_BUG below.
+	//StringToBuffer buf( value );
+
+	return LoadFile( Value(), encoding );
+}
+
+
+bool TiXmlDocument::SaveFile() const
+{
+	// See STL_STRING_BUG below.
+//	StringToBuffer buf( value );
+//
+//	if ( buf.buffer && SaveFile( buf.buffer ) )
+//		return true;
+//
+//	return false;
+	return SaveFile( Value() );
+}
+
+bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
+{
+	// There was a really terrifying little bug here. The code:
+	//		value = filename
+	// in the STL case, cause the assignment method of the std::string to
+	// be called. What is strange, is that the std::string had the same
+	// address as it's c_str() method, and so bad things happen. Looks
+	// like a bug in the Microsoft STL implementation.
+	// Add an extra string to avoid the crash.
+	TIXML_STRING filename( _filename );
+	value = filename;
+
+	// reading in binary mode so that tinyxml can normalize the EOL
+	FILE* file = TiXmlFOpen( value.c_str (), "rb" );
+
+	if ( file )
+	{
+		bool result = LoadFile( file, encoding );
+		fclose( file );
+		return result;
+	}
+	else
+	{
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+}
+
+bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
+{
+	if ( !file )
+	{
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	// Delete the existing data:
+	Clear();
+	location.Clear();
+
+	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
+	long length = 0;
+	fseek( file, 0, SEEK_END );
+	length = ftell( file );
+	fseek( file, 0, SEEK_SET );
+
+	// Strange case, but good to handle up front.
+	if ( length <= 0 )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	// If we have a file, assume it is all one big XML file, and read it in.
+	// The document parser may decide the document ends sooner than the entire file, however.
+	TIXML_STRING data;
+	data.reserve( length );
+
+	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
+	// 2.11 End-of-Line Handling
+	// <snip>
+	// <quote>
+	// ...the XML processor MUST behave as if it normalized all line breaks in external
+	// parsed entities (including the document entity) on input, before parsing, by translating
+	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
+	// a single #xA character.
+	// </quote>
+	//
+	// It is not clear fgets does that, and certainly isn't clear it works cross platform.
+	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
+	// convention, and not work generally.
+
+	/*
+	while( fgets( buf, sizeof(buf), file ) )
+	{
+		data += buf;
+	}
+	*/
+
+	char* buf = new char[ length+1 ];
+	buf[0] = 0;
+
+	if ( fread( buf, length, 1, file ) != 1 ) {
+		delete [] buf;
+		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return false;
+	}
+
+	const char* lastPos = buf;
+	const char* p = buf;
+
+	buf[length] = 0;
+	while( *p ) {
+		assert( p < (buf+length) );
+		if ( *p == 0xa ) {
+			// Newline character. No special rules for this. Append all the characters
+			// since the last string, and include the newline.
+			data.append( lastPos, (p-lastPos+1) );	// append, include the newline
+			++p;									// move past the newline
+			lastPos = p;							// and point to the new buffer (may be 0)
+			assert( p <= (buf+length) );
+		}
+		else if ( *p == 0xd ) {
+			// Carriage return. Append what we have so far, then
+			// handle moving forward in the buffer.
+			if ( (p-lastPos) > 0 ) {
+				data.append( lastPos, p-lastPos );	// do not add the CR
+			}
+			data += (char)0xa;						// a proper newline
+
+			if ( *(p+1) == 0xa ) {
+				// Carriage return - new line sequence
+				p += 2;
+				lastPos = p;
+				assert( p <= (buf+length) );
+			}
+			else {
+				// it was followed by something else...that is presumably characters again.
+				++p;
+				lastPos = p;
+				assert( p <= (buf+length) );
+			}
+		}
+		else {
+			++p;
+		}
+	}
+	// Handle any left over characters.
+	if ( p-lastPos ) {
+		data.append( lastPos, p-lastPos );
+	}
+	delete [] buf;
+	buf = 0;
+
+	Parse( data.c_str(), 0, encoding );
+
+	if (  Error() )
+        return false;
+    else
+		return true;
+}
+
+
+bool TiXmlDocument::SaveFile( const char * filename ) const
+{
+	// The old c stuff lives on...
+	FILE* fp = TiXmlFOpen( filename, "w" );
+	if ( fp )
+	{
+		bool result = SaveFile( fp );
+		fclose( fp );
+		return result;
+	}
+	return false;
+}
+
+
+bool TiXmlDocument::SaveFile( FILE* fp ) const
+{
+	if ( useMicrosoftBOM )
+	{
+		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+		fputc( TIXML_UTF_LEAD_0, fp );
+		fputc( TIXML_UTF_LEAD_1, fp );
+		fputc( TIXML_UTF_LEAD_2, fp );
+	}
+	Print( fp, 0 );
+	return (ferror(fp) == 0);
+}
+
+
+void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
+{
+	TiXmlNode::CopyTo( target );
+
+	target->error = error;
+	target->errorId = errorId;
+	target->errorDesc = errorDesc;
+	target->tabsize = tabsize;
+	target->errorLocation = errorLocation;
+	target->useMicrosoftBOM = useMicrosoftBOM;
+
+	TiXmlNode* node = 0;
+	for ( node = firstChild; node; node = node->NextSibling() )
+	{
+		target->LinkEndChild( node->Clone() );
+	}
+}
+
+
+TiXmlNode* TiXmlDocument::Clone() const
+{
+	TiXmlDocument* clone = new TiXmlDocument();
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+void TiXmlDocument::Print( FILE* cfile, int depth ) const
+{
+	assert( cfile );
+	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+	{
+		node->Print( cfile, depth );
+		fprintf( cfile, "\n" );
+	}
+}
+
+
+bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
+{
+	if ( visitor->VisitEnter( *this ) )
+	{
+		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
+		{
+			if ( !node->Accept( visitor ) )
+				break;
+		}
+	}
+	return visitor->VisitExit( *this );
+}
+
+
+const TiXmlAttribute* TiXmlAttribute::Next() const
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( next->value.empty() && next->name.empty() )
+		return 0;
+	return next;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Next()
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( next->value.empty() && next->name.empty() )
+		return 0;
+	return next;
+}
+*/
+
+const TiXmlAttribute* TiXmlAttribute::Previous() const
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( prev->value.empty() && prev->name.empty() )
+		return 0;
+	return prev;
+}
+
+/*
+TiXmlAttribute* TiXmlAttribute::Previous()
+{
+	// We are using knowledge of the sentinel. The sentinel
+	// have a value or name.
+	if ( prev->value.empty() && prev->name.empty() )
+		return 0;
+	return prev;
+}
+*/
+
+void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+	TIXML_STRING n, v;
+
+	EncodeString( name, &n );
+	EncodeString( value, &v );
+
+	if (value.find ('\"') == TIXML_STRING::npos) {
+		if ( cfile ) {
+		fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
+		}
+		if ( str ) {
+			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
+		}
+	}
+	else {
+		if ( cfile ) {
+		fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
+		}
+		if ( str ) {
+			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
+		}
+	}
+}
+
+
+int TiXmlAttribute::QueryIntValue( int* ival ) const
+{
+	if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
+		return TIXML_SUCCESS;
+	return TIXML_WRONG_TYPE;
+}
+
+int TiXmlAttribute::QueryDoubleValue( double* dval ) const
+{
+	if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
+		return TIXML_SUCCESS;
+	return TIXML_WRONG_TYPE;
+}
+
+void TiXmlAttribute::SetIntValue( int _value )
+{
+	char buf [64];
+	#if defined(TIXML_SNPRINTF)
+		TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
+	#else
+		sprintf (buf, "%d", _value);
+	#endif
+	SetValue (buf);
+}
+
+void TiXmlAttribute::SetDoubleValue( double _value )
+{
+	char buf [256];
+	#if defined(TIXML_SNPRINTF)
+		TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
+	#else
+		sprintf (buf, "%lf", _value);
+	#endif
+	SetValue (buf);
+}
+
+int TiXmlAttribute::IntValue() const
+{
+	return atoi (value.c_str ());
+}
+
+double  TiXmlAttribute::DoubleValue() const
+{
+	return atof (value.c_str ());
+}
+
+
+TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
+{
+	copy.CopyTo( this );
+}
+
+
+void TiXmlComment::operator=( const TiXmlComment& base )
+{
+	Clear();
+	base.CopyTo( this );
+}
+
+
+void TiXmlComment::Print( FILE* cfile, int depth ) const
+{
+	assert( cfile );
+	for ( int i=0; i<depth; i++ )
+	{
+		fprintf( cfile,  "    " );
+	}
+	fprintf( cfile, "<!--%s-->", value.c_str() );
+}
+
+
+void TiXmlComment::CopyTo( TiXmlComment* target ) const
+{
+	TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlComment::Clone() const
+{
+	TiXmlComment* clone = new TiXmlComment();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+void TiXmlText::Print( FILE* cfile, int depth ) const
+{
+	assert( cfile );
+	if ( cdata )
+	{
+		int i;
+		fprintf( cfile, "\n" );
+		for ( i=0; i<depth; i++ ) {
+			fprintf( cfile, "    " );
+		}
+		fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
+	}
+	else
+	{
+		TIXML_STRING buffer;
+		EncodeString( value, &buffer );
+		fprintf( cfile, "%s", buffer.c_str() );
+	}
+}
+
+
+void TiXmlText::CopyTo( TiXmlText* target ) const
+{
+	TiXmlNode::CopyTo( target );
+	target->cdata = cdata;
+}
+
+
+bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlText::Clone() const
+{
+	TiXmlText* clone = 0;
+	clone = new TiXmlText( "" );
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+TiXmlDeclaration::TiXmlDeclaration( const char * _version,
+									const char * _encoding,
+									const char * _standalone )
+	: TiXmlNode( TiXmlNode::DECLARATION )
+{
+	version = _version;
+	encoding = _encoding;
+	standalone = _standalone;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
+									const std::string& _encoding,
+									const std::string& _standalone )
+	: TiXmlNode( TiXmlNode::DECLARATION )
+{
+	version = _version;
+	encoding = _encoding;
+	standalone = _standalone;
+}
+#endif
+
+
+TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
+	: TiXmlNode( TiXmlNode::DECLARATION )
+{
+	copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
+{
+	Clear();
+	copy.CopyTo( this );
+}
+
+
+void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+	if ( cfile ) fprintf( cfile, "<?xml " );
+	if ( str )	 (*str) += "<?xml ";
+
+	if ( !version.empty() ) {
+		if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
+		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
+	}
+	if ( !encoding.empty() ) {
+		if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
+		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
+	}
+	if ( !standalone.empty() ) {
+		if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
+		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
+	}
+	if ( cfile ) fprintf( cfile, "?>" );
+	if ( str )	 (*str) += "?>";
+}
+
+
+void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
+{
+	TiXmlNode::CopyTo( target );
+
+	target->version = version;
+	target->encoding = encoding;
+	target->standalone = standalone;
+}
+
+
+bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlDeclaration::Clone() const
+{
+	TiXmlDeclaration* clone = new TiXmlDeclaration();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+TiXmlStylesheetReference::TiXmlStylesheetReference( const char * _type,
+													const char * _href )
+	: TiXmlNode( TiXmlNode::STYLESHEETREFERENCE )
+{
+	type = _type;
+	href = _href;
+}
+
+
+#ifdef TIXML_USE_STL
+TiXmlStylesheetReference::TiXmlStylesheetReference(	const std::string& _type,
+													const std::string& _href )
+	: TiXmlNode( TiXmlNode::STYLESHEETREFERENCE )
+{
+	type = _type;
+	href = _href;
+}
+#endif
+
+
+TiXmlStylesheetReference::TiXmlStylesheetReference( const TiXmlStylesheetReference& copy )
+	: TiXmlNode( TiXmlNode::STYLESHEETREFERENCE )
+{
+	copy.CopyTo( this );
+}
+
+
+void TiXmlStylesheetReference::operator=( const TiXmlStylesheetReference& copy )
+{
+	Clear();
+	copy.CopyTo( this );
+}
+
+
+void TiXmlStylesheetReference::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
+{
+	if ( cfile ) fprintf( cfile, "<?xml-stylesheet " );
+	if ( str )	 (*str) += "<?xml-stylesheet ";
+
+	if ( !type.empty() ) {
+		if ( cfile ) fprintf (cfile, "type=\"%s\" ", type.c_str ());
+		if ( str ) { (*str) += "type=\""; (*str) += type; (*str) += "\" "; }
+	}
+	if ( !href.empty() ) {
+		if ( cfile ) fprintf (cfile, "href=\"%s\" ", href.c_str ());
+		if ( str ) { (*str) += "href=\""; (*str) += href; (*str) += "\" "; }
+	}
+	if ( cfile ) fprintf (cfile, "?>");
+	if ( str )	 (*str) += "?>";
+}
+
+void TiXmlStylesheetReference::CopyTo( TiXmlStylesheetReference* target ) const
+{
+	TiXmlNode::CopyTo( target );
+
+	target->type = type;
+	target->href = href;
+}
+
+bool TiXmlStylesheetReference::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+TiXmlNode* TiXmlStylesheetReference::Clone() const
+{
+	TiXmlStylesheetReference* clone = new TiXmlStylesheetReference();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+void TiXmlUnknown::Print( FILE* cfile, int depth ) const
+{
+	for ( int i=0; i<depth; i++ )
+		fprintf( cfile, "    " );
+	fprintf( cfile, "<%s>", value.c_str() );
+}
+
+
+void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
+{
+	TiXmlNode::CopyTo( target );
+}
+
+
+bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
+{
+	return visitor->Visit( *this );
+}
+
+
+TiXmlNode* TiXmlUnknown::Clone() const
+{
+	TiXmlUnknown* clone = new TiXmlUnknown();
+
+	if ( !clone )
+		return 0;
+
+	CopyTo( clone );
+	return clone;
+}
+
+
+TiXmlAttributeSet::TiXmlAttributeSet()
+{
+	sentinel.next = &sentinel;
+	sentinel.prev = &sentinel;
+}
+
+
+TiXmlAttributeSet::~TiXmlAttributeSet()
+{
+	assert( sentinel.next == &sentinel );
+	assert( sentinel.prev == &sentinel );
+}
+
+
+void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
+{
+    #ifdef TIXML_USE_STL
+	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
+	#else
+	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
+	#endif
+
+	addMe->next = &sentinel;
+	addMe->prev = sentinel.prev;
+
+	sentinel.prev->next = addMe;
+	sentinel.prev      = addMe;
+}
+
+void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
+{
+	TiXmlAttribute* node;
+
+	for( node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node == removeMe )
+		{
+			node->prev->next = node->next;
+			node->next->prev = node->prev;
+			node->next = 0;
+			node->prev = 0;
+			return;
+		}
+	}
+	assert( 0 );		// we tried to remove a non-linked attribute.
+}
+
+
+#ifdef TIXML_USE_STL
+const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
+{
+	for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node->name == name )
+			return node;
+	}
+	return 0;
+}
+
+/*
+TiXmlAttribute*	TiXmlAttributeSet::Find( const std::string& name )
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( node->name == name )
+			return node;
+	}
+	return 0;
+}
+*/
+#endif
+
+
+const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
+{
+	for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( strcmp( node->name.c_str(), name ) == 0 )
+			return node;
+	}
+	return 0;
+}
+
+/*
+TiXmlAttribute*	TiXmlAttributeSet::Find( const char* name )
+{
+	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
+	{
+		if ( strcmp( node->name.c_str(), name ) == 0 )
+			return node;
+	}
+	return 0;
+}
+*/
+
+#ifdef TIXML_USE_STL
+std::istream& operator>> (std::istream & in, TiXmlNode & base)
+{
+	TIXML_STRING tag;
+	tag.reserve( 8 * 1000 );
+	base.StreamIn( &in, &tag );
+
+	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
+	return in;
+}
+#endif
+
+
+#ifdef TIXML_USE_STL
+std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
+{
+	TiXmlPrinter printer;
+	printer.SetStreamPrinting();
+	base.Accept( &printer );
+	out << printer.Str();
+
+	return out;
+}
+
+
+std::string& operator<< (std::string& out, const TiXmlNode& base )
+{
+	TiXmlPrinter printer;
+	printer.SetStreamPrinting();
+	base.Accept( &printer );
+	out.append( printer.Str() );
+
+	return out;
+}
+#endif
+
+
+TiXmlHandle TiXmlHandle::FirstChild() const
+{
+	if ( node )
+	{
+		TiXmlNode* child = node->FirstChild();
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
+{
+	if ( node )
+	{
+		TiXmlNode* child = node->FirstChild( value );
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement() const
+{
+	if ( node )
+	{
+		TiXmlElement* child = node->FirstChildElement();
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
+{
+	if ( node )
+	{
+		TiXmlElement* child = node->FirstChildElement( value );
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlNode* child = node->FirstChild();
+		for (	i=0;
+				child && i<count;
+				child = child->NextSibling(), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlNode* child = node->FirstChild( value );
+		for (	i=0;
+				child && i<count;
+				child = child->NextSibling( value ), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlElement* child = node->FirstChildElement();
+		for (	i=0;
+				child && i<count;
+				child = child->NextSiblingElement(), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
+{
+	if ( node )
+	{
+		int i;
+		TiXmlElement* child = node->FirstChildElement( value );
+		for (	i=0;
+				child && i<count;
+				child = child->NextSiblingElement( value ), ++i )
+		{
+			// nothing
+		}
+		if ( child )
+			return TiXmlHandle( child );
+	}
+	return TiXmlHandle( 0 );
+}
+
+
+bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
+{
+	return true;
+}
+
+bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
+{
+	return true;
+}
+
+bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
+{
+	DoIndent();
+	buffer += "<";
+	buffer += element.Value();
+
+	for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
+	{
+		buffer += " ";
+		attrib->Print( 0, 0, &buffer );
+	}
+
+	if ( !element.FirstChild() )
+	{
+		buffer += " />";
+		DoLineBreak();
+	}
+	else
+	{
+		buffer += ">";
+		if (    element.FirstChild()->ToText()
+			  && element.LastChild() == element.FirstChild()
+			  && element.FirstChild()->ToText()->CDATA() == false )
+		{
+			simpleTextPrint = true;
+			// no DoLineBreak()!
+		}
+		else
+		{
+			DoLineBreak();
+		}
+	}
+	++depth;
+	return true;
+}
+
+
+bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
+{
+	--depth;
+	if ( !element.FirstChild() )
+	{
+		// nothing.
+	}
+	else
+	{
+		if ( simpleTextPrint )
+		{
+			simpleTextPrint = false;
+		}
+		else
+		{
+			DoIndent();
+		}
+		buffer += "</";
+		buffer += element.Value();
+		buffer += ">";
+		DoLineBreak();
+	}
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlText& text )
+{
+	if ( text.CDATA() )
+	{
+		DoIndent();
+		buffer += "<![CDATA[";
+		buffer += text.Value();
+		buffer += "]]>";
+		DoLineBreak();
+	}
+	else if ( simpleTextPrint )
+	{
+		TIXML_STRING str;
+		TiXmlBase::EncodeString( text.ValueTStr(), &str );
+		buffer += str;
+	}
+	else
+	{
+		DoIndent();
+		TIXML_STRING str;
+		TiXmlBase::EncodeString( text.ValueTStr(), &str );
+		buffer += str;
+		DoLineBreak();
+	}
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
+{
+	DoIndent();
+	declaration.Print( 0, 0, &buffer );
+	DoLineBreak();
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlComment& comment )
+{
+	DoIndent();
+	buffer += "<!--";
+	buffer += comment.Value();
+	buffer += "-->";
+	DoLineBreak();
+	return true;
+}
+
+
+bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
+{
+	DoIndent();
+	buffer += "<";
+	buffer += unknown.Value();
+	buffer += ">";
+	DoLineBreak();
+	return true;
+}
+
+bool TiXmlPrinter::Visit( const TiXmlStylesheetReference& stylesheet )
+{
+	    DoIndent();
+	    stylesheet.Print( 0, 0, &buffer );
+	    DoLineBreak();
+	    return true;
+}
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxml.h
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxml.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxml.h	(revision 11817)
@@ -0,0 +1,1884 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TINYXML_INCLUDED
+#define TINYXML_INCLUDED
+
+#ifdef _MSC_VER
+#pragma warning( push )
+#pragma warning( disable : 4530 )
+#pragma warning( disable : 4786 )
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// Help out windows:
+#if defined( _DEBUG ) && !defined( DEBUG )
+#define DEBUG
+#endif
+
+#ifdef TIXML_USE_TICPP
+	#ifndef TIXML_USE_STL
+		#define TIXML_USE_STL
+	#endif
+#endif
+
+#ifdef TIXML_USE_STL
+	#include <string>
+ 	#include <iostream>
+	#include <sstream>
+	#define TIXML_STRING		std::string
+#else
+	#include "tinystr.h"
+	#define TIXML_STRING		TiXmlString
+#endif
+
+// Deprecated library function hell. Compilers want to use the
+// new safe versions. This probably doesn't fully address the problem,
+// but it gets closer. There are too many compilers for me to fully
+// test. If you get compilation troubles, undefine TIXML_SAFE
+#define TIXML_SAFE
+
+#ifdef TIXML_SAFE
+	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		// Microsoft visual studio, version 2005 and higher.
+		#define TIXML_SNPRINTF _snprintf_s
+		#define TIXML_SNSCANF  _snscanf_s
+		#define TIXML_SSCANF   sscanf_s
+	#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
+		// Microsoft visual studio, version 6 and higher.
+		//#pragma message( "Using _sn* functions." )
+		#define TIXML_SNPRINTF _snprintf
+		#define TIXML_SNSCANF  _snscanf
+		#define TIXML_SSCANF   sscanf
+	#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+		// GCC version 3 and higher.s
+		//#warning( "Using sn* functions." )
+		#define TIXML_SNPRINTF snprintf
+		#define TIXML_SNSCANF  snscanf
+		#define TIXML_SSCANF   sscanf
+	#else
+		#define TIXML_SSCANF   sscanf
+	#endif
+#endif
+
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlStylesheetReference;
+class TiXmlParsingData;
+
+const int TIXML_MAJOR_VERSION = 2;
+const int TIXML_MINOR_VERSION = 5;
+const int TIXML_PATCH_VERSION = 3;
+
+/*	Internal structure for tracking location of items
+	in the XML file.
+*/
+struct TiXmlCursor
+{
+	TiXmlCursor()		{ Clear(); }
+	void Clear()		{ row = col = -1; }
+
+	int row;	// 0 based.
+	int col;	// 0 based.
+};
+
+
+/**
+	If you call the Accept() method, it requires being passed a TiXmlVisitor
+	class to handle callbacks. For nodes that contain other nodes (Document, Element)
+	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
+	are simple called with Visit().
+
+	If you return 'true' from a Visit method, recursive parsing will continue. If you return
+	false, <b>no children of this node or its sibilings</b> will be Visited.
+
+	All flavors of Visit methods have a default implementation that returns 'true' (continue
+	visiting). You need to only override methods that are interesting to you.
+
+	Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
+
+	You should never change the document from a callback.
+
+	@sa TiXmlNode::Accept()
+*/
+class TiXmlVisitor
+{
+public:
+	virtual ~TiXmlVisitor() {}
+
+	/// Visit a document.
+	virtual bool VisitEnter( const TiXmlDocument& /*doc*/ )			{ return true; }
+	/// Visit a document.
+	virtual bool VisitExit( const TiXmlDocument& /*doc*/ )			{ return true; }
+
+	/// Visit an element.
+	virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ )	{ return true; }
+	/// Visit an element.
+	virtual bool VisitExit( const TiXmlElement& /*element*/ )		{ return true; }
+
+	/// Visit a declaration
+	virtual bool Visit( const TiXmlDeclaration& /*declaration*/ )	{ return true; }
+	/// Visit a stylesheet reference
+	virtual bool Visit( const TiXmlStylesheetReference& /*stylesheet*/ )	{ return true; }
+	/// Visit a text node
+	virtual bool Visit( const TiXmlText& /*text*/ )					{ return true; }
+	/// Visit a comment node
+	virtual bool Visit( const TiXmlComment& /*comment*/ )			{ return true; }
+	/// Visit an unknow node
+	virtual bool Visit( const TiXmlUnknown& /*unknown*/ )			{ return true; }
+};
+
+// Only used by Attribute::Query functions
+enum
+{
+	TIXML_SUCCESS,
+	TIXML_NO_ATTRIBUTE,
+	TIXML_WRONG_TYPE
+};
+
+
+// Used by the parsing routines.
+enum TiXmlEncoding
+{
+	TIXML_ENCODING_UNKNOWN,
+	TIXML_ENCODING_UTF8,
+	TIXML_ENCODING_LEGACY
+};
+
+const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
+
+/** TiXmlBase is a base class for every class in TinyXml.
+	It does little except to establish that TinyXml classes
+	can be printed and provide some utility functions.
+
+	In XML, the document and elements can contain
+	other elements and other types of nodes.
+
+	@verbatim
+	A Document can contain:	Element	(container or leaf)
+							Comment (leaf)
+							Unknown (leaf)
+							Declaration( leaf )
+
+	An Element can contain:	Element (container or leaf)
+							Text	(leaf)
+							Attributes (not on tree)
+							Comment (leaf)
+							Unknown (leaf)
+
+	A Decleration contains: Attributes (not on tree)
+	@endverbatim
+*/
+#ifdef TIXML_USE_TICPP
+#include "ticpprc.h"
+class TiXmlBase : public TiCppRC
+#else
+class TiXmlBase
+#endif
+{
+	friend class TiXmlNode;
+	friend class TiXmlElement;
+	friend class TiXmlDocument;
+
+public:
+	TiXmlBase()	:	userData(0)		{}
+	virtual ~TiXmlBase()			{}
+
+	/**	All TinyXml classes can print themselves to a filestream
+		or the string class (TiXmlString in non-STL mode, std::string
+		in STL mode.) Either or both cfile and str can be null.
+
+		This is a formatted print, and will insert
+		tabs and newlines.
+
+		(For an unformatted stream, use the << operator.)
+	*/
+	virtual void Print( FILE* cfile, int depth ) const = 0;
+
+	/**	The world does not agree on whether white space should be kept or
+		not. In order to make everyone happy, these global, static functions
+		are provided to set whether or not TinyXml will condense all white space
+		into a single space or not. The default is to condense. Note changing this
+		value is not thread safe.
+	*/
+	static void SetCondenseWhiteSpace( bool condense )		{ condenseWhiteSpace = condense; }
+
+	/// Return the current white space setting.
+	static bool IsWhiteSpaceCondensed()						{ return condenseWhiteSpace; }
+
+	/** Return the position, in the original source file, of this node or attribute.
+		The row and column are 1-based. (That is the first row and first column is
+		1,1). If the returns values are 0 or less, then the parser does not have
+		a row and column value.
+
+		Generally, the row and column value will be set when the TiXmlDocument::Load(),
+		TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
+		when the DOM was created from operator>>.
+
+		The values reflect the initial load. Once the DOM is modified programmatically
+		(by adding or changing nodes and attributes) the new values will NOT update to
+		reflect changes in the document.
+
+		There is a minor performance cost to computing the row and column. Computation
+		can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
+
+		@sa TiXmlDocument::SetTabSize()
+	*/
+	int Row() const			{ return location.row + 1; }
+	int Column() const		{ return location.col + 1; }	///< See Row()
+
+	void  SetUserData( void* user )			{ userData = user; }	///< Set a pointer to arbitrary user data.
+	void* GetUserData()						{ return userData; }	///< Get a pointer to arbitrary user data.
+	const void* GetUserData() const 		{ return userData; }	///< Get a pointer to arbitrary user data.
+
+	// Table that returs, for a given lead byte, the total number of bytes
+	// in the UTF-8 sequence.
+	static const int utf8ByteTable[256];
+
+	virtual const char* Parse(	const char* p,
+								TiXmlParsingData* data,
+								TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
+
+	/** Expands entities in a string. Note this should not contian the tag's '<', '>', etc,
+		or they will be transformed into entities!
+	*/
+	static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out );
+
+	enum
+	{
+		TIXML_NO_ERROR = 0,
+		TIXML_ERROR,
+		TIXML_ERROR_OPENING_FILE,
+		TIXML_ERROR_OUT_OF_MEMORY,
+		TIXML_ERROR_PARSING_ELEMENT,
+		TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
+		TIXML_ERROR_READING_ELEMENT_VALUE,
+		TIXML_ERROR_READING_ATTRIBUTES,
+		TIXML_ERROR_PARSING_EMPTY,
+		TIXML_ERROR_READING_END_TAG,
+		TIXML_ERROR_PARSING_UNKNOWN,
+		TIXML_ERROR_PARSING_COMMENT,
+		TIXML_ERROR_PARSING_DECLARATION,
+		TIXML_ERROR_DOCUMENT_EMPTY,
+		TIXML_ERROR_EMBEDDED_NULL,
+		TIXML_ERROR_PARSING_CDATA,
+		TIXML_ERROR_DOCUMENT_TOP_ONLY,
+
+		TIXML_ERROR_STRING_COUNT
+	};
+
+protected:
+
+	static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding );
+	inline static bool IsWhiteSpace( char c )
+	{
+		return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' );
+	}
+	inline static bool IsWhiteSpace( int c )
+	{
+		if ( c < 256 )
+			return IsWhiteSpace( (char) c );
+		return false;	// Again, only truly correct for English/Latin...but usually works.
+	}
+
+	#ifdef TIXML_USE_STL
+	static bool	StreamWhiteSpace( std::istream * in, TIXML_STRING * tag );
+	static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag );
+	#endif
+
+	/*	Reads an XML name into the string provided. Returns
+		a pointer just past the last character of the name,
+		or 0 if the function has an error.
+	*/
+	static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
+
+	/*	Reads text. Returns a pointer past the given end tag.
+		Wickedly complex options, but it keeps the (sensitive) code in one place.
+	*/
+	static const char* ReadText(	const char* in,				// where to start
+									TIXML_STRING* text,			// the string read
+									bool ignoreWhiteSpace,		// whether to keep the white space
+									const char* endTag,			// what ends this text
+									bool ignoreCase,			// whether to ignore case in the end tag
+									TiXmlEncoding encoding );	// the current encoding
+
+	// If an entity has been found, transform it into a character.
+	static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
+
+	// Get a character, while interpreting entities.
+	// The length can be from 0 to 4 bytes.
+	inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
+	{
+		assert( p );
+		if ( encoding == TIXML_ENCODING_UTF8 )
+		{
+			*length = utf8ByteTable[ *((const unsigned char*)p) ];
+			assert( *length >= 0 && *length < 5 );
+		}
+		else
+		{
+			*length = 1;
+		}
+
+		if ( *length == 1 )
+		{
+			if ( *p == '&' )
+				return GetEntity( p, _value, length, encoding );
+			*_value = *p;
+			return p+1;
+		}
+		else if ( *length )
+		{
+			//strncpy( _value, p, *length );	// lots of compilers don't like this function (unsafe),
+												// and the null terminator isn't needed
+			for( int i=0; p[i] && i<*length; ++i ) {
+				_value[i] = p[i];
+			}
+			return p + (*length);
+		}
+		else
+		{
+			// Not valid text.
+			return 0;
+		}
+	}
+
+	// Return true if the next characters in the stream are any of the endTag sequences.
+	// Ignore case only works for english, and should only be relied on when comparing
+	// to English words: StringEqual( p, "version", true ) is fine.
+	static bool StringEqual(	const char* p,
+								const char* endTag,
+								bool ignoreCase,
+								TiXmlEncoding encoding );
+
+	static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
+
+	TiXmlCursor location;
+
+    /// Field containing a generic user pointer
+	void*			userData;
+
+	// None of these methods are reliable for any language except English.
+	// Good for approximation, not great for accuracy.
+	static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
+	static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
+	inline static int ToLower( int v, TiXmlEncoding encoding )
+	{
+		if ( encoding == TIXML_ENCODING_UTF8 )
+		{
+			if ( v < 128 ) return tolower( v );
+			return v;
+		}
+		else
+		{
+			return tolower( v );
+		}
+	}
+	static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
+
+private:
+	TiXmlBase( const TiXmlBase& );				// not implemented.
+	void operator=( const TiXmlBase& base );	// not allowed.
+
+	struct Entity
+	{
+		const char*     str;
+		unsigned int	strLength;
+		char		    chr;
+	};
+	enum
+	{
+		NUM_ENTITY = 5,
+		MAX_ENTITY_LENGTH = 6
+
+	};
+	static Entity entity[ NUM_ENTITY ];
+	static bool condenseWhiteSpace;
+};
+
+
+/** The parent class for everything in the Document Object Model.
+	(Except for attributes).
+	Nodes have siblings, a parent, and children. A node can be
+	in a document, or stand on its own. The type of a TiXmlNode
+	can be queried, and it can be cast to its more defined type.
+*/
+class TiXmlNode : public TiXmlBase
+{
+	friend class TiXmlDocument;
+	friend class TiXmlElement;
+
+public:
+	#ifdef TIXML_USE_STL
+
+	    /** An input stream operator, for every class. Tolerant of newlines and
+		    formatting, but doesn't expect them.
+	    */
+	    friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
+
+	    /** An output stream operator, for every class. Note that this outputs
+		    without any newlines or formatting, as opposed to Print(), which
+		    includes tabs and new lines.
+
+		    The operator<< and operator>> are not completely symmetric. Writing
+		    a node to a stream is very well defined. You'll get a nice stream
+		    of output, without any extra whitespace or newlines.
+
+		    But reading is not as well defined. (As it always is.) If you create
+		    a TiXmlElement (for example) and read that from an input stream,
+		    the text needs to define an element or junk will result. This is
+		    true of all input streams, but it's worth keeping in mind.
+
+		    A TiXmlDocument will read nodes until it reads a root element, and
+			all the children of that root element.
+	    */
+	    friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
+
+		/// Appends the XML node or attribute to a std::string.
+		friend std::string& operator<< (std::string& out, const TiXmlNode& base );
+
+	#endif
+
+	/** The types of XML nodes supported by TinyXml. (All the
+			unsupported types are picked up by UNKNOWN.)
+	*/
+	enum NodeType
+	{
+		DOCUMENT,
+		ELEMENT,
+		COMMENT,
+		UNKNOWN,
+		TEXT,
+		DECLARATION,
+		STYLESHEETREFERENCE,
+		TYPECOUNT
+	};
+
+	virtual ~TiXmlNode();
+
+	/** The meaning of 'value' changes for the specific type of
+		TiXmlNode.
+		@verbatim
+		Document:	filename of the xml file
+		Element:	name of the element
+		Comment:	the comment text
+		Unknown:	the tag contents
+		Text:		the text string
+		@endverbatim
+
+		The subclasses will wrap this function.
+	*/
+	const char *Value() const { return value.c_str (); }
+
+    #ifdef TIXML_USE_STL
+	/** Return Value() as a std::string. If you only use STL,
+	    this is more efficient than calling Value().
+		Only available in STL mode.
+	*/
+	const std::string& ValueStr() const { return value; }
+	#endif
+
+	const TIXML_STRING& ValueTStr() const { return value; }
+
+	/** Changes the value of the node. Defined as:
+		@verbatim
+		Document:	filename of the xml file
+		Element:	name of the element
+		Comment:	the comment text
+		Unknown:	the tag contents
+		Text:		the text string
+		@endverbatim
+	*/
+	void SetValue(const char * _value) { value = _value;}
+
+    #ifdef TIXML_USE_STL
+	/// STL std::string form.
+	void SetValue( const std::string& _value )	{ value = _value; }
+	#endif
+
+	/// Delete all the children of this node. Does not affect 'this'.
+	void Clear();
+
+	/// One step up the DOM.
+	TiXmlNode* Parent()							{ return parent; }
+	const TiXmlNode* Parent() const				{ return parent; }
+
+	const TiXmlNode* FirstChild()	const		{ return firstChild; }	///< The first child of this node. Will be null if there are no children.
+	TiXmlNode* FirstChild()						{ return firstChild; }
+	const TiXmlNode* FirstChild( const char * value ) const;			///< The first child of this node with the matching 'value'. Will be null if none found.
+	/// The first child of this node with the matching 'value'. Will be null if none found.
+	TiXmlNode* FirstChild( const char * _value ) {
+		// Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe)
+		// call the method, cast the return back to non-const.
+		return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value ));
+	}
+	const TiXmlNode* LastChild() const	{ return lastChild; }		/// The last child of this node. Will be null if there are no children.
+	TiXmlNode* LastChild()	{ return lastChild; }
+
+	const TiXmlNode* LastChild( const char * value ) const;			/// The last child of this node matching 'value'. Will be null if there are no children.
+	TiXmlNode* LastChild( const char * _value ) {
+		return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value ));
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlNode* FirstChild( const std::string& _value ) const	{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* FirstChild( const std::string& _value )				{	return FirstChild (_value.c_str ());	}	///< STL std::string form.
+	const TiXmlNode* LastChild( const std::string& _value ) const	{	return LastChild (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* LastChild( const std::string& _value )				{	return LastChild (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/** An alternate way to walk the children of a node.
+		One way to iterate over nodes is:
+		@verbatim
+			for( child = parent->FirstChild(); child; child = child->NextSibling() )
+		@endverbatim
+
+		IterateChildren does the same thing with the syntax:
+		@verbatim
+			child = 0;
+			while( child = parent->IterateChildren( child ) )
+		@endverbatim
+
+		IterateChildren takes the previous child as input and finds
+		the next one. If the previous child is null, it returns the
+		first. IterateChildren will return null when done.
+	*/
+	const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
+	TiXmlNode* IterateChildren( const TiXmlNode* previous ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) );
+	}
+
+	/// This flavor of IterateChildren searches for children with a particular 'value'
+	const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
+	TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const	{	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
+	TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) {	return IterateChildren (_value.c_str (), previous);	}	///< STL std::string form.
+	#endif
+
+	/** Add a new node related to this. Adds a child past the LastChild.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
+
+
+	/** Add a new node related to this. Adds a child past the LastChild.
+
+		NOTE: the node to be added is passed by pointer, and will be
+		henceforth owned (and deleted) by tinyXml. This method is efficient
+		and avoids an extra copy, but should be used with care as it
+		uses a different memory model than the other insert functions.
+
+		@sa InsertEndChild
+	*/
+	TiXmlNode* LinkEndChild( TiXmlNode* addThis );
+
+	/** Add a new node related to this. Adds a child before the specified child.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
+
+	/** Add a new node related to this. Adds a child after the specified child.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
+
+	/** Replace a child of this node.
+		Returns a pointer to the new object or NULL if an error occured.
+	*/
+	TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
+
+	/// Delete a child of this node.
+	bool RemoveChild( TiXmlNode* removeThis );
+
+	/// Navigate to a sibling node.
+	const TiXmlNode* PreviousSibling() const			{ return prev; }
+	TiXmlNode* PreviousSibling()						{ return prev; }
+
+	/// Navigate to a sibling node.
+	const TiXmlNode* PreviousSibling( const char * ) const;
+	TiXmlNode* PreviousSibling( const char *_prev ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlNode* PreviousSibling( const std::string& _value ) const	{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* PreviousSibling( const std::string& _value ) 			{	return PreviousSibling (_value.c_str ());	}	///< STL std::string form.
+	const TiXmlNode* NextSibling( const std::string& _value) const		{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
+	TiXmlNode* NextSibling( const std::string& _value) 					{	return NextSibling (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Navigate to a sibling node.
+	const TiXmlNode* NextSibling() const				{ return next; }
+	TiXmlNode* NextSibling()							{ return next; }
+
+	/// Navigate to a sibling node with the given 'value'.
+	const TiXmlNode* NextSibling( const char * ) const;
+	TiXmlNode* NextSibling( const char* _next ) {
+		return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) );
+	}
+
+	/** Convenience function to get through elements.
+		Calls NextSibling and ToElement. Will skip all non-Element
+		nodes. Returns 0 if there is not another element.
+	*/
+	const TiXmlElement* NextSiblingElement() const;
+	TiXmlElement* NextSiblingElement() {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() );
+	}
+
+	/** Convenience function to get through elements.
+		Calls NextSibling and ToElement. Will skip all non-Element
+		nodes. Returns 0 if there is not another element.
+	*/
+	const TiXmlElement* NextSiblingElement( const char * ) const;
+	TiXmlElement* NextSiblingElement( const char *_next ) {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlElement* NextSiblingElement( const std::string& _value) const	{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
+	TiXmlElement* NextSiblingElement( const std::string& _value)				{	return NextSiblingElement (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/// Convenience function to get through elements.
+	const TiXmlElement* FirstChildElement()	const;
+	TiXmlElement* FirstChildElement() {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() );
+	}
+
+	/// Convenience function to get through elements.
+	const TiXmlElement* FirstChildElement( const char * _value ) const;
+	TiXmlElement* FirstChildElement( const char * _value ) {
+		return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) );
+	}
+
+    #ifdef TIXML_USE_STL
+	const TiXmlElement* FirstChildElement( const std::string& _value ) const	{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
+	TiXmlElement* FirstChildElement( const std::string& _value )				{	return FirstChildElement (_value.c_str ());	}	///< STL std::string form.
+	#endif
+
+	/** Query the type (as an enumerated value, above) of this node.
+		The possible types are: DOCUMENT, ELEMENT, COMMENT,
+								UNKNOWN, TEXT, and DECLARATION.
+	*/
+	int Type() const	{ return type; }
+
+	/** Return a pointer to the Document this node lives in.
+		Returns null if not in a document.
+	*/
+	const TiXmlDocument* GetDocument() const;
+	TiXmlDocument* GetDocument() {
+		return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() );
+	}
+
+	/// Returns true if this node has no children.
+	bool NoChildren() const						{ return !firstChild; }
+
+	virtual const TiXmlDocument*    ToDocument()    const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlElement*     ToElement()     const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlComment*     ToComment()     const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlUnknown*     ToUnknown()     const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlText*        ToText()        const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual const TiXmlStylesheetReference* ToStylesheetReference() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+	virtual TiXmlDocument*          ToDocument()    { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlElement*           ToElement()	    { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlComment*           ToComment()     { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlUnknown*           ToUnknown()	    { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlText*	            ToText()        { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlDeclaration*       ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+	virtual TiXmlStylesheetReference*       ToStylesheetReference() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type.
+
+	/** Create an exact duplicate of this node and return it. The memory must be deleted
+		by the caller.
+	*/
+	virtual TiXmlNode* Clone() const = 0;
+
+	/** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
+		XML tree will be conditionally visited and the host will be called back
+		via the TiXmlVisitor interface.
+
+		This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
+		the XML for the callbacks, so the performance of TinyXML is unchanged by using this
+		interface versus any other.)
+
+		The interface has been based on ideas from:
+
+		- http://www.saxproject.org/
+		- http://c2.com/cgi/wiki?HierarchicalVisitorPattern
+
+		Which are both good references for "visiting".
+
+		An example of using Accept():
+		@verbatim
+		TiXmlPrinter printer;
+		tinyxmlDoc.Accept( &printer );
+		const char* xmlcstr = printer.CStr();
+		@endverbatim
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const = 0;
+
+protected:
+	TiXmlNode( NodeType _type );
+
+	// Copy to the allocated object. Shared functionality between Clone, Copy constructor,
+	// and the assignment operator.
+	void CopyTo( TiXmlNode* target ) const;
+
+	#ifdef TIXML_USE_STL
+	    // The real work of the input operator.
+	virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0;
+	#endif
+
+	// Figure out what is at *p, and parse it. Returns null if it is not an xml node.
+	TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
+
+	TiXmlNode*		parent;
+	NodeType		type;
+
+	TiXmlNode*		firstChild;
+	TiXmlNode*		lastChild;
+
+	TIXML_STRING	value;
+
+	TiXmlNode*		prev;
+	TiXmlNode*		next;
+
+private:
+	TiXmlNode( const TiXmlNode& );				// not implemented.
+	void operator=( const TiXmlNode& base );	// not allowed.
+};
+
+
+/** An attribute is a name-value pair. Elements have an arbitrary
+	number of attributes, each with a unique name.
+
+	@note The attributes are not TiXmlNodes, since they are not
+		  part of the tinyXML document object model. There are other
+		  suggested ways to look at this problem.
+*/
+class TiXmlAttribute : public TiXmlBase
+{
+	friend class TiXmlAttributeSet;
+
+public:
+	/// Construct an empty attribute.
+	TiXmlAttribute() : TiXmlBase()
+	{
+		document = 0;
+		prev = next = 0;
+	}
+
+	#ifdef TIXML_USE_STL
+	/// std::string constructor.
+	TiXmlAttribute( const std::string& _name, const std::string& _value )
+	{
+		name = _name;
+		value = _value;
+		document = 0;
+		prev = next = 0;
+	}
+	#endif
+
+	/// Construct an attribute with a name and value.
+	TiXmlAttribute( const char * _name, const char * _value )
+	{
+		name = _name;
+		value = _value;
+		document = 0;
+		prev = next = 0;
+	}
+
+	const char*		Name()  const		{ return name.c_str(); }		///< Return the name of this attribute.
+	const char*		Value() const		{ return value.c_str(); }		///< Return the value of this attribute.
+	#ifdef TIXML_USE_STL
+	const std::string& ValueStr() const	{ return value; }				///< Return the value of this attribute.
+	#endif
+	int				IntValue() const;									///< Return the value of this attribute, converted to an integer.
+	double			DoubleValue() const;								///< Return the value of this attribute, converted to a double.
+
+	// Get the tinyxml string representation
+	const TIXML_STRING& NameTStr() const { return name; }
+
+	/** QueryIntValue examines the value string. It is an alternative to the
+		IntValue() method with richer error checking.
+		If the value is an integer, it is stored in 'value' and
+		the call returns TIXML_SUCCESS. If it is not
+		an integer, it returns TIXML_WRONG_TYPE.
+
+		A specialized but useful call. Note that for success it returns 0,
+		which is the opposite of almost all other TinyXml calls.
+	*/
+	int QueryIntValue( int* _value ) const;
+	/// QueryDoubleValue examines the value string. See QueryIntValue().
+	int QueryDoubleValue( double* _value ) const;
+
+	void SetName( const char* _name )	{ name = _name; }				///< Set the name of this attribute.
+	void SetValue( const char* _value )	{ value = _value; }				///< Set the value.
+
+	void SetIntValue( int _value );										///< Set the value from an integer.
+	void SetDoubleValue( double _value );								///< Set the value from a double.
+
+    #ifdef TIXML_USE_STL
+	/// STL std::string form.
+	void SetName( const std::string& _name )	{ name = _name; }
+	/// STL std::string form.
+	void SetValue( const std::string& _value )	{ value = _value; }
+	#endif
+
+	/// Get the next sibling attribute in the DOM. Returns null at end.
+	const TiXmlAttribute* Next() const;
+	TiXmlAttribute* Next() {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() );
+	}
+
+	/// Get the previous sibling attribute in the DOM. Returns null at beginning.
+	const TiXmlAttribute* Previous() const;
+	TiXmlAttribute* Previous() {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() );
+	}
+
+	bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
+	bool operator<( const TiXmlAttribute& rhs )	 const { return name < rhs.name; }
+	bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
+
+	/*	Attribute parsing starts: first letter of the name
+						 returns: the next char after the value end quote
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	// Prints this Attribute to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const {
+		Print( cfile, depth, 0 );
+	}
+	void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+
+	// [internal use]
+	// Set the document pointer so the attribute can report errors.
+	void SetDocument( TiXmlDocument* doc )	{ document = doc; }
+
+private:
+	TiXmlAttribute( const TiXmlAttribute& );				// not implemented.
+	void operator=( const TiXmlAttribute& base );	// not allowed.
+
+	TiXmlDocument*	document;	// A pointer back to a document, for error reporting.
+	TIXML_STRING name;
+	TIXML_STRING value;
+	TiXmlAttribute*	prev;
+	TiXmlAttribute*	next;
+};
+
+
+/*	A class used to manage a group of attributes.
+	It is only used internally, both by the ELEMENT and the DECLARATION.
+
+	The set can be changed transparent to the Element and Declaration
+	classes that use it, but NOT transparent to the Attribute
+	which has to implement a next() and previous() method. Which makes
+	it a bit problematic and prevents the use of STL.
+
+	This version is implemented with circular lists because:
+		- I like circular lists
+		- it demonstrates some independence from the (typical) doubly linked list.
+*/
+class TiXmlAttributeSet
+{
+public:
+	TiXmlAttributeSet();
+	~TiXmlAttributeSet();
+
+	void Add( TiXmlAttribute* attribute );
+	void Remove( TiXmlAttribute* attribute );
+
+	const TiXmlAttribute* First()	const	{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+	TiXmlAttribute* First()					{ return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
+	const TiXmlAttribute* Last() const		{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+	TiXmlAttribute* Last()					{ return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
+
+	const TiXmlAttribute*	Find( const char* _name ) const;
+	TiXmlAttribute*	Find( const char* _name ) {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
+	}
+	#ifdef TIXML_USE_STL
+	const TiXmlAttribute*	Find( const std::string& _name ) const;
+	TiXmlAttribute*	Find( const std::string& _name ) {
+		return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) );
+	}
+
+	#endif
+
+private:
+	//*ME:	Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
+	//*ME:	this class must be also use a hidden/disabled copy-constructor !!!
+	TiXmlAttributeSet( const TiXmlAttributeSet& );	// not allowed
+	void operator=( const TiXmlAttributeSet& );	// not allowed (as TiXmlAttribute)
+
+	TiXmlAttribute sentinel;
+};
+
+
+/** The element is a container class. It has a value, the element name,
+	and can contain other elements, text, comments, and unknowns.
+	Elements also contain an arbitrary number of attributes.
+*/
+class TiXmlElement : public TiXmlNode
+{
+public:
+	/// Construct an element.
+	TiXmlElement (const char * in_value);
+
+	#ifdef TIXML_USE_STL
+	/// std::string constructor.
+	TiXmlElement( const std::string& _value );
+	#endif
+
+	TiXmlElement( const TiXmlElement& );
+
+	void operator=( const TiXmlElement& base );
+
+	virtual ~TiXmlElement();
+
+	/** Given an attribute name, Attribute() returns the value
+		for the attribute of that name, or null if none exists.
+	*/
+	const char* Attribute( const char* name ) const;
+
+	/** Given an attribute name, Attribute() returns the value
+		for the attribute of that name, or null if none exists.
+		If the attribute exists and can be converted to an integer,
+		the integer value will be put in the return 'i', if 'i'
+		is non-null.
+	*/
+	const char* Attribute( const char* name, int* i ) const;
+
+	/** Given an attribute name, Attribute() returns the value
+		for the attribute of that name, or null if none exists.
+		If the attribute exists and can be converted to an double,
+		the double value will be put in the return 'd', if 'd'
+		is non-null.
+	*/
+	const char* Attribute( const char* name, double* d ) const;
+
+	/** QueryIntAttribute examines the attribute - it is an alternative to the
+		Attribute() method with richer error checking.
+		If the attribute is an integer, it is stored in 'value' and
+		the call returns TIXML_SUCCESS. If it is not
+		an integer, it returns TIXML_WRONG_TYPE. If the attribute
+		does not exist, then TIXML_NO_ATTRIBUTE is returned.
+	*/
+	int QueryIntAttribute( const char* name, int* _value ) const;
+	/// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
+	int QueryDoubleAttribute( const char* name, double* _value ) const;
+	/// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
+	int QueryFloatAttribute( const char* name, float* _value ) const {
+		double d;
+		int result = QueryDoubleAttribute( name, &d );
+		if ( result == TIXML_SUCCESS ) {
+			*_value = (float)d;
+		}
+		return result;
+	}
+
+    #ifdef TIXML_USE_STL
+	/** Template form of the attribute query which will try to read the
+		attribute into the specified type. Very easy, very powerful, but
+		be careful to make sure to call this with the correct type.
+
+		NOTE: This method doesn't work correctly for 'string' types.
+
+		@return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE
+	*/
+	template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const
+	{
+		const TiXmlAttribute* node = attributeSet.Find( name );
+		if ( !node )
+			return TIXML_NO_ATTRIBUTE;
+
+		std::stringstream sstream( node->ValueStr() );
+		sstream >> *outValue;
+		if ( !sstream.fail() )
+			return TIXML_SUCCESS;
+		return TIXML_WRONG_TYPE;
+	}
+	/*
+	 This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string"
+	 but template specialization is hard to get working cross-compiler. Leaving the bug for now.
+
+	// The above will fail for std::string because the space character is used as a seperator.
+	// Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string
+	template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const
+	{
+		const TiXmlAttribute* node = attributeSet.Find( name );
+		if ( !node )
+			return TIXML_NO_ATTRIBUTE;
+		*outValue = node->ValueStr();
+		return TIXML_SUCCESS;
+	}
+	*/
+	#endif
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetAttribute( const char* name, const char * _value );
+
+    #ifdef TIXML_USE_STL
+	const std::string* Attribute( const std::string& name ) const;
+	const std::string* Attribute( const std::string& name, int* i ) const;
+	const std::string* Attribute( const std::string& name, double* d ) const;
+	int QueryIntAttribute( const std::string& name, int* _value ) const;
+	int QueryDoubleAttribute( const std::string& name, double* _value ) const;
+
+	/// STL std::string form.
+	void SetAttribute( const std::string& name, const std::string& _value );
+	///< STL std::string form.
+	void SetAttribute( const std::string& name, int _value );
+	#endif
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetAttribute( const char * name, int value );
+
+	/** Sets an attribute of name to a given value. The attribute
+		will be created if it does not exist, or changed if it does.
+	*/
+	void SetDoubleAttribute( const char * name, double value );
+
+	/** Deletes an attribute with the given name.
+	*/
+	void RemoveAttribute( const char * name );
+    #ifdef TIXML_USE_STL
+	void RemoveAttribute( const std::string& name )	{	RemoveAttribute (name.c_str ());	}	///< STL std::string form.
+	#endif
+
+	const TiXmlAttribute* FirstAttribute() const	{ return attributeSet.First(); }		///< Access the first attribute in this element.
+	TiXmlAttribute* FirstAttribute() 				{ return attributeSet.First(); }
+	const TiXmlAttribute* LastAttribute()	const 	{ return attributeSet.Last(); }		///< Access the last attribute in this element.
+	TiXmlAttribute* LastAttribute()					{ return attributeSet.Last(); }
+
+	/** Convenience function for easy access to the text inside an element. Although easy
+		and concise, GetText() is limited compared to getting the TiXmlText child
+		and accessing it directly.
+
+		If the first child of 'this' is a TiXmlText, the GetText()
+		returns the character string of the Text node, else null is returned.
+
+		This is a convenient method for getting the text of simple contained text:
+		@verbatim
+		<foo>This is text</foo>
+		const char* str = fooElement->GetText();
+		@endverbatim
+
+		'str' will be a pointer to "This is text".
+
+		Note that this function can be misleading. If the element foo was created from
+		this XML:
+		@verbatim
+		<foo><b>This is text</b></foo>
+		@endverbatim
+
+		then the value of str would be null. The first child node isn't a text node, it is
+		another element. From this XML:
+		@verbatim
+		<foo>This is <b>text</b></foo>
+		@endverbatim
+		GetText() will return "This is ".
+
+		WARNING: GetText() accesses a child node - don't become confused with the
+				 similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are
+				 safe type casts on the referenced node.
+	*/
+	const char* GetText() const;
+
+	/// Creates a new Element and returns it - the returned element is a copy.
+	virtual TiXmlNode* Clone() const;
+	// Print the Element to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	/*	Attribtue parsing starts: next char past '<'
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlElement*     ToElement()     const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlElement*           ToElement()	          { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+
+	void CopyTo( TiXmlElement* target ) const;
+	void ClearThis();	// like clear, but initializes 'this' object as well
+
+	// Used to be public [internal use]
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+	/*	[internal use]
+		Reads the "value" of the element -- another element, or text.
+		This should terminate with the current end tag.
+	*/
+	const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+private:
+
+	TiXmlAttributeSet attributeSet;
+};
+
+
+/**	An XML comment.
+*/
+class TiXmlComment : public TiXmlNode
+{
+public:
+	/// Constructs an empty comment.
+	TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
+	/// Construct a comment from text.
+	TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) {
+		SetValue( _value );
+	}
+	TiXmlComment( const TiXmlComment& );
+	void operator=( const TiXmlComment& base );
+
+	virtual ~TiXmlComment()	{}
+
+	/// Returns a copy of this Comment.
+	virtual TiXmlNode* Clone() const;
+	// Write this Comment to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	/*	Attribtue parsing starts: at the ! of the !--
+						 returns: next char past '>'
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlComment*  ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlComment*  ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+	void CopyTo( TiXmlComment* target ) const;
+
+	// used to be public
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+//	virtual void StreamOut( TIXML_OSTREAM * out ) const;
+
+private:
+
+};
+
+
+/** XML text. A text node can have 2 ways to output the next. "normal" output
+	and CDATA. It will default to the mode it was parsed from the XML file and
+	you generally want to leave it alone, but you can change the output mode with
+	SetCDATA() and query it with CDATA().
+*/
+class TiXmlText : public TiXmlNode
+{
+	friend class TiXmlElement;
+public:
+	/** Constructor for text element. By default, it is treated as
+		normal, encoded text. If you want it be output as a CDATA text
+		element, set the parameter _cdata to 'true'
+	*/
+	TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT)
+	{
+		SetValue( initValue );
+		cdata = false;
+	}
+	virtual ~TiXmlText() {}
+
+	#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
+	{
+		SetValue( initValue );
+		cdata = false;
+	}
+	#endif
+
+	TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT )	{ copy.CopyTo( this ); }
+	void operator=( const TiXmlText& base )							 	{ base.CopyTo( this ); }
+
+	// Write this text object to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	/// Queries whether this represents text using a CDATA section.
+	bool CDATA() const				{ return cdata; }
+	/// Turns on or off a CDATA representation of text.
+	void SetCDATA( bool _cdata )	{ cdata = _cdata; }
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlText*       ToText()       { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+	///  [internal use] Creates a new Element and returns it.
+	virtual TiXmlNode* Clone() const;
+	void CopyTo( TiXmlText* target ) const;
+
+	bool Blank() const;	// returns true if all white space and new lines
+	// [internal use]
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+	bool cdata;			// true if this should be input and output as a CDATA style text element
+};
+
+
+/** In correct XML the declaration is the first entry in the file.
+	@verbatim
+		<?xml version="1.0" standalone="yes"?>
+	@endverbatim
+
+	TinyXml will happily read or write files without a declaration,
+	however. There are 3 possible attributes to the declaration:
+	version, encoding, and standalone.
+
+	Note: In this version of the code, the attributes are
+	handled as special cases, not generic attributes, simply
+	because there can only be at most 3 and they are always the same.
+*/
+class TiXmlDeclaration : public TiXmlNode
+{
+public:
+	/// Construct an empty declaration.
+	TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
+
+#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlDeclaration(	const std::string& _version,
+						const std::string& _encoding,
+						const std::string& _standalone );
+#endif
+
+	/// Construct.
+	TiXmlDeclaration(	const char* _version,
+						const char* _encoding,
+						const char* _standalone );
+
+	TiXmlDeclaration( const TiXmlDeclaration& copy );
+	void operator=( const TiXmlDeclaration& copy );
+
+	virtual ~TiXmlDeclaration()	{}
+
+	/// Version. Will return an empty string if none was found.
+	const char *Version() const			{ return version.c_str (); }
+	/// Encoding. Will return an empty string if none was found.
+	const char *Encoding() const		{ return encoding.c_str (); }
+	/// Is this a standalone document?
+	const char *Standalone() const		{ return standalone.c_str (); }
+
+	/// Creates a copy of this Declaration and returns it.
+	virtual TiXmlNode* Clone() const;
+	// Print this declaration to a FILE stream.
+	virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+	virtual void Print( FILE* cfile, int depth ) const {
+		Print( cfile, depth, 0 );
+	}
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlDeclaration*       ToDeclaration()       { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+	void CopyTo( TiXmlDeclaration* target ) const;
+	// used to be public
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+
+	TIXML_STRING version;
+	TIXML_STRING encoding;
+	TIXML_STRING standalone;
+};
+
+/** A stylesheet reference looks like this:
+	@verbatim
+		<?xml-stylesheet type="text/xsl" href="style.xsl"?>
+	@endverbatim
+
+	Note: In this version of the code, the attributes are
+	handled as special cases, not generic attributes, simply
+	because there can only be at most 2 and they are always the same.
+*/
+class TiXmlStylesheetReference : public TiXmlNode
+{
+public:
+	/// Construct an empty declaration.
+	TiXmlStylesheetReference()   : TiXmlNode( TiXmlNode::STYLESHEETREFERENCE ) {}
+
+#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlStylesheetReference(	const std::string& _type,
+								const std::string& _href );
+#endif
+
+	/// Construct.
+	TiXmlStylesheetReference(	const char* _type,
+								const char* _href );
+
+	TiXmlStylesheetReference( const TiXmlStylesheetReference& copy );
+	void operator=( const TiXmlStylesheetReference& copy );
+
+	virtual ~TiXmlStylesheetReference()	{}
+
+	/// Type. Will return an empty string if none was found.
+	const char *Type() const { return type.c_str (); }
+	/// Href. Will return an empty string if none was found.
+	const char *Href() const		{ return href.c_str (); }
+
+	/// Creates a copy of this StylesheetReference and returns it.
+	virtual TiXmlNode* Clone() const;
+	// Print this declaration to a FILE stream.
+	virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const;
+	virtual void Print( FILE* cfile, int depth ) const {
+		Print( cfile, depth, 0 );
+	}
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlStylesheetReference* ToStylesheetReference() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlStylesheetReference*       ToStylesheetReference()       { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* visitor ) const;
+
+protected:
+	void CopyTo( TiXmlStylesheetReference* target ) const;
+	// used to be public
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+
+	TIXML_STRING type;
+	TIXML_STRING href;
+};
+
+/** Any tag that tinyXml doesn't recognize is saved as an
+	unknown. It is a tag of text, but should not be modified.
+	It will be written back to the XML, unchanged, when the file
+	is saved.
+
+	DTD tags get thrown into TiXmlUnknowns.
+*/
+class TiXmlUnknown : public TiXmlNode
+{
+public:
+	TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN )	{}
+	virtual ~TiXmlUnknown() {}
+
+	TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN )		{ copy.CopyTo( this ); }
+	void operator=( const TiXmlUnknown& copy )										{ copy.CopyTo( this ); }
+
+	/// Creates a copy of this Unknown and returns it.
+	virtual TiXmlNode* Clone() const;
+	// Print this Unknown to a FILE stream.
+	virtual void Print( FILE* cfile, int depth ) const;
+
+	virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
+
+	virtual const TiXmlUnknown*     ToUnknown()     const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlUnknown*           ToUnknown()	    { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected:
+	void CopyTo( TiXmlUnknown* target ) const;
+
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+
+};
+
+
+/** Always the top level node. A document binds together all the
+	XML pieces. It can be saved, loaded, and printed to the screen.
+	The 'value' of a document node is the xml file name.
+*/
+class TiXmlDocument : public TiXmlNode
+{
+public:
+	/// Create an empty document, that has no name.
+	TiXmlDocument();
+	/// Create a document with a name. The name of the document is also the filename of the xml.
+	TiXmlDocument( const char * documentName );
+
+	#ifdef TIXML_USE_STL
+	/// Constructor.
+	TiXmlDocument( const std::string& documentName );
+	#endif
+
+	TiXmlDocument( const TiXmlDocument& copy );
+	void operator=( const TiXmlDocument& copy );
+
+	virtual ~TiXmlDocument() {}
+
+	/** Load a file using the current document value.
+		Returns true if successful. Will delete any existing
+		document data before loading.
+	*/
+	bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	/// Save a file using the current document value. Returns true if successful.
+	bool SaveFile() const;
+	/// Load a file using the given filename. Returns true if successful.
+	bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	/// Save a file using the given filename. Returns true if successful.
+	bool SaveFile( const char * filename ) const;
+	/** Load a file using the given FILE*. Returns true if successful. Note that this method
+		doesn't stream - the entire object pointed at by the FILE*
+		will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
+		file location. Streaming may be added in the future.
+	*/
+	bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+	/// Save a file using the given FILE*. Returns true if successful.
+	bool SaveFile( FILE* ) const;
+
+	#ifdef TIXML_USE_STL
+	bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING )			///< STL std::string version.
+	{
+//		StringToBuffer f( filename );
+//		return ( f.buffer && LoadFile( f.buffer, encoding ));
+		return LoadFile( filename.c_str(), encoding );
+	}
+	bool SaveFile( const std::string& filename ) const		///< STL std::string version.
+	{
+//		StringToBuffer f( filename );
+//		return ( f.buffer && SaveFile( f.buffer ));
+		return SaveFile( filename.c_str() );
+	}
+	#endif
+
+	/** Parse the given null terminated block of xml data. Passing in an encoding to this
+		method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
+		to use that encoding, regardless of what TinyXml might otherwise try to detect.
+	*/
+	virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
+
+	/** Get the root element -- the only top level element -- of the document.
+		In well formed XML, there should only be one. TinyXml is tolerant of
+		multiple elements at the document level.
+	*/
+	const TiXmlElement* RootElement() const		{ return FirstChildElement(); }
+	TiXmlElement* RootElement()					{ return FirstChildElement(); }
+
+	/** If an error occurs, Error will be set to true. Also,
+		- The ErrorId() will contain the integer identifier of the error (not generally useful)
+		- The ErrorDesc() method will return the name of the error. (very useful)
+		- The ErrorRow() and ErrorCol() will return the location of the error (if known)
+	*/
+	bool Error() const						{ return error; }
+
+	/// Contains a textual (english) description of the error if one occurs.
+	const char * ErrorDesc() const	{ return errorDesc.c_str (); }
+
+	/** Generally, you probably want the error string ( ErrorDesc() ). But if you
+		prefer the ErrorId, this function will fetch it.
+	*/
+	int ErrorId()	const				{ return errorId; }
+
+	/** Returns the location (if known) of the error. The first column is column 1,
+		and the first row is row 1. A value of 0 means the row and column wasn't applicable
+		(memory errors, for example, have no row/column) or the parser lost the error. (An
+		error in the error reporting, in that case.)
+
+		@sa SetTabSize, Row, Column
+	*/
+	int ErrorRow() const	{ return errorLocation.row+1; }
+	int ErrorCol() const	{ return errorLocation.col+1; }	///< The column where the error occured. See ErrorRow()
+
+	/** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol())
+		to report the correct values for row and column. It does not change the output
+		or input in any way.
+
+		By calling this method, with a tab size
+		greater than 0, the row and column of each node and attribute is stored
+		when the file is loaded. Very useful for tracking the DOM back in to
+		the source file.
+
+		The tab size is required for calculating the location of nodes. If not
+		set, the default of 4 is used. The tabsize is set per document. Setting
+		the tabsize to 0 disables row/column tracking.
+
+		Note that row and column tracking is not supported when using operator>>.
+
+		The tab size needs to be enabled before the parse or load. Correct usage:
+		@verbatim
+		TiXmlDocument doc;
+		doc.SetTabSize( 8 );
+		doc.Load( "myfile.xml" );
+		@endverbatim
+
+		@sa Row, Column
+	*/
+	void SetTabSize( int _tabsize )		{ tabsize = _tabsize; }
+
+	int TabSize() const	{ return tabsize; }
+
+	/** If you have handled the error, it can be reset with this call. The error
+		state is automatically cleared if you Parse a new XML block.
+	*/
+	void ClearError()						{	error = false;
+												errorId = 0;
+												errorDesc = "";
+												errorLocation.row = errorLocation.col = 0;
+												//errorLocation.last = 0;
+											}
+
+	/** Write the document to standard out using formatted printing ("pretty print"). */
+	void Print() const						{ Print( stdout, 0 ); }
+
+	/* Write the document to a string using formatted printing ("pretty print"). This
+		will allocate a character array (new char[]) and return it as a pointer. The
+		calling code pust call delete[] on the return char* to avoid a memory leak.
+	*/
+	//char* PrintToMemory() const;
+
+	/// Print this Document to a FILE stream.
+	virtual void Print( FILE* cfile, int depth = 0 ) const;
+	// [internal use]
+	void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
+
+	virtual const TiXmlDocument*    ToDocument()    const { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+	virtual TiXmlDocument*          ToDocument()          { return this; } ///< Cast to a more defined type. Will return null not of the requested type.
+
+	/** Walk the XML tree visiting this node and all of its children.
+	*/
+	virtual bool Accept( TiXmlVisitor* content ) const;
+
+protected :
+	// [internal use]
+	virtual TiXmlNode* Clone() const;
+	#ifdef TIXML_USE_STL
+	virtual void StreamIn( std::istream * in, TIXML_STRING * tag );
+	#endif
+
+private:
+	void CopyTo( TiXmlDocument* target ) const;
+
+	bool error;
+	int  errorId;
+	TIXML_STRING errorDesc;
+	int tabsize;
+	TiXmlCursor errorLocation;
+	bool useMicrosoftBOM;		// the UTF-8 BOM were found when read. Note this, and try to write.
+};
+
+
+/**
+	A TiXmlHandle is a class that wraps a node pointer with null checks; this is
+	an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
+	DOM structure. It is a separate utility class.
+
+	Take an example:
+	@verbatim
+	<Document>
+		<Element attributeA = "valueA">
+			<Child attributeB = "value1" />
+			<Child attributeB = "value2" />
+		</Element>
+	<Document>
+	@endverbatim
+
+	Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
+	easy to write a *lot* of code that looks like:
+
+	@verbatim
+	TiXmlElement* root = document.FirstChildElement( "Document" );
+	if ( root )
+	{
+		TiXmlElement* element = root->FirstChildElement( "Element" );
+		if ( element )
+		{
+			TiXmlElement* child = element->FirstChildElement( "Child" );
+			if ( child )
+			{
+				TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+				if ( child2 )
+				{
+					// Finally do something useful.
+	@endverbatim
+
+	And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
+	of such code. A TiXmlHandle checks for null	pointers so it is perfectly safe
+	and correct to use:
+
+	@verbatim
+	TiXmlHandle docHandle( &document );
+	TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+	if ( child2 )
+	{
+		// do something useful
+	@endverbatim
+
+	Which is MUCH more concise and useful.
+
+	It is also safe to copy handles - internally they are nothing more than node pointers.
+	@verbatim
+	TiXmlHandle handleCopy = handle;
+	@endverbatim
+
+	What they should not be used for is iteration:
+
+	@verbatim
+	int i=0;
+	while ( true )
+	{
+		TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement();
+		if ( !child )
+			break;
+		// do something
+		++i;
+	}
+	@endverbatim
+
+	It seems reasonable, but it is in fact two embedded while loops. The Child method is
+	a linear walk to find the element, so this code would iterate much more than it needs
+	to. Instead, prefer:
+
+	@verbatim
+	TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement();
+
+	for( child; child; child=child->NextSiblingElement() )
+	{
+		// do something
+	}
+	@endverbatim
+*/
+class TiXmlHandle
+{
+public:
+	/// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
+	TiXmlHandle( TiXmlNode* _node )					{ this->node = _node; }
+	/// Copy constructor
+	TiXmlHandle( const TiXmlHandle& ref )			{ this->node = ref.node; }
+	TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
+
+	/// Return a handle to the first child node.
+	TiXmlHandle FirstChild() const;
+	/// Return a handle to the first child node with the given name.
+	TiXmlHandle FirstChild( const char * value ) const;
+	/// Return a handle to the first child element.
+	TiXmlHandle FirstChildElement() const;
+	/// Return a handle to the first child element with the given name.
+	TiXmlHandle FirstChildElement( const char * value ) const;
+
+	/** Return a handle to the "index" child with the given name.
+		The first child is 0, the second 1, etc.
+	*/
+	TiXmlHandle Child( const char* value, int index ) const;
+	/** Return a handle to the "index" child.
+		The first child is 0, the second 1, etc.
+	*/
+	TiXmlHandle Child( int index ) const;
+	/** Return a handle to the "index" child element with the given name.
+		The first child element is 0, the second 1, etc. Note that only TiXmlElements
+		are indexed: other types are not counted.
+	*/
+	TiXmlHandle ChildElement( const char* value, int index ) const;
+	/** Return a handle to the "index" child element.
+		The first child element is 0, the second 1, etc. Note that only TiXmlElements
+		are indexed: other types are not counted.
+	*/
+	TiXmlHandle ChildElement( int index ) const;
+
+	#ifdef TIXML_USE_STL
+	TiXmlHandle FirstChild( const std::string& _value ) const				{ return FirstChild( _value.c_str() ); }
+	TiXmlHandle FirstChildElement( const std::string& _value ) const		{ return FirstChildElement( _value.c_str() ); }
+
+	TiXmlHandle Child( const std::string& _value, int index ) const			{ return Child( _value.c_str(), index ); }
+	TiXmlHandle ChildElement( const std::string& _value, int index ) const	{ return ChildElement( _value.c_str(), index ); }
+	#endif
+
+	/** Return the handle as a TiXmlNode. This may return null.
+	*/
+	TiXmlNode* ToNode() const			{ return node; }
+	/** Return the handle as a TiXmlElement. This may return null.
+	*/
+	TiXmlElement* ToElement() const		{ return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
+	/**	Return the handle as a TiXmlText. This may return null.
+	*/
+	TiXmlText* ToText() const			{ return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
+	/** Return the handle as a TiXmlUnknown. This may return null.
+	*/
+	TiXmlUnknown* ToUnknown() const		{ return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
+
+	/** @deprecated use ToNode.
+		Return the handle as a TiXmlNode. This may return null.
+	*/
+	TiXmlNode* Node() const			{ return ToNode(); }
+	/** @deprecated use ToElement.
+		Return the handle as a TiXmlElement. This may return null.
+	*/
+	TiXmlElement* Element() const	{ return ToElement(); }
+	/**	@deprecated use ToText()
+		Return the handle as a TiXmlText. This may return null.
+	*/
+	TiXmlText* Text() const			{ return ToText(); }
+	/** @deprecated use ToUnknown()
+		Return the handle as a TiXmlUnknown. This may return null.
+	*/
+	TiXmlUnknown* Unknown() const	{ return ToUnknown(); }
+
+private:
+	TiXmlNode* node;
+};
+
+
+/** Print to memory functionality. The TiXmlPrinter is useful when you need to:
+
+	-# Print to memory (especially in non-STL mode)
+	-# Control formatting (line endings, etc.)
+
+	When constructed, the TiXmlPrinter is in its default "pretty printing" mode.
+	Before calling Accept() you can call methods to control the printing
+	of the XML document. After TiXmlNode::Accept() is called, the printed document can
+	be accessed via the CStr(), Str(), and Size() methods.
+
+	TiXmlPrinter uses the Visitor API.
+	@verbatim
+	TiXmlPrinter printer;
+	printer.SetIndent( "\t" );
+
+	doc.Accept( &printer );
+	fprintf( stdout, "%s", printer.CStr() );
+	@endverbatim
+*/
+class TiXmlPrinter : public TiXmlVisitor
+{
+public:
+	TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ),
+					 buffer(), indent( "    " ), lineBreak( "\n" ) {}
+
+	virtual bool VisitEnter( const TiXmlDocument& doc );
+	virtual bool VisitExit( const TiXmlDocument& doc );
+
+	virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute );
+	virtual bool VisitExit( const TiXmlElement& element );
+
+	virtual bool Visit( const TiXmlDeclaration& declaration );
+	virtual bool Visit( const TiXmlText& text );
+	virtual bool Visit( const TiXmlComment& comment );
+	virtual bool Visit( const TiXmlUnknown& unknown );
+	virtual bool Visit( const TiXmlStylesheetReference& stylesheet );
+
+	/** Set the indent characters for printing. By default 4 spaces
+		but tab (\t) is also useful, or null/empty string for no indentation.
+	*/
+	void SetIndent( const char* _indent )			{ indent = _indent ? _indent : "" ; }
+	/// Query the indention string.
+	const char* Indent()							{ return indent.c_str(); }
+	/** Set the line breaking string. By default set to newline (\n).
+		Some operating systems prefer other characters, or can be
+		set to the null/empty string for no indenation.
+	*/
+	void SetLineBreak( const char* _lineBreak )		{ lineBreak = _lineBreak ? _lineBreak : ""; }
+	/// Query the current line breaking string.
+	const char* LineBreak()							{ return lineBreak.c_str(); }
+
+	/** Switch over to "stream printing" which is the most dense formatting without
+		linebreaks. Common when the XML is needed for network transmission.
+	*/
+	void SetStreamPrinting()						{ indent = "";
+													  lineBreak = "";
+													}
+	/// Return the result.
+	const char* CStr()								{ return buffer.c_str(); }
+	/// Return the length of the result string.
+	size_t Size()									{ return buffer.size(); }
+
+	#ifdef TIXML_USE_STL
+	/// Return the result.
+	const std::string& Str()						{ return buffer; }
+	#endif
+
+private:
+	void DoIndent()	{
+		for( int i=0; i<depth; ++i )
+			buffer += indent;
+	}
+	void DoLineBreak() {
+		buffer += lineBreak;
+	}
+
+	int depth;
+	bool simpleTextPrint;
+	TIXML_STRING buffer;
+	TIXML_STRING indent;
+	TIXML_STRING lineBreak;
+};
+
+
+#ifdef _MSC_VER
+#pragma warning( pop )
+#endif
+
+#endif
+
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxmlerror.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxmlerror.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxmlerror.cpp	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include "tinyxml.h"
+
+// The goal of the seperate error file is to make the first
+// step towards localization. tinyxml (currently) only supports
+// english error messages, but the could now be translated.
+//
+// It also cleans up the code a bit.
+//
+
+const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
+{
+	"No error",
+	"Error",
+	"Failed to open file",
+	"Memory allocation failed.",
+	"Error parsing Element.",
+	"Failed to read Element name",
+	"Error reading Element value.",
+	"Error reading Attributes.",
+	"Error: empty tag.",
+	"Error reading end tag.",
+	"Error parsing Unknown.",
+	"Error parsing Comment.",
+	"Error parsing Declaration.",
+	"Error document empty.",
+	"Error null (0) or unexpected EOF found in input stream.",
+	"Error parsing CDATA.",
+	"Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.",
+};
Index: /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxmlparser.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxmlparser.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tinyxml/tinyxmlparser.cpp	(revision 11817)
@@ -0,0 +1,1722 @@
+/*
+www.sourceforge.net/projects/tinyxml
+Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+#include <stddef.h>
+
+#include "tinyxml.h"
+
+//#define DEBUG_PARSER
+#if defined( DEBUG_PARSER )
+#	if defined( DEBUG ) && defined( _MSC_VER )
+#		include <windows.h>
+#		define TIXML_LOG OutputDebugString
+#	else
+#		define TIXML_LOG printf
+#	endif
+#endif
+
+// Note tha "PutString" hardcodes the same list. This
+// is less flexible than it appears. Changing the entries
+// or order will break putstring.
+TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] =
+{
+	{ "&amp;",  5, '&' },
+	{ "&lt;",   4, '<' },
+	{ "&gt;",   4, '>' },
+	{ "&quot;", 6, '\"' },
+	{ "&apos;", 6, '\'' }
+};
+
+// Bunch of unicode info at:
+//		http://www.unicode.org/faq/utf_bom.html
+// Including the basic of this table, which determines the #bytes in the
+// sequence from the lead byte. 1 placed for invalid sequences --
+// although the result will be junk, pass it through as much as possible.
+// Beware of the non-characters in UTF-8:
+//				ef bb bf (Microsoft "lead bytes")
+//				ef bf be
+//				ef bf bf
+
+const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
+const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
+const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
+
+const int TiXmlBase::utf8ByteTable[256] =
+{
+	//	0	1	2	3	4	5	6	7	8	9	a	b	c	d	e	f
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x00
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x10
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x20
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x30
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x40
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x50
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x60
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x70	End of ASCII range
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x80 0x80 to 0xc1 invalid
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0x90
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0xa0
+		1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	// 0xb0
+		1,	1,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	// 0xc0 0xc2 to 0xdf 2 byte
+		2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	2,	// 0xd0
+		3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	3,	// 0xe0 0xe0 to 0xef 3 byte
+		4,	4,	4,	4,	4,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1,	1	// 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
+};
+
+
+void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
+{
+	const unsigned long BYTE_MASK = 0xBF;
+	const unsigned long BYTE_MARK = 0x80;
+	const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+	if (input < 0x80)
+		*length = 1;
+	else if ( input < 0x800 )
+		*length = 2;
+	else if ( input < 0x10000 )
+		*length = 3;
+	else if ( input < 0x200000 )
+		*length = 4;
+	else
+		{ *length = 0; return; }	// This code won't covert this correctly anyway.
+
+	output += *length;
+
+	// Scary scary fall throughs.
+	switch (*length)
+	{
+		case 4:
+			--output;
+			*output = (char)((input | BYTE_MARK) & BYTE_MASK);
+			input >>= 6;
+		case 3:
+			--output;
+			*output = (char)((input | BYTE_MARK) & BYTE_MASK);
+			input >>= 6;
+		case 2:
+			--output;
+			*output = (char)((input | BYTE_MARK) & BYTE_MASK);
+			input >>= 6;
+		case 1:
+			--output;
+			*output = (char)(input | FIRST_BYTE_MARK[*length]);
+	}
+}
+
+
+/*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+	// This will only work for low-ascii, everything else is assumed to be a valid
+	// letter. I'm not sure this is the best approach, but it is quite tricky trying
+	// to figure out alhabetical vs. not across encoding. So take a very
+	// conservative approach.
+
+//	if ( encoding == TIXML_ENCODING_UTF8 )
+//	{
+		if ( anyByte < 127 )
+			return isalpha( anyByte );
+		else
+			return 1;	// What else to do? The unicode set is huge...get the english ones right.
+//	}
+//	else
+//	{
+//		return isalpha( anyByte );
+//	}
+}
+
+
+/*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ )
+{
+	// This will only work for low-ascii, everything else is assumed to be a valid
+	// letter. I'm not sure this is the best approach, but it is quite tricky trying
+	// to figure out alhabetical vs. not across encoding. So take a very
+	// conservative approach.
+
+//	if ( encoding == TIXML_ENCODING_UTF8 )
+//	{
+		if ( anyByte < 127 )
+			return isalnum( anyByte );
+		else
+			return 1;	// What else to do? The unicode set is huge...get the english ones right.
+//	}
+//	else
+//	{
+//		return isalnum( anyByte );
+//	}
+}
+
+
+class TiXmlParsingData
+{
+	friend class TiXmlDocument;
+  public:
+	void Stamp( const char* now, TiXmlEncoding encoding );
+
+	const TiXmlCursor& Cursor()	{ return cursor; }
+
+  private:
+	// Only used by the document!
+	TiXmlParsingData( const char* start, int _tabsize, int row, int col )
+	{
+		assert( start );
+		stamp = start;
+		tabsize = _tabsize;
+		cursor.row = row;
+		cursor.col = col;
+	}
+
+	TiXmlCursor		cursor;
+	const char*		stamp;
+	int				tabsize;
+};
+
+
+void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding )
+{
+	assert( now );
+
+	// Do nothing if the tabsize is 0.
+	if ( tabsize < 1 )
+	{
+		return;
+	}
+
+	// Get the current row, column.
+	int row = cursor.row;
+	int col = cursor.col;
+	const char* p = stamp;
+	assert( p );
+
+	while ( p < now )
+	{
+		// Treat p as unsigned, so we have a happy compiler.
+		const unsigned char* pU = (const unsigned char*)p;
+
+		// Code contributed by Fletcher Dunn: (modified by lee)
+		switch (*pU) {
+			case 0:
+				// We *should* never get here, but in case we do, don't
+				// advance past the terminating null character, ever
+				return;
+
+			case '\r':
+				// bump down to the next line
+				++row;
+				col = 0;
+				// Eat the character
+				++p;
+
+				// Check for \r\n sequence, and treat this as a single character
+				if (*p == '\n') {
+					++p;
+				}
+				break;
+
+			case '\n':
+				// bump down to the next line
+				++row;
+				col = 0;
+
+				// Eat the character
+				++p;
+
+				// Check for \n\r sequence, and treat this as a single
+				// character.  (Yes, this bizarre thing does occur still
+				// on some arcane platforms...)
+				if (*p == '\r') {
+					++p;
+				}
+				break;
+
+			case '\t':
+				// Eat the character
+				++p;
+
+				// Skip to next tab stop
+				col = (col / tabsize + 1) * tabsize;
+				break;
+
+			case TIXML_UTF_LEAD_0:
+				if ( encoding == TIXML_ENCODING_UTF8 )
+				{
+					if ( *(p+1) && *(p+2) )
+					{
+						// In these cases, don't advance the column. These are
+						// 0-width spaces.
+						if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 )
+							p += 3;
+						else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU )
+							p += 3;
+						else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU )
+							p += 3;
+						else
+							{ p +=3; ++col; }	// A normal character.
+					}
+				}
+				else
+				{
+					++p;
+					++col;
+				}
+				break;
+
+			default:
+				if ( encoding == TIXML_ENCODING_UTF8 )
+				{
+					// Eat the 1 to 4 byte utf8 character.
+					int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)];
+					if ( step == 0 )
+						step = 1;		// Error case from bad encoding, but handle gracefully.
+					p += step;
+
+					// Just advance one column, of course.
+					++col;
+				}
+				else
+				{
+					++p;
+					++col;
+				}
+				break;
+		}
+	}
+	cursor.row = row;
+	cursor.col = col;
+	assert( cursor.row >= -1 );
+	assert( cursor.col >= -1 );
+	stamp = p;
+	assert( stamp );
+}
+
+
+const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding )
+{
+	if ( !p || !*p )
+	{
+		return 0;
+	}
+	if ( encoding == TIXML_ENCODING_UTF8 )
+	{
+		while ( *p )
+		{
+			const unsigned char* pU = (const unsigned char*)p;
+
+			// Skip the stupid Microsoft UTF-8 Byte order marks
+			if (	*(pU+0)==TIXML_UTF_LEAD_0
+				 && *(pU+1)==TIXML_UTF_LEAD_1
+				 && *(pU+2)==TIXML_UTF_LEAD_2 )
+			{
+				p += 3;
+				continue;
+			}
+			else if(*(pU+0)==TIXML_UTF_LEAD_0
+				 && *(pU+1)==0xbfU
+				 && *(pU+2)==0xbeU )
+			{
+				p += 3;
+				continue;
+			}
+			else if(*(pU+0)==TIXML_UTF_LEAD_0
+				 && *(pU+1)==0xbfU
+				 && *(pU+2)==0xbfU )
+			{
+				p += 3;
+				continue;
+			}
+
+			if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' )		// Still using old rules for white space.
+				++p;
+			else
+				break;
+		}
+	}
+	else
+	{
+		while ( ( *p && IsWhiteSpace( *p ) ) || *p == '\n' || *p =='\r' )
+			++p;
+	}
+
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag )
+{
+	for( ;; )
+	{
+		if ( !in->good() ) return false;
+
+		int c = in->peek();
+		// At this scope, we can't get to a document. So fail silently.
+		if ( !IsWhiteSpace( c ) || c <= 0 )
+			return true;
+
+		*tag += (char) in->get();
+	}
+}
+
+/*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag )
+{
+	//assert( character > 0 && character < 128 );	// else it won't work in utf-8
+	while ( in->good() )
+	{
+		int c = in->peek();
+		if ( c == character )
+			return true;
+		if ( c <= 0 )		// Silent failure: can't get document at this scope
+			return false;
+
+		in->get();
+		*tag += (char) c;
+	}
+	return false;
+}
+#endif
+
+// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The
+// "assign" optimization removes over 10% of the execution time.
+//
+const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding )
+{
+	// Oddly, not supported on some comilers,
+	//name->clear();
+	// So use this:
+	*name = "";
+	assert( p );
+
+	// Names start with letters or underscores.
+	// Of course, in unicode, tinyxml has no idea what a letter *is*. The
+	// algorithm is generous.
+	//
+	// After that, they can be letters, underscores, numbers,
+	// hyphens, or colons. (Colons are valid ony for namespaces,
+	// but tinyxml can't tell namespaces from names.)
+	if (    p && *p
+		 && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) )
+	{
+		const char* start = p;
+		while(		p && *p
+				&&	(		IsAlphaNum( (unsigned char ) *p, encoding )
+						 || *p == '_'
+						 || *p == '-'
+						 || *p == '.'
+						 || *p == ':' ) )
+		{
+			//(*name) += *p; // expensive
+			++p;
+		}
+		if ( p-start > 0 ) {
+			name->assign( start, p-start );
+		}
+		return p;
+	}
+	return 0;
+}
+
+const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding )
+{
+	// Presume an entity, and pull it out.
+    TIXML_STRING ent;
+	int i;
+	*length = 0;
+
+	if ( *(p+1) && *(p+1) == '#' && *(p+2) )
+	{
+		unsigned long ucs = 0;
+		ptrdiff_t delta = 0;
+		unsigned mult = 1;
+
+		if ( *(p+2) == 'x' )
+		{
+			// Hexadecimal.
+			if ( !*(p+3) ) return 0;
+
+			const char* q = p+3;
+			q = strchr( q, ';' );
+
+			if ( !q || !*q ) return 0;
+
+			delta = q-p;
+			--q;
+
+			while ( *q != 'x' )
+			{
+				if ( *q >= '0' && *q <= '9' )
+					ucs += mult * (*q - '0');
+				else if ( *q >= 'a' && *q <= 'f' )
+					ucs += mult * (*q - 'a' + 10);
+				else if ( *q >= 'A' && *q <= 'F' )
+					ucs += mult * (*q - 'A' + 10 );
+				else
+					return 0;
+				mult *= 16;
+				--q;
+			}
+		}
+		else
+		{
+			// Decimal.
+			if ( !*(p+2) ) return 0;
+
+			const char* q = p+2;
+			q = strchr( q, ';' );
+
+			if ( !q || !*q ) return 0;
+
+			delta = q-p;
+			--q;
+
+			while ( *q != '#' )
+			{
+				if ( *q >= '0' && *q <= '9' )
+					ucs += mult * (*q - '0');
+				else
+					return 0;
+				mult *= 10;
+				--q;
+			}
+		}
+		if ( encoding == TIXML_ENCODING_UTF8 )
+		{
+			// convert the UCS to UTF-8
+			ConvertUTF32ToUTF8( ucs, value, length );
+		}
+		else
+		{
+			*value = (char)ucs;
+			*length = 1;
+		}
+		return p + delta + 1;
+	}
+
+	// Now try to match it.
+	for( i=0; i<NUM_ENTITY; ++i )
+	{
+		if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 )
+		{
+			assert( strlen( entity[i].str ) == entity[i].strLength );
+			*value = entity[i].chr;
+			*length = 1;
+			return ( p + entity[i].strLength );
+		}
+	}
+
+	// So it wasn't an entity, its unrecognized, or something like that.
+	*value = *p;	// Don't put back the last one, since we return it!
+	//*length = 1;	// Leave unrecognized entities - this doesn't really work.
+					// Just writes strange XML.
+	return p+1;
+}
+
+
+bool TiXmlBase::StringEqual( const char* p,
+							 const char* tag,
+							 bool ignoreCase,
+							 TiXmlEncoding encoding )
+{
+	assert( p );
+	assert( tag );
+	if ( !p || !*p )
+	{
+		assert( 0 );
+		return false;
+	}
+
+	const char* q = p;
+
+	if ( ignoreCase )
+	{
+		while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) )
+		{
+			++q;
+			++tag;
+		}
+
+		if ( *tag == 0 )
+			return true;
+	}
+	else
+	{
+		while ( *q && *tag && *q == *tag )
+		{
+			++q;
+			++tag;
+		}
+
+		if ( *tag == 0 )		// Have we found the end of the tag, and everything equal?
+			return true;
+	}
+	return false;
+}
+
+const char* TiXmlBase::ReadText(	const char* p,
+									TIXML_STRING * text,
+									bool trimWhiteSpace,
+									const char* endTag,
+									bool caseInsensitive,
+									TiXmlEncoding encoding )
+{
+    *text = "";
+	if (    !trimWhiteSpace			// certain tags always keep whitespace
+		 || !condenseWhiteSpace )	// if true, whitespace is always kept
+	{
+		// Keep all the white space.
+		while (	   p && *p
+				&& !StringEqual( p, endTag, caseInsensitive, encoding )
+			  )
+		{
+			int len;
+			char cArr[4] = { 0, 0, 0, 0 };
+			p = GetChar( p, cArr, &len, encoding );
+			text->append( cArr, len );
+		}
+	}
+	else
+	{
+		bool whitespace = false;
+
+		// Remove leading white space:
+		p = SkipWhiteSpace( p, encoding );
+		while (	   p && *p
+				&& !StringEqual( p, endTag, caseInsensitive, encoding ) )
+		{
+			if ( *p == '\r' || *p == '\n' )
+			{
+				whitespace = true;
+				++p;
+			}
+			else if ( IsWhiteSpace( *p ) )
+			{
+				whitespace = true;
+				++p;
+			}
+			else
+			{
+				// If we've found whitespace, add it before the
+				// new character. Any whitespace just becomes a space.
+				if ( whitespace )
+				{
+					(*text) += ' ';
+					whitespace = false;
+				}
+				int len;
+				char cArr[4] = { 0, 0, 0, 0 };
+				p = GetChar( p, cArr, &len, encoding );
+				if ( len == 1 )
+					(*text) += cArr[0];	// more efficient
+				else
+					text->append( cArr, len );
+			}
+		}
+	}
+	if ( p )
+		p += strlen( endTag );
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	// The basic issue with a document is that we don't know what we're
+	// streaming. Read something presumed to be a tag (and hope), then
+	// identify it, and call the appropriate stream method on the tag.
+	//
+	// This "pre-streaming" will never read the closing ">" so the
+	// sub-tag can orient itself.
+
+	if ( !StreamTo( in, '<', tag ) )
+	{
+		SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return;
+	}
+
+	while ( in->good() )
+	{
+		int tagIndex = (int) tag->length();
+		while ( in->good() && in->peek() != '>' )
+		{
+			int c = in->get();
+			if ( c <= 0 )
+			{
+				SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+				break;
+			}
+			(*tag) += (char) c;
+		}
+
+		if ( in->good() )
+		{
+			// We now have something we presume to be a node of
+			// some sort. Identify it, and call the node to
+			// continue streaming.
+			TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING );
+
+			if ( node )
+			{
+				node->StreamIn( in, tag );
+				bool isElement = node->ToElement() != 0;
+				delete node;
+				node = 0;
+
+				// If this is the root element, we're done. Parsing will be
+				// done by the >> operator.
+				if ( isElement )
+				{
+					return;
+				}
+			}
+			else
+			{
+				SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+				return;
+			}
+		}
+	}
+	// We should have returned sooner.
+	SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN );
+}
+
+#endif
+
+const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding )
+{
+	ClearError();
+
+	// Parse away, at the document level. Since a document
+	// contains nothing but other tags, most of what happens
+	// here is skipping white space.
+	if ( !p || !*p )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	// Note that, for a document, this needs to come
+	// before the while space skip, so that parsing
+	// starts from the pointer we are given.
+	location.Clear();
+	if ( prevData )
+	{
+		location.row = prevData->cursor.row;
+		location.col = prevData->cursor.col;
+	}
+	else
+	{
+		location.row = 0;
+		location.col = 0;
+	}
+	TiXmlParsingData data( p, TabSize(), location.row, location.col );
+	location = data.Cursor();
+
+	if ( encoding == TIXML_ENCODING_UNKNOWN )
+	{
+		// Check for the Microsoft UTF-8 lead bytes.
+		const unsigned char* pU = (const unsigned char*)p;
+		if (	*(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0
+			 && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1
+			 && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 )
+		{
+			encoding = TIXML_ENCODING_UTF8;
+			useMicrosoftBOM = true;
+		}
+	}
+
+    p = SkipWhiteSpace( p, encoding );
+	if ( !p )
+	{
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	while ( p && *p )
+	{
+		TiXmlNode* node = Identify( p, encoding );
+		if ( node )
+		{
+			p = node->Parse( p, &data, encoding );
+			LinkEndChild( node );
+		}
+		else
+		{
+			break;
+		}
+
+		// Did we get encoding info?
+		if (    encoding == TIXML_ENCODING_UNKNOWN
+			 && node->ToDeclaration() )
+		{
+			TiXmlDeclaration* dec = node->ToDeclaration();
+			const char* enc = dec->Encoding();
+			assert( enc );
+
+			if ( *enc == 0 )
+				encoding = TIXML_ENCODING_UTF8;
+			else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) )
+				encoding = TIXML_ENCODING_UTF8;
+			else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) )
+				encoding = TIXML_ENCODING_UTF8;	// incorrect, but be nice
+			else
+				encoding = TIXML_ENCODING_LEGACY;
+		}
+
+		p = SkipWhiteSpace( p, encoding );
+	}
+
+	// Was this empty?
+	if ( !firstChild ) {
+		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding );
+		return 0;
+	}
+
+	// All is well.
+	return p;
+}
+
+void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	// The first error in a chain is more accurate - don't set again!
+	if ( error )
+		return;
+
+	assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
+	error   = true;
+	errorId = err;
+	errorDesc = errorString[ errorId ];
+
+	errorLocation.Clear();
+	if ( pError && data )
+	{
+		data->Stamp( pError, encoding );
+		errorLocation = data->Cursor();
+	}
+}
+
+
+TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding )
+{
+	TiXmlNode* returnNode = 0;
+
+	p = SkipWhiteSpace( p, encoding );
+	if( !p || !*p || *p != '<' )
+	{
+		return 0;
+	}
+
+	TiXmlDocument* doc = GetDocument();
+	p = SkipWhiteSpace( p, encoding );
+
+	if ( !p || !*p )
+	{
+		return 0;
+	}
+
+	// What is this thing?
+	// - Elements start with a letter or underscore, but xml is reserved.
+	// - Comments: <!--
+	// - Decleration: <?xml
+	// - StylesheetReference <?xml-stylesheet
+	// - Everthing else is unknown to tinyxml.
+	//
+
+	const char* xmlHeader = { "<?xml" };
+	const char* xmlSSHeader = { "<?xml-stylesheet" };
+	const char* commentHeader = { "<!--" };
+	const char* dtdHeader = { "<!" };
+	const char* cdataHeader = { "<![CDATA[" };
+
+	if ( StringEqual( p, xmlSSHeader, true, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Stylesheet Reference\n" );
+		#endif
+		returnNode = new TiXmlStylesheetReference();
+	}
+	else if ( StringEqual( p, xmlHeader, true, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Declaration\n" );
+		#endif
+		returnNode = new TiXmlDeclaration();
+	}
+	else if ( StringEqual( p, commentHeader, false, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Comment\n" );
+		#endif
+		returnNode = new TiXmlComment();
+	}
+	else if ( StringEqual( p, cdataHeader, false, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing CDATA\n" );
+		#endif
+		TiXmlText* text = new TiXmlText( "" );
+		text->SetCDATA( true );
+		returnNode = text;
+	}
+	else if ( StringEqual( p, dtdHeader, false, encoding ) )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Unknown(1)\n" );
+		#endif
+		returnNode = new TiXmlUnknown();
+	}
+	else if (    IsAlpha( *(p+1), encoding )
+			  || *(p+1) == '_' )
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Element\n" );
+		#endif
+		returnNode = new TiXmlElement( "" );
+	}
+	else
+	{
+		#ifdef DEBUG_PARSER
+			TIXML_LOG( "XML parsing Unknown(2)\n" );
+		#endif
+		returnNode = new TiXmlUnknown();
+	}
+
+	if ( returnNode )
+	{
+		// Set the parent, so it can report errors
+		returnNode->parent = this;
+	}
+	else
+	{
+		if ( doc )
+			doc->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
+	}
+	return returnNode;
+}
+
+#ifdef TIXML_USE_STL
+
+void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag)
+{
+	// We're called with some amount of pre-parsing. That is, some of "this"
+	// element is in "tag". Go ahead and stream to the closing ">"
+	while( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c ;
+
+		if ( c == '>' )
+			break;
+	}
+
+	if ( tag->length() < 3 ) return;
+
+	// Okay...if we are a "/>" tag, then we're done. We've read a complete tag.
+	// If not, identify and stream.
+
+	if (    tag->at( tag->length() - 1 ) == '>'
+		 && tag->at( tag->length() - 2 ) == '/' )
+	{
+		// All good!
+		return;
+	}
+	else if ( tag->at( tag->length() - 1 ) == '>' )
+	{
+		// There is more. Could be:
+		//		text
+		//		cdata text (which looks like another node)
+		//		closing tag
+		//		another node.
+		for ( ;; )
+		{
+			StreamWhiteSpace( in, tag );
+
+			// Do we have text?
+			if ( in->good() && in->peek() != '<' )
+			{
+				// Yep, text.
+				TiXmlText text( "" );
+				text.StreamIn( in, tag );
+
+				// What follows text is a closing tag or another node.
+				// Go around again and figure it out.
+				continue;
+			}
+
+			// We now have either a closing tag...or another node.
+			// We should be at a "<", regardless.
+			if ( !in->good() ) return;
+			assert( in->peek() == '<' );
+			int tagIndex = (int) tag->length();
+
+			bool closingTag = false;
+			bool firstCharFound = false;
+
+			for( ;; )
+			{
+				if ( !in->good() )
+					return;
+
+				int c = in->peek();
+				if ( c <= 0 )
+				{
+					TiXmlDocument* document = GetDocument();
+					if ( document )
+						document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+					return;
+				}
+
+				if ( c == '>' )
+					break;
+
+				*tag += (char) c;
+				in->get();
+
+				// Early out if we find the CDATA id.
+				if ( c == '[' && tag->size() >= 9 )
+				{
+					size_t len = tag->size();
+					const char* start = tag->c_str() + len - 9;
+					if ( strcmp( start, "<![CDATA[" ) == 0 ) {
+						assert( !closingTag );
+						break;
+					}
+				}
+
+				if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) )
+				{
+					firstCharFound = true;
+					if ( c == '/' )
+						closingTag = true;
+				}
+			}
+			// If it was a closing tag, then read in the closing '>' to clean up the input stream.
+			// If it was not, the streaming will be done by the tag.
+			if ( closingTag )
+			{
+				if ( !in->good() )
+					return;
+
+				int c = in->get();
+				if ( c <= 0 )
+				{
+					TiXmlDocument* document = GetDocument();
+					if ( document )
+						document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+					return;
+				}
+				assert( c == '>' );
+				*tag += (char) c;
+
+				// We are done, once we've found our closing tag.
+				return;
+			}
+			else
+			{
+				// If not a closing tag, id it, and stream.
+				const char* tagloc = tag->c_str() + tagIndex;
+				TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING );
+				if ( !node )
+					return;
+				node->StreamIn( in, tag );
+				delete node;
+				node = 0;
+
+				// No return: go around from the beginning: text, closing tag, or node.
+			}
+		}
+	}
+}
+#endif
+
+const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	p = SkipWhiteSpace( p, encoding );
+	TiXmlDocument* document = GetDocument();
+
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding );
+		return 0;
+	}
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+
+	if ( *p != '<' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding );
+		return 0;
+	}
+
+	p = SkipWhiteSpace( p+1, encoding );
+
+	// Read the name.
+	const char* pErr = p;
+
+    p = ReadName( p, &value, encoding );
+	if ( !p || !*p )
+	{
+		if ( document )	document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding );
+		return 0;
+	}
+
+    TIXML_STRING endTag ("</");
+	endTag += value;
+	endTag += ">";
+
+	// Check for and read attributes. Also look for an empty
+	// tag or an end tag.
+	while ( p && *p )
+	{
+		pErr = p;
+		p = SkipWhiteSpace( p, encoding );
+		if ( !p || !*p )
+		{
+			if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+			return 0;
+		}
+		if ( *p == '/' )
+		{
+			++p;
+			// Empty tag.
+			if ( *p  != '>' )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding );
+				return 0;
+			}
+			return (p+1);
+		}
+		else if ( *p == '>' )
+		{
+			// Done with attributes (if there were any.)
+			// Read the value -- which can include other
+			// elements -- read the end tag, and return.
+			++p;
+			p = ReadValue( p, data, encoding );		// Note this is an Element method, and will set the error if one happens.
+			if ( !p || !*p ) {
+				// We were looking for the end tag, but found nothing.
+				// Fix for [ 1663758 ] Failure to report error on bad XML
+				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+				return 0;
+			}
+
+			// We should find the end tag now
+			if ( StringEqual( p, endTag.c_str(), false, encoding ) )
+			{
+				p += endTag.length();
+				return p;
+			}
+			else
+			{
+				if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding );
+				return 0;
+			}
+		}
+		else
+		{
+			// Try to read an attribute:
+			TiXmlAttribute* attrib = new TiXmlAttribute();
+			if ( !attrib )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, pErr, data, encoding );
+				return 0;
+			}
+
+			attrib->SetDocument( document );
+			pErr = p;
+			p = attrib->Parse( p, data, encoding );
+
+			if ( !p || !*p )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding );
+				delete attrib;
+				return 0;
+			}
+
+			// Handle the strange case of double attributes:
+			#ifdef TIXML_USE_STL
+			TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() );
+			#else
+			TiXmlAttribute* node = attributeSet.Find( attrib->Name() );
+			#endif
+			if ( node )
+			{
+				node->SetValue( attrib->Value() );
+				delete attrib;
+				return 0;
+			}
+
+			attributeSet.Add( attrib );
+		}
+	}
+	return p;
+}
+
+
+const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	TiXmlDocument* document = GetDocument();
+
+	// Read in text and elements in any order.
+	const char* pWithWhiteSpace = p;
+	p = SkipWhiteSpace( p, encoding );
+
+	while ( p && *p )
+	{
+		if ( *p != '<' )
+		{
+			// Take what we have, make a text element.
+			TiXmlText* textNode = new TiXmlText( "" );
+
+			if ( !textNode )
+			{
+				if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, encoding );
+				    return 0;
+			}
+
+			if ( TiXmlBase::IsWhiteSpaceCondensed() )
+			{
+				p = textNode->Parse( p, data, encoding );
+			}
+			else
+			{
+				// Special case: we want to keep the white space
+				// so that leading spaces aren't removed.
+				p = textNode->Parse( pWithWhiteSpace, data, encoding );
+			}
+
+			if ( !textNode->Blank() )
+				LinkEndChild( textNode );
+			else
+				delete textNode;
+		}
+		else
+		{
+			// We hit a '<'
+			// Have we hit a new element or an end tag? This could also be
+			// a TiXmlText in the "CDATA" style.
+			if ( StringEqual( p, "</", false, encoding ) )
+			{
+				return p;
+			}
+			else
+			{
+				TiXmlNode* node = Identify( p, encoding );
+				if ( node )
+				{
+					p = node->Parse( p, data, encoding );
+					LinkEndChild( node );
+				}
+				else
+				{
+					return 0;
+				}
+			}
+		}
+		pWithWhiteSpace = p;
+		p = SkipWhiteSpace( p, encoding );
+	}
+
+	if ( !p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding );
+	}
+	return p;
+}
+
+
+#ifdef TIXML_USE_STL
+void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;
+		}
+	}
+}
+#endif
+
+
+const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	TiXmlDocument* document = GetDocument();
+	p = SkipWhiteSpace( p, encoding );
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+	if ( !p || !*p || *p != '<' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding );
+		return 0;
+	}
+	++p;
+    value = "";
+
+	while ( p && *p && *p != '>' )
+	{
+		value += *p;
+		++p;
+	}
+
+	if ( !p )
+	{
+		if ( document )	document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding );
+	}
+	if ( *p == '>' )
+		return p+1;
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+
+		(*tag) += (char) c;
+
+		if ( c == '>'
+			 && tag->at( tag->length() - 2 ) == '-'
+			 && tag->at( tag->length() - 3 ) == '-' )
+		{
+			// All is well.
+			return;
+		}
+	}
+}
+#endif
+
+
+const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	TiXmlDocument* document = GetDocument();
+	value = "";
+
+	p = SkipWhiteSpace( p, encoding );
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+	const char* startTag = "<!--";
+	const char* endTag   = "-->";
+
+	if ( !StringEqual( p, startTag, false, encoding ) )
+	{
+		document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding );
+		return 0;
+	}
+	p += strlen( startTag );
+
+	// [ 1475201 ] TinyXML parses entities in comments
+	// Oops - ReadText doesn't work, because we don't want to parse the entities.
+	// p = ReadText( p, &value, false, endTag, false, encoding );
+	//
+	// from the XML spec:
+	/*
+	 [Definition: Comments may appear anywhere in a document outside other markup; in addition,
+	              they may appear within the document type declaration at places allowed by the grammar.
+				  They are not part of the document's character data; an XML processor MAY, but need not,
+				  make it possible for an application to retrieve the text of comments. For compatibility,
+				  the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity
+				  references MUST NOT be recognized within comments.
+
+				  An example of a comment:
+
+				  <!-- declarations for <head> & <body> -->
+	*/
+
+    value = "";
+	// Keep all the white space.
+	while (	p && *p && !StringEqual( p, endTag, false, encoding ) )
+	{
+		value.append( p, 1 );
+		++p;
+	}
+	if ( p )
+		p += strlen( endTag );
+
+	return p;
+}
+
+
+const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p ) return 0;
+
+//	int tabsize = 4;
+//	if ( document )
+//		tabsize = document->TabSize();
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+	// Read the name, the '=' and the value.
+	const char* pErr = p;
+	p = ReadName( p, &name, encoding );
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding );
+		return 0;
+	}
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p || *p != '=' )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+		return 0;
+	}
+
+	++p;	// skip '='
+	p = SkipWhiteSpace( p, encoding );
+	if ( !p || !*p )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+		return 0;
+	}
+
+	const char* end;
+	const char SINGLE_QUOTE = '\'';
+	const char DOUBLE_QUOTE = '\"';
+
+	if ( *p == SINGLE_QUOTE )
+	{
+		++p;
+		end = "\'";		// single quote in string
+		p = ReadText( p, &value, false, end, false, encoding );
+	}
+	else if ( *p == DOUBLE_QUOTE )
+	{
+		++p;
+		end = "\"";		// double quote in string
+		p = ReadText( p, &value, false, end, false, encoding );
+	}
+	else
+	{
+		// All attribute values should be in single or double quotes.
+		// But this is such a common error that the parser will try
+		// its best, even without them.
+		value = "";
+		while (    p && *p											// existence
+				&& !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r'	// whitespace
+				&& *p != '/' && *p != '>' )							// tag end
+		{
+			if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) {
+				// [ 1451649 ] Attribute values with trailing quotes not handled correctly
+				// We did not have an opening quote but seem to have a
+				// closing one. Give up and throw an error.
+				if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding );
+				return 0;
+			}
+			value += *p;
+			++p;
+		}
+	}
+	return p;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->peek();
+		if ( !cdata && (c == '<' ) )
+		{
+			return;
+		}
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+
+		(*tag) += (char) c;
+		in->get();	// "commits" the peek made above
+
+		if ( cdata && c == '>' && tag->size() >= 3 ) {
+			size_t len = tag->size();
+			if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) {
+				// terminator of cdata.
+				return;
+			}
+		}
+	}
+}
+#endif
+
+const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding )
+{
+	value = "";
+	TiXmlDocument* document = GetDocument();
+
+	if ( data )
+	{
+		data->Stamp( p, encoding );
+		location = data->Cursor();
+	}
+
+	const char* const startTag = "<![CDATA[";
+	const char* const endTag   = "]]>";
+
+	if ( cdata || StringEqual( p, startTag, false, encoding ) )
+	{
+		cdata = true;
+
+		if ( !StringEqual( p, startTag, false, encoding ) )
+		{
+			document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding );
+			return 0;
+		}
+		p += strlen( startTag );
+
+		// Keep all the white space, ignore the encoding, etc.
+		while (	   p && *p
+				&& !StringEqual( p, endTag, false, encoding )
+			  )
+		{
+			value += *p;
+			++p;
+		}
+
+		TIXML_STRING dummy;
+		p = ReadText( p, &dummy, false, endTag, false, encoding );
+		return p;
+	}
+	else
+	{
+		bool ignoreWhite = true;
+
+		const char* end = "<";
+		p = ReadText( p, &value, ignoreWhite, end, false, encoding );
+		if ( p )
+			return p-1;	// don't truncate the '<'
+		return 0;
+	}
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;
+		}
+	}
+}
+#endif
+
+const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+	p = SkipWhiteSpace( p, _encoding );
+	// Find the beginning, find the end, and look for
+	// the stuff in-between.
+	TiXmlDocument* document = GetDocument();
+	if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+		return 0;
+	}
+	if ( data )
+	{
+		data->Stamp( p, _encoding );
+		location = data->Cursor();
+	}
+	p += 5;
+
+	version = "";
+	encoding = "";
+	standalone = "";
+
+	while ( p && *p )
+	{
+		if ( *p == '>' )
+		{
+			++p;
+			return p;
+		}
+
+		p = SkipWhiteSpace( p, _encoding );
+		if ( StringEqual( p, "version", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );
+			version = attrib.Value();
+		}
+		else if ( StringEqual( p, "encoding", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );
+			encoding = attrib.Value();
+		}
+		else if ( StringEqual( p, "standalone", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );
+			standalone = attrib.Value();
+		}
+		else
+		{
+			// Read over whatever it is.
+			while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+				++p;
+		}
+	}
+	return 0;
+}
+
+bool TiXmlText::Blank() const
+{
+	for ( unsigned i=0; i<value.length(); i++ )
+		if ( !IsWhiteSpace( value[i] ) )
+			return false;
+	return true;
+}
+
+#ifdef TIXML_USE_STL
+void TiXmlStylesheetReference::StreamIn( std::istream * in, TIXML_STRING * tag )
+{
+	while ( in->good() )
+	{
+		int c = in->get();
+		if ( c <= 0 )
+		{
+			TiXmlDocument* document = GetDocument();
+			if ( document )
+				document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN );
+			return;
+		}
+		(*tag) += (char) c;
+
+		if ( c == '>' )
+		{
+			// All is well.
+			return;
+		}
+	}
+}
+#endif
+
+const char* TiXmlStylesheetReference::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding )
+{
+	p = SkipWhiteSpace( p, _encoding );
+	// Find the beginning, find the end, and look for
+	// the stuff in-between.
+	TiXmlDocument* document = GetDocument();
+	if ( !p || !*p || !StringEqual( p, "<?xml-stylesheet", true, _encoding ) )
+	{
+		if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding );
+		return 0;
+	}
+	if ( data )
+	{
+		data->Stamp( p, _encoding );
+		location = data->Cursor();
+	}
+	p += 5;
+
+	type = "";
+	href = "";
+
+	while ( p && *p )
+	{
+		if ( *p == '>' )
+		{
+			++p;
+			return p;
+		}
+
+		p = SkipWhiteSpace( p, _encoding );
+		if ( StringEqual( p, "type", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );
+			type = attrib.Value();
+		}
+		else if ( StringEqual( p, "href", true, _encoding ) )
+		{
+			TiXmlAttribute attrib;
+			p = attrib.Parse( p, data, _encoding );
+			href = attrib.Value();
+		}
+		else
+		{
+			// Read over whatever it is.
+			while( p && *p && *p != '>' && !IsWhiteSpace( *p ) )
+				++p;
+		}
+	}
+	return 0;
+}
Index: /code/branches/RacingBots_FS18/src/external/tolua/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,61 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+################## Tolua++ generator ##################
+
+ORXONOX_ADD_EXECUTABLE(toluaapp_orxonox
+  ORXONOX_EXTERNAL
+  VERSION
+    1.0.92
+  NO_INSTALL
+  LINK_LIBRARIES
+    ${LUA5.1_LIBRARY}
+  SOURCE_FILES
+    tolua.c
+)
+
+# Set some variables to the cache in order to use them in the TOLUA macro
+SET(TOLUA_PARSER_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/all-5.1.lua" CACHE INTERNAL "")
+SET(TOLUA_PARSER_DEPENDENCIES
+  toluaapp_orxonox
+  ${CMAKE_CURRENT_SOURCE_DIR}/all-5.1.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/compat-5.1.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/compat.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/basic.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/feature.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/verbatim.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/code.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/typedef.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/container.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/package.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/module.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/namespace.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/define.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/enumerate.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/declaration.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/variable.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/array.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/function.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/operator.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/class.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/clean.lua
+  ${CMAKE_CURRENT_SOURCE_DIR}/lua/doit.lua
+
+  CACHE INTERNAL ""
+)
Index: /code/branches/RacingBots_FS18/src/external/tolua/MANUAL
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/MANUAL	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/MANUAL	(revision 11817)
@@ -0,0 +1,58 @@
+This tolua++ is modified with support for exception handling, and more will
+likely come over time.
+
+So to avoid forgetting how it works and what's new, all added features will
+be documented in full in this file:
+
+***********************
+* Exception handling: *
+***********************
+A new function modifier 'tolua_throws' has been added. It goes the same place
+as 'tolua_outside' etc. - so before the function name and return type.
+
+Two "types" of exceptions are supported internally, but they can be customized
+by making the tolua++ binary execute a Lua script before parsing with the '-L'
+command line option.
+Look in '../LuaScriptModule/package/exceptions.lua' to see the format. It's
+fairly simple and gives you alot of control.
+
+You always have 'std::exception' and 'any' (which means ...) available.
+
+This first example would be valid in a .pkg file for tolua++, and would ensure
+that any exceptions based on 'std::exception' thrown by the real C++ function
+would result in return value of 'nil' in Lua:
+
+	tolua_throws|std::exception,nil| void I_Throw:StdException();
+
+Inside the pipes the exception name follow by return values (or actions) are
+listed. The syntax is like so:
+
+	tolua_throws|<exceptionName>[,<ret1>[,<ret2> ... [, <retN>]]]|[<exceptionName>...|]
+
+The return values can by any of the following:
+* nil
+* message (the exception message, or 'Unknown' if not possible.
+* true
+* false
+* error (can only be used alone, will contain the exception is possible)
+
+In case no return values are specified, it will default to: 'nil, message'.
+
+Example 1: 
+----------
+Returns 'nil, false' for all exceptions:
+
+	tolua_throws|any,nil,false|
+
+Example 2:
+----------
+Returns 'nil, message' if a 'std::exception' is thrown:
+
+	tolua_throws|std::exception,nil,message|
+
+Example 3:
+----------
+If a CEGUI::Exception is thrown, return 'nil, message'.
+If any other kind of exception is thrown abort (error).
+
+	tolua_throws|CEGUI::Exception|any,error|
Index: /code/branches/RacingBots_FS18/src/external/tolua/README
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/README	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/README	(revision 11817)
@@ -0,0 +1,32 @@
+This is tolua++-1.0
+
+* What is tolua++?
+  tolua++ is an extension of toLua, a tool to integrate C/C++ code with
+  Lua. tolua++ includes new features oriented to c++, such as class
+  templates.
+
+  tolua is a tool that greatly simplifies the integration of C/C++ code 
+  with Lua. Based on a "cleaned" header file, tolua automatically generates 
+  the binding code to access C/C++ features from Lua. Using Lua-5.0 API and
+  metamethod facilities, the current version automatically maps C/C++ 
+  constants, external variables, functions, namespace, classes, and methods 
+  to Lua. It also provides facilities to create Lua modules.
+
+* Availability
+  tolua is freely available; you can redistribute it and/or modify it.
+  The software provided hereunder is on an "as is" basis, and
+  the author has no obligation to provide maintenance, support, 
+  updates, enhancements, or modifications.
+
+  tolua can be downloaded from the sites below:
+            http://www.codenix.com/~tolua/
+            http://www.codenix.com/~tolua/tolua++-1.0.tar.bz2
+
+* Installation
+  See INSTALL.
+
+* Contacting the author
+  tolua has been designed and implemented by Waldemar Celes.
+  tolua++ is maintained by Ariel Manzur.
+  Send your comments, bug reports and anything else to 
+  tolua@codenix.com
Index: /code/branches/RacingBots_FS18/src/external/tolua/README_ORXONOX
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/README_ORXONOX	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/README_ORXONOX	(revision 11817)
@@ -0,0 +1,2 @@
+Beware that this tolua folder does not fully contain Tolua++. Instead you can only find the source code required for the generator executable.
+The actual tolua library has to be supplied and is called CEGUI_TOLUA_LIBRARY because we use the one supplied with CEGUI.
Index: /code/branches/RacingBots_FS18/src/external/tolua/VERSION
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/VERSION	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/VERSION	(revision 11817)
@@ -0,0 +1,9 @@
+Tolua++ v1.0.92 (generator application only) with changes:
+
+- Exception handling by CEGUI team
+- Corrected all indentation by Orxonox
+- Added more command line arguments by Orxonox
+- Several small changes considering the output files by Orxonox
+
+The changes to the C source files are stored in changes_orxonox.diff
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/all-5.1.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/all-5.1.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/all-5.1.lua	(revision 11817)
@@ -0,0 +1,29 @@
+dofile(path.."lua/compat-5.1.lua")
+dofile(path.."lua/compat.lua")
+dofile(path.."lua/basic.lua")
+dofile(path.."lua/feature.lua")
+dofile(path.."lua/verbatim.lua")
+dofile(path.."lua/code.lua")
+dofile(path.."lua/typedef.lua")
+dofile(path.."lua/container.lua")
+dofile(path.."lua/package.lua")
+dofile(path.."lua/module.lua")
+dofile(path.."lua/namespace.lua")
+dofile(path.."lua/define.lua")
+dofile(path.."lua/enumerate.lua")
+dofile(path.."lua/declaration.lua")
+dofile(path.."lua/variable.lua")
+dofile(path.."lua/array.lua")
+dofile(path.."lua/function.lua")
+dofile(path.."lua/operator.lua")
+dofile(path.."lua/class.lua")
+dofile(path.."lua/clean.lua")
+--dofile(path.."lua/custom.lua")
+dofile(path.."lua/doit.lua")
+
+local err,msg = xpcall(doit, debug.traceback)
+if not err then
+--print("**** msg is "..tostring(msg))
+ local _,_,label,msg = strfind(msg,"(.-:.-:%s*)(.*)")
+ tolua_error(msg,label)
+end
Index: /code/branches/RacingBots_FS18/src/external/tolua/changes_orxonox.diff
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/changes_orxonox.diff	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/changes_orxonox.diff	(revision 11817)
@@ -0,0 +1,144 @@
+diff -ruN tolua/tolua.c tolua2/tolua.c
+--- tolua/tolua.c	Wed Jan 28 21:51:00 2009
++++ tolua2/tolua.c	Sat Jan 10 14:48:45 2009
+@@ -4,6 +4,8 @@
+ ** TeCGraf/PUC-Rio
+ ** Aug 2003
+ ** $Id:$
++** Extension by Orxonox (Reto Grieder) to support working directory
++** and direct usage of lua files. (2008)
+ */
+ 
+ /* This code is free software; you can redistribute it and/or modify it.
+@@ -33,6 +35,8 @@
+          "  -o  file : set output file; default is stdout.\n"
+          "  -H  file : create include file.\n"
+          "  -n  name : set package name; default is input file root name.\n"
++         "  -w  directory : set working directory; default is location of package file.\n"
++         "  -s  file : specify source lua code for the parser; all.lua is default.\n"
+          "  -p       : parse only.\n"
+          "  -P       : parse and print structure information (for debug).\n"
+          "  -S       : disable support for c++ strings.\n"
+@@ -64,12 +68,12 @@
+ }
+ 
+ static void add_extra (lua_State* L, char* value) {
+-	int len;
+-	lua_getglobal(L, "_extra_parameters");
+-	len = luaL_getn(L, -1);
+-	lua_pushstring(L, value);
+-	lua_rawseti(L, -2, len+1);
+-	lua_pop(L, 1);
++ int len;
++ lua_getglobal(L, "_extra_parameters");
++ len = luaL_getn(L, -1);
++ lua_pushstring(L, value);
++ lua_rawseti(L, -2, len+1);
++ lua_pop(L, 1);
+ };
+ 
+ static void error (char* o)
+@@ -81,6 +85,9 @@
+ 
+ int main (int argc, char* argv[])
+ {
++ char* working_directory = "";
++ char* lua_source = "";
++
+  #ifdef LUA_VERSION_NUM /* lua 5.1 */
+  lua_State* L = luaL_newstate();
+  luaL_openlibs(L);
+@@ -97,6 +104,7 @@
+  lua_pushstring(L,TOLUA_VERSION); lua_setglobal(L,"TOLUA_VERSION");
+  lua_pushstring(L,LUA_VERSION); lua_setglobal(L,"TOLUA_LUA_VERSION");
+ 
++
+  if (argc==1)
+  {
+   help();
+@@ -124,6 +132,14 @@
+      case 'o': setfield(L,t,"o",argv[++i]); break;
+      case 'n': setfield(L,t,"n",argv[++i]); break;
+      case 'H': setfield(L,t,"H",argv[++i]); break;
++     case 'w':
++      working_directory = argv[++i];
++      setfield(L,t,"w",argv[i]);
++      break;
++     case 's':
++      lua_source = argv[++i];
++      setfield(L,t,"s",argv[i]);
++      break;
+      case 'S': setfield(L,t,"S",""); break;
+      case '1': setfield(L,t,"1",""); break;
+      case 'L': setfield(L,t,"L",argv[++i]); break;
+@@ -143,25 +159,53 @@
+   }
+   lua_pop(L,1);
+  }
+-/* #define TOLUA_SCRIPT_RUN */
+-#ifndef TOLUA_SCRIPT_RUN
++
+  {
+-  int tolua_tolua_open (lua_State* L);
+-  tolua_tolua_open(L);
+- }
++  char path[BUFSIZ];
++  char file[BUFSIZ];
++  path[0] = '\0';
++  file[0] = '\0';
++
++  if (strlen(lua_source) > 0 &&
++      lua_source[0] != '/' &&
++      lua_source[0] != '\\' &&
++      strlen(lua_source) > 1 &&
++      lua_source[1] != ':')
++  {
++   /* Relative path, prefix working directory */
++   strcpy(path, working_directory);
++   /* Make sure there is '\\' or '/' at the end of the path */
++   if (strlen(path) > 0)
++   {
++    char last = path[strlen(path) - 1];
++    if (last != '\\' && last != '/')
++     strcat(path, "/");
++   }
++  }
++
++  strcat(path, lua_source);
++
++  /* Extract the full path */
++  {
++   char* p;
++   p = strrchr(path, '/');
++   if (p == NULL)
++    p = strrchr(path, '\\');
++   p = (p == NULL) ? path : p + 1;
++   strcpy(file, p);
++   *p = '\0';
++  }
++  if (strlen(file) == 0)
++   strcpy(file, "all.lua");
++
++  lua_pushstring(L, path);
++  lua_setglobal(L, "path");
++  strcat(path, file);
++#ifdef LUA_VERSION_NUM /* lua 5.1 */
++  luaL_dofile(L, path);
+ #else
+- {
+-  char* p;
+-  char  path[BUFSIZ];
+-  strcpy(path,argv[0]);
+-  p = strrchr(path,'/');
+-  if (p==NULL) p = strrchr(path,'\\');
+-  p = (p==NULL) ? path : p+1;
+-  sprintf(p,"%s","../src/bin/lua/");
+-  lua_pushstring(L,path); lua_setglobal(L,"path");
+-		strcat(path,"all.lua");
+-  lua_dofile(L,path);
+- }
++  lua_dofile(L, path);
+ #endif
++ }
+  return 0;
+ }
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/array.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/array.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/array.lua	(revision 11817)
@@ -0,0 +1,226 @@
+-- tolua: array class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1999
+-- $Id: array.lua,v 1.1 2000/11/06 22:03:57 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Array class
+-- Represents a extern array variable or a public member of a class.
+-- Stores all fields present in a declaration.
+classArray = {
+}
+classArray.__index = classArray
+setmetatable(classArray,classDeclaration)
+
+-- Print method
+function classArray:print (ident,close)
+    print(ident.."Array{")
+    print(ident.." mod  = '"..self.mod.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.." ptr  = '"..self.ptr.."',")
+    print(ident.." name = '"..self.name.."',")
+    print(ident.." def  = '"..self.def.."',")
+    print(ident.." dim  = '"..self.dim.."',")
+    print(ident.." ret  = '"..self.ret.."',")
+    print(ident.."}"..close)
+end
+
+-- check if it is a variable
+function classArray:isvariable ()
+    return true
+end
+
+
+-- get variable value
+function classArray:getvalue (class,static)
+    if class and static then
+        return class..'::'..self.name..'[tolua_index]'
+    elseif class then
+        return 'self->'..self.name..'[tolua_index]'
+    else
+        return self.name..'[tolua_index]'
+    end
+end
+
+-- Write binding functions
+function classArray:supcode ()
+    local class = self:inclass()
+
+    -- get function ------------------------------------------------
+    if class then
+        output("/* get function:",self.name," of class ",class," */")
+    else
+        output("/* get function:",self.name," */")
+    end
+    self.cgetname = self:cfuncname("tolua_get")
+    output("#ifndef TOLUA_DISABLE_"..self.cgetname)
+    output("\nstatic int",self.cgetname,"(lua_State* tolua_S)")
+    output("{")
+    output(" int tolua_index;")
+
+    -- declare self, if the case
+    local _,_,static = strfind(self.mod,'^%s*(static)')
+    if class and static==nil then
+        output(' ',self.parent.type,'*','self;')
+        output(' lua_pushstring(tolua_S,".self");')
+        output(' lua_rawget(tolua_S,1);')
+        output(' self = ')
+        output('(',self.parent.type,'*) ')
+        output('lua_touserdata(tolua_S,-1);')
+    elseif static then
+        _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+    end
+
+    -- check index
+    output('#ifndef TOLUA_RELEASE\n')
+    output(' {')
+    output('  tolua_Error tolua_err;')
+    output('  if (!tolua_isnumber(tolua_S,2,0,&tolua_err))')
+    output('   tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);')
+    output(' }')
+    output('#endif\n')
+    if flags['1'] then -- for compatibility with tolua5 ?
+        output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0)-1;')
+    else
+        output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0);')
+    end
+    output('#ifndef TOLUA_RELEASE\n')
+    if self.dim and self.dim ~= '' then
+        output(' if (tolua_index<0 || tolua_index>='..self.dim..')')
+    else
+        output(' if (tolua_index<0)')
+    end
+    output('  tolua_error(tolua_S,"array indexing out of range.",NULL);')
+    output('#endif\n')
+
+    -- return value
+    local t,ct = isbasic(self.type)
+    if t then
+        output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static)..');')
+    else
+        t = self.type
+        if self.ptr == '&' or self.ptr == '' then
+            output(' tolua_pushusertype(tolua_S,(void*)&'..self:getvalue(class,static)..',"',t,'");')
+        else
+            output(' tolua_pushusertype(tolua_S,(void*)'..self:getvalue(class,static)..',"',t,'");')
+        end
+    end
+    output(' return 1;')
+    output('}')
+    output('#endif //#ifndef TOLUA_DISABLE\n')
+    output('\n')
+
+    -- set function ------------------------------------------------
+    if not strfind(self.type,'const') then
+        if class then
+            output("/* set function:",self.name," of class ",class," */")
+        else
+            output("/* set function:",self.name," */")
+        end
+        self.csetname = self:cfuncname("tolua_set")
+        output("#ifndef TOLUA_DISABLE_"..self.csetname)
+        output("\nstatic int",self.csetname,"(lua_State* tolua_S)")
+        output("{")
+
+        -- declare index
+        output(' int tolua_index;')
+
+        -- declare self, if the case
+        local _,_,static = strfind(self.mod,'^%s*(static)')
+        if class and static==nil then
+            output(' ',self.parent.type,'*','self;')
+            output(' lua_pushstring(tolua_S,".self");')
+            output(' lua_rawget(tolua_S,1);')
+            output(' self = ')
+            output('(',self.parent.type,'*) ')
+            output('lua_touserdata(tolua_S,-1);')
+        elseif static then
+            _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+        end
+
+        -- check index
+        output('#ifndef TOLUA_RELEASE\n')
+        output(' {')
+        output('  tolua_Error tolua_err;')
+        output('  if (!tolua_isnumber(tolua_S,2,0,&tolua_err))')
+        output('   tolua_error(tolua_S,"#vinvalid type in array indexing.",&tolua_err);')
+        output(' }')
+        output('#endif\n')
+
+        if flags['1'] then -- for compatibility with tolua5 ?
+            output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0)-1;')
+        else
+            output(' tolua_index = (int)tolua_tonumber(tolua_S,2,0);')
+        end
+
+        output('#ifndef TOLUA_RELEASE\n')
+        if self.dim and self.dim ~= '' then
+            output(' if (tolua_index<0 || tolua_index>='..self.dim..')')
+        else
+            output(' if (tolua_index<0)')
+        end
+        output('  tolua_error(tolua_S,"array indexing out of range.",NULL);')
+        output('#endif\n')
+
+        -- assign value
+        local ptr = ''
+        if self.ptr~='' then ptr = '*' end
+            output(' ')
+        if class and static then
+            output(class..'::'..self.name..'[tolua_index]')
+        elseif class then
+            output('self->'..self.name..'[tolua_index]')
+        else
+            output(self.name..'[tolua_index]')
+        end
+        local t = isbasic(self.type)
+        output(' = ')
+        if not t and ptr=='' then output('*') end
+        output('((',self.mod,self.type)
+        if not t then
+            output('*')
+        end
+        output(') ')
+        local def = 0
+        if self.def ~= '' then def = self.def end
+        if t then
+            output('tolua_to'..t,'(tolua_S,3,',def,'));')
+        else
+            output('tolua_tousertype(tolua_S,3,',def,'));')
+        end
+        output(' return 0;')
+        output('}')
+        output('#endif //#ifndef TOLUA_DISABLE\n')
+        output('\n')
+    end
+end
+
+function classArray:register (pre)
+    pre = pre or ''
+    if self.csetname then
+        output(pre..'tolua_array(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');')
+    else
+        output(pre..'tolua_array(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);')
+    end
+end
+
+-- Internal constructor
+function _Array (t)
+    setmetatable(t,classArray)
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects a string representing the variable declaration.
+function Array (s)
+    return _Array (Declaration(s,'var'))
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/basic.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/basic.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/basic.lua	(revision 11817)
@@ -0,0 +1,358 @@
+-- tolua: basic utility functions
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- Last update: Apr 2003
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Basic C types and their corresponding Lua types
+-- All occurrences of "char*" will be replaced by "_cstring",
+-- and all occurrences of "void*" will be replaced by "_userdata"
+_basic = {
+    ['void'] = '',
+    ['char'] = 'number',
+    ['int'] = 'number',
+    ['short'] = 'number',
+    ['long'] = 'number',
+    ['unsigned'] = 'number',
+    ['float'] = 'number',
+    ['double'] = 'number',
+    ['_cstring'] = 'string',
+    ['_userdata'] = 'userdata',
+    ['char*'] = 'string',
+    ['void*'] = 'userdata',
+    ['bool'] = 'boolean',
+    ['lua_Object'] = 'value',
+    ['LUA_VALUE'] = 'value',    -- for compatibility with tolua 4.0
+    ['lua_State*'] = 'state',
+    ['_lstate'] = 'state',
+    ['lua_Function'] = 'value',
+}
+
+_basic_ctype = {
+    number = "lua_Number",
+    string = "const char*",
+    userdata = "void*",
+    boolean = "bool",
+    value = "int",
+    state = "lua_State*",
+}
+
+-- functions the are used to do a 'raw push' of basic types
+_basic_raw_push = {}
+
+-- List of user defined types
+-- Each type corresponds to a variable name that stores its tag value.
+_usertype = {}
+
+-- List of types that have to be collected
+_collect = {}
+
+-- List of types
+_global_types = {n=0}
+_global_types_hash = {}
+
+-- list of classes
+_global_classes = {}
+
+-- List of enum constants
+_global_enums = {}
+
+-- List of auto renaming
+_renaming = {}
+function appendrenaming (s)
+    local b,e,old,new = strfind(s,"%s*(.-)%s*@%s*(.-)%s*$")
+    if not b then
+        error("#Invalid renaming syntax; it should be of the form: pattern@pattern")
+    end
+    tinsert(_renaming,{old=old, new=new})
+end
+
+function applyrenaming (s)
+    for i=1,getn(_renaming) do
+        local m,n = gsub(s,_renaming[i].old,_renaming[i].new)
+        if n ~= 0 then
+            return m
+        end
+    end
+    return nil
+end
+
+-- Error handler
+function tolua_error (s,f)
+    if _curr_code then
+        print("***curr code for error is "..tostring(_curr_code))
+        print(debug.traceback())
+    end
+    local out = _OUTPUT
+    _OUTPUT = _STDERR
+    if strsub(s,1,1) == '#' then
+        write("\n** tolua: "..strsub(s,2)..".\n\n")
+        if _curr_code then
+            local _,_,s = strfind(_curr_code,"^%s*(.-\n)") -- extract first line
+            if s==nil then s = _curr_code end
+            s = gsub(s,"_userdata","void*") -- return with 'void*'
+            s = gsub(s,"_cstring","char*")  -- return with 'char*'
+            s = gsub(s,"_lstate","lua_State*")  -- return with 'lua_State*'
+            write("Code being processed:\n"..s.."\n")
+        end
+    else
+        if not f then f = "(f is nil)" end
+        print("\n** tolua internal error: "..f..s..".\n\n")
+        return
+    end
+    _OUTPUT = out
+end
+
+function warning (msg)
+    local out = _OUTPUT
+    _OUTPUT = _STDERR
+    write("\n** tolua warning: "..msg..".\n\n")
+    _OUTPUT = out
+end
+
+-- register an user defined type: returns full type
+function regtype (t)
+    --if isbasic(t) then
+    --    return t
+    --end
+    local ft = findtype(t)
+
+    if not _usertype[ft] then
+        return appendusertype(t)
+    end
+    return ft
+end
+
+-- return type name: returns full type
+function typevar(type)
+    if type == '' or type == 'void' then
+        return type
+    else
+        local ft = findtype(type)
+        if ft then
+            return ft
+        end
+        _usertype[type] = type
+        return type
+    end
+end
+
+-- check if basic type
+function isbasic (type)
+    local t = gsub(type,'const ','')
+    local m,t = applytypedef('', t)
+    local b = _basic[t]
+    if b then
+        return b,_basic_ctype[b]
+    end
+    return nil
+end
+
+-- split string using a token
+function split (s,t)
+    local l = {n=0}
+    local f = function (s)
+        l.n = l.n + 1
+        l[l.n] = s
+        return ""
+    end
+    local p = "%s*(.-)%s*"..t.."%s*"
+    s = gsub(s,"^%s+","")
+    s = gsub(s,"%s+$","")
+    s = gsub(s,p,f)
+    l.n = l.n + 1
+    l[l.n] = gsub(s,"(%s%s*)$","")
+    return l
+end
+
+-- splits a string using a pattern, considering the spacial cases of C code (templates, function parameters, etc)
+-- pattern can't contain the '^' (as used to identify the begining of the line)
+-- also strips whitespace
+function split_c_tokens(s, pat)
+
+    s = string.gsub(s, "^%s*", "")
+    s = string.gsub(s, "%s*$", "")
+
+    local token_begin = 1
+    local token_end = 1
+    local ofs = 1
+    local ret = {n=0}
+
+    function add_token(ofs)
+
+        local t = string.sub(s, token_begin, ofs)
+        t = string.gsub(t, "^%s*", "")
+        t = string.gsub(t, "%s*$", "")
+        ret.n = ret.n + 1
+        ret[ret.n] = t
+    end
+
+    while ofs <= string.len(s) do
+
+        local sub = string.sub(s, ofs, -1)
+        local b,e = string.find(sub, "^"..pat)
+        if b then
+            add_token(ofs-1)
+            ofs = ofs+e
+            token_begin = ofs
+        else
+            local char = string.sub(s, ofs, ofs)
+            if char == "(" or char == "<" then
+
+                local block
+                if char == "(" then block = "^%b()" end
+                if char == "<" then block = "^%b<>" end
+
+                b,e = string.find(sub, block)
+                if not b then
+                    -- unterminated block?
+                    ofs = ofs+1
+                else
+                    ofs = ofs + e
+                end
+
+            else
+                ofs = ofs+1
+            end
+        end
+
+    end
+    add_token(ofs)
+    --if ret.n == 0 then
+
+    --    ret.n=1
+    --    ret[1] = ""
+    --end
+
+    return ret
+
+end
+
+-- concatenate strings of a table
+function concat (t,f,l,jstr)
+    jstr = jstr or " "
+    local s = ''
+    local i=f
+    while i<=l do
+        s = s..t[i]
+        i = i+1
+        if i <= l then s = s..jstr end
+    end
+    return s
+end
+
+-- concatenate all parameters, following output rules
+function concatparam (line, ...)
+    local i=1
+    while i<=arg.n do
+        if _cont and not strfind(_cont,'[%(,"]') and
+            strfind(arg[i],"^[%a_~]") then
+            line = line .. ' '
+        end
+        line = line .. arg[i]
+        if arg[i] ~= '' then
+            _cont = strsub(arg[i],-1,-1)
+        end
+        i = i+1
+    end
+    if strfind(arg[arg.n],"[%/%)%;%{%}]$") then
+        _cont=nil line = line .. '\n'
+    end
+    return line
+end
+
+-- output line
+function output (...)
+    local i=1
+    while i<=arg.n do
+        if _cont and not strfind(_cont,'[%(,"]') and
+            strfind(arg[i],"^[%a_~]") then
+            write(' ')
+        end
+        write(arg[i])
+        if arg[i] ~= '' then
+            _cont = strsub(arg[i],-1,-1)
+        end
+        i = i+1
+    end
+    if strfind(arg[arg.n],"[%/%)%;%{%}]$") then
+        _cont=nil write('\n')
+    end
+end
+
+function get_property_methods(ptype, name)
+
+    if get_property_methods_hook and get_property_methods_hook(ptype,name) then
+        return get_property_methods_hook(ptype, name)
+    end
+
+    if ptype == "default" then -- get_name, set_name
+        return "get_"..name, "set_"..name
+    end
+
+    if ptype == "qt" then -- name, setName
+        return name, "set"..string.upper(string.sub(name, 1, 1))..string.sub(name, 2, -1)
+    end
+
+    if ptype == "overload" then -- name, name
+        return name,name
+    end
+
+    return nil
+end
+
+-------------- the hooks
+
+-- called right after processing the $[ichl]file directives,
+-- right before processing anything else
+-- takes the package object as the parameter
+function preprocess_hook(p)
+    -- p.code has all the input code from the pkg
+end
+
+
+-- called for every $ifile directive
+-- takes a table with a string called 'code' inside, the filename, and any extra arguments
+-- passed to $ifile. no return value
+function include_file_hook(t, filename, ...)
+
+end
+
+-- called after processing anything that's not code (like '$renaming', comments, etc)
+-- and right before parsing the actual code.
+-- takes the Package object with all the code on the 'code' key. no return value
+function preparse_hook(package)
+
+end
+
+
+-- called after writing all the output.
+-- takes the Package object
+function post_output_hook(package)
+
+end
+
+
+-- called from 'get_property_methods' to get the methods to retrieve a property
+-- according to its type
+function get_property_methods_hook(property_type, name)
+
+end
+
+-- called from ClassContainer:doparse with the string being parsed
+-- return nil, or a substring
+function parser_hook(s)
+
+    return nil
+end
+
+-- called after all the required C++ includes have been written
+function post_include_hook(package_name)
+end
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/class.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/class.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/class.lua	(revision 11817)
@@ -0,0 +1,220 @@
+-- tolua: class class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Class class
+-- Represents a class definition.
+-- Stores the following fields:
+--    name = class name
+--    base = class base, if any (only single inheritance is supported)
+--    {i}  = list of members
+classClass = {
+    classtype = 'class',
+    name = '',
+    base = '',
+    type = '',
+    btype = '',
+    ctype = '',
+}
+classClass.__index = classClass
+setmetatable(classClass,classContainer)
+
+
+-- register class
+function classClass:register (pre)
+    if not self:check_public_access() then
+        return
+    end
+
+    pre = pre or ''
+    push(self)
+    if _collect[self.type] then
+        output(pre,'#ifdef __cplusplus\n')
+        output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",'.._collect[self.type]..');')
+        output(pre,'#else\n')
+        output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
+        output(pre,'#endif\n')
+    else
+        output(pre..'tolua_cclass(tolua_S,"'..self.lname..'","'..self.type..'","'..self.btype..'",NULL);')
+    end
+    if self.extra_bases then
+        for k,base in ipairs(self.extra_bases) do
+            -- not now
+            --output(pre..' tolua_addbase(tolua_S, "'..self.type..'", "'..base..'");')
+        end
+    end
+    output(pre..'tolua_beginmodule(tolua_S,"'..self.lname..'");')
+    local i=1
+    while self[i] do
+        self[i]:register(pre..' ')
+        i = i+1
+    end
+    output(pre..'tolua_endmodule(tolua_S);')
+    pop()
+end
+
+-- return collection requirement
+function classClass:requirecollection (t)
+    if self.flags.protected_destructor then
+        return false
+    end
+    push(self)
+    local r = false
+    local i=1
+    while self[i] do
+        r = self[i]:requirecollection(t) or r
+        i = i+1
+    end
+    pop()
+    -- only class that exports destructor can be appropriately collected
+    -- classes that export constructors need to have a collector (overrided by -D flag on command line)
+    if self._delete or ((not flags['D']) and self._new) then
+        --t[self.type] = "tolua_collect_" .. gsub(self.type,"::","_")
+        t[self.type] = "tolua_collect_" .. clean_template(self.type)
+        r = true
+    end
+    return r
+end
+
+-- output tags
+function classClass:decltype ()
+    push(self)
+    self.type = regtype(self.original_name or self.name)
+    self.btype = typevar(self.base)
+    self.ctype = 'const '..self.type
+    if self.extra_bases then
+        for i=1,table.getn(self.extra_bases) do
+            self.extra_bases[i] = typevar(self.extra_bases[i])
+        end
+    end
+    local i=1
+    while self[i] do
+        self[i]:decltype()
+        i = i+1
+    end
+    pop()
+end
+
+
+-- Print method
+function classClass:print (ident,close)
+    print(ident.."Class{")
+    print(ident.." name = '"..self.name.."',")
+    print(ident.." base = '"..self.base.."';")
+    print(ident.." lname = '"..self.lname.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.." btype = '"..self.btype.."',")
+    print(ident.." ctype = '"..self.ctype.."',")
+    local i=1
+    while self[i] do
+        self[i]:print(ident.." ",",")
+        i = i+1
+    end
+    print(ident.."}"..close)
+end
+
+function classClass:set_protected_destructor(p)
+self.flags.protected_destructor = self.flags.protected_destructor or p
+end
+
+-- Internal constructor
+function _Class (t)
+    setmetatable(t,classClass)
+    t:buildnames()
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects the name, the base (array) and the body of the class.
+function Class (n,p,b)
+
+    if table.getn(p) > 1 then
+        b = string.sub(b, 1, -2)
+        for i=2,table.getn(p),1 do
+            b = b.."\n tolua_inherits "..p[i].." __"..p[i].."__;\n"
+        end
+        b = b.."\n}"
+    end
+
+    -- check for template
+    b = string.gsub(b, "^{%s*TEMPLATE_BIND", "{\nTOLUA_TEMPLATE_BIND")
+    local t,_,T,I = string.find(b, "^{%s*TOLUA_TEMPLATE_BIND%s*%(+%s*\"?([^\",]*)\"?%s*,%s*([^%)]*)%s*%)+")
+    if t then
+
+        -- remove quotes
+        I = string.gsub(I, "\"", "")
+        T = string.gsub(T, "\"", "")
+        -- get type list
+        local types = split_c_tokens(I, ",")
+        -- remove TEMPLATE_BIND line
+        local bs = string.gsub(b, "^{%s*TOLUA_TEMPLATE_BIND[^\n]*\n", "{\n")
+
+        -- replace
+        for i =1 , types.n do
+
+            local Tl = split(T, " ")
+            local Il = split_c_tokens(types[i], " ")
+            local bI = bs
+            local pI = {}
+            for j = 1,Tl.n do
+                Tl[j] = findtype(Tl[j]) or Tl[j]
+                bI = string.gsub(bI, "([^_%w])"..Tl[j].."([^_%w])", "%1"..Il[j].."%2")
+                if p then
+                    for i=1,table.getn(p) do
+                        pI[i] = string.gsub(p[i], "([^_%w]?)"..Tl[j].."([^_%w]?)", "%1"..Il[j].."%2")
+                    end
+                end
+            end
+            --local append = "<"..string.gsub(types[i], "%s+", ",")..">"
+            local append = "<"..concat(Il, 1, table.getn(Il), ",")..">"
+            append = string.gsub(append, "%s*,%s*", ",")
+            append = string.gsub(append, ">>", "> >")
+            for i=1,table.getn(pI) do
+                --pI[i] = string.gsub(pI[i], ">>", "> >")
+                pI[i] = resolve_template_types(pI[i])
+            end
+            bI = string.gsub(bI, ">>", "> >")
+            Class(n..append, pI, bI)
+        end
+        return
+    end
+
+    local mbase
+
+    if p then
+        mbase = table.remove(p, 1)
+        if not p[1] then p = nil end
+    end
+
+    mbase = mbase and resolve_template_types(mbase)
+
+    local c
+    local oname = string.gsub(n, "@.*$", "")
+    oname = getnamespace(classContainer.curr)..oname
+
+    if _global_classes[oname] then
+        c = _global_classes[oname]
+        if mbase and ((not c.base) or c.base == "") then
+            c.base = mbase
+        end
+    else
+        c = _Class(_Container{name=n, base=mbase, extra_bases=p})
+
+        local ft = getnamespace(c.parent)..c.original_name
+        append_global_type(ft, c)
+    end
+
+    push(c)
+    c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
+    pop()
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/clean.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/clean.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/clean.lua	(revision 11817)
@@ -0,0 +1,79 @@
+-- mark up comments and strings
+STR1 = "\001"
+STR2 = "\002"
+STR3 = "\003"
+STR4 = "\004"
+REM  = "\005"
+ANY  = "([\001-\005])"
+ESC1 = "\006"
+ESC2 = "\007"
+
+MASK = { -- the substitution order is important
+    {ESC1, "\\'"},
+    {ESC2, '\\"'},
+    {STR1, "'"},
+    {STR2, '"'},
+    {STR3, "%[%["},
+    {STR4, "%]%]"},
+    {REM , "%-%-"},
+}
+
+function mask (s)
+    for i = 1,getn(MASK)  do
+        s = gsub(s,MASK[i][2],MASK[i][1])
+    end
+    return s
+end
+
+function unmask (s)
+    for i = 1,getn(MASK)  do
+        s = gsub(s,MASK[i][1],MASK[i][2])
+    end
+    return s
+end
+
+function clean (s)
+    -- check for compilation error
+    local code = "return function ()\n" .. s .. "\n end"
+    if not dostring(code) then
+        return nil
+    end
+
+    if flags['C'] then
+        return s
+    end
+
+    local S = "" -- saved string
+
+    s = mask(s)
+
+    -- remove blanks and comments
+    while 1 do
+        local b,e,d = strfind(s,ANY)
+        if b then
+            S = S..strsub(s,1,b-1)
+            s = strsub(s,b+1)
+            if d==STR1 or d==STR2 then
+                e = strfind(s,d)
+                S = S ..d..strsub(s,1,e)
+                s = strsub(s,e+1)
+            elseif d==STR3 then
+                e = strfind(s,STR4)
+                S = S..d..strsub(s,1,e)
+                s = strsub(s,e+1)
+            elseif d==REM then
+                s = gsub(s,"[^\n]*(\n?)","%1",1)
+            end
+        else
+            S = S..s
+            break
+        end
+    end
+    -- eliminate unecessary spaces
+    S = gsub(S,"[ \t]+"," ")
+    S = gsub(S,"[ \t]*\n[ \t]*","\n")
+    S = gsub(S,"\n+","\n")
+    S = unmask(S)
+    return S
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/code.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/code.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/code.lua	(revision 11817)
@@ -0,0 +1,100 @@
+-- tolua: code class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1999
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+-- global
+code_n = 1
+
+-- Code class
+-- Represents Lua code to be compiled and included
+-- in the initialization function.
+-- The following fields are stored:
+--   text = text code
+classCode = {
+    text = '',
+}
+classCode.__index = classCode
+setmetatable(classCode,classFeature)
+
+-- register code
+function classCode:register (pre)
+    pre = pre or ''
+    -- clean Lua code
+    local s = clean(self.text)
+    if not s then
+        --print(self.text)
+        error("parser error in embedded code")
+    end
+
+    -- get first line
+    local _, _, first_line=string.find(self.text, "^([^\n\r]*)")
+    if string.find(first_line, "^%s*%-%-") then
+        if string.find(first_line, "^%-%-##") then
+            first_line = string.gsub(first_line, "^%-%-##", "")
+            if flags['C'] then
+                s = string.gsub(s, "^%-%-##[^\n\r]*\n", "")
+            end
+        end
+    else
+        first_line = ""
+    end
+
+    -- convert to C
+    output('\n'..pre..'{ /* begin embedded lua code */\n')
+    output(pre..' int top = lua_gettop(tolua_S);')
+    output(pre..' static unsigned char B[] = {\n   ')
+    local t={n=0}
+    local b = gsub(s, '(.)',
+        function (c)
+            local e = ''
+            t.n=t.n+1
+            if t.n==15 then
+             t.n=0 e='\n'..pre..'  '
+            end
+            return format('%3u,%s',strbyte(c),e)
+        end
+    )
+    output(b..strbyte(" "))
+    output('\n'..pre..' };\n')
+    if first_line and first_line ~= "" then
+        output(pre..' tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua embedded: '..first_line..'");')
+    else
+        output(pre..' tolua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua: embedded Lua code '..code_n..'");')
+    end
+    output(pre..' lua_settop(tolua_S, top);')
+    output(pre..'} /* end of embedded lua code */\n\n')
+    code_n = code_n +1
+end
+
+
+-- Print method
+function classCode:print (ident,close)
+    print(ident.."Code{")
+    print(ident.." text = [["..self.text.."]],")
+    print(ident.."}"..close)
+end
+
+
+-- Internal constructor
+function _Code (t)
+    setmetatable(t,classCode)
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects a string representing the code text
+function Code (l)
+    return _Code {
+        text = l
+    }
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/compat-5.1.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/compat-5.1.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/compat-5.1.lua	(revision 11817)
@@ -0,0 +1,52 @@
+if string.find(_VERSION, "5%.0") then
+    return
+end
+
+-- "loadfile"
+local function pp_dofile(path)
+    local loaded = false
+    local getfile = function()
+
+        if loaded then
+            return
+        else
+            local file,err = io.open(path)
+            if not file then
+                error("error loading file "..path..": "..err)
+            end
+            local ret = file:read("*a")
+            file:close()
+
+            ret = string.gsub(ret, "%.%.%.%s*%)", "...) local arg = {n=select('#', ...), ...};")
+
+            loaded = true
+            return ret
+        end
+    end
+
+    local f = load(getfile, path)
+    return f()
+end
+
+old_dofile = dofile
+dofile = pp_dofile
+
+
+-- string.gsub
+--[[
+local ogsub = string.gsub
+local function compgsub(a,b,c,d)
+    if type(c) == "function" then
+        local oc = c
+        c = function (...) return oc(...) or '' end
+    end
+    return ogsub(a,b,c,d)
+end
+string.repl = ogsub
+--]]
+
+--string.gsub = compgsub
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/compat.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/compat.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/compat.lua	(revision 11817)
@@ -0,0 +1,193 @@
+-------------------------------------------------------------------
+-- Real globals
+-- _ALERT
+-- _ERRORMESSAGE
+-- _VERSION
+-- _G
+-- assert
+-- error
+-- metatable
+-- next
+-- print
+-- require
+-- tonumber
+-- tostring
+-- type
+-- unpack
+
+-------------------------------------------------------------------
+-- collectgarbage
+-- gcinfo
+
+-- globals
+
+-- call   -> protect(f, err)
+-- loadfile
+-- loadstring
+
+-- rawget
+-- rawset
+
+-- getargs = Main.getargs ??
+
+rawtype = type
+
+function do_ (f, err)
+    if not f then print(err); return end
+    local a,b = pcall(f)
+    if not a then print(b); return nil
+    else return b or true
+    end
+end
+
+function dostring(s) return do_(loadstring(s)) end
+-- function dofile(s) return do_(loadfile(s)) end
+
+-------------------------------------------------------------------
+-- Table library
+local tab = table
+foreach = tab.foreach
+foreachi = tab.foreachi
+getn = tab.getn
+tinsert = tab.insert
+tremove = tab.remove
+sort = tab.sort
+
+-------------------------------------------------------------------
+-- Debug library
+local dbg = debug
+getinfo = dbg.getinfo
+getlocal = dbg.getlocal
+setcallhook = function () error"`setcallhook' is deprecated" end
+setlinehook = function () error"`setlinehook' is deprecated" end
+setlocal = dbg.setlocal
+
+-------------------------------------------------------------------
+-- math library
+local math = math
+abs = math.abs
+acos = function (x) return math.deg(math.acos(x)) end
+asin = function (x) return math.deg(math.asin(x)) end
+atan = function (x) return math.deg(math.atan(x)) end
+atan2 = function (x,y) return math.deg(math.atan2(x,y)) end
+ceil = math.ceil
+cos = function (x) return math.cos(math.rad(x)) end
+deg = math.deg
+exp = math.exp
+floor = math.floor
+frexp = math.frexp
+ldexp = math.ldexp
+log = math.log
+log10 = math.log10
+max = math.max
+min = math.min
+mod = math.mod
+PI = math.pi
+--??? pow = math.pow  
+rad = math.rad
+random = math.random
+randomseed = math.randomseed
+sin = function (x) return math.sin(math.rad(x)) end
+sqrt = math.sqrt
+tan = function (x) return math.tan(math.rad(x)) end
+
+-------------------------------------------------------------------
+-- string library
+local str = string
+strbyte = str.byte
+strchar = str.char
+strfind = str.find
+format = str.format
+gsub = str.gsub
+strlen = str.len
+strlower = str.lower
+strrep = str.rep
+strsub = str.sub
+strupper = str.upper
+
+-------------------------------------------------------------------
+-- os library
+clock = os.clock
+date = os.date
+difftime = os.difftime
+execute = os.execute --?
+exit = os.exit
+getenv = os.getenv
+remove = os.remove
+rename = os.rename
+setlocale = os.setlocale
+time = os.time
+tmpname = os.tmpname
+
+-------------------------------------------------------------------
+-- compatibility only
+getglobal = function (n) return _G[n] end
+setglobal = function (n,v) _G[n] = v end
+
+-------------------------------------------------------------------
+
+local io, tab = io, table
+
+-- IO library (files)
+_STDIN = io.stdin
+_STDERR = io.stderr
+_STDOUT = io.stdout
+_INPUT = io.stdin
+_OUTPUT = io.stdout
+seek = io.stdin.seek   -- sick ;-)
+tmpfile = io.tmpfile
+closefile = io.close
+openfile = io.open
+
+function flush (f)
+    if f then f:flush()
+    else _OUTPUT:flush()
+    end
+end
+
+function readfrom (name)
+    if name == nil then
+        local f, err, cod = io.close(_INPUT)
+        _INPUT = io.stdin
+        return f, err, cod
+    else
+        local f, err, cod = io.open(name, "r")
+        _INPUT = f or _INPUT
+        return f, err, cod
+    end
+end
+
+function writeto (name)
+    if name == nil then
+        local f, err, cod = io.close(_OUTPUT)
+        _OUTPUT = io.stdout
+        return f, err, cod
+    else
+        local f, err, cod = io.open(name, "w")
+        _OUTPUT = f or _OUTPUT
+        return f, err, cod
+    end
+end
+
+function appendto (name)
+    local f, err, cod = io.open(name, "a")
+    _OUTPUT = f or _OUTPUT
+    return f, err, cod
+end
+
+function read (...)
+    local f = _INPUT
+    if rawtype(arg[1]) == 'userdata' then
+        f = tab.remove(arg, 1)
+    end
+    return f:read(unpack(arg))
+end
+
+function write (...)
+    local f = _OUTPUT
+    if rawtype(arg[1]) == 'userdata' then
+        f = tab.remove(arg, 1)
+    end
+    return f:write(unpack(arg))
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/container.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/container.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/container.lua	(revision 11817)
@@ -0,0 +1,770 @@
+-- tolua: container abstract class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+-- table to store namespaced typedefs/enums in global scope
+global_typedefs = {}
+global_enums = {}
+
+-- Container class
+-- Represents a container of features to be bound
+-- to lua.
+classContainer =
+{
+    curr = nil,
+}
+classContainer.__index = classContainer
+setmetatable(classContainer,classFeature)
+
+-- output tags
+function classContainer:decltype ()
+    push(self)
+    local i=1
+    while self[i] do
+        self[i]:decltype()
+        i = i+1
+    end
+    pop()
+end
+
+
+-- write support code
+function classContainer:supcode ()
+
+    if not self:check_public_access() then
+        return
+    end
+
+    push(self)
+    local i=1
+    while self[i] do
+        if self[i]:check_public_access() then
+            self[i]:supcode()
+        end
+        i = i+1
+    end
+    pop()
+end
+
+function classContainer:hasvar ()
+    local i=1
+    while self[i] do
+        if self[i]:isvariable() then
+            return 1
+        end
+        i = i+1
+    end
+    return 0
+end
+
+-- Internal container constructor
+function _Container (self)
+    setmetatable(self,classContainer)
+    self.n = 0
+    self.typedefs = {tolua_n=0}
+    self.usertypes = {}
+    self.enums = {tolua_n=0}
+    self.lnames = {}
+    return self
+end
+
+-- push container
+function push (t)
+    t.prox = classContainer.curr
+    classContainer.curr = t
+end
+
+-- pop container
+function pop ()
+    --print("name",classContainer.curr.name)
+    --foreach(classContainer.curr.usertypes,print)
+    --print("______________")
+    classContainer.curr = classContainer.curr.prox
+end
+
+-- get current namespace
+function getcurrnamespace ()
+    return getnamespace(classContainer.curr)
+end
+
+-- append to current container
+function append (t)
+    return classContainer.curr:append(t)
+end
+
+-- append typedef to current container
+function appendtypedef (t)
+    return classContainer.curr:appendtypedef(t)
+end
+
+-- append usertype to current container
+function appendusertype (t)
+    return classContainer.curr:appendusertype(t)
+end
+
+-- append enum to current container
+function appendenum (t)
+    return classContainer.curr:appendenum(t)
+end
+
+-- substitute typedef
+function applytypedef (mod,type)
+    return classContainer.curr:applytypedef(mod,type)
+end
+
+-- check if is type
+function findtype (type)
+    local t = classContainer.curr:findtype(type)
+    return t
+end
+
+-- check if is typedef
+function istypedef (type)
+    return classContainer.curr:istypedef(type)
+end
+
+-- get fulltype (with namespace)
+function fulltype (t)
+    local curr =  classContainer.curr
+    while curr do
+        if curr then
+            if curr.typedefs and curr.typedefs[t] then
+                return curr.typedefs[t]
+            elseif curr.usertypes and curr.usertypes[t] then
+                return curr.usertypes[t]
+            end
+        end
+        curr = curr.prox
+    end
+    return t
+end
+
+-- checks if it requires collection
+function classContainer:requirecollection (t)
+    push(self)
+    local i=1
+    local r = false
+    while self[i] do
+        r = self[i]:requirecollection(t) or r
+        i = i+1
+    end
+    pop()
+    return r
+end
+
+
+-- get namesapce
+function getnamespace (curr)
+    local namespace = ''
+    while curr do
+        if curr and
+            ( curr.classtype == 'class' or curr.classtype == 'namespace')
+        then
+            namespace = (curr.original_name or curr.name) .. '::' .. namespace
+            --namespace = curr.name .. '::' .. namespace
+        end
+        curr = curr.prox
+    end
+    return namespace
+end
+
+-- get namespace (only namespace)
+function getonlynamespace ()
+    local curr = classContainer.curr
+    local namespace = ''
+    while curr do
+        if curr.classtype == 'class' then
+            return namespace
+        elseif curr.classtype == 'namespace' then
+            namespace = curr.name .. '::' .. namespace
+        end
+        curr = curr.prox
+    end
+    return namespace
+end
+
+-- check if is enum
+function isenum (type)
+    return classContainer.curr:isenum(type)
+end
+
+-- append feature to container
+function classContainer:append (t)
+    self.n = self.n + 1
+    self[self.n] = t
+    t.parent = self
+end
+
+-- append typedef
+function classContainer:appendtypedef (t)
+    local namespace = getnamespace(classContainer.curr)
+    self.typedefs.tolua_n = self.typedefs.tolua_n + 1
+    self.typedefs[self.typedefs.tolua_n] = t
+    self.typedefs[t.utype] = namespace .. t.utype
+    global_typedefs[namespace..t.utype] = t
+    t.ftype = findtype(t.type) or t.type
+    --print("appending typedef "..t.utype.." as "..namespace..t.utype.." with ftype "..t.ftype)
+    append_global_type(namespace..t.utype)
+    if t.ftype and isenum(t.ftype) then
+        global_enums[namespace..t.utype] = true
+    end
+end
+
+-- append usertype: return full type
+function classContainer:appendusertype (t)
+    local container
+    if t == (self.original_name or self.name) then
+        container = self.prox
+    else
+        container = self
+    end
+    local ft = getnamespace(container) .. t
+    container.usertypes[t] = ft
+    _usertype[ft] = ft
+    return ft
+end
+
+-- append enum
+function classContainer:appendenum (t)
+    local namespace = getnamespace(classContainer.curr)
+    self.enums.tolua_n = self.enums.tolua_n + 1
+    self.enums[self.enums.tolua_n] = t
+    global_enums[namespace..t.name] = t
+end
+
+-- determine lua function name overload
+function classContainer:overload (lname)
+    if not self.lnames[lname] then
+        self.lnames[lname] = 0
+    else
+        self.lnames[lname] = self.lnames[lname] + 1
+    end
+    return format("%02d",self.lnames[lname])
+end
+
+-- applies typedef: returns the 'the facto' modifier and type
+function classContainer:applytypedef (mod,type)
+    if global_typedefs[type] then
+        --print("found typedef "..global_typedefs[type].type)
+        local mod1, type1 = global_typedefs[type].mod, global_typedefs[type].ftype
+        local mod2, type2 = applytypedef(mod.." "..mod1, type1)
+        --return mod2 .. ' ' .. mod1, type2
+        return mod2, type2
+    end
+    do return mod,type end
+end
+
+-- check if it is a typedef
+function classContainer:istypedef (type)
+    local env = self
+    while env do
+        if env.typedefs then
+            local i=1
+            while env.typedefs[i] do
+                if env.typedefs[i].utype == type then
+                    return type
+                end
+                i = i+1
+            end
+        end
+        env = env.parent
+    end
+    return nil
+end
+
+function find_enum_var(var)
+
+    if tonumber(var) then return var end
+
+    local c = classContainer.curr
+    while c do
+        local ns = getnamespace(c)
+        for k,v in pairs(_global_enums) do
+            if match_type(var, v, ns) then
+                return v
+            end
+        end
+        if c.base and c.base ~= '' then
+            c = _global_classes[c:findtype(c.base)]
+        else
+            c = nil
+        end
+    end
+
+    return var
+end
+
+-- check if is a registered type: return full type or nil
+function classContainer:findtype (t)
+
+    t = string.gsub(t, "=.*", "")
+    if _basic[t] then
+     return t
+    end
+
+    local _,_,em = string.find(t, "([&%*])%s*$")
+    t = string.gsub(t, "%s*([&%*])%s*$", "")
+    p = self
+    while p and type(p)=='table' do
+        local st = getnamespace(p)
+
+        for i=_global_types.n,1,-1 do -- in reverse order
+
+            if match_type(t, _global_types[i], st) then
+                return _global_types[i]..(em or "")
+            end
+        end
+        if p.base and p.base ~= '' and p.base ~= t then
+            --print("type is "..t..", p is "..p.base.." self.type is "..self.type.." self.name is "..self.name)
+            p = _global_classes[p:findtype(p.base)]
+        else
+            p = nil
+        end
+    end
+
+    return nil
+end
+
+function append_global_type(t, class)
+    _global_types.n = _global_types.n +1
+    _global_types[_global_types.n] = t
+    _global_types_hash[t] = 1
+    if class then append_class_type(t, class) end
+end
+
+function append_class_type(t,class)
+    if _global_classes[t] then
+        class.flags = _global_classes[t].flags
+        class.lnames = _global_classes[t].lnames
+        if _global_classes[t].base and (_global_classes[t].base ~= '') then
+            class.base = _global_classes[t].base or class.base
+        end
+    end
+    _global_classes[t] = class
+    class.flags = class.flags or {}
+end
+
+function match_type(childtype, regtype, st)
+--print("findtype "..childtype..", "..regtype..", "..st)
+    local b,e = string.find(regtype, childtype, -string.len(childtype), true)
+    if b then
+
+        if e == string.len(regtype) and
+                (b == 1 or (string.sub(regtype, b-1, b-1) == ':' and
+                string.sub(regtype, 1, b-1) == string.sub(st, 1, b-1))) then
+            return true
+        end
+    end
+
+    return false
+end
+
+function findtype_on_childs(self, t)
+
+    local tchild
+    if self.classtype == 'class' or self.classtype == 'namespace' then
+        for k,v in ipairs(self) do
+            if v.classtype == 'class' or v.classtype == 'namespace' then
+                if v.typedefs and v.typedefs[t] then
+                 return v.typedefs[t]
+                elseif v.usertypes and v.usertypes[t] then
+                 return v.usertypes[t]
+                end
+                tchild = findtype_on_childs(v, t)
+                if tchild then return tchild end
+            end
+        end
+    end
+    return nil
+
+end
+
+function classContainer:isenum (type)
+    if global_enums[type] then
+        return type
+    else
+        return false
+    end
+
+    local basetype = gsub(type,"^.*::","")
+    local env = self
+    while env do
+        if env.enums then
+            local i=1
+            while env.enums[i] do
+                if env.enums[i].name == basetype then
+                    return true
+                end
+                i = i+1
+            end
+        end
+        env = env.parent
+    end
+    return false
+end
+
+methodisvirtual = false -- a global
+
+-- parse chunk
+function classContainer:doparse (s)
+    --print ("parse "..s)
+
+    -- try the parser hook
+    do
+        local sub = parser_hook(s)
+        if sub then
+            return sub
+        end
+    end
+
+    -- try the null statement
+    do
+        local b,e,code = string.find(s, "^%s*;")
+        if b then
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try empty verbatim line
+    do
+        local b,e,code = string.find(s, "^%s*$\n")
+        if b then
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try Lua code
+    do
+        local b,e,code = strfind(s,"^%s*(%b\1\2)")
+        if b then
+            Code(strsub(code,2,-2))
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try C code
+    do
+        local b,e,code = strfind(s,"^%s*(%b\3\4)")
+        if b then
+            code = '{'..strsub(code,2,-2)..'\n}\n'
+            Verbatim(code,'r')        -- verbatim code for 'r'egister fragment
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try C code for preamble section
+    do
+        local b,e,code = string.find(s, "^%s*(%b\5\6)")
+        if b then
+            code = string.sub(code, 2, -2).."\n"
+            Verbatim(code, '')
+            return string.sub(s, e+1)
+        end
+    end
+
+    -- try default_property directive
+    do
+        local b,e,ptype = strfind(s, "^%s*TOLUA_PROPERTY_TYPE%s*%(+%s*([^%)%s]*)%s*%)+%s*;?")
+        if b then
+            if not ptype or ptype == "" then
+                ptype = "default"
+            end
+            self:set_property_type(ptype)
+            return strsub(s, e+1)
+        end
+    end
+
+    -- try protected_destructor directive
+    do
+        local b,e = string.find(s, "^%s*TOLUA_PROTECTED_DESTRUCTOR%s*;?")
+        if b then
+            if self.set_protected_destructor then
+                self:set_protected_destructor(true)
+            end
+            return strsub(s, e+1)
+        end
+    end
+
+    -- try 'extern' keyword
+    do
+        local b,e = string.find(s, "^%s*extern%s+")
+        if b then
+            -- do nothing
+            return strsub(s, e+1)
+        end
+    end
+
+    -- try 'virtual' keyworkd
+    do
+        local b,e = string.find(s, "^%s*virtual%s+")
+        if b then
+            methodisvirtual = true
+            return strsub(s, e+1)
+        end
+    end
+
+    -- try labels (public, private, etc)
+    do
+        local b,e = string.find(s, "^%s*%w*%s*:[^:]")
+        if b then
+            return strsub(s, e) -- preserve the [^:]
+        end
+    end
+
+    -- try module
+    do
+        local b,e,name,body = strfind(s,"^%s*module%s%s*([_%w][_%w]*)%s*(%b{})%s*")
+        if b then
+            _curr_code = strsub(s,b,e)
+            Module(name,body)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try namesapce
+    do
+        local b,e,name,body = strfind(s,"^%s*namespace%s%s*([_%w][_%w]*)%s*(%b{})%s*;?")
+        if b then
+            _curr_code = strsub(s,b,e)
+            Namespace(name,body)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try define
+    do
+        local b,e,name = strfind(s,"^%s*#define%s%s*([^%s]*)[^\n]*\n%s*")
+        if b then
+            _curr_code = strsub(s,b,e)
+            Define(name)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try enumerates
+
+    do
+        local b,e,name,body,varname = strfind(s,"^%s*enum%s+(%S*)%s*(%b{})%s*([^%s;]*)%s*;?%s*")
+        if b then
+            --error("#Sorry, declaration of enums and variables on the same statement is not supported.\nDeclare your variable separately (example: '"..name.." "..varname..";')")
+            _curr_code = strsub(s,b,e)
+            Enumerate(name,body,varname)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- do
+    --    local b,e,name,body = strfind(s,"^%s*enum%s+(%S*)%s*(%b{})%s*;?%s*")
+    --    if b then
+    --        _curr_code = strsub(s,b,e)
+    --        Enumerate(name,body)
+    --        return strsub(s,e+1)
+    --    end
+    -- end
+
+    do
+        local b,e,body,name = strfind(s,"^%s*typedef%s+enum[^{]*(%b{})%s*([%w_][^%s]*)%s*;%s*")
+        if b then
+        _curr_code = strsub(s,b,e)
+        Enumerate(name,body)
+        return strsub(s,e+1)
+        end
+    end
+
+    -- try operator
+    do
+        local b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&:<>,]-%s+operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
+        if not b then
+            -- try inline
+            b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&:<>,]-%s+operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)[%s\n]*%b{}%s*;?%s*")
+        end
+        if not b then
+            -- try cast operator
+            b,e,decl,kind,arg,const = strfind(s, "^%s*(operator)%s+([%w_:%d<>%*%&%s]+)%s*(%b())%s*(c?o?n?s?t?)");
+            if b then
+                local _,ie = string.find(s, "^%s*%b{}", e+1)
+                if ie then
+                    e = ie
+                end
+            end
+        end
+        if b then
+            _curr_code = strsub(s,b,e)
+            Operator(decl,kind,arg,const)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try function
+    do
+        --local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
+        local b,e,decl,arg,const,virt = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)%s*(=?%s*0?)%s*;%s*")
+        if not b then
+            -- try function with template
+            b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w]%b<>)%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*")
+        end
+        if not b then
+            -- try a single letter function name
+            b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*;%s*")
+        end
+        if b then
+            if virt and string.find(virt, "[=0]") then
+                if self.flags then
+                    self.flags.pure_virtual = true
+                end
+            end
+            _curr_code = strsub(s,b,e)
+            Function(decl,arg,const)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try inline function
+    do
+        local b,e,decl,arg,const = strfind(s,"^%s*([^%(\n]+)%s*(%b())%s*(c?o?n?s?t?)[^;{]*%b{}%s*;?%s*")
+        --local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&:<>]*[_%w>])%s*(%b())%s*(c?o?n?s?t?)[^;]*%b{}%s*;?%s*")
+        if not b then
+            -- try a single letter function name
+            b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?).-%b{}%s*;?%s*")
+        end
+        if b then
+            _curr_code = strsub(s,b,e)
+            Function(decl,arg,const)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try class
+    do
+        local b,e,name,base,body
+        base = '' body = ''
+        b,e,name = strfind(s,"^%s*class%s*([_%w][_%w@]*)%s*;")  -- dummy class
+        if not b then
+            b,e,name = strfind(s,"^%s*struct%s*([_%w][_%w@]*)%s*;")    -- dummy struct
+            if not b then
+                b,e,name,base,body = strfind(s,"^%s*class%s*([_%w][_%w@]*)%s*(.-)%s*(%b{})%s*;%s*")
+                if not b then
+                    b,e,name,base,body = strfind(s,"^%s*struct%s*([_%w][_%w@]*)%s*(.-)%s*(%b{})%s*;%s*")
+                    if not b then
+                        b,e,name,base,body = strfind(s,"^%s*union%s*([_%w][_%w@]*)%s*(.-)%s*(%b{})%s*;%s*")
+                        if not b then
+                            base = ''
+                            b,e,body,name = strfind(s,"^%s*typedef%s%s*struct%s%s*[_%w]*%s*(%b{})%s*([_%w][_%w@]*)%s*;%s*")
+                        end
+                    end
+                end
+            end
+        end
+        if b then
+            if base ~= '' then
+                base = string.gsub(base, "^%s*:%s*", "")
+                base = string.gsub(base, "%s*public%s*", "")
+                base = split(base, ",")
+                --local b,e
+                --b,e,base = strfind(base,".-([_%w][_%w<>,:]*)$")
+            else
+                base = {}
+            end
+            _curr_code = strsub(s,b,e)
+            Class(name,base,body)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try typedef
+    do
+        local b,e,types = strfind(s,"^%s*typedef%s%s*(.-)%s*;%s*")
+        if b then
+            _curr_code = strsub(s,b,e)
+            Typedef(types)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try variable
+    do
+        local b,e,decl = strfind(s,"^%s*([_%w][_@%s%w%d%*&:<>,]*[_%w%d])%s*;%s*")
+        if b then
+            _curr_code = strsub(s,b,e)
+
+            local list = split_c_tokens(decl, ",")
+            Variable(list[1])
+            if list.n > 1 then
+                local _,_,type = strfind(list[1], "(.-)%s+([^%s]*)$");
+
+                local i =2;
+                while list[i] do
+                    Variable(type.." "..list[i])
+                    i=i+1
+                end
+            end
+            --Variable(decl)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try string
+    do
+        local b,e,decl = strfind(s,"^%s*([_%w]?[_%s%w%d]-char%s+[_@%w%d]*%s*%[%s*%S+%s*%])%s*;%s*")
+        if b then
+            _curr_code = strsub(s,b,e)
+            Variable(decl)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- try array
+    do
+        local b,e,decl = strfind(s,"^%s*([_%w][][_@%s%w%d%*&:]*[]_%w%d])%s*;%s*")
+        if b then
+            _curr_code = strsub(s,b,e)
+            Array(decl)
+            return strsub(s,e+1)
+        end
+    end
+
+    -- no matching
+    if gsub(s,"%s%s*","") ~= "" then
+        _curr_code = s
+        error("#parse error")
+    else
+        return ""
+    end
+
+end
+
+function classContainer:parse (s)
+
+    self.curr_member_access = nil
+
+    while s ~= '' do
+        s = self:doparse(s)
+        methodisvirtual = false
+    end
+end
+
+
+-- property types
+
+function get_property_type()
+
+    return classContainer.curr:get_property_type()
+end
+
+function classContainer:set_property_type(ptype)
+    ptype = string.gsub(ptype, "^%s*", "")
+    ptype = string.gsub(ptype, "%s*$", "")
+
+    self.property_type = ptype
+end
+
+function classContainer:get_property_type()
+    return self.property_type or (self.parent and self.parent:get_property_type()) or "default"
+end
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/custom.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/custom.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/custom.lua	(revision 11817)
@@ -0,0 +1,45 @@
+
+function extract_code(fn,s)
+    local code = ""
+    if fn then
+        code = '\n$#include "'..fn..'"\n'
+    end
+    s= "\n" .. s .. "\n" -- add blank lines as sentinels
+    local _,e,c,t = strfind(s, "\n([^\n]-)SCRIPT_([%w_]*)[^\n]*\n")
+    while e do
+        t = strlower(t)
+        if t == "bind_begin" then
+            _,e,c = strfind(s,"(.-)\n[^\n]*SCRIPT_BIND_END[^\n]*\n",e)
+            if not e then
+             tolua_error("Unbalanced 'SCRIPT_BIND_BEGIN' directive in header file")
+            end
+        end
+        if t == "bind_class" or t == "bind_block" then
+            local b
+            _,e,c,b = string.find(s, "([^{]-)(%b{})", e)
+            c = c..'{\n'..extract_code(nil, b)..'\n};\n'
+        end
+        code = code .. c .. "\n"
+     _,e,c,t = strfind(s, "\n([^\n]-)SCRIPT_([%w_]*)[^\n]*\n",e)
+    end
+    return code
+end
+
+function preprocess_hook(p)
+end
+
+function preparse_hook(p)
+end
+
+function include_file_hook(p, filename)
+    do return end
+--print("FILENAME is "..filename)
+    p.code = string.gsub(p.code, "\n%s*SigC::Signal", "\n\ttolua_readonly SigC::Signal")
+    p.code = string.gsub(p.code, "#ifdef __cplusplus\nextern \"C\" {\n#endif", "")
+    p.code = string.gsub(p.code, "#ifdef __cplusplus\n};?\n#endif", "")
+    p.code = string.gsub(p.code, "DECLSPEC", "")
+    p.code = string.gsub(p.code, "SDLCALL", "")
+    p.code = string.gsub(p.code, "DLLINTERFACE", "")
+    p.code = string.gsub(p.code, "#define[^\n]*_[hH]_?%s*\n", "\n")
+--print("code is "..p.code)
+end
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/custom_hide.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/custom_hide.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/custom_hide.lua	(revision 11817)
@@ -0,0 +1,21 @@
+-- extract code with tolua_hide, and also
+function extract_code(fn,s)
+    local code = '\n$#include "'..fn..'"\n'
+    s= "\n" .. s .. "\n" -- add blank lines as sentinels
+    local _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n")
+    while e do
+        t = strlower(t)
+        if t == "begin" then
+            _,e,c = strfind(s,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n",e)
+            if not e then
+             tolua_error("Unbalanced 'tolua_begin' directive in header file")
+            end
+        end
+        c = c.."\n"
+        c = string.gsub(c, "\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[hH][iI][Dd][eE][^\n]*\n", "\n");
+        c = string.gsub(c, "#define[^%(\n]*%(.-\n", "\n")
+        code = code .. c
+     _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e)
+    end
+    return code
+end
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/declaration.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/declaration.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/declaration.lua	(revision 11817)
@@ -0,0 +1,567 @@
+-- tolua: declaration class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Declaration class
+-- Represents variable, function, or argument declaration.
+-- Stores the following fields:
+--  mod  = type modifiers
+--  type = type
+--  ptr  = "*" or "&", if representing a pointer or a reference
+--  name = name
+--  dim  = dimension, if a vector
+--  def  = default value, if any (only for arguments)
+--  ret  = "*" or "&", if value is to be returned (only for arguments)
+classDeclaration = {
+    mod = '',
+    type = '',
+    ptr = '',
+    name = '',
+    dim = '',
+    ret = '',
+    def = ''
+}
+classDeclaration.__index = classDeclaration
+setmetatable(classDeclaration,classFeature)
+
+-- Create an unique variable name
+function create_varname ()
+    if not _varnumber then _varnumber = 0 end
+    _varnumber = _varnumber + 1
+    return "tolua_var_".._varnumber
+end
+
+-- Check declaration name
+-- It also identifies default values
+function classDeclaration:checkname ()
+
+    if strsub(self.name,1,1) == '[' and not findtype(self.type) then
+        self.name = self.type..self.name
+        local m = split(self.mod,'%s%s*')
+        self.type = m[m.n]
+        self.mod = concat(m,1,m.n-1)
+    end
+
+    local t = split(self.name,'=')
+    if t.n==2 then
+        self.name = t[1]
+        self.def = find_enum_var(t[t.n])
+    end
+
+    local b,e,d = strfind(self.name,"%[(.-)%]")
+    if b then
+        self.name = strsub(self.name,1,b-1)
+        self.dim = find_enum_var(d)
+    end
+
+
+    if self.type ~= '' and self.type ~= 'void' and self.name == '' then
+        self.name = create_varname()
+    elseif self.kind=='var' then
+        if self.type=='' and self.name~='' then
+            self.type = self.type..self.name
+            self.name = create_varname()
+        elseif findtype(self.name) then
+            if self.type=='' then self.type = self.name
+            else self.type = self.type..' '..self.name end
+            self.name = create_varname()
+        end
+    end
+
+    -- adjust type of string
+    if self.type == 'char' and self.dim ~= '' then
+        self.type = 'char*'
+    end
+
+    if self.kind and self.kind == 'var' then
+        self.name = string.gsub(self.name, ":.*$", "") -- ???
+    end
+end
+
+-- Check declaration type
+-- Substitutes typedef's.
+function classDeclaration:checktype ()
+
+    -- check if there is a pointer to basic type
+    local basic = isbasic(self.type)
+    if self.kind == 'func' and basic=='number' and string.find(self.ptr, "%*") then
+        self.type = '_userdata'
+        self.ptr = ""
+    end
+    if basic and self.ptr~='' then
+        self.ret = self.ptr
+        self.ptr = nil
+        if isbasic(self.type) == 'number' then
+            self.return_userdata = true
+        end
+    end
+
+    -- check if there is array to be returned
+    if self.dim~='' and self.ret~='' then
+        error('#invalid parameter: cannot return an array of values')
+    end
+    -- restore 'void*' and 'string*'
+    if self.type == '_userdata' then self.type = 'void*'
+    elseif self.type == '_cstring' then self.type = 'char*'
+    elseif self.type == '_lstate' then self.type = 'lua_State*'
+    end
+
+    -- resolve types inside the templates
+    if self.type then
+        self.type = resolve_template_types(self.type)
+    end
+
+    --
+    -- -- if returning value, automatically set default value
+    -- if self.ret ~= '' and self.def == '' then
+    --  self.def = '0'
+    -- end
+    --
+
+end
+
+function resolve_template_types(type)
+
+    if isbasic(type) then
+        return type
+    end
+    local b,_,m = string.find(type, "(%b<>)")
+    if b then
+
+        m = split_c_tokens(string.sub(m, 2, -2), ",")
+        for i=1, table.getn(m) do
+            m[i] = string.gsub(m[i],"%s*([%*&])", "%1")
+            m[i] = findtype(m[i]) or m[i]
+            m[i] = resolve_template_types(m[i])
+        end
+
+        local b,i
+        type,b,i = break_template(type)
+        local template_part = "<"..string.gsub(concat(m, 1, m.n), " ", ",")..">"
+        type = rebuild_template(type, b, template_part)
+        type = string.gsub(type, ">>", "> >")
+    end
+    return type
+end
+
+function break_template(s)
+    local b,e,timpl = string.find(s, "(%b<>)")
+    if timpl then
+        s = string.gsub(s, "%b<>", "")
+        return s, b, timpl
+    else
+        return s, 0, nil
+    end
+end
+
+function rebuild_template(s, b, timpl)
+
+    if b == 0 then
+        return s
+    end
+
+    return string.sub(s, 1, b-1)..timpl..string.sub(s, b, -1)
+end
+
+-- Print method
+function classDeclaration:print (ident,close)
+    print(ident.."Declaration{")
+    print(ident.." mod  = '"..self.mod.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.." ptr  = '"..self.ptr.."',")
+    print(ident.." name = '"..self.name.."',")
+    print(ident.." dim  = '"..self.dim.."',")
+    print(ident.." def  = '"..self.def.."',")
+    print(ident.." ret  = '"..self.ret.."',")
+    print(ident.."}"..close)
+end
+
+-- check if array of values are returned to Lua
+function classDeclaration:requirecollection (t)
+ if self.mod ~= 'const' and
+        self.dim and self.dim ~= '' and
+                 not isbasic(self.type) and
+                 self.ptr == '' then
+        local type = gsub(self.type,"%s*const%s+","")
+        t[type] = "tolua_collect_" .. clean_template(type)
+        return true
+    end
+    return false
+end
+
+-- declare tag
+function classDeclaration:decltype ()
+
+    self.type = typevar(self.type)
+    if strfind(self.mod,'const') then
+        self.type = 'const '..self.type
+        self.mod = gsub(self.mod,'const%s*','')
+    end
+end
+
+
+-- output type checking
+function classDeclaration:outchecktype (narg)
+    local def
+    local t = isbasic(self.type)
+    if self.def~='' then
+        def = 1
+    else
+        def = 0
+    end
+    if self.dim ~= '' then
+        --if t=='string' then
+        --    return 'tolua_isstringarray(tolua_S,'..narg..','..def..',&tolua_err)'
+        --else
+        return 'tolua_istable(tolua_S,'..narg..',0,&tolua_err)'
+        --end
+    elseif t then
+        return 'tolua_is'..t..'(tolua_S,'..narg..','..def..',&tolua_err)'
+    else
+        return 'tolua_isusertype(tolua_S,'..narg..',"'..self.type..'",'..def..',&tolua_err)'
+    end
+end
+
+function classDeclaration:builddeclaration (narg, cplusplus)
+    local array = self.dim ~= '' and tonumber(self.dim)==nil
+    local line = ""
+    local ptr = ''
+    local mod
+    local type = self.type
+    if self.dim ~= '' then
+        type = gsub(self.type,'const%s+','')  -- eliminates const modifier for arrays
+    end
+    if self.ptr~='' and not isbasic(type) then ptr = '*' end
+    line = concatparam(line," ",self.mod,type,ptr)
+    if array then
+        line = concatparam(line,'*')
+    end
+    line = concatparam(line,self.name)
+    if self.dim ~= '' then
+        if tonumber(self.dim)~=nil then
+            line = concatparam(line,'[',self.dim,'];')
+        else
+            if cplusplus then
+                line = concatparam(line,' = new',type,ptr,'['..self.dim..'];')
+            else
+                line = concatparam(line,' = (',type,ptr,'*)',
+                'malloc((',self.dim,')*sizeof(',type,ptr,'));')
+            end
+        end
+    else
+    local t = isbasic(type)
+    line = concatparam(line,' = ')
+    if t == 'state' then
+        line = concatparam(line, 'tolua_S;')
+    else
+        --print("t is "..tostring(t)..", ptr is "..tostring(self.ptr))
+        if t == 'number' and string.find(self.ptr, "%*") then
+            t = 'userdata'
+        end
+        if not t and ptr=='' then line = concatparam(line,'*') end
+            line = concatparam(line,'((',self.mod,type)
+            if not t then
+                line = concatparam(line,'*')
+            end
+            line = concatparam(line,') ')
+            if isenum(type) then
+                line = concatparam(line,'(int) ')
+            end
+            local def = 0
+            if self.def ~= '' then
+                def = self.def
+                if (ptr == '' or self.ptr == '&') and not t then
+                    def = "(void*)&(const "..type..")"..def
+                end
+            end
+            if t then
+                line = concatparam(line,'tolua_to'..t,'(tolua_S,',narg,',',def,'));')
+            else
+                line = concatparam(line,'tolua_tousertype(tolua_S,',narg,',',def,'));')
+            end
+        end
+    end
+    return line
+end
+
+-- Declare variable
+function classDeclaration:declare (narg)
+    if self.dim ~= '' and tonumber(self.dim)==nil then
+        output('#ifdef __cplusplus\n')
+        output(self:builddeclaration(narg,true))
+        output('#else\n')
+        output(self:builddeclaration(narg,false))
+        output('#endif\n')
+    else
+        output(self:builddeclaration(narg,false))
+    end
+end
+
+-- Get parameter value
+function classDeclaration:getarray (narg)
+    if self.dim ~= '' then
+        local type = gsub(self.type,'const ','')
+        output('  {')
+        output('#ifndef TOLUA_RELEASE\n')
+        local def; if self.def~='' then def=1 else def=0 end
+        local t = isbasic(type)
+        if (t) then
+            output('   if (!tolua_is'..t..'array(tolua_S,',narg,',',self.dim,',',def,',&tolua_err))')
+        else
+            output('   if (!tolua_isusertypearray(tolua_S,',narg,',"',type,'",',self.dim,',',def,',&tolua_err))')
+        end
+        output('    goto tolua_lerror;')
+        output('   else\n')
+        output('#endif\n')
+        output('   {')
+        output('    int i;')
+        output('    for(i=0; i<'..self.dim..';i++)')
+        local t = isbasic(type)
+        local ptr = ''
+        if self.ptr~='' then ptr = '*' end
+        output('   ',self.name..'[i] = ')
+        if not t and ptr=='' then output('*') end
+        output('((',type)
+        if not t then
+            output('*')
+        end
+        output(') ')
+        local def = 0
+        if self.def ~= '' then def = self.def end
+        if t then
+            output('tolua_tofield'..t..'(tolua_S,',narg,',i+1,',def,'));')
+        else
+            output('tolua_tofieldusertype(tolua_S,',narg,',i+1,',def,'));')
+        end
+        output('   }')
+        output('  }')
+    end
+end
+
+-- Get parameter value
+function classDeclaration:setarray (narg)
+    if not strfind(self.type,'const%s+') and self.dim ~= '' then
+        local type = gsub(self.type,'const ','')
+        output('  {')
+        output('   int i;')
+        output('   for(i=0; i<'..self.dim..';i++)')
+        local t,ct = isbasic(type)
+        if t then
+            output('    tolua_pushfield'..t..'(tolua_S,',narg,',i+1,(',ct,')',self.name,'[i]);')
+        else
+            if self.ptr == '' then
+                output('   {')
+                output('#ifdef __cplusplus\n')
+                output('    void* tolua_obj = new',type,'(',self.name,'[i]);')
+                output('    tolua_pushfieldusertype_and_takeownership(tolua_S,',narg,',i+1,tolua_obj,"',type,'");')
+                output('#else\n')
+                output('    void* tolua_obj = tolua_copy(tolua_S,(void*)&',self.name,'[i],sizeof(',type,'));')
+                output('    tolua_pushfieldusertype(tolua_S,',narg,',i+1,tolua_obj,"',type,'");')
+                output('#endif\n')
+                output('   }')
+            else
+                output('   tolua_pushfieldusertype(tolua_S,',narg,',i+1,(void*)',self.name,'[i],"',type,'");')
+            end
+        end
+        output('  }')
+    end
+end
+
+-- Free dynamically allocated array
+function classDeclaration:freearray ()
+    if self.dim ~= '' and tonumber(self.dim)==nil then
+        output('#ifdef __cplusplus\n')
+        output('  delete []',self.name,';')
+        output('#else\n')
+        output('  free(',self.name,');')
+        output('#endif\n')
+    end
+end
+
+-- Pass parameter
+function classDeclaration:passpar ()
+    if self.ptr=='&' and not isbasic(self.type) then
+        output('*'..self.name)
+    elseif self.ret=='*' then
+        output('&'..self.name)
+    else
+        output(self.name)
+    end
+end
+
+-- Return parameter value
+function classDeclaration:retvalue ()
+    if self.ret ~= '' then
+        local t,ct = isbasic(self.type)
+        if t and t~='' then
+            output('   tolua_push'..t..'(tolua_S,(',ct,')'..self.name..');')
+        else
+            output('   tolua_pushusertype(tolua_S,(void*)'..self.name..',"',self.type,'");')
+        end
+        return 1
+    end
+    return 0
+end
+
+-- Internal constructor
+function _Declaration (t)
+
+    setmetatable(t,classDeclaration)
+    t:buildnames()
+    t:checkname()
+    t:checktype()
+    local ft = findtype(t.type) or t.type
+    if not isenum(ft) then
+        t.mod, t.type = applytypedef(t.mod, ft)
+    end
+
+    if t.kind=="var" and (string.find(t.mod, "tolua_property%s") or string.find(t.mod, "tolua_property$")) then
+        t.mod = string.gsub(t.mod, "tolua_property", "tolua_property__"..get_property_type())
+    end
+
+    return t
+end
+
+-- Constructor
+-- Expects the string declaration.
+-- The kind of declaration can be "var" or "func".
+function Declaration (s,kind,is_parameter)
+
+    -- eliminate spaces if default value is provided
+    s = gsub(s,"%s*=%s*","=")
+    s = gsub(s, "%s*<", "<")
+
+    local defb,tmpdef
+    defb,_,tmpdef = string.find(s, "(=.*)$")
+    if defb then
+        s = string.gsub(s, "=.*$", "")
+    else
+        tmpdef = ''
+    end
+    if kind == "var" then
+        -- check the form: void
+        if s == '' or s == 'void' then
+            return _Declaration{type = 'void', kind = kind, is_parameter = is_parameter}
+        end
+    end
+
+    -- check the form: mod type*& name
+    local t = split_c_tokens(s,'%*%s*&')
+    if t.n == 2 then
+        if kind == 'func' then
+            error("#invalid function return type: "..s)
+        end
+        --local m = split(t[1],'%s%s*')
+        local m = split_c_tokens(t[1],'%s+')
+        return _Declaration {
+            name = t[2]..tmpdef,
+            ptr = '*',
+            ret = '&',
+            --type = rebuild_template(m[m.n], tb, timpl),
+            type = m[m.n],
+            mod = concat(m,1,m.n-1),
+            is_parameter = is_parameter,
+            kind = kind
+        }
+    end
+
+    -- check the form: mod type** name
+    t = split_c_tokens(s,'%*%s*%*')
+    if t.n == 2 then
+        if kind == 'func' then
+            error("#invalid function return type: "..s)
+        end
+        --local m = split(t[1],'%s%s*')
+        local m = split_c_tokens(t[1],'%s+')
+        return _Declaration {
+            name = t[2]..tmpdef,
+            ptr = '*',
+            ret = '*',
+            --type = rebuild_template(m[m.n], tb, timpl),
+            type = m[m.n],
+            mod = concat(m,1,m.n-1),
+            is_parameter = is_parameter,
+            kind = kind
+        }
+    end
+
+    -- check the form: mod type& name
+    t = split_c_tokens(s,'&')
+    if t.n == 2 then
+        --local m = split(t[1],'%s%s*')
+        local m = split_c_tokens(t[1],'%s+')
+        return _Declaration {
+            name = t[2]..tmpdef,
+            ptr = '&',
+            --type = rebuild_template(m[m.n], tb, timpl),
+            type = m[m.n],
+            mod = concat(m,1,m.n-1),
+            is_parameter = is_parameter,
+            kind = kind
+        }
+    end
+
+    -- check the form: mod type* name
+    local s1 = gsub(s,"(%b\[\])",function (n) return gsub(n,'%*','\1') end)
+    t = split_c_tokens(s1,'%*')
+    if t.n == 2 then
+        t[2] = gsub(t[2],'\1','%*') -- restore * in dimension expression
+        --local m = split(t[1],'%s%s*')
+        local m = split_c_tokens(t[1],'%s+')
+        return _Declaration {
+            name = t[2]..tmpdef,
+            ptr = '*',
+            type = m[m.n],
+            --type = rebuild_template(m[m.n], tb, timpl),
+            mod = concat(m,1,m.n-1)   ,
+            is_parameter = is_parameter,
+            kind = kind
+        }
+    end
+
+    if kind == 'var' then
+        -- check the form: mod type name
+        --t = split(s,'%s%s*')
+        t = split_c_tokens(s,'%s+')
+        local v
+        if findtype(t[t.n]) then v = create_varname() else v = t[t.n]; t.n = t.n-1 end
+        return _Declaration {
+            name = v..tmpdef,
+            --type = rebuild_template(t[t.n], tb, timpl),
+            type = t[t.n],
+            mod = concat(t,1,t.n-1),
+            is_parameter = is_parameter,
+            kind = kind
+        }
+
+    else -- kind == "func"
+
+        -- check the form: mod type name
+        --t = split(s,'%s%s*')
+        t = split_c_tokens(s,'%s+')
+        local v = t[t.n]  -- last word is the function name
+        local tp,md
+        if t.n>1 then
+            tp = t[t.n-1]
+            md = concat(t,1,t.n-2)
+        end
+        --if tp then tp = rebuild_template(tp, tb, timpl) end
+        return _Declaration {
+            name = v,
+            type = tp,
+            mod = md,
+            is_parameter = is_parameter,
+            kind = kind
+        }
+    end
+
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/define.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/define.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/define.lua	(revision 11817)
@@ -0,0 +1,63 @@
+-- tolua: define class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: define.lua,v 1.2 1999/07/28 22:21:08 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Define class
+-- Represents a numeric const definition
+-- The following filds are stored:
+--   name = constant name
+classDefine = {
+    name = '',
+}
+classDefine.__index = classDefine
+setmetatable(classDefine,classFeature)
+
+-- register define
+function classDefine:register (pre)
+    if not self:check_public_access() then
+        return
+    end
+
+    pre = pre or ''
+    output(pre..'tolua_constant(tolua_S,"'..self.lname..'",'..self.name..');')
+end
+
+-- Print method
+function classDefine:print (ident,close)
+    print(ident.."Define{")
+    print(ident.." name = '"..self.name.."',")
+    print(ident.." lname = '"..self.lname.."',")
+    print(ident.."}"..close)
+end
+
+
+-- Internal constructor
+function _Define (t)
+    setmetatable(t,classDefine)
+    t:buildnames()
+
+    if t.name == '' then
+        error("#invalid define")
+    end
+
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects a string representing the constant name
+function Define (n)
+    return _Define {
+        name = n
+    }
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/doit.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/doit.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/doit.lua	(revision 11817)
@@ -0,0 +1,126 @@
+-- Generate binding code
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- Last update: Apr 2003
+-- $Id: $
+
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+function parse_extra()
+
+    for k,v in ipairs(_extra_parameters or {}) do
+        
+        local b,e,name,value = string.find(v, "^([^=])=(.*)$")
+        if b then
+            _extra_parameters[name] = value
+        else
+            _extra_parameters[v] = true
+        end
+    end
+end
+
+function doit ()
+    -- define package name, if not provided
+    if not flags.n then
+        if flags.f then
+            flags.n = gsub(flags.f,"%..*$","")
+            _,_,flags.n = string.find(flags.n, "([^/\\]*)$")
+        else
+            error("#no package name nor input file provided")
+        end
+    end
+
+    -- parse table with extra paramters
+    parse_extra()
+
+    -- get potential working directory
+    if not flags.w then
+        flags.w = ''
+    end
+
+    -- do this after setting the package name
+    if flags.L then
+        if string.sub(flags.L, 1, 1) == '/' or string.sub(flags.L, 1, 1) == '\\' or (string.len(flags.L) > 1 and string.sub(flags.L, 2, 2) == ':') then
+            dofile(flags.L)
+        else
+            dofile(flags.w..'/'..flags.L)
+        end
+    end
+
+    -- add cppstring
+    if not flags.S then
+        _basic['string'] = 'cppstring'
+        _basic['std::string'] = 'cppstring'
+        _basic_ctype.cppstring = 'const char*'
+    end
+
+    -- proccess package
+    local file
+    if flags.f then
+        if string.sub(flags.f, 1, 1) == '/' or string.sub(flags.f, 1, 1) == '\\' or (string.len(flags.f) > 1 and string.sub(flags.f, 2, 2) == ':') then
+            file = flags.f
+        else
+            file = flags.w..'/'..flags.f
+        end
+    else
+        file = flags.f
+    end
+    local p  = Package(flags.n, file)
+
+    if flags.p then
+        return        -- only parse
+    end
+
+    if flags.o then
+        local file
+        if string.sub(flags.o, 1, 1) == '/' or string.sub(flags.o, 1, 1) == '\\' or (string.len(flags.o) > 1 and string.sub(flags.o, 2, 2) == ':') then
+            file = flags.o
+        else
+            file = flags.w..'/'..flags.o
+        end
+        local st,msg = writeto(file)
+        if not st then
+            error('#'..msg)
+        end
+    end
+
+    p:decltype()
+    if flags.P then
+        p:print()
+    else
+        p:preamble()
+        p:supcode()
+        p:register()
+        push(p)
+        post_output_hook(p)
+        pop()
+    end
+
+    if flags.o then
+        writeto()
+    end
+
+    -- write header file
+    if not flags.P then
+        if flags.H then
+            local file
+            if string.sub(flags.H, 1, 1) == '/' or string.sub(flags.H, 1, 1) == '\\' or (string.len(flags.H) > 1 and string.sub(flags.H, 2, 2) == ':') then
+                file = flags.H
+            else
+                file = flags.w..'/'..flags.H
+            end
+            local st,msg = writeto(file)
+            if not st then
+                error('#'..msg)
+            end
+            p:header()
+            writeto()
+        end
+    end
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/enumerate.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/enumerate.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/enumerate.lua	(revision 11817)
@@ -0,0 +1,95 @@
+-- tolua: enumerate class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: enumerate.lua,v 1.3 2000/01/24 20:41:15 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Enumerate class
+-- Represents enumeration
+-- The following fields are stored:
+--    {i} = list of constant names
+classEnumerate = {
+}
+classEnumerate.__index = classEnumerate
+setmetatable(classEnumerate,classFeature)
+
+-- register enumeration
+function classEnumerate:register (pre)
+    pre = pre or ''
+    local nspace = getnamespace(classContainer.curr)
+    local i=1
+    while self[i] do
+        output(pre..'tolua_constant(tolua_S,"'..self.lnames[i]..'",'..nspace..self[i]..');')
+        i = i+1
+    end
+end
+
+-- Print method
+function classEnumerate:print (ident,close)
+    print(ident.."Enumerate{")
+    print(ident.." name = "..self.name)
+    local i=1
+    while self[i] do
+        print(ident.." '"..self[i].."'("..self.lnames[i].."),")
+        i = i+1
+    end
+    print(ident.."}"..close)
+end
+
+-- Internal constructor
+function _Enumerate (t,varname)
+    setmetatable(t,classEnumerate)
+    append(t)
+    appendenum(t)
+    if varname and varname ~= "" then
+        if t.name ~= "" then
+            Variable(t.name.." "..varname)
+        else
+            local ns = getcurrnamespace()
+            warning("Variable "..ns..varname.." of type <anonymous enum> is declared as read-only")
+            Variable("tolua_readonly int "..varname)
+        end
+    end
+    return t
+end
+
+-- Constructor
+-- Expects a string representing the enumerate body
+function Enumerate (n,b,varname)
+    b = string.gsub(b, ",[%s\n]*}", "\n}") -- eliminate last ','
+    local t = split(strsub(b,2,-2),',') -- eliminate braces
+    local i = 1
+    local e = {n=0}
+    while t[i] do
+        local tt = split(t[i],'=')  -- discard initial value
+        e.n = e.n + 1
+        e[e.n] = tt[1]
+        i = i+1
+    end
+    -- set lua names
+    i  = 1
+    e.lnames = {}
+    local ns = getcurrnamespace()
+    while e[i] do
+        local t = split(e[i],'@')
+        e[i] = t[1]
+        if not t[2] then
+            t[2] = applyrenaming(t[1])
+        end
+        e.lnames[i] = t[2] or t[1]
+        _global_enums[ ns..e[i] ] = (ns..e[i])
+        i = i+1
+    end
+    e.name = n
+    if n ~= "" then
+        Typedef("int "..n)
+    end
+    return _Enumerate(e, varname)
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/feature.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/feature.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/feature.lua	(revision 11817)
@@ -0,0 +1,128 @@
+-- tolua: abstract feature class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Feature class
+-- Represents the base class of all mapped feature.
+classFeature = {
+}
+classFeature.__index = classFeature
+
+-- write support code
+function classFeature:supcode ()
+end
+
+-- output tag
+function classFeature:decltype ()
+end
+
+-- register feature
+function classFeature:register (pre)
+end
+
+-- translate verbatim
+function classFeature:preamble ()
+end
+
+-- check if it is a variable
+function classFeature:isvariable ()
+ return false
+end
+
+-- check if it requires collection
+function classFeature:requirecollection (t)
+    return false
+end
+
+-- build names
+function classFeature:buildnames ()
+    if self.name and self.name~='' then
+        local n = split(self.name,'@')
+        self.name = n[1]
+        if not n[2] then
+            n[2] = applyrenaming(n[1])
+        end
+        self.lname = n[2] or gsub(n[1],"%[.-%]","")
+        self.original_name = self.name
+        self.lname = clean_template(self.lname)
+    end
+    if not self.is_parameter then
+        self.name = getonlynamespace() .. self.name
+    end
+
+    local parent = classContainer.curr
+    if parent then
+        self.access = parent.curr_member_access
+    else
+    end
+end
+
+function classFeature:check_public_access()
+
+    if self.access and self.access ~= 0 then
+        return false
+    end
+
+    local parent = classContainer.curr
+    while parent do
+        if parent.access and parent.access ~= 0 then
+            return false
+        end
+        parent = parent.prox
+    end
+    return true
+end
+
+function clean_template(t)
+
+    return string.gsub(t, "[<>:, %*]", "_")
+end
+
+-- check if feature is inside a container definition
+-- it returns the container class name or nil.
+function classFeature:incontainer (which)
+    if self.parent then
+        local parent = self.parent
+        while parent do
+            if parent.classtype == which then
+                return parent.name
+            end
+            parent = parent.parent
+        end
+    end
+    return nil
+end
+
+function classFeature:inclass ()
+    return self:incontainer('class')
+end
+
+function classFeature:inmodule ()
+    return self:incontainer('module')
+end
+
+function classFeature:innamespace ()
+    return self:incontainer('namespace')
+end
+
+-- return C binding function name based on name
+-- the client specifies a prefix
+function classFeature:cfuncname (n)
+
+    if self.parent then
+        n = self.parent:cfuncname(n)
+    end
+
+    n = string.gsub(n..'_'.. (self.lname or self.name), "[<>:, \.%*&]", "_")
+
+    return n
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/function.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/function.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/function.lua	(revision 11817)
@@ -0,0 +1,737 @@
+-- tolua: function class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: function.lua 1597 2008-03-11 22:25:01Z ice-drezday $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- CEGUILua mod
+-- exception handling
+-- patch from Tov
+-- modded by Lindquist
+exceptionDefs = exceptionDefs or {}
+exceptionDefs["std::exception"]             = {}
+exceptionDefs["std::exception"]["var"]      = "&e"
+exceptionDefs["std::exception"]["c_str"]    = "e.what()"
+
+exceptionDefs["any"]                        = {}
+exceptionDefs["any"]["var"]                 = ""
+exceptionDefs["any"]["c_str"]               = '"Unknown"'
+
+exceptionMessageBufferSize = 512
+
+function outputExceptionError(f,e,errBuf)
+    -- if the exception is not "..." then use the "c_str" info the get a real exception message
+    local messageC_str = true
+    if e.name == "any" then
+        messageC_str = false
+    end
+
+    -- make a default e.ret if empty
+    if not e.ret or e.ret == "" then
+        e.ret = "nil,message"
+    end
+
+    -- create a default exceptionDef if we dont have one
+    if not exceptionDefs[e.name] then
+        exceptionDefs[e.name] = {}
+        exceptionDefs[e.name].var = "&e"
+        exceptionDefs[e.name].c_str = '"Unknown"'
+    end
+
+    -- print catch header
+    local nameToEcho = e.name
+    if nameToEcho == "any" then
+        nameToEcho = "..."
+    end
+    if e.ret == "nil" then
+        output("catch(",nameToEcho," CEGUIDeadException(",exceptionDefs[e.name].var,"))\n{\n")
+    else
+        output("catch(",nameToEcho,exceptionDefs[e.name].var,")\n{\n")
+    end
+
+    -- if just a nil
+    if e.ret == "nil" then
+        output("return 0;\n")
+    -- if error should be raised
+    elseif string.find(e.ret,"error") then
+        if messageC_str then
+            output("snprintf(errorBuffer,"..exceptionMessageBufferSize..",\"Exception of type '"..e.name.."' was thrown by function '"..f.."'\\nMessage: %s\","..exceptionDefs[e.name].c_str..");\n")
+        else
+            output("snprintf(errorBuffer,"..exceptionMessageBufferSize..",\"Unknown exception thrown by function '"..f.."'\");\n")
+        end
+        output("errorDoIt = true;\n")
+    -- else go through the returns
+    else
+        -- buffer for message
+        if string.find(e.ret,"message") and messageC_str and errBuf == false then
+            output("char errorBuffer["..exceptionMessageBufferSize.."];\n")
+        end
+        local numrets = 0
+        local retpat = "(%w+),?"
+        local i,j,retval = string.find(e.ret,retpat)
+        while i do
+            local code = ""
+
+            -- NIL
+            if retval == "nil" then
+                code = "tolua_pushnil(tolua_S);\n"
+
+            -- MESSAGE
+            elseif retval == "message" then
+                if messageC_str then
+                    code = "snprintf(errorBuffer,"..exceptionMessageBufferSize..",\"Exception of type '"..e.name.."' was thrown by function '"..f.."'\\nMessage: %s\","..exceptionDefs[e.name].c_str..");\ntolua_pushstring(tolua_S,errorBuffer);\n"
+                else
+                    code = "tolua_pushstring(tolua_S,\"Unknown exception thrown by function '"..f.."'\");\n"
+                end
+
+            -- TRUE
+            elseif retval == "true" then
+                code = "tolua_pushboolean(tolua_S, 1);\n"
+
+            -- FALSE
+            elseif retval == "false" then
+                code = "tolua_pushboolean(tolua_S, 0);\n"
+            end
+
+            -- print code for this return value
+            if code ~= "" then
+                output(code)
+                numrets = numrets + 1
+            end
+
+            -- next return value
+            i,j,retval = string.find(e.ret,retpat,j+1)
+        end
+        output("return ",numrets,";\n")
+    end
+
+    -- print catch footer
+    output("}\n")
+end
+
+function outputExceptionCatchBlocks(func,throws,err)
+    for i=1,table.getn(throws) do
+        outputExceptionError(func, throws[i], err)
+    end
+
+    -- if an error should be raised, we do it here
+    if err then
+        output("if (errorDoIt) {\n")
+        output("luaL_error(tolua_S,errorBuffer);\n")
+        output("}\n")
+    end
+end
+
+
+-- Function class
+-- Represents a function or a class method.
+-- The following fields are stored:
+--  mod  = type modifiers
+--  type = type
+--  ptr  = "*" or "&", if representing a pointer or a reference
+--  name = name
+--  lname = lua name
+--  args  = list of argument declarations
+--  const = if it is a method receiving a const "this".
+classFunction = {
+    mod = '',
+    type = '',
+    ptr = '',
+    name = '',
+    args = {n=0},
+    const = '',
+}
+classFunction.__index = classFunction
+setmetatable(classFunction,classFeature)
+
+-- declare tags
+function classFunction:decltype ()
+    self.type = typevar(self.type)
+    if strfind(self.mod,'const') then
+        self.type = 'const '..self.type
+        self.mod = gsub(self.mod,'const','')
+    end
+    local i=1
+    while self.args[i] do
+        self.args[i]:decltype()
+        i = i+1
+    end
+end
+
+
+-- Write binding function
+-- Outputs C/C++ binding function.
+function classFunction:supcode (local_constructor)
+
+    local overload = strsub(self.cname,-2,-1) - 1  -- indicate overloaded func
+    local nret = 0      -- number of returned values
+    local class = self:inclass()
+    local _,_,static = strfind(self.mod,'^%s*(static)')
+    if class then
+
+        if self.name == 'new' and self.parent.flags.pure_virtual then
+            -- no constructor for classes with pure virtual methods
+            return
+        end
+
+        if local_constructor then
+           output("/* method: new_local of class ",class," */")
+       else
+           output("/* method:",self.name," of class ",class," */")
+       end
+    else
+        output("/* function:",self.name," */")
+    end
+
+    if local_constructor then
+        output("#ifndef TOLUA_DISABLE_"..self.cname.."_local")
+        output("\nstatic int",self.cname.."_local","(lua_State* tolua_S)")
+    else
+        output("#ifndef TOLUA_DISABLE_"..self.cname)
+        output("\nstatic int",self.cname,"(lua_State* tolua_S)")
+    end
+    output("{")
+
+    -- check types
+    if overload < 0 then
+        output('#ifndef TOLUA_RELEASE\n')
+    end
+    output(' tolua_Error tolua_err;')
+    output(' if (\n')
+    -- check self
+    local narg
+    if class then narg=2 else narg=1 end
+    if class then
+        local func = 'tolua_isusertype'
+        local type = self.parent.type
+        if self.name=='new' or static~=nil then
+            func = 'tolua_isusertable'
+            type = self.parent.type
+        end
+        if self.const ~= '' then
+            type = "const "..type
+        end
+        output('     !'..func..'(tolua_S,1,"'..type..'",0,&tolua_err) ||\n')
+    end
+    -- check args
+    if self.args[1].type ~= 'void' then
+        local i=1
+        while self.args[i] do
+            local btype = isbasic(self.args[i].type)
+            if btype ~= 'value' and btype ~= 'state' then
+                output('     !'..self.args[i]:outchecktype(narg)..' ||\n')
+            end
+            if btype ~= 'state' then
+                narg = narg+1
+            end
+            i = i+1
+        end
+    end
+    -- check end of list
+    output('     !tolua_isnoobj(tolua_S,'..narg..',&tolua_err)\n )')
+    output('  goto tolua_lerror;')
+
+    output(' else\n')
+    if overload < 0 then
+        output('#endif\n')
+    end
+    output(' {')
+
+    -- declare self, if the case
+    local narg
+    if class then narg=2 else narg=1 end
+    if class and self.name~='new' and static==nil then
+        output(' ',self.const,self.parent.type,'*','self = ')
+        output('(',self.const,self.parent.type,'*) ')
+        output('tolua_tousertype(tolua_S,1,0);')
+    elseif static then
+        _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+    end
+    -- declare parameters
+    if self.args[1].type ~= 'void' then
+        local i=1
+        while self.args[i] do
+            self.args[i]:declare(narg)
+            if isbasic(self.args[i].type) ~= "state" then
+                narg = narg+1
+            end
+            i = i+1
+        end
+    end
+
+    -- check self
+    if class and self.name~='new' and static==nil then
+        output('#ifndef TOLUA_RELEASE\n')
+        output('  if (!self) tolua_error(tolua_S,"invalid \'self\' in function \''..self.name..'\'",NULL);');
+        output('#endif\n')
+    end
+
+    -- get array element values
+    if class then narg=2 else narg=1 end
+    if self.args[1].type ~= 'void' then
+        local i=1
+        while self.args[i] do
+            self.args[i]:getarray(narg)
+            narg = narg+1
+            i = i+1
+        end
+    end
+
+    --------------------------------------------------
+    -- CEGUILua mod
+    -- init exception handling
+    local throws = false
+    do
+        local pattern = "tolua_throws|.*|"
+        local i,j = string.find(self.mod, pattern)
+        if i then
+            throws = {}
+            -- ensure table is empty.  Used to be: table.setn(throws,0)
+            for x in pairs(throws) do
+                throws[x] = nil
+            end
+            local excepts = string.sub(self.mod, i+12,j)
+            local epattern = "|.-|"
+            local i,j = string.find(excepts, epattern)
+            while i do
+                local e = string.sub(excepts,i+1,j-1)
+                local _,_,name,rest = string.find(e, "([%w:_]+),?(.*)")
+                table.insert(throws,{name=name, ret=rest})
+                i,j = string.find(excepts, epattern, j)
+            end
+            self.mod = string.gsub(self.mod, pattern, "")
+        end
+    end
+    local exRaiseError = false
+    --------------------------------------------------
+
+    local out = string.find(self.mod, "tolua_outside")
+
+    ---------------
+    -- CEGUILua mod
+    -- remove "tolua_outside" from self.mod
+    if out then
+        self.mod = string.gsub(self.mod, "tolua_outside", "")
+    end
+
+    -- call function
+    if class and self.name=='delete' then
+        output('  delete self;')
+    elseif class and self.name == 'operator&[]' then
+        if flags['1'] then -- for compatibility with tolua5 ?
+            output('  self->operator[](',self.args[1].name,'-1) = ',self.args[2].name,';')
+        else
+            output('  self->operator[](',self.args[1].name,') = ',self.args[2].name,';')
+        end
+    else
+    -- CEGUILua mod begin- throws
+    if throws then
+        for i=1,table.getn(throws) do
+            if string.find(throws[i].ret, "error") then
+                output("char errorBuffer["..exceptionMessageBufferSize.."];\n")
+                output("bool errorDoIt = false;\n")
+                exRaiseError = true
+                break
+            end
+        end
+        output("try\n")
+    end
+    -- CEGUILua mod end - throws
+    output('  {')
+    if self.type ~= '' and self.type ~= 'void' then
+        output('  ',self.mod,self.type,self.ptr,'tolua_ret = ')
+        output('(',self.mod,self.type,self.ptr,') ')
+    else
+        output('  ')
+    end
+    if class and self.name=='new' then
+        output('new',self.type,'(')
+    elseif class and static then
+        if out then
+            output(self.name,'(')
+        else
+            output(class..'::'..self.name,'(')
+        end
+    elseif class then
+        if out then
+            output(self.name,'(')
+        else
+            if self.cast_operator then
+                output('static_cast<',self.mod,self.type,self.ptr,'>(*self')
+            else
+                output('self->'..self.name,'(')
+            end
+        end
+    else
+        output(self.name,'(')
+    end
+
+    if out and not static then
+        output('self')
+        if self.args[1] and self.args[1].name ~= '' then
+            output(',')
+        end
+    end
+    -- write parameters
+    local i=1
+    while self.args[i] do
+        self.args[i]:passpar()
+        i = i+1
+        if self.args[i] then
+            output(',')
+        end
+    end
+
+    if class and self.name == 'operator[]' and flags['1'] then
+        output('-1);')
+    else
+        output(');')
+    end
+
+    -- return values
+    if self.type ~= '' and self.type ~= 'void' then
+        nret = nret + 1
+        local t,ct = isbasic(self.type)
+        if t then
+            if self.cast_operator and _basic_raw_push[t] then
+                output('   ',_basic_raw_push[t],'(tolua_S,(',ct,')tolua_ret);')
+            else
+                output('   tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
+            end
+            else
+                t = self.type
+                new_t = string.gsub(t, "const%s+", "")
+                if self.ptr == '' then
+                    output('   {')
+                    output('#ifdef __cplusplus\n')
+                    output('    void* tolua_obj = new',new_t,'(tolua_ret);')
+                    output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
+                    output('#else\n')
+                    output('    void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
+                    output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
+                    output('#endif\n')
+                    output('   }')
+                elseif self.ptr == '&' then
+                    output('   tolua_pushusertype(tolua_S,(void*)&tolua_ret,"',t,'");')
+                else
+                    if local_constructor then
+                        output('   tolua_pushusertype_and_takeownership(tolua_S,(void *)tolua_ret,"',t,'");')
+                    else
+                        output('   tolua_pushusertype(tolua_S,(void*)tolua_ret,"',t,'");')
+                    end
+                end
+            end
+        end
+        local i=1
+        while self.args[i] do
+            nret = nret + self.args[i]:retvalue()
+            i = i+1
+        end
+        output('  }')
+
+        ------------------------------------------
+        -- CEGUILua mod
+        -- finish exception handling
+        -- catch
+        if throws then
+            outputExceptionCatchBlocks(self.name, throws, exRaiseError)
+        end
+        ------------------------------------------
+
+        -- set array element values
+        if class then narg=2 else narg=1 end
+        if self.args[1].type ~= 'void' then
+            local i=1
+            while self.args[i] do
+                self.args[i]:setarray(narg)
+                narg = narg+1
+                i = i+1
+            end
+        end
+
+        -- free dynamically allocated array
+        if self.args[1].type ~= 'void' then
+            local i=1
+            while self.args[i] do
+                self.args[i]:freearray()
+                i = i+1
+            end
+        end
+    end
+
+    output(' }')
+    output(' return '..nret..';')
+
+    -- call overloaded function or generate error
+    if overload < 0 then
+
+        output('#ifndef TOLUA_RELEASE\n')
+        output('tolua_lerror:\n')
+        output(' tolua_error(tolua_S,"#ferror in function \''..self.lname..'\'.",&tolua_err);')
+        output(' return 0;')
+        output('#endif\n')
+    else
+        local _local = ""
+        if local_constructor then
+            _local = "_local"
+        end
+        output('tolua_lerror:\n')
+        output(' return '..strsub(self.cname,1,-3)..format("%02d",overload).._local..'(tolua_S);')
+    end
+    output('}')
+    output('#endif //#ifndef TOLUA_DISABLE\n')
+    output('\n')
+
+    -- recursive call to write local constructor
+    if class and self.name=='new' and not local_constructor then
+
+        self:supcode(1)
+    end
+
+end
+
+
+-- register function
+function classFunction:register (pre)
+
+    if not self:check_public_access() then
+        return
+    end
+
+    if self.name == 'new' and self.parent.flags.pure_virtual then
+        -- no constructor for classes with pure virtual methods
+        return
+    end
+
+    output(pre..'tolua_function(tolua_S,"'..self.lname..'",'..self.cname..');')
+    if self.name == 'new' then
+        output(pre..'tolua_function(tolua_S,"new_local",'..self.cname..'_local);')
+        output(pre..'tolua_function(tolua_S,".call",'..self.cname..'_local);')
+        --output(' tolua_set_call_event(tolua_S,'..self.cname..'_local, "'..self.parent.type..'");')
+    end
+end
+
+-- Print method
+function classFunction:print (ident,close)
+    print(ident.."Function{")
+    print(ident.." mod  = '"..self.mod.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.." ptr  = '"..self.ptr.."',")
+    print(ident.." name = '"..self.name.."',")
+    print(ident.." lname = '"..self.lname.."',")
+    print(ident.." const = '"..self.const.."',")
+    print(ident.." cname = '"..self.cname.."',")
+    print(ident.." lname = '"..self.lname.."',")
+    print(ident.." args = {")
+    local i=1
+    while self.args[i] do
+        self.args[i]:print(ident.."  ",",")
+        i = i+1
+    end
+    print(ident.." }")
+    print(ident.."}"..close)
+end
+
+-- check if it returns an object by value
+function classFunction:requirecollection (t)
+    local r = false
+    if self.type ~= '' and not isbasic(self.type) and self.ptr=='' then
+        local type = gsub(self.type,"%s*const%s+","")
+        t[type] = "tolua_collect_" .. clean_template(type)
+        r = true
+    end
+    local i=1
+    while self.args[i] do
+        r = self.args[i]:requirecollection(t) or r
+        i = i+1
+    end
+    return r
+end
+
+-- determine lua function name overload
+function classFunction:overload ()
+    return self.parent:overload(self.lname)
+end
+
+
+function param_object(par) -- returns true if the parameter has an object as its default value
+
+    if not string.find(par, '=') then return false end -- it has no default value
+
+    local _,_,def = string.find(par, "=(.*)$")
+
+    if string.find(par, "|") then -- a list of flags
+
+        return true
+    end
+
+    if string.find(par, "%*") then -- it's a pointer with a default value
+
+        if string.find(par, '=%s*new') then -- it's a pointer with an instance as default parameter.. is that valid?
+            return true
+        end
+        return false -- default value is 'NULL' or something
+    end
+
+
+    if string.find(par, "[%(&]") then
+        return true
+    end -- default value is a constructor call (most likely for a const reference)
+
+    --if string.find(par, "&") then
+
+    --    if string.find(def, ":") or string.find(def, "^%s*new%s+") then
+
+    --        -- it's a reference with default to something like Class::member, or 'new Class'
+    --        return true
+    --    end
+    --end
+
+    return false -- ?
+end
+
+function strip_last_arg(all_args, last_arg) -- strips the default value from the last argument
+
+    local _,_,s_arg = string.find(last_arg, "^([^=]+)")
+    last_arg = string.gsub(last_arg, "([%%%(%)])", "%%%1");
+    all_args = string.gsub(all_args, "%s*,%s*"..last_arg.."%s*%)%s*$", ")")
+    return all_args, s_arg
+end
+
+
+
+-- Internal constructor
+function _Function (t)
+    setmetatable(t,classFunction)
+
+    if t.const ~= 'const' and t.const ~= '' then
+        error("#invalid 'const' specification")
+    end
+
+    append(t)
+    if t:inclass() then
+        --print ('t.name is '..t.name..', parent.name is '..t.parent.name)
+        if string.gsub(t.name, "%b<>", "") == string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
+            t.name = 'new'
+            t.lname = 'new'
+            t.parent._new = true
+            t.type = t.parent.name
+            t.ptr = '*'
+        elseif string.gsub(t.name, "%b<>", "") == '~'..string.gsub(t.parent.original_name or t.parent.name, "%b<>", "") then
+            t.name = 'delete'
+            t.lname = 'delete'
+            t.parent._delete = true
+        end
+    end
+    t.cname = t:cfuncname("tolua")..t:overload(t)
+    return t
+end
+
+-- Constructor
+-- Expects three strings: one representing the function declaration,
+-- another representing the argument list, and the third representing
+-- the "const" or empty string.
+function Function (d,a,c)
+    --local t = split(strsub(a,2,-2),',') -- eliminate braces
+    --local t = split_params(strsub(a,2,-2))
+
+    if not flags['W'] and string.find(a, "%.%.%.%s*%)") then
+
+        warning("Functions with variable arguments (`...') are not supported. Ignoring "..d..a..c)
+        return nil
+    end
+
+
+    local i=1
+    local l = {n=0}
+
+    a = string.gsub(a, "%s*([%(%)])%s*", "%1")
+    local t,strip,last = strip_pars(strsub(a,2,-2));
+    if strip then
+        --local ns = string.sub(strsub(a,1,-2), 1, -(string.len(last)+1))
+        local ns = join(t, ",", 1, last-1)
+
+        ns = "("..string.gsub(ns, "%s*,%s*$", "")..')'
+        --ns = strip_defaults(ns)
+
+        Function(d, ns, c)
+        for i=1,last do
+            t[i] = string.gsub(t[i], "=.*$", "")
+        end
+    end
+
+    while t[i] do
+        l.n = l.n+1
+        l[l.n] = Declaration(t[i],'var',true)
+        i = i+1
+    end
+    local f = Declaration(d,'func')
+    f.args = l
+    f.const = c
+    return _Function(f)
+end
+
+function join(t, sep, first, last)
+
+    first = first or 1
+    last = last or table.getn(t)
+    local lsep = ""
+    local ret = ""
+    local loop = false
+    for i = first,last do
+
+        ret = ret..lsep..t[i]
+        lsep = sep
+        loop = true
+    end
+    if not loop then
+        return ""
+    end
+
+    return ret
+end
+
+function strip_pars(s)
+
+    local t = split_c_tokens(s, ',')
+    local strip = false
+    local last
+
+    for i=t.n,1,-1 do
+
+        if not strip and param_object(t[i]) then
+            last = i
+            strip = true
+        end
+        --if strip then
+        --    t[i] = string.gsub(t[i], "=.*$", "")
+        --end
+    end
+
+    return t,strip,last
+
+end
+
+function strip_defaults(s)
+
+    s = string.gsub(s, "^%(", "")
+    s = string.gsub(s, "%)$", "")
+
+    local t = split_c_tokens(s, ",")
+    local sep, ret = "",""
+    for i=1,t.n do
+        t[i] = string.gsub(t[i], "=.*$", "")
+        ret = ret..sep..t[i]
+        sep = ","
+    end
+
+    return "("..ret..")"
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/module.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/module.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/module.lua	(revision 11817)
@@ -0,0 +1,68 @@
+-- tolua: module class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Module class
+-- Represents module.
+-- The following fields are stored:
+--    {i} = list of objects in the module.
+classModule = {
+    classtype = 'module'
+}
+classModule.__index = classModule
+setmetatable(classModule,classContainer)
+
+-- register module
+function classModule:register (pre)
+    pre = pre or ''
+    push(self)
+    output(pre..'tolua_module(tolua_S,"'..self.name..'",',self:hasvar(),');')
+    output(pre..'tolua_beginmodule(tolua_S,"'..self.name..'");')
+    local i=1
+    while self[i] do
+        self[i]:register(pre..' ')
+        i = i+1
+    end
+    output(pre..'tolua_endmodule(tolua_S);')
+    pop()
+end
+
+-- Print method
+function classModule:print (ident,close)
+    print(ident.."Module{")
+    print(ident.." name = '"..self.name.."';")
+    local i=1
+    while self[i] do
+        self[i]:print(ident.." ",",")
+        i = i+1
+    end
+    print(ident.."}"..close)
+end
+
+-- Internal constructor
+function _Module (t)
+    setmetatable(t,classModule)
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects two string representing the module name and body.
+function Module (n,b)
+    local t = _Module(_Container{name=n})
+    push(t)
+    t:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
+    pop()
+    return t
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/namespace.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/namespace.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/namespace.lua	(revision 11817)
@@ -0,0 +1,52 @@
+-- tolua: namespace class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 2003
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Namespace class
+-- Represents a namesapce definition.
+-- Stores the following fields:
+--    name = class name
+--    {i}  = list of members
+classNamespace = {
+    classtype = 'namespace',
+    name = '',
+}
+classNamespace.__index = classNamespace
+setmetatable(classNamespace,classModule)
+
+-- Print method
+function classNamespace:print (ident,close)
+    print(ident.."Namespace{")
+    print(ident.." name = '"..self.name.."',")
+    local i=1
+    while self[i] do
+        self[i]:print(ident.." ",",")
+        i = i+1
+    end
+    print(ident.."}"..close)
+end
+
+-- Internal constructor
+function _Namespace (t)
+    setmetatable(t,classNamespace)
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects the name and the body of the namespace.
+function Namespace (n,b)
+    local c = _Namespace(_Container{name=n})
+    push(c)
+    c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces
+    pop()
+end
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/operator.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/operator.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/operator.lua	(revision 11817)
@@ -0,0 +1,215 @@
+-- tolua: operator class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Operator class
+-- Represents an operator function or a class operator method.
+-- It stores the same fields as functions do plus:
+--  kind = set of character representing the operator (as it appers in C++ code)
+classOperator = {
+    kind = '',
+}
+classOperator.__index = classOperator
+setmetatable(classOperator,classFunction)
+
+-- table to transform operator kind into the appropriate tag method name
+_TM = {
+    ['+'] = 'add',
+    ['-'] = 'sub',
+    ['*'] = 'mul',
+    ['/'] = 'div',
+    ['<'] = 'lt',
+    ['<='] = 'le',
+    ['=='] = 'eq',
+    ['[]'] = 'geti',
+    ['&[]'] = 'seti',
+    --['->'] = 'flechita',
+}
+
+
+-- Print method
+function classOperator:print (ident,close)
+    print(ident.."Operator{")
+    print(ident.." kind  = '"..self.kind.."',")
+    print(ident.." mod  = '"..self.mod.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.." ptr  = '"..self.ptr.."',")
+    print(ident.." name = '"..self.name.."',")
+    print(ident.." const = '"..self.const.."',")
+    print(ident.." cname = '"..self.cname.."',")
+    print(ident.." lname = '"..self.lname.."',")
+    print(ident.." args = {")
+    local i=1
+    while self.args[i] do
+        self.args[i]:print(ident.."  ",",")
+        i = i+1
+    end
+    print(ident.." }")
+    print(ident.."}"..close)
+end
+
+function classOperator:supcode_tmp()
+
+    if not _TM[self.kind] then
+        return classFunction.supcode(self)
+    end
+
+    -- no overload, no parameters, always inclass
+    output("/* method:",self.name," of class ",self:inclass()," */")
+
+    output("#ifndef TOLUA_DISABLE_"..self.cname)
+    output("\nstatic int",self.cname,"(lua_State* tolua_S)")
+
+    if overload < 0 then
+        output('#ifndef TOLUA_RELEASE\n')
+    end
+    output(' tolua_Error tolua_err;')
+    output(' if (\n')
+    -- check self
+    output('     !'..'tolua_isusertype(tolua_S,1,"'..self.parent.type..'",0,&tolua_err) ||\n')
+    output('     !tolua_isnoobj(tolua_S,2,&tolua_err)\n )')
+    output('  goto tolua_lerror;')
+
+    output(' else\n')
+    output('#endif\n') -- tolua_release
+    output(' {')
+
+    -- declare self
+    output(' ',self.const,self.parent.type,'*','self = ')
+    output('(',self.const,self.parent.type,'*) ')
+    output('tolua_tousertype(tolua_S,1,0);')
+
+    -- check self
+    output('#ifndef TOLUA_RELEASE\n')
+    output('  if (!self) tolua_error(tolua_S,"invalid \'self\' in function \''..self.name..'\'",NULL);');
+    output('#endif\n')
+
+    -- cast self
+    output('  ',self.mod,self.type,self.ptr,'tolua_ret = ')
+    output('(',self.mod,self.type,self.ptr,')(*self);')
+
+    -- return value
+    local t,ct = isbasic(self.type)
+    if t then
+        output('   tolua_push'..t..'(tolua_S,(',ct,')tolua_ret);')
+    else
+        t = self.type
+        new_t = string.gsub(t, "const%s+", "")
+        if self.ptr == '' then
+            output('   {')
+            output('#ifdef __cplusplus\n')
+            output('    void* tolua_obj = new',new_t,'(tolua_ret);')
+            output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
+            output('#else\n')
+            output('    void* tolua_obj = tolua_copy(tolua_S,(void*)&tolua_ret,sizeof(',t,'));')
+            output('    tolua_pushusertype_and_takeownership(tolua_S,tolua_obj,"',t,'");')
+            output('#endif\n')
+            output('   }')
+        elseif self.ptr == '&' then
+            output('   tolua_pushusertype(tolua_S,(void*)&tolua_ret,"',t,'");')
+        else
+            if local_constructor then
+                output('   tolua_pushusertype_and_takeownership(tolua_S,(void *)tolua_ret,"',t,'");')
+            else
+                output('   tolua_pushusertype(tolua_S,(void*)tolua_ret,"',t,'");')
+            end
+        end
+    end
+
+    output('  }')
+    output(' return 1;')
+
+    output('#ifndef TOLUA_RELEASE\n')
+    output('tolua_lerror:\n')
+    output(' tolua_error(tolua_S,"#ferror in function \''..self.lname..'\'.",&tolua_err);')
+    output(' return 0;')
+    output('#endif\n')
+
+
+    output('}')
+    output('#endif //#ifndef TOLUA_DISABLE\n')
+    output('\n')
+end
+
+-- Internal constructor
+function _Operator (t)
+    setmetatable(t,classOperator)
+
+    if t.const ~= 'const' and t.const ~= '' then
+        error("#invalid 'const' specification")
+    end
+
+    append(t)
+    if not t:inclass() then
+        error("#operator can only be defined as class member")
+    end
+
+    --t.name = t.name .. "_" .. (_TM[t.kind] or t.kind)
+    t.cname = t:cfuncname("tolua")..t:overload(t)
+    t.name = "operator" .. t.kind  -- set appropriate calling name
+    return t
+end
+
+-- Constructor
+function Operator (d,k,a,c)
+
+    local op_k = string.gsub(k, "^%s*", "")
+    op_k = string.gsub(k, "%s*$", "")
+    --if string.find(k, "^[%w_:%d<>%*%&]+$") then
+    if d == "operator" and k ~= '' then
+
+        d = k.." operator"
+    elseif not _TM[op_k] then
+
+        if flags['W'] then
+            error("tolua: no support for operator" .. f.kind)
+        else
+            warning("No support for operator "..op_k..", ignoring")
+            return nil
+        end
+    end
+
+    local ref = ''
+    local t = split_c_tokens(strsub(a,2,strlen(a)-1),',') -- eliminate braces
+    local i=1
+    local l = {n=0}
+    while t[i] do
+        l.n = l.n+1
+        l[l.n] = Declaration(t[i],'var')
+        i = i+1
+    end
+    if k == '[]' then
+        local _
+        _, _, ref = strfind(d,'(&)')
+        d = gsub(d,'&','')
+    elseif k=='&[]' then
+        l.n = l.n+1
+        l[l.n] = Declaration(d,'var')
+        l[l.n].name = 'tolua_value'
+    end
+    local f = Declaration(d,'func')
+    if k == '[]' and (l[1]==nil or isbasic(l[1].type)~='number') then
+        error('operator[] can only be defined for numeric index.')
+    end
+    f.args = l
+    f.const = c
+    f.kind = op_k
+    f.lname = "."..(_TM[f.kind] or f.kind)
+    if not _TM[f.kind] then
+        f.cast_operator = true
+    end
+    if f.kind == '[]' and ref=='&' and f.const~='const' then
+        Operator(d,'&'..k,a,c)     -- create correspoding set operator
+    end
+    return _Operator(f)
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/package.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/package.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/package.lua	(revision 11817)
@@ -0,0 +1,343 @@
+-- tolua: package class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Package class
+-- Represents the whole package being bound.
+-- The following fields are stored:
+--    {i} = list of objects in the package.
+classPackage = {
+    classtype = 'package'
+}
+classPackage.__index = classPackage
+setmetatable(classPackage,classContainer)
+
+-- Print method
+function classPackage:print ()
+    print("Package: "..self.name)
+    local i=1
+    while self[i] do
+        self[i]:print("","")
+        i = i+1
+    end
+end
+
+function classPackage:preprocess ()
+
+    -- avoid preprocessing embedded Lua code
+    local L = {}
+    self.code = gsub(self.code,"\n%s*%$%[","\1") -- deal with embedded lua code
+    self.code = gsub(self.code,"\n%s*%$%]","\2")
+    self.code = gsub(self.code,"(%b\1\2)", function (c)
+                                               tinsert(L,c)
+                                               return "\n#["..getn(L).."]#"
+                                           end
+    )
+    -- avoid preprocessing embedded C code
+    local C = {}
+    self.code = gsub(self.code,"\n%s*%$%<","\3") -- deal with embedded C code
+    self.code = gsub(self.code,"\n%s*%$%>","\4")
+    self.code = gsub(self.code,"(%b\3\4)", function (c)
+                                               tinsert(C,c)
+                                               return "\n#<"..getn(C)..">#"
+                                           end
+    )
+    -- avoid preprocessing embedded C code
+    self.code = gsub(self.code,"\n%s*%$%{","\5") -- deal with embedded C code
+    self.code = gsub(self.code,"\n%s*%$%}","\6")
+    self.code = gsub(self.code,"(%b\5\6)", function (c)
+                                               tinsert(C,c)
+                                               return "\n#<"..getn(C)..">#"
+                                           end
+    )
+
+    --self.code = gsub(self.code,"\n%s*#[^d][^\n]*\n", "\n\n") -- eliminate preprocessor directives that don't start with 'd'
+    self.code = gsub(self.code,"\n[ \t]*#[ \t]*[^d%<%[]", "\n//") -- eliminate preprocessor directives that don't start with 'd'
+
+    -- avoid preprocessing verbatim lines
+    local V = {}
+    self.code = gsub(self.code,"\n(%s*%$[^%[%]][^\n]*)", function (v)
+                                                             tinsert(V,v)
+                                                             return "\n#"..getn(V).."#"
+                                                         end
+    )
+
+    -- perform global substitution
+
+    self.code = gsub(self.code,"(//[^\n]*)","")     -- eliminate C++ comments
+    self.code = gsub(self.code,"/%*","\1")
+    self.code = gsub(self.code,"%*/","\2")
+    self.code = gsub(self.code,"%b\1\2","")
+    self.code = gsub(self.code,"\1","/%*")
+    self.code = gsub(self.code,"\2","%*/")
+    self.code = gsub(self.code,"%s*@%s*","@") -- eliminate spaces beside @
+    self.code = gsub(self.code,"%s?inline(%s)","%1") -- eliminate 'inline' keyword
+    self.code = gsub(self.code,"%)%s?override;",");") -- eliminate 'override' keyword... at least most of the times
+    --self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword
+    --self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword
+    --self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword
+    self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
+    self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
+    self.code = gsub(self.code,"([^%w_])char%s*%*","%1_cstring ")  -- substitute 'char*'
+    self.code = gsub(self.code,"([^%w_])lua_State%s*%*","%1_lstate ")  -- substitute 'lua_State*'
+
+    -- restore embedded Lua code
+    self.code = gsub(self.code,"%#%[(%d+)%]%#", function (n)
+                                                    return L[tonumber(n)]
+                                                end
+    )
+    -- restore embedded C code
+    self.code = gsub(self.code,"%#%<(%d+)%>%#", function (n)
+                                                    return C[tonumber(n)]
+                                                end
+    )
+    -- restore verbatim lines
+    self.code = gsub(self.code,"%#(%d+)%#", function (n)
+                                                return V[tonumber(n)]
+                                            end
+    )
+
+    self.code = string.gsub(self.code, "\n%s*%$([^\n]+)", function (l)
+                                                              Verbatim(l.."\n")
+                                                              return "\n"
+                                                          end
+    )
+end
+
+-- translate verbatim
+function classPackage:preamble ()
+    output('/*\n')
+    output('** Lua binding: '..self.name..'\n')
+    output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
+    output('*/\n\n')
+
+    output('#ifndef __cplusplus\n')
+    output('#include <stdlib.h>\n')
+    output('#endif\n')
+    output('#include <string.h>\n\n')
+    output('#include <tolua++.h>\n\n')
+
+    if flags.H then
+        output('#include "'..flags.H..'"\n')
+    end
+
+    local i=1
+    while self[i] do
+        self[i]:preamble()
+        i = i+1
+    end
+
+    post_include_hook(self.name)
+
+    output('\n')
+    output('#ifdef ORXONOX_RELEASE\n')
+    output('#  define TOLUA_RELEASE\n')
+    output('#endif\n')
+
+    if self:requirecollection(_collect) then
+        output('\n')
+        output('/* function to release collected object via destructor */')
+        output('#ifdef __cplusplus\n')
+        for i,v in pairs(_collect) do
+            output('\nstatic int '..v..' (lua_State* tolua_S)')
+            output('{')
+            output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);')
+            output('    delete self;')
+            output('    return 0;')
+            output('}')
+        end
+        output('#endif\n\n')
+    end
+
+    output('\n')
+    output('/* function to register type */')
+    output('static void tolua_reg_types (lua_State* tolua_S)')
+    output('{')
+    foreach(_usertype,function(n,v) output(' tolua_usertype(tolua_S,"',v,'");') end)
+    if flags.t then
+        output("#ifndef Mtolua_typeid\n#define Mtolua_typeid(L,TI,T)\n#endif\n")
+        foreach(_usertype,function(n,v) output(' Mtolua_typeid(tolua_S,typeid(',v,'), "',v,'");') end)
+    end
+    output('}')
+    output('\n')
+end
+
+-- register package
+-- write package open function
+function classPackage:register (pre)
+    pre = pre or ''
+    push(self)
+    output(pre.."/* Open function */")
+    output(pre.."int tolua_"..self.name.."_open (lua_State* tolua_S)")
+    output(pre.."{")
+    output(pre.." tolua_open(tolua_S);")
+    output(pre.." tolua_reg_types(tolua_S);")
+    output(pre.." tolua_module(tolua_S,NULL,",self:hasvar(),");")
+    output(pre.." tolua_beginmodule(tolua_S,NULL);")
+    local i=1
+    while self[i] do
+        self[i]:register(pre.."  ")
+        i = i+1
+    end
+    output(pre.." tolua_endmodule(tolua_S);")
+    output(pre.." return 1;")
+    output(pre.."}")
+
+    output("\n\n")
+    output("#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501\n");
+    output(pre.."int luaopen_"..self.name.." (lua_State* tolua_S) {")
+    output(pre.." return tolua_"..self.name.."_open(tolua_S);")
+    output(pre.."};")
+    output("#endif\n\n")
+
+    pop()
+end
+
+-- write header file
+function classPackage:header ()
+    output('/*\n') output('** Lua binding: '..self.name..'\n')
+    output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
+    output('*/\n\n')
+
+    if flags.H then
+        output('#include "'..flags.w..'/'..self.name..'Prereqs.h"\n')
+        output('/* Exported function */')
+        output('_'..self.name..'Export')
+        output('int  tolua_'..self.name..'_open (lua_State* tolua_S);')
+        output('\n')
+    end
+end
+
+-- Internal constructor
+function _Package (self)
+    setmetatable(self,classPackage)
+    return self
+end
+
+-- Parse C header file with tolua directives
+-- *** Thanks to Ariel Manzur for fixing bugs in nested directives ***
+function extract_code(fn,s)
+    local code = '\n$#include "'..flags.w..'/'..fn..'"\n'
+    s= "\n" .. s .. "\n" -- add blank lines as sentinels
+
+    -- eliminate export macro problems in class declarations
+    s = gsub(s, ' _%w*Export ', ' ')
+
+    local _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n")
+    while e do
+        t = strlower(t)
+        if t == "begin" then
+            _,e,c = strfind(s,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n",e)
+            if not e then
+             tolua_error("Unbalanced 'tolua_begin' directive in header file")
+            end
+        end
+        code = code .. c .. "\n"
+        _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e)
+    end
+    return code
+end
+
+-- Constructor
+-- Expects the package name, the file extension, and the file text.
+function Package (name,fn)
+    local ext = "pkg"
+
+    -- open input file, if any
+    if fn then
+        local file
+        if flags.f then
+            if string.sub(flags.f, 1, 1) == '/' or string.sub(flags.f, 1, 1) == '\\' or (string.len(flags.f) > 1 and string.sub(flags.f, 2, 2) == ':') then
+                file = flags.f
+            else
+                file = flags.w..'/'..flags.f
+            end
+        else
+            file = flags.f
+        end
+        local st, msg = readfrom(file)
+        if not st then
+            error('#'..msg..' path: '..flags.f)
+        end
+        local _; _, _, ext = strfind(fn,".*%.(.*)$")
+    end
+    local code = "\n" .. read('*a')
+    if ext == 'h' or ext == 'hpp' then
+        code = extract_code(fn,code)
+    end
+
+    -- close file
+    if fn then
+        readfrom()
+    end
+
+    -- prepare working directory
+    local current_path
+    if not flags.w and flags.f then
+        current_path = gsub(flags.f, '(/)[^/]*%.?[^/]*$', '%1')
+    elseif flags.w then
+        if not (string.sub(flags.w, string.len(flags.w)) == '/') then
+            current_path = flags.w..'/'
+        else
+            current_path = flags.w
+        end
+    else
+        current_path = ''
+    end
+
+    -- deal with include directive
+    local nsubst
+    repeat
+        code,nsubst = gsub(code,'\n%s*%$(.)file%s*"(.-)"([^\n]*)\n',
+            function (kind,fn,extra)
+                local _, _, ext = strfind(fn,".*%.(.*)$")
+                local fp,msg = openfile(current_path..fn,'r')
+                if not fp then
+                    error('#'..msg..': '..fn)
+                end
+                local s = read(fp,'*a')
+                closefile(fp)
+                if kind == 'c' or kind == 'h' then
+                    return extract_code(fn,s)
+                elseif kind == 'p' then
+                    return "\n\n" .. s
+                elseif kind == 'l' then
+                    return "\n$[--##"..fn.."\n" .. s .. "\n$]\n"
+                elseif kind == 'i' then
+                    local t = {code=s}
+                    extra = string.gsub(extra, "^%s*,%s*", "")
+                    local pars = split_c_tokens(extra, ",")
+                    include_file_hook(t, fn, unpack(pars))
+                    return "\n\n" .. t.code
+                else
+                    error('#Invalid include directive (use $cfile, $pfile, $lfile or $ifile)')
+                end
+            end
+        )
+    until nsubst==0
+
+    -- deal with renaming directive
+    repeat -- I don't know why this is necesary
+        code,nsubst = gsub(code,'\n%s*%$renaming%s*(.-)%s*\n', function (r) appendrenaming(r) return "\n" end)
+    until nsubst == 0
+
+    local t = _Package(_Container{name=name, code=code})
+    push(t)
+    preprocess_hook(t)
+    t:preprocess()
+    preparse_hook(t)
+    t:parse(t.code)
+    pop()
+    return t
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/typedef.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/typedef.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/typedef.lua	(revision 11817)
@@ -0,0 +1,71 @@
+-- tolua: typedef class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Typedef class
+-- Represents a type synonym.
+-- The 'de facto' type replaces the typedef before the
+-- remaining code is parsed.
+-- The following fields are stored:
+--   utype = typedef name
+--   type = 'the facto' type
+--   mod = modifiers to the 'de facto' type
+classTypedef = {
+    utype = '',
+    mod = '',
+    type = ''
+}
+classTypedef.__index = classTypedef
+
+-- Print method
+function classTypedef:print (ident,close)
+    print(ident.."Typedef{")
+    print(ident.." utype = '"..self.utype.."',")
+    print(ident.." mod = '"..self.mod.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.."}"..close)
+end
+
+-- Return it's not a variable
+function classTypedef:isvariable ()
+    return false
+end
+
+-- Internal constructor
+function _Typedef (t)
+    setmetatable(t,classTypedef)
+    t.type = resolve_template_types(t.type)
+    appendtypedef(t)
+    return t
+end
+
+-- Constructor
+-- Expects one string representing the type definition.
+function Typedef (s)
+    if strfind(string.gsub(s, '%b<>', ''),'[%*&]') then
+        tolua_error("#invalid typedef: pointers (and references) are not supported")
+    end
+    local o = {mod = ''}
+    if string.find(s, "[<>]") then
+        _,_,o.type,o.utype = string.find(s, "^%s*([^<>]+%b<>[^%s]*)%s+(.-)$")
+    else
+        local t = split(gsub(s,"%s%s*"," ")," ")
+        o = {
+            utype = t[t.n],
+            type = t[t.n-1],
+            mod = concat(t,1,t.n-2),
+        }
+    end
+    return _Typedef(o)
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/variable.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/variable.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/variable.lua	(revision 11817)
@@ -0,0 +1,295 @@
+-- tolua: variable class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+-- Variable class
+-- Represents a extern variable or a public member of a class.
+-- Stores all fields present in a declaration.
+classVariable = {
+    _get = {},   -- mapped get functions
+    _set = {},   -- mapped set functions
+}
+classVariable.__index = classVariable
+setmetatable(classVariable,classDeclaration)
+
+-- Print method
+function classVariable:print (ident,close)
+    print(ident.."Variable{")
+    print(ident.." mod  = '"..self.mod.."',")
+    print(ident.." type = '"..self.type.."',")
+    print(ident.." ptr  = '"..self.ptr.."',")
+    print(ident.." name = '"..self.name.."',")
+    if self.dim then print(ident.." dim = '"..self.dim.."',") end
+    print(ident.." def  = '"..self.def.."',")
+    print(ident.." ret  = '"..self.ret.."',")
+    print(ident.."}"..close)
+end
+
+-- Generates C function name
+function classVariable:cfuncname (prefix)
+    local parent = ""
+    local unsigned = ""
+    local ptr = ""
+
+    local p = self:inmodule() or self:innamespace() or self:inclass()
+
+    if p then
+        if self.parent.classtype == 'class' then
+            parent = "_" .. self.parent.type
+        else
+            parent = "_" .. p
+        end
+    end
+
+    if strfind(self.mod,"(unsigned)") then
+        unsigned = "_unsigned"
+    end
+
+    if self.ptr == "*" then ptr = "_ptr"
+    elseif self.ptr == "&" then ptr = "_ref"
+    end
+
+    local name =  prefix .. parent .. unsigned .. "_" .. gsub(self.lname or self.name,".*::","") .. ptr
+
+    name = clean_template(name)
+    return name
+
+end
+
+-- check if it is a variable
+function classVariable:isvariable ()
+    return true
+end
+
+-- get variable value
+function classVariable:getvalue (class,static, prop_get)
+
+    local name
+    if prop_get then
+
+        name = prop_get.."()"
+    else
+        name = self.name
+    end
+
+    if class and static then
+        return self.parent.type..'::'..name
+    elseif class then
+        return 'self->'..name
+    else
+        return name
+    end
+end
+
+-- get variable pointer value
+function classVariable:getpointervalue (class,static)
+    if class and static then
+        return class..'::p'
+    elseif class then
+        return 'self->p'
+    else
+        return 'p'
+    end
+end
+
+-- Write binding functions
+function classVariable:supcode ()
+
+ local class = self:inclass()
+
+    local prop_get,prop_set
+    if string.find(self.mod, 'tolua_property') then
+
+        _,_,type = string.find(self.mod, "tolua_property__([^%s]*)")
+        type = type or "default"
+        prop_get,prop_set = get_property_methods(type, self.name)
+        self.mod = string.gsub(self.mod, "tolua_property[^%s]*", "")
+    end
+
+    -- get function ------------------------------------------------
+    if class then
+        output("/* get function:",self.name," of class ",class," */")
+    else
+        output("/* get function:",self.name," */")
+    end
+    self.cgetname = self:cfuncname("tolua_get")
+    output("#ifndef TOLUA_DISABLE_"..self.cgetname)
+    output("\nstatic int",self.cgetname,"(lua_State* tolua_S)")
+    output("{")
+
+    -- declare self, if the case
+    local _,_,static = strfind(self.mod,'^%s*(static)')
+    if class and static==nil then
+        output(' ',self.parent.type,'*','self = ')
+        output('(',self.parent.type,'*) ')
+        output('tolua_tousertype(tolua_S,1,0);')
+    elseif static then
+        _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+    end
+
+
+    -- check self value
+    if class and static==nil then
+        output('#ifndef TOLUA_RELEASE\n')
+        output('  if (!self) tolua_error(tolua_S,"invalid \'self\' in accessing variable \''..self.name..'\'",NULL);');
+        output('#endif\n')
+    end
+
+    -- return value
+    if string.find(self.mod, 'tolua_inherits') then
+        output('#ifdef __cplusplus\n')
+        output('  tolua_pushusertype(tolua_S,(void*)static_cast<'..self.type..'*>(self), "',self.type,'");')
+        output('#else\n')
+        output('  tolua_pushusertype(tolua_S,(void*)(('..self.type..'*)self), "',self.type,'");')
+        output('#endif\n')
+    else
+        local t,ct = isbasic(self.type)
+        if t then
+            output('  tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static,prop_get)..');')
+        else
+            t = self.type
+            if self.ptr == '&' or self.ptr == '' then
+                output('  tolua_pushusertype(tolua_S,(void*)&'..self:getvalue(class,static,prop_get)..',"',t,'");')
+            else
+                output('  tolua_pushusertype(tolua_S,(void*)'..self:getvalue(class,static,prop_get)..',"',t,'");')
+            end
+        end
+    end
+    output(' return 1;')
+    output('}')
+    output('#endif //#ifndef TOLUA_DISABLE\n')
+    output('\n')
+
+    -- set function ------------------------------------------------
+    if not (strfind(self.type,'const%s+') or string.find(self.mod, 'tolua_readonly') or string.find(self.mod, 'tolua_inherits'))  then
+    if class then
+        output("/* set function:",self.name," of class ",class," */")
+    else
+        output("/* set function:",self.name," */")
+    end
+    self.csetname = self:cfuncname("tolua_set")
+    output("#ifndef TOLUA_DISABLE_"..self.csetname)
+    output("\nstatic int",self.csetname,"(lua_State* tolua_S)")
+    output("{")
+
+    -- declare self, if the case
+    if class and static==nil then
+        output(' ',self.parent.type,'*','self = ')
+        output('(',self.parent.type,'*) ')
+        output('tolua_tousertype(tolua_S,1,0);')
+        -- check self value
+    end
+    -- check types
+    output('#ifndef TOLUA_RELEASE\n')
+    output('  tolua_Error tolua_err;')
+    if class and static==nil then
+        output('  if (!self) tolua_error(tolua_S,"invalid \'self\' in accessing variable \''..self.name..'\'",NULL);');
+    elseif static then
+        _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)')
+    end
+
+    -- check variable type
+    output('  if (!'..self:outchecktype(2)..')')
+    output('   tolua_error(tolua_S,"#vinvalid type in variable assignment.",&tolua_err);')
+    output('#endif\n')
+
+    -- assign value
+    local def = 0
+    if self.def ~= '' then def = self.def end
+    if self.type == 'char*' and self.dim ~= '' then -- is string
+        output(' strncpy(')
+        if class and static then
+            output(self.parent.type..'::'..self.name)
+            elseif class then
+                output('self->'..self.name)
+            else
+                output(self.name)
+            end
+            output(',tolua_tostring(tolua_S,2,',def,'),',self.dim,'-1);')
+        else
+            local ptr = ''
+            if self.ptr~='' then ptr = '*' end
+            output(' ')
+            local name = prop_set or self.name
+            if class and static then
+                output(self.parent.type..'::'..name)
+            elseif class then
+                output('self->'..name)
+            else
+                output(name)
+            end
+            local t = isbasic(self.type)
+            if prop_set then
+                output('(')
+            else
+                output(' = ')
+            end
+            if not t and ptr=='' then output('*') end
+            output('((',self.mod,self.type)
+            if not t then
+                output('*')
+            end
+            output(') ')
+            if t then
+                if isenum(self.type) then
+                    output('(int) ')
+                end
+                output('tolua_to'..t,'(tolua_S,2,',def,'))')
+            else
+                output('tolua_tousertype(tolua_S,2,',def,'))')
+            end
+            if prop_set then
+                output(")")
+            end
+            output(";")
+        end
+        output(' return 0;')
+        output('}')
+        output('#endif //#ifndef TOLUA_DISABLE\n')
+        output('\n')
+    end
+
+end
+
+function classVariable:register (pre)
+
+    if not self:check_public_access() then
+        return
+    end
+    pre = pre or ''
+    local parent = self:inmodule() or self:innamespace() or self:inclass()
+    if not parent then
+        if classVariable._warning==nil then
+            warning("Mapping variable to global may degrade performance")
+            classVariable._warning = 1
+        end
+    end
+    if self.csetname then
+        output(pre..'tolua_variable(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');')
+    else
+        output(pre..'tolua_variable(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);')
+    end
+end
+
+-- Internal constructor
+function _Variable (t)
+    setmetatable(t,classVariable)
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects a string representing the variable declaration.
+function Variable (s)
+    return _Variable (Declaration(s,'var'))
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/lua/verbatim.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/lua/verbatim.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/lua/verbatim.lua	(revision 11817)
@@ -0,0 +1,78 @@
+-- tolua: verbatim class
+-- Written by Waldemar Celes
+-- TeCGraf/PUC-Rio
+-- Jul 1998
+-- $Id: verbatim.lua,v 1.3 2000/01/24 20:41:16 celes Exp $
+
+-- This code is free software; you can redistribute it and/or modify it.
+-- The software provided hereunder is on an "as is" basis, and
+-- the author has no obligation to provide maintenance, support, updates,
+-- enhancements, or modifications.
+
+
+
+-- Verbatim class
+-- Represents a line translated directed to the binding file.
+-- The following filds are stored:
+--   line = line text
+classVerbatim = {
+    line = '',
+    cond = nil,    -- condition: where to generate the code (s=suport, r=register)
+}
+classVerbatim.__index = classVerbatim
+setmetatable(classVerbatim,classFeature)
+
+-- preamble verbatim
+function classVerbatim:preamble ()
+    if self.cond == '' then
+        write(self.line)
+    end
+end
+
+-- support code
+function classVerbatim:supcode ()
+    if strfind(self.cond,'s') then
+        write(self.line)
+        write('\n')
+    end
+end
+
+-- register code
+function classVerbatim:register (pre)
+    if strfind(self.cond,'r') then
+        write(self.line)
+    end
+end
+
+
+-- Print method
+function classVerbatim:print (ident,close)
+    print(ident.."Verbatim{")
+    print(ident.." line = '"..self.line.."',")
+    print(ident.."}"..close)
+    end
+
+
+-- Internal constructor
+function _Verbatim (t)
+    setmetatable(t,classVerbatim)
+    append(t)
+    return t
+end
+
+-- Constructor
+-- Expects a string representing the text line
+function Verbatim (l,cond)
+    if strsub(l,1,1) == "'" then
+        l = strsub(l,2)
+    elseif strsub(l,1,1) == '$' then
+        cond = 'sr'       -- generates in both suport and register fragments
+        l = strsub(l,2)
+    end
+    return _Verbatim {
+        line = l,
+        cond = cond or '',
+    }
+end
+
+
Index: /code/branches/RacingBots_FS18/src/external/tolua/tolua.c
===================================================================
--- /code/branches/RacingBots_FS18/src/external/tolua/tolua.c	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/external/tolua/tolua.c	(revision 11817)
@@ -0,0 +1,211 @@
+/* tolua
+** Support code for Lua bindings.
+** Written by Waldemar Celes
+** TeCGraf/PUC-Rio
+** Aug 2003
+** $Id:$
+** Extension by Orxonox (Reto Grieder) to support working directory
+** and direct usage of lua files. (2008)
+*/
+
+/* This code is free software; you can redistribute it and/or modify it.
+** The software provided hereunder is on an "as is" basis, and
+** the author has no obligation to provide maintenance, support, updates,
+** enhancements, or modifications.
+*/
+
+#include "tolua++.h"
+
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+static void help (void)
+{
+ fprintf(stderr,"\n"
+         "usage: tolua++ [options] input_file\n"
+         "\n"
+         "Command line options are:\n"
+         "  -v       : print version information.\n"
+         "  -o  file : set output file; default is stdout.\n"
+         "  -H  file : create include file.\n"
+         "  -n  name : set package name; default is input file root name.\n"
+         "  -w  directory : set working directory; default is location of package file.\n"
+         "  -s  file : specify source lua code for the parser; all.lua is default.\n"
+         "  -p       : parse only.\n"
+         "  -P       : parse and print structure information (for debug).\n"
+         "  -S       : disable support for c++ strings.\n"
+         "  -1       : substract 1 to operator[] index (for compatibility with tolua5).\n"
+         "  -L  file : run lua file (with dofile()) before doing anything.\n"
+         "  -D       : disable automatic exporting of destructors for classes that have\n"
+         "             constructors (for compatibility with tolua5)\n"
+         "  -W       : disable warnings for unsupported features (for compatibility\n"
+         "             with tolua5)\n"
+         "  -C       : disable cleanup of included lua code (for easier debugging)\n"
+         "  -E  value[=value] : add extra values to the luastate\n"
+         "  -t       : export a list of types asociates with the C++ typeid name\n"
+         "  -h       : print this message.\n"
+         "Should the input file be omitted, stdin is assumed;\n"
+         "in that case, the package name must be explicitly set.\n\n"
+        );
+}
+
+static void version (void)
+{
+ fprintf(stderr, "%s (written by W. Celes, A. Manzur)\n",TOLUA_VERSION);
+}
+
+static void setfield (lua_State* L, int table, char* f, char* v)
+{
+ lua_pushstring(L,f);
+ lua_pushstring(L,v);
+ lua_settable(L,table);
+}
+
+static void add_extra (lua_State* L, char* value) {
+ int len;
+ lua_getglobal(L, "_extra_parameters");
+ len = luaL_getn(L, -1);
+ lua_pushstring(L, value);
+ lua_rawseti(L, -2, len+1);
+ lua_pop(L, 1);
+};
+
+static void error (char* o)
+{
+ fprintf(stderr,"tolua: unknown option '%s'\n",o);
+ help();
+ exit(1);
+}
+
+int main (int argc, char* argv[])
+{
+ char* working_directory = "";
+ char* lua_source = "";
+
+ #ifdef LUA_VERSION_NUM /* lua 5.1 */
+ lua_State* L = luaL_newstate();
+ luaL_openlibs(L);
+ #else
+ lua_State* L = lua_open();
+ luaopen_base(L);
+ luaopen_io(L);
+ luaopen_string(L);
+ luaopen_table(L);
+ luaopen_math(L);
+ luaopen_debug(L);
+ #endif
+
+ lua_pushstring(L,TOLUA_VERSION); lua_setglobal(L,"TOLUA_VERSION");
+ lua_pushstring(L,LUA_VERSION); lua_setglobal(L,"TOLUA_LUA_VERSION");
+
+
+ if (argc==1)
+ {
+  help();
+  return 0;
+ }
+ else
+ {
+  int i, t;
+  lua_newtable(L);
+  lua_setglobal(L, "_extra_parameters");
+  lua_newtable(L);
+  lua_pushvalue(L,-1);
+  lua_setglobal(L,"flags");
+  t = lua_gettop(L);
+  for (i=1; i<argc; ++i)
+  {
+   if (*argv[i] == '-')
+   {
+    switch (argv[i][1])
+    {
+     case 'v': version(); return 0;
+     case 'h': help(); return 0;
+     case 'p': setfield(L,t,"p",""); break;
+     case 'P': setfield(L,t,"P",""); break;
+     case 'o': setfield(L,t,"o",argv[++i]); break;
+     case 'n': setfield(L,t,"n",argv[++i]); break;
+     case 'H': setfield(L,t,"H",argv[++i]); break;
+     case 'w':
+      working_directory = argv[++i];
+      setfield(L,t,"w",argv[i]);
+      break;
+     case 's':
+      lua_source = argv[++i];
+      setfield(L,t,"s",argv[i]);
+      break;
+     case 'S': setfield(L,t,"S",""); break;
+     case '1': setfield(L,t,"1",""); break;
+     case 'L': setfield(L,t,"L",argv[++i]); break;
+     case 'D': setfield(L,t,"D",""); break;
+     case 'W': setfield(L,t,"W",""); break;
+     case 'C': setfield(L,t,"C",""); break;
+     case 'E': add_extra(L,argv[++i]); break;
+     case 't': setfield(L,t,"t",""); break;
+     default: error(argv[i]); break;
+    }
+   }
+   else
+   {
+    setfield(L,t,"f",argv[i]);
+    break;
+   }
+  }
+  lua_pop(L,1);
+ }
+
+ {
+  char path[BUFSIZ];
+  char file[BUFSIZ];
+  path[0] = '\0';
+  file[0] = '\0';
+
+  if (strlen(lua_source) > 0 &&
+      lua_source[0] != '/' &&
+      lua_source[0] != '\\' &&
+      strlen(lua_source) > 1 &&
+      lua_source[1] != ':')
+  {
+   /* Relative path, prefix working directory */
+   strcpy(path, working_directory);
+   /* Make sure there is '\\' or '/' at the end of the path */
+   if (strlen(path) > 0)
+   {
+    char last = path[strlen(path) - 1];
+    if (last != '\\' && last != '/')
+     strcat(path, "/");
+   }
+  }
+
+  strcat(path, lua_source);
+
+  /* Extract the full path */
+  {
+   char* p;
+   p = strrchr(path, '/');
+   if (p == NULL)
+    p = strrchr(path, '\\');
+   p = (p == NULL) ? path : p + 1;
+   strcpy(file, p);
+   *p = '\0';
+  }
+  if (strlen(file) == 0)
+   strcpy(file, "all.lua");
+
+  lua_pushstring(L, path);
+  lua_setglobal(L, "path");
+  strcat(path, file);
+#ifdef LUA_VERSION_NUM /* lua 5.1 */
+  luaL_dofile(L, path);
+#else
+  lua_dofile(L, path);
+#endif
+ }
+ return 0;
+}
Index: /code/branches/RacingBots_FS18/src/libraries/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,27 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+################ Sub Directories ################
+
+ADD_SUBDIRECTORY(util)
+ADD_SUBDIRECTORY(core)
+ADD_SUBDIRECTORY(network)
+ADD_SUBDIRECTORY(tools)
Index: /code/branches/RacingBots_FS18/src/libraries/core/ApplicationPaths.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ApplicationPaths.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ApplicationPaths.cc	(revision 11817)
@@ -0,0 +1,249 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ApplicationPaths.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <fstream>
+#include <vector>
+#include <boost/filesystem.hpp>
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN
+#  endif
+#  include <windows.h>
+#  undef min
+#  undef max
+#elif defined(ORXONOX_PLATFORM_APPLE)
+#  include <sys/param.h>
+#  include <mach-o/dyld.h>
+#else /* Linux */
+#  include <sys/types.h>
+#  include <unistd.h>
+#endif
+
+#include "SpecialConfig.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+
+// Differentiate Boost Filesystem v2 and v3
+#if (BOOST_FILESYSTEM_VERSION < 3)
+#  define BF_LEAF leaf
+#  define BF_GENERIC_STRING string
+#else
+#  define BF_LEAF path().filename().string
+#  define BF_GENERIC_STRING generic_string
+#endif
+
+namespace orxonox
+{
+    namespace bf = boost::filesystem;
+
+    //! Static pointer to the singleton
+    ApplicationPaths* ApplicationPaths::singletonPtr_s  = nullptr;
+
+    ApplicationPaths::ApplicationPaths()
+        : rootPath_(*(new bf::path()))
+        , executablePath_(*(new bf::path()))
+        , modulePath_(*(new bf::path()))
+        , pluginPath_(*(new bf::path()))
+        , bBuildDirectoryRun_(false)
+    {
+        //////////////////////////
+        // FIND EXECUTABLE PATH //
+        //////////////////////////
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+        // get executable module
+        TCHAR buffer[1024];
+        if (GetModuleFileName(nullptr, buffer, 1024) == 0)
+            ThrowException(General, "Could not retrieve executable path.");
+
+#elif defined(ORXONOX_PLATFORM_APPLE)
+        char buffer[1024];
+        uint32_t path_len = 1023;
+        if (_NSGetExecutablePath(buffer, &path_len))
+            ThrowException(General, "Could not retrieve executable path.");
+
+#else /* Linux */
+        /* written by Nicolai Haehnle <prefect_@gmx.net> */
+
+        /* Get our PID and build the name of the link in /proc */
+        char linkname[64]; /* /proc/<pid>/exe */
+        if (snprintf(linkname, sizeof(linkname), "/proc/%i/exe", getpid()) < 0)
+        {
+            /* This should only happen on large word systems. I'm not sure
+               what the proper response is here.
+               Since it really is an assert-like condition, aborting the
+               program seems to be in order. */
+            assert(false);
+        }
+
+        /* Now read the symbolic link */
+        char buffer[1024];
+        int ret;
+        ret = readlink(linkname, buffer, 1024);
+        /* In case of an error, leave the handling up to the caller */
+        if (ret == -1)
+            ThrowException(General, "Could not retrieve executable path.");
+
+        /* Ensure proper NUL termination */
+        buffer[ret] = 0;
+#endif
+
+        // Remove executable filename
+        executablePath_ = bf::path(buffer).branch_path();
+
+        /////////////////////////////////
+        // SET MODULE AND PLUGIN PATHS //
+        /////////////////////////////////
+
+        if (bf::exists(executablePath_ / "orxonox_dev_build.keep_me"))
+        {
+            orxout(internal_info) << "Running from the build tree." << endl;
+            ApplicationPaths::bBuildDirectoryRun_ = true;
+            modulePath_ = specialConfig::moduleDevDirectory;
+            pluginPath_ = specialConfig::pluginDevDirectory;
+        }
+        else
+        {
+
+#ifdef INSTALL_COPYABLE // --> relative paths
+
+            // Also set the root path
+            bf::path relativeExecutablePath(specialConfig::defaultRuntimePath);
+            rootPath_ = executablePath_;
+            while (!bf::equivalent(rootPath_ / relativeExecutablePath, executablePath_) && !rootPath_.empty())
+                rootPath_ = rootPath_.branch_path();
+            if (rootPath_.empty())
+                ThrowException(General, "Could not derive a root directory. Might the binary installation directory contain '..' when taken relative to the installation prefix path?");
+
+            // Module and plugin paths are fixed as well
+            modulePath_ = rootPath_ / specialConfig::defaultModulePath;
+            pluginPath_ = rootPath_ / specialConfig::defaultPluginPath;
+
+#else
+
+            // There is no root path, so don't set it at all
+            // Module and plugin paths are fixed as well
+            modulePath_ = specialConfig::moduleInstallDirectory;
+            pluginPath_ = specialConfig::pluginInstallDirectory;
+
+#endif
+        }
+    }
+
+    ApplicationPaths::~ApplicationPaths()
+    {
+        delete &rootPath_;
+        delete &executablePath_;
+        delete &modulePath_;
+        delete &pluginPath_;
+    }
+
+    std::map<std::string, std::string> ApplicationPaths::getModulePaths()
+    {
+        return this->getModuleOrPluginPaths(modulePath_, specialConfig::moduleExtension);
+    }
+
+    std::map<std::string, std::string> ApplicationPaths::getPluginPaths()
+    {
+        return this->getModuleOrPluginPaths(pluginPath_, specialConfig::pluginExtension);
+    }
+
+    std::map<std::string, std::string> ApplicationPaths::getModuleOrPluginPaths(boost::filesystem::path& directory, const std::string& extension)
+    {
+        std::map<std::string, std::string> paths;
+
+        // We search for helper files with the following extension
+        size_t extensionlength = extension.size();
+
+        // Make sure the path exists, otherwise don't load modules/plugins
+        if (!boost::filesystem::exists(directory))
+            return paths;
+
+        boost::filesystem::directory_iterator file(directory);
+        boost::filesystem::directory_iterator end;
+
+        // Iterate through all files
+        while (file != end)
+        {
+            std::string filename = file->BF_LEAF();
+
+            // Check if the file ends with the extension in question
+            if (filename.size() > extensionlength)
+            {
+                if (filename.substr(filename.size() - extensionlength) == extension)
+                {
+                    // We've found a helper file
+                    const std::string& moduleName = filename.substr(0, filename.size() - extensionlength);
+
+                    // Read it's content to get the library's name
+                    std::ifstream infile(file->path().string().c_str());
+                    std::string libraryName;
+                    if (infile >> libraryName)
+                    {
+                        std::string libraryNameWithoutExtension = libraryName.substr(0, libraryName.find_first_of('.'));
+                        std::string libraryPath = directory.BF_GENERIC_STRING() + '/' + libraryNameWithoutExtension;
+                        paths[moduleName] = libraryPath;
+                    }
+                    else
+                    {
+                        orxout(internal_warning) << "Could not file " << filename << endl;
+                    }
+                }
+            }
+            ++file;
+        }
+
+        return paths;
+    }
+
+    /*static*/ std::string ApplicationPaths::getRootPathString()
+    {
+        return getInstance().rootPath_.BF_GENERIC_STRING() + '/';
+    }
+
+    /*static*/ std::string ApplicationPaths::getExecutablePathString()
+    {
+        return getInstance().executablePath_.BF_GENERIC_STRING() + '/';
+    }
+
+    /*static*/ std::string ApplicationPaths::getModulePathString()
+    {
+        return getInstance().modulePath_.BF_GENERIC_STRING() + '/';
+    }
+
+    /*static*/ std::string ApplicationPaths::getPluginPathString()
+    {
+        return getInstance().pluginPath_.BF_GENERIC_STRING() + '/';
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/ApplicationPaths.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ApplicationPaths.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ApplicationPaths.h	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Management Resources
+*/
+
+#ifndef _ApplicationPaths_H__
+#define _ApplicationPaths_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <vector>
+#include "util/Singleton.h"
+
+//tolua_begin
+namespace orxonox
+{
+//tolua_end
+    /**
+    @brief
+        The ApplicationPaths class is a singleton which provides static paths of the application.
+    @details
+        The class provides information about the executable, root and module/plugin path.
+        It determines those by the use of platform specific functions.
+    @remarks
+        Not all paths are always available:
+        - root only when installed copyable
+    */
+    class _CoreExport ApplicationPaths //tolua_export
+        : public Singleton<ApplicationPaths>
+    { //tolua_export
+        friend class Singleton<ApplicationPaths>;
+
+        public:
+            /**
+            @brief
+                Retrieves the executable path and sets all hard coded fixed paths (currently only the module and the plugin paths)
+                Also checks for "orxonox_dev_build.keep_me" in the executable directory.
+                If found it means that this is not an installed run, hence we
+                don't write the logs and config files to ~/.orxonox
+            @throw
+                GeneralException
+            */
+            ApplicationPaths();
+            ~ApplicationPaths();
+
+            //! Returns the path to the root folder as boost::filesystem::path
+            static const boost::filesystem::path& getRootPath()
+                { return getInstance().rootPath_; }
+            //! Returns the path to the executable folder as boost::filesystem::path
+            static const boost::filesystem::path& getExecutablePath()
+                { return getInstance().executablePath_; }
+            //! Returns the path to the modules as boost::filesystem::path
+            static const boost::filesystem::path& getModulePath()
+                { return getInstance().modulePath_; }
+            //! Returns the path to the plugins as boost::filesystem::path
+            static const boost::filesystem::path& getPluginPath()
+                { return getInstance().pluginPath_; }
+
+            //! Returns the path to the root folder as std::string
+            static std::string getRootPathString();
+            //! Returns the path to the executable folder as std::string
+            static std::string getExecutablePathString();
+            //! Returns the path to the modules as std::string
+            static std::string getModulePathString();
+            //! Returns the path to the plugins as std::string
+            static std::string getPluginPathString();
+
+            //! Return true for runs in the build directory (not installed)
+            static bool buildDirectoryRun() { return getInstance().bBuildDirectoryRun_; }
+
+            //! Returns a map with all modules declared by a *.module file in the module folder; key = module-name, value = library-path (content of the file).
+            std::map<std::string, std::string> getModulePaths();
+            //! Returns a map with all plugins declared by a *.plugin file in the plugin folder; key = plugin-name, value = library-path (content of the file).
+            std::map<std::string, std::string> getPluginPaths();
+
+        private:
+            // non-copyable:
+            ApplicationPaths(const ApplicationPaths&) = delete;
+            ApplicationPaths& operator=(const ApplicationPaths&) = delete;
+
+            std::map<std::string, std::string> getModuleOrPluginPaths(boost::filesystem::path& directory, const std::string& extension);
+
+            //! Path to the parent directory of the ones above if program was installed with relative paths
+            boost::filesystem::path& rootPath_;
+            boost::filesystem::path& executablePath_;        //!< Path to the executable
+            boost::filesystem::path& modulePath_;            //!< Path to the modules
+            boost::filesystem::path& pluginPath_;            //!< Path to the plugins
+
+            bool                     bBuildDirectoryRun_;    //!< True for runs in the build directory (not installed)
+            static ApplicationPaths* singletonPtr_s;
+    }; //tolua_export
+} //tolua_export
+
+#endif /* _ApplicationPaths_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/BaseObject.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/BaseObject.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/BaseObject.cc	(revision 11817)
@@ -0,0 +1,498 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the BaseObject class.
+*/
+
+#include "BaseObject.h"
+
+#include <tinyxml/tinyxml.h>
+
+#include "CoreIncludes.h"
+#include "Event.h"
+#include "EventIncludes.h"
+#include "Template.h"
+#include "XMLFile.h"
+#include "XMLNameListener.h"
+#include "XMLPort.h"
+#include "command/Functor.h"
+#include "object/Iterator.h"
+
+#include "class/OrxonoxInterface.h" // we include this only to include OrxonoxInterface.h at least once in core to keep MSVC happy...
+
+namespace orxonox
+{
+    RegisterClass(BaseObject);
+
+    /**
+        @brief Constructor: Registers the object in the BaseObject-list.
+    */
+    BaseObject::BaseObject(Context* context) : bInitialized_(false)
+    {
+        RegisterObject(BaseObject);
+
+        this->bInitialized_ = true;
+
+        this->bActive_ = true;
+        this->bVisible_ = true;
+        this->bRegisteredEventStates_ = false;
+
+        this->lastLoadedXMLElement_ = nullptr;
+
+        this->mainStateFunctor_ = nullptr;
+
+        if (context)
+            this->setContext(context);
+
+        BaseObject* creator = orxonox_cast<BaseObject*>(context);
+        this->setCreator(creator);
+        if (this->creator_)
+        {
+            this->setFile(this->creator_->getFile());
+
+            // store strong-pointers on all four base objects by default (can be overwritten with weak-ptr after the constructor if necessary)
+            this->setNamespace(this->creator_->namespace_.createStrongPtr());
+            this->setScene    (this->creator_->scene_    .createStrongPtr(), this->creator_->sceneID_);
+            this->setGametype (this->creator_->gametype_ .createStrongPtr());
+            this->setLevel    (this->creator_->level_    .createStrongPtr());
+        }
+        else
+        {
+            this->file_ = nullptr;
+            this->sceneID_ = OBJECTID_UNKNOWN;
+        }
+    }
+
+    /**
+        @brief Destructor
+    */
+    BaseObject::~BaseObject()
+    {
+        if (this->isInitialized())
+        {
+            for (std::map<BaseObject*, std::string>::const_iterator it = this->eventSources_.begin(); it != this->eventSources_.end(); )
+                this->removeEventSource((it++)->first);
+
+            for (std::set<BaseObject*>::const_iterator it = this->eventListeners_.begin(); it != this->eventListeners_.end(); )
+                (*(it++))->removeEventSource(this);
+
+            for (std::map<std::string, EventState*>::const_iterator it = this->eventStates_.begin(); it != this->eventStates_.end(); ++it)
+                delete it->second;
+        }
+    }
+
+    /** @brief Adds an object which listens to the events of this object. */
+    void BaseObject::registerEventListener(BaseObject* object)
+    {
+        orxout(verbose, context::events) << "New EventListener: " << object->getIdentifier()->getName() << " &(" << object << ")." << endl;
+        this->eventListeners_.insert(object);
+    }
+
+    /**
+        @brief XML loading and saving.
+        @param xmlelement The XML-element
+        @param mode The mode defines the operation that is being executed: loading or saving the object (from or to XML respectively)
+    */
+    void BaseObject::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(BaseObject, "name", setXMLName, getName, xmlelement, mode);
+        XMLPortParam(BaseObject, "visible", setVisible, isVisible, xmlelement, mode);
+        XMLPortParam(BaseObject, "active", setActive, isActive, xmlelement, mode);
+        XMLPortParam(BaseObject, "mainstate", setMainStateName, getMainStateName, xmlelement, mode);
+        XMLPortParamTemplate(BaseObject, "template", addTemplate, getSingleTemplate, xmlelement, mode, const std::string&);
+
+        XMLPortObjectTemplate(BaseObject, Template, "templates", addTemplate, getTemplate, xmlelement, mode, Template*);
+        XMLPortObject(BaseObject, BaseObject, "eventlisteners", addEventListener, getEventListener, xmlelement, mode);
+
+        Element* events = nullptr;
+        if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
+            events = xmlelement.FirstChildElement("events", false);
+        else if (mode == XMLPort::SaveObject)
+            {}
+        if (events)
+            this->XMLEventPort(*events, mode);
+    }
+
+    /**
+        @brief Defines the possible event states of this object and parses eventsources from an XML file.
+        @param xmlelement The XML-element
+        @param mode The mode defines the operation that is being executed: loading or saving the object (from or to XML respectively)
+    */
+    void BaseObject::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortEventState(BaseObject, BaseObject, "activity", setActive, xmlelement, mode);
+        XMLPortEventState(BaseObject, BaseObject, "visibility", setVisible, xmlelement, mode);
+        XMLPortEventState(BaseObject, BaseObject, "mainstate", setMainState, xmlelement, mode);
+
+        this->bRegisteredEventStates_ = true;
+    }
+
+    /**
+        @brief Loads the name of the object through XML and calls all XMLNameListener.
+        @param name The name of the object
+    */
+    void BaseObject::setXMLName(const std::string& name)
+    {
+        this->setName(name);
+
+        for (XMLNameListener* listener : ObjectList<XMLNameListener>())
+            listener->loadedNewXMLName(this);
+    }
+
+    /**
+        @brief Returns the levelfile that loaded this object.
+        @return The levelfile
+    */
+    const std::string& BaseObject::getFilename() const
+    {
+        if (this->file_)
+            return this->file_->getFilename();
+        else
+            return BLANKSTRING;
+    }
+
+    /**
+        @brief Adds a Template to the object.
+        @param name The name of the Template
+    */
+    void BaseObject::addTemplate(const std::string& name)
+    {
+        Template* temp = Template::getTemplate(name);
+        if (temp)
+            this->addTemplate(temp);
+        else
+            orxout(internal_error) << "\"" << name << "\" is not a valid Template name (in class: " << this->getIdentifier()->getName() << ", name: " << this->getName() << ")." << endl;
+    }
+
+    /**
+        @brief Adds a Template to the object.
+        @param temp The Template
+    */
+    void BaseObject::addTemplate(Template* temp)
+    {
+        // network
+        if (temp->isLink())
+        {
+            this->networkTemplateNames_.insert(temp->getLink());
+
+            Template* link;
+            assert(!(link = Template::getTemplate(temp->getLink())) || !link->isLink());
+            (void)link; // avoid compiler warning
+        }
+        else
+            this->networkTemplateNames_.insert(temp->getName());
+
+        // add template
+        this->templates_.insert(temp);
+        temp->applyOn(this);
+    }
+
+    /**
+        @brief Returns the name of the first Template.
+        @return The name as string.
+    */
+    const std::string& BaseObject::getSingleTemplate(void) const
+    {
+        if(this->templates_.empty())
+            return BLANKSTRING;
+
+        return (*this->templates_.begin())->getName();
+    }
+
+    /**
+        @brief Returns the Template with the given index.
+        @param index The index
+    */
+    Template* BaseObject::getTemplate(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (Template* temp : this->templates_)
+        {
+            if (i == index)
+                return temp;
+            i++;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Adds a new event source for a specific state.
+        @param source The object which sends events to this object
+        @param state The state of this object which will be affected by the events
+    */
+    void BaseObject::addEventSource(BaseObject* source, const std::string& state)
+    {
+        this->eventSources_[source] = state;
+        source->registerEventListener(this);
+    }
+
+    /**
+        @brief Removes an eventsource (but doesn't unregister itself at the source).
+    */
+    void BaseObject::removeEventSource(BaseObject* source)
+    {
+        this->eventSources_.erase(source);
+        source->unregisterEventListener(this);
+    }
+
+    /**
+        @brief Returns an eventsource with a given index.
+    */
+    BaseObject* BaseObject::getEventSource(unsigned int index, const std::string& state) const
+    {
+        unsigned int i = 0;
+        for (const auto& mapEntry : this->eventSources_)
+        {
+            if (mapEntry.second != state)
+                continue;
+
+            if (i == index)
+                return mapEntry.first;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Adds an object which listens to the events of this object. The events are sent to the other objects mainstate.
+    */
+    void BaseObject::addEventListener(BaseObject* listener)
+    {
+        this->eventListenersXML_.insert(listener);
+        listener->addEventSource(this, "mainstate");
+    }
+
+    /**
+        @brief Returns an event listener with a given index.
+    */
+    BaseObject* BaseObject::getEventListener(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (BaseObject* listener : this->eventListenersXML_)
+        {
+            if (i == index)
+                return listener;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Adds a new event-state to the object. Event-states are states which can be changed by events.
+        @param name  The name of the event
+        @param state The object containing information about the event-state
+    */
+    void BaseObject::addEventState(const std::string& name, EventState* state)
+    {
+        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(name);
+        if (it != this->eventStates_.end())
+        {
+            orxout(internal_warning, context::events) << "Overwriting EventState in class " << this->getIdentifier()->getName() << '.' << endl;
+            delete (it->second);
+        }
+
+        this->eventStates_[name] = state;
+    }
+
+    /**
+        @brief Returns the event-state with the given name.
+    */
+    EventState* BaseObject::getEventState(const std::string& name) const
+    {
+        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(name);
+        if (it != this->eventStates_.end())
+            return (it->second);
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Fires an event (without a state).
+    */
+    void BaseObject::fireEvent(const std::string& name)
+    {
+        this->fireEvent(true, name);
+        this->fireEvent(false, name);
+    }
+
+    /**
+        @brief Fires an event which activates or deactivates a state.
+    */
+    void BaseObject::fireEvent(bool activate, const std::string& name)
+    {
+        this->fireEvent(activate, this, name);
+    }
+
+    /**
+        @brief Fires an event which activates or deactivates a state with agiven originator (the object which triggered the event).
+    */
+    void BaseObject::fireEvent(bool activate, BaseObject* originator, const std::string& name)
+    {
+        Event event(activate, originator, name);
+
+        for (BaseObject* listener : this->eventListeners_)
+        {
+            event.statename_ = listener->eventSources_[this];
+            listener->processEvent(event);
+        }
+    }
+
+    /**
+        @brief Fires an event, using the Event struct.
+    */
+    void BaseObject::fireEvent(Event& event)
+    {
+        for (BaseObject* listener : this->eventListeners_)
+            listener->processEvent(event);
+    }
+
+    /**
+        @brief Processing an event by calling the right main state.
+        @param event The event struct which contains the information about the event
+    */
+    void BaseObject::processEvent(Event& event)
+    {
+        this->registerEventStates();
+
+        orxout(verbose, context::events) << this->getIdentifier()->getName() << " (&" << this << ") processing event. originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << "), activate: " << event.activate_ << ", name: " << event.name_ << ", statename: " << event.statename_ << "." << endl;
+
+        std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(event.statename_);
+        if (it != this->eventStates_.end())
+            it->second->process(event, this);
+        else if (!event.statename_.empty())
+            orxout(internal_warning, context::events) << "\"" << event.statename_ << "\" is not a valid state in object \"" << this->getName() << "\" of class " << this->getIdentifier()->getName() << "." << endl;
+        else
+            orxout(internal_warning, context::events) << "Event with invalid source sent to object \"" << this->getName() << "\" of class " << this->getIdentifier()->getName() << "." << endl;
+    }
+
+    /**
+        @brief Sets the main state of the object to a given boolean value.
+
+        Note: The main state of an object can be set with the @ref setMainStateName function.
+        It's part of the eventsystem and used for event forwarding (when the target object can't specify a specific state,
+        the main state is used by default).
+    */
+    void BaseObject::setMainState(bool state)
+    {
+        if (this->mainStateFunctor_)
+        {
+            if (this->mainStateFunctor_->getParamCount() == 0)
+            {
+                if (state)
+                    (*this->mainStateFunctor_)();
+            }
+            else
+            {
+                (*this->mainStateFunctor_)(state);
+            }
+        }
+        else
+            orxout(internal_warning, context::events) << "No MainState defined in object \"" << this->getName() << "\" (" << this->getIdentifier()->getName() << ")" << endl;
+    }
+
+    /**
+        @brief This function gets called if the main state name of the object changes.
+    */
+    void BaseObject::changedMainStateName()
+    {
+        this->mainStateFunctor_ = nullptr;
+
+        if (!this->mainStateName_.empty())
+        {
+            this->registerEventStates();
+
+            std::map<std::string, EventState*>::const_iterator it = this->eventStates_.find(this->mainStateName_);
+            if (it != this->eventStates_.end() && it->second->getFunctor())
+            {
+                if (it->second->getFunctor()->getParamCount() <= 1)
+                    this->mainStateFunctor_ = it->second->getFunctor();
+                else
+                    orxout(internal_warning, context::events) << "Can't use \"" << this->mainStateName_ << "\" as MainState because it needs a second argument." << endl;
+            }
+            else
+                orxout(internal_warning, context::events) << "\"" << this->mainStateName_ << "\" is not a valid MainState." << endl;
+        }
+    }
+
+    /**
+        @brief Calls XMLEventPort with an empty XML-element to register the event states if necessary.
+    */
+    void BaseObject::registerEventStates()
+    {
+        if (!this->bRegisteredEventStates_)
+        {
+            Element xmlelement;
+            this->XMLEventPort(xmlelement, XMLPort::NOP);
+        }
+    }
+
+    /**
+        @brief Manually loads all event states, even if the class doesn't officially support them. This is needed by some classes like @ref EventDispatcher or @ref EventTarget.
+    */
+    void BaseObject::loadAllEventStates(Element& xmlelement, XMLPort::Mode mode, BaseObject* object, Identifier* identifier)
+    {
+        Element* events = xmlelement.FirstChildElement("events", false);
+        if (events)
+        {
+            // get the list of all states present
+            std::list<std::string> eventnames;
+            if (mode == XMLPort::LoadObject || mode == XMLPort::ExpandObject)
+            {
+                for (ticpp::Iterator<ticpp::Element> child = events->FirstChildElement(false); child != child.end(); child++)
+                    eventnames.push_back(child->Value());
+            }
+            else if (mode == XMLPort::SaveObject)
+            {
+            }
+
+            // iterate through all states and get the event sources
+            for (const std::string& statename : eventnames)
+            {
+                // if the event state is already known, continue with the next state
+                orxonox::EventState* eventstate = object->getEventState(statename);
+                if (eventstate)
+                    continue;
+
+                XMLPortClassObjectContainer<BaseObject, BaseObject>* container = (XMLPortClassObjectContainer<BaseObject, BaseObject>*)(identifier->getXMLPortObjectContainer(statename));
+                if (!container)
+                {
+                    const ExecutorMemberPtr<BaseObject>& setfunctor = createExecutor(createFunctor(&BaseObject::addEventSource), std::string( "BaseObject" ) + "::" + "addEventSource" + '(' + statename + ')');
+                    const ExecutorMemberPtr<BaseObject>& getfunctor = createExecutor(createFunctor(&BaseObject::getEventSource), std::string( "BaseObject" ) + "::" + "getEventSource" + '(' + statename + ')');
+                    setfunctor->setDefaultValue(1, statename);
+                    getfunctor->setDefaultValue(1, statename);
+
+                    container = new XMLPortClassObjectContainer<BaseObject, BaseObject>(statename, identifier, setfunctor, getfunctor, false, true);
+                    identifier->addXMLPortObjectContainer(statename, container);
+                }
+                container->port(object, *events, mode);
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/BaseObject.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/BaseObject.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/BaseObject.h	(revision 11817)
@@ -0,0 +1,280 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup BaseObject BaseObject
+    @ingroup Core
+*/
+
+/**
+    @file
+    @ingroup BaseObject
+    @brief Declaration of BaseObject, the base class of all objects in Orxonox.
+
+    The BaseObject is the parent of all classes representing an instance in the game.
+*/
+
+#ifndef _BaseObject_H__
+#define _BaseObject_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <list>
+
+#include "util/mbool.h"
+#include "class/OrxonoxClass.h"
+#include "class/Super.h"
+#include "object/StrongPtr.h"
+
+namespace orxonox
+{
+    class Scene;
+    class Gametype;
+    class Level;
+
+    /// The BaseObject is the parent of all classes representing an instance in the game.
+    class _CoreExport BaseObject : public OrxonoxClass
+    {
+        template <class T> friend class XMLPortClassParamContainer;
+
+        public:
+            template <class T>
+            class StrongOrWeakPtr
+            {
+                public:
+                    inline StrongOrWeakPtr();
+                    inline StrongOrWeakPtr(const StrongPtr<T>& ptr);
+                    inline StrongOrWeakPtr(const WeakPtr<T>& ptr);
+
+                    inline T* get() const;
+                    inline StrongPtr<T> createStrongPtr() const;
+
+                private:
+                    StrongPtr<T> strongPtr_;
+                    WeakPtr<T> weakPtr_;
+            };
+
+        public:
+            BaseObject(Context* context);
+            virtual ~BaseObject();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+
+            /** @brief Returns if the object was initialized (passed the object registration). @return True was the object is initialized */
+            inline bool isInitialized() const { return this->bInitialized_; }
+
+            /** @brief Sets the name of the object. @param name The name */
+            inline void setName(const std::string& name) { this->oldName_ = this->name_; this->name_ = name; this->changedName(); }
+            /** @brief Returns the name of the object. */
+            inline const std::string& getName() const { return this->name_; }
+            /** @brief Returns the old name of the object. */
+            inline const std::string& getOldName() const { return this->oldName_; }
+            /** @brief This function gets called if the name of the object changes. */
+            virtual void changedName() {}
+
+            /** @brief Sets the state of the objects activity. @param bActive True = active */
+            inline void setActive(bool bActive)
+            {
+                if (this->bActive_ != bActive)
+                {
+                    this->bActive_ = bActive;
+                    this->changedActivity();
+                }
+            }
+            /** @brief Returns the state of the objects activity. @return The state of the activity */
+            inline const mbool& isActive() const { return this->bActive_; }
+            /** @brief This function gets called if the activity of the object changes. */
+            virtual void changedActivity() {}
+
+            /** @brief Sets the state of the objects visibility. @param bVisible True = visible */
+            inline void setVisible(bool bVisible)
+            {
+                if (this->bVisible_ != bVisible)
+                {
+                    this->bVisible_ = bVisible;
+                    this->changedVisibility();
+                }
+            }
+            /** @brief Returns the state of the objects visibility. @return The state of the visibility */
+            inline const mbool& isVisible() const { return this->bVisible_; }
+            /** @brief This function gets called if the visibility of the object changes. */
+            virtual void changedVisibility() {}
+
+            void setMainState(bool state);
+
+            /** @brief Sets the name of the main state (used for event reactions). */
+            void setMainStateName(const std::string& name)
+            {
+                if (this->mainStateName_ != name)
+                {
+                    this->mainStateName_ = name;
+                    this->changedMainStateName();
+                }
+            }
+            /** @brief Returns the name of the main state. */
+            inline const std::string& getMainStateName() const { return this->mainStateName_; }
+            /** @brief This function gets called if the main state name of the object changes. */
+            virtual void changedMainStateName();
+
+            /** @brief Sets a pointer to the xml file that loaded this object. @param file The pointer to the XMLFile */
+            inline void setFile(const XMLFile* file) { this->file_ = file; }
+            /** @brief Returns a pointer to the XMLFile that loaded this object. @return The XMLFile */
+            inline const XMLFile* getFile() const { return this->file_; }
+            const std::string& getFilename() const;
+
+            void addTemplate(const std::string& name);
+            void addTemplate(Template* temp);
+            /** @brief Returns the set of all aplied templates. */
+            inline const std::set<Template*>& getTemplates() const
+                { return this->templates_; }
+
+            inline void setNamespace(const StrongOrWeakPtr<Namespace>& ns) { this->namespace_ = ns; }
+            inline Namespace* getNamespace() const { return this->namespace_.get(); }
+
+            inline void setCreator(BaseObject* creator) { this->creator_ = creator; }
+            inline BaseObject* getCreator() const { return this->creator_; }
+
+            inline void setScene(const StrongOrWeakPtr<Scene>& scene, uint32_t sceneID) { this->scene_ = scene; this->sceneID_=sceneID; }
+            inline Scene* getScene() const { return this->scene_.get(); }
+            virtual inline uint32_t getSceneID() const { return this->sceneID_; }
+
+            inline void setGametype(const StrongOrWeakPtr<Gametype>& gametype) { this->gametype_ = gametype; }
+            inline Gametype* getGametype() const { return this->gametype_.get(); }
+
+            inline void setLevel(const StrongOrWeakPtr<Level>& level) { this->level_ = level; }
+            inline Level* getLevel() const { return this->level_.get(); }
+
+            void addEventSource(BaseObject* source, const std::string& state);
+            void removeEventSource(BaseObject* source);
+            BaseObject* getEventSource(unsigned int index, const std::string& state) const;
+
+            void addEventListener(BaseObject* listener);
+            BaseObject* getEventListener(unsigned int index) const;
+
+            void fireEvent(const std::string& name = "");
+            void fireEvent(bool activate, const std::string& name = "");
+            void fireEvent(bool activate, BaseObject* originator, const std::string& name = "");
+            void fireEvent(Event& event);
+
+            virtual void processEvent(Event& event);
+
+            /** @brief Sets the indentation of the debug output in the Loader. @param indentation The indentation */
+            inline void setLoaderIndentation(const std::string& indentation) { this->loaderIndentation_ = indentation; }
+            /** @brief Returns the indentation of the debug output in the Loader. @return The indentation */
+            inline const std::string& getLoaderIndentation() const { return this->loaderIndentation_; }
+
+            static void loadAllEventStates(Element& xmlelement, XMLPort::Mode mode, BaseObject* object, Identifier* identifier);
+
+        protected:
+            void addEventState(const std::string& name, EventState* container);
+            EventState* getEventState(const std::string& name) const;
+
+            std::string             name_;                     //!< The name of the object
+            std::string             oldName_;                  //!< The old name of the object
+            mbool                   bActive_;                  //!< True = the object is active
+            mbool                   bVisible_;                 //!< True = the object is visible
+            std::string             mainStateName_;
+            FunctorPtr              mainStateFunctor_;
+            std::set<std::string>   networkTemplateNames_;
+
+        private:
+            /** @brief Adds an object which listens to the events of this object. */
+            void registerEventListener(BaseObject* object);
+            /** @brief Removes an event listener from this object. */
+            inline void unregisterEventListener(BaseObject* object)
+                { this->eventListeners_.erase(object); }
+
+            void setXMLName(const std::string& name);
+            const std::string& getSingleTemplate(void) const;
+            Template* getTemplate(unsigned int index) const;
+            void registerEventStates();
+
+            bool                       bInitialized_;          //!< True if the object was initialized (passed the object registration)
+            const XMLFile*             file_;                  //!< The XMLFile that loaded this object
+            Element*                   lastLoadedXMLElement_;  //!< Non nullptr if the TinyXML attributes have already been copied to our own lowercase map
+            std::map<std::string, std::string> xmlAttributes_; //!< Lowercase XML attributes
+            std::string                loaderIndentation_;     //!< Indentation of the debug output in the Loader
+            StrongOrWeakPtr<Namespace> namespace_;
+            BaseObject*                creator_;
+            StrongOrWeakPtr<Scene>     scene_;
+            uint32_t                   sceneID_;
+            StrongOrWeakPtr<Gametype>  gametype_;
+            StrongOrWeakPtr<Level>     level_;
+            std::set<Template*>        templates_;
+
+            std::map<BaseObject*, std::string>  eventSources_;           //!< List of objects which send events to this object, mapped to the state which they affect
+            std::set<BaseObject*>               eventListeners_;         //!< List of objects which listen to the events of this object
+            std::set<BaseObject*>               eventListenersXML_;      //!< List of objects which listen to the events of this object through the "eventlisteners" subsection in XML
+            std::map<std::string, EventState*>  eventStates_;            //!< Maps the name of the event states to their helper objects
+            bool                                bRegisteredEventStates_; //!< Becomes true after the object registered its event states (with XMLEventPort)
+    };
+
+    SUPER_FUNCTION(0, BaseObject, XMLPort, false);
+    SUPER_FUNCTION(2, BaseObject, changedActivity, false);
+    SUPER_FUNCTION(3, BaseObject, changedVisibility, false);
+    SUPER_FUNCTION(4, BaseObject, XMLEventPort, false);
+    SUPER_FUNCTION(8, BaseObject, changedName, false);
+
+    template <class T>
+    BaseObject::StrongOrWeakPtr<T>::StrongOrWeakPtr()
+    {
+    }
+
+    template <class T>
+    BaseObject::StrongOrWeakPtr<T>::StrongOrWeakPtr(const StrongPtr<T>& ptr) : strongPtr_(ptr)
+    {
+    }
+
+    template <class T>
+    BaseObject::StrongOrWeakPtr<T>::StrongOrWeakPtr(const WeakPtr<T>& ptr) : weakPtr_(ptr)
+    {
+    }
+
+    template <class T>
+    T* BaseObject::StrongOrWeakPtr<T>::get() const
+    {
+        if (this->strongPtr_)
+            return this->strongPtr_;
+        else if (this->weakPtr_)
+            return this->weakPtr_;
+        else
+            return nullptr;
+    }
+
+    template <class T>
+    StrongPtr<T> BaseObject::StrongOrWeakPtr<T>::createStrongPtr() const
+    {
+        if (this->strongPtr_)
+            return this->strongPtr_; // creates a copy
+        else
+            return this->weakPtr_; // converts automatically to StrongPtr
+    }
+}
+
+#endif /* _BaseObject_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,115 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(CORE_SRC_FILES
+
+#BUILD_UNIT CoreStableBuildUnit.cc
+  ClassTreeMask.cc
+  Event.cc
+  Game.cc
+  GameConfig.cc
+  GameMode.cc
+  GameState.cc
+  Language.cc
+  Loader.cc
+  LuaState.cc
+  Namespace.cc
+  NamespaceNode.cc
+  Template.cc
+  UpdateListener.cc
+  ViewportEventListener.cc
+  WindowEventListener.cc
+  XMLNameListener.cc
+  XMLPort.cc
+#END_BUILD_UNIT
+
+  BaseObject.cc
+  Core.cc
+  CoreConfig.cc
+  CoreStaticInitializationHandler.cc
+
+BUILD_UNIT OgreBuildUnit.cc
+  GraphicsManager.cc
+  GUIManager.cc
+  Resource.cc
+END_BUILD_UNIT
+
+BUILD_UNIT FilesystemBuildUnit.cc
+  command/ArgumentCompletionFunctions.cc
+  config/ConfigFile.cc
+  ApplicationPaths.cc
+  ConfigurablePaths.cc
+END_BUILD_UNIT
+
+BUILD_UNIT ThreadBuildUnit.cc
+  command/TclThreadManager.cc
+  Thread.cc
+  ThreadPool.cc
+END_BUILD_UNIT
+)
+
+ADD_SUBDIRECTORY(class)
+ADD_SUBDIRECTORY(command)
+ADD_SUBDIRECTORY(commandline)
+ADD_SUBDIRECTORY(config)
+ADD_SUBDIRECTORY(input)
+ADD_SUBDIRECTORY(module)
+ADD_SUBDIRECTORY(object)
+ADD_SUBDIRECTORY(singleton)
+
+ORXONOX_ADD_LIBRARY(core
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    command/CommandExecutor.h
+    config/SettingsConfigFile.h
+    ApplicationPaths.h
+    ConfigurablePaths.h
+    Game.h
+    GameMode.h
+    GraphicsManager.h
+    GUIManager.h
+    Loader.h
+    LuaState.h
+    input/InputManager.h
+    input/KeyBinder.h
+    input/KeyBinderManager.h
+    ../util/output/OutputDefinitions.h
+  PCH_FILE
+    CorePrecompiledHeaders.h
+  LINK_LIBRARIES
+    ${OGRE_LIBRARY}
+    ${Boost_FILESYSTEM_LIBRARY}
+    ${Boost_SYSTEM_LIBRARY} # Filesystem dependency
+    ${Boost_THREAD_LIBRARY}
+    ${Boost_DATE_TIME_LIBRARY} # Thread dependency
+    ${CEGUI_LIBRARY}
+    ${CEGUILUA_LIBRARY}
+    ${CEGUI_TOLUA_LIBRARY}
+    ${CEGUI_OGRE_RENDERER_LIBRARY}
+    ${LUA5.1_LIBRARY}
+    cpptcl_orxonox
+    ois_orxonox
+    tinyxml_orxonox
+    util
+  LINK_LIBS_UNIX
+    dl
+    pthread
+  SOURCE_FILES
+    ${CORE_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/ClassTreeMask.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ClassTreeMask.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ClassTreeMask.cc	(revision 11817)
@@ -0,0 +1,963 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the ClassTreeMask, ClassTreeMaskNode, and ClassTreeMaskIterator classes.
+*/
+
+#include "ClassTreeMask.h"
+#include "class/Identifier.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###    ClassTreeMaskNode    ###
+    // ###############################
+    /**
+        @brief Constructor: Creates the node, sets the subclass and the rule.
+        @param subclass The subclass the rule refers to
+        @param bIncluded The rule: included (true) or excluded (false)
+    */
+    ClassTreeMaskNode::ClassTreeMaskNode(const Identifier* subclass, bool bIncluded)
+    {
+        this->subclass_ = subclass;
+        this->bIncluded_ = bIncluded;
+    }
+
+    /**
+        @brief Destructor: Deletes all subnodes.
+    */
+    ClassTreeMaskNode::~ClassTreeMaskNode()
+    {
+        // Go through the list of all subnodes and delete them
+        this->deleteAllSubnodes();
+    }
+
+    /**
+        @brief Sets the rule for the node to "included".
+        @param overwrite True = overwrite previously added rules for inheriting classes
+    */
+    void ClassTreeMaskNode::include(bool overwrite)
+    {
+        this->setIncluded(true, overwrite);
+    }
+
+    /**
+        @brief Sets the rule for the node to "excluded".
+        @param overwrite True = overwrite previously added rules for inheriting classes
+    */
+    void ClassTreeMaskNode::exclude(bool overwrite)
+    {
+        this->setIncluded(false, overwrite);
+    }
+
+    /**
+        @brief Sets the rule for the node to a given value and erases all following rules.
+        @param bIncluded The rule: included (true) or excluded (false)
+        @param overwrite True = overwrite previously added rules for inheriting classes
+    */
+    void ClassTreeMaskNode::setIncluded(bool bIncluded, bool overwrite)
+    {
+        if (overwrite)
+            this->deleteAllSubnodes();
+
+        this->bIncluded_ = bIncluded;
+    }
+
+    /**
+        @brief Adds a new subnode to the list of subnodes.
+    */
+    void ClassTreeMaskNode::addSubnode(ClassTreeMaskNode* subnode)
+    {
+        this->subnodes_.insert(this->subnodes_.end(), subnode);
+    }
+
+    /**
+        @brief Deletes all subnodes of this node.
+    */
+    void ClassTreeMaskNode::deleteAllSubnodes()
+    {
+        // Go through the list of all subnodes and delete them
+        for (std::list<ClassTreeMaskNode*>::iterator it = this->subnodes_.begin(); it != this->subnodes_.end(); )
+            delete (*(it++));
+
+        // Clear the list
+        this->subnodes_.clear();
+    }
+
+
+    // ###############################
+    // ###  ClassTreeMaskIterator  ###
+    // ###############################
+    /**
+        @brief Constructor: Initializes the iterator by creating a helper-list with the root-node and putting it to the stack.
+        @param node The root-node
+    */
+    ClassTreeMaskIterator::ClassTreeMaskIterator(ClassTreeMaskNode* node)
+    {
+        // Create a list and put the root-note into it
+        std::list<ClassTreeMaskNode*>::iterator it = this->rootlist_.insert(this->rootlist_.end(), node);
+
+        // Put the iterator to the only element of the list and the corresponding end()-iterator on the stack
+        this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>(it, this->rootlist_.end()));
+    }
+
+    /**
+        @brief Destructor: Does nothing.
+    */
+    ClassTreeMaskIterator::~ClassTreeMaskIterator()
+    {
+    }
+
+    /**
+        @brief Iterates through the rule-tree.
+        @return A reference to the iterator itself
+    */
+    const ClassTreeMaskIterator& ClassTreeMaskIterator::operator++()
+    {
+        // Check if the actual node has subnodes
+        if ((*this->nodes_.top().first)->subnodes_.begin() != (*this->nodes_.top().first)->subnodes_.end())
+        {
+            // Yes it has: Push an iterator, pointing at the first subnode, on the stack
+            this->nodes_.push(std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>((*this->nodes_.top().first)->subnodes_.begin(), (*this->nodes_.top().first)->subnodes_.end()));
+        }
+        else
+        {
+            // No subnodes, meaning we reached a leaf: Go to the next node
+            do
+            {
+                // Iterate one step in the current list
+                ++this->nodes_.top().first;
+
+                // Check if we reached the end of the list (the second item in the stored pair always represents the end)
+                if (this->nodes_.top().first == this->nodes_.top().second)
+                {
+                    // Yes we've reached the end: Pop the list-iterator from the stack
+                    this->nodes_.pop();
+
+                    // Continue with the loop, meaning: Try to iterate through the previous list
+                    continue;
+                }
+
+                // If we reached this point, we aren't yet at the end of the list: Leave the loop
+                break;
+            } while (!this->nodes_.empty()); // Stop looping if the stack is empty, meaning: We've iterated to the end
+        }
+
+        // Finally return a reference to the iterator itself
+        return *this;
+    }
+
+    /**
+        @brief Returns a pointer to the ClassTreeMaskNode whereon the iterator points.
+    */
+    ClassTreeMaskNode* ClassTreeMaskIterator::operator*() const
+    {
+        return (*this->nodes_.top().first);
+    }
+
+    /**
+        @brief Returns a pointer to the ClassTreeMaskNode whereon the iterator points.
+    */
+    ClassTreeMaskNode* ClassTreeMaskIterator::operator->() const
+    {
+        return (*this->nodes_.top().first);
+    }
+
+    /**
+        @brief Returns true if the stack is empty, meaning we've reached the end of the tree.
+    */
+    ClassTreeMaskIterator::operator bool() const
+    {
+        return (!this->nodes_.empty());
+    }
+
+    /**
+        @brief Compares the current node with the given one and returns true if they match.
+    */
+    bool ClassTreeMaskIterator::operator==(ClassTreeMaskNode* compare) const
+    {
+        if (!this->nodes_.empty())
+            return ((*this->nodes_.top().first) == compare);
+        else
+            return (compare == nullptr);
+    }
+
+    /**
+        @brief Compares the current node with the given one and returns true if they don't match.
+    */
+    bool ClassTreeMaskIterator::operator!=(ClassTreeMaskNode* compare) const
+    {
+        if (!this->nodes_.empty())
+            return ((*this->nodes_.top().first) != compare);
+        else
+            return (compare != nullptr);
+    }
+
+
+    // ###############################
+    // ###      ClassTreeMask      ###
+    // ###############################
+    /**
+        @brief Constructor: Adds the root-node of the tree with the first rule ("include everything").
+    */
+    ClassTreeMask::ClassTreeMask()
+    {
+        this->root_ = new ClassTreeMaskNode(ClassIdentifier<BaseObject>::getIdentifier(), true);
+    }
+
+    /**
+        @brief Copy-constructor: Adds the root-node of the tree with the first rule ("include everything") and adds all rules from the other mask.
+    */
+    ClassTreeMask::ClassTreeMask(const ClassTreeMask& other)
+    {
+        this->root_ = new ClassTreeMaskNode(ClassIdentifier<BaseObject>::getIdentifier(), true);
+        for (ClassTreeMaskIterator it = other.root_; it; ++it)
+            this->add(it->getClass(), it->isIncluded(), false);
+    }
+
+    /**
+        @brief Destructor: Deletes the root node (which will delete all subnodes too).
+    */
+    ClassTreeMask::~ClassTreeMask()
+    {
+        delete this->root_;
+    }
+
+    /**
+        @brief Adds a new "include" rule for a given subclass to the mask.
+        @param subclass The subclass
+        @param overwrite True = overwrite previously added rules for inheriting classes
+        @param clean True = clean the tree after adding the new rule
+    */
+    void ClassTreeMask::include(const Identifier* subclass, bool overwrite, bool clean)
+    {
+        this->add(subclass, true, overwrite, clean);
+    }
+
+    /**
+        @brief Adds a new "exclude" rule for a given subclass to the mask.
+        @param subclass The subclass
+        @param overwrite True = overwrite previously added rules for inheriting classes
+        @param clean True = clean the tree after adding the new rule
+    */
+    void ClassTreeMask::exclude(const Identifier* subclass, bool overwrite, bool clean)
+    {
+        this->add(subclass, false, overwrite, clean);
+    }
+
+    /**
+        @brief Adds a new rule for a given subclass to the mask.
+        @param subclass The subclass
+        @param bInclude The rule: include (true) or exclude (false)
+        @param overwrite True = overwrite previously added rules for inheriting classes
+        @param clean True = clean the tree after adding the new rule
+    */
+    void ClassTreeMask::add(const Identifier* subclass, bool bInclude, bool overwrite, bool clean)
+    {
+        if (!subclass)
+            return;
+        // Check if the given subclass is a child of our root-class
+        if (subclass->isA(this->root_->getClass()))
+        {
+            // Yes it is: Just add the rule to the three
+            this->add(this->root_, subclass, bInclude, overwrite);
+        }
+        else
+        {
+            // No it's not: Search for classes inheriting from the given class and add the rules for them
+            for (const Identifier* directChild : subclass->getDirectChildren())
+                if (directChild->isA(this->root_->getClass()))
+                    if (overwrite || (!this->nodeExists(directChild))) // If we don't want to overwrite, only add nodes that don't already exist
+                        this->add(this->root_, directChild, bInclude, overwrite);
+        }
+
+        // Clean the rule-tree
+        if (clean)
+            this->clean();
+    }
+
+    /**
+        @brief Adds a new rule for a given subclass to a node of the internal rule-tree (recursive function).
+        @param node The node
+        @param subclass The subclass
+        @param bInclude The rule: include (true) or exclude (false)
+        @param overwrite True = overwrite previously added rules for inheriting classes
+    */
+    void ClassTreeMask::add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite)
+    {
+        if (!subclass)
+            return;
+        // Check if the current node contains exactly the subclass we want to add
+        if (subclass == node->getClass())
+        {
+            // We're at the right place, just change the mask and return
+            node->setIncluded(bInclude, overwrite);
+            return;
+        }
+        else if (subclass->isA(node->getClass()))
+        {
+            // Search for an already existing node, containing the subclass we want to add
+            for (ClassTreeMaskNode* subnode : node->subnodes_)
+            {
+                if (subclass->isA(subnode->getClass()))
+                {
+                    // We've found an existing node -> delegate the work with a recursive function-call and return
+                    this->add(subnode, subclass, bInclude, overwrite);
+                    return;
+                }
+            }
+
+            // There is no existing node satisfying our needs -> we create a new node
+            ClassTreeMaskNode* newnode = new ClassTreeMaskNode(subclass, bInclude);
+
+            // Search for nodes that should actually be subnodes of our new node and erase them
+            for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
+            {
+                if ((*it)->getClass()->isChildOf(subclass))
+                {
+                    // We've found a subnode: add it to the new node and erase it from the current node
+                    if (!overwrite)
+                        newnode->addSubnode(*it);
+                    else
+                        delete (*it);
+
+                    node->subnodes_.erase(it++);
+                }
+                else
+                {
+                    ++it;
+                }
+            }
+
+            // Finally add the new node as a subnode to the current node
+            node->addSubnode(newnode);
+        }
+    }
+
+    /**
+        @brief Adds a new "include" rule for a single subclass. The new rule doesn't change the mask for inheriting classes.
+        @param subclass The subclass
+        @param clean True = clean the tree after adding the new rule
+    */
+    void ClassTreeMask::includeSingle(const Identifier* subclass, bool clean)
+    {
+        this->addSingle(subclass, true, clean);
+    }
+
+    /**
+        @brief Adds a new "exclude" rule for a single subclass. The new rule doesn't change the mask for inheriting classes.
+        @param subclass The subclass
+        @param clean True = clean the tree after adding the new rule
+    */
+    void ClassTreeMask::excludeSingle(const Identifier* subclass, bool clean)
+    {
+        this->addSingle(subclass, false, clean);
+    }
+
+    /**
+        @brief Adds a new rule for a single subclass. The new rule doesn't change the mask for inheriting classes.
+        @param bInclude The rule: include (true) or exclude (false)
+        @param subclass The subclass
+        @param clean True = clean the tree after adding the new rule
+    */
+    void ClassTreeMask::addSingle(const Identifier* subclass, bool bInclude, bool clean)
+    {
+        if (!subclass)
+            return;
+        for (const Identifier* directChild : subclass->getDirectChildren())
+            this->add(directChild, this->isIncluded(directChild), false, false);
+
+        this->add(subclass, bInclude, false, clean);
+    }
+
+    /**
+        @brief Resets the mask to "include everything".
+    */
+    void ClassTreeMask::reset()
+    {
+        delete this->root_;
+        this->root_ = new ClassTreeMaskNode(ClassIdentifier<BaseObject>::getIdentifier(), true);
+    }
+
+    /**
+        @brief Tells if a given subclass is included or not.
+        @param subclass The subclass
+        @return Included (true) or excluded (false)
+    */
+    bool ClassTreeMask::isIncluded(const Identifier* subclass) const
+    {
+        return this->isIncluded(this->root_, subclass);
+    }
+
+    /**
+        @brief Tells if a given subclass of a node in the rule-tree is included or not (recursive function).
+        @param node The node
+        @param subclass The subclass
+        @return Included (true) or excluded (false)
+    */
+    bool ClassTreeMask::isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const
+    {
+        if (!subclass)
+            return false;
+        // Check if the searched subclass is of the same type as the class in the current node or a derivative
+        if (subclass->isA(node->getClass()))
+        {
+            // Check for the special case
+            if (subclass == node->getClass())
+                return node->isIncluded();
+
+            // Go through the list of subnodes and look for a node containing the searched subclass and delegate the request by a recursive function-call.
+            for (ClassTreeMaskNode* subnode : node->subnodes_)
+                if (subclass->isA(subnode->getClass()))
+                    return isIncluded(subnode, subclass);
+
+            // There is no subnode containing our class -> the rule of the current node takes in effect
+            return node->isIncluded();
+        }
+        else
+        {
+            // The class is not included in the mask: return false
+            return false;
+        }
+    }
+
+    /**
+        @brief Tells if a given subclass is excluded or not.
+        @param subclass The subclass
+        @return The inverted rule: Excluded (true) or included (false)
+    */
+    bool ClassTreeMask::isExcluded(const Identifier* subclass) const
+    {
+        return (!this->isIncluded(subclass));
+    }
+
+    /**
+        @brief Removes all unneeded rules that don't change the information of the mask.
+    */
+    void ClassTreeMask::clean()
+    {
+        this->clean(this->root_);
+    }
+
+    /**
+        @brief Removes all unneded rules that don't change the information of a node of a mask (recursive function).
+        @param node The node
+    */
+    void ClassTreeMask::clean(ClassTreeMaskNode* node)
+    {
+        // Iterate through all subnodes of the given node
+        for (std::list<ClassTreeMaskNode*>::iterator it = node->subnodes_.begin(); it != node->subnodes_.end(); )
+        {
+            // Recursive function-call: Clean the subnode
+            this->clean(*it);
+
+            // Now check if the subnode contains the same rule as the current node
+            if ((*it)->isIncluded() == node->isIncluded())
+            {
+                // It does: Move all subnodes of the redundant subnode to the current node
+                node->subnodes_.insert(node->subnodes_.end(), (*it)->subnodes_.begin(), (*it)->subnodes_.end());
+                (*it)->subnodes_.clear();
+
+                // Remove the redundant subnode from the current node
+                delete (*it);
+                node->subnodes_.erase(it++);
+            }
+            else
+            {
+                // The subnode is necessary: Move on to the next subnode
+                ++it;
+            }
+        }
+    }
+
+    /**
+        @brief Checks if a node for the given subclass exists.
+        @param subclass The Identifier of the subclass
+        @return True = the node exists
+    */
+    bool ClassTreeMask::nodeExists(const Identifier* subclass)
+    {
+        for (ClassTreeMaskIterator it = this->root_; it; ++it)
+            if ((*it)->getClass() == subclass)
+                return true;
+
+        return false;
+    }
+
+    /**
+        @brief Assignment operator: Adds all rules of the other mask.
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    ClassTreeMask& ClassTreeMask::operator=(const ClassTreeMask& other)
+    {
+        // Make a copy to avoid troubles with self-assignments (like A = A).
+        ClassTreeMask temp(other);
+
+        // Removes all current rules
+        this->reset();
+
+        // Copy all rules from the other mask
+        for (ClassTreeMaskIterator it = temp.root_; it; ++it)
+            this->add(it->getClass(), it->isIncluded(), false, false);
+
+        // Return a reference to the mask itself
+        return (*this);
+    }
+
+    /**
+        @brief Compares the mask with another mask and returns true if they represent the same logic.
+        @param other The other mask
+        @return True if both masks represent the same logic
+    */
+    bool ClassTreeMask::operator==(const ClassTreeMask& other) const
+    {
+        ClassTreeMask temp1 = other;
+        ClassTreeMask temp2 = (*this);
+
+        temp1.clean();
+        temp2.clean();
+
+        ClassTreeMaskIterator it1 = temp1.root_;
+        ClassTreeMaskIterator it2 = temp2.root_;
+
+        for ( ; it1 && it2; ++it1, ++it2)
+            if (it1->getClass() != it2->getClass())
+                return false;
+
+        return true;
+    }
+
+    /**
+        @brief Compares the mask with another mask and returns true if they represent different logics.
+        @param other The other mask
+        @return True if the masks represent different logics
+    */
+    bool ClassTreeMask::operator!=(const ClassTreeMask& other) const
+    {
+        return (!((*this) == other));
+    }
+
+    /**
+        @brief Prefix operator + does nothing.
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator+() const
+    {
+        return (*this);
+    }
+
+    /**
+        @brief Prefix operator - inverts the mask.
+        @return The inverted mask
+    */
+    ClassTreeMask ClassTreeMask::operator-() const
+    {
+        return (!(*this));
+    }
+
+    /**
+        @brief Adds two masks in the sense of a union (all classes that are included in at least one of the masks will be included in the resulting mask too).
+        @param other The mask to unite with
+        @return The union
+    */
+    ClassTreeMask ClassTreeMask::operator+(const ClassTreeMask& other) const
+    {
+        // Create a new mask
+        ClassTreeMask newmask;
+
+        // Add all nodes from the first mask, calculate the rule with the or-operation
+        for (ClassTreeMaskIterator it = this->root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass), false, false);
+        }
+
+        // Add all nodes from the second mask, calculate the rule with the or-operation
+        for (ClassTreeMaskIterator it = other.root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, this->isIncluded(subclass) or other.isIncluded(subclass), false, false);
+        }
+
+        // Drop all redundant rules
+        newmask.clean();
+
+        // Return the new mask
+        return newmask;
+    }
+
+    /**
+        @brief Intersects two masks (only classes that are included in both masks will be included in the resulting mask too).
+        @param other The mask to intersect with
+        @return The intersection
+    */
+    ClassTreeMask ClassTreeMask::operator*(const ClassTreeMask& other) const
+    {
+        // Create a new mask
+        ClassTreeMask newmask;
+
+        // Add all nodes from the first mask, calculate the rule with the and-operation
+        for (ClassTreeMaskIterator it = this->root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass), false, false);
+        }
+
+        // Add all nodes from the second mask, calculate the rule with the and-operation
+        for (ClassTreeMaskIterator it = other.root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, this->isIncluded(subclass) and other.isIncluded(subclass), false, false);
+        }
+
+        // Drop all redundant rules
+        newmask.clean();
+
+        // Return the new mask
+        return newmask;
+    }
+
+    /**
+        @brief Removes all elements of the second mask from the first mask (all classes that are included in the first mask stay included, except those that are included in the second mask too).
+        @param other The mask to subtract.
+        @return The difference
+    */
+    ClassTreeMask ClassTreeMask::operator-(const ClassTreeMask& other) const
+    {
+        return ((*this) * (!other));
+    }
+
+    /**
+        @brief Inverts the mask (all included classes are now excluded and vice versa).
+        @return The complement
+    */
+    ClassTreeMask ClassTreeMask::operator!() const
+    {
+        // Create a new mask
+        ClassTreeMask newmask;
+
+        // Add all nodes from the other mask, inverting the rules
+        for (ClassTreeMaskIterator it = this->root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, !this->isIncluded(subclass), false, false);
+        }
+
+        // Return the new mask
+        return newmask;
+    }
+
+    /**
+        @brief Unites this mask with another mask.
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator+=(const ClassTreeMask& other)
+    {
+        (*this) = (*this) + other;
+        return (*this);
+    }
+
+    /**
+        @brief Intersects this mask with another mask.
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator*=(const ClassTreeMask& other)
+    {
+        (*this) = (*this) * other;
+        return (*this);
+    }
+
+    /**
+        @brief Subtracts another mask from this mask.
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator-=(const ClassTreeMask& other)
+    {
+        (*this) = (*this) - other;
+        return (*this);
+    }
+
+    /**
+        @brief Intersects two masks (only classes that are included in both masks will be included in the resulting mask too).
+        @param other The mask to intersect with
+        @return The intersection
+    */
+    ClassTreeMask ClassTreeMask::operator&(const ClassTreeMask& other) const
+    {
+        return ((*this) * other);
+    }
+
+    /**
+        @brief Adds two masks in the sense of a union (all classes that are included in at least one of the masks will be included in the resulting mask too).
+        @param other The mask to unite with
+        @return The union
+    */
+    ClassTreeMask ClassTreeMask::operator|(const ClassTreeMask& other) const
+    {
+        return ((*this) + other);
+    }
+
+    /**
+        @brief Joins two masks in the sense of a xor (exclusivity) operation (all classes that are included in exactly one of the masks, but not in both, will be included in the resulting mask too).
+        @param other The mask to join with
+        @return The result
+    */
+    ClassTreeMask ClassTreeMask::operator^(const ClassTreeMask& other) const
+    {
+        // Create a new mask
+        ClassTreeMask newmask;
+
+        // Add all nodes from the first mask, calculate the rule with the xor-operation
+        for (ClassTreeMaskIterator it = this->root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass), false, false);
+        }
+
+        // Add all nodes from the second mask, calculate the rule with the xor-operation
+        for (ClassTreeMaskIterator it = other.root_; it; ++it)
+        {
+            const Identifier* subclass = it->getClass();
+            newmask.add(subclass, this->isIncluded(subclass) xor other.isIncluded(subclass), false, false);
+        }
+
+        // Drop all redundant rules
+        newmask.clean();
+
+        // Return the new mask
+        return newmask;
+    }
+
+    /**
+        @brief Inverts the mask (all included classes are now excluded and vice versa).
+        @return The complement
+    */
+    ClassTreeMask ClassTreeMask::operator~() const
+    {
+        return (!(*this));
+    }
+
+    /**
+        @brief Intersects this mask with another mask (and-operation)
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator&=(const ClassTreeMask& other)
+    {
+        (*this) = (*this) & other;
+        return (*this);
+    }
+
+    /**
+        @brief Unites this mask with another mask (or-operation).
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator|=(const ClassTreeMask& other)
+    {
+        (*this) = (*this) | other;
+        return (*this);
+    }
+
+    /**
+        @brief Joins this mask with another mask with a xor-operation.
+        @param other The other mask
+        @return A reference to the mask itself
+    */
+    const ClassTreeMask& ClassTreeMask::operator^=(const ClassTreeMask& other)
+    {
+        (*this) = (*this) ^ other;
+        return (*this);
+    }
+
+    /**
+        @brief Converts the content of a mask into a human readable string and puts it on the ostream.
+        @param out The ostream
+        @param mask The mask
+        @return A reference to the ostream
+    */
+    std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask)
+    {
+        // Iterate through all rules
+        for (ClassTreeMaskIterator it = mask.root_; it; ++it)
+        {
+            // Calculate the prefix: + means included, - means excluded
+            if (it->isIncluded())
+                out << '+';
+            else
+                out << '-';
+
+            // Put the name of the corresponding class on the stream
+            out << it->getClass()->getName() << ' ';
+        }
+
+        return out;
+    }
+
+
+    // ###################################
+    // ### ClassTreeMaskObjectIterator ###
+    // ###################################
+    /**
+        @brief Initializes the iterator from a given ClassTreeMask.
+        @param mask The mask
+    */
+    ClassTreeMaskObjectIterator& ClassTreeMaskObjectIterator::operator=(const ClassTreeMask& mask)
+    {
+        // Clear everything, use a cleaned copy of the mask
+        this->subclasses_.clear();
+        ClassTreeMask temp = mask;
+        temp.clean();
+
+        // Create the subclass-list by going through the mask-tree, starting with the root-node
+        this->create(temp.root_);
+
+        // Move the subclass-iterator to the beginning of the subclass-list
+        this->subclassIterator_ = this->subclasses_.begin();
+
+        // If there is a first subclass, move the object-iterator to the first object of this class. Else go to the end
+        if (this->subclassIterator_ != this->subclasses_.end())
+            this->objectIterator_ = Context::getRootContext()->getObjectList(this->subclassIterator_->first)->begin();
+        else
+            this->objectIterator_ = ObjectList<BaseObject>().end();
+
+        // Check if the iterator points on a valid object. If not, go to the next object by calling ++
+        if (!this->objectIterator_ || (this->subclassIterator_->second && !this->objectIterator_->isExactlyA(this->subclassIterator_->first)))
+            this->operator++();
+
+        return (*this);
+    }
+
+    /**
+        @brief Iterate to the next object (if any).
+        @return The iterator itself
+    */
+    const ClassTreeMaskObjectIterator& ClassTreeMaskObjectIterator::operator++()
+    {
+        if (this->objectIterator_)
+        {
+            // The iterator points on a valid object, therefore we also have a valid subclass-iterator at the moment
+            do
+            {
+                // Go to the next object
+                ++this->objectIterator_;
+
+                while (!this->objectIterator_)
+                {
+                    // We reached the end of the current objectlist - go to the next class
+                    ++this->subclassIterator_;
+
+                    // Check if there really is a next class. If yes, move the object-iterator to the first object
+                    if (this->subclassIterator_ != this->subclasses_.end())
+                        this->objectIterator_ = Context::getRootContext()->getObjectList(this->subclassIterator_->first)->begin();
+                    else
+                        return (*this);
+                }
+
+            // Repeat this until we reach a valid object or the end
+            } while (this->subclassIterator_->second && !this->objectIterator_->isExactlyA(this->subclassIterator_->first));
+        }
+        return (*this);
+    }
+
+    /**
+        @brief Recursive function to create the Iterators subclass-list by going through the node-tree of the mask.
+        @param node The current node
+    */
+    void ClassTreeMaskObjectIterator::create(ClassTreeMaskNode* node)
+    {
+        // Add the class of this node to the list, if the class is included
+        if (node->isIncluded())
+        {
+            // If there are some subnodes, the bool is "true", meaning we have to check for the exact clss when iterating
+            if (node->hasSubnodes())
+                this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(node->getClass(), true));
+            else
+                this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(node->getClass(), false));
+        }
+
+        // Now check if the node has subnodes
+        if (node->hasSubnodes())
+        {
+            // Get all _direct_ children of the nodes class
+            std::set<const Identifier*> directChildren = node->getClass()->getDirectChildren();
+
+            // Iterate through all subnodes
+            for (ClassTreeMaskNode* subnode : node->subnodes_)
+            {
+                // Recursive call to this function with the subnode
+                this->create(subnode);
+
+                // Only execute the following code if the current node is included, meaning some of the subnodes might be included too
+                if (node->isIncluded())
+                {
+                    scanChildren: // This is a label for goto
+
+                    // Iterate through all direct children
+                    for (std::set<const Identifier*>::iterator it = directChildren.begin(); it != directChildren.end(); ++it)
+                    {
+                        // Check if the subnode (it1) is a child of the directChild (it2)
+                        if (subnode->getClass()->isA(*it))
+                        {
+                            // Yes it is - remove the directChild (it2) from the list, because it will already be handled by a recursive call to the create() function
+                            directChildren.erase(it);
+
+                            // Check if the removed directChild was exactly the subnode
+                            if (!subnode->getClass()->isExactlyA(*it))
+                            {
+                                // No, it wasn't exactly the subnode - therefore there are some classes between
+
+                                // Add the previously removed directChild (it2) to the subclass-list
+                                this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(*it, true));
+
+                                // Insert all directChildren of the directChild
+                                directChildren.insert((*it)->getDirectChildren().begin(), (*it)->getDirectChildren().end());
+
+                                // Restart the scan with the expanded set of directChildren
+                                goto scanChildren;
+                            }
+                            break;
+                        }
+                    }
+                }
+            }
+
+            // Now add all directChildren which don't have subnodes on their own to the subclass-list
+            // The bool is "false", meaning they have no subnodes and therefore need no further checks
+            if (node->isIncluded())
+                for (const Identifier* directChild : directChildren)
+                    this->subclasses_.insert(this->subclasses_.end(), std::pair<const Identifier*, bool>(directChild, false));
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/ClassTreeMask.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ClassTreeMask.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ClassTreeMask.h	(revision 11817)
@@ -0,0 +1,306 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Class
+    @brief Declaration of the ClassTreeMask, ClassTreeMaskNode, and ClassTreeMaskIterator classes.
+
+    ClassTreeMask is a class to define a mask of the class-tree beginning with orxonox::BaseObject.
+    You can include or exclude classes by calling the corresponding functions with the
+    orxonox::Identifier of the class. This mask can then be used to filter out objects that
+    are instances of classes which aren't included in the tree, for example when Loading a
+    level file or if a Trigger should be triggered by only a few classes.
+
+    See the description of orxonox::ClassTreeMask for a short example.
+
+    You can work with a ClassTreeMask in the sense of the set-theory, meaning that you can create
+    unions, intersections, complements and differences by using overloaded operators.
+
+    @par Tree structure
+
+    The ClassTreeMask is internally represented by a tree. The nodes in the tree are
+    ClassTreeMaskNodes, containing the rule (included or excluded) for this class and all
+    subclasses and a list of all subnodes. To minimize the size, the tree contains only
+    nodes changing the mask. By adding new rules, the tree gets reordered dynamically.
+
+    Adding a new rule overwrites all rules assigned to inherited classes. Use <tt>overwrite = false</tt>
+    if you don't like this feature. Useless rules that don't change the information of the mask
+    aren't saved in the internal tree. Use <tt>clean = false</tt> if you still want to save them.
+
+    With <tt>overwrite = false</tt> and <tt>clean = false</tt> it doesn't matter in which order
+    you create the mask. You can manually drop useless rules from the tree by calling
+    @ref orxonox::ClassTreeMask::clean() "clean()".
+
+    @par Objects
+
+    To iterate through all objects of the classes that were included by a ClassTreeMask,
+    use orxonox::ClassTreeMaskObjectIterator. The description of this class also contains
+    a short example of how to use it.
+*/
+
+#ifndef _ClassTreeMask_H__
+#define _ClassTreeMask_H__
+
+#include "CorePrereqs.h"
+
+#include <list>
+#include <stack>
+#include "BaseObject.h"
+#include "object/Iterator.h"
+#include "class/Identifier.h"
+
+namespace orxonox
+{
+    // ###################################
+    // ###      ClassTreeMaskNode      ###
+    // ###################################
+    /**
+        @brief The ClassTreeMaskNode is a node in the internal tree of the ClassTreeMask, containing the rules of the mask.
+
+        The ClassTreeMaskNode is used to store the rule (included or excluded) for a given
+        class (described by the corresponding Identifier). The nodes are used in the internal
+        tree of ClassTreeMask. To build a tree, they store a list of all subnodes.
+    */
+    class _CoreExport ClassTreeMaskNode
+    {
+        friend class ClassTreeMask;
+        friend class ClassTreeMaskIterator;
+        friend class ClassTreeMaskObjectIterator;
+
+        public:
+            ClassTreeMaskNode(const Identifier* subclass, bool bIncluded = true);
+            ~ClassTreeMaskNode();
+
+            void include(bool overwrite = true);
+            void exclude(bool overwrite = true);
+            void setIncluded(bool bIncluded, bool overwrite = true);
+
+            void addSubnode(ClassTreeMaskNode* subnode);
+
+            /// Tells if the rule is "included" or not.
+            inline bool isIncluded() const { return this->bIncluded_; }
+            /// Tells if the rule is "excluded" or not.
+            inline bool isExcluded() const { return (!this->bIncluded_); }
+
+            /// Returns the Identifier of the class the rule refers to.
+            inline const Identifier* getClass() const { return this->subclass_; }
+
+            /// Returns true if the node has some subnodes.
+            inline bool hasSubnodes() const { return !this->subnodes_.empty(); }
+
+        private:
+            void deleteAllSubnodes();
+
+            const Identifier* subclass_;                ///< The Identifier of the subclass the rule refers to
+            bool bIncluded_;                            ///< The rule: included or excluded
+            std::list<ClassTreeMaskNode*> subnodes_;    ///< A list containing all subnodes of this node
+    };
+
+
+    // ###################################
+    // ###    ClassTreeMaskIterator    ###
+    // ###################################
+    /**
+        @brief The ClassTreeMaskIterator moves through all ClassTreeMaskNodes of the internal tree of a ClassTreeMask which contains the rules.
+
+        Because of the complicated shape of the internal rule-tree of ClassTreeMask, an
+        iterator is used to move through all nodes of the tree. It starts with the BaseObject
+        and moves on to the first subclass until it reaches a leaf of the tree. Then the
+        iterator moves one step back and iterates to the second subclass. If there are no more
+        subclasses, it steps another step back, and so on.
+
+        Example: A and B are children of BaseObject, A1 and A2 are children of A, B1 and B2 are children of B.
+        The ClassTreeMaskIterator would move trough the tree in the following order:
+        BaseObject, A, A1, A2, B, B1, B2.
+
+        Note that the iterator doesn't move trough the whole class-tree, but only through the
+        internal tree of the mask, containing the minimal needed set of nodes to describe the mask.
+    */
+    class _CoreExport ClassTreeMaskIterator
+    {
+        public:
+            ClassTreeMaskIterator(ClassTreeMaskNode* node);
+            ~ClassTreeMaskIterator();
+
+            const ClassTreeMaskIterator& operator++();
+            ClassTreeMaskNode* operator*() const;
+            ClassTreeMaskNode* operator->() const;
+            explicit operator bool() const;
+            bool operator==(ClassTreeMaskNode* compare) const;
+            bool operator!=(ClassTreeMaskNode* compare) const;
+
+        private:
+            std::stack<std::pair<std::list<ClassTreeMaskNode*>::iterator, std::list<ClassTreeMaskNode*>::iterator>> nodes_;    ///< A stack to store list-iterators
+            std::list<ClassTreeMaskNode*> rootlist_;                                                                            ///< A list for internal use (it only stores the root-node)
+    };
+
+
+    // ###################################
+    // ###        ClassTreeMask        ###
+    // ###################################
+    /**
+        @brief The ClassTreeMask is a set of rules, containing the information for each class whether it's included or not.
+
+        With a ClassTreeMask, you can include or exclude subtrees of the class-tree, starting
+        with a given subclass, described by the corresponding Identifier. To minimize the size
+        of the mask, the mask saves only relevant rules. But you can manually add rules that
+        don't change the information of the mask by using <tt>clean = false</tt>. If you want to drop
+        useless rules, call the clean() function.
+
+        Example:
+        @code
+        ClassTreeMask mymask;
+        mymask.exclude(Class(A));
+        mymask.exclude(Class(B));
+        mymask.include(Class(ChildOfA));
+        @endcode
+
+        In this example, the classes A and B are excluded from the mask, but one of the child
+        classes of A is included again.
+    */
+    class _CoreExport ClassTreeMask
+    {
+        friend class ClassTreeMaskObjectIterator;
+
+        public:
+            ClassTreeMask();
+            ClassTreeMask(const ClassTreeMask& other);
+            ~ClassTreeMask();
+
+            void include(const Identifier* subclass, bool overwrite = true, bool clean = true);
+            void exclude(const Identifier* subclass, bool overwrite = true, bool clean = true);
+            void add(const Identifier* subclass, bool bInclude, bool overwrite = true, bool clean = true);
+
+            void includeSingle(const Identifier* subclass, bool clean = true);
+            void excludeSingle(const Identifier* subclass, bool clean = true);
+            void addSingle(const Identifier* subclass, bool bInclude, bool clean = true);
+
+            void reset();
+            void clean();
+
+            bool isIncluded(const Identifier* subclass) const;
+            bool isExcluded(const Identifier* subclass) const;
+
+            /// Begin of the ClassTreeMaskObjectIterator.
+            inline const ClassTreeMask& begin() const { return (*this); }
+            /// End of the ClassTreeMaskObjectIterator.
+            inline BaseObject*          end()   const { return nullptr; }
+
+            ClassTreeMask& operator=(const ClassTreeMask& other);
+
+            bool operator==(const ClassTreeMask& other) const;
+            bool operator!=(const ClassTreeMask& other) const;
+
+            const ClassTreeMask& operator+() const;
+            ClassTreeMask operator-() const;
+
+            ClassTreeMask operator+(const ClassTreeMask& other) const;
+            ClassTreeMask operator*(const ClassTreeMask& other) const;
+            ClassTreeMask operator-(const ClassTreeMask& other) const;
+            ClassTreeMask operator!() const;
+
+            const ClassTreeMask& operator+=(const ClassTreeMask& other);
+            const ClassTreeMask& operator*=(const ClassTreeMask& other);
+            const ClassTreeMask& operator-=(const ClassTreeMask& other);
+
+            ClassTreeMask operator&(const ClassTreeMask& other) const;
+            ClassTreeMask operator|(const ClassTreeMask& other) const;
+            ClassTreeMask operator^(const ClassTreeMask& other) const;
+            ClassTreeMask operator~() const;
+
+            const ClassTreeMask& operator&=(const ClassTreeMask& other);
+            const ClassTreeMask& operator|=(const ClassTreeMask& other);
+            const ClassTreeMask& operator^=(const ClassTreeMask& other);
+
+            friend std::ostream& operator<<(std::ostream& out, const ClassTreeMask& mask);
+
+        private:
+            void add(ClassTreeMaskNode* node, const Identifier* subclass, bool bInclude, bool overwrite = true);
+            bool isIncluded(ClassTreeMaskNode* node, const Identifier* subclass) const;
+            void clean(ClassTreeMaskNode* node);
+            bool nodeExists(const Identifier* subclass);
+
+            ClassTreeMaskNode* root_;   ///< The root-node of the internal rule-tree, usually BaseObject
+    };
+
+
+    // ###################################
+    // ### ClassTreeMaskObjectIterator ###
+    // ###################################
+    /**
+        @brief The ClassTreeMaskObjectIterator iterates through all objects of the classes that were included by a ClassTreeMask.
+
+        This is done the following way:
+        @code
+        ClassTreeMask mask;
+        for (ClassTreeMaskObjectIterator it = mask.begin(); it != mask.end(); ++it)
+            it->doSomething();
+        @endcode
+
+        @note The ClassTreeMaskObjectIterator handles all objects as BaseObjects. If
+              you want to use another class, you should use a dynamic_cast.
+
+        The performance of ClassTreeMaskObjectIterator is good as long as you don't exclude
+        subclasses of included classes. Of course you can still exlucde subclasses, but
+        if this is done more often, we need a new implementation using a second ObjectList
+        in the Identifier, containing all objects of exactly one class.
+    */
+    class _CoreExport ClassTreeMaskObjectIterator
+    {
+        public:
+            /// Default-constructor: Does nothing.
+            inline ClassTreeMaskObjectIterator() = default;
+            /// Copy-Constructor: Initializes the iterator from another ClassTreeMask.
+            inline ClassTreeMaskObjectIterator(const ClassTreeMask& mask) { (*this) = mask; }
+
+            ClassTreeMaskObjectIterator& operator=(const ClassTreeMask& mask);
+
+            const ClassTreeMaskObjectIterator& operator++();
+
+            /// Returns true if the ClassTreeMaskObjectIterator points at the given object.
+            inline bool operator==(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) == pointer) || (!this->objectIterator_ && pointer == nullptr); }
+            /// Returns true if the ClassTreeMaskObjectIterator doesn't point at the given object.
+            inline bool operator!=(BaseObject* pointer) const { return (this->objectIterator_ && (*this->objectIterator_) != pointer) || (!this->objectIterator_ && pointer != nullptr); }
+            /// Returns true if the ClassTreeMaskObjectIterator hasn't already reached the end.
+            inline explicit operator bool() const { return this->objectIterator_.operator bool(); }
+            /// Returns the object the ClassTreeMaskObjectIterator currently points at.
+            inline BaseObject* operator*() const { return (*this->objectIterator_); }
+            /// Returns the object the ClassTreeMaskObjectIterator currently points at.
+            inline BaseObject* operator->() const { return (*this->objectIterator_); }
+
+        private:
+            void create(ClassTreeMaskNode* node);
+
+            std::list<std::pair<const Identifier*, bool>>           subclasses_;       ///< A list of all Identifiers through which objects the iterator should iterate
+            std::list<std::pair<const Identifier*, bool>>::iterator subclassIterator_; ///< The current class of the iterator
+            Iterator<BaseObject>                                    objectIterator_;   ///< The current object of the iterator
+    };
+}
+
+#endif /* _ClassTreeMask_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/ConfigurablePaths.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ConfigurablePaths.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ConfigurablePaths.cc	(revision 11817)
@@ -0,0 +1,184 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ConfigurablePaths.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <cstdio>
+#include <vector>
+#include <boost/filesystem.hpp>
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN
+#  endif
+#  include <windows.h>
+#  undef min
+#  undef max
+#elif defined(ORXONOX_PLATFORM_APPLE)
+#  include <sys/param.h>
+#  include <mach-o/dyld.h>
+#else /* Linux */
+#  include <sys/types.h>
+#  include <unistd.h>
+#endif
+
+#include "SpecialConfig.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "commandline/CommandLineIncludes.h"
+#include "core/ApplicationPaths.h"
+
+// Differentiate Boost Filesystem v2 and v3
+#if (BOOST_FILESYSTEM_VERSION < 3)
+#  define BF_GENERIC_STRING string
+#else
+#  define BF_GENERIC_STRING generic_string
+#endif
+
+namespace orxonox
+{
+    namespace bf = boost::filesystem;
+
+    //! Static pointer to the singleton
+    ConfigurablePaths* ConfigurablePaths::singletonPtr_s  = nullptr;
+
+    SetCommandLineArgument(externalDataPath, "").information("Path to the external data files");
+    SetCommandLineArgument(writingPathSuffix, "").information("Additional subfolder for config and log files");
+
+    ConfigurablePaths::ConfigurablePaths()
+        : dataPath_(*(new bf::path()))
+        , externalDataPath_(*(new bf::path()))
+        , configPath_(*(new bf::path()))
+        , logPath_(*(new bf::path()))
+    {
+    }
+
+    ConfigurablePaths::~ConfigurablePaths()
+    {
+        delete &dataPath_;
+        delete &externalDataPath_;
+        delete &configPath_;
+        delete &logPath_;
+    }
+
+    void ConfigurablePaths::setConfigurablePaths(const ApplicationPaths& applicationPaths)
+    {
+        if (applicationPaths.buildDirectoryRun())
+        {
+            dataPath_         = specialConfig::dataDevDirectory;
+            configPath_       = specialConfig::configDevDirectory;
+            logPath_          = specialConfig::logDevDirectory;
+
+            // Check for data path override by the command line
+            if (!CommandLineParser::getArgument("externalDataPath")->hasDefaultValue())
+                externalDataPath_ = CommandLineParser::getValue("externalDataPath").get<std::string>();
+            else
+                externalDataPath_ = specialConfig::externalDataDevDirectory;
+        }
+        else
+        {
+
+#ifdef INSTALL_COPYABLE // --> relative paths
+
+            // Using paths relative to the install prefix, complete them
+            dataPath_   = applicationPaths.getRootPath() / specialConfig::defaultDataPath;
+            configPath_ = applicationPaths.getRootPath() / specialConfig::defaultConfigPath;
+            logPath_    = applicationPaths.getRootPath() / specialConfig::defaultLogPath;
+
+#else
+
+            dataPath_  = specialConfig::dataInstallDirectory;
+
+            // Get user directory
+#ifdef ORXONOX_PLATFORM_UNIX
+            char* userDataPathPtr(getenv("HOME"));
+#else
+            char* userDataPathPtr(getenv("APPDATA"));
+#endif
+            if (userDataPathPtr == nullptr)
+                ThrowException(General, "Could not retrieve user data path.");
+            bf::path userDataPath(userDataPathPtr);
+            userDataPath /= ".orxonox";
+
+            configPath_ = userDataPath / specialConfig::defaultConfigPath;
+            logPath_    = userDataPath / specialConfig::defaultLogPath;
+
+#endif
+
+        }
+
+        // Option to put all the config and log files in a separate folder
+        if (!CommandLineParser::getArgument("writingPathSuffix")->hasDefaultValue())
+        {
+            const std::string& directory(CommandLineParser::getValue("writingPathSuffix").get<std::string>());
+            configPath_ = configPath_ / directory;
+            logPath_    = logPath_    / directory;
+        }
+
+        // Create directories to avoid problems when opening files in non existent folders.
+        std::vector<std::pair<bf::path, std::string>> directories;
+        directories.emplace_back(bf::path(configPath_), std::string("config"));
+        directories.emplace_back(bf::path(logPath_), std::string("log"));
+
+        for (std::vector<std::pair<bf::path, std::string>>::iterator it = directories.begin();
+            it != directories.end(); ++it)
+        {
+            if (bf::exists(it->first) && !bf::is_directory(it->first))
+            {
+                ThrowException(General, std::string("The ") + it->second + " directory has been preoccupied by a file! \
+                                         Please remove " + it->first.BF_GENERIC_STRING());
+            }
+            if (bf::create_directories(it->first)) // function may not return true at all (bug?)
+            {
+                orxout(internal_info) << "Created " << it->second << " directory" << endl;
+            }
+        }
+    }
+
+    /*static*/ std::string ConfigurablePaths::getDataPathString()
+    {
+        return getInstance().dataPath_.BF_GENERIC_STRING() + '/';
+    }
+
+    /*static*/ std::string ConfigurablePaths::getExternalDataPathString()
+    {
+        return getInstance().externalDataPath_.BF_GENERIC_STRING() + '/';
+    }
+
+    /*static*/ std::string ConfigurablePaths::getConfigPathString()
+    {
+        return getInstance().configPath_.BF_GENERIC_STRING() + '/';
+    }
+
+    /*static*/ std::string ConfigurablePaths::getLogPathString()
+    {
+        return getInstance().logPath_.BF_GENERIC_STRING() + '/';
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/ConfigurablePaths.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ConfigurablePaths.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ConfigurablePaths.h	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Management Resources
+*/
+
+#ifndef _ConfigurablePaths_H__
+#define _ConfigurablePaths_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include "util/Singleton.h"
+
+//tolua_begin
+namespace orxonox
+{
+//tolua_end
+    /**
+    @brief
+        The ConfigurablePaths class is a singleton used to configure different paths.
+    @details
+        The class provides information about the data, config, and log path.
+    @remarks
+        Not all paths are always available:
+        - externalData only for development builds in the build tree
+    */
+    class _CoreExport ConfigurablePaths //tolua_export
+        : public Singleton<ConfigurablePaths>
+    { //tolua_export
+        friend class Singleton<ConfigurablePaths>;
+
+        public:
+            ConfigurablePaths();
+            ~ConfigurablePaths();
+
+            //! Returns the path to the data files as boost::filesystem::path
+            static const boost::filesystem::path& getDataPath()
+                { return getInstance().dataPath_; }
+            //! Returns the path to the external data files as boost::filesystem::path
+            static const boost::filesystem::path& getExternalDataPath()
+                { return getInstance().externalDataPath_; }
+            //! Returns the path to the config files as boost::filesystem::path
+            static const boost::filesystem::path& getConfigPath()
+                { return getInstance().configPath_; }
+            //! Returns the path to the log files as boost::filesystem::path
+            static const boost::filesystem::path& getLogPath()
+                { return getInstance().logPath_; }
+
+            //! Returns the path to the data files as std::string
+            static std::string getDataPathString();
+            //! Returns the path to the external data files as std::string
+            static std::string getExternalDataPathString();
+            //! Returns the path to the config files as std::string
+            static std::string getConfigPathString(); //tolua_export
+            //! Returns the path to the log files as std::string
+            static std::string getLogPathString();
+
+            /**
+            @brief
+                Sets config, log and media path and creates the folders if necessary.
+            @throws
+                GeneralException
+            */
+            void setConfigurablePaths(const ApplicationPaths& applicationPaths);
+
+        private:
+            // non-copyable:
+            ConfigurablePaths(const ConfigurablePaths&) = delete;
+            ConfigurablePaths& operator=(const ConfigurablePaths&) = delete;
+
+            boost::filesystem::path& dataPath_;              //!< Path to the data files folder
+            boost::filesystem::path& externalDataPath_;      //!< Path to the external data files folder
+            boost::filesystem::path& configPath_;            //!< Path to the config files folder
+            boost::filesystem::path& logPath_;               //!< Path to the log files folder
+
+            static ConfigurablePaths* singletonPtr_s;
+    }; //tolua_export
+} //tolua_export
+
+#endif /* _ConfigurablePaths_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Core.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Core.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Core.cc	(revision 11817)
@@ -0,0 +1,494 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the Core singleton with its global variables (avoids boost include)
+*/
+
+#include "Core.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <ctime>
+#include <fstream>
+#include <vector>
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+#  ifndef WIN32_LEAN_AND_MEAN
+#    define WIN32_LEAN_AND_MEAN
+#  endif
+#  include <windows.h>
+#  undef min
+#  undef max
+#endif
+
+#include "util/Clock.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/SignalHandler.h"
+#include "util/output/LogWriter.h"
+#include "util/output/OutputManager.h"
+#include "core/singleton/Scope.h"
+#include "ApplicationPaths.h"
+#include "ConfigurablePaths.h"
+#include "commandline/CommandLineIncludes.h"
+#include "config/ConfigFileManager.h"
+#include "GameMode.h"
+#include "GraphicsManager.h"
+#include "GUIManager.h"
+#include "Language.h"
+#include "Loader.h"
+#include "LuaState.h"
+#include "command/IOConsole.h"
+#include "command/TclBind.h"
+#include "command/TclThreadManager.h"
+#include "input/InputManager.h"
+#include "object/ObjectList.h"
+#include "module/DynLibManager.h"
+#include "module/ModuleInstance.h"
+#include "module/StaticInitializationManager.h"
+#include "module/PluginManager.h"
+#include "CoreStaticInitializationHandler.h"
+#include "UpdateListener.h"
+
+namespace orxonox
+{
+    //! Static pointer to the singleton
+    Core* Core::singletonPtr_s  = nullptr;
+
+    SetCommandLineArgument(settingsFile, "orxonox.ini").information("THE configuration file");
+#if !defined(ORXONOX_PLATFORM_APPLE) && !defined(ORXONOX_USE_WINMAIN)
+    SetCommandLineSwitch(noIOConsole).information("Use this if you don't want to use the IOConsole (for instance for Lua debugging)");
+#endif
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+    SetCommandLineArgument(limitToCPU, 0).information("Limits the program to one CPU/core (1, 2, 3, etc.). Default is off = 0.");
+#endif
+
+    SetCommandLineArgument(generateDoc, "")
+        .information("Generates a Doxygen file from things like SetConsoleCommand");
+
+    Core::Core(const std::string& cmdLine)
+        : applicationPaths_(nullptr)
+        , configurablePaths_(nullptr)
+        , dynLibManager_(nullptr)
+        , signalHandler_(nullptr)
+        , configFileManager_(nullptr)
+        , languageInstance_(nullptr)
+        , loaderInstance_(nullptr)
+        , ioConsole_(nullptr)
+        , tclBind_(nullptr)
+        , tclThreadManager_(nullptr)
+        , rootScope_(nullptr)
+        , graphicsManager_(nullptr)
+        , inputManager_(nullptr)
+        , guiManager_(nullptr)
+        , graphicsScope_(nullptr)
+        , bGraphicsLoaded_(false)
+        , staticInitHandler_(nullptr)
+        , pluginManager_(nullptr)
+        , rootModule_(nullptr)
+        , config_(nullptr)
+        , destructionHelper_(this)
+    {
+        orxout(internal_status) << "initializing Core object..." << endl;
+
+        // Set the hard coded fixed paths
+        this->applicationPaths_ = new ApplicationPaths();
+
+        // Create a new dynamic library manager
+        this->dynLibManager_ = new DynLibManager();
+
+        // create handler for static initialization
+        new StaticInitializationManager(); // create singleton
+        this->staticInitHandler_ = new CoreStaticInitializationHandler();
+        StaticInitializationManager::getInstance().addHandler(this->staticInitHandler_);
+
+        // load root module (all libraries which are linked to the executable, including core, network, and orxonox)
+        this->rootModule_ = ModuleInstance::getCurrentModuleInstance();
+        StaticInitializationManager::getInstance().loadModule(this->rootModule_);
+
+        // Parse command line arguments AFTER the modules have been loaded (static code!)
+        CommandLineParser::parse(cmdLine);
+
+        // Set configurable paths like log, config and media
+        this->configurablePaths_ = new ConfigurablePaths();
+        this->configurablePaths_->setConfigurablePaths(ApplicationPaths::getInstance());
+
+        orxout(internal_info) << "Root path:       " << ApplicationPaths::getRootPathString() << endl;
+        orxout(internal_info) << "Executable path: " << ApplicationPaths::getExecutablePathString() << endl;
+        orxout(internal_info) << "Modules path:    " << ApplicationPaths::getModulePathString() << endl;
+        orxout(internal_info) << "Plugins path:    " << ApplicationPaths::getPluginPathString() << endl;
+
+        orxout(internal_info) << "Data path:       " << ConfigurablePaths::getDataPathString() << endl;
+        orxout(internal_info) << "Ext. data path:  " << ConfigurablePaths::getExternalDataPathString() << endl;
+        orxout(internal_info) << "Config path:     " << ConfigurablePaths::getConfigPathString() << endl;
+        orxout(internal_info) << "Log path:        " << ConfigurablePaths::getLogPathString() << endl;
+
+        // create a signal handler
+        // This call is placed as soon as possible, but after the directories are set
+        this->signalHandler_ = new SignalHandler();
+        this->signalHandler_->doCatch(ApplicationPaths::getExecutablePathString(), ConfigurablePaths::getLogPathString() + "orxonox_crash.log");
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+        // limit the main thread to the first core so that QueryPerformanceCounter doesn't jump
+        // do this after ogre has initialised. Somehow Ogre changes the settings again (not through
+        // the timer though).
+        int limitToCPU = CommandLineParser::getValue("limitToCPU");
+        if (limitToCPU > 0)
+            setThreadAffinity(static_cast<unsigned int>(limitToCPU));
+#endif
+
+        // Manage ini files and set the default settings file (usually orxonox.ini)
+        orxout(internal_info) << "Loading config:" << endl;
+        this->configFileManager_ = new ConfigFileManager();
+        this->configFileManager_->setFilename(ConfigFileType::Settings,
+            CommandLineParser::getValue("settingsFile").get<std::string>());
+
+        // Required as well for the config values
+        orxout(internal_info) << "Loading language:" << endl;
+        this->languageInstance_ = new Language();
+
+        // initialize root context
+        Context::setRootContext(new Context(nullptr));
+
+        // Do this soon after the ConfigFileManager has been created to open up the
+        // possibility to configure everything below here
+        orxout(internal_info) << "configuring Core" << endl;
+        this->config_ = new CoreConfig();
+
+        // Set the correct log path and rewrite the log file with the correct log levels
+        OutputManager::getInstance().getLogWriter()->setLogDirectory(ConfigurablePaths::getLogPathString());
+
+#if !defined(ORXONOX_PLATFORM_APPLE) && !defined(ORXONOX_USE_WINMAIN)
+        // Create persistent IO console
+        if (CommandLineParser::getValue("noIOConsole").get<bool>() == false && this->config_->getStartIOConsole())
+        {
+            orxout(internal_info) << "creating IO console" << endl;
+            this->ioConsole_ = new IOConsole();
+        }
+#endif
+
+        // creates the class hierarchy for all classes with factories
+        orxout(internal_info) << "creating class hierarchy" << endl;
+        this->staticInitHandler_->initInstances(this->rootModule_);
+        this->staticInitHandler_->setInitInstances(true);
+
+        // Create plugin manager and search for plugins
+        this->pluginManager_ = new PluginManager();
+        this->pluginManager_->findPlugins();
+
+        // Loader
+        this->loaderInstance_ = new Loader();
+
+        // Load OGRE excluding the renderer and the render window
+        orxout(internal_info) << "creating GraphicsManager:" << endl;
+        this->graphicsManager_ = new GraphicsManager(false);
+
+        // initialise Tcl
+        this->tclBind_ = new TclBind(ConfigurablePaths::getDataPathString());
+        this->tclThreadManager_ = new TclThreadManager(tclBind_->getTclInterpreter());
+
+        // Create singletons that always exist (in other libraries)
+        orxout(internal_info) << "creating root scope:" << endl;
+        this->rootScope_ = new Scope<ScopeID::ROOT>();
+
+        // Generate documentation instead of normal run?
+        std::string docFilename;
+        CommandLineParser::getValue("generateDoc", &docFilename);
+        if (!docFilename.empty())
+        {
+            std::ofstream docFile(docFilename.c_str());
+            if (docFile.is_open())
+            {
+                CommandLineParser::generateDoc(docFile);
+                docFile.close();
+            }
+            else
+                orxout(internal_error) << "Could not open file for documentation writing" << endl;
+        }
+
+        orxout(internal_status) << "finished initializing Core object" << endl;
+    }
+
+    void Core::destroy()
+    {
+        orxout(internal_status) << "destroying Core object..." << endl;
+
+        safeObjectDelete(&graphicsScope_);
+        safeObjectDelete(&guiManager_);
+        safeObjectDelete(&inputManager_);
+        safeObjectDelete(&graphicsManager_);
+        safeObjectDelete(&rootScope_);
+        safeObjectDelete(&tclThreadManager_);
+        safeObjectDelete(&tclBind_);
+        safeObjectDelete(&ioConsole_);
+        safeObjectDelete(&loaderInstance_);
+        safeObjectDelete(&config_);
+        safeObjectDelete(&languageInstance_);
+        safeObjectDelete(&configFileManager_);
+        safeObjectDelete(&signalHandler_);
+        safeObjectDelete(&pluginManager_);
+        Context::getRootContext()->unregisterObject(); // unregister context from object lists - otherwise the root context would be destroyed while unloading the root module
+        if (this->rootModule_)
+        {
+            StaticInitializationManager::getInstance().unloadModule(this->rootModule_);
+            this->rootModule_->deleteAllStaticallyInitializedInstances();
+        }
+        if (this->staticInitHandler_)
+            StaticInitializationManager::getInstance().removeHandler(this->staticInitHandler_);
+        Context::destroyRootContext();
+        safeObjectDelete(&rootModule_);
+        safeObjectDelete(&staticInitHandler_);
+        delete &StaticInitializationManager::getInstance();
+        safeObjectDelete(&dynLibManager_);
+        safeObjectDelete(&configurablePaths_);
+        safeObjectDelete(&applicationPaths_);
+
+        orxout(internal_status) << "finished destroying Core object" << endl;
+    }
+
+    void Core::loadModules()
+    {
+        orxout(internal_info) << "Loading modules:" << endl;
+
+        const std::map<std::string, std::string>& modulePaths = ApplicationPaths::getInstance().getModulePaths();
+        for (const std::pair<std::string, std::string>& modulePath : modulePaths)
+        {
+            ModuleInstance* module = new ModuleInstance(modulePath.second);
+            this->loadModule(module);
+            this->modules_.push_back(module);
+        }
+
+        orxout(internal_info) << "finished loading modules" << endl;
+    }
+
+    void Core::loadModule(ModuleInstance* module)
+    {
+        orxout(internal_info) << "Loading module " << module->getLibraryName() << "..." << endl;
+
+        try
+        {
+            ModuleInstance::setCurrentModuleInstance(module);
+            DynLib* dynLib = this->dynLibManager_->load(module->getLibraryName());
+            module->setDynLib(dynLib);
+
+            StaticInitializationManager::getInstance().loadModule(module);
+        }
+        catch (...)
+        {
+            orxout(user_error) << "Couldn't load module \"" << module->getLibraryName() << "\": " << Exception::handleMessage() << endl;
+        }
+    }
+
+    void Core::unloadModules()
+    {
+        for (ModuleInstance* module : this->modules_)
+        {
+            this->unloadModule(module);
+            delete module;
+        }
+        this->modules_.clear();
+    }
+
+    void Core::unloadModule(ModuleInstance* module)
+    {
+        orxout(internal_info) << "Unloading module " << module->getLibraryName() << "..." << endl;
+
+        StaticInitializationManager::getInstance().unloadModule(module);
+
+        module->deleteAllStaticallyInitializedInstances();
+        if (module->getDynLib()) {
+            this->dynLibManager_->unload(module->getDynLib());
+            module->setDynLib(nullptr);
+        }
+    }
+
+    void Core::loadGraphics()
+    {
+        orxout(internal_info) << "loading graphics in Core" << endl;
+
+        // Any exception should trigger this, even in upgradeToGraphics (see its remarks)
+        Loki::ScopeGuard unloader = Loki::MakeObjGuard(*this, &Core::unloadGraphics, true);
+
+        // Upgrade OGRE to receive a render window
+        try
+        {
+            graphicsManager_->upgradeToGraphics();
+        }
+        catch (const InitialisationFailedException&)
+        {
+            // Exit the application if the Ogre config dialog was canceled
+            orxout(user_error) << Exception::handleMessage() << endl;
+            exit(EXIT_FAILURE);
+        }
+        catch (...)
+        {
+            // Recovery from this is very difficult. It requires to completely
+            // destroy Ogre related objects and load again (without graphics).
+            // However since Ogre 1.7 there seems to be a problem when Ogre
+            // throws an exception and the graphics engine then gets destroyed
+            // and reloaded between throw and catch (access violation in MSVC).
+            // That's why we abort completely and only display the exception.
+            orxout(user_error) << "An exception occurred during upgrade to graphics. "
+                               << "That is unrecoverable. The message was:" << endl
+                               << Exception::handleMessage() << endl;
+            abort();
+        }
+
+        // Calls the InputManager which sets up the input devices.
+        inputManager_ = new InputManager();
+
+        // Load the CEGUI interface
+        guiManager_ = new GUIManager(inputManager_->getMousePosition());
+
+        bGraphicsLoaded_ = true;
+        GameMode::bShowsGraphics_s = true;
+
+        // Load some sort of a debug overlay (only denoted by its name, "debug.oxo")
+        graphicsManager_->loadDebugOverlay();
+
+        // Create singletons associated with graphics (in other libraries)
+        orxout(internal_info) << "creating graphics scope:" << endl;
+        graphicsScope_ = new Scope<ScopeID::GRAPHICS>();
+
+        unloader.Dismiss();
+
+        orxout(internal_info) << "finished loading graphics in Core" << endl;
+    }
+
+    void Core::unloadGraphics(bool loadGraphicsManagerWithoutRenderer)
+    {
+        orxout(internal_info) << "unloading graphics in Core" << endl;
+
+        if (this->graphicsManager_)
+            this->graphicsManager_->unloadDebugOverlay();
+
+        safeObjectDelete(&graphicsScope_);
+        safeObjectDelete(&guiManager_);
+        safeObjectDelete(&inputManager_);
+        safeObjectDelete(&graphicsManager_);
+
+        // Load Ogre::Root again, but without the render system
+        try
+        {
+            if (loadGraphicsManagerWithoutRenderer)
+                this->graphicsManager_ = new GraphicsManager(false);
+        }
+        catch (...)
+        {
+            orxout(user_error) << "An exception occurred during 'unloadGraphics':" << Exception::handleMessage() << endl
+                               << "Another exception might be being handled which may lead to undefined behaviour!" << endl
+                               << "Terminating the program." << endl;
+            abort();
+        }
+
+        bGraphicsLoaded_ = false;
+        GameMode::bShowsGraphics_s = false;
+    }
+
+    /**
+    @note
+        The code of this function has been copied and adjusted from OGRE, an open source graphics engine.
+            (Object-oriented Graphics Rendering Engine)
+        For the latest info, see http://www.ogre3d.org/
+
+        Copyright (c) 2000-2008 Torus Knot Software Ltd
+
+        OGRE is licensed under the LGPL. For more info, see OGRE license.
+    */
+    void Core::setThreadAffinity(int limitToCPU)
+    {
+#ifdef ORXONOX_PLATFORM_WINDOWS
+
+        if (limitToCPU <= 0)
+            return;
+
+        unsigned int coreNr = limitToCPU - 1;
+        // Get the current process core mask
+        ULONG_PTR procMask;
+        ULONG_PTR sysMask;
+#  if _MSC_VER >= 1400 && defined (_M_X64)
+        GetProcessAffinityMask(GetCurrentProcess(), (PDWORD_PTR)&procMask, (PDWORD_PTR)&sysMask);
+#  else
+        GetProcessAffinityMask(GetCurrentProcess(), &procMask, &sysMask);
+#  endif
+
+        // If procMask is 0, consider there is only one core available
+        // (using 0 as procMask will cause an infinite loop below)
+        if (procMask == 0)
+            procMask = 1;
+
+        // if the core specified with coreNr is not available, take the lowest one
+        if (!(procMask & (1 << coreNr)))
+            coreNr = 0;
+
+        // Find the lowest core that this process uses and coreNr suggests
+        DWORD threadMask = 1;
+        while ((threadMask & procMask) == 0 || (threadMask < (1u << coreNr)))
+            threadMask <<= 1;
+
+        // Set affinity to the first core
+        SetThreadAffinityMask(GetCurrentThread(), threadMask);
+#endif
+    }
+
+    void Core::preUpdate(const Clock& time)
+    {
+        // Update UpdateListeners before general ticking
+        for (UpdateListener* listener : ObjectList<UpdateListener>())
+            listener->preUpdate(time);
+        if (this->bGraphicsLoaded_)
+        {
+            // Process input events
+            this->inputManager_->preUpdate(time);
+            // Update GUI
+            this->guiManager_->preUpdate(time);
+        }
+        // Process console events and status line
+        if (this->ioConsole_ != nullptr)
+            this->ioConsole_->preUpdate(time);
+        // Process thread commands
+        this->tclThreadManager_->preUpdate(time);
+    }
+
+    void Core::postUpdate(const Clock& time)
+    {
+        // Update UpdateListeners just before rendering
+        for (UpdateListener* listener : ObjectList<UpdateListener>())
+            listener->postUpdate(time);
+        if (this->bGraphicsLoaded_)
+        {
+            // Render (doesn't throw)
+            this->graphicsManager_->postUpdate(time);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Core.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Core.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Core.h	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup CoreGame Core and Game
+    @ingroup Management
+*/
+
+/**
+    @file
+    @ingroup Management CoreGame
+    @brief Declaration of the Core singleton which is used to configure the program basics.
+*/
+
+#ifndef _Core_H__
+#define _Core_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include <list>
+#include "util/DestructionHelper.h"
+#include "util/Singleton.h"
+#include "CoreConfig.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The Core class is a singleton used to configure the program basics.
+    @remark
+        You should only create this singleton once because it destroys the identifiers!
+    */
+    class _CoreExport Core : public Singleton<Core>
+    {
+        friend class Singleton<Core>;
+
+        public:
+            /**
+            @brief
+                Determines the executable path, checks for build directory runs, creates
+                the output directories and sets up the other core library singletons.
+            @throws
+                GeneralException
+            */
+            Core(const std::string& cmdLine);
+
+            /// Leave empty and use destroy() instead
+            ~Core() = default;
+            /// Destructor that also executes when the object fails to construct
+            void destroy();
+
+            void preUpdate(const Clock& time);
+            void postUpdate(const Clock& time);
+
+            void loadGraphics();
+            void unloadGraphics(bool loadGraphicsManagerWithoutRenderer = true);
+
+            void loadModules();
+            void unloadModules();
+            void loadModule(ModuleInstance* module);
+            void unloadModule(ModuleInstance* module);
+
+            inline CoreConfig* getConfig() const
+                { return this->config_; }
+
+        private:
+            // non-copyable:
+            Core(const Core&) = delete;
+            Core& operator=(const Core&) = delete;
+
+            void setThreadAffinity(int limitToCPU);
+
+            ApplicationPaths*                applicationPaths_;
+            ConfigurablePaths*               configurablePaths_;
+            DynLibManager*                   dynLibManager_;
+            SignalHandler*                   signalHandler_;
+            ConfigFileManager*               configFileManager_;
+            Language*                        languageInstance_;
+            Loader*                          loaderInstance_;
+            IOConsole*                       ioConsole_;
+            TclBind*                         tclBind_;
+            TclThreadManager*                tclThreadManager_;
+            Scope<ScopeID::ROOT>*            rootScope_;
+            // graphical
+            GraphicsManager*                 graphicsManager_;            //!< Interface to OGRE
+            InputManager*                    inputManager_;               //!< Interface to OIS
+            GUIManager*                      guiManager_;                 //!< Interface to GUI
+            Scope<ScopeID::GRAPHICS>*        graphicsScope_;
+            bool                             bGraphicsLoaded_;
+
+            CoreStaticInitializationHandler* staticInitHandler_;
+            PluginManager*                   pluginManager_;
+            ModuleInstance*                  rootModule_;
+            std::list<ModuleInstance*>       modules_;
+
+            /// Helper object that stores the config values
+            CoreConfig*                      config_;
+
+            /// Helper object that executes the surrogate destructor destroy()
+            DestructionHelper<Core>          destructionHelper_;
+
+            static Core*                     singletonPtr_s;
+    };
+}
+
+#endif /* _Core_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/CoreConfig.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CoreConfig.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CoreConfig.cc	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CoreConfig.h"
+
+#include "util/output/LogWriter.h"
+#include "util/output/OutputManager.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Language.h"
+#include "core/ApplicationPaths.h"
+
+#include <random>
+
+namespace orxonox
+{
+    RegisterClassNoArgs(CoreConfig);
+
+    CoreConfig::CoreConfig()
+        : bDevMode_(false)
+        , bStartIOConsole_(true)
+        , lastLevelTimestamp_(0)
+        , ogreConfigTimestamp_(0)
+    {
+        RegisterObject(CoreConfig);
+        this->setConfigValues();
+    }
+
+    //! Function to collect the SetConfigValue-macro calls.
+    void CoreConfig::setConfigValues()
+    {
+        SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableMaxLevel_,
+                               OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
+                               OutputManager::getInstance().getLogWriter()->getConfigurableMaxLevelName(),
+                               OutputManager::getInstance().getLogWriter()->configurableMaxLevel_)
+            .description("The maximum level of output shown in the log file")
+            .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableLevel);
+        SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableAdditionalContextsMaxLevel_,
+                               OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
+                               OutputManager::getInstance().getLogWriter()->getConfigurableAdditionalContextsMaxLevelName(),
+                               OutputManager::getInstance().getLogWriter()->configurableAdditionalContextsMaxLevel_)
+            .description("The maximum level of output shown in the log file for additional contexts")
+            .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableAdditionalContextsLevel);
+        SetConfigValueExternal(OutputManager::getInstance().getLogWriter()->configurableAdditionalContexts_,
+                               OutputManager::getInstance().getLogWriter()->getConfigurableSectionName(),
+                               OutputManager::getInstance().getLogWriter()->getConfigurableAdditionalContextsName(),
+                               OutputManager::getInstance().getLogWriter()->configurableAdditionalContexts_)
+            .description("Additional output contexts shown in the log file")
+            .callback(static_cast<BaseWriter*>(OutputManager::getInstance().getLogWriter()), &BaseWriter::changedConfigurableAdditionalContexts);
+
+        SetConfigValue(bDevMode_, ApplicationPaths::buildDirectoryRun())
+            .description("Developer mode. If not set, hides some things from the user to not confuse him.")
+            .callback(this, &CoreConfig::devModeChanged);
+        SetConfigValue(language_, Language::getInstance().defaultLanguage_)
+            .description("The language of the in game text")
+            .callback(this, &CoreConfig::languageChanged);
+        SetConfigValue(bInitRandomNumberGenerator_, true)
+            .description("If true, all random actions are different each time you start the game")
+            .callback(this, &CoreConfig::initRandomNumberGenerator);
+        SetConfigValue(bStartIOConsole_, true)
+            .description("Set to false if you don't want to use the IOConsole (for Lua debugging for instance)");
+        SetConfigValue(lastLevelTimestamp_, 0)
+            .description("Timestamp when the last level was started.");
+        SetConfigValue(ogreConfigTimestamp_, 0)
+            .description("Timestamp when the ogre config file was changed.");
+    }
+
+    /** Callback function for changes in the dev mode that affect debug levels.
+        The function behaves according to these rules:
+        - 'normal' mode is defined based on where the program was launched: if
+          the launch path was the build directory, development mode \c on is
+          normal, otherwise normal means development mode \c off.
+        - Debug levels should not be hard configured (\c config instead of
+          \c tconfig) in non 'normal' mode to avoid strange behaviour.
+        - Changing the development mode from 'normal' to the other state will
+          immediately change the debug levels to predefined values which can be
+          reconfigured with \c tconfig.
+    @note
+        The debug levels for the IOConsole and the InGameConsole can be found
+        in the Shell class. The same rules apply.
+    */
+    void CoreConfig::devModeChanged()
+    {
+        // Inform listeners
+        for (DevModeListener* listener : ObjectList<DevModeListener>())
+            listener->devModeChanged(bDevMode_);
+    }
+
+    //! Callback function if the language has changed.
+    void CoreConfig::languageChanged()
+    {
+        // Read the translation file after the language was configured
+        bool success = Language::getInstance().readTranslatedLanguageFile(this->language_);
+        if (!success)
+        {
+            // Set the language in the config-file back to the default.
+            ResetConfigValue(language_);
+            orxout(internal_info, context::language) << "Reset language to " << this->language_ << '.' << endl;
+        }
+    }
+
+    void CoreConfig::initRandomNumberGenerator()
+    {
+        static bool bInitialized = false;
+        if (!bInitialized && this->bInitRandomNumberGenerator_)
+        {
+            std::random_device rnddev;
+            rndseed(rnddev());
+            //Keep the old seeding around because people will probably still use the old functions
+            srand(rnddev());
+            rand();
+            bInitialized = true;
+        }
+    }
+
+    void CoreConfig::updateLastLevelTimestamp()
+    {
+        ModifyConfigValue(lastLevelTimestamp_, set, static_cast<long long>(time(nullptr)));
+    }
+
+    void CoreConfig::updateOgreConfigTimestamp()
+    {
+        ModifyConfigValue(ogreConfigTimestamp_, set, static_cast<long long>(time(nullptr)));
+    }
+
+
+    RegisterAbstractClass(DevModeListener).inheritsFrom<Listable>();
+
+    DevModeListener::DevModeListener()
+    {
+        RegisterObject(DevModeListener);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/CoreConfig.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CoreConfig.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CoreConfig.h	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _CoreConfig_H__
+#define _CoreConfig_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+    class _CoreExport CoreConfig : virtual public Configurable
+    {
+        public:
+            CoreConfig();
+
+            void setConfigValues();
+
+            //! Developers bit. If returns false, some options are not available as to not confuse the normal user.
+            inline bool inDevMode(void) const
+                { return this->bDevMode_; }
+
+            inline bool getStartIOConsole() const
+                { return this->bStartIOConsole_; }
+
+            void updateLastLevelTimestamp();
+            inline long long getLastLevelTimestamp() const
+                { return this->lastLevelTimestamp_; }
+
+            void updateOgreConfigTimestamp();
+            inline long long getOgreConfigTimestamp() const
+                { return this->ogreConfigTimestamp_; }
+
+        private:
+            void devModeChanged();
+            void languageChanged();
+            void initRandomNumberGenerator();
+
+            bool                      bDevMode_;                   //!< Developers bit. If set to false, some options are not available as to not confuse the normal user.
+            std::string               language_;                   //!< The language
+            bool                      bInitRandomNumberGenerator_; //!< If true, srand(time(0)) is called
+            bool                      bStartIOConsole_;            //!< Set to false if you don't want to use the IOConsole
+            long long                 lastLevelTimestamp_;         ///< Timestamp when the last level was started
+            long long                 ogreConfigTimestamp_;        ///< Timestamp wehen the ogre config level was modified
+    };
+
+    //! Informs about changes in the Development Mode.
+    class DevModeListener : virtual public Listable
+    {
+    public:
+        DevModeListener();
+        virtual ~DevModeListener() = default;
+        virtual void devModeChanged(bool value) = 0;
+    };
+}
+
+#endif /* _CoreConfig_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/CoreIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CoreIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CoreIncludes.h	(revision 11817)
@@ -0,0 +1,262 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Factory RegisterObject() and RegisterClass()
+    @ingroup Object
+*/
+
+/**
+    @file
+    @ingroup Object Factory Class Identifier
+    @brief Defines several very important macros used to register objects, register classes, and to work with identifiers.
+
+    Every class needs the @c RegisterObject(class) macro in its constructor.
+
+    To register @a class in the class-hierarchy, use the @c RegisterClass(class) macro outside of the class implementation,
+    so it gets executed statically before @c main(). If you don't want @a class to be loadable, but still register it, call
+    @c RegisterUnloadableClass(class).
+
+    Abstract classes are registered with @c RegisterAbstractClass(class). For abstract classes, the inheritance must be
+    defined manually with @c RegisterAbstractClass(class).inheritsFrom(Class(parent)). Multiple parent classes can be defined
+    by chaining the above command.
+
+    Example:
+    @code
+    // register MyClass
+    RegisterClass(MyClass);
+
+    // Constructor:
+    MyClass::MyClass()
+    {
+        // Register the object in the Identifier of MyClass
+        RegisterObject(MyClass);
+    }
+    @endcode
+
+    This file also defines a number of other useful macros, like, for example, @c Class(class) which
+    returns the @ref orxonox::Identifier "Identifier" of @a class, or @c ClassByString("class") which
+    returns the Identifier of a class with name @a "class".
+
+    Example:
+    @code
+    // Assigns the Identifier of MyClass
+    Identifier* identifier = Class(MyClass);
+    @endcode
+    @code
+    // Assigns the Identifier of a class named "MyClass"
+    Identifier* identifier = ClassByString("MyClass");
+    @endcode
+*/
+
+#ifndef _CoreIncludes_H__
+#define _CoreIncludes_H__
+
+#include "CorePrereqs.h"
+
+#include "util/Output.h"
+#include "class/IdentifierManager.h"
+#include "object/ClassFactory.h"
+#include "object/ObjectList.h"
+#include "module/StaticallyInitializedInstance.h"
+
+// resolve macro conflict on windows
+#if defined(ORXONOX_PLATFORM_WINDOWS)
+#   define WIN32_LEAN_AND_MEAN
+#   include <windows.h>
+#   undef RegisterClass
+#endif
+
+
+/**
+    @brief Registers the class in the framework.
+    @param ClassName The name of the class
+*/
+#define RegisterClass(ClassName) \
+    RegisterClassWithFactory(ClassName, new orxonox::ClassFactoryWithContext<ClassName>(), true)
+
+/**
+    @brief Registers the class in the framework (for classes without arguments in their constructor).
+    @param ClassName The name of the class
+*/
+#define RegisterClassNoArgs(ClassName) \
+    RegisterClassWithFactory(ClassName, new orxonox::ClassFactoryNoArgs<ClassName>(), true)
+
+/**
+    @brief Registers the class in the framework (for classes which should not be loaded through XML).
+    @param ClassName The name of the class
+*/
+#define RegisterUnloadableClass(ClassName) \
+    RegisterClassWithFactory(ClassName, new orxonox::ClassFactoryWithContext<ClassName>(), false)
+
+/**
+    @brief Registers an abstract class in the framework. Should be used in combination with inheritsFrom(base-class-identifier).
+    @param ClassName The name of the class
+*/
+#define RegisterAbstractClass(ClassName) \
+    RegisterClassWithFactory(ClassName, static_cast<ClassFactory<ClassName>*>(nullptr), false)
+
+/**
+    @brief Registers the class in the framework with a given Factory.
+    @param ClassName The name of the class
+    @param FactoryInstance An instance of a factory that can create the class
+    @param bLoadable Whether the class is allowed to be loaded through XML
+*/
+#define RegisterClassWithFactory(ClassName, FactoryInstance, bLoadable) \
+    orxonox::SI_I& _##ClassName##Identifier = (*new orxonox::SI_I(orxonox::registerClass<ClassName>(#ClassName, FactoryInstance, bLoadable)))
+
+/**
+    @brief Registers a newly created object in the framework. Has to be called at the beginning of the constructor of @a ClassName.
+    @param ClassName The name of the class
+*/
+#define RegisterObject(ClassName) \
+    if (ClassIdentifier<ClassName>::getIdentifier()->initializeObject(this)) \
+        return; \
+    else \
+        ((void)0)
+
+/**
+    @brief Returns the Identifier of the given class.
+    @param ClassName The name of the class
+*/
+#define Class(ClassName) \
+    orxonox::ClassIdentifier<ClassName>::getIdentifier()
+
+
+namespace orxonox
+{
+    /**
+     * @brief Overload of registerClass() which determines T implicitly by the template argument of the ClassFactory.
+     */
+    template <class T>
+    inline Identifier* registerClass(const std::string& name, ClassFactory<T>* factory, bool bLoadable = true)
+    {
+        return registerClass<T>(name, static_cast<Factory*>(factory), bLoadable);
+    }
+
+    /**
+     * @brief Registers a class in the framework.
+     * @param name The name of the class
+     * @param factory The factory which is able to create new instances of this class
+     * @param bLoadable Whether the class is allowed to be loaded through XML
+     */
+    template <class T>
+    inline Identifier* registerClass(const std::string& name, Factory* factory, bool bLoadable = true)
+    {
+        return new ClassIdentifier<T>(name, factory, bLoadable);
+    }
+
+    /**
+        @brief Returns the Identifier with a given name.
+        @param name The name of the class
+    */
+    inline Identifier* ClassByString(const std::string& name)
+    {
+        return IdentifierManager::getInstance().getIdentifierByString(name);
+    }
+
+    /**
+        @brief Returns the Identifier with a given lowercase name.
+        @param name The lowercase name of the class
+    */
+    inline Identifier* ClassByLowercaseString(const std::string& name)
+    {
+        return IdentifierManager::getInstance().getIdentifierByLowercaseString(name);
+    }
+
+    /**
+        @brief Returns the Identifier with a given network ID.
+        @param id The network ID of the class
+    */
+    inline Identifier* ClassByID(uint32_t id)
+    {
+        return IdentifierManager::getInstance().getIdentifierByID(id);
+    }
+
+    /**
+        @brief Returns the Identifier with a given 'this' pointer.
+        @note This of course only works with Identifiables.
+              The only use is in conjunction with macros that don't know the class type.
+        @param p Pointer to an Identifiable
+    */
+    template <class T>
+    inline Identifier* ClassByObjectType(const T* p)
+    {
+        return ClassIdentifier<T>::getIdentifier();
+    }
+
+
+
+
+    /**
+     * The static initializer stores the parent classes of this identifier. The corresponding identifiers are later loaded. This prevents identifiers from
+     * being used before they are completely initialized.
+     */
+    class _CoreExport StaticallyInitializedIdentifier : public StaticallyInitializedInstance
+    {
+        template <class T>
+        struct InheritsFromClass : public Identifier::InheritsFrom
+        {
+            virtual Identifier* getParent() const override { return Class(T); }
+        };
+
+        public:
+            StaticallyInitializedIdentifier(Identifier* identifier)
+                : StaticallyInitializedInstance(StaticInitialization::IDENTIFIER)
+                , identifier_(identifier)
+            {}
+            ~StaticallyInitializedIdentifier() { identifier_->destroy(); }
+
+            virtual void load() override
+            {
+                IdentifierManager::getInstance().addIdentifier(this->identifier_);
+            }
+
+            virtual void unload() override
+            {
+                IdentifierManager::getInstance().removeIdentifier(this->identifier_);
+            }
+
+            inline Identifier& getIdentifier()
+                { return *this->identifier_; }
+
+            template <class T>
+            inline StaticallyInitializedIdentifier& inheritsFrom()
+                { this->identifier_->inheritsFrom(new InheritsFromClass<T>()); return *this; }
+
+            inline StaticallyInitializedIdentifier& virtualBase()
+                { this->identifier_->setVirtualBase(true); return *this; }
+
+        private:
+            Identifier* identifier_;
+    };
+
+    typedef StaticallyInitializedIdentifier SI_I;
+}
+
+#endif /* _CoreIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/CorePrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CorePrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CorePrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the core library
+@details
+    Updated: 13. September 2009
+    Total Files: 56
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <string>   // 54
+#include <vector>   // 54
+#include <cassert>  // 53
+#include <fstream>  // 53
+#include <iostream> // 53
+#include <map>      // 53
+#include <sstream>  // 53
+#include <set>      // 50
+#include <memory>
+
+#include "util/Output.h" // 48
+
+#include <deque>    // 43
+#include <list>     // 44
+#include <cmath>    // 42
+
+#include <loki/ScopeGuard.h> // 38
+
+#include <OgreMath.h>        // 36
+#include <OgreVector2.h>     // 36
+#include <OgreVector3.h>     // 36
+#include <OgreVector4.h>     // 36
+#include <OgreQuaternion.h>  // 36
+#include <OgreColourValue.h> // 36
+#include <boost/preprocessor/cat.hpp> // 27
+
+#ifdef ORXONOX_COMPILER_MSVC
+
+#include <ois/OISKeyboard.h> // 15
+#include <ois/OISMouse.h>    // 15
+#include <ois/OISJoyStick.h> // 15
+
+#include "util/SubString.h"  // 14
+
+#include <stack> // 12
+
+#endif /*ORXONOX_COMPILER_MSVC */
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/libraries/core/CorePrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CorePrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CorePrereqs.h	(revision 11817)
@@ -0,0 +1,424 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the core library
+*/
+
+#ifndef _CorePrereqs_H__
+#define _CorePrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include <boost/version.hpp>
+#include <string>
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined( CORE_STATIC_BUILD )
+#  ifdef CORE_SHARED_BUILD
+#    define _CoreExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _CoreExport
+#    else
+#      define _CoreExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _CorePrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _CoreExport  __attribute__ ((visibility("default")))
+#  define _CorePrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _CoreExport
+#  define _CorePrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    static constexpr uint32_t OBJECTID_UNKNOWN = static_cast<uint32_t>(-1);
+}
+
+//-----------------------------------------------------------------------
+// Enums
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    namespace ScopeID
+    {
+        typedef int Value;
+
+        //!A list of available scopes for the Scope template.
+        static constexpr Value ROOT = 1;
+        static constexpr Value GRAPHICS = 2;
+    }
+
+    namespace StaticInitialization
+    {
+        typedef int Type;
+
+        static constexpr Type STATIC_INITIALIZATION_HANDLER = 1;
+        static constexpr Type IDENTIFIER = 2;
+        static constexpr Type SCOPED_SINGLETON_WRAPPER = 3;
+        static constexpr Type COMMAND_LINE_ARGUMENT = 4;
+        static constexpr Type CONSOLE_COMMAND = 5;
+    }
+
+    namespace XMLPort
+    {
+        enum Mode
+        {
+            NOP,
+            LoadObject,
+            SaveObject,
+            ExpandObject
+        };
+    }
+
+    namespace ConfigFileType
+    {
+        enum Value
+        {
+            Settings,
+            JoyStickCalibration,
+            CommandHistory
+            // Don't forget to adjust the array size in the ConfigFileManager when adding a new entry here!
+        };
+    }
+
+    namespace KeybindMode
+    {
+        enum Value
+        {
+            OnPress,
+            OnHold,
+            OnRelease,
+            OnPressAndRelease,
+            None
+        };
+    };
+}
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    typedef std::string LanguageEntryLabel;
+
+    template <class T, class U>
+    T orxonox_cast(U*);
+
+    class ApplicationPaths;
+    class BaseObject;
+    template <class T>
+    class ClassFactory;
+    template <class T>
+    class ClassFactoryWithContext;
+    template <class T>
+    class ClassIdentifier;
+    class ClassTreeMask;
+    class ClassTreeMaskIterator;
+    class ClassTreeMaskNode;
+    class ClassTreeMaskObjectIterator;
+    class CommandLineParser;
+    class CommandLineArgument;
+    class ConfigFile;
+    class ConfigFileEntry;
+    class ConfigFileEntryComment;
+    class ConfigFileEntryValue;
+    class ConfigFileManager;
+    class ConfigFileSection;
+    class Configurable;
+    class ConfigurablePaths;
+    class ConfigValueContainer;
+    class Context;
+    class Core;
+    class CoreConfig;
+    class CoreStaticInitializationHandler;
+    class Destroyable;
+    class DestroyLaterManager;
+    class DestructionListener;
+    class DynLib;
+    class DynLibManager;
+    struct Event;
+    class EventState;
+    class Factory;
+    class Game;
+    class GameConfig;
+    class GameState;
+    struct GameStateInfo;
+    struct GameStateTreeNode;
+    class GlowMaterialListener;
+    class GraphicsManager;
+    class GUIManager;
+    class Identifiable;
+    class Identifier;
+    template <class T>
+    class Iterator;
+    class Language;
+    class Listable;
+    class Loader;
+    class LuaFunctor;
+    class LuaState;
+    class MemoryArchive;
+    class MemoryArchiveFactory;
+    class ModuleInstance;
+    class Namespace;
+    class NamespaceNode;
+    template <class T>
+    class ObjectList;
+    class ObjectListBase;
+    class ObjectListBaseElement;
+    template <class T>
+    class ObjectListElement;
+    template <class T>
+    class ObjectListIterator;
+    class OgreWindowEventListener;
+    class OrxonoxClass;
+    class OrxonoxInterface;
+    class Plugin;
+    class PluginManager;
+    class PluginReference;
+    struct ResourceInfo;
+    template <ScopeID::Value>
+    class Scope;
+    class ScopeManager;
+    class ScopedSingletonWrapper;
+    class SettingsConfigFile;
+    class StaticallyInitializedInstance;
+    class StaticInitializationHandler;
+    class StaticInitializationManager;
+    template <class T>
+    class StrongPtr;
+    template <class T>
+    class SubclassIdentifier;
+    class Template;
+    class Thread;
+    class ThreadPool;
+    class UpdateListener;
+    class ViewportEventListener;
+    template <class T>
+    class WeakPtr;
+    class WindowEventListener;
+    class XMLFile;
+    class XMLNameListener;
+    template <class T, class O>
+    class XMLPortClassObjectContainer;
+    template <class T>
+    class XMLPortClassParamContainer;
+    class XMLPortObjectContainer;
+    class XMLPortParamContainer;
+
+    // Command
+    class ArgumentCompleter;
+    class ArgumentCompletionListElement;
+    class CommandEvaluation;
+    class ConsoleCommand;
+    class ConsoleCommandManager;
+    class Executor;
+    template <class T>
+    class ExecutorMember;
+    class ExecutorStatic;
+    class Functor;
+    template <class O>
+    class FunctorMember;
+    typedef FunctorMember<void> FunctorStatic;
+    template <class F, class O>
+    class FunctorPointer;
+    class IOConsole;
+    class IRC;
+    class Shell;
+    class ShellListener;
+    class TclBind;
+    struct TclInterpreterBundle;
+    template <class T>
+    class TclThreadList;
+    class TclThreadManager;
+
+    // Input
+    class BaseCommand;
+    class BufferedParamCommand;
+    class Button;
+    class HalfAxis;
+    class InputBuffer;
+    class InputDevice;
+    template <class Traits>
+    class InputDeviceTemplated;
+    class InputHandler;
+    class InputManager;
+    class InputState;
+    struct InputStatePriority;
+    class JoyStickQuantityListener;
+    class JoyStick;
+    class KeyBinder;
+    class KeyBinderManager;
+    class Keyboard;
+    class KeyDetector;
+    class KeyEvent;
+    class Mouse;
+    class ParamCommand;
+    class SimpleCommand;
+}
+
+#include "command/FunctorPtr.h"
+#include "command/ExecutorPtr.h"
+
+// CppTcl
+namespace Tcl
+{
+    class interpreter;
+    class object;
+}
+
+// Boost
+namespace boost
+{
+#if (BOOST_VERSION < 104400)
+
+    namespace filesystem
+    {
+        struct path_traits;
+        template <class String, class Traits> class basic_path;
+        typedef basic_path<std::string, path_traits> path;
+    }
+
+#elif (BOOST_VERSION < 105000)
+
+# if BOOST_FILESYSTEM_VERSION == 2
+    namespace filesystem2
+    {
+        struct path_traits;
+        template <class String, class Traits> class basic_path;
+        typedef basic_path<std::string, path_traits> path;
+    }
+    namespace filesystem
+    {
+        using filesystem2::basic_path;
+        using filesystem2::path_traits;
+        using filesystem2::path;
+    }
+# elif BOOST_FILESYSTEM_VERSION == 3
+    namespace filesystem3
+    {
+        class path;
+    }
+    namespace filesystem
+    {
+        using filesystem3::path;
+    }
+# endif
+
+#else
+
+    namespace filesystem
+    {
+        class path;
+    }
+
+#endif
+
+    class thread;
+    class mutex;
+    class shared_mutex;
+    class condition_variable;
+}
+
+// Ogre
+namespace Ogre
+{
+    class DataStream;
+    template <class T> class SharedPtr;
+    typedef SharedPtr<DataStream> DataStreamPtr;
+}
+namespace orxonox
+{
+    // Import the Ogre::DataStream
+    using Ogre::DataStream;
+    using Ogre::DataStreamPtr;
+}
+
+// CEGUI
+namespace CEGUI
+{
+    class DefaultLogger;
+    class Logger;
+    class LuaScriptModule;
+
+#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
+    class OgreCEGUIRenderer;
+    class OgreCEGUIResourceProvider;
+    class OgreCEGUITexture;
+#else
+    class OgreRenderer;
+    class OgreResourceProvider;
+    class OgreImageCodec;
+#endif
+}
+
+// Lua
+struct lua_State;
+
+// TinyXML and TinyXML++
+class TiXmlString;
+class TiXmlOutStream;
+class TiXmlNode;
+class TiXmlHandle;
+class TiXmlDocument;
+class TiXmlElement;
+class TiXmlComment;
+class TiXmlUnknown;
+class TiXmlAttribute;
+class TiXmlText;
+class TiXmlDeclaration;
+class TiXmlParsingData;
+namespace ticpp
+{
+    class Document;
+    class Element;
+    class Declaration;
+    class StylesheetReference;
+    class Text;
+    class Comment;
+    class Attribute;
+}
+namespace orxonox
+{
+    using ticpp::Element;
+}
+
+#endif /* _CorePrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/CoreStaticInitializationHandler.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CoreStaticInitializationHandler.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CoreStaticInitializationHandler.cc	(revision 11817)
@@ -0,0 +1,136 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CoreStaticInitializationHandler.h"
+
+#include "CoreIncludes.h"
+#include "module/ModuleInstance.h"
+#include "object/Iterator.h"
+#include "class/IdentifierManager.h"
+#include "singleton/ScopeManager.h"
+#include "command/ConsoleCommandManager.h"
+#include "commandline/CommandLineParser.h"
+
+namespace orxonox
+{
+    void CoreStaticInitializationHandler::setupHandler()
+    {
+        // initialize singletons
+        new IdentifierManager();
+        new ScopeManager();
+        new CommandLineParser();
+        new ConsoleCommandManager();
+    }
+
+    void CoreStaticInitializationHandler::shutdownHandler()
+    {
+        delete &ConsoleCommandManager::getInstance();
+        delete &CommandLineParser::getInstance();
+        delete &ScopeManager::getInstance();
+        delete &IdentifierManager::getInstance();
+    }
+
+    void CoreStaticInitializationHandler::loadModule(ModuleInstance* module)
+    {
+        this->loadInstances(module);
+        if (this->bInitInstances_)
+            this->initInstances(module);
+    }
+
+    void CoreStaticInitializationHandler::loadInstances(ModuleInstance* module)
+    {
+        // the order of initialization is important: handlers > identifiers > singletons > everything else
+        module->loadAllStaticallyInitializedInstances(StaticInitialization::STATIC_INITIALIZATION_HANDLER);
+        module->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+        module->loadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
+        module->loadAllStaticallyInitializedInstances(StaticInitialization::COMMAND_LINE_ARGUMENT);
+        module->loadAllStaticallyInitializedInstances(StaticInitialization::CONSOLE_COMMAND);
+    }
+
+    void CoreStaticInitializationHandler::initInstances(ModuleInstance* module)
+    {
+        IdentifierManager::getInstance().createClassHierarchy();
+    }
+
+    void CoreStaticInitializationHandler::unloadModule(ModuleInstance* module)
+    {
+        // inverted order of initialization
+        module->unloadAllStaticallyInitializedInstances(StaticInitialization::CONSOLE_COMMAND);
+        module->unloadAllStaticallyInitializedInstances(StaticInitialization::COMMAND_LINE_ARGUMENT);
+        module->unloadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
+
+        // until now every object (including singletons) of the unloaded identifiers should have been destroyed in a controlled manner.
+        // every remaining object is now destroyed in random order.
+        this->destroyObjects(module);
+
+        // all objects are gone now and we can unload identifiers
+        module->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+        module->unloadAllStaticallyInitializedInstances(StaticInitialization::STATIC_INITIALIZATION_HANDLER);
+    }
+
+    void CoreStaticInitializationHandler::destroyObjects(ModuleInstance* module)
+    {
+        // collect all identifiers that are about to be unloaded
+        std::set<Identifier*> identifiers;
+        const std::set<StaticallyInitializedInstance*>& instances = module->getInstances(StaticInitialization::IDENTIFIER);
+        for (StaticallyInitializedInstance* instance : instances)
+            identifiers.insert(&static_cast<StaticallyInitializedIdentifier*>(instance)->getIdentifier());
+
+        // destroy objects. some objects may survive this at first because they still have strong pointers pointing at them. this is
+        // ok as long as those strong pointers are held by objects that are also about to be destroyed in the same loop. this means
+        // that objects within one module may reference each other by strong pointers. but it is not allowed that objects from another
+        // module (which is not unloaded) uses strong pointers to point at objects inside the unloaded module. this will lead to a crash.
+        for (Identifier* identifier : identifiers)
+            identifier->destroyObjects();
+
+        // check if all objects were really destroyed. this is not the case if an object is referenced by a strong pointer from another
+        // module (or if two objects inside this module reference each other). this will lead to a crash and must be fixed (e.g. by
+        // changing object dependencies; or by changing the logic that allows modules to be unloaded).
+        for (Identifier* identifier : identifiers)
+        {
+            ObjectListBase* objectList = Context::getRootContext()->getObjectList(identifier);
+            if (objectList->size() > 0)
+            {
+                orxout(internal_error) << "There are still " << objectList->size() << " objects of type " << identifier->getName()
+                    << " after unloading the Identifier. This may lead to a crash" << endl;
+            }
+        }
+
+        // destroy object-lists in all contexts
+        for (Identifier* identifier : identifiers)
+        {
+            // only do this if the Identifier is not a Context itself; otherwise we delete the list we're iterating over
+            if (!identifier->isExactlyA(Class(Context)))
+            {
+                // iterate over all contexts
+                for (Context* context : ObjectList<Context>())
+                    context->destroyObjectList(identifier);
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/CoreStaticInitializationHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/CoreStaticInitializationHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/CoreStaticInitializationHandler.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _CoreStaticInitializationHandler_H__
+#define _CoreStaticInitializationHandler_H__
+
+#include "core/CorePrereqs.h"
+
+#include "module/StaticInitializationHandler.h"
+
+namespace orxonox
+{
+    class _CoreExport CoreStaticInitializationHandler : public StaticInitializationHandler
+    {
+        friend class Core;
+
+        public:
+            CoreStaticInitializationHandler() : bInitInstances_(false) {}
+
+            virtual void setupHandler() override;
+            virtual void shutdownHandler() override;
+
+            virtual void loadModule(ModuleInstance* module) override;
+            virtual void unloadModule(ModuleInstance* module) override;
+
+            inline void setInitInstances(bool bInitInstances)
+                { this->bInitInstances_ = bInitInstances; }
+
+        private:
+            void loadInstances(ModuleInstance* module);
+            void initInstances(ModuleInstance* module);
+
+            void destroyObjects(ModuleInstance* module);
+
+            bool bInitInstances_;
+    };
+}
+
+#endif /* _CoreStaticInitializationHandler_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Event.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Event.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Event.cc	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the classes Event and EventState.
+*/
+
+#include "Event.h"
+
+#include "BaseObject.h"
+#include "class/Identifier.h"
+
+namespace orxonox
+{
+    /**
+        @brief Processes an event (calls the set-function if the necessary conditions are met).
+
+        @param event     The fired event
+        @param object    The object whose state is affected by the event (only needed for debug output)
+    */
+    void EventState::process(const Event& event, BaseObject* object)
+    {
+        if (this->bProcessingEvent_)
+        {
+            orxout(internal_warning, context::events) << "Detected Event loop in section \"" << event.statename_ << "\" of object \"" << object->getName() << "\" and fired by \"" << event.originator_->getName() << '"' << endl;
+            return;
+        }
+
+        this->bProcessingEvent_ = true;
+
+        orxout(verbose, context::events) << "Processing event (EventState) : originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << "), activate: " << event.activate_ << ", name: " << event.name_ << ", statename: " << event.statename_ << ", object: " << object->getIdentifier()->getName() << " (&" << object << ")" << "." << endl;
+
+        // check if the originator is an instance of the requested class
+        if (event.originator_->isA(this->subclass_))
+        {
+            // If the EventState doesn't act as an EventSink.
+            // actualize the activationcounter
+            if(!this->bSink_)
+            {
+                if (event.activate_)
+                    ++this->activeEvents_;
+                else
+                {
+                    --this->activeEvents_;
+
+                    if (this->activeEvents_ < 0)
+                        this->activeEvents_ = 0;
+                }
+            }
+
+            if (this->statefunction_->getParamCount() == 0 && event.activate_)
+            {
+                // if the eventfunction doesn't have a state, just call it whenever an activation-event comes in
+                (*this->statefunction_)();
+            }
+            else if (this->bSink_ || (!this->bSink_ && ((this->activeEvents_ == 1 && event.activate_) || (this->activeEvents_ == 0 && !event.activate_)) ) )
+            {
+                // if the eventfunction needs a state, we just call the function if the state changed from 0 to 1 (state = true) or from 1 to 0 (state = false) [but not if activeEvents_ is > 1]
+                if (this->statefunction_->getParamCount() == 1)
+                {
+                    // one argument: just the eventstate
+                    (*this->statefunction_)(event.activate_);
+                }
+                else if (this->statefunction_->getParamCount() >= 2)
+                {
+                    // two arguments: the eventstate and the originator
+                    if (this->subclass_->isExactlyA(ClassIdentifier<BaseObject>::getIdentifier()))
+                    {
+                        // if the subclass is BaseObject, we don't have to cast the pointer
+                        (*this->statefunction_)(event.activate_, event.originator_);
+                    }
+                    else
+                    {
+                        // else cast the pointer to the desired class
+                        void* castOriginator = event.originator_->getDerivedPointer(this->subclass_->getClassID());
+                        (*this->statefunction_)(event.activate_, castOriginator);
+                    }
+                }
+            }
+        }
+
+        this->bProcessingEvent_ = false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Event.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Event.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Event.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Event Events
+    @ingroup Core
+*/
+
+/**
+    @file
+    @ingroup Event
+    @brief Declaration of the classes Event and EventState.
+*/
+
+#ifndef _Event_H__
+#define _Event_H__
+
+#include "CorePrereqs.h"
+#include <string>
+
+namespace orxonox
+{
+    /**
+        @brief The Event struct contains information about a fired Event.
+    */
+    struct _CoreExport Event
+    {
+        Event(bool activate, BaseObject* originator, const std::string& name) : activate_(activate), originator_(originator), name_(name) {}
+
+        bool        activate_;   //!< True if this is an activating event (the event source was inactive before and just triggered the event) - false otherwise
+        std::string statename_;  //!< The name of the state this event affects
+        BaseObject* originator_; //!< The object which triggered this event
+        std::string name_;       //!< The name of this event
+
+    };
+
+    /**
+        @brief The EventState contains information about an event state.
+
+        An event state is a state of an object, which can be changed by events.
+        Event states are changed through functions. Possible functions headers for set event states are:
+         - memoryless state: <tt>function()</tt>
+         - boolean state:    <tt>function(bool state)</tt>
+         - individual state: <tt>function(bool state, SomeClass originator)</tt>
+
+        Note that SomeClass may be any class deriving from BaseObject. You will not receive events from originators of other classes.
+        The actual class for SomeClass must be specified as the second argument of the XMLPortEventState() macro.
+
+        The this pointer of the affected object is hidden in the functors, because the events are processed in the BaseObject, but some
+        statefunctions may be from child-classes.
+    */
+    class _CoreExport EventState
+    {
+        public:
+            EventState(const FunctorPtr& statefunction, Identifier* subclass, bool bSink = false) : bProcessingEvent_(false), activeEvents_(0), statefunction_(statefunction), subclass_(subclass), bSink_(bSink) {}
+
+            void process(const Event& event, BaseObject* object);
+
+            const FunctorPtr& getFunctor() const
+                { return this->statefunction_; }
+
+        private:
+            bool        bProcessingEvent_;  //!< This becomes true while the container processes an event (used to prevent loops)
+            int         activeEvents_;      //!< The number of events which affect this state and are currently active
+            FunctorPtr  statefunction_;     //!< A functor to set the state
+            Identifier* subclass_;          //!< Originators must be an instance of this class (usually BaseObject, but some statefunctions allow a second argument with an originator of a specific class)
+            bool        bSink_;             //!< Determines whether the EventState acts as an EventSink forwarding any Event (even if the state didn't change) or in the normal manner, only processing Events that change the state.
+    };
+}
+
+#endif /* _Event_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/EventIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/EventIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/EventIncludes.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Event
+    @brief Definition of the XMLPortEventState() macro, as well as some more useful macros.
+*/
+
+#ifndef _EventIncludes_H__
+#define _EventIncludes_H__
+
+#include "CorePrereqs.h"
+
+#include "Event.h"
+#include "XMLPort.h"
+#include "command/Executor.h"
+
+/**
+    @brief Defines a new event state (a state of the object which can be changed by events).
+
+    @param classname    The name of this class
+    @param subclassname Usually BaseObject - if different, only instances of this class can send events to this object
+    @param statename    The name (string) of this state
+    @param function     The function which should be used to set the state
+    @param xmlelement   Argument for XMLPort
+    @param mode         Argument for XMLPort
+*/
+#define XMLPortEventState(classname, subclassname, statename, function, xmlelement, mode) \
+    orxonox::EventState* containername##function = this->getEventState(statename); \
+    if (!containername##function) \
+    { \
+        containername##function = new orxonox::EventState(orxonox::createFunctor(&classname::function, this), orxonox::ClassIdentifier<subclassname>::getIdentifier()); \
+        this->addEventState(statename, containername##function); \
+    } \
+    XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
+
+/**
+    @brief Like XMLPortEventState but creates an event sink instead of an event state.
+           The most important destinction between an EventState and an EventSink is, that an EventState only processes events which change the state of the EventState, where as an EventSink is an EventState that processes any Event that reaches it.
+*/
+
+#define XMLPortEventSink(classname, subclassname, statename, function, xmlelement, mode) \
+    orxonox::EventState* containername##function = this->getEventState(statename); \
+    if (!containername##function) \
+    { \
+        containername##function = new orxonox::EventState(orxonox::createFunctor(&classname::function, this), orxonox::ClassIdentifier<subclassname>::getIdentifier(), true); \
+        this->addEventState(statename, containername##function); \
+    } \
+    XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
+
+
+#define XMLPortEventStateTemplate(classname, subclassname, statename, function, xmlelement, mode, ...) \
+    orxonox::EventState* containername##function = this->getEventState(statename); \
+    if (!containername##function) \
+    { \
+        containername##function = new orxonox::EventState(orxonox::createFunctor<classname, __VA_ARGS__ >(&classname::function, this), orxonox::ClassIdentifier<subclassname>::getIdentifier()); \
+        this->addEventState(statename, containername##function); \
+    } \
+    XMLPortEventStateIntern(xmlportevent##function, classname, statename, xmlelement, mode)
+
+#define XMLPortEventStateIntern(name, classname, statename, xmlelement, mode) \
+    static orxonox::ExecutorPtr xmlsetfunctorbase##name = orxonox::createExecutor(orxonox::createFunctor(&classname::addEventSource), std::string( #classname ) + "::" + "addEventSource" + '(' + statename + ')'); \
+    static orxonox::ExecutorPtr xmlgetfunctorbase##name = orxonox::createExecutor(orxonox::createFunctor(&classname::getEventSource), std::string( #classname ) + "::" + "getEventSource" + '(' + statename + ')'); \
+    static orxonox::ExecutorMemberPtr<classname> xmlsetfunctor##name = std::static_pointer_cast<orxonox::ExecutorMember<classname>>(xmlsetfunctorbase##name); \
+    static orxonox::ExecutorMemberPtr<classname> xmlgetfunctor##name = std::static_pointer_cast<orxonox::ExecutorMember<classname>>(xmlgetfunctorbase##name); \
+    xmlsetfunctor##name->setDefaultValue(1, statename); \
+    xmlgetfunctor##name->setDefaultValue(1, statename); \
+    XMLPortObjectGeneric(xmlport##name, classname, orxonox::BaseObject, statename, xmlsetfunctor##name, xmlgetfunctor##name, xmlelement, mode, false, true)
+
+
+/**
+    @brief Defines a new event name for a class. Named events can only have names which were defined with this macro.
+
+    @param classname The name of the class
+    @param name      The name of the event
+*/
+#define CreateEventName(classname, name) \
+    static std::string eventname##classname##name = #name
+
+/**
+    @brief This macro is needed to fire an event with this name. The event name must previously be declared with @ref CreateEventName.
+*/
+#define FireEventName(classname, name) \
+    eventname##classname##name
+
+#endif /* _EventIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/GUIManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GUIManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GUIManager.cc	(revision 11817)
@@ -0,0 +1,971 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GUIManager.h"
+
+#include <fstream>
+#include <memory>
+#include <functional>
+#include <OgreRenderQueue.h>
+#include <OgreRenderWindow.h>
+
+extern "C" {
+#include <lua.h>
+}
+
+#if CEGUI_VERSION >= 0x000800
+#   include <CEGUI/DefaultLogger.h>
+#   include <CEGUI/Exceptions.h>
+#   include <CEGUI/FontManager.h>
+#   include <CEGUI/InputEvent.h>
+#   include <CEGUI/MouseCursor.h>
+#   include <CEGUI/ResourceProvider.h>
+#   include <CEGUI/System.h>
+#   include <CEGUI/Window.h>
+#   include <CEGUI/WindowManager.h>
+#   include <CEGUI/XMLAttributes.h>
+#   include <CEGUI/widgets/Listbox.h>
+#   include <CEGUI/widgets/ListboxItem.h>
+#else
+#   include <CEGUIDefaultLogger.h>
+#   include <CEGUIExceptions.h>
+#   include <CEGUIFontManager.h>
+#   include <CEGUIInputEvent.h>
+#   include <CEGUIMouseCursor.h>
+#   include <CEGUIResourceProvider.h>
+#   include <CEGUISystem.h>
+#   include <CEGUIWindow.h>
+#   include <CEGUIWindowManager.h>
+#   include <CEGUIXMLAttributes.h>
+#   include <elements/CEGUIListbox.h>
+#   include <elements/CEGUIListboxItem.h>
+#endif
+
+#ifdef ORXONOX_OLD_CEGUI
+#   include <CEGUILua.h>
+#   include <ogreceguirenderer/OgreCEGUIRenderer.h>
+extern "C" {
+#   include <lauxlib.h>
+}
+#else
+#   if CEGUI_VERSION >= 0x000800
+#       include <CEGUI/ScriptModules/Lua/ScriptModule.h>
+#       include <CEGUI/RendererModules/Ogre/ImageCodec.h>
+#       include <CEGUI/RendererModules/Ogre/Renderer.h>
+#       include <CEGUI/RendererModules/Ogre/ResourceProvider.h>
+#   else
+#       include <ScriptingModules/LuaScriptModule/CEGUILua.h>
+#       include <RendererModules/Ogre/CEGUIOgreImageCodec.h>
+#       include <RendererModules/Ogre/CEGUIOgreRenderer.h>
+#       include <RendererModules/Ogre/CEGUIOgreResourceProvider.h>
+#   endif
+#   include <OgreCamera.h>
+#   include <OgreRenderQueueListener.h>
+#   include <OgreRenderSystem.h>
+#   include <OgreRoot.h>
+#   include <OgreSceneManager.h>
+#endif
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_COMPILER_MINGW)
+#  include <windows.h>
+#endif
+
+#include "util/Clock.h"
+#include "util/Convert.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/Math.h"
+#include "util/OrxAssert.h"
+#include "util/output/BaseWriter.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+#include "config/ConfigValueIncludes.h"
+#include "Core.h"
+#include "CoreIncludes.h"
+#include "Game.h"
+#include "GraphicsManager.h"
+#include "LuaState.h"
+#include "ConfigurablePaths.h"
+#include "Resource.h"
+#include "command/ConsoleCommandIncludes.h"
+#include "input/InputManager.h"
+#include "input/InputState.h"
+#include "input/KeyBinderManager.h"
+
+namespace orxonox
+{
+    namespace arg = std::placeholders;
+
+    static void key_esc()
+        { GUIManager::getInstance().keyESC(); }
+    SetConsoleCommand("keyESC", &key_esc);
+
+    class CEGUILogger : public CEGUI::DefaultLogger
+    {
+    public:
+        virtual void logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level = CEGUI::Standard) override
+        {
+            OutputLevel orxonoxLevel = level::debug_output;
+            switch (level)
+            {
+                case CEGUI::Errors:      orxonoxLevel = level::internal_error; break;
+                case CEGUI::Warnings:    orxonoxLevel = level::internal_warning; break;
+                case CEGUI::Standard:    orxonoxLevel = level::verbose; break;
+                case CEGUI::Informative: orxonoxLevel = level::verbose_more; break;
+                case CEGUI::Insane:      orxonoxLevel = level::verbose_ultra; break;
+                default: OrxAssert(false, "CEGUI log level out of range, inspect immediately!");
+            }
+
+            orxout(orxonoxLevel, context::cegui) << message << endl;
+
+            CEGUI::DefaultLogger::logEvent(message, level);
+        }
+
+        /// Carbon copy from CEGUIDefaultLogger.cpp with a bugfix for Windows
+        virtual void setLogFilename(const CEGUI::String& filename, bool append = false) override
+        {
+            // Close current log file (if any)
+            if (d_ostream.is_open())
+                d_ostream.close();
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_COMPILER_MINGW)
+            // filename.c_str() is UTF-8 encoded, but Windows expects characters
+            // according to the current codepage or UTF-16 (wchar)
+            d_ostream.open(utf8ToUtf16(filename.c_str()).c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::trunc));
+#else
+            d_ostream.open(filename.c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::trunc));
+#endif
+            if (!d_ostream)
+                ThrowException(General, "Setting the CEGUI log filename failed");
+
+            // Initialise width for date & time alignment.
+            d_ostream.width(2);
+
+            // Write out cached log strings.
+            if (d_caching)
+            {
+                d_caching = false;
+
+                std::vector<std::pair<CEGUI::String, CEGUI::LoggingLevel>>::iterator it = d_cache.begin();
+
+                while (it != d_cache.end())
+                {
+                    if (d_level >= it->second)
+                    {
+                        d_ostream << it->first;
+                        // Ensure new event is written to the file, rather than just being buffered.
+                        d_ostream.flush();
+                    }
+                    ++it;
+                }
+
+                d_cache.clear();
+            }
+        }
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_COMPILER_MINGW)
+        /// Converts a UTF-8 character sequence to Windows UTF-16
+        static std::wstring utf8ToUtf16(const std::string& utf8text)
+        {
+            const int textLen = MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(),
+                utf8text.size() + 1, 0, 0);
+
+            if (textLen == 0)
+                ThrowException(General, "Utf8ToUtf16 - MultiByteToWideChar failed");
+
+            std::wstring wideStr(textLen, 0);
+            MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(), utf8text.size() + 1,
+                &wideStr[0], wideStr.size());
+            return wideStr;
+        }
+#endif
+    };
+
+#ifdef ORXONOX_OLD_CEGUI
+    /** Class with the same memory layout as CEGUI::LuaScriptModule. <br>
+        We need this to fix a problem with an uninitialised member variable
+        in CEGUI < 0.7 <br>
+        Notice the "public" modifier for the otherwise private variables.
+    */
+    class LuaScriptModuleWorkaround : public CEGUI::ScriptModule
+    {
+    public:
+        LuaScriptModuleWorkaround();
+        ~LuaScriptModuleWorkaround();
+
+    public:
+        bool d_ownsState;
+        lua_State* d_state;
+        CEGUI::String d_errFuncName;
+        int d_errFuncIndex;
+        CEGUI::String d_activeErrFuncName;
+        int d_activeErrFuncIndex;
+    };
+#else
+    /// RenderQueueListener based class used to hook into the ogre rendering system
+    class RQListener : public Ogre::RenderQueueListener
+    {
+    public:
+        /// Callback from Ogre invoked before other stuff in our target queue is rendered
+        virtual void renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue) override
+        {
+            if (id == Ogre::RENDER_QUEUE_OVERLAY && invocation.empty())
+            {
+#if CEGUI_VERSION >= 0x000800
+                CEGUI::System::getSingleton().renderAllGUIContexts();
+#else
+                CEGUI::System::getSingleton().renderGUI();
+#endif
+
+                // Important workaround! (at least required by CEGUI 0.7.5)
+                // If we don't reset the scissor test, OGRE will only render overlays
+                // in the area where CEGUI last drew, which is usually nothing
+                // or a little box where the focused element is.
+                Ogre::Root::getSingleton().getRenderSystem()->setScissorTest(false);
+            }
+        }
+#if OGRE_VERSION < 0x010700
+        virtual void renderQueueEnded(Ogre::uint8 id, const Ogre::String& invocation, bool& repeatThisInvocation) override {}
+#endif
+    };
+#endif
+
+    static CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button);
+
+    GUIManager* GUIManager::singletonPtr_s = nullptr;
+    /*static*/ const std::string GUIManager::defaultScheme_ = "TaharezGreen"; //Alternative: Orxonox (not fully complete yet, see the graphics menu)
+
+    namespace autocompletion
+    {
+        /**
+            @brief Returns the names of all currently existing OverlayGroups.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(guinames)();
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(guinames)()
+        {
+            ArgumentCompletionList names;
+            const std::vector<std::string> guis = GUIManager::getInstance().getLoadedGUIs();
+            for (const std::string gui : guis)
+                names.push_back(ArgumentCompletionListElement(gui, getLowercase(gui)));
+            return names;
+        }
+    }
+
+    SetConsoleCommand("showGUI", &GUIManager::showGUI).defaultValue(1, false).defaultValue(2, false)
+            .argumentCompleter(0, autocompletion::guinames());
+    SetConsoleCommand("hideGUI", &GUIManager::hideGUI)
+            .argumentCompleter(0, autocompletion::guinames());
+    SetConsoleCommand("toggleGUI", &GUIManager::toggleGUI).defaultValue(1, false).defaultValue(2, false)
+            .argumentCompleter(0, autocompletion::guinames());
+
+    RegisterAbstractClass(GUIManager).inheritsFrom<WindowEventListener>();
+
+    /**
+    @brief
+        Constructs the GUIManager by starting up CEGUI
+
+        Creates the interface to Ogre, sets up the CEGUI renderer and the Lua script module together with the Lua engine.
+        The log is set up and connected to the CEGUILogger.
+        After Lua setup tolua++-elements are linked to Lua-state to give Lua access to C++-code.
+        Finally initial Lua code is executed (maybe we can do this with the CEGUI startup script automatically).
+    @return true if success, otherwise false
+    */
+    GUIManager::GUIManager(const std::pair<int, int>& mousePosition)
+        : guiRenderer_(nullptr)
+        , resourceProvider_(nullptr)
+#ifndef ORXONOX_OLD_CEGUI
+        , rqListener_(nullptr)
+        , imageCodec_(nullptr)
+#endif
+        , luaState_(nullptr)
+        , scriptModule_(nullptr)
+        , guiSystem_(nullptr)
+        , ceguiLogger_(nullptr)
+        , rootWindow_(nullptr)
+        , hudRootWindow_(nullptr)
+        , menuRootWindow_(nullptr)
+        , camera_(nullptr)
+        , destructionHelper_(this)
+    {
+        RegisterObject(GUIManager);
+
+        orxout(internal_status) << "initializing GUIManager..." << endl;
+
+        this->setConfigValues();
+
+        using namespace CEGUI;
+
+        orxout(internal_info) << "Initialising CEGUI." << endl;
+
+        this->oldCEGUI_ = false;
+
+        // Note: No SceneManager specified yet
+#ifdef ORXONOX_OLD_CEGUI
+        guiRenderer_ = new OgreCEGUIRenderer(GraphicsManager::getInstance().getRenderWindow(), Ogre::RENDER_QUEUE_OVERLAY, false, 3000);
+        resourceProvider_ = guiRenderer_->createResourceProvider();
+        this->oldCEGUI_ = true;
+#else
+        guiRenderer_ = &OgreRenderer::create(*GraphicsManager::getInstance().getRenderWindow());
+        // We use our own RenderQueueListener so we can draw UNDER overlays
+        guiRenderer_->setFrameControlExecutionEnabled(false);
+        rqListener_ = new RQListener();
+        resourceProvider_ = &OgreRenderer::createOgreResourceProvider();
+        imageCodec_ = &OgreRenderer::createOgreImageCodec();
+#endif
+        resourceProvider_->setDefaultResourceGroup("General");
+
+        // Setup scripting
+        luaState_ = new LuaState();
+        rootFileInfo_ = Resource::getInfo("InitialiseGUI.lua");
+        // This is necessary to ensure that input events also use the right resource info when triggering lua functions
+        luaState_->setDefaultResourceInfo(this->rootFileInfo_);
+#ifdef ORXONOX_OLD_CEGUI
+        scriptModule_ = new LuaScriptModule(luaState_->getInternalLuaState());
+        // Ugly workaround: older CEGUILua versions don't initialise the member
+        // d_activeErrFuncIndex at all. That leads to "error in error handling"
+        // problems when a Lua error occurs.
+        // We fix this by setting the member manually.
+        reinterpret_cast<LuaScriptModuleWorkaround*>(scriptModule_)->d_activeErrFuncIndex = LUA_NOREF;
+        luaState_->doString("ORXONOX_OLD_CEGUI = true");
+#else
+        scriptModule_ = &LuaScriptModule::create(luaState_->getInternalLuaState());
+#endif
+        scriptModule_->setDefaultPCallErrorHandler(LuaState::ERROR_HANDLER_NAME);
+
+        // Create our own logger to specify the filepath
+        std::unique_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
+        ceguiLogger->setLogFilename(ConfigurablePaths::getLogPathString() + "cegui.log");
+        ceguiLogger->setLoggingLevel(static_cast<CEGUI::LoggingLevel>(this->outputLevelCeguiLog_));
+        this->ceguiLogger_ = ceguiLogger.release();
+
+        // Create the CEGUI system singleton
+#ifdef ORXONOX_OLD_CEGUI
+        guiSystem_ = new System(guiRenderer_, resourceProvider_, nullptr, scriptModule_);
+        // Add functions that have been renamed in newer versions
+        luaState_->doString("CEGUI.SchemeManager.create = CEGUI.SchemeManager.loadScheme");
+        luaState_->doString("CEGUI.Window.getUnclippedOuterRect = CEGUI.Window.getUnclippedPixelRect");
+        luaState_->doString("CEGUI.ImagesetManager.createFromImageFile= CEGUI.ImagesetManager.createImagesetFromImageFile");
+#else
+        guiSystem_ = &System::create(*guiRenderer_, resourceProvider_, nullptr, imageCodec_, scriptModule_);
+#endif
+
+        CEGUI::String defaultXMLParserName = CEGUI::System::getSingleton().getDefaultXMLParserName();
+        try
+        {
+            // Force Xerces parser (CEGUI 0.7.5+)
+            CEGUI::System::getSingleton().setXMLParser("XercesParser");
+        }
+        catch (const CEGUI::GenericException&)
+        {
+            // Fall back to default parser
+            orxout(internal_warning) << "Cannot use XercesParser for CEGUI - using " << defaultXMLParserName << " instead" << endl;
+            CEGUI::System::getSingleton().setXMLParser(defaultXMLParserName);
+        }
+
+        // Align CEGUI mouse with OIS mouse
+#if CEGUI_VERSION >= 0x000800
+        guiSystem_->getDefaultGUIContext().injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
+#else
+        guiSystem_->injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
+#endif
+
+        // Initialise the Lua framework and load the schemes
+        orxout(user_info) << "Loading user interface..." << endl;
+        this->luaState_->doFile("InitialiseGUI.lua");
+
+        // Create the root nodes
+        this->rootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("MenuWidgets/StaticImage", "AbsoluteRootWindow");
+        this->rootWindow_->setProperty("FrameEnabled", "False");
+        this->hudRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "HUDRootWindow");
+        this->menuRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "MenuRootWindow");
+        // And connect them
+#if CEGUI_VERSION >= 0x000800
+        CEGUI::System::getSingleton().getDefaultGUIContext().setRootWindow(this->rootWindow_);
+        this->rootWindow_->addChild(this->hudRootWindow_);
+        this->rootWindow_->addChild(this->menuRootWindow_);
+#else
+        CEGUI::System::getSingleton().setGUISheet(this->rootWindow_);
+        this->rootWindow_->addChildWindow(this->hudRootWindow_);
+        this->rootWindow_->addChildWindow(this->menuRootWindow_);
+#endif
+
+        // No background to start with (sets the alpha value to 0)
+        this->setBackgroundImage("");
+
+        // Set up the sheet manager in the Lua framework
+        this->luaState_->doFile("SheetManager.lua");
+
+        orxout(internal_status) << "finished initializing GUIManager" << endl;
+    }
+
+    void GUIManager::destroy()
+    {
+        orxout(internal_status) << "destroying GUIManager..." << endl;
+
+        using namespace CEGUI;
+
+#ifdef ORXONOX_OLD_CEGUI
+        safeObjectDelete(&guiSystem_);
+        safeObjectDelete(&guiRenderer_);
+        safeObjectDelete(&scriptModule_);
+#else
+        System::destroy();
+        OgreRenderer::destroyOgreResourceProvider(*resourceProvider_);
+        OgreRenderer::destroyOgreImageCodec(*imageCodec_);
+        OgreRenderer::destroy(*guiRenderer_);
+        LuaScriptModule::destroy(*scriptModule_);
+        safeObjectDelete(&ceguiLogger_);
+        safeObjectDelete(&rqListener_);
+#endif
+        safeObjectDelete(&luaState_);
+
+        orxout(internal_status) << "finished destroying GUIManager" << endl;
+    }
+
+    void GUIManager::setConfigValues(void)
+    {
+        SetConfigValue(guiScheme_, GUIManager::defaultScheme_).description("Changes the current GUI scheme.").callback(this, &GUIManager::changedGUIScheme);
+        SetConfigValue(numScrollLines_, 1).description("How many lines to scroll in a list if the scroll wheel is used");
+        SetConfigValue(bPreloadMenuSheets_, false).description("Pre-load menu sheets during startup");
+
+        SetConfigValueExternal(outputLevelCeguiLog_, BaseWriter::getConfigurableSectionName(), "outputLevelCeguiLog", CEGUI::Standard).description("The log level of the CEGUI log file").callback(this, &GUIManager::changedCeguiOutputLevel);
+    }
+
+    void GUIManager::changedGUIScheme(void)
+    {
+    }
+
+    void GUIManager::changedCeguiOutputLevel()
+    {
+        if (this->ceguiLogger_)
+            this->ceguiLogger_->setLoggingLevel(static_cast<CEGUI::LoggingLevel>(this->outputLevelCeguiLog_));
+    }
+
+    /**
+    @brief
+        used to tick the GUI
+    @param time
+        clock which provides time value for the GUI System
+
+        Ticking the GUI means updating it with a certain regularity.
+        The elapsed time since the last call is given in the time value provided by the clock.
+        This time value is then used to provide a fluent animation of the GUI.
+    */
+    void GUIManager::preUpdate(const Clock& time)
+    {
+        assert(guiSystem_);
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectTimePulse, arg::_1, time.getDeltaTime()));
+    }
+
+    /**
+    @brief
+        Tells the GUIManager which SceneManager to use
+    @param camera
+        The current camera on which the GUI should be displayed on.
+
+        In fact the GUIManager needs the SceneManager and not the Camera to display the GUI.
+        This means the GUI is not bound to a camera but rather to the SceneManager.
+        Hiding the GUI when needed can therefore not be resolved by just NOT setting the current camera.
+    */
+    void GUIManager::setCamera(Ogre::Camera* camera)
+    {
+#ifdef ORXONOX_OLD_CEGUI
+        if (camera == nullptr)
+            this->guiRenderer_->setTargetSceneManager(nullptr);
+        else
+            this->guiRenderer_->setTargetSceneManager(camera->getSceneManager());
+#else
+        if (camera_ != nullptr && camera_->getSceneManager() != nullptr)
+            camera_->getSceneManager()->removeRenderQueueListener(rqListener_);
+        if (camera != nullptr && camera->getSceneManager() != nullptr)
+            camera->getSceneManager()->addRenderQueueListener(rqListener_);
+#endif
+        this->camera_ = camera;
+    }
+
+    /**
+    @brief
+        Executes Lua code
+    @param str
+        reference to string object holding the Lua code which is to be executed
+    */
+    void GUIManager::executeCode(const std::string& str)
+    {
+        this->luaState_->doString(str, rootFileInfo_);
+    }
+
+    std::vector<std::string> GUIManager::getLoadedGUIs()
+    {
+        // TODO: is there a better way to read back a return value from lua? i.e. by using LuaState?
+        lua_State* L = this->luaState_->getInternalLuaState();
+
+        // push function
+        lua_getglobal(L, "getLoadedSheets");
+
+        // do the call (0 arguments, 1 result)
+        if (lua_pcall(L, 0, 1, 0) != 0)
+          orxout(internal_error) << "error running function: " << lua_tostring(L, -1) << endl;
+
+        // retrieve result
+        if (!lua_isstring(L, -1))
+          orxout(internal_error) << "function must return a string" << endl;
+        std::string value = lua_tostring(L, -1);
+        lua_pop(L, 1);
+
+        SubString tokens(value, ",");
+        return tokens.getAllStrings();
+    }
+
+    /** Loads a GUI sheet by Lua script
+    @param name
+        The name of the GUI (like the script name, but without the extension)
+    */
+    void GUIManager::loadGUI(const std::string& name)
+    {
+        this->executeCode("loadSheet(\"" + name + "\")");
+    }
+
+    /**
+    @brief
+        Displays specified GUI on screen
+    @param name
+        The name of the GUI
+    @param bHidePrevious
+        If true all displayed GUIs on the stack, that are below this GUI are hidden.
+    @param bNoInput
+        If true the GUI is transparent to input.
+
+        The function executes the Lua function with the same name in case the GUIManager is ready.
+    */
+    /*static*/ void GUIManager::showGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
+    {
+        GUIManager::getInstance().executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
+    }
+
+    /**
+    @brief
+        Hack-ish. Needed for GUIOverlay.
+    */
+    void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious, bool bNoInput)
+    {
+        this->executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ", " + ptr + ")");
+    }
+
+    /**
+    @brief
+        Hides specified GUI.
+    @param name
+        The name of the GUI.
+    */
+    /*static*/ void GUIManager::hideGUI(const std::string& name)
+    {
+        GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
+    }
+
+    /**
+    @brief
+        Toggles specified GUI.
+        If the GUI with the input name is already shown and on the top, it is hidden, else it is shown.
+    */
+    /*static*/ void GUIManager::toggleGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
+    {
+        GUIManager::getInstance().executeCode("getGUIFirstActive(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
+    }
+
+    /**
+    @brief
+        Helper method to toggle a specified GUI.
+        Is called by lua.
+    */
+    void GUIManager::toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show)
+    {
+        if(show)
+            GUIManager::showGUI(name, bHidePrevious, bNoInput);
+        else
+            GUIManager::hideGUI(name);
+    }
+
+    const std::string& GUIManager::createInputState(const std::string& name, tribool showCursor, tribool useKeyboard, bool bBlockJoyStick)
+    {
+        InputState* state = InputManager::getInstance().createInputState(name);
+        if (!state)
+            return BLANKSTRING;
+
+        /* Table that maps isFullScreen() and showCursor to mouseExclusive
+        isFullscreen / showCursor | True  | False | Dontcare
+        ----------------------------------------------------
+        true                      | True  | True  | Dontcare
+        ----------------------------------------------------
+        false                     | False | True  | Dontcare
+        */
+
+#ifdef ORXONOX_PLATFORM_APPLE
+        // There is no non exclusive mode on OS X yet
+        state->setMouseExclusive(true);
+#else
+        if (showCursor == dontcare)
+            state->setMouseExclusive(dontcare);
+        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == false)
+            state->setMouseExclusive(true);
+        else
+            state->setMouseExclusive(false);
+#endif
+
+        if (showCursor == true)
+            state->setMouseHandler(this);
+        else if (showCursor == false)
+            state->setMouseHandler(&InputHandler::EMPTY);
+
+        if (useKeyboard == true)
+            state->setKeyHandler(this);
+        else if (useKeyboard == false)
+            state->setKeyHandler(&InputHandler::EMPTY);
+
+        if (bBlockJoyStick)
+            state->setJoyStickHandler(&InputHandler::EMPTY);
+
+        return state->getName();
+    }
+
+    void GUIManager::keyESC()
+    {
+        this->executeCode("keyESC()");
+    }
+
+    void GUIManager::setBackgroundImage(const std::string& imageSet, const std::string imageName)
+    {
+        if (imageSet.empty() || imageName.empty())
+            this->setBackgroundImage("");
+        else
+            this->setBackgroundImage("set: " + imageSet + " image: " + imageName);
+    }
+
+    void GUIManager::setBackgroundImage(const std::string& image)
+    {
+        if (image.empty())
+            this->rootWindow_->setProperty("Alpha", "0.0");
+        else
+            this->rootWindow_->setProperty("Alpha", "1.0");
+        this->rootWindow_->setProperty("Image", image);
+    }
+
+    void GUIManager::buttonPressed(const KeyEvent& evt)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectKeyDown, arg::_1, (CEGUI::Key::Scan) evt.getKeyCode())); // TODO: will this cast always work?
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectChar, arg::_1, evt.getText()));
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectKeyDown, arg::_1, evt.getKeyCode()));
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectChar, arg::_1, evt.getText()));
+#endif
+    }
+
+    void GUIManager::buttonReleased(const KeyEvent& evt)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectKeyUp, arg::_1, (CEGUI::Key::Scan) evt.getKeyCode())); // TODO: will this cast always work?
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectKeyUp, arg::_1, evt.getKeyCode()));
+#endif
+    }
+
+    /**
+    @brief
+        Function receiving a mouse button pressed event.
+    @param id
+        ID of the mouse button which got pressed
+
+        This function is inherited by MouseHandler and injects the event into CEGUI.
+        It is for CEGUI to process the event.
+    */
+    void GUIManager::buttonPressed(MouseButtonCode::ByEnum id)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectMouseButtonDown, arg::_1, convertButton(id)));
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectMouseButtonDown, arg::_1, convertButton(id)));
+#endif
+    }
+
+    /**
+    @brief
+        Function receiving a mouse button released event.
+    @param id
+        ID of the mouse button which got released
+
+        This function is inherited by MouseHandler and injects the event into CEGUI.
+        It is for CEGUI to process the event.
+    */
+    void GUIManager::buttonReleased(MouseButtonCode::ByEnum id)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectMouseButtonUp, arg::_1, convertButton(id)));
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectMouseButtonUp, arg::_1, convertButton(id)));
+#endif
+    }
+
+    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectMousePosition, arg::_1, (float)abs.x, (float)abs.y));
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectMousePosition, arg::_1, (float)abs.x, (float)abs.y));
+#endif
+    }
+
+    void GUIManager::mouseScrolled(int abs, int rel)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectMouseWheelChange, arg::_1, (float)sgn(rel) * this->numScrollLines_));
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectMouseWheelChange, arg::_1, (float)sgn(rel) * this->numScrollLines_));
+#endif
+    }
+
+    /**
+        @brief Indicates that the mouse left the application's window.
+    */
+    void GUIManager::mouseLeft()
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->protectedCeguiContextCall(std::bind(&CEGUI::GUIContext::injectMouseLeaves, arg::_1));
+#else
+        this->protectedCeguiSystemCall(std::bind(&CEGUI::System::injectMouseLeaves, arg::_1));
+#endif
+    }
+
+    /**
+    @brief
+        converts mouse event code to CEGUI event code
+    @param button
+        code of the mouse button as we use it in Orxonox
+    @return
+        code of the mouse button as it is used by CEGUI
+
+        Simple conversion from mouse event code in Orxonox to the one used in CEGUI.
+     */
+    static inline CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button)
+    {
+        switch (button)
+        {
+        case MouseButtonCode::Left:
+            return CEGUI::LeftButton;
+
+        case MouseButtonCode::Right:
+            return CEGUI::RightButton;
+
+        case MouseButtonCode::Middle:
+            return CEGUI::MiddleButton;
+
+        case MouseButtonCode::Button3:
+            return CEGUI::X1Button;
+
+        case MouseButtonCode::Button4:
+            return CEGUI::X2Button;
+
+        default:
+            return CEGUI::NoButton;
+        }
+    }
+
+    /**
+    @copydoc protectedCeguiSystemCall
+    @param function
+        Any callable object/function that takes one parameter.
+    @param object
+        Object to be used as an argument for the @p function
+    @return
+        True if input was handled, false otherwise. A caught exception yields true.
+    */
+    template <typename FunctionType, typename ObjectType>
+    bool GUIManager::protectedCall(FunctionType function, ObjectType object)
+    {
+        try
+        {
+            return function(object);
+        }
+        catch (CEGUI::ScriptException& ex)
+        {
+            // Display the error and proceed. See @remarks why this can be dangerous.
+            orxout(internal_error) << ex.getMessage() << endl;
+            return true;
+        }
+    }
+
+    /**
+        Executes a CEGUI function normally, but catches CEGUI::ScriptException.
+        When a ScriptException occurs, the error message will be displayed and
+        the program carries on.
+    @remarks
+        The exception behaviour may pose problems if the code is not written
+        exception-safe (and you can forget about that in Lua). The program might
+        be left in an undefined state. But otherwise one script error would
+        terminate the whole program...
+    @note
+        Your life gets easier if you use std::bind to create the object/function.
+    @param function
+        Any callable object/function that takes this->guiSystem_ as its only parameter.
+    @return
+        True if input was handled, false otherwise. A caught exception yields true.
+    */
+    template <typename FunctionType>
+    bool GUIManager::protectedCeguiSystemCall(FunctionType function)
+    {
+        return this->protectedCall(function, this->guiSystem_);
+    }
+
+#if CEGUI_VERSION >= 0x000800
+    template <typename FunctionType>
+    bool GUIManager::protectedCeguiContextCall(FunctionType function)
+    {
+        return this->protectedCall(function, this->guiSystem_->getDefaultGUIContext());
+    }
+#endif
+
+    /**
+    @brief
+        Subscribe the input function to the input event for the input window.
+        This is a helper to be used in lua, because subscribeScriptedEvent() doesn't work in lua.
+    @param window
+        The window for which the event is subscribed.
+    @param event
+        The type of event to which we subscribe.
+    @param function
+        The function that is called when the event occurs.
+    */
+    void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
+    {
+        window->subscribeScriptedEvent(event, function);
+    }
+
+    /**
+    @brief
+        Set the input tooltip text for the input ListboxItem.
+    @param item
+        The ListboxItem for which the tooltip should be set.
+    @param tooltip
+        The tooltip text that should be set.
+    */
+    void GUIManager::setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& tooltip)
+    {
+        item->setTooltipText(tooltip);
+    }
+
+    /**
+    @brief
+        Set whether the tooltips for the input Listbox are enabled.
+    @param listbox
+        The Listbox for which to enable (or disable) tooltips.
+    @param enabled
+        Whether to enable or disable the tooltips.
+    */
+    void GUIManager::setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled)
+    {
+        listbox->setItemTooltipsEnabled(enabled);
+    }
+
+    /** Helper method to get the developer's mode without having to export Core.h.
+    @see Core::inDevMode
+    */
+    /*static*/ bool GUIManager::inDevMode()
+    {
+         return Core::getInstance().getConfig()->inDevMode();
+    }
+
+    /**
+        @brief Callback of window event listener, called if the window is resized. Sets the display size of CEGUI.
+    */
+    void GUIManager::windowResized(unsigned int newWidth, unsigned int newHeight)
+    {
+#if CEGUI_VERSION >= 0x000800
+        this->guiRenderer_->setDisplaySize(CEGUI::Sizef((float)newWidth, (float)newHeight));
+        this->rootWindow_->setSize(CEGUI::USize(CEGUI::UDim(1, (float)newWidth), CEGUI::UDim(1, (float)newHeight)));
+#else
+        this->guiRenderer_->setDisplaySize(CEGUI::Size((float)newWidth, (float)newHeight));
+        this->rootWindow_->setSize(CEGUI::UVector2(CEGUI::UDim(1, (float)newWidth), CEGUI::UDim(1, (float)newHeight)));
+#endif
+    }
+
+    /**
+        @brief Notify CEGUI if the windows loses the focus (stops highlighting of menu items, etc).
+    */
+    void GUIManager::windowFocusChanged(bool bFocus)
+    {
+        if (!bFocus)
+            this->mouseLeft();
+    }
+
+    /**
+    @brief
+        Adds a new freetype font to the CEGUI system.
+    @param name
+        The name of the new font.
+    @param size
+        The font size of the new font in pixels.
+        @param fontName
+        The filename of the font.
+    */
+    /*static*/ void GUIManager::addFontHelper(const std::string& name, int size, const std::string& fontName)
+    {
+#ifdef ORXONOX_OLD_CEGUI
+        if(CEGUI::FontManager::getSingleton().isFontPresent(name)) // If a font with that name already exists.
+            return;
+
+        CEGUI::Font* font = nullptr;
+        CEGUI::XMLAttributes xmlAttributes;
+
+        // Attributes specified within CEGUIFont
+        xmlAttributes.add("Name", name);
+        xmlAttributes.add("Filename", fontName);
+        xmlAttributes.add("ResourceGroup", "");
+        xmlAttributes.add("AutoScaled", "true");
+        xmlAttributes.add("NativeHorzRes", "800");
+        xmlAttributes.add("NativeVertRes", "600");
+
+        // Attributes specified within CEGUIXMLAttributes
+        xmlAttributes.add("Size", multi_cast<std::string>(size));
+        xmlAttributes.add("AntiAlias", "true");
+
+        font = CEGUI::FontManager::getSingleton().createFont("FreeType", xmlAttributes);
+        if(font != nullptr)
+            font->load();
+#else
+        if(CEGUI::FontManager::getSingleton().isDefined(name)) // If a font with that name already exists.
+            return;
+
+    #if CEGUI_VERSION >= 0x000800
+        CEGUI::FontManager::getSingleton().createFreeTypeFont(name, (float)size, true, fontName, "", CEGUI::ASM_Both, CEGUI::Sizef(800.0f, 600.0f));
+    #else
+        CEGUI::FontManager::getSingleton().createFreeTypeFont(name, (float)size, true, fontName, "", true, 800.0f, 600.0f);
+    #endif
+#endif
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/GUIManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GUIManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GUIManager.h	(revision 11817)
@@ -0,0 +1,226 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Graphics
+*/
+
+#ifndef _GUIManager_H__
+#define _GUIManager_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <string>
+#include <memory>
+
+#if CEGUI_VERSION >= 0x000800
+#   include <CEGUI/ForwardRefs.h>
+#   include <CEGUI/Version.h>
+#else
+#   include <CEGUIForwardRefs.h>
+#   include <CEGUIVersion.h>
+#endif
+
+#include "util/DestructionHelper.h"
+#include "util/OgreForwardRefs.h"
+#include "util/tribool.h"
+#include "util/Singleton.h"
+#include "input/InputHandler.h"
+#include "WindowEventListener.h"
+
+#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
+#  define ORXONOX_OLD_CEGUI
+#endif
+
+namespace orxonox // tolua_export
+{ // tolua_export
+    class PlayerInfo; // Forward declaration
+
+    // Acquaint Tolua with tribool
+    /* tolua_begin
+    struct dontcare_keyword_t
+    {
+        dontcare_keyword_t();
+    };
+    class tribool
+    {
+        tribool(bool value);
+        tribool(dontcare_keyword_t);
+        bool operator==(tribool);
+    };
+    tolua_end */
+
+    /**
+    @class GUIManager
+    @brief
+        Provides a simple interface to CEGUI with tolua methods and console commands. It also acts as a key and mouse handler.
+
+        The GUIManager is a singleton and can be called anywhere when access on the GUI is needed.
+
+        Since the GUI needs user input, the GUIManager implements the functions needed to act as a key and/or mouse handler.
+        Those input events are then injected into CEGUI in Lua.
+    */
+    class _CoreExport GUIManager // tolua_export
+        : public Singleton<GUIManager>, public InputHandler, public WindowEventListener
+    { // tolua_export
+        friend class Singleton<GUIManager>;
+    public:
+        GUIManager(const std::pair<int, int>& mousePosition);
+
+        //! Leave empty and use cleanup() instead
+        ~GUIManager() = default;
+        /// Destructor that also executes when object fails to construct
+        void destroy();
+
+        void setConfigValues(void);
+        void changedGUIScheme(void);
+
+        void preUpdate(const Clock& time);
+
+        std::vector<std::string> getLoadedGUIs();
+
+        void loadGUI(const std::string& name);
+        static void showGUI(const std::string& name, bool bHidePrevious = false, bool bNoInput = false);
+        void showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious = false, bool bNoInput = false);
+        static void hideGUI(const std::string& name);
+        static void toggleGUI(const std::string& name, bool bHidePrevious = false, bool bNoInput = false);
+        void toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show); // tolua_export
+        void keyESC();
+        void setBackgroundImage(const std::string& imageSet, const std::string imageName); // tolua_export
+        void setBackgroundImage(const std::string& image);
+
+        static bool preloadMenuSheets() { return GUIManager::getInstance().bPreloadMenuSheets_; } // tolua_export
+        static bool inDevMode(void); // tolua_export
+
+        //! Creates a new InputState to be used with a GUI Sheet
+        const std::string& createInputState(const std::string& name, tribool showCursor = tribool(true), tribool useKeyboard = tribool(true), bool bBlockJoyStick = false); // tolua_export
+        LuaState* getLuaState(void)
+            { return this->luaState_; }
+
+        //! Returns the root window for all menu sheets
+        CEGUI::Window* getMenuRootWindow() { return this->menuRootWindow_; } // tolua_export
+        //! Returns the root window for all HUD sheets
+        CEGUI::Window* getHUDRootWindow() { return this->hudRootWindow_; } // tolua_export
+
+        void setCamera(Ogre::Camera* camera);
+        Ogre::Camera* getCamera() { return this->camera_; }
+
+        inline void setPlayer(const std::string& guiname, PlayerInfo* player)
+            { this->players_[guiname] = player; }
+        inline orxonox::PlayerInfo* getPlayer(const std::string& guiname) const { std::map<std::string, PlayerInfo*>::const_iterator it = this->players_.find(guiname); return (it != this->players_.end()) ? it->second : nullptr; } // tolua_export
+
+        // TODO: Temporary hack because the tolua exported CEGUI method does not seem to work
+        static void subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function); // tolua_export
+        static void setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& toooltip); // tolua_export
+        static void setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled); // tolua_export
+        static void addFontHelper(const std::string& name, int size, const std::string& fontName); // tolua_export
+
+        static GUIManager& getInstance() { return Singleton<GUIManager>::getInstance(); } // tolua_export
+
+        /**
+        @brief Check whether CEGUI is version < 0.7.
+        @return Returns true if the CEGUI version is < 0.7. False otherwise.
+        */
+        inline bool usingOldCEGUI(void) { return this->oldCEGUI_; } // tolua_export
+
+    private:
+        // non-copyable:
+        GUIManager(const GUIManager&) = delete;
+        GUIManager& operator=(const GUIManager&) = delete;
+
+        void executeCode(const std::string& str);
+
+        template <typename FunctionType, typename ObjectType>
+        bool protectedCall(FunctionType function, ObjectType object);
+
+        template <typename FunctionType>
+        bool protectedCeguiSystemCall(FunctionType function);
+
+#if CEGUI_VERSION >= 0x000800
+        template <typename FunctionType>
+        bool protectedCeguiContextCall(FunctionType function);
+#endif
+
+        void changedCeguiOutputLevel();
+
+        // keyHandler functions
+        virtual void buttonPressed (const KeyEvent& evt) override;
+        virtual void buttonReleased(const KeyEvent& evt) override;
+
+        // mouseHandler functions
+        virtual void buttonPressed (MouseButtonCode::ByEnum id) override;
+        virtual void buttonReleased(MouseButtonCode::ByEnum id) override;
+        virtual void mouseMoved    (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize) override;
+        virtual void mouseScrolled (int abs, int rel) override;
+        void mouseLeft     ();
+
+        // window event handler
+        virtual void windowResized(unsigned int newWidth, unsigned int newHeight) override;
+        virtual void windowFocusChanged(bool bFocus) override;
+
+#ifdef ORXONOX_OLD_CEGUI
+        CEGUI::OgreCEGUIRenderer*            guiRenderer_;          //!< CEGUI's interface to the Ogre Engine
+        CEGUI::ResourceProvider*             resourceProvider_;     //!< CEGUI's resource provider
+#else
+        CEGUI::OgreRenderer*                 guiRenderer_;          //!< CEGUI's interface to the Ogre Engine
+        CEGUI::OgreResourceProvider*         resourceProvider_;     //!< CEGUI's resource provider
+        Ogre::RenderQueueListener*           rqListener_;           //!< RQ listener so we can draw UNDER Ogre overlays
+        CEGUI::OgreImageCodec*               imageCodec_;
+#endif
+        LuaState*                            luaState_;             //!< LuaState, access point to the Lua engine
+        CEGUI::LuaScriptModule*              scriptModule_;         //!< CEGUI's script module to use Lua
+        CEGUI::System*                       guiSystem_;            //!< CEGUI's main system
+        std::shared_ptr<ResourceInfo>        rootFileInfo_;         //!< Resource information about the root script
+        CEGUI::Logger*                       ceguiLogger_;          //!< CEGUI's logger to be able to log CEGUI errors in our log
+        int                                  outputLevelCeguiLog_;  //!< CEGUI's log level
+        CEGUI::Window*                       rootWindow_;           //!< Root node for all windows
+        CEGUI::Window*                       hudRootWindow_;        //!< Root node for the HUD sheets
+        CEGUI::Window*                       menuRootWindow_;       //!< Root node for the menu sheets (used by Lua)
+        std::map<std::string, PlayerInfo*>   players_;              //!< Stores the player (owner) for each GUI
+        Ogre::Camera*                        camera_;               //!< Camera used to render the scene with the GUI
+
+        /// Helper object that executes the surrogate destructor destroy()
+        DestructionHelper<GUIManager>        destructionHelper_;
+
+        static GUIManager*                   singletonPtr_s;        //!< Singleton reference to GUIManager
+
+        // The used CEGUI scheme.
+        static const std::string defaultScheme_;
+        std::string guiScheme_;
+        bool oldCEGUI_;
+
+        int numScrollLines_;        ///< How many lines to scroll in a list if the scroll wheel is used
+        bool bPreloadMenuSheets_;   ///< If true, menu sheets are pre-loaded during startup
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _GUIManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Game.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Game.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Game.cc	(revision 11817)
@@ -0,0 +1,630 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the Game class.
+*/
+
+#include "Game.h"
+
+#include <exception>
+#include <loki/ScopeGuard.h>
+
+#include "util/Clock.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/Sleep.h"
+#include "util/SubString.h"
+#include "Core.h"
+#include "commandline/CommandLineParser.h"
+#include "GameConfig.h"
+#include "GameMode.h"
+#include "GameState.h"
+#include "GraphicsManager.h"
+#include "GUIManager.h"
+#include "command/ConsoleCommandIncludes.h"
+
+namespace orxonox
+{
+    static void stop_game()
+        { Game::getInstance().stop(); }
+    SetConsoleCommand("exit", &stop_game);
+    static void printFPS()
+        { orxout(message) << Game::getInstance().getAvgFPS() << endl; }
+    SetConsoleCommand("Stats", "printFPS", &printFPS);
+    static void printTickTime()
+        { orxout(message) << Game::getInstance().getAvgTickTime() << endl; }
+    SetConsoleCommand("Stats", "printTickTime", &printTickTime);
+
+    std::map<std::string, GameStateInfo> Game::gameStateDeclarations_s;
+    Game* Game::singletonPtr_s = nullptr;
+
+    //! Represents one node of the game state tree.
+    struct GameStateTreeNode
+    {
+        std::string name_;
+        std::weak_ptr<GameStateTreeNode> parent_;
+        std::vector<std::shared_ptr<GameStateTreeNode>> children_;
+    };
+
+    Game::Game(const std::string& cmdLine)
+        : gameClock_(nullptr)
+        , core_(nullptr)
+        , bChangingState_(false)
+        , bAbort_(false)
+        , config_(nullptr)
+        , destructionHelper_(this)
+    {
+        orxout(internal_status) << "initializing Game object..." << endl;
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+        minimumSleepTime_ = 1000/*us*/;
+#else
+        minimumSleepTime_ = 0/*us*/;
+#endif
+
+        // reset statistics
+        this->statisticsStartTime_ = 0;
+        this->statisticsTickTimes_.clear();
+        this->periodTickTime_ = 0;
+        this->periodTime_ = 0;
+        this->avgFPS_ = 0.0f;
+        this->avgTickTime_ = 0.0f;
+        this->excessSleepTime_ = 0;
+
+        // Create an empty root state
+        this->declareGameState<GameState>("GameState", "emptyRootGameState", true, false);
+
+        // Set up a basic clock to keep time
+        this->gameClock_ = new Clock();
+
+        // Create the Core
+        orxout(internal_info) << "creating Core object:" << endl;
+        this->core_ = new Core(cmdLine);
+        this->core_->loadModules();
+
+        // Do this after the Core creation!
+        this->config_ = new GameConfig();
+
+        // After the core has been created, we can safely instantiate the GameStates that don't require graphics
+        for (const auto& mapEntry : gameStateDeclarations_s)
+        {
+            if (!mapEntry.second.bGraphicsMode)
+                constructedStates_[mapEntry.second.stateName] = GameStateFactory::fabricate(mapEntry.second);
+        }
+
+        // The empty root state is ALWAYS loaded!
+        this->rootStateNode_ = std::shared_ptr<GameStateTreeNode>(std::make_shared<GameStateTreeNode>());
+        this->rootStateNode_->name_ = "emptyRootGameState";
+        this->loadedTopStateNode_ = this->rootStateNode_;
+        this->loadedStates_.push_back(this->getState(rootStateNode_->name_));
+
+        orxout(internal_status) << "finished initializing Game object" << endl;
+    }
+
+    void Game::destroy()
+    {
+        orxout(internal_status) << "destroying Game object..." << endl;
+
+        assert(loadedStates_.size() <= 1); // Just empty root GameState
+        // Destroy all GameStates (std::shared_ptrs take care of actual destruction)
+        constructedStates_.clear();
+
+        GameStateFactory::getFactories().clear();
+        safeObjectDelete(&config_);
+        if (this->core_)
+            this->core_->unloadModules();
+        safeObjectDelete(&core_);
+        safeObjectDelete(&gameClock_);
+
+        orxout(internal_status) << "finished destroying Game object..." << endl;
+    }
+
+    /**
+    @brief
+        Main loop of the orxonox game.
+    @note
+        We use the Ogre::Timer to measure time since it uses the most precise
+        method an any platform (however the windows timer lacks time when under
+        heavy kernel load!).
+    */
+    void Game::run()
+    {
+        if (this->requestedStateNodes_.empty())
+            orxout(user_error) << "Starting game without requesting GameState. This automatically terminates the program." << endl;
+
+        // Update the GameState stack if required. We do this already here to have a properly initialized game before entering the main loop
+        this->updateGameStateStack();
+
+        orxout(user_status) << "Game loaded" << endl;
+        orxout(internal_status) << "-------------------- starting main loop --------------------" << endl;
+
+        // START GAME
+        // first delta time should be about 0 seconds
+        this->gameClock_->capture();
+        // A first item is required for the fps limiter
+        StatisticsTickInfo tickInfo = {0, 0};
+        statisticsTickTimes_.push_back(tickInfo);
+        while (!this->bAbort_ && (!this->loadedStates_.empty() || this->requestedStateNodes_.size() > 0))
+        {
+            // Generate the dt
+            this->gameClock_->capture();
+
+            // Statistics init
+            StatisticsTickInfo tickInfo = {gameClock_->getMicroseconds(), 0};
+            statisticsTickTimes_.push_back(tickInfo);
+            this->periodTime_ += this->gameClock_->getDeltaTimeMicroseconds();
+
+            // Update the GameState stack if required
+            this->updateGameStateStack();
+
+            // Core preUpdate
+            try
+                { this->core_->preUpdate(*this->gameClock_); }
+            catch (...)
+            {
+                orxout(user_error) << "An exception occurred in the Core preUpdate: " << Exception::handleMessage() << endl;
+                orxout(user_error) << "This should really never happen! Closing the program." << endl;
+                this->stop();
+                break;
+            }
+
+            // Update the GameStates bottom up in the stack
+            this->updateGameStates();
+
+            // Core postUpdate
+            try
+                { this->core_->postUpdate(*this->gameClock_); }
+            catch (...)
+            {
+                orxout(user_error) << "An exception occurred in the Core postUpdate: " << Exception::handleMessage() << endl;
+                orxout(user_error) << "This should really never happen! Closing the program." << endl;
+                this->stop();
+                break;
+            }
+
+            // Evaluate statistics
+            this->updateStatistics();
+
+            // Limit frame rate
+            static bool hasVSync = GameMode::showsGraphics() && GraphicsManager::getInstance().hasVSyncEnabled(); // can be static since changes of VSync currently require a restart
+            if (this->config_->getFpsLimit() > 0 && !hasVSync)
+                this->updateFPSLimiter();
+        }
+
+        orxout(internal_status) << "-------------------- finished main loop --------------------" << endl;
+
+        // UNLOAD all remaining states
+        while (this->loadedStates_.size() > 1)
+            this->unloadState(this->loadedStates_.back()->getName());
+        this->loadedTopStateNode_ = this->rootStateNode_;
+        this->requestedStateNodes_.clear();
+    }
+
+    void Game::updateGameStateStack()
+    {
+        while (this->requestedStateNodes_.size() > 0)
+        {
+            std::shared_ptr<GameStateTreeNode> requestedStateNode = this->requestedStateNodes_.front();
+            assert(this->loadedTopStateNode_);
+            if (!this->loadedTopStateNode_->parent_.expired() && requestedStateNode == this->loadedTopStateNode_->parent_.lock())
+                this->unloadState(loadedTopStateNode_->name_);
+            else // has to be child
+            {
+                try
+                {
+                    this->loadState(requestedStateNode->name_);
+                }
+                catch (...)
+                {
+                    orxout(user_error) << "Loading GameState '" << requestedStateNode->name_ << "' failed: " << Exception::handleMessage() << endl;
+                    // All scheduled operations have now been rendered inert --> flush them and issue a warning
+                    if (this->requestedStateNodes_.size() > 1)
+                        orxout(internal_info) << "All " << this->requestedStateNodes_.size() - 1 << " scheduled transitions have been ignored." << endl;
+                    this->requestedStateNodes_.clear();
+                    break;
+                }
+            }
+            this->loadedTopStateNode_ = requestedStateNode;
+            this->requestedStateNodes_.erase(this->requestedStateNodes_.begin());
+        }
+    }
+
+    void Game::updateGameStates()
+    {
+        // Note: The first element is the empty root state, which doesn't need ticking
+        for (const std::shared_ptr<GameState>& state : this->loadedStates_)
+        {
+            try
+            {
+                // Add tick time for most of the states
+                uint64_t timeBeforeTick = 0;
+                if (state->getInfo().bIgnoreTickTime)
+                    timeBeforeTick = this->gameClock_->getRealMicroseconds();
+                state->update(*this->gameClock_);
+                if (state->getInfo().bIgnoreTickTime)
+                    this->subtractTickTime(static_cast<int32_t>(this->gameClock_->getRealMicroseconds() - timeBeforeTick));
+            }
+            catch (...)
+            {
+                orxout(user_error) << "An exception occurred while updating '" << state->getName() << "': " << Exception::handleMessage() << endl;
+                orxout(user_error) << "This should really never happen!" << endl;
+                orxout(user_error) << "Unloading all GameStates depending on the one that crashed." << endl;
+                std::shared_ptr<GameStateTreeNode> current = this->loadedTopStateNode_;
+                while (current->name_ != state->getName() && current)
+                    current = current->parent_.lock();
+                if (current && current->parent_.lock())
+                    this->requestState(current->parent_.lock()->name_);
+                else
+                    this->stop();
+                break;
+            }
+        }
+    }
+
+    void Game::updateStatistics()
+    {
+        // Add the tick time of this frame (rendering time has already been subtracted)
+        uint64_t currentTime = gameClock_->getMicroseconds();
+        uint64_t currentRealTime = gameClock_->getRealMicroseconds();
+        this->statisticsTickTimes_.back().tickLength += (uint32_t)(currentRealTime - currentTime);
+        this->periodTickTime_ += (uint32_t)(currentRealTime - currentTime);
+        if (this->periodTime_ > this->config_->getStatisticsRefreshCycle())
+        {
+            std::list<StatisticsTickInfo>::iterator it = this->statisticsTickTimes_.begin();
+            assert(it != this->statisticsTickTimes_.end());
+            int64_t lastTime = currentTime - this->config_->getStatisticsAvgLength();
+            if (static_cast<int64_t>(it->tickTime) < lastTime)
+            {
+                do
+                {
+                    assert(this->periodTickTime_ >= it->tickLength);
+                    this->periodTickTime_ -= it->tickLength;
+                    ++it;
+                    assert(it != this->statisticsTickTimes_.end());
+                } while (static_cast<int64_t>(it->tickTime) < lastTime);
+                this->statisticsTickTimes_.erase(this->statisticsTickTimes_.begin(), it);
+            }
+
+            uint32_t framesPerPeriod = this->statisticsTickTimes_.size();
+            // Why minus 1? No idea, but otherwise the fps rate is always (from 10 to 200!) one frame too low
+            this->avgFPS_ = -1 + static_cast<float>(framesPerPeriod) / (currentTime - this->statisticsTickTimes_.front().tickTime) * 1000000.0f;
+            this->avgTickTime_ = static_cast<float>(this->periodTickTime_) / framesPerPeriod / 1000.0f;
+
+            this->periodTime_ -= this->config_->getStatisticsRefreshCycle();
+        }
+    }
+
+    void Game::updateFPSLimiter()
+    {
+        uint64_t nextTime = gameClock_->getMicroseconds() - excessSleepTime_ + static_cast<uint32_t>(1000000.0f / this->config_->getFpsLimit());
+        uint64_t currentRealTime = gameClock_->getRealMicroseconds();
+        while (currentRealTime < nextTime - minimumSleepTime_)
+        {
+            usleep((unsigned long)(nextTime - currentRealTime));
+            currentRealTime = gameClock_->getRealMicroseconds();
+        }
+        // Integrate excess to avoid steady state error
+        excessSleepTime_ = (int)(currentRealTime - nextTime);
+        // Anti windup
+        if (excessSleepTime_ > 50000) // 20ms is about the maximum time Windows would sleep for too long
+            excessSleepTime_ = 50000;
+    }
+
+    void Game::stop()
+    {
+        orxout(user_status) << "Exit" << endl;
+        this->bAbort_ = true;
+    }
+
+    void Game::subtractTickTime(int32_t length)
+    {
+        assert(!this->statisticsTickTimes_.empty());
+        this->statisticsTickTimes_.back().tickLength -= length;
+        this->periodTickTime_ -= length;
+    }
+
+
+    /***** GameState related *****/
+
+    void Game::requestState(const std::string& name)
+    {
+        if (!this->checkState(name))
+        {
+            orxout(user_warning) << "GameState named '" << name << "' doesn't exist!" << endl;
+            return;
+        }
+
+        if (this->bChangingState_)
+        {
+            orxout(user_warning) << "Requesting GameStates while loading/unloading a GameState is illegal! Ignoring." << endl;
+            return;
+        }
+
+        std::shared_ptr<GameStateTreeNode> lastRequestedNode;
+        if (this->requestedStateNodes_.empty())
+            lastRequestedNode = this->loadedTopStateNode_;
+        else
+            lastRequestedNode = this->requestedStateNodes_.back();
+        if (name == lastRequestedNode->name_)
+        {
+            orxout(user_warning) << "Requesting the currently active state! Ignoring." << endl;
+            return;
+        }
+
+        // Check children first
+        std::vector<std::shared_ptr<GameStateTreeNode>> requestedNodes;
+        for (unsigned int i = 0; i < lastRequestedNode->children_.size(); ++i)
+        {
+            if (lastRequestedNode->children_[i]->name_ == name)
+            {
+                requestedNodes.push_back(lastRequestedNode->children_[i]);
+                break;
+            }
+        }
+
+        if (requestedNodes.empty())
+        {
+            // Check parent and all its grand parents
+            std::shared_ptr<GameStateTreeNode> currentNode = lastRequestedNode;
+            while (currentNode != nullptr)
+            {
+                if (currentNode->name_ == name)
+                    break;
+                currentNode = currentNode->parent_.lock();
+                requestedNodes.push_back(currentNode);
+            }
+            if (currentNode == nullptr)
+                requestedNodes.clear();
+        }
+
+        if (requestedNodes.empty())
+            orxout(user_error) << "Requested GameState transition is not allowed. Ignoring." << endl;
+        else
+            this->requestedStateNodes_.insert(requestedStateNodes_.end(), requestedNodes.begin(), requestedNodes.end());
+    }
+
+    void Game::requestStates(const std::string& names)
+    {
+        SubString tokens(names, ",;", " ");
+        for (unsigned int i = 0; i < tokens.size(); ++i)
+            this->requestState(tokens[i]);
+    }
+
+    void Game::popState()
+    {
+        std::shared_ptr<GameStateTreeNode> lastRequestedNode;
+        if (this->requestedStateNodes_.empty())
+            lastRequestedNode = this->loadedTopStateNode_;
+        else
+            lastRequestedNode = this->requestedStateNodes_.back();
+        if (lastRequestedNode != this->rootStateNode_)
+            this->requestState(lastRequestedNode->parent_.lock()->name_);
+        else
+            orxout(internal_warning) << "Can't pop the internal dummy root GameState" << endl;
+    }
+
+    std::shared_ptr<GameState> Game::getState(const std::string& name)
+    {
+        GameStateMap::const_iterator it = constructedStates_.find(name);
+        if (it != constructedStates_.end())
+            return it->second;
+        else
+        {
+            std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(name);
+            if (it != gameStateDeclarations_s.end())
+                orxout(internal_error) << "GameState '" << name << "' has not yet been loaded." << endl;
+            else
+                orxout(internal_error) << "Could not find GameState '" << name << "'." << endl;
+            return std::shared_ptr<GameState>();
+        }
+    }
+
+    void Game::setStateHierarchy(const std::string& str)
+    {
+        // Split string into pieces of the form whitespacesText
+        std::vector<std::pair<std::string, int>> stateStrings;
+        size_t pos = 0;
+        size_t startPos = 0;
+        while (pos < str.size())
+        {
+            int indentation = 0;
+            while (pos < str.size() && str[pos] == ' ')
+                ++indentation, ++pos;
+            startPos = pos;
+            while (pos < str.size() && str[pos] != ' ')
+                ++pos;
+            stateStrings.emplace_back(str.substr(startPos, pos - startPos), indentation);
+        }
+        if (stateStrings.empty())
+            ThrowException(GameState, "Emtpy GameState hierarchy provided, terminating.");
+        // Add element with large identation to detect the last with just an iterator
+        stateStrings.emplace_back(std::string(), -1);
+
+        // Parse elements recursively
+        std::vector<std::pair<std::string, int>>::const_iterator begin = stateStrings.begin();
+        parseStates(begin, this->rootStateNode_);
+    }
+
+    /*** Internal ***/
+
+    void Game::parseStates(std::vector<std::pair<std::string, int>>::const_iterator& it, std::shared_ptr<GameStateTreeNode> currentNode)
+    {
+        SubString tokens(it->first, ",");
+        std::vector<std::pair<std::string, int>>::const_iterator startIt = it;
+
+        for (unsigned int i = 0; i < tokens.size(); ++i)
+        {
+            it = startIt; // Reset iterator to the beginning of the sub tree
+            if (!this->checkState(tokens[i]))
+                ThrowException(GameState, "GameState with name '" << tokens[i] << "' not found!");
+            if (tokens[i] == this->rootStateNode_->name_)
+                ThrowException(GameState, "You shouldn't use 'emptyRootGameState' in the hierarchy...");
+            std::shared_ptr<GameStateTreeNode> node(std::make_shared<GameStateTreeNode>());
+            node->name_ = tokens[i];
+            node->parent_ = currentNode;
+            currentNode->children_.push_back(node);
+
+            int currentLevel = it->second;
+            ++it;
+            while (it->second != -1)
+            {
+                if (it->second <= currentLevel)
+                    break;
+                else if (it->second == currentLevel + 1)
+                    parseStates(it, node);
+                else
+                    ThrowException(GameState, "Indentation error while parsing the hierarchy.");
+            }
+        }
+    }
+
+    void Game::loadGraphics()
+    {
+        if (!GameMode::showsGraphics())
+        {
+            orxout(user_status) << "Loading graphics" << endl;
+            orxout(internal_info) << "loading graphics in Game" << endl;
+
+            core_->loadGraphics();
+            Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics, true);
+
+            // Construct all the GameStates that require graphics
+            for (const auto& mapEntry : gameStateDeclarations_s)
+            {
+                if (mapEntry.second.bGraphicsMode)
+                {
+                    // Game state loading failure is serious --> don't catch
+                    std::shared_ptr<GameState> gameState = GameStateFactory::fabricate(mapEntry.second);
+                    if (!constructedStates_.insert(std::make_pair(
+                        mapEntry.second.stateName, gameState)).second)
+                        assert(false); // GameState was already created!
+                }
+            }
+            graphicsUnloader.Dismiss();
+
+            orxout(internal_info) << "finished loading graphics in Game" << endl;
+        }
+    }
+
+    void Game::unloadGraphics(bool loadGraphicsManagerWithoutRenderer)
+    {
+        if (GameMode::showsGraphics())
+        {
+            orxout(user_status) << "Unloading graphics" << endl;
+            orxout(internal_info) << "unloading graphics in Game" << endl;
+
+            // Destroy all the GameStates that require graphics
+            for (GameStateMap::iterator it = constructedStates_.begin(); it != constructedStates_.end();)
+            {
+                if (it->second->getInfo().bGraphicsMode)
+                    constructedStates_.erase(it++);
+                else
+                    ++it;
+            }
+
+            core_->unloadGraphics(loadGraphicsManagerWithoutRenderer);
+        }
+    }
+
+    bool Game::checkState(const std::string& name) const
+    {
+        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(name);
+        if (it == gameStateDeclarations_s.end())
+            return false;
+        else
+            return true;
+    }
+
+    void Game::loadState(const std::string& name)
+    {
+        orxout(internal_status) << "loading state '" << name << "'" << endl;
+
+        this->bChangingState_ = true;
+        LOKI_ON_BLOCK_EXIT_OBJ(*this, &Game::resetChangingState); (void)LOKI_ANONYMOUS_VARIABLE(scopeGuard);
+
+        // If state requires graphics, load it
+        Loki::ScopeGuard graphicsUnloader = Loki::MakeObjGuard(*this, &Game::unloadGraphics, true);
+        if (gameStateDeclarations_s[name].bGraphicsMode && !GameMode::showsGraphics())
+            this->loadGraphics();
+        else
+            graphicsUnloader.Dismiss();
+
+        std::shared_ptr<GameState> state = this->getState(name);
+        state->activateInternal();
+        if (!this->loadedStates_.empty())
+            this->loadedStates_.back()->activity_.topState = false;
+        this->loadedStates_.push_back(state);
+        state->activity_.topState = true;
+
+        graphicsUnloader.Dismiss();
+    }
+
+    void Game::unloadState(const std::string& name)
+    {
+        orxout(internal_status) << "unloading state '" << name << "'" << endl;
+
+        this->bChangingState_ = true;
+        try
+        {
+            std::shared_ptr<GameState> state = this->getState(name);
+            state->activity_.topState = false;
+            this->loadedStates_.pop_back();
+            if (!this->loadedStates_.empty())
+                this->loadedStates_.back()->activity_.topState = true;
+            state->deactivateInternal();
+        }
+        catch (...)
+        {
+            orxout(internal_warning) << "Unloading GameState '" << name << "' threw an exception: " << Exception::handleMessage() << endl;
+            orxout(internal_warning) << "There might be potential resource leaks involved! To avoid this, improve exception-safety." << endl;
+        }
+        // Check if graphics is still required
+        bool graphicsRequired = false;
+        for (const std::shared_ptr<GameState>& state : loadedStates_)
+            graphicsRequired |= state->getInfo().bGraphicsMode;
+        if (!graphicsRequired)
+            this->unloadGraphics(!this->bAbort_); // if abort is false, that means the game is still running while unloading graphics. in this case we load a graphics manager without renderer (to keep all necessary ogre instances alive)
+        this->bChangingState_ = false;
+    }
+
+    /*static*/ std::map<std::string, std::shared_ptr<Game::GameStateFactory>>& Game::GameStateFactory::getFactories()
+    {
+        static std::map<std::string, std::shared_ptr<GameStateFactory>> factories;
+        return factories;
+    }
+
+    /*static*/ std::shared_ptr<GameState> Game::GameStateFactory::fabricate(const GameStateInfo& info)
+    {
+        std::map<std::string, std::shared_ptr<Game::GameStateFactory>>::const_iterator it = getFactories().find(info.className);
+        assert(it != getFactories().end());
+        return it->second->fabricateInternal(info);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Game.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Game.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Game.h	(revision 11817)
@@ -0,0 +1,226 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@ingroup Management CoreGame
+@brief
+    Declaration of Game Singleton which is responsible for running the game.
+ */
+
+#ifndef _Game_H__
+#define _Game_H__
+
+#include "CorePrereqs.h"
+
+#include <cassert>
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+#include <memory>
+#include <boost/preprocessor/cat.hpp>
+
+#include "util/Output.h"
+#include "util/DestructionHelper.h"
+#include "util/Singleton.h"
+
+/**
+@brief
+    Adds a new GameState to the Game. The second parameter is the name as string
+    and every following parameter is a constructor argument (which is usually non existent)
+*/
+#define DeclareGameState(className, stateName, bIgnoreTickTime, bGraphicsMode) \
+    static bool BOOST_PP_CAT(bGameStateDummy_##className, __UNIQUE_NUMBER__) = orxonox::Game::declareGameState<className>(#className, stateName, bIgnoreTickTime, bGraphicsMode)
+// tolua_begin
+namespace orxonox
+{
+// tolua_end
+
+    //! Helper object required before GameStates are being constructed
+    struct GameStateInfo
+    {
+        std::string stateName;
+        std::string className;
+        bool bIgnoreTickTime;
+        bool bGraphicsMode;
+    };
+
+    /**
+    @brief
+        Main class responsible for running the game.
+    @remark
+        You should only create this singleton once because it owns the Core class! (see remark there)
+    */
+// tolua_begin
+    class _CoreExport Game
+// tolua_end
+        : public Singleton<Game>
+    { // tolua_export
+        friend class Singleton<Game>;
+        typedef std::vector<std::shared_ptr<GameState>> GameStateVector;
+        typedef std::map<std::string, std::shared_ptr<GameState>> GameStateMap;
+        typedef std::shared_ptr<GameStateTreeNode> GameStateTreeNodePtr;
+
+    public:
+        Game(const std::string& cmdLine);
+
+        //! Leave empty and use cleanup() instead
+        ~Game() = default;
+        /// Destructor that also executes when object fails to construct
+        void destroy();
+
+        void setStateHierarchy(const std::string& str);
+        std::shared_ptr<GameState> getState(const std::string& name);
+
+        void run();
+        void stop();
+
+        static Game& getInstance(){ return Singleton<Game>::getInstance(); } // tolua_export
+
+        void requestState(const std::string& name); //tolua_export
+        void requestStates(const std::string& names); //tolua_export
+        void popState(); //tolua_export
+
+        const Clock& getGameClock() { return *this->gameClock_; }
+
+        float getAvgTickTime() { return this->avgTickTime_; }
+        float getAvgFPS()      { return this->avgFPS_; }
+
+        void subtractTickTime(int32_t length);
+
+        template <class T>
+        static bool declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bConsoleMode);
+
+    private:
+        class _CoreExport GameStateFactory
+        {
+        public:
+            virtual ~GameStateFactory() = default;
+            static std::shared_ptr<GameState> fabricate(const GameStateInfo& info);
+            template <class T>
+            static void createFactory(const std::string& className)
+                { getFactories()[className].reset(new TemplateGameStateFactory<T>()); }
+
+            virtual std::shared_ptr<GameState> fabricateInternal(const GameStateInfo& info) = 0;
+            static std::map<std::string, std::shared_ptr<GameStateFactory>>& getFactories();
+        };
+        template <class T>
+        class TemplateGameStateFactory : public GameStateFactory
+        {
+        public:
+            virtual std::shared_ptr<GameState> fabricateInternal(const GameStateInfo& info) override
+                { return std::shared_ptr<GameState>(std::make_shared<T>(info)); }
+        };
+
+        struct StatisticsTickInfo
+        {
+            uint64_t    tickTime;
+            uint32_t    tickLength;
+        };
+
+        // non-copyable:
+        Game(const Game&) = delete;
+        Game& operator=(const Game&) = delete;
+
+        void loadGraphics();
+        void unloadGraphics(bool loadGraphicsManagerWithoutRenderer = true);
+
+        void parseStates(std::vector<std::pair<std::string, int>>::const_iterator& it, std::shared_ptr<GameStateTreeNode> currentNode);
+        bool checkState(const std::string& name) const;
+        void loadState(const std::string& name);
+        void unloadState(const std::string& name);
+
+        // Main loop structuring
+        void updateGameStateStack();
+        void updateGameStates();
+        void updateStatistics();
+        void updateFPSLimiter();
+
+        // ScopeGuard helper function
+        void resetChangingState() { this->bChangingState_ = false; }
+
+        Clock*                             gameClock_;
+        Core*                              core_;
+
+        GameStateMap                       constructedStates_;
+        GameStateVector                    loadedStates_;
+        GameStateTreeNodePtr               rootStateNode_;
+        GameStateTreeNodePtr               loadedTopStateNode_;
+        std::vector<GameStateTreeNodePtr>  requestedStateNodes_;
+
+        bool                               bChangingState_;
+        bool                               bAbort_;
+
+        // variables for time statistics
+        uint64_t                           statisticsStartTime_;
+        std::list<StatisticsTickInfo>      statisticsTickTimes_;
+        uint32_t                           periodTime_;
+        uint32_t                           periodTickTime_;
+        float                              avgFPS_;
+        float                              avgTickTime_;
+        int                                excessSleepTime_;
+        unsigned int                       minimumSleepTime_;
+
+        /// Helper object that stores the config values
+        GameConfig*                        config_;
+
+        /// Helper object that executes the surrogate destructor destroy()
+        DestructionHelper<Game>            destructionHelper_;
+
+        static std::map<std::string, GameStateInfo> gameStateDeclarations_s;
+        static Game* singletonPtr_s;        //!< Pointer to the Singleton
+    }; //tolua_export
+
+    template <class T>
+    /*static*/ bool Game::declareGameState(const std::string& className, const std::string& stateName, bool bIgnoreTickTime, bool bGraphicsMode)
+    {
+        std::map<std::string, GameStateInfo>::const_iterator it = gameStateDeclarations_s.find(stateName);
+        if (it == gameStateDeclarations_s.end())
+        {
+            GameStateInfo& info = gameStateDeclarations_s[stateName];
+            info.stateName = stateName;
+            info.className = className;
+            info.bIgnoreTickTime = bIgnoreTickTime;
+            info.bGraphicsMode = bGraphicsMode;
+        }
+        else
+        {
+            orxout(internal_warning) << "Cannot declare two GameStates with the same name." << endl;
+            orxout(internal_warning) << "Ignoring second one ('" << stateName << "')." << endl;
+        }
+
+        // Create a factory to delay GameState creation
+        GameStateFactory::createFactory<T>(className);
+
+        // just a required dummy return value
+        return true;
+    }
+} //tolua_export
+
+#endif /* _Game_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/GameConfig.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GameConfig.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GameConfig.cc	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GameConfig.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(GameConfig);
+
+    GameConfig::GameConfig()
+    {
+        RegisterObject(GameConfig);
+        this->setConfigValues();
+    }
+
+    void GameConfig::setConfigValues()
+    {
+        SetConfigValue(statisticsRefreshCycle_, 250000)
+            .description("Sets the time in microseconds interval at which average fps, etc. get updated.");
+        SetConfigValue(statisticsAvgLength_, 1000000)
+            .description("Sets the time in microseconds interval at which average fps, etc. gets calculated.");
+
+        SetConfigValueExternal(fpsLimit_, "GraphicsSettings", "fpsLimit", 50)
+            .description("Sets the desired frame rate (0 for no limit).");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/GameConfig.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GameConfig.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GameConfig.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GameConfig_H__
+#define _GameConfig_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+    class _CoreExport GameConfig : virtual public Configurable
+    {
+        public:
+            GameConfig();
+
+            void setConfigValues();
+
+            inline unsigned int getStatisticsRefreshCycle() const
+                { return this->statisticsRefreshCycle_; }
+            inline unsigned int getStatisticsAvgLength() const
+                { return this->statisticsAvgLength_; }
+            inline unsigned int getFpsLimit() const
+                { return this->fpsLimit_; }
+
+        private:
+            // config values
+            unsigned int statisticsRefreshCycle_;
+            unsigned int statisticsAvgLength_;
+            unsigned int fpsLimit_;
+    };
+}
+
+#endif /* _GameConfig_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/GameMode.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GameMode.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GameMode.cc	(revision 11817)
@@ -0,0 +1,39 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GameMode.h"
+
+namespace orxonox
+{
+    bool GameMode::bShowsGraphics_s = false;
+    bool GameMode::bPlaysSound_s    = false;
+    bool GameMode::bIsServer_s      = false;
+    bool GameMode::bIsClient_s      = false;
+    bool GameMode::bIsStandalone_s  = false;
+    bool GameMode::bIsMaster_s      = false;
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/GameMode.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GameMode.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GameMode.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Management CoreGame
+    @brief Declaration of the GameMode class which stores and returns the current mode of the game.
+*/
+
+#ifndef _GameMode_H__
+#define _GameMode_H__
+
+#include "CorePrereqs.h"
+
+// tolua_begin
+namespace orxonox
+{
+    /// Helper class, stores and returns the current mode of the game.
+    class _CoreExport GameMode
+    {
+// tolua_end
+        friend class Core;
+
+        public:
+// tolua_begin
+            static bool showsGraphics() { return bShowsGraphics_s; }    ///< Returns true if the game shows graphics, false if it is in text-console mode
+            static bool playsSound()    { return bPlaysSound_s; }       ///< Returns true if the game is able to play sounds
+            static bool isServer()      { return bIsServer_s; }         ///< Returns true if we're currently a server (online)
+            static bool isClient()      { return bIsClient_s; }         ///< Returns true if we're currently a client (online)
+            static bool isStandalone()  { return bIsStandalone_s; }     ///< Returns true if we're in standalone mode (offline)
+            static bool isMaster()      { return bIsMaster_s; }         ///< Returns true if we're in control of the game (either standalone or server)
+// tolua_end
+
+            static void setPlaysSound   (bool val) { bPlaysSound_s    = val; }                      ///< Defines if the game can play sounds
+            static void setIsServer     (bool val) { bIsServer_s      = val; updateIsMaster(); }    ///< Defines if the program is in server mode (online)
+            static void setIsClient     (bool val) { bIsClient_s      = val; updateIsMaster(); }    ///< Defines if the program is in client mode (online)
+            static void setIsStandalone (bool val) { bIsStandalone_s  = val; updateIsMaster(); }    ///< Defines if the program is in standalone mode (offline)
+
+        private:
+            // static class, no instances allowed:
+            GameMode() = delete;
+            GameMode(const GameMode&) = delete;
+            GameMode& operator=(const GameMode&) = delete;
+            ~GameMode() = delete;
+
+            /// Checks if we're in control of the game (either standalone or server).
+            static void updateIsMaster()
+            {
+                bIsMaster_s = (bIsServer_s || bIsStandalone_s);
+            }
+
+            static bool bShowsGraphics_s;                   //!< global variable that tells whether to show graphics
+            static bool bPlaysSound_s;                      //!< global variable that tells whether to sound works
+            static bool bIsServer_s;                        //!< global variable that tells whether this is a server (online)
+            static bool bIsClient_s;                        //!< global variable that tells whether this is a client (online)
+            static bool bIsStandalone_s;                    //!< global variable that tells whether the game is running in standalone mode (offline)
+            static bool bIsMaster_s;                        //!< global variable that tells whether we're in control of the game (standalone or server)
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _GameMode_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/GameState.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GameState.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GameState.cc	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of GameState class.
+*/
+
+#include "GameState.h"
+
+#include "util/Exception.h"
+#include "util/OrxAssert.h"
+#include "Game.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Constructor only initialises variables and sets the name permanently.
+    */
+    GameState::GameState(const GameStateInfo& info)
+        : info_(info)
+    {
+        this->activity_.activating   = false;
+        this->activity_.active       = false;
+        this->activity_.deactivating = false;
+        this->activity_.suspended    = false;
+        this->activity_.topState     = false;
+        this->activity_.updating     = false;
+    }
+
+    /**
+    @brief
+        Destructor only checks that we don't delete an active state.
+    */
+    GameState::~GameState()
+    {
+        OrxAssert(this->activity_.active == false, "Deleting an active GameState is a very bad idea..");
+    }
+
+    const std::string& GameState::getName() const
+    {
+        return info_.stateName;
+    }
+
+    void GameState::activateInternal()
+    {
+        this->activity_.activating = true;
+        this->activate();
+        this->activity_.activating = false;
+        this->activity_.active = true;
+    }
+
+    void GameState::deactivateInternal()
+    {
+        this->activity_.active = false;
+        this->activity_.deactivating = true;
+        this->deactivate();
+        this->activity_.deactivating = false;
+        this->activity_.suspended = false;
+        this->activity_.updating = false;
+    }
+
+    void GameState::updateInternal(const Clock& time)
+    {
+        this->activity_.updating = true;
+        this->update(time);
+        this->activity_.updating = false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/GameState.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GameState.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GameState.h	(revision 11817)
@@ -0,0 +1,104 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@ingroup Management CoreGame
+@brief
+    Definition of GameState class.
+*/
+
+#ifndef _GameState_H__
+#define _GameState_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <string>
+#include "util/UtilPrereqs.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        An implementation of a tree to manage game states.
+        This leads to a certain hierarchy that is created at runtime.
+        To actually use the structure, you will have to derive from it and
+        implement 'enter', 'leave' and 'tick'. The latter corresponds to an
+        update function.
+
+        Internally the tree is managed by two maps per node: One stores all its
+        children, grandchildren, etc. by name of the state. The other maps these
+        children states to the actual child of the node.
+        An example: Foo is a grandchildren of Bar and Foofoo is the Foo's parent.
+        Then Bar stores Foo in map by its name. The other one then maps Foo to Foofoo.
+    */
+    class _CoreExport GameState
+    {
+        friend class Game;
+
+    public:
+        /**
+        @brief
+            Gives information about what the GameState is currently doing
+        */
+        struct State
+        {
+            unsigned active       : 1;
+            unsigned activating   : 1;
+            unsigned deactivating : 1;
+            unsigned updating     : 1;
+            unsigned suspended    : 1;
+            unsigned topState     : 1;
+        };
+
+    public:
+        GameState(const GameStateInfo& info);
+        virtual ~GameState();
+
+        const std::string& getName()   const;
+        State getActivity()            const { return activity_; }
+        const GameStateInfo& getInfo() const { return info_; }
+
+    protected:
+        virtual void activate() { }
+        virtual void deactivate() { }
+        virtual void update(const Clock& time) { }
+
+    private:
+        void setActivity(State activity);
+        void activateInternal();
+        void deactivateInternal();
+        void updateInternal(const Clock& time);
+
+        const GameStateInfo& info_;
+        State                activity_;
+    };
+}
+
+#endif /* _GameState_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/GlowMaterialListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GlowMaterialListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GlowMaterialListener.h	(revision 11817)
@@ -0,0 +1,48 @@
+#ifndef _GlowMaterialListener_H__
+#define _GlowMaterialListener_H__
+
+#include <Ogre.h>
+#include <OgreMaterialManager.h>
+
+namespace orxonox
+{
+    class GlowMaterialListener : public Ogre::MaterialManager::Listener
+    {
+        public:
+            GlowMaterialListener()
+            {
+                mBlackMat = Ogre::MaterialManager::getSingleton().create("mGlowBlack", "Internal");
+                mBlackMat->getTechnique(0)->getPass(0)->setDiffuse(0,0,0,0);
+                mBlackMat->getTechnique(0)->getPass(0)->setSpecular(0,0,0,0);
+                mBlackMat->getTechnique(0)->getPass(0)->setAmbient(0,0,0);
+                mBlackMat->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,0);
+
+                mTransparentMat = Ogre::MaterialManager::getSingleton().create("mGlowTransparent", "Internal");
+                mTransparentMat->getTechnique(0)->getPass(0)->setDiffuse(0,0,0,0);
+                mTransparentMat->getTechnique(0)->getPass(0)->setSpecular(0,0,0,0);
+                mTransparentMat->getTechnique(0)->getPass(0)->setAmbient(0,0,0);
+                mTransparentMat->getTechnique(0)->getPass(0)->setSelfIllumination(0,0,0);
+                mTransparentMat->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_ADD);
+                mTransparentMat->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
+            }
+
+            Ogre::Technique* handleSchemeNotFound(unsigned short, const Ogre::String& schemeName, Ogre::Material* mat, unsigned short, const Ogre::Renderable*)
+            {
+                if (schemeName == "glow")
+                {
+                    // try to figure out if the original material is transparent. if yes, use a black transparent material, otherwise a black opaque one.
+                    if (mat->isTransparent())
+                        return mTransparentMat->getTechnique(0);
+                    else
+                        return mBlackMat->getTechnique(0);
+                }
+                return NULL;
+            }
+
+        private:
+            Ogre::MaterialPtr mBlackMat;
+            Ogre::MaterialPtr mTransparentMat;
+    };
+}
+
+#endif /* _GlowMaterialListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/GraphicsManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GraphicsManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GraphicsManager.cc	(revision 11817)
@@ -0,0 +1,575 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
+ *   Co-authors:
+ *      Felix Schulthess
+ *
+ */
+
+#include "GraphicsManager.h"
+
+#include <cstdlib>
+#include <fstream>
+#include <sstream>
+#include <boost/filesystem.hpp>
+
+#include <OgreFrameListener.h>
+#include <OgreRoot.h>
+#include <OgreLogManager.h>
+#include <OgreMaterialManager.h>
+#include <OgreRenderWindow.h>
+#include <OgreRenderSystem.h>
+#include <OgreResourceGroupManager.h>
+#include <OgreTextureManager.h>
+#include <OgreViewport.h>
+#include <OgreWindowEventUtilities.h>
+
+#include "SpecialConfig.h"
+#include "util/Clock.h"
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+#include "config/ConfigValueIncludes.h"
+#include "CoreIncludes.h"
+#include "Core.h"
+#include "Game.h"
+#include "GameMode.h"
+#include "GlowMaterialListener.h"
+#include "GUIManager.h"
+#include "Loader.h"
+#include "ApplicationPaths.h"
+#include "ConfigurablePaths.h"
+#include "ViewportEventListener.h"
+#include "WindowEventListener.h"
+#include "XMLFile.h"
+#include "command/ConsoleCommandIncludes.h"
+#include "input/InputManager.h"
+
+namespace orxonox
+{
+    static const std::string __CC_GraphicsManager_group = "GraphicsManager";
+    static const std::string __CC_setScreenResolution_name = "setScreenResolution";
+    static const std::string __CC_setFSAA_name = "setFSAA";
+    static const std::string __CC_setVSync_name = "setVSync";
+    DeclareConsoleCommand(__CC_GraphicsManager_group, __CC_setScreenResolution_name, &prototype::string__uint_uint_bool);
+    DeclareConsoleCommand(__CC_GraphicsManager_group, __CC_setFSAA_name, &prototype::string__string);
+    DeclareConsoleCommand(__CC_GraphicsManager_group, __CC_setVSync_name, &prototype::string__bool);
+
+    static const std::string __CC_printScreen_name = "printScreen";
+    DeclareConsoleCommand(__CC_printScreen_name, &prototype::void__void);
+
+    class OgreWindowEventListener : public Ogre::WindowEventListener
+    {
+    public:
+        virtual void windowResized     (Ogre::RenderWindow* rw) override
+            { orxonox::WindowEventListener::resizeWindow(rw->getWidth(), rw->getHeight()); }
+        virtual void windowFocusChange (Ogre::RenderWindow* rw) override
+            { orxonox::WindowEventListener::changeWindowFocus(rw->isActive()); }
+        virtual void windowClosed      (Ogre::RenderWindow* rw) override
+            { orxonox::Game::getInstance().stop(); }
+        virtual void windowMoved       (Ogre::RenderWindow* rw) override
+            { orxonox::WindowEventListener::moveWindow(); }
+    };
+
+    GraphicsManager* GraphicsManager::singletonPtr_s = nullptr;
+
+    RegisterAbstractClass(GraphicsManager).inheritsFrom<Configurable>();
+
+    GraphicsManager::GraphicsManager(bool bLoadRenderer)
+        : ogreWindowEventListener_(new OgreWindowEventListener())
+        , renderWindow_(nullptr)
+        , viewport_(nullptr)
+        , glowMaterialListener_(nullptr)
+        , lastFrameStartTime_(0.0f)
+        , lastFrameEndTime_(0.0f)
+        , destructionHelper_(this)
+    {
+        RegisterObject(GraphicsManager);
+
+        orxout(internal_status) << "initializing GraphicsManager..." << endl;
+        this->setConfigValues();
+
+        // Ogre setup procedure (creating Ogre::Root)
+        this->loadOgreRoot();
+
+        // At first, add the root paths of the data directories as resource locations
+        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(ConfigurablePaths::getDataPathString(), "FileSystem");
+        // Load resources
+        resources_.reset(new XMLFile("DefaultResources.oxr"));
+        resources_->setLuaSupport(false);
+        Loader::getInstance().load(resources_.get(), ClassTreeMask(), false);
+
+        // Only for runs in the build directory (not installed)
+        if (ApplicationPaths::buildDirectoryRun())
+            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(ConfigurablePaths::getExternalDataPathString(), "FileSystem");
+
+        extResources_.reset(new XMLFile("resources.oxr"));
+        extResources_->setLuaSupport(false);
+        Loader::getInstance().load(extResources_.get(), ClassTreeMask(), false);
+
+        if (bLoadRenderer)
+        {
+            // Reads the ogre config and creates the render window
+            this->upgradeToGraphics();
+        }
+
+        orxout(internal_status) << "finished initializing GraphicsManager" << endl;
+    }
+
+    void GraphicsManager::destroy()
+    {
+        orxout(internal_status) << "destroying GraphicsManager..." << endl;
+
+        Ogre::MaterialManager::getSingleton().removeListener(this->glowMaterialListener_);
+        Ogre::WindowEventUtilities::removeWindowEventListener(renderWindow_, ogreWindowEventListener_);
+
+        ModifyConsoleCommand(__CC_printScreen_name).resetFunction();
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setScreenResolution_name).resetFunction();
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setFSAA_name).resetFunction();
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setVSync_name).resetFunction();
+
+        // Undeclare the resources
+        Loader::getInstance().unload(resources_.get());
+        Loader::getInstance().unload(extResources_.get());
+
+        safeObjectDelete(&ogreRoot_);
+        safeObjectDelete(&ogreLogger_);
+        safeObjectDelete(&ogreWindowEventListener_);
+        safeObjectDelete(&glowMaterialListener_);
+
+        orxout(internal_status) << "finished destroying GraphicsManager" << endl;
+    }
+
+    void GraphicsManager::setConfigValues()
+    {
+        SetConfigValue(ogreConfigFile_,  "ogre.cfg")
+            .description("Location of the Ogre config file");
+        SetConfigValue(ogrePlugins_, specialConfig::ogrePlugins)
+            .description("Comma separated list of all plugins to load.");
+        SetConfigValue(ogreLogFile_,     "ogre.log")
+            .description("Logfile for messages from Ogre. Use \"\" to suppress log file creation.");
+    }
+
+    /**
+    @brief
+        Loads the renderer and creates the render window if not yet done so.
+    @remarks
+        This operation is irreversible without recreating the GraphicsManager!
+        So if it throws you HAVE to recreate the GraphicsManager!!!
+        It therefore offers almost no exception safety.
+    */
+    void GraphicsManager::upgradeToGraphics()
+    {
+        if (renderWindow_ != nullptr)
+            return;
+
+        orxout(internal_info) << "GraphicsManager upgrade to graphics" << endl;
+
+        // load all the required plugins for Ogre
+        orxout(user_info) << "Loading Ogre plugins..." << endl;
+        this->loadOgrePlugins();
+
+        orxout(user_info) << "Creating render window..." << endl;
+        this->loadRenderer();
+
+        // Initialise all resources (do this AFTER the renderer has been loaded!)
+        // Note: You can only do this once! Ogre will check whether a resource group has
+        // already been initialised. If you need to load resources later, you will have to
+        // choose another resource group.
+        orxout(user_info) << "Initializing all resource groups..." << endl;
+        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+
+        orxout(internal_info) << "GraphicsManager finished upgrade to graphics" << endl;
+    }
+
+    /**
+    @brief
+        Creates the Ogre Root object and sets up the ogre log.
+    */
+    void GraphicsManager::loadOgreRoot()
+    {
+        orxout(internal_info) << "Setting up Ogre..." << endl;
+
+        if (ogreConfigFile_.empty())
+        {
+            orxout(internal_warning) << "Ogre config file set to \"\". Defaulting to config.cfg" << endl;
+            ModifyConfigValue(ogreConfigFile_, tset, "config.cfg");
+        }
+        if (ogreLogFile_.empty())
+        {
+            orxout(internal_warning) << "Ogre log file set to \"\". Defaulting to ogre.log" << endl;
+            ModifyConfigValue(ogreLogFile_, tset, "ogre.log");
+        }
+
+        boost::filesystem::path ogreConfigFilepath(ConfigurablePaths::getConfigPath() / this->ogreConfigFile_);
+        boost::filesystem::path ogreLogFilepath(ConfigurablePaths::getLogPath() / this->ogreLogFile_);
+
+        // create a new logManager
+        // Ogre::Root will detect that we've already created a Log
+        ogreLogger_ = new Ogre::LogManager();
+        orxout(internal_info) << "Ogre LogManager created" << endl;
+
+        // create our own log that we can listen to
+        Ogre::Log *myLog;
+        myLog = ogreLogger_->createLog(ogreLogFilepath.string(), true, false, false);
+        orxout(internal_info) << "Ogre Log created" << endl;
+
+        myLog->setLogDetail(Ogre::LL_BOREME);
+        myLog->addListener(this);
+
+        orxout(internal_info) << "Creating Ogre Root..." << endl;
+
+        // check for config file existence because Ogre displays (caught) exceptions if not
+        if (!boost::filesystem::exists(ogreConfigFilepath))
+        {
+            // create a zero sized file
+            std::ofstream creator;
+            creator.open(ogreConfigFilepath.string().c_str());
+            creator.close();
+        }
+
+        // Leave plugins file empty. We're going to do that part manually later
+        ogreRoot_ = new Ogre::Root("", ogreConfigFilepath.string(), ogreLogFilepath.string());
+
+        orxout(internal_info) << "Ogre set up done." << endl;
+    }
+
+    void GraphicsManager::loadOgrePlugins()
+    {
+        orxout(internal_info) << "loading ogre plugins" << endl;
+
+        // Plugin path can have many different locations...
+        std::string pluginPath = specialConfig::ogrePluginsDirectory;
+#ifdef DEPENDENCY_PACKAGE_ENABLE
+        if (!ApplicationPaths::buildDirectoryRun())
+        {
+#  if defined(ORXONOX_PLATFORM_WINDOWS)
+            pluginPath = ApplicationPaths::getExecutablePathString();
+#  elif defined(ORXONOX_PLATFORM_APPLE)
+            // TODO: Where are the plugins being installed to?
+            pluginPath = ApplicationPaths::getExecutablePathString();
+#  endif
+        }
+#endif
+
+        // Do some SubString magic to get the comma separated list of plugins
+        SubString plugins(ogrePlugins_, ",", " ", false, '\\', false, '"', false, '{', '}', false, '\0');
+        for (unsigned int i = 0; i < plugins.size(); ++i)
+            ogreRoot_->loadPlugin(pluginPath + '/' + plugins[i]);
+    }
+
+    void GraphicsManager::loadRenderer()
+    {
+        orxout(internal_info) << "GraphicsManager: Configuring Renderer" << endl;
+
+        bool updatedConfig = Core::getInstance().getConfig()->getOgreConfigTimestamp() > Core::getInstance().getConfig()->getLastLevelTimestamp();
+        if (updatedConfig)
+            orxout(user_info)<< "Ogre config file has changed, but no level was started since then. Displaying config dialogue again to verify the changes." << endl;
+
+        if (!ogreRoot_->restoreConfig() || updatedConfig)
+        {
+            if (!ogreRoot_->showConfigDialog())
+                ThrowException(InitialisationFailed, "OGRE graphics configuration dialogue canceled.");
+            else
+                Core::getInstance().getConfig()->updateOgreConfigTimestamp();
+        }
+
+        orxout(internal_info) << "Creating render window" << endl;
+
+        this->renderWindow_ = ogreRoot_->initialise(true, "Orxonox");
+        // Propagate the size of the new winodw
+        this->ogreWindowEventListener_->windowResized(renderWindow_);
+
+        Ogre::WindowEventUtilities::addWindowEventListener(this->renderWindow_, ogreWindowEventListener_);
+
+        // create a full screen default viewport
+        // Note: This may throw when adding a viewport with an existing z-order!
+        //       But in our case we only have one viewport for now anyway, therefore
+        //       no ScopeGuards or anything to handle exceptions.
+        this->viewport_ = this->renderWindow_->addViewport(nullptr, 0);
+
+        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(Ogre::MIP_UNLIMITED);
+
+        this->glowMaterialListener_ = new GlowMaterialListener();
+        Ogre::MaterialManager::getSingleton().addListener(this->glowMaterialListener_);
+
+        //Add program icon
+#if defined(ORXONOX_PLATFORM_WINDOWS)
+        HWND hwnd;
+        this->renderWindow_->getCustomAttribute("WINDOW", (void*)&hwnd);
+        LONG_PTR iconID = (LONG_PTR)LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(101));
+        SetClassLongPtr(hwnd, GCLP_HICON, iconID);
+#endif
+
+
+        // add console commands
+        ModifyConsoleCommand(__CC_printScreen_name).setFunction(&GraphicsManager::printScreen, this);
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setScreenResolution_name).setFunction(&GraphicsManager::setScreenResolution, this);
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setFSAA_name).setFunction(&GraphicsManager::setFSAA, this);
+        ModifyConsoleCommand(__CC_GraphicsManager_group, __CC_setVSync_name).setFunction(&GraphicsManager::setVSync, this);
+    }
+
+    void GraphicsManager::loadDebugOverlay()
+    {
+        // Load debug overlay to show info about fps and tick time
+        orxout(internal_info) << "Loading Debug Overlay..." << endl;
+        debugOverlay_.reset(new XMLFile("debug.oxo"));
+        Loader::getInstance().load(debugOverlay_.get(), ClassTreeMask(), false);
+    }
+
+    void GraphicsManager::unloadDebugOverlay()
+    {
+        Loader::getInstance().unload(debugOverlay_.get());
+    }
+
+    /**
+    @note
+        A note about the Ogre::FrameListener: Even though we don't use them,
+        they still get called.
+    */
+    void GraphicsManager::postUpdate(const Clock& time)
+    {
+        // Time before rendering
+        uint64_t timeBeforeTick = time.getRealMicroseconds();
+
+        // Ogre's time keeping object
+        Ogre::FrameEvent evt;
+
+        // Translate to Ogre float times before the update
+        float temp = lastFrameStartTime_;
+        lastFrameStartTime_ = (float)timeBeforeTick * 0.000001f;
+        evt.timeSinceLastFrame = lastFrameStartTime_ - temp;
+        evt.timeSinceLastEvent = lastFrameStartTime_ - lastFrameEndTime_;
+
+        // Ogre requires the time too
+        ogreRoot_->_fireFrameStarted(evt);
+
+        // Pump messages in all registered RenderWindows
+        // This calls the WindowEventListener objects.
+        Ogre::WindowEventUtilities::messagePump();
+        // Make sure the window stays active even when not focused
+        // (probably only necessary on windows)
+        this->renderWindow_->setActive(true);
+
+        // Render frame
+        ogreRoot_->_updateAllRenderTargets();
+
+        uint64_t timeAfterTick = time.getRealMicroseconds();
+        // Subtract the time used for rendering from the tick time counter
+        Game::getInstance().subtractTickTime((int32_t)(timeAfterTick - timeBeforeTick));
+
+        // Translate to Ogre float times after the update
+        temp = lastFrameEndTime_;
+        lastFrameEndTime_ = (float)timeBeforeTick * 0.000001f;
+        evt.timeSinceLastFrame = lastFrameEndTime_ - temp;
+        evt.timeSinceLastEvent = lastFrameEndTime_ - lastFrameStartTime_;
+
+        // Ogre also needs the time after the frame finished
+        ogreRoot_->_fireFrameEnded(evt);
+    }
+
+    void GraphicsManager::setCamera(Ogre::Camera* camera)
+    {
+        Ogre::Camera* oldCamera = this->viewport_->getCamera();
+
+        this->viewport_->setCamera(camera);
+        GUIManager::getInstance().setCamera(camera);
+
+        for (ViewportEventListener* listener : ObjectList<ViewportEventListener>())
+            listener->cameraChanged(this->viewport_, oldCamera);
+    }
+
+    /**
+    @brief
+        Method called by the LogListener interface from Ogre.
+        We use it to capture Ogre log messages and handle it ourselves.
+    @param message
+        The message to be logged
+    @param lml
+        The message level the log is using
+    @param maskDebug
+        If we are printing to the console or not
+    @param logName
+        The name of this log (so you can have several listeners
+        for different logs, and identify them)
+    @param skipThisMessage
+        If set to true by the messageLogged() implementation message will not be logged
+    */
+#if OGRE_VERSION >= 0x010800
+    void GraphicsManager::messageLogged(const std::string& message,
+        Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName, bool& skipThisMessage)
+        // TODO: do we have to ignore the message if skipThisMessage is set?
+#else
+    void GraphicsManager::messageLogged(const std::string& message,
+        Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName)
+#endif
+    {
+        OutputLevel orxonoxLevel;
+        std::string introduction;
+        // Do not show caught OGRE exceptions in front
+        if (message.find("EXCEPTION") != std::string::npos)
+        {
+            orxonoxLevel = level::internal_error;
+            introduction = "Ogre, caught exception: ";
+        }
+        else
+        {
+            switch (lml)
+            {
+            case Ogre::LML_TRIVIAL:
+                orxonoxLevel = level::verbose_more;
+                break;
+            case Ogre::LML_NORMAL:
+                orxonoxLevel = level::verbose;
+                break;
+            case Ogre::LML_CRITICAL:
+                orxonoxLevel = level::internal_warning;
+                break;
+            default:
+                orxonoxLevel = level::debug_output;
+            }
+            introduction = "Ogre: ";
+        }
+
+        orxout(orxonoxLevel, context::ogre) << introduction << message << endl;
+    }
+
+    size_t GraphicsManager::getRenderWindowHandle()
+    {
+        size_t windowHnd = 0;
+        renderWindow_->getCustomAttribute("WINDOW", &windowHnd);
+        return windowHnd;
+    }
+
+    bool GraphicsManager::isFullScreen() const
+    {
+        return this->renderWindow_->isFullScreen();
+    }
+
+    unsigned int GraphicsManager::getWindowWidth() const
+    {
+        return this->renderWindow_->getWidth();
+    }
+
+    unsigned int GraphicsManager::getWindowHeight() const
+    {
+        return this->renderWindow_->getHeight();
+    }
+
+    bool GraphicsManager::hasVSyncEnabled() const
+    {
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("VSync");
+        if (it != options.end())
+            return (it->second.currentValue == "Yes");
+        else
+            return false;
+    }
+
+    std::string GraphicsManager::getFSAAMode() const
+    {
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("FSAA");
+        if (it != options.end())
+            return it->second.currentValue;
+        else
+            return "";
+    }
+
+    std::string GraphicsManager::setScreenResolution(unsigned int width, unsigned int height, bool fullscreen)
+    {
+        // workaround to detect if the colour depth should be written to the config file
+        bool bWriteColourDepth = false;
+        Ogre::ConfigOptionMap& options = ogreRoot_->getRenderSystem()->getConfigOptions();
+        Ogre::ConfigOptionMap::iterator it = options.find("Video Mode");
+        if (it != options.end())
+            bWriteColourDepth = (it->second.currentValue.find('@') != std::string::npos);
+
+        if (bWriteColourDepth)
+        {
+            this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width)
+                                                                    + " x " + multi_cast<std::string>(height)
+                                                                    + " @ " + multi_cast<std::string>(this->getRenderWindow()->getColourDepth()) + "-bit colour");
+        }
+        else
+        {
+            this->ogreRoot_->getRenderSystem()->setConfigOption("Video Mode", multi_cast<std::string>(width)
+                                                                    + " x " + multi_cast<std::string>(height));
+        }
+
+        this->ogreRoot_->getRenderSystem()->setConfigOption("Full Screen", fullscreen ? "Yes" : "No");
+
+        std::string validate = this->ogreRoot_->getRenderSystem()->validateConfigOptions();
+
+        if (validate == "")
+        {
+            GraphicsManager::getInstance().getRenderWindow()->setFullscreen(fullscreen, width, height);
+            this->ogreRoot_->saveConfig();
+            Core::getInstance().getConfig()->updateOgreConfigTimestamp();
+            // Also reload the input devices
+            InputManager::getInstance().reload();
+        }
+
+        return validate;
+    }
+
+    std::string GraphicsManager::setFSAA(const std::string& mode)
+    {
+        this->ogreRoot_->getRenderSystem()->setConfigOption("FSAA", mode);
+
+        std::string validate = this->ogreRoot_->getRenderSystem()->validateConfigOptions();
+
+        if (validate == "")
+        {
+            //this->ogreRoot_->getRenderSystem()->reinitialise(); // can't use this that easily, because it recreates the render window, invalidating renderWindow_
+            this->ogreRoot_->saveConfig();
+            Core::getInstance().getConfig()->updateOgreConfigTimestamp();
+        }
+
+        return validate;
+    }
+
+    std::string GraphicsManager::setVSync(bool vsync)
+    {
+        this->ogreRoot_->getRenderSystem()->setConfigOption("VSync", vsync ? "Yes" : "No");
+
+        std::string validate = this->ogreRoot_->getRenderSystem()->validateConfigOptions();
+
+        if (validate == "")
+        {
+            //this->ogreRoot_->getRenderSystem()->reinitialise(); // can't use this that easily, because it recreates the render window, invalidating renderWindow_
+            this->ogreRoot_->saveConfig();
+            Core::getInstance().getConfig()->updateOgreConfigTimestamp();
+        }
+
+        return validate;
+    }
+
+    void GraphicsManager::printScreen()
+    {
+        assert(this->renderWindow_);
+        this->renderWindow_->writeContentsToTimestampedFile(ConfigurablePaths::getLogPathString() + "screenShot_", ".png");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/GraphicsManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/GraphicsManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/GraphicsManager.h	(revision 11817)
@@ -0,0 +1,154 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
+ *   Co-authors:
+ *      Felix Schulthess
+ *
+ */
+
+/**
+    @defgroup Graphics Graphics and GUI
+    @ingroup Core
+*/
+
+/**
+@file
+@ingroup Graphics
+@brief
+    Declaration of GraphicsManager Singleton.
+ */
+
+#ifndef _GraphicsManager_H__
+#define _GraphicsManager_H__
+
+#include "CorePrereqs.h"
+
+#include <cassert>
+#include <string>
+#include <memory>
+
+#include <OgreLog.h>
+
+#include "util/DestructionHelper.h"
+#include "util/Singleton.h"
+#include "config/Configurable.h"
+
+// tolua_begin
+namespace orxonox
+{
+    /**
+    @brief
+        Graphics engine manager class
+    */
+    class _CoreExport GraphicsManager
+// tolua_end
+        : public Singleton<GraphicsManager>, public Configurable, public Ogre::LogListener
+    { // tolua_export
+        friend class Singleton<GraphicsManager>;
+    public:
+        GraphicsManager(bool bLoadRenderer = true);
+
+        //! Leave empty and use cleanup() instead
+        ~GraphicsManager() = default;
+        /// Destructor that also executes when object fails to construct
+        void destroy();
+
+        void setConfigValues();
+
+        void postUpdate(const Clock& time);
+
+        Ogre::Viewport* getViewport()         { return this->viewport_; }
+        Ogre::RenderWindow* getRenderWindow() { return this->renderWindow_; }
+        size_t getRenderWindowHandle();
+
+// tolua_begin
+        static GraphicsManager& getInstance() { return Singleton<GraphicsManager>::getInstance(); } // tolua_export
+
+        bool isFullScreen() const;
+        unsigned int getWindowWidth() const;
+        unsigned int getWindowHeight() const;
+
+        bool hasVSyncEnabled() const;
+        std::string getFSAAMode() const;
+// tolua_end
+
+        void upgradeToGraphics();
+        void loadDebugOverlay();
+        void unloadDebugOverlay();
+        bool rendererLoaded() const { return renderWindow_ != nullptr; }
+
+        void setCamera(Ogre::Camera* camera);
+
+    private:
+        // non-copyable:
+        GraphicsManager(const GraphicsManager&) = delete;
+        GraphicsManager& operator=(const GraphicsManager&) = delete;
+
+        // OGRE initialisation
+        void loadOgreRoot();
+        void loadOgrePlugins();
+        void loadRenderer();
+
+        // event from Ogre::LogListener
+#if OGRE_VERSION >= 0x010800
+        virtual void messageLogged(const std::string& message, Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName, bool& skipThisMessage) override;
+#else
+        virtual void messageLogged(const std::string& message, Ogre::LogMessageLevel lml, bool maskDebug, const std::string& logName) override;
+#endif
+
+        // console commands
+        void printScreen();
+        std::string setScreenResolution(unsigned int width, unsigned int height, bool fullscreen);
+        std::string setFSAA(const std::string& mode);
+        std::string setVSync(bool vsync);
+
+        OgreWindowEventListener* ogreWindowEventListener_; //!< Pimpl to hide OgreWindowUtilities.h
+        Ogre::LogManager*        ogreLogger_;
+        Ogre::Root*              ogreRoot_;                //!< Ogre's root
+        Ogre::RenderWindow*      renderWindow_;            //!< the one and only render window
+        Ogre::Viewport*          viewport_;                //!< default full size viewport
+        GlowMaterialListener*    glowMaterialListener_;    //!< Material Listener for the 'Glow' compositor
+        float                    lastFrameStartTime_;      //!< Time stamp of the beginning of the last frame
+        float                    lastFrameEndTime_;        //!< Time stamp of the end of the last frame
+
+        // XML files for the resources and the debug overlay
+        std::shared_ptr<XMLFile> resources_;           //!< XML with resource locations
+        std::shared_ptr<XMLFile> extResources_;        //!< XML with resource locations in the external path (only for dev runs)
+        std::shared_ptr<XMLFile> debugOverlay_;        //!< XML with various debug overlays
+
+        // config values
+        std::string         ogreConfigFile_;           //!< ogre config filename
+        std::string         ogrePlugins_;              //!< Comma separated list of all plugins to load
+        std::string         ogreLogFile_;              //!< log filename for Ogre log messages
+
+        /// Helper object that executes the surrogate destructor destroy()
+        DestructionHelper<GraphicsManager> destructionHelper_;
+
+        static GraphicsManager* singletonPtr_s;        //!< Pointer to the Singleton
+// tolua_begin
+    };
+}
+// tolua_end
+
+#endif /* _GraphicsManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Language.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Language.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Language.cc	(revision 11817)
@@ -0,0 +1,328 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the Language and the LanguageEntry classes.
+*/
+
+#include "Language.h"
+
+#include <fstream>
+#include "util/Output.h"
+#include "util/StringUtils.h"
+#include "ConfigurablePaths.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###      LanguageEntry      ###
+    // ###############################
+    /**
+        @brief Constructor: Sets the default entry.
+        @param fallbackEntry The default entry
+    */
+    LanguageEntry::LanguageEntry(const std::string& fallbackEntry)
+    {
+        this->fallbackEntry_ = fallbackEntry;
+        this->localisedEntry_ = fallbackEntry; // Set the localisation to the fallback entry, for the case that no translation gets assigned
+        this->bLocalisationSet_ = false;
+    }
+
+    /**
+        @brief Sets the localisation of the entry.
+        @param localisation The localisation
+    */
+    void LanguageEntry::setLocalisation(const std::string& localisation)
+    {
+        // Check if the translation is more than just an empty string
+        if (!localisation.empty())
+        {
+            this->localisedEntry_ = localisation;
+            this->bLocalisationSet_ = true;
+        }
+        else
+            this->localisedEntry_ = this->fallbackEntry_;
+    }
+
+    /**
+        @brief Sets the default entry.
+        @param fallbackEntry The default entry
+    */
+    void LanguageEntry::setDefault(const std::string& fallbackEntry)
+    {
+        // If the default entry changes and the translation wasn't set yet, use the new default entry as translation
+        if (!this->bLocalisationSet_)
+            this->localisedEntry_ = fallbackEntry;
+
+        this->fallbackEntry_ = fallbackEntry;
+    }
+
+    // ###############################
+    // ###        Language         ###
+    // ###############################
+
+    Language* Language::singletonPtr_s = nullptr;
+
+    /**
+        @brief Constructor: Reads the default language file and sets some values.
+    */
+    Language::Language()
+    {
+        this->defaultLanguage_ = "default";
+        this->defaultLocalisation_ = "ERROR: LANGUAGE ENTRY DOESN'T EXIST!";
+
+        // Read the default language file to create all known LanguageEntry objects
+        this->readDefaultLanguageFile();
+    }
+
+    /**
+        @brief Destructor: Deletes all language entries.
+    */
+    Language::~Language()
+    {
+        for (const auto& mapEntry : this->languageEntries_)
+            delete (mapEntry.second);
+    }
+
+    /**
+        @brief Creates a new LanguageEntry with a given label and a given default entry.
+        @param label The label of the entry
+        @param entry The default entry
+        @return The created LanguageEntry object
+    */
+    LanguageEntry* Language::createEntry(const LanguageEntryLabel& label, const std::string& entry)
+    {
+        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
+
+        // Make sure we don't create a duplicate entry
+        if (it == this->languageEntries_.end())
+        {
+            LanguageEntry* newEntry = new LanguageEntry(entry);
+            newEntry->setLabel(label);
+            this->languageEntries_[label] = newEntry;
+            return newEntry;
+        }
+
+        orxout(internal_warning, context::language) << "Language entry " << label << " is duplicate in " << getFilename(this->defaultLanguage_) << '!' << endl;
+        return it->second;
+    }
+
+    /**
+        @brief Adds a new LanguageEntry, if it's not already existing.
+        @param label The label of the entry
+        @param entry The default entry
+    */
+    void Language::addEntry(const LanguageEntryLabel& label, const std::string& entry)
+    {
+        orxout(verbose, context::language) << "Called addEntry with" << '\n' << "label: " << label << '\n' << "entry: " <<  entry << endl;
+        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
+        if (it == this->languageEntries_.end())
+        {
+            // The entry isn't available yet, meaning it's new, so create it
+            this->createEntry(label, entry);
+        }
+        else if (it->second->getDefault().compare(entry) == 0)
+        {
+            // The entry is available and the default string is the same, so return because everything is fine
+            return;
+        }
+        else
+        {
+            // The defined default entry is not the same as in the default language file - change it to the new entry
+            it->second->setDefault(entry);
+        }
+
+        // Write the default language file because either a new entry was created or an existing entry has changed
+        this->writeDefaultLanguageFile();
+
+    }
+
+    /**
+        @brief Returns the localisation of a given entry.
+        @param label The label of the entry
+        @param bError If true, an error is printed if the label doesn't exist and the default localisation is returned. If false, no error is printed and an empty string is returned.
+        @return The localisation
+    */
+    const std::string& Language::getLocalisation(const LanguageEntryLabel& label, bool bError) const
+    {
+        std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(label);
+        if (it != this->languageEntries_.end())
+            return it->second->getLocalisation();
+        else if (bError)
+        {
+            // Uh, oh, an undefined entry was requested: return the default string
+            orxout(internal_warning, context::language) << "Language entry \"" << label << "\" not found!" << endl;
+            return this->defaultLocalisation_;
+        }
+        else
+            return BLANKSTRING;
+    }
+
+    /**
+        @brief Creates the name of the language file out of the languages name.
+        @param language The name of the language
+        @return The filename
+    */
+    std::string Language::getFilename(const std::string& language)
+    {
+        return std::string("translation_" + language + ".lang");
+    }
+
+    /**
+        @brief Reads the default language file and creates a LanguageEntry objects for every entry.
+    */
+    void Language::readDefaultLanguageFile()
+    {
+        orxout(internal_info, context::language) << "Read default language file." << endl;
+
+        const std::string& filepath = ConfigurablePaths::getConfigPathString() + getFilename(this->defaultLanguage_);
+
+        // This creates the file if it's not existing
+        std::ofstream createFile;
+        createFile.open(filepath.c_str(), std::fstream::app);
+        createFile.close();
+
+        // Open the file
+        std::ifstream file;
+        file.open(filepath.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            orxout(internal_error, context::language) << "An error occurred in Language.cc:" << endl;
+            orxout(internal_error, context::language) << "Couldn't open file " << getFilename(this->defaultLanguage_) << " to read the default language entries!" << endl;
+            return;
+        }
+
+        // Iterate through the file and create the LanguageEntries
+        while (file.good() && !file.eof())
+        {
+            std::string lineString;
+            std::getline(file, lineString);
+
+            // Check if the line is empty
+            if (!lineString.empty())
+            {
+                size_t pos = lineString.find('=');
+
+                // Check if the length is at least 3 and if there's an entry before and behind the =
+                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
+                    this->createEntry(lineString.substr(0, pos), lineString.substr(pos + 1));
+                else
+                {
+                    orxout(internal_warning, context::language) << "Invalid language entry \"" << lineString << "\" in " << getFilename(this->defaultLanguage_) << endl;
+                }
+            }
+        }
+
+        file.close();
+    }
+
+    /**
+        @brief Reads the language file of the configured language and assigns the localisation to the corresponding LanguageEntry object.
+        @return Returns false if the language file couldn't be found.
+    */
+    bool Language::readTranslatedLanguageFile(const std::string& language)
+    {
+        orxout(internal_info, context::language) << "Read translated language file (" << language << ")." << endl;
+
+        const std::string& filepath = ConfigurablePaths::getConfigPathString() + getFilename(language);
+
+        // Open the file
+        std::ifstream file;
+        file.open(filepath.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            orxout(internal_error, context::language) << "An error occurred in Language.cc:" << endl;
+            orxout(internal_error, context::language) << "Couldn't open file " << getFilename(language) << " to read the translated language entries!" << endl;
+            return false;
+        }
+
+        // Iterate through the file and create the LanguageEntries
+        while (file.good() && !file.eof())
+        {
+            std::string lineString;
+            std::getline(file, lineString);
+
+            // Check if the line is empty
+            if (!lineString.empty())
+            {
+                size_t pos = lineString.find('=');
+
+                // Check if the length is at least 3 and if there's an entry before and behind the =
+                if (pos > 0 && pos < (lineString.size() - 1) && lineString.size() >= 3)
+                {
+                    std::map<std::string, LanguageEntry*>::const_iterator it = this->languageEntries_.find(lineString.substr(0, pos));
+
+                    // Check if the entry exists
+                    if (it != this->languageEntries_.end())
+                        it->second->setLocalisation(lineString.substr(pos + 1));
+                    else
+                        this->createEntry(lineString.substr(0, pos), this->defaultLocalisation_)->setLocalisation(lineString.substr(pos + 1));
+                }
+                else
+                {
+                    orxout(internal_warning, context::language) << "Invalid language entry \"" << lineString << "\" in " << getFilename(language) << endl;
+                }
+            }
+        }
+
+        file.close();
+        return true;
+    }
+
+    /**
+        @brief Writes all default entries to the default language file.
+    */
+    void Language::writeDefaultLanguageFile() const
+    {
+        orxout(verbose, context::language) << "Write default language file." << endl;
+
+        const std::string& filepath = ConfigurablePaths::getConfigPathString() + getFilename(this->defaultLanguage_);
+
+        // Open the file
+        std::ofstream file;
+        file.open(filepath.c_str(), std::fstream::out);
+
+        if (!file.is_open())
+        {
+            orxout(internal_error, context::language) << "An error occurred in Language.cc:" << endl;
+            orxout(internal_error, context::language) << "Couldn't open file " << getFilename(this->defaultLanguage_) << " to write the default language entries!" << endl;
+            return;
+        }
+
+        // Iterate through the list an write the lines into the file
+        for (const auto& mapEntry : this->languageEntries_)
+        {
+            file << mapEntry.second->getLabel() << '=' << mapEntry.second->getDefault() << endl;
+        }
+
+        file.close();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Language.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Language.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Language.h	(revision 11817)
@@ -0,0 +1,209 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Language Language
+    @ingroup Core
+*/
+
+/**
+    @file
+    @ingroup Language
+    @brief Declaration of the Language and the LanguageEntry class, as well as some helper functions.
+
+    @anchor LanguageExample
+
+    The Language class is used, to get a localisation of a string in the configured language.
+    The string is identified by another string, the label of the entry.
+    If the translation in the configured language isn't available, the default entry, defined in the code, is used.
+
+    Usage:
+     - Set the entry with the default string:
+       @code
+       Language::getInstance()->addEntry("label of the entry", "the string to translate");
+       @endcode
+
+     - Get the localisation of the entry in the configured language:
+       @code
+       orxout() << Language::getInstance()->getLocalisation("name of the entry") << endl;
+       @endcode
+
+    Example:
+    @code
+    int age = 20;
+    AddLanguageEntry("user_age", "Age");
+    orxout() << GetLocalisation("user_age") << ": " << age << endl;
+    @endcode
+
+    Resulting output:
+    @code
+    Age: 20
+    @endcode
+
+    The language entry is now defined in @a translation_default.lang:
+    @code
+    user_age=Age
+    @endcode
+
+    We can add a translation for another language, for example @a translation_german.lang:
+    @code
+    user_age=Alter
+    @endcode
+
+    Now change the language in @a orxonox.ini to "german":
+    @code
+    language_ = "german"
+    @endcode
+
+    Now you will see the translated language entry in the resulting output of the above code:
+    @code
+    Alter: 20
+    @endcode
+*/
+
+#ifndef _Language_H__
+#define _Language_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <string>
+#include <cassert>
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###      LanguageEntry      ###
+    // ###############################
+    /**
+        @brief The LanguageEntry class stores the default- and the translated string of a given entry in the language file.
+
+        This class belongs to the Language class.
+    */
+    class _CoreExport LanguageEntry
+    {
+        public:
+            explicit LanguageEntry(const std::string& fallbackEntry);
+            void setLocalisation(const std::string& localisation);
+            void setDefault(const std::string& fallbackEntry);
+
+            /**
+              @brief Returns the localised entry in the configured language.
+              @return The translated entry
+            */
+            inline const std::string& getLocalisation()
+                { return this->localisedEntry_; }
+
+            /**
+              @brief Returns the default entry.
+              @return The default entry
+            */
+            inline const std::string& getDefault()
+                { return this->fallbackEntry_; }
+
+            /**
+                @brief Sets the label of this entry.
+                @param label The label
+            */
+            inline void setLabel(const LanguageEntryLabel& label)
+                { this->label_ = label; }
+
+            /**
+                @brief Returns the label of this entry.
+                @return The label
+            */
+            inline const LanguageEntryLabel& getLabel() const
+                { return this->label_; }
+
+        private:
+            LanguageEntryLabel label_;              //!< The label of the entry
+            std::string fallbackEntry_;             //!< The default entry: Used, if no translation is available or no language configured
+            std::string localisedEntry_;            //!< The localised entry in the configured language
+            bool bLocalisationSet_;                 //!< True if the translation was set
+    };
+
+
+    // ###############################
+    // ###         Language        ###
+    // ###############################
+    /**
+        @brief The Language class manges the language files and entries and stores the LanguageEntry objects in a map.
+
+        @see See @ref LanguageExample "Language.h" for some examples.
+    */
+    class _CoreExport Language : public Singleton<Language>
+    {
+        friend class Singleton<Language>;
+        friend class CoreConfig;
+
+        public:
+            Language();
+            ~Language();
+
+            void addEntry(const LanguageEntryLabel& label, const std::string& entry);
+            const std::string& getLocalisation(const LanguageEntryLabel& label, bool bError = true) const;
+
+        private:
+            // non-copyable:
+            Language(const Language&) = delete;
+            Language& operator=(const Language&) = delete;
+
+            void readDefaultLanguageFile();
+            bool readTranslatedLanguageFile(const std::string& language);
+            void writeDefaultLanguageFile() const;
+            static std::string getFilename(const std::string& language);
+            LanguageEntry* createEntry(const LanguageEntryLabel& label, const std::string& entry);
+
+            std::string defaultLanguage_;                           //!< The default language
+            std::string defaultLocalisation_;                       //!< The returned string, if an entry unavailable entry is requested
+            std::map<std::string, LanguageEntry*> languageEntries_; //!< A map to store all LanguageEntry objects and their labels
+
+            static Language* singletonPtr_s;
+    };
+
+    /// Shortcut function for Language::addEntry
+    inline void AddLanguageEntry(const LanguageEntryLabel& label, const std::string& fallbackString)
+    {
+        Language::getInstance().addEntry(label, fallbackString);
+    }
+
+    /// Shortcut function for Language::getLocalisation
+    inline const std::string& GetLocalisation(const LanguageEntryLabel& label)
+    {
+        return Language::getInstance().getLocalisation(label);
+    }
+
+    /// Shortcut function for Language::getLocalisation without printing an error in case the label doesn't exist
+    inline const std::string& GetLocalisation_noerror(const LanguageEntryLabel& label)
+    {
+        return Language::getInstance().getLocalisation(label, false);
+    }
+}
+
+#endif /* _Language_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Loader.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Loader.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Loader.cc	(revision 11817)
@@ -0,0 +1,427 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Loader.h"
+
+#include <sstream>
+#include <tinyxml/ticpp.h>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "BaseObject.h"
+#include "LuaState.h"
+#include "Namespace.h"
+#include "Resource.h"
+#include "XMLFile.h"
+#include "object/Iterator.h"
+#include "object/ObjectList.h"
+
+namespace orxonox
+{
+    Loader* Loader::singletonPtr_s = nullptr;
+
+    /**
+    @brief
+        Loads the input file, while conforming to the restrictions given by the input ClassTreeMask.
+    @param file
+        The file to be loaded.
+    @param mask
+        A ClassTreeMask, which defines which types of classes are loaded and which aren't.
+    @param bVerbose
+        Whether the loader is verbose (prints its progress in a low output level) or not.
+    @param bRemoveLuaTags
+        If true lua tags are just ignored and removed. The default is false.
+    @return
+        Returns true if successful.
+    */
+    bool Loader::load(const XMLFile* file, const ClassTreeMask& mask, bool bVerbose, bool bRemoveLuaTags)
+    {
+        if (!file)
+            return false;
+
+        this->currentMask_ = file->getMask() * mask;
+
+        std::string xmlInput;
+
+        std::shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> lineTrace(std::make_shared<std::vector<std::vector<std::pair<std::string, size_t>>>>());
+        lineTrace->reserve(1000); //arbitrary number
+
+
+        if (file->getLuaSupport() && !bRemoveLuaTags)
+        {
+            // Use the LuaState to replace the XML tags (calls our function)
+            const std::unique_ptr<LuaState> luaState(new LuaState());
+            luaState->setTraceMap(lineTrace);
+            luaState->setIncludeParser(&Loader::replaceLuaTags);
+            luaState->includeFile(file->getFilename());
+            xmlInput = luaState->getOutput().str();
+        }
+        else
+        {
+            std::shared_ptr<ResourceInfo> info = Resource::getInfo(file->getFilename());
+            if (info == nullptr)
+            {
+                orxout(user_error, context::loader) << "Could not find XML file '" << file->getFilename() << "'." << endl;
+                return false;
+            }
+            xmlInput = Resource::open(file->getFilename())->getAsString();
+
+            if (bRemoveLuaTags)
+            {
+                // Remove all Lua code.
+                // Note: we only need this to speed up parsing of level files at the
+                // start of the program.
+                // Assumption: the LevelInfo tag does not use Lua scripting
+                xmlInput = Loader::removeLuaTags(xmlInput);
+            }
+        }
+
+        try
+        {
+            if(bVerbose)
+            {
+                orxout(user_info) << "Start loading " << file->getFilename() << "..." << endl;
+                orxout(internal_info, context::loader) << "Mask: " << this->currentMask_ << endl;
+            }
+            else
+            {
+                orxout(verbose, context::loader) << "Start loading " << file->getFilename() << "..." << endl;
+                orxout(verbose_more, context::loader) << "Mask: " << this->currentMask_ << endl;
+            }
+
+            ticpp::Document xmlfile(file->getFilename());
+            xmlfile.Parse(xmlInput, true);
+
+            ticpp::Element rootElement;
+            rootElement.SetAttribute("name", "root");
+            rootElement.SetAttribute("bAutogenerated", true);
+
+            for (ticpp::Iterator<ticpp::Element> child = xmlfile.FirstChildElement(false); child != child.end(); child++)
+                rootElement.InsertEndChild(*child);
+
+            orxout(verbose, context::loader) << "  creating root-namespace..." << endl;
+            Namespace* rootNamespace = new Namespace(Context::getRootContext());
+            rootNamespace->setLoaderIndentation("    ");
+            rootNamespace->setFile(file);
+            rootNamespace->setRoot(true);
+            rootNamespace->XMLPort(rootElement, XMLPort::LoadObject);
+
+            if(bVerbose)
+                orxout(user_info) << "Finished loading " << file->getFilename() << '.' << endl;
+            else
+                orxout(verbose, context::loader) << "Finished loading " << file->getFilename() << '.' << endl;
+
+            orxout(verbose, context::loader) << "Namespace-tree:" << '\n' << rootNamespace->toString("  ") << endl;
+
+            return true;
+        }
+        catch (ticpp::Exception& ex)
+        {
+            orxout(user_error, context::loader) << endl;
+            orxout(user_error, context::loader) << "An XML-error occurred in Loader.cc while loading " << file->getFilename() << ':' << endl;
+            OutputLevel ticpplevel = user_error;
+            if (lineTrace->size() > 0)
+            {
+                ticpplevel = internal_error;
+                //Extract the line number from the exception
+                std::string tempstring(ex.what());
+                std::string::size_type pos = tempstring.find("\nLine: ");
+                if (pos != std::string::npos)
+                {
+                    std::istringstream istr(tempstring.substr(pos + 7));
+                    size_t line;
+                    istr >> line;
+                    if (line <= lineTrace->size())
+                    {
+                        std::vector<std::pair<std::string, size_t>> linesources = lineTrace->at(line - 1);
+                        std::ostringstream message;
+                        message << "Possible sources of error:" << endl;
+                        for (const std::pair<std::string, size_t>& pair : linesources)
+                        {
+                            message << pair.first << ", Line " << pair.second << endl;
+                        }
+                        orxout(user_error, context::loader) << message.str() << endl;
+                    }
+                }
+            }
+            orxout(ticpplevel, context::loader) << ex.what() << endl;
+            orxout(user_error, context::loader) << "Loading aborted." << endl;
+        }
+        catch (Exception& ex)
+        {
+            orxout(user_error, context::loader) << endl;
+            orxout(user_error, context::loader) << "A loading-error occurred in Loader.cc while loading " << file->getFilename() << ':' << endl;
+            orxout(user_error, context::loader) << ex.what() << endl;
+            orxout(user_error, context::loader) << "Loading aborted." << endl;
+        }
+        catch (...)
+        {
+            orxout(user_error, context::loader) << endl;
+            orxout(user_error, context::loader) << "An error occurred in Loader.cc while loading " << file->getFilename() << ':' << endl;
+            orxout(user_error, context::loader) << Exception::handleMessage() << endl;
+            orxout(user_error, context::loader) << "Loading aborted." << endl;
+        }
+        //The Tardis' version of boost is too old...
+#if BOOST_VERSION >= 104600
+        boost::filesystem::path temppath = boost::filesystem::temp_directory_path() / "orxonoxml.xml";
+        //Need binary mode, because xmlInput already has \r\n for windows
+        boost::filesystem::ofstream outfile(temppath, std::ios_base::binary | std::ios_base::out);
+        outfile << xmlInput;
+        outfile.flush();
+        outfile.close();
+        orxout(internal_error, context::loader) << "The complete xml file has been saved to " << temppath << endl;
+#endif
+        return false;
+    }
+
+    void Loader::unload(const XMLFile* file, const ClassTreeMask& mask)
+    {
+        if (!file)
+            return;
+        for (ObjectList<BaseObject>::iterator it = ObjectList<BaseObject>().begin(); it; )
+        {
+            if ((it->getFile() == file) && mask.isIncluded(it->getIdentifier()))
+                (it++)->destroy();
+            else
+                ++it;
+        }
+    }
+
+    bool Loader::getLuaTags(const std::string& text, std::map<size_t, bool>& luaTags)
+    {
+        // fill map with all Lua tags
+        {
+            size_t pos = 0;
+            while ((pos = text.find("<?lua", pos)) != std::string::npos)
+                luaTags[pos++] = true;
+        }
+        {
+            size_t pos = 0;
+            while ((pos = text.find("?>", pos)) != std::string::npos)
+                luaTags[pos++] = false;
+        }
+
+        // erase all tags from the map that are between two quotes
+        // that means occurrences like "..<?lua.." and "..?>.." would be deleted
+        // however occurrences of lua tags within quotas are retained: ".. <?lua ... ?> .. "
+        {
+            std::map<size_t, bool>::iterator it = luaTags.begin();
+            bool bBetweenQuotes = false;
+            size_t pos = 0;
+            while ((pos = getNextQuote(text, pos)) != std::string::npos)
+            {
+                while ((it != luaTags.end()) && (it->first < pos))
+                {
+                    if (bBetweenQuotes)
+                    {
+                        std::map<size_t, bool>::iterator it2 = it;
+                        it2++;
+                        if (it->second && !(it2->second) && it2->first < pos)
+                            std::advance(it, 2);
+                        else
+                            luaTags.erase(it++);
+                    }
+                    else
+                        ++it;
+                }
+                bBetweenQuotes = !bBetweenQuotes;
+                pos++;
+            }
+        }
+
+        // check whether on every opening <?lua tag a closing ?> tag follows
+        {
+            bool expectedValue = true;
+            for (const auto& mapEntry : luaTags)
+            {
+                if (mapEntry.second == expectedValue)
+                    expectedValue = !expectedValue;
+                else
+                {
+                    expectedValue = false;
+                    break;
+                }
+            }
+            if (!expectedValue)
+            {
+                orxout(internal_error, context::loader) << "Error parsing file: lua tags not matching" << endl;
+                // TODO: error handling
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    std::string Loader::replaceLuaTags(const std::string& text)
+    {
+        // create a map with all lua tags
+        std::map<size_t, bool> luaTags;
+        if (!getLuaTags(text, luaTags))
+            return "";
+
+        // Use a stringstream object to speed up the parsing
+        std::ostringstream output;
+
+        // cut the original string into pieces and put them together with print() instead of lua tags
+        {
+            std::map<size_t, bool>::iterator it = luaTags.begin();
+            bool bInPrintFunction = true;
+            size_t start = 0;
+            size_t end = 0;
+
+            do
+            {
+                if (it != luaTags.end())
+                    end = (it++)->first;
+                else
+                    end = std::string::npos;
+
+                unsigned int equalSignCounter = 0;
+
+                if (bInPrintFunction)
+                {
+                    // count ['='[ and ]'='] and replace tags with print([[ and ]])
+                    const std::string& temp = text.substr(start, end - start);
+                    {
+                    size_t pos = 0;
+                    while ((pos = temp.find('[', pos)) != std::string::npos)
+                    {
+                        unsigned int tempCounter = 1;
+                        size_t tempPos = pos++;
+                        while (temp[++tempPos] == '=')
+                        {
+                            tempCounter++;
+                        }
+                        if (temp[tempPos] != '[')
+                        {
+                            tempCounter = 0;
+                        }
+                        else if (tempCounter == 0)
+                        {
+                            tempCounter = 1;
+                        }
+                        if (tempCounter > equalSignCounter)
+                            equalSignCounter = tempCounter;
+                        }
+                    }
+                    {
+                        size_t pos = 0;
+                        while ((pos = temp.find(']', pos)) != std::string::npos)
+                        {
+                            unsigned int tempCounter = 1;
+                            size_t tempPos = pos++;
+                            while (temp[++tempPos] == '=')
+                            {
+                                tempCounter++;
+                            }
+                            if (temp[tempPos] != ']')
+                            {
+                                tempCounter = 0;
+                            }
+                            else if (tempCounter == 0)
+                            {
+                                tempCounter = 1;
+                            }
+                            if (tempCounter > equalSignCounter)
+                                equalSignCounter = tempCounter;
+                        }
+                    }
+                    std::string equalSigns;
+                    for (unsigned int i = 0; i < equalSignCounter; i++)
+                    {
+                        equalSigns += '=';
+                    }
+                    //A newline directly after square brackets is ignored. To make sure that the string is printed
+                    //exactly as it is, including newlines at the beginning, insert a space after the brackets.
+                    bool needsExtraSpace = false;
+                    if (temp.size() > 0 && (temp[0] == '\n' || temp[0] == '\r')) // begins with \n or \r (a line break)
+                        needsExtraSpace = true;
+                    output << "print([" + equalSigns + (needsExtraSpace ? "[ " : "[") + temp + ']' + equalSigns +"])";
+                    start = end + 5;
+                }
+                else
+                {
+                    output << text.substr(start, end - start);
+                    start = end + 2;
+                }
+
+                bInPrintFunction = !bInPrintFunction;
+            }
+            while (end != std::string::npos);
+        }
+
+        return output.str();
+    }
+
+    std::string Loader::removeLuaTags(const std::string& text)
+    {
+        // create a map with all lua tags
+        std::map<size_t, bool> luaTags;
+        if (!getLuaTags(text, luaTags))
+            return "";
+
+        // Use a stringstream object to speed up the concatenation
+        std::ostringstream output;
+
+        // cut the original string into pieces and only write the non Lua parts
+        std::map<size_t, bool>::iterator it = luaTags.begin();
+        bool bLuaCode = false;
+        size_t start = 0;
+        size_t end = 0;
+
+        do
+        {
+            if (it != luaTags.end())
+                end = (it++)->first;
+            else
+                end = std::string::npos;
+
+            if (!bLuaCode)
+            {
+                output << text.substr(start, end - start);
+                start = end + 5;
+            }
+            else
+            {
+                //Preserve the amount of lines, otherwise the linenumber from the xml parse error is useless
+                std::string tempstring = text.substr(start, end - start);
+                output << std::string(std::count(tempstring.begin(), tempstring.end(), '\n'), '\n');
+                start = end + 2;
+            }
+
+            bLuaCode = !bLuaCode;
+        }
+        while (end != std::string::npos);
+
+        return output.str();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Loader.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Loader.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Loader.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Loader Loader
+    @ingroup XML
+*/
+
+/**
+    @file
+    @ingroup XML Loader
+*/
+
+#ifndef _Loader_H__
+#define _Loader_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <vector>
+
+#include "util/Singleton.h"
+#include "ClassTreeMask.h"
+
+namespace orxonox
+{
+    class _CoreExport Loader : public Singleton<Loader>
+    {
+        friend class Singleton<Loader>;
+
+        public:
+            bool load(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask(),
+                      bool bVerbose = true, bool bRemoveLuaTags = false);
+            void unload(const XMLFile* file, const ClassTreeMask& mask = ClassTreeMask());
+
+            static std::string replaceLuaTags(const std::string& text);
+            static std::string removeLuaTags(const std::string& text);
+
+            ClassTreeMask currentMask_;
+
+        private:
+            static bool getLuaTags(const std::string& text, std::map<size_t, bool>& luaTags);
+
+            std::vector<std::pair<const XMLFile*, ClassTreeMask>> files_;
+
+            static Loader* singletonPtr_s;
+    };
+}
+
+#endif /* _Loader_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/LuaState.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/LuaState.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/LuaState.cc	(revision 11817)
@@ -0,0 +1,395 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LuaState.h"
+
+#include <tolua++.h>
+extern "C" {
+#include <lua.h>
+#include <lualib.h>
+}
+#include <loki/ScopeGuard.h>
+
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "Resource.h"
+#include "command/IOConsole.h"
+
+namespace orxonox
+{
+    const std::string LuaState::ERROR_HANDLER_NAME = "errorHandler";
+
+    LuaState::LuaState()
+        : bIsRunning_(false)
+        , includeParseFunction_(nullptr)
+    {
+        // Create new lua state and configure it
+        luaState_ = lua_open();
+        Loki::ScopeGuard luaStateGuard = Loki::MakeGuard(&lua_close, luaState_);
+        luaL_openlibs(luaState_);
+
+        // Open all available tolua interfaces
+        this->openToluaInterfaces(luaState_);
+
+        // Create dummy file info
+        sourceFileInfo_.reset(new ResourceInfo());
+        sourceFileInfo_->group = "General";
+        sourceFileInfo_->size = 0;
+
+        // Push 'this' pointer
+        tolua_pushusertype(luaState_, static_cast<void*>(this), "orxonox::LuaState");
+        lua_setglobal(luaState_, "luaState");
+
+        // Parse init script
+        if (!this->doFile("LuaStateInit.lua"))
+            ThrowException(InitialisationFailed, "Running LuaStateInit.lua failed");
+
+        luaStateGuard.Dismiss();
+    }
+
+    LuaState::~LuaState()
+    {
+        lua_close(luaState_);
+    }
+
+    std::shared_ptr<ResourceInfo> LuaState::getFileInfo(const std::string& filename)
+    {
+        // Look in the current directory first
+        std::shared_ptr<ResourceInfo> sourceInfo = Resource::getInfo(sourceFileInfo_->path + filename);
+        // Continue search in root directories
+        if (sourceInfo == nullptr && !sourceFileInfo_->path.empty())
+            sourceInfo = Resource::getInfo(filename);
+        return sourceInfo;
+    }
+
+    bool LuaState::includeFile(const std::string& filename)
+    {
+        std::shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
+        if (sourceInfo != nullptr)
+            return this->includeString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
+        else
+        {
+            orxout(internal_warning, context::lua) << "LuaState: Cannot include file '" << filename << "' (not found)." << endl;
+            return false;
+        }
+    }
+
+    bool LuaState::includeString(const std::string& code, const std::shared_ptr<ResourceInfo>& sourceFileInfo)
+    {
+        // Parse string with provided include parser (otherwise don't preparse at all)
+        std::string luaInput;
+        if (includeParseFunction_ != nullptr)
+            luaInput = (*includeParseFunction_)(code);
+        else
+            luaInput = code;
+
+        if (sourceFileInfo != nullptr)
+        {
+            // Also fill a map with the actual source code. This is just for the include* commands
+            // where the content of sourceFileInfo->filename doesn't match 'code'
+            this->sourceCodeMap_[sourceFileInfo->filename] = code;
+        }
+
+        bool returnValue = this->doString(luaInput, sourceFileInfo);
+
+        if (sourceFileInfo != nullptr)
+        {
+            // Delete source code entry
+            if (sourceFileInfo != nullptr)
+                this->sourceCodeMap_.erase(sourceFileInfo->filename);
+        }
+
+        return returnValue;
+    }
+
+    bool LuaState::doFile(const std::string& filename)
+    {
+        std::shared_ptr<ResourceInfo> sourceInfo = this->getFileInfo(filename);
+        if (sourceInfo != nullptr)
+            return this->doString(Resource::open(sourceInfo)->getAsString(), sourceInfo);
+        else
+        {
+            orxout(internal_warning, context::lua) << "LuaState: Cannot do file '" << filename << "' (not found)." << endl;
+            return false;
+        }
+    }
+
+    bool LuaState::doString(const std::string& code, const std::shared_ptr<ResourceInfo>& sourceFileInfo)
+    {
+        // Save the old source file info
+        std::shared_ptr<ResourceInfo> oldSourceFileInfo = sourceFileInfo_;
+        // Only override if sourceFileInfo provides useful information
+        if (sourceFileInfo != nullptr)
+            sourceFileInfo_ = sourceFileInfo;
+
+        std::string chunkname;
+        if (sourceFileInfo != nullptr)
+        {
+            // Provide lua_load with the filename for debug purposes
+            // The '@' is a Lua convention to identify the chunk name as filename
+            chunkname = '@' + sourceFileInfo->filename;
+        }
+        else
+        {
+            // Use the code string to identify the chunk
+            chunkname = code;
+        }
+
+        // Push custom error handler that uses the debugger
+        lua_getglobal(this->luaState_, ERROR_HANDLER_NAME.c_str());
+        int errorHandler = lua_gettop(luaState_);
+        if (lua_isnil(this->luaState_, -1))
+        {
+            lua_pop(this->luaState_, 1);
+            errorHandler = 0;
+        }
+
+        int error = luaL_loadbuffer(luaState_, code.c_str(), code.size(), chunkname.c_str());
+
+        switch (error)
+        {
+        case LUA_ERRSYNTAX: // Syntax error
+            orxout(internal_error, context::lua) << "Lua syntax error: " << lua_tostring(luaState_, -1) << endl;
+            break;
+        case LUA_ERRMEM:    // Memory allocation error
+            orxout(internal_error, context::lua) << "Lua memory allocation error: Consult your dentist immediately!" << endl;
+            break;
+        }
+
+        if (error == 0)
+        {
+            // Execute the chunk in protected mode with an error handler function (stack index)
+            error = lua_pcall(luaState_, 0, 1, errorHandler);
+
+            switch (error)
+            {
+            case LUA_ERRRUN: // Runtime error
+                if (errorHandler)
+                {
+                    // Do nothing (we already display the error in the
+                    // 'errorHandler' Lua function in LuaStateInit.lua)
+                }
+                else
+                {
+                    std::string errorString = lua_tostring(this->luaState_, -1);
+                    if (errorString.find("Error propagation") == std::string::npos)
+                        orxout(internal_error, context::lua) << "Lua runtime error: " << errorString << endl;
+                }
+                break;
+            case LUA_ERRERR: // Error in the error handler
+                orxout(internal_error, context::lua) << "Lua error in error handler. No message available." << endl;
+                break;
+            case LUA_ERRMEM: // Memory allocation error
+                orxout(internal_error, context::lua) << "Lua memory allocation error: Consult your dentist immediately!" << endl;
+                break;
+            }
+        }
+
+        if (error != 0)
+        {
+            lua_pop(luaState_, 1);  // Remove error message
+            lua_pushnil(luaState_); // Push a nil return value
+        }
+
+        if (errorHandler != 0)
+            lua_remove(luaState_, errorHandler); // Remove error handler from stack
+
+        // Set return value to a global variable because we cannot return a table in this function
+        // here. It would work for numbers, pointers and strings, but certainly not for Lua tables.
+        lua_setglobal(luaState_, "LuaStateReturnValue");
+
+        // Load the old info again
+        sourceFileInfo_ = oldSourceFileInfo;
+
+        return (error == 0);
+    }
+
+    void LuaState::luaPrint(const std::string& str)
+    {
+        if (lineTrace_)
+        {
+            //Get lua debug info of second level in stack (level 1 is function print in LuaStateInit.lua)
+            lua_Debug ar;
+            lua_getstack(luaState_, 2, &ar);
+            lua_getinfo(luaState_, "nSl", &ar);
+            int line = ar.currentline;
+            std::string filename(ar.short_src);
+
+            //Add first line, which always exists
+            //Note: due to newlines etc., it's possible that one line consists of parts of
+            //      multiple, different files
+            std::vector<std::vector<std::pair<std::string, size_t>>>::reverse_iterator it = lineTrace_->rbegin();
+            std::pair<std::string, size_t> temppair = std::make_pair(filename, line);
+            //Avoid duplicate entries. This could happen if there were lua blocks on the same line
+            if (it->size() == 0 || std::find(it->begin(), it->end(), temppair) == it->end())
+            {
+                it->push_back(temppair);
+            }
+
+            //Add the rest of the lines, if there are any. Empty or not doesn't matter
+            size_t newlinecount = std::count(str.begin(), str.end(), '\n');
+            //i newlines -> i+1 lines, first line already added
+            for (size_t i = 1; i <= newlinecount; i++)
+            {
+                //Add the new line to the trace map
+                lineTrace_->emplace_back();
+                //Add the source of the line at the end
+                lineTrace_->rbegin()->emplace_back(filename, line + i);
+            }
+        }
+
+        output_ << str;
+    }
+
+    void LuaState::luaOutput(OutputLevel level, const std::string& context, const std::string& message)
+    {
+        orxout(level, registerContext(context)) << message << endl;
+    }
+
+    void LuaState::luaOutput(OutputLevel level, const std::string& message)
+    {
+        orxout(level, context::lua) << message << endl;
+    }
+
+    void LuaState::luaOutput(const std::string& message)
+    {
+        orxout(debug_output, context::lua) << message << endl;
+    }
+
+    bool LuaState::fileExists(const std::string& filename)
+    {
+        std::shared_ptr<ResourceInfo> info = this->getFileInfo(filename);
+        if (info == nullptr)
+            return false;
+        else
+            return true;
+    }
+
+    //! Returns the content of a file
+    std::string LuaState::getSourceCode(const std::string& filename)
+    {
+        // Try the internal map first to get the actual Lua code
+        // and not just some pseudo Lua-XML code when using include* commands
+        std::map<std::string, std::string>::const_iterator it = this->sourceCodeMap_.find(filename);
+        if (it != this->sourceCodeMap_.end())
+            return it->second;
+        std::shared_ptr<ResourceInfo> info = Resource::getInfo(filename);
+        if (info == nullptr)
+            return "";
+        else
+            return Resource::open(info)->getAsString();
+    }
+
+    bool LuaState::usingIOConsole() const
+    {
+        return IOConsole::exists();
+    }
+
+    /*static*/ LuaState::ToluaInterfaceMap& LuaState::getToluaInterfaces()
+    {
+        static ToluaInterfaceMap p;
+        return p;
+    }
+
+    /*static*/ std::vector<LuaState*>& LuaState::getInstances()
+    {
+        static std::vector<LuaState*> p;
+        return p;
+    }
+
+    /*static*/ bool LuaState::addToluaInterface(int (*function)(lua_State*), const std::string& name)
+    {
+        for (const auto& mapEntry : getToluaInterfaces())
+        {
+            if (mapEntry.first == name || mapEntry.second == function)
+            {
+                orxout(internal_warning, context::lua) << "Trying to add a Tolua interface with the same name or function." << endl;
+                return true;
+            }
+        }
+        getToluaInterfaces()[name] = function;
+
+        // Open interface in all LuaStates
+        for (LuaState* state : getInstances())
+            (*function)(state->luaState_);
+
+        // Return dummy bool
+        return true;
+    }
+
+    /*static*/ bool LuaState::removeToluaInterface(const std::string& name)
+    {
+        ToluaInterfaceMap::iterator it = getToluaInterfaces().find(name);
+        if (it == getToluaInterfaces().end())
+        {
+            orxout(internal_warning, context::lua) << "Cannot remove Tolua interface '" << name << "': Not found" << endl;
+            return true;
+        }
+
+        // Close interface in all LuaStates
+        for (LuaState* state : getInstances())
+        {
+            lua_pushnil(state->luaState_);
+            lua_setglobal(state->luaState_, it->first.c_str());
+        }
+
+        // Remove entry
+        getToluaInterfaces().erase(it);
+
+        // Return dummy bool
+        return true;
+    }
+
+    /*static*/ void LuaState::openToluaInterfaces(lua_State* state)
+    {
+        for (const auto& mapEntry : getToluaInterfaces())
+            (mapEntry.second)(state);
+    }
+
+    /*static*/ void LuaState::closeToluaInterfaces(lua_State* state)
+    {
+        for (const auto& mapEntry : getToluaInterfaces())
+        {
+            lua_pushnil(state);
+            lua_setglobal(state, mapEntry.first.c_str());
+        }
+    }
+
+
+    LuaFunctor::LuaFunctor(const std::string& code, LuaState* luaState)
+    {
+        this->code_ = code;
+        this->lua_ = luaState;
+    }
+
+    void LuaFunctor::operator()()
+    {
+        lua_->doString(this->code_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/LuaState.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/LuaState.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/LuaState.h	(revision 11817)
@@ -0,0 +1,151 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Lua Lua
+    @ingroup Core
+*/
+
+/**
+    @file
+    @ingroup Lua
+*/
+
+#ifndef _LuaState_H__
+#define _LuaState_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "util/Output.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+    class LuaFunctor; // tolua_export
+
+    //! callback class that executes lua code
+    class _CoreExport LuaFunctor
+    {
+        public:
+            LuaFunctor(const std::string& code, LuaState* luaState);
+            void operator()();
+
+        private:
+            std::string code_;
+            LuaState*   lua_;
+    };
+
+
+    /**
+    @brief
+        Representation of an interface to lua
+    */
+    class _CoreExport LuaState // tolua_export
+    { // tolua_export
+    public:
+        LuaState();
+        ~LuaState();
+
+        bool doFile(const std::string& filename); // tolua_export
+        bool doString(const std::string& code, const std::shared_ptr<ResourceInfo>& sourceFileInfo = std::shared_ptr<ResourceInfo>());
+
+        bool includeFile(const std::string& filename); // tolua_export
+        bool includeString(const std::string& code, const std::shared_ptr<ResourceInfo>& sourceFileInfo = std::shared_ptr<ResourceInfo>());
+
+        void luaPrint(const std::string& str); // tolua_export
+        void luaOutput(orxonox::level::OutputLevel level, const std::string& context, const std::string& message); // tolua_export
+        void luaOutput(orxonox::level::OutputLevel level, const std::string& message); // tolua_export
+        void luaOutput(const std::string& message); // tolua_export
+        bool fileExists(const std::string& filename); // tolua_export
+        std::string getSourceCode(const std::string& filename); // tolua_export
+
+        const std::stringstream& getOutput() const { return output_; }
+        void clearOutput() { output_.clear(); } // tolua_export
+
+        void setTraceMap(std::shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> map)
+            { map->emplace_back(); lineTrace_ = map; }
+
+        void setIncludeParser(std::string (*function)(const std::string&)) { includeParseFunction_ = function; }
+        lua_State* getInternalLuaState() { return luaState_; }
+
+        void setDefaultResourceInfo(const std::shared_ptr<ResourceInfo>& sourceFileInfo) { this->sourceFileInfo_ = sourceFileInfo; }
+        const std::shared_ptr<ResourceInfo>& getDefaultResourceInfo() { return this->sourceFileInfo_; }
+
+        LuaFunctor* createLuaFunctor(const std::string& code) { return new LuaFunctor(code, this); } // tolua_export
+        //! Tells about whether IOConsole was activated. The Lua debugger only works with a normal console.
+        bool usingIOConsole() const; // tolua_export
+
+        static bool addToluaInterface(int (*function)(lua_State*), const std::string& name);
+        static bool removeToluaInterface(const std::string& name);
+        static void openToluaInterfaces(lua_State* state);
+        static void closeToluaInterfaces(lua_State* state);
+
+        static const std::string ERROR_HANDLER_NAME;
+
+    private:
+        std::shared_ptr<ResourceInfo> getFileInfo(const std::string& filename);
+        std::shared_ptr<std::vector<std::vector<std::pair<std::string, size_t>>>> lineTrace_;
+        
+        std::stringstream output_;
+        lua_State* luaState_;
+        bool bIsRunning_;
+        std::shared_ptr<ResourceInfo> sourceFileInfo_;
+        std::map<std::string, std::string> sourceCodeMap_;
+        std::string (*includeParseFunction_)(const std::string&);
+
+        typedef std::map<std::string, int (*)(lua_State *L)> ToluaInterfaceMap;
+        static ToluaInterfaceMap& getToluaInterfaces();
+        static std::vector<LuaState*>& getInstances();
+    }; // tolua_export
+
+
+    //! Helper class that registers/unregisters tolua bindings
+    class ToluaBindingsHelper
+    {
+    public:
+        ToluaBindingsHelper(int (*function)(lua_State*), const std::string& libraryName)
+            : libraryName_(libraryName)
+        {
+            LuaState::addToluaInterface(function, libraryName_);
+        }
+        ~ToluaBindingsHelper()
+        {
+            LuaState::removeToluaInterface(libraryName_);
+        }
+    private:
+        std::string libraryName_;
+    };
+} // tolua_export
+
+#endif /* _LuaState_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Namespace.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Namespace.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Namespace.cc	(revision 11817)
@@ -0,0 +1,179 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Namespace.h"
+
+#include <set>
+
+#include "NamespaceNode.h"
+#include "CoreIncludes.h"
+#include "XMLPort.h"
+#include "util/SubString.h"
+
+namespace orxonox
+{
+    RegisterClass(Namespace);
+
+    Namespace::Namespace(Context* context) : BaseObject(context), Context(context),
+      bAutogeneratedFileRootNamespace_(false),
+      bRoot_(false),
+      operator_("or")
+    {
+        RegisterObject(Namespace);
+
+        this->setNamespace(WeakPtr<Namespace>(this)); // store a weak-pointer to itself (a strong-pointer would create a recursive dependency)
+    }
+
+    Namespace::~Namespace()
+    {
+        if (this->bRoot_)
+            for (NamespaceNode* node : this->representingNamespaces_)
+                delete node;
+    }
+
+    void Namespace::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Namespace, XMLPort, xmlelement, mode);
+
+        std::string name = this->getName();
+        size_t pos = 0;
+        while ((pos = name.find(',')) != std::string::npos)
+            name.replace(pos, 1, " ");
+        while ((pos = name.find(';')) != std::string::npos)
+            name.replace(pos, 1, " ");
+        while ((pos = name.find('\n')) != std::string::npos)
+            name.replace(pos, 1, " ");
+        while ((pos = name.find('\t')) != std::string::npos)
+            name.replace(pos, 1, " ");
+        SubString tokens(name, " ", "", false, '\\', true, '"', true, '\0', '\0', true, '\0');
+        if (this->bRoot_)
+        {
+            this->representingNamespaces_.insert(new NamespaceNode(this->getName()));
+        }
+        else
+        {
+            for (unsigned int i = 0; i < tokens.size(); i++)
+            {
+                for (NamespaceNode* node : this->getNamespace()->representingNamespaces_)
+                {
+                    std::set<NamespaceNode*> temp = node->getNodeRelative(tokens[i]);
+                    this->representingNamespaces_.insert(temp.begin(), temp.end());
+                }
+            }
+        }
+
+        XMLPortParam(Namespace, "operator", setOperator, getOperator, xmlelement, mode);
+        XMLPortParam(Namespace, "bAutogenerated", setAutogenerated, isAutogenerated, xmlelement, mode);
+
+        if (this->bAutogeneratedFileRootNamespace_)
+        {
+            for (NamespaceNode* node : this->representingNamespaces_)
+            {
+                node->setRoot(true);
+                node->setHidden(true);
+            }
+        }
+
+        XMLPortObjectExtended(Namespace, BaseObject, "", loadObjects, saveObjects, xmlelement, mode, true, false);
+    }
+
+    void Namespace::loadObjects(BaseObject* object)
+    {
+    }
+
+    const BaseObject* Namespace::saveObjects(unsigned int index) const
+    {
+        return nullptr; // todo
+    }
+
+    bool Namespace::includes(const Namespace* ns) const
+    {
+        for (NamespaceNode* node1 : this->representingNamespaces_)
+        {
+            for (NamespaceNode* node2 : ns->representingNamespaces_)
+            {
+                if (node1->includes(node2))
+                {
+                    if (this->operator_ == "or")
+                        return true;
+
+                    if (this->operator_ == "not")
+                        return false;
+                }
+                else
+                {
+                    if (this->operator_ == "and")
+                        return false;
+                }
+            }
+        }
+
+        if (this->operator_ == "or")
+            return false;
+        else if (this->operator_ == "and")
+            return true;
+        else if (this->operator_ == "not")
+            return true;
+
+        return false;
+    }
+
+    std::string Namespace::toString() const
+    {
+        std::string output;
+
+        int i = 0;
+        for (NamespaceNode* node : this->representingNamespaces_)
+        {
+            if (i > 0)
+                output += " / ";
+
+            output += node->toString();
+            i++;
+        }
+
+        return output;
+    }
+
+    std::string Namespace::toString(const std::string& indentation) const
+    {
+        std::string output;
+
+        int i = 0;
+        for (NamespaceNode* node : this->representingNamespaces_)
+        {
+            if (i > 0)
+                output += '\n';
+
+            output += node->toString(indentation);
+            i++;
+        }
+
+        return output;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Namespace.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Namespace.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Namespace.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup XML Loader
+*/
+
+#ifndef _Namespace_H__
+#define _Namespace_H__
+
+#include "CorePrereqs.h"
+
+#include <set>
+#include <string>
+#include "BaseObject.h"
+#include "object/Context.h"
+
+namespace orxonox
+{
+    class Namespace : public BaseObject, public Context
+    {
+        public:
+            Namespace(Context* context);
+            virtual ~Namespace();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void loadObjects(BaseObject* object);
+            const BaseObject* saveObjects(unsigned int index) const;
+
+            void setAutogenerated(bool bAutogenerated)
+                { this->bAutogeneratedFileRootNamespace_ = bAutogenerated; }
+            bool isAutogenerated() const
+                { return this->bAutogeneratedFileRootNamespace_; }
+
+            void setOperator(const std::string& op)
+                { this->operator_ = op; }
+            const std::string& getOperator() const
+                { return this->operator_; }
+
+            void setRoot(bool bRoot)
+                { this->bRoot_ = bRoot; }
+
+            bool includes(const Namespace* ns) const;
+            bool isIncludedIn(const Namespace* ns) const { return ns->includes(this); }
+
+            std::string toString() const;
+            std::string toString(const std::string& indentation) const;
+
+        private:
+            std::set<NamespaceNode*> representingNamespaces_;
+            bool bAutogeneratedFileRootNamespace_;
+            bool bRoot_;
+            std::string operator_;
+    };
+}
+
+#endif /* _Namespace_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/NamespaceNode.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/NamespaceNode.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/NamespaceNode.cc	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "NamespaceNode.h"
+#include "util/Output.h"
+
+namespace orxonox
+{
+    NamespaceNode::NamespaceNode(const std::string& name, NamespaceNode* parent)
+    {
+        this->name_ = name;
+        this->parent_ = parent;
+        this->bRoot_ = false;
+        this->bHidden_ = false;
+    }
+
+    NamespaceNode::~NamespaceNode()
+    {
+        for (std::map<std::string, NamespaceNode*>::iterator it = this->subnodes_.begin(); it != this->subnodes_.end(); )
+            delete (it++)->second;
+    }
+
+    std::set<NamespaceNode*> NamespaceNode::getNodeRelative(const std::string& name)
+    {
+        std::set<NamespaceNode*> nodes;
+
+        if (name.empty())
+        {
+            nodes.insert(this);
+        }
+        else
+        {
+            size_t pos = name.find("::");
+            std::string firstPart = name;
+            std::string secondPart;
+
+            if (pos != std::string::npos)
+            {
+                firstPart = name.substr(0, pos);
+                secondPart = name.substr(pos + 2, std::string::npos);
+            }
+
+            if (firstPart == "..")
+            {
+                if (this->bRoot_)
+                {
+                    orxout(internal_warning) << "Can't go to enclosing namespace with '..' operator in namespace " << this->name_ << ", namespace is root." << endl;
+                    nodes = this->getNodeRelative(secondPart);
+                }
+                else if (!this->parent_)
+                {
+                    orxout(internal_warning) << "Can't go to enclosing namespace with '..' operator in namespace " << this->name_ << ", no parent namespace set." << endl;
+                    nodes = this->getNodeRelative(secondPart);
+                }
+                else
+                {
+                    nodes = this->parent_->getNodeRelative(secondPart);
+                }
+            }
+            else if (name.find('@') != 0)
+            {
+                std::map<std::string, NamespaceNode*>::iterator it = this->subnodes_.find(firstPart);
+                if (it == this->subnodes_.end())
+                    it = this->subnodes_.insert(this->subnodes_.begin(), std::pair<std::string, NamespaceNode*>(firstPart, new NamespaceNode(firstPart, this)));
+
+                if (it->second->isHidden())
+                {
+                    orxout(internal_warning) << "Subnamespace '" << firstPart << "' in namespace '" << this->name_ << "' is hidden and can't be accessed." << endl;
+                    nodes.insert(this);
+                }
+                else
+                {
+                    nodes = it->second->getNodeRelative(secondPart);
+                }
+            }
+            else
+            {
+                bool bFoundMatchingNamespace = false;
+
+                for (const auto& mapEntry : this->subnodes_)
+                {
+                    if (mapEntry.first.find(firstPart) == (mapEntry.first.size() - firstPart.size()))
+                    {
+                        std::set<NamespaceNode*> temp2 = mapEntry.second->getNodeRelative(secondPart);
+                        nodes.insert(temp2.begin(), temp2.end());
+                        bFoundMatchingNamespace = true;
+                    }
+                }
+
+                if (!bFoundMatchingNamespace)
+                {
+                    orxout(internal_warning) << "No file included with name '" << firstPart.substr(1, std::string::npos) << "' at this part of the level file, using parent namespace instead." << endl;
+                    nodes = this->getNodeRelative(secondPart);
+                }
+            }
+        }
+
+        return nodes;
+    }
+
+    bool NamespaceNode::includes(const NamespaceNode* ns) const
+    {
+        if (ns == this)
+        {
+            return true;
+        }
+        else
+        {
+            for (const auto& mapEntry : this->subnodes_)
+                if (mapEntry.second->includes(ns))
+                    return true;
+        }
+
+        return false;
+    }
+
+    std::string NamespaceNode::toString() const
+    {
+        std::string output = this->name_;
+
+        if (this->subnodes_.size() > 0)
+        {
+            output += " (";
+
+            int i = 0;
+            for (const auto& mapEntry : this->subnodes_)
+            {
+                if (i > 0)
+                    output += ", ";
+
+                output += mapEntry.second->toString();
+                i++;
+            }
+
+            output += ')';
+        }
+
+        return output;
+    }
+
+    std::string NamespaceNode::toString(const std::string& indentation) const
+    {
+        std::string output = (indentation + this->name_ + '\n');
+
+        for (const auto& mapEntry : this->subnodes_)
+            output += mapEntry.second->toString(indentation + "  ");
+
+        return output;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/NamespaceNode.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/NamespaceNode.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/NamespaceNode.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup XML Loader
+*/
+
+#ifndef _NamespaceNode_H__
+#define _NamespaceNode_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+namespace orxonox
+{
+    class NamespaceNode
+    {
+        public:
+            NamespaceNode(const std::string& name, NamespaceNode* parent = nullptr);
+            ~NamespaceNode();
+
+            std::set<NamespaceNode*> getNodeRelative(const std::string& name);
+
+            void setRoot(bool bRoot) { this->bRoot_ = bRoot; }
+            void setHidden(bool bHidden) { this->bHidden_ = bHidden; }
+
+            bool isRoot() const { return this->bRoot_; }
+            bool isHidden() const { return this->bHidden_; }
+
+            bool includes(const NamespaceNode*) const;
+
+            std::string toString() const;
+            std::string toString(const std::string& indentation) const;
+
+        private:
+            std::string name_;
+            NamespaceNode* parent_;
+            std::map<std::string, NamespaceNode*> subnodes_;
+            bool bHidden_;
+            bool bRoot_;
+    };
+}
+
+#endif /* _NamespaceNode_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Resource.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Resource.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Resource.cc	(revision 11817)
@@ -0,0 +1,130 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Resource.h"
+
+#include <boost/filesystem/path.hpp>
+#include <OgreException.h>
+#include <OgreFileSystem.h>
+#include <OgreResourceGroupManager.h>
+
+// Differentiate Boost Filesystem v2 and v3
+#if (BOOST_FILESYSTEM_VERSION < 3)
+#  define BF_GENERIC_STRING string
+#else
+#  define BF_GENERIC_STRING generic_string
+#endif
+
+namespace orxonox
+{
+    const std::string& Resource::getDefaultResourceGroup()
+    {
+        return Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME;
+    }
+
+    DataStreamPtr Resource::open(const std::string& name)
+    {
+        return Ogre::ResourceGroupManager::getSingleton().openResource(name,
+            getDefaultResourceGroup(), true);
+    }
+
+    DataStreamListPtr Resource::openMulti(const std::string& pattern)
+    {
+        DataStreamListPtr resources(new Ogre::DataStreamList());
+        const Ogre::StringVector& groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
+        for (const std::string& group : groups)
+        {
+            DataStreamListPtr temp = Ogre::ResourceGroupManager::getSingleton().openResources(pattern, group);
+            resources->insert(resources->end(), temp->begin(), temp->end());
+        }
+        return resources;
+    }
+
+    bool Resource::exists(const std::string& name)
+    {
+        try
+        {
+            Ogre::ResourceGroupManager::getSingleton().findGroupContainingResource(name);
+            return true;
+        }
+        catch (const Ogre::Exception&)
+        {
+            return false;
+        }
+    }
+
+    std::shared_ptr<ResourceInfo> Resource::getInfo(const std::string& name)
+    {
+        std::string group;
+        try
+        {
+            group = Ogre::ResourceGroupManager::getSingleton().findGroupContainingResource(name);
+        }
+        catch (const Ogre::Exception&)
+        {
+            return std::shared_ptr<ResourceInfo>();
+        }
+        Ogre::FileInfoListPtr infos = Ogre::ResourceGroupManager::getSingleton().findResourceFileInfo(group, name);
+        for (Ogre::FileInfoList::const_iterator it = infos->begin(); it != infos->end(); ++it)
+        {
+            if (it->filename == name)
+            {
+                std::shared_ptr<ResourceInfo> ptr(std::make_shared<ResourceInfo>());
+                ptr->filename = name;
+                ptr->path = it->path;
+                ptr->basename = it->basename;
+                ptr->group = group;
+                ptr->size = it->uncompressedSize;
+#if OGRE_VERSION >= 0x010800
+                if (dynamic_cast<const Ogre::FileSystemArchive*>(it->archive) != nullptr)
+#else
+                if (dynamic_cast<Ogre::FileSystemArchive*>(it->archive) != nullptr)
+#endif
+                {
+                    boost::filesystem::path base(it->archive->getName());
+                    base /= it->filename;
+                    ptr->fileSystemPath = base.BF_GENERIC_STRING();
+                }
+                return ptr;
+            }
+        }
+        return std::shared_ptr<ResourceInfo>();
+    }
+
+    StringVectorPtr Resource::findResourceNames(const std::string& pattern)
+    {
+        StringVectorPtr resourceNames(new Ogre::StringVector());
+        const Ogre::StringVector& groups = Ogre::ResourceGroupManager::getSingleton().getResourceGroups();
+        for (const std::string& group : groups)
+        {
+            StringVectorPtr temp = Ogre::ResourceGroupManager::getSingleton().findResourceNames(group, pattern);
+            resourceNames->insert(resourceNames->end(), temp->begin(), temp->end());
+        }
+        return resourceNames;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Resource.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Resource.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Resource.h	(revision 11817)
@@ -0,0 +1,151 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Resources Resources
+    @ingroup Management
+*/
+
+/**
+    @file
+    @ingroup Management Resources
+*/
+
+#ifndef _Core_Resource_H__
+#define _Core_Resource_H__
+
+#include "CorePrereqs.h"
+
+#include <memory>
+
+#include <OgreDataStream.h>
+#include <OgreStringVector.h>
+
+namespace orxonox
+{
+    // Import the Ogre::DataStreamList
+    using Ogre::DataStreamList;
+    using Ogre::DataStreamListPtr;
+    using Ogre::StringVector;
+    using Ogre::StringVectorPtr;
+
+    //! Stores basic information about a Resource from Ogre
+    struct ResourceInfo
+    {
+        //! The file's fully qualified name
+        std::string filename;
+        //! Path name; separated by '/' and ending with '/'
+        std::string path;
+        //! Base filename
+        std::string basename;
+        //! Resource group the file is in
+        std::string group;
+        //! Uncompressed size
+        size_t size;
+        //! Absolute file path ("" for files not on filesystem)
+        std::string fileSystemPath;
+    };
+
+    /** Provides simple functions to easily access the Ogre::ResourceGroupManager.
+        The wrapper functions also avoid having to deal with resource groups.
+    */
+    class _CoreExport Resource
+    {
+        // Docs by Ogre::ResourceGroupManager.h
+    public:
+        /**
+        @brief
+            Open a single resource by name and return a DataStream
+            pointing at the source of the data.
+        @param name
+            The name of the resource to locate.
+            Even if resource locations are added recursively, you
+            must provide a fully qualified name to this method.
+        @return
+            Shared pointer to data stream containing the data. Will be
+            destroyed automatically when no longer referenced.
+        */
+        static DataStreamPtr open(const std::string& name);
+
+        //! Similar to open(string, string, bool), but with a fileInfo struct
+        static DataStreamPtr open(std::shared_ptr<ResourceInfo> fileInfo)
+        {
+            return open(fileInfo->filename);
+        }
+
+        /**
+        @brief
+            Open all resources matching a given pattern (which can contain
+            the character '*' as a wildcard), and return a collection of
+            DataStream objects on them.
+        @param pattern
+            The pattern to look for. If resource locations have been
+            added recursively, subdirectories will be searched too so this
+            does not need to be fully qualified.
+        @return
+            Shared pointer to a data stream list , will be
+            destroyed automatically when no longer referenced
+        */
+        static DataStreamListPtr openMulti(const std::string& pattern);
+
+        /**
+            Find out if the named file exists.
+        @param name
+            Fully qualified name of the file to test for
+        */
+        static bool exists(const std::string& name);
+
+        /**
+            Get struct with information about path and size.
+        @param name
+            Fully qualified name of the file to test for
+        */
+        static std::shared_ptr<ResourceInfo> getInfo(const std::string& name);
+
+        /**
+            Retrieves a list with all resources matching a certain pattern.
+        @param pattern
+            The pattern to look for. If resource locations have been
+            added recursively, subdirectories will be searched too so this
+            does not need to be fully qualified.
+        */
+        static StringVectorPtr findResourceNames(const std::string& pattern);
+
+        //! Name of the default resource group (usually "General")
+        static const std::string& getDefaultResourceGroup();
+
+    private:
+        // static class, no instances allowed:
+        Resource() = delete;
+        Resource(const Resource&) = delete;
+        Resource& operator=(const Resource&) = delete;
+        ~Resource() = delete;
+    };
+}
+
+#endif /* _Core_Resource_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Template.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Template.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Template.cc	(revision 11817)
@@ -0,0 +1,188 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Template.h"
+
+#include <tinyxml/tinyxml.h>
+#include <tinyxml/ticpp.h>
+
+#include "util/Output.h"
+#include "CoreIncludes.h"
+#include "XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(Template);
+
+    Template::Template(Context* context) : BaseObject(context)
+    {
+        this->xmlelement_ = new TiXmlElement("");
+
+        RegisterObject(Template);
+
+        this->bIsLink_ = false;
+        this->bLoadDefaults_ = true;
+        this->bIsReturningXMLElement_ = false;
+        this->baseclassIdentifier_ = nullptr;
+    }
+
+    Template::~Template()
+    {
+        Template::getTemplateMap().erase(this->getName());
+        delete this->xmlelement_;
+    }
+
+    void Template::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Template, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Template, "link",      setLink,         getLink,         xmlelement, mode);
+        XMLPortParam(Template, "baseclass", setBaseclass,    getBaseclass,    xmlelement, mode);
+        XMLPortParam(Template, "defaults",  setLoadDefaults, getLoadDefaults, xmlelement, mode).defaultValues(true);
+
+        Element* element = xmlelement.FirstChildElement(false);
+        if (element)
+        {
+            TiXmlElement* tixmlelement = static_cast<TiXmlElement*>(element->GetTiXmlPointer());
+            if (tixmlelement)
+                this->setXMLElement(*tixmlelement);
+        }
+    }
+
+    void Template::changedName()
+    {
+        SUPER(Template, changedName);
+
+        if (!this->getName().empty())
+        {
+            std::map<std::string, Template*>::iterator it;
+            it = Template::getTemplateMap().find(this->getOldName());
+            if (it != Template::getTemplateMap().end())
+                Template::getTemplateMap().erase(it);
+
+            it = Template::getTemplateMap().find(this->getName());
+            if (it != Template::getTemplateMap().end())
+                orxout(internal_warning, context::templates) << "Template with name \"" << this->getName() << "\" already exists." << endl;
+            else
+                Template::getTemplateMap()[this->getName()] = this;
+        }
+    }
+
+    void Template::setXMLElement(const TiXmlElement& xmlelement)
+    {
+        *this->xmlelement_ = xmlelement;
+    }
+
+    const TiXmlElement& Template::getXMLElement()
+    {
+        if (this->bIsLink_)
+        {
+            Template* temp = Template::getTemplate(this->link_);
+            if (temp)
+            {
+                this->bLoadDefaults_ = temp->bLoadDefaults_;
+
+                if (!temp->bIsReturningXMLElement_)
+                {
+                    this->bIsReturningXMLElement_ = true;
+                    const TiXmlElement& element = temp->getXMLElement();
+                    this->bIsReturningXMLElement_ = false;
+                    return element;
+                }
+                else
+                {
+                    orxout(internal_warning, context::templates) << "Linking from \"" << this->getName() << "\" to \"" << this->link_ << "\" leads to an infinite loop. Returning own element." << endl;
+                }
+            }
+            else
+            {
+                orxout(internal_warning, context::templates) << '"' << this->link_ << "\" is not an existing Template name. Returning own element." << endl;
+            }
+        }
+
+        return *this->xmlelement_;
+    }
+
+    void Template::setBaseclass(const std::string& baseclass)
+    {
+        this->baseclassIdentifier_ = ClassByString(baseclass);
+        if (this->baseclassIdentifier_)
+            this->baseclass_ = baseclass;
+    }
+
+    void Template::applyOn(BaseObject* object)
+    {
+        if (this->baseclassIdentifier_)
+        {
+            if (!object->isA(this->baseclassIdentifier_))
+            {
+                orxout(internal_error, context::templates) << "Can't apply template (name: " << this->getName() << "), object (name: " << object->getName() << ", class: " << object->getIdentifier()->getName() << ") is not a " << this->baseclassIdentifier_->getName() << endl;
+                return;
+            }
+        }
+
+        orxout(verbose, context::templates) << object->getLoaderIndentation() << " aplying Template \"" << this->getName() << "\"..." << endl;
+
+        // check if the template is applied on an object of the right type
+        Identifier* identifier = ClassByString(this->getXMLElement().Value());
+        if (!object->getIdentifier()->isA(identifier))
+            orxout(internal_warning, context::templates) << "Template was defined for " << identifier->getName() << " but the object is of type " << object->getIdentifier()->getName() << endl;
+
+        Element temp = &const_cast<TiXmlElement&>(this->getXMLElement());
+
+        if (this->bLoadDefaults_)
+            object->XMLPort(temp, XMLPort::LoadObject);
+        else
+            object->XMLPort(temp, XMLPort::ExpandObject);
+    }
+
+    std::map<std::string, Template*>& Template::getTemplateMap()
+    {
+        static std::map<std::string, Template*> templateMap;
+        return templateMap;
+    }
+
+    Template* Template::getTemplate(const std::string& name)
+    {
+        std::map<std::string, Template*>::iterator it = Template::getTemplateMap().find(name);
+        if (it != Template::getTemplateMap().end())
+            return it->second;
+        else
+        {
+            orxout(internal_warning, context::templates) << "Template with name " << name << " doesn't exist." << endl;
+            return nullptr;
+        }
+    }
+
+    void Template::apply(const std::string& name, BaseObject* object)
+    {
+        std::map<std::string, Template*>::iterator it = Template::getTemplateMap().find(name);
+        if (it != Template::getTemplateMap().end())
+            it->second->applyOn(object);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/Template.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Template.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Template.h	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Template Template
+    @ingroup XML
+*/
+
+/**
+    @file
+    @ingroup XML Template
+*/
+
+#ifndef _Template_H__
+#define _Template_H__
+
+#include "CorePrereqs.h"
+
+#include <map>
+#include <string>
+#include "BaseObject.h"
+
+namespace orxonox
+{
+    class _CoreExport Template : public BaseObject
+    {
+        public:
+            Template(Context* context);
+            virtual ~Template();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedName() override;
+
+            inline void setLink(const std::string& link)
+                { this->link_ = link; this->bIsLink_ = !link.empty(); }
+            inline const std::string& getLink() const
+                { return this->link_; }
+            inline bool isLink() const
+                { return this->bIsLink_; }
+
+            inline void setLoadDefaults(bool bLoadDefaults)
+                { this->bLoadDefaults_ = bLoadDefaults; }
+            inline bool getLoadDefaults() const
+                { return this->bLoadDefaults_; }
+
+            void setXMLElement(const TiXmlElement& xmlelement);
+            const TiXmlElement& getXMLElement();
+
+            void setBaseclass(const std::string& baseclass);
+            inline const std::string& getBaseclass() const
+                { return this->baseclass_; }
+            inline Identifier* getBaseclassIdentifier() const
+                { return this->baseclassIdentifier_; }
+
+            void applyOn(BaseObject* object);
+
+            static std::map<std::string, Template*>& getTemplateMap();
+            static Template* getTemplate(const std::string& name);
+            static void apply(const std::string& name, BaseObject* object);
+
+        private:
+            TiXmlElement* xmlelement_;
+            std::string link_;
+            std::string baseclass_;
+            Identifier* baseclassIdentifier_;
+            bool bIsLink_;
+            bool bLoadDefaults_;
+            mutable bool bIsReturningXMLElement_;
+    };
+}
+
+#endif /* _Template_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/Thread.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Thread.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Thread.cc	(revision 11817)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Thread.h"
+
+#if defined(ORXONOX_PLATFORM_WINDOWS)
+  #include "ThreadWin.cc"
+#elif defined(ORXONOX_PLATFORM_UNIX)
+
+#include <cassert>
+#include <functional>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+
+#include "util/Sleep.h"
+#include "command/Executor.h"
+
+namespace orxonox
+{
+    boost::posix_time::millisec THREAD_WAIT_BEFORE_DETACH(1000);
+
+
+    Thread::Thread():
+        executor_(nullptr),
+        isWorking_(false),
+        stopThread_(false)
+    {
+        this->executorMutex_ = new boost::mutex;
+        this->isWorkingMutex_ = new boost::mutex;
+        this->stopThreadMutex_ = new boost::mutex;
+        this->workerThread_ = new boost::thread( std::bind(&Thread::threadLoop, this) );
+    }
+
+    Thread::~Thread()
+    {
+        this->stopThreadMutex_->lock();
+        this->stopThread_ = true;
+        this->stopThreadMutex_->unlock();
+        if( !this->workerThread_->timed_join( THREAD_WAIT_BEFORE_DETACH ) )
+            assert(0); // this should not happen
+        delete this->workerThread_;
+        delete this->executorMutex_;
+        delete this->stopThreadMutex_;
+        delete this->isWorkingMutex_;
+    }
+
+    bool Thread::isWorking()
+    {
+      this->isWorkingMutex_->lock();
+      bool isWorking = this->isWorking_;
+      this->isWorkingMutex_->unlock();
+      return isWorking;
+    }
+
+    bool Thread::evaluateExecutor( const ExecutorPtr& executor )
+    {
+        this->isWorkingMutex_->lock();
+        this->isWorking_=true;
+        this->isWorkingMutex_->unlock();
+        this->executorMutex_->lock();
+        this->executor_ = executor;
+        this->executorMutex_->unlock();
+        return true;
+    }
+
+    void Thread::threadLoop()
+    {
+        bool stopThread = false;
+        while( !stopThread )
+        {
+            this->executorMutex_->lock();
+            ExecutorPtr executor = this->executor_;
+            this->executorMutex_->unlock();
+            if( executor )
+            {
+                (*executor)();
+                this->executorMutex_->lock();
+                this->executor_ = nullptr;
+                this->executorMutex_->unlock();
+                this->isWorkingMutex_->lock();
+                this->isWorking_=false;
+                this->isWorkingMutex_->unlock();
+            }
+            else
+            {
+                this->workerThread_->yield();
+            }
+            this->stopThreadMutex_->lock();
+            stopThread = this->stopThread_;
+            this->stopThreadMutex_->unlock();
+        }
+    }
+
+    void Thread::waitUntilFinished()
+    {
+        bool stillWorking = true;
+        while( stillWorking )
+        {
+            this->isWorkingMutex_->lock();
+            stillWorking = this->isWorking_;
+            this->isWorkingMutex_->unlock();
+            if( stillWorking )
+                msleep( 1 );
+        }
+    }
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/core/Thread.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/Thread.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/Thread.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup ThreadPool
+*/
+
+#ifndef _Thread_H__
+#define _Thread_H__
+
+#include "CorePrereqs.h"
+
+namespace boost{
+  class recursive_mutex;
+}
+
+ namespace orxonox
+{
+    class _CoreExport Thread
+    {
+    public:
+        Thread();
+        virtual ~Thread();
+
+        bool isWorking();
+        void waitUntilFinished();
+        bool evaluateExecutor( const ExecutorPtr& executor );
+
+    private:
+        void            threadLoop();
+
+        ExecutorPtr     executor_;
+        bool            isWorking_;
+        bool            stopThread_;
+        boost::thread*  workerThread_;
+        boost::mutex*   executorMutex_;
+        boost::mutex*   isWorkingMutex_;
+        boost::mutex*   stopThreadMutex_;
+    };
+
+ }
+
+#endif /* _Thread_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/ThreadPool.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ThreadPool.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ThreadPool.cc	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ThreadPool.h"
+
+#include "util/OrxAssert.h"
+#include "Thread.h"
+
+namespace orxonox
+{
+
+    ThreadPool::ThreadPool()
+    {
+    }
+
+    ThreadPool::~ThreadPool()
+    {
+        OrxVerify(this->setNrOfThreads(0) == 0, "ERROR: could not join remaining threads in ThreadPool" );
+    }
+
+    void ThreadPool::addThreads( unsigned int nr )
+    {
+        for( unsigned int i=0; i<nr; i++ )
+            this->threadPool_.push_back(new Thread());
+    }
+    unsigned int ThreadPool::removeThreads( unsigned int nr )
+    {
+        unsigned int i=0;
+        std::vector<Thread*>::iterator it;
+        for( it = this->threadPool_.begin(); it != threadPool_.end() && i<nr; )
+        {
+            if( ! (*it)->isWorking() )
+            {
+                Thread* temp = *it;
+                it=this->threadPool_.erase( it );
+                delete temp;
+                ++i;
+            }
+            else
+              ++it;
+        }
+        return i;
+    }
+    unsigned int ThreadPool::setNrOfThreads( unsigned int nr )
+    {
+        unsigned int currentsize = this->threadPool_.size();
+        if ( nr < currentsize )
+            return currentsize - removeThreads( currentsize - nr );
+        else if ( nr == currentsize )
+            return currentsize;
+        else
+        {
+            addThreads( nr - currentsize );
+            return nr;
+        }
+    }
+
+    bool ThreadPool::passFunction( const ExecutorPtr& executor, bool addThread )
+    {
+        for ( Thread* thread : threadPool_ )
+        {
+            if ( ! thread->isWorking() )
+            {
+                // If that fails, then there is some code error
+                OrxVerify( thread->evaluateExecutor( executor ), "ERROR: could not evaluate Executor" );
+                return true;
+            }
+        }
+        if ( addThread )
+        {
+            addThreads( 1 );
+            OrxVerify( this->threadPool_.back()->evaluateExecutor( executor ), "ERROR: could not evaluate Executor" ); // access the last element
+            return true;
+        }
+        else
+            return false;
+    }
+
+    void ThreadPool::synchronise()
+    {
+        for ( Thread* thread : this->threadPool_ )
+        {
+            thread->waitUntilFinished();
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/ThreadPool.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ThreadPool.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ThreadPool.h	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup ThreadPool Thread pool
+    @ingroup Core
+*/
+
+/**
+    @file
+    @ingroup ThreadPool
+*/
+
+#ifndef _ThreadPool_H__
+#define _ThreadPool_H__
+
+#include "CorePrereqs.h"
+
+#include <vector>
+
+ namespace orxonox
+{
+    class _CoreExport ThreadPool
+    {
+    public:
+        ThreadPool();
+        virtual ~ThreadPool();
+
+        void addThreads( unsigned int nr );
+        unsigned int removeThreads( unsigned int nr );
+        unsigned int setNrOfThreads( unsigned int nr );
+
+        bool passFunction( const ExecutorPtr& executor, bool addThread=false );
+        void synchronise();
+
+    private:
+        std::vector<Thread*> threadPool_;
+
+    };
+}
+
+#endif /* _ThreadPool_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/ThreadWin.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ThreadWin.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ThreadWin.cc	(revision 11817)
@@ -0,0 +1,132 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#include "Thread.h"
+
+#include <cassert>
+// #include <functional>
+// #include <boost/thread/thread.hpp>
+// #include <boost/thread/mutex.hpp>
+// #include <boost/thread/thread_time.hpp>
+
+// #include "util/Sleep.h"
+#include "command/Executor.h"
+
+namespace orxonox
+{
+//     boost::posix_time::millisec THREAD_WAIT_BEFORE_DETACH(1000);
+
+
+    Thread::Thread():
+        executor_(nullptr),
+        isWorking_(false),
+        stopThread_(false)
+    {
+//         this->executorMutex_ = new boost::mutex;
+//         this->isWorkingMutex_ = new boost::mutex;
+//         this->stopThreadMutex_ = new boost::mutex;
+//         this->workerThread_ = new boost::thread( std::bind(&Thread::threadLoop, this) );
+    }
+
+    Thread::~Thread()
+    {
+//         this->stopThreadMutex_->lock();
+//         this->stopThread_ = true;
+//         this->stopThreadMutex_->unlock();
+//         if( !this->workerThread_->timed_join( THREAD_WAIT_BEFORE_DETACH ) )
+//             assert(0); // this should not happen
+//         delete this->workerThread_;
+//         delete this->executorMutex_;
+//         delete this->stopThreadMutex_;
+//         delete this->isWorkingMutex_;
+    }
+
+    bool Thread::isWorking()
+    {
+//       this->isWorkingMutex_->lock();
+//       bool isWorking = this->isWorking_;
+//       this->isWorkingMutex_->unlock();
+//       return isWorking;
+        return false;
+    }
+
+    bool Thread::evaluateExecutor( const ExecutorPtr& executor )
+    {
+//         this->isWorkingMutex_->lock();
+//         this->isWorking_=true;
+//         this->isWorkingMutex_->unlock();
+//         this->executorMutex_->lock();
+//         this->executor_ = executor;
+//         this->executorMutex_->unlock();
+        (*executor)();
+        return true;
+    }
+
+    void Thread::threadLoop()
+    {
+//         bool stopThread = false;
+//         while( !stopThread )
+//         {
+//             this->executorMutex_->lock();
+//             ExecutorPtr executor = this->executor_;
+//             this->executorMutex_->unlock();
+//             if( executor )
+//             {
+//                 (*executor)();
+//                 this->executorMutex_->lock();
+//                 this->executor_ = nullptr;
+//                 this->executorMutex_->unlock();
+//                 this->isWorkingMutex_->lock();
+//                 this->isWorking_=false;
+//                 this->isWorkingMutex_->unlock();
+//             }
+//             else
+//             {
+//                 this->workerThread_->yield();
+//             }
+//             this->stopThreadMutex_->lock();
+//             stopThread = this->stopThread_;
+//             this->stopThreadMutex_->unlock();
+//         }
+    }
+
+    void Thread::waitUntilFinished()
+    {
+//         bool stillWorking = true;
+//         while( stillWorking )
+//         {
+//             this->isWorkingMutex_->lock();
+//             stillWorking = this->isWorking_;
+//             this->isWorkingMutex_->unlock();
+//             if( stillWorking )
+//                 msleep( 1 );
+//         }
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/libraries/core/ToluaInterfaceHook.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ToluaInterfaceHook.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ToluaInterfaceHook.lua	(revision 11817)
@@ -0,0 +1,30 @@
+--
+--             ORXONOX - the hottest 3D action shooter ever to exist
+--                             > www.orxonox.net <
+--
+--        This program 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.
+--
+--       This program 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 this program; if not, write to the Free Software Foundation,
+--     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+--
+--
+--  Author:
+--    Reto Grieder
+--
+
+-- Writes the static initialiser that registers the package open() function
+function post_include_hook(package_name)
+    output('\n')
+    output('#include "core/LuaState.h"\n')
+    output('int tolua_'..package_name..'_open(lua_State* tolua_S);\n')
+    output('static orxonox::ToluaBindingsHelper initialiser(&tolua_'..package_name..'_open, "'..package_name..'");')
+end
Index: /code/branches/RacingBots_FS18/src/libraries/core/UpdateListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/UpdateListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/UpdateListener.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "UpdateListener.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(UpdateListener).inheritsFrom<Listable>();
+
+    UpdateListener::UpdateListener()
+    {
+        RegisterObject(UpdateListener);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/UpdateListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/UpdateListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/UpdateListener.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _UpdateListener_H__
+#define _UpdateListener_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    /**
+     * Inherit from UpdateListener if you need to receive calls before or after the game is ticked. All classes inheriting from UpdateListener
+     * need to be strictly independent of each other and may not rely on a specific order in which all UpdateListeners are called.
+     *
+     * If you do have such a dependency between two UpdateListeners, e.g. A::preUpdate() always needs to be called before B::preUpdate(), then
+     * you need to create a third class C (which inherits from UpdateListener) with the following implementation:
+     * void C::preUpdate()
+     * {
+     *     A::preUpdate();
+     *     B::preUpdate();
+     * }
+     * This is the only way to ensure that A gets called before B. In this example, only C inherits from UpdateListener, while A and B do not.
+     * Instead they receive the update from C.
+     */
+    class _CoreExport UpdateListener : virtual public Listable
+    {
+        public:
+            UpdateListener();
+
+            /// Gets called by Core before the framework is ticked.
+            virtual void preUpdate(const Clock& time) = 0;
+            /// Gets called by Core after the framework was ticked (but before graphics are drawn).
+            virtual void postUpdate(const Clock& time) = 0;
+    };
+}
+
+#endif /* _UpdateListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/ViewportEventListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ViewportEventListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ViewportEventListener.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ViewportEventListener.h"
+#include "CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(ViewportEventListener).inheritsFrom<Listable>();
+
+    ViewportEventListener::ViewportEventListener()
+    {
+        RegisterObject(ViewportEventListener);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/ViewportEventListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/ViewportEventListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/ViewportEventListener.h	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ViewportEventListener_H__
+#define _ViewportEventListener_H__
+
+#include "CorePrereqs.h"
+
+#include "util/OgreForwardRefs.h"
+#include "object/Listable.h"
+
+namespace orxonox
+{
+    class _CoreExport ViewportEventListener : virtual public Listable
+    {
+        public:
+            virtual void cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera) {}
+
+        protected:
+            ViewportEventListener();
+            virtual ~ViewportEventListener() = default;
+    };
+}
+
+#endif /* _ViewportEventListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/WindowEventListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/WindowEventListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/WindowEventListener.cc	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WindowEventListener.h"
+#include "CoreIncludes.h"
+
+namespace orxonox
+{
+    unsigned int WindowEventListener::windowWidth_s  = 0;
+    unsigned int WindowEventListener::windowHeight_s = 0;
+
+    RegisterAbstractClass(WindowEventListener).inheritsFrom<Listable>();
+
+    WindowEventListener::WindowEventListener()
+    {
+        RegisterObject(WindowEventListener);
+    }
+
+    //! Calls all registered objects
+    /*static*/ void WindowEventListener::moveWindow()
+    {
+        for (WindowEventListener* listener : ObjectList<WindowEventListener>())
+            listener->windowMoved();
+    }
+
+    //! Calls all registered objects and sets the static variables
+    /*static*/ void WindowEventListener::resizeWindow(unsigned int newWidth, unsigned int newHeight)
+    {
+        windowWidth_s = newWidth;
+        windowHeight_s = newHeight;
+        for (WindowEventListener* listener : ObjectList<WindowEventListener>())
+            listener->windowResized(newWidth, newHeight);
+    }
+
+    //! Calls all registered objects
+    /*static*/ void WindowEventListener::changeWindowFocus(bool bFocus)
+    {
+        for (WindowEventListener* listener : ObjectList<WindowEventListener>())
+            listener->windowFocusChanged(bFocus);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/WindowEventListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/WindowEventListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/WindowEventListener.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Graphics
+*/
+
+#ifndef _WindowEventListener_H__
+#define _WindowEventListener_H__
+
+#include "CorePrereqs.h"
+#include "object/Listable.h"
+
+namespace orxonox
+{
+    //! Interface for receiving window events like resize, moved and focusChanged
+    class _CoreExport WindowEventListener : virtual public Listable
+    {
+        friend class OgreWindowEventListener;
+
+        protected:
+            WindowEventListener();
+            virtual ~WindowEventListener() = default;
+
+            //! Returns the current render window width
+            unsigned int getWindowWidth() const { return windowWidth_s; }
+            //! Returns the current render window height
+            unsigned int getWindowHeight() const { return windowHeight_s; }
+
+        private:
+            //! Window has been moved
+            virtual void windowMoved() { }
+
+            //! Window has resized
+            virtual void windowResized(unsigned int newWidth, unsigned int newHeight) { }
+
+            //! Window has lost/gained focus
+            virtual void windowFocusChanged(bool bFocus) { }
+
+            static void moveWindow();
+            static void resizeWindow(unsigned int newWidth, unsigned int newHeight);
+            static void changeWindowFocus(bool bFocus);
+
+            //! Static variable that holds the latest distributed information
+            static unsigned int windowWidth_s;
+            static unsigned int windowHeight_s;
+    };
+}
+
+#endif /* _WindowEventListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/XMLFile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/XMLFile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/XMLFile.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup XML XMLPort
+*/
+
+#ifndef _XMLFile_H__
+#define _XMLFile_H__
+
+#include "CorePrereqs.h"
+
+#include <string>
+#include "ClassTreeMask.h"
+
+namespace orxonox
+{
+    class _CoreExport XMLFile
+    {
+        public:
+            XMLFile(const std::string& filename)
+                : filename_(filename)
+                , bLuaSupport_(true)
+            { }
+            XMLFile(const ClassTreeMask& mask, const std::string& filename)
+                : filename_(filename)
+                , mask_(mask)
+                , bLuaSupport_(true)
+            { }
+
+            void setLuaSupport(bool val) { bLuaSupport_ = val; }
+
+            const std::string& getFilename() const { return this->filename_; }
+            const ClassTreeMask& getMask() const { return this->mask_; }
+            bool getLuaSupport() const { return this->bLuaSupport_; }
+
+        private:
+            std::string filename_;
+            ClassTreeMask mask_;
+            bool bLuaSupport_; // Default is true
+    };
+}
+
+#endif /* _XMLFile_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/XMLNameListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/XMLNameListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/XMLNameListener.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "XMLNameListener.h"
+#include "CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(XMLNameListener).inheritsFrom<Listable>();
+
+    XMLNameListener::XMLNameListener()
+    {
+        RegisterObject(XMLNameListener);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/XMLNameListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/XMLNameListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/XMLNameListener.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup XML XMLPort
+*/
+
+#ifndef _XMLNameListener_H__
+#define _XMLNameListener_H__
+
+#include "CorePrereqs.h"
+#include "object/Listable.h"
+
+namespace orxonox
+{
+    class _CoreExport XMLNameListener : virtual public Listable
+    {
+        public:
+            XMLNameListener();
+            virtual ~XMLNameListener() = default;
+
+            virtual void loadedNewXMLName(BaseObject* object) = 0;
+    };
+}
+
+#endif /* _XMLNameListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/XMLPort.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/XMLPort.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/XMLPort.cc	(revision 11817)
@@ -0,0 +1,137 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "XMLPort.h"
+
+#include "CoreIncludes.h"
+#include "Loader.h"
+#include "Namespace.h"
+
+namespace orxonox
+{
+    // ################################
+    // ###  XMLPortObjectContainer  ###
+    // ################################
+    bool XMLPortObjectContainer::identifierIsIncludedInLoaderMask(const Identifier* identifier)
+    {
+        return ((!this->bApplyLoaderMask_) || identifier->isA(ClassIdentifier<Namespace>::getIdentifier()) || Loader::getInstance().currentMask_.isIncluded(identifier));
+    }
+
+    XMLPortObjectContainer& XMLPortObjectContainer::port(BaseObject* object, Element& xmlelement, XMLPort::Mode mode)
+    {
+        if ((mode == XMLPort::LoadObject) || (mode == XMLPort::ExpandObject))
+        {
+            try
+            {
+                Element* xmlsubelement;
+                if (!this->sectionname_.empty())
+                    xmlsubelement = xmlelement.FirstChildElement(this->sectionname_, false);
+                else
+                    xmlsubelement = &xmlelement;
+
+                if (!xmlsubelement)
+                    return (*this);
+
+                for (ticpp::Iterator<ticpp::Element> child = xmlsubelement->FirstChildElement(false); child != child.end(); child++)
+                {
+                    Identifier* identifier = ClassByString(child->Value());
+                    if (!identifier)
+                    {
+                        if (!this->sectionname_.empty())
+                        {
+                            orxout(internal_warning, context::xml) << object->getLoaderIndentation() << "'" << child->Value() << "' is not a valid classname." << endl;
+                        }
+                        else
+                        {
+                            // It's probably just another subsection
+                        }
+                        continue;
+                    }
+                    if (!identifier->isA(objectIdentifier_))
+                    {
+                        orxout(internal_warning, context::xml) << object->getLoaderIndentation() << "'" << child->Value() << "' is not a '" << objectIdentifier_->getName() << "'." << endl;
+                        continue;
+                    }
+                    if (!identifier->isLoadable())
+                    {
+                        orxout(internal_warning, context::xml) << object->getLoaderIndentation() << "'" << child->Value() << "' is not loadable." << endl;
+                        continue;
+                    }
+                    if (!this->identifierIsIncludedInLoaderMask(identifier))
+                        continue;
+
+                    try
+                    {
+                        orxout(verbose, context::xml) << object->getLoaderIndentation() << "fabricating " << child->Value() << "..." << endl;
+
+                        BaseObject* newObject = orxonox_cast<BaseObject*>(identifier->fabricate(object->getContext()));
+                        newObject->setLoaderIndentation(object->getLoaderIndentation() + "  ");
+
+                        if (this->bLoadBefore_)
+                        {
+                            newObject->XMLPort(*child, XMLPort::LoadObject);
+                            orxout(verbose, context::xml) << object->getLoaderIndentation() << "assigning " << child->Value() << " (objectname " << newObject->getName() << ") to " << this->identifier_->getName() << " (objectname " << static_cast<BaseObject*>(object)->getName() << ')' << endl;
+                        }
+                        else
+                        {
+                            orxout(verbose, context::xml) << object->getLoaderIndentation() << "assigning " << child->Value() << " (object not yet loaded) to " << this->identifier_->getName() << " (objectname " << static_cast<BaseObject*>(object)->getName() << ')' << endl;
+                        }
+
+                        this->callLoadExecutor(object, newObject);
+
+                        if (!this->bLoadBefore_)
+                            newObject->XMLPort(*child, XMLPort::LoadObject);
+
+                        orxout(verbose, context::xml) << object->getLoaderIndentation() << "fabricated " << child->Value() << " (objectname " << newObject->getName() << ")." << endl;
+                    }
+                    catch (AbortLoadingException& ex)
+                    {
+                        orxout(internal_error, context::xml) << "An error occurred while loading object, abort loading..." << endl;
+                        throw ex;
+                    }
+                    catch (...)
+                    {
+                        orxout(internal_error, context::xml) << "An error occurred while loading object:" << endl;
+                        orxout(internal_error, context::xml) << Exception::handleMessage() << endl;
+                    }
+                }
+            }
+            catch (ticpp::Exception& ex)
+            {
+                orxout(internal_error, context::xml) << endl;
+                orxout(internal_error, context::xml) << "An error occurred in XMLPort.h while loading a '" << objectIdentifier_->getName() << "' in '" << this->sectionname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << object->getName() << ") in " << object->getFilename() << ':' << endl;
+                orxout(internal_error, context::xml) << ex.what() << endl;
+            }
+        }
+        else if (mode == XMLPort::SaveObject)
+        {
+        }
+
+        return (*this);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/XMLPort.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/XMLPort.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/XMLPort.h	(revision 11817)
@@ -0,0 +1,606 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup XMLPort XMLPort
+    @ingroup XML
+*/
+
+/**
+    @file
+    @ingroup XML XMLPort
+    @brief Declaration of the XMLPort helper classes and macros.
+
+    XMLPort is a virtual function of every BaseObject. Every object can change this function.
+    The XMLPort function gets called with an XMLElement, containing all attributes and
+    subclasses the object gets from the levelfile.
+
+    This file declares classes and macros to simplify XML-parsing.
+*/
+
+#ifndef _XMLPort_H__
+#define _XMLPort_H__
+
+#include "CorePrereqs.h"
+
+#include <cassert>
+#include <string>
+#include <tinyxml/ticpp.h>
+
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/MultiType.h"
+#include "util/OrxAssert.h"
+#include "util/StringUtils.h"
+#include "class/Identifier.h"
+#include "BaseObject.h"
+#include "command/Executor.h"
+
+// ------------
+// XMLPortParam
+
+/**
+    @brief Declares an XML attribute with a name, which will be set through load- and savefunctions.
+    @param classname The name of the class owning this param
+    @param paramname The name of the attribute
+    @param loadfunction A function to set the param in the object with a given value (~a set-function)
+    @param savefunction A function to get the value of the param from the object (~a get-function)
+    @param xmlelement The XMLElement, you get this from the XMLPort function
+    @param mode The mode (load or save), you get this from the XMLPort function
+
+    In the XML file, a param or attribute will be set like this:
+    @code
+    <classname paramname="value" />
+    @endcode
+
+    The macro will then call loadfunction(value) to set the given value (or call savefunction() to
+    write an existing value to an XML file).
+*/
+#define XMLPortParam(classname, paramname, loadfunction, savefunction, xmlelement, mode) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
+    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode)
+
+/**
+    @brief Declares an XML attribute with a name, which will be set through a variable.
+    @param classname The name of the class owning this param
+    @param paramname The name of the attribute
+    @param variable Name of the variable used to save and load the value
+    @param xmlelement The XMLElement, you get this from the XMLPort function
+    @param mode The mode (load or save), you get this from the XMLPort function
+
+    In the XML file, a param or attribute will be set like this:
+    @code
+    <classname paramname="value" />
+    @endcode
+
+    The macro will then store "value" in the variable or read it when saving.
+*/
+#define XMLPortParamVariable(classname, paramname, variable, xmlelement, mode) \
+    XMLPortVariableHelperClass xmlcontainer##variable##dummy(static_cast<void*>(&variable)); \
+    static ExecutorMemberPtr<orxonox::XMLPortVariableHelperClass> xmlcontainer##variable##loadexecutor = orxonox::createExecutor(orxonox::createFunctor(orxonox::XMLPortVariableHelperClass::getLoader(variable)), std::string( #classname ) + "::" + #variable + "loader"); \
+    static ExecutorMemberPtr<orxonox::XMLPortVariableHelperClass> xmlcontainer##variable##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(orxonox::XMLPortVariableHelperClass::getSaver (variable)), std::string( #classname ) + "::" + #variable + "saver" ); \
+    XMLPortParamGeneric(xmlcontainer##variable, classname, orxonox::XMLPortVariableHelperClass, &xmlcontainer##variable##dummy, paramname, xmlcontainer##variable##loadexecutor, xmlcontainer##variable##saveexecutor, xmlelement, mode)
+
+/**
+    @brief This is the same as XMLPortParam, but you can set the template arguments needed to store the loadfunction.
+
+    Sometimes the name of the loadfunction is ambiguous (example: setPosition(Vector3) or
+    setPosition(float, float, float)). In this case, you can choose the right function by
+    telling the types of the functionparams. In our example, this would be either
+    > XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, Vector3);
+    or
+    > XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, float, float, float);
+    You don't have to use this, if there exist only one function with the given name.
+*/
+#define XMLPortParamTemplate(classname, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor<void, classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
+    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, classname, this, paramname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode)
+
+// --------------------
+// XMLPortParamLoadOnly
+
+/**
+    @brief Declares an XML attribute with a name, which can be set through a loadfunction.
+
+    This is the same as XMLPortParam, but you don't need a savefunction (get-function). Therefore,
+    this param won't be saved in an XML file, but you can add the attribute manually an it will be
+    loaded.
+
+    This might be helpful in cases, when you have several options to set a value, for example the
+    rotation. You can set the rotation with a quaternion, but you could also use three angles.
+    When saving the object, only one of both options has to be saved; this is, where this macro helps.
+*/
+#define XMLPortParamLoadOnly(classname, paramname, loadfunction, xmlelement, mode) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##0##loadexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, xmlcontainer##loadfunction##0##loadexecutor, 0, xmlelement, mode)
+/**
+    @brief This is the same as XMLPortParamTemplate, but for load-only attributes (see XMLPortParamLoadOnly).
+*/
+#define XMLPortParamLoadOnlyTemplate(classname, paramname, loadfunction, xmlelement, mode, ...) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##0##loadexecutor = orxonox::createExecutor(orxonox::createFunctor<void, classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    XMLPortParamGeneric(xmlcontainer##loadfunction##0, classname, classname, this, paramname, xmlcontainer##loadfunction##0##loadexecutor, 0, xmlelement, mode)
+
+// ------------------
+// XMLPortParamExtern
+
+/**
+    @brief This is the same as XMLPortParam, but for attributes in an extern class.
+    @param classname The name of the class owning the object owning the attribute
+    @param externclass The name of the extern class (the objects class)
+    @param object The name of the object of the extern class (a member of the main class)
+    @param paramname The name of the attribute
+    @param loadfunction The function to set the attribute inside of the member object.
+    @param savefunction The function to get the attribute from the member object
+    @param xmlelement The XML-element that is parsed by this macro
+    @param mode Loading or saving
+
+    Sometimes you'll have a member object in your class, which has it's own load- and savefunctions.
+    With this macro, you can simply use them instead of writing your own functions.
+
+    Example:
+    Your class is called SpaceShip and this class has an object (myPilot_) of class Pilot. Pilot has a name
+    and two functions, setName(name) and getName(). Now you want an attribute "pilotname" in your
+    SpaceShip class. Instead of writing wrapper functions, you can simply use the XMLPortParamExtern
+    macro:
+    > XMLPortParamExtern(SpaceShip, Pilot, myPilot_, "pilotname", setName, getName, xmlelement, mode);
+*/
+#define XMLPortParamExtern(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode) \
+    static ExecutorMemberPtr<externclass> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<externclass> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction); \
+    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode);
+/**
+    @brief This is the same as XMLPortParamTemplate, but for extern attributes (see XMLPortParamExtern).
+*/
+#define XMLPortParamExternTemplate(classname, externclass, object, paramname, loadfunction, savefunction, xmlelement, mode, ...) \
+    static ExecutorMemberPtr<externclass> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor<void, externclass, __VA_ARGS__ >(&externclass::loadfunction), std::string( #externclass ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<externclass> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&externclass::savefunction), std::string( #externclass ) + "::" + #savefunction); \
+    XMLPortParamGeneric(xmlcontainer##loadfunction##savefunction, classname, externclass, object, paramname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode);
+
+// -------------------
+// XMLPortParamGeneric
+
+/**
+    @brief This is the generic XMLPort param macro, which is used by all six specialized macros above.
+*/
+#define XMLPortParamGeneric(containername, classname, objectclass, object, paramname, loadexecutor, saveexecutor, xmlelement, mode) \
+    orxonox::XMLPortClassParamContainer<objectclass>* containername = static_cast<orxonox::XMLPortClassParamContainer<objectclass>*>(ClassIdentifier<classname>::getIdentifier()->getXMLPortParamContainer(paramname)); \
+    if (!containername) \
+    { \
+        containername = new orxonox::XMLPortClassParamContainer<objectclass>(std::string(paramname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor); \
+        ClassIdentifier<classname>::getIdentifier()->addXMLPortParamContainer(paramname, containername); \
+    } \
+    containername->port(orxonox_cast<BaseObject*>(this), object, xmlelement, mode)
+
+// --------------------
+// XMLPortObjectExtended
+
+/**
+    @brief Declares a possible sub-object that can be added in the XML file.
+    @param classname The name of the class that uses this macro
+    @param objectclass The baseclass of objects that can be added
+    @param sectionname The name of the subsection in the XML file that encloses the sub-objects ("" means no subsection)
+    @param loadfunction The function to add a new object to the class
+    @param savefunction The function to get all added objects from the class
+    @param xmlelement The XMLElement (received through the XMLPort function)
+    @param mode The mode (load/save) (received through the XMLPort function)
+    @param bApplyLoaderMask If this is true, an added sub-object gets loaded only if it's class is included in the Loaders ClassTreeMask (this is usually false)
+    @param bLoadBefore If this is true, the sub-object gets loaded (through XMLPort) BEFORE it gets added to the main class (this is usually true)
+
+    bApplyLoaderMask is usually false for the following reason:
+    If the loaders mask says, for example, "load only SpaceShips" and you added weapons to the
+    SpaceShips, then the Weapons will still be loaded (which is most probably what you want).
+    Of course, if there are "standalone" weapons in the level, they wont be loaded.
+
+    If bLoadBefore is true, an added object already has all attributes set (like it's name). This is most
+    likely the best option, so this is usually true.
+
+    @details
+    The load- and savefunctions have to follow an exactly defined protocol.
+    Loadfunction:
+      The loadfunction gets a pointer to the object.
+      @code
+      void loadfunction(objectclass* pointer);
+      @endcode
+
+    Savefunction:
+      The savefunction gets an index, starting with 0. For every returnvalue != 0, the savefunction
+      gets called again, but with index + 1. It's the functions responsibility to do something smart
+      with the index and to return 0 if all objects were returned.
+      @code
+      objectclass* savefunction(unsigned int index) const;
+      @endcode
+
+      Possible implementation:
+      @code
+        objectclass* savefunction(unsigned int index) const
+        {
+          if (index < number_of_added_objects_)
+            return my_added_objects[index];
+          else
+            return nullptr;
+        }
+      @endcode
+
+    Example:
+    Possible usage of the macro:
+    @code
+    XMLPortObject(SpaceShip, Weapon, "weapons", addWeapon, getWeapon, xmlelement, mode, false, true);
+    @endcode
+
+    Now you can add weapons through the XML file:
+    @code
+    <SpaceShip someattribute="..." ...>
+      <weapons>
+        <Weapon someattribute="..." ... />
+        <Weapon someattribute="..." ... />
+        <Weapon someattribute="..." ... />
+      </weapons>
+    </SpaceShip>
+    @endcode
+
+    Note that "weapons" is the subsection. This allows you to add more types of sub-objects. In our example,
+    you could add pilots, blinking lights or other stuff. If you don't want a subsection, just use "" (an
+    empty string). Then you can add sub-objects directly into the mainclass.
+*/
+#define XMLPortObjectExtended(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
+    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore)
+/**
+    @brief This is the same as XMLPortObjectExtended, but you can specify the loadfunction by adding the param types. See XMLPortParamTemplate for more details about the types.
+*/
+#define XMLPortObjectExtendedTemplate(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, bApplyLoaderMask, bLoadBefore, ...) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor<void, classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
+    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore)
+
+// -------------
+// XMLPortObject
+
+/**
+    @brief This is the same as XMLPortObjectExtended, but bApplyLoaderMask is false and bLoadBefore is true by default.
+*/
+#define XMLPortObject(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
+    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode, false, true)
+/**
+    @brief This is the same as XMLPortObject, but you can specify the loadfunction by adding the param types. See XMLPortParamTemplate for more details about the types.
+*/
+#define XMLPortObjectTemplate(classname, objectclass, sectionname, loadfunction, savefunction, xmlelement, mode, ...) \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##loadexecutor = orxonox::createExecutor(orxonox::createFunctor<void, classname, __VA_ARGS__ >(&classname::loadfunction), std::string( #classname ) + "::" + #loadfunction); \
+    static ExecutorMemberPtr<classname> xmlcontainer##loadfunction##savefunction##saveexecutor = orxonox::createExecutor(orxonox::createFunctor(&classname::savefunction), std::string( #classname ) + "::" + #savefunction); \
+    XMLPortObjectGeneric(xmlcontainer##loadfunction##savefunction, classname, objectclass, sectionname, xmlcontainer##loadfunction##savefunction##loadexecutor, xmlcontainer##loadfunction##savefunction##saveexecutor, xmlelement, mode, false, true)
+
+// --------------------
+// XMLPortObjectGeneric
+
+/**
+    @brief Generic XMLPortObject macro, that gets called by all other XMLPortObject macros above.
+*/
+#define XMLPortObjectGeneric(containername, classname, objectclass, sectionname, loadexecutor, saveexecutor, xmlelement, mode, bApplyLoaderMask, bLoadBefore) \
+    orxonox::XMLPortClassObjectContainer<classname, objectclass>* containername = (orxonox::XMLPortClassObjectContainer<classname, objectclass>*)(ClassIdentifier<classname>::getIdentifier()->getXMLPortObjectContainer(sectionname)); \
+    if (!containername) \
+    { \
+        containername = new orxonox::XMLPortClassObjectContainer<classname, objectclass>(std::string(sectionname), ClassIdentifier<classname>::getIdentifier(), loadexecutor, saveexecutor, bApplyLoaderMask, bLoadBefore); \
+        ClassIdentifier<classname>::getIdentifier()->addXMLPortObjectContainer(sectionname, containername); \
+    } \
+    containername->port(this, xmlelement, mode)
+
+
+namespace orxonox
+{
+    // ###############################
+    // ###  XMLPortParamContainer  ###
+    // ###############################
+    class _CoreExport XMLPortParamContainer
+    {
+    public:
+        enum class ParseResult
+        {
+            not_started,
+            finished,
+            waiting_for_default_values
+        };
+
+        public:
+            XMLPortParamContainer()
+                { this->parseResult_ = ParseResult::not_started; }
+            virtual ~XMLPortParamContainer() = default;
+
+            inline const std::string& getName() const
+                { return this->paramname_; }
+
+            inline XMLPortParamContainer& description(const std::string& description)
+                { this->description_ = description; return *this; }
+            inline const std::string& getDescription() const
+                { return this->description_; }
+
+            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param) = 0;
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1) = 0;
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2) = 0;
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3) = 0;
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) = 0;
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) = 0;
+
+        protected:
+            std::string paramname_;
+            ParseResult parseResult_;
+            Identifier* identifier_;
+            BaseObject* owner_;
+            std::string description_;
+    };
+
+    template <class T>
+    class XMLPortClassParamContainer : public XMLPortParamContainer
+    {
+        struct ParseParams
+        {
+            T* object;
+            Element* xmlelement;
+            XMLPort::Mode mode;
+        };
+
+        public:
+            XMLPortClassParamContainer(const std::string& paramname, Identifier* identifier, const ExecutorMemberPtr<T>& loadexecutor, const ExecutorMemberPtr<T>& saveexecutor)
+            {
+                this->paramname_ = paramname;
+                this->identifier_ = identifier;
+                this->loadexecutor_ = loadexecutor;
+                this->saveexecutor_ = saveexecutor;
+            }
+
+            XMLPortParamContainer& port(BaseObject* owner, T* object, Element& xmlelement, XMLPort::Mode mode)
+            {
+                OrxAssert(owner, "XMLPortParamContainer must have a BaseObject as owner.");
+                this->owner_ = owner;
+                this->parseParams_.object = object;
+                this->parseParams_.xmlelement = &xmlelement;
+                this->parseParams_.mode = mode;
+
+                if ((mode == XMLPort::LoadObject) || (mode == XMLPort::ExpandObject))
+                {
+                    try
+                    {
+                        if (this->owner_->lastLoadedXMLElement_ != &xmlelement)
+                        {
+                            this->owner_->xmlAttributes_.clear();
+                            // Iterate through the attributes manually in order to make them case insensitive
+                            ticpp::Attribute* attribute = xmlelement.FirstAttribute(false);
+                            while (attribute != nullptr)
+                            {
+                                this->owner_->xmlAttributes_[getLowercase(attribute->Name())] = attribute->Value();
+                                attribute = attribute->Next(false);
+                            }
+                            this->owner_->lastLoadedXMLElement_ = &xmlelement;
+                        }
+                        std::map<std::string, std::string>::const_iterator it = this->owner_->xmlAttributes_.find(getLowercase(this->paramname_));
+                        std::string attributeValue;
+                        if (it != this->owner_->xmlAttributes_.end())
+                            attributeValue = it->second;
+
+                        // TODO: Checking the iterator would be better since then we can have strings with value "" as well.
+                        //       Unfortunately this does not seem to work with the Executor parser yet.
+                        if ((!attributeValue.empty()) || ((mode != XMLPort::ExpandObject) && this->loadexecutor_->allDefaultValuesSet()))
+                        {
+                            orxout(verbose_more, context::xml) << this->owner_->getLoaderIndentation() << "Loading parameter " << this->paramname_ << " in " << this->identifier_->getName() << " (objectname " << this->owner_->getName() << ")." << endl;
+                            int error;
+                            this->loadexecutor_->parse(object, attributeValue, &error, ",");
+                            if (!error || (mode  == XMLPort::ExpandObject))
+                                this->parseResult_ = ParseResult::finished;
+                            else
+                                this->parseResult_ = ParseResult::waiting_for_default_values;
+                        }
+                        else if (mode == XMLPort::ExpandObject)
+                            this->parseResult_ = ParseResult::finished;
+                        else
+                            this->parseResult_ = ParseResult::waiting_for_default_values;
+                    }
+                    catch (ticpp::Exception& ex)
+                    {
+                        orxout(internal_error, context::xml) << endl;
+                        orxout(internal_error, context::xml) << "An error occurred in XMLPort.h while loading attribute '" << this->paramname_ << "' of '" << this->identifier_->getName() << "' (objectname: " << this->owner_->getName() << ") in " << this->owner_->getFilename() << ':' << endl;
+                        orxout(internal_error, context::xml) << ex.what() << endl;
+                    }
+                }
+                else if (mode == XMLPort::SaveObject)
+                {
+                    if (this->saveexecutor_)
+                    {
+//                        xmlelement.SetAttribute(this->paramname_, "...");
+                    }
+                }
+
+                return (*this);
+            }
+
+            XMLPortParamContainer& port(BaseObject* owner, const ParseParams& parseParams)
+            {
+                return this->port(owner, parseParams.object, *parseParams.xmlelement, parseParams.mode);
+            }
+
+            XMLPortParamContainer& portIfWaitingForDefaultValues(const ParseResult& result, const ParseParams& params)
+            {
+                if (result == ParseResult::waiting_for_default_values)
+                    return this->port(this->owner_, params);
+                else
+                    return (*this);
+            }
+
+            virtual XMLPortParamContainer& defaultValue(unsigned int index, const MultiType& param) override
+            {
+                if (!this->loadexecutor_->defaultValueSet(index))
+                    this->loadexecutor_->setDefaultValue(index, param);
+                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
+            }
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1) override
+            {
+                if (!this->loadexecutor_->defaultValueSet(0))
+                    this->loadexecutor_->setDefaultValues(param1);
+                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
+            }
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2) override
+            {
+                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)))
+                    this->loadexecutor_->setDefaultValues(param1, param2);
+                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
+            }
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3) override
+            {
+                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)))
+                    this->loadexecutor_->setDefaultValues(param1, param2, param3);
+                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
+            }
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4) override
+            {
+                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)))
+                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4);
+                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
+            }
+            virtual XMLPortParamContainer& defaultValues(const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) override
+            {
+                if ((!this->loadexecutor_->defaultValueSet(0)) || (!this->loadexecutor_->defaultValueSet(1)) || (!this->loadexecutor_->defaultValueSet(2)) || (!this->loadexecutor_->defaultValueSet(3)) || (!this->loadexecutor_->defaultValueSet(4)))
+                    this->loadexecutor_->setDefaultValues(param1, param2, param3, param4, param5);
+                return this->portIfWaitingForDefaultValues(this->parseResult_, this->parseParams_);
+            }
+
+        private:
+            ExecutorMemberPtr<T> loadexecutor_;
+            ExecutorMemberPtr<T> saveexecutor_;
+            ParseParams parseParams_;
+    };
+
+
+    // ################################
+    // ###  XMLPortObjectContainer  ###
+    // ################################
+    class _CoreExport XMLPortObjectContainer
+    {
+        public:
+            XMLPortObjectContainer()
+                { this->bApplyLoaderMask_ = false; }
+            virtual ~XMLPortObjectContainer() = default;
+
+            XMLPortObjectContainer& port(BaseObject* object, Element& xmlelement, XMLPort::Mode mode);
+
+            virtual void callLoadExecutor(BaseObject* object, BaseObject* newObject) = 0;
+
+            inline const std::string& getName() const
+                { return this->sectionname_; }
+
+            inline XMLPortObjectContainer& description(const std::string& description)
+                { this->description_ = description; return *this; }
+            const std::string& getDescription() const
+                { return this->description_; }
+
+            bool identifierIsIncludedInLoaderMask(const Identifier* identifier);
+
+        protected:
+            std::string sectionname_;
+            bool bApplyLoaderMask_;
+            bool bLoadBefore_;
+            Identifier* identifier_;
+            Identifier* objectIdentifier_;
+            std::string description_;
+    };
+
+    template <class T, class O>
+    class XMLPortClassObjectContainer : public XMLPortObjectContainer
+    {
+        public:
+            XMLPortClassObjectContainer(const std::string& sectionname, Identifier* identifier, const ExecutorMemberPtr<T>& loadexecutor, const ExecutorMemberPtr<T>& saveexecutor, bool bApplyLoaderMask, bool bLoadBefore)
+            {
+                this->sectionname_ = sectionname;
+                this->identifier_ = identifier;
+                assert(identifier->isA(ClassIdentifier<T>::getIdentifier()));
+                this->objectIdentifier_ = ClassIdentifier<O>::getIdentifier();
+                this->loadexecutor_ = loadexecutor;
+                this->saveexecutor_ = saveexecutor;
+                this->bApplyLoaderMask_ = bApplyLoaderMask;
+                this->bLoadBefore_ = bLoadBefore;
+            }
+
+            virtual void callLoadExecutor(BaseObject* object, BaseObject* newObject) override
+            {
+                T* castObject = orxonox_cast<T*>(object);
+                assert(castObject);
+                O* castNewObject = orxonox_cast<O*>(newObject);
+                assert(castNewObject);
+
+                (*this->loadexecutor_)(castObject, castNewObject);
+            }
+
+        private:
+            ExecutorMemberPtr<T> loadexecutor_;
+            ExecutorMemberPtr<T> saveexecutor_;
+    };
+
+
+    // ####################################
+    // ###  XMLPortVariableHelperClass  ###
+    // ####################################
+    /**
+    @brief
+        Helper class to load and save simple variables with XMLPort.
+
+        getLoader and getSaver were necessary to get the type T with
+        the help of template function type deduction (const T& is unused).
+        These functions return the adress of save<T> or load<T>.
+    */
+    class XMLPortVariableHelperClass
+    {
+        public:
+            XMLPortVariableHelperClass(void* var)
+                : variable_(var)
+                { }
+            virtual ~XMLPortVariableHelperClass() {}
+
+            template <class T>
+            void load(const T& value)
+                { *static_cast<T*>(this->variable_) = value; }
+
+            template <class T>
+            const T& save()
+                { return *static_cast<T*>(this->variable_); }
+
+            template <class T>
+            static void (XMLPortVariableHelperClass::*getLoader(const T& var))(const T& value)
+                { return &XMLPortVariableHelperClass::load<T>; }
+
+            template <class T>
+            static const T& (XMLPortVariableHelperClass::*getSaver(const T& var))()
+                { return &XMLPortVariableHelperClass::save<T>; }
+
+        private:
+            void* variable_;
+    };
+}
+
+#endif /* _XMLPort_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,7 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  Identifiable.cc
+  Identifier.cc
+  IdentifierManager.cc
+  OrxonoxClass.cc
+  OrxonoxInterface.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/Identifiable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/Identifiable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/Identifiable.cc	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of Identifiable.
+*/
+
+#include "Identifiable.h"
+
+#include <cassert>
+#include "core/CoreIncludes.h"
+#include "core/object/Context.h"
+#include "Identifier.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(Identifiable).virtualBase();
+
+    /**
+        @brief Constructor: Sets the default values.
+    */
+    Identifiable::Identifiable()
+    {
+        this->identifier_ = nullptr;
+        this->objectPointers_.reserve(6); // Optimisation
+
+        RegisterObject(Identifiable);
+    }
+
+    /// Returns true if the object's class is of the given type or a derivative.
+    bool Identifiable::isA(const Identifier* identifier)
+        { return this->getIdentifier()->isA(identifier); }
+    /// Returns true if the object's class is exactly of the given type.
+    bool Identifiable::isExactlyA(const Identifier* identifier)
+        { return this->getIdentifier()->isExactlyA(identifier); }
+    /// Returns true if the object's class is a child of the given type.
+    bool Identifiable::isChildOf(const Identifier* identifier)
+        { return this->getIdentifier()->isChildOf(identifier); }
+    /// Returns true if the object's class is a direct child of the given type.
+    bool Identifiable::isDirectChildOf(const Identifier* identifier)
+        { return this->getIdentifier()->isDirectChildOf(identifier); }
+    /// Returns true if the object's class is a parent of the given type.
+    bool Identifiable::isParentOf(const Identifier* identifier)
+        { return this->getIdentifier()->isParentOf(identifier); }
+    /// Returns true if the object's class is a direct parent of the given type.
+    bool Identifiable::isDirectParentOf(const Identifier* identifier)
+        { return this->getIdentifier()->isDirectParentOf(identifier); }
+
+
+    /// Returns true if the object's class is of the given type or a derivative.
+    bool Identifiable::isA(const Identifiable* object)
+        { return this->getIdentifier()->isA(object->getIdentifier()); }
+    /// Returns true if the object's class is exactly of the given type.
+    bool Identifiable::isExactlyA(const Identifiable* object)
+        { return this->getIdentifier()->isExactlyA(object->getIdentifier()); }
+    /// Returns true if the object's class is a child of the given type.
+    bool Identifiable::isChildOf(const Identifiable* object)
+        { return this->getIdentifier()->isChildOf(object->getIdentifier()); }
+    /// Returns true if the object's class is a direct child of the given type.
+    bool Identifiable::isDirectChildOf(const Identifiable* object)
+        { return this->getIdentifier()->isDirectChildOf(object->getIdentifier()); }
+    /// Returns true if the object's class is a parent of the given type.
+    bool Identifiable::isParentOf(const Identifiable* object)
+        { return this->getIdentifier()->isParentOf(object->getIdentifier()); }
+    /// Returns true if the object's class is a direct child of the given type.
+    bool Identifiable::isDirectParentOf(const Identifiable* object)
+        { return this->getIdentifier()->isDirectParentOf(object->getIdentifier()); }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/Identifiable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/Identifiable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/Identifiable.h	(revision 11817)
@@ -0,0 +1,127 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Class Identifier
+    @brief Declaration of Identifiable, the base of all classes that should own an Identifier.
+
+    It stores the Identifier and has all needed functions to create and use the class-hierarchy.
+*/
+
+#ifndef _Identifiable_H__
+#define _Identifiable_H__
+
+#include "core/CorePrereqs.h"
+
+#include <set>
+#include <vector>
+
+namespace orxonox
+{
+    /**
+        @brief Identifiable is needed to create the class-hierarchy at startup and to store the Identifier.
+    */
+    class _CoreExport Identifiable
+    {
+        template <class T>
+        friend class ClassIdentifier;
+
+        public:
+            Identifiable();
+            virtual ~Identifiable() {}
+
+            /// Returns the Identifier of the object.
+            inline Identifier* getIdentifier() const { return this->identifier_; }
+
+            bool isA(const Identifier* identifier);
+            bool isExactlyA(const Identifier* identifier);
+            bool isChildOf(const Identifier* identifier);
+            bool isDirectChildOf(const Identifier* identifier);
+            bool isParentOf(const Identifier* identifier);
+            bool isDirectParentOf(const Identifier* identifier);
+
+            /// Returns true if the object's class is of the given type or a derivative.
+            template <class B> inline bool isA(const SubclassIdentifier<B>* identifier)
+                { return this->isA(*identifier); }
+            /// Returns true if the object's class is exactly of the given type.
+            template <class B> inline bool isExactlyA(const SubclassIdentifier<B>* identifier)
+                { return this->isExactlyA(*identifier); }
+            /// Returns true if the object's class is a child of the given type.
+            template <class B> inline bool isChildOf(const SubclassIdentifier<B>* identifier)
+                { return this->isChildOf(*identifier); }
+            /// Returns true if the object's class is a direct child of the given type.
+            template <class B> inline bool isDirectChildOf(const SubclassIdentifier<B>* identifier)
+                { return this->isDirectChildOf(*identifier); }
+            /// Returns true if the object's class is a parent of the given type.
+            template <class B> inline bool isParentOf(const SubclassIdentifier<B>* identifier)
+                { return this->isParentOf(*identifier); }
+            /// Returns true if the object's class is a direct parent of the given type.
+            template <class B> inline bool isDirectParentOf(const SubclassIdentifier<B>* identifier)
+                { return this->isDirectParentOf(*identifier); }
+
+            bool isA(const Identifiable* object);
+            bool isExactlyA(const Identifiable* object);
+            bool isChildOf(const Identifiable* object);
+            bool isDirectChildOf(const Identifiable* object);
+            bool isParentOf(const Identifiable* object);
+            bool isDirectParentOf(const Identifiable* object);
+
+            /**
+            @brief
+                Returns a valid pointer of any derived type that is
+                registered in the class hierarchy.
+            @return
+                Returns nullptr if the no pointer was found.
+            */
+            ORX_FORCEINLINE void* getDerivedPointer(unsigned int classID)
+            {
+                for (int i = this->objectPointers_.size() - 1; i >= 0; --i)
+                {
+                    if (this->objectPointers_[i].first == classID)
+                        return this->objectPointers_[i].second;
+                }
+                return nullptr;
+            }
+
+            /// Version of getDerivedPointer with template
+            template <class T> ORX_FORCEINLINE T* getDerivedPointer(unsigned int classID)
+            {   return static_cast<T*>(this->getDerivedPointer(classID));   }
+            /// Const version of getDerivedPointer with template
+            template <class T> ORX_FORCEINLINE const T* getDerivedPointer(unsigned int classID) const
+            {   return const_cast<Identifiable*>(this)->getDerivedPointer<T>(classID);   }
+
+        private:
+            Identifier* identifier_;               //!< The Identifier of the object
+
+            /// 'Fast map' that holds this-pointers of all derived types
+            std::vector<std::pair<unsigned int, void*>> objectPointers_;
+    };
+}
+
+#endif /* _Identifiable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/Identifier.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/Identifier.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/Identifier.cc	(revision 11817)
@@ -0,0 +1,477 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the Identifier class.
+*/
+
+#include "Identifier.h"
+
+#include <ostream>
+
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueContainer.h"
+#include "core/XMLPort.h"
+#include "core/object/ClassFactory.h"
+
+namespace orxonox
+{
+    bool Identifier::initConfigValues_s = true;
+
+    // ###############################
+    // ###       Identifier        ###
+    // ###############################
+    /**
+        @brief Constructor: No factory, no object created, new ObjectList and a unique networkID.
+    */
+    Identifier::Identifier(const std::string& name, Factory* factory, bool bLoadable)
+    {
+        orxout(verbose, context::identifier) << "Create identifier for " << name << endl;
+
+        static unsigned int classIDCounter = 0;
+
+        this->classID_ = classIDCounter++;
+        this->name_ = name;
+        this->factory_ = factory;
+        this->bLoadable_ = bLoadable;
+        this->bInitialized_ = false;
+        this->bIsVirtualBase_ = false;
+
+        this->bHasConfigValues_ = false;
+
+        // Default network ID is the class ID
+        this->networkID_ = this->classID_;
+    }
+
+    /**
+        @brief Destructor: Deletes the list containing the children.
+    */
+    Identifier::~Identifier()
+    {
+        if (this->factory_)
+            delete this->factory_;
+
+        for (const InheritsFrom* manualDirectParent : this->manualDirectParents_)
+            delete manualDirectParent;
+
+        // erase this Identifier from all related identifiers
+        for (const Identifier* parent : this->parents_)
+            const_cast<Identifier*>(parent)->children_.erase(this);
+        for (const Identifier* directParent : this->directParents_)
+            const_cast<Identifier*>(directParent)->directChildren_.erase(this);
+        for (const Identifier* child : this->children_)
+            const_cast<Identifier*>(child)->parents_.remove(this);
+        for (const Identifier* directChild : this->directChildren_)
+            const_cast<Identifier*>(directChild)->directParents_.remove(this);
+
+        for (const auto& mapEntry : this->configValues_)
+            delete (mapEntry.second);
+        for (const auto& mapEntry : this->xmlportParamContainers_)
+            delete (mapEntry.second);
+        for (const auto& mapEntry : this->xmlportObjectContainers_)
+            delete (mapEntry.second);
+    }
+
+
+    /**
+        @brief Creates an object of the type the Identifier belongs to.
+        @return The new object
+    */
+    Identifiable* Identifier::fabricate(Context* context)
+    {
+        if (this->factory_)
+        {
+            return this->factory_->fabricate(context);
+        }
+        else
+        {
+            orxout(user_error) << "An error occurred in Identifier.cc:" << endl;
+            orxout(user_error) << "Cannot fabricate an object of type '" << this->name_ << "'. Class has no factory." << endl;
+            orxout(user_error) << "Aborting..." << endl;
+            abort();
+            return nullptr;
+        }
+    }
+
+    /**
+        @brief Sets the network ID to a new value and changes the entry in the ID-Identifier-map.
+    */
+    void Identifier::setNetworkID(uint32_t id)
+    {
+        this->networkID_ = id;
+        IdentifierManager::getInstance().addIdentifier(this);    // add with new id
+    }
+
+    /**
+     * @brief Used to define the direct parents of an Identifier of an abstract class.
+     */
+    Identifier& Identifier::inheritsFrom(InheritsFrom* directParent)
+    {
+        if (this->directParents_.empty())
+            this->manualDirectParents_.push_back(directParent);
+        else
+            orxout(internal_error) << "Trying to manually add direct parent of " << this->getName() << " after the latter was already initialized" << endl;
+
+        return *this;
+    }
+
+    /**
+     * @brief Initializes the parents of this Identifier while creating the class hierarchy.
+     * @param initializationTrace All identifiers that were recorded while creating an instance of this class (including nested classes and this identifier itself)
+     */
+    void Identifier::initializeParents(const std::list<const Identifier*>& initializationTrace)
+    {
+        if (!IdentifierManager::getInstance().isCreatingHierarchy())
+        {
+            orxout(internal_warning) << "Identifier::initializeParents() created outside of class hierarchy creation" << endl;
+            return;
+        }
+
+        if (this->directParents_.empty())
+        {
+            for (const Identifier* identifier : initializationTrace)
+                if (identifier != this)
+                    this->parents_.push_back(identifier);
+        }
+        else
+            orxout(internal_error) << "Trying to add parents to " << this->getName() << " after it was already initialized with manual calls to inheritsFrom<Class>()." << endl;
+    }
+
+    /**
+     * @brief Finishes the initialization of this Identifier after creating the class hierarchy by wiring the (direct) parent/child references correctly.
+     */
+    void Identifier::finishInitialization()
+    {
+        if (!IdentifierManager::getInstance().isCreatingHierarchy())
+        {
+            orxout(internal_warning) << "Identifier::finishInitialization() created outside of class hierarchy creation" << endl;
+            return;
+        }
+
+        if (this->isInitialized())
+            return;
+
+        if (!this->parents_.empty())
+        {
+            // parents defined -> this class was initialized by creating a sample instance and recording the trace of identifiers
+
+            // initialize all parents
+            for (const Identifier* parent : this->parents_)
+                const_cast<Identifier*>(parent)->finishInitialization(); // initialize parent
+
+            // parents of parents are no direct parents of this identifier
+            this->directParents_ = this->parents_;
+            for (const Identifier* parent : this->parents_)
+                for (const Identifier* parent_parent : const_cast<Identifier*>(parent)->parents_)
+                    this->directParents_.remove(parent_parent);
+
+            this->verifyIdentifierTrace();
+        }
+        else if (!this->manualDirectParents_.empty())
+        {
+            // no parents defined -> this class was manually initialized by calling inheritsFrom<Class>()
+
+            // initialize all direct parents
+            for (const InheritsFrom* manualDirectParent : this->manualDirectParents_)
+            {
+                Identifier* directParent = manualDirectParent->getParent();
+                this->directParents_.push_back(directParent);
+                directParent->finishInitialization(); // initialize parent
+            }
+
+            // direct parents and their parents are also parents of this identifier (but only add them once)
+            for (const Identifier* parent : this->directParents_)
+            {
+                for (const Identifier* parent_parent : const_cast<Identifier*>(parent)->parents_)
+                    this->addIfNotExists(this->parents_, parent_parent);
+                this->addIfNotExists(this->parents_, parent);
+            }
+        }
+        else if (!this->isExactlyA(Class(Identifiable)))
+        {
+            // only Identifiable is allowed to have no parents (even tough it's currently not abstract)
+            orxout(internal_error) << "Identifier " << this->getName() << " / " << this->getTypeInfo().name() << " is marked as abstract but has no direct parents defined" << endl;
+            orxout(internal_error) << "  If this class is not abstract, use RegisterClass(ThisClass);" << endl;
+            orxout(internal_error) << "  If this class is abstract, use RegisterAbstractClass(ThisClass).inheritsFrom(Class(BaseClass));" << endl;
+        }
+
+        // tell all parents that this identifier is a child
+        for (const Identifier* parent : this->parents_)
+            const_cast<Identifier*>(parent)->children_.insert(this);
+
+        // tell all direct parents that this identifier is a direct child
+        for (const Identifier* directChild : this->directParents_)
+        {
+            const_cast<Identifier*>(directChild)->directChildren_.insert(this);
+
+            // Create the super-function dependencies
+            directChild->createSuperFunctionCaller();
+        }
+
+        this->bInitialized_ = true;
+    }
+
+    /**
+     * Resets all information about the class hierarchy. The identifier is considered uninitialized afterwards.
+     */
+    void Identifier::reset()
+    {
+        this->directParents_.clear();
+        this->parents_.clear();
+        this->directChildren_.clear();
+        this->children_.clear();
+        this->bInitialized_ = false;
+    }
+
+    /**
+     * Verifies if the recorded trace of parent identifiers matches the expected trace according to the class hierarchy. If it doesn't match, the class
+     * hierarchy is likely wrong, e.g. due to wrong inheritsFrom<>() definitions in abstract classes.
+     */
+    void Identifier::verifyIdentifierTrace() const
+    {
+
+        std::list<const Identifier*> expectedIdentifierTrace;
+
+        // if any parent class is virtual, it will be instantiated first, so we need to add them first.
+        for (const Identifier* parent : this->parents_)
+        {
+            if (parent->isVirtualBase())
+            {
+                for (const Identifier* parent_parent : const_cast<Identifier*>(parent)->parents_)
+                    this->addIfNotExists(expectedIdentifierTrace, parent_parent);
+                this->addIfNotExists(expectedIdentifierTrace, parent);
+            }
+        }
+
+        // now all direct parents get created recursively. already added identifiers (e.g. virtual base classes) are not added again.
+        for (const Identifier* directParent : this->directParents_)
+        {
+            for (const Identifier* parent_parent : const_cast<Identifier*>(directParent)->parents_)
+                this->addIfNotExists(expectedIdentifierTrace, parent_parent);
+            this->addIfNotExists(expectedIdentifierTrace, directParent);
+        }
+
+        // check if the expected trace matches the actual trace (which was defined by creating a sample instance)
+        if (expectedIdentifierTrace != this->parents_)
+        {
+            orxout(internal_warning) << this->getName() << " has an unexpected initialization trace:" << endl;
+
+            orxout(internal_warning) << "  Actual trace (after creating a sample instance):" << endl << "    ";
+            for (const Identifier* parent : this->parents_)
+                orxout(internal_warning) << " " << parent->getName();
+            orxout(internal_warning) << endl;
+
+            orxout(internal_warning) << "  Expected trace (according to class hierarchy definitions):" << endl << "    ";
+            for (const Identifier* parent : expectedIdentifierTrace)
+                orxout(internal_warning) << " " << parent->getName();
+            orxout(internal_warning) << endl;
+
+            orxout(internal_warning) << "  Direct parents (according to class hierarchy definitions):" << endl << "    ";
+            for (const Identifier* directParent : this->directParents_)
+                orxout(internal_warning) << " " << directParent->getName();
+            orxout(internal_warning) << endl;
+        }
+    }
+
+    /**
+     * Adds @param identifierToAdd to @param list if this identifier is not already contained in the list.
+     */
+    void Identifier::addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const
+    {
+        if (std::find(list.begin(), list.end(), identifierToAdd) == list.end())
+            list.push_back(identifierToAdd);
+    }
+
+    /**
+        @brief Returns true, if the Identifier is at least of the given type.
+        @param identifier The identifier to compare with
+    */
+    bool Identifier::isA(const Identifier* identifier) const
+    {
+        return (identifier == this || (this->isChildOf(identifier)));
+    }
+
+    /**
+        @brief Returns true, if the Identifier is exactly of the given type.
+        @param identifier The identifier to compare with
+    */
+    bool Identifier::isExactlyA(const Identifier* identifier) const
+    {
+        return (identifier == this);
+    }
+
+    /**
+        @brief Returns true, if the assigned identifier is a child of the given identifier.
+        @param identifier The identifier to compare with
+    */
+    bool Identifier::isChildOf(const Identifier* identifier) const
+    {
+        return (std::find(this->parents_.begin(), this->parents_.end(),  identifier) != this->parents_.end());
+    }
+
+    /**
+        @brief Returns true, if the assigned identifier is a direct child of the given identifier.
+        @param identifier The identifier to compare with
+    */
+    bool Identifier::isDirectChildOf(const Identifier* identifier) const
+    {
+        return (std::find(this->directParents_.begin(), this->directParents_.end(), identifier) != this->directParents_.end());
+    }
+
+    /**
+        @brief Returns true, if the assigned identifier is a parent of the given identifier.
+        @param identifier The identifier to compare with
+    */
+    bool Identifier::isParentOf(const Identifier* identifier) const
+    {
+        return (this->children_.find(identifier) != this->children_.end());
+    }
+
+    /**
+        @brief Returns true, if the assigned identifier is a direct parent of the given identifier.
+        @param identifier The identifier to compare with
+    */
+    bool Identifier::isDirectParentOf(const Identifier* identifier) const
+    {
+        return (this->directChildren_.find(identifier) != this->directChildren_.end());
+    }
+
+    /**
+        @brief Adds the ConfigValueContainer of a variable, given by the string of its name.
+        @param varname The name of the variablee
+        @param container The container
+    */
+    void Identifier::addConfigValueContainer(const std::string& varname, ConfigValueContainer* container)
+    {
+        std::map<std::string, ConfigValueContainer*>::const_iterator it = this->configValues_.find(varname);
+        if (it != this->configValues_.end())
+        {
+            orxout(internal_warning) << "Overwriting config-value with name " << varname << " in class " << this->getName() << '.' << endl;
+            delete (it->second);
+        }
+
+        this->bHasConfigValues_ = true;
+        this->configValues_[varname] = container;
+    }
+
+    /**
+        @brief Returns the ConfigValueContainer of a variable, given by the string of its name.
+        @param varname The name of the variable
+        @return The ConfigValueContainer
+    */
+    ConfigValueContainer* Identifier::getConfigValueContainer(const std::string& varname)
+    {
+        std::map<std::string, ConfigValueContainer*>::const_iterator it = configValues_.find(varname);
+        if (it != configValues_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Returns a XMLPortParamContainer that loads a parameter of this class.
+        @param paramname The name of the parameter
+        @return The container
+    */
+    XMLPortParamContainer* Identifier::getXMLPortParamContainer(const std::string& paramname)
+    {
+        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
+        if (it != this->xmlportParamContainers_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Adds a new XMLPortParamContainer that loads a parameter of this class.
+        @param paramname The name of the parameter
+        @param container The container
+    */
+    void Identifier::addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container)
+    {
+        std::map<std::string, XMLPortParamContainer*>::const_iterator it = this->xmlportParamContainers_.find(paramname);
+        if (it != this->xmlportParamContainers_.end())
+        {
+            orxout(internal_warning) << "Overwriting XMLPortParamContainer in class " << this->getName() << '.' << endl;
+            delete (it->second);
+        }
+
+        this->xmlportParamContainers_[paramname] = container;
+    }
+
+    /**
+        @brief Returns a XMLPortObjectContainer that attaches an object to this class.
+        @param sectionname The name of the section that contains the attachable objects
+        @return The container
+    */
+    XMLPortObjectContainer* Identifier::getXMLPortObjectContainer(const std::string& sectionname)
+    {
+        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
+        if (it != this->xmlportObjectContainers_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Adds a new XMLPortObjectContainer that attaches an object to this class.
+        @param sectionname The name of the section that contains the attachable objects
+        @param container The container
+    */
+    void Identifier::addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container)
+    {
+        std::map<std::string, XMLPortObjectContainer*>::const_iterator it = this->xmlportObjectContainers_.find(sectionname);
+        if (it != this->xmlportObjectContainers_.end())
+        {
+            orxout(internal_warning) << "Overwriting XMLPortObjectContainer in class " << this->getName() << '.' << endl;
+            delete (it->second);
+        }
+
+        this->xmlportObjectContainers_[sectionname] = container;
+    }
+
+    /**
+        @brief Lists the names of all Identifiers in a std::set<const Identifier*>.
+        @param out The outstream
+        @param list The list (or set) of Identifiers
+        @return The outstream
+    */
+    std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list)
+    {
+        for (std::set<const Identifier*>::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                out << ' ';
+            out << (*it)->getName();
+        }
+
+        return out;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/Identifier.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/Identifier.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/Identifier.h	(revision 11817)
@@ -0,0 +1,499 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Identifier Identifier
+    @ingroup Class
+*/
+
+/**
+    @file
+    @ingroup Class Identifier
+    @brief Declaration of Identifier, definition of ClassIdentifier<T>; used to identify the class of an object.
+
+    @anchor IdentifierExample
+
+    An Identifier "identifies" the class of an object. It contains different information about
+    the class: Its name and ID, a list of all instances of this class, a factory to create new
+    instances of this class, and more.
+
+    It also contains information about the inheritance of this class: It stores a list of the
+    Identifiers of all parent-classes as well as a list of all child-classes. These relationships
+    can be tested using functions like @c isA(), @c isChildOf(), @c isParentOf(), and more.
+
+    Every Identifier is in fact a ClassIdentifier<T> (where T is the class that is identified
+    by the Identifier), Identifier is just the common base-class.
+
+    Example:
+    @code
+    MyClass* object = new MyClass();                                            // create an instance of MyClass
+
+    object->getIdentifier()->getName();                                         // returns "MyClass"
+
+    Identifiable* other = object->getIdentifier()->fabricate(nullptr);                // fabricates a new instance of MyClass
+
+
+    // test the class hierarchy
+    object->getIdentifier()->isA(Class(MyClass));                               // returns true
+    object->isA(Class(MyClass));                                                // returns true (short version)
+
+    object->isA(Class(BaseClass));                                              // returns true if MyClass is a child of BaseClass
+
+    Class(ChildClass)->isChildOf(object->getIdentifier());                      // returns true if ChildClass is a child of MyClass
+    @endcode
+*/
+
+#ifndef _Identifier_H__
+#define _Identifier_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+#include <map>
+#include <set>
+#include <string>
+#include <typeinfo>
+#include <loki/TypeTraits.h>
+
+#include "util/Output.h"
+#include "util/OrxAssert.h"
+#include "core/object/ObjectList.h"
+#include "core/object/Listable.h"
+#include "core/object/Context.h"
+#include "core/object/Destroyable.h"
+#include "core/object/WeakPtr.h"
+#include "IdentifierManager.h"
+#include "Super.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###       Identifier        ###
+    // ###############################
+    /**
+        @brief The Identifier is used to identify the class of an object and to store information about the class.
+
+        Each Identifier stores information about one class. The Identifier can then be used to identify
+        this class. On the other hand it's also possible to get the corresponding Identifier of a class,
+        for example by using the macro Class().
+
+        @see See @ref IdentifierExample "Identifier.h" for more information and some examples.
+
+        @note You can't directly create an Identifier, it's just the base-class of ClassIdentifier<T>.
+    */
+    class _CoreExport Identifier : public Destroyable
+    {
+        public:
+            struct InheritsFrom //! helper class to manually define inheritance
+            {
+                virtual ~InheritsFrom() {}
+                virtual Identifier* getParent() const = 0;
+            };
+
+        public:
+            Identifier(const std::string& name, Factory* factory, bool bLoadable);
+            virtual ~Identifier();
+
+            // non-copyable:
+            Identifier(const Identifier&) = delete;
+            Identifier& operator=(const Identifier&) = delete;
+
+            /// Returns the name of the class the Identifier belongs to.
+            inline const std::string& getName() const { return this->name_; }
+
+            /// Returns the type_info of the class as it is returned by typeid(T)
+            virtual const std::type_info& getTypeInfo() = 0;
+
+            /// Returns the network ID to identify a class through the network.
+            inline uint32_t getNetworkID() const { return this->networkID_; }
+            void setNetworkID(uint32_t id);
+
+            /// Returns the unique ID of the class.
+            ORX_FORCEINLINE unsigned int getClassID() const { return this->classID_; }
+
+            /// Returns true if the Identifier has a Factory.
+            inline bool hasFactory() const { return (this->factory_ != nullptr); }
+
+            Identifiable* fabricate(Context* context);
+
+            /// Returns true if the class can be loaded through XML.
+            inline bool isLoadable() const { return this->bLoadable_; }
+
+            /// Returns true if child classes should inherit virtually from this class.
+            inline bool isVirtualBase() const { return this->bIsVirtualBase_; }
+            /// Defines if child classes should inherit virtually from this class.
+            inline void setVirtualBase(bool bIsVirtualBase) { this->bIsVirtualBase_ = bIsVirtualBase; }
+
+            /// Returns true if the Identifier was completely initialized.
+            inline bool isInitialized() const { return this->bInitialized_; }
+
+            virtual void destroyObjects() = 0;
+
+            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const = 0;
+
+            static bool initConfigValues_s; // TODO: this is a hack - remove it as soon as possible
+
+
+            /////////////////////////////
+            ////// Class Hierarchy //////
+            /////////////////////////////
+            Identifier& inheritsFrom(InheritsFrom* directParent);
+
+            void initializeParents(const std::list<const Identifier*>& initializationTrace);
+            void finishInitialization();
+            void reset();
+
+            bool isA(const Identifier* identifier) const;
+            bool isExactlyA(const Identifier* identifier) const;
+            bool isChildOf(const Identifier* identifier) const;
+            bool isDirectChildOf(const Identifier* identifier) const;
+            bool isParentOf(const Identifier* identifier) const;
+            bool isDirectParentOf(const Identifier* identifier) const;
+
+            /// Returns the direct parents of the class the Identifier belongs to.
+            inline const std::list<const Identifier*>& getDirectParents() const { return this->directParents_; }
+            /// Returns the parents of the class the Identifier belongs to.
+            inline const std::list<const Identifier*>& getParents() const { return this->parents_; }
+
+            /// Returns the direct children the class the Identifier belongs to.
+            inline const std::set<const Identifier*>& getDirectChildren() const { return this->directChildren_; }
+            /// Returns the children of the class the Identifier belongs to.
+            inline const std::set<const Identifier*>& getChildren() const { return this->children_; }
+
+
+            /////////////////////////
+            ///// Config Values /////
+            /////////////////////////
+            virtual void updateConfigValues(bool updateChildren = true) const = 0;
+
+            /// Returns true if this class has at least one config value.
+            inline bool hasConfigValues() const { return this->bHasConfigValues_; }
+
+            void addConfigValueContainer(const std::string& varname, ConfigValueContainer* container);
+            ConfigValueContainer* getConfigValueContainer(const std::string& varname);
+
+
+            ///////////////////
+            ///// XMLPort /////
+            ///////////////////
+            /// Returns the map that stores all XMLPort params.
+            inline const std::map<std::string, XMLPortParamContainer*>& getXMLPortParamMap() const { return this->xmlportParamContainers_; }
+
+            /// Returns the map that stores all XMLPort objects.
+            inline const std::map<std::string, XMLPortObjectContainer*>& getXMLPortObjectMap() const { return this->xmlportObjectContainers_; }
+
+            void addXMLPortParamContainer(const std::string& paramname, XMLPortParamContainer* container);
+            XMLPortParamContainer* getXMLPortParamContainer(const std::string& paramname);
+
+            void addXMLPortObjectContainer(const std::string& sectionname, XMLPortObjectContainer* container);
+            XMLPortObjectContainer* getXMLPortObjectContainer(const std::string& sectionname);
+
+        protected:
+            virtual void createSuperFunctionCaller() const = 0;
+
+        private:
+            void verifyIdentifierTrace() const;
+            void addIfNotExists(std::list<const Identifier*>& list, const Identifier* identifierToAdd) const;
+
+            std::list<const InheritsFrom*> manualDirectParents_;            //!< Manually defined direct parents
+            std::list<const Identifier*> directParents_;                    //!< The direct parents of the class the Identifier belongs to (sorted by their order of initialization)
+            std::list<const Identifier*> parents_;                          //!< The parents of the class the Identifier belongs to (sorted by their order of initialization)
+
+            std::set<const Identifier*> directChildren_;                   //!< The direct children of the class the Identifier belongs to
+            std::set<const Identifier*> children_;                         //!< The children of the class the Identifier belongs to
+
+            bool bInitialized_;                                            //!< Is true if the Identifier was completely initialized
+            bool bLoadable_;                                               //!< False = it's not permitted to load the object through XML
+            bool bIsVirtualBase_;                                          //!< If true, it is recommended to inherit virtually from this class. This changes the order of initialization of child classes, thus this information is necessary to check the class hierarchy.
+            std::string name_;                                             //!< The name of the class the Identifier belongs to
+            Factory* factory_;                                             //!< The Factory, able to create new objects of the given class (if available)
+            uint32_t networkID_;                                           //!< The network ID to identify a class through the network
+            unsigned int classID_;                                         //!< Uniquely identifies a class (might not be the same as the networkID_)
+
+            bool bHasConfigValues_;                                        //!< True if this class has at least one assigned config value
+            std::map<std::string, ConfigValueContainer*> configValues_;    //!< A map to link the string of configurable variables with their ConfigValueContainer
+
+            std::map<std::string, XMLPortParamContainer*> xmlportParamContainers_;     //!< All loadable parameters
+            std::map<std::string, XMLPortObjectContainer*> xmlportObjectContainers_;   //!< All attachable objects
+    };
+
+    _CoreExport std::ostream& operator<<(std::ostream& out, const std::set<const Identifier*>& list);
+
+
+    // ###############################
+    // ###     ClassIdentifier     ###
+    // ###############################
+    /**
+        @brief The ClassIdentifier is derived from Identifier and holds all class-specific functions and variables the Identifier cannot have.
+
+        ClassIdentifier is a Singleton, which means that only one ClassIdentifier for a given type T exists.
+        This makes it possible to store information about a class, sharing them with all
+        objects of that class without defining static variables in every class.
+
+        To be really sure that not more than exactly one object exists (even with libraries),
+        ClassIdentifiers are stored in a static map in Identifier.
+    */
+    template <class T>
+    class ClassIdentifier : public Identifier
+    {
+        static_assert(std::is_base_of<Identifiable, T>::value, "ClassIdentifier can only be used with Identifiables");
+
+        #ifndef DOXYGEN_SHOULD_SKIP_THIS
+          #define SUPER_INTRUSIVE_DECLARATION_INCLUDE
+          #include "Super.h"
+        #endif
+
+        public:
+            ClassIdentifier(const std::string& name, Factory* factory, bool bLoadable) : Identifier(name, factory, bLoadable)
+            {
+                OrxVerify(ClassIdentifier<T>::classIdentifier_s == nullptr, "Assertion failed in ClassIdentifier of type " << typeid(T).name());
+                ClassIdentifier<T>::classIdentifier_s = this;
+
+                SuperFunctionInitialization<0, T>::initialize(this);
+            }
+            ~ClassIdentifier()
+            {
+                SuperFunctionDestruction<0, T>::destroy(this);
+            }
+
+            bool initializeObject(T* object);
+
+            virtual void updateConfigValues(bool updateChildren = true) const override;
+
+            virtual const std::type_info& getTypeInfo() override
+                { return typeid(T); }
+
+            virtual bool canDynamicCastObjectToIdentifierClass(Identifiable* object) const override
+                { return dynamic_cast<T*>(object) != nullptr; }
+
+            virtual void destroyObjects() override;
+
+            static ClassIdentifier<T>* getIdentifier();
+
+        private:
+            // non-copyable:
+            ClassIdentifier(const ClassIdentifier<T>&) = delete;
+            ClassIdentifier& operator=(const ClassIdentifier<T>&) = delete;
+
+            void setConfigValues(T* object, Configurable*) const;
+            void setConfigValues(T* object, Identifiable*) const;
+
+            void addObjectToList(T* object, Listable*);
+            void addObjectToList(T* object, Identifiable*);
+
+            void destroyObjects(Listable*);
+            void destroyObjects(void*);
+
+            void destroyObject(Destroyable* object);
+            void destroyObject(void* object);
+
+            void updateConfigValues(bool updateChildren, Listable*) const;
+            void updateConfigValues(bool updateChildren, Identifiable*) const;
+
+            static WeakPtr<ClassIdentifier<T>> classIdentifier_s;
+    };
+
+    template <class T>
+    WeakPtr<ClassIdentifier<T>> ClassIdentifier<T>::classIdentifier_s;
+
+    /**
+        @brief Returns the only instance of this class.
+        @return The unique Identifier
+    */
+    template <class T>
+    /*static*/ inline ClassIdentifier<T>* ClassIdentifier<T>::getIdentifier()
+    {
+        if (ClassIdentifier<T>::classIdentifier_s == nullptr)
+            ClassIdentifier<T>::classIdentifier_s = (ClassIdentifier<T>*) IdentifierManager::getInstance().getIdentifierByTypeInfo(typeid(T));
+
+        OrxVerify(ClassIdentifier<T>::classIdentifier_s != nullptr, "Did you forget to register the class of type " << typeid(T).name() << "?");
+        return ClassIdentifier<T>::classIdentifier_s;
+    }
+
+    /**
+        @brief Adds an object of the given type to the ObjectList.
+        @param object The object to add
+    */
+    template <class T>
+    bool ClassIdentifier<T>::initializeObject(T* object)
+    {
+        orxout(verbose, context::object_list) << "Register Object: " << this->getName() << endl;
+
+        object->identifier_ = this;
+        if (IdentifierManager::getInstance().isCreatingHierarchy())
+        {
+            IdentifierManager::getInstance().createdObject(object);
+
+            if (Identifier::initConfigValues_s)
+                this->setConfigValues(object, object);
+
+            return true;
+        }
+        else
+        {
+            this->addObjectToList(object, object);
+
+            // Add pointer of type T to the map in the Identifiable instance that enables "dynamic_casts"
+            object->objectPointers_.emplace_back(this->getClassID(), static_cast<void*>(object));
+            return false;
+        }
+    }
+
+    /**
+     * @brief Only configures the object if is a @ref Configurable
+     */
+    template <class T>
+    void ClassIdentifier<T>::setConfigValues(T* object, Configurable*) const
+    {
+        object->setConfigValues();
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::setConfigValues(T*, Identifiable*) const
+    {
+        // no action
+    }
+
+    /**
+     * @brief Only adds the object to the object list if is a @ref Listable
+     */
+    template <class T>
+    void ClassIdentifier<T>::addObjectToList(T* object, Listable* listable)
+    {
+        if (listable->getContext())
+            listable->getContext()->addObject(object);
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::addObjectToList(T*, Identifiable*)
+    {
+        // no action
+    }
+
+    /**
+     * @brief Destroy all objects of this class (must be Listable).
+     * Destroyables are destroyed with destroy(), all other classes with delete.
+     */
+    template <class T>
+    void ClassIdentifier<T>::destroyObjects()
+    {
+        this->destroyObjects((T*)nullptr);
+    }
+
+    /**
+     * @brief Only searches and destroys objects if is a @ref Listable
+     */
+    template <class T>
+    void ClassIdentifier<T>::destroyObjects(Listable*)
+    {
+        ObjectList<T> list(Context::getRootContext()->getObjectList(this));
+        for (typename ObjectList<T>::iterator it = list.begin(); it != list.end(); )
+            this->destroyObject(*(it++));
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::destroyObjects(void*)
+    {
+        // no action
+    }
+
+    /**
+     * @brief Call 'object->destroy()' for Destroyables and 'delete object' for all other types.
+     */
+    template <class T>
+    void ClassIdentifier<T>::destroyObject(Destroyable* object)
+    {
+        object->destroy();
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::destroyObject(void* object)
+    {
+        delete static_cast<Identifiable*>(object);
+    }
+
+    /**
+        @brief Updates the config-values of all existing objects of this class by calling their setConfigValues() function.
+    */
+    template <class T>
+    void ClassIdentifier<T>::updateConfigValues(bool updateChildren) const
+    {
+        this->updateConfigValues(updateChildren, static_cast<T*>(nullptr));
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::updateConfigValues(bool updateChildren, Listable*) const
+    {
+        if (!this->hasConfigValues())
+            return;
+
+        for (T* object : ObjectList<T>())
+            this->setConfigValues(object, object);
+
+        if (updateChildren)
+            for (const Identifier* child : this->getChildren())
+                child->updateConfigValues(false);
+    }
+
+    template <class T>
+    void ClassIdentifier<T>::updateConfigValues(bool updateChildren, Identifiable*) const
+    {
+        // no action
+    }
+
+
+    // ###############################
+    // ###      orxonox_cast       ###
+    // ###############################
+    /**
+    @brief
+        Casts on object of type Identifiable to any derived type that is
+        registered in the class hierarchy.
+    @return
+        Returns nullptr if the cast is not possible
+    @note
+        In case of nullptr return (and using MSVC), a dynamic_cast might still be possible if
+        a class forgot to register its objects.
+        Also note that the function is implemented differently for GCC/MSVC.
+    */
+    template <class T, class U>
+    ORX_FORCEINLINE T orxonox_cast(U* source)
+    {
+#ifdef ORXONOX_COMPILER_MSVC
+        typedef Loki::TypeTraits<typename Loki::TypeTraits<T>::PointeeType>::NonConstType ClassType;
+        if (source != nullptr)
+            return source->template getDerivedPointer<ClassType>(ClassIdentifier<ClassType>::getIdentifier()->getClassID());
+        else
+            return nullptr;
+#else
+        return dynamic_cast<T>(source);
+#endif
+    }
+}
+
+#endif /* _Identifier_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/IdentifierManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/IdentifierManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/IdentifierManager.cc	(revision 11817)
@@ -0,0 +1,276 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the Identifier class.
+*/
+
+#include "IdentifierManager.h"
+
+#include <ostream>
+
+#include "util/StringUtils.h"
+#include "core/Core.h"
+#include "core/config/ConfigValueContainer.h"
+#include "core/XMLPort.h"
+#include "core/object/ClassFactory.h"
+
+namespace orxonox
+{
+    IdentifierManager* IdentifierManager::singletonPtr_s = nullptr;
+
+    IdentifierManager::IdentifierManager()
+    {
+        this->hierarchyCreatingCounter_s = 0;
+        this->recordTraceForIdentifier_ = nullptr;
+    }
+
+    /**
+     * Registers the identifier in all maps of the IdentifierManager.
+     */
+    void IdentifierManager::addIdentifier(Identifier* identifier)
+    {
+        orxout(verbose, context::identifier) << "Adding identifier for " << identifier->getName() << " / " << identifier->getTypeInfo().name() << endl;
+
+        this->identifiers_.insert(identifier);
+        this->identifierByTypeIndex_[identifier->getTypeInfo()] = identifier;
+        this->identifierByString_[identifier->getName()] = identifier;
+        this->identifierByLowercaseString_[getLowercase(identifier->getName())] = identifier;
+        this->identifierByNetworkId_[identifier->getNetworkID()] = identifier;
+    }
+
+    /**
+     * Unregisters the identifier from all maps of the IdentifierManager.
+     */
+    void IdentifierManager::removeIdentifier(Identifier* identifier)
+    {
+        this->identifiers_.erase(identifier);
+        this->identifierByTypeIndex_.erase(identifier->getTypeInfo());
+        this->identifierByString_.erase(identifier->getName());
+        this->identifierByLowercaseString_.erase(getLowercase(identifier->getName()));
+        this->identifierByNetworkId_.erase(identifier->getNetworkID());
+    }
+
+    /**
+        @brief Creates the class-hierarchy by creating and destroying one object of each type.
+    */
+    void IdentifierManager::createClassHierarchy()
+    {
+        orxout(internal_status) << "Create class-hierarchy" << endl;
+        this->startCreatingHierarchy();
+
+        std::set<Identifier*> initializedIdentifiers;
+
+        // ensure root context exists before starting to create objects. if the root context is dynamically created while creating the class hierarchy, we
+        // would mistakenly assume the class of the currently created object inherits from Context
+        Context::getRootContext();
+
+        // iterate over all identifiers, create one instance of each class and initialize the identifiers
+        {
+            Context temporaryContext(nullptr);
+            for (Identifier* identifier : this->identifiers_)
+            {
+                if (identifier->isInitialized())
+                    continue;
+
+                orxout(verbose, context::identifier) << "Initialize ClassIdentifier<" << identifier->getName() << ">-Singleton." << endl;
+                // To initialize the identifier, we create a new object and delete it afterwards.
+                if (identifier->hasFactory())
+                {
+                    this->identifierTraceOfNewObject_.clear();
+                    this->recordTraceForIdentifier_ = identifier;
+
+                    Identifiable* temp = identifier->fabricate(&temporaryContext);
+
+                    this->recordTraceForIdentifier_ = nullptr;
+
+                    if (temp->getIdentifier() != identifier)
+                        orxout(internal_error) << "Newly created object of type " << identifier->getName() << " has unexpected identifier. Did you forget to use RegisterObject(classname)?" << endl;
+
+                    identifier->initializeParents(this->identifierTraceOfNewObject_[temp]);
+
+                    delete temp;
+                }
+
+                initializedIdentifiers.insert(identifier);
+            }
+
+            size_t numberOfObjects = temporaryContext.getObjectList<Listable>()->size();
+            if (numberOfObjects > 0)
+                orxout(internal_warning) << "There are still " << numberOfObjects << " listables left after creating the class hierarchy" << endl;
+        }
+
+        // finish the initialization of all identifiers
+        for (Identifier* initializedIdentifier : initializedIdentifiers)
+            initializedIdentifier->finishInitialization();
+
+        // only check class hierarchy in dev mode because it's an expensive operation and it requires a developer to fix detected problems anyway.
+        if (!Core::exists() || Core::getInstance().getConfig()->inDevMode())
+            this->verifyClassHierarchy(initializedIdentifiers);
+
+        this->stopCreatingHierarchy();
+        orxout(internal_status) << "Finished class-hierarchy creation" << endl;
+    }
+
+    /**
+     * Verifies if the class hierarchy is consistent with the RTTI.
+     */
+    void IdentifierManager::verifyClassHierarchy(const std::set<Identifier*>& initializedIdentifiers)
+    {
+        // check if there are any uninitialized identifiers remaining
+        for (Identifier* identifier : this->identifiers_)
+            if (!identifier->isInitialized())
+                orxout(internal_error) << "Identifier was registered late and is not initialized: " << identifier->getName() << " / " << identifier->getTypeInfo().name() << endl;
+
+        // for all initialized identifiers, check if a sample instance behaves as expected according to the class hierarchy
+        Context temporaryContext(nullptr);
+        for (Identifier* initializedIdentifier : initializedIdentifiers)
+        {
+            if (!initializedIdentifier->hasFactory())
+                continue;
+
+            Identifiable* temp = initializedIdentifier->fabricate(&temporaryContext);
+
+            for (Identifier* identifier : this->identifiers_)
+            {
+                bool isA_AccordingToRtti = identifier->canDynamicCastObjectToIdentifierClass(temp);
+                bool isA_AccordingToClassHierarchy = temp->isA(identifier);
+
+                if (isA_AccordingToRtti != isA_AccordingToClassHierarchy)
+                {
+                    orxout(internal_error) << "Class hierarchy does not match RTTI: Class hierarchy claims that " << initializedIdentifier->getName() <<
+                        (isA_AccordingToClassHierarchy ? " is a " : " is not a ") << identifier->getName() << " but RTTI says the opposite." << endl;
+                }
+            }
+
+            delete temp;
+        }
+        orxout(internal_info) << "Class hierarchy matches RTTI" << endl;
+
+        size_t numberOfObjects = temporaryContext.getObjectList<Listable>()->size();
+        if (numberOfObjects > 0)
+            orxout(internal_warning) << "There are still " << numberOfObjects << " listables left after creating the class hierarchy" << endl;
+    }
+
+    /**
+     * @brief Resets all Identifiers.
+     */
+    void IdentifierManager::destroyClassHierarchy()
+    {
+        orxout(internal_status) << "Destroy class-hierarchy" << endl;
+        for (Identifier* identifier : this->identifiers_)
+            identifier->reset();
+    }
+
+    /**
+     * @brief Notifies the IdentifierManager about a newly created object while creating the class hierarchy.
+     */
+    void IdentifierManager::createdObject(Identifiable* identifiable)
+    {
+        if (this->isCreatingHierarchy())
+        {
+            if (this->recordTraceForIdentifier_)
+            {
+                std::list<const Identifier*>& traceForObject = this->identifierTraceOfNewObject_[identifiable];
+                if (std::find(traceForObject.begin(), traceForObject.end(), identifiable->getIdentifier()) != traceForObject.end())
+                {
+                    orxout(internal_warning) << this->recordTraceForIdentifier_->getName() << " inherits two times from " <<
+                        identifiable->getIdentifier()->getName() << ". Did you forget to use virtual inheritance?" << endl;
+                }
+                traceForObject.push_back(identifiable->getIdentifier());
+            }
+        }
+        else
+            orxout(internal_warning) << "createdObject() called outside of class hierarchy creation" << endl;
+    }
+
+    /**
+        @brief Returns the Identifier with a given name.
+        @param name The name of the wanted Identifier
+        @return The Identifier
+    */
+    Identifier* IdentifierManager::getIdentifierByString(const std::string& name)
+    {
+        std::map<std::string, Identifier*>::const_iterator it = this->identifierByString_.find(name);
+        if (it != this->identifierByString_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Returns the Identifier with a given name in lowercase.
+        @param name The name of the wanted Identifier
+        @return The Identifier
+    */
+    Identifier* IdentifierManager::getIdentifierByLowercaseString(const std::string& name)
+    {
+        std::map<std::string, Identifier*>::const_iterator it = this->identifierByLowercaseString_.find(name);
+        if (it != this->identifierByLowercaseString_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Returns the Identifier with a given network ID.
+        @param id The network ID of the wanted Identifier
+        @return The Identifier
+    */
+    Identifier* IdentifierManager::getIdentifierByID(const uint32_t id)
+    {
+        std::map<uint32_t, Identifier*>::const_iterator it = this->identifierByNetworkId_.find(id);
+        if (it != this->identifierByNetworkId_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Returns the Identifier with a given typeid-name.
+        @param typeInfo The type_info of the wanted Identifier
+        @return The Identifier
+    */
+    Identifier* IdentifierManager::getIdentifierByTypeInfo(const std::type_info& typeInfo)
+    {
+        auto it = this->identifierByTypeIndex_.find(typeInfo);
+        if (it != this->identifierByTypeIndex_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Cleans the NetworkID map (needed on clients for correct initialization)
+    */
+    void IdentifierManager::clearNetworkIDs()
+    {
+        this->identifierByNetworkId_.clear();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/IdentifierManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/IdentifierManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/IdentifierManager.h	(revision 11817)
@@ -0,0 +1,125 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Class Identifier
+*/
+
+#ifndef _IdentifierManager_H__
+#define _IdentifierManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <typeindex>
+#include <map>
+#include <unordered_map>
+#include <set>
+#include <list>
+#include <string>
+
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    class _CoreExport IdentifierManager : public Singleton<IdentifierManager>
+    {
+        friend class Singleton<IdentifierManager>;
+
+        public:
+            IdentifierManager();
+            ~IdentifierManager() = default;
+
+            void addIdentifier(Identifier* identifier);
+            void removeIdentifier(Identifier* identifier);
+
+
+            /////////////////////////////
+            ////// Class Hierarchy //////
+            /////////////////////////////
+            void createClassHierarchy();
+            void verifyClassHierarchy(const std::set<Identifier*>& initializedIdentifiers);
+            void destroyClassHierarchy();
+
+            void createdObject(Identifiable* identifiable);
+
+            /// Returns true, if a branch of the class-hierarchy is being created, causing all new objects to store their parents.
+            inline bool isCreatingHierarchy()
+                { return (hierarchyCreatingCounter_s > 0); }
+
+
+            //////////////////////////
+            ///// Identifier Map /////
+            //////////////////////////
+            Identifier* getIdentifierByString(const std::string& name);
+            Identifier* getIdentifierByLowercaseString(const std::string& name);
+            Identifier* getIdentifierByID(uint32_t id);
+            Identifier* getIdentifierByTypeInfo(const std::type_info& typeInfo);
+
+            void clearNetworkIDs();
+
+            /// Returns the map that stores all Identifiers with their names.
+            inline const std::map<std::string, Identifier*>& getIdentifierByStringMap()
+                { return this->identifierByString_; }
+            /// Returns the map that stores all Identifiers with their names in lowercase.
+            inline const std::map<std::string, Identifier*>& getIdentifierByLowercaseStringMap()
+                { return this->identifierByLowercaseString_; }
+            /// Returns the map that stores all Identifiers with their IDs.
+            inline const std::map<uint32_t, Identifier*>& getIdentifierByNetworkIdMap()
+                { return this->identifierByNetworkId_; }
+
+        private:
+            // non-copyable:
+            IdentifierManager(const IdentifierManager&) = delete;
+            IdentifierManager& operator=(const IdentifierManager&) = delete;
+
+            /// Increases the hierarchyCreatingCounter_s variable, causing all new objects to store their parents.
+            inline void startCreatingHierarchy()
+                { hierarchyCreatingCounter_s++; }
+            /// Decreases the hierarchyCreatingCounter_s variable, causing the objects to stop storing their parents.
+            inline void stopCreatingHierarchy()
+                { hierarchyCreatingCounter_s--; }
+
+            std::set<Identifier*> identifiers_;                                      //!< All identifiers. This is only used internally.
+            std::unordered_map<std::type_index, Identifier*> identifierByTypeIndex_; //!< Map that stores all Identifiers with their type_index.
+            std::map<std::string, Identifier*> identifierByString_;                  //!< Map that stores all Identifiers with their names.
+            std::map<std::string, Identifier*> identifierByLowercaseString_;         //!< Map that stores all Identifiers with their names in lowercase.
+            std::map<uint32_t, Identifier*> identifierByNetworkId_;                  //!< Returns the map that stores all Identifiers with their network IDs.
+
+            int hierarchyCreatingCounter_s;                         //!< Bigger than zero if at least one Identifier stores its parents (its an int instead of a bool to avoid conflicts with multithreading)
+
+            /// Used while creating the object hierarchy to keep track of the identifiers of a newly created object (and all other objects that get created as
+            /// a consequence of this, e.g. nested member objects).
+            std::map<Identifiable*, std::list<const Identifier*>> identifierTraceOfNewObject_;
+            Identifier* recordTraceForIdentifier_; //!< The identifier for which we want to record the trace of identifiers during object creation. If null, no trace is recorded.
+
+            static IdentifierManager* singletonPtr_s;
+    };
+}
+
+#endif /* _IdentifierManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxClass.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxClass.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxClass.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OrxonoxClass.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(OrxonoxClass);
+
+    OrxonoxClass::OrxonoxClass()
+    {
+        RegisterObject(OrxonoxClass);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxClass.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxClass.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxClass.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup OrxonoxClass OrxonoxClass
+    @ingroup Class
+*/
+
+/**
+    @file
+    @ingroup Class OrxonoxClass
+    @brief Declaration of OrxonoxClass, the base class of all objects in Orxonox.
+*/
+
+#ifndef _OrxonoxClass_H__
+#define _OrxonoxClass_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/config/Configurable.h"
+#include "core/object/Destroyable.h"
+
+namespace orxonox
+{
+    /**
+        @brief This is the class from which all objects of the game-logic (not the engine) are derived from.
+    */
+    class _CoreExport OrxonoxClass : virtual public Configurable, virtual public Destroyable
+    {
+        public:
+            OrxonoxClass();
+
+            // This is only here to work around a bogus warning in GCC:
+            //
+            //   OrxonoxClass.h:53:23: warning: defaulted move assignment for 'orxonox::OrxonoxClass' calls a non-trivial move assignment operator for virtual base 'orxonox::Configurable' [-Wvirtual-move-assign]
+            //   class _CoreExport OrxonoxClass : virtual public Configurable, virtual public Destroyable
+            //
+            // You can remove this line if the whole project compiles without warnings in future versions of GCC.
+            OrxonoxClass& operator=(const OrxonoxClass&) = default;
+    };
+}
+
+#endif /* _OrxonoxClass_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxInterface.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxInterface.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxInterface.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OrxonoxInterface.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(OrxonoxInterface).virtualBase();
+
+    OrxonoxInterface::OrxonoxInterface()
+    {
+        RegisterObject(OrxonoxInterface);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/OrxonoxInterface.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Class OrxonoxClass
+    @brief Declaration of OrxonoxInterface, the base class of all interfaces in Orxonox.
+*/
+
+#ifndef _OrxonoxInterface_H__
+#define _OrxonoxInterface_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/config/Configurable.h"
+#include "core/object/Destroyable.h"
+
+namespace orxonox
+{
+    /**
+        @brief This is the class from which all interfaces of the game-logic (not the engine) are derived from.
+
+        Interfaces are derived with @c virtual @c public @c OrxonoxInterface from OrxonoxInterface.
+    */
+    class _CoreExport OrxonoxInterface : virtual public Configurable, virtual public Destroyable
+    {
+        public:
+            OrxonoxInterface();
+    };
+}
+
+#endif /* _OrxonoxInterface_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/SubclassIdentifier.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/SubclassIdentifier.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/SubclassIdentifier.h	(revision 11817)
@@ -0,0 +1,204 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Class Identifier
+    @brief Definition of SubclassIdentifier.
+
+    @anchor SubclassIdentifierExample
+
+    SubclassIdentifier is a separated class, acting like an Identifier, but has a given class.
+    You can only assign Identifiers of exactly the given class or of a derivative to a SubclassIdentifier.
+
+    Example:
+
+    You can assign an Identifier either through the constructor or by using the assignment @c operator=:
+    @code
+    SubclassIdentifier<BaseClass> identifier = Class(SubClass);
+    @endcode
+
+    The @c operator-> is overloaded an returns the assigned Identifier. That way you can just call
+    functions of the assigned Identifier by using @c ->function():
+    @code
+    SubclassIdentifier<BaseClass> identifier = Class(SubClass);
+    identifier->getName();      // returns "SubClass"
+    @endcode
+
+    There are two possibilities to create an object out of a SubclassIdentifier: Either you just use
+    the @c fabricate() function of the assigned Identifier through the overloaded @c operator->, which
+    returns a @c OrxonoxClass* pointer, or you use the function of SubclassIdentifier, this time by using
+    @c operator., which returns a @c BaseClass* pointer (@a BaseClass is the baseclass specified by the
+    template argument):
+    @code
+    identifier->fabricate();    // calls Identifier::fabricate(), creates a SubClass, returns a OrxonoxClass* pointer
+
+    identifier.fabricate();     // calls SubclassIdentifier::fabricate(), creates a SubClass, returns a BaseClass* pointer
+    @endcode
+*/
+
+#ifndef _SubclassIdentifier_H__
+#define _SubclassIdentifier_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cstdlib>
+#include "util/Output.h"
+#include "Identifier.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###   SubclassIdentifier    ###
+    // ###############################
+    /**
+        @brief The SubclassIdentifier acts almost like an Identifier, but has some prerequisites.
+
+        You can only assign an Identifier that belongs to a class T (or derived) to a SubclassIdentifier<T>.
+        If you assign something else, the program prints an error.
+
+        Because we know the base-type, a @c dynamic_cast is done, which makes it easier to create a new object.
+
+        @see See @ref SubclassIdentifierExample "SubclassIdentifier.h" for some examples.
+    */
+    template <class T>
+    class SubclassIdentifier
+    {
+        public:
+            /// Constructor: Automaticaly assigns the Identifier of the given class.
+            SubclassIdentifier() : identifier_(nullptr)
+            {
+                this->identifier_ = ClassIdentifier<T>::getIdentifier();
+            }
+
+            /// Constructor: Assigns the given Identifier.
+            SubclassIdentifier(Identifier* identifier) : identifier_(nullptr)
+            {
+                this->operator=(identifier);
+            }
+
+            /// Copyconstructor: Assigns the identifier of another SubclassIdentifier.
+            template <class O>
+            SubclassIdentifier(const SubclassIdentifier<O>& identifier) : identifier_(nullptr)
+            {
+                this->operator=(identifier.getIdentifier());
+            }
+
+            /**
+                @brief Overloading of the = operator: assigns the identifier and checks its type.
+                @param identifier The Identifier to assign
+                @return The SubclassIdentifier itself
+            */
+            SubclassIdentifier<T>& operator=(Identifier* identifier)
+            {
+                if (!identifier || !identifier->isA(ClassIdentifier<T>::getIdentifier()))
+                {
+                    orxout(internal_error) << "An error occurred in SubclassIdentifier (Identifier.h):" << endl;
+                    if (identifier)
+                    {
+                        orxout(internal_error) << "Class " << identifier->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << '!' << endl;
+                        orxout(internal_error) << "SubclassIdentifier<" << ClassIdentifier<T>::getIdentifier()->getName() << "> = Class(" << identifier->getName() << ") is forbidden." << endl;
+                    }
+                    else
+                    {
+                        orxout(internal_error) << "Can't assign nullptr identifier" << endl;
+                    }
+                }
+                else
+                {
+                    this->identifier_ = identifier;
+                }
+                return *this;
+            }
+
+            /// Overloading of the = operator: assigns the identifier of another SubclassIdentifier.
+            template <class O>
+            SubclassIdentifier<T>& operator=(const SubclassIdentifier<O>& identifier)
+            {
+                return this->operator=(identifier.getIdentifier());
+            }
+
+            /// Overloading of the * operator: returns the assigned identifier.
+            inline Identifier* operator*() const
+            {
+                return this->identifier_;
+            }
+
+            /// Overloading of the -> operator: returns the assigned identifier.
+            inline Identifier* operator->() const
+            {
+                return this->identifier_;
+            }
+
+            /// Returns the assigned identifier. This allows you to assign a SubclassIdentifier to a normal Identifier*.
+            inline operator Identifier*() const
+            {
+                return this->identifier_;
+            }
+
+            /// Creates a new object of the type of the assigned Identifier and dynamic_casts it to the minimal type given by T.
+            T* fabricate(Context* context) const
+            {
+                Identifiable* newObject = this->identifier_->fabricate(context);
+
+                // Check if the creation was successful
+                if (newObject)
+                {
+                    return orxonox_cast<T*>(newObject);
+                }
+                else
+                {
+                    // Something went terribly wrong
+                    if (this->identifier_)
+                    {
+                        orxout(user_error) << "An error occurred in SubclassIdentifier (Identifier.h):" << endl;
+                        orxout(user_error) << "Class " << this->identifier_->getName() << " is not a " << ClassIdentifier<T>::getIdentifier()->getName() << '!' << endl;
+                        orxout(user_error) << "Couldn't fabricate a new Object." << endl;
+                    }
+                    else
+                    {
+                        orxout(user_error) << "An error occurred in SubclassIdentifier (Identifier.h):" << endl;
+                        orxout(user_error) << "Couldn't fabricate a new Object - Identifier is undefined." << endl;
+                    }
+
+                    orxout(user_error) << "Aborting..." << endl;
+                    abort();
+                    return nullptr;
+                }
+            }
+
+            /// Returns the assigned identifier.
+            inline Identifier* getIdentifier() const
+                { return this->identifier_; }
+
+        private:
+            Identifier* identifier_;            //!< The assigned identifier
+    };
+}
+
+#endif /* _SubclassIdentifier_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/class/Super.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/class/Super.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/class/Super.h	(revision 11817)
@@ -0,0 +1,626 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Super Super
+    @ingroup Class
+*/
+
+/**
+    @file
+    @ingroup Class Super
+    @brief Definition of all super-function related macros, used to call functions of the base class.
+
+    This file defines all macros needed to add a new "super-function". If you add
+    a super-function, you can call <tt>SUPER(myclass, functionname, arguments)</tt>
+    inside your code and the function of the parent-class gets called. This is comparable
+    to <tt>super.functionname(arguments)</tt> in Java or other languages.
+
+    This works only with virtual functions that return nothing (@c void) and belong to
+    classes that have an @ref orxonox::Identifier "Identifier". Arguments however are
+    supported, there's no limitation for their number and type, except that the type has
+    to be known in Super.h.
+
+    To add a new super-function, you have to process 4 steps:
+
+    -# Add a new @c SUPER macro <br />
+       This allows you to call the super-function in your code. <br />
+       Location: This file (Super.h), marked with "--> HERE <--" comments (1/3)
+    -# Call the @c SUPER_FUNCTION_GLOBAL_DECLARATION_PART1/2 macros. <br />
+       This defines some global classes and templates, needed to create and call the super-functions. <br />
+       Location: This file (Super.h), marked with "--> HERE <--" comments (2/3)
+    -# Call the @c SUPER_INTRUSIVE_DECLARATION macro. <br />
+       This will be included into the declaration of @c ClassIdentifier<T>. <br />
+       Location: This file (Super.h), marked with "--> HERE <--" comments (3/3)
+    -# Call the @c SUPER_FUNCTION macro. <br />
+       This defines a partially specialized template that will decide if a class is "super" to another class.
+       If the check returns true, a @c SuperFunctionCaller gets created, which will be used by the @c SUPER macro.
+       You have to add this into the header-file of the baseclass of the super-function (the class that first
+       implements the function), below the class declaration. You can't call it directly in this file, because
+       otherwise you had to include the headerfile right here, which would cause some ugly back-dependencies,
+       include loops and slower compilation. <br />
+       Dont forget to include Super.h in the header-file. <br />
+       Location: The header-file of the baseclass (Baseclass.h), below the class declaration
+*/
+
+#ifndef _Super_H__
+#define _Super_H__
+
+#include "core/CorePrereqs.h"
+#include "util/Output.h"
+
+///////////////////////
+// Macro definitions //
+///////////////////////
+
+//// Common macros ////
+
+    /**
+        @brief Declares a new super-function by creating a specialized template. Add this below the class declaration of the baseclass.
+        @param functionnumber Each super-function needs a unique number, starting with zero, increasing by one
+        @param baseclass The baseclass of the super-function (~the root)
+        @param functionname The name of the super-function
+        @param purevirtualbase "true" if the function is pure virtual in the baseclass, "false" if the function is implemented (without "")
+    */
+    #define SUPER_FUNCTION(functionnumber, baseclass, functionname, purevirtualbase) \
+        template <class T, int templatehack2> \
+        struct SuperFunctionCondition<functionnumber, T, 0, templatehack2> \
+        { \
+            static void superCheck() \
+            { \
+                SuperFunctionCondition<functionnumber, T, 0, templatehack2>::apply(static_cast<T*>(nullptr)); \
+                SuperFunctionCondition<functionnumber + 1, T, 0, templatehack2>::superCheck(); \
+            } \
+            \
+            static void apply(void*) {} \
+            \
+            static void apply(baseclass*) \
+            { \
+                ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier(); \
+                for (const Identifier* child : identifier->getDirectChildren()) \
+                { \
+                    if (((ClassIdentifier<T>*)child)->bSuperFunctionCaller_##functionname##_isFallback_ && ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_) \
+                    { \
+                        delete ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_; \
+                        ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_ = nullptr; \
+                        ((ClassIdentifier<T>*)child)->bSuperFunctionCaller_##functionname##_isFallback_ = false; \
+                    } \
+                    \
+                    if (!((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_) \
+                    { \
+                        orxout(verbose, context::super) << "Added SuperFunctionCaller for " << #functionname << ": " << ClassIdentifier<T>::getIdentifier()->getName() << " <- " << ((ClassIdentifier<T>*)child)->getName() << endl; \
+                        ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_ = new SuperFunctionClassCaller_##functionname <T>; \
+                    } \
+                    else if (((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_->getParentIdentifier() != ClassIdentifier<T>::getIdentifier()) \
+                        orxout(internal_warning, context::super) << "SuperFunctionCaller for " << #functionname << " in " << ((ClassIdentifier<T>*)child)->getName() << " calls function of " << ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_->getParentIdentifier()->getName() << " but " << ClassIdentifier<T>::getIdentifier()->getName() << " is also possible (do you use multiple inheritance?)" << endl; \
+                } \
+            } \
+        }; \
+        \
+        SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND##purevirtualbase(functionnumber, baseclass)
+
+    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND0(functionnumber, baseclass) SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDfalse(functionnumber, baseclass)
+    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND1(functionnumber, baseclass) SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDtrue(functionnumber, baseclass)
+    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDfalse(functionnumber, baseclass)
+    #define SUPER_FUNCTION_PUREVIRTUAL_WORKAROUNDtrue(functionnumber, baseclass) \
+        template <int templatehack2> \
+        struct SuperFunctionCondition<functionnumber, baseclass, 0, templatehack2> \
+        { \
+            static void superCheck() \
+            { \
+                SuperFunctionCondition<functionnumber + 1, baseclass, 0, templatehack2>::superCheck(); \
+            } \
+        };
+
+
+    /*
+    //// Comments about the macro ////
+
+        // Partially specialized template (templatehack is now specialized too).
+        //
+        // This ensures the compiler takes THIS template if the header-file of the super-function
+        // is included. In any other case, the compiler just uses the fallback template which is
+        // defined in this file.
+        template <class T, templatehack2>
+        struct SuperFunctionCondition<functionnumber, T, 0, templatehack2>
+        {
+            static void superCheck()
+            {
+                // This call to the apply-function is the whole check. By calling the function with
+                // a T* pointer, the right function get's called.
+                SuperFunctionCondition<functionnumber, T, 0, templatehack2>::apply(static_cast<T*>(nullptr));
+
+                // Go go the superCheck for of next super-function (functionnumber + 1)
+                SuperFunctionCondition<functionnumber + 1, T, 0, templatehack2>::superCheck();
+            }
+
+            // This function gets called if T is not a child of the baseclass.
+            // The function does nothing.
+            static void apply(void* temp) {}
+
+            // This function gets called if T is a child of the baseclass and can therefore be converted.
+            // The function adds a SuperFunctionCaller to the Identifier of all subclasses of T.
+            static void apply(baseclass* temp)
+            {
+                ClassIdentifier<T>* identifier = ClassIdentifier<T>::getIdentifier();
+
+                // Iterate through all children
+                for (const Identifier* child : identifier->getDirectChildren())
+                {
+                    // Check if the caller is a fallback-caller
+                    if (((ClassIdentifier<T>*)child)->bSuperFunctionCaller_##functionname##_isFallback_ && ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_)
+                    {
+                        // Delete the fallback caller an prepare to get a real caller
+                        delete ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_;
+                        ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_ = nullptr;
+                        ((ClassIdentifier<T>*)child)->bSuperFunctionCaller_##functionname##_isFallback_ = false;
+                    }
+
+                    // Check if there's not already a caller
+                    if (!((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_)
+                    {
+                        // Add the SuperFunctionCaller
+                        orxout(verbose, context::super) << "adding functionpointer to " << ((ClassIdentifier<T>*)child)->getName() << endl;
+                        ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_ = new SuperFunctionClassCaller_##functionname <T>;
+                    }
+
+                    // If there is already a caller, but for another parent, print a warning
+                    else if (((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_->getParentIdentifier() != ClassIdentifier<T>::getIdentifier())
+                        orxout(internal_warning, context::super) << "SuperFunctionCaller for " << #functionname << " in " << ((ClassIdentifier<T>*)child)->getName() << " calls function of " << ((ClassIdentifier<T>*)child)->superFunctionCaller_##functionname##_->getParentIdentifier()->getName() << " but " << ClassIdentifier<T>::getIdentifier()->getName() << " is also possible (do you use multiple inheritance?)" << endl;
+                }
+            }
+        };
+        SUPER_FUNCTION_PUREVIRTUAL_WORKAROUND##purevirtualbase
+
+
+        // The following piece of code is only added if purevirtualbase = true
+
+        // Explicit specialization of the Condition template for the baseclass to avoid
+        // errors if the function is pure virtual in the baseclass.
+        template <int templatehack2> \
+        struct SuperFunctionCondition<functionnumber, baseclass, 0, templatehack2> \
+        { \
+            // The superCheck function acts like the fallback - it advances to the check for the next super-function (functionnumber + 1)
+            static void superCheck() \
+            { \
+                SuperFunctionCondition<functionnumber + 1, baseclass, 0, templatehack2>::superCheck(); \
+            } \
+        };
+    */
+
+    /// SUPER-macro: Calls Parent::functionname(...) where Parent is the direct parent of @a classname
+    #ifdef ORXONOX_COMPILER_MSVC
+        #define SUPER(classname, functionname, ...) \
+            __super::functionname(__VA_ARGS__)
+    #else
+        #define SUPER(classname, functionname, ...) \
+            SUPER_##functionname(classname, functionname, __VA_ARGS__)
+    #endif
+
+    // helper macro: for functions without arguments
+    #define SUPER_NOARGS(classname, functionname) \
+        (*ClassIdentifier<classname>::getIdentifier()->superFunctionCaller_##functionname##_)(this)
+
+    // helper macro: for functions with arguments
+    #define SUPER_ARGS(classname, functionname, ...) \
+        (*ClassIdentifier<classname>::getIdentifier()->superFunctionCaller_##functionname##_)(this, __VA_ARGS__)
+
+
+//// Function-specific macros ////
+
+    /*
+        Add a macro for each super-function
+
+        Example (no arguments):
+        #define SUPER_myfunction(classname, functionname, ...) \
+            SUPER_NOARGS(classname, functionname)
+
+        Example (with arguments):
+        #define SUPER_myfunction(classname, functionname, ...) \
+            SUPER_ARGS(classname, functionname, __VA_ARGS__)
+    */
+
+    // (1/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
+    #define SUPER_XMLPort(classname, functionname, ...) \
+        SUPER_ARGS(classname, functionname, __VA_ARGS__)
+
+    #define SUPER_tick(classname, functionname, ...) \
+        SUPER_ARGS(classname, functionname, __VA_ARGS__)
+
+    #define SUPER_changedActivity(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedVisibility(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_XMLEventPort(classname, functionname, ...) \
+        SUPER_ARGS(classname, functionname, __VA_ARGS__)
+
+    #define SUPER_changedScale(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedOwner(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedOverlayGroup(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedName(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedUsed(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedCarrier(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    #define SUPER_changedPickedUp(classname, functionname, ...) \
+        SUPER_NOARGS(classname, functionname)
+
+    // (1/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
+
+
+namespace orxonox
+{
+    /////////////////////////////////////////////////////////////////////////////////////////////////////
+    // This code gets included by Identifier.h and every other header file that needs a super-function //
+    /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    //// Common code ////
+
+        // Base templates
+        /**
+            @brief Creates the SuperFunctionCaller if T is a child of the super-functions baseclass.
+        */
+        template <int functionnumber, class T, int templatehack1, int templatehack2>
+        struct SuperFunctionCondition
+        {
+            static void superCheck() {}
+        };
+
+        /**
+            @brief Initializes the SuperFunctionCaller-pointer with zero.
+        */
+        template <int functionnumber, class T>
+        struct SuperFunctionInitialization
+        {
+            static void initialize(ClassIdentifier<T>*) {}
+        };
+
+        /**
+            @brief Deletes the SuperFunctionCaller.
+        */
+        template <int functionnumber, class T>
+        struct SuperFunctionDestruction
+        {
+            static void destroy(ClassIdentifier<T>*) {}
+        };
+
+
+    //// Function-specific code ////
+
+        /**
+            @brief Creates the needed objects and templates to call a super-function.
+            @param functionnumber Each super-function needs a unique number, starting with zero, increasing by one
+            @param functionname The name of the super-function
+            @param hasarguments "false" if the function doesn't take any arguments, "true" if it does (without "")
+            @param ... Variadic: If the function takes arguments, add them here with type and name. Example: int myvalue, float myothervalue
+        */
+        #define SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(functionnumber, functionname, hasarguments, ...) \
+            template <class T, int templatehack1, int templatehack2> \
+            struct SuperFunctionCondition<functionnumber, T, templatehack1, templatehack2> \
+            { \
+                static void superCheck() \
+                { \
+                    SuperFunctionCondition<functionnumber + 1, T, templatehack1, templatehack2>::superCheck(); \
+                } \
+            }; \
+            \
+            class _CoreExport SuperFunctionCaller_##functionname \
+            { \
+                public: \
+                    virtual void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) = 0; \
+                    virtual ~SuperFunctionCaller_##functionname () {} \
+                    virtual Identifier* getParentIdentifier() const = 0; \
+            }; \
+            \
+            template <class T> \
+            class SuperFunctionClassCaller_purevirtualfallback_##functionname : public SuperFunctionCaller_##functionname \
+            { \
+                public: \
+                    inline void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) \
+                    { \
+                    } \
+                    \
+                    Identifier* getParentIdentifier() const \
+                    { \
+                        return ClassIdentifier<T>::getIdentifier(); \
+                    } \
+            }; \
+            \
+            template <class T> \
+            struct SuperFunctionInitialization<functionnumber, T> \
+            { \
+                static void initialize(ClassIdentifier<T>* identifier) \
+                { \
+                    identifier->superFunctionCaller_##functionname##_ = new SuperFunctionClassCaller_purevirtualfallback_##functionname <T>; \
+                    identifier->bSuperFunctionCaller_##functionname##_isFallback_ = true; \
+                    SuperFunctionInitialization<functionnumber + 1, T>::initialize(identifier); \
+                } \
+            }; \
+            \
+            template <class T> \
+            struct SuperFunctionDestruction<functionnumber, T> \
+            { \
+                static void destroy(ClassIdentifier<T>* identifier) \
+                { \
+                    if (identifier->superFunctionCaller_##functionname##_) \
+                        delete identifier->superFunctionCaller_##functionname##_; \
+                    SuperFunctionDestruction<functionnumber + 1, T>::destroy(identifier); \
+                } \
+            }; \
+            \
+            template <class T> \
+            class SuperFunctionClassCaller_##functionname : public SuperFunctionCaller_##functionname \
+            { \
+                public: \
+                    inline void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) \
+                    { \
+                        (orxonox_cast<T*>(object))->T:: functionname
+
+        /*
+            JUST ADD THE FUNCTION ARGUMENTS BETWEEN BOTH MACROS, ENCLOSED BY BRACKETS
+            EXAMPLE:
+
+              SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(0, myfunction, true, int myvalue, float myothervalue) <-- !!! DONT ADD A SEMICOLON HERE !!!
+                (myvalue, myothervalue)
+              SUPER_FUNCTION_GLOBAL_DECLARATION_PART2
+        */
+
+        #define SUPER_FUNCTION_GLOBAL_DECLARATION_PART2 \
+                                                        ; \
+                    } \
+                    \
+                    Identifier* getParentIdentifier() const \
+                    { \
+                        return ClassIdentifier<T>::getIdentifier(); \
+                    } \
+            };
+
+        #define SUPER_CALL_ARGUMENTSfalse(...) Identifiable* object
+        #define SUPER_CALL_ARGUMENTS0(...)     Identifiable* object
+        #define SUPER_CALL_ARGUMENTStrue(...) Identifiable* object, __VA_ARGS__
+        #define SUPER_CALL_ARGUMENTS1(...)    Identifiable* object, __VA_ARGS__
+
+
+    /*
+    //// COMMENTS ABOUT THE MACRO ////
+
+        // Partially specialized template (templatehack not yet specialized, this
+        // will be done by the real condition in the header-file of the super-function)
+        // Only used as fallback
+        template <class T, int templatehack1, int templatehack2>
+        struct SuperFunctionCondition<functionnumber, T, templatehack1, templatehack2>
+        {
+            // If this function gets called, the header-file of the super function is not
+            // included, so this fallback template (templatehack not specialized) is used
+            static void superCheck()
+            {
+                // Calls the condition-check of the next super-function (functionnumber + 1)
+                SuperFunctionCondition<functionnumber + 1, T, templatehack1, templatehack2>::superCheck();
+            }
+        };
+
+        // Baseclass of the super-function caller. The real call will be done by a
+        // templatized subclass through the virtual () operator.
+        class _CoreExport SuperFunctionCaller_##functionname
+        {
+            public:
+                virtual void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) ) = 0;
+                virtual ~SuperFunctionCaller_##functionname () {}
+                virtual Identifier* getParentIdentifier() const = 0;
+        };
+
+        // Fallback if the base is pure virtual
+        template <class T>
+        class SuperFunctionClassCaller_purevirtualfallback_##functionname : public SuperFunctionCaller_##functionname
+        {
+            public:
+                // Fallback does nothing
+                inline void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) )
+                {
+                }
+
+                Identifier* getParentIdentifier() const
+                {
+                    return ClassIdentifier<T>::getIdentifier();
+                }
+        };
+
+        // Initializes the SuperFunctionCaller-pointer with a fallback caller in case the base function is pure virtual
+        template <class T>
+        struct SuperFunctionInitialization<functionnumber, T>
+        {
+            static void initialize(ClassIdentifier<T>* identifier)
+            {
+                identifier->superFunctionCaller_##functionname##_ = new SuperFunctionClassCaller_purevirtualfallback_##functionname <T>;
+                identifier->bSuperFunctionCaller_##functionname##_isFallback_ = true;
+
+                // Calls the initialization of the next super-function (functionnumber + 1)
+                SuperFunctionInitialization<functionnumber + 1, T>::initialize(identifier);
+            }
+        };
+
+        // Deletes the SuperFunctionCaller.
+        template <class T>
+        struct SuperFunctionDestruction<functionnumber, T>
+        {
+            static void destroy(ClassIdentifier<T>* identifier)
+            {
+                if (identifier->superFunctionCaller_##functionname##_)
+                    delete identifier->superFunctionCaller_##functionname##_;
+
+                // Calls the destruction of the next super-function (functionnumber + 1)
+                SuperFunctionDestruction<functionnumber + 1, T>::destroy(identifier);
+            }
+        };
+
+        // The real super-function caller: Calls T::functionname()
+        // T should be the parent, but this will be done by the spezialized condition template
+        template <class T>
+        class SuperFunctionClassCaller_##functionname : public SuperFunctionCaller_##functionname
+        {
+            public:
+                // @brief Calls the function.
+                // @param object The object to call the function on
+                // @param ... The arguments of the function
+                inline void operator()( SUPER_CALL_ARGUMENTS##hasarguments(__VA_ARGS__) )
+                {
+                    (orxonox_cast<T*>(object))->T:: functionname ( Call the function with it's arguments );
+                }
+
+                Identifier* getParentIdentifier() const
+                {
+                    return ClassIdentifier<T>::getIdentifier();
+                }
+        }
+    */
+
+
+    //// Execute the code for each super-function ////
+
+        // (2/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(0, XMLPort, true, Element& xmlelement, XMLPort::Mode mode)
+            (xmlelement, mode)
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(1, tick, true, float dt)
+            (dt)
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(2, changedActivity, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(3, changedVisibility, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(4, XMLEventPort, true, Element& xmlelement, XMLPort::Mode mode)
+            (xmlelement, mode)
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(5, changedScale, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(6, changedOwner, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(7, changedOverlayGroup, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(8, changedName, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(9, changedUsed, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(10, changedCarrier, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART1(11, changedPickedUp, false)
+            ()
+        SUPER_FUNCTION_GLOBAL_DECLARATION_PART2;
+
+        // (2/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
+
+}
+
+#else /* _Super_H__ */
+  #ifdef SUPER_INTRUSIVE_DECLARATION_INCLUDE
+
+//////////////////////////////////////////////////////////////////////////
+// This code gets included within the declaration of ClassIdentifier<T> //
+//////////////////////////////////////////////////////////////////////////
+
+//// Common code ////
+
+    private:
+
+        template <int functionnumber, class TT, int templatehack1, int templatehack2>
+        friend struct SuperFunctionCondition;
+
+        // Creates the super-function-callers by calling the first SuperFunctionCondition check
+        // This get's called within the initialization of an Identifier
+        virtual void createSuperFunctionCaller() const override
+        {
+            SuperFunctionCondition<0, T, 0, 0>::superCheck();
+        }
+
+
+//// Function-specific code ////
+
+    public:
+        /**
+            @brief Adds a pointer to the SuperFunctionCaller as a member of ClassIdentifier.
+            @param functionname The name of the super-function
+        */
+        #ifndef SUPER_INTRUSIVE_DECLARATION
+          #define SUPER_INTRUSIVE_DECLARATION(functionname) \
+            SuperFunctionCaller_##functionname * superFunctionCaller_##functionname##_; \
+            bool bSuperFunctionCaller_##functionname##_isFallback_
+        #endif
+
+
+//// Execute the code for each super-function ////
+
+    // (3/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
+    SUPER_INTRUSIVE_DECLARATION(XMLPort);
+    SUPER_INTRUSIVE_DECLARATION(tick);
+    SUPER_INTRUSIVE_DECLARATION(changedActivity);
+    SUPER_INTRUSIVE_DECLARATION(changedVisibility);
+    SUPER_INTRUSIVE_DECLARATION(XMLEventPort);
+    SUPER_INTRUSIVE_DECLARATION(changedScale);
+    SUPER_INTRUSIVE_DECLARATION(changedOwner);
+    SUPER_INTRUSIVE_DECLARATION(changedOverlayGroup);
+    SUPER_INTRUSIVE_DECLARATION(changedName);
+    SUPER_INTRUSIVE_DECLARATION(changedUsed);
+    SUPER_INTRUSIVE_DECLARATION(changedCarrier);
+    SUPER_INTRUSIVE_DECLARATION(changedPickedUp);
+    // (3/3) --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <-- --> HERE <--
+
+
+    #undef SUPER_INTRUSIVE_DECLARATION_INCLUDE
+  #endif /* SUPER_INTRUSIVE_DECLARATION_INCLUDE */
+#endif /* _Super_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompleter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompleter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompleter.h	(revision 11817)
@@ -0,0 +1,121 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup ArgumentCompletion Argument completion
+    @ingroup Command
+*/
+
+/**
+    @file
+    @ingroup Command ArgumentCompletion
+    @brief Definition of the orxonox::ArgumentCompleter class that is used to execute @ref ArgumentCompletionFunctions.h "argument completion functions".
+
+    An ArgumentCompleter can be assigned to an orxonox::ConsoleCommand using
+    @ref orxonox::ConsoleCommand::argumentCompleter "argumentCompleter()".
+    The ArgumentCompleter calls an argument completion function that is defined
+    in ArgumentCompletionFunctions.h. This can be used to list possible arguments
+    for console commands and to allow auto-completion.
+
+    Instances of ArgumentCompleter are usually not created manually but rather
+    by the macros defined in ArgumentCompletionFunctions.h. There you'll also
+    find some examples.
+
+    @see See the @ref ArgumentCompletionExample "examples".
+*/
+
+#ifndef _ArgumentCompleter_H__
+#define _ArgumentCompleter_H__
+
+#include "core/CorePrereqs.h"
+#include "ArgumentCompletionListElement.h"
+
+namespace orxonox
+{
+    /**
+        @brief This class executes an argument completion function and returns a list of the possible arguments.
+
+        ArgumentCompleter is used to wrap argument completion functions as defined
+        in ArgumentCompletionFunctions.h and can be assigned to a ConsoleCommand to
+        create a list of possible arguments.
+
+        @see See ArgumentCompleter.h for more information.
+        @see See @ref ArgumentCompletionExample "ArgumentCompletionFunctions.h" for an example.
+    */
+    class _CoreExport ArgumentCompleter
+    {
+        public:
+            ArgumentCompleter(ArgumentCompletionList (*function) (void), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(0), function_0_(function) {} ///< Constructor, assigns a function-pointer with no arguments.
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(1), function_1_(function) {} ///< Constructor, assigns a function-pointer with one argument.
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(2), function_2_(function) {} ///< Constructor, assigns a function-pointer with two arguments.
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(3), function_3_(function) {} ///< Constructor, assigns a function-pointer with three arguments.
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(4), function_4_(function) {} ///< Constructor, assigns a function-pointer with four arguments.
+            ArgumentCompleter(ArgumentCompletionList (*function) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5), bool bUseMultipleWords) : bUseMultipleWords_(bUseMultipleWords), paramCount_(5), function_5_(function) {} ///< Constructor, assigns a function-pointer with five arguments.
+
+            /**
+                @brief Calls the argument completion function with a maximum of five parameters.
+                @return Returns the list of possible arguments, created by the argument completion function
+            */
+            ArgumentCompletionList operator()(const std::string& param1 = "", const std::string& param2 = "", const std::string& param3 = "", const std::string& param4 = "", const std::string& param5 = "")
+            {
+                switch (this->paramCount_)
+                {
+                    case 0:
+                        return (*this->function_0_)();
+                    case 1:
+                        return (*this->function_1_)(param1);
+                    case 2:
+                        return (*this->function_2_)(param1, param2);
+                    case 3:
+                        return (*this->function_3_)(param1, param2, param3);
+                    case 4:
+                        return (*this->function_4_)(param1, param2, param3, param4);
+                    case 5:
+                        return (*this->function_5_)(param1, param2, param3, param4, param5);
+                    default:
+                        return ArgumentCompletionList();
+                }
+            }
+
+            /// Returns true if the argument completion list supports multiple words.
+            inline bool useMultipleWords() const
+                { return this->bUseMultipleWords_; }
+
+        private:
+            bool bUseMultipleWords_;    ///< If true, the argument completion list supports multiple words
+            unsigned char paramCount_;  ///< The number of parameters of the argument completion function
+            ArgumentCompletionList (*function_0_) (void);   ///< Function-pointer for an argument completion function with no arguments
+            ArgumentCompletionList (*function_1_) (const std::string& param1);   ///< Function-pointer for an argument completion function with one argument
+            ArgumentCompletionList (*function_2_) (const std::string& param1, const std::string& param2);   ///< Function-pointer for an argument completion function with two arguments
+            ArgumentCompletionList (*function_3_) (const std::string& param1, const std::string& param2, const std::string& param3);   ///< Function-pointer for an argument completion function with three arguments
+            ArgumentCompletionList (*function_4_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4);   ///< Function-pointer for an argument completion function with four arguments
+            ArgumentCompletionList (*function_5_) (const std::string& param1, const std::string& param2, const std::string& param3, const std::string& param4, const std::string& param5);   ///< Function-pointer for an argument completion function with five arguments
+    };
+}
+
+#endif /* _ArgumentCompleter_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionFunctions.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionFunctions.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionFunctions.cc	(revision 11817)
@@ -0,0 +1,342 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of all argument completion functions
+*/
+
+#include "ArgumentCompletionFunctions.h"
+
+#include <map>
+#include <boost/filesystem.hpp>
+
+#include "util/Convert.h"
+#include "util/StringUtils.h"
+#include "core/class/Identifier.h"
+#include "core/config/SettingsConfigFile.h"
+#include "core/config/ConfigValueContainer.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommand.h"
+#include "ConsoleCommandManager.h"
+#include "TclThreadManager.h"
+
+// Differentiate Boost Filesystem v2 and v3
+#if (BOOST_FILESYSTEM_VERSION < 3)
+#  define BF_LEAF leaf
+#  define BF_GENERIC_STRING string
+#  define BF_DICTIONARY_ENTRY_NAME string
+#else
+#  define BF_LEAF path().filename().string
+#  define BF_GENERIC_STRING generic_string
+#  define BF_DICTIONARY_ENTRY_NAME path().string
+#endif
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        /**
+            @brief Fallback implementation, returns an empty list.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(fallback)()
+        {
+            return ArgumentCompletionList();
+        }
+
+        namespace detail
+        {
+            /**
+                @brief Returns true if a group of console commands is visible (i.e. if at least one command in this group is visible).
+            */
+            bool groupIsVisible(const std::map<std::string, ConsoleCommand*>& group, bool bOnlyShowHidden)
+            {
+                for (const auto& mapEntry : group)
+                    if (mapEntry.second->isActive() && mapEntry.second->hasAccess() && (!mapEntry.second->isHidden())^bOnlyShowHidden)
+                        return true;
+
+                return false;
+            }
+
+            /**
+                @brief Returns a list of all console command groups AND all console command shortcuts.
+                @param fragment The last argument
+                @param bOnlyShowHidden If true, only hidden groups and commands are returned
+            */
+            ArgumentCompletionList _groupsandcommands(const std::string& fragment, bool bOnlyShowHidden)
+            {
+                // note: this function returns only arguments that begin with "fragment", which wouldn't be necessary for the
+                //       auto-completion, but it's necessary to place the line-break "\n" between groups and commands
+                //       only if both groups AND commands are in the list.
+
+                ArgumentCompletionList groupList;
+                std::string fragmentLC = getLowercase(fragment);
+
+                // get all the groups that are visible (except the shortcut group "")
+                const std::map<std::string, std::map<std::string, ConsoleCommand*>>& commands = ConsoleCommandManager::getInstance().getCommands();
+                for (const auto& mapEntry : commands)
+                    if (groupIsVisible(mapEntry.second, bOnlyShowHidden) && mapEntry.first != "" && (fragmentLC == "" || getLowercase(mapEntry.first).find(fragmentLC) == 0))
+                        groupList.emplace_back(mapEntry.first, getLowercase(mapEntry.first));
+
+                // now add all shortcuts (in group "")
+                std::map<std::string, std::map<std::string, ConsoleCommand*>>::const_iterator it_group = commands.find("");
+                if (it_group != commands.end())
+                {
+                    // add a line-break if the list isn't empty
+                    if (!groupList.empty())
+                        groupList.emplace_back("", "", "\n");
+
+                    // add the shortcuts
+                    for (const auto& mapEntry : it_group->second)
+                        if (mapEntry.second->isActive() && mapEntry.second->hasAccess() && (!mapEntry.second->isHidden())^bOnlyShowHidden && (fragmentLC == "" || getLowercase(mapEntry.first).find(fragmentLC) == 0))
+                            groupList.emplace_back(mapEntry.first, getLowercase(mapEntry.first));
+                }
+
+                // if no shortcut was added, remove the line-break again
+                if (!groupList.empty() && groupList.back().getDisplay() == "\n")
+                    groupList.pop_back();
+
+                return groupList;
+            }
+
+            /**
+                @brief Returns a list of all console commands in a given group.
+                @param fragment The last argument
+                @param group The group's name
+                @param bOnlyShowHidden If true, only hidden console commands are returned
+            */
+            ArgumentCompletionList _subcommands(const std::string& fragment, const std::string& group, bool bOnlyShowHidden)
+            {
+                ArgumentCompletionList commandList;
+
+                std::string groupLC = getLowercase(group);
+
+                // find the iterator of the given group
+                std::map<std::string, std::map<std::string, ConsoleCommand*>>::const_iterator it_group = ConsoleCommandManager::getInstance().getCommands().begin();
+                for ( ; it_group != ConsoleCommandManager::getInstance().getCommands().end(); ++it_group)
+                    if (getLowercase(it_group->first) == groupLC)
+                        break;
+
+                // add all commands in the group to the list
+                if (it_group != ConsoleCommandManager::getInstance().getCommands().end())
+                {
+                    for (const auto& mapEntry : it_group->second)
+                        if (mapEntry.second->isActive() && mapEntry.second->hasAccess() && (!mapEntry.second->isHidden())^bOnlyShowHidden)
+                            commandList.emplace_back(mapEntry.first, getLowercase(mapEntry.first));
+                }
+
+                return commandList;
+            }
+        }
+
+        /**
+            @brief Returns a list of all console command groups AND all console command shortcuts.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(groupsandcommands)(const std::string& fragment)
+        {
+            return detail::_groupsandcommands(fragment, false);
+        }
+
+        /**
+            @brief Returns a list of all console commands in a given group.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(subcommands)(const std::string& fragment, const std::string& group)
+        {
+            return detail::_subcommands(fragment, group, false);
+        }
+
+        /**
+            @brief Returns a list of commands and groups and also supports auto-completion of the arguments of these commands.
+
+            This is a multi-word function, because commands are composed of 1-2 words and additional arguments.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(command)(const std::string& fragment)
+        {
+            CommandEvaluation evaluation = CommandExecutor::evaluate(fragment);
+            const std::string& hint = evaluation.hint();
+
+            if (evaluation.getPossibleArguments().size() > 0 && evaluation.getPossibleArgumentsSize() > 0)
+            {
+                return evaluation.getPossibleArguments();
+            }
+            else
+            {
+                ArgumentCompletionList list;
+                list.emplace_back("", "", hint);
+                return list;
+            }
+        }
+
+        /**
+            @brief Returns a list of hidden commands and groups and also supports auto-completion of the arguments of these commands.
+
+            This is a multi-word function, because commands are composed of 1-2 words and additional arguments.
+
+            This function makes commands visible that would usually be hidden.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(hiddencommand)(const std::string& fragment)
+        {
+            SubString tokens(fragment, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0');
+
+            if (tokens.size() == 0)
+                return detail::_groupsandcommands(fragment, true);
+
+            if (ConsoleCommandManager::getInstance().getCommandLC(getLowercase(tokens[0])))
+                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
+
+            if (tokens.size() == 1)
+            {
+                std::map<std::string, std::map<std::string, ConsoleCommand*>>::const_iterator it_group = ConsoleCommandManager::getInstance().getCommands().find(tokens[0]);
+                if (it_group != ConsoleCommandManager::getInstance().getCommands().end())
+                    return detail::_subcommands(fragment, tokens[0], true);
+                else
+                    return detail::_groupsandcommands(fragment, true);
+            }
+
+            if (ConsoleCommandManager::getInstance().getCommandLC(getLowercase(tokens[0]), getLowercase(tokens[1])))
+                return ARGUMENT_COMPLETION_FUNCTION_CALL(command)(fragment);
+
+            return ArgumentCompletionList();
+        }
+
+        /**
+            @brief Returns possible files and directories and also supports files in arbitrary deeply nested subdirectories.
+
+            This function returns files and directories in the given path. This allows to
+            navigate iteratively through the file system. The first argument @a fragment
+            is used to get the current path.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(files)(const std::string& fragment)
+        {
+            ArgumentCompletionList dirlist;
+            ArgumentCompletionList filelist;
+
+            try
+            {
+                boost::filesystem::path input(fragment);
+                boost::filesystem::path startdirectory(input.branch_path());
+
+                if (!boost::filesystem::exists(startdirectory))
+                {
+                    startdirectory = ".";
+                }
+#ifdef ORXONOX_PLATFORM_WINDOWS
+                else
+                {
+                    const std::string& dir = startdirectory.BF_GENERIC_STRING();
+                    if (dir.size() > 0 && dir[dir.size() - 1] == ':')
+                        startdirectory = dir + '/';
+                }
+#endif
+
+                boost::filesystem::directory_iterator file(startdirectory);
+                boost::filesystem::directory_iterator end;
+
+                while (file != end)
+                {
+                    if (boost::filesystem::is_directory(*file))
+                        dirlist.emplace_back(file->BF_DICTIONARY_ENTRY_NAME() + '/', getLowercase(file->BF_DICTIONARY_ENTRY_NAME()) + '/', file->BF_LEAF() + '/');
+                    else
+                        filelist.emplace_back(file->BF_DICTIONARY_ENTRY_NAME(), getLowercase(file->BF_DICTIONARY_ENTRY_NAME()), file->BF_LEAF());
+                    ++file;
+                }
+            }
+            catch (...) {}
+
+            filelist.insert(filelist.begin(), dirlist.begin(), dirlist.end());
+            return filelist;
+        }
+
+        /**
+            @brief Returns the sections of the config file.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingssections)()
+        {
+            ArgumentCompletionList sectionList;
+
+            const std::set<std::string>& names = SettingsConfigFile::getInstance().getSectionNames();
+            for (const std::string& name : names)
+                sectionList.emplace_back(name, getLowercase(name));
+
+            return sectionList;
+        }
+
+        /**
+            @brief Returns the entries in a given section of the config file.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsentries)(const std::string& fragment, const std::string& section)
+        {
+            ArgumentCompletionList entryList;
+            SettingsConfigFile& settings = SettingsConfigFile::getInstance();
+            const std::string& sectionLC = getLowercase(section);
+
+            SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
+            for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
+                entryList.emplace_back(it->second.second->getName(), it->second.first);
+
+            return entryList;
+        }
+
+        /**
+            @brief Returns the current value of a given value in a given section of the config file.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section)
+        {
+            ArgumentCompletionList oldValue;
+            SettingsConfigFile& settings = SettingsConfigFile::getInstance();
+            const std::string& sectionLC = getLowercase(section);
+            const std::string& entryLC = getLowercase(entry);
+
+            SettingsConfigFile::ContainerMap::const_iterator upper = settings.getContainerUpperBound(sectionLC);
+            for (SettingsConfigFile::ContainerMap::const_iterator it = settings.getContainerLowerBound(sectionLC); it != upper; ++it)
+            {
+                if (it->second.first == entryLC)
+                {
+                    const std::string& valuestring = it->second.second->toString();
+                    oldValue.emplace_back(valuestring, getLowercase(valuestring), "Old value: " + valuestring);
+                }
+            }
+
+            return oldValue;
+        }
+
+        /**
+            @brief Returns a list of indexes of the available Tcl threads (see TclThreadManager).
+        */
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(tclthreads)()
+        {
+            std::list<unsigned int> threadnumbers = TclThreadManager::getInstance().getThreadList();
+            ArgumentCompletionList threads;
+
+            for (unsigned int threadnumber : threadnumbers)
+                threads.emplace_back(multi_cast<std::string>(threadnumber));
+
+            return threads;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionFunctions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionFunctions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionFunctions.h	(revision 11817)
@@ -0,0 +1,211 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ArgumentCompletion
+    @brief Declaration of all argument completion functions and macros used to define them.
+
+    @anchor ArgumentCompletionExample
+
+    Argument completion functions are used to create a list of possible arguments
+    for an orxonox::ConsoleCommand. These functions are usually wrapped by an instance
+    of orxonox::ArgumentCompleter.
+
+    Argument completion functions can be declared and implemented by using the macros
+    ARGUMENT_COMPLETION_FUNCTION_DECLARATION() and ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION()
+    respectively. They are necessary because they don't simply define the function, but they also
+    create a static helper function that returns an instance of orxonox::ArgumentCompleter which
+    wraps the defined function. This allows easier referencing of argument completion functions
+    by simply calling autocompletion::functionname().
+
+    Argument completion functions can take up to 5 arguments, all of type std::string.
+    The first argument is always the current argument which is being entered by the user
+    in the shell. The second argument is the argument before, so in fact arguments from
+    the shell are sent in reversed order to the argument completion function. This is
+    necessary because the number of arguments can be variable
+
+    Example: The user types the following into the shell:
+    @code
+    $ commandname argument1 argument2 argum
+    @endcode
+    Then he presses the @a tab key to print the possible arguments. Now the argument
+    completion function for the @a third argument of @a commandname will be called in
+    the following way:
+    @code
+    list = argcompfunction3("argum", "argument2", "argument1");
+    @endcode
+
+    Usually each argument is one word (without whitespaces in it), but some argument completion
+    functions need more than one word. This can be achieved by using ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI().
+    In this case all supernumerous words are passed to the first (!) argument.
+
+    An example to show how to declare, implement, and use an argument completion function:
+    @code
+    // ArgumentCompletionFunctions.h:
+    // ------------------------------
+
+    // Declaration of the function:
+    ARGUMENT_COMPLETION_FUNCTION_DECLARATION(month)(const std::string& fragment);
+
+    // ArgumentCompletionFunctions.cc:
+    // -------------------------------
+
+    // Implementation of the function
+    ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(month)(const std::string& fragment)
+    {
+        ArgumentCompletionList list;
+
+        // check if the first part of the argument is a number - if yes, the user likely wants to enter the month as a number
+        if (isNumber(fragment))
+        {
+            for (int month = 1; month <= 12; ++month)
+                list.emplace_back(multi_cast<std::string>(month));
+        }
+        else
+        {
+            list.emplace_back("January",   "january");
+            list.emplace_back("February",  "february");
+            list.emplace_back("March",     "march");
+            list.emplace_back("April",     "april");
+            list.emplace_back("May",       "may");
+            list.emplace_back("June",      "june");
+            list.emplace_back("July",      "july");
+            list.emplace_back("August",    "august");
+            list.emplace_back("September", "september");
+            list.emplace_back("October",   "october");
+            list.emplace_back("November",  "november");
+            list.emplace_back("December",  "december");
+        }
+
+        return list;
+    }
+
+    // SomeFile:
+    // ---------
+
+    // A class to manage the date:
+    class Date
+    {
+        public:
+            static void setDate(int day, const std::string& month, int year);
+    };
+
+    // Define a console command that needs a date. Add argument completion for the month:
+    SetConsoleCommand("setDate", &Date::setDate).argumentCompleter(1, autocompletion::month());
+    @endcode
+
+    This example defines an argument completion function that returns a list of possible
+    months. If the first part of the argument is a number, it returns the numbers 1-12,
+    otherwise the name of the months are returned. Note how the list is composed by
+    instances of orxonox::ArgumentCompletionListElement. For the name of the months,
+    two strings are provided, one in normal case and one in lower case. See the documentation
+    of orxonox::ArgumentCompletionListElement for more information about this.
+
+    Also note that the argument completion list is assigned to the console command by using
+    @ref orxonox::ConsoleCommand::argumentCompleter "argumentCompleter()". The first argument
+    is the index of the argument:
+     - 0 is the first argument (@a day)
+     - 1 is the second argument (@a month)
+     - 2 is the third argument (@a year)
+
+    @a day and @a year don't need an argument completion function as they are just integers.
+
+    The function @c autocompletion::month() is automatically created by the macros
+    ARGUMENT_COMPLETION_FUNCTION_DECLARATION() and ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION()
+    and returns an orxonox::ArgumentCompleter that wraps the defined argument completion function.
+
+    The implemented argument completion function uses only one argument, the fragment of the
+    currently entered argument. More complex functions can also use the previous arguments
+    to return different arguments depending on the other arguments (for example to list the
+    members of a class, where the class-name is the first argument and the member the second).
+*/
+
+#ifndef _ArgumentCompletionFunctions_H__
+#define _ArgumentCompletionFunctions_H__
+
+#include "core/CorePrereqs.h"
+#include "ArgumentCompleter.h"
+
+/**
+    @brief Used to declare an argument completion function with name @a functionname.
+    @param functionname The name of the function, will also be used for the implementation of the function.
+
+    The macro also defines a static function that returns an orxonox::ArgumentCompleter
+    which wraps the defined function. This can be accessed by calling autocompletion::functionname();
+*/
+#define ARGUMENT_COMPLETION_FUNCTION_DECLARATION(functionname) \
+    ArgumentCompleter* functionname(); \
+    ArgumentCompletionList acf_##functionname
+
+/**
+    @brief Used to implement an argument completion function.
+    @param functionname The name of the function
+*/
+#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(functionname) \
+    _ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_INTERNAL(functionname, false)
+
+/**
+    @brief Used to implement an argument completion function which allows multiple words.
+    @param functionname The name of the function
+*/
+#define ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_MULTI(functionname) \
+    _ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_INTERNAL(functionname, true)
+
+/// Internal macro
+#define _ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION_INTERNAL(functionname, bUseMultipleWords) \
+    ArgumentCompleter* functionname() \
+    { \
+        static ArgumentCompleter completer = ArgumentCompleter(&acf_##functionname, bUseMultipleWords); \
+        return &completer; \
+    } \
+    \
+    ArgumentCompletionList acf_##functionname
+
+/// Calls an argument completion function. Used for functions that return the results of another argument completion function.
+#define ARGUMENT_COMPLETION_FUNCTION_CALL(functionname) acf_##functionname
+
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(fallback)();
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(groupsandcommands)(const std::string& fragment);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(subcommands)(const std::string& fragment, const std::string& group);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(command)(const std::string& fragment);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(hiddencommand)(const std::string& fragment);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(files)(const std::string& fragment);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingssections)();
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingsentries)(const std::string& fragment, const std::string& section);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(settingsvalue)(const std::string& fragment, const std::string& entry, const std::string& section);
+        _CoreExport ARGUMENT_COMPLETION_FUNCTION_DECLARATION(tclthreads)();
+    }
+}
+
+#endif /* _ArgumentCompletionFunctions_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionListElement.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionListElement.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ArgumentCompletionListElement.h	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ArgumentCompletion
+    @brief Definition of ArgumentCompletionList, which is  used in @ref ArgumentCompletionFunctions.h "argument completion functions", and its element.
+*/
+
+#ifndef _ArgumentCompletionListElement_H__
+#define _ArgumentCompletionListElement_H__
+
+#include "core/CorePrereqs.h"
+
+#include <list>
+#include <string>
+
+namespace orxonox
+{
+    const int ACL_MODE_NORMAL     = 1;  ///< A flag, used if there's a normal string
+    const int ACL_MODE_COMPARABLE = 2;  ///< A flag, used if there's a different string used to compare
+    const int ACL_MODE_DISPLAY    = 4;  ///< A flag, used if there's a different string used to be displayed
+
+    typedef std::list<ArgumentCompletionListElement> ArgumentCompletionList;
+
+    /**
+        @brief This class is used in argument completion lists and contains up to three different strings, used in different situations.
+
+        A list containing elements of type ArgumentCompletionListElement is returned by
+        an @ref ArgumentCompletionFunctions.h "argument completion function". These elements
+        are composed of up to three strings with different usage:
+         - normal: What is used as the actual argument
+         - comparable: What is used to compere the argument to the input of the user (usually lowercase, except for case-sensitive arguments)
+         - display: This is displayed in the list of possible arguments - can differ from what is actually used for better readability
+
+        @remarks An element with an empty ("") 'comparable' string will be ignored by the argument
+        completion algorithms, but it's 'display' string will still be printed in the list. This
+        can be used to add additional information, whitespaces, linebreaks or whatever is needed
+        to format the output.
+    */
+    class _CoreExport ArgumentCompletionListElement
+    {
+        public:
+            /// Constructor: Normal, comparable, and display string are all the same.
+            ArgumentCompletionListElement(const std::string& normalcase) : mode_(ACL_MODE_NORMAL), normal_(normalcase) {}
+            /// Constructor: Normal and display string are the same, a different (usually lowercase) string is used for comparison.
+            ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase) : mode_(ACL_MODE_NORMAL | ACL_MODE_COMPARABLE), normal_(normalcase), comparable_(lowercase) {}
+            /// Constructor: Normal, comparable, and display are all different strings.
+            ArgumentCompletionListElement(const std::string& normalcase, const std::string& lowercase, const std::string& display) : mode_(ACL_MODE_NORMAL | ACL_MODE_COMPARABLE | ACL_MODE_DISPLAY), normal_(normalcase), comparable_(lowercase), display_(display) {}
+
+            /// Returns the normal string which is used as the actual argument.
+            const std::string& getString() const
+                { return this->normal_; }
+            /// Returns the comparable string which is used to compare arguments and user input
+            const std::string& getComparable() const
+                { return (this->mode_ & ACL_MODE_COMPARABLE) ? this->comparable_ : this->normal_; }
+            /// Returns the display string which is used in the displayed list of possible arguments
+            const std::string& getDisplay() const
+                { return (this->mode_ & ACL_MODE_DISPLAY) ? this->display_ : this->normal_; }
+
+            /// Returns true if there's a different string for comparison.
+            bool hasComparable() const
+                { return (this->mode_ & ACL_MODE_COMPARABLE); }
+            /// Returns true if there's a different string to display.
+            bool hasDisplay() const
+                { return (this->mode_ & ACL_MODE_DISPLAY); }
+
+            /// Overloaded operator for usage in maps and sets.
+            bool operator<(const ArgumentCompletionListElement& other) const
+                { return (this->getComparable() < other.getComparable()); }
+
+        private:
+            unsigned char mode_;        ///< The flags
+            std::string normal_;        ///< The normal string
+            std::string comparable_;    ///< The comparable (usually lowercase) string
+            std::string display_;       ///< The string to display
+    };
+}
+
+#endif /* _ArgumentCompletionListElement_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,13 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  CommandEvaluation.cc
+  CommandExecutor.cc
+  ConsoleCommand.cc
+  ConsoleCommandCompilation.cc
+  ConsoleCommandIncludes.cc
+  ConsoleCommandManager.cc
+  Executor.cc
+  IOConsole.cc
+  IRC.cc
+  Shell.cc
+  TclBind.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/CommandEvaluation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/CommandEvaluation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/CommandEvaluation.cc	(revision 11817)
@@ -0,0 +1,609 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of CommandEvaluation
+*/
+
+#include "CommandEvaluation.h"
+
+#include "util/StringUtils.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommand.h"
+#include "ConsoleCommandManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: Initializes the command evaluation with an empty command.
+    */
+    CommandEvaluation::CommandEvaluation()
+    {
+        this->initialize("");
+    }
+
+    /**
+        @brief Initializes all values.
+    */
+    void CommandEvaluation::initialize(const std::string& command)
+    {
+        this->execCommand_ = nullptr;
+        this->hintCommand_ = nullptr;
+        this->string_ = command;
+        this->execArgumentsOffset_ = 0;
+        this->hintArgumentsOffset_ = 0;
+        this->bPossibleArgumentsRetrieved_ = false;
+        this->possibleArguments_.clear();
+        this->bEvaluatedArguments_ = false;
+        this->bTriedToEvaluatedArguments_ = false;
+        this->numberOfEvaluatedArguments_ = 0;
+
+        // split the command into tokens
+        this->tokens_.split(command, " ", SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0');
+    }
+
+    /**
+        @brief Returns the number of tokens according to the definition of CommandExecutor (which counts also an empty argument at the end of the string).
+    */
+    unsigned int CommandEvaluation::getNumberOfArguments() const
+    {
+        unsigned int count = this->tokens_.size();
+
+        // If the last char in the string is a space character (or the string is empty), add +1 to the number of tokens, because this counts as an additional (but empty) argument
+        if (count == 0 || this->string_[this->string_.size() - 1] == ' ')
+            return count + 1;
+        else
+            return count;
+    }
+
+    /**
+        @brief Returns the last argument (which is the one the user currently enters into the shell).
+    */
+    const std::string& CommandEvaluation::getLastArgument() const
+    {
+        // the string is empty or ends with a space character, the user is just about to enter a new argument (but its still empty). return a blank string in this case.
+        if (this->tokens_.size() == 0 || this->string_[this->string_.size() - 1] == ' ')
+            return BLANKSTRING;
+        else
+            return this->tokens_.back();
+    }
+
+    /**
+        @brief Returns the token with the given index (or a blank string if it doesn't exist).
+    */
+    const std::string& CommandEvaluation::getToken(unsigned int i) const
+    {
+        if (i < this->tokens_.size())
+            return this->tokens_[i];
+        else
+            return BLANKSTRING;
+    }
+
+    /**
+        @brief Executes the command which was evaluated by this object.
+        @return Returns the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+    */
+    int CommandEvaluation::execute()
+    {
+        int error;
+        this->query(&error);
+        return error;
+    }
+
+    /**
+        @brief Executes the command which was evaluated by this object and returns its return-value.
+        @param error A pointer to an integer (or nullptr) which will be used to write error codes to (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+        @return Returns the result of the command (or MultiType::Null if there is no return value)
+    */
+    MultiType CommandEvaluation::query(int* error)
+    {
+        // check if an error value was passed by reference
+        if (error)
+        {
+            // Determine the error-code and return if it is not Success
+
+            *error = CommandExecutor::Success;
+
+            if (!this->execCommand_)
+                *error = CommandExecutor::Inexistent;
+            else if (!this->execCommand_->isActive())
+                *error = CommandExecutor::Deactivated;
+            else if (!this->execCommand_->hasAccess())
+                *error = CommandExecutor::Denied;
+
+            if (*error != CommandExecutor::Success)
+                return MultiType::Null;
+        }
+
+        // check if it's possible to execute the command
+        if (this->execCommand_ && this->execCommand_->isActive() && this->execCommand_->hasAccess())
+        {
+            // if the arguments weren't evaluated yet, do it now.
+            if (!this->bTriedToEvaluatedArguments_)
+                this->evaluateArguments(false);
+
+            // check if the argument evaluation succeded
+            if (this->bEvaluatedArguments_)
+            {
+                orxout(verbose, context::commands) << "CE_execute (evaluation): " << this->execCommand_->getName() << " with " << this->numberOfEvaluatedArguments_ << " arguments: " << this->arguments_[0] << ' ' << this->arguments_[1] << ' ' << this->arguments_[2] << ' ' << this->arguments_[3] << ' ' << this->arguments_[4] << endl;
+
+                // pass as many arguments to the executor as were evaluated (thus the executor can still use additional default values)
+                switch (this->numberOfEvaluatedArguments_)
+                {
+                    case 0:  return (*this->execCommand_->getExecutor())();
+                    case 1:  return (*this->execCommand_->getExecutor())(this->arguments_[0]);
+                    case 2:  return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1]);
+                    case 3:  return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1], this->arguments_[2]);
+                    case 4:  return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1], this->arguments_[2], this->arguments_[3]);
+                    case 5:
+                    default: return (*this->execCommand_->getExecutor())(this->arguments_[0], this->arguments_[1], this->arguments_[2], this->arguments_[3], this->arguments_[4]);
+                }
+            }
+            else if (error)
+                *error = CommandExecutor::Incomplete;
+        }
+
+        // return a null value in case of an error
+        return MultiType::Null;
+    }
+
+    /**
+        @brief Evaluates the arguments of the command.
+        @param bPrintError If true, the function prints an error message if it doesn't succeed
+        @return Returns the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+    */
+    int CommandEvaluation::evaluateArguments(bool bPrintError)
+    {
+        this->bTriedToEvaluatedArguments_ = true;
+
+        // check if there's a command to execute
+        if (!this->execCommand_)
+        {
+            if (bPrintError)
+                orxout(internal_error, context::commands) << "Can't evaluate arguments, no console command assigned." << endl;
+            return CommandExecutor::Inexistent;
+        }
+
+        int error;
+
+        // try to evaluate the arguments using the executor of the evaluated command.
+        // the arguments are currently stored as strings in token_, but afterwards they will be converted to the right type and stored in arguments_
+        this->numberOfEvaluatedArguments_ = this->execCommand_->getExecutor()->evaluateArguments(this->tokens_.subSet(this->execArgumentsOffset_), this->arguments_, &error, " ");
+
+        // check if an error occurred
+        if (!error)
+            this->bEvaluatedArguments_ = true;
+        else if (bPrintError)
+            orxout(internal_error, context::commands) << "Can't evaluate arguments, not enough arguments given." << endl;
+
+        return error;
+    }
+
+    /**
+        @brief Replaces an evaluated argument with a new value.
+        @param index The index of the parameter (the first argument has index 0)
+        @param arg The new value of the parameter
+    */
+    void CommandEvaluation::setEvaluatedArgument(unsigned int index, const MultiType& arg)
+    {
+        if (index < MAX_FUNCTOR_ARGUMENTS)
+            this->arguments_[index] = arg;
+    }
+
+    /**
+        @brief Returns the evaluated argument with given index.
+        @param index The index of the argument (the first argument has index 0)
+    */
+    MultiType CommandEvaluation::getEvaluatedArgument(unsigned int index) const
+    {
+        if (index < MAX_FUNCTOR_ARGUMENTS)
+            return this->arguments_[index];
+
+        return MultiType::Null;
+    }
+
+    /**
+        @brief Completes the given command string using the list of possible arguments.
+        @return Returns the completed command string
+
+        This is called by the shell if the user presses the @a tab key. The currently entered
+        argument will be completed as good as possible by using the argument completion list
+        of the evaluated command.
+    */
+    std::string CommandEvaluation::complete()
+    {
+        // check if it's possible to complete the command
+        if (!this->hintCommand_ || !this->hintCommand_->isActive())
+            return this->string_;
+
+        // get the list of possible arguments
+        if (!this->bPossibleArgumentsRetrieved_)
+            this->retrievePossibleArguments();
+
+        // if the list is empty, return the current command string
+        if (CommandEvaluation::getSize(this->possibleArguments_) == 0)
+        {
+            return this->string_;
+        }
+        else
+        {
+            // get the first part of the command string from the beginning up to the last space character
+            std::string output = this->string_.substr(0, this->string_.find_last_of(' ') + 1);
+
+            // add the common begin of all possible arguments
+            output += CommandEvaluation::getCommonBegin(this->possibleArguments_);
+
+            // return the resulting string
+            return output;
+        }
+    }
+
+    /**
+        @brief Returns a string containing hints or possible arguments for the evaluated command.
+
+        This is called by the shell if the user presses the @a tab key. It prints a list of
+        possible arguments or other hints, returned by the argument completion list of the
+        evaluated command. If there's no such list, the syntax of the command is returned.
+    */
+    std::string CommandEvaluation::hint()
+    {
+        // check if it's possible to get hints for this command
+        if (!this->hintCommand_ || !this->hintCommand_->isActive())
+            return "";
+
+        // get the list of possible arguments
+        if (!this->bPossibleArgumentsRetrieved_)
+            this->retrievePossibleArguments();
+
+        // return the list of possible arguments if:
+        //   a) it contains at least one non-empty argument
+        //   b) it contains an entry that may be empty (not an actual argument, just a helping text) AND the command is valid
+        if (CommandEvaluation::getSize(this->possibleArguments_) > 0 || (!this->possibleArguments_.empty() && this->isValid()))
+            return CommandEvaluation::dump(this->possibleArguments_);
+
+        // at this point there's no valid argument in the list, so check if the command is actually valid
+        if (this->isValid())
+        {
+            // yes it is - return the syntax of the command
+            return CommandEvaluation::dump(this->hintCommand_);
+        }
+        else
+        {
+            // no the command is not valid
+            if (this->getNumberOfArguments() > 2)
+            {
+                // the user typed 2+ arguments, but they don't name a command - print an error
+                return std::string("Error: There is no command with name \"") + this->getToken(0) + " " + this->getToken(1) + "\".";
+            }
+            else
+            {
+                // the user typed 1-2 arguments, check what he tried to type and print a suitable error
+                std::string groupLC = getLowercase(this->getToken(0));
+                for (const auto& mapEntry : ConsoleCommandManager::getInstance().getCommandsLC())
+                    if (mapEntry.first == groupLC)
+                        return std::string("Error: There is no command in group \"") + this->getToken(0) + "\" starting with \"" + this->getToken(1) + "\".";
+
+                return std::string("Error: There is no command starting with \"") + this->getToken(0) + "\".";
+            }
+        }
+    }
+
+    /**
+        @brief If the command couln't be evaluated because it doesn't exist, print a suggestion for
+        a command that looks close to the entered command (useful if the user mistyped the command).
+    */
+    std::string CommandEvaluation::getCommandSuggestion() const
+    {
+        std::string token0_LC = getLowercase(this->getToken(0));
+        std::string token1_LC = getLowercase(this->getToken(1));
+
+        std::string nearestCommand;
+        unsigned int nearestDistance = (unsigned int)-1;
+
+        // iterate through all groups and their commands and calculate the distance to the current command. keep the best.
+        for (const auto& mapEntryGroup : ConsoleCommandManager::getInstance().getCommandsLC())
+        {
+            if (mapEntryGroup.first != "")
+            {
+                for (const auto& mapEntryName : mapEntryGroup.second)
+                {
+                    std::string command = mapEntryGroup.first + " " + mapEntryName.first;
+                    unsigned int distance = getLevenshteinDistance(command, token0_LC + " " + token1_LC);
+                    if (distance < nearestDistance)
+                    {
+                        nearestCommand = command;
+                        nearestDistance = distance;
+                    }
+                }
+            }
+        }
+
+        // now also iterate through all shortcuts and keep the best if it's better than the one found above.
+        std::map<std::string, std::map<std::string, ConsoleCommand*>>::const_iterator it_group = ConsoleCommandManager::getInstance().getCommandsLC().find("");
+        if (it_group !=  ConsoleCommandManager::getInstance().getCommandsLC().end())
+        {
+            for (const auto& mapEntry : it_group->second)
+            {
+                std::string command = mapEntry.first;
+                unsigned int distance = getLevenshteinDistance(command, token0_LC);
+                if (distance < nearestDistance)
+                {
+                    nearestCommand = command;
+                    nearestDistance = distance;
+                }
+            }
+        }
+
+        // return the command that's closest to the current one.
+        return nearestCommand;
+    }
+
+    /**
+        @brief Gets the possible arguments for the command in its current state.
+    */
+    void CommandEvaluation::retrievePossibleArguments()
+    {
+        this->bPossibleArgumentsRetrieved_ = true;
+
+        // we use the hintCommand_ to get possible arguments. get the index of the last argument. limit the index if its greater than the number of arguments supported by the command.
+        unsigned int argumentID = std::min(this->getNumberOfArguments() - this->hintArgumentsOffset_, this->hintCommand_->getExecutor()->getParamCount());
+
+        // get the argument completer for the given argument index
+        ArgumentCompleter* ac = this->hintCommand_->getArgumentCompleter(argumentID - 1);
+
+        // check if an argument completer exists
+        if (ac)
+        {
+            MultiType arg[MAX_FUNCTOR_ARGUMENTS];
+
+            // the index of the last argument in the command string that is supported by this argument completer
+            size_t max = this->hintArgumentsOffset_ + this->hintCommand_->getExecutor()->getParamCount();
+
+            // write the argument strings to the argument array (in reversed order, as required by the argument completion function)
+            for (size_t i = 0; i < argumentID; ++i)
+                arg[i] = this->getToken(std::min(this->getNumberOfArguments(), (unsigned int)max) - i - 1);
+
+            // check if there are more arguments given by the user than supported
+            if (this->getNumberOfArguments() > max)
+            {
+                // yes - now check if multiple words are supported by the argument completer
+                if (ac->useMultipleWords())
+                {
+                    // yes - join the surplus arguments
+                    std::string surplusArguments = this->tokens_.subSet(max - 1).join();
+                    if (this->string_[this->string_.size() - 1] == ' ')
+                        surplusArguments += ' ';
+
+                    // pass all surplus arguments as the first argument to the argument completer
+                    this->possibleArguments_ = (*ac)(surplusArguments, arg[1], arg[2], arg[3], arg[4]);
+
+                    // strip the list using the last argument
+                    CommandEvaluation::strip(this->possibleArguments_, this->getToken(this->getNumberOfArguments() - 1));
+                }
+                else
+                {
+                    // no - the user typed more arguments than supported, no action
+                }
+            }
+            else
+            {
+                // no - so simply call the argument completer and get the list of arguments
+                this->possibleArguments_ = (*ac)(arg[0], arg[1], arg[2], arg[3], arg[4]);
+
+                // strip the list using the last argument (stored arg[0])
+                CommandEvaluation::strip(this->possibleArguments_, arg[0]);
+            }
+        }
+    }
+
+    /**
+        @brief Returns the size of an argument completion list - empty ("") arguments are not counted.
+    */
+    /* static */ size_t CommandEvaluation::getSize(const ArgumentCompletionList& list)
+    {
+        size_t count = 0;
+        for (const ArgumentCompletionListElement& element : list)
+            if (element.getComparable() != "")
+                ++count;
+        return count;
+    }
+
+    /**
+        @brief Removes all elements from the list that don't start with @a fragment.
+        @param list The argument completion list
+        @param fragment The argument that is currently entered by the user and that needs to be completed
+    */
+    /* static */ void CommandEvaluation::strip(ArgumentCompletionList& list, const std::string& fragment)
+    {
+        std::string fragmentLC = getLowercase(fragment);
+
+        // iterate through the list
+        for (ArgumentCompletionList::iterator it = list.begin(); it != list.end(); )
+        {
+            const std::string& entry = it->getComparable();
+
+            // check if the argument is empty - if yes, keep it always in the list
+            if (entry == "")
+            {
+                ++it;
+                continue;
+            }
+
+            // check the length of the argument - arguments smaller than 'fragment' are always erased
+            if (entry.size() < fragmentLC.size())
+            {
+                list.erase(it++);
+            }
+            else
+            {
+                // compare the argument char by char with 'fragment'
+                bool bErase = false;
+                for (size_t i = 0; i < fragmentLC.size(); ++i)
+                {
+                    if (fragmentLC[i] != entry[i])
+                    {
+                        bErase = true;
+                        break;
+                    }
+                }
+
+                if (bErase)
+                    list.erase(it++);
+                else
+                    ++it;
+            }
+        }
+    }
+
+    /**
+        @brief Returns the commond begin of all arguments in the list.
+    */
+    /* static */ std::string CommandEvaluation::getCommonBegin(const ArgumentCompletionList& list)
+    {
+        if (CommandEvaluation::getSize(list) == 0)
+        {
+            // no (non-empty) values in the list, return an empty string
+            return "";
+        }
+        else if (CommandEvaluation::getSize(list) == 1)
+        {
+            // only one (non-empty) value in the list - search it and return it
+            for (const ArgumentCompletionListElement& element : list)
+            {
+                if (element.getComparable() != "")
+                {
+                    // arguments that have a separate string to be displayed need a little more care - just return them without modification. add a space character to the others.
+                    if (element.hasDisplay())
+                        return (element.getString());
+                    else
+                        return (element.getString() + ' ');
+                }
+            }
+
+            return "";
+        }
+        else
+        {
+            // multiple arguments in the list - iterate through it and find the common begin of all arguments
+            std::string output;
+            for (unsigned int i = 0; true; i++)
+            {
+                char tempComparable = '\0';
+                char temp = '\0';
+                for (const ArgumentCompletionListElement& element : list)
+                {
+                    const std::string& argumentComparable = element.getComparable();
+                    const std::string& argument = element.getString();
+
+                    // ignore empty arguments
+                    if (argumentComparable == "")
+                        continue;
+
+                    if (argument.size() > i)
+                    {
+                        if (tempComparable == '\0')
+                        {
+                            // the first entry is always taken
+                            tempComparable = argumentComparable[i];
+                            temp = argument[i];
+                        }
+                        else
+                        {
+                            // all other entries need comparison to the first entry
+                            if (tempComparable != argumentComparable[i])
+                                return output;
+                            else if (temp != argument[i]) // the comparables match, but the normal chars don't - switch to comparable only
+                                temp = tempComparable;
+                        }
+                    }
+                    else
+                    {
+                        return output;
+                    }
+                }
+                output += temp;
+            }
+            return output;
+        }
+    }
+
+    /**
+        @brief Joins the elements of the given list to a string.
+    */
+    /* static */ std::string CommandEvaluation::dump(const ArgumentCompletionList& list)
+    {
+        std::string output;
+        for (const ArgumentCompletionListElement& element : list)
+        {
+            output += element.getDisplay();
+
+            // add a space character between two elements for all non-empty arguments
+            if (element.getComparable() != "")
+                output += ' ';
+        }
+        return output;
+    }
+
+    /**
+        @brief Returns a string that explains the syntax of the given command.
+    */
+    /* static */ std::string CommandEvaluation::dump(const ConsoleCommand* command)
+    {
+        // get the name of the command
+        std::string output = command->getName();
+
+        // check if there are parameters
+        if (command->getExecutor()->getParamCount() > 0)
+            output += ": ";
+
+        // iterate through the parameters
+        for (unsigned int i = 0; i < command->getExecutor()->getParamCount(); i++)
+        {
+            // separate the parameters with a space character
+            if (i != 0)
+                output += ' ';
+
+            // print default values in [], others in {} braces
+            if (command->getExecutor()->defaultValueSet(i))
+                output += '[';
+            else
+                output += '{';
+
+            // add the type-name of the parameter
+            output += command->getExecutor()->getTypenameParam(i);
+
+            // print the default value if available
+            if (command->getExecutor()->defaultValueSet(i))
+                output += '=' + command->getExecutor()->getDefaultValue(i).get<std::string>() + ']';
+            else
+                output += '}';
+        }
+        return output;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/CommandEvaluation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/CommandEvaluation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/CommandEvaluation.h	(revision 11817)
@@ -0,0 +1,155 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup CommandExecEval Command execution and evaluation
+    @ingroup Command
+*/
+
+/**
+    @file
+    @ingroup Command CommandExecEval
+    @brief Declaration of the orxonox::CommandEvaluation class which is returned by orxonox::CommandExecutor::evaluate().
+
+    The orxonox::CommandEvaluation class gathers all information about a command-string. It is used
+    internally by orxonox::CommandExecutor and can also be returned by it to provide more information
+    about a command. It's also possible to evaluate the arguments of a command to execute it faster.
+
+    @see See @ref CommandExecutorExample "this description" for an example.
+*/
+
+#ifndef _CommandEvaluation_H__
+#define _CommandEvaluation_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+
+#include "util/SubString.h"
+#include "util/MultiType.h"
+#include "ArgumentCompletionListElement.h"
+#include "Functor.h"
+
+namespace orxonox
+{
+    /**
+        @brief CommandEvaluation is used to gather information about a command and to evaluate its arguments
+
+        This class provides several information about a command-string, for example the
+        evaluated ConsoleCommand, but also other information like hints if the command
+        is not yet finished.
+
+        @note You don't have to call evaluateArguments() manually, it's also done automatically
+        if you call the command the first time. However you can of course do it at any earlier
+        time, for example to return an error message if it doesn't work.
+
+        @remarks execCommand_ and hintCommand_ can be different in this case: There are multiple
+        commands avaliable, let's say "tcl" and "TclThreadManager". The user enters "tcl", which
+        is already a valid command. Now execCommand_ points to the "tcl"-command, but hintCommand_
+        still points to the autocompletion command of CommandExecutor, because the auto-completion
+        list must still return the two possible commands, "tcl TclThreadManager" because the user
+        may want to write "TclThreadManager ..." and needs auto-completion.
+
+        @see See @ref CommandExecutorExample "this description" for an example.
+    */
+    class _CoreExport CommandEvaluation
+    {
+        friend class CommandExecutor;
+
+        public:
+            CommandEvaluation();
+
+            int execute();
+            MultiType query(int* error = nullptr);
+
+            std::string complete();
+            std::string hint();
+
+            std::string getCommandSuggestion() const;
+
+            int evaluateArguments(bool bPrintError = false);
+
+            /// Returns true if the command evaluation contains a valid command that can be executed.
+            inline bool isValid() const
+                { return (this->execCommand_ != nullptr); }
+
+            /// Returns the console command that was evaluated by this object.
+            inline const ConsoleCommand* getConsoleCommand() const
+                { return this->execCommand_; }
+
+            void setEvaluatedArgument(unsigned int index, const MultiType& arg);
+            MultiType getEvaluatedArgument(unsigned int index) const;
+
+            /**
+                @brief Returns a list of possible arguments for the given command.
+
+                Note that the command's arguments may not be complete yet, so in this case
+                this list returns the possibilities. They can then be used to display a list
+                of the possible arguments or to apply auto-completion.
+            */
+            const ArgumentCompletionList& getPossibleArguments() const
+                { return this->possibleArguments_; }
+
+            /// Returns the number of possible arguments. Empty ("") arguments are not counted.
+            size_t getPossibleArgumentsSize() const
+                { return CommandEvaluation::getSize(this->possibleArguments_); }
+
+        private:
+            void initialize(const std::string& command);
+
+            unsigned int getNumberOfArguments() const;
+            const std::string& getLastArgument() const;
+            const std::string& getToken(unsigned int i) const;
+
+            void retrievePossibleArguments();
+
+            static void strip(ArgumentCompletionList& list, const std::string& fragment);
+            static size_t getSize(const ArgumentCompletionList& list);
+
+            static std::string dump(const ArgumentCompletionList& list);
+            static std::string dump(const ConsoleCommand* command);
+
+            static std::string getCommonBegin(const ArgumentCompletionList& list);
+
+            const ConsoleCommand* execCommand_;             ///< The command that will be executed (can be nullptr if the command is not valid)
+            const ConsoleCommand* hintCommand_;             ///< The command that is used to display hints and argument lists (can be different to execCommand_ in some cases)
+            SubString tokens_;                              ///< The single words of the command string, split into tokens
+            std::string string_;                            ///< The original command string, entered by the user in the shell
+            unsigned int execArgumentsOffset_;              ///< The index of the first argument in tokens_ used to execute the command
+            unsigned int hintArgumentsOffset_;              ///< The index of the first argument in tokens_ used to display hints and argument lists
+            bool bPossibleArgumentsRetrieved_;              ///< True if the list of possible arguments was already retrieved
+            ArgumentCompletionList possibleArguments_;      ///< List of possible arguments for the command in the current state
+
+            bool bEvaluatedArguments_;                      ///< True if the arguments of the command have been evaluated (and stored in arguments_)
+            bool bTriedToEvaluatedArguments_;               ///< True if an attempt was started to evaluate the arguments (but not necessarily successful)
+            unsigned int numberOfEvaluatedArguments_;       ///< The number of evaluated arguments (ranges from 0 to MAX_FUNCTOR_ARGUMENTS)
+            MultiType arguments_[MAX_FUNCTOR_ARGUMENTS];    ///< The evaluated arguments (the arguments from string_ or tokens_ converted to the right type)
+    };
+}
+
+#endif /* _CommandEvaluation_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/CommandExecutor.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/CommandExecutor.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/CommandExecutor.cc	(revision 11817)
@@ -0,0 +1,308 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of CommandExecutor
+*/
+
+#include "CommandExecutor.h"
+
+#include "ConsoleCommandIncludes.h"
+#include "TclBind.h"
+#include "Shell.h"
+
+namespace orxonox
+{
+    static const std::string __CC_CommandExecutor_name = "CommandExecutor";
+    static const std::string __CC_autocomplete_name = "autocomplete";
+
+    SetConsoleCommand(__CC_CommandExecutor_name, __CC_autocomplete_name, &CommandExecutor::_autocomplete)
+        .hide()
+        .argumentCompleter(0, autocompletion::groupsandcommands())
+        .argumentCompleter(1, autocompletion::subcommands());
+
+    SetConsoleCommand("unhide", &CommandExecutor::unhide)
+        .argumentCompleter(0, autocompletion::hiddencommand());
+
+    SetConsoleCommand("alias", &CommandExecutor::alias)
+        .argumentCompleter(1, autocompletion::command());
+
+    /**
+        @brief Returns a reference to the only instance of CommandExecutor.
+    */
+    /* static */ CommandExecutor& CommandExecutor::getInstance()
+    {
+        static CommandExecutor instance;
+        return instance;
+    }
+
+    /**
+        @brief Executes a command.
+        @param command A string containing the command
+        @param useTcl If true, the command is passed to tcl (see TclBind)
+        @param printErrors If true, print an error when command failed
+        @return Returns the error-code (see @ref CommandExecutorErrorCodes "error codes")
+    */
+    /* static */ int CommandExecutor::execute(const std::string& command, bool useTcl, bool printErrors)
+    {
+        int error;
+        CommandExecutor::queryMT(command, &error, useTcl);
+        if (error && printErrors)
+            orxout(user_error) << "Can't execute \"" << command << "\", " << CommandExecutor::getErrorDescription(error) << ". (execute)" << endl;
+        return error;
+    }
+
+    /**
+        @brief Executes a command and returns its return-value.
+        @param command A string containing the command
+        @param error A pointer to a value (or nullptr) where the error-code should be written to (see @ref CommandExecutorErrorCodes "error codes")
+        @param useTcl If true, the command is passed to tcl (see TclBind)
+        @return Returns the return-value of the command (if any - MultiType::Null otherwise)
+    */
+    /* static */ MultiType CommandExecutor::queryMT(const std::string& command, int* error, bool useTcl)
+    {
+        MultiType result;
+        int error_internal;
+
+        if (useTcl)
+        {
+            // pass the command to tcl
+            result = TclBind::eval(command, &error_internal);
+        }
+        else
+        {
+            CommandEvaluation evaluation;
+
+            // try to get the command evaluation from the cache
+            if (!CommandExecutor::getInstance().getCached(command, evaluation))
+            {
+                // it wasn't in the cache - evaluate the command
+                evaluation = CommandExecutor::evaluate(command);
+
+                // evaluate its arguments
+                evaluation.evaluateArguments();
+
+                // write the evaluation to the cache
+                CommandExecutor::getInstance().cache(command, evaluation);
+            }
+
+            // query the command and return its return-value
+            result = evaluation.query(&error_internal);
+        }
+
+        if (error)
+            *error = error_internal;
+        else if (error_internal)
+            orxout(user_error) << "Can't execute \"" << command << "\", " << CommandExecutor::getErrorDescription(error_internal) << ". (query)" << endl;
+
+        return result;
+    }
+
+    /**
+        @brief Executes a command and returns its return-value as string.
+        @param command A string containing the command
+        @param error A pointer to a value (or nullptr) where the error-code should be written to (see @ref CommandExecutorErrorCodes "error codes")
+        @param useTcl If true, the command is passed to tcl (see TclBind)
+        @return Returns the return-value of the command converted to a string (or "" if there's no return value)
+    */
+    /* static */ std::string CommandExecutor::query(const std::string& command, int* error, bool useTcl)
+    {
+        return CommandExecutor::queryMT(command, error, useTcl).get<std::string>();
+    }
+
+    /**
+        @brief Evaluates the given command.
+        @param command A string containing the command
+        @return Returns an instance of CommandEvaluation, which contains the evaluated ConsoleCommand, if the command is valid.
+
+        Evaluates the given command string and returns an instance of CommandEvaluation.
+        If the command is valid, this contains the evaluated ConsoleCommand. Otherwise it
+        can still be used to print hints or complete the command.
+
+        @note Tcl commands can not be evaluated. You have to pass them to execute() or to
+        TclBind directly.
+    */
+    /* static */ CommandEvaluation CommandExecutor::evaluate(const std::string& command)
+    {
+        // initialize the command evaluation
+        CommandEvaluation evaluation;
+        evaluation.initialize(command);
+
+        // assign the fallback-command to get hints about the possible commands and groups
+        evaluation.hintCommand_ = ConsoleCommandManager::getInstance().getCommand(__CC_CommandExecutor_name, __CC_autocomplete_name);
+
+        // check if there's at least one argument
+        if (evaluation.getNumberOfArguments() >= 1)
+        {
+            // try to get a command from the first token
+            evaluation.execCommand_ = ConsoleCommandManager::getInstance().getCommandLC(evaluation.getToken(0));
+            if (evaluation.execCommand_)
+                evaluation.execArgumentsOffset_ = 1;
+            else if (evaluation.getNumberOfArguments() >= 2)
+            {
+                // try to get a command from the first two tokens
+                evaluation.execCommand_ = ConsoleCommandManager::getInstance().getCommandLC(evaluation.getToken(0), evaluation.getToken(1));
+                if (evaluation.execCommand_)
+                    evaluation.execArgumentsOffset_ = 2;
+            }
+        }
+
+        // if a valid command was found and the user is already entering arguments, overwrite hintCommand_ with execCommand_
+        if (evaluation.execCommand_ && evaluation.getNumberOfArguments() > evaluation.execArgumentsOffset_)
+        {
+            evaluation.hintCommand_ = evaluation.execCommand_;
+            evaluation.hintArgumentsOffset_ = evaluation.execArgumentsOffset_;
+        }
+
+        return evaluation;
+    }
+
+    /**
+        @brief Returns a description of the error code.
+        @param error The error code
+    */
+    /* static */ std::string CommandExecutor::getErrorDescription(int error)
+    {
+        switch (error)
+        {
+            case CommandExecutor::Inexistent:  return "command doesn't exist";
+            case CommandExecutor::Incomplete:  return "not enough arguments given";
+            case CommandExecutor::Deactivated: return "command is not active";
+            case CommandExecutor::Denied:      return "access denied";
+            case CommandExecutor::Error:       return "an error occurred";
+            default: return "";
+        }
+    }
+
+    /**
+        @brief Gets an evaluated command from the cache.
+        @param command The command that should be looked up in the cache
+        @param evaluation Reference to a CommandEvaluation that will be used to return the cached evaluation.
+        @return Returns true if the command was found in the cache
+    */
+    bool CommandExecutor::getCached(const std::string& command, CommandEvaluation& evaluation)
+    {
+        if (Shell::getCacheSize() == 0)
+            return false;
+
+        // check if the command is in the cache
+        std::map<std::string, CacheEntry>::iterator it = this->cache_.find(command);
+        if (it != this->cache_.end())
+        {
+            // update ordered list of cached commands (move it to the front)
+            this->cachelist_.erase(it->second.iterator_);
+            this->cachelist_.push_front(command);
+            it->second.iterator_ = this->cachelist_.begin();
+
+            // assign the cached evaluation
+            evaluation = it->second.evaluation_;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+        @brief Writes a command evaluation for a given command to the cache.
+    */
+    void CommandExecutor::cache(const std::string& command, const CommandEvaluation& evaluation)
+    {
+        if (Shell::getCacheSize() == 0)
+            return;
+
+        // push command to the front of the ordered list
+        this->cachelist_.push_front(command);
+
+        // create a cache entry and store it in the cache
+        CacheEntry entry;
+        entry.evaluation_ = evaluation;
+        entry.iterator_ = this->cachelist_.begin();
+        this->cache_[command] = entry;
+
+        // remove the last command in the ordered list from the cache if it exceeds the maximum size of the cache
+        if (this->cachelist_.size() > Shell::getCacheSize())
+        {
+            this->cache_.erase(this->cachelist_.back());
+            this->cachelist_.pop_back();
+        }
+    }
+
+    /**
+        @brief This function is used as console command which executes commands that are usually hidden.
+
+        The argument completion function of this console commands is used to find
+        and enter hidden commands and their arguments.
+    */
+    /* static */ MultiType CommandExecutor::unhide(const std::string& command)
+    {
+        return CommandExecutor::queryMT(command);
+    }
+
+    /**
+        @brief This function is used as console command which saves a command and optionally also it's arguments as a new console command with a new name.
+        @param alias The name of the new command alias
+        @param command The existing command and (optionally) its arguments
+    */
+    /* static */ void CommandExecutor::alias(const std::string& alias, const std::string& command)
+    {
+        // first check if the given command is valid, else print an error
+        CommandEvaluation evaluation = CommandExecutor::evaluate(command);
+        if (evaluation.isValid())
+        {
+            // it is valid - copy the executor of this command
+            ExecutorPtr executor = std::make_shared<Executor>(*evaluation.getConsoleCommand()->getExecutor().get());
+
+            // evaluate the arguments and if this returns no error, store them as default values
+            if (!evaluation.evaluateArguments())
+            {
+                for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
+                    executor->setDefaultValue(i, evaluation.getEvaluatedArgument(i));
+            }
+
+            // split the alias in tokens
+            SubString tokens(alias, " ");
+
+            // check if the alias already exists - print an error and return if it does
+            if ((tokens.size() == 1 && ConsoleCommandManager::getInstance().getCommand(tokens[0])) || (tokens.size() == 2 && ConsoleCommandManager::getInstance().getCommand(tokens[0], tokens[1])))
+            {
+                orxout(user_error) << "A command with name \"" << alias << "\" already exists." << endl;
+                return;
+            }
+
+            // create a new console command with the given alias as its name
+            if (tokens.size() == 1)
+                ConsoleCommandManager::getInstance().registerCommand(new ConsoleCommand(tokens[0], executor));
+            else if (tokens.size() == 2)
+                ConsoleCommandManager::getInstance().registerCommand(new ConsoleCommand(tokens[0], tokens[1], executor));
+            else
+                orxout(user_error) << "\"" << alias << "\" is not a valid alias name (must have one or two words)." << endl;
+        }
+        else
+            orxout(user_error) << "\"" << command << "\" is not a valid command (did you mean \"" << evaluation.getCommandSuggestion() << "\"?)." << endl;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/CommandExecutor.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/CommandExecutor.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/CommandExecutor.h	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command CommandExecEval
+    @brief Declaration of the orxonox::CommandExecutor class which is used to execute and evaluate @ref orxonox::ConsoleCommand "console commands".
+
+    @anchor CommandExecutorExample
+
+    orxonox::CommandExecutor can be used to execute console commands (see orxonox::ConsoleCommand).
+    Commands are strings that can be entered by the user in the shell or they can be part of a
+    script.
+
+    A command can be passed to orxonox::CommandExecutor::execute() which will execute them - eiter
+    directly, or - if requested - passes it to Tcl. See orxonox::TclBind for more information.
+    Appart from execute() the command can also be passed to orxonox::CommandExecutor::query() which
+    behaves the same except for that it returns the return value of the command.
+
+    If you don't want to execute the command, but rather gather more information about it, pass it
+    to orxonox::CommandExecutor::evaluate(). This function returns an instance of
+    orxonox::CommandEvaluation. This class provides more information about the command, for example
+    the evaluated instance of orxonox::ConsoleCommand. Its also possible to gather hints about the
+    command or to complete the command-string by using argument completion functions. More than that
+    the command evaluation can also evaluate the arguments, which allows faster execution of the
+    command.
+
+    Example:
+    @code
+    CommandExecutor::execute("log test");               // writes "test" to the console
+    CommandExecutor::execute("log [expr 1+1]");         // writes "2" to the console - expr is a Tcl command
+
+    CommandExecutor::query("expr 1+1");                 // returns "2"
+    CommandExecutor::queryMT("expr 1+1");               // returns 2
+    @endcode
+
+    And another example about how to use evaluate():
+    @code
+    CommandEvaluation evaluation;
+    evaluation = CommandExecutor::evaluate("log test"); // returns an evaluation of "log test"
+
+    evaluation.execute();                               // writes "test" to the console
+    evaluation.hint();                                  // returns "log: {string}"
+    @endcode
+
+    @anchor CommandExecutorErrorCodes
+
+    @b Error @b codes:
+
+    orxonox::CommandExecutor defines a number of error codes that are returned
+    by different functions that operate with commands:
+
+     - CommandExecutor::Success: No error
+     - CommandExecutor::Error: The command doesn't exist
+     - CommandExecutor::Incomplete: The command needs more arguments
+     - CommandExecutor::Deactivated: The command is not active
+     - CommandExecutor::Denied: The command needs a different @ref orxonox::AccessLevel "access level"
+*/
+
+#ifndef _CommandExecutor_H__
+#define _CommandExecutor_H__
+
+#include "core/CorePrereqs.h"
+
+#include <map>
+#include <list>
+#include <string>
+
+#include "util/MultiType.h"
+#include "CommandEvaluation.h"
+
+// tolua_begin
+namespace orxonox
+{
+    /**
+        @brief This class is used to execute and evaluate command-strings.
+
+        CommandExecutor executes command-strings and returns evaluated commands. It's
+        also possible to execute Tcl commands if the corresponding argument of execute()
+        is true.
+
+        @see See @ref CommandExecutorExample "this description" for more information and some examples.
+    */
+    class _CoreExport CommandExecutor
+    {
+// tolua_end
+        public:
+            static int execute(const std::string& command, bool useTcl = true, bool printErrors = true); // tolua_export
+
+            static MultiType queryMT(const std::string& command, int* error = nullptr, bool useTcl = true);
+            static std::string query(const std::string& command, int* error = NULL, bool useTcl = true); // tolua_export
+
+            static CommandEvaluation evaluate(const std::string& command);
+
+            static constexpr int Success = 0;       ///< Error code for "success" (or no error)
+            static constexpr int Inexistent = 1;    ///< Error code if the command doesn't exist
+            static constexpr int Incomplete = 2;    ///< Error code if the command needs more arguments
+            static constexpr int Deactivated = 3;   ///< Error code if the command is not active
+            static constexpr int Denied = 4;        ///< Error code if the command needs a different access level
+            static constexpr int Error = 5;         ///< Error code if the command returned an error
+
+            static std::string getErrorDescription(int error);
+
+            static MultiType unhide(const std::string& command);
+            static void alias(const std::string& alias, const std::string& command);
+            static void _autocomplete(const std::string& group, const std::string& name) {} ///< Pseudo console command used whenever no real command is available. In these cases this command provides auto-completion for console commands and groups.
+
+        private:
+            CommandExecutor() = default;                      ///< Empty constructor
+            ~CommandExecutor() = default;                     ///< Empty destructor
+
+            // non-copyable:
+            CommandExecutor(const CommandExecutor&) = delete;
+            CommandExecutor& operator=(const CommandExecutor&) = delete;
+
+            static CommandExecutor& getInstance();
+
+            bool getCached(const std::string& command, CommandEvaluation& evaluation);
+            void cache(const std::string& command, const CommandEvaluation& evaluation);
+
+            /// Helper struct, used to store cached entries
+            struct CacheEntry
+            {
+                CommandEvaluation evaluation_;                  ///< The command evaluation which is stored in the cache
+                std::list<std::string>::iterator iterator_;     ///< The iterator of the corresponding element in cachelist_, used for faster access
+            };
+
+            std::map<std::string, CacheEntry> cache_;   ///< A map that connects command strings and evaluated commands in the cache
+            std::list<std::string> cachelist_;          ///< A list used to sort the elements in the cache by their age
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _CommandExecutor_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommand.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommand.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommand.cc	(revision 11817)
@@ -0,0 +1,604 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the ConsoleCommand class.
+*/
+
+#include "ConsoleCommand.h"
+
+#include "util/Convert.h"
+#include "core/Language.h"
+#include "core/GameMode.h"
+#include "core/input/KeyBinder.h"
+#include "core/input/KeyBinderManager.h"
+#include "ConsoleCommandManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: Initializes all values and registers the command (without a group).
+        @param name The name of the command
+        @param executor The executor of the command
+        @param bInitialized If true, the executor is used for both, the definition of the function-header AND to executute the command. If false, the command is inactive and needs to be assigned a function before it can be used.
+    */
+    ConsoleCommand::ConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized)
+        : ConsoleCommand("", name, executor, bInitialized)
+    {
+    }
+
+    /**
+        @brief Constructor: Initializes all values and registers the command (with a group).
+        @param group The group of the command
+        @param name The name of the command
+        @param executor The executor of the command
+        @param bInitialized If true, the executor is used for both, the definition of the function-header AND to executute the command. If false, the command is inactive and needs to be assigned a function before it can be used.
+    */
+    ConsoleCommand::ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
+    {
+        this->init(group, name, executor, bInitialized);
+    }
+
+    void ConsoleCommand::init(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized)
+    {
+        this->bActive_ = true;
+        this->bHidden_ = false;
+        this->accessLevel_ = AccessLevel::All;
+
+        this->baseName_ = name;
+        this->baseFunctor_ = executor->getFunctor();
+
+        for (ArgumentCompleter*& completer : this->argumentCompleter_)
+            completer = nullptr;
+
+        this->keybindMode_ = KeybindMode::OnPress;
+        this->inputConfiguredParam_ = -1;
+
+        if (bInitialized)
+            this->executor_ = executor;
+
+        this->names_.emplace_back(group, name);
+    }
+
+    /**
+        @brief Destructor: Unregisters the command.
+    */
+    ConsoleCommand::~ConsoleCommand()
+    {
+    }
+
+    /**
+        @brief Registers the command with the same name, but without group, as shortcut.
+    */
+    ConsoleCommand& ConsoleCommand::addShortcut()
+    {
+        this->names_.emplace_back("", this->baseName_);
+        return *this;
+    }
+
+    /**
+        @brief Registers the command with an alias as shortcut.
+    */
+    ConsoleCommand& ConsoleCommand::addShortcut(const std::string&  name)
+    {
+        this->names_.emplace_back("", name);
+        return *this;
+    }
+
+    /**
+        @brief Registers the command in a different group but with the same name.
+    */
+    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group)
+    {
+        this->names_.emplace_back(group, this->baseName_);
+        return *this;
+    }
+
+    /**
+        @brief Registers an alias of the command in a different group with a different name.
+    */
+    ConsoleCommand& ConsoleCommand::addGroup(const std::string& group, const std::string&  name)
+    {
+        this->names_.emplace_back(group, name);
+        return *this;
+    }
+
+    /**
+        @brief Returns true if the command can be executed right now.
+
+        This returns only true, if the following conditions are met:
+         - The command is active
+         - The command has an executor
+         - The executor has a functor
+         - The functor is static or has an object
+    */
+    bool ConsoleCommand::isActive() const
+    {
+        return (this->bActive_ && this->executor_ && this->executor_->getFunctor() && (this->executor_->getFunctor()->getType() == Functor::Type::Static || this->executor_->getFunctor()->getRawObjectPointer()));
+    }
+
+    /**
+        @brief Returns true if the current state of the game matches the required access level.
+    */
+    bool ConsoleCommand::hasAccess() const
+    {
+        switch (this->accessLevel_)
+        {
+            case AccessLevel::All:        return true;
+            case AccessLevel::Standalone: return GameMode::isStandalone();
+            case AccessLevel::Master:     return GameMode::isMaster();
+            case AccessLevel::Server:     return GameMode::isServer();
+            case AccessLevel::Client:     return GameMode::isClient();
+            case AccessLevel::Online:     return (GameMode::isServer() || GameMode::isClient());
+            case AccessLevel::Offline:    return GameMode::isStandalone();
+            case AccessLevel::None:       return false;
+            default:                      return false;
+        }
+    }
+
+    /**
+        @brief Returns true if the headers of the given functor match the declaration of this command.
+    */
+    bool ConsoleCommand::headersMatch(const FunctorPtr& functor)
+    {
+        // get the minimum of the number of parameters of both commands
+        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), functor->getParamCount());
+
+        // if the reduced headers don't match -> return false
+        if (this->baseFunctor_->getHeaderIdentifier(minparams) != functor->getHeaderIdentifier(minparams))
+            return false;
+        // if the reduced headers match and the new functor has less or equal parameters -> return true
+        else if (functor->getParamCount() <= this->baseFunctor_->getParamCount())
+            return true;
+        // the headers match but the new functor has more arguments and there is no executor with default-values -> return false
+        else if (!this->executor_)
+            return false;
+        // the headers match but the new functor has more arguments, check if the executor has enough default-values
+        else
+        {
+            for (unsigned int i = this->baseFunctor_->getParamCount(); i < functor->getParamCount(); ++i)
+            {
+                if (!this->executor_->defaultValueSet(i))
+                {
+                    orxout(internal_warning, context::commands) << "Default value " << i << " is missing" << endl;
+                    return false;
+                }
+            }
+
+            return true;
+        }
+    }
+
+    /**
+        @brief Returns true if the headers of the given executor match the declaration of this command.
+    */
+    bool ConsoleCommand::headersMatch(const ExecutorPtr& executor)
+    {
+        // get the minimum of the number of parameters of both commands
+        unsigned int minparams = std::min(this->baseFunctor_->getParamCount(), executor->getParamCount());
+
+        // if the reduced headers don't match -> return false
+        if (this->baseFunctor_->getHeaderIdentifier(minparams) != executor->getFunctor()->getHeaderIdentifier(minparams))
+            return false;
+        // if the reduced headers match and the new functor has less or equal parameters -> return true
+        else if (executor->getParamCount() <= this->baseFunctor_->getParamCount())
+            return true;
+        // the headers match but the new functor has more arguments, check if the new executor has enough default-values
+        else
+        {
+            for (unsigned int i = this->baseFunctor_->getParamCount(); i < executor->getParamCount(); ++i)
+            {
+                if (!executor->defaultValueSet(i))
+                {
+                    orxout(internal_warning, context::commands) << "Default value " << i << " is missing" << endl;
+                    return false;
+                }
+            }
+
+            return true;
+        }
+    }
+
+    /**
+        @brief Changes the executor.
+        @param executor The new executor
+        @param bForce If true, the executor is always assigned, even if the headers don't match
+        @return Returns true if the assignment was successful
+    */
+    bool ConsoleCommand::setFunction(const ExecutorPtr& executor, bool bForce)
+    {
+        // assign the executor if a) it's a null-pointer, b) its functor is a null-pointer, c) it's forced, d) the headers match
+        if (!executor || !executor->getFunctor() || bForce || this->headersMatch(executor))
+        {
+            // assign the executor and clear the object stack (because it's also a new function)
+            this->executor_ = executor;
+            this->objectStack_.clear();
+            return true;
+        }
+        else
+        {
+            orxout(internal_error, context::commands) << "Couldn't assign new executor to console command \"" << this->baseName_ << "\", headers don't match." << endl;
+            return false;
+        }
+    }
+
+    /**
+        @brief Changes the functor of the current executor.
+        @param functor The new functor
+        @param bForce If true, the functor is always assigned, even if the headers don't match
+        @return Returns true if the assignment was successful
+    */
+    bool ConsoleCommand::setFunction(const FunctorPtr& functor, bool bForce)
+    {
+        // assign the functor if a) it's a null-pointer, b) it's forced, c) the headers match
+        if (!functor || bForce || this->headersMatch(functor))
+        {
+            // assign the functor (create a new executor if necessary) and clear the object stack
+            if (this->executor_)
+                this->executor_->setFunctor(functor);
+            else if (functor)
+                this->executor_ = createExecutor(functor);
+            this->objectStack_.clear();
+
+            return true;
+        }
+        else
+        {
+            orxout(internal_error, context::commands) << "Couldn't assign new functor to console command \"" << this->baseName_ << "\", headers don't match." << endl;
+            return false;
+        }
+    }
+
+    /**
+        @brief Pushes a new executor to the command-stack.
+        @param executor The new executor
+        @param bForce If true, the executor is always assigned, even if the headers don't match
+    */
+    void ConsoleCommand::pushFunction(const ExecutorPtr& executor, bool bForce)
+    {
+        // prepare the old function to be put on the stack
+        Command command;
+        command.executor_ = this->executor_;
+        if (command.executor_)
+            command.functor_ = this->executor_->getFunctor();
+        command.objectStack_ = this->objectStack_;
+
+        // check if the new executor can be assigned and push the old function to the stack
+        if (this->setFunction(executor, bForce))
+            this->commandStack_.push(command);
+    }
+
+    /**
+        @brief Pushes a new functor to the command-stack.
+        @param functor The new functor
+        @param bForce If true, the functor is always assigned, even if the headers don't match
+    */
+    void ConsoleCommand::pushFunction(const FunctorPtr& functor, bool bForce)
+    {
+        // prepare the old function to be put on the stack
+        Command command;
+        command.executor_ = this->executor_;
+        if (command.executor_)
+            command.functor_ = this->executor_->getFunctor();
+        command.objectStack_ = this->objectStack_;
+
+        // check if the new functor can be assigned and push the old function to the stack
+        if (this->setFunction(functor, bForce))
+            this->commandStack_.push(command);
+    }
+
+    /**
+        @brief Pushes a copy of the current executor and functor on the stack.
+    */
+    void ConsoleCommand::pushFunction()
+    {
+        if (this->executor_)
+            this->pushFunction(std::make_shared<Executor>(*this->executor_.get()));
+        else
+            orxout(internal_error, context::commands) << "Couldn't push copy of executor in console command \"" << this->baseName_ << "\", no executor set." << endl;
+    }
+
+    /**
+        @brief Removes the current function from the stack and restores the old state.
+    */
+    void ConsoleCommand::popFunction()
+    {
+        Command command;
+
+        // check if there's a function on the stack
+        if (!this->commandStack_.empty())
+        {
+            // yes it is - assign it to command and remove it from the stack
+            command = this->commandStack_.top();
+            this->commandStack_.pop();
+        }
+
+        // restore the old executor (and also restore its functor in case this was changed in the meantime)
+        this->executor_ = command.executor_;
+        if (command.executor_)
+            this->executor_->setFunctor(command.functor_);
+        this->objectStack_ = command.objectStack_;
+    }
+
+    /**
+        @brief Sets the functor to nullptr (which also deactivates the command).
+    */
+    void ConsoleCommand::resetFunction()
+    {
+        if (this->executor_)
+            this->executor_->setFunctor(nullptr);
+        this->objectStack_.clear();
+    }
+
+    /**
+        @brief Returns the current executor which can be used to execute the command.
+    */
+    const ExecutorPtr& ConsoleCommand::getExecutor() const
+    {
+        return this->executor_;
+    }
+
+    /**
+        @brief Changes the current object that is used to execute member-functions.
+        @return Returns true if the object was successfully changed
+    */
+    bool ConsoleCommand::setObject(void* object)
+    {
+        // check if there's an executor
+        if (this->executor_)
+        {
+            // check if there's a functor
+            if (this->executor_->getFunctor())
+            {
+                // change the object
+                this->executor_->getFunctor()->setRawObjectPointer(object);
+                return true;
+            }
+            else if (object)
+                orxout(internal_error, context::commands) << "Can't assign object to console command \"" << this->baseName_ << "\", no functor set." << endl;
+        }
+        else if (object)
+            orxout(internal_error, context::commands) << "Can't assign object to console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return false;
+    }
+
+    /**
+        @brief Push a new object to the object-stack.
+    */
+    void ConsoleCommand::pushObject(void* object)
+    {
+        void* oldobject = this->getObject();
+        if (this->setObject(object))
+            this->objectStack_.push_back(oldobject);
+    }
+
+    /**
+        @brief Removes the current object from the stack an restores the old object.
+    */
+    void ConsoleCommand::popObject()
+    {
+        void* newobject = nullptr;
+        if (!this->objectStack_.empty())
+        {
+            newobject = this->objectStack_.back();
+            this->objectStack_.pop_back();
+        }
+        this->setObject(newobject);
+    }
+
+    /**
+        @brief Returns the current object pointer that is used to execute member-functions.
+    */
+    void* ConsoleCommand::getObject() const
+    {
+        if (this->executor_ && this->executor_->getFunctor())
+            return this->executor_->getFunctor()->getRawObjectPointer();
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Changes the default values of the current executor.
+    */
+    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1)
+    {
+        if (this->executor_)
+            this->executor_->setDefaultValues(arg1);
+        else
+            orxout(internal_error, context::commands) << "Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Changes the default values of the current executor.
+    */
+    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2)
+    {
+        if (this->executor_)
+            this->executor_->setDefaultValues(arg1, arg2);
+        else
+            orxout(internal_error, context::commands) << "Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Changes the default values of the current executor.
+    */
+    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
+    {
+        if (this->executor_)
+            this->executor_->setDefaultValues(arg1, arg2, arg3);
+        else
+            orxout(internal_error, context::commands) << "Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Changes the default values of the current executor.
+    */
+    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
+    {
+        if (this->executor_)
+            this->executor_->setDefaultValues(arg1, arg2, arg3, arg4);
+        else
+            orxout(internal_error, context::commands) << "Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Changes the default values of the current executor.
+    */
+    ConsoleCommand& ConsoleCommand::defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
+    {
+        if (this->executor_)
+            this->executor_->setDefaultValues(arg1, arg2, arg3, arg4, arg5);
+        else
+            orxout(internal_error, context::commands) << "Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Changes the default value of the argument with given index of the current executor.
+        @param index The index of the argument (the first argument has index 0)
+        @param arg The new default value
+    */
+    ConsoleCommand& ConsoleCommand::defaultValue(unsigned int index, const MultiType& arg)
+    {
+        if (this->executor_)
+            this->executor_->setDefaultValue(index, arg);
+        else
+            orxout(internal_error, context::commands) << "Can't set default values in console command \"" << this->baseName_ << "\", no executor set." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Changes the argument completer for the given argument.
+        @param index The index of the argument (the first argument has index 0)
+        @param completer The new argument completer
+    */
+    ConsoleCommand& ConsoleCommand::argumentCompleter(unsigned int index, ArgumentCompleter* completer)
+    {
+        if (index < 5)
+            this->argumentCompleter_[index] = completer;
+        else
+            orxout(internal_warning, context::commands) << "Couldn't add autocompletion-function for index " << index << " in console command \"" << this->baseName_ << "\": index out of bound." << endl;
+
+        return *this;
+    }
+
+    /**
+        @brief Returns the argument completer for the argument with given index.
+    */
+    ArgumentCompleter* ConsoleCommand::getArgumentCompleter(unsigned int index) const
+    {
+        if (index < 5)
+            return this->argumentCompleter_[index];
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Sets the description of this command.
+    */
+    ConsoleCommand& ConsoleCommand::description(const std::string& description)
+    {
+        this->description_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::function");
+        AddLanguageEntry(this->description_, description);
+        return *this;
+    }
+
+    /**
+        @brief Returns the description of this command.
+    */
+    const std::string& ConsoleCommand::getDescription() const
+    {
+        return GetLocalisation_noerror(this->description_);
+    }
+
+    /**
+        @brief Sets the description for an argument with given index.
+    */
+    ConsoleCommand& ConsoleCommand::descriptionParam(unsigned int index, const std::string& description)
+    {
+        if (index < MAX_FUNCTOR_ARGUMENTS)
+        {
+            this->descriptionParam_[index] = std::string("ConsoleCommandDescription::" + this->baseName_ + "::param" + multi_cast<std::string>(index));
+            AddLanguageEntry(this->descriptionParam_[index], description);
+        }
+        return *this;
+    }
+
+    /**
+        @brief Returns the description for the argument with given index.
+    */
+    const std::string& ConsoleCommand::getDescriptionParam(unsigned int index) const
+    {
+        if (index < MAX_FUNCTOR_ARGUMENTS)
+            return GetLocalisation_noerror(this->descriptionParam_[index]);
+
+        return this->descriptionParam_[0];
+    }
+
+    /**
+        @brief Sets the description for the return-value.
+    */
+    ConsoleCommand& ConsoleCommand::descriptionReturnvalue(const std::string& description)
+    {
+        this->descriptionReturnvalue_ = std::string("ConsoleCommandDescription::" + this->baseName_ + "::returnvalue");
+        AddLanguageEntry(this->descriptionReturnvalue_, description);
+        return *this;
+    }
+
+    /**
+        @brief Returns the description for the return-value.
+    */
+    const std::string& ConsoleCommand::getDescriptionReturnvalue(int index) const
+    {
+        return GetLocalisation_noerror(this->descriptionReturnvalue_);
+    }
+
+    /**
+        @brief Changes the keybind mode.
+    */
+    ConsoleCommand& ConsoleCommand::changeKeybindMode(KeybindMode::Value mode)
+    {
+        if( KeyBinderManager::exists() )
+            KeyBinderManager::getInstance().getCurrent()->changeMode(this, mode);
+
+        this->keybindMode(mode);
+        return *this;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommand.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommand.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommand.h	(revision 11817)
@@ -0,0 +1,413 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ConsoleCommand
+    @brief Declaration of the orxonox::ConsoleCommand class.
+*/
+
+#ifndef _ConsoleCommand_H__
+#define _ConsoleCommand_H__
+
+#include "core/CorePrereqs.h"
+
+#include <stack>
+#include <vector>
+
+#include "ArgumentCompletionFunctions.h"
+#include "Executor.h"
+
+namespace orxonox
+{
+    /**
+        @brief A small collection of functions that can be used in DeclareConsoleCommand() if
+        you don't want to use the real function-pointer.
+    */
+    namespace prototype
+    {
+        inline void void__void(void) {}
+        inline void void__string(const std::string&) {}
+
+        inline std::string string__bool(bool) { return ""; }
+        inline std::string string__string(const std::string&) { return ""; }
+        inline std::string string__uint_uint_bool(unsigned int, unsigned int, bool) { return ""; }
+    }
+
+    /**
+        @brief Possible access levels: A command can only be executed if the program is in the state which is requested by the access level.
+    */
+    enum class AccessLevel
+    {
+        All,
+        Standalone,
+        Master,
+        Server,
+        Client,
+        Online,
+        Offline,
+        None
+    };
+
+    /**
+        @brief The ConsoleCommand class stores all information about a console command which can be executed by CommandExecutor.
+
+        Console commands can be entered by the user into the shell, called in scripts, or
+        used for key-bindings. They are simple text strings that can be executed by
+        CommandExecutor. CommandExecutor will search for a ConsoleCommand with the given
+        group and name and will execute it's Executor (which again calls the Functor and
+        this finally calls the command-function).
+
+        @see See @ref ConsoleCommandExample "ConsoleCommand.h" for more information and some examples.
+    */
+    class _CoreExport ConsoleCommand
+    {
+        friend struct ConsoleCommandManipulator;
+
+        /**
+            @brief Helper class that is used to put the current state of the ConsoleCommand on a stack.
+        */
+        struct Command
+        {
+            ExecutorPtr executor_;              ///< The executor
+            FunctorPtr functor_;                ///< The function that is used with the executor - has to be stored separatley because the executor is often used with different functors
+            std::vector<void*> objectStack_;    ///< The object stack
+        };
+
+        public:
+            /**
+             * @brief Defines the name of a command, consisting of an optional group ("" means no group) and the name itself.
+             */
+            struct CommandName
+            {
+                CommandName(const std::string& group, const std::string& name) : group_(group), name_(name) {}
+                std::string group_;
+                std::string name_;
+            };
+
+            /**
+                @brief Helper class that is used to manipulate console commands.
+
+                An instance of this class is returned if you call the ModifyConsoleCommand macro.
+                This class provides an interface which wraps some functions of ConsoleCommand. It
+                allows access to some private functions like setFunction() (that can't be called
+                right after SetConsoleCommand()) but it also hides some functions that shouln't be
+                called after the static declaration like addShortcut() or description().
+
+                @see See @ref ConsoleCommandExample "ConsoleCommand.h" for more information and examples.
+            */
+            struct ConsoleCommandManipulator
+            {
+                public:
+                    /// Constructor: Creates a manipulator for a given ConsoleCommand.
+                    ConsoleCommandManipulator(ConsoleCommand* command) : command_(command) {}
+
+                    /// Changes the current function of the command. @param function The new function-pointer @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
+                    template <class F>
+                    inline ConsoleCommandManipulator& setFunction(F function, bool bForce = false)
+                        {
+                            if (this->command_)
+                            {
+                                // check if the headers match. If they do, only change the function-pointer of the current Functor instead of creating a new Functor
+                                if (this->command_->getExecutor() && this->command_->getExecutor()->getFunctor() && this->command_->getExecutor()->getFunctor()->getFullIdentifier() == typeid(F))
+                                {
+                                    FunctorPointer<F>* functor = static_cast<FunctorPointer<F>*>(this->command_->getExecutor()->getFunctor().get());
+                                    functor->setFunction(function);
+                                    return *this;
+                                }
+                                this->command_->setFunction(createFunctor(function), bForce);
+                            }
+                            return *this;
+                        }
+                    /// Changes the current function of the command. @param function The new function-pointer @param object The new object-pointer (for member-functions) @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
+                    template <class F, class O>
+                    inline ConsoleCommandManipulator& setFunction(F function, O* object, bool bForce = false)
+                        {
+                            if (this->command_)
+                            {
+                                // check if the headers match. If they do, only change the function-pointer of the current Functor instead of creating a new Functor
+                                if (this->command_->getExecutor() && this->command_->getExecutor()->getFunctor() && this->command_->getExecutor()->getFunctor()->getFullIdentifier() == typeid(F))
+                                {
+                                    FunctorPointer<F, O>* functor = static_cast<FunctorPointer<F, O>*>(this->command_->getExecutor()->getFunctor().get());
+                                    functor->setFunction(function);
+                                    functor->setObject(object);
+                                    return *this;
+                                }
+                                this->command_->setFunction(createFunctor(function, object), bForce);
+                            }
+                            return *this;
+                        }
+                    /// Changes the current Functor of the command. @param functor The new Functor @param bForce If true, the new Functor is always assigned, even if the headers don't match
+                    inline ConsoleCommandManipulator& setFunction(const FunctorPtr& functor, bool bForce = false)
+                        { if (this->command_) { this->command_->setFunction(functor, bForce); } return *this; }
+                    /// Changes the current Executor of the command. @param executor The new Executor @param bForce If true, the new Executor is always assigned, even if the headers don't match
+                    inline ConsoleCommandManipulator& setFunction(const ExecutorPtr& executor, bool bForce = false)
+                        { if (this->command_) { this->command_->setFunction(executor, bForce); } return *this; }
+
+                    /// Pushes a copy of the current Executor on the command-stack, that can be altered without changing the old Executor. @details This function is especially useful if you don't wan't to change the function, but only the default values of the executor.
+                    inline ConsoleCommandManipulator& pushFunction()
+                        { if (this->command_) { this->command_->pushFunction(); } return *this; }
+                    /// Pushes a new function on the command-stack. @param function The new function-pointer @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
+                    template <class F>
+                    inline ConsoleCommandManipulator& pushFunction(F function, bool bForce = false)
+                        { if (this->command_) { this->command_->pushFunction(createFunctor(function), bForce); } return *this; }
+                    /// Pushes a new function on the command-stack. @param function The new function-pointer @param object The new object-pointer (for member-functions) @param bForce If true, the new function-pointer is always assigned, even if the headers don't match
+                    template <class F, class O>
+                    inline ConsoleCommandManipulator& pushFunction(F function, O* object, bool bForce = false)
+                        { if (this->command_) { this->command_->pushFunction(createFunctor(function, object), bForce); } return *this; }
+                    /// Pushes a new Functor on the command-stack. @param functor The new Functor @param bForce If true, the new Functor is always assigned, even if the headers don't match
+                    inline ConsoleCommandManipulator& pushFunction(const FunctorPtr& functor, bool bForce = false)
+                        { if (this->command_) { this->command_->pushFunction(functor, bForce); } return *this; }
+                    /// Pushes a new Executor on the command-stack. @param executor The new Executor @param bForce If true, the new Executor is always assigned, even if the headers don't match
+                    inline ConsoleCommandManipulator& pushFunction(const ExecutorPtr& executor, bool bForce = false)
+                        { if (this->command_) { this->command_->pushFunction(executor, bForce); } return *this; }
+
+                    /// Removes the current function from the stack and restores the old state. If there's no other function on the stack, the command is deactivated.
+                    inline ConsoleCommandManipulator& popFunction()
+                        { if (this->command_) { this->command_->popFunction(); } return *this; }
+
+                    /// Sets the current function-pointer to nullptr, which also deactivates the command.
+                    inline ConsoleCommandManipulator& resetFunction()
+                        { if (this->command_) { this->command_->resetFunction(); } return *this; }
+
+                    /// Changes the current object (used for member-functions).
+                    inline ConsoleCommandManipulator& setObject(void* object)
+                        { if (this->command_) { this->command_->setObject(object); } return *this; }
+                    /// Pushes a new object on the object-stack.
+                    inline ConsoleCommandManipulator& pushObject(void* object)
+                        { if (this->command_) { this->command_->pushObject(object); } return *this; }
+                    /// Removes the current object from the object-stack and restores the old object (or nullptr if there's no object left on the stack).
+                    inline ConsoleCommandManipulator& popObject()
+                        { if (this->command_) { this->command_->popObject(); } return *this; }
+
+                    /// Changes the activity of the command.
+                    inline ConsoleCommandManipulator& setActive(bool bActive)
+                        { if (this->command_) { this->command_->setActive(bActive); } return *this; }
+                    /// Activates the command.
+                    inline ConsoleCommandManipulator& activate()
+                        { return this->setActive(true); }
+                    /// Deactivates the command.
+                    inline ConsoleCommandManipulator& deactivate()
+                        { return this->setActive(false); }
+
+                    /// Changes the visibility of the command.
+                    inline ConsoleCommandManipulator& setHidden(bool bHidden)
+                        { if (this->command_) { this->command_->setHidden(bHidden); } return *this; }
+                    /// Hides the command (can still be executed, but is not visible in the list of available commands).
+                    inline ConsoleCommandManipulator& hide()
+                        { return this->setHidden(true); }
+                    /// Makes the command visible.
+                    inline ConsoleCommandManipulator& show()
+                        { return this->setHidden(false); }
+
+                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1)
+                        { if (this->command_) { this->command_->defaultValues(arg1); } return *this; }
+                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2)
+                        { if (this->command_) { this->command_->defaultValues(arg1, arg2); } return *this; }
+                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
+                        { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3); } return *this; }
+                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
+                        { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3, arg4); } return *this; }
+                    /// Changes the default values of the current executor (doesn't modify executors on deeper levels of the command-stack).
+                    inline ConsoleCommandManipulator& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
+                        { if (this->command_) { this->command_->defaultValues(arg1, arg2, arg3, arg4, arg5); } return *this; }
+                    /// Changes the default value of the argument with given index of the current executor (doesn't modify executors on deeper levels of the command-stack).
+                    inline ConsoleCommandManipulator& defaultValue(unsigned int index, const MultiType& arg)
+                        { if (this->command_) { this->command_->defaultValue(index, arg); } return *this; }
+
+                    /// Changes the access level of the command.
+                    inline ConsoleCommandManipulator& accessLevel(AccessLevel level)
+                        { if (this->command_) { this->command_->accessLevel(level); } return *this; }
+
+                    /// Changes the argument completer for the given parameter.
+                    inline ConsoleCommandManipulator& argumentCompleter(unsigned int index, ArgumentCompleter* completer)
+                        { if (this->command_) { this->command_->argumentCompleter(index, completer); } return *this; }
+
+                    /// Defines the command to be an input command.
+                    inline ConsoleCommandManipulator& setAsInputCommand()
+                        { if (this->command_) { this->command_->setAsInputCommand(); } return *this; }
+                    /// Changes the keybind mode of the command.
+                    inline ConsoleCommandManipulator& keybindMode(KeybindMode::Value mode)
+                        { if (this->command_) { this->command_->changeKeybindMode(mode); } return *this; }
+                    /// Sets the input configured param to the given index.
+                    inline ConsoleCommandManipulator& inputConfiguredParam(int index)
+                        { if (this->command_) { this->command_->inputConfiguredParam(index); } return *this; }
+
+                private:
+                    ConsoleCommand* command_;   ///< The command which is being manipulated by this object
+            };
+
+        public:
+            ConsoleCommand(const std::string& name, const ExecutorPtr& executor, bool bInitialized = true);
+            ConsoleCommand(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized = true);
+            ~ConsoleCommand();
+
+            ConsoleCommand& addShortcut();
+            ConsoleCommand& addShortcut(const std::string&  name);
+            ConsoleCommand& addGroup(const std::string& group);
+            ConsoleCommand& addGroup(const std::string& group, const std::string&  name);
+
+            /// Returns the name that was first used for this command.
+            inline const std::string& getName() const
+                { return this->baseName_; }
+
+            const ExecutorPtr& getExecutor() const;
+            /// Returns the functor that defines the required header for this command (but isn't necessarily executed).
+            inline const FunctorPtr& getBaseFunctor() const
+                { return this->baseFunctor_; }
+
+            /// Changes the activity of the command.
+            inline ConsoleCommand& setActive(bool bActive)
+                { this->bActive_ = bActive; return *this; }
+            /// Activates the command.
+            inline ConsoleCommand& activate()
+                { return this->setActive(true); }
+            /// Deactivates the command.
+            inline ConsoleCommand& deactivate()
+                { return this->setActive(false); }
+
+            /// Changes the visibility of the command.
+            inline ConsoleCommand& setHidden(bool bHidden)
+                { this->bHidden_ = bHidden; return *this; }
+            /// Hides the command (can still be executed, but is not visible in the list of available commands).
+            inline ConsoleCommand& hide()
+                { return this->setHidden(true); }
+            /// Makes the command visible.
+            inline ConsoleCommand& show()
+                { return this->setHidden(false); }
+
+            bool isActive() const;
+            bool hasAccess() const;
+            /// Returns true if the command is currently hidden.
+            inline bool isHidden() const
+                { return this->bHidden_; }
+
+            ConsoleCommand& description(const std::string& description);
+            const std::string& getDescription() const;
+
+            ConsoleCommand& descriptionParam(unsigned int index, const std::string& description);
+            const std::string& getDescriptionParam(unsigned int index) const;
+
+            ConsoleCommand& descriptionReturnvalue(const std::string& description);
+            const std::string& getDescriptionReturnvalue(int index) const;
+
+            ConsoleCommand& defaultValues(const MultiType& arg1);
+            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2);
+            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3);
+            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4);
+            ConsoleCommand& defaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5);
+            ConsoleCommand& defaultValue(unsigned int index, const MultiType& arg);
+
+            /// Changes the access level of the command.
+            inline ConsoleCommand& accessLevel(AccessLevel level)
+                { this->accessLevel_ = level; return *this; }
+            /// Returns the access level of the command.
+            inline AccessLevel getAccessLevel() const
+                { return this->accessLevel_; }
+
+            ConsoleCommand& argumentCompleter(unsigned int index, ArgumentCompleter* completer);
+            ArgumentCompleter* getArgumentCompleter(unsigned int index) const;
+
+            /// Defines the command to be an input command
+            inline ConsoleCommand& setAsInputCommand()
+            {
+                this->keybindMode(KeybindMode::OnHold);
+                this->defaultValue(0, Vector2(0.0f, 0.0f));
+                this->inputConfiguredParam(0);
+                return *this;
+            }
+
+            /// Sets the keybind mode. Note: use changeKeybindMode if you intend to change the mode.
+            inline ConsoleCommand& keybindMode(KeybindMode::Value mode)
+                { this->keybindMode_ = mode; return *this; }
+            /// Returns the keybind mode
+            inline KeybindMode::Value getKeybindMode() const
+                { return this->keybindMode_; }
+
+            ConsoleCommand& changeKeybindMode(KeybindMode::Value mode);
+
+            /// Changes the input configured param to the given index.
+            inline ConsoleCommand& inputConfiguredParam(int index)
+                { this->inputConfiguredParam_ = index; return *this; }
+            /// Returns the input configured param.
+            inline int getInputConfiguredParam() const
+                { return this->inputConfiguredParam_; }
+
+            /// Returns a manipulator for this command.
+            inline ConsoleCommandManipulator getManipulator()
+                { return this; }
+
+            inline const std::vector<CommandName>& getNames()
+                { return this->names_; }
+
+        private:
+            void init(const std::string& group, const std::string& name, const ExecutorPtr& executor, bool bInitialized);
+
+            bool headersMatch(const FunctorPtr& functor);
+            bool headersMatch(const ExecutorPtr& executor);
+
+            bool setFunction(const ExecutorPtr& executor, bool bForce = false);
+            bool setFunction(const FunctorPtr& functor, bool bForce = false);
+            void pushFunction(const ExecutorPtr& executor, bool bForce = false);
+            void pushFunction(const FunctorPtr& functor, bool bForce = false);
+            void pushFunction();
+            void popFunction();
+            void resetFunction();
+
+            bool setObject(void* object);
+            void pushObject(void* object);
+            void popObject();
+            void* getObject() const;
+
+            bool bActive_;                                                  ///< True if the command should be active (it can still be inactive, for example if the function is missing)
+            bool bHidden_;                                                  ///< True if the command is hidden (it is still executable, but not visible in the list of available commands)
+            AccessLevel accessLevel_;                                       ///< The access level (the state of the game in which you can access the command)
+            std::string baseName_;                                          ///< The name that was first assigned to the command
+            std::vector<CommandName> names_;                                ///< All names and aliases of this command
+            FunctorPtr baseFunctor_;                                        ///< The functor that defines the header of the command-function
+
+            ExecutorPtr executor_;                                          ///< The Executor that is used to execute the command
+            std::stack<Command> commandStack_;                              ///< A stack of commands, used to push and pop different functions
+            std::vector<void*> objectStack_;                                ///< A stack of objects, used to push and pop different objects for a function
+
+            ArgumentCompleter* argumentCompleter_[MAX_FUNCTOR_ARGUMENTS];   ///< ArgumentCompleter for each argument
+
+            KeybindMode::Value keybindMode_;                                ///< The keybind mode
+            int inputConfiguredParam_;                                      ///< The input configured param
+
+            LanguageEntryLabel description_;                                ///< The description of the command
+            LanguageEntryLabel descriptionReturnvalue_;                     ///< A description of the return-value
+            LanguageEntryLabel descriptionParam_[MAX_FUNCTOR_ARGUMENTS];    ///< A description for each argument
+    };
+}
+
+#endif /* _ConsoleCommand_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandCompilation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandCompilation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandCompilation.cc	(revision 11817)
@@ -0,0 +1,291 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of some console commands.
+*/
+
+#include "ConsoleCommandCompilation.h"
+
+#include <fstream>
+#include <set>
+#include <string>
+
+#include "util/Output.h"
+#include "util/ExprParser.h"
+#include "util/StringUtils.h"
+#include "ConsoleCommandIncludes.h"
+#include "CommandExecutor.h"
+
+namespace orxonox
+{
+    SetConsoleCommand("echo", echo);
+
+    SetConsoleCommand("orxout", orxout_level);
+    SetConsoleCommand("orxout_context", orxout_level_context);
+
+    SetConsoleCommand("log"    , log    );
+    SetConsoleCommand("error"  , error  ).hide();
+    SetConsoleCommand("warning", warning).hide();
+    SetConsoleCommand("status" , status ).hide();
+    SetConsoleCommand("info"   , info   ).hide();
+    SetConsoleCommand("debug"  , debug  ).hide();
+
+//    SetConsoleCommand("source", source).argumentCompleter(0, autocompletion::files());  // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("read", read).argumentCompleter(0, autocompletion::files());      // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("append", append).argumentCompleter(0, autocompletion::files());  // disabled because we use the implementation in Tcl
+//    SetConsoleCommand("write", write).argumentCompleter(0, autocompletion::files());    // disabled because we use the implementation in Tcl
+
+    SetConsoleCommand("calculate", calculate);
+
+    /**
+        @brief Simply returns the arguments.
+    */
+    std::string echo(const std::string& text)
+    {
+        return text;
+    }
+
+    /**
+        @brief Builds a map that maps the levels of all output levels to their ID.
+    */
+    std::map<std::string, OutputLevel> getOutputLevelsMap()
+    {
+        std::map<std::string, OutputLevel> levels;
+
+        levels["message"]          = level::message;
+        levels["debug_output"]     = level::debug_output;
+        levels["user_error"]       = level::user_error;
+        levels["user_warning"]     = level::user_warning;
+        levels["user_status"]      = level::user_status;
+        levels["user_info"]        = level::user_info;
+        levels["internal_error"]   = level::internal_error;
+        levels["internal_warning"] = level::internal_warning;
+        levels["internal_status"]  = level::internal_status;
+        levels["internal_info"]    = level::internal_info;
+        levels["verbose"]          = level::verbose;
+        levels["verbose_more"]     = level::verbose_more;
+        levels["verbose_ultra"]    = level::verbose_ultra;
+
+        return levels;
+    }
+
+    /**
+        @brief Prints text to the console.
+        @param level_name The name of the output level
+        @param text The text to print
+    */
+    void orxout_level(const std::string& level_name, const std::string& text)
+    {
+        static std::map<std::string, OutputLevel> levels = getOutputLevelsMap();
+
+        OutputLevel level = level::debug_output;
+        std::map<std::string, OutputLevel>::iterator it = levels.find(level_name);
+        if (it != levels.end())
+            level = it->second;
+        else
+            orxout(internal_warning) << "'" << level_name << "' is not a valid output level" << endl;
+
+        orxout(level) << text << endl;
+    }
+
+    /**
+        @brief Prints text to the console.
+        @param level_name The name of the output level
+        @param context_name The name of the output context
+        @param text The text to print
+    */
+    void orxout_level_context(const std::string& level_name, const std::string& context_name, const std::string& text)
+    {
+        static std::map<std::string, OutputLevel> levels = getOutputLevelsMap();
+
+        OutputLevel level = level::debug_output;
+        std::map<std::string, OutputLevel>::iterator it = levels.find(level_name);
+        if (it != levels.end())
+            level = it->second;
+        else
+            orxout(internal_warning) << "'" << level_name << "' is not a valid output level" << endl;
+
+        OutputContextContainer context = registerContext(context_name);
+
+        orxout(level, context) << text << endl;
+    }
+
+    /// @brief Prints text to the console and the logfile.
+    void log(const std::string& text)
+    { orxout() << text << endl; }
+
+    /// @brief Prints output with error level.
+    void error(const std::string& text)
+    { orxout(user_error) << text << endl; }
+
+    /// @brief Prints output with warning level.
+    void warning(const std::string& text)
+    { orxout(user_warning) << text << endl; }
+
+    /// @brief Prints output with status level.
+    void status(const std::string& text)
+    { orxout(user_status) << text << endl; }
+
+    /// @brief Prints output with info level.
+    void info(const std::string& text)
+    { orxout(user_info) << text << endl; }
+
+    /// @brief Prints debug output with verbose level.
+    void debug(const std::string& text)
+    { orxout(verbose, context::tcl) << text << endl; }
+
+    /**
+        @brief Reads the content of a file and executes the commands in it line by line.
+    */
+    void source(const std::string& filename)
+    {
+        static std::set<std::string> executingFiles;
+
+        std::set<std::string>::const_iterator it = executingFiles.find(filename);
+        if (it != executingFiles.end())
+        {
+            orxout(user_error) << "Recurring source command in \"" << filename << "\". Stopped execution." << endl;
+            return;
+        }
+
+        // Open the file
+        std::ifstream file;
+        file.open(filename.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            orxout(user_error) << "Couldn't open file \"" << filename << "\"." << endl;
+            return;
+        }
+
+        executingFiles.insert(filename);
+
+        // Iterate through the file and put the lines into the CommandExecutor
+        while (file.good() && !file.eof())
+        {
+            std::string line;
+            std::getline(file, line);
+            CommandExecutor::execute(line);
+        }
+
+        executingFiles.erase(filename);
+        file.close();
+    }
+
+    /**
+        @brief Writes text to a file.
+    */
+    void write(const std::string& filename, const std::string& text)
+    {
+        std::ofstream file;
+        file.open(filename.c_str(), std::fstream::out);
+
+        if (!file.is_open())
+        {
+            orxout(user_error) << "Couldn't write to file \"" << filename << "\"." << endl;
+            return;
+        }
+
+        file << text << endl;
+        file.close();
+    }
+
+    /**
+        @brief Appends text to a file.
+    */
+    void append(const std::string& filename, const std::string& text)
+    {
+        std::ofstream file;
+        file.open(filename.c_str(), std::fstream::app);
+
+        if (!file.is_open())
+        {
+            orxout(user_error) << "Couldn't append to file \"" << filename << "\"." << endl;
+            return;
+        }
+
+        file << text << endl;
+        file.close();
+    }
+
+    /**
+        @brief Reads text from a file
+    */
+    std::string read(const std::string& filename)
+    {
+        std::ifstream file;
+        file.open(filename.c_str(), std::fstream::in);
+
+        if (!file.is_open())
+        {
+            orxout(user_error) << "Couldn't read from file \"" << filename << "\"." << endl;
+            return "";
+        }
+
+        std::string output;
+        while (file.good() && !file.eof())
+        {
+            std::string line;
+            std::getline(file, line);
+            output += line;
+            output += "\n";
+        }
+
+        file.close();
+
+        return output;
+    }
+
+    /**
+        @brief Parses the mathematical expression and returns the result.
+    */
+    float calculate(const std::string& calculation)
+    {
+        ExprParser expr;
+        expr.parse(calculation);
+        if (expr.getSuccess())
+        {
+            if (expr.getResult() == 42.0)
+            {
+                orxout(user_info) << "Greetings from the restaurant at the end of the universe." << endl;
+            }
+            if (!expr.getRemains().empty())
+            {
+                orxout(user_warning) << "Expression could not be parsed to the end! Remains: '" << expr.getRemains() << '\'' << endl;
+            }
+            return static_cast<float>(expr.getResult());
+        }
+        else
+        {
+            orxout(user_error) << "Cannot calculate expression: Parse error." << endl;
+            return 0;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandCompilation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandCompilation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandCompilation.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ConsoleCommand
+    @brief Declaration of some console commands.
+*/
+
+#ifndef _ConsoleCommandCompilation_H__
+#define _ConsoleCommandCompilation_H__
+
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    _CoreExport void source(const std::string& filename);
+    _CoreExport std::string echo(const std::string& text);
+
+    _CoreExport void orxout_level(const std::string& level_name, const std::string& text);
+    _CoreExport void orxout_level_context(const std::string& level_name, const std::string& context_name, const std::string& text);
+
+    _CoreExport void log(const std::string& text);
+    _CoreExport void error(const std::string& text);
+    _CoreExport void warning(const std::string& text);
+    _CoreExport void status(const std::string& text);
+    _CoreExport void info(const std::string& text);
+    _CoreExport void debug(const std::string& text);
+
+    _CoreExport void write(const std::string& filename, const std::string& text);
+    _CoreExport void append(const std::string& filename, const std::string& text);
+    _CoreExport std::string read(const std::string& filename);
+
+    _CoreExport float calculate(const std::string& calculation);
+}
+
+#endif /* _ConsoleCommandCompilation_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandIncludes.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandIncludes.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandIncludes.cc	(revision 11817)
@@ -0,0 +1,44 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ConsoleCommandIncludes.h"
+
+#include "ConsoleCommandManager.h"
+
+namespace orxonox
+{
+    void StaticallyInitializedConsoleCommand::load()
+    {
+        ConsoleCommandManager::getInstance().registerCommand(this->command_);
+    }
+
+    void StaticallyInitializedConsoleCommand::unload()
+    {
+        ConsoleCommandManager::getInstance().unregisterCommand(this->command_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandIncludes.h	(revision 11817)
@@ -0,0 +1,350 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup ConsoleCommand Console commands
+    @ingroup Command
+*/
+
+/**
+    @file
+    @ingroup Command ConsoleCommand
+    @brief Declaration the SetConsoleCommand() macro.
+
+    @anchor ConsoleCommandExample
+
+    Console commands can be used to write scripts, use key-bindings or simply to be
+    entered into the shell by the user. Instances of orxonox::ConsoleCommand define
+    the function of a command, and also more information like, for example, if it is
+    active, default values, and possible arguments.
+
+    Commands need to be registered to the system statically on startup by using the
+    SetConsoleCommand() or DeclareConsoleCommand() macros outside of a function.
+    This ensures that commands are known to the system at any time, so they can be
+    evaluated (see orxonox::CommandExecutor::evaluate()), for example for key-bindings.
+
+    Example:
+    @code
+    void myCoutFunction(const std::string& text)        // Define a static function
+    {
+        orxout() << "Text: " << text << endl;           // Print the text to the console
+    }
+
+    SetConsoleCommand("cout", &myCoutFunction);         // Register the function as command with name "cout"
+    @endcode
+
+    Now you can open the shell and execute the command:
+    @code
+    $ cout Hello World
+    @endcode
+
+    Internally this command is now passed to orxonox::CommandExecutor::execute():
+    @code
+    CommandExecutor::execute("cout HelloWorld");
+    @endcode
+
+    CommandExecutor searches for a command with name "cout" and passes the arguments
+    "Hello World" to it. Because we registered myCoutFunction() with this command,
+    as a result the following text will be printed to the console:
+    @code
+    Text: Hello World
+    @endcode
+
+    You can add more attributes to the ConsoleCommand, by using the command-chain feature
+    of SetConsoleCommand(). For example like this:
+    @code
+    SetConsoleCommand("cout", &myCoutFunction)
+        .addGroup("output", "text")
+        .accessLevel(AccessLevel::Offline)
+        .defaultValues("no text");
+    @endcode
+
+    Open the shell again and try it:
+    @code
+    $ cout Hello World
+    Text: Hello World
+    $ output text Hello World
+    Text: Hello World
+    $ cout
+    Text: no text
+    @endcode
+
+    If you execute it online (note: the access level is "Offline"), you will see the
+    following (or something similar):
+    @code
+    $ cout Hello World
+    Error: Can't execute command "cout", access denied.
+    @endcode
+
+    If a command is executed, the arguments are passed to an underlying function,
+    whitch is wrapped by an orxonox::Functor which again is wrapped by an orxonox::Executor.
+    The Functor contains the function-pointer, as well as the object-pointer in
+    case of a non-static member-function. The executor stores possible default-values
+    for each argument of the function.
+
+    The function of a command can be changed at any time. It's possible to just exchange
+    the function-pointer of the underlying Functor if the headers of the functions are
+    exactly the same. But you can also exchange the Functor itself or even completely
+    replace the Executor. Also the other attributes of a ConsoleCommand can be modified
+    during the game, for example it can be activated or deactivated.
+
+    To do so, the function ModifyConsoleCommand() has to be used. It returns an instance
+    of orxonox::ConsoleCommand::ConsoleCommandManipulator which has an interface similar to
+    orxonox::ConsoleCommand, but with slight differences. You can use it the same way like
+    SetConsoleCommand(), meaning you can use command-chains to change different attributes at
+    the same time. ModifyConsoleCommand() must not be executed statically, but rather in a
+    function at some point of the execution of the program.
+
+    Example:
+    @code
+    void myOtherCoutFunction(const std::string& text)                       // Define a new static function
+    {
+        orxout() << "Uppercase: " << getUppercase(text) << endl;            // Print the text in uppercase to the console
+    }
+
+    {
+        // ...                                                              // somewhere in the code
+
+        ModifyConsoleCommand("cout").setFunction(&myOtherCoutFunction);     // Modify the underlying function of the command
+
+        // ...
+    }
+    @endcode
+
+    If you now enter the command into the shell, you'll see a different behavior:
+    @code
+    $ cout Hello World
+    Uppercase: HELLO WORLD
+    $ cout
+    Uppercase: NO TEXT
+    @endcode
+
+    A few important notes about changing functions:
+
+    Instead of changing the function with setFunction(), you can also create a command-stack
+    by using pushFunction() and popFunction(). It's important to note a few things about that,
+    because the underlying structure of Executor and Functor has a few pitfalls:
+     - If you push a new function-pointer, the same executor as before will be used (and, if
+       the headers match, even the same functor can be used, which is very fast)
+     - If you push a new Functor, the same executor as before will be used
+     - If you push a new Executor, everything is changed
+
+    Note that the executor contains the @b default @b values, so if you just exchange the
+    Functor, the default values remain the same. However if you decide to change the default
+    values at any point of the stack, <b>this will also change the default values on all
+    other stack-levels</b> that share the same executor. If you don't like this behavior,
+    you have to explicitly push a new executor before changing the default values, either by
+    calling pushFunction(executor) or by calling pushFunction(void) which pushes a copy of
+    the current executor to the stack.
+
+    Another important point are object pointers in case of non-static member-functions.
+    Whenever you set or push a new function, <b>you must add the object pointer again</b>
+    because objects are stored in the Functor which is usually exchanged if you change
+    the function.
+
+    You can also use a stack for objects, but note that this <b>object-stack is different for each
+    function</b> - so if you set a new function, the object-stack will be cleared. If you push
+    a new function, the old object-stack is stored in the stack, so it can be restored if
+    you pop the function.
+
+    %DeclareConsoleCommand():
+
+    Appart from SetConsoleCommand() you can also call DeclareConsoleCommand(). In contrast
+    to SetConsoleCommand(), this doesn't assign a function to the command. Indeed you have
+    to pass a function-pointer to DeclareConsoleCommand(), but it is only used to determine
+    the header of the future command-function. This allows to declare a command statically,
+    thus it's possible to evaluate key-bindings of this command, but the actual function
+    can be assigned at a later point.
+
+    Example:
+    @code
+    DeclareConsoleCommand("cout", &prototype::void__string);
+    @endcode
+
+    If you try to execute the command now, you see the following (or something similar):
+    @code
+    $ cout Hello World
+    Error: Can't execute command "cout", command is not active.
+    @endcode
+
+    You first have to assign a function to use the command:
+    @code
+    {
+        // ...
+
+        ModifyConsoleCommand("cout").setFunction(&myCoutFunction);
+
+        // ...
+    }
+    @endcode
+
+    Now you can use it:
+    @code
+    $ cout Hello World
+    Text: Hello World
+    @endcode
+
+    Note that the initial function prototype::void__string is defined in the namespace
+    orxonox::prototype. If there's no function with the desired header, you can extend
+    the collection of functions or simply use another function that has the same header.
+*/
+
+#ifndef _ConsoleCommandIncludes_H__
+#define _ConsoleCommandIncludes_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ConsoleCommand.h"
+#include "ConsoleCommandManager.h"
+#include "util/VA_NARGS.h"
+#include "core/module/StaticallyInitializedInstance.h"
+
+
+/**
+    @brief Defines a console command. The macro is overloaded for 2-4 parameters.
+
+    This is an overloaded macro. Depending on the number of arguments a different
+    overloaded implementation of the macro will be chosen.
+
+    Console commands created with SetConsoleCommand() become active immediately and
+    the given function-pointer (and optionally the object) will be used to execute
+    the command.
+*/
+#define SetConsoleCommand(...) \
+    BOOST_PP_EXPAND(BOOST_PP_CAT(SetConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+/**
+    @brief This macro is executed if you call SetConsoleCommand() with 2 arguments.
+    @param name The name (string) of the console command
+    @param functionpointer The function-pointer of the corresponding command-function
+*/
+#define SetConsoleCommand2(name, functionpointer) \
+    SetConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
+/**
+    @brief This macro is executed if you call SetConsoleCommand() with 3 arguments.
+    @param group The group (string) of the console command
+    @param name The name (string) of the console command
+    @param functionpointer The function-pointer of the corresponding command-function
+*/
+#define SetConsoleCommand3(group, name, functionpointer) \
+    SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
+/**
+    @brief This macro is executed if you call SetConsoleCommand() with 4 arguments.
+    @param group The group (string) of the console command
+    @param name The name (string) of the console command
+    @param functionpointer The function-pointer of the corresponding command-function
+    @param object The object that will be assigned to the command. Used for member-functions.
+*/
+#define SetConsoleCommand4(group, name, functionpointer, object) \
+    SetConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer, object))
+
+/// Internal macro
+#define SetConsoleCommandGeneric(group, name, functor) \
+    static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __UNIQUE_NUMBER__) \
+        = (new orxonox::SI_CC(new orxonox::ConsoleCommand(group, name, orxonox::createExecutor(functor))))->getCommand()
+
+
+/**
+    @brief Declares a console command. The macro is overloaded for 2-3 parameters.
+
+    This is an overloaded macro. Depending on the number of arguments a different
+    overloaded implementation of the macro will be chosen.
+
+    Console commands created with DeclareConsoleCommand() don't use the the given
+    function-pointer to execute the command, it is only used to define the header
+    of the future command-function. The command is inactive until you manually
+    set a function with orxonox::ModifyConsoleCommand(). You can use a different
+    function-pointer than in the final command, as long as it has the same header.
+*/
+#define DeclareConsoleCommand(...) \
+    BOOST_PP_EXPAND(BOOST_PP_CAT(DeclareConsoleCommand, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+/**
+    @brief This macro is executed if you call DeclareConsoleCommand() with 2 arguments.
+    @param name The name (string) of the console command
+    @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
+*/
+#define DeclareConsoleCommand2(name, functionpointer) \
+    DeclareConsoleCommandGeneric("", name, orxonox::createFunctor(functionpointer))
+/**
+    @brief This macro is executed if you call DeclareConsoleCommand() with 3 arguments.
+    @param group The group (string) of the console command
+    @param name The name (string) of the console command
+    @param functionpointer The function-pointer of an arbitrary function that has the same header as the final function
+*/
+#define DeclareConsoleCommand3(group, name, functionpointer) \
+    DeclareConsoleCommandGeneric(group, name, orxonox::createFunctor(functionpointer))
+
+/// Internal macro
+#define DeclareConsoleCommandGeneric(group, name, functor) \
+    static orxonox::ConsoleCommand& BOOST_PP_CAT(__consolecommand_, __UNIQUE_NUMBER__) \
+        = (new orxonox::SI_CC(new orxonox::ConsoleCommand(group, name, orxonox::createExecutor(functor), false)))->getCommand()
+
+
+namespace orxonox
+{
+    class _CoreExport StaticallyInitializedConsoleCommand : public StaticallyInitializedInstance
+    {
+        public:
+            StaticallyInitializedConsoleCommand(ConsoleCommand* command)
+                : StaticallyInitializedInstance(StaticInitialization::CONSOLE_COMMAND)
+                , command_(command)
+            {}
+            ~StaticallyInitializedConsoleCommand() { delete command_; }
+
+            virtual void load() override;
+            virtual void unload() override;
+
+            inline ConsoleCommand& getCommand()
+                { return *this->command_; }
+
+        private:
+            ConsoleCommand* command_;
+    };
+
+    typedef StaticallyInitializedConsoleCommand SI_CC;
+
+    /**
+        @brief Returns a manipulator for a command with the given name.
+
+        @note If the command doesn't exist, the manipulator contains a nullptr to the command,
+        but it can still be used without checks, because all functions of ConsoleCommandManipulator
+        check internally if the command exists.
+    */
+    inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& name)
+        { return ConsoleCommandManager::getInstance().getCommand(name, true); }
+    /**
+        @brief Returns a manipulator for a command with the given group and name.
+
+        @note If the command doesn't exist, the manipulator contains a nullptr to the command,
+        but it can still be used without checks, because all functions of ConsoleCommandManipulator
+        check internally if the command exists.
+    */
+    inline ConsoleCommand::ConsoleCommandManipulator ModifyConsoleCommand(const std::string& group, const std::string& name)
+        { return ConsoleCommandManager::getInstance().getCommand(group, name, true); }
+}
+
+#endif /* _ConsoleCommandIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandManager.cc	(revision 11817)
@@ -0,0 +1,189 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the ConsoleCommand class.
+*/
+
+#include "ConsoleCommandManager.h"
+
+#include "ConsoleCommand.h"
+#include "util/StringUtils.h"
+
+namespace orxonox
+{
+    ConsoleCommandManager* ConsoleCommandManager::singletonPtr_s = nullptr;
+
+    /**
+        @brief Returns the command with given group an name.
+        @param group The group of the requested command
+        @param name The group of the requested command
+        @param bPrintError If true, an error is printed if the command doesn't exist
+    */
+    ConsoleCommand* ConsoleCommandManager::getCommand(const std::string& group, const std::string& name, bool bPrintError)
+    {
+        // find the group
+        std::map<std::string, std::map<std::string, ConsoleCommand*>>::const_iterator it_group = this->commandMap_.find(group);
+        if (it_group != this->commandMap_.end())
+        {
+            // find the name
+            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(name);
+            if (it_name != it_group->second.end())
+            {
+                // return the pointer
+                return it_name->second;
+            }
+        }
+        if (bPrintError)
+        {
+            if (group == "")
+                orxout(internal_error, context::commands) << "Couldn't find console command with shortcut \"" << name << "\"" << endl;
+            else
+                orxout(internal_error, context::commands) << "Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << endl;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Returns the command with given group an name in lowercase.
+        @param group The group of the requested command in lowercase
+        @param name The group of the requested command in lowercase
+        @param bPrintError If true, an error is printed if the command doesn't exist
+    */
+    ConsoleCommand* ConsoleCommandManager::getCommandLC(const std::string& group, const std::string& name, bool bPrintError)
+    {
+        std::string groupLC = getLowercase(group);
+        std::string nameLC = getLowercase(name);
+
+        // find the group
+        std::map<std::string, std::map<std::string, ConsoleCommand*>>::const_iterator it_group = this->commandMapLC_.find(groupLC);
+        if (it_group != this->commandMapLC_.end())
+        {
+            // find the name
+            std::map<std::string, ConsoleCommand*>::const_iterator it_name = it_group->second.find(nameLC);
+            if (it_name != it_group->second.end())
+            {
+                // return the pointer
+                return it_name->second;
+            }
+        }
+        if (bPrintError)
+        {
+            if (group == "")
+                orxout(internal_error, context::commands) << "Couldn't find console command with shortcut \"" << name << "\"" << endl;
+            else
+                orxout(internal_error, context::commands) << "Couldn't find console command with group \"" << group << "\" and name \"" << name << "\"" << endl;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Registers a new command with the groups and names that are defined by ConsoleCommand::getNames().
+    */
+    void ConsoleCommandManager::registerCommand(ConsoleCommand* command)
+    {
+        for (size_t i = 0; i < command->getNames().size(); ++i)
+        {
+            const ConsoleCommand::CommandName& name = command->getNames()[i];
+            this->registerCommand(name.group_, name.name_, command);
+        }
+    }
+
+    /**
+        @brief Registers a new command with given group an name by adding it to the command map.
+    */
+    void ConsoleCommandManager::registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command)
+    {
+        if (name == "")
+            return;
+
+        // check if a command with this name already exists
+        if (this->getCommand(group, name) != nullptr)
+        {
+            if (group == "")
+                orxout(internal_warning, context::commands) << "A console command with shortcut \"" << name << "\" already exists." << endl;
+            else
+                orxout(internal_warning, context::commands) << "A console command with name \"" << name << "\" already exists in group \"" << group << "\"." << endl;
+        }
+        else
+        {
+            // add the command to the map
+            this->commandMap_[group][name] = command;
+            this->commandMapLC_[getLowercase(group)][getLowercase(name)] = command;
+        }
+    }
+
+    /**
+        @brief Removes the command from the command map.
+    */
+    void ConsoleCommandManager::unregisterCommand(ConsoleCommand* command)
+    {
+        // iterate through all groups
+        for (std::map<std::string, std::map<std::string, ConsoleCommand*>>::iterator it_group = this->commandMap_.begin(); it_group != this->commandMap_.end(); )
+        {
+            // iterate through all commands of each group
+            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
+            {
+                // erase the command
+                if (it_name->second == command)
+                    it_group->second.erase(it_name++);
+                else
+                    ++it_name;
+            }
+
+            // erase the group if it is empty now
+            if (it_group->second.empty())
+                this->commandMap_.erase(it_group++);
+            else
+                ++it_group;
+        }
+
+        // now the same for the lowercase-map:
+
+        // iterate through all groups
+        for (std::map<std::string, std::map<std::string, ConsoleCommand*>>::iterator it_group = this->commandMapLC_.begin(); it_group != this->commandMapLC_.end(); )
+        {
+            // iterate through all commands of each group
+            for (std::map<std::string, ConsoleCommand*>::iterator it_name = it_group->second.begin(); it_name != it_group->second.end(); )
+            {
+                // erase the command
+                if (it_name->second == command)
+                    it_group->second.erase(it_name++);
+                else
+                    ++it_name;
+            }
+
+            // erase the group if it is empty now
+            if (it_group->second.empty())
+                this->commandMapLC_.erase(it_group++);
+            else
+                ++it_group;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ConsoleCommandManager.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup ConsoleCommand Console commands
+    @ingroup Command
+*/
+
+#ifndef _ConsoleCommandManager_H__
+#define _ConsoleCommandManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include "util/Singleton.h"
+
+#include <map>
+
+namespace orxonox
+{
+    /**
+     * A singleton that stores all existing ConsoleCommands.
+     */
+    class _CoreExport ConsoleCommandManager : public Singleton<ConsoleCommandManager>
+    {
+        friend class Singleton<ConsoleCommandManager>;
+
+        public:
+            void registerCommand(ConsoleCommand* command);
+            void registerCommand(const std::string& group, const std::string& name, ConsoleCommand* command);
+            void unregisterCommand(ConsoleCommand* command);
+
+            /// Returns the map with all groups and commands.
+            inline const std::map<std::string, std::map<std::string, ConsoleCommand*>>& getCommands()
+                { return this->commandMap_; }
+            /// Returns the map with all groups and commands in lowercase.
+            inline const std::map<std::string, std::map<std::string, ConsoleCommand*>>& getCommandsLC()
+                { return this->commandMapLC_; }
+
+            /// Returns a command (shortcut) with given name. @param name The name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
+            inline ConsoleCommand* getCommand(const std::string& name, bool bPrintError = false)
+                { return this->getCommand("", name, bPrintError); }
+            /// Returns a command (shortcut) with given name in lowercase. @param name The lowercase name of the command shortcut @param bPrintError If true, an error is printed if the command doesn't exist
+            inline ConsoleCommand* getCommandLC(const std::string& name, bool bPrintError = false)
+                { return this->getCommandLC("", name, bPrintError); }
+
+            ConsoleCommand* getCommand(const std::string& group, const std::string& name, bool bPrintError = false);
+            ConsoleCommand* getCommandLC(const std::string& group, const std::string& name, bool bPrintError = false);
+
+        private:
+            std::map<std::string, std::map<std::string, ConsoleCommand*>> commandMap_;
+            std::map<std::string, std::map<std::string, ConsoleCommand*>> commandMapLC_;
+
+            static ConsoleCommandManager* singletonPtr_s;
+    };
+}
+
+#endif /* _ConsoleCommandManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/Executor.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/Executor.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/Executor.cc	(revision 11817)
@@ -0,0 +1,219 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ *   Inspiration: Executor by Benjamin Grauer
+ */
+
+/**
+    @file
+    @brief Implementation of orxonox::Executor
+*/
+
+#include "Executor.h"
+
+#include <algorithm>
+
+#include "util/Convert.h"
+#include "util/Output.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+#include "CommandExecutor.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: Creates an executor.
+        @param functor The wrapped functor
+        @param name The name of the executor (optional, used mostly for debug output)
+    */
+    Executor::Executor(const FunctorPtr& functor, const std::string& name)
+    {
+        this->functor_ = functor;
+        this->name_ = name;
+    }
+
+    /**
+        @brief Copy-constructor: Creates a new executor with the same values and a clone of the wrapped Functor.
+    */
+    Executor::Executor(const Executor& other) : name_(other.name_)
+    {
+        for (size_t i = 0; i < MAX_FUNCTOR_ARGUMENTS; ++i)
+            defaultValue_[i] = other.defaultValue_[i];
+        this->functor_ = other.functor_->clone();
+    }
+
+    /**
+        @brief Calls the wrapped function with arguments that are passed in a string.
+        @param arguments The arguments that should be passed to the function, separated by @a delimiter
+        @param error A pointer to a variable (or nullptr) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+        @param delimiter The delimiter that is used to separate the arguments in the string @a arguments
+        @param bPrintError If true, errors are printed to the console if the function couldn't be executed with the given arguments
+        @return Returns the return value of the function (or MultiType::Null if there is no return value)
+    */
+    MultiType Executor::parse(const std::string& arguments, int* error, const std::string& delimiter, bool bPrintError) const
+    {
+        return this->parse(SubString(arguments, delimiter, SubString::WhiteSpaces, false, '\\', true, '"', true, '{', '}', true, '\0'), error, delimiter, bPrintError);
+    }
+
+    /**
+        @brief Calls the wrapped function with arguments that are passed as tokens in a SubString
+        @param arguments The arguments that should be passed to the function
+        @param error A pointer to a variable (or nullptr) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+        @param delimiter The delimiter that was used to separate the arguments in the SubString @a arguments (used to join the surplus arguments)
+        @param bPrintError If true, errors are printed to the console if the function couldn't be executed with the given arguments
+        @return Returns the return value of the function (or MultiType::Null if there is no return value)
+    */
+    MultiType Executor::parse(const SubString& arguments, int* error, const std::string& delimiter, bool bPrintError) const
+    {
+        // evaluate the arguments
+        MultiType arg[MAX_FUNCTOR_ARGUMENTS];
+        unsigned int argCount = this->evaluateArguments(arguments, arg, error, delimiter);
+
+        // check if an error occurred
+        if (error && *error)
+        {
+            if (bPrintError)
+                orxout(internal_warning) << "Can't call executor " << this->name_ << " through parser: Not enough arguments or default values given (input: " << arguments.join() << ")." << endl;
+            return MultiType::Null;
+        }
+
+        orxout(verbose, context::misc::executor) << "Executor::parse: \"" << arguments.join(delimiter) << "\" -> " << argCount << " arguments: " << arg[0] << " / " << arg[1] << " / " << arg[2] << " / " << arg[3] << " / " << arg[4] << endl;
+
+        // execute the function with the evaluated arguments (the default values of the executor are also included in these arguments)
+        switch (argCount)
+        {
+            case 0:  return (*this->functor_)();
+            case 1:  return (*this->functor_)(arg[0]);
+            case 2:  return (*this->functor_)(arg[0], arg[1]);
+            case 3:  return (*this->functor_)(arg[0], arg[1], arg[2]);
+            case 4:  return (*this->functor_)(arg[0], arg[1], arg[2], arg[3]);
+            case 5:
+            default: return (*this->functor_)(arg[0], arg[1], arg[2], arg[3], arg[4]);
+        }
+    }
+
+    /**
+        @brief Converts the arguments in a SubString to the right type, so they can be used to execute the function without further conversions.
+        @param arguments The arguments that should be converted
+        @param arg An array of MultiType where the converted arguments will be stored
+        @param error A pointer to a variable (or nullptr) that is used to store the error code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+        @param delimiter The delimiter that was used to separate the arguments in the SubString @a arguments (used to join the surplus arguments)
+        @return Returns the number of evaluated arguments
+    */
+    int Executor::evaluateArguments(const SubString& arguments, MultiType arg[MAX_FUNCTOR_ARGUMENTS], int* error, const std::string& delimiter) const
+    {
+        unsigned int paramCount = this->functor_->getParamCount();
+        unsigned int argumentCount = arguments.size();
+
+        // if there are not enough params given, check if there are default values
+        for (unsigned int i = argumentCount; i < paramCount; i++)
+        {
+            if (this->defaultValue_[i].null())
+            {
+                if (error)
+                    *error = CommandExecutor::Incomplete;
+                return 0;
+            }
+        }
+
+        // assign all given arguments to the multitypes
+        for (unsigned int i = 0; i < std::min(std::min(argumentCount, paramCount), MAX_FUNCTOR_ARGUMENTS); i++)
+            arg[i] = arguments[i];
+
+        // fill the remaining multitypes with default values
+        for (unsigned int i = argumentCount; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
+            arg[i] = this->defaultValue_[i];
+
+        // assign the remaining arguments all to the last parameter if it is a string
+        if ((paramCount <= MAX_FUNCTOR_ARGUMENTS) &&(argumentCount > paramCount) && (paramCount == 1 || this->functor_->getTypenameParam(paramCount - 1) == "string"))
+            arg[paramCount - 1] = arguments.subSet(paramCount - 1).join(delimiter);
+
+        // evaluate the parameter types through the functor
+        for (unsigned int i = 0; i < std::min(paramCount, MAX_FUNCTOR_ARGUMENTS); i++)
+            this->functor_->evaluateArgument(i, arg[i]);
+
+        if (error)
+            *error = CommandExecutor::Success;
+        return paramCount;
+    }
+
+    /// Defines the default value for the first parameter.
+    void Executor::setDefaultValues(const MultiType& arg1)
+    {
+        this->defaultValue_[0] = arg1;
+    }
+
+    /// Defines the default value for the first two parameters.
+    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2)
+    {
+        this->defaultValue_[0] = arg1;
+        this->defaultValue_[1] = arg2;
+    }
+
+    /// Defines the default value for the first three parameters.
+    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3)
+    {
+        this->defaultValue_[0] = arg1;
+        this->defaultValue_[1] = arg2;
+        this->defaultValue_[2] = arg3;
+    }
+
+    /// Defines the default value for the first four parameters.
+    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4)
+    {
+        this->defaultValue_[0] = arg1;
+        this->defaultValue_[1] = arg2;
+        this->defaultValue_[2] = arg3;
+        this->defaultValue_[3] = arg4;
+    }
+
+    /// Defines the default value for the first five parameters.
+    void Executor::setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5)
+    {
+        this->defaultValue_[0] = arg1;
+        this->defaultValue_[1] = arg2;
+        this->defaultValue_[2] = arg3;
+        this->defaultValue_[3] = arg4;
+        this->defaultValue_[4] = arg5;
+    }
+
+    /// Defines the default value for a parameter with given index (the first parameter has index 0).
+    void Executor::setDefaultValue(unsigned int index, const MultiType& arg)
+    {
+        if (index < MAX_FUNCTOR_ARGUMENTS)
+            this->defaultValue_[index] = arg;
+    }
+
+    /// Returns true if the executor has a default value for each parameter of the wrapped function, so it can be called without passing additional arguments.
+    bool Executor::allDefaultValuesSet() const
+    {
+        for (unsigned int i = 0; i < this->functor_->getParamCount(); i++)
+            if (this->defaultValue_[i].null())
+                return false;
+
+        return true;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/Executor.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/Executor.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/Executor.h	(revision 11817)
@@ -0,0 +1,286 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ *   Inspiration: Executor by Benjamin Grauer
+ */
+
+/**
+    @defgroup FunctorExecutor Functor and Executor
+    @ingroup Command
+*/
+
+/**
+    @file
+    @ingroup Command FunctorExecutor
+    @brief Declaration of the orxonox::Executor class and the createExecutor() functions.
+
+    @anchor ExecutorExample
+
+    orxonox::Executor is used to wrap an orxonox::Functor and to store default values for
+    its parameters. Usually one uses the function createExecutor() to create a new executor.
+    This function returns an orxonox::ExecutorPtr which is a typedef of "std::shared_ptr<Executor>",
+    used to manage the pointer to the executor.
+
+    Executors are mostly used to execute callbacks. Because some callback functions need arguments,
+    Executor provides an easy interface to store these arguments as default values, so the
+    executor can also be executed without arguments because it will use these default values.
+
+    The Executor doesn't contain the function-pointer directly. Instead it wraps an instance
+    of orxonox::Functor. See @ref FunctorExample "Functor.h" for more information and some
+    examples.
+
+    Example:
+    @code
+    void myFunction(int a, int b)                           // declare a static function
+    {
+        orxout() << "The sum is " << (a + b) << endl;       // print the sum of a and b to the console
+    }
+
+    FunctorPtr functor = createFunctor(&myFunction);        // create a functor that wraps the function-pointer
+    ExecutorPtr executor = createExecutor(functor);         // create an executor that wraps the functor
+
+    (*executor)(2, 5);                                      // calls the executor with arguments 2 and 5, prints "The sum is 7" to the console
+
+    executor->setDefaultValue(1, 10);                       // sets the default-value for the second parameter (note: paramters start at index 0) to 10
+
+    (*executor)(2);                                         // calls the executor with argument 2 and default-value 10, prints "The sum is 12"
+
+    executor->setDefaultValue(0, 5);                        // sets the default-value for the first parameter to 5
+
+    (*executor)();                                          // calls the executor with default-values only, prints "The sum is 15"
+    @endcode
+
+    Executors don't need to be deleted after usage normally because they are managed by an
+    std::shared_ptr when they were created with createExecutor().
+*/
+
+#ifndef _Executor_H__
+#define _Executor_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+#include "util/MultiType.h"
+#include "Functor.h"
+#include "ExecutorPtr.h"
+
+namespace orxonox
+{
+    /**
+        @brief This class is used to wrap a Functor and to store default values for any of its parameters.
+
+        @see See @ref ExecutorExample "Executor.h" for an example.
+    */
+    class _CoreExport Executor
+    {
+        public:
+            Executor(const FunctorPtr& functor, const std::string& name = "");
+            Executor(const Executor& other);
+            virtual ~Executor() = default;
+
+            /// Calls the wrapped function with 0 arguments. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()() const
+                { return (*this->functor_)(this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 1 argument. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(const MultiType& arg1) const
+                { return (*this->functor_)(arg1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 2 arguments. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(const MultiType& arg1, const MultiType& arg2) const
+                { return (*this->functor_)(arg1, arg2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 3 arguments. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3) const
+                { return (*this->functor_)(arg1, arg2, arg3, this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 4 arguments. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4) const
+                { return (*this->functor_)(arg1, arg2, arg3, arg4, this->defaultValue_[4]); }
+            /// Calls the wrapped function with 5 arguments. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5) const
+                { return (*this->functor_)(arg1, arg2, arg3, arg4, arg5); }
+
+            MultiType parse(const std::string& arguments, int* error = nullptr, const std::string& delimiter = " ", bool bPrintError = false) const;
+            MultiType parse(const SubString& arguments, int* error = nullptr, const std::string& delimiter = " ", bool bPrintError = false) const;
+
+            int evaluateArguments(const SubString& arguments, MultiType arg[MAX_FUNCTOR_ARGUMENTS], int* error = nullptr, const std::string& delimiter = " ") const;
+
+            /// Changes the functor.
+            inline void setFunctor(const FunctorPtr& functor)
+                { this->functor_ = functor; }
+            /// Returns the functor.
+            inline const FunctorPtr& getFunctor() const
+                { return this->functor_; }
+
+            /// Changes the name of the executor.
+            inline void setName(const std::string& name)
+                { this->name_ = name; }
+            /// Returns the name of the executor.
+            inline const std::string& getName() const
+                { return this->name_; }
+
+            /// Returns the number of parameters of the wrapped function.
+            inline unsigned int getParamCount() const
+                { return this->functor_->getParamCount(); }
+            /// Returns true if the wrapped function returns a value.
+            inline bool hasReturnvalue() const
+                { return this->functor_->hasReturnvalue(); }
+            /// Returns the type of the wrapped function (static or member).
+            inline Functor::Type getType() const
+                { return this->functor_->getType(); }
+            /// Returns the name of the type of a parameter with given index (the first parameter has index 0).
+            inline std::string getTypenameParam(unsigned int param) const
+                { return this->functor_->getTypenameParam(param); }
+            /// Returns the name of the type of the return value.
+            inline std::string getTypenameReturnvalue() const
+                { return this->functor_->getTypenameReturnvalue(); }
+
+            void setDefaultValues(const MultiType& arg1);
+            void setDefaultValues(const MultiType& arg1, const MultiType& arg2);
+            void setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3);
+            void setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4);
+            void setDefaultValues(const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5);
+            void setDefaultValue(unsigned int index, const MultiType& arg);
+
+            /// Returns the default value for a parameter with given index (the first parameter has index 0).
+            inline MultiType getDefaultValue(unsigned int index) const
+            {
+                if (index < MAX_FUNCTOR_ARGUMENTS)
+                    return this->defaultValue_[index];
+
+                return MultiType::Null;
+            }
+
+            bool allDefaultValuesSet() const;
+
+            /// Returns true if the executor contains a default value for the parameter with given index (the first parameter has index 0).
+            inline bool defaultValueSet(unsigned int index) const
+            {
+                if (index < MAX_FUNCTOR_ARGUMENTS)
+                    return !this->defaultValue_[index].null();
+
+                return false;
+            }
+
+        protected:
+            FunctorPtr functor_;                                ///< The underlying Functor that wraps a function
+            std::string name_;                                  ///< The name of the executor
+            MultiType defaultValue_[MAX_FUNCTOR_ARGUMENTS];     ///< The default values, one for each parameter
+    };
+
+    /**
+        @brief A child class of Executor, used to distinguish executors that wrap static functions from executors that wrap member-functions.
+
+        Behaves exactly like Executor, because static functions need no special treatment.
+    */
+    class _CoreExport ExecutorStatic : public Executor
+    {
+        public:
+            /// Constructor: Initializes the parent class
+            ExecutorStatic(const FunctorStaticPtr& functor, const std::string& name = "") : Executor(functor, name) {}
+            /// Destructor
+            virtual ~ExecutorStatic() {}
+    };
+
+    /**
+        @brief A child class of Executor, used for easier handling of non-static member-functions.
+
+        Overloads some functions that call the underlying FunctorMember and additionally pass
+        an object-pointer that is needed for non-static member-functions.
+    */
+    template <class T>
+    class ExecutorMember : public Executor
+    {
+        public:
+            /// Constructor: Initializes the parent class and the pointer to the member-functor.
+            ExecutorMember(const FunctorMemberPtr<T>& functor, const std::string& name = "") : Executor(functor, name), functorMember_(functor) {}
+            /// Destructor
+            virtual ~ExecutorMember() {}
+
+            using Executor::operator();
+
+            /// Calls the wrapped function with 0 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(T* object) const
+                { return (*this->functorMember_)(object, this->defaultValue_[0], this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 1 argument and an object-pointer. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(T* object, const MultiType& arg1) const
+                { return (*this->functorMember_)(object, arg1, this->defaultValue_[1], this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 2 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2) const
+                { return (*this->functorMember_)(object, arg1, arg2, this->defaultValue_[2], this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 3 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2, const MultiType& arg3) const
+                { return (*this->functorMember_)(object, arg1, arg2, arg3, this->defaultValue_[3], this->defaultValue_[4]); }
+            /// Calls the wrapped function with 4 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4) const
+                { return (*this->functorMember_)(object, arg1, arg2, arg3, arg4, this->defaultValue_[4]); }
+            /// Calls the wrapped function with 5 arguments and an object-pointer. If the function needs more arguments, the executor's default values are used.
+            inline MultiType operator()(T* object, const MultiType& arg1, const MultiType& arg2, const MultiType& arg3, const MultiType& arg4, const MultiType& arg5) const
+                { return (*this->functorMember_)(object, arg1, arg2, arg3, arg4, arg5); }
+
+            /// Changes the object-pointer of the underlying FunctorMember.
+            inline void setObject(T* object) const
+                { this->functorMember_->setObject(object); }
+            /// Returns the object-pointer of the underlying FunctorMember.
+            inline T* getObject() const
+                { return this->functorMember_->getObject(); }
+
+            using Executor::parse;
+
+            /// Overloads Executor::parse() with an additional object-pointer.
+            MultiType parse(T* object, const std::string& arguments, int* error = nullptr, const std::string& delimiter = " ", bool bPrintError = false) const
+            {
+                T* oldobject = this->functorMember_->getObject();
+
+                this->functorMember_->setObject(object);
+                const MultiType& result = this->Executor::parse(arguments, error, delimiter, bPrintError);
+                this->functorMember_->setObject(oldobject);
+
+                return result;
+            }
+
+        protected:
+            FunctorMemberPtr<T> functorMember_;     ///< A pointer to the FunctorMember is stored separately to avoid casting when executing the function.
+    };
+
+    /// Creates a new Executor that wraps a given Functor.
+    inline ExecutorPtr createExecutor(const FunctorPtr& functor, const std::string& name = "")
+    {
+        return std::make_shared<Executor>(functor, name);
+    }
+
+    /// Creates a new ExecutorMember that wraps a given FunctorMember.
+    template <class T>
+    inline ExecutorMemberPtr<T> createExecutor(const FunctorMemberPtr<T>& functor, const std::string& name = "")
+    {
+        return std::make_shared<ExecutorMember<T>>(functor, name);
+    }
+
+    /// Creates a new ExecutorStatic that wraps a given FunctorStatic.
+    inline ExecutorStaticPtr createExecutor(const FunctorStaticPtr& functor, const std::string& name = "")
+    {
+        return std::make_shared<ExecutorStatic>(functor, name);
+    }
+}
+
+#endif /* _Executor_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/ExecutorPtr.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/ExecutorPtr.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/ExecutorPtr.h	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command FunctorExecutor
+    @brief Typedefs and definitions of ExecutorPtr, ExecutorStaticPtr, and ExecutorMemberPtr
+
+    Instances of orxonox::Executor are usually managed by an std::shared_ptr. This ensures
+    that Executors will be destroyed after usage. To make things easier, there's a typedef
+    that defines ExecutorPtr as std::shared_ptr<Executor>.
+
+    Because there's not only orxonox::Executor, but also orxonox::ExecutorStatic, and
+    orxonox::ExecutorMember, the shared pointers need to store them all and also reflect
+    their hierarchy - ExecutorStatic and ExecutorMember should not be mixed, but both can
+    be converted to Executor. This is achieved by using orxonox::SharedChildPtr.
+
+    Because it's not possible to use a typedef for a template, we have to define the
+    helper class ExecutorMemberPtr<T> that makes it easier to use ExecutorMember.
+*/
+
+#ifndef _ExecutorPtr_H__
+#define _ExecutorPtr_H__
+
+#include "core/CorePrereqs.h"
+#include <memory>
+
+namespace orxonox
+{
+    using ExecutorPtr = std::shared_ptr<Executor>;
+    using ExecutorStaticPtr = std::shared_ptr<ExecutorStatic>;
+    template <class T>
+    using ExecutorMemberPtr = std::shared_ptr<ExecutorMember<T>>;
+}
+
+#endif /* _ExecutorPtr_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/Functor.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/Functor.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/Functor.h	(revision 11817)
@@ -0,0 +1,595 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command FunctorExecutor
+    @brief Definition of orxonox::Functor and its specialized subclasses, as well as the createFunctor() functions.
+
+    @anchor FunctorExample
+
+    Functors can be used to wrap function-pointers. While function-pointers have a very
+    complicated syntax in C++, Functors are always the same and you can call the wrapped
+    function-pointer independently of its parameter with arguments of type MultiType. These
+    arguments are then automatically converted to the right type.
+
+    To create a Functor, the helper function createFunctor() is used. It returns an instance
+    of orxonox::FunctorPtr which is simply a typedef of "std::shared_ptr<Functor>". This
+    means you don't have to delete the Functor after using it, because it is managed
+    by the std::shared_ptr.
+
+    Example:
+    @code
+    int myStaticFunction(int value)                         // Definition of a static function
+    {
+        return (value * 2);                                 // Return the double of the value
+    }
+
+    FunctorPtr functor = createFunctor(&myStaticFunction);  // Create a Functor
+
+    int result = (*functor)(5);                             // Calls the functor with value = 5, result == 10
+
+    int result = (*functor)("7");                           // Calls the functor with a string which is converted to an integer, result == 14
+    @endcode
+
+    Functors can also be used if you work with member-functions. In this case createFunctor()
+    returns an instance of orxonox::FunctorMemberPtr - this allows you to define the object
+    that will be used to call the function.
+
+    Example:
+    @code
+    class MyClass                                                   // Define a class
+    {
+        public:
+            MyClass(const std::string& text)                        // Constructor
+            {
+                this->text_ = text;
+            }
+
+            bool contains(const std::string& word)                  // Function that searches for "word" in "text"
+            {
+                return (this->text_.find(word) != std::string::npos);
+            }
+
+        private:
+            std::string text_;                                      // Member variable
+    };
+
+    MyClass* object = new MyClass("Hello World");                   // Create an object of type MyClass and set its text to "Hello World"
+
+    FunctorPtr functor = createFunctor(&MyClass:contains, object);  // Create a Functor (note the object!)
+
+    bool result = (*functor)("World");                              // result == true
+    bool result = (*functor)("test");                               // result == false
+    @endcode
+
+    Instead of assigning the object directly to the functor when creating it, you can also define
+    it at any later point or when you call the functor. Note however that this works only with
+    orxonox::FunctorMember.
+
+    @code
+    MyClass* object1 = new MyClass("Hello World");                  // Create an object
+    MyClass* object2 = new MyClass("this is a test");               // Create another object
+
+    FunctorMemberPtr functor = createFunctor(&MyClass:contains);    // Create a FunctorMember (note: no object this time)
+
+    bool result = (*functor)("World");                              // result == false and an error: "Error: Can't execute FunctorMember, no object set."
+
+    bool result = (*functor)(object1, "World");                     // result == true
+    bool result = (*functor)(object1, "test");                      // result == false
+    bool result = (*functor)(object2, "test");                      // result == true
+
+    functor->setObject(object1);                                    // Assign an object to the FunctorMember
+
+    bool result = (*functor)("World");                              // result == true (no error this time, because the object was set using setObject())
+    @endcode
+*/
+
+#ifndef _Functor_H__
+#define _Functor_H__
+
+#include "core/CorePrereqs.h"
+
+#include <typeinfo>
+
+#include "util/Output.h"
+#include "util/MultiType.h"
+#include "core/object/Destroyable.h"
+#include "FunctorPtr.h"
+
+namespace orxonox
+{
+    const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;   ///< The maximum number of parameters of a function that is supported by Functor
+
+    namespace detail
+    {
+        template <class T>
+        inline std::string _typeToString() { return "unknown"; }
+
+        template <> inline std::string _typeToString<void>()               { return "void"; }
+        template <> inline std::string _typeToString<int>()                { return "int"; }
+        template <> inline std::string _typeToString<unsigned int>()       { return "uint"; }
+        template <> inline std::string _typeToString<char>()               { return "char"; }
+        template <> inline std::string _typeToString<unsigned char>()      { return "uchar"; }
+        template <> inline std::string _typeToString<short>()              { return "short"; }
+        template <> inline std::string _typeToString<unsigned short>()     { return "ushort"; }
+        template <> inline std::string _typeToString<long>()               { return "long"; }
+        template <> inline std::string _typeToString<unsigned long>()      { return "ulong"; }
+        template <> inline std::string _typeToString<long long>()          { return "longlong"; }
+        template <> inline std::string _typeToString<unsigned long long>() { return "ulonglong"; }
+        template <> inline std::string _typeToString<float>()              { return "float"; }
+        template <> inline std::string _typeToString<double>()             { return "double"; }
+        template <> inline std::string _typeToString<long double>()        { return "longdouble"; }
+        template <> inline std::string _typeToString<bool>()               { return "bool"; }
+        template <> inline std::string _typeToString<std::string>()        { return "string"; }
+        template <> inline std::string _typeToString<Vector2>()            { return "Vector2"; }
+        template <> inline std::string _typeToString<Vector3>()            { return "Vector3"; }
+        template <> inline std::string _typeToString<Quaternion>()         { return "Quaternion"; }
+        template <> inline std::string _typeToString<ColourValue>()        { return "ColourValue"; }
+        template <> inline std::string _typeToString<Radian>()             { return "Radian"; }
+        template <> inline std::string _typeToString<Degree>()             { return "Degree"; }
+    }
+
+    /// Returns the name of type @a T as string.
+    template <class T>
+    inline std::string typeToString() { return detail::_typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
+
+    /**
+        @brief The Functor classes are used to wrap function pointers.
+
+        Function-pointers in C++ have a pretty complicated syntax and you can't store
+        and call them unless you know the exact type. A Functor can be used to wrap
+        a function-pointer and to store it independent of its type. You can also call
+        it independently of its parameters by passing the arguments as MultiType. They
+        are converted automatically to the right type.
+
+        Functor is a pure virtual base class.
+
+        @see See @ref FunctorExample "Functor.h" for some examples.
+    */
+    class _CoreExport Functor
+    {
+        public:
+            /// Defines the type of a function (static or member)
+            enum class Type
+            {
+                Static,
+                Member
+            };
+
+        public:
+            virtual ~Functor() = default;
+
+            /// Calls the function-pointer with up to five arguments. In case of a member-function, the assigned object-pointer is used to call the function. @return Returns the return-value of the function (if any; MultiType::Null otherwise)
+            virtual MultiType operator()(const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) = 0;
+
+            /// Creates a new instance of Functor with the same values like this (used instead of a copy-constructor)
+            virtual FunctorPtr clone() = 0;
+
+            /// Returns the type of the function: static or member.
+            virtual Type getType() const = 0;
+            /// Returns the number of parameters of the function.
+            virtual unsigned int getParamCount() const = 0;
+            /// Returns true if the function has a return-value.
+            virtual bool hasReturnvalue() const = 0;
+
+            /// Returns the type-name of the parameter with given index (the first parameter has index 0).
+            virtual std::string getTypenameParam(unsigned int index) const = 0;
+            /// Returns the type-name of the return-value.
+            virtual std::string getTypenameReturnvalue() const = 0;
+
+            /// Converts a given argument to the type of the parameter with given index (the first parameter has index 0).
+            virtual void evaluateArgument(unsigned int index, MultiType& argument) const = 0;
+
+            /// Assigns an object-pointer to the functor which is used to execute a member-function.
+            virtual void setRawObjectPointer(void* object) = 0;
+            /// Returns the object-pointer.
+            virtual void* getRawObjectPointer() const = 0;
+
+            /// Enables or disables the safe mode which causes the functor to change the object pointer to nullptr if the object is deleted (only member functors).
+            virtual void setSafeMode(bool bSafeMode) = 0;
+
+            /// Returns the full identifier of the function-pointer which is defined as typeid(@a F), where @a F is the type of the stored function-pointer. Used to compare functors.
+            virtual const std::type_info& getFullIdentifier() const = 0;
+            /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
+            virtual const std::type_info& getHeaderIdentifier() const = 0;
+            /// Returns an identifier of the header of the function (doesn't include the function's class), but regards only the first @a params parameters. Used to compare functions if an Executor provides default-values for the other parameters.
+            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
+    };
+
+    /**
+        @brief FunctorMember is a child class of Functor and expands it with an object-pointer, that
+        is used for member-functions, as well as an overloaded execution operator.
+
+        @param O The type of the function's class (or void if it's a static function)
+
+        Note that FunctorMember is also used for static functions, but with T = void. FunctorStatic
+        is a typedef of FunctorMember<void>. The void* object-pointer is ignored in this case.
+
+        @see See @ref FunctorExample "Functor.h" for some examples.
+    */
+    template <class O>
+    class FunctorMember : public Functor, public DestructionListener
+    {
+        public:
+            /// Constructor: Stores the object-pointer.
+            FunctorMember(O* object = nullptr) : object_(object), bSafeMode_(false) {}
+            virtual ~FunctorMember() { if (this->bSafeMode_) { this->unregisterObject(this->object_); } }
+
+            /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be nullptr. @return Returns the return-value of the function (if any; MultiType::Null otherwise)
+            virtual MultiType operator()(O* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) = 0;
+
+            // see Functor::operator()()
+            virtual MultiType operator()(const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override
+            {
+                // call the function if an object was assigned
+                if (this->object_)
+                    return (*this)(this->object_, param1, param2, param3, param4, param5);
+                else
+                {
+                    orxout(internal_error) << "Can't execute FunctorMember, no object set." << endl;
+                    return MultiType::Null;
+                }
+            }
+
+            // see Functor::getType()
+            virtual inline Functor::Type getType() const override
+                { return Functor::Type::Member; }
+
+            /// Assigns an object-pointer to the functor which is used to execute a member-function.
+            inline void setObject(O* object)
+            {
+                if (this->bSafeMode_ && object != this->object_)
+                {
+                    this->unregisterObject(this->object_);
+                    this->registerObject(object);
+                }
+                this->object_ = object;
+            }
+            /// Returns the object-pointer.
+            inline O* getObject() const
+                { return this->object_; }
+
+            // see Functor::setRawObjectPointer()
+            virtual inline void setRawObjectPointer(void* object) override
+                { this->setObject((O*)object); }
+            // see Functor::getRawObjectPointer()
+            virtual inline void* getRawObjectPointer() const override
+                { return this->object_; }
+
+            // see Functor::setSafeMode()
+            virtual inline void setSafeMode(bool bSafeMode) override
+            {
+                if (bSafeMode == this->bSafeMode_)
+                    return;
+
+                this->bSafeMode_ = bSafeMode;
+
+                if (bSafeMode)
+                    this->registerObject(this->object_);
+                else
+                    this->unregisterObject(this->object_);
+            }
+
+        protected:
+            /// Casts the object and registers as destruction listener if the object is a Destroyable.
+            inline void registerObject(Destroyable* object)
+                { this->registerAsDestructionListener(object); }
+
+            inline void registerObject(void* object) {}
+
+            /// Casts the object and unregisters as destruction listener if the object is a Destroyable.
+            inline void unregisterObject(Destroyable* object)
+                { this->unregisterAsDestructionListener(object); }
+
+            inline void unregisterObject(void* object) {}
+
+            /// Will be called by Destroyable::~Destroyable() if the stored object is a Destroyable and deleted and the Functor is in safe mode.
+            virtual inline void objectDeleted() override
+                { this->object_ = nullptr; }
+
+            O* object_;     ///< The stored object-pointer, used to execute a member-function (or nullptr for static functions)
+            bool bSafeMode_; ///< If true, the functor is in safe mode and registers itself as listener at the object and changes the pointer to nullptr if the object is deleted
+    };
+
+    /// Specialization of FunctorMember with @a T = void.
+    template <>
+    class FunctorMember<void> : public Functor
+    {
+        public:
+            /// Constructor: Stores the object-pointer.
+            FunctorMember(void* object = nullptr) {}
+
+            /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be nullptr. @return Returns the return-value of the function (if any; MultiType::Null otherwise)
+            virtual MultiType operator()(void* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) = 0;
+
+            // see Functor::operator()()
+            virtual MultiType operator()(const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override
+            {
+                return (*this)((void*)nullptr, param1, param2, param3, param4, param5);
+            }
+
+            // see Functor::getType()
+            virtual inline Functor::Type getType() const override
+                { return Functor::Type::Static; }
+
+            // see Functor::setRawObjectPointer()
+            virtual inline void setRawObjectPointer(void*) override
+                { orxout(internal_warning) << "Can't assign an object pointer to a static functor" << endl; }
+            // see Functor::getRawObjectPointer()
+            virtual inline void* getRawObjectPointer() const override
+                { return nullptr; }
+
+            // see Functor::setSafeMode()
+            virtual inline void setSafeMode(bool) override {}
+    };
+
+    /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
+    typedef FunctorMember<void> FunctorStatic;
+
+    /**
+        @brief FunctorPointer is a child class of FunctorMember and extends it with a function-pointer (or a function-object).
+        @param F The type of the function-pointer (or the function-object)
+        @param O The type of the function's class (or void if it's a static function or a function-object)
+
+        The template FunctorPointer has an additional template parameter that defines the type
+        of the function-pointer (or the function-object). This can be handy if you want to get
+        or set the function-pointer (or the function-object). You can then use a static_cast
+        to cast a Functor to FunctorPointer if you know the type of the function.
+
+        However FunctorPointer is not aware of the types of the different parameters or the
+        return value.
+    */
+    template <class F, class O = void>
+    class FunctorPointer : public FunctorMember<O>
+    {
+        public:
+            /// Constructor: Initializes the base class and stores the function-pointer.
+            FunctorPointer(F functionPointer, O* object = nullptr) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
+
+            /// Changes the function-pointer.
+            inline void setFunction(F functionPointer)
+                { this->functionPointer_ = functionPointer; }
+            /// Returns the function-pointer.
+            inline F getFunction() const
+                { return this->functionPointer_; }
+
+        protected:
+            F functionPointer_;     ///< The stored function-pointer
+    };
+
+    namespace detail
+    {
+        // Helper class to get the type of the function-pointer (or the function-object) with the given class, parameters, return-value, and constness
+        template <class F, class R, class O, bool isconst, class... Params> struct FunctionType /* generic type is undefined */;
+        template <         class R, class O,               class... Params> struct FunctionType<void, R, O,    false, Params...> { typedef R (O::*Type)(Params...); };       // spezialization: non-const member function
+        template <         class R, class O,               class... Params> struct FunctionType<void, R, O,    true,  Params...> { typedef R (O::*Type)(Params...) const; }; // spezialization: const member function
+        template <         class R,                        class... Params> struct FunctionType<void, R, void, false, Params...> { typedef R (*Type)(Params...); };          // spezialization: static function
+        template <class F, class R,                        class... Params> struct FunctionType<F,    R, void, false, Params...> { typedef F Type; };                        // spezialization: function object
+
+        // Helper class, used to call a function with a given object and parameters and to return its return-value (if available)
+        template <class F, class R, class O, bool isconst, class... Params> struct FunctorCaller /* generic type is undefined */;
+        template <         class R, class O, bool isconst, class... Params> struct FunctorCaller<void, R,    O,    isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, R,    O,    isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { return (object->*functionPointer)(parameters...); } };                  // spezialization: member function with return value
+        template <                  class O, bool isconst, class... Params> struct FunctorCaller<void, void, O,    isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, void, O,    isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { (object->*functionPointer)(parameters...); return MultiType::Null; } }; // spezialization: member function without return value
+        template <         class R,                        class... Params> struct FunctorCaller<void, R,    void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, R,    void, false,   Params...>::Type functionPointer, void*,     const Params&... parameters, const UnusedParams&...) { return (*functionPointer)(parameters...); } };                          // spezialization: static function with return value
+        template <                                         class... Params> struct FunctorCaller<void, void, void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, void, void, false,   Params...>::Type functionPointer, void*,     const Params&... parameters, const UnusedParams&...) { (*functionPointer)(parameters...); return MultiType::Null; } };         // spezialization: static function without return value
+        template <class F, class R,                        class... Params> struct FunctorCaller<F,    R,    void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<F,    R,    void, false,   Params...>::Type functor,         void*,     const Params&... parameters, const UnusedParams&...) { return functor(parameters...); } };                                     // spezialization: function object with return value
+        template <class F,                                 class... Params> struct FunctorCaller<F,    void, void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<F,    void, void, false,   Params...>::Type functor,         void*,     const Params&... parameters, const UnusedParams&...) { functor(parameters...); return MultiType::Null; } };                    // spezialization: function object without return value
+
+        // Helper class to determine if a function has a returnvalue
+        template <class T>
+        struct FunctorHasReturnvalue
+        { enum { result = true }; };
+        template <>
+        struct FunctorHasReturnvalue<void>
+        { enum { result = false }; };
+
+        // Helper class to determine the N-th parameter of a variadic template (with 0 being the index of the first parameter)
+        template <int n, typename T = void, typename... Other>
+        struct GetNthParamType
+        { typedef typename GetNthParamType<n - 1, Other...>::Type Type; };
+        template <typename T, typename... Other>
+        struct GetNthParamType<0, T, Other...>
+        { typedef T Type; };
+
+        // Helper structs to deduce the first N types of a parameter pack
+        template<class... Types> struct type_list {};
+
+        template <class T1, class... AllTypes>
+        struct make_type_list_helper
+        {
+            template <std::size_t N, class... Types>
+            struct make_type_list_impl : make_type_list_helper<AllTypes...>::template make_type_list_impl<N - 1, Types..., T1> {};
+
+            template <class... Types>
+            struct make_type_list_impl<1u, Types...> : type_list<Types..., T1> {};
+        };
+
+        template <class T1>
+        struct make_type_list_helper<T1>
+        {
+            template <std::size_t N, class... Types>
+            struct make_type_list_impl : type_list<Types..., T1> {};
+        };
+
+        template <std::size_t N, class... Types>
+        struct make_type_list : make_type_list_helper<Types...>::template make_type_list_impl<N> {};
+
+        template <class... Types>
+        struct make_type_list<0u, Types...> : type_list<> {};
+
+        template <std::size_t N>
+        struct make_type_list<N> : type_list<> {};
+
+        template <>
+        struct make_type_list<0u> : type_list<> {};
+    }
+
+    /**
+        @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
+        that need to know the exact types of the parameters, return-value, and class.
+
+        @param F the type of the function-object (or void if a function-pointer is used).
+        @param R The type of the return-value of the function
+        @param O The class of the function
+        @param isconst True if the function is a const member-function
+        @param Params The types of the parameters
+
+        This template has many parameters and is usually not used directly. It is created by
+        createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
+        are used directly. It implements all the virtual functions that are declared by its
+        base classes.
+
+        All template arguments can be void.
+    */
+    template <class F, class R, class O, bool isconst, class... Params>
+    class FunctorTemplate : public FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O>
+    {
+        static_assert(sizeof...(Params) <= 5, "Only up to 5 parameters are supported");
+
+        public:
+            /// Constructor: Initializes the base class.
+            FunctorTemplate(typename detail::FunctionType<F, R, O, isconst, Params...>::Type functionPointer, O* object = nullptr) : FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O>(functionPointer, object) {}
+
+            // see FunctorMember::operator()()
+            virtual MultiType operator()(O* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override
+            {
+                return detail::FunctorCaller<F, R, O, isconst, Params...>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
+            }
+
+            // see Functor::clone()
+            virtual FunctorPtr clone() override
+            {
+                return std::make_shared<FunctorTemplate>(*this);
+            }
+
+            // see Functor::evaluateArgument()
+            virtual void evaluateArgument(unsigned int index, MultiType& argument) const override
+            {
+                switch (index)
+                {
+                    case 0: argument.convert<typename detail::GetNthParamType<0, Params...>::Type>(); break;
+                    case 1: argument.convert<typename detail::GetNthParamType<1, Params...>::Type>(); break;
+                    case 2: argument.convert<typename detail::GetNthParamType<2, Params...>::Type>(); break;
+                    case 3: argument.convert<typename detail::GetNthParamType<3, Params...>::Type>(); break;
+                    case 4: argument.convert<typename detail::GetNthParamType<4, Params...>::Type>(); break;
+                }
+            }
+
+            // see Functor::getParamCount()
+            virtual unsigned int getParamCount() const override
+            {
+                return sizeof...(Params);
+            }
+
+            // see Functor::hasReturnvalue()
+            virtual bool hasReturnvalue() const override
+            {
+                return detail::FunctorHasReturnvalue<R>::result;
+            }
+
+            // see Functor::getTypenameParam()
+            virtual std::string getTypenameParam(unsigned int index) const override
+            {
+                switch (index)
+                {
+                    case 0:  return typeToString<typename detail::GetNthParamType<0, Params...>::Type>();
+                    case 1:  return typeToString<typename detail::GetNthParamType<1, Params...>::Type>();
+                    case 2:  return typeToString<typename detail::GetNthParamType<2, Params...>::Type>();
+                    case 3:  return typeToString<typename detail::GetNthParamType<3, Params...>::Type>();
+                    case 4:  return typeToString<typename detail::GetNthParamType<4, Params...>::Type>();
+                    default: return "";
+                }
+            }
+
+            // see Functor::getTypenameReturnvalue()
+            virtual std::string getTypenameReturnvalue() const override
+            {
+                return typeToString<R>();
+            }
+
+            // see Functor::getFullIdentifier()
+            virtual const std::type_info& getFullIdentifier() const override
+            {
+                return typeid(typename detail::FunctionType<void, R, O, isconst, Params...>::Type);
+            }
+
+            // see Functor::getHeaderIdentifier()
+            virtual const std::type_info& getHeaderIdentifier() const override
+            {
+                return typeid(typename detail::FunctionType<void, R, void, false, Params...>::Type);
+            }
+
+            // see Functor::getHeaderIdentifier(unsigned int)
+            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const override
+            {
+                switch (params)
+                {
+                    case 0:  return this->getTypelistIdentifier(detail::make_type_list<0, Params...>{});
+                    case 1:  return this->getTypelistIdentifier(detail::make_type_list<1, Params...>{});
+                    case 2:  return this->getTypelistIdentifier(detail::make_type_list<2, Params...>{});
+                    case 3:  return this->getTypelistIdentifier(detail::make_type_list<3, Params...>{});
+                    case 4:  return this->getTypelistIdentifier(detail::make_type_list<4, Params...>{});
+                    default: return this->getTypelistIdentifier(detail::make_type_list<5, Params...>{});
+                }
+            }
+
+    private:
+            /// Helper function that deduces a parameter pack of types and returns the corresponding identifier
+            template<class... Types>
+            const std::type_info& getTypelistIdentifier(detail::type_list<Types...>) const
+            {
+                return typeid(typename detail::FunctionType<void, R, void, false, Types...>::Type);
+            }
+    };
+
+
+    namespace detail
+    {
+        // Helper functions to deduce types and constness of operator() and return the correct FunctorTemplate
+        template <class F>
+        struct CallableHelper
+        {
+            template <class R, class... Params> static inline FunctorStaticPtr create(const F& functionObject, R(F::*)(Params...))       { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); }
+            template <class R, class... Params> static inline FunctorStaticPtr create(const F& functionObject, R(F::*)(Params...) const) { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); } // note: both const and non-const function-objects are treated as static functors with isconst=false.
+        };
+    }
+
+    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...),       OO* object) { return std::make_shared<FunctorTemplate<void, R, O, false, Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const, OO* object) { return std::make_shared<FunctorTemplate<void, R, O, true,  Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+
+    template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...))       { return std::make_shared<FunctorTemplate<void, R, O, false, Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+    template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const) { return std::make_shared<FunctorTemplate<void, R, O, true,  Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
+
+    template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<void, R, void, false, Params...>>(functionPointer); } ///< Creates a new FunctorStatic with the given function-pointer
+
+    /** Take care that this functor does not outlive objects that have been captured by reference in a lambda. */
+    template <class F> inline FunctorStaticPtr createFunctor(const F& functionObject) { return detail::CallableHelper<F>::create(functionObject, &F::operator()); } ///< Creates a new Functor with a callable object
+}
+
+#endif /* _Functor_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/FunctorPtr.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/FunctorPtr.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/FunctorPtr.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command FunctorExecutor
+    @brief Typedefs and definitions of FunctorPtr, FunctorMemberPtr, FunctorStaticPtr, and FunctorPointerPtr
+
+    Instances of orxonox::Functor are usually managed by an std::shared_ptr. This ensures
+    that Functors will be destroyed after usage. To make things easier, there's a typedef
+    that defines FunctorPtr as std::shared_ptr<Functor>.
+
+    Because there's not only orxonox::Functor, but also orxonox::FunctorStatic, and
+    orxonox::FunctorMember, the shared pointers need to store them all and also reflect
+    their hierarchy - FunctorStatic and FunctorMember should not be mixed, but both can
+    be converted to Functor. This is achieved by using orxonox::SharedChildPtr.
+
+    Because it's not possible to use a typedef for a template, we have to define the
+    helper class FunctorMemberPtr<T> that makes it easier to use FunctorMember. The
+    same is also done for FunctorPointerPtr<T>, which can be converted to both,
+    FunctorMemberPtr<T> as well as FunctorPtr.
+*/
+
+#ifndef _FunctorPtr_H__
+#define _FunctorPtr_H__
+
+#include "core/CorePrereqs.h"
+#include <memory>
+
+namespace orxonox
+{
+    using FunctorPtr = std::shared_ptr<Functor>;
+    template <class T>
+    using FunctorMemberPtr = std::shared_ptr<FunctorMember<T>>;
+    using FunctorStaticPtr = std::shared_ptr<FunctorMember<void>>;
+    template <class F, class T>
+    using FunctorPointerPtr = std::shared_ptr<FunctorPointer<F, T>>;
+}
+
+#endif /* _FunctorPtr_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsole.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsole.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsole.cc	(revision 11817)
@@ -0,0 +1,35 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "IOConsole.h"
+
+#if defined(ORXONOX_PLATFORM_UNIX)
+  #include "IOConsolePOSIX.cc"
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+  #include "IOConsoleWindows.cc"
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsole.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsole.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsole.h	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ShellConsole
+*/
+
+#include "OrxonoxConfig.h"
+
+#if defined(ORXONOX_PLATFORM_UNIX)
+  #include "IOConsolePOSIX.h"
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+  #include "IOConsoleWindows.h"
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsolePOSIX.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsolePOSIX.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsolePOSIX.cc	(revision 11817)
@@ -0,0 +1,429 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "IOConsole.h"
+
+#include <iomanip>
+#include <iostream>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#include "util/Clock.h"
+#include "util/Math.h"
+#include "util/output/ConsoleWriter.h"
+#include "util/output/OutputManager.h"
+#include "core/Game.h"
+#include "core/input/InputBuffer.h"
+
+namespace orxonox
+{
+    IOConsole* IOConsole::singletonPtr_s = nullptr;
+
+    enum class EscapeMode
+    {
+        None,
+        First,
+        Second
+    };
+
+    IOConsole::IOConsole()
+        : shell_(new Shell("Console", false))
+        , buffer_(shell_->getInputBuffer())
+        , cout_(std::cout.rdbuf())
+        , promptString_("orxonox # ")
+        , bStatusPrinted_(false)
+        , originalTerminalSettings_(nullptr)
+    {
+        this->setTerminalMode();
+        this->shell_->registerListener(this);
+
+        // Manually set the widths of the individual status lines
+        this->statusLineWidths_.push_back(29);
+        this->statusLineMaxWidth_ = 29;
+
+        this->getTerminalSize();
+        this->lastTerminalWidth_ = this->terminalWidth_;
+        this->lastTerminalHeight_ = this->terminalHeight_;
+
+        // Disable standard std::cout logging
+        OutputManager::getInstance().getConsoleWriter()->disable();
+        // Redirect std::cout to an ostringstream
+        // (Other part is in the initialiser list)
+        std::cout.rdbuf(this->origCout_.rdbuf());
+
+        // Make sure we make way for the status lines
+        this->preUpdate(Game::getInstance().getGameClock());
+    }
+
+    IOConsole::~IOConsole()
+    {
+        // Process output written to std::cout in the meantime
+        std::cout.flush();
+        if (!this->origCout_.str().empty())
+            this->shell_->addOutput(this->origCout_.str(), Shell::LineType::Cout);
+        // Erase input and status lines
+        this->cout_ << "\033[1G\033[J";
+        // Move cursor to the bottom
+        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
+        // Scroll terminal to compensate for erased lines
+        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'T';
+
+        resetTerminalMode();
+        delete this->shell_;
+
+        // Restore this->cout_ redirection
+        std::cout.rdbuf(this->cout_.rdbuf());
+        // Enable standard std::cout logging again
+        OutputManager::getInstance().getConsoleWriter()->enable();
+    }
+
+    void IOConsole::preUpdate(const Clock& time)
+    {
+        unsigned char c;
+        std::string escapeSequence;
+        EscapeMode escapeMode = EscapeMode::None;
+        while (std::cin.good())
+        {
+            c = std::cin.get();
+            if (!std::cin.good())
+                break;
+
+            if (escapeMode == EscapeMode::First && (c == '[' || c=='O') )
+                escapeMode = EscapeMode::Second;
+            // Get Alt+Tab combination when switching applications
+            else if (escapeMode == EscapeMode::First && c == '\t')
+            {
+                this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab, '\t', KeyboardModifier::Alt));
+                escapeMode = EscapeMode::None;
+            }
+            else if (escapeMode == EscapeMode::Second)
+            {
+                escapeSequence += c;
+                escapeMode = EscapeMode::None;
+                if      (escapeSequence == "A")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Up,       0, 0));
+                else if (escapeSequence == "B")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Down,     0, 0));
+                else if (escapeSequence == "C")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Right,    0, 0));
+                else if (escapeSequence == "D")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Left,     0, 0));
+                else if (escapeSequence == "1~" || escapeSequence == "H")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Home,     0, 0));
+                else if (escapeSequence == "2~")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert,   0, 0));
+                else if (escapeSequence == "3~")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete,   0, 0));
+                else if (escapeSequence == "4~" || escapeSequence == "F")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::End,      0, 0));
+                else if (escapeSequence == "5~")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp,   0, 0));
+                else if (escapeSequence == "6~")
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, 0, 0));
+                else
+                    // Waiting for sequence to complete
+                    // If the user presses ESC and then '[' or 'O' while the loop is not
+                    // running (for instance while loading), the whole sequence gets dropped
+                    escapeMode = EscapeMode::Second;
+            }
+            else // not in an escape sequence OR user might have pressed just ESC
+            {
+                if (escapeMode == EscapeMode::First)
+                {
+                    this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, c, 0));
+                    escapeMode = EscapeMode::None;
+                }
+                if (c == '\033')
+                {
+                    escapeMode = EscapeMode::First;
+                    escapeSequence.clear();
+                }
+                else
+                {
+                    KeyCode::ByEnum code;
+                    switch (c)
+                    {
+                    case '\n'  : case '\r': code = KeyCode::Return; break;
+                    case '\177': case '\b': code = KeyCode::Back;   break;
+                    case '\t'             : code = KeyCode::Tab;    break;
+                    default:
+                        // We don't encode the key code (would be a very large switch)
+                        // because the InputBuffer will only insert the text anyway
+                        // Replacement character is simply KeyCode::A
+                        code = KeyCode::A;
+                    }
+                    this->buffer_->buttonPressed(KeyEvent(code, c, 0));
+                }
+            }
+        }
+        // Reset error flags in std::cin
+        std::cin.clear();
+
+        // If there is still an escape key pending (escape key ONLY), then
+        // it sure isn't an escape sequence anymore
+        if (escapeMode == EscapeMode::First)
+            this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape, '\033', 0));
+
+        // Determine terminal width and height
+        this->lastTerminalWidth_ = this->terminalWidth_;
+        this->lastTerminalHeight_ = this->terminalHeight_;
+        this->getTerminalSize();
+
+        int heightDiff = this->terminalHeight_ - this->lastTerminalHeight_;
+        if (this->bStatusPrinted_ && heightDiff < 0)
+        {
+            // Terminal width has shrunk. The cursor will still be on the input line,
+            // but that line might very well be the last
+            int newLines = std::min((int)this->statusLineWidths_.size(), -heightDiff);
+            // Scroll terminal to create new lines
+            this->cout_ << "\033[" << newLines << 'S';
+        }
+
+        if (!this->bStatusPrinted_ && this->willPrintStatusLines())
+        {
+            // Scroll console to make way for status lines
+            this->cout_ << "\033[" << this->statusLineWidths_.size() << 'S';
+            this->bStatusPrinted_ = true;
+        }
+
+        // We always assume that the cursor is on the input line.
+        // But we cannot always be sure about that, esp. if we scroll the console
+        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'B';
+        this->cout_ << "\033[" << this->statusLineWidths_.size() << 'A';
+
+        // Erase status and input lines
+        this->cout_ << "\033[1G\033[J";
+        this->printInputLine();
+        this->printStatusLines();
+        this->cout_.flush();
+
+        // Process output written to std::cout
+        std::cout.flush();
+        if (!this->origCout_.str().empty())
+        {
+            this->shell_->addOutput(this->origCout_.str(), Shell::LineType::Cout);
+            this->origCout_.str("");
+        }
+    }
+
+    void IOConsole::printOutputLine(const std::string& text, Shell::LineType type)
+    {
+        // Colour line
+        switch (type)
+        {
+            case Shell::LineType::Message:
+            case Shell::LineType::DebugOutput:     this->cout_ << "\033[0m"; break;
+
+            case Shell::LineType::UserError:       this->cout_ << "\033[91m"; break;
+            case Shell::LineType::UserWarning:     this->cout_ << "\033[93m"; break;
+            case Shell::LineType::UserStatus:      this->cout_ << "\033[92m"; break;
+            case Shell::LineType::UserInfo:        this->cout_ << "\033[96m"; break;
+
+            case Shell::LineType::InternalError:   this->cout_ << "\033[31m"; break;
+            case Shell::LineType::InternalWarning: this->cout_ << "\033[33m"; break;
+            case Shell::LineType::InternalStatus:  this->cout_ << "\033[32m"; break;
+            case Shell::LineType::InternalInfo:    this->cout_ << "\033[36m"; break;
+
+            case Shell::LineType::Verbose:         this->cout_ << "\033[94m"; break;
+            case Shell::LineType::VerboseMore:     this->cout_ << "\033[34m"; break;
+            case Shell::LineType::VerboseUltra:    this->cout_ << "\033[34m"; break;
+
+            case Shell::LineType::Command:         this->cout_ << "\033[95m"; break;
+            case Shell::LineType::Hint:            this->cout_ << "\033[35m"; break;
+
+            default:                               this->cout_ << "\033[37m"; break;
+        }
+
+        // Print output line
+        this->cout_ << text;
+
+        // Reset colour atributes
+        this->cout_ << "\033[0m";
+    }
+
+    void IOConsole::printInputLine()
+    {
+        // Set cursor to the beginning of the line and erase the line
+        this->cout_ << "\033[1G\033[K";
+        // Indicate a command prompt
+        this->cout_ << this->promptString_;
+        // Save cursor position
+        this->cout_ << "\033[s";
+        // Print command line buffer
+        this->cout_ << this->shell_->getInput();
+        // Restore cursor position and move it to the right
+        this->cout_ << "\033[u";
+        if (this->buffer_->getCursorPosition() > 0)
+            this->cout_ << "\033[" << this->buffer_->getCursorPosition() << 'C';
+    }
+
+    void IOConsole::printStatusLines()
+    {
+        if (this->willPrintStatusLines())
+        {
+            // Save cursor position
+            this->cout_ << "\033[s";
+            // Move cursor down (don't create a new line here because the buffer might flush then!)
+            this->cout_ << "\033[1B\033[1G";
+            this->cout_ << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
+            this->cout_ <<               std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
+            // Restore cursor position
+            this->cout_ << "\033[u";
+            this->bStatusPrinted_ = true;
+        }
+        else
+            this->bStatusPrinted_ = false;
+    }
+
+    void IOConsole::setTerminalMode()
+    {
+        termios new_settings;
+        this->originalTerminalSettings_ = new termios();
+
+        tcgetattr(0, this->originalTerminalSettings_);
+        new_settings = *this->originalTerminalSettings_;
+        new_settings.c_lflag &= ~(ICANON | ECHO);
+        //new_settings.c_lflag |= (ISIG | IEXTEN);
+        new_settings.c_cc[VTIME] = 0;
+        new_settings.c_cc[VMIN]  = 0;
+        tcsetattr(0, TCSANOW, &new_settings);
+        atexit(&IOConsole::resetTerminalMode);
+    }
+
+    /*static*/ void IOConsole::resetTerminalMode()
+    {
+        if (IOConsole::singletonPtr_s && IOConsole::singletonPtr_s->originalTerminalSettings_)
+        {
+            tcsetattr(0, TCSANOW, IOConsole::singletonPtr_s->originalTerminalSettings_);
+            delete IOConsole::singletonPtr_s->originalTerminalSettings_;
+            IOConsole::singletonPtr_s->originalTerminalSettings_ = nullptr;
+        }
+    }
+
+    void IOConsole::getTerminalSize()
+    {
+        this->terminalWidth_  = 0;
+        this->terminalHeight_ = 0;
+
+#ifdef TIOCGSIZE
+        struct ttysize win;
+        if (!ioctl(STDIN_FILENO, TIOCGSIZE, &win))
+        {
+            this->terminalWidth_  = win.ts_cols;
+            this->terminalHeight_ = win.ts_lines;
+        }
+#elif defined TIOCGWINSZ
+        struct winsize win;
+        if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &win))
+        {
+            this->terminalWidth_  = win.ws_col;
+            this->terminalHeight_ = win.ws_row;
+        }
+#endif
+
+        const char* s;
+        if (!this->terminalWidth_ && (s = getenv("COLUMNS")))
+            this->terminalWidth_  = strtol(s, nullptr, 10);
+        if (!this->terminalWidth_)
+            this->terminalWidth_ = 80;
+        if (!this->terminalHeight_ && (s = getenv("LINES")))
+            this->terminalHeight_ = strtol(s, nullptr, 10);
+        if (!this->terminalHeight_)
+            this->terminalHeight_ = 24;
+    }
+
+    inline bool IOConsole::willPrintStatusLines()
+    {
+        return !this->statusLineWidths_.empty()
+             && this->terminalWidth_  >= this->statusLineMaxWidth_
+             && this->terminalHeight_ >= this->minOutputLines_ + (int)this->statusLineWidths_.size();
+    }
+
+    // ###############################
+    // ###  ShellListener methods  ###
+    // ###############################
+
+    //! Called if all output-lines have to be reprinted
+    void IOConsole::linesChanged()
+    {
+        // Method only gets called upon start to draw all the lines
+        // or when scrolling. But scrolling is disabled and the output
+        // is already in std::cout when we start the IOConsole
+    }
+
+    //! Called if a command is about to be executed
+    void IOConsole::executed()
+    {
+        this->shell_->addOutput(this->promptString_ + this->shell_->getInput(), Shell::LineType::Command);
+    }
+
+    //! Called if the console gets closed
+    void IOConsole::exit()
+    {
+        // Exit is not an option, just do nothing (Shell doesn't really exit too)
+    }
+
+    //! Called if a new output-line was added
+    void IOConsole::lineAdded()
+    {
+        int newLines = this->shell_->getNewestLineIterator()->first.size() / this->terminalWidth_ + 1;
+        // Create new lines by scrolling the screen
+        this->cout_ << "\033[" << newLines << 'S';
+        // Move cursor to the beginning of the new (last) output line
+        this->cout_ << "\033[" << newLines << "A\033[1G";
+        // Erase screen from here
+        this->cout_ << "\033[J";
+        // Print the new output lines
+        for (int i = 0; i < newLines; ++i)
+        {
+            Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
+            this->printOutputLine(it->first.substr(i*this->terminalWidth_, this->terminalWidth_), it->second);
+        }
+        // Move cursor down
+        this->cout_ << "\033[1B\033[1G";
+        // Print status and input lines
+        this->printInputLine();
+        this->printStatusLines();
+        this->cout_.flush();
+    }
+
+    //! Called if the text in the input-line has changed
+    void IOConsole::inputChanged()
+    {
+        this->printInputLine();
+        this->cout_.flush();
+    }
+
+    //! Called if the position of the cursor in the input-line has changed
+    void IOConsole::cursorChanged()
+    {
+        this->printInputLine();
+        this->cout_.flush();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsolePOSIX.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsolePOSIX.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsolePOSIX.h	(revision 11817)
@@ -0,0 +1,100 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ShellConsole
+*/
+
+#ifndef _IOConsole_H__
+#define _IOConsole_H__
+
+#include "core/CorePrereqs.h"
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include "util/Singleton.h"
+#include "Shell.h"
+
+struct termios;
+
+namespace orxonox
+{
+    class _CoreExport IOConsole : public Singleton<IOConsole>, public ShellListener
+    {
+        friend class Singleton<IOConsole>;
+
+    public:
+        IOConsole();
+        ~IOConsole();
+
+        void preUpdate(const Clock& time);
+
+    private:
+        void setTerminalMode();
+        void getTerminalSize();
+        void printStatusLines();
+        static int extractLogLevel(std::string* text);
+
+        // Methods from ShellListener
+        virtual void linesChanged() override;
+        virtual void lineAdded() override;
+        virtual void inputChanged() override;
+        virtual void cursorChanged() override;
+        virtual void executed() override;
+        virtual void exit() override;
+
+        bool willPrintStatusLines();
+        void printInputLine();
+        void printOutputLine(const std::string& line, Shell::LineType type);
+        static void resetTerminalMode();
+
+        Shell*                  shell_;
+        InputBuffer*            buffer_;
+        std::ostream            cout_;
+        std::ostringstream      origCout_;
+        int                     terminalWidth_;
+        int                     terminalHeight_;
+        int                     lastTerminalWidth_;
+        int                     lastTerminalHeight_;
+        const std::string       promptString_;
+
+        bool                    bPrintStatusLine_;
+        bool                    bStatusPrinted_;
+        std::vector<int>        statusLineWidths_;
+        int                     statusLineMaxWidth_;
+        static const int        minOutputLines_ = 3;
+        termios*                originalTerminalSettings_;
+
+        static IOConsole* singletonPtr_s;
+    };
+}
+
+#endif /* _IOConsole_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsoleWindows.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsoleWindows.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsoleWindows.cc	(revision 11817)
@@ -0,0 +1,403 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "IOConsole.h"
+
+#include <iomanip>
+#include <iostream>
+
+#include "util/Clock.h"
+#include "util/Math.h"
+#include "util/output/ConsoleWriter.h"
+#include "util/output/OutputManager.h"
+#include "core/Game.h"
+#include "core/input/InputBuffer.h"
+
+namespace orxonox
+{
+    IOConsole* IOConsole::singletonPtr_s = nullptr;
+
+    //! Redirects std::cout, creates the corresponding Shell and changes the terminal mode
+    IOConsole::IOConsole()
+        : shell_(new Shell("Console", false))
+        , buffer_(shell_->getInputBuffer())
+        , cout_(std::cout.rdbuf())
+        , promptString_("orxonox # ")
+        , inputLineHeight_(1)
+        , statusLines_(1)
+        , lastOutputLineHeight_(0)
+    {
+        // Disable standard this->cout_ logging
+        OutputManager::getInstance().getConsoleWriter()->disable();
+        // Redirect std::cout to an ostringstream
+        // (Other part is in the initialiser list)
+        std::cout.rdbuf(this->origCout_.rdbuf());
+
+        this->setTerminalMode();
+        CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
+        GetConsoleScreenBufferInfo(this->stdOutHandle_, &screenBufferInfo);
+        this->terminalWidth_  = screenBufferInfo.dwSize.X;
+        this->terminalHeight_ = screenBufferInfo.dwSize.Y;
+        // Determines where we are in respect to output already written with std::cout
+        this->inputLineRow_ = screenBufferInfo.dwCursorPosition.Y;
+/*
+        this->lastTerminalWidth_  = this->terminalWidth_;
+        this->lastTerminalHeight_ = this->terminalHeight_;
+*/
+
+        // Cursor already at the end of the screen buffer?
+        // (assuming the current input line height is 1)
+        if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
+            SetConsoleCursorPosition(this->stdOutHandle_, makeCOORD(0, this->terminalHeight_ - this->statusLines_));
+
+        // Prevent input line from overflowing
+        int maxInputLength = (this->terminalHeight_ - this->statusLines_) * this->terminalWidth_ - 1 - this->promptString_.size();
+        // Consider that the echo of a command might include the command plus some other characters (assumed max 80)
+        // Also put a minimum so the config file parser is not overwhelmed with the command history
+        this->buffer_->setMaxLength(std::min(8192, (maxInputLength - 80) / 2));
+
+        // Print input and status line and position cursor
+        this->inputChanged();
+        this->cursorChanged();
+        this->lastRefreshTime_ = Game::getInstance().getGameClock().getRealMicroseconds();
+        this->preUpdate(Game::getInstance().getGameClock());
+
+        this->shell_->registerListener(this);
+    }
+
+    //! Resets std::cout redirection and restores the terminal mode
+    IOConsole::~IOConsole()
+    {
+        // Process output written to std::cout in the meantime
+        std::cout.flush();
+        if (!this->origCout_.str().empty())
+            this->shell_->addOutput(this->origCout_.str(), Shell::LineType::Cout);
+
+        this->shell_->unregisterListener(this);
+
+        // Erase input and status lines
+        COORD pos = makeCOORD(0, this->inputLineRow_);
+        this->writeText(std::string((this->inputLineHeight_ + this->statusLines_) * this->terminalWidth_, ' '), pos);
+        // Move cursor to the beginning of the line
+        SetConsoleCursorPosition(stdOutHandle_, pos);
+
+        // Restore this->cout_ redirection
+        std::cout.rdbuf(this->cout_.rdbuf());
+        // Enable standard this->cout_ logging again
+        OutputManager::getInstance().getConsoleWriter()->enable();
+
+        resetTerminalMode();
+        delete this->shell_;
+    }
+
+    //! Processes the pending input key strokes, refreshes the status lines and handles std::cout (redirected)
+    void IOConsole::preUpdate(const Clock& time)
+    {
+        // Process input
+        while (true)
+        {
+            DWORD count;
+            INPUT_RECORD inrec;
+            PeekConsoleInput(this->stdInHandle_, &inrec, 1, &count);
+            if (count == 0)
+                break;
+            ReadConsoleInput(this->stdInHandle_, &inrec, 1, &count);
+            if (inrec.EventType == KEY_EVENT && inrec.Event.KeyEvent.bKeyDown)
+            {
+                // Process keyboard modifiers (Ctrl, Alt and Shift)
+                DWORD modifiersIn = inrec.Event.KeyEvent.dwControlKeyState;
+                int modifiersOut = 0;
+                if ((modifiersIn & (LEFT_ALT_PRESSED  | RIGHT_ALT_PRESSED))  != 0)
+                    modifiersOut |= KeyboardModifier::Alt;
+                if ((modifiersIn & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) != 0)
+                    modifiersOut |= KeyboardModifier::Ctrl;
+                if ((modifiersIn & SHIFT_PRESSED) != 0)
+                    modifiersOut |= KeyboardModifier::Shift;
+
+                // ASCII character (0 for special keys)
+                char asciiChar = inrec.Event.KeyEvent.uChar.AsciiChar;
+
+                // Process special keys and if not found, use Key::A as dummy (InputBuffer uses the ASCII text anyway)
+                switch (inrec.Event.KeyEvent.wVirtualKeyCode)
+                {
+                case VK_BACK:   this->buffer_->buttonPressed(KeyEvent(KeyCode::Back,     asciiChar, modifiersOut)); break;
+                case VK_TAB:    this->buffer_->buttonPressed(KeyEvent(KeyCode::Tab,      asciiChar, modifiersOut)); break;
+                case VK_RETURN: this->buffer_->buttonPressed(KeyEvent(KeyCode::Return,   asciiChar, modifiersOut)); break;
+                case VK_PAUSE:  this->buffer_->buttonPressed(KeyEvent(KeyCode::Pause,    asciiChar, modifiersOut)); break;
+                case VK_ESCAPE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Escape,   asciiChar, modifiersOut)); break;
+                case VK_SPACE:  this->buffer_->buttonPressed(KeyEvent(KeyCode::Space,    asciiChar, modifiersOut)); break;
+                case VK_PRIOR:  this->buffer_->buttonPressed(KeyEvent(KeyCode::PageUp,   asciiChar, modifiersOut)); break;
+                case VK_NEXT:   this->buffer_->buttonPressed(KeyEvent(KeyCode::PageDown, asciiChar, modifiersOut)); break;
+                case VK_END:    this->buffer_->buttonPressed(KeyEvent(KeyCode::End,      asciiChar, modifiersOut)); break;
+                case VK_HOME:   this->buffer_->buttonPressed(KeyEvent(KeyCode::Home,     asciiChar, modifiersOut)); break;
+                case VK_LEFT:   this->buffer_->buttonPressed(KeyEvent(KeyCode::Left,     asciiChar, modifiersOut)); break;
+                case VK_UP:     this->buffer_->buttonPressed(KeyEvent(KeyCode::Up,       asciiChar, modifiersOut)); break;
+                case VK_RIGHT:  this->buffer_->buttonPressed(KeyEvent(KeyCode::Right,    asciiChar, modifiersOut)); break;
+                case VK_DOWN:   this->buffer_->buttonPressed(KeyEvent(KeyCode::Down,     asciiChar, modifiersOut)); break;
+                case VK_INSERT: this->buffer_->buttonPressed(KeyEvent(KeyCode::Insert,   asciiChar, modifiersOut)); break;
+                case VK_DELETE: this->buffer_->buttonPressed(KeyEvent(KeyCode::Delete,   asciiChar, modifiersOut)); break;
+                default:        this->buffer_->buttonPressed(KeyEvent(KeyCode::A,        asciiChar, modifiersOut));
+                }
+            }
+        }
+
+        // TODO: Respect screen buffer size changes
+/*
+        // The user can manually adjust the screen buffer size on Windows
+        // And we don't want to screw the console because of that
+        this->lastTerminalWidth_ = this->terminalWidth_;
+        this->lastTerminalHeight_ = this->terminalHeight_;
+        this->getTerminalSize(); // Also sets this->inputLineRow_ according to the cursor position
+        // Is there still enough space below the cursor for the status line(s)?
+        if (this->inputLineRow_ >= this->terminalHeight_ - this->statusLines_)
+            this->moveCursor(0, -this->inputLineRow_ + this->terminalHeight_ - this->statusLines_ - 1);
+*/
+
+        // Refresh status line 5 times per second
+        if (time.getMicroseconds() > this->lastRefreshTime_ + 1000000)
+        {
+            this->printStatusLines();
+            this->lastRefreshTime_ = time.getMicroseconds();
+        }
+
+        // Process output written to std::cout
+        std::cout.flush();
+        if (!this->origCout_.str().empty())
+        {
+            this->shell_->addOutput(this->origCout_.str(), Shell::LineType::Cout);
+            this->origCout_.str("");
+        }
+    }
+
+    //! Prints output text. Similar to writeText, but sets the colour according to the output level
+    void IOConsole::printOutputLine(const std::string& text, Shell::LineType type, const COORD& pos)
+    {
+        // Colour line
+        WORD colour = 0;
+        switch (type)
+        {
+            case Shell::LineType::Message:
+            case Shell::LineType::DebugOutput:     colour = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
+
+            case Shell::LineType::UserError:       colour = FOREGROUND_INTENSITY | FOREGROUND_RED | 0                | 0              ; break;
+            case Shell::LineType::UserWarning:     colour = FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | 0              ; break;
+            case Shell::LineType::UserStatus:      colour = FOREGROUND_INTENSITY | 0              | FOREGROUND_GREEN | 0              ; break;
+            case Shell::LineType::UserInfo:        colour = FOREGROUND_INTENSITY | 0              | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
+
+            case Shell::LineType::InternalError:   colour = 0                    | FOREGROUND_RED | 0                | 0              ; break;
+            case Shell::LineType::InternalWarning: colour = 0                    | FOREGROUND_RED | FOREGROUND_GREEN | 0              ; break;
+            case Shell::LineType::InternalStatus:  colour = 0                    | 0              | FOREGROUND_GREEN | 0              ; break;
+            case Shell::LineType::InternalInfo:    colour = 0                    | 0              | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
+
+            case Shell::LineType::Verbose:         colour = FOREGROUND_INTENSITY | 0              | 0                | FOREGROUND_BLUE; break;
+            case Shell::LineType::VerboseMore:     colour = FOREGROUND_INTENSITY | 0              | 0                | FOREGROUND_BLUE; break;
+            case Shell::LineType::VerboseUltra:    colour = FOREGROUND_INTENSITY | 0              | 0                | FOREGROUND_BLUE; break;
+
+            case Shell::LineType::Command:         colour = FOREGROUND_INTENSITY | FOREGROUND_RED | 0                | FOREGROUND_BLUE; break;
+            case Shell::LineType::Hint:            colour = 0                    | FOREGROUND_RED | 0                | FOREGROUND_BLUE; break;
+
+            default:                               colour = 0                    | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; break;
+        }
+
+        // Print output line
+        this->writeText(text, pos, colour);
+    }
+
+    //! Prints all status lines with current content
+    void IOConsole::printStatusLines()
+    {
+        // Prepare text to be written
+        std::ostringstream oss;
+        oss << std::fixed << std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgFPS() << " fps, ";
+        oss <<               std::setprecision(2) << std::setw(5) << Game::getInstance().getAvgTickTime() << " ms tick time";
+        // Clear rest of the line by inserting spaces
+        oss << std::string(this->terminalWidth_ - oss.str().size(), ' ');
+        this->writeText(oss.str(), makeCOORD(0, this->inputLineRow_ + this->inputLineHeight_), FOREGROUND_GREEN);
+    }
+
+    //! Changes the console parameters for unbuffered input
+    void IOConsole::setTerminalMode()
+    {
+        // Set the console mode to no-echo, raw input, and no window or mouse events
+        this->stdOutHandle_ = GetStdHandle(STD_OUTPUT_HANDLE);
+        this->stdInHandle_  = GetStdHandle(STD_INPUT_HANDLE);
+        if (this->stdInHandle_ == INVALID_HANDLE_VALUE
+            || !GetConsoleMode(this->stdInHandle_, &this->originalTerminalSettings_)
+            || !SetConsoleMode(this->stdInHandle_, 0))
+        {
+            orxout(user_error) << "Could not set Windows console settings" << endl;
+            return;
+        }
+        FlushConsoleInputBuffer(this->stdInHandle_);
+    }
+
+    //! Restores the console parameters
+    void IOConsole::resetTerminalMode()
+    {
+        SetConsoleMode(this->stdInHandle_, this->originalTerminalSettings_);
+    }
+
+    //! Sets this->terminalWidth_ and this->terminalHeight_
+    void IOConsole::getTerminalSize()
+    {
+        CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
+        GetConsoleScreenBufferInfo(this->stdOutHandle_, &screenBufferInfo);
+        this->terminalWidth_  = screenBufferInfo.dwSize.X;
+        this->terminalHeight_ = screenBufferInfo.dwSize.Y;
+    }
+
+    //! Writes arbitrary text to the console with a certain colour and screen buffer position
+    void IOConsole::writeText(const std::string& text, const COORD& coord, WORD attributes)
+    {
+        DWORD count;
+        WriteConsoleOutputCharacter(stdOutHandle_, text.c_str(), text.size(), coord, &count);
+        FillConsoleOutputAttribute(stdOutHandle_, attributes, text.size(), coord, &count);
+    }
+
+    /** Scrolls the console screen buffer to create empty lines above the input line.
+    @details
+        If the input and status lines are already at the bottom of the screen buffer
+        the whole output gets scrolled up. In the other case the input and status
+        lines get scrolled down.
+        In any case the status and input lines get scrolled down as far as possible.
+    @param lines
+        Number of lines to be inserted. Behavior for negative values is undefined.
+    */
+    void IOConsole::createNewOutputLines(int lines)
+    {
+        CHAR_INFO fillChar = {{' '}, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
+        // Lines to scroll input/status down (if possible)
+        int linesDown = clamp(terminalHeight_ - inputLineRow_ - inputLineHeight_ - statusLines_, 0, lines);
+        if (linesDown > 0)
+        {
+            // Scroll input and status lines down
+            SMALL_RECT oldRect = makeSMALL_RECT(0, this->inputLineRow_,
+                this->terminalWidth_ - 1, this->inputLineRow_ + this->inputLineHeight_ + this->statusLines_ - 1);
+            this->inputLineRow_ += linesDown;
+            ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, nullptr, makeCOORD(0, this->inputLineRow_), &fillChar);
+            // Move cursor down to the new bottom so the user can see the status lines
+            COORD pos = makeCOORD(0, this->inputLineRow_ + this->inputLineHeight_ - 1 + this->statusLines_);
+            SetConsoleCursorPosition(stdOutHandle_, pos);
+            // Get cursor back to the right position
+            this->cursorChanged();
+        }
+        // Check how many lines we still have to scroll up the output
+        if (lines - linesDown > 0)
+        {
+            // Scroll output up
+            SMALL_RECT oldRect = makeSMALL_RECT(0, lines - linesDown, this->terminalWidth_ - 1, this->inputLineRow_ - 1);
+            ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, nullptr, makeCOORD(0, 0), &fillChar);
+        }
+    }
+
+    // ###############################
+    // ###  ShellListener methods  ###
+    // ###############################
+
+    //! Called if all output-lines have to be reprinted
+    void IOConsole::linesChanged()
+    {
+        // Method only gets called upon start to draw all the lines
+        // or when scrolling. But scrolling is disabled and the output
+        // is already in std::cout when we start the IOConsole
+    }
+
+    //! Called if a command is about to be executed
+    void IOConsole::executed()
+    {
+        this->shell_->addOutput(this->promptString_ + this->shell_->getInput(), Shell::LineType::Command);
+    }
+
+    //! Called if the console gets closed
+    void IOConsole::exit()
+    {
+        // Exit is not an option, just do nothing (Shell doesn't really exit too)
+    }
+
+    //! Called if the text in the input line has changed
+    void IOConsole::inputChanged()
+    {
+        int newInputLineLength = this->promptString_.size() + this->shell_->getInput().size();
+        int newInputLineHeight = 1 + newInputLineLength / this->terminalWidth_;
+        int newLines = newInputLineHeight - this->inputLineHeight_;
+        if (newLines > 0)
+        {
+            // Abuse this function to scroll the console
+            this->createNewOutputLines(newLines);
+            // Either Compensate for side effects (input/status lines scrolled down)
+            // or we have to do this anyway (output scrolled up)
+            this->inputLineRow_ -= newLines;
+        }
+        else if (newLines < 0)
+        {
+            // Scroll status lines up
+            int statusLineRow = this->inputLineRow_ + this->inputLineHeight_;
+            SMALL_RECT oldRect = makeSMALL_RECT(0, statusLineRow, this->terminalWidth_ - 1, statusLineRow + this->statusLines_);
+            CHAR_INFO fillChar = {{' '}, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED};
+            ScrollConsoleScreenBuffer(stdOutHandle_, &oldRect, nullptr, makeCOORD(0, statusLineRow + newLines), &fillChar);
+            // Clear potential leftovers
+            if (-newLines - this->statusLines_ > 0)
+            {
+                COORD pos = makeCOORD(0, this->inputLineRow_ + newInputLineHeight + this->statusLines_);
+                this->writeText(std::string((-newLines - this->statusLines_) * this->terminalWidth_, ' '), pos);
+            }
+        }
+        this->inputLineHeight_ = newInputLineHeight;
+
+        // Print the whole line, including spaces that erase leftovers
+        std::string inputLine = this->promptString_ + this->shell_->getInput();
+        inputLine += std::string(this->terminalWidth_ - newInputLineLength % this->terminalWidth_, ' ');
+        this->writeText(inputLine, makeCOORD(0, this->inputLineRow_), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+        // If necessary, move cursor
+        if (newLines != 0)
+            this->cursorChanged();
+    }
+
+    //! Called if the position of the cursor in the input-line has changed
+    void IOConsole::cursorChanged()
+    {
+        int rawCursorPos = this->promptString_.size() + this->buffer_->getCursorPosition();
+        // Compensate for cursor further to the right than the terminal width
+        COORD pos;
+        pos.X = rawCursorPos % this->terminalWidth_;
+        pos.Y = this->inputLineRow_ + rawCursorPos / this->terminalWidth_;
+        SetConsoleCursorPosition(stdOutHandle_, pos);
+    }
+
+    //! Called if a new output line was added
+    void IOConsole::lineAdded()
+    {
+        Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
+        // Scroll console
+        this->lastOutputLineHeight_ = 1 + it->first.size() / this->terminalWidth_;
+        this->createNewOutputLines(this->lastOutputLineHeight_);
+        // Write the text
+        COORD pos = makeCOORD(0, this->inputLineRow_ - this->lastOutputLineHeight_);
+        this->printOutputLine(it->first, it->second, pos);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsoleWindows.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsoleWindows.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IOConsoleWindows.h	(revision 11817)
@@ -0,0 +1,117 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command ShellConsole
+*/
+
+#ifndef _IOConsole_H__
+#define _IOConsole_H__
+
+#include "core/CorePrereqs.h"
+
+#include <sstream>
+#include <string>
+#include "util/Singleton.h"
+#include "Shell.h"
+
+#define WIN32_LEAN_AND_MEAN
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#include <windows.h>
+
+namespace orxonox
+{
+    class _CoreExport IOConsole : public Singleton<IOConsole>, public ShellListener
+    {
+        friend class Singleton<IOConsole>;
+
+    public:
+        IOConsole();
+        ~IOConsole();
+
+        void preUpdate(const Clock& time);
+
+    private:
+        void setTerminalMode();
+        void getTerminalSize();
+        void printStatusLines();
+        static int extractLogLevel(std::string* text);
+
+        // Methods from ShellListener
+        virtual void linesChanged() override;
+        virtual void lineAdded() override;
+        virtual void inputChanged() override;
+        virtual void cursorChanged() override;
+        virtual void executed() override;
+        virtual void exit() override;
+
+        void resetTerminalMode();
+        void moveCursor(int dx, int dy);
+        void writeText(const std::string& text, const COORD& pos, WORD attributes = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
+        void createNewOutputLines(int lines);
+        void printOutputLine(const std::string& line, Shell::LineType type, const COORD& pos);
+
+        static inline COORD makeCOORD(SHORT x, SHORT y)
+        {
+            COORD val = {x, y};
+            return val;
+        }
+
+        static inline SMALL_RECT makeSMALL_RECT(SHORT left, SHORT top, SHORT right, SHORT bottom)
+        {
+            SMALL_RECT val = {left, top, right, bottom};
+            return val;
+        }
+
+        Shell*                  shell_;
+        InputBuffer*            buffer_;
+        std::ostream            cout_;
+        std::ostringstream      origCout_;
+        int                     terminalWidth_;
+        int                     terminalHeight_;
+        int                     lastTerminalWidth_;
+        int                     lastTerminalHeight_;
+        const std::string       promptString_;
+
+        DWORD                   originalTerminalSettings_;
+        HANDLE                  stdInHandle_;
+        HANDLE                  stdOutHandle_;
+        int                     inputLineRow_;
+        int                     inputLineHeight_;
+        const int               statusLines_;
+        int                     lastOutputLineHeight_;
+        uint64_t                lastRefreshTime_;
+
+        static IOConsole* singletonPtr_s;
+    };
+}
+
+#endif /* _IOConsole_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IRC.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IRC.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IRC.cc	(revision 11817)
@@ -0,0 +1,161 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the IRC class and the IRC console commands.
+*/
+
+#include "IRC.h"
+
+#include <cpptcl/cpptcl.h>
+
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "ConsoleCommandIncludes.h"
+#include "TclThreadManager.h"
+
+namespace orxonox
+{
+    static constexpr unsigned int IRC_TCL_THREADID  = 1421421421;   ///< The ID of the thread in TclThreadManager that is used for the IRC connection
+
+    SetConsoleCommand("IRC", "say",  &IRC::say);
+    SetConsoleCommand("IRC", "msg",  &IRC::msg);
+    SetConsoleCommand("IRC", "nick", &IRC::nick);
+
+    /**
+        @brief Returns the only existing instance of IRC.
+    */
+    IRC& IRC::getInstance()
+    {
+        static IRC instance;
+        return instance;
+    }
+
+    /**
+        @brief Constructor: Doesn't yet connect to IRC nor does it create a Tcl interpreter.
+        The IRC object will automatically connect to the IRC server if one of the registered
+        console commands is used the first time.
+    */
+    IRC::IRC()
+    {
+        this->interpreter_ = nullptr;
+    }
+
+    /**
+        @brief Creates and initializes a new multithreaded Tcl-interpreter and defines some callbacks to display IRC-messages in the console.
+    */
+    void IRC::initialize()
+    {
+        unsigned int threadID = IRC_TCL_THREADID;
+        this->interpreter_ = TclThreadManager::createWithId(threadID);
+
+        try
+        {
+            this->interpreter_->def("::orxonox::irc::say", IRC::tcl_say, Tcl::variadic());
+            this->interpreter_->def("::orxonox::irc::privmsg", IRC::tcl_privmsg, Tcl::variadic());
+            this->interpreter_->def("::orxonox::irc::action", IRC::tcl_action, Tcl::variadic());
+            this->interpreter_->def("::orxonox::irc::info", IRC::tcl_info, Tcl::variadic());
+        }
+        catch (Tcl::tcl_error const &e)
+        {   orxout(user_error, context::tcl) << "Tcl (IRC) error: " << e.what() << endl;   }
+
+        this->nickname_ = "orx" + multi_cast<std::string>(static_cast<unsigned int>(rand()));
+        TclThreadManager::execute(threadID, "set nickname " + this->nickname_);
+        TclThreadManager::execute(threadID, "source irc.tcl");
+    }
+
+    /**
+        @brief Executes a Tcl-command on the Tcl-interpreter.
+    */
+    bool IRC::eval(const std::string& command)
+    {
+        if (!IRC::getInstance().interpreter_)
+        {
+            IRC::getInstance().initialize();
+            orxout(user_error) << "IRC client wasn't yet initialized, please try again." << endl;
+            return false;
+        }
+
+        try
+        {
+            IRC::getInstance().interpreter_->eval(command);
+            return true;
+        }
+        catch (Tcl::tcl_error const &e)
+        {   orxout(user_error, context::tcl) << "Tcl (IRC) error: " << e.what() << endl;   }
+
+        return false;
+    }
+
+    /// Console command: Sends a message to the current channel on the IRC server.
+    void IRC::say(const std::string& message)
+    {
+        if (IRC::eval("irk::say $conn #orxonox {" + message + '}'))
+            IRC::tcl_say(Tcl::object(), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
+    }
+
+    /// Console command: Sends a message to a given channel or nickname on the IRC server.
+    void IRC::msg(const std::string& channel, const std::string& message)
+    {
+        if (IRC::eval("irk::say $conn " + channel + " {" + message + '}'))
+            IRC::tcl_privmsg(Tcl::object(channel), Tcl::object(IRC::getInstance().nickname_), Tcl::object(message));
+    }
+
+    /// Console command: Changes the nickname on the IRC server.
+    void IRC::nick(const std::string& nickname)
+    {
+        if (IRC::eval("irk::nick $conn " + nickname))
+            IRC::getInstance().nickname_ = nickname;
+    }
+
+    /// Tcl-callback: Prints a message that was received from the current IRC channel to the console.
+    void IRC::tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+    {
+        orxout(message) << "IRC> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << endl;
+    }
+
+    /// Tcl-callback: Prints a private message that was received from a user to the console.
+    void IRC::tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args)
+    {
+        orxout(message) << "IRC (" << query.get() << ")> " << nick.get() << ": " << stripEnclosingBraces(args.get()) << endl;
+    }
+
+    /// Tcl-callback: Prints an action-message (usually /me ...) that was received from the current IRC channel to the console.
+    void IRC::tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args)
+    {
+        orxout(message) << "IRC> * " << nick.get() << ' ' << stripEnclosingBraces(args.get()) << endl;
+    }
+
+    /// Tcl-callback: Prints all kinds of information that were received from the IRC server or channel (connection info, join, part, modes, ...) to the console.
+    void IRC::tcl_info(Tcl::object const &channel, Tcl::object const &args)
+    {
+        orxout(message) << "IRC> --> " << stripEnclosingBraces(args.get()) << endl;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/IRC.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/IRC.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/IRC.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command Tcl
+    @brief Declaration of IRC helper class, used for IRC connections using Tcl.
+*/
+
+#ifndef _IRC_H__
+#define _IRC_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+
+namespace orxonox
+{
+    /**
+        @brief The IRC class creates a Tcl-thread (see TclThreadManager) and connects to an IRC server.
+        It provides different console commands to send messages and to perform other actions on the IRC server.
+    */
+    class _CoreExport IRC
+    {
+        public:
+            static IRC& getInstance();
+
+            static void say(const std::string& message);
+            static void msg(const std::string& channel, const std::string& message);
+            static void nick(const std::string& nickname);
+
+            static void tcl_say(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
+            static void tcl_privmsg(Tcl::object const &query, Tcl::object const &nick, Tcl::object const &args);
+            static void tcl_action(Tcl::object const &channel, Tcl::object const &nick, Tcl::object const &args);
+            static void tcl_info(Tcl::object const &channel, Tcl::object const &args);
+
+        private:
+            static bool eval(const std::string& command);
+            void initialize();
+
+            IRC();
+            ~IRC() = default;
+
+            // non-copyable:
+            IRC(const IRC&) = delete;
+            IRC& operator=(const IRC&) = delete;
+
+            Tcl::interpreter* interpreter_;     ///< The Tcl interpreter that is used for the IRC connection
+            std::string nickname_;              ///< The user's nickname on the IRC server
+    };
+}
+
+#endif /* _IRC_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/Shell.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/Shell.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/Shell.cc	(revision 11817)
@@ -0,0 +1,539 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the Shell class.
+*/
+
+#include "Shell.h"
+
+#include "util/Math.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+#include "util/output/OutputManager.h"
+#include "util/output/MemoryWriter.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigFileManager.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/ApplicationPaths.h"
+#include "core/input/InputBuffer.h"
+#include "CommandExecutor.h"
+
+namespace orxonox
+{
+    unsigned int Shell::cacheSize_s;
+
+    namespace DefaultLogLevel
+    {
+        const OutputLevel Dev  = level::internal_warning;
+        const OutputLevel User = level::user_info;
+    }
+
+    RegisterClassNoArgs(Shell);
+
+    /**
+        @brief Constructor: Initializes the values.
+        @param consoleName The name of the shell - used to define the name of the soft-debug-level config-value
+        @param bScrollable If true, the user is allowed to scroll through the output-lines
+    */
+    Shell::Shell(const std::string& consoleName, bool bScrollable)
+        : BaseWriter(consoleName, false)
+        , inputBuffer_(new InputBuffer())
+        , bScrollable_(bScrollable)
+    {
+        RegisterObject(Shell);
+
+        OutputManager::getInstance().registerListener(this);
+
+        this->scrollPosition_ = 0;
+        this->maxHistoryLength_ = 100;
+        this->historyPosition_ = 0;
+        this->historyOffset_ = 0;
+
+        this->clearOutput();
+        this->configureInputBuffer();
+
+        // Specify file for the command history
+        ConfigFileManager::getInstance().setFilename(ConfigFileType::CommandHistory, "commandHistory.ini");
+
+        // Choose the default level according to the path Orxonox was started (build directory or not)
+        OutputLevel defaultDebugLevel = (ApplicationPaths::buildDirectoryRun() ? DefaultLogLevel::Dev : DefaultLogLevel::User);
+        this->setLevelMax(defaultDebugLevel);
+
+        this->setConfigValues();
+
+        // Get the previous output and add it to the Shell
+        OutputManager::getInstance().getMemoryWriter()->resendOutput(this);
+    }
+
+    /**
+        @brief Destructor
+    */
+    Shell::~Shell()
+    {
+        delete this->inputBuffer_;
+
+        OutputManager::getInstance().unregisterListener(this);
+    }
+
+    /**
+        @brief Defines the config values.
+    */
+    void Shell::setConfigValues()
+    {
+        SetConfigValue(maxHistoryLength_, 100)
+            .callback(this, &Shell::commandHistoryLengthChanged);
+        SetConfigValue(historyOffset_, 0)
+            .callback(this, &Shell::commandHistoryOffsetChanged);
+        setConfigValueGeneric(this, &commandHistory_, ConfigFileType::CommandHistory, "Shell", "commandHistory_", std::vector<std::string>());
+        SetConfigValue(cacheSize_s, 32);
+
+        SetConfigValueExternal(this->configurableMaxLevel_,
+                               this->getConfigurableSectionName(),
+                               this->getConfigurableMaxLevelName(),
+                               this->configurableMaxLevel_)
+            .description("The maximum level of output shown in the " + this->getName())
+            .callback(static_cast<BaseWriter*>(this), &BaseWriter::changedConfigurableLevel);
+        SetConfigValueExternal(this->configurableAdditionalContextsMaxLevel_,
+                               this->getConfigurableSectionName(),
+                               this->getConfigurableAdditionalContextsMaxLevelName(),
+                               this->configurableAdditionalContextsMaxLevel_)
+            .description("The maximum level of output shown in the " + this->getName() + " for additional contexts")
+            .callback(static_cast<BaseWriter*>(this), &BaseWriter::changedConfigurableAdditionalContextsLevel);
+        SetConfigValueExternal(this->configurableAdditionalContexts_,
+                               this->getConfigurableSectionName(),
+                               this->getConfigurableAdditionalContextsName(),
+                               this->configurableAdditionalContexts_)
+            .description("Additional output contexts shown in the " + this->getName())
+            .callback(static_cast<BaseWriter*>(this), &BaseWriter::changedConfigurableAdditionalContexts);
+    }
+
+    /**
+        @brief Config-value callback: Called when the history offset has changed in the config-file.
+    */
+    void Shell::commandHistoryOffsetChanged()
+    {
+        if (this->historyOffset_ >= this->maxHistoryLength_)
+            this->historyOffset_ = 0;
+    }
+
+    /**
+        @brief Config-value callback: Called when the length of the command history has changed in the config-file.
+    */
+    void Shell::commandHistoryLengthChanged()
+    {
+        this->commandHistoryOffsetChanged();
+
+        while (this->commandHistory_.size() > this->maxHistoryLength_)
+        {
+            unsigned int index = this->commandHistory_.size() - 1;
+            this->commandHistory_.erase(this->commandHistory_.begin() + index);
+            ModifyConfigValue(commandHistory_, remove, index);
+        }
+    }
+
+    /** Called upon changes in the development mode (by Core)
+        Behaviour details see Core::devModeChanged.
+    */
+    void Shell::devModeChanged(bool value)
+    {
+        bool isNormal = (value == ApplicationPaths::buildDirectoryRun());
+        if (isNormal)
+        {
+            ModifyConfigValueExternal(this->configurableMaxLevel_, this->getConfigurableMaxLevelName(), update);
+        }
+        else
+        {
+            OutputLevel level = (value ? DefaultLogLevel::Dev : DefaultLogLevel::User);
+            ModifyConfigValueExternal(this->configurableMaxLevel_, this->getConfigurableMaxLevelName(), tset, static_cast<int>(level));
+        }
+    }
+
+    /**
+        @brief Registers this object as listener for different key-events at the input buffer.
+    */
+    void Shell::configureInputBuffer()
+    {
+        this->inputBuffer_->registerListener(this, &Shell::inputChanged, true);
+        this->inputBuffer_->registerListener(this, &Shell::execute,         '\r',   false);
+        this->inputBuffer_->registerListener(this, &Shell::execute,         '\n',   false);
+        this->inputBuffer_->registerListener(this, &Shell::hintAndComplete, '\t',   true);
+        this->inputBuffer_->registerListener(this, &Shell::backspace,       '\b',   true);
+        this->inputBuffer_->registerListener(this, &Shell::backspace,       '\177', true);
+        this->inputBuffer_->registerListener(this, &Shell::exit,            '\033', true); // escape
+        this->inputBuffer_->registerListener(this, &Shell::deleteChar,      KeyCode::Delete);
+        this->inputBuffer_->registerListener(this, &Shell::cursorRight,     KeyCode::Right);
+        this->inputBuffer_->registerListener(this, &Shell::cursorLeft,      KeyCode::Left);
+        this->inputBuffer_->registerListener(this, &Shell::cursorEnd,       KeyCode::End);
+        this->inputBuffer_->registerListener(this, &Shell::cursorHome,      KeyCode::Home);
+        this->inputBuffer_->registerListener(this, &Shell::historyUp,       KeyCode::Up);
+        this->inputBuffer_->registerListener(this, &Shell::historyDown,     KeyCode::Down);
+        if (this->bScrollable_)
+        {
+            this->inputBuffer_->registerListener(this, &Shell::scrollUp,    KeyCode::PageUp);
+            this->inputBuffer_->registerListener(this, &Shell::scrollDown,  KeyCode::PageDown);
+        }
+        else
+        {
+            this->inputBuffer_->registerListener(this, &Shell::historySearchUp,   KeyCode::PageUp);
+            this->inputBuffer_->registerListener(this, &Shell::historySearchDown, KeyCode::PageDown);
+        }
+    }
+
+    /**
+        @brief Registers a shell listener which listens for changes in this shell.
+    */
+    void Shell::registerListener(ShellListener* listener)
+    {
+        this->listeners_.push_back(listener);
+    }
+
+    /**
+        @brief Unregisters a shell listener.
+    */
+    void Shell::unregisterListener(ShellListener* listener)
+    {
+        for (std::list<ShellListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+        {
+            if ((*it) == listener)
+                it = this->listeners_.erase(it);
+            else
+                ++it;
+        }
+    }
+
+    /**
+        @brief Changes the position of the cursor in the input buffer.
+    */
+    void Shell::setCursorPosition(unsigned int cursor)
+    {
+        this->inputBuffer_->setCursorPosition(cursor);
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// Returns the current position of the cursor in the input buffer.
+    unsigned int Shell::getCursorPosition() const
+    {
+        return this->inputBuffer_->getCursorPosition();
+    }
+
+    /// Returns the current content of the input buffer (the text which was entered by the user)
+    const std::string& Shell::getInput() const
+    {
+        return this->inputBuffer_->get();
+    }
+
+    /**
+        @brief Adds multiple lines to the internal output buffer.
+    */
+    void Shell::addOutput(const std::string& text, LineType type)
+    {
+        std::vector<std::string> lines;
+        vectorize(text, '\n', &lines);
+
+        for (const std::string& line : lines)
+            this->addLine(line, type);
+    }
+
+    /**
+        @brief Adds a line to the internal output buffer.
+    */
+    void Shell::addLine(const std::string& line, LineType type)
+    {
+        // yes it was - push the new line to the list
+        this->outputLines_.push_front(std::make_pair(line, type));
+
+        // adjust the scroll position if needed
+        if (this->scrollPosition_)
+            this->scrollPosition_++;
+        else
+            this->scrollIterator_ = this->outputLines_.begin();
+
+        if (!this->scrollPosition_)
+            this->updateListeners<&ShellListener::lineAdded>();
+    }
+
+    /**
+        @brief Clears the list of output-lines.
+    */
+    void Shell::clearOutput()
+    {
+        this->outputLines_.clear();
+        this->scrollIterator_ = this->outputLines_.begin();
+
+        this->scrollPosition_ = 0;
+
+        this->updateListeners<&ShellListener::linesChanged>();
+    }
+
+    /**
+        @brief Inherited from BaseWriter (LogListener), called if a new line of output was sent.
+    */
+    void Shell::printLine(const std::string& line, OutputLevel level)
+    {
+        this->addLine(line, static_cast<LineType>(level));
+    }
+
+    /**
+        @brief Returns an iterator to the newest line of output (except if the user is currently scrolling through the output).
+    */
+    Shell::LineList::const_iterator Shell::getNewestLineIterator() const
+    {
+        if (this->scrollPosition_)
+            return this->scrollIterator_;
+        else
+            return this->outputLines_.begin();
+    }
+
+    /**
+        @brief Returns the end() iterator of the list of output-lines.
+    */
+    Shell::LineList::const_iterator Shell::getEndIterator() const
+    {
+        return this->outputLines_.end();
+    }
+
+    /**
+        @brief Adds a command to the history of entered commands and writes it to the config-file.
+    */
+    void Shell::addToHistory(const std::string& command)
+    {
+        if (command == "")
+            return;
+
+        size_t previous_offset = mod(static_cast<int>(this->historyOffset_) - 1, this->maxHistoryLength_);
+        if (previous_offset < this->commandHistory_.size() && command == this->commandHistory_[previous_offset])
+            return;
+
+        ModifyConfigValue(commandHistory_, set, this->historyOffset_, command);
+        this->historyPosition_ = 0;
+        ModifyConfigValue(historyOffset_, set, (this->historyOffset_ + 1) % this->maxHistoryLength_);
+    }
+
+    /**
+        @brief Returns a command from the history of entered commands (usually the most recent history entry, but the user can scroll through the history).
+    */
+    const std::string& Shell::getFromHistory() const
+    {
+        unsigned int index = mod(static_cast<int>(this->historyOffset_) - static_cast<int>(this->historyPosition_), this->maxHistoryLength_);
+        if (index < this->commandHistory_.size() && this->historyPosition_ != 0)
+            return this->commandHistory_[index];
+        else
+            return BLANKSTRING;
+    }
+
+    /**
+        @brief Clears the text in the input buffer.
+    */
+    void Shell::clearInput()
+    {
+        this->inputBuffer_->clear();
+        this->historyPosition_ = 0;
+        this->updateListeners<&ShellListener::inputChanged>();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+
+    // ##########################################
+    // ###   InputBuffer callback functions   ###
+    // ##########################################
+
+    /// InputBuffer callback: Called if the input changes.
+    void Shell::inputChanged()
+    {
+        this->updateListeners<&ShellListener::inputChanged>();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that executes a command (usually [return]).
+    void Shell::execute()
+    {
+        this->addToHistory(this->inputBuffer_->get());
+        this->updateListeners<&ShellListener::executed>();
+
+        int error;
+        const std::string& result = CommandExecutor::query(this->inputBuffer_->get(), &error);
+        if (error)
+            this->addOutput("Error: Can't execute \"" + this->inputBuffer_->get() + "\", " + CommandExecutor::getErrorDescription(error) + ". (Shell)", LineType::UserError);
+        else if (result != "")
+            this->addOutput(result, LineType::Result);
+
+        this->clearInput();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that shows hints and completes a command (usually [tab]).
+    void Shell::hintAndComplete()
+    {
+        this->inputBuffer_->set(CommandExecutor::evaluate(this->inputBuffer_->get()).complete());
+        this->addOutput(CommandExecutor::evaluate(this->inputBuffer_->get()).hint(), LineType::Hint);
+
+        this->inputChanged();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that deletes the character before the cursor (usually [backspace]).
+    void Shell::backspace()
+    {
+        this->inputBuffer_->removeBehindCursor();
+        this->updateListeners<&ShellListener::inputChanged>();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that deletes the character after the cursor (usually [delete]).
+    void Shell::deleteChar()
+    {
+        this->inputBuffer_->removeAtCursor();
+        this->updateListeners<&ShellListener::inputChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that moves the input cursor the right (usually [arrow right]).
+    void Shell::cursorRight()
+    {
+        this->inputBuffer_->increaseCursor();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that moves the input cursor the left (usually [arrow left]).
+    void Shell::cursorLeft()
+    {
+        this->inputBuffer_->decreaseCursor();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that moves the input cursor the end of the input line (usually [end]).
+    void Shell::cursorEnd()
+    {
+        this->inputBuffer_->setCursorToEnd();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that moves the input cursor the beginning of the input line (usually [home]).
+    void Shell::cursorHome()
+    {
+        this->inputBuffer_->setCursorToBegin();
+        this->updateListeners<&ShellListener::cursorChanged>();
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that scrolls upwards through the history of entered commands (usually [arrow up]).
+    void Shell::historyUp()
+    {
+        if (this->historyPosition_ < this->commandHistory_.size())
+        {
+            this->historyPosition_++;
+            this->inputBuffer_->set(this->getFromHistory());
+        }
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that scrolls downwards through the history of entered commands (usually [arrow down]).
+    void Shell::historyDown()
+    {
+        if (this->historyPosition_ > 0)
+        {
+            this->historyPosition_--;
+            this->inputBuffer_->set(this->getFromHistory());
+        }
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that searches upwards through the history for a command stat starts like the one the user is currently typing (usually [page up]). Only if the shell is not scrollable.
+    void Shell::historySearchUp()
+    {
+        if (this->historyPosition_ == this->historyOffset_)
+            return;
+        unsigned int cursorPosition = this->getCursorPosition();
+        const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline until the cursor position
+        for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
+        {
+            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
+            {
+                this->historyPosition_ = newPos;
+                this->inputBuffer_->set(this->getFromHistory());
+                this->setCursorPosition(cursorPosition);
+                return;
+            }
+        }
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that searches downwards through the history for a command stat starts like the one the user is currently typing (usually [page down]). Only if the shell is not scrollable.
+    void Shell::historySearchDown()
+    {
+        if (this->historyPosition_ == 0)
+            return;
+        unsigned int cursorPosition = this->getCursorPosition();
+        const std::string& input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning
+        for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
+        {
+            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
+            {
+                this->historyPosition_ = newPos;
+                this->inputBuffer_->set(this->getFromHistory());
+                this->setCursorPosition(cursorPosition);
+                return;
+            }
+        }
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that scrolls upwards through the output history (usually [page up]). Only if the shell is scrollable.
+    void Shell::scrollUp()
+    {
+        if (this->scrollIterator_ != this->outputLines_.end())
+        {
+            ++this->scrollIterator_;
+            ++this->scrollPosition_;
+
+            this->updateListeners<&ShellListener::linesChanged>();
+        }
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that scrolls downwards through the output history (usually [page down]). Only if the shell is scrollable.
+    void Shell::scrollDown()
+    {
+        if (this->scrollIterator_ != this->outputLines_.begin())
+        {
+            --this->scrollIterator_;
+            --this->scrollPosition_;
+
+            this->updateListeners<&ShellListener::linesChanged>();
+        }
+    }
+
+    /// InputBuffer callback: Called if a key was pressed that clears the text in the input buffer or closes the shell (usually [esc]).
+    void Shell::exit()
+    {
+        if (this->inputBuffer_->getSize() > 0)
+        {
+            this->clearInput();
+            return;
+        }
+
+        this->clearInput();
+        this->scrollPosition_ = 0;
+        this->scrollIterator_ = this->outputLines_.begin();
+
+        this->updateListeners<&ShellListener::exit>();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/Shell.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/Shell.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/Shell.h	(revision 11817)
@@ -0,0 +1,208 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+/**
+    @defgroup ShellConsole Shell and console
+    @ingroup Command
+*/
+
+/**
+    @file
+    @ingroup Command ShellConsole
+    @brief Declaration of the Shell and ShellListener classes.
+*/
+
+#ifndef _Shell_H__
+#define _Shell_H__
+
+#include "core/CorePrereqs.h"
+
+#include <list>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "util/output/BaseWriter.h"
+#include "core/CoreConfig.h"
+
+namespace orxonox
+{
+    /**
+        @brief An interface, used to get a notification if the state of the Shell changes.
+    */
+    class _CoreExport ShellListener
+    {
+        friend class Shell;
+
+        public:
+            ShellListener() = default;
+            virtual ~ShellListener() = default;
+
+        private:
+            virtual void linesChanged() {}          ///< Called if all output-lines have changed
+            virtual void lineAdded() {}             ///< Called if a new line was added to the output
+            virtual void inputChanged() {}          ///< Called if the input has changed
+            virtual void cursorChanged() {}         ///< Called if the cursor in the input line has changed
+            virtual void executed() {}              ///< Called if a command from the input line was executed
+            virtual void exit() {}                  ///< Called if the console should be closed
+    };
+
+
+    /**
+        @brief The Shell is the logical component of the console that displays output to the user and allows him to enter commands.
+
+        The Shell gathers output sent from OutputManager by inheriting from BaseWriter.
+        The output-lines are stored in the shell, so they can be displayed in a graphical
+        console. Additionally the Shell has an InputBuffer which is needed by the user to
+        enter commands.
+
+        Different graphical consoles build upon a Shell, for example InGameConsole and IOConsole.
+    */
+    class _CoreExport Shell : public BaseWriter, public DevModeListener
+    {
+        public:
+            /// Defines the type of a line of text in the Shell - some types depend on the output level, others are of internal use.
+            enum class LineType
+            {
+                DebugOutput     = debug_output,
+                Message         = message,
+                UserError       = user_error,
+                UserWarning     = user_warning,
+                UserStatus      = user_status,
+                UserInfo        = user_info,
+                InternalError   = internal_error,
+                InternalWarning = internal_warning,
+                InternalStatus  = internal_status,
+                InternalInfo    = internal_info,
+                Verbose         = verbose,
+                VerboseMore     = verbose_more,
+                VerboseUltra    = verbose_ultra,
+                Cout,
+                Input,
+                Command,
+                Result,
+                Hint
+            };
+
+            Shell(const std::string& consoleName = "", bool bScrollable = true);
+            ~Shell();
+
+            void setConfigValues();
+            void commandHistoryOffsetChanged();
+            void commandHistoryLengthChanged();
+
+            void registerListener(ShellListener* listener);
+            void unregisterListener(ShellListener* listener);
+
+            /// Returns the input buffer which is needed by the user to enter text into the shell.
+            inline InputBuffer* getInputBuffer()
+                { return this->inputBuffer_; }
+
+            void setCursorPosition(unsigned int cursor);
+            unsigned int getCursorPosition() const;
+
+            const std::string& getInput() const;
+
+            typedef std::list<std::pair<std::string, LineType>> LineList;
+            LineList::const_iterator getNewestLineIterator() const;
+            LineList::const_iterator getEndIterator() const;
+
+            void addOutput(const std::string& text, LineType type = LineType::DebugOutput);
+            void addLine(const std::string& line, LineType type = LineType::DebugOutput);
+            void clearOutput();
+
+            /// Returns the number of output-lines that are displayed in the shell.
+            inline unsigned int getNumLines() const
+                { return this->outputLines_.size(); }
+            /// Returns the line which is currently viewed if the user scrolls through the older output-lines in the shell.
+            inline unsigned int getScrollPosition() const
+                { return this->scrollPosition_; }
+
+            /// Returns the cache size that is actually used in CommandExecutor, but placed here for better readability of the config file.
+            static inline unsigned int getCacheSize()
+                { return Shell::cacheSize_s; }
+
+        private:
+            // non-copyable:
+            Shell(const Shell&) = delete;
+            Shell& operator=(const Shell&) = delete;
+
+            // DevModeListener
+            virtual void devModeChanged(bool value) override;
+
+            void addToHistory(const std::string& command);
+            const std::string& getFromHistory() const;
+            void clearInput();
+            // BaseWriter
+            virtual void printLine(const std::string& line, OutputLevel level) override;
+
+            void configureInputBuffer();
+
+            // InputBuffer callbacks
+            void inputChanged();
+            void execute();
+            void hintAndComplete();
+            void backspace();
+            void deleteChar();
+            void cursorRight();
+            void cursorLeft();
+            void cursorEnd();
+            void cursorHome();
+            void historyUp();
+            void historyDown();
+            void historySearchUp();
+            void historySearchDown();
+            void scrollUp();
+            void scrollDown();
+            void exit();
+
+            /// Iterates through all registered @ref ShellListener "shell listeners" and calls the function @a F.
+            template <void (ShellListener::*F)()>
+            void updateListeners()
+            {
+                for (std::list<ShellListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+                    ((*(it++))->*F)();
+            }
+
+            std::list<ShellListener*> listeners_;           ///< The registered shell listeners
+            InputBuffer*              inputBuffer_;         ///< The input buffer that is needed by the user to enter text
+            LineList                  outputLines_;         ///< A list of all output-lines that were displayed in the shell so far
+            LineList::const_iterator  scrollIterator_;      ///< An iterator to an entry of the list of output-lines, changes if the user scrolls through the output in the shell
+            unsigned int              scrollPosition_;      ///< The number of the line that is currently being referenced by scrollIterator_
+            unsigned int              historyPosition_;     ///< If the user scrolls through the history of entered commands (stored in commandHistory_), this contains the currently viewed history entry
+            const bool                bScrollable_;         ///< If true, the user can scroll through the output-lines
+
+            // Config values
+            unsigned int              maxHistoryLength_;    ///< The maximum number of saved commands
+            unsigned int              historyOffset_;       ///< The command history is a circular buffer, this variable defines the current write-offset
+            std::vector<std::string>  commandHistory_;      ///< The history of commands that were entered by the user
+            static unsigned int       cacheSize_s;          ///< The maximum cache size of the CommandExecutor - this is stored here for better readability of the config file and because CommandExecutor is not configurable
+    };
+}
+
+#endif /* _Shell_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/TclBind.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/TclBind.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/TclBind.cc	(revision 11817)
@@ -0,0 +1,250 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TclBind.h"
+
+#include <exception>
+#include <string>
+#include <cpptcl/cpptcl.h>
+
+#include "SpecialConfig.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "core/ApplicationPaths.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommandIncludes.h"
+#include "TclThreadManager.h"
+
+namespace orxonox
+{
+    SetConsoleCommand("tcl", &TclBind::tcl);
+    SetConsoleCommand("bgerror", &TclBind::bgerror).hide();
+
+    TclBind* TclBind::singletonPtr_s = nullptr;
+
+    /**
+        @brief Constructor: Initializes the Tcl-interpreter with a given data path.
+        @param datapath Path to the directory that contains the Orxonox-specific Tcl-files
+    */
+    TclBind::TclBind(const std::string& datapath)
+    {
+        this->interpreter_ = nullptr;
+        this->bSetTclDataPath_ = false;
+        this->setDataPath(datapath);
+    }
+
+    /**
+        @brief Destructor: Deletes the Tcl-interpreter.
+    */
+    TclBind::~TclBind()
+    {
+        if (this->interpreter_)
+            delete this->interpreter_;
+    }
+
+    /**
+        @brief Defines the path to the directory that contains the Orxonox-specific Tcl-files and initializes the Tcl-interpreter accordingly.
+    */
+    void TclBind::setDataPath(const std::string& datapath)
+    {
+        // String has POSIX slashes
+        this->tclDataPath_ = datapath + "tcl" + '/';
+        this->bSetTclDataPath_ = true;
+
+        this->initializeTclInterpreter();
+    }
+
+    /**
+        @brief Creates and initializes the Tcl-interpreter by registering all callbacks and defining some useful functions.
+    */
+    void TclBind::initializeTclInterpreter()
+    {
+        if (this->bSetTclDataPath_ && !this->interpreter_)
+        {
+            this->interpreter_ = this->createTclInterpreter();
+
+            this->interpreter_->def("::orxonox::query", TclBind::tcl_query, Tcl::variadic());
+            this->interpreter_->def("::orxonox::execute", TclBind::tcl_execute, Tcl::variadic());
+            this->interpreter_->def("::orxonox::crossquery", TclThreadManager::tcl_crossquery, Tcl::variadic());
+            this->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
+
+            try
+            {
+                this->interpreter_->def("query", TclBind::tcl_query, Tcl::variadic());
+                this->interpreter_->def("execute", TclBind::tcl_execute, Tcl::variadic());
+                this->interpreter_->eval("proc crossquery   {id args} { ::orxonox::crossquery 0 $id $args }");
+                this->interpreter_->eval("proc crossexecute {id args} { ::orxonox::crossexecute 0 $id $args }");
+                this->interpreter_->eval("proc running      {}        { return 1 }");
+                this->interpreter_->eval("set id 0");
+                this->interpreter_->eval("rename exit ::tcl::exit; proc exit {} { execute exit }");
+            }
+            catch (Tcl::tcl_error const &e)
+            {   orxout(internal_error, context::tcl) << "Tcl error while creating Tcl-interpreter: " << e.what() << endl;   }
+        }
+    }
+
+    /**
+        @brief Creates and initializes a new Tcl-interpreter and calls the Orxonox-specific
+        init.tcl script that defines some special functions which are required by Orxonox.
+    */
+    Tcl::interpreter* TclBind::createTclInterpreter()
+    {
+        Tcl::interpreter* interpreter = new Tcl::interpreter();
+        const std::string& libpath = TclBind::getTclLibraryPath();
+
+        try
+        {
+            if (!libpath.empty())
+                interpreter->eval("set tcl_library \"" + libpath + '"');
+
+            Tcl_Init(interpreter->get());
+
+            interpreter->eval("source \"" + TclBind::getInstance().tclDataPath_ + "/init.tcl\"");
+        }
+        catch (Tcl::tcl_error const &e)
+        {
+            orxout(internal_error, context::tcl) << "Tcl error while creating Tcl-interpreter: " << e.what() << endl;
+            orxout(user_error, context::tcl) << "Tcl isn't properly initialized. Orxonox might possibly not work like that." << endl;
+        }
+
+        return interpreter;
+    }
+
+    /**
+        @brief Returns the path to the Tcl-library (not the Orxonox-specific Tcl-files).
+    */
+    std::string TclBind::getTclLibraryPath()
+    {
+#ifdef DEPENDENCY_PACKAGE_ENABLE
+        if (ApplicationPaths::buildDirectoryRun())
+            return (std::string(specialConfig::dependencyLibraryDirectory) + "/tcl");
+        else
+            return (ApplicationPaths::getRootPathString() + specialConfig::defaultLibraryPath + "/tcl");
+#else
+        return "";
+#endif
+    }
+
+    /**
+        @brief Callback: Used to send an Orxonox-command from Tcl to the CommandExecutor and to send its result back to Tcl.
+    */
+    std::string TclBind::tcl_query(Tcl::object const &args)
+    {
+        orxout(verbose, context::commands) << "Tcl_query: " << args.get() << endl;
+        return TclBind::tcl_helper(args, true);
+    }
+
+    /**
+        @brief Callback: Used to send an Orxonox-command from Tcl to the CommandExecutor.
+    */
+    void TclBind::tcl_execute(Tcl::object const &args)
+    {
+        orxout(verbose, context::commands) << "Tcl_execute: " << args.get() << endl;
+        TclBind::tcl_helper(args, false);
+    }
+
+    /**
+        @brief Helper function, used by tcl_query() and tcl_execute().
+    */
+    std::string TclBind::tcl_helper(Tcl::object const &args, bool bQuery)
+    {
+        const std::string& command = stripEnclosingBraces(args.get());
+
+        int error;
+        std::string result;
+
+        CommandEvaluation evaluation = CommandExecutor::evaluate(command);
+
+        if (bQuery)
+            result = evaluation.query(&error).get<std::string>();
+        else
+            error = evaluation.execute();
+
+        if (error)
+        {
+            orxout(user_error) << "Can't execute command \"" << command << "\", " + CommandExecutor::getErrorDescription(error) + ". (TclBind)" << endl;
+            if (error == CommandExecutor::Inexistent)
+                orxout(user_info) << "Did you mean \"" << evaluation.getCommandSuggestion() << "\"?" << endl;
+        }
+
+        return result;
+    }
+
+    /**
+        @brief Console command, executes Tcl code. Can be used to bind Tcl-commands to a key, because native
+        Tcl-commands can not be evaluated and are thus not supported by the key-binder.
+    */
+    std::string TclBind::tcl(const std::string& tclcode)
+    {
+        if (TclBind::getInstance().interpreter_)
+        {
+            try
+            {
+                return TclBind::getInstance().interpreter_->eval("uplevel #0 " + tclcode);
+            }
+            catch (Tcl::tcl_error const &e)
+            {   orxout(user_error, context::tcl) << "Tcl error: " << e.what() << endl;   }
+        }
+
+        return "";
+    }
+
+    /**
+        @brief Console command and implementation of the Tcl-feature "bgerror" which is called if an error
+        occurred in the background of a Tcl-script.
+    */
+    void TclBind::bgerror(const std::string& error)
+    {
+        orxout(user_error, context::tcl) << "Tcl background error: " << stripEnclosingBraces(error) << endl;
+    }
+
+    /**
+        @brief Executes Tcl-code and returns the return-value.
+        @param tclcode A string that contains Tcl-code
+        @param error A pointer to an integer (or nullptr) that is used to write an error-code (see @ref CommandExecutorErrorCodes "CommandExecutor error codes")
+        @return Returns the return-value of the executed code (or an empty string if there's no return-value)
+    */
+    std::string TclBind::eval(const std::string& tclcode, int* error)
+    {
+        if (error)
+            *error = CommandExecutor::Success;
+
+        try
+        {
+            // execute the code
+            return TclBind::getInstance().interpreter_->eval(tclcode);
+        }
+        catch (Tcl::tcl_error const &e)
+        {   orxout(user_error, context::tcl) << "Tcl error: " << e.what() << endl;   }
+
+        if (error)
+            *error = CommandExecutor::Error;
+        return "";
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/TclBind.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/TclBind.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/TclBind.h	(revision 11817)
@@ -0,0 +1,140 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Tcl Tcl
+    @ingroup Command
+*/
+
+/**
+    @file
+    @ingroup Command Tcl
+    @brief Declaration of the TclBind class.
+
+    @anchor TclBindExample
+
+    orxonox::TclBind is a wrapper class for a Tcl interpreter. It is implemented as
+    singleton, so it can be accessed by everyone, but all share the same static
+    Tcl interpreter. If you need a Tcl interpreter at your own, see orxonox::TclThreadManager
+    for more information.
+
+    orxonox::TclBind is used by orxonox::CommandExecutor to execute Tcl commands. It can
+    also be used to execute Tcl commands from different sources, but note that they may
+    interfer with the ingame console if used improperly. By no means execute blocking
+    commands such as endless loops or the tcl command @c vwait. Use orxonox::TclThreadManager
+    and execute these commands in a multithreaded Tcl interpreter instead.
+
+    TclBind also defines different callback functions to return commands from the
+    Tcl interpreter back to Orxonox. Because of that it's possible to send a mixture
+    of Orxonox- and Tcl-commands to TclBind::eval() and still get the desired behavior.
+
+    Example:
+    @code
+    TclBind::eval("puts \"Hello World\"");                              // calls the tcl command "puts", prints "Hello World" to the console
+    TclBind::eval("log Hello World");                                   // calls the orxonox command "log", prints "Hello World" to the console
+
+    TclBind::eval("log [expr 1+1]");                                    // prints "2" to the console (which is the result of the tcl command "expr")
+
+    TclBind::eval("puts -nonewline Hello; log World");                  // prints "HelloWorld" to the console
+
+    TclBind::eval("for {set i 0} {$i < 10} {incr i} {log test: $i}");   // prints "test: 0", ..., "test: 9" to the console
+    @endcode
+
+    Note that @c puts and @c log behave slightly different, even though both can print
+    text to the console. @c puts needs quotation marks around multi-word output, while
+    @c log doesn't. @c puts on the other hand supports the flag @c -nonewline.
+
+    TclBind::eval() can also be used to obtain the return-value of a Tcl command:
+    @code
+    std::string result = TclBind::eval("expr 1+1");                     // result == "2"
+    @endcode
+*/
+
+#ifndef _TclBind_H__
+#define _TclBind_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+#include <string>
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    /**
+        @brief A wrapper class for a Tcl interpreter. Used to execute Tcl commands.
+
+        TclBind is used to execute Tcl commands, for example if sent to CommandExecutor::execute().
+        It also defines different callbacks for Tcl, which allows to combine Orxonox-console-commands
+        and Tcl-function without problems.
+
+        @see See @ref TclBindExample "TclBind.h" for more information and an example.
+    */
+    class _CoreExport TclBind : public Singleton<TclBind>
+    {
+        friend class Singleton<TclBind>;
+        public:
+            TclBind(const std::string& datapath);
+            ~TclBind();
+
+            static std::string tcl(const std::string& tclcode);
+            static void bgerror(const std::string& error);
+
+            void setDataPath(const std::string& datapath);
+            static std::string getTclLibraryPath();
+            /// Returns the path to the Orxonox-specific Tcl-files.
+            inline const std::string& getTclDataPath() const
+                { return this->tclDataPath_; }
+
+            void initializeTclInterpreter();
+            static Tcl::interpreter* createTclInterpreter();
+            /// Returns the Tcl-interpreter
+            inline Tcl::interpreter* getTclInterpreter() const
+                { return this->interpreter_; }
+
+            static std::string tcl_query(Tcl::object const &args);
+            static void tcl_execute(Tcl::object const &args);
+
+            static std::string eval(const std::string& tclcode, int* error = nullptr);
+
+        private:
+            // non-copyable:
+            TclBind(const TclBind&) = delete;
+            TclBind& operator=(const TclBind&) = delete;
+
+            static std::string tcl_helper(Tcl::object const &args, bool bQuery);
+
+            Tcl::interpreter* interpreter_;     ///< The wrapped Tcl interpreter
+            std::string tclDataPath_;           ///< The path to the directory that contains the Orxonox-specific Tcl-files
+            bool bSetTclDataPath_;              ///< True if tclDataPath_ was defined (after a call to setDataPath())
+
+            static TclBind* singletonPtr_s;     ///< The singleton pointer
+    };
+}
+
+#endif /* _TclBind_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadList.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadList.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadList.h	(revision 11817)
@@ -0,0 +1,272 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command Tcl
+    @brief Definition of TclThreadList.
+*/
+
+#ifndef _TclThreadList_H__
+#define _TclThreadList_H__
+
+#include "core/CorePrereqs.h"
+
+#include <list>
+
+#include <boost/thread/condition_variable.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/locks.hpp>
+
+namespace orxonox
+{
+    /**
+        @brief A thread-safe implementation of a message queue, used by TclThreadManager.
+    */
+    template <class T>
+    class TclThreadList
+    {
+        public:
+            void push_front(const T& value);
+            void push_back(const T& value);
+            template <class InputIterator> void insert(typename std::list<T>::iterator position, InputIterator begin, InputIterator end);
+
+            void wait_and_pop_front(T* value);
+            void wait_and_pop_back(T* value);
+            bool try_pop_front(T* value);
+            bool try_pop_back(T* value);
+            void clear();
+
+            size_t size() const;
+            bool empty() const;
+            bool is_in(const T& value) const;
+
+            /**
+                @brief Returns a reference to the list. Don't forget to lock the mutex (see @ref getMutex).
+            */
+            inline std::list<T>& getList()
+                { return this->list_; }
+
+            /**
+                @brief Returns a reference to the list. Don't forget to lock the mutex (see @ref getMutex).
+            */
+            inline const std::list<T>& getList() const
+                { return this->list_; }
+
+            /**
+                @brief Returns a reference to the mutex which might be useful if you want to iterate through the list (see @ref getList()).
+            */
+            inline boost::shared_mutex& getMutex() const
+                { return this->mutex_; }
+
+        private:
+            std::list<T>                  list_;        ///< A standard list for type T
+            mutable boost::shared_mutex   mutex_;       ///< A mutex to grant exclusive access to the list
+            boost::condition_variable_any condition_;   ///< A condition variable to wake threads waiting for the mutex to become ready
+    };
+
+    /**
+        @brief Pushes a new element to the front of the list. A unique_lock is needed.
+    */
+    template <class T>
+    void TclThreadList<T>::push_front(const T& value)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+        this->list_.push_front(value);
+        lock.unlock();                  // unlock the mutex...
+        this->condition_.notify_all();  // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
+    }
+
+    /**
+        @brief Pushes a new element to the back of the list. A unique_lock is needed.
+    */
+    template <class T>
+    void TclThreadList<T>::push_back(const T& value)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+        this->list_.push_back(value);
+        lock.unlock();                  // unlock the mutex...
+        this->condition_.notify_all();  // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
+    }
+
+    /**
+        @brief Inserts new elements into the list. A unique_lock is needed.
+    */
+    template <class T>
+    template <class InputIterator> void TclThreadList<T>::insert(typename std::list<T>::iterator position, InputIterator begin, InputIterator end)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+        this->list_.insert(position, begin, end);
+        lock.unlock();                  // unlock the mutex...
+        this->condition_.notify_all();  // ...then call notify_all to wake threads waiting in wait_and_pop_front/back
+    }
+
+    /**
+        @brief Waits until the list contains at least one element and then pops and returns the front element.
+        @param value The front value will be stored in the variable referenced by this pointer.
+    */
+    template <class T>
+    void TclThreadList<T>::wait_and_pop_front(T* value)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+
+        while (this->list_.empty())       // check if there's an element in the list
+            this->condition_.wait(lock);  // wait until the condition becomes true (a notification comes from push_front, push_back or insert
+
+        *value = this->list_.front();
+        this->list_.pop_front();
+    }
+
+    /**
+        @brief Waits until the list contains at least one element and then pops and returns the back element.
+        @param value The back value will be stored in the variable referenced by this pointer.
+    */
+    template <class T>
+    void TclThreadList<T>::wait_and_pop_back(T* value)
+    {
+        boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+
+        while (this->list_.empty())       // check if there's an element in the list
+            this->condition_.wait(lock);  // wait until the condition becomes true (a notification comes from push_front, push_back or insert
+
+        *value = this->list_.back();
+        this->list_.pop_back();
+    }
+
+    /**
+        @brief Pops and returns the front element if there's at least one element in the list.
+        @param value The front value will be stored in the variable referenced by this pointer.
+        @return Returns true if there was at least one element in the list (which got poped). If the list was empty, false is returned immediately.
+
+        Needs a unique_lock if there's an element to pop. If not, shared_lock is sufficient.
+    */
+    template <class T>
+    bool TclThreadList<T>::try_pop_front(T* value)
+    {
+        boost::upgrade_lock<boost::shared_mutex> lock(this->mutex_); // gain shared lock
+
+        if (this->list_.empty())
+        {
+            // No elements - return immediately
+            return false;
+        }
+        else
+        {
+            // At least one element - write it into the passed variable and pop it from the list
+            boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); // upgrade to unique lock to modify the list
+            *value = this->list_.front();
+            this->list_.pop_front();
+        }
+        return true;
+    }
+
+    /**
+        @brief Pops and returns the back element if there's at least one element in the list.
+        @param value The back value will be stored in the variable referenced by this pointer.
+        @return Returns true if there was at least one element in the list (which got poped). If the list was empty, false is returned immediately.
+
+        Needs a unique_lock if there's an element to pop. If not, shared_lock is sufficient.
+    */
+    template <class T>
+    bool TclThreadList<T>::try_pop_back(T* value)
+    {
+        boost::upgrade_lock<boost::shared_mutex> lock(this->mutex_); // gain shared lock
+
+        if (this->list_.empty())
+        {
+            // No elements - return immediately
+            return false;
+        }
+        else
+        {
+            // At least one element - write it into the passed variable and pop it from the list
+            boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(lock); // upgrade to unique lock to modify the list
+            *value = this->list_.back();
+            this->list_.pop_back();
+        }
+        return true;
+    }
+
+    /**
+        @brief Clears the list. A unique_lock is needed.
+    */
+    template <class T>
+    void TclThreadList<T>::clear()
+    {
+        boost::unique_lock<boost::shared_mutex> lock(this->mutex_);
+        this->list_.clear();
+    }
+
+    /**
+        @brief Returns the size of the list. A shared_lock is needed.
+
+        Warning: Don't change the list based on the result of size(). Use an atomic function instead. Other threads may change the list
+        beween your call to size() and your further actions, so be careful and use this function only if you really want nothing else than
+        just the size of the list.
+    */
+    template <class T>
+    size_t TclThreadList<T>::size() const
+    {
+        boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
+        return this->list_.size();
+    }
+
+    /**
+        @brief Returns true if the list is empty, false otherwise. A shared_lock is needed.
+
+        Warning: Don't change the list based on the result of empty(). Use an atomic function instead. Other threads may change the list
+        beween your call to empty() and your further actions, so be careful and use this function only if you really want nothing else than
+        just if the list is empty or not.
+    */
+    template <class T>
+    bool TclThreadList<T>::empty() const
+    {
+        boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
+        return this->list_.empty();
+    }
+
+    /**
+        @brief Returns true if a given element is in the list, false otherwise. A shared_lock is needed.
+
+        Warning: The result of this function might be wrong just one instruction after the call. Use this function just to get information
+        about a temporary snapshot and don't change the list based on the result of this function.
+    */
+    template <class T>
+    bool TclThreadList<T>::is_in(const T& value) const
+    {
+        boost::shared_lock<boost::shared_mutex> lock(this->mutex_);
+
+        for (const T& element : this->list_)
+            if (element == value)
+                return true;
+
+        return false;
+    }
+}
+
+#endif /* _TclThreadList_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadManager.cc	(revision 11817)
@@ -0,0 +1,677 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of TclThreadManager.
+*/
+
+#include "TclThreadManager.h"
+
+#include <functional>
+#include <boost/thread/thread.hpp>
+#include <boost/thread/locks.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <OgreTimer.h>
+#include <cpptcl/cpptcl.h>
+
+#include "util/Clock.h"
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "CommandExecutor.h"
+#include "ConsoleCommandIncludes.h"
+#include "TclBind.h"
+#include "TclThreadList.h"
+
+namespace orxonox
+{
+    const float TCLTHREADMANAGER_MAX_CPU_USAGE = 0.50f;
+
+    SetConsoleCommand("TclThreadManager", "create",  &TclThreadManager::create);
+    SetConsoleCommand("TclThreadManager", "destroy", &TclThreadManager::destroy).argumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand("TclThreadManager", "execute", &TclThreadManager::execute).argumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand("TclThreadManager", "query",   &TclThreadManager::query  ).argumentCompleter(0, autocompletion::tclthreads());
+    SetConsoleCommand("TclThreadManager", "source",  &TclThreadManager::source ).argumentCompleter(0, autocompletion::tclthreads());
+
+    /**
+        @brief A struct containing all information about a Tcl-interpreter
+    */
+    struct TclInterpreterBundle
+    {
+        TclInterpreterBundle()
+        {
+            this->lock_ = new boost::unique_lock<boost::mutex>(this->mutex_, boost::defer_lock);
+            this->bRunning_ = true;
+        }
+
+        ~TclInterpreterBundle()
+        {
+            delete this->lock_;
+        }
+
+        unsigned int                      id_;             ///< The id of the interpreter
+        Tcl::interpreter*                 interpreter_;    ///< The Tcl-interpreter
+        boost::mutex                      mutex_;          ///< A mutex to lock the interpreter while it's being used
+        boost::unique_lock<boost::mutex>* lock_;           ///< The corresponding lock for the mutex
+        TclThreadList<std::string>        queue_;          ///< The command queue for commands passed by execute(command)
+        TclThreadList<unsigned int>       queriers_;       ///< A list containing the id's of all other threads sending a query to this interpreter (to avoid circular queries and deadlocks)
+        bool                              bRunning_;       ///< This variable stays true until destroy() gets called
+    };
+
+    TclThreadManager* TclThreadManager::singletonPtr_s = nullptr;
+
+    /**
+        @brief Constructor
+        @param interpreter A pointer to the standard Tcl-interpreter (see @ref TclBind)
+    */
+    TclThreadManager::TclThreadManager(Tcl::interpreter* interpreter)
+    {
+        this->numInterpreterBundles_ = 0;
+
+        this->interpreterBundlesMutex_ = new boost::shared_mutex();
+        this->mainInterpreterMutex_ = new boost::mutex();
+        this->messageQueue_ = new TclThreadList<std::string>();
+
+        TclInterpreterBundle* newbundle = new TclInterpreterBundle();
+        newbundle->id_ = 0;
+        newbundle->interpreter_ = interpreter;
+        newbundle->lock_->lock();
+
+        {
+            boost::unique_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+            this->interpreterBundles_[0] = newbundle;
+        }
+    }
+
+    /**
+        @brief Destructor
+    */
+    TclThreadManager::~TclThreadManager()
+    {
+        delete this->interpreterBundles_[0];
+        delete this->interpreterBundlesMutex_;
+//        delete this->mainInterpreterMutex_; // <-- temporarily disabled to avoid crash if a thread is still actively querying
+        delete this->messageQueue_;
+    }
+
+    /**
+        @brief The "main loop" of the TclThreadManager. Creates new threads if needed and handles queries and queued commands for the main interpreter.
+    */
+    void TclThreadManager::preUpdate(const Clock& time)
+    {
+        // Get the bundle of the main interpreter (0)
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(0);
+        if (bundle)
+        {
+            // Unlock the mutex to allow other threads accessing the main interpreter
+            bundle->lock_->unlock();
+
+            // Lock the main interpreter mutex once to synchronize with threads that want to query the main interpreter
+            {
+                boost::unique_lock<boost::mutex> lock(*this->mainInterpreterMutex_);
+            }
+
+            // Lock the mutex again to gain exclusive access to the interpreter for the rest of the mainloop
+            bundle->lock_->lock();
+
+            // Execute commands in the queues of the threaded interpreters
+            {
+                boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+                for (const auto& mapEntry : this->interpreterBundles_)
+                {
+                    if (mapEntry.first == 0)
+                        continue; // We'll handle the default interpreter later (and without threads of course)
+
+                    TclInterpreterBundle* bundle = mapEntry.second;
+                    if (!bundle->queue_.empty())
+                    {
+                        // There are commands in the queue
+                        try
+                        {
+                            if (!bundle->lock_->owns_lock() && bundle->lock_->try_lock())
+                            {
+                                // We sucessfully obtained a lock for the interpreter
+                                std::string command;
+                                if (bundle->queue_.try_pop_front(&command))
+                                {
+                                    // Start a thread to execute the command
+                                    boost::thread(std::bind(&tclThread, bundle, command));
+                                }
+                                else
+                                {
+                                    // Somehow the queue become empty (maybe multiple consumers) - unlock the mutex
+                                    bundle->lock_->unlock();
+                                }
+                            }
+                        }
+                        catch (...)
+                        {
+                            // A lock error occurred - this is possible if the lock gets locked between !bundle->lock_->owns_lock() and bundle->lock_->try_lock()
+                            // This isn't too bad, just continue
+                        }
+                    }
+                }
+            }
+
+            // Execute commands in the message queue
+            if (!this->messageQueue_->empty())
+            {
+                std::string command;
+                while (true)
+                {
+                    // Pop the front value from the list (break the loop if there are no elements in the list)
+                    if (!this->messageQueue_->try_pop_front(&command))
+                        break;
+
+                    // Execute the command
+                    CommandExecutor::execute(command, false);
+                }
+            }
+
+            // Execute commands in the queue of the main interpreter
+            if (!bundle->queue_.empty())
+            {
+                // Calculate the time we have until we reach the maximal cpu usage
+                unsigned long maxtime = (unsigned long)(time.getDeltaTime() * 1000000 * TCLTHREADMANAGER_MAX_CPU_USAGE);
+
+                Ogre::Timer timer;
+                std::string command;
+
+                while (timer.getMicroseconds() < maxtime)
+                {
+                    // Pop the front value from the list (break the loop if there are no elements in the list)
+                    if (!bundle->queue_.try_pop_front(&command))
+                        break;
+
+                    // Execute the command
+                    CommandExecutor::execute(command, false);
+                }
+            }
+        }
+    }
+
+    /**
+        @brief Creates a new Tcl-interpreter.
+    */
+    unsigned int TclThreadManager::create()
+    {
+        TclThreadManager::getInstance().numInterpreterBundles_++;
+        TclThreadManager::createWithId(TclThreadManager::getInstance().numInterpreterBundles_);
+        orxout(user_info) << "Created new Tcl-interpreter with ID " << TclThreadManager::getInstance().numInterpreterBundles_ << endl;
+        return TclThreadManager::getInstance().numInterpreterBundles_;
+    }
+
+    /**
+        @brief Creates a new Tcl-interpreter with a given id.
+
+        Use with caution - if the id collides with an already existing interpreter, this call will fail.
+        This will also be a problem, if the auto-numbered interpreters (by using create()) reach an id
+        which was previously used in this function. Use high numbers to be safe.
+    */
+    Tcl::interpreter* TclThreadManager::createWithId(unsigned int id)
+    {
+        TclInterpreterBundle* newbundle = new TclInterpreterBundle();
+        newbundle->id_ = id;
+        newbundle->interpreter_ = TclBind::createTclInterpreter();
+
+        TclThreadManager::initialize(newbundle);
+
+        {
+            // Add the new bundle to the map
+            boost::unique_lock<boost::shared_mutex> lock(*TclThreadManager::getInstance().interpreterBundlesMutex_);
+            TclThreadManager::getInstance().interpreterBundles_[id] = newbundle;
+        }
+
+        return newbundle->interpreter_;
+    }
+
+    void TclThreadManager::initialize(TclInterpreterBundle* bundle)
+    {
+        const std::string& id_string = multi_cast<std::string>(bundle->id_);
+
+        // Initialize the new interpreter
+        try
+        {
+            // Define the functions which are implemented in C++
+            bundle->interpreter_->def("::orxonox::execute",      TclThreadManager::tcl_execute,      Tcl::variadic());
+            bundle->interpreter_->def("::orxonox::crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
+            bundle->interpreter_->def("::orxonox::query",        TclThreadManager::tcl_query,        Tcl::variadic());
+            bundle->interpreter_->def("::orxonox::crossquery",   TclThreadManager::tcl_crossquery,   Tcl::variadic());
+            bundle->interpreter_->def("::orxonox::running",      TclThreadManager::tcl_running);
+
+            // Create threadspecific shortcuts for the functions above
+            bundle->interpreter_->def("execute",      TclThreadManager::tcl_execute,      Tcl::variadic());
+            bundle->interpreter_->def("crossexecute", TclThreadManager::tcl_crossexecute, Tcl::variadic());
+            bundle->interpreter_->eval("proc query      {args}    { ::orxonox::query " + id_string + " $args }");
+            bundle->interpreter_->eval("proc crossquery {id args} { ::orxonox::crossquery " + id_string + " $id $args }");
+            bundle->interpreter_->eval("proc running    {}        { return [::orxonox::running " + id_string + "] }");
+
+            // Define a variable containing the thread id
+            bundle->interpreter_->eval("set id " + id_string);
+
+            // Use our own exit function to avoid shutting down the whole program instead of just the interpreter
+            bundle->interpreter_->eval("rename exit ::tcl::exit");
+            bundle->interpreter_->eval("proc exit {} { execute TclThreadManager destroy " + id_string + " }");
+
+            // Redefine some native functions
+            bundle->interpreter_->eval("rename while ::tcl::while");
+            bundle->interpreter_->eval("rename ::orxonox::while while");
+            bundle->interpreter_->eval("rename for ::tcl::for");
+            bundle->interpreter_->eval("rename ::orxonox::for for");
+        }
+        catch (const Tcl::tcl_error& e)
+        {
+            bundle->interpreter_ = nullptr;
+            orxout(user_error, context::tcl) << "Tcl error while creating Tcl-interpreter (" << id_string << "): " << e.what() << endl;
+        }
+    }
+
+    /**
+        @brief Stops and destroys a given Tcl-interpreter
+    */
+    void TclThreadManager::destroy(unsigned int id)
+    {
+        // TODO
+        // Not yet implemented
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id);
+        if (bundle)
+        {
+            bundle->bRunning_ = false;
+        }
+    }
+
+    /**
+        @brief Sends a command to the queue of a given Tcl-interpreter
+        @param target_id The id of the target interpreter
+        @param command The command to be sent
+    */
+    void TclThreadManager::execute(unsigned int target_id, const std::string& command)
+    {
+        TclThreadManager::getInstance()._execute(target_id, command);
+    }
+
+    /**
+        @brief This function can be called from Tcl to execute a console command.
+
+        Commands which shall be executed are put into a queue and processed as soon as the
+        main thread feels ready to do so. The queue may also be full which results in a temporary
+        suspension of the calling thread until the queue gets ready again.
+    */
+    void TclThreadManager::tcl_execute(const Tcl::object& args)
+    {
+        TclThreadManager::getInstance()._execute(0, stripEnclosingBraces(args.get()));
+    }
+
+    /**
+        @brief This function can be called from Tcl to send a command to the queue of any interpreter.
+        @param target_id The id of the target thread
+        @param args Contains the content of the command
+    */
+    void TclThreadManager::tcl_crossexecute(int target_id, const Tcl::object& args)
+    {
+        TclThreadManager::getInstance()._execute(static_cast<unsigned int>(target_id), stripEnclosingBraces(args.get()));
+    }
+
+    /**
+        @brief Sends a command to the queue of a given Tcl-interpreter
+        @param target_id The id of the target interpreter
+        @param command The command to be sent
+    */
+    void TclThreadManager::_execute(unsigned int target_id, const std::string& command)
+    {
+        TclInterpreterBundle* bundle = this->getInterpreterBundle(target_id);
+        if (bundle)
+            bundle->queue_.push_back(command);
+    }
+
+
+    /**
+        @brief Sends a query to a given Tcl-interpreter and waits for the result
+        @param target_id The id of the target interpreter
+        @param command The command to be sent
+        @return The result of the command
+    */
+    std::string TclThreadManager::query(unsigned int target_id, const std::string& command)
+    {
+        return TclThreadManager::getInstance()._query(0, target_id, command);
+    }
+
+    /**
+        @brief This function can be called from Tcl to send a query to the main thread.
+        @param source_id The id of the calling thread
+        @param args Contains the content of the query
+
+        A query waits for the result of the command. This means, the calling thread will be blocked until
+        the main thread answers the query. In return, the main thread sends the result of the console
+        command back to Tcl.
+    */
+    std::string TclThreadManager::tcl_query(int source_id, const Tcl::object& args)
+    {
+        return TclThreadManager::getInstance()._query(static_cast<unsigned int>(source_id), 0, stripEnclosingBraces(args.get()), true);
+    }
+
+    /**
+        @brief This function can be called from Tcl to send a query to another thread.
+        @param source_id The id of the calling thread
+        @param target_id The id of the target thread
+        @param args Contains the content of the query
+    */
+    std::string TclThreadManager::tcl_crossquery(int source_id, int target_id, const Tcl::object& args)
+    {
+        return TclThreadManager::getInstance()._query(static_cast<unsigned int>(source_id), static_cast<unsigned int>(target_id), stripEnclosingBraces(args.get()));
+    }
+
+    /**
+        @brief This function performs a query to any Tcl interpreter
+        @param source_id The id of the calling thread
+        @param target_id The id of the target thread
+        @param command The command to send as a query
+        @param bUseCommandExecutor Only used if the target_id is 0 (which references the main interpreter). In this case it means if the command should be passed to the CommandExecutor (true) or to the main Tcl interpreter (false). This is true when called by tcl_query() and false when called by tcl_crossquery().
+    */
+    std::string TclThreadManager::_query(unsigned int source_id, unsigned int target_id, const std::string& command, bool bUseCommandExecutor)
+    {
+        TclInterpreterBundle* source_bundle = this->getInterpreterBundle(source_id);
+        TclInterpreterBundle* target_bundle = this->getInterpreterBundle(target_id);
+        std::string output;
+
+        if (source_bundle && target_bundle)
+        {
+            // At this point we assume the mutex of source_bundle to be locked (because it's executing this query right now an waits for the return value)
+            // We can safely use it's querier list (because there's no other place in the code using the list except this query - and the interpreter can't start more than one query)
+
+            if ((source_bundle->id_ == target_bundle->id_) || source_bundle->queriers_.is_in(target_bundle->id_))
+            {
+                // This query would lead to a deadlock - return with an error
+                TclThreadManager::error("Circular query (" + this->dumpList(source_bundle->queriers_.getList()) + ' ' + multi_cast<std::string>(source_bundle->id_)
+                            + " -> " + multi_cast<std::string>(target_bundle->id_)
+                            + "), couldn't query Tcl-interpreter with ID " + multi_cast<std::string>(target_bundle->id_)
+                            + " from other interpreter with ID " + multi_cast<std::string>(source_bundle->id_) + '.');
+            }
+            else
+            {
+                boost::unique_lock<boost::mutex> lock(target_bundle->mutex_, boost::try_to_lock);
+                boost::unique_lock<boost::mutex> mainlock(*this->mainInterpreterMutex_, boost::defer_lock);
+
+                if (!lock.owns_lock() && source_bundle->id_ != 0)
+                {
+                    // We couldn't obtain the try_lock immediately and we're not the main interpreter - wait until the lock becomes possible (note: the main interpreter won't wait and instead returns an error - see below)
+                    if (target_bundle->id_ == 0)
+                    {
+                        // We're querying the main interpreter - use the main interpreter mutex to synchronize
+                        mainlock.lock();
+                        lock.lock();
+                    }
+                    else
+                    {
+                        // We're querying a threaded interpreter - no synchronization needed
+                        lock.lock();
+                    }
+                }
+
+                if (lock.owns_lock())
+                {
+                    // Now the mutex of target_bundle is also locked an we can update the querier list
+                    target_bundle->queriers_.insert(target_bundle->queriers_.getList().begin(), source_bundle->queriers_.getList().begin(), source_bundle->queriers_.getList().end());
+                    target_bundle->queriers_.push_back(source_bundle->id_);
+
+                    // Perform the query (note: this happens in the main thread because we need the returnvalue)
+                    if (target_bundle->id_ == 0 && bUseCommandExecutor)
+                    {
+                        // It's a query to the CommandExecutor
+                        TclThreadManager::debug("TclThread_query -> CE: " + command);
+                        int error;
+                        output = CommandExecutor::query(command, &error, false);
+                        if (error)
+                            TclThreadManager::error("Can't execute command \"" + command + "\", " + CommandExecutor::getErrorDescription(error) + ". (TclThreadManager)");
+                    }
+                    else
+                    {
+                        // It's a query to a Tcl interpreter
+                        TclThreadManager::debug("TclThread_query: " + command);
+
+                        output = TclThreadManager::eval(target_bundle, command, "query");
+                    }
+
+                    // Clear the queriers list of the target
+                    target_bundle->queriers_.clear();
+
+                    // Unlock the mutex of the target_bundle
+                    lock.unlock();
+
+                    // Finally unlock the main interpreter lock if necessary
+                    if (mainlock.owns_lock())
+                        mainlock.unlock();
+                }
+                else
+                {
+                    // This happens if the main thread tries to query a busy interpreter
+                    // To avoid a lock of the main thread, we simply don't proceed with the query in this case
+                    TclThreadManager::error("Couldn't query Tcl-interpreter with ID " + multi_cast<std::string>(target_bundle->id_) + ", interpreter is busy right now.");
+                }
+            }
+
+        }
+
+        return output;
+    }
+
+    /**
+        @brief Creates a non-interactive Tcl-interpreter which executes a file.
+    */
+    void TclThreadManager::source(const std::string& file)
+    {
+        boost::thread(std::bind(&sourceThread, file));
+    }
+
+    /**
+        @brief This function can be called from Tcl to ask if the thread is still suposed to be running.
+        @param id The id of the thread in question
+    */
+    bool TclThreadManager::tcl_running(int id)
+    {
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(static_cast<unsigned int>(id));
+        if (bundle)
+            return bundle->bRunning_;
+        else
+            return false;
+    }
+
+    /**
+        @brief Returns the interpreter bundle with the given id.
+        @param id The id of the interpreter
+        @return The interpreter or 0 if the id doesn't exist
+    */
+    TclInterpreterBundle* TclThreadManager::getInterpreterBundle(unsigned int id)
+    {
+        boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+
+        std::map<unsigned int, TclInterpreterBundle*>::const_iterator it = this->interpreterBundles_.find(id);
+        if (it != this->interpreterBundles_.end())
+        {
+            return it->second;
+        }
+        else
+        {
+            TclThreadManager::error("No Tcl-interpreter with ID " + multi_cast<std::string>(id) + " existing.");
+            return nullptr;
+        }
+    }
+
+    /**
+        @brief Returns a string containing all elements of a unsigned-integer-list separated by spaces.
+    */
+    std::string TclThreadManager::dumpList(const std::list<unsigned int>& list)
+    {
+        std::string output;
+        for (std::list<unsigned int>::const_iterator it = list.begin(); it != list.end(); ++it)
+        {
+            if (it != list.begin())
+                output += ' ';
+
+            output += multi_cast<std::string>(*it);
+        }
+        return output;
+    }
+
+    /**
+        @brief Returns a list with the numbers of all existing Tcl-interpreters.
+
+        This function is used by the auto completion function.
+    */
+    std::list<unsigned int> TclThreadManager::getThreadList() const
+    {
+        boost::shared_lock<boost::shared_mutex> lock(*this->interpreterBundlesMutex_);
+
+        std::list<unsigned int> threads;
+        for (const auto& mapEntry : this->interpreterBundles_)
+            if (mapEntry.first > 0 && mapEntry.first <= this->numInterpreterBundles_) // only list autonumbered interpreters (created with create()) - exclude the default interpreter 0 and all manually numbered interpreters)
+                threads.push_back(mapEntry.first);
+        return threads;
+    }
+
+    /**
+        @brief A helper function to print errors in a thread safe manner.
+    */
+    void TclThreadManager::error(const std::string& error)
+    {
+        TclThreadManager::getInstance().messageQueue_->push_back("error " + error);
+    }
+
+    /**
+        @brief A helper function to print debug information in a thread safe manner.
+    */
+    void TclThreadManager::debug(const std::string& error)
+    {
+        TclThreadManager::getInstance().messageQueue_->push_back("debug " + error);
+    }
+
+    /**
+        @brief Evaluates a Tcl command without throwing exceptions (which may rise problems on certain machines).
+        @return The Tcl return value
+
+        Errors are reported through the @ref error function.
+    */
+    std::string TclThreadManager::eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action)
+    {
+        Tcl_Interp* interpreter = bundle->interpreter_->get();
+        int cc = Tcl_Eval(interpreter, command.c_str());
+
+        Tcl::details::result result(interpreter);
+
+        if (cc != TCL_OK)
+        {
+            TclThreadManager::error("Tcl error (" + action + ", ID " + multi_cast<std::string>(bundle->id_) + "): " + static_cast<std::string>(result));
+            return "";
+        }
+        else
+        {
+            return result;
+        }
+    }
+
+    ////////////////
+    // The Thread //
+    ////////////////
+
+    /**
+        @brief The main function of the thread. Executes a Tcl command.
+        @param bundle The interpreter bundle containing all necessary variables
+        @param command the Command to execute
+    */
+    void tclThread(TclInterpreterBundle* bundle, const std::string& command)
+    {
+        TclThreadManager::debug("TclThread_execute: " + command);
+
+        TclThreadManager::eval(bundle, command, "execute");
+
+        bundle->lock_->unlock();
+    }
+
+    /**
+        @brief The main function of a non-interactive source thread. Executes the file.
+        @param file The name of the file that should be executed by the non-interactive interpreter.
+    */
+    void sourceThread(const std::string& file)
+    {
+        TclThreadManager::debug("TclThread_source: " + file);
+
+        // Prepare the command-line arguments
+        const int argc = 2;
+        char* argv[argc];
+        argv[0] = const_cast<char*>("tclthread");
+        argv[1] = const_cast<char*>(file.c_str());
+
+        // Start the Tcl-command Tcl_Main with the Tcl_OrxonoxAppInit hook
+        Tcl_Main(argc, argv, Tcl_OrxonoxAppInit);
+
+//        Tcl::object object(file);
+//        int cc = Tcl_FSEvalFile(bundle->interpreter_->get(), object.get_object());
+//        Tcl::details::result result(bundle->interpreter_->get());
+//        if (cc != TCL_OK)
+//            TclThreadManager::error("Tcl error (source, ID " + getConvertedValue<unsigned int, std::string>(bundle->id_) + "): " + static_cast<std::string>(result));
+//
+//        // Unlock the mutex
+//        bundle->lock_->unlock();
+    }
+
+    /**
+        @brief A tcl-init hook to inject the non-interactive Tcl-interpreter into the TclThreadManager.
+    */
+    int Tcl_OrxonoxAppInit(Tcl_Interp* interp)
+    {
+        // Create a new interpreter bundle
+        unsigned int id = TclThreadManager::create();
+        TclInterpreterBundle* bundle = TclThreadManager::getInstance().getInterpreterBundle(id);
+
+        // Replace the default interpreter in the bundle with the non-interactive one (passed as an argument to this function)
+        if (bundle->interpreter_)
+            delete bundle->interpreter_;
+        bundle->interpreter_ = new Tcl::interpreter(interp, true);
+
+        // Initialize the non-interactive interpreter (like in @ref TclBind::createTclInterpreter but exception safe)
+        const std::string& libpath = TclBind::getTclLibraryPath();
+        if (!libpath.empty())
+            TclThreadManager::eval(bundle, "set tcl_library \"" + libpath + '"', "source");
+        int cc = Tcl_Init(interp);
+        TclThreadManager::eval(bundle, "source \"" + TclBind::getInstance().getTclDataPath() + "/init.tcl\"", "source");
+
+        // Initialize the non-interactive interpreter also with the thread-specific stuff
+        TclThreadManager::initialize(bundle);
+
+        // Lock the mutex (this will be locked until the thread finishes - no chance to interact with the interpreter)
+        bundle->lock_->lock();
+
+        // Return to Tcl_Main
+        if (!bundle->interpreter_)
+            return TCL_ERROR;
+        else
+            return cc;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/command/TclThreadManager.h	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Command Tcl
+    @brief Declaration of TclThreadManager, used to create multithreaded Tcl interpreters.
+*/
+
+#ifndef _TclThreadManager_H__
+#define _TclThreadManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+#include <list>
+#include <map>
+#include <string>
+
+#include "util/Singleton.h"
+
+struct Tcl_Interp;
+
+namespace orxonox
+{
+    class _CoreExport TclThreadManager : public Singleton<TclThreadManager>
+    {
+        friend class Singleton<TclThreadManager>;
+        friend class TclBind;
+        friend _CoreExport void tclThread(TclInterpreterBundle* bundle, const std::string& command);
+        friend _CoreExport void sourceThread(const std::string& file);
+        friend _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp);
+
+        public:
+            TclThreadManager(Tcl::interpreter* interpreter);
+            virtual ~TclThreadManager();
+
+            static unsigned int      create();
+            static Tcl::interpreter* createWithId(unsigned int id);
+            static void              destroy(unsigned int id);
+            static void              execute(unsigned int target_id, const std::string& command);
+            static std::string       query(unsigned int target_id, const std::string& command);
+            static void              source(const std::string& file);
+
+            static void error(const std::string& error);
+            static void debug(const std::string& error);
+
+            void preUpdate(const Clock& time);
+
+            std::list<unsigned int> getThreadList() const;
+
+        private:
+            static void tcl_execute(const Tcl::object& args);
+            static void tcl_crossexecute(int target_id, const Tcl::object& args);
+            static std::string tcl_query(int source_id, const Tcl::object& args);
+            static std::string tcl_crossquery(int source_id, int target_id, const Tcl::object& args);
+            static bool tcl_running(int id);
+
+            void _execute(unsigned int target_id, const std::string& command);
+            std::string _query(unsigned int source_id, unsigned int target_id, const std::string& command, bool bUseCommandExecutor = false);
+
+            TclInterpreterBundle* getInterpreterBundle(unsigned int id);
+            std::string dumpList(const std::list<unsigned int>& list);
+
+            static void initialize(TclInterpreterBundle* bundle);
+            static std::string eval(TclInterpreterBundle* bundle, const std::string& command, const std::string& action);
+
+            static TclThreadManager* singletonPtr_s;                            ///< Singleton pointer
+
+            unsigned int numInterpreterBundles_;                                ///< Number of created Tcl-interpreters (only used for auto-numbered interpreters, not affected by @ref createWithId)
+            std::map<unsigned int, TclInterpreterBundle*> interpreterBundles_;  ///< A map containing all Tcl-interpreters
+            boost::shared_mutex* interpreterBundlesMutex_;                      ///< A mutex used to synchronize threads when accessing @ref interpreterBundles_
+            TclThreadList<std::string>* messageQueue_;                          ///< A queue to pass messages from Tcl-threads to the main thread
+            boost::mutex* mainInterpreterMutex_;                                ///< A mutex to synchronize queries to the main interpreter
+    };
+
+    _CoreExport void tclThread(TclInterpreterBundle* bundle, const std::string& command);
+    _CoreExport void sourceThread(const std::string& file);
+    _CoreExport int Tcl_OrxonoxAppInit(Tcl_Interp* interp);
+}
+
+#endif /* _TclThreadManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/commandline/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/commandline/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/commandline/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,3 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  CommandLineParser.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineIncludes.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup CmdArgs Commandline arguments
+    @ingroup Config
+*/
+
+/**
+    @file
+    @ingroup Config CmdArgs
+    @brief Declaration of CommandLineParser and CommandLineArgument, definition of the SetCommandLineArgument() macros.
+*/
+
+#ifndef _CommandLineIncludes_H__
+#define _CommandLineIncludes_H__
+
+#include "core/CorePrereqs.h"
+
+#include "CommandLineParser.h"
+#include "core/module/StaticallyInitializedInstance.h"
+
+#define SetCommandLineArgument(name, defaultValue) \
+    orxonox::CommandLineArgument& CmdArgumentDummyBoolVar##name \
+        = (new orxonox::SI_CLA(new orxonox::CommandLineArgument(#name, defaultValue)))->getArgument()
+#define SetCommandLineSwitch(name) \
+    SetCommandLineArgument(name, false)
+
+namespace orxonox
+{
+    class _CoreExport StaticallyInitializedCommandLineArgument : public StaticallyInitializedInstance
+    {
+        public:
+            StaticallyInitializedCommandLineArgument(CommandLineArgument* argument)
+                : StaticallyInitializedInstance(StaticInitialization::COMMAND_LINE_ARGUMENT)
+                , argument_(argument)
+            {}
+            ~StaticallyInitializedCommandLineArgument() { delete argument_; }
+
+            virtual void load() override
+                { CommandLineParser::addArgument(this->argument_); }
+
+            virtual void unload() override
+                { CommandLineParser::removeArgument(this->argument_); }
+
+            inline CommandLineArgument& getArgument()
+                { return *this->argument_; }
+
+        private:
+            CommandLineArgument* argument_;
+    };
+
+    typedef StaticallyInitializedCommandLineArgument SI_CLA;
+}
+
+#endif /* _CommandLineIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineParser.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineParser.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineParser.cc	(revision 11817)
@@ -0,0 +1,334 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CommandLineParser.h"
+
+#include <algorithm>
+#include <sstream>
+
+#include "util/Convert.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "util/SubString.h"
+
+namespace orxonox
+{
+    CommandLineParser* CommandLineParser::singletonPtr_s = nullptr;
+
+    /**
+    @brief
+        Parses a value string for a command line argument.
+        It simply uses convertValue(Output, Input) to do that.
+        Bools are treated specially. That is necessary
+        so that you can have simple command line switches.
+    */
+    void CommandLineArgument::parse(const std::string& value)
+    {
+        if (value_.isType<bool>())
+        {
+            // simulate command line switch
+            bool temp;
+            if (convertValue(&temp, value))
+            {
+                this->bHasDefaultValue_ = false;
+                this->value_ = temp;
+            }
+            else if (value.empty())
+            {
+                this->bHasDefaultValue_ = false;
+                this->value_ = true;
+            }
+            else
+                ThrowException(Argument, "Could not read command line argument '" + getName() + "'.");
+        }
+        else
+        {
+            if (!value_.set(value))
+            {
+                value_.set(defaultValue_);
+                ThrowException(Argument, "Could not read command line argument '" + getName() + "'.");
+            }
+            else
+                this->bHasDefaultValue_ = false;
+        }
+    }
+
+
+    /**
+    @brief
+        Destructor destroys all CommandLineArguments with it.
+    */
+    CommandLineParser::~CommandLineParser()
+    {
+    }
+
+    /** Parses the command line string for arguments and stores these.
+    @note
+        The reason that you have to provide the string to be parsed as
+        space separated list is because of argc and argv. If you only have
+        a whole string, simply use getAllStrings() of SubString.
+    @param cmdLine
+        Command line string WITHOUT the execution path.
+    */
+    void CommandLineParser::_parse(const std::string& cmdLine)
+    {
+        std::vector<std::string> arguments;
+        SubString tokens(cmdLine, " ", " ", false, '\\', true, '"', true, '\0', '\0', false);
+        for (unsigned i = 0; i < tokens.size(); ++i)
+            arguments.push_back(tokens[i]);
+
+        try
+        {
+            // why this? See bFirstTimeParse_ declaration.
+            if (bFirstTimeParse_)
+            {
+                // first shove all the shortcuts in a map
+                for (const auto& mapEntry : cmdLineArgs_)
+                {
+                    OrxAssert(cmdLineArgsShortcut_.find(mapEntry.second->getShortcut()) == cmdLineArgsShortcut_.end(),
+                        "Cannot have two command line shortcut with the same name.");
+                    if (!mapEntry.second->getShortcut().empty())
+                        cmdLineArgsShortcut_[mapEntry.second->getShortcut()] = mapEntry.second;
+                }
+                bFirstTimeParse_ = false;
+            }
+
+            std::string name;
+            std::string shortcut;
+            std::string value;
+            for (const std::string& argument : arguments)
+            {
+                if (argument.size() != 0)
+                {
+                    // sure not ""
+                    if (argument[0] == '-')
+                    {
+                        // start with "-"
+                        if (argument.size() == 1)
+                        {
+                            // argument[i] is "-", probably a minus sign
+                            value += "- ";
+                        }
+                        else if (argument[1] <= 57 && argument[1] >= 48)
+                        {
+                            // negative number as a value
+                            value += argument + ' ';
+                        }
+                        else
+                        {
+                            // can be shortcut or full name argument
+
+                            // save old data first
+                            value = removeTrailingWhitespaces(value);
+                            if (!name.empty())
+                            {
+                                checkFullArgument(name, value);
+                                name.clear();
+                                assert(shortcut.empty());
+                            }
+                            else if (!shortcut.empty())
+                            {
+                                checkShortcut(shortcut, value);
+                                shortcut.clear();
+                                assert(name.empty());
+                            }
+
+                            if (argument[1] == '-')
+                            {
+                                // full name argument with "--name"
+                                name = argument.substr(2);
+                            }
+                            else
+                            {
+                                // shortcut with "-s"
+                                shortcut = argument.substr(1);
+                            }
+
+                            // reset value string
+                            value.clear();
+                        }
+                    }
+                    else
+                    {
+                        // value string
+
+                        if (name.empty() && shortcut.empty())
+                        {
+                            ThrowException(Argument, "Expected \"-\" or \"-\" in command line arguments.\n");
+                        }
+
+                        // Concatenate strings as long as there's no new argument by "-" or "--"
+                        value += argument + ' ';
+                    }
+                }
+            }
+
+            // parse last argument
+            value = removeTrailingWhitespaces(value);
+            if (!name.empty())
+            {
+                checkFullArgument(name, value);
+                assert(shortcut.empty());
+            }
+            else if (!shortcut.empty())
+            {
+                checkShortcut(shortcut, value);
+                assert(name.empty());
+            }
+        }
+        catch (const ArgumentException& ex)
+        {
+            orxout(user_error) << "Could not parse command line: " << ex.what() << endl;
+            orxout(user_error) << CommandLineParser::getUsageInformation() << endl;
+            throw GeneralException("");
+        }
+    }
+
+    /**
+    @brief
+        Parses an argument based on its full name.
+    @param name
+        Full name of the argument
+    @param value
+        String containing the value
+    */
+    void CommandLineParser::checkFullArgument(const std::string& name, const std::string& value)
+    {
+        std::map<std::string, CommandLineArgument*>::const_iterator it = cmdLineArgs_.find(name);
+        if (it == cmdLineArgs_.end())
+            ThrowException(Argument, "Command line argument '" + name + "' does not exist.");
+
+        it->second->parse(value);
+    }
+
+    /**
+    @brief
+        Parses an argument based on its shortcut.
+    @param shortcut
+        Shortcut to the argument
+    @param value
+        String containing the value
+    */
+    void CommandLineParser::checkShortcut(const std::string& shortcut, const std::string& value)
+    {
+        std::map<std::string, CommandLineArgument*>::const_iterator it = cmdLineArgsShortcut_.find(shortcut);
+        if (it == cmdLineArgsShortcut_.end())
+            ThrowException(Argument, "Command line shortcut '" + shortcut + "' does not exist.");
+
+        it->second->parse(value);
+    }
+
+    std::string CommandLineParser::getUsageInformation()
+    {
+        CommandLineParser& inst = getInstance();
+        std::ostringstream infoStr;
+
+        // determine maximum name size
+        size_t maxNameSize = 0;
+        for (const auto& mapEntry : inst.cmdLineArgs_)
+        {
+            maxNameSize = std::max(mapEntry.second->getName().size(), maxNameSize);
+        }
+
+        infoStr << endl;
+        infoStr << "Usage: orxonox [options]" << endl;
+        infoStr << "Available options:" << endl;
+
+        for (const auto& mapEntry : inst.cmdLineArgs_)
+        {
+            if (!mapEntry.second->getShortcut().empty())
+                infoStr << " [-" << mapEntry.second->getShortcut() << "] ";
+            else
+                infoStr << "      ";
+            infoStr << "--" << mapEntry.second->getName() << ' ';
+            if (mapEntry.second->getValue().isType<bool>())
+                infoStr << "    ";
+            else
+                infoStr << "ARG ";
+            // fill with the necessary amount of blanks
+            infoStr << std::string(maxNameSize - mapEntry.second->getName().size(), ' ');
+            infoStr << ": " << mapEntry.second->getInformation();
+            infoStr << endl;
+        }
+        return infoStr.str();
+    }
+
+    void CommandLineParser::generateDoc(std::ofstream& file)
+    {
+        file << "/** @page cmdargspage Command Line Arguments Reference" << endl;
+        file << "    @verbatim"; /*no endl*/
+        file << getUsageInformation(); /*no endl*/
+        file << "    @endverbatim" << endl;
+        file << "*/" << endl;
+    }
+
+    /**
+    @brief
+        Retrieves a CommandLineArgument.
+        The method throws an exception if 'name' was not found or the value could not be converted.
+    @note
+        You should of course not call this method before the command line has been parsed.
+    */
+    const CommandLineArgument* CommandLineParser::getArgument(const std::string& name)
+    {
+        std::map<std::string, CommandLineArgument*>::const_iterator it = getInstance().cmdLineArgs_.find(name);
+        if (it == getInstance().cmdLineArgs_.end())
+        {
+            ThrowException(Argument, "Could find command line argument '" + name + "'.");
+        }
+        else
+        {
+            return it->second;
+        }
+    }
+
+    /**
+    @brief
+        Adds a new CommandLineArgument to the internal map.
+        Note that only such arguments are actually valid.
+    */
+    void CommandLineParser::addArgument(CommandLineArgument* argument)
+    {
+        OrxAssert(!getInstance().existsArgument(argument->getName()),
+            "Cannot add a command line argument with name '" + argument->getName() + "' twice.");
+        OrxAssert(!argument->getDefaultValue().isType<bool>() || argument->getDefaultValue().get<bool>() != true,
+               "Boolean command line arguments with positive default values are not supported." << endl
+            << "Please use SetCommandLineSwitch and adjust your argument: " << argument->getName());
+
+        getInstance().cmdLineArgs_[argument->getName()] = argument;
+    }
+
+    /**
+     * @brief Removes a CommandLineArgument from the internal map.
+     */
+    void CommandLineParser::removeArgument(CommandLineArgument* argument)
+    {
+        getInstance().cmdLineArgs_.erase(argument->getName());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineParser.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineParser.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/commandline/CommandLineParser.h	(revision 11817)
@@ -0,0 +1,196 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config CmdArgs
+    @brief Declaration of CommandLineParser and CommandLineArgument, definition of the SetCommandLineArgument() macros.
+*/
+
+#ifndef _CommandLine_H__
+#define _CommandLine_H__
+
+#include "core/CorePrereqs.h"
+
+#include <fstream>
+#include <map>
+#include "util/OrxAssert.h"
+#include "util/MultiType.h"
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Container class for a command line argument of any type supported by MultiType.
+
+        Whenever you want to have an option specified by a command line switch,
+        you need to first define it with SetCommandLineArgument(name, defaultValue).
+        It is then added to a map and possibly changed when the command line is being parsed.
+        If the option was not given, you can detect this by asking hasDefaultValue().
+
+        There is a possibility to define a short cut so you can write "-p 20" instead of "--port 20".
+        Note the difference between "-" and "--"!
+        Also, there is no restriction to the number of strings you add after --name.
+        So "--startVector {2, 4, 5}" is perfectly legal.
+
+        Retrieving an argument is possible with the getCommandLineArgument function of the
+        CommandLineParser class. It is a Singleton, but the public interface is static.
+    */
+    class _CoreExport CommandLineArgument
+    {
+        friend class CommandLineParser;
+
+    public:
+        //! Constructor initialises both value_ and defaultValue_ with defaultValue.
+        CommandLineArgument(const std::string& name, const MultiType& defaultValue)
+            : bHasDefaultValue_(true)
+            , name_(name)
+            , value_(defaultValue)
+            , defaultValue_(defaultValue)
+        { }
+        ~CommandLineArgument() { }
+
+        //! Tells whether the value has been changed by the command line.
+        bool hasDefaultValue() const { return bHasDefaultValue_; }
+        //! Returns the name of the argument.
+        const std::string& getName() const { return name_; }
+
+        //! Returns the shortcut (example: "-p 22" for "--port 22") of the argument.
+        //! Evaluates to "" if there is none.
+        const std::string& getShortcut() const { return shortcut_; }
+        //! Sets the shortcut for the argument
+        CommandLineArgument& shortcut(const std::string& shortcut)
+        { this->shortcut_ = shortcut; return *this; }
+
+        //! Returns the usage information
+        const std::string& getInformation() const { return this->usageInformation_; }
+        //! Sets the option information when displaying orxonox usage.
+        CommandLineArgument& information(const std::string& usage)
+        { this->usageInformation_ = usage; return *this; }
+
+        //! Returns the actual value of the argument. Can be equal to default value.
+        const MultiType& getValue() const { return value_; }
+        //! Returns the given default value as type T.
+        const MultiType& getDefaultValue() const { return defaultValue_; }
+
+    private:
+        // non-copyable:
+        CommandLineArgument(const CommandLineArgument&) = delete;
+        CommandLineArgument& operator=(const CommandLineArgument&) = delete;
+
+        //! Parses the value string of a command line argument.
+        void parse(const std::string& value);
+
+        //! Tells whether the value has been changed by the command line.
+        bool bHasDefaultValue_;
+
+    private:
+        std::string name_;             //!< Name of the argument
+        std::string shortcut_;         //!< Shortcut of the argument. @see getShortcut().
+        std::string usageInformation_; //!< Tells about the usage of this parameter
+
+        MultiType   value_;            //!< The actual value
+        MultiType   defaultValue_;     //!< Default value. Should not be changed.
+    };
+
+
+    /**
+    @brief
+        Global interface to command line options.
+        Allows to add and retrieve command line arguments. Also does the parsing.
+    @note
+        Internally it is a Singleton, but the public interface is static.
+    @see
+        CommandLineArgument
+    */
+    class _CoreExport CommandLineParser : public Singleton<CommandLineParser>
+    {
+        friend class Singleton<CommandLineParser>;
+
+    public:
+        //! Constructor initialises bFirstTimeParse_ with true.
+        CommandLineParser() : bFirstTimeParse_(true) { }
+        ~CommandLineParser();
+
+        //! Parse redirection to internal member method.
+        static void parse(const std::string& cmdLine)
+        { getInstance()._parse(cmdLine); }
+
+        static std::string getUsageInformation();
+
+        static const CommandLineArgument* getArgument(const std::string& name);
+        //! Writes the argument value in the given parameter.
+        template <class T>
+        static void getValue(const std::string& name, T* value)
+        { *value = (T)(getArgument(name)->getValue()); }
+        static const MultiType& getValue(const std::string& name)
+        { return getArgument(name)->getValue(); }
+
+        static void addArgument(CommandLineArgument* argument);
+        static void removeArgument(CommandLineArgument* argument);
+
+        static bool existsArgument(const std::string& name)
+        {
+            std::map<std::string, CommandLineArgument*>::const_iterator it = getInstance().cmdLineArgs_.find(name);
+            return !(it == getInstance().cmdLineArgs_.end());
+        }
+
+        static void generateDoc(std::ofstream& file);
+
+    private:
+        //! Undefined copy constructor
+        CommandLineParser(const CommandLineParser& instance);
+
+        void _parse(const std::string& cmdLine);
+        void checkFullArgument(const std::string& name, const std::string& value);
+        void checkShortcut(const std::string& shortcut, const std::string& value);
+
+        /**
+            Tells whether we parsed for the first time. The CommmandLineArguments are added before main().
+            So when we call parse() the first time, we need to create a map with all shortcuts since these
+            get added after addCommandLineArgument().
+        */
+        bool bFirstTimeParse_;
+
+        //! Holds all pointers to the arguments and serves as a search map by name.
+        std::map<std::string, CommandLineArgument*> cmdLineArgs_;
+        //! Search map by shortcut for the arguments.
+        std::map<std::string, CommandLineArgument*> cmdLineArgsShortcut_;
+
+        static CommandLineParser* singletonPtr_s;
+    };
+
+    template <>
+    inline void CommandLineParser::getValue<std::string>(const std::string& name, std::string* value)
+    {
+        *value = getArgument(name)->getValue().get<std::string>();
+    }
+}
+
+#endif /* _CommandLine_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,10 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+#  ConfigFile.cc is already included in FilesystemBuildUnit.cc
+  ConfigFileEntryValue.cc
+  ConfigFileEntryVectorValue.cc
+  ConfigFileManager.cc
+  ConfigFileSection.cc
+  Configurable.cc
+  ConfigValueContainer.cc
+  SettingsConfigFile.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFile.cc	(revision 11817)
@@ -0,0 +1,324 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of ConfigFile.
+*/
+
+#include "ConfigFile.h"
+
+#include <boost/filesystem.hpp>
+
+#include <iterator>
+#include <algorithm>
+#include <fstream>
+
+#include "util/Convert.h"
+#include "util/StringUtils.h"
+#include "core/ConfigurablePaths.h"
+#include "ConfigFileEntryComment.h"
+#include "ConfigFileEntryValue.h"
+
+namespace orxonox
+{
+    ////////////////
+    // ConfigFile //
+    ////////////////
+
+    const char* ConfigFile::DEFAULT_CONFIG_FOLDER = "defaultConfig";
+
+    /**
+        @brief Constructor: Initializes the config file.
+        @param filename The file-name of this config file
+        @param bCopyFallbackFile If true, the default config file is copied into the config-directory before loading the file
+    */
+    ConfigFile::ConfigFile(const std::string& filename, bool bCopyFallbackFile)
+        : filename_(filename)
+        , bCopyFallbackFile_(bCopyFallbackFile)
+        , bUpdated_(false)
+    {
+    }
+
+    /**
+        @brief Destructor: Deletes all sections and entries.
+    */
+    ConfigFile::~ConfigFile()
+    {
+        this->clear();
+    }
+
+    /**
+        @brief Loads the config file from the hard-disk and reads the sections and their values.
+    */
+    void ConfigFile::load()
+    {
+        // Be sure we start from new in the memory
+        this->clear();
+
+        boost::filesystem::path filepath(this->filename_);
+        if (!filepath.is_complete())
+        {
+            filepath = ConfigurablePaths::getConfigPath() / filepath;
+            if (this->bCopyFallbackFile_)
+            {
+                // Look for default file in the data folder
+                if (!boost::filesystem::exists(filepath))
+                {
+                    boost::filesystem::path defaultFilepath(ConfigurablePaths::getDataPath() / DEFAULT_CONFIG_FOLDER / this->filename_);
+                    if (boost::filesystem::exists(defaultFilepath))
+                    {
+                        // Try to copy default file from the data folder
+                        try
+                        {
+                            std::ifstream input(defaultFilepath.string().c_str(), std::ifstream::in | std::ifstream::binary);
+                            std::ofstream output(filepath.string().c_str(), std::ofstream::out | std::ofstream::binary);
+                            copy(std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>(), std::ostream_iterator<char>(output));
+                            orxout(internal_info, context::config) << "Copied " << this->filename_ << " from the default config folder." << endl;
+                        }
+                        catch (const boost::filesystem::filesystem_error& ex)
+                        { orxout(user_error, context::config) << "Error in ConfigFile: " << ex.what() << endl; }
+                    }
+                }
+            }
+        }
+
+        // Open the file
+        std::ifstream file;
+        file.open(filepath.string().c_str(), std::fstream::in);
+        if (file.is_open())
+        {
+            ConfigFileSection* newsection = nullptr;
+
+            while (file.good() && !file.eof())
+            {
+                std::string line;
+                std::getline(file, line);
+
+                const std::string& temp = getStripped(line);
+                if (!isEmpty(temp) && !isComment(temp))
+                {
+                    size_t   pos1 = temp.find('[');
+                    if (pos1 == 0) pos1 = line.find('['); else pos1 = std::string::npos;
+                    size_t   pos2 = line.find(']');
+
+                    if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1)
+                    {
+                        // New section
+                        const std::string& comment = line.substr(pos2 + 1);
+                        if (isComment(comment))
+                            newsection = new ConfigFileSection(line.substr(pos1 + 1, pos2 - pos1 - 1), comment);
+                        else
+                            newsection = new ConfigFileSection(line.substr(pos1 + 1, pos2 - pos1 - 1));
+                        this->sections_.insert(this->sections_.end(), newsection);
+                        continue;
+                    }
+                }
+
+                if (newsection != nullptr)
+                {
+                    if (isComment(line))
+                    {
+                        // New comment
+                        newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryComment(removeTrailingWhitespaces(line)));
+                        continue;
+                    }
+                    else
+                    {
+                        size_t pos1 = line.find('=');
+
+                        if (pos1 != std::string::npos && pos1 > 0)
+                        {
+                            // New entry
+                            size_t pos2 = line.find('[');
+                            size_t pos3 = line.find(']');
+                            size_t commentposition = getNextCommentPosition(line, pos1 + 1);
+                            while (isBetweenQuotes(line, commentposition))
+                            {
+                                commentposition = getNextCommentPosition(line, commentposition + 1);
+                            }
+                            std::string value, comment;
+                            if (commentposition == std::string::npos)
+                            {
+                                value = line.substr(pos1 + 1);
+                            }
+                            else
+                            {
+                                value = line.substr(pos1 + 1, commentposition - pos1 - 1);
+                                comment = removeTrailingWhitespaces(line.substr(commentposition));
+                            }
+
+                            value = removeTrailingWhitespaces(value);
+                            value = removeSlashes(value);
+
+                            if (pos2 != std::string::npos && pos3 != std::string::npos && pos3 > pos2 + 1)
+                            {
+                                // There might be an array index
+                                unsigned int index = 0;
+                                if (convertValue(&index, line.substr(pos2 + 1, pos3 - pos2 - 1)))
+                                {
+                                    // New array
+                                    std::list<ConfigFileEntry*>::iterator it = newsection->getOrCreateEntryIterator(getStripped(line.substr(0, pos2)), index, value, false);
+                                    (*it)->setValue(value);
+                                    (*it)->setComment(comment);
+                                    continue;
+                                }
+                            }
+
+                            // New value
+                            newsection->getEntries().insert(newsection->getEntries().end(), new ConfigFileEntryValue(getStripped(line.substr(0, pos1)), value, false, comment));
+                            continue;
+                        }
+                    }
+                }
+            }
+
+            file.close();
+
+            orxout(internal_info, context::config) << "Loaded config file \"" << this->filename_ << "\"." << endl;
+
+            // DO NOT save the file --> we can open supposedly read only config files
+        } // end file.is_open()
+    }
+
+    /**
+        @brief Writes the sections and values to the hard-disk.
+    */
+    void ConfigFile::save() const
+    {
+        this->saveAs(this->filename_);
+    }
+
+    /**
+        @brief Writes the sections and values to a given file on the hard-disk.
+    */
+    void ConfigFile::saveAs(const std::string& filename) const
+    {
+        boost::filesystem::path filepath(filename);
+        if (!filepath.is_complete())
+            filepath = ConfigurablePaths::getConfigPath() / filename;
+        std::ofstream file;
+        file.open(filepath.string().c_str(), std::fstream::out);
+        file.setf(std::ios::fixed, std::ios::floatfield);
+        file.precision(6);
+
+        if (!file.is_open())
+        {
+            orxout(user_error, context::config) << "Couldn't open config-file \"" << filename << "\"." << endl;
+            return;
+        }
+
+        for (ConfigFileSection* section : this->sections_)
+        {
+            file << section->getFileEntry() << endl;
+
+            for (ConfigFileEntry* entry : section->getEntries())
+                file << entry->getFileEntry() << endl;
+
+            file << endl;
+        }
+
+        file.close();
+
+        orxout(verbose, context::config) << "Saved config file \"" << filename << "\"." << endl;
+    }
+
+    /**
+        @brief Deletes all sections (which again delete all their values) and clears the list of sections.
+    */
+    void ConfigFile::clear()
+    {
+        for (std::list<ConfigFileSection*>::iterator it = this->sections_.begin(); it != this->sections_.end(); )
+            delete (*(it++));
+        this->sections_.clear();
+    }
+
+    /**
+        @brief Deletes all elements of a config vector if their index is greater or equal to @a startindex.
+
+        @param section      The name of the section
+        @param name         The name of the vector
+        @param startindex   The index of the first element that will be deleted
+    */
+    void ConfigFile::deleteVectorEntries(const std::string& section, const std::string& name, unsigned int startindex)
+    {
+        if (ConfigFileSection* sectionPtr = this->getSection(section))
+        {
+            sectionPtr->deleteVectorEntries(name, startindex);
+            this->save();
+        }
+    }
+
+    /**
+        @brief Returns a pointer to the section with given name (or nullptr if the section doesn't exist).
+    */
+    ConfigFileSection* ConfigFile::getSection(const std::string& sectionName) const
+    {
+        for (ConfigFileSection* section : this->sections_)
+            if (section->getName() == sectionName)
+                return section;
+        return nullptr;
+    }
+
+    /**
+        @brief Returns a pointer to the section with given name. If it doesn't exist, the section is created.
+    */
+    ConfigFileSection* ConfigFile::getOrCreateSection(const std::string& sectionName)
+    {
+        for (ConfigFileSection* section : this->sections_)
+            if (section->getName() == sectionName)
+                return section;
+
+        this->bUpdated_ = true;
+
+        return (*this->sections_.insert(this->sections_.end(), new ConfigFileSection(sectionName)));
+    }
+
+    /**
+        @brief Saves the config file if it was updated (or if any of its sections were updated).
+    */
+    void ConfigFile::saveIfUpdated()
+    {
+        bool sectionsUpdated = false;
+
+        for (ConfigFileSection* section : this->sections_)
+        {
+            if (section->bUpdated_)
+            {
+                sectionsUpdated = true;
+                section->bUpdated_ = false;
+            }
+        }
+
+        if (this->bUpdated_ || sectionsUpdated)
+        {
+            this->bUpdated_ = false;
+            this->save();
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFile.h	(revision 11817)
@@ -0,0 +1,178 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _ConfigFile_H__
+#define _ConfigFile_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ConfigFileSection.h"
+
+namespace orxonox
+{
+    ////////////////
+    // ConfigFile //
+    ////////////////
+    /**
+        @brief This class represents a config file, which is stored on the hard-disk and contains config values in different sections.
+
+        It provides an interface to manipulate the sections and values.
+    */
+    class _CoreExport ConfigFile
+    {
+        public:
+            ConfigFile(const std::string& filename, bool bCopyFallbackFile = true);
+            virtual ~ConfigFile();
+
+            virtual void load();
+            virtual void save() const;
+            virtual void saveAs(const std::string& filename) const;
+            virtual void clear();
+
+            /// Returns the file-name of this config file
+            inline const std::string& getFilename()
+                { return this->filename_; }
+
+            /**
+                @brief Stores a value in the config file. If the entry or its section doesn't exist, it's created.
+
+                @param section  The name of the section
+                @param name     The name of the entry
+                @param value    The new value
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline void setValue(const std::string& section, const std::string& name, const std::string& value, bool bString)
+            {
+                this->getOrCreateSection(section)->setValue(name, value, bString);
+                this->save();
+            }
+            /**
+                @brief Returns the value of a given entry in the config file. Returns a blank string if the value doesn't exist.
+
+                @param section  The name of the section
+                @param name     The name of the entry
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getValue(const std::string& section, const std::string& name, bool bString)
+            {
+                ConfigFileSection* sectionPtr = this->getSection(section);
+                return (sectionPtr ? sectionPtr->getValue(name, bString) : BLANKSTRING);
+            }
+            /**
+                @brief Returns the value of a given entry in the config file. If it doesn't exist, the entry is created using the fallback value.
+
+                @param section  The name of the section
+                @param name     The name of the entry
+                @param fallback The value that will be used if the entry doesn't exist
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getOrCreateValue(const std::string& section, const std::string& name, const std::string& fallback, bool bString)
+            {
+                const std::string& output = this->getOrCreateSection(section)->getOrCreateValue(name, fallback, bString);
+                this->saveIfUpdated();
+                return output;
+            }
+
+            /**
+                @brief Stores the value of an element of a vector in the config file. If the entry or its section doesn't exist, it's created.
+
+                @param section  The name of the section
+                @param name     The name of the vector
+                @param index    The index of the element in the vector
+                @param value    The new value
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline void setValue(const std::string& section, const std::string& name, unsigned int index, const std::string& value, bool bString)
+            {
+                this->getOrCreateSection(section)->setValue(name, index, value, bString);
+                this->save();
+            }
+            /**
+                @brief Returns the value of a given element of a vector in the config file. Returns a blank string if the value doesn't exist.
+
+                @param section  The name of the section
+                @param name     The name of the vector
+                @param index    The index of the element in the vector
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getValue(const std::string& section, const std::string& name, unsigned int index, bool bString)
+            {
+                ConfigFileSection* sectionPtr = this->getSection(section);
+                return (sectionPtr ? sectionPtr->getValue(name, index, bString) : BLANKSTRING);
+            }
+            /**
+                @brief Returns the value of a given element of a vector in the config file. If it doesn't exist, the entry is created using the fallback value.
+
+                @param section  The name of the section
+                @param name     The name of the vector
+                @param index    The index of the element in the vector
+                @param fallback The value that will be used if the entry doesn't exist
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            const std::string& getOrCreateValue(const std::string& section, const std::string& name, unsigned int index, const std::string& fallback, bool bString)
+            {
+                const std::string& output = this->getOrCreateSection(section)->getOrCreateValue(name, index, fallback, bString);
+                this->saveIfUpdated();
+                return output;
+            }
+
+            void deleteVectorEntries(const std::string& section, const std::string& name, unsigned int startindex = 0);
+            /**
+                @brief Returns the size of a config vector.
+                @param section  The section of the vector
+                @param name     The name of the vector
+            */
+            inline unsigned int getVectorSize(const std::string& section, const std::string& name) const
+            {
+                ConfigFileSection* sectionPtr = this->getSection(section);
+                return (sectionPtr ? sectionPtr->getVectorSize(name) : 0);
+            }
+
+            static const char* DEFAULT_CONFIG_FOLDER;   ///< The folder where the default config files will be stored
+
+        protected:
+            ConfigFileSection* getSection(const std::string& section) const;
+            ConfigFileSection* getOrCreateSection(const std::string& section);
+
+            std::list<ConfigFileSection*> sections_;    ///< A list of sections in this config file
+
+        private:
+            void saveIfUpdated();
+
+            const std::string filename_;                ///< The filename of this config file
+            const bool bCopyFallbackFile_;              ///< If true, the default config file is copied into the config-directory before loading the file
+            bool bUpdated_;                             ///< Becomes true if a section is added
+    };
+}
+
+#endif /* _ConfigFile_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntry.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntry.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntry.h	(revision 11817)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _ConfigFileEntry_H__
+#define _ConfigFileEntry_H__
+
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    /////////////////////
+    // ConfigFileEntry //
+    /////////////////////
+    /**
+        @brief This class represents an entry in the config file.
+
+        This class is pure virtual. Use one of the derived classes to define the type of the entry.
+    */
+    class _CoreExport ConfigFileEntry
+    {
+        public:
+            /// Destructor
+            virtual ~ConfigFileEntry() = default;
+
+            /// Changes the value of the entry.
+            virtual void setValue(const std::string& value) = 0;
+            /// Returns the value of the entry.
+            virtual const std::string& getValue() const = 0;
+
+            /// Returns the name of the entry
+            virtual const std::string& getName() const = 0;
+
+            /// Changes the comment of the entry (will be placed after the value)
+            virtual void setComment(const std::string& comment) = 0;
+
+            /// Returns the index of the entry in a vector (used only if it is a vector)
+            virtual unsigned int getIndex() const { return 0; }
+
+            /// Defines if this entry is treated as string which means some special treatment of special characters.
+            virtual void setString(bool bString) = 0;
+
+            /// Returns the line as it will be stored in the config file.
+            virtual const std::string& getFileEntry() const = 0;
+    };
+}
+
+#endif /* _ConfigFileEntry_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryComment.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryComment.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryComment.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _ConfigFileEntryComment_H__
+#define _ConfigFileEntryComment_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ConfigFileEntry.h"
+
+namespace orxonox
+{
+    ////////////////////////////
+    // ConfigFileEntryComment //
+    ////////////////////////////
+    /**
+        @brief This class represents a line in the config file which contains only a comment.
+    */
+    class _CoreExport ConfigFileEntryComment : public ConfigFileEntry
+    {
+        public:
+            /// Constructor: Initializes the object.
+            inline ConfigFileEntryComment(const std::string& comment) : comment_(comment) {}
+
+            /// Destructor
+            virtual inline ~ConfigFileEntryComment() = default;
+
+            virtual inline const std::string& getName() const override
+                { return this->comment_; }
+
+            virtual inline void setComment(const std::string& comment) override
+                { this->comment_ = comment; }
+
+            virtual inline void setValue(const std::string& value) override
+                {}
+            virtual inline const std::string& getValue() const override
+                { return BLANKSTRING; }
+
+            virtual inline void setString(bool bString) override
+                {}
+
+            virtual inline const std::string& getFileEntry() const override
+                { return this->comment_; }
+
+        private:
+            std::string comment_;   ///< The comment
+    };
+}
+
+#endif /* _ConfigFileEntryComment_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryValue.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryValue.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryValue.cc	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of ConfigFileEntryValue.
+*/
+
+#include "ConfigFileEntryValue.h"
+
+#include "util/StringUtils.h"
+
+namespace orxonox
+{
+    //////////////////////////
+    // ConfigFileEntryValue //
+    //////////////////////////
+    /**
+        @brief Updates the string that will be stored in the file after one of it's components (name, value, comment) has changed.
+    */
+    void ConfigFileEntryValue::update()
+    {
+        // Make sure we remove the quotes when bString changes
+        if (this->bString_)
+            this->value_ = stripEnclosingQuotes(this->value_);
+        // Assemble the entry line
+        this->fileEntry_ = this->getKeyString() + " = ";
+        if (this->bString_ && !this->value_.empty())
+            this->fileEntry_ += '"' + addSlashes(this->value_) + '"';
+        else
+            this->fileEntry_ += this->value_;
+        if (!this->additionalComment_.empty())
+            this->fileEntry_ += ' ' + this->additionalComment_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryValue.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryValue.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryValue.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _ConfigFileEntryValue_H__
+#define _ConfigFileEntryValue_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+#include "ConfigFileEntry.h"
+
+namespace orxonox
+{
+    //////////////////////////
+    // ConfigFileEntryValue //
+    //////////////////////////
+    /**
+        @brief This class represents a normal value in the config file.
+    */
+    class _CoreExport ConfigFileEntryValue : public ConfigFileEntry
+    {
+        public:
+            /**
+                @brief Constructor: Initializes the entry.
+
+                @param name                 The name of the entry
+                @param value                The value of the entry
+                @param bString              If true, the value is treated as string which means some special treatment of special characters.
+                @param additionalComment    An optional comment that will be placed behind the value in the config file
+            */
+            inline ConfigFileEntryValue(const std::string& name, const std::string& value = "", bool bString = false, const std::string& additionalComment = "")
+                : name_(name)
+                , value_(value)
+                , additionalComment_(additionalComment)
+                , bString_(bString)
+                { this->update(); }
+
+            /// Destructor
+            virtual inline ~ConfigFileEntryValue() = default;
+
+            virtual inline const std::string& getName() const override
+                { return this->name_; }
+
+            virtual inline void setComment(const std::string& comment) override
+                { this->additionalComment_ = comment; this->update(); }
+
+            virtual inline void setValue(const std::string& value) override
+                { this->value_ = value; this->update(); }
+            virtual inline const std::string& getValue() const override
+                { return this->value_; }
+
+            virtual inline void setString(bool bString) override
+                { this->bString_ = bString; this->update(); }
+
+            virtual inline const std::string& getFileEntry() const override
+                { return this->fileEntry_; }
+
+            /// Returns the "key" of the value (in this case it's just the name of the entry, but for vectors it's different)
+            virtual inline const std::string& getKeyString() const
+                { return this->name_; }
+
+        protected:
+            virtual void update();
+
+            const std::string name_;            ///< The name of the value
+            std::string value_;                 ///< The value
+            std::string additionalComment_;     ///< The additional comment
+            std::string fileEntry_;             ///< The string as it will be stored in the config file
+            bool bString_;                      ///< If true, the value is treated as string which means some special treatment of special characters.
+    };
+}
+
+#endif /* _ConfigFileEntryValue_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryVectorValue.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryVectorValue.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryVectorValue.cc	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of ConfigFileEntryVectorValue.
+*/
+
+#include "ConfigFileEntryVectorValue.h"
+
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    ////////////////////////////////
+    // ConfigFileEntryVectorValue //
+    ////////////////////////////////
+    /**
+        @brief Updates the string that will be stored in the file after one of it's components (name, value, index, comment) has changed.
+    */
+    void ConfigFileEntryVectorValue::update()
+    {
+        this->keyString_ = this->name_ + '[' + multi_cast<std::string>(this->index_) + ']';
+        ConfigFileEntryValue::update();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryVectorValue.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryVectorValue.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileEntryVectorValue.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _ConfigFileEntryVectorValue_H__
+#define _ConfigFileEntryVectorValue_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ConfigFileEntryValue.h"
+
+namespace orxonox
+{
+    ////////////////////////////////
+    // ConfigFileEntryVectorValue //
+    ////////////////////////////////
+    /**
+        @brief Subclass of ConfigFileEntryValue, represents an element of a vector.
+    */
+    class _CoreExport ConfigFileEntryVectorValue : public ConfigFileEntryValue
+    {
+        public:
+            /**
+                @brief Constructor: Initializes the entry.
+
+                @param name                 The name of the vector
+                @param index                The index of the element in the vector
+                @param value                The value of the element
+                @param bString              If true, the value is treated as string which means some special treatment of special characters.
+                @param additionalComment    An optional comment that will be placed behind the value in the config file
+            */
+            inline ConfigFileEntryVectorValue(const std::string& name, unsigned int index, const std::string& value = "", bool bString = false, const std::string& additionalComment = "")
+                : ConfigFileEntryValue(name, value, bString, additionalComment)
+                , index_(index)
+                { this->update(); /*No virtual calls in base class ctor*/ }
+
+            /// Destructor
+            inline ~ConfigFileEntryVectorValue() = default;
+
+            virtual inline unsigned int getIndex() const override
+                { return this->index_; }
+
+            /// Returns the "key" of the value (the name of the vector plus the index of the element)
+            virtual inline const std::string& getKeyString() const override
+                { return this->keyString_; }
+
+        private:
+            virtual void update() override;
+
+            unsigned int index_;        ///< The index of the element in the vector
+            std::string keyString_;     ///< The full name of the entry (the name of the vector plus the index of the element)
+    };
+}
+
+#endif /* _ConfigFileEntryVectorValue_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileManager.cc	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of ConfigFileManager.
+*/
+
+#include "ConfigFileManager.h"
+
+#include "SettingsConfigFile.h"
+
+namespace orxonox
+{
+    ///////////////////////
+    // ConfigFileManager //
+    ///////////////////////
+
+    ConfigFileManager* ConfigFileManager::singletonPtr_s = nullptr;
+
+    /// Constructor: Initializes the array of config files with nullptr.
+    ConfigFileManager::ConfigFileManager()
+    {
+        this->configFiles_.fill(nullptr);
+    }
+
+    /// Destructor: Deletes the config files.
+    ConfigFileManager::~ConfigFileManager()
+    {
+        for (ConfigFile* configFile : this->configFiles_)
+            if (configFile)
+                delete configFile;
+    }
+
+    /// Defines the file-name for the config file of a given type (settings, calibration, etc.).
+    void ConfigFileManager::setFilename(ConfigFileType::Value type, const std::string& filename)
+    {
+        if (this->getConfigFile(type))
+            delete this->configFiles_[type];
+        // Create and load config file
+        switch (type)
+        {
+        case ConfigFileType::Settings:
+            this->configFiles_[type] = new SettingsConfigFile(filename);
+            break;
+        case ConfigFileType::JoyStickCalibration:
+        case ConfigFileType::CommandHistory:
+            this->configFiles_[type] = new ConfigFile(filename);
+            break;
+        }
+        this->configFiles_[type]->load();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileManager.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+    @brief Declaration of ConfigFileManager, used to load and save config files.
+*/
+
+#ifndef _ConfigFileManager_H__
+#define _ConfigFileManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <array>
+
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    ///////////////////////
+    // ConfigFileManager //
+    ///////////////////////
+    /**
+        @brief Manages the different config files (settings, calibration, etc). Implemented as Singleton.
+    */
+    class _CoreExport ConfigFileManager : public Singleton<ConfigFileManager>
+    {
+        friend class Singleton<ConfigFileManager>;
+        public:
+            ConfigFileManager();
+            ~ConfigFileManager();
+
+            void setFilename(ConfigFileType::Value type, const std::string& filename);
+
+            /// Returns the config file of a given type (settings, calibration, etc.)
+            inline ConfigFile* getConfigFile(ConfigFileType::Value type)
+            {
+                // Check array bounds
+                return configFiles_.at(type);
+            }
+
+        private:
+            // non-copyable:
+            ConfigFileManager(const ConfigFileManager&) = delete;
+            ConfigFileManager& operator=(const ConfigFileManager&) = delete;
+
+            std::array<ConfigFile*, 3> configFiles_;        ///< Stores the config files for each type in an array (must have the same size like ConfigFileType::Value)
+            static ConfigFileManager* singletonPtr_s;       ///< Stores the singleton-pointer
+    };
+}
+
+#endif /* _ConfigFileManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileSection.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileSection.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileSection.cc	(revision 11817)
@@ -0,0 +1,180 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of ConfigFileSection.
+*/
+
+#include "ConfigFileSection.h"
+
+#include "ConfigFileEntryValue.h"
+#include "ConfigFileEntryVectorValue.h"
+
+namespace orxonox
+{
+    ///////////////////////
+    // ConfigFileSection //
+    ///////////////////////
+    /**
+        @brief Destructor: Deletes all entries.
+    */
+    ConfigFileSection::~ConfigFileSection()
+    {
+        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); )
+            delete (*(it++));
+    }
+
+    /**
+        @brief Deletes all elements of a config vector if their index is greater or equal to @a startindex.
+
+        @param name         The name of the vector
+        @param startindex   The index of the first element that will be deleted
+    */
+    void ConfigFileSection::deleteVectorEntries(const std::string& name, unsigned int startindex)
+    {
+        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); )
+        {
+            if (((*it)->getName() == name) && ((*it)->getIndex() >= startindex))
+            {
+                delete (*it);
+                this->entries_.erase(it++);
+            }
+            else
+            {
+                ++it;
+            }
+        }
+    }
+
+    /**
+        @brief Returns the size of a config vector.
+        @param name     The name of the vector
+    */
+    unsigned int ConfigFileSection::getVectorSize(const std::string& name) const
+    {
+        unsigned int size = 0;
+        for (ConfigFileEntry* entry : this->entries_)
+            if (entry->getName() == name)
+                if (entry->getIndex() >= size)
+                    size = entry->getIndex() + 1;
+        return size;
+    }
+
+    /**
+        @brief Returns the title and comment of the section as it will be stored in the file.
+    */
+    std::string ConfigFileSection::getFileEntry() const
+    {
+        if (this->additionalComment_.empty())
+            return ('[' + this->name_ + ']');
+        else
+            return ('[' + this->name_ + "] " + this->additionalComment_);
+    }
+
+    /**
+        @brief Returns the entry with given name (or nullptr if it doesn't exist).
+
+        @param name     The name of the entry
+    */
+    ConfigFileEntry* ConfigFileSection::getEntry(const std::string& name) const
+    {
+        for (ConfigFileEntry* entry : this->entries_)
+        {
+            if (entry->getName() == name)
+                return entry;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Returns the entry of a vector element with given name and index (or nullptr if it doesn't exist).
+
+        @param name     The name of the vector
+        @param index    The index of the element in the vector
+    */
+    ConfigFileEntry* ConfigFileSection::getEntry(const std::string& name, unsigned int index) const
+    {
+        for (ConfigFileEntry* entry : this->entries_)
+        {
+            if ((entry->getName() == name) && (entry->getIndex() == index))
+                return entry;
+        }
+        return nullptr;
+    }
+
+    /**
+        @brief Returns the iterator to the entry with given name. If the entry doesn't exist, it is created using the fallback value.
+
+        @param name     The name of the entry
+        @param fallback The value that will be used if the entry doesn't exist
+        @param bString  If true, the value is treated as string which means some special treatment of special characters.
+    */
+    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getOrCreateEntryIterator(const std::string& name, const std::string& fallback, bool bString)
+    {
+        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
+        {
+            if ((*it)->getName() == name)
+            {
+                (*it)->setString(bString);
+                return it;
+            }
+        }
+
+        this->bUpdated_ = true;
+
+        return this->entries_.insert(this->entries_.end(), new ConfigFileEntryValue(name, fallback, bString));
+    }
+
+    /**
+        @brief Returns the iterator to the entry of a vector element with given name and index. If the entry doesn't exist, it is created using the fallback value.
+
+        @param name     The name of the vector
+        @param index    The index of the element in the vector
+        @param fallback The value that will be used if the entry doesn't exist
+        @param bString  If true, the value is treated as string which means some special treatment of special characters.
+    */
+    std::list<ConfigFileEntry*>::iterator ConfigFileSection::getOrCreateEntryIterator(const std::string& name, unsigned int index, const std::string& fallback, bool bString)
+    {
+        for (std::list<ConfigFileEntry*>::iterator it = this->entries_.begin(); it != this->entries_.end(); ++it)
+        {
+            if (((*it)->getName() == name) && ((*it)->getIndex() == index))
+            {
+                (*it)->setString(bString);
+                return it;
+            }
+        }
+
+        this->bUpdated_ = true;
+
+        if (index == 0)
+            return this->entries_.insert(this->entries_.end(), new ConfigFileEntryVectorValue(name, index, fallback, bString));
+        else
+            return this->entries_.insert(++this->getOrCreateEntryIterator(name, index - 1, "", bString), new ConfigFileEntryVectorValue(name, index, fallback, bString));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileSection.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileSection.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigFileSection.h	(revision 11817)
@@ -0,0 +1,199 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _ConfigFileSection_H__
+#define _ConfigFileSection_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+#include <list>
+#include "util/StringUtils.h"
+#include "ConfigFileEntry.h"
+
+namespace orxonox
+{
+    ///////////////////////
+    // ConfigFileSection //
+    ///////////////////////
+    /**
+        @brief Represents a section in a config file.
+
+        A section has a name and a list of config values.
+    */
+    class _CoreExport ConfigFileSection
+    {
+        friend class ConfigFile;
+        friend class SettingsConfigFile;
+
+        public:
+            /**
+                @brief Constructor: Initializes the section.
+
+                @param name The name of the section
+                @param additionalComment An additional comment placed after the title of the section in the config file
+            */
+            inline ConfigFileSection(const std::string& name, const std::string& additionalComment = "")
+                : name_(name)
+                , additionalComment_(additionalComment)
+                , bUpdated_(false)
+                {}
+            ~ConfigFileSection();
+
+            /// Returns the name of the section.
+            inline const std::string& getName() const
+                { return this->name_; }
+
+            /// Changes the comment which is placed after the title of the section in the config file.
+            inline void setComment(const std::string& comment)
+                { this->additionalComment_ = comment; }
+
+            /**
+                @brief Stores a value in the section. If the entry doesn't exist, it's created.
+
+                @param name     The name of the entry
+                @param value    The new value
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline void setValue(const std::string& name, const std::string& value, bool bString)
+                { this->getOrCreateEntry(name, value, bString)->setValue(value); }
+            /**
+                @brief Returns the value of a given entry in the section. Returns a blank string if the value doesn't exist.
+
+                @param name     The name of the entry
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getValue(const std::string& name, bool bString)
+            {
+                ConfigFileEntry* entry = this->getEntry(name);
+                if (entry)
+                {
+                    entry->setString(bString);  // if the entry was loaded from the config file, we have to tell it if it's a string
+                    return entry->getValue();
+                }
+                return BLANKSTRING;
+            }
+            /**
+                @brief Returns the value of a given entry in the section. If it doesn't exist, the entry is created using the fallback value.
+
+                @param name     The name of the entry
+                @param fallback The value that will be used if the entry doesn't exist
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getOrCreateValue(const std::string& name, const std::string& fallback, bool bString)
+                { return this->getOrCreateEntry(name, fallback, bString)->getValue(); }
+
+            /**
+                @brief Stores the value of an element of a vector in the section. If the entry doesn't exist, it's created.
+
+                @param name     The name of the vector
+                @param index    The index of the element in the vector
+                @param value    The new value
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline void setValue(const std::string& name, unsigned int index, const std::string& value, bool bString)
+                { this->getOrCreateEntry(name, index, value, bString)->setValue(value); }
+            /**
+                @brief Returns the value of a given element of a vector in the section. Returns a blank string if the value doesn't exist.
+
+                @param name     The name of the vector
+                @param index    The index of the element in the vector
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getValue(const std::string& name, unsigned int index, bool bString)
+            {
+                ConfigFileEntry* entry = this->getEntry(name, index);
+                if (entry)
+                {
+                    entry->setString(bString);  // if the entry was loaded from the config file, we have to tell it if it's a string
+                    return entry->getValue();
+                }
+                return BLANKSTRING;
+            }
+            /**
+                @brief Returns the value of a given element of a vector in the section. If it doesn't exist, the entry is created using the fallback value.
+
+                @param name     The name of the vector
+                @param index    The index of the element in the vector
+                @param fallback The value that will be used if the entry doesn't exist
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline const std::string& getOrCreateValue(const std::string& name, unsigned int index, const std::string& fallback, bool bString)
+                { return this->getOrCreateEntry(name, index, fallback, bString)->getValue(); }
+
+            void deleteVectorEntries(const std::string& name, unsigned int startindex = 0);
+            unsigned int getVectorSize(const std::string& name) const;
+
+            std::string getFileEntry() const;
+
+        private:
+            /// Returns the list of entries in this section.
+            std::list<ConfigFileEntry*>& getEntries()
+                { return this->entries_; }
+            const std::list<ConfigFileEntry*>& getEntries() const
+                { return this->entries_; }
+
+            std::list<ConfigFileEntry*>::iterator getOrCreateEntryIterator(const std::string& name, const std::string& fallback, bool bString);
+            std::list<ConfigFileEntry*>::iterator getOrCreateEntryIterator(const std::string& name, unsigned int index, const std::string& fallback, bool bString);
+
+            ConfigFileEntry* getEntry(const std::string& name) const;
+            /**
+                @brief Returns the entry with given name. If it doesn't exist, the entry is created using the fallback value.
+
+                @param name     The name of the entry
+                @param fallback The value that will be used if the entry doesn't exist
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline ConfigFileEntry* getOrCreateEntry(const std::string& name, const std::string& fallback, bool bString)
+                { return (*this->getOrCreateEntryIterator(name, fallback, bString)); }
+
+            ConfigFileEntry* getEntry(const std::string& name, unsigned int index) const;
+            /**
+                @brief Returns the entry that contains an element of a vector with given name. If it doesn't exist, the entry is created using the fallback value.
+
+                @param name     The name of the entry
+                @param index    The index of the element in the vector
+                @param fallback The value that will be used if the entry doesn't exist
+                @param bString  If true, the value is treated as string which means some special treatment of special characters.
+            */
+            inline ConfigFileEntry* getOrCreateEntry(const std::string& name, unsigned int index, const std::string& fallback, bool bString)
+                { return (*this->getOrCreateEntryIterator(name, index, fallback, bString)); }
+
+            std::string name_;                      ///< The name of the section
+            std::string additionalComment_;         ///< The additional comment which is placed after the title of the section in the config file
+            std::list<ConfigFileEntry*> entries_;   ///< The list of entries in this section
+            bool bUpdated_;                         ///< True if an entry is created
+    };
+}
+
+#endif /* _ConfigFileSection_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueContainer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueContainer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueContainer.cc	(revision 11817)
@@ -0,0 +1,353 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the ConfigValueContainer class.
+*/
+
+#include "ConfigValueContainer.h"
+
+#include "util/Convert.h"
+#include "util/SubString.h"
+#include "core/Language.h"
+#include "ConfigFileManager.h"
+#include "SettingsConfigFile.h"
+
+namespace orxonox
+{
+    const unsigned int MAX_VECTOR_INDEX  = 255; // to avoid up to 4*10^9 vector entries in the config file after accidentally using a wrong argument
+
+    /**
+        @brief Initializes the ConfigValueContainer with default values.
+    */
+    void ConfigValueContainer::init(ConfigFileType::Value type, Identifier* identifier, const std::string& sectionname, const std::string& varname)
+    {
+        this->type_ = type;
+        this->identifier_ = identifier;
+        this->sectionname_ = sectionname;
+        this->varname_ = varname;
+        this->callback_ = nullptr;
+        this->bContainerIsNew_ = true;
+        this->bDoInitialCallback_ = false;
+        this->bAddedDescription_ = false;
+
+        // Register containers for general settings
+        if (this->type_ == ConfigFileType::Settings)
+            SettingsConfigFile::getInstance().addConfigValueContainer(this);
+    }
+
+    /**
+        @brief Does some special initialization for single config-values.
+    */
+    void ConfigValueContainer::initValue(const MultiType& defvalue)
+    {
+        this->value_ = defvalue;
+        this->bIsVector_ = false;
+
+        this->defvalueString_ = this->value_.get<std::string>();
+        this->update();
+    }
+
+    /**
+        @brief Does some special initialization for vector config-values.
+    */
+    void ConfigValueContainer::initVector()
+    {
+        this->bIsVector_ = true;
+
+        for (unsigned int i = 0; i < this->valueVector_.size(); i++)
+        {
+            ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType<std::string>());
+            this->defvalueStringVector_.push_back(this->valueVector_[i]);
+        }
+
+        this->update();
+    }
+
+    /**
+        @brief Destructor: Deletes the callback object if necessary.
+    */
+    ConfigValueContainer::~ConfigValueContainer()
+    {
+        if (this->callback_)
+            delete this->callback_;
+
+        // Unregister general settings containers
+        if (this->type_ == ConfigFileType::Settings && SettingsConfigFile::exists())
+            SettingsConfigFile::getInstance().removeConfigValueContainer(this);
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
+        @param input The new value
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::set(const MultiType& input)
+    {
+        if (this->bIsVector_)
+        {
+            return this->callFunctionWithIndex(&ConfigValueContainer::set, input);
+        }
+        else
+        {
+            if (this->tset(input))
+            {
+                ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, input, this->value_.isType<std::string>());
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
+        @param index The index in the vector
+        @param input The new value
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::set(unsigned int index, const MultiType& input)
+    {
+        if (this->bIsVector_)
+        {
+            if (this->tset(index, input))
+            {
+                ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, index, input, this->value_.isType<std::string>());
+                return true;
+            }
+        }
+        else
+        {
+            orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
+        }
+        return false;
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
+        @param input The new value. If bIsVector_ then write "index value"
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::tset(const MultiType& input)
+    {
+        if (this->bIsVector_)
+        {
+            return this->callFunctionWithIndex(&ConfigValueContainer::tset, input);
+        }
+        else
+        {
+            this->value_ = input;
+
+            if (this->identifier_)
+                this->identifier_->updateConfigValues();
+
+            return true;
+        }
+    }
+
+    /**
+        @brief Assigns a new value to the config-value of all objects, but doesn't change the config-file (t stands for temporary).
+        @param index The index in the vector
+        @param input The new value
+        @return True if the new value was successfully assigned
+    */
+    bool ConfigValueContainer::tset(unsigned int index, const MultiType& input)
+    {
+        if (this->bIsVector_)
+        {
+            if (index > MAX_VECTOR_INDEX)
+            {
+                orxout(user_error, context::config) << "Index " << index << " is too large." << endl;
+                return false;
+            }
+
+            if (index >= this->valueVector_.size())
+            {
+                for (unsigned int i = this->valueVector_.size(); i <= index; i++)
+                {
+                    this->valueVector_.emplace_back();
+                }
+            }
+
+            this->valueVector_[index] = input;
+
+            if (this->identifier_)
+                this->identifier_->updateConfigValues();
+
+            return true;
+        }
+        else
+        {
+            orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
+            return false;
+        }
+    }
+
+    /**
+        @brief Adds a new entry to the end of the vector.
+        @param input The new entry
+        @return True if the new entry was successfully added
+    */
+    bool ConfigValueContainer::add(const MultiType& input)
+    {
+        if (this->bIsVector_)
+            return this->set(this->valueVector_.size(), input);
+
+        orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
+        return false;
+    }
+
+    /**
+        @brief Removes an existing entry from the vector.
+        @param index The index of the entry
+        @return True if the entry was removed
+    */
+    bool ConfigValueContainer::remove(unsigned int index)
+    {
+        if (this->bIsVector_)
+        {
+            if (index < this->valueVector_.size())
+            {
+                // Erase the entry from the vector, change (shift) all entries beginning with index in the config file, remove the last entry from the file
+                this->valueVector_.erase(this->valueVector_.begin() + index);
+                for (unsigned int i = index; i < this->valueVector_.size(); i++)
+                    ConfigFileManager::getInstance().getConfigFile(this->type_)->setValue(this->sectionname_, this->varname_, i, this->valueVector_[i], this->value_.isType<std::string>());
+                ConfigFileManager::getInstance().getConfigFile(this->type_)->deleteVectorEntries(this->sectionname_, this->varname_, this->valueVector_.size());
+
+                return true;
+            }
+            orxout(user_error, context::config) << "Invalid vector-index." << endl;
+        }
+
+        orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is not a vector." << endl;
+        return false;
+    }
+
+    /**
+        @brief Sets the value of the variable back to the default value and resets the config-file entry.
+    */
+    bool ConfigValueContainer::reset()
+    {
+        if (!this->bIsVector_)
+            return this->set(this->defvalueString_);
+        else
+        {
+            bool success = true;
+            for (unsigned int i = 0; i < this->defvalueStringVector_.size(); i++)
+                if (!this->set(i, this->defvalueStringVector_[i]))
+                    success = false;
+            ConfigFileManager::getInstance().getConfigFile(this->type_)->deleteVectorEntries(this->sectionname_, this->varname_, this->defvalueStringVector_.size());
+            return success;
+        }
+    }
+
+    /**
+        @brief Retrieves the configured value from the currently loaded config-file.
+    */
+    void ConfigValueContainer::update()
+    {
+        if (!this->bIsVector_)
+            this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, this->defvalueString_, this->value_.isType<std::string>());
+        else
+        {
+            this->valueVector_.clear();
+            unsigned int vectorSize = ConfigFileManager::getInstance().getConfigFile(this->type_)->getVectorSize(this->sectionname_, this->varname_);
+            for (unsigned int i = 0; i < vectorSize; i++)
+            {
+                if (i < this->defvalueStringVector_.size())
+                {
+                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, this->defvalueStringVector_[i], this->value_.isType<std::string>());
+                }
+                else
+                {
+                    this->value_ = ConfigFileManager::getInstance().getConfigFile(this->type_)->getOrCreateValue(this->sectionname_, this->varname_, i, MultiType(), this->value_.isType<std::string>());
+                }
+
+                this->valueVector_.push_back(this->value_);
+            }
+        }
+    }
+
+    /**
+        @brief Calls the given function with parsed index and the parsed argument from the input string.
+        @param function The function to call
+        @param input The input string
+        @return The returnvalue of the functioncall
+    */
+    bool ConfigValueContainer::callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiType&), const std::string& input)
+    {
+        SubString token(input, " ", SubString::WhiteSpaces, true, '\\', false, '"', false, '\0', '\0', false, '\0');
+        int index = -1;
+        bool success = false;
+
+        if (token.size() > 0)
+            success = convertValue(&index, token[0]);
+
+        if (!success || index < 0 || index > (signed int)MAX_VECTOR_INDEX)
+        {
+            if (!success)
+            {
+                orxout(user_error, context::config) << "Config-value '" << this->varname_ << "' in " << this->sectionname_ << " is a vector." << endl;
+            }
+            else
+            {
+                orxout(user_error, context::config) << "Invalid vector-index." << endl;
+            }
+            return false;
+        }
+
+        if (token.size() >= 2)
+            return (this->*function)(index, token.subSet(1).join());
+        else
+            return (this->*function)(index, "");
+    }
+
+    /**
+        @brief Adds a description to the config-value.
+        @param description The description
+    */
+    ConfigValueContainer& ConfigValueContainer::description(const std::string& description)
+    {
+        if (!this->bAddedDescription_)
+        {
+            this->description_ = std::string("ConfigValueDescription::" + this->sectionname_ + "::" + this->varname_);
+            AddLanguageEntry(this->description_, description);
+            this->bAddedDescription_ = true;
+        }
+        return (*this);
+    }
+
+    /**
+        @brief Returns the description of the config-value.
+        @return The description
+    */
+    const std::string& ConfigValueContainer::getDescription() const
+    {
+        return GetLocalisation(this->description_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueContainer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueContainer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueContainer.h	(revision 11817)
@@ -0,0 +1,305 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+    @brief Declaration of the ConfigValueContainer class, caches a config-value.
+
+    The ConfigValueContainer class contains all needed information about a configurable variable:
+     - the name of the variable
+     - the name of the class the variable belongs to
+     - the default value
+     - the user-specified value
+     - a pointer to the entry in the config-file
+
+    This is needed to assign the configured values to all newly created objects.
+*/
+
+#ifndef _ConfigValueContainer_H__
+#define _ConfigValueContainer_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+#include <vector>
+
+#include "util/MultiType.h"
+#include "core/class/Identifier.h"
+
+namespace orxonox
+{
+    class ConfigValueCallbackBase
+    {
+        public:
+            virtual void call(void* object) = 0;
+            virtual inline ~ConfigValueCallbackBase() {}
+    };
+
+    template <class T>
+    class ConfigValueCallback: public ConfigValueCallbackBase
+    {
+        public:
+            inline ConfigValueCallback(void (T::*function) (void)) : function_(function) {}
+            virtual inline ~ConfigValueCallback() = default;
+            virtual inline void call(void* object) override
+            {
+                if (!IdentifierManager::getInstance().isCreatingHierarchy())
+                    (static_cast<T*>(object)->*this->function_)();
+            }
+
+        private:
+            void (T::*function_) (void);
+    };
+
+
+    /**
+        @brief The ConfigValuecontainer contains all needed information about a configurable variable.
+
+        The ConfigValueContainer class contains all needed information about a configurable variable:
+         - the name of the variable
+         - the name of the class the variable belongs to
+         - the default value
+         - the user-specified value
+         - a pointer to the entry in the config-file
+
+        This is needed to assign the configured values to all newly created objects.
+
+        The container searches for the entry in the config file.
+        If there is an entry, it parses the specified value and assigns it to the variable of the right type.
+        If there is no entry, it adds the entry with the default-value to the section of the variables class.
+        If there is no section, the section and the entry are added to the end of the config-file.
+    */
+    class _CoreExport ConfigValueContainer
+    {
+        public:
+            /**
+                @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
+                @param type The type of the corresponding config-file
+                @param identifier The identifier of the class the variable belongs to
+                @param sectionname Name of the section the configValue should be put in.
+                @param varname The name of the variable
+                @param defvalue The default-value
+                @param value Only needed do determine the right type.
+            */
+            template <class D, class V>
+            ConfigValueContainer(ConfigFileType::Value type, Identifier* identifier, const std::string& sectionname, const std::string& varname, const D& defvalue, const V& value)
+            {
+                this->init(type, identifier, sectionname, varname);
+                this->initValue(static_cast<V>(defvalue));
+            }
+
+            /**
+                @brief Constructor: Converts the default-value to a string, checks the config-file for a changed value, sets the intern value variable.
+                @param type The type of the corresponding config-file
+                @param identifier The identifier of the class the variable belongs to
+                @param sectionname Name of the section the configValue should be put in.
+                @param varname The name of the variable
+                @param defvalue The default-value
+                @param value Only needed do determine the right type.
+            */
+            template <class D, class V>
+            ConfigValueContainer(ConfigFileType::Value type, Identifier* identifier, const std::string& sectionname, const std::string& varname, const std::vector<D>& defvalue, const std::vector<V>& value)
+            {
+                this->init(type, identifier, sectionname, varname);
+
+                this->value_ = V();
+                for (const D& defvalueElement : defvalue)
+                    this->valueVector_.emplace_back(defvalueElement);
+
+                this->initVector();
+            }
+
+            ~ConfigValueContainer();
+
+            /**
+                @brief Returns the configured value.
+                @param value A pointer to the variable to store the value.
+                @param object The object calling this function
+                @return The ConfigValueContainer
+            */
+            template <typename T, class C>
+            ConfigValueContainer& getValue(T* value, C* object)
+            {
+                if ((this->callback_ && object) || this->bContainerIsNew_)
+                {
+                    T temp = *value;
+                    this->value_.getValue(value);
+                    if (this->bContainerIsNew_ || (*value) != temp)
+                    {
+                        this->bContainerIsNew_ = false;
+                        if (this->callback_ && object)
+                            this->callback_->call(object);
+                        else
+                            this->bDoInitialCallback_ = true;
+                    }
+                }
+                else
+                {
+                    this->value_.getValue(value);
+                }
+                return *this;
+            }
+
+            /**
+                @brief Returns the configured vector.
+                @param value A pointer to the vector to store the values.
+                @param object The object calling this function
+                @return The ConfigValueContainer
+            */
+            template <typename T, class C>
+            ConfigValueContainer& getValue(std::vector<T>* value, C* object)
+            {
+                if ((this->callback_ && object) || this->bContainerIsNew_)
+                {
+                    if (this->bContainerIsNew_)
+                        this->bContainerIsNew_ = false;
+
+                    std::vector<T> temp = *value;
+                    value->clear();
+                    for (const MultiType& vectorEntry : this->valueVector_)
+                        value->push_back(vectorEntry);
+
+                    if (value->size() != temp.size())
+                    {
+                        if (this->callback_ && object)
+                            this->callback_->call(object);
+                        else
+                            this->bDoInitialCallback_ = true;
+                    }
+                    else
+                    {
+                        for (unsigned int i = 0; i < value->size(); ++i)
+                        {
+                            if ((*value)[i] != temp[i])
+                            {
+                                if (this->callback_ && object)
+                                    this->callback_->call(object);
+                                else
+                                    this->bDoInitialCallback_ = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    value->clear();
+                    for (const MultiType& vectorEntry : this->valueVector_)
+                        value->push_back(vectorEntry);
+                }
+                return *this;
+            }
+
+            /// Returns the name of this container.
+            inline const std::string& getName() const
+                { return this->varname_; }
+            /// Returns the name of the section this config value is in.
+            inline const std::string& getSectionName() const
+                { return this->sectionname_; }
+            /// Returns the associated identifier (can be nullptr).
+            inline Identifier* getIdentifier() const
+                { return this->identifier_; }
+            /// Returns true if this config-value is a vector.
+            inline bool isVector() const
+                { return this->bIsVector_; }
+            /// Returns the vectors size (or zero if it's not a vector).
+            inline unsigned int getVectorSize() const
+                { return this->valueVector_.size(); }
+
+            ConfigValueContainer& description(const std::string& description);
+            const std::string& getDescription() const;
+
+            /**
+                @brief Adds a callback function, that gets called after getValue() if the newly assigned value differs from the old value of the variable.
+                @param object The object to call the function
+                @param function The callback function
+            */
+            template <class T>
+            inline ConfigValueContainer& callback(T* object, void (T::*function) (void))
+            {
+                if (!this->callback_)
+                {
+                    this->callback_ = new ConfigValueCallback<T>(function);
+
+                    if (this->bDoInitialCallback_)
+                    {
+                        this->bDoInitialCallback_ = false;
+                        this->callback_->call(object);
+                    }
+                }
+
+                return (*this);
+            }
+
+            bool set(const MultiType& input);
+            bool tset(const MultiType& input);
+
+            bool set(unsigned int index, const MultiType& input);
+            bool tset(unsigned int index, const MultiType& input);
+            bool add(const MultiType& input);
+            bool remove(unsigned int index);
+
+            bool reset();
+            void update();
+
+            /// Converts the config-value to a string.
+            inline std::string toString() const
+                { return this->value_; }
+            /// Returns the typename of the assigned config-value.
+            inline std::string getTypename() const
+                { return this->value_.getTypename(); }
+
+        private:
+            void init(ConfigFileType::Value type, Identifier* identifier, const std::string& sectionname, const std::string& varname);
+            void initValue(const MultiType& defvalue);
+            void initVector();
+            bool callFunctionWithIndex(bool (ConfigValueContainer::* function) (unsigned int, const MultiType&), const std::string& input);
+
+            bool                       bIsVector_;                  //!< True if the container contains a std::vector
+
+            ConfigFileType::Value      type_;                       //!< The type of the corresponding config-file
+            Identifier*                identifier_;                 //!< The identifier of the class
+            std::string                sectionname_;                //!< The name of the class the variable belongs to
+            std::string                varname_;                    //!< The name of the variable
+            std::string                defvalueString_;             //!< The string of the default-value
+            std::vector<std::string>   defvalueStringVector_;       //!< A vector, containg the strings of the default-values in case we're storing a vector
+
+            MultiType                  value_;                      //!< The value
+            std::vector<MultiType>     valueVector_;                //!< A vector, containg the values in case we're storing a vector
+
+            bool                       bAddedDescription_;          //!< True if a description was added
+            LanguageEntryLabel         description_;                //!< The description
+            ConfigValueCallbackBase*   callback_;                   //!< A callback function to call after getValue if the value changed
+
+            bool                       bContainerIsNew_;            //!< True if it's the first time getValue() gets called
+            bool                       bDoInitialCallback_;         //!< True if the callback should be called as soon as it gets created
+    };
+}
+
+#endif /* _ConfigValueContainer_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/ConfigValueIncludes.h	(revision 11817)
@@ -0,0 +1,272 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder (functions)
+ *
+ */
+
+/**
+    @defgroup ConfigFile Config file
+    @ingroup Config
+*/
+
+/**
+    @file
+    @ingroup Config ConfigFile
+    @brief Definition of macros and functions for config-values.
+
+    An example of how to use SetConfigValue():
+
+    Definition of a class in the header-file:
+    @code
+    class MyClass : public BaseObject
+    {
+        public:
+            MyClass();              // Constructor
+            void setConfigValues(); // Inherited function
+
+            const std::string& getName()
+                { return this->name_; }
+
+            float getVersion()
+                { return this->version_; }
+
+        private:
+            std::string name_;
+            float version_;
+    };
+    @endcode
+
+    Implementation of the class source-file:
+    @code
+    MyClass::MyClass()
+    {
+        // Macro-call to create an Identifier
+        RegisterObject(MyClass);
+
+        // Function-call to assign the config-values to the new object
+        this->setConfigValues();
+    }
+
+    void MyClass::setConfigValues()
+    {
+        SetConfigValue(name_, "Orxonox").description("The name of the game");
+        SetConfigValue(version_, "1.0").description("The version-number");
+    }
+    @endcode
+
+    Extract of orxonox.ini:
+    @code
+    [MyClass]
+    name_ = "Orxonox"
+    version_ = 1.1 // We have changed this value from 1.0 to 1.1
+    @endcode
+
+    Some other code:
+    @code
+    MyObject orxonoxobject;
+    orxout() << "Name:    " << orxonoxobject.getName() << endl;
+    orxout() << "Version: " << orxonoxobject.getVersion() << endl;
+    @endcode
+
+    Output:
+    @code
+    Name:    Orxonox
+    Version: 1.1
+    @endcode
+*/
+
+#ifndef _ConfigValueIncludes_H__
+#define _ConfigValueIncludes_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/class/Identifier.h"
+#include "ConfigValueContainer.h"
+
+namespace orxonox
+{
+    /** Sets a runtime configurable value.
+        If the container for the value doesn't yet exist, a new one is created.
+        Also, the @a variable argument will be modified and set to the new value (default or from ini file).
+    @param object
+        Class instance that the config value should belong to (usually just 'this')
+    @param variable
+        Pointer to the variable where the value should be written to
+    @param type
+        Type of the config file, usually ConfigFileType::Settings
+    @param sectionName
+        Name of the section in the ini file (e.g. [MySection])
+    @param entryName
+        Name of the entry in the ini file (e.g. [MySection] myValue)
+    @param defaultValue
+        Value to be used if it cannot be read from the ini file
+    */
+    template <class T, class D, class V>
+    inline ConfigValueContainer& setConfigValueGeneric(T* object, V* variable, ConfigFileType::Value type, const std::string& sectionName, const std::string& entryName, const D& defaultValue)
+    {
+        ConfigValueContainer* container = ClassIdentifier<T>::getIdentifier()->getConfigValueContainer(entryName);
+        if (!container)
+        {
+            container = new ConfigValueContainer(type, ClassIdentifier<T>::getIdentifier(), sectionName, entryName, defaultValue, *variable);
+            ClassIdentifier<T>::getIdentifier()->addConfigValueContainer(entryName, container);
+        }
+        return container->getValue(variable, object);
+    }
+}
+
+/** Sets a runtime configurable value (simplified macro version of setConfigValueGeneric)
+    If the container for the value doesn't yet exist, a new one is created.
+    Also, the @a varname argument will be modified and set to the new value (default or from ini file).
+@param varname
+    Variable name as C++ identifier. It will be used as entry name and as variable pointer
+@param defaultValue
+    Value to be used if it cannot be read from the ini file
+*/
+#define SetConfigValue(varname, defaultValue) \
+    orxonox::setConfigValueGeneric(this, &varname, ConfigFileType::Settings, this->getIdentifier()->getName(), #varname, defaultValue)
+
+/** Sets a runtime configurable value (simplified macro version of setConfigValueGeneric)
+    If the container for the value doesn't yet exist, a new one is created.
+    Also, the @a varname argument will be modified and set to the new value (default or from ini file).
+@param variable
+    Variable name as C++ identifier.
+@param entryName
+    Name of the entry in the ini file (e.g. [MySection] myValue)
+@param defaultValue
+    Value to be used if it cannot be read from the ini file
+*/
+#define SetConfigValueAlias(variable, entryName, defaultValue) \
+    orxonox::setConfigValueGeneric(this, &variable, ConfigFileType::Settings, this->getIdentifier()->getName(), entryName, defaultValue)
+
+/** Sets a runtime configurable value (simplified macro version of setConfigValueGeneric)
+    If the container for the value doesn't yet exist, a new one is created.
+    Also, the @a varname argument will be modified and set to the new value (default or from ini file).
+@param variable
+    Variable name as C++ identifier.
+@param sectionName
+    Name of the section in the ini file (e.g. [MySection])
+@param entryName
+    Name of the entry in the ini file (e.g. [MySection] myValue)
+@param defaultValue
+    Value to be used if it cannot be read from the ini file
+*/
+#define SetConfigValueExternal(variable, sectionName, entryName, defaultValue) \
+    orxonox::setConfigValueGeneric(this, &variable, ConfigFileType::Settings, sectionName, entryName, defaultValue)
+
+
+namespace orxonox
+{
+    /** Resets a runtime configurable value to its default.
+        If the container for the value doesn't yet exist, a warning is displayed.
+        Also, the @a variable argument will be modified and set to the default value.
+    @param object
+        Class instance that the config value should belong to (usually just 'this')
+    @param variable
+        Pointer to the variable where the value should be written to
+    @param entryName
+        Name of the entry in the ini file (e.g. [MySection] myValue)
+    */
+    template <class T, class V>
+    inline void resetConfigValueGeneric(T* object, V* variable, const std::string& entryName)
+    {
+        ConfigValueContainer* container = ClassIdentifier<T>::getIdentifier()->getConfigValueContainer(entryName);
+        if (container)
+        {
+            container->reset();
+            container->getValue(variable, object);
+        }
+        else
+        {
+            orxout(user_warning, context::config) << "Couldn't reset config-value '" << entryName << "' in class '"
+                                                  << ClassIdentifier<T>::getIdentifier()->getName() << "', corresponding container doesn't exist." << endl;
+        }
+    }
+}
+
+/** Resets a runtime configurable value to its default (simplified macro version of modifyConfigValueGeneric)
+    If the container for the value doesn't yet exist, a warning is displayed.
+    Also, the @a varname argument will be modified and set to the default value.
+@param varname
+    Variable name as C++ identifier. It will be used as entry name and as variable pointer
+*/
+#define ResetConfigValue(varname) \
+    orxonox::resetConfigValueGeneric(this, &varname, #varname)
+
+
+/** Modifies a runtime configurable value by using a modifier and some arguments.
+    If the container for the value doesn't yet exist, a warning is displayed.
+    Also, the @a variable argument will be modified and set to the current value.
+@param object
+    Class instance that the config value should belong to (usually just 'this')
+@param variable
+    Pointer to the variable where the value should be written to
+@param entryName
+    Name of the entry in the ini file (e.g. [MySection] myValue)
+@param modifier
+    On of these functions: set, tset, add, remove, reset, update
+@param ...
+    Arguments for the modifier function
+*/
+#define ModifyConfigValueGeneric(object, variable, entryName, modifier, ...) \
+    if (orxonox::ConfigValueContainer* container = ClassByObjectType(object)->getConfigValueContainer(entryName)) \
+    { \
+        container->modifier(__VA_ARGS__); \
+        container->getValue(variable, object); \
+    } \
+    else \
+    { \
+        orxout(user_warning, context::config) << "Couldn't modify config-value '" << entryName << "' in class '" \
+                                              << ClassByObjectType(object)->getName() << "', corresponding container doesn't exist." << endl; \
+    }
+
+/** Modifies a runtime configurable value by using a modifier and some arguments.
+    If the container for the value doesn't yet exist, a warning is displayed.
+    Also, the @a varname argument will be modified and set to the current value.
+@param varname
+    Variable name as C++ identifier. It will be used as entry name and as variable pointer
+@param modifier
+    On of these functions: set, tset, add, remove, reset, update
+@param ...
+    Arguments for the modifier function
+*/
+#define ModifyConfigValue(varname, modifier, ...) \
+    ModifyConfigValueGeneric(this, &varname, #varname, modifier, __VA_ARGS__)
+
+/** Modifies a runtime configurable value by using a modifier and some arguments.
+    If the container for the value doesn't yet exist, a warning is displayed.
+    Also, the @a variable argument will be modified and set to the current value.
+@param variable
+    Pointer to the variable where the value should be written to
+@param entryName
+    Name of the entry in the ini file (e.g. [MySection] myValue)
+@param modifier
+    On of these functions: set, tset, add, remove, reset, update
+@param ...
+    Arguments for the modifier function
+*/
+#define ModifyConfigValueExternal(variable, entryName, modifier, ...) \
+    ModifyConfigValueGeneric(this, &variable, entryName, modifier, __VA_ARGS__)
+
+#endif /* _ConfigValueIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/Configurable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/Configurable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/Configurable.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Configurable.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(Configurable).virtualBase();
+
+    Configurable::Configurable()
+    {
+        RegisterObject(Configurable);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/Configurable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/Configurable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/Configurable.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+    @brief Declaration of Configurable, the base class of all objects which may contain config values.
+*/
+
+#ifndef _Configurable_H__
+#define _Configurable_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    /**
+        @brief This is the base class of all objects which may contain config values
+    */
+    class _CoreExport Configurable : virtual public Listable
+    {
+        public:
+            Configurable();
+
+            /// Function to collect the SetConfigValue-macro calls.
+            void setConfigValues() {};
+    };
+}
+
+#endif /* _Configurable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/SettingsConfigFile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/SettingsConfigFile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/SettingsConfigFile.cc	(revision 11817)
@@ -0,0 +1,277 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of SettingsConfigFile.
+*/
+
+#include "SettingsConfigFile.h"
+
+#include "util/StringUtils.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "ConfigFileManager.h"
+#include "ConfigValueContainer.h"
+
+namespace orxonox
+{
+    ////////////////////////
+    // SettingsConfigFile //
+    ////////////////////////
+
+    static const std::string __CC_load_name = "reloadSettings";
+    static const std::string __CC_setFilename_name = "setSettingsFile";
+    static const std::string __CC_config_name = "config";
+    static const std::string __CC_tconfig_name = "tconfig";
+    static const std::string __CC_getConfig_name = "getConfig";
+
+    SetConsoleCommand(__CC_load_name,            &ConfigFile::load);
+    SetConsoleCommand(__CC_setFilename_name,     &SettingsConfigFile::setFilename);
+    SetConsoleCommand(__CC_config_name,          &SettingsConfigFile::config).argumentCompleter(0, autocompletion::settingssections()).argumentCompleter(1, autocompletion::settingsentries()).argumentCompleter(2, autocompletion::settingsvalue());
+    SetConsoleCommand(__CC_tconfig_name,         &SettingsConfigFile::tconfig).argumentCompleter(0, autocompletion::settingssections()).argumentCompleter(1, autocompletion::settingsentries()).argumentCompleter(2, autocompletion::settingsvalue());
+    SetConsoleCommand(__CC_getConfig_name,       &SettingsConfigFile::getConfig).argumentCompleter(0, autocompletion::settingssections()).argumentCompleter(1, autocompletion::settingsentries());
+
+    SettingsConfigFile* SettingsConfigFile::singletonPtr_s = nullptr;
+
+    /**
+        @brief Constructor: Activates the console commands.
+    */
+    SettingsConfigFile::SettingsConfigFile(const std::string& filename)
+        : ConfigFile(filename)
+    {
+        ModifyConsoleCommand(__CC_load_name).setObject(this);
+        ModifyConsoleCommand(__CC_setFilename_name).setObject(this);
+        ModifyConsoleCommand(__CC_config_name).setObject(this);
+        ModifyConsoleCommand(__CC_tconfig_name).setObject(this);
+        ModifyConsoleCommand(__CC_getConfig_name).setObject(this);
+    }
+
+    /**
+        @brief Destructor: Deactivates the console commands.
+    */
+    SettingsConfigFile::~SettingsConfigFile()
+    {
+        ModifyConsoleCommand(__CC_load_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_setFilename_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_config_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_tconfig_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_getConfig_name).setObject(nullptr);
+    }
+
+    /**
+        @brief Loads the config file and updates the @ref ConfigValueContainer "config value containers".
+    */
+    void SettingsConfigFile::load()
+    {
+        ConfigFile::load();
+        this->updateConfigValues();
+    }
+
+    /**
+        @brief Changes the file-name.
+    */
+    void SettingsConfigFile::setFilename(const std::string& filename)
+    {
+        ConfigFileManager::getInstance().setFilename(ConfigFileType::Settings, filename);
+    }
+
+    /**
+        @brief Registers a new @ref ConfigValueContainer "config value container".
+    */
+    void SettingsConfigFile::addConfigValueContainer(ConfigValueContainer* container)
+    {
+        if (container == nullptr)
+            return;
+        std::pair<std::string, ConfigValueContainer*> second(getLowercase(container->getName()), container);
+        this->containers_.insert(std::make_pair(getLowercase(container->getSectionName()), second));
+        this->sectionNames_.insert(container->getSectionName());
+    }
+
+    /**
+        @brief Unregisters a @ref ConfigValueContainer "config value container".
+    */
+    void SettingsConfigFile::removeConfigValueContainer(ConfigValueContainer* container)
+    {
+        if (container == nullptr)
+            return;
+        const std::string& sectionLC = getLowercase(container->getSectionName());
+        ContainerMap::iterator upper = this->containers_.upper_bound(sectionLC);
+        for (ContainerMap::iterator it = this->containers_.lower_bound(sectionLC); it != upper; ++it)
+        {
+            if (it->second.second == container)
+            {
+                // Remove entry from section name set this was the last container for that section
+                if (upper == this->containers_.lower_bound(sectionLC))
+                    this->sectionNames_.erase(container->getSectionName());
+                this->containers_.erase(it);
+                break;
+            }
+        }
+    }
+
+    /**
+        @brief Updates all @ref ConfigValueContainer "config value containers".
+    */
+    void SettingsConfigFile::updateConfigValues()
+    {
+        // todo: can this be done more efficiently? looks like some identifiers will be updated multiple times.
+
+        for (const auto& mapEntry : this->containers_)
+        {
+            mapEntry.second.second->update();
+            mapEntry.second.second->getIdentifier()->updateConfigValues();
+        }
+    }
+
+    /**
+        @brief Removes entries and sections from the file that don't exist anymore (i.e. if there's no corresponding @ref ConfigValueContainer "config value container").
+        @param bCleanComments If true, comments are also removed from the file
+    */
+    void SettingsConfigFile::clean(bool bCleanComments)
+    {
+        for (std::list<ConfigFileSection*>::iterator itSection = this->sections_.begin(); itSection != this->sections_.end(); )
+        {
+            const std::string& sectionLC = getLowercase((*itSection)->getName());
+            ContainerMap::const_iterator lower = this->containers_.lower_bound(sectionLC);
+            ContainerMap::const_iterator upper = this->containers_.upper_bound(sectionLC);
+            if (lower != upper)
+            {
+                // The section exists, delete comment
+                if (bCleanComments)
+                    (*itSection)->setComment("");
+                for (std::list<ConfigFileEntry*>::iterator itEntry = (*itSection)->entries_.begin(); itEntry != (*itSection)->entries_.end(); )
+                {
+                    const std::string& entryLC = getLowercase((*itEntry)->getName());
+                    bool bFound = false;
+                    for (ContainerMap::const_iterator itContainer = lower; itContainer != upper; ++itContainer)
+                    {
+                        if (itContainer->second.first == entryLC)
+                        {
+                            // The config-value exists, delete comment
+                            if (bCleanComments)
+                                (*itEntry)->setComment("");
+                            ++itEntry;
+                            bFound = true;
+                            break;
+                        }
+                    }
+                    if (!bFound)
+                    {
+                        // The config-value doesn't exist
+                        delete (*itEntry);
+                        (*itSection)->entries_.erase(itEntry++);
+                    }
+                }
+                ++itSection;
+            }
+            else
+            {
+                // The section doesn't exist
+                delete (*itSection);
+                this->sections_.erase(itSection++);
+            }
+        }
+
+        // Save the file
+        this->save();
+    }
+
+    /**
+        @brief Console-command: Changes the value of an entry and stores it the file.
+
+        @param section  The section of the config value
+        @param entry    The name of the config value
+        @param value    The new value
+    */
+    void SettingsConfigFile::config(const std::string& section, const std::string& entry, const std::string& value)
+    {
+        if (!this->configImpl(section, entry, value, &ConfigValueContainer::set))
+            orxout(user_error, context::config) << "Config value \"" << entry << "\" in section \"" << section << "\" doesn't exist." << endl;
+    }
+
+    /**
+        @brief Console-command: Changes the value of an entry, but doesn't store it in the file (it's only a temporary change).
+
+        @param section  The section of the config value
+        @param entry    The name of the config value
+        @param value    The new value
+    */
+    void SettingsConfigFile::tconfig(const std::string& section, const std::string& entry, const std::string& value)
+    {
+        if (!this->configImpl(section, entry, value, &ConfigValueContainer::tset))
+            orxout(user_error, context::config) << "Config value \"" << entry << "\" in section \"" << section << "\" doesn't exist." << endl;
+    }
+
+    /**
+        @brief Changes the value of an entry, depending on @a function, either by using "set" or "tset"
+
+        @param section  The section of the config value
+        @param entry    The name of the config value
+        @param value    The new value
+        @param function The function ("set" or "tset") that will be used to change the value.
+    */
+    bool SettingsConfigFile::configImpl(const std::string& section, const std::string& entry, const std::string& value, bool (ConfigValueContainer::*function)(const MultiType&))
+    {
+        const std::string& sectionLC = getLowercase(section);
+        const std::string& entryLC = getLowercase(entry);
+        ContainerMap::iterator upper = this->containers_.upper_bound(sectionLC);
+        for (ContainerMap::iterator it = this->containers_.lower_bound(sectionLC); it != upper; ++it)
+        {
+            // Note: Config value vectors cannot be supported
+            if (it->second.first == entryLC && !it->second.second->isVector())
+            {
+                return (it->second.second->*function)(value);
+            }
+        }
+        return false;
+    }
+
+    /**
+        @brief Console-command: Returns the value of a given entry.
+
+        @param section  The section of the config value
+        @param entry    The name of the config value
+    */
+    std::string SettingsConfigFile::getConfig(const std::string& section, const std::string& entry)
+    {
+        const std::string& sectionLC = getLowercase(section);
+        const std::string& entryLC = getLowercase(entry);
+        ContainerMap::iterator upper = this->containers_.upper_bound(sectionLC);
+        for (ContainerMap::iterator it = this->containers_.lower_bound(sectionLC); it != upper; ++it)
+        {
+            // Note: Config value vectors cannot be supported
+            if (it->second.first == entryLC && ! it->second.second->isVector())
+            {
+                std::string value;
+                it->second.second->getValue<std::string, void>(&value, nullptr);
+                return value;
+            }
+        }
+        return "";
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/config/SettingsConfigFile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/config/SettingsConfigFile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/config/SettingsConfigFile.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Config ConfigFile
+*/
+
+#ifndef _SettingsConfigFile_H__
+#define _SettingsConfigFile_H__
+
+#include "core/CorePrereqs.h"
+
+#include <set>
+#include <map>
+#include "ConfigFile.h"
+#include "util/Singleton.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    ////////////////////////
+    // SettingsConfigFile //
+    ////////////////////////
+    /**
+        @brief Child class of ConfigFile, used to store the settings of the game.
+
+        In addition to ConfigFile, this class provides an interface to manipulate the settings
+        with console commands and to cache entries in instances of ConfigValueContainer.
+
+        SettingsConfigFile is a Singleton, meaning there's only one instance of this class
+        (and thus only one config file that stores settings).
+    */
+    class _CoreExport SettingsConfigFile // tolua_export
+        : public ConfigFile, public Singleton<SettingsConfigFile>
+    { // tolua_export
+        friend class Singleton<SettingsConfigFile>;
+
+        public:
+            typedef std::multimap<std::string, std::pair<std::string, ConfigValueContainer*>> ContainerMap;
+
+            SettingsConfigFile(const std::string& filename);
+            ~SettingsConfigFile();
+
+            virtual void load() override; // tolua_export
+            void setFilename(const std::string& filename); // tolua_export
+            void clean(bool bCleanComments = false); // tolua_export
+
+            void config(const std::string& section, const std::string& entry, const std::string& value); // tolua_export
+            void tconfig(const std::string& section, const std::string& entry, const std::string& value); // tolua_export
+            std::string getConfig(const std::string& section, const std::string& entry); // tolua_export
+
+            void addConfigValueContainer(ConfigValueContainer* container);
+            void removeConfigValueContainer(ConfigValueContainer* container);
+
+            /// Returns a set containing the names of all sections in this config file.
+            inline const std::set<std::string>& getSectionNames()
+                { return this->sectionNames_; }
+            /// Returns the lower-bound-iterator of the @ref ConfigValueContainer "config value containers" for the given section.
+            inline ContainerMap::const_iterator getContainerLowerBound(const std::string section)
+                { return this->containers_.lower_bound(section); }
+            /// Returns the upper-bound-iterator of the @ref ConfigValueContainer "config value containers" for the given section.
+            inline ContainerMap::const_iterator getContainerUpperBound(const std::string section)
+                { return this->containers_.upper_bound(section); }
+
+            static SettingsConfigFile& getInstance() { return Singleton<SettingsConfigFile>::getInstance(); } // tolua_export
+
+        private:
+            void updateConfigValues();
+            bool configImpl(const std::string& section, const std::string& entry, const std::string& value, bool (ConfigValueContainer::*function)(const MultiType&));
+
+            ContainerMap containers_;                   ///< Stores all @ref ConfigValueContainer "config value containers"
+            std::set<std::string> sectionNames_;        ///< Stores all section names
+            static SettingsConfigFile* singletonPtr_s;  ///< The singleton pointer
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _SettingsConfigFile_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/Button.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/Button.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/Button.cc	(revision 11817)
@@ -0,0 +1,276 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the different input handlers.
+*/
+
+#include "Button.h"
+
+#include "util/Convert.h"
+#include "util/SubString.h"
+#include "util/StringUtils.h"
+#include "util/Output.h"
+#include "core/command/ConsoleCommand.h"
+#include "core/command/CommandEvaluation.h"
+#include "core/command/CommandExecutor.h"
+#include "core/config/ConfigFile.h"
+
+namespace orxonox
+{
+    /**
+    @note
+        bButtonThresholdUser_: We set it to true so that setConfigValues in KeyBinder sets the value
+        correctly the first time. It is then set to false first and changed later in Button::parse().
+    */
+    Button::Button()
+        : bButtonThresholdUser_(false)
+        , paramCommandBuffer_(nullptr)
+    {
+        nCommands_[0]=0;
+        nCommands_[1]=0;
+        nCommands_[2]=0;
+    }
+
+    Button::~Button()
+    {
+        this->clear();
+    }
+
+    void Button::clear()
+    {
+        for (unsigned int j = 0; j < 3; j++)
+        {
+            if (nCommands_[j])
+            {
+                // delete all commands and the command pointer array
+                for (unsigned int i = 0; i < nCommands_[j]; i++)
+                    delete commands_[j][i];
+                delete[] commands_[j];
+                commands_[j] = nullptr;
+                nCommands_[j] = 0;
+            }
+        }
+        this->bindingString_.clear();
+    }
+
+    void Button::readBinding(ConfigFile* configFile, ConfigFile* fallbackFile)
+    {
+        std::string binding = configFile->getOrCreateValue(groupName_, name_, "", true);
+        if (binding.empty() && fallbackFile)
+            binding = fallbackFile->getValue(groupName_, name_, true);
+        this->parse(binding);
+    }
+
+    void Button::setBinding(ConfigFile* configFile, ConfigFile* fallbackFile, const std::string& binding, bool bTemporary)
+    {
+        if (!bTemporary)
+            configFile->setValue(groupName_, name_, binding, true);
+        this->parse(binding);
+    }
+
+    void Button::parse(const std::string& binding)
+    {
+        if (binding == this->bindingString_)
+            return;
+
+        // delete all commands
+        clear();
+        this->bindingString_ = binding;
+
+        if (isEmpty(bindingString_) || removeTrailingWhitespaces(getLowercase(binding)) == "nobinding")
+            return;
+
+        // reset this to false first when parsing (was true before when parsing for the first time)
+        bButtonThresholdUser_ = false;
+
+        // use std::vector for a temporary dynamic array
+        std::vector<BaseCommand*> commands[3];
+
+        // separate the commands
+        SubString commandStrings(bindingString_, "|", SubString::WhiteSpaces, false,
+            '\\', false, '"', false, '{', '}', false, '\0');
+
+        for (unsigned int iCommand = 0; iCommand < commandStrings.size(); iCommand++)
+        {
+            if (!commandStrings[iCommand].empty())
+            {
+                SubString tokens(commandStrings[iCommand], " ", SubString::WhiteSpaces, false,
+                    '\\', false, '"', false, '{', '}', false, '\0');
+
+                KeybindMode::Value mode = KeybindMode::None;
+                float paramModifier = 1.0f;
+                std::string commandStr;
+                bool forceArguments = false;
+
+                for (unsigned int iToken = 0; iToken < tokens.size(); ++iToken)
+                {
+                    const std::string& token = getLowercase(tokens[iToken]);
+
+                    if (token == "onpress")
+                        mode = KeybindMode::OnPress;
+                    else if (token == "onrelease")
+                        mode = KeybindMode::OnRelease;
+                    else if (token == "onpressandrelease")
+                        mode = KeybindMode::OnPressAndRelease;
+                    else if (token == "onhold")
+                        mode = KeybindMode::OnHold;
+                    else if (token == "forcearguments")
+                        forceArguments = true;
+                    else if (token == "buttonthreshold")
+                    {
+                        // for real axes, we can feed a ButtonThreshold argument
+                        ++iToken;
+                        if (iToken == tokens.size())
+                            continue;
+                        // may fail, but doesn't matter (default value already set)
+                        if (!convertValue(&buttonThreshold_, tokens[iToken + 1]))
+                            parseError("Could not parse 'ButtonThreshold' argument. \
+                                Switching to default value.", true);
+                        else
+                            this->bButtonThresholdUser_ = true;
+                    }
+                    else if (token == "scale")
+                    {
+                        ++iToken;
+                        if (iToken == tokens.size() || !convertValue(&paramModifier, tokens[iToken]))
+                            parseError("Could not parse 'scale' argument. Switching to default value.", true);
+                    }
+                    else
+                    {
+                        // no input related argument
+                        // we interpret everything from here as a command string
+                        while (iToken != tokens.size())
+                            commandStr += tokens[iToken++] + ' ';
+                    }
+                }
+
+                if (commandStr.empty())
+                {
+                    parseError("No command string given.", false);
+                    continue;
+                }
+
+                // evaluate the command
+                CommandEvaluation eval = CommandExecutor::evaluate(commandStr);
+                if (!eval.isValid() || eval.evaluateArguments(true))
+                {
+                    parseError("Command evaluation of \"" + commandStr + "\"failed.", true);
+                    continue;
+                }
+
+                // check for param command
+                int paramIndex = eval.getConsoleCommand()->getInputConfiguredParam();
+                if (paramIndex >= 0 && !forceArguments)
+                {
+                    // parameter supported command
+                    ParamCommand* cmd = new ParamCommand();
+                    cmd->scale_ = paramModifier;
+
+                    // add command to the buffer if not yet existing
+                    for (BufferedParamCommand* command : *paramCommandBuffer_)
+                    {
+                        if (command->evaluation_.getConsoleCommand()
+                            == eval.getConsoleCommand())
+                        {
+                            // already in list
+                            cmd->paramCommand_ = command;
+                            break;
+                        }
+                    }
+                    if (cmd->paramCommand_ == nullptr)
+                    {
+                        cmd->paramCommand_ = new BufferedParamCommand();
+                        paramCommandBuffer_->push_back(cmd->paramCommand_);
+                        cmd->paramCommand_->evaluation_ = eval;
+                        cmd->paramCommand_->paramIndex_ = paramIndex;
+                    }
+
+
+                    // we don't know whether this is an actual axis or just a button
+                    if (mode != KeybindMode::None || !addParamCommand(cmd))
+                        this->addCommand(cmd, mode, commands);
+                }
+                else
+                {
+                    SimpleCommand* cmd = new SimpleCommand();
+                    cmd->evaluation_ = eval;
+
+                    this->addCommand(cmd, mode, commands);
+                }
+            }
+        }
+
+        for (unsigned int j = 0; j < 3; j++)
+        {
+            nCommands_[j] = commands[j].size();
+            if (nCommands_[j])
+            {
+                commands_[j] = new BaseCommand*[nCommands_[j]];
+                for (unsigned int i = 0; i < commands[j].size(); i++)
+                    commands_[j][i] = commands[j][i];
+            }
+            else
+                commands_[j] = nullptr;
+        }
+    }
+
+    inline void Button::addCommand(BaseCommand* cmd, KeybindMode::Value mode, std::vector<BaseCommand*> commands[3])
+    {
+        if (mode == KeybindMode::None)
+            mode = cmd->getEvaluation()->getConsoleCommand()->getKeybindMode();
+        else
+            cmd->setFixedKeybindMode(true);
+
+        if (mode == KeybindMode::OnPressAndRelease)
+        {
+            BaseCommand* cmd2 = cmd->clone();
+
+            commands[KeybindMode::OnPress].push_back(cmd);
+            commands[KeybindMode::OnRelease].push_back(cmd2); // clone
+        }
+        else
+            commands[mode].push_back(cmd);
+    }
+
+    inline void Button::parseError(const std::string& message, bool serious)
+    {
+        if (serious)
+        {
+            orxout(internal_error, context::input) << "Error while parsing binding for button/axis " << this->name_ << ". "
+                << message << endl;
+        }
+        else
+        {
+            orxout(internal_warning, context::input) << "Warning while parsing binding for button/axis " << this->name_ << ". "
+                << message << endl;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/Button.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/Button.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/Button.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Different definitions of input processing.
+*/
+
+#ifndef _Button_H__
+#define _Button_H__
+
+#include "InputPrereqs.h"
+
+#include <string>
+#include <vector>
+#include "InputCommands.h"
+
+namespace orxonox
+{
+    class _CoreExport Button
+    {
+    public:
+        Button();
+        virtual ~Button();
+        virtual void clear();
+        virtual bool addParamCommand(ParamCommand* command) { return false; }
+        void parse(const std::string& binding);
+        void readBinding(ConfigFile* configFile, ConfigFile* fallbackFile);
+        void setBinding(ConfigFile* configFile, ConfigFile* fallbackFile, const std::string& binding, bool bTemporary);
+        bool execute(KeybindMode::Value mode, float abs = 1.0f, float rel = 1.0f);
+
+        //! The configured string value
+        std::string bindingString_;
+        //! Name of the trigger as strings
+        std::string name_;
+        //! Name of the group of input triggers
+        std::string groupName_;
+        //! Basic commands for OnPress, OnHold and OnRelease
+        BaseCommand** commands_[3];
+        //! Number of basic commands
+        unsigned int nCommands_[3];
+        //! Says how much it takes for an analog axis to trigger a button
+        //! Note: This variable is here to have only one parse() function.
+        float buttonThreshold_;
+        bool bButtonThresholdUser_;
+        //! Pointer to the list of parametrised commands
+        std::vector<BufferedParamCommand*>* paramCommandBuffer_;
+
+    private:
+        void parseError(const std::string& message, bool serious);
+        void addCommand(BaseCommand* cmd, KeybindMode::Value mode, std::vector<BaseCommand*> commands[3]);
+    };
+
+    inline bool Button::execute(KeybindMode::Value mode, float abs, float rel)
+    {
+        // execute all the parsed commands in the string
+        for (unsigned int iCommand = 0; iCommand < nCommands_[mode]; iCommand++)
+            commands_[mode][iCommand]->execute(abs, rel);
+        return true;
+    }
+
+}
+
+#endif /* _Button_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,15 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  Button.cc
+  HalfAxis.cc
+  InputBuffer.cc
+  InputCommands.cc
+  InputManager.cc
+  InputState.cc
+  JoyStick.cc
+  JoyStickQuantityListener.cc
+  KeyBinder.cc
+  KeyBinderManager.cc
+  Keyboard.cc
+  KeyDetector.cc
+  Mouse.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/HalfAxis.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/HalfAxis.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/HalfAxis.cc	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the different input handlers.
+*/
+
+#include "HalfAxis.h"
+#include "core/command/CommandEvaluation.h"
+
+namespace orxonox
+{
+    void HalfAxis::clear()
+    {
+        Button::clear();
+        if (nParamCommands_)
+        {
+            // delete all commands and the command pointer array
+            for (unsigned int i = 0; i < nParamCommands_; i++)
+                delete paramCommands_[i];
+            delete[] paramCommands_;
+            nParamCommands_ = 0;
+        }
+    }
+
+    bool HalfAxis::addParamCommand(ParamCommand* command)
+    {
+        ParamCommand** cmds = paramCommands_;
+        paramCommands_ = new ParamCommand*[++nParamCommands_];
+        unsigned int i;
+        for (i = 0; i < nParamCommands_ - 1; i++)
+            paramCommands_[i] = cmds[i];
+        paramCommands_[i] = command;
+        if (nParamCommands_ > 1)
+            delete[] cmds;
+        return true;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/HalfAxis.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/HalfAxis.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/HalfAxis.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Different definitions of input processing.
+*/
+
+#ifndef _HalfAxis_H__
+#define _HalfAxis_H__
+
+#include "InputPrereqs.h"
+
+#include "Button.h"
+#include "InputCommands.h"
+
+namespace orxonox
+{
+    class _CoreExport HalfAxis : public Button
+    {
+    public:
+        HalfAxis()
+            : relVal_(0.0f)
+            , absVal_(0.0f)
+            , paramCommands_(nullptr)
+            , nParamCommands_(0)
+            , pressed_(false)
+            , hasChanged_(false)
+        { }
+        using Button::execute;
+        bool execute();
+        virtual bool addParamCommand(ParamCommand* command) override;
+        virtual void clear() override;
+        void reset();
+
+        // axis related
+        float relVal_;
+        float absVal_;
+        ParamCommand** paramCommands_;
+        unsigned int nParamCommands_;
+
+        // button related
+        bool pressed_;
+        bool hasChanged_;
+    };
+
+    inline bool HalfAxis::execute()
+    {
+        bool success = true;
+        for (unsigned int i = 0; i < nParamCommands_; i++)
+            success = paramCommands_[i]->execute(absVal_, relVal_) && success;
+        return success;
+    }
+
+    inline void HalfAxis::reset()
+    {
+        this->relVal_ = 0.0f;
+        this->absVal_ = 0.0f;
+        this->hasChanged_ = true;
+    }
+}
+
+#endif /* _HalfAxis_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputBuffer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputBuffer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputBuffer.cc	(revision 11817)
@@ -0,0 +1,272 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#include "InputBuffer.h"
+
+#include "util/Clipboard.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(InputBuffer);
+
+    InputBuffer::InputBuffer()
+    {
+        RegisterObject(InputBuffer);
+
+        this->cursor_ = 0;
+        this->maxLength_ = 1024;
+        this->allowedChars_ = "abcdefghijklmnopqrstuvwxyz \
+                               ABCDEFGHIJKLMNOPQRSTUVWXYZ \
+                               0123456789 \
+                               \\\"(){}[]<>.:,;_-+*/=!?|$&%^~#";
+
+        this->lastKey_ = KeyCode::Unassigned;
+        this->timeSinceKeyPressed_ = 0.0f;
+        this->timeSinceKeyRepeated_ = 0.0f;
+        this->keysToRepeat_ = 0;
+
+        setConfigValues();
+    }
+
+    InputBuffer::InputBuffer(const std::string& allowedChars)
+    {
+        RegisterObject(InputBuffer);
+
+        this->maxLength_ = 1024;
+        this->allowedChars_ = allowedChars;
+        this->cursor_ = 0;
+
+        this->lastKey_ = KeyCode::Unassigned;
+        this->timeSinceKeyPressed_ = 0.0f;
+        this->timeSinceKeyRepeated_ = 0.0f;
+        this->keysToRepeat_ = 0;
+
+        setConfigValues();
+    }
+
+    InputBuffer::~InputBuffer()
+    {
+        for (BaseInputBufferListenerTuple* listener : this->listeners_)
+            delete listener;
+    }
+
+    void InputBuffer::setConfigValues()
+    {
+        SetConfigValue(keyRepeatDeleay_, 0.4).description("Key repeat delay of the input buffer");
+        SetConfigValue(keyRepeatTime_, 0.022).description("Key repeat time of the input buffer");
+
+        if (keyRepeatDeleay_ < 0.0)
+        {
+            ResetConfigValue(keyRepeatDeleay_);
+        }
+        if (keyRepeatTime_ < 0.0)
+        {
+            ResetConfigValue(keyRepeatTime_);
+        }
+    }
+
+    void InputBuffer::setMaxLength(unsigned int length)
+    {
+        this->maxLength_ = length;
+        if (this->buffer_.size() > length)
+            this->buffer_.resize(length);
+    }
+
+    void InputBuffer::set(const std::string& input, bool update)
+    {
+        this->clear(false);
+        this->insert(input, update);
+    }
+
+    void InputBuffer::insert(const std::string& input, bool update)
+    {
+        for (const char& inputChar : input)
+        {
+            this->insert(inputChar, false);
+
+            if (update)
+                this->updated(inputChar, false);
+        }
+
+        if (update)
+            this->updated();
+    }
+
+    void InputBuffer::insert(const char& input, bool update)
+    {
+        if (this->charIsAllowed(input))
+        {
+            if (this->buffer_.size() >= this->maxLength_)
+                return;
+            this->buffer_.insert(this->cursor_, 1, input);
+            ++this->cursor_;
+        }
+
+        if (update)
+            this->updated(input, true);
+    }
+
+    void InputBuffer::clear(bool update)
+    {
+        this->buffer_.clear();
+        this->cursor_ = 0;
+
+        if (update)
+            this->updated();
+    }
+
+    void InputBuffer::removeBehindCursor(bool update)
+    {
+        if (this->cursor_ > 0)
+        {
+            --this->cursor_;
+            this->buffer_.erase(this->cursor_, 1);
+
+            if (update)
+                this->updated();
+        }
+    }
+
+    void InputBuffer::removeAtCursor(bool update)
+    {
+        if (this->cursor_ < this->buffer_.size())
+        {
+            this->buffer_.erase(this->cursor_, 1);
+
+            if (update)
+                this->updated();
+        }
+    }
+
+    void InputBuffer::updated()
+    {
+        for (BaseInputBufferListenerTuple* listener : this->listeners_)
+        {
+            if (listener->bListenToAllChanges_)
+                listener->callFunction();
+        }
+    }
+
+    void InputBuffer::updated(const char& update, bool bSingleInput)
+    {
+        for (BaseInputBufferListenerTuple* listener : this->listeners_)
+        {
+            if ((!listener->trueKeyFalseChar_) && (listener->bListenToAllChanges_ || (listener->char_ == update)) && (!listener->bOnlySingleInput_ || bSingleInput))
+                listener->callFunction();
+        }
+    }
+
+    bool InputBuffer::charIsAllowed(const char& input)
+    {
+        if (this->allowedChars_.empty())
+            return true;
+        else
+            return (this->allowedChars_.find(input) != std::string::npos);
+    }
+
+
+    void InputBuffer::processKey(const KeyEvent& evt)
+    {
+        // Prevent disaster when switching applications
+        if (evt.isModifierDown(KeyboardModifier::Alt) && evt.getKeyCode() == KeyCode::Tab)
+            return;
+
+        for (BaseInputBufferListenerTuple* listener : this->listeners_)
+        {
+            if (listener->trueKeyFalseChar_ && (listener->key_ == evt.getKeyCode()))
+                listener->callFunction();
+        }
+
+        if (evt.isModifierDown(KeyboardModifier::Ctrl))
+        {
+            if (evt.getKeyCode() == KeyCode::V)
+                this->insert(fromClipboard());
+            else if (evt.getKeyCode() == KeyCode::C)
+                toClipboard(this->buffer_);
+            else if (evt.getKeyCode() == KeyCode::X)
+            {
+                toClipboard(this->buffer_);
+                this->clear();
+            }
+        }
+        else if (evt.isModifierDown(KeyboardModifier::Shift))
+        {
+            if (evt.getKeyCode() == KeyCode::Insert)
+                this->insert(fromClipboard());
+            else if (evt.getKeyCode() == KeyCode::Delete)
+            {
+                toClipboard(this->buffer_);
+                this->clear();
+            }
+        }
+
+        this->insert(static_cast<char>(evt.getText()));
+    }
+
+    /**
+        @brief This update() function is called by the InputState if the InputBuffer is active.
+        @param dt Delta time
+    */
+    void InputBuffer::keyboardUpdated(float dt)
+    {
+        timeSinceKeyPressed_ += dt;
+        if (keysToRepeat_ < 10 && timeSinceKeyPressed_ > keyRepeatDeleay_)
+        {
+            // initial time out has gone by, start repeating keys
+            while (timeSinceKeyPressed_ - timeSinceKeyRepeated_ > keyRepeatTime_)
+            {
+                timeSinceKeyRepeated_ += keyRepeatTime_;
+                keysToRepeat_++;
+            }
+        }
+    }
+
+    void InputBuffer::buttonPressed(const KeyEvent& evt)
+    {
+        lastKey_ = evt.getKeyCode();
+        timeSinceKeyPressed_ = 0.0;
+        timeSinceKeyRepeated_ = keyRepeatDeleay_;
+        keysToRepeat_ = 0;
+
+        processKey(evt);
+    }
+
+    void InputBuffer::buttonHeld(const KeyEvent& evt)
+    {
+        if (evt.getKeyCode() == lastKey_)
+        {
+            while (keysToRepeat_)
+            {
+                processKey(evt);
+                keysToRepeat_--;
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputBuffer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputBuffer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputBuffer.h	(revision 11817)
@@ -0,0 +1,193 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#ifndef _InputBuffer_H__
+#define _InputBuffer_H__
+
+#include "InputPrereqs.h"
+
+#include <list>
+#include <string>
+#include "core/config/Configurable.h"
+#include "InputHandler.h"
+
+namespace orxonox
+{
+    class BaseInputBufferListenerTuple
+    {
+    public:
+        BaseInputBufferListenerTuple(bool bListenToAllChanges, bool bOnlySingleInput,
+            bool trueKeyFalseChar, char _char, KeyCode::ByEnum key)
+            : bListenToAllChanges_(bListenToAllChanges), bOnlySingleInput_(bOnlySingleInput),
+              trueKeyFalseChar_(trueKeyFalseChar), char_(_char), key_(key)
+        { }
+        virtual ~BaseInputBufferListenerTuple() = default;
+        virtual void callFunction() = 0;
+        bool bListenToAllChanges_;
+        bool bOnlySingleInput_;
+        bool trueKeyFalseChar_;
+        char char_;
+        KeyCode::ByEnum key_;
+    };
+
+    template <class T>
+    class InputBufferListenerTuple : public BaseInputBufferListenerTuple
+    {
+    public:
+        InputBufferListenerTuple(T* listener, void (T::*function)(), bool bListenToAllChanges,
+            bool bOnlySingleInput, bool trueKeyFalseChar, char _char, KeyCode::ByEnum key)
+            : BaseInputBufferListenerTuple(bListenToAllChanges, bOnlySingleInput, trueKeyFalseChar, _char, key),
+              listener_(listener), function_(function)
+        { }
+        virtual ~InputBufferListenerTuple() = default;
+        virtual void callFunction() override
+        {
+            (listener_->*function_)();
+        }
+        T* listener_;
+        void (T::*function_)();
+    };
+
+    class _CoreExport InputBuffer : public InputHandler, public Configurable
+    {
+        public:
+            InputBuffer();
+            ~InputBuffer();
+            InputBuffer(const std::string& allowedChars);
+
+            void setConfigValues();
+
+            unsigned int getMaxLength() const { return this->maxLength_; }
+            void setMaxLength(unsigned int length);
+
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), bool bOnlySingleInput)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, true, bOnlySingleInput, false, '\0', KeyCode::Unassigned);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)() const, bool bOnlySingleInput)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, true, bOnlySingleInput, false, '\0', KeyCode::Unassigned);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), char _char, bool bOnlySingleInput)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, false, bOnlySingleInput, false, _char, KeyCode::Unassigned);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)() const, char _char, bool bOnlySingleInput)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, false, bOnlySingleInput, false, _char, KeyCode::Unassigned);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
+
+            template <class T>
+            void registerListener(T* listener, void (T::*function)(), KeyCode::ByEnum key)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, false, true, true, '\0', key);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
+            template <class T>
+            void registerListener(T* listener, void (T::*function)() const, KeyCode::ByEnum key)
+            {
+                InputBufferListenerTuple<T>* newTuple = new InputBufferListenerTuple<T>(listener, (void (T::*)())function, false, true, true, '\0', key);
+                this->listeners_.insert(this->listeners_.end(), newTuple);
+            }
+
+            template <class T>
+            void unregisterListener(T* listener)
+            {
+                for (std::list<BaseInputBufferListenerTuple*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); )
+                {
+                    InputBufferListenerTuple<T>* refListener = static_cast<InputBufferListenerTuple<T>*>(*it);
+                    if (refListener && refListener->listener_ == listener)
+                        this->listeners_.erase(it++);
+                    else
+                        it++;
+                }
+            }
+
+            void set(const std::string& input, bool update = true);
+            void insert(const std::string& input, bool update = true);
+            void insert(const char& input, bool update = true);
+            void clear(bool update = true);
+            void removeAtCursor(bool update = true);
+            void removeBehindCursor(bool update = true);
+
+            void updated();
+            void updated(const char& update, bool bSingleInput);
+
+            inline const std::string& get() const
+                { return this->buffer_; }
+            inline unsigned int getSize() const
+                { return this->buffer_.size(); }
+
+            inline unsigned int getCursorPosition() const
+                { return this->cursor_; }
+            inline void setCursorPosition(unsigned int cursor)
+                { if (cursor <= this->buffer_.size()) { this->cursor_ = cursor; } }
+            inline void setCursorToEnd()
+                { this->cursor_ = this->buffer_.size(); }
+            inline void setCursorToBegin()
+                { this->cursor_ = 0; }
+            inline void increaseCursor()
+                { if (this->cursor_ < this->buffer_.size()) { ++this->cursor_; } }
+            inline void decreaseCursor()
+                { if (this->cursor_ > 0) { --this->cursor_; } }
+
+            virtual void buttonPressed(const KeyEvent& evt) override;
+
+        private:
+            bool charIsAllowed(const char& input);
+
+            virtual void buttonHeld (const KeyEvent& evt) override;
+            void processKey (const KeyEvent& evt);
+
+            virtual void keyboardUpdated(float dt) override;
+
+            std::string buffer_;
+            std::list<BaseInputBufferListenerTuple*> listeners_;
+            std::string allowedChars_;
+            unsigned int maxLength_;
+            unsigned int cursor_;
+
+            KeyCode::ByEnum lastKey_;
+            float timeSinceKeyPressed_;
+            float timeSinceKeyRepeated_;
+            int keysToRepeat_;
+
+            float keyRepeatDeleay_;
+            float keyRepeatTime_;
+    };
+}
+
+#endif /* _InputBuffer_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputCommands.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputCommands.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputCommands.cc	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the different input handlers.
+*/
+
+#include "InputCommands.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###  BufferedParamCommand   ###
+    // ###############################
+
+    /**
+    @brief
+        Executes a buffered command. This is used for commands with additional
+        parameters.
+    @return
+        True if command execution was successful or value was zero.
+    */
+    bool BufferedParamCommand::execute()
+    {
+        if (this->abs_ != 0.0f || this->rel_ != 0.0f)
+        {
+            evaluation_.setEvaluatedArgument(paramIndex_, Vector2(abs_, rel_));
+            // reset
+            rel_ = 0.0;
+            abs_ = 0.0;
+            return evaluation_.execute();
+        }
+        else
+            return true;
+    }
+
+    // ###############################
+    // #####    ParamCommand     #####
+    // ###############################
+
+    /**
+    @brief
+        Executes a parameter command. The commmand string is not directly executed,
+        but instead stored in a buffer list so that values can be combined.
+    @return
+        Always true.
+    */
+    bool ParamCommand::execute(float abs, float rel)
+    {
+        BufferedParamCommand& cmd = *paramCommand_;
+        // command has an additional parameter
+        if (rel != 0.0f)
+        {
+            // calculate relative movement.
+            // scale_ says how much one keystroke is
+            cmd.rel_ += scale_ * rel;
+        }
+
+        if (abs != 0.0f)
+        {
+            cmd.abs_ += scale_ * abs;
+            if (cmd.abs_ > 1.0)
+                cmd.abs_ = 1.0;
+            if (cmd.abs_ < -1.0)
+                cmd.abs_ = -1.0;
+        }
+        return true;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputCommands.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputCommands.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputCommands.h	(revision 11817)
@@ -0,0 +1,124 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Different definitions of input processing.
+*/
+
+#ifndef _InputCommands_H__
+#define _InputCommands_H__
+
+#include "InputPrereqs.h"
+#include "core/command/CommandEvaluation.h"
+
+namespace orxonox
+{
+    class _CoreExport BufferedParamCommand
+    {
+    public:
+        BufferedParamCommand() : abs_(0.0f), rel_(0.0), paramIndex_(-1) { }
+        bool execute();
+
+        float abs_;
+        float rel_;
+        int paramIndex_;
+        CommandEvaluation evaluation_;
+    };
+
+    class _CoreExport BaseCommand
+    {
+    public:
+        BaseCommand() : bFixedKeybindMode_(false) {}
+        virtual ~BaseCommand() = default;
+
+        virtual bool execute(float abs = 1.0f, float rel = 1.0f) = 0;
+        virtual CommandEvaluation* getEvaluation() = 0;
+
+        inline void setFixedKeybindMode(bool fixed)
+            { this->bFixedKeybindMode_ = fixed; }
+        inline bool hasFixedKeybindMode() const
+            { return this->bFixedKeybindMode_; }
+
+        virtual BaseCommand* clone() = 0;
+
+    private:
+        bool bFixedKeybindMode_;
+    };
+
+    class _CoreExport SimpleCommand : public BaseCommand
+    {
+    public:
+        virtual bool execute(float abs = 1.0f, float rel = 1.0f) override;
+        virtual CommandEvaluation* getEvaluation() override;
+        virtual SimpleCommand* clone() override { return new SimpleCommand(*this); }
+
+        CommandEvaluation evaluation_;
+    };
+
+    /**
+    @brief
+        Executes a simple command with no additional paramters.
+    @return
+        True if command execution was successful, false otherwise.
+    */
+    inline bool SimpleCommand::execute(float abs, float rel)
+    {
+        return evaluation_.execute();
+    }
+
+    /// Returns a pointer to the encapsuled evaluation.
+    inline CommandEvaluation* SimpleCommand::getEvaluation()
+    {
+        return &this->evaluation_;
+    }
+
+    class _CoreExport ParamCommand : public BaseCommand
+    {
+    public:
+        ParamCommand() : scale_(1.0f), paramCommand_(nullptr) { }
+        virtual bool execute(float abs = 1.0f, float rel = 1.0f) override;
+        virtual CommandEvaluation* getEvaluation() override;
+        virtual ParamCommand* clone() override { return new ParamCommand(*this); }
+
+        float scale_;
+        BufferedParamCommand* paramCommand_;
+    };
+
+    /// Returns a pointer to the encapsuled evaluation.
+    inline CommandEvaluation* ParamCommand::getEvaluation()
+    {
+        if (this->paramCommand_)
+            return &this->paramCommand_->evaluation_;
+        else
+            return nullptr;
+    }
+}
+
+#endif /* _InputCommands_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputDevice.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputDevice.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputDevice.h	(revision 11817)
@@ -0,0 +1,242 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of InputDevice and InputDeviceTemplated
+*/
+
+#ifndef _InputDevice_H__
+#define _InputDevice_H__
+
+#include "InputPrereqs.h"
+
+#include <vector>
+#include <ois/OISInputManager.h>
+#include <ois/OISException.h>
+
+#include "util/Clock.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "InputState.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Abstract base class for all input devices (mouse, keyboard and joy sticks).
+
+        It provides common virtual functions to be used by the InputManager.
+    */
+    class InputDevice
+    {
+    public:
+        //! Only resets the members
+        InputDevice(unsigned int id) : bCalibrating_(false), deviceID_(id) { }
+        virtual ~InputDevice() = default;
+        //! Returns the device class (derived) name as string
+        virtual std::string getClassName() const = 0;
+        //! Updates the device which should in turn distribute events
+        virtual void update(const Clock& time) = 0;
+        //! Clear all button related buffers
+        virtual void clearBuffers() = 0;
+
+        //! Start calibrating (only useful for joy sticks)
+        void startCalibration()
+        {
+            bCalibrating_ = true;
+            this->calibrationStarted();
+        }
+
+        //! Stop calibrating and evaluate the data (only useful for joy sticks)
+        void stopCalibration()
+        {
+            this->calibrationStopped();
+            bCalibrating_ = false;
+        }
+
+        //! Returns a reference to the internal input state vector. Use with care!
+        std::vector<InputState*>& getStateListRef() { return this->inputStates_; }
+        //! Returns the ID of the device (the same as in InputDeviceEnumerator for mouse and keyboard)
+        unsigned int getDeviceID() const { return this->deviceID_; }
+        //! Tells whether the device is in calibration mode
+        bool isCalibrating() const { return bCalibrating_; }
+
+    protected:
+        //! To be ovrridden by the subclass
+        virtual void calibrationStarted() { }
+        //! To be ovrridden by the subclass
+        virtual void calibrationStopped() { }
+
+        //! List of all input states that receive events from this device
+        std::vector<InputState*> inputStates_;
+
+    private:
+        // non-copyable:
+        InputDevice(const InputDevice&) = delete;
+        InputDevice& operator=(const InputDevice&) = delete;
+
+        bool bCalibrating_;                  //!< Whether the device is in calibration mode
+        const unsigned int deviceID_;        //!< ID of the device (the same as in InputDeviceEnumerator for mouse and keyboard)
+    };
+
+    /**
+    @brief
+        Heavily templated base class for all three input devices.
+
+        The purpose of this class is not to provide an interface but rather
+        to reduce code redundancy. This concerns device creation and destruction
+        as well as common code for button events (press, release, hold).
+
+        In order to derive from this class you have to supply it with a struct
+        as template parameter that contains the necessary type traits.
+    */
+    template <class Traits>
+    class InputDeviceTemplated : public InputDevice
+    {
+        typedef typename Traits::DeviceClass DeviceClass;
+        typedef typename Traits::OISDeviceClass OISDeviceClass;
+        typedef typename Traits::ButtonType ButtonType;
+        typedef typename Traits::ButtonTypeParam ButtonTypeParam;
+        static const OIS::Type OISDeviceValue = Traits::OISDeviceValue;
+
+    public:
+        //! Creates the OIS device
+        InputDeviceTemplated(unsigned int id, OIS::InputManager* oisInputManager)
+            : InputDevice(id)
+            , oisInputManager_(oisInputManager)
+        {
+            oisDevice_ = static_cast<OISDeviceClass*>(oisInputManager_->createInputObject(OISDeviceValue, true));
+            // Note: after the static_cast here, the cast this pointer becomes
+            //       invalid right until the subclass has been constructed!
+            oisDevice_->setEventCallback(static_cast<DeviceClass*>(this));
+            orxout(verbose, context::input) << "Instantiated a " << this->getClassName() << endl;
+        }
+
+        //! Destroys the OIS device
+        virtual ~InputDeviceTemplated()
+        {
+            try
+            {
+                oisInputManager_->destroyInputObject(oisDevice_);
+            }
+            catch (const OIS::Exception& ex)
+            {
+                orxout(internal_error, context::input) << this->getClassName() << " destruction failed: " << ex.eText << '\n'
+                                                       << "Potential resource leak!" << endl;
+            }
+        }
+
+        //! Captures OIS events (which then get distributed to the derived class) and creates the button held events
+        virtual void update(const Clock& time) override
+        {
+            oisDevice_->capture();
+
+            // Call all the states with the held button event
+            for (ButtonType& button : pressedButtons_)
+                for (InputState* state : inputStates_)
+                    state->template buttonEvent<ButtonEvent::THold, typename Traits::ButtonTypeParam>(
+                        this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
+
+            // Call states with device update events
+            for (InputState* state : inputStates_)
+                state->update(time.getDeltaTime(), this->getDeviceID());
+
+            static_cast<DeviceClass*>(this)->updateImpl(time);
+        }
+
+        //! Clears the list of pressed buttons and calls the derived class's method
+        virtual void clearBuffers() override
+        {
+            pressedButtons_.clear();
+            static_cast<DeviceClass*>(this)->clearBuffersImpl();
+        }
+
+        // Returns a pointer to the OIS device
+        OISDeviceClass* getOISDevice()   { return this->oisDevice_; }
+        // Returns the name of the derived class as string
+        virtual std::string getClassName() const override { return DeviceClass::getClassNameImpl(); }
+
+    protected:
+        //! Common code for all button pressed events (updates pressed buttons list and calls the input states)
+        ORX_FORCEINLINE void buttonPressed(ButtonTypeParam button)
+        {
+            // check whether the button already is in the list (can happen when focus was lost)
+            unsigned int iButton = 0;
+            while (iButton < pressedButtons_.size() && pressedButtons_[iButton] != button)
+                iButton++;
+            if (iButton == pressedButtons_.size())
+                pressedButtons_.push_back(button);
+            else
+                return; // Button already pressed
+
+            // Call states
+            for (InputState* state : inputStates_)
+                state->template buttonEvent<ButtonEvent::TPress, typename Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
+        }
+
+        //! Common code for all button released events (updates pressed buttons list and calls the input states)
+        ORX_FORCEINLINE void buttonReleased(ButtonTypeParam button)
+        {
+            // remove the button from the pressedButtons_ list
+            bool found = false;
+            for (unsigned int iButton = 0; iButton < pressedButtons_.size(); iButton++)
+            {
+                if (pressedButtons_[iButton] == button)
+                {
+                    pressedButtons_.erase(pressedButtons_.begin() + iButton);
+                    found = true;
+                    break;
+                }
+            }
+            if (!found)
+                return; // We ignore release strokes when the press was not captured
+
+            // Call states
+            for (InputState* state : inputStates_)
+                state->template buttonEvent<ButtonEvent::TRelease, typename Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
+        }
+
+        //! Managed pointer to the OIS device
+        OISDeviceClass* oisDevice_;
+
+    private:
+        //!< Fallback dummy function for static polymorphism
+        void clearBuffersImpl() { }
+        //!< Fallback dummy function for static polymorphism
+        void updateImpl(const Clock& time) { }
+        //!< Fallback dummy function for static polymorphism
+        ButtonType& getButtonEventArg(ButtonType& button) { return button; }
+
+        std::vector<ButtonType> pressedButtons_; //!< List of all buttons that are currently pressed down
+        OIS::InputManager* oisInputManager_;     //!< Pointer to the OIS InputManager that can create and destroy devices
+    };
+}
+
+#endif /* _InputDevice_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputHandler.h	(revision 11817)
@@ -0,0 +1,163 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _InputHandler_H__
+#define _InputHandler_H__
+
+#include "InputPrereqs.h"
+
+namespace orxonox
+{
+    /// A Vector class containing two integers @a x and @a y.
+    class IntVector2
+    {
+    public:
+        IntVector2() : x(0), y(0) { }
+        IntVector2(int _x, int _y) : x(_x), y(_y) { }
+        int x;
+        int y;
+    };
+
+    namespace ButtonEvent
+    {
+        //! Helper enum to deploy events with the help of templates
+        enum Value
+        {
+            Press,
+            Release,
+            Hold
+        };
+
+        //! Enables function overloading with integer values
+        template <ButtonEvent::Value Event>
+        struct EnumToType { };
+        typedef EnumToType<Press>   TPress;
+        typedef EnumToType<Release> TRelease;
+        typedef EnumToType<Hold>    THold;
+    }
+
+    namespace KeyboardModifier
+    {
+        //! Keyboard modifiers (shift, ctrl and alt)
+        enum Enum
+        {
+            Shift = 0x0000001,
+            Ctrl  = 0x0000010,
+            Alt   = 0x0000100
+        };
+    }
+
+    //! Event argument for key events
+    class _CoreExport KeyEvent
+    {
+    public:
+        KeyEvent(const OIS::KeyEvent& evt)
+            : key_(static_cast<KeyCode::ByEnum>(evt.key))
+            , text_(evt.text)
+            , modifiers_(0)
+        { }
+        KeyEvent(KeyCode::ByEnum key, unsigned int text, int modifiers)
+            : key_(key)
+            , text_(text)
+            , modifiers_(modifiers)
+        { }
+        bool operator==(const KeyEvent& rhs) const
+            { return rhs.key_ == key_; }
+        bool operator!=(const KeyEvent& rhs) const
+            { return rhs.key_ != key_; }
+        void setModifiers(int modifiers)
+            { modifiers_ = modifiers; }
+
+        bool isModifierDown(KeyboardModifier::Enum modifier) const
+            { return static_cast<KeyboardModifier::Enum>(modifier & modifiers_); }
+        KeyCode::ByEnum getKeyCode() const
+            { return key_; }
+        unsigned int getText() const { return text_; }
+
+    private:
+        KeyCode::ByEnum key_;
+        unsigned int text_;
+        int modifiers_;
+    };
+
+    /**
+    @brief
+        Base class for all input handlers like KeyBinder, InputBuffer, etc.
+
+        Derive from this class if you wish to receive input events.
+        But keep in mind that this is pointless without first having an InputState.
+    @note
+        The definitions for the button events with the weird arguments are simply
+        to avoid redundant code in the input devices.
+    */
+    class _CoreExport InputHandler
+    {
+    public:
+        virtual ~InputHandler() = default;
+
+        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TPress)
+            { this->buttonPressed(button); }
+        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::TRelease)
+            { this->buttonReleased(button); }
+        template<class T> void buttonEvent(unsigned int device, T button, ButtonEvent::THold)
+            { this->buttonHeld(button); }
+
+        virtual void buttonPressed (const KeyEvent& evt) { }
+        virtual void buttonReleased(const KeyEvent& evt) { }
+        virtual void buttonHeld    (const KeyEvent& evt) { }
+
+        virtual void buttonPressed (MouseButtonCode::ByEnum button) { }
+        virtual void buttonReleased(MouseButtonCode::ByEnum button) { }
+        virtual void buttonHeld    (MouseButtonCode::ByEnum button) { }
+        virtual void mouseMoved    (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize) { }
+        virtual void mouseScrolled (int abs, int rel) { }
+
+        virtual void buttonPressed (unsigned int joyStick, JoyStickButtonCode::ByEnum button) { }
+        virtual void buttonReleased(unsigned int joyStick, JoyStickButtonCode::ByEnum button) { }
+        virtual void buttonHeld    (unsigned int joyStick, JoyStickButtonCode::ByEnum button) { }
+        virtual void axisMoved     (unsigned int joyStick, unsigned int axis, float value){ }
+
+        virtual void keyboardUpdated(float dt) { }
+        virtual void mouseUpdated   (float dt) { }
+        virtual void joyStickUpdated(unsigned int joyStick, float dt) { }
+
+        virtual void allDevicesUpdated(float dt) { }
+
+        //! Use this input handler if you want to occupy a device in an input state.
+        static InputHandler EMPTY;
+    };
+
+    template<> inline void InputHandler::buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TPress)
+        { this->buttonPressed(device - InputDeviceEnumerator::FirstJoyStick, button); }
+    template<> inline void InputHandler::buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::TRelease)
+        { this->buttonReleased(device - InputDeviceEnumerator::FirstJoyStick, button); }
+    template<> inline void InputHandler::buttonEvent<JoyStickButtonCode::ByEnum>(unsigned int device, JoyStickButtonCode::ByEnum button, ButtonEvent::THold)
+        { this->buttonHeld(device - InputDeviceEnumerator::FirstJoyStick, button); }
+}
+
+#endif /* _InputHandler_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputManager.cc	(revision 11817)
@@ -0,0 +1,662 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the InputManager and a static variable from the InputHandler.
+*/
+
+#include "InputManager.h"
+
+#include <cassert>
+#include <climits>
+#include <ois/OISException.h>
+#include <ois/OISInputManager.h>
+#include <loki/ScopeGuard.h>
+
+#include "util/Clock.h"
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/GraphicsManager.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/commandline/CommandLineIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/command/Functor.h"
+
+#include "InputBuffer.h"
+#include "JoyStick.h"
+#include "JoyStickQuantityListener.h"
+#include "Mouse.h"
+#include "Keyboard.h"
+
+namespace orxonox
+{
+    SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard");
+
+    static const std::string __CC_InputManager_name = "InputManager";
+    static const std::string __CC_calibrate_name = "calibrate";
+    static const std::string __CC_reload_name = "reload";
+
+    SetConsoleCommand(__CC_InputManager_name, __CC_calibrate_name, &InputManager::calibrate).addShortcut();
+    SetConsoleCommand(__CC_InputManager_name, __CC_reload_name,    &InputManager::reload   );
+
+    // Abuse of this source file for the InputHandler
+    InputHandler InputHandler::EMPTY;
+
+    InputManager* InputManager::singletonPtr_s = nullptr;
+
+    //! Defines the |= operator for easier use.
+    inline InputManager::State operator|=(InputManager::State& lval, InputManager::State rval)
+    {
+        return (lval = (InputManager::State)(lval | rval));
+    }
+
+    //! Defines the &= operator for easier use.
+    inline InputManager::State operator&=(InputManager::State& lval, int rval)
+    {
+        return (lval = (InputManager::State)(lval & rval));
+    }
+
+    RegisterAbstractClass(InputManager).inheritsFrom<WindowEventListener>();
+
+    // ############################################################
+    // #####                  Initialisation                  #####
+    // ##########                                        ##########
+    // ############################################################
+    InputManager::InputManager()
+        : internalState_(Bad)
+        , oisInputManager_(nullptr)
+        , devices_(2)
+        , exclusiveMouse_(false)
+        , emptyState_(nullptr)
+        , calibratorCallbackHandler_(nullptr)
+    {
+        RegisterObject(InputManager);
+
+        orxout(internal_status, context::input) << "InputManager: Constructing..." << endl;
+
+        // Allocate space for the function call buffer
+        this->callBuffer_.reserve(16);
+
+        this->setConfigValues();
+
+        if (GraphicsManager::getInstance().isFullScreen())
+            exclusiveMouse_ = true;
+        this->loadDevices();
+
+        // Lowest priority empty InputState
+        emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty);
+        emptyState_->setHandler(&InputHandler::EMPTY);
+        activeStates_[emptyState_->getPriority()] = emptyState_;
+
+        // Joy stick calibration helper callback
+        InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
+        calibrator->setHandler(&InputHandler::EMPTY);
+        calibratorCallbackHandler_ = new InputBuffer();
+        calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true);
+        calibrator->setKeyHandler(calibratorCallbackHandler_);
+
+        this->updateActiveStates();
+
+        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(this);
+        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(this);
+
+        orxout(internal_status, context::input) << "InputManager: Construction complete." << endl;
+        internalState_ = Nothing;
+    }
+
+    void InputManager::setConfigValues()
+    {
+    }
+
+    /**
+    @brief
+        Creates the OIS::InputMananger, the keyboard, the mouse and
+        the joys ticks. If either of the first two fail, this method throws an exception.
+    */
+    void InputManager::loadDevices()
+    {
+        orxout(verbose, context::input) << "InputManager: Loading input devices..." << endl;
+
+        // When loading the devices they should not already be loaded
+        assert(internalState_ & Bad);
+        assert(devices_[InputDeviceEnumerator::Mouse] == nullptr);
+        assert(devices_[InputDeviceEnumerator::Keyboard] == nullptr);
+        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
+
+        typedef std::pair<std::string, std::string> StringPair;
+
+        // Fill parameter list
+        OIS::ParamList paramList;
+        size_t windowHnd = GraphicsManager::getInstance().getRenderWindowHandle();
+        paramList.insert(StringPair("WINDOW", multi_cast<std::string>(windowHnd)));
+#if defined(ORXONOX_PLATFORM_WINDOWS)
+        paramList.insert(StringPair("w32_keyboard", "DISCL_NONEXCLUSIVE"));
+        paramList.insert(StringPair("w32_keyboard", "DISCL_FOREGROUND"));
+        paramList.insert(StringPair("w32_mouse", "DISCL_FOREGROUND"));
+        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
+        {
+            // Disable Windows key plus special keys (like play, stop, next, etc.)
+            paramList.insert(StringPair("w32_keyboard", "DISCL_NOWINKEY"));
+            paramList.insert(StringPair("w32_mouse", "DISCL_EXCLUSIVE"));
+        }
+        else
+            paramList.insert(StringPair("w32_mouse", "DISCL_NONEXCLUSIVE"));
+#elif defined(ORXONOX_PLATFORM_LINUX)
+        // Enabling this is probably a bad idea, but whenever orxonox crashes, the setting stays on
+        // Trouble might be that the Pressed event occurs a bit too often...
+        paramList.insert(StringPair("XAutoRepeatOn", "true"));
+
+        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
+        {
+            if (CommandLineParser::getValue("keyboard_no_grab").get<bool>())
+                paramList.insert(StringPair("x11_keyboard_grab", "false"));
+            else
+                paramList.insert(StringPair("x11_keyboard_grab", "true"));
+            paramList.insert(StringPair("x11_mouse_grab",  "true"));
+            paramList.insert(StringPair("x11_mouse_hide", "true"));
+        }
+        else
+        {
+            paramList.insert(StringPair("x11_keyboard_grab", "false"));
+            paramList.insert(StringPair("x11_mouse_grab",  "false"));
+            paramList.insert(StringPair("x11_mouse_hide", "false"));
+        }
+#endif
+
+        try
+        {
+            oisInputManager_ = OIS::InputManager::createInputSystem(paramList);
+            // Exception-safety
+            Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_);
+            orxout(verbose, context::input) << "Created OIS input manager." << endl;
+
+            if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0)
+                devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard, oisInputManager_);
+            else
+                ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
+
+            // Successful initialisation
+            guard.Dismiss();
+        }
+        catch (const std::exception& ex)
+        {
+            oisInputManager_ = nullptr;
+            internalState_ |= Bad;
+            ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
+        }
+
+        this->loadMouse();
+        this->loadJoySticks();
+
+        // Reorder states in case some joy sticks were added/removed
+        this->updateActiveStates();
+
+        orxout(verbose, context::input) << "Input devices loaded." << endl;
+    }
+
+    //! Creates a new orxonox::Mouse
+    void InputManager::loadMouse()
+    {
+        if (oisInputManager_->getNumberOfDevices(OIS::OISMouse) > 0)
+        {
+            try
+            {
+                devices_[InputDeviceEnumerator::Mouse] = new Mouse(InputDeviceEnumerator::Mouse, oisInputManager_);
+            }
+            catch (const std::exception& ex)
+            {
+                orxout(user_warning, context::input) << "Failed to create Mouse:" << ex.what() << '\n'
+                                                     << "Proceeding without mouse support." << endl;
+            }
+        }
+        else
+            orxout(user_warning, context::input) << "No mouse found! Proceeding without mouse support." << endl;
+    }
+
+    //! Creates as many joy sticks as are available.
+    void InputManager::loadJoySticks()
+    {
+        for (int i = 0; i < oisInputManager_->getNumberOfDevices(OIS::OISJoyStick); i++)
+        {
+            try
+            {
+                devices_.push_back(new JoyStick(InputDeviceEnumerator::FirstJoyStick + i, oisInputManager_));
+            }
+            catch (const std::exception& ex)
+            {
+                orxout(user_warning, context::input) << "Failed to create joy stick: " << ex.what() << endl;
+            }
+        }
+
+        // inform all JoyStick Device Number Listeners
+        std::vector<JoyStick*> joyStickList;
+        for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i)
+            joyStickList.push_back(static_cast<JoyStick*>(devices_[i]));
+        JoyStickQuantityListener::changeJoyStickQuantity(joyStickList);
+    }
+
+    // ############################################################
+    // #####                    Destruction                   #####
+    // ##########                                        ##########
+    // ############################################################
+
+    InputManager::~InputManager()
+    {
+        orxout(internal_status, context::input) << "InputManager: Destroying..." << endl;
+
+        // Leave all active InputStates (except "empty")
+        while (this->activeStates_.size() > 1)
+            this->leaveState(this->activeStates_.rbegin()->second->getName());
+        this->activeStates_.clear();
+
+        // Destroy calibrator helper handler and state
+        this->destroyState("calibrator");
+        // Destroy KeyDetector and state
+        delete calibratorCallbackHandler_;
+        // Destroy the empty InputState
+        this->destroyStateInternal(this->emptyState_);
+
+        // Destroy all user InputStates
+        while (statesByName_.size() > 0)
+            this->destroyStateInternal(statesByName_.rbegin()->second);
+
+        if (!(internalState_ & Bad))
+            this->destroyDevices();
+
+        // Reset console commands
+        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(nullptr);
+
+        orxout(internal_status, context::input) << "InputManager: Destruction complete." << endl;
+    }
+
+    /**
+    @brief
+        Destoys all input devices (joy sticks, mouse, keyboard and OIS::InputManager)
+    @throw
+        Method does not throw
+    */
+    void InputManager::destroyDevices()
+    {
+        orxout(verbose, context::input) << "InputManager: Destroying devices..." << endl;
+
+        for (InputDevice*& device : devices_)
+        {
+            if (device == nullptr)
+                continue;
+            const std::string& className = device->getClassName();
+            delete device;
+            device = nullptr;
+            orxout(verbose, context::input) << className << " destroyed." << endl;
+        }
+        devices_.resize(InputDeviceEnumerator::FirstJoyStick);
+
+        assert(oisInputManager_ != nullptr);
+        try
+        {
+            OIS::InputManager::destroyInputSystem(oisInputManager_);
+        }
+        catch (const OIS::Exception& ex)
+        {
+            orxout(internal_error, context::input) << "OIS::InputManager destruction failed" << ex.eText << '\n'
+                                                   << "Potential resource leak!" << endl;
+        }
+        oisInputManager_ = nullptr;
+
+        internalState_ |= Bad;
+        orxout(verbose, context::input) << "Destroyed devices." << endl;
+    }
+
+    // ############################################################
+    // #####                     Reloading                    #####
+    // ##########                                        ##########
+    // ############################################################
+
+    void InputManager::reload()
+    {
+        if (internalState_ & Calibrating)
+            orxout(internal_warning, context::input) << "Cannot reload input system. Joy sticks are currently being calibrated." << endl;
+        else
+            reloadInternal();
+    }
+
+    //! Internal reload method. Destroys the OIS devices and loads them again.
+    void InputManager::reloadInternal()
+    {
+        orxout(verbose, context::input) << "InputManager: Reloading ..." << endl;
+
+        this->destroyDevices();
+        this->loadDevices();
+
+        internalState_ &= ~Bad;
+        orxout(verbose, context::input) << "InputManager: Reloading complete." << endl;
+    }
+
+    // ############################################################
+    // #####                  Runtime Methods                 #####
+    // ##########                                        ##########
+    // ############################################################
+
+    void InputManager::preUpdate(const Clock& time)
+    {
+        if (internalState_ & Bad)
+            ThrowException(General, "InputManager was not correctly reloaded.");
+
+        // check whether a state has changed its EMPTY situation
+        bool bUpdateRequired = false;
+        for (const auto& mapEntry : activeStates_)
+        {
+            if (mapEntry.second->hasExpired())
+            {
+                mapEntry.second->resetExpiration();
+                bUpdateRequired = true;
+            }
+        }
+        if (bUpdateRequired)
+            updateActiveStates();
+
+        // Capture all the input and collect the function calls
+        // No event gets triggered here yet!
+        for  (InputDevice* device : devices_)
+            if (device != nullptr)
+                device->update(time);
+
+        // Collect function calls for the update
+        for (InputState* state : activeStatesTicked_)
+            state->update(time.getDeltaTime());
+
+        // Execute all cached function calls in order
+        // Why so complicated? The problem is that an InputHandler could trigger
+        // a reload that would destroy the OIS devices or it could even leave and
+        // then destroy its own InputState. That would of course lead to access
+        // violations.
+        // If we delay the calls, then OIS and and the InputStates are not anymore
+        // in the call stack and can therefore be edited.
+        for (auto& function : this->callBuffer_)
+            function();
+
+        this->callBuffer_.clear();
+    }
+
+    /**
+    @brief
+        Updates the currently active states (according to activeStates_) for each device.
+        Also, a list of all active states (no duplicates!) is compiled for the general preUpdate().
+    */
+    void InputManager::updateActiveStates()
+    {
+        // Calculate the stack of input states
+        // and assign it to the corresponding device
+        for (unsigned int i = 0; i < devices_.size(); ++i)
+        {
+            if (devices_[i] == nullptr)
+                continue;
+            std::vector<InputState*>& states = devices_[i]->getStateListRef();
+            bool occupied = false;
+            states.clear();
+            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
+            {
+                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
+                {
+                    states.push_back(rit->second);
+                    if (!rit->second->bTransparent_)
+                        occupied = true;
+                }
+            }
+        }
+
+        // See that we only update each InputState once for each device
+        // Using an std::set to avoid duplicates
+        std::set<InputState*> tempSet;
+        for (InputDevice* device : devices_)
+            if (device != nullptr)
+                for (unsigned int iState = 0; iState < device->getStateListRef().size(); ++iState)
+                    tempSet.insert(device->getStateListRef()[iState]);
+
+        // Copy the content of the std::set back to the actual vector
+        activeStatesTicked_.clear();
+        for (InputState* state : tempSet)
+            activeStatesTicked_.push_back(state);
+
+        // Check whether we have to change the mouse mode
+        tribool requestedMode = dontcare;
+        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
+        if (mouseStates.empty())
+            requestedMode = false;
+        else
+            requestedMode = mouseStates.front()->getMouseExclusive();
+        if (requestedMode != dontcare && exclusiveMouse_ != requestedMode)
+        {
+            assert(requestedMode != dontcare);
+            exclusiveMouse_ = (requestedMode == true);
+            if (!GraphicsManager::getInstance().isFullScreen())
+                this->reloadInternal();
+        }
+    }
+
+    void InputManager::clearBuffers()
+    {
+        for (InputDevice* device : devices_)
+            if (device != nullptr)
+                device->clearBuffers();
+    }
+
+    void InputManager::calibrate()
+    {
+        orxout(message) << "Move all joy stick axes fully in all directions." << '\n'
+                        << "When done, put the axex in the middle position and press enter." << endl;
+
+        for (InputDevice* device : devices_)
+            if (device != nullptr)
+                device->startCalibration();
+
+        internalState_ |= Calibrating;
+        enterState("calibrator");
+    }
+
+    //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well!
+    void InputManager::stopCalibration()
+    {
+        for (InputDevice* device : devices_)
+            if (device != nullptr)
+                device->stopCalibration();
+
+        // restore old input state
+        leaveState("calibrator");
+        internalState_ &= ~Calibrating;
+        // Clear buffers to prevent button hold events
+        this->clearBuffers();
+
+        orxout(message) << "Calibration has been stored." << endl;
+    }
+
+    //! Gets called by WindowEventListener upon focus change --> clear buffers
+    void InputManager::windowFocusChanged(bool bFocus)
+    {
+        this->clearBuffers();
+    }
+
+    std::pair<int, int> InputManager::getMousePosition() const
+    {
+        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
+        if (mouse != nullptr)
+        {
+            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
+            return std::make_pair(state.X.abs, state.Y.abs);
+        }
+        else
+            return std::make_pair(0, 0);
+    }
+
+    // ############################################################
+    // #####                    Input States                  #####
+    // ##########                                        ##########
+    // ############################################################
+
+    InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
+    {
+        if (name.empty())
+            return nullptr;
+        if (statesByName_.find(name) == statesByName_.end())
+        {
+            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
+            {
+                // Make sure we don't add two high priority states with the same priority
+                for (const auto& mapEntry : this->statesByName_)
+                {
+                    if (mapEntry.second->getPriority() == priority)
+                    {
+                        orxout(internal_warning, context::input) << "Could not add an InputState with the same priority '"
+                            << static_cast<int>(priority) << "' != 0." << endl;
+                        return nullptr;
+                    }
+                }
+            }
+            InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority);
+            statesByName_[name] = state;
+
+            return state;
+        }
+        else
+        {
+            orxout(internal_warning, context::input) << "Could not add an InputState with the same name '" << name << "'." << endl;
+            return nullptr;
+        }
+    }
+
+    InputState* InputManager::getState(const std::string& name)
+    {
+        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
+        if (it != statesByName_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    bool InputManager::enterState(const std::string& name)
+    {
+        // get pointer from the map with all stored handlers
+        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
+        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
+        {
+            // exists and not active
+            if (it->second->getPriority() == 0)
+            {
+                // Get smallest possible priority between 1 and maxStateStackSize_s
+                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
+                    rit != activeStates_.rend(); ++rit)
+                {
+                    if (rit->first < InputStatePriority::HighPriority)
+                    {
+                        it->second->setPriority(rit->first + 1);
+                        break;
+                    }
+                }
+                // In case no normal handler was on the stack
+                if (it->second->getPriority() == 0)
+                    it->second->setPriority(1);
+            }
+            activeStates_[it->second->getPriority()] = it->second;
+            updateActiveStates();
+            it->second->entered();
+
+            return true;
+        }
+        return false;
+    }
+
+    bool InputManager::leaveState(const std::string& name)
+    {
+        if (name == "empty")
+        {
+            orxout(internal_warning, context::input) << "InputManager: Leaving the empty state is not allowed!" << endl;
+            return false;
+        }
+        // get pointer from the map with all stored handlers
+        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
+        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
+        {
+            // exists and active
+
+            it->second->left();
+
+            activeStates_.erase(it->second->getPriority());
+            if (it->second->getPriority() < InputStatePriority::HighPriority)
+                it->second->setPriority(0);
+            updateActiveStates();
+
+            return true;
+        }
+        return false;
+    }
+
+    bool InputManager::destroyState(const std::string& name)
+    {
+        if (name == "empty")
+        {
+            orxout(internal_warning, context::input) << "InputManager: Removing the empty state is not allowed!" << endl;
+            return false;
+        }
+        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
+        if (it != statesByName_.end())
+        {
+            this->leaveState(name);
+            destroyStateInternal(it->second);
+
+            return true;
+        }
+        return false;
+    }
+
+    //! Destroys an InputState internally.
+    void InputManager::destroyStateInternal(InputState* state)
+    {
+        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
+        statesByName_.erase(state->getName());
+        delete state;
+    }
+
+    bool InputManager::setMouseExclusive(const std::string& name, tribool value)
+    {
+        if (name == "empty")
+        {
+            orxout(internal_warning, context::input) << "InputManager: Changing the empty state is not allowed!" << endl;
+            return false;
+        }
+        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
+        if (it != statesByName_.end())
+        {
+            it->second->setMouseExclusive(value);
+            return true;
+        }
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputManager.h	(revision 11817)
@@ -0,0 +1,234 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _InputManager_H__
+#define _InputManager_H__
+
+#include "InputPrereqs.h"
+
+#include <map>
+#include <string>
+#include <vector>
+#include <functional>
+
+#include "util/Singleton.h"
+#include "util/tribool.h"
+#include "core/WindowEventListener.h"
+
+// tolua_begin
+namespace orxonox
+{
+    /**
+    @brief
+        Manages the input devices (mouse, keyboard, joy sticks) and the input states.
+
+        Every input device has its own wrapper class which does the actually input event
+        distribution. The InputManager only creates reloads (on request) those devices.
+
+        The other functionality concerns handling InputStates. They act as a layer
+        between InputHandlers (like the KeyBinder or the GUIManager) and InputDevices.
+        InputStates are memory managed by the IputManager. You cannot create or destroy
+        them on your own. Therefore all states get destroyed with the InputManager d'tor.
+    @note
+        - The actual lists containing all the InputStates for a specific device are stored
+          in the InputDevices themselves.
+        - The devices_ vector always has at least two elements: Keyboard (first) and mouse.
+          You best access them internally with InputDeviceEnumerator::Keyboard/Mouse
+          The first joy stick is accessed with InputDeviceEnumerator::FirstJoyStick.
+        - Keyboard construction is mandatory , mouse and joy sticks are not.
+          If the OIS::InputManager or the Keyboard fail, an exception is thrown.
+    */
+    class _CoreExport InputManager
+// tolua_end
+        : public Singleton<InputManager>, public WindowEventListener
+    { // tolua_export
+        friend class Singleton<InputManager>;
+    public:
+        //! Represents internal states of the InputManager.
+        enum State
+        {
+            Nothing       = 0x00,
+            Bad           = 0x02,
+            Calibrating   = 0x04,
+        };
+
+        /**
+        @brief
+            Loads the devices and initialises the KeyDetector and the Calibrator.
+
+            If either the OIS input system and/or the keyboard could not be created,
+            the constructor fails with an std::exception.
+        */
+        InputManager();
+        //! Destroys all devices AND all input states!
+        ~InputManager();
+        void setConfigValues();
+
+        /**
+        @brief
+            Updates the devices (which distribute the input events) and the input states.
+
+            Any InpuStates changes (destroy, enter, leave) and happens here. If a reload request
+            was submitted while updating, the request will be postponed until the next update call.
+        */
+        void preUpdate(const Clock& time);
+        //! Clears all input device buffers. This usually only includes the pressed button list.
+        void clearBuffers();
+        //! Starts joy stick calibration.
+        void calibrate();
+        /**
+        @brief
+            Reloads all the input devices. Use this method to initialise new joy sticks.
+        @note
+            Only reloads immediately if the call stack doesn't include the preUpdate() method.
+        */
+        void reload();
+
+        //-------------------------------
+        // Input States
+        //-------------------------------
+        /**
+        @brief
+            Creates a new InputState that gets managed by the InputManager.
+        @remarks
+            The InputManager will take care of the state completely. That also
+            means it gets deleted when the InputManager is destroyed!
+        @param name
+            Unique name of the InputState when referenced as string
+        @param bAlwaysGetsInput
+            InputState always gets the input when activated
+        @param bTransparent
+            InputState will not prevent underlaying state from receiving input
+        @param priority
+            Priority matters when multiple states are active. You can specify any
+            number, but 1 - 99 is preferred (99 means high priority).
+        */
+        InputState* createInputState(const std::string& name, bool bAlwaysGetsInput = false, bool bTransparent = false, InputStatePriority priority = InputStatePriority::Dynamic);
+        /**
+        @brief
+            Returns a pointer to a InputState referenced by name.
+        @return
+            Returns nullptr if state was not found.
+        */
+        InputState* getState(const std::string& name);
+        /**
+        @brief
+            Activates a specific input state.
+            It might not actually be activated if the priority is too low!
+        @return
+            False if name was not found, true otherwise.
+        */
+        bool enterState(const std::string& name); // tolua_export
+        /**
+        @brief
+            Deactivates a specific input state.
+        @return
+            False if name was not found, true otherwise.
+        */
+        bool leaveState(const std::string& name); // tolua_export
+        /**
+        @brief
+            Removes and destroys an input state.
+        @return
+            True if removal was successful, false if name was not found.
+        @remarks
+            - You can't remove the internal states "empty", "calibrator" and "detector".
+            - The removal process is being postponed if InputManager::preUpdate() is currently running.
+        */
+        bool destroyState(const std::string& name); // tolua_export
+        /**
+        @brief
+            Changes the mouse mode of an input state.
+        @return
+            True if the call was successful, fals if the name was not found
+        */
+        bool setMouseExclusive(const std::string& name, tribool value); // tolua_export
+
+        //-------------------------------
+        // Various getters and setters
+        //-------------------------------
+        //! Returns the number of joy stick that have been created since the c'tor or last call to reload().
+        unsigned int getJoyStickQuantity() const
+            { return devices_.size() - InputDeviceEnumerator::FirstJoyStick; }
+        //! Returns a pointer to the OIS InputManager. Only you if you know what you're doing!
+        OIS::InputManager* getOISInputManager() { return this->oisInputManager_; }
+        //! Returns the position of the cursor as std::pair of ints
+        std::pair<int, int> getMousePosition() const;
+        //! Tells whether the mouse is used exclusively to the game
+        bool isMouseExclusive() const { return this->exclusiveMouse_; } // tolua_export
+
+        //-------------------------------
+        // Function call caching
+        //-------------------------------
+        void pushCall(const std::function<void ()>& function)
+            { this->callBuffer_.push_back(function); }
+
+        static InputManager& getInstance() { return Singleton<InputManager>::getInstance(); } // tolua_export
+
+    private: // functions
+        // non-copyable:
+        InputManager(const InputManager&) = delete;
+        InputManager& operator=(const InputManager&) = delete;
+
+        // Internal methods
+        void loadDevices();
+        void loadMouse();
+        void loadJoySticks();
+        void destroyDevices();
+
+        void stopCalibration();
+        void reloadInternal();
+
+        void destroyStateInternal(InputState* state);
+        void updateActiveStates();
+
+        // From WindowEventListener
+        virtual void windowFocusChanged(bool bFocus) override;
+
+    private: // variables
+        State                               internalState_;        //!< Current internal state
+        OIS::InputManager*                  oisInputManager_;      //!< OIS input manager
+        std::vector<InputDevice*>           devices_;              //!< List of all input devices (keyboard, mouse, joy sticks)
+        bool                                exclusiveMouse_;       //!< Currently applied mouse mode
+
+        // some internally handled states and handlers
+        InputState*                         emptyState_;           //!< Lowest priority states (makes handling easier)
+        //! InputBuffer that reacts to the Enter key when calibrating the joy sticks
+        InputBuffer*                        calibratorCallbackHandler_;
+
+        std::map<std::string, InputState*>  statesByName_;         //!< Contains all the created input states by name
+        std::map<int, InputState*>          activeStates_;         //!< Contains all active input states by priority (std::map is sorted!)
+        std::vector<InputState*>            activeStatesTicked_;   //!< Like activeStates_, but only contains the ones that currently receive events
+
+        std::vector<std::function<void ()>> callBuffer_;        //!< Caches all calls from InputStates to be executed afterwards (see preUpdate)
+
+        static InputManager*                singletonPtr_s;        //!< Pointer reference to the singleton
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _InputManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputPrereqs.h	(revision 11817)
@@ -0,0 +1,466 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Declarations of all key/button/axis code enumeration and string literals
+    and an input device enumeration.
+*/
+
+#ifndef _InputPrereqs_H__
+#define _InputPrereqs_H__
+
+#include "core/CorePrereqs.h"
+
+#include <ois/OISKeyboard.h>
+#include <ois/OISMouse.h>
+#include "util/OrxEnum.h"
+
+namespace orxonox
+{
+    //-----------------------------------------------------------------------
+    // Code enumerations
+    //-----------------------------------------------------------------------
+
+    namespace KeyCode
+    {
+        const unsigned int numberOfKeys = 0xEE; // 238
+
+        //! Key codes as enumeration
+        enum ByEnum
+        {
+            Unassigned    = OIS::KC_UNASSIGNED,
+            Escape        = OIS::KC_ESCAPE,
+            NumRow1       = OIS::KC_1,
+            NumRow2       = OIS::KC_2,
+            NumRow3       = OIS::KC_3,
+            NumRow4       = OIS::KC_4,
+            NumRow5       = OIS::KC_5,
+            NumRow6       = OIS::KC_6,
+            NumRow7       = OIS::KC_7,
+            NumRow8       = OIS::KC_8,
+            NumRow9       = OIS::KC_9,
+            NumRow0       = OIS::KC_0,
+            Minus         = OIS::KC_MINUS,           // - on main keyboard
+            Equals        = OIS::KC_EQUALS,
+            Back          = OIS::KC_BACK,            // backspace
+            Tab           = OIS::KC_TAB,
+            Q             = OIS::KC_Q,
+            W             = OIS::KC_W,
+            E             = OIS::KC_E,
+            R             = OIS::KC_R,
+            T             = OIS::KC_T,
+            Y             = OIS::KC_Y,
+            U             = OIS::KC_U,
+            I             = OIS::KC_I,
+            O             = OIS::KC_O,
+            P             = OIS::KC_P,
+            LeftBracket   = OIS::KC_LBRACKET,
+            RightBracket  = OIS::KC_RBRACKET,
+            Return        = OIS::KC_RETURN,          // Enter on main keyboard
+            LeftControl   = OIS::KC_LCONTROL,
+            A             = OIS::KC_A,
+            S             = OIS::KC_S,
+            D             = OIS::KC_D,
+            F             = OIS::KC_F,
+            G             = OIS::KC_G,
+            H             = OIS::KC_H,
+            J             = OIS::KC_J,
+            K             = OIS::KC_K,
+            L             = OIS::KC_L,
+            Semicolon     = OIS::KC_SEMICOLON,
+            Apostrophe    = OIS::KC_APOSTROPHE,
+            Grave         = OIS::KC_GRAVE,           // accent
+            LeftShift     = OIS::KC_LSHIFT,
+            Backslash     = OIS::KC_BACKSLASH,
+            Z             = OIS::KC_Z,
+            X             = OIS::KC_X,
+            C             = OIS::KC_C,
+            V             = OIS::KC_V,
+            B             = OIS::KC_B,
+            N             = OIS::KC_N,
+            M             = OIS::KC_M,
+            Comma         = OIS::KC_COMMA,
+            Period        = OIS::KC_PERIOD,          // . on main keyboard
+            Slash         = OIS::KC_SLASH,           // / on main keyboard
+            RightShift    = OIS::KC_RSHIFT,
+            Multiply      = OIS::KC_MULTIPLY,        // * on numeric keypad
+            LeftAlt       = OIS::KC_LMENU,           // left Alt
+            Space         = OIS::KC_SPACE,
+            CapsLock      = OIS::KC_CAPITAL,
+            F1            = OIS::KC_F1,
+            F2            = OIS::KC_F2,
+            F3            = OIS::KC_F3,
+            F4            = OIS::KC_F4,
+            F5            = OIS::KC_F5,
+            F6            = OIS::KC_F6,
+            F7            = OIS::KC_F7,
+            F8            = OIS::KC_F8,
+            F9            = OIS::KC_F9,
+            F10           = OIS::KC_F10,
+            NumLock       = OIS::KC_NUMLOCK,
+            ScrollLock    = OIS::KC_SCROLL,          // Scroll Lock
+            Numpad7       = OIS::KC_NUMPAD7,
+            Numpad8       = OIS::KC_NUMPAD8,
+            Numpad9       = OIS::KC_NUMPAD9,
+            NumpadSubtract= OIS::KC_SUBTRACT,        // - on numeric keypad
+            Numpad4       = OIS::KC_NUMPAD4,
+            Numpad5       = OIS::KC_NUMPAD5,
+            Numpad6       = OIS::KC_NUMPAD6,
+            NumpadAdd     = OIS::KC_ADD,             // + on numeric keypad
+            Numpad1       = OIS::KC_NUMPAD1,
+            Numpad2       = OIS::KC_NUMPAD2,
+            Numpad3       = OIS::KC_NUMPAD3,
+            Numpad0       = OIS::KC_NUMPAD0,
+            NumpadPeriod  = OIS::KC_DECIMAL,         // . on numeric keypad
+            LessThan      = OIS::KC_OEM_102,         // < > | on UK/Germany keyboards
+            F11           = OIS::KC_F11,
+            F12           = OIS::KC_F12,
+            F13           = OIS::KC_F13,             //                     (NEC PC98)
+            F14           = OIS::KC_F14,             //                     (NEC PC98)
+            F15           = OIS::KC_F15,             //                     (NEC PC98)
+            Kana          = OIS::KC_KANA,            // (Japanese keyboard)
+            ABNT_C1       = OIS::KC_ABNT_C1,         // / ? on Portugese (Brazilian) keyboards
+            Convert       = OIS::KC_CONVERT,         // (Japanese keyboard)
+            NoConvert     = OIS::KC_NOCONVERT,       // (Japanese keyboard)
+            Yen           = OIS::KC_YEN,             // (Japanese keyboard)
+            ABNT_C2       = OIS::KC_ABNT_C2,         // Numpad . on Portugese (Brazilian) keyboards
+            NumpadEquals  = OIS::KC_NUMPADEQUALS,    // = on numeric keypad (NEC PC98)
+            PreviousTrack = OIS::KC_PREVTRACK,       // Previous Track (KC_CIRCUMFLEX on Japanese keyboard)
+            AT            = OIS::KC_AT,              //                     (NEC PC98)
+            Colon         = OIS::KC_COLON,           //                     (NEC PC98)
+            Underline     = OIS::KC_UNDERLINE,       //                     (NEC PC98)
+            Kanji         = OIS::KC_KANJI,           // (Japanese keyboard)
+            Stop          = OIS::KC_STOP,            //                     (NEC PC98)
+            AX            = OIS::KC_AX,              //                     (Japan AX)
+            Unlabeled     = OIS::KC_UNLABELED,       //                        (J3100)
+            NextTrack     = OIS::KC_NEXTTRACK,       // Next Track
+            NumpadEnter   = OIS::KC_NUMPADENTER,     // Enter on numeric keypad
+            RightControl  = OIS::KC_RCONTROL,
+            Mute          = OIS::KC_MUTE,            // Mute
+            Calculator    = OIS::KC_CALCULATOR,      // Calculator
+            PlayPause     = OIS::KC_PLAYPAUSE,       // Play / Pause
+            MediaStop     = OIS::KC_MEDIASTOP,       // Media Stop
+            VolumeDown    = OIS::KC_VOLUMEDOWN,      // Volume -
+            VolumeUp      = OIS::KC_VOLUMEUP,        // Volume +
+            WebHome       = OIS::KC_WEBHOME,         // Web home
+            NumpadComma   = OIS::KC_NUMPADCOMMA,     // , on numeric keypad (NEC PC98)
+            Divide        = OIS::KC_DIVIDE,          // / on numeric keypad
+            SystemRequest = OIS::KC_SYSRQ,
+            RightAlt      = OIS::KC_RMENU,           // right Alt
+            Pause         = OIS::KC_PAUSE,           // Pause
+            Home          = OIS::KC_HOME,            // Home on arrow keypad
+            Up            = OIS::KC_UP,              // UpArrow on arrow keypad
+            PageUp        = OIS::KC_PGUP,            // PgUp on arrow keypad
+            Left          = OIS::KC_LEFT,            // LeftArrow on arrow keypad
+            Right         = OIS::KC_RIGHT,           // RightArrow on arrow keypad
+            End           = OIS::KC_END,             // End on arrow keypad
+            Down          = OIS::KC_DOWN,            // DownArrow on arrow keypad
+            PageDown      = OIS::KC_PGDOWN,          // PgDn on arrow keypad
+            Insert        = OIS::KC_INSERT,          // Insert on arrow keypad
+            Delete        = OIS::KC_DELETE,          // Delete on arrow keypad
+            LeftWindows   = OIS::KC_LWIN,            // Left Windows key
+            RightWindows  = OIS::KC_RWIN,            // Right Windows key
+            Apps          = OIS::KC_APPS,            // AppMenu key
+            Power         = OIS::KC_POWER,           // System Power
+            Sleep         = OIS::KC_SLEEP,           // System Sleep
+            Wake          = OIS::KC_WAKE,            // System Wake
+            WebSearch     = OIS::KC_WEBSEARCH,       // Web Search
+            WebFavorites  = OIS::KC_WEBFAVORITES,    // Web Favorites
+            WebRefresh    = OIS::KC_WEBREFRESH,      // Web Refresh
+            WebStop       = OIS::KC_WEBSTOP,         // Web Stop
+            WebForward    = OIS::KC_WEBFORWARD,      // Web Forward
+            WebBack       = OIS::KC_WEBBACK,         // Web Back
+            MyComputer    = OIS::KC_MYCOMPUTER,      // My Computer
+            Mail          = OIS::KC_MAIL,            // Mail
+            MediaSelect   = OIS::KC_MEDIASELECT      // Media Select
+        };
+
+        //! Key codes as strings
+        const char* const ByString[] =
+        {
+            "Unassigned",
+            "Escape",
+            "NumRow1", "NumRow2", "NumRow3", "NumRow4", "NumRow5",
+            "NumRow6", "NumRow7", "NumRow8", "NumRow9", "NumRow0",
+            "Minus", "Equals", "Back", "Tab",
+            "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",
+            "LeftBracket", "RightBracket",
+            "Return", "LeftControl",
+            "A", "S", "D", "F", "G", "H", "J", "K", "L",
+            "Semicolon", "Apostrophe", "Grave",
+            "LeftShift", "Backslash",
+            "Z", "X", "C", "V", "B", "N", "M",
+            "Comma", "Period", "Slash",
+            "RightShift",
+            "Multiply",
+            "LeftAlt",
+            "Space",
+            "CapsLock",
+            "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",
+            "NumLock", "ScrollLock",
+            "Numpad7", "Numpad8", "Numpad9",
+            "NumpadSubtract",
+            "Numpad4", "Numpad5", "Numpad6",
+            "NumpadAdd",
+            "Numpad1", "Numpad2", "Numpad3", "Numpad0",
+            "NumpadPeriod",
+            "","",
+            "LessThan",
+            "F11", "F12",
+            "","","","","","","","","","","",
+            "F13", "F14", "F15",
+            "","","","","","","","","","",
+            "Kana",
+            "","",
+            "ABNT_C1",
+            "","","","","",
+            "Convert",
+            "",
+            "NoConvert",
+            "",
+            "Yen",
+            "ABNT_C2",
+            "","","","","","","","","","","","","","",
+            "NumpadEquals",
+            "","",
+            "PreviousTrack",
+            "AT",
+            "Colon", "Underline",
+            "Kanji",
+            "Stop",
+            "AX",
+            "Unlabeled",
+            "NextTrack",
+            "","",
+            "NumpadEnter",
+            "RightControl",
+            "","",
+            "Mute",
+            "Calculator",
+            "PlayPause",
+            "",
+            "MediaStop",
+            "","","","","","","","","",
+            "VolumeDown",
+            "",
+            "VolumeUp",
+            "",
+            "WebHome",
+            "NumpadComma",
+            "",
+            "Divide",
+            "",
+            "SystemRequest",
+            "RightAlt",
+            "","","","","","","","","","","","",
+            "Pause",
+            "",
+            "Home",
+            "UP",
+            "PageUp",
+            "",
+            "Left",
+            "",
+            "Right",
+            "",
+            "End", "Down", "PageDown", "Insert", "Delete",
+            "","","","","","","",
+            "LeftWindows", "RightWindows", "Apps",
+            "Power", "Sleep",
+            "","","",
+            "Wake",
+            "",
+            "WebSearch", "WebFavorites", "WebRefresh", "WebStop", "WebForward", "WebBack",
+            "MyComputer", "Mail", "MediaSelect"
+        };
+    }
+
+
+    namespace MouseButtonCode
+    {
+        const unsigned int numberOfButtons = 8;
+
+        //! Mouse button codes as enumeration
+        enum ByEnum
+        {
+            Left    = OIS::MB_Left,
+            Right   = OIS::MB_Right,
+            Middle  = OIS::MB_Middle,
+            Button3 = OIS::MB_Button3,
+            Button4 = OIS::MB_Button4,
+            Button5 = OIS::MB_Button5,
+            Button6 = OIS::MB_Button6,
+            Button7 = OIS::MB_Button7,
+        };
+
+        // Mouse button codes as strings
+        const char* const ByString[] =
+        {
+            "Left",
+            "Right",
+            "Middle",
+            "Button3",
+            "Button4",
+            "Button5",
+            "Button6",
+            "Button7",
+        };
+    }
+
+    namespace MouseAxisCode
+    {
+        const unsigned int numberOfAxes = 2;
+
+        // Mouse axis codes as enumeration
+        enum ByEnum
+        {
+            X,
+            Y
+        };
+
+        // Mouse axis codes as strings
+        const char* const ByString[] =
+        {
+            "X",
+            "Y"
+        };
+    }
+
+
+    namespace JoyStickButtonCode
+    {
+        const unsigned int numberOfButtons = 64;
+
+        // Joy stick button codes as enumeration
+        enum ByEnum
+        {
+            Button0       =  0, Button1       =  1, Button2       =  2, Button3       =  3,
+            Button4       =  4, Button5       =  5, Button6       =  6, Button7       =  7,
+            Button8       =  8, Button9       =  9, Button10      = 10, Button11      = 11,
+            Button12      = 12, Button13      = 13, Button14      = 14, Button15      = 15,
+            Button16      = 16, Button17      = 17, Button18      = 18, Button19      = 19,
+            Button20      = 20, Button21      = 21, Button22      = 22, Button23      = 23,
+            Button24      = 24, Button25      = 25, Button26      = 26, Button27      = 27,
+            Button28      = 28, Button29      = 29, Button30      = 30, Button31      = 31,
+
+            POV0North     = 32, POV0South     = 33, POV0East      = 34, POV0West      = 35,
+            POV0NorthEast = 36, POV0SouthEast = 37, POV0NorthWest = 38, POV0SouthWest = 39,
+
+            POV1North     = 40, POV1South     = 41, POV1East      = 42, POV1West      = 43,
+            POV1NorthEast = 44, POV1SouthEast = 45, POV1NorthWest = 46, POV1SouthWest = 47,
+
+            POV2North     = 48, POV2South     = 49, POV2East      = 50, POV2West      = 51,
+            POV2NorthEast = 52, POV2SouthEast = 53, POV2NorthWest = 54, POV2SouthWest = 55,
+
+            POV3North     = 56, POV3South     = 57, POV3East      = 58, POV3West      = 59,
+            POV3NorthEast = 60, POV3SouthEast = 61, POV3NorthWest = 62, POV3SouthWest = 63,
+        };
+
+        // Joy stick button codes as strings
+        const char* const ByString[] =
+        {
+            "Button00",      "Button01",      "Button02",      "Button03",
+            "Button04",      "Button05",      "Button06",      "Button07",
+            "Button08",      "Button09",      "Button10",      "Button11",
+            "Button12",      "Button13",      "Button14",      "Button15",
+            "Button16",      "Button17",      "Button18",      "Button19",
+            "Button20",      "Button21",      "Button22",      "Button23",
+            "Button24",      "Button25",      "Button26",      "Button27",
+            "Button28",      "Button29",      "Button30",      "Button31",
+            "POV0North",     "POV0South",     "POV0East",      "POV0West",
+            "POV0NorthEast", "POV0SouthEast", "POV0NorthWest", "POV0SouthWest",
+            "POV1North",     "POV1South",     "POV1East",      "POV1West",
+            "POV1NorthEast", "POV1SouthEast", "POV1NorthWest", "POV1SouthWest",
+            "POV2North",     "POV2South",     "POV2East",      "POV2West",
+            "POV2NorthEast", "POV2SouthEast", "POV2NorthWest", "POV2SouthWest",
+            "POV3North",     "POV3South",     "POV3East",      "POV3West",
+            "POV3NorthEast", "POV3SouthEast", "POV3NorthWest", "POV3SouthWest"
+        };
+    }
+
+    namespace JoyStickAxisCode
+    {
+        const unsigned int numberOfAxes = 24;
+
+        // Joy stick axis codes as enumeration
+        enum ByEnum
+        {
+            Slider0 =  0, Slider1 =  1, Slider2 =  2, Slider3 =  3,
+            Slider4 =  4, Slider5 =  5, Slider6 =  6, Slider7 =  7,
+            Axis0   =  8, Axis1   =  9, Axis2   = 10, Axis3   = 11,
+            Axis4   = 12, Axis5   = 13, Axis6   = 14, Axis7   = 15,
+            Axis8   = 16, Axis9   = 17, Axis10  = 18, Axis11  = 19,
+            Axis12  = 20, Axis13  = 21, Axis14  = 22, Axis15  = 23
+        };
+
+        // Joy stick axis codes as strings
+        const char* const ByString[] =
+        {
+            "Slider0", "Slider1", "Slider2", "Slider3",
+            "Slider4", "Slider5", "Slider6", "Slider7",
+            "Axis00",  "Axis01",  "Axis02",  "Axis03",
+            "Axis04",  "Axis05",  "Axis06",  "Axis07",
+            "Axis08",  "Axis09",  "Axis10",  "Axis11",
+            "Axis12",  "Axis13",  "Axis14",  "Axis15"
+        };
+    }
+
+
+    //-----------------------------------------------------------------------
+    // Miscellaneous
+    //-----------------------------------------------------------------------
+
+    namespace InputDeviceEnumerator
+    {
+        //! Used to access the devices in an array
+        enum Value
+        {
+            Keyboard = 0,
+            Mouse = 1,
+            FirstJoyStick = 2
+        };
+    }
+
+    //! Enumeration wrapper for input state priorities
+    struct InputStatePriority : OrxEnum<InputStatePriority>
+    {
+        OrxEnumConstructors(InputStatePriority);
+
+        static constexpr int Empty        = -1;
+        static constexpr int Dynamic      = 0;
+
+        static constexpr int HighPriority = 1000;
+        static constexpr int Console      = HighPriority + 0;
+        static constexpr int Calibrator   = HighPriority + 1;
+        static constexpr int Detector     = HighPriority + 2;
+    };
+}
+
+#endif /* _InputPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputState.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputState.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputState.cc	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "InputState.h"
+#include "core/command/Functor.h"
+
+namespace orxonox
+{
+    //! Sets priority of it's a high priority and resizes the handler list
+    InputState::InputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
+        : name_(name)
+        , bAlwaysGetsInput_(bAlwaysGetsInput)
+        , bTransparent_(bTransparent)
+        , exclusiveMouse_(dontcare)
+        , bExpired_(true)
+        , handlers_(2)
+        , joyStickHandlerAll_(nullptr)
+        , enterFunctor_(nullptr)
+        , leaveFunctor_(nullptr)
+    {
+        if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
+            priority_ = priority;
+        else
+            priority_ = 0;
+
+        handlers_.resize(InputDeviceEnumerator::FirstJoyStick + this->getJoyStickList().size(), nullptr);
+    }
+
+    bool InputState::isInputDeviceEnabled(unsigned int device)
+    {
+        if (device < handlers_.size())
+            return handlers_[device] != nullptr;
+        else
+            return false;
+    }
+
+    //! Called by JoyStickQuantityListener upon joy stick adding/removal
+    void InputState::JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList)
+    {
+        unsigned int oldSize = handlers_.size();
+        handlers_.resize(InputDeviceEnumerator::FirstJoyStick + joyStickList.size(), nullptr);
+
+        for (unsigned int i = oldSize; i < handlers_.size(); ++i)
+            handlers_[i] = joyStickHandlerAll_;
+
+        bExpired_ = true;
+    }
+
+    bool InputState::setJoyStickHandler(InputHandler* handler, unsigned int joyStick)
+    {
+        unsigned device = joyStick + firstJoyStickIndex_s;
+        if (joyStick >= handlers_.size() - device)
+            return false;
+
+        handlers_[device] = handler;
+        bExpired_ = true;
+        return true;
+    }
+
+    void InputState::setJoyStickHandler(InputHandler* handler)
+    {
+        joyStickHandlerAll_ = handler;
+        for (unsigned int i = firstJoyStickIndex_s; i < handlers_.size(); ++i)
+            handlers_[i] = handler;
+        bExpired_ = true;
+    }
+
+    void InputState::setHandler(InputHandler* handler)
+    {
+        setKeyHandler(handler);
+        setMouseHandler(handler);
+        setJoyStickHandler(handler);
+    }
+
+    void InputState::entered()
+    {
+        if (enterFunctor_)
+            (*enterFunctor_)();
+
+    }
+
+    void InputState::left()
+    {
+        if (leaveFunctor_)
+            (*leaveFunctor_)();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/InputState.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/InputState.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/InputState.h	(revision 11817)
@@ -0,0 +1,237 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _InputState_H__
+#define _InputState_H__
+
+#include "InputPrereqs.h"
+
+#include <cassert>
+#include <string>
+#include <vector>
+#include <functional>
+
+#include "util/tribool.h"
+#include "InputHandler.h"
+#include "InputManager.h"
+#include "JoyStickQuantityListener.h"
+
+#define INPUT_STATE_PUSH_CALL(deviceIndex, functionName, ...) \
+    InputManager::getInstance().pushCall(std::function<void ()>(std::bind(&InputHandler::functionName, handlers_[deviceIndex], __VA_ARGS__)))
+
+namespace orxonox
+{
+    /**
+    @brief
+        InputStates allow you to customise the input event targets at runtime.
+
+        The general idea is a stack: Every activated InputState will be pushed on
+        that stack and only the top one gets the input events. This is done for
+        every device (keyboard, mouse, all joy sticks) separately to allow
+        for instance keyboard input capturing for the console while you can still
+        steer a ship with the mouse.
+        There are two exceptions to this behaviour though:
+        - If an InputState is created with the 'Transparent' parameter on, the
+          state will not prevent input from getting to the state below it on the stack.
+          This can be useful for instance if you need to deploy input to multiple
+          handlers: Simply create two InputStates and make the high priority one transparent.
+        - If an InputState is created with the 'AlwaysGetsInput' parameter on, then
+          the state will always receive input as long as it is activated.
+        - Note: If you mark an InputState with both parameters on, then it will
+          not influence only other InputState at all.
+
+    @par Priorities
+        Every InputState has a priority when on the stack, but mostly this
+        priority is dynamic (InputStatePriority::Dynamic) which means that a state
+        pushed onto the stack will simply have a higher priority than the top one.
+        This behaviour really only applies to normal states that don't have
+        a high priority (InputStatePriority::HighPriority). These 'special' ones
+        are used for features like the KeyDetector or the console. Use with care!
+
+    @par Exclusive/Non-Exclusive mouse Mode
+        You can select a specific mouse mode that tells whether the application
+        should have exclusive access to it or not.
+        When in non-exclusive mode, you can move the mouse out of the window
+        like with any other normal window (only for windowed mode!).
+        The setting is dictated by the topmost InputState that gets mouse events.
+    */
+    class _CoreExport InputState : public JoyStickQuantityListener
+    {
+        friend class InputManager;
+
+        //! Marks the index in the handler vector for the keyboard handler
+        static const InputDeviceEnumerator::Value keyboardIndex_s = InputDeviceEnumerator::Keyboard;
+        //! Marks the index in the handler vector for the mouse handler
+        static const InputDeviceEnumerator::Value mouseIndex_s = InputDeviceEnumerator::Mouse;
+        //! Marks the index in the handler vector for the first joy stick handler
+        static const InputDeviceEnumerator::Value firstJoyStickIndex_s = InputDeviceEnumerator::FirstJoyStick;
+
+    public:
+        //! Sets the keyboard event handler (overwrites if there already was one!)
+        void setKeyHandler     (InputHandler* handler)
+            { handlers_[keyboardIndex_s] = handler; bExpired_ = true; }
+        //! Sets the mouse event handler (overwrites if there already was one!)
+        void setMouseHandler   (InputHandler* handler)
+            { handlers_[mouseIndex_s]    = handler; bExpired_ = true; }
+        /**
+        @brief
+            Sets the joy stick event handler for one specific joy stick (overwrites if there already was one!)
+        @return
+            Returns false if the specified device was not found
+        */
+        bool setJoyStickHandler(InputHandler* handler, unsigned int joyStick);
+        //! Sets the joy stick event handler for all joy sticks (overwrites if there already was one!)
+        void setJoyStickHandler(InputHandler* handler);
+        //! Sets an InputHandler to be used for all devices
+        void setHandler        (InputHandler* handler);
+
+        void setMouseExclusive(tribool value) { exclusiveMouse_ = value; this->bExpired_ = true; }
+        tribool getMouseExclusive() const { return exclusiveMouse_; }
+
+        //! Returns the name of the state (which is unique!)
+        const std::string& getName() const { return name_; }
+        //! Returns the priority of the state (which is unique if != 0)
+        int getPriority()            const { return priority_; }
+
+        //! Tells whether there a handler installed for a specific device
+        bool isInputDeviceEnabled(unsigned int device);
+
+        //! Returns true if the handler situation has changed
+        bool hasExpired()      { return this->bExpired_; }
+        //! Call this if you have applied the changes resulting from changed handlers
+        void resetExpiration() { bExpired_ = false; }
+
+        //! Updates one specific device handler with deviceUpdated
+        void update(float dt, unsigned int device);
+        //! Updates all handlers with allDevicesUpdated
+        void update(float dt);
+
+        //! Generic function that distributes all 9 button events
+        template <typename EventType, class ButtonTypeParam>
+        void buttonEvent(unsigned int device, ButtonTypeParam button);
+
+        //! Event handler
+        void mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize);
+        //! Event handler
+        void mouseScrolled(int abs, int rel);
+        //! Event handler
+        void joyStickAxisMoved(unsigned int device, unsigned int axis, float value);
+
+        // Functors
+        //! Called when the state is being activated (even if it doesn't get any events afterwards!)
+        void entered();
+        //! Called upon deactivation of the state
+        void left();
+        //! Sets a functor to be called upon activation of the state
+        void setEnterFunctor(const FunctorPtr& functor) { this->enterFunctor_ = functor; }
+        //! Sets a functor to be called upon deactivation of the state
+        void setLeaveFunctor(const FunctorPtr& functor) { this->leaveFunctor_ = functor; }
+
+    private:
+        InputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority);
+        ~InputState() = default;
+
+        virtual void JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList) override;
+
+        //! Sets the priority (only to be used by the InputManager!)
+        void setPriority(int priority) { priority_ = priority; }
+
+        const std::string           name_;                  //!< Name of the state
+        const bool                  bAlwaysGetsInput_;      //!< See class declaration for explanation
+        const bool                  bTransparent_;          //!< See class declaration for explanation
+        tribool                     exclusiveMouse_;        //!< See class declaration for explanation
+        int                         priority_;              //!< Current priority (might change)
+        bool                        bExpired_;              //!< See hasExpired()
+        std::vector<InputHandler*>  handlers_;              //!< Vector with all handlers where the index is the device ID
+        //! Handler to be used for all joy sticks (needs to be saved in case another joy stick gets attached)
+        InputHandler*               joyStickHandlerAll_;
+        FunctorPtr                  enterFunctor_;          //!< Functor to be executed on enter
+        FunctorPtr                  leaveFunctor_;          //!< Functor to be executed on leave
+    };
+
+    ORX_FORCEINLINE void InputState::update(float dt)
+    {
+        for (unsigned int i = 0; i < handlers_.size(); ++i)
+            if (handlers_[i] != nullptr)
+                INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt);
+    }
+
+    ORX_FORCEINLINE void InputState::update(float dt, unsigned int device)
+    {
+        switch (device)
+        {
+        case InputDeviceEnumerator::Keyboard:
+            if (handlers_[keyboardIndex_s] != nullptr)
+                INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt);
+            break;
+
+        case InputDeviceEnumerator::Mouse:
+            if (handlers_[mouseIndex_s] != nullptr)
+                INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt);
+            break;
+
+        default: // joy sticks
+            if (handlers_[device] != nullptr)
+                INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt);
+            break;
+        }
+    }
+
+    template <typename EventType, class ButtonTypeParam>
+    ORX_FORCEINLINE void InputState::buttonEvent(unsigned int device, ButtonTypeParam button)
+    {
+        assert(device < handlers_.size());
+        if (handlers_[device] != nullptr)
+        {
+            // We have to store the function pointer to tell the compiler about its actual type because of overloading
+            void (InputHandler::*function)(unsigned int, ButtonTypeParam, EventType) = &InputHandler::buttonEvent<ButtonTypeParam>;
+            InputManager::getInstance().pushCall(std::function<void ()>(std::bind(function, handlers_[device], device, button, EventType())));
+        }
+    }
+
+    ORX_FORCEINLINE void InputState::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
+    {
+        if (handlers_[mouseIndex_s] != nullptr)
+            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize);
+    }
+
+    ORX_FORCEINLINE void InputState::mouseScrolled(int abs, int rel)
+    {
+        if (handlers_[mouseIndex_s] != nullptr)
+            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel);
+    }
+
+    ORX_FORCEINLINE void InputState::joyStickAxisMoved(unsigned int device, unsigned int axis, float value)
+    {
+        assert(device < handlers_.size());
+        if (handlers_[device] != nullptr)
+            INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value);
+    }
+}
+
+#endif /* _InputState_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStick.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStick.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStick.cc	(revision 11817)
@@ -0,0 +1,264 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "JoyStick.h"
+
+#include <climits>
+#include <ois/OISJoyStick.h>
+
+#include "util/StringUtils.h"
+#include "core/config/ConfigFile.h"
+#include "core/config/ConfigFileManager.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "util/Convert.h"
+#include "InputState.h"
+
+namespace orxonox
+{
+    //! Helper function that loads the config value vector of one coefficient
+    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue);
+
+    std::vector<std::string> JoyStick::deviceNames_s;
+
+    RegisterAbstractClass(JoyStick).inheritsFrom<Configurable>();
+
+    JoyStick::JoyStick(unsigned int id, OIS::InputManager* oisInputManager)
+        : super(id, oisInputManager)
+    {
+        RegisterObject(JoyStick);
+        this->setConfigValues();
+        // Initialise POV and Slider states
+        this->clearBuffersImpl();
+
+        // Generate unique name
+        if (oisDevice_->vendor().empty())
+            deviceName_ = "Unknown_";
+        else
+        {
+            std::string name = oisDevice_->vendor();
+            replaceCharacters(name, ' ', '_');
+            deviceName_ = name + '_';
+        }
+        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Button))  + '_';
+        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Axis))    + '_';
+        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Slider))  + '_';
+        deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_POV));
+        //deviceName_ += multi_cast<std::string>(oisDevice_->getNumberOfComponents(OIS::OIS_Vector3));
+
+        for (const std::string& idString : deviceNames_s)
+        {
+            if (deviceName_ == idString)
+            {
+                // Make the ID unique for this execution time.
+                deviceName_ += '_' + multi_cast<std::string>(this->getDeviceName());
+                break;
+            }
+        }
+
+        orxout(verbose, context::input) << "Created OIS joy stick with ID " << deviceName_ << endl;
+
+        // Load calibration
+        size_t axes = sliderAxes_s + static_cast<size_t>(oisDevice_->getNumberOfComponents(OIS::OIS_Axis));
+        loadCalibration(configMinValues_,  deviceName_, "MinValue",  axes,  -32768);
+        loadCalibration(configMaxValues_,  deviceName_, "MaxValue",  axes,   32768);
+        loadCalibration(configZeroValues_, deviceName_, "ZeroValue", axes, 0);
+        this->evaluateCalibration();
+    }
+
+    //! Callback for the joy stick calibration config file.
+    void JoyStick::calibrationFileCallback()
+    {
+        ConfigFileManager::getInstance().setFilename(ConfigFileType::JoyStickCalibration, calibrationFilename_);
+    }
+
+    void JoyStick::setConfigValues()
+    {
+        SetConfigValue(calibrationFilename_, "joystick_calibration.ini")
+            .description("Ini filename for the the joy stick calibration data.")
+            .callback(this, &JoyStick::calibrationFileCallback);
+    }
+
+    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue)
+    {
+        list.resize(size);
+        unsigned int configValueVectorSize = ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)->getVectorSize(sectionName, valueName);
+        if (configValueVectorSize > size)
+            configValueVectorSize = size;
+
+        for (unsigned int i = 0; i < configValueVectorSize; ++i)
+        {
+            list[i] = multi_cast<int>(ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
+                ->getOrCreateValue(sectionName, valueName, i, multi_cast<std::string>(defaultValue), false));
+        }
+
+        // fill the rest with default values
+        for (unsigned int i = configValueVectorSize; i < size; ++i)
+            list[i] = defaultValue;
+    }
+
+    //! Called by InputDevice when calibration mode has started
+    void JoyStick::calibrationStarted()
+    {
+        // Set initial values
+        for (int& minVal : configMinValues_)
+            minVal = INT_MAX;
+        for (int& minVal : configMaxValues_)
+            minVal = INT_MIN;
+        for (int& zeroVal : configZeroValues_)
+            zeroVal = 0;
+    }
+
+    //! Called by InputDevice when calibration mode has stopped
+    void JoyStick::calibrationStopped()
+    {
+        // Get the middle positions now
+        unsigned int iAxis = 0;
+        for (unsigned int i = 0; i < sliderAxes_s/2; ++i)
+        {
+            configZeroValues_[iAxis++] = oisDevice_->getJoyStickState().mSliders[i].abX;
+            configZeroValues_[iAxis++] = oisDevice_->getJoyStickState().mSliders[i].abY;
+        }
+        // Note: joyStickZeroValues_[iJoyStick] was already correctly resised in loadCalibration()
+        assert(oisDevice_->getJoyStickState().mAxes.size() == configZeroValues_.size() - sliderAxes_s);
+        for (unsigned int i = 0; i < configZeroValues_.size() - sliderAxes_s; ++i)
+            configZeroValues_[iAxis++] = oisDevice_->getJoyStickState().mAxes[i].abs;
+
+        for (unsigned int i = 0; i < configMinValues_.size(); ++i)
+        {
+            // Minimum values
+            if (configMinValues_[i] == INT_MAX)
+                configMinValues_[i] = -32768;
+            ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
+                ->getOrCreateValue(deviceName_, "MinValue", i, multi_cast<std::string>(configMinValues_[i]), false);
+
+            // Maximum values
+            if (configMaxValues_[i] == INT_MIN)
+                configMaxValues_[i] = 32767;
+            ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
+                ->getOrCreateValue(deviceName_, "MaxValue", i, multi_cast<std::string>(configMaxValues_[i]), false);
+
+            // Middle values
+            ConfigFileManager::getInstance().getConfigFile(ConfigFileType::JoyStickCalibration)
+                ->getOrCreateValue(deviceName_, "ZeroValue", i, multi_cast<std::string>(configZeroValues_[i]), false);
+        }
+
+        this->evaluateCalibration();
+    }
+
+    //! Evaluates the accumulated values during calibration
+    void JoyStick::evaluateCalibration()
+    {
+        for (unsigned int i = 0; i < configMinValues_.size(); i++)
+        {
+            zeroValues_[i] = configZeroValues_[i];
+            negativeCoeffs_[i] = - 1.0f / (configMinValues_[i] - configZeroValues_[i]);
+            positiveCoeffs_[i] =   1.0f / (configMaxValues_[i] - configZeroValues_[i]);
+        }
+    }
+
+    //! Resets the pov states
+    void JoyStick::clearBuffersImpl()
+    {
+        for (int& state : povStates_)
+            state = 0;
+    }
+
+    //! Generic method to forward axis events
+    void JoyStick::fireAxis(int axis, int value)
+    {
+        if (this->isCalibrating())
+        {
+            if (value < configMinValues_[axis])
+                configMinValues_[axis] = value;
+            if (value > configMaxValues_[axis])
+                configMaxValues_[axis] = value;
+        }
+        else
+        {
+            float fValue = static_cast<float>(value - zeroValues_[axis]);
+            if (fValue > 0.0f)
+                fValue *= positiveCoeffs_[axis];
+            else
+                fValue *= negativeCoeffs_[axis];
+
+            for (InputState* state : inputStates_)
+                state->joyStickAxisMoved(this->getDeviceID(), axis, fValue);
+        }
+    }
+
+    //! OIS joy stick axis event handler
+    bool JoyStick::axisMoved(const OIS::JoyStickEvent &arg, int axis)
+    {
+        // keep in mind that the first 8 axes are reserved for the sliders
+        this->fireAxis(axis + sliderAxes_s, arg.state.mAxes[axis].abs);
+
+        return true;
+    }
+
+    //! A Slider always has an X and an Y direction!
+    bool JoyStick::sliderMoved(const OIS::JoyStickEvent &arg, int id)
+    {
+        if (sliderStates_[id][0] != arg.state.mSliders[id].abX)
+            fireAxis(id * 2, arg.state.mSliders[id].abX);
+        else if (sliderStates_[id][1] != arg.state.mSliders[id].abY)
+            fireAxis(id * 2 + 1, arg.state.mSliders[id].abY);
+
+        return true;
+    }
+
+    //! A POV is the big button that can point in all directions (but only in one at once)
+    bool JoyStick::povMoved(const OIS::JoyStickEvent &arg, int id)
+    {
+        // translate the POV into 8 simple buttons
+
+        int lastState = povStates_[id];
+        if (lastState & OIS::Pov::North)
+            buttonReleased(arg, 32 + id * 4 + 0);
+        if (lastState & OIS::Pov::South)
+            buttonReleased(arg, 32 + id * 4 + 1);
+        if (lastState & OIS::Pov::East)
+            buttonReleased(arg, 32 + id * 4 + 2);
+        if (lastState & OIS::Pov::West)
+            buttonReleased(arg, 32 + id * 4 + 3);
+
+        povStates_[id] = arg.state.mPOV[id].direction;
+
+        int currentState = povStates_[id];
+        if (currentState & OIS::Pov::North)
+            buttonPressed(arg, 32 + id * 4 + 0);
+        if (currentState & OIS::Pov::South)
+            buttonPressed(arg, 32 + id * 4 + 1);
+        if (currentState & OIS::Pov::East)
+            buttonPressed(arg, 32 + id * 4 + 2);
+        if (currentState & OIS::Pov::West)
+            buttonPressed(arg, 32 + id * 4 + 3);
+
+        return true;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStick.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStick.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStick.h	(revision 11817)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Core_JoyStick_H__
+#define _Core_JoyStick_H__
+
+#include "InputPrereqs.h"
+
+#include <string>
+#include <vector>
+#include <ois/OISJoyStick.h>
+#include "InputDevice.h"
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+    //! %Template parameter collection for the base class
+    struct JoyStickTraits
+    {
+        typedef JoyStick DeviceClass;
+        typedef OIS::JoyStick OISDeviceClass;
+        typedef JoyStickButtonCode::ByEnum ButtonType;
+        typedef JoyStickButtonCode::ByEnum ButtonTypeParam;
+        static const OIS::Type OISDeviceValue = OIS::OISJoyStick;
+    };
+
+    /**
+    @brief
+        Wraps around an OIS::JoyStick and forwards the input events to
+        a list of input states.
+
+        The class also supports joy stick calibration and stores the values
+        in an ini-file.
+    */
+    class _CoreExport JoyStick
+        : public Configurable
+        , public InputDeviceTemplated<JoyStickTraits>
+        , public OIS::JoyStickListener
+    {
+        friend class InputDeviceTemplated<JoyStickTraits>;
+        //! Super class alias
+        typedef InputDeviceTemplated<JoyStickTraits> super;
+
+    public:
+        //! Assigns a generated ID string and loads the calibration (if present)
+        JoyStick(unsigned int id, OIS::InputManager* oisInputManager);
+        ~JoyStick() = default;
+        void setConfigValues();
+
+        //! Returns the name generated from the number of knobs and the device name
+        const std::string& getDeviceName() const { return this->deviceName_; }
+
+    private:
+        virtual void calibrationStarted() override;
+        virtual void calibrationStopped() override;
+        void evaluateCalibration();
+
+        void clearBuffersImpl();
+        void calibrationFileCallback();
+        void fireAxis(int axis, int value);
+
+        //! OIS event handler
+        virtual bool buttonPressed (const OIS::JoyStickEvent &arg, int button) override
+        {
+            super::buttonPressed(static_cast<JoyStickButtonCode::ByEnum>(button));
+            return true;
+        }
+
+        //! OIS event handler
+        virtual bool buttonReleased(const OIS::JoyStickEvent &arg, int button) override
+        {
+            super::buttonReleased(static_cast<JoyStickButtonCode::ByEnum>(button));
+            return true;
+        }
+
+        virtual bool axisMoved     (const OIS::JoyStickEvent &arg, int axis) override;
+        virtual bool sliderMoved   (const OIS::JoyStickEvent &arg, int id) override;
+        virtual bool povMoved      (const OIS::JoyStickEvent &arg, int id) override;
+        //! OIS event handler (don't remove that because of OIS version issues!)
+        virtual bool vector3Moved  (const OIS::JoyStickEvent &arg, int id) override { return true; }
+
+        //! Returns the class name as string
+        static std::string getClassNameImpl() { return "JoyStick"; }
+
+        std::string deviceName_;              //!< Name generated by the number of knobs and the device name
+        int povStates_[4];                    //!< Internal states for the POVs
+        int sliderStates_[4][2];              //!< Internal states for the Sliders (each slider has X and Y!)
+
+        // calibration
+        int zeroValues_[24];                  //!< Axes values when the knob is in the middle
+        float positiveCoeffs_[24];            //!< Maps the negative part of an axis to a 0.0 to 1.0 floating range
+        float negativeCoeffs_[24];            //!< Maps the positive part of an axis to a 0.0 to 1.0 floating range
+
+        std::vector<int> configZeroValues_;   //!< Config file stored axis values when the knob is in the middle
+        std::vector<int> configMinValues_;    //!< Config file stored minimum axis values
+        std::vector<int> configMaxValues_;    //!< Config file stored maximum axis values
+
+        // ConfigValues
+        std::string calibrationFilename_;     //!< Joy stick calibration ini filename
+
+        //! Contains a list of all names to avoid duplicates
+        static std::vector<std::string> deviceNames_s;
+
+        //!< Maximum number of slider axes
+        static const unsigned int sliderAxes_s = 8;
+    };
+}
+
+#endif /* _Core_JoyStick_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStickQuantityListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStickQuantityListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStickQuantityListener.cc	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "JoyStickQuantityListener.h"
+
+#include "core/CoreIncludes.h"
+#include "core/object/ObjectList.h"
+
+namespace orxonox
+{
+    std::vector<JoyStick*> JoyStickQuantityListener::joyStickList_s;
+
+    RegisterAbstractClass(JoyStickQuantityListener).inheritsFrom<Listable>();
+
+    JoyStickQuantityListener::JoyStickQuantityListener()
+    {
+        RegisterObject(JoyStickQuantityListener);
+    }
+
+    //! Calls all registered objects and sets the static variable
+    /*static*/ void JoyStickQuantityListener::changeJoyStickQuantity(const std::vector<JoyStick*>& joyStickList)
+    {
+        joyStickList_s = joyStickList;
+        for (JoyStickQuantityListener* listener : ObjectList<JoyStickQuantityListener>())
+            listener->JoyStickQuantityChanged(joyStickList);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStickQuantityListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStickQuantityListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/JoyStickQuantityListener.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#ifndef _JoyStickQuantityListener_H__
+#define _JoyStickQuantityListener_H__
+
+#include "InputPrereqs.h"
+
+#include <vector>
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    //! Derive from this class to get informed when joy sticks get added/removed
+    class _CoreExport JoyStickQuantityListener : virtual public Listable
+    {
+        friend class InputManager;
+    protected:
+        JoyStickQuantityListener();
+        virtual ~JoyStickQuantityListener() = default;
+
+        //! Returns a list with all JoySticks currently loaded
+        const std::vector<JoyStick*>& getJoyStickList() const { return joyStickList_s; }
+
+    private:
+        //! Called whenever joy sticks get added/removed
+        virtual void JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList) = 0;
+
+        static void changeJoyStickQuantity(const std::vector<JoyStick*>& joyStickList);
+
+        //! Static variable that holds the latest distributed information
+        static std::vector<JoyStick*> joyStickList_s;
+    };
+}
+
+#endif /* _JoyStickQuantityListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinder.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinder.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinder.cc	(revision 11817)
@@ -0,0 +1,715 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "KeyBinder.h"
+
+#include <algorithm>
+#include <sstream>
+#include "util/Convert.h"
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/config/ConfigFile.h"
+#include "core/ApplicationPaths.h"
+#include "core/ConfigurablePaths.h"
+#include "InputCommands.h"
+#include "JoyStick.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(KeyBinder).inheritsFrom<JoyStickQuantityListener>();
+
+    /**
+    @brief
+        Constructor that does as little as necessary.
+    */
+    KeyBinder::KeyBinder(const std::string& filename)
+        : deriveTime_(0.0f)
+        , filename_(filename)
+        , configFile_(nullptr)
+        , fallbackConfigFile_(nullptr)
+    {
+        mouseRelative_[0] = 0;
+        mouseRelative_[1] = 0;
+        mousePosition_[0] = 0.0;
+        mousePosition_[1] = 0.0;
+
+        RegisterObject(KeyBinder);
+
+        // initialise all buttons and half axes to avoid creating everything with 'new'
+        // keys
+        for (unsigned int i = 0; i < KeyCode::numberOfKeys; i++)
+        {
+            const std::string keyname = KeyCode::ByString[i];
+            if (!keyname.empty())
+                keys_[i].name_ = std::string("Key") + keyname;
+            else
+                keys_[i].name_.clear();
+            keys_[i].paramCommandBuffer_ = &paramCommandBuffer_;
+            keys_[i].groupName_ = "Keys";
+        }
+        // mouse buttons plus 4 mouse wheel buttons only 'generated' by KeyBinder
+        const char* const mouseWheelNames[] = { "Wheel1Down", "Wheel1Up", "Wheel2Down", "Wheel2Up" };
+        for (unsigned int i = 0; i < numberOfMouseButtons_; i++)
+        {
+            std::string nameSuffix;
+            if (i < MouseButtonCode::numberOfButtons)
+                nameSuffix = MouseButtonCode::ByString[i];
+            else
+                nameSuffix = mouseWheelNames[i - MouseButtonCode::numberOfButtons];
+            mouseButtons_[i].name_ = nameSuffix;
+            mouseButtons_[i].paramCommandBuffer_ = &paramCommandBuffer_;
+            mouseButtons_[i].groupName_ = "MouseButtons";
+        }
+        // mouse axes
+        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
+        {
+            mouseAxes_[i].name_ = MouseAxisCode::ByString[i / 2];
+            if (i & 1)
+                mouseAxes_[i].name_ += "Pos";
+            else
+                mouseAxes_[i].name_ += "Neg";
+            mouseAxes_[i].paramCommandBuffer_ = &paramCommandBuffer_;
+            mouseAxes_[i].groupName_ = "MouseAxes";
+        }
+
+        // initialise joy sticks separatly to allow for reloading
+        this->JoyStickQuantityChanged(this->getJoyStickList());
+
+        // set them here to use allHalfAxes_
+        setConfigValues();
+
+        // Load the bindings if filename was given
+        if (!this->filename_.empty())
+            this->loadBindings();
+    }
+
+    /**
+    @brief
+        Destructor
+    */
+    KeyBinder::~KeyBinder()
+    {
+        // almost no destructors required because most of the arrays are static.
+        clearBindings(); // does some destruction work
+        if (this->configFile_)
+            delete this->configFile_;
+        if (this->fallbackConfigFile_)
+            delete this->fallbackConfigFile_;
+    }
+
+    /**
+    @brief
+        Loader for the key bindings, managed by config values.
+    */
+    void KeyBinder::setConfigValues()
+    {
+        SetConfigValue(analogThreshold_, 0.05f)
+            .description("Threshold for analog axes until which the state is 0.");
+        SetConfigValue(bFilterAnalogNoise_, false)
+            .description("Specifies whether to filter small analog values like joy stick fluctuations.");
+        SetConfigValue(mouseSensitivity_, 3.0f)
+            .description("Mouse sensitivity.");
+        this->totalMouseSensitivity_ = this->mouseSensitivity_ / this->mouseClippingSize_;
+        SetConfigValue(bDeriveMouseInput_, false)
+            .description("Whether or not to derive moues movement for the absolute value.");
+        SetConfigValue(derivePeriod_, 0.05f)
+            .description("Accuracy of the mouse input deriver. The higher the more precise, but laggier.");
+        SetConfigValue(mouseSensitivityDerived_, 1.0f)
+            .description("Mouse sensitivity if mouse input is derived.");
+        SetConfigValue(mouseWheelStepSize_, 120)
+            .description("Equals one step of the mousewheel.");
+        SetConfigValue(buttonThreshold_, 0.80f)
+            .description("Threshold for analog axes until which the button is not pressed.")
+            .callback(this, &KeyBinder::buttonThresholdChanged);
+    }
+
+    void KeyBinder::buttonThresholdChanged()
+    {
+        for (HalfAxis* halfAxis : allHalfAxes_)
+            if (!halfAxis->bButtonThresholdUser_)
+                halfAxis->buttonThreshold_ = this->buttonThreshold_;
+    }
+
+    void KeyBinder::JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList)
+    {
+        unsigned int oldValue = joySticks_.size();
+        joySticks_ = joyStickList;
+
+        // initialise joy stick bindings
+        initialiseJoyStickBindings();
+
+        // collect all Buttons and HalfAxes again
+        compilePointerLists();
+
+        // load the bindings if required
+        if (configFile_ != nullptr)
+        {
+            for (unsigned int iDev = oldValue; iDev < joySticks_.size(); ++iDev)
+            {
+                for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; ++i)
+                    (*joyStickButtons_[iDev])[i].readBinding(this->configFile_, this->fallbackConfigFile_);
+                for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; ++i)
+                    (*joyStickAxes_[iDev])[i].readBinding(this->configFile_, this->fallbackConfigFile_);
+            }
+        }
+
+        // Set the button threshold for potential new axes
+        buttonThresholdChanged();
+    }
+
+    void KeyBinder::initialiseJoyStickBindings()
+    {
+        while (joyStickAxes_.size() < joySticks_.size())
+            joyStickAxes_.push_back(std::make_shared<JoyStickAxisVector>());
+        while (joyStickButtons_.size() < joySticks_.size())
+            joyStickButtons_.push_back(std::make_shared<JoyStickButtonVector>());
+        // For the case the new size is smaller
+        this->joyStickAxes_.resize(joySticks_.size());
+        this->joyStickButtons_.resize(joySticks_.size());
+
+        // reinitialise all joy stick bindings (doesn't overwrite the old ones)
+        for (unsigned int iDev = 0; iDev < joySticks_.size(); iDev++)
+        {
+            const std::string& deviceName = joySticks_[iDev]->getDeviceName();
+            // joy stick buttons
+            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
+            {
+                (*joyStickButtons_[iDev])[i].name_ = JoyStickButtonCode::ByString[i];
+                (*joyStickButtons_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
+                (*joyStickButtons_[iDev])[i].groupName_ = "JoyStickButtons_" + deviceName;
+            }
+            // joy stick axes
+            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
+            {
+                (*joyStickAxes_[iDev])[i].name_ = JoyStickAxisCode::ByString[i / 2];
+                if (i & 1)
+                    (*joyStickAxes_[iDev])[i].name_ += "Pos";
+                else
+                    (*joyStickAxes_[iDev])[i].name_ += "Neg";
+                (*joyStickAxes_[iDev])[i].paramCommandBuffer_ = &paramCommandBuffer_;
+                (*joyStickAxes_[iDev])[i].groupName_ = "JoyStickAxes_" + deviceName;
+            }
+        }
+    }
+
+    void KeyBinder::compilePointerLists()
+    {
+        allButtons_.clear();
+        allHalfAxes_.clear();
+
+        // Note: Don't include the dummy keys which don't actually exist in OIS but have a number
+        for (unsigned int i = 0; i < KeyCode::numberOfKeys; i++)
+            if (!keys_[i].name_.empty())
+                allButtons_[keys_[i].groupName_ + '.' + keys_[i].name_] = keys_ + i;
+        for (unsigned int i = 0; i < numberOfMouseButtons_; i++)
+            allButtons_[mouseButtons_[i].groupName_ + '.' + mouseButtons_[i].name_] = mouseButtons_ + i;
+        for (unsigned int i = 0; i < MouseAxisCode::numberOfAxes * 2; i++)
+        {
+            allButtons_[mouseAxes_[i].groupName_ + '.' + mouseAxes_[i].name_] = mouseAxes_ + i;
+            allHalfAxes_.push_back(mouseAxes_ + i);
+        }
+        for (unsigned int iDev = 0; iDev < joySticks_.size(); iDev++)
+        {
+            for (unsigned int i = 0; i < JoyStickButtonCode::numberOfButtons; i++)
+                allButtons_[(*joyStickButtons_[iDev])[i].groupName_ + '.' + (*joyStickButtons_[iDev])[i].name_] = &((*joyStickButtons_[iDev])[i]);
+            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
+            {
+                allButtons_[(*joyStickAxes_[iDev])[i].groupName_ + '.' + (*joyStickAxes_[iDev])[i].name_] = &((*joyStickAxes_[iDev])[i]);
+                allHalfAxes_.push_back(&((*joyStickAxes_[iDev])[i]));
+            }
+        }
+    }
+
+    /**
+    @brief
+        Loads the key and button bindings.
+    */
+    void KeyBinder::loadBindings()
+    {
+        orxout(internal_info, context::input) << "KeyBinder: Loading key bindings..." << endl;
+
+        this->configFile_ = new ConfigFile(this->filename_, !ApplicationPaths::buildDirectoryRun());
+        this->configFile_->load();
+
+        if (ApplicationPaths::buildDirectoryRun())
+        {
+            // Dev users should have combined key bindings files
+            std::string defaultFilepath(ConfigurablePaths::getDataPathString() + ConfigFile::DEFAULT_CONFIG_FOLDER + '/' + this->filename_);
+            std::ifstream file(defaultFilepath.c_str());
+            if (file.is_open())
+            {
+                file.close();
+                // Open the default file for later use (use absolute path!)
+                this->fallbackConfigFile_ = new ConfigFile(defaultFilepath, false);
+                this->fallbackConfigFile_->load();
+            }
+        }
+
+        // Parse bindings and create the ConfigValueContainers if necessary
+        for (const auto& mapEntry : allButtons_)
+        {
+            mapEntry.second->readBinding(this->configFile_, this->fallbackConfigFile_);
+            addButtonToCommand(mapEntry.second->bindingString_, mapEntry.second);
+        }
+
+        orxout(internal_info, context::input) << "KeyBinder: Loading key bindings done." << endl;
+    }
+
+    bool KeyBinder::setBinding(const std::string& binding, const std::string& name, bool bTemporary)
+    {
+        std::map<std::string, Button*>::iterator it = allButtons_.find(name);
+        if (it != allButtons_.end())
+        {
+            addButtonToCommand(binding, it->second);
+            std::string str = binding;
+            if (ApplicationPaths::buildDirectoryRun() && binding.empty())
+                str = "NoBinding";
+            it->second->setBinding(this->configFile_, this->fallbackConfigFile_, binding, bTemporary);
+            return true;
+        }
+        else
+        {
+            orxout(internal_warning, context::input) << "Could not find key/button/axis with name '" << name << "'." << endl;
+            return false;
+        }
+    }
+
+     void KeyBinder::addButtonToCommand(const std::string& command, Button* button)
+     {
+        std::ostringstream stream;
+        stream << button->groupName_  << '.' << button->name_;
+
+        std::vector<std::string>& oldKeynames = this->allCommands_[button->bindingString_];
+        std::vector<std::string>::iterator it = std::find(oldKeynames.begin(), oldKeynames.end(), stream.str());
+        if (it != oldKeynames.end())
+            oldKeynames.erase(it);
+
+        if (!command.empty())
+        {
+            std::vector<std::string>& keynames = this->allCommands_[command];
+            if (std::find(keynames.begin(), keynames.end(), stream.str()) == keynames.end())
+                this->allCommands_[command].push_back(stream.str());
+        }
+     }
+
+    /**
+    @brief
+        Return the first key name for a specific command
+    */
+    std::string KeyBinder::getBinding(const std::string& commandName)
+    {
+        if (this->allCommands_.find(commandName) != this->allCommands_.end())
+        {
+            std::vector<std::string>& keynames = this->allCommands_[commandName];
+            return keynames.front();
+        }
+
+        return BLANKSTRING;
+    }
+
+    /**
+    @brief
+        Return the key name for a specific command at a given index.
+    @param commandName
+        The command name the key name is returned for.
+    @param index
+        The index at which the key name is returned for.
+    */
+    std::string KeyBinder::getBinding(const std::string& commandName, unsigned int index)
+    {
+        if (this->allCommands_.find(commandName) != this->allCommands_.end())
+        {
+            std::vector<std::string>& keynames = this->allCommands_[commandName];
+            if (index < keynames.size())
+                return keynames[index];
+
+            return BLANKSTRING;
+        }
+
+        return BLANKSTRING;
+    }
+
+    /**
+    @brief
+        Return the first key name for a specific command in a human readable form
+    */
+    std::string KeyBinder::getBindingReadable(const std::string& commandName)
+    {
+        std::string binding = this->getBinding(commandName);
+
+        SubString substring = SubString(binding, ".");
+        std::string name;
+        std::string group;
+        switch(substring.size())
+        {
+            case 0:
+                return binding;
+            case 1:
+                return binding;
+            case 2:
+                group = substring[0];
+            default:
+                name = substring.subSet(1).join(".");
+        }
+
+        std::stringstream stream;
+        if(group.compare("Keys") == 0)
+            stream << "Key " << name.substr(3);
+        else if(group.compare("MouseButtons") == 0)
+            stream << "Mouse " << name;
+        else if(group.compare("JoyStickButtons") == 0)
+            stream << "Joystick " << name;
+        else if(group.compare("JoyStickAxes") == 0)
+            stream << "Joystick Axis" << name.substr(5, 6) << name.substr(name.find("Axis")+6);
+        else if(group.compare("MouseAxes") == 0)
+            stream << "Mouse " << name.substr(1,3) << " " << name.substr(0, 1) << "-Axis";
+        else
+            return binding;
+
+        binding = stream.str();
+        return binding;
+    }
+
+    /**
+    @brief
+        Get the number of different key bindings of a specific command.
+    @param commandName
+        The command.
+    */
+    unsigned int KeyBinder::getNumberOfBindings(const std::string& commandName)
+    {
+        if (this->allCommands_.find(commandName) != this->allCommands_.end())
+        {
+            std::vector<std::string>& keynames = this->allCommands_[commandName];
+            return keynames.size();
+        }
+
+        return 0;
+    }
+
+    /**
+    @brief
+        Overwrites all bindings with ""
+    */
+    void KeyBinder::clearBindings()
+    {
+        for (const auto& mapEntry : allButtons_)
+            mapEntry.second->clear();
+
+        for (BufferedParamCommand* command : paramCommandBuffer_)
+            delete command;
+        paramCommandBuffer_.clear();
+    }
+
+    /**
+        @brief Changes the keybind mode of a given console command.
+    */
+    void KeyBinder::changeMode(ConsoleCommand* command, KeybindMode::Value new_mode)
+    {
+        // iterate over all buttons
+        for (const auto& mapEntry : this->allButtons_)
+        {
+            Button* button = mapEntry.second;
+
+            // iterate over all modes
+            for (int mode_index = 0; mode_index < 3; ++mode_index)
+            {
+                if (mode_index == new_mode) // skip commands that are already in the desired mode
+                    continue;
+
+                // iterate over all commands of the given mode at the given button
+                for (size_t command_index = 0; command_index < button->nCommands_[mode_index]; ++command_index)
+                {
+                    if (button->commands_[mode_index][command_index]->hasFixedKeybindMode())
+                        continue;
+
+                    CommandEvaluation* evaluation = button->commands_[mode_index][command_index]->getEvaluation();
+
+                    // compare the command
+                    if (evaluation && evaluation->getConsoleCommand() == command)
+                    {
+                        // increase array of new mode
+                        BaseCommand** array_new_mode = new BaseCommand*[button->nCommands_[new_mode] + 1];
+                        // copy array content
+                        for (size_t c = 0; c < button->nCommands_[new_mode]; ++c)
+                            array_new_mode[c] = button->commands_[new_mode][c];
+                        // insert changed command at the end
+                        array_new_mode[button->nCommands_[new_mode]] = button->commands_[mode_index][command_index];
+                        // delete old array
+                        delete[] button->commands_[new_mode];
+                        // assign new array
+                        button->commands_[new_mode] = array_new_mode;
+                        // increase counter
+                        button->nCommands_[new_mode]++;
+
+                        // erase command from old array
+                        for (size_t c = command_index; c < button->nCommands_[mode_index] - 1; ++c)
+                            button->commands_[mode_index][c] = button->commands_[mode_index][c + 1];
+                        // decrease counter
+                        button->nCommands_[mode_index]--;
+                        // old array would not get deleted if nCommands_ is now 0
+                        // otherwise: nobody cares about an array that is one element too large - nCommands_ defines the size
+                        if (button->nCommands_[mode_index] == 0)
+                        {
+                            delete[] button->commands_[mode_index];
+                            button->commands_[mode_index] = nullptr;
+                        }
+
+                        // decrement the index since we shifted the array and continue searching for more occurrences of the command
+                        command_index--;
+                    }
+                }
+            }
+        }
+    }
+
+    void KeyBinder::resetJoyStickAxes()
+    {
+        for (unsigned int iDev = 0; iDev < joySticks_.size(); ++iDev)
+            for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
+                (*joyStickAxes_[iDev])[i].reset();
+    }
+
+    /**
+        @brief Sets the position of the mouse back to 0/0.
+    */
+    void KeyBinder::resetMouseAxes()
+    {
+        this->mousePosition_[0] = 0.0f;
+        this->mousePosition_[1] = 0.0f;
+
+        for (HalfAxis& axis : mouseAxes_)
+            axis.reset();
+    }
+
+    void KeyBinder::mouseUpdated(float dt)
+    {
+        if (bDeriveMouseInput_)
+        {
+            // only update when derivation dt has passed
+            if (deriveTime_ > derivePeriod_)
+            {
+                for (int i = 0; i < 2; i++)
+                {
+                    if (mouseRelative_[i] < 0)
+                    {
+                        mouseAxes_[2*i + 0].absVal_
+                            = -mouseRelative_[i] / deriveTime_ * 0.0005f * mouseSensitivityDerived_;
+                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
+                    }
+                    else if (mouseRelative_[i] > 0)
+                    {
+                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
+                        mouseAxes_[2*i + 1].absVal_
+                            =  mouseRelative_[i] / deriveTime_ * 0.0005f * mouseSensitivityDerived_;
+                    }
+                    else
+                    {
+                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
+                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
+                    }
+                    mouseRelative_[i] = 0;
+                    mouseAxes_[2*i + 0].hasChanged_ = true;
+                    mouseAxes_[2*i + 1].hasChanged_ = true;
+                }
+                deriveTime_ = 0.0f;
+            }
+            else
+                deriveTime_ += dt;
+        }
+
+        for (HalfAxis& axis : mouseAxes_)
+        {
+            // Why dividing relative value by dt? The reason lies in the simple fact, that when you
+            // press a button that has relative movement, that value has to be multiplied by dt to be
+            // frame rate independent. This can easily (and only) be done in updateInput(float).
+            // Hence we need to divide by dt here for the mouse to compensate, because the relative
+            // move movements have nothing to do with dt.
+            if (dt != 0.0f)
+            {
+                // just ignore if dt == 0.0 because we have multiplied by 0.0 anyway..
+                axis.relVal_ /= dt;
+            }
+
+            tickHalfAxis(axis);
+        }
+    }
+
+    void KeyBinder::joyStickUpdated(unsigned int joyStick, float dt)
+    {
+        for (unsigned int i = 0; i < JoyStickAxisCode::numberOfAxes * 2; i++)
+        {
+            tickHalfAxis((*joyStickAxes_[joyStick])[i]);
+        }
+    }
+
+    void KeyBinder::tickHalfAxis(HalfAxis& halfAxis)
+    {
+        // button mode
+        // TODO: optimize out all the half axes that don't act as a button at the moment
+        if (halfAxis.hasChanged_)
+        {
+            if (!halfAxis.pressed_ && halfAxis.absVal_ > halfAxis.buttonThreshold_)
+            {
+                // key pressed event
+                halfAxis.pressed_ = true;
+                if (halfAxis.nCommands_[KeybindMode::OnPress])
+                    halfAxis.execute(KeybindMode::OnPress);
+            }
+            else if (halfAxis.pressed_ && halfAxis.absVal_ < halfAxis.buttonThreshold_)
+            {
+                // key released event
+                halfAxis.pressed_ = false;
+                if (halfAxis.nCommands_[KeybindMode::OnRelease])
+                    halfAxis.execute(KeybindMode::OnRelease);
+            }
+            halfAxis.hasChanged_ = false;
+        }
+
+        if (halfAxis.pressed_)
+        {
+            // key held event
+            if (halfAxis.nCommands_[KeybindMode::OnHold])
+                halfAxis.execute(KeybindMode::OnHold);
+        }
+
+        // these are the actually useful axis bindings for analog input
+        halfAxis.execute();
+    }
+
+    /**
+    @brief
+        Event handler for the mouseMoved Event.
+    @param abs_
+        The absolute position of the mouse
+    @param rel_
+        The relative movement of the mouse
+    @param clippingSize
+        Mouse screen area in pixels (usually 1024x1024)
+    */
+    void KeyBinder::mouseMoved(IntVector2 abs_, IntVector2 rel_, IntVector2 clippingSize)
+    {
+        // y axis of mouse input is inverted
+        int rel[] = { rel_.x, -rel_.y };
+
+        if (bDeriveMouseInput_)
+        {
+            mouseRelative_[0] += rel[0];
+            mouseRelative_[1] += rel[1];
+        }
+        else
+        {
+            for (int i = 0; i < 2; i++)
+            {
+                if (rel[i]) // performance opt. for the case that rel[i] == 0
+                {
+                    // write absolute values
+                    mouseAxes_[2*i + 0].hasChanged_ = true;
+                    mouseAxes_[2*i + 1].hasChanged_ = true;
+                    mousePosition_[i] += rel[i] * totalMouseSensitivity_;
+
+                    // clip absolute position
+                    if (mousePosition_[i] > 1.0)
+                        mousePosition_[i] =  1.0;
+                    if (mousePosition_[i] < -1.0)
+                        mousePosition_[i] = -1.0;
+
+                    if (mousePosition_[i] < 0.0)
+                    {
+                        mouseAxes_[2*i + 0].absVal_ = -mousePosition_[i];
+                        mouseAxes_[2*i + 1].absVal_ = 0.0f;
+                    }
+                    else
+                    {
+                        mouseAxes_[2*i + 0].absVal_ = 0.0f;
+                        mouseAxes_[2*i + 1].absVal_ =  mousePosition_[i];
+                    }
+                }
+            }
+        }
+
+        // relative
+        for (int i = 0; i < 2; i++)
+        {
+            if (rel[i] < 0)
+                mouseAxes_[0 + 2*i].relVal_ = -rel[i] * totalMouseSensitivity_;
+            else
+                mouseAxes_[1 + 2*i].relVal_ =  rel[i] * totalMouseSensitivity_;
+        }
+    }
+
+    /**
+    @brief Event handler for the mouseScrolled Event.
+    @param abs The absolute position of the scroll wheel
+    @param rel The relative movement of the scroll wheel
+    */
+    void KeyBinder::mouseScrolled(int abs, int rel)
+    {
+        if (rel < 0)
+            for (int i = 0; i < -rel/mouseWheelStepSize_; i++)
+                mouseButtons_[8].execute(KeybindMode::OnPress, static_cast<float>(abs)/mouseWheelStepSize_);
+        else
+            for (int i = 0; i < rel/mouseWheelStepSize_; i++)
+                mouseButtons_[9].execute(KeybindMode::OnPress, static_cast<float>(abs)/mouseWheelStepSize_);
+    }
+
+    void KeyBinder::axisMoved(unsigned int device, unsigned int axisID, float value)
+    {
+        // Filter analog noise
+        if (this->bFilterAnalogNoise_ && std::abs(value) < this->analogThreshold_)
+            value = 0.0;
+        int i = axisID * 2;
+        JoyStickAxisVector& axis = *joyStickAxes_[device];
+        if (value < 0)
+        {
+            axis[i].absVal_ = -value;
+            axis[i].relVal_ = -value;
+            axis[i].hasChanged_ = true;
+            if (axis[i + 1].absVal_ > 0.0f)
+            {
+                axis[i + 1].absVal_ = -0.0f;
+                axis[i + 1].relVal_ = -0.0f;
+                axis[i + 1].hasChanged_ = true;
+            }
+        }
+        else
+        {
+            axis[i + 1].absVal_ = value;
+            axis[i + 1].relVal_ = value;
+            axis[i + 1].hasChanged_ = true;
+            if (axis[i].absVal_ > 0.0f)
+            {
+                axis[i].absVal_ = -0.0f;
+                axis[i].relVal_ = -0.0f;
+                axis[i].hasChanged_ = true;
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinder.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinder.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinder.h	(revision 11817)
@@ -0,0 +1,241 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _KeyBinder_H__
+#define _KeyBinder_H__
+
+#include "InputPrereqs.h"
+
+#include <cassert>
+#include <string>
+#include <vector>
+#include <map>
+#include <memory>
+
+#include "InputHandler.h"
+#include "Button.h"
+#include "HalfAxis.h"
+#include "InputCommands.h"
+#include "JoyStickQuantityListener.h"
+
+// tolua_begin
+namespace orxonox
+{
+    // tolua_end
+    /**
+    @brief
+        Maps mouse, keyboard and joy stick input to command strings and executes them.
+
+        The bindings are stored in ini-files (like the one for configValues) in the config Path.
+    @remarks
+        You cannot change the filename because the KeyBinderManager maps these filenames to the
+        KeyBinders. If you need to load other bindings, just create a new one.
+    */
+    class _CoreExport KeyBinder // tolua_export
+        : public InputHandler, public JoyStickQuantityListener
+    { // tolua_export
+    public:
+        KeyBinder (const std::string& filename);
+        virtual ~KeyBinder();
+
+        void clearBindings();
+        bool setBinding(const std::string& binding, const std::string& name, bool bTemporary = false);
+        std::string getBinding(const std::string& commandName); //tolua_export
+        std::string getBinding(const std::string& commandName, unsigned int index); //tolua_export
+        std::string getBindingReadable(const std::string& commandName); //tolua_export
+        unsigned int getNumberOfBindings(const std::string& commandName); //tolua_export
+
+        const std::string& getBindingsFilename()
+            { return this->filename_; }
+        void setConfigValues();
+        void resetJoyStickAxes();
+        void resetMouseAxes();
+
+        void changeMode(ConsoleCommand* command, KeybindMode::Value mode);
+
+    protected: // functions
+        void loadBindings();
+        void buttonThresholdChanged();
+        void initialiseJoyStickBindings();
+        void compilePointerLists();
+        // from JoyStickQuantityListener interface
+        virtual void JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList) override;
+
+        virtual void allDevicesUpdated(float dt) override;
+        virtual void mouseUpdated(float dt) override;
+        virtual void joyStickUpdated(unsigned int joyStick, float dt) override;
+        // internal
+        void tickHalfAxis(HalfAxis& halfAxis);
+
+        virtual void buttonPressed (const KeyEvent& evt) override;
+        virtual void buttonReleased(const KeyEvent& evt) override;
+        virtual void buttonHeld    (const KeyEvent& evt) override;
+
+        virtual void buttonPressed (MouseButtonCode::ByEnum button) override;
+        virtual void buttonReleased(MouseButtonCode::ByEnum button) override;
+        virtual void buttonHeld    (MouseButtonCode::ByEnum button) override;
+        virtual void mouseMoved    (IntVector2 abs, IntVector2 rel, IntVector2 clippingSize) override;
+        virtual void mouseScrolled (int abs, int rel) override;
+
+        virtual void buttonPressed (unsigned int device, JoyStickButtonCode::ByEnum button) override;
+        virtual void buttonReleased(unsigned int device, JoyStickButtonCode::ByEnum button) override;
+        virtual void buttonHeld    (unsigned int device, JoyStickButtonCode::ByEnum button) override;
+        virtual void axisMoved     (unsigned int device, unsigned int axis, float value) override;
+
+    protected: // variables
+        //! Currently active joy sticks
+        std::vector<JoyStick*>  joySticks_;
+
+        //! Actual key bindings for keys on the keyboard
+        Button keys_            [KeyCode::numberOfKeys];
+        //! Number of mouse buttons in KeyBinder (+4)
+        static const unsigned int numberOfMouseButtons_ = MouseButtonCode::numberOfButtons + 4;
+        //! Actual key bindings for mouse buttons including the wheel(s)
+        Button mouseButtons_    [numberOfMouseButtons_];
+        //! Actual key bindings for mouse axes
+        HalfAxis mouseAxes_     [MouseAxisCode::numberOfAxes * 2];
+
+        //! Helper class to use something like std:vector<Button[64]>
+        struct JoyStickButtonVector
+        {
+            Button& operator[](unsigned int index) { return buttons[index]; }
+            Button buttons[JoyStickButtonCode::numberOfButtons];
+        };
+        //! Actual key bindings for joy stick buttons
+        std::vector<std::shared_ptr<JoyStickButtonVector>> joyStickButtons_;
+        //! Helper class to use something like std:vector<HalfAxis[48]>
+        struct JoyStickAxisVector
+        {
+            HalfAxis& operator[](unsigned int index) { return halfAxes[index]; }
+            HalfAxis halfAxes[JoyStickAxisCode::numberOfAxes * 2];
+        };
+        //! Actual key bindings for joy stick axes (and sliders)
+        std::vector<std::shared_ptr<JoyStickAxisVector>> joyStickAxes_;
+
+        //! Pointer map with all Buttons, including half axes
+        std::map<std::string, Button*> allButtons_;
+        //! Pointer list with all half axes
+        std::vector<HalfAxis*> allHalfAxes_;
+        //! Maps input commands to all Button names, including half axes
+        std::map< std::string, std::vector<std::string>> allCommands_;
+
+        /**
+        @brief
+            Commands that have additional parameters (axes) are executed at the end of
+            update() so that all values can be buffered for single execution.
+        */
+        std::vector<BufferedParamCommand*> paramCommandBuffer_;
+
+        //! Keeps track of the absolute mouse value
+        float mousePosition_[2];
+        //! Used to derive mouse input if requested
+        int mouseRelative_[2];
+        float deriveTime_;
+
+        //! Name of the file used in this KeyBinder (constant!)
+        const std::string filename_;
+        //! Config file used. nullptr in case of KeyDetector. Also indicates whether we've already loaded.
+        ConfigFile* configFile_;
+        //! Config file from the data directory that only serves as fallback
+        ConfigFile* fallbackConfigFile_;
+
+    private:
+        void addButtonToCommand(const std::string& command, Button* button);
+
+        //##### ConfigValues #####
+        //! Whether to filter small value analog input
+        bool bFilterAnalogNoise_;
+        //! Threshold for analog triggers until which the state is 0.
+        float analogThreshold_;
+        //! Threshold for analog triggers until which the button is not pressed.
+        float buttonThreshold_;
+        //! Derive mouse input for absolute values?
+        bool bDeriveMouseInput_;
+        //! Accuracy of the mouse input deriver. The higher the more precise, but laggier.
+        float derivePeriod_;
+        //! mouse sensitivity
+        float mouseSensitivity_;
+        //! mouse sensitivity if mouse input is derived
+        float mouseSensitivityDerived_;
+        //! Equals one step of the mouse wheel
+        int mouseWheelStepSize_;
+
+        //! Multiplication of mouse sensitivity and clipping size
+        float totalMouseSensitivity_;
+
+        //##### Constant config variables #####
+        // Use some value at about 1000. This can be configured with mouseSensitivity_ anyway.
+        static const int mouseClippingSize_ = 1024;
+    };// tolua_export
+
+
+    inline void KeyBinder::buttonPressed (const KeyEvent& evt)
+    { assert(!keys_[evt.getKeyCode()].name_.empty()); keys_[evt.getKeyCode()].execute(KeybindMode::OnPress, 1); }
+
+    inline void KeyBinder::buttonReleased(const KeyEvent& evt)
+    { assert(!keys_[evt.getKeyCode()].name_.empty()); keys_[evt.getKeyCode()].execute(KeybindMode::OnRelease, 0); }
+
+    inline void KeyBinder::buttonHeld    (const KeyEvent& evt)
+    { assert(!keys_[evt.getKeyCode()].name_.empty()); keys_[evt.getKeyCode()].execute(KeybindMode::OnHold); }
+
+
+    inline void KeyBinder::buttonPressed (MouseButtonCode::ByEnum button)
+    { mouseButtons_[button].execute(KeybindMode::OnPress, 1); }
+
+    inline void KeyBinder::buttonReleased(MouseButtonCode::ByEnum button)
+    { mouseButtons_[button].execute(KeybindMode::OnRelease, 0); }
+
+    inline void KeyBinder::buttonHeld    (MouseButtonCode::ByEnum button)
+    { mouseButtons_[button].execute(KeybindMode::OnHold); }
+
+
+    inline void KeyBinder::buttonPressed (unsigned int device, JoyStickButtonCode::ByEnum button)
+    { (*joyStickButtons_[device])[button].execute(KeybindMode::OnPress, 1); }
+
+    inline void KeyBinder::buttonReleased(unsigned int device, JoyStickButtonCode::ByEnum button)
+    { (*joyStickButtons_[device])[button].execute(KeybindMode::OnRelease, 0); }
+
+    inline void KeyBinder::buttonHeld    (unsigned int device, JoyStickButtonCode::ByEnum button)
+    { (*joyStickButtons_[device])[button].execute(KeybindMode::OnHold); }
+
+    inline void KeyBinder::allDevicesUpdated(float dt)
+    {
+        // execute all buffered bindings (additional parameter)
+        for (BufferedParamCommand* command : paramCommandBuffer_)
+        {
+            command->rel_ *= dt;
+            command->execute();
+        }
+
+        // always reset the relative movement of the mouse
+        for (HalfAxis& axis : mouseAxes_)
+            axis.relVal_ = 0.0f;
+    }
+}// tolua_export
+
+#endif /* _KeyBinder_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinderManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinderManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinderManager.cc	(revision 11817)
@@ -0,0 +1,209 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "KeyBinderManager.h"
+
+#include "util/Output.h"
+#include "util/Exception.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/LuaState.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "InputManager.h"
+#include "KeyDetector.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(KeyBinderManager, ScopeID::GRAPHICS, false);
+
+    static const std::string __CC_keybind_name = "keybind";
+    static const std::string __CC_tkeybind_name = "tkeybind";
+    static const std::string __CC_unbind_name = "unbind";
+    static const std::string __CC_tunbind_name = "tunbind";
+
+    SetConsoleCommand(__CC_keybind_name,  &KeyBinderManager::keybind).defaultValues("").argumentCompleter(0, autocompletion::command());
+    SetConsoleCommand(__CC_tkeybind_name, &KeyBinderManager::tkeybind).defaultValues("").argumentCompleter(0, autocompletion::command());
+    SetConsoleCommand(__CC_unbind_name,   &KeyBinderManager::unbind).defaultValues("");
+    SetConsoleCommand(__CC_tunbind_name,  &KeyBinderManager::tunbind).defaultValues("");
+
+    RegisterAbstractClass(KeyBinderManager).inheritsFrom<Configurable>();
+
+    KeyBinderManager::KeyBinderManager()
+        : currentBinder_(nullptr)
+        , bDefaultFileLoaded_(true)
+        , bBinding_(false)
+    {
+        RegisterObject(KeyBinderManager);
+        this->setConfigValues();
+
+        // keybind console commands
+        ModifyConsoleCommand(__CC_keybind_name ).setObject(this);
+        ModifyConsoleCommand(__CC_tkeybind_name).setObject(this);
+        ModifyConsoleCommand(__CC_unbind_name  ).setObject(this);
+        ModifyConsoleCommand(__CC_tunbind_name ).setObject(this);
+
+        // Load default key binder
+        this->setCurrent(defaultFilename_);
+    }
+
+    KeyBinderManager::~KeyBinderManager()
+    {
+        // Delete all remaining KeyBinders
+        for (const auto& mapEntry : this->binders_)
+            delete mapEntry.second;
+
+        // Reset console commands
+        ModifyConsoleCommand(__CC_keybind_name ).setObject(nullptr);
+        ModifyConsoleCommand(__CC_tkeybind_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_unbind_name  ).setObject(nullptr);
+        ModifyConsoleCommand(__CC_tunbind_name ).setObject(nullptr);
+    }
+
+    void KeyBinderManager::setConfigValues()
+    {
+        SetConfigValue(defaultFilename_, "keybindings.ini")
+            .description("Filename for the default keybindings file.")
+            .callback(this, &KeyBinderManager::defaultFilenameChanged);
+    }
+
+    void KeyBinderManager::defaultFilenameChanged()
+    {
+        if (this->bDefaultFileLoaded_)
+            this->setCurrent(this->defaultFilename_);
+    }
+
+    void KeyBinderManager::setCurrent(const std::string& filename)
+    {
+        this->currentBinder_ = this->get(filename);
+        if (filename == this->defaultFilename_)
+            this->bDefaultFileLoaded_ = true;
+        else
+            this->bDefaultFileLoaded_ = false;
+    }
+
+    inline void KeyBinderManager::unbind(const std::string& binding)
+    {
+        this->currentBinder_->setBinding("", binding, false);
+    }
+
+    inline void KeyBinderManager::tunbind(const std::string& binding)
+    {
+        this->currentBinder_->setBinding("", binding, true);
+    }
+
+    void KeyBinderManager::load(const std::string& filename)
+    {
+        std::map<std::string, KeyBinder*>::const_iterator it = this->binders_.find(filename);
+        if (it != this->binders_.end())
+            return;
+
+        KeyBinder* binder = new KeyBinder(filename);
+        this->binders_[filename] = binder;
+    }
+
+    void KeyBinderManager::unload(const std::string& filename)
+    {
+        if (filename == this->defaultFilename_)
+            ThrowException(General, "KeyBinderManager: Cannot unload the default file");
+        if (filename == this->currentBinder_->getBindingsFilename())
+        {
+            // unloading current file --> set default file
+            this->setCurrent(this->defaultFilename_);
+        }
+        std::map<std::string, KeyBinder*>::iterator it = this->binders_.find(filename);
+        if (it != this->binders_.end())
+        {
+            delete it->second;
+            this->binders_.erase(it);
+        }
+    }
+
+    KeyBinder* KeyBinderManager::get(const std::string& name)
+    {
+        this->load(name);
+        return this->binders_[name];
+    }
+
+    InputHandler* KeyBinderManager::getCurrentAsHandler()
+    {
+        return this->getCurrent();
+    }
+
+    InputHandler* KeyBinderManager::getDefaultAsHandler()
+    {
+        return this->getDefault();
+    }
+
+    InputHandler* KeyBinderManager::getAsHandler(const std::string& name)
+    {
+        return this->get(name);
+    }
+
+    void KeyBinderManager::keybindInternal(const std::string& command, bool bTemporary)
+    {
+        if (!this->bBinding_)
+        {
+            orxout(message) << "Press any button/key or move a mouse/joystick axis" << endl;
+            KeyDetector::getInstance().setCallback(createFunctor(&KeyBinderManager::keybindKeyPressed, this));
+            InputManager::getInstance().enterState("detector");
+            this->command_ = command;
+            this->bTemporary_ = bTemporary;
+            this->bBinding_ = true;
+        }
+        // else: We're still in a keybind command. Ignore this call.
+    }
+
+    // Gets called by the KeyDetector (registered with a Functor)
+    void KeyBinderManager::keybindKeyPressed(const std::string& keyName)
+    {
+        if (this->bBinding_)
+        {
+            if (keyName == "Keys.KeyEscape")
+            {
+                orxout(message) << "Keybinding aborted." << endl;
+            }
+            else
+            {
+                orxout(message) << "Binding string \"" << command_ << "\" on key '" << keyName << "'" << endl;
+                this->currentBinder_->setBinding(command_, keyName, bTemporary_);
+            }
+            InputManager::getInstance().leaveState("detector");
+            // inform whatever was calling the command
+            if (this->callbackFunction_)
+                (*this->callbackFunction_)();
+            this->bBinding_ = false;
+        }
+        // else: A key was probably pressed within the same tick, ignore it.
+    }
+
+    void KeyBinderManager::registerKeybindCallback(LuaFunctor* function)
+    {
+        this->callbackFunction_.reset(function);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinderManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinderManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/KeyBinderManager.h	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _KeyBinderManager_H__
+#define _KeyBinderManager_H__
+
+#include "InputPrereqs.h"
+
+#include <map>
+#include <string>
+#include <memory>
+
+#include "util/Singleton.h"
+#include "core/config/Configurable.h"
+
+namespace orxonox //tolua_export
+{ //tolua_export
+    /**
+    @brief
+        Handles the KeyBinders and supplies them throughout the game.
+
+        This interface merely serves to provide a static "keybind" command that always
+        maps to the currently active KeyBinder. You can set that with setCurrent().
+        There is also a default one, retrieved with getDefault(). The idea is that
+        mostly the default KeyBinder is active except for special situations (mini-game for inst).
+    @remarks
+        You are not forced to use the KeyBinder imposed by getCurrent(). But be aware that "keybind"
+        will not work as expected!
+    */
+    class _CoreExport KeyBinderManager //tolua_export
+        : public Singleton<KeyBinderManager>, public Configurable
+    { //tolua_export
+        friend class Singleton<KeyBinderManager>;
+    public:
+        KeyBinderManager();
+        ~KeyBinderManager();
+        void setConfigValues();
+
+        static KeyBinderManager& getInstance() { return Singleton<KeyBinderManager>::getInstance(); } //tolua_export
+        //! Returns the currently selected KeyBinder
+        KeyBinder* getCurrent() { return this->currentBinder_; } //tolua_export
+        //! Like getCurrent(), but returns it as InputHandler* (so you don't have to include KeyBinder.h)
+        InputHandler* getCurrentAsHandler();
+        //! Selects the current KeyBinder and creates it if not yet loaded.
+        void setCurrent(const std::string& filename);
+
+        //! Returns the default KeyBinder
+        KeyBinder* getDefault()
+            { return binders_[this->defaultFilename_]; }
+        //! Returns the default KeyBinder as InputHandler* (so you don't have to include KeyBinder.h)
+        InputHandler* getDefaultAsHandler();
+        //! Returns the filename of the default key bindings
+        const std::string& getDefaultFilename()
+            { return defaultFilename_; }
+        //! Selects the default KeyBinder as current one
+        void setToDefault()
+            { this->setCurrent(this->defaultFilename_); }
+
+        //! Returns a pointer to a KeyBinder (creates it if not yet loaded)
+        KeyBinder* get(const std::string& name);
+        //! Like get() but return value is of type InputHandler* (so you don't have to include KeyBinder.h)
+        InputHandler* getAsHandler(const std::string& name);
+
+        //! Loads a KeyBinder by creating it (no different from get() except for the return value)
+        void load(const std::string& filename);
+        //! Destroys a KeyBinder completely (does nothing if not yet loaded)
+        void unload(const std::string& filename);
+
+        //! Bind 'command' to any key pressed after this call (use with care!)
+        inline void keybind(const std::string& command) { this->keybindInternal(command, false); } //tolua_export
+        //! Bind 'command' to any key pressed after this call (use with care!), but temporarily (no file save)
+        inline void tkeybind(const std::string& command)
+            { this->keybindInternal(command, true); }
+        void unbind(const std::string& binding); //tolua_export
+        void tunbind(const std::string& binding);
+        void registerKeybindCallback(LuaFunctor* function); //tolua_export
+
+    private:
+        // non-copyable:
+        KeyBinderManager(const KeyBinderManager&) = delete;
+        KeyBinderManager& operator=(const KeyBinderManager&) = delete;
+
+        void keybindInternal(const std::string& command, bool bTemporary);
+        void keybindKeyPressed(const std::string& keyName);
+        void defaultFilenameChanged();
+
+        // KeyBinder management
+        KeyBinder* currentBinder_;                      //! Currently selected KeyBinder (never nullptr!)
+        std::map<std::string, KeyBinder*> binders_;     //! All loaded KeyBinders
+        bool bDefaultFileLoaded_;                       //! Tells whether the default one is loaded
+        std::string defaultFilename_;                   //! Name of the file with the default key bindings
+
+        // keybind command related
+        std::shared_ptr<LuaFunctor> callbackFunction_;  //! Function to be called when key was pressed after "keybind" command
+        bool bBinding_;                                 //! Tells whether a key binding process is active
+        bool bTemporary_;                               //! Stores tkeybind/keybind value
+        std::string command_;                           //! Stores the command received by (t)keybind
+
+        static KeyBinderManager* singletonPtr_s;
+    }; //tolua_export
+} //tolua_export
+
+#endif /* _KeyBinderManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/KeyDetector.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/KeyDetector.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/KeyDetector.cc	(revision 11817)
@@ -0,0 +1,88 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "KeyDetector.h"
+
+#include "core/CoreIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "Button.h"
+#include "InputManager.h"
+#include "InputState.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(KeyDetector, ScopeID::GRAPHICS, false);
+
+    static const std::string __CC_KeyDetector_callback_name = "KeyDetectorKeyPressed";
+    DeclareConsoleCommand(__CC_KeyDetector_callback_name, &prototype::void__string).hide();
+
+    RegisterAbstractClass(KeyDetector).inheritsFrom<KeyBinder>();
+
+    KeyDetector::KeyDetector()
+        : KeyBinder("")
+    {
+        RegisterObject(KeyDetector);
+
+        ModifyConsoleCommand(__CC_KeyDetector_callback_name).setFunction(&KeyDetector::callback, this);
+
+        this->assignCommands();
+
+        inputState_ = InputManager::getInstance().createInputState("detector", false, false, InputStatePriority::Detector);
+        // Create a callback to avoid buttonHeld events after the key has been detected
+        inputState_->setLeaveFunctor(createFunctor(&InputManager::clearBuffers, &InputManager::getInstance()));
+        inputState_->setHandler(this);
+    }
+
+    KeyDetector::~KeyDetector()
+    {
+        inputState_->setHandler(nullptr);
+        InputManager::getInstance().destroyState("detector");
+        ModifyConsoleCommand(__CC_KeyDetector_callback_name).resetFunction();
+    }
+
+    void KeyDetector::assignCommands()
+    {
+        // Assign every button/axis the same command, but with its name as argument
+        for (const auto& mapEntry : allButtons_)
+            mapEntry.second->parse(__CC_KeyDetector_callback_name + ' ' + mapEntry.second->groupName_ + "." + mapEntry.second->name_);
+    }
+
+    void KeyDetector::callback(const std::string& name)
+    {
+        // Call the registered function
+        if (this->callbackFunction_)
+            (*this->callbackFunction_)(name);
+    }
+
+    void KeyDetector::JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList)
+    {
+        KeyBinder::JoyStickQuantityChanged(joyStickList);
+        this->assignCommands();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/KeyDetector.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/KeyDetector.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/KeyDetector.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _KeyDetector_H__
+#define _KeyDetector_H__
+
+#include "InputPrereqs.h"
+
+#include "util/Singleton.h"
+#include "KeyBinder.h"
+
+namespace orxonox
+{
+    class _CoreExport KeyDetector : public KeyBinder, public Singleton<KeyDetector>
+    {
+        friend class Singleton<KeyDetector>;
+
+    public:
+        KeyDetector();
+        ~KeyDetector();
+
+        void setCallback(const FunctorPtr& function) { this->callbackFunction_ = function; }
+
+    private:
+        // non-copyable:
+        KeyDetector(const KeyDetector&) = delete;
+        KeyDetector& operator=(const KeyDetector&) = delete;
+
+        void callback(const std::string& name);
+        virtual void JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList) override;
+        void assignCommands();
+
+        FunctorPtr callbackFunction_;
+        InputState* inputState_;
+        static KeyDetector* singletonPtr_s;
+    };
+}
+
+#endif /* _KeyDetector_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/Keyboard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/Keyboard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/Keyboard.cc	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Keyboard.h"
+#include "InputState.h"
+
+namespace orxonox
+{
+    //! OIS event handler
+    bool Keyboard::keyPressed(const OIS::KeyEvent& arg)
+    {
+        // update modifiers
+        switch (arg.key)
+        {
+            case OIS::KC_RMENU:
+            case OIS::KC_LMENU:
+                modifiers_ |= KeyboardModifier::Alt;   // alt key
+                break;
+            case OIS::KC_RCONTROL:
+            case OIS::KC_LCONTROL:
+                modifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
+                break;
+            case OIS::KC_RSHIFT:
+            case OIS::KC_LSHIFT:
+                modifiers_ |= KeyboardModifier::Shift; // shift key
+                break;
+            case OIS::KC_TAB:
+                // Do not distribute the alt+tab event (messes with the operating system)
+                if ((modifiers_ & KeyboardModifier::Alt) != 0)
+                    return true;
+            default:;
+        }
+
+        KeyEvent evt(static_cast<KeyCode::ByEnum>(arg.key), Keyboard::getKeyText(arg), 0);
+        super::buttonPressed(evt);
+        return true;
+    }
+
+    //! OIS event handler
+    bool Keyboard::keyReleased(const OIS::KeyEvent& arg)
+    {
+        // update modifiers
+        switch (arg.key)
+        {
+            case OIS::KC_RMENU:
+            case OIS::KC_LMENU:
+                modifiers_ &= ~KeyboardModifier::Alt;   // alt key
+                break;
+            case OIS::KC_RCONTROL:
+            case OIS::KC_LCONTROL:
+                modifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
+                break;
+            case OIS::KC_RSHIFT:
+            case OIS::KC_LSHIFT:
+                modifiers_ &= ~KeyboardModifier::Shift; // shift key
+                break;
+            default:;
+        }
+
+        KeyEvent evt(static_cast<KeyCode::ByEnum>(arg.key), Keyboard::getKeyText(arg), 0);
+        super::buttonReleased(evt);
+        return true;
+    }
+
+    /// A map which returns the corresponding chars for some key codes
+    unsigned int Keyboard::getKeyText(const OIS::KeyEvent& arg)
+    {
+        switch (arg.key)
+        {
+            case OIS::KC_NUMPAD0:     return static_cast<unsigned int>('0');
+            case OIS::KC_NUMPAD1:     return static_cast<unsigned int>('1');
+            case OIS::KC_NUMPAD2:     return static_cast<unsigned int>('2');
+            case OIS::KC_NUMPAD3:     return static_cast<unsigned int>('3');
+            case OIS::KC_NUMPAD4:     return static_cast<unsigned int>('4');
+            case OIS::KC_NUMPAD5:     return static_cast<unsigned int>('5');
+            case OIS::KC_NUMPAD6:     return static_cast<unsigned int>('6');
+            case OIS::KC_NUMPAD7:     return static_cast<unsigned int>('7');
+            case OIS::KC_NUMPAD8:     return static_cast<unsigned int>('8');
+            case OIS::KC_NUMPAD9:     return static_cast<unsigned int>('9');
+            case OIS::KC_DECIMAL:     return static_cast<unsigned int>('.');
+            case OIS::KC_DIVIDE:      return static_cast<unsigned int>('/');
+            case OIS::KC_NUMPADENTER: return static_cast<unsigned int>('\n');
+            default:                  return arg.text;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/Keyboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/Keyboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/Keyboard.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Core_Keyboard_H__
+#define _Core_Keyboard_H__
+
+#include "InputPrereqs.h"
+#include "InputDevice.h"
+
+namespace orxonox
+{
+    //! %Template parameter collection for the base class
+    struct KeyboardTraits
+    {
+        typedef Keyboard DeviceClass;
+        typedef OIS::Keyboard OISDeviceClass;
+        typedef KeyEvent ButtonType;
+        typedef KeyEvent& ButtonTypeParam;
+        static const OIS::Type OISDeviceValue = OIS::OISKeyboard;
+    };
+
+    /**
+    @brief
+        Wraps around an OIS::Mouse and forwards the input events to
+        a list of input states.
+
+        It also saves the state of the keyboard modifiers (like shift, etc.)
+    */
+    class _CoreExport Keyboard
+        : public InputDeviceTemplated<KeyboardTraits>
+        , public OIS::KeyListener
+    {
+        friend class InputDeviceTemplated<KeyboardTraits>;
+        //! Super class alias
+        typedef InputDeviceTemplated<KeyboardTraits> super;
+
+    public:
+        //! Only resets the keyboard modifiers. Initialising is done in the base class.
+        Keyboard(unsigned int id, OIS::InputManager* oisInputManager) : super(id, oisInputManager), modifiers_(0) { }
+        ~Keyboard() = default;
+
+    private:
+        //! Resets the keyboard modifiers
+        void clearBuffersImpl() { this->modifiers_ = 0; }
+        //! Translates the KeyHandle to a KeyEvent
+        KeyEvent& getButtonEventArg(KeyEvent& button)
+        {
+            button.setModifiers(modifiers_);
+            return button;
+        }
+
+        virtual bool keyPressed(const OIS::KeyEvent& arg) override;
+        virtual bool keyReleased(const OIS::KeyEvent& arg) override;
+
+        //! Returns the class name as string
+        static std::string getClassNameImpl() { return "Keyboard"; }
+
+        static unsigned int getKeyText(const OIS::KeyEvent& arg);
+
+        //! Bit mask representing keyboard modifiers
+        int modifiers_;
+    };
+}
+
+#endif /* _Core_Keyboard_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/Mouse.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/Mouse.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/Mouse.cc	(revision 11817)
@@ -0,0 +1,119 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Mouse.h"
+
+#include <ois/OISMouse.h>
+#include "core/CoreIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "InputState.h"
+
+#ifdef ORXONOX_PLATFORM_LINUX
+// include this as last, X11 seems to define some macros...
+#include <ois/linux/LinuxMouse.h>
+#undef Success
+#endif
+
+namespace orxonox
+{
+#ifdef ORXONOX_PLATFORM_LINUX
+    static const std::string __CC_Mouse_name = "Mouse";
+    static const std::string __CC_grab_name = "grab";
+    static const std::string __CC_ungrab_name = "ungrab";
+
+    SetConsoleCommand(__CC_Mouse_name, __CC_grab_name,   &Mouse::grab);
+    SetConsoleCommand(__CC_Mouse_name, __CC_ungrab_name, &Mouse::ungrab);
+#endif
+
+    RegisterAbstractClass(Mouse).inheritsFrom<WindowEventListener>();
+
+    Mouse::Mouse(unsigned int id, OIS::InputManager* oisInputManager)
+        : super(id, oisInputManager)
+    {
+        RegisterObject(Mouse);
+        this->windowResized(this->getWindowWidth(), this->getWindowHeight());
+
+#ifdef ORXONOX_PLATFORM_LINUX
+        ModifyConsoleCommand(__CC_Mouse_name, __CC_grab_name).setObject(this);
+        ModifyConsoleCommand(__CC_Mouse_name, __CC_ungrab_name).setObject(this);
+#endif
+    }
+
+    Mouse::~Mouse()
+    {
+#ifdef ORXONOX_PLATFORM_LINUX
+        ModifyConsoleCommand(__CC_Mouse_name, __CC_grab_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_Mouse_name, __CC_ungrab_name).setObject(nullptr);
+#endif
+    }
+
+    //! OIS event handler
+    bool Mouse::mouseMoved(const OIS::MouseEvent &e)
+    {
+        // check for actual moved event
+        if (e.state.X.rel != 0 || e.state.Y.rel != 0)
+        {
+            IntVector2 abs(e.state.X.abs, e.state.Y.abs);
+            IntVector2 rel(e.state.X.rel, e.state.Y.rel);
+            IntVector2 clippingSize(e.state.width, e.state.height);
+            for (InputState* state : inputStates_)
+                state->mouseMoved(abs, rel, clippingSize);
+        }
+
+        // check for mouse scrolled event
+        if (e.state.Z.rel != 0)
+        {
+            for (InputState* state : inputStates_)
+                state->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
+        }
+
+        return true;
+    }
+
+    void Mouse::windowResized(unsigned int newWidth, unsigned int newHeight)
+    {
+        oisDevice_->getMouseState().width  = newWidth;
+        oisDevice_->getMouseState().height = newHeight;
+    }
+
+#ifdef ORXONOX_PLATFORM_LINUX
+    void Mouse::grab()
+    {
+        OIS::LinuxMouse* linuxMouse = dynamic_cast<OIS::LinuxMouse*>(oisDevice_);
+        assert(linuxMouse);
+        linuxMouse->grab(true);
+    }
+
+    void Mouse::ungrab()
+    {
+        OIS::LinuxMouse* linuxMouse = dynamic_cast<OIS::LinuxMouse*>(oisDevice_);
+        assert(linuxMouse);
+        linuxMouse->grab(false);
+    }
+#endif
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/input/Mouse.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/input/Mouse.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/input/Mouse.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Core_Mouse_H__
+#define _Core_Mouse_H__
+
+#include "InputPrereqs.h"
+
+#include "InputDevice.h"
+#include "core/WindowEventListener.h"
+
+namespace orxonox
+{
+    //! %Template parameter collection for the base class
+    struct MouseTraits
+    {
+        typedef Mouse DeviceClass;
+        typedef OIS::Mouse OISDeviceClass;
+        typedef MouseButtonCode::ByEnum ButtonType;
+        typedef MouseButtonCode::ByEnum ButtonTypeParam;
+        static const OIS::Type OISDeviceValue = OIS::OISMouse;
+    };
+
+    /**
+    @brief
+        Wraps around an OIS::Mouse and forwards the input events to
+        a list of input states.
+    */
+    class _CoreExport Mouse
+        : public InputDeviceTemplated<MouseTraits>
+        , public OIS::MouseListener
+        , public WindowEventListener
+    {
+        friend class InputDeviceTemplated<MouseTraits>;
+        //! Super class alias
+        typedef InputDeviceTemplated<MouseTraits> super;
+
+    public:
+        //! Only sets the clipping size. Initialising is done in the base class.
+        Mouse(unsigned int id, OIS::InputManager* oisInputManager);
+        ~Mouse();
+
+#ifdef ORXONOX_PLATFORM_LINUX
+        // TODO: Make this a feature rather than a hack
+        void grab();
+        void ungrab();
+#endif
+
+    private:
+        //! OIS event handler
+        virtual bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id) override
+        {
+            super::buttonPressed(static_cast<MouseButtonCode::ByEnum>(id));
+            return true;
+        }
+
+        //! OIS event handler
+        virtual bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id) override
+        {
+            super::buttonReleased(static_cast<MouseButtonCode::ByEnum>(id));
+            return true;
+        }
+
+        virtual bool mouseMoved(const OIS::MouseEvent &arg) override;
+
+        virtual void windowResized(unsigned int newWidth, unsigned int newHeight) override;
+
+        // Returns the class name as string
+        static std::string getClassNameImpl() { return "Mouse"; }
+    };
+}
+
+#endif /* _Core_Mouse_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,11 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  DynLib.cc
+  DynLibManager.cc
+  ModuleInstance.cc
+  Plugin.cc
+  PluginManager.cc
+  PluginReference.cc
+  StaticallyInitializedInstance.cc
+  StaticInitializationHandlerIncludes.cc
+  StaticInitializationManager.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/DynLib.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/DynLib.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/DynLib.cc	(revision 11817)
@@ -0,0 +1,148 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+// 08/11/2009: Small adjustments for Orxonox by Fabian 'x3n' Landau
+
+#include "DynLib.h"
+
+#include <algorithm>
+
+#include "util/Exception.h"
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+#  define WIN32_LEAN_AND_MEAN
+#  ifndef NOMINMAX
+#    define NOMINMAX // required to stop windows.h messing up std::min
+#  endif
+#  include <windows.h>
+#endif
+
+#ifdef ORXONOX_PLATFORM_UNIX
+#  include <dlfcn.h>
+#endif
+
+#ifdef ORXONOX_PLATFORM_APPLE
+#   include <OSX/macUtils.h> // OGRE include
+#endif
+
+namespace orxonox
+{
+    //-----------------------------------------------------------------------
+    DynLib::DynLib( const std::string& name )
+    {
+        mName = name;
+        m_hInst = nullptr;
+    }
+
+    //-----------------------------------------------------------------------
+    DynLib::~DynLib()
+    {
+    }
+
+    //-----------------------------------------------------------------------
+    void DynLib::load()
+    {
+        // Log library load
+        orxout(internal_info) << "load DynLib " << mName << endl;
+
+        std::string name = mName;
+#ifdef ORXONOX_PLATFORM_LINUX
+        // dlopen() does not add .so to the filename, like windows does for .dll
+        if (name.substr(name.length() - 3, 3) != ".so")
+           name += ".so";
+#elif defined(ORXONOX_PLATFORM_APPLE)
+        // dlopen() does not add .dylib to the filename, like windows does for .dll
+        if (name.substr(name.length() - 6, 6) != ".dylib")
+            name += ".dylib";
+#elif defined(ORXONOX_PLATFORM_WINDOWS)
+        //altered search path doesn't work with paths with forward slashes
+        std::replace(name.begin(), name.end(), '/', '\\');
+        // Although LoadLibraryEx will add .dll itself when you only specify the library name,
+        // if you include a relative path then it does not. So, add it to be sure.
+        if (name.substr(name.length() - 4, 4) != ".dll")
+            name += ".dll";
+#endif
+
+        m_hInst = (DYNLIB_HANDLE)DYNLIB_LOAD( name.c_str() );
+
+        if (!m_hInst)
+            ThrowException(
+                General,
+                "Could not load dynamic library " + mName +
+                ".  System Error: " + dynlibError());
+    }
+
+    //-----------------------------------------------------------------------
+    void DynLib::unload()
+    {
+        // Log library unload
+        orxout(internal_info) << "unload DynLib " << mName << endl;
+
+        if (DYNLIB_UNLOAD( m_hInst ))
+        {
+            ThrowException(
+                General,
+                "Could not unload dynamic library " + mName +
+                ".  System Error: " + dynlibError());
+        }
+
+    }
+
+    //-----------------------------------------------------------------------
+    void* DynLib::getSymbol( const std::string& strName ) const throw()
+    {
+        return (void*)DYNLIB_GETSYM( m_hInst, strName.c_str() );
+    }
+    //-----------------------------------------------------------------------
+    std::string DynLib::dynlibError( void )
+    {
+#if defined(ORXONOX_PLATFORM_WINDOWS)
+        LPVOID lpMsgBuf;
+        FormatMessage(
+            FORMAT_MESSAGE_ALLOCATE_BUFFER |
+            FORMAT_MESSAGE_FROM_SYSTEM |
+            FORMAT_MESSAGE_IGNORE_INSERTS,
+            nullptr,
+            GetLastError(),
+            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+            (LPTSTR) &lpMsgBuf,
+            0,
+            nullptr
+            );
+        std::string ret = (char*)lpMsgBuf;
+        // Free the buffer.
+        LocalFree( lpMsgBuf );
+        return ret;
+#elif defined(ORXONOX_PLATFORM_UNIX)
+        return std::string(dlerror());
+#else
+        return "";
+#endif
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/DynLib.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/DynLib.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/DynLib.h	(revision 11817)
@@ -0,0 +1,119 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+// 08/11/2009: Small adjustments for Orxonox by Fabian 'x3n' Landau
+
+/**
+    @file
+    @ingroup Management CoreGame
+    @brief Declaration of DynLib which represents a dynamically loaded module.
+*/
+
+#ifndef _Core_DynLib_H__
+#define _Core_DynLib_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+
+#if defined(ORXONOX_PLATFORM_WINDOWS)
+#    define DYNLIB_HANDLE hInstance
+#    define DYNLIB_LOAD( a ) LoadLibraryEx( a, nullptr, LOAD_WITH_ALTERED_SEARCH_PATH )
+#    define DYNLIB_GETSYM( a, b ) GetProcAddress( a, b )
+#    define DYNLIB_UNLOAD( a ) !FreeLibrary( a )
+
+struct HINSTANCE__;
+typedef struct HINSTANCE__* hInstance;
+
+#elif defined(ORXONOX_PLATFORM_UNIX)
+#    define DYNLIB_HANDLE void*
+#    define DYNLIB_LOAD( a ) dlopen( a, RTLD_LAZY | RTLD_GLOBAL)
+#    define DYNLIB_GETSYM( a, b ) dlsym( a, b )
+#    define DYNLIB_UNLOAD( a ) dlclose( a )
+#endif
+
+namespace orxonox
+{
+    /** %Resource holding data about a dynamic library.
+        @remarks
+            This class holds the data required to get symbols from
+            libraries loaded at run-time (i.e. from DLL's for so's)
+        @author
+            Adrian Cearnãu (cearny@cearny.ro)
+        @since
+            27 January 2002
+    */
+    class _CoreExport DynLib
+    {
+    protected:
+        std::string mName;
+        /// Gets the last loading error
+        std::string dynlibError(void);
+    public:
+        /** Default constructor - used by DynLibManager.
+            @warning
+                Do not call directly
+        */
+        DynLib( const std::string& name );
+
+        /** Default destructor.
+        */
+        ~DynLib();
+
+        /** Load the library
+        */
+        void load();
+        /** Unload the library
+        */
+        void unload();
+        /// Get the name of the library
+        const std::string& getName(void) const { return mName; }
+
+        /**
+            Returns the address of the given symbol from the loaded library.
+            @param
+                strName The name of the symbol to search for
+            @returns
+                If the function succeeds, the returned value is a handle to
+                the symbol.
+            @par
+                If the function fails, the returned value is <b>nullptr</b>.
+
+        */
+        void* getSymbol( const std::string& strName ) const throw();
+
+    protected:
+
+        /// Handle to the loaded library.
+        DYNLIB_HANDLE m_hInst;
+    };
+
+}
+
+#endif /* _Core_DynLib_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/DynLibManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/DynLibManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/DynLibManager.cc	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+// 08/11/2009: Small adjustments for Orxonox by Fabian 'x3n' Landau
+
+#include "DynLibManager.h"
+
+#include "DynLib.h"
+
+namespace orxonox
+{
+    //-----------------------------------------------------------------------
+    //! Static pointer to the singleton
+    DynLibManager* DynLibManager::singletonPtr_s  = nullptr;
+
+    //-----------------------------------------------------------------------
+    DynLibManager::DynLibManager()
+    {
+    }
+    //-----------------------------------------------------------------------
+    DynLib* DynLibManager::load( const std::string& filename)
+    {
+        DynLibList::iterator i = mLibList.find(filename);
+        if (i != mLibList.end())
+        {
+            return i->second;
+        }
+        else
+        {
+            DynLib* pLib = new DynLib(filename);
+            pLib->load();
+            mLibList[filename] = pLib;
+            return pLib;
+        }
+    }
+    //-----------------------------------------------------------------------
+    void DynLibManager::unload(DynLib* lib)
+    {
+        DynLibList::iterator i = mLibList.find(lib->getName());
+        if (i != mLibList.end())
+        {
+            mLibList.erase(i);
+        }
+        lib->unload();
+        delete lib;
+    }
+    //-----------------------------------------------------------------------
+    DynLibManager::~DynLibManager()
+    {
+        // Unload & delete resources in turn
+        for (const auto& mapEntry : mLibList)
+        {
+            mapEntry.second->unload();
+            delete mapEntry.second;
+        }
+
+        // Empty the list
+        mLibList.clear();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/DynLibManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/DynLibManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/DynLibManager.h	(revision 11817)
@@ -0,0 +1,104 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place - Suite 330, Boston, MA 02111-1307, USA, or go to
+http://www.gnu.org/copyleft/lesser.txt.
+
+You may alternatively use this source under the terms of a specific version of
+the OGRE Unrestricted License provided you have obtained such a license from
+Torus Knot Software Ltd.
+-----------------------------------------------------------------------------
+*/
+
+// 08/11/2009: Small adjustments for Orxonox by Fabian 'x3n' Landau
+
+/**
+    @file
+    @ingroup Management CoreGame
+    @brief Declaration of DynLibManager, used to load modules at runtime.
+*/
+
+#ifndef _Core_DynLibManager_H__
+#define _Core_DynLibManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <map>
+#include <string>
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    /** Manager for Dynamic-loading Libraries.
+        @remarks
+            This manager keeps a track of all the open dynamic-loading
+            libraries, opens them and returns references to already-open
+            libraries.
+    */
+    class _CoreExport DynLibManager: public Singleton<DynLibManager>
+    {
+        friend class Singleton<DynLibManager>;
+
+        protected:
+            typedef std::map<std::string, DynLib*> DynLibList;
+            DynLibList mLibList;
+
+        public:
+            /**
+            @brief
+                Default constructor.
+            @note
+                Should never be called as the singleton is automatically
+                created during the creation of the Root object.
+            @see
+                Root::Root
+            */
+            DynLibManager();
+
+            /**
+            @brief
+                Default destructor.
+            @see
+                Root::~Root
+            */
+            virtual ~DynLibManager();
+
+            /**
+            @brief
+                Loads the passed library.
+            @param filename
+                The name of the library. The extension can be omitted
+            */
+            DynLib* load(const std::string& filename);
+
+            /**
+            @brief
+                Unloads the passed library.
+            @param lib
+                A pointer to the library object
+            */
+            void unload(DynLib* lib);
+
+        private:
+            static DynLibManager* singletonPtr_s;
+    };
+}
+
+#endif /* _Core_DynLibManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/ModuleInstance.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/ModuleInstance.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/ModuleInstance.cc	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ModuleInstance.h"
+
+#include "StaticallyInitializedInstance.h"
+
+namespace orxonox
+{
+    ModuleInstance* ModuleInstance::currentModuleInstance_s = nullptr;
+
+    ModuleInstance::ModuleInstance(const std::string& libraryName)
+        : libraryName_(libraryName)
+        , dynLib_(nullptr)
+    {
+    }
+
+    ModuleInstance::~ModuleInstance()
+    {
+        this->deleteAllStaticallyInitializedInstances();
+    }
+
+    void ModuleInstance::addStaticallyInitializedInstance(StaticallyInitializedInstance* instance)
+    {
+        this->staticallyInitializedInstancesByType_[instance->getType()].insert(instance);
+    }
+
+    void ModuleInstance::removeStaticallyInitializedInstance(StaticallyInitializedInstance* instance)
+    {
+        this->staticallyInitializedInstancesByType_[instance->getType()].erase(instance);
+    }
+
+    void ModuleInstance::loadAllStaticallyInitializedInstances(StaticInitialization::Type type)
+    {
+        const std::set<StaticallyInitializedInstance*>& instances = this->staticallyInitializedInstancesByType_[type];
+        for (StaticallyInitializedInstance* instance : instances)
+            instance->load();
+    }
+
+    void ModuleInstance::unloadAllStaticallyInitializedInstances(StaticInitialization::Type type)
+    {
+        // unload in reversed order
+        const std::set<StaticallyInitializedInstance*>& instances = this->staticallyInitializedInstancesByType_[type];
+        for (std::set<StaticallyInitializedInstance*>::reverse_iterator it = instances.rbegin(); it != instances.rend(); ++it)
+            (*it)->unload();
+    }
+
+    void ModuleInstance::deleteAllStaticallyInitializedInstances()
+    {
+        std::map<StaticInitialization::Type, std::set<StaticallyInitializedInstance*>> copy(this->staticallyInitializedInstancesByType_);
+        this->staticallyInitializedInstancesByType_.clear();
+        for (const auto& mapEntry : copy)
+            for (StaticallyInitializedInstance* instance : mapEntry.second)
+                delete instance;
+    }
+
+
+    /*static*/ void ModuleInstance::setCurrentModuleInstance(ModuleInstance* instance)
+    {
+        ModuleInstance::currentModuleInstance_s = instance;
+    }
+
+    /*static*/ ModuleInstance* ModuleInstance::getCurrentModuleInstance()
+    {
+        if (!ModuleInstance::currentModuleInstance_s)
+            ModuleInstance::currentModuleInstance_s = new ModuleInstance("");
+        return ModuleInstance::currentModuleInstance_s;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/ModuleInstance.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/ModuleInstance.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/ModuleInstance.h	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ModuleInstance_H__
+#define _ModuleInstance_H__
+
+#include "core/CorePrereqs.h"
+
+#include <set>
+#include <map>
+#include <string>
+
+#include "StaticallyInitializedInstance.h"
+
+namespace orxonox
+{
+    class _CoreExport ModuleInstance
+    {
+        public:
+            ModuleInstance(const std::string& libraryName);
+            ~ModuleInstance();
+
+            void addStaticallyInitializedInstance(StaticallyInitializedInstance* instance);
+            void removeStaticallyInitializedInstance(StaticallyInitializedInstance* instance);
+
+            void loadAllStaticallyInitializedInstances(StaticInitialization::Type type);
+            void unloadAllStaticallyInitializedInstances(StaticInitialization::Type type);
+
+            inline const std::set<StaticallyInitializedInstance*>& getInstances(StaticInitialization::Type type)
+                { return this->staticallyInitializedInstancesByType_[type]; }
+
+            void deleteAllStaticallyInitializedInstances();
+
+            inline const std::string& getLibraryName() const
+                { return this->libraryName_; }
+
+            inline void setDynLib(DynLib* dynLib)
+                { this->dynLib_ = dynLib; }
+            inline DynLib* getDynLib() const
+                { return this->dynLib_; }
+
+            static void setCurrentModuleInstance(ModuleInstance* instance);
+            static ModuleInstance* getCurrentModuleInstance();
+
+        private:
+            std::map<StaticInitialization::Type, std::set<StaticallyInitializedInstance*>> staticallyInitializedInstancesByType_;
+            std::string libraryName_;
+            DynLib* dynLib_;
+
+            static ModuleInstance* currentModuleInstance_s;
+    };
+}
+
+#endif /* _ModuleInstance_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/Plugin.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/Plugin.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/Plugin.cc	(revision 11817)
@@ -0,0 +1,121 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Plugin.h"
+
+#include "ModuleInstance.h"
+#include "util/Output.h"
+#include "core/Core.h"
+#include "StaticInitializationManager.h"
+
+namespace orxonox
+{
+    Plugin::Plugin(const std::string& name, const std::string& libraryName) : name_(name), libraryName_(libraryName)
+    {
+        this->referenceCounter_ = 0;
+        this->moduleInstance_ = nullptr;
+    }
+
+    Plugin::~Plugin()
+    {
+        // force unloading of the module when the plugin is destroyed
+        if (this->moduleInstance_ != nullptr)
+            this->unloadModule();
+    }
+
+    void Plugin::reference()
+    {
+        this->referenceCounter_++;
+        if (this->referenceCounter_ == 1) // increased from 0 to 1 -> load plugin
+            this->load();
+        else
+            orxout(internal_info) << "Increased reference count for plugin " << this->name_ << " to " << this->referenceCounter_ << endl;
+    }
+
+    void Plugin::dereference(bool bMerelyDeactivate)
+    {
+        if (this->referenceCounter_ == 0)
+        {
+            orxout(internal_warning) << "Tried to dereference plugin " << this->name_ << " more often than it was referenced" << endl;
+            return;
+        }
+
+        this->referenceCounter_--;
+        if (this->referenceCounter_ == 0) // reduced from 1 to 0 -> load plugin
+            this->unload(bMerelyDeactivate);
+        else
+            orxout(internal_info) << "Reduced reference count for plugin " << this->name_ << " to " << this->referenceCounter_ << endl;
+    }
+
+    //////////////////////////////////////////
+    //                 LOAD                 //
+    //////////////////////////////////////////
+    void Plugin::load()
+    {
+        // only load module if it isn't already loaded. otherwise merely activate it.
+        if (this->moduleInstance_ == nullptr)
+            this->loadModule();
+        else
+            this->activateModule();
+    }
+    void Plugin::loadModule()
+    {
+        orxout(internal_info) << "Loading plugin " << this->name_ << "..." << endl;
+        this->moduleInstance_ = new ModuleInstance(this->libraryName_);
+        Core::getInstance().loadModule(this->moduleInstance_);
+    }
+    void Plugin::activateModule()
+    {
+        orxout(internal_info) << "Activating plugin " << this->name_ << "..." << endl;
+        StaticInitializationManager::getInstance().loadModule(this->moduleInstance_);
+    }
+
+    //////////////////////////////////////////
+    //                UNLOAD                //
+    //////////////////////////////////////////
+    void Plugin::unload(bool bMerelyDeactivate)
+    {
+        // fully unload the module unless otherwise requested.
+        if (bMerelyDeactivate)
+            this->deactivateModule();
+        else
+            this->unloadModule();
+    }
+    void Plugin::unloadModule()
+    {
+        orxout(internal_info) << "Unloading plugin " << this->name_ << "..." << endl;
+        Core::getInstance().unloadModule(this->moduleInstance_);
+        delete this->moduleInstance_;
+        this->moduleInstance_ = nullptr;
+    }
+    void Plugin::deactivateModule()
+    {
+        orxout(internal_info) << "Deactivating plugin " << this->name_ << "..." << endl;
+        StaticInitializationManager::getInstance().unloadModule(this->moduleInstance_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/Plugin.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/Plugin.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/Plugin.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Plugin_H__
+#define _Plugin_H__
+
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    class _CoreExport Plugin
+    {
+        public:
+            Plugin(const std::string& name, const std::string& libraryName);
+            ~Plugin();
+
+            void reference();
+            void dereference(bool bMerelyDeactivate);
+
+        private:
+            void load();
+            void unload(bool bMerelyDeactivate);
+
+            void loadModule();
+            void activateModule();
+
+            void unloadModule();
+            void deactivateModule();
+
+            std::string name_;
+            std::string libraryName_;
+            unsigned int referenceCounter_;
+            ModuleInstance* moduleInstance_;
+    };
+}
+
+#endif /* _Plugin_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/PluginManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/PluginManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/PluginManager.cc	(revision 11817)
@@ -0,0 +1,152 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PluginManager.h"
+
+#include "SpecialConfig.h"
+#include "Plugin.h"
+#include "PluginReference.h"
+#include "core/CoreIncludes.h"
+#include "core/ApplicationPaths.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/object/Context.h"
+
+#ifdef DO_NOT_UNLOAD_PLUGINS
+#  define MERELY_DEACTIVATE_PLUGINS true
+#else
+#  define MERELY_DEACTIVATE_PLUGINS false
+#endif
+
+namespace orxonox
+{
+    static const std::string __CC_PluginManager_load_name  = "load";
+    static const std::string __CC_PluginManager_unload_name  = "unload";
+
+    SetConsoleCommand("PluginManager", __CC_PluginManager_load_name, &PluginManager::loadPlugin);
+    SetConsoleCommand("PluginManager", __CC_PluginManager_unload_name, &PluginManager::unloadPlugin);
+
+    PluginManager* PluginManager::singletonPtr_s  = nullptr;
+
+    RegisterAbstractClass(PluginManager).inheritsFrom<Configurable>();
+
+    PluginManager::PluginManager()
+    {
+        RegisterObject(PluginManager);
+
+        ModifyConsoleCommand("PluginManager", __CC_PluginManager_load_name).setObject(this);
+        ModifyConsoleCommand("PluginManager", __CC_PluginManager_unload_name).setObject(this);
+
+        this->setConfigValues();
+    }
+
+    PluginManager::~PluginManager()
+    {
+        ModifyConsoleCommand("PluginManager", __CC_PluginManager_load_name).setObject(nullptr);
+        ModifyConsoleCommand("PluginManager", __CC_PluginManager_unload_name).setObject(nullptr);
+
+        for (const auto& mapEntry : this->references_)
+            delete mapEntry.second;
+        for (const auto& mapEntry : this->plugins_)
+            delete mapEntry.second;
+    }
+
+    void PluginManager::setConfigValues()
+    {
+        SetConfigValue(bMerelyDeactivatePlugins_, MERELY_DEACTIVATE_PLUGINS).callback(this, &PluginManager::changedConfigValue);
+    }
+
+    void PluginManager::changedConfigValue()
+    {
+        if (this->bMerelyDeactivatePlugins_)
+        {
+            orxout(internal_warning) << "Orxonox is configured to NOT completely unload plugins."
+                " This means that it's not possible to re-compile and reload a plugin at runtime." << endl;
+        }
+    }
+
+    void PluginManager::findPlugins()
+    {
+        const std::map<std::string, std::string>& pluginPaths = ApplicationPaths::getInstance().getPluginPaths();
+        for (const std::pair<std::string, std::string>& pluginPath : pluginPaths)
+        {
+            const std::string& name = pluginPath.first;
+            const std::string& libraryName = pluginPath.second;
+
+            orxout(internal_info) << "Found plugin with name '" << name << "' in module " << libraryName << endl;
+            this->plugins_[name] = new Plugin(name, libraryName);
+        }
+    }
+
+    void PluginManager::referencePlugin(const std::string& name)
+    {
+        Plugin* plugin = this->plugins_[name];
+        if (plugin != nullptr)
+            plugin->reference();
+        else
+            orxout(internal_warning) << "Cannot find plugin with name " << name << endl;
+    }
+
+    void PluginManager::dereferencePlugin(const std::string& name)
+    {
+        Plugin* plugin = this->plugins_[name];
+        if (plugin != nullptr)
+            plugin->dereference(this->bMerelyDeactivatePlugins_);
+        else
+            orxout(internal_warning) << "Cannot find plugin with name " << name << endl;
+    }
+
+    /**
+     * @brief Console command to manually load a plugin. The plugin stays loaded until @ref unloadPlugin is called.
+     */
+    void PluginManager::loadPlugin(const std::string& name)
+    {
+        if (this->references_[name] == nullptr)
+        {
+            this->references_[name] = new PluginReference(name);
+        }
+        else
+            orxout(internal_warning) << "Plugin " << name << " is already loaded" << endl;
+    }
+
+    /**
+     * @brief Console command to unload a plugin if it was previously loaded manually by calling @ref loadPlugin.
+     * Does not unload the plugin immediately if it is still used by another @ref PluginReference (e.g. by a @ref Level).
+     */
+    void PluginManager::unloadPlugin(const std::string& name)
+    {
+        PluginReference* reference = this->references_[name];
+        if (reference != nullptr)
+        {
+            this->references_[name] = nullptr;
+            delete reference;
+        }
+        else
+            orxout(internal_warning) << "Plugin " << name << " is already unloaded" << endl;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/PluginManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/PluginManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/PluginManager.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PluginManager_H__
+#define _PluginManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <map>
+#include <string>
+#include "util/Singleton.h"
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+    class _CoreExport PluginManager : public Singleton<PluginManager>, public Configurable
+    {
+        friend class Singleton<PluginManager>;
+
+        public:
+            PluginManager();
+            ~PluginManager();
+
+            void setConfigValues();
+
+            void findPlugins();
+
+            void referencePlugin(const std::string& name);
+            void dereferencePlugin(const std::string& name);
+
+            // console commands
+            void loadPlugin(const std::string& name);
+            void unloadPlugin(const std::string& name);
+
+        private:
+            void changedConfigValue();
+
+            std::map<std::string, Plugin*> plugins_;
+            std::map<std::string, PluginReference*> references_; // references that were created by console command
+            bool bMerelyDeactivatePlugins_;
+
+            static PluginManager* singletonPtr_s;
+    };
+}
+
+#endif /* _PluginManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/PluginReference.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/PluginReference.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/PluginReference.cc	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PluginReference.h"
+
+#include "PluginManager.h"
+
+namespace orxonox
+{
+    PluginReference::PluginReference(const std::string& name) : name_(name)
+    {
+        // load plugin
+        PluginManager::getInstance().referencePlugin(this->name_);
+    }
+
+    PluginReference::~PluginReference()
+    {
+        // unload plugin
+        PluginManager::getInstance().dereferencePlugin(this->name_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/PluginReference.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/PluginReference.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/PluginReference.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PluginReference_H__
+#define _PluginReference_H__
+
+#include "core/CorePrereqs.h"
+
+#include "core/object/Destroyable.h"
+
+namespace orxonox
+{
+    class _CoreExport PluginReference : public Destroyable
+    {
+        public:
+            PluginReference(const std::string& name);
+            ~PluginReference();
+
+        private:
+            std::string name_;
+    };
+}
+
+#endif /* _PluginReference_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandler.h	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _StaticInitializationHandler_H__
+#define _StaticInitializationHandler_H__
+
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    class _CoreExport StaticInitializationHandler
+    {
+        public:
+            StaticInitializationHandler() = default;
+            virtual ~StaticInitializationHandler() = default;
+
+            virtual void setupHandler() = 0;
+            virtual void shutdownHandler() = 0;
+
+            virtual void loadModule(ModuleInstance* module) = 0;
+            virtual void unloadModule(ModuleInstance* module) = 0;
+    };
+}
+
+#endif /* _StaticInitializationHandler_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandlerIncludes.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandlerIncludes.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandlerIncludes.cc	(revision 11817)
@@ -0,0 +1,44 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "StaticInitializationHandlerIncludes.h"
+
+#include "StaticInitializationManager.h"
+
+namespace orxonox
+{
+    void StaticallyInitializedStaticInitializationHandler::load()
+    {
+        StaticInitializationManager::getInstance().addHandler(this->handler_);
+    }
+
+    void StaticallyInitializedStaticInitializationHandler::unload()
+    {
+        StaticInitializationManager::getInstance().removeHandler(this->handler_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandlerIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandlerIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationHandlerIncludes.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _StaticInitializationHandlerIncludes_H__
+#define _StaticInitializationHandlerIncludes_H__
+
+#include "core/CorePrereqs.h"
+
+#include "StaticInitializationHandler.h"
+#include "StaticallyInitializedInstance.h"
+
+/**
+ * Registers a StaticInitializationHandler
+ */
+#define RegisterStaticInitializationHandler(className) \
+    static StaticInitializationHandler& className##StaticInitializationHandler \
+        = (new orxonox::SI_SIH(new className()))->getHandler()
+
+namespace orxonox
+{
+    class _CoreExport StaticallyInitializedStaticInitializationHandler : public StaticallyInitializedInstance
+    {
+        public:
+            StaticallyInitializedStaticInitializationHandler(StaticInitializationHandler* handler)
+                : StaticallyInitializedInstance(StaticInitialization::STATIC_INITIALIZATION_HANDLER)
+                , handler_(handler)
+            {}
+            ~StaticallyInitializedStaticInitializationHandler() { delete handler_; }
+
+            virtual void load() override;
+            virtual void unload() override;
+
+            inline StaticInitializationHandler& getHandler()
+                { return *this->handler_; }
+
+        private:
+            StaticInitializationHandler* handler_;
+    };
+
+    typedef StaticallyInitializedStaticInitializationHandler SI_SIH;
+}
+
+#endif /* _StaticInitializationHandlerIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationManager.cc	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "StaticInitializationManager.h"
+
+#include "StaticInitializationHandler.h"
+
+namespace orxonox
+{
+    StaticInitializationManager* StaticInitializationManager::singletonPtr_s = nullptr;
+
+    void StaticInitializationManager::addHandler(StaticInitializationHandler* handler)
+    {
+        handler->setupHandler();
+        this->handlers_.push_back(handler);
+    }
+
+    void StaticInitializationManager::removeHandler(StaticInitializationHandler* handler)
+    {
+        this->handlers_.remove(handler);
+        handler->shutdownHandler();
+    }
+
+    void StaticInitializationManager::loadModule(ModuleInstance* module)
+    {
+        // attention: loading a module may add new handlers to the list
+        for (StaticInitializationHandler* handler : this->handlers_)
+            handler->loadModule(module);
+    }
+
+    void StaticInitializationManager::unloadModule(ModuleInstance* module)
+    {
+        // unload in reversed order
+        // attention: unloading a module may remove handlers from the list
+        for (std::list<StaticInitializationHandler*>::reverse_iterator it = this->handlers_.rbegin(); it != this->handlers_.rend(); )
+            (*(it++))->unloadModule(module);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticInitializationManager.h	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _StaticInitializationManager_H__
+#define _StaticInitializationManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <list>
+
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    class _CoreExport StaticInitializationManager : public Singleton<StaticInitializationManager>
+    {
+        friend class Singleton<StaticInitializationManager>;
+
+        public:
+            StaticInitializationManager() = default;
+            virtual ~StaticInitializationManager() = default;
+
+            void addHandler(StaticInitializationHandler* handler);
+            void removeHandler(StaticInitializationHandler* handler);
+
+            void loadModule(ModuleInstance* module);
+            void unloadModule(ModuleInstance* module);
+
+        private:
+            std::list<StaticInitializationHandler*> handlers_;
+
+            static StaticInitializationManager* singletonPtr_s;
+    };
+}
+
+#endif /* _StaticInitializationManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticallyInitializedInstance.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticallyInitializedInstance.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticallyInitializedInstance.cc	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "StaticallyInitializedInstance.h"
+
+#include "ModuleInstance.h"
+
+namespace orxonox
+{
+    StaticallyInitializedInstance::StaticallyInitializedInstance(StaticInitialization::Type type)
+    {
+        this->type_ = type;
+        this->module_ = ModuleInstance::getCurrentModuleInstance();
+        this->module_->addStaticallyInitializedInstance(this);
+    }
+
+    StaticallyInitializedInstance::~StaticallyInitializedInstance()
+    {
+        this->module_->removeStaticallyInitializedInstance(this);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/module/StaticallyInitializedInstance.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/module/StaticallyInitializedInstance.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/module/StaticallyInitializedInstance.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _StaticallyInitializedInstance_H__
+#define _StaticallyInitializedInstance_H__
+
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    class _CoreExport StaticallyInitializedInstance
+    {
+        public:
+
+            StaticallyInitializedInstance(StaticInitialization::Type type);
+            virtual ~StaticallyInitializedInstance();
+
+            virtual void load() = 0;
+            virtual void unload() = 0;
+
+            inline StaticInitialization::Type getType() const
+                { return this->type_; }
+
+        private:
+            ModuleInstance* module_;
+            StaticInitialization::Type type_;
+    };
+}
+
+#endif /* _StaticallyInitializedInstance_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,7 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  Context.cc
+  Destroyable.cc
+  DestroyLaterManager.cc
+  Listable.cc
+  ObjectListBase.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/ClassFactory.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/ClassFactory.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/ClassFactory.h	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object Factory
+    @brief Definition and implementation of the ClassFactory class
+
+    The ClassFactory is able to create new objects of a specific class which creates objects.
+*/
+
+#ifndef _ClassFactory_H__
+#define _ClassFactory_H__
+
+#include "core/CorePrereqs.h"
+
+#include <string>
+
+#include "util/Output.h"
+
+namespace orxonox
+{
+    // ###########################
+    // ###       Factory       ###
+    // ###########################
+    /// Base-class of all factories.
+    class _CoreExport Factory
+    {
+        public:
+            Factory() = default;
+            virtual ~Factory() = default;
+            virtual Identifiable* fabricate(Context* context) = 0;
+    };
+
+    // ###############################
+    // ###      ClassFactory       ###
+    // ###############################
+    /// The ClassFactory is the base-class of all class-spezific factories
+    template <class T>
+    class ClassFactory : public Factory
+    {
+    };
+
+    // ###############################
+    // ###   ClassFactoryNoArgs    ###
+    // ###############################
+    /// The ClassFactoryNoArgs is able to create new objects of a specific class that require no constructor arguments.
+    template <class T>
+    class ClassFactoryNoArgs : public ClassFactory<T>
+    {
+        public:
+            /**
+                @brief Creates and returns a new object of class T.
+                @return The new object
+            */
+            inline Identifiable* fabricate(Context* context)
+            {
+                return static_cast<Identifiable*>(new T());
+            }
+    };
+
+    // ###############################
+    // ### ClassFactoryWithContext ###
+    // ###############################
+    /// The ClassFactoryWithContext is able to create new objects of a specific class that require a context as constructor argument
+    template <class T>
+    class ClassFactoryWithContext : public ClassFactory<T>
+    {
+        public:
+            /**
+                @brief Creates and returns a new object of class T.
+                @return The new object
+            */
+            inline Identifiable* fabricate(Context* context)
+            {
+                return static_cast<Identifiable*>(new T(context));
+            }
+    };
+}
+
+#endif /* _ClassFactory_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Context.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Context.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Context.cc	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of Context.
+*/
+
+#include "Context.h"
+#include "core/class/Identifier.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(Context);
+
+    Context* Context::rootContext_s = nullptr;
+
+    Context* getContextForInitializationOfOtherContexts()
+    {
+        static size_t count = 0;
+        // the first time this is called, ++count returns 1 and the context is created
+        // the second time this is called, ++count returns 2 and nullptr is returned because we're in the constructor of the context itself
+        // for each future call the context (now completely created) is returned
+        if (++count == 2)
+            return nullptr;
+        else
+        {
+            static Context context(nullptr);
+            return &context;
+        }
+    }
+
+    // Initialize Listable(*) with a special context, only used to initialize other contexts. Later in the constructor we change the context
+    Context::Context(Context* context) : Listable(getContextForInitializationOfOtherContexts()), parentContext_(context)
+    {
+        RegisterObject(Context);
+
+        // the context is its own context
+        this->setContext(this);
+    }
+
+    Context::~Context()
+    {
+        // unregister context from object lists before object lists are destroyed
+        this->unregisterObject();
+        for (ObjectListBase* objectList : this->objectLists_)
+            delete objectList;
+    }
+
+    /*static*/ void Context::setRootContext(Context* context)
+    {
+        Context::rootContext_s = context;
+    }
+
+    /*static*/ void Context::destroyRootContext()
+    {
+        delete Context::rootContext_s;
+        Context::rootContext_s = nullptr;
+    }
+
+    /*static*/ Context* Context::getRootContext()
+    {
+        OrxVerify(Context::rootContext_s != nullptr, "Root Context is undefined");
+        return Context::rootContext_s;
+    }
+
+    ObjectListBase* Context::getObjectList(const Identifier* identifier)
+    {
+        unsigned int classID = identifier->getClassID();
+        if (classID >= this->objectLists_.size())
+            this->objectLists_.resize(classID + 1);
+        if (!this->objectLists_[classID])
+            this->objectLists_[classID] = new ObjectListBase();
+        return this->objectLists_[classID];
+    }
+
+    void Context::destroyObjectList(const Identifier* identifier)
+    {
+        ObjectListBase* objectList = this->getObjectList(identifier);
+        delete objectList;
+        this->objectLists_[identifier->getClassID()] = nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Context.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Context.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Context.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object
+*/
+
+#ifndef _Context_H__
+#define _Context_H__
+
+#include "core/CorePrereqs.h"
+
+#include <vector>
+
+#include "Listable.h"
+
+namespace orxonox
+{
+    class _CoreExport Context : virtual public Listable
+    {
+        public:
+            static void setRootContext(Context* context);
+            static void destroyRootContext();
+            static Context* getRootContext();
+
+            Context(Context* context);
+            virtual ~Context();
+
+            inline Context* getParentContext() const
+                { return this->parentContext_; }
+
+            ObjectListBase* getObjectList(const Identifier* identifier);
+
+            template <class T>
+            inline ObjectListBase* getObjectList()
+                { return this->getObjectList(ClassIdentifier<T>::getIdentifier()); }
+
+            template <class T>
+            inline void addObject(T* object)
+            {
+                ObjectListBaseElement* element = Listable::createObjectListElement(object);
+                this->getObjectList<T>()->addElement(element);
+                object->elements_.push_back(element);
+                if (this->getParentContext())
+                    this->getParentContext()->addObject(object);
+            }
+
+            void destroyObjectList(const Identifier* identifier);
+
+        private:
+            Context* parentContext_;
+            std::vector<ObjectListBase*> objectLists_;
+
+            static Context* rootContext_s;
+    };
+}
+
+#endif /* _Context_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/DestroyLaterManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/DestroyLaterManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/DestroyLaterManager.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DestroyLaterManager.h"
+
+#include "core/CoreIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(DestroyLaterManager, ScopeID::ROOT, false);
+
+    RegisterAbstractClass(DestroyLaterManager).inheritsFrom<UpdateListener>();
+
+    DestroyLaterManager::DestroyLaterManager()
+    {
+        RegisterObject(DestroyLaterManager);
+    }
+
+    DestroyLaterManager::~DestroyLaterManager()
+    {
+        // Be sure to release all instances
+        this->retainedInstances_.clear();
+    }
+
+    void DestroyLaterManager::postUpdate(const Clock& time)
+    {
+        // clearing the list will destroy all strong pointers and thus all retained instances (as long as there are no other strong pointers pointing to them).
+        this->retainedInstances_.clear();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/DestroyLaterManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/DestroyLaterManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/DestroyLaterManager.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DestroyLaterManager_H__
+#define _DestroyLaterManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include "util/Singleton.h"
+#include "core/UpdateListener.h"
+#include "StrongPtr.h"
+
+namespace orxonox
+{
+    class _CoreExport DestroyLaterManager : public Singleton<DestroyLaterManager>, public UpdateListener
+    {
+            friend class Singleton<DestroyLaterManager>;
+        public:
+            DestroyLaterManager();
+            virtual ~DestroyLaterManager();
+
+            virtual void preUpdate(const Clock& time) override { /*no action*/ }
+            virtual void postUpdate(const Clock& time) override;
+
+            void retain(Destroyable* instance)
+                { this->retainedInstances_.push_back(instance); }
+
+        private:
+            std::vector<StrongPtr<Destroyable>> retainedInstances_;
+
+            static DestroyLaterManager* singletonPtr_s;
+    };
+}
+
+#endif /* _DestroyLaterManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Destroyable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Destroyable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Destroyable.cc	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of Destroyable.
+*/
+
+#include "Destroyable.h"
+#include "DestroyLaterManager.h"
+#include "core/class/IdentifierManager.h"
+
+#include <cassert>
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: Sets the default values.
+    */
+    Destroyable::Destroyable()
+    {
+        this->referenceCount_ = 0;
+        this->requestedDestruction_ = false;
+    }
+
+    /**
+        @brief Destructor: Notifies all DestructionListener (for example @ref WeakPtr "weak pointers") that this object is being deleted.
+    */
+    Destroyable::~Destroyable()
+    {
+        if (!this->requestedDestruction_ && IdentifierManager::exists() && !IdentifierManager::getInstance().isCreatingHierarchy())
+            orxout(internal_warning) << "Deleted destroyable object without destroy()" << endl;
+
+        assert(this->referenceCount_ <= 0);
+
+        // notify all destruction listeners
+        for (std::set<DestructionListener*>::iterator it = this->destructionListeners_.begin(); it != this->destructionListeners_.end(); )
+            (*(it++))->objectDeleted();
+    }
+
+    /**
+        @brief Deletes the object if no @ref orxonox::StrongPtr "strong pointers" point to this object. Otherwise schedules the object to be deleted as soon as possible.
+        Always call destroy() instead of using 'delete' directly, otherwise strong pointers won't work.
+    */
+    void Destroyable::destroy()
+    {
+        assert(this); // Just in case someone tries to delete a nullptr
+        this->requestedDestruction_ = true;
+        if (this->referenceCount_ == 0)
+        {
+            this->preDestroy();
+            if (this->referenceCount_ == 0)
+                delete this;
+        }
+    }
+
+    /**
+     * Works like @ref destroy() but doesn't destroy the object until the current tick has ended.
+     */
+    void Destroyable::destroyLater()
+    {
+        // register in DestroyLaterManager - this ensures that a strongPtr points to this object and keeps it alive for a while
+        DestroyLaterManager::getInstance().retain(this);
+
+        // request destruction -> object will be deleted after all strongPtrs (including the one in DestroyLaterManager) were destroyed.
+        this->destroy();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Destroyable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Destroyable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Destroyable.h	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object
+    @brief Declaration of Destroyable, the base class of all objects which can be used with StrongPtr and WeakPtr.
+*/
+
+#ifndef _Destroyable_H__
+#define _Destroyable_H__
+
+#include "core/CorePrereqs.h"
+
+#include <set>
+
+namespace orxonox
+{
+    /**
+        @brief Classes must inherit from this class if they should be used with StrongPtr or WeakPtr.
+    */
+    class _CoreExport Destroyable
+    {
+        template <class T>
+        friend class StrongPtr;
+
+        friend class DestructionListener;
+
+        public:
+            Destroyable();
+            virtual ~Destroyable();
+
+            void destroy();
+            void destroyLater();
+
+            /// Returns the number of @ref orxonox::StrongPtr "strong pointers" that point to this object.
+            inline unsigned int getReferenceCount() const
+                { return this->referenceCount_; }
+
+        protected:
+            /// This virtual function is called if destroy() is called and no StrongPtr points to this object. Used in some cases to create a new StrongPtr to
+            /// prevent destruction. Don't call this function directly - use destroy() instead.
+            virtual void preDestroy() {}
+
+        private:
+            /// Increments the reference counter (for strong pointers).
+            inline void incrementReferenceCount()
+                { ++this->referenceCount_; }
+            /// Decrements the reference counter (for strong pointers).
+            inline void decrementReferenceCount()
+            {
+                --this->referenceCount_;
+                if (this->referenceCount_ == 0 && this->requestedDestruction_)
+                    this->destroy();
+            }
+
+            /// Register a destruction listener (for example a weak pointer which points to this object).
+            inline void registerDestructionListener(DestructionListener* pointer)
+                { this->destructionListeners_.insert(pointer); }
+            /// Unegister a destruction listener (for example a weak pointer which pointed to this object before).
+            inline void unregisterDestructionListener(DestructionListener* pointer)
+                { this->destructionListeners_.erase(pointer); }
+
+            int referenceCount_;                                    //!< Counts the references from strong pointers to this object
+            bool requestedDestruction_;                             //!< Becomes true after someone called delete on this object
+            std::set<DestructionListener*> destructionListeners_;   //!< All destruction listeners (for example weak pointers which point to this object and like to get notified if it dies)
+    };
+
+    /**
+        @brief This listener is used to inform weak pointers if an object of type Destroyable gets destroyed.
+    */
+    class _CoreExport DestructionListener
+    {
+        friend class Destroyable;
+
+        protected:
+            virtual ~DestructionListener() {}
+
+            inline void registerAsDestructionListener(Destroyable* object)
+                { if (object) { object->registerDestructionListener(this); } }
+            inline void unregisterAsDestructionListener(Destroyable* object)
+                { if (object) { object->unregisterDestructionListener(this); } }
+
+            virtual void objectDeleted() = 0;
+    };
+
+}
+
+#endif /* _Destroyable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Iterator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Iterator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Iterator.h	(revision 11817)
@@ -0,0 +1,117 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object ObjectList
+    @brief Definition of the Iterator class, used to iterate through object-lists.
+
+    @anchor IteratorExample
+
+    @ref orxonox::Iterator "Iterator" allows to iterate through an @ref orxonox::ObjectListBase
+    "ObjectListBase". Objects in this list are cast to the template argument @a T of Iterator<T> using
+    @c dynamic_cast. In contrast to @ref orxonox::ObjectListIterator "ObjectListIterator<T>",
+    @ref orxonox::Iterator "Iterator<T>" can iterate through every object-list. In practice though it
+    is limited to objects of type @a T and its subclasses. Because of the @c dynamic_cast, this iterator
+    is much slower than ObjectListIterator.
+
+    Usage:
+    @code
+    for (Iterator<myClass> it = anyidentifier->getObjects()->begin(); it != anyidentifier->getObjects()->end(); ++it)
+    {
+        it->someFunction(...);
+        myClass* myObject = *it;
+    }
+    @endcode
+*/
+
+#ifndef _Iterator_H__
+#define _Iterator_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ObjectListBase.h"
+#include "IteratorBase.h"
+
+namespace orxonox
+{
+    /**
+        @brief The Iterator allows to iterate through a given ObjectList.
+
+        Independent of the object-list's type, the objects in the list are always casted
+        to @a T using @c dynamic_cast.
+
+        @see See @ref IteratorExample "Iterator.h" for more information an example.
+    */
+    template <class T>
+    class Iterator : public IteratorBase<T, Iterator<T>>
+    {
+        public:
+            /**
+                @brief Constructor: Sets the element, whereon the iterator points, to zero.
+            */
+            inline Iterator() : IteratorBase<T, Iterator<T>>() {}
+
+            /**
+                @brief Constructor: Sets this element to the element of another Iterator.
+                @param other The other Iterator
+            */
+            template <class OT, class OI>
+            inline Iterator(const IteratorBase<OT, OI>& other) : IteratorBase<T, Iterator<T>>(other) {}
+
+            /**
+                @brief Assigns a given element.
+                @param element The element
+            */
+            inline Iterator<T>& operator=(ObjectListBaseElement* element)
+            {
+                this->setElement(element);
+                return (*this);
+            }
+
+            /**
+                @brief Overloading of the *it operator: returns the pointer to the object.
+                @return The object the Iterator points at
+            */
+            inline T* operator*() const
+            {
+                return orxonox_cast<T*>(this->element_->objectBase_);
+            }
+
+            /**
+                @brief Overloading of the it-> operator: returns the pointer to the object.
+                @return The object the Iterator points at
+            */
+            inline T* operator->() const
+            {
+                return orxonox_cast<T*>(this->element_->objectBase_);
+            }
+    };
+}
+
+#endif /* _Iterator_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/IteratorBase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/IteratorBase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/IteratorBase.h	(revision 11817)
@@ -0,0 +1,224 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object ObjectList
+    @brief Definition of the IteratorBase class, used to iterate through object-lists.
+*/
+
+#ifndef _IteratorBase_H__
+#define _IteratorBase_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ObjectListBase.h"
+
+namespace orxonox
+{
+    /**
+        @brief The Iterator allows to iterate through object lists.
+        It serves as base class for @ref ObjectListIterator and @ref Iterator
+    */
+    template <class T, class I>
+    class IteratorBase : public ObjectListElementRemovalListener
+    {
+        static_assert(std::is_base_of<Listable, T>::value, "IteratorBase can only be used with Listables");
+
+        public:
+            /**
+                @brief Constructor: Sets the element, whereon the iterator points, to the given element.
+            */
+            inline IteratorBase(ObjectListElement<T>* element = nullptr)
+            {
+                this->element_ = element;
+                this->registerIterator();
+            }
+
+            /**
+                @brief Constructor: Sets the element, whereon the iterator points, to the given element of another type.
+                The element's type O must be a derivative of the Iterator's type T.
+            */
+            template <class OT, class OI>
+            inline IteratorBase(const IteratorBase<OT, OI>& other)
+            {
+                this->element_ = other.getElement();
+                this->registerIterator();
+            }
+
+            /**
+                @brief Unregisters the Iterator from the ObjectList.
+            */
+            inline ~IteratorBase()
+            {
+                this->unregisterIterator();
+            }
+
+            /**
+                @brief Assigns a given element.
+                @param element The element
+            */
+            inline IteratorBase<T, I>& operator=(ObjectListElement<T>* element)
+            {
+                this->setElement(element);
+                return (*this);
+            }
+
+            /**
+                @brief Assigns the element of another Iterator.
+                @param other The other Iterator
+            */
+            inline IteratorBase<T, I>& operator=(const IteratorBase<T, I>& other)
+            {
+                this->setElement(other.element_);
+                return (*this);
+            }
+
+            /**
+                @brief Overloading of the ++it operator: Iterator points to the next object in the list.
+                @return The Iterator itself
+            */
+            inline const IteratorBase<T, I>& operator++()
+            {
+                this->element_ = this->element_->next_;
+                return *this;
+            }
+
+            /**
+                @brief Overloading of the it++ operator: Iterator points to the next object in the list.
+                @return The Iterator itself
+            */
+            inline I operator++(int)
+            {
+                I copy = *this;
+                this->element_ = this->element_->next_;
+                return copy;
+            }
+
+            /**
+                @brief Overloading of the --it operator: Iterator points to the previous object in the list.
+                @return The Iterator itself
+            */
+            inline const IteratorBase<T, I>& operator--()
+            {
+                this->element_ = this->element_->prev_;
+                return *this;
+            }
+
+            /**
+                @brief Overloading of the it-- operator: Iterator points to the previous object in the list.
+                @return The Iterator itself
+            */
+            inline I operator--(int i)
+            {
+                I copy = *this;
+                this->element_ = this->element_->prev_;
+                return copy;
+            }
+
+            /**
+                @brief Overloading of the typecast-operator to bool: returns true if the iterator points to an existing object.
+                @return True if the Iterator points to an existing object.
+            */
+            inline explicit operator bool() const
+            {
+                return (this->element_ != nullptr);
+            }
+
+            /**
+                @brief Overloading of the == operator to compare with another Iterator.
+                @param compare The other Iterator
+                @return True if the iterators point to the same element
+            */
+            inline bool operator==(const IteratorBase<T, I>& compare) const
+            {
+                return (this->element_ == compare.element_);
+            }
+
+            /**
+                @brief Overloading of the != operator to compare with another Iterator.
+                @param compare The other Iterator
+                @return True if the iterators point to different elements
+            */
+            inline bool operator!=(const IteratorBase<T, I>& compare) const
+            {
+                return (this->element_ != compare.element_);
+            }
+
+            /**
+                @brief Increments the Iterator if it points at the given element.
+                @param element The element to compare with
+            */
+            virtual void removedElement(ObjectListBaseElement* element) override
+            {
+                if (this->element_ == element)
+                    this->operator++();
+            }
+
+            inline ObjectListBaseElement* getElement() const
+            {
+                return this->element_;
+            }
+
+        protected:
+            inline void setElement(ObjectListBaseElement* element)
+            {
+                this->unregisterIterator();
+                this->element_ = element;
+                this->registerIterator();
+            }
+
+            /**
+             * @brief Registers the Iterator at the list to which it belongs
+             */
+            inline void registerIterator()
+            {
+                if (this->element_)
+                {
+                    this->list_ = this->element_->list_;
+                    this->list_->registerRemovalListener(this);
+                }
+                else
+                    this->list_ = nullptr;
+            }
+
+            /**
+             * @brief Unregisters the Iterator from the list (if any)
+             */
+            inline void unregisterIterator()
+            {
+                if (this->list_)
+                    this->list_->unregisterRemovalListener(this);
+            }
+
+            ObjectListBaseElement* element_;    //!< The element the Iterator points at
+            ObjectListBase* list_;              //!< The list in which the Iterator registered itself
+    };
+}
+
+#endif /* _IteratorBase_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Listable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Listable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Listable.cc	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of Listable.
+*/
+
+#include "Listable.h"
+#include "core/CoreIncludes.h"
+#include "ObjectListBase.h"
+#include "Context.h"
+
+namespace orxonox
+{
+    RegisterClass(Listable).virtualBase();
+
+    /**
+        @brief Constructor: Allocates space in the element list.
+    */
+    Listable::Listable() : Listable(Context::getRootContext())
+    {
+    }
+
+    /**
+        @brief Constructor: Allocates space in the element list and assigns the context
+    */
+    Listable::Listable(Context* context)
+    {
+        this->context_ = context;
+        this->elements_.reserve(6);
+
+        RegisterObject(Listable);
+    }
+
+    /**
+        @brief Destructor: Removes the object from the object-lists
+    */
+    Listable::~Listable()
+    {
+        this->unregisterObject();
+    }
+
+    /**
+        @brief Removes this object from the object-lists.
+    */
+    void Listable::unregisterObject()
+    {
+        for (ObjectListBaseElement* element : this->elements_)
+            Listable::deleteObjectListElement(element);
+        this->elements_.clear();
+    }
+
+    /**
+     * @brief Changes the context.
+     * The object is removed from the current context and added to the new one. This also applies to all object lists the object is registered in.
+     */
+    void Listable::setContext(Context* context)
+    {
+        assert(context);
+        std::vector<ObjectListBaseElement*> copy = this->elements_;
+        this->elements_.clear();
+
+        for (ObjectListBaseElement* element : copy)
+        {
+            element->changeContext(this->context_, context);
+            Listable::deleteObjectListElement(element);
+        }
+
+        this->context_ = context;
+    }
+
+    /* static */ SmallObjectAllocator& Listable::getObjectListElementAllocator()
+    {
+        static SmallObjectAllocator allocator(sizeof(ObjectListElement<Listable>), 1024);
+        return allocator;
+    }
+
+    /* static */ void Listable::deleteObjectListElement(ObjectListBaseElement* element)
+    {
+        element->~ObjectListBaseElement();
+        Listable::getObjectListElementAllocator().free(element);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/Listable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/Listable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/Listable.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object ObjectList
+    @brief Declaration of Listable, the base of all classes whose instances can be stored in object lists.
+*/
+
+#ifndef _Listable_H__
+#define _Listable_H__
+
+#include "core/CorePrereqs.h"
+
+#include <vector>
+
+#include "util/SmallObjectAllocator.h"
+#include "core/class/Identifiable.h"
+
+namespace orxonox
+{
+    /**
+        @brief Listable stores the entries of all object lists pointing to this instance.
+    */
+    class _CoreExport Listable : virtual public Identifiable
+    {
+        friend class Context;
+
+        public:
+            Listable();
+            Listable(Context* context);
+            virtual ~Listable();
+
+            void unregisterObject();
+
+            void setContext(Context* context);
+            inline Context* getContext() const
+                { return this->context_; }
+
+        private:
+            static SmallObjectAllocator& getObjectListElementAllocator();
+
+            template <class T>
+            static ObjectListElement<T>* createObjectListElement(T* object)
+            {
+                void* chunk = Listable::getObjectListElementAllocator().alloc();
+                return new (chunk) ObjectListElement<T>(object);
+            }
+
+            static void deleteObjectListElement(ObjectListBaseElement* element);
+
+            Context* context_;                             //!< The object will register itself in the object lists of this context
+            std::vector<ObjectListBaseElement*> elements_; //!< The corresponding ObjectListElements in all object lists the object is registered in
+    };
+}
+
+#endif /* _Listable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectList.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectList.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectList.h	(revision 11817)
@@ -0,0 +1,100 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup ObjectList Object-lists and iterators
+    @ingroup Object
+*/
+
+/**
+    @file
+    @ingroup Object ObjectList
+    @brief Definition of the ObjectList class, a wrapper of ObjectListBase.
+
+    @ref orxonox::ObjectList "ObjectList<T>" is a wrapper of an @ref orxonox::ObjectListBase
+    "ObjectListBase" of class @a T. Use @ref orxonox::ObjectListIterator "ObjectListIterator<T>"
+    to iterate through the list.
+*/
+
+#ifndef _ObjectList_H__
+#define _ObjectList_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ObjectListBase.h"
+#include "ObjectListIterator.h"
+#include "Context.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###       ObjectList        ###
+    // ###############################
+    /**
+        @brief The ObjectList contains all objects of the given class.
+
+        Wraps the ObjectListBase which contains all objects of type @a T. Use @ref ObjectListIterator
+        "ObjectListIterator<T>" or its typedef ObjectList<T>::iterator to iterate through all objects
+        in the list.
+    */
+    template <class T>
+    class ObjectList
+    {
+        static_assert(std::is_base_of<Listable, T>::value, "ObjectList can only be used with Listables");
+
+        public:
+            typedef ObjectListIterator<T> iterator;
+
+            ObjectList() : ObjectList(Context::getRootContext()) {}
+            ObjectList(Context* context) : ObjectList(context->getObjectList<T>()) {}
+            ObjectList(ObjectListBase* list) : list_(list) {}
+
+            /// Returns the size of the list
+            inline size_t size()
+            {   return this->list_->size();   }
+
+            /// Returns an Iterator to the first element in the list.
+            inline ObjectListIterator<T> begin()
+            {   return static_cast<ObjectListElement<T>*>(this->list_->begin());   }
+            /// Returns an Iterator to the element after the last element in the list.
+            inline ObjectListIterator<T> end()
+            {   return static_cast<ObjectListElement<T>*>(this->list_->end());   }
+
+            /// Returns an Iterator to the last element in the list.
+            inline ObjectListIterator<T> rbegin()
+            {   return static_cast<ObjectListElement<T>*>(this->list_->rbegin());   }
+            /// Returns an Iterator to the element before the first element in the list.
+            inline ObjectListIterator<T> rend()
+            {   return static_cast<ObjectListElement<T>*>(this->list_->rend());   }
+
+        private:
+            ObjectListBase* list_;
+    };
+}
+
+#endif /* _ObjectList_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListBase.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListBase.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListBase.cc	(revision 11817)
@@ -0,0 +1,162 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the ObjectListBase class.
+*/
+
+#include "ObjectListBase.h"
+
+#include <set>
+#include "Iterator.h"
+#include "Listable.h"
+#include "ObjectListIterator.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###  ObjectListBaseElement  ###
+    // ###############################
+    void ObjectListBaseElement::removeFromList()
+    {
+        if (this->list_)
+            this->list_->removeElement(this);
+    }
+
+    // ###############################
+    // ###     ObjectListBase      ###
+    // ###############################
+    /**
+        @brief Constructor: Sets default values.
+    */
+    ObjectListBase::ObjectListBase()
+    {
+        this->first_ = nullptr;
+        this->last_ = nullptr;
+        this->size_ = 0;
+    }
+
+    /**
+        @brief Destructor: Detaches all list-elements, but doesn't delete them (nor the objects).
+    */
+    ObjectListBase::~ObjectListBase()
+    {
+        ObjectListBaseElement* current = this->first_;
+        while (current)
+        {
+            ObjectListBaseElement* next = current->next_;
+
+            current->list_ = nullptr;
+            current->next_ = nullptr;
+            current->prev_ = nullptr;
+
+            current = next;
+        }
+
+        if (!this->listeners_.empty())
+            orxout(internal_error) << "Deleting ObjectListBase but it still has " << this->listeners_.size() << " listeners. This will lead to a crash. "
+                                   << "Ensure that all Iterators are destroyed before deleting object lists." << endl;
+    }
+
+    /**
+        @brief Notifies all listeners that the given element is about to get removed.
+        @param element The element that gets removed
+        This is mainly used for iterators which point at the removed element
+    */
+    void ObjectListBase::notifyRemovalListeners(ObjectListBaseElement* element) const
+    {
+        for (ObjectListElementRemovalListener* listener : this->listeners_)
+            listener->removedElement(element);
+    }
+
+    /**
+        @brief Adds a new object to the end of the list.
+        @param element The element to add
+    */
+    void ObjectListBase::addElement(ObjectListBaseElement* element)
+    {
+        if (element->list_)
+        {
+            orxout(internal_error) << "Element is already registered in another list" << endl;
+            return;
+        }
+
+        if (element->objectBase_)
+            orxout(verbose, context::object_list) << "Added object to " << element->objectBase_->getIdentifier()->getName() << "-list." << endl;
+
+        if (!this->last_)
+        {
+            // If the list is empty
+            this->last_ = element;
+            this->first_ = element; // There's only one object in the list now
+        }
+        else
+        {
+            // If the list isn't empty
+            ObjectListBaseElement* temp = this->last_;
+            this->last_ = element;
+            element->prev_ = temp;
+            temp->next_ = element;
+        }
+
+        element->list_ = this;
+        ++this->size_;
+    }
+
+    /**
+     * @brief Removes the element from the list
+     */
+    void ObjectListBase::removeElement(ObjectListBaseElement* element)
+    {
+        if (element->list_ != this)
+        {
+            orxout(internal_error) << "Element is not registered in this list" << endl;
+            return;
+        }
+
+        if (element->objectBase_)
+            orxout(verbose, context::object_list) << "Removing Object from " << element->objectBase_->getIdentifier()->getName() << "-list." << endl;
+        this->notifyRemovalListeners(element);
+
+        if (element->next_)
+            element->next_->prev_ = element->prev_;
+        else
+            this->last_ = element->prev_; // If there is no next_, we deleted the last object and have to update the last_ pointer of the list
+
+        if (element->prev_)
+            element->prev_->next_ = element->next_;
+        else
+            this->first_ = element->next_; // If there is no prev_, we deleted the first object and have to update the first_ pointer of the list
+
+        element->list_ = nullptr;
+        element->next_ = nullptr;
+        element->prev_ = nullptr;
+        --this->size_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListBase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListBase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListBase.h	(revision 11817)
@@ -0,0 +1,168 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object ObjectList
+    @brief Declaration of the ObjectListBase class which stores all objects of each class.
+
+    orxonox::ObjectListBase is a double-linked list, used by @ref orxonox::Identifier "Identifiers"
+    to store all objects of a given class. Newly created objects are added to the list through the
+    @c RegisterObject() macro in the constructor.
+*/
+
+#ifndef _ObjectListBase_H__
+#define _ObjectListBase_H__
+
+#include "core/CorePrereqs.h"
+#include <vector>
+#include "Context.h"
+
+namespace orxonox
+{
+    // ###############################
+    // ###  ObjectListBaseElement  ###
+    // ###############################
+    /// The list-element of the ObjectListBase
+    class _CoreExport ObjectListBaseElement
+    {
+        public:
+            /**
+                @brief Constructor: Creates the list-element with an object.
+                @param object The object to store
+            */
+            ObjectListBaseElement(Listable* object) : next_(nullptr), prev_(nullptr), objectBase_(object), list_(nullptr) {}
+            virtual ~ObjectListBaseElement() { this->removeFromList(); }
+
+            virtual void changeContext(Context* oldContext, Context* newContext) = 0;
+
+            ObjectListBaseElement* next_;       //!< The next element in the list
+            ObjectListBaseElement* prev_;       //!< The previous element in the list
+            Listable* objectBase_;              //!< The object
+            ObjectListBase* list_;              //!< The list
+
+        protected:
+            void removeFromList();
+    };
+
+
+    // ###############################
+    // ###    ObjectListElement    ###
+    // ###############################
+    /// The list-element that actually contains the object
+    template <class T>
+    class ObjectListElement : public ObjectListBaseElement
+    {
+        public:
+            ObjectListElement(T* object) : ObjectListBaseElement(static_cast<Listable*>(object)), object_(object) {}
+
+            virtual void changeContext(Context* oldContext, Context* newContext) override
+            {
+                // add object to new context, but only if this element belongs exactly to the old context (and not to a sub-context to avoid re-adding objects
+                // multiple times if they are in multiple contexts)
+                if (oldContext->getObjectList<T>() == this->list_)
+                    newContext->addObject(this->object_);
+
+                // remove from old list
+                this->removeFromList();
+            }
+
+            T* object_;              //!< The object
+    };
+
+
+    // ########################################
+    // ### ObjectListElementRemovalListener ###
+    // ########################################
+    /// Gets called by the object list if an element is removed
+    class _CoreExport ObjectListElementRemovalListener
+    {
+        public:
+            ObjectListElementRemovalListener() = default;
+            virtual ~ObjectListElementRemovalListener() = default;
+            virtual void removedElement(ObjectListBaseElement* element) = 0;
+    };
+
+    // ###############################
+    // ###     ObjectListBase      ###
+    // ###############################
+    /**
+        @brief The ObjectListBase contains all objects of a given class.
+
+        The ObjectListBase is used by Identifiers to store all objects of their class.
+        You can use Identifier::getObjects() to get the object-list from an Identifier.
+        Use @ref Iterator "Iterator<T>" to iterate through them.
+
+        Alternatively you can also use the static helper class @ref orxonox::ObjectList "ObjectList<T>"
+        to get the list of all objects of type @a T. Use @ref ObjectListIterator "ObjectListIterator<T>"
+        or @ref Iterator "Iterator<T>" to iterate through them.
+    */
+    class _CoreExport ObjectListBase
+    {
+        public:
+            ObjectListBase();
+            ~ObjectListBase();
+
+            void addElement(ObjectListBaseElement* element);
+            void removeElement(ObjectListBaseElement* element);
+
+            size_t size() const { return this->size_; }
+
+            /// Returns a pointer to the first element in the list. Works only with Iterator.
+            inline ObjectListBaseElement* begin() const { return this->first_; }
+            /// Returns a pointer to the element after the last element in the list. Works only with Iterator.
+            inline ObjectListBaseElement* end() const { return nullptr; }
+            /// Returns a pointer to the last element in the list. Works only with Iterator.
+            inline ObjectListBaseElement* rbegin() const { return this->last_; }
+            /// Returns a pointer to the element in front of the first element in the list. Works only with Iterator.
+            inline ObjectListBaseElement* rend() const { return nullptr; }
+
+            inline void registerRemovalListener(ObjectListElementRemovalListener* listener) { this->listeners_.push_back(listener); }
+            inline void unregisterRemovalListener(ObjectListElementRemovalListener* listener)
+            {
+                for (unsigned int i = 0; i < this->listeners_.size(); ++i)
+                {
+                    if (listeners_[i] == listener)
+                    {
+                        listeners_.erase(listeners_.begin() + i);
+                        break;
+                    }
+                }
+            }
+
+        private:
+            void notifyRemovalListeners(ObjectListBaseElement* element) const;
+
+            ObjectListBaseElement* first_;                              //!< The first element in the list
+            ObjectListBaseElement* last_;                               //!< The last element in the list
+            size_t size_;                                               //!< The number of elements in the list
+            std::vector<ObjectListElementRemovalListener*> listeners_;  //!< A list of Iterators pointing on an element in this list
+    };
+}
+
+#endif /* _ObjectListBase_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListIterator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListIterator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/ObjectListIterator.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Object ObjectList
+    @brief Definition of the ObjectListIterator class, used to iterate through object-lists.
+
+    @anchor ObjectListIteratorExample
+
+    @ref orxonox::ObjectListIterator "ObjectListIterator<T>" allows to iterate through
+    @ref orxonox::ObjectList "ObjectList<T>", containing all objects of type @a T. In contrast to
+    @ref orxonox::Iterator "Iterator<T>", this iterator is limited to the object-list of type @a T.
+    It is, however, much faster as it doesn't need a @c dynamic_cast.
+
+    Usage:
+    @code
+    ObjectList<myClass> list;
+    for (ObjectListIterator<myClass> it = list.begin(); it != list.end(); ++it)
+    {
+        it->someFunction(...);
+        myClass* myObject = *it;
+    }
+    @endcode
+
+    @note @ref orxonox::ObjectList::iterator "ObjectList<T>::iterator" is identical to
+          @ref orxonox::ObjectListIterator "ObjectListIterator<T>" (it's just a typedef).
+*/
+
+#ifndef _ObjectListIterator_H__
+#define _ObjectListIterator_H__
+
+#include "core/CorePrereqs.h"
+#include "core/class/Identifier.h"
+#include "ObjectList.h"
+#include "IteratorBase.h"
+
+namespace orxonox
+{
+    /**
+        @brief ObjectListIterator<T> allows to iterate through the ObjectList of class @a T.
+
+        @see See @ref ObjectListIteratorExample "ObjectListIterator.h" for more information an example.
+    */
+    template <class T>
+    class ObjectListIterator : public IteratorBase<T, ObjectListIterator<T>>
+    {
+        public:
+            /**
+                @brief Constructor: Sets the element, whereon the ObjectListIterator points, to zero.
+            */
+            inline ObjectListIterator() : IteratorBase<T, ObjectListIterator<T>>() {}
+
+            /**
+                @brief Constructor: Sets this element to a given element.
+                @param element The element to start with
+            */
+            inline ObjectListIterator(ObjectListElement<T>* element) : IteratorBase<T, ObjectListIterator<T>>(element) {}
+
+            /**
+                @brief Constructor: Sets this element to the element of another ObjectListIterator.
+                @param other The other ObjectListIterator
+            */
+            template <class OI>
+            inline ObjectListIterator(const IteratorBase<T, OI>& other) : IteratorBase<T, ObjectListIterator<T>>(other) {}
+
+            /**
+                @brief Overloading of the *it operator: returns the pointer to the object.
+                @return The object the ObjectListIterator points at
+            */
+            inline T* operator*() const
+            {
+                return static_cast<ObjectListElement<T>*>(this->element_)->object_;
+            }
+
+            /**
+                @brief Overloading of the it-> operator: returns the pointer to the object.
+                @return The object the ObjectListIterator points at
+            */
+            inline T* operator->() const
+            {
+                return static_cast<ObjectListElement<T>*>(this->element_)->object_;
+            }
+    };
+}
+
+#endif /* _ObjectListIterator_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/StrongPtr.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/StrongPtr.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/StrongPtr.h	(revision 11817)
@@ -0,0 +1,311 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+// Inspired by boost::intrusive_ptr by Peter Dimov
+
+/**
+    @defgroup SmartPtr StrongPtr<T> and WeakPtr<T>
+    @ingroup Object
+*/
+
+/**
+    @file
+    @ingroup Object SmartPtr
+    @brief Definition of StrongPtr<T>, wraps a pointer to an object and keeps it alive.
+
+    @anchor StrongPtrExample
+
+    orxonox::StrongPtr is an implementation of a smart pointer - it wraps a pointer to an
+    object  and keeps this object alive until no StrongPtr points to this object anymore.
+    In contrast to std::shared_ptr, StrongPtr works only with classes that are derived
+    from orxonox::Destroyable, because it's an intrusive implementation, meaning the
+    reference counter is stored in the object itself.
+
+    It's possible to use normal pointers and strong pointers to an object simultaneously.
+    You don't have to use StrongPtr all the time, you can create a StrongPtr for an object
+    at any time and also convert it back to a normal pointer if you like. This is possible
+    because the reference counter is stored in the object itself and not in StrongPtr (in
+    contrast to std::shared_ptr).
+
+    @b Important: If you want to delete an object, you must not use @c delete @c object but
+    rather @c object->destroy(). This function will check if there are strong pointers
+    pointing to the object. If yes, the object will be kept alive until all strong pointers
+    are destroyed. If no, the object is deleted instantly.
+
+    If all strong pointers that point to an object are destroyed, but you never called
+    @c object->destroy() before, the object will not be deleted! All a StrongPtr will do
+    is to really just keep an object alive, but it will not delete it automatically
+    unless you tried to destroy it before.
+
+    Example:
+    @code
+    class MyClass                                           // class declaration
+    {
+        public:
+            void setObject(OtherClass* object)              // passes a normal pointer which will be stored in a StrongPtr
+                { this->object_ = object; }
+
+            OtherClass* getObject() const                   // converts the StrongPtr to a normal pointer and returns it
+                { return this->object_; }
+
+        private:
+            StrongPtr<OtherClass> object_;                  // a pointer to an instance of OtherClass is stored in a StrongPtr
+    };
+    @endcode
+    In this example we assume that OtherClass is a child of Destroyable. We don't care
+    about the inheritance of MyClass though.
+
+    Now we create an instance of MyClass and assign a pointer to an instance of OtherClass:
+    @code
+    MyClass* myclass = new MyClass();                       // create an instance of MyClass
+    OtherClass* object = new OtherClass();                  // create an instance of OtherClass
+    myclass->setObject(object);                             // the object is now stored in a StrongPtr inside myclass
+
+    object->destroy();                                      // we try to destroy object, but there's still a StrongPtr pointing at it.
+
+    # object still exists at this point (because a StrongPtr points at it)
+
+    delete myclass;                                         // now we delete myclass, which also destroys the StrongPtr
+
+    # object doesn't exist anymore (because the StrongPtr is now destroyed)
+    @endcode
+
+    Now we look at the same example, but we first delete myclass, then destroy object:
+    @code
+    MyClass* myclass = new MyClass();                       // create an instance of MyClass
+    OtherClass* object = new OtherClass();                  // create an instance of OtherClass
+    myclass->setObject(object);                             // the object is now stored in a StrongPtr inside myclass
+
+    delete myclass;                                         // we delete myclass, which also destroys the StrongPtr
+
+    # object still exists at this point (because destroy() was not called yet)
+
+    object->destroy();                                      // now we try to destroy object, which works instantly
+
+    # object doesn't exist anymore (because we just destroyed it)
+    @endcode
+
+    Note that in any case @c object->destroy() has to be called to delete the object.
+    However if a StrongPtr points at it, the destruction is delayed until all StrongPtr
+    are destroyed.
+*/
+
+#ifndef _StrongPtr_H__
+#define _StrongPtr_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+
+#include "core/object/Destroyable.h"
+#include "WeakPtr.h"
+
+namespace orxonox
+{
+    /**
+        @brief A strong pointer which wraps a pointer to an object and keeps this object alive as long as the strong pointer exists.
+
+        @see See @ref StrongPtrExample "this description" for more information and an example.
+    */
+    template <class T>
+    class StrongPtr
+    {
+        public:
+            /// Constructor: Initializes the strong pointer with a null pointer.
+            inline StrongPtr() : pointer_(nullptr), base_(nullptr)
+            {
+            }
+
+            /// Constructor: Initializes the strong pointer with a pointer to an object. @param pointer The pointer
+            inline StrongPtr(T* pointer) : pointer_(pointer), base_(pointer)
+            {
+                if (this->base_)
+                    this->base_->incrementReferenceCount();
+            }
+
+            /// Copy-constructor
+            inline StrongPtr(const StrongPtr& other) : pointer_(other.pointer_), base_(other.base_)
+            {
+                if (this->base_)
+                    this->base_->incrementReferenceCount();
+            }
+
+            /// Copy-constructor for strong pointers to objects of another class.
+            template <class O>
+            inline StrongPtr(const StrongPtr<O>& other) : pointer_(other.get()), base_(other.getBase())
+            {
+                if (this->base_)
+                    this->base_->incrementReferenceCount();
+            }
+
+            /// Constructor: Initializes the strong pointer with the pointer that is stored in a WeakPtr.
+            template <class O>
+            inline StrongPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.getBase())
+            {
+                if (this->base_)
+                    this->base_->incrementReferenceCount();
+            }
+
+            /// Move-constructor
+            inline StrongPtr(StrongPtr&& other) : pointer_(other.pointer_), base_(other.base_)
+            {
+                other.pointer_ = nullptr;
+                other.base_ = nullptr;
+            }
+
+            /// Destructor: Decrements the reference counter.
+            inline ~StrongPtr()
+            {
+                if (this->base_)
+                    this->base_->decrementReferenceCount();
+            }
+
+            /// Assigns a new pointer.
+            inline StrongPtr& operator=(T* pointer)
+            {
+                StrongPtr(pointer).swap(*this);
+                return *this;
+            }
+
+            /// Assigns the wrapped pointer of another StrongPtr.
+            inline StrongPtr& operator=(StrongPtr other)
+            {
+                other.swap(*this);
+                return *this;
+            }
+
+            /// Assigns the wrapped pointer of a StrongPtr of another class
+            template <class O>
+            inline StrongPtr& operator=(const StrongPtr<O>& other)
+            {
+                StrongPtr(other).swap(*this);
+                return *this;
+            }
+
+            /// Assigns the wrapped pointer of a WeakPtr.
+            template <class O>
+            inline StrongPtr& operator=(const WeakPtr<O>& other)
+            {
+                StrongPtr(other).swap(*this);
+                return *this;
+            }
+
+            /// Returns the wrapped pointer as @c T*
+            inline T* get() const
+            {
+                return this->pointer_;
+            }
+
+            /// Returns the wrapped pointer as @c Destroyable*
+            inline Destroyable* getBase() const
+            {
+                return this->base_;
+            }
+
+            /// Implicitly converts the StrongPtr to a pointer of type @c T*
+            inline operator T*() const
+            {
+                return this->pointer_;
+            }
+
+            /// Overloaded operator, returns a pointer to the stored object.
+            inline T* operator->() const
+            {
+                assert(this->pointer_ != nullptr);
+                return this->pointer_;
+            }
+
+            /// Overloaded operator, returns a reference to the stored object.
+            inline T& operator*() const
+            {
+                assert(this->pointer_ != nullptr);
+                return *this->pointer_;
+            }
+
+            /// Returns true if the pointer is not nullptr.
+            inline explicit operator bool() const
+            {
+                return (this->pointer_ != nullptr);
+            }
+
+            /// Swaps the contents of two strong pointers.
+            inline void swap(StrongPtr& other)
+            {
+                {
+                    T* temp = this->pointer_;
+                    this->pointer_ = other.pointer_;
+                    other.pointer_ = temp;
+                }
+                {
+                    Destroyable* temp = this->base_;
+                    this->base_ = other.base_;
+                    other.base_ = temp;
+                }
+            }
+
+            /// Resets the strong pointer (equivalent to assigning a nullptr).
+            inline void reset()
+            {
+                StrongPtr().swap(*this);
+            }
+
+        private:
+            T* pointer_;            ///< The wrapped pointer to an object of type @a T
+            Destroyable* base_;    ///< The wrapped pointer, casted up to Destroyable (this is needed because with just a T* pointer, StrongPtr couln't be used with forward declarations)
+    };
+
+    /// Swaps the contents of two strong pointers.
+    template <class T>
+    void swap(StrongPtr<T>& a, StrongPtr<T>& b)
+    {
+        a.swap(b);
+    }
+
+    /// Uses a static_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new StrongPtr<T>.
+    template <class T, class U>
+    StrongPtr<T> static_pointer_cast(const StrongPtr<U>& p)
+    {
+        return static_cast<T*>(p.get());
+    }
+
+    /// Uses a const_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new StrongPtr<T>.
+    template <class T, class U>
+    StrongPtr<T> const_pointer_cast(const StrongPtr<U>& p)
+    {
+        return const_cast<T*>(p.get());
+    }
+
+    /// Uses a dynamic_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new StrongPtr<T>.
+    template <class T, class U>
+    StrongPtr<T> dynamic_pointer_cast(const StrongPtr<U>& p)
+    {
+        return orxonox_cast<T*>(p.get());
+    }
+}
+
+#endif /* _StrongPtr_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/object/WeakPtr.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/object/WeakPtr.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/object/WeakPtr.h	(revision 11817)
@@ -0,0 +1,274 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+// Inspired by boost::intrusive_ptr by Peter Dimov
+
+/**
+    @file
+    @ingroup Object SmartPtr
+    @brief Definition of WeakPtr<T>, wraps a pointer to an object.
+
+    @anchor WeakPtrExample
+
+    A WeakPtr wraps a pointer to an object. If the object gets deleted, the WeakPtr becomes
+    nullptr. This can be used to store pointers to objects without knowing when they will be
+    destroyed.
+
+    WeakPtr works only with objects that are derived from orxonox::Destroyable, because
+    WeakPtr is intrusive and registers itself in the stored object, to get a notification if
+    the object is being deleted.
+
+    Example:
+    @code
+    MyClass* object = new MyClass();                    // create an instance of MyClass
+
+    WeakPtr<MyClass> pointer = object;                  // create a WeakPtr and assign the object
+
+    if (pointer)                                        // checks if pointer is not nullptr (which is true)
+        pointer->someFunction();                        // calls MyClass::someFunction()
+
+    object->destroy();                                  // calls destroy() which deletes the object
+
+    if (pointer)                                        // checks if pointer is not nullptr (which is now false)
+        pointer->someFunction();                        // this will not be executed
+    @endcode
+    In this example we assumed that MyClass is derived of Destroyable (otherwise it couldn't
+    be used with a WeakPtr).
+
+    A callback can be registerd with the WeakPtr that will be called if the object gets deleted.
+    @code
+    void myCallback()                                   // definition of the callback function
+    {
+        orxout() << "Object destroyed" << endl;
+    }
+
+    MyClass* object = new MyClass();                    // create an instance of MyClass
+
+    WeakPtr<MyClass> pointer = object;                  // create a WeakPtr and assign the object
+
+    pointer.setCallback(createFunctor(&myCallback));    // defines a callback
+
+    object->destroy();                                  // calls destroy() which deletes the object. prints "Object destroyed" to the console
+    @endcode
+*/
+
+#ifndef _WeakPtr_H__
+#define _WeakPtr_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+
+#include "core/object/Destroyable.h"
+#include "core/command/Functor.h"
+
+namespace orxonox
+{
+    /**
+        @brief WeakPtr wraps a pointer to an object, which becomes nullptr if the object is deleted.
+
+        @see See @ref WeakPtrExample "this description" for more information and an example.
+    */
+    template <class T>
+    class WeakPtr : public DestructionListener
+    {
+        public:
+            /// Constructor: Initializes the weak pointer with a null pointer.
+            inline WeakPtr() : pointer_(nullptr), base_(nullptr), callback_(nullptr)
+            {
+            }
+
+            /// Constructor: Initializes the weak pointer with a pointer to an object.
+            inline WeakPtr(T* pointer) : pointer_(pointer), base_(pointer), callback_(nullptr)
+            {
+                this->registerAsDestructionListener(this->base_);
+            }
+
+            /// Copy-constructor
+            inline WeakPtr(const WeakPtr& other) : pointer_(other.pointer_), base_(other.base_), callback_(nullptr)
+            {
+                this->registerAsDestructionListener(this->base_);
+            }
+
+            /// Copy-constructor for weak pointers to objects of another class.
+            template <class O>
+            inline WeakPtr(const WeakPtr<O>& other) : pointer_(other.get()), base_(other.getBase()), callback_(nullptr)
+            {
+                this->registerAsDestructionListener(this->base_);
+            }
+
+            /// Destructor
+            virtual inline ~WeakPtr()
+            {
+                this->unregisterAsDestructionListener(this->base_);
+            }
+
+            /// Assigns a new pointer.
+            inline WeakPtr& operator=(T* pointer)
+            {
+                WeakPtr(pointer).swap(*this);
+                return *this;
+            }
+
+            /// Assigns the wrapped pointer of another WeakPtr.
+            inline WeakPtr& operator=(WeakPtr other)
+            {
+                other.swap(*this);
+                return *this;
+            }
+
+            /// Assigns the wrapped pointer of a WeakPtr of another class
+            template <class O>
+            inline WeakPtr& operator=(const WeakPtr<O>& other)
+            {
+                WeakPtr(other).swap(*this);
+                return *this;
+            }
+
+            /// Returns the wrapped pointer as @c T*
+            inline T* get() const
+            {
+                return this->pointer_;
+            }
+
+            /// Returns the wrapped pointer as @c Destroyable*
+            inline Destroyable* getBase() const
+            {
+                return this->base_;
+            }
+
+            /// Implicitly converts the WeakPtr to a pointer of type @c T*
+            inline operator T*() const
+            {
+                return this->pointer_;
+            }
+
+            /// Overloaded operator, returns a pointer to the stored object.
+            inline T* operator->() const
+            {
+                assert(this->pointer_ != nullptr);
+                return this->pointer_;
+            }
+
+            /// Overloaded operator, returns a reference to the stored object.
+            inline T& operator*() const
+            {
+                assert(this->pointer_ != nullptr);
+                return *this->pointer_;
+            }
+
+            /// Returns true if the pointer is not nullptr.
+            inline explicit operator bool() const
+            {
+                return (this->pointer_ != nullptr);
+            }
+
+            /// Swaps the contents of two weak pointers.
+            inline void swap(WeakPtr& other)
+            {
+                this->unregisterAsDestructionListener(this->base_);
+                other.unregisterAsDestructionListener(other.base_);
+
+                {
+                    T* temp = this->pointer_;
+                    this->pointer_ = other.pointer_;
+                    other.pointer_ = temp;
+                }
+                {
+                    Destroyable* temp = this->base_;
+                    this->base_ = other.base_;
+                    other.base_ = temp;
+                }
+
+                this->registerAsDestructionListener(this->base_);
+                other.registerAsDestructionListener(other.base_);
+            }
+
+            /// Resets the weak pointer (equivalent to assigning a nullptr).
+            inline void reset()
+            {
+                WeakPtr().swap(*this);
+            }
+
+            /// Registers a callback that will be executed if the stored object is destroyed.
+            inline void setCallback(const FunctorPtr& callback)
+            {
+                this->callback_ = callback;
+            }
+
+            /// Returns the registered callback.
+            inline const FunctorPtr& getCallback() const
+            {
+                return this->callback_;
+            }
+
+        private:
+            /// Will be called by Destroyable::~Destroyable() if the stored object is deleted. Resets the wrapped pointer and executes the callback.
+            virtual inline void objectDeleted() override
+            {
+                this->base_ = nullptr;
+                this->pointer_ = nullptr;
+                if (this->callback_)
+                    (*this->callback_)();
+            }
+
+            T* pointer_;            ///< The wrapped pointer to an object of type @a T
+            Destroyable* base_;    ///< The wrapped pointer, casted up to Destroyable (this is needed because with just a T* pointer, WeakPtr couln't be used with forward declarations)
+            FunctorPtr callback_;   ///< This callback will be executed if the stored object is deleted
+    };
+
+    /// Swaps the contents of two weak pointers.
+    template <class T>
+    void swap(WeakPtr<T>& a, WeakPtr<T>& b)
+    {
+        a.swap(b);
+    }
+
+    /// Uses a static_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new WeakPtr<T>.
+    template <class T, class U>
+    WeakPtr<T> static_pointer_cast(const WeakPtr<U>& p)
+    {
+        return static_cast<T*>(p.get());
+    }
+
+    /// Uses a const_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new WeakPtr<T>.
+    template <class T, class U>
+    WeakPtr<T> const_pointer_cast(const WeakPtr<U>& p)
+    {
+        return const_cast<T*>(p.get());
+    }
+
+    /// Uses a dynamic_cast to cast a pointer of type U* to a pointer of type T* and returns it in a new WeakPtr<T>.
+    template <class T, class U>
+    WeakPtr<T> dynamic_pointer_cast(const WeakPtr<U>& p)
+    {
+        return orxonox_cast<T*>(p.get());
+    }
+}
+
+#endif /* _WeakPtr_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,4 @@
+ADD_SOURCE_FILES(CORE_SRC_FILES
+  ScopeManager.cc
+  ScopedSingletonIncludes.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/Scope.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/Scope.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/Scope.h	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@ingroup SingletonScope
+@brief Declaration of the classes that are needed to use Scopes: orxonox::Scope and orxonox::ScopeListener.
+
+@anchor Scope
+
+A virtual scope can be represented by an instance of class orxonox::Scope. orxonox::Scope<@a scope> is a template
+an its template argument defines the name of the virtual scope. See orxonox::ScopeID for an enumeration of the
+available values for @a scope. The orxonox::Scope object for a given @a scope can be activated or deactivated.
+Instances of orxonox::ScopeListener can register in orxonox::ScopeMAnager for a given @a scope and will get a
+notification if the corresponding orxonox::Scope object changes its state.
+
+Scopes are usually used to control the creation and destruction of Singletons.
+
+@see orxonox::Singleton
+*/
+
+#ifndef __Core_Scope_H__
+#define __Core_Scope_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+#include <map>
+#include <set>
+#include <loki/ScopeGuard.h>
+
+#include "util/Output.h"
+#include "ScopeManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief ScopeListeners register themselves in the corresponding Scope and wait for notifications.
+        Notifications are sent if a Scope is activated or deactivated.
+
+        @see See @ref Scope "this description" for details about the interrelationship of Scope, ScopeListener, and ScopeManager.
+    */
+    class _CoreExport ScopeListener
+    {
+        friend class ScopeManager;
+
+        protected:
+            ScopeListener() : bActivated_(false) { }
+            virtual ~ScopeListener() = default;
+
+            //! Gets called if the scope is activated
+            virtual void activated() = 0;
+            //! Gets called if the scope is deactivated
+            virtual void deactivated() = 0;
+
+        private:
+            bool bActivated_;
+    };
+
+    /**
+        @brief A scope for a given template argument is either active or not.
+
+        Objects inheriting from a ScopeListener are registered in a list (different for each scope).
+        If the scope gets activated or deactivated, all objects in this list are notified.
+
+        @see See @ref Scope "this description" for details about the interrelationship of Scope, ScopeListener, and ScopeManager.
+    */
+    template <ScopeID::Value scope>
+    class Scope
+    {
+        public:
+            //! Constructor: activate the listeners.
+            Scope()
+            {
+                orxout(internal_status) << "creating scope... (" << scope << ")" << endl;
+
+                Loki::ScopeGuard deactivator = Loki::MakeObjGuard(*this, &Scope::deactivateScope);
+                ScopeManager::getInstance().addScope(scope);
+                deactivator.Dismiss();
+
+                orxout(internal_status) << "created scope (" << scope << ")" << endl;
+            }
+
+            //! Destructor: deactivate the listeners.
+            ~Scope()
+            {
+                orxout(internal_status) << "destroying scope... (" << scope << ")" << endl;
+
+                this->deactivateScope();
+
+                orxout(internal_status) << "destroyed scope (" << scope << ")" << endl;
+            }
+
+            //! Deactivates the listeners of this scope in case the scope is destroyed or the construction fails.
+            void deactivateScope()
+            {
+                ScopeManager::getInstance().removeScope(scope);
+            }
+
+            //! Returns true if the scope is active.
+            static bool isActive()
+            {
+                return ScopeManager::getInstance().isActive(scope);
+            }
+    };
+}
+
+#endif /* __Core_Scope_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopeManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopeManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopeManager.cc	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of orxonox::ScopeManager.
+*/
+
+#include "ScopeManager.h"
+
+#include "Scope.h"
+
+namespace orxonox
+{
+    ScopeManager* ScopeManager::singletonPtr_s = nullptr;
+
+    void ScopeManager::addScope(ScopeID::Value scope)
+    {
+        this->activeScopes_.insert(scope);
+        this->activateListenersForScope(scope);
+    }
+
+    void ScopeManager::removeScope(ScopeID::Value scope)
+    {
+        this->activeScopes_.erase(scope);
+        this->deactivateListenersForScope(scope);
+    }
+
+    bool ScopeManager::isActive(ScopeID::Value scope)
+    {
+        return this->activeScopes_.find(scope) != this->activeScopes_.end();
+    }
+
+    void ScopeManager::addListener(ScopeListener* listener, ScopeID::Value scope)
+    {
+        this->listeners_[scope].insert(listener);
+        if (this->isActive(scope))
+            this->activateListener(listener);
+    }
+
+    void ScopeManager::removeListener(ScopeListener* listener, ScopeID::Value scope)
+    {
+        if (this->isActive(scope))
+            this->deactivateListener(listener);
+        this->listeners_[scope].erase(listener);
+    }
+
+    void ScopeManager::activateListenersForScope(ScopeID::Value scope)
+    {
+        for (ScopeListener* listener : this->listeners_[scope])
+            this->activateListener(listener);
+    }
+
+    void ScopeManager::deactivateListenersForScope(ScopeID::Value scope)
+    {
+        for (ScopeListener* listener : this->listeners_[scope])
+            this->deactivateListener(listener);
+    }
+
+    void ScopeManager::activateListener(ScopeListener* listener)
+    {
+        listener->activated();
+        listener->bActivated_ = true;
+    }
+
+    void ScopeManager::deactivateListener(ScopeListener* listener)
+    {
+        if (listener->bActivated_)
+        {
+            try
+                { listener->deactivated(); }
+            catch (...)
+                { orxout(internal_warning) << "ScopeListener::deactivated() failed! This MUST NOT happen, fix it!" << endl; }
+            listener->bActivated_ = false;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopeManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopeManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopeManager.h	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@ingroup SingletonScope
+@brief Declaration of orxonox::ScopeManager.
+*/
+
+#ifndef __ScopeManager_H__
+#define __ScopeManager_H__
+
+#include "core/CorePrereqs.h"
+
+#include <map>
+#include <set>
+
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    /**
+        @brief The ScopeManager stores the variables of the Scope templates in a statically linked context.
+
+        If all Scope objects are managed by this class, they are statically linked in the core library.
+        Without this, a new instance of Scope<T> for each T would be created in every library of Orxonox,
+        which is of course not the desired behavior.
+
+        @see See @ref Scope "this description" for details about the interrelationship of Scope, ScopeListener, and ScopeManager.
+    */
+    class _CoreExport ScopeManager : public Singleton<ScopeManager>
+    {
+        friend class Singleton<ScopeManager>;
+
+        public:
+            /** Adds a scope and activates all listeners which are registered for this scope */
+            void addScope(ScopeID::Value scope);
+            /** Removes a scope and deactivates all listeners which are registered for this scope */
+            void removeScope(ScopeID::Value scope);
+            /** Returns true if this scope is active */
+            bool isActive(ScopeID::Value scope);
+
+            /** Registers a listener for the given scope. If the scope is already active, the listener is activate immediately. */
+            void addListener(ScopeListener* listener, ScopeID::Value scope);
+            /** Unregisters a listener for the given scope. If the scope is still active, the listener is deactivated before removal. */
+            void removeListener(ScopeListener* listener, ScopeID::Value scope);
+
+            /** Returns all registered listeners for a given scope. */
+            const std::set<ScopeListener*>& getListeners(ScopeID::Value scope)
+                { return this->listeners_[scope]; }
+
+        private:
+            void activateListenersForScope(ScopeID::Value scope);
+            void deactivateListenersForScope(ScopeID::Value scope);
+
+            void activateListener(ScopeListener* listener);
+            void deactivateListener(ScopeListener* listener);
+
+            std::set<ScopeID::Value> activeScopes_;
+            std::map<ScopeID::Value, std::set<ScopeListener*>> listeners_; //!< Stores all listeners for a scope
+
+            static ScopeManager* singletonPtr_s;
+    };
+}
+
+#endif /* __ScopeManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonIncludes.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonIncludes.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonIncludes.cc	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ScopedSingletonIncludes.h"
+
+namespace orxonox
+{
+    void StaticallyInitializedScopedSingletonWrapper::load()
+    {
+        ScopeManager::getInstance().addListener(this->wrapper_, this->scope_);
+    }
+
+    void StaticallyInitializedScopedSingletonWrapper::unload()
+    {
+        ScopeManager::getInstance().removeListener(this->wrapper_, this->scope_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonIncludes.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup SingletonScope
+    @brief Definition of the ManageScopedSingleton macro.
+*/
+
+#ifndef __ScopedSingletonIncludes_H__
+#define __ScopedSingletonIncludes_H__
+
+#include "core/CorePrereqs.h"
+
+#include "ScopedSingletonWrapper.h"
+#include "core/module/StaticallyInitializedInstance.h"
+
+/**
+    @brief Creates an orxonox::ScopedSingletonWrapper for an orxonox::Singleton and registers it with orxonox::ScopeManager.
+    @param className The name of the singleton class
+    @param scope The scope in which the singleton should exist
+    @param allowedToFail If true, the singleton is allowed to fail and thus a try-catch block is used when creating the singleton.
+
+    If this macro is called for a singleton, it is wrapped in a ScopedSingletonWrapper and registered with ScopeManager
+    and will thus be created if its scope becomes active and destroyed if is deactivated.
+
+
+    Usually a singleton gets created automatically when it is first used, but it will never
+    be destroyed (unless the singleton explicitly deletes itself). To allow controlled
+    construction and destruction, the singleton can be put within a virtual scope. This is
+    done by registering the singleton class with orxonox::ScopeManager. To
+    do so, the ManageScopedSingleton() macro has to be called:
+
+    @code
+    ManageScopedSingleton(TestSingleton, ScopeID::Graphics, false); // muste be called in a source (*.cc) file
+    @endcode
+
+    @b Important: If you call ManageScopedSingleton(), you don't have to initialize singletonPtr_s anymore,
+    because that's already done by the macro.
+
+    Now the singleton TestSingleton gets automatically created if the scope Graphics becomes
+    active and also gets destroyed if the scope is deactivated.
+
+    Note that not all singletons must register with a scope, but it's recommended.
+
+*/
+#define ManageScopedSingleton(className, scope, allowedToFail) \
+    className* className::singletonPtr_s = nullptr; \
+    static ScopedSingletonWrapper& className##ScopedSingletonWrapper \
+        = (new orxonox::SI_SSW(new ClassScopedSingletonWrapper<className, allowedToFail>(#className), scope))->getWrapper()
+
+namespace orxonox
+{
+    class _CoreExport StaticallyInitializedScopedSingletonWrapper : public StaticallyInitializedInstance
+    {
+        public:
+            StaticallyInitializedScopedSingletonWrapper(ScopedSingletonWrapper* wrapper, ScopeID::Value scope)
+                : StaticallyInitializedInstance(StaticInitialization::SCOPED_SINGLETON_WRAPPER)
+                , wrapper_(wrapper)
+                , scope_(scope)
+            {}
+            ~StaticallyInitializedScopedSingletonWrapper() { delete wrapper_; }
+
+            virtual void load() override;
+            virtual void unload() override;
+
+            inline ScopedSingletonWrapper& getWrapper()
+                { return *this->wrapper_; }
+
+        private:
+            ScopedSingletonWrapper* wrapper_;
+            ScopeID::Value scope_;
+    };
+
+    typedef StaticallyInitializedScopedSingletonWrapper SI_SSW;
+}
+
+#endif /* __ScopedSingletonIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonWrapper.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonWrapper.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/core/singleton/ScopedSingletonWrapper.h	(revision 11817)
@@ -0,0 +1,196 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup SingletonScope
+    @brief Definition of orxonox::ScopedSingletonWrapper and orxonox::ClassScopedSingletonWrapper.
+
+    ScopedSingletonWrapper is used to create and destroy Singletons that belong to
+    a given Scope. For each one of these singletons, the macro ManageScopedSingleton()
+    has to be called to register the wrapper with orxonox::ScopeManager.
+
+    See @ref SingletonExample "this code" for an example.
+
+    @see orxonox::Singleton
+    @see orxonox::Scope
+*/
+
+#ifndef __ScopedSingletonWrapper_H__
+#define __ScopedSingletonWrapper_H__
+
+#include "core/CorePrereqs.h"
+
+#include <cassert>
+#include "util/Exception.h"
+#include "util/Singleton.h"
+#include "Scope.h"
+
+namespace orxonox
+{
+    /**
+        @brief Base class of ClassScopedSingletonWrapper.
+    */
+    class _CoreExport ScopedSingletonWrapper : public ScopeListener
+    {
+        public:
+            /// Constructor: Initializes all the values
+            ScopedSingletonWrapper(const std::string& className)
+                : className_(className)
+            { }
+            virtual ~ScopedSingletonWrapper() = default;
+
+        protected:
+            const std::string className_;   ///< The name of the scoped singleton class that is managed by this object
+    };
+
+    /**
+        @anchor ClassScopedSingletonWrapper
+
+        @brief Manages a scoped singleton
+        @param T The managed singleton class
+        @param allowedToFail If true, a specialization of this template is used, that uses try-catch blocks to handle possible failures.
+
+        This class inherits from ScopeListener and is registered for a scope in ScopeManager and thus its functions
+        activated() and deactivated() are called whenever the Scope changes its state.
+
+        If the Scope is activated, a new instance of @a T (which must be a singleton) is created.
+        If the Scope is deactivated, the singleton is destroyed.
+
+        @see Singleton
+    */
+    template <class T, bool allowedToFail>
+    class ClassScopedSingletonWrapper : public ScopedSingletonWrapper
+    {
+    public:
+        ClassScopedSingletonWrapper(const std::string& className)
+            : ScopedSingletonWrapper(className)
+            , singletonPtr_(nullptr)
+        {
+        }
+
+        ~ClassScopedSingletonWrapper()
+        {
+            if (singletonPtr_)
+                this->destroy(singletonPtr_);
+        }
+
+        //! Called if the Scope of the Singleton gets active (creates the instance)
+        virtual void activated() override
+        {
+            assert(singletonPtr_ == nullptr);
+            singletonPtr_ = new T();
+        }
+
+        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
+        virtual void deactivated() override
+        {
+            assert(singletonPtr_ != nullptr);
+            this->destroy(singletonPtr_);
+            singletonPtr_ = nullptr;
+        }
+
+        //! Destroys the singleton instance - overloaded for Destroyable, calls Destroyable::destroy()
+        void destroy(Destroyable*)
+        {
+            singletonPtr_->destroy();
+        }
+        //! Destroys the singleton instance - overloaded for all other pointers, calls delete
+        void destroy(void*)
+        {
+            delete singletonPtr_;
+        }
+
+    private:
+        T* singletonPtr_;   ///< Unique instance of the singleton class @a T
+    };
+
+    /**
+        @brief This class partially spezializes ClassScopedSingletonWrapper for classes @a T that are allowed to fail.
+        @param T The managed singleton class
+
+        Because @a T could fail when being created, this partial spezialization of ClassScopedSingletonWrapper
+        uses a try-catch block to handle exceptions.
+
+        See @ref ClassScopedSingletonWrapper for a full documentation of the basis template.
+    */
+    template <class T>
+    class ClassScopedSingletonWrapper<T, true> : public ScopedSingletonWrapper
+    {
+    public:
+        ClassScopedSingletonWrapper(const std::string& className)
+            : ScopedSingletonWrapper(className)
+            , singletonPtr_(nullptr)
+        {
+        }
+
+        ~ClassScopedSingletonWrapper()
+        {
+            if (singletonPtr_)
+                this->destroy(singletonPtr_);
+        }
+
+        //! Called if the Scope of the Singleton gets active (creates the instance)
+        virtual void activated() override
+        {
+            assert(singletonPtr_ == nullptr);
+            try
+                { singletonPtr_ = new T(); }
+            catch (const InitialisationAbortedException& ex)
+                { orxout(internal_error) << ex.getDescription() << endl; }
+            catch (...)
+                { orxout(internal_error) << "Singleton creation failed: " << Exception::handleMessage() << endl; }
+        }
+
+        //! Called if the Scope of this Singleton gets deactivated (destroys the instance)
+        virtual void deactivated() override
+        {
+            if (singletonPtr_ != nullptr)
+            {
+                this->destroy(singletonPtr_);
+                singletonPtr_ = nullptr;
+            }
+        }
+
+        //! Destroys the singleton instance - overloaded for Destroyable, calls Destroyable::destroy()
+        void destroy(Destroyable*)
+        {
+            singletonPtr_->destroy();
+        }
+        //! Destroys the singleton instance - overloaded for void*, calls delete
+        void destroy(void*)
+        {
+            delete singletonPtr_;
+        }
+
+    private:
+        T* singletonPtr_;   ///< Unique instance of the singleton class @a T
+    };
+}
+
+#endif /* __ScopedSingletonWrapper_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,69 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(NETWORK_SRC_FILES
+  Client.cc
+  ClientConnection.cc
+  ClientConnectionListener.cc
+  Connection.cc
+  FunctionCall.cc
+  FunctionCallManager.cc
+  GamestateManager.cc
+  #GamestateClient.cc
+  GamestateHandler.cc
+  LANDiscoverable.cc
+  LANDiscovery.cc
+  WANDiscoverable.cc
+  WANDiscovery.cc
+  MasterServerComm.cc
+  NetworkFunction.cc
+  NetworkFunctionIncludes.cc
+  NetworkFunctionManager.cc
+  NetworkStaticInitializationHandler.cc
+  Host.cc
+  Server.cc
+  MasterServer.cc
+  PeerList.cc
+  ServerList.cc
+  ServerConnection.cc
+  TrafficControl.cc
+)
+
+ADD_SUBDIRECTORY(packet)
+ADD_SUBDIRECTORY(synchronisable)
+
+ORXONOX_ADD_LIBRARY(network
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    Client.h
+    LANDiscovery.h
+    WANDiscovery.h
+  PCH_FILE
+    NetworkPrecompiledHeaders.h
+  LINK_LIBRARIES
+    ${ZLIB_LIBRARY}
+    #${ENET_LIBRARY}
+    enet_orxonox
+    ${Boost_THREAD_LIBRARY}
+    ${CEGUI_TOLUA_LIBRARY}
+    util
+    core
+  SOURCE_FILES
+    ${NETWORK_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/libraries/network/Client.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Client.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Client.cc	(revision 11817)
@@ -0,0 +1,211 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Implementation: Client
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "Client.h"
+
+#include <cassert>
+
+#include "util/Clock.h"
+#include "util/Output.h"
+#include "synchronisable/Synchronisable.h"
+#include "packet/Chat.h"
+#include "packet/Gamestate.h"
+#include "FunctionCallManager.h"
+#include "core/CoreIncludes.h"
+#include "core/Game.h"
+#include "core/commandline/CommandLineParser.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+namespace orxonox
+{
+
+  ManageScopedSingleton( Client, ScopeID::ROOT, false );
+
+  /**
+  * Constructor for the Client class
+  * initializes the address and the port to default localhost:NETWORK_PORT
+  */
+  Client::Client():
+      isSynched_(false),
+      gameStateFailure_(false),
+      timeSinceLastUpdate_(0)
+  {
+    this->setDestination( CommandLineParser::getValue("dest").get<std::string>(), CommandLineParser::getValue("port") );
+  }
+
+  Client::~Client()
+  {
+    if ( ClientConnection::isConnected() )
+      closeConnection();
+  }
+
+  /**
+  * Establish the Connection to the Server
+  * @return true/false
+  */
+  bool Client::establishConnection()
+  {
+    Synchronisable::setClient(true);
+    if( ClientConnection::establishConnection() )
+    {
+      Host::setActive(true);
+      GamestateManager::addPeer(NETWORK_PEER_ID_SERVER);
+      return true;
+    }
+    else
+      return false;
+  }
+
+  /**
+  * closes the Connection to the Server
+  * @return true/false
+  */
+  bool Client::closeConnection()
+  {
+    Host::setActive(false);
+    GamestateManager::removePeer(NETWORK_PEER_ID_SERVER);
+    return ClientConnection::closeConnection();
+  }
+
+  void Client::setDestination(const std::string& serverAddress, unsigned int port)
+  {
+    ClientConnection::setServerAddress(serverAddress);
+    ClientConnection::setPort(port);
+  }
+
+  void Client::queuePacket(ENetPacket *packet, int clientID, uint8_t channelID)
+  {
+    ClientConnection::addPacket(packet, channelID);
+  }
+
+  void Client::printRTT()
+  {
+    orxout(message) << "Round trip time to server is " << ClientConnection::getRTT() << " ms" << endl;
+  }
+
+  /**
+   * @brief Sends a chat message to the server.
+   * @param message message to be sent
+   * @param sourceID the ID of the sender
+   * @param targetID the ID of the receiver
+   */
+  void Client::doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
+  {
+    // send the message to the server
+    packet::Chat* packet = new packet::Chat(message, sourceID, targetID);
+    packet->send(static_cast<Host*>(this));
+  }
+
+  /**
+   * @brief Gets called if a packet::Chat packet is received. Calls the parent function which passes the message to the listeners.
+   */
+  void Client::doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
+  {
+    // call the parent function which passes the message to the listeners
+    Host::doReceiveChat(message, sourceID, targetID);
+  }
+
+  /**
+   * Processes incoming packets, sends a gamestate to the server and does the cleanup
+   * @param time
+   */
+  void Client::update(const Clock& time)
+  {
+    //this steers our network frequency
+    timeSinceLastUpdate_+=time.getDeltaTime();
+    if(timeSinceLastUpdate_>=NETWORK_PERIOD)
+    {
+      timeSinceLastUpdate_ -= static_cast<unsigned int>( timeSinceLastUpdate_ / NETWORK_PERIOD ) * NETWORK_PERIOD;
+      if ( isConnected() && isSynched_ )
+      {
+        orxout(verbose, context::network) << "popping partial gamestate: " << endl;
+//         packet::Gamestate *gs = GamestateClient::getGamestate();
+        if( GamestateManager::update() )
+        {
+          std::vector<packet::Gamestate*> gamestates = GamestateManager::getGamestates();
+          for( packet::Gamestate* gamestate : gamestates )
+          {
+            gamestate->send( static_cast<Host*>(this) );
+          }
+        }
+        //assert(gs); <--- there might be the case that no data has to be sent, so its commented out now
+//         if(gs){
+//           orxout(verbose, context::network) << "client tick: sending gs " << gs << endl;
+//           if( !gs->send() )
+//             orxout(internal_warning, context::network) << "Problem adding partial gamestate to queue" << endl;
+//         // gs gets automatically deleted by enet callback
+//         }
+        FunctionCallManager::sendCalls(static_cast<Host*>(this));
+      }
+    }
+//     sendPackets(); // flush the enet queue
+
+    Connection::processQueue();
+    if(GamestateManager::processGamestates())
+    {
+      FunctionCallManager::processBufferedFunctionCalls();
+      if(!isSynched_)
+        isSynched_=true;
+    }
+//     GamestateManager::cleanup();;
+//     Connection::sendPackets();
+
+    return;
+  }
+
+  void Client::connectionClosed()
+  {
+    Game::getInstance().popState();
+    Game::getInstance().popState();
+  }
+
+  void Client::processPacket(packet::Packet* packet)
+  {
+    if( packet->isReliable() )
+    {
+      if( this->getLastReceivedGamestateID(packet->getPeerID()) >= packet->getRequiredGamestateID() )
+        packet->process(static_cast<Host*>(this));
+      else
+        this->packetQueue_.push_back(packet);
+    }
+    else
+      packet->process(static_cast<Host*>(this));
+  }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/Client.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Client.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Client.h	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Interface: Client
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef _Client_H__
+#define _Client_H__
+
+#include "NetworkPrereqs.h"
+
+#include <string>
+#include <deque>
+
+#include "util/UtilPrereqs.h"
+#include "util/Singleton.h"
+#include "ClientConnection.h"
+// #include "GamestateClient.h"
+#include "Host.h"
+#include "LANDiscovery.h"
+#include "packet/ServerInformation.h"
+
+// tolua_begin
+namespace orxonox
+{
+// tolua_end
+  /**
+  Client *client;
+  * The network/Client class
+  * This class implements all necessary function for the network communication
+  * It is the root class of the network module
+  *
+  */
+  class _NetworkExport Client // tolua_export
+    : public Host, protected ClientConnection, public Singleton<Client>
+  { // tolua_export
+  friend class Singleton<Client>;
+  public:
+    Client();
+    ~Client();
+
+    static Client* getInstance(){ return singletonPtr_s; } // tolua_export
+
+    virtual bool establishConnection() override;
+    void setDestination( const std::string& serverAddress, unsigned int port ); // tolua_export
+    virtual bool closeConnection() override;
+    virtual void queuePacket(ENetPacket* packet, int clientID, uint8_t channelID) override;
+    virtual bool sendPacket( packet::Packet* packet ) override{ return packet->send( static_cast<Host*>(this) ); }
+    virtual void doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID) override;
+    virtual void doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID) override;
+    virtual void printRTT() override;
+
+    void update(const Clock& time);
+  protected:
+    virtual void connectionClosed() override;
+  private:
+    Client(const Client& copy); // not used
+    virtual bool isServer_() override{return false;}
+    virtual void processPacket(packet::Packet* packet) override;
+
+    static Client* singletonPtr_s;
+    bool isSynched_;
+    std::deque<packet::Packet*> packetQueue_;
+
+    bool gameStateFailure_;
+    float timeSinceLastUpdate_;
+  }; // tolua_export
+
+
+} // tolua_export
+
+#endif /* _Client_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/ClientConnection.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ClientConnection.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ClientConnection.cc	(revision 11817)
@@ -0,0 +1,183 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ClientConnection.h"
+
+#include <cassert>
+#define WIN32_LEAN_AND_MEAN
+#include <enet/enet.h>
+#include "util/Output.h"
+
+namespace orxonox
+{
+  const unsigned int NETWORK_CLIENT_WAIT_TIME = 1;
+  const unsigned int NETWORK_CLIENT_CONNECTION_TIMEOUT = 3000; //millisecs
+  const unsigned int NETWORK_CLIENT_MAX_CONNECTIONS = 1;
+
+
+  ClientConnection::ClientConnection():
+    Connection(NETWORK_PEER_ID_SERVER),
+    established_(false),
+    server_(nullptr)
+  {
+    this->serverAddress_ = new ENetAddress();
+    //set standard address and port
+    enet_address_set_host(this->serverAddress_, "127.0.0.1"); // TODO: check for IPv6 and connect to ::1 instead
+    serverAddress_->port = NETWORK_PORT;
+  }
+
+  ClientConnection::~ClientConnection(){
+    if(this->established_)
+      closeConnection();
+    delete this->serverAddress_; // surely was created
+  }
+
+  void ClientConnection::setServerAddress( const std::string& serverAddress ) {
+    if (enet_address_set_host (this->serverAddress_, serverAddress.c_str()) < 0)
+        orxout(internal_error, context::network) << "Could not resolve \"" << serverAddress << "\"." << endl;
+  }
+
+  void ClientConnection::setPort( unsigned int port ) {
+    this->serverAddress_->port = port;
+  }
+
+  bool ClientConnection::establishConnection()
+  {
+    ENetEvent event;
+
+    // create host
+    this->host_ = enet_host_create(nullptr, NETWORK_CLIENT_MAX_CONNECTIONS, NETWORK_CHANNEL_COUNT, 0, 0);
+    
+    if ( this->host_ == nullptr )
+    {
+      orxout(internal_error, context::network) << "ClientConnection: host_ == nullptr" << endl;
+      // error handling
+      return false;
+    }
+    
+    // enable compression
+    this->enableCompression();
+    
+    assert( this->host_->socket4 != ENET_SOCKET_NULL || this->host_->socket6 != ENET_SOCKET_NULL );
+    if (this->host_->socket4 == ENET_SOCKET_NULL)
+        orxout(internal_warning, context::network) << "IPv4 Socket failed." << endl;
+    else if (this->host_->socket6 == ENET_SOCKET_NULL)
+        orxout(internal_warning, context::network) << "IPv6 Socket failed." << endl;
+    else
+        orxout(internal_info, context::network) << "Using IPv4 and IPv6 Sockets." << endl;
+
+    this->server_ = enet_host_connect(this->host_, serverAddress_, NETWORK_CHANNEL_COUNT, 0);
+    if ( this->server_==nullptr )
+    {
+      orxout(internal_error, context::network) << "ClientConnection: server_ == nullptr" << endl;
+      // error handling
+      return false;
+    }
+    // handshake
+    for( unsigned int i=0; i<NETWORK_CLIENT_CONNECTION_TIMEOUT/NETWORK_CLIENT_WAIT_TIME; i++ )
+    {
+      if( enet_host_service(this->host_, &event, NETWORK_CLIENT_WAIT_TIME)>=0 && event.type == ENET_EVENT_TYPE_CONNECT )
+      {
+        // manually add server to list of peers
+        /*incomingEvent inEvent = */Connection::preprocessConnectEvent(event);
+//         addPeer(inEvent.peerID);
+        // start communication thread
+        this->established_=true;
+        Connection::startCommunicationThread();
+        return true;
+      }
+    }
+    orxout(user_error, context::network) << "Could not connect to server" << endl;
+    return false;
+  }
+
+  bool ClientConnection::closeConnection() {
+    ENetEvent event;
+
+    if ( !this->established_ )
+      return true;
+    this->established_ = false;
+    
+    // stop communication thread and disconnect server
+    Connection::stopCommunicationThread();
+    enet_peer_disconnect(this->server_, 0);
+    for( unsigned int i=0; i<NETWORK_CLIENT_CONNECTION_TIMEOUT/NETWORK_CLIENT_WAIT_TIME; i++)
+    {
+      if ( enet_host_service(this->host_, &event, NETWORK_CLIENT_WAIT_TIME) >= 0 )
+      {
+        switch (event.type)
+        {
+          case ENET_EVENT_TYPE_NONE:
+          case ENET_EVENT_TYPE_CONNECT:
+            break;
+          case ENET_EVENT_TYPE_RECEIVE:
+            enet_packet_destroy(event.packet);
+            break;
+          case ENET_EVENT_TYPE_DISCONNECT:
+            orxout(verbose, context::network) << "received disconnect confirmation from server" << endl;
+            this->connectionClosed();
+            return true;
+        }
+      }
+    }
+    enet_peer_reset( this->server_ );
+    this->connectionClosed();
+    return false;
+  }
+
+
+  void ClientConnection::addPacket(ENetPacket *packet, uint8_t channelID) {
+    assert( this->server_ );
+    assert( packet );
+//     return Connection::addPacket( packet, NETWORK_PEER_ID_SERVER, channelID );
+    // HACK: actually there should be a way to do this using addPacket and the correct peerID
+    return Connection::broadcastPacket(packet, channelID);
+  }
+
+  void ClientConnection::addPeer(uint32_t peerID)
+  {
+    assert(0);
+  }
+  void ClientConnection::removePeer(uint32_t peerID)
+  {
+    this->established_=false;
+    orxout(internal_error, context::network) << "Received disconnect Packet from Server!" << endl;
+        // server closed the connection
+    this->stopCommunicationThread();
+    this->connectionClosed();
+  }
+
+  uint32_t ClientConnection::getRTT()
+  {
+    if (server_)
+        return server_->roundTripTime;
+    else
+        return 0;
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/ClientConnection.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ClientConnection.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ClientConnection.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ClientConnection_H__
+#define _ClientConnection_H__
+
+#include "NetworkPrereqs.h"
+#include "Connection.h"
+
+namespace orxonox
+{
+
+  class _NetworkExport ClientConnection: public Connection{
+  public:
+    ClientConnection();
+    virtual ~ClientConnection();
+
+    void setServerAddress( const std::string& serverAddress );
+    void setPort( unsigned int port );
+
+//     ENetEvent *getEvent();
+    // check wheter the packet queue is empty
+//     bool queueEmpty();
+    // create a new listener thread
+    virtual bool establishConnection();
+    virtual bool closeConnection();
+    // add a packet to queue for the server
+    void addPacket(ENetPacket *packet, uint8_t channelID);
+    inline bool isConnected(){ return this->established_; }
+  protected:
+    virtual void connectionClosed()=0;
+    uint32_t getRTT();
+  private:
+    virtual void addPeer(uint32_t peerID) override;
+    virtual void removePeer(uint32_t peerID) override;
+
+    bool disconnectConnection();
+    // enet stuff
+    ENetAddress *serverAddress_;
+    bool established_;
+    // clientlist
+    ENetPeer *server_;
+};
+
+
+}
+
+#endif /* _ClientConnection_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/ClientConnectionListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ClientConnectionListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ClientConnectionListener.cc	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ClientConnectionListener.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+// #include "ClientInformation.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(ClientConnectionListener).inheritsFrom<Listable>();
+
+    ClientConnectionListener::ClientConnectionListener()
+    {
+        RegisterObject(ClientConnectionListener);
+    }
+
+    void ClientConnectionListener::broadcastClientConnected(unsigned int clientID)
+    {
+        for (ClientConnectionListener* listener : ObjectList<ClientConnectionListener>())
+            listener->clientConnected(clientID);
+    }
+
+    void ClientConnectionListener::broadcastClientDisconnected(unsigned int clientID)
+    {
+        for (ClientConnectionListener* listener : ObjectList<ClientConnectionListener>())
+            listener->clientDisconnected(clientID);
+    }
+
+//     void ClientConnectionListener::getConnectedClients()
+//     {
+//         ClientInformation* client = ClientInformation::getBegin();
+//         while (client)
+//         {
+//             this->clientConnected(client->getID());
+//             client = client->next();
+//         }
+//     }
+}
+
+
Index: /code/branches/RacingBots_FS18/src/libraries/network/ClientConnectionListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ClientConnectionListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ClientConnectionListener.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ClientConnectionListener_H__
+#define _ClientConnectionListener_H__
+
+#include "NetworkPrereqs.h"
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    class _NetworkExport ClientConnectionListener : virtual public Listable
+    {
+        public:
+            ClientConnectionListener();
+            virtual ~ClientConnectionListener() {}
+
+            static void broadcastClientConnected(unsigned int clientID);
+            static void broadcastClientDisconnected(unsigned int clientID);
+
+            virtual void clientConnected(unsigned int clientID) = 0;
+            virtual void clientDisconnected(unsigned int clientID) = 0;
+
+        protected:
+//             void getConnectedClients();
+    };
+}
+
+
+#endif /* _ClientConnectionListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/Connection.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Connection.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Connection.cc	(revision 11817)
@@ -0,0 +1,364 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Connection.h"
+
+#include <cassert>
+#include <deque>
+#define WIN32_LEAN_AND_MEAN
+#include <enet/enet.h>
+#include <boost/thread.hpp>
+#include <boost/thread/mutex.hpp>
+#include <boost/date_time.hpp>
+
+#include "packet/Packet.h"
+#include <util/Sleep.h>
+
+namespace orxonox
+{
+  const boost::posix_time::millisec NETWORK_COMMUNICATION_THREAD_WAIT_TIME(200);
+  const unsigned int                NETWORK_DISCONNECT_TIMEOUT = 500;
+
+  Connection::Connection(uint32_t firstPeerID):
+    host_(nullptr), bCommunicationThreadRunning_(false), nextPeerID_(firstPeerID)
+  {
+    enet_initialize();
+    atexit(enet_deinitialize);
+    this->incomingEventsMutex_ = new boost::mutex;
+    this->outgoingEventsMutex_ = new boost::mutex;
+//     this->overallMutex_ = new boost::mutex;
+  }
+
+  Connection::~Connection()
+  {
+    delete this->incomingEventsMutex_;
+    delete this->outgoingEventsMutex_;
+  }
+
+  void Connection::startCommunicationThread()
+  {
+    this->bCommunicationThreadRunning_ = true;
+    this->communicationThread_ = new boost::thread(&Connection::communicationThread, this);
+  }
+  
+  void Connection::stopCommunicationThread()
+  {
+    this->bCommunicationThreadRunning_ = false;
+    if( !this->communicationThread_->timed_join(NETWORK_COMMUNICATION_THREAD_WAIT_TIME) )
+    {
+      // force thread to stop
+      this->communicationThread_->interrupt();
+    }
+    delete this->communicationThread_;
+  }
+
+  void Connection::disconnectPeer(uint32_t peerID)
+  {
+//     this->overallMutex_->lock();
+    outgoingEvent outEvent = { peerID, OutgoingEventType::disconnectPeer, nullptr, 0 };
+    
+    this->outgoingEventsMutex_->lock();
+    this->outgoingEvents_.push_back(outEvent);
+    this->outgoingEventsMutex_->unlock();
+//     this->overallMutex_->unlock();
+  }
+  
+  void Connection::disconnectPeers()
+  {
+    outgoingEvent outEvent = { 0, OutgoingEventType::disconnectPeers, nullptr, 0 };
+    
+    this->outgoingEventsMutex_->lock();
+    this->outgoingEvents_.push_back(outEvent);
+    this->outgoingEventsMutex_->unlock();
+  }
+
+  void Connection::addPacket(ENetPacket* packet, uint32_t peerID, uint8_t channelID)
+  {
+//     this->overallMutex_->lock();
+    outgoingEvent outEvent = { peerID, OutgoingEventType::sendPacket, packet, channelID };
+    
+    this->outgoingEventsMutex_->lock();
+    this->outgoingEvents_.push_back(outEvent);
+    this->outgoingEventsMutex_->unlock();
+//     this->overallMutex_->unlock();
+  }
+  
+  void Connection::broadcastPacket(ENetPacket* packet, uint8_t channelID)
+  {
+//     this->overallMutex_->lock();
+    outgoingEvent outEvent = { 0, OutgoingEventType::broadcastPacket, packet, channelID };
+    
+    this->outgoingEventsMutex_->lock();
+    this->outgoingEvents_.push_back(outEvent);
+    this->outgoingEventsMutex_->unlock();
+//     this->overallMutex_->unlock();
+  }
+
+  
+  void Connection::communicationThread()
+  {
+    ENetEvent event;
+    
+//     this->overallMutex_->lock();
+    while( bCommunicationThreadRunning_ )
+    {
+      // Receive all pending incoming Events (such as packets, connects and disconnects)
+      while( enet_host_check_events( this->host_, &event ) > 0 )
+      {
+        processIncomingEvent(event);
+      }
+      
+//       this->overallMutex_->unlock();
+      msleep(1);
+//       this->overallMutex_->lock();
+      
+      // Send all waiting outgoing packets
+      this->outgoingEventsMutex_->lock();
+      uint32_t outgoingEventsCount = this->outgoingEvents_.size();
+      this->outgoingEventsMutex_->unlock();
+      while( outgoingEventsCount > 0 )
+      {
+//         orxout(verbose, context::network) << "outgoing event" << endl;
+        this->outgoingEventsMutex_->lock();
+        outgoingEvent outEvent = this->outgoingEvents_.front();
+        this->outgoingEvents_.pop_front();
+        this->outgoingEventsMutex_->unlock();
+        
+        processOutgoingEvent(outEvent);
+        
+        this->outgoingEventsMutex_->lock();
+        outgoingEventsCount = this->outgoingEvents_.size();
+        this->outgoingEventsMutex_->unlock();
+      }
+      
+      // Wait for incoming events (at most NETWORK_WAIT_TIMEOUT ms)
+      if( enet_host_service( this->host_, &event, NETWORK_WAIT_TIMEOUT ) > 0 )
+      {
+        processIncomingEvent(event);
+      }
+    }
+//     this->overallMutex_->unlock();
+  }
+  
+  void Connection::processIncomingEvent(ENetEvent& event)
+  {
+    incomingEvent inEvent;
+    // preprocess event
+    switch( event.type )
+    {
+      case ENET_EVENT_TYPE_CONNECT:
+        inEvent = preprocessConnectEvent(event);
+        break;
+      case ENET_EVENT_TYPE_RECEIVE:
+        inEvent = preprocessReceiveEvent(event);
+        break;
+      case ENET_EVENT_TYPE_DISCONNECT:
+        inEvent = preprocessDisconnectEvent(event);
+        break;
+      case ENET_EVENT_TYPE_NONE:
+      default:
+        return;
+    }
+    
+    // pushing event to queue
+    this->incomingEventsMutex_->lock();
+    this->incomingEvents_.push_back(inEvent);
+    this->incomingEventsMutex_->unlock();
+  }
+  
+  void Connection::processOutgoingEvent(outgoingEvent& event)
+  {
+    ENetPeer* peer;
+    switch( event.type )
+    {
+      case OutgoingEventType::sendPacket:
+        // check whether the peer is still/already in the peer list
+        if( this->peerMap_.find(event.peerID) != this->peerMap_.end() )
+        {
+          peer = this->peerMap_[event.peerID];
+          enet_peer_send( peer, event.channelID, event.packet );
+        }
+        else
+        {
+          // peer probably already disconnected so just discard packet
+          assert(event.peerID<this->nextPeerID_);
+          enet_packet_destroy(event.packet);
+        }
+        break;
+      case OutgoingEventType::disconnectPeer:
+        if( this->peerMap_.find(event.peerID) != this->peerMap_.end() )
+        {
+          peer = this->peerMap_[event.peerID];
+          enet_peer_disconnect(peer, 0);
+        }
+        else
+        {
+          // peer probably already disconnected so just discard disconnect event
+          assert(event.peerID<this->nextPeerID_);
+        }
+        break;
+      case OutgoingEventType::disconnectPeers:
+        disconnectPeersInternal();
+        break;
+      case OutgoingEventType::broadcastPacket:
+        enet_host_broadcast( this->host_, event.channelID, event.packet );
+        break;
+      default:
+        assert(0);
+    }
+  }
+
+
+  void Connection::disconnectPeersInternal()
+  {
+    for( const auto& mapEntry : this->peerMap_ )
+    {
+      enet_peer_disconnect(mapEntry.second, 0);
+    }
+    uint32_t iterations = NETWORK_DISCONNECT_TIMEOUT/NETWORK_WAIT_TIMEOUT;
+    uint32_t i = 0;
+    while( this->peerMap_.size() && i++ < iterations )
+    {
+      ENetEvent event;
+      if( enet_host_service( this->host_, &event, NETWORK_WAIT_TIMEOUT ) > 0 )
+      {
+        processIncomingEvent(event);
+      }
+    }
+  }
+
+  void Connection::processQueue()
+  {
+    incomingEvent inEvent;
+
+    this->incomingEventsMutex_->lock();
+    uint32_t incomingEventsCount = this->incomingEvents_.size();
+    this->incomingEventsMutex_->unlock();
+    while( incomingEventsCount > 0 )
+    {
+      // pop event from queue
+      this->incomingEventsMutex_->lock();
+      inEvent = this->incomingEvents_.front();
+      this->incomingEvents_.pop_front();
+      this->incomingEventsMutex_->unlock();
+      
+      // process event
+      switch( inEvent.type )
+      {
+        case IncomingEventType::peerConnect:
+          addPeer(inEvent.peerID);
+          break;
+        case IncomingEventType::peerDisconnect:
+          removePeer(inEvent.peerID);
+          break;
+        case IncomingEventType::receivePacket:
+          processPacket(inEvent.packet);
+          break;
+        default:
+          break;
+      }
+      
+      // check whether there are still events in the queue
+      this->incomingEventsMutex_->lock();
+      incomingEventsCount = this->incomingEvents_.size();
+      this->incomingEventsMutex_->unlock();
+    }
+  }
+  
+  void Connection::waitOutgoingQueue()
+  {
+    uint32_t outgoingEventsCount;
+    this->outgoingEventsMutex_->lock();
+    outgoingEventsCount = this->outgoingEvents_.size();
+    this->outgoingEventsMutex_->unlock();
+    while( outgoingEventsCount )
+    {
+      msleep(1);
+      this->outgoingEventsMutex_->lock();
+      outgoingEventsCount = this->outgoingEvents_.size();
+      this->outgoingEventsMutex_->unlock();
+    }
+  }
+
+
+  incomingEvent Connection::preprocessConnectEvent(ENetEvent& event)
+  {
+    // make sure this peer doesn't exist
+    assert( this->peerMap_.find(this->nextPeerID_) == this->peerMap_.end() );
+    assert( this->peerIDMap_.find(event.peer) == this->peerIDMap_.end() );
+    
+    // give peer a new id and increase peerID for next peer
+    uint32_t peerID = this->nextPeerID_;
+    ++this->nextPeerID_;
+    
+    // add peer/peerID into peerMap_ and peerIDMap_
+    this->peerMap_[peerID] = event.peer;
+    this->peerIDMap_[event.peer] = peerID;
+    
+    // create new peerEvent and return it
+    incomingEvent inEvent = { peerID, IncomingEventType::peerConnect, nullptr };
+    return inEvent;
+  }
+  
+  incomingEvent Connection::preprocessDisconnectEvent(ENetEvent& event)
+  {
+    // assert that the peer exists and get peerID
+    assert( this->peerIDMap_.find(event.peer) != this->peerIDMap_.end() );
+    uint32_t peerID = this->peerIDMap_[event.peer];
+    
+    // remove peer/peerID from maps
+    this->peerIDMap_.erase(this->peerIDMap_.find(event.peer));
+    this->peerMap_.erase(this->peerMap_.find(peerID));
+    
+    // create new peerEvent and return it
+    incomingEvent inEvent = { peerID, IncomingEventType::peerDisconnect, nullptr };
+    return inEvent;
+  }
+  
+  incomingEvent Connection::preprocessReceiveEvent(ENetEvent& event)
+  {
+    // assert that the peer exists and get peerID
+    assert( this->peerIDMap_.find(event.peer) != this->peerIDMap_.end() );
+    uint32_t peerID = this->peerIDMap_[event.peer];
+    
+    // create new Packet from ENetPacket
+    packet::Packet* p = packet::Packet::createPacket(event.packet, peerID);
+    
+    // create new peerEvent and return it
+    incomingEvent inEvent = { peerID, IncomingEventType::receivePacket, p };
+    return inEvent;
+  }
+
+  
+  void Connection::enableCompression()
+  {
+    enet_host_compress_with_range_coder( this->host_ );
+  }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/Connection.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Connection.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Connection.h	(revision 11817)
@@ -0,0 +1,145 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Interface: Connection
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef _Connection_H__
+#define _Connection_H__
+
+#include "NetworkPrereqs.h"
+
+#include <deque>
+#include <map>
+#include <enet/enet.h>
+
+namespace boost
+{
+  class thread;
+  class mutex;
+}
+
+namespace orxonox
+{
+  const unsigned int NETWORK_PORT                   = 55556;
+  const unsigned int NETWORK_MAX_CONNECTIONS        = 50;
+  const unsigned int NETWORK_WAIT_TIMEOUT           = 1;
+  const unsigned int NETWORK_MAX_QUEUE_PROCESS_TIME = 5;
+  
+  enum class IncomingEventType
+  {
+    receivePacket   = 1,  // incoming packet
+    peerConnect     = 2,  // incoming connect request
+    peerDisconnect  = 3   // incoming disconnect request
+  };
+  
+  enum class OutgoingEventType
+  {
+    sendPacket      = 1,  // outgoing packet
+    broadcastPacket = 2,  // outgoing broadcast packet
+    disconnectPeer  = 3,  // outgoing disconnect request
+    disconnectPeers = 4   // outgoing disconnect request
+  };
+  
+  struct _NetworkExport incomingEvent
+  {
+    uint32_t          peerID;
+    IncomingEventType type;
+    packet::Packet*   packet;
+  };
+  
+  struct _NetworkExport outgoingEvent
+  {
+    uint32_t          peerID;
+    OutgoingEventType type;
+    ENetPacket*       packet;
+    ENetChannelID     channelID;
+  };
+  
+  class _NetworkExport Connection
+  {
+  public:
+    virtual ~Connection();
+
+  protected:
+    Connection(uint32_t firstPeerID = NETWORK_PEER_ID_SERVER+1);
+    
+    void startCommunicationThread();
+    void stopCommunicationThread();
+    
+    void addPacket(ENetPacket *packet, uint32_t peerID, uint8_t channelID);
+    void broadcastPacket(ENetPacket* packet, uint8_t channelID);
+    void disconnectPeer(uint32_t peerID);
+    void disconnectPeers();
+    
+    void enableCompression();
+
+    void processQueue();
+    void waitOutgoingQueue();     // wait for the outgoing queue to become empty (everything processed by communication thread)
+    virtual void addPeer(uint32_t peerID)=0;
+    virtual void removePeer(uint32_t peerID)=0;
+    virtual void processPacket( packet::Packet* packet)=0;
+    
+    incomingEvent preprocessConnectEvent(ENetEvent& event);
+    incomingEvent preprocessDisconnectEvent(ENetEvent& event);
+    incomingEvent preprocessReceiveEvent(ENetEvent& event);
+    
+    void processIncomingEvent(ENetEvent& event);
+    void processOutgoingEvent(outgoingEvent& event);
+    
+    void disconnectPeersInternal();
+
+    ENetHost*                     host_;
+  private:
+    void communicationThread();
+    
+    boost::thread*                communicationThread_;
+    bool                          bCommunicationThreadRunning_;
+    ENetAddress*                  bindAddress_;
+    std::deque<incomingEvent>     incomingEvents_;
+    std::deque<outgoingEvent>     outgoingEvents_;
+    boost::mutex*                 incomingEventsMutex_;
+    boost::mutex*                 outgoingEventsMutex_;
+    boost::mutex*                 overallMutex_;
+    std::map<uint32_t, ENetPeer*> peerMap_;
+    std::map<ENetPeer*, uint32_t> peerIDMap_;
+    uint32_t                      nextPeerID_;
+
+  };
+
+}
+
+#endif /* _Connection_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/FunctionCall.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/FunctionCall.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/FunctionCall.cc	(revision 11817)
@@ -0,0 +1,141 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] orxonox.net>, (C) 2010
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FunctionCall.h"
+
+#include <cassert>
+#include "util/MultiType.h"
+#include "NetworkFunction.h"
+#include "NetworkFunctionManager.h"
+
+namespace orxonox {
+
+FunctionCall::FunctionCall()
+ : nrOfArguments_(-1), objectID_(OBJECTID_UNKNOWN), size_(0)
+{
+}
+
+FunctionCall::~FunctionCall()
+{
+}
+
+
+bool FunctionCall::execute(){
+  NetworkFunctionBase* fct = NetworkFunctionManager::getInstance().getFunctionByNetworkId( this->functionID_ );
+  assert( fct != nullptr );
+  assert( this->nrOfArguments_==this->arguments_.size() );
+  switch(this->nrOfArguments_)
+  {
+    case 0:
+      return fct->call(this->objectID_);
+    case 1:
+      return fct->call(this->objectID_, this->arguments_[0]);
+    case 2:
+      return fct->call(this->objectID_, this->arguments_[0], this->arguments_[1]);
+    case 3:
+      return fct->call(this->objectID_, this->arguments_[0], this->arguments_[1], this->arguments_[2]);
+    case 4:
+      return fct->call(this->objectID_, this->arguments_[0], this->arguments_[1], this->arguments_[2], this->arguments_[3]);
+    case 5:
+      return fct->call(this->objectID_, this->arguments_[0], this->arguments_[1], this->arguments_[2], this->arguments_[3], this->arguments_[4]);
+    default:
+      assert(0);
+      return true; // return true to avoid that this functions gets called over and over again
+  }
+}
+
+void FunctionCall::setCall( uint32_t networkID, uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5){
+
+  // first determine the size that has to be reserved for this call
+  uint32_t callsize = 3*sizeof(uint32_t); //size for network-function-id and nrOfArguments and the objectID
+  uint32_t nrOfArguments = 0;
+  if(!mt1.null())
+  {
+    nrOfArguments++;
+    callsize += mt1.getNetworkSize();
+    this->arguments_.push_back(mt1);
+    if(!mt2.null())
+    {
+      nrOfArguments++;
+      callsize += mt2.getNetworkSize();
+      this->arguments_.push_back(mt2);
+      if(!mt3.null())
+      {
+        nrOfArguments++;
+        callsize += mt3.getNetworkSize();
+        this->arguments_.push_back(mt3);
+        if(!mt4.null())
+        {
+          nrOfArguments++;
+          callsize += mt4.getNetworkSize();
+          this->arguments_.push_back(mt4);
+          if(!mt5.null())
+          {
+            nrOfArguments++;
+            callsize += mt5.getNetworkSize();
+            this->arguments_.push_back(mt5);
+          }
+        }
+      }
+    }
+  }
+  this->nrOfArguments_ = nrOfArguments;
+  this->functionID_ = networkID;
+  this->objectID_ = objectID;
+  this->size_ = callsize;
+}
+
+void FunctionCall::loadData(uint8_t*& mem)
+{
+  this->functionID_ = *(uint32_t*)mem;
+  this->nrOfArguments_ = *(uint32_t*)(mem+sizeof(uint32_t));
+  this->objectID_ = *(uint32_t*)(mem+2*sizeof(uint32_t));
+  mem += 3*sizeof(uint32_t);
+  for( unsigned int i=0; i<this->nrOfArguments_; ++i )
+  {
+    this->arguments_.emplace_back();
+    this->arguments_.back().importData(mem);
+  }
+}
+
+void FunctionCall::saveData(uint8_t*& mem)
+{
+  // now serialise the mt values and copy the function id and isStatic
+  *(uint32_t*)mem = this->functionID_;
+  *(uint32_t*)(mem+sizeof(uint32_t)) = this->nrOfArguments_;
+  *(uint32_t*)(mem+2*sizeof(uint32_t)) = this->objectID_;
+  mem += 3*sizeof(uint32_t);
+  for(const MultiType& argument : this->arguments_)
+  {
+    argument.exportData( mem );
+  }
+}
+
+
+
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/FunctionCall.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/FunctionCall.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/FunctionCall.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FunctionCall_H__
+#define _FunctionCall_H__
+
+#include "network/NetworkPrereqs.h"
+#include "util/UtilPrereqs.h"
+#include "util/MultiType.h"
+
+#include <cassert>
+#include <vector>
+
+namespace orxonox {
+/**
+    @author
+*/
+
+
+class _NetworkExport FunctionCall
+{
+public:
+  FunctionCall();
+  ~FunctionCall();
+
+  inline unsigned int getSize() const { return this->size_; }
+  bool execute();
+
+  void setCall( uint32_t networkID, uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5);
+  
+  void saveData( uint8_t*& mem );
+  void loadData( uint8_t*& mem );
+private:
+  uint32_t                  nrOfArguments_;
+  uint32_t                  functionID_;
+  uint32_t                  objectID_; // equals OBJECTID_UNKNOWN for static functions
+  uint32_t                  size_;
+  std::vector<MultiType>    arguments_;
+};
+
+} //namespace orxonox
+
+#endif /* _FunctionCalls_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/FunctionCallManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/FunctionCallManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/FunctionCallManager.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FunctionCallManager.h"
+#include "packet/FunctionCalls.h"
+#include "core/GameMode.h"
+#include "GamestateHandler.h"
+#include "Host.h"
+#include "util/OrxAssert.h"
+
+namespace orxonox {
+
+std::map<uint32_t, packet::FunctionCalls*> FunctionCallManager::sPeerMap_;
+std::vector<std::pair<FunctionCall, std::pair<uint32_t, uint32_t>>> FunctionCallManager::sIncomingFunctionCallBuffer_;
+
+
+void FunctionCallManager::addCall(uint32_t functionID, uint32_t objectID, uint32_t peerID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5)
+{
+  if(sPeerMap_.find(peerID)==sPeerMap_.end())
+  {
+    FunctionCallManager::sPeerMap_[peerID] = new packet::FunctionCalls;
+    FunctionCallManager::sPeerMap_[peerID]->setPeerID(peerID);
+  }
+  FunctionCallManager::sPeerMap_[peerID]->addCall(functionID, objectID, mt1, mt2, mt3, mt4, mt5);
+}
+
+// Send calls
+
+void FunctionCallManager::sendCalls(orxonox::Host* host)
+{
+  for (const auto& mapEntry : FunctionCallManager::sPeerMap_ )
+  {
+    assert(!FunctionCallManager::sPeerMap_.empty());
+    mapEntry.second->send(host);
+  }
+  FunctionCallManager::sPeerMap_.clear();
+}
+
+void FunctionCallManager::bufferIncomingFunctionCall(const orxonox::FunctionCall& fctCall, uint32_t minGamestateID, uint32_t peerID)
+{
+  FunctionCallManager::sIncomingFunctionCallBuffer_.emplace_back(fctCall, std::make_pair(minGamestateID, peerID));
+}
+
+void FunctionCallManager::processBufferedFunctionCalls()
+{
+  std::vector<std::pair<FunctionCall, std::pair<uint32_t, uint32_t>>>::iterator it = FunctionCallManager::sIncomingFunctionCallBuffer_.begin();
+  while( it!=FunctionCallManager::sIncomingFunctionCallBuffer_.end() )
+  {
+    OrxAssert( Host::getActiveInstance(), "No Host class existing" );
+    if( it->second.first <= Host::getActiveInstance()->getLastReceivedGamestateID(it->second.second) && it->first.execute() )
+      FunctionCallManager::sIncomingFunctionCallBuffer_.erase(it++);
+    else
+    {
+      ++it;
+    }
+  }
+}
+
+
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/FunctionCallManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/FunctionCallManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/FunctionCallManager.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FunctionCallManager_H__
+#define _FunctionCallManager_H__
+
+#include "NetworkPrereqs.h"
+
+#include <map>
+#include <vector>
+#include <utility>
+#include "util/UtilPrereqs.h"
+#include "FunctionCall.h"
+
+namespace orxonox {
+/**
+    @author
+*/
+
+class _NetworkExport FunctionCallManager
+{
+public:
+  static void addCall(uint32_t functionID, uint32_t objectID, uint32_t peerID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5);
+
+  static void sendCalls(orxonox::Host* host);
+  
+  static void bufferIncomingFunctionCall( const FunctionCall& fctCall, uint32_t minGamestateID, uint32_t peerID );
+  static void processBufferedFunctionCalls();
+
+  static std::map<uint32_t, packet::FunctionCalls*>                           sPeerMap_;
+  static std::vector<std::pair<FunctionCall,std::pair<uint32_t, uint32_t>>> sIncomingFunctionCallBuffer_;
+protected:
+  FunctionCallManager();
+  ~FunctionCallManager();
+};
+
+} //namespace orxonox
+
+#endif /* _FunctionCallManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/GamestateHandler.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/GamestateHandler.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/GamestateHandler.cc	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GamestateHandler.h"
+#include <cassert>
+
+namespace orxonox {
+
+// GamestateHandler *GamestateHandler::instance_=nullptr;
+
+GamestateHandler::GamestateHandler()
+{
+}
+
+
+GamestateHandler::~GamestateHandler()
+{
+}
+
+
+
+}//namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/GamestateHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/GamestateHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/GamestateHandler.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GamestateHandler_H__
+#define _GamestateHandler_H__
+
+#include "NetworkPrereqs.h"
+
+#include <cassert>
+
+namespace orxonox {
+
+/**
+    @author Oliver Scheuss
+*/
+class _NetworkExport GamestateHandler
+{
+  private:
+
+
+  protected:
+    GamestateHandler();
+    virtual ~GamestateHandler();
+
+  public:
+    virtual bool      addGamestate(packet::Gamestate* gs, unsigned int clientID) = 0;
+    virtual bool      ackGamestate(unsigned int gamestateID, unsigned int clientID) = 0;
+    virtual uint32_t  getLastReceivedGamestateID( unsigned int clientID )=0;
+    virtual uint32_t  getCurrentGamestateID()=0;
+};
+
+}
+
+#endif /* _GamestateHandler_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/GamestateManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/GamestateManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/GamestateManager.cc	(revision 11817)
@@ -0,0 +1,378 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Implementation: GameStateManager
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "GamestateManager.h"
+
+#include <cassert>
+#include <queue>
+// #include <boost/thread/mutex.hpp>
+
+#include "packet/Acknowledgement.h"
+#include "packet/Gamestate.h"
+#include "synchronisable/NetworkCallbackManager.h"
+
+#include "core/ThreadPool.h"
+#include "core/command/Executor.h"
+#include "core/GameMode.h"
+#include "util/Output.h"
+#include "util/Clock.h"
+#include "util/OrxAssert.h"
+// #include "TrafficControl.h"
+
+namespace orxonox
+{ 
+  GamestateManager::GamestateManager() :
+  currentGamestate_(nullptr), id_(0)
+  {
+//     trafficControl_ = new TrafficControl();
+//     threadMutex_ = new boost::mutex();
+//     threadPool_ = new ThreadPool();
+  }
+
+  GamestateManager::~GamestateManager()
+  {
+    if( this->currentGamestate_ )
+        delete this->currentGamestate_;
+    for( const auto& mapEntry : gamestateQueue )
+      delete mapEntry.second;
+    for( const auto& mapEntryPeer : peerMap_ )
+    {
+      for( const auto& mapEntryGamestate : mapEntryPeer.second.gamestates )
+        delete mapEntryGamestate.second;
+    }
+//     this->trafficControl_->destroy();
+//     delete this->threadMutex_;
+//     delete this->threadPool_;
+  }
+
+  bool GamestateManager::update(){
+//     cleanup();
+    return getSnapshot();
+  }
+
+  bool GamestateManager::addGamestate(packet::Gamestate *gs, unsigned int clientID)
+  {
+    assert(gs);
+    std::map<unsigned int, packet::Gamestate*>::iterator it = gamestateQueue.find(clientID);
+    if(it!=gamestateQueue.end())
+    {
+      // delete obsolete gamestate
+      delete it->second;
+    }
+    gamestateQueue[clientID] = gs;
+    return true;
+  }
+
+  bool GamestateManager::processGamestates()
+  {
+    if( this->gamestateQueue.empty() )
+        return true;
+    // now push only the most recent gamestates we received (ignore obsolete ones)
+    for(const auto& mapEntry : gamestateQueue)
+    {
+      OrxVerify(processGamestate(mapEntry.second), "ERROR: could not process Gamestate");
+      sendAck( mapEntry.second->getID(), mapEntry.second->getPeerID() );
+      delete mapEntry.second;
+    }
+    // now clear the queue
+    gamestateQueue.clear();
+    //and call all queued callbacks
+    NetworkCallbackManager::callCallbacks();
+    return true;
+  }
+  
+  bool GamestateManager::sendAck(unsigned int gamestateID, uint32_t peerID)
+  {
+    assert( gamestateID != ACKID_NACK );
+    packet::Acknowledgement *ack = new packet::Acknowledgement(gamestateID, peerID);
+    if( !this->sendPacket(ack))
+    {
+      orxout(internal_warning, context::network) << "could not ack gamestate: " << gamestateID << endl;
+      return false;
+    }
+    else
+    {
+      orxout(verbose_more, context::network) << "acked a gamestate: " << gamestateID << endl;
+      return true;
+    }
+  }
+
+
+  bool GamestateManager::getSnapshot(){
+    if ( currentGamestate_ != nullptr )
+      delete currentGamestate_;
+    uint8_t gsMode;
+    if( GameMode::isMaster() )
+      gsMode = packet::GAMESTATE_MODE_SERVER;
+    else
+      gsMode = packet::GAMESTATE_MODE_CLIENT;
+    uint32_t newID;
+    if( GameMode::isMaster() )
+      newID = ++id_;
+    else
+    {
+      assert(peerMap_.size()!=0);
+      newID = peerMap_[NETWORK_PEER_ID_SERVER].lastReceivedGamestateID;
+      if( newID == GAMESTATEID_INITIAL )
+      {
+        return false;
+      }
+    }
+    
+    currentGamestate_ = new packet::Gamestate();
+    
+    if(!currentGamestate_->collectData(newID, gsMode))
+    { //we have no data to send
+      delete currentGamestate_;
+      currentGamestate_=nullptr;
+      return false;
+    }
+    return true;
+  }
+
+  std::vector<packet::Gamestate*> GamestateManager::getGamestates()
+  {
+    if(!currentGamestate_)
+      return std::vector<packet::Gamestate*>();
+    std::vector<packet::Gamestate*> peerGamestates;
+    
+    for( const auto& mapEntry : peerMap_ )
+    {
+      if( !mapEntry.second.isSynched )
+      {
+        orxout(verbose_more, context::network) << "Server: not sending gamestate" << endl;
+        continue;
+      }
+      orxout(verbose_more, context::network) << "client id: " << mapEntry.first << endl;
+      orxout(verbose_more, context::network) << "Server: doing gamestate gamestate preparation" << endl;
+      int peerID = mapEntry.first; //get client id
+
+      unsigned int lastAckedGamestateID = mapEntry.second.lastAckedGamestateID;
+
+      packet::Gamestate* baseGamestate=nullptr;
+      if(lastAckedGamestateID != GAMESTATEID_INITIAL)
+      {
+        assert(peerMap_.find(peerID)!=peerMap_.end());
+        std::map<uint32_t, packet::Gamestate*>::iterator it = peerMap_[peerID].gamestates.find(lastAckedGamestateID);
+        assert(it!=peerMap_[peerID].gamestates.end());
+        baseGamestate = it->second;
+      }
+
+      peerGamestates.push_back(nullptr);  // insert an empty gamestate* to be changed
+      finishGamestate( peerID, peerGamestates.back(), baseGamestate, currentGamestate_ );
+      if( peerGamestates.back()==nullptr )
+        // nothing to send to remove pointer from vector
+        peerGamestates.pop_back();
+      //FunctorMember<GamestateManager>* functor =
+//       ExecutorMember<GamestateManager>* executor = createExecutor( createFunctor(&GamestateManager::finishGamestate, this) );
+//       executor->setDefaultValues( cid, &clientGamestates.back(), client, currentGamestate_ );
+//       (*static_cast<Executor*>(executor))();
+//       this->threadPool_->passFunction( executor, true );
+//       (*functor)( cid, &(clientGamestates.back()), client, currentGamestate_ );
+    }
+
+//     threadPool_->synchronise();
+
+    return peerGamestates;
+  }
+
+
+  void GamestateManager::finishGamestate( unsigned int peerID, packet::Gamestate*& destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate ) {
+    //why are we searching the same client's gamestate id as we searched in
+    //Server::sendGameState?
+    // save the (undiffed) gamestate in the clients gamestate map
+    //chose wheather the next gamestate is the first or not
+
+//     packet::Gamestate *gs = gamestate->doSelection(clientID, 20000);
+//       packet::Gamestate* gs = new packet::Gamestate(*gamestate);
+//     packet::Gamestate* gs = gamestate;
+    packet::Gamestate *gs = new packet::Gamestate(*gamestate); //this is neccessary because the gamestate are being kept (to diff them later on) for each client seperately
+//     packet::Gamestate *gs = new packet::Gamestate();
+//     gs->collectData( id_, 0x1 );
+//     this->threadMutex_->lock();
+    peerMap_[peerID].gamestates[gamestate->getID()]=gs;
+//     this->threadMutex_->unlock();
+    Clock clock;
+    clock.capture();
+
+    if(base)
+    {
+      packet::Gamestate *diffed1 = gs->diffVariables(base);
+      if( diffed1->getDataSize() == 0 )
+      {
+        delete diffed1;
+        destgamestate = nullptr;
+        return;
+      }
+      gs = diffed1;
+    }
+    else
+    {
+      gs = new packet::Gamestate(*gs);
+    }
+
+
+//     OrxVerify(gs->compressData(), "");
+    clock.capture();
+    orxout(verbose_more, context::network) << "diff and compress time: " << clock.getDeltaTime() << endl;
+//     orxout(verbose_more, context::network) << "sending gamestate with id " << gs->getID();
+//     if(gamestate->isDiffed())
+//       orxout(verbose_more, context::network) << " and baseid " << gs->getBaseID() << endl;
+//     else
+//       orxout(verbose_more, context::network) << endl;
+    gs->setPeerID(peerID);
+    destgamestate = gs;
+  }
+
+
+  bool GamestateManager::ackGamestate(unsigned int gamestateID, unsigned int peerID)
+  {
+//     ClientInformation *temp = ClientInformation::findClient(peerID);
+//     assert(temp);
+    std::map<uint32_t, peerInfo>::iterator it = this->peerMap_.find(peerID);
+    assert(it!=this->peerMap_.end());
+    unsigned int curid = it->second.lastAckedGamestateID;
+
+    assert(gamestateID != ACKID_NACK);
+//     if(gamestateID == ACKID_NACK){
+//       it->second.lastAckedGamestateID = GAMESTATEID_INITIAL;
+// //       temp->setGamestateID(GAMESTATEID_INITIAL);
+//       // now delete all saved gamestates for this client
+//       std::map<uint32_t, packet::Gamestate*>::iterator it2;
+//       for(it2 = it->second.gamestates.begin(); it2!=it->second.gamestates.end(); ++it2 ){
+//         delete it2->second;
+//       }
+//       it->second.gamestates.clear();
+//       return true;
+//     }
+
+//    assert(curid==GAMESTATEID_INITIAL || curid<=gamestateID); // this line is commented out because acknowledgements are unreliable and may arrive in distorted order
+    if( gamestateID <= curid && curid != GAMESTATEID_INITIAL )
+        return true;
+orxout(verbose, context::network) << "acking gamestate " << gamestateID << " for peerID: " << peerID << " curid: " << curid << endl;
+    std::map<uint32_t, packet::Gamestate*>::iterator it2;
+    for( it2=it->second.gamestates.begin(); it2!=it->second.gamestates.end(); )
+    {
+      if( it2->second->getID() < gamestateID )
+      {
+        delete it2->second;
+        it->second.gamestates.erase(it2++);
+      }
+      else
+        ++it2;
+    }
+    
+//     std::map<unsigned int, packet::Gamestate*>::iterator it;
+//     for(it = gamestateMap_[peerID].begin(); it!=gamestateMap_[peerID].end() && it->first<gamestateID; ){
+//       delete it->second;
+//       gamestateMap_[peerID].erase(it++);
+//     }
+    it->second.lastAckedGamestateID = gamestateID;
+//     temp->setGamestateID(gamestateID);
+//     TrafficControl::processAck(peerID, gamestateID);
+    return true;
+  }
+  
+  uint32_t GamestateManager::getLastReceivedGamestateID(unsigned int peerID)
+  {
+    assert( this->peerMap_.find(peerID)!=this->peerMap_.end() );
+    if( this->peerMap_.find(peerID) != this->peerMap_.end() )
+      return this->peerMap_[peerID].lastReceivedGamestateID;
+    else
+      return GAMESTATEID_INITIAL;
+  }
+  
+  
+  void GamestateManager::addPeer(uint32_t peerID)
+  {
+    assert(peerMap_.find(peerID)==peerMap_.end());
+    peerMap_[peerID].peerID = peerID;
+    peerMap_[peerID].lastReceivedGamestateID = GAMESTATEID_INITIAL;
+    peerMap_[peerID].lastAckedGamestateID = GAMESTATEID_INITIAL;
+    if( GameMode::isMaster() )
+      peerMap_[peerID].isSynched = false;
+    else
+      peerMap_[peerID].isSynched = true;
+  }
+
+  void GamestateManager::removePeer(uint32_t peerID)
+  {
+    assert(peerMap_.find(peerID)!=peerMap_.end());
+    for( const auto& mapEntry : peerMap_[peerID].gamestates )
+    {
+      delete mapEntry.second;
+    }
+    peerMap_.erase(peerMap_.find(peerID));
+  }
+
+
+//   void GamestateManager::removeClient(ClientInformation* client){
+//     assert(client);
+//     std::map<unsigned int, std::map<unsigned int, packet::Gamestate*>>::iterator clientMap = gamestateMap_.find(client->getID());
+//     // first delete all remained gamestates
+//     std::map<unsigned int, packet::Gamestate*>::iterator it;
+//     for(it=clientMap->second.begin(); it!=clientMap->second.end(); it++)
+//       delete it->second;
+//     // now delete the clients gamestatemap
+//     gamestateMap_.erase(clientMap);
+//   }
+
+  bool GamestateManager::processGamestate(packet::Gamestate *gs)
+  {
+    if(gs->isCompressed())
+    {
+       OrxVerify(gs->decompressData(), "ERROR: could not decompress Gamestate");
+    }
+    assert(!gs->isDiffed());
+    uint8_t gsMode;
+    if( GameMode::isMaster() )
+      gsMode = packet::GAMESTATE_MODE_SERVER;
+    else
+      gsMode = packet::GAMESTATE_MODE_CLIENT;
+    if( gs->spreadData(gsMode) )
+    {
+      this->peerMap_[gs->getPeerID()].lastReceivedGamestateID = gs->getID();
+      return true;
+    }
+    else
+      return false;
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/GamestateManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/GamestateManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/GamestateManager.h	(revision 11817)
@@ -0,0 +1,122 @@
+  /*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Interface: GamestateManager
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef _GamestateManager_H__
+#define _GamestateManager_H__
+
+#include "NetworkPrereqs.h"
+
+#include <map>
+#include "GamestateHandler.h"
+#include "core/CorePrereqs.h"
+#include "packet/Gamestate.h"
+
+namespace orxonox
+{
+
+  const int KEEP_GAMESTATES = 10;
+
+  /**
+  * This Class implements a manager for gamestates:
+  * - creating snapshots of gamestates
+  * - writing gamestates to universe
+  * - diffing gamestates
+  * EN/DECODATION:
+  * a: last Gamestate a client has received
+  * b: new Gamestate
+  * x: diffed and compressed gamestate
+  * x=(a^b)
+  * b=(a^x)
+  * diff(a,diff(a,x))=x (hope this is correct)
+  * @author Oliver Scheuss
+  */
+  class _NetworkExport GamestateManager: public GamestateHandler
+  {
+    struct peerInfo
+    {
+      uint32_t  peerID;
+      uint32_t  lastReceivedGamestateID;  //!< id of the last gamestate which was received (and processed) from the peer
+      uint32_t  lastAckedGamestateID;     //!< id of the last gamestate on which we received an ack from the peer
+      bool      isSynched;
+      std::map< uint32_t, packet::Gamestate* > gamestates;
+    };
+
+  public:
+
+    GamestateManager();
+    ~GamestateManager();
+
+    virtual bool      addGamestate(packet::Gamestate *gs, unsigned int peerID) override;
+    virtual bool      ackGamestate(unsigned int gamestateID, unsigned int peerID) override;
+    virtual uint32_t  getLastReceivedGamestateID( unsigned int peerID ) override;
+    virtual uint32_t  getCurrentGamestateID() override{ if( currentGamestate_) return currentGamestate_->getID(); else return GAMESTATEID_INITIAL; }
+
+    bool processGamestates();
+    bool sendAck(unsigned int gamestateID, uint32_t peerID);
+    bool update();
+    std::vector<packet::Gamestate*> getGamestates();
+    void finishGamestate( unsigned int peerID, packet::Gamestate*& destgamestate, packet::Gamestate* base, packet::Gamestate* gamestate );
+
+    bool getSnapshot();
+
+    void addPeer( uint32_t peerID );
+    void setSynched( uint32_t peerID )
+      { assert(peerMap_.find(peerID)!=peerMap_.end()); peerMap_[peerID].isSynched = true; }
+    void removePeer( uint32_t peerID );
+    bool hasPeers(){ return this->peerMap_.size()!=0; }
+//     void removeClient(ClientInformation *client);
+  protected:
+    virtual bool sendPacket( packet::Packet* packet ) = 0;
+  private:
+    bool processGamestate(packet::Gamestate *gs);
+
+//     std::map<unsigned int, std::map<unsigned int, packet::Gamestate*>> gamestateMap_;
+    std::map<unsigned int, packet::Gamestate*> gamestateQueue;
+//     std::map<unsigned int, uint32_t> lastProcessedGamestateID_;
+    std::map<uint32_t, peerInfo> peerMap_;
+    packet::Gamestate* currentGamestate_;
+//     TrafficControl *trafficControl_;
+    unsigned int id_;
+//     boost::mutex* threadMutex_;
+    ThreadPool*   /*thread*/Pool_;
+  };
+
+}
+
+#endif /* _GameStateManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/Host.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Host.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Host.cc	(revision 11817)
@@ -0,0 +1,152 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Host.h"
+
+#include <cassert>
+#include <string>
+
+#include "core/CoreIncludes.h"
+#include "core/object/ObjectList.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "NetworkChatListener.h"
+
+namespace orxonox {
+
+  static const std::string __CC_printRTT_group = "Stats";
+  static const std::string __CC_printRTT_name = "printRTT";
+
+  SetConsoleCommand(__CC_printRTT_group, __CC_printRTT_name, &Host::printRTT);
+
+  // Host*               Host::instance_=nullptr;
+  uint32_t            Host::clientID_s=0;
+//   uint32_t            Host::shipID_s=-1;
+  std::vector<Host*>  Host::instances_s;
+
+  /**
+  * @brief Constructor: assures that only one reference will be created and sets the pointer
+  */
+  Host::Host()
+  {
+  //   assert(instance_==nullptr);
+    instances_s.push_back(this);
+    ModifyConsoleCommand(__CC_printRTT_group, __CC_printRTT_name).setObject(this);
+    this->bIsActive_ = false;
+  }
+
+
+  /**
+  * @brief Destructor: resets the instance pointer to nullptr
+  */
+  Host::~Host()
+  {
+    assert( std::find( instances_s.begin(), instances_s.end(), this )!=instances_s.end() );
+    instances_s.erase(std::find( instances_s.begin(), instances_s.end(), this ));
+    ModifyConsoleCommand(__CC_printRTT_group, __CC_printRTT_name).setObject(nullptr);
+  }
+
+  /**
+  * This function is used to add an enetpacket to be sent to another peer
+  * @param packet Packet to be added
+  * @param clientID ID of the client the packet should be sent to
+  * @param channelID ID of the channel.
+  * @return success?
+  */
+  void Host::addPacket(ENetPacket *packet, int clientID, uint8_t channelID)
+  {
+    for(Host* host : instances_s)
+    {
+      if( host->isActive() )
+      {
+        host->queuePacket(packet, clientID, channelID);
+      }
+    }
+  }
+
+  /**
+   * @brief Sends a chat message through the network.
+   * @param message message to be sent
+   * @param sourceID the ID of the sender
+   * @param targetID the ID of the receiver
+   */
+  void Host::sendChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
+  {
+    for(Host* host : instances_s)
+      if( host->isActive() )
+        host->doSendChat(message, sourceID, targetID);
+  }
+
+  /**
+   * @brief Gets called if a packet::Chat packet is received. Passes the message to the listeners.
+   */
+  void Host::doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
+  {
+    for (NetworkChatListener* listener : ObjectList<NetworkChatListener>())
+      listener->incomingChat(message, sourceID);
+  }
+
+
+  bool Host::isServer()
+  {
+    for (Host* host : instances_s)
+    {
+      if( host->isActive() )
+      {
+        if( host->isServer_() )
+          return true;
+      }
+    }
+    return false;
+  }
+
+  Host* Host::getActiveInstance()
+  {
+    std::vector<Host*>::iterator it = Host::instances_s.begin();
+    while( it != Host::instances_s.end() )
+    {
+      if( (*it)->isActive() )
+        return *it;
+      else
+        ++it;
+    }
+    return nullptr;
+  }
+
+
+  //////////////////////////////////////////////////////////////////////////
+  // NetworkChatListener                                                  //
+  //////////////////////////////////////////////////////////////////////////
+
+  RegisterAbstractClass(NetworkChatListener).inheritsFrom<Listable>();
+
+  NetworkChatListener::NetworkChatListener()
+  {
+      RegisterObject(NetworkChatListener);
+  }
+
+}//namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/Host.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Host.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Host.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NETWORK_Host_H__
+#define _NETWORK_Host_H__
+
+#include "NetworkPrereqs.h"
+#include "GamestateManager.h"
+#include "core/CorePrereqs.h"
+
+#include <vector>
+
+namespace orxonox {
+
+  const unsigned int CLIENTID_SERVER = 0;
+  const unsigned int NETWORK_FREQUENCY = 25;
+  const float NETWORK_PERIOD = 1.0f/NETWORK_FREQUENCY;
+
+/**
+*       @brief Base class of Server and Client
+*       This is the Base class of the Server and Client classes
+*       - Makes server and client a singleton
+*       - defines static functions available on both server and client
+*       - is the interface to be used when communicating with the network
+*       @author Oliver Scheuss
+*/
+class _NetworkExport Host: public GamestateManager
+{
+  friend class packet::Chat;
+
+  private:
+    virtual void queuePacket(ENetPacket *packet, int clientID, uint8_t channelID)=0;
+    virtual bool isServer_()=0;
+
+  protected:
+    Host();
+    virtual ~Host();
+    void setActive( bool bActive ){ bIsActive_ = bActive; }
+
+    virtual void doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID)=0;
+    virtual void doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID)=0;
+
+  public:
+    static Host* getActiveInstance();
+    static bool running(){ return instances_s.size(); }
+    static void addPacket(ENetPacket* packet, int clientID = NETWORK_PEER_ID_SERVER, uint8_t channelID = 0);
+    static unsigned int getPlayerID(){ return clientID_s; }
+    static void setClientID(unsigned int id){ clientID_s = id; }
+    static bool isServer();
+    static void sendChat(const std::string& message, unsigned int sourceID, unsigned int targetID);
+    virtual void printRTT()=0;
+    bool isActive(){ return bIsActive_; }
+  private:
+    static uint32_t clientID_s;
+    static std::vector<Host*> instances_s;
+    bool bIsActive_;
+};
+
+}
+
+#endif /* _NETWORK_Host_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/LANDiscoverable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/LANDiscoverable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/LANDiscoverable.cc	(revision 11817)
@@ -0,0 +1,132 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LANDiscoverable.h"
+
+#include <enet/enet.h>
+#include <cassert>
+#include <cstring>
+
+#include "util/Output.h"
+#include "packet/ServerInformation.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+
+
+namespace orxonox
+{
+  const char* LAN_DISCOVERY_MESSAGE = "Orxonox Client";
+  const char* LAN_DISCOVERY_ACK     = "Orxonox Server Ack";
+
+  RegisterClassNoArgs(LANDiscoverable);
+
+  LANDiscoverable::LANDiscoverable() : bActive_(false), host_(nullptr)
+  {
+    /* register object in orxonox */
+    RegisterObject(LANDiscoverable);
+
+    this->setConfigValues();
+  }
+
+  void LANDiscoverable::setConfigValues()
+  {
+    /* update ownName string from orxonox.ini config file, if it
+     * has changed.
+     */
+    SetConfigValueExternal(ownName, "Discovery", "ownName", "OrxServer");
+  }
+
+  LANDiscoverable::~LANDiscoverable()
+  {
+    if( this->host_ )
+    {
+      enet_host_destroy( this->host_ );
+      assert( this->bActive_ );
+    }
+  }
+
+  void LANDiscoverable::setActivity(bool bActive)
+  {
+    if( bActive == this->bActive_ )        // no change
+      return;
+
+    if( bActive )
+    {
+      ENetAddress bindAddress;
+      memset(& bindAddress, 0, sizeof(ENetAddress));
+      bindAddress.host = ENET_HOST_ANY;
+      bindAddress.port = LAN_DISCOVERY_PORT;
+      assert( this->host_ == nullptr );
+      this->host_ = enet_host_create( &bindAddress, 10, 0, 0, 0 );
+      if ( this->host_ == nullptr )
+          orxout(internal_error, context::network) << "LANDiscoverable: host_ == nullptr" << endl;
+    }
+    else
+    {
+      enet_host_destroy( this->host_ );
+      this->host_ = nullptr;
+    }
+      this->bActive_ = bActive;
+  }
+
+  void LANDiscoverable::update()
+  {
+    ENetEvent event;
+
+    if( this->bActive_==false )
+      return;
+    assert(this->host_);
+
+    while( enet_host_service( this->host_, &event, 0 ) > 0 )
+    {
+      switch(event.type)
+      {
+        case ENET_EVENT_TYPE_CONNECT:
+            orxout(verbose, context::network) << "Received LAN discovery connect from client " << event.peer->host->receivedAddress << endl;
+            break;
+        case ENET_EVENT_TYPE_DISCONNECT:
+        case ENET_EVENT_TYPE_NONE:
+          break;
+        case ENET_EVENT_TYPE_RECEIVE:
+          if( strcmp( LAN_DISCOVERY_MESSAGE, (char*)event.packet->data ) == 0 )      // check for a suitable orxonox client
+          {
+            orxout(internal_info, context::network) << "Received LAN discovery message from client " << event.peer->host->receivedAddress << endl;
+            packet::ServerInformation info;
+            info.setServerName(this->ownName);
+            info.setClientNumber(this->clientNumber);
+            info.send(event.peer);
+//             ENetPacket* packet = enet_packet_create( LAN_DISCOVERY_ACK, strlen(LAN_DISCOVERY_ACK)+1, ENET_PACKET_FLAG_RELIABLE );
+//             enet_peer_send(event.peer, 0, packet );
+            enet_host_flush(this->host_);
+          }
+          break;
+      }
+    }
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/LANDiscoverable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/LANDiscoverable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/LANDiscoverable.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _LANDISCOVERABLE_H__
+#define _LANDISCOVERABLE_H__
+
+#include "NetworkPrereqs.h"
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+
+  class LANDiscoverable: public Configurable
+  {
+    public:
+      LANDiscoverable();
+      virtual ~LANDiscoverable();
+      void setActivity( bool bActive );
+      void update();
+      void updateClientNumber(int clientNumber) {this->clientNumber = clientNumber;}
+;
+      /** Function used for the configuration file parameter update */
+      void setConfigValues();
+
+    private:
+      bool            bActive_;
+      ENetHost*       host_;
+      std::string     ownName;
+      int             clientNumber;
+  };
+
+}
+
+#endif // LANDISCOVERABLE_H
Index: /code/branches/RacingBots_FS18/src/libraries/network/LANDiscovery.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/LANDiscovery.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/LANDiscovery.cc	(revision 11817)
@@ -0,0 +1,148 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LANDiscovery.h"
+
+#include <enet/enet.h>
+#include <cstring>
+
+#include "core/CoreIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+
+namespace orxonox
+{
+  ManageScopedSingleton(LANDiscovery, ScopeID::GRAPHICS, false);
+
+  LANDiscovery::LANDiscovery()
+  {
+    this->host_ = enet_host_create(nullptr, 10, 0, 0, 0 );
+    if ( this->host_ == nullptr )
+        orxout(internal_error, context::network) << "LANDiscovery: host_ == nullptr" << endl;
+  }
+
+  LANDiscovery::~LANDiscovery()
+  {
+    if (this->host_ != nullptr)
+      enet_host_destroy(this->host_);
+  }
+
+  void LANDiscovery::discover()
+  {
+    this->servers_.clear();
+    ENetPeer* peer;
+    ENetAddress address;
+    memset(&address, 0, sizeof(ENetAddress));
+    address.port = LAN_DISCOVERY_PORT;
+
+    /* TODO: check for availability of each protocol */
+    /* IPv4 */
+    address.host = ENET_HOST_BROADCAST;
+    peer = enet_host_connect(this->host_, &address, 0, 0);
+    if (peer == nullptr)
+        orxout(internal_error, context::network) << "Could not send LAN discovery to IPv4 Broadcast." << endl;
+
+    /* IPv6 */
+    enet_address_set_host(&address, "ff02::1"); // TODO: use a multicast group
+    peer = enet_host_connect(this->host_, &address, 0, 0);
+    if (peer == nullptr)
+        orxout(internal_error, context::network) << "Could not send LAN discovery to IPv6 Multicast." << endl;
+
+    ENetEvent event;
+    while( enet_host_service(this->host_, &event, 1000 ) )
+    {
+      switch( event.type )
+      {
+        case ENET_EVENT_TYPE_CONNECT:
+        {
+          orxout(verbose, context::network) << "Received LAN discovery connect from server " << event.peer->host->receivedAddress << endl;
+          ENetPacket* packet = enet_packet_create(LAN_DISCOVERY_MESSAGE, strlen(LAN_DISCOVERY_MESSAGE)+1, ENET_PACKET_FLAG_RELIABLE);
+          enet_peer_send(event.peer, 0, packet);
+          break;
+        }
+        case ENET_EVENT_TYPE_RECEIVE:
+          {
+            packet::ServerInformation info(&event);
+            std::string payload = info.getServerName();
+            info.setServerName(payload.substr(0,payload.length()-2));
+            info.setClientNumber( Ogre::StringConverter::parseInt(payload.substr(payload.length()-1)));
+            orxout(internal_info, context::network) << "Received LAN discovery server information; Name: " << info.getServerName() << ", Address: " << info.getServerIP() << ", Players: " << info.getClientNumber() << ", RTT: " << info.getServerRTT() << endl;
+            std::vector<packet::ServerInformation>::iterator it;
+            for( it=this->servers_.begin(); it!=this->servers_.end(); ++it )
+            {
+              if( (*it).getServerIP() == info.getServerIP() )
+                break;
+            }
+            if( it==this->servers_.end() )
+              this->servers_.push_back(info);
+          }
+//           enet_address_get_host_ip(&event.peer->address, buffer, buflen );
+//           serverIPs.push_back(std::string(buffer));
+          break;
+        default:
+          break;
+      }
+    }
+  }
+
+  std::string LANDiscovery::getServerListItemName(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else
+      return this->servers_[index].getServerName();
+  }
+
+  std::string LANDiscovery::getServerListItemIP(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else
+      return this->servers_[index].getServerIP();
+  }
+
+  std::string LANDiscovery::getServerListItemRTT(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else{
+      uint32_t serverrtt = this->servers_[index].getServerRTT();
+      return Ogre::StringConverter::toString(serverrtt);
+    }
+  }
+
+  std::string LANDiscovery::getServerListItemPlayerNumber(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else{
+      int playerNumber = this->servers_[index].getClientNumber();
+      return Ogre::StringConverter::toString(playerNumber);
+    }
+  }
+} // namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/LANDiscovery.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/LANDiscovery.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/LANDiscovery.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef LANDISCOVERY_H
+#define LANDISCOVERY_H
+
+#include "NetworkPrereqs.h"
+#include "packet/ServerInformation.h"
+#include "util/Singleton.h"
+#include <OgreStringConverter.h>
+
+#include <vector>
+
+// tolua_begin
+namespace orxonox
+{
+
+  class _NetworkExport LANDiscovery
+// tolua_end
+    : public Singleton<LANDiscovery>
+  { // tolua_export
+    friend class Singleton<LANDiscovery>;
+    public:
+      LANDiscovery();
+      ~LANDiscovery();
+      void discover(); // tolua_export
+      std::string getServerListItemName( unsigned int index ); // tolua_export
+      std::string getServerListItemIP( unsigned int index ); // tolua_export
+      std::string getServerListItemRTT( unsigned int index ); // tolua_export
+      std::string getServerListItemPlayerNumber( unsigned int index ); // tolua_export
+      static LANDiscovery& getInstance(){ return Singleton<LANDiscovery>::getInstance(); } // tolua_export
+
+    private:
+      static LANDiscovery* singletonPtr_s;
+      ENetHost* host_;
+      std::vector<packet::ServerInformation> servers_;
+  }; // tolua_export
+
+} // tolua_export
+
+#endif // LANDISCOVERY_H
Index: /code/branches/RacingBots_FS18/src/libraries/network/MasterServer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/MasterServer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/MasterServer.cc	(revision 11817)
@@ -0,0 +1,420 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MasterServer.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/CorePrereqs.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "util/Output.h"
+
+namespace orxonox
+{
+  /*** MACROS ***/
+  /* commands for the terminal interface */
+  SetConsoleCommand( "ms-listservers", &MasterServer::listServers );
+  SetConsoleCommand( "ms-delserver", &MasterServer::delServer );
+  //SetConsoleCommand( "ms-serverinfo", &MasterServer::serverInfo );
+
+  /* forward declaration so the linker doesn't complain */
+  MasterServer *MasterServer::instance = nullptr;
+
+  /* command: list servers */
+  void
+  MasterServer::listServers( void )
+  {
+    /* print list header */
+    orxout(user_info) << "List of connected servers" << std::endl;
+
+    /* loop through list elements */
+    for( const ServerListElem& elem : MasterServer::getInstance()->mainlist.serverlist )
+    {
+      orxout(user_info) << "  " << elem.ServerInfo.getServerIP() << std::endl;
+    }
+
+    /* display end of list */
+    orxout(user_info) << MasterServer::getInstance()->mainlist.serverlist.size() <<
+      " servers connected." << std::endl;
+  }
+
+  void
+  MasterServer::delServer( std::string todeladdr )
+  {
+    /* tell the user we're now removing the entry from the server list */
+    orxout(user_info) << "MS: Deleting server \"" << todeladdr << "\"..."
+      << std::endl;
+
+    /* see if we actually have that server on our list */
+    ServerListSearchResult shandle =
+      MasterServer::getInstance()->mainlist.findServerByAddress(todeladdr);
+
+    if( !shandle.success )
+    { orxout(user_info) << "MS: Server not found, not removing." << std::endl;
+      return;
+    }
+
+    /* force-disconnect the server */
+    enet_peer_disconnect( shandle.result.peer, 0 );
+
+    /* actually remove the entry from the server list by address */
+    MasterServer::getInstance()->mainlist.delServerByAddress( todeladdr);
+
+    /* tell the user about our success */
+    orxout(user_info) << "MS: Server deletion successful." << std::endl;
+  }
+
+
+  /* helpers */
+  static void
+  helper_output_debug( ENetEvent *event, char *addrconv )
+  {
+    orxout(verbose, context::master_server)
+      << "A packet of length"
+      << event->packet->dataLength
+      << " containing "
+      << (const char*)event->packet->data
+      << " was received from "
+      << addrconv
+      << " on channel "
+      << event->channelID << endl;
+  }
+
+  void
+  MasterServer::helper_sendlist( ENetEvent *event )
+  {
+    /* packet holder */
+    ENetPacket *reply;
+
+    /* loop through list elements */
+    for( const ServerListElem& elem : mainlist.serverlist )
+    {
+      /* send this particular server */
+      /* build reply string */
+      int packetlen = MSPROTO_SERVERLIST_ITEM_LEN + 1 + elem.ServerInfo.getServerIP().length() + 1 + elem.ServerInfo.getServerName().length() + 1 + sizeof(elem.ServerInfo.getClientNumber()) + 1;
+      char *tosend = (char *)calloc(packetlen ,1 );
+      if( !tosend )
+      { orxout(internal_warning, context::master_server) << "Masterserver.cc: Memory allocation failed." << endl;
+        continue;
+      }
+      sprintf( tosend, "%s %s %s %u", MSPROTO_SERVERLIST_ITEM,
+          elem.ServerInfo.getServerIP().c_str(), elem.ServerInfo.getServerName().c_str(), elem.ServerInfo.getClientNumber());
+
+      /* create packet from it */
+      reply = enet_packet_create( tosend,
+          strlen( tosend ) + 1,
+          ENET_PACKET_FLAG_RELIABLE);
+
+      /* Send the reply to the peer over channel id 0. */
+      enet_peer_send( event->peer, 0, reply );
+
+      /* One could just use enet_host_service() instead. */
+      enet_host_flush( this->server );
+
+      /* free the tosend buffer */
+      free( tosend );
+    }
+
+    /* create end-of-list packet */
+    reply = enet_packet_create( MSPROTO_SERVERLIST_END,
+        MSPROTO_SERVERLIST_END_LEN + 1,
+        ENET_PACKET_FLAG_RELIABLE );
+
+    /* send end-of-list packet */
+    enet_peer_send( event->peer, 0, reply );
+
+    /* One could just use enet_host_service() instead. */
+    enet_host_flush( this->server );
+  }
+
+  /* maybe the two methods below can be merged into one and
+   * made to use ENet's RTT functionality to check for disconnected
+   * servers.
+   */
+  void
+  MasterServer::helper_cleanupServers( void )
+  {
+    if( mainlist.serverlist.size() == 0 )
+      return;
+
+    /* loop through list elements */
+    for( const ServerListElem& elem : mainlist.serverlist )
+    { /* see if we have a disconnected peer */
+      if( elem.peer &&
+         (elem.peer->state == ENET_PEER_STATE_DISCONNECTED ||
+          elem.peer->state == ENET_PEER_STATE_ZOMBIE ))
+      {
+        /* Remove it from the list */
+        orxout(internal_warning) << (char*)elem.peer->data << " timed out.\n";
+        mainlist.delServerByName( elem.ServerInfo.getServerName() );
+
+        /* stop iterating, we manipulated the list */
+        /* TODO note: this only removes one dead server per loop
+         * iteration. not beautiful, but one iteration is ~100ms,
+         * so not really relevant for the moment.
+         */
+        break;
+      }
+    }
+
+  }
+
+
+
+
+  /***** EVENTS *****/
+  /* connect event */
+  int
+  MasterServer::eventConnect( ENetEvent *event )
+  { /* check for bad parameters */
+    if( !event )
+    { orxout(internal_warning, context::master_server) << "MasterServer::eventConnect: No event given." << endl;
+      return -1;
+    }
+
+    /* convert address to string. */
+    char *addrconv = (char *) calloc( 50, 1 );
+    enet_address_get_host_ip( &(event->peer->address), addrconv, 49 );
+
+    /* output debug info */
+    orxout(verbose, context::master_server) << "A new client connected from "
+      << addrconv
+      << " on port "
+      << event->peer->address.port << endl;
+
+    /* store string form of address here */
+    event->peer->data = addrconv;
+
+    /* all fine. */
+    return 0;
+  }
+
+  /* disconnect event */
+  int
+  MasterServer::eventDisconnect( ENetEvent *event )
+  { /* check for bad parameters */
+    if( !event )
+    { orxout(internal_warning, context::master_server) << "No event given." << endl;
+      return -1;
+    }
+
+    /* output that the disconnect happened */
+    orxout(verbose, context::master_server) << (char*)event->peer->data << " disconnected." << endl;
+
+    /* create string from peer data */
+    std::string name = std::string( (char*)event->peer->data );
+
+    /* remove the server from the list it belongs to */
+    this->mainlist.delServerByName( name );
+
+    /* Reset the peer's client information. */
+    if( event->peer->data ) free( event->peer->data );
+
+    /* done */
+    return 0;
+  }
+
+  /* data event */
+  int
+  MasterServer::eventData( ENetEvent *event )
+  { /* validate packet */
+    if( !event || !(event->packet) || !(event->peer) )
+    { orxout(internal_warning, context::master_server) << "No complete event given." << endl;
+      return -1;
+    }
+
+    /* generate address in readable form */
+    char *addrconv = (char *) calloc( 50, 1 );
+    enet_address_get_host_ip( &(event->peer->address), addrconv, 49 );
+    /* convert to string */
+    std::string ip = std::string( addrconv );
+    /* output debug info about the data that has come */
+    helper_output_debug(event, addrconv);
+    /* delete addrconv */
+    if( addrconv ) free( addrconv );
+
+    /* pointer to full packet data */
+    char * packetdata = (char *)event->packet->data;
+
+
+    /* GAME SERVER OR CLIENT CONNECTION? */
+    if( !strncmp(packetdata, MSPROTO_GAME_SERVER, MSPROTO_GAME_SERVER_LEN ) )
+    { /* Game server */
+
+      if( !strncmp( packetdata + MSPROTO_GAME_SERVER_LEN+1, MSPROTO_REGISTER_SERVER, MSPROTO_REGISTER_SERVER_LEN ) )
+      { /* register new server */
+        mainlist.addServer( packet::ServerInformation( event ), event->peer );
+
+        /* tell people we did so */
+        orxout(internal_info, context::master_server) << "Added new server to list: " <<
+          packet::ServerInformation( event ).getServerIP() << endl;
+      }
+
+      else if( !strncmp( packetdata + MSPROTO_GAME_SERVER_LEN+1, MSPROTO_SERVERDC, MSPROTO_SERVERDC_LEN ) )
+      { /* disconnect server */
+
+        /* remove the server from the list it belongs to */
+        this->mainlist.delServerByAddress( ip );
+
+        /* tell the user */
+        orxout(internal_info, context::master_server) << "Removed server " << ip << " from list." << endl;
+      }
+      /* TODO add hook for disconnect here */
+
+      else if( !strncmp( packetdata + MSPROTO_GAME_SERVER_LEN+1, MSPROTO_SET_NAME, MSPROTO_SET_NAME_LEN ) )
+      { /* save server name */
+        /* create string from peer data */
+        std::string data (event->packet->data,event->packet->data + event->packet->dataLength );
+        std::string name = data.substr(MSPROTO_GAME_SERVER_LEN+1 + MSPROTO_SET_NAME_LEN + 1);
+
+        /* remove the server from the list it belongs to */
+        this->mainlist.setNameByAddress( ip, name );
+
+        /* tell the user */
+        orxout(internal_info, context::master_server) << "Updated server " << ip << " with new name " << name << endl;
+      }
+
+      else if( !strncmp( packetdata + MSPROTO_GAME_SERVER_LEN+1, MSPROTO_SET_CLIENTS, MSPROTO_SET_CLIENTS_LEN ) )
+      { /* save client count from server */
+        /* create string from peer data */
+        std::string data (event->packet->data,event->packet->data + event->packet->dataLength );
+        std::string textform= data.substr(MSPROTO_GAME_SERVER_LEN + 1 + MSPROTO_SET_CLIENTS_LEN + 1);
+        int clientNumber = Ogre::StringConverter::parseInt(textform);
+
+        this->mainlist.setClientsByAddress( ip, clientNumber);
+
+        /* tell the user */
+        orxout(internal_info, context::master_server) << "Updated server " << ip << " with new client number " << clientNumber << endl;
+      }
+    }
+    else if( !strncmp( packetdata, MSPROTO_CLIENT, MSPROTO_CLIENT_LEN) )
+    { /* client */
+      if( !strncmp( packetdata + MSPROTO_CLIENT_LEN+1, MSPROTO_REQ_LIST, MSPROTO_REQ_LIST_LEN ) )
+        /* send server list */
+        helper_sendlist( event );
+    }
+    else
+    { /* bad message, don't do anything. */ }
+
+    /* Clean up the packet now that we're done using it. */
+    enet_packet_destroy( event->packet );
+    return 0;
+  }
+
+
+  /**** MAIN ROUTINE *****/
+  int
+  MasterServer::run()
+  {
+    /***** ENTER MAIN LOOP *****/
+    ENetEvent *event = (ENetEvent *)calloc(1, sizeof(ENetEvent));
+    if( event == nullptr )
+    {
+      orxout(user_error, context::master_server) << "Could not create ENetEvent structure, exiting." << endl;
+      exit( EXIT_FAILURE );
+    }
+
+    /* check for timed out peers and remove those from * the server list */
+    helper_cleanupServers();
+
+
+    /* create an iterator for the loop */
+    enet_host_service( this->server, event, 100 );
+
+    /* check what type of event it is and react accordingly */
+    switch (event->type)
+    { /* new connection */
+      case ENET_EVENT_TYPE_CONNECT:
+        eventConnect( event ); break;
+
+        /* disconnect */
+      case ENET_EVENT_TYPE_DISCONNECT:
+        eventDisconnect( event ); break;
+
+        /* incoming data */
+      case ENET_EVENT_TYPE_RECEIVE: eventData( event ); break;
+      default: break;
+    }
+
+    /* done */
+    free(event);
+    return 0;
+  }
+
+  /* constructor */
+  MasterServer::MasterServer()
+  {
+    /***** INITIALIZE NETWORKING *****/
+    if( enet_initialize () != 0)
+    { orxout(user_error, context::master_server) << "An error occurred while initializing ENet." << endl;
+      exit( EXIT_FAILURE );
+    }
+
+    /* register deinitialization */
+    atexit( enet_deinitialize );
+
+    /* set the quit flag to false */
+    this->quit = false;
+
+    /* Bind the server to the default localhost and port ORX_MSERVER_PORT */
+    this->address.host = ENET_HOST_ANY;
+    this->address.port = ORX_MSERVER_PORT;
+
+    /* create a host with the above settings (the last two 0 mean: accept
+     * any input/output bandwidth */
+    this->server = enet_host_create( &this->address, ORX_MSERVER_MAXCONNS,
+        ORX_MSERVER_MAXCHANS, 0, 0 );
+    assert(this->server);
+
+    /* see if creation worked */
+    if( !this->server )
+    { orxout(user_error, context::master_server) <<
+        "An error occurred while trying to create an ENet server host." << endl;
+      exit( EXIT_FAILURE );
+    }
+
+    /* set pointer to this instance */
+    MasterServer::setInstance( this );
+
+    /* tell people we're now initialized */
+    orxout(internal_status, context::master_server) << "MasterServer initialized, waiting for connections." << endl;
+  }
+
+  /* destructor */
+  MasterServer::~MasterServer()
+  {
+    /***** CLEANUP PROCESS *****/
+    /* terminate all networking connections */
+    enet_host_destroy( this->server );
+
+    /* free all used memory */
+    /* clear the list of connected game servers */
+    /* clear the list of connected game clients */
+  }
+
+/* end of namespace */
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/MasterServer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/MasterServer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/MasterServer.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MasterServer_H__
+#define _MasterServer_H__
+
+#include "NetworkPrereqs.h"
+
+/* orxonox includes */
+#include <enet/enet.h>
+#include <network/packet/Chat.h>
+#include <network/packet/ClassID.h>
+#include <network/packet/DeleteObjects.h>
+#include <network/packet/FunctionIDs.h>
+#include <network/packet/Gamestate.h>
+#include <network/packet/Welcome.h>
+#include <network/MasterServerProtocol.h>
+
+/* my includes */
+#include "ServerList.h"
+#include "PeerList.h"
+
+/* c compatibility */
+#include <cstdio>
+
+#include <OgreStringConverter.h>
+
+
+namespace orxonox
+{
+  /* singleton */
+  class _NetworkExport MasterServer
+  {
+    public:
+      MasterServer();
+      ~MasterServer();
+
+      /* main routine */
+      int run();
+
+      /* static pointer for commands */
+      static MasterServer *instance;
+      static MasterServer *getInstance()
+        { return instance; }
+      static void setInstance( MasterServer *setto )
+        { instance = setto;  }
+
+      /* functions for commands */
+      static void listServers( void );
+      static void delServer( std::string todeladdr );
+
+    private:
+      /* methods */
+      int eventConnect( ENetEvent *event );
+      int eventDisconnect( ENetEvent *event );
+      int eventData( ENetEvent *event );
+
+      /* helpers */
+      void helper_sendlist( ENetEvent *event );
+      void helper_cleanupServers( void );
+
+      /* members */
+      ENetAddress address;
+      ENetHost *server;
+      ServerList mainlist;
+
+      unsigned int port;
+      bool quit;
+
+  };
+}
+
+#endif /* _MasterServer_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/MasterServerComm.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/MasterServerComm.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/MasterServerComm.cc	(revision 11817)
@@ -0,0 +1,257 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MasterServerComm.h"
+#include "util/Output.h"
+#include "WANDiscovery.h"
+
+namespace orxonox
+{
+
+  MasterServerComm::MasterServerComm()
+  { /* nothing anymore, everything's been outsourced to 
+     * the initialize method to facilitate debugging
+     */
+    /* register object in orxonox */
+  } 
+
+  int MasterServerComm::initialize()
+  {
+    /* initialize Enet */
+    if( enet_initialize () != 0 )
+    { orxout(internal_error, context::master_server) << "An error occurred while initializing ENet." << endl;
+      return 1;
+    }
+
+    /* initialize the event holder */
+//     this->event = (ENetEvent *)calloc( sizeof(ENetEvent), 1 );
+    
+
+    /* initiate the client */
+    this->client = enet_host_create( nullptr /* create a client host */,
+        1,
+        2, /* allow up 2 channels to be used, 0 and 1 */
+        0, 
+        0 ); 
+
+    /* see if it worked */
+    if (this->client == nullptr)
+    { orxout(internal_error, context::master_server) << "An error occurred while trying to create an " 
+        << "ENet client host." << endl;
+      return 1;
+    }
+
+    return 0;
+  }
+
+  MasterServerComm::~MasterServerComm()
+  {
+    /* destroy the enet facilities */
+    enet_host_destroy(this->client);
+  }
+
+  int MasterServerComm::connect( const char *address, unsigned int port )
+  {
+    /* Connect to address:port. */
+    enet_address_set_host( &this->address, address );
+    this->address.port = port;
+
+    /* Initiate the connection, allocating the two channels 0 and 1. */
+    this->peer = enet_host_connect(this->client, &this->address, 2, 0);    
+
+    if( this->peer == nullptr )
+    { orxout(internal_error, context::master_server) << "No available peers for initiating an ENet"
+        << " connection." << endl;
+      return -1;
+    }
+
+    /* Wait up to 2 seconds for the connection attempt to succeed. */
+    if (enet_host_service (this->client, &this->event, 500) > 0 &&
+        this->event.type == ENET_EVENT_TYPE_CONNECT )
+      orxout(internal_info, context::master_server) << "Connection to master server succeeded." << endl;
+    else
+    {
+      enet_peer_reset (this->peer);
+      orxout(internal_warning, context::master_server) << "Connection to " << address << " failed." << endl;
+      return -1;
+    }
+
+    /* all fine */
+    return 0;
+  }
+  
+void MasterServerComm::update()
+{
+  while( enet_host_service( this->client, &this->event, 1 ) );
+}
+
+
+  int MasterServerComm::disconnect( void )
+  {
+    while( enet_host_service( this->client, &this->event, 1 ) );
+    enet_peer_disconnect( this->peer, 0 );
+
+    /* Allow up to 1 second for the disconnect to succeed
+     * and drop any packets received packets.
+     */
+    while (enet_host_service (this->client, &this->event, 1000) > 0)
+    {
+      switch (this->event.type)
+      {
+        case ENET_EVENT_TYPE_RECEIVE:
+          enet_packet_destroy (event.packet);
+          break;
+
+        case ENET_EVENT_TYPE_DISCONNECT:
+          orxout(verbose, context::master_server) << "Disconnect from master server successful." << endl; 
+          return 0;
+        default: break;
+      }
+    }
+
+    /* We've arrived here, so the disconnect attempt didn't
+     * succeed yet, hence: force the connection down.            
+     */
+    enet_peer_reset( this->peer );
+
+    /* done */
+    return 0;
+  }
+
+  /* NOTE this is to be reimplemented soon to return 
+   * a structure containing 
+   * - addrconv
+   * - the event
+   * so we can also make callbacks from objects
+   */
+  int MasterServerComm::pollForReply( WANDiscovery* listener, int delayms )
+  { 
+    /* see whether anything happened */
+    /* WORK MARK REMOVE THIS OUTPUT */
+    orxout(verbose, context::master_server) << "polling masterserver..." << endl;
+
+    /* address buffer */
+    char *addrconv = nullptr;
+    int retval = 0;
+
+    /* enet_host_service returns 0 if no event occured */
+    /* just newly set below test to >0 from >= 0, to be tested */
+    if( enet_host_service( this->client, &this->event, delayms ) > 0 )
+    { 
+      /* check what type of event it is and react accordingly */
+      switch (this->event.type)
+      { /* new connection, not supposed to happen. */
+        case ENET_EVENT_TYPE_CONNECT: break;
+
+        /* disconnect */
+        case ENET_EVENT_TYPE_DISCONNECT: /* ?? */ break;
+
+        /* incoming data */
+        case ENET_EVENT_TYPE_RECEIVE: 
+          addrconv = (char *) calloc( 50, 1 );
+          if( !addrconv ) 
+          { orxout(internal_warning, context::master_server) << "MasterServerComm.cc: Could not allocate memory!" << endl;
+            break;
+          }
+
+          /* resolve IP */
+          enet_address_get_host_ip( &(this->event.peer->address), 
+            addrconv, 49 );
+
+          /* DEBUG */
+          orxout(verbose, context::master_server) << "MasterServer Debug: A packet of length " 
+            << this->event.packet->dataLength 
+            << " containing " << this->event.packet->data
+            << " was received from " << addrconv 
+            << " on channel " << this->event.channelID;
+          /* END DEBUG */
+
+          /* call the supplied callback, if any. */
+          if( listener != nullptr )
+            retval = listener->rhandler( addrconv, &(this->event) );
+
+          /* clean up */
+          enet_packet_destroy( event.packet );
+          if( addrconv ) 
+            free( addrconv );
+
+          break;
+        default: break;
+      }
+
+      /* event handled, return 0 */
+      return retval;
+    }
+
+    /* show that no event occured */
+    return 0;
+  }
+
+  int MasterServerComm::sendRequest( const char *data )
+  {
+    /* send the data to the friend */
+    /* Create a reliable packet of size 7 containing "packet\0" */
+    ENetPacket * packet = enet_packet_create( data, 
+        strlen( data ) + 1, 
+        ENET_PACKET_FLAG_RELIABLE);
+
+    /* Send the packet to the peer over channel id 0. */
+    enet_peer_send (this->peer, 0, packet);
+
+    /* One could just use enet_host_service() instead. */
+    enet_host_flush( this->client );
+   
+    /* free the packet */
+    // PLEASE: never do this, because enet will free the packet once it's delivered. this will cause double frees
+//     enet_packet_destroy( packet );
+
+    /* all done. */
+    return 0;
+  }
+
+  int MasterServerComm::sendRequest( std::string data )
+  {
+    /* send the data to the friend */
+    /* Create a reliable packet of size 7 containing "packet\0" */
+    ENetPacket * packet = enet_packet_create( data.c_str(), 
+        data.length() + 1, 
+        ENET_PACKET_FLAG_RELIABLE);
+
+    /* Send the packet to the peer over channel id 0. */
+    enet_peer_send (this->peer, 0, packet);
+
+    /* One could just use enet_host_service() instead. */
+    enet_host_flush( this->client );
+    // PLEASE: never do this, because enet will free the packet once it's delivered. this will cause double frees
+//     enet_packet_destroy( packet );
+
+    /* all done. */
+    return 0;
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/MasterServerComm.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/MasterServerComm.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/MasterServerComm.h	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MasterServerComm_H__
+#define _MasterServerComm_H__
+
+#include "NetworkPrereqs.h"
+
+#include <cstdlib>
+#include <cstdio>
+#include <string>
+#include <cstring>
+#include <enet/enet.h>
+
+
+namespace orxonox
+{
+  class _NetworkExport MasterServerComm 
+  { 
+    public: 
+      /** constructor */
+      MasterServerComm();
+
+      /** destructor */
+      ~MasterServerComm();
+
+      /** \return 0 for success, other for error
+       * 
+       * Initialize everything for the master server communication 
+       */
+      int initialize();
+      
+      void update();
+
+
+      /** \param address Address to connect to (Host name or IP in text form)
+       * \param port Port to connect on 
+       * \return 0 for success, other for error 
+       * 
+       * Connect to the master server with the given address on the given port. 
+       */
+      int connect( const char *address, unsigned int port );
+
+      /** \return 0 for success, other for error
+       * 
+       * Disconnect from master server.
+       */
+      int disconnect( void );
+
+      /** \param data The data to be sent. 
+       * \return 0 for success, other for error. 
+       * 
+       * Send a request to the master server containing data specified in data
+       */
+      int sendRequest( const char *data );
+
+      /** \param data The data to be sent. 
+       * \return 0 for success, other for error. 
+       * 
+       * Send a request to the master server containing data specified in data
+       * (string version)
+       */
+      int sendRequest( std::string data );
+
+      /** \param listener The listener to call with data received.
+       *  \param delayms Delay in milliseconds.
+       * \return 0 for success, other for error
+       * 
+       * Poll the master server for new data and act accordingly */
+      int pollForReply( WANDiscovery* listener, int delayms );
+
+    private:
+      /** client handle */
+      ENetHost* client;
+
+      /** event data holder */
+      ENetEvent event;
+
+      /** address holder */
+      ENetAddress address;
+
+      /** peer data holder */
+      ENetPeer* peer;
+  }; 
+
+} 
+
+#endif /* _MasterServerComm_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/MasterServerProtocol.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/MasterServerProtocol.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/MasterServerProtocol.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MasterServerProtocol_H__
+#define _MasterServerProtocol_H__
+
+/* master server address (to be moved elsewhere later) */
+#define MS_ADDRESS "129.132.3.8"
+
+
+/*** CLIENT COMMUNICATIONS ***/
+/* Client token (shows that the party sending data is a client */
+#define MSPROTO_CLIENT "CL"
+#define MSPROTO_CLIENT_LEN 2
+
+/* Request: Serverlist (requiest made from client to master server */
+#define MSPROTO_REQ_LIST "REQ:LIST"
+#define MSPROTO_REQ_LIST_LEN 8
+
+
+/*** GAME SERVER COMMUNICATIONS ***/
+/* Game server token (shows that the party sending data is a game server) */
+#define MSPROTO_GAME_SERVER "GS"
+#define MSPROTO_GAME_SERVER_LEN 2
+
+/* Register game server at the master server, meaning request to be taken into$
+ * the master servers game server list.
+ */
+#define MSPROTO_REGISTER_SERVER "REG:SER"
+#define MSPROTO_REGISTER_SERVER_LEN 7
+
+/* Server list item token */
+#define MSPROTO_SERVERLIST_ITEM "SI"
+#define MSPROTO_SERVERLIST_ITEM_LEN 2
+
+/* server list end token */
+#define MSPROTO_SERVERLIST_END "SL_END"
+#define MSPROTO_SERVERLIST_END_LEN 6
+
+/* ping request from server */
+#define MSPROTO_PING_GAMESERVER "PING"
+#define MSPROTO_PING_GAMESERVER_LEN 4
+
+/* server disconnect */
+#define MSPROTO_SERVERDC "DC"
+#define MSPROTO_SERVERDC_LEN 2
+
+/* ping reply */
+#define MSPROTO_ACK "ACK"
+#define MSPROTO_ACK_LEN 3
+
+/* server name */
+#define MSPROTO_SET_NAME "NAM"
+#define MSPROTO_SET_NAME_LEN 3
+
+/* server number of clients */
+#define MSPROTO_SET_CLIENTS "CLI"
+#define MSPROTO_SET_CLIENTS_LEN 3
+
+#define SERVER_NAME_MAXLEN 7
+
+/* default master server port */
+#define ORX_MSERVER_PORT 55557
+
+
+/* some constants for the networking of the master server, not very important.
+ * play with those if things don't work out well.$
+ */
+#define ORX_MSERVER_MAXCONNS 32
+#define ORX_MSERVER_MAXCHANS 2
+
+
+#endif /* _MasterServerProtocol_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkChatListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkChatListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkChatListener.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NetworkChatListener_H__
+#define _NetworkChatListener_H__
+
+#include "NetworkPrereqs.h"
+
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    /**
+        @brief The only function of this interface, incomingChat(), gets called whenever a chat
+        message was received through the network.
+
+        This interface exists mostly to resolve circular dependencies between the chat functions
+        in Host and ChatManager. ChatManager is the main derivative of this interface.
+    */
+    class _NetworkExport NetworkChatListener : virtual public Listable
+    {
+        friend class Host;
+
+        public:
+            NetworkChatListener(); // implemented in Host.cc
+            virtual ~NetworkChatListener() {}
+
+        protected:
+            /**
+                @brief Gets called when a chat message was received through the network.
+                @param message The message
+                @param sourceID The (network) client ID of the sender
+            */
+            virtual void incomingChat(const std::string& message, unsigned int sourceID) = 0;
+    };
+}
+
+#endif /* _NetworkChatListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunction.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunction.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunction.cc	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "NetworkFunction.h"
+#include "NetworkFunctionManager.h"
+
+namespace orxonox
+{
+    NetworkFunctionBase::NetworkFunctionBase(const std::string& name, const NetworkFunctionPointer& pointer)
+    {
+        static uint32_t networkID = 0;
+        this->networkID_ = networkID++;
+        this->name_ = name;
+        this->pointer_ = pointer;
+    }
+
+    void NetworkFunctionBase::setNetworkID(uint32_t id)
+    {
+        this->networkID_ = id;
+        NetworkFunctionManager::getInstance().registerFunction(this);   // register with new id
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunction.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunction.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunction.h	(revision 11817)
@@ -0,0 +1,211 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NetworkFunction_H__
+#define _NetworkFunction_H__
+
+#include "NetworkPrereqs.h"
+
+#include <cassert>
+#include <cstring>
+#include <map>
+#include <string>
+
+#include "core/command/Functor.h"
+#include "FunctionCallManager.h"
+#include "synchronisable/Synchronisable.h"
+
+namespace orxonox
+{
+
+#if defined(ORXONOX_COMPILER_GCC) && defined(ORXONOX_ARCH_32)
+static constexpr unsigned int MAX_FUNCTION_POINTER_SIZE = 8;
+#else
+static constexpr unsigned int MAX_FUNCTION_POINTER_SIZE = 16;
+#endif //ORXONOX_COMPILER_GCC
+static constexpr unsigned int MAX_FUNCTION_POINTER_INTS = (MAX_FUNCTION_POINTER_SIZE-1)/4+1;
+
+struct _NetworkExport NetworkFunctionPointer {
+  uint32_t pointer[MAX_FUNCTION_POINTER_INTS];
+  bool operator<(const NetworkFunctionPointer& b) const
+  {
+#if defined(ORXONOX_COMPILER_GCC) && defined(ORXONOX_ARCH_32)
+    if (pointer[0] != b.pointer[0])
+        return pointer[0] < b.pointer[0];
+    else if (pointer[1] != b.pointer[1])
+        return pointer[1] < b.pointer[1];
+    else
+        return false;
+#else
+    if (pointer[0] != b.pointer[0])
+        return pointer[0] < b.pointer[0];
+    else if (pointer[1] != b.pointer[1])
+        return pointer[1] < b.pointer[1];
+    else if (pointer[2] != b.pointer[2])
+        return pointer[2] < b.pointer[2];
+    else if (pointer[3] != b.pointer[3])
+        return pointer[3] < b.pointer[3];
+    else
+        return false;
+#endif
+  }
+};
+
+
+
+
+
+class _NetworkExport NetworkFunctionBase {
+  public:
+    NetworkFunctionBase(const std::string& name, const NetworkFunctionPointer& pointer);
+    virtual ~NetworkFunctionBase() {}
+
+    void setNetworkID(uint32_t id);
+    inline uint32_t     getNetworkID() const                { return this->networkID_; }
+    inline const std::string& getName() const               { return this->name_; }
+    inline const NetworkFunctionPointer& getPointer() const { return this->pointer_; }
+
+    virtual bool call(uint32_t objectID)=0;
+    virtual bool call(uint32_t objectID, const MultiType& mt1)=0;
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2)=0;
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3)=0;
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4)=0;
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5)=0;
+
+  private:
+    uint32_t networkID_;
+    std::string name_;
+    NetworkFunctionPointer pointer_;
+
+};
+
+
+class _NetworkExport NetworkFunctionStatic: public NetworkFunctionBase {
+  public:
+    NetworkFunctionStatic(const FunctorStaticPtr& functor, const std::string& name, const NetworkFunctionPointer& p)
+        : NetworkFunctionBase(name, p)
+        , functor_(functor)
+    { }
+
+    // ignore the objectID because its a static function
+    virtual bool call(uint32_t objectID) override{ (*this->functor_)(); return true; }
+    virtual bool call(uint32_t objectID, const MultiType& mt1) override{ (*this->functor_)(mt1); return true; }
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2) override{ (*this->functor_)(mt1, mt2); return true; }
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3) override{ (*this->functor_)(mt1, mt2, mt3); return true; }
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4) override{ (*this->functor_)(mt1, mt2, mt3, mt4); return true; }
+    virtual bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5) override{ (*this->functor_)(mt1, mt2, mt3, mt4, mt5); return true; }
+
+  private:
+    FunctorStaticPtr functor_;
+
+};
+
+
+class _NetworkExport NetworkMemberFunctionBase: public NetworkFunctionBase {
+  public:
+    NetworkMemberFunctionBase(const std::string& name, const NetworkFunctionPointer& p)
+        : NetworkFunctionBase(name, p)
+    { }
+};
+
+
+template <class T> class NetworkMemberFunction: public NetworkMemberFunctionBase {
+  public:
+    NetworkMemberFunction(const FunctorMemberPtr<T>& functor, const std::string& name, const NetworkFunctionPointer& p)
+        : NetworkMemberFunctionBase(name, p)
+        , functor_(functor)
+    { }
+
+    virtual inline bool call(uint32_t objectID) override
+    {
+      if ( Synchronisable::getSynchronisable(objectID)!=nullptr )
+      {
+        (*this->functor_)(orxonox_cast<T*>(Synchronisable::getSynchronisable(objectID)));
+        return true;
+      }
+      else
+        return false;
+    }
+    virtual inline bool call(uint32_t objectID, const MultiType& mt1) override
+    {
+      if ( Synchronisable::getSynchronisable(objectID)!=nullptr )
+      {
+        (*this->functor_)(orxonox_cast<T*>(Synchronisable::getSynchronisable(objectID)), mt1);
+        return true;
+      }
+      else
+        return false;
+    }
+    virtual inline bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2) override
+    {
+      if ( Synchronisable::getSynchronisable(objectID)!=nullptr )
+      {
+        (*this->functor_)(orxonox_cast<T*>(Synchronisable::getSynchronisable(objectID)), mt1, mt2);
+        return true;
+      }
+      else
+        return false;
+    }
+    virtual inline bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3) override
+    {
+      if ( Synchronisable::getSynchronisable(objectID)!=nullptr )
+      {
+        (*this->functor_)(orxonox_cast<T*>(Synchronisable::getSynchronisable(objectID)), mt1, mt2, mt3);
+        return true;
+      }
+      else
+        return false;
+    }
+    virtual inline bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4) override
+    {
+      if ( Synchronisable::getSynchronisable(objectID)!=nullptr )
+      {
+        (*this->functor_)(orxonox_cast<T*>(Synchronisable::getSynchronisable(objectID)), mt1, mt2, mt3, mt4);
+        return true;
+      }
+      else
+        return false;
+    }
+    virtual inline bool call(uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5) override
+    {
+      if ( Synchronisable::getSynchronisable(objectID)!=nullptr )
+      {
+        (*this->functor_)(orxonox_cast<T*>(Synchronisable::getSynchronisable(objectID)), mt1, mt2, mt3, mt4, mt5);
+        return true;
+      }
+      else
+        return false;
+    }
+
+  private:
+    FunctorMemberPtr<T> functor_;
+};
+
+}
+
+#endif /* _NetworkFunction_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionIncludes.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionIncludes.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionIncludes.cc	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "NetworkFunctionIncludes.h"
+#include "NetworkFunctionManager.h"
+
+#include "core/module/StaticInitializationHandlerIncludes.h"
+#include "NetworkStaticInitializationHandler.h"
+
+namespace orxonox
+{
+    RegisterStaticInitializationHandler(NetworkStaticInitializationHandler);
+
+    void StaticallyInitializedNetworkFunction::load()
+    {
+        NetworkFunctionManager::getInstance().registerFunction(this->function_);
+    }
+
+    void StaticallyInitializedNetworkFunction::unload()
+    {
+        NetworkFunctionManager::getInstance().unregisterFunction(this->function_);
+    }
+
+    uint32_t getNetworkIdForPointer(const NetworkFunctionPointer& pointer)
+    {
+        return NetworkFunctionManager::getInstance().getFunctionByFunctionPointer(pointer)->getNetworkID();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionIncludes.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionIncludes.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionIncludes.h	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#ifndef _NetworkFunctionIncludes_H__
+#define _NetworkFunctionIncludes_H__
+
+#include "NetworkPrereqs.h"
+
+#include <boost/preprocessor/cat.hpp>
+
+#include "NetworkFunction.h"
+#include "core/module/StaticallyInitializedInstance.h"
+
+#define registerStaticNetworkFunction( functionPointer ) \
+    static orxonox::NetworkFunctionBase& BOOST_PP_CAT( NETWORK_FUNCTION_, __UNIQUE_NUMBER__ ) \
+        = (new orxonox::SI_NF(orxonox::registerStaticNetworkFunctionFct( functionPointer, #functionPointer )))->getFunction()
+
+#define registerMemberNetworkFunction( class, function ) \
+    static orxonox::NetworkFunctionBase& BOOST_PP_CAT( NETWORK_FUNCTION_##class, __UNIQUE_NUMBER__ ) \
+        = (new orxonox::SI_NF(orxonox::registerMemberNetworkFunctionFct<class>( &class::function, #class "_" #function)))->getFunction()
+
+namespace orxonox
+{
+    class _NetworkExport StaticallyInitializedNetworkFunction : public StaticallyInitializedInstance
+    {
+        public:
+            StaticallyInitializedNetworkFunction(NetworkFunctionBase* function)
+                : StaticallyInitializedInstance(StaticInitialization::NETWORK_FUNCTION)
+                , function_(function)
+            {}
+            ~StaticallyInitializedNetworkFunction() { delete function_; }
+
+            virtual void load() override;
+            virtual void unload() override;
+
+            inline NetworkFunctionBase& getFunction()
+                { return *this->function_; }
+
+        private:
+            NetworkFunctionBase* function_;
+    };
+
+    typedef StaticallyInitializedNetworkFunction SI_NF;
+
+    template<class PT>
+    inline NetworkFunctionBase* registerStaticNetworkFunctionFct(PT ptr, const std::string& name)
+    {
+        static_assert(sizeof(PT) <= sizeof(NetworkFunctionPointer), "check pointer size"); // if this fails your compiler uses bigger pointers for static functions than defined above
+        NetworkFunctionPointer destptr;
+        copyPtr(ptr, destptr);
+        return new NetworkFunctionStatic(createFunctor(ptr), name, destptr);
+    }
+
+    template<class T, class PT>
+    inline NetworkFunctionBase* registerMemberNetworkFunctionFct(PT ptr, const std::string& name)
+    {
+        static_assert(sizeof(PT) <= sizeof(NetworkFunctionPointer), "check pointer size"); // if this fails your compiler uses bigger pointers for a specific kind of member functions than defined above
+        NetworkFunctionPointer destptr;
+        copyPtr(ptr, destptr);
+        return new NetworkMemberFunction<T>(createFunctor(ptr), name, destptr);
+    }
+
+    _NetworkExport uint32_t getNetworkIdForPointer(const NetworkFunctionPointer& pointer);
+
+    // call it with functionPointer, clientID, args
+    template<class PT>
+    void callStaticNetworkFunction(PT ptr, uint32_t clientID, const MultiType& mt1 = MultiType::Null, const MultiType& mt2 = MultiType::Null, const MultiType& mt3 = MultiType::Null, const MultiType& mt4 = MultiType::Null, const MultiType& mt5 = MultiType::Null)
+    {
+        NetworkFunctionPointer destptr;
+        copyPtr(ptr, destptr);
+        FunctionCallManager::addCall(getNetworkIdForPointer(destptr), OBJECTID_UNKNOWN, clientID, mt1, mt2, mt3, mt4, mt5);
+    }
+
+    // call it with class::function, objectID, clientID, args
+    template<class PT>
+    void callMemberNetworkFunction(PT ptr, uint32_t objectID, uint32_t clientID, const MultiType& mt1 = MultiType::Null, const MultiType& mt2 = MultiType::Null, const MultiType& mt3 = MultiType::Null, const MultiType& mt4 = MultiType::Null, const MultiType& mt5 = MultiType::Null)
+    {
+        NetworkFunctionPointer destptr;
+        copyPtr(ptr, destptr);
+        FunctionCallManager::addCall(getNetworkIdForPointer(destptr), objectID, clientID, mt1, mt2, mt3, mt4, mt5);
+    }
+
+    template<class PT>
+    inline void copyPtr(PT ptr, NetworkFunctionPointer& destptr)
+    {
+        if (sizeof(NetworkFunctionPointer) - sizeof(PT) > 0)
+            memset((uint8_t*)&destptr + sizeof(PT), 0, sizeof(NetworkFunctionPointer) - sizeof(PT));
+        PT p2 = ptr;
+        memcpy(&destptr, &p2, sizeof(PT));
+    }
+}
+
+#endif /* _NetworkFunctionIncludes_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionManager.cc	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "NetworkFunctionManager.h"
+#include "NetworkFunction.h"
+
+namespace orxonox
+{
+    NetworkFunctionManager* NetworkFunctionManager::singletonPtr_s = nullptr;
+
+    void NetworkFunctionManager::registerFunction(NetworkFunctionBase* function)
+    {
+        this->functions_.insert(function);
+        this->nameMap_[function->getName()] = function;
+        this->idMap_[function->getNetworkID()] = function;
+        this->functorMap_[function->getPointer()] = function;
+    }
+
+    void NetworkFunctionManager::unregisterFunction(NetworkFunctionBase* function)
+    {
+        this->functions_.erase(function);
+        this->nameMap_.erase(function->getName());
+        this->idMap_.erase(function->getNetworkID());
+        this->functorMap_.erase(function->getPointer());
+    }
+
+    NetworkFunctionBase* NetworkFunctionManager::getFunctionByName(const std::string& name)
+    {
+        std::map<std::string, NetworkFunctionBase*>::iterator it = nameMap_.find(name);
+        assert(it != nameMap_.end());
+        return it->second;
+    }
+
+    NetworkFunctionBase* NetworkFunctionManager::getFunctionByFunctionPointer(const NetworkFunctionPointer& p)
+    {
+        std::map<NetworkFunctionPointer, NetworkFunctionBase*>::iterator it = functorMap_.find(p);
+        assert(it != functorMap_.end());
+        return it->second;
+    }
+
+    NetworkFunctionBase* NetworkFunctionManager::getFunctionByNetworkId(uint32_t id)
+    {
+        std::map<uint32_t, NetworkFunctionBase*>::iterator it = idMap_.find(id);
+        assert(it != idMap_.end());
+        if(it != idMap_.end())
+            return it->second;
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Cleans the NetworkID map (needed on clients for correct initialization)
+    */
+    void NetworkFunctionManager::clearNetworkIDs()
+    {
+        this->idMap_.clear();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkFunctionManager.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef __NetworkFunctionManager_H__
+#define __NetworkFunctionManager_H__
+
+#include "NetworkPrereqs.h"
+
+#include <cassert>
+#include <map>
+#include <set>
+
+#include "util/Singleton.h"
+#include "NetworkFunction.h"
+
+namespace orxonox
+{
+    class _NetworkExport NetworkFunctionManager : public Singleton<NetworkFunctionManager>
+    {
+        friend class Singleton<NetworkFunctionManager>;
+
+        public:
+            void registerFunction(NetworkFunctionBase* function);
+            void unregisterFunction(NetworkFunctionBase* function);
+
+            inline const std::set<NetworkFunctionBase*>& getAllFunctions()
+                { return functions_; }
+
+            NetworkFunctionBase* getFunctionByName(const std::string& name);
+            NetworkFunctionBase* getFunctionByFunctionPointer(const NetworkFunctionPointer& p);
+            NetworkFunctionBase* getFunctionByNetworkId(uint32_t id);
+
+            void clearNetworkIDs();
+
+        private:
+            std::set<NetworkFunctionBase*> functions_;
+            std::map<std::string, NetworkFunctionBase*> nameMap_;
+            std::map<NetworkFunctionPointer, NetworkFunctionBase*> functorMap_;
+            std::map<uint32_t, NetworkFunctionBase*> idMap_;
+
+            static NetworkFunctionManager* singletonPtr_s;
+    };
+}
+
+#endif /* __NetworkFunctionManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the network library
+@details
+    Updated: 13. September 2009
+    Total Files: 28
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <cstring>  // 26
+#include <cassert>  // 24
+#include <string>   // 23
+#include <vector>   // 23
+#include <map>      // 23
+#include <fstream>  // 22
+#include <iostream> // 22
+#include <sstream>  // 22
+#include <set>      // 20
+
+#include "util/Output.h"      // 20
+#include <loki/TypeTraits.h> // 18
+
+#ifdef ORXONOX_COMPILER_MSVC
+
+#include <deque>    // 17
+#include <queue>    // 17
+#include <list>     // 16
+#include <cmath>    // 15
+
+#include <OgreMath.h>        // 15
+#include <OgreVector2.h>     // 15
+#include <OgreVector3.h>     // 15
+#include <OgreVector4.h>     // 15
+#include <OgreQuaternion.h>  // 15
+#include <OgreColourValue.h> // 15
+
+#define WIN32_LEAN_AND_MEAN
+#include <enet/enet.h> // 6, 3.1MB
+
+#include "util/mbool.h" // 11
+
+#endif /*ORXONOX_COMPILER_MSVC */
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkPrereqs.h	(revision 11817)
@@ -0,0 +1,186 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the network library
+*/
+
+#ifndef _NetworkPrereqs_H__
+#define _NetworkPrereqs_H__
+
+#include "OrxonoxConfig.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined( NETWORK_STATIC_BUILD )
+#  ifdef NETWORK_SHARED_BUILD
+#    define _NetworkExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _NetworkExport
+#    else
+#      define _NetworkExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _NetworkPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _NetworkExport  __attribute__ ((visibility("default")))
+#  define _NetworkPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _NetworkExport
+#  define _NetworkPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+  static constexpr unsigned int GAMESTATEID_INITIAL       = static_cast<unsigned int>(-1);
+  extern const char* LAN_DISCOVERY_MESSAGE;
+  extern const char* LAN_DISCOVERY_ACK;
+  static constexpr unsigned int LAN_DISCOVERY_PORT          = 55558;
+  static constexpr unsigned int NETWORK_PEER_ID_SERVER      = 0;
+  static constexpr unsigned int NETWORK_PEER_ID_BROADCAST   = static_cast<unsigned int>(-1);
+  static constexpr unsigned int NETWORK_PEER_ID_UNKNOWN     = static_cast<unsigned int>(-2);
+  static constexpr unsigned int NETWORK_CHANNEL_DEFAULT     = 0;
+  static constexpr unsigned int NETWORK_CHANNEL_UNRELIABLE  = 1;
+  static constexpr unsigned int NETWORK_CHANNEL_COUNT       = 2;
+}
+
+//-----------------------------------------------------------------------
+// Enums
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+  namespace packet
+  {
+    namespace PacketFlag
+    {
+      static constexpr uint32_t Reliable    = 1;
+      static constexpr uint32_t Unsequenced = 2;
+      static constexpr uint32_t NoAllocate  = 4;
+    }
+  }
+
+  namespace StaticInitialization
+  {
+    typedef int Type;
+    static constexpr Type NETWORK_FUNCTION = 6;
+  }
+}
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+// from ENet
+struct _ENetPeer;
+typedef _ENetPeer     ENetPeer;
+struct _ENetPacket;
+typedef _ENetPacket   ENetPacket;
+struct _ENetEvent;
+typedef _ENetEvent    ENetEvent;
+struct _ENetHost;
+typedef _ENetHost     ENetHost;
+struct _ENetAddress;
+typedef _ENetAddress  ENetAddress;
+typedef uint8_t       ENetChannelID;
+
+namespace orxonox
+{
+  class Client;
+  class ClientConnection;
+  class ClientConnectionListener;
+  class ClientInformation;
+  class Connection;
+  class FunctionCall;
+  class FunctionCallManager;
+  class GamestateClient;
+  class GamestateHandler;
+  class GamestateManager;
+  class Host;
+  class MasterServer;
+  class MasterServerComm;
+  class NetworkChatListener;
+  class NetworkFunctionBase;
+  struct NetworkFunctionPointer;
+  class NetworkFunctionStatic;
+  template <class T>
+  class NetworkMemberFunction;
+  class NetworkMemberFunctionBase;
+  class PeerList;
+  class Server;
+  class ServerConnection;
+  class TrafficControl;
+  class WANDiscoverable;
+  class WANDiscovery;
+
+  // packet
+  namespace packet
+  {
+    class Acknowledgement;
+    class Chat;
+    class ClassID;
+    class DeleteObjects;
+    class FunctionCalls;
+    class FunctionIDs;
+    class Gamestate;
+    class Packet;
+    class Welcome;
+  }
+
+  // synchronisable
+  template <class T>
+  class NetworkCallback;
+  template <class T, class U>
+  class NetworkCallbackNotify;
+  class NetworkCallbackBase;
+  class NetworkCallbackManager;
+  class Synchronisable;
+  class SynchronisableHeader;
+  template <class T>
+  class SynchronisableVariable;
+  class SynchronisableVariableBase;
+  template <class T>
+  class SynchronisableVariableBidirectional;
+}
+
+namespace boost
+{
+  class mutex;
+  class thread;
+}
+
+#endif /* _NetworkPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkStaticInitializationHandler.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkStaticInitializationHandler.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkStaticInitializationHandler.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "NetworkStaticInitializationHandler.h"
+
+#include "core/module/ModuleInstance.h"
+#include "NetworkFunctionManager.h"
+
+namespace orxonox
+{
+    void NetworkStaticInitializationHandler::setupHandler()
+    {
+        // initialize singleton
+        new NetworkFunctionManager();
+    }
+
+    void NetworkStaticInitializationHandler::shutdownHandler()
+    {
+        delete &NetworkFunctionManager::getInstance();
+    }
+
+    void NetworkStaticInitializationHandler::loadModule(ModuleInstance* module)
+    {
+        module->loadAllStaticallyInitializedInstances(StaticInitialization::NETWORK_FUNCTION);
+    }
+
+    void NetworkStaticInitializationHandler::unloadModule(ModuleInstance* module)
+    {
+        module->unloadAllStaticallyInitializedInstances(StaticInitialization::NETWORK_FUNCTION);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/NetworkStaticInitializationHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/NetworkStaticInitializationHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/NetworkStaticInitializationHandler.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NetworkStaticInitializationHandler_H__
+#define _NetworkStaticInitializationHandler_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include "core/module/StaticInitializationHandler.h"
+
+namespace orxonox
+{
+    class _NetworkExport NetworkStaticInitializationHandler : public StaticInitializationHandler
+    {
+        public:
+            virtual void setupHandler() override;
+            virtual void shutdownHandler() override;
+
+            virtual void loadModule(ModuleInstance* module) override;
+            virtual void unloadModule(ModuleInstance* module) override;
+    };
+}
+
+#endif /* _NetworkStaticInitializationHandler_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/PeerList.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/PeerList.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/PeerList.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PeerList.h"
+
+#include <cstdio>
+#include "util/Output.h"
+#include "network/packet/ServerInformation.h"
+
+namespace orxonox
+{
+  PeerList::PeerList() { }
+  PeerList::~PeerList() { }
+
+  int
+  PeerList::addPeer( ENetPeer *toadd )
+  { /* error correction */
+    if( toadd == nullptr )
+    { orxout(internal_error, context::master_server) << "PeerList::addPeer: empty peer given." << endl;
+      return -1;
+    }
+
+    /* if all went well, push to back of list */
+    this->peerlist.push_back( toadd );
+    return 0;
+  }
+
+  bool sub_compAddr( ENetAddress addr1, ENetAddress addr2 )
+  {
+    for( int i = 0; i < 16; ++i )
+      if( addr1.host.addr[i] < addr2.host.addr[i] )
+        return -i;
+      else if( addr1.host.addr[i] > addr2.host.addr[i] )
+        return i;
+
+    return 0;
+  }
+
+
+  bool
+  PeerList::remPeerByAddr( ENetAddress addr )
+  {
+    /* loop through list elements */
+    for( ENetPeer* peer : peerlist )
+      if( !sub_compAddr(peer->address, addr ) )
+      { /* found this name, remove and quit */
+        this->peerlist.remove( peer );
+        return true;
+      }
+
+    /* not found */
+    return false;
+  }
+
+  ENetPeer *
+  PeerList::findPeerByAddr( ENetAddress addr )
+  {
+    /* loop through list elements */
+    for( ENetPeer* peer : peerlist )
+      if( !sub_compAddr(peer->address, addr ) )
+        /* found this name, remove and quit */
+        return peer;
+
+    /* not found */
+    return nullptr;
+  }
+
+  int
+  PeerList::count(){
+    return this->peerlist.size();
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/PeerList.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/PeerList.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/PeerList.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PeerList_
+#define _PeerList_
+
+#include <list>
+#include <string>
+#include <enet/enet.h>
+
+/* peer list */
+namespace orxonox
+{
+  /** This class keeps a list of open connections
+   * and some info about them.
+   */
+  class PeerList
+  { public:
+      /** constructor */
+      PeerList();
+
+      /** destructor */
+      ~PeerList();
+
+      /** \param toadd The peer to add
+       * \return 0 for success, -1 for error.
+       *
+       * Add new peer to list
+       */
+      int addPeer( ENetPeer *toadd );
+
+      /** \param addr Address to look for
+       * \return if the peer was found or not
+       *
+       * Remove peer from list by address
+       */
+      bool remPeerByAddr( ENetAddress addr );
+
+      /** \param addr The address to find by
+       *
+       * Find a connection by address
+       */
+      ENetPeer *findPeerByAddr( ENetAddress addr );
+
+      /**
+       * Count current peers
+       */
+       int count();
+
+      /* NOTE: making this list public so it can easily
+       * be iterated. This makes sense since iterating it
+       * will happen all the time, and using getter methods
+       * for the next in list would slow things down unnecessarily.
+       */
+      /** the list of servers for internal storage */
+      std::list<ENetPeer *> peerlist;
+    private:
+      /* nothing so far. */
+  };
+}
+
+
+
+#endif /* _PeerList_ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/Server.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Server.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Server.cc	(revision 11817)
@@ -0,0 +1,455 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Implementation: Server
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "Server.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <enet/enet.h>
+#include <cassert>
+#include <string>
+
+#include "util/Clock.h"
+#include "util/Output.h"
+#include "core/command/Executor.h"
+#include "packet/Chat.h"
+#include "packet/ClassID.h"
+#include "packet/DeleteObjects.h"
+#include "packet/FunctionIDs.h"
+#include "packet/Gamestate.h"
+#include "packet/Welcome.h"
+// #include "ClientInformation.h"
+#include "FunctionCallManager.h"
+#include "GamestateManager.h"
+
+namespace orxonox
+{
+  const unsigned int MAX_FAILURES = 20;
+
+  /**
+  * Constructor for default values (bindaddress is set to ENET_HOST_ANY
+  *
+  */
+  Server::Server()
+  {
+    this->timeSinceLastUpdate_=0;
+  }
+
+  Server::Server(int port)
+  {
+    this->setPort( port );
+    this->timeSinceLastUpdate_=0;
+  }
+/*
+  Server::Server(int port, const std::string name)
+  {
+    this->setPort( port );
+    this->timeSinceLastUpdate_=0;
+    this->serverName_=name;
+  }*/
+  /**
+  * Constructor
+  * @param port Port to listen on
+  * @param bindAddress Address to listen on
+  */
+  Server::Server(int port, const std::string& bindAddress)
+  {
+    this->setPort( port );
+    this->setBindAddress( bindAddress );
+    this->timeSinceLastUpdate_=0;
+  }
+
+  /**
+  * @brief Destructor
+  */
+  Server::~Server()
+  {
+  }
+
+  /**
+  * This function opens the server by creating the listener thread
+  */
+  void Server::open()
+  {
+    Host::setActive(true);
+    orxout(verbose, context::network) << "opening server" << endl;
+    this->openListener();
+
+    /* make discoverable on LAN */
+    LANDiscoverable::setActivity(true);
+    LANDiscoverable::updateClientNumber(0);
+
+    /* make discoverable on WAN */
+    WANDiscoverable::setActivity(true);
+    WANDiscoverable::updateClientNumber(0);
+
+    /* done */
+    return;
+  }
+
+  /**
+  * This function closes the server
+  */
+  void Server::close()
+  {
+    Host::setActive(false);
+    orxout(verbose, context::network) << "closing server" << endl;
+    this->disconnectClients();
+    this->closeListener();
+
+    /* tell master server we're closing */
+    orxout(internal_info, context::network) << "disconnecting." << endl;
+    WANDiscoverable::setActivity(false);
+    orxout(internal_info, context::network) << "disconnecting done" << endl;
+
+    LANDiscoverable::setActivity(false);
+    return;
+  }
+
+  /**
+  * Run this function once every tick
+  * calls processQueue and updateGamestate
+  * @param time time since last tick
+  */
+  void Server::update(const Clock& time)
+  {
+    // receive incoming packets
+    Connection::processQueue();
+
+    // receive and process incoming discovery packets
+    LANDiscoverable::update();
+
+    if ( GamestateManager::hasPeers() )
+    {
+      // process incoming gamestates
+      GamestateManager::processGamestates();
+      FunctionCallManager::processBufferedFunctionCalls();
+
+      // send function calls to clients
+      FunctionCallManager::sendCalls( static_cast<Host*>(this) );
+
+      //this steers our network frequency
+      timeSinceLastUpdate_+=time.getDeltaTime();
+      if(timeSinceLastUpdate_>=NETWORK_PERIOD)
+      {
+        timeSinceLastUpdate_ -= static_cast<unsigned int>( timeSinceLastUpdate_ / NETWORK_PERIOD ) * NETWORK_PERIOD;
+        updateGamestate();
+      }
+//       sendPackets(); // flush the enet queue
+    }
+  }
+
+  void Server::queuePacket(ENetPacket *packet, int clientID, uint8_t channelID)
+  {
+    ServerConnection::addPacket(packet, clientID, channelID);
+  }
+
+  /**
+   * @brief: returns ping time to client in milliseconds
+   */
+  unsigned int Server::getRTT(unsigned int clientID)
+  {
+//     assert(ClientInformation::findClient(clientID));
+//     return ClientInformation::findClient(clientID)->getRTT();
+    // TODO: reimplement
+    return 0;
+  }
+
+  void Server::printRTT()
+  {
+//     for( ClientInformation* temp=ClientInformation::getBegin(); temp!=nullptr; temp=temp->next() )
+//       orxout(message) << "Round trip time to client with ID: " << temp->getID() << " is " << temp->getRTT() << " ms" << endl;
+  }
+
+  /**
+   * @brief: return packet loss ratio to client (scales from 0 to 1)
+   */
+  float Server::getPacketLoss(unsigned int clientID)
+  {
+//     assert(ClientInformation::findClient(clientID));
+//     return ClientInformation::findClient(clientID)->getPacketLoss();
+    return 0.;
+  }
+
+  /**
+  * takes a new snapshot of the gamestate and sends it to the clients
+  */
+  void Server::updateGamestate()
+  {
+    if( this->clientIDs_.size()==0 )
+      //no client connected
+      return;
+    GamestateManager::update();
+//     orxout(verbose_more, context::network) << "Server: one gamestate update complete, goig to sendGameState" << endl;
+    //orxout(verbose_more, context::network) << "updated gamestate, sending it" << endl;
+    //if(clients->getGamestateID()!=GAMESTATEID_INITIAL)
+    sendGameStates();
+    sendObjectDeletes();
+//     orxout(verbose_more, context::network) << "Server: one sendGameState turn complete, repeat in next tick" << endl;
+    //orxout(verbose_more, context::network) << "sent gamestate" << endl;
+  }
+
+  /**
+  * sends the current gamestate to all peers
+  */
+  bool Server::sendGameStates()
+  {
+    std::vector<packet::Gamestate*> gamestates = GamestateManager::getGamestates();
+    for( packet::Gamestate* gamestate : gamestates )
+    {
+      gamestate->send(static_cast<Host*>(this));
+    }
+    return true;
+  }
+
+
+  bool Server::sendObjectDeletes()
+  {
+//     ClientInformation *temp = ClientInformation::getBegin();
+//     if( temp == nullptr )
+      //no client connected
+    if( this->clientIDs_.size()==0 )
+      return true;
+    packet::DeleteObjects *del = new packet::DeleteObjects();
+    if(!del->fetchIDs())
+    {
+      delete del;
+      return true;  //everything ok (no deletes this tick)
+    }
+//     orxout(verbose, context::network) << "sending DeleteObjects" << endl;
+//     while(temp != nullptr){
+//       if( !(temp->getSynched()) )
+//       {
+//         orxout(verbose_more, context::network) << "Server: not sending gamestate" << endl;
+//         temp=temp->next();
+//         continue;
+//       }
+//       int cid = temp->getID(); //get client id
+//       packet::DeleteObjects *cd = new packet::DeleteObjects(*del);
+//       assert(cd);
+    del->setPeerID(NETWORK_PEER_ID_BROADCAST);
+    if ( !del->send( static_cast<Host*>(this) ) )
+      orxout(internal_warning, context::network) << "Server: could not broadcast deleteObjects packet" << endl;
+//       temp=temp->next();
+      // gs gets automatically deleted by enet callback
+//     }
+//     delete del;
+    return true;
+  }
+
+
+  void Server::addPeer(uint32_t peerID)
+  {
+//     static unsigned int newid=1;
+//
+//     orxout(internal_info, context::network) << "Server: adding client" << endl;
+//     ClientInformation *temp = ClientInformation::insertBack(new ClientInformation);
+//     if(!temp)
+//     {
+//       orxout(internal_warning, context::network) << "Server: could not add client" << endl;
+//     }
+//     temp->setID(newid);
+//     temp->setPeer(event->peer);
+
+    // inform all the listeners
+    this->clientIDs_.push_back(peerID);
+    WANDiscoverable::updateClientNumber(this->clientIDs_.size());
+    LANDiscoverable::updateClientNumber(this->clientIDs_.size());
+
+    ClientConnectionListener::broadcastClientConnected(peerID);
+    GamestateManager::addPeer(peerID);
+
+//     ++newid;
+
+    orxout(internal_info, context::network) << "Server: added client id: " << peerID << endl;
+
+    createClient(peerID);
+}
+
+  void Server::removePeer(uint32_t peerID)
+  {
+    orxout(verbose, context::network) << "removing client from list" << endl;
+//     ClientInformation *client = ClientInformation::findClient(&event->peer->address);
+//     if(!client)
+//       return;
+//     else
+//     {
+  std::vector<uint32_t>::iterator it;
+  for( it=this->clientIDs_.begin(); it!=this->clientIDs_.end(); ++it )
+  {
+    if( *it == peerID )
+    {
+      this->clientIDs_.erase(it);
+      break;
+    }
+  }
+  WANDiscoverable::updateClientNumber(this->clientIDs_.size());
+  LANDiscoverable::updateClientNumber(this->clientIDs_.size());
+
+  ClientConnectionListener::broadcastClientDisconnected(peerID);
+  GamestateManager::removePeer(peerID);
+      //ServerConnection::disconnectClient( client );
+      //ClientConnectionListener::broadcastClientDisconnected( client->getID() ); //this is done in ClientInformation now
+//       delete client;
+//     }
+  }
+
+  void Server::processPacket(packet::Packet* packet)
+  {
+    if( packet->isReliable() )
+    {
+      if( this->getLastReceivedGamestateID(packet->getPeerID()) >= packet->getRequiredGamestateID() )
+        packet->process(static_cast<Host*>(this));
+      else
+        this->packetQueue_.push_back(packet);
+    }
+    else
+      packet->process(static_cast<Host*>(this));
+  }
+
+
+  bool Server::createClient(int clientID)
+  {
+//     ClientInformation *temp = ClientInformation::findClient(clientID);
+//     if(!temp)
+//     {
+//       orxout(internal_error, context::network) << "Server. could not create client with id: " << clientID << endl;
+//       return false;
+//     }
+//     orxout(verbose, context::network) << "Con.Man: creating client id: " << temp->getID() << endl;
+
+    // synchronise class ids
+    syncClassid(clientID);
+
+    // now synchronise functionIDs
+    packet::FunctionIDs *fIDs = new packet::FunctionIDs();
+    fIDs->setPeerID(clientID);
+    bool b = fIDs->send( static_cast<Host*>(this) );
+    assert(b);
+
+//     temp->setSynched(true);
+    GamestateManager::setSynched(clientID);
+
+    orxout(verbose, context::network) << "sending welcome" << endl;
+    packet::Welcome *w = new packet::Welcome(clientID);
+    w->setPeerID(clientID);
+    b = w->send( static_cast<Host*>(this) );
+    assert(b);
+    (void)b; // avoid compiler warning
+//     packet::Gamestate *g = new packet::Gamestate();
+//     g->setPeerID(clientID);
+//     b = g->collectData(0,packet::GAMESTATE_MODE_SERVER);
+//     assert(b);
+//     if(!b)
+//       return false; //no data for the client
+// //     b = g->compressData();
+// //     assert(b);
+//     b = g->send( static_cast<Host*>(this) );
+//     assert(b);
+    return true;
+  }
+
+  void Server::disconnectClient( uint32_t clientID )
+  {
+    ServerConnection::disconnectClient( clientID );
+    GamestateManager::removePeer( clientID );
+    // inform all the listeners
+    // ClientConnectionListener::broadcastClientDisconnected(client->getID()); // this is done in ClientInformation now
+  }
+
+  /**
+   * @brief Sends a chat message to the given target ID.
+   * @param message message to be sent
+   * @param sourceID the ID of the sender
+   * @param targetID the ID of the receiver
+   */
+  void Server::doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
+  {
+    // check if the target exists. just ignore the message otherwise
+    if (!this->isValidTarget(targetID)) // TODO: remove this if an invalid clientIDs don't trigger assertions anymore
+      return;
+
+    // send the message to the target
+    packet::Chat* packet = new packet::Chat(message, sourceID, targetID);
+    packet->setPeerID(targetID);
+    packet->send( static_cast<Host*>(this) );
+
+    // if the target is (or includes) this host as well, call the parent function which passes the message to the listeners
+    if (targetID == NETWORK_PEER_ID_BROADCAST || targetID == Host::getPlayerID())
+      Host::doReceiveChat(message, sourceID, targetID);
+  }
+
+  /**
+   * @brief Gets called if a packet::Chat packet is received. Forwards the packet to the target
+   * and calls the parent function if necessary.
+   */
+  void Server::doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID)
+  {
+      this->doSendChat(message, sourceID, targetID);
+  }
+
+  /**
+   * @brief Returns true if the target ID is in the list of clients (or if it
+   * corresponds to the broadcast or the server ID).
+   */
+  bool Server::isValidTarget(unsigned int targetID)
+  {
+    if (targetID == NETWORK_PEER_ID_BROADCAST || targetID == NETWORK_PEER_ID_SERVER)
+      return true;
+
+    for( uint32_t id : this->clientIDs_ )
+      if( id == targetID )
+        return true;
+
+    return false;
+  }
+
+  void Server::syncClassid(unsigned int clientID)
+  {
+    int failures=0;
+    packet::ClassID *classid = new packet::ClassID();
+    classid->setPeerID(clientID);
+    while(!classid->send( static_cast<Host*>(this) ) && failures < 10){
+      failures++;
+    }
+    assert(failures<10);
+    orxout(verbose, context::network) << "syncClassid:\tall synchClassID packets have been sent" << endl;
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/Server.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/Server.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/Server.h	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Server_H__
+#define _Server_H__
+
+#include "NetworkPrereqs.h"
+
+#include <deque>
+#include <vector>
+
+#include "util/UtilPrereqs.h"
+#include "core/CorePrereqs.h"
+#include "Host.h"
+// #include "GamestateManager.h"
+#include "ServerConnection.h"
+#include "LANDiscoverable.h"
+#include "WANDiscoverable.h"
+
+
+namespace orxonox
+{
+
+  /**
+  * This class is the root class of the network module for a server.
+  * It implements all functions necessary for a Server
+  */
+  class _NetworkExport Server : public Host, public ServerConnection, public LANDiscoverable, public WANDiscoverable
+  {
+  public:
+    Server();
+    Server(int port);
+    Server(int port, const std::string& bindAddress);
+    ~Server();
+
+    void open();
+    void close();
+    virtual void queuePacket(ENetPacket *packet, int clientID, uint8_t channelID) override;
+    virtual bool sendPacket( packet::Packet* packet ) override{ return packet->send( static_cast<Host*>(this) ); }
+    void update(const Clock& time);
+    unsigned int getRTT(unsigned int clientID);
+    virtual void printRTT() override;
+    float getPacketLoss(unsigned int clientID);
+    int getClientCount() { return this->clientIDs_.size();}
+    std::string getServerName() { return this->serverName_;}
+
+  protected:
+    void updateGamestate();
+  private:
+    virtual bool isServer_() override{return true;}
+    unsigned int playerID(){return 0;}
+
+    virtual void addPeer(uint32_t peerID) override;
+    virtual void removePeer(uint32_t peerID) override;
+    virtual void processPacket(packet::Packet* packet) override;
+
+    bool createClient(int clientID);
+    void disconnectClient( uint32_t clientID );
+    bool sendGameStates();
+    bool sendObjectDeletes();
+    bool isValidTarget(unsigned int targetID);
+    virtual void doSendChat(const std::string& message, unsigned int sourceID, unsigned int targetID) override;
+    virtual void doReceiveChat(const std::string& message, unsigned int sourceID, unsigned int targetID) override;
+    void syncClassid(unsigned int clientID);
+
+    float timeSinceLastUpdate_;
+    std::deque<packet::Packet*> packetQueue_;
+    std::vector<uint32_t>       clientIDs_;
+    std::string                 serverName_;
+  };
+
+
+
+
+}
+
+#endif /* _Server_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/ServerConnection.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ServerConnection.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ServerConnection.cc	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ServerConnection.h"
+
+#include <cassert>
+#include <string>
+#define WIN32_LEAN_AND_MEAN
+#include <enet/enet.h>
+
+#include "util/Output.h"
+#include <util/Sleep.h>
+// #include "ClientInformation.h"
+
+namespace orxonox
+{
+
+  ServerConnection::ServerConnection():
+    bListening_(false)
+  {
+    this->bindAddress_ = new ENetAddress();
+//     memset(this->bindAddress_, 0, sizeof(ENetAddress));
+    this->bindAddress_->host = ENET_HOST_ANY;
+    this->bindAddress_->port = NETWORK_PORT;
+    this->bindAddress_->scopeID = 0;
+  }
+
+  ServerConnection::~ServerConnection()
+  {
+    if ( this->bListening_ )
+      closeListener();
+    delete this->bindAddress_;
+  }
+
+  void ServerConnection::setBindAddress( const std::string& bindAddress )
+  {
+    if (enet_address_set_host (this->bindAddress_, bindAddress.c_str()) < 0)
+        orxout(internal_error, context::network) << "Could not resolve \"" << bindAddress << "\"." << endl;
+  }
+
+  void ServerConnection::setPort( unsigned int port ) {
+      this->bindAddress_->port = port;
+  }
+
+  bool ServerConnection::openListener()
+  {
+    // create host
+    this->host_ = enet_host_create(this->bindAddress_, NETWORK_MAX_CONNECTIONS, NETWORK_CHANNEL_COUNT, 0, 0);
+    
+    if ( this->host_ == nullptr )
+    {
+        orxout(internal_error, context::network) << "ServerConnection: host_ == nullptr" << endl;
+        return false;
+    }
+    
+    // enable compression
+    this->enableCompression();
+    assert( this->host_->socket4 != ENET_SOCKET_NULL || this->host_->socket6 != ENET_SOCKET_NULL );
+    if (this->host_->socket4 == ENET_SOCKET_NULL)
+        orxout(internal_warning, context::network) << "IPv4 Socket failed." << endl;
+    else if (this->host_->socket6 == ENET_SOCKET_NULL)
+        orxout(internal_warning, context::network) << "IPv6 Socket failed." << endl;
+    else
+        orxout(internal_info, context::network) << "Using IPv4 and IPv6 Sockets." << endl;
+    
+    // start communication thread
+    Connection::startCommunicationThread();
+
+    return true;
+  }
+
+  bool ServerConnection::closeListener()
+  {
+    this->bListening_=false;
+    disconnectClients();
+    Connection::stopCommunicationThread();
+    enet_host_destroy(this->host_);
+    return true;
+  }
+
+  void ServerConnection::addPacket(ENetPacket *packet, unsigned int clientID, uint8_t channelID)
+  {
+    if ( clientID == NETWORK_PEER_ID_BROADCAST )
+    {
+      broadcastPacket(packet, channelID);
+    }
+    else
+    {
+//       ClientInformation *temp = ClientInformation::findClient(clientID);
+//       if(!temp){
+//         orxout(internal_warning, context::network) << "C.Man: addPacket findClient failed" << endl;
+//       }
+      Connection::addPacket(packet, clientID, channelID);
+    }
+  }
+
+//   void ServerConnection::disconnectClient(ClientInformation *client)
+//   {
+//     Connection::disconnectPeer( client->getPeer() );
+//   }
+
+  void ServerConnection::disconnectClient(int clientID)
+  {
+//     ClientInformation *client = ClientInformation::findClient(clientID);
+//     if(client)
+    Connection::disconnectPeer(clientID);
+  }
+
+  void ServerConnection::disconnectClients()
+  {
+    Connection::disconnectPeers();
+    Connection::waitOutgoingQueue();
+    return;
+  }
+
+
+//   int ServerConnection::getClientID(ENetPeer* peer)
+//   {
+//     return getClientID(&(peer->address));
+//   }
+
+//   int ServerConnection::getClientID(ENetAddress* address)
+//   {
+//     return ClientInformation::findClient(address)->getID();
+//   }
+// 
+//   ENetPeer *ServerConnection::getClientPeer(int clientID)
+//   {
+//     return ClientInformation::findClient(clientID)->getPeer();
+//   }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/ServerConnection.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ServerConnection.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ServerConnection.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+//
+// C++ Interface: ServerConnection
+//
+// Description:
+//
+//
+// Author:  Oliver Scheuss, (C) 2007
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef _ServerConnection_H__
+#define _ServerConnection_H__
+
+#include "NetworkPrereqs.h"
+#include "Connection.h"
+
+namespace orxonox
+{
+
+  class _NetworkExport ServerConnection : public Connection{
+  public:
+    ~ServerConnection();
+
+    void setBindAddress( const std::string& bindAddress );
+    void setPort( unsigned int port );
+
+    bool openListener();
+    bool closeListener();
+    void addPacket(ENetPacket *packet, unsigned int ID, uint8_t channelID);
+//     virtual void disconnectClient(ClientInformation *client);
+    void disconnectClient(int clientID);
+  protected:
+    ServerConnection();
+    void disconnectClients();
+
+  private:
+//     int getClientID(ENetPeer* peer);
+//     int getClientID(ENetAddress* address);
+//     ENetPeer* getClientPeer(int clientID);
+
+    ENetAddress* bindAddress_;
+
+    bool bListening_;
+
+  };
+
+}
+
+#endif /* _ServerConnection_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/ServerList.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ServerList.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ServerList.cc	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ServerList.h"
+
+namespace orxonox
+{
+  ServerList::ServerList()
+  { /* create a new list */ }
+
+  ServerList::~ServerList()
+  { /* delete the list */
+    serverlist.clear();
+  }
+
+  int
+  ServerList::addServer( packet::ServerInformation toadd,
+    ENetPeer *peer )
+  {
+    ServerListElem toAdd;
+    toAdd.ServerInfo = toadd;
+    toAdd.peer = peer;
+
+    this->serverlist.push_back( toAdd );
+    return 0;
+  }
+
+  bool
+  ServerList::delServerByName( std::string name )
+  {
+    /* get an iterator */
+    std::list<ServerListElem>::iterator i;
+
+    /* loop through list elements */
+    for( i = serverlist.begin(); i != serverlist.end(); ++i )
+      if( (*i).ServerInfo.getServerName() == name )
+      { /* found this name, remove and quit */
+        this->serverlist.erase( i );
+        return true;
+      }
+    return false;
+  }
+
+  bool ServerList::delServerByAddress( std::string address )
+  {
+    /* get an iterator */
+    std::list<ServerListElem>::iterator i;
+
+    /* loop through list elements */
+    for( i = serverlist.begin(); i != serverlist.end(); ++i )
+      if( (*i).ServerInfo.getServerIP() == address )
+      { /* found this name, remove and quit */
+        this->serverlist.erase( i );
+        return true;
+      }
+    return false;
+  }
+
+  /* SEARCHING */
+  ServerListSearchResult
+  ServerList::findServerByAddress( std::string address )
+  {
+    /* get an iterator */
+    std::list<ServerListElem>::iterator i;
+
+    /* loop through list elements */
+    for( i = serverlist.begin(); i != serverlist.end(); ++i )
+      if( (*i).ServerInfo.getServerIP() == address )
+      { /* found the target, return it */
+        ServerListSearchResult res = { (*i), true };
+        return res;
+      }
+
+    /* no success */
+    ServerListSearchResult res = { (*i), false };
+    return res;
+  }
+
+  ServerListSearchResult
+  ServerList::findServerByName( std::string name )
+  {
+    /* get an iterator */
+    std::list<ServerListElem>::iterator i;
+
+    /* iterate, return when name found */
+    /* loop through list elements */
+    for( i = serverlist.begin(); i != serverlist.end(); ++i )
+      if( (*i).ServerInfo.getServerName() == name )
+      {
+        ServerListSearchResult res = { (*i), true };
+        return res;
+      }
+
+    /* no luck, return a struct that tells the caller so */
+    ServerListSearchResult res = { (*i), false };
+    return res;
+  }
+
+  /* SORTING */
+  /* sort by name */
+  bool sub_compare_names( ServerListElem no1,
+    ServerListElem no2 )
+  { return no1.ServerInfo.getServerName() > no2.ServerInfo.getServerName(); }
+
+  void ServerList::sortByName()
+  {
+    this->serverlist.sort( sub_compare_names );
+  }
+
+  /* sort by ping */
+  bool sub_compare_pings( ServerListElem no1,
+    ServerListElem no2 )
+  {
+    return no1.ServerInfo.getServerRTT() > no2.ServerInfo.getServerRTT();
+  }
+
+  void ServerList::sortByPing()
+  {
+    this->serverlist.sort( sub_compare_pings );
+  }
+
+  bool ServerList::setNameByAddress( std::string address, std::string name  ){
+    /* get an iterator */
+    std::list<ServerListElem>::iterator i;
+
+    /* loop through list elements */
+    for( i = serverlist.begin(); i != serverlist.end(); ++i )
+      if( (*i).ServerInfo.getServerIP() == address )
+      { /* found this adress, rename and quit */
+        (*i).ServerInfo.setServerName( name );
+        return true;
+      }
+    return false;
+  };
+
+  bool ServerList::setClientsByAddress( std::string address, int clientNumber ){
+    /* get an iterator */
+    std::list<ServerListElem>::iterator i;
+
+    /* loop through list elements */
+    for( i = serverlist.begin(); i != serverlist.end(); ++i )
+      if( (*i).ServerInfo.getServerIP() == address )
+      { /* found this adress, rename and quit */
+        (*i).ServerInfo.setClientNumber( clientNumber );
+        return true;
+      }
+    return false;
+  };
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/ServerList.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/ServerList.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/ServerList.h	(revision 11817)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ServerList_
+#define _ServerList_
+
+#include <list>
+#include <string>
+#include <network/packet/ServerInformation.h>
+
+/* methods necessary */
+namespace orxonox
+{
+  /* HELPER STRUCTURES */
+  struct ServerListElem
+  {
+    /* server information (name, IP, etc) */
+    packet::ServerInformation ServerInfo;
+
+    /* peer pointer */
+    ENetPeer* peer;
+  };
+
+  struct ServerListSearchResult
+  {
+    /* list element found */
+    ServerListElem result;
+
+    /* successful search */
+    bool success;
+  };
+
+
+
+
+
+  /** This class is keeps a list of game servers
+   * and some info about them.
+   */
+  class ServerList
+  { public:
+      /** constructor */
+      ServerList();
+
+      /** destructor */
+      ~ServerList();
+
+
+      /* BASIC MANIPULATION */
+      /** \param toadd the server to add.
+       *  \param peer the peer
+       *
+       * Add server to the game server list
+       */
+      int addServer( packet::ServerInformation toadd,
+        ENetPeer *peer );
+
+      /** \param name Name of the server to remove
+       *
+       * Remove server by name
+       */
+      bool delServerByName( std::string name );
+
+      /** \param address IP address of the server to remove
+       *
+       * Remove server by address
+       */
+      bool delServerByAddress( std::string address );
+
+      bool setNameByAddress( std::string address, std::string name  );
+
+      bool setClientsByAddress( std::string address, int clientNumber );
+
+      /* SEARCHING */
+      /* \param address The address of the server that is to be
+       *  found
+       * \return A struct containing a result of the search and a boolean
+       *  that is only true if the search was successful
+       *
+       * Find and return the list handle of a given address.
+       */
+      ServerListSearchResult
+      findServerByAddress( std::string address );
+
+
+      /* \param name The name of the server that is to be
+       *  found
+       * \return The struct containing the list entry of the server
+       *
+       * Find and return the list handle of a given name.
+       */
+      ServerListSearchResult
+      findServerByName( std::string name );
+
+
+      /* SORTING */
+      /** sort by name  */
+      void sortByName();
+
+      /** sort by ping */
+      void sortByPing();
+
+      /** the list of servers for internal storage */
+      std::list<ServerListElem> serverlist;
+    private:
+  };
+}
+
+#endif /*_ServerList_*/
Index: /code/branches/RacingBots_FS18/src/libraries/network/TODO
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/TODO	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/TODO	(revision 11817)
@@ -0,0 +1,11 @@
+todo: 
+	test network functionality with paketloss/delay: http://www.linuxfoundation.org/en/Net:Netem#Packet_loss
+
+	minimize synchronisableHeader
+
+	!!! ensure that objects get synched, when newly created, even if not their tick
+
+	setvariable mode
+	objectmode
+	priorities (put into gamestatehandler)
+		manage delete object handling (only send deletes of acked objects)
Index: /code/branches/RacingBots_FS18/src/libraries/network/TrafficControl.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/TrafficControl.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/TrafficControl.cc	(revision 11817)
@@ -0,0 +1,328 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TrafficControl.h"
+
+#include <cassert>
+#include <functional>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "synchronisable/Synchronisable.h"
+
+namespace orxonox {
+
+  static constexpr unsigned int SCHED_PRIORITY_OFFSET = static_cast<unsigned int>(-1);
+  namespace arg = std::placeholders;
+
+  objInfo::objInfo(uint32_t ID, uint32_t creatorID, int32_t curGsID, int32_t diffGsID, uint32_t size, unsigned int prioperm, unsigned int priosched)
+  {
+    objID = ID; objCreatorID = creatorID; objCurGS = curGsID; objDiffGS = diffGsID; objSize = size; objValuePerm = prioperm; objValueSched = priosched;
+  }
+
+  objInfo::objInfo()
+  {
+    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objCurGS = GAMESTATEID_INITIAL; objDiffGS = objCurGS; objSize = 0; objValuePerm = 0; objValueSched = 0;
+  }
+
+
+
+  obj::obj()
+  {
+    objID = OBJECTID_UNKNOWN; objCreatorID = OBJECTID_UNKNOWN; objSize = 0; objDataOffset = 0;
+  }
+  obj::obj( uint32_t ID, uint32_t creatorID, uint32_t size, uint32_t offset )
+  {
+    objID = ID; objCreatorID = creatorID; objSize = size; objDataOffset = offset;
+  }
+
+/**
+*Initializing protected members
+*/
+    TrafficControl *TrafficControl::instance_=nullptr;
+
+    /**
+    * @brief Constructor: assures that only one reference will be created and sets the pointer
+    */
+    TrafficControl::TrafficControl()
+    {
+    RegisterObject(TrafficControl);
+      assert(instance_==nullptr);
+      instance_=this;
+    this->setConfigValues();
+    }
+
+    /**
+    * @brief Destructor: resets the instance pointer to nullptr
+    */
+    TrafficControl::~TrafficControl()
+    {
+      instance_=nullptr;
+    }
+
+/**
+*Definition of public members
+*/
+
+  void TrafficControl::setConfigValues()
+  {
+    SetConfigValue ( bActive_, false );
+    SetConfigValue ( targetSize, 10000 );
+  }
+
+  /**
+  * sort-algorithm for sorting the objectlist after priorities
+  */
+  bool TrafficControl::prioritySort(uint32_t clientID, obj i, obj j)
+  {
+    assert(clientListPerm_.find(clientID) != clientListPerm_.end());  //make sure the client exists in our list
+    assert(clientListPerm_[clientID].find(i.objID) != clientListPerm_[clientID].end()); // make sure the object i is in the client list
+    assert(clientListPerm_[clientID].find(j.objID) != clientListPerm_[clientID].end()); // make sure the object j is in the client list
+
+    int prio1 = clientListPerm_[clientID][i.objID].objValuePerm + clientListPerm_[clientID][i.objID].objValueSched;
+    int prio2 = clientListPerm_[clientID][j.objID].objValuePerm + clientListPerm_[clientID][j.objID].objValueSched;
+    return prio1 < prio2;
+  }
+
+  /**
+  * sort-algorithm for sorting the objectList after position in original data stream
+  */
+  bool TrafficControl::dataSort(obj i, obj j)
+  {
+    int pos1 = i.objDataOffset;
+    int pos2 = j.objDataOffset;
+    return pos1 < pos2;
+  }
+
+
+
+    void TrafficControl::processObjectList(unsigned int clientID, unsigned int gamestateID, std::list<obj>& list)
+    {
+      currentClientID=clientID;
+      currentGamestateID=gamestateID;
+      evaluateList(clientID, list);
+      return;
+    }
+
+  TrafficControl *TrafficControl::getInstance()
+  {
+    assert(instance_);
+    return instance_;
+  }
+
+    void TrafficControl::ack(unsigned int clientID, unsigned int gamestateID)
+    {
+    if ( !this->bActive_ )
+      return;
+      std::list<obj>::iterator itvec;  // iterator to iterate through the acked objects
+
+    //assertions to make sure the maps already exist
+    assert(clientListTemp_.find(clientID) != clientListTemp_.end() );
+    assert(clientListPerm_.find(clientID) != clientListPerm_.end() );
+    assert( clientListTemp_[clientID].find(gamestateID) != clientListTemp_[clientID].end() );
+
+    // shortcut for maps
+    std::map<unsigned int, objInfo >& objectListPerm = clientListPerm_[clientID];
+    std::map<unsigned int, std::list<obj>>& objectListTemp = clientListTemp_[clientID];
+
+    for(itvec = objectListTemp[gamestateID].begin(); itvec != objectListTemp[gamestateID].end(); itvec++)
+      {
+      if(objectListPerm.find(itvec->objID) != objectListPerm.end()) // check whether the obj already exists in our lists
+      {
+        objectListPerm[itvec->objID].objCurGS = gamestateID;
+        objectListPerm[itvec->objID].objValueSched = 0; //set scheduling value back
+      }
+      else
+      {
+        assert(0);
+        objectListPerm[itvec->objID].objCurGS = gamestateID;
+        objectListPerm[itvec->objID].objID = itvec->objID;
+        objectListPerm[itvec->objID].objCreatorID = itvec->objCreatorID;
+        objectListPerm[itvec->objID].objSize = itvec->objSize;
+      }
+      }
+       // remove temporary list (with acked objects) from the map
+    objectListTemp.erase( objectListTemp.find(gamestateID) );
+    }
+
+/**
+*Definition of private members
+*/
+
+    /**
+    *updateClientListPerm
+    *returns void
+    */
+    void TrafficControl::insertinClientListPerm(unsigned int clientID, obj objinf)
+    {
+      std::map<unsigned int,std::map<unsigned int, objInfo>>::iterator itperm;//iterator clientListPerm over clientIDs
+    unsigned int gsid=GAMESTATEID_INITIAL, gsdiff=currentGamestateID, prioperm=Synchronisable::getSynchronisable(objinf.objID)->getPriority(), priomom=0;
+    clientListPerm_[clientID][objinf.objID] = objInfo(objinf.objID, objinf.objCreatorID,gsid,gsdiff, objinf.objSize,prioperm,priomom);
+    }
+
+  /**
+  * updateClientListTemp
+  * takes the shortened list which will be sent to the gsmanager and puts the *info into clientListTemp
+  */
+  void TrafficControl::updateClientListTemp(std::list<obj>& list)
+  {
+    clientListTemp_[currentClientID][currentGamestateID] = list;
+  }
+
+  /**
+  *cut
+  *takes the current list that has to be returned to the gsmanager and shortens it in criteria of bandwidth of clientID(XY)
+  */
+  void TrafficControl::cut(std::list<obj>& list, unsigned int targetsize)
+  {
+    unsigned int size=0;
+    std::list<obj>::iterator itvec, ittemp;
+    assert(!list.empty());
+    for(itvec = list.begin(); itvec != list.end();)
+    {
+      assert( itvec->objSize < 1000);
+      if ( ( size + itvec->objSize ) < targetsize )
+      {
+        size += itvec->objSize;//objSize is given in bytes
+        ++itvec;
+      }
+      else
+      {
+        clientListPerm_[currentClientID][itvec->objID].objValueSched += SCHED_PRIORITY_OFFSET; // NOTE: SCHED_PRIORITY_OFFSET is negative
+        list.erase(itvec, list.end());
+        break;
+      }
+//       printList(list, currentClientID);
+    }
+    assert(!list.empty());
+  }
+
+
+    /**
+    *evaluateList evaluates whether new obj are there, whether there are things to be updatet and manipulates all this.
+    */
+    void TrafficControl::evaluateList(unsigned int clientID, std::list<obj>& list)
+    {
+
+    if( bActive_ )
+    {
+      //now the sorting
+
+      //compare listToProcess vs clientListPerm
+      //if listToProcess contains new Objects, add them to clientListPerm
+      std::list<obj>::iterator itvec;
+
+      std::map<unsigned int, objInfo >& objectListPerm = clientListPerm_[clientID];
+
+      for( itvec=list.begin(); itvec != list.end(); itvec++)
+      {
+        if ( objectListPerm.find( itvec->objID) != objectListPerm.end() )
+        {
+        // we already have the object in our map
+        //obj bleibt in liste und permanente prio wird berechnet
+          objectListPerm[itvec->objID].objDiffGS = currentGamestateID - objectListPerm[itvec->objID].objCurGS;
+          continue;//check next objId
+        }
+        else
+        {
+        // insert the object into clientListPerm
+          insertinClientListPerm(clientID,*itvec);
+          continue;//check next objId
+        }
+      }
+    //end compare listToProcess vs clientListPerm
+
+      //sort copied list according to priorities
+      // use std::bind here because we need to pass a memberfunction to stl sort
+//       sort( list.begin(), list.end(), std::bind(&TrafficControl::prioritySort, this, clientID, arg::_1, arg::_2) );
+      list.sort( std::bind(&TrafficControl::prioritySort, this, clientID, arg::_1, arg::_2) );
+
+//       list.sort(std::bind(&TrafficControl::prioritySort, this, clientID, arg::_1, arg::_2) );
+
+      //now we check, that the creator of an object always exists on a client
+      std::list<obj>::iterator itcreator;
+      for(itvec = list.begin(); itvec != list.end(); itvec++)
+      {
+        fixCreatorDependencies(itvec, list, clientID);
+      }
+      //end of sorting
+      //now the cutting, work the same obj out in processobjectlist and copiedlist, compression rate muss noch festgelegt werden.
+//       printList(list, clientID);
+      cut(list, targetSize);
+      //now sort again after objDataOffset
+//       sort(list.begin(), list.end(), std::bind(&TrafficControl::dataSort, this, arg::_1, arg::_2) );
+      list.sort( std::bind(&TrafficControl::dataSort, this, arg::_1, arg::_2) );
+
+      //diese Funktion updateClientList muss noch gemacht werden
+      updateClientListTemp(list);
+      //end of sorting
+    }
+  }
+
+  void TrafficControl::printList(std::list<obj>& list, unsigned int clientID)
+  {
+    std::list<obj>::iterator it;
+    orxout(debug_output, context::network) << "=========== Objectlist ===========" << endl;
+    for( it=list.begin(); it!=list.end(); it++)
+      orxout(debug_output, context::network) << "ObjectID: " << it->objID << " creatorID: " << it->objCreatorID << " Priority: " << clientListPerm_[clientID][it->objID].objValuePerm + clientListPerm_[clientID][it->objID].objValueSched << " size: " << it->objSize << endl;
+  }
+
+  void TrafficControl::fixCreatorDependencies(std::list<obj>::iterator it1, std::list<obj>& list, unsigned int clientID)
+  {
+    if ( it1->objCreatorID == OBJECTID_UNKNOWN )
+      return;
+    if( clientListPerm_[clientID][it1->objCreatorID].objCurGS != GAMESTATEID_INITIAL )
+      return;
+    std::list<obj>::iterator it2, it3=it1;
+    for( it2 = ++it3; it2 != list.end(); it2++ )
+    {
+      if( it2->objID == it1->objCreatorID )
+      {
+        it3 = list.insert(it1, *it2); //insert creator before it1
+        list.erase(it2);
+//         printList(list, clientID);
+        fixCreatorDependencies( it3, list, clientID );
+        break;
+      }
+    }
+  }
+
+  void TrafficControl::clientDisconnected(unsigned int clientID)
+  {
+    if( clientListPerm_.find(clientID) == clientListPerm_.end() )
+    {
+      assert(!this->bActive_);
+      return;
+    }
+    clientListTemp_.erase(clientListTemp_.find(clientID));
+    if( clientListTemp_.find(clientID) != clientListTemp_.end() )
+      clientListPerm_.erase(clientListPerm_.find(clientID));
+  }
+
+
+}//namespace network
Index: /code/branches/RacingBots_FS18/src/libraries/network/TrafficControl.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/TrafficControl.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/TrafficControl.h	(revision 11817)
@@ -0,0 +1,142 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
+ *   Co-authors:
+ *      ...
+ *
+
+ */
+#ifndef _TrafficControl_H__
+#define _TrafficControl_H__
+
+#include "NetworkPrereqs.h"
+
+#include <list>
+#include <map>
+#include "ClientConnectionListener.h"
+
+namespace orxonox {
+
+
+  /**
+   *a list of objects of this type will be given by the Server's Gamestate Manager
+   */
+  class objInfo
+  {
+    public:
+      uint32_t objID;
+      uint32_t objCreatorID;
+      uint32_t objCurGS;//current GameState ID
+      uint32_t objDiffGS;//difference between current and latest GameState
+      uint32_t objSize;
+      int objValuePerm;
+      int objValueSched;
+      objInfo(uint32_t ID, uint32_t creatorID, int32_t curGsID, int32_t diffGsID, uint32_t size, unsigned int prioperm, unsigned int priosched);
+      objInfo();
+  };
+
+/**
+   *a list of objects of this type will be given by the Server's Gamestate Manager
+ */
+  class obj
+  {
+    public:
+      uint32_t objID;
+      uint32_t objCreatorID;
+      uint32_t objSize;
+      uint32_t objDataOffset;
+      obj();
+      obj( uint32_t ID, uint32_t creatorID, uint32_t size, uint32_t offset );
+  };
+
+
+
+
+/**
+*
+*/
+class TrafficControl : public ClientConnectionListener {
+  private:
+
+    /**
+    *permanent client list: contains client ids, object ids and objectInfos (in this order)
+    */
+    std::map<unsigned int, std::map<unsigned int, objInfo >> clientListPerm_;
+    //has to be created with constructor and then needs to be updated by evaluateList().
+
+    /**
+    *temporary client list: contains client ids, gamestate ids and object ids (in this order)
+    */
+    std::map<unsigned int, std::map<unsigned int, std::list<obj>>> clientListTemp_;
+
+    /**updateReferenceList
+    *currentGamestateID and currentClientID will be defined as soon as TrafficControl is being called by Server
+    */
+    unsigned int currentGamestateID;
+    unsigned int currentClientID;
+    unsigned int targetSize;
+    bool         bActive_;
+
+    void insertinClientListPerm(unsigned int clientID, obj objinf);
+
+    void cut(std::list<obj>& list, unsigned int targetsize);
+    void updateClientListTemp(std::list<obj>& list);//done
+    /**
+    *evaluates Data given (list) and produces result(->Data to be updated)
+    */
+    void evaluateList(unsigned int clientID, std::list<obj>& list);//done
+    void ack(unsigned int clientID, unsigned int gamestateID);  // this function gets called when the server receives an ack from the client
+
+    //ClientConnectionListener functions
+    virtual void clientConnected(unsigned int clientID) override{};
+    virtual void clientDisconnected(unsigned int clientID) override;
+
+
+  protected:
+    static TrafficControl *instance_;
+
+  public:
+    TrafficControl();
+    virtual ~TrafficControl();
+    /**
+    *is being used by GSManager from Server:
+    *list contains: ObjIds, CreatorIds, Size (in this order) from Client XY
+    *Elements of list are accessed by *list[i]
+    *Elements of struct i are therefore: *list[i].objID
+    */
+    void setConfigValues();
+    static TrafficControl *getInstance();
+    void processObjectList(unsigned int clientID, unsigned int gamestateID, std::list<obj>& list); //gets a pointer to the list (containing objectIDs) and sorts it
+    static void processAck(unsigned int clientID, unsigned int gamestateID)
+    { return instance_->ack(clientID, gamestateID); }
+    void deleteObject(unsigned int objectID);               // this function gets called when an object has been deleted (in order to clean up lists and maps)
+
+    bool prioritySort(uint32_t clientID, obj i, obj j);
+    bool dataSort(obj i, obj j);
+    void printList(std::list<obj>& list, unsigned int clientID);
+    void fixCreatorDependencies(std::list<obj>::iterator it, std::list<obj>& list, unsigned int clientID);
+};
+
+}
+
+#endif /* _TrafficControl_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/WANDiscoverable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/WANDiscoverable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/WANDiscoverable.cc	(revision 11817)
@@ -0,0 +1,136 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      Oliver Scheuss (original)
+ *
+ */
+
+#include "WANDiscoverable.h"
+
+#include <enet/enet.h>
+#include <cstring>
+
+#include "MasterServerProtocol.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+
+
+namespace orxonox
+{
+  RegisterAbstractClass(WANDiscoverable).inheritsFrom<Configurable>();
+
+  WANDiscoverable::WANDiscoverable(): bActive_(false)
+  {
+    /* debugging output */
+    orxout(verbose, context::master_server) << "Creating WANDiscoverable." << endl;
+
+    /* register object in orxonox */
+    RegisterObject(WANDiscoverable);
+
+    /* check for the masterserver address option in orxonox.ini */
+    this->setConfigValues();
+
+  }
+
+  void WANDiscoverable::setConfigValues()
+  {
+    /* update msaddress string from orxonox.ini config file, if it
+     * has changed.
+     */
+    SetConfigValueExternal(msaddress, "Discovery", "msaddress", "orxonox.net");
+    SetConfigValueExternal(ownName, "Discovery", "ownName", "OrxServer");
+  }
+
+  WANDiscoverable::~WANDiscoverable()
+  {
+    if( this->bActive_ )
+      this->disconnect();
+  }
+
+  void WANDiscoverable::setActivity(bool bActive)
+  {
+    if( bActive==this->bActive_ )
+      return;
+
+    if( bActive )
+    {
+      if( this->connect() )
+        this->bActive_ = true;
+    }
+    else
+    {
+      this->disconnect();
+      this->bActive_ = false;
+    }
+  }
+
+  bool WANDiscoverable::connect()
+  {
+    /* initialize it and see if it worked */
+    if( msc.initialize() )
+    {
+      orxout(internal_error, context::master_server) << "Could not initialize master server communications!" << endl;
+      return false;
+    }
+
+    /* connect and see if it worked */
+    if( msc.connect( this->msaddress.c_str(), ORX_MSERVER_PORT ) )
+    {
+      orxout(internal_error, context::master_server) << "Could not connect to master server at "
+                 << this->msaddress << endl;
+      return false;
+    }
+
+    /* debugging output */
+    orxout(verbose, context::master_server) << "Initialization of WANDiscoverable complete." << endl;
+
+    // Now register the server at the master server
+    this->msc.sendRequest( MSPROTO_GAME_SERVER " " MSPROTO_REGISTER_SERVER );
+
+    std::string request = MSPROTO_GAME_SERVER " " MSPROTO_SET_NAME " ";
+    request += this->ownName;
+    this->msc.sendRequest( request );
+
+    return true;
+  }
+
+  void WANDiscoverable::disconnect()
+  {
+    this->msc.sendRequest( MSPROTO_GAME_SERVER " " MSPROTO_SERVERDC );
+    msc.disconnect();
+  }
+
+  void WANDiscoverable::updateClientNumber(int clientNumber)
+  {
+    orxout(verbose, context::master_server) << "Sending new number of clients: " << clientNumber << endl;
+    std::string request = MSPROTO_GAME_SERVER " " MSPROTO_SET_CLIENTS " ";
+    request += Ogre::StringConverter::toString(clientNumber);
+
+    this->msc.sendRequest( request );
+  }
+
+
+
+
+} // namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/WANDiscoverable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/WANDiscoverable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/WANDiscoverable.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software Foundation, Inc., 51
+ *   Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      Oliver Scheuss (original)
+ *
+ */
+
+#ifndef _WANDiscoverable_H__
+#define _WANDiscoverable_H__
+
+#include "NetworkPrereqs.h"
+#include "core/config/Configurable.h"
+#include "MasterServerComm.h"
+#include <OgreStringConverter.h>
+
+namespace orxonox
+{
+
+  class _NetworkExport WANDiscoverable: public Configurable
+  {
+    public:
+      /** constructor */
+      WANDiscoverable();
+
+      /** destructor */
+      ~WANDiscoverable();
+
+      /** \return Address of the master server
+       *
+       * Get the master server address
+       */
+      std::string getMSAddress()
+      { return this->msaddress; }
+
+      /** Function used for the configuration file parameter update */
+      void setConfigValues();
+
+      /** Function used to set the activity/discoverability */
+      void setActivity( bool bActive );
+
+      void updateClientNumber(int clientNumber);
+
+      /** Master server communications object */
+      MasterServerComm msc;
+
+    private:
+      /** Function used to connect to the master server */
+      bool connect();
+
+      /** Function used to disconnect from the master server */
+      void disconnect();
+
+      /** master server address */
+      std::string msaddress;
+      std::string ownName;
+      bool        bActive_;
+
+  };
+
+}
+
+#endif // _WANDiscoverable_H__
Index: /code/branches/RacingBots_FS18/src/libraries/network/WANDiscovery.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/WANDiscovery.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/WANDiscovery.cc	(revision 11817)
@@ -0,0 +1,187 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      Oliver Scheuss (original)
+ *
+ */
+
+#include "WANDiscovery.h"
+
+#include <enet/enet.h>
+#include <cstring>
+
+#include "core/CoreIncludes.h"
+
+
+namespace orxonox
+{
+  RegisterAbstractClass(WANDiscovery).inheritsFrom<Configurable>();
+
+  WANDiscovery::WANDiscovery()
+  {
+    /* debugging output */
+    orxout(verbose, context::master_server) << "Creating WANDiscovery." << endl;
+
+    /* register object in orxonox */
+    RegisterObject(WANDiscovery);
+
+    /* check for the masterserver address option in orxonox.ini */
+    this->setConfigValues();
+
+    /* initialize it and see if it worked */
+    if( msc.initialize() )
+      orxout(internal_error, context::master_server) << "Could not initialize master server communications!" << endl;
+
+    /* connect and see if it worked */
+    if( msc.connect( this->msaddress.c_str(), ORX_MSERVER_PORT ) )
+      orxout(internal_error, context::master_server) << "Could not connect to master server at "
+        << this->msaddress << endl;
+
+    /* debugging output */
+    orxout(verbose, context::master_server) << "Initialization of WANDiscovery complete." << endl;
+  }
+
+  void WANDiscovery::setConfigValues()
+  {
+    /* update msaddress string from orxonox.ini config file, if it
+     * has changed.
+     */
+    SetConfigValue( msaddress, "master.orxonox.net");
+  }
+
+  WANDiscovery::~WANDiscovery()
+  {
+    /* clear server list */
+    this->servers_.clear();
+  }
+
+  /* callback for the network reply poller */
+  int WANDiscovery::rhandler( char *addr, ENetEvent *ev )
+  {
+    /* error recognition */
+    if( !ev || !ev->packet || !ev->packet->data )
+    { orxout(internal_warning, context::master_server) << "Bad arguments received in WANDiscovery's reply handler." << endl;
+      return 0;
+    }
+
+    /* handle incoming data */
+    /* if a list entry arrives add to list */
+    if( !strncmp( (char*)ev->packet->data, MSPROTO_SERVERLIST_ITEM,
+      MSPROTO_SERVERLIST_ITEM_LEN ) )
+    {
+      /* create server structure from that item */
+      packet::ServerInformation toadd;
+
+      /* fill in data, -1 for the index: index should be length -1 */
+      std::string datastr = std::string((char*)ev->packet->data + MSPROTO_SERVERLIST_ITEM_LEN+1);
+      int separator = datastr.find(" ");
+      toadd.setServerIP(datastr.substr(0,separator));
+      int secondsep = datastr.find(" ", separator + 1);
+      toadd.setServerName(datastr.substr(separator + 1, secondsep - separator - 1));
+      toadd.setClientNumber(Ogre::StringConverter::parseInt(datastr.substr(secondsep+1)));
+
+      orxout(internal_info, context::network) << "Received WAN discovery server information; Name: " << toadd.getServerName() << ", Address: " << toadd.getServerIP() << ", Players: " << toadd.getClientNumber() << ", RTT: " << toadd.getServerRTT() << endl;
+
+      /* add to list */
+      this->servers_.push_back( toadd );
+    }
+    else if( !strncmp( (char*)ev->packet->data, MSPROTO_SERVERLIST_END,
+      MSPROTO_SERVERLIST_END_LEN ) )
+    {
+      /* this is the only case where 2 should be returned,
+       * as 1 is used to signal that we're done receiving
+       * the list
+       */
+      return 2;
+    }
+
+    /* done handling, return all ok code 0 */
+    return 1;
+  }
+
+  void WANDiscovery::discover()
+  {
+    /* clear list */
+    this->servers_.clear();
+
+    /* send request to server */
+    this->msc.sendRequest( MSPROTO_CLIENT " " MSPROTO_REQ_LIST );
+
+    /* poll for replies */
+    int i = WANDISC_MAXTRIES;
+    while( i > 0 )
+    {
+      /* poll for reply and act according to what was received */
+      switch( this->msc.pollForReply( this, 500 ) )
+      { case 0: /* no event occured, decrease timeout */
+          --i; break;
+        case 1: /* got a list element, continue */
+          break;
+        case 2: /* done. */
+          i = 0; break;
+      }
+    }
+  }
+
+  std::string WANDiscovery::getServerListItemName(unsigned int index)
+  {
+    /* if the index is out of range, return empty */
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else
+      /* else return the name of the server */
+      return this->servers_[index].getServerName();
+  }
+
+  std::string WANDiscovery::getServerListItemIP(unsigned int index)
+  {
+    /* if the index is out of range, return empty */
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else
+      /* else return the IP of the server */
+      return this->servers_[index].getServerIP();
+  }
+
+  std::string WANDiscovery::getServerListItemRTT(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else{
+      uint32_t serverrtt = this->servers_[index].getServerRTT();
+      return Ogre::StringConverter::toString(serverrtt);
+    }
+
+  }
+  std::string WANDiscovery::getServerListItemPlayerNumber(unsigned int index)
+  {
+    if( index >= this->servers_.size() )
+      return BLANKSTRING;
+    else{
+      int playerNumber = this->servers_[index].getClientNumber();
+      return Ogre::StringConverter::toString(playerNumber);
+    }
+  }
+
+} // namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/WANDiscovery.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/WANDiscovery.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/WANDiscovery.h	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software Foundation, Inc., 51
+ *   Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      Oliver Scheuss (original)
+ *
+ */
+
+#ifndef _WANDiscovery_H__
+#define _WANDiscovery_H__
+
+#include "NetworkPrereqs.h"
+#include "packet/ServerInformation.h"
+#include "core/config/Configurable.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "MasterServerComm.h"
+#include "MasterServerProtocol.h"
+#include <OgreStringConverter.h>
+
+#include <vector>
+
+#define WANDISC_MAXTRIES 5
+
+// tolua_begin
+namespace orxonox
+{
+
+  class _NetworkExport WANDiscovery
+// tolua_end
+    : public Configurable
+  { // tolua_export
+    public:
+      /** constructor */
+      WANDiscovery(); // tolua_export
+
+      /** destructor */
+      ~WANDiscovery();
+
+      /** \return Address of the master server
+       *
+       * Get the master server address
+       */
+      std::string getMSAddress()
+      { return this->msaddress; }
+
+      /** ask server for server list  */
+      void discover(); // tolua_export
+
+      /** \param index Index to get the name of
+       * \return The name of the server
+       *
+       * Get the name of the server at index index.
+       */
+      std::string getServerListItemName( unsigned int index ); // tolua_export
+
+      /** \param index Index to get the IP of
+       * \return The IP of the server
+       *
+       * Get the IP of the server at index index.
+       */
+      std::string getServerListItemIP( unsigned int index ); // tolua_export
+
+      /** \param index Index to get the RTT of
+       * \return The RTT of the server
+       *
+       * Get the RTT of the server at index index.
+       */
+      std::string getServerListItemRTT( unsigned int index ); // tolua_export
+
+      /** \param index Index to get the RTT of
+       * \return The number of players on the server
+       *
+       * Get the number of players on the server
+       */
+      std::string getServerListItemPlayerNumber( unsigned int index ); // tolua_export
+
+      /* todo: might make this private and use getter/setter methods
+       * at some later time.
+       */
+      /** game server list */
+      std::vector<packet::ServerInformation> servers_;
+
+      /** Function used for the configuration file parameter update */
+      void setConfigValues();
+
+      /** Master server communications object */
+      MasterServerComm msc;
+
+      int rhandler( char *addr, ENetEvent *ev );
+
+    private:
+      /** master server address */
+      std::string msaddress;
+
+  }; // tolua_export
+
+} // tolua_export
+
+#endif // _WANDiscovery_H__
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Acknowledgement.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Acknowledgement.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Acknowledgement.cc	(revision 11817)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Acknowledgement.h"
+
+#include "util/Output.h"
+#include "network/GamestateHandler.h"
+#include "network/Host.h"
+
+namespace orxonox {
+namespace packet {
+
+#define PACKET_FLAGS_ACK    0
+#define _PACKETID           0
+#define _ACKID              _PACKETID + sizeof(packet::Type)
+
+Acknowledgement::Acknowledgement( unsigned int id, unsigned int peerID )
+ : Packet()
+{
+  flags_ = flags_ | PACKET_FLAGS_ACK;
+  data_=new uint8_t[ getSize() ];
+  *(Type *)(data_ + _PACKETID ) = Type::Acknowledgement;
+  *(uint32_t *)(data_ + _ACKID ) = id;
+  peerID_=peerID;
+}
+
+Acknowledgement::Acknowledgement( uint8_t *data, unsigned int peerID )
+  : Packet(data, peerID)
+{
+}
+
+Acknowledgement::~Acknowledgement()
+{
+}
+
+unsigned int Acknowledgement::getSize() const{
+  return _ACKID + sizeof(uint32_t);
+}
+
+bool Acknowledgement::process(orxonox::Host* host){
+  orxout(verbose_more, context::packets) << "processing ACK with ID: " << getAckID() << endl;
+  bool b = host->ackGamestate(getAckID(), peerID_);
+  delete this;
+  return b;
+}
+
+unsigned int Acknowledgement::getAckID(){
+  return *(uint32_t *)(data_ + _ACKID);
+}
+
+} //namespace packet
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Acknowledgement.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Acknowledgement.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Acknowledgement.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Acknowledgement_H__
+#define _Acknowledgement_H__
+
+#include "network/NetworkPrereqs.h"
+#include "Packet.h"
+
+namespace orxonox {
+const unsigned int ACKID_NACK = 0;
+namespace packet {
+/**
+    @author
+*/
+class _NetworkExport Acknowledgement : public Packet
+{
+public:
+  Acknowledgement( unsigned int id, unsigned int peerID );
+  Acknowledgement( uint8_t* data, unsigned int peerID );
+  ~Acknowledgement();
+
+  virtual inline unsigned int getSize() const override;
+  virtual bool process(orxonox::Host* host) override;
+
+  unsigned int getAckID();
+private:
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _Acknowledgement_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,29 @@
+ADD_SOURCE_FILES(NETWORK_SRC_FILES
+
+BUILD_UNIT PacketBuildUnit.cc
+  Acknowledgement.cc
+  Chat.cc
+  ClassID.cc
+  DeleteObjects.cc
+  FunctionIDs.cc
+  FunctionCalls.cc
+  Gamestate.cc
+  Packet.cc
+  Welcome.cc
+END_BUILD_UNIT
+
+  ServerInformation.cc
+)
+
+ADD_SOURCE_FILES(NETWORK_HDR_FILES
+  Acknowledgement.h
+  Chat.h
+  ClassID.h
+  DeleteObjects.h
+  FunctionCalls.h
+  FunctionIDs.h
+  Gamestate.h
+  Packet.h
+  ServerInformation.h
+  Welcome.h
+)
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Chat.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Chat.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Chat.cc	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Chat.h"
+
+#include <cstring>
+#include <string>
+#include "network/Host.h"
+
+namespace orxonox {
+namespace packet {
+
+#define   PACKET_FLAGS_CHAT PacketFlag::Reliable
+
+/* Some lengths */
+#define _PACKETID         0
+#define _SOURCEID         _PACKETID + sizeof(Type)
+#define _TARGETID         _SOURCEID + sizeof(uint32_t)
+#define _MESSAGELENGTH    _TARGETID + sizeof(uint32_t)
+#define _MESSAGE          _MESSAGELENGTH + sizeof(uint32_t)
+
+Chat::Chat( const std::string& message, unsigned int sourceID, unsigned int targetID )
+ : Packet()
+{
+  /* Add chat flag to packet flags */
+  flags_ = flags_ | PACKET_FLAGS_CHAT;
+
+  /* set message length to length of input string + 1 */
+  messageLength_ = message.length()+1;
+
+  /* allocate memory for the data */
+  data_=new unsigned char[ getSize() ];
+
+  *(Type *)(data_ + _PACKETID ) = Type::Chat;
+  *(unsigned int *)(data_ + _SOURCEID ) = sourceID;
+  *(unsigned int *)(data_ + _TARGETID ) = targetID;
+  *(unsigned int *)(data_ + _MESSAGELENGTH ) = messageLength_;
+
+  /* cast the hell out of the message string, and copy it into the
+   * data buffer.
+   */
+  memcpy( data_+_MESSAGE, static_cast<void*>(const_cast<char*>(message.c_str())), messageLength_ );
+}
+
+Chat::Chat( uint8_t* data, unsigned int clientID )
+  : Packet(data, clientID)
+{
+  messageLength_ = *(uint32_t *)(data + _MESSAGELENGTH );
+}
+
+Chat::~Chat()
+{
+}
+
+unsigned int Chat::getSize() const{
+  return _MESSAGE + messageLength_;
+}
+
+bool Chat::process(orxonox::Host* host){
+  host->doReceiveChat(std::string((const char*)data_+_MESSAGE), *(uint32_t *)(data_+_SOURCEID), *(uint32_t *)(data_+_TARGETID));
+  delete this;
+  return true;
+}
+
+unsigned char *Chat::getMessage(){
+  return data_ + _MESSAGE;
+}
+
+} //namespace packet
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Chat.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Chat.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Chat.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NETWORK_Chat_H__
+#define _NETWORK_Chat_H__
+
+#include "network/NetworkPrereqs.h"
+#include "Packet.h"
+
+namespace orxonox {
+namespace packet {
+/**
+    @author
+*/
+class _NetworkExport Chat : public Packet
+{
+public:
+  /* constructors */
+  Chat( const std::string& message, unsigned int sourceID, unsigned int targetID );
+  Chat( uint8_t* data, unsigned int clientID );
+
+  /* destructor */
+  ~Chat();
+
+  /* get size of packet */
+  virtual inline unsigned int getSize() const override;
+
+  /* process chat message packet and remove it afterwards */
+  virtual bool process(orxonox::Host* host) override;
+
+  /* Get the length of the message (not the full size of the packet) */
+  unsigned int getMessageLength(){ return messageLength_; };
+
+  /* return message content */
+  unsigned char *getMessage();
+
+private:
+
+  /* Message length */
+  uint32_t messageLength_;
+
+  /* Client ID (an integral value for identification) */
+  unsigned int clientID_;
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _NETWORK_Chat_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/ClassID.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/ClassID.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/ClassID.cc	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ClassID.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <map>
+#include <queue>
+#include <string>
+
+#include "core/CoreIncludes.h"
+
+namespace orxonox {
+namespace packet {
+
+
+#define PACKET_FLAGS_CLASSID  PacketFlag::Reliable
+#define _PACKETID             0
+
+
+ClassID::ClassID( ) : Packet(){
+  Identifier *id;
+  unsigned int nrOfClasses=0;
+  unsigned int packetSize=2*sizeof(uint32_t); //space for the packetID and for the nrofclasses
+  uint32_t network_id;
+  flags_ = flags_ | PACKET_FLAGS_CLASSID;
+  std::queue<std::pair<uint32_t, std::string>> tempQueue;
+
+  //calculate total needed size (for all strings and integers)
+  for(const auto& mapEntry : IdentifierManager::getInstance().getIdentifierByStringMap()){
+    id = mapEntry.second;
+    if(id == nullptr || !id->hasFactory())
+      continue;
+    const std::string& classname = id->getName();
+    network_id = id->getNetworkID();
+    // now push the network id and the classname to the stack
+    tempQueue.push( std::pair<unsigned int, std::string>(network_id, classname) );
+    ++nrOfClasses;
+    packetSize += (classname.size()+1)+sizeof(network_id)+sizeof(uint32_t);
+  }
+
+  this->data_=new uint8_t[ packetSize ];
+  //set the appropriate packet id
+  assert(this->data_);
+  *(Type *)(this->data_ + _PACKETID ) = Type::ClassID;
+
+  uint8_t *temp=data_+sizeof(uint32_t);
+  // save the number of all classes
+  *(uint32_t*)temp = nrOfClasses;
+  temp += sizeof(uint32_t);
+
+  // now save all classids and classnames
+  std::pair<uint32_t, std::string> tempPair;
+  uint32_t tempsize = 2*sizeof(uint32_t); // packetid and nrOfClasses
+  while( !tempQueue.empty() ){
+    tempPair = tempQueue.front();
+    tempQueue.pop();
+    *(uint32_t*)temp = tempPair.first;
+    *(uint32_t*)(temp+sizeof(uint32_t)) = tempPair.second.size()+1;
+    memcpy(temp+2*sizeof(uint32_t), tempPair.second.c_str(), tempPair.second.size()+1);
+    temp+=2*sizeof(uint32_t)+tempPair.second.size()+1;
+    tempsize+=2*sizeof(uint32_t)+tempPair.second.size()+1;
+  }
+  assert(tempsize==packetSize);
+
+  orxout(verbose_more, context::packets) << "classid packetSize is " << packetSize << endl;
+
+}
+
+ClassID::ClassID( uint8_t* data, unsigned int clientID )
+  : Packet(data, clientID)
+{
+}
+
+ClassID::~ClassID()
+{
+}
+
+uint32_t ClassID::getSize() const{
+  uint8_t *temp = data_+sizeof(uint32_t); // packet identification
+  uint32_t totalsize = sizeof(uint32_t); // packet identification
+  uint32_t nrOfClasses = *(uint32_t*)temp;
+  temp += sizeof(uint32_t);
+  totalsize += sizeof(uint32_t); // storage size for nr of all classes
+
+  for(unsigned int i=0; i<nrOfClasses; i++){
+    totalsize += 2*sizeof(uint32_t) + *(uint32_t*)(temp + sizeof(uint32_t));
+    temp += 2*sizeof(uint32_t) + *(uint32_t*)(temp + sizeof(uint32_t));
+  }
+  return totalsize;
+}
+
+
+bool ClassID::process(orxonox::Host* host){
+  int nrOfClasses;
+  uint8_t *temp = data_+sizeof(uint32_t); //skip the packetid
+  uint32_t networkID;
+  uint32_t stringsize;
+  unsigned char *classname;
+
+
+  //clear the map of network ids
+  IdentifierManager::getInstance().clearNetworkIDs();
+
+  orxout(verbose, context::packets) << "=== processing classids: " << endl;
+  std::pair<uint32_t, std::string> tempPair;
+  Identifier *id;
+  // read the total number of classes
+  nrOfClasses = *(uint32_t*)temp;
+  temp += sizeof(uint32_t);
+
+  for( int i=0; i<nrOfClasses; i++){
+    networkID = *(uint32_t*)temp;
+    stringsize = *(uint32_t*)(temp+sizeof(uint32_t));
+    classname = temp+2*sizeof(uint32_t);
+    id=ClassByString( std::string((const char*)classname) );
+    orxout(internal_info, context::packets) << "processing classid: " << networkID << " name: " << classname << " id: " << id << endl;
+    if(id==nullptr){
+      orxout(user_error, context::packets) << "Received a bad classname" << endl;
+      abort();
+    }
+    id->setNetworkID( networkID );
+    temp += 2*sizeof(uint32_t) + stringsize;
+  }
+  delete this;
+  return true;
+}
+
+
+} //namespace packet
+}//namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/ClassID.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/ClassID.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/ClassID.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NETWORK_ClassID_H__
+#define _NETWORK_ClassID_H__
+
+#include "network/NetworkPrereqs.h"
+#include "Packet.h"
+
+namespace orxonox {
+namespace packet {
+
+
+/**
+    @author
+*/
+class _NetworkExport ClassID : public Packet
+{
+public:
+  ClassID( );
+  ClassID( uint8_t* data, unsigned int clientID );
+  ~ClassID();
+
+  virtual uint32_t getSize() const override;
+  virtual bool process(orxonox::Host* host) override;
+
+private:
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _NETWORK_ClassID_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/DeleteObjects.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/DeleteObjects.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/DeleteObjects.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#include "DeleteObjects.h"
+
+#include <cassert>
+#include "util/Output.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox {
+namespace packet {
+
+#define PACKET_FLAG_DELETE  PacketFlag::Reliable
+#define _PACKETID           0
+#define _QUANTITY           _PACKETID + sizeof(Type)
+#define _OBJECTIDS          _QUANTITY + sizeof(uint32_t)
+
+DeleteObjects::DeleteObjects()
+ : Packet()
+{
+  flags_ = flags_ | PACKET_FLAG_DELETE;
+}
+
+DeleteObjects::DeleteObjects( uint8_t *data, unsigned int clientID )
+  : Packet(data, clientID)
+{
+}
+
+DeleteObjects::~DeleteObjects()
+{
+}
+
+bool DeleteObjects::fetchIDs()
+{
+  unsigned int number = Synchronisable::getNumberOfDeletedObject();
+  if(number==0)
+    return false;
+  orxout(verbose, context::packets) << "sending DeleteObjects: ";
+  unsigned int size = sizeof(Type) + sizeof(uint32_t)*(number+1);
+  data_ = new uint8_t[size];
+  uint8_t *tdata = data_;
+  *reinterpret_cast<Type*>(tdata) = Type::DeleteObjects;
+  tdata += sizeof(Type);
+  *(uint32_t *)tdata = number;
+  tdata += sizeof(uint32_t);
+  for(unsigned int i=0; i<number; i++){
+    unsigned int temp = Synchronisable::popDeletedObject();
+    *reinterpret_cast<uint32_t*>(tdata) = temp;
+    orxout(verbose, context::packets) << temp << ' ';
+    tdata += sizeof(uint32_t);
+  }
+  orxout(verbose, context::packets) << endl;
+  return true;
+}
+
+unsigned int DeleteObjects::getSize() const
+{
+  assert(data_);
+  return _OBJECTIDS + *(uint32_t*)(data_+_QUANTITY)*sizeof(uint32_t);
+}
+
+bool DeleteObjects::process(orxonox::Host* host)
+{
+  for(unsigned int i=0; i<*(unsigned int *)(data_+_QUANTITY); i++)
+  {
+    orxout(verbose, context::packets) << "deleting object with id: " << *(uint32_t*)(data_+_OBJECTIDS+i*sizeof(uint32_t)) << endl;
+    Synchronisable::deleteObject( *(uint32_t*)(data_+_OBJECTIDS+i*sizeof(uint32_t)) );
+  }
+  delete this;
+  return true;
+}
+
+
+} //namespace packet
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/DeleteObjects.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/DeleteObjects.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/DeleteObjects.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+#ifndef _DeleteObjects_H__
+#define _DeleteObjects_H__
+
+#include "network/NetworkPrereqs.h"
+#include "Packet.h"
+
+namespace orxonox
+{
+namespace packet
+{
+/**
+    @author
+*/
+class _NetworkExport DeleteObjects : public Packet
+{
+public:
+  DeleteObjects( );
+  DeleteObjects( uint8_t* data, unsigned int clientID );
+  ~DeleteObjects();
+
+  bool fetchIDs();
+
+  virtual inline unsigned int getSize() const override;
+  virtual bool process(orxonox::Host* host) override;
+
+private:
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _DeleteObjects_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionCalls.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionCalls.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionCalls.cc	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FunctionCalls.h"
+
+#include <cassert>
+#include "network/FunctionCall.h"
+#include "network/FunctionCallManager.h"
+#include "network/GamestateHandler.h"
+#include "network/Host.h"
+
+namespace orxonox {
+namespace packet {
+
+#define   PACKET_FLAGS_FUNCTIONCALLS PacketFlag::Reliable
+#define   _PACKETID         0
+const unsigned int FUNCTIONCALLS_MEM_ALLOCATION = 1000;
+
+FunctionCalls::FunctionCalls():
+  Packet(), minGamestateID_(GAMESTATEID_INITIAL)
+{
+  flags_ = flags_ | PACKET_FLAGS_FUNCTIONCALLS;
+  currentSize_ = 3*sizeof(uint32_t); // for packetid, nrOfCalls and minGamestateID_
+}
+
+FunctionCalls::FunctionCalls( uint8_t* data, unsigned int clientID ): 
+  Packet(data, clientID), minGamestateID_(GAMESTATEID_INITIAL)
+{
+}
+
+FunctionCalls::~FunctionCalls()
+{
+}
+
+
+bool FunctionCalls::process(orxonox::Host* host)
+{
+  assert(isDataENetAllocated());
+  
+  uint8_t* temp = data_+sizeof(uint32_t); //skip packetid
+  uint32_t nrOfCalls = *(uint32_t*)temp;
+  temp += sizeof(uint32_t);
+  this->minGamestateID_ = *(uint32_t*)temp;
+  temp += sizeof(uint32_t);
+  for( unsigned int i = 0; i<nrOfCalls; i++ )
+  {
+    FunctionCall fctCall;
+    fctCall.loadData(temp);
+    if( !fctCall.execute() )
+    {
+      FunctionCallManager::bufferIncomingFunctionCall( fctCall, minGamestateID_, this->getPeerID() );
+    }
+  }
+  
+  delete this;
+  return true;
+}
+
+void FunctionCalls::addCall( uint32_t networkID, uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5)
+{
+  assert(!isDataENetAllocated());
+  
+  this->functionCalls_.push(orxonox::FunctionCall());
+  this->functionCalls_.back().setCall( networkID, objectID, mt1, mt2, mt3, mt4, mt5 );
+  this->currentSize_ += this->functionCalls_.back().getSize();
+}
+
+bool FunctionCalls::send(orxonox::Host* host)
+{
+  this->minGamestateID_ = host->getCurrentGamestateID();
+  assert(this->functionCalls_.size());
+  data_=new uint8_t[ currentSize_ ];
+  *(Type *)(data_ + _PACKETID ) = Type::FunctionCalls; // Set the Packet ID
+  *(uint32_t*)(data_+sizeof(uint32_t)) = this->functionCalls_.size(); // set nrOfCalls
+  *(uint32_t*)(data_+2*sizeof(uint32_t)) = this->minGamestateID_; // set minGamestateID_
+  uint8_t* temp = data_+3*sizeof(uint32_t);
+  
+  while( this->functionCalls_.size() )
+  {
+    this->functionCalls_.front().saveData( temp );
+    this->functionCalls_.pop();
+  }
+  
+  assert( temp==data_+currentSize_ );
+  
+  Packet::send(host);
+  return true;
+}
+
+
+
+} //namespace packet
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionCalls.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionCalls.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionCalls.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FunctionCalls_H__
+#define _FunctionCalls_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include <cassert>
+#include <queue>
+#include "Packet.h"
+#include "network/FunctionCall.h"
+
+namespace orxonox {
+
+namespace packet {
+/**
+    @author
+*/
+
+
+class _NetworkExport FunctionCalls : public Packet
+{
+public:
+  FunctionCalls();
+  FunctionCalls( uint8_t* data, unsigned int clientID );
+  ~FunctionCalls();
+
+  virtual inline unsigned int getSize() const override
+    { assert(!this->isDataENetAllocated()); return currentSize_; }
+  virtual bool process(orxonox::Host* host) override;
+
+  void addCall( uint32_t networkID, uint32_t objectID, const MultiType& mt1, const MultiType& mt2, const MultiType& mt3, const MultiType& mt4, const MultiType& mt5);
+  virtual bool send(orxonox::Host* host) override;
+private:
+  std::queue<orxonox::FunctionCall> functionCalls_;
+  unsigned int                      clientID_;
+  uint32_t                          minGamestateID_;
+  uint32_t                          currentSize_;
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _FunctionCalls_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionIDs.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionIDs.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionIDs.cc	(revision 11817)
@@ -0,0 +1,154 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FunctionIDs.h"
+
+#include <cassert>
+#include <cstring>
+#include <queue>
+#include <string>
+
+#include "util/Output.h"
+#include "core/object/ObjectList.h"
+#include "network/NetworkFunction.h"
+#include "network/NetworkFunctionManager.h"
+
+namespace orxonox {
+namespace packet {
+
+
+#define PACKET_FLAGS_FUNCTIONIDS  PacketFlag::Reliable
+#define _PACKETID                 0
+
+
+FunctionIDs::FunctionIDs( ) : Packet()
+{
+  unsigned int nrOfFunctions=0;
+  unsigned int packetSize=2*sizeof(uint32_t); //space for the packetID and for the nroffunctions
+  uint32_t networkID;
+  flags_ = flags_ | PACKET_FLAGS_FUNCTIONIDS;
+  std::queue<std::pair<uint32_t, std::string>> tempQueue;
+
+  //calculate total needed size (for all strings and integers)
+  const std::set<NetworkFunctionBase*>& set = NetworkFunctionManager::getInstance().getAllFunctions();
+  std::set<NetworkFunctionBase*>::const_iterator it;
+  for (it = set.begin(); it != set.end(); ++it)
+  {
+    const std::string& functionname = (*it)->getName();
+    networkID = (*it)->getNetworkID();
+    // now push the network id and the classname to the stack
+    tempQueue.push( std::pair<unsigned int, std::string>(networkID, functionname) );
+    ++nrOfFunctions;
+    packetSize += (functionname.size()+1)+sizeof(uint32_t)+sizeof(uint32_t); // reserver size for the functionname string, the functionname length and the networkID
+  }
+
+  this->data_=new uint8_t[ packetSize ];
+  //set the appropriate packet id
+  assert(this->data_);
+  *(Type *)(this->data_ + _PACKETID ) = Type::FunctionIDs;
+
+  uint8_t *temp=data_+sizeof(uint32_t);
+  // save the number of all classes
+  *(uint32_t*)temp = nrOfFunctions;
+  temp += sizeof(uint32_t);
+
+  // now save all classids and classnames
+  std::pair<uint32_t, std::string> tempPair;
+  while( !tempQueue.empty() )
+  {
+    tempPair = tempQueue.front();
+    tempQueue.pop();
+    *(uint32_t*)temp = tempPair.first;
+    *(uint32_t*)(temp+sizeof(uint32_t)) = tempPair.second.size()+1;
+    memcpy(temp+2*sizeof(uint32_t), tempPair.second.c_str(), tempPair.second.size()+1);
+    temp+=2*sizeof(uint32_t)+tempPair.second.size()+1;
+  }
+
+  orxout(verbose_more, context::packets) << "FunctionIDs packetSize is " << packetSize << endl;
+
+}
+
+FunctionIDs::FunctionIDs( uint8_t* data, unsigned int clientID )
+  : Packet(data, clientID)
+{
+}
+
+FunctionIDs::~FunctionIDs()
+{
+}
+
+uint32_t FunctionIDs::getSize() const
+{
+  assert(this->data_);
+  uint8_t *temp = data_+sizeof(uint32_t); // packet identification
+  uint32_t totalsize = sizeof(uint32_t); // data size
+  uint32_t nrOfFunctions = *(uint32_t*)temp;
+  temp += sizeof(uint32_t);
+  totalsize += sizeof(uint32_t); // storage size for nr of all classes
+
+  for(unsigned int i=0; i<nrOfFunctions; i++){
+    totalsize += 2*sizeof(uint32_t) + *(uint32_t*)(temp + sizeof(uint32_t)); // for each network function add size for id, sizeof(string) and length of string itself to totalsize
+    temp += 2*sizeof(uint32_t) + *(uint32_t*)(temp + sizeof(uint32_t));
+  }
+  return totalsize;
+}
+
+
+bool FunctionIDs::process(orxonox::Host* host)
+{
+  int nrOfFunctions;
+  uint8_t *temp = data_+sizeof(uint32_t); //skip the packetid
+  uint32_t networkID;
+  uint32_t stringsize;
+  unsigned char *functionname;
+
+  //clear the map of network ids
+  NetworkFunctionManager::getInstance().clearNetworkIDs();
+
+  orxout(verbose, context::packets) << "=== processing functionids: " << endl;
+  std::pair<uint32_t, std::string> tempPair;
+  // read the total number of classes
+  nrOfFunctions = *(uint32_t*)temp;
+  temp += sizeof(uint32_t);
+
+  for( int i=0; i<nrOfFunctions; i++)
+  {
+    networkID = *(uint32_t*)temp;
+    stringsize = *(uint32_t*)(temp+sizeof(uint32_t));
+    functionname = temp+2*sizeof(uint32_t);
+    orxout(internal_info, context::packets) << "processing functionid: " << networkID << " name: " << functionname << endl;
+    NetworkFunctionManager::getInstance().getFunctionByName((const char*)functionname)->setNetworkID(networkID);
+    temp += 2*sizeof(uint32_t) + stringsize;
+  }
+  delete this;
+  return true;
+}
+
+
+} //namespace packet
+}//namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionIDs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionIDs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/FunctionIDs.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FunctionIDs_H__
+#define _FunctionIDs_H__
+
+#include "network/NetworkPrereqs.h"
+#include "Packet.h"
+
+namespace orxonox {
+namespace packet {
+
+
+/**
+    @author
+*/
+class _NetworkExport FunctionIDs : public Packet
+{
+public:
+  FunctionIDs( );
+  FunctionIDs( uint8_t* data, unsigned int clientID );
+  ~FunctionIDs();
+
+  virtual uint32_t getSize() const override;
+  virtual bool process(orxonox::Host* host) override;
+
+private:
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _FunctionIDs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Gamestate.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Gamestate.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Gamestate.cc	(revision 11817)
@@ -0,0 +1,774 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Gamestate.h"
+
+#include <zlib.h>
+
+#include "util/Output.h"
+#include "util/OrxAssert.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/object/ObjectList.h"
+#include "network/synchronisable/Synchronisable.h"
+#include "network/GamestateHandler.h"
+#include "network/Host.h"
+
+namespace orxonox {
+
+namespace packet {
+
+#define GAMESTATE_START(data) (data + GamestateHeader::getSize())
+
+// #define PACKET_FLAG_GAMESTATE  PacketFlag::Reliable
+#define PACKET_FLAG_GAMESTATE  0
+
+inline bool memzero( uint8_t* data, uint32_t datalength)
+{
+  uint64_t* d = (uint64_t*)data;
+
+  for( unsigned int i=0; i<datalength/8; i++ )
+  {
+    if( *(d+i) != 0 )
+      return false;
+  }
+  // now process the rest (when datalength isn't a multiple of 4)
+  for( unsigned int j = 8*(datalength/8); j<datalength; j++ )
+  {
+    if( *(data+j) != 0 )
+      return false;
+  }
+  return true;
+}
+
+
+Gamestate::Gamestate():
+  header_()
+{
+  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
+}
+
+
+Gamestate::Gamestate(uint8_t *data, unsigned int clientID):
+  Packet(data, clientID), header_(data)
+{
+  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
+}
+
+
+Gamestate::Gamestate(uint8_t *data):
+  header_(data)
+{
+  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
+  data_ = data;
+}
+
+
+Gamestate::Gamestate(const Gamestate& g) :
+  Packet( *(Packet*)&g ), header_(this->data_), nrOfVariables_(0)
+{
+  flags_ = flags_ | PACKET_FLAG_GAMESTATE;
+  sizes_ = g.sizes_;
+}
+
+
+Gamestate::~Gamestate()
+{
+}
+
+
+bool Gamestate::collectData(int id, uint8_t mode)
+{
+  uint32_t tempsize=0, currentsize=0;
+  assert(data_==nullptr);
+  uint32_t size = calcGamestateSize(id, mode);
+
+  orxout(verbose_more, context::packets) << "G.ST.Man: producing gamestate with id: " << id << endl;
+  if(size==0)
+    return false;
+  data_ = new uint8_t[size + GamestateHeader::getSize()];
+  if(!data_)
+  {
+    orxout(internal_warning, context::packets) << "GameStateManager: could not allocate memory" << endl;
+    return false;
+  }
+
+  // tell the gamestate header where to store the data
+  header_.setData(this->data_);
+
+  //start collect data synchronisable by synchronisable
+  uint8_t *mem = data_; // in this stream store all data of the variables and the headers of the synchronisable
+  mem += GamestateHeader::getSize();
+  ObjectList<Synchronisable>::iterator it;
+  for(it = ObjectList<Synchronisable>().begin(); it; ++it)
+  {
+
+//     tempsize=it->getSize(id, mode);
+
+    tempsize = it->getData(mem, this->sizes_, id, mode);
+    if ( tempsize != 0 )
+      dataVector_.emplace_back(it->getObjectID(), it->getContextID(), tempsize, mem-data_);
+
+#ifndef NDEBUG
+    if(currentsize+tempsize > size)
+    {
+      assert(0); // if we don't use multithreading this part shouldn't be neccessary
+      // start allocate additional memory
+      orxout(internal_info, context::packets) << "Gamestate: need additional memory" << endl;
+      ObjectList<Synchronisable>::iterator temp = it;
+      uint32_t addsize=tempsize;
+      while(++temp)
+        addsize+=temp->getSize(id, mode);
+      data_ = (uint8_t *)realloc(data_, GamestateHeader::getSize() + currentsize + addsize);
+      if(!data_)
+        return false;
+      size = currentsize+addsize;
+    }// stop allocate additional memory
+#endif
+//     if(!it->getData(mem, id, mode))
+//       return false; // mem pointer gets automatically increased because of call by reference
+    // increase size counter by size of current synchronisable
+    currentsize+=tempsize;
+  }
+
+
+  //start write gamestate header
+  header_.setDataSize( currentsize );
+  header_.setCompSize( 0 );
+  header_.setID( id );
+  header_.setBaseID( GAMESTATEID_INITIAL );
+  header_.setDiffed( false );
+  header_.setComplete( true );
+  header_.setCompressed( false );
+  //stop write gamestate header
+
+  orxout(verbose_more, context::packets) << "Gamestate: Gamestate size: " << currentsize << endl;
+  orxout(verbose_more, context::packets) << "Gamestate: 'estimated' (and corrected) Gamestate size: " << size << endl;
+  return true;
+}
+
+
+bool Gamestate::spreadData(uint8_t mode)
+{
+  orxout(verbose_more, context::packets) << "processing gamestate with id " << header_.getID() << endl;
+  assert(data_);
+  assert(!header_.isCompressed());
+  uint8_t *mem=data_+GamestateHeader::getSize();
+  Synchronisable *s;
+  
+  // update the data of the objects we received
+  while(mem < data_+GamestateHeader::getSize()+header_.getDataSize())
+  {
+    SynchronisableHeader objectheader(mem);
+
+    s = Synchronisable::getSynchronisable( objectheader.getObjectID() );
+    if(!s)
+    {
+      if (!GameMode::isMaster())
+      {
+        Synchronisable::fabricate(mem, mode);
+      }
+      else
+      {
+//         orxout(verbose, context::packets) << "not creating object of classid " << objectheader.getClassID() << endl;
+        mem += objectheader.getDataSize() + ( objectheader.isDiffed() ? SynchronisableHeaderLight::getSize() : SynchronisableHeader::getSize() );
+      }
+    }
+    else
+    {
+//       orxout(verbose, context::packets) << "updating object of classid " << objectheader.getClassID() << endl;
+      OrxVerify(s->updateData(mem, mode), "ERROR: could not update Synchronisable with Gamestate data");
+    }
+  }
+  assert((uintptr_t)(mem-data_) == GamestateHeader::getSize()+header_.getDataSize());
+  
+   // In debug mode, check first, whether there are no duplicate objectIDs
+#ifndef NDEBUG
+  if(this->getID()%1000==1)
+  {
+    std::list<uint32_t> v1;
+    for (Synchronisable* synchronisable : ObjectList<Synchronisable>())
+    {
+      if (synchronisable->getObjectID() == OBJECTID_UNKNOWN)
+      {
+        if (synchronisable->objectMode_ != 0x0)
+        {
+          orxout(user_error, context::packets) << "Found object with OBJECTID_UNKNOWN on the client with objectMode != 0x0!" << endl;
+          orxout(user_error, context::packets) << "Possible reason for this error: Client created a synchronized object without the Server's approval." << endl;
+          orxout(user_error, context::packets) << "Objects class: " << synchronisable->getIdentifier()->getName() << endl;
+          assert(false);
+        }
+      }
+      else
+      {
+        for (uint32_t id : v1)
+        {
+          if (synchronisable->getObjectID() == id)
+          {
+            orxout(user_error, context::packets) << "Found duplicate objectIDs on the client!" << endl
+                                                 << "Are you sure you don't create a Sychnronisable objcect with 'new' \
+                                                     that doesn't have objectMode = 0x0?" << endl;
+            assert(false);
+          }
+        }
+        v1.push_back(synchronisable->getObjectID());
+      }
+    }
+  }
+#endif
+  return true;
+}
+
+
+uint32_t Gamestate::getSize() const
+{
+  assert(data_);
+  if(header_.isCompressed())
+    return header_.getCompSize()+GamestateHeader::getSize();
+  else
+  {
+    return header_.getDataSize()+GamestateHeader::getSize();
+  }
+}
+
+
+bool Gamestate::operator==(packet::Gamestate gs)
+{
+  uint8_t *d1 = data_+GamestateHeader::getSize();
+  uint8_t *d2 = gs.data_+GamestateHeader::getSize();
+  GamestateHeader h1(data_);
+  GamestateHeader h2(gs.data_);
+  assert(h1.getDataSize() == h2.getDataSize());
+  assert(!isCompressed());
+  assert(!gs.isCompressed());
+  return memcmp(d1, d2, h1.getDataSize())==0;
+}
+
+
+bool Gamestate::process(orxonox::Host* host)
+{
+  return host->addGamestate(this, getPeerID());
+}
+
+
+bool Gamestate::compressData()
+{
+  assert(data_);
+  assert(!header_.isCompressed());
+  uLongf buffer = (uLongf)(((header_.getDataSize() + 12)*1.01)+1);
+  if(buffer==0)
+    return false;
+
+  uint8_t *ndata = new uint8_t[buffer+GamestateHeader::getSize()];
+  uint8_t *dest = ndata + GamestateHeader::getSize();
+  uint8_t *source = data_ + GamestateHeader::getSize();
+  int retval;
+  retval = compress( dest, &buffer, source, (uLong)(header_.getDataSize()) );
+  switch ( retval )
+  {
+    case Z_OK: orxout(verbose_more, context::packets) << "G.St.Man: compress: successfully compressed" << endl; break;
+    case Z_MEM_ERROR: orxout(internal_error, context::packets) << "G.St.Man: compress: not enough memory available in gamestate.compress" << endl; return false;
+    case Z_BUF_ERROR: orxout(internal_warning, context::packets) << "G.St.Man: compress: not enough memory available in the buffer in gamestate.compress" << endl; return false;
+    case Z_DATA_ERROR: orxout(internal_warning, context::packets) << "G.St.Man: compress: data corrupted in gamestate.compress" << endl; return false;
+  }
+
+  //copy and modify header
+  GamestateHeader *temp = new GamestateHeader(data_);
+  header_.setData(ndata);
+  header_ = *temp;
+  delete temp;
+  //delete old data
+  delete[] data_;
+  //save new data
+  data_ = ndata;
+  header_.setCompSize( buffer );
+  header_.setCompressed( true );
+  orxout(verbose, context::packets) << "gamestate compress datasize: " << header_.getDataSize() << " compsize: " << header_.getCompSize() << endl;
+  return true;
+}
+
+
+bool Gamestate::decompressData()
+{
+  assert(data_);
+  assert(header_.isCompressed());
+  orxout(verbose, context::packets) << "GameStateClient: uncompressing gamestate. id: " << header_.getID() << ", baseid: " << header_.getBaseID() << ", datasize: " << header_.getDataSize() << ", compsize: " << header_.getCompSize() << endl;
+  uint32_t datasize = header_.getDataSize();
+  uint32_t compsize = header_.getCompSize();
+  uint32_t bufsize;
+  bufsize = datasize;
+  assert(bufsize!=0);
+  uint8_t *ndata = new uint8_t[bufsize + GamestateHeader::getSize()];
+  uint8_t *dest = ndata + GamestateHeader::getSize();
+  uint8_t *source = data_ + GamestateHeader::getSize();
+  int retval;
+  uLongf length=bufsize;
+  retval = uncompress( dest, &length, source, (uLong)compsize );
+  switch ( retval )
+  {
+    case Z_OK: orxout(verbose_more, context::packets) << "successfully decompressed" << endl; break;
+    case Z_MEM_ERROR: orxout(internal_error, context::packets) << "not enough memory available" << endl; return false;
+    case Z_BUF_ERROR: orxout(internal_warning, context::packets) << "not enough memory available in the buffer" << endl; return false;
+    case Z_DATA_ERROR: orxout(internal_warning, context::packets) << "data corrupted (zlib)" << endl; return false;
+  }
+
+  //copy over the header
+  GamestateHeader* temp = new GamestateHeader( data_ );
+  header_.setData(ndata);
+  header_ = *temp;
+  delete temp;
+
+  if (this->bDataENetAllocated_)
+  {
+    // Memory was allocated by ENet. --> We let it be since enet_packet_destroy will
+    // deallocated it anyway. So data and packet stay together.
+    this->bDataENetAllocated_ = false;
+  }
+  else
+  {
+    // We allocated the memory in the first place (unlikely). So we destroy the old data
+    // and overwrite it with the new decompressed data.
+    delete[] this->data_;
+  }
+
+  //set new pointers
+  data_ = ndata;
+  header_.setCompressed( false );
+  assert(header_.getDataSize()==datasize);
+  assert(header_.getCompSize()==compsize);
+  return true;
+}
+
+
+inline void /*Gamestate::*/diffObject( uint8_t*& newDataPtr, uint8_t*& origDataPtr, uint8_t*& baseDataPtr, SynchronisableHeader& objectHeader, std::vector<uint32_t>::iterator& sizes )
+{
+  assert( objectHeader.getDataSize() == SynchronisableHeader(baseDataPtr).getDataSize() );
+  
+  uint32_t objectOffset = SynchronisableHeader::getSize(); // offset inside the object in the origData and baseData
+  // Check whether the whole object stayed the same
+  if( memcmp( origDataPtr+objectOffset, baseDataPtr+objectOffset, objectHeader.getDataSize()) == 0 )
+  {
+//     orxout(verbose, context::packets) << "skip object " << Synchronisable::getSynchronisable(objectHeader.getObjectID())->getIdentifier()->getName() << endl;
+    origDataPtr += objectOffset + objectHeader.getDataSize(); // skip the whole object
+    baseDataPtr += objectOffset + objectHeader.getDataSize();
+    sizes += Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables();
+  }
+  else
+  {
+    // Now start to diff the Object
+    SynchronisableHeaderLight newObjectHeader(newDataPtr);
+    newObjectHeader = objectHeader; // copy over the objectheader
+    VariableID variableID = 0;
+    uint32_t diffedObjectOffset = SynchronisableHeaderLight::getSize();
+    // iterate through all variables
+    while( objectOffset < objectHeader.getDataSize()+SynchronisableHeader::getSize() )
+    {
+      // check whether variable changed and write id and copy over variable to the new stream
+      // otherwise skip variable
+      uint32_t varSize = *sizes;
+      assert( varSize == Synchronisable::getSynchronisable(objectHeader.getObjectID())->getVarSize(variableID) );
+      if ( varSize != 0 )
+      {
+        if ( memcmp(origDataPtr+objectOffset, baseDataPtr+objectOffset, varSize) != 0 )
+        {
+          *(VariableID*)(newDataPtr+diffedObjectOffset) = variableID; // copy over the variableID
+          diffedObjectOffset += sizeof(VariableID);
+          memcpy( newDataPtr+diffedObjectOffset, origDataPtr+objectOffset, varSize );
+          diffedObjectOffset += varSize;
+          objectOffset += varSize;
+        }
+        else
+        {
+          objectOffset += varSize;
+        }
+      }
+
+      ++variableID;
+      ++sizes;
+    }
+    
+    // if there are variables from this object with 0 size left in sizes
+    if( Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables() != variableID )
+      sizes += Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables() - variableID;
+    
+    newObjectHeader.setDiffed(true);
+    newObjectHeader.setDataSize(diffedObjectOffset-SynchronisableHeaderLight::getSize());
+    assert(objectOffset == objectHeader.getDataSize()+SynchronisableHeader::getSize());
+    assert(newObjectHeader.getDataSize()>0);
+    
+    origDataPtr += objectOffset;
+    baseDataPtr += objectOffset;
+    newDataPtr += diffedObjectOffset;
+  }
+}
+
+inline void /*Gamestate::*/copyObject( uint8_t*& newData, uint8_t*& origData, uint8_t*& baseData, SynchronisableHeader& objectHeader, std::vector<uint32_t>::iterator& sizes )
+{
+  //       orxout(verbose, context::packets) << "docopy" << endl;
+  // Just copy over the whole Object
+  memcpy( newData, origData, objectHeader.getDataSize()+SynchronisableHeader::getSize() );
+  SynchronisableHeader(newData).setDiffed(false);
+  
+  newData += objectHeader.getDataSize()+SynchronisableHeader::getSize();
+  origData += objectHeader.getDataSize()+SynchronisableHeader::getSize();
+//   SynchronisableHeader baseHeader( baseData );
+//   baseData += baseHeader.getDataSize()+SynchronisableHeader::getSize();
+  //       orxout(verbose, context::packets) << "copy " << h.getObjectID() << endl;
+  //       orxout(verbose, context::packets) << "copy " << h.getObjectID() << ":";
+  sizes += Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables();
+//   for( unsigned int i = 0; i < Synchronisable::getSynchronisable(objectHeader.getObjectID())->getNrOfVariables(); ++i )
+//   {
+//     //         orxout(verbose, context::packets) << " " << *sizes;
+//     ++sizes;
+//   }
+    //       orxout(verbose, context::packets) << endl;
+}
+
+inline bool findObject(uint8_t*& dataPtr, uint8_t* endPtr, SynchronisableHeader& objectHeader)
+{
+  // Some assertions to make sure the dataPtr is valid (pointing to a SynchronisableHeader)
+  {
+    SynchronisableHeader htemp2(dataPtr);
+    assert(htemp2.getClassID()<500);
+    assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
+    assert(htemp2.isDiffed()==false);
+  }
+  uint32_t objectID = objectHeader.getObjectID();
+  while ( dataPtr < endPtr )
+  {
+    SynchronisableHeader htemp(dataPtr);
+    assert( htemp.getDataSize()!=0 );
+    if ( htemp.getObjectID() == objectID )
+    {
+      assert( objectHeader.getClassID() == htemp.getClassID() );
+      assert( objectHeader.getContextID() == htemp.getContextID() );
+      return true;
+    }
+    {
+      if( dataPtr+htemp.getDataSize()+SynchronisableHeader::getSize() < endPtr )
+      {
+        SynchronisableHeader htemp2(dataPtr+htemp.getDataSize()+SynchronisableHeader::getSize());
+        assert(htemp2.getClassID()<500);
+        assert(htemp2.getDataSize()!=0 && htemp2.getDataSize()<1000);
+        assert(htemp2.isDiffed()==false);
+      }
+    }
+    dataPtr += htemp.getDataSize()+SynchronisableHeader::getSize();
+    
+  }
+  assert(dataPtr == endPtr);
+  
+  return false;
+}
+
+Gamestate* Gamestate::diffVariables(Gamestate *base)
+{
+  assert(base); assert(data_ && base->data_);
+  assert(!header_.isCompressed() && !base->header_.isCompressed());
+  assert(!header_.isDiffed());
+  assert( header_.getDataSize() && base->header_.getDataSize() );
+
+
+  // *** first do a raw diff of the two gamestates
+
+  uint8_t *baseDataPtr = GAMESTATE_START(base->data_);
+  uint8_t *origDataPtr = GAMESTATE_START(this->data_);
+  uint8_t *origDataEnd = origDataPtr + header_.getDataSize();
+  uint8_t *baseDataEnd = baseDataPtr + base->header_.getDataSize();
+//   uint32_t origLength = header_.getDataSize();
+//   uint32_t baseLength = base->header_.getDataSize();
+
+  // Allocate new space for diffed gamestate
+  uint32_t newDataSize = header_.getDataSize() + GamestateHeader::getSize() + sizeof(uint32_t)*this->nrOfVariables_;
+  uint8_t *newData = new uint8_t[newDataSize]; // this is the maximum size needed in the worst case
+  uint8_t *destDataPtr = GAMESTATE_START(newData);
+
+  std::vector<uint32_t>::iterator sizesIt = this->sizes_.begin();
+
+  while( origDataPtr < origDataEnd )
+  {
+    //iterate through all objects
+
+    SynchronisableHeader origHeader(origDataPtr);
+
+    // Find (if possible) the current object in the datastream of the old gamestate
+    // Start at the current offset position
+    if(baseDataPtr == baseDataEnd)
+      baseDataPtr = GAMESTATE_START(base->data_);
+    uint8_t* oldBaseDataPtr = baseDataPtr;
+    
+    assert(baseDataPtr < baseDataEnd);
+    assert(destDataPtr < newData + newDataSize);
+    assert(sizesIt != this->sizes_.end());
+    
+    assert(Synchronisable::getSynchronisable(origHeader.getObjectID()));
+    assert(ClassByID(origHeader.getClassID()));
+    assert(origHeader.getDataSize() < 500);
+    
+    if( findObject(baseDataPtr, baseDataEnd, origHeader) )
+    {
+      SynchronisableHeader baseHeader(baseDataPtr);
+      assert(Synchronisable::getSynchronisable(baseHeader.getObjectID()));
+      assert(ClassByID(baseHeader.getClassID()));
+      assert(baseHeader.getDataSize() < 500);
+      if( SynchronisableHeader(baseDataPtr).getDataSize()==origHeader.getDataSize() )
+      {
+//         orxout(verbose, context::packets) << "diffing object in order: " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
+        diffObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
+      }
+      else
+      {
+//         orxout(verbose, context::packets) << "copy object because of different data sizes (1): " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
+        copyObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
+        assert(sizesIt != this->sizes_.end() || origDataPtr==origDataEnd);
+      }
+        
+    }
+    else
+    {
+      assert( baseDataPtr == baseDataEnd );
+      baseDataPtr = GAMESTATE_START(base->data_);
+      if( findObject(baseDataPtr, oldBaseDataPtr, origHeader) )
+      {
+        SynchronisableHeader baseHeader(baseDataPtr);
+        assert(Synchronisable::getSynchronisable(baseHeader.getObjectID()));
+        assert(ClassByID(baseHeader.getClassID()));
+        assert(baseHeader.getDataSize() < 500);
+        if( SynchronisableHeader(baseDataPtr).getDataSize()==origHeader.getDataSize() )
+        {
+//           orxout(verbose, context::packets) << "diffing object out of order: " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
+          diffObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
+        }
+        else
+        {
+//           orxout(verbose, context::packets) << "copy object because of different data sizes (2): " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
+          copyObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
+          assert(sizesIt != this->sizes_.end() || origDataPtr==origDataEnd);
+        }
+      }
+      else
+      {
+//         orxout(verbose, context::packets) << "copy object: " << Synchronisable::getSynchronisable(origHeader.getObjectID())->getIdentifier()->getName() << endl;
+        assert(baseDataPtr == oldBaseDataPtr);
+        copyObject(destDataPtr, origDataPtr, baseDataPtr, origHeader, sizesIt);
+        assert(sizesIt != this->sizes_.end() || origDataPtr==origDataEnd);
+      }
+    }
+  }
+  assert(sizesIt==this->sizes_.end());
+
+
+  Gamestate *g = new Gamestate(newData, getPeerID());
+  (g->header_) = header_;
+  g->header_.setBaseID( base->getID() );
+  g->header_.setDataSize(destDataPtr - newData - GamestateHeader::getSize());
+  g->flags_=flags_;
+  g->packetDirection_ = packetDirection_;
+  assert(!g->isCompressed());
+  return g;
+}
+
+
+/*Gamestate* Gamestate::diffData(Gamestate *base)
+{
+  assert(this && base); assert(data_ && base->data_);
+  assert(!header_.isCompressed() && !base->header_.isCompressed());
+  assert(!header_.isDiffed());
+
+  uint8_t *basep = GAMESTATE_START(base->data_);
+  uint8_t *gs = GAMESTATE_START(this->data_);
+  uint32_t dest_length = header_.getDataSize();
+
+  if(dest_length==0)
+    return nullptr;
+
+  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
+  uint8_t *dest = GAMESTATE_START(ndata);
+
+  rawDiff( dest, gs, basep, header_.getDataSize(), base->header_.getDataSize() );
+#ifndef NDEBUG
+  uint8_t *dest2 = new uint8_t[dest_length];
+  rawDiff( dest2, dest, basep, header_.getDataSize(), base->header_.getDataSize() );
+  assert( memcmp( dest2, gs, dest_length) == 0 );
+  delete dest2;
+#endif
+
+  Gamestate *g = new Gamestate(ndata, getClientID());
+  assert(g->header_);
+  *(g->header_) = *header_;
+  g->header_.setDiffed( true );
+  g->header_.setBaseID( base->getID() );
+  g->flags_=flags_;
+  g->packetDirection_ = packetDirection_;
+  assert(g->isDiffed());
+  assert(!g->isCompressed());
+  return g;
+}
+
+
+Gamestate* Gamestate::undiff(Gamestate *base)
+{
+  assert(this && base); assert(data_ && base->data_);
+  assert(!header_.isCompressed() && !base->header_.isCompressed());
+  assert(header_.isDiffed());
+
+  uint8_t *basep = GAMESTATE_START(base->data_);
+  uint8_t *gs = GAMESTATE_START(this->data_);
+  uint32_t dest_length = header_.getDataSize();
+
+  if(dest_length==0)
+    return nullptr;
+
+  uint8_t *ndata = new uint8_t[dest_length*sizeof(uint8_t)+GamestateHeader::getSize()];
+  uint8_t *dest = ndata + GamestateHeader::getSize();
+
+  rawDiff( dest, gs, basep, header_.getDataSize(), base->header_.getDataSize() );
+
+  Gamestate *g = new Gamestate(ndata, getClientID());
+  assert(g->header_);
+  *(g->header_) = *header_;
+  g->header_.setDiffed( false );
+  g->flags_=flags_;
+  g->packetDirection_ = packetDirection_;
+  assert(!g->isDiffed());
+  assert(!g->isCompressed());
+  return g;
+}
+
+
+void Gamestate::rawDiff( uint8_t* newdata, uint8_t* data, uint8_t* basedata, uint32_t datalength, uint32_t baselength)
+{
+  uint64_t* gd = (uint64_t*)data;
+  uint64_t* bd = (uint64_t*)basedata;
+  uint64_t* nd = (uint64_t*)newdata;
+
+  unsigned int i;
+  for( i=0; i<datalength/8; i++ )
+  {
+    if( i<baselength/8 )
+      *(nd+i) = *(gd+i) ^ *(bd+i);  // xor the data
+    else
+      *(nd+i) = *(gd+i); // just copy over the data
+  }
+  unsigned int j;
+  // now process the rest (when datalength isn't a multiple of 4)
+  for( j = 8*(datalength/8); j<datalength; j++ )
+  {
+    if( j<baselength )
+      *(newdata+j) = *(data+j) ^ *(basedata+j); // xor
+    else
+      *(newdata+j) = *(data+j); // just copy
+  }
+  assert(j==datalength);
+}*/
+
+
+/*Gamestate* Gamestate::doSelection(unsigned int clientID, unsigned int targetSize){
+  assert(data_);
+  std::list<obj>::iterator it;
+
+  // allocate memory for new data
+  uint8_t *gdata = new uint8_t[header_.getDataSize()+GamestateHeader::getSize()];
+  // create a gamestate out of it
+  Gamestate *gs = new Gamestate(gdata);
+  uint8_t *newdata = gdata + GamestateHeader::getSize();
+  uint8_t *origdata = GAMESTATE_START(data_);
+
+  //copy the GamestateHeader
+  assert(gs->header_);
+  *(gs->header_) = *header_;
+
+  uint32_t objectOffset;
+  unsigned int objectsize, destsize=0;
+  // TODO: Why is this variable not used?
+  //Synchronisable *object;
+
+  //call TrafficControl
+  TrafficControl::getInstance()->processObjectList( clientID, header_.getID(), dataVector_ );
+
+  //copy in the zeros
+//   std::list<obj>::iterator itt;
+//   orxout() << "myvector contains:";
+//   for ( itt=dataVector_.begin() ; itt!=dataVector_.end(); itt++ )
+//     orxout() << " " << (*itt).objID;
+//   orxout() << endl;
+  for(it=dataVector_.begin(); it!=dataVector_.end();){
+    SynchronisableHeader oldobjectheader(origdata);
+    SynchronisableHeader newobjectheader(newdata);
+    if ( (*it).objSize == 0 )
+    {
+      ++it;
+      continue;
+    }
+    objectsize = oldobjectheader.getDataSize()+SynchronisableHeader::getSize();
+    objectOffset=SynchronisableHeader::getSize(); //skip the size and the availableData variables in the objectheader
+    if ( (*it).objID == oldobjectheader.getObjectID() ){
+      memcpy(newdata, origdata, objectsize);
+      ++it;
+    }else{
+      newobjectheader = oldobjectheader;
+      memset(newdata+objectOffset, 0, objectsize-objectOffset);
+    }
+    newdata += objectsize;
+    origdata += objectsize;
+    destsize += objectsize;
+  }
+#ifndef NDEBUG
+  uint32_t origsize = destsize;
+  while ( origsize < header_.getDataSize() )
+  {
+    SynchronisableHeader oldobjectheader(origdata);
+    objectsize = oldobjectheader.getDataSize()+SynchronisableHeader::getSize();
+    origdata += objectsize;
+    origsize += objectsize;
+  }
+  assert(origsize==header_.getDataSize());
+  assert(destsize!=0);
+#endif
+  gs->header_.setDataSize( destsize );
+  return gs;
+}*/
+
+
+uint32_t Gamestate::calcGamestateSize(uint32_t id, uint8_t mode)
+{
+  uint32_t size = 0;
+  uint32_t nrOfVariables = 0;
+    // get total size of gamestate
+  for(Synchronisable* synchronisable : ObjectList<Synchronisable>()){
+    size+=synchronisable->getSize(id, mode); // size of the actual data of the synchronisable
+    nrOfVariables += synchronisable->getNrOfVariables();
+  }
+//   orxout() << "allocating " << nrOfVariables << " ints" << endl;
+  this->sizes_.reserve(nrOfVariables);
+  return size;
+}
+
+
+} //namespace packet
+} //namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Gamestate.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Gamestate.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Gamestate.h	(revision 11817)
@@ -0,0 +1,156 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _Gamestate_H__
+#define _Gamestate_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include <cassert>
+#include <cstring>
+#include <list>
+#include <vector>
+
+#include "util/CRC32.h"
+#include "network/TrafficControl.h"
+#include "Packet.h"
+
+namespace orxonox
+{
+
+namespace packet
+{
+    
+static constexpr uint8_t GAMESTATE_MODE_SERVER = 0x1;
+static constexpr uint8_t GAMESTATE_MODE_CLIENT = 0x2;
+
+class _NetworkExport GamestateHeader
+{
+  public:
+    GamestateHeader(){ data_=nullptr; }
+    GamestateHeader(uint8_t* data)
+      { assert(data); data_ = data; *(Type*)data_ = Type::Gamestate; }
+    /*GamestateHeader(uint8_t* data, GamestateHeader* h)
+      { assert(data); data_=data; memcpy(data_, h->data_, getSize()); }*/
+    void setData(uint8_t* data)
+      { assert(data); data_ = data; *(Type*)data_ = Type::Gamestate; }
+    static inline uint32_t getSize()
+      { return 21; }
+
+    inline uint32_t getID() const
+      { assert(data_); return *(uint32_t*)(data_+4); }
+    inline void setID(uint32_t id)
+      { assert(data_); *(uint32_t*)(data_+4) = id; }
+
+    inline uint32_t getBaseID() const
+      { assert(data_); return *(uint32_t*)(data_+8); }
+    inline void setBaseID(uint32_t id)
+      { assert(data_); *(uint32_t*)(data_+8) = id; }
+
+    inline uint32_t getDataSize() const
+      { assert(data_); return *(uint32_t*)(data_+12); }
+    inline void setDataSize(uint32_t size)
+      { assert(data_); *(uint32_t*)(data_+12) = size; }
+
+    inline uint32_t getCompSize() const
+    { assert(data_); return *(uint32_t*)(data_+16); }
+    inline void setCompSize(uint32_t size)
+    { assert(data_); *(uint32_t*)(data_+16) = size; }
+
+    inline bool isDiffed() const
+      { assert(data_); return *(int8_t*)(data_+20) & 0x1; }
+    inline void setDiffed(bool b)
+      { assert(data_); *(int8_t*)(data_+20) = (b<<0) | (*(int8_t*)(data_+20) & 0x6 ); }
+
+    inline bool isComplete() const
+      { assert(data_); return *(int8_t*)(data_+20) & 0x2; }
+    inline void setComplete(bool b)
+      { assert(data_); *(int8_t*)(data_+20) = (b<<1) | (*(int8_t*)(data_+20) & 0x5 ); }
+
+    inline bool isCompressed() const
+      { assert(data_); return *(int8_t*)(data_+20) & 0x4; }
+    inline void setCompressed(bool b)
+      { assert(data_); *(int8_t*)(data_+20) = (b<<2) | (*(int8_t*)(data_+20) & 0x3 ); }
+
+    inline void operator=(GamestateHeader& h)
+      { assert(data_); assert(h.data_); memcpy( data_, h.data_, getSize()); }
+  private:
+    uint8_t* data_;
+
+};
+
+/**
+    @author Oliver Scheuss
+*/
+class _NetworkExport Gamestate: public Packet
+{
+  public:
+    Gamestate();
+    Gamestate(uint8_t *data, unsigned int clientID);
+    Gamestate(uint8_t *data);
+    Gamestate(const Gamestate& g);
+
+    ~Gamestate();
+
+    bool collectData(int id, uint8_t mode=0x0);
+    bool spreadData( uint8_t mode=0x0);
+    inline uint32_t getID() const { return header_.getID(); }
+    inline bool isDiffed() const { return header_.isDiffed(); }
+    inline bool isCompressed() const { return header_.isCompressed(); }
+    inline int32_t getBaseID() const { return header_.getBaseID(); }
+    inline uint32_t getDataSize() const { return header_.getDataSize(); }
+    Gamestate* diffVariables(Gamestate *base);
+//     Gamestate* diffData(Gamestate *base);
+//     Gamestate *undiff(Gamestate *base);
+//     Gamestate* doSelection(unsigned int clientID, unsigned int targetSize);
+    bool compressData();
+    bool decompressData();
+    bool operator ==(packet::Gamestate gs);
+
+    // Packet functions
+  private:
+//     void rawDiff( uint8_t* newdata, uint8_t* data, uint8_t* basedata, uint32_t datalength, uint32_t baselength);
+//     inline uint32_t findObject( const SynchronisableHeader& header, uint8_t* mem, uint32_t dataLength, uint32_t startPosition = 0 );
+    virtual uint32_t getSize() const override;
+    virtual bool process(orxonox::Host* host) override;
+    uint32_t calcGamestateSize(uint32_t id, uint8_t mode=0x0);
+//     inline void diffObject( uint8_t*& newData, uint8_t*& origData, uint8_t*& baseData, SynchronisableHeader& objectHeader, std::vector<uint32_t>::iterator& sizes );
+//     inline void copyObject( uint8_t*& newData, uint8_t*& origData, uint8_t*& baseData, SynchronisableHeader& objectHeader, std::vector<uint32_t>::iterator& sizes );
+    
+    std::list<obj>          dataVector_;
+    GamestateHeader         header_;
+    std::vector<uint32_t>   sizes_;
+    uint32_t                nrOfVariables_;
+};
+
+}
+
+}
+
+#endif /* _Gamestate_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Packet.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Packet.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Packet.cc	(revision 11817)
@@ -0,0 +1,262 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#include "Packet.h"
+
+#include <cassert>
+#include <cstring>
+#define WIN32_LEAN_AND_MEAN
+#include <enet/enet.h>
+#include <boost/thread/mutex.hpp>
+
+#include "util/Output.h"
+#include "Acknowledgement.h"
+#include "Chat.h"
+#include "ClassID.h"
+#include "DeleteObjects.h"
+#include "FunctionCalls.h"
+#include "FunctionIDs.h"
+#include "Gamestate.h"
+#include "Welcome.h"
+#include "network/Host.h"
+// #include "network/ClientInformation.h"
+
+namespace orxonox{
+
+namespace packet{
+
+// Make sure we assume the right values
+static_assert(static_cast<int>(PacketFlag::Reliable)    == static_cast<int>(ENET_PACKET_FLAG_RELIABLE),    "check enum");
+static_assert(static_cast<int>(PacketFlag::Unsequenced) == static_cast<int>(ENET_PACKET_FLAG_UNSEQUENCED), "check enum");
+static_assert(static_cast<int>(PacketFlag::NoAllocate)  == static_cast<int>(ENET_PACKET_FLAG_NO_ALLOCATE), "check enum");
+
+#define PACKET_FLAG_DEFAULT PacketFlag::NoAllocate
+#define _PACKETID           0
+
+std::map<size_t, Packet *> Packet::packetMap_;
+boost::mutex Packet::packetMapMutex_;
+
+Packet::Packet()
+{
+  flags_ = PACKET_FLAG_DEFAULT;
+  packetDirection_ = Direction::Outgoing;
+  peerID_=0;
+  data_=nullptr;
+  enetPacket_=nullptr;
+  bDataENetAllocated_ = false;
+}
+
+Packet::Packet(uint8_t *data, unsigned int peerID)
+{
+  flags_ = PACKET_FLAG_DEFAULT;
+  packetDirection_ = Direction::Incoming;
+  peerID_=peerID;
+  data_=data;
+  enetPacket_=nullptr;
+  bDataENetAllocated_ = false;
+}
+
+
+Packet::Packet(const Packet &p)
+{
+  enetPacket_=p.enetPacket_;
+  flags_=p.flags_;
+  packetDirection_ = p.packetDirection_;
+  peerID_ = p.peerID_;
+  if(p.data_){
+    data_ = new uint8_t[p.getSize()];
+    memcpy(data_, p.data_, p.getSize());
+  }else
+    data_=nullptr;
+  bDataENetAllocated_ = p.bDataENetAllocated_;
+}
+
+/**
+@brief
+    Destroys a packet completely.
+
+    That also means destroying the ENetPacket if one exists. There
+*/
+Packet::~Packet()
+{
+  // Deallocate data_ memory if necessary.
+  if (this->bDataENetAllocated_)
+  {
+    // In this case ENet allocated data_ and will destroy it.
+  }
+  else if (this->data_)
+  {
+    // This destructor was probably called as a consequence of ENet executing our callback.
+    // It simply serves us to be able to deallocate the packet content (data_) ourselves since
+    // we have created it in the first place.
+    delete[] this->data_;
+  }
+
+  // Destroy the ENetPacket if necessary.
+  // Note: For the case ENet used the callback to destroy the packet, we have already set
+  // enetPacket_ to nullptr to avoid destroying it again.
+  if (this->enetPacket_)
+  {
+    // enetPacket_->data gets destroyed too by ENet if it was allocated by it.
+    enet_packet_destroy(enetPacket_);
+  }
+}
+
+bool Packet::send(orxonox::Host* host)
+{
+  if(packetDirection_ != Direction::Outgoing && packetDirection_ != Direction::Bidirectional )
+  {
+    assert(0);
+    return false;
+  }
+  if(!enetPacket_)
+  {
+    if(!data_){
+      assert(0);
+      return false;
+    }
+    // We deliver ENet the data address so that it doesn't memcpy everything again.
+    // --> We have to delete data_ ourselves!
+    enetPacket_ = enet_packet_create(getData(), getSize(), getFlags());
+    enetPacket_->freeCallback = &Packet::deletePacket;
+    // Add the packet to a global list so we can access it again once enet calls our
+    // deletePacket method. We can of course only give a one argument function to the ENet C library.
+    {
+      // Assures we don't create a packet and destroy it right after in another thread
+      // without having a reference in the packetMap_
+      Packet::packetMapMutex_.lock();
+      packetMap_[reinterpret_cast<size_t>(enetPacket_)] = this;
+      Packet::packetMapMutex_.unlock();
+    }
+  }
+#ifndef NDEBUG
+  switch( *(Type *)(data_ + _PACKETID) )
+  {
+    case Type::Acknowledgement:
+    case Type::Chat:
+    case Type::ClassID:
+    case Type::Gamestate:
+    case Type::Welcome:
+    case Type::DeleteObjects:
+    case Type::FunctionIDs:
+    case Type::FunctionCalls:
+      break;
+    default:
+      assert(0); //there was some error, if this is the case
+      break;
+  }
+#endif
+//  ENetPacket *temp = enetPacket_;
+//  enetPacket_ = nullptr; // otherwise we have a double free because enet already handles the deallocation of the packet
+  if( this->flags_ & PacketFlag::Reliable )
+    host->addPacket( enetPacket_, peerID_, NETWORK_CHANNEL_DEFAULT);
+  else
+    host->addPacket( enetPacket_, peerID_, NETWORK_CHANNEL_UNRELIABLE);
+  return true;
+}
+
+Packet *Packet::createPacket(ENetPacket* packet, uint32_t peerID)
+{
+  uint8_t *data = packet->data;
+//   assert(ClientInformation::findClient(&peer->address)->getID() != static_cast<unsigned int>(-2) || !Host::isServer());
+//   unsigned int peerID = ClientInformation::findClient(&peer->address)->getID();
+  // HACK
+//   if( peerID==static_cast<unsigned int>(-2))
+//     peerID = NETWORK_PEER_ID_SERVER;
+  Packet *p = nullptr;
+//   orxout(verbose_ultra, context::packets) << "packet type: " << *(Type *)&data[_PACKETID] << endl;
+  switch( *(Type *)(data + _PACKETID) )
+  {
+    case Type::Acknowledgement:
+//       orxout(verbose_more, context::packets) << "ack" << endl;
+    p = new Acknowledgement( data, peerID );
+      break;
+    case Type::Chat:
+//       orxout(verbose_more, context::packets) << "chat" << endl;
+      p = new Chat( data, peerID );
+      break;
+    case Type::ClassID:
+//       orxout(verbose_more, context::packets) << "classid" << endl;
+      p = new ClassID( data, peerID );
+      break;
+    case Type::Gamestate:
+//       orxout(verbose_more, context::packets) << "gamestate" << endl;
+      p = new Gamestate( data, peerID );
+      break;
+    case Type::Welcome:
+//       orxout(verbose_more, context::packets) << "welcome" << endl;
+      p = new Welcome( data, peerID );
+      break;
+    case Type::DeleteObjects:
+//       orxout(verbose_more, context::packets) << "deleteobjects" << endl;
+      p = new DeleteObjects( data, peerID );
+      break;
+    case Type::FunctionCalls:
+//       orxout(verbose_more, context::packets) << "functionCalls" << endl;
+      p = new FunctionCalls( data, peerID );
+      break;
+    case Type::FunctionIDs:
+//       orxout(verbose_more, context::packets) << "functionIDs" << endl;
+      p = new FunctionIDs( data, peerID );
+      break;
+    default:
+      assert(0);
+      break;
+  }
+
+  // Data was created by ENet
+  p->bDataENetAllocated_ = true;
+  p->enetPacket_ = packet;
+
+  return p;
+}
+
+/**
+@brief
+    ENet calls this method whenever it wants to destroy a packet that contains
+    data we allocated ourselves.
+*/
+void Packet::deletePacket(ENetPacket *enetPacket)
+{
+  // Get our Packet from a global map with all Packets created in the send() method of Packet.
+  Packet::packetMapMutex_.lock();
+  std::map<size_t, Packet*>::iterator it = packetMap_.find(reinterpret_cast<size_t>(enetPacket));
+  assert(it != packetMap_.end());
+  // Make sure we don't delete it again in the destructor
+  it->second->enetPacket_ = nullptr;
+  delete it->second;
+  packetMap_.erase(it);
+  Packet::packetMapMutex_.unlock();
+//   orxout(verbose_ultra, context::packets) << "PacketMap size: " << packetMap_.size() << endl;
+}
+
+} // namespace packet
+
+} // namespace orxonox
+
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Packet.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Packet.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Packet.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+#ifndef _NETWORK_Packet_H__
+#define _NETWORK_Packet_H__
+
+#include "network/NetworkPrereqs.h"
+#include <map>
+
+namespace orxonox
+{
+
+namespace packet
+{
+
+enum class Direction
+{
+  Incoming,
+  Outgoing,
+  Bidirectional
+};
+enum class Type : uint8_t
+{
+  Acknowledgement,
+  Chat,
+  ClassID,
+  DeleteObjects,
+  FunctionIDs,
+  FunctionCalls,
+  Gamestate,
+  Welcome
+};
+
+/**
+    @author Oliver Scheuss <scheusso [at] ee.ethz.ch>
+*/
+class _NetworkExport Packet
+{
+  public:
+    Packet(const Packet &p);
+    virtual ~Packet();
+    static Packet* createPacket(ENetPacket* packet, uint32_t peerID);
+    static void deletePacket(ENetPacket* packet);
+
+    virtual unsigned char* getData(){ return data_; };
+    virtual unsigned int getSize() const =0;
+    virtual bool process(orxonox::Host* host)=0;
+    inline uint32_t getFlags()
+      { return flags_; }
+    inline int getPeerID()
+      { return peerID_; }
+    inline void setPeerID( int id )
+      { peerID_ = id; }
+    inline bool isReliable()
+      { return this->flags_ & PacketFlag::Reliable; }
+    inline uint32_t getRequiredGamestateID()
+      { return this->requiredGamestateID_; }
+
+    virtual bool send(orxonox::Host* host);
+  protected:
+    Packet();
+    Packet(uint8_t *data, unsigned int peerID);
+//    Packet(ENetPacket *packet, ENetPeer *peer);
+    inline bool isDataENetAllocated() const
+      { return bDataENetAllocated_; }
+
+    uint32_t flags_;
+    unsigned int peerID_;
+    uint32_t requiredGamestateID_;
+    Direction packetDirection_;
+    /** Pointer to the data. Be careful when deleting it because it might
+        point to a location that was allocated by ENet.
+        See bDataENetAllocated_ */
+    uint8_t *data_;
+    /** Tells whether data_ was allocated by ENet or ourselves.
+        data_ might no correlate with enetPacket_->data. */
+    bool bDataENetAllocated_;
+  private:
+    static std::map<size_t, Packet *> packetMap_;
+    static boost::mutex               packetMapMutex_;
+    ENetPacket *enetPacket_;
+};
+
+} //namespace packet
+
+} //namespace orxonox
+
+#endif /* _NETWORK_Packet_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/ServerInformation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/ServerInformation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/ServerInformation.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ServerInformation.h"
+
+#include <enet/enet.h>
+#include <cassert>
+#include <cstring>
+
+#include "util/Serialise.h"
+
+namespace orxonox
+{
+  namespace packet
+  {
+
+    ServerInformation::ServerInformation()
+    {
+    }
+
+    ServerInformation::ServerInformation(ENetEvent* event)
+    {
+      char serverIP[64];
+
+      // Save Server Round Trip Time
+      this->serverRTT_ = event->peer->roundTripTime;
+      // Save Server Address, leave some space for scope ID
+      enet_address_get_host_ip(&event->peer->address, serverIP, 64);
+      this->serverIP_ = std::string(serverIP);
+      // Save ACK
+      uint8_t* temp = event->packet->data;
+      char* ack = nullptr;
+      loadAndIncrease((char*&)ack, temp);
+
+      /* Fabian, what is this used for? it crashes the masterserver, hence commenting it */
+      // written by Oli: this is just to make sure that loadAndIncrease really writes the whole ACK string into char* ack
+//       assert(strcmp(ack, (const char*)LAN_DISCOVERY_ACK)==0);
+
+      // Save Server Name
+      loadAndIncrease(this->serverName_, temp);
+      delete[] ack;
+    }
+
+    ServerInformation::~ServerInformation()
+    {
+
+    }
+
+    void ServerInformation::send(ENetPeer* peer)
+    {
+      std::string payload = this->serverName_ + Ogre::StringConverter::toString(this->clientNumber_);
+      uint32_t size = returnSize(LAN_DISCOVERY_ACK) + returnSize(payload);
+      uint8_t* temp = new uint8_t[size];
+      uint8_t* temp2 = temp;
+      saveAndIncrease(LAN_DISCOVERY_ACK, temp2);
+      saveAndIncrease(payload, temp2);
+      ENetPacket* packet = enet_packet_create( temp, size, 0 );
+      enet_peer_send(peer, 0, packet);
+
+      delete[] temp;
+    }
+
+  } // namespace packet
+
+} // namespace orxonox
+
+std::ostream& operator<<(std::ostream& out, const ENetAddress& address)
+{
+    char addr[64];
+    if (!enet_address_get_host_ip(&address, addr, 64))
+        out << addr;
+    return out;
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/ServerInformation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/ServerInformation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/ServerInformation.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "../NetworkPrereqs.h"
+
+#include <string>
+#include <OgreStringConverter.h>
+
+
+#ifndef SERVERINFORMATION_H
+#define SERVERINFORMATION_H
+
+namespace orxonox
+{
+  namespace packet
+  {
+
+    class ServerInformation
+    {
+      public:
+        ServerInformation();
+        ServerInformation(ENetEvent* event);
+        ~ServerInformation();
+
+        void          send( ENetPeer* peer );
+        void          setServerName(std::string name) { this->serverName_ = name; }
+        std::string   getServerName() const { return this->serverName_; }
+        void          setServerIP( std::string IP ) { this->serverIP_ = IP; }
+        std::string   getServerIP() const { return this->serverIP_; }
+        void          setClientNumber( int clientNumber ) { this->clientNumber_ = clientNumber; }
+        int           getClientNumber() const { return this->clientNumber_; }
+        uint32_t      getServerRTT() const { return this->serverRTT_; }
+
+      private:
+        std::string   serverName_;
+        int           clientNumber_;
+        std::string   serverIP_;
+        uint32_t      serverRTT_;
+    };
+
+  }
+
+}
+
+_NetworkExport std::ostream& operator<<(std::ostream& out, const ENetAddress& address);
+
+#endif // SERVERINFORMATION_H
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Welcome.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Welcome.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Welcome.cc	(revision 11817)
@@ -0,0 +1,88 @@
+
+
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Welcome.h"
+
+#include <cassert>
+#include "util/Output.h"
+#include "network/Host.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox {
+namespace packet {
+
+#define PACKET_FLAGS_CLASSID  PacketFlag::Reliable
+#define _PACKETID             0
+#define _CLIENTID             _PACKETID + sizeof(Type)
+#define _ENDIANTEST           _CLIENTID + sizeof(uint32_t)
+
+  Welcome::Welcome( uint32_t clientID )
+ : Packet()
+{
+  flags_ = flags_ | PACKET_FLAGS_CLASSID;
+  assert(getSize());
+  data_=new uint8_t[ getSize() ];
+  assert(data_);
+  *(packet::Type *)(data_ + _PACKETID ) = packet::Type::Welcome;
+  *(uint32_t *)(data_ + _CLIENTID ) = static_cast<uint32_t>(clientID);
+  *(uint32_t *)(data_ + _ENDIANTEST ) = 0xFEDC4321;
+}
+
+Welcome::Welcome( uint8_t* data, uint32_t clientID )
+  : Packet(data, clientID)
+{
+}
+
+Welcome::~Welcome()
+{
+}
+
+uint8_t *Welcome::getData(){
+  return data_;
+}
+
+unsigned int Welcome::getSize() const{
+  return sizeof(packet::Type) + 2*sizeof(uint32_t);
+}
+
+bool Welcome::process(orxonox::Host* host){
+  uint32_t clientID;
+  clientID = *(uint32_t *)(data_ + _CLIENTID );
+  assert(*(uint32_t *)(data_ + _ENDIANTEST ) == 0xFEDC4321);
+  host->setClientID(clientID);
+  orxout(internal_info, context::packets) << "Welcome set clientId: " << clientID << endl;
+  Synchronisable::setClient(true);
+  delete this;
+  return true;
+}
+
+
+} //namespace packet
+}//namespace orxonox
Index: /code/branches/RacingBots_FS18/src/libraries/network/packet/Welcome.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/packet/Welcome.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/packet/Welcome.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss <scheusso [at] ee.ethz.ch>, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+#ifndef _NETWORK_Welcome_H__
+#define _NETWORK_Welcome_H__
+
+#include "network/NetworkPrereqs.h"
+#include "Packet.h"
+
+namespace orxonox {
+namespace packet {
+
+/**
+    @author
+*/
+class _NetworkExport Welcome : public Packet
+{
+public:
+  Welcome( uint32_t clientID );
+  Welcome( uint8_t* data, uint32_t clientID );
+  virtual ~Welcome();
+
+  virtual uint8_t *getData() override;
+  virtual inline unsigned int getSize() const override;
+  virtual bool process(orxonox::Host* host) override;
+
+private:
+};
+
+} //namespace packet
+} //namespace orxonox
+
+#endif /* _NETWORK_Welcome_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,12 @@
+ADD_SOURCE_FILES(NETWORK_SRC_FILES
+  NetworkCallbackManager.cc
+  Synchronisable.cc
+)
+
+ADD_SOURCE_FILES(NETWORK_HDR_FILES
+  NetworkCallback.h
+  NetworkCallbackManager.h
+  Serialise.h
+  Synchronisable.h
+  SynchronisableVariable.h
+)
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallback.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallback.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallback.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _NetworkCallback_H__
+#define _NetworkCallback_H__
+
+#include "network/NetworkPrereqs.h"
+#include "NetworkCallbackManager.h"
+// #include "util/MultiType.h"
+
+namespace orxonox{
+
+  struct EmptyType{};
+
+  class _NetworkExport NetworkCallbackBase
+  {
+    public:
+      virtual void call() = 0;
+      NetworkCallbackBase(){ NetworkCallbackManager::registerCallback( this ); }
+      virtual ~NetworkCallbackBase() {}
+  };
+
+  template <class T>
+  class NetworkCallback: public NetworkCallbackBase
+  {
+    public:
+      NetworkCallback(T* object, void (T::*function) (void)) : object_(object), function_(function) {}
+      virtual ~NetworkCallback() {}
+      virtual void call() override
+        { (this->object_->*function_)(); }
+
+    private:
+      T* object_;
+      void (T::*function_) (void);
+  };
+
+  template <class T, class U>
+  class NetworkCallbackNotify: public NetworkCallbackBase
+  {
+    public:
+      NetworkCallbackNotify(T* object, void (T::*function) (const U&)) : object_(object), function_(function) {}
+      NetworkCallbackNotify() {}
+      virtual ~NetworkCallbackNotify() {}
+      virtual void call() override
+        { (this->object_->*function_)( this->oldValue_ ); }
+      void setOldValue(const U& value){ this->oldValue_ = value; }
+    private:
+      T* object_;
+      U oldValue_;
+      void (T::*function_) (const U&);
+  };
+
+}
+
+
+#endif /* _NetworkCallback_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallbackManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallbackManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallbackManager.cc	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "NetworkCallbackManager.h"
+#include "NetworkCallback.h"
+
+namespace orxonox{
+
+  std::set<NetworkCallbackBase*> NetworkCallbackManager::callbackSet_;
+  std::queue<NetworkCallbackBase*> NetworkCallbackManager::triggeredCallbacks_;
+
+  void NetworkCallbackManager::registerCallback(NetworkCallbackBase *cb)
+  {
+    callbackSet_.insert(cb);
+  }
+  void NetworkCallbackManager::deleteCallback(NetworkCallbackBase *cb)
+  {
+    std::set<NetworkCallbackBase*>::iterator it = callbackSet_.find(cb);
+    if (it != callbackSet_.end())
+    {
+      callbackSet_.erase(it);
+      delete cb;
+    }
+  }
+
+  void NetworkCallbackManager::triggerCallback(NetworkCallbackBase *cb)
+  {
+    if (triggeredCallbacks_.empty() || triggeredCallbacks_.front() != cb)
+      triggeredCallbacks_.push(cb);
+  }
+
+  void NetworkCallbackManager::callCallbacks()
+  {
+    while( triggeredCallbacks_.empty()==false )
+    {
+      //make sure callback hasn't been deleted before
+      if ( callbackSet_.find(triggeredCallbacks_.front()) != callbackSet_.end() )
+        triggeredCallbacks_.front()->call();
+      triggeredCallbacks_.pop();
+    }
+  }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallbackManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallbackManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/NetworkCallbackManager.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2008
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _NetworkCallbackManager_H__
+#define _NetworkCallbackManager_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include <set>
+#include <queue>
+
+namespace orxonox{
+
+  class _NetworkExport NetworkCallbackManager{
+    public:
+      static void registerCallback(NetworkCallbackBase *cb);
+      static void deleteCallback(NetworkCallbackBase *cb);
+      static void triggerCallback(NetworkCallbackBase *cb);
+      static void callCallbacks();
+    private:
+      static std::set<NetworkCallbackBase*> callbackSet_;
+      static std::queue<NetworkCallbackBase*> triggeredCallbacks_;
+  };
+
+
+}
+
+
+#endif /* _NetworkCallbackManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Serialise.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Serialise.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Serialise.h	(revision 11817)
@@ -0,0 +1,152 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Functions to serialise pointers to objects that inherit from Synchronisable
+*/
+
+#ifndef _NetworkSerialise_H__
+#define _NetworkSerialise_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include <loki/TypeTraits.h>
+
+#include "util/Serialise.h"
+#include "core/CorePrereqs.h"
+
+namespace orxonox{
+
+    // These functions implement loading / saving / etc. for pointer types
+
+    /** @brief returns the size of the objectID needed to synchronise the pointer */
+    template <class T> inline uint32_t returnSize( T*& variable )
+    {
+      return sizeof(uint32_t);
+    }
+
+    /** @brief reads the objectID of a pointer out of the bytestream and increases the mem pointer */
+    template <class T> inline void loadAndIncrease( T*& variable, uint8_t*& mem )
+    {
+        *const_cast<typename Loki::TypeTraits<T*>::UnqualifiedType*>(&variable) = dynamic_cast<T*>(variable->getSynchronisable( *(uint32_t*)(mem) ));
+        mem += returnSize( variable );
+    }
+
+    /** @brief saves the objectID of a pointer into the bytestream and increases the mem pointer */
+    template <class T> inline void saveAndIncrease( T*& variable, uint8_t*& mem )
+    {
+        if ( variable )
+            *(uint32_t*)(mem) = static_cast<uint32_t>(variable->getObjectID());
+        else
+            *(uint32_t*)(mem) = OBJECTID_UNKNOWN;
+        mem += returnSize( variable );
+    }
+
+    /** @brief checks whether the objectID of the variable is the same as in the bytestream */
+    template <class T> inline  bool checkEquality( T*& variable, uint8_t* mem )
+    {
+        if ( variable )
+            return *(uint32_t*)(mem) == variable->getObjectID();
+        else
+            return variable == variable->getSynchronisable(*(uint32_t*)(mem));
+    }
+
+    // These functions implement loading / saving / etc. for StrongPtr<T>
+
+    /** @brief returns the size of the objectID needed to synchronise the pointer */
+    template <class T> inline uint32_t returnSize( const StrongPtr<T>& )
+    {
+        return sizeof(uint32_t);
+    }
+
+    /** @brief reads the objectID of a pointer out of the bytestream and increases the mem pointer */
+    template <class T> inline void loadAndIncrease( const StrongPtr<T>& variable, uint8_t*& mem )
+    {
+//         *const_cast<typename Loki::TypeTraits<T*>::UnqualifiedType*>(&variable) = dynamic_cast<T*>(variable->getSynchronisable( *(uint32_t*)(mem) ));
+        *const_cast<typename Loki::TypeTraits<StrongPtr<T>>::UnqualifiedType*>(&variable) = orxonox_cast<T*>(T::getSynchronisable(*(uint32_t*)(mem)));
+        mem += returnSize( variable );
+    }
+
+    /** @brief saves the objectID of a pointer into the bytestream and increases the mem pointer */
+    template <class T> inline void saveAndIncrease( const StrongPtr<T>& variable, uint8_t*& mem )
+    {
+        if ( variable.get() )
+            *(uint32_t*)(mem) = static_cast<uint32_t>(variable->getObjectID());
+        else
+            *(uint32_t*)(mem) = OBJECTID_UNKNOWN;
+        mem += returnSize( variable );
+    }
+
+    /** @brief checks whether the objectID of the variable is the same as in the bytestream */
+    template <class T> inline  bool checkEquality( const StrongPtr<T>& variable, uint8_t* mem )
+    {
+        if ( variable.get() )
+            return *(uint32_t*)(mem) == variable->getObjectID();
+        else
+            return *(uint32_t*)(mem) == OBJECTID_UNKNOWN;
+    }
+
+    // These functions implement loading / saving / etc. for WeakPtr<T>
+
+    /** @brief returns the size of the objectID needed to synchronise the pointer */
+    template <class T> inline uint32_t returnSize( const WeakPtr<T>& variable )
+    {
+        return sizeof(uint32_t);
+    }
+
+    /** @brief reads the objectID of a pointer out of the bytestream and increases the mem pointer */
+    template <class T> inline void loadAndIncrease( const WeakPtr<T>& variable, uint8_t*& mem )
+    {
+        //         *const_cast<typename Loki::TypeTraits<T*>::UnqualifiedType*>(&variable) = dynamic_cast<T*>(variable->getSynchronisable( *(uint32_t*)(mem) ));
+        *const_cast<typename Loki::TypeTraits<WeakPtr<T>>::UnqualifiedType*>(&variable) = orxonox_cast<T*>(T::getSynchronisable(*(uint32_t*)(mem)));
+        mem += returnSize( variable );
+    }
+
+    /** @brief saves the objectID of a pointer into the bytestream and increases the mem pointer */
+    template <class T> inline void saveAndIncrease( const WeakPtr<T>& variable, uint8_t*& mem )
+    {
+        if ( variable.get() )
+            *(uint32_t*)(mem) = static_cast<uint32_t>(variable->getObjectID());
+        else
+            *(uint32_t*)(mem) = OBJECTID_UNKNOWN;
+        mem += returnSize( variable );
+    }
+
+    /** @brief checks whether the objectID of the variable is the same as in the bytestream */
+    template <class T> inline  bool checkEquality( const WeakPtr<T>& variable, uint8_t* mem )
+    {
+        if ( variable.get() )
+            return *(uint32_t*)(mem) == variable->getObjectID();
+        else
+            return *(uint32_t*)(mem) == OBJECTID_UNKNOWN;
+    }
+}
+
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Synchronisable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Synchronisable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Synchronisable.cc	(revision 11817)
@@ -0,0 +1,480 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Dumeni Manatschal, (C) 2007
+ *      Oliver Scheuss, (C) 2007
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#include "Synchronisable.h"
+
+#include <cstdlib>
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/BaseObject.h"
+#include "network/Host.h"
+
+namespace orxonox
+{
+
+  std::map<uint32_t, Synchronisable *> Synchronisable::objectMap_;
+  std::queue<uint32_t> Synchronisable::deletedObjects_;
+
+  uint8_t Synchronisable::state_=0x1; // detemines wheter we are server (default) or client
+
+  RegisterAbstractClass(Synchronisable).inheritsFrom<OrxonoxInterface>();
+
+  /**
+  * Constructor:
+  * Initializes all Variables and sets the right objectID_
+  */
+  Synchronisable::Synchronisable(Context* context)
+  {
+      RegisterObject(Synchronisable);
+    static uint32_t idCounter=0;
+    objectMode_=0x1; // by default do not send data to server
+    if ( GameMode::isMaster()/* || ( Host::running() && Host::isServer() )*/ )
+    {
+      this->setObjectID( idCounter++ );
+    }
+    else
+    {
+      objectID_=OBJECTID_UNKNOWN;
+    }
+    classID_ = static_cast<uint32_t>(-1);
+
+    // set dataSize to 0
+    this->dataSize_ = 0;
+    // set standard priority
+    this->setPriority( Priority::Normal );
+
+    // get context id
+    this->contextID_ = this->findContextID(context);
+  }
+
+  /**
+   * Destructor:
+   * Delete all callback objects and remove objectID_ from the objectMap_
+   */
+  Synchronisable::~Synchronisable()
+  {
+    // delete callback function objects
+    if(!IdentifierManager::getInstance().isCreatingHierarchy()){
+      // remove object from the static objectMap
+      if (this->objectMode_ != 0x0 && (Host::running() && Host::isServer()))
+        deletedObjects_.push(objectID_);
+    }
+    // delete all Synchronisable Variables from syncList_ ( which are also in stringList_ )
+    for(SynchronisableVariableBase* variable : syncList_)
+      delete variable;
+    syncList_.clear();
+    stringList_.clear();
+    std::map<uint32_t, Synchronisable*>::iterator it2;
+    it2 = objectMap_.find(objectID_);
+    if (it2 != objectMap_.end())
+      objectMap_.erase(it2);
+
+  }
+
+  /**
+   * @brief Returns the id of the context.
+   * If the context is not Synchronisable, it moves on to its parent, recursively.
+   */
+  uint32_t Synchronisable::findContextID(Context* context)
+  {
+      if (context == nullptr)
+          return OBJECTID_UNKNOWN;
+
+      Synchronisable* synchronisableContext = orxonox_cast<Synchronisable*>(context);
+      if (synchronisableContext != nullptr)
+          return synchronisableContext->getObjectID();
+      else
+          return this->findContextID(context->getParentContext());
+  }
+
+  /**
+   * This function sets the internal mode for synchronisation
+   * @param b true if this object is located on a client or on a server
+   */
+  void Synchronisable::setClient(bool b)
+  {
+    if(b) // client
+      state_=0x2;
+    else  // server
+      state_=0x1;
+  }
+
+  /**
+   * This function fabricated a new synchrnisable (and children of it), sets calls updateData and create
+   * After calling this function the mem pointer will be increased by the size of the needed data
+   * @param mem pointer to where the appropriate data is located
+   * @param mode defines the mode, how the data should be loaded
+   * @return pointer to the newly created synchronisable
+   */
+  Synchronisable *Synchronisable::fabricate(uint8_t*& mem, uint8_t mode)
+  {
+    SynchronisableHeader header(mem);
+    if( header.isDiffed() )
+    {
+      mem += header.getDataSize() + header.getSize();
+      return nullptr;
+    }
+//     assert( !header.isDiffed() );
+
+    orxout(verbose, context::network) << "fabricating object with id: " << header.getObjectID() << endl;
+
+    Identifier* id = ClassByID(header.getClassID());
+    if (!id)
+    {
+        for(int i = 0; i<160; i++)
+            orxout(user_error, context::network) << "classid: " << i << " identifier: " << ClassByID(i) << endl;
+        orxout(user_error, context::network) << "Assertion failed: Could not find Identifier for ClassID " << header.getClassID() << endl;
+        orxout(user_error, context::network) << "Possible reason for this error: Client received a synchronizable object whose class has no factory." << endl;
+        abort();
+    }
+    assert(id);
+    Context* context = nullptr;
+    if (header.getContextID() != OBJECTID_UNKNOWN)
+    {
+      Synchronisable* synchronisable_context = Synchronisable::getSynchronisable(header.getContextID());
+      if (!synchronisable_context)
+      {
+        mem += header.getDataSize()+SynchronisableHeader::getSize(); //.TODO: this suckz.... remove size from header
+        assert(0); // TODO: uncomment this if we have a clean objecthierarchy (with destruction of children of objects) ^^
+        return nullptr;
+      }
+      else
+        context = orxonox_cast<Context*>(synchronisable_context);
+    }
+    else
+      context = Context::getRootContext();
+
+    assert(getSynchronisable(header.getObjectID())==nullptr);   //make sure no object with this id exists
+    BaseObject *bo = orxonox_cast<BaseObject*>(id->fabricate(context));
+    assert(bo);
+    Synchronisable *no = orxonox_cast<Synchronisable*>(bo);
+    assert(no);
+    assert( Synchronisable::objectMap_.find(header.getObjectID()) == Synchronisable::objectMap_.end() );
+    no->setObjectID(header.getObjectID());
+    //no->contextID=header.getContextID(); //TODO: remove this
+    no->setClassID(header.getClassID());
+    assert(no->contextID_ == header.getContextID());
+    //assert(no->classID_ == header.getClassID());
+    orxout(verbose, context::network) << "fabricate objectID_: " << no->objectID_ << " classID_: " << no->classID_ << endl;
+          // update data and create object/entity...
+    bool b = no->updateData(mem, mode, true);
+    assert(b);
+    if (b)
+    {
+//        b = no->create();
+        assert(b);
+    }
+    return no;
+  }
+
+
+  /**
+   * Finds and deletes the Synchronisable with the appropriate objectID_
+   * @param objectID_ objectID_ of the Synchronisable
+   * @return true/false
+   */
+  bool Synchronisable::deleteObject(uint32_t objectID_)
+  {
+    if(!getSynchronisable(objectID_))
+      return false;
+    assert(getSynchronisable(objectID_)->objectID_==objectID_);
+    Synchronisable *s = getSynchronisable(objectID_);
+    if(s)
+      s->destroy(); // or delete?
+    else
+      return false;
+    return true;
+  }
+
+  /**
+   * This function looks up the objectID_ in the objectMap_ and returns a pointer to the right Synchronisable
+   * @param objectID_ objectID_ of the Synchronisable
+   * @return pointer to the Synchronisable with the objectID_
+   */
+  Synchronisable* Synchronisable::getSynchronisable(uint32_t objectID_)
+  {
+    std::map<uint32_t, Synchronisable*>::iterator it1;
+    it1 = objectMap_.find(objectID_);
+    if (it1 != objectMap_.end())
+      return it1->second;
+    // if the objects not in the map it should'nt exist at all anymore
+    return nullptr;
+  }
+
+
+  /**
+   * This function takes all SynchronisableVariables out of the Synchronisable and saves them together with the size, objectID_ and classID_ to the given memory
+   * takes a pointer to already allocated memory (must have at least getSize bytes length)
+   * structure of the bitstream:
+   * |totalsize,objectID_,classID_,var1,var2,string1_length,string1,var3,...|
+   * length of varx: size saved int syncvarlist
+   * @param mem pointer to allocated memory with enough size
+   * @param sizes vector containing sizes of all objects in gamestate (to be appended)
+   * @param id gamestateid of the gamestate to be saved (important for priorities)
+   * @param mode defines the direction in which the data will be send/received
+   *             0x1: server->client
+   *             0x2: client->server
+   *             0x3: bidirectional
+   * @return true: if !doSync or if everything was successfully saved
+   */
+  uint32_t Synchronisable::getData(uint8_t*& mem, std::vector<uint32_t>& sizes, int32_t id, uint8_t mode)
+  {
+    unsigned int test = 0;
+    if(mode==0x0)
+      mode=state_;
+    //if this tick is we dont synchronise, then abort now
+    if(!doSync(/*id,*/ mode))
+      return 0;
+    uint32_t tempsize = 0;
+#ifndef NDEBUG
+    uint8_t* oldmem = mem;
+    if (this->classID_==0)
+      orxout(internal_info, context::network) << "classid 0 " << this->getIdentifier()->getName() << endl;
+#endif
+
+    if (this->classID_ == static_cast<uint32_t>(-1))
+        this->classID_ = this->getIdentifier()->getNetworkID();
+
+    assert(ClassByID(this->classID_));
+    assert(this->classID_==this->getIdentifier()->getNetworkID());
+    assert(this->objectID_!=OBJECTID_UNKNOWN);
+
+    // start copy header
+    SynchronisableHeader header(mem);
+    mem += SynchronisableHeader::getSize();
+    // end copy header
+
+    orxout(verbose_more, context::network) << "getting data from objectID_: " << objectID_ << ", classID_: " << classID_ << endl;
+//     orxout(verbose, context::network) << "objectid: " << this->objectID_ << ":";
+    // copy to location
+    for(SynchronisableVariableBase* variable : syncList_)
+    {
+      uint32_t varsize = variable->getData( mem, mode );
+//       orxout(verbose, context::network) << " " << varsize;
+      tempsize += varsize;
+      sizes.push_back(varsize);
+      ++test;
+      //tempsize += (*i)->getSize( mode );
+    }
+    assert(tempsize!=0);  // if this happens an empty object (with no variables) would be transmitted
+//     orxout(verbose, context::network) << endl;
+
+    header.setObjectID( this->objectID_ );
+    header.setContextID( this->contextID_ );
+    header.setClassID( this->classID_ );
+    header.setDataSize( tempsize );
+    assert( tempsize == mem-oldmem-SynchronisableHeader::getSize() );
+    assert( test == this->getNrOfVariables() );
+    header.setDiffed(false);
+    tempsize += SynchronisableHeader::getSize();
+
+#ifndef NDEBUG
+    uint32_t size;
+    size=getSize(id, mode);
+    assert(tempsize==size);
+#endif
+    return tempsize;
+  }
+
+
+  /**
+   * This function takes a bytestream and loads the data into the registered variables
+   * @param mem pointer to the bytestream
+   * @param mode same as in getData
+   * @param forceCallback this makes updateData call each callback
+   * @return true/false
+   */
+  bool Synchronisable::updateData(uint8_t*& mem, uint8_t mode, bool forceCallback)
+  {
+    if(mode==0x0)
+      mode=state_;
+    
+    if(syncList_.empty())
+    {
+      orxout(internal_warning, context::network) << "Synchronisable::updateData syncList_ is empty" << endl;
+      assert(0);
+      return false;
+    }
+
+    uint8_t* data=mem;
+    // start extract header
+    SynchronisableHeaderLight syncHeaderLight(mem);
+    assert(syncHeaderLight.getObjectID()==this->getObjectID());
+    
+    if( !this->doReceive(mode) )
+    {
+      uint32_t headerSize;
+      if( syncHeaderLight.isDiffed() )
+        headerSize = SynchronisableHeaderLight::getSize();
+      else
+        headerSize = SynchronisableHeader::getSize();
+      mem += syncHeaderLight.getDataSize() + headerSize;
+      return true;
+    }
+
+    //orxout(verbose_more, context::network) << "Synchronisable: objectID_ " << syncHeader.getObjectID() << ", classID_ " << syncHeader.getClassID() << " size: " << syncHeader.getDataSize() << " synchronising data" << endl;
+    if( !syncHeaderLight.isDiffed() )
+    {
+      SynchronisableHeader syncHeader2(mem);
+      assert( this->getClassID() == syncHeader2.getClassID() );
+      assert( this->getContextID() == syncHeader2.getContextID() );
+      mem += SynchronisableHeader::getSize();
+      for(SynchronisableVariableBase* variable : syncList_)
+      {
+        assert( mem <= data+syncHeader2.getDataSize()+SynchronisableHeader::getSize() ); // always make sure we don't exceed the datasize in our stream
+        variable->putData( mem, mode, forceCallback );
+      }
+      assert(mem == data+syncHeaderLight.getDataSize()+SynchronisableHeader::getSize() );
+    }
+    else
+    {
+      mem += SynchronisableHeaderLight::getSize();
+//       orxout(debug_output, context::network) << "objectID: " << this->objectID_ << endl;
+      while( mem < data+syncHeaderLight.getDataSize()+SynchronisableHeaderLight::getSize() )
+      {
+        VariableID varID = *(VariableID*)mem;
+//         orxout(debug_output, context::network) << "varID: " << varID << endl;
+        assert( varID < syncList_.size() );
+        mem += sizeof(VariableID);
+        syncList_[varID]->putData( mem, mode, forceCallback );
+      }
+      assert(mem == data+syncHeaderLight.getDataSize()+SynchronisableHeaderLight::getSize() );
+    }
+    return true;
+  }
+
+  /**
+  * This function returns the total amount of bytes needed by getData to save the whole content of the variables
+  * @param id id of the gamestate
+  * @param mode same as getData
+  * @return amount of bytes
+  */
+  uint32_t Synchronisable::getSize(int32_t id, uint8_t mode)
+  {
+    uint32_t tsize=SynchronisableHeader::getSize();
+    if (mode==0x0)
+      mode=state_;
+    if (!doSync(/*id, */mode))
+      return 0;
+    assert( mode==state_ );
+    tsize += this->dataSize_;
+    for(SynchronisableVariableBase* variable : stringList_)
+    {
+      tsize += variable->getSize( mode );
+    }
+    return tsize;
+  }
+
+  /**
+   * This function determines, wheter the object should be saved to the bytestream (according to its syncmode/direction)
+   * @param mode Synchronisation mode (toclient, toserver or bidirectional)
+   * @return true/false
+   */
+  bool Synchronisable::doSync(/*int32_t id,*/ uint8_t mode)
+  {
+//     if(mode==0x0)
+//       mode=state_;
+    assert(mode!=0x0);
+    return ( (this->objectMode_ & mode)!=0 && (!syncList_.empty() ) );
+  }
+  
+  /**
+   * This function determines, wheter the object should accept data from the bytestream (according to its syncmode/direction)
+   * @param mode Synchronisation mode (toclient, toserver or bidirectional)
+   * @return true/false
+   */
+  bool Synchronisable::doReceive( uint8_t mode)
+  {
+    //return mode != this->objectMode_ || this->objectMode_ == ObjectDirection::Bidirectional;
+    return true;
+  }
+
+  /**
+   * This function sets the synchronisation mode of the object
+   * If set to 0x0 variables will not be synchronised at all
+   * If set to 0x1 variables will only be synchronised to the client
+   * If set to 0x2 variables will only be synchronised to the server
+   * If set to 0x3 variables will be synchronised bidirectionally (only if set so in registerVar)
+   * @param mode same as in registerVar
+   */
+  void Synchronisable::setSyncMode(uint8_t mode)
+  {
+    assert(mode==0x0 || mode==0x1 || mode==0x2 || mode==0x3);
+    this->objectMode_=mode;
+  }
+
+  template <> void Synchronisable::registerVariable( std::string& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional)
+  {
+    SynchronisableVariableBase* sv;
+    if (bidirectional)
+      sv = new SynchronisableVariableBidirectional<std::string>(variable, mode, cb);
+    else
+      sv = new SynchronisableVariable<std::string>(variable, mode, cb);
+    syncList_.push_back(sv);
+    stringList_.push_back(sv);
+  }
+
+template <> void Synchronisable::unregisterVariable( std::string& variable )
+  {
+    bool unregistered_nonexistent_variable = true;
+    std::vector<SynchronisableVariableBase*>::iterator it = syncList_.begin();
+    while(it!=syncList_.end())
+    {
+      if( ((*it)->getReference()) == &variable )
+      {
+        delete (*it);
+        syncList_.erase(it);
+        unregistered_nonexistent_variable = false;
+        break;
+      }
+      else
+        ++it;
+    }
+    assert(unregistered_nonexistent_variable == false);
+    (void)unregistered_nonexistent_variable; // avoid compiler warning
+    
+    it = stringList_.begin();
+    while(it!=stringList_.end())
+    {
+      if( ((*it)->getReference()) == &variable )
+      {
+        delete (*it);
+        stringList_.erase(it);
+        return;
+      }
+      else
+        ++it;
+    }
+    assert(false); //if we reach this point something went wrong:
+    // the variable has not been registered before
+  }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Synchronisable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Synchronisable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/Synchronisable.h	(revision 11817)
@@ -0,0 +1,274 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss, (C) 2007
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Synchronisable_H__
+#define _Synchronisable_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include <cassert>
+#include <cstring>
+#include <vector>
+#include <map>
+#include <queue>
+#include <set>
+#include <type_traits>
+
+#include "util/mbool.h"
+#include "util/Output.h"
+#include "core/class/OrxonoxInterface.h"
+#include "SynchronisableVariable.h"
+#include "NetworkCallback.h"
+
+
+namespace orxonox
+{
+
+  namespace ObjectDirection{
+    enum Value{
+      None=0x0,
+      ToClient=0x1,
+      ToServer=0x2,
+      Bidirectional=0x3
+    };
+  }
+
+  namespace Priority{
+    enum Value{
+      VeryHigh    = -100,
+      High        = -15,
+      Normal      = 0,
+      Low         = 15,
+      VeryLow     = 100
+    };
+  }
+
+    /**
+   * @brief: stores information about a Synchronisable (light version)
+   *
+   * This class stores the information about a Synchronisable (objectID_, dataSize)
+   * in an emulated bitset.
+   * Bit 1 to 31 store the size of the Data the synchronisable consumes in the stream
+   * Bit 32 is a bool and defines whether the variables are stored in diff mode
+   * Byte 5 to 8: objectID_
+   */
+  class _NetworkExport SynchronisableHeaderLight
+  {
+    protected:
+      uint8_t* data_;
+    public:
+      SynchronisableHeaderLight(uint8_t* data)
+        { data_ = data; }
+      inline static uint32_t getSize()
+        { return 6; }
+      inline uint16_t getDataSize() const
+        { return (*(uint16_t*)data_) & 0x7FFF; } //only use the first 31 bits
+      inline void setDataSize(uint16_t size)
+        { *(uint16_t*)(data_) = (size & 0x7FFFFFFF) | (*(uint16_t*)(data_) & 0x8000 ); }
+      inline bool isDiffed() const
+        { return ( (*(uint16_t*)data_) & 0x8000 ) == 0x8000; }
+      inline void setDiffed( bool b)
+        { *(uint16_t*)(data_) = (b << 15) | (*(uint16_t*)(data_) & 0x7FFF ); }
+      inline uint32_t getObjectID() const
+        { return *(uint32_t*)(data_+2); }
+      inline void setObjectID(uint32_t objectID_)
+        { *(uint32_t*)(data_+2) = objectID_; }
+      inline void operator=(SynchronisableHeaderLight& h)
+        { memcpy(data_, h.data_, SynchronisableHeaderLight::getSize()); }
+  };
+  
+  typedef uint8_t VariableID;
+  
+  /**
+   * @brief: stores information about a Synchronisable
+   *
+   * This class stores the information about a Synchronisable (objectID_, classID_, contextID_, dataSize)
+   * in an emulated bitset.
+   * Bit 1 to 31 store the size of the Data the synchronisable consumes in the stream
+   * Bit 32 is a bool and defines whether the variables are stored in diff mode
+   * Byte 5 to 8: objectID_
+   * Byte 9 to 12: classID_
+   * Byte 13 to 16: contextID_
+   */
+  class _NetworkExport SynchronisableHeader: public SynchronisableHeaderLight
+  {
+    public:
+      SynchronisableHeader(uint8_t* data): SynchronisableHeaderLight(data)
+        {}
+      inline static uint32_t getSize()
+        { return SynchronisableHeaderLight::getSize()+8; }
+      inline uint32_t getClassID() const
+        { return *(uint32_t*)(data_+SynchronisableHeaderLight::getSize()); }
+      inline void setClassID(uint32_t classID_)
+        { *(uint32_t*)(data_+SynchronisableHeaderLight::getSize()) = classID_; }
+      inline uint32_t getContextID() const
+        { return *(uint32_t*)(data_+SynchronisableHeaderLight::getSize()+4); }
+      inline void setContextID(uint32_t contextID_)
+        { *(uint32_t*)(data_+SynchronisableHeaderLight::getSize()+4) = contextID_; }
+      inline void operator=(SynchronisableHeader& h)
+        { memcpy(data_, h.data_, getSize()); }
+  };
+  
+//   inline void operator=(SynchronisableHeaderLight& h1, SynchronisableHeader& h2)
+//   {
+//     memcpy(h1.data_, h2.data_, h1.getSize());
+//   }
+
+  /**
+  * This class is the base class of all the Objects in the universe that need to be synchronised over the network
+  * Every class, that inherits from this class has to link the DATA THAT NEEDS TO BE SYNCHRONISED into the linked list.
+  * @author Oliver Scheuss
+  */
+  class _NetworkExport Synchronisable : virtual public OrxonoxInterface {
+  public:
+    friend class packet::Gamestate;
+    virtual ~Synchronisable();
+
+    static void setClient(bool b);
+
+    static Synchronisable *fabricate(uint8_t*& mem, uint8_t mode=0x0);
+    static bool deleteObject(uint32_t objectID_);
+    static Synchronisable *getSynchronisable(uint32_t objectID_);
+    static unsigned int getNumberOfDeletedObject(){ return deletedObjects_.size(); }
+    static uint32_t popDeletedObject(){ uint32_t i = deletedObjects_.front(); deletedObjects_.pop(); return i; }
+
+    inline uint32_t getObjectID() const {return this->objectID_;}
+    inline unsigned int getContextID() const {return this->contextID_;}
+    inline uint32_t getClassID() const {return this->classID_;}
+    inline unsigned int getPriority() const { return this->objectFrequency_;}
+    inline uint8_t getSyncMode() const { return this->objectMode_; }
+
+    void setSyncMode(uint8_t mode);
+    
+    inline uint32_t getNrOfVariables(){ return this->syncList_.size(); }
+    inline uint32_t getVarSize( VariableID ID )
+    { return this->syncList_[ID]->getSize(state_); }
+
+  protected:
+    Synchronisable(Context* context);
+    template <class T> void registerVariable(T& variable, uint8_t mode=0x1, NetworkCallbackBase *cb=nullptr, bool bidirectional=false);
+    template <class T> void registerVariable(std::set<T>& variable, uint8_t mode=0x1, NetworkCallbackBase *cb=nullptr, bool bidirectional=false);
+    template <class T> void unregisterVariable(T& var);
+
+    void setPriority(unsigned int freq){ objectFrequency_ = freq; }
+    uint32_t findContextID(Context* context);
+
+  private:
+    uint32_t getData(uint8_t*& mem, std::vector<uint32_t>& sizes, int32_t id, uint8_t mode);
+    uint32_t getSize(int32_t id, uint8_t mode=0x0);
+    bool updateData(uint8_t*& mem, uint8_t mode=0x0, bool forceCallback=false);
+    bool doSync(/*int32_t id,*/ uint8_t mode=0x0);
+    bool doReceive( uint8_t mode );
+
+    inline void setObjectID(uint32_t id){ this->objectID_ = id; objectMap_[this->objectID_] = this; }
+    inline void setClassID(uint32_t id){ this->classID_ = id; }
+
+    uint32_t objectID_;
+    uint32_t contextID_;
+    uint32_t classID_;
+
+    std::vector<SynchronisableVariableBase*> syncList_;
+    std::vector<SynchronisableVariableBase*> stringList_;
+    uint32_t dataSize_; //size of all variables except strings
+    static uint8_t state_; // detemines wheter we are server (default) or client
+    bool backsync_; // if true the variables with mode > 1 will be synchronised to server (client -> server)
+    unsigned int objectFrequency_;
+    int objectMode_;
+    static std::map<uint32_t, Synchronisable *> objectMap_;
+    static std::queue<uint32_t> deletedObjects_;
+  };
+
+  namespace detail
+  {
+    template <class T, bool = std::is_enum<T>::value>
+    struct UnderlyingType;
+    template <class T>
+    struct UnderlyingType<T, true> { typedef typename std::underlying_type<T>::type type; };
+    template <class T>
+    struct UnderlyingType<T, false> { typedef T type; };
+  }
+
+  template <class T>
+  void Synchronisable::registerVariable(T& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional)
+  {
+    typedef typename detail::UnderlyingType<T>::type UnderlyingType;
+    if (bidirectional)
+    {
+      syncList_.push_back(new SynchronisableVariableBidirectional<UnderlyingType>(reinterpret_cast<UnderlyingType&>(variable), mode, cb));
+      this->dataSize_ += syncList_.back()->getSize(state_);
+    }
+    else
+    {
+      syncList_.push_back(new SynchronisableVariable<UnderlyingType>(reinterpret_cast<UnderlyingType&>(variable), mode, cb));
+      if ( this->state_ == mode )
+        this->dataSize_ += syncList_.back()->getSize(state_);
+    }
+  }
+  
+  template <class T>
+  void Synchronisable::unregisterVariable(T& variable)
+  {
+    std::vector<SynchronisableVariableBase*>::iterator it = syncList_.begin();
+    while(it!=syncList_.end())
+    {
+      if( ((*it)->getReference()) == &variable )
+      {
+        this->dataSize_ -= (*it)->getSize(Synchronisable::state_);
+        delete (*it);
+        syncList_.erase(it);
+        return;
+      }
+      else
+        it++;
+    }
+    orxout(internal_error, context::network) << "Tried to unregister not registered variable" << endl;
+    assert(false); //if we reach this point something went wrong:
+    // the variable has not been registered before
+  }
+
+  template <class T>
+  void Synchronisable::registerVariable( std::set<T>& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional)
+  {
+    typedef typename detail::UnderlyingType<T>::type UnderlyingType;
+    SynchronisableVariableBase* sv;
+    if (bidirectional)
+      sv = new SynchronisableVariableBidirectional<std::set<UnderlyingType>>(reinterpret_cast<std::set<UnderlyingType>&>(variable), mode, cb);
+    else
+      sv = new SynchronisableVariable<std::set<UnderlyingType>>(reinterpret_cast<std::set<UnderlyingType>&>(variable), mode, cb);
+    syncList_.push_back(sv);
+    stringList_.push_back(sv);
+  }
+
+  template <> _NetworkExport void Synchronisable::registerVariable( std::string& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional);
+//   template <class T> _NetworkExport void Synchronisable::registerVariable<std::set<T>>( std::set<T>& variable, uint8_t mode, NetworkCallbackBase *cb, bool bidirectional);
+  template <> _NetworkExport void Synchronisable::unregisterVariable( std::string& variable );
+
+
+}
+
+#endif /* _Synchronisable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/SynchronisableVariable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/SynchronisableVariable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/network/synchronisable/SynchronisableVariable.h	(revision 11817)
@@ -0,0 +1,255 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _SynchronisableVariable_H__
+#define _SynchronisableVariable_H__
+
+#include "network/NetworkPrereqs.h"
+
+#include <cassert>
+#include <cstring>
+#include <loki/TypeTraits.h>
+
+#include "Serialise.h"
+#include "core/GameMode.h"
+#include "network/synchronisable/NetworkCallbackManager.h"
+
+namespace orxonox{
+
+  namespace VariableDirection{
+    enum Value{
+      ToClient=0x1,
+      ToServer=0x2
+    };
+  }
+  namespace Bidirectionality{
+    enum Value{
+      ServerMaster=0x1,
+      ClientMaster=0x2
+    };
+  }
+
+  class _NetworkExport SynchronisableVariableBase
+  {
+    public:
+      virtual uint32_t getData(uint8_t*& mem, uint8_t mode)=0;
+      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false)=0;
+      virtual uint32_t getSize(uint8_t mode)=0;
+      virtual void* getReference()=0;
+      virtual uint8_t getMode()=0;
+      virtual ~SynchronisableVariableBase() {}
+  };
+
+  template <class T>
+  class SynchronisableVariable: public SynchronisableVariableBase
+  {
+    public:
+      SynchronisableVariable(T& variable, uint8_t syncDirection=VariableDirection::ToClient, NetworkCallbackBase *cb=nullptr);
+      virtual ~SynchronisableVariable();
+
+      virtual inline uint8_t getMode() override{ return mode_; }
+      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode) override;
+      virtual inline void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false) override;
+      virtual inline uint32_t getSize(uint8_t mode) override;
+      virtual inline void* getReference() override{ return static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->variable_)); }
+    protected:
+      T&                       variable_;
+      uint8_t                  mode_;
+      NetworkCallbackBase      *callback_;
+  };
+
+  template <class T>
+  class SynchronisableVariableBidirectional: public SynchronisableVariable<T>
+  {
+    public:
+      SynchronisableVariableBidirectional(T& variable, uint8_t master=Bidirectionality::ServerMaster, NetworkCallbackBase *cb=nullptr);
+      virtual ~SynchronisableVariableBidirectional();
+
+      virtual inline uint8_t getMode(){ return 0x3; } //this basically is a hack ^^
+      virtual inline uint32_t getData(uint8_t*& mem, uint8_t mode);
+      virtual void putData(uint8_t*& mem, uint8_t mode, bool forceCallback = false);
+      virtual inline uint32_t getSize(uint8_t mode);
+    private:
+      T varBuffer_;
+      uint8_t varReference_;
+  };
+
+  // ================= Unidirectional Part ===============
+
+  template <class T> SynchronisableVariable<T>::SynchronisableVariable(T& variable, uint8_t syncDirection, NetworkCallbackBase *cb):
+      variable_( variable ), mode_( syncDirection ), callback_( cb )
+  {
+  }
+
+  template <class T> SynchronisableVariable<T>::~SynchronisableVariable()
+  {
+    if (this->callback_)
+    {
+      NetworkCallbackManager::deleteCallback(this->callback_); //safe call for deletion
+      // this is neccessary because for example for a Vector3 all 3 components of the vector use the same callback
+    }
+  }
+
+  template <class T> inline uint32_t SynchronisableVariable<T>::getData(uint8_t*& mem, uint8_t mode)
+  {
+    if ( mode == this->mode_ )
+    {
+      saveAndIncrease( this->variable_, mem );
+      return returnSize( this->variable_ );
+    }
+    else
+      return 0;
+  }
+
+  template <class T> void SynchronisableVariable<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
+  {
+    assert ( mode == 0x1 || mode == 0x2 );
+    bool callback = false;
+    if ( mode == this->mode_ ) //don't do anything
+      return;
+  // check whether we need to consider a callback
+    if ( this->callback_ )
+    {
+      callback = forceCallback || !checkEquality( this->variable_, mem );
+    }
+  // now do a callback if neccessary
+    if ( callback )
+    {
+      NetworkCallbackManager::triggerCallback( this->callback_ );
+    }
+  // write the data
+    loadAndIncrease( this->variable_, mem );
+  }
+
+  template <class T> inline uint32_t SynchronisableVariable<T>::getSize(uint8_t mode)
+  {
+    if ( mode == this->mode_ )
+      return returnSize( this->variable_ );
+    else
+      return 0;
+  }
+
+
+
+
+// ================= Bidirectional Part ================
+
+    template <class T> SynchronisableVariableBidirectional<T>::SynchronisableVariableBidirectional(T& variable, uint8_t master, NetworkCallbackBase *cb):
+    SynchronisableVariable<T>( variable, master, cb ), varBuffer_( variable ), varReference_( 0 )
+    {
+    }
+
+    template <class T> SynchronisableVariableBidirectional<T>::~SynchronisableVariableBidirectional()
+    {
+    }
+
+    template <class T> uint32_t SynchronisableVariableBidirectional<T>::getData(uint8_t*& mem, uint8_t mode)
+    {
+      if ( this->mode_ == mode )
+      {   // we are master for this variable and have to check whether to change the varReference
+        if( this->varBuffer_ != this->variable_ )
+        {
+          this->varReference_++;
+          memcpy(static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->varBuffer_)), &this->variable_, sizeof(this->variable_));
+        }
+      }
+  // write the reference number to the stream
+      *static_cast<uint8_t*>(mem) = varReference_;
+      mem += sizeof(this->varReference_);
+  // now write the content
+      saveAndIncrease( this->variable_, mem );
+      return SynchronisableVariableBidirectional::getSize(mode);
+    }
+
+    template <class T> void SynchronisableVariableBidirectional<T>::putData(uint8_t*& mem, uint8_t mode, bool forceCallback)
+    {
+      bool callback = false;
+      if ( this->mode_ == mode )
+      {   //        MASTER
+        // check that the client (source of the data) has a recent version of this variable
+        if ( *static_cast<uint8_t*>(mem) != this->varReference_ )
+        { // wrong reference number, so discard the data
+//           orxout(debug_output, context::network) << "discharding data" << endl;
+          mem += getSize( mode ); // SynchronisableVariableBidirectional::getSize returns size of variable + reference
+          return;
+        }
+        else{
+          // apply data
+          if ( checkEquality( this->variable_, mem+sizeof(varReference_) )==true )
+          {
+            mem += getSize( mode );
+            return;
+          }
+          else
+          {
+            mem += sizeof(varReference_);
+            memcpy(static_cast<void*>(const_cast<typename Loki::TypeTraits<T>::UnqualifiedType*>(&this->varBuffer_)), &this->variable_, sizeof(T));
+            if ( this->callback_ )
+              callback = true;
+          }
+        }
+      }
+      else
+      {   // we are slave for this variable
+        if (*static_cast<uint8_t*>(mem) == this->varReference_ && !forceCallback)
+        {
+          mem += getSize( mode ); //just skip the variable because nothing changed
+          return;
+        }
+        else
+        {
+          this->varReference_ = *static_cast<uint8_t*>(mem);
+          mem += sizeof(varReference_);
+          if ( checkEquality( this->variable_, mem ) == false )
+          {
+            // value changed so remark for callback
+            if ( this->callback_ )
+              callback = true;
+          }
+        }
+      }
+  // now do a callback if neccessary
+      if ( callback )
+      {
+        NetworkCallbackManager::triggerCallback( this->callback_ );
+      }
+  // now write the data
+      loadAndIncrease(this->variable_, mem);
+    }
+
+    template <class T> inline uint32_t SynchronisableVariableBidirectional<T>::getSize(uint8_t mode)
+    {
+      return returnSize( this->variable_ ) + sizeof(varReference_);
+    }
+
+
+}
+
+
+#endif /* _SynchronisableVariable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/BillboardSet.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/BillboardSet.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/BillboardSet.cc	(revision 11817)
@@ -0,0 +1,155 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "BillboardSet.h"
+
+#include <cassert>
+#include <string>
+#include <sstream>
+#include <OgreSceneManager.h>
+#include <OgreBillboardSet.h>
+#include <OgreBillboard.h>
+
+#include "util/Convert.h"
+#include "util/Math.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+    unsigned int BillboardSet::billboardSetCounter_s = 0;
+
+    BillboardSet::BillboardSet()
+    {
+        this->billboardSet_ = nullptr;
+    }
+
+    BillboardSet::~BillboardSet()
+    {
+        this->destroyBillboardSet();
+    }
+
+    void BillboardSet::setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, int count)
+    {
+        this->setBillboardSet(scenemanager, file, Vector3::ZERO, count);
+    }
+
+    void BillboardSet::setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, const ColourValue& colour, int count)
+    {
+        this->setBillboardSet(scenemanager, file, colour, Vector3::ZERO, count);
+    }
+
+    void BillboardSet::setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, const Vector3& position, int count)
+    {
+        this->setBillboardSet(scenemanager, file, ColourValue::White, position, count);
+    }
+
+    void BillboardSet::setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, const ColourValue& colour, const Vector3& position, int count)
+    {
+        assert(scenemanager);
+        this->destroyBillboardSet();
+
+        try
+        {
+            if (GameMode::showsGraphics())
+            {
+                this->billboardSet_ = scenemanager->createBillboardSet("Billboard" + multi_cast<std::string>(BillboardSet::billboardSetCounter_s++), count);
+                this->billboardSet_->createBillboard(position, colour);
+                this->billboardSet_->setMaterialName(file);
+            }
+        }
+        catch (...)
+        {
+            orxout(internal_error) << "Couldn't load billboard \"" << file << '"' << endl;
+            this->billboardSet_ = nullptr;
+        }
+
+        this->scenemanager_ = scenemanager;
+    }
+
+    void BillboardSet::destroyBillboardSet()
+    {
+        if (this->billboardSet_ && this->scenemanager_)
+            this->scenemanager_->destroyBillboardSet(this->billboardSet_);
+        this->billboardSet_ = nullptr;
+    }
+
+    const std::string& BillboardSet::getName() const
+    {
+        if (this->billboardSet_)
+            return this->billboardSet_->getName();
+        else
+            return BLANKSTRING;
+    }
+
+    void BillboardSet::setVisible(bool visible)
+    {
+        if (this->billboardSet_)
+            this->billboardSet_->setVisible(visible);
+    }
+
+    bool BillboardSet::getVisible() const
+    {
+        if (this->billboardSet_)
+            return this->billboardSet_->getVisible();
+        else
+            return false;
+    }
+
+    void BillboardSet::setColour(const ColourValue& colour)
+    {
+        if (this->billboardSet_)
+        {
+            for (int i = 0; i < this->billboardSet_->getNumBillboards(); ++i)
+                this->billboardSet_->getBillboard(i)->setColour(colour);
+        }
+    }
+
+    const ColourValue& BillboardSet::getColour() const
+    {
+        if (this->billboardSet_ && this->billboardSet_->getNumBillboards() > 0)
+        {
+            return this->billboardSet_->getBillboard(0)->getColour();
+        }
+        else
+            return ColourValue::White;
+    }
+
+    void BillboardSet::setMaterial(const std::string& material)
+    {
+        if (this->billboardSet_)
+            this->billboardSet_->setMaterialName(material);
+    }
+
+    const std::string& BillboardSet::getMaterial() const
+    {
+        if (this->billboardSet_)
+            return this->billboardSet_->getMaterialName();
+        else
+            return BLANKSTRING;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/BillboardSet.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/BillboardSet.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/BillboardSet.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _BillboardSet_H__
+#define _BillboardSet_H__
+
+#include "tools/ToolsPrereqs.h"
+#include "util/OgreForwardRefs.h"
+
+namespace orxonox
+{
+    class _ToolsExport BillboardSet
+    {
+        public:
+            BillboardSet();
+            ~BillboardSet();
+
+            void setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, int count = 1);
+            void setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, const ColourValue& colour, int count = 1);
+            void setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, const Vector3& position, int count = 1);
+            void setBillboardSet(Ogre::SceneManager* scenemanager, const std::string& file, const ColourValue& colour, const Vector3& position, int count = 1);
+
+            inline Ogre::BillboardSet* getBillboardSet()
+                { return this->billboardSet_; }
+            inline Ogre::SceneManager* getSceneManager() const
+                { return this->scenemanager_; }
+
+            const std::string& getName() const;
+
+            void setVisible(bool visible);
+            bool getVisible() const;
+
+            void setColour(const ColourValue& colour);
+            const ColourValue& getColour() const;
+
+            void setMaterial(const std::string& material);
+            const std::string& getMaterial() const;
+
+        private:
+            void destroyBillboardSet();
+
+            Ogre::BillboardSet* billboardSet_;
+            Ogre::SceneManager* scenemanager_;
+
+            static unsigned int billboardSetCounter_s;
+    };
+}
+
+#endif /* _BillboardSet_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/BulletConversions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/BulletConversions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/BulletConversions.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _BulletConversions_H__
+#define _BulletConversions_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include "util/Convert.h"
+#include "util/Math.h"
+#include <LinearMath/btQuaternion.h>
+#include <LinearMath/btVector3.h>
+
+namespace orxonox
+{
+    // Vector3 to btVector3
+    template <>
+    struct ConverterExplicit<orxonox::Vector3, btVector3>
+    {
+        ORX_FORCEINLINE static bool convert(btVector3* output, const orxonox::Vector3& input)
+        {
+            output->setX(input.x);
+            output->setY(input.y);
+            output->setZ(input.z);
+            return true;
+        }
+    };
+
+    // btVector3 to Vector3
+    template <>
+    struct ConverterExplicit<btVector3, orxonox::Vector3>
+    {
+        ORX_FORCEINLINE static bool convert(orxonox::Vector3* output, const btVector3& input)
+        {
+            output->x = input.x();
+            output->y = input.y();
+            output->z = input.z();
+            return true;
+        }
+    };
+
+    // Quaternion to btQuaternion
+    template <>
+    struct ConverterExplicit<orxonox::Quaternion, btQuaternion>
+    {
+        ORX_FORCEINLINE static bool convert(btQuaternion* output, const orxonox::Quaternion& input)
+        {
+            output->setW(input.w);
+            output->setX(input.x);
+            output->setY(input.y);
+            output->setZ(input.z);
+            return true;
+        }
+    };
+
+    // btQuaternion to Vector3
+    template <>
+    struct ConverterExplicit<btQuaternion, orxonox::Quaternion>
+    {
+        ORX_FORCEINLINE static bool convert(orxonox::Quaternion* output, const btQuaternion& input)
+        {
+            output->w = input.w();
+            output->x = input.x();
+            output->y = input.y();
+            output->z = input.z();
+            return true;
+        }
+    };
+}
+
+#endif /* _BulletConversions_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/BulletDebugDrawer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/BulletDebugDrawer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/BulletDebugDrawer.cc	(revision 11817)
@@ -0,0 +1,166 @@
+/**
+ * @file BulletDebugDrawer.cc
+ * Originally from http://www.ogre3d.org/tikiwiki/BulletDebugDrawer&structure=Cookbook
+ * This source code is released into the Public Domain.
+ *
+ * Modified by Fabian 'x3n' Landau by using DebugDrawer and Orxonox specific utilities (e.g. output).
+ */
+
+#include "BulletDebugDrawer.h"
+#include "OgreBulletUtils.h"
+
+#include <OgreRoot.h>
+#include <OgreManualObject.h>
+#include <OgreSceneManager.h>
+#include <OgreTimer.h>
+
+#include "util/Output.h"
+#include "DebugDrawer.h"
+
+namespace orxonox
+{
+    BulletDebugDrawer::BulletDebugDrawer(Ogre::SceneManager* sceneManager)
+    {
+        this->drawer_ = new DebugDrawer(sceneManager, 0.5f);
+        this->bFill_ = true;
+
+        mContactPoints = &mContactPoints1;
+
+        mDebugMode = (DebugDrawModes) DBG_DrawWireframe;
+        Ogre::Root::getSingleton().addFrameListener(this);
+    }
+
+    BulletDebugDrawer::~BulletDebugDrawer()
+    {
+        Ogre::Root::getSingleton().removeFrameListener(this);
+        delete this->drawer_;
+    }
+
+    void BulletDebugDrawer::drawLine(const btVector3& from, const btVector3& to, const btVector3& color)
+    {
+        this->drawer_->drawLine(vector3(from), vector3(to), colour(color, 1.0f));
+    }
+
+//    void BulletDebugDrawer::drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& color, btScalar alpha)
+//    {
+//        // TODO
+//    }
+
+    void BulletDebugDrawer::drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
+    {
+        this->drawer_->drawSphere(vector3(p), Ogre::Quaternion::IDENTITY, radius, colour(color, 1.0f), this->bFill_);
+    }
+
+    void BulletDebugDrawer::drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
+    {
+        Ogre::Matrix4 matrix = matrix4(transform);
+        this->drawer_->drawSphere(matrix.getTrans(), matrix.extractQuaternion(), radius, colour(color, 1.0f), this->bFill_);
+    }
+
+    void BulletDebugDrawer::drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
+    {
+        Ogre::Vector3* corners = new Ogre::Vector3[8];
+        corners[0]  = Ogre::Vector3(bbMin[0], bbMin[1], bbMin[2]);
+        corners[1]  = Ogre::Vector3(bbMin[0], bbMax[1], bbMin[2]);
+        corners[2]  = Ogre::Vector3(bbMax[0], bbMax[1], bbMin[2]);
+        corners[3]  = Ogre::Vector3(bbMax[0], bbMin[1], bbMin[2]);
+        corners[4]  = Ogre::Vector3(bbMax[0], bbMax[1], bbMax[2]);
+        corners[5]  = Ogre::Vector3(bbMin[0], bbMax[1], bbMax[2]);
+        corners[6]  = Ogre::Vector3(bbMin[0], bbMin[1], bbMax[2]);
+        corners[7]  = Ogre::Vector3(bbMax[0], bbMin[1], bbMax[2]);
+        this->drawer_->drawCuboid(corners, colour(color, 1.0f), this->bFill_);
+    }
+
+    void BulletDebugDrawer::drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
+    {
+        Ogre::Vector3* corners = new Ogre::Vector3[8];
+        corners[0]  = Ogre::Vector3(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]));
+        corners[1]  = Ogre::Vector3(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]));
+        corners[2]  = Ogre::Vector3(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]));
+        corners[3]  = Ogre::Vector3(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]));
+        corners[4]  = Ogre::Vector3(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]));
+        corners[5]  = Ogre::Vector3(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]));
+        corners[6]  = Ogre::Vector3(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]));
+        corners[7]  = Ogre::Vector3(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]));
+        this->drawer_->drawCuboid(corners, colour(color, 1.0f), this->bFill_);
+    }
+
+    void BulletDebugDrawer::drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
+    {
+        Ogre::Matrix4 matrix = matrix4(transform);
+        this->drawer_->drawCylinder(matrix.getTrans(), matrix.extractQuaternion(), radius, halfHeight * 2, colour(color, 1.0f), this->bFill_);
+    }
+
+    void BulletDebugDrawer::drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
+    {
+        Ogre::Matrix4 matrix = matrix4(transform);
+        this->drawer_->drawCone(matrix.getTrans(), matrix.extractQuaternion(), radius, height, colour(color, 1.0f), this->bFill_);
+    }
+
+    void BulletDebugDrawer::drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color)
+    {
+        mContactPoints->resize(mContactPoints->size() + 1);
+        ContactPoint p = mContactPoints->back();
+        p.from = vector3(PointOnB);
+        p.to = p.from + vector3(normalOnB) * distance;
+        p.dieTime = Ogre::Root::getSingleton().getTimer()->getMilliseconds() + lifeTime;
+        p.color.r = color.x();
+        p.color.g = color.y();
+        p.color.b = color.z();
+    }
+
+    bool BulletDebugDrawer::frameStarted(const Ogre::FrameEvent& evt)
+    {
+        size_t now = Ogre::Root::getSingleton().getTimer()->getMilliseconds();
+        std::vector<ContactPoint>* newCP = mContactPoints == &mContactPoints1 ? &mContactPoints2 : &mContactPoints1;
+        for (std::vector<ContactPoint>::iterator i = mContactPoints->begin(); i < mContactPoints->end(); i++ )
+        {
+            ContactPoint& cp = *i;
+            this->drawer_->drawLine(cp.from, cp.to, cp.color);
+            if (now <= cp.dieTime)
+                newCP->push_back(cp);
+        }
+        mContactPoints->clear();
+        mContactPoints = newCP;
+
+        // Right before the frame is rendered, call DebugDrawer::build().
+        this->drawer_->build();
+
+        return true;
+    }
+
+    bool BulletDebugDrawer::frameEnded(const Ogre::FrameEvent& evt)
+    {
+        // After the frame is rendered, call DebugDrawer::clear()
+        this->drawer_->clear();
+
+        return true;
+    }
+
+    void BulletDebugDrawer::reportErrorWarning(const char* warningString)
+    {
+        orxout(internal_error) << warningString << endl;
+        Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(warningString);
+    }
+
+    void BulletDebugDrawer::draw3dText(const btVector3& location, const char* textString)
+    {
+
+    }
+
+    void BulletDebugDrawer::setDebugMode(int debugMode)
+    {
+        mDebugMode = (DebugDrawModes) debugMode;
+    }
+
+    int BulletDebugDrawer::getDebugMode() const
+    {
+        return mDebugMode;
+    }
+
+    void BulletDebugDrawer::configure(bool bFill, float fillAlpha)
+    {
+        this->bFill_ = bFill;
+        this->drawer_->setFillAlpha(fillAlpha);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/BulletDebugDrawer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/BulletDebugDrawer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/BulletDebugDrawer.h	(revision 11817)
@@ -0,0 +1,67 @@
+#ifndef _BulletDebugDrawer_H__
+#define _BulletDebugDrawer_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <btBulletCollisionCommon.h>
+#include <OgreFrameListener.h>
+#include <OgreVector3.h>
+#include <OgreColourValue.h>
+
+namespace orxonox
+{
+    /**
+    * Originally from http://www.ogre3d.org/tikiwiki/BulletDebugDrawer&structure=Cookbook
+    * This source code is released into the Public Domain.
+    *
+    * Modified by Fabian 'x3n' Landau by using DebugDrawer and Orxonox specific utilities (e.g. output).
+    */
+    class _ToolsExport BulletDebugDrawer : public btIDebugDraw, public Ogre::FrameListener
+    {
+        public:
+            BulletDebugDrawer(Ogre::SceneManager* sceneManager);
+            ~BulletDebugDrawer();
+            virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override;
+//            virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& color, btScalar) override;
+            virtual void drawSphere (const btVector3& p, btScalar radius, const btVector3& color) override;
+            virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color) override;
+            virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color) override;
+            virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color) override;
+            virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color) override;
+            virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color) override;
+//            virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color) override;
+
+            virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override;
+
+            virtual void reportErrorWarning(const char* warningString) override;
+            virtual void draw3dText(const btVector3& location, const char* textString) override;
+
+            virtual void setDebugMode(int debugMode) override;
+            virtual int getDebugMode() const override;
+
+            void configure(bool bFill, float fillAlpha);
+
+        protected:
+            virtual bool frameStarted(const Ogre::FrameEvent& evt) override;
+            virtual bool frameEnded(const Ogre::FrameEvent& evt) override;
+
+        private:
+            struct ContactPoint
+            {
+                Ogre::Vector3 from;
+                Ogre::Vector3 to;
+                Ogre::ColourValue color;
+                size_t dieTime;
+            };
+
+            bool bFill_;
+            DebugDrawer* drawer_;
+
+            DebugDrawModes mDebugMode;
+            std::vector<ContactPoint>* mContactPoints;
+            std::vector<ContactPoint> mContactPoints1;
+            std::vector<ContactPoint> mContactPoints2;
+    };
+}
+
+#endif /* _BulletDebugDrawer_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,39 @@
+SET_SOURCE_FILES(TOOLS_SRC_FILES
+
+BUILD_UNIT ResourceBuildUnit.cc
+  ResourceCollection.cc
+  ResourceLocation.cc
+END_BUILD_UNIT
+
+  TextureGenerator.cc
+  Timer.cc
+
+BUILD_UNIT OgreBuildUnit.cc
+  BillboardSet.cc
+  BulletDebugDrawer.cc
+  DebugDrawer.cc
+  DynamicLines.cc
+  DynamicRenderable.cc
+  IcoSphere.cc
+  Mesh.cc
+  ParticleInterface.cc
+  Shader.cc
+END_BUILD_UNIT
+)
+
+#ADD_SUBDIRECTORY(bsp)
+ADD_SUBDIRECTORY(interfaces)
+
+ORXONOX_ADD_LIBRARY(tools
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    ${OGRE_LIBRARY}
+    ${Boost_FILESYSTEM_LIBRARY}
+    ${Boost_SYSTEM_LIBRARY} # Filesystem dependency
+    tinyxml_orxonox
+    bullet_orxonox
+    util
+    core
+  SOURCE_FILES
+    ${TOOLS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/libraries/tools/DebugDrawer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/DebugDrawer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/DebugDrawer.cc	(revision 11817)
@@ -0,0 +1,469 @@
+/**
+ * @file DebugDrawer.cc
+ * Copy-pasted from
+ *  - https://bitbucket.org/hasyimi/ogre-debug-drawing-utility/src
+ *  - http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Debug+Drawing+Utility+Class
+ *
+ * This source code is released into the Public Domain.
+ *
+ * Modified by Fabian 'x3n' Landau
+ */
+
+#include "DebugDrawer.h"
+
+#include <OgreSceneManager.h>
+#include <OgreRenderQueue.h>
+#include <OgreManualObject.h>
+#include <OgreAxisAlignedBox.h>
+
+#define DEFAULT_ICOSPHERE_RECURSION_LEVEL 1
+
+namespace orxonox
+{
+    DebugDrawer::DebugDrawer(Ogre::SceneManager *_sceneManager, float _fillAlpha) :
+            sceneManager(_sceneManager), fillAlpha(_fillAlpha), manualObject(nullptr), isEnabled(true), linesIndex(0), trianglesIndex(0)
+    {
+        initialise();
+    }
+
+    DebugDrawer::~DebugDrawer()
+    {
+        shutdown();
+    }
+
+    void DebugDrawer::initialise()
+    {
+        manualObject = sceneManager->createManualObject("debug_object");
+        sceneManager->getRootSceneNode()->createChildSceneNode("debug_object")->attachObject(manualObject);
+        manualObject->setDynamic(true);
+
+        icoSphere0.create(0);
+        icoSphere1.create(1);
+        icoSphere2.create(2);
+        icoSphere3.create(3);
+        icoSphere4.create(4);
+
+        manualObject->begin("debug_draw", Ogre::RenderOperation::OT_LINE_LIST);
+        manualObject->position(Ogre::Vector3::ZERO);
+        manualObject->colour(Ogre::ColourValue::ZERO);
+        manualObject->index(0);
+        manualObject->end();
+        manualObject->begin("debug_draw", Ogre::RenderOperation::OT_TRIANGLE_LIST);
+        manualObject->position(Ogre::Vector3::ZERO);
+        manualObject->colour(Ogre::ColourValue::ZERO);
+        manualObject->index(0);
+        manualObject->end();
+
+        linesIndex = trianglesIndex = 0;
+    }
+
+    void DebugDrawer::shutdown()
+    {
+        sceneManager->destroySceneNode("debug_object");
+        sceneManager->destroyManualObject(manualObject);
+    }
+
+    void DebugDrawer::buildLine(const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::ColourValue& colour, float alpha)
+    {
+        int i = addLineVertex(start, Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(end, Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        addLineIndices(i, i + 1);
+    }
+
+    void DebugDrawer::buildQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = addLineVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(vertices[1], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(vertices[2], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(vertices[3], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        for (int i = 0; i < 4; ++i)
+            addLineIndices(index + i, index + ((i + 1) % 4));
+    }
+
+    void DebugDrawer::buildCircle(const Ogre::Matrix4& transform, float radius, int segmentsCount, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = linesIndex;
+        float increment = 2 * Ogre::Math::PI / segmentsCount;
+        float angle = 0.0f;
+
+        for (int i = 0; i < segmentsCount; i++)
+        {
+            addLineVertex(transform * Ogre::Vector3(radius * Ogre::Math::Cos(angle), 0, radius * Ogre::Math::Sin(angle)),
+                    Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+            angle += increment;
+        }
+
+        for (int i = 0; i < segmentsCount; i++)
+            addLineIndices(index + i, i + 1 < segmentsCount ? index + i + 1 : index);
+    }
+
+    void DebugDrawer::buildFilledCircle(const Ogre::Matrix4& transform, float radius, int segmentsCount, const Ogre::ColourValue& colour, bool up, float alpha)
+    {
+        int index = trianglesIndex;
+        float increment = 2 * Ogre::Math::PI / segmentsCount;
+        float angle = 0.0f;
+
+        for (int i = 0; i < segmentsCount; i++)
+        {
+            addTriangleVertex(transform * Ogre::Vector3(radius * Ogre::Math::Cos(angle), 0, radius * Ogre::Math::Sin(angle)),
+                    Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+            angle += increment;
+        }
+
+        addTriangleVertex(transform.getTrans(), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        for (int i = 0; i < segmentsCount; i++)
+        {
+            if (up)
+                addTriangleIndices(i + 1 < segmentsCount ? index + i + 1 : index, index + i, index + segmentsCount);
+            else
+                addTriangleIndices(index + i, i + 1 < segmentsCount ? index + i + 1 : index, index + segmentsCount);
+        }
+    }
+
+    void DebugDrawer::buildCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = linesIndex;
+
+        Ogre::Matrix4 transform(rotation);
+        transform.setTrans(centre + rotation * Ogre::Vector3(0, height / 2, 0));
+        this->buildCircle(transform, radius, segmentsCount, colour, alpha);
+        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
+        this->buildCircle(transform, radius, segmentsCount, colour, alpha);
+
+        for (int i = 0; i < segmentsCount; i++)
+            addLineIndices(index + i, segmentsCount + index + i);
+    }
+
+    void DebugDrawer::buildFilledCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour,
+            float alpha)
+    {
+        int index = trianglesIndex;
+
+        Ogre::Matrix4 transform(rotation);
+        transform.setTrans(centre + rotation * Ogre::Vector3(0, height / 2, 0));
+        this->buildCircle(transform, radius, segmentsCount, colour);
+        this->buildFilledCircle(transform, radius, segmentsCount, colour, true, alpha);
+
+        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
+        this->buildCircle(transform, radius, segmentsCount, colour);
+        this->buildFilledCircle(transform, radius, segmentsCount, colour, false, alpha);
+
+        for (int i = 0; i < segmentsCount; i++)
+        {
+            addQuadIndices(index + i, i + 1 < segmentsCount ? index + i + 1 : index,
+                    i + 1 < segmentsCount ? (segmentsCount + 1) + index + i + 1 : (segmentsCount + 1) + index, (segmentsCount + 1) + index + i);
+        }
+    }
+
+    void DebugDrawer::buildCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = linesIndex;
+
+        Ogre::Matrix4 transform(rotation);
+        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
+        this->buildCircle(transform, radius, segmentsCount, colour, alpha);
+
+        addLineVertex(centre + rotation * Ogre::Vector3(0, height / 2, 0), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        for (int i = 0; i < segmentsCount; i++)
+            addLineIndices(index + i, index + segmentsCount);
+    }
+
+    void DebugDrawer::buildFilledCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour,
+            float alpha)
+    {
+        int index = trianglesIndex;
+
+        Ogre::Matrix4 transform(rotation);
+        transform.setTrans(centre + rotation * Ogre::Vector3(0, -height / 2, 0));
+        this->buildCircle(transform, radius, segmentsCount, colour);
+        this->buildFilledCircle(transform, radius, segmentsCount, colour, false, alpha);
+
+        addTriangleVertex(centre + rotation * Ogre::Vector3(0, height / 2, 0), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        for (int i = 0; i < segmentsCount; i++)
+            addTriangleIndices(index + i, index + segmentsCount + 1, i + 1 < segmentsCount ? index + i + 1 : index);
+    }
+
+    void DebugDrawer::buildCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = addLineVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        for (int i = 1; i < 8; ++i)
+            addLineVertex(vertices[i], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        for (int i = 0; i < 4; ++i)
+            addLineIndices(index + i, index + ((i + 1) % 4));
+        for (int i = 4; i < 8; ++i)
+            addLineIndices(index + i, i == 7 ? index + 4 : index + i + 1);
+        addLineIndices(index + 1, index + 5);
+        addLineIndices(index + 2, index + 4);
+        addLineIndices(index, index + 6);
+        addLineIndices(index + 3, index + 7);
+    }
+
+    void DebugDrawer::buildFilledCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = addTriangleVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        for (int i = 1; i < 8; ++i)
+            addTriangleVertex(vertices[i], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        addQuadIndices(index, index + 1, index + 2, index + 3);
+        addQuadIndices(index + 4, index + 5, index + 6, index + 7);
+
+        addQuadIndices(index + 1, index + 5, index + 4, index + 2);
+        addQuadIndices(index, index + 3, index + 7, index + 6);
+
+        addQuadIndices(index + 1, index, index + 6, index + 5);
+        addQuadIndices(index + 4, index + 7, index + 3, index + 2);
+    }
+
+    void DebugDrawer::buildFilledQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = addTriangleVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(vertices[1], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(vertices[2], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(vertices[3], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        addQuadIndices(index, index + 1, index + 2, index + 3);
+    }
+
+    void DebugDrawer::buildFilledTriangle(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = addTriangleVertex(vertices[0], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(vertices[1], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(vertices[2], Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        addTriangleIndices(index, index + 1, index + 2);
+    }
+
+    void DebugDrawer::buildTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = linesIndex;
+
+        // Distance from the centre
+        float bottomDistance = scale * 0.2f;
+        float topDistance = scale * 0.62f;
+        float frontDistance = scale * 0.289f;
+        float backDistance = scale * 0.577f;
+        float leftRightDistance = scale * 0.5f;
+
+        addLineVertex(Ogre::Vector3(centre.x, centre.y + topDistance, centre.z), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(Ogre::Vector3(centre.x, centre.y - bottomDistance, centre.z + frontDistance), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(Ogre::Vector3(centre.x + leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
+                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addLineVertex(Ogre::Vector3(centre.x - leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
+                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        addLineIndices(index, index + 1);
+        addLineIndices(index, index + 2);
+        addLineIndices(index, index + 3);
+
+        addLineIndices(index + 1, index + 2);
+        addLineIndices(index + 2, index + 3);
+        addLineIndices(index + 3, index + 1);
+    }
+
+    void DebugDrawer::buildFilledTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, float alpha)
+    {
+        int index = trianglesIndex;
+
+        // Distance from the centre
+        float bottomDistance = scale * 0.2f;
+        float topDistance = scale * 0.62f;
+        float frontDistance = scale * 0.289f;
+        float backDistance = scale * 0.577f;
+        float leftRightDistance = scale * 0.5f;
+
+        addTriangleVertex(Ogre::Vector3(centre.x, centre.y + topDistance, centre.z), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(Ogre::Vector3(centre.x, centre.y - bottomDistance, centre.z + frontDistance), Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(Ogre::Vector3(centre.x + leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
+                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+        addTriangleVertex(Ogre::Vector3(centre.x - leftRightDistance, centre.y - bottomDistance, centre.z - backDistance),
+                Ogre::ColourValue(colour.r, colour.g, colour.b, alpha));
+
+        addTriangleIndices(index, index + 1, index + 2);
+        addTriangleIndices(index, index + 2, index + 3);
+        addTriangleIndices(index, index + 3, index + 1);
+
+        addTriangleIndices(index + 1, index + 3, index + 2);
+    }
+
+    void DebugDrawer::drawLine(const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::ColourValue& colour)
+    {
+        buildLine(start, end, colour);
+    }
+
+    void DebugDrawer::drawCircle(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        int segmentsCount = std::min<int>(100, (int) (radius / 2.5));
+
+        Ogre::Matrix4 transform(rotation);
+        transform.setTrans(centre);
+
+        buildCircle(transform, radius, segmentsCount, colour);
+        if (isFilled)
+            buildFilledCircle(transform, radius, segmentsCount, colour, fillAlpha);
+    }
+
+    void DebugDrawer::drawCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, float height, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        int segmentsCount = std::min<int>(100, (int) (radius / 2.5));
+
+        if (isFilled)
+            buildFilledCylinder(centre, rotation, radius, segmentsCount, height, colour, fillAlpha);
+        else
+            buildCylinder(centre, rotation, radius, segmentsCount, height, colour);
+    }
+
+    void DebugDrawer::drawCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, float height, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        int segmentsCount = std::min<int>(100, (int) (radius / 2.5));
+
+        if (isFilled)
+            buildFilledCone(centre, rotation, radius, segmentsCount, height, colour, fillAlpha);
+        else
+            buildCone(centre, rotation, radius, segmentsCount, height, colour);
+    }
+
+    void DebugDrawer::drawQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        buildQuad(vertices, colour);
+        if (isFilled)
+            buildFilledQuad(vertices, colour, fillAlpha);
+    }
+
+    void DebugDrawer::drawCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        buildCuboid(vertices, colour);
+        if (isFilled)
+            buildFilledCuboid(vertices, colour, fillAlpha);
+    }
+
+    void DebugDrawer::drawSphere(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        const IcoSphere& sphere = this->getIcoSphere(radius);
+
+        if (isFilled)
+        {
+            this->drawCircle(centre, rotation * Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3(1, 0, 0)), radius, colour, false);
+            this->drawCircle(centre, rotation * Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3(0, 1, 0)), radius, colour, false);
+            this->drawCircle(centre, rotation * Ogre::Quaternion(Ogre::Degree(90), Ogre::Vector3(0, 0, 1)), radius, colour, false);
+
+            int baseIndex = trianglesIndex;
+            trianglesIndex += sphere.addToVertices(&triangleVertices, centre, Ogre::ColourValue(colour.r, colour.g, colour.b, fillAlpha), radius);
+            sphere.addToTriangleIndices(baseIndex, &triangleIndices);
+        }
+        else
+        {
+            int baseIndex = linesIndex;
+            linesIndex += sphere.addToVertices(&lineVertices, centre, colour, radius);
+            sphere.addToLineIndices(baseIndex, &lineIndices);
+        }
+    }
+
+    const IcoSphere& DebugDrawer::getIcoSphere(float radius) const
+    {
+        if (radius < 50)
+            return this->icoSphere0;
+        else if (radius < 500)
+            return this->icoSphere1;
+        else if (radius < 5000)
+            return this->icoSphere2;
+        else if (radius < 50000)
+            return this->icoSphere3;
+        else
+            return this->icoSphere4;
+    }
+
+    void DebugDrawer::drawTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, bool isFilled)
+    {
+        buildTetrahedron(centre, scale, colour);
+        if (isFilled)
+            buildFilledTetrahedron(centre, scale, colour, fillAlpha);
+    }
+
+    void DebugDrawer::build()
+    {
+        manualObject->beginUpdate(0);
+        if (lineVertices.size() > 0 && isEnabled)
+        {
+            manualObject->estimateVertexCount(lineVertices.size());
+            manualObject->estimateIndexCount(lineIndices.size());
+            for (const VertexPair& pair : lineVertices)
+            {
+                manualObject->position(pair.first);
+                manualObject->colour(pair.second);
+            }
+            for (int lineIndex : lineIndices)
+                manualObject->index(lineIndex);
+        }
+        else
+            manualObject->index(0); // this is necessary to avoid crashes with ogre 1.7 if there's a light source in the level
+        manualObject->end();
+
+        manualObject->beginUpdate(1);
+        if (triangleVertices.size() > 0 && isEnabled)
+        {
+            manualObject->estimateVertexCount(triangleVertices.size());
+            manualObject->estimateIndexCount(triangleIndices.size());
+            for (const VertexPair& pair : triangleVertices)
+            {
+                manualObject->position(pair.first);
+                manualObject->colour(pair.second.r, pair.second.g, pair.second.b, fillAlpha);
+            }
+            for (int triangleIndex : triangleIndices)
+                manualObject->index(triangleIndex);
+        }
+        else
+            manualObject->index(0); // this is necessary to avoid crashes with ogre 1.7 if there's a light source in the level
+        manualObject->end();
+    }
+
+    void DebugDrawer::clear()
+    {
+        lineVertices.clear();
+        triangleVertices.clear();
+        lineIndices.clear();
+        triangleIndices.clear();
+        linesIndex = trianglesIndex = 0;
+    }
+
+    int DebugDrawer::addLineVertex(const Ogre::Vector3& vertex, const Ogre::ColourValue& colour)
+    {
+        lineVertices.emplace_back(vertex, colour);
+        return linesIndex++;
+    }
+
+    void DebugDrawer::addLineIndices(int index1, int index2)
+    {
+        lineIndices.push_back(index1);
+        lineIndices.push_back(index2);
+    }
+
+    int DebugDrawer::addTriangleVertex(const Ogre::Vector3& vertex, const Ogre::ColourValue& colour)
+    {
+        triangleVertices.emplace_back(vertex, colour);
+        return trianglesIndex++;
+    }
+
+    void DebugDrawer::addTriangleIndices(int index1, int index2, int index3)
+    {
+        triangleIndices.push_back(index1);
+        triangleIndices.push_back(index2);
+        triangleIndices.push_back(index3);
+    }
+
+    void DebugDrawer::addQuadIndices(int index1, int index2, int index3, int index4)
+    {
+        triangleIndices.push_back(index1);
+        triangleIndices.push_back(index2);
+        triangleIndices.push_back(index3);
+
+        triangleIndices.push_back(index1);
+        triangleIndices.push_back(index3);
+        triangleIndices.push_back(index4);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/DebugDrawer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/DebugDrawer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/DebugDrawer.h	(revision 11817)
@@ -0,0 +1,118 @@
+/**
+ * @file DebugDrawer.h
+ * Copy-pasted from
+ *  - https://bitbucket.org/hasyimi/ogre-debug-drawing-utility/src
+ *  - http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Debug+Drawing+Utility+Class
+ *
+ * This source code is released into the Public Domain.
+ *
+ * Modified by Fabian 'x3n' Landau
+ */
+
+
+
+#ifndef _DebugDrawer_H__
+#define _DebugDrawer_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <map>
+
+#include "IcoSphere.h"
+
+namespace orxonox
+{
+    /**
+     * @brief DebugDrawer is a utility to draw debug shapes (lines, triangles, spheres) with Ogre.
+     * This utility is e.g. used by @ref orxonox::BulletDebugDrawer to visualize collision shapes and other physical entities.
+     */
+    class _ToolsExport DebugDrawer
+    {
+        public:
+            DebugDrawer(Ogre::SceneManager *_sceneManager, float _fillAlpha);
+            ~DebugDrawer();
+
+            void build();
+
+            void drawLine(const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::ColourValue& colour);
+            void drawCircle(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, const Ogre::ColourValue& colour, bool isFilled = false);
+            void drawCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, float height, const Ogre::ColourValue& colour, bool isFilled = false);
+            void drawCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, float height, const Ogre::ColourValue& colour, bool isFilled = false);
+
+            void drawQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, bool isFilled = false);
+            void drawCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, bool isFilled = false);
+            void drawSphere(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, const Ogre::ColourValue& colour, bool isFilled = false);
+            void drawTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, bool isFilled = false);
+
+            void setFillAlpha(float alpha)
+            {
+                fillAlpha = alpha;
+            }
+
+            bool getEnabled()
+            {
+                return isEnabled;
+            }
+            void setEnabled(bool _isEnabled)
+            {
+                isEnabled = _isEnabled;
+            }
+            void switchEnabled()
+            {
+                isEnabled = !isEnabled;
+            }
+
+            void clear();
+
+        private:
+            const IcoSphere& getIcoSphere(float radius) const;
+
+            Ogre::SceneManager* sceneManager;
+            float fillAlpha;
+            Ogre::ManualObject* manualObject;
+            IcoSphere icoSphere0;
+            IcoSphere icoSphere1;
+            IcoSphere icoSphere2;
+            IcoSphere icoSphere3;
+            IcoSphere icoSphere4;
+
+            bool isEnabled;
+
+            std::list<VertexPair> lineVertices, triangleVertices;
+            std::list<int> lineIndices, triangleIndices;
+
+            int linesIndex, trianglesIndex;
+
+            void initialise();
+            void shutdown();
+
+            void buildLine(const Ogre::Vector3& start, const Ogre::Vector3& end, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledQuad(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledTriangle(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledCuboid(const Ogre::Vector3* vertices, const Ogre::ColourValue& colour, float alpha = 1.0f);
+
+            void buildCircle(const Ogre::Matrix4& transform, float radius, int segmentsCount, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledCircle(const Ogre::Matrix4& transform, float radius, int segmentsCount, const Ogre::ColourValue& colour, bool up, float alpha = 1.0f);
+
+            void buildCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledCylinder(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha = 1.0f);
+
+            void buildCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledCone(const Ogre::Vector3& centre, const Ogre::Quaternion& rotation, float radius, int segmentsCount, float height, const Ogre::ColourValue& colour, float alpha = 1.0f);
+
+            void buildTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, float alpha = 1.0f);
+            void buildFilledTetrahedron(const Ogre::Vector3& centre, float scale, const Ogre::ColourValue& colour, float alpha = 1.0f);
+
+            int addLineVertex(const Ogre::Vector3& vertex, const Ogre::ColourValue& colour);
+            void addLineIndices(int index1, int index2);
+
+            int addTriangleVertex(const Ogre::Vector3& vertex, const Ogre::ColourValue& colour);
+            void addTriangleIndices(int index1, int index2, int index3);
+
+            void addQuadIndices(int index1, int index2, int index3, int index4);
+    };
+}
+
+#endif /* _DebugDrawer_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/DynamicLines.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/DynamicLines.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/DynamicLines.cc	(revision 11817)
@@ -0,0 +1,178 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Baxissimo, Emmeran, DWORD, EtherDrive (OGRE Wiki)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DynamicLines.h"
+
+#include <cassert>
+#include <cmath>
+
+namespace Ogre
+{
+    enum
+    {
+        POSITION_BINDING,
+        TEXCOORD_BINDING
+    };
+
+    DynamicLines::DynamicLines(OperationType opType)
+    {
+        initialize(opType,false);
+        setMaterial("BaseWhiteNoLighting");
+        mDirty = true;
+    }
+
+    DynamicLines::~DynamicLines()
+    {
+    }
+
+    void DynamicLines::setOperationType(OperationType opType)
+    {
+        mRenderOp.operationType = opType;
+    }
+
+    RenderOperation::OperationType DynamicLines::getOperationType() const
+    {
+        return mRenderOp.operationType;
+    }
+
+    void DynamicLines::addPoint(const Vector3 &p)
+    {
+        mPoints.push_back(p);
+        mDirty = true;
+    }
+
+    void DynamicLines::addPoint(Real x, Real y, Real z)
+    {
+        mPoints.emplace_back(x,y,z);
+        mDirty = true;
+    }
+
+    const Vector3& DynamicLines::getPoint(unsigned short index) const
+    {
+        assert(index < mPoints.size() && "Point index is out of bounds!!");
+        return mPoints[index];
+    }
+
+    unsigned short DynamicLines::getNumPoints(void) const
+    {
+        return (unsigned short)mPoints.size();
+    }
+
+    void DynamicLines::setPoint(unsigned short index, const Vector3 &value)
+    {
+        assert(index < mPoints.size() && "Point index is out of bounds!!");
+
+        mPoints[index] = value;
+        mDirty = true;
+    }
+
+    void DynamicLines::clear()
+    {
+        mPoints.clear();
+        mDirty = true;
+    }
+
+    void DynamicLines::update()
+    {
+        if (mDirty)
+            fillHardwareBuffers();
+    }
+
+    void DynamicLines::createVertexDeclaration()
+    {
+        VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration;
+        decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION);
+    }
+
+    void DynamicLines::fillHardwareBuffers()
+    {
+        int size = mPoints.size();
+
+        prepareHardwareBuffers(size,0);
+
+        if (!size)
+        {
+            mBox.setExtents(Vector3::ZERO,Vector3::ZERO);
+            mDirty=false;
+            return;
+        }
+
+        Vector3 vaabMin = mPoints[0];
+        Vector3 vaabMax = mPoints[0];
+
+        HardwareVertexBufferSharedPtr vbuf =
+            mRenderOp.vertexData->vertexBufferBinding->getBuffer(0);
+
+        Real *prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD));
+        for (int i = 0; i < size; i++)
+        {
+            *prPos++ = mPoints[i].x;
+            *prPos++ = mPoints[i].y;
+            *prPos++ = mPoints[i].z;
+
+            if (mPoints[i].x < vaabMin.x)
+                vaabMin.x = mPoints[i].x;
+            if (mPoints[i].y < vaabMin.y)
+                vaabMin.y = mPoints[i].y;
+            if (mPoints[i].z < vaabMin.z)
+                vaabMin.z = mPoints[i].z;
+
+            if (mPoints[i].x > vaabMax.x)
+                vaabMax.x = mPoints[i].x;
+            if (mPoints[i].y > vaabMax.y)
+                vaabMax.y = mPoints[i].y;
+            if (mPoints[i].z > vaabMax.z)
+                vaabMax.z = mPoints[i].z;
+        }
+        vbuf->unlock();
+
+        mBox.setExtents(vaabMin, vaabMax);
+
+        mDirty = false;
+    }
+
+    /*
+    void DynamicLines::getWorldTransforms(Matrix4 *xform) const
+    {
+        // return identity matrix to prevent parent transforms
+        *xform = Matrix4::IDENTITY;
+    }
+    */
+
+    /*
+    const Quaternion &DynamicLines::getWorldOrientation(void) const
+    {
+        return Quaternion::IDENTITY;
+    }
+
+    const Vector3 &DynamicLines::getWorldPosition(void) const
+    {
+        return Vector3::ZERO;
+    }
+    */
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/DynamicLines.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/DynamicLines.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/DynamicLines.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Baxissimo, Emmeran, DWORD, EtherDrive (OGRE Wiki)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DynamicLines_H__
+#define _DynamicLines_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <vector>
+#include "DynamicRenderable.h"
+
+namespace Ogre
+{
+    class _ToolsExport DynamicLines : public DynamicRenderable
+    {
+        typedef RenderOperation::OperationType OperationType;
+
+    public:
+        /// Constructor - see setOperationType() for description of argument.
+        DynamicLines(OperationType opType = RenderOperation::OT_LINE_STRIP);
+        virtual ~DynamicLines();
+
+        /// Add a point to the point list
+        void addPoint(const Vector3 &p);
+        /// Add a point to the point list
+        void addPoint(Real x, Real y, Real z);
+
+        /// Change the location of an existing point in the point list
+        void setPoint(unsigned short index, const Vector3 &value);
+
+        /// Return the location of an existing point in the point list
+        const Vector3& getPoint(unsigned short index) const;
+
+        /// Return the total number of points in the point list
+        unsigned short getNumPoints(void) const;
+
+        /// Remove all points from the point list
+        void clear();
+
+        /// Call this to update the hardware buffer after making changes.
+        void update();
+
+        /**
+        @brief
+            Set the type of operation to draw with.
+        @param opType
+            Can be one of
+                - RenderOperation::OT_LINE_STRIP
+                - RenderOperation::OT_LINE_LIST
+                - RenderOperation::OT_POINT_LIST
+                - RenderOperation::OT_TRIANGLE_LIST
+                - RenderOperation::OT_TRIANGLE_STRIP
+                - RenderOperation::OT_TRIANGLE_FAN
+            The default is OT_LINE_STRIP.
+        */
+        void setOperationType(OperationType opType);
+        OperationType getOperationType() const;
+
+    protected:
+        /// Implementation DynamicRenderable, creates a simple vertex-only decl
+        virtual void createVertexDeclaration() override;
+        /// Implementation DynamicRenderable, pushes point list out to hardware memory
+        virtual void fillHardwareBuffers() override;
+
+    private:
+        std::vector<Vector3> mPoints;
+        bool mDirty;
+    };
+}
+
+#endif /* _DynamicLines_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/DynamicRenderable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/DynamicRenderable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/DynamicRenderable.cc	(revision 11817)
@@ -0,0 +1,160 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sinbad, Baxissimo, DWORD, TheBren (OGRE Wiki)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DynamicRenderable.h"
+
+#include <OgreCamera.h>
+#include <OgreHardwareBufferManager.h>
+
+namespace Ogre
+{
+    DynamicRenderable::DynamicRenderable()
+    {
+    }
+
+    DynamicRenderable::~DynamicRenderable()
+    {
+        delete mRenderOp.vertexData;
+        delete mRenderOp.indexData;
+    }
+
+    void DynamicRenderable::initialize(RenderOperation::OperationType operationType,
+           bool useIndices)
+    {
+        // Initialize render operation
+        mRenderOp.operationType = operationType;
+        mRenderOp.useIndexes = useIndices;
+        mRenderOp.vertexData = new VertexData;
+        if (mRenderOp.useIndexes)
+            mRenderOp.indexData = new IndexData;
+
+        // Reset buffer capacities
+        mVertexBufferCapacity = 0;
+        mIndexBufferCapacity = 0;
+
+        // Create vertex declaration
+        createVertexDeclaration();
+    }
+
+    void DynamicRenderable::prepareHardwareBuffers(size_t vertexCount, size_t indexCount)
+    {
+        // Prepare vertex buffer
+        size_t newVertCapacity = mVertexBufferCapacity;
+        if ((vertexCount > mVertexBufferCapacity) || (!mVertexBufferCapacity))
+        {
+            // vertexCount exceeds current capacity!
+            // It is necessary to reallocate the buffer.
+
+            // Check if this is the first call
+            if (!newVertCapacity)
+                newVertCapacity = 1;
+
+            // Make capacity the next power of two
+            while (newVertCapacity < vertexCount)
+                newVertCapacity <<= 1;
+        }
+        else if (vertexCount < mVertexBufferCapacity>>1)
+        {
+            // Make capacity the previous power of two
+            while (vertexCount < newVertCapacity>>1)
+                newVertCapacity >>= 1;
+        }
+        if (newVertCapacity != mVertexBufferCapacity)
+        {
+            mVertexBufferCapacity = newVertCapacity;
+            // Create new vertex buffer
+            HardwareVertexBufferSharedPtr vbuf =
+                HardwareBufferManager::getSingleton().createVertexBuffer(
+                mRenderOp.vertexData->vertexDeclaration->getVertexSize(0),
+                mVertexBufferCapacity,
+                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?
+
+            // Bind buffer
+            mRenderOp.vertexData->vertexBufferBinding->setBinding(0, vbuf);
+        }
+        // Update vertex count in the render operation
+        mRenderOp.vertexData->vertexCount = vertexCount;
+
+        if (mRenderOp.useIndexes)
+        {
+            OgreAssert(indexCount <= std::numeric_limits<unsigned short>::max(), "indexCount exceeds 16 bit");
+
+            size_t newIndexCapacity = mIndexBufferCapacity;
+            // Prepare index buffer
+            if ((indexCount > newIndexCapacity) || (!newIndexCapacity))
+            {
+                // indexCount exceeds current capacity!
+                // It is necessary to reallocate the buffer.
+
+                // Check if this is the first call
+                if (!newIndexCapacity)
+                    newIndexCapacity = 1;
+
+                // Make capacity the next power of two
+                while (newIndexCapacity < indexCount)
+                    newIndexCapacity <<= 1;
+            }
+            else if (indexCount < newIndexCapacity>>1)
+            {
+                // Make capacity the previous power of two
+                while (indexCount < newIndexCapacity>>1)
+                    newIndexCapacity >>= 1;
+            }
+
+            if (newIndexCapacity != mIndexBufferCapacity)
+            {
+                mIndexBufferCapacity = newIndexCapacity;
+                // Create new index buffer
+                mRenderOp.indexData->indexBuffer =
+                    HardwareBufferManager::getSingleton().createIndexBuffer(
+                    HardwareIndexBuffer::IT_16BIT,
+                    mIndexBufferCapacity,
+                    HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?
+            }
+
+            // Update index count in the render operation
+            mRenderOp.indexData->indexCount = indexCount;
+        }
+    }
+
+    Real DynamicRenderable::getBoundingRadius(void) const
+    {
+        return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength()));
+    }
+
+    Real DynamicRenderable::getSquaredViewDepth(const Camera* cam) const
+    {
+        Vector3 vMin, vMax, vMid, vDist;
+        vMin = mBox.getMinimum();
+        vMax = mBox.getMaximum();
+        vMid = ((vMax - vMin) * 0.5) + vMin;
+        vDist = cam->getDerivedPosition() - vMid;
+
+        return vDist.squaredLength();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/DynamicRenderable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/DynamicRenderable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/DynamicRenderable.h	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sinbad, Baxissimo, DWORD, TheBren (OGRE Wiki)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DynamicRenderable_H__
+#define _DynamicRenderable_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <OgreSimpleRenderable.h>
+
+namespace Ogre
+{
+    /// Abstract base class providing mechanisms for dynamically growing hardware buffers.
+    class _ToolsExport DynamicRenderable : public SimpleRenderable
+    {
+    public:
+        /// Constructor
+        DynamicRenderable();
+        /// Virtual destructor
+        virtual ~DynamicRenderable();
+
+        /**
+        @brief
+            Initializes the dynamic renderable.
+        @remarks
+            This function should only be called once. It initializes the
+            render operation, and calls the abstract function
+            createVertexDeclaration().
+        @param operationType
+            The type of render operation to perform.
+        @param useIndices
+            Specifies whether to use indices to determine the vertices to use as input.
+        */
+        void initialize(RenderOperation::OperationType operationType,
+        bool useIndices);
+
+        /// Implementation of SimpleRenderable
+        virtual Real getBoundingRadius(void) const override;
+        /// Implementation of SimpleRenderable
+        virtual Real getSquaredViewDepth(const Camera* cam) const override;
+
+    protected:
+        /// Maximum capacity of the currently allocated vertex buffer.
+        size_t mVertexBufferCapacity;
+        /// Maximum capacity of the currently allocated index buffer.
+        size_t mIndexBufferCapacity;
+
+        /**
+        @brief
+            Creates the vertex declaration.
+        @remarks
+            Override and set mRenderOp.vertexData->vertexDeclaration here.
+            mRenderOp.vertexData will be created for you before this method
+            is called.
+        */
+        virtual void createVertexDeclaration() = 0;
+
+        /**
+        @brief
+            Prepares the hardware buffers for the requested vertex and index counts.
+        @remarks
+            This function must be called before locking the buffers in
+            fillHardwareBuffers(). It guarantees that the hardware buffers
+            are large enough to hold at least the requested number of
+            vertices and indices (if using indices). The buffers are
+            possibly reallocated to achieve this.
+        @par
+            The vertex and index count in the render operation are set to
+            the values of vertexCount and indexCount respectively.
+        @param vertexCount
+            The number of vertices the buffer must hold.
+        @param indexCount
+            The number of indices the buffer must hold. This
+            parameter is ignored if not using indices.
+        */
+        void prepareHardwareBuffers(size_t vertexCount, size_t indexCount);
+
+        /**
+        @brief
+            Fills the hardware vertex and index buffers with data.
+        @remarks
+            This function must call prepareHardwareBuffers() before locking
+            the buffers to ensure the they are large enough for the data to
+            be written. Afterwards the vertex and index buffers (if using
+            indices) can be locked, and data can be written to them.
+        */
+        virtual void fillHardwareBuffers() = 0;
+    };
+}
+
+#endif /* _DynamicRenderable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/IcoSphere.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/IcoSphere.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/IcoSphere.cc	(revision 11817)
@@ -0,0 +1,224 @@
+/**
+ * @file IcoSphere.cc
+ * Copy-pasted from
+ *  - https://bitbucket.org/hasyimi/ogre-debug-drawing-utility/src
+ *  - http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Debug+Drawing+Utility+Class
+ *
+ * This source code is released into the Public Domain.
+ *
+ * Modified by Fabian 'x3n' Landau
+ */
+
+#include "IcoSphere.h"
+
+#include <OgreSceneManager.h>
+#include <OgreRenderQueue.h>
+#include <OgreManualObject.h>
+#include <OgreAxisAlignedBox.h>
+
+namespace orxonox
+{
+    IcoSphere::IcoSphere() :
+            index(0)
+    {
+    }
+
+    IcoSphere::~IcoSphere()
+    {
+    }
+
+    void IcoSphere::create(int recursionLevel)
+    {
+        vertices.clear();
+        lineIndices.clear();
+        triangleIndices.clear();
+        faces.clear();
+        middlePointIndexCache.clear();
+        index = 0;
+
+        float t = (1.0f + Ogre::Math::Sqrt(5.0f)) / 2.0f;
+
+        addVertex(Ogre::Vector3(-1.0f, t, 0.0f));
+        addVertex(Ogre::Vector3(1.0f, t, 0.0f));
+        addVertex(Ogre::Vector3(-1.0f, -t, 0.0f));
+        addVertex(Ogre::Vector3(1.0f, -t, 0.0f));
+
+        addVertex(Ogre::Vector3(0.0f, -1.0f, t));
+        addVertex(Ogre::Vector3(0.0f, 1.0f, t));
+        addVertex(Ogre::Vector3(0.0f, -1.0f, -t));
+        addVertex(Ogre::Vector3(0.0f, 1.0f, -t));
+
+        addVertex(Ogre::Vector3(t, 0.0f, -1.0f));
+        addVertex(Ogre::Vector3(t, 0.0f, 1.0f));
+        addVertex(Ogre::Vector3(-t, 0.0f, -1.0f));
+        addVertex(Ogre::Vector3(-t, 0.0f, 1.0f));
+
+        addFace(0, 11, 5);
+        addFace(0, 5, 1);
+        addFace(0, 1, 7);
+        addFace(0, 7, 10);
+        addFace(0, 10, 11);
+
+        addFace(1, 5, 9);
+        addFace(5, 11, 4);
+        addFace(11, 10, 2);
+        addFace(10, 7, 6);
+        addFace(7, 1, 8);
+
+        addFace(3, 9, 4);
+        addFace(3, 4, 2);
+        addFace(3, 2, 6);
+        addFace(3, 6, 8);
+        addFace(3, 8, 9);
+
+        addFace(4, 9, 5);
+        addFace(2, 4, 11);
+        addFace(6, 2, 10);
+        addFace(8, 6, 7);
+        addFace(9, 8, 1);
+
+        addLineIndices(1, 0);
+        addLineIndices(1, 5);
+        addLineIndices(1, 7);
+        addLineIndices(1, 8);
+        addLineIndices(1, 9);
+
+        addLineIndices(2, 3);
+        addLineIndices(2, 4);
+        addLineIndices(2, 6);
+        addLineIndices(2, 10);
+        addLineIndices(2, 11);
+
+        addLineIndices(0, 5);
+        addLineIndices(5, 9);
+        addLineIndices(9, 8);
+        addLineIndices(8, 7);
+        addLineIndices(7, 0);
+
+        addLineIndices(10, 11);
+        addLineIndices(11, 4);
+        addLineIndices(4, 3);
+        addLineIndices(3, 6);
+        addLineIndices(6, 10);
+
+        addLineIndices(0, 11);
+        addLineIndices(11, 5);
+        addLineIndices(5, 4);
+        addLineIndices(4, 9);
+        addLineIndices(9, 3);
+        addLineIndices(3, 8);
+        addLineIndices(8, 6);
+        addLineIndices(6, 7);
+        addLineIndices(7, 10);
+        addLineIndices(10, 0);
+
+        for (int i = 0; i < recursionLevel; i++)
+        {
+            std::list<TriangleIndices> faces2;
+
+            for (const TriangleIndices& f : faces)
+            {
+                int a = getMiddlePoint(f.v1, f.v2);
+                int b = getMiddlePoint(f.v2, f.v3);
+                int c = getMiddlePoint(f.v3, f.v1);
+
+                removeLineIndices(f.v1, f.v2);
+                removeLineIndices(f.v2, f.v3);
+                removeLineIndices(f.v3, f.v1);
+
+                faces2.emplace_back(f.v1, a, c);
+                faces2.emplace_back(f.v2, b, a);
+                faces2.emplace_back(f.v3, c, b);
+                faces2.emplace_back(a, b, c);
+
+                addTriangleLines(f.v1, a, c);
+                addTriangleLines(f.v2, b, a);
+                addTriangleLines(f.v3, c, b);
+            }
+
+            faces = faces2;
+        }
+    }
+
+    void IcoSphere::addLineIndices(int index0, int index1)
+    {
+        lineIndices.emplace_back(index0, index1);
+    }
+
+    void IcoSphere::removeLineIndices(int index0, int index1)
+    {
+        std::list<LineIndices>::iterator result = std::find(lineIndices.begin(), lineIndices.end(), LineIndices(index0, index1));
+
+        if (result != lineIndices.end())
+            lineIndices.erase(result);
+    }
+
+    void IcoSphere::addTriangleLines(int index0, int index1, int index2)
+    {
+        addLineIndices(index0, index1);
+        addLineIndices(index1, index2);
+        addLineIndices(index2, index0);
+    }
+
+    int IcoSphere::addVertex(const Ogre::Vector3& vertex)
+    {
+        Ogre::Real length = vertex.length();
+        vertices.emplace_back(vertex.x / length, vertex.y / length, vertex.z / length);
+        return index++;
+    }
+
+    int IcoSphere::getMiddlePoint(int index0, int index1)
+    {
+        bool isFirstSmaller = index0 < index1;
+        int64_t smallerIndex = isFirstSmaller ? index0 : index1;
+        int64_t largerIndex = isFirstSmaller ? index1 : index0;
+        int64_t key = (smallerIndex << 32) | largerIndex;
+
+        if (middlePointIndexCache.find(key) != middlePointIndexCache.end())
+            return middlePointIndexCache[key];
+
+        Ogre::Vector3 point1 = vertices[index0];
+        Ogre::Vector3 point2 = vertices[index1];
+        Ogre::Vector3 middle = point1.midPoint(point2);
+
+        int index = addVertex(middle);
+        middlePointIndexCache[key] = index;
+        return index;
+    }
+
+    void IcoSphere::addFace(int index0, int index1, int index2)
+    {
+        faces.emplace_back(index0, index1, index2);
+    }
+
+    void IcoSphere::addToLineIndices(int baseIndex, std::list<int>* target) const
+    {
+        for (const LineIndices& line : lineIndices)
+        {
+            target->push_back(baseIndex + line.v1);
+            target->push_back(baseIndex + line.v2);
+        }
+    }
+
+    void IcoSphere::addToTriangleIndices(int baseIndex, std::list<int>* target) const
+    {
+        for (const TriangleIndices& triangle : faces)
+        {
+            target->push_back(baseIndex + triangle.v1);
+            target->push_back(baseIndex + triangle.v2);
+            target->push_back(baseIndex + triangle.v3);
+        }
+    }
+
+    int IcoSphere::addToVertices(std::list<VertexPair>* target, const Ogre::Vector3& position, const Ogre::ColourValue& colour, float scale) const
+    {
+        Ogre::Matrix4 transform = Ogre::Matrix4::IDENTITY;
+        transform.setTrans(position);
+        transform.setScale(Ogre::Vector3(scale, scale, scale));
+
+        for (const Ogre::Vector3& vertex : vertices)
+            target->emplace_back(transform * vertex, colour);
+
+        return vertices.size();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/IcoSphere.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/IcoSphere.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/IcoSphere.h	(revision 11817)
@@ -0,0 +1,83 @@
+
+
+#ifndef _IcoSphere_H__
+#define _IcoSphere_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <OgreSingleton.h>
+#include <map>
+
+namespace orxonox
+{
+    typedef std::pair<Ogre::Vector3, Ogre::ColourValue> VertexPair;
+
+    /**
+    * Copy-pasted from
+    *  - https://bitbucket.org/hasyimi/ogre-debug-drawing-utility/src
+    *  - http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Debug+Drawing+Utility+Class
+    *
+    * This source code is released into the Public Domain.
+    *
+    * Modified by Fabian 'x3n' Landau
+    */
+    class _ToolsExport IcoSphere
+    {
+        public:
+            struct TriangleIndices
+            {
+                    int v1, v2, v3;
+
+                    TriangleIndices(int _v1, int _v2, int _v3) :
+                            v1(_v1), v2(_v2), v3(_v3)
+                    {
+                    }
+
+                    bool operator <(const TriangleIndices &o) const
+                    {
+                        return v1 < o.v1 && v2 < o.v2 && v3 < o.v3;
+                    }
+            };
+
+            struct LineIndices
+            {
+                    int v1, v2;
+
+                    LineIndices(int _v1, int _v2) :
+                            v1(_v1), v2(_v2)
+                    {
+                    }
+
+                    bool operator ==(const LineIndices &o) const
+                    {
+                        return (v1 == o.v1 && v2 == o.v2) || (v1 == o.v2 && v2 == o.v1);
+                    }
+            };
+
+            IcoSphere();
+            ~IcoSphere();
+
+            void create(int recursionLevel);
+            void addToLineIndices(int baseIndex, std::list<int>* target) const;
+            int addToVertices(std::list<VertexPair>* target, const Ogre::Vector3& position, const Ogre::ColourValue& colour, float scale) const;
+            void addToTriangleIndices(int baseIndex, std::list<int>* target) const;
+
+        private:
+            int addVertex(const Ogre::Vector3& vertex);
+            void addLineIndices(int index0, int index1);
+            void addTriangleLines(int index0, int index1, int index2);
+            int getMiddlePoint(int index0, int index1);
+            void addFace(int index0, int index1, int index2);
+
+            void removeLineIndices(int index0, int index1);
+
+            std::vector<Ogre::Vector3> vertices;
+            std::list<LineIndices> lineIndices;
+            std::list<int> triangleIndices;
+            std::list<TriangleIndices> faces;
+            std::map<int64_t, int> middlePointIndexCache;
+            int index;
+    };
+}
+
+#endif /* _IcoSphere_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/Mesh.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/Mesh.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/Mesh.cc	(revision 11817)
@@ -0,0 +1,139 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Mesh.h"
+
+#include <cassert>
+#include <sstream>
+#include <string>
+#include <OgreEntity.h>
+#include <OgreSubEntity.h>
+#include <OgreSceneManager.h>
+
+#include "util/Convert.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+    unsigned int Mesh::meshCounter_s = 0;
+
+    Mesh::Mesh()
+    {
+        this->entity_ = nullptr;
+        this->bCastShadows_ = true;
+    }
+
+    Mesh::~Mesh()
+    {
+        if (this->entity_ && this->scenemanager_)
+            this->scenemanager_->destroyEntity(this->entity_);
+    }
+
+    void Mesh::setMeshSource(Ogre::SceneManager* scenemanager, const std::string& meshsource)
+    {
+        assert(scenemanager);
+
+        this->scenemanager_ = scenemanager;
+
+        if (this->entity_)
+            this->scenemanager_->destroyEntity(this->entity_);
+
+        if (GameMode::showsGraphics())
+        {
+            try
+            {
+                this->entity_ = this->scenemanager_->createEntity("Mesh" + multi_cast<std::string>(Mesh::meshCounter_s++), meshsource);
+                this->entity_->setCastShadows(this->bCastShadows_);
+            }
+            catch (...)
+            {
+                orxout(internal_error) << "Couldn't load mesh \"" << meshsource << '"' << endl;
+                this->entity_ = nullptr;
+            }
+        }
+    }
+
+    void Mesh::setCastShadows(bool bCastShadows)
+    {
+        this->bCastShadows_ = bCastShadows;
+        if (this->entity_)
+            this->entity_->setCastShadows(this->bCastShadows_);
+    }
+
+    const std::string& Mesh::getName() const
+    {
+        if (this->entity_)
+            return this->entity_->getName();
+        else
+            return BLANKSTRING;
+    }
+
+    void Mesh::setMaterial(const std::string& name)
+    {
+        if (this->entity_)
+            this->entity_->setMaterialName(name);
+    }
+
+    // PRE: a valid  Ogre::Entity* entity with a valid subentity at index
+    // POST: changed material of subentity at index to name
+    void Mesh::setSubMaterial(const std::string& name, const int index){
+         if (this->entity_ && this->entity_->getSubEntity(index))
+        {
+                this->entity_->getSubEntity(index)->setMaterialName(name);
+        }
+        else 
+            orxout() << "ERROR at Index " << index << endl;
+    }
+
+    const std::string& Mesh::getMaterial() const
+    {
+        if (this->entity_)
+        {
+            if(this->entity_->getSubEntity(0))
+                return this->entity_->getSubEntity(0)->getMaterialName(); //return the Material of the first SubEntity, should be enough for now
+            else
+                return BLANKSTRING;
+        }
+        else
+            return BLANKSTRING;
+    }
+
+    void Mesh::setVisible(bool bVisible)
+    {
+        if (this->entity_)
+            this->entity_->setVisible(bVisible);
+    }
+
+    bool Mesh::isVisible() const
+    {
+        if (this->entity_)
+            return this->entity_->getVisible();
+        else
+            return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/Mesh.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/Mesh.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/Mesh.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Mesh_H__
+#define _Mesh_H__
+
+#include "tools/ToolsPrereqs.h"
+#include "util/OgreForwardRefs.h"
+
+namespace orxonox
+{
+    class _ToolsExport Mesh
+    {
+        public:
+            Mesh();
+            ~Mesh();
+
+            void setMeshSource(Ogre::SceneManager* scenemanager, const std::string& file);
+
+            inline Ogre::Entity* getEntity()
+                { return this->entity_; }
+
+            const std::string& getName() const;
+
+            void setMaterial(const std::string& name);
+            const std::string& getMaterial() const;
+
+            void setSubMaterial(const std::string& name, const int index);
+
+            void setVisible(bool bVisible);
+            bool isVisible() const;
+
+            void setCastShadows(bool bCastShadows);
+            inline bool getCastShadows() const
+                { return this->bCastShadows_; }
+
+        private:
+            Ogre::Entity* entity_;
+            bool bCastShadows_;
+            Ogre::SceneManager* scenemanager_;
+
+            static unsigned int meshCounter_s;
+    };
+}
+
+#endif /* _Mesh_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/OgreBulletUtils.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/OgreBulletUtils.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/OgreBulletUtils.h	(revision 11817)
@@ -0,0 +1,68 @@
+/**
+ * @file OgreBulletUtils.h
+ * Copy-pasted from http://www.ogre3d.org/tikiwiki/BulletDebugDrawer&structure=Cookbook
+ * This source code is released into the Public Domain.
+ *
+ * Modified by Fabian 'x3n' Landau
+ */
+
+#ifndef _OgreBulletUtils_H__
+#define _OgreBulletUtils_H__
+
+#include "tools/ToolsPrereqs.h"
+#include <OgreVector3.h>
+#include <OgreQuaternion.h>
+#include <OgreColourValue.h>
+#include <OgreMatrix3.h>
+#include <OgreMatrix4.h>
+
+namespace orxonox
+{
+    inline btVector3 vector3(const Ogre::Vector3& V)
+    {
+        return btVector3(V.x, V.y, V.z);
+    }
+
+    inline Ogre::Vector3 vector3(const btVector3& V)
+    {
+        return Ogre::Vector3(V.x(), V.y(), V.z());
+    }
+
+    inline btQuaternion quaternion(const Ogre::Quaternion& Q)
+    {
+        return btQuaternion(Q.x, Q.y, Q.z, Q.w);
+    }
+
+    inline Ogre::Quaternion quaternion(const btQuaternion& Q)
+    {
+        return Ogre::Quaternion(Q.w(), Q.x(), Q.y(), Q.z());
+    }
+
+    inline Ogre::ColourValue colour(const btVector3& color, btScalar alpha)
+    {
+        Ogre::ColourValue c(color.getX(), color.getY(), color.getZ(), alpha);
+        c.saturate();
+        return c;
+    }
+
+    inline Ogre::Matrix3 matrix3(const btMatrix3x3& matrix)
+    {
+        return Ogre::Matrix3(
+                matrix[0][0], matrix[0][1], matrix[0][2],
+                matrix[1][0], matrix[1][1], matrix[1][2],
+                matrix[2][0], matrix[2][1], matrix[2][2]
+            );
+    }
+
+    inline Ogre::Matrix4 matrix4(const btTransform& transform)
+    {
+        const btMatrix3x3& rotation = transform.getBasis();
+        const btVector3& translation = transform.getOrigin();
+
+        Ogre::Matrix4 matrix4 = Ogre::Matrix4(matrix3(rotation));
+        matrix4.setTrans(vector3(translation));
+        return matrix4;
+    }
+}
+
+#endif /* _OgreBulletUtils_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ParticleInterface.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ParticleInterface.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ParticleInterface.cc	(revision 11817)
@@ -0,0 +1,240 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+* @file
+* @brief class to control praticle effects
+*/
+
+#include "ParticleInterface.h"
+
+#include <cassert>
+#include <string>
+#include <OgreParticleSystem.h>
+#include <OgreParticleEmitter.h>
+#include <OgreSceneManager.h>
+
+#include "util/Convert.h"
+#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+    unsigned int ParticleInterface::counter_s = 0;
+
+    RegisterAbstractClass(ParticleInterface).inheritsFrom<TimeFactorListener>();
+
+    ParticleInterface::ParticleInterface(Ogre::SceneManager* scenemanager, const std::string& templateName, LODParticle::Value detaillevel)
+    {
+        RegisterObject(ParticleInterface);
+
+        assert(scenemanager);
+
+        this->scenemanager_ = scenemanager;
+        this->particleSystem_ = nullptr;
+
+        this->bEnabled_ = true;
+        this->bVisible_ = true;
+        this->bAllowedByLOD_ = true;
+        this->speedFactor_ = 1.0f;
+
+        this->setDetailLevel(static_cast<unsigned int>(detaillevel));
+
+        this->setConfigValues();
+
+        if (GameMode::showsGraphics())
+        {
+            try
+            {
+                this->particleSystem_ = this->scenemanager_->createParticleSystem("particles" + multi_cast<std::string>(ParticleInterface::counter_s++), templateName);
+                this->setSpeedFactor(1.0f);
+            }
+            catch (...)
+            {
+                orxout(internal_error) << "Couldn't load particle system \"" << templateName << '"' << endl;
+                this->particleSystem_ = nullptr;
+            }
+        }
+    }
+
+    ParticleInterface::~ParticleInterface()
+    {
+        if (this->particleSystem_)
+        {
+            this->particleSystem_->removeAllEmitters();
+            this->scenemanager_->destroyParticleSystem(this->particleSystem_);
+        }
+    }
+
+    void ParticleInterface::setConfigValues()
+    {
+        SetConfigValueExternal(globalDetailLevel_, "GraphicsSettings", "particlesDetailLevel", 2)
+            .description("O: off, 1: low, 2: normal, 3: high")
+            .callback(this, &ParticleInterface::detailLevelChanged);
+    }
+
+    Ogre::ParticleEmitter* ParticleInterface::createNewEmitter()
+    {
+        if (this->particleSystem_ && this->particleSystem_->getNumEmitters() > 0)
+        {
+            Ogre::ParticleEmitter* newemitter = this->particleSystem_->addEmitter(this->particleSystem_->getEmitter(0)->getType());
+            this->particleSystem_->getEmitter(0)->copyParametersTo(newemitter);
+            return newemitter;
+        }
+        else
+            return nullptr;
+    }
+    Ogre::ParticleEmitter* ParticleInterface::getEmitter(unsigned int emitterNr) const
+    {
+        if (this->particleSystem_ && (emitterNr < this->particleSystem_->getNumEmitters()))
+            return this->particleSystem_->getEmitter(emitterNr);
+        else
+            return nullptr;
+    }
+    void ParticleInterface::removeEmitter(unsigned int emitterNr)
+    {
+        if (this->particleSystem_ && (emitterNr < this->particleSystem_->getNumEmitters()))
+            this->particleSystem_->removeEmitter(emitterNr);
+    }
+    void ParticleInterface::removeAllEmitters()
+    {
+        if (this->particleSystem_)
+            this->particleSystem_->removeAllEmitters();
+    }
+    unsigned int ParticleInterface::getNumEmitters() const
+    {
+        if (this->particleSystem_)
+            return this->particleSystem_->getNumEmitters();
+        else
+            return 0;
+    }
+
+    Ogre::ParticleAffector* ParticleInterface::addAffector(const std::string& name)
+    {
+        if (this->particleSystem_)
+            return this->particleSystem_->addAffector(name);
+        else
+            return nullptr;
+    }
+    Ogre::ParticleAffector* ParticleInterface::getAffector(unsigned int affectorNr)
+    {
+        if (this->particleSystem_ && (affectorNr < this->particleSystem_->getNumAffectors()))
+            return this->particleSystem_->getAffector(affectorNr);
+        else
+            return nullptr;
+    }
+    void ParticleInterface::removeAffector(unsigned int affectorNr)
+    {
+        if (this->particleSystem_ && (affectorNr < this->particleSystem_->getNumAffectors()))
+            this->particleSystem_->removeAffector(affectorNr);
+    }
+    void ParticleInterface::removeAllAffectors()
+    {
+        if (this->particleSystem_)
+            this->particleSystem_->removeAllAffectors();
+    }
+    unsigned int ParticleInterface::getNumAffectors() const
+    {
+        if (this->particleSystem_)
+            return this->particleSystem_->getNumAffectors();
+        else
+            return 0;
+    }
+
+    void ParticleInterface::setEnabled(bool enable)
+    {
+        this->bEnabled_ = enable;
+
+        if (this->particleSystem_)
+            for (unsigned int i = 0; i < this->particleSystem_->getNumEmitters(); i++)
+                this->particleSystem_->getEmitter(i)->setEnabled(this->bEnabled_ && this->bAllowedByLOD_);
+    }
+
+    void ParticleInterface::setVisible(bool visible)
+    {
+        this->bVisible_ = visible;
+
+        if (this->particleSystem_)
+            this->particleSystem_->setVisible(this->bVisible_ && this->bAllowedByLOD_);
+    }
+
+    void ParticleInterface::setDetailLevel(unsigned int level)
+    {
+        this->detaillevel_ = level;
+        if (GameMode::showsGraphics())
+            this->detailLevelChanged();
+    }
+
+    void ParticleInterface::detailLevelChanged()
+    {
+        if (this->globalDetailLevel_ >= this->detaillevel_)
+            this->bAllowedByLOD_ = true;
+        else
+            this->bAllowedByLOD_ = false;
+
+        this->updateVisibility();
+    }
+
+    void ParticleInterface::updateVisibility()
+    {
+        this->setEnabled(this->isEnabled());
+        this->setVisible(this->isVisible());
+    }
+
+    void ParticleInterface::setSpeedFactor(float factor)
+    {
+        this->speedFactor_ = factor;
+
+        if (this->particleSystem_)
+            this->particleSystem_->setSpeedFactor(factor * this->getTimeFactor());
+    }
+    void ParticleInterface::changedTimeFactor(float factor_new, float factor_old)
+    {
+        this->setSpeedFactor(this->speedFactor_);
+    }
+
+    bool ParticleInterface::getKeepParticlesInLocalSpace() const
+    {
+        if (this->particleSystem_)
+            return this->particleSystem_->getKeepParticlesInLocalSpace();
+        else
+            return false;
+    }
+    void ParticleInterface::setKeepParticlesInLocalSpace(bool keep)
+    {
+        if (this->particleSystem_)
+            this->particleSystem_->setKeepParticlesInLocalSpace(keep);
+    }
+
+    void ParticleInterface::setDimensions(float scale)
+    {
+        this->particleSystem_->setDefaultDimensions(scale * this->particleSystem_->getDefaultWidth(), scale * this->particleSystem_->getDefaultHeight());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ParticleInterface.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ParticleInterface.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ParticleInterface.h	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ParticleInterface_H__
+#define _ParticleInterface_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include "util/OgreForwardRefs.h"
+#include "tools/interfaces/TimeFactorListener.h"
+
+namespace orxonox
+{
+    class _ToolsExport ParticleInterface : public TimeFactorListener
+    {
+        public:
+            ParticleInterface(Ogre::SceneManager* scenemanager, const std::string& templateName, LODParticle::Value detaillevel);
+            virtual ~ParticleInterface();
+            void setConfigValues();
+
+            inline Ogre::ParticleSystem* getParticleSystem()
+                { return this->particleSystem_; }
+
+            Ogre::ParticleEmitter* createNewEmitter();
+            Ogre::ParticleEmitter* getEmitter(unsigned int emitterNr) const;
+            void removeEmitter(unsigned int emitterNr);
+            void removeAllEmitters();
+            unsigned int getNumEmitters() const;
+
+            Ogre::ParticleAffector* addAffector(const std::string& name);
+            Ogre::ParticleAffector* getAffector(unsigned int affectorNr);
+            void removeAffector(unsigned int affectorNr);
+            void removeAllAffectors();
+            unsigned int getNumAffectors() const;
+
+            inline float getSpeedFactor() const
+                { return this->speedFactor_; }
+            void setSpeedFactor(float factor);
+            bool getKeepParticlesInLocalSpace() const;
+            void setKeepParticlesInLocalSpace(bool keep);
+
+            void setEnabled(bool enable);
+            inline bool isEnabled() const
+                { return this->bEnabled_; }
+
+            void setVisible(bool visible);
+            inline bool isVisible() const
+                { return this->bVisible_; }
+
+            void setDetailLevel(unsigned int level);
+
+            void setDimensions(float scale);
+
+        protected:
+            virtual void changedTimeFactor(float factor_new, float factor_old) override;
+
+        private:
+            void updateVisibility();
+            void detailLevelChanged();
+
+            Ogre::ParticleSystem*     particleSystem_;
+            Ogre::SceneManager*       scenemanager_;
+            bool                      bVisible_;
+            bool                      bEnabled_;
+            bool                      bAllowedByLOD_;
+            unsigned int              detaillevel_;       //!< Detail level of this particle effect (0: off, 1: low, 2: normal, 3: high)
+            float                     speedFactor_;
+
+            // config values
+            unsigned int              globalDetailLevel_; //!< Global maximum detail level of particle effects (0: off, 1: low, 2: normal, 3: high)
+
+            static unsigned int       counter_s;
+    };
+}
+
+#endif /* _ParticleInterface_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ResourceCollection.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ResourceCollection.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ResourceCollection.cc	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ResourceCollection.h"
+
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/Resource.h"
+#include "core/XMLPort.h"
+#include "ResourceLocation.h"
+
+namespace orxonox
+{
+    RegisterClass(ResourceCollection);
+
+    ResourceCollection::ResourceCollection(Context* context)
+        : BaseObject(context)
+    {
+        RegisterObject(ResourceCollection);
+
+        // Default group is "General"
+        this->setResourceGroup(Resource::getDefaultResourceGroup());
+    }
+
+    void ResourceCollection::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(ResourceCollection, "resourceGroup", setResourceGroup, getResourceGroup, xmlelement, mode);
+        XMLPortObject(ResourceCollection, ResourceLocation, "", addResourceLocation, getResourceLocation, xmlelement, mode);
+    }
+
+    void ResourceCollection::setResourceGroup(const std::string& resourceGroup)
+    {
+        if (resourceGroup.empty())
+        {
+            orxout(internal_warning) << "\"\" is not a valid resource group." << endl;
+            return;
+        }
+        if (!resourceLocations_.empty())
+            ThrowException(InitialisationFailed, "ResourceGroup: Group change not allowed with locations already added!");
+        resourceGroup_ = resourceGroup;
+    }
+
+    void ResourceCollection::addResourceLocation(ResourceLocation* location)
+    {
+        location->load(resourceGroup_);
+        this->resourceLocations_.push_back(location);
+    }
+
+    void ResourceCollection::removeResourceLocation(ResourceLocation* location)
+    {
+        for (std::vector<ResourceLocation*>::iterator it = resourceLocations_.begin(); it != resourceLocations_.end(); )
+        {
+            if (*it == location)
+            {
+                it = resourceLocations_.erase(it);
+                location->unload(); // doesn't throw
+            }
+            else
+                ++it;
+        }
+    }
+
+    ResourceLocation* ResourceCollection::getResourceLocation(unsigned int index) const
+    {
+        if (index >= resourceLocations_.size())
+            return nullptr;
+        else
+            return resourceLocations_[index];
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ResourceCollection.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ResourceCollection.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ResourceCollection.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ResourceCollection_H__
+#define _ResourceCollection_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <string>
+#include <vector>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _ToolsExport ResourceCollection : public BaseObject
+    {
+    public:
+        ResourceCollection(Context* context);
+        virtual ~ResourceCollection() = default;
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        void setResourceGroup(const std::string& resourceGroup);
+        const std::string& getResourceGroup() const { return resourceGroup_; }
+
+        void addResourceLocation(ResourceLocation* location);
+        void removeResourceLocation(ResourceLocation* location);
+        ResourceLocation* getResourceLocation(unsigned int index) const;
+
+    private:
+        // non-copyable:
+        ResourceCollection(const ResourceCollection&) = delete;
+        ResourceCollection& operator=(const ResourceCollection&) = delete;
+
+        std::string resourceGroup_;
+        std::vector<ResourceLocation*> resourceLocations_;
+    };
+}
+
+#endif /* _ResourceCollection_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ResourceLocation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ResourceLocation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ResourceLocation.cc	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ResourceLocation.h"
+
+#include <OgreResourceGroupManager.h>
+#include <OgreException.h>
+#include <boost/filesystem.hpp>
+
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/ApplicationPaths.h"
+#include "core/ConfigurablePaths.h"
+#include "core/XMLFile.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(ResourceLocation);
+
+    ResourceLocation::ResourceLocation(Context* context)
+        : BaseObject(context)
+    {
+        RegisterObject(ResourceLocation);
+
+        // Default values
+        archiveType_ = "FileSystem";
+        bRecursive_  = false;
+    }
+
+    void ResourceLocation::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(ResourceLocation, "path",        setPath,        getPath,        xmlelement, mode);
+        XMLPortParam(ResourceLocation, "archiveType", setArchiveType, getArchiveType, xmlelement, mode);
+        XMLPortParam(ResourceLocation, "recursive",   setRecursive,   getRecursive,   xmlelement, mode);
+        if (path_.empty())
+            ThrowException(AbortLoading, "ResourceLocation: No path given.");
+    }
+
+    void ResourceLocation::load(const std::string& resourceGroup)
+    {
+        if (path_.empty())
+            ThrowException(InitialisationFailed, "ResourceLocation: Trying to add one without the path being set");
+
+        // Find the path
+        namespace bf = boost::filesystem;
+        bf::path path;
+        if (bf::exists(ConfigurablePaths::getDataPath() / this->getPath()))
+            path = ConfigurablePaths::getDataPath() / this->getPath();
+        else if (ApplicationPaths::buildDirectoryRun() && bf::exists(ConfigurablePaths::getExternalDataPath() / this->getPath()))
+            path = ConfigurablePaths::getExternalDataPath() / this->getPath();
+        else
+        {
+            orxout(internal_warning) << "ResourceLocation '" << this->getPath() << "' does not seem to exist" << endl;
+            return;
+        }
+
+        // Add it to the Ogre paths
+        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
+            path.string(), this->getArchiveType(), resourceGroup, this->getRecursive());
+        resourceGroup_ = resourceGroup;
+    }
+
+    void ResourceLocation::unload()
+    {
+        // Remove from Ogre paths
+        resourceGroup_.clear();
+        try
+        {
+            Ogre::ResourceGroupManager::getSingleton().removeResourceLocation(
+                this->getPath(), this->getResourceGroup());
+        }
+        catch (const Ogre::Exception& ex)
+        {
+            orxout(internal_error) << "Removing of a ResourceLocation failed: " << ex.what() << endl;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ResourceLocation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ResourceLocation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ResourceLocation.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ResourceLocation_H__
+#define _ResourceLocation_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <string>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _ToolsExport ResourceLocation : public BaseObject
+    {
+        // for load/unload
+        friend class ResourceCollection;
+
+    public:
+        ResourceLocation(Context* context);
+        virtual ~ResourceLocation() = default;
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        void setPath(const std::string& path) { path_ = path; }
+        const std::string& getPath() const { return path_; }
+
+        void setArchiveType(const std::string& archiveType) { archiveType_ = archiveType; }
+        const std::string& getArchiveType() const { return archiveType_; }
+
+        void setRecursive(bool bRecursive) { bRecursive_ = bRecursive; }
+        bool getRecursive() const { return bRecursive_; }
+
+        const std::string& getResourceGroup() const { return resourceGroup_; }
+
+    private:
+        // non-copyable:
+        ResourceLocation(const ResourceLocation&) = delete;
+        ResourceLocation& operator=(const ResourceLocation&) = delete;
+
+        void load(const std::string& resourceGroup);
+        void unload();
+
+        std::string path_;
+        std::string archiveType_;
+        std::string resourceGroup_;
+        bool bRecursive_;
+    };
+}
+
+#endif /* _ResourceLocation_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/Shader.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/Shader.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/Shader.cc	(revision 11817)
@@ -0,0 +1,236 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Shader.h"
+
+#include <OgreCompositorManager.h>
+#include <OgreRoot.h>
+#include <OgrePlugin.h>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/GraphicsManager.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(Shader);
+
+    /**
+        @brief Initializes the values and sets the scene manager.
+    */
+    Shader::Shader(Ogre::SceneManager* scenemanager) : compositorInstance_(nullptr)
+    {
+        RegisterObject(Shader);
+
+        this->scenemanager_ = scenemanager;
+        this->bVisible_ = true;
+        this->bLoadCompositor_ = GameMode::showsGraphics();
+        this->registeredAsListener_ = false;
+
+        static bool hasCgProgramManager = Shader::hasCgProgramManager();
+
+        this->bLoadCompositor_ &= hasCgProgramManager;
+    }
+
+    /**
+        @brief Removes the compositor and frees the resources.
+    */
+    Shader::~Shader()
+    {
+        if (this->compositorInstance_ && GraphicsManager::getInstance().getViewport())
+            Ogre::CompositorManager::getSingleton().removeCompositor(GraphicsManager::getInstance().getViewport(), this->compositorName_);
+    }
+
+    /**
+        @brief Inherited from ViewportEventListener - called if the camera changes.
+
+        Since the new camera could be in a different scene, the shader has to make sure
+        it deactivates or activates itself accordingly.
+
+        Additionally the shader has to be turned off and on even if the camera stays in
+        the same scene to fix a weird behavior of Ogre.
+    */
+    void Shader::cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera)
+    {
+        if (!this->bLoadCompositor_ || !this->scenemanager_)
+            return;
+
+        // load the compositor if not already done
+        if (!this->compositorName_.empty() && !this->compositorInstance_)
+            this->changedCompositorName(viewport);
+
+        // update compositor in viewport (shader should only be active if the current camera is in the same scene as the shader)
+
+        // Note:
+        // The shader needs also to be switched off and on after changing the camera in the
+        // same scene to avoid weird behaviour with active compositors while switching the
+        // camera (like freezing the image)
+        //
+        // Last known Ogre version needing this workaround:
+        // 1.4.8
+        // 1.7.2
+
+        if (oldCamera && this->scenemanager_ == oldCamera->getSceneManager())
+            Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, false);
+
+        if (viewport->getCamera() && this->scenemanager_ == viewport->getCamera()->getSceneManager())
+            Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, this->isVisible());
+    }
+
+    /**
+        @brief Changes the compositor - default viewport.
+    */
+    void Shader::changedCompositorName()
+    {
+        // For the moment, we get the viewport always from the graphics manager
+        // TODO: Try to support multiple viewports - note however that scenemanager_->getCurrentViewport() returns nullptr
+        //       after switching to a camera in a different scene (only for the first time this scene is displayed though)
+        this->changedCompositorName(GraphicsManager::getInstance().getViewport());
+    }
+
+    /**
+        @brief Changes the compositor.
+    */
+    void Shader::changedCompositorName(Ogre::Viewport* viewport)
+    {
+        if (this->bLoadCompositor_)
+        {
+            assert(viewport);
+            if (this->compositorInstance_)
+            {
+                // remove the old compositor, remove the listener
+                Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->oldcompositorName_);
+                this->compositorInstance_->removeListener(this);
+                this->compositorInstance_ = nullptr;
+            }
+            if (!this->compositorName_.empty())
+            {
+                // add the new compositor
+                this->compositorInstance_ = Ogre::CompositorManager::getSingleton().addCompositor(viewport, this->compositorName_);
+                if (this->compositorInstance_)
+                {
+                    // register as listener if required
+                    if (this->registeredAsListener_)
+                        this->compositorInstance_->addListener(this);
+                    // set visibility according to the isVisible() and the camera/viewport
+                    if (viewport->getCamera())
+                        Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, this->isVisible() && viewport->getCamera() && this->scenemanager_ == viewport->getCamera()->getSceneManager());
+                }
+                else
+                    orxout(internal_warning) << "Couldn't load compositor with name \"" << this->compositorName_ << "\"." << endl;
+            }
+            this->oldcompositorName_ = this->compositorName_;
+        }
+    }
+
+    /**
+        @brief Changes the visibility of the shader. Doesn't free any resources if set to invisible.
+    */
+    void Shader::updateVisibility()
+    {
+        if (this->compositorInstance_)
+            Ogre::CompositorManager::getSingleton().setCompositorEnabled(GraphicsManager::getInstance().getViewport(), this->compositorName_, this->isVisible());
+    }
+
+    /**
+        @brief Defines a new integer value for a given parameter. The parameter will be updated if the compositor is rendered the next time.
+    */
+    void Shader::setParameter(unsigned short technique, unsigned short pass, const std::string& parameter, int value)
+    {
+        ParameterContainer container = {technique, pass, parameter, value};
+        this->parameters_.push_back(container);
+        this->addAsListener();
+    }
+
+    /**
+        @brief Defines a new float value for a given parameter. The parameter will be updated if the compositor is rendered the next time.
+    */
+    void Shader::setParameter(unsigned short technique, unsigned short pass, const std::string& parameter, float value)
+    {
+        ParameterContainer container = {technique, pass, parameter, value};
+        this->parameters_.push_back(container);
+        this->addAsListener();
+    }
+
+    /**
+        @brief Registers the shader as CompositorInstance::Listener at the compositor. Used to change parameters.
+    */
+    void Shader::addAsListener()
+    {
+        if (!this->registeredAsListener_)
+        {
+            this->registeredAsListener_ = true;
+            if (this->compositorInstance_)
+                this->compositorInstance_->addListener(this);
+        }
+    }
+
+    /**
+        @brief Inherited by Ogre::CompositorInstance::Listener, called whenever the material is rendered. Used to change parameters.
+    */
+    void Shader::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr& materialPtr)
+    {
+        // iterate through the list of parameters
+        for (const ParameterContainer& parameter : this->parameters_)
+        {
+            Ogre::Technique* techniquePtr = materialPtr->getTechnique(parameter.technique_);
+            if (techniquePtr)
+            {
+                Ogre::Pass* passPtr = techniquePtr->getPass(parameter.pass_);
+                if (passPtr)
+                {
+                    // change the value of the parameter depending on its type
+                    if (parameter.value_.isType<int>())
+                        passPtr->getFragmentProgramParameters()->setNamedConstant(parameter.parameter_, parameter.value_.get<int>());
+                    else if (parameter.value_.isType<float>())
+                        passPtr->getFragmentProgramParameters()->setNamedConstant(parameter.parameter_, parameter.value_.get<float>());
+                }
+                else
+                    orxout(internal_warning) << "No pass " << parameter.pass_ << " in technique " << parameter.technique_ << " in compositor \"" << this->compositorName_ << "\" or pass has no shader." << endl;
+            }
+            else
+                orxout(internal_warning) << "No technique " << parameter.technique_ << " in compositor \"" << this->compositorName_ << "\" or technique has no pass with shader." << endl;
+        }
+        this->parameters_.clear();
+    }
+
+    /**
+        @brief Detects if the Cg program manager plugin is active.
+    */
+    /* static */ bool Shader::hasCgProgramManager()
+    {
+        if (Ogre::Root::getSingletonPtr())
+        {
+            const Ogre::Root::PluginInstanceList& plugins = Ogre::Root::getSingleton().getInstalledPlugins();
+            for (Ogre::Plugin* plugin : plugins)
+                if (plugin->getName() == "Cg Program Manager")
+                    return true;
+        }
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/Shader.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/Shader.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/Shader.h	(revision 11817)
@@ -0,0 +1,124 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Shader_H__
+#define _Shader_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <list>
+#include <string>
+#include <OgreCompositorInstance.h>
+
+#include "util/MultiType.h"
+#include "core/ViewportEventListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief Shader is a wrapper class around Ogre::CompositorInstance. It provides some
+        functions to easily change the visibility and parameters for shader programs.
+    */
+    class _ToolsExport Shader : public ViewportEventListener, public Ogre::CompositorInstance::Listener
+    {
+        public:
+            Shader(Ogre::SceneManager* scenemanager = nullptr);
+            virtual ~Shader();
+
+            /// Defines if the shader is visible or not.
+            inline void setVisible(bool bVisible)
+            {
+                if (this->bVisible_ != bVisible)
+                {
+                    this->bVisible_ = bVisible;
+                    this->updateVisibility();
+                }
+            }
+            /// Returns whether or not the shader is visible.
+            inline bool isVisible() const
+                { return this->bVisible_; }
+            void updateVisibility();
+
+            /// Defines the compositor's name (located in a .compositor file).
+            inline void setCompositorName(const std::string& name)
+            {
+                if (this->compositorName_ != name)
+                {
+                    this->compositorName_ = name;
+                    this->changedCompositorName();
+                }
+            }
+            /// Returns the compositor's name.
+            inline const std::string& getCompositorName() const
+                { return this->compositorName_; }
+            void changedCompositorName();
+            void changedCompositorName(Ogre::Viewport* viewport);
+
+            /// Sets the scenemanager (usually provided in the constructor, but can be set later). Shouldn't be changed once it's set.
+            inline void setSceneManager(Ogre::SceneManager* scenemanager)
+                { this->scenemanager_ = scenemanager; }
+            /// Returns the scene manager.
+            inline Ogre::SceneManager* getSceneManager() const
+                { return this->scenemanager_; }
+
+            virtual void cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera) override;
+
+            void setParameter(unsigned short technique, unsigned short pass, const std::string& parameter, float value);
+            void setParameter(unsigned short technique, unsigned short pass, const std::string& parameter, int value);
+
+            virtual void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr& materialPtr) override;
+
+        private:
+            static bool hasCgProgramManager();
+
+            Ogre::SceneManager* scenemanager_;              ///< The scenemanager for which the shader is active
+            Ogre::CompositorInstance* compositorInstance_;  ///< The compositor instance representing the wrapped compositor
+            bool bVisible_;                                 ///< True if the shader should be visible
+            bool bLoadCompositor_;                          ///< True if the compositor should be loaded (usually false if no graphics)
+            std::string compositorName_;                    ///< The name of the current compositor
+            std::string oldcompositorName_;                 ///< The name of the previous compositor (used to unregister)
+
+        private:
+            void addAsListener();
+
+            /// Helper struct to store parameters for shader programs.
+            struct ParameterContainer
+            {
+                unsigned short technique_;  ///< The ID of the technique
+                unsigned short pass_;       ///< The ID of the pass
+                std::string parameter_;     ///< The name of the parameter
+
+                MultiType value_;           ///< The desired value of the parameter
+            };
+
+            std::list<ParameterContainer> parameters_;  ///< The list of parameters that should be set on the next update
+            bool registeredAsListener_;                 ///< True if the shader should register itself as listener at the compositor
+    };
+}
+
+#endif /* _Shader_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/TextureGenerator.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/TextureGenerator.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/TextureGenerator.cc	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the TextureGenerator.
+*/
+
+#include "TextureGenerator.h"
+
+#include <OgreMaterialManager.h>
+#include <OgreTechnique.h>
+#include "util/Convert.h"
+#include "util/Math.h"
+
+#if _MSC_VER >= 1900
+#define STLSPEC constexpr
+#else
+#define STLSPEC inline
+#endif
+
+namespace std
+{
+    template <>
+    STLSPEC bool less<orxonox::ColourValue>::operator()(const orxonox::ColourValue& __x, const orxonox::ColourValue& __y) const
+    {
+        //MSVC14 needs this function to be constexpr, but doesn't support C++14's style
+        //Keep the old code around for superior readability
+        //if (__x.r == __y.r)
+        //{
+        //    if (__x.g == __y.g)
+        //    {
+        //        if (__x.b == __y.b)
+        //        {
+        //            return __x.a < __y.a;
+        //        }
+        //        return __x.b < __y.b;
+        //    }
+        //    return __x.g < __y.g;
+        //}
+        //return __x.r < __y.r;
+        return __x.r == __y.r ? __x.g == __y.g ? __x.b == __y.b ? __x.a < __y.a : __x.b < __y.b : __x.g < __y.g :  __x.r < __y.r;
+    }
+}
+
+namespace orxonox
+{
+    std::map<std::string, std::map<ColourValue, std::string>> TextureGenerator::materials_s;
+    unsigned int TextureGenerator::materialCount_s = 0;
+
+    /*static*/ const std::string& TextureGenerator::getMaterialName(const std::string& textureName, const ColourValue& colour)
+    {
+        std::map<ColourValue, std::string>& colourMap = materials_s[textureName];
+        std::map<ColourValue, std::string>::const_iterator it = colourMap.find(colour);
+
+        if (it == colourMap.end())
+        {
+            const std::string& materialName = textureName + "_Material_" + multi_cast<std::string>(materialCount_s++);
+            Ogre::MaterialPtr material = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().create(materialName, "General"));
+            material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
+            Ogre::TextureUnitState* textureUnitState = material->getTechnique(0)->getPass(0)->createTextureUnitState();
+            textureUnitState->setTextureName(textureName);
+            textureUnitState->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, colour);
+            return (colourMap[colour] = materialName);
+        }
+        else
+        {
+            return it->second;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/TextureGenerator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/TextureGenerator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/TextureGenerator.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+/**
+    @file
+    @brief
+*/
+
+#ifndef _TextureGenerator_H__
+#define _TextureGenerator_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include <map>
+#include <string>
+#include "util/UtilPrereqs.h"
+
+namespace orxonox
+{
+    class _ToolsExport TextureGenerator
+    {
+    public:
+        static const std::string& getMaterialName(const std::string& textureName, const ColourValue& colour);
+
+    private:
+        // static class, no instances allowed:
+        TextureGenerator() = delete;
+        TextureGenerator(const TextureGenerator&) = delete;
+        TextureGenerator& operator=(const TextureGenerator&) = delete;
+        ~TextureGenerator() = delete;
+
+        static std::map<std::string, std::map<ColourValue, std::string>> materials_s;
+        static unsigned int materialCount_s;
+    };
+}
+
+#endif /* _TextureGenerator_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/Timer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/Timer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/Timer.cc	(revision 11817)
@@ -0,0 +1,269 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the Timer class.
+*/
+
+#include "Timer.h"
+
+#include <set>
+
+#include <boost/bimap.hpp>
+
+#include "util/Clock.h"
+#include "core/CoreIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/command/CommandExecutor.h"
+#include "core/command/Executor.h"
+#include "core/command/Functor.h"
+#include "tools/interfaces/TimeFactorListener.h"
+
+namespace orxonox
+{
+    SetConsoleCommand("delay", &delay).argumentCompleter(1, autocompletion::command());
+    SetConsoleCommand("delayreal", &delayreal).argumentCompleter(1, autocompletion::command());
+    SetConsoleCommand("killdelay", &killdelay);
+    SetConsoleCommand("killdelays", &killdelays);
+
+    static boost::bimap<unsigned int, Timer*> delaytimers;
+    static unsigned int delayHandleCounter = 0;
+
+    /**
+        @brief Console-command: Calls another console command after @a delay seconds (game time).
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int delay(float delay, const std::string& command)
+    {
+        return addDelayedCommand(new Timer(), delay, command);
+    }
+
+    /**
+        @brief Console-command: Calls another console command after @a delay seconds (real time)
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int delayreal(float delay, const std::string& command)
+    {
+        return addDelayedCommand(new RealTimer(), delay, command);
+    }
+
+    /**
+        @brief Helper function, used by delay() and delayreal() to add a delayed command.
+        @param timer The timer which will execute the command
+        @param delay The delay in seconds
+        @param command The console command
+        @return The handle of the delayed command, can be used as argument for killdelay()
+    */
+    unsigned int addDelayedCommand(Timer* timer, float delay, const std::string& command)
+    {
+        delaytimers.insert(boost::bimap<unsigned int, Timer*>::value_type(++delayHandleCounter, timer));
+
+        const ExecutorStaticPtr& delayexecutor = createExecutor(createFunctor(&executeDelayedCommand));
+        delayexecutor->setDefaultValues(timer, command);
+        timer->setTimer(delay, false, delayexecutor);
+
+        return delayHandleCounter;
+    }
+
+    /**
+        @brief Helper function for delay(), executes the command and destroys the timer.
+        @param timer The timer which called this function.
+        @param command The command to execute
+    */
+    void executeDelayedCommand(Timer* timer, const std::string& command)
+    {
+        CommandExecutor::execute(command);
+        delete timer;
+        delaytimers.right.erase(timer);
+    }
+
+    /**
+        @brief Console-command: Kills all scheduled commands that were delayed using delay().
+    */
+    void killdelays()
+    {
+        for (boost::bimap<unsigned int, Timer*>::left_map::iterator it = delaytimers.left.begin(); it != delaytimers.left.end(); ++it)
+            delete it->second;
+
+        delaytimers.clear();
+    }
+
+    /**
+        @brief Console-command: Kills a delayed command with given handle.
+    */
+    void killdelay(unsigned int handle)
+    {
+        boost::bimap<unsigned int, Timer*>::left_map::iterator it = delaytimers.left.find(handle);
+        if (it != delaytimers.left.end())
+        {
+            delete it->second;
+            delaytimers.left.erase(it);
+        }
+    }
+
+    RegisterClassNoArgs(Timer);
+
+    /**
+        @brief Constructor: Sets the default-values.
+    */
+    Timer::Timer()
+    {
+        this->init();
+        RegisterObject(Timer);
+    }
+
+    /**
+        @brief Constructor: Initializes and starts the timer, which will call an executor after some time.
+        @param interval         The timer-interval in seconds
+        @param bLoop            If true, the executor gets called every @a interval seconds
+        @param executor         The executor that will be called
+        @param bKillAfterCall   If true, the timer will be deleted after the executor was called
+    */
+    Timer::Timer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall)
+    {
+        this->init();
+        RegisterObject(Timer);
+
+        this->setTimer(interval, bLoop, executor, bKillAfterCall);
+    }
+
+    /**
+        @brief Initializes the Timer
+    */
+    void Timer::init()
+    {
+        this->executor_ = nullptr;
+        this->interval_ = 0;
+        this->bLoop_ = false;
+        this->bActive_ = false;
+        this->bKillAfterCall_ = false;
+
+        this->time_ = 0;
+    }
+
+    /**
+        @brief Returns the current time factor of the game.
+    */
+    float Timer::getTimeFactor()
+    {
+        return TimeFactorListener::getTimeFactor();
+    }
+
+    /**
+        @brief Initializes and starts the timer, which will call an executor after some time.
+        @param interval         The timer-interval in seconds
+        @param bLoop            If true, the executor gets called every @a interval seconds
+        @param executor         The executor that will be called
+        @param bKillAfterCall   If true, the timer will be deleted after the executor was called
+    */
+    void Timer::setTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall)
+    {
+        this->setInterval(interval);
+        this->bLoop_ = bLoop;
+        this->executor_ = executor;
+        this->bActive_ = true;
+
+        this->time_ = this->interval_;
+        this->bKillAfterCall_ = bKillAfterCall;
+
+        executor->getFunctor()->setSafeMode(true);
+    }
+
+    /**
+        @brief Calls the executor and destroys the timer if requested.
+    */
+    void Timer::run()
+    {
+        bool temp = this->bKillAfterCall_; // to avoid errors with bKillAfterCall_=false and an exutors which destroy the timer
+
+        (*this->executor_)();
+
+        if (temp)
+            delete this;
+    }
+
+    /**
+        @brief Updates the timer before the frames are rendered.
+    */
+    void Timer::tick(const Clock& time)
+    {
+        if (this->bActive_)
+        {
+            // If active: Decrease the timer by the duration of the last frame
+            this->time_ -= static_cast<long long>(time.getDeltaTimeMicroseconds() * this->getTimeFactor());
+
+            if (this->time_ <= 0)
+            {
+                // It's time to call the function
+                if (this->bLoop_ && !this->bKillAfterCall_)
+                {
+                    this->time_ += this->interval_; // Q: Why '+=' and not '='? A: Think about it. It's more accurate like that. Seriously.
+                    while (this->time_ <= 0)
+                    {
+                        // The interval was shorter than one tick, so execute the function more than once
+                        this->run();
+                        this->time_ += this->interval_;
+                    }
+                }
+                else
+                    this->stopTimer(); // Stop the timer if we don't want to loop
+
+                this->run();
+            }
+        }
+    }
+
+    ///////////////
+    // RealTimer //
+    ///////////////
+
+    RegisterClassNoArgs(RealTimer);
+
+    /// @copydoc Timer::Timer
+    RealTimer::RealTimer()
+    {
+        RegisterObject(RealTimer);
+    }
+
+    /// @copydoc Timer::Timer(float, bool, const ExecutorPtr&, bool)
+    RealTimer::RealTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall) : Timer(interval, bLoop, executor, bKillAfterCall)
+    {
+        RegisterObject(RealTimer);
+    }
+
+    /// Returns always 1 because RealTimer doesn't depend on the game time.
+    float RealTimer::getTimeFactor()
+    {
+        return 1;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/Timer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/Timer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/Timer.h	(revision 11817)
@@ -0,0 +1,181 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Timer Timer
+    @ingroup Tools
+*/
+
+/**
+    @file
+    @ingroup Timer
+    @brief Declaration of the Timer class, used to call functions after a given time-interval.
+
+    @anchor TimerExample
+
+    Timer is a helper class that executes a function after a given amount of time.
+
+    Usage: <br>
+    header.h:
+    @code
+    class MyClass
+    {
+        public:
+            MyClass();
+            void functionName();
+
+        private:
+            Timer myTimer;
+    };
+    @endcode
+
+    source.cc:
+    @code
+    #include "core/command/Executor.h"
+
+    MyClass::MyClass()
+    {
+        myTimer.setTimer(3, false, createExecutor(createFunctor(&ClassName::myFunction, this)));
+    }
+
+    void MyClass::myFunction()
+    {
+        orxout() << "Hello World" << endl;
+    }
+    @endcode
+
+    The code in this example prints "Hello World" to the console, 3 seconds after creating
+    an instance of MyClass.
+*/
+
+#ifndef _Timer_H__
+#define _Timer_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include "core/object/Listable.h"
+#include "core/command/ExecutorPtr.h"
+
+namespace orxonox
+{
+    unsigned int delay(float delay, const std::string& command);
+    unsigned int delayreal(float delay, const std::string& command);
+
+    unsigned int addDelayedCommand(Timer* timer, float delay, const std::string& command);
+    void executeDelayedCommand(Timer* timer, const std::string& command);
+
+    void killdelay(unsigned int handle);
+    void killdelays();
+
+    /**
+        @brief Timer is a helper class that executes a function after a given amount of seconds in game-time.
+
+        @see See @ref TimerExample "Timer.h" for an example.
+
+        The time interval of Timer depends on the game time, hence it stops if the game is paused or runs
+        slower/faster if the game-speed is modified. See RealTimer for a timer class which doesn't depend
+        on the game time.
+    */
+    class _ToolsExport Timer : public Listable
+    {
+        public:
+            Timer();
+
+            Timer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall = false);
+
+            void setTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall = false);
+
+            void run();
+
+            /// Re-starts the timer: The executor will be called after @a interval seconds.
+            inline void startTimer()
+                { this->bActive_ = true; this->time_ = this->interval_; }
+            /// Stops the timer.
+            inline void stopTimer()
+                { this->bActive_ = false; this->time_ = this->interval_; }
+            /// Pauses the timer - it will continue with the actual state if you call unpauseTimer().
+            inline void pauseTimer()
+                { this->bActive_ = false; }
+            /// Unpauses the timer - continues with the given state.
+            inline void unpauseTimer()
+                { this->bActive_ = true; }
+            /// Returns true if the timer is active (neither stopped nor paused).
+            inline bool isActive() const
+                { return this->bActive_; }
+            /// Returns the remaining time until the timer calls the executor.
+            inline float getRemainingTime() const
+                { return static_cast<float>(this->time_ / 1000000.0f); }
+            /// Increases the remaining time of the timer by the given amount of time (in seconds).
+            inline void addTime(float time)
+                { if (time > 0.0f) this->time_ += static_cast<long long>(time * 1000000.0f); }
+            /// Decreases the remaining time of the timer by the given amount of time (in seconds)
+            inline void removeTime(float time)
+                { if (time > 0.0f) this->time_ -= static_cast<long long>(time * 1000000.0f); }
+            /// Changes the calling interval.
+            inline void setInterval(float interval)
+                { this->interval_ = static_cast<long long>(interval * 1000000.0f); }
+            /// Defines if the timer call the executor every @a interval seconds or only once.
+            inline void setLoop(bool bLoop)
+                { this->bLoop_ = bLoop; }
+
+            void tick(const Clock& time);
+
+        protected:
+            virtual float getTimeFactor();
+
+        private:
+            void init();
+
+            ExecutorPtr executor_;  //!< The executor of the function that will be called when the time expires
+
+            long long interval_;    //!< The time-interval in micro seconds
+            bool bLoop_;            //!< If true, the executor gets called every @a interval seconds
+            bool bActive_;          //!< If true, the timer ticks and calls the executor if the time's up
+            bool bKillAfterCall_;   //!< If true the timer gets deleted after it expired and called the executor
+
+            long long time_;        //!< Internal variable, counting the time untill the next executor-call
+    };
+
+    /**
+        @brief RealTimer is a helper class that executes a function after a given amount of seconds in real-time.
+
+        The time interval of RealTimer doesn't depend on the game time, it will also call the function
+        if the game is paused. See Timer for a timer class that depends on the game time.
+    */
+    class _ToolsExport RealTimer : public Timer
+    {
+        public:
+            RealTimer();
+            RealTimer(float interval, bool bLoop, const ExecutorPtr& executor, bool bKillAfterCall = false);
+
+        protected:
+            virtual float getTimeFactor() override;
+    };
+}
+
+#endif /* _Timer_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/ToolsPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/ToolsPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/ToolsPrereqs.h	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the tools module
+*/
+
+#ifndef _ToolsPrereqs_H__
+#define _ToolsPrereqs_H__
+
+#include "OrxonoxConfig.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(TOOLS_STATIC_BUILD)
+#  ifdef TOOLS_SHARED_BUILD
+#    define _ToolsExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _ToolsExport
+#    else
+#      define _ToolsExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _ToolsPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _ToolsExport  __attribute__ ((visibility("default")))
+#  define _ToolsPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _ToolsExport
+#  define _ToolsPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Enums
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    namespace LODParticle
+    {
+        enum Value
+        {
+            Off = 0,
+            Low = 1,
+            Normal = 2,
+            High = 3
+        };
+    }
+}
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class BillboardSet;
+    class BulletDebugDrawer;
+    class DebugDrawer;
+    class IcoSphere;
+    class Mesh;
+    class ParticleInterface;
+    class RealTimer;
+    class ResourceCollection;
+    class ResourceLocation;
+    class Shader;
+    class Tickable;
+    class TimeFactorListener;
+    class Timer;
+}
+
+namespace Ogre
+{
+    // OGRE Wiki adapted code
+    class DynamicLines;
+    class DynamicRenderable;
+}
+
+#endif /* _ToolsPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,8 @@
+ADD_SOURCE_FILES(TOOLS_SRC_FILES
+  DemoApp.cpp
+  OgreFramework.cpp
+  OgreGpuCommandBufferFlush.cpp
+  Q3Map.cpp
+  Q3Map_Bezier.cpp
+  Q3Map_BspVertex.cpp
+)
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/DemoApp.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/DemoApp.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/DemoApp.cpp	(revision 11817)
@@ -0,0 +1,602 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include "DemoApp.hpp"
+
+#include <OgreLight.h>
+#include <OgreWindowEventUtilities.h>
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+DemoApp::DemoApp()
+{
+	
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+DemoApp::~DemoApp()
+{
+	StereoConfig_Write() ; // write out the stereo configuration.  Just rough for now, a binary file
+
+	
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void DemoApp::startDemo()
+{
+	
+	
+	m_bShutdown = false;
+	
+	
+
+
+
+
+
+		new OgreFramework();
+
+		
+
+		OgreFramework::getSingletonPtr()->initOgre("Video Start", this, 0);
+		
+		BZNConfig_Read() ;
+
+		OgreFramework::getSingletonPtr()->AdditionalSetup() ;
+
+		if(!setupDemoScene()) return ; // failure setting up level
+		
+		
+		
+		//runDemo_Default();
+		runDemo_MethodA();
+
+		OgreFramework::getSingletonPtr()->UnloadMap(true) ;
+		//OgreFramework::getSingletonPtr()->OFBug.MessageInt(333) ;
+		//delete OgreFramework::getSingletonPtr(); // causes a crash on exit in 1.7, was ok in 1.6.3
+		//OgreFramework::getSingletonPtr()->
+		
+		OgreFramework::getSingletonPtr()->FinalShutdown() ;
+
+		
+		//OgreFramework::getSingletonPtr()->OFBug.MessageInt(333) ;
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+int DemoApp::setupDemoScene()
+{
+	return OgreFramework::getSingletonPtr()->LoadMap() ;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+// four different versions of runDemo() depending on method of GPUBuffer flushing.
+
+int DemoApp::runDemo_Default()
+{
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (Default)...");
+
+//	char chMessage[1024] ;
+	
+	UINT uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+	UINT uFrameTotalTime=0 ;
+
+	OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+	
+	
+
+
+
+	while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown()) 
+	{
+
+
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+			Ogre::WindowEventUtilities::messagePump() ;
+#endif	
+
+
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+		{
+
+
+         // get start time of frame
+         uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+            
+         // update input and physics
+         OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+         OgreFramework::getSingletonPtr()->m_pMouse->capture();
+         OgreFramework::getSingletonPtr()->updateOgre(uFrameTotalTime/1000.0f);
+
+
+         // render the frame
+				 OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+
+
+				
+
+			// calculate frame time.
+			uFrameTotalTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+		}
+		else
+		{
+			Sleep(1000);
+		}
+
+
+	}
+
+
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (Default)");
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+	return 1 ;
+}
+
+int DemoApp::runDemo_MethodA()
+{
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (MethodA)...");
+
+//	char chMessage[1024] ;
+	
+	UINT uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+	UINT uFrameTotalTime=0 ;
+
+	OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+	
+	
+
+
+	/////////////////////////////////////////////////////////////////////////////////////////////
+	// use a renderQueueListener with 1 to 4 HardwareOcclusionQueries to prevent the CPU from 
+	// getting too far ahead of the GPU and causing input lag from keyboard and mouse.
+	// thanks to Sinbad for this suggestion and code outline.
+	// We aren't actually doing Hardware Occlusion Culling, just exploiting the way we can
+	// make it flush the GPU buffer for prior frames.
+	// Messing with the GPU command buffer can be turned off completely by seting m_nMaxGPUQuery to 0 
+
+	
+	// get the maximum gpu queries to be used.  
+	int nMaxGPUQuery=OgreFramework::getSingletonPtr()->m_nMaxGPUQuery ;
+	unsigned int dummy=0 ;
+	int nNewQuery=0 ;
+	int nOldQuery=0 ;
+	rQueueListener* rqListener=NULL ;
+	Ogre::HardwareOcclusionQuery** pHOQ=NULL ;
+
+	int nQueryReady[MAXGPUQUERY] ;
+		
+
+	if(nMaxGPUQuery!=0) // if querying is turned on
+	{
+		// make sure it is in range.
+		if(nMaxGPUQuery<1) 
+			nMaxGPUQuery=1 ;
+		else
+			if(nMaxGPUQuery>MAXGPUQUERY) 
+			nMaxGPUQuery=MAXGPUQUERY ;
+
+
+		rqListener = new rQueueListener ;
+		
+		OgreFramework::getSingletonPtr()->m_pSceneMgr->addRenderQueueListener(rqListener) ;
+
+		// create our queries
+		pHOQ=rqListener->Query ;
+		for(nNewQuery=0 ; nNewQuery<nMaxGPUQuery ; nNewQuery++)
+			pHOQ[nNewQuery] = OgreFramework::getSingletonPtr()->m_pRoot->getRenderSystem()->createHardwareOcclusionQuery() ;
+
+		nNewQuery=nOldQuery-1 ;
+		if(nNewQuery<0)
+			nNewQuery+=nMaxGPUQuery ;
+
+		// set the queries to not ready
+		for(int nReadyLoop=0 ; nReadyLoop<MAXGPUQUERY ; nReadyLoop++)
+			nQueryReady[nReadyLoop]=0 ;
+	}
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+	while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown()) 
+	{
+
+
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+			Ogre::WindowEventUtilities::messagePump() ;
+#endif	
+
+
+			//OgreFramework::getSingletonPtr()->m_pLog->logMessage("Update START");
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+		{
+
+			// get start time of frame
+			uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+				
+			// update input and physics
+			OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+			OgreFramework::getSingletonPtr()->m_pMouse->capture();
+			OgreFramework::getSingletonPtr()->updateOgre(uFrameTotalTime/1000.0f);
+
+			
+			if(nMaxGPUQuery==0) // querying the GPU command buffer is disabled
+			{
+				// render the frame
+				OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+			}
+			else								// querying the GPU command buffer is enabled
+			{
+				// increment the buffer.  
+				nNewQuery=nOldQuery ;
+				nOldQuery++ ;
+				if(nOldQuery==nMaxGPUQuery)
+					nOldQuery=0 ;
+
+
+				// define query beginning for this frame
+				pHOQ[ nNewQuery ]->beginOcclusionQuery() ;
+
+				// render the frame
+				//OgreFramework::getSingletonPtr()->m_pRoot->renderOneFrame();
+				OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+				// define query end for this frame
+				pHOQ[ nNewQuery ]->endOcclusionQuery() ;
+				nQueryReady[ nNewQuery ]=1 ;
+			
+
+
+				// pull query for a prior frame.  Flushes GPU command buffer up to the end of a prior frame but no further.
+				if(nQueryReady[ nOldQuery ])
+				{
+					pHOQ[ nOldQuery ]->pullOcclusionQuery(&dummy) ;
+					nQueryReady[ nOldQuery ]=0 ;
+				}
+			}
+			
+
+
+			// calculate frame time.
+			uFrameTotalTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+		}
+		else
+		{
+			Sleep(1000);
+		}
+
+
+	}
+
+	if(nMaxGPUQuery>0) // if necessary, clean up our HOQ queries and renderQueueListener
+	{
+	
+		for(nNewQuery=0 ; nNewQuery<nMaxGPUQuery ; nNewQuery++)
+			OgreFramework::getSingletonPtr()->m_pRoot->getRenderSystem()->destroyHardwareOcclusionQuery( pHOQ[nNewQuery] ) ;
+		
+		OgreFramework::getSingletonPtr()->m_pSceneMgr->removeRenderQueueListener(rqListener) ;
+		delete rqListener ;
+	}
+
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (MethodA)");
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+	return 1 ;
+}
+
+int DemoApp::runDemo_MethodB()
+{
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (MethodB)...");
+
+//	char chMessage[1024] ;
+	
+	UINT uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+	UINT uFrameTotalTime=0 ;
+
+	OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+	
+
+	
+	int numberOfQueuedFrames=1 ;
+	bool GPUBufferSetupDone=false ;
+
+
+	while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown()) 
+	{
+
+
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+			Ogre::WindowEventUtilities::messagePump() ;
+#endif	
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+		{
+
+
+			   if(GPUBufferSetupDone==false) // I added it here because I assume I can be very sure there's an active render window by now.
+         {
+            GPUBufferSetupDone=true ;
+            mBufferFlush.start(numberOfQueuedFrames);
+         }
+
+         // get start time of frame
+         uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+            
+         // update input and physics
+         OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+         OgreFramework::getSingletonPtr()->m_pMouse->capture();
+         OgreFramework::getSingletonPtr()->updateOgre(uFrameTotalTime/1000.0f);
+
+
+         // render the frame
+				 OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+
+
+
+			// calculate frame time.
+			uFrameTotalTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+
+		}
+		else
+		{
+			Sleep(1000);
+		}
+
+
+
+	}
+
+
+	mBufferFlush.stop() ;
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (MethodB)");
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+	return 1 ;
+}
+
+
+int DemoApp::runDemo_MethodC()
+{
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Start main loop (MethodC)...");
+
+	char chMessage[1024] ;
+	
+	int uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMilliseconds();
+	int uFrameRenderTime=0 ;
+	int uFrameTargetTime=10000 ;
+
+	OgreFramework::getSingletonPtr()->m_pRenderWnd->resetStatistics() ;
+	
+	
+
+	int uSleepTime=0 ;
+
+	while(!m_bShutdown && !OgreFramework::getSingletonPtr()->isOgreToBeShutDown()) 
+	{
+
+
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isClosed())m_bShutdown = true;
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
+			Ogre::WindowEventUtilities::messagePump() ;
+#endif	
+
+
+
+
+		if(OgreFramework::getSingletonPtr()->m_pRenderWnd->isActive())
+		{
+
+
+       // get start time of frame
+       uFrameStartTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+            
+         // update input and physics
+         OgreFramework::getSingletonPtr()->m_pKeyboard->capture();
+         OgreFramework::getSingletonPtr()->m_pMouse->capture();
+         OgreFramework::getSingletonPtr()->updateOgre(uFrameTargetTime/1000.0f);
+
+
+         // render the frame
+				 OgreFramework::getSingletonPtr()->UpdateRenderTargets() ;
+
+
+			// calculate frame time.
+			uFrameRenderTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds()-uFrameStartTime ;
+			
+
+			uFrameTargetTime-=1000 ;
+			if(uFrameTargetTime<0) uFrameTargetTime=0 ;
+
+			if(uFrameRenderTime>uFrameTargetTime-10000)
+				uFrameTargetTime=uFrameRenderTime+20000 ;
+
+			if(uFrameTargetTime>100000) uFrameTargetTime=100000 ;
+
+
+			
+
+
+			uSleepTime=(int)((uFrameTargetTime-uFrameRenderTime)/1000.0f) ;
+			if(uSleepTime>0) Sleep(uSleepTime) ;
+
+			sprintf(chMessage, "render %i, target %i, sleep %i", uFrameRenderTime, uFrameTargetTime, uSleepTime) ;
+			OgreFramework::getSingletonPtr()->m_pLog->logMessage(chMessage);
+
+		}
+		else
+		{
+			Sleep(1000);
+		}
+
+
+	}
+
+
+
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Main loop quit (MethodC)");
+	OgreFramework::getSingletonPtr()->m_pLog->logMessage("Shutdown OGRE...");
+
+
+	return 1 ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+void DemoApp::ResetSectionTimer()
+{
+	m_uLastTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+}
+
+UINT DemoApp::GetSectionTimer()
+{
+	UINT uThisTime=OgreFramework::getSingletonPtr()->m_pTimer->getMicroseconds() ;
+	UINT uSectionTime=uThisTime-m_uLastTime ;
+	m_uLastTime=uThisTime ;
+	return uSectionTime ;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+
+bool DemoApp::keyPressed(const OIS::KeyEvent &keyEventRef)
+{
+	
+	OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);
+	
+	if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_F))
+	{
+		 //do something
+	}
+	
+	return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool DemoApp::keyReleased(const OIS::KeyEvent &keyEventRef)
+{
+	OgreFramework::getSingletonPtr()->keyReleased(keyEventRef);
+	
+	return true;
+}
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void DemoApp::StereoConfig_Write( void )
+{
+	int fh;
+	if( (fh = _open( "stereoscopic.cfg", _O_RDWR | _O_BINARY | _O_CREAT | _O_TRUNC, 
+                               _S_IREAD | _S_IWRITE )) != -1 )
+	{
+		write( fh, (void*)&OgreFramework::getSingletonPtr()->m_nGoggleMode,						sizeof(int)) ;
+		write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleZPos,					sizeof(float))	;
+		write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXGap,					sizeof(float))	;
+		write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXScale,				sizeof(float))	;
+		write( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleYScale,				sizeof(float))	;
+		_close( fh );
+	}
+}
+bool DemoApp::StereoConfig_Read(void)
+{
+ 	int fh;
+	bool found_file=true ;
+
+	// Open file for input
+	if( (fh = _open( "stereoscopic.cfg", _O_RDONLY | _O_BINARY )) == -1 )
+	{
+		found_file=false ;
+	}
+	else
+	{
+		read( fh, (void*)&OgreFramework::getSingletonPtr()->m_nGoggleMode,						sizeof(int)) ;
+		read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleZPos,						sizeof(float))	;
+		read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXGap,						sizeof(float))	;
+		read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleXScale,					sizeof(float))	;
+		read( fh, (void*)&OgreFramework::getSingletonPtr()->m_flGoggleYScale,					sizeof(float))	;
+		_close( fh );
+	 }//  end if else
+	return found_file ;
+}
+
+
+void DemoApp::BZNConfig_Write(void)
+{
+	int fh;
+	if( (fh = _open( "bzn.cfg", _O_RDWR | _O_BINARY | _O_CREAT | _O_TRUNC, 
+                               _S_IREAD | _S_IWRITE )) != -1 )
+	{
+		write( fh, (void*)OgreFramework::getSingletonPtr()->m_chBZNConfig,						BZN_CONFIG_SIZE) ;
+		_close( fh );
+	}
+}
+
+bool DemoApp::BZNConfig_Read(void)
+{
+
+	int fh;
+	bool found_file=true ;
+
+	// make sure the config memory is blank
+	ZeroMemory((void*)OgreFramework::getSingletonPtr()->m_chBZNConfig, BZN_CONFIG_SIZE) ;
+
+	// Open file for input
+	if( (fh = _open( "bzn.cfg", _O_RDONLY | _O_BINARY )) == -1 )
+	{
+		found_file=false ;
+	}
+	else
+	{
+		read( fh, (void*)OgreFramework::getSingletonPtr()->m_chBZNConfig,						BZN_CONFIG_SIZE) ;
+		_close( fh );
+		OgreFramework::getSingletonPtr()->ParseBZNConfig() ;
+	 }//  end if else
+	
+	
+	return found_file ;
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/DemoApp.hpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/DemoApp.hpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/DemoApp.hpp	(revision 11817)
@@ -0,0 +1,57 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#ifndef OGRE_DEMO_HPP
+#define OGRE_DEMO_HPP
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include "OgreFramework.hpp"
+
+// for loading/saving the stereo config file
+#include <io.h>
+#include <fcntl.h>      /* Needed only for _O_RDWR definition */
+#include <sys/stat.h>
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+class DemoApp : public OIS::KeyListener
+{
+public:
+	DemoApp();
+	~DemoApp();
+
+	void startDemo();
+	
+	bool keyPressed(const OIS::KeyEvent &keyEventRef);
+	bool keyReleased(const OIS::KeyEvent &keyEventRef);
+
+private:
+	int setupDemoScene();
+	int runDemo_Default(); // no gpu buffer flushing code
+	int runDemo_MethodA(); // my HOQ gpu buffer flushing code
+	int runDemo_MethodB(); // ogre HOQ gpu buffer flushing code
+	int runDemo_MethodC(); // my blit gpu buffer flushing code
+
+	UINT m_uLastTime ;
+	void ResetSectionTimer() ;
+	UINT GetSectionTimer() ;
+
+
+	void StereoConfig_Write( void ) ;
+	bool StereoConfig_Read(void) ;
+
+	void BZNConfig_Write(void) ;
+	bool BZNConfig_Read(void) ;
+
+	
+
+	Ogre::GpuCommandBufferFlush mBufferFlush;
+
+	bool						m_bShutdown;
+};
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#endif 
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/ExampleApplication.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/ExampleApplication.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/ExampleApplication.h	(revision 11817)
@@ -0,0 +1,257 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+(Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+You may use this sample code for anything you like, it is not covered by the
+LGPL like the rest of the engine.
+-----------------------------------------------------------------------------
+*/
+/*
+-----------------------------------------------------------------------------
+Filename:    ExampleApplication.h
+Description: Base class for all the OGRE examples
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __ExampleApplication_H__
+#define __ExampleApplication_H__
+
+#include "Ogre.h"
+#include "OgreConfigFile.h"
+#include "ExampleFrameListener.h"
+
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+#include <CoreFoundation/CoreFoundation.h>
+
+// This function will locate the path to our application on OS X,
+// unlike windows you can not rely on the curent working directory
+// for locating your configuration files and resources.
+std::string macBundlePath()
+{
+    char path[1024];
+    CFBundleRef mainBundle = CFBundleGetMainBundle();
+    assert(mainBundle);
+
+    CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);
+    assert(mainBundleURL);
+
+    CFStringRef cfStringRef = CFURLCopyFileSystemPath( mainBundleURL, kCFURLPOSIXPathStyle);
+    assert(cfStringRef);
+
+    CFStringGetCString(cfStringRef, path, 1024, kCFStringEncodingASCII);
+
+    CFRelease(mainBundleURL);
+    CFRelease(cfStringRef);
+
+    return std::string(path);
+}
+#endif
+
+using namespace Ogre;
+
+/** Base class which manages the standard startup of an Ogre application.
+    Designed to be subclassed for specific examples if required.
+*/
+class ExampleApplication
+{
+public:
+    /// Standard constructor
+    ExampleApplication()
+    {
+        mFrameListener = 0;
+        mRoot = 0;
+		// Provide a nice cross platform solution for locating the configuration files
+		// On windows files are searched for in the current working directory, on OS X however
+		// you must provide the full path, the helper function macBundlePath does this for us.
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+		mResourcePath = macBundlePath() + "/Contents/Resources/";
+#else
+		mResourcePath = "";
+#endif
+    }
+    /// Standard destructor
+    virtual ~ExampleApplication()
+    {
+        if (mFrameListener)
+            delete mFrameListener;
+        if (mRoot)
+            OGRE_DELETE mRoot;
+    }
+
+    /// Start the example
+    virtual void go(void)
+    {
+        if (!setup())
+            return;
+
+        mRoot->startRendering();
+
+        // clean up
+        destroyScene();
+    }
+
+protected:
+    Root *mRoot;
+    Camera* mCamera;
+    SceneManager* mSceneMgr;
+    ExampleFrameListener* mFrameListener;
+    RenderWindow* mWindow;
+	Ogre::String mResourcePath;
+
+    // These internal methods package up the stages in the startup process
+    /** Sets up the application - returns false if the user chooses to abandon configuration. */
+    virtual bool setup(void)
+    {
+
+		String pluginsPath;
+		// only use plugins.cfg if not static
+#ifndef OGRE_STATIC_LIB
+		pluginsPath = mResourcePath + "plugins.cfg";
+#endif
+		
+        mRoot = OGRE_NEW Root(pluginsPath, 
+            mResourcePath + "ogre.cfg", mResourcePath + "Ogre.log");
+
+        setupResources();
+
+        bool carryOn = configure();
+        if (!carryOn) return false;
+
+        chooseSceneManager();
+        createCamera();
+        createViewports();
+
+        // Set default mipmap level (NB some APIs ignore this)
+        TextureManager::getSingleton().setDefaultNumMipmaps(5);
+
+		// Create any resource listeners (for loading screens)
+		createResourceListener();
+		// Load resources
+		loadResources();
+
+		// Create the scene
+        createScene();
+
+        createFrameListener();
+
+        return true;
+
+    }
+    /** Configures the application - returns false if the user chooses to abandon configuration. */
+    virtual bool configure(void)
+    {
+        // Show the configuration dialog and initialise the system
+        // You can skip this and use root.restoreConfig() to load configuration
+        // settings if you were sure there are valid ones saved in ogre.cfg
+        if(mRoot->showConfigDialog())
+        {
+            // If returned true, user clicked OK so initialise
+            // Here we choose to let the system create a default rendering window by passing 'true'
+            mWindow = mRoot->initialise(true);
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    virtual void chooseSceneManager(void)
+    {
+        // Create the SceneManager, in this case a generic one
+        mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "ExampleSMInstance");
+    }
+    virtual void createCamera(void)
+    {
+        // Create the camera
+        mCamera = mSceneMgr->createCamera("PlayerCam");
+
+        // Position it at 500 in Z direction
+        mCamera->setPosition(Vector3(0,0,500));
+        // Look back along -Z
+        mCamera->lookAt(Vector3(0,0,-300));
+        mCamera->setNearClipDistance(5);
+
+    }
+    virtual void createFrameListener(void)
+    {
+        mFrameListener= new ExampleFrameListener(mWindow, mCamera);
+        mFrameListener->showDebugOverlay(true);
+        mRoot->addFrameListener(mFrameListener);
+    }
+
+    virtual void createScene(void) = 0;    // pure virtual - this has to be overridden
+
+    virtual void destroyScene(void){}    // Optional to override this
+
+    virtual void createViewports(void)
+    {
+        // Create one viewport, entire window
+        Viewport* vp = mWindow->addViewport(mCamera);
+        vp->setBackgroundColour(ColourValue(0,0,0));
+
+        // Alter the camera aspect ratio to match the viewport
+        mCamera->setAspectRatio(
+            Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
+    }
+
+    /// Method which will define the source of resources (other than current folder)
+    virtual void setupResources(void)
+    {
+        // Load resource paths from config file
+        ConfigFile cf;
+        cf.load(mResourcePath + "resources.cfg");
+
+        // Go through all sections & settings in the file
+        ConfigFile::SectionIterator seci = cf.getSectionIterator();
+
+        String secName, typeName, archName;
+        while (seci.hasMoreElements())
+        {
+            secName = seci.peekNextKey();
+            ConfigFile::SettingsMultiMap *settings = seci.getNext();
+            ConfigFile::SettingsMultiMap::iterator i;
+            for (i = settings->begin(); i != settings->end(); ++i)
+            {
+                typeName = i->first;
+                archName = i->second;
+#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
+                // OS X does not set the working directory relative to the app,
+                // In order to make things portable on OS X we need to provide
+                // the loading with it's own bundle path location
+                ResourceGroupManager::getSingleton().addResourceLocation(
+                    String(macBundlePath() + "/" + archName), typeName, secName);
+#else
+                ResourceGroupManager::getSingleton().addResourceLocation(
+                    archName, typeName, secName);
+#endif
+            }
+        }
+    }
+
+	/// Optional override method where you can create resource listeners (e.g. for loading screens)
+	virtual void createResourceListener(void)
+	{
+
+	}
+
+	/// Optional override method where you can perform resource group loading
+	/// Must at least do ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+	virtual void loadResources(void)
+	{
+		// Initialise, parse scripts etc
+		ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+
+	}
+
+
+
+};
+
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/ExampleFrameListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/ExampleFrameListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/ExampleFrameListener.h	(revision 11817)
@@ -0,0 +1,419 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of OGRE
+    (Object-oriented Graphics Rendering Engine)
+For the latest info, see http://www.ogre3d.org/
+
+Copyright (c) 2000-2006 Torus Knot Software Ltd
+Also see acknowledgements in Readme.html
+
+You may use this sample code for anything you like, it is not covered by the
+LGPL like the rest of the engine.
+-----------------------------------------------------------------------------
+*/
+/*
+-----------------------------------------------------------------------------
+Filename:    ExampleFrameListener.h
+Description: Defines an example frame listener which responds to frame events.
+This frame listener just moves a specified camera around based on
+keyboard and mouse movements.
+Mouse:    Freelook
+W or Up:  Forward
+S or Down:Backward
+A:        Step left
+D:        Step right
+             PgUp:     Move upwards
+             PgDown:   Move downwards
+             F:        Toggle frame rate stats on/off
+			 R:        Render mode
+             T:        Cycle texture filtering
+                       Bilinear, Trilinear, Anisotropic(8)
+             P:        Toggle on/off display of camera position / orientation
+-----------------------------------------------------------------------------
+*/
+
+#ifndef __ExampleFrameListener_H__
+#define __ExampleFrameListener_H__
+
+#include "Ogre.h"
+#include "OgreStringConverter.h"
+#include "OgreException.h"
+
+//Use this define to signify OIS will be used as a DLL
+//(so that dll import/export macros are in effect)
+#ifndef OIS_DYNAMIC_LIB
+#  define OIS_DYNAMIC_LIB
+#endif
+#include <OIS/OIS.h>
+
+using namespace Ogre;
+
+class ExampleFrameListener: public FrameListener, public WindowEventListener
+{
+protected:
+	virtual void updateStats(void)
+	{
+		static String currFps = "Current FPS: ";
+		static String avgFps = "Average FPS: ";
+		static String bestFps = "Best FPS: ";
+		static String worstFps = "Worst FPS: ";
+		static String tris = "Triangle Count: ";
+		static String batches = "Batch Count: ";
+
+		// update stats when necessary
+		try {
+			OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps");
+			OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps");
+			OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps");
+			OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps");
+
+			const RenderTarget::FrameStats& stats = mWindow->getStatistics();
+			guiAvg->setCaption(avgFps + StringConverter::toString(stats.avgFPS));
+			guiCurr->setCaption(currFps + StringConverter::toString(stats.lastFPS));
+			guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS)
+				+" "+StringConverter::toString(stats.bestFrameTime)+" ms");
+			guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS)
+				+" "+StringConverter::toString(stats.worstFrameTime)+" ms");
+
+			OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris");
+			guiTris->setCaption(tris + StringConverter::toString(stats.triangleCount));
+
+			OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches");
+			guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount));
+
+			OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText");
+			guiDbg->setCaption(mDebugText);
+		}
+		catch(...) { /* ignore */ }
+	}
+
+public:
+	// Constructor takes a RenderWindow because it uses that to determine input context
+	ExampleFrameListener(RenderWindow* win, Camera* cam, bool bufferedKeys = false, bool bufferedMouse = false,
+			     bool bufferedJoy = false ) :
+		mCamera(cam), mTranslateVector(Vector3::ZERO), mCurrentSpeed(0), mWindow(win), mStatsOn(true), mNumScreenShots(0),
+		mMoveScale(0.0f), mRotScale(0.0f), mTimeUntilNextToggle(0), mFiltering(TFO_BILINEAR),
+		mAniso(1), mSceneDetailIndex(0), mMoveSpeed(100), mRotateSpeed(36), mDebugOverlay(0),
+		mInputManager(0), mMouse(0), mKeyboard(0), mJoy(0)
+	{
+
+		mDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
+
+		LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
+		OIS::ParamList pl;
+		size_t windowHnd = 0;
+		std::ostringstream windowHndStr;
+
+		win->getCustomAttribute("WINDOW", &windowHnd);
+		windowHndStr << windowHnd;
+		pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
+
+		mInputManager = OIS::InputManager::createInputSystem( pl );
+
+		//Create all devices (We only catch joystick exceptions here, as, most people have Key/Mouse)
+		mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, bufferedKeys ));
+		mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, bufferedMouse ));
+		try {
+			mJoy = static_cast<OIS::JoyStick*>(mInputManager->createInputObject( OIS::OISJoyStick, bufferedJoy ));
+		}
+		catch(...) {
+			mJoy = 0;
+		}
+
+		//Set initial mouse clipping size
+		windowResized(mWindow);
+
+		showDebugOverlay(true);
+
+		//Register as a Window listener
+		WindowEventUtilities::addWindowEventListener(mWindow, this);
+	}
+
+	//Adjust mouse clipping area
+	virtual void windowResized(RenderWindow* rw)
+	{
+		unsigned int width, height, depth;
+		int left, top;
+		rw->getMetrics(width, height, depth, left, top);
+
+		const OIS::MouseState &ms = mMouse->getMouseState();
+		ms.width = width;
+		ms.height = height;
+	}
+
+	//Unattach OIS before window shutdown (very important under Linux)
+	virtual void windowClosed(RenderWindow* rw)
+	{
+		//Only close for window that created OIS (the main window in these demos)
+		if( rw == mWindow )
+		{
+			if( mInputManager )
+			{
+				mInputManager->destroyInputObject( mMouse );
+				mInputManager->destroyInputObject( mKeyboard );
+				mInputManager->destroyInputObject( mJoy );
+
+				OIS::InputManager::destroyInputSystem(mInputManager);
+				mInputManager = 0;
+			}
+		}
+	}
+
+	virtual ~ExampleFrameListener()
+	{
+		//Remove ourself as a Window listener
+		WindowEventUtilities::removeWindowEventListener(mWindow, this);
+		windowClosed(mWindow);
+	}
+
+	virtual bool processUnbufferedKeyInput(const FrameEvent& evt)
+	{
+
+		if(mKeyboard->isKeyDown(OIS::KC_A))
+			mTranslateVector.x = -mMoveScale;	// Move camera left
+
+		if(mKeyboard->isKeyDown(OIS::KC_D))
+			mTranslateVector.x = mMoveScale;	// Move camera RIGHT
+
+		if(mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W) )
+			mTranslateVector.z = -mMoveScale;	// Move camera forward
+
+		if(mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S) )
+			mTranslateVector.z = mMoveScale;	// Move camera backward
+
+		if(mKeyboard->isKeyDown(OIS::KC_PGUP))
+			mTranslateVector.y = mMoveScale;	// Move camera up
+
+		if(mKeyboard->isKeyDown(OIS::KC_PGDOWN))
+			mTranslateVector.y = -mMoveScale;	// Move camera down
+
+		if(mKeyboard->isKeyDown(OIS::KC_RIGHT))
+			mCamera->yaw(-mRotScale);
+
+		if(mKeyboard->isKeyDown(OIS::KC_LEFT))
+			mCamera->yaw(mRotScale);
+
+		if( mKeyboard->isKeyDown(OIS::KC_ESCAPE) || mKeyboard->isKeyDown(OIS::KC_Q) )
+			return false;
+
+       	if( mKeyboard->isKeyDown(OIS::KC_F) && mTimeUntilNextToggle <= 0 )
+		{
+			mStatsOn = !mStatsOn;
+			showDebugOverlay(mStatsOn);
+			mTimeUntilNextToggle = 1;
+		}
+
+		if( mKeyboard->isKeyDown(OIS::KC_T) && mTimeUntilNextToggle <= 0 )
+		{
+			switch(mFiltering)
+			{
+			case TFO_BILINEAR:
+				mFiltering = TFO_TRILINEAR;
+				mAniso = 1;
+				break;
+			case TFO_TRILINEAR:
+				mFiltering = TFO_ANISOTROPIC;
+				mAniso = 8;
+				break;
+			case TFO_ANISOTROPIC:
+				mFiltering = TFO_BILINEAR;
+				mAniso = 1;
+				break;
+			default: break;
+			}
+			MaterialManager::getSingleton().setDefaultTextureFiltering(mFiltering);
+			MaterialManager::getSingleton().setDefaultAnisotropy(mAniso);
+
+			showDebugOverlay(mStatsOn);
+			mTimeUntilNextToggle = 1;
+		}
+
+		if(mKeyboard->isKeyDown(OIS::KC_SYSRQ) && mTimeUntilNextToggle <= 0)
+		{
+			std::ostringstream ss;
+			ss << "screenshot_" << ++mNumScreenShots << ".png";
+			mWindow->writeContentsToFile(ss.str());
+			mTimeUntilNextToggle = 0.5;
+			mDebugText = "Saved: " + ss.str();
+		}
+
+		if(mKeyboard->isKeyDown(OIS::KC_R) && mTimeUntilNextToggle <=0)
+		{
+			mSceneDetailIndex = (mSceneDetailIndex+1)%3 ;
+			switch(mSceneDetailIndex) {
+				case 0 : mCamera->setPolygonMode(PM_SOLID); break;
+				case 1 : mCamera->setPolygonMode(PM_WIREFRAME); break;
+				case 2 : mCamera->setPolygonMode(PM_POINTS); break;
+			}
+			mTimeUntilNextToggle = 0.5;
+		}
+
+		static bool displayCameraDetails = false;
+		if(mKeyboard->isKeyDown(OIS::KC_P) && mTimeUntilNextToggle <= 0)
+		{
+			displayCameraDetails = !displayCameraDetails;
+			mTimeUntilNextToggle = 0.5;
+			if (!displayCameraDetails)
+				mDebugText = "";
+		}
+
+		// Print camera details
+		if(displayCameraDetails)
+			mDebugText = "P: " + StringConverter::toString(mCamera->getDerivedPosition()) +
+						 " " + "O: " + StringConverter::toString(mCamera->getDerivedOrientation());
+
+		// Return true to continue rendering
+		return true;
+	}
+
+	virtual bool processUnbufferedMouseInput(const FrameEvent& evt)
+	{
+
+		// Rotation factors, may not be used if the second mouse button is pressed
+		// 2nd mouse button - slide, otherwise rotate
+		const OIS::MouseState &ms = mMouse->getMouseState();
+		if( ms.buttonDown( OIS::MB_Right ) )
+		{
+			mTranslateVector.x += ms.X.rel * 0.13;
+			mTranslateVector.y -= ms.Y.rel * 0.13;
+		}
+		else
+		{
+			mRotX = Degree(-ms.X.rel * 0.13);
+			mRotY = Degree(-ms.Y.rel * 0.13);
+		}
+
+		return true;
+	}
+
+	virtual void moveCamera()
+	{
+		// Make all the changes to the camera
+		// Note that YAW direction is around a fixed axis (freelook style) rather than a natural YAW
+		//(e.g. airplane)
+		mCamera->yaw(mRotX);
+		mCamera->pitch(mRotY);
+		mCamera->moveRelative(mTranslateVector);
+	}
+
+	virtual void showDebugOverlay(bool show)
+	{
+		if (mDebugOverlay)
+		{
+			if (show)
+				mDebugOverlay->show();
+			else
+				mDebugOverlay->hide();
+		}
+	}
+
+	// Override frameRenderingQueued event to process that (don't care about frameEnded)
+	bool frameRenderingQueued(const FrameEvent& evt)
+	{
+
+		if(mWindow->isClosed())	return false;
+
+		mSpeedLimit = mMoveScale * evt.timeSinceLastFrame;
+
+		//Need to capture/update each device
+		mKeyboard->capture();
+		mMouse->capture();
+		if( mJoy ) mJoy->capture();
+
+		bool buffJ = (mJoy) ? mJoy->buffered() : true;
+
+    	Ogre::Vector3 lastMotion = mTranslateVector;
+
+		//Check if one of the devices is not buffered
+		if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )
+		{
+			// one of the input modes is immediate, so setup what is needed for immediate movement
+			if (mTimeUntilNextToggle >= 0)
+				mTimeUntilNextToggle -= evt.timeSinceLastFrame;
+
+			// Move about 100 units per second
+			mMoveScale = mMoveSpeed * evt.timeSinceLastFrame;
+			// Take about 10 seconds for full rotation
+			mRotScale = mRotateSpeed * evt.timeSinceLastFrame;
+
+			mRotX = 0;
+			mRotY = 0;
+			mTranslateVector = Ogre::Vector3::ZERO;
+
+		}
+
+		//Check to see which device is not buffered, and handle it
+		if( !mKeyboard->buffered() )
+			if( processUnbufferedKeyInput(evt) == false )
+				return false;
+		if( !mMouse->buffered() )
+			if( processUnbufferedMouseInput(evt) == false )
+				return false;
+
+		// ramp up / ramp down speed
+    	if (mTranslateVector == Ogre::Vector3::ZERO)
+		{
+			// decay (one third speed)
+			mCurrentSpeed -= evt.timeSinceLastFrame * 0.3;
+			mTranslateVector = lastMotion;
+		}
+		else
+		{
+			// ramp up
+			mCurrentSpeed += evt.timeSinceLastFrame;
+
+		}
+		// Limit motion speed
+		if (mCurrentSpeed > 1.0)
+			mCurrentSpeed = 1.0;
+		if (mCurrentSpeed < 0.0)
+			mCurrentSpeed = 0.0;
+
+		mTranslateVector *= mCurrentSpeed;
+
+
+		if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )
+			moveCamera();
+
+		return true;
+	}
+
+	bool frameEnded(const FrameEvent& evt)
+	{
+		updateStats();
+		return true;
+	}
+
+protected:
+	Camera* mCamera;
+
+	Vector3 mTranslateVector;
+	Real mCurrentSpeed;
+	RenderWindow* mWindow;
+	bool mStatsOn;
+
+	std::string mDebugText;
+
+	unsigned int mNumScreenShots;
+	float mMoveScale;
+	float mSpeedLimit;
+	Degree mRotScale;
+	// just to stop toggles flipping too fast
+	Real mTimeUntilNextToggle ;
+	Radian mRotX, mRotY;
+	TextureFilterOptions mFiltering;
+	int mAniso;
+
+	int mSceneDetailIndex ;
+	Real mMoveSpeed;
+	Degree mRotateSpeed;
+	Overlay* mDebugOverlay;
+
+	//OIS Input devices
+	OIS::InputManager* mInputManager;
+	OIS::Mouse*    mMouse;
+	OIS::Keyboard* mKeyboard;
+	OIS::JoyStick* mJoy;
+};
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreFramework.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreFramework.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreFramework.cpp	(revision 11817)
@@ -0,0 +1,7002 @@
+//|||||||||||||||||||||||||||||||||||||||||||||||
+/*
+===========================================================================
+Copyright (C) 2010 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "OgreFramework.hpp"
+
+#include <io.h>
+#include <fcntl.h>      /* Needed only for _O_RDWR definition */
+#include <sys/stat.h>
+#include "Q3Map_misc.h"	// safe pointer deletes
+
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+using namespace Ogre;
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+template<> OgreFramework* Ogre::Singleton<class OgreFramework>::ms_Singleton = 0;
+
+
+
+OgreFramework::OgreFramework()
+{
+
+	m_nNewCount=0 ;
+	ZeroMemory((void*)m_nNewCheck, sizeof(m_nNewCheck)) ;
+
+	m_MoveSpeed			= 0.1;
+	m_RotateSpeed		= 0.3;
+
+	m_bShutDownOgre		= false;
+	m_iNumScreenShots	= 0;
+
+	m_pRoot				= 0;
+	m_pSceneMgr			= 0;
+	m_pRenderWnd		= 0;
+	m_pCamera			= 0;
+	m_pViewport			= 0;
+	m_pLog				= 0;
+	m_pTimer			= 0;
+
+	m_pInputMgr			= 0;
+	m_pKeyboard			= 0;
+	m_pMouse			= 0;
+
+	m_pDebugOverlay		= 0;
+	m_pInfoOverlay		= 0;
+
+	//mRawFileManager=NULL ; // pointer for text file resource handler
+	m_pRawBspFile=NULL ;
+	m_bRawBspFileIsLoaded=false ;
+
+	// pointers for q3map stuff
+	m_TempMem=NULL ;
+	m_Q3Map=NULL ;
+	
+
+	m_pZoneMO=NULL ;
+	m_pZoneMesh=NULL ;
+	m_pZoneEntity=NULL ;
+	m_pZoneEntityMaterialType=NULL ;
+
+	int nPTex=0 ;
+	for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+	{
+		m_pZoneEntityMaterial_Base[nPTex]=NULL ;
+		m_pZoneEntityMaterial_Fast[nPTex]=NULL ;
+	}
+
+	m_pZoneEntityMaterial_Black=NULL ;
+
+	m_pZoneEntityMaterial_DfShColour=NULL ;
+	m_pZoneEntityMaterial_Shadow=NULL ;
+	m_pZoneEntityMaterial_ShadeFront=NULL ;
+	m_pZoneEntityMaterial_ShadeBack=NULL ;
+	m_pZoneEntityMaterial_DfShPosition=NULL ;
+	m_pZoneEntityMaterial_DfShDiffuse=NULL ;
+	//m_pZoneEntityMaterial_DSNormal=NULL ;
+	m_pZoneEntityMaterial_DfShFuncTNB=NULL ;
+	m_pZoneEntityMaterial_DfShSpecular=NULL ;
+	m_pZoneEntityMaterial_DfShEmissive=NULL ;
+	//m_pZoneEntityMaterial_DfShData=NULL ;
+	m_pZoneEntityMaterial_DfShMix=NULL ;
+
+
+	/////////////////////////////////
+
+	m_nMaxEntity=0 ;
+	m_pEntityInfo=NULL ;
+	m_nMaxVisibleEntity=0 ;
+	m_pVisibleEntity=NULL ;
+	m_nMaxFrustumEntity=0 ;
+	m_pFrustumEntity=NULL ;
+
+
+	// debug light meshes
+	m_pLightMO=NULL ;
+	m_pPortalMO=NULL ;
+	m_pPortalNode=NULL ;
+
+	m_pCubeNode			= 0;
+	m_pCubeEntity		= 0;
+
+	nMap=2 ;
+	m_nLoadToggle=0 ;
+	m_nJumpToggle=0 ;
+	m_nJumpVal=-1 ;
+
+	
+
+
+
+	m_nDebugA=0 ;
+	m_nDebugB=0 ;
+	m_nDebugC=0 ;
+	m_nRecurseCount=0 ;
+
+
+	m_nDebugLightBox=0 ;
+	m_nZoneCullingActive=1 ;
+	
+	m_nPortalDebug=0 ;
+	m_nPortalToggle=0 ;
+	m_nPortalState=1 ;
+
+	m_nKeyDown_Shift=0 ;
+	m_nKeyDown_Ctrl=0 ;
+
+
+
+	m_flStereoFrustumTweak=0.0f ;
+
+	m_nGoggleMode=GOGGLE_MODE_OFF ;
+	m_pGoggleL=NULL ;
+	m_pGoggleR=NULL ;
+	m_pNodeGoggles=NULL ;
+
+	// default goggle settings
+	m_flGoggleZPos=-250 ;
+	m_flGoggleXGap=0.0 ;
+	m_flGoggleXScale=1.0 ;
+	m_flGoggleYScale=1.0 ;
+
+	m_nMapLoaded=0 ;
+
+	m_nTime=0 ;
+
+	
+
+	ZeroMemory((void*)m_nFrameTime, sizeof(m_nFrameTime)) ;
+	m_nFrame=0 ;
+	m_nGotInput=0 ;
+
+	ZeroMemory((void*)m_nKeyToggle, sizeof(m_nKeyToggle)) ;
+
+//	OFBug.LogInit() ;
+
+	m_nRTTAssetsExist=0 ;
+	
+	m_nToggle=0 ;
+	
+	m_nFlashLight=0 ;
+
+
+
+	m_flAspectRatio=1.0f ;
+	m_flFOV=60.0f ;
+
+	// whether we are drawing the render or one of the info screens, such as wireframe or one of the deferred screens
+	m_nDisplayInfoMode=0 ;
+
+	m_nSpeedRender=0 ;
+
+	//m_nRenderHDR=0 ;
+
+	srand( (unsigned)time( NULL ) );
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+OgreFramework::~OgreFramework()
+{
+//	OFBug.LogSave("OFBug.txt") ;
+
+	/*
+	char chMessage[1024] ;
+	int nFrame=0 ;
+	m_pLog->logMessage("   ");
+	m_pLog->logMessage("   Mircosecs:   Physics    Render    Ideal   Average    Pragma     Total");
+	m_pLog->logMessage("   ----------------------------------------");
+	for(nFrame=0 ; nFrame<MAXFRAME ; nFrame++)
+	{
+		//sprintf(chMessage, "   Frame %3i:  %8i  %8i  %8i", nFrame, m_nFrameTime[nFrame][0], m_nFrameTime[nFrame][1], m_nFrameTime[nFrame][2]) ;
+		sprintf(chMessage, "  Frame %3i:  %8i  %8i  %8i  %8i  %8i  %8i", nFrame, m_nFrameTime[nFrame][0], m_nFrameTime[nFrame][1], m_nFrameTime[nFrame][2], m_nFrameTime[nFrame][3], m_nFrameTime[nFrame][4], m_nFrameTime[nFrame][5]) ;
+		m_pLog->logMessage(chMessage);
+	}
+	m_pLog->logMessage("");
+	*/
+
+	//UnloadMap(true) ;
+
+
+	//mRawFileManager->~RawFileManager() ; //!! is this correct?  
+	//DELETE_POINTER( mRawFileManager ) ;
+
+
+	DELETE_POINTER( m_pKeyboard );
+	DELETE_POINTER( m_pMouse );
+	OIS::InputManager::destroyInputSystem(m_pInputMgr);
+
+	
+	//DELETE_POINTER( m_pRoot );
+	//delete m_pRoot ;
+}
+
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener, OIS::MouseListener *pMouseListener)
+{
+//	Ogre::LogManager* logMgr = new Ogre::LogManager();
+	
+	m_pLog = Ogre::LogManager::getSingleton().createLog("OgreLogfile.log", true, true, false);
+	m_pLog->setDebugOutputEnabled(true);
+	
+	m_pRoot = new Ogre::Root();
+
+	// our manager for the raw bsp
+	//mRawFileManager = new RawFileManager();
+	//ResourceGroupManager::getSingleton().createResourceGroup("Raw Bsp") ;
+
+	
+
+
+	m_pRoot->showConfigDialog();
+
+	if (!m_pRoot->restoreConfig() && !m_pRoot->showConfigDialog())
+	{
+		throw Exception(52, "User canceled the config dialog!", "Application::setupRenderSystem()");
+	}
+
+	
+	m_pRenderWnd = m_pRoot->initialise(true, wndTitle);
+
+	m_pSceneMgr = m_pRoot->createSceneManager(ST_GENERIC, "SceneManager");
+	m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.0, 0.0, 0.0));
+
+
+	m_pCamera = m_pSceneMgr->createCamera("Camera");
+	m_pCamera->setPosition(Vector3(0, 0, 0));
+	m_pCamera->lookAt(Vector3(0,0,0));
+	m_pCamera->setNearClipDistance(NEARCLIP);
+  m_pCamera->setFarClipDistance(FARCLIP);
+	m_pCamera->setFOVy( Degree(m_flFOV) ) ;
+
+	m_pCameraCopy = m_pSceneMgr->createCamera("CameraCopy");
+	m_pCameraCopy->setNearClipDistance(NEARCLIP);
+  m_pCameraCopy->setFarClipDistance(FARCLIP);
+
+
+	
+	m_pCameraNoJitter = m_pSceneMgr->createCamera("CameraNoJitter");
+
+
+	
+	
+
+	m_pViewport = m_pRenderWnd->addViewport(m_pCamera);
+
+	m_pViewport->setBackgroundColour(ColourValue(0.5, 0.5, 0.5, 1.0));
+
+	m_flAspectRatio= (float)m_pViewport->getActualWidth() / (float)m_pViewport->getActualHeight() ;
+
+	m_flGoggleAspectRatio=m_flAspectRatio ; // we use this to set up the Goggles
+	m_pCamera->setAspectRatio( Real(m_flAspectRatio) );
+	m_pCameraCopy->setAspectRatio(  Real(m_flAspectRatio) );
+	
+	m_pViewport->setCamera(m_pCamera);
+	m_pViewport->setClearEveryFrame(true);//, FBT_DEPTH) ;
+
+	
+
+
+	unsigned long hWnd = 0;
+    OIS::ParamList paramList;
+    m_pRenderWnd->getCustomAttribute("WINDOW", &hWnd);
+
+	paramList.insert(OIS::ParamList::value_type("WINDOW", Ogre::StringConverter::toString(hWnd)));
+
+	m_pInputMgr = OIS::InputManager::createInputSystem(paramList);
+
+  m_pKeyboard = static_cast<OIS::Keyboard*>(m_pInputMgr->createInputObject(OIS::OISKeyboard, true));
+	m_pMouse = static_cast<OIS::Mouse*>(m_pInputMgr->createInputObject(OIS::OISMouse, true));
+
+    
+	m_pMouse->getMouseState().height = m_pRenderWnd->getHeight();
+	m_pMouse->getMouseState().width	 = m_pRenderWnd->getWidth();
+
+	if(pKeyListener == 0)
+		m_pKeyboard->setEventCallback(this);
+	else
+		m_pKeyboard->setEventCallback(pKeyListener);
+
+	if(pMouseListener == 0)
+		m_pMouse->setEventCallback(this);
+	else
+		m_pMouse->setEventCallback(pMouseListener);
+
+	SetupResourceLocations() ;
+
+	// D3D or OGL
+	if (Root::getSingleton().getRenderSystem()->getName().find("GL") != String::npos)
+		m_IsOpenGL = true;
+	else
+		m_IsOpenGL = false;
+
+
+
+
+
+	m_pTimer = new Ogre::Timer();
+	m_pTimer->reset();
+	
+
+	
+
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
+	
+
+	
+
+	
+
+	m_nRTTWidth = m_pRenderWnd->getWidth() ;
+	m_nRTTHeight = m_pRenderWnd->getHeight() ;
+	
+
+	m_pRenderWnd->addListener(this);
+	m_pRenderWnd->setActive(true);
+
+
+	// default values, may be changed from the bzn.cfg file
+	m_nShadowMapSize=512 ;
+	m_nShadowRGBSize=512 ;
+	m_nColouredShadow=1 ;
+	m_nRenderHDR=1 ;
+	m_nMaxGPUQuery=1 ;
+	
+}
+
+void OgreFramework::FinalShutdown(void)
+{
+
+	//Ogre::ResourceGroupManager::getSingleton().shutdownAll();
+	//m_pRoot->destroySceneManager(m_pSceneMgr);
+	//m_pRoot->shutdown() ;
+	delete m_pRoot ;
+}
+
+void OgreFramework::AdditionalSetup()
+{
+
+	CreateRTTAssets() ;
+}
+
+
+void OgreFramework::SetupResourceLocations()
+{
+	Ogre::String secName, typeName, archName;
+	Ogre::ConfigFile cf;
+    cf.load("resources.cfg");
+
+	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();
+    while (seci.hasMoreElements())
+    {
+        secName = seci.peekNextKey();
+		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
+        Ogre::ConfigFile::SettingsMultiMap::iterator i;
+        for (i = settings->begin(); i != settings->end(); ++i)
+        {
+            typeName = i->first;
+            archName = i->second;
+            Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
+        }
+    }
+	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
+}
+
+
+// create the textures, materials and miniscreens needed for the RTTs
+void OgreFramework::CreateRTTAssets()
+{
+	
+
+	// I originally had problems with OpenGL 2.1.1 suddenly running very slow if I had more than 12 RTT surfaces
+	// but that issue seems to have vanished, perhaps because all my surfaces are now FLOAT16_RGB or FLOAT16_RGBA.
+	// It doesn't like FLOAT32 surfaces, and it also didn't seem to like mixing R8G8B8 with FLOAT16, at least
+	// those configurations seem to have been problems in the past, so I try to keep everything FLOAT16_RGB where possible.
+
+	// I go through quite a few RTT surfaces, and I don't use MRT since I couldn't get it working.
+
+	MaterialManager::getSingleton().initialise() ;
+
+	// need our own resource group so that the RTTs dont get destroyed when we load a new level.
+	Ogre::ResourceGroupManager::getSingleton().createResourceGroup("RTTResources") ;
+
+	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();	
+
+	int RTTWidth = m_nRTTWidth ;//m_pRenderWnd->getWidth() ;
+	int RTTHeight = m_nRTTHeight ; //m_pRenderWnd->getHeight() ;
+
+	int DSWidth = m_nRTTWidth ;
+	int DSHeight = m_nRTTHeight ;
+
+	int DSWidthB = m_nSpeedRender ? m_nRTTWidth/2 : m_nRTTWidth ;
+	int DSHeightB = m_nSpeedRender ? m_nRTTHeight/2 : m_nRTTHeight ;
+
+	int TEMPWidth = m_nRTTWidth ;
+	int TEMPHeight = m_nRTTHeight ;
+
+
+	Ogre::ColourValue ClearColour=Ogre::ColourValue(0,0,0,1) ; // clears alpha as well. for RGBA textures 
+	//!! for now use alpha 1, since Ogre seems to force it to 1 anyway on shadow render.
+
+
+	
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// Shadow
+	
+	RTT_Texture_Shadow = Ogre::TextureManager::getSingleton().createManual("RttTex_Shadow",
+      "RTTResources", TEX_TYPE_2D, m_nShadowMapSize, m_nShadowMapSize, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_Shadow = RTT_Texture_Shadow->getBuffer()->getRenderTarget();
+	renderTexture_Shadow->addViewport(m_pCamera);
+	renderTexture_Shadow->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_Shadow->getViewport(0)->setBackgroundColour(ColourValue::White);
+	renderTexture_Shadow->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_Shadow = MaterialManager::getSingleton().create("RttMat_Shadow", "RTTResources");
+	RTT_Technique_Shadow = RTT_Mat_Shadow->createTechnique();
+	RTT_Technique_Shadow->createPass();
+	TextureUnitState* tState_Shadow = RTT_Mat_Shadow->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_Shadow");
+	tState_Shadow->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_Shadow->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_Shadow->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+	miniScreen_Shadow = new Ogre::Rectangle2D(true);
+	miniScreen_Shadow->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_Shadow->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_Shadow = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_Shadow");
+	miniScreenNode_Shadow->attachObject(miniScreen_Shadow);
+	miniScreen_Shadow->setMaterial("RttMat_Shadow");
+
+
+	if(m_nColouredShadow)
+	{
+		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		// ShadeFront
+		
+		RTT_Texture_ShadeFront = Ogre::TextureManager::getSingleton().createManual("RttTex_ShadeFront",
+				"RTTResources", TEX_TYPE_2D, m_nShadowRGBSize, m_nShadowRGBSize, 0, PF_FLOAT16_RGBA,
+				TU_RENDERTARGET);
+
+		
+		renderTexture_ShadeFront = RTT_Texture_ShadeFront->getBuffer()->getRenderTarget();
+		renderTexture_ShadeFront->addViewport(m_pCamera);
+		renderTexture_ShadeFront->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
+		renderTexture_ShadeFront->getViewport(0)->setBackgroundColour(ColourValue::White);
+		renderTexture_ShadeFront->getViewport(0)->setOverlaysEnabled(false);
+
+		RTT_Mat_ShadeFront = MaterialManager::getSingleton().create("RttMat_ShadeFront", "RTTResources");
+		RTT_Technique_ShadeFront = RTT_Mat_ShadeFront->createTechnique();
+		RTT_Technique_ShadeFront->createPass();
+		TextureUnitState* tState_ShadeFront = RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_ShadeFront");
+		tState_ShadeFront->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+		RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+		RTT_Mat_ShadeFront->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+		
+		miniScreen_ShadeFront = new Ogre::Rectangle2D(true);
+		miniScreen_ShadeFront->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+		miniScreen_ShadeFront->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+		miniScreenNode_ShadeFront = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_ShadeFront");
+		miniScreenNode_ShadeFront->attachObject(miniScreen_ShadeFront);
+		miniScreen_ShadeFront->setMaterial("RttMat_ShadeFront");
+		
+		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		// ShadeBack
+		
+		RTT_Texture_ShadeBack = Ogre::TextureManager::getSingleton().createManual("RttTex_ShadeBack",
+				"RTTResources", TEX_TYPE_2D, m_nShadowRGBSize, m_nShadowRGBSize, 0, PF_FLOAT16_RGBA,
+				TU_RENDERTARGET);
+
+		
+		renderTexture_ShadeBack = RTT_Texture_ShadeBack->getBuffer()->getRenderTarget();
+		renderTexture_ShadeBack->addViewport(m_pCamera);
+		renderTexture_ShadeBack->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH);
+		renderTexture_ShadeBack->getViewport(0)->setBackgroundColour(ColourValue::White);
+		renderTexture_ShadeBack->getViewport(0)->setOverlaysEnabled(false);
+
+		RTT_Mat_ShadeBack = MaterialManager::getSingleton().create("RttMat_ShadeBack", "RTTResources");
+		RTT_Technique_ShadeBack = RTT_Mat_ShadeBack->createTechnique();
+		RTT_Technique_ShadeBack->createPass();
+		TextureUnitState* tState_ShadeBack = RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_ShadeBack");
+		tState_ShadeBack->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+		RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+		RTT_Mat_ShadeBack->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+		
+		miniScreen_ShadeBack = new Ogre::Rectangle2D(true);
+		miniScreen_ShadeBack->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+		miniScreen_ShadeBack->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+		miniScreenNode_ShadeBack = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_ShadeBack");
+		miniScreenNode_ShadeBack->attachObject(miniScreen_ShadeBack);
+		miniScreen_ShadeBack->setMaterial("RttMat_ShadeBack");
+	
+	} // end if coloured shadows
+	
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShPosition
+	
+	RTT_Texture_DfShPosition = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShPosition",
+      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DfShPosition = RTT_Texture_DfShPosition->getBuffer()->getRenderTarget();
+	renderTexture_DfShPosition->addViewport(m_pCamera);
+	renderTexture_DfShPosition->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_DfShPosition->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShPosition->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShPosition = MaterialManager::getSingleton().create("RttMat_DfShPosition", "RTTResources");
+	RTT_Technique_DfShPosition = RTT_Mat_DfShPosition->createTechnique();
+	RTT_Technique_DfShPosition->createPass();
+	TextureUnitState* tState_DfShPosition = RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShPosition");
+	tState_DfShPosition->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DfShPosition->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+	
+	//renderTexture_DfShPosition->addListener(this);
+
+	miniScreen_DfShPosition = new Ogre::Rectangle2D(true);
+	miniScreen_DfShPosition->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShPosition->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShPosition = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShPosition");
+	miniScreenNode_DfShPosition->attachObject(miniScreen_DfShPosition);
+	miniScreen_DfShPosition->setMaterial("RttMat_DfShPosition");
+	
+	
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShDiffuse
+	
+	RTT_Texture_DfShDiffuse = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShDiffuse",
+      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DfShDiffuse = RTT_Texture_DfShDiffuse->getBuffer()->getRenderTarget();
+	renderTexture_DfShDiffuse->addViewport(m_pCamera);
+	renderTexture_DfShDiffuse->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_DfShDiffuse->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShDiffuse->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShDiffuse = MaterialManager::getSingleton().create("RttMat_DfShDiffuse", "RTTResources");
+	RTT_Technique_DfShDiffuse = RTT_Mat_DfShDiffuse->createTechnique();
+	RTT_Technique_DfShDiffuse->createPass();
+	TextureUnitState* tState_DfShDiffuse = RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShDiffuse");
+	tState_DfShDiffuse->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DfShDiffuse->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+	
+	//renderTexture_DfShDiffuse->addListener(this);
+
+	miniScreen_DfShDiffuse = new Ogre::Rectangle2D(true);
+	miniScreen_DfShDiffuse->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShDiffuse->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShDiffuse = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShDiffuse");
+	miniScreenNode_DfShDiffuse->attachObject(miniScreen_DfShDiffuse);
+	miniScreen_DfShDiffuse->setMaterial("RttMat_DfShDiffuse");
+
+	/*
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DSNormal
+	
+	RTT_Texture_DSNormal = Ogre::TextureManager::getSingleton().createManual("RttTex_DSNormal",
+      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DSNormal = RTT_Texture_DSNormal->getBuffer()->getRenderTarget();
+	renderTexture_DSNormal->addViewport(m_pCamera);
+	renderTexture_DSNormal->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_DSNormal->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DSNormal->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DSNormal = MaterialManager::getSingleton().create("RttMat_DSNormal", "RTTResources");
+	RTT_Technique_DSNormal = RTT_Mat_DSNormal->createTechnique();
+	RTT_Technique_DSNormal->createPass();
+	TextureUnitState* tState_DSNormal = RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DSNormal");
+	tState_DSNormal->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DSNormal->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+	
+	
+	//renderTexture_DSNormal->addListener(this);
+
+	miniScreen_DSNormal = new Ogre::Rectangle2D(true);
+	miniScreen_DSNormal->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DSNormal->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DSNormal = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DSNormal");
+	miniScreenNode_DSNormal->attachObject(miniScreen_DSNormal);
+	miniScreen_DSNormal->setMaterial("RttMat_DSNormal");
+	
+	*/
+
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShFuncTNB
+
+	RTT_Texture_DfShFuncTNB = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShFuncTNB",
+      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DfShFuncTNB = RTT_Texture_DfShFuncTNB->getBuffer()->getRenderTarget();
+	renderTexture_DfShFuncTNB->addViewport(m_pCamera);
+	renderTexture_DfShFuncTNB->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_DfShFuncTNB->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShFuncTNB->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShFuncTNB = MaterialManager::getSingleton().create("RttMat_DfShFuncTNB", "RTTResources");
+	RTT_Technique_DfShFuncTNB = RTT_Mat_DfShFuncTNB->createTechnique();
+	RTT_Technique_DfShFuncTNB->createPass();
+	TextureUnitState* tState_DfShFuncTNB = RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShFuncTNB");
+	tState_DfShFuncTNB->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DfShFuncTNB->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+	//renderTexture_DfShFuncTNB->addListener(this);
+
+	miniScreen_DfShFuncTNB = new Ogre::Rectangle2D(true);
+	miniScreen_DfShFuncTNB->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShFuncTNB->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShFuncTNB = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShFuncTNB");
+	miniScreenNode_DfShFuncTNB->attachObject(miniScreen_DfShFuncTNB);
+	miniScreen_DfShFuncTNB->setMaterial("RttMat_DfShFuncTNB");
+
+	
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShSpecular
+
+	RTT_Texture_DfShSpecular = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShSpecular",
+      "RTTResources", TEX_TYPE_2D, DSWidthB, DSHeightB, 0, PF_FLOAT16_RGBA,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DfShSpecular = RTT_Texture_DfShSpecular->getBuffer()->getRenderTarget();
+	renderTexture_DfShSpecular->addViewport(m_pCamera);
+	renderTexture_DfShSpecular->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_DfShSpecular->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShSpecular->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShSpecular = MaterialManager::getSingleton().create("RttMat_DfShSpecular", "RTTResources");
+	RTT_Technique_DfShSpecular = RTT_Mat_DfShSpecular->createTechnique();
+	RTT_Technique_DfShSpecular->createPass();
+	TextureUnitState* tState_DfShSpecular = RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShSpecular");
+	tState_DfShSpecular->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	if(m_nSpeedRender)
+		RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+	else
+		RTT_Mat_DfShSpecular->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+
+	//renderTexture_DfShSpecular->addListener(this);
+
+	miniScreen_DfShSpecular = new Ogre::Rectangle2D(true);
+	miniScreen_DfShSpecular->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShSpecular->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShSpecular = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShSpecular");
+	miniScreenNode_DfShSpecular->attachObject(miniScreen_DfShSpecular);
+	miniScreen_DfShSpecular->setMaterial("RttMat_DfShSpecular");
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShEmissive
+
+	RTT_Texture_DfShEmissive = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShEmissive",
+      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DfShEmissive = RTT_Texture_DfShEmissive->getBuffer()->getRenderTarget();
+	renderTexture_DfShEmissive->addViewport(m_pCamera);
+	renderTexture_DfShEmissive->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH);
+	renderTexture_DfShEmissive->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShEmissive->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShEmissive = MaterialManager::getSingleton().create("RttMat_DfShEmissive", "RTTResources");
+	RTT_Technique_DfShEmissive = RTT_Mat_DfShEmissive->createTechnique();
+	RTT_Technique_DfShEmissive->createPass();
+	TextureUnitState* tState_DfShEmissive = RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShEmissive");
+	tState_DfShEmissive->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	if(m_nSpeedRender)
+		RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+	else
+		RTT_Mat_DfShEmissive->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	
+
+	//renderTexture_DfShEmissive->addListener(this);
+
+	miniScreen_DfShEmissive = new Ogre::Rectangle2D(true);
+	miniScreen_DfShEmissive->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShEmissive->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShEmissive = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShEmissive");
+	miniScreenNode_DfShEmissive->attachObject(miniScreen_DfShEmissive);
+	miniScreen_DfShEmissive->setMaterial("RttMat_DfShEmissive");
+
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShLamp
+
+	RTT_Texture_DfShLamp = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShLamp",
+      "RTTResources", TEX_TYPE_2D, DSWidth, DSHeight, 0, PF_FLOAT16_RGB, 
+      TU_RENDERTARGET);//, 0, false, 6);
+	
+	renderTexture_DfShLamp = RTT_Texture_DfShLamp->getBuffer()->getRenderTarget();
+	renderTexture_DfShLamp->addViewport(m_pCamera);
+	renderTexture_DfShLamp->getViewport(0)->setClearEveryFrame(true);//, FBT_DEPTH); 
+	renderTexture_DfShLamp->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShLamp->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShLamp = MaterialManager::getSingleton().create("RttMat_DfShLamp", "RTTResources");
+	RTT_Technique_DfShLamp = RTT_Mat_DfShLamp->createTechnique();
+	RTT_Technique_DfShLamp->createPass();
+	TextureUnitState* tState_DfShLamp = RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShLamp");
+	tState_DfShLamp->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DfShLamp->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	//renderTexture_DfShLamp->addListener(this);
+
+	miniScreen_DfShLamp = new Ogre::Rectangle2D(true);
+	miniScreen_DfShLamp->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShLamp->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShLamp = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShLamp");
+	miniScreenNode_DfShLamp->attachObject(miniScreen_DfShLamp);
+	miniScreen_DfShLamp->setMaterial("RttMat_DfShLamp");
+	
+	
+
+	/*
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShData
+
+	RTT_Texture_DfShData = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShData",
+      "RTTResources", TEX_TYPE_2D, DSWidthB, DSHeightB, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+	
+	renderTexture_DfShData = RTT_Texture_DfShData->getBuffer()->getRenderTarget();
+	renderTexture_DfShData->addViewport(m_pCamera);
+	renderTexture_DfShData->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH); 
+	renderTexture_DfShData->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShData->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShData = MaterialManager::getSingleton().create("RttMat_DfShData", "RTTResources");
+	RTT_Technique_DfShData = RTT_Mat_DfShData->createTechnique();
+	RTT_Technique_DfShData->createPass();
+	TextureUnitState* tState_DfShData = RTT_Mat_DfShData->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShData");
+	tState_DfShData->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	if(m_nSpeedRender)
+		RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+	else
+		RTT_Mat_DfShData->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	//renderTexture_DfShData->addListener(this);
+
+	miniScreen_DfShData = new Ogre::Rectangle2D(true);
+	miniScreen_DfShData->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShData->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShData = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShData");
+	miniScreenNode_DfShData->attachObject(miniScreen_DfShData);
+	miniScreen_DfShData->setMaterial("RttMat_DfShData");
+	
+	*/
+
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShTemp
+
+	RTT_Texture_DfShTemp = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShTemp",
+      "RTTResources", TEX_TYPE_2D, TEMPWidth, TEMPHeight, 0, PF_FLOAT16_RGB, 
+      TU_RENDERTARGET);//, 0, false, 6);
+	
+	renderTexture_DfShTemp = RTT_Texture_DfShTemp->getBuffer()->getRenderTarget();
+	renderTexture_DfShTemp->addViewport(m_pCamera);
+	renderTexture_DfShTemp->getViewport(0)->setClearEveryFrame(true, FBT_DEPTH); 
+	renderTexture_DfShTemp->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShTemp->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShTemp = MaterialManager::getSingleton().create("RttMat_DfShTemp", "RTTResources");
+	RTT_Technique_DfShTemp = RTT_Mat_DfShTemp->createTechnique();
+	RTT_Technique_DfShTemp->createPass();
+	TextureUnitState* tState_DfShTemp = RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShTemp");
+	tState_DfShTemp->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DfShTemp->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+	//renderTexture_DfShTemp->addListener(this);
+
+	miniScreen_DfShTemp = new Ogre::Rectangle2D(true);
+	miniScreen_DfShTemp->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShTemp->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShTemp = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShTemp");
+	miniScreenNode_DfShTemp->attachObject(miniScreen_DfShTemp);
+	miniScreen_DfShTemp->setMaterial("RttMat_DfShTemp");
+
+
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// DfShMix
+
+		RTT_Texture_DfShMix = Ogre::TextureManager::getSingleton().createManual("RttTex_DfShMix",
+      "RTTResources", TEX_TYPE_2D, RTTWidth, RTTHeight, 0, PF_FLOAT16_RGB,
+      TU_RENDERTARGET);
+
+	
+	renderTexture_DfShMix = RTT_Texture_DfShMix->getBuffer()->getRenderTarget();
+	renderTexture_DfShMix->addViewport(m_pCamera);
+	renderTexture_DfShMix->getViewport(0)->setClearEveryFrame(false);//, FBT_DEPTH);
+	renderTexture_DfShMix->getViewport(0)->setBackgroundColour(ColourValue::Black);
+	renderTexture_DfShMix->getViewport(0)->setOverlaysEnabled(false);
+
+	RTT_Mat_DfShMix = MaterialManager::getSingleton().create("RttMat_DfShMix", "RTTResources");
+	RTT_Technique_DfShMix = RTT_Mat_DfShMix->createTechnique();
+	RTT_Technique_DfShMix->createPass();
+	TextureUnitState* tState_DfShMix = RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_DfShMix");
+	tState_DfShMix->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+	RTT_Mat_DfShMix->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_NONE) ;
+
+
+	miniScreen_DfShMix = new Ogre::Rectangle2D(true);
+	miniScreen_DfShMix->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShMix->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShMix = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShMix");
+	miniScreenNode_DfShMix->attachObject(miniScreen_DfShMix);
+	miniScreen_DfShMix->setMaterial("RttMat_DfShMix");
+	
+	if(m_nRenderHDR)
+	{
+
+		
+		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		// BlurA
+		
+		RTT_Texture_BlurA = Ogre::TextureManager::getSingleton().createManual("RttTex_BlurA",
+				"RTTResources", TEX_TYPE_2D, DSWidth/2, DSHeight/2, 0, PF_FLOAT16_RGB,
+				TU_RENDERTARGET);
+		
+		renderTexture_BlurA = RTT_Texture_BlurA->getBuffer()->getRenderTarget();
+		renderTexture_BlurA->addViewport(m_pCamera);
+		renderTexture_BlurA->getViewport(0)->setClearEveryFrame(false);
+		renderTexture_BlurA->getViewport(0)->setBackgroundColour(ColourValue::Black);
+		renderTexture_BlurA->getViewport(0)->setOverlaysEnabled(false);
+
+		RTT_Mat_BlurA = MaterialManager::getSingleton().create("RttMat_BlurA", "RTTResources");
+		RTT_Technique_BlurA = RTT_Mat_BlurA->createTechnique();
+		RTT_Technique_BlurA->createPass();
+		TextureUnitState* tState_BlurA = RTT_Mat_BlurA->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_BlurA");
+		tState_BlurA->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+		RTT_Mat_BlurA->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+		RTT_Mat_BlurA->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+
+		miniScreen_BlurA = new Ogre::Rectangle2D(true);
+		miniScreen_BlurA->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+		miniScreen_BlurA->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+		miniScreenNode_BlurA = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_BlurA");
+		miniScreenNode_BlurA->attachObject(miniScreen_BlurA);
+		miniScreen_BlurA->setMaterial("RttMat_BlurA");
+
+		//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		// BlurB
+		
+		RTT_Texture_BlurB = Ogre::TextureManager::getSingleton().createManual("RttTex_BlurB",
+				"RTTResources", TEX_TYPE_2D, DSWidth/2, DSHeight/2, 0, PF_FLOAT16_RGB,
+				TU_RENDERTARGET);
+		
+		renderTexture_BlurB = RTT_Texture_BlurB->getBuffer()->getRenderTarget();
+		renderTexture_BlurB->addViewport(m_pCamera);
+		renderTexture_BlurB->getViewport(0)->setClearEveryFrame(false);
+		renderTexture_BlurB->getViewport(0)->setBackgroundColour(ColourValue::Black);
+		renderTexture_BlurB->getViewport(0)->setOverlaysEnabled(false);
+
+		RTT_Mat_BlurB = MaterialManager::getSingleton().create("RttMat_BlurB", "RTTResources");
+		RTT_Technique_BlurB = RTT_Mat_BlurB->createTechnique();
+		RTT_Technique_BlurB->createPass();
+		TextureUnitState* tState_BlurB = RTT_Mat_BlurB->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex_BlurB");
+		tState_BlurB->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+		RTT_Mat_BlurB->getTechnique(0)->getPass(0)->setLightingEnabled(false);
+		RTT_Mat_BlurB->getTechnique(0)->getPass(0)->setTextureFiltering(TFO_BILINEAR) ;
+
+		miniScreen_BlurB = new Ogre::Rectangle2D(true);
+		miniScreen_BlurB->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+		miniScreen_BlurB->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+		miniScreenNode_BlurB = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_BlurB");
+		miniScreenNode_BlurB->attachObject(miniScreen_BlurB);
+		miniScreen_BlurB->setMaterial("RttMat_BlurB");
+		
+	} // end if m_nRenderHDR	
+	
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// mixing quad
+	miniScreen_DfShMaster = new Ogre::Rectangle2D(true);
+	miniScreen_DfShMaster->setCorners(-1.0001, 1.0001, 1.0, -1.0);
+	miniScreen_DfShMaster->setBoundingBox(AxisAlignedBox(-100000.0*Vector3::UNIT_SCALE, 100000.0*Vector3::UNIT_SCALE)); 
+	miniScreenNode_DfShMaster = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MiniScreenNode_DfShMaster");
+	miniScreenNode_DfShMaster->attachObject(miniScreen_DfShMaster);
+	//miniScreen_DfShMaster->setMaterial("RttMat_DfShDiffuse") ;
+	//miniScreen_DfShMaster->setMaterial("DfShMix") ; // doesn't matter what material we use, since we mix from pre-rendered textures
+	
+	//RTT_Mat_Shadow->getTechnique(0)->getPass(0)->getTextureUnitState("RttTex_Shadow")->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP) ;
+	
+}
+
+void OgreFramework::DestroyRTTAssets()
+{
+}
+
+void OgreFramework::UpdateRenderTargets()
+{
+
+	int nZoneList=0 ;
+	int nZone=0 ;
+	Ogre::Entity*	pEntity=NULL ;
+	int nMO=0 ;
+	int nZGStart=0 ;
+	int nZGEnd=0 ;
+
+	int nVisEnt=0 ;
+	int nEntity=0 ;
+//	int nMaxEntity=0 ;
+	int nSubMesh=0 ;
+	int nMaxSubMesh=0 ;
+
+	int nMaxVisibleZone=*m_pGlobal_MaxVisibleZone ;
+
+	SetAllLightsOff() ;
+
+	
+	// extra texture params
+	// TexParam.x is 1 for d3d, -1 for ogl, needed for screen space UV calculations y flip
+	// TexParam.y is game time, in 1/10th of a second since start of level
+
+	Ogre::Vector4 TexParam ;
+	if(m_IsOpenGL) 
+		TexParam.x=-1 ; 
+	else 
+		TexParam.x= 1 ;
+	TexParam.y=m_GameTime/100 ;
+	TexParam.z=512.0f ; // pixelnoise subdivisions for the emmissive data function.
+
+
+	// remove all the nodes, so we start with a clean slate
+	m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+	
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// 
+	// deferred shading data textures
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
+
+	// attach the entity masternode, update positions and orientations
+	for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+	{
+		nEntity=m_pFrustumEntity[nVisEnt] ;
+		m_pEntityInfo[ nEntity ].pMasterNode->setPosition( m_pEntityInfo[nEntity].Postition ) ; // set position.
+		m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
+	}
+
+
+	
+	
+	/////////////////////////////////////////////////////////////////////
+	// DfShPosition
+	
+	// change material
+	for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+	{
+		nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+		nZGStart	=	m_nZoneMOStart[nZone] ;
+		nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+		for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+			{
+				pEntity=m_pZoneEntity[nMO] ;
+				pEntity->setMaterial( m_pZoneEntityMaterial_DfShPosition[nMO] ) ;
+			}// end for entities
+
+	}// end for zonelist
+
+
+	// first time we set materials we need to set non-opaque to the be invisible.  After we don't need to do it, they'll already be invisible
+	// Set the entity material
+
+	for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+	{
+		nEntity=m_pFrustumEntity[nVisEnt] ;
+		nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+		for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+			{
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShPosition[nSubMesh] ) ;
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ; // first time around, make sure it is visible
+			}
+			else
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ;
+	}
+
+
+
+	renderTexture_DfShPosition->update(true) ;
+	
+	/////////////////////////////////////////////////////////////////////
+	// DfShFuncTNB
+
+	// change material
+	for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+	{
+		nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+		nZGStart	=	m_nZoneMOStart[nZone] ;
+		nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+		for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+			{
+				pEntity=m_pZoneEntity[nMO] ;
+				pEntity->setMaterial( m_pZoneEntityMaterial_DfShFuncTNB[nMO] ) ;
+			}// end for entities
+
+	}// end for zonelist
+
+	for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+	{
+		nEntity=m_pFrustumEntity[nVisEnt] ;
+		nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+		for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShFuncTNB[nSubMesh] ) ;
+	}
+
+
+	renderTexture_DfShFuncTNB->update(true) ;
+	
+	
+	/////////////////////////////////////////////////////////////////////
+	// DfShDiffuse
+	
+	// the diffuse pass is used for the wireframe render as well
+
+
+
+	if(m_nDisplayInfoMode!=1)
+	{
+		// change material
+		for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+		{
+			nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+			nZGStart	=	m_nZoneMOStart[nZone] ;
+			nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+				
+			for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+				if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+				{
+					pEntity=m_pZoneEntity[nMO] ;
+					pEntity->setMaterial( m_pZoneEntityMaterial_DfShDiffuse[nMO] ) ;
+				}// end for entities
+
+		}// end for zonelist
+
+		// set the entity material
+
+		for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+		{
+			nEntity=m_pFrustumEntity[nVisEnt] ;
+			nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+			for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+				if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+					m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShDiffuse[nSubMesh] ) ;
+		}
+
+
+		renderTexture_DfShDiffuse->update(true) ;
+	}
+	else // if we are doing wireframe we use this pass for it
+	{
+		// add gels just for the wireframe
+		SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;	
+
+
+		// clear the RTT texture, since our wireframe won't clear it.
+		m_pRoot->getRenderSystem()->_setViewport(renderTexture_DfShDiffuse->getViewport(0)) ;
+		m_pRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR|FBT_DEPTH, Ogre::ColourValue(0,0,0,1)) ;
+		
+		// set the camera to wireframe mode
+		m_pCamera->setPolygonMode(PM_WIREFRAME);
+
+		// change material
+		for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+		{
+			nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+			nZGStart	=	m_nZoneMOStart[nZone] ;
+			nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+				
+			for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+				if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+				{
+					pEntity=m_pZoneEntity[nMO] ;
+					pEntity->setMaterial( MaterialManager::getSingleton().getByName("White") ) ;
+				}// end for entities
+
+		}// end for zonelist
+
+		for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+		{
+			nEntity=m_pFrustumEntity[nVisEnt] ;
+			nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+			for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			{
+				if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_OPAQUE) // any non-opaque submeshes need to be made visible
+					m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial(MaterialManager::getSingleton().getByName("White") ) ;
+			}
+		}
+
+		renderTexture_DfShDiffuse->update(true) ;
+	
+		// reset back to pre-wireframe setup
+		m_pCamera->setPolygonMode(PM_SOLID);
+
+		// remove everything and then add back OPAQUE
+		m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+		SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ;
+
+
+		// reattach entities, make non-opaque subentities invisible
+		for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+		{
+			nEntity=m_pFrustumEntity[nVisEnt] ;
+			nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+			m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[  nEntity  ].pMasterNode) ;
+
+			for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			{
+				if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_OPAQUE) 
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ;
+			}
+		}
+
+
+
+	}
+
+	
+	
+	/////////////////////////////////////////////////////////////////////
+	// DfShSpecular
+
+	// change material
+	for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+	{
+		nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+		nZGStart	=	m_nZoneMOStart[nZone] ;
+		nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+		for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+			{
+				pEntity=m_pZoneEntity[nMO] ;
+				pEntity->setMaterial( m_pZoneEntityMaterial_DfShSpecular[nMO] ) ;
+			}// end for entities
+
+	}// end for zonelist
+
+	for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+	{
+		nEntity=m_pFrustumEntity[nVisEnt] ;
+		nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+		// set the entity material
+		for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh] ) ;
+	}
+
+	renderTexture_DfShSpecular->update(true) ;
+	
+	/*
+	/////////////////////////////////////////////////////////////////////
+	// DfShData
+
+	// change material
+	for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+	{
+		nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+		nZGStart	=	m_nZoneMOStart[nZone] ;
+		nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+		for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+			{
+				pEntity=m_pZoneEntity[nMO] ;
+				pEntity->setMaterial( m_pZoneEntityMaterial_DfShData[nMO] ) ;
+			}// end for entities
+
+	}// end for zonelist
+
+	renderTexture_DfShData->update(true) ;
+	*/
+
+	
+	/////////////////////////////////////////////////////////////////////
+	// DfShEmissive
+
+	// we add the glow entities for this pass, if we are doing HDR
+	if(m_nRenderHDR)
+		SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GLOW) ;
+
+
+	// change material
+	for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+	{
+		nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+		nZGStart	=	m_nZoneMOStart[nZone] ;
+		nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+		for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GLOW))
+			{
+				pEntity=m_pZoneEntity[nMO] ;
+				pEntity->setMaterial( m_pZoneEntityMaterial_DfShEmissive[nMO] ) ;
+
+				TexParam.z=512.0f ; // pixelnoise subdivisions for the emmissive data function.
+				pEntity->getSubEntity(0)->setCustomParameter(4, TexParam) ; // emissive makes use of gametime for some lighting effects
+			}// end for entities
+
+	}// end for zonelist
+
+	// set the entity material
+	for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+	{
+		nEntity=m_pFrustumEntity[nVisEnt] ;
+		nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+		for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW))
+			{
+				// make glow stuff visible
+				if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW)
+					m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShEmissive[nSubMesh] ) ;
+			}
+	}
+
+	renderTexture_DfShEmissive->update(true) ;
+
+	
+
+	////////////////////////////////////////////////////////////////////
+	// we need to know how to colour stuff if we're seeing it through gel
+	// this colouring will be applied when we mix lamp and emmissive down to DfShMix
+	//
+	// Note that this leaves the light/lamp glow entities attached in HDR mode,
+	// we need them to block the gels otherwise the blur on the lights/lamps 
+	// comes out incorrectly coloured by gel that should be behind it. 
+
+	// add the transparent stuff
+	SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ;
+
+	// change material
+	for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+	{
+		nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+		nZGStart	=	m_nZoneMOStart[nZone] ;
+		nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+		for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL) || (m_pZoneEntityMaterialType[nMO]==MAT_GLOW))
+			{
+				pEntity=m_pZoneEntity[nMO] ;
+				pEntity->setMaterial( m_pZoneEntityMaterial_DfShColour[nMO] ) ;
+			}// end for entities
+
+
+	}// end for zonelist
+
+	for(nVisEnt=0 ; nVisEnt<m_nMaxFrustumEntity ; nVisEnt++)
+	{
+		nEntity=m_pFrustumEntity[nVisEnt] ;
+		nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+		// set the entity material
+		for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+			if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW))
+			{
+				// make gel stuff visible (glow was already made visible on the emissive pass)
+				if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL)
+					m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+				m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_DfShColour[nSubMesh] ) ;
+			}
+	}
+
+	// render colour to the temp surface
+	renderTexture_DfShTemp->update(true) ;
+
+	
+
+	//clear the mix buffer once
+	m_pRoot->getRenderSystem()->_setViewport(renderTexture_DfShMix->getViewport(0)) ;
+	m_pRoot->getRenderSystem()->clearFrameBuffer(FBT_COLOUR|FBT_DEPTH, Ogre::ColourValue(0,0,0,1)) ;
+
+	// remove all the nodes
+	m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// 
+	// deferred shading non-shadowing point lights
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+	if(true)
+	{
+		SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_LAMP) ; // attach the lamp boxes
+
+		// this renders our deferred shader lamps
+		renderTexture_DfShLamp->update(true) ;
+
+		// this shader combines the deferred light render with the emissive render and colours it with any gels
+		miniScreen_DfShMaster->setMaterial("Mix_Lamps") ; 
+
+		// get rid of all the scene geometry
+		m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+		// put up a fullscreen quad so DfShMix has some UV coordinates.
+		m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+		// update DfShMix, but don't swap buffers yet since we may be back again next loop with more lights to add.
+		renderTexture_DfShMix->update(false) ; 
+
+		// now DfShMix has all the deferred render stuff mixed onto it, as well as emissive stuff, 
+		// and it's ready for forward rendered shadowing lights to be additively blended over it.
+	} // end if deferred render active
+
+
+
+	
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// 
+	// forward rendered shadowing spotlights
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// we now add entities from m_pVisibleEntity instead of m_pFrustumEntity since entities outside the frustum might still contribute shadows.
+	//''
+	if(true)
+	{
+
+
+		// multiple attempts at getting additive blending of the shadows failed, so I have to do an extra pass to "accumulate" the data :(
+
+		int nMaxVisibleLight=*m_pGlobal_MaxVisibleLight ;
+
+		// the texture view projection per light.  We use four Vector4 instead of a single Matrix4 because we have to pass them to the shaders as custom params
+		Ogre::Vector4	tvpMat0 ;
+		Ogre::Vector4	tvpMat1 ;
+		Ogre::Vector4	tvpMat2 ;
+		Ogre::Vector4	tvpMat3 ;
+
+
+
+		int nVisibleLight=0 ;
+		int nLt=0 ;
+		int nProjector=0 ;
+		int nEntLtIndex=0 ;
+		int nEntLtIndexMax=0 ;
+
+		m_nVisibleLightCount=0 ; // total shadow lights added from all loops 
+
+
+		miniScreen_DfShMaster->setMaterial("Mix_ShadowLights") ;
+		
+		
+		// loop through shadow casting lights
+		for(nVisibleLight=0 ; nVisibleLight<nMaxVisibleLight ; nVisibleLight++)
+		{
+			 // copy the camera's original settings because we'll be modifying it
+			m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ;
+
+			nLt=m_pGlobal_VisibleLightList[nVisibleLight] ;
+
+			// setup the light and light's shadow camera, skip if light isn't really visible
+			if(SetupSingleVisibleLightAndShadowCamera(nLt, m_pGlobal_LightVis, m_pGlobal_VisibleLightList, m_pCamera))
+			{
+				// count the light
+				m_nVisibleLightCount++ ;
+				
+				
+
+				
+				/////////////////////////////////////////////////////////////////////////////////////////////////////
+				// Render the shadow map
+
+				// add all the opaque stuff
+				m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; 
+				SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_OPAQUE) ; 
+
+				
+				for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+				{
+					// check if this entity touches this light
+					nEntity=m_pVisibleEntity[nVisEnt] ;
+					
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[ nEntity ].pMasterNode) ;
+
+					nEntLtIndexMax=m_pEntityInfo[nEntity].Light[INDEX_LIGHTPERENTITY] ;
+					m_pEntityInfo[nEntity].LightTouch=0 ; // default, doesn't touch this light, use black material
+					for(nEntLtIndex=0 ; nEntLtIndex<nEntLtIndexMax ; nEntLtIndex++)
+						if(m_pEntityInfo[nEntity].Light[nEntLtIndex]==nLt) // found a match, entity is touched by this light
+						{
+							m_pEntityInfo[nEntity].LightTouch=1 ; // touches this light, don't use black
+							break ;
+						}
+
+				}// end for nVisEnt
+				
+
+
+
+
+
+
+				// change to shadow pass material
+				for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+				{
+					nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+					nZGStart	=	m_nZoneMOStart[nZone] ;
+					nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+						
+					for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+						if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+						{
+							pEntity=m_pZoneEntity[nMO] ;
+							pEntity->setMaterial( m_pZoneEntityMaterial_Shadow[nMO] ) ;
+						}// end for entities
+
+				}// end for zonelist
+
+				for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+				{
+					nEntity=m_pVisibleEntity[nVisEnt] ;
+					nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+					// set the entity material
+					for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+						if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE)
+							m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Shadow[nSubMesh] ) ;
+						else
+							m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(false) ; // non-opaque stuff is invisible
+				}
+
+
+				// render the shadow map out to the Shadow texture
+				renderTexture_Shadow->update(true) ;
+
+				// Opaque nodes are already in the scene, add all the Transparent stuff
+				SetZoneNodeAttachments(m_uVisibleZoneListL, &m_nMaxVisibleZoneL, MAT_GEL) ; 
+
+				// if this light is flagged as needing colourized shadows, we do the slower shadow method
+				// this means rendering an extra couple of coloured shadow maps here, plus a different material for the view render
+				if(m_nColouredShadow)
+				{
+					
+					/////////////////////////////////////////////////////////////////////////////////////////////////////
+					// Render the ShadeFront map
+
+					
+
+					// change to shadow pass material
+					for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+					{
+						nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+						nZGStart	=	m_nZoneMOStart[nZone] ;
+						nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+							
+						for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+							if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+							{
+								pEntity=m_pZoneEntity[nMO] ;
+								pEntity->setMaterial( m_pZoneEntityMaterial_ShadeFront[nMO] ) ;
+							}// end for entities
+
+					}// end for zonelist
+
+					for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+					{
+						nEntity=m_pVisibleEntity[nVisEnt] ;
+						nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+						// set the entity material (pClearMaterial is already set)
+						for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+							if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
+							{
+								// make gel stuff visible
+								if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL)
+									m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setVisible(true) ;
+
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_ShadeFront[nSubMesh] ) ;
+							}
+					}
+
+					// render the shadow map out to the Shadow texture
+					renderTexture_ShadeFront->update(true) ;
+
+					
+					/////////////////////////////////////////////////////////////////////////////////////////////////////
+					// Render the ShadeBack map
+
+					// change to shadow pass material
+					for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+					{
+						nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+						nZGStart	=	m_nZoneMOStart[nZone] ;
+						nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+							
+						for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+							if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+							{
+								pEntity=m_pZoneEntity[nMO] ;
+								pEntity->setMaterial( m_pZoneEntityMaterial_ShadeBack[nMO] ) ;
+							}// end for entities
+
+					}// end for zonelist
+
+					for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+					{
+						nEntity=m_pVisibleEntity[nVisEnt] ;
+						nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+						// set the entity material (pClearMaterial is already set)
+						for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+							if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_ShadeBack[nSubMesh] ) ;
+					}
+
+					// render the shadow map out to the Shadow texture
+					renderTexture_ShadeBack->update(true) ;
+					
+				} // end if we need coloured shadows
+
+
+	
+
+
+
+
+				/////////////////////////////////////////////////////////////////////////////////////////////////////
+				// Apply the shadow map to the view
+
+				// calculate the texture view projection matrix for this light
+				Matrix4 TexViewProj=CreateTextureViewProjectionMatrix(m_pCamera) ;
+
+				// change the matrix to four Vector4s so we can pass it in as a shader parameter 
+				tvpMat0[0]=TexViewProj[0][0] ; tvpMat0[1]=TexViewProj[0][1] ; tvpMat0[2]=TexViewProj[0][2] ; tvpMat0[3]=TexViewProj[0][3] ;
+				tvpMat1[0]=TexViewProj[1][0] ; tvpMat1[1]=TexViewProj[1][1] ; tvpMat1[2]=TexViewProj[1][2] ; tvpMat1[3]=TexViewProj[1][3] ;
+				tvpMat2[0]=TexViewProj[2][0] ; tvpMat2[1]=TexViewProj[2][1] ; tvpMat2[2]=TexViewProj[2][2] ; tvpMat2[3]=TexViewProj[2][3] ;
+				tvpMat3[0]=TexViewProj[3][0] ; tvpMat3[1]=TexViewProj[3][1] ; tvpMat3[2]=TexViewProj[3][2] ; tvpMat3[3]=TexViewProj[3][3] ;
+
+				// put the camera back to its proper position and settings.
+				m_pCamera->synchroniseBaseSettingsWith(m_pCameraCopy) ;
+				m_pCamera->setFOVy( Degree(m_flFOV) ) ;
+				m_pCamera->setAspectRatio( Real(m_flAspectRatio) );
+
+
+				nProjector=m_Q3Map->m_pLight[nLt].Texture ; // what projector texture is this light using?
+
+				// change material and set all the tvp custom params
+				for(nZoneList=0 ; nZoneList<nMaxVisibleZone ; nZoneList++)
+				{
+					nZone=m_pGlobal_VisibleZoneList[nZoneList] ;
+					nZGStart	=	m_nZoneMOStart[nZone] ;
+					nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+						
+					for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+						if((m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE) || (m_pZoneEntityMaterialType[nMO]==MAT_GEL))
+						{
+							pEntity=m_pZoneEntity[nMO] ;
+
+
+							// since the spot light pass is one of the slowest, we set the material of all the zones that don't touch
+							// this light to just a black material.  Only the zone of this light gets the real lighting material
+							// We need to have the other zones though or we end up seeing through walls.
+							// ALSO don't set gels to black, or else they block out the light in other zones.
+
+							
+							if((m_pZoneEntityMaterialType[nMO]==MAT_GEL) || (LightTouchesZone(nLt, nZone)) )
+							{
+								if(m_nColouredShadow)
+									pEntity->setMaterial( m_pZoneEntityMaterial_Base[nProjector][nMO] ) ; // coloured shadows
+								else
+									pEntity->setMaterial( m_pZoneEntityMaterial_Fast[nProjector][nMO] ) ; // fast shadows
+							}
+							else
+								pEntity->setMaterial( m_pZoneEntityMaterial_Black[nMO] ) ; // just flat black, alpha tested for some
+
+
+							
+				
+
+							// set the custom parameter, our texture view projection matrix for this light
+							pEntity->getSubEntity(0)->setCustomParameter(0, tvpMat0) ;
+							pEntity->getSubEntity(0)->setCustomParameter(1, tvpMat1) ;
+							pEntity->getSubEntity(0)->setCustomParameter(2, tvpMat2) ;
+							pEntity->getSubEntity(0)->setCustomParameter(3, tvpMat3) ;
+
+							pEntity->getSubEntity(0)->setCustomParameter(4, TexParam) ;
+
+						}// end for entities
+
+				}// end for zonelist
+
+				for(nVisEnt=0 ; nVisEnt<m_nMaxVisibleEntity ; nVisEnt++)
+				{
+					nEntity=m_pVisibleEntity[nVisEnt] ;
+					nMaxSubMesh=m_pEntityInfo[nEntity].MaxSubMesh ;
+
+					// set the entity material
+					for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+						if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_OPAQUE) || (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL))
+						{
+
+							// if it's gel or the light touches the entity, use proper material, else use black
+							if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GEL) || m_pEntityInfo[nEntity].LightTouch)
+							{
+								if(m_nColouredShadow)
+									m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Base[nProjector][nSubMesh] ) ; // coloured shadows
+								else
+									m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Fast[nProjector][nSubMesh] ) ; // fast shadows
+							}
+							else
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( m_pEntityInfo[nEntity].Material_Black[nSubMesh] ) ; // flat black
+
+
+
+							// set the custom parameter, our texture view projection matrix for this light
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(0, tvpMat0) ;
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(1, tvpMat1) ;
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(2, tvpMat2) ;
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(3, tvpMat3) ;
+
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setCustomParameter(4, TexParam) ;
+						}
+						else
+								m_pEntityInfo[nEntity].pEnt->getSubEntity(nSubMesh)->setMaterial( pClearMaterial ) ;
+				}
+
+
+
+
+				// if this is the first visible light, add emmissive transparent/alphablend particles.  
+				// they are added here so that they render correctly according to gels.
+				// But since they aren't shadowed, we only need render them for one light.
+				if(m_nVisibleLightCount==1)
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pParticleNode) ; // attach the particles
+
+
+
+				/////////////////////////////////////////////////////////////////////////////////////////////
+				// render the scene out to the DfShTemp texture.
+				//
+
+				renderTexture_DfShTemp->update(true) ; 
+
+				//
+				/////////////////////////////////////////////////////////////////////////////////////////////
+				
+				
+				
+				// remove the particles
+				if(m_nVisibleLightCount==1)
+					m_pSceneMgr->getRootSceneNode()->removeChild(m_pParticleNode) ;
+
+
+				///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+				// Render Mix
+
+				//?? unfortunately Ogre shares depth buffers in a manner that won't allow us to just additively render to DfShMix.
+				// If we try, we get glitching from the buffer sharing between Shadow and DfShMix.
+				// So instead we get rid of all geometry and additively render a fullscreen quad of DfShTemp to DfShMix.
+				// Slows things down a little, but at least it works.
+
+				// get rid of all the scene geometry
+				m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+				// put up a fullscreen quad so DfShMix has some UV coordinates.
+				m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+				// update DfShMix, but don't swap buffers yet since we may be back again next loop with more lights to add.
+				renderTexture_DfShMix->update(false) ; 
+
+			}// end if light is visible
+
+
+		}// end for nVisibleLight
+			
+	}// end if forward render active
+
+	///////////////////////////////////////////////////////////////////////////////////////
+
+
+
+	// after we've finished with all the lights and mixing, time to swap the mix buffer
+	renderTexture_DfShMix->swapBuffers(false) ;
+
+	
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// 
+	// HDR bloom
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	
+	if(m_nRenderHDR)
+	{
+		/////////////////////////////////////////////////////////
+		// copy DfShMix to BlurA
+
+		// get rid of all the scene geometry
+		m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+		// this shader renders DfShMix onto a surface 
+		miniScreen_DfShMaster->setMaterial("HDR_MixToBlurA") ; 
+
+		// put up a fullscreen quad so BlurA has some UV coordinates.
+		m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+		// render DfShMix to BlurA
+		renderTexture_BlurA->update(true) ;
+
+		
+
+
+		//////////////////////////////////////////////////////////////
+		// now we do a few rounds of ping-pong bluring of A to B, B to A.
+		int nMaxBlur=4 ;
+//		int nLastBlur=nMaxBlur-1 ;
+		int nBlurLoop=0 ;
+
+		
+		// opengl and direct3d give different results for the same blur shader, 
+		// the issue is that d3d with bilinear filtering will offset stuff, 
+		// leading to a right-down drift that we need to compensate for.
+		// So we need two versions of the blur shaders, one for ogl and one for d3d.
+
+		if(m_IsOpenGL)
+		{
+			miniScreen_BlurA->setMaterial("HDR_BlurA_ogl");
+			miniScreen_BlurB->setMaterial("HDR_BlurB_ogl");
+		}
+		else
+		{
+			miniScreen_BlurA->setMaterial("HDR_BlurA_d3d");
+			miniScreen_BlurB->setMaterial("HDR_BlurB_d3d");
+		}
+
+				
+		// the main blur
+		for(nBlurLoop=0 ; nBlurLoop<nMaxBlur ; nBlurLoop++)
+		{
+			// blur A onto B
+			m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+			m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ;
+			renderTexture_BlurB->update(true) ;
+
+			// blur B onto A
+			m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+			m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurB) ;
+			renderTexture_BlurA->update(true) ;
+		}
+		
+
+		// If I don't set these materials back to their originals, I get a crash on exit. 
+		// Not sure why.  Something to do with deleting the originals?
+		// Doesn't matter, this fixes things.
+
+		miniScreen_BlurA->setMaterial("RttMat_BlurA");
+		miniScreen_BlurB->setMaterial("RttMat_BlurB");
+		
+		
+
+		//////////////////////////////////////////////////////////////////
+		// blend BlurA onto DfShMix
+
+		// get rid of all the scene geometry
+		m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+		// this shader blends BlurA onto a surface
+		if(m_IsOpenGL)
+			miniScreen_DfShMaster->setMaterial("HDR_BlurAToMix_ogl") ;
+		else
+			miniScreen_DfShMaster->setMaterial("HDR_BlurAToMix_d3d") ;
+
+		// put up a fullscreen quad so DfShMix has some UV coordinates.
+		m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+		// update DfShMix.
+		renderTexture_DfShMix->update(true) ;
+
+	}// end if HDR
+	
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// 
+	// display a rendered window
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	
+	m_pSceneMgr->getRootSceneNode()->removeAllChildren() ; // remove all the objects
+	
+	
+	if(m_nGoggleMode==GOGGLE_MODE_OFF) // stereo rendering not active
+	{
+		switch(m_nDisplayInfoMode)
+		{
+
+			case 0:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ; break ;
+			case 1:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShTemp) ; break ; // for wireframe view
+			case 2:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShLamp) ; break ;
+			case 3:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ; break ;
+
+			case 4: // instead of showing the original position texture, we show a scaled version, since the original is outside 0-1 range
+
+				// get rid of all the scene geometry
+				m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+				// this shader renders DfShMix onto a surface 
+				miniScreen_DfShMaster->setMaterial("Mix_ScalePosition") ; 
+
+				// put up a fullscreen quad so BlurA has some UV coordinates.
+				m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMaster) ;
+
+				// render DfShPostion to DfShMix
+				renderTexture_DfShMix->update(true) ;
+
+				// display mix, which is a scaled copy of position.
+				m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ;
+				break ;
+			
+			case 5:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShFuncTNB) ; break ;
+			case 6:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ; break ;
+			case 7:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShSpecular) ; break ;			
+			case 8:	m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShEmissive) ; break ;
+		}
+
+
+
+
+		
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShPosition) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShFuncTNB) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShSpecular) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShEmissive) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShData) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShLamp) ;
+
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_BlurA) ;
+
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShMix) ;
+		
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_Shadow) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShTemp) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_ShadeBack) ;
+		//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_ShadeFront) ;
+	}
+	else
+	{
+		// add and position the Goggles
+		m_pSceneMgr->getRootSceneNode()->addChild(m_pNodeGoggles) ;
+		m_pNodeGoggles->setOrientation( m_pCamera->getOrientation() ) ;
+		m_pNodeGoggles->setPosition( m_pCamera->getPosition() ) ;
+	}
+
+	
+	//m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+	//m_pSceneMgr->getRootSceneNode()->addChild(miniScreenNode_DfShDiffuse) ;
+	
+	
+	m_pRenderWnd->update(true) ;
+
+
+	//m_pSceneMgr->getRootSceneNode()->removeChild(miniScreenNode_DfShSpecular) ;
+	m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+	
+
+
+	///////////////////////////////////////////
+	// blittomemory experiment
+	//uchar pixelData[64] ;
+	//RTT_Texture_DfShPosition->getBuffer()->blitToMemory( Box( 0, 0, 1, 1), PixelBox(2, 2, 1, PF_FLOAT16_RGB, (void*)pixelData) ) ;
+
+
+}
+
+// generate the texture view Projection matrix used in shadow mapping
+Ogre::Matrix4 OgreFramework::CreateTextureViewProjectionMatrix(Ogre::Camera* pCamera)
+{
+
+	const Matrix4 PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE(
+		      0.5,    0,    0,  0.5,
+			    0,   -0.5,    0,  0.5,
+				  0,      0,    1,    0,
+					0,      0,    0,    1);
+
+	Matrix4 TexViewProj = PROJECTIONCLIPSPACE2DTOIMAGESPACE_PERSPECTIVE * pCamera->getProjectionMatrixWithRSDepth() * pCamera->getViewMatrix();
+
+	return TexViewProj ;
+
+}
+
+void OgreFramework::DestroyGoggles()
+{
+	//m_pGoggleL->~ManualObject() ;
+	//m_pGoggleR->~ManualObject() ;
+
+	//m_pNodeGoggles->~SceneNode() ;
+	
+
+}
+
+// create the "virtual" virtual reality goggles we use to get around stereoscopic driver problems.
+int OgreFramework::CreateGoggles()
+{
+
+	
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+
+
+	// if they already exist, destroy them so we can recreate them
+	if(m_pNodeGoggles!=NULL)	m_pNodeGoggles->detachAllObjects() ;
+	if(m_pGoggleL!=NULL)			m_pGoggleL->clear() ;
+	if(m_pGoggleR!=NULL)			m_pGoggleR->clear() ;
+	
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// left goggle
+
+		if(m_pGoggleL==NULL) m_pGoggleL=m_pSceneMgr->createManualObject("GoggleL") ;
+		m_pGoggleL->begin("RttMat_DfShMix", RenderOperation::OT_TRIANGLE_LIST) ;
+	
+		flMinX=-100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+		flMinY=-50*m_flGoggleYScale ;
+
+
+		flMaxX=0 ;
+		flMaxY=50*m_flGoggleYScale ;
+
+		
+		m_pGoggleL->position(flMinX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(0.0, 0.0) ;
+		m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(1.0, 0.0) ;
+		m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(1.0, 1.0) ;
+		m_pGoggleL->position(flMinX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(0.0, 1.0) ;
+
+		m_pGoggleL->quad(3, 2, 1, 0) ;
+		m_pGoggleL->end() ;
+
+		m_pGoggleL->setCastShadows(false) ;
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// right goggle
+
+		if(m_pGoggleR==NULL) m_pGoggleR=m_pSceneMgr->createManualObject("GoggleR") ;
+		m_pGoggleR->begin("RttMat_DfShMix", RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+		flMinX=0 ;
+		flMinY=-50*m_flGoggleYScale ;
+
+
+		flMaxX=100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+		flMaxY=50*m_flGoggleYScale ;
+
+		
+		m_pGoggleR->position(flMinX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(0.0, 0.0) ;
+		m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(1.0, 0.0) ;
+		m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(1.0, 1.0) ;
+		m_pGoggleR->position(flMinX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(0.0, 1.0) ;
+
+		m_pGoggleR->quad(3, 2, 1, 0) ;
+		m_pGoggleR->end() ;
+
+		m_pGoggleR->setCastShadows(false) ;
+		
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// attach the goggles to the node.
+	if(m_pNodeGoggles==NULL) m_pNodeGoggles=m_pSceneMgr->getRootSceneNode()->createChildSceneNode("NodeGoggles") ;
+	m_pNodeGoggles->attachObject(m_pGoggleL) ;
+	m_pNodeGoggles->attachObject(m_pGoggleR) ;
+
+	return 1 ;
+}
+
+// create the "virtual" virtual reality goggles we use to get around stereoscopic driver problems.
+// This version of the goggles just has a test image for setting up the correct real driver settings,
+// so that the left eye sees only the left "goggle" and the right eye only the right "goggle",
+// and the goggles have the right depth relative to the screen (flat to it)
+int OgreFramework::CreateGogglesTestImage() 
+{
+
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+
+
+	// if they already exist, destroy them so we can recreate them
+	if(m_pNodeGoggles!=NULL)	m_pNodeGoggles->detachAllObjects() ;
+	if(m_pGoggleL!=NULL)			m_pGoggleL->clear() ;
+	if(m_pGoggleR!=NULL)			m_pGoggleR->clear() ;
+	
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// left goggle
+
+		if(m_pGoggleL==NULL) m_pGoggleL=m_pSceneMgr->createManualObject("GoggleL") ;
+		m_pGoggleL->begin("GoggleTest", RenderOperation::OT_TRIANGLE_LIST) ;
+	
+		flMinX=-100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+		flMinY=-50*m_flGoggleYScale ;
+
+
+		flMaxX=0 ;
+		flMaxY=50*m_flGoggleYScale ;
+
+		
+		m_pGoggleL->position(flMinX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(0.0, 0.0) ;
+		m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(1.0, 0.0) ;
+		m_pGoggleL->position(flMaxX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(1.0, 1.0) ;
+		m_pGoggleL->position(flMinX-m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleL->normal(0.0, 0.0, -1) ;
+		m_pGoggleL->textureCoord(0.0, 1.0) ;
+
+		m_pGoggleL->quad(3, 2, 1, 0) ;
+		m_pGoggleL->end() ;
+
+		m_pGoggleL->setCastShadows(false) ;
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// right goggle
+
+		if(m_pGoggleR==NULL) m_pGoggleR=m_pSceneMgr->createManualObject("GoggleR") ;
+		m_pGoggleR->begin("GoggleTest", RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+		flMinX=0 ;
+		flMinY=-50*m_flGoggleYScale ;
+
+
+		flMaxX=100*m_flGoggleAspectRatio*m_flGoggleXScale ;
+		flMaxY=50*m_flGoggleYScale ;
+
+		
+		m_pGoggleR->position(flMinX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(1.0, 1.0) ;
+		m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMaxY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(0.0, 1.0) ;
+		m_pGoggleR->position(flMaxX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(0.0, 0.0) ;
+		m_pGoggleR->position(flMinX+m_flGoggleXGap, flMinY, m_flGoggleZPos) ;
+		m_pGoggleR->normal(0.0, 0.0, -1) ;
+		m_pGoggleR->textureCoord(1.0, 0.0) ;
+
+		m_pGoggleR->quad(3, 2, 1, 0) ;
+		m_pGoggleR->end() ;
+
+		m_pGoggleR->setCastShadows(false) ;
+		
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// attach the goggles to the node.
+	if(m_pNodeGoggles==NULL) m_pNodeGoggles=m_pSceneMgr->getRootSceneNode()->createChildSceneNode("NodeGoggles") ;
+	m_pNodeGoggles->attachObject(m_pGoggleL) ;
+	m_pNodeGoggles->attachObject(m_pGoggleR) ;
+
+	return 1 ;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::keyPressed(const OIS::KeyEvent &keyEventRef)
+{
+	//m_pLog->logMessage("OgreFramework::keyPressed");
+	
+	if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
+	{
+			m_bShutDownOgre = true;
+			return true;
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_SYSRQ))
+	{
+		std::ostringstream ss;
+		ss << "screenshot_" << ++m_iNumScreenShots << ".png";
+		m_pRenderWnd->writeContentsToFile(ss.str());
+		return true;
+	}
+
+	/*
+	if(m_pKeyboard->isKeyDown(OIS::KC_M))
+	{
+		static int mode = 0;
+		
+		if(mode == 2)
+		{
+			m_pCamera->setPolygonMode(PM_SOLID);
+			mode = 0;
+		}
+		else if(mode == 0)
+		{
+			 m_pCamera->setPolygonMode(PM_WIREFRAME);
+			 mode = 1;
+		}
+		else if(mode == 1)
+		{
+			m_pCamera->setPolygonMode(PM_POINTS);
+			mode = 2;
+		}
+	}
+	*/
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_O))
+	{
+		if(m_pDebugOverlay)
+		{
+			if(!m_pDebugOverlay->isVisible())
+				m_pDebugOverlay->show();
+			else
+				m_pDebugOverlay->hide();
+		}
+	}
+
+
+
+	return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::keyReleased(const OIS::KeyEvent &keyEventRef)
+{
+	return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::mouseMoved(const OIS::MouseEvent &evt)
+{
+	m_pCamera->yaw(Degree(evt.state.X.rel * -0.1));
+	m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1));
+	
+	return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
+{
+	return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+bool OgreFramework::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
+{
+	return true;
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::updateOgre(double timeSinceLastFrame)
+{
+
+
+
+
+	// update the game time
+	m_GameTime+=timeSinceLastFrame ;
+
+
+	m_MoveScale = m_MoveSpeed   * timeSinceLastFrame;
+	m_RotScale  = m_RotateSpeed * timeSinceLastFrame;
+		
+	m_TranslateVector = Vector3::ZERO;
+
+//	char chMessage[1024] ;
+	//sprintf(chMessage, "winmessage %u, %u, %u", m_pRenderWnd->m_Test_uMsg, (UINT)m_pRenderWnd->m_Test_wParam, (UINT)m_pRenderWnd->m_Test_lParam) ; 
+	//m_pLog->logMessage(chMessage) ;
+
+
+
+	/*
+	if((m_pRenderWnd->m_Test_uMsg==258) && (m_pRenderWnd->m_Test_wParam==0x78))
+	//if(GetAsyncKeyState(0x78))
+	{
+
+		m_TranslateVector.z = -m_MoveScale;
+		//m_nGotInput=1 ;
+		
+		//sprintf(chMessage, "T %i: winmessage %u, %u, %u", m_nTime, m_pRenderWnd->m_Test_uMsg, (UINT)m_pRenderWnd->m_Test_wParam, (UINT)m_pRenderWnd->m_Test_lParam) ; 
+		//m_pLog->logMessage(chMessage) ;
+	}
+	else
+		m_nGotInput=0 ;
+	*/
+
+	// add a test particle to the system
+	/*
+	if( m_ps->getNumParticles() < m_ps->getParticleQuota() )
+	{
+		Ogre::Particle *p = m_ps->createParticle() ;
+		p->setDimensions( m_ps->getDefaultWidth(), m_ps->getDefaultHeight() ) ;
+		p->colour = Ogre::ColourValue::White;
+		p->direction = Ogre::Vector3::UNIT_Y;
+		p->position = Ogre::Vector3::ZERO;
+		p->timeToLive = p->totalTimeToLive = 10;
+		p->rotation = Ogre::Radian(0);   
+		p->rotationSpeed = Ogre::Radian(0);
+	}
+	*/
+
+
+	m_ps->_update(timeSinceLastFrame/1000.0f) ;
+
+	getInput();
+
+	moveCamera();
+
+
+	//Ogre::Vector3 Pos ;
+	//float CamPos[3] ;
+	//Pos=m_pCamera->getPosition() ;
+	//CamPos[0]=Pos.x ;
+	//CamPos[1]=Pos.y ;
+	//CamPos[2]=Pos.z ;
+
+
+
+	if(m_nGoggleMode==GOGGLE_MODE_OFF)
+	{
+
+
+		m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ; // copy the camera's original settings because we'll be modifying it for the LR views.
+		m_pCameraCopy->setFOVy( Degree(m_flFOV) ) ;
+		m_pCameraCopy->setAspectRatio( Real(m_flAspectRatio) );
+
+
+
+		if(m_nMapLoaded)
+		{
+			SetupEntityZones() ;
+			
+			CalculateZoneVisibility(m_pCameraCopy, &m_nCameraZoneL, m_chZoneVisL, m_chLightVisL, m_chSubLightVisL, m_chPortalVisL, &m_nMaxVisibleLightL, m_uVisibleLightListL) ;
+			CalculateEntityVisibility(m_pCameraCopy, m_chZoneVisL) ;
+
+			UpdateVisibleZoneList(m_chZoneVisL, m_uVisibleZoneListL, &m_nMaxVisibleZoneL) ;
+
+			//m_nVisibleLightCount=m_nMaxVisibleLightL ;
+			m_nVisibleZoneCount=m_nMaxVisibleZoneL ;
+		}
+
+
+
+		m_pGlobal_VisibleZoneList=m_uVisibleZoneListL ;
+		m_pGlobal_MaxVisibleZone=&m_nMaxVisibleZoneL ;
+
+		m_pGlobal_VisibleLightList	=	m_uVisibleLightListL ;
+		m_pGlobal_MaxVisibleLight		=	&m_nMaxVisibleLightL ;
+		m_pGlobal_LightVis					=	m_chLightVisL ;
+
+
+	}
+	else
+	{
+		// "virtual" stereo goggle mode.  Render everything twice, L and R view, and output to L quad and a R quad.
+
+		m_pCameraCopy->synchroniseBaseSettingsWith(m_pCamera) ; // copy the camera's original settings because we'll be modifying it for the LR views.
+
+		if(m_nMapLoaded)
+		{
+			SetupEntityZones() ;
+
+			CalculateZoneVisibility(m_pCameraCopy, &m_nCameraZoneL, m_chZoneVisL, m_chLightVisL, m_chSubLightVisL, m_chPortalVisL, &m_nMaxVisibleLightL, m_uVisibleLightListL) ;
+			UpdateVisibleZoneList(m_chZoneVisL, m_uVisibleZoneListL, &m_nMaxVisibleZoneL) ;
+
+			
+			//m_nVisibleLightCount=m_nMaxVisibleLightL ;
+			m_nVisibleZoneCount=m_nMaxVisibleZoneL ;
+		}
+
+		m_pGlobal_VisibleZoneList=m_uVisibleZoneListL ;
+		m_pGlobal_MaxVisibleZone=&m_nMaxVisibleZoneL ;
+	}
+
+
+	updateStats();
+
+
+	//,,
+	//sprintf(m_chFrame, "End of updateOgre frame %i",m_nFrame) ;
+	//OFBug.LogAddCR(m_chFrame) ;
+	
+
+
+	m_nFrame++ ;
+
+
+	
+}
+
+
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::updateStats() 
+{ 
+	
+	
+	Ogre::Vector3 Pos ;
+	Pos=m_pCamera->getPosition() ;
+	Ogre::Real nCamX=Pos.x ;
+	Ogre::Real nCamY=Pos.y ;
+	Ogre::Real nCamZ=Pos.z ;
+
+
+	static String currFps = "FPS: "; 
+    static String avgFps = "Av FPS: "; 
+    static String bestFps = "Best FPS: "; 
+    static String worstFps = "Worst FPS: "; 
+    static String tris = "Triangle Count: "; 
+    static String batches = "Batch Count: "; 
+
+ 
+    OverlayElement* guiAvg = OverlayManager::getSingleton().getOverlayElement("Core/AverageFps"); 
+    OverlayElement* guiCurr = OverlayManager::getSingleton().getOverlayElement("Core/CurrFps"); 
+    OverlayElement* guiBest = OverlayManager::getSingleton().getOverlayElement("Core/BestFps"); 
+    OverlayElement* guiWorst = OverlayManager::getSingleton().getOverlayElement("Core/WorstFps"); 
+
+	const RenderTarget::FrameStats& stats = m_pRenderWnd->getStatistics();
+    
+		//int LastFrameTime=1000000/stats.lastFPS ;
+		float LastFrameTime=1000/stats.lastFPS ;
+
+
+
+
+
+		switch(m_nDisplayInfoMode)
+		{
+
+			case 0:
+				if(m_IsOpenGL)
+					guiCurr->setCaption("OGL FPS: " + StringConverter::toString(stats.lastFPS) +" "+StringConverter::toString(LastFrameTime)+" ms"); 
+				else
+					guiCurr->setCaption("D3D FPS: " + StringConverter::toString(stats.lastFPS) +" "+StringConverter::toString(LastFrameTime)+" ms"); 
+				break ;
+
+			case 1: guiCurr->setCaption("Wireframe") ; break ;
+			case 2: guiCurr->setCaption("Lamps") ; break ;
+			case 3: guiCurr->setCaption("HDR Blur") ; break ;
+			case 4: guiCurr->setCaption("DefShade Position (Scaled)") ; break ;
+			case 5: guiCurr->setCaption("DefShade Normals") ; break ;
+			case 6: guiCurr->setCaption("DefShade Diffuse") ; break ;
+			case 7: guiCurr->setCaption("DefShade Specular") ; break ;
+			case 8: guiCurr->setCaption("DefShade Emissive") ; break ;
+
+		}
+
+		guiAvg->setCaption("Lt: " + StringConverter::toString(m_nVisibleLightCount)
+			+ " Zn: " + StringConverter::toString(m_nVisibleZoneCount)  
+			+ " Cam: "+StringConverter::toString(nCamX)+" "+StringConverter::toString(nCamY)+" "+StringConverter::toString(nCamZ));
+
+
+
+
+		//m_flDebug0=m_nTotalTriangles ;
+		//m_flDebug1=m_nMaxVisibleEntity ;
+		//m_flDebug2=m_nMaxFrustumEntity ;
+		guiWorst->setCaption("ZnEnt: " + StringConverter::toString(m_nMaxVisibleEntity) + " Tri: " + StringConverter::toString(m_nVisibleEntityTriangleCount) + " FwdTri: " + StringConverter::toString(m_nVisibleEntityTriangleCount)    ) ;
+		guiBest->setCaption("FrEnt: " + StringConverter::toString(m_nMaxFrustumEntity) + " Tri: " + StringConverter::toString(m_nFrustumEntityTriangleCount) + " DefTri: " + StringConverter::toString(m_nFrustumEntityTriangleCount)    ) ;
+
+
+
+
+		//guiWorst->setCaption(StringConverter::toString(m_flDebug0) + " " + StringConverter::toString(m_flDebug1) + " " + StringConverter::toString(m_flDebug2)) ;
+		//guiBest->setCaption(StringConverter::toString(m_flDebug3) + " " + StringConverter::toString(m_flDebug4) + " " + StringConverter::toString(m_flDebug5)) ;
+		/*
+		guiWorst->setCaption(
+			" A "+StringConverter::toString(m_flDebugMatrix[0][0])+" "+StringConverter::toString(m_flDebugMatrix[0][1])+" "+StringConverter::toString(m_flDebugMatrix[0][2])+" "+StringConverter::toString(m_flDebugMatrix[0][3]) +
+			" B "+StringConverter::toString(m_flDebugMatrix[1][0])+" "+StringConverter::toString(m_flDebugMatrix[1][1])+" "+StringConverter::toString(m_flDebugMatrix[1][2])+" "+StringConverter::toString(m_flDebugMatrix[1][3]) ) ;
+
+		guiBest->setCaption(
+			" C "+StringConverter::toString(m_flDebugMatrix[2][0])+" "+StringConverter::toString(m_flDebugMatrix[2][1])+" "+StringConverter::toString(m_flDebugMatrix[2][2])+" "+StringConverter::toString(m_flDebugMatrix[2][3]) +
+			" D "+StringConverter::toString(m_flDebugMatrix[3][0])+" "+StringConverter::toString(m_flDebugMatrix[3][1])+" "+StringConverter::toString(m_flDebugMatrix[3][2])+" "+StringConverter::toString(m_flDebugMatrix[3][3]) ) ;
+		*/
+	
+		
+		
+		
+		//guiWorst->setCaption(StringConverter::toString(flVarA)+" "+StringConverter::toString(flVarB)+" "+StringConverter::toString(flVarC)+" "+StringConverter::toString(flVarD)
+   
+	//guiBest->setCaption(bestFps + StringConverter::toString(stats.bestFPS) 
+  //          +" "+StringConverter::toString(stats.bestFrameTime)+" ms"); 
+	//guiWorst->setCaption(worstFps + StringConverter::toString(stats.worstFPS) 
+  //          +" "+StringConverter::toString(stats.worstFrameTime)+" ms"); 
+	
+	//guiWorst->setCaption(worstFps + StringConverter::toString(nCamX)+" " + StringConverter::toString(nCamY)+" " + StringConverter::toString(nCamZ)+" ") ;
+    
+	
+	OverlayElement* guiTris = OverlayManager::getSingleton().getOverlayElement("Core/NumTris"); 
+	guiTris->setCaption("MpTri: " + StringConverter::toString(m_nTotalTriangles)); 
+
+	OverlayElement* guiBatches = OverlayManager::getSingleton().getOverlayElement("Core/NumBatches"); 
+    guiBatches->setCaption(batches + StringConverter::toString(stats.batchCount)); 
+
+	OverlayElement* guiDbg = OverlayManager::getSingleton().getOverlayElement("Core/DebugText"); 
+		guiDbg->setCaption("A:"+StringConverter::toString(m_nDebugA) + " B:" + StringConverter::toString(m_nDebugB) + " C:" + StringConverter::toString(m_nDebugC) + " ") ;
+	
+	//guiDbg->setCaption(
+	//	" A "+StringConverter::toString(m_flDebugMatrix[0][0])+" "+StringConverter::toString(m_flDebugMatrix[0][1])+" "+StringConverter::toString(m_flDebugMatrix[0][2])+" "+StringConverter::toString(m_flDebugMatrix[0][3]) +
+	//	" B "+StringConverter::toString(m_flDebugMatrix[1][0])+" "+StringConverter::toString(m_flDebugMatrix[1][1])+" "+StringConverter::toString(m_flDebugMatrix[1][2])+" "+StringConverter::toString(m_flDebugMatrix[1][3]) +
+	//	" C "+StringConverter::toString(m_flDebugMatrix[2][0])+" "+StringConverter::toString(m_flDebugMatrix[2][1])+" "+StringConverter::toString(m_flDebugMatrix[2][2])+" "+StringConverter::toString(m_flDebugMatrix[2][3]) +
+	//	" D "+StringConverter::toString(m_flDebugMatrix[3][0])+" "+StringConverter::toString(m_flDebugMatrix[3][1])+" "+StringConverter::toString(m_flDebugMatrix[3][2])+" "+StringConverter::toString(m_flDebugMatrix[3][3]) ) ;
+
+
+
+
+	//guiDbg->setCaption("");
+} 
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::moveCamera()
+{
+	if( m_nKeyDown_Ctrl && m_nKeyDown_Shift ) // super slow
+			m_pCamera->moveRelative(m_TranslateVector/50);
+		else
+			if(m_nKeyDown_Shift)	// fast
+				m_pCamera->moveRelative(m_TranslateVector*10);
+			else
+				if(m_nKeyDown_Ctrl) // slow 
+					m_pCamera->moveRelative(m_TranslateVector/5);
+				else
+					m_pCamera->moveRelative(m_TranslateVector*2); // normal
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+void OgreFramework::getInput()
+{
+	if(m_pKeyboard->isKeyDown(OIS::KC_LCONTROL))
+		m_nKeyDown_Ctrl=1 ;
+	else
+		m_nKeyDown_Ctrl=0 ;
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_LSHIFT))
+		m_nKeyDown_Shift=1 ;
+	else
+		m_nKeyDown_Shift=0 ;
+
+
+
+
+
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_A))
+	{
+		m_TranslateVector.x = -m_MoveScale;
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_D))
+	{
+		m_TranslateVector.x = m_MoveScale;
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_W))
+	{
+		m_TranslateVector.z = -m_MoveScale;
+		m_nGotInput=1 ;
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_S))
+	{
+		m_TranslateVector.z = m_MoveScale;
+	}
+
+
+	// generic toggle for debugging
+	if(m_pKeyboard->isKeyDown(OIS::KC_T))
+	{
+		if(m_nKeyToggle[OIS::KC_T]==0)
+		{
+			m_nKeyToggle[OIS::KC_T]=1 ; // toggle to stop key repeating
+			m_nToggle=1-m_nToggle ;
+			//OFBug.MessageInt(m_nToggle) ;
+		}
+	}
+	else
+		m_nKeyToggle[OIS::KC_T]=0 ;
+
+	//m_flDebug0=m_nKeyToggle[OIS::KC_T] ;
+	//m_flDebug1=m_nToggle ;
+
+	/*
+	if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
+	{
+		m_pCamera->yaw(m_RotScale);
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
+	{
+		m_pCamera->yaw(-m_RotScale);
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_UP))
+	{
+		m_pCamera->pitch(m_RotScale);
+	}
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
+	{
+		m_pCamera->pitch(-m_RotScale);
+	}
+	*/
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////
+	//
+	// Stereo controls
+
+	
+
+	// toggle stereo test image mode
+	if(m_pKeyboard->isKeyDown(OIS::KC_DELETE))
+	{
+		if(m_nKeyToggle[OIS::KC_DELETE]==0)
+		{
+			m_nKeyToggle[OIS::KC_DELETE]=1 ; // toggle to stop key repeating
+			
+			m_nGoggleMode++ ; // cyle through the goggle modes
+			if(m_nGoggleMode>=GOGGLE_MODE_MAX)
+				m_nGoggleMode=GOGGLE_MODE_OFF ;
+
+			if(m_nGoggleMode==GOGGLE_MODE_TEST)
+				CreateGogglesTestImage() ; // create the test goggles
+			else
+				if(m_nGoggleMode==GOGGLE_MODE_ON)
+					CreateGoggles() ; // create the stereo goggles
+		}
+	}
+	else
+		m_nKeyToggle[OIS::KC_DELETE]=0 ;
+
+	if(m_nGoggleMode==GOGGLE_MODE_TEST) // controls for setting up the test image
+	{
+		int nDoPause=0 ; // if any control gets used we do a quick pause to make the rate of change a bit more consistent, not as frame-rate dependent
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_PGUP))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift)
+				m_flGoggleZPos-=1.0 ;
+			else
+				if(m_nKeyDown_Ctrl)
+					m_flGoggleZPos-=0.01 ;
+				else
+					m_flGoggleZPos-=0.1 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_PGDOWN))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift)
+				m_flGoggleZPos+=1.0 ;
+			else
+				if(m_nKeyDown_Ctrl)
+					m_flGoggleZPos+=0.01 ;
+				else
+					m_flGoggleZPos+=0.1 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_HOME))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift)
+				m_flGoggleXGap-=0.1 ;
+			else
+				if(m_nKeyDown_Ctrl)
+					m_flGoggleXGap-=0.001 ;
+				else
+					m_flGoggleXGap-=0.01 ;
+
+			if(m_flGoggleXGap<0)
+				m_flGoggleXGap=0 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_END))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift)
+				m_flGoggleXGap+=0.1 ;
+			else
+				if(m_nKeyDown_Ctrl)
+					m_flGoggleXGap+=0.001 ;
+				else
+					m_flGoggleXGap+=0.01 ;
+
+			if(m_flGoggleXGap<0)
+				m_flGoggleXGap=0 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_UP))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+				m_flGoggleYScale=1.0 ;
+			else
+				if(m_nKeyDown_Shift)
+					m_flGoggleYScale+=0.002 ;
+				else
+					if(m_nKeyDown_Ctrl)
+						m_flGoggleYScale+=0.00002 ;
+					else
+						m_flGoggleYScale+=0.0002 ;
+
+				if(m_flGoggleYScale<0)
+					m_flGoggleYScale=0 ;
+
+				CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_DOWN))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+				m_flGoggleYScale=1.0 ;
+			else
+				if(m_nKeyDown_Shift)
+					m_flGoggleYScale-=0.002 ;
+				else
+					if(m_nKeyDown_Ctrl)
+						m_flGoggleYScale-=0.00002 ;
+					else
+						m_flGoggleYScale-=0.0002 ;
+
+			if(m_flGoggleYScale<0)
+				m_flGoggleYScale=0 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_LEFT))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+				m_flGoggleXScale=1.0 ;
+			else
+				if(m_nKeyDown_Shift)
+					m_flGoggleXScale+=0.002 ;
+				else
+					if(m_nKeyDown_Ctrl)
+						m_flGoggleXScale+=0.00002 ;
+					else
+						m_flGoggleXScale+=0.0002 ;
+
+			if(m_flGoggleXScale<0)
+				m_flGoggleXScale=0 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		if(m_pKeyboard->isKeyDown(OIS::KC_RIGHT))
+		{
+			nDoPause=1 ;
+
+			if(m_nKeyDown_Shift && m_nKeyDown_Ctrl)
+				m_flGoggleXScale=1.0 ;
+			else
+				if(m_nKeyDown_Shift)
+					m_flGoggleXScale-=0.002 ;
+				else
+					if(m_nKeyDown_Ctrl)
+						m_flGoggleXScale-=0.00002 ;
+					else
+						m_flGoggleXScale-=0.0002 ;
+
+			if(m_flGoggleXScale<0)
+				m_flGoggleXScale=0 ;
+
+			CreateGogglesTestImage() ;
+		}
+
+		
+
+		if(nDoPause) Sleep(20) ; // pause makes rate more consisent, less frame rate dependent.
+
+	}// end test image controls
+
+	
+
+	//
+	//
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// flashlight
+	if(m_pKeyboard->isKeyDown(OIS::KC_F))
+	{
+		if(m_nKeyToggle[OIS::KC_F]==0)
+		{
+			m_nKeyToggle[OIS::KC_F]=1 ; // toggle to stop key repeating
+			m_nFlashLight=1-m_nFlashLight ;
+			m_nDebugA=m_nFlashLight ;
+			//OFBug.MessageInt(m_nToggle) ;
+		}
+	}
+	else
+		m_nKeyToggle[OIS::KC_F]=0 ;
+
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_J))
+	{
+		if(m_nJumpToggle==0)
+		{
+			m_nJumpToggle=1 ;
+
+
+			m_nJumpVal++ ;
+			if(m_nJumpVal>=m_Q3Map->m_nLightMax)
+				m_nJumpVal=0 ;
+
+			//m_flDebug0=m_nJumpVal ;
+			
+			
+			//m_nJumpVal=12 ; // for now always jump to light 0
+			//m_pCamera->setPosition(m_Q3Map->m_pLight[m_nJumpVal].Position[0], m_Q3Map->m_pLight[m_nJumpVal].Position[1], m_Q3Map->m_pLight[m_nJumpVal].Position[2]) ;
+			//m_nJumpVal=13 ;
+			//m_pCamera->lookAt(Vector3(m_Q3Map->m_pLight[m_nJumpVal].Position[0], m_Q3Map->m_pLight[m_nJumpVal].Position[1], m_Q3Map->m_pLight[m_nJumpVal].Position[2]));
+			
+			//m_pCamera->setPosition(166, 222, -111) ;
+			//m_pCamera->setDirection(0.707, 0, -0.707) ;
+
+			//m_pCamera->setPosition(m_Q3Map->m_pLight[0].Position[0], m_Q3Map->m_pLight[0].Position[1], m_Q3Map->m_pLight[0].Position[2]) ;
+			//m_pCamera->setDirection(m_Q3Map->m_pLight[0].Direction[0], m_Q3Map->m_pLight[0].Direction[1], m_Q3Map->m_pLight[0].Direction[2]) ;
+			//m_pCamera->setFOVy( Degree(m_Q3Map->m_pLight[0].Angle ) ) ;
+
+			//m_pCamera->setDirection(m_pLight[m_nJumpVal].Direction[0], m_pLight[m_nJumpVal].Direction[1], m_pLight[m_nJumpVal].Direction[2]) ;
+			// 880 120 -340
+			//m_pCamera->lookAt(Vector3(880,120,-340));
+			//m_pCamera->lookAt(Vector3(915,155,-340));
+
+
+			m_pCamera->setPosition(600, 200, -250) ;
+			//m_pCamera->setDirection(1.0, 0.0, 0.0) ;
+			m_pCamera->lookAt(700, 200, -450);
+
+			
+
+		}
+	}
+	else
+		m_nJumpToggle=0 ;
+	
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_L))
+	{
+		if(m_nLoadToggle==0)
+		{
+			UnloadMap(false) ;
+			nMap++ ;
+			LoadMap() ;
+			//m_nLoadToggle=1 ;
+		}
+	}
+	else
+		m_nLoadToggle=0 ;
+
+
+		// generic toggle for debugging
+	if(m_pKeyboard->isKeyDown(OIS::KC_M))
+	{
+		if(m_nKeyToggle[OIS::KC_M]==0)
+		{
+			m_nKeyToggle[OIS::KC_M]=1 ; // toggle to stop key repeating
+
+			m_nDisplayInfoMode++ ;
+			if(m_nDisplayInfoMode==9)
+				m_nDisplayInfoMode=0 ;
+
+
+
+		}
+	}
+	else
+		m_nKeyToggle[OIS::KC_M]=0 ;
+
+
+
+
+
+	//if(m_pKeyboard->isKeyDown(OIS::KC_K)) m_nVideoRestart=1 ;
+
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_P))
+	{
+		if(m_nPortalToggle==0)
+		{
+			m_nPortalState=1-m_nPortalState ;
+			m_nPortalToggle=1 ;
+		}
+	}
+	else
+		m_nPortalToggle=0 ;
+
+	if(m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
+	{
+			m_bShutDownOgre = true;
+	}
+
+}
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+//shutdown
+// the dynamic memory deletes are all safe, so it's ok to try and delete them even if they don't exist.
+void OgreFramework::UnloadMap(bool bShutdown)
+{	
+
+	//if(!bShutdown) DestroyRTTAssets() ;
+
+	//if(ResourceGroupManager::getSingleton().isResourceGroupLoaded("Raw Bsp"))
+	//	ResourceGroupManager::getSingleton().clearResourceGroup("Raw Bsp") ; 
+
+
+	// only do if there was a definitely a map loaded.
+	if(m_nMapLoaded)
+	{
+		char chSceneNodeName[1024] ;
+		// make sure all the zone nodes are re-attached to the root node or they won't get deleted
+		for(int nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+		{
+			// Opaque nodes
+			if(m_nOpaqueNodeUsed[nZone]) // only do this if the node actually exists
+			{
+				if(!m_pOpaqueNode[nZone]->isInSceneGraph())
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
+
+				sprintf(chSceneNodeName, "Opaque%05i", nZone) ;
+				m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+			}
+
+			// Trans nodes
+			if(m_nTransNodeUsed[nZone]) // only do this if the node actually exists
+			{
+				if(!m_pTransNode[nZone]->isInSceneGraph())
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
+
+				sprintf(chSceneNodeName, "Trans%05i", nZone) ;
+				m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+			}
+
+			// Lamp nodes
+			if(m_nLampNodeUsed[nZone]) // only do this if the node actually exists
+			{
+				if(!m_pLampNode[nZone]->isInSceneGraph())
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
+
+				sprintf(chSceneNodeName, "Lamp%05i", nZone) ;
+				m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+			}
+
+			// Glow nodes
+			if(m_nGlowNodeUsed[nZone]) // only do this if the node actually exists
+			{
+				if(!m_pGlowNode[nZone]->isInSceneGraph())
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
+
+				sprintf(chSceneNodeName, "Glow%05i", nZone) ;
+				m_pSceneMgr->getRootSceneNode()->removeAndDestroyChild(chSceneNodeName) ;
+
+			}
+
+		}
+
+
+		// reattach all entity scenenodes.
+		int nLoop=0 ;
+//		int nSubMesh=0 ;
+//		int nMaxSubMesh=0 ;
+		for(nLoop=0 ; nLoop<m_nMaxEntity ; nLoop++)
+			m_pSceneMgr->getRootSceneNode()->addChild(m_pEntityInfo[nLoop].pMasterNode) ;
+
+	}// end if map loaded
+
+
+	// free ogre stuff
+	//Ogre::ResourceGroupManager::getSingleton().clearResourceGroup(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
+
+	//Ogre::ResourcePtr RTT=Ogre::TextureManager::getSingleton().getByName("RttTex") ;
+	//Ogre::TextureManager::getSingleton().remove(RTT) ;
+	
+	//RTT_Texture->unload() ;
+
+	
+
+
+	
+	
+
+	//m_pSceneMgr->clearScene() ;
+	m_pSceneMgr->getRootSceneNode()->removeAndDestroyAllChildren() ; // destroy all scenenodes
+	
+	m_pSceneMgr->destroyAllEntities() ;
+	m_pSceneMgr->destroyAllLights() ;
+	m_pSceneMgr->destroyAllManualObjects() ;
+	
+
+	/*
+	// unload all the meshes
+	int nMaxMesh=m_nZoneMOStart[m_Q3Map->m_nMaxZone] ;
+	int nMesh=0 ;
+	for(nMesh=0 ; nMesh<nMaxMesh ; nMesh++)
+	{
+		m_pSceneMgr->destroyEntity(m_pZoneEntity[nMesh]) ;
+		//m_pZoneMesh[nMesh]->cleanupDictionary() ;
+		//m_pZoneMesh[nMesh]->unload() ;
+
+
+	}
+	*/
+	
+	MeshManager::getSingleton().removeAll() ; // this destroys all the meshes
+
+	
+
+	//OFBug.MessageInt(333) ;
+	//Ogre::TextureManager::getSingleton().unloadAll() ;
+	//Ogre::TextureManager::getSingleton().removeAll() ;
+	
+	//Ogre::MaterialManager::getSingleton().unloadAll() ;
+	//Ogre::MaterialManager::getSingleton().removeAll() ;
+
+	
+
+
+
+	//SetupResourceLocations() ;
+
+	// delete our array of Zone group manual objects 
+	//CHECKDELETE_ARRAY( m_pZoneMO ) ;
+	CHECKDELETE_ARRAY( m_pZoneMesh, NEW_CHECK_m_pZoneMesh ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntity, NEW_CHECK_m_pZoneEntity  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterialType, NEW_CHECK_m_pZoneEntityMaterialType  ) ; 
+
+
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Shadow, NEW_CHECK_m_pZoneEntityMaterial_Shadow  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeFront, NEW_CHECK_m_pZoneEntityMaterial_ShadeFront  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeBack, NEW_CHECK_m_pZoneEntityMaterial_ShadeBack  ) ; 
+
+	int nPTex=0 ;
+	for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+	{
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Base[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Base  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Fast[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Fast  ) ; 
+	}
+
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Black, NEW_CHECK_m_pZoneEntityMaterial_Black  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShColour, NEW_CHECK_m_pZoneEntityMaterial_DfShColour  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShPosition, NEW_CHECK_m_pZoneEntityMaterial_DfShPosition  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShDiffuse, NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse  ) ; 
+	//CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DSNormal ) ;
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShFuncTNB, NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShSpecular, NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular  ) ; 
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShEmissive, NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive  ) ; 
+	//CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShData ) ;
+	CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShMix, NEW_CHECK_m_pZoneEntityMaterial_DfShMix  ) ; 
+
+	////////////////////////////////////////////////////////
+	CHECKDELETE_ARRAY( m_pEntityInfo, NEW_CHECK_m_pEntityInfo  ) ; 
+	CHECKDELETE_ARRAY( m_pVisibleEntity, NEW_CHECK_m_pVisibleEntity  ) ;
+	CHECKDELETE_ARRAY( m_pFrustumEntity, NEW_CHECK_m_pFrustumEntity  ) ;
+
+
+	// was leaking before, but this seems to have fixed things.
+	Ogre::ResourceGroupManager::getSingleton().clearResourceGroup(ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ;
+
+	// delete our debug light manualobjects/zones
+//	CHECKDELETE_ARRAY( m_pLightMO ) ;
+
+//	CHECKDELETE_ARRAY( m_pPortalMO ) ;
+//	CHECKDELETE_ARRAY( m_pPortalNode ) ;
+
+	// free our dynamic memory
+	if(m_Q3Map)
+	{
+		m_Q3Map->~Q3Map() ;		// get rid of all the m_Q3Map stuff
+		CHECKDELETE_POINTER( m_Q3Map, NEW_CHECK_m_Q3Map) ;  
+		m_Q3Map=NULL ;
+	}
+
+	if(m_bRawBspFileIsLoaded) 
+	{
+		//m_pRawBspFile->unload() ;
+		CHECKDELETE_ARRAY(m_pRawBspFile, NEW_CHECK_m_pRawBspFile ) ;  
+		m_bRawBspFileIsLoaded=false ;
+	}
+
+	// indicate that there is no map.
+	m_nMapLoaded=0 ;
+
+	
+
+	
+	int nCheck=0 ;
+	for(nCheck=0 ; nCheck<MAX_NEW_CHECK ; nCheck++)
+	if(m_nNewCheck[nCheck]!=0)
+	{
+		sprintf(m_chBug, "MEMORY LEAK: NewCheck %i, NewCount %i", nCheck, m_nNewCheck[nCheck]) ;
+		m_pLog->logMessage(m_chBug) ;
+	}
+
+
+		//OFBug.MessageInt(333) ;
+		//Sleep(50) ;
+}
+
+
+
+
+
+
+
+
+ /***********************************************************************************************************\
+                                               
+                                                 LOAD MAP 
+                                                
+ \***********************************************************************************************************/
+
+
+
+
+int OgreFramework::LoadMap(void)
+{	
+	m_pLog->logMessage("LoadMap.") ;
+
+
+
+	ZeroMemory((void*)m_nKeyToggle, sizeof(m_nKeyToggle)) ; // good place to clear the keytoggle just in case
+
+	m_pLog->logMessage("Pre InitAllResourceGroups.") ;
+	Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();	
+	m_pLog->logMessage("Post InitAllResourceGroups.") ;
+
+	// setup the clear material
+	pClearMaterial=MaterialManager::getSingleton().getByName("Clear") ;
+
+	
+	//CreateRTTAssets() ;
+
+
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+		m_pDebugOverlay = OverlayManager::getSingleton().getByName("Core/DebugOverlay");
+		m_pDebugOverlay->show();
+
+		//m_MapName="test04e.bsp" ;
+		//m_MapName="test04g.bsp" ;
+		//m_MapName="test03f.bsp" ;
+
+		//m_MapName="testnew00a.bsp" ;
+		//m_MapName="test04gNew.bsp" ;
+
+		//m_MapName="test10a.bsp" ;
+		m_MapName="testmap06.bsp" ;
+		
+
+		//////////////////////////////////////////////////////////////////////////////////////////////////
+		// Load the file, get the data
+	
+
+
+		// open the stream to the bsp
+		Ogre::DataStreamPtr stream = Ogre::ResourceGroupManager::getSingleton().openResource(m_MapName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, true);
+
+		// create memory to hold the bsp
+		size_t Size = stream->size() ;
+		m_pRawBspFile= new char[Size] ;
+		if( m_pRawBspFile==NULL) 
+			{ m_pLog->logMessage("Error loading map: Initial load out of memory.")			; UnloadMap(false) ; return 0 ; }
+		else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pRawBspFile]++ ; }
+
+		// stream bsp into memory
+		stream->read((void*)m_pRawBspFile, Size) ;
+
+		// close the stream, don't need it anymore
+		stream->close() ;
+		
+		// indicate that the raw bsp is loaded
+		m_bRawBspFileIsLoaded=true ;
+
+
+
+	
+
+		
+		//////////////////////////////////////////////////////////////////////////////////////////////////
+		// Setup Q3Map
+
+		m_Q3Map=new Q3Map();
+		if(m_Q3Map==NULL) 
+			{ m_pLog->logMessage("Error loading map: New Map.")			; UnloadMap(false) ; return 0 ; }
+		else
+			{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_Q3Map]++ ; }
+
+
+
+		m_pLog->logMessage("pre ParseMap") ;
+
+		// process the bsp, log errors and fail if needed.
+		switch(m_Q3Map->ParseAndTriangulateMap( m_pRawBspFile, Size ) )
+		{
+			case ERROR_ParseMap:						m_pLog->logMessage("Error loading map: Parse Map.") ;							UnloadMap(false) ; return 0 ;
+			case ERROR_ParseEntities:				m_pLog->logMessage("Error loading map: Parse Entities.") ;				UnloadMap(false) ; return 0 ;
+			case ERROR_AllocateVertex:			m_pLog->logMessage("Error loading map: Allocate Vertex.") ;				UnloadMap(false) ; return 0 ;
+			case ERROR_AllocateTriangle:		m_pLog->logMessage("Error loading map: Allocate Triangle.") ;			UnloadMap(false) ; return 0 ;
+			case ERROR_InitializeFaces:			m_pLog->logMessage("Error loading map: Initialize Faces") ;				UnloadMap(false) ; return 0 ;
+			case ERROR_ConvertFaces:				m_pLog->logMessage("Error loading map: Convert Faces.") ;					UnloadMap(false) ; return 0 ;
+			case ERROR_ConvertPatches:			m_pLog->logMessage("Error loading map: Convert Patches.") ;				UnloadMap(false) ; return 0 ;
+			case ERROR_ConvertTexLamp:			m_pLog->logMessage("Error loading map: Convert TexLamps.") ;			UnloadMap(false) ; return 0 ;
+			case ERROR_ConvertLamps:				m_pLog->logMessage("Error loading map: Convert Lamps.") ;					UnloadMap(false) ; return 0 ;
+			case ERROR_ConvertLampGlow:			m_pLog->logMessage("Error loading map: Convert Lamp Glow.") ;			UnloadMap(false) ; return 0 ;
+			case ERROR_ConvertLightGlow:		m_pLog->logMessage("Error loading map: Convert Light Glow.") ;		UnloadMap(false) ; return 0 ;
+			case ERROR_AssignTriangles:			m_pLog->logMessage("Error loading map: Assign Triangles") ;				UnloadMap(false) ; return 0 ;
+			case ERROR_SortTriangles:				m_pLog->logMessage("Error loading map: Sort Triangles") ;					UnloadMap(false) ; return 0 ;
+			case ERROR_SetupTransTextures:	m_pLog->logMessage("Error loading map: Setup Trans Textures") ;		UnloadMap(false) ; return 0 ;
+			case ERROR_SortGroups:					m_pLog->logMessage("Error loading map: Sort Groups") ;						UnloadMap(false) ; return 0 ;
+		}
+
+		m_pLog->logMessage("post ParseMap") ;
+
+		//////////////////////////////////////////////////////////////////////////////////////////////////
+		// use the triangles to build our zone/texture manualObjects, which make up the map
+		if(!ConstructMapFromTriangles()){ m_pLog->logMessage("Error loading map: Construct Map") ;		UnloadMap(false) ; return 0 ; }
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		// delete all the stuff that was only needed for parsing the bsp and converting it into manaulObjects.
+		m_Q3Map->FreeParseMem() ;
+	
+
+
+		
+
+		
+		
+		//////////////////////////////////////////////////////////////////////////////////////////////////
+		// Create the scenenodes for the zones and attach the manualObjects
+
+		int nZone=0 ;
+		char chSceneNodeName[1024] ;
+		int nMO=0 ;
+		int nZGStart=0 ;
+		int nZGEnd=0 ;
+
+		char chMessage[1024] ;
+		sprintf(chMessage, "Max Zones %i", m_Q3Map->m_nMaxZone) ; m_pLog->logMessage(chMessage) ;
+		for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+		{
+			//sprintf(chMessage, "Zone %i Top", nZone) ; m_pLog->logMessage(chMessage) ;
+
+
+			// create Opaque node if needed
+			if(m_nOpaqueNodeUsed[nZone])
+			{
+				sprintf(chSceneNodeName, "Opaque%05i", nZone) ;
+				m_pOpaqueNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+			}
+
+			// create Trans node if needed
+			if(m_nTransNodeUsed[nZone])
+			{
+				sprintf(chSceneNodeName, "Trans%05i", nZone) ;
+				m_pTransNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+			}
+
+			// create Lamp node if needed
+			if(m_nLampNodeUsed[nZone])
+			{
+				sprintf(chSceneNodeName, "Lamp%05i", nZone) ;
+				m_pLampNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+			}
+
+			// create Glow node if needed
+			if(m_nGlowNodeUsed[nZone])
+			{
+				sprintf(chSceneNodeName, "Glow%05i", nZone) ;
+				m_pGlowNode[nZone]=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName) ;
+			}
+
+			// get start and end of this zone's batches.  
+			// If there's none, the start and end will be the same. (don't have to worry about checking for m_pZoneMO[nZone]==NULL)
+			nZGStart	=	m_nZoneMOStart[nZone] ;
+			nZGEnd		=	m_nZoneMOStart[nZone+1] ;
+			
+			//sprintf(chMessage, "  Zone %i, ZGStart %i, ZGEnd %i", nZone, nZGStart, nZGEnd) ; m_pLog->logMessage(chMessage) ;
+
+			for(nMO=nZGStart ; nMO<nZGEnd ; nMO++)
+			{
+				//sprintf(chMessage, "    Zone %i, nMO %i", nZone, nMO) ; m_pLog->logMessage(chMessage) ;
+
+				// attach the entity to the appropriate node
+
+				if(m_pZoneEntityMaterialType[nMO]==MAT_OPAQUE)
+					m_pOpaqueNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+				else
+				if(m_pZoneEntityMaterialType[nMO]==MAT_GEL)
+					m_pTransNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+				else
+				if(m_pZoneEntityMaterialType[nMO]==MAT_LAMP)
+					m_pLampNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+				else
+				if(m_pZoneEntityMaterialType[nMO]==MAT_GLOW)
+					m_pGlowNode[nZone]->attachObject( m_pZoneEntity[nMO] ) ;
+			}
+
+		}
+
+
+		// add the game entities
+		if(!SetupGameEntities()) { m_pLog->logMessage("Error loading map: Setup Entities") ;		UnloadMap(false) ; return 0 ; }
+
+
+		// prior to the first frame, all zone scenenodes are detached.
+		m_pSceneMgr->getRootSceneNode()->removeAllChildren() ;
+
+		//////////////////////////////////////////////////////////////////////////////////////////////////////
+		// Setup the lights
+
+
+
+		
+		initLight() ; 
+
+		//if(m_nDebugLightBox)
+		//	AddLightCullingBoxes() ;
+
+
+		//if(m_nPortalDebug)
+		//	AddPortalBoxes() ;
+
+
+		///////////////////////////////////////////////////////////////////////////////////////////////////
+		// misc finalization of the map
+
+		m_nCameraZone=-1 ; // indicate that we need to look up the zone the player is in.
+		m_nCameraZoneL=-1 ;
+		m_nCameraZoneR=-1 ;
+
+		m_nMapLoaded=1 ; // map was loaded ok
+
+
+
+		// set the camera's start position here.
+		// I tried setting it during startup, but for some strange reason it didn't work IF the camera was in a zone 
+		// but was ok if the camera started outside a zone.  Bit of a mystery... but it makes more sense to set it here anyway.
+		m_pCamera->setPosition(Vector3(0, 0, 0));
+
+		if(m_Q3Map->m_nLightMax>0) // make sure there's at least one light before we point to it!
+			m_pCamera->lookAt(Ogre::Vector3(m_Q3Map->m_pLight[0].Position[0], m_Q3Map->m_pLight[0].Position[1], m_Q3Map->m_pLight[0].Position[2])) ;
+
+
+		
+
+		if(m_nGoggleMode==GOGGLE_MODE_TEST)
+				CreateGogglesTestImage() ; // create the test goggles
+			else
+				if(m_nGoggleMode==GOGGLE_MODE_ON)
+					CreateGoggles() ; // create the stereo goggles
+
+
+		SetupParticles() ;
+
+
+		m_pLog->logMessage("LoadMap bottom.") ;
+
+		// reset the game timer
+		m_GameTime=0.0 ;
+		m_nFrame=0 ;
+
+
+
+		//OFBug.MessageInt(m_nNewCount) ;
+
+		return 1 ;
+}
+
+//''
+int OgreFramework::SetupParticles()
+{
+			ParticleSystem::setDefaultNonVisibleUpdateTimeout(5);  // set nonvisible timeout
+
+		
+
+    // create some nice fireworks and place it at the origin
+    //m_ps = m_pSceneMgr->createParticleSystem("Fireworks", "particle/fallspark00");
+		m_ps = m_pSceneMgr->createParticleSystem("Fireworks", "particle/spark00");
+		m_pParticleNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("ParticleNode") ;
+		m_pParticleNode->attachObject(m_ps) ;
+
+		//m_pParticleNode->setPosition(360.0f, 360.0f, -860.0f) ;
+		m_pParticleNode->setPosition(586.0f, 228.0f, -520.0f) ;
+
+
+	return 1 ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// take the sorted list of triangles and contruct our Zone manualObjects array, m_pZoneMO, etc
+// and setup all the materials.
+int OgreFramework::ConstructMapFromTriangles(void)
+{
+
+
+	int nVert=0 ;
+	int nMaxVertex=0 ;
+	
+	float flPosX=0.0f ;
+	float flPosY=0.0f ;
+	float flPosZ=0.0f ;
+	float	flNormX=0.0f ;
+	float	flNormY=0.0f ;
+	float	flNormZ=0.0f ;
+	float flTexU=0.0f ;
+	float flTexV=0.0f ;
+
+	float flLampPosX=0.0f ;
+	float flLampPosY=0.0f ;
+	float flLampPosZ=0.0f ;
+	float flLampBrightness=0.0f ;
+	float flLampR=0.0f ;
+	float flLampG=0.0f ;
+	float flLampB=0.0f ;
+
+	int nVertA=0 ;
+	int nVertB=0 ;
+	int nVertC=0 ;
+
+	char chMessage[1024] ;
+
+	int nZone=0 ;
+	char chManualName[1024] ; // name for manual objects we create
+	char chMeshName[1024] ;
+
+	int nTriangle=0 ;
+//	int nStart=0 ;
+	int nEnd=0 ;
+	int nMaterial=0 ;
+	int nGroup=0 ;
+	int nTri=0 ;
+	int nPos=0 ;
+
+	ZeroMemory((void*)m_nOpaqueNodeUsed, sizeof(m_nOpaqueNodeUsed)) ; // set all as unused
+	ZeroMemory((void*)m_nTransNodeUsed, sizeof(m_nTransNodeUsed)) ; // set all as unused
+	ZeroMemory((void*)m_nLampNodeUsed, sizeof(m_nLampNodeUsed)) ; // set all as unused
+	ZeroMemory((void*)m_nGlowNodeUsed, sizeof(m_nGlowNodeUsed)) ; // set all as unused
+	
+	char chMaterial_Base[1024] ;
+	MaterialPtr pMaterial_Base ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+	
+	char chMaterial_Fast[1024] ;
+	MaterialPtr pMaterial_Fast ; // faster version of the base, mainly non-coloured shadowning.
+
+	char chMaterial_Black[1024] ;
+	MaterialPtr pMaterial_Black ; // just plain black, or black with alpha testing.
+
+	char chMaterial_DfShColour[1024] ;
+	MaterialPtr pMaterial_DfShColour ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+	
+
+	char chMaterial_Shadow[1024] ;
+	MaterialPtr pMaterial_Shadow ;
+
+	char chMaterial_ShadeFront[1024] ;
+	MaterialPtr pMaterial_ShadeFront ;
+
+	char chMaterial_ShadeBack[1024] ;
+	MaterialPtr pMaterial_ShadeBack ;
+
+	char chMaterial_DfShPosition[1024] ;
+	MaterialPtr pMaterial_DfShPosition ;
+	
+	char chMaterial_DfShDiffuse[1024] ;
+	MaterialPtr pMaterial_DfShDiffuse ;
+	
+	//char chMaterial_DSNormal[1024] ;
+	//MaterialPtr pMaterial_DSNormal ;
+	
+	char chMaterial_DfShFuncTNB[1024] ;
+	MaterialPtr pMaterial_DfShFuncTNB ;
+
+	char chMaterial_DfShSpecular[1024] ;
+	MaterialPtr pMaterial_DfShSpecular ;
+
+	char chMaterial_DfShEmissive[1024] ;
+	MaterialPtr pMaterial_DfShEmissive ;
+
+	//char chMaterial_DfShData[1024] ;
+	//MaterialPtr pMaterial_DfShData ;
+
+	char chMaterial_DfShMix[1024] ;
+	MaterialPtr pMaterial_DfShMix ;
+
+	char chCompare[1024] ;
+
+	// for calculating bounds of mesh
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+	float flMaxZ=0.0f ;
+//	float flMidX=0.0f ;
+//	float flMidY=0.0f ;
+//	float flMidZ=0.0f ;
+	float flDisX=0.0f ;
+	float flDisY=0.0f ;
+	float flDisZ=0.0f ;
+	float flRadius=0.0f ;
+	AxisAlignedBox AABB ;
+	unsigned short src, dest; // for tangent vectors
+
+
+	// Work out how many manual objects we are going to need.  We need one for every group within every material within every zone.
+	// Groups tend to all be 0 except for transparent triangles which have different groups within the same material/zone,
+	// due to the need to sort and render transparent things in a specific depth order relative to the camera.
+
+
+	int nMOCount=0 ;
+	nMaterial=-1 ;
+	nZone=-1 ;
+	nGroup=-1 ;
+
+	// loop through all triangles to count how many manual objects we'll need.
+	for(nTri=0 ; nTri<m_Q3Map->m_nTriangleMax ; nTri++)
+	{
+		
+		if(m_Q3Map->m_pTriangle[nTri].Zone!=nZone) // found a new zone
+		{
+			nZone=m_Q3Map->m_pTriangle[nTri].Zone ; 
+			nMaterial=m_Q3Map->m_pTriangle[nTri].Texture ;
+			nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
+			nMOCount++ ;
+		}
+		else
+			if(m_Q3Map->m_pTriangle[nTri].Texture!=nMaterial) // found a new material within the current zone
+			{
+				nMaterial=m_Q3Map->m_pTriangle[nTri].Texture ;
+				nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
+				nMOCount++ ;
+			}
+			else
+				if(m_Q3Map->m_pTriangle[nTri].Group!=nGroup) // found a new group within the current material within the current zone
+				{
+					nGroup=m_Q3Map->m_pTriangle[nTri].Group ;
+					nMOCount++ ;
+				}
+
+	}// end for tri
+	
+
+
+	// create the manualobject array for our zones and materials
+	m_pZoneMO = new Ogre::ManualObject*[nMOCount] ;
+	if(m_pZoneMO==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneMO]++ ; }
+
+	m_pZoneMesh = new Ogre::MeshPtr[nMOCount] ;
+	if(m_pZoneMesh==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneMesh]++ ; }
+
+	// our entities for the meshes
+	m_pZoneEntity = new Ogre::Entity*[nMOCount] ;
+	if(m_pZoneEntity==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntity]++ ; }
+
+	// need to keep track of which entities are transparent
+	m_pZoneEntityMaterialType = new int[nMOCount] ;
+	if(m_pZoneEntityMaterialType==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterialType]++ ; }
+	ZeroMemory((void*)m_pZoneEntityMaterialType, nMOCount*sizeof(int)) ; // set all as non-transparent
+
+
+	int nPTex=0 ;
+	for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+	{
+		// our base materials for the meshes
+		m_pZoneEntityMaterial_Base[nPTex] = new Ogre::MaterialPtr[nMOCount] ;
+		if(m_pZoneEntityMaterial_Base[nPTex]==NULL) 
+			return 0 ; // fail, out of mem
+		else
+			{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Base]++ ; }
+
+		// our fast materials for the meshes
+		m_pZoneEntityMaterial_Fast[nPTex] = new Ogre::MaterialPtr[nMOCount] ;
+		if(m_pZoneEntityMaterial_Fast[nPTex]==NULL) 
+			return 0 ; // fail, out of mem
+		else
+			{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Fast]++ ; }
+	}
+
+	// our black materials for the meshes
+	m_pZoneEntityMaterial_Black = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_Black==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Black]++ ; }
+
+	// our base materials for the meshes
+	m_pZoneEntityMaterial_DfShColour = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShColour==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShColour]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_Shadow = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_Shadow==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_Shadow]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_ShadeFront = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_ShadeFront==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_ShadeFront]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_ShadeBack = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_ShadeBack==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_ShadeBack]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_DfShPosition = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShPosition==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShPosition]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_DfShDiffuse = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShDiffuse==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse]++ ; }
+
+	// materials for the meshes
+	//m_pZoneEntityMaterial_DSNormal = new Ogre::MaterialPtr[nMOCount] ;
+	//if(m_pZoneEntityMaterial_DSNormal==NULL) return 0 ; // fail, out of mem
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_DfShFuncTNB = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShFuncTNB==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_DfShSpecular = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShSpecular==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular]++ ; }
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_DfShEmissive = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShEmissive==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive]++ ; }
+
+
+	// materials for the meshes
+	//m_pZoneEntityMaterial_DfShData = new Ogre::MaterialPtr[nMOCount] ;
+	//if(m_pZoneEntityMaterial_DfShData==NULL) return 0 ; // fail, out of mem
+
+	// materials for the meshes
+	m_pZoneEntityMaterial_DfShMix = new Ogre::MaterialPtr[nMOCount] ;
+	if(m_pZoneEntityMaterial_DfShMix==NULL) 
+		return 0 ; // fail, out of mem
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pZoneEntityMaterial_DfShMix]++ ; }
+
+
+	// memory for keeping track of re-assigned verts, since we only add verts to a manualobject if they are needed, we don't add every vertex
+	int* pVertIndex = new int [m_Q3Map->m_nVertexMax] ; // at most, there can be m_Q3Map->m_nVertexMax verts in a zone if the map is one big subzone.
+	if(pVertIndex==NULL) //{ CHECKDELETE_ARRAY( m_pZoneMO ) ; return 0 ; } // fail, out of mem
+		return 0 ;
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_pVertIndex]++ ; }
+
+
+
+
+
+	// go through all the zones and create their manualobjects in m_pZoneMO, one for each material
+	int nMOIndex=0 ;
+	for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+	{
+		m_nZoneTriangleCount[nZone]=0 ; // just for our stats
+
+
+		m_nZoneMOStart[nZone]=nMOIndex ; // record where we start from.
+
+		// because the triangles have been sorted in order of zone, if there are any triangles in this zone
+		// then nTriangle will already be on the first example.  However it could be there is a zone that contains
+		// no triangles.  If we have such an empty zone, we don't create any manual object for it and set its pointer
+		// to NULL.
+
+		if(m_Q3Map->m_pTriangle[nTriangle].Zone!=nZone)
+		{
+			m_pZoneMO[nMOIndex]=NULL ;
+			continue ;
+			//break ;
+		}
+
+		
+
+
+		// scan through all triangles in this zone
+		while((nTriangle<m_Q3Map->m_nTriangleMax) && (m_Q3Map->m_pTriangle[nTriangle].Zone==nZone))
+		{
+			
+
+			
+			//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+			//
+			// start adding a begin/end block of all triangles in a zone with the same material/group
+			//
+			//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+			
+			nMaterial=m_Q3Map->m_pTriangle[nTriangle].Texture ;
+			nGroup=m_Q3Map->m_pTriangle[nTriangle].Group ;
+			
+
+			
+
+			// create the zone's manualobject
+			sprintf(chManualName, "ZoneMO_%04i_%04i_%05i", nZone, nMaterial, nTriangle) ;
+			m_pZoneMO[nMOIndex]=m_pSceneMgr->createManualObject(chManualName) ;
+			
+			
+
+			// scan forward to find the end of this block of triangles with the same texture and group
+			nEnd=nTriangle+1 ;
+			while(
+								(nEnd<m_Q3Map->m_nTriangleMax) 
+							&&(m_Q3Map->m_pTriangle[nEnd].Zone==nZone)
+							&&(m_Q3Map->m_pTriangle[nEnd].Texture==nMaterial)
+							&&(m_Q3Map->m_pTriangle[nEnd].Group==nGroup)
+						)
+				nEnd++ ;
+
+			// copy the material name.
+			// q3 texture names are a max of 64 characters ( Q3NAMESIZE ) and may not be null terminated.  They have no extension either.
+			nPos=-1 ;
+			while((++nPos<Q3NAMESIZE) && (m_Q3Map->m_pTexture[nMaterial].name[nPos]!=' ') && (m_Q3Map->m_pTexture[nMaterial].name[nPos]!='\0'))
+				chMaterial_Base[nPos]=m_Q3Map->m_pTexture[nMaterial].name[nPos] ;
+
+			// make sure name is null terminated
+			chMaterial_Base[nPos]='\0' ;
+
+
+
+			//..
+
+			//if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_ShinyGlassPlateTL") ; 
+			//if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_Prototype") ; 
+			//if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_Prototype") ; 
+			if(strcmp(chMaterial_Base, "textures/common/exptex")==0) strcpy(chMaterial_Base, "GEL_DSC_glassred") ; 
+			if(strcmp(chMaterial_Base, "textures/common/exptex2")==0) strcpy(chMaterial_Base, "GEL_GreyGlass") ; 
+			if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "ALPHAPF_DSCE_Prototype") ;
+			//if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
+			//if(strcmp(chMaterial_Base, "textures/common/alphaplate")==0) strcpy(chMaterial_Base, "ALPHAPF_DS_alphaplategreen") ;
+
+
+			
+			// if the material is a lamp material we need to specify either an OpenGl or Direct3D version
+			strcpy(chCompare, chMaterial_Base) ;
+			chCompare[12]='\0' ;
+			if(strcmp("lights/lamp_", chCompare)==0) // material is LAMP 
+			{
+				if(m_IsOpenGL)
+					strcat(chMaterial_Base, "_ogl") ;
+				else
+					strcat(chMaterial_Base, "_d3d") ;
+
+			}
+
+			strcpy(chCompare, chMaterial_Base) ;
+			chCompare[17]='\0' ;
+			if(strcmp("lights/lamp2pass_", chCompare)==0) // material is LAMP, 2 pass version 
+			{
+				if(m_IsOpenGL)
+					strcat(chMaterial_Base, "_ogl") ;
+				else
+					strcat(chMaterial_Base, "_d3d") ;
+			}
+			
+
+
+			// check that this material script exists, if not set to the default
+			pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+			if(pMaterial_Base.isNull())
+			{
+				strcat(chMaterial_Base, " *** MISSING ***") ;
+//				OFBug.LogAddCR(chMaterial_Base) ;
+				
+				//sprintf(chMessage, "Missing material, using default: %s", chMaterial_Base) ;
+				//m_pLog->logMessage(chMessage);
+
+				/*
+				switch(rand()%6)
+				{
+					case 0: strcpy(chMaterial_Base, "OPAQUE_DSC_Plate2x2A") ;					break ;
+					case 1: strcpy(chMaterial_Base, "OPAQUE_DSC_HexColourA") ;				break ;
+					case 2: strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;			break ;
+					case 3: strcpy(chMaterial_Base, "OPAQUE_DSC_FloorA") ;						break ;
+					case 4: strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimUD_A") ;			break ;
+					case 5: strcpy(chMaterial_Base, "OPAQUE_DSCE_TechRadar") ;				break ;
+				}
+				*/
+
+				//strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;	
+
+				//strcpy(chMaterial_Base, "OPAQUE_DSC_Plate2x2A") ;
+				//strcpy(chMaterial_Base, "OPAQUE_DSC_HexColourA") ;
+				//strcpy(chMaterial_Base, "OPAQUE_DSC_SimplePlateB") ;
+				//strcpy(chMaterial_Base, "OPAQUE_DSC_FloorA") ;
+				strcpy(chMaterial_Base, "textures/metaltech/OPAQUE_DSCE_TechRadar") ;
+				//strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimA") ;
+				//strcpy(chMaterial_Base, "OPAQUE_DSCE_WallTrimB") ;
+
+				//strcpy(chMaterial_Base, "Standard_Normal") ;
+				//strcpy(chMaterial_Base, "test") ;
+				//strcpy(chMaterial_Base, "metalN") ;
+				//strcpy(chMaterial_Base, "OPAQUE_DSC_Prototype") ;
+				
+				//strcpy(chMaterial_Base, "textures/common/exptex") ;
+				//strcpy(chMaterial_Base, "metalN_DSNormal") ;
+				//strcpy(chMaterial_Base, "metalN_DfShFuncTNB") ;
+				//strcpy(chMaterial_Base, "metalN_DfShDiffuse") ;
+				//strcpy(chMaterial_Base, "metalN_DfShPosition") ;
+				//strcpy(chMaterial_Base, "metalD") ;
+				//strcpy(chMaterial_Base, "metalR") ;	
+				//strcpy(chMaterial_Base, "WonderShader_Lim3_Fast") ;
+				//strcpy(chMaterial_Base, "reliefMaterial") ;
+				//strcpy(chMaterial_Base, "tute02") ;reliefMaterial
+				//strcpy(chMaterial_Base, "Examples/OffsetMapping/Specular") ;
+				pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+			}
+			else
+//				OFBug.LogAddCR(chMaterial_Base) ;
+
+
+
+			if(nMOIndex==20)
+			{
+				sprintf(m_chBug, "****** %s *******", chMaterial_Base) ;
+				m_pLog->logMessage(m_chBug);
+			}
+
+
+
+
+			// setup whether this material and it's entities are transparent or whatever
+
+			if(strstr(chMaterial_Base, "OPAQUE")!=NULL) // material and its entity are OPAQUE
+			{
+				m_nOpaqueNodeUsed[nZone]=1 ;
+				m_pZoneEntityMaterialType[nMOIndex]=MAT_OPAQUE ; // note that the derived entity will be opaque
+			}
+			else
+			{
+
+				if(strstr(chMaterial_Base, "ALPHAPF")!=NULL) // material and its entity are ALPHAPF
+				{
+					m_nOpaqueNodeUsed[nZone]=1 ;
+					m_pZoneEntityMaterialType[nMOIndex]=MAT_OPAQUE ; // note that the derived entity will be opaque
+				}
+				else
+				{
+
+					if(strstr(chMaterial_Base, "GEL")!=NULL) // material and its entity are GEL
+					{
+						m_nTransNodeUsed[nZone]=1 ;
+						m_pZoneEntityMaterialType[nMOIndex]=MAT_GEL ; // note that the derived entity will be transparent
+					}
+					else
+					{
+
+						strcpy(chCompare, chMaterial_Base) ;
+						chCompare[12]='\0' ;
+						if(strcmp("lights/lamp_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+						{
+							m_nLampNodeUsed[nZone]=1 ;
+							m_pZoneEntityMaterialType[nMOIndex]=MAT_LAMP ; // note that the derived entity will be lamp
+						}
+						else
+						{
+							strcpy(chCompare, chMaterial_Base) ;
+							chCompare[17]='\0' ;
+							if(strcmp("lights/lamp2pass_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+							{
+								m_nLampNodeUsed[nZone]=1 ;
+								m_pZoneEntityMaterialType[nMOIndex]=MAT_LAMP ; // note that the derived entity will be lamp
+							}
+							else
+							{
+
+								if(strstr(chMaterial_Base, "GLOW_")!=NULL) // material and its entity are GLOW
+								{
+									m_nGlowNodeUsed[nZone]=1 ;
+									m_pZoneEntityMaterialType[nMOIndex]=MAT_GLOW ; // note that the derived entity will be glow
+								}
+							}	
+						}					
+					}
+				}
+			}
+
+
+
+
+
+
+			///////////////////////////////////////////////////////////////////////////////////////////////////////
+			//
+			// Setup the different material names and pointers needed for various passes
+			//
+			// Lamps need only one material, pMaterial_Base, which is already assigned above, so it skips all this.
+			//
+			// Glow needs two materials, pMaterial_Base plus pMaterial_DfShColour for the coloured gel deferred pass.
+			// However it's better to make a third, and duplicate the pMaterial_Base to pMaterial_Emissive, since
+			// when glow gets rendered on the Emmisive pass it would be odd to switch to the base material instead
+			// of the emmisive.
+			//
+			// Other objects need multiple materials for various different deferred shading and FX passes
+			
+			if((m_pZoneEntityMaterialType[nMOIndex]!=MAT_LAMP) && (m_pZoneEntityMaterialType[nMOIndex]!=MAT_GLOW))
+			{
+
+				// material for fast shading
+				strcpy(chMaterial_Fast, chMaterial_Base) ;
+				strcat(chMaterial_Fast, "_Fast") ;
+
+				pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+				if(pMaterial_Fast.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_Fast) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_Fast, "Fast") ;
+					pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+				}
+
+				// material for black shading
+				strcpy(chMaterial_Black, chMaterial_Base) ;
+				strcat(chMaterial_Black, "_Black") ;
+				pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+				if(pMaterial_Black.isNull())
+				{
+					// only issue a warning if this is an alpha testing material, others don't need specialized Black materials
+					if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+					{
+						sprintf(chMessage, "Missing material, using default: %s", chMaterial_Black) ;
+						m_pLog->logMessage(chMessage);
+					}
+
+					strcpy(chMaterial_Black, "Black") ;
+					pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+				}
+				
+				// material for shadow casting
+				strcpy(chMaterial_Shadow, chMaterial_Base) ;
+				strcat(chMaterial_Shadow, "_Shadow") ;
+				pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+				if(pMaterial_Shadow.isNull())
+				{
+					strcpy(chMaterial_Shadow, "OPAQUE_Shadow") ;
+					pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+				}
+
+				
+				
+				// material for shadow casting
+				strcpy(chMaterial_ShadeFront, chMaterial_Base) ;
+				strcat(chMaterial_ShadeFront, "_ShadeFront") ;
+				pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+				if(pMaterial_ShadeFront.isNull())
+				{
+					 // standard opaque ShadeFront.  
+					// Transparent surfaces MUST have their own _ShadeFront material or they will not colour light and can interfere with other trans surfaces.
+					strcpy(chMaterial_ShadeFront, "OPAQUE_ShadeFront") ;
+
+					pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+				}
+
+
+				// material for shadow casting
+				strcpy(chMaterial_ShadeBack, chMaterial_Base) ;
+				strcat(chMaterial_ShadeBack, "_ShadeBack") ;
+				pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+				if(pMaterial_ShadeBack.isNull())
+				{
+					 // standard opaque ShadeBack.  
+					// Transparent surfaces MUST have their own _ShadeBack material or they will not colour light and can interfere with other trans surfaces.
+					strcpy(chMaterial_ShadeBack, "OPAQUE_ShadeBack") ;
+
+					pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+				}
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShColour, chMaterial_Base) ;
+				strcat(chMaterial_DfShColour, "_DfShColour") ;
+				pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+				if(pMaterial_DfShColour.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShColour) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShColour, "DfShColour") ;
+					pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+				}
+				
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShPosition, chMaterial_Base) ;
+				strcat(chMaterial_DfShPosition, "_DfShPosition") ;
+				pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+				if(pMaterial_DfShPosition.isNull())
+				{
+					// only issue a warning if this is an alpha testing material, others don't need specialized DfShPosition materials
+					if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+					{
+						sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShPosition) ;
+						m_pLog->logMessage(chMessage);
+					}
+
+					strcpy(chMaterial_DfShPosition, "DfShPosition") ;
+					pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+				}
+				
+				// material for deferred shading
+				strcpy(chMaterial_DfShDiffuse, chMaterial_Base) ;
+				strcat(chMaterial_DfShDiffuse, "_DfShDiffuse") ;
+				pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+				if(pMaterial_DfShDiffuse.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShDiffuse) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShDiffuse, "DfShDiffuse") ;
+					pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+				}
+
+				/*
+				// material for deferred shading // UNUSED
+				strcpy(chMaterial_DSNormal, chMaterial_Base) ;
+				strcat(chMaterial_DSNormal, "_DSNormal") ;
+				pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+				if(pMaterial_DSNormal.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DSNormal) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DSNormal, "DSNormal") ;
+					pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+				}
+				*/
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShFuncTNB, chMaterial_Base) ;
+				strcat(chMaterial_DfShFuncTNB, "_DfShFuncTNB") ;
+				pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+				if(pMaterial_DfShFuncTNB.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShFuncTNB) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShFuncTNB, "DfShFuncTNB") ;
+					pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+				}
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShSpecular, chMaterial_Base) ;
+				strcat(chMaterial_DfShSpecular, "_DfShSpecular") ;
+				pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+				if(pMaterial_DfShSpecular.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShSpecular) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShSpecular, "DfShSpecular") ;
+					pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+				}
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShEmissive, chMaterial_Base) ;
+				strcat(chMaterial_DfShEmissive, "_DfShEmissive") ;
+				pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+				if(pMaterial_DfShEmissive.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShEmissive) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShEmissive, "DfShEmissive") ;
+					pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+				}
+
+
+				/*
+				// material for deferred shading
+				strcpy(chMaterial_DfShData, chMaterial_Base) ;
+				strcat(chMaterial_DfShData, "_DfShData") ;
+				pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+				if(pMaterial_DfShData.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShData) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShData, "DfShData") ; 
+					pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+				}
+				*/
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShMix, chMaterial_Base) ;
+				strcat(chMaterial_DfShMix, "_DfShMix") ;
+				pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+				if(pMaterial_DfShMix.isNull())
+				{
+					// Pretty much all materials just use the default mix material,
+					// so don't issue warnings if there isn't a specialized version
+					//sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShMix) ;
+					//m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShMix, "DfShMix") ;
+					pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+				}
+				
+			
+
+
+
+			}// end if not MAT_LAMP or MAT_GLOW
+			else
+				if(m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW) // the two materials that glow needs
+				{
+
+					// when I get around to allowing user defined GLOW materials as well as the automatic ones,
+					// this'll be the place to add it.  
+					// For now, just the automatically generated lamp/light stuff has a glow.
+					
+					// if the base material was "GLOW_lamp"	
+					strcpy(chCompare, chMaterial_Base) ;
+					chCompare[strlen("GLOW_lamp")]='\0' ;
+					if(strcmp("GLOW_lamp", chCompare)==0) 
+					{
+						strcpy(chMaterial_DfShColour, "GLOW_lampcol") ;
+						pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+						strcpy(chMaterial_DfShEmissive, "GLOW_lamp") ;
+						pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+					}
+					else
+					{
+
+						// if the base material was "GLOW_light"
+						strcpy(chCompare, chMaterial_Base) ;
+						chCompare[strlen("GLOW_light")]='\0' ;
+						if(strcmp("GLOW_light", chCompare)==0) 
+						{
+							strcpy(chMaterial_DfShColour, "GLOW_lightcol") ;
+							pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+							strcpy(chMaterial_DfShEmissive, "GLOW_light") ;
+							pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+						}
+
+					}
+				}
+
+
+
+
+
+
+			// work out which vertices we'll need, we don't add every vertex, just used ones.
+			nMaxVertex=0 ;
+			for(nVert=0 ; nVert<m_Q3Map->m_nVertexMax ; nVert++)
+				pVertIndex[nVert]=-1 ; // initialize all verts as unused.
+			
+
+			// start defining the manualObject
+			m_pZoneMO[nMOIndex]->begin(chMaterial_Base, RenderOperation::OT_TRIANGLE_LIST) ;
+
+
+			// reset the min max stuff
+			flMinX=flMinY=flMinZ=MINMAXLIMIT ;
+			flMaxX=flMaxY=flMaxZ=-MINMAXLIMIT ;
+	
+
+			// add the verts.  We avoid repeating the same vert multiple times where it is used by many triangles
+			for(nTri=nTriangle ; nTri<nEnd ; nTri++)
+				for(nVert=0 ; nVert<3 ; nVert++)
+				{
+					if(pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ]==-1) // this vert hasn't been added yet
+					{
+						pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert] ]=nMaxVertex++ ; // so we can correctly look it up when we add the triangles
+
+						flPosX=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]  ].position[0] ;
+						flPosY=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].position[1] ;
+						flPosZ=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].position[2] ;
+						flNormX=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].normal[0] ;
+						flNormY=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].normal[1] ;
+						flNormZ=m_Q3Map->m_pVertex[ m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].normal[2] ;
+						
+						
+						
+						// lamps have some different vertex data, also glow
+						// lamp needs colour and also info about the origin, which is stored in the UVs.
+						// glow only needs the colour, but it doesn't hurt to store the orgin too, no harm and simpler code.
+						if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW))
+						{
+							flLampPosX =			m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].texcoord[0][0] ;
+							flLampPosY =			m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].texcoord[0][1] ;
+							flLampPosZ =			m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].texcoord[1][0] ;
+							flLampBrightness=	m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].texcoord[1][1] ;
+
+							flLampR=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].color[0]/255.0f ;
+							flLampG=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].color[1]/255.0f ;
+							flLampB=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].color[2]/255.0f ;
+
+							// set the vertex data
+							m_pZoneMO[nMOIndex]->position(flPosX, flPosY, flPosZ) ;
+							m_pZoneMO[nMOIndex]->normal(flNormX, flNormY, flNormZ) ;
+							m_pZoneMO[nMOIndex]->textureCoord(flLampPosX, flLampPosY, flLampPosZ, flLampBrightness) ;
+							m_pZoneMO[nMOIndex]->colour(flLampR, flLampG, flLampB) ;
+
+						}
+						else // non-lamps
+						{
+							flTexU=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].texcoord[0][0] ;
+							flTexV=m_Q3Map->m_pVertex[	m_Q3Map->m_pTriangle[nTri].VIndex[nVert]	].texcoord[0][1] ;
+
+							// set the vertex data
+							m_pZoneMO[nMOIndex]->position(flPosX, flPosY, flPosZ) ;
+							m_pZoneMO[nMOIndex]->normal(flNormX, flNormY, flNormZ) ;
+							m_pZoneMO[nMOIndex]->textureCoord(flTexU, flTexV) ;
+						}
+
+						// update bounds
+						if(flPosX<flMinX) flMinX=flPosX ;
+						if(flPosY<flMinY) flMinY=flPosY ;
+						if(flPosZ<flMinZ) flMinZ=flPosZ ;
+						if(flPosX>flMaxX) flMaxX=flPosX ;
+						if(flPosY>flMaxY) flMaxY=flPosY ;
+						if(flPosZ>flMaxZ) flMaxZ=flPosZ ;
+
+					}// end if adding vert
+				}
+
+			// add the triangles
+			for(nTri=nTriangle ; nTri<nEnd ; nTri++)
+			{
+				nVertA=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[0] ] ;
+				nVertB=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[1] ] ;
+				nVertC=pVertIndex[ m_Q3Map->m_pTriangle[nTri].VIndex[2] ] ;
+				m_pZoneMO[nMOIndex]->triangle(nVertA, nVertC, nVertB) ;
+				m_nZoneTriangleCount[nZone]++ ;
+				//m_pZoneMO[nMOIndex]->triangle(nVertA, nVertB, nVertC) ;
+			}
+
+
+			// all done for this block of material
+			m_pZoneMO[nMOIndex]->end() ;
+			m_pZoneMO[nMOIndex]->setCastShadows(true) ;
+			m_pZoneMO[nMOIndex]->setDynamic(false) ;
+
+			// convert the manualobject to a mesh
+			sprintf(chMeshName, "ZoneMesh_%04i_%04i_%05i", nZone, nMaterial, nTriangle) ;
+			m_pZoneMesh[nMOIndex]= m_pZoneMO[nMOIndex]->convertToMesh(chMeshName);
+
+			// don't need the manual object anymore
+			m_pSceneMgr->destroyManualObject(m_pZoneMO[nMOIndex]) ;
+
+
+			// temp cludge to add thickness
+			flMinX-=1.0f ;
+			flMinY-=1.0f ;
+			flMinZ-=1.0f ;
+			flMaxX+=1.0f ;
+			flMaxY+=1.0f ;
+			flMaxZ+=1.0f ;
+
+			// set axis aligned bounding box of this mesh
+			AABB.setMinimumX(flMinX) ; 
+			AABB.setMinimumY(flMinY) ; 
+			AABB.setMinimumZ(flMinZ) ;
+			AABB.setMaximumX(flMaxX) ; 
+			AABB.setMaximumY(flMaxY) ; 
+			AABB.setMaximumZ(flMaxZ) ;
+			m_pZoneMesh[nMOIndex]->_setBounds(AABB, false) ;
+			
+			// set bounding sphere of this mesh
+			flDisX=flMaxX-flMinX ;
+			flDisY=flMaxY-flMinY ;
+			flDisZ=flMaxZ-flMinZ ;
+			flRadius=sqrt( flDisX*flDisX + flDisY*flDisY + flDisZ*flDisZ )/2.0 ;
+			m_pZoneMesh[nMOIndex]->_setBoundingSphereRadius(flRadius) ;
+
+
+			//if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassred")==0)
+			//	OFBug.MessageFloat(flRadius, flMinX, flMinY, flMinZ, flMaxX, flMaxY, flMaxZ) ;
+
+			//if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassgreen")==0)
+			//	OFBug.MessageFloat(flRadius, flMinX, flMinY, flMinZ, flMaxX, flMaxY, flMaxZ) ;
+
+			// calculate tangents for the mesh		
+			if((m_pZoneEntityMaterialType[nMOIndex]!=MAT_LAMP) && (m_pZoneEntityMaterialType[nMOIndex]!=MAT_GLOW))// lamps and glow don't need tangent vectors
+			{
+				m_pZoneMesh[nMOIndex]->suggestTangentVectorBuildParams(VES_TANGENT, src, dest) ;
+				m_pZoneMesh[nMOIndex]->buildTangentVectors(VES_TANGENT, src, dest);
+			}
+   	
+			m_pZoneMesh[nMOIndex]->load() ;
+
+			m_pZoneMesh[nMOIndex]->getSubMesh(0)->generateExtremes(8) ;
+
+			// create an entity for this mesh.  We need this so we can change the material during deferred shading
+			m_pZoneEntity[nMOIndex]=m_pSceneMgr->createEntity(m_pZoneMesh[nMOIndex]->getName(), m_pZoneMesh[nMOIndex]->getName()) ;
+
+			// if the entity is a lamp or glow, set its material because they never get changed
+			if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW)) 
+				m_pZoneEntity[nMOIndex]->setMaterial( pMaterial_Base) ;
+
+
+			//AABB=m_pZoneEntity[nMOIndex]->getBoundingBox() ;
+			//Ogre::Vector3 mn, mx ;
+			//mn=AABB.getMinimum() ;
+			//mx=AABB.getMaximum() ;
+			//if(strcmp(chMaterial_Base, "textures/metaltech/GEL_DSC_glassred")==0)
+			//	OFBug.MessageFloat(mn.x, mn.y, mn.z, mx.x, mx.y, mx.z) ; 
+
+
+
+
+
+
+			// store the pointers to the materials of this entity
+			//m_pZoneEntityMaterial_Base[nMOIndex]=pMaterial_Base ;
+			//m_pZoneEntityMaterial_Fast[nMOIndex]=pMaterial_Fast ;
+			m_pZoneEntityMaterial_Black[nMOIndex]=pMaterial_Black ;
+			m_pZoneEntityMaterial_DfShColour[nMOIndex]=pMaterial_DfShColour ;
+			m_pZoneEntityMaterial_Shadow[nMOIndex]=pMaterial_Shadow ;
+			m_pZoneEntityMaterial_ShadeFront[nMOIndex]=pMaterial_ShadeFront ;
+			m_pZoneEntityMaterial_ShadeBack[nMOIndex]=pMaterial_ShadeBack ;
+			m_pZoneEntityMaterial_DfShPosition[nMOIndex]=pMaterial_DfShPosition ;
+			m_pZoneEntityMaterial_DfShDiffuse[nMOIndex]=pMaterial_DfShDiffuse ;
+			//m_pZoneEntityMaterial_DSNormal[nMOIndex]=pMaterial_DSNormal ;
+			m_pZoneEntityMaterial_DfShFuncTNB[nMOIndex]=pMaterial_DfShFuncTNB ;
+			m_pZoneEntityMaterial_DfShSpecular[nMOIndex]=pMaterial_DfShSpecular ;
+			m_pZoneEntityMaterial_DfShEmissive[nMOIndex]=pMaterial_DfShEmissive ;
+			//m_pZoneEntityMaterial_DfShData[nMOIndex]=pMaterial_DfShData ;
+			m_pZoneEntityMaterial_DfShMix[nMOIndex]=pMaterial_DfShMix ;
+
+
+			//////////////////////////////////////////////////////////////////////////////////////////
+
+			char chNewName[1024] ;
+			for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+			{
+				Ogre::AliasTextureNamePairList AliasList ;
+				
+				// check the necessary texture exists
+				//if(TextureManager::getSingleton().getByName(m_Q3Map->m_chSpotlightTexture[nPTex]).isNull())
+				//	OFBug.MessageInt(666) ;
+				
+				
+				AliasList.insert(AliasTextureNamePairList::value_type("projector_tex", m_Q3Map->m_chSpotlightTexture[nPTex]));
+
+				
+
+				sprintf(chNewName, "%s_%i", chMaterial_Base, 0) ;
+				m_pZoneEntityMaterial_Base[nPTex][nMOIndex]=pMaterial_Base->clone(chNewName) ;
+				// change the texture unit
+				m_pZoneEntityMaterial_Base[nPTex][nMOIndex]->applyTextureAliases(AliasList) ;
+
+				sprintf(chNewName, "%s_%i", chMaterial_Fast, 0) ;
+				m_pZoneEntityMaterial_Fast[nPTex][nMOIndex]=pMaterial_Fast->clone(chNewName) ;
+				// change the texture unit
+				m_pZoneEntityMaterial_Fast[nPTex][nMOIndex]->applyTextureAliases(AliasList) ;
+
+			}
+
+
+
+			//////////////////////////////////////////////////////////////////////////////////////////
+
+
+			// move to the end of this block of materials
+			nTriangle=nEnd ;
+			nMOIndex++ ;
+
+
+			//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+			//
+			// end adding a begin/end block of all triangles in a zone with the same material
+			//
+			//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+		}// end scanning triangles in a zone
+
+
+
+	}// end looping through all zones
+
+	m_nZoneMOStart[m_Q3Map->m_nMaxZone]=nMOIndex ; // indicates the end pos of all the manual objects 
+
+	CHECKDELETE_ARRAY( pVertIndex, NEW_CHECK_pVertIndex  );  // free the vert index memory we used
+
+	CHECKDELETE_ARRAY( m_pZoneMO, NEW_CHECK_m_pZoneMO  ) ;  // free the manual object memory we used
+	// quick check
+	if(nMOCount!=nMOIndex)
+	{
+		sprintf(chMessage, "ERROR ConstructMap: MOIndex %i does not match MOCount %i", nMOIndex, nMOCount) ;
+		m_pLog->logMessage(chMessage);
+		//CHECKDELETE_ARRAY( m_pZoneMO ) ;
+		CHECKDELETE_ARRAY( m_pZoneMesh, NEW_CHECK_m_pZoneMesh  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntity, NEW_CHECK_m_pZoneEntity  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterialType, NEW_CHECK_m_pZoneEntityMaterialType  ) ; 
+
+		for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+		{
+			CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Base[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Base  ) ; 
+			CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Fast[nPTex], NEW_CHECK_m_pZoneEntityMaterial_Fast  ) ; 
+		}
+
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Black, NEW_CHECK_m_pZoneEntityMaterial_Black  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShColour, NEW_CHECK_m_pZoneEntityMaterial_DfShColour  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_Shadow, NEW_CHECK_m_pZoneEntityMaterial_Shadow  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeFront, NEW_CHECK_m_pZoneEntityMaterial_ShadeFront  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_ShadeBack, NEW_CHECK_m_pZoneEntityMaterial_ShadeBack  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShPosition, NEW_CHECK_m_pZoneEntityMaterial_DfShPosition  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShDiffuse, NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse  ) ; 
+		//CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DSNormal ) ;
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShFuncTNB, NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShSpecular, NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular  ) ; 
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShEmissive, NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive  ) ; 
+		//CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShData ) ;
+		CHECKDELETE_ARRAY( m_pZoneEntityMaterial_DfShMix, NEW_CHECK_m_pZoneEntityMaterial_DfShMix  ) ; 
+
+
+		return 0 ;
+	}
+
+
+	return 1 ;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// setup the game entities
+//
+
+int OgreFramework::SetupGameEntities(void)
+{
+	int nEntity=0 ;
+	char chMeshName[1024] ;
+	
+
+	// work out the maximum number of entities we need
+	m_nMaxEntity=10 ;
+	int nHalfMax=m_nMaxEntity/2 ;
+	
+
+
+
+	// create the dynamic memory for the entities
+	m_pEntityInfo=new ENTITYINFO[m_nMaxEntity] ;
+	if(m_pEntityInfo==NULL) 
+		return 0 ;
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pEntityInfo]++ ; }
+
+	m_pVisibleEntity=new int[m_nMaxEntity] ;
+	if(m_pVisibleEntity==NULL) 
+		return 0 ;
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pVisibleEntity]++ ; }
+
+	m_pFrustumEntity=new int[m_nMaxEntity] ;
+	if(m_pFrustumEntity==NULL) 
+		return 0 ;
+	else
+		{m_nNewCount++ ; m_nNewCheck[NEW_CHECK_m_pFrustumEntity]++ ; }
+
+
+
+	// setup materials and default data for the entities
+	for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+	{
+		//switch(nEntity%3)
+		//{
+		//	case 0: strcpy(chMeshName, "robot.mesh") ; break ;
+		//	case 1: strcpy(chMeshName, "ninja.mesh") ; break ;
+		//	case 2: strcpy(chMeshName, "athene.mesh") ; break ;
+		//}
+
+		strcpy(chMeshName, "robot.mesh") ;
+
+		SetupEntity(nEntity, chMeshName) ;
+	}
+
+
+
+
+	// setup start data for each entity
+	for(nEntity=0 ; nEntity<nHalfMax ; nEntity++)
+	{
+		m_pEntityInfo[nEntity].Postition=Ogre::Vector3(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ;
+		//m_pEntityInfo[nEntity].pMasterNode->setPosition(750.0f, 128.0f, -1950.0f-nEntity*40.0f) ;
+	}
+
+	for(nEntity=nHalfMax ; nEntity<m_nMaxEntity ; nEntity++)
+	{
+		m_pEntityInfo[nEntity].Postition=Ogre::Vector3(590.0f, 128.0f, -320.0f-nEntity*40.0f) ;
+		//m_pEntityInfo[nEntity].pMasterNode->setPosition(590.0f, 128.0f, -320.0f-nEntity*40.0f) ;
+	}
+
+	
+
+	for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+	{
+		m_pEntityInfo[nEntity].Active=1 ;
+		m_pVisibleEntity[nEntity]=nEntity ;
+		m_pFrustumEntity[nEntity]=nEntity ;
+	}
+
+
+	m_nMaxVisibleEntity=m_nMaxEntity ;
+	m_nMaxFrustumEntity=m_nMaxEntity ;
+
+	return 1 ;
+
+}
+
+
+int OgreFramework::SetupEntity(int nEntity, char *chMeshName)
+{
+
+	char chEntityName[1024] ;
+	//char chMeshName[1024] ;
+
+
+	int nSubMesh=0 ;
+	int nMaxSubMesh=0 ;
+
+
+
+	Ogre::String MaterialName ;
+
+
+	char chMaterial_Base[1024] ;
+	MaterialPtr pMaterial_Base ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+	
+	char chMaterial_Fast[1024] ;
+	MaterialPtr pMaterial_Fast ; // faster version of the base, mainly non-coloured shadowning.
+
+	char chMaterial_Black[1024] ;
+	MaterialPtr pMaterial_Black ; // just plain black, or black with alpha testing.
+
+	char chMaterial_DfShColour[1024] ;
+	MaterialPtr pMaterial_DfShColour ; // used for checking if material scripts exist, and stored for the material switching that happens in deferred shading
+	
+
+	char chMaterial_Shadow[1024] ;
+	MaterialPtr pMaterial_Shadow ;
+
+	char chMaterial_ShadeFront[1024] ;
+	MaterialPtr pMaterial_ShadeFront ;
+
+	char chMaterial_ShadeBack[1024] ;
+	MaterialPtr pMaterial_ShadeBack ;
+
+	char chMaterial_DfShPosition[1024] ;
+	MaterialPtr pMaterial_DfShPosition ;
+	
+	char chMaterial_DfShDiffuse[1024] ;
+	MaterialPtr pMaterial_DfShDiffuse ;
+	
+	//char chMaterial_DSNormal[1024] ;
+	//MaterialPtr pMaterial_DSNormal ;
+	
+	char chMaterial_DfShFuncTNB[1024] ;
+	MaterialPtr pMaterial_DfShFuncTNB ;
+
+	char chMaterial_DfShSpecular[1024] ;
+	MaterialPtr pMaterial_DfShSpecular ;
+
+	char chMaterial_DfShEmissive[1024] ;
+	MaterialPtr pMaterial_DfShEmissive ;
+
+	//char chMaterial_DfShData[1024] ;
+	//MaterialPtr pMaterial_DfShData ;
+
+	char chMaterial_DfShMix[1024] ;
+	MaterialPtr pMaterial_DfShMix ;
+
+	char chCompare[1024] ;
+
+	unsigned short src, dest; // for tangent vectors
+
+	char chMasterNodeName[1024] ;
+	char chSubNodeName[1024] ;
+
+	char chMessage[1024] ;
+	int nPTex=0 ;
+
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+		sprintf(chEntityName, "Entity_%05i", nEntity) ;
+		//strcpy(chMeshName, "robot.mesh") ;
+
+
+		// load the mesh
+
+		m_pEntityInfo[nEntity].pEnt=m_pSceneMgr->createEntity( chEntityName, chMeshName );
+
+		m_pEntityInfo[nEntity].TriangleCount=0 ;
+		
+
+		// create the master scenenode
+		sprintf(chMasterNodeName, "Entity_%05i", nEntity) ;
+		m_pEntityInfo[nEntity].pMasterNode=m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chMasterNodeName) ;
+		m_pEntityInfo[nEntity].pMasterNode->attachObject(m_pEntityInfo[nEntity].pEnt) ;
+
+		nMaxSubMesh=m_pEntityInfo[nEntity].pEnt->getMesh()->getNumSubMeshes() ;
+		if(nMaxSubMesh>MAX_SUBMESH)
+		{
+			sprintf(m_chBug, "MESH ERROR: Mesh %s has %i submeshes, max is %i", chMeshName, m_pEntityInfo[nEntity].MaxSubMesh, MAX_SUBMESH) ;
+			m_pLog->logMessage(m_chBug);
+			nMaxSubMesh=MAX_SUBMESH ;
+		}
+		m_pEntityInfo[nEntity].MaxSubMesh=nMaxSubMesh ;
+
+		sprintf(m_chBug, "Entity %i, Mesh %s, MaxSubMesh %i", nEntity, chMeshName,  m_pEntityInfo[nEntity].MaxSubMesh) ;
+		m_pLog->logMessage(m_chBug);
+
+		// assign all the materials needed for all the submeshes
+		for(nSubMesh=0 ; nSubMesh<nMaxSubMesh ; nSubMesh++)
+		{
+			// we count the triangles just for stats
+			m_pEntityInfo[nEntity].TriangleCount += m_pEntityInfo[nEntity].pEnt->getMesh()->getSubMesh(nSubMesh)->indexData->indexCount/3 ;
+
+
+			MaterialName=m_pEntityInfo[nEntity].pEnt->getMesh()->getSubMesh(nSubMesh)->getMaterialName() ;
+		
+			
+			
+
+			if(MaterialName.size()<512) // make sure name isn't too long before we copy it.
+				strcpy(chMaterial_Base, MaterialName.c_str()) ;
+			else
+			{
+				sprintf(m_chBug, "MESH ERROR: Mesh %s submesh %i material name is too long.", chMeshName, nSubMesh) ;
+				m_pLog->logMessage(m_chBug);
+				m_pLog->logMessage(MaterialName) ;
+				chMaterial_Base[0]='\0' ; // no material
+			}
+
+			sprintf(m_chBug, "Entity %i SubMesh %i, Material %s", nEntity, nSubMesh, chMaterial_Base) ;
+			m_pLog->logMessage(m_chBug);
+
+
+			// if the material is a lamp material we need to specify either an OpenGl or Direct3D version
+			strcpy(chCompare, chMaterial_Base) ;
+			chCompare[12]='\0' ;
+			if(strcmp("lights/lamp_", chCompare)==0) // material is LAMP 
+			{
+				if(m_IsOpenGL)
+					strcat(chMaterial_Base, "_ogl") ;
+				else
+					strcat(chMaterial_Base, "_d3d") ;
+
+			}
+
+			strcpy(chCompare, chMaterial_Base) ;
+			chCompare[17]='\0' ;
+			if(strcmp("lights/lamp2pass_", chCompare)==0) // material is LAMP, 2 pass version 
+			{
+				if(m_IsOpenGL)
+					strcat(chMaterial_Base, "_ogl") ;
+				else
+					strcat(chMaterial_Base, "_d3d") ;
+			}
+			
+			// check that this material script exists, if not set to the default
+			pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+			if(true)//pMaterial_Base.isNull())
+			{
+				strcat(chMaterial_Base, " *** MISSING ***") ;
+//				OFBug.LogAddCR(chMaterial_Base) ;
+				
+				strcpy(chMaterial_Base, "textures/metaltech/OPAQUE_DSCE_TechRadar") ;
+				pMaterial_Base=MaterialManager::getSingleton().getByName(chMaterial_Base) ;
+			}
+
+
+			// setup whether this material and it's entities are transparent or whatever
+			
+			m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=0 ;// default to nothing
+			
+			if(strstr(chMaterial_Base, "OPAQUE")!=NULL) // material and its entity are OPAQUE
+			{
+				m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_OPAQUE ; // note that the derived entity will be opaque
+
+			}
+			else
+			{
+
+				if(strstr(chMaterial_Base, "ALPHAPF")!=NULL) // material and its entity are ALPHAPF
+				{
+					m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_OPAQUE ; // note that the derived entity will be opaque
+				}
+				else
+				{
+
+					if(strstr(chMaterial_Base, "GEL")!=NULL) // material and its entity are GEL
+					{
+						m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_GEL ; // note that the derived entity will be transparent
+					}
+					else
+					{
+
+						strcpy(chCompare, chMaterial_Base) ;
+						chCompare[12]='\0' ;
+						if(strcmp("lights/lamp_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+						{
+							m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_LAMP ; // note that the derived entity will be lamp
+						}
+						else
+						{
+							strcpy(chCompare, chMaterial_Base) ;
+							chCompare[17]='\0' ;
+							if(strcmp("lights/lamp2pass_", chCompare)==0) // material and its entity are LAMP (spotlights don't ever make triangles, only lamps)
+							{
+								m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_LAMP ; // note that the derived entity will be lamp
+							}
+							else
+							{
+
+								if(strstr(chMaterial_Base, "GLOW_")!=NULL) // material and its entity are GLOW
+								{
+									m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]=MAT_GLOW ; // note that the derived entity will be glow
+								}
+							}	
+						}					
+					}
+				}
+			}
+
+
+
+			
+
+			///////////////////////////////////////////////////////////////////////////////////////////////////////
+			//
+			// Setup the different material names and pointers needed for various passes
+			//
+			// Lamps need only one material, pMaterial_Base, which is already assigned above, so it skips all this.
+			//
+			// Glow needs two materials, pMaterial_Base plus pMaterial_DfShColour for the coloured gel deferred pass.
+			// However it's better to make a third, and duplicate the pMaterial_Base to pMaterial_Emissive, since
+			// when glow gets rendered on the Emmisive pass it would be odd to switch to the base material instead
+			// of the emmisive.
+			//
+			// Other objects need multiple materials for various different deferred shading and FX passes
+			
+			if((m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_LAMP) && (m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]!=MAT_GLOW))
+			{
+
+				// material for fast shading
+				strcpy(chMaterial_Fast, chMaterial_Base) ;
+				strcat(chMaterial_Fast, "_Fast") ;
+				pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+				if(pMaterial_Fast.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_Fast) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_Fast, "Fast") ;
+					pMaterial_Fast=MaterialManager::getSingleton().getByName(chMaterial_Fast) ;
+				}
+
+				// material for black shading
+				strcpy(chMaterial_Black, chMaterial_Base) ;
+				strcat(chMaterial_Black, "_Black") ;
+				pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+				if(pMaterial_Black.isNull())
+				{
+					// only issue a warning if this is an alpha testing material, others don't need specialized Black materials
+					if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+					{
+						sprintf(chMessage, "Missing material, using default: %s", chMaterial_Black) ;
+						m_pLog->logMessage(chMessage);
+					}
+
+					strcpy(chMaterial_Black, "Black") ;
+					pMaterial_Black=MaterialManager::getSingleton().getByName(chMaterial_Black) ;
+				}
+				
+				// material for shadow casting
+				strcpy(chMaterial_Shadow, chMaterial_Base) ;
+				strcat(chMaterial_Shadow, "_Shadow") ;
+				pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+				if(pMaterial_Shadow.isNull())
+				{
+					strcpy(chMaterial_Shadow, "OPAQUE_Shadow") ;
+					pMaterial_Shadow=MaterialManager::getSingleton().getByName(chMaterial_Shadow) ;
+				}
+
+				
+				
+				// material for shadow casting
+				strcpy(chMaterial_ShadeFront, chMaterial_Base) ;
+				strcat(chMaterial_ShadeFront, "_ShadeFront") ;
+				pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+				if(pMaterial_ShadeFront.isNull())
+				{
+					 // standard opaque ShadeFront.  
+					// Transparent surfaces MUST have their own _ShadeFront material or they will not colour light and can interfere with other trans surfaces.
+					strcpy(chMaterial_ShadeFront, "OPAQUE_ShadeFront") ;
+
+					pMaterial_ShadeFront=MaterialManager::getSingleton().getByName(chMaterial_ShadeFront) ;
+				}
+
+
+				// material for shadow casting
+				strcpy(chMaterial_ShadeBack, chMaterial_Base) ;
+				strcat(chMaterial_ShadeBack, "_ShadeBack") ;
+				pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+				if(pMaterial_ShadeBack.isNull())
+				{
+					 // standard opaque ShadeBack.  
+					// Transparent surfaces MUST have their own _ShadeBack material or they will not colour light and can interfere with other trans surfaces.
+					strcpy(chMaterial_ShadeBack, "OPAQUE_ShadeBack") ;
+
+					pMaterial_ShadeBack=MaterialManager::getSingleton().getByName(chMaterial_ShadeBack) ;
+				}
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShColour, chMaterial_Base) ;
+				strcat(chMaterial_DfShColour, "_DfShColour") ;
+				pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+				if(pMaterial_DfShColour.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShColour) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShColour, "DfShColour") ;
+					pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+				}
+				
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShPosition, chMaterial_Base) ;
+				strcat(chMaterial_DfShPosition, "_DfShPosition") ;
+				pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+				if(pMaterial_DfShPosition.isNull())
+				{
+					// only issue a warning if this is an alpha testing material, others don't need specialized DfShPosition materials
+					if(strstr(chMaterial_Base, "ALPHAPF")!=NULL)
+					{
+						sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShPosition) ;
+						m_pLog->logMessage(chMessage);
+					}
+
+					strcpy(chMaterial_DfShPosition, "DfShPosition") ;
+					pMaterial_DfShPosition=MaterialManager::getSingleton().getByName(chMaterial_DfShPosition) ;
+				}
+				
+				// material for deferred shading
+				strcpy(chMaterial_DfShDiffuse, chMaterial_Base) ;
+				strcat(chMaterial_DfShDiffuse, "_DfShDiffuse") ;
+				pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+				if(pMaterial_DfShDiffuse.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShDiffuse) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShDiffuse, "DfShDiffuse") ;
+					pMaterial_DfShDiffuse=MaterialManager::getSingleton().getByName(chMaterial_DfShDiffuse) ;
+				}
+
+				/*
+				// material for deferred shading // UNUSED
+				strcpy(chMaterial_DSNormal, chMaterial_Base) ;
+				strcat(chMaterial_DSNormal, "_DSNormal") ;
+				pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+				if(pMaterial_DSNormal.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DSNormal) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DSNormal, "DSNormal") ;
+					pMaterial_DSNormal=MaterialManager::getSingleton().getByName(chMaterial_DSNormal) ;
+				}
+				*/
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShFuncTNB, chMaterial_Base) ;
+				strcat(chMaterial_DfShFuncTNB, "_DfShFuncTNB") ;
+				pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+				if(pMaterial_DfShFuncTNB.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShFuncTNB) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShFuncTNB, "DfShFuncTNB") ;
+					pMaterial_DfShFuncTNB=MaterialManager::getSingleton().getByName(chMaterial_DfShFuncTNB) ;
+				}
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShSpecular, chMaterial_Base) ;
+				strcat(chMaterial_DfShSpecular, "_DfShSpecular") ;
+				pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+				if(pMaterial_DfShSpecular.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShSpecular) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShSpecular, "DfShSpecular") ;
+					pMaterial_DfShSpecular=MaterialManager::getSingleton().getByName(chMaterial_DfShSpecular) ;
+				}
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShEmissive, chMaterial_Base) ;
+				strcat(chMaterial_DfShEmissive, "_DfShEmissive") ;
+				pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+				if(pMaterial_DfShEmissive.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShEmissive) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShEmissive, "DfShEmissive") ;
+					pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+				}
+
+
+				/*
+				// material for deferred shading
+				strcpy(chMaterial_DfShData, chMaterial_Base) ;
+				strcat(chMaterial_DfShData, "_DfShData") ;
+				pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+				if(pMaterial_DfShData.isNull())
+				{
+					sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShData) ;
+					m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShData, "DfShData") ; 
+					pMaterial_DfShData=MaterialManager::getSingleton().getByName(chMaterial_DfShData) ;
+				}
+				*/
+
+				// material for deferred shading
+				strcpy(chMaterial_DfShMix, chMaterial_Base) ;
+				strcat(chMaterial_DfShMix, "_DfShMix") ;
+				pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+				if(pMaterial_DfShMix.isNull())
+				{
+					// Pretty much all materials just use the default mix material,
+					// so don't issue warnings if there isn't a specialized version
+					//sprintf(chMessage, "Missing material, using default: %s", chMaterial_DfShMix) ;
+					//m_pLog->logMessage(chMessage);
+
+					strcpy(chMaterial_DfShMix, "DfShMix") ;
+					pMaterial_DfShMix=MaterialManager::getSingleton().getByName(chMaterial_DfShMix) ;
+				}
+				
+			
+
+
+
+			}// end if not MAT_LAMP or MAT_GLOW
+			else
+				if(m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]==MAT_GLOW) // the two materials that glow needs
+				{
+
+					// when I get around to allowing user defined GLOW materials as well as the automatic ones,
+					// this'll be the place to add it.  
+					// For now, just the automatically generated lamp/light stuff has a glow.
+					
+					// if the base material was "GLOW_lamp"	
+					strcpy(chCompare, chMaterial_Base) ;
+					chCompare[strlen("GLOW_lamp")]='\0' ;
+					if(strcmp("GLOW_lamp", chCompare)==0) 
+					{
+						strcpy(chMaterial_DfShColour, "GLOW_lampcol") ;
+						pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+						strcpy(chMaterial_DfShEmissive, "GLOW_lamp") ;
+						pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+					}
+					else
+					{
+
+						// if the base material was "GLOW_light"
+						strcpy(chCompare, chMaterial_Base) ;
+						chCompare[strlen("GLOW_light")]='\0' ;
+						if(strcmp("GLOW_light", chCompare)==0) 
+						{
+							strcpy(chMaterial_DfShColour, "GLOW_lightcol") ;
+							pMaterial_DfShColour=MaterialManager::getSingleton().getByName(chMaterial_DfShColour) ;
+
+							strcpy(chMaterial_DfShEmissive, "GLOW_light") ;
+							pMaterial_DfShEmissive=MaterialManager::getSingleton().getByName(chMaterial_DfShEmissive) ;
+						}
+
+					}
+				}
+
+
+
+
+			// if the entity is a lamp or glow, set its material because they never get changed
+			//if((m_pZoneEntityMaterialType[nMOIndex]==MAT_LAMP) || (m_pZoneEntityMaterialType[nMOIndex]==MAT_GLOW)) 
+			//	m_pZoneEntity[nMOIndex]->setMaterial( pMaterial_Base) ;
+
+
+			// store the pointers to the materials of this entity
+			//m_pZoneEntityMaterial_Base[nMOIndex]=pMaterial_Base ;
+			//m_pZoneEntityMaterial_Fast[nMOIndex]=pMaterial_Fast ;
+			m_pEntityInfo[nEntity].Material_Black[nSubMesh]=pMaterial_Black ;
+			m_pEntityInfo[nEntity].Material_DfShColour[nSubMesh]=pMaterial_DfShColour ;
+			m_pEntityInfo[nEntity].Material_Shadow[nSubMesh]=pMaterial_Shadow ;
+			m_pEntityInfo[nEntity].Material_ShadeFront[nSubMesh]=pMaterial_ShadeFront ;
+			m_pEntityInfo[nEntity].Material_ShadeBack[nSubMesh]=pMaterial_ShadeBack ;
+			m_pEntityInfo[nEntity].Material_DfShPosition[nSubMesh]=pMaterial_DfShPosition ;
+			m_pEntityInfo[nEntity].Material_DfShDiffuse[nSubMesh]=pMaterial_DfShDiffuse ;
+			//m_pEntityInfo[nEntity].Material_DSNormal[nSubMesh]=pMaterial_DSNormal ;
+			m_pEntityInfo[nEntity].Material_DfShFuncTNB[nSubMesh]=pMaterial_DfShFuncTNB ;
+			m_pEntityInfo[nEntity].Material_DfShSpecular[nSubMesh]=pMaterial_DfShSpecular ;
+			m_pEntityInfo[nEntity].Material_DfShEmissive[nSubMesh]=pMaterial_DfShEmissive ;
+			//m_pEntityInfo[nEntity].Material_DfShData[nSubMesh]=pMaterial_DfShData ;
+			m_pEntityInfo[nEntity].Material_DfShMix[nSubMesh]=pMaterial_DfShMix ;
+
+			
+			//////////////////////////////////////////////////////////////////////////////////////////
+
+			char chNewName[1024] ;
+			for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+			{
+				Ogre::AliasTextureNamePairList AliasList ;
+				
+				// check the necessary texture exists
+				//if(TextureManager::getSingleton().getByName(m_Q3Map->m_chSpotlightTexture[nPTex]).isNull())
+				//	OFBug.MessageInt(666) ;
+				
+				AliasList.insert(AliasTextureNamePairList::value_type("projector_tex", m_Q3Map->m_chSpotlightTexture[nPTex]));
+
+				sprintf(chNewName, "%s_%i", chMaterial_Base, 0) ;
+				m_pEntityInfo[nEntity].Material_Base[nPTex][nSubMesh]=pMaterial_Base->clone(chNewName) ;
+				// change the texture unit
+				m_pEntityInfo[nEntity].Material_Base[nPTex][nSubMesh]->applyTextureAliases(AliasList) ;
+
+				sprintf(chNewName, "%s_%i", chMaterial_Fast, 0) ;
+				m_pEntityInfo[nEntity].Material_Fast[nPTex][nSubMesh]=pMaterial_Fast->clone(chNewName) ;
+				// change the texture unit
+				m_pEntityInfo[nEntity].Material_Fast[nPTex][nSubMesh]->applyTextureAliases(AliasList) ;
+
+			}
+
+			// create the sub scenenodes
+			//sprintf(chSubNodeName, "Entity_%05i_%05i", nEntity, nSubMesh) ;
+			//m_pEntityInfo[nEntity].pSubNode[nSubMesh]=m_pEntityInfo[nEntity].pMasterNode->createChildSceneNode(chSubNodeName) ;
+
+
+			sprintf(m_chBug, "Node %s, Subnode %s, Type %i", chMasterNodeName, chSubNodeName, m_pEntityInfo[nEntity].SubMeshMaterialType[nSubMesh]) ;
+			m_pLog->logMessage(m_chBug);
+		
+		}// end for submesh
+
+		// build tangent vectors for the mesh
+		m_pEntityInfo[nEntity].pEnt->getMesh()->suggestTangentVectorBuildParams(VES_TANGENT, src, dest) ;
+		m_pEntityInfo[nEntity].pEnt->getMesh()->buildTangentVectors(VES_TANGENT, src, dest);
+
+
+	// default to not active, not visible and in no zones
+	m_pEntityInfo[nEntity].Active=0 ;
+	m_pEntityInfo[nEntity].Visible=0 ;
+	m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=0 ;
+
+	// add some info about the bounding box
+	Ogre::AxisAlignedBox aabb ;
+	Ogre::Vector3 Minimum ;
+	Ogre::Vector3 Maximum ;
+
+	aabb=m_pEntityInfo[nEntity].pEnt->getBoundingBox() ;
+	Minimum=aabb.getMinimum() ;
+	Maximum=aabb.getMaximum() ;
+
+	m_pEntityInfo[nEntity].AABB=aabb ;
+	m_pEntityInfo[nEntity].Centre.x=(Maximum.x-Minimum.x)/2.0f ;
+	m_pEntityInfo[nEntity].Centre.y=(Maximum.y-Minimum.y)/2.0f ;
+	m_pEntityInfo[nEntity].Centre.z=(Maximum.z-Minimum.z)/2.0f ;
+
+	m_pEntityInfo[nEntity].AABBMin[0]=Minimum.x ;
+	m_pEntityInfo[nEntity].AABBMin[1]=Minimum.y ;
+	m_pEntityInfo[nEntity].AABBMin[2]=Minimum.z ;
+	m_pEntityInfo[nEntity].AABBMax[0]=Maximum.x ;
+	m_pEntityInfo[nEntity].AABBMax[1]=Maximum.y ;
+	m_pEntityInfo[nEntity].AABBMax[2]=Maximum.z ;
+
+
+	m_pEntityInfo[nEntity].Postition=Ogre::Vector3(0.0f, 0.0f, 0.0f) ;
+
+
+
+	return 1 ;
+}
+
+
+// Hmm... wanted to control some CG compiling, mainly to turn shadow filtering on or off, but I couln't get this to work.
+// I ended up just manually creating filtered and unfiltered version of the materials.
+/*
+int OgreFramework::ApplyCGDefines(void)
+{
+	int nZoneMO=0 ;
+	int nMaxZoneMO=m_nZoneMOStart[m_Q3Map->m_nMaxZone] ;
+	int nPTex=0 ;
+	
+	Ogre::Pass *CGPass ;
+	int nPass=0 ;
+	int nMaxPass=0 ;
+
+	for(nZoneMO=0 ; nZoneMO<nMaxZoneMO ; nZoneMO++)
+	{
+		//OFBug.MessageInt(nZoneMO, nMaxZoneMO, m_pZoneEntityMaterialType[nZoneMO]) ;
+		
+		if(m_pZoneEntityMaterialType[nZoneMO]==MAT_OPAQUE)
+			for(nPTex=0 ; nPTex<MAX_PROJECTORTEX ; nPTex++)
+			{
+				//m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ;
+				nMaxPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getNumPasses() ;
+				
+				for(nPass=0 ; nPass<nMaxPass ; nPass++)
+				{
+					m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(nPass)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON=1") ;
+					//m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(nPass)->getFragmentProgram()->reload();
+				}	
+				//CGPass=m_pZoneEntityMaterial_Base[nPTex][nZoneMO]->getTechnique(0)->getPass(0) ;
+			}
+	}
+	
+
+	//m_pZoneEntityMaterial_Base[0][0]->getTechnique(0)->getPass(1)->getFragmentProgram()->setParameter("compile_arguments", "-DFILTER_ON 1") ;
+		
+
+	return 1 ;
+
+
+}
+*/
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// create light manual objects, just for debugging/testing.
+// This is an array of manualobject AABBs that show the light culling box (double sided) for each light
+
+int OgreFramework::AddLightCullingBoxes()
+{
+	int nLt=0 ;
+	// for calculating bounds of mesh
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+	float flMaxZ=0.0f ;
+	int nMaxLight=m_Q3Map->m_nLightMax ;
+
+	char chSceneNodeName[1024] ;
+	char chManualName[1024] ;
+
+	m_pLightMO = new Ogre::ManualObject*[nMaxLight] ;
+	if(m_pLightMO==NULL) return 0 ; // fail, out of mem
+
+	for(nLt=0 ; nLt<nMaxLight ; nLt++)
+	{
+		
+		sprintf(chManualName, "LightMO_%05i", nLt) ;
+		m_pLightMO[nLt]=m_pSceneMgr->createManualObject(chManualName) ;
+
+		// start defining the manualObject
+		m_pLightMO[nLt]->begin("lighttest", RenderOperation::OT_TRIANGLE_LIST) ;
+
+		
+		flMinX=m_Q3Map->m_pLight[nLt].Min[0] ;
+		flMinY=m_Q3Map->m_pLight[nLt].Min[1] ;
+		flMinZ=m_Q3Map->m_pLight[nLt].Min[2] ;
+
+		flMaxX=m_Q3Map->m_pLight[nLt].Max[0] ;
+		flMaxY=m_Q3Map->m_pLight[nLt].Max[1] ;
+		flMaxZ=m_Q3Map->m_pLight[nLt].Max[2] ;
+		
+		
+		//////////////////////////////////////////////////////
+		// back face
+		m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+		m_pLightMO[nLt]->quad(0, 1, 2, 3) ;
+		m_pLightMO[nLt]->quad(3, 2, 1, 0) ;
+
+		//////////////////////////////////////////////////////
+		// front face
+		m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+		m_pLightMO[nLt]->quad(7, 6, 5, 4) ;
+		m_pLightMO[nLt]->quad(4, 5, 6, 7) ;
+
+		//////////////////////////////////////////////////////
+		// left face
+		m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+		m_pLightMO[nLt]->quad(8, 9, 10, 11) ;
+		m_pLightMO[nLt]->quad(11, 10, 9, 8) ;
+
+		
+		//////////////////////////////////////////////////////
+		// right face
+		m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, 1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+		m_pLightMO[nLt]->quad(15, 14, 13, 12) ;
+		m_pLightMO[nLt]->quad(12, 13, 14, 15) ;
+
+		//////////////////////////////////////////////////////
+		// top face
+		m_pLightMO[nLt]->position(flMinX, flMaxY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMaxY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMaxY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMaxY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+		m_pLightMO[nLt]->quad(16, 17, 18, 19) ;
+		m_pLightMO[nLt]->quad(19, 18, 17, 16) ;
+
+		//////////////////////////////////////////////////////
+		// bottom face
+		m_pLightMO[nLt]->position(flMinX, flMinY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMinY, flMaxZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 0.0) ;
+
+		m_pLightMO[nLt]->position(flMaxX, flMinY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(1.0, 1.0) ;
+
+		m_pLightMO[nLt]->position(flMinX, flMinY, flMinZ) ;
+		m_pLightMO[nLt]->normal(0.0, 0.0, -1) ;
+		m_pLightMO[nLt]->textureCoord(0.0, 1.0) ;
+
+		m_pLightMO[nLt]->quad(23, 22, 21, 20) ;
+		m_pLightMO[nLt]->quad(20, 21, 22, 23) ;
+		//////////////////////////////////////////////////////
+
+		m_pLightMO[nLt]->end() ;
+
+
+
+		sprintf(chSceneNodeName, "LSN%05i", nLt) ;
+		m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName)->attachObject(m_pLightMO[nLt]) ;
+
+		
+	}
+
+	return 1 ;
+}
+
+int OgreFramework::AddPortalBoxes()
+{
+	int nPt=0 ;
+	// for calculating bounds of mesh
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+	float flMaxZ=0.0f ;
+	int nMaxPortal=m_Q3Map->m_iNumPortals ;
+
+	char chSceneNodeName[1024] ;
+	char chManualName[1024] ;
+
+	m_pPortalMO = new Ogre::ManualObject*[nMaxPortal] ;
+	if(m_pPortalMO==NULL) return 0 ; // fail, out of mem
+
+	m_pPortalNode = new Ogre::Node*[nMaxPortal] ;
+	if(m_pPortalNode==NULL) 
+	{
+		//CHECKDELETE_ARRAY( m_pPortalMO ) ;
+		return 0 ; // fail, out of mem
+	}
+
+	for(nPt=0 ; nPt<nMaxPortal ; nPt++)
+	{
+		
+		sprintf(chManualName, "PortalMO_%05i", nPt) ;
+		m_pPortalMO[nPt]=m_pSceneMgr->createManualObject(chManualName) ;
+
+		// start defining the manualObject
+		m_pPortalMO[nPt]->begin("white", RenderOperation::OT_TRIANGLE_LIST) ;
+
+		flMinX=m_Q3Map->m_pPortals[nPt].Min[0] ;
+		flMinY=m_Q3Map->m_pPortals[nPt].Min[1] ;
+		flMinZ=m_Q3Map->m_pPortals[nPt].Min[2] ;
+
+		flMaxX=m_Q3Map->m_pPortals[nPt].Max[0] ;
+		flMaxY=m_Q3Map->m_pPortals[nPt].Max[1] ;
+		flMaxZ=m_Q3Map->m_pPortals[nPt].Max[2] ;
+		
+		
+		//////////////////////////////////////////////////////
+		// back face
+		m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+		m_pPortalMO[nPt]->quad(0, 1, 2, 3) ;
+		m_pPortalMO[nPt]->quad(3, 2, 1, 0) ;
+
+		//////////////////////////////////////////////////////
+		// front face
+		m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+		m_pPortalMO[nPt]->quad(7, 6, 5, 4) ;
+		m_pPortalMO[nPt]->quad(4, 5, 6, 7) ;
+
+		//////////////////////////////////////////////////////
+		// left face
+		m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+		m_pPortalMO[nPt]->quad(8, 9, 10, 11) ;
+		m_pPortalMO[nPt]->quad(11, 10, 9, 8) ;
+
+		
+		//////////////////////////////////////////////////////
+		// right face
+		m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, 1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+		m_pPortalMO[nPt]->quad(15, 14, 13, 12) ;
+		m_pPortalMO[nPt]->quad(12, 13, 14, 15) ;
+
+		//////////////////////////////////////////////////////
+		// top face
+		m_pPortalMO[nPt]->position(flMinX, flMaxY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMaxY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMaxY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+		m_pPortalMO[nPt]->quad(16, 17, 18, 19) ;
+		m_pPortalMO[nPt]->quad(19, 18, 17, 16) ;
+
+		//////////////////////////////////////////////////////
+		// bottom face
+		m_pPortalMO[nPt]->position(flMinX, flMinY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMinY, flMaxZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 0.0) ;
+
+		m_pPortalMO[nPt]->position(flMaxX, flMinY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(1.0, 1.0) ;
+
+		m_pPortalMO[nPt]->position(flMinX, flMinY, flMinZ) ;
+		m_pPortalMO[nPt]->normal(0.0, 0.0, -1) ;
+		m_pPortalMO[nPt]->textureCoord(0.0, 1.0) ;
+
+		m_pPortalMO[nPt]->quad(23, 22, 21, 20) ;
+		m_pPortalMO[nPt]->quad(20, 21, 22, 23) ;
+		//////////////////////////////////////////////////////
+
+		m_pPortalMO[nPt]->end() ;
+
+
+
+		sprintf(chSceneNodeName, "PSN%05i", nPt) ;
+		m_pSceneMgr->getRootSceneNode()->createChildSceneNode(chSceneNodeName)->attachObject(m_pPortalMO[nPt]) ;
+		m_pPortalNode[nPt]=m_pSceneMgr->getRootSceneNode()->getChild(chSceneNodeName) ;
+		
+	}
+
+	return 1 ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+// this function calculates which zones are visible.  
+// If they are in the view frustum and any connecting portals are open, they're visible.  
+// It calls a recursive functions that goes into each visible zone and scans it's portals 
+// for more visible zones, cutting down the frustum as it goes.
+//
+// This function also checks which lights are visible.
+// First it scans the original zone the camera is in, any light whose centre is in that zone
+// is visible regardless of how many other zones that light touches.
+// Lights that are completely contained in any of the further zones are checked against the
+// current cut down frustum.
+void OgreFramework::CalculateZoneVisibility(Ogre::Camera *pCamera, int *pCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList)
+{
+
+	
+	int nZone=0 ;
+//	int nZoneIndex=0 ;
+	int nSubZone=0 ;
+//	int nSubZoneIndex=0 ;
+	int nMaxSubZone=0 ;
+	int nPortal=0 ;
+//	int nPortalIndex=0 ;
+	int nMaxPortal=0 ;
+//	int nMaxPortalZone=0 ;
+//	int nPortalZone=0 ;
+//	int nPortalZoneIndex=0 ;
+//	int nMaxZone=0 ;
+	
+
+	int nMaxLight=m_Q3Map->m_nLightMax ;
+	int nLt=0 ;
+
+//	int nMaxSubLight=m_Q3Map->m_nSubLightMax ;
+	int nSubLt=0 ;
+	
+	m_nMaxVisibleLight=0 ;
+
+	
+
+	Ogre::Vector3 Pos=pCamera->getPosition() ;
+	float flPos[3]={Pos.x, Pos.y, Pos.z} ;
+
+	Ogre::AxisAlignedBox AAB ;
+
+
+
+	// initially all lights are invisible
+	// set all remaining real lights to invisible
+	SetAllLightsOff() ;
+
+	m_nTotalTriangles=0 ;
+
+	*pMaxVisibleLight=0 ; // no lights in the list 
+	
+	if(m_nZoneCullingActive) // if zone culling is active
+	{
+		
+		// by default, all zones are not visible
+		nZone=m_Q3Map->m_nMaxZone ;
+		while(nZone)
+			pZoneVis[--nZone]=ZONE_UNCHECKED ;
+
+		// by default, all lights are not visible
+		nLt=nMaxLight ;
+		while(nLt)
+			pLightVis[--nLt]=LIGHT_UNCHECKED ;
+
+		// by default, all lights are not visible
+		nSubLt=m_Q3Map->m_nSubLightMax ;
+		while(nSubLt)
+			pSubLightVis[--nSubLt]=LIGHT_UNCHECKED ;
+
+		// by default, all portals are not visible
+		nPortal=m_Q3Map->m_iNumPortals ;
+		while(nPortal)
+			pPortalVis[--nPortal]=PORTAL_UNCHECKED ;
+	}
+	else
+	{
+		// for debugging, all zones are visible
+		nZone=m_Q3Map->m_nMaxZone ;
+		while(nZone)
+			pZoneVis[--nZone]=ZONE_VISIBLE ;
+
+
+		// by default, all lights are visible
+		nLt=nMaxLight ;
+		while(nLt)
+			pLightVis[--nLt]=LIGHT_VISIBLE ;
+
+		nSubLt=m_Q3Map->m_nSubLightMax ;
+		while(nSubLt)
+			pSubLightVis[--nSubLt]=LIGHT_VISIBLE ;
+
+		// by default, all portals are visible
+		nPortal=m_Q3Map->m_iNumPortals ;
+		while(nPortal)
+			pPortalVis[--nPortal]=PORTAL_VISIBLE ;
+
+		return ;
+	}
+
+
+
+
+
+
+
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	
+
+
+	/////////////////////////////////////////////////////////////////////////////////////
+	// check camera is actually in the zone designated, otherwise update it.
+
+	if((*pCameraZone==-1) || (!m_Q3Map->PointInZone(flPos, *pCameraZone)) )
+	{
+
+		nSubZone=m_Q3Map->GetNextSubZone(flPos, -1, m_Q3Map->m_iNumSubZones) ;
+			
+		// subzone might still be -1 if the point isn't in any zone.  If this happens, set all zones in the view frustum as visible.
+		// this shouldn't generally happen, but if we aren't clipping and are flying around testing, it can.
+		// Don't worry about optimizing this.
+
+
+
+		if(nSubZone==-1)
+		{
+
+			nMaxSubZone=m_Q3Map->m_iNumSubZones ;
+			for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+			{
+				AAB.setExtents(m_Q3Map->m_pSubZones[nSubZone].Min[0], m_Q3Map->m_pSubZones[nSubZone].Min[1], m_Q3Map->m_pSubZones[nSubZone].Min[2], m_Q3Map->m_pSubZones[nSubZone].Max[0], m_Q3Map->m_pSubZones[nSubZone].Max[1], m_Q3Map->m_pSubZones[nSubZone].Max[2]) ;
+
+				if(pCamera->isVisible(AAB))
+					pZoneVis[ m_Q3Map->m_pSubZones[nSubZone].Zone ]=ZONE_VISIBLE ;
+			}	
+
+			*pCameraZone=-1 ;
+			return ; // skip everything else
+		}
+
+		*pCameraZone=m_Q3Map->m_pSubZones[nSubZone].Zone ; // update the zone
+	
+	}
+
+	//
+	/////////////////////////////////////////////////////////////////////////////////////
+
+
+	// update the portal states
+	nMaxPortal=m_Q3Map->m_iNumPortals ;
+	nPortal=nMaxPortal ;
+	while(nPortal)
+	{
+		nPortal-- ;
+
+		if(m_nPortalDebug==0)
+			m_chPortalState[nPortal]=PORTALSTATE_OPEN ; 
+		else
+		{
+			//if(m_nPortalState==1)
+				m_chPortalState[nPortal]=PORTALSTATE_OPEN ; 
+			//else
+			//	m_chPortalState[nPortal]=PORTALSTATE_CLOSED ;
+
+
+			
+		}
+		
+		//m_chPortalState[nPortal]|=PORTAL_FLAG_UNCHECKED ; // by default all portals are unchecked
+		
+		//m_chPortalState[nPortal]&=~(PORTAL_FLAG_VISCHECK|PORTAL_FLAG_VISIBLE) ; // by default, all portals are vis unchecked and not visible
+	}
+
+	//m_chPortalState[0]=PORTAL_FLAG_CLOSED ;
+	if(m_nPortalState==1)
+		m_chPortalState[1]=PORTALSTATE_OPEN ;
+	else
+		m_chPortalState[1]=PORTALSTATE_CLOSED ;
+
+
+
+
+	//Ogre::Camera* pTestCamera ;
+	//pTestCamera->synchroniseBaseSettingsWith(pCamera) ;
+
+	//Ogre::Real OrigL, OrigR, OrigT, OrigB ; // original frustum extents
+	//pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
+	
+	//pCamera->setFrustumExtents(OrigL/2.0, OrigR/2.0, OrigT/2.0, OrigB/2.0) ; // reset the original frustum extents
+
+	m_nRecurseCount=0 ;
+
+	
+	// work out the aspect scaling we'll need
+	Ogre::Real OrigL, OrigR, OrigT, OrigB, ScaleX, ScaleY ; // frustum extents per each portal in this zone
+	Ogre::Real NewL, NewR, NewT, NewB ;
+	pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
+
+	m_ViewMatrix=pCamera->getViewMatrix(true) ;
+	m_ProjectionMatrix=pCamera->getProjectionMatrix() ;
+	
+
+	//if(m_nOriginalZoneOpenPortals=0) // no portals on player zone are open, so we can only see the current zones.
+	//	pZoneVis[nZone]=ZONE_VISIBLE ; // flag this subzone as visible
+	//else
+	{
+
+		/*
+		// apply the stereofrustum tweak if needed
+		if(m_flStereoFrustumTweak!=0.0f)
+		{
+
+			NewL=OrigL-m_flStereoFrustumTweak ;
+			NewR=OrigR+m_flStereoFrustumTweak ;
+			NewT=OrigT ;
+			NewB=OrigB ;
+			pCamera->setFrustumExtents(NewL, NewR, NewT, NewB) ;
+		}
+		else
+		*/
+		{
+			NewL=OrigL ;
+			NewR=OrigR ;
+			NewT=OrigT ;
+			NewB=OrigB ;
+		}
+		
+		ScaleX=NewR ;
+		ScaleY=NewT ;
+
+
+		PortalScan(pCamera, *pCameraZone, ScaleX, ScaleY, pZoneVis, pLightVis, pSubLightVis, pPortalVis, pMaxVisibleLight, pVisibleLightList) ; // recursively scan portals and work out zone visibility
+
+		
+		pCamera->setFrustumExtents(OrigL, OrigR, OrigT, OrigB) ; // reset the original frustum extents
+
+		CheckMultiZoneLights(*pCameraZone, pZoneVis, pLightVis, pSubLightVis) ;
+		AddZonesFromMultiZoneLights(pZoneVis, pLightVis, pSubLightVis) ;
+
+		// check entity visibility
+		
+
+	}
+
+
+
+
+
+
+
+	
+}
+
+
+void OgreFramework::SetupEntityZones(void)
+{
+	// work out what zones any active entities are in.
+	int nEntity=0 ;
+	float Centre[3] ;
+	float AABBMin[3] ;
+	float AABBMax[3] ;
+	float* pLightMin ;
+	float* pLightMax ;
+	
+	int nOldZone=0 ;
+	int nCurrentZone=0 ;
+	int nMaxOldZone=0 ;
+	int nZonePerZoneIndex=0 ;
+	int nZone=0 ;
+	int nZoneIndex=0 ;
+	int nMaxZone=0 ;
+	int nMaxSubLightIndex=0 ;
+	int nSubLightIndex=0 ;
+	int nSubLight=0 ;
+
+//	int nLight=0;
+	int nLightIndex=0 ;
+
+
+	
+
+	for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+		if(m_pEntityInfo[nEntity].Active)
+		{
+			nLightIndex=0 ;
+			// to calculate what zones an entity is in, we test the centre of it's bounding box to get the main zone.
+			// we then test all zones that touch the central zone and see if they touch the entity bounding box.
+
+			// check if the entity central point is still in the same zone as last time.
+			Centre[0]=m_pEntityInfo[nEntity].Centre.x + m_pEntityInfo[nEntity].Postition.x ;
+			Centre[1]=m_pEntityInfo[nEntity].Centre.y + m_pEntityInfo[nEntity].Postition.y ;
+			Centre[2]=m_pEntityInfo[nEntity].Centre.z + m_pEntityInfo[nEntity].Postition.z ;
+
+			nMaxOldZone=m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT] ;
+
+
+
+			if(nMaxOldZone>0)
+			{
+				nOldZone=m_pEntityInfo[nEntity].Zone[0] ;
+				if(m_Q3Map->PointInZone(Centre, nOldZone))
+					nCurrentZone=nOldZone ;	// still in the same zone as last round
+				else
+				{
+					// see if we are in one of the other zones that were touched by this entity's aabb last round
+
+					nCurrentZone=-1 ;
+					for(nZoneIndex=1 ; nZoneIndex<nMaxOldZone ; nZoneIndex++)
+					{
+						if(m_Q3Map->PointInZone(Centre, m_pEntityInfo[nEntity].Zone[nZoneIndex]))
+						{
+							nCurrentZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ; // found the current zone we are in
+							break ;
+						}// end if point in zone
+
+					}// end for zoneindex
+
+				}// end if not in old zone.
+			}
+			else
+				nCurrentZone=-1 ;
+
+
+			// if we haven't found the current zone so far, we need to check every zone.
+			if(nCurrentZone==-1)
+			{
+				nZone=m_Q3Map->m_nMaxZone ;
+				while(nZone)
+					if(m_Q3Map->PointInZone(Centre, --nZone))
+					{
+						nCurrentZone=nZone ;
+						break ;
+					}
+			}// end if nCurrentZone -1
+
+
+			
+			// now either nCurrentZone is the zone the central point is in, or the entity isn't in any zone
+			if(nCurrentZone==-1)
+				m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=0 ;
+			else
+			{
+				// scan through all the zones that touch this entitys central zone
+				// see if the entitys AABB touches those other zones.
+				m_pEntityInfo[nEntity].Zone[0]=nCurrentZone ;
+				nZonePerZoneIndex=1 ;
+				
+				AABBMin[0]=m_pEntityInfo[nEntity].Postition.x + m_pEntityInfo[nEntity].AABBMin[0] ; 
+				AABBMin[1]=m_pEntityInfo[nEntity].Postition.y + m_pEntityInfo[nEntity].AABBMin[1] ; 
+				AABBMin[2]=m_pEntityInfo[nEntity].Postition.z + m_pEntityInfo[nEntity].AABBMin[2] ;
+
+				AABBMax[0]=m_pEntityInfo[nEntity].Postition.x + m_pEntityInfo[nEntity].AABBMax[0] ; 
+				AABBMax[1]=m_pEntityInfo[nEntity].Postition.y + m_pEntityInfo[nEntity].AABBMax[1] ; 
+				AABBMax[2]=m_pEntityInfo[nEntity].Postition.z + m_pEntityInfo[nEntity].AABBMax[2] ;
+
+
+				nMaxZone=m_Q3Map->m_nZoneTouchesZone[nCurrentZone][INDEX_ZONEPERZONECOUNT] ;
+				for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
+				{
+					nZone=m_Q3Map->m_nZoneTouchesZone[nCurrentZone][nZoneIndex] ;
+
+					if(m_Q3Map->AABBTouchesZone(AABBMin, AABBMax, nZone)) 
+					{
+						m_pEntityInfo[nEntity].Zone[nZonePerZoneIndex]=nZone ;
+						nZonePerZoneIndex++ ;
+
+						if(nZonePerZoneIndex>MAX_ZONEPERENTITY)
+							nZonePerZoneIndex=MAX_ZONEPERENTITY ;
+					}
+
+					
+
+				}// end for nZoneIndex
+
+
+				m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT]=nZonePerZoneIndex ;
+
+				// go through all the zones and check which lights touch this entity AABB
+				for(nZoneIndex=0 ; nZoneIndex<nZonePerZoneIndex ; nZoneIndex++)
+				{
+					nZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ;
+
+					nMaxSubLightIndex=m_Q3Map->m_nZoneTouchesSubLight[nZone][MAX_LIGHTPERZONE] ;
+					for(nSubLightIndex=0 ; nSubLightIndex<nMaxSubLightIndex ; nSubLightIndex++)
+					{
+						nSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][nSubLightIndex] ;
+						pLightMin=m_Q3Map->m_SubLight[nSubLight].Min ;
+						pLightMax=m_Q3Map->m_SubLight[nSubLight].Max ;
+
+						// if the entity overlaps the sublight
+						if(
+									 (AABBMin[0]<pLightMax[0]) && (AABBMax[0]>pLightMin[0])
+								&& (AABBMin[1]<pLightMax[1]) && (AABBMax[1]>pLightMin[1])
+								&& (AABBMin[2]<pLightMax[2]) && (AABBMax[2]>pLightMin[2])
+							)
+						{
+							// add this to the list of lights.
+							// it's possible it might get listed more than once if this is a multizone light, that's ok.
+			
+							m_pEntityInfo[nEntity].Light[nLightIndex]=m_Q3Map->m_SubLight[nSubLight].Light ;
+							nLightIndex++ ;
+							if(nLightIndex>MAX_LIGHTPERENTITY)
+								nLightIndex=MAX_LIGHTPERENTITY ;
+
+
+						} // end if overlap
+
+					}// end for nSubLightIndex
+
+				}// end for nZoneIndex
+
+			}// end if we have a central zone
+			
+			
+			m_pEntityInfo[nEntity].Light[INDEX_LIGHTPERENTITY]=nLightIndex ;
+
+
+		}// end if entity is active
+}
+
+// spotlights need entities set as visible if they are in a visible zone, even if they aren't in the frustum, 
+// because they might cast shadows that are in the frustum.
+// However the deferred render only needs consider entities which are in a visible zone AND in the frustum.
+// m_pVisibleEntity holds entities in visible zones,
+// m_pFrustumEntity holds entities in visible zones that are also in the view frustum.
+void OgreFramework::CalculateEntityVisibility(Ogre::Camera* pCamera, char* pZoneVis)
+{
+
+	int nEntity=0 ;
+	int nMaxZone=0 ;
+	int nZone=0 ;
+	int nZoneIndex=0 ;
+//	int nVisible=0 ;
+	Ogre::AxisAlignedBox AABB ;
+
+
+	m_nMaxVisibleEntity=0 ; // default to an empty list 
+	m_nMaxFrustumEntity=0 ; // default to an empty list 
+
+	m_nVisibleEntityTriangleCount=0 ;
+	m_nFrustumEntityTriangleCount=0 ;
+
+	for(nEntity=0 ; nEntity<m_nMaxEntity ; nEntity++)
+		if(m_pEntityInfo[nEntity].Active)
+		{
+			m_pEntityInfo[nEntity].Visible=0 ; // default to not visible
+			m_pEntityInfo[nEntity].Frustum=0 ; // default to not visible and not in frustum
+
+			nMaxZone=m_pEntityInfo[nEntity].Zone[INDEX_ENTITYZONECOUNT] ;
+
+
+
+				for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
+				{
+					nZone=m_pEntityInfo[nEntity].Zone[nZoneIndex] ;
+
+					// if a zone this entity touches is visible, test if it is in the view frustrum	
+					if(pZoneVis[nZone]==ZONE_VISIBLE)
+					{
+
+						m_pEntityInfo[nEntity].Visible=1 ;
+						m_nVisibleEntityTriangleCount+=m_pEntityInfo[nEntity].TriangleCount ;
+						m_pVisibleEntity[m_nMaxVisibleEntity++]=nEntity ;
+						
+
+						// is this entity also in the view frustum?
+						AABB.setMinimum( m_pEntityInfo[nEntity].AABB.getMinimum() + m_pEntityInfo[nEntity].Postition ) ;
+						AABB.setMaximum( m_pEntityInfo[nEntity].AABB.getMaximum() + m_pEntityInfo[nEntity].Postition ) ;
+
+						if(pCamera->isVisible(AABB))
+						{
+							m_pEntityInfo[nEntity].Frustum=1 ;
+							m_nFrustumEntityTriangleCount+=m_pEntityInfo[nEntity].TriangleCount ;
+							m_pFrustumEntity[m_nMaxFrustumEntity++]=nEntity ;
+						}
+
+
+
+
+
+						break ; // get out of the loop, we know the entity is visible.
+
+					}// end if zone is visible
+
+				}// end for nZoneIndex
+
+		}// end if entity is active
+
+}
+
+
+
+
+
+void OgreFramework::SetAllLightsOff(void)
+{
+	Light *light;
+	char chLightName[1024] ;
+	int nLt=0 ;
+	for(nLt=0 ; nLt<MAXLIGHTPERLOOP ; nLt++)
+	{
+		sprintf(chLightName, "LT%02i", nLt) ;
+		light=m_pSceneMgr->getLight(chLightName) ;
+		light->setVisible(false) ;
+	}
+}
+
+void OgreFramework::SetSingleVisibleLight(int nLt, bool bOn)
+{
+	Light *light;
+
+	light=m_pSceneMgr->getLight("LT00") ;
+
+
+	// if we're just turning the light off, make it invisible and return.
+	if(bOn==false)
+	{
+		light->setVisible(false) ;
+		return ;
+	}
+
+	
+			
+	light->setDiffuseColour(Ogre::ColourValue(1,1,1));
+	light->setSpecularColour(Ogre::ColourValue(1,1,1));
+			
+	light->setAttenuation(m_Q3Map->m_pLight[nLt].Cutoff, 1.0, 1.0, 0.005);
+	light->setPosition(Ogre::Vector3(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]));
+	light->setDirection(Ogre::Vector3(m_Q3Map->m_pLight[nLt].Direction[0], m_Q3Map->m_pLight[nLt].Direction[1], m_Q3Map->m_pLight[nLt].Direction[2]));
+			
+	light->setSpotlightRange(Degree(m_Q3Map->m_pLight[nLt].Angle-5.0), Degree(m_Q3Map->m_pLight[nLt].Angle), 1.0) ;
+	light->setVisible(true) ;
+}
+
+
+// sets up a single visible light from the visible light list and assigns the camera to its position and settings
+// returns true if successful, false if not (such as if the light isn't actually visible)
+
+bool OgreFramework::SetupSingleVisibleLightAndShadowCamera(int nLt, char* pLightVis, unsigned short* pVisibleLightList, Ogre::Camera* pCamera)
+{
+	//if(nLt!=4) return false ;
+	
+	if((pLightVis[nLt]&LIGHT_VISIBLE)==0) // we need to check this again, since there's a chance a multi-zone light might have been culled at the last stage
+		return false ;
+
+	
+	Light *light=m_pSceneMgr->getLight("LT00") ;
+	
+	light->setDiffuseColour(Ogre::ColourValue(m_Q3Map->m_pLight[nLt].Colour[0], m_Q3Map->m_pLight[nLt].Colour[1], m_Q3Map->m_pLight[nLt].Colour[2]));
+
+	float	flRange=m_Q3Map->m_pLight[nLt].Cutoff ; // set the range
+	if(flRange<10240.0) //!! Ogre seems to cut off lights wrongly if the range is low, so set it to a minimum.
+		flRange=10240 ;
+
+	// The light attenuation parameters have been co-opted by me... they no longer represent range, constant, linear, quadratic
+	// instead, 
+	// first parameter is the above range, just set high so Ogre doesn't turn lights off itself.  The shaders ignore this parameter.
+	// second parameter is the cutoff used in the shader.  Light suddenly cuts off after this distance.
+	// third parameter is the brightness.  This controls the quadratic falloff of the light.
+	// fourth parameter is unused, leave as 1.0 for now.
+
+	light->setAttenuation(flRange, m_Q3Map->m_pLight[nLt].Cutoff, m_Q3Map->m_pLight[nLt].Brightness, 1.0) ;
+	
+	
+	
+	// Ogre uses a fixed yaw axis which will cause pCamera->setDirection to malfunction if we point directly up or down.
+	// To avoid this we need to check for such lights and shift their direction a little.
+	
+	float DirX=m_Q3Map->m_pLight[nLt].Direction[0] ;
+	float DirY=m_Q3Map->m_pLight[nLt].Direction[1] ;
+	float DirZ=m_Q3Map->m_pLight[nLt].Direction[2] ;
+	
+
+	if((DirY>1.0-CAMERA_EPSILON) && (DirY<1.0+CAMERA_EPSILON)) // camera is pointing directly up
+	{
+		DirX=0.0f ;
+		DirY=1.0f ;
+		DirZ=0.000001f ;
+	}
+	else
+		if((DirY>-1.0-CAMERA_EPSILON) && (DirY<-1.0+CAMERA_EPSILON)) // camera is pointing directly down
+		{
+			DirX=0.0f ;
+			DirY=-1.0f ;
+			DirZ=0.000001f ;
+		}
+	
+	light->setPosition(Ogre::Vector3(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]));
+	light->setDirection(Ogre::Vector3(DirX, DirY, DirZ));
+			
+	light->setSpotlightRange(Degree(m_Q3Map->m_pLight[nLt].Angle-5.0), Degree(m_Q3Map->m_pLight[nLt].Angle), 1.0) ;
+	light->setVisible(true) ;
+
+	// setup the camera
+	pCamera->setAspectRatio(1) ;
+	pCamera->yaw(Ogre::Radian(0)) ;
+	pCamera->roll(Ogre::Radian(0)) ;
+	pCamera->pitch(Ogre::Radian(0)) ;
+	pCamera->setPosition(m_Q3Map->m_pLight[nLt].Position[0], m_Q3Map->m_pLight[nLt].Position[1], m_Q3Map->m_pLight[nLt].Position[2]) ;
+	pCamera->setDirection(DirX, DirY, DirZ) ;
+	pCamera->setFOVy( Degree(m_Q3Map->m_pLight[nLt].Angle ) ) ;
+
+	return true ;
+
+}
+
+
+void OgreFramework::UpdateVisibleZoneList(char* pZoneVis, unsigned short* pVisibleZoneList, int* pMaxVisibleZone)
+{
+	int nZone=0 ;
+	int nMaxVisibleZone=0 ;
+
+	for(nZone=0 ; nZone<m_Q3Map->m_nMaxZone ; nZone++)
+		if(pZoneVis[nZone]==ZONE_VISIBLE)
+			pVisibleZoneList[nMaxVisibleZone++]=nZone ;
+
+	*pMaxVisibleZone=nMaxVisibleZone ;
+
+}
+
+void OgreFramework::SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags)
+{
+
+		int nListPos=0 ;
+		int nZone=0 ;
+		int nMaxListPos=*pMaxVisibleZone ;
+
+
+
+		for(nListPos=0 ; nListPos<nMaxListPos ; nListPos++)
+		{
+			nZone=pVisibleZoneList[nListPos] ;
+
+				// if the zone node is not already attached, attach it.
+
+				if( m_nOpaqueNodeUsed[nZone] && (nMaterialFlags&MAT_OPAQUE) && !m_pOpaqueNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
+
+				if( m_nTransNodeUsed[nZone] && (nMaterialFlags&MAT_GEL) && !m_pTransNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
+
+				if( m_nLampNodeUsed[nZone] && (nMaterialFlags&MAT_LAMP) && !m_pLampNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
+
+				if( m_nGlowNodeUsed[nZone] && (nMaterialFlags&MAT_GLOW) && !m_pGlowNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
+
+		}
+
+
+			
+/*
+		if(m_nDebugLightBox)
+		{
+			int nLt=0 ;
+			int nMaxLight=m_Q3Map->m_nLightMax ;
+
+			for(nLt=0 ; nLt<nMaxLight ; nLt++)
+				if(m_chLightVis[nLt]==LIGHT_VISIBLE)
+				{
+					m_pLightMO[nLt]->setVisible(true) ;
+
+				}
+				else
+					m_pLightMO[nLt]->setVisible(false) ;
+
+
+
+		}
+
+		if(m_nPortalDebug)
+		{
+			int nPt=0 ;
+			int nMaxPortal=m_Q3Map->m_iNumPortals ;
+
+			for(nPt=0 ; nPt<nMaxPortal ; nPt++)
+				if(
+							(m_chPortalVis[nPt]&PORTAL_VISIBLE) 
+							&&
+							(m_chPortalState[nPt]&PORTALSTATE_CLOSED)
+					)
+					m_pPortalMO[nPt]->setVisible(true) ;
+				else
+					m_pPortalMO[nPt]->setVisible(false) ;
+		}		
+			
+	*/
+}
+
+
+void OgreFramework::SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags, int nLight)
+{
+
+		nLight=IGNORE_LIGHT ;
+
+		int nListPos=0 ;
+		int nZone=0 ;
+		int nMaxListPos=*pMaxVisibleZone ;
+
+		int nLightZone=0 ;
+		int nMaxLightZone=0 ;
+		int nFoundZone=0 ;
+
+
+		for(nListPos=0 ; nListPos<nMaxListPos ; nListPos++)
+		{
+			nZone=pVisibleZoneList[nListPos] ;
+
+			// is this zone touched by this light?
+			if(nLight!=IGNORE_LIGHT)
+			{
+				nMaxLightZone=m_Q3Map->m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+
+				nFoundZone=0 ;
+				for(nLightZone=0 ; nLightZone<nMaxLightZone ; nLightZone++)
+					if(m_Q3Map->m_nLightTouchesZone[nLight][nLightZone]==nZone)
+					{
+						nFoundZone=1 ;
+						break ;
+					}
+
+			}
+			else
+				nFoundZone=1 ;
+
+
+			if(nFoundZone) // if the light touches this zone, or we're ignoring lights
+			{
+				// if the zone node is not already attached, attach it.
+
+				if( m_nOpaqueNodeUsed[nZone] && (nMaterialFlags&MAT_OPAQUE) && !m_pOpaqueNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pOpaqueNode[nZone]) ;
+
+				if( m_nTransNodeUsed[nZone] && (nMaterialFlags&MAT_GEL) && !m_pTransNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pTransNode[nZone]) ;
+
+				if( m_nLampNodeUsed[nZone] && (nMaterialFlags&MAT_LAMP) && !m_pLampNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pLampNode[nZone]) ;
+
+				if( m_nGlowNodeUsed[nZone] && (nMaterialFlags&MAT_GLOW) && !m_pGlowNode[nZone]->isInSceneGraph() )
+					m_pSceneMgr->getRootSceneNode()->addChild(m_pGlowNode[nZone]) ;
+			}
+		}
+
+}
+
+bool OgreFramework::LightTouchesZone(int nLight, int nZone)
+{
+		int nLightZone=0 ;
+		int nMaxLightZone=0 ;
+
+		nMaxLightZone=m_Q3Map->m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+				
+		for(nLightZone=0 ; nLightZone<nMaxLightZone ; nLightZone++)
+			if(m_Q3Map->m_nLightTouchesZone[nLight][nLightZone]==nZone)
+				return true ;
+
+		return false ;
+}
+
+
+// last chance to cull some more multizone lights
+// Then we set all zones the remaining multizone lights touch to visible so that we get correct shadows
+void OgreFramework::CheckMultiZoneLights(int nCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis)
+{
+	int nLightMax=m_Q3Map->m_nMaxMultiZoneLight ;
+	int nLight=0 ;
+	int nLightIndex=0 ;
+//	int nLightVal=0 ;
+	int nOpenPortals=0 ;
+//	int nZoneHasOpenPortals=0 ;
+	int nPortal=0 ;
+	int nPortalIndex=0 ;
+	int nMaxPortal=0 ;
+//	int nZone=0 ;
+//	int nMaxZone=0 ;
+//	int nZoneIndex=0 ;
+
+	int nSubLightMax=0 ;
+//	int nSubLightIndex=0 ;
+	int nSubLight=0 ;
+	int nSubLightStart=0 ;
+
+	int nPortalLightMax=0 ;
+	int nPortalLightIndex=0 ;
+//	int nPortalLight=0 ;
+
+	int nCentreZone=0 ;
+
+
+	for(nLightIndex=0 ; nLightIndex<nLightMax ; nLightIndex++)
+	{
+		nLight=m_Q3Map->m_nMultiZoneLight[nLightIndex] ;
+		if(pLightVis[nLight]==LIGHT_VISIBLE) // try to kill multizone lights that are currently set as visible
+		{
+
+			////////////////////////////////////////////////////////////////////////////////////////////////////////////.
+			// if the zone that contains the centre isn't visible, 
+			// and the portals that the light touches are closed,
+			// then this light can't be visible anywhere else
+
+			nCentreZone=m_Q3Map->m_pLight[nLight].CentreZone ;
+			
+			
+			// is the zone that contains the light centre not visible?
+			if(pZoneVis[nCentreZone]!=ZONE_VISIBLE)
+			{
+				// check the portals on the centre sublight zone.  
+				// If the ones that the light touches are closed, 
+				// then this light can't be visible
+
+				
+				nMaxPortal=m_Q3Map->m_nZoneTouchesPortal[nCentreZone][INDEX_PORTALCOUNT] ;
+				nOpenPortals=0 ;
+				nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
+
+				for(nPortalIndex=0 ; nPortalIndex<nMaxPortal ; nPortalIndex++)
+				{
+					nPortal=m_Q3Map->m_nZoneTouchesPortal[nCentreZone][nPortalIndex] ;
+
+					// if portal's open...
+					if(m_chPortalState[nPortal]&PORTALSTATE_OPEN)
+					{
+						nPortalLightMax=m_Q3Map->m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT] ;
+						
+						// scan all the lights that touch this portal to see if our current light is one of them
+						for(nPortalLightIndex=0 ; nPortalLightIndex<nPortalLightMax ; nPortalLightIndex++)
+							if(m_Q3Map->m_nPortalTouchesLight[nPortal][nPortalLightIndex]==nLight)
+							{
+								nOpenPortals=1 ;
+								break ;
+							}
+
+					}// end if portal is open
+
+					if(nOpenPortals) break ; // get out if we found an open portal that the light touches
+				}// end for portals
+
+
+
+				// if none of the portals touched by the centre light were open, set this light and it's sublights to not visible
+				if(nOpenPortals==0)
+				{
+					pLightVis[nLight]=LIGHT_UNCHECKED ;
+
+					nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
+					nSubLightMax=nSubLightStart+m_Q3Map->m_pLight[nLight].ZoneCount ; 
+
+					for(nSubLight=nSubLightStart ; nSubLight<nSubLightMax ; nSubLight++)
+						pSubLightVis[nSubLightStart]=LIGHT_UNCHECKED ;
+
+				}// end if no light centre portals that touched lights were open
+
+
+
+			}// end if light centre zone isn't visible
+
+		}// end if light is visibile
+
+	}// end for lightindex
+
+}
+
+
+// for lights that touch multiple zones, work out what additional zones we need to make
+// visible in order that lighting will come out with correct shadows.
+void OgreFramework::AddZonesFromMultiZoneLights(char* pZoneVis, char* pLightVis, char* pSubLightVis)
+{
+	int nLightMax=m_Q3Map->m_nMaxMultiZoneLight ;
+	int nLight=0 ;
+	int nLightIndex=0 ;
+	float flMinX=0.0f ;
+	float flMaxX=0.0f ;
+	float flMinY=0.0f ;
+	float flMaxY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxZ=0.0f ;
+
+	int nSubLightMax=0 ;
+//	int nSubLightIndex=0 ;
+	int nSubLight=0 ;
+	int nSubLightStart=0 ;
+	int nSubLightFirst=0 ;
+
+	int nInnerLight=0 ;
+
+
+	for(nLightIndex=0 ; nLightIndex<nLightMax ; nLightIndex++)
+	{
+		nLight=m_Q3Map->m_nMultiZoneLight[nLightIndex] ;
+		if(pLightVis[nLight]==LIGHT_VISIBLE)
+		{
+			nSubLightStart=m_Q3Map->m_pLight[nLight].SubLightStart ; // the first sublight also contains the light centre
+			nSubLightFirst=nSubLightStart+1 ;// start from the first sublight after the one containing the centre
+			nSubLightMax=nSubLightStart+m_Q3Map->m_pLight[nLight].ZoneCount ; 
+			
+
+			for(nSubLight=nSubLightStart ; nSubLight<nSubLightMax ; nSubLight++)	
+				if(pSubLightVis[nSubLight]==LIGHT_VISIBLE) // sublight is visible (and unchecked)
+				{
+					// create the new AABB
+					// this is bounded by this sublight and the centre holding sublight.  
+					flMinX = m_Q3Map->m_SubLight[nSubLight].Min[0] < m_Q3Map->m_SubLight[nSubLightStart].Min[0] ? m_Q3Map->m_SubLight[nSubLight].Min[0] : m_Q3Map->m_SubLight[nSubLightStart].Min[0] ; 
+					flMinY = m_Q3Map->m_SubLight[nSubLight].Min[1] < m_Q3Map->m_SubLight[nSubLightStart].Min[1] ? m_Q3Map->m_SubLight[nSubLight].Min[1] : m_Q3Map->m_SubLight[nSubLightStart].Min[1] ; 
+					flMinZ = m_Q3Map->m_SubLight[nSubLight].Min[2] < m_Q3Map->m_SubLight[nSubLightStart].Min[2] ? m_Q3Map->m_SubLight[nSubLight].Min[2] : m_Q3Map->m_SubLight[nSubLightStart].Min[2] ; 
+				
+					flMaxX = m_Q3Map->m_SubLight[nSubLight].Max[0] > m_Q3Map->m_SubLight[nSubLightStart].Max[0] ? m_Q3Map->m_SubLight[nSubLight].Max[0] : m_Q3Map->m_SubLight[nSubLightStart].Max[0] ; 
+					flMaxY = m_Q3Map->m_SubLight[nSubLight].Max[1] > m_Q3Map->m_SubLight[nSubLightStart].Max[1] ? m_Q3Map->m_SubLight[nSubLight].Max[1] : m_Q3Map->m_SubLight[nSubLightStart].Max[1] ; 
+					flMaxZ = m_Q3Map->m_SubLight[nSubLight].Max[2] > m_Q3Map->m_SubLight[nSubLightStart].Max[2] ? m_Q3Map->m_SubLight[nSubLight].Max[2] : m_Q3Map->m_SubLight[nSubLightStart].Max[2] ; 
+				
+					for(nInnerLight=nSubLightStart ; nInnerLight<nSubLightMax ; nInnerLight++)
+					{
+
+						
+						if(
+									(nInnerLight!=nSubLight) // no need to test itself
+								&&(pZoneVis[  m_Q3Map->m_SubLight[nInnerLight].Zone  ] != ZONE_VISIBLE) // don't test if already visible
+								// if overlap, InnerLight's zone is visible
+								&&(flMinX<m_Q3Map->m_SubLight[nInnerLight].Max[0]) && (flMaxX>m_Q3Map->m_SubLight[nInnerLight].Min[0])
+								&&(flMinY<m_Q3Map->m_SubLight[nInnerLight].Max[1]) && (flMaxY>m_Q3Map->m_SubLight[nInnerLight].Min[1])
+								&&(flMinZ<m_Q3Map->m_SubLight[nInnerLight].Max[2]) && (flMaxZ>m_Q3Map->m_SubLight[nInnerLight].Min[2])
+							)
+						{
+							pZoneVis[  m_Q3Map->m_SubLight[nInnerLight].Zone  ]=ZONE_VISIBLE ; // flag this zone as visible
+							m_nTotalTriangles+=m_nZoneTriangleCount[ m_Q3Map->m_SubLight[nInnerLight].Zone ] ; // just some stats for interest
+						}
+
+					} // end for innerlight
+					
+				}// end if sublight is visible
+
+		}// end if light is visible
+
+	}// end for nLightIndex
+
+}
+
+// scan all the unchecked portals in a subzone to see if they are visible, 
+// then move into any visible subzones and recurse.
+// scalex and scaley will convert the screen space numbers (-1 to 1) into frustum numbers (varies, often -0.5ish to 0.5ish) which is probably due to screen aspect ratios etc
+
+// we also add visible lights if they are in the view frustum
+void OgreFramework::PortalScan(Ogre::Camera *pCamera, int nZone, Ogre::Real ScaleX, Ogre::Real ScaleY, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList)
+{
+	Ogre::Real OrigL, OrigR, OrigT, OrigB ; // original frustum extents
+	Ogre::Real PortalL, PortalR, PortalT, PortalB ; // frustum extents per each portal in this zone
+	pCamera->getFrustumExtents(OrigL, OrigR, OrigT, OrigB) ;
+	
+
+	
+
+	Ogre::AxisAlignedBox AAB ;
+
+
+	int nPortalMax=m_Q3Map->m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT] ;
+	int nPortalIndex=0 ;
+	int nPortal=0 ;
+
+	int nPortalZoneMax=0 ;
+	int nPortalZone=0 ;
+	int nPortalZoneIndex=0 ;
+
+
+	//////////////////////////////////////////////////////////////////////////////////////
+	//
+	// LIGHTING CHECKS
+	//
+
+	int nLight=0;
+	int nLightVal=0 ;
+//	int nLightIndex=0 ;
+//	int nMaxLight=0 ;
+
+	int nSubLight=0 ;
+	int nSubLightIndex=0 ;
+	int nMaxSubLight=0 ;
+//	int nSubLightVal=0 ;
+
+	
+	// check all lights completely contained in this zone to see if they're visible
+	nMaxSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
+	for(nSubLightIndex=0 ; nSubLightIndex<nMaxSubLight ; nSubLightIndex++)
+	{
+		nSubLight=m_Q3Map->m_nZoneTouchesSubLight[nZone][nSubLightIndex] ;
+		//nSubLightVal=m_chSubLightVis[nSubLight] ;
+
+		nLight=m_Q3Map->m_SubLight[nSubLight].Light ;
+		nLightVal=pLightVis[nLight] ;
+
+		// if we haven't previously established that the light is visible or out of the frustum, check it.
+
+			AAB.setExtents(m_Q3Map->m_SubLight[nSubLight].Min[0], m_Q3Map->m_SubLight[nSubLight].Min[1], m_Q3Map->m_SubLight[nSubLight].Min[2], m_Q3Map->m_SubLight[nSubLight].Max[0], m_Q3Map->m_SubLight[nSubLight].Max[1], m_Q3Map->m_SubLight[nSubLight].Max[2]) ;
+			if(pCamera->isVisible(AAB)) // sublight is visible
+			{
+				// flag this light and sublight as visible
+				if((nLightVal!=LIGHT_VISIBLE) && (*pMaxVisibleLight<MAXVISIBLELIGHT))
+				{
+					pVisibleLightList[*pMaxVisibleLight]=nLight ;
+					*pMaxVisibleLight=*pMaxVisibleLight+1 ;
+				}
+				pSubLightVis[nSubLight] = pLightVis[nLight] = LIGHT_VISIBLE ;
+				
+			}
+
+
+	}// end for lights in zone
+	
+
+	//
+	///////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+	pZoneVis[nZone]=ZONE_VISIBLE ; // flag this zone as visible
+	m_nTotalTriangles+=m_nZoneTriangleCount[nZone] ; // just some stats for interest
+
+
+	// loop through all the portals in this zone
+	for(nPortalIndex=0 ; nPortalIndex<nPortalMax ; nPortalIndex++)
+	{
+		
+
+		nPortal=m_Q3Map->m_nZoneTouchesPortal[nZone][nPortalIndex] ;
+
+
+		if((pPortalVis[nPortal]&PORTAL_VISCHECK)==0) // portal hasn't already been checked
+		{
+
+			pPortalVis[nPortal] |= PORTAL_VISCHECK ; // flag portal as vischecked
+			AAB.setExtents(m_Q3Map->m_pPortals[nPortal].Min[0], m_Q3Map->m_pPortals[nPortal].Min[1], m_Q3Map->m_pPortals[nPortal].Min[2], m_Q3Map->m_pPortals[nPortal].Max[0], m_Q3Map->m_pPortals[nPortal].Max[1], m_Q3Map->m_pPortals[nPortal].Max[2]) ;
+		
+			if(pCamera->isVisible(AAB)) // portal is in the view frustum
+			{			
+
+				pPortalVis[nPortal] |= PORTAL_VISIBLE ; // flag portal as visible
+
+				// if the portal is open, go in and check the new zone.
+				if(m_chPortalState[nPortal]&PORTALSTATE_OPEN)
+				{
+			
+					// calculate the new frustum extents through this portal
+					PortalL=OrigL ;
+					PortalR=OrigR ;
+					PortalT=OrigT ;
+					PortalB=OrigB ;
+
+					if(CalculatePortalFrustum(pCamera, nPortal, &PortalL, &PortalR, &PortalT, &PortalB, ScaleX, ScaleY))
+					{
+
+
+
+
+
+						// Loop through all the zones attached to this portal
+						nPortalZoneMax=m_Q3Map->m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
+						for(nPortalZoneIndex=0 ; nPortalZoneIndex<nPortalZoneMax ; nPortalZoneIndex++)
+						{
+							nPortalZone=m_Q3Map->m_nPortalTouchesZone[nPortal][nPortalZoneIndex] ;
+							if(pZoneVis[nPortalZone]==ZONE_UNCHECKED) // don't go back into zones we've already scanned.
+							{
+
+								pCamera->setFrustumExtents(PortalL, PortalR, PortalT, PortalB) ; // set the frustum extents
+
+								// recurse
+								//m_nRecurseCount++ ;
+								PortalScan(pCamera, nPortalZone, ScaleX, ScaleY, pZoneVis, pLightVis, pSubLightVis, pPortalVis, pMaxVisibleLight, pVisibleLightList) ;
+								//m_nRecurseCount-- ;
+
+								
+								
+							}// end if zone hasn't already been checked
+
+						}// end scanning all zones connected by this portal
+
+					}// end if frustum is still active
+
+				}// end if portal is open
+				
+			}// end if portal is in the view frustum
+		
+		}// end if portal hasn't been checked	
+
+		// reset the frustum
+		pCamera->setFrustumExtents(OrigL, OrigR, OrigT, OrigB) ; // reset the original frustum extents
+	
+	}// end for portalindex
+
+
+}
+
+// gives new frustum settings, and returns 0 if the frustum has been killed completely.
+int OgreFramework::CalculatePortalFrustum(Ogre::Camera *pCamera, int nPortal, Ogre::Real* pPortalL, Ogre::Real* pPortalR, Ogre::Real* pPortalT, Ogre::Real* pPortalB, Ogre::Real ScaleX, Ogre::Real ScaleY)
+{
+
+
+	// if the camera is actually inside the portal then don't change the frustum but return OK
+	Vector3 CamPos=pCamera->getPosition() ;
+
+	if(
+				(CamPos.x>=m_Q3Map->m_pPortals[nPortal].Min[0]) && (CamPos.x<=m_Q3Map->m_pPortals[nPortal].Max[0])
+			&&(CamPos.y>=m_Q3Map->m_pPortals[nPortal].Min[1]) && (CamPos.y<=m_Q3Map->m_pPortals[nPortal].Max[1])
+			&&(CamPos.z>=m_Q3Map->m_pPortals[nPortal].Min[2]) && (CamPos.z<=m_Q3Map->m_pPortals[nPortal].Max[2])
+		)
+		return 1 ;
+
+
+
+
+
+	int nLoop=0 ;
+	int nBehindPoint=0 ; // keep track of how many transformed points are behind the camera
+	//Real OrigL=*pPortalL ;
+	//Real OrigR=*pPortalR ;
+	//Real OrigT=*pPortalT ;
+	//Real OrigB=*pPortalB ;
+
+	Real MinX=MINMAXLIMIT ;
+	Real MaxX=-MINMAXLIMIT ;
+	Real MaxY=-MINMAXLIMIT ;
+	Real MinY=MINMAXLIMIT ;
+
+
+	// set portal corners as 8 individual points.  order is xyz, Xyz, xYz, XYz, xyZ, XyZ, xYZ, XYZ, 
+	Vector3 xyz[8] ;
+
+	
+	xyz[0].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+	xyz[0].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+	xyz[0].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+	xyz[1].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+	xyz[1].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+	xyz[1].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+	xyz[2].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+	xyz[2].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+	xyz[2].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+	xyz[3].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+	xyz[3].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+	xyz[3].z=m_Q3Map->m_pPortals[nPortal].Min[2] ;
+
+	xyz[4].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+	xyz[4].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+	xyz[4].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+	xyz[5].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+	xyz[5].y=m_Q3Map->m_pPortals[nPortal].Min[1] ;
+	xyz[5].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+	xyz[6].x=m_Q3Map->m_pPortals[nPortal].Min[0] ;
+	xyz[6].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+	xyz[6].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+	xyz[7].x=m_Q3Map->m_pPortals[nPortal].Max[0] ;
+	xyz[7].y=m_Q3Map->m_pPortals[nPortal].Max[1] ;
+	xyz[7].z=m_Q3Map->m_pPortals[nPortal].Max[2] ;
+
+	// transform the points to eyespace
+	for(nLoop=0 ; nLoop<8 ; nLoop++)
+		xyz[nLoop]=m_ViewMatrix*xyz[nLoop] ;//pCamera->getViewMatrix(true)*xyz[nLoop] ;
+
+	// transform the points to screen space
+	for(nLoop=0 ; nLoop<8 ; nLoop++)
+		if(xyz[nLoop].z<0) // less than zero means point is in front of camera
+		{
+			xyz[nLoop]=m_ProjectionMatrix*xyz[nLoop] ;// pCamera->getProjectionMatrix()*xyz[nLoop] ;
+			if(xyz[nLoop].x<MinX) MinX=xyz[nLoop].x ;
+			if(xyz[nLoop].x>MaxX) MaxX=xyz[nLoop].x ;
+			if(xyz[nLoop].y<MinY) MinY=xyz[nLoop].y ;
+			if(xyz[nLoop].y>MaxY) MaxY=xyz[nLoop].y ;
+
+		}
+		else // point is behind the camera
+			nBehindPoint++ ;
+		
+
+
+	
+	MinX*=ScaleX ;
+	MaxX*=ScaleX ;
+	MinY*=ScaleY ;
+	MaxY*=ScaleY ;
+	
+	// apply the stereofrustum tweak if needed
+	//float flTweak=0.0f ;
+	//if(m_flStereoFrustumTweak!=0.0f)
+	//{
+	//	MinX-=m_flStereoFrustumTweak ;
+	//	MaxX+=m_flStereoFrustumTweak ;
+	//}
+
+
+	// if we have more than three behindpoints, don't cull
+	if(nBehindPoint>3) return 1 ;
+
+	// use these to cut down the frustum
+	if(MinX>*pPortalL) *pPortalL=MinX ;
+	if(MaxX<*pPortalR) *pPortalR=MaxX ;
+	if(MinY>*pPortalB) *pPortalB=MinY ;
+	if(MaxY<*pPortalT) *pPortalT=MaxY ;
+
+
+
+	
+
+	
+
+	// check if frustum has been cut out of existence
+	// culling at this point didn't work, so this is a hack to make if function.
+	if((*pPortalL>=*pPortalR) || (*pPortalB>=*pPortalT))
+		return 0 ;
+
+
+	/*
+	if(*pPortalL>=*pPortalR)
+	{
+		*pPortalL=(*pPortalL+*pPortalR)/2.0-0.01 ;
+		*pPortalR=*pPortalL+0.02 ;
+	}
+
+	if(*pPortalB>=*pPortalT)
+	{
+		*pPortalB=(*pPortalB+*pPortalT)/2.0-0.01 ;
+		*pPortalT=*pPortalB+0.02 ;
+	}
+	*/
+
+		
+		//return 0 ;
+
+
+	return 1 ;
+}
+
+
+
+
+
+
+
+
+ /***********************************************************************************************************\
+                                               
+                                            LIGHTING SETUP
+                                                
+ \***********************************************************************************************************/
+
+
+
+
+
+void OgreFramework::initLight() 
+{
+//	char chMessage[1024] ;
+
+		// these lights only have placeholder settings to begin with, since they get moved around and reused thoughout the level.
+	
+		int nLt=0 ;
+		int nMaxLt=MAXLIGHTPERLOOP ;
+		Light *light;
+		char chLightName[1024] ;
+
+
+		
+
+		for(nLt=0 ; nLt<nMaxLt ; nLt++)
+		{
+			sprintf(chLightName, "LT%02i", nLt) ;
+			
+			light = m_pSceneMgr->createLight(chLightName);
+			light->setType(Light::LT_SPOTLIGHT);
+			light->setCastShadows(true);
+			light->setVisible(false) ;
+
+		}
+	
+}
+
+ /***********************************************************************************************************\
+                                               
+                                            CONFIG FILE
+                                                
+ \***********************************************************************************************************/
+
+void OgreFramework::ParseBZNConfig(void)
+{
+	const int KVSIZE=1024 ;
+	// make sure the config is a string
+	int nConfigPos=-1 ;
+//	int nPos=0 ;
+	int nKeyPos=0 ;
+	int nValuePos=0 ;
+
+	char chKey[KVSIZE] ;
+	char chValue[KVSIZE] ;
+	int nValue=0 ;
+
+	
+
+	while(nConfigPos<BZN_CONFIG_SIZE)
+	{
+		// scan forward to find the next key
+		while	(			
+								(++nConfigPos<BZN_CONFIG_SIZE)
+						&&	((m_chBZNConfig[nConfigPos]<'A') || (m_chBZNConfig[nConfigPos]>'z'))
+					) ;
+
+		if(nConfigPos<BZN_CONFIG_SIZE)
+		{
+
+
+
+			// find the end of the key
+			nKeyPos=0 ;
+			while	((m_chBZNConfig[nConfigPos]!=' ') && (m_chBZNConfig[nConfigPos]!='/') && (m_chBZNConfig[nConfigPos]!=0x0A) && (m_chBZNConfig[nConfigPos]!=0x0D))
+			{
+				chKey[nKeyPos++]=m_chBZNConfig[nConfigPos++] ;
+				if((nConfigPos==BZN_CONFIG_SIZE) || (nKeyPos==KVSIZE))
+					break ;
+			}
+
+			if((nConfigPos<BZN_CONFIG_SIZE) && (nKeyPos<KVSIZE))
+			{
+				chKey[nKeyPos]='\0' ; // null terminate the key
+			
+				// scan off the the number
+				nValuePos=0 ;
+				
+
+				while	((m_chBZNConfig[nConfigPos]!=0x0A) && (m_chBZNConfig[nConfigPos]!=0x0D) && (m_chBZNConfig[nConfigPos]!='/'))
+				{
+					if(
+									((m_chBZNConfig[nConfigPos]>='0') && (m_chBZNConfig[nConfigPos]<='9'))
+							||	(m_chBZNConfig[nConfigPos]=='-') 
+							||	(m_chBZNConfig[nConfigPos]=='.')
+						)
+						chValue[nValuePos++]=m_chBZNConfig[nConfigPos] ;
+
+					nConfigPos++ ;
+					if((nConfigPos==BZN_CONFIG_SIZE) || (nKeyPos==KVSIZE))
+						break ;
+				}
+
+				if((nConfigPos<BZN_CONFIG_SIZE) && (nValuePos<KVSIZE))
+				{
+					chValue[nValuePos]='\0' ; // null terminate the value
+				
+					// convert value string to a float
+					nValue=atoi(chValue) ;
+
+					// assign that value
+					if(strcmp("r_shadowmapsize", chKey)==0)		{ m_nShadowMapSize=nValue ; if(m_nShadowMapSize<2) m_nShadowMapSize=2 ; }
+					if(strcmp("r_shadowrgbsize", chKey)==0)		{ m_nShadowRGBSize=nValue ; if(m_nShadowRGBSize<2) m_nShadowRGBSize=2 ; }
+					if(strcmp("r_colouredshadow", chKey)==0)	{ m_nColouredShadow=nValue ; }
+					if(strcmp("r_renderhdr", chKey)==0)				{ m_nRenderHDR=nValue ; }
+					if(strcmp("r_maxgpuquery", chKey)==0)			{ m_nMaxGPUQuery=nValue ; if(m_nMaxGPUQuery<0) m_nMaxGPUQuery=0 ; if(m_nMaxGPUQuery>MAXGPUQUERY) m_nMaxGPUQuery=MAXGPUQUERY ; }
+
+					//sprintf(m_chBug, "Key: %s, Value: %i", chKey, nValue) ;
+					//m_pLog->logMessage(m_chBug);
+				
+				}// end found end of value
+
+
+
+
+
+
+
+			}// end found end of key
+
+
+
+
+
+		}// end found start of key
+						
+
+
+	}// end scanning whole config
+
+
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreFramework.hpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreFramework.hpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreFramework.hpp	(revision 11817)
@@ -0,0 +1,724 @@
+/*
+===========================================================================
+Copyright (C) 2010 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#ifndef OGRE_FRAMEWORK_HPP
+#define OGRE_FRAMEWORK_HPP
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#include <OgreCamera.h>
+#include <OgreEntity.h>
+#include <OgreLogManager.h>
+#include <OgreOverlay.h>
+#include <OgreOverlayElement.h>
+#include <OgreOverlayManager.h>
+#include <OgreRoot.h>
+#include <OgreViewport.h>
+#include <OgreSceneManager.h>
+#include <OgreRenderWindow.h>
+#include <OgreConfigFile.h>
+#include <OgreManualObject.h>
+#include <OgreMaterialManager.h>
+#include <OgreRenderSystem.h> 
+#include <OgreOverlayContainer.h> 
+#include <OgreHardwarePixelBuffer.h>
+#include <OgreRenderQueueListener.h>
+#include <OgreHardwareOcclusionQuery.h>
+#include <OgreTextureUnitState.h>
+#include "OgreGpuCommandBufferFlush.h"
+
+
+#include "ExampleFrameListener.h"
+//#include <OgreFrameListener.h>
+//#include <OgreRenderTargetListener.h>
+
+
+#include <OIS/OIS.h>
+#include <OIS/OISEvents.h>
+#include <OIS/OISInputManager.h>
+#include <OIS/OISKeyboard.h>
+#include <OIS/OISMouse.h>
+
+#include "Q3Map.h"
+
+//#include "JarDebug.h" //!! just for debugging, remove from final build
+
+
+#define CHECKDELETE_ARRAY(x, y)		if(x) { delete [] x ; x=0 ; m_nNewCount-- ; m_nNewCheck[y]-- ;}
+#define CHECKDELETE_POINTER(x, y)  if(x) { delete x		; x=0 ; m_nNewCount-- ; m_nNewCheck[y]-- ;}
+
+enum {
+	NEW_CHECK_m_pRawBspFile=0,
+	NEW_CHECK_m_Q3Map,
+	NEW_CHECK_m_pZoneMO,
+	NEW_CHECK_m_pZoneMesh,
+	NEW_CHECK_m_pZoneEntity,
+	NEW_CHECK_m_pZoneEntityMaterialType,
+	NEW_CHECK_m_pZoneEntityMaterial_Base,
+	NEW_CHECK_m_pZoneEntityMaterial_Fast,
+	NEW_CHECK_m_pZoneEntityMaterial_Black,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShColour,
+	NEW_CHECK_m_pZoneEntityMaterial_Shadow,
+	NEW_CHECK_m_pZoneEntityMaterial_ShadeFront,
+	NEW_CHECK_m_pZoneEntityMaterial_ShadeBack,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShPosition,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShDiffuse,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShFuncTNB,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShSpecular,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShEmissive,
+	NEW_CHECK_m_pZoneEntityMaterial_DfShMix,
+	NEW_CHECK_pVertIndex,
+	NEW_CHECK_m_pEntityInfo,
+	NEW_CHECK_m_pVisibleEntity,
+	NEW_CHECK_m_pFrustumEntity,
+	MAX_NEW_CHECK
+} ;
+
+#define MAXFRAME 1000 // debugging/testing, copy out data on a per-frame basis
+
+#define MAXGPUQUERY 4
+
+#define MAXVISIBLELIGHT	128 // most shadow lights ever visible.
+#define MAXLIGHTPERLOOP	1 // most shadow lights rendered per deferred shader sub-loop.  So shadow lights are rendered in lots of 4// no longer used
+
+#define NEARCLIP 1			// camera default near clip distance
+#define FARCLIP 10000		// camera default far clip distance
+
+#define CAMERA_EPSILON  0.000001f // small value to check for up/down cameras that would break with Ogre's fixed Yaw.
+
+#define IGNORE_LIGHT		-1
+
+enum GoggleMode
+{
+	GOGGLE_MODE_OFF = 0,
+	GOGGLE_MODE_TEST,
+	GOGGLE_MODE_ON,
+	GOGGLE_MODE_MAX
+} ;
+
+#define MAT_OPAQUE		1				// Typical solid stuff.  Can have emissive parts.
+#define MAT_TRANS			2				// Unused
+#define MAT_GLOW			4				// Only rendered in the deferred shader emmisive pass.  Used to create the hdr bloom for light points.
+#define MAT_GEL				8				// Translucent, colours spotlights that pass through it.
+#define MAT_ALPHAPF		16			// Same as MAT_OPAQUE, but with alpha testing.
+#define MAT_LAMP			32			// The bounding boxes of deferred shading lights (lamps). Rendered as the last phase in deferred shading.
+
+#define BZN_CONFIG_SIZE	1024
+
+class rQueueListener: public Ogre::RenderQueueListener
+{
+public:
+	
+	rQueueListener() {}
+	~rQueueListener() {}
+
+	Ogre::HardwareOcclusionQuery* Query[MAXGPUQUERY] ;
+
+	void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) {}
+	void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String &invocation, bool &skipThisInvocation) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#define MAX_SUBMESH						16	// most submeshes allowed in a mesh.
+#define MAX_ZONEPERENTITY			8		// the most zones an entity can touch at once.
+#define INDEX_ENTITYZONECOUNT	8		// index to value that holds the count of how many zones this entity touches
+#define MAX_LIGHTPERENTITY		64	// most shadowing lights that an entity can be lit by
+#define INDEX_LIGHTPERENTITY	64	// index to value
+typedef struct
+{
+	int Active ;
+	int Visible ;
+	int Frustum ;
+	int LightTouch ;
+
+	int TriangleCount ;
+
+	Ogre::Vector3 Postition ;
+	Ogre::Quaternion Orientation ;
+
+	Ogre::AxisAlignedBox AABB ;
+	Ogre::Vector3 Centre ;
+	float AABBMin[3] ;
+	float AABBMax[3] ;
+
+	unsigned short Zone[MAX_ZONEPERENTITY+1] ;		// the zones this entity touches.  Last value is a count of how many zones were touched.
+	unsigned short Light[MAX_LIGHTPERENTITY+1] ;	// the shadow casting spotlights this entity touches.  Last value is a count of how many lights.
+
+	int MaxSubMesh ;
+	int SubMeshMaterialType[MAX_SUBMESH] ;
+
+	Ogre::Entity*				pEnt ;
+	Ogre::SceneNode*    pMasterNode ;
+
+	Ogre::MaterialPtr		Material_Base[MAX_PROJECTORTEX][MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_Fast[MAX_PROJECTORTEX][MAX_SUBMESH] ;
+
+	Ogre::MaterialPtr		Material_Black[MAX_SUBMESH] ;
+
+	Ogre::MaterialPtr		Material_DfShColour[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_Shadow[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_ShadeFront[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_ShadeBack[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_DfShPosition[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_DfShDiffuse[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_DfShFuncTNB[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_DfShSpecular[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_DfShEmissive[MAX_SUBMESH] ;
+	Ogre::MaterialPtr		Material_DfShMix[MAX_SUBMESH] ;
+}
+ENTITYINFO;
+
+typedef struct
+{
+
+	int Type ;
+
+	Ogre::ParticleSystem*	PSystem ;
+	Ogre::SceneNode*			PNode ;
+
+}
+PARTICLEINFO;
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+class OgreFramework : public Ogre::Singleton<OgreFramework>, OIS::KeyListener, OIS::MouseListener, public RenderTargetListener
+{
+public:
+	OgreFramework();
+	~OgreFramework();
+
+	int m_nNewCount ;
+	int m_nNewCheck[MAX_NEW_CHECK] ;
+
+	int m_nStartTime ;
+	int m_nTime ;
+
+//	CJarDebug OFBug ; //!! just for debugging, remove from final build
+	char m_chBug[10240] ;
+	int m_nFrameTime[MAXFRAME][10] ;
+	int m_nFrame ;
+	char m_chFrame[1024] ;
+	int m_nGotInput ;
+
+	void initOgre(Ogre::String wndTitle, OIS::KeyListener *pKeyListener = 0, OIS::MouseListener *pMouseListener = 0);
+	void AdditionalSetup() ;
+
+	void updateOgre(double timeSinceLastFrame);
+	void updateStats();
+	void moveCamera();
+	void getInput();
+
+	bool isOgreToBeShutDown()const{return m_bShutDownOgre;}  
+
+	bool keyPressed(const OIS::KeyEvent &keyEventRef);
+	bool keyReleased(const OIS::KeyEvent &keyEventRef);
+
+	bool mouseMoved(const OIS::MouseEvent &evt);
+	bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id); 
+	bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
+	
+	Ogre::Root*					m_pRoot;
+	Ogre::SceneManager*			m_pSceneMgr;
+	Ogre::RenderWindow*			m_pRenderWnd;
+	Ogre::Camera*				m_pCamera;
+	Ogre::Viewport*				m_pViewport;
+	Ogre::Log*					m_pLog;
+	Ogre::Timer*				m_pTimer;
+
+	Ogre::Camera* m_pCameraCopy ;
+	Ogre::Camera* m_pCameraNoJitter ;
+
+	float m_flAspectRatio ;
+	float m_flFOV ;
+
+
+	//RawFilePtr m_pRawBspFile ;	bool m_bRawBspFileIsLoaded ;
+
+	char *m_pRawBspFile ;	
+	bool m_bRawBspFileIsLoaded ;
+	
+	OIS::InputManager*			m_pInputMgr;
+	OIS::Keyboard*				m_pKeyboard;
+	OIS::Mouse*					m_pMouse;
+
+	int nMap ;
+	Ogre::String m_MapName ;
+	int m_nLoadToggle ;
+
+	int m_nJumpToggle ;
+	int m_nJumpVal;
+
+	int m_nToggle ;
+
+	void UnloadMap(bool bShutdown) ;
+	int LoadMap(void) ;
+	int m_nMapLoaded ;
+
+	int m_nDebugLightBox ;
+	int m_nZoneCullingActive ;
+	int m_nPortalDebug ;
+	int m_nPortalToggle ;
+	int m_nPortalState ; 
+
+	// Add this to OgreFramework and initialize it from 0 to MAXGPUQUERY
+	// If you're good you'll make it private and add some get/set functions, 
+	// I just made it public for now.
+
+	// A value of 0 means don't mess with the GPU buffers at all.  There
+	// might be some systems where the queries cause problems, so let the user 
+	// deactivate the queries completely if desired.
+
+	// A value of 1 means we flush every frame, so no GPU command buffering.
+	// This is good for low FPS because even just 1 buffer gives noticable
+	// input lag.  However users with high FPS can afford a few buffers.
+	
+	int m_nMaxGPUQuery ;
+
+
+	int m_nDebugA ;
+	int m_nDebugB ;
+	int m_nDebugC ;
+	int m_nVisibleLightCount ;
+	int m_nVisibleZoneCount ;
+
+	float m_flDebugMatrix[4][4] ;
+	
+	int m_nRecurseCount ;
+	char m_chDebug[10240] ;
+	float m_flDebug0 ;
+	float m_flDebug1 ;
+	float m_flDebug2 ;
+	float m_flDebug3 ;
+	float m_flDebug4 ;
+	float m_flDebug5 ;
+
+
+	
+	Ogre::ManualObject* m_pGoggleL ;
+	Ogre::ManualObject* m_pGoggleR ;
+	Ogre::SceneNode*		m_pNodeGoggles ;
+	int m_nGoggleMode ;
+	float m_flGoggleAspectRatio	;
+	float m_flGoggleZPos ;
+	float m_flGoggleXGap ;
+	float m_flGoggleXScale ;
+	float m_flGoggleYScale ;
+	int m_nGoggleTestImage ;
+	void DestroyGoggles() ;
+	int CreateGogglesTestImage() ;
+	int CreateGoggles() ;
+
+
+	void UpdateRenderTargets() ;
+
+	double m_GameTime ;
+
+	char m_chBZNConfig[BZN_CONFIG_SIZE] ;
+	void ParseBZNConfig(void) ;
+
+	void FinalShutdown(void) ;
+
+private:
+	OgreFramework(const OgreFramework&);
+	OgreFramework& operator= (const OgreFramework&);
+
+	Ogre::Overlay*				m_pDebugOverlay;
+	Ogre::Overlay*				m_pInfoOverlay;
+	int							m_iNumScreenShots;
+
+	bool						m_bShutDownOgre;
+	
+	Ogre::Vector3				m_TranslateVector;
+	Ogre::Real					m_MoveSpeed; 
+	Ogre::Degree				m_RotateSpeed; 
+	float						m_MoveScale; 
+	Ogre::Degree				m_RotScale;
+
+	int m_nKeyDown_Shift ;
+	int m_nKeyDown_Ctrl ;
+
+
+	
+
+
+	//RawFileManager *mRawFileManager;
+
+	char* m_TempMem ;
+	Q3Map *m_Q3Map;
+
+
+	Ogre::SceneNode*			m_pCubeNode;
+	Ogre::Entity*				m_pCubeEntity;
+
+	Ogre::SceneNode *m_pOpaqueNode[MAX_ZONE] ;
+	int m_nOpaqueNodeUsed[MAX_ZONE] ; 
+	Ogre::SceneNode *m_pTransNode[MAX_ZONE] ;
+	int m_nTransNodeUsed[MAX_ZONE] ;
+	Ogre::SceneNode *m_pLampNode[MAX_ZONE] ;
+	int m_nLampNodeUsed[MAX_ZONE] ;
+	Ogre::SceneNode *m_pGlowNode[MAX_ZONE] ;
+	int m_nGlowNodeUsed[MAX_ZONE] ;
+
+	Ogre::Matrix4	m_ViewMatrix ;
+	Ogre::Matrix4	m_ProjectionMatrix ;
+
+	Ogre::ManualObject** m_pZoneMO ; // the Zone's manualObject array
+	Ogre::MeshPtr* m_pZoneMesh ;
+	Ogre::Entity** m_pZoneEntity ;
+	int* m_pZoneEntityMaterialType ;
+
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_Base[MAX_PROJECTORTEX] ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_Fast[MAX_PROJECTORTEX] ;
+
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_Black ;
+
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShColour ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_Shadow ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_ShadeFront ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_ShadeBack ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShPosition ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShDiffuse ;
+	//Ogre::MaterialPtr* m_pZoneEntityMaterial_DSNormal ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShFuncTNB ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShSpecular ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShEmissive ;
+	//Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShData ;
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_DfShMix ;
+
+	Ogre::MaterialPtr* m_pZoneEntityMaterial_BlurA ;
+
+
+	/////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+	Ogre::MeshPtr* m_pGameMesh ;
+	ENTITYINFO* m_pEntityInfo ;
+	int* m_pVisibleEntity ; // entities that are in a visible zone
+	int* m_pFrustumEntity ; // entities that are in a visible zone and also in the view frustum
+
+	int m_nMaxGameMesh ;
+	int m_nMaxEntity ;
+	int m_nMaxVisibleEntity ;
+	int m_nMaxFrustumEntity ;
+	int m_nVisibleEntityTriangleCount ;
+	int m_nFrustumEntityTriangleCount ;
+	int m_nTotalTriangles ;
+	int m_nZoneTriangleCount[MAX_ZONE] ;
+
+	/////////////////////////////////////////////////////////////////////////////////
+
+	// for debugging/testing, make light volumes into meshes
+	Ogre::ManualObject** m_pLightMO ; // the manualObject array
+	int AddLightCullingBoxes(void) ;
+
+	// for debugging/testing, make portal volumes into meshes
+	Ogre::ManualObject** m_pPortalMO ; // the manualObject array
+	Ogre::Node** m_pPortalNode ; // the node of this portal
+	int AddPortalBoxes(void) ;
+
+	/////////////////////////////////////////////////////////////////////////////////
+
+	
+	
+
+
+	void SetupResourceLocations() ;
+	
+
+
+	float m_flStereoFrustumTweak ; // in stereoscopic mode the portal frustums might be too tight, so enlarge them a bit.
+
+
+	bool m_IsOpenGL ;
+
+	
+	void initLight() ;
+
+	Ogre::Matrix4 CreateTextureViewProjectionMatrix(Ogre::Camera* pCamera) ;
+	bool SetupSingleVisibleLightAndShadowCamera(int nLt, char* pLightVis, unsigned short* pVisibleLightList, Ogre::Camera* pCamera) ;
+	
+
+	int SetupParticles() ;
+	Ogre::ParticleSystem*		m_ps;
+	Ogre::SceneNode*				m_pParticleNode;
+	
+	int m_nMaxParticleSystem ;
+	
+	
+	int ConstructMapFromTriangles(void) ;
+	
+	int SetupGameEntities(void) ;
+	int SetupEntity(int nEntity, char *chMeshName) ;
+	
+	
+
+	int m_nKeyToggle[OIS::KC_MEDIASELECT+1] ; // for preventing multiple key triggers when needed.
+
+	int m_nFlashLight ;
+	
+
+	
+
+
+
+
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// left/mono visibility info
+	char m_chZoneVisL[MAX_ZONE] ;
+	char m_chLightVisL[MAX_LIGHT] ;
+	char m_chSubLightVisL[MAX_SUBLIGHT] ;
+	char m_chPortalVisL[MAX_PORTAL] ;
+	int  m_nMaxVisibleZoneL ;
+	unsigned short m_uVisibleZoneListL[MAX_ZONE] ;				// if MAX_ZONE goes above 65536 this will need to change to an int 
+	int  m_nMaxVisibleLightL ;
+	unsigned short m_uVisibleLightListL[MAXVISIBLELIGHT]; // if MAX_LIGHT goes above 65536 this will need to change to an int
+	int m_nCameraZoneL ; // zone player left eye is in.
+	
+	// right visibility info
+	char m_chZoneVisR[MAX_ZONE] ;
+	char m_chLightVisR[MAX_LIGHT] ;
+	char m_chSubLightVisR[MAX_SUBLIGHT] ;
+	char m_chPortalVisR[MAX_PORTAL] ;
+	int  m_nMaxVisibleZoneR ;
+	unsigned short m_uVisibleZoneListR[MAX_ZONE] ;				// if MAX_ZONE goes above 65536 this will need to change to an int 
+	int  m_nMaxVisibleLightR ;
+	unsigned short m_uVisibleLightListR[MAXVISIBLELIGHT]; // if MAX_LIGHT goes above 65536 this will need to change to an int 
+	int m_nCameraZoneR ; // zone player right eye is in.
+	
+	int m_nCameraZone ;  // zone player is in.
+	
+	
+
+
+
+	char* m_pGlobal_ZoneVis ;
+	char* m_pGlobal_LightVis ;
+	unsigned short* m_pGlobal_VisibleZoneList ;
+	int*  m_pGlobal_MaxVisibleZone ;
+	unsigned short* m_pGlobal_VisibleLightList ;
+	int*  m_pGlobal_MaxVisibleLight ;
+
+	char m_chPortalState[MAX_PORTAL] ;
+	
+	int  m_nMaxVisibleLight ;
+
+
+
+
+
+
+
+	int m_nZoneMOStart[MAX_ZONE+1] ; // index into m_pZoneMO for each zone, since each material within a zone is another manualObject.
+
+	void CalculateZoneVisibility(Ogre::Camera* pCamera, int *pCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList) ;
+	void SetupEntityZones(void) ;
+	void CalculateEntityVisibility(Ogre::Camera* pCamera, char* pZoneVis) ;
+
+	void SetAllLightsOff(void) ;
+	void SetSingleVisibleLight(int nLt, bool bOn) ;
+	void UpdateVisibleZoneList(char* pZoneVis, unsigned short* pVisibleZoneList, int* pMaxVisibleZone) ;
+	
+	void SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags) ;
+	void SetZoneNodeAttachments(unsigned short* pVisibleZoneList, int* pMaxVisibleZone, int nMaterialFlags, int nLight) ;
+	bool LightTouchesZone(int nLight, int nZone) ;
+
+	void PortalScan(Ogre::Camera *pCamera, int nZone, Ogre::Real ScaleX, Ogre::Real ScaleY, char* pZoneVis, char* pLightVis, char* pSubLightVis, char* pPortalVis, int* pMaxVisibleLight, unsigned short* pVisibleLightList) ;
+	int m_nOriginalZoneOpenPortals ;
+	void CheckMultiZoneLights(int nCameraZone, char* pZoneVis, char* pLightVis, char* pSubLightVis) ;
+	void AddZonesFromMultiZoneLights(char* pZoneVis, char* pLightVis, char* pSubLightVis) ;
+	int CalculatePortalFrustum(Ogre::Camera *pCamera, int nPortal, Ogre::Real* pPortalL, Ogre::Real* pPortalR, Ogre::Real* pPortalT, Ogre::Real* pPortalB, Ogre::Real ScaleX, Ogre::Real ScaleY) ;
+
+
+
+
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	
+
+
+
+	//int ApplyCGDefines(void) ;
+	
+
+	
+
+	int m_nSpeedRender ;
+	int m_nRenderHDR ;
+	int m_nColouredShadow ;
+	int m_nShadowMapSize ;
+	int m_nShadowRGBSize ;
+
+	int m_nDisplayInfoMode ;
+	
+	///////////////////////////////////////////////////////////////////////////////////////////
+	// render to texture quasi-deferred shading stuff
+	
+	void CreateRTTAssets() ;
+	void DestroyRTTAssets() ;
+	int m_nRTTAssetsExist ;
+
+	// Shadow
+	Rectangle2D*					miniScreen_Shadow;
+	Ogre::SceneNode*			miniScreenNode_Shadow;
+	Ogre::TexturePtr			RTT_Texture_Shadow ;
+	Ogre::RenderTexture*	renderTexture_Shadow ;
+	Ogre::MaterialPtr			RTT_Mat_Shadow ;
+	Ogre::Technique*			RTT_Technique_Shadow ;
+
+	// ShadeFront
+	Rectangle2D*					miniScreen_ShadeFront;
+	Ogre::SceneNode*			miniScreenNode_ShadeFront;
+	Ogre::TexturePtr			RTT_Texture_ShadeFront ;
+	Ogre::RenderTexture*	renderTexture_ShadeFront ;
+	Ogre::MaterialPtr			RTT_Mat_ShadeFront ;
+	Ogre::Technique*			RTT_Technique_ShadeFront ;
+
+	// ShadeBack
+	Rectangle2D*					miniScreen_ShadeBack;
+	Ogre::SceneNode*			miniScreenNode_ShadeBack;
+	Ogre::TexturePtr			RTT_Texture_ShadeBack ;
+	Ogre::RenderTexture*	renderTexture_ShadeBack ;
+	Ogre::MaterialPtr			RTT_Mat_ShadeBack ;
+	Ogre::Technique*			RTT_Technique_ShadeBack ;
+
+	// DfShPosition
+	Rectangle2D*					miniScreen_DfShPosition;
+	SceneNode*						miniScreenNode_DfShPosition;
+	TexturePtr						RTT_Texture_DfShPosition ;
+	RenderTexture*				renderTexture_DfShPosition ;
+	MaterialPtr						RTT_Mat_DfShPosition ;
+	Technique*						RTT_Technique_DfShPosition ;
+	RenderTargetListener* Listener_DfShPosition ;
+
+	// DfShDiffuse
+	Rectangle2D*					miniScreen_DfShDiffuse;
+	Ogre::SceneNode*			miniScreenNode_DfShDiffuse;
+	Ogre::TexturePtr			RTT_Texture_DfShDiffuse ;
+	Ogre::RenderTexture*	renderTexture_DfShDiffuse ;
+	Ogre::MaterialPtr			RTT_Mat_DfShDiffuse ;
+	Ogre::Technique*			RTT_Technique_DfShDiffuse ;
+
+	/*
+	// DSNormal // UNUSED
+	Rectangle2D*					miniScreen_DSNormal;
+	Ogre::SceneNode*			miniScreenNode_DSNormal;
+	Ogre::TexturePtr			RTT_Texture_DSNormal ;
+	Ogre::RenderTexture*	renderTexture_DSNormal ;
+	Ogre::MaterialPtr			RTT_Mat_DSNormal ;
+	Ogre::Technique*			RTT_Technique_DSNormal ;
+	*/
+
+	// DfShFuncTNB
+	Rectangle2D*					miniScreen_DfShFuncTNB;
+	Ogre::SceneNode*			miniScreenNode_DfShFuncTNB;
+	Ogre::TexturePtr			RTT_Texture_DfShFuncTNB ;
+	Ogre::RenderTexture*	renderTexture_DfShFuncTNB ;
+	Ogre::MaterialPtr			RTT_Mat_DfShFuncTNB ;
+	Ogre::Technique*			RTT_Technique_DfShFuncTNB ;
+
+	// DfShSpecular
+	Rectangle2D*					miniScreen_DfShSpecular;
+	Ogre::SceneNode*			miniScreenNode_DfShSpecular;
+	Ogre::TexturePtr			RTT_Texture_DfShSpecular ;
+	Ogre::RenderTexture*	renderTexture_DfShSpecular ;
+	Ogre::MaterialPtr			RTT_Mat_DfShSpecular ;
+	Ogre::Technique*			RTT_Technique_DfShSpecular ;
+
+	// DfShEmissive
+	Rectangle2D*					miniScreen_DfShEmissive;
+	Ogre::SceneNode*			miniScreenNode_DfShEmissive;
+	Ogre::TexturePtr			RTT_Texture_DfShEmissive ;
+	Ogre::RenderTexture*	renderTexture_DfShEmissive ;
+	Ogre::MaterialPtr			RTT_Mat_DfShEmissive ;
+	Ogre::Technique*			RTT_Technique_DfShEmissive ;
+
+	// DfShLamp
+	Rectangle2D*					miniScreen_DfShLamp;
+	Ogre::SceneNode*			miniScreenNode_DfShLamp;
+	Ogre::TexturePtr			RTT_Texture_DfShLamp ;
+	Ogre::RenderTexture*	renderTexture_DfShLamp ;
+	Ogre::MaterialPtr			RTT_Mat_DfShLamp ;
+	Ogre::Technique*			RTT_Technique_DfShLamp ;
+
+	/*
+	// DfShData
+	Rectangle2D*					miniScreen_DfShData;
+	Ogre::SceneNode*			miniScreenNode_DfShData;
+	Ogre::TexturePtr			RTT_Texture_DfShData ;
+	Ogre::RenderTexture*	renderTexture_DfShData ;
+	Ogre::MaterialPtr			RTT_Mat_DfShData ;
+	Ogre::Technique*			RTT_Technique_DfShData ;
+	*/
+
+	// DfShMix
+	Rectangle2D*					miniScreen_DfShMix;
+	Ogre::SceneNode*			miniScreenNode_DfShMix;
+	Ogre::TexturePtr			RTT_Texture_DfShMix ;
+	Ogre::RenderTexture*	renderTexture_DfShMix ;
+	Ogre::MaterialPtr			RTT_Mat_DfShMix ;
+	Ogre::Technique*			RTT_Technique_DfShMix ;
+
+	
+	// DfShTemp
+	Rectangle2D*					miniScreen_DfShTemp;
+	Ogre::SceneNode*			miniScreenNode_DfShTemp;
+	Ogre::TexturePtr			RTT_Texture_DfShTemp ;
+	Ogre::RenderTexture*	renderTexture_DfShTemp ;
+	Ogre::MaterialPtr			RTT_Mat_DfShTemp ;
+	Ogre::Technique*			RTT_Technique_DfShTemp ;
+
+	Rectangle2D*					miniScreen_DfShMaster;
+	Ogre::SceneNode*			miniScreenNode_DfShMaster;
+
+	int m_nRTTWidth ;
+	int m_nRTTHeight ;
+
+	// blur for hdr
+	Rectangle2D*					miniScreen_BlurA;
+	Ogre::SceneNode*			miniScreenNode_BlurA;
+	Ogre::TexturePtr			RTT_Texture_BlurA ;
+	Ogre::RenderTexture*	renderTexture_BlurA ;
+	Ogre::MaterialPtr			RTT_Mat_BlurA ;
+	Ogre::Technique*			RTT_Technique_BlurA ;
+
+	Rectangle2D*					miniScreen_BlurB;
+	Ogre::SceneNode*			miniScreenNode_BlurB;
+	Ogre::TexturePtr			RTT_Texture_BlurB ;
+	Ogre::RenderTexture*	renderTexture_BlurB ;
+	Ogre::MaterialPtr			RTT_Mat_BlurB ;
+	Ogre::Technique*			RTT_Technique_BlurB ;
+	
+	
+
+	Ogre::MaterialPtr			pClearMaterial ;
+
+
+};
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
+
+#endif 
+
+//|||||||||||||||||||||||||||||||||||||||||||||||
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreGpuCommandBufferFlush.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreGpuCommandBufferFlush.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreGpuCommandBufferFlush.cpp	(revision 11817)
@@ -0,0 +1,105 @@
+#include "OgreGpuCommandBufferFlush.h"
+#include "OgreRoot.h"
+#include "OgreRenderSystem.h"
+#include "OgreHardwareOcclusionQuery.h"
+
+namespace Ogre
+{
+	//---------------------------------------------------------------------
+	GpuCommandBufferFlush::GpuCommandBufferFlush()
+		: mUseOcclusionQuery(true)
+		, mMaxQueuedFrames(2)
+		, mCurrentFrame(0)
+		, mStartPull(false)
+		, mStarted(false)
+	{
+
+	}
+	//---------------------------------------------------------------------
+	GpuCommandBufferFlush::~GpuCommandBufferFlush()
+	{
+		stop();
+	}
+	//---------------------------------------------------------------------
+	void GpuCommandBufferFlush::start(size_t maxQueuedFrames)
+	{
+		if (!Root::getSingletonPtr() || !Root::getSingletonPtr()->getRenderSystem())
+			return;
+
+		stop();
+		mMaxQueuedFrames = maxQueuedFrames;
+		RenderSystem* rsys = Root::getSingleton().getRenderSystem();
+		mUseOcclusionQuery = rsys->getCapabilities()->hasCapability(RSC_HWOCCLUSION);
+
+		if (mUseOcclusionQuery)
+		{
+			for (size_t i = 0; i < mMaxQueuedFrames; ++i)
+			{
+				HardwareOcclusionQuery* hoq = rsys->createHardwareOcclusionQuery();
+				mHOQList.push_back(hoq);
+			}
+		}
+
+		mCurrentFrame = 0;
+		mStartPull = false;
+
+		Root::getSingleton().addFrameListener(this);
+
+		mStarted = true;
+
+	}
+	//---------------------------------------------------------------------
+	void GpuCommandBufferFlush::stop()
+	{
+		if (!mStarted || !Root::getSingletonPtr() || !Root::getSingletonPtr()->getRenderSystem())
+			return;
+
+		RenderSystem* rsys = Root::getSingleton().getRenderSystem();
+		for (HOQList::iterator i = mHOQList.begin(); i != mHOQList.end(); ++i)
+		{
+			rsys->destroyHardwareOcclusionQuery(*i);
+		}
+		mHOQList.clear();
+
+		Root::getSingleton().removeFrameListener(this);
+
+		mStarted = false;
+
+	}
+	//---------------------------------------------------------------------
+	bool GpuCommandBufferFlush::frameStarted(const FrameEvent& evt)
+	{
+		if (mUseOcclusionQuery)
+		{
+
+			mHOQList[mCurrentFrame]->beginOcclusionQuery();
+
+		}
+
+		return true;
+	}
+	//---------------------------------------------------------------------
+	bool GpuCommandBufferFlush::frameEnded(const FrameEvent& evt)
+	{
+		if (mUseOcclusionQuery)
+		{
+			mHOQList[mCurrentFrame]->endOcclusionQuery();
+		}
+		mCurrentFrame = (mCurrentFrame + 1) % mMaxQueuedFrames;
+		// If we've wrapped around, time to start pulling
+		if (mCurrentFrame == 0)
+			mStartPull = true;
+
+		if (mStartPull)
+		{
+			unsigned int dummy;
+			mHOQList[mCurrentFrame]->pullOcclusionQuery(&dummy);
+		}
+
+		return true;
+	}
+	//---------------------------------------------------------------------
+
+
+}
+
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreGpuCommandBufferFlush.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreGpuCommandBufferFlush.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/OgreGpuCommandBufferFlush.h	(revision 11817)
@@ -0,0 +1,43 @@
+#ifndef __GPUCOMMANDBUFFERFLUSH_H__
+#define __GPUCOMMANDBUFFERFLUSH_H__
+
+#include "OgrePrerequisites.h"
+#include "OgreFrameListener.h"
+
+namespace Ogre
+{
+	
+	/** Helper class which can assist you in making sure the GPU command
+		buffer is regularly flushed, so in cases where the CPU is outpacing the
+		GPU we do not hit a situation where the CPU suddenly has to stall to 
+		wait for more space in the buffer.
+	*/
+	class GpuCommandBufferFlush : public FrameListener
+	{
+	protected:
+		bool mUseOcclusionQuery;
+		typedef std::vector<HardwareOcclusionQuery*> HOQList;
+		HOQList mHOQList;
+		size_t mMaxQueuedFrames;
+		size_t mCurrentFrame;
+		bool mStartPull;
+		bool mStarted;
+
+	public:
+		GpuCommandBufferFlush();
+		virtual ~GpuCommandBufferFlush();
+
+		void start(size_t maxQueuedFrames = 2);
+		void stop();
+		bool frameStarted(const FrameEvent& evt);
+		bool frameEnded(const FrameEvent& evt);
+
+	};
+
+
+}
+
+
+#endif
+
+
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map.cpp	(revision 11817)
@@ -0,0 +1,4881 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+Copyright (C) 2009 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Q3Map.cpp -- handles the map data
+
+#include <string>
+#include <math.h>
+
+#include "Q3Map.h"
+#include "Q3Map_misc.h"
+
+
+//temp
+//#include <io.h>
+//#include <fcntl.h>      /* Needed only for _O_RDWR definition */
+//#include <sys/stat.h>
+
+Q3Map::Q3Map()
+{
+	m_nDebugA=0 ;
+
+	m_nNewCount=0 ;
+	
+  m_pTexturesOrig=NULL ;
+  m_pFaces=NULL ;
+  m_pVertices=NULL ;
+  m_pMeshVerts=NULL ;
+  m_pLeafs=NULL ;
+  m_pLeafFaces=NULL ;
+  m_pPlanes=NULL ;
+  m_pNodes=NULL ;
+
+	//m_VisData->vecs=NULL ; // can't NULL this because m_VisData doesn't exist yet!
+	m_VisData=NULL ;
+   
+  m_pBrushes=NULL ;
+  m_pLeafBrushes=NULL ;
+  m_pBrushSides=NULL ;
+  m_pLightMaps=NULL ;
+  m_pEntities=NULL ;
+
+	m_pSubZones=NULL ;
+	m_pPortals=NULL ;
+	//////////////////////////////////////////////////////
+
+	// initiallize our triangle memory management
+	m_nTriangleSize=0 ;
+	m_pTriangleMem=NULL ;
+	m_pTriangle=NULL ;
+	m_nTriangleMax=0 ;
+	m_nTriangleLimit=0 ;
+
+	m_nVertexSize=0 ;
+	m_pVertexMem=NULL ;
+	m_pVertex=NULL ;
+	m_nVertexMax=0 ;
+	m_nVertexLimit=0 ;
+
+	m_nLightSize=0 ;
+	m_pLightMem=NULL ;
+	m_pLight=NULL ;
+	m_nLightMax=0 ;
+	m_nLightLimit=0 ;
+	m_nMaxMultiZoneLight=0 ;
+
+	m_nLampSize=0 ;
+	m_pLampMem=NULL ;
+	m_pLamp=NULL ;
+	m_nLampMax=0 ;
+	m_nLampLimit=0 ;
+
+	m_nTextureSize=0 ;
+	m_pTextureMem=NULL ;
+	m_pTexture=NULL ;
+	m_nTextureMax=0 ;
+	m_nTextureLimit=0 ;
+
+	m_nTexLampSize=0 ;
+	m_pTexLampMem=NULL ;
+	m_pTexLamp=NULL ;
+	m_nTexLampMax=0 ;
+	m_nTexLampLimit=0 ;
+
+	m_BspFaces=NULL;
+
+	m_pTransTexture=NULL ;
+
+
+//	Q3Bug.LogInit() ;
+
+}
+
+Q3Map::~Q3Map()
+{
+//	Q3Bug.LogSave("Q3Bug.log") ;
+
+	DELETE_ARRAY(m_pTransTexture) ;
+	//DELETE_ARRAY(m_pSubZones) ;
+	DELETE_ARRAY(mVisibleFaces) ;
+
+	FreeLightMemory() ;
+	FreeLampMemory() ;
+	FreeVertexMemory() ;
+	FreeTriangleMemory() ;
+	FreeTextureMemory() ;
+	FreeTexLampMemory() ;
+	DestroyBspFacesMemory() ;	// free up face and patch data.  Normally already done if we're just loading a new level or quitting, but we might also be here due to a loading fail or something.
+
+	// no need to delete any of the pointers to the lumps since their memory belongs to m_pRawBspFile over in OgreFramework.
+
+	
+}
+
+void Q3Map::DestroyBspFacesMemory(void)
+{
+	if(m_BspFaces) 
+	{
+		// clean up any memory declared for patches
+		for (int i=0; i < m_NumBspFaces; i++)
+      if ((m_BspFaces[i].type == PATCH) && (m_BspFaces[i].patch != NULL))
+			{
+				DELETE_ARRAY( m_BspFaces[i].patch->bezier ) ;
+				DELETE_POINTER( m_BspFaces[i].patch ) ;
+			}
+
+		// delete the faces memory
+		DELETE_ARRAY( m_BspFaces ) ;
+	}
+}
+
+
+
+int Q3Map::parseMap(const char* pMem, size_t Size)
+{	
+	// we check all lump info to make sure it isn't trying to go out of bounds,
+	// in case some mangled bsp is trying to do something devious or is just corrupted
+	
+	
+	
+
+
+	m_BspHeader=*((Q3BspHeader_t*)pMem) ; // pointer to the header
+
+	// run a check that the total size of all the iLengths plus the header isn't too large
+	size_t TotalLength=sizeof(Q3BspHeader_t) ; // initialize to the size of the header
+	int nLump=0 ;
+	int nOther=0 ;
+	int nLumpMin=0 ;
+	int nLumpMax=0 ;
+	int nOtherMin=0 ;
+	int nOtherMax=0 ;
+	for(nLump=0 ; nLump<MAX_LUMP ; nLump++)
+	{
+		if(m_BspHeader.Lumps[nLump].iLength<0) return -1 ; // lumps shouldn't have a negative size. FAIL!
+		if(m_BspHeader.Lumps[nLump].iLength>MAX_LUMP_SIZE) return -2 ; // no lump has a right to be this big... FAIL!
+		
+		
+		if( (m_BspHeader.Lumps[nLump].iLength>0) && (m_BspHeader.Lumps[nLump].iOffset<sizeof(Q3BspHeader_t)) )
+			return -3 ; // lump overlaps header, FAIL!
+
+		if((m_BspHeader.Lumps[nLump].iLength==0) && (m_BspHeader.Lumps[nLump].iOffset!=0))
+			return -4 ; // lump size is zero and yet offset is not zero???  FAIL!
+
+
+		TotalLength+=m_BspHeader.Lumps[nLump].iLength ;
+		if(TotalLength>Size) return -5 ;// this file is messed up, the lumps add up to more than the file size.  FAIL!
+
+		// make sure this lump doesn't overlap any other lumps
+		nLumpMin=m_BspHeader.Lumps[nLump].iOffset ;
+		nLumpMax=nLumpMin+m_BspHeader.Lumps[nLump].iLength-1 ;
+
+		for(nOther=nLump+1 ; nOther<MAX_LUMP ; nOther++)
+			if((m_BspHeader.Lumps[nLump].iLength>0) && (m_BspHeader.Lumps[nOther].iLength>0)) // don't check zero sized lumps
+			{
+				nOtherMin=m_BspHeader.Lumps[nOther].iOffset ;
+				nOtherMax=nOtherMin+m_BspHeader.Lumps[nOther].iLength-1 ;
+
+				if((nLumpMax>=nOtherMin) && (nLumpMin<=nOtherMax)) 
+				return -6 ; // lump overlaps another lump, FAIL!
+			}
+	}
+
+	
+
+
+	// setup pointers to the lumps
+
+	if((m_BspHeader.Lumps[0].iOffset<0) || (m_BspHeader.Lumps[0].iOffset>=Size)) return -7 ; // fail if out of memory bounds
+	m_pEntities=(char*)(pMem+m_BspHeader.Lumps[0].iOffset) ;
+
+	if((m_BspHeader.Lumps[Faces].iOffset<0) || (m_BspHeader.Lumps[Faces].iOffset>=Size)) return -8 ; // out of bounds
+	if(m_BspHeader.Lumps[Faces].iOffset+m_BspHeader.Lumps[Faces].iLength>Size) return -9 ; // out of bounds
+  m_iNumFaces = m_BspHeader.Lumps[Faces].iLength / sizeof(Q3BspFace_t);
+	m_pFaces=(Q3BspFace_t*)(pMem+m_BspHeader.Lumps[Faces].iOffset) ;
+
+	if((m_BspHeader.Lumps[Vertices].iOffset<0) || (m_BspHeader.Lumps[Vertices].iOffset>=Size)) return -10 ; // out of bounds
+	if(m_BspHeader.Lumps[Vertices].iOffset+m_BspHeader.Lumps[Vertices].iLength>Size) return -11 ; // out of bounds
+  m_iNumVertices = m_BspHeader.Lumps[Vertices].iLength / sizeof(Q3BspVertex);
+	m_pVertices=(Q3BspVertex*)(pMem+m_BspHeader.Lumps[Vertices].iOffset) ;
+
+	if((m_BspHeader.Lumps[MeshVerts].iOffset<0) || (m_BspHeader.Lumps[MeshVerts].iOffset>=Size)) return -12 ; // out of bounds
+	if(m_BspHeader.Lumps[MeshVerts].iOffset+m_BspHeader.Lumps[MeshVerts].iLength>Size) return -13 ; // out of bounds
+  m_iNumMeshVerts = m_BspHeader.Lumps[MeshVerts].iLength / sizeof(int);
+	m_pMeshVerts=(int*)(pMem+m_BspHeader.Lumps[MeshVerts].iOffset) ;
+
+	if((m_BspHeader.Lumps[Leafs].iOffset<0) || (m_BspHeader.Lumps[Leafs].iOffset>=Size)) return -14 ; // out of bounds
+	if(m_BspHeader.Lumps[Leafs].iOffset+m_BspHeader.Lumps[Leafs].iLength>Size) return -15 ; // out of bounds
+  m_iNumLeafs = m_BspHeader.Lumps[Leafs].iLength / sizeof(Q3BspLeaf);
+	m_pLeafs=(Q3BspLeaf*)(pMem+m_BspHeader.Lumps[Leafs].iOffset) ;
+
+	if((m_BspHeader.Lumps[LeafFaces].iOffset<0) || (m_BspHeader.Lumps[LeafFaces].iOffset>=Size)) return -16 ; // out of bounds
+	if(m_BspHeader.Lumps[LeafFaces].iOffset+m_BspHeader.Lumps[LeafFaces].iLength>Size) return -17 ; // out of bounds
+  m_iNumLeafFaces = m_BspHeader.Lumps[LeafFaces].iLength / sizeof(int);
+	m_pLeafFaces=(int*)(pMem+m_BspHeader.Lumps[LeafFaces].iOffset) ;
+
+	if((m_BspHeader.Lumps[LeafBrushes].iOffset<0) || (m_BspHeader.Lumps[LeafBrushes].iOffset>=Size)) return -18 ; // out of bounds
+	if(m_BspHeader.Lumps[LeafBrushes].iOffset+m_BspHeader.Lumps[LeafBrushes].iLength>Size) return -19 ; // out of bounds
+  m_iNumLeafBrushes = m_BspHeader.Lumps[LeafBrushes].iLength / sizeof(int);
+	m_pLeafBrushes=(int*)(pMem+m_BspHeader.Lumps[LeafBrushes].iOffset) ;
+
+	if((m_BspHeader.Lumps[Textures].iOffset<0) || (m_BspHeader.Lumps[Textures].iOffset>=Size)) return -20 ; // out of bounds
+	if(m_BspHeader.Lumps[Textures].iOffset+m_BspHeader.Lumps[Textures].iLength>Size) return -21 ; // out of bounds
+  m_iNumTexs = m_BspHeader.Lumps[Textures].iLength / sizeof(Q3BspTexture);
+	m_pTexturesOrig=(Q3BspTexture*)(pMem+m_BspHeader.Lumps[Textures].iOffset) ;
+
+	if((m_BspHeader.Lumps[Planes].iOffset<0) || (m_BspHeader.Lumps[Planes].iOffset>=Size)) return -22 ; // out of bounds
+	if(m_BspHeader.Lumps[Planes].iOffset+m_BspHeader.Lumps[Planes].iLength>Size) return -23 ; // out of bounds
+  m_iNumPlanes = m_BspHeader.Lumps[Planes].iLength / sizeof(Q3BspPlane);
+	m_pPlanes=(Q3BspPlane*)(pMem+m_BspHeader.Lumps[Planes].iOffset) ;
+
+	if((m_BspHeader.Lumps[Nodes].iOffset<0) || (m_BspHeader.Lumps[Nodes].iOffset>=Size)) return -24 ; // out of bounds
+	if(m_BspHeader.Lumps[Nodes].iOffset+m_BspHeader.Lumps[Nodes].iLength>Size) return -25 ; // out of bounds
+  m_iNumNodes = m_BspHeader.Lumps[Nodes].iLength / sizeof(Q3BspNode);
+	m_pNodes=(Q3BspNode*)(pMem+m_BspHeader.Lumps[Nodes].iOffset) ;
+
+  //m_iNumModels = m_BspHeader.Lumps[Models].iLength / sizeof(Q3BspModel);
+  //m_pModels = new Q3BspModel[m_iNumModels];
+
+	// bzn doesn't use lightmaps
+  //m_iNumLightMaps = m_BspHeader.Lumps[LightMaps].iLength / sizeof(Q3BspLightMap);
+	//m_pLightMaps=(Q3BspLightMap*)(pMem+m_BspHeader.Lumps[LightMaps].iOffset) ;
+
+	if((m_BspHeader.Lumps[Brushes].iOffset<0) || (m_BspHeader.Lumps[Brushes].iOffset>=Size)) return -26 ; // out of bounds
+	if(m_BspHeader.Lumps[Brushes].iOffset+m_BspHeader.Lumps[Brushes].iLength>Size) return -27 ; // out of bounds
+  m_iNumBrushes = m_BspHeader.Lumps[Brushes].iLength / sizeof(Q3BspBrush);
+	m_pBrushes=(Q3BspBrush*)(pMem+m_BspHeader.Lumps[Brushes].iOffset) ;
+
+
+	if((m_BspHeader.Lumps[BrushSides].iOffset<0) || (m_BspHeader.Lumps[BrushSides].iOffset>=Size)) return -28 ; // out of bounds
+	if(m_BspHeader.Lumps[BrushSides].iOffset+m_BspHeader.Lumps[BrushSides].iLength>Size) return -29 ; // out of bounds
+  m_iNumBrushSides = m_BspHeader.Lumps[BrushSides].iLength / sizeof(Q3BspBrushSide);
+	m_pBrushSides=(Q3BspBrushSide*)(pMem+m_BspHeader.Lumps[BrushSides].iOffset) ;
+
+  //m_iNumEffects = m_BspHeader.Lumps[Effects].iLength / sizeof(Q3BspEffect);
+  //m_pEffects = new Q3BspEffect[m_iNumEffects];
+  //
+  //m_pImages = new BDTexture[m_iNumTexs];
+
+	// bzn doesn't use visdata
+	//m_VisData=(Q3BspVisData*)(pMem+m_BspHeader.Lumps[VisData].iOffset) ;
+	//m_VisData->vecs=(unsigned char*)(pMem+m_BspHeader.Lumps[VisData].iOffset + 2*sizeof(int)) ;
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// bzn specific data
+	if((m_BspHeader.Lumps[SubZoneData].iOffset<0) || (m_BspHeader.Lumps[SubZoneData].iOffset>=Size)) return -30 ; // out of bounds
+	if(m_BspHeader.Lumps[SubZoneData].iOffset+m_BspHeader.Lumps[SubZoneData].iLength>Size) return -31 ; // out of bounds
+	m_iNumSubZones = m_BspHeader.Lumps[SubZoneData].iLength / sizeof(BZN_SubZone_t);
+  m_pSubZones=(BZN_SubZone_t*)(pMem+m_BspHeader.Lumps[SubZoneData].iOffset) ;
+
+	if((m_BspHeader.Lumps[PortalData].iOffset<0) || (m_BspHeader.Lumps[PortalData].iOffset>=Size)) return -32 ; // out of bounds
+	if(m_BspHeader.Lumps[PortalData].iOffset+m_BspHeader.Lumps[PortalData].iLength>Size) return -33 ; // out of bounds
+	m_iNumPortals = m_BspHeader.Lumps[PortalData].iLength / sizeof(BZN_Portal_t);
+	m_pPortals=(BZN_Portal_t*)(pMem+m_BspHeader.Lumps[PortalData].iOffset) ;
+
+	
+
+
+
+
+	// fix coords and setup face memory
+	swizzleCoords();
+  mVisibleFaces = new int[m_iNumFaces];
+
+
+	// we need a new version of the textures, because when we parse the lights they will have textures to add to it,
+	// and we can't expand the texture lump because it's in the middle of a block of memory containing all the lumps.
+
+	// copy the texture lump
+	int nTexture=0 ;
+	for(nTexture=0 ; nTexture<m_iNumTexs ; nTexture++)
+	{
+		if(!AddTexture(m_pTexturesOrig[nTexture])) return -34 ; // failed to add texture, probably out of memory
+	}
+	
+	return 0 ;
+
+}
+
+
+void Q3Map::swizzleCoords(void)
+{
+  //DEBUG_OUTPUT("swizziling data...");
+  // vertices
+  for (int i=0; i < m_iNumVertices; i++)
+  {
+    swizzleFloat3(m_pVertices[i].position);
+    swizzleFloat3(m_pVertices[i].normal);
+    //m_pVertices[i].texcoord[0][0] = 1.0f - m_pVertices[i].texcoord[0][0];		
+  }
+
+  // leafs
+  for (int i=0; i < m_iNumLeafs; i++)
+  {
+    swizzleInt3(m_pLeafs[i].maxs);
+    swizzleInt3(m_pLeafs[i].mins);
+  }
+
+  // faces, do lightmaps later...
+  for (int i=0; i < m_iNumFaces; i++)
+  {
+    swizzleFloat3(m_pFaces[i].normal);
+  }
+
+  // planes
+  for (int i=0; i < m_iNumPlanes; i++)
+  {
+    swizzleFloat3(m_pPlanes[i].normal);		
+  }
+
+  // nodes
+  for (int i=0; i < m_iNumNodes; i++)
+  {
+    swizzleInt3(m_pNodes[i].maxs);
+    swizzleInt3(m_pNodes[i].mins);
+  }
+
+	
+	// subzones
+	float flTemp=0.0f ;
+	for (int i=0; i < m_iNumSubZones; i++)
+  {
+		swizzleFloat3(m_pSubZones[i].Max);		
+		swizzleFloat3(m_pSubZones[i].Min);
+
+		// swizzling will mix up z max and min due to the sign change, so swap them
+		flTemp=m_pSubZones[i].Max[2] ;
+		m_pSubZones[i].Max[2]=m_pSubZones[i].Min[2] ;
+		m_pSubZones[i].Min[2]=flTemp ;
+
+  }
+
+	// portals
+	for (int i=0; i < m_iNumPortals; i++)
+  {
+		swizzleFloat3(m_pPortals[i].Max);		
+		swizzleFloat3(m_pPortals[i].Min);
+
+		// swizzling will mix up z max and min due to the sign change, so swap them
+		flTemp=m_pPortals[i].Max[2] ;
+		m_pPortals[i].Max[2]=m_pPortals[i].Min[2] ;
+		m_pPortals[i].Min[2]=flTemp ;
+
+  }
+
+	
+	
+
+}
+
+void Q3Map::swizzleFloat3(float t[3])
+{	
+  float temp;
+  temp = t[1];
+  t[1] = t[2];
+  t[2] = -temp;
+}
+
+void Q3Map::swizzleInt3(int t[3])
+{	
+  int temp;
+  temp = t[1];
+  t[1] = t[2];
+  t[2] = -temp;
+}
+
+
+
+Q3BspPatch *Q3Map::handlePatch(int faceIndex)
+{
+  Q3BspPatch *q3patch;
+  q3patch = new Q3BspPatch;
+
+  int patch_size_x = (m_pFaces[faceIndex].size[0] - 1) / 2;
+  int patch_size_y = (m_pFaces[faceIndex].size[1] - 1) / 2;
+  int num_bezier_patches = patch_size_y * patch_size_x;
+
+  q3patch->size = num_bezier_patches;
+  q3patch->bezier = new Bezier[q3patch->size];
+
+  int patchIndex =  0;
+  int ii, n, j, nn;
+  for (ii = 0, n = 0; n < patch_size_x; n++, ii = 2*n)
+  {				
+    for (j=0, nn=0; nn < patch_size_y; nn++, j = 2*nn)
+    {
+      int index = 0;
+      for (int ctr = 0; ctr < 3; ctr++)
+      { 
+        int pos = ctr * m_pFaces[faceIndex].size[0];
+
+        q3patch->bezier[patchIndex].mControls[index++] = 
+          BspVertex(
+          // position
+          m_pVertices[m_pFaces[faceIndex].vertex + 
+          ii + 
+          m_pFaces[faceIndex].size[0] * j + 
+          pos].position,
+          // texture coordinates
+          m_pVertices[m_pFaces[faceIndex].vertex + 
+          ii + 
+          m_pFaces[faceIndex].size[0] * j +
+          pos].texcoord,
+          // normal
+          m_pVertices[m_pFaces[faceIndex].vertex +
+          ii +
+          m_pFaces[faceIndex].size[0] * j +
+          pos].normal);
+
+        q3patch->bezier[patchIndex].mControls[index++] = 
+                BspVertex(
+                  m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].position,
+                  m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].texcoord,
+                  m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 1].normal);
+
+        q3patch->bezier[patchIndex].mControls[index++] = 
+                BspVertex(
+                  m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].position,
+                  m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].texcoord,
+                  m_pVertices[m_pFaces[faceIndex].vertex + ii + m_pFaces[faceIndex].size[0] * j + pos + 2].normal);						
+      }      
+      q3patch->bezier[patchIndex].tessellate(5);
+      patchIndex++;
+    }
+  }
+
+  return q3patch;
+}
+
+
+int Q3Map::findVisibleFaces(const QVECTOR *camPos, int *facesToRender)
+{
+  int leaf;
+  int visCluster;	
+
+  leaf = findLeaf(camPos);	
+
+  visCluster = m_pLeafs[leaf].cluster;
+
+  memset(mVisibleFaces, 0, sizeof(int) * m_iNumFaces);	
+
+  int faceindex;
+  int renderindex=0;
+  m_ClusterCount=0 ;
+  
+  for (int i=0; i < m_iNumLeafs; i++)
+  {
+    if (isClusterVisible(visCluster, m_pLeafs[i].cluster))
+    {				
+			m_ClusterCount++ ;
+      bool vis=true ;//bool vis = mViewFrustum->checkIfBoxInside(m_pLeafs[i].mins, m_pLeafs[i].maxs);						
+      
+	  if (vis)
+      {
+        for (int k=0; k < m_pLeafs[i].n_leaffaces; k++)
+        {					
+          faceindex =	m_pLeafFaces[m_pLeafs[i].leafface + k];				
+          if (mVisibleFaces[faceindex] == 0)
+          {
+            mVisibleFaces[faceindex] = 1;						
+            facesToRender[renderindex++] = faceindex;
+          }
+        }
+      }			
+    }
+  }
+  
+
+  facesToRender[renderindex] = -1;	
+
+  return renderindex;
+}
+
+
+int Q3Map::findLeaf(const QVECTOR *camPos) const
+{
+  int index = 0;
+
+  while (index >= 0)
+  {
+    const Q3BspNode *node = &m_pNodes[index];
+    const Q3BspPlane *plane = &m_pPlanes[node->plane];
+
+    // distance from point to plane
+    //QVECTOR normal = QVECTOR(plane->normal);		 
+    QVECTOR normal ;
+	normal[0]=plane->normal[0] ;
+	normal[1]=plane->normal[1] ;
+	normal[2]=plane->normal[2] ;
+	
+	
+	//const float distance = D3DXVec3Dot(&normal,camPos) - plane->dist;
+
+	const float distance=(normal[0]* *camPos[0] + normal[1]* *camPos[1] + normal[2]* *camPos[2]) - plane->dist ;
+
+    if(distance >= 0)
+      index = node->children[0];
+    else
+      index = node->children[1];
+  }
+
+  return -index - 1;
+}
+
+bool Q3Map::isClusterVisible(int visCluster, int testCluster) const
+{
+  if (m_VisData == NULL)
+    return true;
+
+  if ((m_VisData->vecs == NULL) || (visCluster < 0)) 	
+    return true;    
+
+  int i = (visCluster * m_VisData->sz_vecs) + (testCluster >> 3);
+  unsigned char visSet = m_VisData->vecs[i];
+
+  return (visSet & (1 << (testCluster & 7))) != 0;
+}
+
+Q3BspFace_t *Q3Map::getFaces(void)
+{
+  return m_pFaces;
+}
+
+
+
+
+
+ /***********************************************************************************************************\
+                                               
+                                   New Parsing and Triangulation Functions 
+                                                
+ \***********************************************************************************************************/
+
+
+
+
+// This routine is basically an overview of the entire process that converts the BSP
+// into something our Ogre code can use to construct the map's mesh and level data.
+// In essence, it converts the map geometry into a list of triangles sorted by zone and material,
+// as well as extracting other map info like zone and portal bounding boxes, lights, entities etc.
+
+int Q3Map::ParseAndTriangulateMap(const char* pData, size_t Size)
+{
+	
+//	char chMessage[1024] ;
+	int nError=0 ;
+
+		// setup pointers to the various lumps and get their quantities
+		nError=parseMap( pData, Size ) ;
+		if(nError<0)
+		{
+			//sprintf(chMessage, "Parse Map Error: %i", nError) ; 
+			//Q3Bug.LogAddCR(chMessage) ;
+			return ERROR_ParseMap ;
+		}
+
+		// extract entities such as lights, monsters, etc
+		if(!ParseEntities())										return ERROR_ParseEntities ;
+
+		// initial memory allocation for triangles
+		m_nVertexMax=0 ;
+		if(!AllocateVertexMemory(m_iNumVertices))	return ERROR_AllocateVertex ;
+		if(!AllocateTriangleMemory())						return ERROR_AllocateTriangle ;
+		if(!initFaces())												return ERROR_InitializeFaces ;
+
+		// no new map textures should be added after here, or else SetupTransTextures won't work
+		if(!SetupTransTextures())								return ERROR_SetupTransTextures ;
+
+		// work out the zones
+		SetupZones() ;
+
+		// convert faces to triangles
+		if(!ConvertFacesToTriangles())					return ERROR_ConvertFaces ;
+
+		if(!ConvertPatchesToTriangles())				return ERROR_ConvertPatches ;
+
+		if(!ConvertLampsToTriangles())					return ERROR_ConvertLamps ;
+
+		if(!ConvertLampsToGlowTriangles())			return ERROR_ConvertLampGlow ;
+
+		if(!ConvertLightsToGlowTriangles())			return ERROR_ConvertLightGlow ;
+
+		GetTexLampTextureNumbers() ; // find out which textures, if any, are textures/common/bzn_lightnode0 to textures/common/bzn_lightnode3
+
+		// assign triangles to zones, splitting them where necessary
+		if(!AssignTrianglesToZones())						return ERROR_AssignTriangles ;
+
+		if(!ConvertTexLampsToLampTriangles())		return ERROR_ConvertTexLamp ;
+
+		// sort by group and re-range the group numbers
+		if(!SortTrianglesIntoGroups())					return ERROR_SortGroups ;
+
+		// sort the triangles in order of zone and texture.  This will also get rid of any unsubzoned triangles.
+		if(!SortTrianglesIntoBatches())					return ERROR_SortTriangles ;
+
+		
+
+
+		// Setup the portals, lights and various bits of map connectivity
+		AssignPortalsToZones() ;		// what portals each zone touches
+		AssignLightsToZones() ;			// what lights each zone touches
+		AssignLightsToPortals() ;		// what lights each portal touches
+		AssignZonesToZones() ;			// what zones each zone touches
+
+
+		return NOERROR ;
+}
+
+void Q3Map::FreeParseMem(void)
+{
+	FreeVertexMemory() ;
+	FreeTriangleMemory() ;
+	DestroyBspFacesMemory() ;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// memory management
+
+int Q3Map::AllocateTriangleMemory(void)
+{
+	// memory for the Triangle
+	m_nTriangleSize=MEMADD ; // starting memory size
+	m_pTriangleMem=malloc(m_nTriangleSize) ; // allocate starting memory space
+	m_pTriangle=(triangle_t*)m_pTriangleMem ; // a pointer to the memory cast as a triangle_t
+	m_nTriangleMax=0 ;
+	m_nTriangleLimit=m_nTriangleSize/sizeof(triangle_t) ; // if pos reaches this memory must expand
+
+	if(m_pTriangleMem==NULL)
+		return 0 ;
+
+	return 1 ;
+}
+
+void Q3Map::FreeTriangleMemory(void)
+{
+	if(m_pTriangleMem) free(m_pTriangleMem) ;
+	m_pTriangleMem=NULL ;
+	m_pTriangle=NULL ;
+	m_nTriangleMax=0 ;
+	m_nTriangleLimit=0 ;
+}
+
+// increase size of Triangle memory, return 0 if failed
+int Q3Map::ExpandTriangleMemory(void)
+{
+	m_nTriangleSize+=MEMADD ; // increase size
+	m_pTriangleMem=realloc(m_pTriangleMem, m_nTriangleSize) ; // reallocate the memory
+	if(m_pTriangleMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+	// if here then memory allocation succeeded
+	m_pTriangle=(triangle_t*)m_pTriangleMem ; // pointer to the memory cast as a triangle_t
+	m_nTriangleLimit=m_nTriangleSize/sizeof(triangle_t) ; // if pos reaches this memory must expand
+	return 1 ; // ok
+}
+
+int Q3Map::AddTriangle(triangle_t Triangle)
+{
+	if(m_nTriangleMax>=m_nTriangleLimit)
+		if( !ExpandTriangleMemory() )
+			return 0 ;
+
+	m_pTriangle[m_nTriangleMax++]=Triangle ;
+
+	return 1 ;
+}
+
+int Q3Map::AllocateVertexMemory(int nVertNum)
+{
+	// memory for the Vertex
+	m_nVertexSize=nVertNum*sizeof(Q3BspVertex)+MEMADD ; // starting memory size
+	m_pVertexMem=malloc(m_nVertexSize) ; // allocate starting memory space
+	m_pVertex=(Q3BspVertex*)m_pVertexMem ; // a pointer to the memory cast as a triangle_t
+	m_nVertexLimit=m_nVertexSize/sizeof(Q3BspVertex) ; // if pos reaches this memory must expand
+
+	if(m_pVertexMem==NULL)
+		return 0 ;
+
+	return 1 ;
+}
+
+void Q3Map::FreeVertexMemory(void)
+{
+	if(m_pVertexMem) free(m_pVertexMem) ;
+	m_pVertexMem=NULL ;
+	m_pVertex=NULL ;
+	m_nVertexMax=0 ;
+	m_nVertexLimit=0 ;
+}
+
+// increase size of Vertex memory, return 0 if failed
+int Q3Map::ExpandVertexMemory(void)
+{
+	m_nVertexSize+=MEMADD ; // increase size
+	m_pVertexMem=realloc(m_pVertexMem, m_nVertexSize) ; // reallocate the memory
+	if(m_pVertexMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+	// if here then memory allocation succeeded
+	m_pVertex=(Q3BspVertex*)m_pVertexMem ; // pointer to the memory cast as a triangle_t
+	m_nVertexLimit=m_nVertexSize/sizeof(Q3BspVertex) ; // if pos reaches this memory must expand
+	return 1 ; // ok
+}
+
+int Q3Map::AddVertex(Q3BspVertex Vertex)
+{
+
+	if(m_nVertexMax>=m_nVertexLimit)
+		if( !ExpandVertexMemory() )
+			return 0 ;
+
+	m_pVertex[m_nVertexMax++]=Vertex ;
+
+	return 1 ;
+}
+
+int Q3Map::AllocateLightMemory(void)
+{
+	// memory for the Light
+	m_nLightSize=MEMADD ; // starting memory size
+	m_pLightMem=malloc(m_nLightSize) ; // allocate starting memory space
+	m_pLight=(light_t*)m_pLightMem ; // a pointer to the memory cast as a light_t
+	m_nLightMax=0 ;
+	m_nLightLimit=m_nLightSize/sizeof(light_t) ; // if pos reaches this memory must expand
+
+	if(m_pLightMem==NULL)
+		return 0 ;
+
+	return 1 ;
+}
+
+void Q3Map::FreeLightMemory(void)
+{
+	if(m_pLightMem) free(m_pLightMem) ;
+	m_pLightMem=NULL ;
+	m_pLight=NULL ;
+	m_nLightMax=0 ;
+	m_nLightLimit=0 ;
+}
+
+// increase size of Light memory, return 0 if failed
+int Q3Map::ExpandLightMemory(void)
+{
+	m_nLightSize+=MEMADD ; // increase size
+	m_pLightMem=realloc(m_pLightMem, m_nLightSize) ; // reallocate the memory
+	if(m_pLightMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+	// if here then memory allocation succeeded
+	m_pLight=(light_t*)m_pLightMem ; // pointer to the memory cast as a light_t
+	m_nLightLimit=m_nLightSize/sizeof(light_t) ; // if pos reaches this memory must expand
+	return 1 ; // ok
+}
+
+int Q3Map::AddLight(light_t Light)
+{
+	if(m_nLightLimit==0) // light memory hasn't been allocated yet
+	{
+		if( !AllocateLightMemory() )
+			return 0 ;
+	}
+	else
+		if(m_nLightMax>=m_nLightLimit)
+			if( !ExpandLightMemory() )
+				return 0 ;
+
+	m_pLight[m_nLightMax++]=Light ;
+
+	return 1 ;
+}
+
+// lamps are deferred shading, non-shadowing point lights
+int Q3Map::AllocateLampMemory(void)
+{
+	// memory for the Lamp
+	m_nLampSize=MEMADD ; // starting memory size
+	m_pLampMem=malloc(m_nLampSize) ; // allocate starting memory space
+	m_pLamp=(lamp_t*)m_pLampMem ; // a pointer to the memory cast as a lamp_t
+	m_nLampMax=0 ;
+	m_nLampLimit=m_nLampSize/sizeof(lamp_t) ; // if pos reaches this memory must expand
+
+	if(m_pLampMem==NULL)
+		return 0 ;
+
+	return 1 ;
+}
+
+void Q3Map::FreeLampMemory(void)
+{
+	if(m_pLampMem) free(m_pLampMem) ;
+	m_pLampMem=NULL ;
+	m_pLamp=NULL ;
+	m_nLampMax=0 ;
+	m_nLampLimit=0 ;
+}
+
+// increase size of Lamp memory, return 0 if failed
+int Q3Map::ExpandLampMemory(void)
+{
+	m_nLampSize+=MEMADD ; // increase size
+	m_pLampMem=realloc(m_pLampMem, m_nLampSize) ; // reallocate the memory
+	if(m_pLampMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+	// if here then memory allocation succeeded
+	m_pLamp=(lamp_t*)m_pLampMem ; // pointer to the memory cast as a lamp_t
+	m_nLampLimit=m_nLampSize/sizeof(lamp_t) ; // if pos reaches this memory must expand
+	return 1 ; // ok
+}
+
+int Q3Map::AddLamp(lamp_t Lamp)
+{
+	if(m_nLampLimit==0) // Lamp memory hasn't been allocated yet
+	{
+		if( !AllocateLampMemory() )
+			return 0 ;
+	}
+	else
+		if(m_nLampMax>=m_nLampLimit)
+			if( !ExpandLampMemory() )
+				return 0 ;
+
+	m_pLamp[m_nLampMax++]=Lamp ;
+
+	return 1 ;
+}
+
+//////////////
+// Q3BspTexture textures.  We duplicate the loaded texture mem and then add lighting textures to it.
+
+int Q3Map::AllocateTextureMemory(void)
+{
+	// memory for the Texture
+	m_nTextureSize=MEMADD ; // starting memory size
+	m_pTextureMem=malloc(m_nTextureSize) ; // allocate starting memory space
+	m_pTexture=(Q3BspTexture*)m_pTextureMem ; // a pointer to the memory cast as a Q3BspTexture
+	m_nTextureMax=0 ;
+	m_nTextureLimit=m_nTextureSize/sizeof(Q3BspTexture) ; // if pos reaches this memory must expand
+
+	if(m_pTextureMem==NULL)
+		return 0 ;
+
+	return 1 ;
+}
+
+void Q3Map::FreeTextureMemory(void)
+{
+	if(m_pTextureMem) free(m_pTextureMem) ;
+	m_pTextureMem=NULL ;
+	m_pTexture=NULL ;
+	m_nTextureMax=0 ;
+	m_nTextureLimit=0 ;
+}
+
+// increase size of Texture memory, return 0 if failed
+int Q3Map::ExpandTextureMemory(void)
+{
+	m_nTextureSize+=MEMADD ; // increase size
+	m_pTextureMem=realloc(m_pTextureMem, m_nTextureSize) ; // reallocate the memory
+	if(m_pTextureMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+	// if here then memory allocation succeeded
+	m_pTexture=(Q3BspTexture*)m_pTextureMem ; // pointer to the memory cast as a Q3BspTexture
+	m_nTextureLimit=m_nTextureSize/sizeof(Q3BspTexture) ; // if pos reaches this memory must expand
+	return 1 ; // ok
+}
+
+int Q3Map::AddTexture(Q3BspTexture Texture)
+{
+	if(m_nTextureLimit==0) // Texture memory hasn't been allocated yet
+	{
+		if( !AllocateTextureMemory() )
+			return 0 ;
+	}
+	else
+		if(m_nTextureMax>=m_nTextureLimit)
+			if( !ExpandTextureMemory() )
+				return 0 ;
+
+	m_pTexture[m_nTextureMax++]=Texture ;
+
+	return 1 ;
+}
+
+// special version of the Add function, will not add if the texture name already exist.  
+// Will succeed even if the texture is already on the list, but fails if it can't add a new texture
+// returns texture index, or -1 on fail
+// Q3 texture names can be tricky, I think I've had cases where they ended in spaces instead of nulls,
+// and they might go all the way to the end without either.
+
+int Q3Map::AddTextureUnique(Q3BspTexture Texture)
+{
+	if(m_nTextureLimit==0) // Texture memory hasn't been allocated yet
+		if( !AllocateTextureMemory() )
+			return ADDTEXTUREUNIQUE_FAIL ; // fail
+
+
+	// scan through all the newly added textures so far and see if this one already exists.
+	int nTexture=0 ;
+	int nPos=0 ;
+
+	bool bMatch=false ;
+
+	for(nTexture=0 ; nTexture<m_nTextureMax ; nTexture++)
+	{
+		bMatch=true ;
+		// scan through the characters of the texture names, comparing them.  We start after the original textures
+		//for(nPos=m_iNumTexs ; nPos<Q3NAMESIZE ; nPos++)
+		for(nPos=0 ; nPos<Q3NAMESIZE ; nPos++)
+		{
+			// is it the end of the texture name?  
+			if(
+						((Texture.name[nPos]							==0)	|| (Texture.name[nPos]							==' ')) // Texture    name end
+					&&((m_pTexture[nTexture].name[nPos] ==0)	|| (m_pTexture[nTexture].name[nPos]	==' ')) // m_pTexture name end
+				)
+				break ;
+
+			// do the two textures have a difference in the name at this position?
+			if(Texture.name[nPos]!=m_pTexture[nTexture].name[nPos])
+			{
+				bMatch=false ;
+				break ;
+			}
+		
+		}// end scanning name
+
+		if(bMatch) // found a match, so return ok but don't add a texture
+		{
+			return nTexture ;  // we don't add any new texture, return this texture's index
+		}
+	}
+
+	// if we got this far, we must have a unique texture
+
+	// add the texture, it is unique
+	if(m_nTextureMax>=m_nTextureLimit)
+		if( !ExpandTextureMemory() )
+			return ADDTEXTUREUNIQUE_FAIL ; // fail
+
+	m_pTexture[m_nTextureMax++]=Texture ;
+
+	return m_nTextureMax-1 ; // return this new texture's index
+
+}
+
+
+////////////////////////////////////////
+
+int Q3Map::AllocateTexLampMemory(void)
+{
+	// memory for the TexLamp
+	m_nTexLampSize=MEMADD ; // starting memory size
+	m_pTexLampMem=malloc(m_nTexLampSize) ; // allocate starting memory space
+	m_pTexLamp=(int*)m_pTexLampMem ; // a pointer to the memory cast as an int
+	m_nTexLampMax=0 ;
+	m_nTexLampLimit=m_nTexLampSize/sizeof(int) ; // if pos reaches this memory must expand
+
+	if(m_pTexLampMem==NULL)
+		return 0 ;
+
+	return 1 ;
+}
+
+void Q3Map::FreeTexLampMemory(void)
+{
+	if(m_pTexLampMem) free(m_pTexLampMem) ;
+	m_pTexLampMem=NULL ;
+	m_pTexLamp=NULL ;
+	m_nTexLampMax=0 ;
+	m_nTexLampLimit=0 ;
+}
+
+// increase size of TexLamp memory, return 0 if failed
+int Q3Map::ExpandTexLampMemory(void)
+{
+	m_nTexLampSize+=MEMADD ; // increase size
+	m_pTexLampMem=realloc(m_pTexLampMem, m_nTexLampSize) ; // reallocate the memory
+	if(m_pTexLampMem==NULL) return 0 ; // failed to allocate memory, get out and return false
+
+	// if here then memory allocation succeeded
+	m_pTexLamp=(int*)m_pTexLampMem ; // pointer to the memory cast as an int
+	m_nTexLampLimit=m_nTexLampSize/sizeof(int) ; // if pos reaches this memory must expand
+	return 1 ; // ok
+}
+
+int Q3Map::AddTexLamp(int TexLamp)
+{
+	if(m_nTexLampMax>=m_nTexLampLimit)
+		if( !ExpandTexLampMemory() )
+			return 0 ;
+
+	m_pTexLamp[m_nTexLampMax++]=TexLamp ;
+
+	return 1 ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// extract entities from bsp entities lump
+int Q3Map::ParseEntities(void)
+{
+//	char chKey[MAX_TOKENSIZE+1] ;   // +1 to leave room for null terminator
+//	char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+	int nPos=0 ;
+	int nMaxPos=m_BspHeader.Lumps[0].iLength ;
+	int nEntityType=0 ;
+
+
+	// reset the spotlight textures
+	m_nMaxSpotlightTexture=0 ;
+	for(nPos=0 ; nPos<MAX_PROJECTORTEX ; nPos++)
+		m_chSpotlightTexture[nPos][0]='\0' ;
+
+	strcpy(m_chSpotlightTexture[m_nMaxSpotlightTexture], "spotlight.dds") ; // the default spotlight texture
+	m_nMaxSpotlightTexture++ ;
+
+	////////////////////////////////////////////////////////////////////////////
+	// before adding all the entities we need to add some default textures
+	Q3BspTexture Texture ;
+	Texture.contents=0 ;
+	Texture.flags=0 ;
+
+	// default lamp texture
+	strcpy(Texture.name, "lights/lamp_default") ;
+	m_nDefaultTextureIndexLamp=AddTextureUnique(Texture) ;
+	if(m_nDefaultTextureIndexLamp==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+	// default lamp2Pass texture
+	strcpy(Texture.name, "lights/lamp2pass_default") ;
+	m_nDefaultTextureIndexLamp2Pass=AddTextureUnique(Texture) ;
+	if(m_nDefaultTextureIndexLamp2Pass==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+	// default glow texture
+	strcpy(Texture.name, "GLOW_lamp") ;
+	m_nDefaultTextureIndexGlowLamp=AddTextureUnique(Texture) ;
+	if(m_nDefaultTextureIndexGlowLamp==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+	// default glow texture
+	strcpy(Texture.name, "GLOW_light") ;
+	m_nDefaultTextureIndexGlowLight=AddTextureUnique(Texture) ;
+	if(m_nDefaultTextureIndexGlowLight==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+
+	// default spotlight texture
+	//strcpy(Texture.name, "lights/light_default") ;
+	//m_nDefaultTextureIndexSpotlight=AddTextureUnique(Texture) ;
+	//if(m_nDefaultTextureIndexSpotlight==ADDTEXTUREUNIQUE_FAIL) return 0 ;
+
+	//
+	///////////////////////////////////////////////////////////////////////////
+
+
+	nPos=-1 ;
+	while(NextEntity(&nPos, nMaxPos))
+	{
+		
+		nEntityType=GetEntityType(nPos, nMaxPos) ; // what type of entity is it?
+
+
+		switch(nEntityType)
+		{
+			case ENTITY_ERROR: return 0 ; // something is wrong with the entity data
+
+			case ENTITY_LIGHT: 
+				if(!ParseAndAddLight(&nPos, nMaxPos)) 
+					return 0 ; // something went wrong with parsing the light
+				break ;
+		}// end switch entity type
+
+
+	}// end get next entity
+
+
+
+	// everything is ok.
+	return 1 ;
+}
+
+// move to the beginning of the next entity.
+// fail if there are no more.
+int Q3Map::NextEntity(int* pPos, int nMaxPos)
+{
+	while((++*pPos<nMaxPos) && (m_pEntities[*pPos]!='{')) ;
+
+	if(*pPos==nMaxPos) 
+		return 0 ;
+
+	return 1 ;
+}
+
+// find out what type of entity this is.
+// Since the classname might not be at the beginning we have to scan through the whole entity
+// This function also doesn't update the position like the others do,
+// since scanning of further key/values will have to start at the beginning of the entity again.
+int Q3Map::GetEntityType(int nPos, int nMaxPos)
+{
+	char chKey[MAX_TOKENSIZE+1] ;   // +1 to leave room for null terminator
+	char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+
+	while(nPos<nMaxPos)
+	{
+		if(GetEntityKeyAndValue(&nPos, nMaxPos, chKey, chValue)!=KEY_OK) return ENTITY_ERROR ; // something went wrong, couldn't find any good keys
+		
+		if(strcmp(chKey, "classname")==0) // found the classname key
+		{
+			if(strcmp(chValue, "worldspawn")==0)			return ENTITY_WORLDSPAWN ;
+			if(strcmp(chValue, "light")==0)						return ENTITY_LIGHT ;
+
+			// wasn't any entity we recognize
+			return ENTITY_UNKNOWN ;
+
+		}// end if got entity classname
+
+	}// end while nPos
+
+	// didn't find any classname
+	return ENTITY_ERROR ;
+}
+
+// get next entity key and value
+int Q3Map::GetEntityKeyAndValue(int* pPos, int nMaxPos, char* pKey, char* pValue)
+{
+
+	char* pEntText=m_pEntities ;
+	int nEntPos=*pPos ;
+	int nKeyPos=-1 ;
+	int nValuePos=-1 ;
+
+	// clear key and value strings
+	pKey[0]='\0' ;
+	pValue[0]='\0' ;
+
+	/////////////////////////////////////////////////////////////////////////////////////////
+	// Key
+
+	// find the next "
+	while((++nEntPos<nMaxPos) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) ;
+
+	// didn't find key, get out
+	if((nEntPos==nMaxPos) || (pEntText[nEntPos]=='}'))
+		return KEY_NONE ;
+
+
+	// copy key
+	while((++nEntPos<nMaxPos) && (nKeyPos<MAX_TOKENSIZE) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) 
+		pKey[++nKeyPos]=pEntText[nEntPos] ;
+
+	if((nEntPos==nMaxPos) || (nKeyPos==MAX_TOKENSIZE) || (pEntText[nEntPos]=='}'))
+		return KEY_ERROR ; // entity was incomplete or too big
+
+	pKey[++nKeyPos]='\0' ;
+
+	/////////////////////////////////////////////////////////////////////////////////////////
+	// value
+
+	// find the next "
+	while((++nEntPos<nMaxPos) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) ;
+
+	// didn't find value, get out
+	if((nEntPos==nMaxPos) || (pEntText[nEntPos]=='}'))
+		return KEY_ERROR ; 
+
+	// copy value
+	while((++nEntPos<nMaxPos) && (nValuePos<MAX_TOKENSIZE) && (pEntText[nEntPos]!='}') && (pEntText[nEntPos]!='"')) 
+		pValue[++nValuePos]=pEntText[nEntPos] ;
+
+	if((nEntPos==nMaxPos) || (nValuePos==MAX_TOKENSIZE) || (pEntText[nEntPos]=='}'))
+		return KEY_ERROR ; // entity was incomplete or too big
+
+	pValue[++nValuePos]='\0' ;
+
+	/////////////////////////////////////////////////////////////////////////////////////////
+
+	*pPos=nEntPos+1 ;
+
+	return KEY_OK ;
+}
+
+
+// fills array pNumber with the values extracted from pValue, returns how many numbers it got.
+// float version
+int Q3Map::GetNumbersFromValue(char* pValue, float *pNumber, int nNumberSize)
+{
+	int nLength=strlen(pValue) ;
+	if(nLength<1) return 0 ;
+
+	int nPos=-1 ;
+	int nCount=0 ;
+	char chTemp[MAX_TOKENSIZE+1] ;
+	int nTempPos=0 ;
+
+	do
+	{
+
+		nPos++ ;
+		
+		if(
+				((pValue[nPos]>='0') && (pValue[nPos]<='9')) // found another digit
+				||
+				(pValue[nPos]=='.')
+				||
+				(pValue[nPos]=='-')
+			)
+		{
+			chTemp[nTempPos++]=pValue[nPos] ;
+			if(nTempPos==MAX_TOKENSIZE) return 0 ; // number too big
+		}
+		else // anything else means the end of the number
+		{
+			
+			chTemp[nTempPos]='\0' ;
+			pNumber[nCount++]=atof(chTemp) ;
+			nTempPos=0 ;
+		}
+		
+
+	}while((nPos<nLength) && (nCount<nNumberSize) && (pValue[nPos]!='\0')) ;
+
+
+	return nCount ;
+}
+
+// integer version
+int Q3Map::GetNumbersFromValue(char* pValue, int *pNumber, int nNumberSize)
+{
+	int nLength=strlen(pValue) ;
+	if(nLength<1) return 0 ;
+
+	int nPos=-1 ;
+	int nCount=0 ;
+	char chTemp[MAX_TOKENSIZE+1] ;
+	int nTempPos=0 ;
+
+	do
+	{
+
+		nPos++ ;
+		
+		if(
+				((pValue[nPos]>='0') && (pValue[nPos]<='9')) // found another digit
+				||
+				(pValue[nPos]=='.')
+				||
+				(pValue[nPos]=='-')
+			)
+		{
+			chTemp[nTempPos++]=pValue[nPos] ;
+			if(nTempPos==MAX_TOKENSIZE) return 0 ; // number too big
+		}
+		else // anything else means the end of the number
+		{
+			
+			chTemp[nTempPos]='\0' ;
+			pNumber[nCount++]=atoi(chTemp) ;
+			nTempPos=0 ;
+		}
+		
+
+	}while((nPos<nLength) && (nCount<nNumberSize) && (pValue[nPos]!='\0')) ;
+
+
+	return nCount ;
+}
+
+//''
+// extracts data for either forward rendered shadow casting spotlights or deferred shading non-shadowing point lights
+// the point lights ("lamps") will later be changed into map triangles.
+int Q3Map::ParseAndAddLight(int* pPos, int nMaxPos)
+{
+//	char chMessage[1024] ;
+
+
+	char chKey[MAX_TOKENSIZE+1] ;   // +1 to leave room for null terminator
+	char chValue[MAX_TOKENSIZE+1] ; // +1 to leave room for null terminator
+	float flOrigin[3]={0.0f, 0.0f, 0.0f} ;
+	float flColour[3]={1.0f, 1.0f, 1.0f} ;
+	float flCentre[3]={0.0f, 0.0f, 0.0f} ;
+	float flAimvec[3]={0.0f, 0.0f, 0.0f} ;
+	float flRadius[3]={0.0f, 0.0f, 0.0f} ;
+	
+	float flTemp[3]={0.0f, 0.0f, 0.0f} ;
+	int nTemp[3] ;
+
+	float flAngle=0.0f ;
+	float flCutoff=0.0f ;
+	float flLength=0.0f ;
+	float flBrightness=0.0f ;
+	int nLightNode=-1 ;
+
+	bool bSpotLight=false ;
+
+	Q3BspTexture Q3Texture ;
+	Q3Texture.flags=0 ;
+	Q3Texture.contents=0 ;
+	Q3Texture.name[0]=0 ;
+
+
+	light_t NewLight ; // forward rendered shadow casting spotlight
+	ZeroMemory((void*)&NewLight, sizeof(light_t)) ;
+
+	lamp_t NewLamp ; // deferred shading non-shadowing point light
+	ZeroMemory((void*)&NewLamp, sizeof(lamp_t)) ;
+
+	int nKeyReturn=KEY_NONE ; 
+
+	do
+	{
+		nKeyReturn=GetEntityKeyAndValue(pPos, nMaxPos, chKey, chValue) ;
+	
+		if(nKeyReturn==KEY_OK) // found a key
+		{
+
+			if(strcmp(chKey, "origin")==0)
+			{
+				if(GetNumbersFromValue(chValue, flOrigin, 3)!=3) return 0 ; // extract the numbers
+				swizzleFloat3(flOrigin) ; // fix coordinates
+			}
+			else
+			if(strcmp(chKey, "_color")==0)
+			{
+				if(GetNumbersFromValue(chValue, flColour, 3)!=3) return 0 ; // extract the numbers
+			}
+			else
+			if(strcmp(chKey, "light_center")==0)
+			{
+				if(GetNumbersFromValue(chValue, flCentre, 3)!=3) return 0 ; // extract the numbers		
+				swizzleFloat3(flCentre) ; // fix coordinates
+			}
+			else
+			if(strcmp(chKey, "light_target")==0)
+			{
+				if(GetNumbersFromValue(chValue, flAimvec, 3)!=3) return 0 ; // extract the numbers		
+				swizzleFloat3(flAimvec) ; // fix coordinates
+				bSpotLight=true ; // if there's a target key, then this must be a spotlight
+			}
+			else
+			if(strcmp(chKey, "light_radius")==0)
+			{
+				if(GetNumbersFromValue(chValue, flRadius, 3)!=3) return 0 ; // extract the numbers
+				swizzleFloat3(flRadius) ; // fix coordinates
+				// make sure all values are positive
+				flRadius[0]=fabs(flRadius[0]) ;
+				flRadius[1]=fabs(flRadius[1]) ;
+				flRadius[2]=fabs(flRadius[2]) ;
+			}
+			else
+			if(strcmp(chKey, "light_abc")==0)
+			{
+				if(GetNumbersFromValue(chValue, flTemp, 3)!=3) return 0 ; // extract the numbers
+				flAngle				= flTemp[0] ;
+				flBrightness	= flTemp[1] ;
+				flCutoff			= flTemp[2] ;
+			}
+			else
+			if(strcmp(chKey, "texture")==0)
+			{
+				strcpy(Q3Texture.name, chValue) ;
+			}
+			if(strcmp(chKey, "light_node")==0)
+			{
+				if(GetNumbersFromValue(chValue, nTemp, 1)!=1) return 0 ; // extract the number
+				nLightNode				= nTemp[0] ;	
+				if((nLightNode<0) || (nLightNode>3)) return 0 ; // something dodgy about the lightnode number
+			}
+
+		}// end if key ok
+
+		
+
+	}while(nKeyReturn==KEY_OK) ;  // end do looping through keys
+
+
+	// return a fail if there was a problem with the keys
+	if(nKeyReturn==KEY_ERROR) return 0 ; 
+
+
+	if(bSpotLight)// found a light_target so this must be a spotlight
+	{
+		// light settings.
+		NewLight.Position[0]=flOrigin[0]+flCentre[0] ;
+		NewLight.Position[1]=flOrigin[1]+flCentre[1] ;
+		NewLight.Position[2]=flOrigin[2]+flCentre[2] ;
+
+		NewLight.Min[0]=flOrigin[0]-flRadius[0] ;
+		NewLight.Min[1]=flOrigin[1]-flRadius[1] ;
+		NewLight.Min[2]=flOrigin[2]-flRadius[2] ;
+
+		NewLight.Max[0]=flOrigin[0]+flRadius[0] ;
+		NewLight.Max[1]=flOrigin[1]+flRadius[1] ;
+		NewLight.Max[2]=flOrigin[2]+flRadius[2] ;
+
+		NewLight.Colour[0]=flColour[0] ;
+		NewLight.Colour[1]=flColour[1] ;
+		NewLight.Colour[2]=flColour[2] ;
+
+		NewLight.Angle=flAngle ;
+		NewLight.Cutoff=flCutoff ;
+		NewLight.Brightness=flBrightness * BRIGHTNESSTWEAK ;
+
+
+		// direction light points, as a normal
+		flLength=sqrt( flAimvec[0]*flAimvec[0] + flAimvec[1]*flAimvec[1] + flAimvec[2]*flAimvec[2] ) ;
+		if(flLength>0.0f)
+		{
+			NewLight.Direction[0]=flAimvec[0]/flLength ;
+			NewLight.Direction[1]=flAimvec[1]/flLength ;
+			NewLight.Direction[2]=flAimvec[2]/flLength ;
+		}
+		else
+		{ // default to pointing down
+			NewLight.Direction[0]=0.0f ;
+			NewLight.Direction[1]=1.0f ;
+			NewLight.Direction[2]=0.0f ;
+		}
+
+		NewLight.ZoneCount=0 ;
+		NewLight.CentreZone=0 ;
+	
+		
+		if(Q3Texture.name[0]==0)	
+			strcpy(Q3Texture.name, "spotlight.dds") ;
+		
+		NewLight.Texture=AddSpolightTexture(Q3Texture.name) ;
+
+
+		if(NewLight.Texture==ADDSPOTLIGHTTEXTURE_FAIL)
+			return 0 ; // failure	
+	
+		//AddTextureUnique(Q3Texture) ;
+		/*
+		// add the light's texture index
+		if(Q3Texture.name[0]==0)
+			NewLight.Texture=m_nDefaultTextureIndexSpotlight ;
+		else
+		{
+			NewLight.Texture=AddTextureUnique(Q3Texture) ; // this will add the texture name to the list if it is unique, as well as setting the index
+			if(NewLight.Texture==ADDTEXTUREUNIQUE_FAIL) 
+				return 0 ;
+		}
+		*/
+
+		return AddLight(NewLight) ;
+	}
+	else // add a non-shadowing deferred shading point light
+	{
+		// light settings.
+		NewLamp.Position[0]=flOrigin[0]+flCentre[0] ;
+		NewLamp.Position[1]=flOrigin[1]+flCentre[1] ;
+		NewLamp.Position[2]=flOrigin[2]+flCentre[2] ;
+
+		NewLamp.Min[0]=flOrigin[0]-flRadius[0] ;
+		NewLamp.Min[1]=flOrigin[1]-flRadius[1] ;
+		NewLamp.Min[2]=flOrigin[2]-flRadius[2] ;
+
+		NewLamp.Max[0]=flOrigin[0]+flRadius[0] ;
+		NewLamp.Max[1]=flOrigin[1]+flRadius[1] ;
+		NewLamp.Max[2]=flOrigin[2]+flRadius[2] ;
+
+		NewLamp.Colour[0]=flColour[0] ;
+		NewLamp.Colour[1]=flColour[1] ;
+		NewLamp.Colour[2]=flColour[2] ;
+
+		NewLamp.Brightness=flBrightness * BRIGHTNESSTWEAK ;
+
+		NewLamp.LightNode=nLightNode ; // typically -1, but may be 0 to 3 if this lamp is the node for some TexLamp freeform deferred shading geometry.
+
+
+		// Note that m_pLamp.Zone will be set after we first convert lamps into triangles and then 
+		// assign those triangles to zones.  At that point, if the assigned triangle is also flagged as
+		// coming from a lamp, then the lamp's list of zones will be updated.
+
+				// add the light's texture index
+		if(Q3Texture.name[0]==0)
+		{
+			if(nLightNode==-1)
+				NewLamp.Texture=m_nDefaultTextureIndexLamp ; // normal 1 pass deferred shading
+			else
+				NewLamp.Texture=m_nDefaultTextureIndexLamp2Pass ; // special 2 pass deferred shading to texlamps
+		}
+		else
+		{
+			NewLamp.Texture=AddTextureUnique(Q3Texture) ; // this will add the texture name to the list if it is unique, as well as setting the index
+			if(NewLamp.Texture==ADDTEXTUREUNIQUE_FAIL) 
+				return 0 ;
+		}	
+
+		return AddLamp(NewLamp) ;
+	}
+
+}
+
+// adds a spotlight texture name if it is unique, returns the index to that texture name either way.
+// returns ADDSPOTLIGHTTEXTURE_FAIL on a fail
+
+int Q3Map::AddSpolightTexture(char TEXNAME[])
+{
+	if((strlen(TEXNAME)>Q3NAMESIZE) || (m_nMaxSpotlightTexture>=MAX_PROJECTORTEX))
+		return ADDSPOTLIGHTTEXTURE_FAIL ;
+
+
+	// scan through all the newly added textures so far and see if this one already exists.
+	int nTexture=0 ;
+	int nPos=0 ;
+
+	bool bMatch ;
+
+	for(nTexture=0 ; nTexture<m_nMaxSpotlightTexture ; nTexture++)
+	{
+		bMatch=true ;
+		// scan through the characters of the texture names, comparing them. 
+		for(nPos=0 ; nPos<Q3NAMESIZE ; nPos++)
+		{
+			// do the two textures have a difference in the name at this position?
+			if(m_chSpotlightTexture[nTexture][nPos]!=TEXNAME[nPos])
+			{
+				bMatch=false ;
+				break ;
+			}
+
+			// is it the end of the texture name?  
+			if(TEXNAME[nPos]=='\0') // end of texture
+				break ;
+		
+		}// end scanning name
+
+		if(bMatch) // found a match, so return ok but don't add a texture
+			return nTexture ;  // we don't add any new texture, return this texture's index
+	}
+
+	// if we got this far, we must have a unique texture
+	strcpy(m_chSpotlightTexture[m_nMaxSpotlightTexture], TEXNAME) ;
+	m_nMaxSpotlightTexture++ ;
+
+	return m_nMaxSpotlightTexture-1 ; // return this new texture's index
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+int Q3Map::initFaces(void)
+{
+
+	m_nGroup=0 ; // reset the group counter, used to work out transparent groupings for triangles.
+	
+  Q3BspFace_t *faces = getFaces();
+
+  m_BspFaces = new Q3BspFaceRenderer[m_iNumFaces];
+	if(m_BspFaces==NULL) return 0 ; // fail, out of memory.
+  m_NumBspFaces = m_iNumFaces;
+
+	
+  for (int i=0; i < m_NumBspFaces; i++)
+  {					
+    m_BspFaces[i].lm_index = faces[i].lm_index;
+    m_BspFaces[i].meshvert = faces[i].meshvert;
+    m_BspFaces[i].n_meshverts = faces[i].n_meshverts;
+    m_BspFaces[i].n_vertexes = faces[i].n_vertexes;
+    for (int j=0; j<3; j++)
+      m_BspFaces[i].normal[j] = faces[i].normal[j];
+    m_BspFaces[i].texture = faces[i].texture;
+    m_BspFaces[i].type = faces[i].type;
+    m_BspFaces[i].vertex = faces[i].vertex;
+
+    m_BspFaces[i].n_triangles = m_BspFaces[i].n_meshverts / 3;
+
+    if (m_BspFaces[i].type == PATCH)
+    {
+      m_BspFaces[i].patch = handlePatch(i);
+    }
+    else
+    {
+      m_BspFaces[i].patch = NULL;
+    }
+
+
+  }
+
+
+	// check patches aren't degenerate
+	int numIndex = 0;
+  int numVertex = 0;
+
+
+    for (int i=0; i < m_NumBspFaces; i++)
+    {		
+
+			numIndex = 0;
+			numVertex = 0;
+
+      if ((m_BspFaces[i].type == PATCH) && (m_BspFaces[i].patch != NULL))
+			{
+          for (int j=0; j < m_BspFaces[i].patch->size; j++)
+          {
+            numIndex += m_BspFaces[i].patch->bezier[j].mNumIndex;
+            numVertex += m_BspFaces[i].patch->bezier[j].mNumVertex;
+          }
+
+					if((numIndex==0) || (numVertex==0))
+					{
+						DELETE_ARRAY( m_BspFaces[i].patch->bezier ) ;
+						DELETE_POINTER( m_BspFaces[i].patch ) ;
+					}
+
+      }// end if patch
+
+
+    }// end for 
+
+
+
+	// copy the vertices over.  
+	// We need to work on a copy because we need to create new verts when splitting triangles that cross subzones, and for patches
+	for(int i=0 ; i<m_iNumVertices ; i++)
+	{
+		m_pVertex[i]=m_pVertices[i] ;
+		m_nVertexMax++ ; // need to update this manually since we aren't adding new verts, but filling in the original mem.
+	}
+
+
+	return 1 ;
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// stuff for assigning triangles to subzones, splitting them where necessary.
+//
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Q3Map::SetupZones(void)
+{
+	int nSubZone=0 ;
+	int nZone=0 ;
+	int nPos=0 ;
+
+//	float flMinX=0.0f ;
+//	float flMinY=0.0f ;
+//	float flMinZ=0.0f ;
+//	float flMaxX=0.0f ;
+//	float flMaxY=0.0f ;
+//	float flMaxZ=0.0f ;
+
+	m_nMaxZone=0 ;
+	
+	for(nZone=0 ; nZone<MAX_ZONE ; nZone++)
+	{
+		m_nZone[nZone][INDEX_SUBZONECOUNT]=0 ;
+		m_ZoneBoundary[nZone].Min[0]=MINMAXLIMIT ;
+		m_ZoneBoundary[nZone].Min[1]=MINMAXLIMIT ;
+		m_ZoneBoundary[nZone].Min[2]=MINMAXLIMIT ;
+		m_ZoneBoundary[nZone].Max[0]=-MINMAXLIMIT ;
+		m_ZoneBoundary[nZone].Max[1]=-MINMAXLIMIT ;
+		m_ZoneBoundary[nZone].Max[2]=-MINMAXLIMIT ;
+	}
+
+
+	// find the highest used zone number, then +1 to get our limit.
+	for(nSubZone=0 ; nSubZone<m_iNumSubZones ; nSubZone++)
+		if(m_pSubZones[nSubZone].Zone>m_nMaxZone)
+			m_nMaxZone=m_pSubZones[nSubZone].Zone ;
+
+	m_nMaxZone++ ; // our limit
+
+	
+	//char chMessage[1024] ;
+
+
+	// fill in what subzones are in each zone
+	for(nSubZone=0 ; nSubZone<m_iNumSubZones ; nSubZone++)
+	{
+		
+
+		nZone=m_pSubZones[nSubZone].Zone ;
+
+		// find next empty slot in this zone
+		nPos=0 ;
+		while((nPos<MAX_SUBZONEPERZONE) && (nPos<m_nZone[nZone][INDEX_SUBZONECOUNT]))
+			nPos++ ;
+
+		// if there's room, add the subzone to this zone
+		if(nPos<MAX_SUBZONEPERZONE) 
+		{
+			m_nZone[nZone][nPos]=nSubZone ;
+
+			// limits used for cutting up lights (not useful for other boundary stuff, check subzones instead)
+			if(m_pSubZones[nSubZone].Min[0]<m_ZoneBoundary[nZone].Min[0]) 
+				m_ZoneBoundary[nZone].Min[0]= m_pSubZones[nSubZone].Min[0] ;
+			if(m_pSubZones[nSubZone].Min[1]<m_ZoneBoundary[nZone].Min[1]) 
+				m_ZoneBoundary[nZone].Min[1]= m_pSubZones[nSubZone].Min[1] ;
+			if(m_pSubZones[nSubZone].Min[2]<m_ZoneBoundary[nZone].Min[2]) 
+				m_ZoneBoundary[nZone].Min[2]= m_pSubZones[nSubZone].Min[2] ;
+
+			if(m_pSubZones[nSubZone].Max[0]>m_ZoneBoundary[nZone].Max[0]) 
+				m_ZoneBoundary[nZone].Max[0]= m_pSubZones[nSubZone].Max[0] ;
+			if(m_pSubZones[nSubZone].Max[1]>m_ZoneBoundary[nZone].Max[1]) 
+				m_ZoneBoundary[nZone].Max[1]= m_pSubZones[nSubZone].Max[1] ;
+			if(m_pSubZones[nSubZone].Max[2]>m_ZoneBoundary[nZone].Max[2]) 
+				m_ZoneBoundary[nZone].Max[2]= m_pSubZones[nSubZone].Max[2] ;
+
+			m_nZone[nZone][INDEX_SUBZONECOUNT]++ ;
+		}
+
+
+	}
+
+
+}
+
+
+// work out what zone each triangle is in.
+// if it is in more than one, cut it up into smaller triangles that are only in one zone each.
+int Q3Map::AssignTrianglesToZones(void)
+{
+	int nCurrentTriangle=0 ;
+//	int nZone=0 ;
+
+
+	/*
+	char chMessage[1024] ;
+	float flPos[3] ;
+	int nTri=0 ;
+	float flVert[3][3] ;
+	
+
+	for(nTri=0 ; nTri<m_nTriangleMax ; nTri++)
+	{
+		flVert[0][0]=m_pVertex[  m_pTriangle[nTri].VIndex[0]  ].position[0] ;
+		flVert[0][1]=m_pVertex[  m_pTriangle[nTri].VIndex[0]  ].position[1] ;
+		flVert[0][2]=m_pVertex[  m_pTriangle[nTri].VIndex[0]  ].position[2] ;
+
+		flVert[1][0]=m_pVertex[  m_pTriangle[nTri].VIndex[1]  ].position[0] ;
+		flVert[1][1]=m_pVertex[  m_pTriangle[nTri].VIndex[1]  ].position[1] ;
+		flVert[1][2]=m_pVertex[  m_pTriangle[nTri].VIndex[1]  ].position[2] ;
+
+		flVert[2][0]=m_pVertex[  m_pTriangle[nTri].VIndex[2]  ].position[0] ;
+		flVert[2][1]=m_pVertex[  m_pTriangle[nTri].VIndex[2]  ].position[1] ;
+		flVert[2][2]=m_pVertex[  m_pTriangle[nTri].VIndex[2]  ].position[2] ;
+
+
+		flPos[0]=(flVert[0][0]+flVert[1][0]+flVert[2][0])/3.0f ;
+		flPos[1]=(flVert[0][1]+flVert[1][1]+flVert[2][1])/3.0f ;
+		flPos[2]=(flVert[0][2]+flVert[1][2]+flVert[2][2])/3.0f ;
+
+		nZone=0 ;
+		while((nZone<m_iNumSubZones) && !PointInZone(flPos, nZone))
+			nZone++ ;
+
+
+
+
+	}
+	*/
+
+
+
+	for(nCurrentTriangle=0 ; nCurrentTriangle<m_nTriangleMax ; nCurrentTriangle++)
+	{
+		if(!SetupTriangleZone(nCurrentTriangle)) return 0 ; // what zone completely contains this triangle, if any
+
+	}// end for current triangle
+
+	return 1 ;
+}
+
+// return the zone this triangle is in, or -1 if it is not entirely contained by any zone
+// this is also a convienient spot for us to update Lamp zones when we discover what zones its triangles are in,
+// and also a handy place to note if the triangle is a TexLamp or not 
+// (TexLamp is free form geometry that is bound to a lamp and gets converted to deferred shading lights, allowing us to do fake shadowing)
+
+int Q3Map::FindTriangleZone(int nTriangle)
+{
+	int nZone=0 ;
+//	int nSubZone=0 ;
+	int nPos=0 ;
+	bool bVertInSubZone=false ;
+	int nVert=0 ;
+	bool bTriangleInZone=false ;
+//	int nMaxSubZone=m_iNumSubZones ;
+	float flVert[6][3] ; // verts 0, 1, 2 are the original triangle corners, verts 3, 4, 5 are interpolated edge points.
+	// we need the edge points, since it's possible for all the 
+	// triangle verts to be in one L shaped zone but the triangle they form not be in that zone. 
+	// (such as if there's a vert at the corner and two ends of the "L")
+
+
+	flVert[0][0]=m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[0] ;
+	flVert[0][1]=m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[1] ;
+	flVert[0][2]=m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[2] ;
+
+	flVert[1][0]=m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[0] ;
+	flVert[1][1]=m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[1] ;
+	flVert[1][2]=m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[2] ;
+
+	flVert[2][0]=m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[0] ;
+	flVert[2][1]=m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[1] ;
+	flVert[2][2]=m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[2] ;
+
+	flVert[3][0]=(flVert[0][0]+flVert[1][0])/2.0f ;
+	flVert[3][1]=(flVert[0][1]+flVert[1][1])/2.0f ;
+	flVert[3][2]=(flVert[0][2]+flVert[1][2])/2.0f ;
+
+	flVert[4][0]=(flVert[1][0]+flVert[2][0])/2.0f ;
+	flVert[4][1]=(flVert[1][1]+flVert[2][1])/2.0f ;
+	flVert[4][2]=(flVert[1][2]+flVert[2][2])/2.0f ;
+
+	flVert[5][0]=(flVert[2][0]+flVert[0][0])/2.0f ;
+	flVert[5][1]=(flVert[2][1]+flVert[0][1])/2.0f ;
+	flVert[5][2]=(flVert[2][2]+flVert[0][2])/2.0f ;
+
+
+	// scan through the zones until:
+	// a) we find a zone that completely contains the six vertices
+	// b) we run out of zones.
+
+
+	do
+	{
+		nVert=0 ;
+		bTriangleInZone=false ;
+
+		// scan through the verts until:
+		// a) we find a vert that isn't in this zone
+		// b) we run out of verts
+
+		do
+		{
+
+			// scan through the zone's subzones until: 
+			// a) we find one that contains this vert, 
+			// b) we hit the subzoneperzone limit, 
+			// c) this zone runs out of subzones
+
+			nPos=0 ;
+			do
+			{
+				bVertInSubZone=PointInSubZone(flVert[nVert], m_nZone[nZone][nPos]) ;
+			}while( !bVertInSubZone && (++nPos<MAX_SUBZONEPERZONE) && (nPos<m_nZone[nZone][INDEX_SUBZONECOUNT])) ;
+
+			// if bVertInSubZone is false, we found a vert that isn't in this zone.
+
+		}while(bVertInSubZone && (++nVert<6)) ;
+
+		if(bVertInSubZone) bTriangleInZone=true ;
+
+	}while(!bTriangleInZone && (++nZone<m_nMaxZone)) ;
+
+
+	
+
+
+	if(!bTriangleInZone)
+		return -1 ;
+	else
+	{
+
+		// if this triangle came from a lamp entity, we note in that lamp entity that it touches this zone
+		int nLamp=m_pTriangle[nTriangle].Lamp ;
+		if(nLamp>-1) // if we have a lamp
+		{
+
+
+			int nSlot=m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT] ;
+
+			if(nSlot<MAX_ZONEPERLIGHT) // if the lamp isn't maxed out on zones
+			{
+				// check if we already have this zone recorded
+				int nCheckSlot=0 ;
+				int nFoundDuplicate=0 ;
+				for(nCheckSlot=0 ; nCheckSlot<nSlot ; nCheckSlot++)
+					if(m_pLamp[nLamp].Zone[nCheckSlot]==nZone)
+					{
+						nFoundDuplicate=1 ;
+						break ;
+					}
+
+				if(!nFoundDuplicate)
+				{
+					m_pLamp[nLamp].Zone[nSlot]=nZone ;  // write the zone into this slot
+					m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT]++ ; // note that we have one more zone
+				}
+
+			}
+		}
+
+
+		// if this triangle is a TexLamp triangle (free form deferred lighting shapes)
+		// then we remember this, in order to make assigning it to a lamp faster
+		int nTexture=m_pTriangle[nTriangle].Texture ;
+		if((nTexture==m_nBZN_LightNode0) || (nTexture==m_nBZN_LightNode1) || (nTexture==m_nBZN_LightNode2) || (nTexture==m_nBZN_LightNode3))
+			if(!AddTexLamp(nTriangle)) 
+				return ADDTEXLAMP_FAIL ; //if we failed to note the texlamp (probably out of memory), the whole level load will fail.
+
+
+		// finally, return the zone the triangle is in.
+		return nZone ;
+	}
+}
+
+
+
+// work out what zone a triangle is in, cut it up if it's in more than one.
+int Q3Map::SetupTriangleZone(int nTriangle)
+{
+
+
+	int nZone=0 ;
+
+	nZone=FindTriangleZone(nTriangle) ;
+
+	if(nZone==ADDTEXLAMP_FAIL)
+		return 0 ; 
+
+
+	if(nZone!=-1) // triangle was completely in a zone
+		m_pTriangle[nTriangle].Zone=nZone ;
+	else
+	{
+		// This triangle is in more than one zone.  (Or no subzone at all)
+		// we chop it up along the edges of every subzone it is in (regardless of whether they are a common zone or not)
+		// so that the resulting triangles will all be in just one subzone, and therefore in only one zone.
+		// this might produce a few extra triangles more than we strictly need, since some will both be in the same zone,
+		// but it is simple and the extra triangles are trivial in number.
+
+		// As we go to each new cut plane, it must be applied progressively to all newly created triangles too.
+
+		int nInitialTrianglePos=m_nTriangleMax ; // where we start adding new triangles
+
+		int nTriLoop=0 ;
+		int nTriangleToCut=0 ;
+		int nMaxTriangle=0 ;
+		int nSide=0 ;
+		int nAxis=0 ;
+		float flCutPos=0.0f ;
+		int nSubZone=0 ;
+		int nMaxSubZone=m_iNumSubZones ;
+		int nVert=0 ;
+		float flVert[6][3] ; // verts 0, 1, 2 are the original triangle corners, verts 3, 4, 5 are interpolated edge points.
+		// we need the edge points, since it's possible for all the 
+		// triangle verts to be in one L shaped zone but the triangle they form not be in that zone. 
+		// (such as if there's a vert at the corner and two ends of the "L")
+
+
+		flVert[0][0]=m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[0] ;
+		flVert[0][1]=m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[1] ;
+		flVert[0][2]=m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[2] ;
+
+		flVert[1][0]=m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[0] ;
+		flVert[1][1]=m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[1] ;
+		flVert[1][2]=m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[2] ;
+
+		flVert[2][0]=m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[0] ;
+		flVert[2][1]=m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[1] ;
+		flVert[2][2]=m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[2] ;
+
+		flVert[3][0]=(flVert[0][0]+flVert[1][0])/2.0f ;
+		flVert[3][1]=(flVert[0][1]+flVert[1][1])/2.0f ;
+		flVert[3][2]=(flVert[0][2]+flVert[1][2])/2.0f ;
+
+		flVert[4][0]=(flVert[1][0]+flVert[2][0])/2.0f ;
+		flVert[4][1]=(flVert[1][1]+flVert[2][1])/2.0f ;
+		flVert[4][2]=(flVert[1][2]+flVert[2][2])/2.0f ;
+
+		flVert[5][0]=(flVert[2][0]+flVert[0][0])/2.0f ;
+		flVert[5][1]=(flVert[2][1]+flVert[0][1])/2.0f ;
+		flVert[5][2]=(flVert[2][2]+flVert[0][2])/2.0f ;
+	
+
+
+
+		for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+		{
+			// are any of our original verts in this subzone?
+
+			nVert=0 ;
+			while( !PointInSubZone(flVert[nVert], nSubZone) && (++nVert<6)) ;
+
+			if(nVert<6) // one of the verts must have been in this subzone.
+			{
+				// cutup all triangles by the sides of this subzone.
+				// we'll need to cut more and more triangles as this progresses. (or at least test if they need to be cut)
+				for(nSide=0 ; nSide<6 ; nSide++)
+				{
+					switch(nSide)
+					{
+						case 0: nAxis=AXIS_X ; flCutPos=m_pSubZones[nSubZone].Min[0] ; break ;
+						case 1: nAxis=AXIS_X ; flCutPos=m_pSubZones[nSubZone].Max[0] ; break ;
+						case 2: nAxis=AXIS_Y ; flCutPos=m_pSubZones[nSubZone].Min[1] ; break ;
+						case 3: nAxis=AXIS_Y ; flCutPos=m_pSubZones[nSubZone].Max[1] ; break ;
+						case 4: nAxis=AXIS_Z ; flCutPos=m_pSubZones[nSubZone].Min[2] ; break ;
+						case 5: nAxis=AXIS_Z ; flCutPos=m_pSubZones[nSubZone].Max[2] ; break ;
+					}
+
+
+					nMaxTriangle=m_nTriangleMax-nInitialTrianglePos ;  // how may new triangles have been created since we first started cutting the original.
+
+					for(nTriLoop=-1 ; nTriLoop<nMaxTriangle ; nTriLoop++)
+					{
+						// work out if we are cutting up the original triangle or one of the newly created ones.
+						if(nTriLoop==-1)
+							nTriangleToCut=nTriangle ; // the original triangle, perhaps heavily cutup by now.
+						else
+							nTriangleToCut=nInitialTrianglePos+nTriLoop ;  // one of the newly created triangles.
+
+						if(!SplitTriangle(nTriangleToCut, nAxis, flCutPos)) return 0 ; // cut up the triangle, fail if we're out of memory or whatever.
+
+
+					}// end for nTriLoop
+
+				}// end cutting by each side of the subzone
+
+			}// end if one of the verts was in this subzone
+
+		}// end going through all subzones
+
+
+		// now that the triangle is well and truly chopped up, assign it a zone.
+		// Even though it should be entirely in a subzone by now, there's still the chance that
+		// it might not be inside any subzone at all.  If so, it will be assigned -1 zone and 
+		// exluded from the manualobjects
+		
+		m_pTriangle[nTriangle].Zone=FindTriangleZone(nTriangle) ;
+
+		// we don't have to worry about assigning zones to the newly created triangles, 
+		// they'll get theirs when the AssignTrianglesToZones loop reaches them at the end.
+
+	}// end if triangle was in more than one subzone (or no subzone at all)
+
+	return 1 ;
+}
+
+
+// cut a triangle along some axial plane, turning into 2 or 3 triangles.
+// If the plane doesn't go through the triangle then nothing will happen.
+int Q3Map::SplitTriangle(int nTriangle, int nAxis, float flCutPos)
+{
+
+	triangle_t NewTri ;
+
+	// these will stay -1 if no vert is created, else will be index of the new vert
+	int nABNum=-1 ;
+	int nBCNum=-1 ;
+	int nCANum=-1 ;
+
+	Q3BspVertex	VertA = m_pVertex[  m_pTriangle[ nTriangle ].VIndex[0]  ] ;
+	Q3BspVertex	VertB = m_pVertex[  m_pTriangle[ nTriangle ].VIndex[1]  ] ;
+	Q3BspVertex	VertC = m_pVertex[  m_pTriangle[ nTriangle ].VIndex[2]  ] ;
+	Q3BspVertex	VertexAB ;
+	Q3BspVertex	VertexBC ;
+	Q3BspVertex	VertexCA ;
+
+	float flSpan=0.0f ;
+	float flCutSpan=0.0f ;
+	float flPercent=0.0f ;
+
+	switch(nAxis)
+	{
+
+		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		case AXIS_X:
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline.
+			if( 
+					((VertA.position[0]<flCutPos-SUBZONE_EPSILON) && (VertB.position[0]>flCutPos+SUBZONE_EPSILON))
+					||
+					((VertA.position[0]>flCutPos+SUBZONE_EPSILON) && (VertB.position[0]<flCutPos-SUBZONE_EPSILON))
+				)
+			{
+				// work out the span and percentage
+				if(VertA.position[0]<flCutPos)
+				{
+					flSpan=VertB.position[0]-VertA.position[0] ;
+					flCutSpan=flCutPos-VertA.position[0] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertA.position[0]-VertB.position[0] ;
+					flCutSpan=flCutPos-VertB.position[0] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ;
+				nABNum=m_nVertexMax ;
+				if(!AddVertex(VertexAB)) 
+					return 0 ;
+			}// end if need create VertexAB
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline.
+			if( 
+					((VertB.position[0]<flCutPos-SUBZONE_EPSILON) && (VertC.position[0]>flCutPos+SUBZONE_EPSILON))
+					||
+					((VertB.position[0]>flCutPos+SUBZONE_EPSILON) && (VertC.position[0]<flCutPos-SUBZONE_EPSILON))
+				)
+			{
+				// work out the span and percentage
+				if(VertB.position[0]<flCutPos)
+				{
+					flSpan=VertC.position[0]-VertB.position[0] ;
+					flCutSpan=flCutPos-VertB.position[0] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertB.position[0]-VertC.position[0] ;
+					flCutSpan=flCutPos-VertC.position[0] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ;
+				nBCNum=m_nVertexMax ;
+				if(!AddVertex(VertexBC)) 
+					return 0 ;
+
+			}// end if need create VertexBC
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline.
+			if( 
+					((VertC.position[0]<flCutPos) && (VertA.position[0]>flCutPos))
+					||
+					((VertC.position[0]>flCutPos) && (VertA.position[0]<flCutPos))
+				)
+			{
+				// work out the span and percentage
+				if(VertC.position[0]<flCutPos)
+				{
+					flSpan=VertA.position[0]-VertC.position[0] ;
+					flCutSpan=flCutPos-VertC.position[0] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertC.position[0]-VertA.position[0] ;
+					flCutSpan=flCutPos-VertA.position[0] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ;
+				nCANum=m_nVertexMax ;
+				if(!AddVertex(VertexCA)) 
+					return 0 ;
+
+			}// end if need create VertexCA
+			break ;
+
+		
+		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		case AXIS_Y:
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline.
+			if( 
+					((VertA.position[1]<flCutPos-SUBZONE_EPSILON) && (VertB.position[1]>flCutPos+SUBZONE_EPSILON))
+					||
+					((VertA.position[1]>flCutPos+SUBZONE_EPSILON) && (VertB.position[1]<flCutPos-SUBZONE_EPSILON))
+				)
+			{
+				// work out the span and percentage
+				if(VertA.position[1]<flCutPos)
+				{
+					flSpan=VertB.position[1]-VertA.position[1] ;
+					flCutSpan=flCutPos-VertA.position[1] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertA.position[1]-VertB.position[1] ;
+					flCutSpan=flCutPos-VertB.position[1] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ;
+				nABNum=m_nVertexMax ;
+				if(!AddVertex(VertexAB)) 
+					return 0 ;
+			}// end if need create VertexAB
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline.
+			if( 
+					((VertB.position[1]<flCutPos-SUBZONE_EPSILON) && (VertC.position[1]>flCutPos+SUBZONE_EPSILON))
+					||
+					((VertB.position[1]>flCutPos+SUBZONE_EPSILON) && (VertC.position[1]<flCutPos-SUBZONE_EPSILON))
+				)
+			{
+				// work out the span and percentage
+				if(VertB.position[1]<flCutPos)
+				{
+					flSpan=VertC.position[1]-VertB.position[1] ;
+					flCutSpan=flCutPos-VertB.position[1] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertB.position[1]-VertC.position[1] ;
+					flCutSpan=flCutPos-VertC.position[1] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ;
+				nBCNum=m_nVertexMax ;
+				if(!AddVertex(VertexBC)) 
+					return 0 ;
+
+			}// end if need create VertexBC
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline.
+			if( 
+					((VertC.position[1]<flCutPos) && (VertA.position[1]>flCutPos))
+					||
+					((VertC.position[1]>flCutPos) && (VertA.position[1]<flCutPos))
+				)
+			{
+				// work out the span and percentage
+				if(VertC.position[1]<flCutPos)
+				{
+					flSpan=VertA.position[1]-VertC.position[1] ;
+					flCutSpan=flCutPos-VertC.position[1] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertC.position[1]-VertA.position[1] ;
+					flCutSpan=flCutPos-VertA.position[1] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ;
+				nCANum=m_nVertexMax ;
+				if(!AddVertex(VertexCA)) 
+					return 0 ;
+
+			}// end if need create VertexCA
+			break ;
+
+		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		case AXIS_Z:
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertA is on one side of the cut and VertB is on the other, create VertexAB on the cutline.
+			if( 
+					((VertA.position[2]<flCutPos-SUBZONE_EPSILON) && (VertB.position[2]>flCutPos+SUBZONE_EPSILON))
+					||
+					((VertA.position[2]>flCutPos+SUBZONE_EPSILON) && (VertB.position[2]<flCutPos-SUBZONE_EPSILON))
+				)
+			{
+				// work out the span and percentage
+				if(VertA.position[2]<flCutPos)
+				{
+					flSpan=VertB.position[2]-VertA.position[2] ;
+					flCutSpan=flCutPos-VertA.position[2] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertA.position[2]-VertB.position[2] ;
+					flCutSpan=flCutPos-VertB.position[2] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertA, &VertB, flPercent, &VertexAB) ;
+				nABNum=m_nVertexMax ;
+				if(!AddVertex(VertexAB)) 
+					return 0 ;
+			}// end if need create VertexAB
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertB is on one side of the cut and VertC is on the other, create VertexBC on the cutline.
+			if( 
+					((VertB.position[2]<flCutPos-SUBZONE_EPSILON) && (VertC.position[2]>flCutPos+SUBZONE_EPSILON))
+					||
+					((VertB.position[2]>flCutPos+SUBZONE_EPSILON) && (VertC.position[2]<flCutPos-SUBZONE_EPSILON))
+				)
+			{
+				// work out the span and percentage
+				if(VertB.position[2]<flCutPos)
+				{
+					flSpan=VertC.position[2]-VertB.position[2] ;
+					flCutSpan=flCutPos-VertB.position[2] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertB.position[2]-VertC.position[2] ;
+					flCutSpan=flCutPos-VertC.position[2] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertB, &VertC, flPercent, &VertexBC) ;
+				nBCNum=m_nVertexMax ;
+				if(!AddVertex(VertexBC)) 
+					return 0 ;
+
+			}// end if need create VertexBC
+
+			////////////////////////////////////////////////////////////////////////////////////////////////
+			// if VertC is on one side of the cut and VertA is on the other, create VertexCA on the cutline.
+			if( 
+					((VertC.position[2]<flCutPos) && (VertA.position[2]>flCutPos))
+					||
+					((VertC.position[2]>flCutPos) && (VertA.position[2]<flCutPos))
+				)
+			{
+				// work out the span and percentage
+				if(VertC.position[2]<flCutPos)
+				{
+					flSpan=VertA.position[2]-VertC.position[2] ;
+					flCutSpan=flCutPos-VertC.position[2] ;
+					flPercent=1.0f-flCutSpan/flSpan ;
+				}
+				else
+				{
+					flSpan=VertC.position[2]-VertA.position[2] ;
+					flCutSpan=flCutPos-VertA.position[2] ;
+					flPercent=flCutSpan/flSpan ;
+				}
+
+				CreateTweenVert(&VertC, &VertA, flPercent, &VertexCA) ;
+				nCANum=m_nVertexMax ;
+				if(!AddVertex(VertexCA)) 
+					return 0 ;
+
+			}// end if need create VertexCA
+			break ;
+
+
+	}
+
+//	int nInitialTrianglePos=m_nTriangleMax ; // debugging
+
+	// default parameters for all new triangles
+	NewTri.Texture	=	m_pTriangle[ nTriangle ].Texture ;
+	//NewTri.Lightmap	=	m_pTriangle[ nTriangle ].Lightmap ; // bzn doesn't use lightmaps
+	NewTri.Lamp			= m_pTriangle[ nTriangle ].Lamp ; 
+	NewTri.Group = m_pTriangle[ nTriangle ].Group ;
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	// now we create new triangles depending on the verts we created.
+	if((nABNum!=-1) && (nCANum!=-1))
+	{
+		// add (AB, B, C)
+		NewTri.VIndex[0]=nABNum ;
+		NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// add (C, CA, AB)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		NewTri.VIndex[1]=nCANum ;
+		NewTri.VIndex[2]=nABNum ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// overwrite the original triangle with (A, AB, CA)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		NewTri.VIndex[1]=nABNum ;
+		NewTri.VIndex[2]=nCANum ;
+		m_pTriangle[ nTriangle ]=NewTri ;
+	}
+	else
+	if((nABNum!=-1) && (nBCNum!=-1))
+	{
+		// add (BC, C, A)
+		NewTri.VIndex[0]=nBCNum ;
+		NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// add (A, AB, BC)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		NewTri.VIndex[1]=nABNum ;
+		NewTri.VIndex[2]=nBCNum ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// overwrite the original triangle with (B, BC, AB)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		NewTri.VIndex[1]=nBCNum ;
+		NewTri.VIndex[2]=nABNum ;
+		m_pTriangle[ nTriangle ]=NewTri ;
+	}
+	else
+	if((nBCNum!=-1) && (nCANum!=-1))
+	{
+		// add (CA, A, B)
+		NewTri.VIndex[0]=nCANum ;
+		NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// add (B, BC, CA)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		NewTri.VIndex[1]=nBCNum ;
+		NewTri.VIndex[2]=nCANum ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// overwrite the original triangle with (C, CA, BC)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		NewTri.VIndex[1]=nCANum ;
+		NewTri.VIndex[2]=nBCNum ;
+		m_pTriangle[ nTriangle ]=NewTri ;
+	}
+	else
+	if(nABNum!=-1)
+	{
+		// add (AB, B, C)
+		NewTri.VIndex[0]=nABNum ;
+		NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// overwrite the original triangle with (A, AB, C)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		NewTri.VIndex[1]=nABNum ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		m_pTriangle[ nTriangle ]=NewTri ;
+	}
+	else
+	if(nBCNum!=-1)
+	{
+		// add (BC, C, A)
+		NewTri.VIndex[0]=nBCNum ;
+		NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// overwrite the original triangle with (B, BC, A)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		NewTri.VIndex[1]=nBCNum ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		m_pTriangle[ nTriangle ]=NewTri ;
+	}
+	else
+	if(nCANum!=-1)
+	{
+		// add (CA, A, B)
+		NewTri.VIndex[0]=nCANum ;
+		NewTri.VIndex[1]=m_pTriangle[ nTriangle ].VIndex[0] ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		if(!AddTriangle(NewTri)) return 0 ;
+
+		// overwrite the original triangle with (C, CA, B)
+		NewTri.VIndex[0]=m_pTriangle[ nTriangle ].VIndex[2] ;
+		NewTri.VIndex[1]=nCANum ;
+		NewTri.VIndex[2]=m_pTriangle[ nTriangle ].VIndex[1] ;
+		m_pTriangle[ nTriangle ]=NewTri ;
+	}
+
+	return 1 ;
+}
+
+void Q3Map::CreateTweenVert(Q3BspVertex* pVertA, Q3BspVertex* pVertB, float flPercent0, Q3BspVertex* pVertexAB)
+{
+	float flPercent1=1.0f-flPercent0 ;
+
+	pVertexAB->color[0]=(unsigned char)(flPercent0*pVertA->color[0] + flPercent1*pVertB->color[0]) ;
+	pVertexAB->color[1]=(unsigned char)(flPercent0*pVertA->color[1] + flPercent1*pVertB->color[1]) ;
+	pVertexAB->color[2]=(unsigned char)(flPercent0*pVertA->color[2] + flPercent1*pVertB->color[2]) ;
+	pVertexAB->color[3]=(unsigned char)(flPercent0*pVertA->color[3] + flPercent1*pVertB->color[3]) ;
+
+	pVertexAB->position[0]=flPercent0*pVertA->position[0] + flPercent1*pVertB->position[0] ;
+	pVertexAB->position[1]=flPercent0*pVertA->position[1] + flPercent1*pVertB->position[1] ;
+	pVertexAB->position[2]=flPercent0*pVertA->position[2] + flPercent1*pVertB->position[2] ;
+				
+	pVertexAB->texcoord[0][0]=flPercent0*pVertA->texcoord[0][0] + flPercent1*pVertB->texcoord[0][0] ;
+	pVertexAB->texcoord[0][1]=flPercent0*pVertA->texcoord[0][1] + flPercent1*pVertB->texcoord[0][1] ;
+	pVertexAB->texcoord[1][0]=flPercent0*pVertA->texcoord[1][0] + flPercent1*pVertB->texcoord[1][0] ;
+	pVertexAB->texcoord[1][1]=flPercent0*pVertA->texcoord[1][1] + flPercent1*pVertB->texcoord[1][1] ;
+
+	pVertexAB->normal[0]=flPercent0*pVertA->normal[0] + flPercent1*pVertB->normal[0] ;
+	pVertexAB->normal[1]=flPercent0*pVertA->normal[1] + flPercent1*pVertB->normal[1] ;
+	pVertexAB->normal[2]=flPercent0*pVertA->normal[2] + flPercent1*pVertB->normal[2] ;
+	// normalize
+	float flLen=sqrt(pVertexAB->normal[0]*pVertexAB->normal[0] + pVertexAB->normal[1]*pVertexAB->normal[1] + pVertexAB->normal[2]*pVertexAB->normal[2]) ;
+	if(flLen!=0.0f) // don't divide by zero... but normal is messed up.
+	{
+		pVertexAB->normal[0]/=flLen ;
+		pVertexAB->normal[1]/=flLen ;
+		pVertexAB->normal[2]/=flLen ;
+	}
+	else
+	{
+		// default a messed up normal to point upward
+		pVertexAB->normal[0]=0.0f ;
+		pVertexAB->normal[1]=1.0f ;
+		pVertexAB->normal[2]=0.0f ;
+	}
+}
+
+// returns the next subzone a point is in after the start subzone, or -1 if there are no more subzones
+int Q3Map::GetNextSubZone(float *flPoint, int nStart, int nMax)
+{
+	while(++nStart<nMax)
+		if(PointInSubZone(flPoint, nStart))
+			break ;
+
+	if(nStart==nMax)
+		return -1 ;
+	else
+		return nStart ;
+}
+
+// returns true if a point is in a subzone.
+bool Q3Map::PointInSubZone(float *flPoint, int nSubZone)
+{
+	if(
+				(flPoint[0]>=m_pSubZones[nSubZone].Min[0]-SUBZONE_EPSILON) && (flPoint[0]<=m_pSubZones[nSubZone].Max[0]+SUBZONE_EPSILON)
+			&&(flPoint[1]>=m_pSubZones[nSubZone].Min[1]-SUBZONE_EPSILON) && (flPoint[1]<=m_pSubZones[nSubZone].Max[1]+SUBZONE_EPSILON)
+			&&(flPoint[2]>=m_pSubZones[nSubZone].Min[2]-SUBZONE_EPSILON) && (flPoint[2]<=m_pSubZones[nSubZone].Max[2]+SUBZONE_EPSILON)
+		)
+		return true ;
+
+	return false ;
+}
+
+// returns true if a point is in a zone.
+bool Q3Map::PointInZone(float *flPos, int nZone)
+{
+	int nMaxSubZone=m_nZone[nZone][INDEX_SUBZONECOUNT] ;
+
+	for(int nSubZoneIndex=0 ; nSubZoneIndex<nMaxSubZone ; nSubZoneIndex++)
+		if(PointInSubZone(flPos, m_nZone[nZone][nSubZoneIndex]))
+			return true ;
+		
+	return false ;
+}
+
+// returns true if an axis aligned bounding box touches a subzone.
+bool Q3Map::AABBTouchesSubZone(float *flPointMin, float *flPointMax, int nSubZone)
+{
+	// if test AABB overlaps the subzone AABB
+	if(
+				 (m_pSubZones[nSubZone].Min[0]<flPointMax[0]) && (m_pSubZones[nSubZone].Max[0]>flPointMin[0])
+			&& (m_pSubZones[nSubZone].Min[1]<flPointMax[1]) && (m_pSubZones[nSubZone].Max[1]>flPointMin[1])
+			&& (m_pSubZones[nSubZone].Min[2]<flPointMax[2]) && (m_pSubZones[nSubZone].Max[2]>flPointMin[2])
+		)
+		return true ;
+
+	return false ;
+}
+
+// returns true if an axis aligned bounding box touches a zone.
+bool Q3Map::AABBTouchesZone(float *flPosMin, float *flPosMax, int nZone)
+{
+	int nMaxSubZone=m_nZone[nZone][INDEX_SUBZONECOUNT] ;
+
+	for(int nSubZoneIndex=0 ; nSubZoneIndex<nMaxSubZone ; nSubZoneIndex++)
+		if(AABBTouchesSubZone(flPosMin, flPosMax, m_nZone[nZone][nSubZoneIndex]))
+			return true ;
+		
+	return false ;
+}
+
+// take the faces from the BSP and add them to our list of triangles.
+int Q3Map::ConvertFacesToTriangles(void)
+{
+	int nFaceIndex = 0 ;
+	
+//	int nVertex=0 ;
+//	int nVertexMax=0 ;
+	int nTriangle=0 ;
+	int nTriangleMax=0 ;
+
+//	float flPosX=0.0f ;
+//	float flPosY=0.0f ;
+//	float flPosZ=0.0f ;
+//	float	flNormX=0.0f ;
+//	float	flNormY=0.0f ;
+//	float	flNormZ=0.0f ;
+//	float flTexU=0.0f ;
+//	float flTexV=0.0f ;
+	int nMeshVert=0 ;
+//	int nMeshVertA=0 ;
+//	int nMeshVertB=0 ;
+//	int nMeshVertC=0 ;
+
+//	Q3BspVertex *vertices = m_pVertices ;
+	int *meshverts = m_pMeshVerts ;
+	
+	QVECTOR junk ;
+	junk[0]=0.0f ;
+	junk[1]=0.0f ;
+	junk[2]=0.0f ;
+
+
+	nFaceIndex = 0 ;	
+	while(nFaceIndex<m_iNumFaces)
+	{
+
+		switch (m_BspFaces[nFaceIndex].type)
+		{
+			case MESH:    
+			case POLYGON:	
+
+				nTriangleMax=m_BspFaces[nFaceIndex].n_triangles ;
+				nMeshVert=m_BspFaces[nFaceIndex].meshvert ;
+				
+				for(nTriangle=0 ; nTriangle<nTriangleMax ; nTriangle++)
+				{
+
+					// if we are out of memory, grow it.  If we can't grow it, fail
+					if(m_nTriangleMax>=m_nTriangleLimit)
+						if(!ExpandTriangleMemory())
+							return 0 ;
+
+					
+
+					m_pTriangle[ m_nTriangleMax ].Texture=		m_BspFaces[nFaceIndex].texture ;
+					//m_pTriangle[ m_nTriangleMax ].Lightmap=		m_BspFaces[nFaceIndex].lm_index ; // bzn doesn't use lightmaps
+					m_pTriangle[ m_nTriangleMax ].VIndex[0]=	meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ;
+					m_pTriangle[ m_nTriangleMax ].VIndex[1]=	meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ;
+					m_pTriangle[ m_nTriangleMax ].VIndex[2]=	meshverts[ nMeshVert++ ]+m_BspFaces[nFaceIndex].vertex ;
+
+					m_pTriangle[ m_nTriangleMax ].Lamp=-1 ; // assume it didn't come from a lamp, this will be updated later
+					
+					m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ; // increment group number.  
+
+					m_nTriangleMax++ ;
+				}// end for nTriangle
+				m_nGroup++ ; // increment group.  Every face is a new group.
+				
+			break ;
+
+		}// end switch
+		
+		nFaceIndex++;
+	} // end while	
+
+	return 1 ;
+
+}
+
+
+// convert the patch info from the BSP into bezier curved triangle meshes and add to our triangle list.
+int Q3Map::ConvertPatchesToTriangles(void)
+{
+
+//	float flPosX=0.0f ;
+//	float flPosY=0.0f ;
+//	float flPosZ=0.0f ;
+//	float	flNormX=0.0f ;
+//	float	flNormY=0.0f ;
+//	float	flNormZ=0.0f ;
+//	float flTexU=0.0f ;
+//	float flTexV=0.0f ;
+//	int nMeshVert=0 ;
+	int nMeshVertA=0 ;
+	int nMeshVertB=0 ;
+	int nMeshVertC=0 ;
+
+
+	int nTriPerRow=0 ;
+	int nRow=0 ;
+
+	int nFirstVertex=m_nVertexMax ;
+	
+	int nVertCount=nFirstVertex ;
+//	int nPatchCount=0 ;
+
+	int* pIndexBuffer=NULL ;
+
+	Q3BspVertex NewVert ;
+		
+
+
+
+	int nCount=0 ;
+	int nCountB=0 ;
+
+
+
+		
+    int indexBufferindex = 0;
+	
+    int vertexBufferindex = 0;
+
+    for (int faceIndex=0; faceIndex < m_iNumFaces; faceIndex++)
+    {		
+
+			nCount++ ;
+			if(nCount==1)
+			{
+				nCountB+=nCount ;
+				nCount=0 ;
+			}
+
+
+      if (m_BspFaces[faceIndex].type == PATCH)
+      {
+        Q3BspPatch *patch = m_BspFaces[faceIndex].patch;
+
+        if (patch != NULL)
+        {
+					
+          for (int bezierIndex=0; bezierIndex < patch->size; bezierIndex++)
+          {
+						indexBufferindex = 0;
+						pIndexBuffer = new int[patch->bezier[bezierIndex].mNumIndex] ;
+						if(pIndexBuffer==NULL) return 0 ; // ran out of memory
+
+
+            for (int index=0; index < patch->bezier[bezierIndex].mNumIndex; index++)
+            {	
+              pIndexBuffer[indexBufferindex] = patch->bezier[bezierIndex].mIndex[index];
+              indexBufferindex++;
+            }
+
+            for (int vertex=0; vertex < patch->bezier[bezierIndex].mNumVertex; vertex++)
+            {
+
+              BspVertex *bspVertex = &patch->bezier[bezierIndex].mVertex[vertex];
+
+							NewVert.position[0]=bspVertex->mPosition[0] ;
+							NewVert.position[1]=bspVertex->mPosition[1] ;
+							NewVert.position[2]=bspVertex->mPosition[2] ;
+							NewVert.normal[0]=bspVertex->mNormal[0] ;
+							NewVert.normal[1]=bspVertex->mNormal[1] ;
+							NewVert.normal[2]=bspVertex->mNormal[2] ;
+							NewVert.texcoord[0][0]=bspVertex->mTexcoord[0][0] ;
+							NewVert.texcoord[0][1]=bspVertex->mTexcoord[0][1] ;
+
+							
+
+							// if we are out of memory, grow it.  If we can't grow it, fail
+							if(m_nVertexMax>=m_nVertexLimit)
+								if(!ExpandVertexMemory())
+								{
+									if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ;
+									return 0 ;
+								}
+
+
+							if(!AddVertex(NewVert)) 
+							{
+								if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ;
+								return 0 ;
+							}
+
+							nVertCount++ ;
+              vertexBufferindex++;
+
+            }// end for vertex
+
+
+						for (int j=0; j < 5; j++)
+						{
+							nRow=m_BspFaces[faceIndex].patch->bezier[bezierIndex].mRowIndex[j] ;
+							nTriPerRow=m_BspFaces[faceIndex].patch->bezier[bezierIndex].mTrianglesPerRow[j] ;
+
+							nMeshVertA=pIndexBuffer[nRow+0]+nFirstVertex ;
+							nMeshVertB=pIndexBuffer[nRow+1]+nFirstVertex ;
+							
+							for(int nVert=2 ; nVert<nTriPerRow ; nVert++)
+							{
+								// if we are out of memory, grow it.  If we can't grow it, fail
+								if(m_nTriangleMax>=m_nTriangleLimit)
+									if(!ExpandTriangleMemory())
+									{
+										if(pIndexBuffer) DELETE_ARRAY( pIndexBuffer ) ;
+										return 0 ;
+									}
+
+								m_pTriangle[ m_nTriangleMax ].Texture=		m_BspFaces[faceIndex].texture ;
+								//m_pTriangle[ m_nTriangleMax ].Lightmap=		m_BspFaces[faceIndex].lm_index ; // bzn doesn't use lightmaps
+
+								
+								
+								nMeshVertC=pIndexBuffer[nRow+nVert]+nFirstVertex ;
+
+
+								if(nVert&1)
+								{
+									m_pTriangle[ m_nTriangleMax ].VIndex[0]=	nMeshVertB ;
+									m_pTriangle[ m_nTriangleMax ].VIndex[1]=	nMeshVertA ;
+									m_pTriangle[ m_nTriangleMax ].VIndex[2]=	nMeshVertC ;
+								}
+								else
+								{
+									m_pTriangle[ m_nTriangleMax ].VIndex[0]=	nMeshVertA ;
+									m_pTriangle[ m_nTriangleMax ].VIndex[1]=	nMeshVertB ;
+									m_pTriangle[ m_nTriangleMax ].VIndex[2]=	nMeshVertC ;
+								}
+
+								m_pTriangle[ m_nTriangleMax ].Lamp=-1 ; // assume it didn't come from a lamp, this will be updated later
+
+
+								m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ;
+
+
+								m_nTriangleMax++ ;
+
+								nMeshVertA=nMeshVertB ;
+								nMeshVertB=nMeshVertC ;
+							}
+				
+
+						}
+						
+
+						// finished with the index buffer
+						if(pIndexBuffer) 
+							DELETE_ARRAY( pIndexBuffer ) ; 
+
+						nFirstVertex=nVertCount ;
+          }// end for bezier index
+
+
+					m_nGroup++ ; // increment the group number.  Each patch is treated as a single group.
+
+        }// end if patch not null
+      }// end if patch
+    }// end for faceIndex
+
+	return 1 ;
+
+}
+
+//''
+// some triangles might be designed to be deferred shading shapes inside of Lamp entities.
+// If so, change their material to the deferred shading configuration for that lamp entity.
+int Q3Map::ConvertTexLampsToLampTriangles(void)
+{
+
+	float flCentreX=0.0f ;
+	float flCentreY=0.0f ;
+	float flCentreZ=0.0f ;
+
+//	float flMinX=0.0f ;
+//	float flMinY=0.0f ;
+//	float flMinZ=0.0f ;
+//	float flMaxX=0.0f ;
+//	float flMaxY=0.0f ;
+//	float flMaxZ=0.0f ;
+
+//	float	flNormX=0.0f ;
+//	float	flNormY=0.0f ;
+//	float	flNormZ=0.0f ;
+//	float flTexU=0.0f ;
+//	float flTexV=0.0f ;
+
+	float flColR=0.0f ;
+	float flColG=0.0f ;
+	float flColB=0.0f ;
+
+	float flBrightness=0.0f ;
+
+	int nLamp=0 ;
+	int nTriangle=0 ;
+	int nTexLampListPos=0 ;
+	int nLightNode=0 ;
+	int nTexture=0 ;
+	int nZone=0 ;
+//	int nLampZone=0 ;
+//	int nMaxLampZone=0 ;
+//	int nZoneMatch=0 ;
+
+
+	for(nTexLampListPos=0 ; nTexLampListPos<m_nTexLampMax ; nTexLampListPos++)
+	{
+		nTriangle=m_pTexLamp[nTexLampListPos] ;
+
+		nZone=m_pTriangle[nTriangle].Zone ;
+
+		nTexture=m_pTriangle[nTriangle].Texture ;
+
+		if(nTexture==m_nBZN_LightNode0)
+			nLightNode=0 ;
+		else
+		if(nTexture==m_nBZN_LightNode1)
+			nLightNode=1 ;
+		else
+		if(nTexture==m_nBZN_LightNode2)
+			nLightNode=2 ;
+		else
+		if(nTexture==m_nBZN_LightNode3)
+			nLightNode=3 ;
+		else
+			return 0 ; // didn't match any lightnode, something went wrong.
+
+
+		// scan through all the lamps, finding the ones that touch the same zone as this triangle and that have the same lightnode number
+		for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++)
+		{
+			// skip if the lightnode doesn't match
+			if(m_pLamp[nLamp].LightNode!=nLightNode)
+				continue ;
+
+
+			/*
+			// lightnode matches, check if lamp touches the same zone (lamps can touch multiple zones so we have to check them all)
+			nZoneMatch=0 ;
+			nMaxLampZone=m_pLamp[nLamp].Zone[MAX_ZONEPERLIGHT] ;
+			for(nLampZone=0 ; nLampZone<nMaxLampZone ; nLampZone++)
+			{
+				if(m_pLamp[nLamp].Zone[nLampZone]==nZone)
+				{
+					nZoneMatch=1 ;
+					break ;
+				}
+			}
+			
+			
+			// if the zone didn't match, continue
+			if(!nZoneMatch) continue ;
+
+			*/
+
+
+
+			// check if all three vertices of this triangle fall within the bounds of this lamp
+			if(
+						// first vert
+						(m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[0]>=m_pLamp[nLamp].Min[0])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[0]<=m_pLamp[nLamp].Max[0])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[1]>=m_pLamp[nLamp].Min[1])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[1]<=m_pLamp[nLamp].Max[1])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[2]>=m_pLamp[nLamp].Min[2])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].position[2]<=m_pLamp[nLamp].Max[2])	
+					&&
+						// second vert
+						(m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[0]>=m_pLamp[nLamp].Min[0])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[0]<=m_pLamp[nLamp].Max[0])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[1]>=m_pLamp[nLamp].Min[1])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[1]<=m_pLamp[nLamp].Max[1])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[2]>=m_pLamp[nLamp].Min[2])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].position[2]<=m_pLamp[nLamp].Max[2])	
+					&&
+						// third vert
+						(m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[0]>=m_pLamp[nLamp].Min[0])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[0]<=m_pLamp[nLamp].Max[0])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[1]>=m_pLamp[nLamp].Min[1])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[1]<=m_pLamp[nLamp].Max[1])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[2]>=m_pLamp[nLamp].Min[2])
+					&&(m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].position[2]<=m_pLamp[nLamp].Max[2])	
+	
+					)
+			{
+
+
+				m_pTriangle[nTriangle].Texture=m_pLamp[nLamp].Texture ;
+				m_pTriangle[nTriangle].Lamp=nLamp ;
+
+				flCentreX =		m_pLamp[nLamp].Position[0] ;
+				flCentreY =		m_pLamp[nLamp].Position[1] ;
+				flCentreZ =		m_pLamp[nLamp].Position[2] ;
+				flColR =			m_pLamp[nLamp].Colour[0]*255.0f ;
+				flColG =			m_pLamp[nLamp].Colour[1]*255.0f ;
+				flColB =			m_pLamp[nLamp].Colour[2]*255.0f ;
+				flBrightness=	m_pLamp[nLamp].Brightness ; 
+
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].texcoord[0][0]=flCentreX ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].texcoord[0][1]=flCentreY ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].texcoord[1][0]=flCentreZ ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].texcoord[1][1]=flBrightness ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].color[0]=(unsigned char)flColR ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].color[1]=(unsigned char)flColG ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[0]  ].color[2]=(unsigned char)flColB ;
+
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].texcoord[0][0]=flCentreX ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].texcoord[0][1]=flCentreY ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].texcoord[1][0]=flCentreZ ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].texcoord[1][1]=flBrightness ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].color[0]=(unsigned char)flColR ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].color[1]=(unsigned char)flColG ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[1]  ].color[2]=(unsigned char)flColB ;
+
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].texcoord[0][0]=flCentreX ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].texcoord[0][1]=flCentreY ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].texcoord[1][0]=flCentreZ ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].texcoord[1][1]=flBrightness ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].color[0]=(unsigned char)flColR ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].color[1]=(unsigned char)flColG ;
+				m_pVertex[  m_pTriangle[nTriangle].VIndex[2]  ].color[2]=(unsigned char)flColB ;
+
+				
+				m_pTriangle[ m_nTriangleMax ].Group=m_nGroup ;
+
+
+			}// end triangle is in bounds of lamp
+
+
+			m_nGroup++ ; // increment group number.  Every texture lamp is a group.
+
+
+		}// end for nLamp
+
+
+	}
+
+
+
+	return 1 ;
+}
+
+
+// convert lamps into boxes.  Lamps are deferred shading non-shadowing lights, and are rendered as triangles
+// The texture coords are actually the light centre point, the spot the shaders calculate as the source of the lighting, 
+// and also the brightness
+// The triangles created will remember the lamp they came from, via Triangle.Lamp
+
+int Q3Map::ConvertLampsToTriangles(void)
+{
+	float flCentreX=0.0f ;
+	float flCentreY=0.0f ;
+	float flCentreZ=0.0f ;
+
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+	float flMaxZ=0.0f ;
+
+//	float	flNormX=0.0f ;
+//	float	flNormY=0.0f ;
+//	float	flNormZ=0.0f ;
+//	float flTexU=0.0f ;
+//	float flTexV=0.0f ;
+
+	float flColR=0.0f ;
+	float flColG=0.0f ;
+	float flColB=0.0f ;
+
+	float flBrightness=0.0f ;
+
+	int nLamp=0 ;
+
+	// lower case = min, upper case = max
+	Q3BspVertex Vert_xyz ;
+	Q3BspVertex Vert_Xyz ;
+	Q3BspVertex Vert_xYz ;
+	Q3BspVertex Vert_XYz ;
+	Q3BspVertex Vert_xyZ ;
+	Q3BspVertex Vert_XyZ ;
+	Q3BspVertex Vert_xYZ ;
+	Q3BspVertex Vert_XYZ ;
+
+	int n_xyz=0 ;
+	int n_Xyz=0 ;
+	int n_xYz=0 ;
+	int n_XYz=0 ;
+	int n_xyZ=0 ;
+	int n_XyZ=0 ;
+	int n_xYZ=0 ;
+	int n_XYZ=0 ;
+
+	int nFirstVertex=0 ;
+
+	triangle_t Triangle ;
+	ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ;
+	
+	for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++)
+	{
+		if(m_pLamp[nLamp].LightNode>-1) continue ; // lamps that are lightnodes don't add their own triangles.  They just exist as information for TexLamps.
+
+
+		flCentreX =		m_pLamp[nLamp].Position[0] ;
+		flCentreY =		m_pLamp[nLamp].Position[1] ;
+		flCentreZ =		m_pLamp[nLamp].Position[2] ;
+
+		flMinX =			m_pLamp[nLamp].Min[0] ;
+		flMinY =			m_pLamp[nLamp].Min[1] ;
+		flMinZ =			m_pLamp[nLamp].Min[2] ;
+
+		flMaxX =			m_pLamp[nLamp].Max[0] ;
+		flMaxY =			m_pLamp[nLamp].Max[1] ;
+		flMaxZ =			m_pLamp[nLamp].Max[2] ;
+
+		flColR =			m_pLamp[nLamp].Colour[0]*255.0f ;
+		flColG =			m_pLamp[nLamp].Colour[1]*255.0f ;
+		flColB =			m_pLamp[nLamp].Colour[2]*255.0f ;
+		
+		flBrightness=	m_pLamp[nLamp].Brightness ; 
+		
+		//////////////////////////////////////
+		// setup our 8 vertices.  Normal isn't that important, I just approximate regardless of actual box shape
+
+
+		nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles
+
+		// vertex numbers
+		n_xyz=nFirstVertex+0 ;
+		n_Xyz=nFirstVertex+1 ;
+		n_xYz=nFirstVertex+2 ;
+		n_XYz=nFirstVertex+3 ;
+		n_xyZ=nFirstVertex+4 ;
+		n_XyZ=nFirstVertex+5 ;
+		n_xYZ=nFirstVertex+6 ;
+		n_XYZ=nFirstVertex+7 ;
+
+
+		Vert_xyz.position[0]=flMinX ;
+		Vert_xyz.position[1]=flMinY ;
+		Vert_xyz.position[2]=flMinZ ;
+		Vert_xyz.normal[0]=-0.5773502691896 ;
+		Vert_xyz.normal[1]=-0.5773502691896 ;
+		Vert_xyz.normal[2]=-0.5773502691896 ;
+		Vert_xyz.texcoord[0][0]=flCentreX ;
+		Vert_xyz.texcoord[0][1]=flCentreY ;
+		Vert_xyz.texcoord[1][0]=flCentreZ ;
+		Vert_xyz.texcoord[1][1]=flBrightness ;
+		Vert_xyz.color[0]=(unsigned char)flColR ;
+		Vert_xyz.color[1]=(unsigned char)flColG ;
+		Vert_xyz.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_xyz)) return 0 ;
+			
+
+		Vert_Xyz.position[0]=flMaxX ;
+		Vert_Xyz.position[1]=flMinY ;
+		Vert_Xyz.position[2]=flMinZ ;
+		Vert_Xyz.normal[0]= 0.5773502691896 ;
+		Vert_Xyz.normal[1]=-0.5773502691896 ;
+		Vert_Xyz.normal[2]=-0.5773502691896 ;
+		Vert_Xyz.texcoord[0][0]=flCentreX ;
+		Vert_Xyz.texcoord[0][1]=flCentreY ;
+		Vert_Xyz.texcoord[1][0]=flCentreZ ;
+		Vert_Xyz.texcoord[1][1]=flBrightness ;
+		Vert_Xyz.color[0]=(unsigned char)flColR ;
+		Vert_Xyz.color[1]=(unsigned char)flColG ;
+		Vert_Xyz.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_Xyz)) return 0 ;
+
+		Vert_xYz.position[0]=flMinX ;
+		Vert_xYz.position[1]=flMaxY ;
+		Vert_xYz.position[2]=flMinZ ;
+		Vert_xYz.normal[0]=-0.5773502691896 ;
+		Vert_xYz.normal[1]= 0.5773502691896 ;
+		Vert_xYz.normal[2]=-0.5773502691896 ;
+		Vert_xYz.texcoord[0][0]=flCentreX ;
+		Vert_xYz.texcoord[0][1]=flCentreY ;
+		Vert_xYz.texcoord[1][0]=flCentreZ ;
+		Vert_xYz.texcoord[1][1]=flBrightness ;
+		Vert_xYz.color[0]=(unsigned char)flColR ;
+		Vert_xYz.color[1]=(unsigned char)flColG ;
+		Vert_xYz.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_xYz)) return 0 ;
+
+		Vert_XYz.position[0]=flMaxX ;
+		Vert_XYz.position[1]=flMaxY ;
+		Vert_XYz.position[2]=flMinZ ;
+		Vert_XYz.normal[0]= 0.5773502691896 ;
+		Vert_XYz.normal[1]= 0.5773502691896 ;
+		Vert_XYz.normal[2]=-0.5773502691896 ;
+		Vert_XYz.texcoord[0][0]=flCentreX ;
+		Vert_XYz.texcoord[0][1]=flCentreY ;
+		Vert_XYz.texcoord[1][0]=flCentreZ ;
+		Vert_XYz.texcoord[1][1]=flBrightness ;
+		Vert_XYz.color[0]=(unsigned char)flColR ;
+		Vert_XYz.color[1]=(unsigned char)flColG ;
+		Vert_XYz.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_XYz)) return 0 ;
+
+		//////////////////////////////////////
+
+		Vert_xyZ.position[0]=flMinX ;
+		Vert_xyZ.position[1]=flMinY ;
+		Vert_xyZ.position[2]=flMaxZ ;
+		Vert_xyZ.normal[0]=-0.5773502691896 ;
+		Vert_xyZ.normal[1]=-0.5773502691896 ;
+		Vert_xyZ.normal[2]= 0.5773502691896 ;
+		Vert_xyZ.texcoord[0][0]=flCentreX ;
+		Vert_xyZ.texcoord[0][1]=flCentreY ;
+		Vert_xyZ.texcoord[1][0]=flCentreZ ;
+		Vert_xyZ.texcoord[1][1]=flBrightness ;
+		Vert_xyZ.color[0]=(unsigned char)flColR ;
+		Vert_xyZ.color[1]=(unsigned char)flColG ;
+		Vert_xyZ.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_xyZ)) return 0 ;
+
+		Vert_XyZ.position[0]=flMaxX ;
+		Vert_XyZ.position[1]=flMinY ;
+		Vert_XyZ.position[2]=flMaxZ ;
+		Vert_XyZ.normal[0]= 0.5773502691896 ;
+		Vert_XyZ.normal[1]=-0.5773502691896 ;
+		Vert_XyZ.normal[2]= 0.5773502691896 ;
+		Vert_XyZ.texcoord[0][0]=flCentreX ;
+		Vert_XyZ.texcoord[0][1]=flCentreY ;
+		Vert_XyZ.texcoord[1][0]=flCentreZ ;
+		Vert_XyZ.texcoord[1][1]=flBrightness ;
+		Vert_XyZ.color[0]=(unsigned char)flColR ;
+		Vert_XyZ.color[1]=(unsigned char)flColG ;
+		Vert_XyZ.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_XyZ)) return 0 ;
+
+		Vert_xYZ.position[0]=flMinX ;
+		Vert_xYZ.position[1]=flMaxY ;
+		Vert_xYZ.position[2]=flMaxZ ;
+		Vert_xYZ.normal[0]=-0.5773502691896 ;
+		Vert_xYZ.normal[1]= 0.5773502691896 ;
+		Vert_xYZ.normal[2]= 0.5773502691896 ;
+		Vert_xYZ.texcoord[0][0]=flCentreX ;
+		Vert_xYZ.texcoord[0][1]=flCentreY ;
+		Vert_xYZ.texcoord[1][0]=flCentreZ ;
+		Vert_xYZ.texcoord[1][1]=flBrightness ;
+		Vert_xYZ.color[0]=(unsigned char)flColR ;
+		Vert_xYZ.color[1]=(unsigned char)flColG ;
+		Vert_xYZ.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_xYZ)) return 0 ;
+
+		Vert_XYZ.position[0]=flMaxX ;
+		Vert_XYZ.position[1]=flMaxY ;
+		Vert_XYZ.position[2]=flMaxZ ;
+		Vert_XYZ.normal[0]= 0.5773502691896 ;
+		Vert_XYZ.normal[1]= 0.5773502691896 ;
+		Vert_XYZ.normal[2]= 0.5773502691896 ;
+		Vert_XYZ.texcoord[0][0]=flCentreX ;
+		Vert_XYZ.texcoord[0][1]=flCentreY ;
+		Vert_XYZ.texcoord[1][0]=flCentreZ ;
+		Vert_XYZ.texcoord[1][1]=flBrightness ;
+		Vert_XYZ.color[0]=(unsigned char)flColR ;
+		Vert_XYZ.color[1]=(unsigned char)flColG ;
+		Vert_XYZ.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_XYZ)) return 0 ;
+
+		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+		Triangle.Texture=m_pLamp[nLamp].Texture ;
+		Triangle.Lamp=nLamp ;
+		Triangle.Group=m_nGroup ;
+
+		/////////////////////////////////////
+
+		Triangle.VIndex[2]=n_xyz ;
+		Triangle.VIndex[1]=n_xyZ ;
+		Triangle.VIndex[0]=n_xYZ ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[2]=n_xYZ ;
+		Triangle.VIndex[1]=n_xYz ;
+		Triangle.VIndex[0]=n_xyz ;
+		if(!AddTriangle(Triangle)) return 0 ;
+	
+		/////////////////////////////////////
+
+		Triangle.VIndex[0]=n_Xyz ;
+		Triangle.VIndex[1]=n_XyZ ;
+		Triangle.VIndex[2]=n_XYZ ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_XYZ ;
+		Triangle.VIndex[1]=n_XYz ;
+		Triangle.VIndex[2]=n_Xyz ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		/////////////////////////////////////
+
+		Triangle.VIndex[2]=n_xyz ;
+		Triangle.VIndex[1]=n_xYz ;
+		Triangle.VIndex[0]=n_XYz ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[2]=n_XYz ;
+		Triangle.VIndex[1]=n_Xyz ;
+		Triangle.VIndex[0]=n_xyz ;
+		if(!AddTriangle(Triangle)) return 0 ;
+	
+		/////////////////////////////////////
+
+		Triangle.VIndex[0]=n_xyZ ;
+		Triangle.VIndex[1]=n_xYZ ;
+		Triangle.VIndex[2]=n_XYZ ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_XYZ ;
+		Triangle.VIndex[1]=n_XyZ ;
+		Triangle.VIndex[2]=n_xyZ ;
+		if(!AddTriangle(Triangle)) return 0 ;
+	
+		/////////////////////////////////////
+
+		Triangle.VIndex[0]=n_xyz ;
+		Triangle.VIndex[1]=n_xyZ ;
+		Triangle.VIndex[2]=n_XyZ ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_XyZ ;
+		Triangle.VIndex[1]=n_Xyz ;
+		Triangle.VIndex[2]=n_xyz ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		/////////////////////////////////////
+
+		Triangle.VIndex[2]=n_xYz ;
+		Triangle.VIndex[1]=n_xYZ ;
+		Triangle.VIndex[0]=n_XYZ ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[2]=n_XYZ ;
+		Triangle.VIndex[1]=n_XYz ;
+		Triangle.VIndex[0]=n_xYz ;
+		if(!AddTriangle(Triangle)) return 0 ;
+	
+		m_nGroup++ ; // increment group once for every lamp
+	}
+	
+
+
+	return 1 ;
+}
+
+
+int Q3Map::ConvertLampsToGlowTriangles(void)
+{
+	float flCentreX=0.0f ;
+	float flCentreY=0.0f ;
+	float flCentreZ=0.0f ;
+
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+	float flMaxZ=0.0f ;
+
+//	float	flNormX=0.0f ;
+//	float	flNormY=0.0f ;
+//	float	flNormZ=0.0f ;
+//	float flTexU=0.0f ;
+//	float flTexV=0.0f ;
+
+	float flColR=0.0f ;
+	float flColG=0.0f ;
+	float flColB=0.0f ;
+
+	float flBrightness=0.0f ;
+
+	int nLamp=0 ;
+
+
+	Q3BspVertex Vert_L ;
+	Q3BspVertex Vert_R ;
+	Q3BspVertex Vert_F ;
+	Q3BspVertex Vert_B ;
+	Q3BspVertex Vert_U ;
+	Q3BspVertex Vert_D ;
+
+
+	int n_L=0 ;
+	int n_R=0 ;
+	int n_F=0 ;
+	int n_B=0 ;
+	int n_U=0 ;
+	int n_D=0 ;
+	
+	int nFirstVertex=0 ;
+
+	float flBaseGlowSize=0.15f ;//0.2f;//0.001f ;
+	float flGlowSize=0.0f ;
+
+
+
+	triangle_t Triangle ;
+	ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ;
+	
+	for(nLamp=0 ; nLamp<m_nLampMax ; nLamp++)
+	{
+
+		flGlowSize=flBaseGlowSize*m_pLamp[nLamp].Brightness ;
+
+		flCentreX =		m_pLamp[nLamp].Position[0] ;
+		flCentreY =		m_pLamp[nLamp].Position[1] ;
+		flCentreZ =		m_pLamp[nLamp].Position[2] ;
+
+		flMinX =			flCentreX-flGlowSize ;
+		flMinY =			flCentreY-flGlowSize ;
+		flMinZ =			flCentreZ-flGlowSize ;
+
+		flMaxX =			flCentreX+flGlowSize ;
+		flMaxY =			flCentreY+flGlowSize ;
+		flMaxZ =			flCentreZ+flGlowSize ;
+
+		flColR =			m_pLamp[nLamp].Colour[0]*255.0f ;
+		flColG =			m_pLamp[nLamp].Colour[1]*255.0f ;
+		flColB =			m_pLamp[nLamp].Colour[2]*255.0f ;
+		
+		flBrightness=	m_pLamp[nLamp].Brightness*4.0f ; 
+		
+		//////////////////////////////////////
+		// setup our 8 vertices.  Normal isn't that important, I just approximate regardless of actual box shape
+
+
+		nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles
+
+		// vertex numbers
+		n_L=nFirstVertex+0 ;
+		n_R=nFirstVertex+1 ;
+		n_F=nFirstVertex+2 ;
+		n_B=nFirstVertex+3 ;
+		n_U=nFirstVertex+4 ;
+		n_D=nFirstVertex+5 ;
+
+
+
+		Vert_L.position[0]=flMinX ;
+		Vert_L.position[1]=flCentreY ;
+		Vert_L.position[2]=flCentreZ ;
+		Vert_L.normal[0]=-1.0 ;
+		Vert_L.normal[1]=0.0 ;
+		Vert_L.normal[2]=0.0 ;
+		Vert_L.texcoord[0][0]=flCentreX ;
+		Vert_L.texcoord[0][1]=flCentreY ;
+		Vert_L.texcoord[1][0]=flCentreZ ;
+		Vert_L.texcoord[1][1]=flBrightness ;
+		Vert_L.color[0]=(unsigned char)flColR ;
+		Vert_L.color[1]=(unsigned char)flColG ;
+		Vert_L.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_L)) return 0 ;
+
+		Vert_R.position[0]=flMaxX ;
+		Vert_R.position[1]=flCentreY ;
+		Vert_R.position[2]=flCentreZ ;
+		Vert_R.normal[0]=1.0 ;
+		Vert_R.normal[1]=0.0 ;
+		Vert_R.normal[2]=0.0 ;
+		Vert_R.texcoord[0][0]=flCentreX ;
+		Vert_R.texcoord[0][1]=flCentreY ;
+		Vert_R.texcoord[1][0]=flCentreZ ;
+		Vert_R.texcoord[1][1]=flBrightness ;
+		Vert_R.color[0]=(unsigned char)flColR ;
+		Vert_R.color[1]=(unsigned char)flColG ;
+		Vert_R.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_R)) return 0 ;
+
+		Vert_F.position[0]=flCentreX ;
+		Vert_F.position[1]=flCentreY ;
+		Vert_F.position[2]=flMinZ ;
+		Vert_F.normal[0]=0.0 ;
+		Vert_F.normal[1]=0.0 ;
+		Vert_F.normal[2]=-1.0 ;
+		Vert_F.texcoord[0][0]=flCentreX ;
+		Vert_F.texcoord[0][1]=flCentreY ;
+		Vert_F.texcoord[1][0]=flCentreZ ;
+		Vert_F.texcoord[1][1]=flBrightness ;
+		Vert_F.color[0]=(unsigned char)flColR ;
+		Vert_F.color[1]=(unsigned char)flColG ;
+		Vert_F.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_F)) return 0 ;
+		
+		Vert_B.position[0]=flCentreX ;
+		Vert_B.position[1]=flCentreY ;
+		Vert_B.position[2]=flMaxZ ;
+		Vert_B.normal[0]=0.0 ;
+		Vert_B.normal[1]=0.0 ;
+		Vert_B.normal[2]=1.0 ;
+		Vert_B.texcoord[0][0]=flCentreX ;
+		Vert_B.texcoord[0][1]=flCentreY ;
+		Vert_B.texcoord[1][0]=flCentreZ ;
+		Vert_B.texcoord[1][1]=flBrightness ;
+		Vert_B.color[0]=(unsigned char)flColR ;
+		Vert_B.color[1]=(unsigned char)flColG ;
+		Vert_B.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_B)) return 0 ;
+
+		Vert_U.position[0]=flCentreX ;
+		Vert_U.position[1]=flMaxY ;
+		Vert_U.position[2]=flCentreZ ;
+		Vert_U.normal[0]=0.0 ;
+		Vert_U.normal[1]=1.0 ;
+		Vert_U.normal[2]=0.0 ;
+		Vert_U.texcoord[0][0]=flCentreX ;
+		Vert_U.texcoord[0][1]=flCentreY ;
+		Vert_U.texcoord[1][0]=flCentreZ ;
+		Vert_U.texcoord[1][1]=flBrightness ;
+		Vert_U.color[0]=(unsigned char)flColR ;
+		Vert_U.color[1]=(unsigned char)flColG ;
+		Vert_U.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_U)) return 0 ;
+
+		Vert_D.position[0]=flCentreX ;
+		Vert_D.position[1]=flMinY ;
+		Vert_D.position[2]=flCentreZ ;
+		Vert_D.normal[0]=0.0 ;
+		Vert_D.normal[1]=-1.0 ;
+		Vert_D.normal[2]=0.0 ;
+		Vert_D.texcoord[0][0]=flCentreX ;
+		Vert_D.texcoord[0][1]=flCentreY ;
+		Vert_D.texcoord[1][0]=flCentreZ ;
+		Vert_D.texcoord[1][1]=flBrightness ;
+		Vert_D.color[0]=(unsigned char)flColR ;
+		Vert_D.color[1]=(unsigned char)flColG ;
+		Vert_D.color[2]=(unsigned char)flColB ;
+		if(!AddVertex(Vert_D)) return 0 ;
+
+		////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+		Triangle.Texture=m_nDefaultTextureIndexGlowLamp ;
+		Triangle.Lamp=-1 ;
+		Triangle.Group=m_nGroup ;
+
+		/////////////////////////////////////
+
+		Triangle.VIndex[0]=n_U ;
+		Triangle.VIndex[1]=n_L ;
+		Triangle.VIndex[2]=n_F ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_U ;
+		Triangle.VIndex[1]=n_F ;
+		Triangle.VIndex[2]=n_R ;
+		if(!AddTriangle(Triangle)) return 0 ;
+	
+		Triangle.VIndex[0]=n_U ;
+		Triangle.VIndex[1]=n_R ;
+		Triangle.VIndex[2]=n_B ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_U ;
+		Triangle.VIndex[1]=n_B ;
+		Triangle.VIndex[2]=n_L ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		//////////////////////////////////////
+
+		Triangle.VIndex[2]=n_D ;
+		Triangle.VIndex[1]=n_L ;
+		Triangle.VIndex[0]=n_F ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[2]=n_D ;
+		Triangle.VIndex[1]=n_F ;
+		Triangle.VIndex[0]=n_R ;
+		if(!AddTriangle(Triangle)) return 0 ;
+	
+		Triangle.VIndex[2]=n_D ;
+		Triangle.VIndex[1]=n_R ;
+		Triangle.VIndex[0]=n_B ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[2]=n_D ;
+		Triangle.VIndex[1]=n_B ;
+		Triangle.VIndex[0]=n_L ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		m_nGroup++ ; // increment group once for each glow
+		
+	}
+	
+
+
+	return 1 ;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+int Q3Map::ConvertLightsToGlowTriangles(void)
+{
+	float flCentreX=0.0f ;
+	float flCentreY=0.0f ;
+	float flCentreZ=0.0f ;
+
+	float flMinX=0.0f ;
+	float flMinY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxX=0.0f ;
+	float flMaxY=0.0f ;
+	float flMaxZ=0.0f ;
+
+//	float	flNormX=0.0f ;
+//	float	flNormY=0.0f ;
+//	float	flNormZ=0.0f ;
+//	float flTexU=0.0f ;
+//	float flTexV=0.0f ;
+
+	float flColR=0.0f ;
+	float flColG=0.0f ;
+	float flColB=0.0f ;
+
+	float flBrightness=0.0f ;
+
+	int nLight=0 ;
+
+	Q3BspVertex Vert_Or ;
+	Q3BspVertex Vert_A0 ;
+	Q3BspVertex Vert_A1 ;
+	Q3BspVertex Vert_B0 ;
+	Q3BspVertex Vert_B1 ;
+
+
+	int n_Or=0 ;
+	int n_A0=0 ;
+	int n_A1=0 ;
+	int n_B0=0 ;
+	int n_B1=0 ;
+	
+	int nFirstVertex=0 ;
+
+	float flBaseGlowSize=0.2f ;//0.001f ;
+	float flGlowSize=0.0f ;
+
+//	char chMessage[1024] ;
+
+
+
+	triangle_t Triangle ;
+	ZeroMemory((void*)&Triangle, sizeof(triangle_t)) ;
+	
+	for(nLight=0 ; nLight<m_nLightMax ; nLight++)
+	//for(nLight=0 ; nLight<1 ; nLight++)
+	{
+		//if(m_pLight[nLight].LightNode>-1) continue ; // Lights that are lightnodes don't add their own triangles.  They just exist as information for TexLights.
+
+		flGlowSize=flBaseGlowSize*m_pLight[nLight].Brightness ;
+
+		flCentreX =		m_pLight[nLight].Position[0] ;
+		flCentreY =		m_pLight[nLight].Position[1] ;
+		flCentreZ =		m_pLight[nLight].Position[2] ;
+
+		flMinX =			flCentreX-flGlowSize ;
+		flMinY =			flCentreY-flGlowSize ;
+		flMinZ =			flCentreZ-flGlowSize ;
+
+		flMaxX =			flCentreX+flGlowSize ;
+		flMaxY =			flCentreY+flGlowSize ;
+		flMaxZ =			flCentreZ+flGlowSize ;
+
+		flColR =			m_pLight[nLight].Colour[0]*255.0f ;
+		flColG =			m_pLight[nLight].Colour[1]*255.0f ;
+		flColB =			m_pLight[nLight].Colour[2]*255.0f ;
+		
+		flBrightness=	m_pLight[nLight].Brightness * 0.75 ;//*2.0 ; 
+		
+		//////////////////////////////////////
+		// setup our 5 vertices.
+
+
+		nFirstVertex=m_nVertexMax ; // we need to remember which vertex is which for defining the triangles
+
+		// vertex numbers
+		n_Or=nFirstVertex+0 ;
+		n_A0=nFirstVertex+1 ;
+		n_A1=nFirstVertex+2 ;
+		n_B0=nFirstVertex+3 ;
+		n_B1=nFirstVertex+4 ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+		
+	
+	float flHALFPI =	1.5707963 ;
+	float flTWOPI =		6.2831853 ;
+	float flPI =			3.1415926 ;
+	float flAngle=(m_pLight[nLight].Angle/360.0f*flTWOPI)/2.0 ;
+	float flCutoff=32.0f ;//m_pLight[nLight].Brightness ;
+	
+	Q3BspVertex color ;
+
+	Q3BspVertex NormalVert ;
+	SetVertex(&NormalVert, m_pLight[nLight].Direction[0], m_pLight[nLight].Direction[1], m_pLight[nLight].Direction[2]) ;
+	NormalVert=GetNormalised(&NormalVert) ;
+
+	Q3BspVertex normal ;
+	SetVertex(&normal, m_pLight[nLight].Direction[0]*flCutoff, m_pLight[nLight].Direction[1]*flCutoff, m_pLight[nLight].Direction[2]*flCutoff) ;
+
+	Q3BspVertex adjust=normal ;
+	VertexScale(&adjust, 0.5) ;
+
+	Q3BspVertex start ;		SetVertex(&start, flCentreX, flCentreY, flCentreZ) ;
+	Q3BspVertex end ;			SetVertex(&end, flCentreX+normal.position[0], flCentreY+normal.position[1], flCentreZ+normal.position[2]) ;
+
+	Q3BspVertex xaxis ; SetVertex(&xaxis, 1,0,0) ;
+	Q3BspVertex xaxisneg ; SetVertex(&xaxisneg, -1,0,0) ;
+	Q3BspVertex yaxis ; SetVertex(&yaxis, 0,1,0) ;
+	Q3BspVertex Origin ; SetVertex(&Origin, 0,0,0) ;
+	Q3BspVertex tangentA ;
+	Q3BspVertex tangentB ;
+	Q3BspVertex tangentStart ;
+	Q3BspVertex tangentEnd ;
+	Q3BspVertex tangentEndA0 ;
+	Q3BspVertex tangentEndA1 ;
+	Q3BspVertex tangentEndB0 ;
+	Q3BspVertex tangentEndB1 ;
+
+	Q3BspVertex tangentANorm ;
+	Q3BspVertex tangentBNorm ;
+
+	Q3BspVertex raytangent ;
+
+	Q3BspVertex ray ;
+	float theta=0.0f ;
+	float adjacent=0.0f ;
+	SetVertex(&color, 0.66, 0.66, 0.66) ;
+
+	if(flAngle<0.0001) return 0 ;
+
+	if(flAngle>flPI-0.01) // near on 180 degrees
+		flAngle=flPI-0.01 ;
+
+
+	Q3BspVertex backshift ;
+	backshift=normal ;
+	VertexScale(&backshift, 0.95) ;
+	
+
+	if( !VectorsAreEqual(&NormalVert, &xaxis) && !VectorsAreEqual(&NormalVert, &xaxisneg) )
+		tangentA=NormalizedCrossProduct(Origin, normal, xaxis) ;
+	else
+		tangentA=NormalizedCrossProduct(Origin, normal, yaxis) ;
+	
+	tangentB=NormalizedCrossProduct(Origin, normal, tangentA) ;
+
+	tangentANorm=tangentA ;
+	tangentBNorm=tangentB ;
+
+
+	
+	theta=flHALFPI-flAngle ; // angle between adjacent and hypotenuse (the normal is the "opposite" side, and we know there's a right angle)
+	adjacent=VertexDistance(&Origin, &normal)/tan(theta) ; 
+
+	//////////////////////////////////////////////////////////////////////
+	
+	Vert_Or.position[0]=end.position[0]-backshift.position[0] ;
+	Vert_Or.position[1]=end.position[1]-backshift.position[1] ;
+	Vert_Or.position[2]=end.position[2]-backshift.position[2] ;
+	Vert_Or.normal[0]= NormalVert.position[0] ;
+	Vert_Or.normal[1]= NormalVert.position[1] ;
+	Vert_Or.normal[2]= NormalVert.position[2] ;
+	Vert_Or.texcoord[0][0]=flCentreX ;
+	Vert_Or.texcoord[0][1]=flCentreY ;
+	Vert_Or.texcoord[1][0]=flCentreZ ;
+	Vert_Or.texcoord[1][1]=flBrightness ;
+	Vert_Or.color[0]=(unsigned char)flColR ;
+	Vert_Or.color[1]=(unsigned char)flColG ;
+	Vert_Or.color[2]=(unsigned char)flColB ;
+	if(!AddVertex(Vert_Or)) return 0 ;
+
+
+
+
+	//////////////////////////////////////////////////////////////////////
+
+	flColR=0.0f ;
+	flColG=0.0f ;
+	flColB=0.0f ;
+
+	tangentA=GetNormalised(&tangentA) ;
+	VertexScale(&tangentA,  adjacent) ; 
+
+	tangentStart=start ;
+	tangentEnd=VectorSubtract(&end, &tangentA) ;
+	ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+	ray=GetNormalised(&ray) ;
+	VertexScale(&ray, flCutoff) ;
+	tangentStart=start ;
+	tangentEndA0=VectorAdd(&start, &ray) ;
+
+	raytangent=VectorSubtract(&end, &tangentEndA0) ;
+	raytangent=VectorAdd(&raytangent, &adjust) ;
+	raytangent=GetNormalised(&raytangent) ;
+
+
+
+	tangentEndA0=VectorSubtract(&tangentEndA0, &backshift) ;
+	Vert_A0.position[0]=tangentEndA0.position[0] ;
+	Vert_A0.position[1]=tangentEndA0.position[1] ;
+	Vert_A0.position[2]=tangentEndA0.position[2] ;
+	Vert_A0.normal[0]= -raytangent.position[0] ;
+	Vert_A0.normal[1]= -raytangent.position[1] ;
+	Vert_A0.normal[2]= -raytangent.position[2] ;
+	Vert_A0.texcoord[0][0]=flCentreX ;
+	Vert_A0.texcoord[0][1]=flCentreY ;
+	Vert_A0.texcoord[1][0]=flCentreZ ;
+	Vert_A0.texcoord[1][1]=flBrightness ;
+	Vert_A0.color[0]=(unsigned char)flColR ;//abs(Vert_A0.normal[0])*255 ;//0.0f ;
+	Vert_A0.color[1]=(unsigned char)flColG ;//abs(Vert_A0.normal[1])*255 ;//0.0f ;
+	Vert_A0.color[2]=(unsigned char)flColB ;//abs(Vert_A0.normal[2])*255 ;//0.0f ;
+	if(!AddVertex(Vert_A0)) return 0 ;
+
+
+	tangentStart=start ;
+	tangentEnd=VectorAdd(&end, &tangentA) ;
+	ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+	ray=GetNormalised(&ray) ;
+	VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ;
+	tangentStart=start ;
+	tangentEndA1=VectorAdd(&start, &ray) ;
+
+	raytangent=VectorSubtract(&end, &tangentEndA1) ;
+	raytangent=VectorAdd(&raytangent, &adjust) ;
+	raytangent=GetNormalised(&raytangent) ;
+
+	tangentEndA1=VectorSubtract(&tangentEndA1, &backshift) ;
+	Vert_A1.position[0]=tangentEndA1.position[0] ;
+	Vert_A1.position[1]=tangentEndA1.position[1] ;
+	Vert_A1.position[2]=tangentEndA1.position[2] ;
+	Vert_A1.normal[0]= -raytangent.position[0] ;
+	Vert_A1.normal[1]= -raytangent.position[1] ;
+	Vert_A1.normal[2]= -raytangent.position[2] ;
+	Vert_A1.texcoord[0][0]=flCentreX ;
+	Vert_A1.texcoord[0][1]=flCentreY ;
+	Vert_A1.texcoord[1][0]=flCentreZ ;
+	Vert_A1.texcoord[1][1]=flBrightness ;
+	Vert_A1.color[0]=(unsigned char)flColR ;//abs(Vert_A1.normal[0])*255 ;//0.0f ;
+	Vert_A1.color[1]=(unsigned char)flColG ;//abs(Vert_A1.normal[1])*255 ;//0.0f ;
+	Vert_A1.color[2]=(unsigned char)flColB ;//abs(Vert_A1.normal[2])*255 ;//0.0f ;
+	if(!AddVertex(Vert_A1)) return 0 ;
+
+	//////////////////////////////////////////////////////////////////////
+
+	tangentB=GetNormalised(&tangentB) ;
+	VertexScale(&tangentB, adjacent) ; //tangentB.getScaledBy(adjacent) ;
+
+	tangentStart=start ;
+	tangentEnd=VectorSubtract(&end, &tangentB) ;
+	ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+	ray=GetNormalised(&ray) ;
+	VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ;
+	tangentStart=start ;
+	tangentEndB0=VectorAdd(&start, &ray) ;
+
+	raytangent=VectorSubtract(&end, &tangentEndB0) ;
+	raytangent=VectorAdd(&raytangent, &adjust) ;
+	raytangent=GetNormalised(&raytangent) ;
+
+	tangentEndB0=VectorSubtract(&tangentEndB0, &backshift) ;
+	Vert_B0.position[0]=tangentEndB0.position[0] ;
+	Vert_B0.position[1]=tangentEndB0.position[1] ;
+	Vert_B0.position[2]=tangentEndB0.position[2] ;
+	Vert_B0.normal[0]= -raytangent.position[0] ;
+	Vert_B0.normal[1]= -raytangent.position[1] ;
+	Vert_B0.normal[2]= -raytangent.position[2] ;
+	Vert_B0.texcoord[0][0]=flCentreX ;
+	Vert_B0.texcoord[0][1]=flCentreY ;
+	Vert_B0.texcoord[1][0]=flCentreZ ;
+	Vert_B0.texcoord[1][1]=flBrightness ;
+	Vert_B0.color[0]=(unsigned char)flColR ;//abs(Vert_B0.normal[0])*255 ;//0.0f ;
+	Vert_B0.color[1]=(unsigned char)flColG ;//abs(Vert_B0.normal[1])*255 ;//0.0f ;
+	Vert_B0.color[2]=(unsigned char)flColB ;//abs(Vert_B0.normal[2])*255 ;//0.0f ;
+	if(!AddVertex(Vert_B0)) return 0 ;
+
+	tangentStart=start ;
+	tangentEnd=VectorAdd(&end, &tangentB) ;
+	ray=VectorSubtract(&tangentEnd, &tangentStart) ;
+	ray=GetNormalised(&ray) ;
+	VertexScale(&ray, flCutoff) ; //ray.getScaledBy(cutoff) ;
+	tangentStart=start ;
+	tangentEndB1=VectorAdd(&start, &ray) ;
+
+	raytangent=VectorSubtract(&end, &tangentEndB1) ;
+	raytangent=VectorAdd(&raytangent, &adjust) ;
+	raytangent=GetNormalised(&raytangent) ;
+
+	tangentEndB1=VectorSubtract(&tangentEndB1, &backshift) ;
+	Vert_B1.position[0]=tangentEndB1.position[0] ;
+	Vert_B1.position[1]=tangentEndB1.position[1] ;
+	Vert_B1.position[2]=tangentEndB1.position[2] ;
+	Vert_B1.normal[0]= -raytangent.position[0] ;
+	Vert_B1.normal[1]= -raytangent.position[1] ;
+	Vert_B1.normal[2]= -raytangent.position[2] ;
+	Vert_B1.texcoord[0][0]=flCentreX ;
+	Vert_B1.texcoord[0][1]=flCentreY ;
+	Vert_B1.texcoord[1][0]=flCentreZ ;
+	Vert_B1.texcoord[1][1]=flBrightness ;
+	Vert_B1.color[0]=(unsigned char)flColR ;//abs(Vert_B1.normal[0])*255 ;//0.0f ;
+	Vert_B1.color[1]=(unsigned char)flColG ;//abs(Vert_B1.normal[1])*255 ;//0.0f ;
+	Vert_B1.color[2]=(unsigned char)flColB ;//abs(Vert_B1.normal[2])*255 ;//0.0f ;
+	if(!AddVertex(Vert_B1)) return 0 ;
+
+	/////////////////////////////////////////////////////////////////////
+
+
+
+
+	// the four verts are position correctly to make the large end of a cone (or rather, pyramid) that would be consistent
+	// with the angle and their distance from the origin.  However we cheat and move them back on top of the origin
+	// so that map lights come out looking better.
+	
+	/*
+	SetVertex(&normal, m_pLight[nLight].Direction[0]*flCutoff, m_pLight[nLight].Direction[1]*flCutoff, m_pLight[nLight].Direction[2]*flCutoff) ;
+
+	tangentEndA0=VectorSubtract(&tangentEndA0, &normal) ;
+	Vert_A0.position[0]=tangentEndA0.position[0] ;
+	Vert_A0.position[1]=tangentEndA0.position[1] ;
+	Vert_A0.position[2]=tangentEndA0.position[2] ;
+
+	tangentEndA1=VectorSubtract(&tangentEndA1, &normal) ;
+	Vert_A1.position[0]=tangentEndA1.position[0] ;
+	Vert_A1.position[1]=tangentEndA1.position[1] ;
+	Vert_A1.position[2]=tangentEndA1.position[2] ;
+
+	tangentEndB0=VectorSubtract(&tangentEndB0, &normal) ;
+	Vert_A0.position[0]=tangentEndB0.position[0] ;
+	Vert_A0.position[1]=tangentEndB0.position[1] ;
+	Vert_A0.position[2]=tangentEndB0.position[2] ;
+
+	tangentEndB1=VectorSubtract(&tangentEndB1, &normal) ;
+	Vert_A1.position[0]=tangentEndB1.position[0] ;
+	Vert_A1.position[1]=tangentEndB1.position[1] ;
+	Vert_A1.position[2]=tangentEndB1.position[2] ;
+	*/
+
+
+	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+		Triangle.Texture=m_nDefaultTextureIndexGlowLight ;
+		Triangle.Lamp=-1 ;
+		Triangle.Group=m_nGroup ;
+
+		/////////////////////////////////////
+
+		Triangle.VIndex[0]=n_Or ;
+		Triangle.VIndex[2]=n_A0 ;
+		Triangle.VIndex[1]=n_B1 ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_Or ;
+		Triangle.VIndex[2]=n_B1 ;
+		Triangle.VIndex[1]=n_A1 ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		Triangle.VIndex[0]=n_Or ;
+		Triangle.VIndex[2]=n_A1 ;
+		Triangle.VIndex[1]=n_B0 ;
+		if(!AddTriangle(Triangle)) return 0 ;
+		
+		Triangle.VIndex[0]=n_Or ;
+		Triangle.VIndex[2]=n_B0 ;
+		Triangle.VIndex[1]=n_A0 ;
+		if(!AddTriangle(Triangle)) return 0 ;
+
+		m_nGroup++ ; // increment group once for each glow
+		
+	}
+	
+	return 1 ;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+// some vertex manipulation functions used for setting up the light disk.
+// They only work on the position, so other parts of the struct need to be setup seperately
+
+
+void Q3Map::SetVertex(Q3BspVertex *pVert, float flXPos, float flYPos, float flZPos)
+{
+	pVert->position[0]=flXPos ;
+	pVert->position[1]=flYPos ;
+	pVert->position[2]=flZPos ;
+}
+
+// this doesn't test exact equivalence, but rather within the range of an epsilon VERYSMALL
+bool Q3Map::VectorsAreEqual(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+	if( fabs(pVecA->position[0] - pVecB->position[0])>VERYSMALL ) return false ;
+	if( fabs(pVecA->position[1] - pVecB->position[1])>VERYSMALL ) return false ;
+	if( fabs(pVecA->position[2] - pVecB->position[2])>VERYSMALL ) return false ;
+
+	return true ;
+}
+
+// VertA is the origin of VertB and VertC
+Q3BspVertex Q3Map::NormalizedCrossProduct(Q3BspVertex VertA, Q3BspVertex VertB, Q3BspVertex VertC)
+{
+
+
+	Q3BspVertex Cross ;
+
+	// edge vectors
+	float flVecXA_CP = VertA.position[0] - VertB.position[0] ;
+	float flVecYA_CP = VertA.position[1] - VertB.position[1] ;
+	float flVecZA_CP = VertA.position[2] - VertB.position[2] ;
+	float flVecXB_CP = VertA.position[0] - VertC.position[0] ;
+	float flVecYB_CP = VertA.position[1] - VertC.position[1] ;
+	float flVecZB_CP = VertA.position[2] - VertC.position[2] ;
+
+	// cross product
+	float flCpx_CP = (flVecZA_CP * flVecYB_CP) - (flVecYA_CP * flVecZB_CP);
+	float flCpy_CP = (flVecXA_CP * flVecZB_CP) - (flVecZA_CP * flVecXB_CP);
+	float flCpz_CP = (flVecYA_CP * flVecXB_CP) - (flVecXA_CP * flVecYB_CP);
+
+	// Normalize 
+	float flR_CP = sqrt(flCpx_CP * flCpx_CP + flCpy_CP * flCpy_CP + flCpz_CP * flCpz_CP);
+
+	Cross.position[0] = flCpx_CP / flR_CP;
+	Cross.position[1] = flCpy_CP / flR_CP;
+	Cross.position[2] = flCpz_CP / flR_CP;
+
+	return Cross ;
+}
+
+float Q3Map::VertexDistance(Q3BspVertex* VertA, Q3BspVertex* VertB)
+{
+	float flXDis=VertA->position[0]-VertB->position[0] ;
+	float flYDis=VertA->position[1]-VertB->position[1] ;
+	float flZDis=VertA->position[2]-VertB->position[2] ;
+
+	return sqrt(flXDis*flXDis+flYDis*flYDis+flZDis*flZDis) ;
+}
+
+void Q3Map::VertexScale(Q3BspVertex* pVert, float flScale)
+{
+	pVert->position[0]*=flScale ;
+	pVert->position[1]*=flScale ;
+	pVert->position[2]*=flScale ;
+}
+
+Q3BspVertex Q3Map::GetNormalised(Q3BspVertex* pVector)
+{
+	float flLength=sqrt((pVector->position[0]*pVector->position[0])+(pVector->position[1]*pVector->position[1])+(pVector->position[2]*pVector->position[2])) ;
+
+	Q3BspVertex Vector=*pVector ;
+
+	Vector.position[0]/=flLength ;
+	Vector.position[1]/=flLength ;
+	Vector.position[2]/=flLength ;
+
+	return Vector ;
+}
+
+Q3BspVertex Q3Map::VectorAdd(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+	Q3BspVertex Vector ;
+
+	Vector.position[0]=pVecA->position[0] + pVecB->position[0] ;
+	Vector.position[1]=pVecA->position[1] + pVecB->position[1] ;
+	Vector.position[2]=pVecA->position[2] + pVecB->position[2] ;
+
+	return Vector ;
+}
+
+Q3BspVertex Q3Map::VectorSubtract(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+	Q3BspVertex Vector ;
+
+	Vector.position[0]=pVecA->position[0] - pVecB->position[0] ;
+	Vector.position[1]=pVecA->position[1] - pVecB->position[1] ;
+	Vector.position[2]=pVecA->position[2] - pVecB->position[2] ;
+
+	return Vector ;
+}
+
+Q3BspVertex Q3Map::VectorMultiply(Q3BspVertex* pVecA, Q3BspVertex* pVecB)
+{
+	Q3BspVertex Vector ;
+
+	Vector.position[0]=pVecA->position[0] * pVecB->position[0] ;
+	Vector.position[1]=pVecA->position[1] * pVecB->position[1] ;
+	Vector.position[2]=pVecA->position[2] * pVecB->position[2] ;
+
+	return Vector ;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+void Q3Map::GetTexLampTextureNumbers()
+{
+	m_nBZN_LightNode0=-1 ;
+	m_nBZN_LightNode1=-1 ;
+	m_nBZN_LightNode2=-1 ;
+	m_nBZN_LightNode3=-1 ;
+
+	int nTex=0;
+	char chTexName[1024] ;
+	int nLen=0 ;
+	int nPos=0 ;
+
+	int nMatch=0 ;
+
+	strcpy(chTexName, "textures/common/bzn_lightnode") ;
+	nLen=strlen(chTexName) ;
+
+	for(nTex=0 ; nTex<m_nTextureMax ; nTex++)
+	{
+		nMatch=1 ;
+		for(nPos=nLen-1 ; nPos>=0 ; nPos--) // faster to check backwards since lots of textures will start with "textures/common/"
+			if(m_pTexture[nTex].name[nPos]!=chTexName[nPos])
+			{
+				nMatch=0 ;
+				break ;
+			}
+
+		if(nMatch)
+		{
+			// what is the last character?
+			if(m_pTexture[nTex].name[nLen]=='0')
+				m_nBZN_LightNode0=nTex ;
+			else
+			if(m_pTexture[nTex].name[nLen]=='1')
+				m_nBZN_LightNode1=nTex ;
+			else
+			if(m_pTexture[nTex].name[nLen]=='2')
+				m_nBZN_LightNode2=nTex ;
+			else
+			if(m_pTexture[nTex].name[nLen]=='3')
+				m_nBZN_LightNode3=nTex ;
+			
+		}// end if match
+
+
+	}// end for nTex
+
+}
+
+int Q3Map::SortTrianglesIntoGroups(void)
+{
+
+
+	int nNewSize=0 ; // we will drop non-subzoned (-1 zone) triangles here, so new number of triangles may be less than old number.
+
+	ULONGLONG *pFaceOrder = new ULONGLONG[m_nTriangleMax] ;
+	if(pFaceOrder==NULL) return 0 ; // out of memory.
+
+	// temporary copy of m_pTriangles to make sorting easier
+	triangle_t *TempTriangle = new triangle_t[m_nTriangleMax];
+	if(TempTriangle==NULL) { DELETE_ARRAY( pFaceOrder ) ; return 0 ; } // out of memory
+	memcpy((void*)TempTriangle, (void*)m_pTriangle, m_nTriangleMax*sizeof(triangle_t)) ;
+
+	// create the initial face "value" by setting the most significant bits to it's criteria number
+	for (int i=0; i < m_nTriangleMax; i++)
+		if(m_pTriangle[i].Zone!=-1) // drop unsubzoned triangles
+			pFaceOrder[nNewSize++] = ( ((ULONGLONG)m_pTriangle[i].Zone)<<GROUPSORT_SUBZONE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Texture)<<GROUPSORT_GROUP_SHIFT ) + i ;
+
+	// sort the ULONGLONGs, this will order things according to our criteria
+	// sorting is based firstly on subzone, secondly on texture.  
+	// So all triangles in a subzone will be grouped together, 
+	// and within that group all triangles with the same material will be grouped together.  
+
+	qsort( (void *)pFaceOrder, nNewSize, sizeof(ULONGLONG), &Q3Map::compareGroups);
+
+	// copy the sorted faces back to the original
+	for (int i=0; i < nNewSize; i++)
+		m_pTriangle[i]=TempTriangle[ (pFaceOrder[i]&FACESORT_FACE_MASK) ] ;
+
+	// update m_nTriangleMax to show that there may now be less triangles
+	m_nTriangleMax=nNewSize ;
+
+	// clean up the memory we used
+	DELETE_ARRAY( pFaceOrder ) ;
+	DELETE_ARRAY( TempTriangle ) ;
+
+
+	// now that the triangles are sorting according to zone and group, 
+	// re-assign the group numbers per zone, from 0 to FACESORT_GROUP_LIMIT-1
+	// All non-trans triangles will be group 0, trans triangles will be 1 to FACESORT_GROUP_LIMIT-1
+
+	int nTri=0 ;
+	int nZone=-1 ;
+	int nGroup=-1 ;
+	int nNewGroup=0 ;
+
+	//char chMessage[1024] ;
+
+	for(nTri=0 ; nTri<m_nTriangleMax ; nTri++)
+	{
+		// reset the newgroup if we've got a new zone
+		if(m_pTriangle[nTri].Zone!=nZone) 
+		{
+			nZone=m_pTriangle[nTri].Zone ;
+			nGroup=-1 ;
+			nNewGroup=0 ;
+		}	
+
+		// if we have a new group, increment the newgroup number, fail if we have too many
+		if(m_pTriangle[nTri].Group!=nGroup) 
+		{
+			// if this is a trans triangle, inc the newgroup
+			if(m_pTransTexture[ m_pTriangle[nTri].Texture ])
+			{
+				nNewGroup++ ; // will always be at least 1
+				if(nNewGroup>=FACESORT_GROUP_LIMIT) return 0 ; // too many groups in a zone.
+			}
+
+			nGroup=m_pTriangle[nTri].Group ;
+		}
+
+		if(m_pTransTexture[ m_pTriangle[nTri].Texture ]==0)
+			m_pTriangle[nTri].Group=0 ;
+		else
+			m_pTriangle[nTri].Group=nNewGroup ;
+
+
+
+	}// end for tri
+
+	return 1 ;
+}
+
+
+// static function for sorting groups, required by qsort
+int Q3Map::compareGroups( const void *arg1, const void *arg2 )
+{
+	ULONGLONG FaceA= *(ULONGLONG*)arg1 ;
+	ULONGLONG FaceB= *(ULONGLONG*)arg2 ;
+
+	if(FaceA < FaceB)
+		return -1 ;
+	else
+		if(FaceA > FaceB)
+			return 1 ;
+		
+	return 0 ;
+}
+
+
+
+// sort faces so that we can batch effectively when constructing our manualobjects
+// Currently grouped according to zone and texture.
+// Triangles not in any subzone will be dropped at this stage.
+int Q3Map::SortTrianglesIntoBatches(void)
+{
+
+
+	int nNewSize=0 ; // we will drop non-subzoned (-1 zone) triangles here, so new number of triangles may be less than old number.
+
+	ULONGLONG *pFaceOrder = new ULONGLONG[m_nTriangleMax] ;
+	if(pFaceOrder==NULL) return 0 ; // out of memory.
+
+	// temporary copy of m_pTriangles to make sorting easier
+	triangle_t *TempTriangle = new triangle_t[m_nTriangleMax];
+	if(TempTriangle==NULL) { DELETE_ARRAY( pFaceOrder ) ; return 0 ; } // out of memory
+	memcpy((void*)TempTriangle, (void*)m_pTriangle, m_nTriangleMax*sizeof(triangle_t)) ;
+
+	// create the initial face "value" by setting the most significant bits to it's criteria number
+	for (int i=0; i < m_nTriangleMax; i++)
+		if(m_pTriangle[i].Zone!=-1) // drop unsubzoned triangles
+			pFaceOrder[nNewSize++] = ( ((ULONGLONG)m_pTriangle[i].Zone)<<FACESORT_SUBZONE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Texture)<<FACESORT_TEXTURE_SHIFT ) + ( ((ULONGLONG)m_pTriangle[i].Group)<<FACESORT_GROUP_SHIFT ) + i ;
+
+	// sort the ULONGLONGs, this will order things according to our criteria
+	// sorting is based firstly on subzone, secondly on texture.  
+	// So all triangles in a subzone will be grouped together, 
+	// and within that group all triangles with the same material will be grouped together.  
+
+	qsort( (void *)pFaceOrder, nNewSize, sizeof(ULONGLONG), &Q3Map::compareTriangles);
+
+	// copy the sorted faces back to the original
+	for (int i=0; i < nNewSize; i++)
+		m_pTriangle[i]=TempTriangle[ (pFaceOrder[i]&FACESORT_FACE_MASK) ] ;
+
+	// update m_nTriangleMax to show that there may now be less triangles
+	m_nTriangleMax=nNewSize ;
+
+	// clean up the memory we used
+	DELETE_ARRAY( pFaceOrder ) ;
+	DELETE_ARRAY( TempTriangle ) ;
+
+	return 1 ;
+}
+
+// static function for sorting triangles, required by qsort
+int Q3Map::compareTriangles( const void *arg1, const void *arg2 )
+{
+	ULONGLONG FaceA= *(ULONGLONG*)arg1 ;
+	ULONGLONG FaceB= *(ULONGLONG*)arg2 ;
+
+	if(FaceA < FaceB)
+		return -1 ;
+	else
+		if(FaceA > FaceB)
+			return 1 ;
+		
+	return 0 ;
+}
+
+
+
+
+// note which texture numbers correspond to textures that have transparency.
+// needed for when we work out transparency groups and related stuff
+int Q3Map::SetupTransTextures(void)
+{
+	int nMaterial=0 ;
+	int nPos=0 ;
+	char chMaterial[1024] ;
+
+	// create the memory for the transtextures
+	m_pTransTexture = new int[m_nTextureMax] ;
+	if(m_pTransTexture==NULL) return 0 ; // out of memory.
+
+	for(nMaterial=0 ; nMaterial<m_nTextureMax ; nMaterial++)
+	{
+		// copy the material name.
+		// q3 texture names are a max of 64 characters ( Q3NAMESIZE ) and may not be null terminated.  They have no extension either.
+		nPos=-1 ;
+		while((++nPos<Q3NAMESIZE) && (m_pTexture[nMaterial].name[nPos]!=' ') && (m_pTexture[nMaterial].name[nPos]!='\0'))
+			chMaterial[nPos]=m_pTexture[nMaterial].name[nPos] ;
+
+		// make sure name is null terminated
+		chMaterial[nPos]='\0' ;
+
+
+		// is the texture a type we need to flag as transparent?
+		if(strstr(chMaterial, "GEL")!=NULL)
+			m_pTransTexture[nMaterial]=1 ;
+		else
+			m_pTransTexture[nMaterial]=0 ;
+
+	}// end for nMaterial
+
+	return 1 ;
+
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+int Q3Map::AssignPortalsToZones(void)
+{
+	int nZone=0 ;
+	float flMinX=0.0f ;
+	float flMaxX=0.0f ;
+	float flMinY=0.0f ;
+	float flMaxY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxZ=0.0f ;
+	int nMaxSubZone=m_iNumSubZones ;
+	int nSubZone=0 ;
+	int nMaxPortal=m_iNumPortals ;
+	int nPortal=0 ;
+	int nIndex=0 ;
+	int nPos=0 ;
+
+
+
+	// clear the portal settings.
+	for(nZone=0 ; nZone<m_nMaxZone ; nZone++)
+		m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT]=0 ;
+
+	for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+		m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT]=0 ;
+
+
+
+	// now test each subzone against each portal to see what zones each portal contains.
+	for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+	{
+		nZone=m_pSubZones[nSubZone].Zone ;
+		flMinX=m_pSubZones[nSubZone].Min[0] ;
+		flMaxX=m_pSubZones[nSubZone].Max[0] ;
+		flMinY=m_pSubZones[nSubZone].Min[1] ;
+		flMaxY=m_pSubZones[nSubZone].Max[1] ;
+		flMinZ=m_pSubZones[nSubZone].Min[2] ;
+		flMaxZ=m_pSubZones[nSubZone].Max[2] ;
+
+		// test all the portals to see if any overlap this subzone
+		for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+		{
+
+			// if AABB overlap
+			if(
+						 (flMinX<m_pPortals[nPortal].Max[0]) && (flMaxX>m_pPortals[nPortal].Min[0])
+					&& (flMinY<m_pPortals[nPortal].Max[1]) && (flMaxY>m_pPortals[nPortal].Min[1])
+					&& (flMinZ<m_pPortals[nPortal].Max[2]) && (flMaxZ>m_pPortals[nPortal].Min[2])
+				)
+			{
+
+				// add this portal to the zone's portal list
+				nIndex=m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT] ;
+				if(nIndex<MAX_PORTALPERZONE) // only add if we aren't already maxed out.
+				{
+					// we need to check this portal isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nZoneTouchesPortal[nZone][nPos]!=nPortal)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nPortal in the list
+					{
+						m_nZoneTouchesPortal[nZone][nIndex]=nPortal ;
+						m_nZoneTouchesPortal[nZone][INDEX_PORTALCOUNT]++ ;
+					}
+				}
+
+				// add this zone to the portal's list
+				nIndex=m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
+				if(nIndex<MAX_ZONEPERPORTAL)
+				{
+					// we need to check this zone isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nPortalTouchesZone[nPortal][nPos]!=nZone)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nZone in the list
+					{
+						m_nPortalTouchesZone[nPortal][nIndex]=nZone ;
+						m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT]++ ;
+					}
+				}
+
+			}// end if portal overlaps subzone
+
+		}// end for portal
+
+	}// end for subzone
+
+	return 1 ;
+}
+
+int Q3Map::AssignLightsToZones(void)
+{
+	int nZone=0 ;
+	float flMinX=0.0f ;
+	float flMaxX=0.0f ;
+	float flMinY=0.0f ;
+	float flMaxY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxZ=0.0f ;
+	int nMaxSubZone=m_iNumSubZones ;
+	int nSubZone=0 ;
+	int nMaxLight=m_nLightMax ;
+	int nLight=0 ;
+	int nIndex=0 ;
+	int nPos=0 ;
+
+
+
+	// clear the light settings.
+	for(nZone=0 ; nZone<m_nMaxZone ; nZone++)
+		m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT]=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]=0 ;
+
+	for(nLight=0 ; nLight<nMaxLight ; nLight++)
+		m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]=0 ;
+	
+
+
+
+	// now test each subzone against each light what contains/touches what
+	for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+	{
+		nZone=m_pSubZones[nSubZone].Zone ;
+		flMinX=m_pSubZones[nSubZone].Min[0] ;
+		flMaxX=m_pSubZones[nSubZone].Max[0] ;
+		flMinY=m_pSubZones[nSubZone].Min[1] ;
+		flMaxY=m_pSubZones[nSubZone].Max[1] ;
+		flMinZ=m_pSubZones[nSubZone].Min[2] ;
+		flMaxZ=m_pSubZones[nSubZone].Max[2] ;
+
+		// test all the lights to see if any have centers inside this subzone
+		for(nLight=0 ; nLight<nMaxLight ; nLight++)
+		{
+
+			/////////////////////////////////////////////////////////////////////////////////////
+
+			// if light center is in this subzone
+			if(
+						 (m_pLight[nLight].Position[0]>=flMinX) && (m_pLight[nLight].Position[0]<=flMaxX)
+					&& (m_pLight[nLight].Position[1]>=flMinY) && (m_pLight[nLight].Position[1]<=flMaxY)
+					&& (m_pLight[nLight].Position[2]>=flMinZ) && (m_pLight[nLight].Position[2]<=flMaxZ)
+				)
+			{
+
+				// add this light to the zone's light list
+				nIndex=m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT] ;
+				if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out.
+				{
+					// we need to check this light isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nZoneContainsLightCentre[nZone][nPos]!=nLight)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nLight in the list
+					{
+						m_nZoneContainsLightCentre[nZone][nIndex]=nLight ;
+						m_nZoneContainsLightCentre[nZone][INDEX_LIGHTCOUNT]++ ;
+
+						// assign this zone as the light's centre.  We only allow one zone to be the light's centre zone,
+						// so this will get overwritten if the light is on the border.
+						m_pLight[nLight].CentreZone=nZone ;
+					}
+				}
+
+			}// end if light centre contained by subzone
+
+			/////////////////////////////////////////////////////////////////////////////////////
+
+			// if light touches subzone (we store it in ZoneTouchesSubLight for now, will overwrite later)
+			// if light AABB overlaps the zone AABB
+			if(
+						 (flMinX<m_pLight[nLight].Max[0]) && (flMaxX>m_pLight[nLight].Min[0])
+					&& (flMinY<m_pLight[nLight].Max[1]) && (flMaxY>m_pLight[nLight].Min[1])
+					&& (flMinZ<m_pLight[nLight].Max[2]) && (flMaxZ>m_pLight[nLight].Min[2])
+				)
+			{
+				// add this light to the zone's light list
+				nIndex=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
+				if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out.
+				{
+					// we need to check this light isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nZoneTouchesSubLight[nZone][nPos]!=nLight)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nPortal in the list
+					{
+						m_nZoneTouchesSubLight[nZone][nIndex]=nLight ;
+						m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]++ ;
+					}
+				}
+
+				// add this zone to the light's list
+				nIndex=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+				if(nIndex<MAX_ZONEPERLIGHT)
+				{
+					// we need to check this zone isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nLightTouchesZone[nLight][nPos]!=nZone)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nZone in the list
+					{
+						m_nLightTouchesZone[nLight][nIndex]=nZone ;
+						m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]++ ;
+					}
+				}
+
+			}// end if light touches contained by subzone
+
+			/////////////////////////////////////////////////////////////////////////////////////
+
+
+
+
+		}// end for light
+
+	}// end for subzone
+
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	//
+	// work out the sublights.  These are cut up boxes made from the light boxes, one per zone.
+	// Most lights will just become a single sublight, but multizone lights will be cut up into
+	// multiple sublights.  These are used for calculating light visibility.
+	//
+
+	m_nSubLightMax=0 ;
+	int nMaxZone=0 ;
+	int nZoneIndex=0 ;
+	int nSubLightCentre=0 ;
+	sublight_t TempSubLight ;
+	for(nLight=0 ; nLight<nMaxLight ; nLight++)
+	{
+
+		m_pLight[nLight].ZoneCount=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ; // in the light, note how many zones it touches
+
+		if((m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT]>1) && (m_nMaxMultiZoneLight<MAX_LIGHT))// this is a multizone light
+			m_nMultiZoneLight[m_nMaxMultiZoneLight++]=nLight ;
+
+
+		m_pLight[nLight].SubLightStart=m_nSubLightMax ; // where this light's cut up sublights start in m_SubLight
+
+
+		// break the light up into it's different sublights, cut by zones.
+		nMaxZone=m_nLightTouchesZone[nLight][INDEX_LIGHTZONECOUNT] ;
+		for(nZoneIndex=0 ; nZoneIndex<nMaxZone ; nZoneIndex++)
+		{
+			nZone=m_nLightTouchesZone[nLight][nZoneIndex] ;
+
+			flMinX= m_pLight[nLight].Min[0]<m_ZoneBoundary[nZone].Min[0] ? m_ZoneBoundary[nZone].Min[0] : m_pLight[nLight].Min[0] ; 
+			flMinY= m_pLight[nLight].Min[1]<m_ZoneBoundary[nZone].Min[1] ? m_ZoneBoundary[nZone].Min[1] : m_pLight[nLight].Min[1] ; 
+			flMinZ= m_pLight[nLight].Min[2]<m_ZoneBoundary[nZone].Min[2] ? m_ZoneBoundary[nZone].Min[2] : m_pLight[nLight].Min[2] ;
+
+			flMaxX= m_pLight[nLight].Max[0]>m_ZoneBoundary[nZone].Max[0] ? m_ZoneBoundary[nZone].Max[0] : m_pLight[nLight].Max[0] ; 
+			flMaxY= m_pLight[nLight].Max[1]>m_ZoneBoundary[nZone].Max[1] ? m_ZoneBoundary[nZone].Max[1] : m_pLight[nLight].Max[1] ; 
+			flMaxZ= m_pLight[nLight].Max[2]>m_ZoneBoundary[nZone].Max[2] ? m_ZoneBoundary[nZone].Max[2] : m_pLight[nLight].Max[2] ; 
+
+			// add the cut down light as a sublight
+			m_SubLight[m_nSubLightMax].Light=nLight ;
+			m_SubLight[m_nSubLightMax].Zone=nZone ;
+			m_SubLight[m_nSubLightMax].Min[0]=flMinX ;
+			m_SubLight[m_nSubLightMax].Min[1]=flMinY ;
+			m_SubLight[m_nSubLightMax].Min[2]=flMinZ ;
+			m_SubLight[m_nSubLightMax].Max[0]=flMaxX ;
+			m_SubLight[m_nSubLightMax].Max[1]=flMaxY ;
+			m_SubLight[m_nSubLightMax].Max[2]=flMaxZ ;
+
+			// remember which sublight is the centre
+			if(
+						 (m_pLight[nLight].Position[0]>=flMinX) && (m_pLight[nLight].Position[0]<=flMaxX)
+					&& (m_pLight[nLight].Position[1]>=flMinY) && (m_pLight[nLight].Position[1]<=flMaxY)
+					&& (m_pLight[nLight].Position[2]>=flMinZ) && (m_pLight[nLight].Position[2]<=flMaxZ)
+				)
+				nSubLightCentre=m_nSubLightMax ;
+
+					
+			m_nSubLightMax++ ; // we don't have to worry about bound checking this, because we've already checked there aren't too many lights.
+
+		}// end for zoneindex			
+		
+		// move the sublight that contains the centre to the beginning of the sublights for this light.
+		// We always want the first sublight to contain the centre to make the culling algos work better.
+		TempSubLight=m_SubLight[ m_pLight[nLight].SubLightStart ] ;
+		m_SubLight[ m_pLight[nLight].SubLightStart ] = m_SubLight[ nSubLightCentre ] ;
+		m_SubLight[ nSubLightCentre ] = TempSubLight ;
+
+
+		
+	}// end for light
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	//
+	// recalculate m_nZoneTouchesSubLight using the newly created sublights 
+	// (instead of the complete lights that were originally used)
+	//
+
+	int nSubLight=0 ;
+
+
+	// clear the light settings.
+	for(nZone=0 ; nZone<m_nMaxZone ; nZone++)
+		m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]=0 ;
+
+	for(nSubZone=0 ; nSubZone<nMaxSubZone ; nSubZone++)
+	{
+		nZone=m_pSubZones[nSubZone].Zone ;
+		flMinX=m_pSubZones[nSubZone].Min[0] ;
+		flMaxX=m_pSubZones[nSubZone].Max[0] ;
+		flMinY=m_pSubZones[nSubZone].Min[1] ;
+		flMaxY=m_pSubZones[nSubZone].Max[1] ;
+		flMinZ=m_pSubZones[nSubZone].Min[2] ;
+		flMaxZ=m_pSubZones[nSubZone].Max[2] ;
+
+		// test all the lights to see if any have centers inside this subzone
+		for(nSubLight=0 ; nSubLight<m_nSubLightMax ; nSubLight++)
+		{
+			// if light touches subzone (we store it in ZoneTouchesSubLight for now, will overwrite later)
+			// if light AABB overlaps the zone AABB
+			if(
+						 (flMinX<m_SubLight[nSubLight].Max[0]) && (flMaxX>m_SubLight[nSubLight].Min[0])
+					&& (flMinY<m_SubLight[nSubLight].Max[1]) && (flMaxY>m_SubLight[nSubLight].Min[1])
+					&& (flMinZ<m_SubLight[nSubLight].Max[2]) && (flMaxZ>m_SubLight[nSubLight].Min[2])
+				)
+			{
+				// add this light to the zone's light list
+				nIndex=m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT] ;
+				if(nIndex<MAX_LIGHTPERZONE) // only add if we aren't already maxed out.
+				{
+					// we need to check this light isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nZoneTouchesSubLight[nZone][nPos]!=nSubLight)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nSubLight in the list
+					{
+						m_nZoneTouchesSubLight[nZone][nIndex]=nSubLight ;
+						m_nZoneTouchesSubLight[nZone][INDEX_LIGHTCOUNT]++ ;
+					}
+
+				}
+
+			}// end if overlap
+
+		}// end for nSubLight
+
+	}// end for nSubZone
+
+
+
+
+
+	return 1 ;
+}
+
+
+int Q3Map::AssignLightsToPortals(void)
+{
+	float flMinX=0.0f ;
+	float flMaxX=0.0f ;
+	float flMinY=0.0f ;
+	float flMaxY=0.0f ;
+	float flMinZ=0.0f ;
+	float flMaxZ=0.0f ;
+	int nMaxPortal=m_iNumPortals ;
+	int nPortal=0 ;
+	int nMaxLight=m_nLightMax ;
+	int nLight=0 ;
+	int nIndex=0 ;
+	int nPos=0 ;
+
+
+
+	// clear the light settings.
+	for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+		m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT]=0 ;
+
+	// now test each portal against each light to see if they touch
+	for(nPortal=0 ; nPortal<nMaxPortal ; nPortal++)
+	{
+		flMinX=m_pPortals[nPortal].Min[0] ;
+		flMaxX=m_pPortals[nPortal].Max[0] ;
+		flMinY=m_pPortals[nPortal].Min[1] ;
+		flMaxY=m_pPortals[nPortal].Max[1] ;
+		flMinZ=m_pPortals[nPortal].Min[2] ;
+		flMaxZ=m_pPortals[nPortal].Max[2] ;
+
+		// test all the lights to see if any touch this portal
+		for(nLight=0 ; nLight<nMaxLight ; nLight++)
+		{
+
+			// if light AABB overlaps the portal AABB
+			if(
+						 (flMinX<m_pLight[nLight].Max[0]) && (flMaxX>m_pLight[nLight].Min[0])
+					&& (flMinY<m_pLight[nLight].Max[1]) && (flMaxY>m_pLight[nLight].Min[1])
+					&& (flMinZ<m_pLight[nLight].Max[2]) && (flMaxZ>m_pLight[nLight].Min[2])
+				)
+			{
+
+				// add this light to the portal's light list
+				nIndex=m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT] ;
+				if(nIndex<MAX_LIGHTPERPORTAL) // only add if we aren't already maxed out.
+				{
+					// we need to check this light isn't already on the list.
+					// it might have gotten on by another subzone, since a zone can have multiple subzones.
+					nPos=-1 ;
+					while((++nPos<nIndex) && (m_nPortalTouchesLight[nPortal][nPos]!=nLight)) ; 
+
+					if(nPos==nIndex) // this can only be true if we didn't already find nLight in the list
+					{
+						m_nPortalTouchesLight[nPortal][nIndex]=nLight ;
+						m_nPortalTouchesLight[nPortal][INDEX_PORTALLIGHTCOUNT]++ ;
+					}
+				}
+
+				// we don't keep a list of the portals that a light touches, we don't use such a thing.
+
+			}// end if light touches portal
+
+		}// end for light
+
+	}// end for portal
+
+	return 1 ;
+}
+
+// work out all the other zones each zone touches, via portals
+int Q3Map::AssignZonesToZones(void)
+{
+	
+
+	int nCentralZone=0 ;
+	int nPortalZone=0 ;
+	int nMaxPortalZone=0 ;
+	int nPortalZoneIndex=0 ;
+	int nPortal=0 ;
+	int nPortalIndex=0 ;
+	int nMaxPortal=0 ;
+
+	int nTouchZoneIndex=0 ;
+	int nMaxTouchZone=0 ;
+	int nAddZone=0 ;
+
+
+	// scan through all the zones (consider them "central zones")
+	for(nCentralZone=0 ; nCentralZone<m_nMaxZone ; nCentralZone++)
+	{
+		nMaxTouchZone=0 ;
+
+		// scan through all the portals in this centralzone.
+		nMaxPortal=m_nZoneTouchesPortal[nCentralZone][INDEX_PORTALCOUNT] ;
+		for(nPortalIndex=0 ; nPortalIndex<nMaxPortal; nPortalIndex++)
+		{
+			nPortal=m_nZoneTouchesPortal[nCentralZone][nPortalIndex] ;
+
+			// scan through all the zones this portal touches and add then to the central zone's list
+			nMaxPortalZone=m_nPortalTouchesZone[nPortal][INDEX_PORTALZONECOUNT] ;
+			for(nPortalZoneIndex=0 ; nPortalZoneIndex<nMaxPortalZone ; nPortalZoneIndex++)
+			{
+				nPortalZone=m_nPortalTouchesZone[nPortal][nPortalZoneIndex] ;
+
+				// we've got a portal zone.  
+				if(nPortalZone==nCentralZone) continue ; // if it's the central zone, skip it.
+
+				// check we don't already have it listed.
+				nAddZone=1 ;
+				for(nTouchZoneIndex=0 ; nTouchZoneIndex<nMaxTouchZone ; nTouchZoneIndex++)
+				{
+					if(m_nZoneTouchesPortal[nCentralZone][nTouchZoneIndex]==nPortalZone)
+					{
+						nAddZone=0 ;
+						break ;
+					}// end if
+				}// end for nTouchZoneIndex
+	
+				if(nAddZone)
+				{
+					m_nZoneTouchesZone[nCentralZone][nMaxTouchZone]=nPortalZone ;
+					nMaxTouchZone++ ;
+					if(nMaxTouchZone>=MAX_ZONEPERZONE) 
+						nMaxTouchZone=MAX_ZONEPERZONE-1 ;
+
+					
+				}
+
+
+			}// end for portal zone index
+
+
+		}// end for portal index
+		
+		// set the maximum
+		m_nZoneTouchesZone[nCentralZone][INDEX_ZONEPERZONECOUNT]=nMaxTouchZone ;
+
+		/*
+		sprintf(m_chBug, "CentralZone %i, TouchedZoneCount %i", nCentralZone, m_nZoneTouchesPortal[nCentralZone][INDEX_ZONEPERZONECOUNT]) ;
+		Q3Bug.LogAddCR(m_chBug) ;
+		for(nTouchZoneIndex=0 ; nTouchZoneIndex<m_nZoneTouchesZone[nCentralZone][INDEX_ZONEPERZONECOUNT] ; nTouchZoneIndex++)
+		{
+			sprintf(m_chBug, "     TouchedZone %i", m_nZoneTouchesZone[nCentralZone][nTouchZoneIndex]) ;
+			Q3Bug.LogAddCR(m_chBug) ;
+		}
+		*/
+
+
+	}// end for central zone
+
+
+
+
+	return 1 ;
+}
+
+
+
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map.h	(revision 11817)
@@ -0,0 +1,709 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+Copyright (C) 2009 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Q3Map.h -- handles the map data
+
+#ifndef _Q3MAP_H
+#define _Q3MAP_H
+
+#define WIN32_LEAN_AND_MEAN
+#include "windows.h"
+
+#include "Q3Map_Bezier.h"
+
+#include <string>
+#include <vector>
+
+#include "Q3Map_misc.h"
+
+//#include "JarDebug.h" //!! just for debugging, remove from final build
+
+#define MEMADD	65536 // memory is grown in 66k blocks
+#define MAX_TOKENSIZE 1024 // make sure tokens in texts aren't ridiculously large
+
+
+
+#define MINMAXLIMIT 10000000.0
+
+#define BRIGHTNESSTWEAK	0.5f //1.25f				// tweak for spotlight brightness
+
+#define ADDTEXTUREUNIQUE_FAIL		-1
+#define ADDTEXLAMP_FAIL					-2
+
+#define ADDSPOTLIGHTTEXTURE_FAIL	-1
+
+////////////////////////////////////////////////////
+
+#define AXIS_X	0
+#define AXIS_Y	1
+#define AXIS_Z	2
+
+////////////////////////////////////////////////////
+/*
+#define FACESORT_FACE_LIMIT			16777216
+#define FACESORT_FACE_SHIFT			0
+#define FACESORT_FACE_MASK			0x0000000000FFFFFF
+#define FACESORT_TEXTURE_LIMIT	4096
+#define FACESORT_TEXTURE_SHIFT	24
+#define FACESORT_TEXTURE_MASK		0x0000000FFF000000
+#define FACESORT_SUBZONE_LIMIT			4096 // also see MAX_ZONE
+#define FACESORT_SUBZONE_SHIFT			36
+#define FACESORT_SUBZONE_MASK			0x0000FFF000000000
+*/
+
+#define FACESORT_FACE_LIMIT			16777216
+#define FACESORT_FACE_SHIFT			0
+#define FACESORT_FACE_MASK			0x0000000000FFFFFF
+#define FACESORT_GROUP_LIMIT		65536	// also see MAX_TRANS
+#define FACESORT_GROUP_SHIFT		24
+#define FACESORT_GROUP_MASK			0x000000FFFF000000
+#define FACESORT_TEXTURE_LIMIT	4096
+#define FACESORT_TEXTURE_SHIFT	40
+#define FACESORT_TEXTURE_MASK		0x000FFF0000000000
+#define FACESORT_SUBZONE_LIMIT	4096 // also see MAX_ZONE
+#define FACESORT_SUBZONE_SHIFT	52
+#define FACESORT_SUBZONE_MASK		0xFFF0000000000000
+
+#define GROUPSORT_FACE_LIMIT		16777216
+#define GROUPSORT_FACE_SHIFT		0
+#define GROUPSORT_FACE_MASK			0x0000000000FFFFFF
+#define GROUPSORT_GROUP_LIMIT		16777216
+#define GROUPSORT_GROUP_SHIFT		24
+#define GROUPSORT_GROUP_MASK		0x0000FFFFFF000000
+#define GROUPSORT_SUBZONE_LIMIT	4096 // also see MAX_ZONE
+#define GROUPSORT_SUBZONE_SHIFT	52
+#define GROUPSORT_SUBZONE_MASK	0xFFF0000000000000
+
+
+
+////////////////////////////////////////////////////
+
+#define MAX_ZONE	4096							// max subzones and max zones. Also see FACESORT_SUBZONE_LIMIT
+#define MAX_SUBZONEPERZONE	16			// the most subzones that can make up a zone, further subzones ignored. INDEX_SUBZONECOUNT must be same as this
+#define INDEX_SUBZONECOUNT	16			// helps subzone counting in m_nZone.  See MAX_SUBZONEPERZONE
+
+#define MAX_PORTAL	32768						// max subzoneportals in a map.
+#define MAX_PORTALPERZONE 64				// the most portals that a zone can have, further portals ignored.  INDEX_PORTALCOUNT must be same as this
+#define MAX_ZONEPERPORTAL	8					// the most zones a portal can connect, further zones ignored.  INDEX_PORTALZONECOUNT must be the same as this
+#define MAX_LIGHTPERPORTAL 16				// the most lights that can touch a portal, further lights ignored. INDEX_PORTALLIGHTCOUNT must be the same as this
+#define INDEX_PORTALCOUNT	64				// helps portal counting in m_nZoneTouchesPortal. See MAX_PORTALSPERZONE
+#define INDEX_PORTALZONECOUNT 8			// helps portalconnect counting in m_nPortalTouchesZone. See MAX_ZONEPERPORTAL
+#define INDEX_PORTALLIGHTCOUNT 16		// helps portallight counting in m_PortalConnectsLight.	See MAX_LIGHTPERPORTAL
+
+#define MAX_ZONEPERZONE		64				// the most zones that a zone can connect to.
+#define INDEX_ZONEPERZONECOUNT	64  // helps zone per zone counting.
+
+#define MAX_LIGHT		32768						// max lights in a map, both from the map and other things (flashlight, missiles, etc)
+#define MAX_LIGHTPERZONE 64					// the most lights that a zone can have, further lights ignored.  INDEX_LIGHTCOUNT must be same as this
+#define MAX_ZONEPERLIGHT	8					// the most zones a light can touch, further zones ignored.  INDEX_LIGHTZONECOUNT must be the same as this
+#define INDEX_LIGHTCOUNT	64				// helps light counting in m_nZoneContainsLight.  see MAX_LIGHTPERZONE
+#define INDEX_LIGHTZONECOUNT	8			// helps light counting in m_nLightContainedByZone. See MAX_ZONEPERLIGHT
+
+#define MAX_SUBLIGHT	262144				// must be MAX_LIGHT * MAX_ZONEPERLIGHT
+#define MAX_TRANS			65536					// most transparent objects per zone (objects may be defined in various ways).  see FACESORT_TRANS_LIMIT
+
+
+
+////////////////////////////////////////////////////
+
+#define SUBZONE_EPSILON	0.01f	// small buffer of extra size around subzones so that we don't accidentally exclude a point due to float accuracy errors.
+#define FRUSTUM_EPSILON 0.0001f // once frustum is this tiny consider it dead
+#define VERYSMALL 0.00001			// small number
+
+#define PORTAL_UNCHECKED		0
+#define PORTAL_VISCHECK			1
+#define PORTAL_VISIBLE			2
+
+#define PORTALSTATE_OPENCHECK	0
+#define PORTALSTATE_CLOSED			1
+#define PORTALSTATE_OPEN				2
+
+#define ZONE_UNCHECKED			0
+#define ZONE_VISIBLE				1
+
+#define LIGHT_UNCHECKED				0
+#define LIGHT_OUTOFFRUSTUM		1
+#define LIGHT_INSIDEFRUSTUM		2
+#define LIGHT_NOTVISIBLE			4
+#define LIGHT_VISIBLE					8
+#define LIGHT_CHECKED					16
+
+///////////////////////////////////////////////////
+
+#define MAX_PROJECTORTEX	16		// most types of projector textures we can have per map.
+
+
+///////////////////////////////////////////////////
+
+// NOERROR is already defined in a windows file, it is 0
+#define ERROR_ParseMap						1
+#define ERROR_ParseEntities				2
+#define ERROR_AllocateVertex			3
+#define ERROR_AllocateTriangle		4
+#define ERROR_InitializeFaces			5
+#define ERROR_ConvertFaces				6
+#define ERROR_ConvertPatches			7
+#define ERROR_ConvertLamps				8
+#define ERROR_ConvertLampGlow			9
+#define ERROR_ConvertLightGlow		10
+#define ERROR_AssignTriangles			11
+#define ERROR_SortTriangles				12
+#define ERROR_ConvertTexLamp			13
+#define ERROR_SetupTransTextures	14
+#define ERROR_SortGroups					15
+
+
+///////////////////////////////////////////////////
+// error values for parsing key/values
+#define KEY_OK										0
+#define KEY_NONE									1
+#define KEY_ERROR									2
+
+//////////////////////////////////////////////////
+// entity types
+#define ENTITY_ERROR							0
+#define ENTITY_UNKNOWN						1
+#define ENTITY_WORLDSPAWN					2
+#define ENTITY_LIGHT							3
+
+///////////////////////////////////////////////////
+
+
+
+// The lump idexes that make up a bsp file.
+// Bzn bsp lump data is almost identical to q3a bsp lump data,  except that the
+// Effects, Lightmaps and VisData lumps are removed and there are two new lumps, one
+// describing the subzones and one describing the portals. The other difference is the lighting
+// entities (which are stored as normal entities in lump 0) since q3a bsps don't usually
+// store the light entities at all, and BZN has it's own unique set of lighting keys.
+
+const int Textures = 1;
+const int Planes = 2;
+const int Nodes = 3;
+const int Leafs = 4;
+const int LeafFaces = 5;
+const int LeafBrushes = 6;
+const int Brushes = 8;
+const int BrushSides = 9;
+const int Vertices = 10;
+const int MeshVerts = 11;
+const int Effects = 12;				// removed from bzn
+const int Faces = 13;
+const int LightMaps = 14;			// removed from bzn
+const int VisData = 16;				// removed from bzn
+const int SubZoneData = 17 ;	// added to bzn: overlapping subzones form zones. Zones are like groups of axial boxes.
+const int PortalData = 18 ;		// added to bzn: portals overlapping different zones allow them to see each other.
+const int MAX_LUMP = 19 ;
+
+const int MAX_LUMP_SIZE = 100000000 ; // this value is very large and arbitrary, 100 megabytes.  Just make sure MAX_LUMP_SIZE * MAX_LUMP is less than the max size for a size_t or parseMap error checking won't work.
+
+enum {POLYGON = 1, PATCH, MESH, BILLBOARD};
+
+typedef struct{
+  int iOffset;
+  int iLength;
+} direntry_t;
+
+#define Q3NAMESIZE	64
+typedef struct {
+  char name[Q3NAMESIZE];
+  int flags;
+  int contents;
+} Q3BspTexture;
+
+typedef struct{
+  unsigned char magic[4];
+  int version;
+  direntry_t Lumps[MAX_LUMP];
+} Q3BspHeader_t;
+
+typedef struct{
+  int texture;
+  int effect;
+  int type;
+  int vertex;
+  int n_vertexes;
+  int meshvert;
+  int n_meshverts;
+  int lm_index;
+  int lm_start[2];
+  int lm_size[2];
+  float lm_origin[3];
+  float lm_vecs[2][3];
+  float normal[3];
+  int size[2];
+} Q3BspFace_t;
+
+typedef struct{
+  float position[3];
+  float texcoord[2][2];
+  float normal[3];
+  unsigned char color[4];
+} Q3BspVertex;
+
+typedef struct {
+  int cluster;
+  int area;
+  int mins[3];
+  int maxs[3];
+  int leafface;
+  int n_leaffaces;
+  int leafbrush;
+  int n_leafbrushes;
+} Q3BspLeaf;
+
+typedef struct {
+  float normal[3];
+  float dist;
+} Q3BspPlane;
+
+typedef struct {
+  int plane;
+  int children[2];
+  int mins[3];
+  int maxs[3];
+} Q3BspNode;
+
+typedef struct {
+  int brushside;
+  int n_brushsides;
+  int texture;
+} Q3BspBrush;
+
+typedef struct {
+  int plane;
+  int texture;
+} Q3BspBrushSide;
+
+typedef struct {
+  unsigned char lightmap[128][128][3];
+} Q3BspLightMap;
+
+typedef struct {
+  int n_vecs;
+  int sz_vecs;
+  unsigned char *vecs;
+} Q3BspVisData;
+
+typedef struct {
+  int size;
+  Bezier *bezier;
+} Q3BspPatch;
+
+
+// this struct must be the same as in BZNq3map2
+typedef struct
+{
+	int Zone ;
+	float Min[3] ;
+	float Max[3] ;
+}
+BZN_SubZone_t;
+
+// this struct must be the same as in BZNq3map2
+typedef struct
+{
+	float Min[3] ;
+	float Max[3] ;
+}
+BZN_Portal_t;
+
+
+typedef struct{
+	int texture;    
+	int type;
+	int vertex;
+	int n_vertexes;
+	int meshvert;
+	int n_meshverts;
+	int n_triangles;
+	int lm_index;    
+	float normal[3]; 
+	int zone ; // added by Jared 
+	Q3BspPatch *patch;
+} Q3BspFaceRenderer;
+
+//////////////////////////////////////
+typedef struct {
+	int Zone ; // this gets set to -1 for triangles in no zone, and they don't get added to the manualobjects
+	int Texture ;
+	//int Lightmap ; // bzn doesn't use lightmaps
+	int VIndex[3] ;
+	int Lamp ; // which lamp this triangle came from, -1 for most triangles.
+
+	int Group ; // triangles from the same face are the same group, triangles from the same patch are the same group.  Most stuff is group 0 unless it needs special attention, such as transparent stuff
+} triangle_t;
+
+typedef struct {
+	unsigned int Flags ;
+	float	Position[3] ;
+	float Direction[3] ;
+	float Colour[3] ;
+	float Min[3] ;
+	float Max[3] ;
+	float	Cutoff ;
+	float	Angle ;
+	float Brightness ;
+	int Texture ; // texture index of light
+	unsigned int ZoneCount ; // how many zones this light touches
+	unsigned int CentreZone ; // which zone contains the centre of this light.  even if on a boundary, the light will only choose one zone as its centre.
+	short SubLightStart ; // where this light's sublights start in the sublight list.
+} light_t ;
+
+typedef struct {
+	unsigned int Flags ;
+	float	Position[3] ;
+	float Colour[3] ;
+	float Min[3] ;
+	float Max[3] ;
+	float Brightness ;
+	int Texture ; // texture index of light
+	int LightNode ; // -1 if not a node, 0 - 3 if a node.  LightNodes are used as the data for TexLamps, freeform geometry that gets converted to deferred shading lamp triangles.
+	unsigned short Zone[MAX_ZONEPERLIGHT+1] ; // the zones this lamp touches
+} lamp_t ;
+
+typedef struct
+{
+	float Min[3] ;
+	float Max[3] ;
+}
+minmax_t;
+
+// this used for the light culling algo, where each cutup light is treated as a subzone.
+typedef struct
+{
+	unsigned short Light ;
+	unsigned short Zone ;
+	float Min[3] ;
+	float Max[3] ;
+}
+sublight_t;
+
+
+class Q3Map
+{
+public:
+  Q3Map();
+  ~Q3Map();
+
+	int m_nNewCount ;
+
+	int m_nDebugA ;
+
+//	CJarDebug Q3Bug ; //!! just for debugging, remove from final build
+	char m_chBug[10240] ;
+
+	int ParseAndTriangulateMap(const char* pData, size_t Size) ;
+	void FreeParseMem(void) ;
+
+	int parseMap(const char* pMem, size_t Size);
+
+  int findVisibleFaces(const QVECTOR *camPos, int *facesToRender);
+  Q3BspFace_t *getFaces(void);
+  Q3BspPatch *handlePatch(int faceIndex);
+
+	char m_chSpotlightTexture[MAX_PROJECTORTEX][Q3NAMESIZE] ;
+	int m_nMaxSpotlightTexture ;
+	int AddSpolightTexture(char TEXNAME[]) ;
+
+private:
+
+  
+  
+  
+
+  	
+
+  int findLeaf(const QVECTOR *camPos) const;
+  bool isClusterVisible(int visCluster, int testCluster) const;	
+
+  int *mVisibleFaces;
+
+  std::vector<Q3BspVisData> *patches;
+
+public:
+  // map data
+
+  Q3BspHeader_t m_BspHeader;
+
+  char *m_pEntities;
+
+  int m_iNumTexs;
+  Q3BspTexture *m_pTexturesOrig;
+
+  int m_iNumFaces;
+  Q3BspFace_t *m_pFaces; 
+
+  int m_iNumVertices;
+  Q3BspVertex *m_pVertices;
+
+  int m_iNumMeshVerts;	
+  int *m_pMeshVerts;
+
+  int m_iNumLeafs;
+  Q3BspLeaf *m_pLeafs;
+
+  int m_iNumLeafFaces;
+  int *m_pLeafFaces;
+
+  int m_iNumPlanes;
+  Q3BspPlane *m_pPlanes;
+
+  int m_iNumNodes;
+  Q3BspNode *m_pNodes;
+
+  int m_iNumLeafBrushes;
+  int *m_pLeafBrushes;
+
+  int m_iNumBrushes;
+  Q3BspBrush *m_pBrushes;
+
+  int m_iNumBrushSides;
+  Q3BspBrushSide *m_pBrushSides;
+
+  int m_iNumLightMaps;
+  Q3BspLightMap *m_pLightMaps;
+
+  Q3BspVisData *m_VisData;
+
+	int m_iNumSubZones ;
+  BZN_SubZone_t *m_pSubZones;
+
+	int m_iNumPortals ;
+  BZN_Portal_t *m_pPortals;
+
+
+
+
+  int m_ClusterCount ;
+
+	void swizzleCoords(void);
+  void swizzleFloat3(float t[3]);
+  void swizzleInt3(int t[3]);
+
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	// memory management for the triangles
+	int AllocateTriangleMemory(void) ;
+	void FreeTriangleMemory(void) ;
+	int ExpandTriangleMemory(void) ;
+	int AddTriangle(triangle_t Triangle) ;
+	int m_nTriangleSize ; // starting memory size
+	void* m_pTriangleMem ; // allocate starting memory space
+	triangle_t* m_pTriangle ; // a pointer to the memory cast as a triangle_t
+	int m_nTriangleMax ;
+	int m_nTriangleLimit ;
+
+	// memory management for the vertices
+	int AllocateVertexMemory(int nVertNum) ;
+	void FreeVertexMemory(void) ;
+	int ExpandVertexMemory(void) ;
+	int AddVertex(Q3BspVertex Vertex) ;
+	int m_nVertexSize ; // starting memory size
+	void* m_pVertexMem ; // allocate starting memory space
+	Q3BspVertex* m_pVertex ; // a pointer to the memory cast as a Q3BspVertex
+	int m_nVertexMax ;
+	int m_nVertexLimit ;
+
+	// memory management for the lights
+	int AllocateLightMemory(void) ;
+	void FreeLightMemory(void) ;
+	int ExpandLightMemory(void) ;
+	int AddLight(light_t Light) ;
+	int m_nLightSize ; // starting memory size
+	void* m_pLightMem ; // allocate starting memory space
+	light_t* m_pLight ; // a pointer to the memory cast as a light_t
+	int m_nLightMax ;
+	int m_nLightLimit ;
+
+	// memory management for the lamps (a lamp is a deferred shading non-shadowing point light)
+	int AllocateLampMemory(void) ;
+	void FreeLampMemory(void) ;
+	int ExpandLampMemory(void) ;
+	int AddLamp(lamp_t Lamp) ;
+	int m_nLampSize ; // starting memory size
+	void* m_pLampMem ; // allocate starting memory space
+	lamp_t* m_pLamp ; // a pointer to the memory cast as a lamp_t
+	int m_nLampMax ;
+	int m_nLampLimit ;
+
+	// memory management for the textures
+	int AllocateTextureMemory(void) ;
+	void FreeTextureMemory(void) ;
+	int ExpandTextureMemory(void) ;
+	int AddTexture(Q3BspTexture Texture) ;
+	int AddTextureUnique(Q3BspTexture Texture) ; // special version of the Add function, will not add if the texture name already exist.  returns texture index, or -1 on fail
+	int m_nTextureSize ; // starting memory size
+	void* m_pTextureMem ; // allocate starting memory space
+	Q3BspTexture* m_pTexture ; // a pointer to the memory cast as a Texture_t
+	int m_nTextureMax ;
+	int m_nTextureLimit ;
+
+	// memory management for the TexLamp Triangles
+	int AllocateTexLampMemory(void) ;
+	void FreeTexLampMemory(void) ;
+	int ExpandTexLampMemory(void) ;
+	int AddTexLamp(int TexLamp) ;
+	int m_nTexLampSize ; // starting memory size
+	void* m_pTexLampMem ; // allocate starting memory space
+	int* m_pTexLamp ; // a pointer to the memory cast as an int
+	int m_nTexLampMax ;
+	int m_nTexLampLimit ;
+
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+	int ParseEntities(void) ;
+	int NextEntity(int* pPos, int nMaxPos) ;
+	int GetEntityType(int nPos, int nMaxPos) ;
+	int GetEntityKeyAndValue(int* pPos, int nMaxPos, char* pKey, char* pValue) ;
+	int GetNumbersFromValue(char* pValue, float *pNumber, int nNumberSize) ;
+	int GetNumbersFromValue(char* pValue, int *pNumber, int nNumberSize) ;
+	int ParseAndAddLight(int* pPos, int nMaxPos) ;
+
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+	Q3BspFaceRenderer *m_BspFaces;	
+	int m_NumBspFaces;
+	void DestroyBspFacesMemory(void) ;
+	int initFaces(void) ;
+
+	// we keep track of common texture indexes to avoid slow calls to AddTextureUnique when we add default light texture indexes
+	int m_nDefaultTextureIndexLamp ;
+	int m_nDefaultTextureIndexLamp2Pass ;
+	int m_nDefaultTextureIndexGlowLamp ;
+	int m_nDefaultTextureIndexGlowLight ;
+	int m_nDefaultTextureIndexSpotlight ;
+
+	void GetTexLampTextureNumbers() ;
+	int m_nBZN_LightNode0 ;
+	int m_nBZN_LightNode1 ;
+	int m_nBZN_LightNode2 ;
+	int m_nBZN_LightNode3 ;
+
+	int m_nGroup ;
+
+	////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	//
+	// Much easier to keep track of how zones/subzones/portals/lights connect to each other using hardwired arrays
+	// than dynamically allocated memory, even if it does waste a little space and impose some design limits.
+	// It's fast, easy to manage, and the total memory used is reasonably small.  
+	// The design limits are generous enough that it's unlikely maps will get anywhere near hitting them.
+	//
+	// Memory Footprints:
+	//
+	// m_nZone:											 4096 * (16+1) * sizeof(unsigned short) =	  139,264
+	// m_ZoneBoundary								 4096 *					 sizeof(minmax_t)24			=	   98,304
+	// m_nZoneTouchesPortal					 4096 * (64+1) * sizeof(unsigned short) =	  532,480
+	// m_nPortalTouchesZone					32768 * ( 8+1) * sizeof(unsigned short) =	  589,824
+	//
+	// m_nZoneContainsLightCentre		 4096 * (64+1) * sizeof(unsigned short) =	  532,480 
+	// m_nLightTouchesZone					32768 * ( 8+1) * sizeof(unsigned short) =	  589,824
+	// m_nZoneTouchesSubLight				 4096 * (64+1) * sizeof(unsigned short) =	  532,480
+	//
+	// m_nMultiZoneLight						32768 *					 sizeof(unsigned short)	=		 65,536	
+	// m_SubLight										32768 * 8			 * sizeof(sublight_t)28		=	6,815,744
+	// m_nZoneTouchesZone						 4096 * (64+1) * sizeof(unsigned short) =	  532,480
+	//
+	//																																TOTAL = 10,428,416 (9.9 meg)
+
+	unsigned short m_nZone[MAX_ZONE][MAX_SUBZONEPERZONE+1] ;									// last index is used as a counter, INDEX_SUBZONECOUNT
+	minmax_t m_ZoneBoundary[MAX_ZONE] ; // min and max of a zone.  Since zones might not be square, NEVER use this as the real zone boundary, work it out using the subzones instead.  This is just for cutting up lights.
+	
+	unsigned short m_nZoneTouchesPortal[MAX_ZONE][MAX_PORTALPERZONE+1] ;			// last index is used as a counter, INDEX_PORTALCOUNT
+	unsigned short m_nPortalTouchesZone[MAX_PORTAL][MAX_ZONEPERPORTAL+1] ;		// last index is used as a counter, INDEX_PORTALZONECOUNT
+	
+	// PortalTouchesLight is true if the light AABB touches the portal.
+	unsigned short m_nPortalTouchesLight[MAX_PORTAL][MAX_LIGHTPERPORTAL+1] ;	// last index is used as a counter, INDEX_PORTALLIGHTCOUNT
+
+	unsigned short m_nZoneContainsLightCentre[MAX_ZONE][MAX_LIGHTPERZONE+1] ;				// last index is used as a counter, INDEX_LIGHTCOUNT
+	unsigned short m_nLightTouchesZone[MAX_LIGHT][MAX_ZONEPERLIGHT+1] ;				// last index is used as a counter, INDEX_LIGHTZONECOUNT
+	unsigned short m_nZoneTouchesSubLight[MAX_ZONE][MAX_LIGHTPERZONE+1] ;				// last index is used as a counter, INDEX_LIGHTCOUNT
+
+	unsigned short m_nZoneTouchesZone[MAX_ZONE][MAX_ZONEPERZONE+1] ;				// last index is used as a counter, INDEX_ZONEPERZONECOUNT
+
+	// list of lights that touche more than one zone.  These require more complex visibility checks
+	unsigned short m_nMultiZoneLight[MAX_LIGHT] ; 
+	int m_nMaxMultiZoneLight ;
+	
+	sublight_t m_SubLight[MAX_SUBLIGHT] ;
+	int m_nSubLightMax ;
+	 
+
+	//
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+	int m_nMaxZone ;
+
+	int ConvertFacesToTriangles(void) ;
+	int ConvertPatchesToTriangles(void) ;
+	int ConvertTexLampsToLampTriangles(void) ;
+	int ConvertLampsToTriangles(void) ;
+	int ConvertLampsToGlowTriangles(void) ;
+	int ConvertLightsToGlowTriangles(void) ;
+
+
+	void SetVertex(Q3BspVertex *pVert, float flXPos, float flYPos, float flZPos) ;
+	bool VectorsAreEqual(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+	Q3BspVertex NormalizedCrossProduct(Q3BspVertex VertA, Q3BspVertex VertB, Q3BspVertex VertC) ;
+	float VertexDistance(Q3BspVertex* VertA, Q3BspVertex* VertB) ;
+	void VertexScale(Q3BspVertex* pVert, float flScale) ;
+	Q3BspVertex GetNormalised(Q3BspVertex* pVector) ;
+	Q3BspVertex VectorAdd(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+	Q3BspVertex VectorSubtract(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+	Q3BspVertex VectorMultiply(Q3BspVertex* pVecA, Q3BspVertex* pVecB) ;
+
+	void SetupZones(void) ;
+	int GetNextSubZone(float *flPoint, int nStart, int nMax) ;
+
+	bool PointInSubZone(float *flPoint, int nSubZone) ;
+	bool PointInZone(float *flPos, int nZone) ;
+
+	bool AABBTouchesSubZone(float *flPointMin, float *flPointMax, int nSubZone) ;
+	bool AABBTouchesZone(float *flPosMin, float *flPosMax, int nZone) ;
+
+	int AssignTrianglesToZones(void) ;
+	int FindTriangleZone(int nTriangle) ;
+	int SetupTriangleZone(int nTriangle) ;
+	int SplitTriangle(int nTriangle, int nAxis, float flCutPos) ; // only does axial cuts.  returns false on failure, probably due to lack of memory.
+	void CreateTweenVert(Q3BspVertex* pVertA, Q3BspVertex* pVertB, float flPercent0, Q3BspVertex* pVertAB) ;
+	
+
+	int SortTrianglesIntoGroups(void) ;
+	static int compareGroups( const void *arg1, const void *arg2 ) ;
+
+	int SortTrianglesIntoBatches(void) ;
+	static int compareTriangles( const void *arg1, const void *arg2 ) ;
+
+	int SetupTransTextures(void) ;
+	int* m_pTransTexture ;
+
+
+	int AssignPortalsToZones(void) ;
+	int AssignLightsToPortals(void) ;
+	int AssignLightsToZones(void) ;
+	int AssignZonesToZones(void) ;
+
+};
+
+#endif /* _Q3MAP_H */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_Bezier.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_Bezier.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_Bezier.cpp	(revision 11817)
@@ -0,0 +1,131 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Bezier.cpp -- tessellates the Bezier patches
+
+/* The tessellation code is taken from the document 
+"Rendering Quake 3 Maps" at 
+http://graphics.cs.brown.edu/games/quake/quake3.html
+The author states that it is based on code from 
+Paul Baker's Octagon project,
+http://www.paulsprojects.net/opengl/octagon/octagon.html
+which is released under the New BSD license.
+Please see the licenses folder.
+*/
+
+#include "Q3Map_Bezier.h"
+#include "Q3Map_misc.h"
+
+
+Bezier::Bezier()
+{	
+  mVertex = 0;
+  mIndex = 0;
+  mTrianglesPerRow = 0;
+  mRowIndex = 0;
+}
+
+Bezier::~Bezier()
+{
+  DELETE_ARRAY(mVertex);
+  DELETE_ARRAY(mIndex);
+  DELETE_ARRAY(mTrianglesPerRow);
+  DELETE_ARRAY(mRowIndex);
+}
+
+
+
+
+
+void Bezier::tessellate(int L) 
+{
+  // The number of vertices along a side is 1 + num edges
+  const int L1 = L + 1;
+
+  mVertex = new BspVertex[L1*L1];
+  mNumVertex = L1*L1;
+
+  // Compute the vertices    
+  for (int i = 0; i <= L; ++i)
+  {
+    float a = (float)i / L;
+    float b = 1.0f - a;
+
+    mVertex[i] =
+      mControls[0] * (b * b) + 
+      mControls[3] * (2 * b * a) +
+      mControls[6] * (a * a);
+  }
+
+  for (int i = 1; i <= L; i++) 
+  {
+    float a = (float)i / L;
+    float b = 1.0f - a;
+
+    BspVertex temp[3];
+
+    for (int j = 0; j < 3; j++)
+    {
+      int k = 3 * j;
+      temp[j] =
+        mControls[k + 0] * (b * b) + 
+        mControls[k + 1] * (2 * b * a) +
+        mControls[k + 2] * (a * a);
+    }
+
+    for(int j = 0; j <= L; ++j) 
+    {
+      float a = (float)j / L;
+      float b = 1.0f - a;
+
+      mVertex[i * L1 + j]=
+        temp[0] * (b * b) + 
+        temp[1] * (2 * b * a) +
+        temp[2] * (a * a);
+    }
+  }
+
+  // Compute the indices     
+  mIndex = new unsigned int[L * (L + 1) * 2];
+  mNumIndex = L * (L + 1) * 2;
+
+  for (int row = 0; row < L; ++row) 
+  {
+    for(int col = 0; col <= L; ++col)	
+    {
+      mIndex[(row * (L + 1) + col) * 2 + 1] = row       * L1 + col;
+      mIndex[(row * (L + 1) + col) * 2]     = (row + 1) * L1 + col;
+    }
+  }
+
+  mTrianglesPerRow = new unsigned int[L];
+  mRowIndex = new unsigned int[L];
+
+  for (int row = 0; row < L; ++row) 
+  {
+    mTrianglesPerRow[row] = 2 * L1;
+    //rowIndexes[row]      = &indexes[row * 2 * L1];
+    mRowIndex[row]      = row * 2 * L1;
+  }
+
+  for (int i=0; i < L1*L1; i++)
+    mVertex[i].normalise();
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_Bezier.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_Bezier.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_Bezier.h	(revision 11817)
@@ -0,0 +1,48 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// Bezier.h -- class for the Bezier patches
+
+#ifndef _BEZIER_H
+#define _BEZIER_H
+
+#include "Q3Map_BspVertex.h"
+
+class Bezier 
+{
+public:
+  Bezier();
+  ~Bezier();
+  
+  void tessellate(int level);
+
+  BspVertex mControls[9];
+  BspVertex *mVertex;
+  unsigned int *mIndex;
+  unsigned int *mTrianglesPerRow;
+  unsigned int *mRowIndex;
+  unsigned int mNumIndex;
+  unsigned int mNumVertex;
+  int mBaseBufferindex;
+  int mBaseVertexIndex;
+};
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_BspVertex.cpp
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_BspVertex.cpp	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_BspVertex.cpp	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// BspVertex.cpp -- used in the tessellation of the Bezier patches
+
+
+#include <math.h>
+#include "Q3Map_BspVertex.h"
+
+
+BspVertex::BspVertex()
+{
+  for (int i=0; i<3; i++)
+    mPosition[i] = 0;
+
+  for (int i=0; i<3; i++)
+    mNormal[i] = 0;
+
+  for(int i=0; i<2; i++)
+    for(int j=0; j<2; j++)
+      mTexcoord[i][j] = 0;
+}
+
+BspVertex::BspVertex(float p[3], float texcoord[2][2], float n[3])
+{
+  for (int i=0; i<3; i++)
+    mPosition[i] = p[i];
+
+  for (int i=0; i<3; i++)
+    mNormal[i] = n[i];
+
+  for(int i=0; i<2; i++)
+    for(int j=0; j<2; j++)
+    {		
+      this->mTexcoord[i][j] = texcoord[i][j];
+    }
+}
+
+BspVertex BspVertex::operator+(BspVertex a)
+{
+  BspVertex res;
+
+  for (int i=0; i<3; i++)
+  {
+    res.mPosition[i] = this->mPosition[i] + a.mPosition[i];
+    res.mNormal[i] = this->mNormal[i] + a.mNormal[i];
+  }
+
+  for(int i=0; i<2; i++)
+    for(int j=0; j<2; j++)
+    {			
+      res.mTexcoord[i][j] = this->mTexcoord[i][j] + a.mTexcoord[i][j];
+    }
+
+    return res;
+}
+
+BspVertex BspVertex::operator*(float a)
+{
+  BspVertex res;
+
+  for (int i=0; i<3; i++)
+  {
+    res.mPosition[i] = this->mPosition[i] * a;
+    res.mNormal[i] = this->mNormal[i] * a;
+  }
+
+  for(int i=0; i<2; i++)
+    for(int j=0; j<2; j++)
+      res.mTexcoord[i][j] = this->mTexcoord[i][j] * a;
+
+  return res;
+}
+
+void BspVertex::normalise(void)
+{
+  //QVECTOR n((float)mNormal[0], (float)mNormal[1], (float)mNormal[2]);
+
+  //D3DXVec3Normalize(&n, &n);
+  //mNormal[0] = n.x;
+  //mNormal[1] = n.y;
+  //mNormal[2] = n.z;
+
+	float flLen=sqrt( mNormal[0]*mNormal[0] + mNormal[1]*mNormal[1] + mNormal[2]*mNormal[2] ) ;
+	mNormal[0]/=flLen ;
+	mNormal[1]/=flLen ;
+	mNormal[2]/=flLen ;
+}
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_BspVertex.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_BspVertex.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_BspVertex.h	(revision 11817)
@@ -0,0 +1,44 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// BspVertex.h -- used in the tessellation of the Bezier patches
+
+#ifndef _BSPVERTEX_H
+#define _BSPVERTEX_H
+
+class BspVertex
+{
+public:
+  BspVertex();
+  BspVertex(float p[3], float texcoord[2][2], float n[3]);
+
+  float mPosition[3];
+  float mTexcoord[2][2];
+  float mNormal[3];
+
+  BspVertex operator+(BspVertex a);
+  BspVertex operator*(float a);
+
+  void normalise(void);
+
+};
+
+#endif 
Index: /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_misc.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_misc.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/bsp/Q3Map_misc.h	(revision 11817)
@@ -0,0 +1,33 @@
+/*
+===========================================================================
+Copyright (C) 2008 Daniel Örstadius
+Copyright (C) 2009 Jared Prince
+
+This file is part of bsp-renderer source code.
+
+bsp-renderer 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 3 of the License, or
+(at your option) any later version.
+
+bsp-renderer 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 bsp-renderer.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+// misc.h -- various definitions and functions
+
+#ifndef _MISC_H
+#define _MISC_H
+
+#define DELETE_POINTER(x) if(x) { delete x		; x=0 ; }
+#define DELETE_ARRAY(x)		if(x) { delete [] x ; x=0 ; }
+
+typedef float QVECTOR[3];
+
+#endif /* _MISC_H */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,3 @@
+ADD_SOURCE_FILES(TOOLS_SRC_FILES
+  ToolsInterfaceCompilation.cc
+)
Index: /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/Tickable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/Tickable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/Tickable.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/*!
+    @file
+    @brief Declaration of the Tickable interface.
+
+    The Tickable interface provides a tick(dt) function, that gets called every frame.
+    float dt is the time since the last frame in seconds.
+
+    Attention:
+    Classes derived from a Tickable that want to have a tick(dt) function on their part, MUST call the
+    parent::tick(dt) function explicitly in their implementation of tick(dt) because it's a virtual function.
+*/
+
+#ifndef _Tickable_H__
+#define _Tickable_H__
+
+#include "tools/ToolsPrereqs.h"
+
+#include "core/class/OrxonoxInterface.h"
+#include "core/class/Super.h"
+
+namespace orxonox
+{
+    //! The Tickable interface provides a tick(dt) function, that gets called every frame.
+    class _ToolsExport Tickable : virtual public OrxonoxInterface
+    {
+        public:
+            /**
+                @brief Gets called every frame.
+                @param dt The time since the last frame in seconds
+            */
+            virtual void tick(float dt) { }
+
+        protected:
+            Tickable();
+    };
+
+    SUPER_FUNCTION(1, Tickable, tick, true);
+}
+
+#endif /* _Tickable_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/TimeFactorListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/TimeFactorListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/TimeFactorListener.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TimeFactorListener_H__
+#define _TimeFactorListener_H__
+
+#include "tools/ToolsPrereqs.h"
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    class _ToolsExport TimeFactorListener : virtual public Listable
+    {
+        public:
+            TimeFactorListener();
+            virtual ~TimeFactorListener() = default;
+
+            static void setTimeFactor(float factor);
+            static inline float getTimeFactor()
+                { return TimeFactorListener::timefactor_s; }
+
+        protected:
+            virtual void changedTimeFactor(float factor_new, float factor_old) {}
+
+        private:
+            static float timefactor_s;
+    };
+}
+
+#endif /* _TimeFactorListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/ToolsInterfaceCompilation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/ToolsInterfaceCompilation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/tools/interfaces/ToolsInterfaceCompilation.cc	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compiles all the interfaces in the tools library with mostly just a constructor.
+*/
+
+#include "Tickable.h"
+#include "TimeFactorListener.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+    //----------------------------
+    // TimeFactorListener
+    //----------------------------
+    float TimeFactorListener::timefactor_s = 1.0f;
+
+    RegisterAbstractClass(TimeFactorListener).inheritsFrom<Listable>();
+
+    TimeFactorListener::TimeFactorListener()
+    {
+        RegisterObject(TimeFactorListener);
+    }
+
+    /*static*/ void TimeFactorListener::setTimeFactor(float factor)
+    {
+        if (factor == TimeFactorListener::timefactor_s)
+            return;
+
+        float oldFactor = TimeFactorListener::timefactor_s;
+        TimeFactorListener::timefactor_s = factor;
+        for (TimeFactorListener* listener : ObjectList<TimeFactorListener>())
+            listener->changedTimeFactor(factor, oldFactor);
+    }
+
+    //----------------------------
+    // Tickable
+    //----------------------------
+    RegisterAbstractClass(Tickable).inheritsFrom<OrxonoxInterface>();
+
+    /**
+        @brief Constructor: Registers the object in the Tickable-list
+    */
+    Tickable::Tickable()
+    {
+        RegisterObject(Tickable);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,54 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+SET_SOURCE_FILES(UTIL_SRC_FILES
+
+BUILD_UNIT StableBuildUnit.cc
+  Clipboard.cc
+  Clock.cc
+  Convert.cc
+  CRC32.cc
+  ExprParser.cc
+  Sleep.cc
+  SmallObjectAllocator.cc
+  SubString.cc
+END_BUILD_UNIT
+
+  MultiType.cc
+  Exception.cc
+  Math.cc
+  SignalHandler.cc
+  StringUtils.cc
+)
+
+ADD_SUBDIRECTORY(output)
+
+ORXONOX_ADD_LIBRARY(util
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    ${CEGUI_LIBRARY}
+    ${OGRE_LIBRARY}
+    ${Boost_SYSTEM_LIBRARY}
+  SOURCE_FILES
+    ${UTIL_SRC_FILES}
+)
+
+IF (DBGHELP_FOUND)
+  TARGET_LINK_LIBRARIES(util ${DBGHELP_LIBRARY})
+ENDIF()
Index: /code/branches/RacingBots_FS18/src/libraries/util/CRC32.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/CRC32.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/CRC32.cc	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CRC32.h"
+
+namespace orxonox
+{
+    void calcCRCBit(uint32_t &crc32, int bit)
+    {
+        int hbit = (crc32 & 0x80000000) ? 1 : 0;
+        if (hbit != bit)
+            crc32 = (crc32 << 1) ^ UTIL_CRC32POLY;
+        else
+            crc32 = crc32 << 1;
+      }
+
+    uint32_t calcCRC(unsigned char *data, unsigned int dataLength)
+    {
+        uint32_t crc32 = 0;
+        for(unsigned int i = 0; i < dataLength; i++)
+        {
+            calcCRCBit(crc32, (data[i] & 0x1) >> 0); // 1st bit
+            calcCRCBit(crc32, (data[i] & 0x2) >> 1); // 2nd bit
+            calcCRCBit(crc32, (data[i] & 0x3) >> 2); // 3rd bit
+            calcCRCBit(crc32, (data[i] & 0x4) >> 3); // 4th bit
+            calcCRCBit(crc32, (data[i] & 0x5) >> 4); // 5th bit
+            calcCRCBit(crc32, (data[i] & 0x6) >> 5); // 6th bit
+            calcCRCBit(crc32, (data[i] & 0x7) >> 6); // 7th bit
+            calcCRCBit(crc32, (data[i] & 0x8) >> 7); // 8th bit
+        }
+        return crc32;
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/libraries/util/CRC32.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/CRC32.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/CRC32.h	(revision 11817)
@@ -0,0 +1,43 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Util_CRC_H__
+#define _Util_CRC_H__
+
+#include "UtilPrereqs.h"
+
+namespace orxonox
+{
+    const unsigned int UTIL_CRC32POLY = 0x04C11DB7; /* CRC-32 Polynom */
+
+    _UtilExport void calcCRCBit(uint32_t &crc32, int bit);
+
+    _UtilExport uint32_t calcCRC(unsigned char *data, unsigned int dataLength);
+}
+
+#endif /* _Util_CRC_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Clipboard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Clipboard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Clipboard.cc	(revision 11817)
@@ -0,0 +1,142 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ *   Windows version inspired by "Copy Text To Clipboard" by Laszlo Szathmary, 2007
+ *      http://www.loria.fr/~szathmar/off/projects/C/CopyTextToClipboard/index.php
+ */
+
+/**
+    @file
+    @brief OS-specific implementations of the clipboard functions.
+*/
+
+#include "Clipboard.h"
+
+#ifdef ORXONOX_PLATFORM_WINDOWS
+
+/////////////
+// Windows //
+/////////////
+
+#ifndef WIN32_LEAN_AND_MEAN
+#  define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#undef min
+#undef max
+#include "Output.h"
+
+namespace orxonox
+{
+
+    /**
+        @brief Puts text into the Windows-clipboard
+        @return True if the action was successful
+    */
+    bool toClipboard(const std::string& text)
+    {
+        try
+        {
+            if (OpenClipboard(0))
+            {
+                EmptyClipboard();
+                HGLOBAL clipbuffer = GlobalAlloc(GMEM_DDESHARE, text.size() + 1);
+                char* buffer = static_cast<char*>(GlobalLock(clipbuffer));
+                strcpy(buffer, text.c_str());
+                GlobalUnlock(clipbuffer);
+                SetClipboardData(CF_TEXT, clipbuffer);
+                CloseClipboard();
+
+                return true;
+            }
+        }
+        catch (...)
+        {
+            orxout(user_error) << "Unable to copy the following text to the clipboard:" << endl;
+            orxout(user_error) << '"' << text << '"' << endl;
+        }
+        return false;
+    }
+
+    /**
+        @brief Gets text from the windows-clipboard if there is any text.
+        @return The retrieved text
+    */
+    std::string fromClipboard()
+    {
+        try
+        {
+            if (OpenClipboard(0))
+            {
+                HANDLE hData = GetClipboardData(CF_TEXT);
+                if (hData == nullptr)
+                    return "";
+                std::string output(static_cast<char*>(GlobalLock(hData)));
+                GlobalUnlock(hData);
+                CloseClipboard();
+
+                return output;
+            }
+        }
+        catch (...)
+        {
+            orxout(user_error) << "Unable to retrieve text from the clipboard." << endl;
+        }
+        return "";
+    }
+}
+
+#else /* ORXONOX_PLATFORM_WINDOWS */
+
+/////////////
+// Default //
+/////////////
+
+namespace orxonox
+{
+    static std::string clipboard; ///< Keeps the text of our internal clipboard
+
+    /**
+        @brief Default implementation if there is no OS-specific implementation or no clipboard. Copies the text into an internal clipboard.
+        @see fromClipboard()
+    */
+    bool toClipboard(const std::string& text)
+    {
+        clipboard = text;
+        return true;
+    }
+
+    /**
+        @brief Default implementation if there is no OS-specific implementation or no clipboard. Gets the text from the internal clipboard.
+        @see toClipboard()
+    */
+    std::string fromClipboard()
+    {
+        return clipboard;
+    }
+}
+
+#endif /* ORXONOX_PLATFORM_WINDOWS */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Clipboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Clipboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Clipboard.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util Command
+    @brief Some functions to exchange text between the OS clipboard and the Shell in Orxonox.
+
+    Use fromClipboard() to get text from the clipboard (if there is any text) and
+    toClipboard() to put text into the clipboard.
+
+    These functions can only work properly if there's an OS-specific implementation
+    in Clipboard.cc. If a specific OS is not supported, the clipboard only works
+    within Orxonox, but the exchange with other programs is not possible.
+*/
+
+#ifndef _Clipboard_H__
+#define _Clipboard_H__
+
+#include "UtilPrereqs.h"
+#include <string>
+
+namespace orxonox
+{
+    _UtilExport bool toClipboard(const std::string& text);
+    _UtilExport std::string fromClipboard();
+}
+
+#endif /* _Clipboard_H__ */
+
Index: /code/branches/RacingBots_FS18/src/libraries/util/Clock.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Clock.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Clock.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Clock.h"
+#include <OgreTimer.h>
+
+namespace orxonox
+{
+    Clock::Clock()
+        : timer_(new Ogre::Timer())
+        , tickTime_(0)
+        , tickDt_(0)
+        , tickDtFloat_(0.0f)
+    {
+    }
+
+    Clock::~Clock()
+    {
+        delete timer_;
+    }
+
+    void Clock::capture()
+    {
+        tickDt_ = timer_->getMicroseconds() - (unsigned long)tickTime_;
+        tickTime_ += tickDt_;
+        tickDtFloat_ = static_cast<float>(tickDt_) / 1000000.0f;
+    }
+
+    unsigned long long Clock::getRealMicroseconds() const
+    {
+        return tickTime_ + (timer_->getMicroseconds() - (unsigned long)tickTime_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/Clock.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Clock.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Clock.h	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util
+*/
+
+#ifndef _Clock_H__
+#define _Clock_H__
+
+#include "UtilPrereqs.h"
+#include "OgreForwardRefs.h"
+
+namespace orxonox
+{
+    /** Simple real time clock based on Ogre::Timer
+    @details
+        The class can be used to both capture the current real time or to
+        incrementally capture the time and then distribute that time information
+        via Clock& references (for instance for the game tick). <br>
+        Precision: <br>
+    @par Precision
+        The maximum precision is given by the Ogre::Timer and that is somewhere
+        in the microsecond range for both Windows and UNIX.
+    @par Remarks for Usage on Windows
+        For proper functionality this class MUST be used in the same thread! <br>
+        Furthermore it might be possible that the Ogre::Timer has a performance
+        caveat because it will only capture the time on the same CPU core.
+        Confining the main thread to one process could speed up the game.
+    */
+    class _UtilExport Clock
+    {
+    public:
+        /// Starts the time at 0
+        Clock();
+        ~Clock();
+
+        /** Internally captures the time and stays at that particular time
+        @remarks
+            Mind the types! Ogre::Timer::getMicroseconds() will return an unsigned
+            long, which will eventually overflow. But if you use the subtraction of
+            the current time minus the last time the timer gave us and sum these up to
+            a 64 bit integer, we get the desired result. <br>
+            Also mind that we don't have to store the last timer's time as unsigned long
+            as well because (unsigned long)tickTime_ will do exactly that.
+        */
+        void capture();
+
+        /// Returns the last captured absolute time in microseconds
+        unsigned long long getMicroseconds() const
+            { return tickTime_; }
+        /// Returns the last captured absolute time in milliseconds
+        unsigned long long getMilliseconds() const
+            { return tickTime_ / 1000; }
+        /// Returns the last captured absolute time in seconds
+        unsigned long getSeconds() const
+            { return static_cast<long> (tickTime_ / 1000000); }
+        /// Returns the last captured absolute time in seconds as float
+        float getSecondsPrecise() const
+            { return static_cast<float>(tickTime_ / 1000000.0f); }
+
+        /// Returns the timespan in seconds between the last two calls to capture()
+        float getDeltaTime() const
+            { return tickDtFloat_; }
+        /// Returns the timespan in microseconds between the last two calls to capture()
+        long getDeltaTimeMicroseconds() const
+            { return tickDt_; }
+
+        /** Returns the current real time in microseconds
+        @note
+            This is especially useful to measure execution times because of the
+            high precision.
+        */
+        unsigned long long getRealMicroseconds() const;
+
+    private:
+        // non-copyable:
+        Clock(const Clock&) = delete;
+        Clock& operator=(const Clock&) = delete;
+
+        Ogre::Timer*       timer_;       ///< Ogre timer object
+        unsigned long long tickTime_;    ///< Currently captured time
+        long               tickDt_;      ///< Delta time in microseconds (cache value)
+        float              tickDtFloat_; ///< Delta time in seconds (cache value)
+    };
+}
+
+#endif /* _Clock_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Convert.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Convert.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Convert.cc	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ */
+
+#include "Convert.h"
+#include "StringUtils.h"
+
+namespace orxonox
+{
+    bool ConverterExplicit<std::string, bool>::convert(bool* output, const std::string& input)
+    {
+        const std::string& stripped = getLowercase(removeTrailingWhitespaces(input));
+        if (stripped == "true" || stripped == "on" || stripped == "yes")
+        {
+            *output = true;
+            return true;
+        }
+        else if (stripped == "false" || stripped == "off" || stripped == "no")
+        {
+            *output = false;
+            return true;
+        }
+
+        std::istringstream iss(input);
+        if (iss >> (*output))
+            return true;
+        else
+            return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/Convert.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Convert.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Convert.h	(revision 11817)
@@ -0,0 +1,484 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Fabian 'x3n' Landau
+ *      Benjamin Grauer
+ *   Co-authors:
+ *      ...
+ */
+
+/**
+    @defgroup Convert Conversion functions
+    @ingroup Util
+*/
+
+/** Functions that convert values between different types.
+@file
+@ingroup Convert
+@par Usage
+    There are three ways to use the conversions depending on what you need. <br>
+    - For simply converting values without having to know whether the conversion
+      was successful (for instance float --> string), use orxonox::multi_cast
+      which effectively works exactly like static_cast, etc.
+      @code
+        float input = 42.0;
+        std::string output = multi_cast<std::string>(input);
+      @endcode
+    - If you care about whether the conversion was successful,
+      use orxonox::convertValue.
+      @code
+        std::string input("3.4");
+        float output;
+        bool success = convertValue(&output, input);
+      @endcode
+    - If you care about success and if you can also feed a fallback value,
+      use orxonox::convertValue.
+      @code
+        std::string input("3.4");
+        float output;
+        bool success = convertValue(&output, input, 0.0);
+      @endcode
+    - If success doesn't matter but you can feed a fallback value,
+      use orxonox::getConvertedValue.
+      @code
+        std::string input("3.4");
+        float output = getConvertedValue(input, 0.0);
+      @endcode
+@details
+    The back end of these functions are the actual implementations for the
+    specific conversions, for instance from Ogre::Vector3 to std::string and
+    vice versa. Some of them also use the iostream operators. <br>
+    The real deal is evaluating which function is needed for a conversion based
+    on the input and output type. But there are lots of catches in conjunction
+    with templates which explains why there are so many functions in this file.
+    <br> <br>
+@par Search Order
+    Finding the right function is governed by priority rules: <br>
+    -# (Partial) template specialisation of orxonox::ConverterExplicit::convert()
+    -# An implicit conversion. This includes 'FooBar' to 'int' if FooBar
+       defines operator int() or float().
+    -# Global or member operators for iostream when converting from or
+       to std::string (and FROM const char*)
+    -# (Partial) template specialisation of orxonox::ConverterFallback::convert()
+    -# Fallback function that displays "Could not convert value" with type
+       information obtained from typeid().
+@par Implementing conversion functions
+    To do that you probably need to know a thing or two about the types
+    involved. So, get ready with that. <br>
+    Usually the best way to do it is specialising of the orxonox::ConverterFallback
+    template, like this:
+    @code
+    template <>
+    struct _UtilExport ConverterFallback<std::string, MyType>
+    {
+        static bool convert(MyType* output, const std::string& input)
+        {
+           ...
+           return success;
+        }
+    };
+    @endcode
+    This piece of code converts an std::string to MyType and returns whether the
+    conversion was successful. You can also use partial specialisation.<br>
+    The advantage with orxonox::ConverterFallback is that it has a low priority
+    meaning that when there is an implicit conversion or an iostream method, that
+    comes first and you don't have to deal with it (and the accompanying
+    function call ambiguity). <br>
+    However sometimes you would like to explicitely replace such a conversion.
+    That's where orxonox::ConverterExplicit comes in handy (for instance we
+    replaced the operator << conversions for Ogre::VectorX with our own functions).
+@note
+    There has to be an exact type match when using template specialisations. <br>
+    Template specialisations can be defined after including this file.
+    But any implicit cast function or iostream operator has to be included
+    in this file!
+@par Understanding the Code
+    In order to understand how the templates work, it is probably best to study
+    the functions in order of calling. There are lots of comments explaining
+    what happens, but you'll need to understand a deal about partial template
+    specialisation and function headers are matched in C++.
+*/
+
+#ifndef _Converter_H__
+#define _Converter_H__
+
+#include "UtilPrereqs.h"
+
+#include <string>
+#include <sstream>
+#include <typeinfo>
+#include <type_traits>
+#include <loki/TypeManip.h>
+
+#include "Output.h"
+
+// disable warnings about possible loss of data
+#ifdef ORXONOX_COMPILER_MSVC
+#  pragma warning(push)
+#  pragma warning(disable:4244)
+#endif
+
+namespace orxonox
+{
+    ///////////////////
+    // No Conversion //
+    ///////////////////
+
+    /// Default template. No conversion available at all.
+    template <class FromType, class ToType>
+    struct ConverterFallback
+    {
+        ORX_FORCEINLINE static bool convert(ToType* /*output*/, const FromType& /*input*/)
+        {
+            orxout(internal_warning) << "Could not convert value of type " << typeid(FromType).name()
+                                     << " to type " << typeid(ToType).name() << endl;
+            return false;
+        }
+    };
+
+    /// If all else fails, try a dynamic_cast for pointer types.
+    template <class FromType, class ToType>
+    struct ConverterFallback<FromType*, ToType*>
+    {
+        ORX_FORCEINLINE static bool convert(ToType** output, FromType* const input)
+        {
+            ToType* temp = dynamic_cast<ToType*>(input);
+            if (temp)
+            {
+                *output = temp;
+                return true;
+            }
+            else
+                return false;
+        }
+    };
+}
+
+
+///////////////////////
+// ConverterFallback //
+///////////////////////
+
+/** Fallback template for stringstream
+@details
+    Neither FromType nor ToType was std::string, therefore
+    delegate to orxonox::ConverterFallback
+*/
+template <class FromType, class ToType>
+struct ConverterStringStream
+{
+    ORX_FORCEINLINE static bool convert(ToType* output, const FromType& input)
+    {
+        return orxonox::ConverterFallback<FromType, ToType>::convert(output, input);
+    }
+};
+
+
+/////////////
+// OStream //
+/////////////
+
+/// Extra namespace to avoid exposing the iostream operators in it
+namespace fallbackTemplates
+{
+    /// Fallback operator <<() (delegates to orxonox::ConverterFallback)
+    template <class FromType>
+    ORX_FORCEINLINE bool operator <<(std::ostream& outstream,  const FromType& input)
+    {
+        std::string temp;
+        if (orxonox::ConverterFallback<FromType, std::string>::convert(&temp, input))
+        {
+            std::operator <<(outstream, temp);
+            return true;
+        }
+        else
+            return false;
+    }
+}
+
+/// Template that evaluates whether we can convert to std::string via ostringstream
+template <class FromType>
+struct ConverterStringStream<FromType, std::string>
+{
+    ORX_FORCEINLINE static bool convert(std::string* output, const FromType& input)
+    {
+        using namespace fallbackTemplates;
+        // this operator call only chooses fallbackTemplates::operator<<()
+        // if there's no other fitting function
+        std::ostringstream oss;
+        // Note: std::ostream has operator!() to tell whether any error flag was set
+        if (oss << input)
+        {
+            (*output) = oss.str();
+            return true;
+        }
+        else
+            return false;
+    }
+};
+
+
+/////////////
+// IStream //
+/////////////
+
+namespace fallbackTemplates
+{
+    /// Fallback operator >>() (delegates to orxonox::ConverterFallback)
+    template <class ToType>
+    ORX_FORCEINLINE bool operator >>(std::istream& instream, ToType& output)
+    {
+        std::string input(static_cast<std::istringstream&>(instream).str());
+        return orxonox::ConverterFallback<std::string, ToType>::convert(&output, input);
+    }
+}
+
+/// Template that evaluates whether we can convert from std::string via istringstream
+template <class ToType>
+struct ConverterStringStream<std::string, ToType>
+{
+    ORX_FORCEINLINE static bool convert(ToType* output, const std::string& input)
+    {
+        using namespace fallbackTemplates;
+        // this operator call chooses fallbackTemplates::operator>>()
+        // only if there's no other fitting function
+        std::istringstream iss(input);
+        // Note: std::istream has operator!() to tell whether any error flag was set
+        if (iss >> (*output))
+        {
+            return true;
+        }
+        else
+            return false;
+    }
+};
+
+namespace orxonox
+{
+    ///////////////////
+    // Implicit Cast //
+    ///////////////////
+
+    /// %Template delegates to ::ConverterStringStream
+    template <class FromType, class ToType>
+    ORX_FORCEINLINE bool convertImplicitely(ToType* output, const FromType& input, Loki::Int2Type<false>)
+    {
+        return ConverterStringStream<FromType, ToType>::convert(output, input);
+    }
+
+    /// Makes an implicit cast from \a FromType to \a ToType
+    template <class FromType, class ToType>
+    ORX_FORCEINLINE bool convertImplicitely(ToType* output, const FromType& input, Loki::Int2Type<true>)
+    {
+        (*output) = static_cast<ToType>(input);
+        return true;
+    }
+
+
+    ////////////////////////////////
+    // ConverterExplicit Fallback //
+    ////////////////////////////////
+
+    /** Default template if no orxonox::ConverterExplicit is available
+    @details
+        Evaluates whether \a FromType can be implicitly converted to \a ToType
+        by the use the ImplicitConversion magic.
+    */
+    template <class FromType, class ToType>
+    struct ConverterExplicit
+    {
+        static constexpr bool probe = std::is_convertible<FromType, ToType>::value;
+        ORX_FORCEINLINE static bool convert(ToType* output, const FromType& input)
+        {
+            // Use the probe's value to delegate to the right function
+            return convertImplicitely(output, input, Loki::Int2Type<probe>());
+        }
+    };
+
+
+    //////////////////////
+    // Public Functions //
+    //////////////////////
+
+    /**
+    @brief
+        Converts any value to any other as long as there exists a conversion.
+    @details
+        Otherwise, the conversion will generate a runtime warning and return false.
+    @see Convert.h
+    @param output
+        A pointer to the variable where the converted value will be stored
+    @param input
+        The original value
+    */
+    template <class FromType, class ToType>
+    ORX_FORCEINLINE bool convertValue(ToType* output, const FromType& input)
+    {
+        return ConverterExplicit<FromType, ToType>::convert(output, input);
+    }
+
+    // Calls convertValue and returns true if the conversion was successful.
+    // Otherwise the fallback is used.
+    /**
+    @brief
+        Converts any value to any other as long as there exists a conversion.
+        Otherwise, the conversion will generate a runtime warning and return false.
+        If the conversion doesn't succeed, \a fallback is written to \a output.
+    @see Convert.h
+    @param output
+        A pointer to the variable where the converted value will be stored
+    @param input
+        The original value
+    @param fallback
+        A default value that gets written to '*output' if there is no conversion.
+    */
+    template<class FromType, class ToType>
+    ORX_FORCEINLINE bool convertValue(ToType* output, const FromType& input, const ToType& fallback)
+    {
+        if (convertValue(output, input))
+            return true;
+        else
+        {
+            (*output) = fallback;
+            return false;
+        }
+    }
+
+    /// Directly returns the converted value, but uses the fallback on failure. @see convertValue
+    template<class FromType, class ToType>
+    ORX_FORCEINLINE ToType getConvertedValue(const FromType& input, const ToType& fallback)
+    {
+        ToType output;
+        convertValue(&output, input, fallback);
+        return output;
+    }
+
+    /**
+    @brief
+        Converts any value to any other as long as there exists a conversion.
+    @details
+        Use exactly the way you use static_cast, etc. <br>
+        A failed conversion will return a default instance of \a ToType
+        (possibly uninitialised)
+    @see Convert.h
+    @param input
+        The original value
+    */
+    template<class ToType, class FromType>
+    ORX_FORCEINLINE ToType multi_cast(const FromType& input)
+    {
+        ToType output;
+        convertValue(&output, input);
+        return output;
+    }
+
+    ////////////////////////////////
+    // Special string conversions //
+    ////////////////////////////////
+
+    /// Delegates conversion from const char* to std::string
+    template <class ToType>
+    struct ConverterExplicit<const char*, ToType>
+    {
+        ORX_FORCEINLINE static bool convert(ToType* output, const char* input)
+        {
+            return convertValue<std::string, ToType>(output, input);
+        }
+    };
+
+    /// Conversion would exhibit ambiguous << or >> operators when using iostream
+    template <>
+    struct ConverterExplicit<char, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const char input)
+        {
+            *output = input;
+            return true;
+        }
+    };
+    /// Conversion would exhibit ambiguous << or >> operators when using iostream
+    template <>
+    struct ConverterExplicit<unsigned char, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const unsigned char input)
+        {
+            *output = input;
+            return true;
+        }
+    };
+    /// Conversion would exhibit ambiguous << or >> operators when using iostream
+    template <>
+    struct ConverterExplicit<std::string, char>
+    {
+        ORX_FORCEINLINE static bool convert(char* output, const std::string& input)
+        {
+            if (!input.empty())
+                *output = input[0];
+            else
+                *output = '\0';
+            return true;
+        }
+    };
+    /// Conversion would exhibit ambiguous << or >> operators when using iostream
+    template <>
+    struct ConverterExplicit<std::string, unsigned char>
+    {
+        ORX_FORCEINLINE static bool convert(unsigned char* output, const std::string& input)
+        {
+            if (!input.empty())
+                *output = input[0];
+            else
+                *output = '\0';
+            return true;
+        }
+    };
+
+
+    /// Conversion from bool to std::string
+    template <>
+    struct ConverterExplicit<bool, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const bool& input)
+        {
+            if (input)
+              *output = "true";
+            else
+              *output = "false";
+            return true;
+        }
+    };
+
+    /// Conversion from std::string to bool
+    template <>
+    struct _UtilExport ConverterExplicit<std::string, bool>
+    {
+        static bool convert(bool* output, const std::string& input);
+    };
+}
+
+// Reinstate warnings
+#ifdef ORXONOX_COMPILER_MSVC
+#  pragma warning(pop)
+#endif
+
+#endif /* _Convert_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/DestructionHelper.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/DestructionHelper.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/DestructionHelper.h	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef __DestructionHelper_H__
+#define __DestructionHelper_H__
+
+#include "UtilPrereqs.h"
+
+namespace orxonox
+{
+    /** Deletes an object and resets the pointer
+    @param object
+        Pointer to an object. Handing over nullptr is safe.
+    */
+    template <class T>
+    void safeObjectDelete(T** object)
+    {
+        delete *object;
+        *object = nullptr;
+    }
+
+    /** Utility class that helps to create a special kind of destructor that
+        also executes if the destruction fails.
+        This helps a lot to improve exception handling. <br>
+        <br>
+        Example: <br>
+        @code
+        class MyClass
+        {
+        public:
+            MyClass() : destructionHelper_(this)
+            {
+                // Do something that might throw
+            }
+            ~MyClass()
+            {
+                // Keep empty!
+            }
+            void destroy()
+            {
+                // Place your destruction code here instead
+            }
+
+        private:
+            orxonox::DestructionHelper<MyClass> destructionHelper_;
+        };
+        @endcode
+    */
+    template <class T>
+    class DestructionHelper
+    {
+    public:
+        DestructionHelper(T* object)
+            : object_(object)
+        {
+        }
+
+        ~DestructionHelper()
+        {
+            object_->destroy();
+        }
+
+    private:
+        // non-copyable:
+        DestructionHelper(const DestructionHelper&) = delete;
+        DestructionHelper& operator=(const DestructionHelper&) = delete;
+
+        T* object_;
+    };
+}
+
+#endif /* __DestructionHelper_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/DisplayStringConversions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/DisplayStringConversions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/DisplayStringConversions.h	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ */
+
+/**
+@file
+@brief
+    std::sring to Ogre::UTFString conversion functions
+*/
+
+#ifndef _DisplayStringConversions_H__
+#define _DisplayStringConversions_H__
+
+#include "UtilPrereqs.h"
+#include <OgreOverlayElement.h>
+
+#if OGRE_UNICODE_SUPPORT
+    #include <OgreUTFString.h>
+
+    namespace orxonox
+    {
+        template <>
+        struct ConverterExplicit<std::string, Ogre::DisplayString>
+        {
+            //! Converts an std::string into an Ogre::UTFString
+            inline static bool convert(Ogre::DisplayString* output, const std::string& input)
+            {
+                Ogre::UTFString::code_point cp;
+                for (const char& character : input)
+                {
+                  cp = character;
+                  cp &= 0xFF;
+                  output->append(1, cp);
+                }
+                return true;
+            }
+        };
+    }
+#else
+    namespace orxonox
+    {
+        template <>
+        struct ConverterExplicit<std::string, Ogre::DisplayString>
+        {
+            //! Converts an std::string into an Ogre::String
+            inline static bool convert(Ogre::DisplayString* output, const std::string& input)
+            {
+                *output = input;
+                return true;
+            }
+        };
+    }
+#endif
+
+#endif /* _DisplayStringConversions_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Exception.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Exception.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Exception.cc	(revision 11817)
@@ -0,0 +1,124 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of the Exception class.
+*/
+
+#include "Exception.h"
+
+#include <cstddef>
+
+#if CEGUI_VERSION >= 0x000800
+#   include <CEGUI/Exceptions.h>
+#else
+#   include <CEGUIExceptions.h>
+#endif
+
+#include "Output.h"
+
+namespace orxonox
+{
+    Exception::Exception(const std::string& description, unsigned int lineNumber,
+                         const char* filename, const char* functionName)
+        : description_(description)
+        , lineNumber_(lineNumber)
+        , functionName_(functionName)
+        , filename_(filename)
+    { }
+
+    Exception::Exception(const std::string& description)
+        : description_(description)
+        , lineNumber_(0)
+    { }
+
+    const std::string& Exception::getFullDescription() const
+    {
+        if (fullDescription_.empty())
+        {
+            std::ostringstream fullDesc;
+
+            fullDesc << this->getTypeName() << "Exception";
+
+            if (!this->filename_.empty())
+            {
+                fullDesc << " in " << this->filename_;
+                if (this->lineNumber_)
+                    fullDesc << '(' << this->lineNumber_ << ')';
+            }
+
+            if (!this->functionName_.empty())
+                fullDesc << " in function '" << this->functionName_ << '\'';
+
+            fullDesc << ": ";
+            if (!this->description_.empty())
+                fullDesc << this->description_;
+            else
+                fullDesc << "No description available.";
+
+            this->fullDescription_ = fullDesc.str();
+        }
+
+        return fullDescription_;
+    }
+
+    const char* Exception::what() const throw()
+    {
+        return getDescription().c_str();
+    }
+
+    /*static*/ std::string Exception::handleMessage()
+    {
+        try
+        {
+            // rethrow
+            throw;
+        }
+        catch (const CEGUI::Exception& ex)
+        {
+            return GeneralException(ex.getMessage().c_str(), ex.getLine(),
+                ex.getFileName().c_str(), ex.getName().c_str()).getDescription();
+        }
+        catch (const std::exception& ex)
+        {
+            return ex.what();
+        }
+        catch (const char* ex)
+        {
+            return ex;
+        }
+        catch (...)
+        {
+            orxout(user_error) << "BIG WARNING: Unknown exception type encountered."
+                               << " Rethrowing" << endl;
+            throw;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/Exception.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Exception.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Exception.h	(revision 11817)
@@ -0,0 +1,195 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup ExceptionAssertion Exceptions and assertions
+    @ingroup Util
+*/
+
+/**
+@file
+@ingroup ExceptionAssertion
+@brief
+    Declaration of facilities to handle exceptions.
+@details
+    Any exception thrown should inherit from orxonox::Exception. There is a macro
+    \ref CREATE_ORXONOX_EXCEPTION to create a new exception (you can find a list of
+    available exceptions in the docs of this file). <br>
+    Throwing exception is also very simple:
+    @code
+        ThrowException(General, "Something went wrong");
+    @endcode
+    (\c General is a type of exception, see docs of this file) <br>
+    The exception will automatically contain information about file, line number
+    and function name it occurred in. <br><br>
+    There is also some magic you can do for numbers, etc.:
+    @code
+        ThrowException(General, "Error code: " << myInt << ". more info...");
+    @endcode
+    It works with an std::ostringstream, so you can feed it all sorts of values.
+*/
+
+#ifndef _Exception_H__
+#define _Exception_H__
+
+#include "UtilPrereqs.h"
+
+#include <exception>
+#include <sstream>
+#include <string>
+#include "Output.h"
+
+namespace orxonox
+{
+    /** Base class for all exceptions (derived from std::exception).
+    @details
+        This class provides support for information about the file, the line
+        and the function the error occurred.
+    @see Exception.h
+    */
+    class _UtilExport Exception : public std::exception
+    {
+    public:
+        /**
+        @brief
+            Creates the exception but doesn't yet compose the full descrption (because of the virtual functions)
+        @param description
+            Exception description as string. This message is supposed to help developers!
+        @param lineNumber
+            The number of the code-line in which the exception occurred
+        @param filename
+            The file in which the exception occurred
+        @param functionName
+            The function in which the exception occurred
+        */
+        Exception(const std::string& description, unsigned int lineNumber,
+                  const char* filename, const char* functionName);
+        //! Simplified constructor with just a description. If you need more, use the other one.
+        Exception(const std::string& description);
+
+        //! Needed for compatibility with std::exception
+        virtual ~Exception() throw() { }
+        //! Returns the error description
+        const char* what() const throw();
+
+        /** Returns a full description with type, line, file and function
+        @remarks
+            The composed full description gets stored to fullDescription_. But for compliance
+            with std::exception, this method has to be const. Hence fullDescription_ is declared
+            as mutable.
+        */
+        virtual const std::string& getFullDescription() const;
+        //! Returns the string name of the exception type
+        virtual std::string        getTypeName()        const = 0;
+        //! Returns the short developer written exception
+        virtual const std::string& getDescription()     const { return this->description_; }
+        //! Returns the line number on which the exception occurred.
+        virtual unsigned int getLineNumber()            const { return this->lineNumber_; }
+        //! Returns the function in which the exception occurred.
+        virtual const std::string& getFunctionName()    const { return this->functionName_; }
+        //! Returns the filename in which the exception occurred.
+        virtual const std::string& getFilename()        const { return this->filename_; }
+
+        /**
+        @brief
+            Retrieves information from an exception caught with "..."
+            Works for std::exception and CEGUI::Exception
+        @remarks
+            Never ever call this function without an exception in the stack!
+        */
+        static std::string handleMessage();
+
+    protected:
+        std::string description_;             //!< User typed text about why the exception occurred
+        unsigned int lineNumber_;             //!< Line on which the exception occurred
+        std::string functionName_;            //!< Function (including namespace and class) where the exception occurred
+        std::string filename_;                //!< File where the exception occurred
+        // mutable because "what()" is a const method
+        mutable std::string fullDescription_; //!< Full description with line, file and function
+    };
+
+//! Creates a new type of exception that inherits from orxonox::Exception
+#define CREATE_ORXONOX_EXCEPTION(ExceptionName)                                     \
+    class ExceptionName##Exception : public Exception                               \
+    {                                                                               \
+    public:                                                                         \
+        ExceptionName##Exception(const std::string& description,                    \
+                unsigned int lineNumber, const char* filename,                      \
+                const char* functionName)                                           \
+            : Exception(description, lineNumber, filename, functionName)            \
+        { }                                                                         \
+                                                                                    \
+        ExceptionName##Exception(const std::string& description)                    \
+            : Exception(description)                                                \
+        { }                                                                         \
+                                                                                    \
+        ~ExceptionName##Exception() throw() { }                                     \
+                                                                                    \
+        std::string getTypeName() const { return #ExceptionName; }                  \
+    }
+
+    // Creates all possible exception types.
+    // If you want to add a new type, simply copy and adjust a new line here.
+    CREATE_ORXONOX_EXCEPTION(General);
+    CREATE_ORXONOX_EXCEPTION(FileNotFound);
+    CREATE_ORXONOX_EXCEPTION(Argument);
+    CREATE_ORXONOX_EXCEPTION(PhysicsViolation);
+    CREATE_ORXONOX_EXCEPTION(ParseError);
+    CREATE_ORXONOX_EXCEPTION(PluginsNotFound);
+    CREATE_ORXONOX_EXCEPTION(InitialisationFailed);
+    CREATE_ORXONOX_EXCEPTION(InitialisationAborted);
+    CREATE_ORXONOX_EXCEPTION(NotImplemented);
+    CREATE_ORXONOX_EXCEPTION(GameState);
+    CREATE_ORXONOX_EXCEPTION(NoGraphics);
+    CREATE_ORXONOX_EXCEPTION(AbortLoading);
+
+    /** Helper function that forwards an exception and displays the message.
+    @details
+        This is necessary because only when using 'throw' the objects storage is managed.
+    */
+    template <class T>
+    inline const T& exceptionThrowerHelper(const T& exception)
+    {
+        // let the catcher decide whether to display the message also to the user
+        orxout(internal_error) << exception.getFullDescription() << endl;
+        return exception;
+    }
+
+/** Throws an exception and logs a message beforehand.
+@param type
+    Type of the exception as literal (General, Initialisation, etc.)
+@param description
+    Exception description as string
+@see Exception.h
+*/
+#define ThrowException(type, description) \
+    throw orxonox::exceptionThrowerHelper(type##Exception(static_cast<std::ostringstream&>(std::ostringstream().flush() << description).str(), __LINE__, __FILE__, __FUNCTIONNAME__))
+
+} /* namespace orxonox */
+
+#endif /* _Exception_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/ExprParser.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/ExprParser.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/ExprParser.cc	(revision 11817)
@@ -0,0 +1,463 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+  @file
+  @brief Declaration of FloatParser
+*/
+
+#include "ExprParser.h"
+
+#include <cmath>
+#include <cstring>
+#include <cstdlib>
+#include "Math.h"
+
+// macros for easier if, else statements
+#define CASE_1(var) if (!strcmp(SWITCH,var))
+#define CASE(var) else if (!strcmp(SWITCH,var))
+#define CASE_ELSE else
+
+//! skip white spaces
+#define PARSE_BLANKS while (*reading_stream == ' ') ++reading_stream
+
+namespace orxonox
+{
+    ExprParser::ExprParser()
+    {
+        this->failed_ = false;
+        this->variables_["pi"] = math::pi;
+        this->variables_["e"] = math::e;
+    }
+
+    void ExprParser::setVariable(const std::string& varname, float value)
+    {
+        this->variables_[varname] = value;
+    }
+
+    void ExprParser::parse(const std::string& str)
+    {
+        this->reading_stream = str.c_str();
+        if (str.size() == 0 || *reading_stream == '\0')
+        {
+            this->failed_ = true;
+            this->result_ = 0.0;
+        }
+        else
+        {
+            this->result_ = parse_expr_8();
+            this->remains_ = reading_stream;
+        }
+    }
+
+    //Private functions:
+    /******************/
+    float ExprParser::parse_argument()
+    {
+        float value = parse_expr_8();
+        if (*reading_stream == ',')
+        {
+            ++reading_stream;
+            return value;
+        }
+        else
+        {
+            this->failed_ = true;
+            return 0;
+        }
+    }
+
+    float ExprParser::parse_last_argument()
+    {
+        float value = parse_expr_8();
+        if (*reading_stream == ')')
+        {
+            ++reading_stream;
+            return value;
+        }
+        else
+        {
+            this->failed_ = true;
+            return 0;
+        }
+    }
+
+    float ExprParser::parse_expr_8()
+    {
+        float value = parse_expr_7();
+        for(;;)
+        {
+            switch (op)
+            {
+            case oder:
+                value = parse_expr_7() || value;
+                break;
+            default: return value;
+            }
+        };
+    }
+
+
+    float ExprParser::parse_expr_7()
+    {
+        float value = parse_expr_6();
+        for(;;)
+        {
+            switch (op)
+            {
+            case und:
+                value = value && parse_expr_6();
+                break;
+            default: return value;
+            }
+        };
+    }
+
+    float ExprParser::parse_expr_6()
+    {
+        float value = parse_expr_5();
+        for(;;)
+        {
+            switch (op)
+            {
+            case gleich:
+                value = (value == parse_expr_5());
+                break;
+            case ungleich:
+                value = (value != parse_expr_5());
+                break;
+            default:
+                return value;
+            }
+        };
+    }
+
+    float ExprParser::parse_expr_5()
+    {
+        float value = parse_expr_4();
+        for(;;)
+        {
+            switch (op)
+            {
+            case kleiner:
+                value = (value < parse_expr_4());
+                break;
+            case kleinergleich:
+                value = (value <= parse_expr_4());
+                break;
+            case groesser:
+                value = (value > parse_expr_4());
+                break;
+            case groessergleich:
+                value = (value >= parse_expr_4());
+                break;
+            default:
+                return value;
+            }
+        };
+    }
+
+    float ExprParser::parse_expr_4()
+    {
+        float value = parse_expr_3();
+        for(;;)
+        {
+            switch (op)
+            {
+            case b_plus:
+                value += parse_expr_3();
+                break;
+            case b_minus:
+                value -= parse_expr_3();
+                break;
+            default:
+                return value;
+            }
+        };
+    }
+
+    float ExprParser::parse_expr_3()
+    {
+        float value = parse_expr_2();
+        for(;;)
+        {
+            switch (op)
+            {
+            case mal:
+                value *= parse_expr_2();
+                break;
+            case durch:
+                value /= parse_expr_2();
+                break;
+            case modulo:
+                {
+                    float temp = parse_expr_2();
+                    value = value - floor(value/temp)*temp;
+                    break;
+                }
+            default:
+                return value;
+            }
+        };
+    }
+
+    float ExprParser::parse_expr_2()
+    {
+        float value = parse_expr_1();
+        while (*reading_stream != '\0')
+        {
+            op = parse_binary_operator();
+            switch (op)
+            {
+            case hoch:
+                value = pow(value,parse_expr_1());
+                break;
+            default:
+                return value;
+            }
+        };
+        op = undef;
+        return value;
+    }
+
+    float ExprParser::parse_expr_1()
+    {
+        PARSE_BLANKS;
+        float value;
+
+        unary_operator op = parse_unary_operator();
+        PARSE_BLANKS;
+
+        if (*reading_stream == '\0')
+        {
+            // end of string
+            this->failed_ = true;
+            return 0;
+        }
+        else if ((*reading_stream > 47 && *reading_stream < 59) || *reading_stream == 46)
+        {  // number
+            value = (float)strtod(reading_stream, const_cast<char**>(&reading_stream));
+        }
+        else if ((*reading_stream > 64 && *reading_stream < 91) || (*reading_stream > 96 && *reading_stream < 123) || *reading_stream == 46)
+        {  // variable or function
+            char* word = new char[256];
+            parse_word(word);
+            PARSE_BLANKS;
+            if (*reading_stream == '(')
+            {
+                ++reading_stream;
+#define SWITCH word
+                CASE_1("sin")
+                    value = sin(parse_last_argument());
+                CASE("asin")
+                    value = asin(parse_last_argument());
+                CASE("sinh")
+                    value = sinh(parse_last_argument());
+                CASE("asinh")
+                {
+                    value = parse_last_argument();
+                    value = log(sqrt(pow(value, 2) + 1) + value);
+                }
+                CASE("cos")
+                    value = cos(parse_last_argument());
+                CASE("acos")
+                    value = acos(parse_last_argument());
+                CASE("cosh")
+                    value = cosh(parse_last_argument());
+                CASE("acosh")
+                {
+                    value = parse_last_argument();
+                    value = log(sqrt(pow(value, 2) - 1) + value);
+                }
+                CASE("tan")
+                    value = tan(parse_last_argument());
+                CASE("atan")
+                    value = atan(parse_last_argument());
+                CASE("atan2")
+                    value = atan2(parse_argument(),parse_last_argument());
+                CASE("tanh")
+                    value = tanh(parse_last_argument());
+                CASE("atanh")
+                {
+                    value = parse_last_argument();
+                    value = 0.5f*log((value + 1.0f)/(value - 1.0f));
+                }
+                CASE("int")
+                    value = floor(parse_last_argument());
+                CASE("floor")
+                    value = floor(parse_last_argument());
+                CASE("ceil")
+                    value = ceil(parse_last_argument());
+                CASE("abs")
+                    value = fabs(parse_last_argument());
+                CASE("exp")
+                    value = exp(parse_last_argument());
+                CASE("log")
+                    value = log10(parse_last_argument());
+                CASE("ln")
+                    value = log(parse_last_argument());
+                CASE("sign")
+                {
+                    value = parse_last_argument();
+                    value = (value>0.0f ? 1.0f : (value<0.0f ? -1.0f : 0.0f));
+                }
+                CASE("sqrt")
+                    value = sqrt(parse_last_argument());
+                CASE("degrees")
+                    value = parse_last_argument()*180.0f/math::pi;
+                CASE("radians")
+                    value = parse_last_argument()*math::pi/180.0f;
+                CASE("mod")
+                {
+                    value = parse_argument();
+                    float value2 = parse_last_argument();
+                    value = value - floor(value/value2)*value2;
+                }
+                CASE("pow")
+                    value = pow(parse_argument(),parse_last_argument());
+                CASE("div")
+                    value = floor(parse_argument()/parse_last_argument());
+                CASE("max")
+                    value = std::max(parse_argument(),parse_last_argument());
+                CASE("min")
+                    value = std::min(parse_argument(),parse_last_argument());
+                CASE_ELSE
+                {
+                    this->failed_ = true;
+                    delete[] word;
+                    return 0;
+                }
+            }
+            else
+            {
+                std::map<std::string, float>::const_iterator it = this->variables_.find(word);
+                if (it != this->variables_.end())
+                    value = it->second;
+                else
+                {
+                    this->failed_ = true;
+                    delete[] word;
+                    return 0;
+                }
+            }
+            delete[] word;
+        }
+        else if (*reading_stream == 40)
+        {  // expression in parenthesis
+            ++reading_stream;
+            value = parse_last_argument();
+        }
+        else
+        {
+            this->failed_ = true;
+            return 0;
+        }
+
+        PARSE_BLANKS;
+        switch (op)
+        {
+        case u_nicht: return !value;
+        case u_plus:  return  value;
+        case u_minus: return -value;
+        default:
+            this->failed_ = true;
+            return 0;
+        }
+    }
+
+    void ExprParser::parse_word(char* str)
+    {
+        char* word = str;
+        int counter = 0;
+        while ((*reading_stream > 47 && *reading_stream < 58) || (*reading_stream > 64 && *reading_stream < 91) || (*reading_stream > 96 && *reading_stream < 123) || *reading_stream == 46)
+        {
+            *word++ = *reading_stream++;
+            counter++;
+            if (counter > 255)
+            {
+                this->failed_ = true;
+                return;
+            }
+        };
+        *word = '\0';
+    }
+
+    ExprParser::binary_operator ExprParser::parse_binary_operator()
+    {
+        binary_operator op;
+        switch (*reading_stream)
+        {
+        case '+': op = b_plus; break;
+        case '-': op = b_minus; break;
+        case '*': op = mal; break;
+        case '/': op = durch; break;
+        case '^': op = hoch; break;
+        case '%': op = modulo; break;
+        case '&': op = und; break;
+        case '|': op = oder; break;
+        case '=': op = gleich; break;
+        case '!': op = b_nicht; break;
+        case '<': op = kleiner; break;
+        case '>': op = groesser; break;
+        default: return undef;
+        }
+        if (*++reading_stream == '=')
+        {
+            if (op > 9)
+            {
+                ++reading_stream;
+                return (binary_operator)(op + 3);
+            }
+            else
+            {
+                --reading_stream;
+                return undef;
+            }
+        }
+        else
+            return op;
+    }
+
+    ExprParser::unary_operator ExprParser::parse_unary_operator()
+    {
+        switch (*reading_stream)
+        {
+        case '!':
+            ++reading_stream;
+            return u_nicht;
+        case '+':
+            ++reading_stream;
+            return u_plus;
+        case '-':
+            ++reading_stream;
+            return u_minus;
+        default :
+            return u_plus;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/ExprParser.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/ExprParser.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/ExprParser.h	(revision 11817)
@@ -0,0 +1,164 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@ingroup Util
+@brief Declaration of FloatParser
+*/
+
+#ifndef _FloatParser_H__
+#define _FloatParser_H__
+
+#include "UtilPrereqs.h"
+
+#include <map>
+#include <string>
+
+namespace orxonox
+{
+    /** Parser for expressions like \c "3 * cos(5 + 4) / a" where \a a is a predeclared
+        variable.
+    @par Usage
+        Using it is rather simple:
+        @code
+        std::string str("3 + 4");
+        ExprParser expr;
+        expr.parse(str);
+        if (expr.getSuccess())
+        {
+            if (!expr.getRemains().empty())
+            {
+                orxout(user_warning) << "Expression could not be parsed to the end! Remains: '" << expr.getRemains() << '\'' << endl;
+            }
+            float result = expr.getResult();
+        }
+        else
+            orxout(user_error) << "Cannot calculate expression: Parse error." << endl;
+        @endcode
+        getRemains() returns the expression after what could be parsed. For instance
+        \c "2*3 text" will return \c "text" as remains.
+    @details
+        The implementation of this class is really old and sort of a trial for
+        a first C++ class by Reto. That explains why it looks more like C than
+        C++... Also some of the variable names are in German. <br>
+        Explaining how it works exactly is probably not possible anymore, but it
+        is based on recursively parsing the expression character by character.
+        That much I can remember.
+    @par Functions, operators and variables supported
+        - Variables:
+            - e
+            - pi
+        - Functions:
+            - sin, asin, sinh, asinh
+            - cos, acos, cosh, acosh
+            - tan, atan, tanh, atanh
+            - int, floor, ceil, abs, sign
+            - pow, sqrt, exp, ln, log
+            - mod, div
+            - min, max
+            - radians, degrees
+        - Operators:
+            - +, -, ! (unary)
+            - +, -, *, /, %, ^, |, &, !, <, >, !=, <=, >=, =
+    @note
+        Operators may not be very consistent with C++ rules, but using the class
+        for plus and minus should be perfectly ok.
+    */
+    class _UtilExport ExprParser
+    {
+    public:
+        enum binary_operator
+        {
+            b_plus,
+            b_minus,
+            mal,
+            durch,
+            modulo,
+            hoch,
+            undef,
+            oder,
+            und,
+            gleich,
+            b_nicht,
+            kleiner,
+            groesser,
+            ungleich,
+            kleinergleich,
+            groessergleich
+        };
+
+        enum unary_operator
+        {
+            u_plus,
+            u_minus,
+            u_nicht
+        };
+
+
+        ExprParser();
+        void parse(const std::string& str);
+        const std::string& getRemains() { return  this->remains_; }
+        float              getResult()  { return  this->result_; }
+        bool               getSuccess() { return !this->failed_; }
+
+        void setVariable(const std::string& varname, float value);
+
+    private:
+        float parse_expr_1();
+        float parse_expr_2();
+        float parse_expr_3();
+        float parse_expr_4();
+        float parse_expr_5();
+        float parse_expr_6();
+        float parse_expr_7();
+        float parse_expr_8();
+        void parse_word(char* str);
+        binary_operator parse_binary_operator();
+        unary_operator parse_unary_operator();
+
+        float parse_argument();
+        float parse_last_argument();
+
+        binary_operator op;
+        const char* reading_stream;
+        bool failed_;
+        float result_;
+        std::string remains_;
+        std::map<std::string, float> variables_;
+    };
+
+    //Endzeichen für float expression: ')', '}', ']', ',', ';'
+    _UtilExport bool parse_float(char* const, char**, float*);
+    //Endzeichen angegeben
+    _UtilExport bool parse_float(char* const, char**, char, float*);
+    //Letzter Teil-float eines Vektors parsen (keine Vergleichs- und Logikoperationen)
+    _UtilExport bool parse_vector_float(char* const, char**, bool, float*);
+}
+
+#endif /* _FloatParser_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Math.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Math.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Math.cc	(revision 11817)
@@ -0,0 +1,524 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Wolfgang Roenninger
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of several math-functions.
+*/
+
+#include "Math.h"
+
+#include <OgrePlane.h>
+
+#include "MathConvert.h"
+#include "SubString.h"
+
+namespace orxonox
+{
+#if OGRE_VERSION < 0x010603
+    /**
+        @brief Function for writing a Radian to a stream.
+    */
+    std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian)
+    {
+        out << radian.valueRadians();
+        return out;
+    }
+
+    /**
+        @brief Function for writing a Degree to a stream.
+    */
+    std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree)
+    {
+        out << degree.valueDegrees();
+        return out;
+    }
+#endif
+
+    /**
+        @brief Function for reading a Radian from a stream.
+    */
+    std::istream& operator>>(std::istream& in, orxonox::Radian& radian)
+    {
+        float temp;
+        in >> temp;
+        radian = temp;
+        return in;
+    }
+
+    /**
+        @brief Function for reading a Degree from a stream.
+    */
+    std::istream& operator>>(std::istream& in, orxonox::Degree& degree)
+    {
+        float temp;
+        in >> temp;
+        degree = temp;
+        return in;
+    }
+
+
+    /**
+        @brief Gets the angle between my viewing direction and the direction to the position of the other object.
+        @param myposition My position
+        @param mydirection My viewing direction
+        @param otherposition The position of the other object
+        @return The angle in radian
+
+        Examples:
+         - If the other object is exactly in front of me, the function returns 0.
+         - If the other object is exactly behind me, the function returns pi.
+         - If the other object is exactly right/left to me (or above/below), the function returns pi/2.
+    */
+    float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition)
+    {
+        orxonox::Vector3 distance = otherposition - myposition;
+        float distancelength = distance.length();
+        if (distancelength == 0)
+            return 0;
+        else
+            return acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1));
+    }
+
+    /**
+        @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object.
+        @param myposition My position
+        @param mydirection My viewing direction
+        @param myorthonormal My orthonormalvector (pointing upwards through my head)
+        @param otherposition The position of the other object
+        @return The viewing direction
+
+        Examples:
+         - If the other object is exactly in front of me, the function returns <tt>Vector2(0, 0)</tt>.
+         - If the other object is exactly at my left, the function returns <tt>Vector2(-1, 0)</tt>.
+         - If the other object is exactly at my right, the function returns <tt>Vector2(1, 0)</tt>.
+         - If the other object is only a bit at my right, the function still returns <tt>Vector2(1, 0)</tt>.
+         - If the other object is exactly above me, the function returns <tt>Vector2(0, 1)</tt>.
+    */
+    orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
+    {
+        orxonox::Vector3 distance = otherposition - myposition;
+
+        // project difference vector on our plane
+        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
+
+        float projectionlength = projection.length();
+        if (projectionlength == 0)
+        {
+            if (myposition.dotProduct(otherposition) >= 0)
+                return orxonox::Vector2(0, 0);
+            else
+                return orxonox::Vector2(0, 1);
+        }
+
+        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
+        float sin_value = sqrt( 1 - cos_value*cos_value );
+
+        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
+            return orxonox::Vector2( sin_value, cos_value );
+        else
+            return orxonox::Vector2( -sin_value, cos_value );
+    }
+
+    /**
+        @brief Gets the 2D viewing direction (up/down, left/right) to the position of the other object, multiplied with the viewing distance to the object (0° = 0, 180° = 1).
+        @param myposition My position
+        @param mydirection My viewing direction
+        @param myorthonormal My orthonormalvector (pointing upwards through my head)
+        @param otherposition The position of the other object
+        @return The viewing direction
+
+        Examples:
+         - If the other object is exactly in front of me, the function returns <tt>Vector2(0, 0)</tt>.
+         - If the other object is exactly at my left, the function returns <tt>Vector2(-0.5, 0)</tt>.
+         - If the other object is exactly at my right, the function returns <tt>Vector2(0.5, 0)</tt>.
+         - If the other object is only a bit at my right, the function still returns <tt>Vector2(0.01, 0)</tt>.
+         - If the other object is exactly above me, the function returns <tt>Vector2(0, 0.5)</tt>.
+    */
+    orxonox::Vector2 get2DViewCoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition)
+    {
+        orxonox::Vector3 distance = otherposition - myposition;
+
+        // project difference vector on our plane
+        orxonox::Vector3 projection = Ogre::Plane(mydirection, myposition).projectVector(distance);
+
+        float projectionlength = projection.length();
+        if (projectionlength == 0)
+        {
+            if (myposition.dotProduct(otherposition) >= 0)
+                return orxonox::Vector2(0, 0);
+            else
+                return orxonox::Vector2(0, 1);
+        }
+        //float angle = acos(clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1));
+
+        float cos_value = clamp<float>(myorthonormal.dotProduct(projection) / projectionlength, -1, 1);
+        float sin_value = sqrt( 1 - cos_value*cos_value );
+
+        float distancelength = distance.length();
+        if (distancelength == 0) return orxonox::Vector2(0, 0);
+        float radius = acos(clamp<float>(mydirection.dotProduct(distance) / distancelength, -1, 1)) / math::pi;
+
+        if ((mydirection.crossProduct(myorthonormal)).dotProduct(distance) > 0)
+            return orxonox::Vector2( sin_value * radius, cos_value * radius);
+        else
+            return orxonox::Vector2( -sin_value * radius, cos_value * radius);
+    }
+
+
+    /**
+            @brief Gets the 2D project vector for the 3D Radar .
+            @param myposition My position
+            @param mydirection My viewing direction
+            @param myorthonormal My orthonormalvector (pointing upwards through my head)
+            @param otherposition The position of the other object
+            @param mapangle The angle between line of sight on screen and the 3Dmap-x/z-plain in radian
+            @param detectionlimit The limit in which objects are shown on the map
+            @return The viewing direction
+    */
+    orxonox::Vector2 get3DProjection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float mapangle, const float detectionlimit)
+    {
+        // Orxonox Vectors: x_direction you are looking, y_direction points up, z_direction points to the right
+        orxonox::Vector3 distance = otherposition - myposition; // get vector from Ship to object
+
+        // new coordinate system: x_axsis: mydirection   (points front)
+        //                        y_axsis: myorthonormal (points up)
+        //                        z_axsis: myside        (points right)
+
+        orxonox::Vector3 myside = mydirection.crossProduct(myorthonormal); // get 3. base vector
+
+        distance = 4*distance / detectionlimit; // shrink vector on map
+        if(distance.length() > 1.0f) // if object would wander outside of the map
+        {
+            distance = distance / distance.length();
+        }
+
+        // perform a coordinate transformation to get distance in relation of the position of the ship
+        orxonox::Vector3 distanceShip = getTransformedVector(distance, mydirection, myorthonormal, myside);
+
+        // calculate 2D vector on the map (with angle between x/z - plain and line of sight)
+        float xcoordinate = distanceShip.z; // z; cause x direction on screen is to the right side
+        float ycoordinate = distanceShip.x*sin(mapangle)+distanceShip.y*cos(mapangle);
+        return orxonox::Vector2(xcoordinate , ycoordinate);
+    }
+
+    /**
+               @brief Gets if a object is over the x/z - plain on map
+               @param myposition My position
+               @param mydirection My viewing direction
+               @param myorthonormal My orthonormalvector (pointing upwards through my head)
+               @param otherposition The position of the other object
+               @param mapangle The angle you look on the 3Dmap in radian
+               @return If distancevector to the other object has a positive y-coordinate
+
+               Examples:
+                Returns true if object is over x/z - plain
+                Returns false if object is below x/z -plain
+    */
+    bool isObjectHigherThanShipOnMap(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float mapangle)
+    {
+        // Orxonox Vectors: x_direction you are looking, y_direction points up, z_direction points to the right
+        orxonox::Vector3 distance = otherposition - myposition;
+
+        // new coordinate system: x_axsis: mydirection   (points front)
+        //                        y_axsis: myorthonormal (points up)
+        //                        z_axsis: myside        (points right)
+
+        orxonox::Vector3 myside = mydirection.crossProduct(myorthonormal); // get vector from Ship to object
+
+
+        // perform a coordinate transformation to get distance in relation of the position of the ship
+        orxonox::Vector3 distanceShip = getTransformedVector(distance, mydirection, myorthonormal, myside);
+
+        if(distanceShip.y >= 0)
+            return true;
+        else
+            return false;
+    }
+
+    /**
+                   @brief A value between 0 and 10, in order how other object is in front or in back
+                   @param myposition My position
+                   @param mydirection My viewing direction
+                   @param myorthonormal My orthonormalvector (pointing upwards through my head)
+                   @param otherposition The position of the other object
+                   @param detectionlimit The limit in which objects are shown on the map
+                   @return value between 0 and 100
+    */
+    int determineMap3DZOrder(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float detectionlimit)
+    {
+        orxonox::Vector3 distance = otherposition - myposition; // get vector from Ship to object
+        orxonox::Vector3 myside = mydirection.crossProduct(myorthonormal); // get vector to the side
+
+        distance = 4*distance / detectionlimit; // shrink vector on map
+        if(distance.length() > 1.0f) // if object would wander outside of the map
+        {
+            distance = distance / distance.length();
+        }
+
+        // perform a coordinate transformation to get distance in relation of the position of the ship
+        orxonox::Vector3 distanceShip = getTransformedVector(distance, mydirection, myorthonormal, myside);
+
+        return static_cast<int>(50 - 100*distanceShip.x);
+    }
+
+
+    /**
+                @brief Gets the new vector after a coordinate transformation
+                @param totransform Vector which will be transformed
+                @param newx New x basevector
+                @param newy New y basevector
+                @param newz New z basevector
+                @return Vector in the new coordinates
+
+                x is vector in old coordinates
+                y is vector in old coordinates
+                T is transform matrix with:
+                    T = (t1 , t2 , t3)
+                    t1 = mydirection
+                    t2 = myorthonormal
+                    t3 = myside
+
+                y = T^(-1)*x
+            */
+    orxonox::Vector3 getTransformedVector(const orxonox::Vector3& totransform, const orxonox::Vector3& newx, const orxonox::Vector3& newy, const orxonox::Vector3& newz)
+    {
+        // inverse of the transform matrix
+        float determinant = +newx.x * (newy.y*newz.z - newz.y*newy.z)
+                            -newx.y * (newy.x*newz.z - newy.z*newz.x)
+                            +newx.z * (newy.x*newz.y - newy.y*newz.x);
+        float invdet = 1/determinant;
+
+        // transform matrix
+        orxonox::Vector3 xinvtransform;
+        orxonox::Vector3 yinvtransform;
+        orxonox::Vector3 zinvtransform;
+
+        xinvtransform.x = (newy.y * newz.z        - newz.y        * newy.z)*invdet;
+        xinvtransform.y = (newx.z   * newz.y        - newx.y   * newz.z       )*invdet;
+        xinvtransform.z = (newx.y   * newy.z - newx.z   * newy.y)*invdet;
+        yinvtransform.x = (newy.z * newz.x        - newy.x * newz.z       )*invdet;
+        yinvtransform.y = (newx.x   * newz.z        - newx.z   * newz.x       )*invdet;
+        yinvtransform.z = (newy.x * newx.z   - newx.x   * newy.z)*invdet;
+        zinvtransform.x = (newy.x * newz.y        - newz.x        * newy.y)*invdet;
+        zinvtransform.y = (newz.x        * newx.y   - newx.x   * newz.y       )*invdet;
+        zinvtransform.z = (newx.x   * newy.y - newy.x * newx.y  )*invdet;
+
+        // coordinate transformation
+        orxonox::Vector3 distanceShip;
+        distanceShip.x = xinvtransform.x * totransform.x + yinvtransform.x * totransform.y + zinvtransform.x * totransform.z;
+        distanceShip.y = xinvtransform.y * totransform.x + yinvtransform.y * totransform.y + zinvtransform.y * totransform.z;
+        distanceShip.z = xinvtransform.z * totransform.x + yinvtransform.z * totransform.y + zinvtransform.z * totransform.z;
+
+        return distanceShip;
+    }
+
+    /**
+        @brief Returns the predicted position I have to aim at, if I want to hit a moving target with a moving projectile.
+        @param myposition My position
+        @param projectilespeed The speed of my projectile
+        @param targetposition The position of my target
+        @param targetvelocity The velocity of my target
+        @return The predicted position
+
+        The function predicts the position based on a linear velocity of the target. If the target changes speed or direction, the projectile will miss.
+    */
+    orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity)
+    {
+        orxonox::Vector3 distance = targetposition - myposition;
+        float a = distance.squaredLength();
+        float b = 2 * (distance.x * targetvelocity.x + distance.y * targetvelocity.y + distance.z * targetvelocity.z);
+        float c = targetvelocity.squaredLength() - projectilespeed * projectilespeed;
+
+        float discriminant = b*b - 4*a*c;
+        if (discriminant < 0)
+            return orxonox::Vector3::ZERO; // solution is undefined (e.g. target faster than projectile)
+
+        if (a == 0.0f)
+            return orxonox::Vector3::ZERO; // avoid division by zero
+        float solution = (-b + sqrt(discriminant)) / (2 * a);
+
+        if (solution == 0.0f)
+            return orxonox::Vector3::ZERO; // avoid division by zero
+        float time = 1.0f / solution;
+
+        return (targetposition + targetvelocity * time);
+    }
+
+
+    namespace detail
+    {
+        std::mt19937 rngen;
+    }
+
+    /**
+        @brief Returns a unique number. This function will never return the same value twice.
+    */
+    unsigned long getUniqueNumber()
+    {
+        static unsigned long aNumber = 135;
+        return aNumber++;
+    }
+
+
+    //////////////////////////
+    // Conversion functions //
+    //////////////////////////
+
+    // std::string to Vector2
+    bool ConverterFallback<std::string, orxonox::Vector2>::convert(orxonox::Vector2* output, const std::string& input)
+    {
+        size_t opening_parenthesis, closing_parenthesis = input.find('}');
+        if ((opening_parenthesis = input.find('{')) == std::string::npos)
+            opening_parenthesis = 0;
+        else
+            opening_parenthesis++;
+
+        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
+                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
+        if (tokens.size() >= 2)
+        {
+            if (!convertValue(&(output->x), tokens[0]))
+                return false;
+            if (!convertValue(&(output->y), tokens[1]))
+                return false;
+
+            return true;
+        }
+        return false;
+    }
+
+    // std::string to Vector3
+    bool ConverterFallback<std::string, orxonox::Vector3>::convert(orxonox::Vector3* output, const std::string& input)
+    {
+        size_t opening_parenthesis, closing_parenthesis = input.find('}');
+        if ((opening_parenthesis = input.find('{')) == std::string::npos)
+            opening_parenthesis = 0;
+        else
+            opening_parenthesis++;
+
+        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
+                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
+        if (tokens.size() >= 3)
+        {
+            if (!convertValue(&(output->x), tokens[0]))
+                return false;
+            if (!convertValue(&(output->y), tokens[1]))
+                return false;
+            if (!convertValue(&(output->z), tokens[2]))
+                return false;
+
+            return true;
+        }
+        return false;
+    }
+
+    // std::string to Vector4
+    bool ConverterFallback<std::string, orxonox::Vector4>::convert(orxonox::Vector4* output, const std::string& input)
+    {
+        size_t opening_parenthesis, closing_parenthesis = input.find('}');
+        if ((opening_parenthesis = input.find('{')) == std::string::npos)
+            opening_parenthesis = 0;
+        else
+            opening_parenthesis++;
+
+        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis),
+                         ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
+        if (tokens.size() >= 4)
+        {
+            if (!convertValue(&(output->x), tokens[0]))
+                return false;
+            if (!convertValue(&(output->y), tokens[1]))
+                return false;
+            if (!convertValue(&(output->z), tokens[2]))
+                return false;
+            if (!convertValue(&(output->w), tokens[3]))
+                return false;
+
+            return true;
+        }
+        return false;
+    }
+
+    // std::string to Quaternion
+    bool ConverterFallback<std::string, orxonox::Quaternion>::convert(orxonox::Quaternion* output, const std::string& input)
+    {
+        size_t opening_parenthesis, closing_parenthesis = input.find('}');
+        if ((opening_parenthesis = input.find('{')) == std::string::npos)
+            opening_parenthesis = 0;
+        else
+            opening_parenthesis++;
+
+        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
+        if (tokens.size() >= 4)
+        {
+            if (!convertValue(&(output->w), tokens[0]))
+                return false;
+            if (!convertValue(&(output->x), tokens[1]))
+                return false;
+            if (!convertValue(&(output->y), tokens[2]))
+                return false;
+            if (!convertValue(&(output->z), tokens[3]))
+                return false;
+
+            return true;
+        }
+        return false;
+    }
+
+    // std::string to ColourValue
+    bool ConverterFallback<std::string, orxonox::ColourValue>::convert(orxonox::ColourValue* output, const std::string& input)
+    {
+        size_t opening_parenthesis, closing_parenthesis = input.find('}');
+        if ((opening_parenthesis = input.find('{')) == std::string::npos)
+            opening_parenthesis = 0;
+        else
+            opening_parenthesis++;
+
+        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
+        if (tokens.size() >= 3)
+        {
+            if (!convertValue(&(output->r), tokens[0]))
+                return false;
+            if (!convertValue(&(output->g), tokens[1]))
+                return false;
+            if (!convertValue(&(output->b), tokens[2]))
+                return false;
+            if (tokens.size() >= 4)
+            {
+                if (!convertValue(&(output->a), tokens[3]))
+                    return false;
+            }
+            else
+                output->a = 1.0;
+
+            return true;
+        }
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/Math.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Math.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Math.h	(revision 11817)
@@ -0,0 +1,316 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Wolfgang Roenninger
+ *
+ */
+
+/**
+    @defgroup Math Mathematical functions
+    @ingroup Util
+*/
+
+/**
+    @file
+    @ingroup Math
+    @brief Declaration and implementation of several math-functions, typedefs of some Ogre::Math classes to the orxonox namespace.
+*/
+
+#ifndef _Util_Math_H__
+#define _Util_Math_H__
+
+#include "UtilPrereqs.h"
+
+#include <string>
+#include <cmath>
+#include <cstdlib>
+#include <random>
+#include <type_traits>
+
+#include <OgreMath.h>
+#include <OgreVector2.h>
+#include <OgreVector3.h>
+#include <OgreVector4.h>
+#include <OgreQuaternion.h>
+#include <OgreColourValue.h>
+
+// Certain headers might define unwanted macros...
+#undef max
+#undef min
+#undef sgn
+#undef clamp
+#undef sqrt
+#undef square
+#undef mod
+#undef rnd
+
+namespace orxonox
+{
+    /** Often used numerical constants because C++ doesn't define any.
+    @note
+        The values here are decimal representations of the approximate floating
+        point value as it is stored according to the IEEE 754 standard.
+    */
+    namespace math
+    {
+        constexpr float twoPi   = 6.283185482025146484375f;     ///< PI * 2
+        constexpr float pi      = 3.1415927410125732421875f;    ///< PI
+        constexpr float pi_2    = 1.57079637050628662109375f;   ///< PI / 2
+        constexpr float pi_4    = 0.785398185253143310546875f;  ///< PI / 4
+        constexpr float e       = 2.718281269073486328125f;     ///< e
+        constexpr float sqrt2   = 1.41421353816986083984375f;   ///< sqrt(2)
+        constexpr float sqrt2_2 = 0.707106769084930419921875f;  ///< sqrt(2) / 2
+    }
+
+#if OGRE_VERSION < 0x010603
+    _UtilExport std::ostream& operator<<(std::ostream& out, const orxonox::Radian& radian);
+    _UtilExport std::ostream& operator<<(std::ostream& out, const orxonox::Degree& degree);
+#endif
+    _UtilExport std::istream& operator>>(std::istream& in, orxonox::Radian& radian);
+    _UtilExport std::istream& operator>>(std::istream& in, orxonox::Degree& degree);
+
+    _UtilExport float getAngle(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& otherposition);
+    _UtilExport orxonox::Vector2 get2DViewdirection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition);
+    _UtilExport orxonox::Vector2 get2DViewCoordinates(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition);
+    _UtilExport orxonox::Vector2 get3DProjection(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float mapangle, const float detectionlimit);
+    _UtilExport bool isObjectHigherThanShipOnMap(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float mapangle);
+    _UtilExport int determineMap3DZOrder(const orxonox::Vector3& myposition, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& otherposition, const float detectionlimit);
+    _UtilExport orxonox::Vector3 getTransformedVector(const orxonox::Vector3& distance, const orxonox::Vector3& mydirection, const orxonox::Vector3& myorthonormal, const orxonox::Vector3& myside);
+    _UtilExport orxonox::Vector3 getPredictedPosition(const orxonox::Vector3& myposition, float projectilespeed, const orxonox::Vector3& targetposition, const orxonox::Vector3& targetvelocity);
+
+    /**
+        @brief Returns the sign of the given value.
+        @param x The value
+        @return 1 if the value is positive or zero, -1 if the value is negative
+    */
+    template <typename T>
+    constexpr inline T sgn(T x)
+    {
+        return (x >= 0) ? (T)1 : (T)-1;
+    }
+
+    /**
+        @brief Keeps a value between a lower and an upper limit. Values beyond these limits are limited to either @a min or @a max.
+        @param x The value
+        @param min The lower limit
+        @param max The upper limit
+    */
+    template <typename T>
+    constexpr inline T clamp(T x, T min, T max)
+    {
+        return x < min ? min : (x > max ? max : x);
+    }
+
+    /**
+        @brief Returns the squared value (x^2).
+    */
+    template <typename T>
+    constexpr inline T square(T x)
+    {
+        return x*x;
+    }
+
+    /**
+        @brief Returns the cubed value (x^3).
+    */
+    template <typename T>
+    constexpr inline T cube(T x)
+    {
+        return x*x*x;
+    }
+
+    /**
+        @brief The modulo operation, enhanced to work properly with negative values.
+        @param x The value
+        @param max The operand
+
+        The built in modulo operator % yields a strange behavior with negative values.
+        This function corrects this - the result is guaranteed to lie always between
+        zero and (max-1).
+
+        Example:
+        @code
+        int var = 11 % 10;      //  1
+        int var = -1 % 10;      // -1
+
+        int var = mod(11, 10);  //  1
+        int var = mod(-1, 10);  //  9
+        @endcode
+    */
+    template <typename T>
+    inline int mod(T x, int max)
+    {
+        if (x >= 0)
+            return (x % max);
+        else
+        {
+            T temp = x % max;
+            return (temp < 0) ? (temp + max) : temp;
+        }
+    }
+
+    /**
+        @brief Returns a "zero" value for the given type.
+        @note This is the default template of the zeroise() function. The template is spezialized for each supported type.
+
+        The exact return value of the function depends on the type. For @c int this is 0,
+        for @c float it's 0.0f. For a @c std::string the function returns "" and for
+        @c Vector3 you get <tt>Vector3(0, 0, 0)</tt>.
+    */
+    template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, T>::type
+    inline /*T*/ zeroise()
+    {
+        // If you reach this code, you abused zeroise()!
+        static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
+    }
+    /// Implementation for enum classes: uses the underlying type to create a zero value.
+    template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, T>::type
+    inline /*T*/ zeroise()
+    {
+        return static_cast<T>(zeroise<typename std::underlying_type<T>::type>());
+    }
+
+    template <> inline char                 zeroise<char>()                 { return 0; }
+    template <> inline unsigned char        zeroise<unsigned char>()        { return 0; }
+    template <> inline short                zeroise<short>()                { return 0; }
+    template <> inline unsigned short       zeroise<unsigned short>()       { return 0; }
+    template <> inline int                  zeroise<int>()                  { return 0; }
+    template <> inline unsigned int         zeroise<unsigned int>()         { return 0; }
+    template <> inline long                 zeroise<long>()                 { return 0; }
+    template <> inline unsigned long        zeroise<unsigned long>()        { return 0; }
+    template <> inline long long            zeroise<long long>()            { return 0; }
+    template <> inline unsigned long long   zeroise<unsigned long long>()   { return 0; }
+    template <> inline float                zeroise<float>()                { return 0; }
+    template <> inline double               zeroise<double>()               { return 0; }
+    template <> inline long double          zeroise<long double>()          { return 0; }
+    template <> inline bool                 zeroise<bool>()                 { return 0; }
+    template <> inline void*                zeroise<void*>()                { return nullptr; }
+    template <> inline std::string          zeroise<std::string>()          { return std::string(); }
+    template <> inline orxonox::Radian      zeroise<orxonox::Radian>()      { return orxonox::Radian(0.0f); }
+    template <> inline orxonox::Degree      zeroise<orxonox::Degree>()      { return orxonox::Degree(0.0f); }
+    template <> inline orxonox::Vector2     zeroise<orxonox::Vector2>()     { return orxonox::Vector2    (0, 0)      ; }
+    template <> inline orxonox::Vector3     zeroise<orxonox::Vector3>()     { return orxonox::Vector3    (0, 0, 0)   ; }
+    template <> inline orxonox::Vector4     zeroise<orxonox::Vector4>()     { return orxonox::Vector4    (0, 0, 0, 0); }
+    template <> inline orxonox::ColourValue zeroise<orxonox::ColourValue>() { return orxonox::ColourValue(0, 0, 0, 0); }
+    template <> inline orxonox::Quaternion  zeroise<orxonox::Quaternion>()  { return orxonox::Quaternion (0, 0, 0, 0); }
+
+    /**
+        @brief Provides zero value symbols that can be returned as reference
+        @see zeroise()
+    */
+    template <typename T>
+    struct NilValue
+    {
+        inline operator const T&() const
+        {
+            return value;
+        }
+        static T value;
+    };
+    template <typename T>
+    T NilValue<T>::value = zeroise<T>();
+
+    /**
+        @brief Interpolates between two values for a time between 0 and 1.
+        @param time The time is a value between 0 and 1 - the function returns @a start if @a time is 0, @a end if @a time is 1, and interpolates if @a time is between 0 and 1.
+        @param start The value at @a time = 0
+        @param end The value at @a time = 1
+        @return The interpolated value at a given time
+    */
+    template <typename T>
+    inline T interpolate(float time, const T& start, const T& end)
+    {
+        return static_cast<T>(time * (end - start) + start);
+    }
+
+    /**
+        @brief Interpolates smoothly between two values for a time between 0 and 1. The function starts slowly, increases faster and stops slowly again.
+        @param time The time is a value between 0 and 1 - the function returns @a start if @a time is 0, @a end if @a time is 1, and interpolates if @a time is between 0 and 1.
+        @param start The value at @a time = 0
+        @param end The value at @a time = 1
+        @return The interpolated value at a given time
+    */
+    template <typename T>
+    inline T interpolateSmooth(float time, const T& start, const T& end)
+    {
+        return static_cast<T>((-2 * (end - start) * cube(time)) + (3 * (end - start) * square(time)) + start);
+    }
+
+    namespace detail
+    {
+        /**
+        Random number generator used for the functions below. Marked extern to only have one global instance.
+        */
+        _UtilExport extern std::mt19937 rngen;
+    }
+
+    /**
+    @brief Seeds the random number generator used for the functions below.
+    */
+    inline void rndseed(unsigned int seed)
+    {
+        detail::rngen.seed(seed);
+    }
+
+    /**
+    @brief Returns a random number between @a min and almost @a max: <tt>min <= rnd < max</tt>.
+    @param min The minimum
+    @param max The maximum
+    */
+    inline float rnd(float min, float max)
+    {
+        std::uniform_real_distribution<float> dist(min, max);
+        return dist(detail::rngen);
+    }
+
+    /**
+        @brief Returns a random number between 0 and almost 1: <tt>0 <= rnd < 1</tt>.
+    */
+    inline float rnd()
+    {
+        return rnd(0, 1);
+    }
+
+    /**
+        @brief Returns a random number between 0 and almost @a max: <tt>0 <= rnd < max</tt>.
+        @param max The maximum
+    */
+    inline float rnd(float max)
+    {
+        return rnd(0, max);
+    }
+
+    /**
+        @brief Returns randomly 1 or -1 with equal probability.
+    */
+    inline float rndsgn()
+    {
+        std::uniform_int_distribution<> dist;
+        return static_cast<float>((dist(detail::rngen) & 0x2) - 1); // dist(...) & 0x2 is either 2 or 0
+    }
+
+    _UtilExport unsigned long getUniqueNumber();
+}
+
+#endif /* _Util_Math_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/MathConvert.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/MathConvert.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/MathConvert.h	(revision 11817)
@@ -0,0 +1,210 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ */
+
+/**
+@file
+@ingroup Convert
+@brief
+    Conversion functions for Math types like Ogre::Vector3 (definitions are in Math.cc)
+*/
+
+#ifndef _MathConvert_H__
+#define _MathConvert_H__
+
+#include "UtilPrereqs.h"
+#include "Math.h"
+#include "Convert.h"
+
+namespace orxonox
+{
+    ////////////////////
+    // Math to string //
+    ////////////////////
+
+    /// Ogre::Vector2 to std::string conversion
+    template <>
+    struct ConverterExplicit<orxonox::Vector2, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const orxonox::Vector2& input)
+        {
+            std::ostringstream ostream;
+            if (ostream << input.x << ',' << input.y)
+            {
+                (*output) = ostream.str();
+                return true;
+            }
+            return false;
+        }
+    };
+
+    /// Ogre::Vector3 to std::string conversion
+    template <>
+    struct ConverterExplicit<orxonox::Vector3, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const orxonox::Vector3& input)
+        {
+            std::ostringstream ostream;
+            if (ostream << input.x << ',' << input.y << ',' << input.z)
+            {
+                (*output) = ostream.str();
+                return true;
+            }
+            return false;
+        }
+    };
+
+    /// Ogre::Vector4 to std::string conversion
+    template <>
+    struct ConverterExplicit<orxonox::Vector4, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const orxonox::Vector4& input)
+        {
+            std::ostringstream ostream;
+            if (ostream << input.x << ',' << input.y << ',' << input.z << ',' << input.w)
+            {
+                (*output) = ostream.str();
+                return true;
+            }
+            return false;
+        }
+    };
+
+    /// Ogre::Quaternion to std::string conversion
+    template <>
+    struct ConverterExplicit<orxonox::Quaternion, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const orxonox::Quaternion& input)
+        {
+            std::ostringstream ostream;
+            if (ostream << input.w << ',' << input.x << ',' << input.y << ',' << input.z)
+            {
+                (*output) = ostream.str();
+                return true;
+            }
+            return false;
+        }
+    };
+
+    /// Ogre::ColourValue to std::string conversion
+    template <>
+    struct ConverterExplicit<orxonox::ColourValue, std::string>
+    {
+        ORX_FORCEINLINE static bool convert(std::string* output, const orxonox::ColourValue& input)
+        {
+            std::ostringstream ostream;
+            if (ostream << input.r << ',' << input.g << ',' << input.b << ',' << input.a)
+            {
+                (*output) = ostream.str();
+                return true;
+            }
+            return false;
+        }
+    };
+
+
+    ////////////////////
+    // string to Math //
+    ////////////////////
+
+    /// std::string to Ogre::Vector2 conversion
+    template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector2>
+    { static bool convert(orxonox::Vector2*     output, const std::string& input); };
+    /// std::string to Ogre::Vector3 conversion
+    template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector3>
+    { static bool convert(orxonox::Vector3*     output, const std::string& input); };
+    /// std::string to Ogre::Vector4 conversion
+    template <> struct _UtilExport ConverterFallback<std::string, orxonox::Vector4>
+    { static bool convert(orxonox::Vector4*     output, const std::string& input); };
+    /// std::string to Ogre::Quaternion conversion
+    template <> struct _UtilExport ConverterFallback<std::string, orxonox::Quaternion>
+    { static bool convert(orxonox::Quaternion*  output, const std::string& input); };
+    /// std::string to Ogre::ColourValue conversion
+    template <> struct _UtilExport ConverterFallback<std::string, orxonox::ColourValue>
+    { static bool convert(orxonox::ColourValue* output, const std::string& input); };
+
+
+    ///////////////////////////////
+    // From and to Radian/Degree //
+    ///////////////////////////////
+
+    /// Delegates conversions from Radian to conversions from float
+    template <class ToType>
+    struct ConverterFallback<orxonox::Radian, ToType>
+    {
+        ORX_FORCEINLINE static bool convert(ToType* output, const orxonox::Radian& input)
+        {
+            return convertValue<Ogre::Real, ToType>(output, input.valueRadians());
+        }
+    };
+
+    /// Delegates conversions from Degree to conversions from float
+    template <class ToType>
+    struct ConverterFallback<orxonox::Degree, ToType>
+    {
+        ORX_FORCEINLINE static bool convert(ToType* output, const orxonox::Degree& input)
+        {
+            return convertValue<Ogre::Real, ToType>(output, input.valueDegrees());
+        }
+    };
+
+    /// Delegates conversions to Radian to conversions to float
+    template <class FromType>
+    struct ConverterFallback<FromType, orxonox::Radian>
+    {
+        ORX_FORCEINLINE static bool convert(orxonox::Radian* output, const FromType& input)
+        {
+            float temp;
+            if (convertValue(&temp, input))
+            {
+                *output = temp;
+                return true;
+            }
+            else
+                return false;
+        }
+    };
+
+    /// Delegates conversions to Degree to conversions to float
+    template <class FromType>
+    struct ConverterFallback<FromType, orxonox::Degree>
+    {
+        ORX_FORCEINLINE static bool convert(orxonox::Degree* output, const FromType& input)
+        {
+            float temp;
+            if (convertValue(&temp, input))
+            {
+                *output = temp;
+                return true;
+            }
+            else
+                return false;
+        }
+    };
+}
+
+#endif /* _MathConvert_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/MultiType.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/MultiType.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/MultiType.cc	(revision 11817)
@@ -0,0 +1,186 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the MultiType.
+*/
+
+#include "MultiType.h"
+#include "MultiTypeValue.h"
+
+namespace orxonox
+{
+    const MultiType MultiType::Null;
+
+    /**
+        @brief Converts the current value of the MultiType to a new type.
+        @param type The type
+    */
+    bool MultiType::convert(Type type)
+    {
+        switch (type)
+        {
+            case Type::Null:
+                this->reset(); return true;
+            case Type::Char:
+                return this->convert<char>(); break;
+            case Type::UnsignedChar:
+                return this->convert<unsigned char>(); break;
+            case Type::Short:
+                return this->convert<short>(); break;
+            case Type::UnsignedShort:
+                return this->convert<unsigned short>(); break;
+            case Type::Int:
+                return this->convert<int>(); break;
+            case Type::UnsignedInt:
+                return this->convert<unsigned int>(); break;
+            case Type::Long:
+                return this->convert<long>(); break;
+            case Type::UnsignedLong:
+                return this->convert<unsigned long>(); break;
+            case Type::LongLong:
+                return this->convert<long long>(); break;
+            case Type::UnsignedLongLong:
+                return this->convert<unsigned long long>(); break;
+            case Type::Float:
+                return this->convert<float>(); break;
+            case Type::Double:
+                return this->convert<double>(); break;
+            case Type::LongDouble:
+                return this->convert<long double>(); break;
+            case Type::Bool:
+                return this->convert<bool>(); break;
+            case Type::VoidPointer:
+                return this->convert<void*>(); break;
+            case Type::String:
+                return this->convert<std::string>(); break;
+            case Type::Vector2:
+                return this->convert<orxonox::Vector2>(); break;
+            case Type::Vector3:
+                return this->convert<orxonox::Vector3>(); break;
+            case Type::Vector4:
+                return this->convert<orxonox::Vector4>(); break;
+            case Type::ColourValue:
+                return this->convert<orxonox::ColourValue>(); break;
+            case Type::Quaternion:
+                return this->convert<orxonox::Quaternion>(); break;
+            case Type::Radian:
+                return this->convert<orxonox::Radian>(); break;
+            case Type::Degree:
+                return this->convert<orxonox::Degree>(); break;
+            default:
+                this->reset(); return false; break;
+        };
+    }
+
+    /**
+        @brief Returns the name of the current type.
+        @return The name
+    */
+    std::string MultiType::getTypename() const
+    {
+        Type type = (this->value_) ? this->value_->type_ : Type::Null;
+
+        switch (type)
+        {
+            case Type::Char:
+                return "char"; break;
+            case Type::UnsignedChar:
+                return "unsigned char"; break;
+            case Type::Short:
+                return "short"; break;
+            case Type::UnsignedShort:
+                return "unsigned short"; break;
+            case Type::Int:
+                return "int"; break;
+            case Type::UnsignedInt:
+                return "unsigned int"; break;
+            case Type::Long:
+                return "long"; break;
+            case Type::UnsignedLong:
+                return "unsigned long"; break;
+            case Type::LongLong:
+                return "long long"; break;
+            case Type::UnsignedLongLong:
+                return "unsigned long long"; break;
+            case Type::Float:
+                return "float"; break;
+            case Type::Double:
+                return "double"; break;
+            case Type::LongDouble:
+                return "long double"; break;
+            case Type::Bool:
+                return "bool"; break;
+            case Type::VoidPointer:
+                return "void*"; break;
+            case Type::String:
+                return "std::string"; break;
+            case Type::Vector2:
+                return "orxonox::Vector2"; break;
+            case Type::Vector3:
+                return "orxonox::Vector3"; break;
+            case Type::Vector4:
+                return "orxonox::Vector4"; break;
+            case Type::ColourValue:
+                return "orxonox::ColourValue"; break;
+            case Type::Quaternion:
+                return "orxonox::Quaternion"; break;
+            case Type::Radian:
+                return "orxonox::Radian"; break;
+            case Type::Degree:
+                return "orxonox::Degree"; break;
+            default:
+                return "unknown"; break;
+        };
+    }
+
+    template <> void MultiType::createNewValueContainer(const char& value)                 { this->value_ = new MT_Value<char>                (value, Type::Char            ); }
+    template <> void MultiType::createNewValueContainer(const unsigned char& value)        { this->value_ = new MT_Value<unsigned char>       (value, Type::UnsignedChar    ); }
+    template <> void MultiType::createNewValueContainer(const short& value)                { this->value_ = new MT_Value<short>               (value, Type::Short           ); }
+    template <> void MultiType::createNewValueContainer(const unsigned short& value)       { this->value_ = new MT_Value<unsigned short>      (value, Type::UnsignedShort   ); }
+    template <> void MultiType::createNewValueContainer(const int& value)                  { this->value_ = new MT_Value<int>                 (value, Type::Int             ); }
+    template <> void MultiType::createNewValueContainer(const unsigned int& value)         { this->value_ = new MT_Value<unsigned int>        (value, Type::UnsignedInt     ); }
+    template <> void MultiType::createNewValueContainer(const long& value)                 { this->value_ = new MT_Value<long>                (value, Type::Long            ); }
+    template <> void MultiType::createNewValueContainer(const unsigned long& value)        { this->value_ = new MT_Value<unsigned long>       (value, Type::UnsignedLong    ); }
+    template <> void MultiType::createNewValueContainer(const long long& value)            { this->value_ = new MT_Value<long long>           (value, Type::LongLong        ); }
+    template <> void MultiType::createNewValueContainer(const unsigned long long& value)   { this->value_ = new MT_Value<unsigned long long>  (value, Type::UnsignedLongLong); }
+    template <> void MultiType::createNewValueContainer(const float& value)                { this->value_ = new MT_Value<float>               (value, Type::Float           ); }
+    template <> void MultiType::createNewValueContainer(const double& value)               { this->value_ = new MT_Value<double>              (value, Type::Double          ); }
+    template <> void MultiType::createNewValueContainer(const long double& value)          { this->value_ = new MT_Value<long double>         (value, Type::LongDouble      ); }
+    template <> void MultiType::createNewValueContainer(const bool& value)                 { this->value_ = new MT_Value<bool>                (value, Type::Bool            ); }
+    template <> void MultiType::createNewValueContainer(      void* const& value)          { this->value_ = new MT_Value<void*>               (value, Type::VoidPointer     ); }
+    template <> void MultiType::createNewValueContainer(const std::string& value)          { this->value_ = new MT_Value<std::string>         (value, Type::String          ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::Vector2& value)     { this->value_ = new MT_Value<orxonox::Vector2>    (value, Type::Vector2         ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::Vector3& value)     { this->value_ = new MT_Value<orxonox::Vector3>    (value, Type::Vector3         ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::Vector4& value)     { this->value_ = new MT_Value<orxonox::Vector4>    (value, Type::Vector4         ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::ColourValue& value) { this->value_ = new MT_Value<orxonox::ColourValue>(value, Type::ColourValue     ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::Quaternion& value)  { this->value_ = new MT_Value<orxonox::Quaternion> (value, Type::Quaternion      ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::Radian& value)      { this->value_ = new MT_Value<orxonox::Radian>     (value, Type::Radian          ); }
+    template <> void MultiType::createNewValueContainer(const orxonox::Degree& value)      { this->value_ = new MT_Value<orxonox::Degree>     (value, Type::Degree          ); }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/MultiType.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/MultiType.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/MultiType.h	(revision 11817)
@@ -0,0 +1,557 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup MultiType MultiType
+    @ingroup Util
+*/
+
+/**
+    @file
+    @ingroup MultiType
+    @brief Declaration of the MultiType and some helper constructs.
+
+    @anchor MultiTypeExamples
+
+    The MultiType can hold a value of one of the following types:
+     - all primitives (int, float, bool, etc.)
+     - all pointers (void* and T*)
+     - std::string
+     - Vector2, Vector3, Vector4
+     - Quaternion
+     - ColourValue
+     - Radian, Degree
+
+    The MultiType has an internal "type" determined by the first assigned value, using one of these ways:
+     - @ref orxonox::MultiType::MultiType "The constructor"
+     - The assignment operator= (orxonox::MultiType::operator=())
+     - @ref orxonox::MultiType::set() "set(value)"
+
+    If you assign another value of another type, the MultiType keeps "its" type and
+    converts the new value to the old type.
+
+    If you want to change the type, there are three possibilities:
+     - @ref orxonox::MultiType::convert "convert<T>()" sets the type to T and converts the currently assigned value
+     - @ref orxonox::MultiType::reset "reset<T>()" sets the type to T and resets the value to zero using zeroise<T>()
+     - force<T>(value) assigns a new value and changes the type to T.
+
+    Examples:
+    @code
+    MultiType a = 10;       // a has now the type int and the value 10
+    a.set("3.14");          // a has still the type int and "3.14" gets converted, therefore the value is now 3
+    a.force<float>("3.14"); // a has now the type float and "3.14" gets converted to 3.14f
+    a.convert<bool>();      // converts 3.14f to bool, which is true
+    a = false;              // assigns false, this is equivalent to a.setValue(false)
+    @endcode
+
+    You can pass a MultiType to a function as an argument, even if the argument is
+    not of type MultiType. This works, because the MultiType is automatically converted
+    to the right type.
+
+    Example:
+    @code
+    void myfunction(int value)
+    {
+        orxout() << "doubled value is " << (2 * value) << endl;
+    }
+
+    MultiType a = "50";        // Note: We assigned a string
+    myfunction(a);             // a is converted to int and passed to the function, which prints "value is 100"
+    @endcode
+
+    Note however that it is of course quite expensive to convert values, especially std::string <-> value.
+    So if you can, always assign a value with the right type to avoid conversion.
+
+    @note
+    Whenever a value gets converted, there is a boolean return value telling you whether it was
+    successful or not. If it wasn't a zero value is assigned with the help of zeroise<T>().
+*/
+
+#ifndef _MultiType_H__
+#define _MultiType_H__
+
+#include "UtilPrereqs.h"
+
+#include <cassert>
+#include <string>
+#include <utility>
+#include <OgreVector2.h>
+#include <OgreVector3.h>
+#include <OgreVector4.h>
+#include <OgreQuaternion.h>
+#include <OgreColourValue.h>
+#include <loki/TypeTraits.h>
+#include "Math.h"
+#include "mbool.h"
+
+namespace orxonox
+{
+    /**
+        @brief The MultiType can hold a value of many possible types and convert them to other types.
+
+        The following types are supported by the MultiType:
+         - all primitves
+         - all pointers
+         - string
+         - Vector2, Vector3, Vector4
+         - Quaternion
+         - ColourValue
+         - Radian, Degree
+
+        For more information and some examples see the description @ref MultiTypeExamples "here".
+
+        @see MultiType.h
+    */
+    class _UtilExport MultiType
+    {
+        _UtilExport friend std::ostream& operator<<(std::ostream& outstream, const MultiType& mt);
+        template <typename T> friend class MT_Value;
+
+        /**
+            @brief Enum of all possible types of a MultiType.
+        */
+        enum class Type : uint8_t
+        {
+            Null,
+            Char,
+            UnsignedChar,
+            Short,
+            UnsignedShort,
+            Int,
+            UnsignedInt,
+            Long,
+            UnsignedLong,
+            LongLong,
+            UnsignedLongLong,
+            Float,
+            Double,
+            LongDouble,
+            Bool,
+            VoidPointer,
+            String,
+            Vector2,
+            Vector3,
+            Vector4,
+            ColourValue,
+            Quaternion,
+            Radian,
+            Degree
+        };
+
+    public:
+        /**
+            @brief MT_ValueBase is an almost pure virtual baseclass of MT_Value<T>, which holds the value of the MultiType.
+            This class is only used within the MultiType.
+        */
+        class _UtilExport MT_ValueBase
+        {
+        public:
+            inline MT_ValueBase(void* data, Type type) : type_(type), bLastConversionSuccessful(true), data_(data) {}
+            virtual inline ~MT_ValueBase() {}
+
+            virtual MT_ValueBase* clone() const = 0;
+
+            virtual void reset() = 0;
+
+            /// Returns the type of the current value.
+            inline const Type& getType() const { return this->type_; }
+
+            /// Returns true if the type of the stored value is T. Note: the actual implementations for all supported types are defined outside of the class.
+            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, bool>::type
+            inline /*bool*/ isType() const
+            {
+                // If you reach this code, you used MultiType with an unsupported type T
+                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
+                return false;
+            }
+            /// Implementation for enum classes: Returns true if the type of the stored value is the underlying type of T.
+            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, bool>::type
+            inline /*bool*/ isType() const
+            {
+                return this->isType<typename std::underlying_type<T>::type>();
+            }
+
+            /// Checks whether the value is a default one.
+            inline bool lastConversionSuccessful()   const { return this->bLastConversionSuccessful; }
+
+            virtual bool setValue(const char& value)                 = 0;
+            virtual bool setValue(const unsigned char& value)        = 0;
+            virtual bool setValue(const short& value)                = 0;
+            virtual bool setValue(const unsigned short& value)       = 0;
+            virtual bool setValue(const int& value)                  = 0;
+            virtual bool setValue(const unsigned int& value)         = 0;
+            virtual bool setValue(const long& value)                 = 0;
+            virtual bool setValue(const unsigned long& value)        = 0;
+            virtual bool setValue(const long long& value)            = 0;
+            virtual bool setValue(const unsigned long long& value)   = 0;
+            virtual bool setValue(const float& value)                = 0;
+            virtual bool setValue(const double& value)               = 0;
+            virtual bool setValue(const long double& value)          = 0;
+            virtual bool setValue(const bool& value)                 = 0;
+            virtual bool setValue(      void* const& value)          = 0;
+            virtual bool setValue(const std::string& value)          = 0;
+            virtual bool setValue(const orxonox::Vector2& value)     = 0;
+            virtual bool setValue(const orxonox::Vector3& value)     = 0;
+            virtual bool setValue(const orxonox::Vector4& value)     = 0;
+            virtual bool setValue(const orxonox::ColourValue& value) = 0;
+            virtual bool setValue(const orxonox::Quaternion& value)  = 0;
+            virtual bool setValue(const orxonox::Radian& value)      = 0;
+            virtual bool setValue(const orxonox::Degree& value)      = 0;
+
+            virtual bool setValue(const MultiType& other)            = 0;
+
+            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, bool>::type
+            inline /*bool*/ setValue(const T& value)
+            {
+                // If you reach this code, you used MultiType with an unsupported type T
+                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
+                return false;
+            }
+            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, bool>::type
+            inline /*bool*/ setValue(const T& value)
+            {
+                typedef typename std::underlying_type<T>::type UnderlyingType;
+                return this->setValue(reinterpret_cast<const UnderlyingType&>(value));
+            }
+
+            virtual bool getValue(char*                 value) const = 0;
+            virtual bool getValue(unsigned char*        value) const = 0;
+            virtual bool getValue(short*                value) const = 0;
+            virtual bool getValue(unsigned short*       value) const = 0;
+            virtual bool getValue(int*                  value) const = 0;
+            virtual bool getValue(unsigned int*         value) const = 0;
+            virtual bool getValue(long*                 value) const = 0;
+            virtual bool getValue(unsigned long*        value) const = 0;
+            virtual bool getValue(long long*            value) const = 0;
+            virtual bool getValue(unsigned long long*   value) const = 0;
+            virtual bool getValue(float*                value) const = 0;
+            virtual bool getValue(double*               value) const = 0;
+            virtual bool getValue(long double*          value) const = 0;
+            virtual bool getValue(bool*                 value) const = 0;
+            virtual bool getValue(void**                value) const = 0;
+            virtual bool getValue(std::string*          value) const = 0;
+            virtual bool getValue(orxonox::Vector2*     value) const = 0;
+            virtual bool getValue(orxonox::Vector3*     value) const = 0;
+            virtual bool getValue(orxonox::Vector4*     value) const = 0;
+            virtual bool getValue(orxonox::ColourValue* value) const = 0;
+            virtual bool getValue(orxonox::Quaternion*  value) const = 0;
+            virtual bool getValue(orxonox::Radian*      value) const = 0;
+            virtual bool getValue(orxonox::Degree*      value) const = 0;
+
+            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, bool>::type
+            inline /*bool*/ getValue(T* value) const
+            {
+                // If you reach this code, you used MultiType with an unsupported type T
+                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
+                return false;
+            }
+            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, bool>::type
+            inline /*bool*/ getValue(T* value) const
+            {
+                typedef typename std::underlying_type<T>::type UnderlyingType;
+                return this->getValue(reinterpret_cast<UnderlyingType*>(value));
+            }
+
+            template <typename T> T get() const
+            {
+                if (this->isType<T>())
+                    return *reinterpret_cast<const T*>(this->data_);
+                else
+                {
+                    T value;
+                    this->getValue(&value);
+                    return value;
+                }
+            }
+
+            virtual void toString(std::ostream& outstream) const = 0;
+
+            virtual void importData(uint8_t*& mem) = 0;
+            virtual void exportData(uint8_t*& mem) const = 0;
+            virtual uint8_t getSize() const = 0;
+
+            Type type_;                     ///< The type of the current value
+            bool bLastConversionSuccessful; ///< True if the last conversion was successful
+            void* data_;                    ///< For direct access to the value if the type is known
+        };
+
+        public:
+            static const MultiType Null;
+
+            /// Default constructor: Assigns no value and no type. The type will be determined by the first assignment of a value.
+            inline MultiType()                       : value_(nullptr) { }
+            /// Constructor: Assigns the given value and sets the type.
+            template <typename V>
+            inline MultiType(const V& value)         : value_(nullptr) { this->set(value); }
+            /// Copyconstructor: Assigns value and type of the other MultiType.
+            inline MultiType(const MultiType& other) : value_(nullptr) { this->set(other); }
+            /// Moveconstructor: Moves the value and its type from the other MultiType
+            inline MultiType(MultiType&& other)      : value_(nullptr) { std::swap(this->value_, other.value_); };
+
+            /// Destructor: Deletes the MT_Value.
+            inline ~MultiType() { if (this->value_) { delete this->value_; } }
+
+            /// Assigns a new value. The value will be converted to the current type of the MultiType.
+            template <typename V> inline MultiType& operator=(const V& value)         { this->set(value); return (*this); }
+            /// Assigns a pointer.
+            template <typename V> inline MultiType& operator=(V* value)               { this->set(value); return (*this); }
+            /// Assigns the value of the other MultiType and converts it to the current type of the MultiType.
+            inline                       MultiType& operator=(const MultiType& other) { this->set(other); return (*this); }
+            /// Moves the value and the type of the other MultiType to this one.
+            inline                       MultiType& operator=(MultiType&& other)      { std::swap(this->value_, other.value_); return (*this); }
+
+            /// Assigns the given value and converts it to the current type.
+            template <typename V> inline bool set(const V& value)
+            {
+                if (this->value_)
+                    return this->value_->setValue(value);
+
+                this->assignValue(value);
+                return true;
+            }
+            /// Assigns a pointer.
+            template <typename V> inline bool set(V* value)
+            {
+                if (this->value_)
+                    return this->value_->setValue(static_cast<void*>(const_cast<typename Loki::TypeTraits<V>::UnqualifiedType*>(value)));
+
+                this->assignValue(static_cast<void*>(const_cast<typename Loki::TypeTraits<V>::UnqualifiedType*>(value)));
+                return true;
+            }
+            /// Assigns the value of the other MultiType and converts it to the current type.
+            inline bool set(const MultiType& other)
+            {
+                if (this->value_)
+                    return this->value_->setValue(other);
+                else if (other.value_)
+                    this->value_ = other.value_->clone();
+                return true;
+            }
+
+            /// Changes the type to T and assigns the new value (which might be of another type than T - it gets converted).
+            template <typename T, typename V> inline bool force(const V& value)
+            {
+                this->reset<T>();
+                return this->set(value);
+            }
+
+            /// Copies the other MultiType by assigning value and type.
+            inline void copy(const MultiType& other)
+            {
+                if (this == &other)
+                    return;
+                if (this->value_)
+                    delete this->value_;
+                this->value_ = (other.value_) ? other.value_->clone() : nullptr;
+            }
+
+            /// Converts the current value to type T.
+            template <typename T> inline bool convert() { return this->force<T>(MultiType(*this)); }
+
+            /// Resets value and type. Type will be void afterwards and null() returns true.
+            inline void reset() { if (this->value_) delete this->value_; this->value_ = nullptr; }
+            /// Resets the value and changes the internal type to T.
+            template <typename T> inline void reset() { this->assignValue(typename Loki::TypeTraits<T>::UnqualifiedReferredType()); }
+            /// Current value gets overridden with default zero value
+            inline void resetValue() { if (this->value_) this->value_->reset(); }
+
+            /// Returns true if the type of the current value is T.
+            template <typename T> inline bool isType() const { return (this->value_ ? this->value_->isType<T>() : false); }
+            std::string getTypename() const;
+
+            /// Checks whether the last conversion was successful
+            inline bool lastConversionSuccessful() const { return !this->value_ || this->value_->lastConversionSuccessful(); }
+
+            /// Checks if the MT contains no value.
+            inline bool null() const { return !this->value_; }
+
+            /// Conversion operator for all types
+            template <class T> operator T()  const { return this->get<T>(); }
+
+            /// Assigns the value to the given pointer. The value gets converted if the types don't match.
+            template <typename T> inline bool getValue(T* value) const { if (this->value_) { return this->value_->getValue(value); } return false; }
+
+            /// Returns the current value, converted to the requested type.
+            template <typename T> /* for normal types */ typename std::enable_if<!std::is_pointer<T>::value, T>::type
+            inline /*T*/ get() const { return (this->value_ ? this->value_->get<T>() : NilValue<T>()); }
+            /// Returns the current value, converted to a pointer of the requested type.
+            template <typename T> /* for pointers */ typename std::enable_if<std::is_pointer<T>::value, T>::type
+            inline /*T*/ get() const { return this->value_ ? static_cast<T>(this->value_->get<void*>()) : nullptr; }
+
+
+            ///////////////////////////////
+            // network-related functions //
+            ///////////////////////////////
+            /// Saves the value of the MT to a bytestream (pointed at by mem) and increases mem pointer by size of MT
+            inline void exportData(uint8_t*& mem) const
+            {
+                assert(sizeof(Type) <= 8);
+                *static_cast<uint8_t*>(mem) = static_cast<uint8_t>(this->getType());
+                mem += sizeof(uint8_t);
+                this->value_->exportData(mem);
+            }
+            /// Loads the value of the MT from a bytestream (pointed at by mem) and increases mem pointer by size of MT
+            inline void importData(uint8_t*& mem)
+            {
+                assert(sizeof(Type) <= 8);
+                this->setType(static_cast<Type>(*static_cast<uint8_t*>(mem)));
+                mem += sizeof(uint8_t);
+                this->value_->importData(mem);
+            }
+            /// Saves the value of the MT to a bytestream and increases pointer to bytestream by size of MT
+            inline uint8_t*& operator<<(uint8_t*& mem)
+            {
+                importData(mem);
+                return mem;
+            }
+            /// Loads the value of the MT to a bytestream and increases pointer to bytestream by size of MT
+            inline void operator>>(uint8_t*& mem) const
+            {
+                exportData(mem);
+            }
+            inline uint32_t getNetworkSize() const
+            {
+                assert(this->value_);
+                return this->value_->getSize() + sizeof(uint8_t);
+            }
+
+        private:
+            /// Assigns a new value by changing type and creating a new container.
+            template <typename T> inline void assignValue(const T& value)
+            {
+                if (this->isType<T>())
+                    this->value_->setValue(value);
+                else
+                    this->changeValueContainer(value);
+            }
+            /// Assigns a new value by changing type and creating a new container (overload for pointers).
+            template <typename T> inline void assignValue(T* const& value)
+            {
+                if (this->isType<void*>())
+                    this->value_->setValue(static_cast<void*>(value));
+                else
+                    this->changeValueContainer<void*>(value);
+            }
+
+            /// Resets the value and changes the internal type to the given type.
+            inline void setType(Type type) { this->reset(); this->convert(type); this->resetValue(); }
+            /// Returns the current type.
+            inline Type getType() const { return (this->value_) ? this->value_->type_ : Type::Null; }
+            /// Converts the current value to the given type.
+            bool convert(Type type);
+
+            /// Changes the value container.
+            template <typename T> inline void changeValueContainer(const T& value)
+            {
+                if (this->value_)
+                    delete this->value_;
+                this->createNewValueContainer(value);
+            }
+            /// Creates a new value container (works only with specialized types).
+            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value>::type
+            inline /*void*/ createNewValueContainer(const T& value)
+            { 
+                // If you reach this code, you used MultiType with an unsupported type T
+                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
+            }
+            /// Creates a new value container (implementation for enum classes that must be cast to the underlying type).
+            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value>::type
+            inline /*void*/ createNewValueContainer(const T& value)
+            {
+                typedef typename std::underlying_type<T>::type UnderlyingType;
+                this->createNewValueContainer<UnderlyingType>(reinterpret_cast<const UnderlyingType&>(value));
+            }
+
+            MT_ValueBase* value_; //!< A pointer to the value container
+    };
+
+    /// Puts the MultiType on a stream by using the native << operator of the current type.
+    _UtilExport inline std::ostream& operator<<(std::ostream& outstream, const MultiType& mt)
+    {
+        if (mt.value_)
+            mt.value_->toString(outstream);
+        return outstream;
+    }
+
+    template <> inline bool MultiType::MT_ValueBase::isType<char>()                 const { return this->type_ == Type::Char;             }
+    template <> inline bool MultiType::MT_ValueBase::isType<unsigned char>()        const { return this->type_ == Type::UnsignedChar;     }
+    template <> inline bool MultiType::MT_ValueBase::isType<short>()                const { return this->type_ == Type::Short;            }
+    template <> inline bool MultiType::MT_ValueBase::isType<unsigned short>()       const { return this->type_ == Type::UnsignedShort;    }
+    template <> inline bool MultiType::MT_ValueBase::isType<int>()                  const { return this->type_ == Type::Int;              }
+    template <> inline bool MultiType::MT_ValueBase::isType<unsigned int>()         const { return this->type_ == Type::UnsignedInt;      }
+    template <> inline bool MultiType::MT_ValueBase::isType<long>()                 const { return this->type_ == Type::Long;             }
+    template <> inline bool MultiType::MT_ValueBase::isType<unsigned long>()        const { return this->type_ == Type::UnsignedLong;     }
+    template <> inline bool MultiType::MT_ValueBase::isType<long long>()            const { return this->type_ == Type::LongLong;         }
+    template <> inline bool MultiType::MT_ValueBase::isType<unsigned long long>()   const { return this->type_ == Type::UnsignedLongLong; }
+    template <> inline bool MultiType::MT_ValueBase::isType<float>()                const { return this->type_ == Type::Float;            }
+    template <> inline bool MultiType::MT_ValueBase::isType<double>()               const { return this->type_ == Type::Double;           }
+    template <> inline bool MultiType::MT_ValueBase::isType<long double>()          const { return this->type_ == Type::LongDouble;       }
+    template <> inline bool MultiType::MT_ValueBase::isType<bool>()                 const { return this->type_ == Type::Bool;             }
+    template <> inline bool MultiType::MT_ValueBase::isType<void*>()                const { return this->type_ == Type::VoidPointer;      }
+    template <> inline bool MultiType::MT_ValueBase::isType<std::string>()          const { return this->type_ == Type::String;           }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector2>()     const { return this->type_ == Type::Vector2;          }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector3>()     const { return this->type_ == Type::Vector3;          }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector4>()     const { return this->type_ == Type::Vector4;          }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::ColourValue>() const { return this->type_ == Type::ColourValue;      }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Quaternion>()  const { return this->type_ == Type::Quaternion;       }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Radian>()      const { return this->type_ == Type::Radian;           }
+    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Degree>()      const { return this->type_ == Type::Degree;           }
+
+    template <> inline bool MultiType::set(const char* value)  { return this->set(std::string(value)); }
+    template <> inline bool MultiType::set(const mbool& value) { return this->set((bool)value); }
+
+    // Spezializations for void
+    template <> inline bool MultiType::isType<void>() const { return this->null(); }
+    template <> inline bool MultiType::convert<void>() { this->reset(); return true; }
+
+    template <> _UtilExport void MultiType::createNewValueContainer(const char& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned char& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const short& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned short& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const int& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned int& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const long& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned long& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const long long& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned long long& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const float& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const double& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const bool& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const long double& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(      void* const& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const std::string& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector2& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector3& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector4& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::ColourValue& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Quaternion& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Radian& value);
+    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Degree& value);
+}
+
+#endif /* _MultiType_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/MultiTypeValue.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/MultiTypeValue.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/MultiTypeValue.h	(revision 11817)
@@ -0,0 +1,247 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup MultiType
+    @brief Declaration and Implementation of the MT_Value<T> class.
+
+    The MT_Value<T> class is used to hold a value of type T within a MultiType.
+*/
+
+#ifndef _MultiTypeValue_H__
+#define _MultiTypeValue_H__
+
+#include "UtilPrereqs.h"
+
+#include <cassert>
+#include "MathConvert.h"
+#include "MultiType.h"
+#include "Serialise.h"
+
+namespace orxonox
+{
+    /**
+        @brief The MT_Value<T> class is used to hold a value of type T within a MultiType.
+    */
+    template <typename T>
+    class MT_Value : public MultiType::MT_ValueBase
+    {
+    public:
+        /// Constructor: Assigns the value and the type identifier.
+        MT_Value(const T& value, MultiType::Type type) : MT_ValueBase(&this->value_, type), value_(value) {}
+
+        /// Creates a copy of itself.
+        virtual inline MT_ValueBase* clone() const override { return new MT_Value<T>(this->value_, this->type_); }
+
+        /// Resets the current value to the default.
+        virtual inline void reset() override { this->value_ = zeroise<T>(); bLastConversionSuccessful = true; }
+
+        virtual inline bool getValue(char*                 value) const override { return convertValue<T, char                >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(unsigned char*        value) const override { return convertValue<T, unsigned char       >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(short*                value) const override { return convertValue<T, short               >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(unsigned short*       value) const override { return convertValue<T, unsigned short      >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(int*                  value) const override { return convertValue<T, int                 >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(unsigned int*         value) const override { return convertValue<T, unsigned int        >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(long*                 value) const override { return convertValue<T, long                >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(unsigned long*        value) const override { return convertValue<T, unsigned long       >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(long long*            value) const override { return convertValue<T, long long           >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(unsigned long long*   value) const override { return convertValue<T, unsigned long long  >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(float*                value) const override { return convertValue<T, float               >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(double*               value) const override { return convertValue<T, double              >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(long double*          value) const override { return convertValue<T, long double         >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(bool*                 value) const override { return convertValue<T, bool                >(value, value_, 0); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(void**                value) const override { return convertValue<T, void*               >(value, value_, nullptr); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(std::string*          value) const override { return convertValue<T, std::string         >(value, value_, NilValue<std::string>         ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::Vector2*     value) const override { return convertValue<T, orxonox::Vector2    >(value, value_, NilValue<orxonox::Vector2>    ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::Vector3*     value) const override { return convertValue<T, orxonox::Vector3    >(value, value_, NilValue<orxonox::Vector3>    ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::Vector4*     value) const override { return convertValue<T, orxonox::Vector4    >(value, value_, NilValue<orxonox::Vector4>    ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::ColourValue* value) const override { return convertValue<T, orxonox::ColourValue>(value, value_, NilValue<orxonox::ColourValue>()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::Quaternion*  value) const override { return convertValue<T, orxonox::Quaternion >(value, value_, NilValue<orxonox::Quaternion> ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::Radian*      value) const override { return convertValue<T, orxonox::Radian     >(value, value_, NilValue<orxonox::Radian>     ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+        virtual inline bool getValue(orxonox::Degree*      value) const override { return convertValue<T, orxonox::Degree     >(value, value_, NilValue<orxonox::Degree>     ()); } ///< Assigns the value to the given pointer. The value gets converted if the types don't match.
+
+        /**
+            @brief Assigns the value of the other MultiType, converted to T.
+            @param other The other MultiType
+        */
+        virtual inline bool setValue(const MultiType& other) override
+        {
+            if (other.value_)
+            {
+                return (this->bLastConversionSuccessful = other.value_->getValue(&value_));
+            }
+            else
+            {
+                this->value_ = zeroise<T>();
+                return (bLastConversionSuccessful = false);
+            }
+        }
+
+        virtual inline bool setValue(const char& value)                 override { return (bLastConversionSuccessful = convertValue<char                , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const unsigned char& value)        override { return (bLastConversionSuccessful = convertValue<unsigned char       , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const short& value)                override { return (bLastConversionSuccessful = convertValue<short               , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const unsigned short& value)       override { return (bLastConversionSuccessful = convertValue<unsigned short      , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const int& value)                  override { return (bLastConversionSuccessful = convertValue<int                 , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const unsigned int& value)         override { return (bLastConversionSuccessful = convertValue<unsigned int        , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const long& value)                 override { return (bLastConversionSuccessful = convertValue<long                , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const unsigned long& value)        override { return (bLastConversionSuccessful = convertValue<unsigned long       , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const long long& value)            override { return (bLastConversionSuccessful = convertValue<long long           , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const unsigned long long& value)   override { return (bLastConversionSuccessful = convertValue<unsigned long long  , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const float& value)                override { return (bLastConversionSuccessful = convertValue<float               , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const double& value)               override { return (bLastConversionSuccessful = convertValue<double              , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const long double& value)          override { return (bLastConversionSuccessful = convertValue<long double         , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const bool& value)                 override { return (bLastConversionSuccessful = convertValue<bool                , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(      void* const& value)          override { return (bLastConversionSuccessful = convertValue<void*               , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const std::string& value)          override { return (bLastConversionSuccessful = convertValue<std::string         , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::Vector2& value)     override { return (bLastConversionSuccessful = convertValue<orxonox::Vector2    , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::Vector3& value)     override { return (bLastConversionSuccessful = convertValue<orxonox::Vector3    , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::Vector4& value)     override { return (bLastConversionSuccessful = convertValue<orxonox::Vector4    , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::ColourValue& value) override { return (bLastConversionSuccessful = convertValue<orxonox::ColourValue, T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::Quaternion& value)  override { return (bLastConversionSuccessful = convertValue<orxonox::Quaternion , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::Radian& value)      override { return (bLastConversionSuccessful = convertValue<orxonox::Radian     , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+        virtual inline bool setValue(const orxonox::Degree& value)      override { return (bLastConversionSuccessful = convertValue<orxonox::Degree     , T>(&value_, value, NilValue<T>())); } ///< Assigns the value by converting it to T.
+
+        /// Puts the current value on the stream
+        virtual inline void toString(std::ostream& outstream) const override { outstream << this->value_; }
+
+        /// loads data from the bytestream (mem) into the MT and increases the bytestream pointer by the size of the data
+        virtual inline void importData( uint8_t*& mem ) override         { loadAndIncrease( /*(const T&)*/this->value_, mem ); }
+        /// saves data from the MT into the bytestream (mem) and increases the bytestream pointer by the size of the data
+        virtual inline void exportData( uint8_t*& mem ) const override   { saveAndIncrease( /*(const T&)*/this->value_, mem ); }
+        /// returns the size of the data that would be saved by exportData
+        virtual inline uint8_t getSize() const override { return returnSize( this->value_ ); }
+
+        T value_; ///< The stored value
+    };
+
+    // Import / Export specialisation
+    // ColourValue
+    template <> inline void MT_Value<ColourValue>::importData( uint8_t*& mem )
+    {
+        loadAndIncrease( this->value_.r, mem );
+        loadAndIncrease( this->value_.g, mem );
+        loadAndIncrease( this->value_.b, mem );
+        loadAndIncrease( this->value_.a, mem );
+    }
+    template <> inline void MT_Value<ColourValue>::exportData( uint8_t*& mem ) const
+    {
+        saveAndIncrease( this->value_.r, mem );
+        saveAndIncrease( this->value_.g, mem );
+        saveAndIncrease( this->value_.b, mem );
+        saveAndIncrease( this->value_.a, mem );
+    }
+    template <> inline uint8_t MT_Value<ColourValue>::getSize() const
+    {
+        return 4*returnSize(this->value_.r);
+    }
+    // Ogre::Quaternion
+    template <> inline void MT_Value<Ogre::Quaternion>::importData( uint8_t*& mem )
+    {
+        loadAndIncrease( this->value_.x, mem );
+        loadAndIncrease( this->value_.y, mem );
+        loadAndIncrease( this->value_.z, mem );
+        loadAndIncrease( this->value_.w, mem );
+    }
+    template <> inline void MT_Value<Ogre::Quaternion>::exportData( uint8_t*& mem ) const
+    {
+        saveAndIncrease( this->value_.x, mem );
+        saveAndIncrease( this->value_.y, mem );
+        saveAndIncrease( this->value_.z, mem );
+        saveAndIncrease( this->value_.w, mem );
+    }
+    template <> inline uint8_t MT_Value<Ogre::Quaternion>::getSize() const
+    {
+        return 4*returnSize(this->value_.x);
+    }
+    // Ogre::Vector2
+    template <> inline void MT_Value<Ogre::Vector2>::importData( uint8_t*& mem )
+    {
+        loadAndIncrease( this->value_.x, mem );
+        loadAndIncrease( this->value_.y, mem );
+    }
+    template <> inline void MT_Value<Ogre::Vector2>::exportData( uint8_t*& mem ) const
+    {
+        saveAndIncrease( this->value_.x, mem );
+        saveAndIncrease( this->value_.y, mem );
+    }
+    template <> inline uint8_t MT_Value<Ogre::Vector2>::getSize() const
+    {
+        return 2*returnSize(this->value_.x);
+    }
+    // Ogre::Vector3
+    template <> inline void MT_Value<Ogre::Vector3>::importData( uint8_t*& mem )
+    {
+        loadAndIncrease( this->value_.x, mem );
+        loadAndIncrease( this->value_.y, mem );
+        loadAndIncrease( this->value_.z, mem );
+    }
+    template <> inline void MT_Value<Ogre::Vector3>::exportData( uint8_t*& mem ) const
+    {
+        saveAndIncrease( this->value_.x, mem );
+        saveAndIncrease( this->value_.y, mem );
+        saveAndIncrease( this->value_.z, mem );
+    }
+    template <> inline uint8_t MT_Value<Ogre::Vector3>::getSize() const
+    {
+        return 3*returnSize(this->value_.x);
+    }
+    // Ogre::Vector4
+    template <> inline void MT_Value<Ogre::Vector4>::importData( uint8_t*& mem )
+    {
+        loadAndIncrease( this->value_.x, mem );
+        loadAndIncrease( this->value_.y, mem );
+        loadAndIncrease( this->value_.z, mem );
+        loadAndIncrease( this->value_.w, mem );
+    }
+    template <> inline void MT_Value<Ogre::Vector4>::exportData( uint8_t*& mem ) const
+    {
+        saveAndIncrease( this->value_.x, mem );
+        saveAndIncrease( this->value_.y, mem );
+        saveAndIncrease( this->value_.z, mem );
+        saveAndIncrease( this->value_.w, mem );
+    }
+    template <> inline uint8_t MT_Value<Ogre::Vector4>::getSize() const
+    {
+        return 4*returnSize(this->value_.x);
+    }
+    template <> inline void MT_Value<void*>::importData( uint8_t*& /*mem*/ )
+    {
+        assert(0);
+    }
+    template <> inline void MT_Value<void*>::exportData( uint8_t*& /*mem*/ ) const
+    {
+        assert(0);
+    }
+    template <> inline uint8_t MT_Value<void*>::getSize() const
+    {
+        assert(0); return 0;
+    }
+}
+
+#endif /* _MultiTypeValue_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/OgreForwardRefs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/OgreForwardRefs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/OgreForwardRefs.h	(revision 11817)
@@ -0,0 +1,227 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _OgreForwardRefs_H__
+#define _OgreForwardRefs_H__
+
+#include "UtilPrereqs.h"
+
+namespace Ogre
+{
+    class Angle;
+    class Animation;
+    class AnimationState;
+    class AnimationStateSet;
+    class AnimationTrack;
+    class Archive;
+    class ArchiveFactory;
+    class ArchiveManager;
+    class AutoParamDataSource;
+    class AxisAlignedBox;
+    class AxisAlignedBoxSceneQuery;
+    class Billboard;
+    class BillboardChain;
+    class BillboardSet;
+    class Bone;
+    class Camera;
+    class Codec;
+    class ColourValue;
+    class ConfigDialog;
+    template <typename T> class Controller;
+    template <typename T> class ControllerFunction;
+    class ControllerManager;
+    template <typename T> class ControllerValue;
+    class Degree;
+    class DynLib;
+    class DynLibManager;
+    class EdgeData;
+    class EdgeListBuilder;
+    class Entity;
+    class ErrorDialog;
+    class ExternalTextureSourceManager;
+    class Factory;
+    class Font;
+    class FontPtr;
+    class FontManager;
+    struct FrameEvent;
+    class FrameListener;
+    class Frustum;
+    class GpuProgram;
+    class GpuProgramPtr;
+    class GpuProgramManager;
+    class GpuProgramUsage;
+    class HardwareIndexBuffer;
+    class HardwareOcclusionQuery;
+    class HardwareVertexBuffer;
+    class HardwarePixelBuffer;
+    class HardwarePixelBufferSharedPtr;
+    class HighLevelGpuProgram;
+    class HighLevelGpuProgramPtr;
+    class HighLevelGpuProgramManager;
+    class HighLevelGpuProgramFactory;
+    class IndexData;
+    class IntersectionSceneQuery;
+    class IntersectionSceneQueryListener;
+    class Image;
+    class KeyFrame;
+    class Light;
+    class Log;
+    class LogManager;
+    class ManualResourceLoader;
+    class ManualObject;
+    class Material;
+    class MaterialPtr;
+    class MaterialManager;
+    class MaterialScriptCompiler;
+    class Math;
+    class Matrix3;
+    class Matrix4;
+    class MemoryManager;
+    class Mesh;
+    class MeshPtr;
+    class MeshSerializer;
+    class MeshSerializerImpl;
+    class MeshManager;
+    class MovableObject;
+    class MovablePlane;
+    class Node;
+    class NodeAnimationTrack;
+    class NodeKeyFrame;
+    class NumericAnimationTrack;
+    class NumericKeyFrame;
+    class Overlay;
+    class OverlayContainer;
+    class OverlayElement;
+    class OverlayElementFactory;
+    class OverlayManager;
+    class Particle;
+    class ParticleAffector;
+    class ParticleAffectorFactory;
+    class ParticleEmitter;
+    class ParticleEmitterFactory;
+    class ParticleSystem;
+    class ParticleSystemManager;
+    class ParticleSystemRenderer;
+    class ParticleSystemRendererFactory;
+    class ParticleVisualData;
+    class Pass;
+    class PatchMesh;
+    class PixelBox;
+    class Plane;
+    class PlaneBoundedVolume;
+    class Plugin;
+    class Pose;
+    class ProgressiveMesh;
+    class Profile;
+    class Profiler;
+    class Quaternion;
+    class Radian;
+    class Ray;
+    class RaySceneQuery;
+    class RaySceneQueryListener;
+    class Renderable;
+    class RenderPriorityGroup;
+    class RenderQueue;
+    class RenderQueueGroup;
+    class RenderQueueInvocation;
+    class RenderQueueInvocationSequence;
+    class RenderQueueListener;
+    class RenderSystem;
+    class RenderSystemCapabilities;
+    class RenderTarget;
+    class RenderTargetListener;
+    class RenderTexture;
+    class MultiRenderTarget;
+    class RenderWindow;
+    class RenderOperation;
+    class Resource;
+    class ResourceBackgroundQueue;
+    class ResourceGroupManager;
+    class ResourceManager;
+    class RibbonTrail;
+    class Root;
+    class SceneManager;
+    class SceneManagerEnumerator;
+    class SceneNode;
+    class SceneQuery;
+    class SceneQueryListener;
+    class ScriptLoader;
+    class Serializer;
+    class ShadowCaster;
+    class ShadowRenderable;
+    class ShadowTextureManager;
+    class SimpleRenderable;
+    class SimpleSpline;
+    class Skeleton;
+    class SkeletonPtr;
+    class SkeletonInstance;
+    class SkeletonManager;
+    class Sphere;
+    class SphereSceneQuery;
+    class StaticGeometry;
+    class StringConverter;
+    class StringInterface;
+    class SubEntity;
+    class SubMesh;
+    class TagPoint;
+    class Technique;
+    class TempBlendedBufferInfo;
+    class ExternalTextureSource;
+    class TextureUnitState;
+    class Texture;
+    class TexturePtr;
+    class TextureFont;
+    class TextureManager;
+    class TransformKeyFrame;
+    class Timer;
+    class UserDefinedObject;
+    class Vector2;
+    class Vector3;
+    class Vector4;
+    class Viewport;
+    class VertexAnimationTrack;
+    class VertexBufferBinding;
+    class VertexData;
+    class VertexDeclaration;
+    class VertexMorphKeyFrame;
+    class WireBoundingBox;
+    class Compositor;
+    class CompositorManager;
+    class CompositorChain;
+    class CompositorInstance;
+    class CompositionTechnique;
+    class CompositionPass;
+    class CompositionTargetPass;
+
+    // Originally not in OgrePrerequisites.h
+    class BorderPanelOverlayElement;
+    class PanelOverlayElement;
+    class TextAreaOverlayElement;
+}
+
+#endif /* _OgreForwardRefs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/OrxAssert.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/OrxAssert.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/OrxAssert.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@ingroup ExceptionAssertion
+@brief
+    Declaration of custom assertion facilities
+*/
+
+#ifndef _OrxAssert_H__
+#define _OrxAssert_H__
+
+#include "UtilPrereqs.h"
+
+#include <cassert>
+#include "Output.h"
+
+#ifndef NDEBUG
+
+/** Run time assertion like assert(), but with an embedded message.
+@details
+    The message will be printed as error with orxout(user_error). <br>
+    You can use the same magic here as you can with \ref ThrowException
+    @code
+        OrxAssert(condition, "Text: " << number << " more text");
+    @endcode
+*/
+#define OrxAssert(condition, errorMessage) \
+    do \
+    { \
+        if (!(condition)) \
+        { \
+            orxout(user_error) << __FILE__ << "(" << __LINE__ << "): "; \
+            orxout(user_error) << "Assertion failed in " << __FUNCTIONNAME__ << endl; \
+            orxout(user_error) << "Expression: " << #condition << endl; \
+            orxout(user_error) << "Message   : " << errorMessage << endl; \
+            /* Don't use the condition again to avoid double evaluation */ \
+            /* Instead, stringify the expression and negate it */ \
+            assert(!#condition); \
+        } \
+    } while (false)
+
+/** Works like OrxAssert in debug mode, but also checks the condition in release
+    mode (no abort() triggered then).
+@details
+    The message will be printed as error with orxout(user_error). <br>
+    You can use the same magic here as you can with \ref ThrowException
+    @code
+        OrxVerify(condition, "Text: " << number << " more text");
+    @endcode
+*/
+#define OrxVerify(condition, errorMessage) \
+    do \
+    { \
+        if (!(condition)) \
+        { \
+            orxout(user_error) << __FILE__ << "(" << __LINE__ << "): "; \
+            orxout(user_error) << "Verification failed in " << __FUNCTIONNAME__ << endl; \
+            orxout(user_error) << "Expression: " << #condition << endl; \
+            orxout(user_error) << "Message   : " << errorMessage << endl; \
+            /* Don't use the condition again to avoid double evaluation */ \
+            /* Instead, stringify the expression and negate it */ \
+            assert(!#condition); \
+        } \
+    } while (false)
+
+#else
+
+#define OrxAssert(condition, errorMessage)  ((void)0)
+
+#define OrxVerify(condition, errorMessage) \
+    do \
+    { \
+        if (!(condition)) \
+        { \
+            orxout(user_error) << __FILE__ << "(" << __LINE__ << "): "; \
+            orxout(user_error) << "Verification failed in " << __FUNCTIONNAME__ << endl; \
+            orxout(user_error) << "Expression: " << #condition << endl; \
+            orxout(user_error) << "Message   : " << errorMessage << endl; \
+            /* No assert() in release configuration */ \
+        } \
+    } while (false)
+
+#endif
+
+#endif /* _OrxAssert_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/OrxEnum.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/OrxEnum.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/OrxEnum.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util
+*/
+
+#ifndef _OrxEnum_H__
+#define _OrxEnum_H__
+
+#include "UtilPrereqs.h"
+
+namespace orxonox
+{
+    /** Lightweight enumeration class that can be extended at run time.
+    @details
+        The class accepts type int and also defines operator int(). Therefore
+        int and OrxEnum can be used interchangeably so you can extend the content
+        of the enumeration at run time by adding ints.
+    @par Declaring an OrxEnum
+        Write a struct that inherits OrxEnum and use some macros:
+        @code
+        struct MyEnum : OrxEnum<MyEnum>
+        {
+            OrxEnumConstructors(MyEnum);
+
+            static const int Value1 = -1;
+            static const int Value2 = 0;
+            static const int Value3 = Value2 + 10;
+        };
+        @endcode
+    */
+    template <class T>
+    struct OrxEnum
+    {
+        public:
+            constexpr OrxEnum()                   : type_()                {}
+            constexpr OrxEnum(int type)           : type_(type)            {}
+            constexpr OrxEnum(const T& instance)  : type_(instance.type_)  {}
+            constexpr OrxEnum(const OrxEnum& instance) = delete;
+
+            constexpr operator int() const                  { return type_; }
+            T& operator =(int type)                         { type_ = type; return *this; }
+            constexpr bool operator <(const T& right) const { return (type_ < right.type_); }
+            constexpr bool operator >(const T& right) const { return (type_ > right.type_); }
+
+        private:
+            int type_;
+    };
+}
+
+/// See orxonox::OrxEnum for more info
+#define OrxEnumConstructors(enumName)                                  \
+constexpr enumName() { }                                               \
+constexpr enumName(int type) : OrxEnum<enumName>(type)             { } \
+constexpr enumName(const enumName& inst) : OrxEnum<enumName>(inst) { } \
+void dummyFunction()
+
+#endif /* _OrxEnum_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Output.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Output.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Output.h	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup Output Output system
+    @ingroup Util
+*/
+
+/**
+    @file
+    @ingroup Output
+    @brief Defines the helper function orxout() and includes all necessary headers to use the output system.
+
+    The output system is used to write output to the console, the logfile, and
+    other instances of orxonox::OutputListener. Each line of output is assigned
+    a level and a context. The level defines the type and importance of a
+    message, e.g. if it's a fatal error or just some internal information.
+    The context defines to which part of the program the output belongs.
+    Levels and contexts are defined in OutputDefinitions.h
+
+    Each orxonox::OutputListener can define a mask of desired levels and
+    contexts, to receive only a part of the output. Instances of
+    orxonox::SubcontextOutputListener are even able to filter sub-contexts.
+    A derivative of orxonox::BaseWriter is able to define these levels and
+    contexts through config values.
+
+    @attention
+    A message sent to the output system MUST end with "endl" or the message
+    won't be flushed.
+
+    @code
+    orxout() << "Debug output" << endl;
+    orxout(user_info) << "Orxonox version 1.2.3" << endl;
+    orxout(internal_status, context::input) << "Loading joystick" << endl;
+    @endcode
+*/
+
+#ifndef _Output_H__
+#define _Output_H__
+
+#include "UtilPrereqs.h"
+#include "output/OutputStream.h"
+
+namespace orxonox
+{
+    // Just for convenience
+    using std::endl;
+
+    /**
+        @brief This helper function returns a reference to a commonly used
+        instance of OutputStream.
+
+        It can be used like std::cout except that it is a function. You can
+        pass level and context of the following output as function arguments.
+    */
+    inline OutputStream& orxout(OutputLevel level = level::debug_output, const OutputContextContainer& context = context::undefined())
+    {
+        static OutputStream stream;
+        stream.setOutputAttributes(level, context);
+        return stream;
+    }
+
+    /**
+        @brief Shortcut for orxout() to allow passing contexts directly as
+        functions without using "()".
+
+        @code
+        orxout(user_info, context::example) << "Hello World" << endl; // calls this function
+        orxout(user_info, context::example()) << "Hello World" << endl; // calls the other orxout function
+        @endcode
+    */
+    inline OutputStream& orxout(OutputLevel level, OutputContextFunction context)
+    {
+        return orxout(level, context());
+    }
+
+    // COUT() is deprecated, please use orxout()
+    inline __DEPRECATED__(OutputStream& COUT(int level));
+
+    /**
+        @brief Writes output to the orxonox console. This function is deprecated, please use orxout()
+        @note The output level argument is ignored since it's not supported anymore. See orxout() for the new output levels.
+        @deprecated This function is deprecated. Use orxout() instead.
+    */
+    inline OutputStream& COUT(int)
+    {
+        return orxout();
+    }
+}
+
+#endif /* _Output_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Serialise.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Serialise.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Serialise.h	(revision 11817)
@@ -0,0 +1,736 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util
+    @brief Functions to serialise most of the types/classed used in Orxonox
+*/
+
+#ifndef _Serialise_H__
+#define _Serialise_H__
+
+#include "UtilPrereqs.h"
+
+#include <cstring>
+#include <set>
+#include "Math.h"
+#include "mbool.h"
+
+namespace orxonox{
+
+    /** @brief returns the size of the variable in a datastream */
+    template <class T> inline uint32_t returnSize( const T& variable );
+    /** @brief loads the value of a variable out of the bytestream and increases the mem pointer */
+    template <class T> inline void loadAndIncrease( T& variable, uint8_t*& mem );
+    /** @brief saves the value of a variable into the bytestream and increases the mem pointer */
+    template <class T> inline void saveAndIncrease( const T& variable, uint8_t*& mem );
+    /** @brief checks whether the variable of type T is the same as in the bytestream */
+    template <class T> inline bool checkEquality( const T& variable, uint8_t* mem );
+
+
+  // =========== char*
+
+  inline uint32_t returnSize(const char*& variable )
+  {
+    return strlen(variable)+1;
+  }
+
+  inline void saveAndIncrease(const char*& variable, uint8_t*& mem )
+  {
+    uint32_t len = returnSize(variable);
+    std::memcpy(mem, variable, len);
+    mem += len;
+  }
+
+  inline void loadAndIncrease( char*& variable, uint8_t*& mem )
+  {
+    if( variable )
+      delete variable;
+    uint32_t len = returnSize((const char*&)mem);
+    variable = new char[len];
+    std::memcpy(variable, mem, len);
+    mem += len;
+  }
+
+  inline bool checkEquality( char*& variable, uint8_t* mem )
+  {
+    return strcmp(variable, (char*)mem)==0;
+  }
+
+// =================== Template specialisation stuff =============
+
+// =========== bool
+
+    template <> inline uint32_t returnSize( const bool& )
+    {
+        return sizeof(uint8_t);
+    }
+
+    template <> inline void loadAndIncrease( bool& variable, uint8_t*& mem )
+    {
+        *(uint8_t*)( &variable ) = *static_cast<uint8_t*>(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const bool& variable, uint8_t*& mem )
+    {
+        *static_cast<uint8_t*>(mem) = *(uint8_t*)( &variable );
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const bool& variable, uint8_t* mem )
+    {
+        return *static_cast<uint8_t*>(mem) == *(uint8_t*)( &variable );
+    }
+
+// =========== char
+
+    template <> inline uint32_t returnSize( const char& )
+    {
+        return sizeof(uint8_t);
+    }
+
+    template <> inline void loadAndIncrease( char& variable, uint8_t*& mem )
+    {
+        *(uint8_t*)( &variable ) = *static_cast<uint8_t*>(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const char& variable, uint8_t*& mem )
+    {
+        *static_cast<uint8_t*>(mem) = *(uint8_t*)( &variable );
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const char& variable, uint8_t* mem )
+    {
+        return *static_cast<uint8_t*>(mem) == *(uint8_t*)( &variable );
+    }
+
+// =========== unsigned char
+
+    template <> inline uint32_t returnSize( const unsigned char& )
+    {
+        return sizeof(uint8_t);
+    }
+
+    template <> inline void loadAndIncrease( unsigned char& variable, uint8_t*& mem )
+    {
+        *(uint8_t*)( &variable ) = *static_cast<uint8_t*>(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const unsigned char& variable, uint8_t*& mem )
+    {
+        *static_cast<uint8_t*>(mem) = *(uint8_t*)( &variable );
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const unsigned char& variable, uint8_t* mem )
+    {
+        return *static_cast<uint8_t*>(mem) == *(uint8_t*)( &variable );
+    }
+
+// =========== short
+
+    template <> inline uint32_t returnSize( const short& )
+    {
+        return sizeof(int16_t);
+    }
+
+    template <> inline void loadAndIncrease( short& variable, uint8_t*& mem )
+    {
+        *(short*)( &variable ) = *(int16_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const short& variable, uint8_t*& mem )
+    {
+        *(int16_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const short& variable, uint8_t* mem )
+    {
+        return *(int16_t*)(mem) == static_cast<int16_t>(variable);
+    }
+
+// =========== unsigned short
+
+    template <> inline uint32_t returnSize( const unsigned short& )
+    {
+        return sizeof(uint16_t);
+    }
+
+    template <> inline void loadAndIncrease( unsigned short& variable, uint8_t*& mem )
+    {
+        *(unsigned short*)( &variable ) = *(uint16_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const unsigned short& variable, uint8_t*& mem )
+    {
+        *(uint16_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const unsigned short& variable, uint8_t* mem )
+    {
+        return *(uint16_t*)(mem) == variable;
+    }
+
+// =========== int
+
+    template <> inline uint32_t returnSize( const int& )
+    {
+        return sizeof(int32_t);
+    }
+
+    template <> inline void loadAndIncrease( int& variable, uint8_t*& mem )
+    {
+        *(int *)( &variable ) = *(int32_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const int& variable, uint8_t*& mem )
+    {
+        *(int32_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const int& variable, uint8_t* mem )
+    {
+        return *(int32_t*)(mem) == variable;
+    }
+
+// =========== unsigned int
+
+    template <> inline uint32_t returnSize( const unsigned int& )
+    {
+        return sizeof(uint32_t);
+    }
+
+    template <> inline void loadAndIncrease( unsigned int& variable, uint8_t*& mem )
+    {
+        *(unsigned int*)( &variable ) = *(uint32_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const unsigned int& variable, uint8_t*& mem )
+    {
+        *(uint32_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const unsigned int& variable, uint8_t* mem )
+    {
+        return *(uint32_t*)(mem) == variable;
+    }
+
+// =========== long
+
+    template <> inline uint32_t returnSize( const long& )
+    {
+        return sizeof(int32_t);
+    }
+
+    template <> inline void loadAndIncrease( long& variable, uint8_t*& mem )
+    {
+        *(long*)( &variable ) = *(int32_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const long& variable, uint8_t*& mem )
+    {
+        *(int32_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const long& variable, uint8_t* mem )
+    {
+        return *(int32_t*)(mem) == variable;
+    }
+
+// =========== unsigned long
+
+    template <> inline uint32_t returnSize( const unsigned long& )
+    {
+        return sizeof(uint32_t);
+    }
+
+    template <> inline void loadAndIncrease( unsigned long& variable, uint8_t*& mem )
+    {
+        *(unsigned long*)( &variable ) = *(uint32_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const unsigned long& variable, uint8_t*& mem )
+    {
+        *(uint32_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const unsigned long& variable, uint8_t* mem )
+    {
+        return *(uint32_t*)(mem) == variable;
+    }
+
+// =========== long long
+
+    template <> inline uint32_t returnSize( const long long& )
+    {
+        return sizeof(int64_t);
+    }
+
+    template <> inline void loadAndIncrease( long long& variable, uint8_t*& mem )
+    {
+        *(long long*)( &variable ) = *(int64_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const long long& variable, uint8_t*& mem )
+    {
+        *(int64_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const long long& variable, uint8_t* mem )
+    {
+        return *(int64_t*)(mem) == variable;
+    }
+
+// =========== unsigned long long
+
+    template <> inline uint32_t returnSize( const unsigned long long& )
+    {
+        return sizeof(uint64_t);
+    }
+
+    template <> inline void loadAndIncrease( unsigned long long& variable, uint8_t*& mem )
+    {
+        *(unsigned long long*)( &variable ) = *(uint64_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const unsigned long long& variable, uint8_t*& mem )
+    {
+        *(uint64_t*)(mem) = variable;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const unsigned long long& variable, uint8_t* mem )
+    {
+        return *(uint64_t*)(mem) == variable;
+    }
+
+// =========== float
+
+    template <> inline uint32_t returnSize( const float& )
+    {
+        return sizeof(uint32_t);
+    }
+
+    template <> inline void loadAndIncrease( float& variable, uint8_t*& mem )
+    {
+        *(uint32_t*)( &variable ) = *(uint32_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const float& variable, uint8_t*& mem )
+    {
+        *(uint32_t*)(mem) = *(uint32_t*)( &variable );
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const float& variable, uint8_t* mem )
+    {
+        return *(uint32_t*)(mem) == *(uint32_t*)( &variable );
+    }
+
+// =========== double
+
+    template <> inline uint32_t returnSize( const double& )
+    {
+        return sizeof(uint64_t);
+    }
+
+    template <> inline void loadAndIncrease( double& variable, uint8_t*& mem )
+    {
+        *(uint64_t*)( &variable ) = *(uint64_t*)(mem);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const double& variable, uint8_t*& mem )
+    {
+        *(uint64_t*)(mem) = *(uint64_t*)( &variable );
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const double& variable, uint8_t* mem )
+    {
+        return *(uint64_t*)(mem) == *(uint64_t*)( &variable );
+    }
+
+// =========== long double
+
+    template <> inline uint32_t returnSize( const long double& )
+    {
+        return sizeof(uint64_t);
+    }
+
+    template <> inline void loadAndIncrease( long double& variable, uint8_t*& mem )
+    {
+        double temp;
+        memcpy(&temp, mem, sizeof(uint64_t));
+        *(long double*)( &variable ) = static_cast<long double>(temp);
+        mem += returnSize( variable );
+    }
+
+    template <> inline void saveAndIncrease( const long double& variable, uint8_t*& mem )
+    {
+        double temp = static_cast<double>(variable);
+        memcpy(mem, &temp, sizeof(uint64_t));
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const long double& variable, uint8_t* mem )
+    {
+        double temp = static_cast<double>(variable);
+        return memcmp(&temp, mem, sizeof(uint64_t))==0;
+    }
+
+// =========== string
+
+    template <> inline uint32_t returnSize( const std::string& variable )
+    {
+        return variable.length()+1;
+    }
+
+    template <> inline void saveAndIncrease( const std::string& variable, uint8_t*& mem )
+    {
+        memcpy(mem, variable.c_str(), variable.length()+1);
+        mem += variable.length()+1;
+    }
+
+    template <> inline void loadAndIncrease( std::string& variable, uint8_t*& mem )
+    {
+        *(std::string*)( &variable ) = (const char *)mem;
+        mem += variable.length()+1;
+    }
+
+    template <> inline bool checkEquality( const std::string& variable, uint8_t* mem )
+    {
+        //return std::string((const char*)mem)==variable;
+        return (const char*)mem==variable;
+    }
+
+// =========== Degree
+
+    template <> inline uint32_t returnSize( const Degree& )
+    {
+        return sizeof(Ogre::Real);
+    }
+
+    template <> inline void saveAndIncrease( const Degree& variable, uint8_t*& mem )
+    {
+        Ogre::Real r = variable.valueDegrees();
+        memcpy(mem, &r, returnSize( variable ));
+        mem += returnSize( variable );
+    }
+
+    template <> inline void loadAndIncrease( Degree& variable, uint8_t*& mem )
+    {
+        Ogre::Real* r = (Ogre::Real*)mem;
+        (Degree&)variable = *r;
+        mem += returnSize( variable );
+    }
+
+     template <> inline bool checkEquality( const Degree& variable, uint8_t* mem )
+    {
+        Ogre::Real* r = (Ogre::Real*)mem;
+        return variable==Degree(*r);
+    }
+
+// =========== Radian
+
+    template <> inline uint32_t returnSize( const Radian& )
+    {
+        return sizeof(Ogre::Real);
+    }
+
+    template <> inline void saveAndIncrease( const Radian& variable, uint8_t*& mem )
+    {
+        Ogre::Real r = variable.valueRadians();
+        memcpy(mem, &r, returnSize( variable ));
+        mem += returnSize( variable );
+    }
+
+    template <> inline void loadAndIncrease( Radian& variable, uint8_t*& mem )
+    {
+        Ogre::Real* r = (Ogre::Real*)mem;
+        (Radian&)variable = *r;
+        mem += returnSize( variable );
+    }
+
+    template <> inline bool checkEquality( const Radian& variable, uint8_t* mem )
+    {
+        Ogre::Real* r = (Ogre::Real*)mem;
+        return variable==Degree(*r);
+    }
+
+    // =========== Vector2
+
+    template <> inline uint32_t returnSize( const Vector2& variable )
+    {
+        return returnSize( variable.x )+returnSize( variable.y );
+    }
+
+    template <> inline void saveAndIncrease( const Vector2& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( variable.x, mem );
+        saveAndIncrease( variable.y, mem );
+    }
+
+    template <> inline void loadAndIncrease( Vector2& variable, uint8_t*& mem )
+    {
+        loadAndIncrease( variable.x, mem );
+        loadAndIncrease( variable.y, mem );
+    }
+
+    template <> inline bool checkEquality( const Vector2& variable, uint8_t* mem )
+    {
+        return checkEquality(variable.x, mem) && checkEquality(variable.y, mem+returnSize(variable.x));
+    }
+
+    // =========== Vector3
+
+    template <> inline uint32_t returnSize( const Vector3& variable )
+    {
+        return returnSize( variable.x )+returnSize( variable.y )+returnSize( variable.z );
+    }
+
+    template <> inline void saveAndIncrease( const Vector3& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( variable.x, mem );
+        saveAndIncrease( variable.y, mem );
+        saveAndIncrease( variable.z, mem );
+    }
+
+    template <> inline void loadAndIncrease( Vector3& variable, uint8_t*& mem )
+    {
+        loadAndIncrease( variable.x, mem );
+        loadAndIncrease( variable.y, mem );
+        loadAndIncrease( variable.z, mem );
+    }
+
+    template <> inline bool checkEquality( const Vector3& variable, uint8_t* mem )
+    {
+        return checkEquality(variable.x, mem) && checkEquality(variable.y, mem+returnSize(variable.x)) &&
+            checkEquality(variable.z, mem+returnSize(variable.x)+returnSize(variable.y));
+    }
+
+    // =========== Vector4
+
+    template <> inline uint32_t returnSize( const Vector4& variable )
+    {
+        return returnSize( variable.w )+returnSize( variable.x )+returnSize( variable.y )+returnSize( variable.z );
+    }
+
+    template <> inline void saveAndIncrease( const Vector4& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( variable.w, mem );
+        saveAndIncrease( variable.x, mem );
+        saveAndIncrease( variable.y, mem );
+        saveAndIncrease( variable.z, mem );
+    }
+
+    template <> inline void loadAndIncrease( Vector4& variable, uint8_t*& mem )
+    {
+        loadAndIncrease( variable.w, mem );
+        loadAndIncrease( variable.x, mem );
+        loadAndIncrease( variable.y, mem );
+        loadAndIncrease( variable.z, mem );
+    }
+
+    template <> inline bool checkEquality( const Vector4& variable, uint8_t* mem )
+    {
+        return checkEquality(variable.w, mem) && checkEquality(variable.x, mem+returnSize(variable.w)) &&
+            checkEquality(variable.y, mem+returnSize(variable.w)+returnSize(variable.x)) &&
+            checkEquality(variable.z, mem+returnSize(variable.w)+returnSize(variable.x)+returnSize(variable.y));
+    }
+
+    // =========== Quaternion
+
+    template <> inline uint32_t returnSize( const Quaternion& variable )
+    {
+        return returnSize( variable.w )+returnSize( variable.x )+returnSize( variable.y )+returnSize( variable.z );
+    }
+
+    template <> inline void saveAndIncrease( const Quaternion& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( variable.w, mem );
+        saveAndIncrease( variable.x, mem );
+        saveAndIncrease( variable.y, mem );
+        saveAndIncrease( variable.z, mem );
+    }
+
+    template <> inline void loadAndIncrease( Quaternion& variable, uint8_t*& mem )
+    {
+        loadAndIncrease( variable.w, mem );
+        loadAndIncrease( variable.x, mem );
+        loadAndIncrease( variable.y, mem );
+        loadAndIncrease( variable.z, mem );
+    }
+
+    template <> inline bool checkEquality( const Quaternion& variable, uint8_t* mem )
+    {
+        return checkEquality(variable.w, mem) && checkEquality(variable.x, mem+returnSize(variable.w)) &&
+            checkEquality(variable.y, mem+returnSize(variable.w)+returnSize(variable.x)) &&
+            checkEquality(variable.z, mem+returnSize(variable.w)+returnSize(variable.x)+returnSize(variable.y));
+    }
+
+    // =========== ColourValue
+
+    template <> inline uint32_t returnSize( const ColourValue& variable )
+    {
+        return returnSize( variable.r )+returnSize( variable.g )+returnSize( variable.b )+returnSize( variable.a );
+    }
+
+    template <> inline void saveAndIncrease( const ColourValue& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( variable.r, mem );
+        saveAndIncrease( variable.g, mem );
+        saveAndIncrease( variable.b, mem );
+        saveAndIncrease( variable.a, mem );
+    }
+
+    template <> inline void loadAndIncrease( ColourValue& variable, uint8_t*& mem )
+    {
+        loadAndIncrease( variable.r, mem );
+        loadAndIncrease( variable.g, mem );
+        loadAndIncrease( variable.b, mem );
+        loadAndIncrease( variable.a, mem );
+    }
+
+    template <> inline bool checkEquality( const ColourValue& variable, uint8_t* mem )
+    {
+        return checkEquality(variable.r, mem) && checkEquality(variable.g, mem+returnSize(variable.r)) &&
+            checkEquality(variable.b, mem+returnSize(variable.r)+returnSize(variable.g)) &&
+            checkEquality(variable.a, mem+returnSize(variable.r)+returnSize(variable.g)+returnSize(variable.b));
+    }
+
+    // =========== mbool
+
+    template <> inline uint32_t returnSize( const mbool& variable )
+    {
+        return returnSize( (unsigned char&)((mbool&)variable).getMemory() );
+    }
+
+    template <> inline void saveAndIncrease( const mbool& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( (unsigned char&)((mbool&)variable).getMemory(), mem );
+    }
+
+    template <> inline void loadAndIncrease( mbool& variable, uint8_t*& mem )
+    {
+        loadAndIncrease( (unsigned char&)((mbool&)variable).getMemory(), mem );
+    }
+
+    template <> inline bool checkEquality( const mbool& variable, uint8_t* mem )
+    {
+        return checkEquality( (unsigned char&)((mbool&)variable).getMemory(), mem );
+    }
+
+    // =========== std::set
+
+    template <class T> inline uint32_t returnSize( const std::set<T>& variable )
+    {
+        uint32_t tempsize = sizeof(uint32_t); // for the number of entries
+        for(const T& element : *((std::set<T>*)(&variable)))
+            tempsize += returnSize( element );
+        return tempsize;
+    }
+
+    template <class T> inline void saveAndIncrease(  const std::set<T>& variable, uint8_t*& mem )
+    {
+        saveAndIncrease( (uint32_t)variable.size(), mem );
+        for( const T& elem : variable )
+            saveAndIncrease( elem, mem );
+    }
+
+    template <class T> inline void loadAndIncrease(std::set<T>& variable, uint8_t*& mem )
+    {
+        uint32_t nrOfElements = 0;
+        loadAndIncrease( nrOfElements, mem );
+        typename std::set<T>::iterator it = variable.begin();
+        for( uint32_t i = 0; i<nrOfElements; ++i )
+        {
+            T temp;
+            loadAndIncrease(temp, mem);
+            while( it!=variable.end() && *it!=temp )
+            {
+                variable.erase(it++);
+                ++it;
+            }
+            if( it==variable.end() )
+            {
+                variable.insert(temp);
+            }
+        }
+    }
+
+    template <class T> inline bool checkEquality( const std::set<T>& variable, uint8_t* mem )
+    {
+        uint8_t* temp = mem;
+        uint32_t nrOfElements;
+        loadAndIncrease(nrOfElements, mem);
+        if( variable.size() == nrOfElements )
+        {
+            T tempT;
+            for( uint32_t i=0; i<nrOfElements; ++i )
+            {
+                loadAndIncrease(tempT, mem);
+                if( variable.find(tempT) == variable.end() )
+                {
+                    mem = temp;
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            mem = temp;
+            return false;
+        }
+        return true;
+    }
+}
+
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/util/SignalHandler.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/SignalHandler.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/SignalHandler.cc	(revision 11817)
@@ -0,0 +1,783 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Christoph Renner (Linux implementation)
+ *      Fabian 'x3n' Landau (Windows implementation)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the SignalHandler class.
+*/
+
+#include "SignalHandler.h"
+
+#include <iostream>
+#include <cstdlib>
+#include <cstring>
+#include <cstdio>
+
+#include "Output.h"
+
+namespace orxonox
+{
+    SignalHandler* SignalHandler::singletonPtr_s = nullptr;
+}
+
+#if defined(ORXONOX_PLATFORM_LINUX)
+
+#include <wait.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include <sys/prctl.h>
+#include <unistd.h>
+
+namespace orxonox
+{
+    /**
+     * register signal handlers for SIGSEGV and SIGABRT
+     * @param appName path to executable eg argv[0]
+     * @param filename filename to append backtrace to
+     */
+    void SignalHandler::doCatch( const std::string & appName, const std::string & filename )
+    {
+      this->appName = appName;
+      this->filename = filename;
+
+      // make sure doCatch is only called once without calling dontCatch
+      assert( sigRecList.size() == 0 );
+
+      catchSignal( SIGSEGV );
+      catchSignal( SIGABRT );
+      catchSignal( SIGILL );
+    }
+
+    /**
+     * restore previous signal handlers
+     */
+    void SignalHandler::dontCatch()
+    {
+      for (const SignalRec& sigRec : sigRecList)
+      {
+        signal( sigRec.signal, sigRec.handler );
+      }
+
+      sigRecList.clear();
+    }
+
+    /**
+     * catch signal sig
+     * @param sig signal to catch
+     */
+    void SignalHandler::catchSignal( int sig )
+    {
+      sig_t handler = signal( sig, SignalHandler::sigHandler );
+
+      assert( handler != SIG_ERR );
+
+      SignalRec rec;
+      rec.signal = sig;
+      rec.handler = handler;
+
+      sigRecList.push_front( rec );
+    }
+
+    /**
+     * sigHandler is called when receiving signals
+     * @param sig
+     */
+    void SignalHandler::sigHandler( int sig )
+    {
+      std::string sigName = "UNKNOWN";
+
+      switch ( sig )
+      {
+        case SIGSEGV:
+          sigName = "SIGSEGV";
+          break;
+        case SIGABRT:
+          sigName = "SIGABRT";
+          break;
+        case SIGILL:
+          sigName = "SIGILL";
+          break;
+      }
+      // if the signalhandler has already been destroyed then don't do anything
+      if( SignalHandler::singletonPtr_s == nullptr )
+      {
+        orxout(user_error) << "Received signal " << sigName.c_str() << endl << "Can't write backtrace because SignalHandler is already destroyed" << endl;
+        exit(EXIT_FAILURE);
+      }
+
+      for (const SignalCallbackRec& callback : SignalHandler::getInstance().callbackList)
+      {
+        (*(callback.cb))( callback.someData );
+      }
+
+
+      orxout(user_error) << "Received signal " << sigName.c_str() << endl << "Try to write backtrace to file orxonox_crash.log" << endl;
+
+
+      // First start GDB which will be attached to this process later on
+
+      int gdbIn[2];
+      int gdbOut[2];
+      int gdbErr[2];
+
+      if ( pipe(gdbIn) == -1 || pipe(gdbOut) == -1 || pipe(gdbErr) == -1 )
+      {
+        perror("pipe failed!\n");
+        exit(EXIT_FAILURE);
+      }
+
+      int gdbPid = fork();
+      // this process will run gdb
+
+      if ( gdbPid == -1 )
+      {
+        perror("fork failed\n");
+        exit(EXIT_FAILURE);
+      }
+
+      if ( gdbPid == 0 )
+      {
+        // start gdb
+
+        close(gdbIn[1]);
+        close(gdbOut[0]);
+        close(gdbErr[0]);
+
+        dup2( gdbIn[0], STDIN_FILENO );
+        dup2( gdbOut[1], STDOUT_FILENO );
+        dup2( gdbErr[1], STDERR_FILENO );
+
+        execlp( "sh", "sh", "-c", "gdb", static_cast<void*>(nullptr));
+      }
+
+
+      // Now start a fork of this process on which GDB will be attached on
+
+      int sigPipe[2];
+      if ( pipe(sigPipe) == -1 )
+      {
+        perror("pipe failed!\n");
+        kill( gdbPid, SIGTERM );
+        waitpid( gdbPid, nullptr, 0 );
+        exit(EXIT_FAILURE);
+      }
+
+      int sigPid = fork();
+
+      if ( sigPid == -1 )
+      {
+        perror("fork failed!\n");
+        kill( gdbPid, SIGTERM );
+        waitpid( gdbPid, nullptr, 0 );
+        exit(EXIT_FAILURE);
+      }
+
+      // gdb will be attached to this process
+      if ( sigPid == 0 )
+      {
+        getInstance().dontCatch();
+
+        // make sure gdb is allowed to attach to our PID even if there are some system restrictions
+#ifdef PR_SET_PTRACER
+        if( prctl(PR_SET_PTRACER, gdbPid, 0, 0, 0) == -1 )
+          orxout(user_error) << "could not set proper permissions for GDB to attach to process..." << endl;
+#endif
+
+        // wait for message from parent when it has attached gdb
+        int someData;
+
+        if( read( sigPipe[0], &someData, sizeof(someData) ) != sizeof(someData) )
+          orxout(user_error) << "something went wrong :(" << endl;
+
+        if ( someData != 0x12345678 )
+        {
+          orxout(user_error) << "something went wrong :(" << endl;
+        }
+
+        return;
+      }
+
+      char cmd[256];
+      snprintf( cmd, 256, "file %s\nattach %d\nc\n", getInstance().appName.c_str(), sigPid );
+      write( gdbIn[1], cmd, strlen(cmd) );
+
+      int charsFound = 0;
+      int promptFound = 0;
+      char byte;
+      while ( read( gdbOut[0], &byte, 1 ) == 1 )
+      {
+        if (
+          (charsFound == 0 && byte == '(') ||
+          (charsFound == 1 && byte == 'g') ||
+          (charsFound == 2 && byte == 'd') ||
+          (charsFound == 3 && byte == 'b') ||
+          (charsFound == 4 && byte == ')') ||
+          (charsFound == 5 && byte == ' ')
+            )
+              charsFound++;
+        else
+          charsFound = 0;
+
+        if ( charsFound == 6 )
+        {
+          promptFound++;
+          charsFound = 0;
+        }
+
+        if ( promptFound == 3 )
+        {
+          break;
+        }
+      }
+
+      int someData = 0x12345678;
+      write( sigPipe[1], &someData, sizeof(someData) );
+
+      write( gdbIn[1], "bt\nk\nq\n", 7 );
+
+
+      charsFound = 0;
+      promptFound = 0;
+      std::string bt;
+      while ( read( gdbOut[0], &byte, 1 ) == 1 )
+      {
+        bt += std::string( &byte, 1 );
+
+        if (
+          (charsFound == 0 && byte == '(') ||
+          (charsFound == 1 && byte == 'g') ||
+          (charsFound == 2 && byte == 'd') ||
+          (charsFound == 3 && byte == 'b') ||
+          (charsFound == 4 && byte == ')') ||
+          (charsFound == 5 && byte == ' ')
+            )
+              charsFound++;
+        else
+          charsFound = 0;
+
+        if ( charsFound == 6 )
+        {
+          promptFound++;
+          charsFound = 0;
+          bt += "\n";
+        }
+
+        if ( promptFound == 3 )
+        {
+          break;
+        }
+      }
+
+
+      waitpid( sigPid, nullptr, 0 );
+      waitpid( gdbPid, nullptr, 0 );
+
+      int wsRemoved = 0;
+
+      while ( wsRemoved < 2 && bt.length() > 0 )
+      {
+        if ( bt[1] == '\n' )
+          wsRemoved++;
+        bt.erase(0, 1);
+      }
+
+      if ( bt.length() > 0 )
+        bt.erase(0, 1);
+
+      time_t now = time(nullptr);
+
+      std::string timeString =
+                         "=======================================================\n"
+                         "= time: " + std::string(ctime(&now)) +
+                         "=======================================================\n";
+      bt.insert(0, timeString);
+
+      FILE * f = fopen( getInstance().filename.c_str(), "w" );
+
+      if ( !f )
+      {
+        perror( ( std::string( "could not append to " ) + getInstance().filename ).c_str() );
+        exit(EXIT_FAILURE);
+      }
+
+      if ( fwrite( bt.c_str(), 1, bt.length(), f ) != bt.length() )
+      {
+        orxout(user_error) << "could not write " << bt.length() << " byte to " << getInstance().filename << endl;
+        exit(EXIT_FAILURE);
+      }
+
+      exit(EXIT_FAILURE);
+    }
+
+    void SignalHandler::registerCallback( SignalCallback cb, void * someData )
+    {
+      SignalCallbackRec rec;
+      rec.cb = cb;
+      rec.someData = someData;
+
+      callbackList.push_back(rec);
+    }
+}
+
+#elif defined(ORXONOX_PLATFORM_WINDOWS) && defined(DBGHELP_FOUND)
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <ctime>
+#include <dbghelp.h>
+#include <tlhelp32.h>
+
+#include "Convert.h"
+
+#ifdef ORXONOX_COMPILER_GCC
+#   include <cxxabi.h>
+#endif
+
+#ifdef ORXONOX_COMPILER_GCC
+/// Overwrite the original abort() function in MinGW to enable a break point.
+_UtilExport void __cdecl abort()
+{
+    using namespace orxonox;
+    orxout(user_error) << "This application has requested the Runtime to terminate it in an unusual way." << endl;
+    orxout(user_error) << "Please contact the application's support team for more information." << endl;
+    DebugBreak();
+    exit(0x3);
+}
+
+/// Overwrite the original _abort() function in MinGW to enable a break point.
+_UtilExport void __cdecl _assert(const char* expression, const char* file, int line)
+{
+    using namespace orxonox;
+    orxout(user_error) << "Assertion failed: " << expression << ", file " << file << ", line " << line << endl;
+    orxout(user_error) << endl;
+    abort();
+}
+#endif
+
+namespace orxonox
+{
+    /// Constructor: Initializes the values, but doesn't register the exception handler.
+    SignalHandler::SignalHandler()
+    {
+        this->prevExceptionFilter_ = nullptr;
+    }
+
+    /// Destructor: Removes the exception handler.
+    SignalHandler::~SignalHandler()
+    {
+        if (this->prevExceptionFilter_ != nullptr)
+        {
+            // Remove the unhandled exception filter function
+            SetUnhandledExceptionFilter(this->prevExceptionFilter_);
+            this->prevExceptionFilter_ = nullptr;
+        }
+    }
+
+    /// Registers an exception handler and initializes the filename of the crash log.
+    void SignalHandler::doCatch(const std::string&, const std::string& filename)
+    {
+        this->filename_ = filename;
+
+        // don't register twice
+        assert(this->prevExceptionFilter_ == nullptr);
+
+        if (this->prevExceptionFilter_ == nullptr)
+        {
+            // Install the unhandled exception filter function
+            this->prevExceptionFilter_ = SetUnhandledExceptionFilter(&SignalHandler::exceptionFilter);
+        }
+    }
+
+    /// Exception handler: Will be called by Windows if an unhandled exceptions occurs.
+    /* static */ LONG WINAPI SignalHandler::exceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
+    {
+        // avoid loops
+        static bool bExecuting = false;
+
+        if (!bExecuting)
+        {
+            bExecuting = true;
+
+            orxout(user_error) << endl;
+
+            // if the signalhandler has already been destroyed then don't do anything
+            if (SignalHandler::singletonPtr_s == nullptr)
+            {
+                orxout(user_error) << "Caught an unhandled exception" << endl << "Can't write backtrace because SignalHandler is already destroyed" << endl;
+                exit(EXIT_FAILURE);
+            }
+
+            orxout(user_error) << "Caught an unhandled exception" << endl << "Try to write backtrace to orxonox_crash.log..." << endl;
+
+            // write the crash log
+            std::ofstream crashlog(SignalHandler::getInstance().filename_.c_str());
+
+            time_t now = time(nullptr);
+
+            crashlog << "=======================================================" << endl;
+            crashlog << "= Time: " << std::string(ctime(&now));
+            crashlog << "=======================================================" << endl;
+            crashlog << endl;
+
+            const std::string& error = SignalHandler::getExceptionType(pExceptionInfo);
+
+            crashlog << error << endl;
+            crashlog << endl;
+
+            const std::string& callstack = SignalHandler::getStackTrace(pExceptionInfo);
+
+            crashlog << "Call stack:" << endl;
+            crashlog << callstack << endl;
+
+            crashlog.close();
+
+            // print the same information also to the console
+            orxout(user_error) << endl;
+            orxout(user_error) << error << endl;
+            orxout(user_error) << endl;
+            orxout(user_error) << "Call stack:" << endl;
+            orxout(user_error) << callstack << endl;
+
+            bExecuting = false;
+        }
+        else
+        {
+            orxout(user_error) << "An error occurred while writing the backtrace" << endl;
+        }
+
+        if (SignalHandler::getInstance().prevExceptionFilter_)
+            return SignalHandler::getInstance().prevExceptionFilter_(pExceptionInfo);
+        else
+            return EXCEPTION_CONTINUE_SEARCH;
+    }
+
+    /// Returns the stack trace for either the current function, or, if @a pExceptionInfo is not nullptr, for the given exception context.
+    /* static */ std::string SignalHandler::getStackTrace(PEXCEPTION_POINTERS pExceptionInfo)
+    {
+        // Initialise the symbol table to get function names:
+        SymSetOptions
+        (
+            SYMOPT_DEFERRED_LOADS
+#ifndef ORXONOX_COMPILER_GCC
+            | SYMOPT_UNDNAME
+#endif
+        );
+        SymInitialize(GetCurrentProcess(), 0, true);
+
+        // Store the current stack frame here:
+        STACKFRAME64 frame;
+        memset(&frame, 0, sizeof(STACKFRAME64));
+
+        // Get processor information for the current thread:
+        CONTEXT context;
+        memset(&context, 0, sizeof(CONTEXT));
+
+        if (pExceptionInfo)
+        {
+            // get the context of the exception
+            context = *pExceptionInfo->ContextRecord;
+        }
+        else
+        {
+            context.ContextFlags = CONTEXT_FULL;
+
+            // Load the RTLCapture context function:
+            HMODULE kernel32 = LoadLibrary("Kernel32.dll");
+            typedef void (*RtlCaptureContextFunc) (CONTEXT* ContextRecord);
+            RtlCaptureContextFunc rtlCaptureContext = (RtlCaptureContextFunc) GetProcAddress(kernel32, "RtlCaptureContext");
+
+            // Capture the thread context
+            rtlCaptureContext(&context);
+        }
+
+        DWORD type;
+
+        // set the flags and initialize the stackframe struct
+#ifdef _M_IX86
+        type = IMAGE_FILE_MACHINE_I386;
+
+        frame.AddrPC.Offset         = context.Eip;              // program counter
+        frame.AddrFrame.Offset      = context.Ebp;              // frame pointer (for function arguments)
+        frame.AddrStack.Offset      = context.Esp;              // stack pointer
+#elif _M_X64
+        type = IMAGE_FILE_MACHINE_AMD64;
+
+        frame.AddrPC.Offset         = context.Rip;              // program counter
+        frame.AddrFrame.Offset      = context.Rbp; // (or Rdi)  // frame pointer (for function arguments)
+        frame.AddrStack.Offset      = context.Rsp;              // stack pointer
+#elif _M_IA64
+        type = IMAGE_FILE_MACHINE_IA64;
+
+        frame.AddrPC.Offset         = context.StIIP;            // program counter
+        frame.AddrFrame.Offset      = context.RsBSP;            // frame pointer (for function arguments) // <-- unneeded on Intel IPF, may be removed
+        frame.AddrStack.Offset      = context.IntSp;            // stack pointer
+        frame.AddrBStore.Offset     = context.RsBSP;            // backing store
+        frame.AddrBStore.Mode       = AddrModeFlat;
+#else
+        return "";
+#endif
+
+        frame.AddrPC.Mode           = AddrModeFlat;
+        frame.AddrFrame.Mode        = AddrModeFlat;
+        frame.AddrStack.Mode        = AddrModeFlat;
+
+        std::string output;
+
+        // Keep getting stack frames from windows till there are no more left:
+        for (int i = 0;
+            StackWalk64
+            (
+                type                      ,      // MachineType
+                GetCurrentProcess()       ,      // Process to get stack trace for
+                GetCurrentThread()        ,      // Thread to get stack trace for
+                &frame                    ,      // Where to store next stack frame
+                &context                  ,      // Pointer to processor context record
+                0                         ,      // Routine to read process memory: use the default ReadProcessMemory
+                &SymFunctionTableAccess64 ,      // Routine to access the modules symbol table
+                &SymGetModuleBase64       ,      // Routine to access the modules base address
+                0                                // Something to do with 16-bit code. Not needed.
+            );
+            ++i
+        )
+        {
+            //------------------------------------------------------------------
+            // Declare an image help symbol structure to hold symbol info and
+            // name up to 256 chars This struct is of variable lenght though so
+            // it must be declared as a raw byte buffer.
+            //------------------------------------------------------------------
+            static char symbolBuffer[sizeof(SYMBOL_INFO) + 255];
+            memset(symbolBuffer, 0, sizeof(symbolBuffer));
+
+            // Cast it to a symbol struct:
+            SYMBOL_INFO* symbol = (SYMBOL_INFO*)symbolBuffer;
+
+            // Need to set two fields of this symbol before obtaining name info:
+            symbol->SizeOfStruct    = sizeof(SYMBOL_INFO);
+            symbol->MaxNameLen      = 255;
+
+            // The displacement from the beginning of the symbol is stored here: pretty useless
+            long long unsigned int displacement = 0;
+
+            if (i < 10)
+                output += " ";
+            output += multi_cast<std::string>(i) + ": ";
+
+            // Print the function's address:
+            output += SignalHandler::pointerToString(frame.AddrPC.Offset);
+
+            // Get the symbol information from the address of the instruction pointer register:
+            bool bCorrected = false;
+            BOOL result = SymFromAddr
+            (
+                GetCurrentProcess() ,   // Process to get symbol information for
+                frame.AddrPC.Offset ,   // Address to get symbol for: instruction pointer register
+                &displacement       ,   // Displacement from the beginning of the symbol
+                symbol                  // Where to save the symbol
+            );
+
+            // If the symbol was found, but the displacement is 0, we likely got the wrong symbol - decrease the program counter and try again
+            if (result && displacement == 0)
+            {
+                bCorrected = true;
+                result = SymFromAddr
+                (
+                    GetCurrentProcess()     ,
+                    frame.AddrPC.Offset - 1 ,
+                    &displacement           ,
+                    symbol
+                );
+            }
+
+            // Display the function name + offset
+            if (result)
+            {
+                // Add the name of the function to the function list:
+                output += " ";
+
+#ifdef ORXONOX_COMPILER_GCC
+                int status;
+                char* demangled = __cxxabiv1::__cxa_demangle(symbol->Name, nullptr, nullptr, &status);
+                if (demangled)
+                {
+                    output += demangled;
+                    free(demangled);
+                }
+                else
+#endif
+                {
+                    output += symbol->Name;
+                }
+
+                output += " +" + SignalHandler::pointerToString(displacement, false);
+                if (bCorrected)
+                    output += " (?)";
+            }
+
+            output += "\n";
+
+            // Get the file name and line number
+            IMAGEHLP_LINE64 line;
+            memset(&line, 0, sizeof(IMAGEHLP_LINE64));
+            line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+            DWORD displacement2 = 0;
+
+            if
+            (
+                SymGetLineFromAddr64
+                (
+                    GetCurrentProcess(),
+                    frame.AddrPC.Offset - bCorrected ? 1 : 0,
+                    &displacement2,
+                    &line
+                )
+            )
+            {
+                output += "               ";
+                output += line.FileName;
+                output += ":";
+                output += multi_cast<std::string>(line.LineNumber);
+                output += "\n";
+            }
+        }
+
+        // Cleanup the symbol table:
+        SymCleanup(GetCurrentProcess());
+
+        return output;
+    }
+
+    /// Returns a description of the given exception.
+    // Based on code from Dr. Mingw by Jos\E9 Fonseca
+    /* static */ std::string SignalHandler::getExceptionType(PEXCEPTION_POINTERS pExceptionInfo)
+    {
+        PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+        TCHAR szModule[MAX_PATH];
+        HMODULE hModule;
+
+        std::string output = (GetModuleFileName(nullptr, szModule, MAX_PATH) ? SignalHandler::getModuleName(szModule) : "Application");
+        output += " caused ";
+
+        switch(pExceptionRecord->ExceptionCode)
+        {
+            case EXCEPTION_ACCESS_VIOLATION:            output += "an Access Violation";        break;
+            case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:       output += "an Array Bound Exceeded";    break;
+            case EXCEPTION_BREAKPOINT:                  output += "a Breakpoint";               break;
+            case EXCEPTION_DATATYPE_MISALIGNMENT:       output += "a Datatype Misalignment";    break;
+            case EXCEPTION_FLT_DENORMAL_OPERAND:        output += "a Float Denormal Operand";   break;
+            case EXCEPTION_FLT_DIVIDE_BY_ZERO:          output += "a Float Divide By Zero";     break;
+            case EXCEPTION_FLT_INEXACT_RESULT:          output += "a Float Inexact Result";     break;
+            case EXCEPTION_FLT_INVALID_OPERATION:       output += "a Float Invalid Operation";  break;
+            case EXCEPTION_FLT_OVERFLOW:                output += "a Float Overflow";           break;
+            case EXCEPTION_FLT_STACK_CHECK:             output += "a Float Stack Check";        break;
+            case EXCEPTION_FLT_UNDERFLOW:               output += "a Float Underflow";          break;
+            case EXCEPTION_GUARD_PAGE:                  output += "a Guard Page";               break;
+            case EXCEPTION_ILLEGAL_INSTRUCTION:         output += "an Illegal Instruction";     break;
+            case EXCEPTION_IN_PAGE_ERROR:               output += "an In Page Error";           break;
+            case EXCEPTION_INT_DIVIDE_BY_ZERO:          output += "an Integer Divide By Zero";  break;
+            case EXCEPTION_INT_OVERFLOW:                output += "an Integer Overflow";        break;
+            case EXCEPTION_INVALID_DISPOSITION:         output += "an Invalid Disposition";     break;
+            case EXCEPTION_INVALID_HANDLE:              output += "an Invalid Handle";          break;
+            case EXCEPTION_NONCONTINUABLE_EXCEPTION:    output += "a Noncontinuable Exception"; break;
+            case EXCEPTION_PRIV_INSTRUCTION:            output += "a Privileged Instruction";   break;
+            case EXCEPTION_SINGLE_STEP:                 output += "a Single Step";              break;
+            case EXCEPTION_STACK_OVERFLOW:              output += "a Stack Overflow";           break;
+            case DBG_CONTROL_C:                         output += "a Control+C";                break;
+            case DBG_CONTROL_BREAK:                     output += "a Control+Break";            break;
+            case DBG_TERMINATE_THREAD:                  output += "a Terminate Thread";         break;
+            case DBG_TERMINATE_PROCESS:                 output += "a Terminate Process";        break;
+            case RPC_S_UNKNOWN_IF:                      output += "an Unknown Interface";       break;
+            case RPC_S_SERVER_UNAVAILABLE:              output += "a Server Unavailable";       break;
+            default:                                    output += "an Unknown Exception (" + SignalHandler::pointerToString(pExceptionRecord->ExceptionCode) + ")"; break;
+        }
+
+        // Now print information about where the fault occured
+        output += " at location " + SignalHandler::pointerToString(pExceptionRecord->ExceptionAddress);
+        if ((hModule = (HMODULE) SignalHandler::getModuleBase(pExceptionRecord->ExceptionAddress)) && GetModuleFileName(hModule, szModule, MAX_PATH))
+        {
+            output += " in module ";
+            output += SignalHandler::getModuleName(szModule);
+        }
+
+        // If the exception was an access violation, print out some additional information, to the error log and the debugger.
+        if(pExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION && pExceptionRecord->NumberParameters >= 2)
+        {
+            output += " ";
+            output += pExceptionRecord->ExceptionInformation[0] ? "writing to" : "reading from";
+            output += " location ";
+            output += SignalHandler::pointerToString(pExceptionRecord->ExceptionInformation[1]);
+        }
+
+        return output;
+    }
+
+    /// Strips the directories from the path to the module and returns the module's name only.
+    /* static */ std::string SignalHandler::getModuleName(const std::string& path)
+    {
+        return path.substr(path.find_last_of('\\') + 1);
+    }
+
+    /// Retrieves the base address of the module that contains the specified address.
+    // Code from Dr. Mingw by Jos\E9 Fonseca
+    /* static */ PVOID SignalHandler::getModuleBase(LPCVOID dwAddress)
+    {
+        MEMORY_BASIC_INFORMATION Buffer;
+
+        return VirtualQuery(dwAddress, &Buffer, sizeof(Buffer)) ? Buffer.AllocationBase : 0;
+    }
+
+    /// Converts a value to string, formatted as pointer.
+    template <typename T>
+    /* static */ std::string SignalHandler::pointerToString(T pointer, bool bFillZeros)
+    {
+        std::ostringstream oss;
+
+        if (bFillZeros)
+            oss << std::setw(8) << std::setfill('0');
+
+        oss << std::hex << pointer;
+
+        return std::string("0x") + oss.str();
+    }
+
+    /// Converts a pointer to string.
+    template <typename T>
+    /* static */ std::string SignalHandler::pointerToString(T* pointer)
+    {
+        std::ostringstream oss;
+
+        oss << pointer;
+
+        return oss.str();
+    }
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/libraries/util/SignalHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/SignalHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/SignalHandler.h	(revision 11817)
@@ -0,0 +1,155 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Christoph Renner (Linux implementation)
+ *      Fabian 'x3n' Landau (Windows implementation)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util
+    @brief Declaration of the SignalHandler class.
+*/
+
+#ifndef _SignalHandler_H__
+#define _SignalHandler_H__
+
+#include "UtilPrereqs.h"
+
+#include <cassert>
+#include <string>
+
+#include "Singleton.h"
+#include "SpecialConfig.h"
+
+#if defined(ORXONOX_PLATFORM_LINUX)
+
+#include <list>
+#include <signal.h>
+
+namespace orxonox
+{
+    typedef int (*SignalCallback)( void * someData );
+
+    struct SignalRec
+    {
+        int signal;
+        sig_t handler;
+    };
+
+    struct SignalCallbackRec
+    {
+        SignalCallback cb;
+        void * someData;
+    };
+
+
+    typedef std::list<SignalRec> SignalRecList;
+    typedef std::list<SignalCallbackRec> SignalCallbackList;
+
+    /// The SignalHandler is used to catch signals like SIGSEGV and write a backtrace to the logfile.
+    class _UtilExport SignalHandler : public Singleton<SignalHandler>
+    {
+        friend class Singleton<SignalHandler>;
+
+        public:
+            void registerCallback( SignalCallback cb, void * someData );
+
+            void doCatch( const std::string & appName, const std::string & filename );
+            void dontCatch();
+
+        private:
+            static void sigHandler( int sig );
+
+            void catchSignal( int sig );
+            SignalRecList sigRecList;
+
+            SignalCallbackList callbackList;
+
+            static SignalHandler* singletonPtr_s;
+
+            std::string appName;
+            std::string filename;
+    };
+}
+
+#elif defined(ORXONOX_PLATFORM_WINDOWS) && defined(DBGHELP_FOUND)
+
+#include <windows.h>
+
+namespace orxonox
+{
+    /// The SignalHandler is used to catch unhandled exceptions like access violations and write a backtrace to the logfile.
+    class _UtilExport SignalHandler : public Singleton<SignalHandler>
+    {
+        friend class Singleton<SignalHandler>;
+
+        public:
+            SignalHandler();
+            ~SignalHandler();
+
+            void doCatch(const std::string& appName, const std::string& filename);
+
+            static std::string getStackTrace(PEXCEPTION_POINTERS pExceptionInfo = nullptr);
+            static std::string getExceptionType(PEXCEPTION_POINTERS pExceptionInfo);
+
+        private:
+            static LONG WINAPI exceptionFilter(PEXCEPTION_POINTERS pExceptionInfo);
+
+            static std::string getModuleName(const std::string& path);
+            static PVOID getModuleBase(LPCVOID dwAddress);
+
+            template <typename T>
+            static std::string pointerToString(T pointer, bool bFillZeros = true);
+            template <typename T>
+            static std::string pointerToString(T* pointer);
+
+            static SignalHandler* singletonPtr_s;
+
+            std::string filename_;
+            LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter_;
+    };
+}
+
+#else
+
+namespace orxonox
+{
+    /// The SignalHandler is used to catch signals like SIGSEGV and write a backtrace to the logfile. Not implemented on systems except Linux and Windows.
+    class _UtilExport SignalHandler : public Singleton<SignalHandler>
+    {
+        friend class Singleton<SignalHandler>;
+
+        public:
+            void doCatch(const std::string& appName, const std::string& filename) {}
+
+        private:
+            static SignalHandler* singletonPtr_s;
+    };
+}
+
+#endif
+
+#endif /* _SignalHandler_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Singleton.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Singleton.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Singleton.h	(revision 11817)
@@ -0,0 +1,152 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup SingletonScope Singletons and Scope
+    @ingroup Util
+*/
+
+/**
+    @file
+    @ingroup SingletonScope
+    @brief Definition of the Singleton template that is used as base class for classes that allow only one instance.
+
+    @anchor SingletonExample
+
+    Classes that inherit from orxonox::Singleton follow the singleton pattern and thus
+    allow only one instance of the class to exist. This istance is stored in a static
+    variable called @c singletonPtr_s. orxonox::Singleton will access this variable, but
+    it must be implemented in the deriving class.
+
+    Example:
+    @code
+    class TestSingleton : public Singleton<TestSingleton>   // inherit from Singleton, pass the own class as template argument
+    {
+        friend class Singleton<TestSingleton>;              // friend declaration so Singleton can access singletonPtr_s
+
+        public:
+            TestSingleton();                                // public constructor because we may want to manage this singleton
+                                                            //     with an orxonox::ScopedSingletonWrapper
+            virtual ~TestSingleton();                       // public destructor
+
+            void testFunction();                            // put your functions here
+
+        private:
+            int testValue_;                                 // put your variables here
+
+            static TestSingleton* singletonPtr_s;           // static singleton instance pointer, used by the Singleton template
+    };
+    @endcode
+
+    And don't forget to initialize the static singleton pointer in the source (*.cc) %file:
+    @code
+    TestSingleton* TestSingleton::singletonPtr_s = nullptr;
+    @endcode
+
+    If a class inherits from orxonox::Singleton, it also inherits its functions. The most important
+    function is orxonox::Singleton::getInstance() which returns a reference to the only instance
+    of the singleton.
+
+    Example:
+    @code
+    TestSingleton::TestSingleton()                          // implement the constructor
+    {
+        this->testValue_ = 15;
+    }
+
+    void TestSingleton::testFunction()                      // implement testFunction
+    {
+        orxout() << "My value is " << this->testValue_ << endl;
+    }
+
+    TestSingleton::getInstance().testFunction();            // prints "My value is 15"
+    @endcode
+*/
+
+#ifndef __Util_Singleton_H__
+#define __Util_Singleton_H__
+
+#include "UtilPrereqs.h"
+
+#include <cstring>
+#include <typeinfo>
+
+#include "OrxAssert.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Base for singleton classes.
+
+        Usage:
+        Inherit publicly from Singleton<MyClass> and provide access to MyClass::singletonPtr_s.
+        This can easily be done with a friend declaration.
+
+        See @ref SingletonExample "this example" for an exemplary implementation.
+    */
+    template <class T>
+    class Singleton
+    {
+    public:
+        //! Returns a reference to the singleton instance
+        static T& getInstance()
+        {
+            OrxVerify(T::singletonPtr_s != nullptr, "T=" << typeid(T).name());
+            return *T::singletonPtr_s;
+        }
+
+        //! Tells whether the singleton has been created
+        static bool exists()
+        {
+            return (T::singletonPtr_s != nullptr);
+        }
+
+    protected:
+        //! Constructor sets the singleton instance pointer
+        Singleton()
+        {
+            OrxVerify(T::singletonPtr_s == nullptr, "T=" << typeid(T).name());
+            T::singletonPtr_s = static_cast<T*>(this);
+        }
+
+        //! Destructor resets the singleton instance pointer
+        virtual ~Singleton()
+        {
+            OrxVerify(T::singletonPtr_s != nullptr, "T=" << typeid(T).name());
+            T::singletonPtr_s = nullptr;
+        }
+
+    private:
+        // non-copyable:
+        Singleton(const Singleton&) = delete;
+        Singleton& operator=(const Singleton&) = delete;
+    };
+}
+
+#endif /* __Util_Singleton_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/Sleep.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Sleep.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Sleep.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of three sleep functions.
+*/
+
+#include "Sleep.h"
+
+#include <chrono>
+#include <thread>
+
+namespace orxonox
+{
+    void usleep(unsigned long microseconds)
+    {
+        std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
+    }
+
+    void msleep(unsigned long milliseconds)
+    {
+        std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
+    }
+
+    void sleep(unsigned long seconds)
+    {
+        std::this_thread::sleep_for(std::chrono::seconds(seconds));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/Sleep.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/Sleep.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/Sleep.h	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Functions declarations to make the current thread sleep.
+ */
+
+#ifndef _Sleep_H__
+#define _Sleep_H__
+
+#include "UtilPrereqs.h"
+
+namespace orxonox
+{
+    //! Makes the thread sleep for a few @a microseconds
+    _UtilExport void usleep(unsigned long microseconds);
+    //! Makes the thread sleep for a few @a milliseconds
+    _UtilExport void msleep(unsigned long milliseconds);
+    //! Makes the thread sleep for a few @a seconds
+    _UtilExport void sleep (unsigned long seconds);
+}
+
+#endif /* _Sleep_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/SmallObjectAllocator.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/SmallObjectAllocator.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/SmallObjectAllocator.cc	(revision 11817)
@@ -0,0 +1,122 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of SmallObjectAllocator
+*/
+
+#include "SmallObjectAllocator.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: initializes the allocator and its values.
+        @param objectSize The size in bytes (returned by sizeof()) of the allocated objects
+        @param numObjects The number of objects that are allocated in one block of memory
+    */
+    SmallObjectAllocator::SmallObjectAllocator(size_t objectSize, size_t numObjects)
+    {
+        this->chunkSize_ = std::max(objectSize, sizeof(Chunk)); // the chunk's size will be the maximum of the object's size and the size of a Chunk object itself
+        this->numChunksPerBlock_ = numObjects;
+        this->first_ = nullptr;
+    }
+
+    /**
+        @brief Destructor: deletes the allocated memory blocks.
+    */
+    SmallObjectAllocator::~SmallObjectAllocator()
+    {
+        for (char* block : this->blocks_)
+            delete[] block;
+    }
+
+    /**
+        @brief Helper function, used to set the next_ pointer of a Chunk.
+    */
+    /* static */ void SmallObjectAllocator::setNext(void* chunk, void* next)
+    {
+        static_cast<Chunk*>(chunk)->next_ = static_cast<Chunk*>(next);
+    }
+
+    /**
+        @brief Helper function, returns the next_ pointer of a Chunk
+    */
+    /* static */ void* SmallObjectAllocator::getNext(void* chunk)
+    {
+        return static_cast<Chunk*>(chunk)->next_;
+    }
+
+    /**
+        @brief Returns the first free memory chunk or allocates a new block of memory.
+    */
+    void* SmallObjectAllocator::alloc()
+    {
+        // get the first free chunk
+        void* chunk = this->first_;
+
+        // check if the chunk exists
+        if (chunk)
+        {
+            // yes it does - the first_ pointer now points to the second element in the list
+            this->first_ = getNext(chunk);
+        }
+        else
+        {
+            // no it doesnt - allocate a new block of memory
+            char* block = new char[this->chunkSize_ * this->numChunksPerBlock_];
+            this->blocks_.push_back(block);
+
+            // iterate through the chunks in the new memory block and link them together to a single linked list
+            for (size_t i = 1; i < this->numChunksPerBlock_ - 1; ++i)
+                setNext(block + i * this->chunkSize_, block + (i + 1) * this->chunkSize_);
+
+            // the next_ pointer of the last chunk must point to nullptr
+            setNext(block + (this->numChunksPerBlock_ - 1) * this->chunkSize_, nullptr);
+
+            // The second chunk in the block is assigned to the first_ pointer
+            this->first_ = block + this->chunkSize_;
+
+            // The first chunk in the block is returned
+            chunk = block;
+        }
+
+        // return the pointer to the chunk
+        return chunk;
+    }
+
+    /**
+        @brief Puts the memory chunk back on the list of free memory.
+    */
+    void SmallObjectAllocator::free(void* chunk)
+    {
+        // The first_ pointer points to the freed chunk, its next_ pointer points to the rest of the list
+        setNext(chunk, this->first_);
+        this->first_ = chunk;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/SmallObjectAllocator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/SmallObjectAllocator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/SmallObjectAllocator.h	(revision 11817)
@@ -0,0 +1,117 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup SmallObjectAllocator SmallObjectAllocator
+    @ingroup Util
+*/
+
+/**
+    @file
+    @ingroup SmallObjectAllocator
+    @brief Declaration of SmallObjectAllocator
+
+    @anchor SmallObjectAllocatorExample
+
+    The default implementations of new and delete are designed to work with objects of
+    arbitrary size. They are thus not optimal for small objects.
+    @ref orxonox::SmallObjectAllocator "SmallObjectAllocator" allocates a large memory
+    block and divides it into small chunks. These chunks are returned by the function
+    @ref orxonox::SmallObjectAllocator::alloc() "alloc()" and can be used to create a
+    new object using the placement new operator. Instead of delete, the function
+    @ref orxonox::SmallObjectAllocator::free() "free()" is used to give the memory
+    back to SmallObjectAllocator.
+
+    Example:
+    @code
+    SmallObjectAllocator allocator(sizeof(MySmallObject));  // Create an allocator. The size of the memory chunks must equal the size of the desired class
+
+    void* chunk = allocator.alloc();                        // Allocate a memory chunk
+    MySmallObject* object = new (chunk) MySmallObject();    // Call the placement new operator
+
+    object->someFunction();                                 // Do something with the object
+
+    object->~MySmallObject();                               // Call the destructor
+    allocator.free(object);                                 // Free the allocated memory
+    @endcode
+
+    @b Important: You have to call the destructor of the object manually, because this
+    is not automatically done by the allocator nor free().
+
+    @note The destructor can be ignored if it is empty or not implemented. This saves
+    another amount of time.
+
+    @remarks For a distributed usage of SmallObjectAllocator it may be a good idea to
+    create a static function that returns an instance to it. The allocator then works
+    like a singleton and can be accesses from everywhere.
+*/
+
+#ifndef _SmallObjectAllocator_H__
+#define _SmallObjectAllocator_H__
+
+#include "UtilPrereqs.h"
+#include <vector>
+#include <cstdio>
+
+namespace orxonox
+{
+    /**
+        @brief This class is used to allocate and free small objects (usually not polymorphic).
+
+        SmallObjectAllocator provides a fast alternative to new and delete for small objects.
+
+        @see See @ref SmallObjectAllocatorExample "this description" for more information and an example.
+    */
+    class _UtilExport SmallObjectAllocator
+    {
+        /// The memory chunk is at the same time an element of a single linked list.
+        struct Chunk
+        {
+            Chunk* next_;   ///< A pointer to the next chunk in the list
+        };
+
+        public:
+            SmallObjectAllocator(size_t objectSize, size_t numObjects = 64);
+            ~SmallObjectAllocator();
+
+            void* alloc();
+            void free(void* chunk);
+
+        private:
+            static void setNext(void* chunk, void* next);
+            static void* getNext(void* chunk);
+
+            void* first_;                   ///< A pointer to the first free memory chunk
+            size_t chunkSize_;              ///< The size of each chunk (and usually also the size of the created objects)
+            size_t numChunksPerBlock_;      ///< The number of chunks per memory block
+
+            std::vector<char*> blocks_;     ///< A list of all allocated memory blocks (used to destroy them again)
+    };
+}
+
+#endif /* _SmallObjectAllocator_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/StringUtils.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/StringUtils.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/StringUtils.cc	(revision 11817)
@@ -0,0 +1,517 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Benjamin Grauer
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of several string manipulation functions.
+*/
+
+#include "StringUtils.h"
+
+#include <algorithm>
+#include <cctype>
+#include <ctime>
+#include <memory>
+#include "Convert.h"
+#include "Math.h"
+
+namespace orxonox
+{
+    /// A blank string (""). Used to return a blank string by reference.
+    std::string BLANKSTRING;
+
+    /// Returns a string of a unique number. This function is guaranteed to never return the same string twice.
+    std::string getUniqueNumberString()
+    {
+        return multi_cast<std::string>(getUniqueNumber());
+    }
+
+    /// Removes all whitespaces from a string.
+    void strip(std::string* str)
+    {
+        str->erase(std::remove_if(str->begin(), str->end(), [](char val) { return std::isspace(val) != 0; }), str->end());
+    }
+
+    /// Returns a copy of a string without whitespaces.
+    std::string getStripped(const std::string& str)
+    {
+        std::string output(str);
+        strip(&output);
+        return output;
+    }
+
+    /// Returns a copy of a string without trailing whitespaces.
+    std::string removeTrailingWhitespaces(const std::string& str)
+    {
+        auto pos1 = std::find_if(str.begin(), str.end(), [](char val) { return std::isspace(val) == 0; });
+        auto pos2 = std::find_if(str.rbegin(), str.rend(), [](char val) { return std::isspace(val) == 0; });
+        if (pos1 == str.end() && pos2 == str.rend())
+        {
+            // String doesn't have non-whitespace characters
+            return "";
+        }
+        return std::string(pos1, pos2.base());
+    }
+
+    /// Splits a given string by a delimiter and stores it in an output vector. See @ref SubString for a more sophisticated implementation.
+    void vectorize(const std::string& str, char delimiter, std::vector<std::string>* output)
+    {
+        output->clear();
+        for (size_t start = 0, end = 0; end != std::string::npos; start = end + 1)
+        {
+            end = str.find_first_of(delimiter, start);
+            output->push_back(str.substr(start, end - start));
+        }
+    }
+
+    /**
+        @brief Returns the position of the next quotation mark in the string, starting with start. Escaped quotation marks (with \ in front) are not considered.
+        @param str The string
+        @param start The first position to look at
+        @return The position of the next quotation mark (@c std::string::npos if there is none)
+    */
+    size_t getNextQuote(const std::string& str, size_t start)
+    {
+        size_t quote = start - 1;
+
+        while ((quote = str.find('"', quote + 1)) != std::string::npos)
+        {
+            size_t backslash = quote;
+            size_t numbackslashes = 0;
+            for (; backslash > 0; backslash--, numbackslashes++)
+                if (str[backslash - 1] != '\\')
+                    break;
+
+            if (numbackslashes % 2 == 0)
+                break;
+        }
+
+        return quote;
+    }
+
+    /**
+        @brief Returns true if pos is between two quotation marks.
+        @param str The string
+        @param pos The position to check
+        @return True if pos is between two quotation marks
+    */
+    bool isBetweenQuotes(const std::string& str, size_t pos)
+    {
+        if (pos == std::string::npos)
+            return false;
+
+        size_t quotecount = 0;
+        size_t quote = static_cast<size_t>(-1);
+        while ((quote = getNextQuote(str, quote + 1)) < pos)
+            quotecount++;
+
+        if (quote == pos)
+            return false;
+        if (quote == std::string::npos)
+            return false;
+
+        return ((quotecount % 2) == 1);
+    }
+
+    /// Returns true if the string contains something like '..."between quotaton marks"...'.
+    bool hasStringBetweenQuotes(const std::string& str)
+    {
+        size_t pos1 = getNextQuote(str, 0);
+        size_t pos2 = getNextQuote(str, pos1 + 1);
+        return (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1 + 1);
+    }
+
+    /// If the string contains something like '..."between quotaton marks"...' then 'between quotaton marks' gets returned, otherwise "".
+    std::string getStringBetweenQuotes(const std::string& str)
+    {
+        size_t pos1 = getNextQuote(str, 0);
+        size_t pos2 = getNextQuote(str, pos1 + 1);
+        if (pos1 != std::string::npos && pos2 != std::string::npos)
+            return str.substr(pos1 + 1, pos2 - pos1 - 1);
+        else
+            return "";
+    }
+
+    /**
+        @brief Removes enclosing quotation marks if available (including whitespaces at the outside of the quotation marks).
+        @return The stripped string without quotation marks
+    */
+    std::string stripEnclosingQuotes(const std::string& str)
+    {
+        auto start = str.begin();
+        auto end = str.rbegin();
+
+        for (; start != str.end() && *start != '"'; ++start)
+        {
+            if (std::isspace(*start) == 0)
+                return str;
+        }
+
+        for (; end != str.rend() && *end != '"'; ++end)
+        {
+            if (std::isspace(*end) == 0)
+                return str;
+        }
+
+        if (start != str.end() && end != str.rend())
+        {
+            ++start; // Skip "
+            ++end; // Skip "
+            return std::string(start, end.base());
+        }
+        else
+            return str;
+    }
+
+    /**
+        @brief Removes enclosing braces '{' and '}' (the braces must be exactly on the beginning and the end of the string).
+        @return The stripped string without braces
+    */
+    std::string stripEnclosingBraces(const std::string& str)
+    {
+        if (str.empty())
+        {
+            return "";
+        }
+
+        auto start = str.begin();
+        auto end = str.rbegin();
+
+        while (*start == '{' && *end == '}')
+        {
+            ++start;
+            ++end;
+        }
+
+        return std::string(start, end.base());
+    }
+
+    /**
+        @brief Determines if a string is a comment (starts with a comment-symbol).
+
+        A comment is defined by a leading '#', '%', ';' or '//'.
+    */
+    bool isComment(const std::string& str)
+    {
+        // Strip the line, whitespaces are disturbing
+        const std::string& teststring = getStripped(str);
+
+        // There are four possible comment-symbols:
+        //  1) #comment in script-language style
+        //  2) %comment in matlab style
+        //  3) ;comment in unreal tournament config-file style
+        //  4) //comment in code style
+        if (teststring.size() >= 2)
+        {
+            if (teststring[0] == '#' || teststring[0] == '%' || teststring[0] == ';' || (teststring[0] == '/' && teststring[1] == '/'))
+                return true;
+        }
+        else if (teststring.size() == 1)
+        {
+            if (teststring[0] == '#' || teststring[0] == '%' || teststring[0] == ';')
+                return true;
+        }
+
+        return false;
+    }
+
+    /// Determines if a string is empty (contains only whitespaces).
+    bool isEmpty(const std::string& str)
+    {
+        return std::all_of(str.begin(), str.end(), [](char val) { return std::isspace(val) != 0; });
+    }
+
+    /**
+        @brief Adds backslashes to the given string which makes special chars visible. Existing slashes will be doubled.
+
+        This function converts all special chars like line breaks, tabs, quotation marks etc. into
+        a human readable format by adding a backslash. So for example "\n" will be converted to
+        "\\" + "n".
+
+        This is usually used when a string is written to a file.
+
+        @see removeSlashes
+    */
+    std::string addSlashes(const std::string& str)
+    {
+        std::string output(str.size() * 2, ' ');
+        size_t i = 0;
+        for (const char& character : str)
+        {
+            switch (character)
+            {
+            case '\\': output[i] = '\\'; output[i + 1] = '\\'; break;
+            case '\n': output[i] = '\\'; output[i + 1] =  'n'; break;
+            case '\t': output[i] = '\\'; output[i + 1] =  't'; break;
+            case '\v': output[i] = '\\'; output[i + 1] =  'v'; break;
+            case '\b': output[i] = '\\'; output[i + 1] =  'b'; break;
+            case '\r': output[i] = '\\'; output[i + 1] =  'r'; break;
+            case '\f': output[i] = '\\'; output[i + 1] =  'f'; break;
+            case '\a': output[i] = '\\'; output[i + 1] =  'a'; break;
+            case  '"': output[i] = '\\'; output[i + 1] =  '"'; break;
+            case '\0': output[i] = '\\'; output[i + 1] =  '0'; break;
+            default  : output[i] = character; ++i; continue;
+            }
+            i += 2;
+        }
+        output.resize(i);
+
+        return output;
+    }
+
+    /**
+        @brief Removes backslashes from the given string. Double backslashes are interpreted as one backslash.
+
+        This function removes all backslashes and converts the human readable equivalents of
+        special chars like "\\" + "n" into their real meaning (in this case a line break or "\n").
+
+        This is usually used when reading a string from a file.
+
+        @see addSlashes
+    */
+    std::string removeSlashes(const std::string& str)
+    {
+        if (str.size() <= 1)
+            return str;
+
+        std::string output(str.size(), ' ');
+        size_t i = 0;
+        size_t pos = 0;
+        while (pos < str.size() - 1)
+        {
+            if (str[pos] == '\\')
+            {
+                switch (str[pos + 1])
+                {
+                case '\\': output[i] = '\\'; break;
+                case  'n': output[i] = '\n'; break;
+                case  't': output[i] = '\t'; break;
+                case  'v': output[i] = '\v'; break;
+                case  'b': output[i] = '\b'; break;
+                case  'r': output[i] = '\r'; break;
+                case  'f': output[i] = '\f'; break;
+                case  'a': output[i] = '\a'; break;
+                case  '"': output[i] =  '"'; break;
+                case  '0': output[i] = '\0'; break;
+                default: ++pos; continue;
+                }
+                pos += 2; ++i;
+            }
+            else
+                output[i++] = str[pos++];
+        }
+        if (pos < str.size())
+            output[i++] = str[pos];
+        output.resize(i);
+
+        return output;
+    }
+
+    /// Replaces each char between A and Z with its lowercase equivalent.
+    void lowercase(std::string* str)
+    {
+        std::transform(str->begin(), str->end(), str->begin(), [](char val) { return std::tolower(val); });
+    }
+
+    /// Returns a copy of the given string where all chars are converted to lowercase.
+    std::string getLowercase(const std::string& str)
+    {
+        std::string output(str);
+        lowercase(&output);
+        return output;
+    }
+
+    /// Replaces each char between a and z with its uppercase equivalent.
+    void uppercase(std::string* str)
+    {
+        std::transform(str->begin(), str->end(), str->begin(), [](char val) { return std::toupper(val); });
+    }
+
+    /// Returns a copy of the given string where all chars are converted to uppercase.
+    std::string getUppercase(const std::string& str)
+    {
+        std::string output(str);
+        uppercase(&output);
+        return output;
+    }
+
+    /**
+        @brief Compares two strings ignoring different casing.
+        @return s1 == s2 -> returns 0 / s1 < s2 -> returns -1 / s1 >= s2 -> returns 1
+    */
+    int nocaseCmp(const std::string& s1, const std::string& s2)
+    {
+        size_t size1 = s1.size(), size2 = s2.size(); // cache lengths
+
+        int res = nocaseCmp(s1, s2, std::min(size1, size2));
+
+        if (res != 0)
+        {
+            return res;
+        }
+
+        //return -1,0 or 1 according to strings' lengths
+        if (size1 == size2)
+            return 0;
+        return (size1 < size2) ? -1 : 1;
+
+    }
+
+
+    /**
+        @brief Compares the first @a len chars of two strings ignoring different casing.
+        @param s1 First string
+        @param s2 Second string
+        @param len Maximal number of chars to compare
+    */
+    int nocaseCmp(const std::string& s1, const std::string& s2, size_t len)
+    {
+        if (len == 0)
+            return 0;
+        std::string::const_iterator it1 = s1.begin();
+        std::string::const_iterator it2 = s2.begin();
+
+        //stop when either string's end has been reached
+        while ( (it1 != s1.end()) && (it2 != s2.end()) && len-- > 0)
+        {
+            if(std::toupper(*it1) != std::toupper(*it2)) //letters differ?
+                // return -1 to indicate smaller than, 1 otherwise
+                return (std::toupper(*it1)  < std::toupper(*it2)) ? -1 : 1;
+            //proceed to the next character in each string
+            ++it1;
+            ++it2;
+        }
+        return 0;
+    }
+
+    /// Returns true if the string contains a comment, introduced by #, %, ; or //.
+    bool hasComment(const std::string& str)
+    {
+        return (getNextCommentPosition(str) != std::string::npos);
+    }
+
+    /// If the string contains a comment, the comment gets returned (including the comment symbol and white spaces in front of it), an empty string otherwise.
+    std::string getComment(const std::string& str)
+    {
+        size_t pos = getNextCommentPosition(str);
+        if (pos == std::string::npos)
+            return "";
+        else
+            return str.substr(pos);
+    }
+
+    /**
+        @brief Returns the beginning of the next comment including whitespaces in front of the comment symbol.
+        @param str The string
+        @param start The first position to look at
+    */
+    size_t getNextCommentPosition(const std::string& str, size_t start)
+    {
+        for (size_t i = start; i < str.size(); i++)
+            if (isComment(str.substr(i)))
+                return i;
+
+        return std::string::npos;
+    }
+
+    /**
+        @brief Replaces individual charaters
+        @param str String to be manipulated
+        @param target Character to be replaced
+        @param replacement Replacement character
+        @return Number of replacements
+    */
+    size_t replaceCharacters(std::string& str, char target, char replacement)
+    {
+        size_t j = 0;
+        for (char& character : str)
+        {
+            if (character == target)
+            {
+                character = replacement;
+                ++j;
+            }
+        }
+        return j;
+    }
+
+    /**
+        @brief Calculates the Levenshtein distance between two strings.
+
+        The Levenshtein distance is defined by the number of transformations needed to convert str1
+        into str2. Possible transformations are substituted, added, or removed characters.
+    */
+    unsigned int getLevenshteinDistance(const std::string& str1, const std::string& str2)
+    {
+        size_t cols = str1.size() + 1;
+        size_t rows = str2.size() + 1;
+        const std::unique_ptr<int[]> matrix(new int[rows * cols]);
+
+        for (size_t r = 0; r < rows; ++r)
+            for (size_t c = 0; c < cols; ++c)
+                matrix[r*cols + c] = 0;
+
+        for (size_t i = 1; i < cols; ++i)
+            matrix[0*cols + i] = i;
+        for (size_t i = 1; i < rows; ++i)
+            matrix[i*cols + 0] = i;
+
+        for (size_t r = 1; r < rows; ++r)
+            for (size_t c = 1; c < cols; ++c)
+                matrix[r*cols + c] = (str1[c-1] != str2[r-1]);
+
+        for (size_t r = 1; r < rows; ++r)
+            for (size_t c = 1; c < cols; ++c)
+                matrix[r*cols + c] = std::min(std::min(matrix[(r-1)*cols + c] + 1,
+                                                       matrix[r*cols + c-1] + 1),
+                                              matrix[(r-1)*cols + c-1] + (str1[c-1] != str2[r-1]));
+
+        return matrix[(rows-1)*cols + cols-1];
+    }
+
+    /**
+    @brief
+        Get a timestamp for the current time instant.
+    @return
+        Returns a string with the timestamp.
+    */
+    std::string getTimestamp(void)
+    {
+        time_t ctTime; std::time(&ctTime);
+        tm* pTime = std::localtime(&ctTime);
+        std::ostringstream oss;
+//        oss << std::put_time(pTime, "%m%d%Y_%H%M%S"); // <-- std::put_time is only available in GCC 5+
+        oss << std::setw(2) << std::setfill('0') << (pTime->tm_mon + 1)
+            << std::setw(2) << std::setfill('0') << pTime->tm_mday
+            << std::setw(2) << std::setfill('0') << (pTime->tm_year + 1900)
+            << "_" << std::setw(2) << std::setfill('0') << pTime->tm_hour
+            << std::setw(2) << std::setfill('0') << pTime->tm_min
+            << std::setw(2) << std::setfill('0') << pTime->tm_sec;
+        return oss.str();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/StringUtils.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/StringUtils.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/StringUtils.h	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @defgroup String String functions
+    @ingroup Util
+*/
+
+/**
+    @file
+    @ingroup String
+    @brief Declaration of several string manipulation functions, used in many parts of the game.
+*/
+
+#ifndef _StringUtils_H__
+#define _StringUtils_H__
+
+#include "UtilPrereqs.h"
+#include <string>
+#include <vector>
+
+namespace orxonox
+{
+    extern _UtilExport std::string BLANKSTRING;
+
+    _UtilExport std::string  getUniqueNumberString();
+
+    _UtilExport void         strip(std::string* str);
+    _UtilExport std::string  getStripped(const std::string& str);
+
+    _UtilExport std::string  removeTrailingWhitespaces(const std::string& str);
+
+    _UtilExport void         vectorize(const std::string& str, char delimiter, std::vector<std::string>* output);
+
+    _UtilExport size_t       getNextQuote(const std::string& str, size_t start = 0);
+    _UtilExport bool         isBetweenQuotes(const std::string& str, size_t pos);
+
+    _UtilExport bool         hasStringBetweenQuotes(const std::string& str);
+    _UtilExport std::string  getStringBetweenQuotes(const std::string& str);
+
+    _UtilExport std::string  stripEnclosingQuotes(const std::string& str);
+    _UtilExport std::string  stripEnclosingBraces(const std::string& str);
+
+    _UtilExport bool         isEmpty(const std::string& str);
+    _UtilExport bool         isComment(const std::string& str);
+
+    _UtilExport std::string  addSlashes(const std::string& str);
+    _UtilExport std::string  removeSlashes(const std::string& str);
+
+    _UtilExport void         lowercase(std::string* str);
+    _UtilExport std::string  getLowercase(const std::string& str);
+
+    _UtilExport void         uppercase(std::string* str);
+    _UtilExport std::string  getUppercase(const std::string& str);
+
+    _UtilExport int          nocaseCmp(const std::string& s1, const std::string& s2);
+    _UtilExport int          nocaseCmp(const std::string& s1, const std::string& s2, size_t len);
+
+    _UtilExport bool         hasComment(const std::string& str);
+    _UtilExport std::string  getComment(const std::string& str);
+    _UtilExport size_t       getNextCommentPosition(const std::string& str, size_t start = 0);
+
+    _UtilExport size_t       replaceCharacters(std::string& str, char target, char replacement);
+
+    _UtilExport unsigned int getLevenshteinDistance(const std::string& str1, const std::string& str2);
+
+    _UtilExport std::string  getTimestamp(void);
+}
+
+#endif /* _StringUtils_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/SubString.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/SubString.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/SubString.cc	(revision 11817)
@@ -0,0 +1,481 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Christian Meyer
+ *   Co-authors:
+ *      Benjamin Grauer
+ *
+
+//
+//  splitLine
+//  STL string tokenizer
+//
+//  Created by Clemens Wacha.
+//  Version 1.0
+//  Copyright (c) 2005 Clemens Wacha. All rights reserved.
+//
+
+ *   Extended by Fabian 'x3n' Landau by the SL_PARENTHESES mode.
+ */
+
+/**
+    @file
+    @brief Implementation of the SubString class.
+*/
+
+#include "SubString.h"
+#include <cstdio>
+#include "Output.h"
+
+namespace orxonox
+{
+    const std::string SubString::WhiteSpaces          = " \n\t";
+    const std::string SubString::WhiteSpacesWithComma = " \n\t,";
+    const SubString SubString::NullSubString          = SubString();
+
+    /**
+        @brief Default constructor.
+    */
+    SubString::SubString()
+    {
+    }
+
+    /**
+        @brief Splits a string into multiple tokens.
+        @param line The line to split
+        @param delimiters Multiple characters at which to split the line
+        @param delimiterNeighbours Neighbours of the delimiters that will be erased as well (for example white-spaces)
+        @param bAllowEmptyEntries If true, empty tokens are also added to the SubString (if there are two delimiters without a char in between)
+        @param escapeChar The escape character that is used to escape safemode chars (for example if you want to use a quotation mark between two other quotation marks).
+        @param bRemoveEscapeChar If true, the escape char is removed from the tokens
+        @param safemodeChar Within these characters splitting won't happen (usually the quotation marks)
+        @param bRemoveSafemodeChar Removes the safemodeChar from the beginning and the ending of a token
+        @param openparenthesisChar The beginning of a safemode is marked with this (usually an opening brace)
+        @param closeparenthesisChar The ending of a safemode is marked with this (usually a closing brace)
+        @param bRemoveParenthesisChars Removes the parenthesis chars from the beginning and the ending of a token
+        @param commentChar The comment character (used to ignore the part of the line after the comment char).
+    */
+    SubString::SubString(const std::string& line,
+                         const std::string& delimiters, const std::string& delimiterNeighbours, bool bAllowEmptyEntries,
+                         char escapeChar, bool bRemoveEscapeChar, char safemodeChar, bool bRemoveSafemodeChar,
+                         char openparenthesisChar, char closeparenthesisChar, bool bRemoveParenthesisChars, char commentChar)
+    {
+        SubString::splitLine(this->tokens_, this->bTokenInSafemode_, line, delimiters, delimiterNeighbours, bAllowEmptyEntries, escapeChar, bRemoveEscapeChar, safemodeChar, bRemoveSafemodeChar, openparenthesisChar, closeparenthesisChar, bRemoveParenthesisChars, commentChar);
+    }
+
+    /**
+        @brief creates a new SubString based on a subset of an other SubString.
+        @param other The other SubString
+        @param begin The beginning of the subset
+        @param length The length of the subset
+
+        The subset ranges from the token with index @a begin and contains @a length elements.
+    */
+    SubString::SubString(const SubString& other, size_t begin, size_t length)
+    {
+        for (size_t i = 0; i < length; ++i)
+        {
+            if (begin + i >= other.size())
+                break;
+
+            this->tokens_.push_back(other[begin + i]);
+            this->bTokenInSafemode_.push_back(other.isInSafemode(begin + i));
+        }
+    }
+
+    /**
+        @brief Creates a SubString from a count and values set.
+        @param argc The number of arguments
+        @param argv An array of pointers to the arguments
+    */
+    SubString::SubString(size_t argc, const char** argv)
+    {
+        for (size_t i = 0; i < argc; ++i)
+        {
+            this->tokens_.emplace_back(argv[i]);
+            this->bTokenInSafemode_.push_back(false);
+        }
+    }
+
+    /**
+        @brief Destructor
+    */
+    SubString::~SubString()
+    { }
+
+    /**
+        @brief Stores the tokens of @a other in this SubString
+        @return This SubString.
+    */
+    SubString& SubString::operator=(const SubString& other)
+    {
+        this->tokens_ = other.tokens_;
+        this->bTokenInSafemode_ = other.bTokenInSafemode_;
+        return *this;
+    }
+
+    /**
+        @brief Compares this SubString to another SubString and returns true if they contain the same values.
+    */
+    bool SubString::operator==(const SubString& other) const
+    {
+        return ((this->tokens_ == other.tokens_) && (this->bTokenInSafemode_ == other.bTokenInSafemode_));
+    }
+
+    /**
+        @brief Compares this SubString to another SubString and returns true if the first @a length values match.
+        @param other The other SubString
+        @param length How many tokens to compare
+    */
+    bool SubString::compare(const SubString& other, size_t length) const
+    {
+        if (std::min(length, this->size()) != std::min(length, other.size()))
+            return false;
+
+        for (size_t i = 0; i < std::min(length, this->size()); ++i)
+            if ((this->tokens_[i] != other.tokens_[i]) || (this->bTokenInSafemode_[i] != other.bTokenInSafemode_[i]))
+                return false;
+
+        return true;
+    }
+
+    /**
+        @brief Concatenates the tokens of two SubStrings and returns the resulting new SubString
+        @return A new SubString that contains the tokens of this and the other SubString
+    */
+    SubString SubString::operator+(const SubString& other) const
+    {
+        return SubString(*this) += other;
+    }
+
+    /**
+        @brief Appends the tokens of @a other to this SubString
+        @return This SubString
+    */
+    SubString& SubString::operator+=(const SubString& other)
+    {
+        for (size_t i = 0; i < other.size(); ++i)
+        {
+            this->tokens_.push_back(other[i]);
+            this->bTokenInSafemode_.push_back(other.isInSafemode(i));
+        }
+        return *this;
+    }
+
+    /**
+        @copydoc SubString(const std::string&,const std::string&,const std::string&,bool,char,bool,char,bool,char,char,bool,char)
+    */
+    size_t SubString::split(const std::string& line,
+                            const std::string& delimiters, const std::string& delimiterNeighbours, bool bAllowEmptyEntries,
+                            char escapeChar, bool bRemoveEscapeChar, char safemodeChar, bool bRemoveSafemodeChar,
+                            char openparenthesisChar, char closeparenthesisChar, bool bRemoveParenthesisChars, char commentChar)
+    {
+        this->tokens_.clear();
+        this->bTokenInSafemode_.clear();
+        SubString::splitLine(this->tokens_, this->bTokenInSafemode_, line, delimiters, delimiterNeighbours, bAllowEmptyEntries, escapeChar, bRemoveEscapeChar, safemodeChar, bRemoveSafemodeChar, openparenthesisChar, closeparenthesisChar, bRemoveParenthesisChars, commentChar);
+        return this->tokens_.size();
+    }
+
+    /**
+        @brief Joins the tokens of this SubString using the given delimiter and returns a string.
+        @param delimiter This delimiter will be placed between each two tokens
+        @return The joined string.
+    */
+    std::string SubString::join(const std::string& delimiter) const
+    {
+        if (!this->tokens_.empty())
+        {
+            std::string retVal = this->tokens_[0];
+            for (size_t i = 1; i < this->tokens_.size(); ++i)
+                retVal += delimiter + this->tokens_[i];
+            return retVal;
+        }
+        else
+            return "";
+    }
+
+    /**
+        @brief Creates a subset of this SubString.
+        @param begin The beginning of the subset
+        @param length The length of the subset
+        @return A new SubString containing the defined subset.
+
+        The subset ranges from the token with index @a begin and contains @a length elements.
+
+        This function is added for your convenience, and does the same as
+        SubString::SubString(const SubString& other, size_t begin, size_t length)
+    */
+    SubString SubString::subSet(size_t begin, size_t length) const
+    {
+        return SubString(*this, begin, length);
+    }
+
+    /**
+        @copydoc SubString(const std::string&,const std::string&,const std::string&,bool,char,bool,char,bool,char,char,bool,char)
+        @param tokens The array, where the splitted strings will be stored in
+        @param bTokenInSafemode A vector wich stores for each character of the string if it is in safemode or not
+        @param start_state The internal state of the parser
+
+        This is the actual splitting algorithm from Clemens Wacha.
+        Supports delimiters, escape characters, ignores special characters between safemodeChar and between commentChar and line end "\n".
+
+        Extended by Orxonox to support parenthesis as additional safe-mode.
+    */
+    SubString::SPLIT_LINE_STATE
+    SubString::splitLine(std::vector<std::string>& tokens,
+                         std::vector<bool>& bTokenInSafemode,
+                         const std::string& line,
+                         const std::string& delimiters,
+                         const std::string& delimiterNeighbours,
+                         bool bAllowEmptyEntries,
+                         char escapeChar,
+                         bool bRemoveEscapeChar,
+                         char safemodeChar,
+                         bool bRemoveSafemodeChar,
+                         char openparenthesisChar,
+                         char closeparenthesisChar,
+                         bool bRemoveParenthesisChars,
+                         char commentChar,
+                         SPLIT_LINE_STATE start_state)
+    {
+        SPLIT_LINE_STATE state = start_state;
+        size_t i = 0;
+        size_t fallBackNeighbours = 0;
+
+        std::string token;
+        bool inSafemode = false;
+
+        if(start_state != SPLIT_LINE_STATE::NORMAL && tokens.size() > 0)
+        {
+            token = tokens[tokens.size()-1];
+            tokens.pop_back();
+        }
+        if(start_state != SPLIT_LINE_STATE::NORMAL && bTokenInSafemode.size() > 0)
+        {
+            inSafemode = bTokenInSafemode[bTokenInSafemode.size()-1];
+            bTokenInSafemode.pop_back();
+        }
+
+        while(i < line.size())
+        {
+            switch(state)
+            {
+            case SPLIT_LINE_STATE::NORMAL:
+                if(line[i] == escapeChar)
+                {
+                    state = SPLIT_LINE_STATE::ESCAPE;
+                    if (!bRemoveEscapeChar)
+                        token += line[i];
+                    fallBackNeighbours = 0;
+                }
+                else if(line[i] == safemodeChar)
+                {
+                    state = SPLIT_LINE_STATE::SAFEMODE;
+                    inSafemode = true;
+                    if (!bRemoveSafemodeChar)
+                        token += line[i];
+                    fallBackNeighbours = 0;
+                }
+                else if(line[i] == openparenthesisChar)
+                {
+                    state = SPLIT_LINE_STATE::PARENTHESES;
+                    inSafemode = true;
+                    if (!bRemoveParenthesisChars)
+                        token += line[i];
+                    fallBackNeighbours = 0;
+                }
+                else if(line[i] == commentChar)
+                {
+                    if (fallBackNeighbours > 0)
+                        token = token.substr(0, token.size() - fallBackNeighbours);
+                    fallBackNeighbours = 0;
+                    // FINISH
+                    if(bAllowEmptyEntries || token.size() > 0)
+                    {
+                        tokens.push_back(token);
+                        token.clear();
+                        bTokenInSafemode.push_back(inSafemode);
+                        inSafemode = false;
+                    }
+                    token += line[i];       // EAT
+                    state = SPLIT_LINE_STATE::COMMENT;
+                }
+                else if(delimiters.find(line[i]) != std::string::npos)
+                {
+                    // line[i] is a delimiter
+                    if (fallBackNeighbours > 0)
+                        token = token.substr(0, token.size() - fallBackNeighbours);
+                    fallBackNeighbours = 0;
+                    // FINISH
+                    if(bAllowEmptyEntries || token.size() > 0)
+                    {
+                        tokens.push_back(token);
+                        token.clear();
+                        bTokenInSafemode.push_back(inSafemode);
+                        inSafemode = false;
+                    }
+                    state = SPLIT_LINE_STATE::NORMAL;
+                }
+                else
+                {
+                    if (delimiterNeighbours.find(line[i]) != std::string::npos)
+                    {
+                        if (token.size() > 0)
+                            ++fallBackNeighbours;
+                        else
+                        {
+                            ++i;
+                            continue;
+                        }
+                    }
+                    else
+                        fallBackNeighbours = 0;
+                    token += line[i];       // EAT
+                }
+                break;
+            case SPLIT_LINE_STATE::ESCAPE:
+                if (!bRemoveSafemodeChar)
+                    token += line[i];
+                else
+                {
+                    if(line[i] == 'n') token += '\n';
+                    else if(line[i] == 't') token += '\t';
+                    else if(line[i] == 'v') token += '\v';
+                    else if(line[i] == 'b') token += '\b';
+                    else if(line[i] == 'r') token += '\r';
+                    else if(line[i] == 'f') token += '\f';
+                    else if(line[i] == 'a') token += '\a';
+                    else if(line[i] == '?') token += '\?';
+                    else token += line[i];  // EAT
+                }
+                state = SPLIT_LINE_STATE::NORMAL;
+                break;
+            case SPLIT_LINE_STATE::SAFEMODE:
+                if(line[i] == safemodeChar)
+                {
+                    state = SPLIT_LINE_STATE::NORMAL;
+                    if (!bRemoveSafemodeChar)
+                        token += line[i];
+                }
+                else if(line[i] == escapeChar)
+                {
+                    state = SPLIT_LINE_STATE::SAFEESCAPE;
+                }
+                else
+                {
+                    token += line[i];       // EAT
+                }
+                break;
+
+            case SPLIT_LINE_STATE::SAFEESCAPE:
+                if(line[i] == 'n') token += '\n';
+                else if(line[i] == 't') token += '\t';
+                else if(line[i] == 'v') token += '\v';
+                else if(line[i] == 'b') token += '\b';
+                else if(line[i] == 'r') token += '\r';
+                else if(line[i] == 'f') token += '\f';
+                else if(line[i] == 'a') token += '\a';
+                else if(line[i] == '?') token += '\?';
+                else token += line[i];  // EAT
+                state = SPLIT_LINE_STATE::SAFEMODE;
+                break;
+
+            case SPLIT_LINE_STATE::PARENTHESES:
+                if(line[i] == closeparenthesisChar)
+                {
+                    state = SPLIT_LINE_STATE::NORMAL;
+                    if (!bRemoveParenthesisChars)
+                        token += line[i];
+                }
+                else if(line[i] == escapeChar)
+                {
+                    state = SPLIT_LINE_STATE::PARENTHESESESCAPE;
+                }
+                else
+                {
+                    token += line[i];       // EAT
+                }
+                break;
+
+            case SPLIT_LINE_STATE::PARENTHESESESCAPE:
+                if(line[i] == 'n') token += '\n';
+                else if(line[i] == 't') token += '\t';
+                else if(line[i] == 'v') token += '\v';
+                else if(line[i] == 'b') token += '\b';
+                else if(line[i] == 'r') token += '\r';
+                else if(line[i] == 'f') token += '\f';
+                else if(line[i] == 'a') token += '\a';
+                else if(line[i] == '?') token += '\?';
+                else token += line[i];  // EAT
+                state = SPLIT_LINE_STATE::PARENTHESES;
+                break;
+
+            case SPLIT_LINE_STATE::COMMENT:
+                if(line[i] == '\n')
+                {
+                    // FINISH
+                    if(token.size() > 0)
+                    {
+                        tokens.push_back(token);
+                        token.clear();
+                        bTokenInSafemode.push_back(inSafemode);
+                        inSafemode = false;
+                    }
+                    state = SPLIT_LINE_STATE::NORMAL;
+                }
+                else
+                {
+                    token += line[i];       // EAT
+                }
+                break;
+
+            default:
+                // nothing
+                break;
+            }
+            ++i;
+        }
+
+        // FINISH
+        if (fallBackNeighbours > 0)
+            token = token.substr(0, token.size() - fallBackNeighbours);
+        if(bAllowEmptyEntries || token.size() > 0)
+        {
+            tokens.push_back(token);
+            token.clear();
+            bTokenInSafemode.push_back(inSafemode);
+            inSafemode = false;
+        }
+        return(state);
+    }
+
+    /**
+        @brief Some nice debug information about this SubString.
+    */
+    void SubString::debug() const
+    {
+        orxout(debug_output) << "Substring-information::count=" << this->tokens_.size() << " ::";
+        for (size_t i = 0; i < this->tokens_.size(); ++i)
+            orxout(debug_output) << "s" << i << "='" << this->tokens_[i].c_str() << "'::";
+        orxout(debug_output) << endl;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/SubString.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/SubString.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/SubString.h	(revision 11817)
@@ -0,0 +1,219 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Christian Meyer
+ *   Co-authors:
+ *      Benjamin Grauer
+ *      Fabian 'x3n' Landau
+ *
+
+//  splitLine
+//  STL string tokenizer
+//
+//  Created by Clemens Wacha.
+//  Version 1.0
+//  Copyright (c) 2005 Clemens Wacha. All rights reserved.
+
+ *   Extended by Fabian 'x3n' Landau by the SL_PARENTHESES mode.
+ */
+
+ /**
+    @file
+    @ingroup String
+    @brief A helper class to split a string into several tokens.
+
+    @anchor SubStringExample
+
+    The class SubString can be used to split an std::string into multiple tokens, using
+    a delimiter. SubString allows different options, for example to remove whitespaces
+    around the delimiters or different safe-mode chars, like quotation marks and braces.
+
+    You can access the tokens of the SubString using the [] operator like an array.
+    SubString also supports to join the tokens (or a subset of the tokens) again using
+    @ref orxonox::SubString::join() "join()". It's even possible to get a subset of the
+    SubString as another SubString using @ref orxonox::SubString::subSet() "subSet()".
+
+    Example:
+    @code
+    std::string text = "This is a test, \"Hello \\\" World\" and vector {1, 2, 3}";
+    SubString tokens(text, SubString::WhiteSpaces, "", false, '\\', true, '"', true, '{', '}', true, '\0');
+
+    for (size_t i = 0; i < tokens.size(); ++i)
+        orxout() << i << ": " << tokens[i] << endl;
+    @endcode
+
+    The output of this code is:
+     - 0: This
+     - 1: is
+     - 2: a
+     - 3: test,
+     - 4: Hello " World
+     - 5: and
+     - 6: vector
+     - 7: 1, 2, 3
+
+    The string was split using the delimiter " ". A string between quotation mark is not
+    split, the same holds for strings between '{' and '}'. Note how the quotation marks and
+    the braces were removed from the tokens, because the corresponding argument is 'true'.
+
+    Also note that the comma after "test" in token 3 is still there - it is neither part of the
+    delimiters SubString::WhiteSpaces nor part of the delimiterNeighbours parameter, so it
+    remains a part of the token.
+*/
+
+#ifndef __SubString_H__
+#define __SubString_H__
+
+#include "UtilPrereqs.h"
+
+#include <vector>
+#include <string>
+
+namespace orxonox
+{
+    /**
+        @brief A class that splits a string into multiple tokens using different options.
+
+        The string is split into multiple tokens using a delimiter. Different options like
+        escape character, quotation marks, and more can be used to satisfy your needs.
+
+        See @ref SubStringExample "this description" for an example.
+    */
+    class _UtilExport SubString
+    {
+        /// An enumerator for the internal state of the parser
+        enum class SPLIT_LINE_STATE
+        {
+            NORMAL,            //!< Normal state
+            ESCAPE,            //!< After an escape character
+            SAFEMODE,          //!< In safe mode (usually between quotation marks).
+            SAFEESCAPE,        //!< In safe mode with the internal escape character, that escapes even the savemode character.
+            COMMENT,           //!< In Comment mode.
+            PARENTHESES,       //!< Between parentheses (usually '{' and '}')
+            PARENTHESESESCAPE, //!< Between parentheses with the internal escape character, that escapes even the closing parenthesis character.
+        };
+
+    public:
+        SubString();
+        /// Copy constructor
+        SubString(const SubString& other) = default;
+        /// Move constructor
+        SubString(SubString&& other) = default;
+        SubString(const std::string& line,
+                  const std::string& delimiters = SubString::WhiteSpaces,
+                  const std::string& delimiterNeighbours = "",
+                  bool bAllowEmptyEntries=false,
+                  char escapeChar ='\\',
+                  bool bRemoveEscapeChar = true,
+                  char safemodeChar = '"',
+                  bool bRemoveSafemodeChar = true,
+                  char openparenthesisChar = '{',
+                  char closeparenthesisChar = '}',
+                  bool bRemoveParenthesisChars = true,
+                  char commentChar = '\0');
+        SubString(size_t argc, const char** argv);
+        SubString(const SubString& other, size_t begin, size_t length = std::string::npos);
+        ~SubString();
+
+        // operate on the SubString
+        SubString& operator=(const SubString& other);
+        /// Move assignment
+        SubString& operator=(SubString&& other) = default;
+        bool operator==(const SubString& other) const;
+        bool compare(const SubString& other, size_t length = std::string::npos) const;
+        SubString operator+(const SubString& other) const;
+        SubString& operator+=(const SubString& other);
+        /// Appends the tokens of another SubString to this. @return This SubString.
+        inline SubString& append(const SubString& other) { return (*this += other); }
+
+        /////////////////////////////////////////
+        // Split and Join the any String. ///////
+        size_t split(const std::string& line,
+                     const std::string& delimiters = SubString::WhiteSpaces,
+                     const std::string& delimiterNeighbours = "",
+                     bool bAllowEmptyEntries = false,
+                     char escapeChar ='\\',
+                     bool bRemoveEscapeChar = true,
+                     char safemodeChar = '"',
+                     bool bRemoveSafemodeChar = true,
+                     char openparenthesisChar = '{',
+                     char closeparenthesisChar = '}',
+                     bool bRemoveParenthesisChars = true,
+                     char commentChar = '\0');
+
+        std::string join(const std::string& delimiter = " ") const;
+        ////////////////////////////////////////
+
+        // retrieve a SubSet from the String
+        SubString subSet(size_t begin, size_t length = std::string::npos) const;
+
+        // retrieve Information from within
+        /// Returns true if the SubString is empty
+        inline bool empty() const { return this->tokens_.empty(); }
+        /// Returns the number of tokens stored in this SubString
+        inline size_t size() const { return this->tokens_.size(); }
+        /// Returns the i'th token from the subset of strings @param index The index of the requested token
+        inline const std::string& operator[](size_t index) const { return this->tokens_[index]; }
+        /// Returns the i'th token from the subset of strings @param index The index of the requested token
+        inline const std::string& getString(size_t index) const { return (*this)[index]; }
+        /// Returns all tokens as std::vector
+        inline const std::vector<std::string>& getAllStrings() const { return this->tokens_; }
+        /// Returns true if the token is in safemode. @param index The index of the token
+        inline bool isInSafemode(size_t index) const { return this->bTokenInSafemode_[index]; }
+        /// Returns the front of the list of tokens.
+        inline const std::string& front() const { return this->tokens_.front(); }
+        /// Returns the back of the list of tokens.
+        inline const std::string& back() const { return this->tokens_.back(); }
+        /// Removes the back of the list of tokens.
+        inline void pop_back() { this->tokens_.pop_back(); this->bTokenInSafemode_.pop_back(); }
+
+        void debug() const;
+
+    public:
+        static const std::string WhiteSpaces;           ///< All whitespaces (usually used as delimiters or delimiterNeighbours
+        static const std::string WhiteSpacesWithComma;  ///< All whitespaces and the comma (usually used as delimiters)
+        static const SubString   NullSubString;         ///< An empty SubString
+
+    private:
+        // the almighty algorithm.
+        static SPLIT_LINE_STATE splitLine(std::vector<std::string>& tokens,
+                                          std::vector<bool>& bTokenInSafemode,
+                                          const std::string& line,
+                                          const std::string& delimiters = SubString::WhiteSpaces,
+                                          const std::string& delimiterNeighbours = "",
+                                          bool bAllowEmptyEntries = false,
+                                          char escapeChar = '\\',
+                                          bool bRemoveEscapeChar = true,
+                                          char safemodeChar = '"',
+                                          bool bRemoveSafemodeChar = true,
+                                          char openparenthesisChar = '{',
+                                          char closeparenthesisChar = '}',
+                                          bool bRemoveParenthesisChars = true,
+                                          char commentChar = '\0',
+                                          SPLIT_LINE_STATE start_state = SPLIT_LINE_STATE::NORMAL);
+
+        std::vector<std::string>  tokens_;              ///< The tokens after splitting the input line
+        std::vector<bool>         bTokenInSafemode_;    ///< Saves for each token if it was in safe mode (between quotation marks or parenthesis)
+    };
+}
+
+#endif /* __SubString_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/UtilPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/UtilPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/UtilPrereqs.h	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the util library
+*/
+
+#ifndef _UtilPrereqs_H__
+#define _UtilPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include <string>
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined( UTIL_STATIC_BUILD )
+#  ifdef UTIL_SHARED_BUILD
+#    define _UtilExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _UtilExport
+#    else
+#      define _UtilExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _UtilPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _UtilExport  __attribute__ ((visibility("default")))
+#  define _UtilPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _UtilExport
+#  define _UtilPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class AdditionalContextListener;
+    class BaseWriter;
+    class Clock;
+    class ConsoleWriter;
+    class Exception;
+    class ExprParser;
+    class LogWriter;
+    class MemoryWriter;
+    class MultiType;
+    class OutputListener;
+    class OutputManager;
+    class OutputStream;
+    class ScopeListener;
+    class SignalHandler;
+    template <class T>
+    class Singleton;
+    class SubcontextOutputListener;
+    class SubString;
+}
+
+namespace Ogre
+{
+    class Radian;
+    class Degree;
+    class Vector2;
+    class Vector3;
+    class Vector4;
+    class Matrix3;
+    class Matrix4;
+    class Quaternion;
+    class ColourValue;
+}
+namespace orxonox
+{
+    using Ogre::Radian;
+    using Ogre::Degree;
+    using Ogre::Vector2;
+    using Ogre::Vector3;
+    using Ogre::Vector4;
+    using Ogre::Matrix3;
+    using Ogre::Matrix4;
+    using Ogre::Quaternion;
+    using Ogre::ColourValue;
+}
+
+namespace Loki
+{
+    class ScopeGuardImplBase;
+    typedef const ScopeGuardImplBase& ScopeGuard;
+}
+
+// Just so you don't have to include StringUtils.h everywhere just for this
+namespace orxonox
+{
+    extern _UtilExport std::string BLANKSTRING;
+}
+
+
+#endif /* _UtilPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/VA_NARGS.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/VA_NARGS.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/VA_NARGS.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util
+    @brief Declaration of the ORXONOX_VA_NARGS macro which returns the number of arguments passed to a variadic macro.
+
+    With this utility you can overload a macro for different numbers of arguments
+    (of course overloading is not possible for different types, as macros are not
+    type aware, but for different numbers of arguments is still very powerful).
+
+    Important: The macro can not be overloaded for 0 arguments: ORXONOX_VA_NARGS() returns 1!
+
+    Example: A macro to call functions
+    @code
+    myfunction();                                           // A static function
+    MyClass::myStaticFunction();                            // A static class function
+    MyClass::myFunction();                                  // A member function
+
+    #define CallFunction(...) \                             // Define a variadic macro that passes the arguments to the overloaded implementations
+        BOOST_PP_EXPAND(BOOST_PP_CAT(CallFunction, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+
+    #define CallFunction1(function) \                       // Overloaded macro for 1 argument
+        function()                                          // Calls the static function
+
+    #define CallFunction2(class, function) \                // Overloaded macro for 2 arguments
+        class::function()                                   // Calls the static class function
+
+    #define CallFunction3(class, function, object) \        // Overloaded macro for 3 arguments
+        object->class::function()                           // Calls the function on the object
+
+
+    CallFunction(myFunction);                               // Call the macro with 1 argument
+    CallFunction(MyClass, myStaticFunction);                // Call the macro with 2 arguments
+    CallFunction(MyClass, myFunction, new MyClass());       // Call the macro with 3 arguments
+    @endcode
+
+    Note that the first (variadic) macro concatenates the name "CallFunction" with
+    the number of arguments ("1" - "N"). Then all arguments are passed to the right macro.
+*/
+
+#include <boost/preprocessor/cat.hpp>
+#include <boost/preprocessor/facilities/expand.hpp>
+
+/**
+    @brief Returns the number of arguments passed to a variadic macro. Important: The number of arguments must be greater than zero (ORXONOX_VA_NARGS() returns 1).
+*/
+#define ORXONOX_VA_NARGS(...) \
+    ORXONOX_VA_NARGS_CONCAT(__VA_ARGS__, ORXONOX_VA_NARGS_NUMBERS)
+
+
+// some helper macros //
+
+#define ORXONOX_VA_NARGS_CONCAT(...) \
+    BOOST_PP_EXPAND(ORXONOX_VA_NARGS_INTERN(__VA_ARGS__))
+
+#define ORXONOX_VA_NARGS_INTERN( \
+    arg1,  arg2,  arg3,  arg4,  arg5,  arg6,  arg7,  arg8,  arg9,  arg10, \
+    arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19, arg20, \
+    arg21, arg22, arg23, arg24, arg25, arg26, arg27, arg28, arg29, arg30, \
+    arg31, arg32, arg33, arg34, arg35, arg36, arg37, arg38, arg39, arg40, \
+    arg41, arg42, arg43, arg44, arg45, arg46, arg47, arg48, arg49, arg50, \
+    arg51, arg52, arg53, arg54, arg55, arg56, arg57, arg58, arg59, arg60, \
+    arg61, arg62, arg63, argn, ...) argn
+
+#define ORXONOX_VA_NARGS_NUMBERS \
+    63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, \
+    47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, \
+    31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, \
+    15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0
Index: /code/branches/RacingBots_FS18/src/libraries/util/mbool.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/mbool.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/mbool.h	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Util
+    @brief Declaration and implementation of the @ref orxonox::mbool class.
+*/
+
+#ifndef _mbool_H__
+#define _mbool_H__
+
+#include "UtilPrereqs.h"
+
+namespace orxonox
+{
+    /**
+        @brief mbool is a small helper class that acts like a bool, but keeps track of the number of its state changes.
+
+        The mbool class acts like a bool, but it has an internal counter that counts
+        the number state changes (i.e. when the bool changes from true to false or
+        back). This is used in the network if a boolean value is synchronized, because
+        if a value changes quickly from false to true and back in the same tick, the
+        clients will never be notified of this action. By using mbool however this
+        behaviour is fixed, which is important for triggers and other objects.
+
+        @note This is efficiently solved by using a union that combines a counter and a
+        boolean bitfield of size 1. The boolean value corresponds always to the first
+        bit of the counter - this means, if the counter is incremented, the boolean state
+        changes. On the other hand, if you want to change the state, you can simply increase
+        the counter.
+    */
+    struct mbool
+    {
+        public:
+            /// Constructor: Creates the mbool and initializes the boolean value (default to false).
+            constexpr mbool(bool value = false) : value_{ static_cast<unsigned char>(value ? 1 : 0) }
+                {}
+            /// Copy-constructor, copies state and memory.
+            constexpr mbool(const mbool& value) : value_{ value.value_.memory_ }
+                {}
+            /// Destructor does nothing but not defining it might create a symbol (class is header only)
+            inline ~mbool() = default;
+
+            /// Assigns a boolean value (and increases the memory value if the value is different to the old value).
+            inline mbool& operator=(bool value)
+                { if (value != this->value_.bool_) { ++this->value_.memory_; } return (*this); }
+            /// Assigns another mbool, copies state and memory.
+            inline mbool& operator=(const mbool& value)
+                { this->value_.memory_ = value.value_.memory_; return (*this); }
+
+            /// Increases the memory which also inverts it's state (++mbool).
+            inline mbool& operator++()
+                { ++this->value_.memory_; return (*this); }
+            /// Increases the memory which also inverts it's state (mbool++).
+            inline mbool operator++(int)
+                { mbool temp = (*this); ++this->value_.memory_; return temp; }
+
+            /// Implicitly converts the mbool to a bool.
+            constexpr operator bool() const
+                { return this->value_.bool_; }
+
+            /// Compares the mbool to a bool, returns true if the bool has the same value as the state of the mbool.
+            constexpr bool operator==(bool other) const
+                { return this->value_.bool_ == other; }
+            /// Compares the mbool to a bool, returns true if the bool has a different value than the state of the mbool.
+            constexpr bool operator!=(bool other) const
+                { return this->value_.bool_ != other; }
+
+            /// Compares two mbools, returns true if their memory matches.
+            constexpr bool operator==(const mbool& other) const
+                { return this->value_.memory_ == other.value_.memory_; }
+            /// Compares two mbools, returns true if they have a different memory value.
+            constexpr bool operator!=(const mbool& other) const
+                { return this->value_.memory_ != other.value_.memory_; }
+
+            /// Returns the inverted state of the bool (doesn't change the internal state).
+            constexpr bool operator!() const
+                { return (!this->value_.bool_); }
+
+            /// Returns the memory value.
+            inline unsigned char& getMemory(){ return value_.memory_; }
+
+        private:
+            union
+            {
+                unsigned char memory_;  ///< The memory of the mbool, counts the state-changes (and the first bit represents also the boolean value)
+                bool bool_ : 1;         ///< The boolean state of the mbool, is located on the first bit of the memory variable
+            } value_;                   ///< A union containing the state and the memory of the mbool
+    };
+}
+
+#endif /* _mbool_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/AdditionalContextListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/AdditionalContextListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/AdditionalContextListener.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the AdditionalContextListener interface
+*/
+
+#ifndef _AdditionalContextListener_H__
+#define _AdditionalContextListener_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <vector>
+
+#include "OutputDefinitions.h"
+
+namespace orxonox
+{
+    /**
+        @brief AdditionalContextListener is an interface which is used to notify OutputManager about additional contexts in OutputListeners
+    */
+    class _UtilExport AdditionalContextListener
+    {
+        public:
+            virtual ~AdditionalContextListener() {}
+
+            virtual void updatedLevelMask(const OutputListener* listener) = 0;
+            virtual void updatedAdditionalContextsLevelMask(const OutputListener* listener) = 0;
+            virtual void updatedAdditionalContextsMask(const OutputListener* listener) = 0;
+    };
+}
+
+#endif /* _AdditionalContextListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/BaseWriter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/BaseWriter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/BaseWriter.cc	(revision 11817)
@@ -0,0 +1,145 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the BaseWriter class.
+*/
+
+#include "BaseWriter.h"
+
+#include "OutputManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: Initializes the config-values.
+    */
+    BaseWriter::BaseWriter(const std::string& name, bool bRegister) : SubcontextOutputListener(bRegister)
+    {
+        this->name_ = name;
+
+        this->configurableMaxLevel_ = level::none;
+        this->configurableAdditionalContextsMaxLevel_ = level::verbose;
+        this->configurableAdditionalContexts_.emplace_back("example");
+
+        this->changedConfigurableLevel();
+        this->changedConfigurableAdditionalContextsLevel();
+        this->changedConfigurableAdditionalContexts();
+    }
+
+    /**
+        @brief Destructor.
+    */
+    BaseWriter::~BaseWriter()
+    {
+    }
+
+    /**
+        @brief This function is inherited from OutputListener, each message is split into lines and sent to printLine().
+    */
+    void BaseWriter::output(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines)
+    {
+        const std::string& prefix = OutputManager::getInstance().getDefaultPrefix(level, context);
+        std::string blanks(prefix.length(), ' ');
+
+        for (size_t i = 0; i < lines.size(); ++i)
+            this->printLine((i == 0 ? prefix : blanks) + lines[i], level);
+    }
+
+    /**
+        @brief Overwritten implementation of the function inherited from OutputListener, sets also the corresponding config-value.
+    */
+    void BaseWriter::setLevelMax(OutputLevel max)
+    {
+        this->configurableMaxLevel_ = max;
+        this->changedConfigurableLevel();
+    }
+
+    /**
+        @brief Overwritten implementation of the function inherited from OutputListener, sets also the corresponding config-value.
+    */
+    void BaseWriter::setAdditionalContextsLevelMax(OutputLevel max)
+    {
+        this->configurableAdditionalContextsMaxLevel_ = max;
+        this->changedConfigurableAdditionalContextsLevel();
+    }
+
+    /**
+        @brief Called if the config value has changed, updates the corresponding mask in OutputListener.
+    */
+    void BaseWriter::changedConfigurableLevel()
+    {
+        OutputListener::setLevelMax(static_cast<OutputLevel>(this->configurableMaxLevel_));
+    }
+
+    /**
+        @brief Called if the config value has changed, updates the corresponding mask in OutputListener.
+    */
+    void BaseWriter::changedConfigurableAdditionalContextsLevel()
+    {
+        OutputListener::setAdditionalContextsLevelMax(static_cast<OutputLevel>(this->configurableAdditionalContextsMaxLevel_));
+    }
+
+    /**
+        @brief Called if the config-vector of accepted contexts has changed, updates the masks in SubcontextOutputListener.
+    */
+    void BaseWriter::changedConfigurableAdditionalContexts()
+    {
+        OutputContextMask main_contexts = context::none;
+        std::set<const OutputContextContainer*> sub_contexts;
+
+        // iterate over all strings in the config-vector
+        for (const std::string& full_name : this->configurableAdditionalContexts_)
+        {
+            // split the name into main-name and sub-name (if given; otherwise sub-name remains empty). both names are separated by ::
+            std::string name = full_name;
+            std::string subname;
+
+            size_t pos = full_name.find("::");
+            if (pos != std::string::npos)
+            {
+                name = full_name.substr(0, pos);
+                subname = full_name.substr(pos + 2);
+            }
+
+            // get the context defined by this name
+            const OutputContextContainer& context = OutputManager::getInstance().registerContext(name, subname);
+
+            // if the context is a sub-context, insert it to the set of sub-contexts. Otherwise add it's mask to the mask of main-contexts.
+            if (context.sub_id == context::no_subcontext)
+                main_contexts |= context.mask;
+            else
+                sub_contexts.insert(&context);
+        }
+
+        // pass main-contexts and sub-contexts to SubcontextOutputListener
+        this->setAdditionalContextsMask(main_contexts);
+        this->setAdditionalSubcontexts(sub_contexts);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/BaseWriter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/BaseWriter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/BaseWriter.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the BaseWriter class, the base of all output writers.
+*/
+
+#ifndef _BaseWriter_H__
+#define _BaseWriter_H__
+
+#include "util/UtilPrereqs.h"
+#include "SubcontextOutputListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief BaseWriter is an output listener and makes the accepted output levels and contexts configurable.
+
+        All output writers like ConsoleWriter and LogWriter are inherited from
+        this class. BaseWriter itself inherits from SubcontextOutputListener.
+        It adds helper functions to configure the accepted levels and contexts.
+
+        The levels are not fully configurable, only the "max" form is allowed
+        (which means that it's only possible to define a maximum level, not
+        the full mask).
+
+        Contexts are defined by a vector of strings, each context is defined
+        by it's name. Sub-contexts have the form \a "main-name::sub-name", i.e.
+        their name is concatenated with :: in between.
+
+        Each instance of BaseWriter needs a name to generate distinguishable
+        config values.
+
+        Received output messages are split into lines and sent line by line to
+        the virtual printLine() function. Each line has a prepended prefix
+        which describes the level and context of the output.
+    */
+    class _UtilExport BaseWriter : public SubcontextOutputListener
+    {
+        public:
+            BaseWriter(const std::string& name, bool bRegister = true);
+            virtual ~BaseWriter();
+
+            void setLevelMax(OutputLevel max);
+            void setAdditionalContextsLevelMax(OutputLevel max);
+
+            /// @brief Returns the name of this instance.
+            const std::string& getName() const
+                { return this->name_; }
+
+            /// Config value, used to define the maximum output level (independent of contexts)
+            int configurableMaxLevel_;
+            /// @brief Returns the name of the config value which defines the maximum output level (independent of contexts).
+            inline std::string getConfigurableMaxLevelName() const
+                { return this->name_ + "Level"; }
+
+            /// Config value, used to define the maximum output level of additional context
+            int configurableAdditionalContextsMaxLevel_;
+            /// @brief Returns the name of the config value which defines the maximum output level of additional context.
+            inline std::string getConfigurableAdditionalContextsMaxLevelName() const
+                { return this->name_ + "AdditionalContextsLevel"; }
+
+            /// Config vector, used to define the additional contexts (and sub-contexts)
+            std::vector<std::string> configurableAdditionalContexts_;
+            /// @brief Returns the name of the config vector which defines the additional contexts (and sub-contexts)
+            inline std::string getConfigurableAdditionalContextsName() const
+                { return this->name_ + "AdditionalContexts"; }
+
+            void changedConfigurableLevel();
+            void changedConfigurableAdditionalContextsLevel();
+            void changedConfigurableAdditionalContexts();
+
+            /// Returns the (static) name of the section wherein the config-values are defined.
+            static inline std::string getConfigurableSectionName()
+                { return "Output"; }
+
+        protected:
+            virtual void output(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines) override;
+
+        private:
+            virtual void printLine(const std::string& line, OutputLevel level) = 0; ///< Pure virtual function, gets called for each line of output together with a prefix which describes level and context of the output.
+
+            void setLevelRange(OutputLevel min, OutputLevel max);                   ///< Inherited function, overwritten as private because it is not supported by the config-value
+            void setLevelMask(OutputLevel mask);                                    ///< Inherited function, overwritten as private because it is not supported by the config-value
+
+            void setAdditionalContextsLevelRange(OutputLevel min, OutputLevel max); ///< Inherited function, overwritten as private because it is not supported by the config-value
+            void setAdditionalContextsLevelMask(OutputLevel mask);                  ///< Inherited function, overwritten as private because it is not supported by the config-value
+
+            std::string name_; ///< The name of this instance, used to generate unique config-values
+    };
+}
+
+#endif /* _BaseWriter_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,12 @@
+ADD_SOURCE_FILES(UTIL_SRC_FILES
+BUILD_UNIT OutputBuildUnit.cc
+  OutputStream.cc
+  OutputManager.cc
+  OutputListener.cc
+  SubcontextOutputListener.cc
+  BaseWriter.cc
+  ConsoleWriter.cc
+  LogWriter.cc
+  MemoryWriter.cc
+END_BUILD_UNIT
+)
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/ConsoleWriter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/ConsoleWriter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/ConsoleWriter.cc	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the ConsoleWriter singleton.
+*/
+
+#include "ConsoleWriter.h"
+
+
+#include "OutputManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor, initializes the output level.
+
+        In debug builds, it writes output up to level::internal_warning to the
+        console, in release builds only up to level::user_info.
+
+        After creation, the instance is enabled.
+    */
+    ConsoleWriter::ConsoleWriter(std::ostream& outputStream) : BaseWriter("Console"), outputStream_(outputStream)
+    {
+#ifdef ORXONOX_RELEASE
+        this->setLevelMax(level::user_info);
+#else
+        this->setLevelMax(level::internal_warning);
+#endif
+        this->bEnabled_ = true;
+    }
+
+    /**
+        @brief Destructor.
+    */
+    ConsoleWriter::~ConsoleWriter()
+    {
+    }
+
+    /**
+        @brief Inherited function from BaseWriter, writes output to the console using std::cout.
+    */
+    void ConsoleWriter::printLine(const std::string& line, OutputLevel)
+    {
+        this->outputStream_ << line << std::endl;
+    }
+
+    /**
+        @brief Enables the instance by registering itself as listener at OutputManager.
+    */
+    void ConsoleWriter::enable()
+    {
+        if (!this->bEnabled_)
+        {
+            OutputManager::getInstance().registerListener(this);
+            this->bEnabled_ = true;
+        }
+    }
+
+    /**
+        @brief Disables the instance by unregistering itself from OutputManager.
+    */
+    void ConsoleWriter::disable()
+    {
+        if (this->bEnabled_)
+        {
+            OutputManager::getInstance().unregisterListener(this);
+            this->bEnabled_ = false;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/ConsoleWriter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/ConsoleWriter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/ConsoleWriter.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the ConsoleWriter singleton which is used to write output to the console.
+*/
+
+#ifndef _ConsoleWriter_H__
+#define _ConsoleWriter_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <ostream>
+
+#include "BaseWriter.h"
+
+namespace orxonox
+{
+    /**
+        @brief ConsoleWriter inherits from BaseWriter and writes output to the console.
+
+        This class can be seen as an equivalent to std::cout within the output system.
+    */
+    class _UtilExport ConsoleWriter : public BaseWriter
+    {
+        public:
+            ConsoleWriter(std::ostream& outputStream);
+            virtual ~ConsoleWriter();
+
+            void enable();
+            void disable();
+
+            inline const std::ostream& getOutputStream() const
+                { return this->outputStream_; }
+
+        protected:
+            virtual void printLine(const std::string& line, OutputLevel level) override;
+
+        private:
+            // non-copyable:
+            ConsoleWriter(const ConsoleWriter&) = delete;
+            ConsoleWriter& operator=(const ConsoleWriter&) = delete;
+
+            std::ostream& outputStream_; ///< The ostream to which the console writer writes its output
+            bool bEnabled_;              ///< If false, the instance will not write output to the console.
+    };
+}
+
+#endif /* _ConsoleWriter_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/LogWriter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/LogWriter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/LogWriter.cc	(revision 11817)
@@ -0,0 +1,200 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the LogWriter singleton.
+*/
+
+#include "LogWriter.h"
+
+#include <ctime>
+#include <chrono>
+#include <cstdlib>
+
+#include "OutputManager.h"
+#include "MemoryWriter.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    static constexpr int MAX_ARCHIVED_FILES = 9;
+
+    /**
+        @brief Constructor, initializes the desired output levels and the name and path of the log-file, and opens the log-file.
+
+        By default, LogWriter receives all output up to level::internal_info.
+        The log-file has a default name which usually doesn't change. The path
+        is initialized with a temporary directory, depending on the system,
+        and can be changed later.
+    */
+    LogWriter::LogWriter() : BaseWriter("Log")
+    {
+        this->setLevelMax(level::internal_info);
+
+        this->filename_ = "orxonox.log";
+
+        // get the path for a temporary file, depending on the system
+#ifdef ORXONOX_PLATFORM_WINDOWS
+        this->directory_ = getenv("TEMP");
+#else
+        this->directory_ = "/tmp";
+#endif
+
+        // send a message to the user so that he can find the file in the case of a crash.
+        OutputManager::getInstance().pushMessage(level::user_info, context::undefined(), "Opening log file " + this->getPath());
+
+        this->openFile();
+    }
+
+    /**
+        @brief Destructor, closes the log-file.
+    */
+    LogWriter::~LogWriter()
+    {
+        this->closeFile();
+    }
+
+    /**
+        @brief Opens the log-file in order to write output to it.
+    */
+    void LogWriter::openFile()
+    {
+        // archive the old log file
+        this->archive();
+
+        // open the file
+        this->file_.open(this->getPath().c_str(), std::fstream::out);
+
+        // check if it worked and print some output
+        if (this->file_.is_open())
+            this->printLine("Log file opened", level::none);
+        else
+            OutputManager::getInstance().pushMessage(level::user_warning, context::undefined(), "Failed to open log file. File logging disabled.");
+    }
+
+    /**
+        @brief Closes the log-file.
+    */
+    void LogWriter::closeFile()
+    {
+        if (this->file_.is_open())
+        {
+            this->printLine("Log file closed", level::none);
+            this->file_.close();
+        }
+    }
+
+    /**
+     * @brief Archives old copies of the log file by adding increasing numbers to the filename.
+     */
+    void LogWriter::archive(int index)
+    {
+        std::string oldPath = this->getArchivedPath(index);
+
+        // see if the file already exists, otherwise return
+        std::ifstream stream(oldPath.c_str());
+        bool exists = stream.is_open();
+        stream.close();
+
+        if (!exists)
+            return;
+
+        if (index < MAX_ARCHIVED_FILES)
+        {
+            // increment the index and archive the file with the next higher index
+            this->archive(++index);
+
+            // create the new path based on the incremented index
+            std::string newPath = this->getArchivedPath(index);
+
+            // move the file
+            std::rename(oldPath.c_str(), newPath.c_str());
+        }
+        else
+        {
+            // delete the file
+            std::remove(oldPath.c_str());
+        }
+    }
+    
+    /**
+     * @brief Returns the path for archived copies of the logfile (based on the archive index)
+     */
+    std::string LogWriter::getArchivedPath(int index) const
+    {
+        std::string path = this->getPath();
+        if (index > 0)
+            path += '.' + multi_cast<std::string>(index);
+        return path;
+    }
+
+    /**
+        @brief Changes the path of the log-file. Re-writes the log-file by using MemoryWriter.
+    */
+    void LogWriter::setLogDirectory(const std::string& directory)
+    {
+        // notify about the change of the log-file (because the old file will no longer be updated)
+        OutputManager::getInstance().pushMessage(level::internal_info, context::undefined(), "Migrating log file from " + this->directory_ + "\nto " + directory);
+
+        // close the old file, update the path and open the new file
+        this->closeFile();
+        this->directory_ = directory;
+        this->openFile();
+
+        // request old output from MemoryWriter
+        if (OutputManager::getInstance().getMemoryWriter())
+            OutputManager::getInstance().getMemoryWriter()->resendOutput(this);
+    }
+
+    /**
+        @brief Inherited function from BaseWriter, writers output together with a timestamp to the log-file.
+    */
+    void LogWriter::printLine(const std::string& line, OutputLevel)
+    {
+        if (!this->file_.is_open())
+            return;
+
+        // get the milliseconds
+        std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
+        std::chrono::system_clock::duration timeSinceEpoch = now.time_since_epoch();
+        std::chrono::milliseconds millisSinceEpoch = std::chrono::duration_cast<std::chrono::milliseconds>(timeSinceEpoch);
+        unsigned int millis = (millisSinceEpoch.count() % 1000);
+
+        // get the current time
+        time_t rawtime = std::chrono::system_clock::to_time_t(now);
+        struct tm* timeinfo = localtime(&rawtime);
+
+        // format time: hh:mm:ss:xxx
+        char buffer[13];
+        snprintf(buffer, sizeof(buffer), "%.2i:%.2i:%.2i:%.3i", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, millis);
+
+        // print timestamp and output line to the log file
+        this->file_ << buffer << ' ' << line << std::endl;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/LogWriter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/LogWriter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/LogWriter.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the LogWriter singleton which writes output to a log-file.
+*/
+
+#ifndef _LogWriter_H__
+#define _LogWriter_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <fstream>
+
+#include "BaseWriter.h"
+
+namespace orxonox
+{
+    /**
+        @brief The LogWriter class inherits from BaseWriter and writes output to a log-file.
+
+        The path of the file can be changed, in which case the file
+        is rewritten by using the output stored by MemoryWriter. This adds the
+        possibility to change the desired output levels before changing the
+        path in order to get the complete output with the new output levels
+        at the new path.
+    */
+    class _UtilExport LogWriter : public BaseWriter
+    {
+        public:
+            LogWriter();
+            virtual ~LogWriter();
+
+            void setLogDirectory(const std::string& directory);
+
+            /** @brief Returns the path to the logfile. */
+            inline std::string getPath() const
+                { return this->directory_ + '/' + this->filename_; }
+            /** @brief Returns the open file stream. */
+            inline const std::ofstream& getFile() const
+                { return this->file_; }
+
+        protected:
+            virtual void printLine(const std::string& line, OutputLevel level) override;
+
+        private:
+            // non-copyable:
+            LogWriter(const LogWriter&) = delete;
+            LogWriter& operator=(const LogWriter&) = delete;
+
+            void openFile();
+            void closeFile();
+
+            void archive(int index = 0);
+            std::string getArchivedPath(int index) const;
+
+            std::string filename_;  ///< The name of the log-file (without directory)
+            std::string directory_; ///< The directory where the log-file resided (without file-name)
+            std::ofstream file_;    ///< The output file stream.
+    };
+}
+
+#endif /* _LogWriter_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/MemoryWriter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/MemoryWriter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/MemoryWriter.cc	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the MemoryWriter singleton.
+*/
+
+#include "MemoryWriter.h"
+#include "OutputManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor, initializes the level mask with all levels activated.
+    */
+    MemoryWriter::MemoryWriter()
+    {
+        this->setLevelMask(level::all);
+    }
+
+    /**
+        @brief Destructor.
+    */
+    MemoryWriter::~MemoryWriter()
+    {
+    }
+
+    /**
+        @brief Implementation of the output() function inherited from OutputListener, stores the received output in memory.
+    */
+    void MemoryWriter::output(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines)
+    {
+        this->messages_.emplace_back(level, context, lines);
+    }
+
+    /**
+        @brief Iterates over all stored output messages and sends them to the OutputListener.
+    */
+    void MemoryWriter::resendOutput(OutputListener* listener) const
+    {
+        for (const Message& message : this->messages_)
+        {
+            listener->unfilteredOutput(message.level, *message.context, message.lines);
+        }
+    }
+
+    /**
+        @brief Unregisters the instance from OutputManager, hence it will not receive any further output.
+    */
+    void MemoryWriter::disable()
+    {
+        OutputManager::getInstance().unregisterListener(this);
+        this->output(level::debug_output, context::undefined(), std::vector<std::string>(1, "MemoryWriter disabled, further messages may be lost"));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/MemoryWriter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/MemoryWriter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/MemoryWriter.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the MemoryWriter singleton.
+*/
+
+#ifndef _MemoryWriter_H__
+#define _MemoryWriter_H__
+
+#include "util/UtilPrereqs.h"
+#include "OutputListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief MemoryWriter is a singleton which is derived from OutputListener and writes all output to a list.
+
+        This list can be used to re-send old output to other instances of
+        OutputListener, e.g. if they were newly created or to re-write the
+        log-file.
+
+        Since MemoryWriter receives output of all levels, this means also that
+        all possible output needs to be generated as long as MemoryWriter stays
+        active. Hence disable() should be called as soon as possible.
+    */
+    class _UtilExport MemoryWriter : public OutputListener
+    {
+        /// @brief A helper struct which is used to store output and its properties.
+        struct Message
+        {
+            /// @brief Constructor, assigns all values.
+            Message(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines)
+                : level(level), context(&context), lines(lines) {}
+
+            OutputLevel level;                      ///< The level of the output message
+            const OutputContextContainer* context;  ///< The context of the output message
+            std::vector<std::string> lines;         ///< The lines of text of the output message
+        };
+
+        public:
+            MemoryWriter();
+            virtual ~MemoryWriter();
+
+            void resendOutput(OutputListener* listener) const;
+            void disable();
+
+        protected:
+            virtual void output(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines) override;
+
+        private:
+            // non-copyable:
+            MemoryWriter(const MemoryWriter&) = delete;
+            MemoryWriter& operator=(const MemoryWriter&) = delete;
+
+            std::vector<Message> messages_; ///< Stores all output messages from the creation of this instance until disable() is called.
+    };
+}
+
+#endif /* _MemoryWriter_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputDefinitions.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputDefinitions.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputDefinitions.h	(revision 11817)
@@ -0,0 +1,180 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Defines output levels and output contexts.
+*/
+
+#ifndef _OutputDefinitions_H__
+#define _OutputDefinitions_H__
+
+#include "util/UtilPrereqs.h"
+#include <string>
+
+/**
+    @brief Defines a context function with a given name.
+    @param name Name of the context
+
+    Context functions return a reference to a OutputContextContainer. Context
+    functions (or the containers they return) can be passed to orxout() as
+    context argument.
+*/
+#ifndef DISABLE_OUTPUT_CONTEXT_STATIC_CACHE
+    #define REGISTER_OUTPUT_CONTEXT(name) \
+        inline const OutputContextContainer& name() { static OutputContextContainer context = registerContext(#name); return context; }
+#else
+    #define REGISTER_OUTPUT_CONTEXT(name) \
+        inline const OutputContextContainer& name() { return registerContext(#name); }
+#endif
+
+/**
+    @brief Defines a sub-context.
+    @param name Name of the main-context
+    @param subname Name of the sub-context
+
+    Sub-contexts act like normal contexts, except that multiple sub-contexts
+    share the context mask of their main-context. This allows contexts with
+    more descriptive names (e.g. input::keyboard) and they can be filtered
+    individually by derivatives of orxonox::SubcontextOutputListener.
+*/
+#ifndef DISABLE_OUTPUT_CONTEXT_STATIC_CACHE
+    #define REGISTER_OUTPUT_SUBCONTEXT(name, subname) \
+        inline const OutputContextContainer& subname() { static const OutputContextContainer context = registerContext(#name, #subname); return context; }
+#else
+    #define REGISTER_OUTPUT_SUBCONTEXT(name, subname) \
+        inline const OutputContextContainer& subname() { return registerContext(#name, #subname); }
+#endif
+
+// tolua_begin
+namespace orxonox
+{
+    namespace level
+    {
+        /**
+            @brief Output levels define type and importance of an output message.
+            They can be passed to the orxout() function as level argument.
+        */
+        enum OutputLevel
+        {
+            all              = 0xFFFF, ///< Level mask with all bits set to 1
+            none             = 0x0000, ///< Level mask with all bits set to 0
+
+            message          = 0x0001, ///< Output level, used for messages directed to the user (e.g. "Press any key to continue")
+            debug_output     = 0x0002, ///< Output level, used for temporary debug output while writing code
+            user_error       = 0x0004, ///< Output level, used for error messages which are important for the user
+            user_warning     = 0x0008, ///< Output level, used for warnings which are important for the user
+            user_status      = 0x0010, ///< Output level, used to notify the user about the program's state
+            user_info        = 0x0020, ///< Output level, used to provide the user with additional progress information
+            internal_error   = 0x0040, ///< Output level, used for error messages which are important for developers
+            internal_warning = 0x0080, ///< Output level, used for warnings which are important for developers
+            internal_status  = 0x0100, ///< Output level, used to log the program's internal state in the log file
+            internal_info    = 0x0200, ///< Output level, used to log information about the program's progress in the log file
+            verbose          = 0x0400, ///< Output level, usually not visible, used for unimportant debug information
+            verbose_more     = 0x0800, ///< Output level, usually not visible, used for unimportant debug information (less important than verbose)
+            verbose_ultra    = 0x1000  ///< Output level, usually not visible, used for unimportant debug information (even less important than verbose_more)
+        };
+    }
+// tolua_end
+
+    using namespace level;
+
+    typedef uint64_t OutputContextMask;  ///< Used to store the context masks. Each bit defines a context.
+    typedef uint16_t OutputContextSubID; ///< Used to store the IDs of sub-contexts. Each number except context::no_subcontext defines a sub-context.
+
+    /// @brief Stores all information about a context.
+    struct OutputContextContainer
+    {
+        OutputContextMask mask;     ///< The mask of the context (or the mask of the main-context if this container defines a sub-context)
+        OutputContextSubID sub_id;  ///< The id of the sub-context (or context::no_subcontext if this container doesn't define a sub-context)
+        std::string name;           ///< The name of this context
+
+        inline bool operator==(const OutputContextContainer& other) const
+        {
+            return this->mask == other.mask && this->sub_id == other.sub_id && this->name == other.name;
+        }
+    };
+
+    typedef const OutputContextContainer& (OutputContextFunction)();
+
+    /**
+        @brief Registers a context.
+        This is a shortcut to OutputManager::registerContext() to avoid the inclusion of its header file.
+    */
+    extern _UtilExport const OutputContextContainer& registerContext(const std::string& name, const std::string& subname = "");
+
+    namespace context
+    {
+        static constexpr OutputContextMask all       = 0xFFFFFFFFFFFFFFFFull; ///< Context mask, all bits set to 1
+        static constexpr OutputContextMask none      = 0x0000000000000000ull; ///< Context mask, all bits set to 0
+
+        static constexpr OutputContextSubID no_subcontext = 0; ///< Used as ID for contexts which are not sub-contexts
+
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(undefined); ///< "undefined" context which is implicitly used for all output that has no explicit context
+
+            REGISTER_OUTPUT_CONTEXT(ogre);
+            REGISTER_OUTPUT_CONTEXT(cegui);
+            REGISTER_OUTPUT_CONTEXT(lua);
+            REGISTER_OUTPUT_CONTEXT(tcl);
+            REGISTER_OUTPUT_CONTEXT(identifier);
+            REGISTER_OUTPUT_CONTEXT(object_list);
+            REGISTER_OUTPUT_CONTEXT(super);
+            REGISTER_OUTPUT_CONTEXT(language);
+            REGISTER_OUTPUT_CONTEXT(commands);
+            REGISTER_OUTPUT_CONTEXT(input);
+            REGISTER_OUTPUT_CONTEXT(events);
+            REGISTER_OUTPUT_CONTEXT(config);
+            REGISTER_OUTPUT_CONTEXT(templates);
+            REGISTER_OUTPUT_CONTEXT(loader);
+            REGISTER_OUTPUT_CONTEXT(xml);
+            REGISTER_OUTPUT_CONTEXT(network);
+            REGISTER_OUTPUT_CONTEXT(packets);
+            REGISTER_OUTPUT_CONTEXT(master_server);
+            REGISTER_OUTPUT_CONTEXT(sound);
+            REGISTER_OUTPUT_CONTEXT(lod);
+            REGISTER_OUTPUT_CONTEXT(pickups);
+            REGISTER_OUTPUT_CONTEXT(quests);
+            REGISTER_OUTPUT_CONTEXT(notifications);
+            REGISTER_OUTPUT_CONTEXT(triggers);
+            REGISTER_OUTPUT_CONTEXT(docking);
+
+            namespace misc
+            {
+                REGISTER_OUTPUT_SUBCONTEXT(misc, executor);
+                REGISTER_OUTPUT_SUBCONTEXT(misc, gui);
+                REGISTER_OUTPUT_SUBCONTEXT(misc, overlays);
+                REGISTER_OUTPUT_SUBCONTEXT(misc, script);
+            }
+        }
+    }
+} // tolua_export
+
+#endif /* _OutputDefinitions_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputListener.cc	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the OutputListener class.
+*/
+
+#include "OutputListener.h"
+
+#include "OutputManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor, initializes the values and registers the instance at OutputManager if requested.
+        @param bRegister If \c true, the instance is automatically registered at OutputManager.
+                         Should be \c false if the constructor of the derived class generates output.
+    */
+    OutputListener::OutputListener(bool bRegister)
+    {
+        this->levelMask_ = level::none;
+        this->additionalContextsLevelMask_ = level::none;
+        this->additionalContextsMask_ = context::none;
+
+        if (bRegister)
+            OutputManager::getInstance().registerListener(this);
+    }
+
+    /**
+        @brief Destructor, unregisters the instance from OutputManager.
+    */
+    OutputListener::~OutputListener()
+    {
+        OutputManager::getInstance().unregisterListener(this);
+    }
+
+    /**
+        @brief Adds a listener to the list.
+    */
+    void OutputListener::registerListener(AdditionalContextListener* listener)
+    {
+        this->listeners_.push_back(listener);
+    }
+
+    /**
+        @brief Removes a listener from the list.
+    */
+    void OutputListener::unregisterListener(AdditionalContextListener* listener)
+    {
+        for (std::vector<AdditionalContextListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if (*it == listener)
+            {
+                this->listeners_.erase(it);
+                break;
+            }
+        }
+    }
+
+    /**
+        @brief Defines the level mask in a way which accepts all output up to the level \c max.
+    */
+    void OutputListener::setLevelMax(OutputLevel max)
+    {
+        this->setLevelRange(static_cast<OutputLevel>(0x1), max);
+    }
+
+    /**
+        @brief Defines the level mask in a way which accepts all output between the levels \c min and \c max.
+    */
+    void OutputListener::setLevelRange(OutputLevel min, OutputLevel max)
+    {
+        int mask = 0;
+        for (int level = min; level <= max; level = level << 1)
+            mask |= level;
+
+        this->setLevelMask(static_cast<OutputLevel>(mask));
+    }
+
+    /**
+        @brief Defines the level mask.
+    */
+    void OutputListener::setLevelMask(OutputLevel mask)
+    {
+        this->levelMask_ = mask;
+
+        for (AdditionalContextListener* listener : this->listeners_)
+            listener->updatedLevelMask(this);
+    }
+
+    /**
+        @brief Defines the level mask of additional contexts in a way which accepts all output up to the level \c max.
+    */
+    void OutputListener::setAdditionalContextsLevelMax(OutputLevel max)
+    {
+        this->setAdditionalContextsLevelRange(static_cast<OutputLevel>(0x1), max);
+    }
+
+    /**
+        @brief Defines the level mask of additional contexts in a way which accepts all output between the levels \c min and \c max.
+    */
+    void OutputListener::setAdditionalContextsLevelRange(OutputLevel min, OutputLevel max)
+    {
+        int mask = 0;
+        for (int level = min; level <= max; level = level << 1)
+            mask |= level;
+
+        this->setAdditionalContextsLevelMask(static_cast<OutputLevel>(mask));
+    }
+
+    /**
+        @brief Defines the level mask of additional contexts.
+    */
+    void OutputListener::setAdditionalContextsLevelMask(OutputLevel mask)
+    {
+        this->additionalContextsLevelMask_ = mask;
+
+        for (AdditionalContextListener* listener : this->listeners_)
+            listener->updatedAdditionalContextsLevelMask(this);
+    }
+
+    /**
+        @brief Defines the mask of additional contexts.
+    */
+    void OutputListener::setAdditionalContextsMask(OutputContextMask mask)
+    {
+        this->additionalContextsMask_ = mask;
+
+        for (AdditionalContextListener* listener : this->listeners_)
+            listener->updatedAdditionalContextsMask(this);
+    }
+
+    /**
+        @brief Returns true if this listener accepts output of the given level and context, based on the levels and contexts masks.
+    */
+    bool OutputListener::acceptsOutput(OutputLevel level, const OutputContextContainer& context) const
+    {
+        // check if the output level is accepted by the level mask (independent of the context)
+        if (this->levelMask_ & level)
+            return true;
+
+        // check if the output context is accepted by the additional context mask and if the level matches as well
+        if ((this->additionalContextsMask_ & context.mask) && (this->additionalContextsLevelMask_ & level))
+            return true;
+
+        // otherwise we don't accept the output
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputListener.h	(revision 11817)
@@ -0,0 +1,182 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the OutputListener interface which receives output
+    from orxonox::OutputManager.
+*/
+
+#ifndef _OutputListener_H__
+#define _OutputListener_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <vector>
+
+#include "OutputDefinitions.h"
+
+namespace orxonox
+{
+    /**
+        @brief OutputListener is an interface which is used to receive output of a certain level and context from OutputManager.
+    */
+    //  See below the class declaration for a more detailed description.
+    class _UtilExport OutputListener
+    {
+        public:
+            OutputListener(bool bRegister = true);
+            virtual ~OutputListener();
+
+            void registerListener(AdditionalContextListener* listener);
+            void unregisterListener(AdditionalContextListener* listener);
+
+            void setLevelMax(OutputLevel max);
+            void setLevelRange(OutputLevel min, OutputLevel max);
+            void setLevelMask(OutputLevel mask);
+
+            void setAdditionalContextsLevelMax(OutputLevel max);
+            void setAdditionalContextsLevelRange(OutputLevel min, OutputLevel max);
+            void setAdditionalContextsLevelMask(OutputLevel mask);
+
+            virtual void setAdditionalContextsMask(OutputContextMask mask);
+
+            /// @brief Returns the level mask.
+            inline OutputLevel getLevelMask() const
+                { return this->levelMask_; }
+            /// @brief Returns the additional contexts mask.
+            inline OutputContextMask getAdditionalContextsMask() const
+                { return this->additionalContextsMask_; }
+            /// @brief Returns the additional contexts level mask.
+            inline OutputLevel getAdditionalContextsLevelMask() const
+                { return this->additionalContextsLevelMask_; }
+
+            virtual bool acceptsOutput(OutputLevel level, const OutputContextContainer& context) const;
+
+            /// @brief Called by OutputManager for each line of output, checks if this listener actually accepts this output before it calls the output() function.
+            virtual void unfilteredOutput(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines)
+                { if (this->acceptsOutput(level, context)) this->output(level, context, lines); }
+
+        protected:
+            /// @brief Pure virtual function, needs to be implemented in order to receive output.
+            virtual void output(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines) = 0;
+
+            inline const std::vector<AdditionalContextListener*>& getListeners() const
+                { return this->listeners_; }
+
+        private:
+            std::vector<AdditionalContextListener*> listeners_; ///< List of all registered additional context listeners
+
+            OutputLevel       levelMask_;                       ///< Mask of accepted output levels, independent of contexts
+            OutputContextMask additionalContextsMask_;          ///< Mask of accepted additional contexts
+            OutputLevel       additionalContextsLevelMask_;     ///< Mask of accepted output levels of the additional contexts
+    };
+
+    /**
+        @class OutputListener
+
+        An instance of OutputListener registers itself at OutputManager and
+        declares the desired output levels and contexts. OutputManager will
+        then send output to it by calling the output() function.
+
+        OutputListener has 3 masks to define the desired output. These masks
+        can be used in two different ways (or as a combination of both):
+        \li 1. By defining the \a "level mask": The OutputListener will then
+               receive all output of these levels independent of the context.
+        \li 2. By defining the \a "additional contexts mask" and the
+               \a "additional contexts level mask": This way the listener
+               receives only output of a particular context and level.
+        \li 3. By using all 3 masks which combines the output defined by the
+               first two ways.
+
+        This can be illustrated as follows:
+
+        1. Only level mask:
+        \li level-mask = error | warning;
+
+        @verbatim
+                |   Contexts:   |
+                | A | B | C | D |
+        --------|---|---|---|---|
+        debug   | - | - | - | - |
+        --------|---|---|---|---|
+        error   | x | x | x | x |
+        --------|---|---|---|---|       [x] Receives output
+        warning | x | x | x | x |       [-] Does not receive output
+        --------|---|---|---|---|
+        status  | - | - | - | - |
+        --------|---|---|---|---|
+        verbose | - | - | - | - |
+        --------|---|---|---|---|
+        @endverbatim
+
+        2. Only additional contexts:
+        \li additional-contexts-mask = B | D;
+        \li additional-contexts-level-mask = debug | verbose;
+
+        @verbatim
+                |   Contexts:   |
+                | A | B | C | D |
+        --------|---|---|---|---|
+        debug   | - | x | - | x |
+        --------|---|---|---|---|
+        error   | - | - | - | - |
+        --------|---|---|---|---|       [x] Receives output
+        warning | - | - | - | - |       [-] Does not receive output
+        --------|---|---|---|---|
+        status  | - | - | - | - |
+        --------|---|---|---|---|
+        verbose | - | x | - | x |
+        --------|---|---|---|---|
+        @endverbatim
+
+        3. Both level mask plus additional contexts:
+        \li level-mask = error | warning;
+        \li additional-contexts-mask = B | D;
+        \li additional-contexts-level-mask = debug | verbose;
+
+        @verbatim
+                |   Contexts:   |
+                | A | B | C | D |
+        --------|---|---|---|---|
+        debug   | - | x | - | x |
+        --------|---|---|---|---|
+        error   | x | x | x | x |
+        --------|---|---|---|---|       [x] Receives output
+        warning | x | x | x | x |       [-] Does not receive output
+        --------|---|---|---|---|
+        status  | - | - | - | - |
+        --------|---|---|---|---|
+        verbose | - | x | - | x |
+        --------|---|---|---|---|
+        @endverbatim
+    */
+}
+
+#endif /* _OutputListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputManager.cc	(revision 11817)
@@ -0,0 +1,306 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the OutputManager singleton.
+*/
+
+#include "OutputManager.h"
+
+#include <iostream>
+
+#include "MemoryWriter.h"
+#include "ConsoleWriter.h"
+#include "LogWriter.h"
+#include "util/Output.h"
+#include "util/StringUtils.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor, initializes all values.
+    */
+    OutputManager::OutputManager()
+    {
+        this->combinedLevelMask_ = level::none;
+        this->combinedAdditionalContextsLevelMask_ = level::none;
+        this->combinedAdditionalContextsMask_ = context::none;
+
+        this->subcontextCounter_ = 0;
+
+        this->isInitialized_ = false;
+        this->memoryWriterInstance_ = nullptr;
+        this->consoleWriterInstance_ = nullptr;
+        this->logWriterInstance_ = nullptr;
+
+        // register 'undefined' context in order to give it always the first context-ID
+        this->registerContext("undefined");
+    }
+
+    /**
+        @brief Destructor.
+    */
+    OutputManager::~OutputManager()
+    {
+        while (!this->listeners_.empty())
+            this->unregisterListener(this->listeners_[0]);
+
+        if (this->memoryWriterInstance_)
+            delete this->memoryWriterInstance_;
+        if (this->consoleWriterInstance_)
+            delete this->consoleWriterInstance_;
+        if (this->logWriterInstance_)
+            delete this->logWriterInstance_;
+    }
+
+    /*static*/ std::shared_ptr<OutputManager>& OutputManager::Testing::getInstancePointer()
+    {
+        static std::shared_ptr<OutputManager> instance(new OutputManager());
+        return instance;
+    }
+
+    /**
+        @brief Returns the only existing instance of the OutputManager singleton.
+    */
+    /*static*/ OutputManager& OutputManager::getInstance()
+    {
+        return *OutputManager::Testing::getInstancePointer();
+    }
+
+    /**
+        @brief Returns the only existing instance of the OutputManager singleton
+        and ensures that the most important output listeners exist.
+
+        You should use this function if you send output to OutputManager and want
+        to be sure that the most important output listeners exist. Don't use it
+        elsewhere inside the output system to avoid circular calls.
+    */
+    /*static*/ OutputManager& OutputManager::getInstanceAndCreateListeners()
+    {
+        OutputManager& instance = *OutputManager::Testing::getInstancePointer();
+
+        if (!instance.isInitialized_) {
+            instance.isInitialized_ = true;
+            instance.memoryWriterInstance_ = new MemoryWriter();
+            instance.consoleWriterInstance_ = new ConsoleWriter(std::cout);
+            instance.logWriterInstance_ = new LogWriter();
+        }
+
+        return instance;
+    }
+
+    /**
+        @brief Sends an output message to all output listeners.
+        @param level The level of the message
+        @param context The context of the message
+        @param message The output message (may contain '\\n')
+
+        This function splits the message into lines (if it contains '\\n') and
+        sends it to the output listeners. They may ignore the message if it
+        doesn't match their level- and context-masks.
+    */
+    void OutputManager::pushMessage(OutputLevel level, const OutputContextContainer& context, const std::string& message)
+    {
+        std::vector<std::string> lines;
+        vectorize(message, '\n', &lines);
+
+        for (OutputListener* listener : this->listeners_)
+            listener->unfilteredOutput(level, context, lines);
+    }
+
+    /**
+        @brief Adds an output listener to the list of listeners.
+    */
+    void OutputManager::registerListener(OutputListener* listener)
+    {
+        listener->registerListener(this);
+        this->listeners_.push_back(listener);
+        this->updateMasks();
+    }
+
+    /**
+        @brief Removes an output listener from the list of listeners.
+    */
+    void OutputManager::unregisterListener(OutputListener* listener)
+    {
+        listener->unregisterListener(this);
+        for (std::vector<OutputListener*>::iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
+        {
+            if (*it == listener)
+            {
+                this->listeners_.erase(it);
+                break;
+            }
+        }
+        this->updateMasks();
+    }
+
+    /**
+        @brief Updates all three combined level- and context-masks.
+    */
+    void OutputManager::updateMasks()
+    {
+        this->updateCombinedLevelMask();
+        this->updateCombinedAdditionalContextsLevelMask();
+        this->updateCombinedAdditionalContextsMask();
+    }
+
+    /**
+        @brief Updates the combined level mask. The masks of all listeners are ORed to form the combined mask.
+    */
+    void OutputManager::updateCombinedLevelMask()
+    {
+        int mask = 0;
+        for (OutputListener* listener : this->listeners_)
+            mask |= listener->getLevelMask();
+        this->combinedLevelMask_ = static_cast<OutputLevel>(mask);
+    }
+
+    /**
+        @brief Updates the combined additional contexts level mask. The masks of all listeners are ORed to form the combined mask.
+    */
+    void OutputManager::updateCombinedAdditionalContextsLevelMask()
+    {
+        int mask = 0;
+        for (OutputListener* listener : this->listeners_)
+            mask |= listener->getAdditionalContextsLevelMask();
+        this->combinedAdditionalContextsLevelMask_ = static_cast<OutputLevel>(mask);
+    }
+
+    /**
+        @brief Updates the combined additional contexts mask. The masks of all listeners are ORed to form the combined mask.
+    */
+    void OutputManager::updateCombinedAdditionalContextsMask()
+    {
+        this->combinedAdditionalContextsMask_ = 0;
+        for (OutputListener* listener : this->listeners_)
+            this->combinedAdditionalContextsMask_ |= listener->getAdditionalContextsMask();
+    }
+
+    /**
+        @brief Registers a context (or sub-context) and returns the container which identifies the context.
+        @param name The name of the context
+        @param subname The name of the sub-context (or "" if it is not a sub-context)
+
+        If the context doesn't exist, it gets created. Otherwise the existing instance is returned.
+    */
+    const OutputContextContainer& OutputManager::registerContext(const std::string& name, const std::string& subname)
+    {
+        // the full name of a context is a combination of name and subname with "::" in between
+        std::string full_name = name;
+        if (subname != "")
+            full_name += "::" + subname;
+
+        // check if the context already exists (and return it if it does)
+        std::map<std::string, OutputContextContainer>::iterator it_container = this->contextContainers_.find(full_name);
+        if (it_container != this->contextContainers_.end())
+            return it_container->second;
+
+        // create a new context container
+        OutputContextContainer container;
+        container.name = full_name;
+
+        // check if the mask of the main-context already exists
+        std::map<std::string, OutputContextMask>::iterator it_mask = this->contextMasks_.find(name);
+        if (it_mask != this->contextMasks_.end())
+        {
+            // the mask exists, assign it to the container
+            container.mask = it_mask->second;
+        }
+        else
+        {
+            // the mask doesn't exist, create it. It's a binary mask. The n-th main-context is defined by the n-th bit in the mask.
+            container.mask = static_cast<OutputContextMask>(0x1) << this->contextMasks_.size();
+            this->contextMasks_[name] = container.mask;
+
+            if (container.mask == 0)
+                orxout(internal_warning) << "More than " << sizeof(OutputContextMask) * 8 << " output contexts defined. Context '" << name << "' might not get filtered correctly" << endl;
+        }
+
+        // if the context is a sub-context, assign a unique ID.
+        if (subname == "")
+            container.sub_id = context::no_subcontext;
+        else
+            container.sub_id = ++this->subcontextCounter_; // start with 1
+
+        // add the new context to the map and return it
+        return (this->contextContainers_[full_name] = container);
+    }
+
+    /**
+        @brief Static function, shortcut to OutputManager::registerContext().
+        The function is declared in OutputDefinitions.h.
+    */
+    const OutputContextContainer& registerContext(const std::string& name, const std::string& subname)
+    {
+        return OutputManager::getInstance().registerContext(name, subname);
+    }
+
+    /**
+        @brief Returns a human readable string for each output level.
+    */
+    const std::string& OutputManager::getLevelName(OutputLevel level) const
+    {
+        switch (level)
+        {
+            // using static cache variables for speed
+            case level::none:               { static std::string name = "None"; return name; }
+            case level::message:            { static std::string name = "Message"; return name; }
+            case level::debug_output:       { static std::string name = "Debug"; return name; }
+            case level::user_error:         { static std::string name = "Error"; return name; }
+            case level::user_warning:       { static std::string name = "Warning"; return name; }
+            case level::user_status:        { static std::string name = "Status"; return name; }
+            case level::user_info:          { static std::string name = "Info"; return name; }
+            case level::internal_error:     { static std::string name = "Error (internal)"; return name; }
+            case level::internal_warning:   { static std::string name = "Warning (internal)"; return name; }
+            case level::internal_status:    { static std::string name = "Status (internal)"; return name; }
+            case level::internal_info:      { static std::string name = "Info (internal)"; return name; }
+            case level::verbose:            { static std::string name = "Verbose"; return name; }
+            case level::verbose_more:       { static std::string name = "Verbose (more)"; return name; }
+            case level::verbose_ultra:      { static std::string name = "Verbose (ultra)"; return name; }
+            default:                        { static std::string name = ""; return name; }
+        }
+    }
+
+    /**
+        @brief Returns a string containing the name of the level and the context (if any) which
+        can be prepended to an output message if it is written to the console or the log file.
+    */
+    std::string OutputManager::getDefaultPrefix(OutputLevel level, const OutputContextContainer& context) const
+    {
+        // "undefined" context is ignored because it's used implicitly if no explicit context is defined
+        OutputContextMask undefined_mask = context::undefined().mask;
+
+        std::string prefix = this->getLevelName(level) + ": ";
+        if (context.mask != undefined_mask)
+            prefix += "[" + context.name + "] ";
+
+        return prefix;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputManager.h	(revision 11817)
@@ -0,0 +1,148 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the OutputManager class which receives output from orxonox::OutputStream
+    and distributes it to all instances of orxonox::OutputListener.
+*/
+
+#ifndef _OutputManager_H__
+#define _OutputManager_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <vector>
+#include <map>
+#include <memory>
+
+#include "OutputDefinitions.h"
+#include "AdditionalContextListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief OutputManager acts as the center of the output system and is implemented as a singleton.
+
+        All instances of OutputStream (and hence also the orxout() function)
+        send their buffered output to OutputManager. OutputManager then
+        distributes this output to all registered instances of OutputListener.
+
+        For each listener OutputManager checks if it wants to receive output
+        with the given level and context. OutputManager itself also maintains
+        masks that define the accepted levels and concept. They are a
+        combination of the masks of all output listeners. See the description
+        of OutputListener for a more conclusive description of these masks.
+
+        Additionally OutputManager is used to register output contexts.
+    */
+    class _UtilExport OutputManager : public AdditionalContextListener
+    {
+        public:
+            OutputManager();
+            virtual ~OutputManager();
+
+            static OutputManager& getInstance();
+            static OutputManager& getInstanceAndCreateListeners();
+
+            inline MemoryWriter* getMemoryWriter()   { return this->memoryWriterInstance_; }
+            inline ConsoleWriter* getConsoleWriter() { return this->consoleWriterInstance_; }
+            inline LogWriter* getLogWriter()         { return this->logWriterInstance_; }
+
+            virtual void pushMessage(OutputLevel level, const OutputContextContainer& context, const std::string& message);
+
+            virtual void registerListener(OutputListener* listener);
+            virtual void unregisterListener(OutputListener* listener);
+
+            virtual void updatedLevelMask(const OutputListener* listener) override
+                { this->updateCombinedLevelMask(); }
+            virtual void updatedAdditionalContextsLevelMask(const OutputListener* listener) override
+                { this->updateCombinedAdditionalContextsLevelMask(); }
+            virtual void updatedAdditionalContextsMask(const OutputListener* listener) override
+                { this->updateCombinedAdditionalContextsMask(); }
+
+            /**
+                @brief Returns true if at least one of the output listeners will accept output with the given level and context.
+
+                For the sake of performance, output messages with levels or
+                contexts that are not accepted should be ignored or, even
+                better, not generated at all.
+            */
+            inline bool acceptsOutput(OutputLevel level, const OutputContextContainer& context) const
+            {
+                return (this->combinedLevelMask_ & level) ||
+                       ((this->combinedAdditionalContextsLevelMask_ & level) && (this->combinedAdditionalContextsMask_ & context.mask));
+            }
+
+            const OutputContextContainer& registerContext(const std::string& name, const std::string& subname = "");
+
+            const std::string& getLevelName(OutputLevel level) const;
+            std::string getDefaultPrefix(OutputLevel level, const OutputContextContainer& context) const;
+
+            inline const std::vector<OutputListener*>& getListeners() const
+                { return this->listeners_; }
+
+            inline OutputLevel getCombinedLevelMask() const { return this->combinedLevelMask_; }
+            inline OutputLevel getCombinedAdditionalContextsLevelMask() const { return this->combinedAdditionalContextsLevelMask_; }
+            inline OutputContextMask getCombinedAdditionalContextsMask() const { return this->combinedAdditionalContextsMask_; }
+
+        private:
+            // non-copyable:
+            OutputManager(const OutputManager&) = delete;
+            OutputManager& operator=(const OutputManager&) = delete;
+
+            void updateMasks();
+            void updateCombinedLevelMask();
+            void updateCombinedAdditionalContextsLevelMask();
+            void updateCombinedAdditionalContextsMask();
+
+            std::vector<OutputListener*> listeners_;                            ///< List of all registered output listeners
+
+            OutputLevel       combinedLevelMask_;                               ///< The combined mask of accepted levels of all listeners
+            OutputLevel       combinedAdditionalContextsLevelMask_;             ///< The combined mask of accepted additional contexts levels of all listeners
+            OutputContextMask combinedAdditionalContextsMask_;                  ///< The combined mask of accepted additional contexts of all listeners
+
+            std::map<std::string, OutputContextMask> contextMasks_;             ///< Contains all main-contexts and their masks
+            std::map<std::string, OutputContextContainer> contextContainers_;   ///< Contains all contexts including sub-contexts and their containers
+            OutputContextSubID subcontextCounter_;                              ///< Counts the number of sub-contexts (and generates their IDs)
+
+            bool isInitialized_;                                                ///< Becomes true once the following instances were created
+            MemoryWriter*  memoryWriterInstance_;                               ///< The main instance of MemoryWriter, managed by OutputManager
+            ConsoleWriter* consoleWriterInstance_;                              ///< The main instance of ConsoleWriter, managed by OutputManager
+            LogWriter*     logWriterInstance_;                                  ///< The main instance of LogWriter, managed by OutputManager
+
+        public:
+            struct _UtilExport Testing
+            {
+                static std::shared_ptr<OutputManager>& getInstancePointer();
+            };
+    };
+}
+
+#endif /* _OutputManager_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputStream.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputStream.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputStream.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the non-generic functions of the OutputStream class.
+*/
+
+#include "OutputStream.h"
+
+#include "OutputManager.h"
+
+namespace orxonox
+{
+    /**
+        @brief Default constructor, initializes level and context with default values.
+    */
+    OutputStream::OutputStream() : OutputStream(level::debug_output, context::undefined())
+    {
+    }
+
+    /**
+        @brief Constructor, initializes level and context with the provided values.
+    */
+    OutputStream::OutputStream(OutputLevel level, const OutputContextContainer& context)
+    {
+        this->setOutputAttributes(level, context);
+    }
+
+    /**
+        @brief Destructor, sends remaining output to OutputManager (if any).
+    */
+    OutputStream::~OutputStream()
+    {
+        if (this->str() != "")
+            *this << " [missing endl]" << std::endl;
+    }
+
+    /**
+        @brief Sends the buffered message to OutputManager together with the stored level and context.
+        Additionally empties the buffer.
+    */
+    void OutputStream::sendMessage()
+    {
+        OutputManager::getInstanceAndCreateListeners().pushMessage(this->level_, *this->context_, this->str());
+        this->str("");
+    }
+
+    /**
+        @brief Defines level and context of the following output.
+        Also sets the bAcceptsOutput_ flag according to the masks defined in OutputManager.
+    */
+    void OutputStream::setOutputAttributes(OutputLevel level, const OutputContextContainer& context)
+    {
+        this->level_ = level;
+        this->context_ = &context;
+
+        this->bAcceptsOutput_ = OutputManager::getInstanceAndCreateListeners().acceptsOutput(level, context);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/OutputStream.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/OutputStream.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/OutputStream.h	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the OutputStream class which is used to send output to orxonox::OutputManager.
+*/
+
+#ifndef _OutputStream_H__
+#define _OutputStream_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <sstream>
+
+#include "OutputDefinitions.h"
+
+namespace orxonox
+{
+    /**
+        @brief This class is used to buffer output and send it to OutputManager whenever std::endl is passed to it.
+
+        OutputStream inherits from std::ostringstream and acts like std::cout.
+        This means you can use the << operator to write output to the stream.
+        This class is used by the orxout() function.
+
+        @attention
+        You must end an output message with std::endl, otherwise the message
+        won't be flushed. '\\n' only adds a new line to the message.
+
+        The following code samples are all equivalent:
+        @code
+        OutputStream stream;
+        stream.setOutputAttributes(user_info, context::example());
+        stream << "Hello World" << endl;
+        @endcode
+
+        @code
+        OutputStream stream(user_info, context::example());
+        stream << "Hello World" << endl;
+        @endcode
+
+        @code
+        orxout(user_info, context::example) << "Hello World" << endl;
+        @endcode
+    */
+    class OutputStream : public std::ostringstream
+    {
+        typedef std::ostream& (*EndlType)(std::ostream&);
+
+        public:
+            _UtilExport OutputStream();
+            _UtilExport OutputStream(OutputLevel level, const OutputContextContainer& context);
+            _UtilExport ~OutputStream();
+
+            void _UtilExport setOutputAttributes(OutputLevel level, const OutputContextContainer& context);
+
+            /// @brief Generic << operator which adds output to the stream.
+            template <class T>
+            inline OutputStream& operator<<(const T& val) { return this->output(val); }
+            /// @brief Sends a manipulator to the output stream.
+            inline OutputStream& operator<<(std::ios_base& (*manipulator)(std::ios_base&)) { return this->output(manipulator); }
+            /// @brief Sends a manipulator to the output stream.
+            inline OutputStream& operator<<(std::ios&      (*manipulator)(std::ios&))      { return this->output(manipulator); }
+            /// @brief Sends a manipulator to the output stream and flushes the message if the manipulator is std::endl.
+            inline OutputStream& operator<<(std::ostream&  (*manipulator)(std::ostream&))
+            {
+                if (this->bAcceptsOutput_)
+                {
+                    if (manipulator == static_cast<EndlType>(std::endl))
+                        this->sendMessage(); // send the message to OutputManager
+                    else
+                        return this->output(manipulator); // apply the manipulator
+                }
+                return *this;
+            }
+
+            inline const OutputLevel getOutputLevel() const { return this->level_; }
+            inline const OutputContextContainer* getOutputContext() const { return this->context_; }
+            inline bool acceptsOutput() const { return this->bAcceptsOutput_; }
+
+        private:
+            /// @brief Generic function to add values to the output stream, using the inherited << operator from std::ostringstream.
+            template <class T>
+            inline OutputStream& output(const T& val)
+            {
+                if (this->bAcceptsOutput_)
+                    static_cast<std::ostringstream&>(*this) << val;
+                return *this;
+            }
+
+            void _UtilExport sendMessage();
+
+            OutputLevel level_;                     ///< The output level of the current message
+            const OutputContextContainer* context_; ///< The output context of the current message
+            bool bAcceptsOutput_;                   ///< After defining level and context of the following message, this flag is set according to the masks defined in OutputManager. If it is false, the OutputStream will throw away every output sent using the << operator.
+    };
+}
+
+#endif /* _OutputStream_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/SubcontextOutputListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/SubcontextOutputListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/SubcontextOutputListener.cc	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Implementation of the SubcontextOutputListener interface.
+*/
+
+#include "SubcontextOutputListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor, initializes the context masks.
+    */
+    SubcontextOutputListener::SubcontextOutputListener(bool bRegister) : OutputListener(bRegister)
+    {
+        this->subcontextsCheckMask_ = context::none;
+        this->subcontextsNoCheckMask_ = context::none;
+    }
+
+    /**
+        @brief Destructor.
+    */
+    SubcontextOutputListener::~SubcontextOutputListener()
+    {
+    }
+
+    /**
+        @brief Overwritten implementation of the function defined by OutputListener.
+
+        Contexts defined with this function are accepted independent of the
+        sub-context. The "final" mask of additional contexts is defined by the
+        combination of this mask and the masks of all accepted sub-contexts.
+    */
+    void SubcontextOutputListener::setAdditionalContextsMask(OutputContextMask mask)
+    {
+        this->subcontextsNoCheckMask_ = mask;
+
+        OutputListener::setAdditionalContextsMask(this->subcontextsCheckMask_ | this->subcontextsNoCheckMask_);
+    }
+
+    /**
+        @brief Defines the set of accepted sub-contexts.
+
+        The masks of sub-contexts in this set are added to the mask of
+        additional contexts, but output is only accepted if the exact
+        sub-context exists in this set.
+    */
+    void SubcontextOutputListener::setAdditionalSubcontexts(const std::set<const OutputContextContainer*>& subcontexts)
+    {
+        this->subcontextsCheckMask_ = context::none;
+        this->subcontexts_.clear();
+
+        // compose the mask of subcontexts and build the set of sub-context-IDs
+        for (const OutputContextContainer* subcontext : subcontexts)
+        {
+            this->subcontextsCheckMask_ |= subcontext->mask;
+            this->subcontexts_.insert(subcontext->sub_id);
+        }
+
+        OutputListener::setAdditionalContextsMask(this->subcontextsCheckMask_ | this->subcontextsNoCheckMask_);
+    }
+
+    /**
+        @brief Returns true if this listener accepts output of the given level and context, based on the levels and contexts masks, as well as the set of accepted sub-contexts.
+    */
+    bool SubcontextOutputListener::acceptsOutput(OutputLevel level, const OutputContextContainer& context) const
+    {
+        // check if the output level is accepted by the level mask (independent of the context)
+        if (this->getLevelMask() & level)
+            return true;
+
+        // check if the output level is accepted by the additional contexts level mask
+        if (this->getAdditionalContextsLevelMask() & level)
+        {
+            // check if the output context is accepted by the "no check" mask
+            if (this->subcontextsNoCheckMask_ & context.mask)
+                return true;
+
+            // check if the output context is accepted by the "check" mask
+            if (this->subcontextsCheckMask_ & context.mask)
+            {
+                // check if the output's subcontext is in the set of accepted sub-context
+                if (this->subcontexts_.find(context.sub_id) != this->subcontexts_.end())
+                    return true;
+            }
+        }
+
+        // otherwise we don't accept the output
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/libraries/util/output/SubcontextOutputListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/output/SubcontextOutputListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/output/SubcontextOutputListener.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @ingroup Output
+    @brief Declaration of the SubcontextOutputListener interface which adds the ability to filter sub-contexts to OutputListener.
+*/
+
+#ifndef _SubcontextOutputListener_H__
+#define _SubcontextOutputListener_H__
+
+#include "util/UtilPrereqs.h"
+
+#include <set>
+
+#include "OutputListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief This class extends the basic OutputListener interface and adds the ability to filter sub-contexts.
+
+        Defining additional contexts with setAdditionalContextsMask() enables
+        all sub-contexts of these additional contexts. To accept only some
+        particular sub-contexts, setAdditionalSubcontexts() has to be used.
+        Note that this requires a set, since a mask is not possible with
+        sub-contexts.
+
+        The "final" context mask which will be seen by OutputManager is the
+        combination of all regular contexts plus the masks of all sub-contexts.
+
+        @remark
+        It would have been possible to implement filtering of sub-contexts
+        directly in OutputListener and even to make OutputManager aware of
+        sub-contexts. This would reduce the amount of unnecessarily generated
+        output, but also increase the complexity of the checks whether some
+        output is needed.
+        On the other hand, filtering of sub-contexts makes the whole concept
+        more complicated, as it adds another mask and a set. So to keep it
+        clean and simple I figured it's best to put sub-context filtering into
+        a seaparate class.
+    */
+    class _UtilExport SubcontextOutputListener : public OutputListener
+    {
+        public:
+            SubcontextOutputListener(bool bRegister = true);
+            virtual ~SubcontextOutputListener();
+
+            virtual void setAdditionalContextsMask(OutputContextMask mask) override;
+            void setAdditionalSubcontexts(const std::set<const OutputContextContainer*>& subcontexts);
+
+            virtual bool acceptsOutput(OutputLevel level, const OutputContextContainer& context) const override;
+
+            inline const std::set<OutputContextSubID>& getSubcontexts() const
+                { return this->subcontexts_; }
+
+        private:
+            OutputContextMask subcontextsCheckMask_;    ///< All contexts defined by this mask need to be checked whether they are accepted by the set of sub-contexts
+            OutputContextMask subcontextsNoCheckMask_;  ///< All contexts defined by this mask don't need to be checked since we accept all sub-contexts
+            std::set<OutputContextSubID> subcontexts_;  ///< The set of accepted sub-contexts
+    };
+}
+
+#endif /* _SubcontextOutputListener_H__ */
Index: /code/branches/RacingBots_FS18/src/libraries/util/tribool.h
===================================================================
--- /code/branches/RacingBots_FS18/src/libraries/util/tribool.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/libraries/util/tribool.h	(revision 11817)
@@ -0,0 +1,139 @@
+// Three-state boolean logic library
+
+// Copyright Douglas Gregor 2002-2004. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Modifications by Orxonox to shape the third state into 'dontcare' instead
+// of 'indeterminate'. The difference is that 'dontcare' is actually a value
+// so that (dontcare == dontcare).
+// Also removed all logic operators except for == and !=
+// Added C++11 constexpr
+
+
+// For more information, see http://www.boost.org
+#ifndef ORXONOX_TRIBOOL_H
+#define ORXONOX_TRIBOOL_H
+
+namespace orxonox {
+
+/**
+ * INTERNAL ONLY
+ * The type of the 'dontcare' keyword.
+ */
+struct dontcare_keyword_t {};
+
+/**
+ * \brief Keyword for the dontcare tribool value
+ */
+constexpr dontcare_keyword_t dontcare = dontcare_keyword_t();
+
+/**
+ * \brief A 3-state boolean type.
+ *
+ * 3-state boolean values are either true, false, or
+ * dontcare.
+ */
+class tribool
+{
+public:
+  /**
+   * Construct a new 3-state boolean value with the value 'false'.
+   *
+   * \throws nothrow
+   */
+  constexpr tribool() : value(false_value) {}
+
+  /**
+   * Construct a new 3-state boolean value with the given boolean
+   * value, which may be \c true or \c false.
+   *
+   * \throws nothrow
+   */
+  constexpr tribool(bool value) : value(value? true_value : false_value) {}
+
+  /**
+   * Construct a new 3-state boolean value with an dontcare value.
+   *
+   * \throws nothrow
+   */
+  constexpr tribool(dontcare_keyword_t) : value(dontcare_value) {}
+
+  /**
+   * \brief Compare tribools for equality
+   *
+   * \returns the result of comparing two tribool values.
+   * \throws nothrow
+   */
+  constexpr bool operator==(tribool y) const
+  {
+    return (this->value == y.value);
+  }
+
+  /**
+   * \overload
+   */
+  constexpr bool operator==(bool y) const { return (*this) == tribool(y); }
+
+  /**
+   * \overload
+   */
+  constexpr bool operator==(dontcare_keyword_t) const
+  { return tribool(dontcare) == (*this); }
+
+  /**
+   * \brief Compare tribools for inequality
+   *
+   * \returns the result of comparing two tribool values for inequality.
+   * \throws nothrow
+   */
+  constexpr bool operator!=(tribool y) const
+  {
+    return !((*this) == y);
+  }
+
+  /**
+   * \overload
+   */
+  constexpr bool operator!=(bool y) const { return (*this) != tribool(y); }
+
+  /**
+   * \overload
+   */
+  constexpr bool operator!=(dontcare_keyword_t) const
+  { return (*this) != tribool(dontcare); }
+
+  /**
+   * The actual stored value in this 3-state boolean, which may be false, true,
+   * or dontcare.
+   */
+  enum value_t { false_value, true_value, dontcare_value } value;
+};
+
+/**
+ * \overload
+ */
+constexpr bool operator==(bool x, tribool y) { return tribool(x) == y; }
+
+/**
+ * \overload
+ */
+constexpr bool operator==(dontcare_keyword_t, tribool x)
+{ return tribool(dontcare) == x; }
+
+/**
+ * \overload
+ */
+constexpr bool operator!=(bool x, tribool y) { return tribool(x) != y; }
+
+/**
+ * \overload
+ */
+constexpr bool operator!=(dontcare_keyword_t, tribool x)
+{ return tribool(dontcare) != x; }
+
+} // end namespace orxonox
+
+#endif // ORXONOX_TRIBOOL_H
+
Index: /code/branches/RacingBots_FS18/src/modules/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,50 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+INCLUDE_DIRECTORIES(
+  ${CMAKE_SOURCE_DIR}/src/libraries
+  ${CMAKE_SOURCE_DIR}/src/orxonox
+  ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+################ Sub Directories ################
+
+ADD_SUBDIRECTORY(asteroidmining)
+ADD_SUBDIRECTORY(dialog)
+ADD_SUBDIRECTORY(designtools)
+ADD_SUBDIRECTORY(gametypes)
+ADD_SUBDIRECTORY(notifications)
+ADD_SUBDIRECTORY(objects)
+ADD_SUBDIRECTORY(overlays)
+ADD_SUBDIRECTORY(pickup)
+ADD_SUBDIRECTORY(pong)
+ADD_SUBDIRECTORY(portals)
+ADD_SUBDIRECTORY(questsystem)
+ADD_SUBDIRECTORY(tetris)
+ADD_SUBDIRECTORY(weapons)
+ADD_SUBDIRECTORY(docking)
+ADD_SUBDIRECTORY(towerdefense)
+ADD_SUBDIRECTORY(invader)
+ADD_SUBDIRECTORY(jump)
+ADD_SUBDIRECTORY(mini4dgame)
+ADD_SUBDIRECTORY(dodgerace)
+ADD_SUBDIRECTORY(hover)
+ADD_SUBDIRECTORY(superorxobros)
+ADD_SUBDIRECTORY(asteroids2D)
+ADD_SUBDIRECTORY(flappyorx)
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMinable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMinable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMinable.cc	(revision 11817)
@@ -0,0 +1,367 @@
+
+ /*   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      remartin
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/*
+
+    @file
+    @author remartin
+    @brief An asteroid which can be destroyed. Some smaller asteroids are created and a pickup spawns. 
+
+HANDBUCH:
+o Die Collision Shape kann nur im Konstruktor hinzugefügt werden. Die XML-Argumente werden aber erst nach dem Konstruktor gesetzt. 
+  Darum wird hier beim ersten Aufruf der tick()-Methode via putStuff() ein komplett neuer Asteroid generiert und der alte zerstört. 
+o im Level-File includes/pickups.oxi importieren. 
+
+OFFEN/Weiterentwicklung: 
+o @TODO Add resource pickups. 
+--> data_extern/images/effects: PNG's für die Pickups
+--> https://www.orxonox.net/jenkins/view/Management/job/orxonox_doxygen_trunk/javadoc/group___pickup.html
+
+o Density doesn't add up to 1...
+o Does collision damage work properly
+o Add sound effect (crunching etc. ) (No sound in space...)
+o Explosion parts
+
+ANDERORTS VERÄNDERTE SACHEN: 
+Pickup-Zeug: 
+o PickupSpawner.h: Zugriffsrechte setPickupTemplateName() und setMaxSpawnedItems()
+o PickupSpawner.h: In Tick() zwei Testbedingungen eingefügt.
+o Pawn.h: Attribut acceptsPickups_ inklusive get/set. 
+
+ERLEGTE FEHLER:
+o Grössenabhängige Collision Shape -> putStuff-Methode, Werte noch nicht durchgesickert. 
+o setHealth: maxHealth() des pawns setzen! 
+o Asteroiden fressen Pickups: Argument in Pawn, Test darauf in Tick() von PickupSpawner. 
+o i++ einfach ganz verhindern, ++i stattdessen. 
+o Velocity didn-t get passed properly through the 2nd constructor. Used get/set instead. 
+o Rand() geht bis zu riesigen Nummern! rnd() ist zwischen 0 und 1
+
+NOTIZEN:
+o SUPER
+o Warnungsverhinderung anderswo: (void)pickedUp; // To avoid compiler warning.
+o friend class Pickupable;
+
+
+
+*/
+
+#include "AsteroidMinable.h"
+
+#include <algorithm>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "util/Math.h"
+
+#include "pickup/PickupSpawner.h"
+#include "pickup/Pickup.h"
+
+#include "objects/collisionshapes/SphereCollisionShape.h"
+#include "graphics/Model.h"
+
+namespace orxonox{
+
+    RegisterClass(AsteroidMinable);
+
+    // @brief Standard constructor
+    AsteroidMinable::AsteroidMinable(Context* context) : Pawn(context){
+
+        RegisterObject(AsteroidMinable);
+
+        // Default Values:
+        this->size = 1;
+        this->dropStuff = true; 
+        this->generateSmaller = true; 
+        this->acceptsPickups_ = false; 
+
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+        this->enableCollisionCallback();
+
+        // Old from Pawn
+        this->registerVariables();
+
+        this->initialised = false;
+    }
+
+    AsteroidMinable::~AsteroidMinable(){
+
+    }
+
+    void AsteroidMinable::setSize(float s)
+    {
+        this->size = s;
+        this->health_ = 15*size;
+        this->maxHealth_ = this->health_;
+    }
+
+    // @brief Helper method.
+    void AsteroidMinable::putStuff(){
+
+        // The radar is able to detect whether an asteroid contains resources....
+        if(dropStuff){
+            this->setRadarObjectColour(ColourValue(1.0f, 1.0f, 0.0f, 1.0f));
+            this->setRadarObjectShape(RadarViewable::Shape::Dot);
+        }else{
+            // Somehow remove from radar? (all pawns get registered automatically... )
+            this->setRadarObjectColour(ColourValue(0.663f, 0.663f, 0.663f, 1.0f));
+            this->setRadarObjectShape(RadarViewable::Shape::Dot);
+        }
+
+        // Add Model, random one of the 6 shapes
+        Model* hull = new Model(this->getContext());
+        hull->setMeshSource("ast" + multi_cast<std::string>(1 + (int)rnd(0, 6)) + ".mesh");
+        hull->setScale(this->size);
+        this->attach(hull);
+
+        // Collision shape
+        SphereCollisionShape* cs = new SphereCollisionShape(this->getContext());
+        cs->setRadius((this->size)*2); //OFFEN: Feinabstimmung der Radien. 
+        this->attachCollisionShape(cs); 
+
+        this->initialised=true; 
+    }
+
+    void AsteroidMinable::XMLPort(Element& xmlelement, XMLPort::Mode mode){
+
+        SUPER(AsteroidMinable, XMLPort, xmlelement, mode); 
+
+        XMLPortParam(AsteroidMinable, "size", setSize, getSize, xmlelement, mode);
+        XMLPortParam(AsteroidMinable, "generateSmaller", setShattering, doesShatter, xmlelement, mode);
+        XMLPortParam(AsteroidMinable, "dropStuff", setDropStuff, doesDropStuff, xmlelement, mode);
+
+    }
+
+    void AsteroidMinable::registerVariables(){
+
+        registerVariable(this->size, VariableDirection::ToClient);
+        registerVariable(this->generateSmaller, VariableDirection::ToClient);
+        registerVariable(this->dropStuff, VariableDirection::ToClient); 
+        registerVariable(this->initialised, VariableDirection::ToClient);
+
+    }
+
+    void AsteroidMinable::tick(float dt){
+
+        if(!(this->initialised)){this->putStuff();} 
+
+        if(this->health_ <=0){this->death();}
+
+    }
+
+    void AsteroidMinable::death(){ // @brief Überschreibt die Methode in Pawn
+
+        // just copied that from somewhere else. 
+        this->bAlive_ = false;
+        this->destroyLater();
+        this->setDestroyWhenPlayerLeft(false);
+        // pawn -> addExplosionPart
+        // this->goWithStyle();
+
+
+        // Pickups which can be harvested. It's munition at the moment, could be changed/extended. 
+        if(dropStuff){
+            PickupSpawner* thingy = new PickupSpawner(this->getContext());
+
+            std::string tname;
+            if(this->size <= 5){
+                tname = "smallmunitionpickup";
+            }else if(this->size <= 20){
+                tname = "mediummunitionpickup";
+            }else{
+                tname = "hugemunitionpickup";
+            }
+            thingy->setPickupTemplateName(tname);
+            thingy->setPosition(this->getPosition());
+            thingy->setMaxSpawnedItems(1); // Would be default anyways
+            thingy->setRespawnTime(0.2f);
+        }
+
+        // Smaller Parts = 'Children'
+        if(this->generateSmaller){this->spawnChildren();}
+
+    }
+
+// @brief If the option generateSmaller is enabled, individual fragments are added with this method. 
+    void AsteroidMinable::spawnChildren(){
+
+    if (this->size <=1){return;} // Absicherung trivialer Fall
+
+    float massRem = (this->size-1); //some mass is lost
+    int num = (int)roundf(rnd(massRem-1)) + 1; // random number of children, at least one
+    if(num > 10){num = 10;} // no max function in C? 
+    std::vector<float> masses(num); // Masses of the asteroids
+    // orxout() << "SpawnChildren(): Passed basic stuff. num = " << num << "; massRem(total) = "<< massRem << endl;
+    massRem = massRem-num; // mass must be at least one, add later.  
+
+    // Randomnised spawning points for the new asteroids
+    std::vector<float> phi(num);
+    std::vector<float> theta(num);
+
+    // Discusting C stuff -> use that to initialise dynamic array values to 0. 
+    for(int twat = 0; twat<num; ++twat)
+    {
+        masses[twat] = 0.0f;
+        phi[twat] = 0.0f;
+        theta[twat] = 0.0f;
+    }
+
+    float piG = 3.1415927410125732421875; //pi; // Math.pi ist statisch oder so. 
+    float d_p = 2*piG/num;
+    float d_t = piG/num;
+    float p = d_p/2.0f;
+    float t = d_t/2.0f;
+    // float phiOffset = rnd()*2*pi; // Added everywhere to become independent of the coordinate system?
+    // float thetaOffset = rnd()*pi;
+    float rScaling; // scale radius to prevent asteroids from touching. (distance=AsteroidRadius/tan(sector/2))
+
+    if(num == 1 ){
+        rScaling = 1; // avoid tan(90). Unused. 
+    }else{
+
+        rScaling = tan(t); 
+
+        int pos; // insert at random position (linear probing) in array, to get some randomness.  
+        for(int it = 0; it<num; ++it){
+
+            pos = mod((int)(rnd((float)num)),num);
+            while(phi[pos] != 0.0){// find empty spot in array
+                pos = (int)mod(++pos, num);
+            }
+            phi[pos] = p + it*d_p;// set angle there
+
+            pos = mod((int)(rnd((float)num)),num);
+            while(theta[pos] != 0.0){
+                pos = (int)mod(++pos, num);
+            }
+            theta[pos] = t + it*d_t;
+        }
+    }
+
+    //orxout() << "SpawnChildren(): Phi: "; printArrayString(phi);
+    //orxout() << "SpawnChildren(): Theta: "; printArrayString(theta);
+    //orxout() << "SpawnChildren(): Passed angle stuff. " << endl;
+
+    // Triangular, discrete probability "density" with max at the average value massRem/num. 50% chance to be below that. 
+    if(massRem>0){
+        int c = (int)massRem;
+        std::vector<float> probDensity(c);
+
+        int a = (int)roundf(massRem/num);
+        int b = c-a;
+        
+        int z = 0;
+        float dProbA = 1.0f/(a*a + 3.0f*a + 2.0f); // one 'probability unit' for discrete ramp function. Gauss stuff.
+        for(z = 0; z<a; ++z){probDensity[z] = (z+1)*dProbA; } // rising part
+
+        float dProbB = 1.0f/(b*b +3.0f*b + 2.0f);
+        for(z = 0; z<b; ++z){probDensity[c-1-z] = (z+1)*dProbB;} // falling part
+    
+        // // Just for testing:
+        // float sum = 0.0;
+        // for(int globi = 0; globi<c; ++globi){
+        //     orxout() << "pDensity at [" << globi << "] is: " << probDensity[globi] << endl;
+        //     sum = sum+ probDensity[globi];
+        // }
+        // orxout() << "Sum of densities should b 1, it is: " << sum << endl;
+
+        // Distributing the mass to individual asteroids
+        int result; 
+        float rVal; // between 0 and 1
+        float probSum; // summing up until rval is reached. 
+        for(int trav = 0; trav<num; ++trav){
+            result = 0;
+            rVal = rnd(); 
+            probSum = probDensity[0]; 
+
+            while(rVal>probSum && result<massRem){// Not yet found && there-s smth left to distribute (Incrementing inside!)
+                if(result<(massRem-2)){probSum = probSum + probDensity[result+1];} // avoid logical/acess error
+                ++result;
+            }
+
+            masses[trav] = 1.0f + result; // Fragments have mass of at least one.
+            massRem = massRem-result;
+
+        }
+    }else{
+        for(int schnaegg = 0; schnaegg<num; ++schnaegg){masses[schnaegg] = 1;}
+    }
+
+    // orxout() << "SpawnChildren(): Masses: "; printArrayString(masses);
+    // orxout() << "SpawnChildren(): Passed mass stuff. " << endl;
+
+    // Creating the 'chlidren':
+    for(int fisch = 0; fisch<num; ++fisch){
+
+        Vector3 pos = Vector3::ZERO; // Position offset
+        if(num > 1){// not required if there-s just one child
+            float r = masses[fisch]/rScaling;
+            pos = Vector3(r*sin(theta[fisch])*cos(phi[fisch]), r*sin(theta[fisch])*sin(phi[fisch]), r*cos(theta[fisch])); // convert spheric coordinates to vector
+        }
+        
+        AsteroidMinable* child = new AsteroidMinable(this->getContext());
+        child->setSize(masses[fisch]);
+        child->setPosition(this->getPosition() + pos);
+        child->setVelocity(this->getVelocity());
+        child->setDropStuff(this->dropStuff);
+    }
+    // orxout() << "Leaving spawnChildren() method. " << endl;
+}
+
+// @brief overloading that to prevent asteroids from taking damage from each other (domino effect etc. ) 
+    void AsteroidMinable::hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage){
+
+        // orxout() << "AsteroidMining::Hit(Variante 1) Dings aufgerufen. " << endl; 
+        if(orxonox_cast<AsteroidMinable*>(originator) || orxonox_cast<Pickup*>(originator)){return;}
+        this->damage(damage, healthdamage, shielddamage, originator, cs);
+        this->setVelocity(this->getVelocity() + force);
+
+        // if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator))// && (!this->getController() || !this->getController()->getGodMode()) )
+        // {
+        //     this->damage(damage, healthdamage, shielddamage, originator, cs);
+        //     this->setVelocity(this->getVelocity() + force);
+        // }
+    }
+
+// @brief overloading that to prevent asteroids from taking damage from each other (domino effect etc. ) 
+    void AsteroidMinable::hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage){
+
+        //orxout() << "AsteroidMining::Hit(Variante 2) Dings aufgerufen. " << endl;
+        if(orxonox_cast<AsteroidMinable*>(originator) || orxonox_cast<Pickup*>(originator)){return;}
+        this->damage(damage, healthdamage, shielddamage, originator, cs);
+
+        // if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator))// && (!this->getController() || !this->getController()->getGodMode()) )
+        // {
+        //     this->damage(damage, healthdamage, shielddamage, originator, cs);
+
+        //     //if ( this->getController() )
+        //     //    this->getController()->hit(originator, contactpoint, damage); // changed to damage, why shielddamage?
+        // }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMinable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMinable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMinable.h	(revision 11817)
@@ -0,0 +1,129 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      remartin
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+/**
+
+    @file
+    @author remartin
+    @brief An asteroid which can be destroyed. Some smaller asteroids are created and a pickup spawns. 
+
+HANDBUCH:
+o Die Collision Shape kann nur im Konstruktor hinzugefügt werden. Die XML-Argumente werden aber erst nach dem Konstruktor gesetzt. 
+  Darum wird hier beim ersten Aufruf der tick()-Methode via putStuff() ein komplett neuer Asteroid generiert und der alte zerstört. 
+o im Level-File includes/pickups.oxi importieren. 
+
+OFFEN/Weiterentwicklung: 
+o @TODO Add resource pickups. 
+--> data_extern/images/effects: PNG's für die Pickups
+--> https://www.orxonox.net/jenkins/view/Management/job/orxonox_doxygen_trunk/javadoc/group___pickup.html
+
+o Density doesn't add up to 1...
+o Does collision damage work properly
+o Add sound effect (crunching etc. ) (No sound in space...)
+o Explosion parts
+
+ANDERORTS VERÄNDERTE SACHEN: 
+Pickup-Zeug: 
+o Pickup.h: createSpawner() neu public statt private
+o PickupSpawner.h: Zugriffsrechte setPickupTemplateName() und setMaxSpawnedItems()
+o PickupSpawner.h: In Tick() zwei Testbedingungen eingefügt.
+o Pawn.h: Attribut acceptsPickups_ inklusive get/set. 
+
+ERLEGTE FEHLER:
+o Grössenabhängige Collision Shape -> putStuff-Methode, Werte noch nicht durchgesickert. 
+o setHealth: maxHealth() des pawns setzen! 
+o Asteroiden fressen Pickups: Argument in Pawn, Test darauf in Tick() von PickupSpawner. 
+o i++ einfach ganz verhindern, ++i stattdessen. 
+o Velocity didn-t get passed properly through the 2nd constructor. Used get/set instead. 
+o Rand() geht bis zu riesigen Nummern! rnd() ist zwischen 0 und 1
+
+NOTIZEN:
+o SUPER
+o Warnungsverhinderung anderswo: (void)pickedUp; // To avoid compiler warning.
+o friend class Pickupable;
+
+*/
+
+#ifndef _AsteroidMinable_H__
+#define _AsteroidMinable_H__
+
+#include "AsteroidMiningPrereqs.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox{
+
+
+    class _AsteroidMiningExport AsteroidMinable : public Pawn
+    {
+        public:
+            AsteroidMinable(Context* context);
+            virtual ~AsteroidMinable();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void tick(float dt) override;
+
+            // @brief overloading that to prevent asteroids from taking damage from each other (domino effect etc. ) 
+            virtual void hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
+            virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
+
+            void setSize(float s);
+            inline float getSize(){return this->size;}
+
+            inline void setShattering(bool b){this->generateSmaller = b;}
+            inline bool doesShatter(){return this->generateSmaller;}
+
+            inline void setDropStuff(bool b){this->dropStuff = b;}
+            inline bool doesDropStuff(){return this->dropStuff;}
+
+        protected:
+
+            float size; //!< Implies health and type of dropped pickups
+            bool generateSmaller; //!< Whether this asteroid leaves fragments
+            bool dropStuff; //!< Whether this asteroid yields valuable stuff
+
+            // @brief Überschreibt die Methode in Pawn
+            virtual void death(); 
+
+        private:
+
+            bool initialised; //!< Used in relation to the constructor detour described above 
+
+            void registerVariables();
+
+            // @brief Helper method. 
+            virtual void putStuff();
+
+            // @brief If the option generateSmaller is enabled, individual fragments are added with this method. 
+            virtual void spawnChildren();
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _AsteroidMinable_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMiningPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMiningPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/AsteroidMiningPrereqs.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the AsteroidMining module
+*/
+
+#ifndef _AsteroidMiningPrereqs_H__
+#define _AsteroidMiningPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ASTEROIDMINING_STATIC_BUILD)
+#  ifdef ASTEROIDMINING_SHARED_BUILD
+#    define _AsteroidMiningExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _AsteroidMiningExport
+#    else
+#      define _AsteroidMiningExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _AsteroidMiningPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _AsteroidMiningExport  __attribute__ ((visibility("default")))
+#  define _AsteroidMiningPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _AsteroidMiningExport
+#  define _AsteroidMiningPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class AsteroidMinable;
+    class SpicedAsteroidBelt;
+    class SpicedAsteroidField;
+}
+
+#endif /* _AsteroidMiningPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,19 @@
+SET_SOURCE_FILES(PICKUP_SRC_FILES
+  AsteroidMinable.cc
+  SpicedAsteroidField.cc
+  SpicedAsteroidBelt.cc
+)
+
+ORXONOX_ADD_LIBRARY(asteroidmining
+  MODULE
+  FIND_HEADER_FILES
+  TOLUA_FILES
+
+  PCH_FILE
+
+  LINK_LIBRARIES
+    orxonox
+    objects
+    pickup
+  SOURCE_FILES ${PICKUP_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidBelt.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidBelt.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidBelt.cc	(revision 11817)
@@ -0,0 +1,150 @@
+
+ /*   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      remartin
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+
+    @file 
+    @author remartin
+    @brief Asteroid belt with lots of parameters. Derived from asteroidField.lua
+
+    Generates a ring of asteroids by calling SpicedAsteroidField multiple times. 
+    It's in the xy-plane at default, orientation can be changed with tiltAt 
+    (angle where it gets elevated/lowered the most) and TiltBy (angle at z-axis). 
+    This doesn't work very well and could probably implemented differently with 
+    relative coordinates (attach etc, stuff in WorldEntity). 
+
+    It is required to wait until all XML-arguments are set. That's why the actual 
+    generation happens when tick() gets called for the first time. 
+    
+*/
+
+
+#include "SpicedAsteroidBelt.h"
+#include "SpicedAsteroidField.h"
+
+#include <algorithm>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Math.h"
+
+namespace orxonox{
+
+    RegisterClass(SpicedAsteroidBelt);
+
+    SpicedAsteroidBelt::SpicedAsteroidBelt(Context* context) : BaseObject(context) {
+
+        RegisterObject(SpicedAsteroidBelt);
+
+        // Default Values:
+        this->count = 250; 
+        this->position = Vector3(0,0,0);
+        this->segments = 30;
+        this->minSize = 1;
+        this->maxSize = 50;
+        this->radius0 = 7190;
+        this->radius1 = 7800;
+
+        this->mDensity = 0.3;
+        this->foggy = true;
+        this->fogDensity = 0.5;
+
+        this->tiltAt = 0.0; 
+        this->tiltBy = 0.0;  
+
+    }
+
+    SpicedAsteroidBelt::~SpicedAsteroidBelt(){
+
+    }
+
+    void SpicedAsteroidBelt::create(){
+
+        float myPi = math::pi;
+        float width = fabs(this->radius1 - this->radius0);
+        float radius = (this->radius1 + this->radius0) / 2.0f;
+        int segmentCount = (int)roundf(this->count / this->segments);
+
+        float dPhi = (2 * myPi) / this->segments;
+        float dTheta = 4.0f*this->tiltBy/this->segments;
+        float sepp = -this->tiltAt;
+        float globi = (myPi/2.0f) + this->tiltBy;
+
+        for(int s = 0; s<segments; ++s){
+            sepp = sepp + dPhi;
+            if(s<segments/2){            
+                globi = globi - dTheta; 
+            }else{
+                globi = globi + dTheta; 
+            }
+            
+            Vector3 pos(radius*cos(sepp)*sin(globi), radius*sin(sepp)*sin(globi), radius*cos(globi));
+
+            SpicedAsteroidField* field = new SpicedAsteroidField(this->getContext());
+            field->setPosition(this->position + pos);
+            field->setMinSize(this->minSize);
+            field->setMaxSize(this->maxSize);
+            field->setRadius(width);
+            field->setCount(segmentCount);
+            field->setFog(this->foggy);
+            field->setMineralDensity(this->mDensity);
+            field->setFogDensity(this->fogDensity);
+        }
+    }
+
+    void SpicedAsteroidBelt::XMLPort(Element& xmlelement, XMLPort::Mode mode){
+
+        SUPER(SpicedAsteroidBelt, XMLPort, xmlelement, mode); 
+
+        XMLPortParam(SpicedAsteroidBelt, "count", setCount, getCount, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "mDensity", setMineralDensity, getMineralDensity, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "position", setPosition, getPosition, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "segments", setSegments, getSegments, xmlelement, mode);
+
+        XMLPortParam(SpicedAsteroidBelt, "maxSize", setMaxSize, getMaxSize, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "minSize", setMinSize, getMinSize, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "radius0", setRadius0, getRadius0, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "radius1", setRadius1, getRadius1, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "foggy", setFog, isFoggy, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "fogDensity", setFogDensity, getFogDensity, xmlelement, mode);
+
+        XMLPortParam(SpicedAsteroidBelt, "tiltAt", setTiltAt, getTiltAt, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidBelt, "tiltBy", setTiltBy, getTiltBy, xmlelement, mode); 
+
+    }
+
+    void SpicedAsteroidBelt::tick(float dt){
+
+        this->create();
+        this->destroyLater();
+
+    }
+
+}
+
+
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidBelt.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidBelt.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidBelt.h	(revision 11817)
@@ -0,0 +1,131 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      remartin
+ *   Co-authors:
+ *
+ */
+
+/**
+
+    @file 
+    @author remartin
+    @brief Asteroid belt with lots of parameters. Derived from asteroidField.lua
+
+    Generates a ring of asteroids by calling SpicedAsteroidField multiple times. 
+    It's in the xy-plane at default, orientation can be changed with tiltAt 
+    (angle where it gets elevated/lowered the most) and TiltBy (angle at z-axis). 
+    This doesn't work very well and could probably implemented differently with 
+    relative coordinates (attach etc, stuff in WorldEntity). 
+
+    It is required to wait until all XML-arguments are set. That's why the actual 
+    generation happens when tick() gets called for the first time. 
+    
+*/
+
+
+#ifndef _SpicedAsteroidBelt_H__
+#define _SpicedAsteroidBelt_H__
+
+#include "AsteroidMiningPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox // tolua_export
+{
+
+    // tolua_export
+    class _AsteroidMiningExport SpicedAsteroidBelt : public BaseObject, public Tickable
+    { // tolua_export
+
+        public:
+            SpicedAsteroidBelt(Context* context);// This constructor is for XML access only!
+            virtual ~SpicedAsteroidBelt();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void tick(float dt) override;
+
+            inline void setCount(float s){this->count = s;}
+            inline float getCount(){return this->count;}
+
+            inline void setMineralDensity(float d){this->mDensity = d;}
+            inline float getMineralDensity(){return this->mDensity;}
+
+            inline void setPosition(const Vector3& v){this->position = v;}
+            inline const Vector3& getPosition(){return this->position;}
+
+            inline void setSegments(int s){this->segments = s;}
+            inline int getSegments(){return this->segments;}
+
+            inline void setMaxSize(float i){this->maxSize = i;}
+            inline float getMaxSize(){return this->maxSize;}
+
+            inline void setMinSize(float i){this->minSize = i;}
+            inline float getMinSize(){return this->minSize;}
+
+            inline void setRadius0(float r0){this->radius0 = r0;}
+            inline float getRadius0(){return this->radius0;}
+
+            inline void setRadius1(float r1){this->radius1 = r1;}
+            inline float getRadius1(){return this->radius1;}
+
+            inline void setFog(bool f){this->foggy = f;}
+            inline bool isFoggy(){return this->foggy;}
+
+            inline void setFogDensity(float fd){this->fogDensity = fd;}
+            inline float getFogDensity(){return this->fogDensity;}
+
+            inline void setTiltAt(float ta){this->tiltAt = ta;}
+            inline void setTiltBy(float tb){this->tiltBy = tb;}
+            inline float getTiltAt(){return this->tiltAt;}
+            inline float getTiltBy(){return this->tiltBy;}
+
+
+        protected:
+
+            float count; //!< Approximate number of asteroids
+            float mDensity; //!< Approximate commonness of asteroids that yield stuff, value between 0 and 1;
+
+            Vector3 position;
+
+            int segments; //!< Number of asteroidFields that get generated. 
+            
+            float maxSize; //!< Most obese asteroid possible
+            float minSize; //!< Most meagre asteroid possible
+
+            float radius0; //!< Inner radius
+            float radius1; //!< Outer radius
+
+            bool foggy; //!< Whether there's fog arount the asteroids
+            float fogDensity; 
+
+            float tiltAt; //!< Orientation: Angle where it gets elevated/lowered the most
+            float tiltBy; //!< angle at z-axis
+
+        private:
+            virtual void create();
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _SpicedAsteroidBelt_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidField.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidField.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidField.cc	(revision 11817)
@@ -0,0 +1,132 @@
+
+ /*   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      remartin
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+
+    @file 
+    @author remartin
+    @brief Asteroid field with lots of parameters. Derived from asteroidField.lua
+
+    Generates a bunch of asteroids that may contain some stuff. 
+    It is required to wait until all XML-arguments are set. That's why the actual 
+    generation happens when tick() gets called for the first time. 
+    
+*/
+
+
+#include "SpicedAsteroidField.h"
+#include "AsteroidMinable.h"
+
+#include <algorithm>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Math.h"
+
+#include "graphics/Billboard.h"
+
+
+namespace orxonox{
+
+    RegisterClass(SpicedAsteroidField);
+
+    SpicedAsteroidField::SpicedAsteroidField(Context* context) : BaseObject(context) {
+
+        RegisterObject(SpicedAsteroidField);
+
+        // Default Values: 
+        this->count = 30; 
+        this->mDensity = 0.5;
+        this->position = Vector3(0,0,0);
+        this->maxSize = 40; 
+        this->minSize = 1; 
+        this->radius = 1000;
+        this->foggy = true; 
+        this->fogDensity = 0.5;
+    }
+
+    SpicedAsteroidField::~SpicedAsteroidField(){
+
+    }
+
+    void SpicedAsteroidField::create(){
+
+        float size;
+        float pX;
+        float pY;
+        float pZ;
+
+        for(int gertrud = 0; gertrud<count; ++gertrud){
+
+            AsteroidMinable* a = new AsteroidMinable(this->getContext());
+
+            size = roundf(rnd(this->maxSize - this->minSize)) + this->minSize;
+            a->setSize(size); 
+
+            pX = roundf(rnd(2*this->radius)) - radius;
+            pY = roundf(rnd(2*this->radius)) - radius;
+            pZ = roundf(rnd(2*this->radius)) - radius;
+            Vector3 relPos(pX, pY, pZ);
+            a->setPosition(this->position + relPos);
+
+            bool spiced = (rnd() < (this->mDensity)); // Whether the asteroid does drop pickups etc. 
+            a->setDropStuff(spiced);
+            
+            // Fog is iplemented with billboards (as in asteroidField.lua, that bloke had the idea)
+            if(this->foggy && mod(gertrud, 5) == 0){
+                Billboard* bb = new Billboard(this->getContext());
+                bb->setPosition(this->position + relPos);
+                bb->setMaterial("Smoke/Smoke");
+                bb->setScale(size);
+                bb->setColour(ColourValue(this->fogDensity, this->fogDensity, this->fogDensity));    
+            }
+        }
+    }
+
+    void SpicedAsteroidField::XMLPort(Element& xmlelement, XMLPort::Mode mode){
+
+        SUPER(SpicedAsteroidField, XMLPort, xmlelement, mode); 
+
+        XMLPortParam(SpicedAsteroidField, "count", setCount, getCount, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "mDensity", setMineralDensity, getMineralDensity, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "position", setPosition, getPosition, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "maxSize", setMaxSize, getMaxSize, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "minSize", setMinSize, getMinSize, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "radius", setRadius, getRadius, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "foggy", setFog, isFoggy, xmlelement, mode);
+        XMLPortParam(SpicedAsteroidField, "fogDensity", setFogDensity, getFogDensity, xmlelement, mode);
+
+    }
+
+    void SpicedAsteroidField::tick(float dt){
+
+        this->create();
+        this->destroyLater();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidField.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidField.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroidmining/SpicedAsteroidField.h	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      remartin
+ *   Co-authors:
+ *
+ */
+
+/**
+
+    @file 
+    @author remartin
+    @brief Asteroid field with lots of parameters. Derived from asteroidField.lua
+
+    Generates a bunch of asteroids that may contain some stuff. 
+    It is required to wait until all XML-arguments are set. That's why the actual 
+    generation happens when tick() gets called for the first time. 
+    
+*/
+
+#ifndef _SpicedAsteroidField_H__
+#define _SpicedAsteroidField_H__
+
+#include "AsteroidMiningPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox // tolua_export
+{
+
+    // tolua_export
+    class _AsteroidMiningExport SpicedAsteroidField : public BaseObject, public Tickable
+    { // tolua_export
+
+        public:
+            SpicedAsteroidField(Context* context);
+            virtual ~SpicedAsteroidField();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void tick(float dt) override;
+
+            inline void setCount(int s){this->count = s;}
+            inline int getCount(){return this->count;}
+
+            inline void setMineralDensity(float d){this->mDensity = d;}
+            inline float getMineralDensity(){return this->mDensity;}
+
+            inline void setPosition(const Vector3& v){this->position = v;}
+            inline const Vector3& getPosition(){return this->position;}
+
+            inline void setMaxSize(float i){this->maxSize = i;}
+            inline float getMaxSize(){return this->maxSize;}
+
+            inline void setMinSize(float i){this->minSize = i;}
+            inline float getMinSize(){return this->minSize;}
+
+            inline void setRadius(float r){this->radius = r;}
+            inline float getRadius(){return this->radius;}
+
+            inline void setFog(bool f){this->foggy = f;}
+            inline bool isFoggy(){return this->foggy;}
+
+            inline void setFogDensity(float fd){this->fogDensity = fd;}
+            inline float getFogDensity(){return this->fogDensity;}
+
+        protected:
+
+            int count; //!< Number of asteroids generated
+            float mDensity; //!< Mineral density, between 0 and 1;
+
+            Vector3 position; //!< The center
+            
+            float maxSize; //!< Upper bound to asteroid size
+            float minSize; //!< Lower bound to asteroid size
+
+            float radius; //!< Asteroids can appear within a sphere. 
+            bool foggy; //!< Whether there's fog
+            float fogDensity;
+
+
+        private:
+            virtual void create();
+
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _SpicedAsteroidField_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2D.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2D.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2D.cc	(revision 11817)
@@ -0,0 +1,229 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+
+/**
+    @file Asteroids2D.cc
+    @brief Implementation of the Asteroids2D class.
+
+    TODO: 
+        - Implement a counting system for the score
+        - HUD can be improved (display health, points, level etc.
+        - Problem: The asteroids spawn randomly on the playing field.
+            During spawn or level up, there is the possibility that they pawn at the position of the ship.
+            ->spawn somewhere with a safty distance/radius
+        - look over collisionshapes of the stones ->  sometimes collison with stone is not triggered for bigger stones 
+        - modify parameters in data/levels/templates/spaceshipAsteroids2D.oxt for a better playing experience -> mass, damping, rotation etc.
+
+    IDEAS:
+        - make Asteroids more beautiful! (setting, ship, explosion particles, stones)
+        - particle effect after you got hit -> during bImmune is true
+        - implement shield -> object that can be triggered
+        - Projectiles should also move over the boarders and appear on the other side
+            -> they can also hurt the player
+
+*/
+
+#include "Asteroids2D.h"
+#include "Asteroids2DShip.h" // Necessary for getPlayer function. Do NOT include this in Header!
+#include "Asteroids2DStone.h"
+#include "Asteroids2DCenterPoint.h"
+#include "Asteroids2DHUDinfo.h"
+#include "core/CoreIncludes.h"
+#include "Highscore.h"
+#include "gamestates/GSLevel.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Asteroids2D);
+
+    Asteroids2D::Asteroids2D(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(Asteroids2D);
+
+        bEndGame = false;
+        lives = 3; 
+        level = 1;
+        point = 0;
+        bShowLevel = false;
+        multiplier = 1;
+        b_combo = false;
+        firstTick_ = true;
+        this->numberOfBots_ = 0; //sets number of default bots temporarly to 0
+        this->center_ = nullptr;
+        this->setHUDTemplate("Asteroids2DHUD");
+        levelupTimer.setTimer(30.0f, true, createExecutor(createFunctor(&Asteroids2D::levelUp, this))); //level up every 30s
+    }
+
+    void Asteroids2D::setCenterpoint(Asteroids2DCenterPoint* center)
+    {
+        this->center_ = center;
+    }
+
+    void Asteroids2D::levelUp()
+    {
+        level++;
+        if (getPlayer() != nullptr)
+        {
+
+            //Do something that indicates a level up
+            for (int i = 0; i < 7; i++)
+            {
+                WeakPtr<ExplosionPart> chunk5 = new ExplosionPart(this->center_->getContext());
+                chunk5->setPosition(Vector3(600, 0, 100.f * i - 300));
+                chunk5->setVelocity(Vector3(1000, 0, 0));  //player->getVelocity()
+                chunk5->setScale(10);
+                chunk5->setEffect1("Orxonox/explosion2b");
+                chunk5->setEffect2("Orxonox/smoke6");
+                chunk5->Explode();
+
+            }
+        }
+        addPoints(multiplier * 20);
+        multiplier *= 2;
+        toggleShowLevel();
+        showLevelTimer.setTimer(1.0f, false, createExecutor(createFunctor(&Asteroids2D::toggleShowLevel, this)));
+
+
+        //After level up -> spawn stones. Modify for different difficulty level
+        for(int i = 0; i < level*2; i++){
+            spawnStone();
+        }
+
+    }
+
+    void Asteroids2D::tick(float dt)
+    {
+        //Do this only for the first tick, generate 5 stones in the beginning
+        if(this->firstTick_)
+        {
+            for(int i = 0; i < 5; ++i)
+            {
+                spawnStone();
+            }
+            //after first tick, firstTick_ will remain false
+            this->firstTick_ = false;
+        }
+        
+        SUPER(Asteroids2D, tick, dt);
+    }
+
+    void Asteroids2D::spawnStone()
+    {
+
+        //stones are created with a size -> second constructor in Asteroids2DStone class
+        Asteroids2DStone* newStone = new Asteroids2DStone(this->center_->getContext());
+
+        //look at templates in data/levels/templates/asteroidsAsteroids2D.oxt
+        switch(newStone->getSize()){
+            case 1:
+                newStone->addTemplate("stone1");
+                break;
+            case 2: 
+                newStone->addTemplate("stone2");
+                break;
+            case 3:
+                newStone->addTemplate("stone3");
+                break;
+            default:
+                orxout(internal_error) << "Asteroids2DStone has invalid size and cannot be created" << endl;
+                break;
+
+        }
+    }
+
+    Asteroids2DShip* Asteroids2D::getPlayer()
+    {
+        for (Asteroids2DShip* ship : ObjectList<Asteroids2DShip>())
+        {
+            return ship;
+        }
+        return nullptr;
+    }
+
+    void Asteroids2D::costLife()
+    {
+        --lives;
+        if(lives <= 0){
+            endGameTimer.setTimer(8.0f, false, createExecutor(createFunctor(&Asteroids2D::end, this)));            
+        }
+    };
+    
+    //The first function that will be called
+    void Asteroids2D::start()
+    {
+        //orxout() << "start" << endl;
+
+        // Set variable to temporarily force the player to spawn.
+        this->bForceSpawn_ = false;
+
+        if (this->center_ == nullptr)  // abandon mission!
+        {
+            orxout(internal_error) << "Asteroids2D: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+        // Call start for the parent class.
+        Deathmatch::start();
+    }
+
+    void Asteroids2D::playerPreSpawn(PlayerInfo* player)
+    {
+        this->playerInfo_ = player;
+        if(lives <= 0)
+        {
+            this->end();
+        }
+    }
+
+    //This function will be called from the ship or the stone class (if the stone was hit)
+    void Asteroids2D::addPoints(int numPoints)
+    {
+        if (!bEndGame)
+        {
+            point += numPoints * multiplier;
+            b_combo = true;
+        }
+    }
+
+    void Asteroids2D::end()
+    {
+        // DON'T CALL THIS!
+        //      Deathmatch::end();
+        // It will misteriously crash the game!
+        // Instead startMainMenu, this won't crash.
+        if (Highscore::exists())
+        {
+            int score = this->getPoints();
+            Highscore::getInstance().storeScore("Asteroids2D", score, this->playerInfo_);
+        }
+        GSLevel::startMainMenu();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2D.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2D.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2D.h	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+
+/**
+    @file Asteroids2D.h
+    @brief Gametype:
+     - Goal: Survive as long as you can, do not collide with stones
+     - spawns stones in every level up
+     - if you shoot and hit a stone, it will spit into two smaller stones
+    @ingroup Asteroids2D
+*/
+
+#ifndef _Asteroids2D_H__
+#define _Asteroids2D_H__
+
+#include "asteroids2D/Asteroids2DPrereqs.h"
+
+#include "gametypes/Deathmatch.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+
+    class _Asteroids2DExport Asteroids2D : public Deathmatch
+    {
+       public:
+            Asteroids2D(Context* context);
+
+            virtual void start() override;
+            virtual void end() override;
+
+            //updates the game every few ns
+            virtual void tick(float dt) override;
+
+            virtual void playerPreSpawn(PlayerInfo* player) override;
+
+            void levelUp();
+
+
+            //For HUD
+            int getLives(){return this->lives;}
+            int getLevel(){return this->level;}
+            int getPoints(){return this->point;}
+            int getMultiplier(){return this->multiplier;}
+
+            //Generate Stones
+            void spawnStone();
+            void setCenterpoint(Asteroids2DCenterPoint* center);
+
+            void addPoints(int numPoints);
+            virtual void addBots(unsigned int amount) override{} //<! overwrite function in order to bypass the addbots command
+
+            // checks if multiplier should be reset.
+            void costLife();
+
+            //Returns player (ship) of the game
+            Asteroids2DShip* getPlayer();
+
+            bool bEndGame;
+            bool bShowLevel;
+            int lives;
+            int multiplier;
+
+
+       private:
+
+
+
+            WeakPtr<PlayerInfo> playerInfo_;
+            void toggleShowLevel(){bShowLevel = !bShowLevel;}
+
+            WeakPtr<Asteroids2DCenterPoint> center_;
+            int level;
+            int point;
+            bool b_combo, firstTick_;
+
+            Timer comboTimer;
+            Timer showLevelTimer;
+            Timer levelupTimer;
+            Timer endGameTimer;
+
+
+    };
+}
+
+#endif /* _Asteroids2D_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DCenterPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DCenterPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DCenterPoint.cc	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Asteroids2DCenterPoint.cc
+    @brief Implementation of the Asteroids2DCenterPoint class.
+*/
+
+#include "Asteroids2DCenterPoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Asteroids2D.h"
+
+namespace orxonox
+{
+    RegisterClass(Asteroids2DCenterPoint);
+
+    Asteroids2DCenterPoint::Asteroids2DCenterPoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Asteroids2DCenterPoint);
+
+        this->checkGametype();
+        this->width_ = 1043;
+        this->height_ = 646;
+    }
+
+    
+    /**
+    @brief
+        Method to create a Asteroids2DCenterpoint through XML.
+        Set dimension of the field with "width_, height_"
+    */
+    void Asteroids2DCenterPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Asteroids2DCenterPoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Asteroids2DCenterPoint, "dimension", setFieldDimension, getFieldDimension, xmlelement, mode);
+    }
+
+
+    void Asteroids2DCenterPoint::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Asteroids2D)))
+        {
+            Asteroids2D* Asteroids2DGametype = orxonox_cast<Asteroids2D*>(this->getGametype());
+            Asteroids2DGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DCenterPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DCenterPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DCenterPoint.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Asteroids2DCenterPoint.h
+    @brief Declaration of the Asteroids2DCenterPoint class.
+    @ingroup Asteroids2D
+*/
+
+#ifndef _Asteroids2DCenterPoint_H__
+#define _Asteroids2DCenterPoint_H__
+
+#include "asteroids2D/Asteroids2DPrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _Asteroids2DExport Asteroids2DCenterPoint : public StaticEntity
+    {
+        public:
+            Asteroids2DCenterPoint(Context* context); //checks whether the gametype is actually Asteroids2D.
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method to create a PongCenterpoint through XML.
+            /**
+            @brief Set the dimensions of the playing field.
+            @param dimension A vector with the width of the playing field as first component and the height as second.
+            */
+            void setFieldDimension(const Vector2& dimension)
+                { this->width_ = dimension.x; this->height_ = dimension.y; }
+            /**
+            @brief Get the dimensions of the playing field.
+            @return Returns a vector with the width of the playing field as first component and the height as second.
+            */
+            Vector2 getFieldDimension() const
+                { return Vector2(this->width_, this->height_); }
+
+        private:
+            void checkGametype(); //checks whether the gametype actually is Asteroids2D
+            float width_, height_;
+
+    };
+}
+
+#endif /* _Asteroids2DCenterPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DHUDinfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DHUDinfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DHUDinfo.cc	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *
+ */
+
+#include "Asteroids2DHUDinfo.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "Asteroids2D.h"
+
+namespace orxonox
+{
+    RegisterClass(Asteroids2DHUDinfo);
+
+    Asteroids2DHUDinfo::Asteroids2DHUDinfo(Context* context) : OverlayText(context)
+    {
+        RegisterObject(Asteroids2DHUDinfo);
+
+        this->Asteroids2DGame = nullptr;
+        this->bShowPoints_ = true;
+    }
+
+    void Asteroids2DHUDinfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Asteroids2DHUDinfo, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Asteroids2DHUDinfo,"showPoints", setShowPoints, getShowPoints, xmlelement, mode).defaultValues(false);
+    }
+
+    void Asteroids2DHUDinfo::tick(float dt)
+    {
+        SUPER(Asteroids2DHUDinfo, tick, dt);
+
+
+        if(this->bShowPoints_)
+        {
+            const std::string& points = multi_cast<std::string>(this->Asteroids2DGame->getPoints());
+            if (this->Asteroids2DGame->lives <= 0)
+            {
+                setTextSize(0.2);
+                setPosition(Vector2(0.1, 0.02));
+                this->setCaption("Final score:\n" + points);
+                this->setColour(ColourValue(1, 0, 0, 1));
+            }
+            else
+            {
+                setTextSize(0.04);
+                setPosition(Vector2(0.14, 0.02));
+                this->setColour(ColourValue(1, 1, 1, 1));
+                this->setCaption(points);
+            }
+        }
+
+    }
+
+    void Asteroids2DHUDinfo::changedOwner()
+    {
+        SUPER(Asteroids2DHUDinfo, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->Asteroids2DGame = orxonox_cast<Asteroids2D*>(this->getOwner()->getGametype());
+
+        }
+        else
+        {
+            this->Asteroids2DGame = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DHUDinfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DHUDinfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DHUDinfo.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *      
+ *      TODO: - get information for lives and level from gametype
+ *            - implement it as you did for points  
+ *
+ */
+
+#ifndef _Asteroids2DHUDinfo_H__
+#define _Asteroids2DHUDinfo_H__
+
+#include "asteroids2D/Asteroids2DPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _Asteroids2DExport Asteroids2DHUDinfo : public OverlayText, public Tickable
+    {
+     public:
+            Asteroids2DHUDinfo(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowPoints(bool value)
+                { this->bShowPoints_ = value; }
+            inline bool getShowPoints() const
+                { return this->bShowPoints_; }
+
+
+        private:
+            Asteroids2D* Asteroids2DGame;
+            bool bShowPoints_;
+
+
+    };
+}
+#endif /* _Asteroids2DHUDinfo_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DPrereqs.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the Asteroids2D module
+*/
+
+#ifndef _Asteroids2DPrereqs_H__
+#define _Asteroids2DPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ASTEROIDS2D_STATIC_BUILD)
+#  ifdef ASTEROIDS2D_SHARED_BUILD
+#    define _Asteroids2DExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _Asteroids2DExport
+#    else
+#      define _Asteroids2DExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _Asteroids2DPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _Asteroids2DExport  __attribute__ ((visibility("default")))
+#  define _Asteroids2DPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _Asteroids2DExport
+#  define _Asteroids2DPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Asteroids2D;
+    class Asteroids2DCenterPoint;
+    class Asteroids2DHUDinfo;
+    class Asteroids2DShip;
+    class Asteroids2DStone;
+    class Asteroids2DWeapon;
+}
+
+#endif /* _Asteroids2DPrereqs_H__*/
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DShip.cc	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/*  TODO: 
+
+    @file Asteroids2DShip.cc
+    @brief Implementation of the Asteroids2DShip class.
+*/
+
+#include "Asteroids2DShip.h"
+#include "Asteroids2DStone.h"
+#include "Asteroids2D.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(Asteroids2DShip);
+
+    Asteroids2DShip::Asteroids2DShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(Asteroids2DShip);
+
+        this->bImmune = false;
+        this->width = 1043;
+        this->height = 646;
+
+        //timer.setTimer(3.5f, true, createExecutor(createFunctor(&Asteroids2DShip::showorientation, this)));
+    }
+
+    //Use this function to display your position on the field -> to determine field width and height
+    void Asteroids2DShip::showposition()
+    {
+        Vector3 pos = this->getPosition();
+        orxout() << "x = "<< pos.x << " y = " << pos.y << " z = "<< pos.z << endl; 
+    }
+
+    //Same thing for orientation
+    void Asteroids2DShip::showorientation()
+    {
+        Quaternion ort = this->getOrientation();
+        orxout() << "w = " << ort.w << " x = " << ort.x << " y = " << ort.y << "z = " << ort.z << endl;
+    }
+
+    void Asteroids2DShip::tick(float dt)
+    {
+        SUPER(Asteroids2DShip, tick, dt);
+        Vector3 pos = this->getPosition();
+
+        //ensure that the ship stays in playing field
+        if(pos.x > width/2)   pos.x = -width/2;
+        if(pos.x < -width/2)  pos.x = width/2;
+        if(pos.z > height/2)  pos.z = -height/2;
+        if(pos.z < -height/2) pos.z = height/2;
+
+        //2D movement, position should always = 0 on y-axis
+        if(pos.y!=0) pos.y = 0;
+        this->setPosition(pos);
+
+
+        //if you hit an asteroid, the ship will turn -> you need to reorientate the ship 
+        Quaternion ort = this->getOrientation();
+        ort.x = 0;
+        ort.z = 0;
+        this->setOrientation(ort);
+    }
+
+    void Asteroids2DShip::boost(bool bBoost)
+    {
+    }
+
+    void Asteroids2DShip::updateLevel()
+    {
+        if (getGame())
+            getGame()->levelUp();
+    }
+
+    inline bool Asteroids2DShip::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+
+        Asteroids2DStone* stone = orxonox_cast<Asteroids2DStone*>(otherObject);       
+        if(stone != nullptr && !bImmune)
+        {
+            removeHealth(100); 
+            this->getGame()->addPoints(10);
+
+            //The ship will be immune for 3 seconds after it has been hit by an asteroid
+            bImmune = true;
+            isimmune.setTimer(3.0f, false, createExecutor(createFunctor(&Asteroids2DShip::toggleImmune, this)));
+        }
+        return false;
+    }
+
+    Asteroids2D* Asteroids2DShip::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (Asteroids2D* race : ObjectList<Asteroids2D>())
+            {
+                game = race;
+            }
+        }
+        return game;
+    }
+
+    void Asteroids2DShip::death()
+    {
+        getGame()->costLife();
+        SpaceShip::death();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DShip.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Asteroids2DShip.h
+    @brief Declaration of the Asteroids2DShip class.
+*/
+
+#ifndef _Asteroids2DShip_H__
+#define _Asteroids2DShip_H__
+
+
+#include "asteroids2D/Asteroids2DPrereqs.h"
+
+#include "worldentities/pawns/SpaceShip.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+    class _Asteroids2DExport Asteroids2DShip : public SpaceShip
+    {
+        public:
+            Asteroids2DShip(Context* context);
+
+            virtual void tick(float dt) override;
+
+            //no rotation in x and z direction!
+            virtual void rotatePitch(const Vector2& value) override{}; // Rotate in pitch direction.
+            virtual void rotateRoll(const Vector2& value) override{}; // Rotate in roll direction.
+            virtual void boost(bool boost) override; //Override, so that the ship does not shake
+            virtual void updateLevel();
+
+            virtual inline bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            
+            /*Functions that can be helpful while debugging.
+                - Set a timer so that the function is called for instance every 3s to display the coordinates
+                - Open console with "~`"-key in when you start the Asteroids2D - Minigame.
+            */
+            void showposition();
+            void showorientation();
+
+
+            void toggleImmune()
+            {
+                bImmune = !bImmune;
+            }
+
+        protected:
+            virtual void death() override;
+
+        private:
+            Asteroids2D* getGame();
+
+            float width, height;
+            WeakPtr<Asteroids2D> game;
+            bool bImmune;
+            Timer timer;
+            Timer isimmune;
+    };
+}
+
+#endif /* _Asteroids2DShip_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DStone.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DStone.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DStone.cc	(revision 11817)
@@ -0,0 +1,155 @@
+/*   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+
+/**
+    @file Asteroids2DStone.cc
+
+    @brief Implementation of the Asteroids2DStone class.
+
+    TO DO:  
+    - when to split? It does not work if you override kill() function...->damage() function?
+*/ 
+
+#include "Asteroids2DStone.h"
+#include "Asteroids2D.h"
+#include "Asteroids2DShip.h"
+#include "core/CoreIncludes.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    RegisterClass(Asteroids2DStone);
+
+    Asteroids2DStone::Asteroids2DStone(Context* context) : Pawn(context)
+    {
+        RegisterObject(Asteroids2DStone);
+        this->size = rand()%3+1;
+        this->width = 1043;
+        this->height = 646;
+        this->setPosition(randomPosition(this->width, this->height));
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+        this->setVelocity(randomVelocity(MAX_SPEED));
+    }
+
+    Asteroids2DStone::Asteroids2DStone(Context* c, int sze, Vector3 pos) : Pawn(c)
+    {
+        RegisterObject(Asteroids2DStone);
+        this->size = sze;
+        this->width = 1043;
+        this->height = 646;
+        this->setPosition(pos);
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+        this->setVelocity(randomVelocity(MAX_SPEED));
+    }
+
+    Vector3 Asteroids2DStone::randomPosition(float maxwidth, float maxheight)
+    {
+        Vector3 pos;
+        pos.x = rnd(-maxwidth/2, maxwidth/2);
+        pos.y = 0;
+        pos.z = rnd(-maxheight/2, maxheight/2);
+        return pos;
+    }
+
+    Vector3 Asteroids2DStone::randomVelocity(float maxspeed)
+    {
+        Vector3 vel;
+        vel.x = rnd(-maxspeed, maxspeed);
+        vel.y = 0;
+        vel.z = rnd(-maxspeed, maxspeed);
+        return vel;
+    }
+
+
+    void Asteroids2DStone::tick(float dt)
+    {
+        SUPER(Asteroids2DStone, tick, dt);
+        Vector3 pos = this->getPosition();
+        Vector3 vel = this->getVelocity();
+
+        //ensure that the stone bounces from the playing field borders
+        if(pos.x > width/2  || pos.x < -width/2)  vel.x = -vel.x;
+        if(pos.z > height/2 || pos.z < -height/2) vel.z = -vel.z;
+        this->setVelocity(vel);
+
+        //2D movement, position should always = 0 on y-axis
+        if(pos.y!=0) pos.y = 0;
+        this->setPosition(pos);
+    }
+
+    inline bool Asteroids2DStone::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        if(orxonox_cast<Asteroids2DShip*>(otherObject))
+        {
+            split();
+        }
+        return false;
+    }
+
+    void Asteroids2DStone::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        if (getGame() && orxonox_cast<Asteroids2DShip*>(originator) != nullptr)
+            getGame()->addPoints(100);
+        split();
+        //Pawn::damage(damage, healthdamage, shielddamage, originator, cs);
+    }
+
+    Asteroids2D* Asteroids2DStone::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (Asteroids2D* asteroids : ObjectList<Asteroids2D>())
+                game = asteroids;
+        }
+        return game;
+    }
+
+    void Asteroids2DStone::split()
+    {
+        //orxout() << "split" << endl;
+        if(size == 3)
+        {
+            Asteroids2DStone* newStone1 = new Asteroids2DStone(this->getContext(), 2, this->getPosition());
+            newStone1->addTemplate("stone2");
+            Asteroids2DStone* newStone2 = new Asteroids2DStone(this->getContext(), 2, this->getPosition());
+            newStone2->addTemplate("stone2");
+
+        }else if(size == 2){
+
+
+            //Templates can be found in data/levels/templates/asteroidsAsteroids2D.oxt
+            Asteroids2DStone* newStone1 = new Asteroids2DStone(this->getContext(), 1, this->getPosition());
+            newStone1->addTemplate("stone1");
+            Asteroids2DStone* newStone2 = new Asteroids2DStone(this->getContext(), 1, this->getPosition());
+            newStone2->addTemplate("stone1");
+        }   
+        this->death();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DStone.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DStone.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DStone.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *    TO DO: 
+ *
+ */
+
+/**
+    @file Asteroids2D.h
+    @brief Gametype.
+    @ingroup Asteroids2D
+*/
+
+#ifndef _Asteroids2DStone_H__
+#define _Asteroids2DStone_H__
+
+#include "asteroids2D/Asteroids2DPrereqs.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+
+namespace orxonox
+{
+    class _Asteroids2DExport Asteroids2DStone : public Pawn
+    {
+       public:
+            Asteroids2DStone(Context* context);
+            Asteroids2DStone(Context* c, int sze, Vector3 pos);
+
+            virtual void tick(float dt) override;
+            Vector3 randomPosition (float maxwidth, float maxheight);
+            Vector3 randomVelocity(float maxspeed);
+            virtual int getSize(){ return this->size;}
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void split();
+            virtual void damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs) override;
+
+       private:
+          Asteroids2D* getGame();
+          WeakPtr<Asteroids2D> game;
+          int size; // three sizes, 3-> two 2s, 2-> two 1s, 1-> die
+          float width, height; //field
+          float MAX_SPEED = 100;
+          float delta = 5;
+    };
+}
+
+#endif /* _Asteroids2DStone_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DWeapon.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DWeapon.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DWeapon.cc	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      --
+ *
+ */
+
+/**
+    @file Asteroids2DWeapon.h
+    @brief Implementation of the Asteroids2DWeapon class.
+*/
+
+#include "Asteroids2DWeapon.h"
+
+#include "core/CoreIncludes.h"
+
+#include "graphics/Model.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+
+#include "weapons/projectiles/Projectile.h"
+#include "weapons/MuzzleFlash.h"
+
+namespace orxonox
+{
+    RegisterClass(Asteroids2DWeapon);
+
+    Asteroids2DWeapon::Asteroids2DWeapon(Context* context) : HsW01(context)
+    {
+        RegisterObject(Asteroids2DWeapon);
+
+
+    }
+
+    Asteroids2DWeapon::~Asteroids2DWeapon()
+    {
+
+    }
+
+    void Asteroids2DWeapon::shot()
+    {
+        assert( this->getWeapon() && this->getWeapon()->getWeaponPack() && this->getWeapon()->getWeaponPack()->getWeaponSystem() && this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn() );
+
+        // Create the projectile.
+        Projectile* projectile = new Projectile(this->getContext());
+        Model* model = new Model(projectile->getContext());
+        model->setMeshSource(mesh_);
+        model->setCastShadows(false);
+        projectile->attach(model);
+        model->setScale(5);
+
+        //get position and orientation of the ship to know in which direction the projectile needs to fire off
+        Pawn* player = this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn();
+
+        projectile->setOrientation(player->getOrientation());
+        projectile->setPosition(player->getPosition());
+
+        //Velocity & position of the projectile must be y = 0 since the game takes place in the x-z plane
+        Vector3 muzzle2D = player->getOrientation()* WorldEntity::FRONT ;
+        muzzle2D.y = 0; 
+        projectile->setVelocity(muzzle2D * this->speed_);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+
+        // Display the muzzle flash.
+        this->HsW01::muzzleflash();
+    }
+    
+}
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DWeapon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DWeapon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/Asteroids2DWeapon.h	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Viviane Yang
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Asteroids2DWeapon.h
+    @brief Definition of the Asteroids2DWeapon class.
+*/
+
+#ifndef _Asteroids2DWeapon_H__
+#define _Asteroids2DWeapon_H__
+
+#include "asteroids2D/Asteroids2DPrereqs.h"
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weapons/weaponmodes/HsW01.h"
+
+namespace orxonox
+{
+    class _Asteroids2DExport Asteroids2DWeapon : public HsW01
+    {
+        public:
+            Asteroids2DWeapon(Context* context);
+            virtual ~Asteroids2DWeapon();
+
+        protected:
+            virtual void shot() override; //2D movement
+            WeakPtr<Projectile> projectile;
+    };
+}
+
+#endif /* _Asteroids2DWeapon_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/asteroids2D/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/asteroids2D/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/asteroids2D/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,17 @@
+SET_SOURCE_FILES(MINIGAMESTEST_SRC_FILES
+Asteroids2D.cc
+Asteroids2DCenterPoint.cc
+Asteroids2DShip.cc
+Asteroids2DStone.cc
+Asteroids2DHUDinfo.cc
+Asteroids2DWeapon.cc
+)
+
+ORXONOX_ADD_LIBRARY(asteroids2D
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+  SOURCE_FILES ${MINIGAMESTEST_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/designtools/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,13 @@
+SET_SOURCE_FILES(DESIGNTOOLS_SRC_FILES
+  SkyboxGenerator.cc
+  CreateStars.cc
+  ScreenshotManager.cc
+)
+
+ORXONOX_ADD_LIBRARY(designtools
+  MODULE
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${DESIGNTOOLS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/designtools/CreateStars.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/CreateStars.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/CreateStars.cc	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gion-Andri Cantieni
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CreateStars.h"
+
+#include <OgreVector3.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/Billboard.h"
+
+namespace orxonox
+{
+    RegisterClass(CreateStars);
+
+    CreateStars::CreateStars(Context* context) : BaseObject(context)
+    {
+        RegisterObject(CreateStars);
+        this->material_ = "Examples/Flare";
+        this->alpha_ = 0.7f;
+        this->alphaDiff_ = 0.5f;
+        this->radiusDiff_ = 0.9f;
+        this->colour_.r = 1;
+        this->colour_.g = 1;
+        this->colour_.b = 1;
+        this->colourDiff_ = 0.1f;
+    }
+
+    CreateStars::~CreateStars()
+    {
+        while( billboards_.size()!=0 )
+        {
+            billboards_.back()->destroy();
+            billboards_.pop_back();
+
+        }
+
+        billboards_.clear();
+    }
+
+    void CreateStars::createBillboards()
+    {
+
+        for(int i=0; i < numStars_; i++)
+        {
+            Billboard* bb = new Billboard(this->getContext());
+
+            float r = rnd(-colourDiff_,colourDiff_);
+            float g = rnd(-colourDiff_,colourDiff_);
+            float b = rnd(-colourDiff_,colourDiff_);
+            orxonox::ColourValue thisColour = colour_;
+            float alpha = alpha_+rnd(-alphaDiff_,alphaDiff_);
+            thisColour.r=clamp((thisColour.r+r)*alpha, 0.0f, 1.0f);
+            thisColour.g=clamp((thisColour.g+g)*alpha, 0.0f, 1.0f);
+            thisColour.b=clamp((thisColour.b+b)*alpha, 0.0f, 1.0f);
+
+            bb->setMaterial(material_);
+            bb->setColour(thisColour);
+
+            float phi;
+            float teta;
+
+            while(1)
+            {
+                phi = rnd(math::twoPi);
+                teta = rnd(math::pi);
+                float random = rnd(1);
+                if(sin(teta)>random) break;
+            }
+            float radius = rnd(radiusDiff_,1)*radius_;
+            bb->setPosition( PolarToCartesian(phi, teta, radius) );
+            billboards_.push_back(bb);
+        }
+    }
+
+    Vector3 CreateStars::PolarToCartesian(float phi, float teta, float radius)
+    {
+        float x = radius * cos(phi) * sin(teta);
+        float y = radius * sin(phi) * sin(teta);
+        float z = radius * cos(teta);
+        return Vector3(x,y,z);
+    }
+
+    void CreateStars::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CreateStars, XMLPort, xmlelement, mode);
+
+        XMLPortParam(CreateStars, "numStars", setNumStars, getNumStars, xmlelement, mode);
+        XMLPortParam(CreateStars, "material", setMaterial, getMaterial, xmlelement, mode);
+        XMLPortParam(CreateStars, "colour", setColour, getColour, xmlelement, mode);
+        XMLPortParam(CreateStars, "alpha", setAlpha, getAlpha, xmlelement, mode);
+        XMLPortParam(CreateStars, "colourDiff", setColourDiff, getColourDiff, xmlelement, mode);
+        XMLPortParam(CreateStars, "alphaDiff", setAlphaDiff, getAlphaDiff, xmlelement, mode);
+        XMLPortParam(CreateStars, "radiusDiff", setRadiusDiff, getRadiusDiff, xmlelement, mode);
+        XMLPortParam(CreateStars, "radius", setRadius, getRadius, xmlelement, mode);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/designtools/CreateStars.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/CreateStars.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/CreateStars.h	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gion-Andri Cantieni
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DesignToolsPrereqs.h"
+
+#include <string>
+#include "util/Math.h"
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class CreateStars : public BaseObject
+    {
+        public:
+            CreateStars(Context* context);
+            virtual ~CreateStars();
+
+            void createBillboards();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setNumStars(int num) {
+                this->numStars_ = num;
+            }
+
+            int getNumStars() const {
+                return this->numStars_;
+            }
+
+            void setMaterial(const std::string& material) {
+                this->material_ = material;
+            }
+
+            const std::string& getMaterial() const {
+                return this->material_;
+            }
+
+            void setColour(const orxonox::ColourValue& colour) {
+                this->colour_ = colour;
+            }
+
+            const ColourValue& getColour() const {
+                return this->colour_;
+            }
+
+            void setAlpha(float alpha) {
+                this->alpha_ = alpha;
+            }
+
+            float getAlpha() const {
+                return this->alpha_;
+            }
+
+            void setColourDiff(float colourDiff) {
+                this->colourDiff_ = colourDiff;
+            }
+
+            float getColourDiff() const {
+                return this->colourDiff_;
+            }
+
+            void setAlphaDiff(float alphaDiff) {
+                this->alphaDiff_ = alphaDiff;
+            }
+
+            float getAlphaDiff() const {
+                return this->alphaDiff_;
+            }
+
+            void setRadiusDiff(float radiusDiff) {
+                this->radiusDiff_ = radiusDiff;
+            }
+
+            float getRadiusDiff() const {
+                return this->radiusDiff_;
+            }
+
+            void setRadius(unsigned int dist) {
+                this->radius_ = dist;
+                this->createBillboards();
+            }
+
+            unsigned int getRadius()const {
+                return this->radius_;
+            }
+
+            Vector3 PolarToCartesian(float alpha, float beta, float radius);
+
+        private:
+            int numStars_;
+            std::string material_;
+            ColourValue colour_;
+            std::vector<Billboard*> billboards_;
+            unsigned int radius_;
+            float alpha_;
+            float colourDiff_;
+            float alphaDiff_;
+            float radiusDiff_;
+
+    };
+}
Index: /code/branches/RacingBots_FS18/src/modules/designtools/DesignToolsPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/DesignToolsPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/DesignToolsPrereqs.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the pong module
+*/
+
+#ifndef _DesignToolsPrereqs_H__
+#define _DesignToolsPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(DESIGNTOOLS_STATIC_BUILD)
+#  ifdef DESIGNTOOLS_SHARED_BUILD
+#    define _DesignToolsExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _DesignToolsExport
+#    else
+#      define _DesignToolsExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _DesignToolsPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _DesignToolsExport  __attribute__ ((visibility("default")))
+#  define _DesignToolsPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _DesignToolsExport
+#  define _DesignToolsPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+}
+
+#endif /* _DesignToolsPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/designtools/ScreenshotManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/ScreenshotManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/ScreenshotManager.cc	(revision 11817)
@@ -0,0 +1,297 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      This code comes from http://www.ogre3d.org/tikiwiki/High+resolution+screenshots which is Public Domain.
+ *   Co-authors:
+ *      Oli Scheuss
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+   @file ScreenshotManager.cc
+   @brief Implementation of the ScreenshotManager class.
+   @ingroup Designtools
+*/
+
+#include "ScreenshotManager.h"
+
+#include <OgreCamera.h>
+#include <OgreRenderTexture.h>
+#include <OgreRenderWindow.h>
+#include <OgreRoot.h>
+#include <OgreViewport.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GraphicsManager.h"
+#include "core/ConfigurablePaths.h"
+#include "core/Resource.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "util/StringUtils.h"
+
+#include "CameraManager.h"
+#include "graphics/Camera.h"
+
+// #include <X11/Xlib.h> TODO: Needed?
+
+namespace orxonox
+{
+
+    SetConsoleCommand("printScreenHD", &ScreenshotManager::makeScreenshot_s);
+    
+    ManageScopedSingleton(ScreenshotManager, ScopeID::GRAPHICS, false);
+
+    RegisterAbstractClass(ScreenshotManager).inheritsFrom<Configurable>();
+
+    /**
+    @brief
+        Constructor. 
+    */
+    ScreenshotManager::ScreenshotManager() : finalPicturePB_(nullptr), data_(nullptr)
+    {
+        RegisterObject(ScreenshotManager);
+        
+        this->setConfigValues();
+
+        // Flag for overlay rendering
+        this->disableOverlays_ = true;
+    }
+
+    ScreenshotManager::~ScreenshotManager()
+    {
+        this->cleanup();
+    }
+
+    /**
+    @brief
+        Frees used memory.
+    */
+    void ScreenshotManager::cleanup(void)
+    {
+        if(this->finalPicturePB_ != nullptr)
+        {
+            delete this->finalPicturePB_;
+            this->finalPicturePB_ = nullptr;
+        }
+        if(this->data_ != nullptr)
+        {
+            delete this->data_;
+            this->data_ = nullptr;
+        }
+        if(!this->tempTexture_.isNull())
+            this->tempTexture_.freeMethod();
+    }
+    
+    /**
+    @brief
+        Sets some config values.
+    */
+    void ScreenshotManager::setConfigValues(void)
+    {
+        // Set file extension for the Screenshot files.
+        SetConfigValue(fileExtension_, ".png");
+        // The grid size.
+        SetConfigValue(gridSize_, 3);
+    }
+
+    /**
+    @brief
+        Update internal parameters.
+    */
+    void ScreenshotManager::update(void)
+    {
+        Ogre::RenderWindow* pRenderWindow = GraphicsManager::getInstance().getRenderWindow();
+
+        // Update current window size
+        this->windowWidth_   = pRenderWindow->getWidth();
+        this->windowHeight_  = pRenderWindow->getHeight();
+
+        // Create temporary texture
+        this->tempTexture_ = Ogre::TextureManager::getSingleton().createManual("ScreenShotTex", Resource::getDefaultResourceGroup(), Ogre::TEX_TYPE_2D, this->windowWidth_, this->windowHeight_, 0, Ogre::PF_B8G8R8, Ogre::TU_RENDERTARGET);
+
+        // Get the current render target of the temporary texture
+        this->renderTarget_ = this->tempTexture_->getBuffer()->getRenderTarget();
+
+        // HardwarePixelBufferSharedPtr to the buffer of the temporary texture
+        this->buffer_ = this->tempTexture_->getBuffer();
+
+        // Create PixelBox
+        this->data_ = new uint8_t[(this->windowWidth_ * this->gridSize_) * (this->windowHeight_ * this->gridSize_) * 3];
+        this->finalPicturePB_ = new Ogre::PixelBox(this->windowWidth_ * this->gridSize_, this->windowHeight_ * this->gridSize_, 1, Ogre::PF_B8G8R8, this->data_);
+    }
+
+    /**
+    @brief
+        Make a screenshot.
+        The screenshot is saved in the log folder.
+    */
+    void ScreenshotManager::makeScreenshot()
+    {
+        // Get the screenshot.
+        Ogre::Image* finalImage = getScreenshot();
+        if(finalImage != nullptr)
+        {
+            // Save it.
+            finalImage->save(ConfigurablePaths::getLogPathString() + "screenshot_" + getTimestamp() + this->fileExtension_);
+            delete finalImage;
+            orxout(user_info) << "Finished taking " << this->gridSize_*this->windowWidth_ << "x" << this->gridSize_*this->windowHeight_ << " pixel HD screenshot. Storing in log/." << endl;
+        }
+        else
+            orxout(user_error) << "There needs to be an active camera to make screenshots." << endl;
+
+        this->cleanup();
+    }
+
+    /**
+    @brief
+        Creates a screenshot and returns it.
+        After calling this method the ScreenshotManager should be cleaned using cleanup().
+    @return
+        Returns a pointer to an Ogre::Image with the screenshot. The memory must be freed, when the image is no longer needed.
+    */
+    Ogre::Image* ScreenshotManager::getScreenshot()
+    {
+        if(CameraManager::getInstance().getActiveCamera() == nullptr )
+            return nullptr;
+        return this->getScreenshot(CameraManager::getInstance().getActiveCamera()->getOgreCamera());
+    }
+
+    /**
+    @brief
+        Creates a screenshot with the given camera and returns it.
+        After calling this method the ScreenshotManager should be cleaned using cleanup().
+    @param camera
+        A pointer to the camera the screenshot should be taken with.
+    @return
+        Returns a pointer to an Ogre::Image with the screenshot. The memory must be freed, when the image is no longer needed.
+    */
+    Ogre::Image* ScreenshotManager::getScreenshot(Ogre::Camera* camera)
+    {
+        if(camera == nullptr)
+            return nullptr;
+        
+        // Update the internal parameters.
+        this->update();
+
+        // Add the camera as viewport.
+        this->renderTarget_->removeAllViewports();
+        this->renderTarget_->addViewport(camera);
+
+        // Set the viewport settings
+        Ogre::Viewport *vp = renderTarget_->getViewport(0);
+        vp->setClearEveryFrame(true);
+        vp->setOverlaysEnabled(false);
+
+        // Remind current overlay flag
+        bool enableOverlayFlag = GraphicsManager::getInstance().getViewport()->getOverlaysEnabled();
+        
+        // We disable overlay rendering if it is set in config file and the viewport setting is enabled
+        if(this->disableOverlays_ && enableOverlayFlag)
+            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(false);
+        
+        Ogre::Image* finalImage = new Ogre::Image();
+        
+        if(this->gridSize_ <= 1)
+        {
+            // Simple case where the contents of the screen are taken directly
+            // Also used when an invalid value is passed within gridSize (zero or negative grid size)
+            this->renderTarget_->update(); // Render
+
+            this->buffer_->blitToMemory(*this->finalPicturePB_);
+            finalImage->loadDynamicImage(static_cast<unsigned char*>(finalPicturePB_->data), finalPicturePB_->getWidth(), finalPicturePB_->getHeight(),Ogre::PF_B8G8R8);
+        }
+        else
+        {
+            // Define the original frustum extents variables
+            Ogre::Real originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom;
+            // Set the original Frustum extents
+            camera->getFrustumExtents(originalFrustumLeft, originalFrustumRight, originalFrustumTop, originalFrustumBottom);
+            
+            // Compute the Stepsize for the grid
+            Ogre::Real frustumGridStepHorizontal  = (originalFrustumRight * 2) / this->gridSize_;
+            Ogre::Real frustumGridStepVertical  = (originalFrustumTop * 2) / this->gridSize_;
+            
+            // Process each grid
+            Ogre::Real frustumLeft, frustumRight, frustumTop, frustumBottom;
+            for (unsigned int nbScreenshots = 0; nbScreenshots < this->gridSize_ * this->gridSize_; nbScreenshots++)
+            {
+                int y = nbScreenshots / this->gridSize_;
+                int x = nbScreenshots - y * this->gridSize_;
+                
+                // Shoggoth frustum extents setting
+                // Compute the new frustum extents
+                frustumLeft    = originalFrustumLeft + frustumGridStepHorizontal * x;
+                frustumRight  = frustumLeft + frustumGridStepHorizontal;
+                frustumTop    = originalFrustumTop - frustumGridStepVertical * y;
+                frustumBottom  = frustumTop - frustumGridStepVertical;
+                
+                // Set the frustum extents value to the camera
+                camera->setFrustumExtents(frustumLeft, frustumRight, frustumTop, frustumBottom);
+                
+                // Ignore time duration between frames
+                Ogre::Root::getSingletonPtr()->clearEventTimes();
+                this->renderTarget_->update(); // Render
+                
+                // Define the current box
+                Ogre::Box subBox = Ogre::Box(x* this->windowWidth_,y * this->windowHeight_,x * this->windowWidth_ + this->windowWidth_, y * this->windowHeight_ + this->windowHeight_);
+                // Copy the content from the temp buffer into the final picture PixelBox
+                // Place the tempBuffer content at the right position
+                this->buffer_->blitToMemory(this->finalPicturePB_->getSubVolume(subBox));
+                
+                orxout(internal_info) << "Created screenshot number " << nbScreenshots << " for multi grid HD screenshot." << endl;
+                
+            }
+            
+            // Set frustum extents to previous settings
+            camera->resetFrustumExtents();
+            
+            // Insert the PixelBox data into the Image Object
+            finalImage->loadDynamicImage(static_cast<unsigned char*>(this->finalPicturePB_->data), this->finalPicturePB_->getWidth(), this->finalPicturePB_->getHeight(), 1, Ogre::PF_B8G8R8, false);
+        }
+        
+        // Do we have to re-enable our overlays?
+        if(enableOverlayFlag)
+            GraphicsManager::getInstance().getViewport()->setOverlaysEnabled(true);
+        
+        // Reset time since last frame to pause the scene
+        Ogre::Root::getSingletonPtr()->clearEventTimes();
+        
+        return finalImage;
+    }
+
+    /**
+    @brief
+        Set the size of the grid.
+    @param size
+        The size of the grid.
+    */
+    void ScreenshotManager::setGridSize(unsigned int size)
+    {
+        if(size == this->gridSize_)
+            return;
+
+        this->gridSize_ = size;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/designtools/ScreenshotManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/ScreenshotManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/ScreenshotManager.h	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      This code comes from http://www.ogre3d.org/tikiwiki/High+resolution+screenshots which is Public Domain.
+ *   Co-authors:
+ *      Oli Scheuss
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+   @file ScreenshotManager.h
+   @brief Definition of the ScreenshotManager class.
+   @ingroup Designtools
+*/
+
+#ifndef __ScreenshotManager_h__
+#define __ScreenshotManager_h__
+
+#include "DesignToolsPrereqs.h"
+
+#include <OgrePrerequisites.h>
+#include <OgreTexture.h>
+#include <OgreHardwarePixelBuffer.h>
+
+#include "util/Singleton.h"
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Class encapsulates screenshot functionality and provides a method for making multi grid (i.e. HD) screenshots.
+        
+    @author
+        This code comes from http://www.ogre3d.org/tikiwiki/High+resolution+screenshots which is Public Domain.
+    @author
+        Oli Scheuss
+    @author
+        Damian 'Mozork' Frick
+    @ingroup Designtools
+    */
+    class ScreenshotManager : public Configurable, public Singleton<ScreenshotManager>
+    {
+        friend class Singleton<ScreenshotManager>;
+
+        public:
+            ScreenshotManager();
+            virtual ~ScreenshotManager();
+            void setConfigValues(void); // Sets some config values.
+
+            void makeScreenshot(); // Make a screenshot.
+            Ogre::Image* getScreenshot(); // Creates a screenshot and returns it.
+            Ogre::Image* getScreenshot(Ogre::Camera* camera); // Creates a screenshot with the given camera and returns it.
+
+            /**
+            @brief Creates a screenshot.
+            */
+            static void makeScreenshot_s()
+                { ScreenshotManager::getInstance().makeScreenshot(); }
+
+            void setGridSize(unsigned int size); // Set the size of the grid.
+            /**
+            @brief Get the current grid size.
+            @return Returns the size of the grid.
+            */
+            inline unsigned int getGridSize(void)
+                { return this->gridSize_; }
+
+            void cleanup(void); // Frees used memory.
+            
+        protected:
+            void update(void); // Update internal parameters.
+            
+            static ScreenshotManager* singletonPtr_s;
+
+            std::string fileExtension_; //!< The image extension used to save the screenshot.
+            unsigned int gridSize_; //!< The magnification factor.  A 2 will create a 2x2 grid, doubling the size of the screenshot.  A 3 will create a 3x3 grid, tripling the size of the screenshot.
+            unsigned int windowWidth_, windowHeight_; //!< The width and height of the window.
+            bool disableOverlays_; //!< Whether overlays should be disabled.
+
+            Ogre::TexturePtr tempTexture_; //!< Temporary texture with current screen size.
+            Ogre::RenderTexture* renderTarget_; //!< Render target for the temporary texture.
+            Ogre::HardwarePixelBufferSharedPtr buffer_; //!< Buffer for the temporary texture.
+            
+            Ogre::PixelBox* finalPicturePB_; //!< PixelBox for large screenshots, contains the screenshot for gridSize_ > 1.
+            uint8_t* data_; //!< Data pointer for the PixelBox.
+
+    };
+
+}
+
+#endif  // __ScreenshotManager_h__
Index: /code/branches/RacingBots_FS18/src/modules/designtools/SkyboxGenerator.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/SkyboxGenerator.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/SkyboxGenerator.cc	(revision 11817)
@@ -0,0 +1,321 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gion-Andri Cantieni
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file SkyboxGenerator.cc
+    @brief Implementation of the SkyboxGenerator class.
+*/
+
+#include "SkyboxGenerator.h"
+
+#include <string>
+#include <OgreRenderWindow.h>
+#include <OgreCamera.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GraphicsManager.h"
+#include "core/ConfigurablePaths.h"
+#include "core/Resource.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/command/CommandExecutor.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+#include "controllers/HumanController.h"
+#include "graphics/Camera.h"
+#include "worldentities/ControllableEntity.h"
+
+#include "ScreenshotManager.h"
+
+// #include <X11/Xlib.h> TODO: Needed?
+
+namespace orxonox
+{
+
+    SetConsoleCommand("SkyboxGenerator", "createSkybox", &SkyboxGenerator::createSkybox).addShortcut();
+
+    ManageScopedSingleton(SkyboxGenerator, ScopeID::GRAPHICS, false);
+
+    RegisterAbstractClass(SkyboxGenerator).inheritsFrom<Configurable>().inheritsFrom<Tickable>();
+
+    /**
+    @brief
+        Constructor. Registers and initializes the singleton.
+    */
+    SkyboxGenerator::SkyboxGenerator()
+    {
+        RegisterObject(SkyboxGenerator);
+
+        this->setConfigValues();
+        
+        this->bGenerateSkybox_ = false;
+        this->bCaptionsRemoved_ = false;
+        this->bSetup_ = true;
+        this->bWait_ = false;
+        this->bCreateFace_ = true;
+        this->bCleanup_ = true;
+        this->faceCounter_ = 0;
+        
+        this->names_.emplace_back("fr");
+        this->names_.emplace_back("lf");
+        this->names_.emplace_back("bk");
+        this->names_.emplace_back("rt");
+        this->names_.emplace_back("up");
+        this->names_.emplace_back("dn");
+        
+        this->rotations_.emplace_back(90, 0);
+        this->rotations_.emplace_back(90, 0);
+        this->rotations_.emplace_back(90, 0);
+        this->rotations_.emplace_back(90, 90);
+        this->rotations_.emplace_back(0, 180);
+        this->rotations_.emplace_back(0, 90);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    SkyboxGenerator::~SkyboxGenerator()
+    {
+
+    }
+
+    /**
+    @brief
+        Sets some config values.
+    */
+    void SkyboxGenerator::setConfigValues( )
+    {
+        SetConfigValue(skyboxPrefix_, "SkyboxFile_");
+        SetConfigValue(imageExtension_, ".png");
+        SetConfigValue(size_, 1024);
+    }
+    
+    /**
+    @brief
+        Generate the 6 faces of a skybox.
+    */
+    void SkyboxGenerator::createSkybox()
+    {
+        // Pause
+        CommandExecutor::execute("pause");
+        // Start the skybox generation process.
+        SkyboxGenerator::getInstance().startSkyboxGeneration();
+    }
+
+    /**
+    @brief
+        This is where the skybox generation happens.
+        Generating a skybox takes several (up to 10) ticks.
+    */
+    void SkyboxGenerator::tick(float dt)
+    {
+        // Whether a skybox is currently being generated.
+        if(this->bGenerateSkybox_)
+        {
+            // Wait one tick.
+            if(this->bWait_)
+            {
+                this->bWait_ = false;
+                return;
+            }
+
+            ControllableEntity* entity = nullptr;
+            if(HumanController::getLocalControllerSingleton() != nullptr && HumanController::getLocalControllerSingleton()->getControllableEntity() != nullptr)
+                entity = HumanController::getLocalControllerSingleton()->getControllableEntity();
+            else
+            {
+                orxout(user_error) << "You must be in a level to generate a skybox." << endl;
+                this->bGenerateSkybox_ = false;
+                return;
+            }
+            Ogre::Camera* camera = entity->getCamera()->getOgreCamera();
+            Ogre::RenderWindow* renderWindow = GraphicsManager::getInstance().getRenderWindow();
+            
+            // Setup the SkyboxGenerator to generate a skybox.
+            if(this->bSetup_)
+            {
+                // If there are captions being displayed, don't.
+                if(!this->bCaptionsRemoved_)
+                {
+                    CommandExecutor::execute("GametypeStatus displayCaption false");
+                    this->bCaptionsRemoved_ = true;
+                    return;
+                }
+                
+                // Store the settings for the camera.
+                this->fovy_ = camera->getFOVy();
+                this->aspectRatio_ = camera->getAspectRatio();
+                // Setup the render window.
+                this->setupRenderWindow(renderWindow);
+                // Add the log path to the standard resource group.
+                Ogre::ResourceGroupManager::getSingleton().addResourceLocation(ConfigurablePaths::getLogPathString(), "FileSystem", Resource::getDefaultResourceGroup());
+                
+                orxout(internal_status) << "Setting up SkyboxGenerator..." << endl;
+                
+                this->bSetup_ = false;
+                this->bWait_ = true;
+            }
+            // Create one of the faces. (faceCounter_ decides which)
+            else if(this->bCreateFace_)
+            {
+                // Setup the camera.
+                this->setupCamera(camera);
+                // Take the picture using the ScreenshotManager and save it.
+                this->saveImage(ScreenshotManager::getInstance().getScreenshot(camera), this->skyboxPrefix_+this->names_[this->faceCounter_]+this->imageExtension_);
+                // Rotate the camera to be ready for taking the next picture.
+                std::pair<int, int> rotate = this->rotations_[this->faceCounter_];
+                if(rotate.first != 0)
+                    entity->yaw(Degree((float)rotate.first));
+                if(rotate.second != 0)
+                    entity->pitch(Degree((float)rotate.second));
+                
+                orxout(internal_info) << "Created face number " << this->faceCounter_ << "." << endl;
+                // Check whether we've generated all 6 faces.
+                if(++this->faceCounter_ >= 6)
+                    this->bCreateFace_ = false;
+            }
+            // Cleanup after the successful creation of a skybox.
+            else if(this->bCleanup_)
+            {
+                // Reset the camera parameters.
+                camera->setAspectRatio(this->aspectRatio_);
+                camera->setFOVy(this->fovy_);
+                // Restore the render window.
+                this->restoreRenderWindow(renderWindow);
+                // Remove the log path from the standard resource group.
+                Ogre::ResourceGroupManager::getSingleton().removeResourceLocation(ConfigurablePaths::getLogPathString(), Resource::getDefaultResourceGroup());
+                
+                // Reset the flow parameters for the next skybox generation.
+                this->bGenerateSkybox_ = false;
+                this->bSetup_ = true;
+                this->bWait_ = false;
+                this->bCreateFace_ = true;
+                this->bCleanup_ = true;
+                this->faceCounter_ = 0;
+                
+                // Display captions again.
+                CommandExecutor::execute("GametypeStatus displayCaption true");
+                this->bCaptionsRemoved_ = false;
+                
+                // Unpause.
+                CommandExecutor::execute("pause");
+                
+                orxout(user_info) << "Skybox with face size " << this->size_ << "x" << this->size_ << " pixels created. Storing in log/." << endl;
+            }
+        }
+    }
+    
+    /**
+    @brief
+        Set up the input camera to be ready to generate a skybox face.
+    @param camera
+        The camera to be set up.
+    */
+    void SkyboxGenerator::setupCamera(Ogre::Camera* camera)
+    {
+        camera->setFOVy(Degree(90));
+        camera->setAspectRatio(1.0);
+    }
+    
+    /**
+    @brief
+        Setup the input render window to be ready to generate the skybox.
+    @param renderWindow
+        The render window to be set up.
+    */
+    void SkyboxGenerator::setupRenderWindow(Ogre::RenderWindow* renderWindow)
+    {
+        // Store current window properties.
+        this->windowWidth_ = renderWindow->getWidth();
+        this->windowHeight_ = renderWindow->getHeight();
+        this->windowFullScreen_ = renderWindow->isFullScreen();
+        // Store current ScreenshotManager grid size.
+        this->gridSize_ = ScreenshotManager::getInstance().getGridSize();
+        
+        unsigned int size = this->size_;
+        
+        // If the desired skybox face size is bigger than what the current render window can accommodate we find a size that is a multiple of 256, that fits into the current render window adjust the grid size of the ScreenshotManager such that the screenshots generated are at least as big as we need. 
+        if(this->windowHeight_ < this->size_ || this->windowWidth_ < this->size_)
+        {
+            unsigned int min = std::min(this->windowHeight_, this->windowWidth_);
+            unsigned int step = 256;
+            assert(min >= step);
+            size = step;
+            while(min >= size+step)
+                size += step;
+            
+            unsigned int gridSize = 1;
+            while(gridSize*size < this->size_)
+                gridSize++;
+            
+            renderWindow->setFullscreen(false, size, size);
+            ScreenshotManager::getInstance().setGridSize(gridSize);
+        }
+        else
+            ScreenshotManager::getInstance().setGridSize(1);
+
+    }
+    
+    /**
+    @brief
+        Restore the render window.
+        Reset the window size, reset the grid size of the ScreenshotManager.
+    @param renderWindow
+        The render window to be restored.
+    */
+    void SkyboxGenerator::restoreRenderWindow(Ogre::RenderWindow* renderWindow)
+    {
+        // Restore window size.
+        renderWindow->setFullscreen(this->windowFullScreen_, this->windowWidth_, this->windowHeight_);
+        // Restore grid size.
+        ScreenshotManager::getInstance().setGridSize(this->gridSize_);
+    }
+    
+    /**
+    @brief
+        Resizes and saves the input image under the input name.
+    @param image
+        A pointer to the image to be saved. The image is deleted afterwards,
+    @param name
+        The desired filename of the image.
+    */
+    void SkyboxGenerator::saveImage(Ogre::Image* image, const std::string& name) const
+    {
+        image->save(ConfigurablePaths::getLogPathString()+name);
+        delete image;
+        // Loading the resizing, then saving again. This seems stupid, but resizing doesn't seem to work otherwise.
+        // If someone figures this out, feel free to adjust.
+        image = new Ogre::Image();
+        image->load(name, Resource::getDefaultResourceGroup());
+        image->resize(this->size_, this->size_);
+        image->save(ConfigurablePaths::getLogPathString()+name);
+        delete image;
+        ScreenshotManager::getInstance().cleanup(); // Free memory in ScreenshotManager.
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/designtools/SkyboxGenerator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/designtools/SkyboxGenerator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/designtools/SkyboxGenerator.h	(revision 11817)
@@ -0,0 +1,121 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gion-Andri Cantieni
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file SkyboxGenerator.h
+    @brief Definition of the SkyboxGenerator class.
+    @ingroup Designtools
+*/
+
+#ifndef __SkyboxGenerator_h__
+#define __SkyboxGenerator_h__
+
+#include "core/config/Configurable.h"
+#include "util/Singleton.h"
+#include "tools/interfaces/Tickable.h"
+
+#include <OgreMath.h>
+
+namespace orxonox
+{
+    
+    /**
+    @brief
+        The SkyboxGenerator class is a singleton that allows for the creation of a skybox from a level by taking pictures to all 6 sides.
+        The 6 images created by the createSkybox() method are placed in the log folder in your build directory.
+        
+        The image filename prefix and the file extension can both be adjusted as config values, so can the desired size of the skybox faces.
+        
+    @author
+        Gion-Andri Cantieni
+    @author
+        Damian 'Mozork' Frick
+    @ingroup Designtools
+    */
+    class SkyboxGenerator : public virtual Configurable, public Singleton<SkyboxGenerator>, public Tickable
+    {
+        friend class Singleton<SkyboxGenerator>;
+
+        public:
+            SkyboxGenerator();
+            virtual ~SkyboxGenerator();
+            virtual void tick(float dt) override; // This is where the skybox generation happens.
+            static void createSkybox(void); // Generate the 6 faces of a skybox.
+            void setConfigValues(void); // Sets some config values.
+            
+            /**
+            @brief Set the size of the skybox faces to be generated.
+            @param size The size in pixels.
+            */
+            inline void setSize(unsigned int size)
+                { this->size_ = size; }
+                
+        protected:
+            /**
+            @brief Starts the generation of the skybox.
+            */
+            inline void startSkyboxGeneration(void)
+                { this->bGenerateSkybox_ = true; }
+
+        private:
+            void setupCamera(Ogre::Camera* camera); // Set up the input camera to be ready to generate a skybox face.
+            void setupRenderWindow(Ogre::RenderWindow* renderWindow); // Setup the input render window to be ready to generate the skybox.
+            void restoreRenderWindow(Ogre::RenderWindow* renderWindow); // Restore the render window.
+
+            void saveImage(Ogre::Image* image, const std::string& name) const;
+            
+            static SkyboxGenerator* singletonPtr_s; //!< Singleton pointer.
+            
+            unsigned int size_; //!< The desired size of the skybox faces.
+            std::string skyboxPrefix_; //!< Prefix for the generated image files.
+            std::string imageExtension_; //!< Extension of the generated image files.
+            
+            // FLow control variables
+            bool bGenerateSkybox_; //!< Whether a skybox is currently being generated.
+            bool bCaptionsRemoved_; //!< Whether the overlays have been removed.
+            bool bSetup_; //!< Whether the render window is being setup.
+            bool bWait_; //!< Whether we have to wait for the setup to take effect.
+            bool bCreateFace_; //!< Whether the faces are being created,
+            unsigned int faceCounter_; //!< Counter to keep track of which skybox face is being created.
+            bool bCleanup_; //!< Whether the generator is being cleaned up.
+            
+            std::vector<std::string> names_; //!< The names of the image files for the skybox faces to be generated.
+            std::vector< std::pair<int, int>> rotations_; //!< The rotation in yaw an pitch direction that is applied to the camera after a specific face has been generated.
+            
+            // Storage variables
+            float aspectRatio_; //!< The backed up aspect ratio of the camera.
+            Ogre::Radian fovy_; //!< The backed up field of view of the camera.
+            unsigned int windowWidth_; //!< The backed up window width.
+            unsigned int windowHeight_; //!< The backed up window height.
+            bool windowFullScreen_; //!< Whether the window was in fullscreen mode.
+            unsigned int gridSize_; //!< The backed up grid size of the ScreenshotManager.
+
+    };
+}
+
+#endif  // __SkyboxGenerator_h__
Index: /code/branches/RacingBots_FS18/src/modules/dialog/Answer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/Answer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/Answer.cc	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Answer.h"
+#include "core/CoreIncludes.h"
+
+
+namespace orxonox{
+
+    RegisterClass(Answer);
+
+
+    // Constructor:
+    Answer::Answer(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Answer);
+    }
+
+    void Answer::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Answer, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Answer, "Id", setAnswerId, getAnswerId, xmlelement, mode);
+        XMLPortParam(Answer, "answer", setAnswer, getAnswer, xmlelement, mode);
+        XMLPortParam(Answer, "nextQuestionId", setNextQuestion, getNextQuestion, xmlelement,mode);
+    }
+
+    void Answer::setAnswerId(const std::string& answerId){
+        this->answerId_ = answerId;
+    }
+
+    const std::string& Answer::getAnswerId() const
+    {
+        return this->answerId_;
+    }
+
+    void Answer::setNextQuestion(const std::string& nextId)
+    {
+        this->nextQuestionId_ = nextId;
+    }
+
+    const std::string& Answer::getNextQuestion() const
+    {
+        return this->nextQuestionId_;
+    }
+
+    void Answer::setAnswer(const std::string& answer)
+    {
+        this->answer_ = answer;
+    }
+
+    const std::string& Answer::getAnswer() const
+    {
+        return this->answer_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dialog/Answer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/Answer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/Answer.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Answer_H__
+#define _Answer_H__
+
+#include "core/BaseObject.h"
+#include "DialogPrereqs.h"
+#include "core/XMLPort.h"
+#include "core/CoreIncludes.h"
+#include <string>
+
+namespace orxonox
+{
+    /**
+    @brief
+    class containing the pc side of the Dialog
+
+    this class contains one possible text option of the pc, it's id and the id of the reaction of the npc to this answer
+    */
+
+    class _DialogExport Answer : public BaseObject
+    {
+        public:
+            Answer(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            void setAnswerId(const std::string& answerId); //xmlPort-Funktion, setzt AntwortId
+            const std::string& getAnswerId() const; //xmlPort-Funktion, gibt AntwortId
+
+            void setNextQuestion(const std::string& nextId); //xmlPort-Funktion, um Dialog zu beenden tag benutzen der von keiner Frage benutzt wird
+            const std::string& getNextQuestion() const; //xmlPort-Funktion, gibt Id der Folgefrage
+
+            void setAnswer(const std::string& awns); //xmlPort-Funktion, setzt Antworttext
+            const std::string& getAnswer() const; //xmlPort-Funktion, gibt Antworttext
+
+        private:
+            std::string answerId_;  //!< id of the pc textoption
+            std::string answer_;    //!< string with the pc text
+            std::string nextQuestionId_; //!< id of the npc reaction to pc answer
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/dialog/AnswerId.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/AnswerId.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/AnswerId.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "AnswerId.h"
+#include "core/CoreIncludes.h"
+
+
+namespace orxonox{
+
+    RegisterClass(AnswerId);
+
+    AnswerId::AnswerId(Context* context) : BaseObject(context)
+    {
+        RegisterObject(AnswerId);
+    }
+
+    void AnswerId::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(AnswerId, XMLPort, xmlelement, mode);
+
+        XMLPortParam(AnswerId, "Id", setId, getId, xmlelement, mode);
+    }
+
+    void AnswerId::setId(const std::string& id)
+    {
+        this->id_ = id;
+    }
+
+    const std::string& AnswerId::getId() const
+    {
+        return this->id_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dialog/AnswerId.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/AnswerId.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/AnswerId.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _AnswerID_H__
+#define _AnswerID_H__
+
+#include "DialogPrereqs.h"
+#include "core/XMLPort.h"
+#include "core/BaseObject.h"
+#include "core/CoreIncludes.h"
+
+#include <string>
+
+namespace orxonox{
+
+    /**
+    @brief
+    container class for answerids in xml
+
+    */
+
+    class _DialogExport AnswerId : public BaseObject
+    {
+        public:
+            AnswerId(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            void setId(const std::string& Id);  //allows to set Id, only use in xmlPort for initializing AnswerIds in lvl files
+            const std::string& getId() const;   //allows to get Id, used in xmlPort
+
+        private:
+            std::string id_;    //!< id of one answer
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/dialog/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,17 @@
+SET_SOURCE_FILES(DIALOG_SRC_FILES
+  DialogManager.cc
+  Dialog.cc
+  Question.cc
+  Answer.cc
+  AnswerId.cc
+)
+
+ORXONOX_ADD_LIBRARY(dialog
+  MODULE
+  FIND_HEADER_FILES
+   TOLUA_FILES
+   DialogManager.h
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${DIALOG_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/dialog/Dialog.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/Dialog.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/Dialog.cc	(revision 11817)
@@ -0,0 +1,164 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DialogManager.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/EventIncludes.h"
+#include "Dialog.h"
+#include "Question.h"
+
+
+namespace orxonox
+{
+
+    RegisterClass(Dialog);
+
+    //Constructor:
+    Dialog::Dialog(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Dialog);
+    }
+
+    void Dialog::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Dialog, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Dialog, "name", setName, getName, xmlelement, mode);
+        XMLPortParam(Dialog, "currentQuestionId", setCurrentQuestionId, getCurrentQuestionId, xmlelement, mode);
+        XMLPortObject(Dialog, Question, "questions", addQuestion, getQuestion, xmlelement, mode);
+        XMLPortObject(Dialog, Answer, "answers", addAnswer, getAnswer, xmlelement, mode);
+    }
+
+    void Dialog::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Dialog, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventSink(Dialog, BaseObject, "execute", execute, xmlelement, mode); 
+    }
+
+    void Dialog::setName(const std::string& name)
+    {
+        this->name_ = name;
+    }
+
+    const std::string& Dialog::getName() const
+    {
+        return this->name_;
+    }
+
+    void Dialog::setCurrentQuestionId(const std::string& questionId)
+    {
+        this->currentQuestionId_ = questionId;
+    }
+
+    const std::string& Dialog::getCurrentQuestionId() const
+    {
+        return this->currentQuestionId_;
+    }
+
+
+    void Dialog::addQuestion(Question* question) //fuegt Question der Map hinzu
+    {
+        this->questions_.insert(make_pair(question->getQuestionId(), question));
+    }
+
+    Question* Dialog::getQuestion(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (auto entry : this->questions_)
+        {
+            if (i == index)
+                return entry.second;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    void Dialog::addAnswer(Answer* answer) //fuegt Answer der Map hinzu
+    {
+        this->answers_.insert(make_pair(answer->getAnswerId(), answer));
+    }
+
+    Answer* Dialog::getAnswer(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (auto entry : this->answers_)
+        {
+            if (i == index)
+                return entry.second;
+            ++i;
+        }
+        return nullptr;
+    }
+
+
+    const std::vector<std::string>& Dialog::getAnswerIds() const // returned vector mit allen momentanen AntwortenIds
+    {
+
+        Question* question = (this->questions_.find(this->currentQuestionId_))->second;
+        return question->getAnswerIds();
+
+    }
+
+    bool Dialog::execute(bool bTriggered, BaseObject* trigger)
+    {  
+        DialogManager& m = DialogManager::getInstance();
+
+        if(questions_.count(this->currentQuestionId_)){
+            m.setDialog(this);
+            OrxonoxOverlay::showOverlay("Dialog");
+        }
+        else {
+            orxout() << "no start defined " << endl;
+        }
+
+        return false;
+    }
+
+    void Dialog::update(const std::string& givenAnswerId)
+    {
+        Answer* answer = (answers_.find(givenAnswerId))->second;
+        this->currentQuestionId_ = answer->getNextQuestion();
+    }
+
+    bool Dialog::ending(const std::string& givenAnswerId)
+    {
+        return !this->questions_.count(this->answers_.find(givenAnswerId)->second->getNextQuestion());
+    }
+
+    const std::string& Dialog::getQuestionString()
+    {
+        return this->questions_.find(this->currentQuestionId_)->second->getQuestion();
+    }
+
+    const std::string& Dialog::getAnswerString(const std::string& answerId)
+    {
+        return this->answers_.find(answerId)->second->getAnswer();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dialog/Dialog.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/Dialog.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/Dialog.h	(revision 11817)
@@ -0,0 +1,145 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Dialog_H__
+#define _Dialog_H__
+
+#include "core/BaseObject.h"
+#include "DialogPrereqs.h"
+#include "Question.h"
+#include "Answer.h"
+#include "core/XMLPort.h"
+#include "core/CoreIncludes.h"
+#include "overlays/OrxonoxOverlay.h"
+
+#include <map>
+#include <vector>
+#include <string>
+
+namespace orxonox
+{
+    /**
+    @brief
+    class containing core of one dialog with one npc
+
+    this class contains a map of all answerids to answers (player text options) and one of all questionids to questions (npc text options)
+    it realizes a state machine with the question beeing the states and the answers beeing the connections, it has a current state and
+    can be commanded to go to the next state according to a given answer
+    */
+
+    class _DialogExport Dialog : public BaseObject
+    {
+        public:
+            Dialog(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+
+            void setName(const std::string& name); //xmlPort-Funktion, sets Namen
+            const std::string& getName() const; //xmlPort-Funktion, returns Namen
+
+            void setCurrentQuestionId(const std::string& questionId); //xmlPort-Funktion, sets string id of current question
+            const std::string& getCurrentQuestionId() const; //xmlPort-Funktion, returns id of current question
+
+            void addQuestion(Question* question); //xmlPort-Funktion, adds question to map
+            Question* getQuestion(unsigned int index) const; //xmlPort-Funktion
+
+            void addAnswer(Answer* answer); //xmlPort-Funktion, adds answer to map
+            Answer* getAnswer(unsigned int index) const; //xmlPort-Funktion
+
+            /**
+            @brief
+                returns a pointer to the array of answers belonging to the current question for use in dialogManager
+
+            @return
+                pointer to answerId array of question
+            */
+            const std::vector<std::string>& getAnswerIds() const;
+
+            /**
+            @brief
+                function called when the trigger object defined in the xml file sets to triggered
+
+            @param bTriggered
+                needs to be set like this for correctness
+            @param trigger
+                needs to be set like this for correctness
+            @return
+                not really used
+            */
+            bool execute(bool bTriggered, BaseObject* trigger);
+
+            /**
+            @brief
+                updates the current Dialog according to the id of a given answer, by setting currentQuestionId to the next one
+
+            @param givenAnswerId
+                id of the answer given by player
+            */
+            void update(const std::string& givenAnswerId);
+
+            /**
+            @brief
+                tests if there is a next question for the given answerId
+
+            @param givenAnswerId
+                id of the answer given by player
+            @return
+                true if there is no more Question to the given answerId
+            */
+            bool ending(const std::string& givenAnswerId);
+
+            /**
+            @brief
+                gives the text of the npc in the current state
+
+            @return
+                sting with npc text
+            */
+            const std::string& getQuestionString();
+
+            /**
+            @brief
+                returns a sting with the pc answer to the id
+
+            @param answerId
+                the id of the answer looked for
+            @return
+                sting with answer
+            */
+            const std::string& getAnswerString(const std::string& answerId);
+
+        private:
+            std::string name_; //!< name of the npc talking
+            std::string currentQuestionId_; //!< id of the npc question currently active
+            std::map<std::string, Question*> questions_; //!< a map form the ids of npc textoptions to the objects containing them
+            std::map<std::string, Answer*> answers_; //!< a map form the ids of npc textoptions to the objects containing them
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/dialog/DialogManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/DialogManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/DialogManager.cc	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DialogManager.h"
+#include "core/CoreIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include <string>
+
+namespace orxonox {
+    ManageScopedSingleton(DialogManager, ScopeID::ROOT, false);
+
+
+
+    DialogManager::DialogManager()
+    {
+        this->currentTalk_ = nullptr;
+        this->answerIds_ = nullptr;
+    }
+
+    void DialogManager::setDialog(Dialog* dialog)
+    {
+        this->currentTalk_ = dialog;
+        this->answerIds_ = &this->currentTalk_->getAnswerIds();
+    }
+
+    //from here onward funcionality for lua axports
+
+    std::string DialogManager::getQuestion()
+    {
+        return this->currentTalk_->getQuestionString();
+    }
+
+    int DialogManager::getSize()
+    {   
+        return this->answerIds_->size();
+    }
+
+    std::string DialogManager::getAnswer(int index)
+    {
+        return this->currentTalk_->getAnswerString(this->answerIds_->at(index));
+    }
+
+    std::string DialogManager::getPerson()
+    {
+        return this->currentTalk_->getName();
+    }
+
+    bool DialogManager::endtest(int index)
+    {   
+        if(this->answerIds_->empty())
+        {
+            return true;
+        }
+        else 
+        {
+            return this->currentTalk_->ending(this->answerIds_->at(index));
+        }
+
+    }
+
+    void DialogManager::update(int index)
+    {
+        this->currentTalk_->update(this->answerIds_->at(index));
+        this->answerIds_ = &this->currentTalk_->getAnswerIds();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dialog/DialogManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/DialogManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/DialogManager.h	(revision 11817)
@@ -0,0 +1,156 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DialogManager_H__
+#define _DialogManager_H__
+
+#include "DialogPrereqs.h"
+#include "util/Singleton.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/object/Listable.h"
+#include "Dialog.h"
+
+#include <string>
+
+namespace orxonox //tolua_export
+
+{//tolua_export
+
+    /**
+    @brief
+    this class is used for calling on a dialog form luascript
+
+    the class is the interface of dialog to lua, all lua functionallity is given by this class, it can be found by lua due to singleton definition
+
+    @todo 
+        reseting or setting new start for dialog on exit, to allow coming back to a npc
+        picture of person
+        parameters to differ dialog depending on some world values, like items, completed objectives etc...
+    */
+
+    class _DialogExport DialogManager //tolua_export
+    : public Singleton<DialogManager>
+    {//tolua_export
+        friend class Singleton<DialogManager>;
+    
+        public:
+        
+        DialogManager(); 
+
+        /**
+        @brief
+            gives the pointer to the sigleton dialog manager to the lua script
+
+        @return
+            returns pointer
+        */
+
+        static DialogManager& getInstance() { return Singleton<DialogManager>::getInstance(); } //tolua_export
+
+        /**
+        @brief
+            allows to set the current dialog
+
+            this is used by a dialog when triggered to set its self to the current dialog
+
+        @param dialog
+            pointer to the dialog that wants to be current one
+        */
+        void setDialog(Dialog* dialog);
+
+        //from here on functions for lua interface
+
+        /**
+        @brief
+            gives the string of the momentary npc textoption
+
+        @return
+            string of npc text
+        */
+        std::string getQuestion(); //tolua_export
+
+        /**
+        @brief
+            function that returns size of answerid array
+
+        @return
+            returns number of possible answers to momentary questions, 0 if there are no player text options
+        */
+        int getSize(); //tolua_export
+
+        /**
+        @brief
+            returns the answer to the id that is at index in the array of answers
+
+        @param param1
+            index of desired answer
+
+        @return
+            string of answer
+        */
+        std::string getAnswer(int index); //tolua_export
+
+        /**
+        @brief
+            gives name of npc the player is currently talking to
+
+        @return
+            sting with name
+        */
+        std::string getPerson(); //tolua_export
+
+        /**
+        @brief
+            tests the dialog if there are any followup npc textoptions to the given answer or if there are no answers to the current question 
+
+        @return
+            true if the answer array of the question is empty or the next question id of the answer does not exist
+        */
+        bool endtest(int index); //tolua_export
+
+        /**
+        @brief
+            tells the dialog to update according to a given answer, if no answer is actively clicked the standard index is sett 0 in the lua
+            when called the current question of the dialog is set to the new one and the answerId vector is set accordingly 
+
+        @param param1
+            index of the answer given by the player
+
+        */
+        void update(int index); //tolua_export
+
+private:
+    static DialogManager* singletonPtr_s;   //!< a pointer to the single class object
+
+    Dialog* currentTalk_;   //!< pointer to the currently active dialog or last active if no one is currently active
+    const std::vector<std::string>* answerIds_; //!< pointer to the possible answerIds of the current question, for faster access
+
+    };//tolua_export
+}//tolua_export
+
+#endif /* _DialogManager_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dialog/DialogPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/DialogPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/DialogPrereqs.h	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _DialogPrereqs_H__
+#define _DialogPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(DIALOG_STATIC_BUILD)
+#  ifdef DIALOG_SHARED_BUILD
+#    define _DialogExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _DialogExport
+#    else
+#      define _DialogExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _DialogPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _DialogExport  __attribute__ ((visibility("default")))
+#  define _DialogPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _DialogExport
+#  define _DialogPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+
+    class DialogManager;
+    class Dialog;
+    class Answer;
+    class Question;
+    class AnswerId;
+   
+}
+
+#endif /* _DialogPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dialog/Question.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/Question.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/Question.cc	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Question.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+
+    RegisterClass(Question);
+
+    Question::Question(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Question);
+    }
+
+    void Question::XMLPort(Element& xmlement, XMLPort::Mode mode)
+    {
+        SUPER(Question, XMLPort, xmlement, mode);
+
+        XMLPortParam(Question, "question", setQuestion, getQuestion, xmlement, mode);
+        XMLPortParam(Question, "Id", setQuestionId, getQuestionId, xmlement, mode);
+
+        XMLPortObject(Question, AnswerId, "answerIds", addAnswerId, getAnswerId, xmlement, mode);
+    }
+
+    void Question::setQuestionId(const std::string& Id)
+    {
+        this->questionId_ = Id;
+    }
+
+    const std::string& Question::getQuestionId() const
+    {
+        return this->questionId_;
+    }
+
+    void Question::setQuestion(const std::string& question)
+    {
+        this->question_ = question;
+    }
+
+    const std::string& Question::getQuestion() const
+    {
+        return this->question_;
+    }
+
+    void Question::addAnswerId(AnswerId* answerId)
+    {
+        this->answerIds_.push_back(answerId->getId());
+    }
+
+    AnswerId* Question::getAnswerId(unsigned int index) const
+    {
+        return nullptr;
+    }
+
+    const std::vector<std::string>& Question::getAnswerIds() const
+    {
+        return this->answerIds_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dialog/Question.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dialog/Question.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dialog/Question.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Question_H__
+#define _Question_H__
+
+#include "core/BaseObject.h"
+#include "DialogPrereqs.h"
+#include "AnswerId.h"
+#include "core/XMLPort.h"
+#include "core/CoreIncludes.h"
+
+
+#include <string>
+
+namespace orxonox
+{
+
+    /**
+    @brief
+    class containing the npc side of the Dialog
+
+    this class contains one possible text option of the npc, it's id and the ids of possible player reactions (answers)
+    */
+
+    class _DialogExport Question : public BaseObject
+    {
+        public:
+            Question(Context* context);
+
+            virtual void XMLPort(Element& xmelement, XMLPort::Mode mode);
+
+            void setQuestionId(const std::string& Id); //xmlPort-Funktion, setzt Id
+            const std::string& getQuestionId() const; //xmlPort-Funktion, gibt Id string zuruek
+
+            void setQuestion(const std::string& question); //xmlPort-Funktion, setzt Fragen string
+            const std::string& getQuestion() const; //xmlPort-Funktion, gibt Fragen string
+
+            void addAnswerId(AnswerId* answerId);  //xmlPort-Funktion, nimmt AnswerIds von entsprechenden Objekten und fuegt sie in List ein.
+            AnswerId* getAnswerId(unsigned int index) const; //xmlPort-Funktion, gibt nichts zuruek
+
+            /**
+            @brief
+                gives pointer to possivle answerIds of this question
+
+            @return
+                returns pointer to the array with ids of possible pc textoptions
+            */
+            const std::vector<std::string>& getAnswerIds() const; //returnt Pointer auf Vektor mit allen Ids
+
+
+
+        private:
+            std::string questionId_; //!< id of npc textoption
+            std::string question_; //!< string with npc text
+            std::vector<std::string> answerIds_; //!< vector with possible player reactions
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/docking/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,21 @@
+SET_SOURCE_FILES(DOCKING_SRC_FILES
+  DockingTarget.cc
+  DockingEffect.cc
+  DockingAnimation.cc
+  DockToShip.cc
+  MoveToDockingTarget.cc
+  DockingController.cc
+  Dock.cc
+)
+
+ORXONOX_ADD_LIBRARY(docking
+  MODULE
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    Dock.h
+  PCH_FILE
+    DockingPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${DOCKING_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/docking/Dock.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/Dock.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/Dock.cc	(revision 11817)
@@ -0,0 +1,356 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Dock.cc
+    @brief Docking system main class
+*/
+
+#include "Dock.h"
+
+#include "core/CoreIncludes.h"
+#include "core/LuaState.h"
+#include "core/GUIManager.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "network/NetworkFunctionIncludes.h"
+
+#include "infos/HumanPlayer.h"
+#include "interfaces/PlayerTrigger.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(Dock);
+
+    SetConsoleCommand("Dock", "dock",    &Dock::cmdDock).addShortcut().setAsInputCommand();
+    SetConsoleCommand("Dock", "undock",  &Dock::cmdUndock).addShortcut().setAsInputCommand();
+
+    registerStaticNetworkFunction(Dock::showDockingDialog);
+
+    Dock::Dock(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Dock);
+    }
+
+    Dock::~Dock()
+    {
+    }
+
+    void Dock::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Dock, XMLPort, xmlelement, mode);
+
+        XMLPortObject(Dock, DockingEffect, "effects", addEffect, getEffect, xmlelement, mode);
+        XMLPortObject(Dock, DockingAnimation, "animations", addAnimation, getAnimation, xmlelement, mode);
+        XMLPortEventSink(Dock, BaseObject, "execute", execute, xmlelement, mode);
+        XMLPortEventSink(Dock, BaseObject, "undocking", undocking, xmlelement, mode);
+
+    }
+
+    void Dock::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Dock, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventSink(Dock, BaseObject, "execute", execute, xmlelement, mode);
+
+        XMLPortEventSink(Dock, BaseObject, "undocking", undocking, xmlelement, mode);
+    }
+
+
+    bool Dock::undocking(bool bTriggered, BaseObject* trigger)
+    {
+
+        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+        PlayerInfo* player = nullptr;
+
+        // Check whether it is a player trigger and extract pawn from it
+        if(pTrigger != nullptr)
+        {
+            if(!pTrigger->isForPlayer()) {  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+            orxout(verbose, context::docking) << "Docking:execute PlayerTrigger was not triggered by a player.." << endl;
+            return false;
+            }
+            player = pTrigger->getTriggeringPlayer();
+        }
+        else
+        {
+            orxout(verbose, context::docking) << "Docking::execute Not a player trigger, can't extract pawn from it.." << endl;
+            return false;
+        }
+        if(player == nullptr)
+        {
+            orxout(verbose, context::docking) << "Docking::execute Can't retrieve PlayerInfo from Trigger. (" << trigger->getIdentifier()->getName() << ")" << endl;
+            return false;
+        }
+
+        if(bTriggered)
+        {
+            // Add player to this Docks candidates
+            candidates_.insert(player);
+
+            // Show docking dialog
+            this->showUndockingDialogHelper(player);
+        }
+        else
+        {
+            // Remove player from candidates list
+            candidates_.erase(player);
+        }
+
+        return true;
+    }
+
+
+
+    bool Dock::execute(bool bTriggered, BaseObject* trigger)
+    {
+        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+        PlayerInfo* player = nullptr;
+
+        // Check whether it is a player trigger and extract pawn from it
+        if(pTrigger != nullptr)
+        {
+            if(!pTrigger->isForPlayer()) {  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+                orxout(verbose, context::docking) << "Docking:execute PlayerTrigger was not triggered by a player.." << endl;
+                return false;
+            }
+            player = pTrigger->getTriggeringPlayer();
+        }
+        else
+        {
+            orxout(verbose, context::docking) << "Docking::execute Not a player trigger, can't extract pawn from it.." << endl;
+            return false;
+        }
+        if(player == nullptr)
+        {
+            orxout(verbose, context::docking) << "Docking::execute Can't retrieve PlayerInfo from Trigger. (" << trigger->getIdentifier()->getName() << ")" << endl;
+            return false;
+        }
+
+        if(bTriggered)
+        {
+            // Add player to this Docks candidates
+            candidates_.insert(player);
+
+            // Show docking dialog
+            this->showDockingDialogHelper(player);
+        }
+        else
+        {
+            // Remove player from candidates list
+            candidates_.erase(player);
+        }
+
+        return true;
+    }
+
+
+    void Dock::showUndockingDialogHelper(PlayerInfo* player)
+        {
+            assert(player);
+
+            if(!player->isHumanPlayer())
+                return;
+
+            if(GameMode::isMaster())
+            {
+                if(GameMode::showsGraphics())
+                    GUIManager::showGUI("UndockingDialog");
+            }
+            else
+                callStaticNetworkFunction(&Dock::showDockingDialog, player->getClientID());
+
+        }
+
+    void Dock::showDockingDialogHelper(PlayerInfo* player)
+    {
+        assert(player);
+        
+        if(!player->isHumanPlayer())
+            return;
+        
+        if(GameMode::isMaster())
+        {
+            if(GameMode::showsGraphics())
+                GUIManager::showGUI("DockingDialog");
+        }
+        else
+            callStaticNetworkFunction(&Dock::showDockingDialog, player->getClientID());
+
+    }
+
+    /*static*/ void Dock::showDockingDialog()
+    {
+        if(GameMode::showsGraphics())
+            GUIManager::showGUI("DockingDialog");
+    }
+
+    void Dock::cmdDock()
+    {
+        PlayerInfo* player = HumanController::getLocalControllerSingleton()->getPlayer();
+        for(Dock* dock : ObjectList<Dock>())
+        {
+            if(dock->dock(player))
+                break;
+        }
+    }
+
+    void Dock::cmdUndock()
+    {
+        PlayerInfo* player = HumanController::getLocalControllerSingleton()->getPlayer();
+        for(Dock* dock : ObjectList<Dock>())
+        {
+            if(dock->undock(player))
+                break;
+        }
+    }
+
+    bool Dock::dock(PlayerInfo* player)
+    {
+        // Check if player is a candidate
+        if(candidates_.find(player) == candidates_.end())
+        {
+            orxout(internal_warning, context::docking) << "Dock::dock Player is not a candidate!" << endl;
+            return false;
+        }
+
+        candidates_.erase(player);
+        docked_.insert(player);
+
+        if (animations_.empty())
+            return dockingAnimationFinished(player);
+
+        else
+            DockingAnimation::invokeAnimation(true, player, animations_);
+
+        return true;
+    }
+
+    bool Dock::dockingAnimationFinished(PlayerInfo* player)
+    {
+        if(docked_.find(player) == docked_.end())
+        {
+            orxout(internal_warning, context::docking) << "Dock::dockingAnimationFinished Player is not currently docked." << endl;
+            return false;
+        }
+
+        DockingEffect::invokeEffect(true, player, effects_);
+        return true;
+    }
+
+    bool Dock::undock(PlayerInfo* player)
+    {
+        // Check if player is docked to this Dock
+        if(docked_.find(player) == docked_.end())
+        {
+            orxout(internal_warning, context::docking) << "Dock::undock Player is not docked to this Dock." << endl;
+            return false;
+        }
+
+        docked_.erase(player);
+        candidates_.insert(player);
+
+        DockingEffect::invokeEffect(false, player, effects_);
+
+        if (animations_.empty())
+            return undockingAnimationFinished(player);
+        else
+            DockingAnimation::invokeAnimation(false, player, animations_);
+
+        return true;
+    }
+
+    bool Dock::undockingAnimationFinished(PlayerInfo* player) {
+        orxout(verbose, context::docking) << "Dock::undockingAnimationFinished executed" << endl;
+        return true;
+    }
+
+    unsigned int Dock::getNumberOfActiveDocks()
+    {
+        int i = 0;
+        PlayerInfo* player = HumanController::getLocalControllerSingleton()->getPlayer();
+        for(Dock* dock : ObjectList<Dock>())
+        {
+            if(dock->candidates_.find(player) != dock->candidates_.end())
+                i++;
+        }
+        return i;
+    }
+
+    Dock* Dock::getActiveDockAtIndex(unsigned int index)
+    {
+        PlayerInfo* player = HumanController::getLocalControllerSingleton()->getPlayer();
+        for(Dock* dock : ObjectList<Dock>())
+        {
+            if(dock->candidates_.find(player) != dock->candidates_.end())
+            {
+                if(index == 0)
+                    return dock;
+                index--;
+            }
+        }
+        return nullptr;
+    }
+
+    bool Dock::addEffect(DockingEffect* effect)
+    {
+        assert(effect);
+        effects_.push_back(effect);
+        return true;
+    }
+
+    const DockingEffect* Dock::getEffect(unsigned int i) const
+    {
+        for (DockingEffect* effect : this->effects_)
+        {
+            if(i == 0)
+               return effect;
+            i--;
+        }
+        return nullptr;
+    }
+
+    bool Dock::addAnimation(DockingAnimation* animation)
+    {
+        assert(animation);
+        animation->setParent(this);
+        animations_.push_back(animation);
+        return true;
+    }
+
+    const DockingAnimation* Dock::getAnimation(unsigned int i) const
+    {
+        for (DockingAnimation* animation : this->animations_)
+        {
+            if(i == 0)
+               return animation;
+            i--;
+        }
+        return nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/docking/Dock.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/Dock.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/Dock.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Dock.h
+    @brief Definition of Dock class
+    @ingroup Docking
+*/
+
+#ifndef _Dock_H__
+#define _Dock_H__
+
+#include "DockingPrereqs.h"
+
+#include <set>
+
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+
+#include "controllers/HumanController.h"
+
+#include "DockingAnimation.h"
+#include "DockingEffect.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox // tolua_export
+{  // tolua_export
+
+    class _DockingExport Dock  // tolua_export
+        : public StaticEntity
+    { // tolua_export
+        public:
+            Dock(Context* context);
+            virtual ~Dock();
+
+            // Trigger interface
+            bool execute(bool bTriggered, BaseObject* trigger);
+            bool undocking(bool bTriggered, BaseObject* trigger);
+
+            // XML interface
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            // XML functions
+            bool addEffect(DockingEffect* effect); //!< Add a DockingEffect to the Dock.
+            const DockingEffect* getEffect(unsigned int index) const; //!< Get the DockingEffect at a given index.
+            bool addAnimation(DockingAnimation* animation); //!< Add a DockingAnimation to the Dock.
+            const DockingAnimation* getAnimation(unsigned int index) const; //!< Get the DockingAnimation at a given index.
+
+            // Docking/undocking logic, checks conditions and invokes the DockingAnimations
+            bool dock(PlayerInfo* player); //!< Returns true if given player docked successfully (player must be a candidate)
+            bool undock(PlayerInfo* player); //!< Undocks a player (player must be docked)
+
+            // Animation logic
+            bool dockingAnimationFinished(PlayerInfo* player); //!< Called when a docking animation finished
+            bool undockingAnimationFinished(PlayerInfo* player); //!< Called when a undocking animation finished
+
+            // LUA interface
+            // tolua_begin
+            void dock()
+                { this->dock(HumanController::getLocalControllerSingleton()->getPlayer()); }
+            void undock()
+                { this->undock(HumanController::getLocalControllerSingleton()->getPlayer()); }
+            static unsigned int getNumberOfActiveDocks();
+            static Dock* getActiveDockAtIndex(unsigned int index);
+            // tolua_end
+
+            // Console commands
+            static void cmdDock();
+            static void cmdUndock();
+
+            // Network functions
+            void showDockingDialogHelper(PlayerInfo* player);
+            void showUndockingDialogHelper(PlayerInfo* player);
+            static void showDockingDialog();
+
+        private:
+            std::set<PlayerInfo*> candidates_; //!< A set of all players which are allowed to dock using the console command.
+            std::set<PlayerInfo*> docked_; //!< A set of all docked players
+
+            std::list<DockingEffect*> effects_; //!< The list of DockingEffects to be executed when a player docks.
+            std::list<DockingAnimation*> animations_; //!< The list of DockingAnimations to be executed before a player docks
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _Dock_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockToShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockToShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockToShip.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockToShip.cc
+    @brief Implementation of the DockToShip class.
+*/
+
+#include "DockingEffect.h"
+#include "DockToShip.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(DockToShip);
+
+    DockToShip::DockToShip(Context* context) : DockingEffect(context)
+    {
+        RegisterObject(DockToShip);
+        orxout(verbose, context::docking) << "DockToShip instance created.." << endl;
+    }
+
+    DockToShip::~DockToShip()
+    {
+
+    }
+
+
+    void DockToShip::XMLPort(Element& xmlelement, XMLPort::Mode mode) {
+        SUPER(DockToShip, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DockToShip, "target", setTargetId, getTargetId, xmlelement, mode);
+    }
+
+    void DockToShip::setTargetId(const std::string& str) {
+        this->target_ = str;
+    }
+
+    const std::string& DockToShip::getTargetId() const {
+        return this->target_;
+    }
+
+
+    bool DockToShip::docking(PlayerInfo* player)
+    {
+        orxout(verbose, context::docking) << "DockToShip::attach" << endl;
+
+        DockingTarget *target = DockingEffect::findTarget(this->target_);
+        if (target == nullptr) {
+            orxout(internal_warning, context::docking) << "Can't retrieve target for '" << this->target_ << "'.." << endl;
+            return false;
+        }
+
+        ControllableEntity *dockTo = (ControllableEntity*) target->getParent();
+        if (dockTo == nullptr) {
+            orxout(internal_warning, context::docking) << "Parent is not a ControllableEntity.." << endl;
+            return false;
+        }
+
+        // Make sure target isn't removed when undocking
+        dockTo->setDestroyWhenPlayerLeft(false);
+        player->startControl(dockTo);
+
+        return true;
+    }
+
+    bool DockToShip::release(PlayerInfo* player)
+    {
+        orxout(verbose, context::docking) << "DockToShip::release" << endl;
+
+        player->stopTemporaryControl();
+
+        return true;
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockToShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockToShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockToShip.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockToShip.h
+    @brief DockingEffect which transfers control from spaceship to docked ship ASDF
+    @ingroup Docking
+*/
+
+#ifndef _DockToShip_H__
+#define _DockToShip_H__
+
+#include "DockingPrereqs.h"
+#include "DockToShip.h"
+
+#include "worldentities/ControllableEntity.h"
+
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Allows players to dock onto a ship
+
+    @author
+        Sven Stucki
+
+    @ingroup Docking
+    */
+    class _DockingExport DockToShip : public DockingEffect
+    {
+        public:
+            DockToShip(Context* context);
+            virtual ~DockToShip();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            void setTargetId(const std::string& str);
+            const std::string& getTargetId() const;
+
+            virtual bool docking(PlayerInfo* player) override; //!< Called when docking starts
+            virtual bool release(PlayerInfo* player) override; //!< Called when player wants undock
+        private:
+            std::string target_;
+    };
+
+}
+
+#endif /* _DockToShip_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingAnimation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingAnimation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingAnimation.cc	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockingAnimation.cc
+    @brief Implementation of the DockingAnimation class.
+*/
+
+#include "DockingAnimation.h"
+
+#include "DockingEffect.h"  // For DockingEffect::findTarget
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(DockingAnimation).inheritsFrom<BaseObject>();
+
+    DockingAnimation::DockingAnimation(Context* context) : BaseObject(context)
+    {
+        RegisterObject(DockingAnimation);
+
+        this->parent_ = nullptr;
+    }
+
+    DockingAnimation::~DockingAnimation()
+    {
+
+    }
+
+    bool DockingAnimation::invokeAnimation(bool dock, PlayerInfo* player, std::list<DockingAnimation*> &animations)
+    {
+        bool check = true;
+
+        for (DockingAnimation* animation : animations)
+        {
+            if(dock)
+                check &= animation->docking(player);
+            else
+                check &= animation->release(player);
+        }
+
+        return check;
+    }
+
+    DockingTarget *DockingAnimation::findTarget(std::string name) {
+        return DockingEffect::findTarget(name);
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingAnimation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingAnimation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingAnimation.h	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockingAnimation.h
+    @brief Definition of the DockingAnimation class.
+    @ingroup Docking
+*/
+
+#ifndef _DockingAnimation_H__
+#define _DockingAnimation_H__
+
+#include "core/XMLPort.h"
+
+#include "infos/PlayerInfo.h"
+
+#include "DockingPrereqs.h"
+#include "DockingTarget.h"
+#include "Dock.h"
+
+
+#include <list>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Base class for docking animations used by @ref orxonox::Dock "Docks".
+
+    @author
+        Sven Stucki
+
+    @ingroup Docking
+    */
+    class _DockingExport DockingAnimation : public BaseObject
+    {
+        public:
+            DockingAnimation(Context* context);
+            virtual ~DockingAnimation();
+
+            virtual bool docking(PlayerInfo* player) = 0; //!< Called when a player starts docking
+            virtual bool release(PlayerInfo* player) = 0; //!< Called when player wants to undock
+
+            static bool invokeAnimation(bool dock, PlayerInfo* player, std::list<DockingAnimation*> &animations); //!< Invokes calls the docking or release method of all list entries
+            static DockingTarget *findTarget(std::string name); //!< Iterates through all DockingTarget objects to find the one with name=target
+
+            void setParent(Dock *parent) { this->parent_ = parent; }
+
+        protected:
+            Dock *parent_;
+            std::set<PlayerInfo*> animations_; //!< Contains a list of currently running animations
+    };
+
+}
+
+#endif /* _DockingAnimation_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingController.cc	(revision 11817)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DockingController.h"
+
+#include <cmath>
+
+#include "infos/PlayerInfo.h"
+#include "worldentities/ControllableEntity.h"
+#include "Dock.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(DockingController);
+
+    DockingController::DockingController(Context* context) : ArtificialController(context)
+    {
+        RegisterObject(DockingController);
+
+        this->dock_ = nullptr;
+        this->player_ = nullptr;
+        this->entity_ = nullptr;
+    }
+
+    DockingController::~DockingController()
+    {
+
+    }
+
+    void DockingController::tick(float dt)
+    {
+        ControllableEntity* entity = this->getControllableEntity();
+        if (!entity)
+            return;
+
+        float distance = (this->dock_->getWorldPosition() - entity->getPosition()).length();
+        Vector2 coord = get2DViewCoordinates(     // I don't understand this too
+            entity->getPosition(),
+            entity->getOrientation() * WorldEntity::FRONT,
+            entity->getOrientation() * WorldEntity::UP,
+            dock_->getWorldPosition()
+        );
+
+        // adjust direction of spaceship
+        if (distance > 10)
+        {
+            entity->rotateYaw(-1.0f * 0.8f * clamp(coord.x * 10, -1.0f, 1.0f));
+            entity->rotatePitch(0.8f * clamp(coord.y * 10, -1.0f, 1.0f));
+        }
+
+        /*// adjust speed
+        if (distance < 200 && entity->getVelocity().squaredLength() > dock->getVelocity().squaredLength())
+            entity->moveFrontBack(0.2f);
+        else
+            entity->moveFrontBack(0.8f);*/
+
+        entity->moveFrontBack(0.5f * log(distance/10.0f));
+
+        if (distance < 20)
+            this->positionReached();
+
+        SUPER(DockingController, tick, dt);
+    }
+
+    void DockingController::takeControl(bool docking)
+    {
+        this->docking_ = docking;
+
+        this->entity_ = this->player_->getControllableEntity();
+        assert(this->entity_);
+
+        if (docking)
+        {
+            orxout(verbose, context::docking) << "DockingController::takeControl Taking over control." << endl;
+
+            this->entity_->setDestroyWhenPlayerLeft(false);
+            this->player_->pauseControl();
+            this->entity_->setController(this);
+            this->setControllableEntity(this->entity_);
+        }
+    }
+
+    void DockingController::positionReached()
+    {
+        orxout(verbose, context::docking) << "DockingController::positionReached() called." << endl;
+
+        assert(this->player_);
+        assert(this->dock_);
+
+        // stop spaceship
+        this->entity_->setPosition(this->dock_->getWorldPosition());
+        this->entity_->setVelocity(0, 0, 0);
+        this->entity_->setOrientation(this->dock_->getWorldOrientation());
+
+        // give control back to player
+        this->player_->startControl(this->entity_);
+        this->setActive(false);
+        this->controllableEntity_ = nullptr;
+
+        if (this->docking_)
+            this->dock_->dockingAnimationFinished(this->player_);
+        /*else
+            dock->undockingAnimationFinished(player);*/
+
+        this->destroy();
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingController.h	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DockingController_H__
+#define _DockingController_H__
+
+#include "DockingPrereqs.h"
+
+#include "infos/PlayerInfo.h"
+#include "controllers/ArtificialController.h"
+#include "tools/interfaces/Tickable.h"
+#include "DockingController.h"
+
+namespace orxonox
+{
+    class _DockingExport DockingController : public ArtificialController, public Tickable
+    {
+        public:
+            DockingController(Context* context);
+            virtual ~DockingController();
+
+            virtual void tick(float dt) override;
+
+            void takeControl(bool docking);
+
+            void setDock(Dock* dock) { this->dock_ = dock; }
+            void setPlayer(PlayerInfo* player) { this->player_ = player; }
+
+        protected:
+            virtual void positionReached() override;
+
+        private:
+            bool docking_;
+
+            Dock* dock_;
+            PlayerInfo* player_;
+
+            ControllableEntity* entity_;
+    };
+}
+
+#endif /* _DockingController_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingEffect.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingEffect.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingEffect.cc	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockingEffect.cc
+    @brief Implementation of the DockingEffect class.
+*/
+
+#include "DockingEffect.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(DockingEffect).inheritsFrom<BaseObject>();
+
+    DockingEffect::DockingEffect(Context* context) : BaseObject(context)
+    {
+        RegisterObject(DockingEffect);
+    }
+
+    DockingEffect::~DockingEffect()
+    {
+
+    }
+
+    bool DockingEffect::invokeEffect(bool dock, PlayerInfo* player, std::list<DockingEffect*> & effects)
+    {
+        bool check = true;
+
+        for (DockingEffect* effect : effects)
+        {
+            if (dock)
+                check &= effect->docking(player);
+            else
+                check &= effect->release(player);
+        }
+
+        return check;
+    }
+
+    DockingTarget *DockingEffect::findTarget(std::string name) {
+        for (DockingTarget* target : ObjectList<DockingTarget>())
+        {
+            if (target->getName().compare(name) == 0)
+                return target;
+        }
+        return nullptr;
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingEffect.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingEffect.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingEffect.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki 
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockingEffect.h
+    @brief Definition of the DockingEffect class.
+    @ingroup Docking
+*/
+
+#ifndef _DockingEffect_H__
+#define _DockingEffect_H__
+
+#include "core/XMLPort.h"
+
+#include "infos/PlayerInfo.h"
+
+#include "DockingPrereqs.h"
+#include "DockingTarget.h"
+
+#include <list>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Handles DockingEffects for @ref orxonox::Dock "Docks".
+
+    @author
+        Sven Stucki
+
+    @ingroup Docking
+    */
+    class _DockingExport DockingEffect : public BaseObject
+    {
+        public:
+            DockingEffect(Context* context);
+            virtual ~DockingEffect();
+
+            virtual bool docking(PlayerInfo* player) = 0; //!< Called when player docked
+            virtual bool release(PlayerInfo* player) = 0; //!< Called when player wants to undock
+
+            static bool invokeEffect(bool dock, PlayerInfo* player, std::list<DockingEffect*> & effects); //!< Invokes the event specific method of all DockingEffects in the list
+            static DockingTarget *findTarget(std::string name); //!< Iterates through all DockingTarget objects to find the one with name=target
+    };
+
+}
+
+#endif /* _DockingEffect_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btTransform.h>
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"
+#include "core/XMLPort.h"
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingPrereqs.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _DockingPrereqs_H__
+#define _DockingPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(DOCKING_STATIC_BUILD)
+#  ifdef DOCKING_SHARED_BUILD
+#    define _DockingExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _DockingExport
+#    else
+#      define _DockingExport __declspec(dllimport)
+#    endif
+#  endif
+#elif defined ( ORXONOX_GCC_VISIBILITY )
+#  define _DockingExport  __attribute__ ((visibility("default")))
+#else
+#  define _DockingExport
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Dock;
+    class DockingAnimation;
+    class DockingController;
+    class DockingTarget;
+    class DockingEffect;
+    class DockToShip;
+    class MoveToDockingTarget;
+}
+
+#endif /* _DockingPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingTarget.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingTarget.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingTarget.cc	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockingTarget.cc
+    @brief Docking system main class
+*/
+
+#include "DockingTarget.h"
+#include "core/CoreIncludes.h"
+
+
+namespace orxonox
+{
+    RegisterClass(DockingTarget);
+
+    DockingTarget::DockingTarget(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(DockingTarget);
+    }
+
+    DockingTarget::~DockingTarget()
+    {
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/docking/DockingTarget.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/DockingTarget.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/DockingTarget.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki 
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DockingTarget.h
+    @brief Definition of the DockingTarget class.
+    @ingroup Docking
+*/
+
+#ifndef _DockingTarget_H__
+#define _DockingTarget_H__
+
+#include "DockingPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        DockingTargets for @ref orxonox::Dock "Docks".
+
+    @author
+        Sven Stucki
+
+    @ingroup Docking
+    */
+    class _DockingExport DockingTarget : public StaticEntity
+    {
+        public:
+            DockingTarget(Context* context);
+            virtual ~DockingTarget();
+
+    };
+
+}
+
+#endif /* _DockingTarget_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/docking/MoveToDockingTarget.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/MoveToDockingTarget.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/MoveToDockingTarget.cc	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MoveToDockingTarget.h
+    @brief Definition of the MoveToDockingTarget class.
+    @ingroup Docking
+*/
+
+#include "MoveToDockingTarget.h"
+
+#include "core/XMLPort.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(MoveToDockingTarget);
+
+    MoveToDockingTarget::MoveToDockingTarget(Context* context) : DockingAnimation(context)
+    {
+        RegisterObject(MoveToDockingTarget);
+    }
+
+    MoveToDockingTarget::~MoveToDockingTarget() {
+
+    }
+
+    bool MoveToDockingTarget::docking(PlayerInfo *player)
+    {
+        assert(this->parent_);
+
+        DockingController *dockingController = new DockingController(this->getContext());
+        dockingController->setDock(this->parent_);
+        dockingController->setPlayer(player);
+        dockingController->takeControl(true);
+
+        return true;
+    }
+
+    bool MoveToDockingTarget::release(PlayerInfo *player)
+    {
+        //TODO: Investigate strange things...
+        //this->parent_->detach((WorldEntity*)player->getControllableEntity());
+
+        //TODO: Check the issue with this detach call.
+        //I have removed the line because the detach call only caused a warning and terminated. And because I didn't find a attach call either.
+        //Didn't find the need for the line.
+        this->parent_->undockingAnimationFinished(player);
+        return true;
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/docking/MoveToDockingTarget.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/docking/MoveToDockingTarget.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/docking/MoveToDockingTarget.h	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sven Stucki
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MoveToDockingTarget.h
+    @brief Definition of the MoveToDockingTarget class.
+    @ingroup Docking
+*/
+
+#ifndef _MoveToDockingTarget_H__
+#define _MoveToDockingTarget_H__
+
+#include "DockingPrereqs.h"
+#include "DockingAnimation.h"
+#include "DockingController.h"
+#include "Dock.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Base class for docking animations used by @ref orxonox::Dock "Docks".
+
+    @author
+        Sven Stucki
+
+    @ingroup Docking
+    */
+    class _DockingExport MoveToDockingTarget : public DockingAnimation
+    {
+        public:
+            MoveToDockingTarget(Context* context);
+            virtual ~MoveToDockingTarget();
+
+            virtual bool docking(PlayerInfo* player) override; //!< Called when a player starts docking
+            virtual bool release(PlayerInfo* player) override; //!< Called when player wants to undock
+    };
+
+}
+
+#endif /* _MoveToDockingTarget_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,16 @@
+SET_SOURCE_FILES(Dodgerace_SRC_FILES
+DodgeRace.cc
+DodgeRaceCenterPoint.cc
+DodgeRaceShip.cc
+DodgeRaceCube.cc
+DodgeRaceHUDinfo.cc
+)
+
+ORXONOX_ADD_LIBRARY(dodgerace
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+  SOURCE_FILES ${Dodgerace_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRace.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRace.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRace.cc	(revision 11817)
@@ -0,0 +1,234 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRace.cc
+    @brief Implementation of the DodgeRace class.
+*/
+
+#include "DodgeRace.h"
+#include "DodgeRaceShip.h" // Necessary for getPlayer function. Do NOT include this in Header!
+#include "DodgeRaceCube.h"
+#include "core/CoreIncludes.h"
+#include "Highscore.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(DodgeRace);
+
+    DodgeRace::DodgeRace(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(DodgeRace);
+
+        bEndGame = false;
+        lives = 1;
+        level = 1;
+        point = 0;
+        bShowLevel = false;
+        multiplier = 1;
+        b_combo = false;
+        counter = 5000;
+        pattern = 1;
+        lastPosition = 0;
+        // spawn enemy every 3.5 seconds
+        //enemySpawnTimer.setTimer(3.5f, true, createExecutor(createFunctor(&DodgeRace::spawnEnemy, this)));
+        comboTimer.setTimer(3.0f, true, createExecutor(createFunctor(&DodgeRace::comboControll, this)));
+        this->numberOfBots_ = 0; //sets number of default bots temporarly to 0
+        this->center_ = nullptr;
+
+        this->setHUDTemplate("DodgeRaceHUD");
+    }
+
+    void DodgeRace::levelUp()
+    {
+        level++;
+        if (getPlayer() != nullptr)
+        {
+            for (int i = 0; i < 7; i++)
+            {
+                WeakPtr<ExplosionPart> chunk5 = new ExplosionPart(this->center_->getContext());
+                chunk5->setPosition(Vector3(600, 0, 100.f * i - 300));
+                chunk5->setVelocity(Vector3(1000, 0, 0));  //player->getVelocity()
+                chunk5->setScale(10);
+                chunk5->setEffect1("Orxonox/explosion2b");
+                chunk5->setEffect2("Orxonox/smoke6");
+                chunk5->Explode();
+
+            }
+        }
+        addPoints(multiplier * 42);
+        multiplier *= 2;
+        toggleShowLevel();
+        showLevelTimer.setTimer(1.0f, false, createExecutor(createFunctor(&DodgeRace::toggleShowLevel, this)));
+    }
+
+    void DodgeRace::tick(float dt)
+    {
+        DodgeRaceShip* player = this->getPlayer();
+        if (player != nullptr)
+        {
+            currentPosition = player->getWorldPosition().x;
+            counter = counter + (currentPosition - lastPosition);
+            lastPosition = currentPosition;
+            point = (int) currentPosition;
+            player->speed = 830.0f - (point / 1000);
+
+            for(unsigned int i=0; i < cubeList.size();i++)
+            {
+                if(cubeList.at(i)->getPosition().x < currentPosition-3000)
+                {
+                    cubeList.at(i)->destroy();
+                    cubeList.erase(cubeList.begin()+i);
+                }
+            }
+
+            if(counter >= 3000)
+            {
+                counter = 0;
+                for(int i = 0; i<6; i++)
+                {
+                    DodgeRaceCube* cube = new DodgeRaceCube(this->center_->getContext());
+                    cubeList.push_back(cube);
+                    switch(pattern)
+                    {
+                    case 1: cube->addTemplate("DodgeRaceCube01");
+                    break;
+                    case 2: cube->addTemplate("DodgeRaceCube02");
+                    break;
+
+                    }
+
+                    cube->setPosition(player->getWorldPosition() + Vector3(5000.0f, 0.0f, -3600.0f + (i*1200)));
+                    //stEntity->setScale3D(50,50,50);
+                }
+
+
+                pattern %= 2;
+                pattern ++;
+
+            }
+
+        }
+        SUPER(DodgeRace, tick, dt);
+    }
+
+    DodgeRaceShip* DodgeRace::getPlayer()
+    {
+        for (DodgeRaceShip* ship : ObjectList<DodgeRaceShip>())
+        {
+            return ship;
+        }
+        return nullptr;
+    }
+
+    void DodgeRace::costLife()
+    {
+        //endGameTimer.setTimer(8.0f, false, createExecutor(createFunctor(&DodgeRace::end, this)));
+        lives = 0;
+    };
+
+    void DodgeRace::comboControll()
+    {
+        if (b_combo)
+            multiplier++;
+        // if no combo was performed before, reset multiplier
+        else
+            multiplier = 1;
+        b_combo = false;
+    }
+
+    void DodgeRace::start()
+    {
+        orxout() << "start" << endl;
+        for(unsigned int i=0; i< cubeList.size();i++)
+        {
+            cubeList.at(i)->destroy();
+            cubeList.erase(cubeList.begin()+i);
+
+        }
+        cubeList.clear();
+        // Set variable to temporarily force the player to spawn.
+        this->bForceSpawn_ = false;
+
+        if (this->center_ == nullptr)  // abandon mission!
+        {
+            orxout(internal_error) << "DodgeRace: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+        // Call start for the parent class.
+        Deathmatch::start();
+    }
+
+    void DodgeRace::playerPreSpawn(PlayerInfo* player)
+    {
+        this->playerInfo_ = player;
+        if(lives <= 0)
+        {
+            this->end();
+        }
+
+        // Reset all the cubes
+        /*
+        orxout() << "prespawn" << endl;
+        for(int i=0; i< cubeList.size();i++)
+        {
+            cubeList.at(i)->destroy();
+            cubeList.erase(cubeList.begin()+i);
+        }
+        cubeList.clear();
+        lives = 1;
+        point = 0;
+        lastPosition = 0;
+        */
+    }
+
+    void DodgeRace::addPoints(int numPoints)
+    {
+        if (!bEndGame)
+        {
+            point += numPoints * multiplier;
+            b_combo = true;
+        }
+    }
+
+    void DodgeRace::end()
+    {
+        // DON'T CALL THIS!
+        //      Deathmatch::end();
+        // It will misteriously crash the game!
+        // Instead startMainMenu, this won't crash.
+        if (Highscore::exists())
+        {
+            int score = this->getPoints();
+            Highscore::getInstance().storeScore("Dodge Race", score, this->playerInfo_);
+        }
+        GSLevel::startMainMenu();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRace.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRace.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRace.h	(revision 11817)
@@ -0,0 +1,145 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRace.h
+    @brief Gametype.
+    @ingroup DodgeRace
+*/
+
+#ifndef _DodgeRace_H__
+#define _DodgeRace_H__
+
+#include "dodgerace/DodgeRacePrereqs.h"
+
+#include "DodgeRaceCenterPoint.h" // Necessary for WeakPointer??
+//#include "DodgeRaceShip.h"        DO NOT include in Header. Will cause forward declaration issues
+
+//#include "DodgeRaceHUDinfo.h"
+
+
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+#include "core/config/ConfigValueIncludes.h"
+
+#include "gamestates/GSLevel.h"
+#include "chat/ChatManager.h"
+#include <vector>
+
+// ! HACK
+#include "infos/PlayerInfo.h"
+
+#include "core/command/ConsoleCommand.h"
+
+#include "gametypes/Deathmatch.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+
+    class _DodgeRaceExport DodgeRace : public Deathmatch
+    {
+       public:
+            DodgeRace(Context* context);
+
+            virtual void start() override;
+            virtual void end() override;
+
+            virtual void tick(float dt) override;
+
+            virtual void playerPreSpawn(PlayerInfo* player) override;
+
+            void levelUp();
+
+            int getLives(){return this->lives;}
+            int getLevel(){return this->level;}
+            int getPoints(){return this->point;}
+            int getMultiplier(){return this->multiplier;}
+
+            void setCenterpoint(DodgeRaceCenterPoint* center)
+                       { this->center_ = center; }
+            virtual void addBots(unsigned int amount) override{} //<! overwrite function in order to bypass the addbots command
+
+            // checks if multiplier should be reset.
+            void comboControll();
+            void costLife();
+
+            bool bEndGame;
+            bool bShowLevel;
+            int lives;
+            int multiplier;
+            float counter;
+            int pattern;
+            float currentPosition;
+            float lastPosition;
+
+       private:
+            Timer endGameTimer;
+
+            DodgeRaceShip* getPlayer();
+            WeakPtr<PlayerInfo> playerInfo_;
+            std::vector<DodgeRaceCube*> cubeList;
+            void toggleShowLevel(){bShowLevel = !bShowLevel;}
+            void addPoints(int numPoints);
+
+            WeakPtr<DodgeRaceCenterPoint> center_;
+            int level;
+            int point;
+            bool b_combo;
+
+            Timer enemySpawnTimer;
+            Timer comboTimer;
+            Timer showLevelTimer;
+
+
+         /*
+
+            //void spawnEnemy();
+
+
+
+
+
+
+
+
+
+
+
+
+        private:
+
+
+
+
+            //Context* context;
+            */
+    };
+}
+
+#endif /* _DodgeRace_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCenterPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCenterPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCenterPoint.cc	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRaceCenterPoint.cc
+    @brief Implementation of the DodgeRaceCenterPoint class.
+*/
+
+#include "DodgeRaceCenterPoint.h"
+
+#include "core/CoreIncludes.h"
+
+#include "DodgeRace.h"
+
+namespace orxonox
+{
+    RegisterClass(DodgeRaceCenterPoint);
+
+    DodgeRaceCenterPoint::DodgeRaceCenterPoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(DodgeRaceCenterPoint);
+
+        this->checkGametype();
+    }
+
+    void DodgeRaceCenterPoint::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(DodgeRace)))
+        {
+            DodgeRace* DodgeRaceGametype = orxonox_cast<DodgeRace*>(this->getGametype());
+            DodgeRaceGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCenterPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCenterPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCenterPoint.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRaceCenterPoint.h
+    @brief Declaration of the DodgeRaceCenterPoint class.
+    @ingroup DodgeRace
+*/
+
+#ifndef _DodgeRaceCenterPoint_H__
+#define _DodgeRaceCenterPoint_H__
+
+#include "dodgerace/DodgeRacePrereqs.h"
+
+//#include "DodgeRace.h"
+//#include "DodgeRaceHUDinfo.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _DodgeRaceExport DodgeRaceCenterPoint : public StaticEntity
+    {
+        public:
+            DodgeRaceCenterPoint(Context* context); //checks whether the gametype is actually DodgeRace.
+
+        private:
+            void checkGametype();
+
+    };
+}
+
+#endif /* _DodgeRaceCenterPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCube.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCube.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCube.cc	(revision 11817)
@@ -0,0 +1,47 @@
+/*   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Samuel Riedel
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRace.cc
+    @brief Implementation of the DodgeRace class.
+*/
+
+#include "DodgeRaceCube.h"
+#include "DodgeRace.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(DodgeRaceCube);
+
+    DodgeRaceCube::DodgeRaceCube(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(DodgeRaceCube);
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCube.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCube.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceCube.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Samuel Riedel
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRace.h
+    @brief Gametype.
+    @ingroup DodgeRace
+*/
+
+#ifndef _DodgeRaceCube_H__
+#define _DodgeRaceCube_H__
+
+#include "dodgerace/DodgeRacePrereqs.h"
+
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _DodgeRaceExport DodgeRaceCube : public MovableEntity
+    {
+       public:
+            DodgeRaceCube(Context* context);
+
+       private:
+    };
+}
+
+#endif /* _DodgeRaceCube_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceHUDinfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceHUDinfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceHUDinfo.cc	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *
+ */
+
+#include "DodgeRaceHUDinfo.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+//#include "DodgeRace.h"
+
+namespace orxonox
+{
+    RegisterClass(DodgeRaceHUDinfo);
+
+    DodgeRaceHUDinfo::DodgeRaceHUDinfo(Context* context) : OverlayText(context)
+    {
+        RegisterObject(DodgeRaceHUDinfo);
+
+        this->DodgeRaceGame = nullptr;
+        this->bShowPoints_ = true;
+    }
+
+    void DodgeRaceHUDinfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(DodgeRaceHUDinfo, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DodgeRaceHUDinfo,"showPoints", setShowPoints, getShowPoints, xmlelement, mode).defaultValues(false);
+    }
+
+    void DodgeRaceHUDinfo::tick(float dt)
+    {
+        SUPER(DodgeRaceHUDinfo, tick, dt);
+
+
+        if(this->bShowPoints_)
+        {
+            const std::string& points = multi_cast<std::string>(this->DodgeRaceGame->getPoints());
+            if (this->DodgeRaceGame->lives <= 0)
+            {
+                setTextSize(0.2);
+                setPosition(Vector2(0.1, 0.02));
+                this->setCaption("Final score:\n" + points);
+                this->setColour(ColourValue(1, 0, 0, 1));
+            }
+            else
+            {
+                setTextSize(0.04);
+                setPosition(Vector2(0.14, 0.02));
+                this->setColour(ColourValue(1, 1, 1, 1));
+                this->setCaption(points);
+            }
+        }
+    }
+
+    void DodgeRaceHUDinfo::changedOwner()
+    {
+        SUPER(DodgeRaceHUDinfo, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->DodgeRaceGame = orxonox_cast<DodgeRace*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->DodgeRaceGame = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceHUDinfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceHUDinfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceHUDinfo.h	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *
+ */
+
+#ifndef _DodgeRaceHUDinfo_H__
+#define _DodgeRaceHUDinfo_H__
+
+//#include "DodgeRaceShip.h"
+#include "DodgeRace.h"
+//#include "DodgeRaceCenterPoint.h"
+
+#include "dodgerace/DodgeRacePrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _DodgeRaceExport DodgeRaceHUDinfo : public OverlayText, public Tickable
+    {
+     public:
+            DodgeRaceHUDinfo(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowPoints(bool value)
+                { this->bShowPoints_ = value; }
+            inline bool getShowPoints() const
+                { return this->bShowPoints_; }
+
+
+        private:
+            DodgeRace* DodgeRaceGame;
+            bool bShowPoints_;
+    };
+}
+#endif /* _DodgeRaceHUDinfo_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRacePrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRacePrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRacePrereqs.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the DodgeRace module
+*/
+
+#ifndef _DodgeRacePrereqs_H__
+#define _DodgeRacePrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(DODGERACE_STATIC_BUILD)
+#  ifdef DODGERACE_SHARED_BUILD
+#    define _DodgeRaceExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _DodgeRaceExport
+#    else
+#      define _DodgeRaceExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _DodgeRacePrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _DodgeRaceExport  __attribute__ ((visibility("default")))
+#  define _DodgeRacePrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _DodgeRaceExport
+#  define _DodgeRacePrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class DodgeRace;
+    class DodgeRaceCenterPoint;
+    class DodgeRaceShip;
+    class DodgeRaceCube;
+    //class DodgeRaceEnemy;
+    //class DodgeRaceEnemyShooter;
+    //class DodgeRaceWeapon;
+    //class DodgeRaceWeaponEnemy;
+    //class DodgeRaceHUDinfo;
+}
+
+#endif /* _DodgeRacePrereqs_H__*/
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceShip.cc	(revision 11817)
@@ -0,0 +1,169 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRaceShip.cc
+    @brief Implementation of the DodgeRaceShip class.
+*/
+
+#include "DodgeRaceShip.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(DodgeRaceShip);
+
+    DodgeRaceShip::DodgeRaceShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(DodgeRaceShip);
+
+        speed = 830;
+        isFireing = false;
+        damping = 10;
+
+        // not sure if has to be zero?
+        lastTimeFront = 0;
+        lastTimeLeft = 0;
+        lastTime = 0;
+    }
+
+    void DodgeRaceShip::tick(float dt)
+    {
+        Vector3 pos = getPosition();
+
+        //Movement calculation
+        lastTimeFront += dt * damping;
+        lastTimeLeft += dt * damping;
+        lastTime += dt;
+
+        velocity.x = interpolate(clamp(lastTimeLeft, 0.0f, 1.0f), desiredVelocity.x, 0.0f);
+        velocity.y = interpolate(clamp(lastTimeFront, 0.0f, 1.0f), desiredVelocity.y, 0.0f);
+
+        //Execute movement
+        if (this->hasLocalController())
+        {
+            float dist_y = velocity.y * dt;
+            //float dist_x = velocity.x * dt;
+            if(dist_y + posforeward > -42*3 && dist_y + posforeward < 42*6)
+                posforeward += dist_y;
+            else
+            {
+                velocity.y = 0;
+                // restart if game ended
+/*
+                if (getGame())
+                    if (getGame()->bEndGame)
+                    {
+                        getGame()->start();
+                        return;
+                    }*/
+            }
+
+            pos += Vector3(1000 + velocity.y, 0, velocity.x) * dt;
+        }
+
+
+        // Camera
+        Camera* camera = this->getCamera();
+        if (camera != nullptr)
+        {
+            // camera->setPosition(Vector3(-pos.z, -posforeward, 0));
+            camera->setOrientation(Vector3::UNIT_Z, Degree(0));
+        }
+
+
+
+        // bring back on track!
+        if(pos.y != 0)
+        {
+            pos.y = 0;
+        }
+
+        setPosition(pos);
+        setOrientation(Vector3::UNIT_Y, Degree(270));
+
+        // Level up!
+        if (pos.x > 42000)
+        {
+            updateLevel();
+            setPosition(Vector3(0, 0, pos.z)); // pos - Vector3(30000, 0, 0)
+        }
+
+        SUPER(DodgeRaceShip, tick, dt);
+    }
+
+    void DodgeRaceShip::updateLevel()
+    {
+        lastTime = 0;
+        if (getGame())
+            getGame()->levelUp();
+    }
+
+    void DodgeRaceShip::moveFrontBack(const Vector2& value)
+    {
+        //lastTimeFront = 0;
+        //desiredVelocity.y = value.y * speed * 42;
+
+    }
+
+    void DodgeRaceShip::moveRightLeft(const Vector2& value)
+    {
+        lastTimeLeft = 0;
+        desiredVelocity.x = value.x * speed;
+    }
+    void DodgeRaceShip::boost(bool bBoost)
+    {
+        //getGame()->bEndGame = bBoost;
+    }
+
+    inline bool DodgeRaceShip::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+
+        removeHealth(100);
+        this->death();
+        return false;
+    }
+
+    DodgeRace* DodgeRaceShip::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (DodgeRace* race : ObjectList<DodgeRace>())
+            {
+                game = race;
+            }
+        }
+        return game;
+    }
+
+    void DodgeRaceShip::death()
+    {
+        getGame()->costLife();
+        SpaceShip::death();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/dodgerace/DodgeRaceShip.h	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DodgeRaceShip.h
+    @brief Declaration of the DodgeRaceShip class.
+*/
+
+#ifndef _DodgeRaceShip_H__
+#define _DodgeRaceShip_H__
+
+
+#include "dodgerace/DodgeRacePrereqs.h"
+
+#include "core/XMLPort.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "graphics/Camera.h"
+
+#include "DodgeRace.h" // Is necessary for getGame function
+//#include "DodgeRaceCenterPoint.h"
+
+namespace orxonox
+{
+    class _DodgeRaceExport DodgeRaceShip : public SpaceShip
+    {
+        public:
+            DodgeRaceShip(Context* context);
+
+            virtual void tick(float dt) override;
+
+            // overwrite for 2d movement
+            virtual void moveFrontBack(const Vector2& value) override;
+            virtual void moveRightLeft(const Vector2& value) override;
+
+            // Starts or stops fireing
+            virtual void boost(bool bBoost) override;
+
+            //no rotation!
+            virtual void rotateYaw(const Vector2& value) override{};
+            virtual void rotatePitch(const Vector2& value) override{};
+
+            //return to main menu if game has ended.
+            virtual void rotateRoll(const Vector2& value) override{if (getGame()) if (getGame()->bEndGame) getGame()->end();};
+
+            virtual void updateLevel();
+
+            virtual inline bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+
+            float speed, damping, posforeward;
+            bool isFireing;
+
+        protected:
+            virtual void death() override;
+
+        private:
+            DodgeRace* getGame();
+            WeakPtr<DodgeRace> game;
+            WeakPtr<WorldEntity> lastEntity;
+            Camera* camera;
+            float lastTimeFront, lastTimeLeft, lastTime;
+            struct Velocity
+            {
+                float x;
+                float y;
+            } velocity, desiredVelocity;
+
+    };
+}
+
+#endif /* _DodgeRaceShip_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,17 @@
+SET_SOURCE_FILES(FlappyOrx_SRC_FILES
+BUILD_UNIT FlappyOrxBuildUnit.cc
+  FlappyOrx.cc
+  FlappyOrxShip.cc
+  FlappyOrxHUDinfo.cc
+END_BUILD_UNIT
+)
+
+ORXONOX_ADD_LIBRARY(flappyorx
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+    weapons
+  SOURCE_FILES ${FlappyOrx_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrx.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrx.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrx.cc	(revision 11817)
@@ -0,0 +1,279 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leo Merholz
+ *      Pascal Schärli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlappyOrx.cc
+    @brief Implementation of the FlappyOrx class.
+*/
+
+#include "FlappyOrx.h"
+#include "Highscore.h"
+#include "core/CoreIncludes.h"
+
+
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/XMLPort.h"
+#include "gamestates/GSLevel.h"
+#include "chat/ChatManager.h"
+
+// ! HACK
+#include "infos/PlayerInfo.h"
+
+#include "FlappyOrxShip.h"
+
+#include "core/command/ConsoleCommand.h"
+#include "worldentities/ExplosionPart.h"
+#include <vector>
+
+namespace orxonox
+{
+    RegisterUnloadableClass(FlappyOrx);
+
+    FlappyOrx::FlappyOrx(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(FlappyOrx);
+
+        point = 0;                          //number of cleared tubes
+        bIsDead = true;
+        firstGame = true;                   //needed for the HUD
+
+        speedBase = 0;
+        speedIncrease = 0;
+        tubeDistanceBase = 0;
+        tubeDistanceIncrease = 0;
+        tubeDistance = 200.0f;                  //distance between tubes
+        tubeOffsetX = 500.0f;                    //tube offset (so that we can't see them spawn)
+
+        circlesUsed=0;
+        setHUDTemplate("FlappyOrxHUD");
+        scoreboardTemplate_ = "";
+    }
+    
+    void FlappyOrx::updatePlayerPos(float x){
+
+        //Spawn a new Tube when the spawn distance is reached
+        if(this->tubes.size()==0||x-tubes.back()+tubeOffsetX>tubeDistance){
+            spawnTube();
+            this->tubes.push(x+tubeOffsetX);
+        }
+        //Delete Tubes when we pass through them
+        if(this->tubes.size()!=0&&x>this->tubes.front()){
+            this->tubes.pop();
+            levelUp();
+        }
+        //Delete Asteroids which are not visible anymore
+        while(this->asteroids.size()!=0&&(this->asteroids.front())->getPosition().x<x-tubeOffsetX){
+            MovableEntity* deleteMe = asteroids.front();
+            asteroids.pop();
+            deleteMe->destroy();
+        }
+    }
+
+    //Gets called when we pass through a Tube
+    void FlappyOrx::levelUp(){
+        point++;
+        tubeDistance = tubeDistanceBase-tubeDistanceIncrease*point;            //smaller spawn Distance
+        getPlayer()->setSpeed(speedBase+speedIncrease*point);    //increase speed
+    }
+
+    //Returns our Ship
+    FlappyOrxShip* FlappyOrx::getPlayer(){
+        if (player == nullptr){
+            for (FlappyOrxShip* ship : ObjectList<FlappyOrxShip>()) {
+                player = ship;
+            }
+        }
+        return player;
+    }
+
+    //Spawn new Tube
+    void FlappyOrx::spawnTube(){
+        if (getPlayer() == nullptr)
+            return;
+
+        float space = 130.0f;    //vertical space between top and bottom tube
+        float height = (rnd()-0.5f)*(280.0f-space);  //Randomize height
+           
+        Vector3 pos = player->getPosition();
+
+        //create the two Asteroid fields (Tubes)
+        asteroidField(pos.x+tubeOffsetX,height-space/2,0.8f);  //bottom
+        asteroidField(pos.x+tubeOffsetX,height+space/2,-0.8f); //top
+    }
+
+    //Creates a new asteroid Field
+    void FlappyOrx::asteroidField(float x, float y, float slope){
+        float r = 20.0f;     //Radius of added Asteroids
+        int noadd = 0;  //how many times we failed to add a new asteroid
+
+        clearCircles();   //Delete Circles (we use circles to make sure we don't spawn two asteroids on top of eachother)
+        Circle newAsteroid = Circle();
+        newAsteroid.x=x;
+        newAsteroid.y=y;
+        newAsteroid.r=r;
+        addIfPossible(newAsteroid); //Add Asteroid at peak
+
+        //Fill up triangle with asteroids
+        while(noadd<5&&circlesUsed<NUM_CIRCLES){
+            if(slope>0)
+                newAsteroid.y=rnd(150+y)-150;   //create asteroid on bottom
+            else
+                newAsteroid.y=rnd(150-y)+y;     //create asteroid on top
+            
+            newAsteroid.x=x+(rnd()-0.5f)*(y-newAsteroid.y)/slope;
+            newAsteroid.r=r;
+           
+            int i = addIfPossible(newAsteroid); //Add Asteroid if it doesn't collide
+            if(i==0)
+                noadd++;
+            else if(i==2)
+                noadd=5;
+        }
+    }
+
+    //Create a new Asteroid
+    void FlappyOrx::createAsteroid(Circle &c){
+        MovableEntity* newAsteroid = new MovableEntity(player->getContext());
+
+        //Add Model fitting the Size of the Asteroid
+        if(c.r<=5)
+            newAsteroid->addTemplate(Asteroid5[rand()%NUM_ASTEROIDS]);
+        else if(c.r<=10)
+            newAsteroid->addTemplate(Asteroid10[rand()%NUM_ASTEROIDS]);
+        else if(c.r<=15)
+            newAsteroid->addTemplate(Asteroid15[rand()%NUM_ASTEROIDS]);
+        else
+            newAsteroid->addTemplate(Asteroid20[rand()%NUM_ASTEROIDS]);
+        
+        //Set position
+        newAsteroid->setPosition(Vector3(c.x, 0, c.y));
+
+        //Randomize orientation
+        newAsteroid->setOrientation(Vector3::UNIT_Z, Degree(rnd(360)));
+        newAsteroid->setOrientation(Vector3::UNIT_Y, Degree(rnd(360)));
+
+        //add to Queue (so that we can delete it again)
+        asteroids.push(newAsteroid);
+    }
+
+    //Deletes Asteroids array which stores all the circles used to make sure no asteroids collide when spawning
+    void FlappyOrx::clearCircles(){
+        circlesUsed=0;
+        for(int i = 0; i<NUM_CIRCLES; i++){
+            circles[i].r=0;
+        }
+    }
+
+    //checks if two circles collide
+    bool FlappyOrx::circleCollision(Circle &c1, Circle &c2){
+        if(c1.r<=0 || c2.r<=0)
+            return false;
+        float x = c1.x - c2.x;
+        float y = c1.y - c2.y;
+        float r = c1.r + c2.r;
+
+        return x*x+y*y<r*r*1.5;
+    }
+
+    //Adds a circle if its not colliding
+    int FlappyOrx::addIfPossible(Circle c){
+        int i;
+        for(i=0; i<NUM_CIRCLES && this->circles[i].r!=0 && c.r>0;i++){
+            while(circleCollision(c,this->circles[i])){
+                c.r-=5; //when it collides, try to make it smaller
+            }
+        }
+        if(c.r<=0){
+            return 0;
+        }
+        circlesUsed++;
+        this->circles[i].x=c.x;
+        this->circles[i].y=c.y;
+        this->circles[i].r=c.r;
+        createAsteroid(c);
+        return 1;
+    }
+
+    bool FlappyOrx::isDead(){
+        return bIsDead;
+    }
+
+    void FlappyOrx::setDead(bool value){
+        bIsDead = value;
+        if(not value){
+            point = -1;
+            levelUp();
+        }
+    }
+
+    void FlappyOrx::start()
+    {
+        // Set variable to temporarily force the player to spawn.
+        this->bForceSpawn_ = true;
+
+        // Call start for the parent class.
+        Deathmatch::start();
+    }
+
+    //RIP
+    void FlappyOrx::death(){
+        bIsDead = true;
+        firstGame = false;
+        
+        //Set randomized deathmessages
+        if(point<7)         sDeathMessage = DeathMessage7[rand()%(DeathMessage7.size())];
+        else if(point<20)   sDeathMessage = DeathMessage20[rand()%(DeathMessage20.size())];
+        else if(point<30)   sDeathMessage = DeathMessage30[rand()%(DeathMessage30.size())];
+        else                sDeathMessage = DeathMessageover30[rand()%(DeathMessageover30.size())];
+        
+        //Update Highscore
+        if (Highscore::exists())
+        {
+            int score = this->getPoints();
+            Highscore::getInstance().storeScore("Flappy Orx", score, this->getPlayer()->getPlayer());
+        }
+
+        //Delete all Tubes and asteroids
+        while (!tubes.empty()){
+            tubes.pop();
+        }
+        while (!asteroids.empty()){
+            MovableEntity* deleteMe = asteroids.front();
+            asteroids.pop();
+            deleteMe->destroy();
+        }
+    }
+
+    void FlappyOrx::end()
+    {
+        GSLevel::startMainMenu();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrx.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrx.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrx.h	(revision 11817)
@@ -0,0 +1,173 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leo Merholz
+ *      Pascal Schärli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlappyOrx.h
+    @brief Gametype.
+    @ingroup FlappyOrx
+*/
+
+#ifndef _FlappyOrx_H__
+#define _FlappyOrx_H__
+
+#include "flappyorx/FlappyOrxPrereqs.h"
+    
+
+#include "gametypes/Deathmatch.h"
+#include <vector>
+
+namespace orxonox
+{
+    struct Circle{
+        float r;
+        float x;
+        float y;
+        Circle(float new_r, float new_x, float new_y){
+            r=new_r;
+            x=new_x;
+            y=new_y;
+        }
+        Circle(){
+            r=0;
+            x=0;
+            y=0;
+        }
+    };
+
+    class _FlappyOrxExport FlappyOrx : public Deathmatch
+    {
+        public:
+            FlappyOrx(Context* context);
+
+            virtual void start() override;
+            virtual void end() override;
+            virtual void death();
+           
+            void updatePlayerPos(float x);
+            void createAsteroid(Circle &c);
+            void asteroidField(float x, float y, float slope);
+            void spawnTube();
+           
+            int getPoints(){return this->point;}
+            
+            void levelUp();
+            
+            bool isDead();
+            void setDead(bool value);
+
+            FlappyOrxShip* getPlayer();
+
+            inline void setSpeedBase(float speedBase){ this-> speedBase =  speedBase;}
+            inline float  getSpeedBase(){ return speedBase;}
+            inline void setSpeedIncrease(float speedIncrease){ this-> speedIncrease =  speedIncrease;}
+            inline float  getSpeedIncrease(){ return speedIncrease;}
+
+            inline void setTubeDistanceBase(float tubeDistanceBase){ this-> tubeDistanceBase =  tubeDistanceBase;}
+            inline float  getTubeDistanceBase(){ return tubeDistanceBase;}
+            inline void setTubeDistanceIncrease(float tubeDistanceIncrease){ this-> tubeDistanceIncrease =  tubeDistanceIncrease;}
+            inline float  getTubeDistanceIncrease(){ return tubeDistanceIncrease;}
+
+            
+            bool bIsDead;
+            bool firstGame;
+            std::string sDeathMessage;
+            
+        private:
+            void clearCircles();
+            bool circleCollision(Circle &c1, Circle &c2);
+            int addIfPossible(Circle c);
+
+            int point;
+
+            float speedBase;
+            float speedIncrease;
+
+            float tubeDistanceBase;
+            float tubeDistanceIncrease;
+            float tubeDistance;
+            float tubeOffsetX;
+
+            WeakPtr<FlappyOrxShip> player;
+            std::queue<float> tubes;                  //Saves Position of Tubes
+            std::queue<MovableEntity*> asteroids;   //Stores Asteroids which build up the tubes
+
+            const static int NUM_CIRCLES = 6;
+            int circlesUsed;
+            Circle circles[NUM_CIRCLES];
+
+            const static int NUM_ASTEROIDS = 5;
+
+            const std::string Asteroid5[5] = {"Asteroid3_1","Asteroid3_2","Asteroid3_3","Asteroid3_4","Asteroid3_5"};
+            const std::string Asteroid10[5] = {"Asteroid6_1","Asteroid6_2","Asteroid6_3","Asteroid6_4","Asteroid6_5"};
+            const std::string Asteroid15[5] = {"Asteroid9_1","Asteroid9_2","Asteroid9_3","Asteroid9_4","Asteroid9_5"};
+            const std::string Asteroid20[5] = {"Asteroid12_1","Asteroid12_2","Asteroid12_3","Asteroid12_4","Asteroid12_5"};
+           
+            const std::vector<std::string> DeathMessage7 = {
+                "You should really try that again",
+                "You can do better, can you?",
+                "Hey, maybe you get a participation award, that's good isn't it?",
+                "Congratulations, you get a medal, a wooden one",
+                "That was flappin bad!",
+                "Well, that was a waste of time",
+                "You suck!",
+                "Maybe try SuperOrxoBros. That game is not as hard.",
+                "Here's a tip: Try not to fly into these grey thingies.",
+                "We won't comment on that."};
+            const std::vector<std::string> DeathMessage20 = {
+                "Getting better!",
+                "Training has paid off, huh?",
+                "Good average!",
+                "That was somehow enjoyable to watch",
+                "Flappin average",
+                "Getting closer to something",
+                "That wasn't crap, not bad",
+                "Surprisingly not bad."};
+            const std::vector<std::string> DeathMessage30 = {
+                "Flappin great",
+                "Good job!",
+                "Okay, we give you a shiny medal, not a golden one, tough",
+                "Maybe you should do that professionally",
+                "That was really good,!",
+                "We are proud of you"};
+            const std::vector<std::string> DeathMessageover30 = {
+                "You're flappin amazing",
+                "Fucking great job",
+                "Wow, we're really impressed",
+                "We will honor you!",
+                "Please, please do that again!",
+                "Take that golden medal! You've earned it",
+                "We are completely speechless! That was magnificent"};
+            
+
+
+
+    };
+}
+
+#endif /* _FlappyOrx_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxHUDinfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxHUDinfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxHUDinfo.cc	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leo Merholz
+ *      Pascal Schärli
+ *
+ *      Co-authors:
+ *      ...
+ */
+
+#include "FlappyOrxHUDinfo.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "FlappyOrx.h"
+
+namespace orxonox
+{
+    RegisterClass(FlappyOrxHUDinfo);
+
+    FlappyOrxHUDinfo::FlappyOrxHUDinfo(Context* context) : OverlayText(context)
+    {
+        RegisterObject(FlappyOrxHUDinfo);
+
+        this->FlappyOrxGame = nullptr;
+        this->bShowPoints_ = false;
+        this->bShowMessage_ = false;
+        this->messageID = 0;
+    }
+
+    void FlappyOrxHUDinfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FlappyOrxHUDinfo, XMLPort, xmlelement, mode);
+
+        XMLPortParam(FlappyOrxHUDinfo, "showpoints",    setShowPoints,    getShowPoints,    xmlelement, mode).defaultValues(false);
+        XMLPortParam(FlappyOrxHUDinfo, "showmessage",   setShowMessage,   getShowMessage,   xmlelement, mode).defaultValues(false);
+        XMLPortParam(FlappyOrxHUDinfo, "messageID",     setMessageID,     getMessageID,     xmlelement, mode).defaultValues(0);
+       
+    
+    }
+
+    void FlappyOrxHUDinfo::tick(float dt)
+    {
+        SUPER(FlappyOrxHUDinfo, tick, dt);
+
+        if (this->FlappyOrxGame)
+        {
+            if(not this->FlappyOrxGame->isDead()){
+                if(this->bShowPoints_){
+                    const std::string& points = "Score: "+multi_cast<std::string>(this->FlappyOrxGame->getPoints());
+                    setTextSize(0.04);
+                    this->setCaption(points);
+                }
+                else if(this->bShowMessage_){
+                    setTextSize(0);
+                }
+            }
+            else{
+                if(this->bShowPoints_){
+                    setTextSize(0);
+                }
+                else if(this->bShowMessage_){
+                    if(this->FlappyOrxGame->firstGame){
+                        if(messageID==3){
+                            setTextSize(0.05);
+                            this->setCaption("First click, then press space to start");
+                        }
+                    }
+                    else{
+                        std::string message;
+                        setTextSize(0.05);
+                        switch(messageID){
+                            case 0:
+                                message = "Game Over";
+                                setTextSize(0.1);
+                                this->setCaption(message);
+                            break;
+                            case 1:
+                                message = this->FlappyOrxGame->sDeathMessage;
+                            break;
+                            case 2:
+                                message = "Your Score: "+multi_cast<std::string>(this->FlappyOrxGame->getPoints())+
+                                                        "  Local High Score: "+multi_cast<std::string>(Highscore::getInstance().getHighestScoreOfGame("Flappy Orx"));
+                            break;
+                            case 3:
+                                time_t time = this->FlappyOrxGame->getPlayer()->timeUntilRespawn();
+                                if(time<=0)
+                                    message = "Press space to restart.";
+                                else
+                                    message = "Please wait "+multi_cast<std::string>(time)+" seconds.";
+                            break;
+                        }
+                        this->setCaption(message);
+                    }
+                }
+            }   
+        }
+    }
+
+    void FlappyOrxHUDinfo::changedOwner()
+    {
+        SUPER(FlappyOrxHUDinfo, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->FlappyOrxGame = orxonox_cast<FlappyOrx*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->FlappyOrxGame = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxHUDinfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxHUDinfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxHUDinfo.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *
+ */
+
+#ifndef _FlappyOrxHUDinfo_H__
+#define _FlappyOrxHUDinfo_H__
+
+#include "flappyorx/FlappyOrxPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+#include <cstring>
+
+namespace orxonox
+{
+    class _FlappyOrxExport FlappyOrxHUDinfo : public OverlayText, public Tickable
+    {
+        public:
+            FlappyOrxHUDinfo(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowPoints(bool value)
+                { this->bShowPoints_ = value; }
+            inline bool getShowPoints() const
+                { return this->bShowPoints_; }
+
+            inline void setShowMessage(bool value){
+                bShowMessage_ = value;
+            }
+            inline bool getShowMessage() const
+                { return this->bShowMessage_; }
+
+            inline void setMessageID(int value){
+                messageID = value;
+            }
+            inline int getMessageID() const
+                { return messageID; }
+
+        private:
+            FlappyOrx* FlappyOrxGame;
+            bool bShowPoints_;
+            bool bShowMessage_;
+            int messageID;
+    };
+}
+#endif /* _FlappyOrxHUDinfo_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxPrereqs.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leo Merholz
+ *      Pascal Schärli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the FlappyOrx module
+*/
+
+#ifndef _FlappyOrxPrereqs_H__
+#define _FlappyOrxPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(FLAPPYORX_STATIC_BUILD)
+#  ifdef FLAPPYORX_SHARED_BUILD
+#    define _FlappyOrxExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _FlappyOrxExport
+#    else
+#      define _FlappyOrxExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _FlappyOrxPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _FlappyOrxExport  __attribute__ ((visibility("default")))
+#  define _FlappyOrxPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _FlappyOrxExport
+#  define _FlappyOrxPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class FlappyOrx;
+    class FlappyOrxShip;
+    class FlappyOrxHUDinfo;
+}
+
+#endif /* _FlappyOrxPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxShip.cc	(revision 11817)
@@ -0,0 +1,182 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      FLeo Merholz
+ *      Pascal Schärli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlappyOrxShip.cc
+    @brief Implementation of the FlappyOrxShip class.
+*/
+
+#include "FlappyOrxShip.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/Camera.h"
+#include "graphics/ParticleSpawner.h"
+#include <math.h> 
+#include <ctime>
+
+namespace orxonox
+{
+    RegisterClass(FlappyOrxShip);
+
+    FlappyOrxShip::FlappyOrxShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(FlappyOrxShip);
+
+        isFlapping = false;
+        isDead = true;
+        velocity = 0;
+        speed = 0;
+        upwardThrust = 0;
+        gravity = 0;
+        particleLifespan = 0.1;
+        particleAge = 0;
+        deathTime = 0;
+
+        particlespawner_ = NULL;
+        
+    }
+
+    void FlappyOrxShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {   
+        SUPER(FlappyOrxShip, XMLPort, xmlelement, mode);
+        XMLPortParam(FlappyOrxShip,"speedBase", setSpeedBase, getSpeedBase, xmlelement,mode);
+        XMLPortParam(FlappyOrxShip,"speedIncrease", setSpeedIncrease, getSpeedIncrease, xmlelement,mode);
+        XMLPortParam(FlappyOrxShip,"tubeDistanceBase", setTubeDistanceBase, getTubeDistanceBase, xmlelement,mode);
+        XMLPortParam(FlappyOrxShip,"tubeDistanceIncrease", setTubeDistanceIncrease, getTubeDistanceIncrease, xmlelement,mode);
+
+        XMLPortParam(FlappyOrxShip,"upwardThrust", setUpwardthrust, getUpwardthrust, xmlelement,mode);
+        XMLPortParam(FlappyOrxShip,"gravity", setGravity, getGravity, xmlelement,mode);
+    }
+
+    void FlappyOrxShip::tick(float dt)
+    {
+        SUPER(FlappyOrxShip, tick, dt);
+
+
+        particleAge+=dt;
+        //the particle spawner that generates the fire from the backpack when pressed
+        if (particlespawner_ == NULL) {
+            for (WorldEntity* object : this->getAttachedObjects())
+            {
+                if (object->isA(Class(ParticleSpawner)))
+                particlespawner_ = (ParticleSpawner*) object;
+            }
+        }
+        else if(particleAge>particleLifespan){
+            particlespawner_->setLifetime(1);
+        }
+
+
+        //Execute movement
+        if (this->hasLocalController())
+        {
+            if(getHealth()<0){
+                setHealth(1);
+                getGame()->death();
+                death();   
+            }
+            Vector3 pos = getPosition();
+
+            getGame()->updatePlayerPos(pos.x);
+            
+
+            if(not isDead){
+                velocity += gravity*dt;
+                if(isFlapping){
+                    isFlapping = false;
+                    if(pos.z > -150)
+                        velocity = -upwardThrust;
+                }
+
+                pos += Vector3(speed, 0, velocity) * dt;
+            }
+            
+                        
+            // Camera
+            Camera* camera = this->getCamera();
+            if (camera != nullptr)
+            {
+                camera->setPosition(pos.x,-100,0);
+                camera->setOrientation(Vector3::UNIT_Z, Degree(0));
+
+            }
+
+            
+            setPosition(pos);
+            setOrientation(Vector3::UNIT_Y, Degree(270-velocity/10));
+
+            if(pos.z > 150){
+                getGame()->death();
+                death();
+            }
+            
+        }
+    }
+
+    time_t FlappyOrxShip::timeUntilRespawn(){
+        return 2-time(0)+deathTime;
+    }
+
+    void FlappyOrxShip::boost(bool boost){
+
+        if(not isDead){
+            particleAge = 0;
+        }  
+    
+        if(isDead&&timeUntilRespawn()<=0){
+            isDead = false;
+            getGame()->setDead(false);
+        }
+        isFlapping=boost;
+    }
+
+  
+    FlappyOrx* FlappyOrxShip::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (FlappyOrx* flappyOrx : ObjectList<FlappyOrx>())
+                game = flappyOrx;
+        }
+        return game;
+    }
+
+    void FlappyOrxShip::death()
+    {
+        isDead = true;
+
+        deathTime = time(0);
+        Vector3 pos = getPosition();
+        pos.x = 0;
+        pos.z = 0;
+        pos.y = 0;
+        velocity = 0;
+        setPosition(pos);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/flappyorx/FlappyOrxShip.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leo Merholz
+ *      Pascal Schärli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlappyOrxShip.h
+    @brief Declaration of the FlappyOrxShip class.
+*/
+
+#ifndef _FlappyOrxShip_H__
+#define _FlappyOrxShip_H__
+
+#include "flappyorx/FlappyOrxPrereqs.h"
+
+#include "weapons/WeaponsPrereqs.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "graphics/ParticleSpawner.h"
+#include "FlappyOrx.h"
+
+
+namespace orxonox
+{
+    class _FlappyOrxExport FlappyOrxShip : public SpaceShip
+    {
+        public:
+            FlappyOrxShip(Context* context);
+
+            virtual void tick(float dt) override;
+
+            // Starts or stops fireing
+            virtual void boost(bool bBoost) override;
+            
+            inline void  setSpeedBase(float speedBase){ getGame()->setSpeedBase(speedBase);}
+            inline float getSpeedBase(){ return getGame()->getSpeedBase();}
+            inline void  setSpeedIncrease(float speedIncrease){ getGame()->setSpeedIncrease(speedIncrease);}
+            inline float getSpeedIncrease(){ return getGame()->getSpeedIncrease();}
+
+            inline void setTubeDistanceBase(float tubeDistanceBase){ getGame()->setTubeDistanceBase(tubeDistanceBase);}
+            inline float  getTubeDistanceBase(){ return getGame()->getTubeDistanceBase();}
+            inline void setTubeDistanceIncrease(float tubeDistanceIncrease){ getGame()->setTubeDistanceIncrease(tubeDistanceIncrease);}
+            inline float  getTubeDistanceIncrease(){ return getGame()->getTubeDistanceIncrease();}
+
+            inline void  setUpwardthrust( float upwardThrust ){ this->upwardThrust = upwardThrust; }
+            inline float getUpwardthrust(){ return this->upwardThrust; }
+            inline void  setGravity( float gravity ){ this->gravity = gravity; }
+            inline float getGravity(){ return this->gravity; }
+
+            inline void setSpeed( float speed ){ this->speed = speed; }
+            inline float getSpeed( ){ return this->speed; }
+            
+   
+            virtual time_t timeUntilRespawn();
+            
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+
+        protected:
+            virtual void death() override;
+        private:
+            FlappyOrx* getGame();
+            WeakPtr<FlappyOrx> game;
+            ParticleSpawner* particlespawner_;
+            bool isFlapping;
+            bool isDead;
+            float velocity;
+            float speed, upwardThrust, gravity;
+            float particleAge, particleLifespan;
+            time_t deathTime;
+
+    };
+}
+
+#endif /* _FlappyOrxShip_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,20 @@
+SET_SOURCE_FILES(GAMETYPES_SRC_FILES
+  SpaceRace.cc
+  RaceCheckPoint.cc
+  SpaceRaceManager.cc
+
+  SpaceRaceBot.cc
+  SpaceRaceController.cc
+)
+
+ORXONOX_ADD_LIBRARY(gametypes
+  PLUGIN
+  FIND_HEADER_FILES
+  TOLUA_FILES
+  PCH_FILE
+    GametypesPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+    objects
+  SOURCE_FILES ${GAMETYPES_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/GametypesPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/GametypesPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/GametypesPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btTransform.h>
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/GametypesPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/GametypesPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/GametypesPrereqs.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _GametypesPrereqs_H__
+#define _GametypesPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(Gametypes_STATIC_BUILD)
+#  ifdef GAMETYPES_SHARED_BUILD
+#    define _GametypesExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _GametypesExport
+#    else
+#      define _GametypesExport __declspec(dllimport)
+#    endif
+#  endif
+#elif defined ( ORXONOX_GCC_VISIBILITY )
+#  define _GametypesExport  __attribute__ ((visibility("default")))
+#else
+#  define _GametypesExport
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class SpaceRace;
+    class OldSpaceRace;
+    class SpaceRaceManager;
+    class SpaceRaceBot;
+    class SpaceRaceController;
+}
+
+#endif /* _GametypesPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/RaceCheckPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/RaceCheckPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/RaceCheckPoint.cc	(revision 11817)
@@ -0,0 +1,161 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Mauro Salomon
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "RaceCheckPoint.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "chat/ChatManager.h"
+
+#include <infos/PlayerInfo.h>
+#include <worldentities/ControllableEntity.h>
+
+#include "SpaceRace.h"
+
+namespace orxonox
+{
+    RegisterClass(RaceCheckPoint);
+
+    RaceCheckPoint::RaceCheckPoint(Context* context) : DistanceMultiTrigger(context),
+            RadarViewable(this, static_cast<WorldEntity*> (this))
+    {
+        RegisterObject(RaceCheckPoint);
+        this->setDistance(100);
+        this->setBeaconMode("off");
+        this->setBroadcast(false);
+        this->setSimultaneousTriggerers(100);
+
+        this->setRadarObjectColour(ColourValue::Blue);
+        this->setRadarObjectShape(RadarViewable::Shape::Triangle);
+        this->setRadarVisibility(false);
+        this->settingsChanged();
+
+        this->checkpointIndex_ = 0;
+        this->bIsLast_ = false;
+        this->timeLimit_ = 0;
+    }
+
+    RaceCheckPoint::~RaceCheckPoint()
+    {
+
+    }
+
+    void RaceCheckPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(RaceCheckPoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(RaceCheckPoint, "checkpointindex", setCheckpointIndex, getCheckpointIndex, xmlelement, mode).defaultValues(0);
+        XMLPortParam(RaceCheckPoint, "islast", setLast, isLast, xmlelement, mode).defaultValues(false);
+        XMLPortParam(RaceCheckPoint, "timelimit", setTimelimit, getTimeLimit, xmlelement, mode).defaultValues(0);
+        XMLPortParam(RaceCheckPoint, "nextcheckpoints", setNextCheckpointsAsVector3, getNextCheckpointsAsVector3, xmlelement, mode);
+    }
+
+    void RaceCheckPoint::fire(bool bIsTriggered, BaseObject* originator)
+    {
+        DistanceMultiTrigger::fire(bIsTriggered, originator);
+
+        if (bIsTriggered)
+        {
+            ControllableEntity* entity = orxonox_cast<ControllableEntity*>(originator);
+            if (entity)
+                this->players_.push_back(entity->getPlayer());
+        }
+    }
+
+    void RaceCheckPoint::setTimelimit(float timeLimit)
+    {
+        this->timeLimit_ = timeLimit;
+        if (this->timeLimit_ != 0)
+        {
+            std::string message = "You have " + multi_cast<std::string>(this->timeLimit_)
+            + " seconds to reach the check point " + multi_cast<std::string>(this->checkpointIndex_ + 1);
+            this->getGametype()->getGametypeInfo()->sendAnnounceMessage(message);
+            ChatManager::message(message);
+        }
+    }
+
+    void RaceCheckPoint::setNextCheckpointsAsVector3(const Vector3& checkpoints)
+    {
+        this->nextCheckpoints_.clear();
+
+        if (checkpoints.x > -0.5)
+            this->nextCheckpoints_.insert(static_cast<int>(checkpoints.x + 0.5)); // the red number has the type double and for the cast (to int) is added 0.5 so that the cast works correctly
+        if (checkpoints.y > -0.5)
+            this->nextCheckpoints_.insert(static_cast<int>(checkpoints.y + 0.5));
+        if (checkpoints.z > -0.5)
+            this->nextCheckpoints_.insert(static_cast<int>(checkpoints.z + 0.5));
+    }
+
+    PlayerInfo* RaceCheckPoint::getPlayer(unsigned int clientID) const
+    {
+        if (players_.size() > 0)
+        {
+            for (size_t i = 0; i < players_.size(); i++)
+            {
+                if (this->players_[i]->getClientID() == clientID)
+                {
+                    return players_[i];
+                }
+            }
+        }
+        return nullptr;
+    }
+
+    bool RaceCheckPoint::playerWasHere(PlayerInfo* player) const
+    {
+        if (players_.size() > 0)
+        {
+            for (size_t i = 0; i < players_.size(); i++)
+            {
+                if (this->players_[i] == player)
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    Vector3 RaceCheckPoint::getNextCheckpointsAsVector3()
+    {
+        Vector3 checkpoints(-1,-1,-1); int count=0;
+        for (int nextCheckpoint : nextCheckpoints_)
+        {
+            switch (count)
+            {
+                case 0: checkpoints.x = static_cast<Ogre::Real>(nextCheckpoint); break;
+                case 1: checkpoints.y = static_cast<Ogre::Real>(nextCheckpoint); break;
+                case 2: checkpoints.z = static_cast<Ogre::Real>(nextCheckpoint); break;
+            }
+            ++count;
+        }
+        return checkpoints;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/RaceCheckPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/RaceCheckPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/RaceCheckPoint.h	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Mauro Salomon
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _RaceCheckPoint_H__
+#define _RaceCheckPoint_H__
+
+#include "gametypes/GametypesPrereqs.h"
+#include "objects/triggers/DistanceMultiTrigger.h"
+#include "interfaces/RadarViewable.h"
+
+namespace orxonox
+{
+    /**
+     @brief
+     The RaceCheckPoint class enables the creation of a check point to use in a SpaceRace level.
+     Don't forget to control the indexes of your check points and to set one last check point
+     */
+    class _GametypesExport RaceCheckPoint: public DistanceMultiTrigger,
+            public RadarViewable
+    {
+        public:
+            RaceCheckPoint(Context* context);
+            virtual ~RaceCheckPoint();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setCheckpointIndex(int checkpointIndex)
+            {
+                this->checkpointIndex_ = checkpointIndex;
+            }
+            inline int getCheckpointIndex() const
+            {
+                return this->checkpointIndex_;
+            }
+
+            void setNextCheckpointsAsVector3(const Vector3& checkpoints);
+            Vector3 getNextCheckpointsAsVector3();
+
+            const std::set<int>& getNextCheckpoints()
+            {
+                return nextCheckpoints_;
+            }
+            inline void setLast(bool isLast)
+            {
+                this->bIsLast_ = isLast;
+            }
+            inline bool isLast() const
+            {
+                return this->bIsLast_;
+            }
+
+            virtual void setTimelimit(float timeLimit);
+            inline float getTimeLimit() const
+            {
+                return this->timeLimit_;
+            }
+
+            PlayerInfo* getPlayer(unsigned int clientID) const;
+
+            bool playerWasHere(PlayerInfo* ) const;
+
+            inline void resetPlayer()
+            {
+                this->players_.clear();
+            }
+
+        protected:
+
+            virtual void fire(bool bIsTriggered, BaseObject* originator) override;
+
+            virtual inline const WorldEntity* getWorldEntity() const override
+            {
+                return this;
+            }
+
+        private:
+
+            int checkpointIndex_; ///< The index of this check point. The race starts with the check point with the index 0
+            std::set<int> nextCheckpoints_; ///< the indexes of the next check points
+            bool bIsLast_; ///< True if this check point is the last of the level. There can be only one last check point for each level and there must be a last check point in the level.
+            float timeLimit_; ///< The time limit (from the start of the level) to reach this check point. If the check point is reached after this time, the game ends and the player looses.
+            std::vector<PlayerInfo*> players_; ///< The player that reached the checkpoint
+    };
+}
+
+#endif /* _RaceCheckPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRace.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRace.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRace.cc	(revision 11817)
@@ -0,0 +1,238 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *     Mauro Salomon
+ *   Co-authors:
+ *      Celine Egger*/
+        
+
+
+
+/*
+Edited, Renewed and Revised by 
+        Berkay Berabi
+        Louis Meile
+ 
+ 
+To-do- list by Louis Meile and Berkay Berabi for future projects :
+- improve AI (SpaceRaceController): 
+i) so far bots arent able to evade obstacles. fix that!
+ii) bots should be able to use pickups
+- game crashes when bot wins the game(this is a huge problem you should work with the log file to find out what the errors are )
+- bots rotate while waiting for the countdown to end. make it stop!
+- add elements to level file to make it even more fun to play. be creative!
+*/
+
+
+#include "SpaceRace.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "util/Convert.h"
+#include "util/Math.h"
+#include "infos/Bot.h"
+#include "items/Engine.h"
+#include "controllers/HumanController.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "infos/Bot.h"
+#include "SpaceRaceBot.h"
+#include "items/Engine.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "util/Convert.h"
+#include "util/Math.h"
+#include "SpaceRaceBot.h"
+#include "items/Engine.h"
+#include <vector>
+
+
+namespace orxonox
+{
+    RegisterUnloadableClass(SpaceRace);
+
+    SpaceRace::SpaceRace(Context* context) : Gametype(context)
+    {
+        RegisterObject(SpaceRace);
+
+        this->botclass_ = Class(SpaceRaceBot);
+        this->cantMove_ = false;
+        this->bTimeIsUp_ = false;
+
+        this->numberOfBots_ = 5; // quick fix: don't allow default-bots to enter the race 
+        //we fixed the number of bots in order to have the same starting position all the time ! 
+    }
+
+    void SpaceRace::start()
+    {
+        // define spawn positions of the 5 bots
+
+        float startpos[15];
+        
+        startpos[0] =100;
+        startpos[1] =-40;
+        startpos[2] =0;
+        
+        startpos[3] =100;
+        startpos[4] =-40;
+        startpos[5] =100;
+        
+        startpos[6] =100;
+        startpos[7] =-40;
+        startpos[8] =-100;
+        
+        startpos[9] =0;
+        startpos[10] =-40;
+        startpos[11] =-80;
+        
+        startpos[12] =0;
+        startpos[13] =-40;
+        startpos[14] =80;
+
+        Gametype::start();
+
+        this->spawnPlayersIfRequested();
+        this->cantMove_ = true;
+        //players are unable to move while countdown is running
+        for (Engine* engine : ObjectList<Engine>())
+        {
+            engine->setActive(false);
+        }
+
+        //append spawn positions to bots
+        int a,b,c;
+        a=0;
+        b=1;
+        c=2;
+
+        for (SpaceRaceBot* bot : ObjectList<SpaceRaceBot>())
+        {
+            bot->getControllableEntity()->setPosition(startpos[a], startpos[b], startpos[c]);
+            a += 3;
+            b += 3;
+            c += 3;
+        }
+
+        std::string message("Use headphones to hear the countdown!");
+        this->getGametypeInfo()->sendAnnounceMessage(message);
+        ChatManager::message(message);
+
+        //after 11 seconds , countdownFinished function is called to activate bots` engines
+        Timer* countdownTimer = new Timer();
+        countdownTimer->setTimer(11, false, createExecutor(createFunctor(&SpaceRace::countdownFinished, this)));
+    }
+
+
+
+
+    void SpaceRace::end()
+    {
+        this->clock_.capture();
+        int s = this->clock_.getSeconds();
+        int ms = static_cast<int>(this->clock_.getMilliseconds() - 1000*s);
+        std::string message;
+
+        if (this->bTimeIsUp_)
+        {
+            message = multi_cast<std::string>(s) + "." + multi_cast<std::string>(ms) + " seconds !!\n"
+                        + "You lose!";
+        }
+        else
+        {
+            message = "You win!! Final check point reached after "+ multi_cast<std::string>(s)
+                        + "." + multi_cast<std::string>(ms) + " seconds.";
+        }
+        if (!this->hasEnded())
+        {
+            this->getGametypeInfo()->sendAnnounceMessage(message);
+            ChatManager::message(message);
+        }
+        this->Gametype::end();
+    }
+
+    void SpaceRace::newCheckpointReached(RaceCheckPoint* checkpoint, PlayerInfo* player)
+    {
+        this->checkpointReached_[player] = checkpoint;
+
+        this->clock_.capture();
+        int s = this->clock_.getSeconds();
+        int ms = this->clock_.getMilliseconds() % 1000;
+
+       
+    
+        const std::string& message = player->getName() + " reached the checkpoint " + multi_cast<std::string>(checkpoint->getCheckpointIndex() + 1) 
+        + "after " + multi_cast<std::string>(s) + "." + multi_cast<std::string>(ms) + " seconds.";
+        this->getGametypeInfo()->sendAnnounceMessage(message);
+        ChatManager::message(message);
+
+    }
+
+    void SpaceRace::countdownFinished()//activates the engines of all players
+    {
+
+        std::string message("RACE STARTED ");
+        this->getGametypeInfo()->sendAnnounceMessage(message);
+        ChatManager::message(message);
+
+
+        for (Engine* engine : ObjectList<Engine>())
+            engine->setActive(true);
+    }
+
+    void SpaceRace::playerEntered(PlayerInfo* player)
+    {
+        Gametype::playerEntered(player);
+
+        const std::string& message = player->getName() + " entered the game";
+        ChatManager::message(message);
+    }
+
+
+    void SpaceRace::addBots(unsigned int amount) //function that add the bots to the game
+    {
+        for (unsigned int i = 1; i <= amount; ++i){
+            this->botclass_.fabricate(this->getContext());
+        }
+    }
+
+
+    //set bot configurations
+    bool SpaceRace::allowPawnHit(Pawn* victim, Pawn* originator)
+    {
+        return true;
+    }
+
+    bool SpaceRace::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        return true;
+    }
+
+    bool SpaceRace::allowPawnDeath(Pawn* victim, Pawn* originator)// false because the bots can not recognize the objects and die to earlyif they can
+    {
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRace.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRace.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRace.h	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Mauro Salomon
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SpaceRace_H__
+#define _SpaceRace_H__
+
+#include "gametypes/GametypesPrereqs.h"
+
+#include <set>
+#include <string>
+# include <vector>
+
+#include <util/Clock.h>
+
+#include "gametypes/Gametype.h"
+
+#include "SpaceRaceManager.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The SpaceRace class enables the creation of a space race level, where the player has to reach check points in a given order.
+    */
+    class _GametypesExport SpaceRace : public Gametype
+    {
+        friend class RaceCheckPoint;
+
+
+        public:
+            SpaceRace(Context* context);
+            virtual ~SpaceRace() {}
+
+            virtual void start() override;
+            virtual void end() override;
+            virtual void countdownFinished();
+            virtual void addBots(unsigned int amount) override; //<! overwrite function in order to bypass the addbots command.
+
+
+
+            virtual void playerEntered(PlayerInfo* player) override;
+
+            //virtual void newCheckpointReached();
+
+            void newCheckpointReached(RaceCheckPoint* checkpoint, PlayerInfo* player);
+            
+
+
+            inline RaceCheckPoint* getCheckpointReached(PlayerInfo* player)
+                { return this->checkpointReached_[player]; }
+
+            inline void setTimeIsUp()
+                { this->bTimeIsUp_ = true;}
+            inline Clock& getClock()
+                { return this->clock_; }
+
+            virtual bool allowPawnHit(Pawn* victim, Pawn* originator) override;
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator) override;
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator) override;
+
+        private:
+            bool cantMove_;                                            ///< Helper variable, used to stall the engines before the race starts.
+            std::map<PlayerInfo*, RaceCheckPoint*> checkpointReached_; ///< The number of the last check point reached by each player.
+            bool bTimeIsUp_;                                           ///< True if one of the check points is reached too late.
+
+            Clock clock_; ///< The clock starts running at the beginning of the game. It is used to give the time at each check point, the give the time at the end of the game, and to stop the game if a check point is reached too late.
+    };
+}
+
+#endif /* _SpaceRace_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceBot.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceBot.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceBot.cc	(revision 11817)
@@ -0,0 +1,38 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *  Created on: Oct 8, 2012
+ *      Author: purgham
+ */
+
+#include "SpaceRaceBot.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(SpaceRaceBot);
+
+    SpaceRaceBot::SpaceRaceBot(Context* context) : Bot(context){
+        RegisterObject(SpaceRaceBot);
+        this->defaultController_ = Class(SpaceRaceController);
+        this->createController();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceBot.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceBot.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceBot.h	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *  Created on: Oct 8, 2012
+ *      Author: purgham
+ */
+
+#ifndef SPACERACEBOT_H_
+#define SPACERACEBOT_H_
+
+#include "infos/Bot.h"
+#include "gametypes/GametypesPrereqs.h"
+#include "gametypes/SpaceRaceController.h"
+
+
+namespace orxonox
+{
+
+    class _GametypesExport SpaceRaceBot: public Bot
+    {
+        public:
+            SpaceRaceBot(Context* context);
+            virtual ~SpaceRaceBot() {}
+    };
+}
+
+
+#endif /* SPACERACEBOT_H_ */
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceController.cc	(revision 11817)
@@ -0,0 +1,536 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *  Created on: Oct 8, 2012
+ *      Author: purgham
+ */
+
+#include <gametypes/SpaceRaceController.h>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "gametypes/SpaceRaceManager.h"
+#include "collisionshapes/CollisionShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SpaceRaceController);
+
+    const int ADJUSTDISTANCE = 500;
+    const int MINDISTANCE = 5;
+    /*
+     * Idea: Find static Point (checkpoints the spaceship has to reach)
+     */
+    SpaceRaceController::SpaceRaceController(Context* context) :
+        ArtificialController(context)
+    {
+        RegisterObject(SpaceRaceController);
+        std::vector<RaceCheckPoint*> checkpoints;
+
+        virtualCheckPointIndex = -2;
+        if (ObjectList<SpaceRaceManager>().size() != 1)
+            orxout(internal_warning) << "Expected 1 instance of SpaceRaceManager but found " << ObjectList<SpaceRaceManager>().size() << endl;
+        for (SpaceRaceManager* manager : ObjectList<SpaceRaceManager>())
+        {
+            checkpoints = manager->getAllCheckpoints();
+            nextRaceCheckpoint_ = manager->findCheckpoint(0);
+        }
+
+        OrxAssert(!checkpoints.empty(), "No Checkpoints in Level");
+        checkpoints_ = checkpoints;
+        staticRacePoints_ = findStaticCheckpoints(nextRaceCheckpoint_, checkpoints);
+        // initialisation of currentRaceCheckpoint_
+        currentRaceCheckpoint_ = nullptr;
+
+        int i;
+        for (i = -2; findCheckpoint(i) != nullptr; i--)
+        {
+            continue;
+        }
+
+    }
+
+    //------------------------------
+    // functions for initialisation
+
+    void SpaceRaceController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SpaceRaceController, XMLPort, xmlelement, mode);
+        XMLPortParam(ArtificialController, "accuracy", setAccuracy, getAccuracy, xmlelement, mode).defaultValues(100.0f);
+        XMLPortObject(ArtificialController, WorldEntity, "waypoints", addWaypoint, getWaypoint, xmlelement, mode);
+    }
+
+    /*
+     * called from constructor 'SpaceRaceController'
+     * returns a vector of static Point (checkpoints the spaceship has to reach)
+     */
+    std::vector<RaceCheckPoint*> SpaceRaceController::findStaticCheckpoints(RaceCheckPoint* currentCheckpoint, const std::vector<RaceCheckPoint*>& allCheckpoints)
+    {
+        std::map<RaceCheckPoint*, int> zaehler; // counts how many times the checkpoint was reached (for simulation)
+        for (RaceCheckPoint* checkpoint : allCheckpoints)
+        {
+            zaehler.insert(std::pair<RaceCheckPoint*, int>(checkpoint,0));
+        }
+        int maxWays = rekSimulationCheckpointsReached(currentCheckpoint, zaehler);
+
+        std::vector<RaceCheckPoint*> returnVec;
+        for (const auto& mapEntry : zaehler)
+        {
+            if (mapEntry.second == maxWays)
+            {
+                returnVec.push_back(mapEntry.first);
+            }
+        }
+        return returnVec;
+    }
+
+    /*
+     * called from 'findStaticCheckpoints'
+     * return how many ways go from the given Checkpoint to the last Checkpoint (of the Game)
+     */
+    int SpaceRaceController::rekSimulationCheckpointsReached(RaceCheckPoint* currentCheckpoint, std::map<RaceCheckPoint*, int>& zaehler)
+    {
+
+        if (currentCheckpoint->isLast())
+        {// last point reached
+
+            zaehler[currentCheckpoint] += 1;
+            return 1; // 1 Way form the last point to this one
+        }
+        else
+        {
+            int numberOfWays = 0; // counts number of ways from this Point to the last point
+            for (int checkpointIndex : currentCheckpoint->getNextCheckpoints())
+            {
+                if (currentCheckpoint == findCheckpoint(checkpointIndex))
+                {
+                    //orxout() << currentCheckpoint->getCheckpointIndex()<<endl;
+                    continue;
+                }
+                if (findCheckpoint(checkpointIndex) == nullptr)
+                    orxout(internal_warning) << "Problematic Point: " << checkpointIndex << endl;
+                else
+                    numberOfWays += rekSimulationCheckpointsReached(findCheckpoint(checkpointIndex), zaehler);
+            }
+            zaehler[currentCheckpoint] += numberOfWays;
+            return numberOfWays; // returns the number of ways from this point to the last one
+        }
+    }
+
+    //-------------------------------------
+    // functions for dynamic Way-search
+
+    float SpaceRaceController::distanceSpaceshipToCheckPoint(RaceCheckPoint* CheckPoint)
+    {
+        if (this->getControllableEntity() != nullptr)
+        {
+            return (CheckPoint->getPosition()- this->getControllableEntity()->getPosition()).length();
+        }
+        return -1;
+    }
+
+    /*
+     * called by: 'tick' or  'adjustNextPoint'
+     * returns the next Checkpoint which the shortest way contains
+     */
+    RaceCheckPoint* SpaceRaceController::nextPointFind(RaceCheckPoint* raceCheckpoint)
+    {
+        float minDistance = 0;
+        RaceCheckPoint* minNextRaceCheckPoint = nullptr;
+
+        // find the next checkpoint with the minimal distance
+        for (int checkpointIndex : raceCheckpoint->getNextCheckpoints())
+        {
+            RaceCheckPoint* nextRaceCheckPoint = findCheckpoint(checkpointIndex);
+            float distance = recCalculateDistance(nextRaceCheckPoint, this->getControllableEntity()->getPosition());
+
+            if (distance < minDistance || minNextRaceCheckPoint == nullptr)
+            {
+                minDistance = distance;
+                minNextRaceCheckPoint = nextRaceCheckPoint;
+            }
+
+        }
+
+        return minNextRaceCheckPoint;
+    }
+
+    /*
+     * called from 'nextPointFind'
+     * returns the distance between "currentPosition" and the next static checkpoint that can be reached from "currentCheckPoint"
+     */
+    float SpaceRaceController::recCalculateDistance(RaceCheckPoint* currentCheckPoint, const Vector3& currentPosition)
+    {
+        // find: looks if the currentCheckPoint is a staticCheckPoint (staticCheckPoint is the same as: static Point)
+        if (std::find(staticRacePoints_.begin(), staticRacePoints_.end(), currentCheckPoint) != staticRacePoints_.end())
+        {
+            return (currentCheckPoint->getPosition() - currentPosition).length();
+        }
+        else
+        {
+            float minimum = std::numeric_limits<float>::max();
+            for (int checkpointIndex : currentCheckPoint->getNextCheckpoints())
+            {
+                int dist_currentCheckPoint_currentPosition = static_cast<int> ((currentPosition- currentCheckPoint->getPosition()).length());
+
+                minimum = std::min(minimum, dist_currentCheckPoint_currentPosition + recCalculateDistance(findCheckpoint(checkpointIndex), currentCheckPoint->getPosition()));
+                // minimum of distanz from 'currentPosition' to the next static Checkpoint
+            }
+            return minimum;
+        }
+    }
+
+    /*called by 'tick'
+     *adjust chosen way of the Spaceship every "AdjustDistance" because spaceship could be displaced through an other one
+     */
+    RaceCheckPoint* SpaceRaceController::adjustNextPoint()
+    {
+        if (currentRaceCheckpoint_ == nullptr) // no Adjust possible
+
+        {
+            return nextRaceCheckpoint_;
+        }
+        if ((currentRaceCheckpoint_->getNextCheckpoints()).size() == 1) // no Adjust possible
+
+        {
+            return nextRaceCheckpoint_;
+        }
+
+        //Adjust possible
+
+        return nextPointFind(currentRaceCheckpoint_);
+    }
+
+    RaceCheckPoint* SpaceRaceController::findCheckpoint(int index) const
+    {
+        for (RaceCheckPoint* checkpoint : this->checkpoints_)
+            if (checkpoint->getCheckpointIndex() == index)
+                return checkpoint;
+        return nullptr;
+    }
+
+    /*RaceCheckPoint* SpaceRaceController::addVirtualCheckPoint( RaceCheckPoint* previousCheckpoint, int indexFollowingCheckPoint , const Vector3& virtualCheckPointPosition )
+    {
+        orxout()<<"add VCP at"<<virtualCheckPointPosition.x<<", "<<virtualCheckPointPosition.y<<", "<<virtualCheckPointPosition.z<<endl;
+        RaceCheckPoint* newTempRaceCheckPoint;
+        ObjectList<SpaceRaceManager> list;
+        for (ObjectList<SpaceRaceManager>::iterator it = list.begin(); it!= list.end(); ++it)
+        {
+            newTempRaceCheckPoint = new RaceCheckPoint((*it));
+        }
+        newTempRaceCheckPoint->setVisible(false);
+        newTempRaceCheckPoint->setPosition(virtualCheckPointPosition);
+        newTempRaceCheckPoint->setCheckpointIndex(virtualCheckPointIndex);
+        newTempRaceCheckPoint->setLast(false);
+        newTempRaceCheckPoint->setNextVirtualCheckpointsAsVector3(Vector3(indexFollowingCheckPoint,-1,-1));
+
+        Vector3 temp = previousCheckpoint->getVirtualNextCheckpointsAsVector3();
+        //orxout()<<"temp bei 0: ="<< temp.x<< temp.y<< temp.z<<endl;
+        checkpoints_.insert(checkpoints_.end(), newTempRaceCheckPoint);
+        int positionInNextCheckPoint;
+        for (int i = 0; i <3; i++)
+        {
+            if(previousCheckpoint->getVirtualNextCheckpointsAsVector3()[i] == indexFollowingCheckPoint)
+            positionInNextCheckPoint=i;
+        }
+        switch(positionInNextCheckPoint)
+        {
+            case 0: temp.x=virtualCheckPointIndex; break;
+            case 1: temp.y=virtualCheckPointIndex; break;
+            case 2: temp.z=virtualCheckPointIndex; break;
+        }
+        previousCheckpoint->setNextVirtualCheckpointsAsVector3(temp); //Existiert internes Problem bei negativen index fueer next Checkpoint
+        virtualCheckPointIndex--;
+        //orxout()<<"temp bei 1: ="<< temp.x<< temp.y<< temp.z<<endl;
+        //orxout()<<"temp nach ausgabe: "<<previousCheckpoint->getVirtualNextCheckpointsAsVector3().x<<previousCheckpoint->getVirtualNextCheckpointsAsVector3().y<<previousCheckpoint->getVirtualNextCheckpointsAsVector3().z<<endl;
+        //OrxAssert(virtualCheckPointIndex < -1, "TO much virtual cp");
+        orxout()<<"id: "<< previousCheckpoint->getCheckpointIndex() <<", following:"<<indexFollowingCheckPoint<<" :       "<<temp.x<<", "<<temp.y<<", "<<temp.z<<";       ";
+         temp=previousCheckpoint->getNextCheckpointsAsVector3();
+         orxout()<<"id: "<< previousCheckpoint->getCheckpointIndex() <<":       "<<temp.x<<", "<<temp.y<<", "<<temp.z<<";       ";
+         orxout()<<endl;
+        return newTempRaceCheckPoint;
+    }*/
+
+    SpaceRaceController::~SpaceRaceController()
+    {
+        if (this->isInitialized())
+        {
+            for (int i =-1; i>virtualCheckPointIndex; i--)
+                delete findCheckpoint(i);
+        }
+    }
+
+    void SpaceRaceController::tick(float dt)
+    {
+        if (this->getControllableEntity() == nullptr || this->getControllableEntity()->getPlayer() == nullptr )
+        {
+            //orxout()<< this->getControllableEntity() << " in tick"<<endl;
+            return;
+        }
+        //FOR virtual Checkpoints
+        if(nextRaceCheckpoint_->getCheckpointIndex() < 0)
+        {
+            if( distanceSpaceshipToCheckPoint(nextRaceCheckpoint_) < 200)
+            {
+                currentRaceCheckpoint_=nextRaceCheckpoint_;
+                nextRaceCheckpoint_ = nextPointFind(nextRaceCheckpoint_);
+                lastPositionSpaceship=this->getControllableEntity()->getPosition();
+                //orxout()<< "CP "<< currentRaceCheckpoint_->getCheckpointIndex()<<" chanched to: "<< nextRaceCheckpoint_->getCheckpointIndex()<<endl;
+            }
+        }
+
+        if (nextRaceCheckpoint_->playerWasHere(this->getControllableEntity()->getPlayer()))
+        {//Checkpoint erreicht
+
+            currentRaceCheckpoint_ = nextRaceCheckpoint_;
+            OrxAssert(nextRaceCheckpoint_, "next race checkpoint undefined");
+            nextRaceCheckpoint_ = nextPointFind(nextRaceCheckpoint_);
+            lastPositionSpaceship = this->getControllableEntity()->getPosition();
+            //orxout()<< "CP "<< currentRaceCheckpoint_->getCheckpointIndex()<<" chanched to: "<< nextRaceCheckpoint_->getCheckpointIndex()<<endl;
+        }
+
+        else if ((lastPositionSpaceship-this->getControllableEntity()->getPosition()).length()/dt > ADJUSTDISTANCE)
+        {
+            nextRaceCheckpoint_ = adjustNextPoint();
+            lastPositionSpaceship = this->getControllableEntity()->getPosition();
+        }
+
+        // Abmessung fuer MINDISTANCE gut;
+
+        else if((lastPositionSpaceship - this->getControllableEntity()->getPosition()).length()/dt < MINDISTANCE )
+        {
+            this->moveToPosition(Vector3(rnd()*100, rnd()*100, rnd()*100));
+            this->spin();
+            //orxout(user_status) << "Mindistance reached" << std::endl;
+            return;
+        }
+        //orxout(user_status) << "dt= " << dt << ";  distance= " << (lastPositionSpaceship-this->getControllableEntity()->getPosition()).length() <<std::endl;
+        lastPositionSpaceship = this->getControllableEntity()->getPosition();
+       
+        this->boostControl();
+        this->moveToPosition(nextRaceCheckpoint_->getPosition());
+        this->boostControl();
+    }
+
+    // True if a coordinate of 'pointToPoint' is smaller then the corresponding coordinate of 'groesse'
+    bool SpaceRaceController::vergleicheQuader(const Vector3& pointToPoint, const Vector3& groesse)
+    {
+        if(std::abs(pointToPoint.x) < groesse.x)
+            return true;
+        if(std::abs(pointToPoint.y) < groesse.y)
+            return true;
+        if(std::abs(pointToPoint.z) < groesse.z)
+            return true;
+        return false;
+
+    }
+
+    bool SpaceRaceController::directLinePossible(RaceCheckPoint* racepoint1, RaceCheckPoint* racepoint2, const std::vector<StaticEntity*>& allObjects)
+    {
+
+        Vector3 cP1ToCP2 = (racepoint2->getPosition() - racepoint1->getPosition()) / (racepoint2->getPosition() - racepoint1->getPosition()).length(); //unit Vector
+        Vector3 centerCP1 = racepoint1->getPosition();
+        btVector3 positionObject;
+        btScalar radiusObject;
+
+        for (StaticEntity* object : allObjects)
+        {
+            for (int everyShape=0; object->getAttachedCollisionShape(everyShape) != nullptr; everyShape++)
+            {
+                btCollisionShape* currentShape = object->getAttachedCollisionShape(everyShape)->getCollisionShape();
+                if(currentShape == nullptr)
+                continue;
+
+                currentShape->getBoundingSphere(positionObject,radiusObject);
+                Vector3 positionObjectNonBT(positionObject.x(), positionObject.y(), positionObject.z());
+                if((powf((cP1ToCP2.dotProduct(centerCP1-positionObjectNonBT)),2)-(centerCP1-positionObjectNonBT).dotProduct(centerCP1-positionObjectNonBT)+powf(radiusObject, 2))>0)
+                {
+                    return false;
+                }
+
+            }
+        }
+        return true;
+
+    }
+
+    /*void SpaceRaceController::computeVirtualCheckpoint(RaceCheckPoint* racepoint1, RaceCheckPoint* racepoint2, const std::vector<StaticEntity*>& allObjects)
+    {
+        Vector3 cP1ToCP2=(racepoint2->getPosition()-racepoint1->getPosition()) / (racepoint2->getPosition()-racepoint1->getPosition()).length(); //unit Vector
+        Vector3 centerCP1=racepoint1->getPosition();
+        btVector3 positionObject;
+        btScalar radiusObject;
+
+        for (std::vector<StaticEntity*>::iterator it = allObjects.begin(); it != allObjects.end(); ++it)
+        {
+            for (int everyShape=0; (*it)->getAttachedCollisionShape(everyShape) != nullptr; everyShape++)
+            {
+                btCollisionShape* currentShape = (*it)->getAttachedCollisionShape(everyShape)->getCollisionShape();
+                if(currentShape == nullptr)
+                continue;
+
+                currentShape->getBoundingSphere(positionObject,radiusObject);
+                Vector3 positionObjectNonBT(positionObject.x(), positionObject.y(), positionObject.z());
+                Vector3 norm_r_CP = cP1ToCP2.crossProduct(centerCP1-positionObjectNonBT);
+
+                if(norm_r_CP.length() == 0){
+                    Vector3 zufall;
+                    do{
+                        zufall=Vector3(rnd(),rnd(),rnd());//random
+                    }while((zufall.crossProduct(cP1ToCP2)).length() == 0);
+                    norm_r_CP=zufall.crossProduct(cP1ToCP2);
+                }
+                Vector3 VecToVCP = norm_r_CP.crossProduct(cP1ToCP2);
+                float distanzToCP1 = sqrt(powf(radiusObject,4)/(powf((centerCP1-positionObjectNonBT).length(), 2)-powf(radiusObject,2))+powf(radiusObject,2));
+                float distanzToCP2 = sqrt(powf(radiusObject,4)/(powf((racepoint2->getPosition()-positionObjectNonBT).length(), 2)-powf(radiusObject,2))+powf(radiusObject,2));
+                float distanz = std::max(distanzToCP1,distanzToCP2);
+                //float distanz = 0.0f; //TEMPORARY
+                Vector3 newCheckpointPositionPos = positionObjectNonBT+(distanz*VecToVCP)/VecToVCP.length();
+                Vector3 newCheckpointPositionNeg = positionObjectNonBT-(distanz*VecToVCP)/VecToVCP.length();
+                if((newCheckpointPositionPos - centerCP1).length() + (newCheckpointPositionPos - (centerCP1+cP1ToCP2)).length() < (newCheckpointPositionNeg - centerCP1).length() + (newCheckpointPositionNeg - (centerCP1+cP1ToCP2)).length() )
+                {
+                    RaceCheckPoint* newVirtualCheckpoint = addVirtualCheckPoint(racepoint1,racepoint2->getCheckpointIndex(), newCheckpointPositionPos);
+                }
+                else
+                {
+                    RaceCheckPoint* newVirtualCheckpoint = addVirtualCheckPoint(racepoint1,racepoint2->getCheckpointIndex(), newCheckpointPositionNeg);
+                }
+                return;
+            }
+        }
+
+    }*/
+
+    /*void SpaceRaceController::placeVirtualCheckpoints(RaceCheckPoint* racepoint1, RaceCheckPoint* racepoint2)
+    {
+        Vector3 point1 = racepoint1->getPosition();
+        Vector3 point2 = racepoint2->getPosition();
+        std::vector<StaticEntity*> problematicObjects;
+
+        ObjectList<StaticEntity> list;
+        for (ObjectList<StaticEntity>::iterator it = list.begin(); it!= list.end(); ++it)
+        {
+
+            if (dynamic_cast<RaceCheckPoint*>(*it) != nullptr)
+            {
+                continue;
+            } // does not work jet
+
+            problematicObjects.insert(problematicObjects.end(), *it);
+            //it->getScale3D();// vector fuer halbe wuerfellaenge
+        }
+
+        if(!directLinePossible(racepoint1, racepoint2, problematicObjects))
+        {
+            //orxout()<<"From "<<racepoint1->getCheckpointIndex()<<" to "<<racepoint2->getCheckpointIndex()<<"produces: "<< virtualCheckPointIndex<<endl;
+            computeVirtualCheckpoint(racepoint1, racepoint2, problematicObjects);
+        }
+
+        //
+        //        do{
+        //            zufall=Vector3(rnd(),rnd(),rnd());//random
+        //        }while((zufall.crossProduct(objectmiddle-racepoint1->getPosition())).length()==0);
+        //
+        //        Vector3 normalvec=zufall.crossProduct(objectmiddle-racepoint1->getPosition());
+        //        // a'/b'=a/b => a' =b'*a/b
+        //        float laengeNormalvec=(objectmiddle-racepoint1->getPosition()).length()/sqrt((objectmiddle-racepoint1->getPosition()).squaredLength()-radius*radius)*radius;
+        //        addVirtualCheckPoint(racepoint1,racepoint2->getCheckpointIndex(), objectmiddle+normalvec/normalvec.length()*laengeNormalvec);
+
+        //        Vector3 richtungen [6];
+        //        richtungen[0]= Vector3(1,0,0);
+        //        richtungen[1]= Vector3(-1,0,0);
+        //        richtungen[2]= Vector3(0,1,0);
+        //        richtungen[3]= Vector3(0,-1,0);
+        //        richtungen[4]= Vector3(0,0,1);
+        //        richtungen[5]= Vector3(0,0,-1);
+        //
+        //        for (int i = 0; i< 6; i++)
+        //        {
+        //            const int STEPS=100;
+        //            const float PHI=1.1;
+        //            bool collision=false;
+        //
+        //            for (int j =0; j<STEPS; j++)
+        //            {
+        //                Vector3 tempPosition=(point1 - (point2-point1+richtungen[i]*PHI)*(float)j/STEPS);
+        //                for (std::vector<StaticEntity*>::iterator it = problematicObjects.begin(); it!=problematicObjects.end(); ++it)
+        //                {
+        //                    btVector3 positionObject;
+        //                    btScalar radiusObject;
+        //                    if((*it)==nullptr)
+        //                    {   orxout()<<"Problempoint 1.1"<<endl; continue;}
+        //                    //TODO: Probably it points on a wrong object
+        //                    for (int everyShape=0; (*it)->getAttachedCollisionShape(everyShape)!=nullptr; everyShape++)
+        //                    {
+        //                        if((*it)->getAttachedCollisionShape(everyShape)->getCollisionShape()==nullptr)
+        //                        {    continue;}
+        //
+        //                        orxout()<<"Problempoint 2.1"<<endl;
+        //                        (*it)->getAttachedCollisionShape(everyShape)->getCollisionShape()->getBoundingSphere(positionObject,radiusObject);
+        //                        Vector3 positionObjectNonBT(positionObject.x(), positionObject.y(), positionObject.z());
+        //                        if (((tempPosition - positionObjectNonBT).length()<radiusObject) && (vergleicheQuader((tempPosition-positionObjectNonBT),(*it)->getScale3D())))
+        //                        {
+        //                            collision=true; break;
+        //                        }
+        //                    }
+        //                    if(collision) break;
+        //                }
+        //                if(collision)break;
+        //            }
+        //            if(collision) continue;
+        //            // no collision => possible Way
+        //            for (float j =0; j<STEPS; j++)
+        //            {
+        //                Vector3 possiblePosition=(point1 - (point2-point1+richtungen[i]*PHI)*j/STEPS);
+        //                collision=false;
+        //                for(int ij=0; ij<STEPS; j++)
+        //                {
+        //                    Vector3 tempPosition=(possiblePosition - (point2-possiblePosition)*(float)ij/STEPS);
+        //                    for (std::vector<StaticEntity*>::iterator it = problematicObjects.begin(); it!=problematicObjects.end(); ++it)
+        //                    {
+        //                        btVector3 positionObject;
+        //                        btScalar radiusObject;
+        //                        if((*it)==nullptr)
+        //                        {   orxout()<<"Problempoint 1"<<endl; continue;}
+        //                        for (int everyShape=0; (*it)->getAttachedCollisionShape(everyShape)!=nullptr; everyShape++)
+        //                        {
+        //                            if((*it)->getAttachedCollisionShape(everyShape)->getCollisionShape()==nullptr)
+        //                            {   orxout()<<"Problempoint 2.2"<<endl; continue;}
+        //                            (*it)->getAttachedCollisionShape(everyShape)->getCollisionShape()->getBoundingSphere(positionObject,radiusObject);
+        //                            Vector3 positionObjectNonBT(positionObject.x(), positionObject.y(), positionObject.z());
+        //                            if (((tempPosition-positionObjectNonBT).length()<radiusObject) && (vergleicheQuader((tempPosition-positionObjectNonBT),(*it)->getScale3D())))
+        //                            {
+        //                                collision=true; break;
+        //                            }
+        //                        }
+        //                        if(collision) break;
+        //                    }
+        //                    if(collision)break;
+        //                    //addVirtualCheckPoint(racepoint1, racepoint2->getCheckpointIndex(), possiblePosition);
+        //                    return;
+        //                }
+        //
+        //            }
+        //        }
+
+    }*/
+}
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceController.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *
+ *  Created on: Oct 8, 2012
+ *      Author: purgham
+ */
+
+#ifndef SPACERACECONTROLLER_H_
+#define SPACERACECONTROLLER_H_
+
+#include "gametypes/GametypesPrereqs.h"
+#include "controllers/ArtificialController.h"
+#include "gametypes/Gametype.h"
+#include "gametypes/RaceCheckPoint.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    /**
+     * Conventions:
+     * -first Checkpoint has index 0
+     * -staticCheckPoint= static Point (see def over = constructor)
+     *@todo:
+     *  tICK KORRIGIEREN
+     */
+    class _GametypesExport SpaceRaceController: public ArtificialController,
+            public Tickable
+    {
+        public:
+            SpaceRaceController(Context* context);
+            virtual ~SpaceRaceController();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+        private:
+            float recCalculateDistance(RaceCheckPoint*, const Vector3& currentPosition);
+            float distanceSpaceshipToCheckPoint(RaceCheckPoint*);
+            RaceCheckPoint* nextPointFind(RaceCheckPoint*);
+            RaceCheckPoint* adjustNextPoint();
+            std::vector<RaceCheckPoint*> findStaticCheckpoints(RaceCheckPoint*, const std::vector<RaceCheckPoint*>&);
+            std::vector<RaceCheckPoint*> staticCheckpoints();
+            int rekSimulationCheckpointsReached(RaceCheckPoint*, std::map<RaceCheckPoint*, int>&);
+            // same as SpaceRaceManager, but needed to add virtuell Checkpoints ( Checkpoints which don't exist but needed to avoid collisions with big Objects)
+            RaceCheckPoint* findCheckpoint(int index) const;
+            //RaceCheckPoint * addVirtualCheckPoint(RaceCheckPoint*, int , const Vector3&);
+            //void placeVirtualCheckpoints(RaceCheckPoint*, RaceCheckPoint*);
+            bool vergleicheQuader(const Vector3&, const Vector3&);
+            bool directLinePossible(RaceCheckPoint*, RaceCheckPoint*, const std::vector<StaticEntity*>&);
+            //void computeVirtualCheckpoint(RaceCheckPoint*, RaceCheckPoint*, const std::vector<StaticEntity*>&);
+
+            std::vector<RaceCheckPoint*> staticRacePoints_;
+            RaceCheckPoint* nextRaceCheckpoint_; // checkpoint that should be reached
+            RaceCheckPoint* currentRaceCheckpoint_; // last checkPoint (already reached)
+            std::vector<RaceCheckPoint*> checkpoints_;
+            Vector3 lastPositionSpaceship;
+            int virtualCheckPointIndex;
+    };
+
+}
+
+#endif /* SPACERACECONTROLLER_H_ */
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceManager.cc	(revision 11817)
@@ -0,0 +1,194 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Celine Eggenberger
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SpaceRaceManager.h"
+#include "SpaceRace.h"
+#include "infos/PlayerInfo.h"
+
+#include "core/XMLPort.h"
+
+#include "core/CoreIncludes.h"
+
+#include "util/Convert.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    RegisterClass(SpaceRaceManager);
+
+    SpaceRaceManager::SpaceRaceManager(Context* context) :
+        BaseObject(context)
+    {
+        RegisterObject(SpaceRaceManager);
+        this->race_ = orxonox_cast<SpaceRace*>(this->getGametype());
+        assert(race_);
+        //amountOfPlayers=(race_->getPlayers()).size();
+        this->firstcheckpointvisible_ = false;
+    }
+
+    SpaceRaceManager::~SpaceRaceManager()
+    {
+        for (RaceCheckPoint* checkpoint : this->checkpoints_)
+        checkpoint->destroy();
+    }
+
+    void SpaceRaceManager::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SpaceRaceManager, XMLPort, xmlelement, mode);
+
+        XMLPortObject(SpaceRaceManager, RaceCheckPoint, "checkpoints", addCheckpoint, getCheckpoint, xmlelement, mode);
+    }
+
+    void SpaceRaceManager::tick(float dt)
+    {
+        SUPER(SpaceRaceManager,tick,dt);
+
+        this->players_ = this->race_->getPlayers();
+
+        if (this->checkpoints_[0] != nullptr && !this->firstcheckpointvisible_)
+        {
+            this->checkpoints_[0]->setRadarVisibility(true);
+            this->firstcheckpointvisible_ = true;
+        }
+
+        for (const auto& mapEntry : players_)
+        {
+
+            for (RaceCheckPoint* checkpoint : this->checkpoints_)
+            {
+                if (checkpoint->playerWasHere(mapEntry.first)){
+                this->checkpointReached(checkpoint, mapEntry.first /*this->checkpoints_[i]->getPlayer()*/);
+                }
+            }
+        }
+
+    }
+
+    void SpaceRaceManager::addCheckpoint(RaceCheckPoint* checkpoint)
+    {
+        this->checkpoints_.push_back(checkpoint);
+    }
+
+    RaceCheckPoint* SpaceRaceManager::getCheckpoint(unsigned int index) const
+    {
+        if (index < this->checkpoints_.size())
+        return this->checkpoints_[index];
+        else
+        return nullptr;
+    }
+
+    std::vector<RaceCheckPoint*> SpaceRaceManager::getAllCheckpoints()
+    {
+        return checkpoints_;
+    }
+
+    /**
+     @brief Returns the checkpoint with the given checkpoint-index (@see RaceCheckPoint::getCheckpointIndex).
+     */
+    RaceCheckPoint* SpaceRaceManager::findCheckpoint(int index) const
+    {
+        for (RaceCheckPoint* checkpoint : this->checkpoints_)
+        if (checkpoint->getCheckpointIndex() == index)
+        return checkpoint;
+        return nullptr;
+    }
+
+    bool SpaceRaceManager::reachedValidCheckpoint(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint, PlayerInfo* player) const
+    {
+        if (oldCheckpoint != nullptr)
+        {
+            // the player already visited an old checkpoint; see which checkpoints are possible now
+            const std::set<int>& possibleCheckpoints = oldCheckpoint->getNextCheckpoints();
+            for (int possibleCheckpoint : possibleCheckpoints)
+            if (this->findCheckpoint(possibleCheckpoint) == newCheckpoint)
+            return true;
+            return false;
+        }
+        else
+        {
+            // the player hasn't visited a checkpoint yet, so he must reach the checkpoint with index 0 (hack?)
+            return (newCheckpoint->getCheckpointIndex() == 0);
+        }
+    }
+
+    void SpaceRaceManager::checkpointReached(RaceCheckPoint* newCheckpoint, PlayerInfo* player)
+    {
+        SpaceRace* gametype = orxonox_cast<SpaceRace*>(this->getGametype());
+        assert(gametype);
+        if (!gametype)
+        return;
+
+        RaceCheckPoint* oldCheckpoint = gametype->getCheckpointReached(player); // returns the last from player reached checkpoint
+
+        if (this->reachedValidCheckpoint(oldCheckpoint, newCheckpoint, player))
+        {
+            // the player reached a valid checkpoint
+            gametype->getClock().capture();
+            float time = gametype->getClock().getSecondsPrecise();
+            if (newCheckpoint->getTimeLimit() != 0 && time > newCheckpoint->getTimeLimit())
+            {
+                // time's up - the player has lost the game
+                gametype->setTimeIsUp();
+                gametype->end();
+            }
+            else if (newCheckpoint->isLast())
+            {
+                // the last checkpoint was reached - the player has won the game
+                gametype->end();
+            }
+            else
+            {
+                // adjust the radarvisibility
+                gametype->newCheckpointReached(newCheckpoint, player);
+                if(player->isHumanPlayer())
+                    this->updateRadarVisibility(oldCheckpoint, newCheckpoint);
+            }
+        }
+
+        // newCheckpoint->resetPlayer(); loescht playerpointer TODO: check if problems occur
+    }
+
+    void SpaceRaceManager::updateRadarVisibility(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint) const
+    {
+        if (oldCheckpoint)
+        {
+            const std::set<int>& oldVisible = oldCheckpoint->getNextCheckpoints();
+            for (int checkpointIndex : oldVisible)
+            this->findCheckpoint(checkpointIndex)->setRadarVisibility(false);
+        }
+
+        if (newCheckpoint)
+        {
+            newCheckpoint->setRadarVisibility(false);
+
+            const std::set<int>& newVisible = newCheckpoint->getNextCheckpoints();
+            for (int checkpointIndex : newVisible)
+            this->findCheckpoint(checkpointIndex)->setRadarVisibility(true);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/gametypes/SpaceRaceManager.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Mauro Salomon
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SpaceRaceManager_H__
+#define _SpaceRaceManager_H__
+
+#include "gametypes/GametypesPrereqs.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include <util/Clock.h>
+
+#include "gametypes/Gametype.h"
+#include "tools/interfaces/Tickable.h"
+#include "RaceCheckPoint.h"
+
+
+
+namespace orxonox
+{
+    /**
+    @brief
+        The SpaceRaceManager class controls a space race level, where the player has to reach check points in a given order.
+    */
+    class _GametypesExport SpaceRaceManager : public BaseObject, public Tickable
+    {
+        friend class RaceCheckPoint;
+
+        public:
+            SpaceRaceManager(Context* context);
+            virtual ~SpaceRaceManager() ;
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void addCheckpoint(RaceCheckPoint* checkpoint);
+            RaceCheckPoint* getCheckpoint(unsigned int index) const;
+
+            RaceCheckPoint* findCheckpoint(int index) const;
+
+            void checkpointReached(RaceCheckPoint* newCheckpoint, PlayerInfo* player);
+
+            std::vector<RaceCheckPoint*> getAllCheckpoints();
+
+            virtual void tick(float dt) override;
+
+        protected:
+            bool reachedValidCheckpoint(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint, PlayerInfo* player) const;
+            void updateRadarVisibility(RaceCheckPoint* oldCheckpoint, RaceCheckPoint* newCheckpoint) const;
+
+        private:
+            std::vector<RaceCheckPoint*> checkpoints_;
+            bool firstcheckpointvisible_; ///< true if the first check point is visible.
+            SpaceRace* race_; // needed to get the players
+            //int amountOfPlayers;
+            std::map<PlayerInfo*, Player> players_;
+    };
+}
+
+#endif /* _SpaceRaceManager_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,20 @@
+SET_SOURCE_FILES(Hover_SRC_FILES
+  Hover.cc
+  HoverShip.cc
+  HoverWall.cc
+  HoverOrigin.cc
+  HoverFlag.cc
+  TimeHUD.cc
+  FlagHUD.cc
+  MazeGenerator.cc
+)
+
+ORXONOX_ADD_LIBRARY(hover
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    objects
+    overlays
+  SOURCE_FILES ${Hover_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/hover/FlagHUD.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/FlagHUD.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/FlagHUD.cc	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file FlagHUD.cc
+    @brief Implementation of the FlagHUD
+*/
+
+#include "FlagHUD.h"
+
+#include <OgreOverlayManager.h>
+#include <OgreMaterialManager.h>
+#include <OgrePanelOverlayElement.h>
+
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "Hover.h"
+
+namespace orxonox
+{
+    RegisterClass(FlagHUD);
+
+    FlagHUD::FlagHUD(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(FlagHUD);
+
+        this->hoverGame_ = nullptr;
+        this->panel_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+            .createOverlayElement("Panel", "FlagHUD_Panel_" + getUniqueNumberString()));
+        this->panel_->setMaterialName("Hover/Flag");
+        this->overlay_->add2D(this->panel_);
+
+        this->flagCount_ = 5;
+        setFlagCount(5);
+    }
+
+    FlagHUD::~FlagHUD()
+    {
+        if (this->isInitialized())
+        {
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->panel_);
+        }
+    }
+
+/**
+    @brief Sets the amount of flags displayed, once zero it does not reappear
+    @param flagCount
+*/
+    void FlagHUD::setFlagCount(int flagCount) {
+        if(flagCount == 0){
+            this->panel_->hide();
+            return;
+        }
+        this->panel_->setDimensions(
+            this->panel_->_getRelativeWidth() / ((float) flagCount_) * ((float) flagCount),
+            this->panel_->_getRelativeHeight()
+            );
+        this->panel_->setTiling(flagCount*1.0f, 1.0f);
+
+        this->flagCount_ = flagCount;
+    }
+
+    void FlagHUD::tick(float dt)
+    {
+        SUPER(FlagHUD, tick, dt);
+
+        setFlagCount(this->hoverGame_->getNumberOfFlags());
+    }
+
+    void FlagHUD::changedOwner()
+    {
+        SUPER(FlagHUD, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->hoverGame_ = orxonox_cast<Hover*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->hoverGame_ = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/FlagHUD.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/FlagHUD.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/FlagHUD.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *
+ */
+
+ /**
+    @file FlagHUD.h
+    @brief Declaration of the FlagHUD class.
+*/
+
+#ifndef _FlagHUD_H__
+#define _FlagHUD_H__
+
+#include "HoverPrereqs.h"
+
+#include "util/OgreForwardRefs.h"
+#include "overlays/OrxonoxOverlay.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox
+{
+    class _HoverExport FlagHUD : public OrxonoxOverlay , public Tickable
+    {
+    public:
+        FlagHUD(Context* context);
+        virtual ~FlagHUD();
+
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+
+        void setFlagCount(int flagCount);
+
+    private:
+        Hover* hoverGame_;
+        Ogre::PanelOverlayElement* panel_;
+        int flagCount_;
+    };
+}
+#endif /* _FlagHUD_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/Hover.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/Hover.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/Hover.cc	(revision 11817)
@@ -0,0 +1,115 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file Hover.cc
+    @brief Implementation of the Hover class. Sets up the whole Minigame
+*/
+
+#include "Hover.h"
+
+#include "HoverOrigin.h"
+#include "HoverWall.h"
+#include "HoverFlag.h"
+#include "MazeGenerator.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Hover);
+
+    Hover::Hover(Context* context) : Gametype(context)
+    {
+        RegisterObject(Hover);
+
+        this->origin_ = nullptr;
+        this->numberOfFlags_ = 1;
+        this->firstTick_ = true;
+
+        this->setHUDTemplate("HoverHUD");
+    }
+
+    void Hover::tick(float dt)
+    {
+        SUPER(Hover, tick, dt);
+
+        if(this->firstTick_ && this->origin_)
+        {
+            this->firstTick_ = false;
+
+            int numCells = this->origin_->getNumCells();
+            int cellSize = this->origin_->getCellSize();
+            int cellHeight = this->origin_->getCellHeight();
+
+            MazeGenerator generator(numCells);
+            generator.generateMaze();
+            generator.renderMaze();
+
+            int* levelcode = generator.getLevelcode();
+
+            //Outer Walls
+            for(int i = 0; i<numCells; i++){
+                (new HoverWall(origin_->getContext()))->init(0,        i+1,      cellSize, cellHeight, 1);
+                (new HoverWall(origin_->getContext()))->init(numCells, i+1,      cellSize, cellHeight, 1);
+                (new HoverWall(origin_->getContext()))->init(i+1,      0,        cellSize, cellHeight, 2);
+                (new HoverWall(origin_->getContext()))->init(i+1,      numCells, cellSize, cellHeight, 2);
+            }
+
+            //Generate inner Walls according to levelcode
+            for(int y=0; y<numCells; y++){
+                for(int x=0; x<numCells; x++){
+                    switch(levelcode[ y * numCells + x ]){
+                        case 1: (new HoverWall(origin_->getContext()))->init(x+1, numCells-y, cellSize, cellHeight, 1);
+                                break;
+                        case 3: (new HoverWall(origin_->getContext()))->init(x+1, numCells-y, cellSize, cellHeight, 1);
+                        case 2: (new HoverWall(origin_->getContext()))->init(x+1, numCells-y, cellSize, cellHeight, 0);
+                        default: break;
+                    }
+                }   
+            }
+
+            //Generate 5 flags randomly
+            for ( int i = 0; i < 5; i++ )
+            {
+                HoverFlag* flag = new HoverFlag(origin_->getContext());
+                flag->init(rand()%numCells, rand()%numCells, cellSize);
+                flags_.push_back(flag);
+            }
+
+        }//firsttick end
+
+        // Check if ship collided with one of the flags
+        for ( unsigned int i = 0; i < flags_.size(); i++ ){
+            if(flags_[i]->getCollided()){
+                flags_[i]->destroyLater();
+                flags_.erase (flags_.begin()+i);
+            }
+        }
+        numberOfFlags_ = flags_.size();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/Hover.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/Hover.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/Hover.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Master of Desaster:
+ *      Manuel Meier
+ *   Co-authors:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file Hover.h
+    @brief Gametype. For more information see .cc file
+    @ingroup Hover
+*/
+
+#ifndef _Hover_H__
+#define _Hover_H__
+
+#include "HoverPrereqs.h"
+
+#include <vector>
+
+#include "gametypes/Gametype.h"
+#include "HoverOrigin.h"
+
+namespace orxonox
+{
+    class _HoverExport Hover : public Gametype
+    {
+       public:
+            Hover(Context* context);
+
+            virtual void tick(float dt) override;
+
+            void setOrigin(HoverOrigin* origin)
+                { this->origin_ = origin; }
+
+            inline int getNumberOfFlags() const
+                { return this->numberOfFlags_; }
+
+        private:
+            WeakPtr<HoverOrigin> origin_;
+            std::vector<HoverFlag*> flags_;
+            int numberOfFlags_;
+            bool firstTick_;
+    };
+}
+
+#endif /* _Hover_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverFlag.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverFlag.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverFlag.cc	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HoverFlag.cc
+    @brief The Flags that are being set in the Hover Minigame They support two coordinates from 0-9 each
+*/
+
+#include "HoverFlag.h"
+#include "HoverShip.h"
+
+#include "core/CoreIncludes.h"
+
+#include "graphics/Model.h"
+#include "objects/collisionshapes/BoxCollisionShape.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(HoverFlag);
+
+    HoverFlag::HoverFlag(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(HoverFlag);
+
+        this->model_ = nullptr;
+        this->cs_ = nullptr;
+        this->collided_ = false;
+
+        this->enableCollisionCallback();
+        this->setCollisionResponse(true);
+        this->setCollisionType(CollisionType::Static);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    HoverFlag::~HoverFlag()
+    {
+        if (this->isInitialized())
+        {
+            if (this->model_)
+                this->model_->destroy();
+            if (this->cs_)
+                this->cs_->destroy();
+        }
+    }
+
+    /**
+    @brief
+        Initializes the flag.
+    @param xCoordinate
+        X-Coordinate of the flage, 0-9, origin is bottom left
+    @param yCoordinate
+        Y-Coordinate of the flage, 0-9, origin is bottom left
+    @param cellSize
+        The size of the cells
+    */
+    void HoverFlag::init(int xCoordinate, int yCoordinate, int cellSize)
+    {
+        model_ = new Model(this->getContext());
+        model_->setMeshSource("ss_flag_eu.mesh");
+        model_->setScale3D(Vector3(5, 5, 5));
+        model_->setPosition(Vector3(xCoordinate*cellSize*1.0f + cellSize/2,10.0f,yCoordinate*cellSize*1.0f + cellSize/2));
+
+        this->attach(model_);
+
+        cs_ = new BoxCollisionShape(this->getContext());
+        cs_->setHalfExtents(Vector3(5, 5, 5));
+        cs_->setPosition(Vector3(xCoordinate*cellSize*1.0f + cellSize/2,0.0f,yCoordinate*cellSize*1.0f + cellSize/2));
+
+        this->attachCollisionShape(cs_);
+    }
+
+    /**
+    @brief
+        Checks if the Hovership collided with the flag
+    */
+    bool HoverFlag::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        if(otherObject->isA(Class(HoverShip)))
+            collided_ = true;
+        return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverFlag.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverFlag.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverFlag.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HoverFlag.h
+    @brief See .cc File
+    @ingroup Hover
+*/
+
+#ifndef _HoverFlag_H__
+#define _HoverFlag_H__
+
+#include "HoverPrereqs.h"
+#include "objects/ObjectsPrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _HoverExport HoverFlag : public StaticEntity
+    {
+        public:
+            HoverFlag(Context* context);
+            virtual ~HoverFlag();
+
+            void init(int xCoordinate, int yCoordinate, int cellSize);
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+
+            inline bool getCollided() const
+                { return this->collided_; }
+            inline void setCollided(bool setValue)
+                { this->collided_ = setValue; }
+
+        private:
+            Model* model_;
+            BoxCollisionShape* cs_;
+            bool collided_;
+
+    };
+}
+
+#endif /* _HoverFlag_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverOrigin.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverOrigin.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverOrigin.cc	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HoverOrigin.cc
+    @brief The HoverOrigin is a StaticEntity which represents the level of the minigame. All platforms, enemies and items are attached to the HoverOrigin.
+*/
+
+#include "HoverOrigin.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "Hover.h"
+
+namespace orxonox
+{
+    RegisterClass(HoverOrigin);
+
+    HoverOrigin::HoverOrigin(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(HoverOrigin);
+        checkGametype();
+    }
+
+    void HoverOrigin::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HoverOrigin, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HoverOrigin, "numCells", setNumCells, getNumCells, xmlelement, mode);
+        XMLPortParam(HoverOrigin, "cellSize", setCellSize, getCellSize, xmlelement, mode);
+        XMLPortParam(HoverOrigin, "cellHeight", setCellHeight, getCellHeight, xmlelement, mode);
+    }
+
+    void HoverOrigin::checkGametype()
+    {
+        if (getGametype() != nullptr && this->getGametype()->isA(Class(Hover)))
+        {
+            Hover* hoverGametype = orxonox_cast<Hover*>(this->getGametype());
+            hoverGametype->setOrigin(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverOrigin.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverOrigin.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverOrigin.h	(revision 11817)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HoverOrigin_H__
+#define _HoverOrigin_H__
+
+#include "HoverPrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    
+    /**
+    @brief
+        The HoverOrigin implements the playing field @ref orxonox::Hover "Hover" takes place in and allows for many parameters of the minigame to be set.
+        The playing field resides in the x,z-plane, with the x-axis being the horizontal axis and the z-axis being the vertical axis.
+        For an example, have a look at the <code>Hover.oxw</code> level file.
+
+    */
+    class _HoverExport HoverOrigin : public StaticEntity
+    {
+        public:
+            HoverOrigin(Context* context); //!< Constructor. Registers and initializes the object and checks whether the gametype is actually Hover.
+            virtual ~HoverOrigin() = default;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method to create a HoverOrigin through XML.
+            
+            inline void setNumCells(int numCells)
+                { this->numCells_ = numCells; }
+            inline int getNumCells() const
+                { return this->numCells_; }
+
+            inline void setCellSize(int cellSize)
+                { this->cellSize_ = cellSize; }
+            inline int getCellSize() const
+                { return this->cellSize_; }
+
+            inline void setCellHeight(int cellHeight)
+                { this->cellHeight_ = cellHeight; }
+            inline int getCellHeight() const
+                { return this->cellHeight_; }
+
+        private:
+            void checkGametype();
+       
+            int numCells_;
+            int cellSize_;
+            int cellHeight_;
+    };
+}
+
+#endif /* _HoverOrigin_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverPrereqs.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the Hover module
+*/
+
+#ifndef _HoverPrereqs_H__
+#define _HoverPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(HOVER_STATIC_BUILD)
+#  ifdef HOVER_SHARED_BUILD
+#    define _HoverExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _HoverExport
+#    else
+#      define _HoverExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _HoverPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _HoverExport  __attribute__ ((visibility("default")))
+#  define _HoverPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _HoverExport
+#  define _HoverPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class FlagHUD;
+    class Hover;
+    class HoverFlag;
+    class HoverOrigin;
+    class HoverShip;
+    class HoverWall;
+    class MazeGenerator;
+    class TimeHUD;
+}
+
+#endif /* _HoverPrereqs_H__*/
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverShip.cc	(revision 11817)
@@ -0,0 +1,122 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file HoverShip.cc
+    @brief Implementation of the HoverShip control
+*/
+
+#include "HoverShip.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+
+namespace orxonox
+{
+    RegisterClass(HoverShip);
+
+    HoverShip::HoverShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(HoverShip);
+        enableCollisionCallback();
+        isFloor_ = false;
+        jumpBoost_ = 0;
+    }
+
+    void HoverShip::moveFrontBack(const Vector2& value)
+        { this->steering_.z -= value.x; }
+
+    void HoverShip::moveRightLeft(const Vector2& value)
+        { this->steering_.x += value.x; }
+
+    void HoverShip::moveUpDown(const Vector2& value)
+        { this->steering_.y += value.x; }
+
+    void HoverShip::rotateYaw(const Vector2& value)
+    {
+        this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x);
+
+        Pawn::rotateYaw(value);
+    }
+
+    void HoverShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HoverShip, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HoverShip, "jumpBoost", setJumpBoost, getJumpBoost, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Removed, does nothing.
+    @param value
+    */
+    void HoverShip::rotatePitch(const Vector2& value) { }
+
+    /**
+    @brief
+        Removed, does nothing.
+    @param value
+    */
+    void HoverShip::rotateRoll(const Vector2& value) { }
+
+    /**
+    @brief
+        Checks if the ship is touching the floor. The ship can only jump if there is contact with someting beneath it.
+    */
+    bool HoverShip::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {
+        SpaceShip::collidesAgainst(otherObject, cs, contactPoint);
+        //SUPER(HoverShip, collidesAgainst, otherObject, cs, contactPoint);
+
+        if (contactPoint.m_normalWorldOnB.y() > 0.6
+            && this->getVelocity().y < 1) {
+            this->isFloor_ = true;
+        } else {
+            this->isFloor_ = false;
+        }
+
+        return false;
+    }
+
+    /**
+    @brief
+        Makes the ship jump
+    @param bBoost
+    */
+    void HoverShip::boost(bool bBoost) {
+        if (bBoost && this->isFloor_)
+        {
+            this->setVelocity(
+                this->getVelocity().x,
+                jumpBoost_,
+                this->getVelocity().z
+                );
+            this->isFloor_ = false;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverShip.h	(revision 11817)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file HoverShip.h
+    @brief Declaration of the HoverShip class.
+*/
+
+#ifndef _HoverShip_H__
+#define _HoverShip_H__
+
+#include "HoverPrereqs.h"
+
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    class _HoverExport HoverShip : public SpaceShip
+    {
+        public:
+            HoverShip(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            /// sets this ships jumpBoost
+            inline void setJumpBoost(float jumpBoost)
+                { this->jumpBoost_ = jumpBoost; }
+            /// returns this ships jumpBoost
+            inline float getJumpBoost() const
+                { return this->jumpBoost_; }
+
+            virtual void moveFrontBack(const Vector2& value) override;
+
+            virtual void moveRightLeft(const Vector2& value) override;
+
+            virtual void moveUpDown(const Vector2& value) override;
+
+            virtual void rotateYaw(const Vector2& value) override;
+
+            virtual void rotatePitch(const Vector2& value) override;
+
+            virtual void rotateRoll(const Vector2& value) override;
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+
+            virtual void boost(bool bBoost) override;
+
+        private:
+            float jumpBoost_;
+            bool isFloor_;
+    };
+}
+
+#endif /* _HoverShip_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverWall.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverWall.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverWall.cc	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HoverWall.cc
+    @brief Represents one Wall piece in the Hover Game
+*/
+
+#include "HoverWall.h"
+
+#include "core/CoreIncludes.h"
+#include "graphics/Model.h"
+#include "objects/collisionshapes/BoxCollisionShape.h"
+
+namespace orxonox
+{
+    RegisterClass(HoverWall);
+
+    HoverWall::HoverWall(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(HoverWall);
+
+        this->model_ = nullptr;
+        this->cs_ = nullptr;
+
+        this->enableCollisionCallback();
+        this->setCollisionResponse(true);
+        this->setCollisionType(CollisionType::Static);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    HoverWall::~HoverWall()
+    {
+        if (this->isInitialized())
+        {
+            if (this->model_)
+                this->model_->destroy();
+            if (this->cs_)
+                this->cs_->destroy();
+        }
+    }
+
+    /**
+    @brief
+        Initializes a HoverWall
+    @param x
+        x-Coordinate of the Square that the Wall is attached to, 0-9, Origin is Bottom left
+    @param y
+        y-Coordinate of the Square that the Wall is attached to, 0-9, Origin is Bottom left
+    @param cellSize
+        The size of a cell
+    @param cellHeight
+        The height of a cell
+    @param orientation
+            Wall on the right side (1) or on top (2) of this square, 0-1        
+    */
+    void HoverWall::init(int x, int y, int cellSize, int cellHeight, int orientation)
+    {
+        int xSize_, zSize_, xPos_, zPos_;
+
+        if(orientation == 1){
+            xSize_ = cellSize/2;
+            zSize_ = 2;
+            zPos_ = x*cellSize;
+            xPos_ = y*cellSize-cellSize/2;
+        }
+        else{
+            xSize_ = 2;
+            zSize_ = cellSize/2;
+            zPos_ = x*cellSize-cellSize/2;
+            xPos_ = y*cellSize;
+        }
+
+
+        model_ = new Model(this->getContext());
+        model_->setMeshSource("CuboidBody.mesh");
+        model_->setScale3D(Vector3(xSize_*1.0f, cellHeight*1.0f, zSize_*1.0f));
+        model_->setPosition(Vector3(xPos_*1.0f, 0.0f, zPos_*1.0f));
+
+        this->attach(model_);
+
+        cs_ = new BoxCollisionShape(this->getContext());
+        cs_->setHalfExtents(Vector3(xSize_*1.0f, cellHeight*1.0f, zSize_*1.0f));
+        cs_->setPosition(Vector3(xPos_*1.0f, 0.0f, zPos_*1.0f));
+
+        this->attachCollisionShape(cs_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/HoverWall.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/HoverWall.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/HoverWall.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HoverWall.h
+    @brief See .cc-file for further information
+    @ingroup Hover
+*/
+
+#ifndef _HoverWall_H__
+#define _HoverWall_H__
+
+#include "HoverPrereqs.h"
+#include "objects/ObjectsPrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _HoverExport HoverWall : public StaticEntity
+    {
+        public:
+            HoverWall(Context* context);
+            virtual ~HoverWall();
+
+            void init(int x, int y, int cellSize, int cellHeight, int orientation);
+
+        private:
+            Model* model_;
+            BoxCollisionShape* cs_;
+    };
+}
+
+#endif /* _HoverWall_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/MazeGenerator.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/MazeGenerator.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/MazeGenerator.cc	(revision 11817)
@@ -0,0 +1,255 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Manuel Meier
+ *   Co-authors:
+ *      Cyrill Burgener
+ *
+ *   Based on random-maze-generator by Sergey Kosarevsky, 2014
+ *   https://github.com/corporateshark/random-maze-generator
+ *
+ */
+
+/**
+    @file MazeGenerator.cc
+    @brief Implementation of the MazeGenerator class. Generates the maze.
+*/
+
+#include "MazeGenerator.h"
+
+#include <vector>
+
+#include "util/Output.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    MazeGenerator::MazeGenerator(int numCells)
+    {
+        this->numCells_ = numCells;
+
+        //levelcode_ represents the pitch: It's a 10x10 field.
+        // 1 represents a Wall on the right side of this square
+        // 2 represents a Wall on the top of this square
+        // 3 represents 2 and 1 at the same time
+        // Note: the levelcode_ is generated from the Maze-Generator functions at the beginning of the game
+        this->levelcode_ = new int[ numCells_*numCells_ ];;
+        std::fill( levelcode_, levelcode_ + numCells_*numCells_, 0 );
+
+        this->maze_ = new unsigned char[ numCells_*numCells_ ];
+        std::fill( maze_, maze_ + numCells_*numCells_, 0 );
+
+        // current traversing position
+        this->ptX_ = 0;
+        this->ptY_ = 0;
+
+        //                  0  1  2  3  4  5  6  7  8
+        //                     U  R     D           L
+        int headingX[9] = { 0, 0,+1, 0, 0, 0, 0, 0,-1 };
+        int headingY[9] = { 0,-1, 0, 0,+1, 0, 0, 0, 0 };
+        int mask[9]     = {
+                              0,
+                              eDirection_Down | eDirection_Down << 4,
+                              eDirection_Left | eDirection_Left << 4,
+                              0,
+                              eDirection_Up | eDirection_Up << 4,
+                              0,
+                              0,
+                              0,
+                              eDirection_Right | eDirection_Right << 4
+                          };
+
+        std::copy(headingX, headingX + 9, this->headingX_);
+        std::copy(headingY, headingY + 9, this->headingY_);
+        std::copy(mask,     mask + 9,     this->mask_);
+    }
+
+    MazeGenerator::~MazeGenerator()
+    {
+        delete[] this->levelcode_;
+        delete[] this->maze_;
+    }
+
+    /**
+    @brief
+        Checks if Direction is valid (for Maze-Generator)
+    */
+    bool MazeGenerator::isDirValid( eDirection Dir )
+    {
+        int NewX = ptX_ + headingX_[ Dir ];
+        int NewY = ptY_ + headingY_[ Dir ];
+
+        if ( !Dir || NewX < 0 || NewY < 0 || NewX >= numCells_ || NewY >= numCells_ ) return false;
+
+        return !maze_[ NewX + numCells_ * NewY ];
+    }
+
+    /**
+    @brief
+        Generates new Direction (for Maze-Generator)
+    */
+    eDirection MazeGenerator::getDirection()
+    {
+        eDirection Dir = eDirection( 1 << randomInt4() );
+
+        while ( true )
+        {
+            for ( int x = 0; x < 4; x++ )
+            {
+                if ( isDirValid( Dir ) ) { return eDirection( Dir ); }
+
+                Dir = eDirection( Dir << 1 );
+
+                if ( Dir > eDirection_Left ) { Dir = eDirection_Up; }
+            }
+
+            Dir = eDirection( ( maze_[ cellIdx() ] & 0xf0 ) >> 4 );
+
+            // nowhere to go
+            if ( !Dir ) return eDirection_Invalid;
+
+            ptX_ += headingX_[ Dir ];
+            ptY_ += headingY_[ Dir ];
+
+            Dir = eDirection( 1 << randomInt4() );
+        }
+    }
+
+    /**
+    @brief
+        Generates a Maze (for Maze-Generator)
+    */
+    void MazeGenerator::generateMaze()
+    {
+
+        for ( eDirection Dir = getDirection(); Dir != eDirection_Invalid; Dir = getDirection() )
+        {
+            maze_[ cellIdx() ] |= Dir;
+
+            ptX_ += headingX_[ Dir ];
+            ptY_ += headingY_[ Dir ];
+
+            maze_[ cellIdx() ] = mask_[ Dir ];
+        }
+    }  
+    
+    /**
+    @brief
+        Print Maze (for Debugging only)
+    */
+    void MazeGenerator::mazeOut(){
+        for ( int y = 0; y < numCells_; y++ )
+        {
+            for ( int x = 0; x < numCells_; x++ )
+            {
+                char v = maze_[ y * numCells_ + x ];
+                orxout()<<"[";
+                if ( ( v & eDirection_Up    ) ) orxout()<<"U";
+                else orxout()<<" ";
+                if ( ( v & eDirection_Right ) ) orxout()<<"R";
+                else orxout()<<" ";
+                if ( ( v & eDirection_Down  ) ) orxout()<<" ";
+                else orxout()<<" ";
+                if ( ( v & eDirection_Left  ) ) orxout()<<" ";
+                else orxout()<<" ";
+                orxout()<<"]";
+            }
+            orxout()<<endl;
+        }
+
+    }
+
+    /**
+    @brief
+        Print levelcode_ (for Debugging only)
+    */
+    void MazeGenerator::levelOut(){
+        for ( int y = 0; y < numCells_; y++ )
+        {
+            for ( int x = 0; x < numCells_; x++ )
+            {
+                orxout()<<"[";
+                if ( levelcode_[ y * numCells_ + x ] < 2) orxout()<<"U";
+                else orxout()<<" ";
+                if ( levelcode_[ y * numCells_ + x ] % 2 == 0) orxout()<<"R";
+                else orxout()<<" ";
+
+                orxout()<<" ";
+                orxout()<<" ";
+                orxout()<<"]";
+            }
+            orxout()<<endl;
+        }
+    }
+
+    /**
+    @brief
+        Generate levelcode_ from Maze
+    */
+    void MazeGenerator::renderMaze()
+    {
+        for ( int y = 0; y < numCells_; y++ )
+        {
+            for ( int x = 0; x < numCells_; x++ )
+            {
+                char v = maze_[ y * numCells_ + x ];
+
+                if ( !( v & eDirection_Up    ) && y >0) levelcode_[ y * numCells_ + x ] |= 2;
+                if ( !( v & eDirection_Right ) && x <(numCells_-1)) levelcode_[ y * numCells_ + x ] |= 1;
+            }
+        }
+
+        // leave an empty space in the middle of the maze
+        int lowerBound = numCells_ / 2 - 2;
+        int upperBound = numCells_ / 2 + 2;
+        for ( int y = lowerBound; y < upperBound; y++ )
+        {
+            for ( int x = lowerBound; x < upperBound; x++ )
+            {
+
+                if(y == lowerBound && x != upperBound)
+                    levelcode_[ y * numCells_ + x ] &= 2;
+                else if (x == upperBound && y != lowerBound)
+                    levelcode_[ y * numCells_ + x ] &= 1;
+                else if(x != upperBound)
+                    levelcode_[ y * numCells_ + x ] = 0;
+            }
+        }
+
+    }
+
+    // return the current index in maze_
+    int MazeGenerator::cellIdx()
+    {
+        return ptX_ + numCells_ * ptY_;
+    }
+
+    int MazeGenerator::randomInt()
+    {
+        return (rand() % numCells_);
+    }
+
+    int MazeGenerator::randomInt4()
+    {
+        return (rand() % 4);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/MazeGenerator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/MazeGenerator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/MazeGenerator.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Master of Desaster:
+ *      Manuel Meier
+ *   Co-authors:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file MazeGenerator.h
+    @ingroup Hover
+*/
+
+#ifndef _MazeGenerator_H__
+#define _MazeGenerator_H__
+
+#include "HoverPrereqs.h"
+
+namespace orxonox
+{
+    enum eDirection
+    {
+        eDirection_Invalid = 0,
+        eDirection_Up      = 1,
+        eDirection_Right   = 2,
+        eDirection_Down    = 4,
+        eDirection_Left    = 8
+    }; 
+
+    class _HoverExport MazeGenerator
+    {
+        public:
+            MazeGenerator(int numCells);
+            ~MazeGenerator();
+
+            void generateMaze();
+            void renderMaze();
+            void mazeOut();
+            void levelOut();
+
+            int* getLevelcode() const
+                { return this->levelcode_; }
+
+        private:
+            bool isDirValid( eDirection Dir );
+            eDirection getDirection();
+
+            int cellIdx();
+            int randomInt();
+            int randomInt4();
+
+            int numCells_;
+            int* levelcode_;
+            unsigned char* maze_;
+
+            // current traversing position
+            int ptX_;
+            int ptY_;
+
+            int headingX_[9];
+            int headingY_[9];
+            int mask_[9];
+    };
+}
+
+#endif /* _MazeGenerator_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/hover/TimeHUD.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/TimeHUD.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/TimeHUD.cc	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *
+ */
+
+/**
+    @file TimeHUD.cc
+    @brief Implementation of the TimeHUD
+*/
+
+
+#include "TimeHUD.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Convert.h"
+#include "Hover.h"
+
+namespace orxonox
+{
+    RegisterClass(TimeHUD);
+
+    TimeHUD::TimeHUD(Context* context) : OverlayText(context)
+    {
+        RegisterObject(TimeHUD);
+
+        this->time_ = 0.0f;
+        this->running_ = false;
+        this->hoverGame_ = nullptr;
+        setRunning(true);
+    }
+
+    inline std::string getTimeString(float time) {
+        std::ostringstream ss;
+
+        int h = ((int) (time * 100.0f)) % 100;
+        int s = ((int) time) % 60;
+        int m = (int) (time / 60.0f);
+
+        ss << m << ":";
+
+        if(s < 10) {
+            ss << 0;
+        }
+        ss << s << ":";
+
+        if(h < 10) {
+            ss << 0;
+        }
+        ss << h << "s";
+        return ss.str();
+    }
+
+    void TimeHUD::tick(float dt)
+    {
+        SUPER(TimeHUD, tick, dt);
+
+        if(this->running_) {
+            this->time_ += dt;
+        }
+        if (this->hoverGame_)
+        {
+            this->setCaption(getTimeString(this->time_));
+            if (this->hoverGame_->getNumberOfFlags() == 0)
+                setRunning(false);
+        }
+        
+    }
+
+    void TimeHUD::changedOwner()
+    {
+        SUPER(TimeHUD, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->hoverGame_ = orxonox_cast<Hover*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->hoverGame_ = nullptr;
+        }
+    }
+
+    void TimeHUD::reset()
+    {
+        this->time_ = 0;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/hover/TimeHUD.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/hover/TimeHUD.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/hover/TimeHUD.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Burgener
+ *
+ */
+
+ /**
+    @file TimeHUD.h
+    @brief Declaration of the TimeHUD class.
+*/
+
+#ifndef _TimeHUD_H__
+#define _TimeHUD_H__
+
+#include "HoverPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _HoverExport TimeHUD : public OverlayText, public Tickable
+    {
+        public:
+            TimeHUD(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void changedOwner() override;
+
+            /// sets if the clock is running
+            inline void setRunning(bool running)
+                { this->running_ = running; }
+            /// returns if the clock is running
+            inline bool isRunning() const
+                { return this->running_; }
+
+            void reset();
+
+        private:
+            Hover* hoverGame_;
+            float time_;
+            bool running_;
+    };
+}
+#endif /* _TimeHUD_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,22 @@
+SET_SOURCE_FILES(Invader_SRC_FILES
+BUILD_UNIT InvaderBuildUnit.cc
+  Invader.cc
+  InvaderCenterPoint.cc
+  InvaderShip.cc
+  InvaderEnemy.cc
+  InvaderEnemyShooter.cc
+  InvaderWeapon.cc
+  InvaderWeaponEnemy.cc
+  InvaderHUDinfo.cc
+END_BUILD_UNIT
+)
+
+ORXONOX_ADD_LIBRARY(invader
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+    weapons
+  SOURCE_FILES ${Invader_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/invader/Invader.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/Invader.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/Invader.cc	(revision 11817)
@@ -0,0 +1,198 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Invader.cc
+    @brief Implementation of the Invader class.
+*/
+
+#include "Invader.h"
+#include "Highscore.h"
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+#include "core/config/ConfigValueIncludes.h"
+
+#include "gamestates/GSLevel.h"
+#include "chat/ChatManager.h"
+
+// ! HACK
+#include "infos/PlayerInfo.h"
+
+#include "InvaderCenterPoint.h"
+#include "InvaderShip.h"
+#include "InvaderEnemy.h"
+#include "InvaderEnemyShooter.h"
+
+#include "core/command/ConsoleCommand.h"
+#include "worldentities/ExplosionPart.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Invader);
+
+    Invader::Invader(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(Invader);
+        this->numberOfBots_ = 0; //sets number of default bots temporarly to 0
+        this->center_ = nullptr;
+        bEndGame = false;
+        lives = 3;
+        level = 1;
+        point = 0;
+        bShowLevel = false;
+        multiplier = 1;
+        b_combo = false;
+        // spawn enemy every 3.5 seconds
+        enemySpawnTimer.setTimer(3.5f, true, createExecutor(createFunctor(&Invader::spawnEnemy, this)));
+        comboTimer.setTimer(3.0f, true, createExecutor(createFunctor(&Invader::comboControll, this)));
+        this->setHUDTemplate("InvaderHUD");
+    }
+
+    void Invader::levelUp()
+    {
+        level++;
+        if (getPlayer() != nullptr)
+        {
+            for (int i = 0; i < 7; i++)
+            {
+
+                WeakPtr<ExplosionPart> chunk5 = new ExplosionPart(this->center_->getContext());
+                chunk5->setPosition(this->center_->getPosition());
+                chunk5->setVelocity(Vector3(1000, 0, 0));  //player->getVelocity()
+                chunk5->setScale(10);
+                chunk5->setEffect1("Orxonox/explosion2b");
+                chunk5->setEffect2("Orxonox/smoke6");
+                chunk5->setMinSpeed(0);
+                chunk5->setMaxSpeed(0);
+                chunk5->Explode();
+
+            }
+        }
+        addPoints(multiplier * 42);
+        multiplier *= 2;
+        toggleShowLevel();
+        showLevelTimer.setTimer(1.0f, false, createExecutor(createFunctor(&Invader::toggleShowLevel, this)));
+    }
+
+    InvaderShip* Invader::getPlayer()
+    {
+        if (player == nullptr)
+        {
+            for (InvaderShip* ship : ObjectList<InvaderShip>())
+                player = ship;
+        }
+        return player;
+    }
+
+    void Invader::spawnEnemy()
+    {
+        if (getPlayer() == nullptr)
+            return;
+
+        for (int i = 0; i < (3*log10(static_cast<double>(level)) + 1); i++)
+        {
+            InvaderEnemy* newPawn;
+            if (rand() % 42/(1 + level*level) == 0)
+            {
+                newPawn = new InvaderEnemyShooter(this->center_->getContext());
+                newPawn->addTemplate("enemyinvadershooter");
+            }
+            else
+            {
+                newPawn = new InvaderEnemy(this->center_->getContext());
+                newPawn->addTemplate("enemyinvader");
+            }
+            newPawn->setInvaderPlayer(player);
+            newPawn->level = level;
+            // spawn enemy at random points in front of player.
+            newPawn->setPosition(player->getPosition() + Vector3(500.f + 100 * i, 0, float(rand())/RAND_MAX * 400 - 200));
+        }
+    }
+
+    void Invader::setCenterpoint(InvaderCenterPoint* center)
+    {
+        this->center_ = center;
+    }
+
+    void Invader::costLife()
+    {
+        lives--;
+        multiplier = 1;
+        // end the game in 30 seconds.
+        if (lives <= 0)
+            enemySpawnTimer.setTimer(30.0f, false, createExecutor(createFunctor(&Invader::end, this)));
+    };
+
+    void Invader::comboControll()
+    {
+        if (b_combo)
+            multiplier++;
+        // if no combo was performed before, reset multiplier
+        else
+            multiplier = 1;
+        b_combo = false;
+    }
+
+    void Invader::start()
+    {
+        // Set variable to temporarily force the player to spawn.
+        this->bForceSpawn_ = true;
+
+        if (this->center_ == nullptr)  // abandon mission!
+        {
+            orxout(internal_error) << "Invader: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+        // Call start for the parent class.
+        Deathmatch::start();
+    }
+    void Invader::addPoints(int numPoints)
+    {
+        if (!bEndGame)
+        {
+            point += numPoints * multiplier;
+            b_combo = true;
+        }
+    }
+
+    void Invader::end()
+    {
+        // DON'T CALL THIS!
+        //      Deathmatch::end();
+        // It will misteriously crash the game!
+        // Instead startMainMenu, this won't crash.
+        if (Highscore::exists())
+        {
+            int score = this->getPoints();
+            Highscore::getInstance().storeScore("Orxonox Arcade", score, this->getPlayer()->getPlayer());
+        }
+        GSLevel::startMainMenu();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/Invader.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/Invader.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/Invader.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Invader.h
+    @brief Gametype.
+    @ingroup Invader
+*/
+
+#ifndef _Invader_H__
+#define _Invader_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "gametypes/Deathmatch.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+
+    class _InvaderExport Invader : public Deathmatch
+    {
+        public:
+            Invader(Context* context);
+
+            virtual void start() override;
+            virtual void end() override;
+            virtual void addBots(unsigned int amount) override{} //<! overwrite function in order to bypass the addbots command
+
+            void spawnEnemy();
+
+            void setCenterpoint(InvaderCenterPoint* center);
+
+            int getLives(){return this->lives;}
+            int getLevel(){return this->level;}
+            int getPoints(){return this->point;}
+            int getMultiplier(){return this->multiplier;}
+
+            void costLife();
+            void levelUp();
+            void addPoints(int numPoints);
+            // checks if multiplier should be reset.
+            void comboControll();
+            int lives;
+            int multiplier;
+            bool bEndGame;
+            bool bShowLevel;
+        private:
+            void toggleShowLevel(){bShowLevel = !bShowLevel;}
+            InvaderShip* getPlayer();
+            WeakPtr<InvaderCenterPoint> center_;
+            WeakPtr<InvaderShip> player;
+
+            Timer enemySpawnTimer;
+            Timer comboTimer;
+            Timer showLevelTimer;
+            //Context* context;
+            int level;
+            int point;
+            bool b_combo;
+    };
+}
+
+#endif /* _Invader_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderCenterPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderCenterPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderCenterPoint.cc	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderCenterPoint.cc
+    @brief Implementation of the InvaderCenterPoint class.
+*/
+
+#include "InvaderCenterPoint.h"
+
+#include "core/CoreIncludes.h"
+
+#include "Invader.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderCenterPoint);
+
+    InvaderCenterPoint::InvaderCenterPoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(InvaderCenterPoint);
+
+        this->checkGametype();
+    }
+
+    void InvaderCenterPoint::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Invader)))
+        {
+            Invader* InvaderGametype = orxonox_cast<Invader*>(this->getGametype());
+            InvaderGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderCenterPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderCenterPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderCenterPoint.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderCenterPoint.h
+    @brief Declaration of the InvaderCenterPoint class.
+    @ingroup Invader
+*/
+
+#ifndef _InvaderCenterPoint_H__
+#define _InvaderCenterPoint_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderCenterPoint : public StaticEntity
+    {
+        public:
+            InvaderCenterPoint(Context* context); //checks whether the gametype is actually Invader.
+
+        private:
+            void checkGametype();
+
+    };
+}
+
+#endif /* _InvaderCenterPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemy.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemy.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemy.cc	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderEnemy.h
+    @brief Declaration of the InvaderEnemy class.
+*/
+
+#include "InvaderEnemy.h"
+
+#include "core/CoreIncludes.h"
+#include "Invader.h"
+#include "InvaderShip.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderEnemy);
+
+    InvaderEnemy::InvaderEnemy(Context* context) : Pawn(context)
+    {
+        RegisterObject(InvaderEnemy);
+        enableCollisionCallback();
+        lifetime = 0;
+    }
+
+    void InvaderEnemy::tick(float dt)
+    {
+        lifetime += dt;
+        // die after 5 seconds.
+        if (lifetime > 5000)
+            removeHealth(2000);
+
+        if (player != nullptr)
+        {
+            float newZ = 2/(pow(std::abs(getPosition().x - player->getPosition().x) * 0.01f, 2) + 1) * (player->getPosition().z - getPosition().z);
+            setVelocity(Vector3(1000.f - level * 100 , 0, newZ));
+        }
+        SUPER(InvaderEnemy, tick, dt);
+    }
+
+    inline bool InvaderEnemy::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        if(orxonox_cast<InvaderShip*>(otherObject))
+            removeHealth(2000);
+        return false;
+    }
+
+    Invader* InvaderEnemy::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (Invader* invader : ObjectList<Invader>())
+                game = invader;
+        }
+        return game;
+    }
+
+    void InvaderEnemy::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        Pawn::damage(damage, healthdamage, shielddamage, originator, cs);
+        if (getGame() && orxonox_cast<InvaderShip*>(originator) != nullptr && getHealth() <= 0)
+            getGame()->addPoints(42);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemy.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemy.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemy.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderEnemy.h
+    @brief Declaration of the InvaderEnemy class.
+*/
+
+#ifndef _InvaderEnemy_H__
+#define _InvaderEnemy_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderEnemy : public Pawn
+    {
+        public:
+            InvaderEnemy(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs) override;
+            virtual void setInvaderPlayer(InvaderShip* player){this->player = player;}
+
+            int level;
+        protected:
+            Invader* getGame();
+            WeakPtr<Invader> game;
+            WeakPtr<InvaderShip> player;
+            Camera* camera;
+            bool isFireing;
+            float speed, damping;
+            float lastTimeFront, lastTimeLeft;
+            float lifetime;
+            struct Velocity
+            {
+                float x;
+                float y;
+            } velocity, desiredVelocity;
+
+    };
+}
+
+#endif /* _InvaderEnemy_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemyShooter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemyShooter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemyShooter.cc	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderEnemyShooter.h
+    @brief Declaration of the InvaderEnemyShooter class.
+*/
+
+#include "InvaderEnemyShooter.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "Invader.h"
+#include "InvaderShip.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderEnemyShooter);
+
+    InvaderEnemyShooter::InvaderEnemyShooter(Context* context) : InvaderEnemy(context)
+    {
+        RegisterObject(InvaderEnemyShooter);
+        enableCollisionCallback();
+        lifetime = 0;
+        // shoot every second
+        shootTimer.setTimer(1.0f, true, createExecutor(createFunctor(&InvaderEnemyShooter::shoot, this)));
+    }
+
+    void InvaderEnemyShooter::tick(float dt)
+    {
+        lifetime += dt;
+        // die after 20 seconds.
+        if (lifetime > 20000)
+            removeHealth(2000);
+
+        if (player != nullptr)
+        {
+            float distPlayer = player->getPosition().z - getPosition().z;
+            // orxout() << "i'm different!" << endl;
+            float newZ = 2/(pow(std::abs(getPosition().x - player->getPosition().x) * 0.01f, 2) + 1) * distPlayer;
+            setVelocity(Vector3(950 - std::abs(distPlayer), 0, newZ));
+        }
+        Pawn::tick(dt);
+    }
+
+    void InvaderEnemyShooter::shoot()
+    {
+        ControllableEntity::fire(0);
+    }
+
+    void InvaderEnemyShooter::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        Pawn::damage(damage, healthdamage, shielddamage, originator, cs);
+        if (getGame() && orxonox_cast<InvaderShip*>(originator) != nullptr && getHealth() <= 0)
+            getGame()->addPoints(3*42);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemyShooter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemyShooter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderEnemyShooter.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderEnemyShooter.h
+    @brief Declaration of the InvaderEnemyShooter class.
+*/
+
+#ifndef _InvaderEnemyShooter_H__
+#define _InvaderEnemyShooter_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "invader/InvaderEnemy.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderEnemyShooter : public InvaderEnemy
+    {
+        public:
+            InvaderEnemyShooter(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs) override;
+        protected:
+            void shoot();
+            Timer shootTimer;
+
+    };
+}
+
+#endif /* _InvaderEnemyShooter_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderHUDinfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderHUDinfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderHUDinfo.cc	(revision 11817)
@@ -0,0 +1,137 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *
+ */
+
+#include "InvaderHUDinfo.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "Invader.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderHUDinfo);
+
+    InvaderHUDinfo::InvaderHUDinfo(Context* context) : OverlayText(context)
+    {
+        RegisterObject(InvaderHUDinfo);
+
+        this->InvaderGame = nullptr;
+        this->bShowLives_ = false;
+        this->bShowLevel_ = false;
+        this->bShowPoints_ = false;
+        this->bShowMultiplier_ = false;
+    }
+
+    void InvaderHUDinfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(InvaderHUDinfo, XMLPort, xmlelement, mode);
+
+        XMLPortParam(InvaderHUDinfo, "showlives",     setShowLives,     getShowLives,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(InvaderHUDinfo, "showPoints",     setShowPoints,     getShowPoints,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(InvaderHUDinfo, "showLevel",     setShowLevel,     getShowLevel,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(InvaderHUDinfo, "showMultiplier",     setShowMultiplier,     getShowMultiplier,     xmlelement, mode).defaultValues(false);
+    }
+
+    void InvaderHUDinfo::tick(float dt)
+    {
+        SUPER(InvaderHUDinfo, tick, dt);
+
+        if (this->InvaderGame)
+        {
+            if (this->bShowLives_)
+            {
+                const std::string& lives = multi_cast<std::string>(this->InvaderGame->getLives());
+                this->setCaption(lives);
+            }
+            else if(this->bShowLevel_)
+            {
+                const std::string& Level = multi_cast<std::string>(this->InvaderGame->getLevel());
+                if (this->InvaderGame->lives <= 0)
+                {
+                    setPosition(Vector2(0.1, 0.65));
+                    this->setCaption("Game ends in 30 seconds.\nPress (e)xit / (q)uit to go to the main menu.\nTo restart fly out of the screen!");
+                    setTextSize(0.05);
+                    this->InvaderGame->bEndGame = true;
+                }
+                else if (this->InvaderGame->bShowLevel)
+                {
+                    setTextSize(0.1);
+                    setPosition(Vector2(0.3, 0.55));
+                    std::stringstream sstm;
+                    sstm << "Level " << Level;
+                    this->setCaption(sstm.str()); // + level
+                }
+                else
+                {
+                    setTextSize(0.04);
+                    setPosition(Vector2(0.14, 0.055));
+                    this->setCaption(Level);
+                }
+            }
+            else if(this->bShowPoints_)
+            {
+                const std::string& points = multi_cast<std::string>(this->InvaderGame->getPoints());
+                if (this->InvaderGame->lives <= 0)
+                {
+                    setTextSize(0.2);
+                    setPosition(Vector2(0.1, 0.25));
+                    this->setCaption("Final score:\n" + points);
+                    this->setColour(ColourValue(1, 0, 0, 1));
+                }
+                else
+                {
+                    setTextSize(0.04);
+                    setPosition(Vector2(0.14, 0.1));
+                    this->setColour(ColourValue(1, 1, 1, 1));
+                    this->setCaption(points);
+                }
+            }
+            else if(this->bShowMultiplier_)
+            {
+                int mult = this->InvaderGame->getMultiplier();
+                const std::string& Multiplier = "X " + multi_cast<std::string>(mult);
+                this->setCaption(Multiplier);
+                this->setColour(ColourValue(1, 0, 0, clamp(float(mult * 0.1), 0.0f, 1.0f)));
+                this->setTextSize(clamp(float(mult * 0.1), 0.0f, 1.0f) * 0.01f + 0.04f);
+            }
+        }
+    }
+
+    void InvaderHUDinfo::changedOwner()
+    {
+        SUPER(InvaderHUDinfo, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->InvaderGame = orxonox_cast<Invader*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->InvaderGame = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderHUDinfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderHUDinfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderHUDinfo.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *
+ */
+
+#ifndef _InvaderHUDinfo_H__
+#define _InvaderHUDinfo_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderHUDinfo : public OverlayText, public Tickable
+    {
+        public:
+            InvaderHUDinfo(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowLives(bool value)
+                { this->bShowLives_ = value; }
+            inline bool getShowLives() const
+                { return this->bShowLives_; }
+
+            inline void setShowLevel(bool value)
+                { this->bShowLevel_ = value; }
+            inline bool getShowLevel() const
+                { return this->bShowLevel_; }
+
+            inline void setShowPoints(bool value)
+                { this->bShowPoints_ = value; }
+            inline bool getShowPoints() const
+                { return this->bShowPoints_; }
+
+            inline void setShowMultiplier(bool value)
+                { this->bShowMultiplier_ = value; }
+            inline bool getShowMultiplier() const
+                { return this->bShowMultiplier_; }
+
+
+        private:
+            Invader* InvaderGame;
+            bool bShowLives_;
+            bool bShowLevel_;
+            bool bShowPoints_;
+            bool bShowMultiplier_;
+    };
+}
+#endif /* _InvaderHUDinfo_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderPrereqs.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the Invader module
+*/
+
+#ifndef _InvaderPrereqs_H__
+#define _InvaderPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(INVADER_STATIC_BUILD)
+#  ifdef INVADER_SHARED_BUILD
+#    define _InvaderExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _InvaderExport
+#    else
+#      define _InvaderExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _InvaderPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _InvaderExport  __attribute__ ((visibility("default")))
+#  define _InvaderPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _InvaderExport
+#  define _InvaderPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Invader;
+    class InvaderCenterPoint;
+    class InvaderShip;
+    class InvaderEnemy;
+    class InvaderEnemyShooter;
+    class InvaderWeapon;
+    class InvaderWeaponEnemy;
+    class InvaderHUDinfo;
+}
+
+#endif /* _InvaderPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderShip.cc	(revision 11817)
@@ -0,0 +1,197 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderShip.cc
+    @brief Implementation of the InvaderShip class.
+*/
+
+#include "InvaderShip.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "Invader.h"
+#include "InvaderEnemy.h"
+#include "graphics/Camera.h"
+#include "weapons/projectiles/Projectile.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderShip);
+
+    InvaderShip::InvaderShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(InvaderShip);
+
+        speed = 500;
+        isFireing = false;
+        damping = 10;
+    }
+
+    void InvaderShip::tick(float dt)
+    {
+        Vector3 pos = getPosition();
+
+        //Movement calculation
+        lastTimeFront += dt * damping;
+        lastTimeLeft += dt * damping;
+        lastTime += dt;
+
+        velocity.x = interpolate(clamp(lastTimeLeft, 0.0f, 1.0f), desiredVelocity.x, 0.0f);
+        velocity.y = interpolate(clamp(lastTimeFront, 0.0f, 1.0f), desiredVelocity.y, 0.0f);
+
+        //Execute movement
+        if (this->hasLocalController())
+        {
+            float dist_y = velocity.y * dt;
+            float dist_x = velocity.x * dt;
+            if(dist_y + posforeward > -42*3 && dist_y + posforeward < 42*6)
+                posforeward += dist_y;
+            else
+            {
+                velocity.y = 0;
+                // restart if game ended
+                if (getGame())
+                    if (getGame()->bEndGame)
+                    {
+                        getGame()->start();
+                        return;
+                    }
+            }
+            if (pos.z + dist_x > 42*2.5 || pos.z + dist_x < -42*3)
+                velocity.x = 0;
+            pos += Vector3(1000 + velocity.y, 0, velocity.x) * dt;
+        }
+
+        // shoot!
+        if (isFireing)
+            ControllableEntity::fire(0);
+
+        // Camera
+        Camera* camera = this->getCamera();
+        if (camera != nullptr)
+        {
+            camera->setPosition(Vector3(-pos.z, -posforeward, 0));
+            camera->setOrientation(Vector3::UNIT_Z, Degree(90));
+        }
+
+
+
+        // bring back on track!
+        if(pos.y != 0)
+            pos.y = 0;
+
+        setPosition(pos);
+        setOrientation(Vector3::UNIT_Y, Degree(270));
+
+        // Level up!
+        if (pos.x > 42000)
+        {
+            updateLevel();
+            setPosition(Vector3(0, 0, pos.z)); // pos - Vector3(30000, 0, 0)
+        }
+
+        SUPER(InvaderShip, tick, dt);
+    }
+
+    void InvaderShip::updateLevel()
+    {
+        lastTime = 0;
+        if (getGame())
+            getGame()->levelUp();
+    }
+
+    void InvaderShip::moveFrontBack(const Vector2& value)
+    {
+        lastTimeLeft = 0;
+        desiredVelocity.x = -value.x * speed;
+    }
+
+    void InvaderShip::moveRightLeft(const Vector2& value)
+    {
+        lastTimeFront = 0;
+        desiredVelocity.y = value.y * speed * 42;
+    }
+    void InvaderShip::boost(bool bBoost)
+    {
+        isFireing = bBoost;
+    }
+    void InvaderShip::rotateRoll(const Vector2& value)
+    {
+        if (getGame())
+            if (getGame()->bEndGame)
+                getGame()->end();
+    }
+    inline bool InvaderShip::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        // orxout() << "touch!!! " << endl; //<< otherObject << " at " << contactPoint;
+        InvaderEnemy* enemy = orxonox_cast<InvaderEnemy*>(otherObject);
+        Projectile* shot = orxonox_cast<Projectile*>(otherObject);
+        // ensure that this gets only called once per enemy.
+        if (enemy != nullptr && lastEnemy != enemy)
+        {
+            lastEnemy = enemy;
+
+            removeHealth(20);
+            if (getGame())
+            {
+                getGame()->multiplier = 1;                   
+            }
+        }
+        // was shot, decrease multiplier
+        else if (shot != nullptr  && lastShot != shot)
+        {
+            if (getGame() && orxonox_cast<InvaderEnemy*>(shot->getShooter()) != nullptr)
+            {
+                if (getGame()->multiplier > 1)
+                {
+                    lastShot = shot;
+                    getGame()->multiplier -= 1;     
+                }
+            }
+        }
+        return false;
+        // SUPER(InvaderShip, collidesAgainst, otherObject, contactPoint);
+    }
+
+    Invader* InvaderShip::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (Invader* invader : ObjectList<Invader>())
+                game = invader;
+        }
+        return game;
+    }
+
+    void InvaderShip::death()
+    {
+        getGame()->costLife();
+        SpaceShip::death();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderShip.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderShip.h
+    @brief Declaration of the InvaderShip class.
+*/
+
+#ifndef _InvaderShip_H__
+#define _InvaderShip_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "weapons/WeaponsPrereqs.h"
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderShip : public SpaceShip
+    {
+        public:
+            InvaderShip(Context* context);
+
+            virtual void tick(float dt) override;
+
+            // overwrite for 2d movement
+            virtual void moveFrontBack(const Vector2& value) override;
+            virtual void moveRightLeft(const Vector2& value) override;
+
+            // Starts or stops fireing
+            virtual void boost(bool bBoost) override;
+
+            //no rotation!
+            virtual void rotateYaw(const Vector2& value) override{}; 
+            virtual void rotatePitch(const Vector2& value) override{};
+            //return to main menu if game has ended.
+            virtual void rotateRoll(const Vector2& value) override;
+
+            virtual void updateLevel();
+
+            virtual inline bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+
+        protected:
+            virtual void death() override;
+        private:
+            Invader* getGame();
+            WeakPtr<Invader> game;
+            Camera* camera;
+            bool isFireing;
+            float speed, damping, posforeward;
+            float lastTimeFront, lastTimeLeft, lastTime;
+            struct Velocity
+            {
+                float x;
+                float y;
+            } velocity, desiredVelocity;
+
+            WeakPtr<InvaderEnemy> lastEnemy;
+            WeakPtr<Projectile> lastShot;
+
+    };
+}
+
+#endif /* _InvaderShip_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeapon.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeapon.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeapon.cc	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      --
+ *
+ */
+
+/**
+    @file InvaderWeapon.h
+    @brief Implementation of the InvaderWeapon class.
+*/
+
+#include "InvaderWeapon.h"
+
+#include "core/CoreIncludes.h"
+// #include "core/XMLPort.h"
+// #include "core/command/Executor.h"
+
+#include "graphics/Model.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/WorldEntity.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/Projectile.h"
+#include "weapons/MuzzleFlash.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderWeapon);
+
+    InvaderWeapon::InvaderWeapon(Context* context) : HsW01(context)
+    {
+        RegisterObject(InvaderWeapon);
+    }
+
+    InvaderWeapon::~InvaderWeapon()
+    {
+
+    }
+
+    void InvaderWeapon::shot()
+    {
+        assert( this->getWeapon() && this->getWeapon()->getWeaponPack() && this->getWeapon()->getWeaponPack()->getWeaponSystem() && this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn() );
+
+        // Create the projectile.projectile
+        projectile = new Projectile(this->getContext());
+        Model* model = new Model(projectile->getContext());
+        model->setMeshSource(mesh_);
+        model->setCastShadows(false);
+        projectile->attach(model);
+        model->setScale(5);
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        // only shoot in foreward direction
+        projectile->setOrientation(Quaternion(sqrt(0.5f),0,sqrt(0.5f),0));
+        projectile->setPosition(this->getMuzzlePosition());
+        // only shoot in foreward direction
+        projectile->setVelocity(Vector3(1, 0, 0) * 2000);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+
+        // Display the muzzle flash.
+        this->InvaderWeapon::muzzleflash();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeapon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeapon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeapon.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderWeapon.h
+    @brief Definition of the InvaderWeapon class.
+*/
+
+#ifndef _InvaderWeapon_H__
+#define _InvaderWeapon_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weapons/weaponmodes/HsW01.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderWeapon : public HsW01
+    {
+        public:
+            InvaderWeapon(Context* context);
+            virtual ~InvaderWeapon();
+        protected:
+            virtual void shot() override;
+            WeakPtr<Projectile> projectile;
+    };
+}
+
+#endif /* _InvaderWeapon_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeaponEnemy.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeaponEnemy.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeaponEnemy.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      --
+ *
+ */
+
+/**
+    @file InvaderWeaponEnemy.h
+    @brief Implementation of the InvaderWeaponEnemy class.
+*/
+
+#include "InvaderWeaponEnemy.h"
+
+#include "core/CoreIncludes.h"
+#include "weapons/projectiles/Projectile.h"
+
+namespace orxonox
+{
+    RegisterClass(InvaderWeaponEnemy);
+
+    InvaderWeaponEnemy::InvaderWeaponEnemy(Context* context) : InvaderWeapon(context)
+    {
+        RegisterObject(InvaderWeaponEnemy);
+    }
+
+    void InvaderWeaponEnemy::shot()
+    {
+        InvaderWeapon::shot();
+        // SUPER(InvaderWeaponEnemy, shot);
+        // only shoot in foreward direction
+        projectile->setVelocity(Vector3(1, 0, 0) * 300);
+        // projectile->setOrientation(Quaternion(sqrt(0.5),0,sqrt(0.5),0));
+    }
+}
+
+
Index: /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeaponEnemy.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeaponEnemy.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/invader/InvaderWeaponEnemy.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Florian Zinggeler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvaderWeaponEnemy.h
+    @brief Definition of the InvaderWeaponEnemy class.
+*/
+
+#ifndef _InvaderWeaponEnemy_H__
+#define _InvaderWeaponEnemy_H__
+
+#include "invader/InvaderPrereqs.h"
+
+#include "InvaderWeapon.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+    class _InvaderExport InvaderWeaponEnemy : public InvaderWeapon
+    {
+        public:
+            InvaderWeaponEnemy(Context* context);
+        protected:
+            virtual void shot() override;
+    };
+}
+
+#endif /* _InvaderWeaponEnemy_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,32 @@
+SET_SOURCE_FILES(JUMP_SRC_FILES
+BUILD_UNIT JumpBuildUnit.cc
+  Jump.cc
+  JumpPlatform.cc
+  JumpPlatformStatic.cc
+  JumpPlatformHMove.cc
+  JumpPlatformVMove.cc
+  JumpPlatformDisappear.cc
+  JumpPlatformTimer.cc
+  JumpPlatformFake.cc
+  JumpProjectile.cc
+  JumpEnemy.cc
+  JumpFigure.cc
+  JumpItem.cc
+  JumpSpring.cc
+  JumpRocket.cc
+  JumpShield.cc
+  JumpPropeller.cc
+  JumpBoots.cc
+  JumpCenterpoint.cc
+  JumpScore.cc
+END_BUILD_UNIT
+)
+
+ORXONOX_ADD_LIBRARY(jump
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+  SOURCE_FILES ${JUMP_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/jump/Jump.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/Jump.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/Jump.cc	(revision 11817)
@@ -0,0 +1,1304 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Jump.cc
+    @brief This is the gametype for the awesome minigame. Here the level is randomly created, the camera is shifted, ...
+*/
+
+#include "Jump.h"
+#include "core/CoreIncludes.h"
+#include "Highscore.h"
+
+#include "JumpCenterpoint.h"
+#include "JumpPlatform.h"
+#include "JumpPlatformStatic.h"
+#include "JumpPlatformHMove.h"
+#include "JumpPlatformVMove.h"
+#include "JumpPlatformDisappear.h"
+#include "JumpPlatformTimer.h"
+#include "JumpPlatformFake.h"
+#include "JumpProjectile.h"
+#include "JumpEnemy.h"
+#include "JumpFigure.h"
+#include "JumpItem.h"
+#include "JumpSpring.h"
+#include "JumpRocket.h"
+#include "JumpPropeller.h"
+#include "JumpBoots.h"
+#include "JumpShield.h"
+
+#include "gamestates/GSLevel.h"
+#include "infos/PlayerInfo.h"
+#include "graphics/Camera.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Jump);
+
+    Jump::Jump(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(Jump);
+
+        center_ = nullptr;
+        figure_ = nullptr;
+        camera = nullptr;
+        setHUDTemplate("JumpHUD");
+    }
+
+    Jump::~Jump()
+    {
+        if (isInitialized())
+        {
+            cleanup();
+        }
+    }
+
+    void Jump::tick(float dt)
+    {
+        SUPER(Jump, tick, dt);
+
+        if (figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getPosition();
+            Vector3 figureVelocity = figure_->getVelocity();
+
+            float boundary = totalScreenShift_+center_->getCameraOffset();
+
+            if (figurePosition.z > boundary)
+            {
+                screenShiftSinceLastUpdate_ += figurePosition.z - boundary;
+                totalScreenShift_ = figurePosition.z - center_->getCameraOffset();
+
+                // Create new platforms if needed
+                if (screenShiftSinceLastUpdate_ > center_->getSectionLength())
+                {
+                    if (sectionNumber_ > 2 && sectionNumber_%4 == 0 && rand()%2 == 0 && figure_->propellerActive_ == nullptr && figure_->rocketActive_ == nullptr && addAdventure(adventureNumber_) == true)
+                    {
+                        screenShiftSinceLastUpdate_ -= 2*center_->getSectionLength();
+                        ++ adventureNumber_;
+                    }
+                    else
+                    {
+                        screenShiftSinceLastUpdate_ -= center_->getSectionLength();
+                        addSection();
+                    }
+                }
+            }
+
+            if (figurePosition.z < totalScreenShift_ - center_->getFieldDimension().y + platformHeight_ && figureVelocity.z < 0)
+            {
+                figure_->dead_ = true;
+            }
+
+            if (figure_->fireSignal_ == true)
+            {
+                if (figure_->dead_ == true)
+                {
+                    end();
+                }
+                else
+                {
+                    figure_->fireSignal_ = false;
+                    addProjectile(figurePosition.x, figurePosition.z + figure_->getPropellerPos());
+                }
+            }
+
+
+            if (camera != nullptr)
+            {
+                Vector3 cameraPosition = Vector3(0, totalScreenShift_, 0);
+                camera->setPosition(cameraPosition);
+            }
+            else
+            {
+                orxout() << "No camera found." << endl;
+            }
+        }
+
+        ObjectList<JumpPlatform> listPlatform;
+        ObjectList<JumpPlatform>::iterator itPlatform = listPlatform.begin();
+        Vector3 platformPosition;
+
+        while (itPlatform != listPlatform.end())
+        {
+            platformPosition = itPlatform->getPosition();
+            if (platformPosition.z < totalScreenShift_ - center_->getFieldDimension().y)
+            {
+                ObjectList<JumpPlatform>::iterator temp = itPlatform;
+                ++ itPlatform;
+                center_->detach(*temp);
+                temp->destroy();
+            }
+            else
+            {
+                ++ itPlatform;
+            }
+        }
+
+        // Deleted deactivated platforms
+        ObjectList<JumpPlatformDisappear> listDisappear;
+        ObjectList<JumpPlatformDisappear>::iterator itDisappear = listDisappear.begin();
+
+        while (itDisappear != listDisappear.end())
+        {
+            if (!itDisappear->isActive())
+            {
+                ObjectList<JumpPlatformDisappear>::iterator temp = itDisappear;
+                ++ itDisappear;
+                center_->detach(*temp);
+                temp->destroy();
+            }
+            else
+            {
+                ++ itDisappear;
+            }
+        }
+
+        ObjectList<JumpPlatformTimer> listTimer;
+        ObjectList<JumpPlatformTimer>::iterator itTimer = listTimer.begin();
+
+        while (itTimer != listTimer.end())
+        {
+            if (!itTimer->isActive())
+            {
+                ObjectList<JumpPlatformTimer>::iterator temp = itTimer;
+                ++ itTimer;
+                center_->detach(*temp);
+                temp->destroy();
+            }
+            else
+            {
+                ++ itTimer;
+            }
+        }
+
+        ObjectList<JumpProjectile> listProjectile;
+        ObjectList<JumpProjectile>::iterator itProjectile = listProjectile.begin();
+        Vector3 projectilePosition;
+
+        while (itProjectile != listProjectile.end())
+        {
+            projectilePosition = itProjectile->getPosition();
+            if (projectilePosition.z > totalScreenShift_ + 5*center_->getFieldDimension().y)
+            {
+                ObjectList<JumpProjectile>::iterator temp = itProjectile;
+                ++ itProjectile;
+                center_->detach(*temp);
+                temp->destroy();
+            }
+            else
+            {
+                ++ itProjectile;
+            }
+        }
+
+        ObjectList<JumpEnemy> listEnemy;
+        ObjectList<JumpEnemy>::iterator itEnemy = listEnemy.begin();
+        Vector3 enemyPosition;
+
+        while (itEnemy != listEnemy.end())
+        {
+            enemyPosition = itEnemy->getPosition();
+            if (enemyPosition.z < totalScreenShift_ - center_->getFieldDimension().y || itEnemy->dead_ == true)
+            {
+                ObjectList<JumpEnemy>::iterator temp = itEnemy;
+                ++ itEnemy;
+                center_->detach(*temp);
+                temp->destroy();
+            }
+            else
+            {
+                ++ itEnemy;
+            }
+        }
+
+        ObjectList<JumpItem> listItem;
+        ObjectList<JumpItem>::iterator itItem = listItem.begin();
+        Vector3 itemPosition;
+
+        while (itItem != listItem.end())
+        {
+            itemPosition = itItem->getPosition();
+
+            WorldEntity* parent = itItem->getParent();
+
+            if (itItem->attachedToFigure_ == false && itemPosition.z < totalScreenShift_ - center_->getFieldDimension().y && parent == center_)
+            {
+                ObjectList<JumpItem>::iterator temp = itItem;
+                ++ itItem;
+                center_->detach(*temp);
+                temp->destroy();
+            }
+            else
+            {
+                ++ itItem;
+            }
+        }
+    }
+
+    void Jump::cleanup()
+    {
+        camera = nullptr;
+    }
+
+    void Jump::start()
+    {
+        if (center_ != nullptr) // There needs to be a JumpCenterpoint, i.e. the area the game takes place.
+        {
+            if (figure_ == nullptr)
+            {
+                figure_ = new JumpFigure(center_->getContext());
+                figure_->addTemplate(center_->getFigureTemplate());
+                figure_->InitializeAnimation(center_->getContext());
+            }
+
+            center_->attach(figure_);
+            figure_->setPosition(0, 0, 0);
+            figure_->setFieldDimension(center_->getFieldDimension());
+        }
+        else // If no centerpoint was specified, an error is thrown and the level is exited.
+        {
+            orxout(internal_error) << "Jump: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+
+        // Call start for the parent class.
+        Deathmatch::start();
+
+        if (figure_ != nullptr)
+        {
+            camera = figure_->getCamera();
+        }
+
+        totalScreenShift_ = 0.0;
+        screenShiftSinceLastUpdate_ = 0.0;
+        sectionNumber_ = 0;
+        adventureNumber_ = 0;
+
+        addStartSection();
+        addSection();
+        addSection();
+    }
+
+    void Jump::end()
+    {
+        cleanup();
+        GSLevel::startMainMenu();
+        if (Highscore::exists())
+        {
+            int score = this->getScore(this->getPlayer());
+            Highscore::getInstance().storeScore("Jump", score, this->getPlayer());
+        }
+        Deathmatch::end();
+    }
+
+    void Jump::spawnPlayer(PlayerInfo* player)
+    {
+        assert(player);
+
+        if (figure_->getPlayer() == nullptr)
+        {
+            player->startControl(figure_);
+            players_[player].state_ = PlayerState::Alive;
+        }
+    }
+
+    PlayerInfo* Jump::getPlayer() const
+    {
+        if (this->figure_ != nullptr)
+        {
+            return this->figure_->getPlayer();
+        }
+        else
+        {
+            return nullptr;
+        }
+    }
+
+    void Jump::addPlatform(JumpPlatform* newPlatform, std::string platformTemplate, float xPosition, float zPosition)
+    {
+        if (newPlatform != nullptr && center_ != nullptr)
+        {
+            newPlatform->addTemplate(platformTemplate);
+            newPlatform->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newPlatform->setFigure(this->figure_);
+            center_->attach(newPlatform);
+        }
+    }
+
+    JumpPlatformStatic* Jump::addPlatformStatic(float xPosition, float zPosition)
+    {
+        JumpPlatformStatic* newPlatform = new JumpPlatformStatic(center_->getContext());
+        addPlatform(newPlatform, center_->getPlatformStaticTemplate(), xPosition, zPosition);
+
+        return newPlatform;
+    }
+
+    JumpPlatformHMove* Jump::addPlatformHMove(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float speed)
+    {
+        JumpPlatformHMove* newPlatform = new JumpPlatformHMove(center_->getContext());
+        newPlatform->setProperties(leftBoundary, rightBoundary, speed);
+        addPlatform(newPlatform, center_->getPlatformHMoveTemplate(), xPosition, zPosition);
+
+        return newPlatform;
+    }
+
+    JumpPlatformVMove* Jump::addPlatformVMove(float xPosition, float zPosition, float lowerBoundary, float upperBoundary, float speed)
+    {
+        JumpPlatformVMove* newPlatform = new JumpPlatformVMove(center_->getContext());
+        newPlatform->setProperties(lowerBoundary, upperBoundary, speed);
+        addPlatform(newPlatform, center_->getPlatformVMoveTemplate(), xPosition, zPosition);
+
+        return newPlatform;
+    }
+
+    JumpPlatformDisappear* Jump::addPlatformDisappear(float xPosition, float zPosition)
+    {
+        JumpPlatformDisappear* newPlatform = new JumpPlatformDisappear(center_->getContext());
+        newPlatform->setProperties(true);
+        addPlatform(newPlatform, center_->getPlatformDisappearTemplate(), xPosition, zPosition);
+
+        return newPlatform;
+    }
+
+    JumpPlatformTimer* Jump::addPlatformTimer(float xPosition, float zPosition, float time, float variance)
+    {
+        float additionalTime = (float)(rand()%100)/100.0f*variance - variance/2.0f;
+
+        JumpPlatformTimer* newPlatform = new JumpPlatformTimer(center_->getContext());
+        newPlatform->setProperties(time + additionalTime);
+        addPlatform(newPlatform, center_->getPlatformTimerTemplate(), xPosition, zPosition);
+
+        return newPlatform;
+    }
+
+    JumpPlatformFake* Jump::addPlatformFake(float xPosition, float zPosition)
+    {
+        JumpPlatformFake* newPlatform = new JumpPlatformFake(center_->getContext());
+        addPlatform(newPlatform, center_->getPlatformFakeTemplate(), xPosition, zPosition);
+        newPlatform->setAngularVelocity(Vector3(0, 0, 2.0));
+
+        return newPlatform;
+    }
+
+
+    void Jump::addProjectile(float xPosition, float zPosition)
+    {
+        JumpProjectile* newProjectile = new JumpProjectile(center_->getContext());
+        if (newProjectile != nullptr && center_ != nullptr)
+        {
+            newProjectile->addTemplate(center_->getProjectileTemplate());
+            newProjectile->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newProjectile->setFieldDimension(center_->getFieldDimension());
+            newProjectile->setFigure(this->figure_);
+            center_->attach(newProjectile);
+        }
+    }
+
+    void Jump::addSpring(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity)
+    {
+        JumpSpring* newSpring = new JumpSpring(center_->getContext());
+        if (newSpring != nullptr && center_ != nullptr)
+        {
+            newSpring->addTemplate(center_->getSpringTemplate());
+            newSpring->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newSpring->setProperties(leftBoundary, rightBoundary, lowerBoundary, upperBoundary, xVelocity, zVelocity);
+            newSpring->setFigure(figure_);
+            center_->attach(newSpring);
+        }
+    }
+
+    void Jump::addSpring(JumpPlatform* platform)
+    {
+        JumpSpring* newSpring = new JumpSpring(center_->getContext());
+        if (newSpring != nullptr && center_ != nullptr)
+        {
+            newSpring->addTemplate(center_->getSpringTemplate());
+            newSpring->setPosition(Vector3(0.0, 0.0, 0.0));
+            newSpring->setProperties(-10.0, 10.0, -10.0, 10.0, 0.0, 0.0);
+            newSpring->setFigure(figure_);
+            platform->attach(newSpring);
+        }
+    }
+
+    void Jump::addRocket(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity)
+    {
+        JumpRocket* newRocket = new JumpRocket(center_->getContext());
+        if (newRocket != nullptr && center_ != nullptr)
+        {
+            newRocket->addTemplate(center_->getRocketTemplate());
+            newRocket->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newRocket->setProperties(leftBoundary, rightBoundary, lowerBoundary, upperBoundary, xVelocity, zVelocity);
+            newRocket->setFigure(figure_);
+            center_->attach(newRocket);
+        }
+    }
+
+    void Jump::addRocket(JumpPlatform* platform)
+    {
+        JumpRocket* newRocket = new JumpRocket(center_->getContext());
+        if (newRocket != nullptr && center_ != nullptr)
+        {
+            newRocket->addTemplate(center_->getRocketTemplate());
+            newRocket->setPosition(Vector3(0.0, 0.0, 0.0));
+            newRocket->setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            newRocket->setFigure(figure_);
+            platform->attach(newRocket);
+        }
+    }
+
+    void Jump::addPropeller(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity)
+    {
+        JumpPropeller* newPropeller = new JumpPropeller(center_->getContext());
+        if (newPropeller != nullptr && center_ != nullptr)
+        {
+            newPropeller->addTemplate(center_->getPropellerTemplate());
+            newPropeller->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newPropeller->setProperties(leftBoundary, rightBoundary, lowerBoundary, upperBoundary, xVelocity, zVelocity);
+            newPropeller->setFigure(figure_);
+            center_->attach(newPropeller);
+        }
+    }
+
+    void Jump::addPropeller(JumpPlatform* platform)
+    {
+        JumpPropeller* newPropeller = new JumpPropeller(center_->getContext());
+        if (newPropeller != nullptr && center_ != nullptr)
+        {
+            newPropeller->addTemplate(center_->getPropellerTemplate());
+            newPropeller->setPosition(Vector3(0.0, 0.0, 0.0));
+            newPropeller->setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            newPropeller->setFigure(figure_);
+            platform->attach(newPropeller);
+        }
+    }
+
+    void Jump::addBoots(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity)
+    {
+        JumpBoots* newBoots = new JumpBoots(center_->getContext());
+        if (newBoots != nullptr && center_ != nullptr)
+        {
+            newBoots->addTemplate(center_->getBootsTemplate());
+            newBoots->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newBoots->setProperties(leftBoundary, rightBoundary, lowerBoundary, upperBoundary, xVelocity, zVelocity);
+            newBoots->setFigure(figure_);
+            center_->attach(newBoots);
+        }
+    }
+
+    void Jump::addBoots(JumpPlatform* platform)
+    {
+        JumpBoots* newBoots = new JumpBoots(center_->getContext());
+        if (newBoots != nullptr && center_ != nullptr)
+        {
+            newBoots->addTemplate(center_->getBootsTemplate());
+            newBoots->setPosition(Vector3(0.0, 0.0, 0.0));
+            newBoots->setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            newBoots->setFigure(figure_);
+            platform->attach(newBoots);
+        }
+    }
+
+    void Jump::addShield(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity)
+    {
+        JumpShield* newShield = new JumpShield(center_->getContext());
+        if (newShield != nullptr && center_ != nullptr)
+        {
+            newShield->addTemplate(center_->getShieldTemplate());
+            newShield->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newShield->setProperties(leftBoundary, rightBoundary, lowerBoundary, upperBoundary, xVelocity, zVelocity);
+            newShield->setFigure(figure_);
+            center_->attach(newShield);
+        }
+    }
+
+    void Jump::addShield(JumpPlatform* platform)
+    {
+        JumpShield* newShield = new JumpShield(center_->getContext());
+        if (newShield != nullptr && center_ != nullptr)
+        {
+            newShield->addTemplate(center_->getShieldTemplate());
+            newShield->setPosition(Vector3(0.0, 0.0, 0.0));
+            newShield->setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+            newShield->setFigure(figure_);
+            platform->attach(newShield);
+        }
+    }
+
+    void Jump::addEnemy(int type, float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity)
+    {
+        JumpEnemy* newEnemy = new JumpEnemy(center_->getContext());
+        if (newEnemy != nullptr && center_ != nullptr)
+        {
+            switch (type)
+            {
+            case 1:
+                newEnemy->addTemplate(center_->getEnemy1Template());
+                break;
+            case 2:
+                newEnemy->addTemplate(center_->getEnemy2Template());
+                break;
+            case 3:
+                newEnemy->addTemplate(center_->getEnemy3Template());
+                break;
+            case 4:
+                newEnemy->addTemplate(center_->getEnemy4Template());
+                break;
+            default:
+                return;
+            }
+
+            newEnemy->setPosition(Vector3(xPosition, 0.0, zPosition));
+            newEnemy->setProperties(leftBoundary, rightBoundary, lowerBoundary, upperBoundary, xVelocity, zVelocity);
+            newEnemy->setFieldDimension(center_->getFieldDimension());
+            newEnemy->setFigure(this->figure_);
+            center_->attach(newEnemy);
+        }
+    }
+
+    void Jump::addStartSection()
+    {
+        JumpPlatform* newPlatform;
+
+        float sectionLength = center_->getSectionLength();
+
+        newPlatform = new JumpPlatformStatic(center_->getContext());
+        addPlatform(newPlatform, center_->getPlatformStaticTemplate(), 0.0, -0.05f*sectionLength);
+
+        platformWidth_ = newPlatform->getWidth();
+        platformHeight_ = newPlatform->getHeight();
+
+        for (float xPosition = platformWidth_; xPosition <= center_->getFieldDimension().x; xPosition += platformWidth_)
+        {
+            newPlatform = new JumpPlatformStatic(center_->getContext());
+            addPlatform(newPlatform, center_->getPlatformStaticTemplate(), xPosition, -0.05f*sectionLength);
+            newPlatform = new JumpPlatformStatic(center_->getContext());
+            addPlatform(newPlatform, center_->getPlatformStaticTemplate(), -xPosition, -0.05f*sectionLength);
+        }
+    }
+
+    void Jump::addSection()
+    {
+        float fieldWidth = center_->getFieldDimension().x;
+        float sectionLength = center_->getSectionLength();
+        float sectionBegin = sectionNumber_ * sectionLength;
+        float sectionEnd = (1 + sectionNumber_) * sectionLength;
+
+        const int numI = 6;
+        const int numJ = 4;
+
+        enum class PlatformType
+        {
+            EMPTY, STATIC, HMOVE, VMOVE, DISAPPEAR, TIMER, FAKE
+        };
+
+        enum class ItemType
+        {
+            NOTHING, SPRING, PROPELLER, ROCKET, BOOTS, SHIELD
+        };
+
+        struct PlatformMatrix
+        {
+            PlatformType type;
+            bool done;
+        } matrix[numI][numJ];
+
+
+        for (int i = 0; i < numI; ++i)
+        {
+            for (int j = 0; j < numJ; ++j)
+            {
+                matrix[i][j].type = PlatformType::EMPTY;
+                matrix[i][j].done = false;
+            }
+        }
+        PlatformType platformtype1;
+        PlatformType platformtype2;
+        ItemType itemType = ItemType::NOTHING;
+
+        if (rand()%2 == 0)
+        {
+            itemType = ItemType::SPRING;
+        }
+        else if (rand()%2 == 0 && sectionNumber_ > 3)
+        {
+            switch(rand()%4)
+            {
+            case 0:
+                itemType = ItemType::PROPELLER;
+                break;
+            case 1:
+                itemType = ItemType::ROCKET;
+                break;
+            case 2:
+                itemType = ItemType::BOOTS;
+                break;
+            case 3:
+                itemType = ItemType::SHIELD;
+                break;
+            default:
+                break;
+            }
+        }
+
+        switch((sectionNumber_ > 28) ? rand()%29 : rand()%(sectionNumber_+1))
+        {
+        case 0:
+            platformtype1 = PlatformType::STATIC;
+            platformtype2 = PlatformType::STATIC;
+            break;
+        case 1:
+            platformtype1 = PlatformType::STATIC;
+            platformtype2 = PlatformType::STATIC;
+            break;
+        case 2:
+            platformtype1 = PlatformType::STATIC;
+            platformtype2 = PlatformType::HMOVE;
+            break;
+        case 3:
+            platformtype1 = PlatformType::STATIC;
+            platformtype2 = PlatformType::DISAPPEAR;
+            break;
+        case 4:
+            platformtype1 = PlatformType::STATIC;
+            platformtype2 = PlatformType::VMOVE;
+            break;
+        case 5:
+            platformtype1 = PlatformType::STATIC;
+            platformtype2 = PlatformType::TIMER;
+            break;
+        case 6:
+            platformtype1 = PlatformType::HMOVE;
+            platformtype2 = PlatformType::STATIC;
+            break;
+        case 7:
+            platformtype1 = PlatformType::HMOVE;
+            platformtype2 = PlatformType::HMOVE;
+            break;
+        case 8:
+            platformtype1 = PlatformType::HMOVE;
+            platformtype2 = PlatformType::HMOVE;
+            break;
+        case 9:
+            platformtype1 = PlatformType::HMOVE;
+            platformtype2 = PlatformType::DISAPPEAR;
+            break;
+        case 10:
+            platformtype1 = PlatformType::HMOVE;
+            platformtype2 = PlatformType::VMOVE;
+            break;
+        case 11:
+            platformtype1 = PlatformType::HMOVE;
+            platformtype2 = PlatformType::TIMER;
+            break;
+        case 12:
+            platformtype1 = PlatformType::DISAPPEAR;
+            platformtype2 = PlatformType::STATIC;
+            break;
+        case 13:
+            platformtype1 = PlatformType::DISAPPEAR;
+            platformtype2 = PlatformType::HMOVE;
+            break;
+        case 14:
+            platformtype1 = PlatformType::DISAPPEAR;
+            platformtype2 = PlatformType::DISAPPEAR;
+            break;
+        case 15:
+            platformtype1 = PlatformType::DISAPPEAR;
+            platformtype2 = PlatformType::DISAPPEAR;
+            break;
+        case 16:
+            platformtype1 = PlatformType::DISAPPEAR;
+            platformtype2 = PlatformType::VMOVE;
+            break;
+        case 17:
+            platformtype1 = PlatformType::DISAPPEAR;
+            platformtype2 = PlatformType::TIMER;
+            break;
+        case 18:
+            platformtype1 = PlatformType::VMOVE;
+            platformtype2 = PlatformType::STATIC;
+            break;
+        case 19:
+            platformtype1 = PlatformType::VMOVE;
+            platformtype2 = PlatformType::HMOVE;
+            break;
+        case 20:
+            platformtype1 = PlatformType::VMOVE;
+            platformtype2 = PlatformType::DISAPPEAR;
+            break;
+        case 21:
+            platformtype1 = PlatformType::VMOVE;
+            platformtype2 = PlatformType::VMOVE;
+            break;
+        case 22:
+            platformtype1 = PlatformType::VMOVE;
+            platformtype2 = PlatformType::VMOVE;
+            break;
+        case 23:
+            platformtype1 = PlatformType::VMOVE;
+            platformtype2 = PlatformType::TIMER;
+            break;
+        case 24:
+            platformtype1 = PlatformType::TIMER;
+            platformtype2 = PlatformType::STATIC;
+            break;
+        case 25:
+            platformtype1 = PlatformType::TIMER;
+            platformtype2 = PlatformType::HMOVE;
+            break;
+        case 26:
+            platformtype1 = PlatformType::TIMER;
+            platformtype2 = PlatformType::DISAPPEAR;
+            break;
+        case 27:
+            platformtype1 = PlatformType::TIMER;
+            platformtype2 = PlatformType::VMOVE;
+            break;
+        case 28:
+            platformtype1 = PlatformType::TIMER;
+            platformtype2 = PlatformType::TIMER;
+            break;
+        default:
+            platformtype1 = PlatformType::TIMER;
+            platformtype2 = PlatformType::TIMER;
+            break;
+        }
+
+        // Fill matrix with selected platform types
+        for (int i = 0; i < numI; ++ i)
+        {
+            for (int j = 0; j < numJ; ++ j)
+            {
+                if (rand()%3 == 0)
+                {
+                    matrix[i][j].type = platformtype1;
+                }
+                else
+                {
+                    matrix[i][j].type = platformtype2;
+                }
+                matrix[i][j].done = false;
+            }
+        }
+
+        if (platformtype1 == platformtype2 && sectionNumber_ > 10 && rand()%2 == 0)
+        {
+            matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+        }
+
+        // Delete some planned platforms or replace them with fake platforms
+        if (sectionNumber_ > 5)
+        {
+            if (rand()%2 == 0)
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            }
+            else
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::FAKE;
+            }
+        }
+        else if (sectionNumber_ > 10)
+        {
+            if (rand()%2 == 0)
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            }
+            else
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::FAKE;
+            }
+            if (rand()%2 == 0)
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            }
+            else
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::FAKE;
+            }
+        }
+        else if (sectionNumber_ > 15)
+        {
+            if (rand()%2 == 0)
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            }
+            else
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::FAKE;
+            }
+            if (rand()%2 == 0)
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            }
+            else
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::FAKE;
+            }
+            if (rand()%2 == 0)
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::EMPTY;
+            }
+            else
+            {
+                matrix[rand()%numI][rand()%numJ].type = PlatformType::FAKE;
+            }
+        }
+
+        std::vector<JumpPlatform*> platformList;
+
+        for (int i = 0; i < numI; ++ i)
+        {
+            for (int j = 0; j < numJ; ++ j)
+            {
+                if (matrix[i][j].done == false)
+                {
+                    float xPosition = 0.0;
+                    float zPosition = 0.0;
+                    float leftBoundary = 0.0;
+                    float rightBoundary = 0.0;
+                    float lowerBoundary = 0.0;
+                    float upperBoundary = 0.0;
+                    float xVelocity = 0.0;
+                    float zVelocity = 0.0;
+
+                    switch(matrix[i][j].type)
+                    {
+                    case PlatformType::EMPTY:
+                        matrix[i][j].done = true;
+                        break;
+                    case PlatformType::STATIC:
+                        xPosition = randomXPosition(numJ, j);
+                        zPosition = sectionBegin + i*sectionLength/numI;
+                        platformList.push_back(addPlatformStatic(xPosition, zPosition));
+                        matrix[i][j].done = true;
+                        break;
+                    case PlatformType::FAKE:
+                        xPosition = randomXPosition(numJ, j);
+                        zPosition = sectionBegin + i*sectionLength/numI;
+                        platformList.push_back(addPlatformFake(xPosition, zPosition));
+                        matrix[i][j].done = true;
+                        break;
+                    case PlatformType::TIMER:
+                        xPosition = randomXPosition(numJ, j);
+                        zPosition = sectionBegin + i*sectionLength/numI;
+                        platformList.push_back(addPlatformTimer(xPosition, zPosition, 12.0, 1.5));
+                        matrix[i][j].done = true;
+                        break;
+                    case PlatformType::DISAPPEAR:
+                        xPosition = randomXPosition(numJ, j);
+                        zPosition = sectionBegin + i*sectionLength/numI;
+                        platformList.push_back(addPlatformDisappear(xPosition, zPosition));
+                        matrix[i][j].done = true;
+                        break;
+                    case PlatformType::HMOVE:
+                        xVelocity = randomSpeed();
+                        if (j <= numJ-3 && matrix[i][j+1].type == PlatformType::HMOVE && matrix[i][j+2].type == PlatformType::HMOVE && rand()%2 == 0)
+                        {
+                            leftBoundary = randomXPositionLeft(numJ, j);
+                            rightBoundary = randomXPositionRight(numJ, j+2);
+                            xPosition = randomPosition(leftBoundary, rightBoundary);
+                            zPosition = sectionBegin + i*sectionLength/numI;
+                            platformList.push_back(addPlatformHMove(xPosition, zPosition, leftBoundary, rightBoundary, xVelocity));
+                            matrix[i][j].done = true;
+                            matrix[i][j+1].done = true;
+                            matrix[i][j+2].done = true;
+                        }
+                        else if (j <= numJ-2 && matrix[i][j+1].type == PlatformType::HMOVE && rand()%2 == 0)
+                        {
+                            leftBoundary = randomXPositionLeft(numJ, j);
+                            rightBoundary = randomXPositionRight(numJ, j+1);
+                            xPosition = randomPosition(leftBoundary, rightBoundary);
+                            zPosition = sectionBegin + i*sectionLength/numI;
+                            platformList.push_back(addPlatformHMove(xPosition, zPosition, leftBoundary, rightBoundary, xVelocity));
+                            matrix[i][j].done = true;
+                            matrix[i][j+1].done = true;
+                        }
+                        else
+                        {
+                            leftBoundary = randomXPositionLeft(numJ, j);
+                            rightBoundary = randomXPositionRight(numJ, j);
+                            xPosition = randomPosition(leftBoundary, rightBoundary);
+                            zPosition = sectionBegin + i*sectionLength/numI;
+                            platformList.push_back(addPlatformHMove(xPosition, zPosition, leftBoundary, rightBoundary, xVelocity));
+                            matrix[i][j].done = true;
+                        }
+                        break;
+                    case PlatformType::VMOVE:
+                        zVelocity = randomSpeed();
+                        if (i <= numI-3 && matrix[i+1][j].type == PlatformType::VMOVE && matrix[i+2][j].type == PlatformType::VMOVE && rand()%2 == 0)
+                        {
+                            lowerBoundary = randomZPositionLower(numI, i, sectionBegin, sectionEnd);
+                            upperBoundary = randomZPositionUpper(numI, i+2, sectionBegin, sectionEnd);
+                            zPosition = randomPosition(lowerBoundary, upperBoundary);
+                            xPosition = randomXPosition(numJ, j);
+                            platformList.push_back(addPlatformVMove(xPosition, zPosition, lowerBoundary, upperBoundary, zVelocity));
+                            matrix[i][j].done = true;
+                            matrix[i+1][j].done = true;
+                            matrix[i+2][j].done = true;
+                        }
+                        else if (i <= numI-2 && matrix[i+1][j].type == PlatformType::VMOVE && rand()%2 == 0)
+                        {
+                            lowerBoundary = randomZPositionLower(numI, i, sectionBegin, sectionEnd);
+                            upperBoundary = randomZPositionUpper(numI, i+1, sectionBegin, sectionEnd);
+                            zPosition = randomPosition(lowerBoundary, upperBoundary);
+                            xPosition = randomXPosition(numJ, j);
+                            platformList.push_back(addPlatformVMove(xPosition, zPosition, lowerBoundary, upperBoundary, zVelocity));
+                            matrix[i][j].done = true;
+                            matrix[i+1][j].done = true;
+                        }
+                        else
+                        {
+                            lowerBoundary = randomZPositionLower(numI, i, sectionBegin, sectionEnd);
+                            upperBoundary = randomZPositionUpper(numI, i, sectionBegin, sectionEnd);
+                            zPosition = randomPosition(lowerBoundary, upperBoundary);
+                            xPosition = randomXPosition(numJ, j);
+                            platformList.push_back(addPlatformVMove(xPosition, zPosition, lowerBoundary, upperBoundary, zVelocity));
+                            matrix[i][j].done = true;
+                        }
+                        break;
+                    default:
+                        //ERROR
+                        break;
+
+                    }
+                }
+            }
+        }
+
+        //Add items
+        int numNewPlatforms = platformList.size();
+
+        if (rand()%4 == 0)
+        {
+            if (rand()%2 == 0)
+            {
+                switch (itemType)
+                {
+                case ItemType::ROCKET:
+                    addRocket(0.0, randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/2, fieldWidth/2, 0.0, 0.0, randomSpeed(), 0.0);
+                    break;
+                case ItemType::PROPELLER:
+                    addPropeller(0.0, randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/2, fieldWidth/2, 0.0, 0.0, randomSpeed(), 0.0);
+                    break;
+                case ItemType::BOOTS:
+                    addBoots(0.0, randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/2, fieldWidth/2, 0.0, 0.0, randomSpeed(), 0.0);
+                    break;
+                case ItemType::SHIELD:
+                    addShield(0.0, randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/2, fieldWidth/2, 0.0, 0.0, randomSpeed(), 0.0);
+                    break;
+                default:
+                    break;
+                }
+            }
+            else
+            {
+                switch (itemType)
+                {
+                case ItemType::ROCKET:
+                    addRocket(randomPosition(-fieldWidth/2, fieldWidth/2), sectionBegin + sectionLength/2, 0.0, 0.0, sectionBegin, sectionEnd, 0.0, randomSpeed());
+                    break;
+                case ItemType::PROPELLER:
+                    addPropeller(randomPosition(-fieldWidth/2, fieldWidth/2), sectionBegin + sectionLength/2, 0.0, 0.0, sectionBegin, sectionEnd, 0.0, randomSpeed());
+                    break;
+                case ItemType::BOOTS:
+                    addBoots(randomPosition(-fieldWidth/2, fieldWidth/2), sectionBegin + sectionLength/2, 0.0, 0.0, sectionBegin, sectionEnd, 0.0, randomSpeed());
+                    break;
+                case ItemType::SHIELD:
+                    addShield(randomPosition(-fieldWidth/2, fieldWidth/2), sectionBegin + sectionLength/2, 0.0, 0.0, sectionBegin, sectionEnd, 0.0, randomSpeed());
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+        else
+        {
+            if (numNewPlatforms > 0)
+            {
+                JumpPlatform* itemPlatform = platformList[rand()%numNewPlatforms];
+
+                switch (itemType)
+                {
+                case ItemType::SPRING:
+                    addSpring(itemPlatform);
+                    break;
+                case ItemType::ROCKET:
+                    addRocket(itemPlatform);
+                    break;
+                case ItemType::PROPELLER:
+                    addPropeller(itemPlatform);
+                    break;
+                case ItemType::BOOTS:
+                    addBoots(itemPlatform);
+                    break;
+                case ItemType::SHIELD:
+                    addShield(itemPlatform);
+                    break;
+                default:
+                    break;
+                }
+            }
+        }
+
+        if (sectionNumber_ >= 5 && rand()%3 == 0)
+        {
+            switch(rand()%4)
+            {
+            case 0:
+                addEnemy(1, randomXPosition(), randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/3*2, fieldWidth/3*2, sectionBegin, sectionBegin + sectionLength, randomSpeed(), 0.0);
+                break;
+            case 1:
+                addEnemy(2, randomXPosition(), randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/3*2, fieldWidth/3*2, sectionBegin, sectionBegin + sectionLength, randomSpeed(), 0.0);
+                break;
+            case 2:
+                addEnemy(3, randomXPosition(), randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/3*2, fieldWidth/3*2, sectionBegin, sectionBegin + sectionLength, randomSpeed(), 0.0);
+                break;
+            case 3:
+                addEnemy(4, randomXPosition(), randomPosition(sectionBegin, sectionBegin + sectionLength), -fieldWidth/3*2, fieldWidth/3*2, sectionBegin, sectionBegin + sectionLength, randomSpeed(), 0.0);
+                break;
+            }
+        }
+        ++ sectionNumber_;
+    }
+
+    bool Jump::addAdventure(int number)
+    {
+        float fieldWidth = center_->getFieldDimension().x;
+        float sectionLength = center_->getSectionLength();
+        float sectionBegin = sectionNumber_ * sectionLength;
+        sectionLength *= 2;
+
+        switch(number)
+        {
+        case 0:
+        {
+            int numI = 10;
+            if (rand()%2 == 0)
+            {
+                for (int i = 0; i < numI; ++ i)
+                {
+                    addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth+platformWidth_/2, sectionBegin+i*sectionLength/numI);
+                }
+            }
+            else
+            {
+                for (int i = 0; i < numI; ++ i)
+                {
+                    addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth+platformWidth_/2, sectionBegin+(numI-i)*sectionLength/numI);
+                }
+            }
+            break;
+        }
+        case 1:
+        {
+            int numI = 7;
+
+            addPlatformStatic(0.0, sectionBegin);
+            if (rand()%2 == 0)
+            {
+                for (int i = 1; i < numI; ++ i)
+                {
+                    addPlatformStatic((fieldWidth-platformWidth_/2)*i/numI, sectionBegin+i*sectionLength/numI);
+                    addPlatformStatic(-(fieldWidth-platformWidth_/2)*i/numI, sectionBegin+i*sectionLength/numI);
+                }
+            }
+            else
+            {
+                for (int i = 1; i < numI; ++ i)
+                {
+                    addPlatformStatic((fieldWidth-platformWidth_/2)*i/numI, sectionBegin+(numI-i)*sectionLength/numI);
+                    addPlatformStatic(-(fieldWidth-platformWidth_/2)*i/numI, sectionBegin+(numI-i)*sectionLength/numI);
+                }
+            }
+            break;
+        }
+        case 2:
+        {
+            int numI = 5;
+            for (int i = 0; i <= numI; ++ i)
+            {
+                addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth, sectionBegin);
+                addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth, sectionBegin+sectionLength/5);
+                addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth, sectionBegin+sectionLength*2/5);
+                addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth, sectionBegin+sectionLength*3/5);
+                addPlatformStatic((2*fieldWidth-platformWidth_)*i/numI-fieldWidth, sectionBegin+sectionLength*4/5);
+                addEnemy(4, (2*fieldWidth-platformWidth_)*i/numI-fieldWidth+platformWidth_/2, sectionBegin+sectionLength/2, -fieldWidth, fieldWidth, sectionBegin, sectionBegin + sectionLength, 0.0, 0.0);
+            }
+            break;
+        }
+        case 3:
+        {
+            addRocket(addPlatformStatic(0.0, sectionBegin));
+            addEnemy(2, 0.0, sectionBegin+sectionLength/5, 0.0,0.0, 0.0, 0.0, 0.0, 0.0);
+            break;
+        }
+        case 4:
+        {
+            addPropeller(addPlatformStatic(0.0, sectionBegin));
+            addPropeller(addPlatformStatic(-fieldWidth/2, sectionBegin));
+            addPropeller(addPlatformStatic(fieldWidth/2, sectionBegin));
+            break;
+        }
+        default:
+            return false;
+        }
+        sectionNumber_ +=2;
+        return true;
+    }
+
+    float Jump::randomXPosition()
+    {
+        float fieldWidth = center_->getFieldDimension().x;
+
+        return (float)(rand()%(2*(int)fieldWidth)) - fieldWidth;
+    }
+
+    float Jump::randomXPosition(int totalColumns, int culomn)
+    {
+        float fieldWidth = center_->getFieldDimension().x;
+
+        float halfWidth = fieldWidth/totalColumns;
+        float leftBound = culomn*halfWidth*2-fieldWidth;
+        float rightBound = leftBound + 2*halfWidth;
+
+        return randomPosition(leftBound+platformWidth_/2, rightBound-platformWidth_/2);
+    }
+
+    float Jump::randomXPositionLeft(int totalColumns, int culomn)
+    {
+        float fieldWidth = center_->getFieldDimension().x;
+
+        float halfWidth = fieldWidth/totalColumns;
+        float leftBound = culomn*halfWidth*2-fieldWidth;
+        float rightBound = leftBound + 2*halfWidth/3;
+
+        return randomPosition(leftBound+platformWidth_/2, rightBound-platformWidth_/2);
+    }
+
+    float Jump::randomXPositionRight(int totalColumns, int culomn)
+    {
+        float fieldWidth = center_->getFieldDimension().x;
+
+        float halfWidth = fieldWidth/totalColumns;
+        float rightBound = (culomn+1)*halfWidth*2-fieldWidth;
+        float leftBound = rightBound - 2*halfWidth/3;
+        return randomPosition(leftBound+platformWidth_/2, rightBound-platformWidth_/2);
+    }
+
+    float Jump::randomZPosition(int totalRows, int row, float sectionBegin, float SectionEnd)
+    {
+        float fieldHeight = SectionEnd - sectionBegin;
+        float halfHeight = fieldHeight/totalRows;
+        float lowerBound = row*halfHeight*2+sectionBegin;
+        float upperBound = lowerBound + 2*halfHeight;
+
+        return randomPosition(lowerBound+platformHeight_/2, upperBound-platformHeight_/2);
+    }
+
+    float Jump::randomZPositionLower(int totalRows, int row, float sectionBegin, float SectionEnd)
+    {
+        float fieldHeight = SectionEnd - sectionBegin;
+        float rowHeight = fieldHeight/totalRows;
+        float lowerBound = row*rowHeight+sectionBegin;
+        float upperBound = lowerBound + rowHeight/3;
+
+        return randomPosition(lowerBound+platformHeight_/2, upperBound-platformHeight_/2);
+    }
+
+    float Jump::randomZPositionUpper(int totalRows, int row, float sectionBegin, float SectionEnd)
+    {
+        float fieldHeight = SectionEnd - sectionBegin;
+        float rowHeight = fieldHeight/totalRows;
+        float lowerBound = (row+1)*rowHeight+sectionBegin;
+        float upperBound = lowerBound - rowHeight/3;
+
+        return randomPosition(lowerBound+platformHeight_/2, upperBound-platformHeight_/2);
+    }
+
+    float Jump::randomPosition(float lowerBoundary, float upperBoundary)
+    {
+        if (lowerBoundary >= upperBoundary)
+        {
+            return (lowerBoundary + upperBoundary)/2;
+        }
+
+        return (float)(rand()%(int)(100*(upperBoundary - lowerBoundary)))/100 + lowerBoundary;
+    }
+
+    float Jump::randomSpeed()
+    {
+        float platformSpeed = center_->getPlatformSpeed();
+        return randomPosition(0.5f*platformSpeed, 1.5f*platformSpeed);
+    }
+
+    int Jump::getScore(PlayerInfo* player) const
+    {
+        return sectionNumber_ - 2;
+    }
+
+    float Jump::getFuel() const
+    {
+        if (this->figure_ != nullptr)
+        {
+            if (this->figure_->rocketActive_ != nullptr)
+            {
+                return this->figure_->rocketActive_->getFuelState();
+            }
+            else if (this->figure_->propellerActive_ != nullptr)
+            {
+                return this->figure_->propellerActive_->getFuelState();
+            }
+            else if (this->figure_->shieldActive_ != nullptr)
+            {
+                return this->figure_->shieldActive_->getFuelState();
+            }
+            else if (this->figure_->bootsActive_ != nullptr)
+            {
+                return this->figure_->bootsActive_->getFuelState();
+            }
+        }
+
+        return 0.0;
+    }
+
+    bool Jump::getDead(PlayerInfo* player) const
+    {
+        return figure_->dead_;
+    }
+
+    void Jump::setCenterpoint(JumpCenterpoint* center)
+    {
+        center_ = center;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/Jump.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/Jump.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/Jump.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Jump_H__
+#define _Jump_H__
+
+#include "jump/JumpPrereqs.h"
+#include "gametypes/Deathmatch.h"
+
+namespace orxonox
+{
+    class _JumpExport Jump : public Deathmatch
+    {
+        public:
+            Jump(Context* context);
+            virtual ~Jump();
+            virtual void tick(float dt) override;
+            virtual void start() override;
+            virtual void end() override;
+            virtual void spawnPlayer(PlayerInfo* player) override;
+            int getScore(PlayerInfo* player) const;
+            float getFuel() const;
+            bool getDead(PlayerInfo* player) const;
+            void setCenterpoint(JumpCenterpoint* center);
+            PlayerInfo* getPlayer() const;
+
+        protected:
+            void cleanup();
+            virtual void addPlatform(JumpPlatform* newPlatform, std::string platformTemplate, float xPosition, float zPosition);
+            virtual JumpPlatformStatic* addPlatformStatic(float xPosition, float zPosition);
+            virtual JumpPlatformHMove* addPlatformHMove(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float speed);
+            virtual JumpPlatformVMove* addPlatformVMove(float xPosition, float zPosition, float lowerBoundary, float upperBoundary, float speed);
+            virtual JumpPlatformDisappear* addPlatformDisappear(float xPosition, float zPosition);
+            virtual JumpPlatformTimer* addPlatformTimer(float xPosition, float zPosition, float time, float variance);
+            virtual JumpPlatformFake* addPlatformFake(float xPosition, float zPosition);
+            virtual void addProjectile(float xPosition, float zPosition);
+            virtual void addEnemy(int type, float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity);
+            virtual void addSpring(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity);
+            virtual void addSpring(JumpPlatform* platform);
+            virtual void addRocket(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity);
+            virtual void addRocket(JumpPlatform* platform);
+            virtual void addPropeller(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity);
+            virtual void addPropeller(JumpPlatform* platform);
+            virtual void addBoots(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity);
+            virtual void addBoots(JumpPlatform* platform);
+            virtual void addShield(float xPosition, float zPosition, float leftBoundary, float rightBoundary, float lowerBoundary, float upperBoundary, float xVelocity, float zVelocity);
+            virtual void addShield(JumpPlatform* platform);
+            virtual void addStartSection();
+            virtual void addSection();
+            virtual bool addAdventure(int number);
+            virtual float randomXPosition();
+            virtual float randomXPosition(int totalColumns, int culomn);
+            virtual float randomXPositionLeft(int totalColumns, int culomn);
+            virtual float randomXPositionRight(int totalColumns, int culomn);
+            virtual float randomZPosition(int totalRows, int row, float sectionBegin, float SectionEnd);
+            virtual float randomZPositionLower(int totalRows, int row, float sectionBegin, float SectionEnd);
+            virtual float randomZPositionUpper(int totalRows, int row, float sectionBegin, float SectionEnd);
+            virtual float randomPosition(float lowerBoundary, float upperBoundary);
+            virtual float randomSpeed();
+
+            WeakPtr<JumpCenterpoint> center_;
+            WeakPtr<JumpFigure> figure_;
+            WeakPtr<Camera> camera;
+            float totalScreenShift_;
+            float screenShiftSinceLastUpdate_;
+            int sectionNumber_;
+            int adventureNumber_;
+            float platformWidth_;
+            float platformHeight_;
+    };
+}
+
+#endif /* _Jump_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpBoots.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpBoots.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpBoots.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpBoots.cc
+    @brief These boots give the figure a speed bonus when it jumpes.
+*/
+
+#include "JumpBoots.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpBoots);
+
+    JumpBoots::JumpBoots(Context* context) : JumpItem(context)
+    {
+        RegisterObject(JumpBoots);
+
+        initialFuel_ = 3.0;
+        fuel_ = initialFuel_;
+        attachedToFigure_ = false;
+
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+        setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    }
+
+    JumpBoots::~JumpBoots()
+    {
+
+    }
+
+    void JumpBoots::tick(float dt)
+    {
+        SUPER(JumpBoots, tick, dt);
+
+        Vector3 rocketPosition = getWorldPosition();
+
+        if (attachedToFigure_ == false && figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getWorldPosition();
+
+            if(figurePosition.x > rocketPosition.x-width_ && figurePosition.x < rocketPosition.x+width_ && figurePosition.z > rocketPosition.z-height_ && figurePosition.z < rocketPosition.z+height_)
+            {
+                touchFigure();
+            }
+        }
+        else if (attachedToFigure_ == true)
+        {
+            fuel_ -= dt;
+            if (fuel_ < 0.0)
+            {
+                figure_->StopBoots(this);
+            }
+        }
+    }
+
+    void JumpBoots::touchFigure()
+    {
+        JumpItem::touchFigure();
+
+        attachedToFigure_ = figure_->StartBoots(this);
+    }
+
+    float JumpBoots::getFuelState()
+    {
+        return fuel_/initialFuel_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpBoots.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpBoots.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpBoots.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpBoots_H__
+#define _JumpBoots_H__
+
+#include "JumpPrereqs.h"
+#include "JumpItem.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpBoots : public JumpItem
+    {
+        public:
+            JumpBoots(Context* context);
+            virtual ~JumpBoots();
+            virtual void tick(float dt) override;
+            virtual void touchFigure() override;
+            virtual float getFuelState();
+        protected:
+            float stretch_;
+            float fuel_;
+            float initialFuel_;
+    };
+}
+
+#endif /* _JumpBoots_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpCenterpoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpCenterpoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpCenterpoint.cc	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpCenterpoint.cc
+    @brief The JumpCenterpoint is a StaticEntity which represents the level of the minigame. All platforms, enemies and items are attached to the JumpCenterpoint.
+*/
+
+#include "JumpCenterpoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "Jump.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpCenterpoint);
+
+    JumpCenterpoint::JumpCenterpoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(JumpCenterpoint);
+
+        width_ = 0.0;
+        height_ = 0.0;
+        sectionLength_ = 0.0;
+        platformSpeed_ = 0.0;
+
+        checkGametype();
+    }
+
+    void JumpCenterpoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpCenterpoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(JumpCenterpoint, "dimension", setFieldDimension, getFieldDimension, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "sectionLength", setSectionLength, getSectionLength, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformSpeed", setPlatformSpeed, getPlatformSpeed, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "cameraOffset", setCameraOffset, getCameraOffset, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformStaticTemplate", setPlatformStaticTemplate, getPlatformStaticTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformHMoveTemplate", setPlatformHMoveTemplate, getPlatformHMoveTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformVMoveTemplate", setPlatformVMoveTemplate, getPlatformVMoveTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformDisappearTemplate", setPlatformDisappearTemplate, getPlatformDisappearTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformTimerTemplate", setPlatformTimerTemplate, getPlatformTimerTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "platformFakeTemplate", setPlatformFakeTemplate, getPlatformFakeTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "figureTemplate", setFigureTemplate, getFigureTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "projectileTemplate", setProjectileTemplate, getProjectileTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "springTemplate", setSpringTemplate, getSpringTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "rocketTemplate", setRocketTemplate, getRocketTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "propellerTemplate", setPropellerTemplate, getPropellerTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "bootsTemplate", setBootsTemplate, getBootsTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "shieldTemplate", setShieldTemplate, getShieldTemplate, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "enemy1Template", setEnemy1Template, getEnemy1Template, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "enemy2Template", setEnemy2Template, getEnemy2Template, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "enemy3Template", setEnemy3Template, getEnemy3Template, xmlelement, mode);
+        XMLPortParam(JumpCenterpoint, "enemy4Template", setEnemy4Template, getEnemy4Template, xmlelement, mode);
+    }
+
+    void JumpCenterpoint::checkGametype()
+    {
+        if (getGametype() != nullptr && this->getGametype()->isA(Class(Jump)))
+        {
+            Jump* jumpGametype = orxonox_cast<Jump*>(this->getGametype());
+            jumpGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpCenterpoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpCenterpoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpCenterpoint.h	(revision 11817)
@@ -0,0 +1,159 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpCenterpoint_H__
+#define _JumpCenterpoint_H__
+
+#include "jump/JumpPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    
+    /**
+    @brief
+        @brief The JumpCenterpoint is a StaticEntity which represents the level of the minigame. All platforms, enemies and items are attached to the JumpCenterpoint.
+    */
+    class _JumpExport JumpCenterpoint : public StaticEntity
+    {
+        public:
+            JumpCenterpoint(Context* context); //!< Constructor. Registers and initializes the object and checks whether the gametype is actually Jump.
+            virtual ~JumpCenterpoint() {}
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method to create a JumpCenterpoint through XML.
+            void setPlatformStaticTemplate(const std::string& balltemplate)
+                { this->platformStaticTemplate_ = balltemplate; }
+            const std::string& getPlatformStaticTemplate() const
+                { return this->platformStaticTemplate_; }
+            void setPlatformHMoveTemplate(const std::string& balltemplate)
+                { this->platformHMoveTemplate_ = balltemplate; }
+            const std::string& getPlatformHMoveTemplate() const
+                { return this->platformHMoveTemplate_; }
+            void setPlatformVMoveTemplate(const std::string& balltemplate)
+                { this->platformVMoveTemplate_ = balltemplate; }
+            const std::string& getPlatformVMoveTemplate() const
+                { return this->platformVMoveTemplate_; }
+            void setPlatformDisappearTemplate(const std::string& balltemplate)
+                { this->platformDisappearTemplate_ = balltemplate; }
+            const std::string& getPlatformDisappearTemplate() const
+                { return this->platformDisappearTemplate_; }
+            void setPlatformTimerTemplate(const std::string& balltemplate)
+                { this->platformTimerTemplate_ = balltemplate; }
+            const std::string& getPlatformTimerTemplate() const
+                { return this->platformTimerTemplate_; }
+            void setPlatformFakeTemplate(const std::string& balltemplate)
+                { this->platformFakeTemplate_ = balltemplate; }
+            const std::string& getPlatformFakeTemplate() const
+                { return this->platformFakeTemplate_; }
+            void setProjectileTemplate(const std::string& newTemplate)
+                { this->projectileTemplate_ = newTemplate; }
+            const std::string& getProjectileTemplate() const
+                { return this->projectileTemplate_; }
+            void setSpringTemplate(const std::string& newTemplate)
+                { this->springTemplate_ = newTemplate; }
+            const std::string& getSpringTemplate() const
+                { return this->springTemplate_; }
+            void setRocketTemplate(const std::string& newTemplate)
+                { this->rocketTemplate_ = newTemplate; }
+            const std::string& getRocketTemplate() const
+                { return this->rocketTemplate_; }
+            void setPropellerTemplate(const std::string& newTemplate)
+                { this->propellerTemplate_ = newTemplate; }
+            const std::string& getPropellerTemplate() const
+                { return this->propellerTemplate_; }
+            void setBootsTemplate(const std::string& newTemplate)
+                { this->bootsTemplate_ = newTemplate; }
+            const std::string& getBootsTemplate() const
+                { return this->bootsTemplate_; }
+            void setShieldTemplate(const std::string& newTemplate)
+                { this->shieldTemplate_ = newTemplate; }
+            const std::string& getShieldTemplate() const
+                { return this->shieldTemplate_; }
+            void setFigureTemplate(const std::string& newTemplate)
+                { this->figureTemplate_ = newTemplate; }
+            const std::string& getFigureTemplate() const
+                { return this->figureTemplate_; }
+            void setEnemy1Template(const std::string& newTemplate)
+                { this->enemy1Template_ = newTemplate; }
+            const std::string& getEnemy1Template() const
+                { return this->enemy1Template_; }
+            void setEnemy2Template(const std::string& newTemplate)
+                { this->enemy2Template_ = newTemplate; }
+            const std::string& getEnemy2Template() const
+                { return this->enemy2Template_; }
+            void setEnemy3Template(const std::string& newTemplate)
+                { this->enemy3Template_ = newTemplate; }
+            const std::string& getEnemy3Template() const
+                { return this->enemy3Template_; }
+            void setEnemy4Template(const std::string& newTemplate)
+                { this->enemy4Template_ = newTemplate; }
+            const std::string& getEnemy4Template() const
+                { return this->enemy4Template_; }
+            void setFieldDimension(const Vector2& dimension)
+                { this->width_ = dimension.x; this->height_ = dimension.y; }
+            Vector2 getFieldDimension() const
+                { return Vector2(this->width_, this->height_); }
+            void setSectionLength(const float sectionLength)
+                { this->sectionLength_ = sectionLength; }
+            float getSectionLength() const
+                { return sectionLength_; }
+            void setPlatformSpeed(const float platformSpeed)
+                { this->platformSpeed_ = platformSpeed; }
+            float getPlatformSpeed() const
+                { return platformSpeed_; }
+            void setCameraOffset(const float cameraOffset)
+                { this->cameraOffset_ = cameraOffset; }
+            float getCameraOffset() const
+                { return cameraOffset_; }
+        private:
+            void checkGametype();
+            std::string platformStaticTemplate_;
+            std::string platformHMoveTemplate_;
+            std::string platformVMoveTemplate_;
+            std::string platformDisappearTemplate_;
+            std::string platformTimerTemplate_;
+            std::string platformFakeTemplate_;
+            std::string projectileTemplate_;
+            std::string springTemplate_;
+            std::string rocketTemplate_;
+            std::string propellerTemplate_;
+            std::string bootsTemplate_;
+            std::string shieldTemplate_;
+            std::string figureTemplate_;
+            std::string enemy1Template_;
+            std::string enemy2Template_;
+            std::string enemy3Template_;
+            std::string enemy4Template_;
+            float width_;
+            float height_;
+            float sectionLength_;
+            float platformSpeed_;
+            float cameraOffset_;
+    };
+}
+
+#endif /* _JumpCenterpoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpEnemy.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpEnemy.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpEnemy.cc	(revision 11817)
@@ -0,0 +1,153 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpEnemy.cc
+    @brief All enemies in the minigame inherit from this class. This class manages the movement of all enemies and allows enemies to touch the figure to kill it.
+*/
+
+#include "JumpEnemy.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpEnemy);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    JumpEnemy::JumpEnemy(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(JumpEnemy);
+
+        dead_ = false;
+        figure_ = nullptr;
+        width_ = 0.0;
+        height_ = 0.0;
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+        setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    JumpEnemy::~JumpEnemy()
+    {
+        /*if (this->isInitialized())
+        {
+            if (this->bDeleteBats_)
+                delete this->figure_;
+
+            delete[] this->batID_;
+        }*/
+    }
+
+    //xml port for loading sounds
+    void JumpEnemy::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpEnemy, XMLPort, xmlelement, mode);
+
+        XMLPortParam(JumpEnemy, "height", setHeight, getHeight, xmlelement, mode);
+        XMLPortParam(JumpEnemy, "width", setWidth, getWidth, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called every tick.
+        Handles the movement of the ball and its interaction with the boundaries and bats.
+    @param dt
+        The time since the last tick.
+    */
+    void JumpEnemy::tick(float dt)
+    {
+        SUPER(JumpEnemy, tick, dt);
+
+        // Get the current position, velocity and acceleration of the enemy.
+        Vector3 position = getPosition();
+        Vector3 velocity = getVelocity();
+
+        if ((position.x < leftBoundary_ && velocity.x < 0) || (position.x > rightBoundary_ && velocity.x > 0))
+        {
+            velocity.x = -velocity.x;
+        }
+
+        if ((position.z < lowerBoundary_ && velocity.z < 0) || (position.z > upperBoundary_ && velocity.z > 0))
+        {
+            velocity.z = -velocity.z;
+        }
+
+        // Set the position, velocity and acceleration of the enemy, if they have changed.
+        if (velocity != getVelocity())
+            setVelocity(velocity);
+        if (position != getPosition())
+            setPosition(position);
+
+
+        // Interact with Figure
+        Vector3 enemyPosition = getPosition();
+
+        if (figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getPosition();
+            if(figurePosition.x > enemyPosition.x-width_ && figurePosition.x < enemyPosition.x+width_ && figurePosition.z > enemyPosition.z-height_ && figurePosition.z < enemyPosition.z+height_)
+            {
+                touchFigure();
+            }
+        }
+    }
+
+    void JumpEnemy::setProperties(float newLeftBoundary, float newRightBoundary, float newLowerBoundary, float newUpperBoundary, float newHSpeed, float newVSpeed)
+    {
+        leftBoundary_ = newLeftBoundary;
+        rightBoundary_ = newRightBoundary;
+        lowerBoundary_ = newLowerBoundary;
+        upperBoundary_ = newUpperBoundary;
+
+        this->setVelocity(Vector3(newHSpeed,0,newVSpeed));
+    }
+
+    void JumpEnemy::setFigure(JumpFigure* newFigure)
+    {
+        figure_ = newFigure;
+    }
+
+    void JumpEnemy::touchFigure()
+    {
+        if (dead_ == false)
+        {
+            figure_->CollisionWithEnemy(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpEnemy.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpEnemy.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpEnemy.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpEnemy.h
+    @brief Declaration of the JumpEnemy class.
+    @ingroup Jump
+*/
+
+#ifndef _JumpEnemy_H__
+#define _JumpEnemy_H__
+
+#include "jump/JumpPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpEnemy : public MovableEntity
+    {
+        public:
+            JumpEnemy(Context* context);
+            virtual ~JumpEnemy();
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            void setFieldDimension(float width, float height)
+                { this->fieldWidth_ = width; this->fieldHeight_ = height; }
+            void setFieldDimension(const Vector2& dimension)
+                { this->setFieldDimension(dimension.x, dimension.y); }
+            Vector2 getFieldDimension() const
+                { return Vector2(this->fieldWidth_, this->fieldHeight_); }
+            void setWidth(const float width)
+                { this->width_ = width; }
+            float getWidth() const
+                { return width_; }
+            void setHeight(const float height)
+                { this->height_ = height; }
+            float getHeight() const
+                { return height_; }
+
+            virtual void setProperties(float newLeftBoundary, float newRightBoundary, float newLowerBoundary, float newUpperBoundary, float newHSpeed, float newVSpeed);
+            void setFigure(JumpFigure* newFigure);
+            virtual void touchFigure();
+            bool dead_;
+        protected:
+            float width_;
+            float height_;
+            float fieldWidth_;
+            float fieldHeight_;
+            float leftBoundary_;
+            float rightBoundary_;
+            float lowerBoundary_;
+            float upperBoundary_;
+            WeakPtr<JumpFigure> figure_;
+    };
+}
+
+#endif /* _JumpEnemy_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpFigure.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpFigure.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpFigure.cc	(revision 11817)
@@ -0,0 +1,409 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpFigure.cc
+    @brief This class represents your figure when you play the minigame. Here the movement of the figure, activating items, ... are handled.
+*/
+
+#include "JumpFigure.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/Model.h"
+#include "JumpRocket.h"
+#include "JumpPropeller.h"
+#include "JumpBoots.h"
+#include "JumpShield.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpFigure);
+
+    JumpFigure::JumpFigure(Context* context) : ControllableEntity(context)
+    {
+        RegisterObject(JumpFigure);
+
+        // initialize variables
+        leftHand_ = nullptr;
+        rightHand_ = nullptr;
+        fieldHeight_ = 0;
+        fieldWidth_ = 0;
+        jumpSpeed_ = 0.0;
+        handSpeed_ = 0.0;
+        handMaxAngle_ = 0.0;
+        handMinAngle_ = 0.0;
+        rocketPos_ = 0.0;
+        propellerPos_ = 0.0;
+        bootsPos_ = 0.0;
+        moveUpPressed_ = false;
+        moveDownPressed_ = false;
+        moveLeftPressed_ = false;
+        moveDownPressed_ = false;
+        firePressed_ = false;
+        fireSignal_ = false;
+        timeSinceLastFire_ = 0.0;
+        gravityAcceleration_ = 8.0;
+        mouseFactor_ = 75.0;
+        maxFireRate_ = 0.3;
+        handAngle_ = 0.0;
+        animateHands_ = false;
+        turnUp_ = false;
+        rocketActive_ = nullptr;
+        propellerActive_ = nullptr;
+        bootsActive_ = nullptr;
+        shieldActive_ = nullptr;
+        rocketSpeed_ = 0.0;
+        propellerSpeed_ = 0.0;
+        dead_ = false;
+    }
+
+    void JumpFigure::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpFigure, XMLPort, xmlelement, mode);
+        XMLPortParam(JumpFigure, "mouseFactor", setMouseFactor, getMouseFactor, xmlelement, mode);
+        XMLPortParam(JumpFigure, "modelLefthand", setModelLeftHand, getModelLeftHand, xmlelement, mode);
+        XMLPortParam(JumpFigure, "modelRighthand", setModelRightHand, getModelRightHand, xmlelement, mode);
+        XMLPortParam(JumpFigure, "rocketPos", setRocketPos, getRocketPos, xmlelement, mode);
+        XMLPortParam(JumpFigure, "propellerPos", setPropellerPos, getPropellerPos, xmlelement, mode);
+        XMLPortParam(JumpFigure, "bootsPos", setBootsPos, getBootsPos, xmlelement, mode);
+        XMLPortParam(JumpFigure, "jumpSpeed", setJumpSpeed, getJumpSpeed, xmlelement, mode);
+        XMLPortParam(JumpFigure, "rocketSpeed", setRocketSpeed, getRocketSpeed, xmlelement, mode);
+        XMLPortParam(JumpFigure, "propellerSpeed", setPropellerSpeed, getPropellerSpeed, xmlelement, mode);
+        XMLPortParam(JumpFigure, "handMinAngle", setHandMinAngle, getHandMinAngle, xmlelement, mode);
+        XMLPortParam(JumpFigure, "handMaxAngle", setHandMaxAngle, getHandMaxAngle, xmlelement, mode);
+        XMLPortParam(JumpFigure, "handSpeed", setHandSpeed, getHandSpeed, xmlelement, mode);
+    }
+
+    void JumpFigure::tick(float dt)
+    {
+        SUPER(JumpFigure, tick, dt);
+
+        if (hasLocalController())
+        {
+            timeSinceLastFire_ += dt;
+
+            // Move up/down
+            Vector3 velocity = getVelocity();
+            if (rocketActive_ != nullptr)
+            {
+                velocity.z = rocketSpeed_;
+            }
+            else if (propellerActive_ != nullptr)
+            {
+                velocity.z = propellerSpeed_;
+            }
+            else
+            {
+                velocity.z -= gravityAcceleration_;
+            }
+
+            // Animate Hands
+            if (animateHands_ == true)
+            {
+                if (turnUp_ == true)
+                {
+                    handAngle_ += handSpeed_ * dt;
+                }
+                else
+                {
+                    handAngle_ -= handSpeed_ * dt;
+                }
+                if (handAngle_ > handMaxAngle_)
+                {
+                    turnUp_ = false;
+                }
+                if (handAngle_ <= handMinAngle_)
+                {
+                    animateHands_ = false;
+                }
+
+                if (leftHand_ != nullptr)
+                {
+                    leftHand_->setOrientation(Vector3(0.0, 1.0, 0.0), Degree(-handAngle_));
+                }
+                if (rightHand_ != nullptr)
+                {
+                    rightHand_->setOrientation(Vector3(0.0, 1.0, 0.0), Degree(handAngle_));
+                }
+            }
+
+            // Move left/right
+            if (dead_ == false)
+            {
+                velocity.x = -mouseFactor_*horizontalSpeed_;
+            }
+            else
+            {
+                velocity.x = 0.0;
+            }
+
+            // Cheats
+            /*if (moveUpPressed_ == true)
+            {
+                velocity.z = 400.0f;
+                moveUpPressed_ = false;
+                dead_ = false;
+            }
+            if (moveDownPressed_ == true)
+            {
+                moveDownPressed_ = false;
+            }*/
+
+            setVelocity(velocity);
+
+
+            if (firePressed_ && timeSinceLastFire_ >= maxFireRate_)
+            {
+                firePressed_ = false;
+                timeSinceLastFire_ = 0.0;
+                fireSignal_ = true;
+            }
+        }
+
+        // Move through the left and right screen boundaries
+        Vector3 position = getPosition();
+        if (position.x < -fieldWidth_*1.1f)
+        {
+            position.x = fieldWidth_*1.1f;
+        }
+        else if (position.x > fieldWidth_*1.1f)
+        {
+            position.x = -fieldWidth_*1.1f;
+        }
+        setPosition(position);
+
+        // Reset key variables
+        moveUpPressed_ = false;
+        moveDownPressed_ = false;
+        moveLeftPressed_ = false;
+        moveDownPressed_ = false;
+        firePressed_ = false;
+    }
+
+    void JumpFigure::JumpFromPlatform(JumpPlatform* platform)
+    {
+        if (dead_ == false)
+        {
+            Vector3 velocity = getVelocity();
+            if (bootsActive_ == nullptr)
+            {
+                velocity.z = 1.2f*jumpSpeed_;
+            }
+            else
+            {
+                velocity.z = jumpSpeed_;
+            }
+            setVelocity(velocity);
+            animateHands_ = true;
+            handAngle_ = 0.0;
+            turnUp_ = true;
+        }
+    }
+
+    void JumpFigure::JumpFromSpring(JumpSpring* spring)
+    {
+        if (dead_ == false)
+        {
+            Vector3 velocity = getVelocity();
+            velocity.z = 1.2f*jumpSpeed_;
+            setVelocity(velocity);
+        }
+    }
+
+    void JumpFigure::CollisionWithEnemy(JumpEnemy* enemy)
+    {
+        if (rocketActive_ == nullptr && propellerActive_ == nullptr && shieldActive_ == nullptr)
+        {
+            dead_ = true;
+        }
+    }
+
+    bool JumpFigure::StartRocket(JumpRocket* rocket)
+    {
+        if (rocketActive_ == nullptr && propellerActive_ == nullptr && bootsActive_ == nullptr)
+        {
+            attach(rocket);
+            rocket->setPosition(0.0, rocketPos_, 0.0);
+            rocket->setVelocity(0.0, 0.0, 0.0);
+            rocketActive_ = rocket;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    void JumpFigure::StopRocket(JumpRocket* rocket)
+    {
+        rocket->setPosition(0.0, 0.0, -1000.0);
+        rocket->setVelocity(0.0, 0.0, 0.0);
+        detach(rocket);
+        rocket->destroy();
+        rocketActive_ = nullptr;
+    }
+
+    bool JumpFigure::StartPropeller(JumpPropeller* propeller)
+    {
+        if (rocketActive_ == nullptr && propellerActive_ == nullptr && bootsActive_ == nullptr)
+        {
+            attach(propeller);
+            propeller->setPosition(0.0, 0.0, propellerPos_);
+            propeller->setVelocity(0.0, 0.0, 0.0);
+            propellerActive_ = propeller;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    void JumpFigure::StopPropeller(JumpPropeller* propeller)
+    {
+        propeller->setPosition(0.0, 0.0, -1000.0);
+        propeller->setVelocity(0.0, 0.0, 0.0);
+        detach(propeller);
+        propeller->destroy();
+        propellerActive_ = nullptr;
+    }
+
+    bool JumpFigure::StartBoots(JumpBoots* boots)
+    {
+        if (rocketActive_ == nullptr && propellerActive_ == nullptr && bootsActive_ == nullptr)
+        {
+            attach(boots);
+            boots->setPosition(0.0, 0.0, bootsPos_);
+            boots->setVelocity(0.0, 0.0, 0.0);
+            bootsActive_ = boots;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    void JumpFigure::StopBoots(JumpBoots* boots)
+    {
+        boots->setPosition(0.0, 0.0, -1000.0);
+        boots->setVelocity(0.0, 0.0, 0.0);
+        detach(boots);
+        boots->destroy();
+        bootsActive_ = nullptr;
+    }
+
+    bool JumpFigure::StartShield(JumpShield* shield)
+    {
+        if (shieldActive_ == nullptr)
+        {
+            attach(shield);
+            shield->setPosition(0.0, 0.0, propellerPos_);
+            shield->setVelocity(0.0, 0.0, 0.0);
+            shieldActive_ = shield;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    void JumpFigure::StopShield(JumpShield* shield)
+    {
+        shield->setPosition(0.0, 0.0, -1000.0);
+        shield->setVelocity(0.0, 0.0, 0.0);
+        detach(shield);
+        shield->destroy();
+        shieldActive_ = nullptr;
+    }
+
+    void JumpFigure::InitializeAnimation(Context* context)
+    {
+        leftHand_ = new Model(context);
+        rightHand_ = new Model(context);
+
+        leftHand_->addTemplate(modelLeftHand_);
+        rightHand_->addTemplate(modelRightHand_);
+
+        attach(leftHand_);
+        attach(rightHand_);
+    }
+
+    void JumpFigure::moveFrontBack(const Vector2& value)
+    {
+        if (value.x > 0)
+        {
+            moveUpPressed_ = true;
+            moveDownPressed_ = false;
+        }
+        else
+        {
+            moveUpPressed_ = false;
+            moveDownPressed_ = true;
+        }
+    }
+
+    void JumpFigure::moveRightLeft(const Vector2& value)
+    {
+        if (value.x > 0)
+        {
+            moveLeftPressed_ = false;
+            moveRightPressed_ = true;
+        }
+        else
+        {
+            moveLeftPressed_ = true;
+            moveRightPressed_ = false;
+        }
+    }
+
+    void JumpFigure::rotateYaw(const Vector2& value)
+    {
+        horizontalSpeed_ = value.x;
+    }
+
+    void JumpFigure::rotatePitch(const Vector2& value)
+    {
+
+
+    }
+
+    void JumpFigure::rotateRoll(const Vector2& value)
+    {
+
+
+    }
+
+    void JumpFigure::fire(unsigned int firemode)
+    {
+
+    }
+
+    void JumpFigure::fired(unsigned int firemode)
+    {
+        firePressed_ = true;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpFigure.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpFigure.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpFigure.h	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpFigure_H__
+#define _JumpFigure_H__
+
+#include "jump/JumpPrereqs.h"
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpFigure : public ControllableEntity
+    {
+        public:
+            JumpFigure(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~JumpFigure() {}
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+            virtual void moveFrontBack(const Vector2& value) override; //!< Overloaded the function to steer the figure up and down.
+            virtual void moveRightLeft(const Vector2& value) override; //!< Overloaded the function to steer the figure up and down.
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+            void fire(unsigned int firemode);
+            virtual void fired(unsigned int firemode) override;
+            virtual void JumpFromPlatform(JumpPlatform* platform);
+            virtual void JumpFromSpring(JumpSpring* spring);
+            virtual void CollisionWithEnemy(JumpEnemy* enemy);
+            virtual bool StartRocket(JumpRocket* rocket);
+            virtual void StopRocket(JumpRocket* rocket);
+            virtual bool StartPropeller(JumpPropeller* propeller);
+            virtual void StopPropeller(JumpPropeller* propeller);
+            virtual bool StartBoots(JumpBoots* boots);
+            virtual void StopBoots(JumpBoots* boots);
+            virtual bool StartShield(JumpShield* shield);
+            virtual void StopShield(JumpShield* shield);
+            virtual void InitializeAnimation(Context* context);
+
+            void setFieldDimension(float width, float height)
+                { fieldWidth_ = width; fieldHeight_ = height; }
+            void setFieldDimension(const Vector2& dimension)
+                { setFieldDimension(dimension.x, dimension.y); }
+            Vector2 getFieldDimension() const
+                { return Vector2(fieldWidth_, fieldHeight_); }
+            void setMouseFactor(const float mouseFactor)
+                { mouseFactor_ = mouseFactor; }
+            const float getMouseFactor() const
+                { return mouseFactor_; }
+            void setModelLeftHand(const std::string& modelLeftHand)
+                { modelLeftHand_ = modelLeftHand; }
+            const std::string& getModelLeftHand() const
+                { return modelLeftHand_; }
+            void setModelRightHand(const std::string& modelRightHand)
+                { modelRightHand_ = modelRightHand; }
+            const std::string& getModelRightHand() const
+                { return modelRightHand_; }
+            void setRocketPos(const float rocketPos)
+                { rocketPos_ = rocketPos; }
+            const float getRocketPos() const
+                { return rocketPos_; }
+            void setPropellerPos(const float propellerPos)
+                { propellerPos_ = propellerPos; }
+            const float getPropellerPos() const
+                { return propellerPos_; }
+            void setBootsPos(const float bootsPos)
+                { bootsPos_ = bootsPos; }
+            const float getBootsPos() const
+                { return bootsPos_; }
+            void setJumpSpeed(const float jumpSpeed)
+                { jumpSpeed_ = jumpSpeed; }
+            const float getJumpSpeed() const
+                { return jumpSpeed_; }
+            void setRocketSpeed(const float rocketSpeed)
+                { rocketSpeed_ = rocketSpeed; }
+            const float getRocketSpeed() const
+                { return rocketSpeed_; }
+            void setPropellerSpeed(const float propellerSpeed)
+                { propellerSpeed_ = propellerSpeed; }
+            const float getPropellerSpeed() const
+                { return propellerSpeed_; }
+            void setHandMinAngle(const float handMinAngle)
+                { handMinAngle_ = handMinAngle; }
+            const float getHandMinAngle() const
+                { return handMinAngle_; }
+            void setHandMaxAngle(const float handMaxAngle)
+                { handMaxAngle_ = handMaxAngle; }
+            const float getHandMaxAngle() const
+                { return handMaxAngle_; }
+            void setHandSpeed(const float handSpeed)
+                { handSpeed_ = handSpeed; }
+            const float getHandSpeed() const
+                { return handSpeed_; }
+
+            bool fireSignal_;
+            bool dead_;
+
+            JumpRocket* rocketActive_;
+            JumpPropeller* propellerActive_;
+            JumpBoots* bootsActive_;
+            JumpShield* shieldActive_;
+        private:
+            std::string modelLeftHand_;
+            std::string modelRightHand_;
+            Model* leftHand_;
+            Model* rightHand_;
+            float fieldWidth_;
+            float fieldHeight_;
+            float timeSinceLastFire_;
+            bool moveUpPressed_;
+            bool moveDownPressed_;
+            bool moveLeftPressed_;
+            bool moveRightPressed_;
+            bool firePressed_;
+            float gravityAcceleration_;
+            float mouseFactor_;
+            float jumpSpeed_;
+            float handSpeed_;
+            float handMaxAngle_;
+            float handMinAngle_;
+            float rocketPos_;
+            float propellerPos_;
+            float bootsPos_;
+            float maxFireRate_;
+            float horizontalSpeed_;
+            float handAngle_;
+            bool animateHands_;
+            bool turnUp_;
+            float rocketSpeed_;
+            float propellerSpeed_;
+    };
+}
+
+#endif /* _JumpFigure_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpItem.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpItem.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpItem.cc	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpItem.cc
+    @brief All items in this minigame inherit from this class. Items can move around like platforms and enemies.
+*/
+
+#include "JumpItem.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpItem);
+
+    JumpItem::JumpItem(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(JumpItem);
+
+        attachedToFigure_ = false;
+
+        figure_ = nullptr;
+        height_ = 0.0;
+        width_ = 0.0;
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+    }
+
+    JumpItem::~JumpItem()
+    {
+
+    }
+
+    void JumpItem::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpItem, XMLPort, xmlelement, mode);
+
+        XMLPortParam(JumpItem, "height", setHeight, getHeight, xmlelement, mode);
+        XMLPortParam(JumpItem, "width", setWidth, getWidth, xmlelement, mode);
+    }
+
+    void JumpItem::tick(float dt)
+    {
+        SUPER(JumpItem, tick, dt);
+        // Get the current position, velocity and acceleration of the item.
+        Vector3 position = getWorldPosition();
+        Vector3 velocity = getVelocity();
+
+        if ((position.x < leftBoundary_ && velocity.x < 0) || (position.x > rightBoundary_ && velocity.x > 0))
+        {
+            velocity.x = -velocity.x;
+        }
+
+        if ((position.z < lowerBoundary_ && velocity.z < 0) || (position.z > upperBoundary_ && velocity.z > 0))
+        {
+            velocity.z = -velocity.z;
+        }
+
+        // Set the position, velocity and acceleration of the item, if they have changed.
+        if (velocity != getVelocity())
+        {
+            setVelocity(velocity);
+        }
+    }
+
+    void JumpItem::setProperties(float newLeftBoundary, float newRightBoundary, float newLowerBoundary, float newUpperBoundary, float newHSpeed, float newVSpeed)
+    {
+        leftBoundary_ = newLeftBoundary;
+        rightBoundary_ = newRightBoundary;
+        lowerBoundary_ = newLowerBoundary;
+        upperBoundary_ = newUpperBoundary;
+
+        setVelocity(Vector3(newHSpeed,0,newVSpeed));
+    }
+
+    void JumpItem::setFigure(JumpFigure* newFigure)
+    {
+        figure_ = newFigure;
+    }
+
+    void JumpItem::touchFigure()
+    {
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpItem.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpItem.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpItem.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpItem.h
+    @brief Declaration of the JumpItem class.
+    @ingroup Jump
+*/
+
+#ifndef _JumpItem_H__
+#define _JumpItem_H__
+
+#include "jump/JumpPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _JumpExport JumpItem : public MovableEntity
+    {
+        public:
+            JumpItem(Context* context);
+            virtual ~JumpItem();
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void setProperties(float newLeftBoundary, float newRightBoundary, float newLowerBoundary, float newUpperBoundary, float newHSpeed, float newVSpeed);
+            virtual void setFigure(JumpFigure* newFigure);
+            virtual void touchFigure();
+
+            void setFieldDimension(float width, float height)
+                { this->fieldWidth_ = width; this->fieldHeight_ = height; }
+            void setFieldDimension(const Vector2& dimension)
+                { this->setFieldDimension(dimension.x, dimension.y); }
+            Vector2 getFieldDimension() const
+                { return Vector2(this->fieldWidth_, this->fieldHeight_); }
+            void setWidth(const float width)
+                { this->width_ = width; }
+            float getWidth() const
+                { return width_; }
+            void setHeight(const float height)
+                { this->height_ = height; }
+            float getHeight() const
+                { return height_; }
+
+            bool attachedToFigure_;
+
+        protected:
+            float fieldWidth_;
+            float fieldHeight_;
+            WeakPtr<JumpFigure> figure_;
+            float height_;
+            float width_;
+            float leftBoundary_;
+            float rightBoundary_;
+            float lowerBoundary_;
+            float upperBoundary_;
+    };
+}
+
+#endif /* _JumpItem_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatform.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatform.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatform.cc	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatform.cc
+    @brief All platforms in this minigame inherit from this class. The basic functions of a platform (interact with figure) is implemented here. Special functions are implemented in the specialized classes.
+*/
+
+#include "JumpPlatform.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "sound/WorldSound.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatform);
+
+    JumpPlatform::JumpPlatform(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(JumpPlatform);
+
+        figure_ = nullptr;
+
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    JumpPlatform::~JumpPlatform()
+    {
+
+    }
+
+    //xml port for loading height and width of the platform
+    void JumpPlatform::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpPlatform, XMLPort, xmlelement, mode);
+
+        XMLPortParam(JumpPlatform, "height", setHeight, getHeight, xmlelement, mode);
+        XMLPortParam(JumpPlatform, "width", setWidth, getWidth, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called every tick.
+        Handles the movement of the ball and its interaction with the boundaries and bats.
+    @param dt
+        The time since the last tick.
+    */
+    void JumpPlatform::tick(float dt)
+    {
+        SUPER(JumpPlatform, tick, dt);
+
+        Vector3 platformPosition = this->getPosition();
+
+        if (figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getPosition();
+            Vector3 figureVelocity = figure_->getVelocity();
+
+            float tolerance = 3.0;
+
+            if(figureVelocity.z < 0 && figurePosition.x > platformPosition.x-width_/2 && figurePosition.x < platformPosition.x+width_/2 && figurePosition.z > platformPosition.z-height_/2*tolerance && figurePosition.z < platformPosition.z+height_/2)
+            {
+                touchFigure();
+            }
+        }
+    }
+
+    void JumpPlatform::setFigure(JumpFigure* newFigure)
+    {
+        figure_ = newFigure;
+    }
+
+    void JumpPlatform::touchFigure()
+    {
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatform.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatform.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatform.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatform.h
+    @brief Declaration of the JumpPlatform class.
+    @ingroup Jump
+*/
+
+#ifndef _JumpPlatform_H__
+#define _JumpPlatform_H__
+
+#include "JumpPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPlatform : public MovableEntity
+    {
+        public:
+            JumpPlatform(Context* context);
+            virtual ~JumpPlatform();
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            void setFigure(JumpFigure* newFigure);
+            virtual void touchFigure();
+
+            void setWidth(const float width)
+                { this->width_ = width; }
+            float getWidth() const
+                { return width_; }
+            void setHeight(const float height)
+                { this->height_ = height; }
+            float getHeight() const
+                { return height_; }
+
+        protected:
+            float width_;
+            float height_;
+            WeakPtr<JumpFigure> figure_;
+    };
+}
+
+#endif /* _JumpPlatform_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformDisappear.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformDisappear.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformDisappear.cc	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformDisappear.cc
+    @brief This platform disappears after contact with the figure.
+*/
+
+#include "JumpPlatformDisappear.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatformDisappear);
+
+    JumpPlatformDisappear::JumpPlatformDisappear(Context* context) : JumpPlatform(context)
+    {
+        RegisterObject(JumpPlatformDisappear);
+
+        setProperties(true);
+    }
+
+    JumpPlatformDisappear::~JumpPlatformDisappear()
+    {
+
+    }
+
+    void JumpPlatformDisappear::setProperties(bool active)
+    {
+        active_ = active;
+    }
+
+    bool JumpPlatformDisappear::isActive()
+    {
+        return active_;
+    }
+
+    void JumpPlatformDisappear::touchFigure()
+    {
+        if (isActive())
+        {
+            figure_->JumpFromPlatform(this);
+            active_ = false;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformDisappear.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformDisappear.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformDisappear.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformDisappear.h
+    @brief Declaration of the JumpPlatformDisappear class.
+    @ingroup Jump
+*/
+
+#ifndef _JumpPlatformDisappear_H__
+#define _JumpPlatformDisappear_H__
+
+#include "JumpPrereqs.h"
+#include "JumpPlatform.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPlatformDisappear : public JumpPlatform
+    {
+        public:
+            JumpPlatformDisappear(Context* context);
+            virtual ~JumpPlatformDisappear();
+            virtual void setProperties(bool active);
+            virtual bool isActive();
+            virtual void touchFigure() override;
+
+        protected:
+            bool active_;
+    };
+}
+
+#endif /* _JumpPlatformDisappear_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformFake.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformFake.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformFake.cc	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformFake.cc
+    @brief This platform has a hole in it. You cannot jump from this platform. It has no touchFigure function.
+*/
+
+#include "JumpPlatformFake.h"
+
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatformFake);
+
+    JumpPlatformFake::JumpPlatformFake(Context* context) : JumpPlatform(context)
+    {
+        RegisterObject(JumpPlatformFake);
+    }
+
+    JumpPlatformFake::~JumpPlatformFake()
+    {
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformFake.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformFake.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformFake.h	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformFake.h
+    @brief Declaration of the JumpPlatform class.
+    @ingroup Jump
+*/
+
+#ifndef _JumpPlatformFake_H__
+#define _JumpPlatformFake_H__
+
+#include "JumpPrereqs.h"
+#include "JumpPlatform.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPlatformFake : public JumpPlatform
+    {
+        public:
+            JumpPlatformFake(Context* context);
+            virtual ~JumpPlatformFake();
+    };
+}
+
+#endif /* _JumpPlatformFake_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformHMove.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformHMove.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformHMove.cc	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformHMove.cc
+    @brief This platform can move horizontally.
+*/
+
+#include "JumpPlatformHMove.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatformHMove);
+
+    JumpPlatformHMove::JumpPlatformHMove(Context* context) : JumpPlatform(context)
+    {
+        RegisterObject(JumpPlatformHMove);
+
+        setProperties(-100,100,5);
+    }
+
+    JumpPlatformHMove::~JumpPlatformHMove()
+    {
+
+    }
+
+    void JumpPlatformHMove::tick(float dt)
+    {
+        SUPER(JumpPlatformHMove, tick, dt);
+
+        // Get the current position, velocity and acceleration of the ball.
+        Vector3 position = getPosition();
+        Vector3 velocity = getVelocity();
+
+        if ((position.x < leftBoundary_ && velocity.x < 0) || (position.x > rightBoundary_ && velocity.x > 0))
+
+        {
+            velocity.x = -velocity.x;
+        }
+
+        // Set the position, velocity and acceleration of the ball, if they have changed.
+        if (velocity != getVelocity())
+        {
+            setVelocity(velocity);
+        }
+        if (position != this->getPosition())
+        {
+            setPosition(position);
+        }
+    }
+
+    void JumpPlatformHMove::setProperties(float leftBoundary, float rightBoundary, float speed)
+    {
+        leftBoundary_ = leftBoundary;
+        rightBoundary_ = rightBoundary;
+        setVelocity(Vector3(speed,0,0));
+    }
+
+    void JumpPlatformHMove::touchFigure()
+    {
+        figure_->JumpFromPlatform(this);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformHMove.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformHMove.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformHMove.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpPlatformHMove_H__
+#define _JumpPlatformHMove_H__
+
+#include "JumpPrereqs.h"
+#include "JumpPlatform.h"
+
+namespace orxonox
+{
+
+    class _JumpExport JumpPlatformHMove : public JumpPlatform
+    {
+        public:
+            JumpPlatformHMove(Context* context);
+            virtual ~JumpPlatformHMove();
+            virtual void tick(float dt) override;
+            virtual void setProperties(float leftBoundary, float rightBoundary, float speed);
+            virtual void touchFigure() override;
+
+        protected:
+            float leftBoundary_;
+            float rightBoundary_;
+    };
+}
+
+#endif /* _JumpPlatform_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformStatic.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformStatic.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformStatic.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformStatic.cc
+    @brief This is the most simple platform in this minigame.
+*/
+
+#include "JumpPlatformStatic.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatformStatic);
+
+    JumpPlatformStatic::JumpPlatformStatic(Context* context) : JumpPlatform(context)
+    {
+        RegisterObject(JumpPlatformStatic);
+
+    }
+
+    JumpPlatformStatic::~JumpPlatformStatic()
+    {
+
+    }
+
+    void JumpPlatformStatic::touchFigure()
+    {
+        figure_->JumpFromPlatform(this);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformStatic.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformStatic.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformStatic.h	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpPlatformStatic_H__
+#define _JumpPlatformStatic_H__
+
+#include "JumpPrereqs.h"
+#include "JumpPlatform.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPlatformStatic : public JumpPlatform
+    {
+        public:
+            JumpPlatformStatic(Context* context);
+            virtual ~JumpPlatformStatic();
+
+            virtual void touchFigure() override;
+    };
+}
+
+#endif /* _JumpPlatform_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformTimer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformTimer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformTimer.cc	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformTimer.cc
+    @brief This platform will explode if you wait for too long time.
+*/
+
+#include "JumpPlatformTimer.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/ParticleSpawner.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatformTimer);
+
+    JumpPlatformTimer::JumpPlatformTimer(Context* context) : JumpPlatform(context)
+    {
+        RegisterObject(JumpPlatformTimer);
+
+        particleSpawner_ = nullptr;
+
+        setProperties(3.0);
+
+    }
+
+    JumpPlatformTimer::~JumpPlatformTimer()
+    {
+
+    }
+
+    void JumpPlatformTimer::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpPlatformTimer, XMLPort, xmlelement, mode);
+
+        XMLPortParam(JumpPlatformTimer, "effectPath", setEffectPath, getEffectPath, xmlelement, mode);
+        XMLPortParam(JumpPlatformTimer, "effectStartTime", setEffectStartTime, getEffectStartTime, xmlelement, mode);
+    }
+
+    void JumpPlatformTimer::tick(float dt)
+    {
+        SUPER(JumpPlatformTimer, tick, dt);
+
+        time_ -= dt;
+        if (time_ < effectStartTime_ && particleSpawner_ == nullptr)
+        {
+
+            particleSpawner_ = new ParticleSpawner(getContext());
+            particleSpawner_->setSource(effectPath_);
+            particleSpawner_->setLoop(false);
+            particleSpawner_->setLOD(LODParticle::Low);
+            particleSpawner_->setLifetime(effectStartTime_);
+
+            attach(particleSpawner_);
+        }
+    }
+
+    void JumpPlatformTimer::setProperties(float time)
+    {
+        time_ = time;
+    }
+
+    bool JumpPlatformTimer::isActive(void)
+    {
+        return time_ > 0.0;
+    }
+
+    void JumpPlatformTimer::touchFigure()
+    {
+        if (isActive())
+        {
+            figure_->JumpFromPlatform(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformTimer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformTimer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformTimer.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformTimer.h
+    @brief Declaration of the JumpPlatformTimer class.
+    @ingroup Jump
+*/
+
+#ifndef _JumpPlatformTimer_H__
+#define _JumpPlatformTimer_H__
+
+#include "JumpPrereqs.h"
+#include "JumpPlatform.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPlatformTimer : public JumpPlatform
+    {
+        public:
+            JumpPlatformTimer(Context* context);
+            virtual ~JumpPlatformTimer();
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void setProperties(float time);
+            virtual bool isActive(void);
+            virtual void touchFigure() override;
+
+            void setEffectPath(const std::string& effectPath)
+                { this->effectPath_ = effectPath; }
+
+            const std::string& getEffectPath() const
+                { return this->effectPath_; }
+
+            void setEffectStartTime(const float effectStartTime)
+                { this->effectStartTime_ = effectStartTime; }
+
+            const float getEffectStartTime() const
+                { return this->effectStartTime_; }
+
+        protected:
+            float time_;
+            ParticleSpawner* particleSpawner_;
+            std::string effectPath_;
+            float effectStartTime_;
+    };
+}
+
+#endif /* _JumpPlatformTimer_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformVMove.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformVMove.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformVMove.cc	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPlatformVMove.cc
+    @brief This platform can move vertically.
+*/
+
+#include "JumpPlatformVMove.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPlatformVMove);
+
+    JumpPlatformVMove::JumpPlatformVMove(Context* context) : JumpPlatform(context)
+    {
+        RegisterObject(JumpPlatformVMove);
+
+        setProperties(0,80,10);
+    }
+
+    JumpPlatformVMove::~JumpPlatformVMove()
+    {
+
+    }
+
+    void JumpPlatformVMove::tick(float dt)
+    {
+        SUPER(JumpPlatformVMove, tick, dt);
+
+        // Get the current position, velocity and acceleration of the ball.
+        Vector3 position = getPosition();
+        Vector3 velocity = getVelocity();
+
+        if ((position.z < lowerBoundary_ && velocity.z < 0) || (position.z > upperBoundary_ && velocity.z > 0))
+        {
+            velocity.z = -velocity.z;
+        }
+
+        // Set the position, velocity and acceleration of the ball, if they have changed.
+        if (velocity != getVelocity())
+        {
+            setVelocity(velocity);
+        }
+        if (position != getPosition())
+        {
+            setPosition(position);
+        }
+    }
+
+    void JumpPlatformVMove::setProperties(float lowerBoundary, float upperBoundary, float speed)
+    {
+        lowerBoundary_ = lowerBoundary;
+        upperBoundary_ = upperBoundary;
+
+        setVelocity(Vector3(0,0,speed));
+
+    }
+
+    void JumpPlatformVMove::touchFigure()
+    {
+        figure_->JumpFromPlatform(this);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformVMove.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformVMove.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPlatformVMove.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpPlatformVMove_H__
+#define _JumpPlatformVMove_H__
+
+#include "JumpPrereqs.h"
+#include "JumpPlatform.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPlatformVMove : public JumpPlatform
+    {
+        public:
+            JumpPlatformVMove(Context* context);
+            virtual ~JumpPlatformVMove();
+            virtual void tick(float dt) override;
+            virtual void setProperties(float leftBoundary, float rightBoundary, float speed);
+            virtual void touchFigure() override;
+
+        protected:
+            float lowerBoundary_;
+            float upperBoundary_;
+    };
+}
+
+#endif /* _JumpPlatform_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPrereqs.h	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the jump module
+*/
+
+#ifndef _JumpPrereqs_H__
+#define _JumpPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(JUMP_STATIC_BUILD)
+#  ifdef JUMP_SHARED_BUILD
+#    define _JumpExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _JumpExport
+#    else
+#      define _JumpExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _JumpPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _JumpExport  __attribute__ ((visibility("default")))
+#  define _JumpPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _JumpExport
+#  define _JumpPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Jump;
+    class JumpPlatform;
+    class JumpPlatformStatic;
+    class JumpPlatformHMove;
+    class JumpPlatformVMove;
+    class JumpPlatformDisappear;
+    class JumpPlatformTimer;
+    class JumpPlatformFake;
+    class JumpProjectile;
+    class JumpEnemy;
+    class JumpItem;
+    class JumpSpring;
+    class JumpRocket;
+    class JumpPropeller;
+    class JumpBoots;
+    class JumpShield;
+    class JumpFigure;
+    class JumpCenterpoint;
+    class JumpScore;
+}
+
+#endif /* _JumpPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpProjectile.cc	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpProjectile.cc
+    @brief projectiles are created by the gametype if the figure shoots. All projectiles check every tick, whether they hit an enemy.
+*/
+
+#include "JumpProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+#include "JumpEnemy.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpProjectile);
+
+    JumpProjectile::JumpProjectile(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(JumpProjectile);
+
+        figure_ = nullptr;
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,250.0));
+        setAcceleration(Vector3(0,0,0));
+    }
+
+    JumpProjectile::~JumpProjectile()
+    {
+
+    }
+
+    void JumpProjectile::tick(float dt)
+    {
+        SUPER(JumpProjectile, tick, dt);
+
+        Vector3 projectilePosition = getPosition();
+
+        for (JumpEnemy* enemy : ObjectList<JumpEnemy>())
+        {
+            Vector3 enemyPosition = enemy->getPosition();
+            float enemyWidth = enemy->getWidth();
+            float enemyHeight = enemy->getHeight();
+
+            if(projectilePosition.x > enemyPosition.x-enemyWidth && projectilePosition.x < enemyPosition.x+enemyWidth && projectilePosition.z > enemyPosition.z-enemyHeight && projectilePosition.z < enemyPosition.z+enemyHeight)
+            {
+                enemy->dead_ = true;
+            }
+        }
+    }
+
+    void JumpProjectile::setFigure(JumpFigure* figure)
+    {
+        figure_ = figure;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpProjectile.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpProjectile_H__
+#define _JumpProjectile_H__
+
+#include "jump/JumpPrereqs.h"
+#include "util/Math.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _JumpExport JumpProjectile : public MovableEntity
+    {
+        public:
+            JumpProjectile(Context* context);
+            virtual ~JumpProjectile();
+
+            virtual void tick(float dt) override;
+
+            void setFieldDimension(float width, float height)
+                { this->fieldWidth_ = width; this->fieldHeight_ = height; }
+
+            void setFieldDimension(const Vector2& dimension)
+                { this->setFieldDimension(dimension.x, dimension.y); }
+
+            Vector2 getFieldDimension() const
+                { return Vector2(this->fieldWidth_, this->fieldHeight_); }
+
+            void setFigure(JumpFigure* figure);
+
+        protected:
+            float fieldWidth_;
+            float fieldHeight_;
+            WeakPtr<JumpFigure> figure_;
+    };
+}
+
+#endif /* _JumpProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPropeller.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPropeller.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPropeller.cc	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpPropeller.cc
+    @brief If this propeller is created, attachedToFigure_ is set to false. When the figure picks it up, the variable is set to true and the figure starts flying until the fuel is reduced to zero.
+*/
+
+#include "JumpPropeller.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpPropeller);
+
+    JumpPropeller::JumpPropeller(Context* context) : JumpItem(context)
+    {
+        RegisterObject(JumpPropeller);
+
+        initialFuel_ = 3.0;
+        fuel_ = initialFuel_;
+        attachedToFigure_ = false;
+
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+        setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    }
+
+    JumpPropeller::~JumpPropeller()
+    {
+
+    }
+
+    void JumpPropeller::tick(float dt)
+    {
+        SUPER(JumpPropeller, tick, dt);
+
+        Vector3 PropellerPosition = getWorldPosition();
+
+        if (attachedToFigure_ == false && figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getWorldPosition();
+
+            if(figurePosition.x > PropellerPosition.x-width_ && figurePosition.x < PropellerPosition.x+width_ && figurePosition.z > PropellerPosition.z-height_ && figurePosition.z < PropellerPosition.z+height_)
+            {
+                touchFigure();
+            }
+        }
+        else if (attachedToFigure_ == true)
+        {
+            fuel_ -= dt;
+            if (fuel_ < 0.0)
+            {
+                figure_->StopPropeller(this);
+            }
+        }
+    }
+
+    void JumpPropeller::touchFigure()
+    {
+        JumpItem::touchFigure();
+
+        attachedToFigure_ = figure_->StartPropeller(this);
+        if (attachedToFigure_)
+        {
+            setAngularVelocity(Vector3(0,0,10.0));
+        }
+    }
+
+    float JumpPropeller::getFuelState()
+    {
+        return fuel_/initialFuel_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpPropeller.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpPropeller.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpPropeller.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpPropeller_H__
+#define _JumpPropeller_H__
+
+#include "JumpPrereqs.h"
+#include "JumpItem.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpPropeller : public JumpItem
+    {
+        public:
+            JumpPropeller(Context* context);
+            virtual ~JumpPropeller();
+            virtual void tick(float dt) override;
+            virtual void touchFigure() override;
+            virtual float getFuelState();
+        protected:
+            float stretch_;
+            float fuel_;
+            float initialFuel_;
+    };
+}
+
+#endif /* _JumpPropeller_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpRocket.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpRocket.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpRocket.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpRocket.cc
+    @brief If this rocket is created, attachedToFigure_ is set to false. When the figure picks it up, the variable is set to true and the figure starts flying fast until the fuel is reduced to zero.
+*/
+
+#include "JumpRocket.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpRocket);
+
+    JumpRocket::JumpRocket(Context* context) : JumpItem(context)
+    {
+        RegisterObject(JumpRocket);
+
+        initialFuel_ = 3.0;
+        fuel_ = initialFuel_;
+        attachedToFigure_ = false;
+
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+        setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    }
+
+    JumpRocket::~JumpRocket()
+    {
+
+    }
+
+    void JumpRocket::tick(float dt)
+    {
+        SUPER(JumpRocket, tick, dt);
+
+        Vector3 rocketPosition = getWorldPosition();
+
+        if (attachedToFigure_ == false && figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getWorldPosition();
+
+            if(figurePosition.x > rocketPosition.x-width_ && figurePosition.x < rocketPosition.x+width_ && figurePosition.z > rocketPosition.z-height_ && figurePosition.z < rocketPosition.z+height_)
+            {
+                touchFigure();
+            }
+        }
+        else if (attachedToFigure_ == true)
+        {
+            fuel_ -= dt;
+            if (fuel_ < 0.0)
+            {
+                figure_->StopRocket(this);
+            }
+        }
+    }
+
+    void JumpRocket::touchFigure()
+    {
+        JumpItem::touchFigure();
+
+        attachedToFigure_ = figure_->StartRocket(this);
+    }
+
+    float JumpRocket::getFuelState()
+    {
+        return fuel_/initialFuel_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpRocket.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpRocket.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpRocket.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpRocket_H__
+#define _JumpRocket_H__
+
+#include "JumpPrereqs.h"
+#include "JumpItem.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpRocket : public JumpItem
+    {
+        public:
+            JumpRocket(Context* context);
+            virtual ~JumpRocket();
+            virtual void tick(float dt) override;
+            virtual void touchFigure() override;
+            virtual float getFuelState();
+        protected:
+            float stretch_;
+            float fuel_;
+            float initialFuel_;
+    };
+}
+
+#endif /* _JumpRocket_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpScore.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpScore.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpScore.cc	(revision 11817)
@@ -0,0 +1,127 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpScore.cc
+    @brief HUD of thejump minigame. If showScore_ is set, it displays the score. If showMessages_ is set, it displays the game over message.
+*/
+
+#include "JumpScore.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "infos/PlayerInfo.h"
+#include "Jump.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpScore);
+
+    JumpScore::JumpScore(Context* context) : OverlayText(context)
+    {
+        RegisterObject(JumpScore);
+
+        owner_ = nullptr;
+        showScore_ = false;
+        showFuel_ = false;
+        showMessages_ = false;
+    }
+
+    JumpScore::~JumpScore()
+    {
+
+    }
+
+    void JumpScore::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(JumpScore, XMLPort, xmlelement, mode);
+
+        XMLPortParam(JumpScore, "showScore", setShowScore, getShowScore, xmlelement, mode);
+        XMLPortParam(JumpScore, "showFuel", setShowFuel, getShowFuel, xmlelement, mode);
+        XMLPortParam(JumpScore, "showMessages", setShowMessages, getShowMessages, xmlelement, mode);
+        XMLPortParam(JumpScore, "gameOverText", setGameOverText, getGameOverText, xmlelement, mode);
+    }
+
+    void JumpScore::tick(float dt)
+    {
+        SUPER(JumpScore, tick, dt);
+
+        if (owner_ != nullptr)
+        {
+            if (!owner_->hasEnded())
+            {
+                player_ = owner_->getPlayer();
+
+                if (player_ != nullptr)
+                {
+                    if (showScore_ == true)
+                    {
+                        int score = owner_->getScore(player_);
+
+                        std::string str = multi_cast<std::string>(score);
+                        setCaption(str);
+                    }
+                    else if (showFuel_ == true)
+                    {
+                        float fuel = owner_->getFuel();
+                        std::string str;
+
+                        if (fuel <= 0.0)
+                        {
+                            str = "";
+                        }
+                        else
+                        {
+                            str = multi_cast<std::string>(fuel);
+                        }
+                        setCaption(str);
+                    }
+                    else if (showMessages_ == true)
+                    {
+                        setCaption(owner_->getDead(player_) == true ? gameOverText_ : "");
+                    }
+                }
+            }
+        }
+    }
+
+    void JumpScore::changedOwner()
+    {
+        SUPER(JumpScore, changedOwner);
+
+        if (this->getOwner() != nullptr && this->getOwner()->getGametype())
+        {
+            this->owner_ = orxonox_cast<Jump*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->owner_ = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpScore.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpScore.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpScore.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpScore_H__
+#define _JumpScore_H__
+
+#include "jump/JumpPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpScore : public OverlayText, public Tickable
+    {
+        public:
+            JumpScore(Context* context);
+            virtual ~JumpScore();
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            void setShowScore(const bool showScore)
+                { showScore_ = showScore; }
+
+            const bool getShowScore() const
+                { return showScore_; }
+
+            void setShowFuel(const bool showFuel)
+                { showFuel_ = showFuel; }
+
+            const bool getShowFuel() const
+                { return showFuel_; }
+
+            void setShowMessages(const bool showMessages)
+                { showMessages_ = showMessages; }
+
+            const bool getShowMessages() const
+                { return showMessages_; }
+
+            void setGameOverText(const std::string& gameOverText)
+                { this->gameOverText_ = gameOverText; }
+
+            const std::string& getGameOverText() const
+                { return this->gameOverText_; }
+
+        private:
+            Jump* owner_;
+            WeakPtr<PlayerInfo> player_;
+            WorldSound* scoreSound_;
+            bool showScore_;
+            bool showFuel_;
+            bool showMessages_;
+            std::string gameOverText_;
+    };
+}
+#endif /* _JumpScore_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpShield.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpShield.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpShield.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpShield.cc
+    @brief If this shield is created, attachedToFigure_ is set to false. When the figure picks it up, the variable is set to true and the figure is protected until the fuel is reduced to zero.
+*/
+
+#include "JumpShield.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpShield);
+
+    JumpShield::JumpShield(Context* context) : JumpItem(context)
+    {
+        RegisterObject(JumpShield);
+
+        initialFuel_ = 7.0;
+        fuel_ = initialFuel_;
+        attachedToFigure_ = false;
+
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+        setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    }
+
+    JumpShield::~JumpShield()
+    {
+
+    }
+
+    void JumpShield::tick(float dt)
+    {
+        SUPER(JumpShield, tick, dt);
+
+        Vector3 shieldPosition = getWorldPosition();
+
+        if (attachedToFigure_ == false && figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getWorldPosition();
+
+            if(figurePosition.x > shieldPosition.x-width_ && figurePosition.x < shieldPosition.x+width_ && figurePosition.z > shieldPosition.z-height_ && figurePosition.z < shieldPosition.z+height_)
+            {
+                touchFigure();
+            }
+        }
+        else if (attachedToFigure_ == true)
+        {
+            fuel_ -= dt;
+            if (fuel_ < 0.0)
+            {
+                figure_->StopShield(this);
+            }
+        }
+    }
+
+    void JumpShield::touchFigure()
+    {
+        JumpItem::touchFigure();
+
+        attachedToFigure_ = figure_->StartShield(this);
+    }
+
+    float JumpShield::getFuelState()
+    {
+        return fuel_/initialFuel_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpShield.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpShield.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpShield.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpShield_H__
+#define _JumpShield_H__
+
+#include "JumpPrereqs.h"
+#include "JumpItem.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpShield : public JumpItem
+    {
+        public:
+            JumpShield(Context* context);
+            virtual ~JumpShield();
+            virtual void tick(float dt) override;
+            virtual void touchFigure() override;
+            virtual float getFuelState();
+        protected:
+            float stretch_;
+            float fuel_;
+            float initialFuel_;
+    };
+}
+
+#endif /* _JumpShield_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpSpring.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpSpring.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpSpring.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file JumpSpring.cc
+    @brief If this spring is touched by the figure, it jumps higher then from a platform.
+*/
+
+#include "JumpSpring.h"
+
+#include "core/CoreIncludes.h"
+#include "JumpFigure.h"
+
+namespace orxonox
+{
+    RegisterClass(JumpSpring);
+
+    JumpSpring::JumpSpring(Context* context) : JumpItem(context)
+    {
+        RegisterObject(JumpSpring);
+
+        stretch_ = 1.0;
+
+        setPosition(Vector3(0,0,0));
+        setVelocity(Vector3(0,0,0));
+        setAcceleration(Vector3(0,0,0));
+
+        setProperties(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+    }
+
+    JumpSpring::~JumpSpring()
+    {
+
+    }
+
+    void JumpSpring::tick(float dt)
+    {
+        SUPER(JumpSpring, tick, dt);
+
+        if (stretch_ > 1.0)
+        {
+            stretch_ -= dt;
+            setScale3D(1.0, 1.0, stretch_);
+        }
+
+        Vector3 springPosition = getWorldPosition();
+
+        if (figure_ != nullptr)
+        {
+            Vector3 figurePosition = figure_->getWorldPosition();
+            Vector3 figureVelocity = figure_->getVelocity();
+
+            if(figureVelocity.z < 0 && figurePosition.x > springPosition.x-width_ && figurePosition.x < springPosition.x+width_ && figurePosition.z > springPosition.z-height_ && figurePosition.z < springPosition.z+height_)
+            {
+                touchFigure();
+            }
+        }
+    }
+
+    void JumpSpring::touchFigure()
+    {
+        JumpItem::touchFigure();
+
+        stretch_ = 3.0;
+
+        accelerateFigure();
+    }
+
+    void JumpSpring::accelerateFigure()
+    {
+        if (figure_ != nullptr)
+        {
+            figure_->JumpFromSpring(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/jump/JumpSpring.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/jump/JumpSpring.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/jump/JumpSpring.h	(revision 11817)
@@ -0,0 +1,50 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _JumpSpring_H__
+#define _JumpSpring_H__
+
+#include "JumpPrereqs.h"
+#include "JumpItem.h"
+
+namespace orxonox
+{
+    class _JumpExport JumpSpring : public JumpItem
+    {
+        public:
+            JumpSpring(Context* context);
+            virtual ~JumpSpring();
+            virtual void tick(float dt) override;
+            virtual void accelerateFigure();
+            virtual void touchFigure() override;
+        protected:
+            float stretch_;
+    };
+}
+
+#endif /* _JumpSpring_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,13 @@
+SET_SOURCE_FILES(Mini4Dgame_SRC_FILES
+  Mini4Dgame.cc
+  #Mini4DgameAI.cc
+  Mini4DgameBoard.cc
+)
+
+ORXONOX_ADD_LIBRARY(mini4dgame
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${Mini4Dgame_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4Dgame.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4Dgame.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4Dgame.cc	(revision 11817)
@@ -0,0 +1,201 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      Johannes Ritz
+ *
+ *
+ *
+ *
+ *TASK c) end the game in a nicer way
+ *TASK d) save the highscore
+ *TASK e) eye candy
+ */
+
+/**
+    @file Tetris.cc
+    @brief Implementation of the Mini4Dgame class.
+*/
+
+#include "Mini4Dgame.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "infos/PlayerInfo.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "gamestates/GSLevel.h"
+#include "chat/ChatManager.h"
+
+namespace orxonox
+{
+
+    SetConsoleCommand("Mini4Dgame", "setStone", &Mini4Dgame::setStone).addShortcut();
+    SetConsoleCommand("Mini4Dgame", "undoStone", &Mini4Dgame::undoStone).addShortcut();
+
+    RegisterUnloadableClass(Mini4Dgame);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Mini4Dgame::Mini4Dgame(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(Mini4Dgame);
+
+        this->board_ = nullptr;
+
+        // Set the type of Bots for this particular Gametype.
+        //this->botclass_ = Class(Mini4DgameBot);
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up, if initialized.
+    */
+    Mini4Dgame::~Mini4Dgame()
+    {
+        if (this->isInitialized())
+            this->cleanup();
+    }
+
+    /**
+    @brief
+        Cleans up the Gametype.
+    */
+    void Mini4Dgame::cleanup()
+    {
+        if(this->board_ != nullptr)// Destroy the board, if present.
+        {
+            //this->board_->destroy();
+            this->board_ = nullptr;
+        }
+    }
+
+    /**
+    @brief
+        Starts the mini4Dgame.
+    */
+    void Mini4Dgame::start()
+    {
+        if (this->board_ != nullptr) // There needs to be a Mini4DgameCenterpoint, i.e. the area the game takes place.
+        {
+            /*
+            if (this->board_ == nullptr)
+            {
+                this->board_ = new Mini4DgameBoard(this->board_->getContext());
+                // Apply the template for the ball specified by the centerpoint.
+                this->board_->addTemplate(this->center_->getBoardtemplate());
+            }
+            */
+
+            // Attach the board to the centerpoint and set the parameters as specified in the centerpoint, the ball is attached to.
+
+            this->board_->setPosition(0, 0, 0);
+
+        }
+        else // If no centerpoint was specified, an error is thrown and the level is exited.
+        {
+            orxout(internal_error) << "Mini4Dgame: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+
+        // Set variable to temporarily force the player to spawn.
+        bool temp = this->bForceSpawn_;
+        this->bForceSpawn_ = true;
+
+        // Call start for the parent class.
+        Deathmatch::start();
+
+        // Reset the variable.
+        this->bForceSpawn_ = temp;
+    }
+
+    /**
+    @brief
+        Ends the Mini4Dgame minigame.
+    */
+    void Mini4Dgame::end()
+    {
+        this->cleanup();
+
+        // Call end for the parent class.
+        Deathmatch::end();
+    }
+
+
+    /**
+    @brief
+        Spawns player.
+    */
+    void Mini4Dgame::spawnPlayersIfRequested()
+    {
+        // first spawn human players to assign always the left bat to the player in singleplayer
+        for (const auto& mapEntry : this->players_)
+            if (mapEntry.first->isHumanPlayer() && (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                this->spawnPlayer(mapEntry.first);
+        // now spawn bots
+        for (const auto& mapEntry : this->players_)
+            if (!mapEntry.first->isHumanPlayer() && (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                this->spawnPlayer(mapEntry.first);
+    }
+
+    /**
+    @brief
+        Spawns the input player.
+    @param player
+        The player to be spawned.
+    */
+    void Mini4Dgame::spawnPlayer(PlayerInfo* player)
+    {
+        assert(player);
+
+        if(false)//this->player_ == nullptr)
+        {
+            //this->player_ = player;
+            this->players_[player].state_ = PlayerState::Alive;
+        }
+    }
+
+    void Mini4Dgame::undoStone()//Vector4 move, const int playerColor)
+    {
+        ObjectList<Mini4DgameBoard>::iterator it = ObjectList<Mini4DgameBoard>().begin();
+        it->undoMove();
+    }
+
+    //void Mini4Dgame::setStone(Vector4 move, const int playerColor, Mini4DgameBoard* board)
+    void Mini4Dgame::setStone(int x,int y,int z,int w)//Vector4 move, const int playerColor)
+    {
+        Mini4DgamePosition move = Mini4DgamePosition(x,y,z,w);
+        ObjectList<Mini4DgameBoard>::iterator it = ObjectList<Mini4DgameBoard>().begin();
+        it->makeMove(move);
+    }
+
+    void Mini4Dgame::win(Mini4DgameWinner winner)
+    {
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4Dgame.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4Dgame.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4Dgame.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Mini4Dgame.h
+    @brief Declaration of the Mini4Dgame class.
+*/
+
+#ifndef _Mini4Dgame_H__
+#define _Mini4Dgame_H__
+
+#include "gametypes/Deathmatch.h"
+#include "mini4dgame/Mini4DgamePrereqs.h"
+#include "Mini4DgameBoard.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+
+    @author
+
+    */
+    class _Mini4DgameExport Mini4Dgame : public Deathmatch
+    {
+        public:
+            Mini4Dgame(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~Mini4Dgame(); //!< Destructor. Cleans up, if initialized.
+
+            virtual void start(void) override; //!< Starts the Mini4Dgame minigame.
+            virtual void end(void) override; ///!< Ends the Mini4Dgame minigame.
+
+            virtual void spawnPlayer(PlayerInfo* player) override; //!< Spawns the input player.
+
+            void setGameboard(Mini4DgameBoard* board)
+                { this->board_ = board; }
+
+            Mini4DgameBoard* getBoard(void)
+                { return this->board_; }
+
+            static void undoStone();
+
+            //static void setStone(Vector4 move, const int playerColor, Mini4DgameBoard* board);
+            static void setStone(int x,int y, int z, int w);//Vector4 move, const int playerColor);
+
+            void win(Mini4DgameWinner winner);
+
+        protected:
+            virtual void spawnPlayersIfRequested() override; //!< Spawns player.
+
+
+        private:
+            void cleanup(void); //!< Cleans up the Gametype by destroying the ball and the bats.
+
+            //Player players[2];
+            Mini4DgameBoard* board_;
+    };
+}
+
+#endif /* _Mini4Dgame_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameAI.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameAI.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameAI.cc	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Mini4DgameAI.cc
+    @brief Implementation of the Mini4DgameAI class.
+*/
+
+#include "Mini4DgameAI.h"
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/command/Executor.h"
+#include "tools/Timer.h"
+
+#include <list>
+
+#include "worldentities/ControllableEntity.h"
+
+#include "Mini4DgameCenterpoint.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Mini4DgameAI);
+
+    //const static float MAX_REACTION_TIME = 0.4f;
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Mini4DgameAI::Mini4DgameAI(Context* context) : Controller(context)
+    {
+        RegisterObject(Mini4DgameAI);
+
+        this->setConfigValues();
+        this->center_ = nullptr;
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up the list fo reaction timers.
+    */
+    Mini4DgameAI::~Mini4DgameAI()
+    {
+
+    }
+
+    Vector4 Mini4DgameAI::makeMove(float timeout)
+    {
+        this->copyBoard();
+        std::list<Vector4> possibleMoves = this->getPossibleMoves();
+
+        //TODO: alphabeta ueber possibleMoves
+
+        //when timeout
+        Vector4 move = possibleMoves.front();
+        return move;
+    }
+
+    void Mini4DgameAI::copyBoard()
+    {
+        for(int i=0;i<4;i++){
+            for(int j=0;j<4;j++){
+                for(int k=0;k<4;k++){
+                    for(int l=0;l<4;l++){
+                        this->board_[i][j][k][l]=this->center_->board[i][j][k][l];
+                    }
+                }
+            }
+        }
+    }
+
+    std::list<Vector4> Mini4DgameAI::getPossibleMoves()
+    {
+        std::list<Vector4> possibleMoves = new std::list<Vector4>;
+        for(int i=0;i<4;i++){
+            for(int j=0;j<4;j++){
+                for(int k=0;k<4;k++){
+                    for(int l=0;l<4;l++){
+                        if (this->board_[i][j][k][l]==Mini4DgamePlayerColor::none)
+                            possibleMoves.push_back(Vector4(i,j,k,l));
+                    }
+                }
+            }
+        }
+        return possibleMoves;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameAI.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameAI.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameAI.h	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Mini4DgameAI.h
+    @brief Declaration of the Mini4DgameAI class.
+*/
+
+#ifndef _Mini4DgameAI_H__
+#define _Mini4DgameAI_H__
+
+#include "mini4dgame/Mini4DgamePrereqs.h"
+
+#include <list>
+
+#include "controllers/Controller.h"
+#include "Mini4DgameCenterpoint.h"
+#include "Mini4Dgame.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The Mini4DgameAI is an artificial intelligence for the @ref orxonox::Mini4Dgame "Mini4Dgame" gametype.
+
+    @author
+        Oliver Richter
+    */
+    class _Mini4DgameExport Mini4DgameAI : public Controller
+    {
+        public:
+            Mini4DgameAI(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~Mini4DgameAI();
+
+            //void setConfigValues();
+
+            /**
+                @brief
+                    starts the AI to make a move. implements the intelligence of the AI
+                @param timeout
+                    The time the AI has to decide on a move. (Sets the strength of the AI)
+                @return move
+                    The move that the AI decided to make.
+            */
+            Vector4 makeMove(float timeout);
+
+            void setCenterpoint(Mini4DgameCenterpoint* center)
+                            { this->center_ = center; }
+
+        protected:
+
+            std::list<std::pair<Timer*, char>> reactionTimers_; //!< A list of reaction timers and the directions that take effect when their timer expires.
+            Mini4DgameCenterpoint* center_;
+
+        private:
+
+            std::list<Vector4> getPossibleMoves();
+            void copyBoard();
+            Mini4DgamePlayerColor board_[4][4][4][4];
+    };
+}
+
+#endif /* _Mini4DgameAI_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameBoard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameBoard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameBoard.cc	(revision 11817)
@@ -0,0 +1,904 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBall.cc
+    @brief Implementation of the PongBall class.
+*/
+
+#include "Mini4DgameBoard.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+
+#include "gametypes/Gametype.h"
+#include "graphics/BlinkingBillboard.h"
+
+#include "Mini4Dgame.h"
+
+namespace orxonox
+{
+    RegisterClass(Mini4DgameBoard);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Mini4DgameBoard::Mini4DgameBoard(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Mini4DgameBoard);
+
+        //this->registerVariables();
+
+        //initialize board
+        for(int i=0;i<4;i++){
+            for(int j=0;j<4;j++){
+                for(int k=0;k<4;k++){
+                    for(int l=0;l<4;l++){
+                        this->board[i][j][k][l]=Mini4DgamePlayerColor::none;
+                        this->blinkingBillboards[i][j][k][l] = nullptr;
+                    }
+                }
+            }
+        }
+        this->player_toggle_ = false;
+        this->checkGametype();
+    }
+
+    /**
+        @brief Checks if the move is valid
+        @param move The position where to put the stone
+    */
+    bool Mini4DgameBoard::isValidMove(const Mini4DgamePosition& move)
+    {
+        return (move.x<4 && move.y<4 && move.z<4 && move.w<4
+                && move.x>=0 && move.y>=0 && move.z>=0 && move.w>=0
+                && this->board[move.x][move.y][move.z][move.w] == Mini4DgamePlayerColor::none);
+    }
+
+    void Mini4DgameBoard::undoMove()
+    {
+        const Mini4DgamePosition& move = moves.back();
+        moves.pop_back();
+        this->board[move.x][move.y][move.z][move.w] = Mini4DgamePlayerColor::none;
+        this->blinkingBillboards[move.x][move.y][move.z][move.w]->destroy();
+        this->blinkingBillboards[move.x][move.y][move.z][move.w] = nullptr;
+        if(player_toggle_){
+            this->player_toggle_ = false;
+        }else{
+            this->player_toggle_ = true;
+        }
+    }
+
+    /**
+    @brief makes a move on the logic playboard
+    @param move The position where to put the stone
+    */
+    void Mini4DgameBoard::makeMove(const Mini4DgamePosition& move)
+    {
+        if(this->isValidMove(move))
+        {
+            if(!moves.empty())
+            {
+                //stop blinking of last move
+                const Mini4DgamePosition& lastMove = moves.back();
+                this->blinkingBillboards[lastMove.x][lastMove.y][lastMove.z][lastMove.w]
+                        ->setActive(false);
+                this->blinkingBillboards[lastMove.x][lastMove.y][lastMove.z][lastMove.w]
+                        ->setScale(0.1);
+            }
+
+            moves.push_back(move);
+            Mini4DgamePlayerColor playerColor = Mini4DgamePlayerColor::none;
+            if(player_toggle_){
+                playerColor = Mini4DgamePlayerColor::blue;
+                this->player_toggle_ = false;
+            }else{
+                playerColor = Mini4DgamePlayerColor::green;
+                this->player_toggle_ = true;
+            }
+
+            this->board[move.x][move.y][move.z][move.w] = playerColor;
+
+            BlinkingBillboard* bb = new BlinkingBillboard(this->getContext());
+            bb->setFrequency(0.3);
+            bb->setAmplitude(0.1);
+
+            switch(move.w){
+            case 0: bb->setMaterial("Numbers/One");
+                    bb->setPosition(60.0f*move.x-95,60.0f*move.y-95,60.0f*move.z-95);
+                    break;
+            case 1: bb->setMaterial("Numbers/Two");
+                    bb->setPosition(60.0f*move.x-85,60.0f*move.y-85,60.0f*move.z-95);
+                    break;
+            case 2: bb->setMaterial("Numbers/Three");
+                    bb->setPosition(60.0f*move.x-85,60.0f*move.y-95,60.0f*move.z-85);
+                    break;
+            case 3: bb->setMaterial("Numbers/Four");
+                    bb->setPosition(60.0f*move.x-85,60.0f*move.y-85,60.0f*move.z-85);
+                    break;
+            }
+
+            switch(playerColor){
+            case Mini4DgamePlayerColor::red:
+                bb->setColour(ColourValue(1,0,0)); break;
+            case Mini4DgamePlayerColor::green:
+                bb->setColour(ColourValue(0,1,0)); break;
+            case Mini4DgamePlayerColor::blue:
+                bb->setColour(ColourValue(0,0,1)); break;
+            default: break;
+            }
+
+            this->attach(bb);
+            this->blinkingBillboards[move.x][move.y][move.z][move.w] = bb;
+
+
+            Mini4DgameWinner winner = this->getWinner();
+            if(winner.color_ != Mini4DgamePlayerColor::none)
+            {
+                orxout(user_status) << "Mini4Dgame: win!!!!!!!" << endl;
+                for(int i=0;i<4;i++){
+                    BlinkingBillboard* redFlare = new BlinkingBillboard(this->getContext());
+                    redFlare->setFrequency(0.5);
+                    redFlare->setAmplitude(3);
+                    redFlare->setPosition(60.0f*(int)winner.winningRow[i]-90,
+                                    60.0f*(int)winner.winningColumn[i]-90,
+                                    60.0f*(int)winner.winningHeight[i]-90);
+                    redFlare->setMaterial("Flares/lensflare");
+                    redFlare->setColour(ColourValue(1,0,0));
+                    this->attach(redFlare);
+                    BlinkingBillboard* bb = this->blinkingBillboards[winner.winningRow[i]]
+                                                                    [winner.winningColumn[i]]
+                                                                    [winner.winningHeight[i]]
+                                                                    [winner.winningNumber[i]];
+                    bb->setActive(true);//start blinking
+                }
+            }
+        }else{
+            orxout(internal_error) << "Mini4Dgame: not a valid move"<< endl;
+        }
+    }
+
+    Mini4DgameWinner Mini4DgameBoard::getWinner()
+    {
+        Mini4DgameWinner winner;
+        winner.color_ = Mini4DgamePlayerColor::none;
+
+        //check diagonals rows-columns-height-numbers
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[i][i][i][i]==Mini4DgamePlayerColor::none || this->board[0][0][0][0] != this->board[i][i][i][i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[0][0][0][0];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = x;
+                    winner.winningColumn[x] = x;
+                    winner.winningHeight[x] = x;
+                    winner.winningNumber[x] = x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[3-i][i][i][i]==Mini4DgamePlayerColor::none || this->board[3][0][0][0] != this->board[3-i][i][i][i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[3][0][0][0];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = 3-x;
+                    winner.winningColumn[x] = x;
+                    winner.winningHeight[x] = x;
+                    winner.winningNumber[x] = x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[i][3-i][i][i]==Mini4DgamePlayerColor::none || this->board[0][3][0][0] != this->board[i][3-i][i][i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[0][3][0][0];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = x;
+                    winner.winningColumn[x] = 3-x;
+                    winner.winningHeight[x] = x;
+                    winner.winningNumber[x] = x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[i][i][3-i][i]==Mini4DgamePlayerColor::none || this->board[0][0][3][0] != this->board[i][i][3-i][i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[0][0][3][0];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = x;
+                    winner.winningColumn[x] = x;
+                    winner.winningHeight[x] = 3-x;
+                    winner.winningNumber[x] = x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[i][i][i][3-i]==Mini4DgamePlayerColor::none || this->board[0][0][0][3] != this->board[i][i][i][3-i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[0][0][0][3];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = x;
+                    winner.winningColumn[x] = x;
+                    winner.winningHeight[x] = x;
+                    winner.winningNumber[x] = 3-x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[3-i][3-i][i][i]==Mini4DgamePlayerColor::none || this->board[3][3][0][0] != this->board[3-i][3-i][i][i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[3][3][0][0];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = 3-x;
+                    winner.winningColumn[x] = 3-x;
+                    winner.winningHeight[x] = x;
+                    winner.winningNumber[x] = x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[3-i][i][3-i][i]==Mini4DgamePlayerColor::none || this->board[3][0][3][0] != this->board[3-i][i][3-i][i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[3][0][3][0];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = 3-x;
+                    winner.winningColumn[x] = x;
+                    winner.winningHeight[x] = 3-x;
+                    winner.winningNumber[x] = x;
+                }
+                return winner;
+            }
+        }
+        for(int i=1; i<4; i++)
+        {
+            if(this->board[3-i][i][i][3-i]==Mini4DgamePlayerColor::none || this->board[3][0][0][3] != this->board[3-i][i][i][3-i])
+                break;
+            if(i==3)
+            {
+                winner.color_ = this->board[3][0][0][3];
+                for(int x=0; x<4; x++){
+                    winner.winningRow[x] = 3-x;
+                    winner.winningColumn[x] = x;
+                    winner.winningHeight[x] = x;
+                    winner.winningNumber[x] = 3-x;
+                }
+                return winner;
+            }
+        }
+
+        //check diagonals rows-columns-height
+        for(int l=0; l<4; l++)
+        {
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][i][i][l]==Mini4DgamePlayerColor::none || this->board[0][0][0][l] != this->board[i][i][i][l])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][0][0][l];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = l;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[3-i][i][i][l]==Mini4DgamePlayerColor::none || this->board[3][0][0][l] != this->board[3-i][i][i][l])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[3][0][0][l];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = 3-x;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = l;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][3-i][i][l]==Mini4DgamePlayerColor::none || this->board[0][3][0][l] != this->board[i][3-i][i][l])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][3][0][l];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = 3-x;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = l;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][i][3-i][l]==Mini4DgamePlayerColor::none || this->board[0][0][3][l] != this->board[i][i][3-i][l])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][0][3][l];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = 3-x;
+                        winner.winningNumber[x] = l;
+                    }
+                    return winner;
+                }
+            }
+        }
+
+        //check diagonals rows-columns-numbers
+        for(int l=0; l<4; l++)
+        {
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][i][l][i]==Mini4DgamePlayerColor::none || this->board[0][0][l][0] != this->board[i][i][l][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][0][l][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = l;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[3-i][i][l][i]==Mini4DgamePlayerColor::none || this->board[3][0][l][0] != this->board[3-i][i][l][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[3][0][l][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = 3-x;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = l;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][3-i][l][i]==Mini4DgamePlayerColor::none || this->board[0][3][l][0] != this->board[i][3-i][l][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][3][l][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = 3-x;
+                        winner.winningHeight[x] = l;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][i][l][3-i]==Mini4DgamePlayerColor::none || this->board[0][0][l][3] != this->board[i][i][l][3-i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][0][l][3];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = l;
+                        winner.winningNumber[x] = 3-x;
+                    }
+                    return winner;
+                }
+            }
+        }
+
+        //check diagonals rows-height-numbers
+        for(int l=0; l<4; l++)
+        {
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][l][i][i]==Mini4DgamePlayerColor::none || this->board[0][l][0][0] != this->board[i][l][i][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][l][0][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = l;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[3-i][l][i][i]==Mini4DgamePlayerColor::none || this->board[3][l][0][0] != this->board[3-i][l][i][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[3][l][0][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = 3-x;
+                        winner.winningColumn[x] = l;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][l][3-i][i]==Mini4DgamePlayerColor::none || this->board[0][l][3][0] != this->board[i][l][3-i][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][l][3][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = l;
+                        winner.winningHeight[x] = 3-x;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[i][l][i][3-i]==Mini4DgamePlayerColor::none || this->board[0][l][0][3] != this->board[i][l][i][3-i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[0][l][0][3];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = x;
+                        winner.winningColumn[x] = l;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = 3-x;
+                    }
+                    return winner;
+                }
+            }
+        }
+
+        //check diagonals columns-height-numbers
+        for(int l=0; l<4; l++)
+        {
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[l][i][i][i]==Mini4DgamePlayerColor::none || this->board[l][0][0][0] != this->board[l][i][i][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[l][0][0][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = l;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[l][3-i][i][i]==Mini4DgamePlayerColor::none || this->board[l][3][0][0] != this->board[l][3-i][i][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[l][3][0][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = l;
+                        winner.winningColumn[x] = 3-x;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[l][i][3-i][i]==Mini4DgamePlayerColor::none || this->board[l][0][3][0] != this->board[l][i][3-i][i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[l][0][3][0];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = l;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = 3-x;
+                        winner.winningNumber[x] = x;
+                    }
+                    return winner;
+                }
+            }
+            for(int i=1; i<4; i++)
+            {
+                if(this->board[l][i][i][3-i]==Mini4DgamePlayerColor::none || this->board[l][0][0][3] != this->board[l][i][i][3-i])
+                    break;
+                if(i==3)
+                {
+                    winner.color_ = this->board[l][0][0][3];
+                    for(int x=0; x<4; x++){
+                        winner.winningRow[x] = l;
+                        winner.winningColumn[x] = x;
+                        winner.winningHeight[x] = x;
+                        winner.winningNumber[x] = 3-x;
+                    }
+                    return winner;
+                }
+            }
+        }
+
+        //check 2d diagonals
+        for(int k=0;k<4;k++){
+            for(int l=0;l<4;l++){
+                //rows-columns
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[i][i][k][l]==Mini4DgamePlayerColor::none || this->board[0][0][k][l] != this->board[i][i][k][l])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[0][0][k][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = x;
+                            winner.winningColumn[x] = x;
+                            winner.winningHeight[x] = k;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[3-i][i][k][l]==Mini4DgamePlayerColor::none || this->board[3][0][k][l] != this->board[3-i][i][k][l])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[3][0][k][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = 3-x;
+                            winner.winningColumn[x] = x;
+                            winner.winningHeight[x] = k;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+                //rows-height
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[i][k][i][l]==Mini4DgamePlayerColor::none || this->board[0][k][0][l] != this->board[i][k][i][l])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[0][k][0][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = x;
+                            winner.winningColumn[x] = k;
+                            winner.winningHeight[x] = x;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[3-i][k][i][l]==Mini4DgamePlayerColor::none || this->board[3][k][0][l] != this->board[3-i][k][i][l])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[3][k][0][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = 3-x;
+                            winner.winningColumn[x] = k;
+                            winner.winningHeight[x] = x;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+                //rows-numbers
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[i][k][l][i]==Mini4DgamePlayerColor::none || this->board[0][k][l][0] != this->board[i][k][l][i])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[0][k][l][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = x;
+                            winner.winningColumn[x] = k;
+                            winner.winningHeight[x] = l;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[3-i][k][l][i]==Mini4DgamePlayerColor::none || this->board[3][k][l][0] != this->board[3-i][k][l][i])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[3][k][l][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = 3-x;
+                            winner.winningColumn[x] = k;
+                            winner.winningHeight[x] = l;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+                //column-height
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[k][i][i][l]==Mini4DgamePlayerColor::none || this->board[k][0][0][l] != this->board[k][i][i][l])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[k][0][0][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = k;
+                            winner.winningColumn[x] = x;
+                            winner.winningHeight[x] = x;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[k][3-i][i][l]==Mini4DgamePlayerColor::none || this->board[k][3][0][l] != this->board[k][3-i][i][l])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[k][3][0][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = k;
+                            winner.winningColumn[x] = 3-x;
+                            winner.winningHeight[x] = x;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+                //column-numbers
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[k][i][l][i]==Mini4DgamePlayerColor::none || this->board[k][0][l][0] != this->board[k][i][l][i])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[k][0][l][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = k;
+                            winner.winningColumn[x] = x;
+                            winner.winningHeight[x] = l;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[k][3-i][l][i]==Mini4DgamePlayerColor::none || this->board[k][3][l][0] != this->board[k][3-i][l][i])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[k][3][l][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = k;
+                            winner.winningColumn[x] = 3-x;
+                            winner.winningHeight[x] = l;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+                //height-numbers
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[k][l][i][i]==Mini4DgamePlayerColor::none || this->board[k][l][0][0] != this->board[k][l][i][i])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[k][l][0][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = k;
+                            winner.winningColumn[x] = l;
+                            winner.winningHeight[x] = x;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+                for(int i=1; i<4; i++)
+                {
+                    if(this->board[k][l][3-i][i]==Mini4DgamePlayerColor::none || this->board[k][l][3][0] != this->board[k][l][3-i][i])
+                        break;
+                    if(i==3)
+                    {
+                        winner.color_ = this->board[k][l][3][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = k;
+                            winner.winningColumn[x] = l;
+                            winner.winningHeight[x] = 3-x;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+            }
+        }
+
+        //check rows
+        for(int j=0;j<4;j++){
+            for(int k=0;k<4;k++){
+                for(int l=0;l<4;l++){
+                    if(this->board[0][j][k][l]!= Mini4DgamePlayerColor::none
+                       && this->board[0][j][k][l]==this->board[1][j][k][l]
+                       && this->board[1][j][k][l]==this->board[2][j][k][l]
+                       && this->board[2][j][k][l]==this->board[3][j][k][l])
+                    {
+                        winner.color_ = this->board[0][j][k][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = x;
+                            winner.winningColumn[x] = j;
+                            winner.winningHeight[x] = k;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+            }
+        }
+
+        //check columns
+        for(int i=0;i<4;i++){
+            for(int k=0;k<4;k++){
+                for(int l=0;l<4;l++){
+                    if(this->board[i][0][k][l]!= Mini4DgamePlayerColor::none
+                               && this->board[i][0][k][l]==this->board[i][1][k][l]
+                               && this->board[i][1][k][l]==this->board[i][2][k][l]
+                               && this->board[i][2][k][l]==this->board[i][3][k][l])
+                    {
+                        winner.color_ = this->board[i][0][k][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = i;
+                            winner.winningColumn[x] = x;
+                            winner.winningHeight[x] = k;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+            }
+        }
+
+        //check height
+        for(int i=0;i<4;i++){
+            for(int j=0;j<4;j++){
+                for(int l=0;l<4;l++){
+                    if(this->board[i][j][0][l]!= Mini4DgamePlayerColor::none
+                                       && this->board[i][j][0][l]==this->board[i][j][1][l]
+                                       && this->board[i][j][1][l]==this->board[i][j][2][l]
+                                       && this->board[i][j][2][l]==this->board[i][j][3][l])
+                    {
+                        winner.color_ = this->board[i][j][0][l];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = i;
+                            winner.winningColumn[x] = j;
+                            winner.winningHeight[x] = x;
+                            winner.winningNumber[x] = l;
+                        }
+                        return winner;
+                    }
+                }
+            }
+        }
+
+        //check numbers
+        for(int i=0;i<4;i++){
+            for(int j=0;j<4;j++){
+                for(int k=0;k<4;k++){
+                    if(this->board[i][j][k][0]!= Mini4DgamePlayerColor::none
+                                       && this->board[i][j][k][0]==this->board[i][j][k][1]
+                                       && this->board[i][j][k][1]==this->board[i][j][k][2]
+                                       && this->board[i][j][k][2]==this->board[i][j][k][3])
+                    {
+                        winner.color_ = this->board[i][j][k][0];
+                        for(int x=0; x<4; x++){
+                            winner.winningRow[x] = i;
+                            winner.winningColumn[x] = j;
+                            winner.winningHeight[x] = k;
+                            winner.winningNumber[x] = x;
+                        }
+                        return winner;
+                    }
+                }
+            }
+        }
+        return winner;
+    }
+
+    /**
+    @brief
+        Checks whether the gametype is Mini4Dgame and if it is, sets its centerpoint.
+    */
+    void Mini4DgameBoard::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Mini4Dgame)))
+        {
+            Mini4Dgame* Mini4DgameGametype = orxonox_cast<Mini4Dgame*>(this->getGametype());
+            Mini4DgameGametype->setGameboard(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameBoard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameBoard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgameBoard.h	(revision 11817)
@@ -0,0 +1,99 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Mini4DgameBoard.h
+    @brief Declaration of the Mini4DgameBoard class.
+    @ingroup Pong
+*/
+
+#ifndef _Mini4DgameBoard_H__
+#define _Mini4DgameBoard_H__
+
+#include "mini4dgame/Mini4DgamePrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    enum class Mini4DgamePlayerColor
+    {
+        none,
+        red,
+        blue,
+        green
+    };
+
+    struct Mini4DgamePosition
+    {
+        Mini4DgamePosition(int x, int y, int z, int w) : x(x), y(y), z(z), w(w) {}
+        int x;
+        int y;
+        int z;
+        int w;
+    };
+
+    struct Mini4DgameWinner
+    {
+        int winningRow[4];
+        int winningColumn[4];
+        int winningHeight[4];
+        int winningNumber[4];
+        Mini4DgamePlayerColor color_;
+    };
+
+    /**
+    @brief
+        This class manages the board for @ref orxonox::Mini4Dgame "Mini4Dgame".
+
+    @author
+        Oliver Richter
+    */
+    class _Mini4DgameExport Mini4DgameBoard : public StaticEntity
+    {
+        public:
+            Mini4DgameBoard(Context* context);
+            //virtual ~Mini4DgameBoard();
+
+            bool isValidMove(const Mini4DgamePosition& move);
+            void undoMove();
+            void makeMove(const Mini4DgamePosition& move);
+            Mini4DgameWinner getWinner();
+
+            void checkGametype();
+
+        private:
+            //void registerVariables();
+            std::vector<Mini4DgamePosition> moves;
+            bool player_toggle_;
+            BlinkingBillboard* blinkingBillboards[4][4][4][4];
+            Mini4DgamePlayerColor board[4][4][4][4]; //!< The logical board where the game takes place. board[row][column][height][number]
+    };
+}
+
+#endif /* _Mini4DgameBoard_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgamePrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgamePrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/mini4dgame/Mini4DgamePrereqs.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the mini4dgame module
+*/
+
+#ifndef _Mini4DgamePrereqs_H__
+#define _Mini4DgamePrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(MINI4DGAME_STATIC_BUILD)
+#  ifdef MINI4DGAME_SHARED_BUILD
+#    define _Mini4DgameExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _Mini4DgameExport
+#    else
+#      define _Mini4DgameExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _Mini4DgamePrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _Mini4DgameExport  __attribute__ ((visibility("default")))
+#  define _Mini4DgamePrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _Mini4DgameExport
+#  define _Mini4DgamePrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Mini4Dgame;
+    class Mini4DgameBoard;
+}
+
+#endif /* _Mini4DgamePrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/notifications/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,21 @@
+SET_SOURCE_FILES(NOTIFICATIONS_SRC_FILES
+  NotificationDispatcher.cc
+  NotificationManager.cc
+  NotificationQueue.cc
+  NotificationQueueCEGUI.cc
+)
+
+ADD_SUBDIRECTORY(dispatchers)
+
+ORXONOX_ADD_LIBRARY(notifications
+  MODULE
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    NotificationManager.h
+    NotificationQueueCEGUI.h
+  PCH_FILE
+    NotificationsPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${NOTIFICATIONS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationDispatcher.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationDispatcher.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationDispatcher.cc	(revision 11817)
@@ -0,0 +1,203 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 thes
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationDispatcher.cc
+    @brief Implementation of the NotificationDispatcher class.
+*/
+
+#include "NotificationDispatcher.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+#include "network/NetworkFunctionIncludes.h"
+#include "network/Host.h"
+
+#include "infos/PlayerInfo.h"
+#include "interfaces/NotificationListener.h"
+#include "interfaces/PlayerTrigger.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+
+    RegisterUnloadableClass(NotificationDispatcher);
+
+    registerMemberNetworkFunction(NotificationDispatcher, broadcastHelper);
+    registerMemberNetworkFunction(NotificationDispatcher, dispatch);
+
+    /**
+    @brief
+        Default constructor. Initializes the object.
+    */
+    NotificationDispatcher::NotificationDispatcher(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        RegisterObject(NotificationDispatcher);
+
+        this->sender_ = NotificationListener::NONE;
+        this->bBroadcast_ = false;
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    NotificationDispatcher::~NotificationDispatcher()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a NotificationDispatcher object through XML.
+    */
+    void NotificationDispatcher::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(NotificationDispatcher, XMLPort, xmlelement, mode);
+
+        XMLPortParam(NotificationDispatcher, "sender", setSender, getSender, xmlelement, mode);
+        XMLPortParam(NotificationDispatcher, "broadcast", setBroadcasting, isBroadcasting, xmlelement, mode);
+
+        XMLPortEventSink(NotificationDispatcher, BaseObject, "trigger", trigger, xmlelement, mode);
+    }
+
+    void NotificationDispatcher::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(NotificationDispatcher, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(NotificationDispatcher, BaseObject, "trigger", trigger, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Registers variables for synchronisation.
+    */
+    void NotificationDispatcher::registerVariables(void)
+    {
+        registerVariable(this->sender_, VariableDirection::ToClient);
+    }
+
+    /**
+    @brief
+        Broadcasts a specific Notification.
+    */
+    void NotificationDispatcher::broadcast(void)
+    {
+        // TODO: Needed?
+        const std::string message = this->createNotificationMessage();
+        NotificationListener::sendNotification(message, this->getSender(), NotificationMessageType::info, NotificationSendMode::local);
+
+        // Broadcast
+        if(!GameMode::isStandalone())
+        {
+            callMemberNetworkFunction(&NotificationDispatcher::broadcastHelper, this->getObjectID(), NETWORK_PEER_ID_BROADCAST);
+        }
+    }
+
+    /**
+    @brief
+        Helper function for broadcast.
+    */
+    void NotificationDispatcher::broadcastHelper(void)
+    {
+        this->dispatch(Host::getPlayerID());
+    }
+
+    /**
+    @brief
+        Dispatches a Notification with a message supplied by the createNotificationMessage() method, which can be overloaded.
+    @param clientId
+        The id of the client the notification should be dispatched to.
+    */
+    void NotificationDispatcher::dispatch(unsigned int clientId)
+    {
+        // We don't call sendNotification() directly on the server, because if might be necessary that createNotificationMessage() is executed on the client as the message may be client-specific.
+        if(GameMode::isStandalone() || Host::getPlayerID() == clientId || this->getSyncMode() == ObjectDirection::None)
+        {
+            const std::string message = this->createNotificationMessage();
+            // TODO: Make the type configurable.
+            NotificationListener::sendNotification(message, this->getSender(), NotificationMessageType::info, NotificationSendMode::network, clientId);
+        }
+        else if(GameMode::isServer())
+        {
+            callMemberNetworkFunction(&NotificationDispatcher::dispatch, this->getObjectID(), clientId, clientId);
+        }
+    }
+
+    /**
+    @brief
+        Is called when the NotificationDispatcher is triggered.
+    @param triggered
+        Whether it has been triggered or untriggered. The NotificationDispatcher only reacts to the first kind of events.
+    @param trigger
+        The object that caused the event to be fired.
+    @return
+        Returns true if the NotificationDispatcher was successfully triggered.
+    */
+    bool NotificationDispatcher::trigger(bool triggered, BaseObject* trigger)
+    {
+        if(!triggered || !this->isActive()) // If the NotificationDispatcher is inactive it cannot be executed.
+            return false;
+
+        orxout(verbose, context::notifications) << "NotificationDispatcher (&" << this << ") triggered." << endl;
+
+        // If the NotificationDispatcher is set to broadcast.
+        if(this->isBroadcasting())
+        {
+            this->broadcast();
+            return true;
+        }
+
+        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+        PlayerInfo* player = nullptr;
+
+        // If the trigger is a PlayerTrigger.
+        if(pTrigger != nullptr)
+        {
+            if(!pTrigger->isForPlayer())  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+                return false;
+            else
+                player = pTrigger->getTriggeringPlayer();
+        }
+        else
+            return false;
+
+        if(player == nullptr)
+        {
+            orxout(verbose, context::notifications) << "The NotificationDispatcher was triggered by an entity other than a Pawn. (" << trigger->getIdentifier()->getName() << ")" << endl;
+            return false;
+        }
+
+        this->dispatch(player->getClientID());
+
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationDispatcher.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationDispatcher.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationDispatcher.h	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationDispatcher.h
+    @brief Definition of the NotificationDispatcher class.
+    @ingroup Notifications
+*/
+
+#ifndef _NotificationDispatcher_H__
+#define _NotificationDispatcher_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include <string>
+
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A NotificationDispatcher is an entity that, upon being triggered, dispatches (or sends) a specified @ref orxonox::Notification "Notification".
+
+        There are two parameter to be set:
+        - The @b sender . The sender specifies the part of Orxonox the sent @ref orxonox::Notification "Notification" comes from. The default value is set by the classes implementing NotificationDispatcher.
+        - The @b broadcast . Specifies whether messages are broadcast (i.e. sent to all clients) or just sent to a specific player.
+
+        Its standard usage is:
+        @code
+        <NotificationDispatcher sender="me">
+            <events>
+                <trigger>
+                    <PlayerTrigger />
+                </trigger>
+            </event>
+        </NotificationDispatcher>
+        @endcode
+        But keep in mind, that NotificationDispatcher is an abstract class.
+        Also in this example @ref orxonox::PlayerTrigger "PlayerTrigger" stands for any event that is caused by a @ref orxonox::PlayerTrigger "PlayerTrigger", so instead of @ref orxonox::PlayerTrigger "PlayerTrigger", there could be a @ref orxonox::DistanceTrigger "DistanceTrigger", or a @ref orxonox::DistanceMultiTrigger "DistanceMutliTrigger", or even an @ref orxonox::EventListener "EventListener" that waits for an event coming from any kind of @ref orxonox::PlayerTrigger "PlayerTrigger".
+        If the NotificationDispatcher is not set to broadcast only events caused by @ref orxonox::PlayerTrigger "PlayerTriggers" trigger a message since the information obtained by the @ref orxonox::PlayerTrigger "PlayerTrigger" is used to identify the client to which the message should be sent.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Notifications
+    */
+    class _NotificationsExport NotificationDispatcher : public BaseObject, public Synchronisable
+    {
+        public:
+            NotificationDispatcher(Context* context); //!< Default constructor. Initializes the object.
+            virtual ~NotificationDispatcher(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a NotificationDispatcher object through XML.
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            /**
+            @brief Get the sender of the Notification dispatched by this NotificationDispatcher.
+            @return Returns the name of the sender.
+            */
+            const std::string& getSender(void) const
+                { return this->sender_; }
+            /**
+            @brief Set the sender of the Notification dispatched by this NotificationDispatcher.
+            @param sender The name of the sender.
+            */
+            void setSender(const std::string& sender)
+                { this->sender_ = sender; }
+
+            /**
+            @brief Check whether the NotificationDispatcher is set to broadcast.
+            @return Returns true if the NotificationDispatcher is set to broadcast.
+            */
+            bool isBroadcasting(void) const
+                { return this->bBroadcast_; }
+            /**
+            @brief Set the NotificationDispatcher to broadcast.
+            @param v Whether the NotificationDispatcher is set to broadcast or singlecast.
+            */
+            void setBroadcasting(bool v)
+                { this->bBroadcast_ = v; }
+
+            void broadcast(void); //!< Broadcasts a specific Notification.
+            void broadcastHelper(void); //!< Helper function for broadcast.
+            void dispatch(unsigned int clientId); //!< Dispatches a specific Notification to a given client.
+            bool trigger(bool triggered, BaseObject* trigger); //!< Is called when the NotificationDispatcher is triggered.
+
+        protected:
+            std::string sender_; //!< The name of the sender of the Notification dispatched by this NotificationDispatcher.
+            bool bBroadcast_; //!< Whether the NotificationDispatcher is broadcasting.
+
+            void registerVariables(void); //!< Register some variables for synchronisation.
+
+            /**
+            @brief Creates the notification message that should be sent upon the NotificationDispatcher triggering.
+                   This method can be overloaded to customize the NotificationDispatcher.
+            @return Returns the notification message.
+            */
+            virtual const std::string& createNotificationMessage(void)
+                { return BLANKSTRING; }
+
+    };
+
+}
+
+#endif /* _NotificationDispatcher_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationManager.cc	(revision 11817)
@@ -0,0 +1,466 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationManager.cc
+    @brief Implementation of the NotificationManager class.
+*/
+
+#include "NotificationManager.h"
+
+#include "core/command/ConsoleCommand.h"
+#include "core/CoreIncludes.h"
+#include "core/LuaState.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+#include "interfaces/NotificationListener.h"
+
+#include "NotificationQueue.h"
+#include "NotificationQueueCEGUI.h"
+
+namespace orxonox
+{
+
+    ManageScopedSingleton(NotificationManager, ScopeID::ROOT, false);
+
+    RegisterAbstractClass(NotificationManager).inheritsFrom<NotificationListener>();
+
+    /**
+    @brief
+        Constructor. Registers the Object.
+    */
+    NotificationManager::NotificationManager()
+    {
+        RegisterObject(NotificationManager);
+
+        orxout(internal_info, context::notifications) << "NotificatioManager created." << endl;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    NotificationManager::~NotificationManager()
+    {
+        // Destroys all Notifications.
+        for(const auto& mapEntry : this->allNotificationsList_)
+            mapEntry.second->destroy();
+        this->allNotificationsList_.clear();
+
+        orxout(internal_info, context::notifications) << "NotificationManager destroyed." << endl;
+    }
+
+    /**
+    @brief
+        Is called before the object is destroyed.
+    */
+    void NotificationManager::preDestroy(void)
+    {
+        // Destroys all NotificationQueues that have been registered with the NotificationManager.
+        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin();
+        while(it != this->queues_.end())
+        {
+            it->second->destroy();
+            it = this->queues_.begin();
+        }
+
+        this->queues_.clear();
+    }
+
+    /**
+    @brief
+        Creates and registers a Notification with the input message from the input sender.
+        This is called by the NotificationListener, whenever a new notification arrives.
+    @param message
+        The message of the new Notification.
+    @param sender
+        The name of the entity (of the collective) that sent the new Notification.
+    @param type
+        The type of the new Notification.
+    @return
+        Returns true if successful.
+    */
+    bool NotificationManager::registerNotification(const std::string& message, const std::string& sender, NotificationMessageType type)
+    {
+        // TODO: Do something with the type.
+        Notification* notification = new Notification(message, sender, type);
+        return this->registerNotification(notification);
+    }
+
+    /**
+    @brief
+        Executes the input command from the input sender.
+        This is called by the NotificationListener, whenever a new command arrives.
+    @param command
+        The command to be executed,
+    @param sender
+        The The name of the entity (of the collective) that sent the command.
+    @return
+        Returns true if the command was successfully executed.
+    */
+    bool NotificationManager::executeCommand(NotificationCommand command, const std::string& sender)
+    {
+        bool commandExecuted = false;
+        if(command == NotificationCommand::clear)
+        {
+            if(this->commandClear(sender))
+                commandExecuted = true;
+        }
+
+        if(commandExecuted)
+            orxout(internal_info, context::notifications) << "Notification command \"" << NotificationListener::command2Str(command) << "\" executed." << endl;
+
+        return commandExecuted;
+    }
+
+    /**
+    @brief
+        The clear command. Clears all NotificationQueues that have its sender as a target.
+    @param sender
+        The sender of the clear command.
+    @return
+        Returns true if the command was successfully executed by at least one NotificationQueue, false if it was not executed.
+    */
+    bool NotificationManager::commandClear(const std::string& sender)
+    {
+        bool all = (sender == NotificationListener::ALL);
+        bool executed = false;
+        // Clear all NotificationQueues that have the input sender as target.
+        for(const auto& mapEntry : this->queues_) // Iterate through all NotificationQueues.
+        {
+            const std::set<std::string>& set = mapEntry.second->getTargetsSet();
+            // If either the sender is 'all', the NotificationQueue has as target all or the NotificationQueue has the input sender as a target.
+            if(all || set.find(NotificationListener::ALL) != set.end() || set.find(sender) != set.end())
+                executed = mapEntry.second->tidy() || executed;
+        }
+
+        return executed;
+    }
+    
+    /**
+    @brief
+        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationQueues associated with its sender.
+    @param notification
+        The Notification to be registered.
+    @return
+        Returns true if successful.
+    */
+    bool NotificationManager::registerNotification(Notification* notification)
+    {
+        assert(notification);
+
+        std::time_t time = std::time(0); // Get current time.
+
+        // Add the Notification to the list that holds all Notifications.
+        this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
+
+        if(notification->getSender() == NotificationListener::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
+            return true;
+
+        // If all are the sender, then the Notifications is added to every NotificationQueue.
+        bool all = (notification->getSender() == NotificationListener::ALL);
+
+        // Insert the Notification in all NotificationQueues that have its sender as target.
+        for(const auto& mapEntry : this->queues_) // Iterate through all NotificationQueues.
+        {
+            const std::set<std::string>& set = mapEntry.second->getTargetsSet();
+            bool bAll = set.find(NotificationListener::ALL) != set.end();
+            // If either the Notification has as sender 'all', the NotificationQueue displays all Notifications or the NotificationQueue has the sender of the Notification as target.
+            if(all || bAll || set.find(notification->getSender()) != set.end())
+            {
+                if(!bAll)
+                    this->notificationLists_[mapEntry.second->getName()]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationQueue.
+                mapEntry.second->update(notification, time); // Update the NotificationQueue.
+            }
+        }
+
+        orxout(verbose, context::notifications) << "Notification (&" << notification << ") registered with the NotificationManager." << endl;
+
+        return true;
+    }
+
+    /**
+    @brief
+        Unregisters a Notification within the NotificationManager for a given NotificationQueue.
+    @param notification
+        A pointer to the Notification to be unregistered.
+    @param queue
+        A pointer to the NotificationQueue the Notification is unregistered for.
+    */
+    void NotificationManager::unregisterNotification(Notification* notification, NotificationQueue* queue)
+    {
+        assert(notification);
+        assert(queue);
+
+        // Remove the Notification from the list of Notifications of the input NotificationQueue.
+        this->removeNotification(notification, *(this->notificationLists_.find(queue->getName())->second));
+
+        orxout(verbose, context::notifications) << "Notification (&" << notification << ") unregistered with the NotificationManager from NotificationQueue " << queue->getName() << "." << endl;
+    }
+
+    /**
+    @brief
+        Helper method that removes an input Notification form an input map.
+    @param notification
+        A pointer to the Notification to be removed.
+    @param map
+        The map the Notification should be removed from.
+    @return
+        Returns true if successful.
+    */
+    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
+    {
+        // Iterates through all items in the map until the Notification is found.
+        //TODO: Do more efficiently?
+        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
+        {
+            if(it->second == notification)
+            {
+                map.erase(it);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+    @brief
+        Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
+    @param queue
+        The NotificationQueue the Notifications are fetched for.
+    @param map
+        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
+    @param timeFrameStart
+        The start time of the timeframe.
+    @param timeFrameEnd
+        The end time of the timeframe.
+    @return
+        Returns true if successful.
+    */
+    void NotificationManager::getNotifications(NotificationQueue* queue, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
+    {
+        assert(queue);
+        assert(map);
+
+        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
+
+        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
+        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
+        itLowest = notifications->lower_bound(timeFrameStart);
+        itHighest = notifications->upper_bound(timeFrameEnd);
+
+        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
+            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
+    }
+
+    /**
+    @brief
+        Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
+    @param queue
+        The NotificationQueue the Notifications are fetched for.
+    @param map
+        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
+    @param numberOfNotifications
+        The number of newest Notifications to be got.
+    @return
+        Returns true if successful.
+    */
+    void NotificationManager::getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications)
+    {
+        assert(queue);
+        assert(map);
+
+        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
+
+        if(!notifications->empty()) // If the list of Notifications is not empty.
+        {
+            std::multimap<std::time_t,Notification*>::iterator it = notifications->end();
+            for(int i = 0; i < numberOfNotifications; i++) // Iterate through the Notifications from the newest until we have the specified number of notifications.
+            {
+                it--;
+                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
+                if(it == notifications->begin())
+                    break;
+            }
+        }
+    }
+
+    /**
+    @brief
+        Registers a NotificationQueue.
+        This makes sure that the NotificationQueue can be accessed through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
+    @param queue
+        A pointer to the NotificationQueue to be registered.
+    @return
+        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
+    */
+    bool NotificationManager::registerQueue(NotificationQueue* queue)
+    {
+        assert(queue);
+
+        // If the NotificationQueue is already registered.
+        if(this->queues_.find(queue->getName()) != this->queues_.end())
+            return false;
+
+        this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)); // Add the NotificationQueue to the list of NotificationQueues.
+
+        const std::set<std::string>& set = queue->getTargetsSet();
+
+        // If all senders are the target of the NotificationQueue, then the list of Notifications for that specific NotificationQueue is the same as the list of all Notifications.
+        bool bAll = set.find(NotificationListener::ALL) != set.end();
+        std::multimap<std::time_t, Notification*>* map = nullptr;
+        if(bAll)
+            this->notificationLists_[queue->getName()] = &this->allNotificationsList_;
+        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationQueues.
+        else
+        {
+            this->notificationLists_[queue->getName()] = new std::multimap<std::time_t, Notification*>;
+            map = this->notificationLists_[queue->getName()];
+        }
+
+        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationQueue.
+        for(const auto& mapEntry : this->allNotificationsList_)
+        {
+            if(!bAll && set.find(mapEntry.second->getSender()) != set.end()) // Checks whether the listener has the sender of the current Notification as target.
+                map->insert(std::pair<std::time_t, Notification*>(mapEntry.first, mapEntry.second));
+        }
+
+        queue->update(); // Update the queue.
+        
+        orxout(verbose, context::notifications) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Unregisters a NotificationQueue.
+    @param queue
+        A pointer to the NotificationQueue to be unregistered.
+    */
+    void NotificationManager::unregisterQueue(NotificationQueue* queue)
+    {
+        assert(queue);
+
+        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(queue->getName())->second;
+
+        // If the map is not the map of all Notifications, make sure all Notifications are unregistered.
+        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
+        if(map != &this->allNotificationsList_)
+        {
+            while(it != map->end())
+            {
+                this->unregisterNotification(it->second, queue);
+                it = map->begin();
+            }
+            delete map;
+        }
+
+        // Remove the NotificationQueue from the list of NotificationQueues.
+        this->queues_.erase(queue->getName());
+        // Remove the Notifications list that was associated with the input NotificationQueue.
+        this->notificationLists_.erase(queue->getName());
+        
+        orxout(verbose, context::notifications) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << endl;
+    }
+
+    /**
+    @brief
+        Get the NotificationQueue with the input name.
+    @param name
+        The name of the NotificationQueue.
+    @return
+        Returns a pointer to the NotificationQueue with the input name. Returns nullptr if no NotificationQueue with such a name exists.
+    */
+    NotificationQueue* NotificationManager::getQueue(const std::string & name)
+    {
+        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
+        // Returns nullptr if no such NotificationQueue exists.
+        if(it == this->queues_.end())
+            return nullptr;
+
+        return (*it).second;
+    }
+
+    /**
+    @brief
+        Loads all the NotificationQueues that should exist.
+    */
+    void NotificationManager::loadQueues(void)
+    {
+        /*NotificationQueueCEGUI* allQueue = new NotificationQueueCEGUI("all");
+        allQueue->setDisplaySize(Vector2(0.5, 0));
+        allQueue->setPosition(Vector4(0.0, 10, 0.3, 0));
+
+        NotificationQueueCEGUI* infoQueue = new NotificationQueueCEGUI("info", "gameinfo", 1, -1);
+        infoQueue->setPosition(Vector4(0.2, 0, 0.8, 0));
+        infoQueue->setFontSize(24);
+        infoQueue->setFontColor(Vector4(1.0, 1.0, 0.0, 0.8));
+        infoQueue->setAlignment("HorzCentred");
+        infoQueue->setDisplaySize(Vector2(0.6, 0.0));*/
+    }
+
+    // Notification class
+
+    /**
+    @brief
+        Constructor. Creates a Notification with the input message and sender.
+    @param message
+        The message of the Notification.
+    @param sender
+        The sender of the Notification.
+    @param type
+
+    */
+    Notification::Notification(const std::string& message, const std::string& sender, NotificationMessageType type)
+    {
+        this->initialize();
+        this->message_ = message;
+        this->sender_ = sender;
+        this->type_ = type;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    Notification::~Notification()
+    {
+
+    }
+
+    /**
+    @brief
+        Registers the object and sets some default values.
+    */
+    void Notification::initialize(void)
+    {
+        this->message_.clear();
+        this->sender_ = NotificationListener::NONE;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationManager.h	(revision 11817)
@@ -0,0 +1,174 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationManager.h
+    @brief Definition of the NotificationManager class.
+    @ingroup Notifications
+*/
+
+#ifndef _NotificationManager_H__
+#define _NotificationManager_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include <ctime>
+#include <map>
+#include <string>
+
+#include "util/Singleton.h"
+#include "interfaces/NotificationListener.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        A Notification represents a short message used to inform the player about something that just happened. With the @ref orxonox::NotificationManager "NotificationManager" a Notification can be sent from any part of orxonox and is then displayed by the proper @ref orxonox::NotificationQueue "NotificationQueue(s)" (depending on which senders the specific @ref orxonox::NotificationQueue "NotificationQueues" accepts).
+
+        A Notification is just a data structure that is used internally by the Notifications module.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Notifications
+    */
+    class _NotificationsExport Notification
+    {
+        public:
+            Notification(const std::string& message, const std::string& sender, NotificationMessageType type);
+            virtual ~Notification();
+
+            /**
+            @brief Destroys the Notification.
+            */
+            void destroy(void)
+                { delete this; }
+
+            /**
+            @brief Get the message of the Notification.
+            @return Returns the message of the Notification.
+            */
+            inline const std::string & getMessage(void) const
+                { return this->message_; }
+
+            /**
+            @brief Get the sender of the Notification.
+            @return Returns the sender of the Notification.
+            */
+            inline const std::string & getSender(void) const
+                { return this->sender_; }
+
+            /**
+            @brief Get the type of the Notification.
+            @return Returns an enum with the type of the Notification.
+            */
+            inline NotificationMessageType getType(void) const
+                { return this->type_; }
+
+        private:
+            std::string message_; //!< The Notification message.
+            std::string sender_; //!< The sender of the notification.
+            NotificationMessageType type_; //!< The type of the notification.
+
+            void initialize(void); //!< Registers the object and sets some default values.
+
+    };
+
+    /**
+    @brief
+        The Singleton NotificationManager is a NotificationListener and functions as a gateway between @ref orxonox::Notification "Notifications" and @ref orxonox::NotificationQueue "NotificationQueues".
+        It receives, organizes @ref orxonox::Notification "Notifications" and the redistributes them to the specific @ref orxonox::NotificationQueue "NotificationQueues".
+        It also works as a liaison between the @ref orxonox::NotificationQueue "NotificationQueues" and the GUI that displays notification, called NotificationLayer.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Notifications
+    */
+    class _NotificationsExport NotificationManager // tolua_export
+        : public Singleton<NotificationManager>, public NotificationListener
+    { // tolua_export
+            friend class Singleton<NotificationManager>;
+        public:
+            NotificationManager();
+            virtual ~NotificationManager();
+
+            virtual void preDestroy(void) override; // Is called before the object is destroyed.
+
+            /**
+            @brief Get the instance of the NotificationManager Singleton.
+            @return Returns a reference to the NotificationManager.
+            */
+            static NotificationManager& getInstance() { return Singleton<NotificationManager>::getInstance(); } // tolua_export
+
+            virtual bool registerNotification(const std::string& message, const std::string& sender, NotificationMessageType type) override;
+            virtual bool executeCommand(NotificationCommand command, const std::string& sender) override;
+
+            bool registerNotification(Notification* notification); // Registers a Notification within the NotificationManager.
+            void unregisterNotification(Notification* notification, NotificationQueue* queue); // Unregisters a Notification within the NotificationManager for a given NotificationQueue.
+
+            void getNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd); // Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
+
+            /**
+            @brief Fetches the Notifications for a specific NotificationQueue in a timeframe from (now-timeDelay) to now and stores them in the input map.
+            @param queue The NotificationQueue the Notifications are fetched for.
+            @param map A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
+            @param timeDelay The timespan.
+            @return Returns true if successful.
+            */
+            void getNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int timeDelay)
+                { this->getNotifications(queue, map, std::time(0)-timeDelay, std::time(0)); }
+
+            void getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications); // Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
+
+            bool registerQueue(NotificationQueue* queue); // Registers a NotificationQueue.
+            void unregisterQueue(NotificationQueue* queue); // Unregisters a NotificationQueue.
+
+            void loadQueues(void); // tolua_export // Loads all the NotificationQueues that should exist.
+
+            NotificationQueue* getQueue(const std::string & name); // Get the NotificationQueue with the input name.
+
+        private:
+            static NotificationManager* singletonPtr_s;
+
+            std::multimap<std::time_t, Notification*> allNotificationsList_; //!< Container where all Notifications are stored.
+            std::map<const std::string, std::multimap<std::time_t, Notification*>*> notificationLists_; //!< Container where all Notifications, for each identifier (associated with a NotificationQueue), are stored.
+
+            std::map<const std::string, NotificationQueue*> queues_; //!< The list of NotificationQueues created by the NotificationManager.
+
+            bool removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map); // Helper method that removes an input Notification form an input map.
+            
+            // Commands
+            bool commandClear(const std::string& sender); // The clear command. Clears all NotificationQueues that have its sender as a target.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _NotificationManager_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueue.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueue.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueue.cc	(revision 11817)
@@ -0,0 +1,467 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationQueue.cc
+    @brief Implementation of the NotificationQueue class.
+*/
+
+#include "NotificationQueue.h"
+
+#include <map>
+#include <sstream>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/SubString.h"
+
+namespace orxonox
+{
+
+    RegisterClass(NotificationQueue);
+
+    /**
+    @brief
+        Default constructor. Registers and initializes the object.
+    */
+    NotificationQueue::NotificationQueue(Context* context) : BaseObject(context), Synchronisable(context), registered_(false)
+    {
+        RegisterObject(NotificationQueue);
+
+        this->size_ = 0;
+        this->tickTime_ = 0.0f;
+        this->maxSize_ = NotificationQueue::DEFAULT_SIZE;
+        this->displayTime_ = NotificationQueue::DEFAULT_DISPLAY_TIME;
+
+        this->creationTime_ = std::time(0);
+
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    NotificationQueue::~NotificationQueue()
+    {
+        this->targets_.clear();
+
+        if(this->isRegistered()) // If the NotificationQueue is registered.
+        {
+            this->clear(true);
+
+            // Unregister with the NotificationManager.
+            NotificationManager::getInstance().unregisterQueue(this);
+        }
+    }
+
+    /**
+    @brief
+        Is called when the name of the NotificationQueue has changed.
+        Clears and re-creates the NotificationQueue.
+    */
+    void NotificationQueue::changedName(void)
+    {
+        SUPER(NotificationQueue, changedName);
+
+        if(this->isRegistered())
+            this->clear();
+
+        this->create();
+
+        this->targetsChanged();
+        this->maxSizeChanged();
+        this->displayTimeChanged();
+    }
+
+    /**
+    @brief
+        Creates the NotificationQueue.
+    */
+    void NotificationQueue::create(void)
+    {
+        // Register the NotificationQueue with the NotificationManager.
+        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
+        this->registered_ = true;
+        if(!queueRegistered) // If the registration has failed.
+        {
+            this->registered_ = false;
+            orxout(internal_error, context::notifications) << "NotificationQueue '" << this->getName() << "' could not be registered." << endl;
+            return;
+        }
+
+        orxout(internal_info, context::notifications) << "NotificationQueue '" << this->getName() << "' created." << endl;
+    }
+
+    /**
+    @brief
+        Updates the queue from time to time.
+    @param dt
+        The time interval that has passed since the last tick.
+    */
+    void NotificationQueue::tick(float dt)
+    {
+        this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
+        if(this->displayTime_ != INF && this->tickTime_ >= 1.0) // If the time counter is greater than 1 s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
+        {
+            this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containing the current time.
+
+            std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin();
+            // Iterate through all elements whose creation time is smaller than the current time minus the display time.
+            while(it != this->ordering_.upper_bound(&this->timeLimit_))
+            {
+                this->remove(it); // Remove the Notifications that have expired.
+                it = this->ordering_.begin();
+            }
+
+            this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter.
+        }
+    }
+
+    void NotificationQueue::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(NotificationQueue, XMLPort, xmlelement, mode);
+
+        XMLPortParam(NotificationQueue, "targets", setTargets, getTargets, xmlelement, mode).defaultValues(NotificationListener::ALL);
+        XMLPortParam(NotificationQueue, "size", setMaxSize, getMaxSize, xmlelement, mode);
+        XMLPortParam(NotificationQueue, "displayTime", setDisplayTime, getDisplayTime, xmlelement, mode);
+    }
+
+
+    /**
+    @brief
+        Registers Variables to be Synchronised.
+        Registers Variables which have to be synchronised to the network system.
+      */
+    void NotificationQueue::registerVariables()
+    {
+        registerVariable( this->name_, VariableDirection::ToClient, new NetworkCallback<NotificationQueue>(this, &NotificationQueue::changedName));
+        registerVariable( this->maxSize_, VariableDirection::ToClient, new NetworkCallback<NotificationQueue>(this, &NotificationQueue::maxSizeChanged));
+        registerVariable( this->targets_, VariableDirection::ToClient, new NetworkCallback<NotificationQueue>(this, &NotificationQueue::targetsChanged));
+        registerVariable( this->displayTime_, VariableDirection::ToClient, new NetworkCallback<NotificationQueue>(this, &NotificationQueue::displayTimeChanged));
+    }
+
+    /**
+    @brief
+        Updates the NotificationQueue.
+        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
+        This is called by the NotificationManager when the Notifications have changed so much, that the NotificationQueue may have to re-initialize his operations.
+    */
+    void NotificationQueue::update(void)
+    {
+        this->clear();
+
+        std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
+        // Get the Notifications sent in the interval from now to now minus the display time.
+        if(this->displayTime_ == INF)
+            NotificationManager::getInstance().getNewestNotifications(this, notifications, this->getMaxSize());
+        else
+            NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
+
+        if(!notifications->empty())
+        {
+            // Add all Notifications that have been created after this NotificationQueue was created.
+            for(const auto& mapEntry : *notifications)
+            {
+                if(mapEntry.first >= this->creationTime_)
+                    this->push(mapEntry.second, mapEntry.first);
+            }
+        }
+
+        delete notifications;
+
+        orxout(verbose, context::notifications) << "NotificationQueue '" << this->getName() << "' updated." << endl;
+    }
+
+    /**
+    @brief
+        Updates the NotificationQueue by adding an new Notification.
+    @param notification
+        Pointer to the Notification.
+    @param time
+        The time the Notification was sent.
+    */
+    void NotificationQueue::update(Notification* notification, const std::time_t & time)
+    {
+        assert(notification);
+
+        this->push(notification, time);
+
+        orxout(verbose, context::notifications) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << endl;
+    }
+
+    /**
+    @brief
+        Adds (pushes) a Notification to the NotificationQueue.
+        It inserts it into the storage containers, creates a corresponding container and pushes the notification message to the GUI.
+    @param notification
+        The Notification to be pushed.
+    @param time
+        The time when the Notification has been sent.
+    */
+    void NotificationQueue::push(Notification* notification, const std::time_t & time)
+    {
+        assert(notification);
+
+        NotificationContainer* container = new NotificationContainer;
+        container->notification = notification;
+        container->time = time;
+
+        // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed.
+        if(this->getSize() >= this->getMaxSize())
+            this->pop();
+
+        this->size_++;
+
+        this->ordering_.insert(container);
+        // Insert the Notification at the begin of the list (vector, actually).
+        this->notifications_.insert(this->notifications_.begin(), container);
+
+        // Inform that a Notification was pushed.
+        this->notificationPushed(notification);
+
+        orxout(verbose_more, context::notifications) << "Notification \"" << notification->getMessage() << "\" pushed to NotificationQueue '" << this->getName() << "'" << endl;
+        orxout(internal_info, context::notifications) << "NotificationQueue \"" << this->getName() << "\": " << notification->getMessage() << endl;
+    }
+
+    /**
+    @brief
+        Removes (pops) the least recently added Notification form the NotificationQueue.
+    */
+    void NotificationQueue::pop(void)
+    {
+        NotificationContainer* container = this->notifications_.back();
+        // Get all the NotificationContainers that were sent the same time the NotificationContainer we want to pop was sent.
+        std::pair<std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator, std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator> iterators = this->ordering_.equal_range(container);
+
+        // Iterate through all suspects and remove the container as soon as we find it.
+        for(std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = iterators.first; it != iterators.second; it++)
+        {
+            if(container == *it)
+            {
+                orxout(verbose_more, context::notifications) << "Notification \"" << (*it)->notification->getMessage() << "\" popped from NotificationQueue '" << this->getName() << "'" << endl;
+                this->ordering_.erase(it);
+                break;
+            }
+        }
+        this->notifications_.pop_back();
+
+        this->size_--;
+
+        delete container;
+
+        // Inform that a Notification was popped.
+        this->notificationPopped();
+    }
+
+    /**
+    @brief
+        Removes the Notification that is stored in the input NotificationContainer.
+    @param containerIterator
+        An iterator to the NotificationContainer to be removed.
+    */
+    void NotificationQueue::remove(const std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator& containerIterator)
+    {
+        std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), *containerIterator);
+        // Get the index at which the Notification is.
+        std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin ();
+
+        orxout(verbose_more, context::notifications) << "Notification \"" << (*it)->notification->getMessage() << "\" removed from NotificationQueue '" << this->getName() << "'" << endl;
+
+        delete *containerIterator;
+
+        this->ordering_.erase(containerIterator);
+        this->notifications_.erase(it);
+
+        this->size_--;
+
+        // TODO: index automatically cast?
+        // Inform that a Notification was removed.
+        this->notificationRemoved(index);
+    }
+
+    /**
+    @brief
+        Clears the NotificationQueue by removing all NotificationContainers.
+    @param noGraphics
+        If this is set to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
+    */
+    void NotificationQueue::clear(bool noGraphics)
+    {
+        orxout(verbose, context::notifications) << "Clearing NotificationQueue " << this->getName() << "." << endl;
+        this->ordering_.clear();
+        // Delete all NotificationContainers in the list.
+        for(NotificationContainer* notification : this->notifications_)
+            delete notification;
+
+        this->notifications_.clear();
+        this->size_ = 0;
+    }
+
+    /**
+    @brief
+        Sets the name of the NotificationQueue.
+    @param name
+        The name to be set.
+    */
+    void NotificationQueue::setName(const std::string& name)
+    {
+        this->name_ = name;
+    }
+
+    /**
+    @brief
+        Sets the maximum number of displayed Notifications.
+    @param size
+        The size to be set.
+    */
+    void NotificationQueue::setMaxSize(unsigned int size)
+    {
+        if(this->maxSize_ == size)
+            return;
+
+        if(size == 0)
+        {
+            orxout(internal_warning, context::notifications) << "Trying to set maximal size of NotificationQueue '" << this->getName() << "' to 0. Ignoring..." << endl;
+            return;
+        }
+
+        this->maxSize_ = size;
+        this->maxSizeChanged();
+    }
+
+    /**
+    @brief
+        Is called when the maximum number of displayed Notifications has changed.
+    */
+    void NotificationQueue::maxSizeChanged(void)
+    {
+        if(this->isRegistered())
+            this->update();
+    }
+
+    /**
+    @brief
+        Sets the maximum number of seconds a Notification is displayed.
+    @param time
+        The number of seconds a Notification is displayed.
+    */
+    void NotificationQueue::setDisplayTime(int time)
+    {
+        if(this->displayTime_ == time)
+            return;
+
+        if(time != NotificationQueue::INF && time <= 0)
+        {
+            orxout(internal_warning, context::notifications) << "Trying to set display time of NotificationQueue '" << this->getName() << "' to non-positive value. Ignoring..." << endl;
+        }
+
+        this->displayTime_ = time;
+        this->displayTimeChanged();
+    }
+
+    /**
+    @brief
+        Is called when the maximum number of seconds a Notification is displayed has changed.
+    */
+    void NotificationQueue::displayTimeChanged(void)
+    {
+        if(this->isRegistered())
+            this->update();
+    }
+
+    /**
+    @brief
+        Produces all targets of the NotificationQueue concatenated as string, with commas (',') as separators.
+    @return
+        Returns the targets as a string.
+    */
+    const std::string& NotificationQueue::getTargets(void) const
+    {
+        std::stringstream stream;
+        bool first = true;
+        // Iterate through the set of targets.
+        for(const std::string& target : this->targets_)
+        {
+            if(!first)
+                stream << ", ";
+            else
+                first = false;
+            stream << target;
+        }
+
+        return *(new std::string(stream.str()));
+    }
+
+    /**
+    @brief
+        Sets the targets of the NotificationQueue.
+        The targets are the senders whose Notifications are displayed in this queue.
+    @param targets
+        Accepts a string of targets, each separated by commas (','), spaces are ignored.
+    */
+    void NotificationQueue::setTargets(const std::string & targets)
+    {
+        this->targets_.clear();
+
+        SubString string = SubString(targets, ",", " ", false);
+        for(unsigned int i = 0; i < string.size(); i++)
+            this->targets_.insert(string[i]);
+
+        this->targetsChanged();
+    }
+
+    /**
+    @brief
+        Is called when the NotificationQueue's targets have changed.
+    */
+    void NotificationQueue::targetsChanged(void)
+    {
+        // TODO: Why?
+        if(this->isRegistered())
+        {
+            NotificationManager::getInstance().unregisterQueue(this);
+            NotificationManager::getInstance().registerQueue(this);
+        }
+    }
+
+    /**
+    @brief
+        Pops all Notifications from the NotificationQueue.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool NotificationQueue::tidy(void)
+    {
+        while(this->size_ > 0)
+            this->pop();
+        return true;
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueue.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueue.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueue.h	(revision 11817)
@@ -0,0 +1,215 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationQueue.h
+    @brief Definition of the NotificationQueue class.
+    @ingroup Notifications
+*/
+
+#ifndef _NotificationOueue_H__
+#define _NotificationOueue_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include <ctime>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "NotificationManager.h"
+
+#include "core/BaseObject.h"
+#include "tools/interfaces/Tickable.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Container to allow easy handling of the @ref orxonox::Notification "Notifications".
+
+    @ingroup Notifications
+    */
+    struct NotificationContainer
+    {
+        Notification* notification; //!< The Notification displayed.
+        time_t time; //!< The time the Notification was sent and thus first displayed.
+    };
+
+    /**
+    @brief
+        Struct to allow ordering of @ref orxonox::NotificationContainer "NotificationContainers".
+
+    @ingroup Notifications
+    */
+    struct NotificationContainerCompare {
+        bool operator() (const NotificationContainer* const & a, const NotificationContainer* const & b) const
+            { return a->time < b->time; } //!< Ordering by time.
+    };
+
+    /**
+    @brief
+        Displays @ref orxonox::Notification "Notifications" from specific senders.
+
+        There are quite some parameters that influence the behavior of the NotificationQueue:
+        - @b name The name of the NotificationQueue. It needs to be unique.
+        - @b senders The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
+        - @b size The size of the NotificationQueue, it specifies how many @ref orxonox::Notification "Notifications" are displayed at once at the most.
+        - @b displayTime The time a @ref orxonox::Notification "Notification" is displayed with this NotificationQueue.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Notifications
+    */
+    class _NotificationsExport NotificationQueue : public BaseObject, public Tickable, public Synchronisable
+    {
+
+        public:
+            NotificationQueue(Context* context);
+            virtual ~NotificationQueue();
+
+            virtual void tick(float dt) override; // To update from time to time.
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedName(void) override;
+            
+            void update(void); // Updates the NotificationQueue.
+            void update(Notification* notification, const std::time_t & time); // Updates the NotificationQueue by adding an new Notification.
+
+            // tolua_begin
+            /**
+            @brief Get the name of the NotificationQueue.
+            @return Returns the name.
+            */
+            inline const std::string& getName(void) const
+                { return this->BaseObject::getName(); }
+
+            void setMaxSize(unsigned int size); // Sets the maximum number of displayed Notifications.
+            /**
+            @brief Returns the maximum number of Notifications displayed.
+            @return Returns maximum size.
+            */
+            inline unsigned int getMaxSize(void) const
+                { return this->maxSize_; }
+
+            void setDisplayTime(int time); // Sets the maximum number of seconds a Notification is displayed.
+            /**
+            @brief Returns the time interval the Notification is displayed.
+            @return Returns the display time.
+            */
+            inline int getDisplayTime(void) const
+                { return this->displayTime_; }
+            // tolua_end
+            void maxSizeChanged(void); // Is called when the maximum number of displayed Notifications has changed.
+            void displayTimeChanged(void);
+
+            /**
+            @brief Returns the current number of Notifications displayed.
+            @return Returns the size of the NotificationQueue.
+            */
+            inline unsigned int getSize(void) const
+                { return this->size_; }
+
+            /**
+            @brief Returns the targets of this NotificationQueue, reps. the senders which Notifications are displayed in this NotificationQueue.
+            @return Returns a set of strings holding the different targets.
+            */
+            inline const std::set<std::string> & getTargetsSet(void)
+                { return this->targets_; }
+
+            void setTargets(const std::string & targets); // Set the targets of this NotificationQueue.
+            const std::string& getTargets(void) const; // Returns a string consisting of the concatenation of the targets.
+            void targetsChanged(void); // Is called when the NotificationQueue's targets have changed.
+
+            /**
+            @brief Check whether the NotificationQueue is registered with the NotificationManager.
+            @return Returns true if it is registered, false if not.
+            */
+            inline bool isRegistered(void)
+                { return this->registered_; }
+
+            bool tidy(void); // Pops all Notifications from the NotificationQueue.
+            
+        protected:
+            void registerVariables();
+            
+            /**
+            @brief Is called when a notification was pushed.
+            @param notification The Notification that was pushed.
+            */
+            virtual void notificationPushed(Notification* notification) {}
+            /**
+            @brief Is called when a notification was popped.
+            */
+            virtual void notificationPopped(void) {}
+            /**
+            @brief Is called when a notification was removed.
+            @param index The index the removed notification was at.
+            */
+            virtual void notificationRemoved(unsigned int index) {}
+            
+            virtual void clear(bool noGraphics = false); // Clears the NotificationQueue by removing all NotificationContainers.
+
+        protected:
+            static const unsigned int DEFAULT_SIZE = 5; //!< The default maximum number of Notifications displayed.
+            static const unsigned int DEFAULT_DISPLAY_TIME = 30; //!< The default display time.
+            static const int INF = -1; //!< Constant denoting infinity.
+
+            virtual void create(void); // Creates the NotificationQueue.
+
+        private:
+            time_t creationTime_; //!< The time this NotificationQueue was created.
+            
+            unsigned int maxSize_; //!< The maximal number of Notifications displayed.
+            unsigned int size_; //!< The number of Notifications displayed.
+            int displayTime_; //!< The time a Notification is displayed.
+
+            bool registered_; //!< Helper variable to remember whether the NotificationQueue is registered already.
+
+            std::set<std::string> targets_; //!< The targets the NotificationQueue displays Notifications of.
+
+            std::multiset<NotificationContainer*, NotificationContainerCompare> ordering_; //!< The NotificationContainers ordered by the time they were registered.
+            std::vector<NotificationContainer*> notifications_; //!< The NotificationContainers in the order they were added to the NotificationQueue.
+
+            float tickTime_; //!< Helper variable, to not have to check for Notifications that have been displayed too long, every tick.
+            NotificationContainer timeLimit_; //!< Helper object to check against to determine whether Notifications have expired.
+
+            void setName(const std::string& name); //!< Sets the name of the NotificationQueue.
+
+            void push(Notification* notification, const std::time_t & time); // Adds (pushes) a Notification to the NotificationQueue.
+            void pop(void); // Removes (pops) the least recently added Notification form the NotificationQueue.
+            void remove(const std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator& containerIterator); // Removes the Notification that is stored in the input NotificationContainer.
+
+    };
+
+}
+
+#endif /* _NotificationQueue_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueueCEGUI.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueueCEGUI.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueueCEGUI.cc	(revision 11817)
@@ -0,0 +1,368 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationQueueCEGUI.cc
+    @brief Implementation of the NotificationQueueCEGUI class.
+*/
+
+#include "NotificationQueueCEGUI.h"
+
+#include <sstream>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/GUIManager.h"
+#include "core/LuaState.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+
+    RegisterClass(NotificationQueueCEGUI);
+
+    /*static*/ const std::string NotificationQueueCEGUI::NOTIFICATION_LAYER("NotificationLayer");
+
+    NotificationQueueCEGUI::NotificationQueueCEGUI(Context* context) : NotificationQueue(context)
+    {
+        RegisterObject(NotificationQueueCEGUI);
+
+        this->initialize();
+        this->registerVariables();
+    }
+    
+    NotificationQueueCEGUI::~NotificationQueueCEGUI()
+    {
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".removeQueue(\"" + this->getName() +  "\")");
+    }
+
+    /**
+    @brief
+        Initializes The NotificationQueueCEGUI.
+    */
+    void NotificationQueueCEGUI::initialize(void)
+    {
+        this->displaySize_ = Vector4(1.0, 0.0, 0.0, 0.0);
+        this->position_ = Vector4(0.0, 0.0, 0.0, 0.0);
+        this->alignment_ = "LeftAligned";
+        this->fontSize_ = 10;
+        this->fontColor_ = Vector4(1.0, 1.0, 1.0, 1.0);
+        this->fontColorStr_ = "FFFFFFFF";
+    }
+
+    void NotificationQueueCEGUI::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(NotificationQueueCEGUI, XMLPort, xmlelement, mode);
+
+        XMLPortParam(NotificationQueueCEGUI, "position", setPosition, getPosition, xmlelement, mode);
+        XMLPortParam(NotificationQueueCEGUI, "fontSize", setFontSize, getFontSize, xmlelement, mode);
+        XMLPortParam(NotificationQueueCEGUI, "fontColor", setFontColor, getFontColor, xmlelement, mode);
+        XMLPortParam(NotificationQueueCEGUI, "alignment", setAlignment, getAlignment, xmlelement, mode);
+        XMLPortParam(NotificationQueueCEGUI, "displaySize", setDisplaySize, getDisplaySize, xmlelement, mode);
+    }
+    
+    void NotificationQueueCEGUI::registerVariables()
+    {
+        registerVariable( this->position_, VariableDirection::ToClient, new NetworkCallback<NotificationQueueCEGUI>(this, &NotificationQueueCEGUI::positionChanged));
+        registerVariable( this->fontSize_, VariableDirection::ToClient, new NetworkCallback<NotificationQueueCEGUI>(this, &NotificationQueueCEGUI::fontSizeChanged));
+        registerVariable( this->fontColor_, VariableDirection::ToClient, new NetworkCallback<NotificationQueueCEGUI>(this, &NotificationQueueCEGUI::fontColorChanged));
+        registerVariable( this->alignment_, VariableDirection::ToClient, new NetworkCallback<NotificationQueueCEGUI>(this, &NotificationQueueCEGUI::alignmentChanged));
+        registerVariable( this->displaySize_, VariableDirection::ToClient, new NetworkCallback<NotificationQueueCEGUI>(this, &NotificationQueueCEGUI::displaySizeChanged));
+    }
+
+    void NotificationQueueCEGUI::changedName(void)
+    {
+        SUPER(NotificationQueueCEGUI, changedName);
+
+        this->positionChanged();
+        this->fontSizeChanged();
+        this->fontColorChanged();
+        this->alignmentChanged();
+        this->displaySizeChanged();
+    }
+
+    /**
+    @brief
+        Destroys the NotificationQueueCEGUI.
+        Used in lua and NotificationManager.
+    @param noGraphics
+        If this is set to true (false is default), then the queue is not removed in lua. This is used to destroy the queue, after the GUIManager has been destroyed.
+    */
+    void NotificationQueueCEGUI::destroy(bool noGraphics)
+    {
+        // Remove the NotificationQueue in lua.
+        if(this->isRegistered() && GameMode::showsGraphics() && !noGraphics)
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".removeQueue(\"" + this->getName() +  "\")");
+
+        NotificationQueue::destroy();
+    }
+
+    /**
+    @brief
+        Set the size of the window that displays the NotificationQueue.
+    @param size
+        The size is a vector with components:
+        - The relative width of the window. (A value between 0 and 1)
+        - The absolute width in pixels. (Additional to the relative width, can be negative)
+        - The relative height of the window. (A value between 0 and 1)
+        - The absolute height in pixels. (Additional to the relative width, can be negative.)
+        If both the 3rd and 4th component of size are set to 0 the height is set such that exactly as many Notifications fit as is the maximum size of the NotificationQueue (in terms of the number of Notifications).
+    */
+    void NotificationQueueCEGUI::setDisplaySize(const Vector4& size)
+    {
+        if(this->displaySize_ == size)
+            return;
+
+        if(size.x < 0.0 || size.x > 1.0 || size.z < 0.0 || size.z > 1.0)
+        {
+            orxout(internal_warning, context::notifications) << "The display size of the NotificationQueueCEGUI " << this->getName() << " was trying to be set, but the relative size was not in [0,1]. Aborting..." << endl;
+            return;
+        }
+
+        this->displaySize_ = size;
+        this->displaySizeChanged();
+    }
+
+    /**
+    @brief
+        Is called when the display size has changed.
+    */
+    void NotificationQueueCEGUI::displaySizeChanged(void)
+    {
+        if(this->isRegistered() && GameMode::showsGraphics())
+        {
+            if(this->displaySize_.z == 0.0 && this->displaySize_.w == 0.0)
+                GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".resizeQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->displaySize_.x) + ", " + multi_cast<std::string>(this->displaySize_.y) + ")");
+            else
+                GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".resizeQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->displaySize_.x) + ", " + multi_cast<std::string>(this->displaySize_.y) + ", " + multi_cast<std::string>(this->displaySize_.z) + ", " + multi_cast<std::string>(this->displaySize_.w) + ")");
+        }
+    }
+
+    /**
+    @brief
+        Set the position of the window that displays the NotificationQueue.
+    @param position
+        The position is a vector with components:
+        - The relative x-position of the window. (A value between 0 and 1)
+        - The absolute x-position in pixels. (Additional to the relative x-position, can be negative)
+        - The relative y-position of the window. (A value between 0 and 1)
+        - The absolute y-position in pixels. (Additional to the relative y-position, can be negative.)
+    */
+    void NotificationQueueCEGUI::setPosition(const Vector4& position)
+    {
+        if(this->position_ == position)
+            return;
+
+        if(position.x < 0.0 || position.x > 1.0 || position.z < 0.0 || position.z > 1.0)
+        {
+            orxout(internal_warning, context::notifications) << "The position the NotificationQueueCEGUI " << this->getName() << " was trying to be set, but the relative position was not in [0,1]. Aborting..." << endl;
+            return;
+        }
+
+        this->position_ = position;
+        this->positionChanged();
+    }
+
+    /**
+    @brief
+        Is called when the NotificationQueue's position has changed.
+    */
+    void NotificationQueueCEGUI::positionChanged(void)
+    {
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".moveQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->position_.x) + ", " + multi_cast<std::string>(this->position_.y) + ", " + multi_cast<std::string>(this->position_.z) + ", " + multi_cast<std::string>(this->position_.w) + ")");
+    }
+
+    /**
+    @brief
+        Set the horizontal alignment of the Notifications text.
+    @param alignment
+        The alignment of the Notifications, they are the possible string that the CEGUI Falagard StaticText HorzFormatting property can take.
+    @see http://cegui.org.uk/api_reference/classCEGUI_1_1FalagardStaticTextProperties_1_1HorzFormatting.html
+    */
+    void NotificationQueueCEGUI::setAlignment(const std::string& alignment)
+    {
+        if(this->alignment_ == alignment)
+            return;
+
+        // TODO: Check whether the alignment string is correct?
+        this->alignment_ = alignment;
+        this->alignmentChanged();
+    }
+
+    /**
+    @brief
+        Is called when the horizontal alignment of the Notifications text has changed.
+    */
+    void NotificationQueueCEGUI::alignmentChanged(void)
+    {
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".changeQueueAlignment(\"" + this->getName() + "\", \"" + this->alignment_ + "\")");
+    }
+
+    /**
+    @brief
+        Set the font size of the text displayed by this NotificationQueue.
+    @param size
+        The font size.
+    */
+    void NotificationQueueCEGUI::setFontSize(unsigned int size)
+    {
+        if(this->fontSize_ == size)
+            return;
+
+        this->fontSize_ = size;
+        this->fontSizeChanged();
+    }
+
+    /**
+    @brief
+        Is called when the font size of the text displayed by this NotificationQueue has changed.
+    */
+    void NotificationQueueCEGUI::fontSizeChanged(void)
+    {
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".changeQueueFontSize(\"" + this->getName() + "\", " + multi_cast<std::string>(this->fontSize_) + ")");
+    }
+
+    /**
+    @brief
+        Set the font color if the text displayed by this NotificationQueue.
+    @param color
+        The color is a vector with the components being RGBA and taking values from 0 to 1.
+    */
+    void NotificationQueueCEGUI::setFontColor(const Vector4& color)
+    {
+        if(this->fontColor_ == color)
+            return;
+
+        this->fontColor_ = color;
+        this->fontColorChanged();
+    }
+
+    /**
+    @brief
+        Is called when the font color if the text displayed by this NotificationQueue.
+    */
+    void NotificationQueueCEGUI::fontColorChanged(void)
+    {
+        // Convert to ARGB format.
+        std::stringstream stream;
+        for(unsigned int i = 0; i < 4; i++)
+            stream << std::hex << std::setw(2) << std::setfill('0') << int(this->fontColor_[(i+3)%4]*255);
+        this->fontColorStr_ = stream.str();
+
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".changeQueueFontColor(\"" + this->getName() + "\", \"" + this->fontColorStr_ + "\")");
+    }
+
+    /**
+    @brief
+        Get the NotificationQueueCEGUI with the input name.
+    @param name
+        The name of the NotificationQueueCEGUI to be got.
+    @return
+        Returns a pointer to the NotificationQueueCEGUI, or nullptr if it doesn't exist.
+    */
+    /*static*/ NotificationQueueCEGUI* NotificationQueueCEGUI::getQueue(const std::string& name)
+    {
+        NotificationQueue* queue = NotificationManager::getInstance().getQueue(name);
+        if(queue == nullptr || !queue->isA(Class(NotificationQueueCEGUI)))
+            return nullptr;
+        return static_cast<NotificationQueueCEGUI*>(queue);
+    }
+
+    /**
+    @brief
+        Is called by the NotificationQueue when a Notification was pushed.
+    @param notification
+        The Notification that was pushed.
+    */
+    void NotificationQueueCEGUI::notificationPushed(Notification* notification)
+    {
+         // Push the Notification to the GUI.
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")");
+    }
+
+    /**
+    @brief
+        Is called by the NotificationQueue when a Notification was popped.
+    */
+    void NotificationQueueCEGUI::notificationPopped(void)
+    {
+        // Pops the Notification from the GUI.
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".popNotification(\"" + this->getName() + "\")");
+    }
+
+    /**
+    @brief Is called when a notification was removed.
+    @param index The index the removed Notification was at.
+    */
+    void NotificationQueueCEGUI::notificationRemoved(unsigned int index)
+    {
+        // Removes the Notification from the GUI.
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")");
+    }
+
+    /**
+    @brief
+        Clears the NotificationQueue by removing all NotificationContainers.
+    @param noGraphics
+        If this is set to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
+    */
+    void NotificationQueueCEGUI::clear(bool noGraphics)
+    {
+        NotificationQueue::clear(noGraphics);
+
+        // Clear the NotificationQueue in the GUI.
+        if(this->isRegistered() && GameMode::showsGraphics() && !noGraphics)
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".clearQueue(\"" + this->getName() + "\")");
+    }
+
+    /**
+    @brief
+        Creates the NotificationQueue in lua.
+    */
+    void NotificationQueueCEGUI::create(void)
+    {
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".removeQueue(\"" + this->getName() +  "\")");
+        
+        this->NotificationQueue::create();
+        
+        if(this->isRegistered() && GameMode::showsGraphics())
+            GUIManager::getInstance().getLuaState()->doString(NotificationQueueCEGUI::NOTIFICATION_LAYER + ".createQueue(\"" + this->getName() +  "\", " + multi_cast<std::string>(this->getMaxSize()) + ")");
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueueCEGUI.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueueCEGUI.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationQueueCEGUI.h	(revision 11817)
@@ -0,0 +1,163 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationQueueCEGUI.h
+    @brief Definition of the NotificationQueueCEGUI class.
+    @ingroup Notifications
+*/
+
+#ifndef _NotificationOueueCEGUI_H__
+#define _NotificationOueueCEGUI_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include <string>
+#include "util/Math.h"
+
+#include "NotificationManager.h"
+
+#include "NotificationQueue.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        Displays @ref orxonox::Notification "Notifications" using CEGUI.
+
+        Apart form the parameters inherited by the @ref orxonox::NotificationQueue "NotificationQueue", there are some more parameters that influence the behavior of the NotificationQueueCEGUI:
+        - @b displaySize The size of the window that displays the NotificationQueue.
+        - @b position The position if the window that displays the NotificationQueue.
+        - @b alignment The horizontal alignment of the displayed Notifications.
+        - @b fontSize The font size of the displayed Notifications.
+        - @b fontColor The font color of the displayed Notifications.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @see NotificationQueue
+    @ingroup Notifications
+    */
+    class _NotificationsExport NotificationQueueCEGUI // tolua_export
+        : public NotificationQueue
+    { // tolua_export
+
+        public:
+            NotificationQueueCEGUI(Context* context);
+            virtual ~NotificationQueueCEGUI();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedName(void) override;
+
+            void destroy(bool noGraphics = false); // Destroys the NotificationQueue.
+
+            void setDisplaySize(const Vector4& size); // Set the size of the window that displays the NotificationQueue.
+            
+            /**
+            @brief Get the size of the window that displays the NotificationQueue.
+            @return Returns a vector with the display size.
+            */
+            inline const Vector4& getDisplaySize(void) const
+                { return this->displaySize_; }
+            void displaySizeChanged(void); // Is called when the display size has changed.
+
+            void setPosition(const Vector4& position); // Set the position of the window that displays the NotificationQueue.
+            /**
+            @brief Get the position of the window that displays the NotificationQueue.
+            @return Returns a vector with the position.
+            */
+            inline const Vector4& getPosition(void) const
+                { return this->position_; }
+            void positionChanged(void); // Is called when the NotificationQueue's position has changed.
+
+            void setAlignment(const std::string& alignment); // Set the horizontal alignment of the Notifications text.
+            /**
+            @brief Get the horizontal alignment of the Notifications text.
+            @return Returns a string with the horizontal alignment property.
+            */
+            inline const std::string& getAlignment(void)
+                { return this->alignment_; }
+            void alignmentChanged(void); // Is called when the horizontal alignment of the Notifications text has changed.
+
+            void setFontSize(unsigned int size); // Set the font size of the text displayed by this NotificationQueue.
+            /**
+            @brief Get the font size of the text displayed by this NotificationQueue.
+            @return Returns the font size.
+            */
+            inline unsigned int getFontSize(void)
+                { return this->fontSize_; }
+            void fontSizeChanged(void); // Is called when the font size of the text displayed by this NotificationQueue has changed.
+
+            void setFontColor(const Vector4& color); // Set the font color if the text displayed by this NotificationQueue.
+            /**
+            @brief Get the font color of the text displayed by this NotificationQueue.
+            @return Returns a vector with the components being RGBA, with values from 0 to 1.
+            */
+            inline const Vector4& getFontColor(void) const
+                { return this->fontColor_; }
+            /**
+            @brief Get the font color of the text displayed by this NotificationQueue.
+            @return Returns a string with the ARGB values in hexadecimal format.
+            */
+            inline const std::string& getFontColorStr(void) const
+                { return this->fontColorStr_; }
+            void fontColorChanged(void); // Is called when the font color if the text displayed by this NotificationQueue has changed.
+
+            static NotificationQueueCEGUI* getQueue(const std::string& name); // tolua_export // Get the NotificationQueueCEGUI with the input name.
+            
+        protected:
+            void registerVariables();
+            
+            virtual void create(void) override; // Creates the NotificationQueue in lua.
+            
+            virtual void notificationPushed(Notification* notification) override; // Is called by the NotificationQueue when a Notification was pushed
+            virtual void notificationPopped(void) override; // Is called by the NotificationQueue when a Notification was popped.
+            virtual void notificationRemoved(unsigned int index) override; // Is called when a Notification was removed.
+            
+            virtual void clear(bool noGraphics = false) override; // Clears the NotificationQueue by removing all NotificationContainers.
+
+        protected:
+            static const std::string NOTIFICATION_LAYER; //!< The name of the NotificationLayer menu sheet.
+            
+        private:
+            Vector4 displaySize_; //!< The size of the window that displays the NotificationQueue.
+            Vector4 position_; //!< The position of the window that displays the NotificationQueue.
+            std::string alignment_; //!< The horizontal alignment of the Notifications text.
+            unsigned int fontSize_; //!< The font size of the Notifications text.
+            Vector4 fontColor_; //!< The font color of the Notifications text as a vector, in RGBA form, with values from 0 to 1.
+            std::string fontColorStr_; //!< The font color of the Notifications text as a string with the ARGB hexadecimal values.
+
+            void initialize(void); // Initializes The NotificationQueueCEGUI.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _NotificationQueueCEGUI_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationsPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationsPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationsPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btTransform.h>
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/notifications/NotificationsPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/NotificationsPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/NotificationsPrereqs.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _NotificationsPrereqs_H__
+#define _NotificationsPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(NOTIFICATIONS_STATIC_BUILD)
+#  ifdef NOTIFICATIONS_SHARED_BUILD
+#    define _NotificationsExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _NotificationsExport
+#    else
+#      define _NotificationsExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _NotificationsPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _NotificationsExport  __attribute__ ((visibility("default")))
+#  define _NotificationsPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _NotificationsExport
+#  define _NotificationsPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Notification;
+    class NotificationDispatcher;
+    class NotificationManager;
+    class NotificationQueue;
+    
+    //dispatchers
+    class CommandNotification;
+    class SimpleNotification;
+}
+
+#endif /* _NotificationsPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,4 @@
+ADD_SOURCE_FILES(NOTIFICATIONS_SRC_FILES
+  CommandNotification.cc
+  SimpleNotification.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CommandNotification.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CommandNotification.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CommandNotification.cc	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CommandNotification.cc
+    @brief Implementation of the CommandNotification class.
+*/
+
+#include "CommandNotification.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/input/KeyBinderManager.h"
+#include "core/input/KeyBinder.h"
+#include "util/SubString.h"
+
+#include <sstream>
+
+namespace orxonox {
+
+    RegisterClass(CommandNotification);
+
+    /**
+    @brief
+        Default Constructor. Registers the object and initializes variables.
+    */
+    CommandNotification::CommandNotification(Context* context) : NotificationDispatcher(context)
+    {
+        RegisterObject(CommandNotification);
+
+        this->setSender("commandNotification");
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    CommandNotification::~CommandNotification()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a NotificationDispatcher object through XML.
+    */
+    void CommandNotification::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CommandNotification, XMLPort, xmlelement, mode);
+
+        XMLPortParam(CommandNotification, "command", setCommand, getCommand, xmlelement, mode);
+        XMLPortParam(CommandNotification, "preMessage", setPreMessage, getPreMessage, xmlelement, mode);
+        XMLPortParam(CommandNotification, "postMessage", setPostMessage, getPostMessage, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Register some variables for synchronisation.
+    */
+    void CommandNotification::registerVariables(void)
+    {
+        registerVariable(this->command_, VariableDirection::ToClient);
+        registerVariable(this->preMessage_, VariableDirection::ToClient);
+        registerVariable(this->postMessage_, VariableDirection::ToClient);
+    }
+
+    /**
+    @brief
+        Composes the Notification of the preMessage the name of the key the command is mapped to and the postMessage.
+    @return
+        Returns the message to be sent in the Notification.
+    */
+    const std::string& CommandNotification::createNotificationMessage(void)
+    {
+        std::stringstream stream;
+        stream << this->getPreMessage();
+        stream << KeyBinderManager::getInstance().getCurrent()->getBindingReadable(this->getCommand());
+        stream << this->getPostMessage();
+        return *(new std::string(stream.str()));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CommandNotification.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CommandNotification.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/CommandNotification.h	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CommandNotification.h
+    @brief Definition of the CommandNotification class.
+    @ingroup NotificationDispatchers
+*/
+
+#ifndef _CommandNotification_H__
+#define _CommandNotification_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include <string>
+#include "notifications/NotificationDispatcher.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        This class implements a method of displaying a Notification with information to an input command and the key the command is mapped to.
+        The message that is displayed is a string made out of the concatenation of the preMessage, the key the specified command is mapped to and the postMessage.
+
+        In use it would like this:
+        @code
+        <CommandNotification preMessage="Please press " command="someCommand" postMessage=" to do something." sender="me">
+            <events>
+                <trigger>
+                    <PlayerTrigger />
+                </trigger>
+            </events>
+        </CommandNotification>
+        @endcode
+        Upon being triggered this would display the @ref orxonox::Notification "Notification" "Please press {the binding of the specified command} to do something".
+        For more information on what can be used for @code <PlayerTrigger /> @endcode see the @ref orxonox::NotificationDispatcher "NotificationDispatcher" documentation.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup NotificationDispatchers
+    */
+    class _NotificationsExport CommandNotification : public NotificationDispatcher
+    {
+
+        public:
+            CommandNotification(Context* context); //!< Default Constructor.
+            virtual ~CommandNotification(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a CommandNotification object through XML.
+
+            /**
+            @brief Get the command, whose key is displayed.
+            @return Returns the name of the command.
+            */
+            const std::string& getCommand(void)
+                { return this->command_; }
+            /**
+            @brief Get the preMessage, the first part of the displayed message.
+            @return Returns the preMessage.
+            */
+            const std::string& getPreMessage(void)
+                { return this->preMessage_; }
+            /**
+            @brief Get the postMessage, the last part of the displayed message.
+            @return Returns the postMessage.
+            */
+            const std::string& getPostMessage(void)
+                { return this->postMessage_; }
+
+        protected:
+            virtual const std::string& createNotificationMessage(void); //!< Composes the Notification of the preMessage the name of the key the command is mapped to and the postMessage.
+
+        private:
+            std::string command_; //!< The name of the command.
+            std::string preMessage_; //!< The first part of the displayed message.
+            std::string postMessage_; //!< The last part of the displayed message.
+
+            void registerVariables(void); //!< Register some variables for synchronisation.
+
+            /**
+            @brief Set the command, whose key is displayed.
+            @param command The name of the command.
+            */
+            void setCommand(const std::string& command)
+                { this->command_ = command; }
+            /**
+            @brief Set the preMessage, the first part of the displayed message.
+            @param message The preMessage.
+            */
+            void setPreMessage(const std::string& message)
+                { this->preMessage_ = message; }
+            /**
+            @brief Set the postMessage, the last part of the displayed message.
+            @param message The postMessage.
+            */
+            void setPostMessage(const std::string& message)
+                 { this->postMessage_ = message; }
+    };
+
+}
+
+#endif // _CommandNotification_H__
Index: /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/SimpleNotification.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/SimpleNotification.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/SimpleNotification.cc	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SimpleNotification.cc
+    @brief Implementation of the SimpleNotification class.
+*/
+
+#include "SimpleNotification.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox {
+
+    RegisterClass(SimpleNotification);
+
+    /**
+    @brief
+        Default Constructor. Registers the object and initializes variables.
+    */
+    SimpleNotification::SimpleNotification(Context* context) : NotificationDispatcher(context)
+    {
+        RegisterObject(SimpleNotification);
+
+        this->setSender("simpleNotification");
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    SimpleNotification::~SimpleNotification()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a SimpleNotification object through XML.
+    */
+    void SimpleNotification::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SimpleNotification, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SimpleNotification, "message", setMessage, getMessage, xmlelement, mode);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/SimpleNotification.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/SimpleNotification.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/notifications/dispatchers/SimpleNotification.h	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SimpleNotification.h
+    @brief Declaration of the SimpleNotification class.
+    @ingroup NotificationDispatchers
+*/
+
+#ifndef _SimpleNotification_H__
+#define _SimpleNotification_H__
+
+#include "notifications/NotificationsPrereqs.h"
+
+#include "notifications/NotificationDispatcher.h"
+#include <string>
+
+namespace orxonox {
+
+    /**
+    @brief
+        The SimpleNotification class enables the sending of (in XML) predefined Notifications upon some kind of triggering event.
+
+        In use it would like this:
+        @code
+        <SimpleNotification message="some message..." sender="me">
+            <events>
+                <trigger>
+                    <PlayerTrigger />
+                </trigger>
+            </events>
+        </SimpleNotification>
+        @endcode
+        For more information on what can be used for @code <PlayerTrigger /> @endcode see the @ref orxonox::NotificationDispatcher "NotificationDispatcher" documentation.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup NotificationDispatchers
+    */
+    class _NotificationsExport SimpleNotification : public NotificationDispatcher
+    {
+        public:
+            SimpleNotification(Context* context); //!< Default Constructor.
+            virtual ~SimpleNotification(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a SimpleNotification object through XML.
+
+            /**
+            @brief Get the message, that is displayed.
+            @return Returns the message, that is displayed.
+            */
+            const std::string& getMessage(void)
+                { return this->message_; }
+
+        protected:
+            /**
+            @brief Creates the notification message that should be sent upon the SimpleNotification triggering.
+            @return Returns the notification message.
+            */
+            virtual const std::string& createNotificationMessage(void)
+                { return this->message_; }
+
+        private:
+            std::string message_; //!< The message that is displayed.
+
+            /**
+            @brief Sets the message that is to be displayed.
+            @param message The message to be displayed.
+            */
+            void setMessage(const std::string& message)
+                { this->message_ = message; }
+    };
+
+}
+
+#endif // _SimpleNotification_H__
Index: /code/branches/RacingBots_FS18/src/modules/objects/Attacher.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Attacher.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Attacher.cc	(revision 11817)
@@ -0,0 +1,125 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Attacher.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(Attacher);
+
+    Attacher::Attacher(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Attacher);
+
+        this->target_ = nullptr;
+    }
+
+    void Attacher::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Attacher, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Attacher, "target", setTarget, getTarget, xmlelement, mode);
+        XMLPortObject(Attacher, WorldEntity, "", addObject, getObject, xmlelement, mode);
+    }
+
+    void Attacher::processEvent(Event& event)
+    {
+        if (this->target_)
+            this->target_->processEvent(event);
+    }
+
+    void Attacher::changedActivity()
+    {
+        SUPER(Attacher, changedActivity);
+
+        for (WorldEntity* object : this->objects_)
+            object->setActive(this->isActive());
+    }
+
+    void Attacher::changedVisibility()
+    {
+        SUPER(Attacher, changedVisibility);
+
+        for (WorldEntity* object : this->objects_)
+            object->setVisible(this->isVisible());
+    }
+
+    void Attacher::addObject(WorldEntity* object)
+    {
+        this->objects_.push_back(object);
+
+        this->attach(object);
+    }
+
+    WorldEntity* Attacher::getObject(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (WorldEntity* object : this->objects_)
+        {
+            if (i == index)
+                return object;
+
+            ++i;
+        }
+        return nullptr;
+    }
+
+    void Attacher::setTarget(const std::string& target)
+    {
+        this->targetname_ = target;
+        this->target_ = nullptr;
+
+        if (this->targetname_.empty())
+            return;
+
+        for (WorldEntity* worldEntity : ObjectList<WorldEntity>())
+        {
+            if (worldEntity->getName() == this->targetname_)
+            {
+                this->target_ = worldEntity;
+                this->attachToParent(worldEntity);
+            }
+        }
+    }
+
+    void Attacher::loadedNewXMLName(BaseObject* object)
+    {
+        if (this->target_ || this->targetname_.empty())
+            return;
+
+        WorldEntity* entity = orxonox_cast<WorldEntity*>(object);
+        if (entity && entity->getName() == this->targetname_)
+        {
+            this->target_ = entity;
+            this->attachToParent(entity);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/Attacher.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Attacher.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Attacher.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Attacher.h
+    @brief Definition of the Attacher class.
+    @ingroup Objects
+*/
+
+#ifndef _Attacher_H__
+#define _Attacher_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <list>
+#include <string>
+#include "core/XMLNameListener.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _ObjectsExport Attacher : public StaticEntity, public XMLNameListener
+    {
+        public:
+            Attacher(Context* context);
+            virtual ~Attacher() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void processEvent(Event& event) override;
+            virtual void changedActivity() override;
+            virtual void changedVisibility() override;
+
+            void addObject(WorldEntity* object);
+            WorldEntity* getObject(unsigned int index) const;
+
+            void setTarget(const std::string& target);
+            inline const std::string& getTarget() const
+                { return this->targetname_; }
+
+            virtual void loadedNewXMLName(BaseObject* object) override;
+
+        private:
+            WorldEntity* target_;
+            std::string targetname_;
+            std::list<WorldEntity*> objects_;
+    };
+}
+
+#endif /* _Attacher_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,23 @@
+SET_SOURCE_FILES(OBJECTS_SRC_FILES
+  Attacher.cc
+  ForceField.cc
+  Planet.cc
+  Script.cc
+  SpaceBoundaries.cc
+  Turret.cc
+)
+
+ADD_SUBDIRECTORY(collisionshapes)
+ADD_SUBDIRECTORY(eventsystem)
+ADD_SUBDIRECTORY(triggers)
+ADD_SUBDIRECTORY(controllers)
+
+ORXONOX_ADD_LIBRARY(objects
+  MODULE
+  FIND_HEADER_FILES
+  PCH_FILE
+    ObjectsPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${OBJECTS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/objects/ForceField.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/ForceField.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/ForceField.cc	(revision 11817)
@@ -0,0 +1,274 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      Kevin Young
+ *
+ */
+
+/**
+    @file ForceField.cc
+    @brief Implementation of the ForceField class.
+*/
+
+#include "ForceField.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "worldentities/MobileEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(ForceField);
+
+    /*static*/ const std::string ForceField::modeTube_s = "tube";
+    /*static*/ const std::string ForceField::modeSphere_s = "sphere";
+    /*static*/ const std::string ForceField::modeInvertedSphere_s = "invertedSphere";
+
+    /*static*/ const std::string ForceField::modeHomogen_s = "homogen";
+
+    /*static*/ const std::string ForceField::modeNewtonianGravity_s = "newtonianGravity";
+    /*static*/ const float ForceField::gravConstant_ = 6.673e-11;
+    /*static*/ const float ForceField::attenFactor_ = 1;
+
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes some values.
+    */
+    ForceField::ForceField(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(ForceField);
+
+        //Standard Values
+        this->setDirection(Vector3::ZERO);
+        this->setFieldVelocity(100);
+        this->setDiameter(500);
+        this->setMassDiameter(0);   //! We allow point-masses
+        this->setLength(2000);
+        this->mode_ = ForceFieldMode::tube;
+        
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    ForceField::~ForceField()
+    {
+    }
+
+    /**
+    @brief
+        Creates a ForceField object through XML.
+    */
+    void ForceField::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ForceField, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ForceField, "velocity", setFieldVelocity, getFieldVelocity, xmlelement, mode).defaultValues(100);
+        XMLPortParam(ForceField, "diameter", setDiameter, getDiameter, xmlelement, mode).defaultValues(500);
+        XMLPortParam(ForceField, "massDiameter", setMassDiameter, getMassDiameter, xmlelement, mode).defaultValues(0);
+        XMLPortParam(ForceField, "length", setLength  , getLength  , xmlelement, mode).defaultValues(2000);
+        XMLPortParam(ForceField, "mode", setMode, getMode, xmlelement, mode);
+        XMLPortParam(ForceField, "forcedirection", setForceDirection, getForceDirection, xmlelement, mode).defaultValues(Vector3(0,-400,0));
+    }
+    
+    void ForceField::registerVariables()
+    {
+        registerVariable(this->velocity_, VariableDirection::ToClient);
+        registerVariable(this->radius_, VariableDirection::ToClient);
+        registerVariable(this->massRadius_, VariableDirection::ToClient);
+        registerVariable(this->halfLength_, VariableDirection::ToClient);
+        registerVariable(this->mode_, VariableDirection::ToClient);
+    }
+
+
+    /**
+    @brief
+        A method that is called every tick.
+        Implements the behavior of the ForceField.
+    @param dt
+        The amount of time that elapsed since the last tick.
+    */
+    void ForceField::tick(float dt)
+    {
+        if(this->mode_ == ForceFieldMode::tube)
+        {
+            // Iterate over all objects that could possibly be affected by the ForceField.
+            for (MobileEntity* mobileEntity : ObjectList<MobileEntity>())
+            {
+                // The direction of the orientation of the force field.
+                Vector3 direction = this->getOrientation() * WorldEntity::FRONT;
+                direction.normalise();
+
+                // Vector from the center of the force field to the object its acting on.
+                Vector3 distanceVector = mobileEntity->getWorldPosition() - (this->getWorldPosition() + (this->halfLength_ * direction));
+
+                // The object is outside a ball around the center with radius length/2 of the ForceField.
+                if(distanceVector.length() > this->halfLength_)
+                    continue;
+
+                // The distance of the object form the orientation vector. (Or rather the smallest distance from the orientation vector)
+                float distanceFromDirectionVector = ((mobileEntity->getWorldPosition() - this->getWorldPosition()).crossProduct(direction)).length();
+
+                // If the object in a tube of radius 'radius' around the direction of orientation.
+                if(distanceFromDirectionVector >= this->radius_)
+                    continue;
+
+                // Apply a force to the object in the direction of the orientation.
+                // The force is highest when the object is directly on the direction vector, with a linear decrease, finally reaching zero, when distanceFromDirectionVector = radius.
+                mobileEntity->applyCentralForce((this->radius_ - distanceFromDirectionVector)/this->radius_ * this->velocity_ * direction);
+            }
+        }
+        else if(this->mode_ == ForceFieldMode::sphere)
+        {
+            // Iterate over all objects that could possibly be affected by the ForceField.
+            for (MobileEntity* mobileEntity : ObjectList<MobileEntity>())
+            {
+                Vector3 distanceVector = mobileEntity->getWorldPosition() - this->getWorldPosition();
+                float distance = distanceVector.length();
+                // If the object is within 'radius' distance.
+                if (distance < this->radius_)
+                {
+                    distanceVector.normalise();
+                    // Apply a force proportional to the velocity, with highest force at the origin of the sphere, linear decreasing until reaching a distance of 'radius' from the origin, where the force reaches zero. 
+                    mobileEntity->applyCentralForce((this->radius_ - distance)/this->radius_ * this->velocity_ * distanceVector);
+                }
+            }
+        }
+        else if(this->mode_ == ForceFieldMode::invertedSphere)
+        {
+            // Iterate over all objects that could possibly be affected by the ForceField.
+            for (MobileEntity* mobileEntity : ObjectList<MobileEntity>())
+            {
+                Vector3 distanceVector = this->getWorldPosition() - mobileEntity->getWorldPosition();
+                float distance = distanceVector.length();
+                // If the object is within 'radius' distance and no more than 'length' away from the boundary of the sphere.
+                float range = this->radius_ - this->halfLength_*2;
+                if (distance < this->radius_ && distance > range)
+                {
+                    distanceVector.normalise();
+                    // Apply a force proportional to the velocity, with highest force at the boundary of the sphere, linear decreasing until reaching a distance of 'radius-length' from the origin, where the force reaches zero.
+                    mobileEntity->applyCentralForce((distance-range)/range * this->velocity_ * distanceVector);
+                }
+            }
+        }
+        else if(this->mode_ == ForceFieldMode::newtonianGravity)
+        {
+            // Iterate over all objects that could possibly be affected by the ForceField.
+            for (MobileEntity* mobileEntity : ObjectList<MobileEntity>())
+            {
+                Vector3 distanceVector = mobileEntity->getWorldPosition() - this->getWorldPosition();
+                float distance = distanceVector.length();
+                // If the object is within 'radius' distance and especially further away than massRadius_
+                if (distance < this->radius_ && distance > this->massRadius_)
+                {
+                    distanceVector.normalise();
+                    /* Apply a central force that follows the newtownian law of gravity, ie.:
+                     * F = G * (M*m) / D^2,
+                     * while M is the mass of the stellar body and m is the mass of the affected object. 
+                     * D is the distance from the center of mass of both bodies
+                     * and it should be noted that massRadius_ denotes the radius of the stellar body,
+                     * at which point the force vanishes (you can use this to dictate the size of the body).
+                     * attenFactor_ weakens the field by a constant factor. The -1 is needed for an attractive force.
+                     */
+                    
+                    // Note: this so called force is actually an acceleration!
+                    mobileEntity->applyCentralForce((-1) * (ForceField::attenFactor_ * ForceField::gravConstant_ * this->getMass()) / (distance * distance) * distanceVector);
+                }
+            }
+        }
+        else if(this->mode_ == ForceFieldMode::homogen)
+        {
+            // Iterate over all objects that could possibly be affected by the ForceField.
+            for (MobileEntity* mobileEntity : ObjectList<MobileEntity>())
+            {
+                Vector3 distanceVector = mobileEntity->getWorldPosition() - this->getWorldPosition();
+                float distance = distanceVector.length();
+                if (distance < this->radius_ && distance > this->massRadius_)
+                {
+                    // Add a Acceleration in forceDirection_.
+                    // Vector3(0,0,0) is the direction, where the force should work.
+                    mobileEntity->addAcceleration(forceDirection_ , Vector3(0,0,0));
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        Set the mode of the ForceField.
+    @param mode
+        The mode as a string.
+    */
+    void ForceField::setMode(const std::string& mode)
+    {
+        if(mode == ForceField::modeTube_s)
+            this->mode_ = ForceFieldMode::tube;
+        else if(mode == ForceField::modeSphere_s)
+            this->mode_ = ForceFieldMode::sphere;
+        else if(mode == ForceField::modeInvertedSphere_s)
+            this->mode_ = ForceFieldMode::invertedSphere;
+        else if(mode == ForceField::modeNewtonianGravity_s)
+            this->mode_ = ForceFieldMode::newtonianGravity;
+
+        else if(mode == ForceField::modeHomogen_s)
+            this->mode_ = ForceFieldMode::homogen;
+
+        else
+        {
+            orxout(internal_warning) << "Wrong mode '" << mode << "' in ForceField. Setting to 'tube'." << endl;
+            this->mode_ = ForceFieldMode::tube;
+        }
+    }
+
+    /**
+    @brief
+        Get the mode of the ForceField.
+    @return
+        Returns the mode of the ForceField as a string.
+    */
+    const std::string& ForceField::getMode(void)
+    {
+        switch(this->mode_)
+        {
+            case ForceFieldMode::tube:
+                return ForceField::modeTube_s;
+            case ForceFieldMode::sphere:
+                return ForceField::modeSphere_s;
+            case ForceFieldMode::invertedSphere:
+                return ForceField::modeInvertedSphere_s;
+            case ForceFieldMode::newtonianGravity:
+                return ForceField::modeNewtonianGravity_s;
+
+            case ForceFieldMode::homogen:
+                return ForceField::modeHomogen_s;
+
+            default:
+                return ForceField::modeTube_s;
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/ForceField.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/ForceField.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/ForceField.h	(revision 11817)
@@ -0,0 +1,181 @@
+
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *      Kevin Young
+ *
+ */
+
+/**
+    @file ForceField.h
+    @brief Definition of the ForceField class.
+    @ingroup Objects
+*/
+
+#ifndef _ForceField_H__
+#define _ForceField_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The mode of the ForceField.
+
+    @ingroup Objects
+    */
+    enum class ForceFieldMode {
+        tube, //!< The ForceField has a tube shape.
+        sphere, //!< The ForceField has a spherical shape.
+        invertedSphere, //!< The ForceField has a spherical shape but "inverted" behavior.
+        newtonianGravity, //!< The ForceField imitates Newtonian gravitation for use in stellar bodies.
+        homogen //!< Local homogenous Force field with changeable direction for the Space Station
+    };
+
+    /**
+    @brief
+        Implements a force field, that applies a force to any @ref orxonox::MobileEntity "MobileEntity" that enters its range.
+
+        The following parameters can be set to specify the behavior of the ForceField.
+        - @b forcedirection The direction and the strength of the homogenous force field. Default is 0,-400,0.
+        - @b velocity The amount of force the ForceField excerts. Default is 100.
+        - @b diameter The diameter of the ForceField. Default is 500.
+        - @b length The length of the ForceField. Default is 2000.
+        - @b mode The mode the ForceField is in. For mode:
+            - <em>tube</em> A ForceField which exerts force only in the direction it is oriented. The force is only exerted on objects that are in a tube of length <em>length</em> and diameter <em>diameter</em> (with rounded start and end faces, so in fact the <em>length</em> parameter specifies a ball with <code>origin + length/2</code> as the center and <code>length/2</code> as the radius). The magintude of the force is proportional to the <em>velocity</em>, being highest when an object is in the middle of the tube (radius-wise), linearly decreasing with greater radii and finally reaching zero, when the object is <code>diameter/2</code> away from the orientation vector.
+            - <em>sphere</em> A Force Field which exerts force radially away from itself, with the greatest magnitude (proportional to <em>velocity</em>) being in the origin of the ForceField, linearly decreasing with respect to the distance to the origin and finally reaching zero at distance <code>diameter/2</code>.
+            Default is <em>tube</em>.
+            - <em>invertedSphere</em> A ForceField which excerts force radially towards itself, with the highest force at the boundary of the sphere, linear decreasing until reaching a distance of <code>radius-length</code> from the origin, where the force reaches zero.
+
+    @author
+        Aurelian Jaggi
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Objects
+    */
+    class _ObjectsExport ForceField : public StaticEntity, public Tickable
+    {
+        public:
+            ForceField(Context* context);
+            virtual ~ForceField();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Creates a ForceField object through XML.
+            void registerVariables(); //!< Registers the variables that should get synchronised over the network
+            virtual void tick(float dt) override; //!< A method that is called every tick.
+            
+
+            /**
+            @brief Set the velocity of the ForceField.
+            @param vel The velocity to be set.
+            */
+            inline void setFieldVelocity(float vel)
+                { this->velocity_ = vel; }
+            /**
+            @brief Get the velocity of the ForceField.
+            @return Returns the velocity of the ForceField.
+            */
+            inline float getFieldVelocity()
+                { return this->velocity_; }
+
+            /**
+            @brief Set the diameter of the ForceField. In mode StellarBody this stands for the outer radius.
+            @param diam The diameter to be set.
+            */
+            inline void setDiameter(float diam)
+                { this->radius_ = diam/2; }
+            /**
+            @brief Get the diameter of the ForceField. In mode StellarBody this stands for the outer radius.
+            @return Returns the diameter of the ForceField.
+            */
+            inline float getDiameter()
+                { return this->radius_*2; }
+        
+            /**
+            @brief Set the diameter of the stellar body for the Newtonian ForceField.
+            @param massDiam The diameter of the stellar body.
+            */
+            inline void setMassDiameter(float massDiam)
+                { this->massRadius_ = massDiam/2; }
+        
+            /**
+            @brief Get the diameter of the stellar body for the Newtonian ForceField.
+            @return float Returns the diameter of the stellar body.
+            */
+            inline float getMassDiameter()
+                { return this->massRadius_*2; }
+
+            /**
+            @brief Set the length of the ForceField.
+            @param l The length to be set.
+            */
+            inline void setLength(float l)
+                { this->halfLength_ = l/2; }
+            /**
+            @brief Get the length of the ForceField.
+            @return Returns the length of the ForceField.
+            */
+            inline float getLength()
+                { return this->halfLength_*2; }
+
+            inline void setForceDirection(Vector3 forcedir)
+                { this->forceDirection_ = forcedir; }
+
+            inline Vector3 getForceDirection()
+                { return this->forceDirection_; }
+
+
+            void setMode(const std::string& mode); //!< Set the mode of the ForceField.
+            const std::string& getMode(void); //!< Get the mode of the ForceField.
+
+            //! Strings to represent the modes.
+            static const std::string modeTube_s;
+            static const std::string modeSphere_s;
+            static const std::string modeInvertedSphere_s;
+            static const std::string modeNewtonianGravity_s;
+            static const std::string modeHomogen_s;
+
+        private:
+            float velocity_; //!< The velocity of the ForceField.
+            float radius_; //!< The radius of the ForceField.
+            float massRadius_; //!< The radius of the stellar body for the Newtonian ForceField.
+            float halfLength_; //!< Half of the length of the ForceField.
+            ForceFieldMode mode_; //!< The mode of the ForceField.
+            
+            //! Gravitational constant for Newtonian ForceFields.
+            static const float gravConstant_;
+            //! Attenuation factor for Newtonian ForceFields
+            static const float attenFactor_;
+            Vector3 forceDirection_;
+  };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/objects/ObjectsPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/ObjectsPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/ObjectsPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the objects module
+@details
+    Updated: 19. September 2009
+    Total Files: 15
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btTransform.h> // 11
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"   // 15
+#include "core/CoreIncludes.h" // 15
+#include "core/XMLPort.h"      // 13
+
+///////////////////////////////////////////
+/////      Not so Stable Headers      /////
+///////////////////////////////////////////
+
+#include "network/synchronisable/Synchronisable.h" // 11
+//#include "orxonox/worldentities/StaticEntity.h" // 7
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/objects/ObjectsPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/ObjectsPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/ObjectsPrereqs.h	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the objects module
+*/
+
+#ifndef _ObjectsPrereqs_H__
+#define _ObjectsPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(OBJECTS_STATIC_BUILD)
+#  ifdef OBJECTS_SHARED_BUILD
+#    define _ObjectsExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _ObjectsExport
+#    else
+#      define _ObjectsExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _ObjectsPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _ObjectsExport  __attribute__ ((visibility("default")))
+#  define _ObjectsPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _ObjectsExport
+#  define _ObjectsPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Attacher;
+    class ForceField;
+    class Planet;
+    class Script;
+    class SpaceBoundaries;
+    class Turret;
+
+    // collisionshapes
+    class AbstractRadiusHeightCollisionShape;
+    class BoxCollisionShape;
+    class ConeCollisionShape;
+    class CylinderCollisionShape;
+    class PlaneCollisionShape;
+    class SphereCollisionShape;
+
+    // eventsystem
+    class EventDispatcher;
+    class EventFilter;
+    class EventListener;
+    class EventName;
+    class EventTarget;
+
+    // triggers
+    class CheckPoint;
+    class DistanceMultiTrigger;
+    class DistanceTrigger;
+    class DistanceTriggerBeacon;
+    class EventMultiTrigger;
+    class EventTrigger;
+    class MultiTrigger;
+    class MultiTriggerContainer;
+    class Trigger;
+    class TriggerBase;
+}
+
+#endif /* _ObjectsPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/Planet.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Planet.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Planet.cc	(revision 11817)
@@ -0,0 +1,179 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Marian Runo
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Planet.h"
+
+#include <OgreEntity.h>
+#include <OgreBillboardSet.h>
+#include <OgreProgressiveMesh.h>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+#include "graphics/Camera.h"
+#include "CameraManager.h"
+
+namespace orxonox
+{
+    RegisterClass(Planet);
+
+    /**
+     * @brief Constructor
+     */
+    Planet::Planet(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(Planet);
+        this->registerVariables();
+    }
+
+    /**
+     * @brief Destructor
+     */
+    Planet::~Planet()
+    {
+        if (this->isInitialized() && this->mesh_.getEntity())
+            this->detachOgreObject(this->mesh_.getEntity());
+    }
+
+    void Planet::tick(float dt)
+    {
+        if (!this->isVisible())
+            return;
+
+        if (GameMode::showsGraphics())
+        {
+            Camera* activeCamera = CameraManager::getInstance().getActiveCamera();
+            if (activeCamera && this->billboard_.getBillboardSet())
+            {
+                float distance = this->getPosition().distance( activeCamera->getWorldPosition() );
+                //             orxout(internal_warning) << distance << endl;
+                float planetRadius = this->getScale();
+
+                float newScale = 2 * distance / sqrt(distance*distance - planetRadius*planetRadius);
+                float tempTest = newScale*(1+float(this->atmosphereSize)/float(this->imageSize));
+                newScale = tempTest;
+
+                this->billboard_.getBillboardSet()->setDefaultDimensions(newScale, newScale);
+            }
+        }
+
+        SUPER(Planet, tick, dt);
+    }
+
+    void Planet::changedMesh()
+    {
+        if( GameMode::showsGraphics() )
+        {
+            if (this->mesh_.getEntity())
+                this->detachOgreObject(this->mesh_.getEntity());
+
+            this->mesh_.setMeshSource(this->getScene()->getSceneManager(), this->meshSrc_);
+
+            if (this->mesh_.getEntity())
+            {
+                this->attachOgreObject(this->mesh_.getEntity());
+                this->mesh_.getEntity()->setCastShadows(this->bCastShadows_);
+                this->mesh_.setVisible(this->isVisible());
+
+                float scaleFactor = this->getScale();
+
+#if OGRE_VERSION >= 0x010800
+                Ogre::ProgressiveMesh::LodValueList distList;
+#elif OGRE_VERSION >= 0x010700
+                Ogre::Mesh::LodValueList distList;
+#else
+                Ogre::Mesh::LodDistanceList distList;
+#endif
+
+                distList.push_back(10.0f*scaleFactor);
+                distList.push_back(19.0f*scaleFactor);
+                distList.push_back(27.0f*scaleFactor);
+                distList.push_back(34.0f*scaleFactor);
+                distList.push_back(40.0f*scaleFactor);
+                distList.push_back(45.0f*scaleFactor);
+                distList.push_back(49.0f*scaleFactor);
+                distList.push_back(52.0f*scaleFactor);
+                distList.push_back(54.0f*scaleFactor);
+                distList.push_back(55.0f*scaleFactor);
+
+                float reductionValue = 0.2f;
+
+#if OGRE_VERSION >= 0x010800
+                Ogre::ProgressiveMesh::generateLodLevels(this->mesh_.getEntity()->getMesh().get(), distList, Ogre::ProgressiveMesh::VRQ_PROPORTIONAL,
+                    reductionValue);
+#else
+                this->mesh_.getEntity()->getMesh()->generateLodLevels(distList, Ogre::ProgressiveMesh::VRQ_PROPORTIONAL, reductionValue);
+#endif
+                billboard_.setBillboardSet(this->getScene()->getSceneManager(), this->atmosphere_, Vector3(0,0,0));
+
+                this->attachOgreObject(this->billboard_.getBillboardSet());
+                this->billboard_.getBillboardSet()->setUseAccurateFacing(true);
+                this->setCastShadows(true);
+                this->billboard_.getBillboardSet()->setRenderQueueGroup(this->mesh_.getEntity()->getRenderQueueGroup());
+                this->mesh_.setCastShadows(true);
+            }
+        }
+    }
+
+    void Planet::changedShadows()
+    {
+        this->mesh_.setCastShadows(this->bCastShadows_);
+    }
+
+    void Planet::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Planet, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Planet, "atmosphere", setAtmosphere, getAtmosphere, xmlelement, mode).defaultValues("planet/Atmosphere");
+        XMLPortParam(Planet, "atmospheresize", setAtmosphereSize, getAtmosphereSize, xmlelement,mode);
+        XMLPortParam(Planet, "imagesize", setImageSize, getImageSize, xmlelement,mode);
+        XMLPortParam(Planet, "mesh", setMeshSource, getMeshSource, xmlelement, mode);
+        XMLPortParam(Planet, "shadow", setCastShadows, getCastShadows, xmlelement, mode).defaultValues(true);
+    }
+
+    void Planet::registerVariables()
+    {
+        registerVariable(this->atmosphere_, VariableDirection::ToClient);
+        registerVariable(this->atmosphereSize, VariableDirection::ToClient);
+        registerVariable(this->imageSize, VariableDirection::ToClient);
+        // Note: the meshSrc should be synchronised after atmosphere and other values, because the meshSrc callback setts the atmosphere billboards
+        registerVariable(this->meshSrc_, VariableDirection::ToClient, new NetworkCallback<Planet>(this, &Planet::changedMesh));
+        registerVariable(this->bCastShadows_, VariableDirection::ToClient, new NetworkCallback<Planet>(this, &Planet::changedShadows));
+    }
+
+    void Planet::changedVisibility()
+    {
+        SUPER(Planet, changedVisibility);
+        if (this->isInitialized())
+        {
+            this->mesh_.setVisible(this->isVisible());
+            this->billboard_.setVisible(this->isVisible());
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/Planet.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Planet.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Planet.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Marian Runo
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Planet.h
+    @brief Definition of the Planet class.
+    @ingroup Objects
+*/
+
+#ifndef _Planet_H__
+#define _Planet_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <string>
+#include "tools/BillboardSet.h"
+#include "tools/Mesh.h"
+#include "worldentities/MovableEntity.h"
+
+namespace orxonox
+{
+    class _ObjectsExport Planet : public MovableEntity
+    {
+        public:
+            Planet(Context* context);
+
+            virtual ~Planet();
+
+            virtual void tick(float dt) override;
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedVisibility() override;
+
+            inline void setMeshSource(const std::string& meshname)
+                { this->meshSrc_ = meshname; this->changedMesh(); }
+
+            inline const std::string& getMeshSource() const
+                { return this->meshSrc_; }
+
+            inline void setCastShadows(bool bCastShadows)
+                { this->bCastShadows_ = bCastShadows; this->changedShadows(); }
+
+            inline bool getCastShadows() const
+                { return this->bCastShadows_; }
+
+            inline const std::string& getMesh() const{
+                return this->meshSrc_;
+            }
+
+            inline void setAtmosphereSize(float size){
+                this->atmosphereSize = size;
+            }
+
+            inline float getAtmosphereSize(){
+                return this->atmosphereSize;
+            }
+
+            inline void setAtmosphere(const std::string& atmosphere){
+                this->atmosphere_ = atmosphere;
+            }
+
+            inline const std::string& getAtmosphere(){
+                return this->atmosphere_;
+            }
+
+            inline void setImageSize(float size){
+                this->imageSize = size;
+            }
+
+            inline float getImageSize(){
+                return this->imageSize;
+            }
+
+        protected:
+
+        private:
+            void registerVariables();
+
+            void changedMesh();
+            void changedShadows();
+
+            std::string meshSrc_;
+            std::string atmosphere_;
+            Mesh mesh_;
+            float atmosphereSize;
+            float imageSize;
+            BillboardSet billboard_;
+            bool bCastShadows_;
+
+    };
+}
+
+#endif
+
Index: /code/branches/RacingBots_FS18/src/modules/objects/Script.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Script.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Script.cc	(revision 11817)
@@ -0,0 +1,329 @@
+
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+#include "Script.h"
+
+#include "core/command/CommandExecutor.h"
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/GameMode.h"
+#include "core/LuaState.h"
+#include "core/XMLPort.h"
+#include "network/Host.h"
+#include "network/NetworkFunctionIncludes.h"
+
+#include "PlayerManager.h"
+#include "infos/PlayerInfo.h"
+#include "interfaces/PlayerTrigger.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(Script);
+
+    registerStaticNetworkFunction(Script::executeHelper);
+
+    // Initializing constants.
+    /*static*/ const std::string Script::NORMAL = "normal";
+    /*static*/ const std::string Script::LUA = "lua";
+    /*static*/ const int Script::INF = -1;
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Script::Script(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Script);
+
+        // Initialize variables.
+        this->remainingExecutions_ = Script::INF;
+        this->mode_ = ScriptMode::normal;
+        this->onLoad_ = true;
+        this->times_ = Script::INF;
+        this->needsGraphics_ = false;
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up.
+    */
+    Script::~Script()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a Script object through XML.
+    @param xmlelement
+        The element.
+    @param mode
+        The mode.
+    */
+    void Script::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Script, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Script, "code", setCode, getCode, xmlelement, mode);
+        XMLPortParamTemplate(Script, "mode", setMode, getMode, xmlelement, mode, const std::string&).defaultValues(Script::NORMAL);
+        XMLPortParam(Script, "onLoad", setOnLoad, isOnLoad, xmlelement, mode).defaultValues(true);
+        XMLPortParam(Script, "times", setTimes, getTimes, xmlelement, mode).defaultValues(Script::INF);
+        XMLPortParam(Script, "needsGraphics", setNeedsGraphics, getNeedsGraphics, xmlelement, mode).defaultValues(false);
+        XMLPortParam(Script, "forAll", setForAll, isForAll, xmlelement, mode).defaultValues(false);
+
+        XMLPortEventSink(Script, BaseObject, "trigger", trigger, xmlelement, mode);
+
+        if(this->isOnLoad()) // If the object is onLoad the code is executed at once for the server.
+            this->execute(0, true);
+    }
+
+    /**
+    @brief
+        Creates a port that can be used to channel events and react to them.
+    @param xmlelement
+        The element.
+    @param mode
+        The mode.
+    */
+    void Script::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Script, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(Script, BaseObject, "trigger", trigger, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when an event comes in trough the event port.
+    @param triggered
+        Whether the event is triggering or un-triggering.
+    @param trigger
+        The object that caused the event to be fired.
+    @return
+        Returns true if successful.
+    */
+    bool Script::trigger(bool triggered, BaseObject* trigger)
+    {
+        if(!triggered || !this->isActive()) // If the Script is inactive it cannot be executed.
+            return false;
+
+        orxout(verbose, context::misc::script) << "Script (&" << this << ") triggered." << endl;
+
+        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+        PlayerInfo* player = nullptr;
+
+        // If the trigger is a PlayerTrigger.
+        if(pTrigger != nullptr)
+        {
+            if(!pTrigger->isForPlayer())  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+                return false;
+            else
+                player = pTrigger->getTriggeringPlayer();
+        }
+        else
+            return false;
+
+        if(player == nullptr)  //TODO: Will this ever happen? If not, change in NotificationDispatcher as well.
+        {
+            orxout(internal_warning) << "The Script was triggered by an entity other than a Pawn. (" << trigger->getIdentifier()->getName() << ")" << endl;
+            return false;
+        }
+
+        this->execute(player->getClientID());
+        return true;
+    }
+
+    /**
+    @brief
+        Executes the Scripts code for the input client, depending on the mode.
+    @param clientId
+        The Id of the client the Script should be executed for.
+    @param onLoad
+        Whether this method is executed as a result of the onLoad parameter being set to true. Default is false.
+    */
+    void Script::execute(unsigned int clientId, bool onLoad)
+    {
+        // If this is the server or we're in standalone mode we check whether we still want to execute the code and if so decrease the number of remaining executions.
+        if(GameMode::isMaster())
+        {
+            // If the number of executions have been used up.
+            if(this->times_ != Script::INF && this->remainingExecutions_ <= 0)
+                return;
+        }
+
+        // If this is either the standalone mode or we're on the client we want to be.
+        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
+        {
+            this->executeHelper(this->getCode(), this->getMode(), this->getNeedsGraphics());
+            if(GameMode::isMaster() && !onLoad && this->times_ != Script::INF) // Decrement the number of remaining executions.
+                this->remainingExecutions_--;
+        }
+
+        // If this is the server and we're not on the client we want to be.
+        if(GameMode::isServer() && Host::getPlayerID() != clientId)
+        {
+            // If we want to execute the code for all clients and the server.
+            if(this->isForAll())
+            {
+                const std::map<unsigned int, PlayerInfo*> clients = PlayerManager::getInstance().getClients();
+                for(const auto& mapEntry : clients)
+                {
+                    callStaticNetworkFunction(&Script::executeHelper, mapEntry.first, this->getCode(), this->getMode(), this->getNeedsGraphics());
+                    if(this->times_ != Script::INF) // Decrement the number of remaining executions.
+                    {
+                        this->remainingExecutions_--;
+                        if(this->remainingExecutions_ <= 0)
+                            break;
+                    }
+                }
+            }
+            // Else we execute the code just for the specified client.
+            else
+            {
+                callStaticNetworkFunction(&Script::executeHelper, clientId, this->getCode(), this->getMode(), this->getNeedsGraphics());
+                if(this->times_ != Script::INF) // Decrement the number of remaining executions.
+                    this->remainingExecutions_--;
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper method that is used to reach this Script object on other clients.
+    */
+    /*static*/ void Script::executeHelper(const std::string& code, const std::string& mode, bool needsGraphics)
+    {
+        // If the code needs graphics to be executed but the GameMode doesn't show graphics the code isn't executed.
+        if(needsGraphics && !GameMode::showsGraphics())
+            return;
+
+        if(mode == Script::NORMAL) // If the mode is 'normal'.
+            CommandExecutor::execute(code);
+        else if(mode == Script::LUA) // If it's 'lua'.
+        {
+            LuaState* luaState = new LuaState();
+            luaState->doString(code);
+            delete luaState;
+        }
+    }
+
+    /**
+    @brief
+        Callback that is called when a new client has connected.
+    @param clientId
+        The clientId of the new client that has connected.
+    */
+    void Script::clientConnected(unsigned int clientId)
+    {
+        // If this is the server and the Script is specified as being 'onLoad'.
+        if(GameMode::isServer() && this->isOnLoad())
+        {
+            callStaticNetworkFunction(&Script::executeHelper, clientId, this->getCode(), this->getMode(), this->getNeedsGraphics());
+        }
+    }
+
+    /**
+    @brief
+        Sets the mode of the Script.
+    @param mode
+        The mode as a string.
+    */
+    void Script::setMode(const std::string& mode)
+    {
+        if(mode == Script::NORMAL)
+        {
+            this->setMode(ScriptMode::normal);
+            this->modeStr_ = Script::NORMAL;
+        }
+        else if(mode == Script::LUA)
+        {
+            this->setMode(ScriptMode::lua);
+            this->modeStr_ = Script::LUA;
+        }
+        else
+        {
+            orxout(internal_warning) << "Invalid mode '" << mode << "' in Script object. Setting to 'normal'." << endl;
+            this->setMode(ScriptMode::normal);
+            this->modeStr_ = Script::NORMAL;
+        }
+    }
+
+    /**
+    @brief
+        Sets the mode to the mode specified in this->modeStr_.
+        This is used internally for networking purposes.
+    */
+    void Script::modeChanged(void)
+    {
+        this->setMode(this->modeStr_);
+    }
+
+    /**
+    @brief
+        Get the mode of the Script.
+    @return
+        Returns the mode as a string.
+    */
+    const std::string& Script::getMode(void)
+    {
+        switch(this->mode_)
+        {
+            case ScriptMode::normal:
+                return Script::NORMAL;
+            case ScriptMode::lua:
+                return Script::LUA;
+            default: // This will never happen...
+                return Script::NORMAL;
+        }
+    }
+
+    /**
+    @brief
+        Set the number of times this Script is executed at the most.
+        -1 denotes infinity.
+    @param times
+        The number of times to be set.
+    */
+    void Script::setTimes(int times)
+    {
+        if(times >= -1)
+        {
+            this->times_ = times;
+            this->remainingExecutions_ = times;
+        }
+        else
+        {
+            orxout(internal_warning) << "Invalid times '" << times << "' in Script. Setting to infinity." << endl;
+            this->times_ = Script::INF;
+            this->remainingExecutions_ = Script::INF;
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/Script.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Script.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Script.h	(revision 11817)
@@ -0,0 +1,197 @@
+
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file Script.h
+    @brief Definition of the Script class.
+    @ingroup Objects
+*/
+
+#ifndef _Script_H__
+#define _Script_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <string>
+#include <vector>
+
+#include "core/BaseObject.h"
+#include "network/ClientConnectionListener.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief The mode a specific @ref orxonox::Script "Script" is in.
+    */
+    enum class ScriptMode
+    {
+        normal, //!< The @ref orxonox::Script "Scripts'" code is executed through the @ref orxonox::CommandExecutor "CommandExecutor".
+        lua //!< The @ref orxonox::Script "Scripts'" code is executed through lua.
+    };
+
+    /**
+    @brief
+        The Script class lets you execute a piece of code, either the normal way or in lua, through XML. It can be specified whether the code is executed upon loading (creation) of the object. Additionally the code is executed each time a trigger event comes in.
+        There are three parameters:
+        - @b code The code that should be executed.
+        - @b mode The mode, specifying whether the set code should be executed the normal way (<em>normal</em>) or in lua (<em>lua</em>). Default is <em>normal</em>.
+        - @b onLoad Whether the code is executed upon loading (creation) of this object. If this is set the code is executed ofr all players, regardless of the value of parameter <em>forAll</em>. Default is true.
+        - @b needsGraphics Whether the code needs graphics to be executed or not. Default is false.
+        - @b forAll Whether the code is executed for all players each time the Script is triggered or jut for the player triggering the Script. If forAll is false, which is default, the event that triggers the Script must come from a @ref orxonox::PlayerTrigger "PlayerTrigger".
+
+        Here are two examples illustrating the usage:
+        @code
+        <Script code="showGUI QuestGUI" needsGraphics=true />
+        @endcode
+        This would show the QuestGUI opon creation of the object. The <em>mode</em> is <em>normal</em>, not specified here since that is the default, also <em>onLoad</em> is true, also not specified, since it is the default as well. Also <em>needsGraphics</em> is set to true because showGUI needs graphics to work.
+
+        @code
+        <Script code="hideGUI QuestGUI" mode="normal" onLoad="false" needsGraphics=true >
+            <events>
+                <trigger>
+                    <DistanceTrigger distance=10 target="Pawn" />
+                </trigger>
+            </events>
+        </Script>
+        @endcode
+        This would hide the QuestGUI as soon as a @ref orxonox::Pawn "Pawn" got in range of the @ref orxonox::DistanceTrigger "DistanceTrigger". The mode is <em>normal</em>, it is specified here, but could be ommitted as well, since it is the default. <em>OnLoad</em> is false, that is why it can't be ommitted. Also <em>needsGraphics</em> is set to true because showGUI needs graphics to work.
+
+    @author
+        Benjamin Knecht
+    @author
+        Damian 'Mozork' Frick
+    */
+    class _ObjectsExport Script : public BaseObject, public ClientConnectionListener
+    {
+        public:
+            Script(Context* context);
+            virtual ~Script();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a Script object through XML.
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Creates a port that can be used to channel events and react to them.
+
+            bool trigger(bool triggered, BaseObject* trigger); //!< Is called when an event comes in trough the event port.
+            void execute(unsigned int clientId, bool onLoad = false); //!< Executes the Scripts code for the input client, depending on the mode.
+            static void executeHelper(const std::string& code, const std::string& mode, bool needsGraphics); //!< Helper method that is used to reach this Script object on other clients.
+
+            /**
+            @brief Sets the code that is executed by this Script.
+            @param code  The code that is executed by this Script.
+            */
+            inline void setCode(const std::string& code)
+                { code_ = code; }
+            /**
+            @brief Get the code that is executed by this Script.
+            @return Returns the code that is executed by this Script.
+            */
+            inline const std::string& getCode() const
+                { return code_; }
+
+            void setMode(const std::string& mode); //!< Sets the mode of the Script.
+            const std::string& getMode(void); //!< Get the mode of the Script.
+
+            /**
+            @brief Set whether this Script is executed onLoad or not.
+            @param onLoad if true the Script is executed onLoad, if false it's not.
+            */
+            inline void setOnLoad(bool onLoad)
+                { this->onLoad_ = onLoad; }
+            /**
+            @brief Get whether this Script is executed onLoad.
+            @return Returns true if this Script is executed onLoad, false if not.
+            */
+            inline bool isOnLoad(void)
+                { return this->onLoad_; }
+
+            void setTimes(int times); //!< Set the number of times this Script is executed at the most.
+            /**
+            @brief Get the number of times this Script is executed at the most.
+            @return Returns the number of times this Script is executed at the most. -1 denotes infinity.
+            */
+            inline int getTimes(void)
+                { return this->times_; }
+
+            /**
+            @brief Set whether the code to be executed needs graphics to work.
+            @param needsGraphics True if the cde needs graphics to be executed properly.
+            */
+            void setNeedsGraphics(bool needsGraphics)
+                { this->needsGraphics_ = needsGraphics; }
+            /**
+            @brief Get whether the code to be executed needs graphics to work.
+            @return Returns true if the code needs graphic, false if not.
+            */
+            bool getNeedsGraphics(void)
+                { return this->needsGraphics_; }
+
+            /**
+            @brief Set whether the code is executed for all players or just for the player triggering the Script.
+            @param forAll If true the code is executed for all players.
+            */
+            void setForAll(bool forAll)
+                { this->forAll_ = forAll; }
+            /**
+            @brief Get whether the Script executes its code for all players or just for the player triggering the Script.
+            @return Returns true if the code is executed for all players, false if not.
+            */
+            bool isForAll(void)
+                { return this->forAll_; }
+
+            virtual void clientConnected(unsigned int clientId) override; //!< Callback that is called when a new client has connected.
+            virtual void clientDisconnected(unsigned int clientid) override {}
+
+        private:
+            //! Static variables to avoid magic strings.
+            static const std::string NORMAL;
+            static const std::string LUA;
+            static const int INF;
+
+            std::string code_; //!< The code that is executed by this Script.
+            ScriptMode mode_; //!< The mode the Script is in. Determines whether the code is executed the normal way or in lua.
+            std::string modeStr_; //!< The mode the Script is in, as a string. Is used for networking purposes.
+            bool onLoad_; //!< Whether the Scripts code is executed upon loading (creation) of this Script.
+            int times_; //!< The number of times the Scripts code is executed at the most. -1 denotes infinity.
+            bool needsGraphics_; //!< Whether the code to be executed needs graphics.
+            bool forAll_; //!< Whether the code is executed for all players (in a multiplayer setup) or just for the one triggering the Script.
+
+            int remainingExecutions_; //!< The number of remainign executions. -1 denotes infinity.
+
+            void modeChanged(); //!< Sets the mode to the mode specified in this->modeStr_.
+
+            /**
+            @brief Sets the mode of the Script.
+            @param mode The mode of the Script.
+            */
+            inline void setMode(ScriptMode mode)
+                { this->mode_ = mode; }
+    };
+}
+
+#endif /* _Script_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/SpaceBoundaries.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/SpaceBoundaries.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/SpaceBoundaries.cc	(revision 11817)
@@ -0,0 +1,327 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Maurus Kaufmann
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SpaceBoundaries.h"
+
+#include <OgreBillboardSet.h>
+
+#include "core/CoreIncludes.h"
+#include "core/object/ObjectListIterator.h"
+#include "core/XMLPort.h"
+
+#include "graphics/Billboard.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/WorldEntity.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(SpaceBoundaries);
+
+    SpaceBoundaries::SpaceBoundaries(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(SpaceBoundaries);
+
+        this->setMaxDistance(3000);
+        this->setWarnDistance(this->getMaxDistance());
+        this->setShowDistance(this->getMaxDistance());
+        this->setReaction(0);
+    }
+    SpaceBoundaries::~SpaceBoundaries()
+    {
+        if (this->isInitialized())
+        {
+            this->pawnsIn_.clear();
+
+            for(BillboardAdministration& billboard : this->billboards_)
+            {
+                if( billboard.billy != nullptr)
+                {
+                    delete billboard.billy;
+                }
+            }
+            this->billboards_.clear();
+        }
+    }
+
+    void SpaceBoundaries::checkWhoIsIn()
+    {
+        pawnsIn_.clear();
+        for(Pawn* currentPawn : ObjectList<Pawn>())
+        {
+            if( this->reaction_ == 0 )
+            {
+                float distance = this->computeDistance(currentPawn);
+                if(distance <= this->maxDistance_)
+                {
+                    pawnsIn_.push_back(currentPawn);
+                }
+            }
+            else if (this->reaction_ == 2)
+            {
+                float distance = this->computeDistance(currentPawn);
+                if(distance >= this->maxDistance_)
+                {
+                    pawnsIn_.push_back(currentPawn);
+                }
+            }
+            else
+            {
+                pawnsIn_.push_back(currentPawn);
+            }
+        }
+    }
+
+    void SpaceBoundaries::positionBillboard(const Vector3& position, float alpha)
+    {
+        size_t current;
+        for (current = 0; current < this->billboards_.size(); ++current)
+            if (!this->billboards_[current].usedYet)
+                break;
+
+        if (current == this->billboards_.size())
+        {
+            Billboard* billboard = new Billboard(this->getContext());
+            billboard->setPosition(position);
+            billboard->setSyncMode(ObjectDirection::None);
+            this->setBillboardOptions(billboard);
+            BillboardAdministration ba = {true, billboard};
+            this->billboards_.push_back(ba);
+        }
+
+        this->billboards_[current].billy->setPosition(position);
+        this->billboards_[current].billy->setVisible(true);
+        this->billboards_[current].billy->setColour(ColourValue(1, 1, 1, alpha));
+        this->billboards_[current].usedYet = true;
+
+        Vector3 directionVector = (this->getWorldPosition() - position).normalisedCopy(); // vector from the position of the billboard to the center of the sphere
+        this->billboards_[current].billy->setCommonDirection(directionVector);
+
+        Vector3 upVector = Vector3(directionVector.z, directionVector.z, -(directionVector.x + directionVector.y)); // vector perpendicular to the direction vector
+        upVector.normalise();
+        this->billboards_[current].billy->setCommonUpVector(upVector);
+    }
+
+    void SpaceBoundaries::setBillboardOptions(Billboard *billy)
+    {
+        if(billy != nullptr)
+        {
+            billy->setMaterial("Grid");
+            billy->setBillboardType(Ogre::BBT_PERPENDICULAR_COMMON);
+            billy->setDefaultDimensions(150, 150);
+            billy->setVisible(true);
+        }
+    }
+
+    void SpaceBoundaries::removeAllBillboards()
+    {
+        for(BillboardAdministration& billboard : this->billboards_)
+        {
+            billboard.usedYet = false;
+            billboard.billy->setVisible(false);
+        }
+    }
+
+    void SpaceBoundaries::setMaxDistance(float r)
+    {
+        this->maxDistance_ = r;
+    }
+    float SpaceBoundaries::getMaxDistance()
+    {
+        return this->maxDistance_;
+    }
+
+    void SpaceBoundaries::setWarnDistance(float r)
+    {
+        this->warnDistance_ = r;
+    }
+    float SpaceBoundaries::getWarnDistance()
+    {
+        return this->warnDistance_;
+    }
+
+    void SpaceBoundaries::setShowDistance(float r)
+    {
+        this->showDistance_ = r;
+    }
+    float SpaceBoundaries::getShowDistance()
+    {
+        return this->showDistance_;
+    }
+
+    void SpaceBoundaries::setHealthDecrease(float amount)
+    {
+        this->healthDecrease_ = amount/1000;
+    }
+    float SpaceBoundaries::getHealthDecrease()
+    {
+        return this->healthDecrease_;
+    }
+
+    void SpaceBoundaries::setReaction(int mode)
+    {
+        this->reaction_ = mode;
+    }
+    int SpaceBoundaries::getReaction()
+    {
+        return this->reaction_;
+    }
+
+    void SpaceBoundaries::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SpaceBoundaries, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SpaceBoundaries, "maxDistance", setMaxDistance, getMaxDistance, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "warnDistance", setWarnDistance, getWarnDistance, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "showDistance", setShowDistance, getShowDistance, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "healthDecrease", setHealthDecrease, getHealthDecrease, xmlelement, mode);
+        XMLPortParam(SpaceBoundaries, "reactionMode", setReaction, getReaction, xmlelement, mode);
+    }
+
+    void SpaceBoundaries::tick(float dt)
+    {
+        this->checkWhoIsIn();
+        this->removeAllBillboards();
+
+        if(!this->isActive())
+            return;
+
+        float distance;
+        bool humanItem;
+        for(Pawn* currentPawn : pawnsIn_)
+        {
+            if( currentPawn && currentPawn->getNode() ) 
+            {
+                distance = this->computeDistance(currentPawn);
+                humanItem = this->isHumanPlayer(currentPawn);
+//                orxout() << "Distance:" << distance << endl; // message for debugging
+                if(distance > this->warnDistance_ && distance < this->maxDistance_) // Display warning
+                {
+                    if(humanItem)
+                    {
+                        this->displayWarning("Attention! You are close to the boundary!");
+                    }
+                }
+                if(/* humanItem &&*/ std::abs(this->maxDistance_ - distance) < this->showDistance_ )
+                {
+                    this->displayBoundaries(currentPawn, 1.0f - fabs(this->maxDistance_ - distance) / this->showDistance_); // Show the boundary
+                }
+                if(distance > this->maxDistance_ && (this->reaction_ == 1) )
+                {
+                    if( humanItem )
+                    {
+//                        orxout() << "Health should be decreasing!" << endl;
+                        this->displayWarning("You are out of the area now!");
+                    }
+                    currentPawn->removeHealth( (distance - this->maxDistance_) * this->healthDecrease_);
+                }
+                if( (this->reaction_ == 0) && (distance + 100 > this->maxDistance_)) // Exception: A Pawn can't move more than 100 units per tick.
+                {
+                    this->conditionalBounceBack(currentPawn, distance, dt);
+                }
+                if( this->reaction_ == 2 && (distance - 100 < this->maxDistance_) )
+                {
+                    this->conditionalBounceBack(currentPawn, distance, dt);
+                }
+            }
+        }
+    }
+
+    float SpaceBoundaries::computeDistance(WorldEntity *item)
+    {
+        if(item != nullptr)
+        {
+            Vector3 itemPosition = item->getWorldPosition();
+            return (itemPosition.distance(this->getWorldPosition()));
+        } else {
+            return -1;
+        }
+    }
+
+    void SpaceBoundaries::displayWarning(const std::string warnText)
+    {
+        // TODO
+    }
+
+    void SpaceBoundaries::displayBoundaries(Pawn *item, float alpha)
+    {
+
+        Vector3 direction = item->getWorldPosition() - this->getWorldPosition();
+        direction.normalise();
+
+        Vector3 boundaryPosition = this->getWorldPosition() + direction * this->maxDistance_;
+
+        this->positionBillboard(boundaryPosition, alpha);
+    }
+
+    void SpaceBoundaries::conditionalBounceBack(Pawn *item, float currentDistance, float dt)
+    {
+        Vector3 normal = item->getWorldPosition() - this->getWorldPosition();
+        normal.normalise();
+        Vector3 velocity = item->getVelocity();
+        float normalSpeed = item->getVelocity().dotProduct(normal);
+
+        /* Check, whether the Pawn would leave the boundary in the next tick, if so send it back. */
+        if( this->reaction_ == 0 && currentDistance + normalSpeed * dt > this->maxDistance_ - 10 ) // -10: "security measure"
+        {
+            bounceBack(item, &normal, &velocity);
+        } else if (this->reaction_ == 2 && currentDistance - normalSpeed * dt < this->maxDistance_ + 10 ) // 10: "security measure"
+        {
+            normal = normal * (-1);
+            bounceBack(item, &normal, &velocity);
+        }
+    }
+
+    void SpaceBoundaries::bounceBack(Pawn *item, Vector3 *normal, Vector3 *velocity)
+    {
+        float dampingFactor = 0.5;
+        *velocity = velocity->reflect(*normal);
+        Vector3 acceleration = item->getAcceleration();
+        acceleration = acceleration.reflect(*normal);
+
+        item->lookAt( *velocity + this->getWorldPosition() );
+
+        item->setAcceleration(acceleration * dampingFactor);
+        item->setVelocity(*velocity * dampingFactor);
+
+        item->setPosition( item->getWorldPosition() - *normal * 10 ); // Set the position of the Pawn to be well inside the boundary.
+    }
+
+    bool SpaceBoundaries::isHumanPlayer(Pawn *item)
+    {
+        if(item != nullptr)
+        {
+            if(item->getPlayer())
+            {
+                return item->getPlayer()->isHumanPlayer();
+            }
+        }
+        return false;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/SpaceBoundaries.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/SpaceBoundaries.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/SpaceBoundaries.h	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Maurus Kaufmann
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SpaceBoundaries_H__
+#define _SpaceBoundaries_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <string>
+#include <list>
+#include <vector>
+
+#include "core/object/WeakPtr.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief SpaceBoundaries gives level creators the possibility to bar Pawns from leaving a defined area (until now this area is a ball).
+
+        Some attributes can/should be defined in the XML-File:
+        - 'position' : absolute position of the object of SpaceBoundaries in the level (usually 0,0,0)
+        - 'maxDistance' : defines the area, where a pawn is allowed to be (radius of a ball).
+        - 'warnDistance' : If the distance between the pawn of the human player and 'position' is bigger than 'warnDistance', a message is displayed to
+                            inform the player that he'll soon be leaving the allowed area. (not implemented yet!)
+        - 'showDistance' : If the distance between the pawn and the boundary of the allowed area is smaller than 'showDistance', the boundary is shown.
+        - 'reactionMode' : Integer-Value. Defines what effect appears if a space ship has crossed the boundaries.
+                                0: Reflect the space ship (default).
+                                1: Decrease Health of the space ship after having left the allowed area.
+                                2: Inverted Version of 0. Prohibit to fly INTO a defined area.
+        - 'healthDecrease' : a measure to define how fast the health of a pawn should decrease after leaving the allowed area (unnecessary if 'reactionMode' == 0).
+                                Recommended values: 0.1 (slow health decrease) to 5 (very fast health decrease)
+
+        Follow http://www.orxonox.net/wiki/SpaceBoundaries to get some further information.
+
+        Examples:
+        Two examples how one could include SpaceBoundaries in the XML-File. The first one uses reflection, the second one health decrease.
+        @code
+        <SpaceBoundaries position="0,0,0" maxDistance="1000" warnDistance="800" showDistance="100" reactionMode="0" />
+        @endcode
+
+        @code
+        <SpaceBoundaries position="0,0,0" maxDistance="1000" warnDistance="800" showDistance="100" reactionMode="1" healthDecrease="0.2" />
+        @endcode
+    */
+    class _ObjectsExport SpaceBoundaries : public StaticEntity, public Tickable
+    {
+        public:
+            SpaceBoundaries(Context* context);
+            ~SpaceBoundaries();
+
+            void setMaxDistance(float r);
+            float getMaxDistance();
+
+            void setWarnDistance(float r);
+            float getWarnDistance();
+
+            void setShowDistance(float r);
+            float getShowDistance();
+
+            void setHealthDecrease(float amount);
+            float getHealthDecrease();
+
+            void setReaction(int mode);
+            int getReaction();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void tick(float dt) override;
+
+        private:
+            struct BillboardAdministration{ bool usedYet; Billboard* billy; };
+
+            // Variabeln::
+            std::list<WeakPtr<Pawn>> pawnsIn_; //!< List of the pawns that this instance of SpaceBoundaries has to handle.
+
+            std::vector<BillboardAdministration> billboards_;
+
+            int reaction_; //!< Values: 0, 1, 2.
+                           //!< 0: Reflection on boundary (Standard).
+                           //!< 1: Decrease-Health-Mode.
+                           //!< 2: Inverted Version of 0. Prohibit to fly INTO a defined area.
+            float maxDistance_; //!<  Maximum allowed distance.
+            float warnDistance_; //!< Distance in which a warning is displayed.
+            float showDistance_; //!< Distance at which the boundaries are displayed.
+
+            float healthDecrease_; //!< Rate of health loss.
+
+            //RadarViewable* centerRadar_; //!< Representation of the space boundary in the radar.
+
+            // Funktionen::
+            float computeDistance(WorldEntity *item); //!< Compute distance to center point.
+            void displayWarning(const std::string warnText); //!< TODO: Implement.
+            void displayBoundaries(Pawn *item, float alpha);
+            void conditionalBounceBack(Pawn *item, float currentDistance, float dt);
+            void bounceBack(Pawn *item, Vector3 *normal, Vector3 *velocity);
+            bool isHumanPlayer(Pawn *item);
+
+            void checkWhoIsIn(); //!< Update the list 'pawnsIn_'.
+
+            void positionBillboard(const Vector3& position, float alpha); //!< Display a Billboard at the position 'position'.
+            void setBillboardOptions(Billboard *billy);
+            void removeAllBillboards(); //!< Hide all elements of '*billboard_' and set their attribute 'usedYet' to 0.
+    };
+}
+
+#endif /* _SpaceBoundaries_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/Turret.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Turret.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Turret.cc	(revision 11817)
@@ -0,0 +1,285 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Marian Runo, Martin Mueller
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Turret.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+#include <OgreSceneManager.h>
+
+
+namespace orxonox
+{
+    RegisterClass(Turret);
+
+
+
+    /**
+        @brief 
+        Sets default values for all variables. Also hides the turret from the radar.
+
+        @param context
+        The context
+     */
+    Turret::Turret(Context* context) : Pawn(context)
+    {
+        RegisterObject(Turret);
+        this->rotationThrust_ = 50;
+        this->startDir_ = Vector3::ZERO;
+        this->localZ_ = Vector3::UNIT_Z;
+        this->localY_ = Vector3::UNIT_Y;
+        this->localX_ = Vector3::UNIT_X;
+        this->maxAttackRadius_ = 200;
+        this->minAttackRadius_ = 0;
+        this->maxPitch_ = 90;
+        this->maxYaw_ = 90;
+        this->once_ = false;
+        this->rotation_ = Quaternion::IDENTITY;
+
+        this->setRadarVisibility(false);
+
+        //this->rayTest_ = this->getScene()->getSceneManager()->createRayQuery(Ogre::Ray());
+    }
+
+    /**
+        @brief 
+        Destructor. Destroys the rayTest_ element (if it was used)  .
+     */
+    Turret::~Turret()
+    {
+        //this->getScene()->getSceneManager()->destroyQuery(this->rayTest_);
+    }
+
+    /**
+        @brief
+        Checks, if a WorldEntity is inside the turret's range.
+
+        This function is safe to use on turrets that are attached, rotated, etc.
+        The turret's range is determined with the maxPitch, maxYaw, and the two attackRadius.
+
+        @param target
+        The WorldEntity to check
+
+        @return
+        The squared distance to the position. -1, if it's ouside of range
+    */
+    float Turret::isInRange(const WorldEntity* target )
+    {
+        //Check distance
+        Vector3 distance = target->getWorldPosition() - this->getWorldPosition();
+        float distanceVal = distance.squaredLength();
+        if(distanceVal > (this->maxAttackRadius_ * this->maxAttackRadius_) || distanceVal < (this->minAttackRadius_ * this->minAttackRadius_))
+        {
+            return -1.f;
+        }
+
+        //Check pitch
+        Vector3 dir = getTransformedVector(distance, this->localX_, this->localY_, this->localZ_);
+        Vector3 dirProjected = dir;
+        dirProjected.x = 0;
+        Vector3 startDirProjected = this->startDir_;
+        startDirProjected.x = 0;
+        Ogre::Real angle = startDirProjected.angleBetween(dirProjected).valueDegrees();
+        if(angle > this->maxPitch_)
+        {
+            return -1.f;
+        }
+
+        //Check yaw
+        dirProjected = dir;
+        dirProjected.y = 0;
+        startDirProjected = this->startDir_;
+        startDirProjected.y = 0;
+        angle = startDirProjected.angleBetween(dirProjected).valueDegrees();
+        if(angle > this->maxYaw_)
+        {
+            return -1.f;
+        }
+
+        //TODO: Finish this. Find a way to convert objects from Ogre to Orxonox
+        /*Ogre::Ray ray = Ogre::Ray(this->getWorldPosition(), distance);
+        this->rayTest_->setRay(ray);
+        Ogre::RaySceneQueryResult result = this->rayTest_->execute();*/
+
+
+        return distanceVal;
+    }
+
+    /**
+        @brief
+        Rotates the turret to make it aim at a certain position.
+
+        @note
+        There are no checks, if the position is valid (i.e. if the turret is allowed to aim there).
+        This function must be called again for every tick, or the turret will stop rotating.
+
+        @param position
+        The position to aim at
+    */
+    void Turret::aimAtPosition(const Vector3& position)
+    {
+        Vector3 currDir = this->getWorldOrientation() * WorldEntity::FRONT;
+        Vector3 targetDir = position - this->getWorldPosition();
+
+        this->rotation_ = currDir.getRotationTo(targetDir);
+    }
+
+    /**
+        @brief
+        Does currently nothing.
+
+        Should rotate the turret with the specified pitch. Contains a failed attempt at limiting said rotation.
+    */
+    void Turret::rotatePitch(const Vector2& value)
+    {    
+        //This is a failed attempt at limiting the turret's rotation. It's handled in the controller (for now?)
+        /*
+        Vector3 currentDir = getTransformedVector(this->getOrientation() * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
+        Vector3 currentDirProjected = currentDir;
+        currentDirProjected.x = 0;
+        Vector3 startDirProjected = this->startDir_;
+        startDirProjected.x = 0;     
+        Ogre::Real angle = startDirProjected.angleBetween(currentDirProjected).valueDegrees();
+        //orxout() << "Pitch: " << angle << endl;   
+        //if(angle < this->maxPitch_ || (currentDirProjected.y <= 0 && value.x > 0) || (currentDirProjected.y > 0 && value.x < 0) )
+        {
+            this->localAngularAcceleration_.setX(this->localAngularAcceleration_.x() + value.x*0.8f);
+        }
+        */
+    }
+
+    /**
+        @brief
+        Does currently nothing.
+
+        Should rotate the turret with the specified yaw. Contains a failed attempt at limiting said rotation.
+    */
+    void Turret::rotateYaw(const Vector2& value)
+    {
+        //This is a failed attempt at limiting the turret's rotation. It's handled in the controller (for now?)
+        /*
+        Vector3 currentDir = getTransformedVector(this->getOrientation() * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
+        Vector3 currentDirProjected = currentDir;
+        currentDirProjected.y = 0;
+        Vector3 startDirProjected = this->startDir_;
+        startDirProjected.y = 0;
+        Ogre::Real angle = startDirProjected.angleBetween(currentDirProjected).valueDegrees();
+        orxout() << "Yaw: " << angle << endl;
+        if(angle < this->maxYaw_ || (currentDirProjected.x <= 0 && value.x < 0) || (currentDirProjected.x > 0 && value.x > 0))
+        {
+            this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x*0.8f);
+        }
+        */
+    }
+
+    /**
+        @brief
+        Does currently nothing.
+
+        May be used to limit turret's rotation in the future.
+    */
+    void Turret::rotateRoll(const Vector2& value)
+    {
+    }
+
+    /**
+        @brief
+        Loads parameters from xml
+
+        Parameters loaded are: rotationThrust, maxAttackRadius, minAttackRadius, maxYaw, maxPitch
+    */
+    void Turret::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Turret, XMLPort, xmlelement, mode);
+        
+        XMLPortParamVariable(Turret, "rotationThrust", rotationThrust_, xmlelement, mode);
+        XMLPortParam(Turret, "maxAttackRadius", setMaxAttackRadius, getMaxAttackRadius, xmlelement, mode);
+        XMLPortParam(Turret, "minAttackRadius", setMinAttackRadius, getMinAttackRadius, xmlelement, mode);
+        XMLPortParam(Turret, "maxYaw", setMaxYaw, getMaxYaw, xmlelement, mode);
+        XMLPortParam(Turret, "maxPitch", setMaxPitch, getMaxPitch, xmlelement, mode);
+        XMLPortParam(Turret, "rotationThrust", setRotationThrust, getRotationThrust, xmlelement, mode);
+    }
+
+    /**
+        @brief
+        The turret's actions are done here.
+
+        Every tick, the turret gets rotated if it should, and the local axes get updated with the parent's rotation.
+    
+        @param dt
+        Duration of the tick
+    */
+    void Turret::tick(float dt)
+    {
+        SUPER(Turret, tick, dt);
+
+        //Stuff isn't properly initialized in the c'tor, so we have to do it like this
+        if(!this->once_)
+        {
+            //Account for rotations done in xml
+            Quaternion startOrient = this->getOrientation();
+            this->localXStart_ = startOrient * this->localX_;
+            this->localXStart_.normalise();
+            this->localX_ = this->localXStart_;
+            this->localYStart_ = startOrient * this->localY_;
+            this->localYStart_.normalise();
+            this->localY_ = this->localYStart_;
+            this->localZStart_ = startOrient * this->localZ_;
+            this->localZStart_.normalise();
+            this->localZ_ = this->localZStart_;
+
+            //startDir should always be (0,0,-1)
+            this->startDir_ = getTransformedVector(startOrient * WorldEntity::FRONT, this->localX_, this->localY_, this->localZ_);
+
+            this->once_ = true;
+
+        }
+
+        //Adjust local axes to parent's rotation
+        WorldEntity* parent = this->getParent();
+        if(parent)
+        {
+            Quaternion parentrot = parent->getWorldOrientation();
+            this->localX_ = parentrot * this->localXStart_;
+            this->localY_ = parentrot * this->localYStart_;
+            this->localZ_ = parentrot * this->localZStart_;
+        }
+
+        //rotate
+        if(this->rotation_ != Quaternion::IDENTITY)
+        {
+            //Don't make the rotation instantaneous. Use an arbitrary interpolation, not that great...
+            //TODO: make the rotation better (constant velocity etc.). At the moment, the turret rotates
+            //slower the closer it is to the destination
+            Quaternion drot = Quaternion::nlerp(dt*this->rotationThrust_/20.f, Quaternion::IDENTITY, this->rotation_);
+            this->rotate(drot, WorldEntity::TransformSpace::World);
+            this->rotation_ = Quaternion::IDENTITY;
+        }
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/Turret.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/Turret.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/Turret.h	(revision 11817)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Marian Runo, Martin Mueller
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Turret.h
+    @brief Definition of the Turret class.
+    @ingroup Objects
+*/
+
+#ifndef _Turret_H__
+#define _Turret_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "worldentities/pawns/Pawn.h"
+#include <OgreSceneQuery.h>
+
+namespace orxonox
+{
+    /**
+    @brief
+        Creates a turret with limited rotation. The point of this class is to be able to attach
+        a turret to a spaceship or a spacestation which is more or less completely autonomous in
+        it's behaviour.
+
+        This class also contains a custom local coordinate system, which gets initially rotated through xml, and
+        afterwards is updated with the parent's rotation (if there is one). This allows for almost trivialal calculation
+        of pitch, yaw and roll through coordinate transformation. (TODO: Ogre should do something like this already, investigate...)
+        
+
+    @note
+        The rotation isn't limited "physically". You have to call isInRange to find out if the turret is allowed to shoot at a target.
+    */
+    class _ObjectsExport Turret : public Pawn
+    {
+        public:
+            Turret(Context* context);
+            virtual ~Turret();
+
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+            virtual float isInRange(const WorldEntity* target);
+            virtual void aimAtPosition(const Vector3 &position);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+            /** @brief Sets the maximum distance the turret is allowed to shoot. @param radius The distance*/
+            inline void setMaxAttackRadius(float radius)
+                { this->maxAttackRadius_ = radius; }
+
+            /** @brief Sets the minimum distance the turret is allowed to shoot. @param radius The distance*/
+            inline void setMinAttackRadius(float radius)
+                { this->minAttackRadius_ = radius; }
+
+            /** @brief Sets the maximum pitch the turret can have (in both directions). @param pitch The pitch (in one direction)*/
+            inline void setMaxPitch(float pitch)
+                { this->maxPitch_ = pitch; }
+
+            /** @brief Sets the maximum yaw the turret can have (in both directions). @param yaw The yaw (in one direction)*/
+            inline void setMaxYaw(float yaw)
+                { this->maxYaw_ = yaw; }
+
+            /** @brief Returns the maximum distance the turret is allowed to shoot. @return The distance */
+            inline float getMaxAttackRadius() const
+                { return this->maxAttackRadius_; }                
+
+            /** @brief Returns the minimum distance the turret is allowed to shoot. @return The distance */
+            inline float getMinAttackRadius() const
+                { return this->minAttackRadius_; }   
+
+            /** @brief Returns the maximum pitch the turret can have. @return The pitch */
+            inline float getMaxPitch() const
+                { return this->maxPitch_; }
+
+            /** @brief Returns the maximum yaw the turret can have. @return The yaw */
+            inline float getMaxYaw() const
+                { return this->maxYaw_; }
+
+            inline void setRotationThrust(float rotationthrust)
+                { this->rotationThrust_ = rotationthrust; }
+
+            inline float getRotationThrust()
+                { return this->rotationThrust_; }
+
+        protected:
+            Vector3 startDir_; //!< The initial facing direction, in local coordinates.
+            Vector3 localZ_; //!< The local z-axis, includes for the parent's rotation and rotations done in xml.
+            Vector3 localY_; //!< The local y-axis, includes for the parent's rotation and rotations done in xml.
+            Vector3 localX_; //!< The local x-axis, includes for the parent's rotation and rotations done in xml.      
+            Quaternion rotation_; //!< The rotation to be done by the turret.
+
+        private:
+            bool once_; //!< Flag for executing code in the tick function only once.
+
+            Vector3 localZStart_; //!< The local z-axis, without the parent's rotation.
+            Vector3 localYStart_; //!< The local y-axis, without the parent's rotation.
+            Vector3 localXStart_; //!< The local x-axis, without the parent's rotation.
+            float maxAttackRadius_; //!< The maximum distance the turret is allowed to shoot.
+            float minAttackRadius_; //!< The minimum distance the turret is allowed to shoot.
+            Ogre::Real maxPitch_; //!< The maxmium pitch the turret can have (on one side).
+            Ogre::Real maxYaw_; //!< The maxmium yaw the turret can have (on one side).
+            float rotationThrust_;  //!< The velocity the turret rotates with.
+            Ogre::RaySceneQuery* rayTest_; //!< Used to perform a raytest, currently unused @see isInRange
+
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/AbstractRadiusHeightCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/AbstractRadiusHeightCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/AbstractRadiusHeightCollisionShape.cc	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+/**
+    @file AbstractRadiusHeightCollisionShape.cc
+    @brief Implementation of the AbstractRadiusHeightCollisionShape class.
+*/
+
+#include "AbstractRadiusHeightCollisionShape.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(AbstractRadiusHeightCollisionShape).inheritsFrom<CollisionShape>();
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    AbstractRadiusHeightCollisionShape::AbstractRadiusHeightCollisionShape(Context* context) : CollisionShape(context)
+    {
+        RegisterObject(AbstractRadiusHeightCollisionShape);
+
+        this->radius_ = 1.0f;
+        this->height_ = 1.0f;
+
+        this->registerVariables();
+    }
+
+    void AbstractRadiusHeightCollisionShape::registerVariables()
+    {
+        registerVariable(this->radius_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::updateShape));
+        registerVariable(this->height_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::updateShape));
+    }
+
+    void AbstractRadiusHeightCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(AbstractRadiusHeightCollisionShape, XMLPort, xmlelement, mode);
+
+        XMLPortParam(AbstractRadiusHeightCollisionShape, "radius", setRadius, getRadius, xmlelement, mode);
+        XMLPortParam(AbstractRadiusHeightCollisionShape, "height", setHeight, getHeight, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the scale of the AbstractRadiusHeightCollisionShape has changed.
+    */
+    void AbstractRadiusHeightCollisionShape::changedScale()
+    {
+        CollisionShape::changedScale();
+
+        // Resize the internal collision shape
+        // TODO: Assuming setLocalScaling works.
+        //this->collisionShape_->setLocalScaling(multi_cast<btVector3>(this->getScale3D()));
+        if(!this->hasUniformScaling())
+        {
+            orxout(internal_error) << "AbstractRadiusHeightCollisionShape: Non-uniform scaling is not yet supported." << endl;
+            return;
+        }
+
+        this->radius_ *= this->getScale();
+        this->height_ *= this->getScale();
+        this->updateShape();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/AbstractRadiusHeightCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/AbstractRadiusHeightCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/AbstractRadiusHeightCollisionShape.h	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+/**
+    @file AbstractRadiusHeightCollisionShape.h
+    @brief Definition of the AbstractRadiusHeightCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _AbstractRadiusHeightCollisionShape_H__
+#define _AbstractRadiusHeightCollisionShape_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "collisionshapes/CollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet collision shapes with radius and height.
+
+    @ingroup Collisionshapes
+    */
+    class _ObjectsExport AbstractRadiusHeightCollisionShape : public CollisionShape
+    {
+        public:
+            AbstractRadiusHeightCollisionShape(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            /**
+            @brief Set the radius of the AbstractRadiusHeightCollisionShape.
+                   If the radius changes, this causes the internal collision shape to be recreated.
+            @param value The radius to be set.
+            @return Returns true if the radius has changed, false if not.
+            */
+            inline bool setRadius(float value)
+                { if(this->radius_ == value) return false; this->radius_ = value; updateShape(); return true; }
+            /**
+            @brief Get the radius of the AbstractRadiusHeightCollisionShape.
+            @return Returns the radius of the AbstractRadiusHeightCollisionShape.
+            */
+            inline float getRadius() const
+                { return radius_; }
+
+            /**
+            @brief Set the height of the AbstractRadiusHeightCollisionShape.
+                   If the height changes, this causes the internal collision shape to be recreated.
+            @param value The height to be set.
+            @return Returns true if the height has changed, false if not.
+            */
+            inline bool setHeight(float value)
+                { if(this->height_ == value) return false; this->height_ = value; updateShape(); return true; }
+            /**
+            @brief Get the height of the AbstractRadiusHeightCollisionShape.
+            @return Returns the height of the AbstractRadiusHeightCollisionShape.
+            */
+            inline float getHeight() const
+                { return this->height_; }
+
+            virtual void changedScale(); // Is called when the scale of the AbstractRadiusHeightCollisionShape has changed.
+
+        private:
+            void registerVariables();
+
+            float radius_; //!< The radius of the AbstractRadiusHeightCollisionShape.
+            float height_; //!< The height of the AbstractRadiusHeightCollisionShape.
+     };
+}
+
+#endif /* _AbstractRadiusHeightCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/BoxCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/BoxCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/BoxCollisionShape.cc	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BoxCollisionShape.cc
+    @brief Implementation of the BoxCollisionShape class.
+*/
+
+#include "BoxCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btBoxShape.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterClass(BoxCollisionShape);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    BoxCollisionShape::BoxCollisionShape(Context* context) : CollisionShape(context)
+    {
+        RegisterObject(BoxCollisionShape);
+
+        this->halfExtents_ = Vector3(1, 1, 1);
+        this->updateShape();
+
+        this->registerVariables();
+    }
+
+    void BoxCollisionShape::registerVariables()
+    {
+        registerVariable(this->halfExtents_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::updateShape));
+    }
+
+    void BoxCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(BoxCollisionShape, XMLPort, xmlelement, mode);
+
+        XMLPortParam(BoxCollisionShape, "halfExtents",  setHalfExtents,  getHalfExtents,  xmlelement, mode);
+        XMLPortParamLoadOnly(BoxCollisionShape, "width",  setWidth,  xmlelement, mode);
+        XMLPortParamLoadOnly(BoxCollisionShape, "height", setHeight, xmlelement, mode);
+        XMLPortParamLoadOnly(BoxCollisionShape, "length", setLength, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the scale of the BoxCollisionShape has changed.
+    */
+    void BoxCollisionShape::changedScale()
+    {
+        CollisionShape::changedScale();
+
+        // Resize the internal collision shape
+        // TODO: Assuming setLocalScaling works.
+        // this->collisionShape_->setLocalScaling(multi_cast<btVector3>(this->getScale3D()));
+        if(!this->hasUniformScaling())
+        {
+            orxout(internal_error) << "BoxCollisionShape: Non-uniform scaling is not yet supported." << endl;
+            return;
+        }
+
+        this->setHalfExtents(this->halfExtents_ * this->getScale());
+    }
+
+    /**
+    @brief
+        Creates a new internal collision shape for the BoxCollisionShape.
+    @return
+        Returns a pointer to the newly created btBoxShape.
+    */
+    btCollisionShape* BoxCollisionShape::createNewShape() const
+    {
+        return new btBoxShape(multi_cast<btVector3>(this->halfExtents_));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/BoxCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/BoxCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/BoxCollisionShape.h	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BoxCollisionShape.h
+    @brief Definition of the BoxCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _BoxCollisionShape_H__
+#define _BoxCollisionShape_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "util/Math.h"
+#include "collisionshapes/CollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet box collision shape class btBoxShape.
+
+    @author
+        Reto Grieder
+
+    @see btBoxShape
+    @ingroup Collisionshapes
+    */
+    class _ObjectsExport BoxCollisionShape : public CollisionShape
+    {
+        public:
+            BoxCollisionShape(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            /**
+            @brief Set the half extents of the BoxCollisionShape.
+                   If the half extent changes, this causes the internal collision shape to be recreated.
+            @param extents A vector with the half extents.
+                   The x-component is half the length, the y-component is half the height and the z-component is half the width.
+            @return Returns true if the half extent has changed, false if not.
+            */
+            inline bool setHalfExtents(const Vector3& extents)
+                { if(this->halfExtents_ == extents) return false; this->halfExtents_ = extents; updateShape(); return true; }
+            /**
+            @brief Get the half extents of the BoxCollisionShape.
+            @return Returns a vector containing the half extents.
+            */
+            inline const Vector3& getHalfExtents() const
+                { return halfExtents_;}
+
+            /**
+            @brief Set the width of the BoxCollisionShape.
+                   If the width changes, this causes the internal collision shape to be recreated.
+            @param value The width to be set.
+            @return Returns true if the width has changed, false if not.
+            */
+            inline bool setWidth(float value)
+                { if(this->halfExtents_.z == value/2.0f) return false; this->halfExtents_.z = value / 2.0f; updateShape(); return true; }
+            /**
+            @brief Get the width of the BoxCollisionShape.
+            @return Returns the width of the BoxCollisionShape.
+            */
+            inline float getWidth() const
+                { return this->halfExtents_.z * 2.0f; }
+
+            /**
+            @brief Set the height of the BoxCollisionShape.
+                   If the height changes, this causes the internal collision shape to be recreated.
+            @param value The height to be set.
+            @return Returns true if the height has changed, false if not.
+            */
+            inline bool setHeight(float value)
+                { if(this->halfExtents_.y == value/2.0f) return false; this->halfExtents_.y = value / 2.0f; updateShape(); return true; }
+            /**
+            @brief Get the height of the BoxCollisionShape.
+            @return Returns the height of the BoxCollisionShape.
+            */
+            inline float getHeight() const
+                { return this->halfExtents_.y * 2.0f; }
+
+            /**
+            @brief Set the length of the BoxCollisionShape.
+                   If the length changes, this causes the internal collision shape to be recreated.
+            @param value The length to be set.
+            @return Returns true if the length has changed, false if not.
+            */
+            inline bool setLength(float value)
+                { if(this->halfExtents_.x == value/2.0f) return false; this->halfExtents_.x = value / 2.0f; updateShape(); return true; }
+            /**
+            @brief Get the length of the BoxCollisionShape.
+            @return Returns the length of the BoxCollisionShape.
+            */
+            inline float getLength() const
+                { return this->halfExtents_.x * 2.0f; }
+
+            virtual void changedScale(); // Is called when the scale of the BoxCollisionShape has changed.
+
+        private:
+            void registerVariables();
+
+            btCollisionShape* createNewShape() const; // Creates a new internal collision shape for the BoxCollisionShape.
+
+            Vector3 halfExtents_; //!< The half extents of the BoxCollisionShape. The x-component is half the length, the y-component is half the height and the z-component is half the width.
+     };
+}
+
+#endif /* _BoxCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,8 @@
+ADD_SOURCE_FILES(OBJECTS_SRC_FILES
+  AbstractRadiusHeightCollisionShape.cc
+  BoxCollisionShape.cc
+  ConeCollisionShape.cc
+  CylinderCollisionShape.cc
+  PlaneCollisionShape.cc
+  SphereCollisionShape.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/ConeCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/ConeCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/ConeCollisionShape.cc	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ConeCollisionShape.cc
+    @brief Implementation of the ConeCollisionShape class.
+*/
+
+#include "ConeCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btConeShape.h>
+
+#include "core/CoreIncludes.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterClass(ConeCollisionShape);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    ConeCollisionShape::ConeCollisionShape(Context* context) : AbstractRadiusHeightCollisionShape(context)
+    {
+        RegisterObject(ConeCollisionShape);
+
+        updateShape();
+    }
+
+    /**
+    @brief
+        Creates a new internal collision shape for the ConeCollisionShape.
+    @return
+        Returns a pointer to the newly created btConeShape.
+    */
+    btCollisionShape* ConeCollisionShape::createNewShape() const
+    {
+        return new btConeShape(this->getRadius(), this->getHeight());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/ConeCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/ConeCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/ConeCollisionShape.h	(revision 11817)
@@ -0,0 +1,64 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ConeCollisionShape.h
+    @brief Definition of the ConeCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _ConeCollisionShape_H__
+#define _ConeCollisionShape_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "AbstractRadiusHeightCollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet cone collision shape class btConeShape.
+
+    @author
+        Reto Grieder
+
+    @see btConeShape
+    @ingroup Collisionshapes
+    */
+    class _ObjectsExport ConeCollisionShape : public AbstractRadiusHeightCollisionShape
+    {
+        public:
+            ConeCollisionShape(Context* context);
+
+        private:
+            btCollisionShape* createNewShape() const; // Creates a new internal collision shape for the ConeCollisionShape.
+     };
+}
+
+#endif /* _ConeCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CylinderCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CylinderCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CylinderCollisionShape.cc	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CylinderCollisionShape.cc
+    @brief Implementation of the CylinderCollisionShape class.
+*/
+
+#include "CylinderCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btCylinderShape.h>
+
+#include "core/CoreIncludes.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterClass(CylinderCollisionShape);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    CylinderCollisionShape::CylinderCollisionShape(Context* context) : AbstractRadiusHeightCollisionShape(context)
+    {
+        RegisterObject(CylinderCollisionShape);
+
+        updateShape();
+    }
+
+    /**
+    @brief
+        Creates a new internal collision shape for the CylinderCollisionShape.
+    @return
+        Returns a pointer to the newly created btCylinderShape.
+    */
+    btCollisionShape* CylinderCollisionShape::createNewShape() const
+    {
+        // divide height by 2 because bullet expects the half extents
+        return new btCylinderShape(btVector3(this->getRadius(), this->getHeight() / 2, 0));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CylinderCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CylinderCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/CylinderCollisionShape.h	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CylinderCollisionShape.h
+    @brief Definition of the CylinderCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _CylinderCollisionShape_H__
+#define _CylinderCollisionShape_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "AbstractRadiusHeightCollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet Cylinder collision shape class btCylinderShape.
+
+    @see btCylinderShape
+    @ingroup Collisionshapes
+    */
+    class _ObjectsExport CylinderCollisionShape : public AbstractRadiusHeightCollisionShape
+    {
+        public:
+            CylinderCollisionShape(Context* context);
+
+        private:
+            btCollisionShape* createNewShape() const; // Creates a new internal collision shape for the CylinderCollisionShape.
+     };
+}
+
+#endif /* _CylinderCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/PlaneCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/PlaneCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/PlaneCollisionShape.cc	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Stypinski
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PlaneCollisionShape.cc
+    @brief Implementation of the PlaneCollisionShape class.
+*/
+
+#include "PlaneCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btStaticPlaneShape.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterClass(PlaneCollisionShape);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    PlaneCollisionShape::PlaneCollisionShape(Context* context) : CollisionShape(context)
+    {
+        RegisterObject(PlaneCollisionShape);
+
+        this->normal_ = Vector3(0, 1, 0);
+        this->offset_ = 0.0f;
+        updateShape();
+
+        this->registerVariables();
+    }
+
+    void PlaneCollisionShape::registerVariables()
+    {
+        registerVariable(this->normal_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::updateShape));
+        registerVariable(this->offset_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::updateShape));
+    }
+
+    void PlaneCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PlaneCollisionShape, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PlaneCollisionShape, "normal", setNormal, getNormal, xmlelement, mode);
+        XMLPortParam(PlaneCollisionShape, "offset", setOffset, getOffset, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the scale of the PlaneCollisionShape has changed.
+    */
+    void PlaneCollisionShape::changedScale()
+    {
+        CollisionShape::changedScale();
+
+        // Resize the internal collision shape
+        // TODO: Assuming setLocalScaling works.
+        //this->collisionShape_->setLocalScaling(multi_cast<btVector3>(this->getScale3D()));
+        if(!this->hasUniformScaling())
+        {
+            orxout(internal_error) << "PlaneCollisionShape: Non-uniform scaling is not yet supported." << endl;
+            return;
+        }
+
+        this->setOffset(this->offset_*this->getScale());
+    }
+
+    /**
+    @brief
+        Creates a new internal collision shape for the PlaneCollisionShape.
+    @return
+        Returns a pointer to the newly created btStaticPlaneShape.
+    */
+    btCollisionShape* PlaneCollisionShape::createNewShape() const
+    {
+        return new btStaticPlaneShape(multi_cast<btVector3>(this->normal_), this->offset_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/PlaneCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/PlaneCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/PlaneCollisionShape.h	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Stypinski
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PlaneCollisionShape.h
+    @brief Definition of the PlaneCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _PlaneCollisionShape_H__
+#define _PlaneCollisionShape_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "util/Math.h"
+#include "collisionshapes/CollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet plane collision shape class btStaticPlaneShape.
+
+    @author
+        Martin Stypinski
+
+    @see btStaticPlaneShape
+    @ingroup Collisionshapes
+    */
+    class _ObjectsExport PlaneCollisionShape : public CollisionShape
+    {
+        public:
+            PlaneCollisionShape(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            /**
+            @brief Set the normal of the PlaneCollisionShape.
+                   If the normal changes, this causes the internal collision shape to be recreated.
+            @param normal The normal vector to be set.
+            @return Returns true if the normal has changed, false if not.
+            */
+            inline bool setNormal(const Vector3& normal)
+                { if(this->normal_ == normal) return false; this->normal_ = normal; updateShape(); return true; }
+            /**
+            @brief Get the normal of the PlaneCollisionShape.
+            @return Returns the normal vector of the PlaneCollisionShape.
+            */
+            inline const Vector3& getNormal() const
+                { return normal_;}
+
+            /**
+            @brief Set the offset of the PlaneCollisionShape.
+                   If the offset changes, this causes the internal collision shape to be recreated.
+            @param offset The offset to be set.
+            @return Returns true if the offset has changed, false if not.
+            */
+            inline bool setOffset(float offset)
+                { if(this->offset_ == offset) return false; this->offset_ = offset; updateShape(); return true; }
+            /**
+            @brief Get the offset of the PlaneCollisionShape.
+            @return Returns the offset of the PlaneCollisionShape.
+            */
+            inline float getOffset() const
+                { return this->offset_;}
+
+            virtual void changedScale(); // Is called when the scale of the PlaneCollisionShape has changed.
+
+        private:
+            void registerVariables();
+
+            btCollisionShape* createNewShape() const; // Creates a new internal collision shape for the PlaneCollisionShape.
+
+            Vector3 normal_; //!< The normal vector of the PlaneCollisionShape.
+            float   offset_; //!< The offset of the PlaneCollisionShape.
+     };
+}
+
+#endif /* _PlaneCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/SphereCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/SphereCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/SphereCollisionShape.cc	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SphereCollisionShape.cc
+    @brief Implementation of the SphereCollisionShape class.
+*/
+
+#include "SphereCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btSphereShape.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterClass(SphereCollisionShape);
+
+    /**
+    @brief
+        Constructor. registers and initializes the object.
+    */
+    SphereCollisionShape::SphereCollisionShape(Context* context) : CollisionShape(context)
+    {
+        RegisterObject(SphereCollisionShape);
+
+        this->radius_ = 1.0f;
+        updateShape();
+
+        this->registerVariables();
+    }
+
+    void SphereCollisionShape::registerVariables()
+    {
+        registerVariable(this->radius_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::updateShape));
+    }
+
+    void SphereCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SphereCollisionShape, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SphereCollisionShape, "radius", setRadius, getRadius, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the scale of the SphereCollisionShape has changed.
+    */
+    void SphereCollisionShape::changedScale()
+    {
+        CollisionShape::changedScale();
+
+        // Resize the internal collision shape
+        // TODO: Assuming setLocalScaling works.
+        //this->collisionShape_->setLocalScaling(multi_cast<btVector3>(this->getScale3D()));
+        if(!this->hasUniformScaling())
+        {
+            orxout(internal_error) << "SphereCollisionShape: Non-uniform scaling is not yet supported." << endl;
+            return;
+        }
+
+        this->setRadius(this->radius_*this->getScale());
+    }
+
+    /**
+    @brief
+        Creates a new internal collision shape for the SphereCollisionShape.
+    @return
+        Returns a pointer to the newly created btSphereShape.
+    */
+    btCollisionShape* SphereCollisionShape::createNewShape() const
+    {
+        return new btSphereShape(this->radius_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/SphereCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/SphereCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/collisionshapes/SphereCollisionShape.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SphereCollisionShape.h
+    @brief Definition of the SphereCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _SphereCollisionShape_H__
+#define _SphereCollisionShape_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "collisionshapes/CollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet sphere collision shape class btSphereShape.
+
+    @author
+        Reto Grieder
+
+    @see btSphereShape
+    @ingroup Collisionshapes
+    */
+    class _ObjectsExport SphereCollisionShape : public CollisionShape
+    {
+        public:
+            SphereCollisionShape(Context* context);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            /**
+            @brief Set the radius of the SphereCollisionShape.
+                   If the radius changes, this causes the internal collision shape to be recreated.
+            @param radius The radius to be set.
+            @return Returns true if the radius has changed, false if not.
+            */
+            inline bool setRadius(float radius)
+                { if(this->radius_ == radius) return false; this->radius_ = radius; updateShape(); return true; }
+            /**
+            @brief Get the radius of the SphereCollisionShape.
+            @return Returns the radius of the SphereCollisionShape.
+            */
+            inline float getRadius() const
+                { return this->radius_; }
+
+            virtual void changedScale(); // Is called when the scale of the SphereCollisionShape has changed.
+
+        private:
+            void registerVariables();
+
+            btCollisionShape* createNewShape() const;
+
+            float radius_; //!< The radius of the SphereCollisionShape.
+    };
+}
+
+#endif /* _SphereCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/controllers/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/controllers/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/controllers/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,4 @@
+ADD_SOURCE_FILES(OBJECTS_SRC_FILES
+  TurretController.cc
+  TeamTargetProxy.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/objects/controllers/TeamTargetProxy.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/controllers/TeamTargetProxy.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/controllers/TeamTargetProxy.cc	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Mueller
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TeamTargetProxy.h"
+#include "core/CoreIncludes.h"
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(TeamTargetProxy);
+
+   /**
+       @brief 
+       Sets default values for all variables.
+
+       @param context
+       The context
+    */
+    TeamTargetProxy::TeamTargetProxy(Context* context) : FormationController(context)
+    {
+        RegisterObject(TeamTargetProxy);
+
+        this->once_ = false;
+    }
+
+    /**
+        @brief 
+        Destructor. Nothing to see here.
+     */
+    TeamTargetProxy::~TeamTargetProxy()
+    {
+    }
+
+    /**
+        @brief
+        Copies the team and the target from the parent.
+
+        That's all there is.
+    */
+    void TeamTargetProxy::tick(float dt)
+    {
+        if (!this->isActive() || !this->getControllableEntity())
+            return;
+
+        ControllableEntity* parent = orxonox_cast<ControllableEntity*> (this->getControllableEntity()->getParent());
+
+        if(this->getTeam() != -1 && !this->once_ && parent)
+        {
+            orxout(internal_warning) << "TeamTargetProxy: Team already set, may result in undesired behaviour. Will get overridden by the parent's team." << endl;
+        }
+
+        if(!this->once_)
+            this->once_ = true;
+
+        //Teams aren't set immediately, after creation, so we have to check every tick...
+        if(parent)
+        {
+            Controller* parentcontroller = parent->getController();
+            if(parentcontroller)
+            {
+                this->setTeam(parentcontroller->getTeam());
+            }
+            else
+            {
+                this->setTeam(parent->getTeam());
+            }
+            this->getControllableEntity()->setTeam(parent->getTeam());
+        }
+
+        if(parent)
+        {
+            Pawn* parenttarget = orxonox_cast<Pawn*>(parent->getTarget());
+            if(parenttarget)
+            {
+                this->setTarget(parenttarget);
+                this->getControllableEntity()->setTarget(parenttarget);
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/controllers/TeamTargetProxy.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/controllers/TeamTargetProxy.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/controllers/TeamTargetProxy.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Mueller
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamTargetProxy_H__
+#define _TeamTargetProxy_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "controllers/FormationController.h"
+
+ namespace orxonox
+ {
+    /**
+        @brief
+        A controller, that just copies the team and the target of a parent for itself and it's controllable entity.
+
+        Useful for following (and similar) situations: (-> means attached to)
+            turret (rotates) -> some kind of turret base (looks nice) -> spaceship (flies around)
+            The turret has a controller that wants to copy the spaceship's target and team. In this case it doesn't work though,
+            because the turret isn't directly attached to the spaceship. Here's where this controller comes in. Drawback: the base
+            has to be controllable and ticks every second (performance?)
+    */
+    class _ObjectsExport TeamTargetProxy : public FormationController, public Tickable
+    {
+        public:
+            TeamTargetProxy(Context* context);
+            virtual ~TeamTargetProxy();
+
+            virtual void tick(float dt);
+
+        private:
+            bool once_; //!< Flag for executing code in the tick function only once.
+    };
+ }
+
+ #endif
Index: /code/branches/RacingBots_FS18/src/modules/objects/controllers/TurretController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/controllers/TurretController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/controllers/TurretController.cc	(revision 11817)
@@ -0,0 +1,204 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Mueller
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TurretController.h"
+#include "worldentities/pawns/Pawn.h"
+#include "objects/Turret.h"
+#include "core/object/ObjectList.h"
+#include "core/CoreIncludes.h"
+
+ namespace orxonox
+ {
+    RegisterClass(TurretController);
+
+    /**
+        @brief 
+        Sets default values for all variables.
+
+        @param context
+        The context
+    */
+    TurretController::TurretController(Context* context) : ArtificialController(context)
+    {
+        RegisterObject(TurretController);
+
+        this->once_ = false;
+
+    }
+
+    /**
+        @brief 
+        Destructor. Nothing to see here.
+    */
+    TurretController::~TurretController()
+    {
+
+    }
+
+    /**
+        @brief 
+        Searches a valid target for the turret to aim at.
+
+        Loops through all pawns and tests, if it is in range. Scores every pawn and chooses the best one (the one with the lowest score).
+        If the turret has a parent, try to aim at the same target the parent has, if there is one.
+
+        @see targetScore
+        The function that scores the pawns.
+    */
+    void TurretController::searchTarget()
+    {
+        Turret* turret = orxonox_cast<Turret*>(this->getControllableEntity());
+
+        //The controller might find a target before teams are set, so we need to check again here.
+        if(this->target_ && turret->isInRange(target_) != -1.f && !FormationController::sameTeam(turret, this->target_, this->getGametype()))
+        {
+            return;
+        }
+        else
+        {
+            this->forgetTarget();
+            turret->setTarget(nullptr);
+        }
+
+
+        ControllableEntity* parent = orxonox_cast<ControllableEntity*>(turret->getParent());
+        if(parent)
+        {
+            Pawn* parenttarget = orxonox_cast<Pawn*>(parent->getTarget());
+            if(parenttarget && turret->isInRange(parenttarget))
+            {
+                this->setTarget(parenttarget);
+                turret->setTarget(parenttarget);
+                return;
+            }
+        }
+
+        float minScore = FLT_MAX;
+        float tempScore;
+        Pawn* minScorePawn = nullptr;
+
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if (!pawn || FormationController::sameTeam(turret, pawn, this->getGametype()))
+                continue;
+            tempScore = turret->isInRange(pawn);
+            if(tempScore != -1.f)
+            {
+                if(tempScore < minScore)
+                {
+                    minScore = tempScore;
+                    minScorePawn = pawn;
+                }
+            }
+        }
+        this->setTarget(minScorePawn);
+        turret->setTarget(minScorePawn);
+    }
+
+    /**
+        @brief 
+        Tests, if the turret is looking at the target, with a specified tolerance
+
+        This uses the world position as opposed to the local position in the old version.
+
+        @param angle
+        The tolerance, in radians
+    */
+    bool TurretController::isLookingAtTargetNew(float angle) const
+    {
+        return (getAngle(this->getControllableEntity()->getWorldPosition(), this->getControllableEntity()->getWorldOrientation() * WorldEntity::FRONT, this->target_->getWorldPosition()) < angle);
+    }
+
+    /**
+        @brief 
+        Scores a pawn as a target, based on distance and health.
+
+        The more health and distance a pawn has, the higher the score. This means lower equals better.
+
+        @param pawn
+        The pawn to score
+
+        @param distance
+        The distance. Can be squared or normed, doesn't matter as long as all are treated the same.
+    */   
+    float TurretController::targetScore(Pawn* pawn, float distance) const
+    {
+        return pawn->getHealth()/pawn->getMaxHealth() + distance;
+    }
+
+    /**
+        @brief
+        Does all the controlling of the turret.
+
+        If the turret has a parent, copies the team from there, if it's not already set.
+        Other actions are: Search a target. If a target has been found, aim and shoot at it.
+    */
+    void TurretController::tick(float dt)
+    {
+        if (!this->isActive() || !this->getControllableEntity())
+            return;
+
+
+        ControllableEntity* parent = orxonox_cast<ControllableEntity*> (this->getControllableEntity()->getParent());
+        if(this->getTeam() != -1 && !this->once_ && parent)
+        {
+            orxout(internal_warning) << "TurretController: Team already set, may result in undesired behaviour. Will get overridden by the parent's team." << endl;
+        }
+
+        if(!this->once_)
+            this->once_ = true;
+     
+        //Teams aren't set immediately, after creation, so we have to check every tick...
+        if(parent)
+        {
+            Controller* parentcontroller = parent->getController();
+            if(parentcontroller)
+            {
+                this->setTeam(parentcontroller->getTeam());
+            }
+            else
+            {
+                this->setTeam(parent->getTeam());
+            }
+            this->getControllableEntity()->setTeam(parent->getTeam());
+        }
+
+        this->searchTarget();
+        if(this->target_)
+        {
+            Turret* turret = orxonox_cast<Turret*> (this->getControllableEntity());
+            this->aimAtTarget();
+            turret->aimAtPosition(target_->getWorldPosition());
+            if(this->isLookingAtTargetNew(Degree(5).valueRadians()))
+            {
+
+                this->getControllableEntity()->fire(0);
+            }
+        }
+    }
+ }
Index: /code/branches/RacingBots_FS18/src/modules/objects/controllers/TurretController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/controllers/TurretController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/controllers/TurretController.h	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Mueller
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TurretController_H__
+#define _TurretController_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "controllers/ArtificialController.h"
+
+ namespace orxonox
+ {
+    /**
+        @brief
+        Controller for turrets. Chooses a target, and makes the turret aim/shoot at it.
+
+        The controllableEntity gets casted to Turret, so this controller won't work for anything else.
+    */
+    class _ObjectsExport TurretController : public ArtificialController, public Tickable
+    {
+        public:
+            TurretController(Context* context);
+            virtual ~TurretController();
+
+            virtual void tick(float dt);
+
+        private:
+
+            void searchTarget();
+            bool isLookingAtTargetNew(float angle) const;
+            float targetScore(Pawn* pawn, float distance) const;
+
+            bool once_; //!< Flag for executing code in the tick function only once.
+    };
+ }
+
+ #endif
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,7 @@
+ADD_SOURCE_FILES(OBJECTS_SRC_FILES
+  EventDispatcher.cc
+  EventFilter.cc
+  EventListener.cc
+  EventName.cc
+  EventTarget.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventDispatcher.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventDispatcher.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventDispatcher.cc	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "EventDispatcher.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(EventDispatcher);
+
+    EventDispatcher::EventDispatcher(Context* context) : BaseObject(context)
+    {
+        RegisterObject(EventDispatcher);
+    }
+
+    EventDispatcher::~EventDispatcher()
+    {
+        if (this->isInitialized())
+            for (BaseObject* target : this->targets_)
+                target->destroy();
+    }
+
+    void EventDispatcher::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventDispatcher, XMLPort, xmlelement, mode);
+
+        XMLPortObject(EventDispatcher, BaseObject, "targets", addTarget, getTarget, xmlelement, mode);
+
+        // since we need event sources mapped to any state, we have to parse XML by ourselves
+        this->loadAllEventStates(xmlelement, mode, this, Class(EventDispatcher));
+    }
+
+    void EventDispatcher::processEvent(Event& event)
+    {
+        for (BaseObject* target : this->targets_)
+            target->processEvent(event);
+    }
+
+    void EventDispatcher::addTarget(BaseObject* target)
+    {
+        this->targets_.push_back(target);
+    }
+
+    BaseObject* EventDispatcher::getTarget(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (BaseObject* target : this->targets_)
+        {
+            if (i == index)
+                return target;
+            ++i;
+        }
+        return nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventDispatcher.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventDispatcher.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventDispatcher.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventDispatcher.h
+    @brief Definition of the EventDispatcher class.
+    @ingroup Eventsystem
+*/
+
+#ifndef _EventDispatcher_H__
+#define _EventDispatcher_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <list>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _ObjectsExport EventDispatcher : public BaseObject
+    {
+        public:
+            EventDispatcher(Context* context);
+            virtual ~EventDispatcher();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            virtual void processEvent(Event& event);
+
+            void addTarget(BaseObject* target);
+            BaseObject* getTarget(unsigned int index) const;
+
+        private:
+            std::list<BaseObject*> targets_;
+    };
+}
+
+#endif /* _EventDispatcher_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventFilter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventFilter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventFilter.cc	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "EventFilter.h"
+
+#include "core/CoreIncludes.h"
+#include "core/Event.h"
+#include "core/XMLPort.h"
+#include "EventName.h"
+
+namespace orxonox
+{
+    RegisterClass(EventFilter);
+
+    EventFilter::EventFilter(Context* context) : BaseObject(context)
+    {
+        RegisterObject(EventFilter);
+
+        this->bActive_ = false;
+    }
+
+    EventFilter::~EventFilter()
+    {
+        for (std::list<EventName*>::const_iterator it = this->names_.begin(); it != this->names_.end(); )
+            (*(it++))->destroy();
+    }
+
+    void EventFilter::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventFilter, XMLPort, xmlelement, mode);
+
+        XMLPortObject(EventFilter, BaseObject, "", addFilterSource, getFilterSource, xmlelement, mode);
+        XMLPortObject(EventFilter, EventName, "names", addEventName, getEventName, xmlelement, mode);
+    }
+
+    void EventFilter::processEvent(Event& event)
+    {
+        if (this->bActive_)
+        {
+            orxout(internal_warning, context::events) << "Detected Event loop in EventFilter \"" << this->getName() << '"' << endl;
+            return;
+        }
+
+        if (this->names_.size() > 0)
+        {
+            bool success = false;
+            for (EventName* name : this->names_)
+            {
+                if (name->getName() == event.name_)
+                {
+                    success = true;
+                    break;
+                }
+            }
+            if (!success)
+                return;
+        }
+
+        this->bActive_ = true;
+        this->fireEvent(event.activate_, event.originator_, event.name_);
+        this->bActive_ = false;
+    }
+
+    void EventFilter::addFilterSource(BaseObject* source)
+    {
+        this->sources_.push_back(source);
+        this->addEventSource(source, "");
+    }
+
+    BaseObject* EventFilter::getFilterSource(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (BaseObject* source : this->sources_)
+        {
+            if (i == index)
+                return source;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    void EventFilter::addEventName(EventName* eventname)
+    {
+        this->names_.push_back(eventname);
+    }
+
+    EventName* EventFilter::getEventName(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (EventName* name : this->names_)
+        {
+            if (i == index)
+                return name;
+            ++i;
+        }
+        return nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventFilter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventFilter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventFilter.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventFilter.h
+    @brief Definition of the EventFilter class.
+    @ingroup Eventsystem
+*/
+
+#ifndef _EventFilter_H__
+#define _EventFilter_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <list>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _ObjectsExport EventFilter : public BaseObject
+    {
+        public:
+            EventFilter(Context* context);
+            virtual ~EventFilter();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            virtual void processEvent(Event& event);
+
+            void addFilterSource(BaseObject* source);
+            BaseObject* getFilterSource(unsigned int index) const;
+
+            void addEventName(EventName* eventname);
+            EventName* getEventName(unsigned int index) const;
+
+        private:
+            std::list<BaseObject*> sources_;
+            std::list<EventName*> names_;
+            bool bActive_;
+    };
+}
+
+#endif /* _EventFilter_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventListener.cc	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "EventListener.h"
+
+#include "core/CoreIncludes.h"
+#include "core/Event.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(EventListener);
+
+    EventListener::EventListener(Context* context) : BaseObject(context)
+    {
+        RegisterObject(EventListener);
+
+        this->bActive_ = false;
+    }
+
+    EventListener::~EventListener()
+    {
+    }
+
+    void EventListener::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventListener, XMLPort, xmlelement, mode);
+
+        XMLPortParam(EventListener, "event", setEventName, getEventName, xmlelement, mode);
+    }
+
+    void EventListener::processEvent(Event& event)
+    {
+        if (this->bActive_)
+        {
+            orxout(internal_warning, context::events) << "Detected Event loop in EventListener \"" << this->getName() << '"' << endl;
+            return;
+        }
+
+        orxout(verbose, context::events) << "EventListener, processing event: originator: " << event.originator_->getIdentifier()->getName() << " (&" << event.originator_ << ")" << ", activate: " << event.activate_ << ", name: " << event.name_ << endl;
+
+        this->bActive_ = true;
+        //TODO: Why not this->fireEvent(event)?
+        this->fireEvent(event.activate_, event.originator_, event.name_);
+        this->bActive_ = false;
+    }
+
+    void EventListener::setEventName(const std::string& eventname)
+    {
+        this->eventName_ = eventname;
+
+        if (this->eventName_.empty())
+            return;
+
+        for (BaseObject* object : ObjectList<BaseObject>())
+            if (object->getName() == this->eventName_)
+                this->addEventSource(object, "");
+    }
+
+    void EventListener::loadedNewXMLName(BaseObject* object)
+    {
+        if (this->eventName_.empty())
+            return;
+
+        if (object->getName() == this->eventName_)
+            this->addEventSource(object, "");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventListener.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventListener.h
+    @brief Definition of the EventListener class.
+    @ingroup Eventsystem
+*/
+
+#ifndef _EventListener_H__
+#define _EventListener_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <string>
+#include "core/BaseObject.h"
+#include "core/XMLNameListener.h"
+
+namespace orxonox
+{
+    class _ObjectsExport EventListener : public BaseObject, public XMLNameListener
+    {
+        public:
+            EventListener(Context* context);
+            virtual ~EventListener();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            virtual void processEvent(Event& event);
+
+            void setEventName(const std::string& eventname);
+            inline const std::string& getEventName() const
+                { return this->eventName_; }
+
+        private:
+            virtual void loadedNewXMLName(BaseObject* object);
+
+            std::string eventName_;
+            bool bActive_;
+    };
+}
+
+#endif /* _EventListener_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventName.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventName.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventName.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "EventName.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(EventName);
+
+    EventName::EventName(Context* context) : BaseObject(context)
+    {
+        RegisterObject(EventName);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventName.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventName.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventName.h	(revision 11817)
@@ -0,0 +1,52 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventName.h
+    @brief Definition of the EventName class.
+    @ingroup Eventsystem
+*/
+
+#ifndef _EventName_H__
+#define _EventName_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _ObjectsExport EventName : public BaseObject
+    {
+        public:
+            EventName(Context* context);
+            virtual ~EventName() {}
+    };
+}
+
+#endif /* _EventName_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventTarget.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventTarget.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventTarget.cc	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "EventTarget.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(EventTarget);
+
+    EventTarget::EventTarget(Context* context) : BaseObject(context)
+    {
+        RegisterObject(EventTarget);
+
+        this->bActive_ = false;
+    }
+
+    EventTarget::~EventTarget()
+    {
+    }
+
+    void EventTarget::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventTarget, XMLPort, xmlelement, mode);
+
+        XMLPortParam(EventTarget, "target", setTargetName, getTargetName, xmlelement, mode);
+
+        // since we need event sources mapped to any state, we have to parse XML by ourselves
+        this->loadAllEventStates(xmlelement, mode, this, Class(EventTarget));
+    }
+
+    void EventTarget::processEvent(Event& event)
+    {
+        if (this->bActive_)
+        {
+            orxout(internal_warning, context::events) << "Detected Event loop in EventTarget \"" << this->getName() << '"' << endl;
+            return;
+        }
+
+        this->bActive_ = true;
+        this->fireEvent(event);
+        this->bActive_ = false;
+    }
+
+    void EventTarget::setTargetName(const std::string& name)
+    {
+        this->target_ = name;
+
+        for (BaseObject* object : ObjectList<BaseObject>())
+            if (object->getName() == this->target_)
+                this->addEventTarget(object);
+    }
+
+    void EventTarget::loadedNewXMLName(BaseObject* object)
+    {
+        if (this->target_.empty())
+            return;
+
+        if (object->getName() == this->target_)
+            this->addEventTarget(object);
+    }
+
+    void EventTarget::addEventTarget(BaseObject* object)
+    {
+        if (object != static_cast<BaseObject*>(this))
+            object->addEventSource(this, "");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventTarget.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventTarget.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/eventsystem/EventTarget.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventTarget.h
+    @brief Definition of the EventTarget class.
+    @ingroup Eventsystem
+*/
+
+#ifndef _EventTarget_H__
+#define _EventTarget_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "core/XMLNameListener.h"
+
+namespace orxonox
+{
+    class _ObjectsExport EventTarget : public BaseObject, public XMLNameListener
+    {
+        public:
+            EventTarget(Context* context);
+            virtual ~EventTarget();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            virtual void processEvent(Event& event);
+
+            void setTargetName(const std::string& name);
+            inline const std::string& getTargetName() const
+                { return this->target_; }
+
+        private:
+            virtual void loadedNewXMLName(BaseObject* object);
+            void addEventTarget(BaseObject* object);
+
+            std::string target_;
+            bool bActive_;
+    };
+}
+
+#endif /* _EventTarget_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,12 @@
+ADD_SOURCE_FILES(OBJECTS_SRC_FILES
+  CheckPoint.cc
+  DistanceMultiTrigger.cc
+  DistanceTrigger.cc
+  DistanceTriggerBeacon.cc
+  EventMultiTrigger.cc
+  EventTrigger.cc
+  MultiTrigger.cc
+  MultiTriggerContainer.cc
+  Trigger.cc
+  TriggerBase.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/CheckPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/CheckPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/CheckPoint.cc	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CheckPoint.cc
+    @brief Implementation of the CheckPoint class.
+    @ingroup NormalTrigger
+*/
+
+#include "CheckPoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "gametypes/Asteroids.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(CheckPoint);
+
+    CheckPoint::CheckPoint(Context* context)
+        : DistanceTrigger(context)
+        , RadarViewable(this, static_cast<WorldEntity*>(this))
+    {
+        RegisterObject(CheckPoint);
+
+        this->setStayActive(true);
+        this->setDistance(50);
+        this->bIsFirst_ = false;
+        this->bIsDestination_ = false;
+
+        this->setRadarObjectColour(ColourValue::Green);
+        this->setRadarObjectShape(RadarViewable::Shape::Dot);
+        this->setRadarVisibility(false);
+
+        this->notifyMaskUpdate();
+    }
+
+    CheckPoint::~CheckPoint()
+    {
+    }
+
+    void CheckPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CheckPoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(CheckPoint, "isfirst", setFirst, getFirst, xmlelement, mode).defaultValues(false);
+        XMLPortParam(CheckPoint, "isdestination", setDestination, getDestination, xmlelement, mode).defaultValues(false);
+        XMLPortParam(CheckPoint, "addtime", setAddTime, getAddTime, xmlelement, mode).defaultValues(30);
+    }
+
+    void CheckPoint::changedActivity()
+    {
+        SUPER(CheckPoint, changedActivity);
+
+        if (this->BaseObject::isActive())
+        {
+            this->setRadarVisibility(true);
+        }
+        else
+        {
+            this->setRadarVisibility(false);
+        }
+    }
+
+    void CheckPoint::triggered(bool bIsTriggered)
+    {
+        DistanceTrigger::triggered(bIsTriggered);
+
+        Asteroids* gametype = orxonox_cast<Asteroids*>(this->getGametype());
+        if (gametype)
+        {
+            gametype->addTime(addTime_);
+            this->setRadarVisibility(false);
+
+            if (bIsTriggered)
+            {
+                if (bIsFirst_)
+                {
+                    gametype->setTimeLimit(addTime_);
+                    gametype->firstCheckpointReached(true);
+                }
+
+                if (bIsDestination_)
+                {
+                    gametype->getGametypeInfo()->sendAnnounceMessage("Congratulations - you have won the match!");
+                    gametype->end();
+                }
+
+                if (!bIsFirst_ && !bIsDestination_)
+                {
+                    gametype->getGametypeInfo()->sendAnnounceMessage("Checkpoint reached");
+                }
+            }
+        }
+    }
+
+    void CheckPoint::notifyMaskUpdate()
+    {
+        this->targetMask_.exclude(Class(BaseObject));
+        this->targetMask_.include(Class(Pawn));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/CheckPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/CheckPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/CheckPoint.h	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CheckPoint.h
+    @brief Definition of the CheckPoint class.
+    @ingroup NormalTrigger
+*/
+
+#ifndef _CheckPoint_H__
+#define _CheckPoint_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "interfaces/RadarViewable.h"
+#include "DistanceTrigger.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+
+    @author
+        Aurelian Jaggi
+
+    @ingroup NormalTrigger
+    */
+    class _ObjectsExport CheckPoint : public DistanceTrigger, public RadarViewable
+    {
+    public:
+        CheckPoint(Context* context);
+        virtual ~CheckPoint();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a CheckPoint object through XML.
+        virtual void changedActivity();
+
+    private:
+        virtual void triggered(bool bIsTriggered);
+        virtual void notifyMaskUpdate();
+
+        inline void setDestination(bool isDestination)
+            { bIsDestination_ = isDestination; }
+
+        inline const WorldEntity* getWorldEntity() const
+            { return this; }
+
+        inline bool getDestination()
+            { return bIsDestination_; }
+
+        inline void setFirst(bool isFirst)
+            { this->bIsFirst_ = isFirst; }
+
+        inline bool getFirst()
+            { return this->bIsFirst_; }
+
+        inline void setAddTime(float time)
+            { this->addTime_ = time; }
+
+        inline bool getAddTime()
+            { return this->addTime_; }
+
+        bool bIsFirst_;
+        bool bIsDestination_;
+        float addTime_;
+    };
+}
+
+#endif /* _CheckPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceMultiTrigger.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceMultiTrigger.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceMultiTrigger.cc	(revision 11817)
@@ -0,0 +1,266 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file DistanceMultiTrigger.cc
+    @brief Implementation of the DistanceMultiTrigger class.
+    @ingroup MultiTrigger
+*/
+
+#include "DistanceMultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "DistanceTriggerBeacon.h"
+
+namespace orxonox
+{
+
+    /*static*/ const std::string DistanceMultiTrigger::beaconModeOff_s = "off";
+    /*static*/ const std::string DistanceMultiTrigger::beaconModeIdentify_s = "identify";
+    /*static*/ const std::string DistanceMultiTrigger::beaconModeExlcude_s = "exclude";
+    
+    RegisterClass(DistanceMultiTrigger);
+
+    /**
+    @brief
+        Default Constructor. Registers the object and initializes default values.
+    */
+    DistanceMultiTrigger::DistanceMultiTrigger(Context* context) : MultiTrigger(context)
+    {
+        RegisterObject(DistanceMultiTrigger);
+
+        this->distance_ = 100.0f;
+        this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::off);
+        this->targetName_ = "";
+        this->beaconMask_.exclude(Class(BaseObject));
+        this->beaconMask_.include(Class(DistanceTriggerBeacon));
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    DistanceMultiTrigger::~DistanceMultiTrigger()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a DistanceMultiTrigger object through XML.
+    */
+    void DistanceMultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(DistanceMultiTrigger, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DistanceMultiTrigger, "distance", setDistance, getDistance, xmlelement, mode);
+        XMLPortParam(DistanceMultiTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
+        XMLPortParam(DistanceMultiTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
+
+        In this implementation we iterate through all possible objects and check whether the fact that they are in range or not has changed and fire and hand a state ofer to the MultiTrigger if so.
+    @return
+        Returns a pointer to a queue of MultiTriggerState pointers, containing all the necessary information to decide whether these states should indeed become new states of the MultiTrigger.
+    */
+    std::queue<MultiTriggerState*>* DistanceMultiTrigger::letTrigger(void)
+    {
+
+        std::queue<MultiTriggerState*>* queue = nullptr;
+
+        // Check for objects that were in range but no longer are. Iterate through all objects, that are in range.
+        for(std::set<WeakPtr<WorldEntity>>::iterator it = this->range_.begin(); it != this->range_.end(); )
+        {
+            WorldEntity* entity = *it;
+
+            // If the entity no longer exists.
+            if(entity == nullptr)
+            {
+                this->range_.erase(it++);
+                continue;
+            }
+
+            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
+            // If the object is no longer in range.
+            if (distanceVec.length() > this->distance_)
+            {
+                this->range_.erase(it++);
+
+                // If no queue has been created, yet.
+                if(queue == nullptr)
+                    queue = new std::queue<MultiTriggerState*>();
+
+                // Create a state and append it to the queue.
+                MultiTriggerState* state = new MultiTriggerState;
+                state->bTriggered = false; // Because the entity went out of range.
+                state->originator = entity;
+                queue->push(state);
+            }
+            else
+            {
+                ++it;
+            }
+        }
+
+        // Check for new objects that are in range
+        ClassTreeMask targetMask = this->getTargetMask();
+        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
+        if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::identify)
+            targetMask = this->beaconMask_;
+
+        // Iterate through all objects that are targets of the DistanceMultiTrigger.
+        for(ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
+        {
+            WorldEntity* entity = static_cast<WorldEntity*>(*it);
+
+            // If the DistanceMultiTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
+            if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::identify)
+            {
+                if(entity->getName() != this->targetName_)
+                    continue;
+                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
+                else if(this->getTargetMask().isExcluded(entity->getParent()->getIdentifier()))
+                    continue;
+            }
+            
+            // If the DistanceMultiTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
+            if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::exclude)
+            {
+                
+                const std::set<WorldEntity*> attachedObjects = entity->getAttachedObjects();
+                bool found = false;
+                for(WorldEntity* attachedObject : attachedObjects)
+                {
+                    if(attachedObject->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(attachedObject)->getName() == this->targetName_)
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+                if(found)
+                    continue;
+            }
+
+            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
+            // If the object is in range.
+            if (distanceVec.length() <= this->distance_)
+            {
+                // Add the object to the objects that are in range.
+                // Objects that already are in range are not added twice, because in a map (this->range_) each key can only exist once and thus addToRange() will reject all attempts of duplicate entries.
+                if(!this->addToRange(entity))
+                    continue;
+
+                // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
+                if(this->beaconMode_ == DistanceMultiTriggerBeaconMode::identify)
+                    entity = entity->getParent();
+
+                // If no queue has been created, yet.
+                if(queue == nullptr)
+                    queue = new std::queue<MultiTriggerState*>();
+
+                // Create a state and append it to the queue.
+                MultiTriggerState* state = new MultiTriggerState;
+                state->bTriggered = true; // Because the entity came into range.
+                state->originator = entity;
+                queue->push(state);
+            }
+        }
+
+        return queue;
+    }
+    
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as an enum.
+    */
+    void DistanceMultiTrigger::setBeaconModeDirect(DistanceMultiTriggerBeaconMode mode)
+    {
+        this->beaconMode_ = mode;
+    }
+    
+    /**
+    @brief
+        Get the beacon mode.
+    @return
+        Returns the mode as a string.
+    */
+    const std::string& DistanceMultiTrigger::getBeaconMode(void) const
+    {
+        switch(this->getBeaconModeDirect())
+        {
+            case DistanceMultiTriggerBeaconMode::off :
+                return DistanceMultiTrigger::beaconModeOff_s;
+            case DistanceMultiTriggerBeaconMode::identify:
+                return DistanceMultiTrigger::beaconModeIdentify_s;
+            case DistanceMultiTriggerBeaconMode::exclude:
+                return DistanceMultiTrigger::beaconModeExlcude_s;
+            default :
+                assert(0); // This is impossible.
+                return BLANKSTRING;
+        }
+    }
+    
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as a string.
+    */
+    void DistanceMultiTrigger::setBeaconMode(const std::string& mode)
+    {
+        if(mode == DistanceMultiTrigger::beaconModeOff_s)
+            this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::off);
+        else if(mode == DistanceMultiTrigger::beaconModeIdentify_s)
+            this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::identify);
+        else if(mode == DistanceMultiTrigger::beaconModeExlcude_s)
+            this->setBeaconModeDirect(DistanceMultiTriggerBeaconMode::exclude);
+        else
+            orxout(internal_error, context::triggers) << "Invalid beacon mode in DistanceMultiTrigger." << endl;
+    }
+
+    /**
+    @brief
+        Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
+    @param entity
+        A pointer to the entity.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool DistanceMultiTrigger::addToRange(WorldEntity* entity)
+    {
+        std::pair<std::set<WeakPtr<WorldEntity>>::iterator, bool> pair = this->range_.insert(entity);
+        return pair.second;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceMultiTrigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceMultiTrigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceMultiTrigger.h	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file DistanceMultiTrigger.h
+    @brief Definition of the DistanceMultiTrigger class.
+    @ingroup MultiTrigger
+*/
+
+#ifndef _DistanceMultiTrigger_H__
+#define _DistanceMultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <map>
+
+#include "core/object/WeakPtr.h"
+
+#include "worldentities/WorldEntity.h"
+
+#include "MultiTrigger.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Enum for the beacon mode of the DistanceMultiTrigger.
+        
+    @ingroup MultiTrigger
+    */
+    enum class DistanceMultiTriggerBeaconMode {
+        off, //!< The DistanceMultiTrigger is not in <em>beacon-mode</em>.
+        identify, //!< The DistanceTrigger is in <em>identify-mode</em>.
+        exclude //!< The DistanceTrigger is in <em>exclude-mode</em>.
+    };
+
+    /**
+    @brief
+        The DistanceMultiTrigger is a MultiTrigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceMultiTrigger. The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+        Parameters are (additional to the ones of MultiTrigger):
+        - @b distance Which specifies the maximum distance at which the DistanceMultiTrigger still triggers. Default is <code>100</code>.
+        - @b beaconMode Which specifies, whether the DistanceMultiTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceMultiTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceMultiTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+        - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceMultiTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+
+        A simple DistanceMultiTrigger could look like this:
+        @code
+        <DistanceMultiTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
+        @endcode
+
+        An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
+        @code
+        <DistanceMultiTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
+        @endcode
+        This particular DistanceMultiTrigger would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
+
+    @see MultiTrigger
+        For more information on @ref orxonox::MultiTrigger "MultiTriggers".
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup MultiTrigger
+    */
+    class _ObjectsExport DistanceMultiTrigger : public MultiTrigger 
+    {
+
+        public:
+            DistanceMultiTrigger(Context* context); // Default Constructor. Registers the object and initializes default values.
+            virtual ~DistanceMultiTrigger(); // Destructor.
+
+            void XMLPort(Element& xmlelement, XMLPort::Mode mode); // Method for creating a DistanceMultiTrigger object through XML.
+            
+            /**
+            @brief Set the distance at which the DistanceMultiTrigger triggers.
+            @param distance The distance.
+            */
+            inline void setDistance(float distance)
+                { if(distance >= 0) this->distance_ = distance; }
+            /**
+            @brief Get the distance at which the DistanceMultiTrigger triggers.
+            @return Returns the distance.
+            */
+            inline float getDistance() const
+                { return this->distance_; }
+            
+            void setBeaconModeDirect(DistanceMultiTriggerBeaconMode mode); // Set the beacon mode.
+            /**
+            @brief Get the beacon mode.
+            @return Returns the mode as an enum.
+            */
+            inline DistanceMultiTriggerBeaconMode getBeaconModeDirect(void) const
+                { return this->beaconMode_; }
+            void setBeaconMode(const std::string& mode); // Set the beacon mode.
+            const std::string& getBeaconMode(void) const; // Get the beacon mode.
+
+            /**
+            @brief Set the target name of DistanceTriggerBeacons that triggers this DistanceMultiTrigger.
+            @param targetname The name of the DistanceTriggerBeacon as a string.
+            */
+            inline void setTargetName(const std::string& targetname)
+                { this->targetName_ = targetname; }
+            /**
+            @brief Get the target name of the DistanceTriggerbeacon, that triggers this DistanceMultiTrigger.
+            @return Returns the target name as a string.
+            */
+            inline const std::string& getTargetName(void) const
+                { return this->targetName_; }
+
+        protected:
+            virtual std::queue<MultiTriggerState*>* letTrigger(void); // This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
+
+            bool addToRange(WorldEntity* entity); // Add a given entity to the entities, that currently are in range of the DistanceMultiTrigger.
+
+        private:
+            //! Strings for the beacon modes.
+            static const std::string beaconModeOff_s;
+            static const std::string beaconModeIdentify_s;
+            static const std::string beaconModeExlcude_s;
+            
+            float distance_; //!< The distance at which the DistanceMultiTrigger triggers.
+
+            DistanceMultiTriggerBeaconMode beaconMode_; //!< The beacon mode, the DistanceMultiTrigger is in.
+            std::string targetName_; //!< The target name, used in <em>single-target</em> mode.
+            ClassTreeMask beaconMask_; //!< A mask, that only accepts DistanceTriggerBeacons.
+
+            std::set<WeakPtr<WorldEntity>> range_; //!< The set of entities that currently are in range of the DistanceMultiTrigger.
+
+    };
+
+}
+
+#endif // _DistanceMultiTrigger_H__
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTrigger.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTrigger.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTrigger.cc	(revision 11817)
@@ -0,0 +1,289 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DistanceTrigger.cc
+    @brief Implementation of the DistanceTrigger class.
+    @ingroup NormalTrigger
+*/
+
+#include "DistanceTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+#include "DistanceTriggerBeacon.h"
+
+namespace orxonox
+{
+
+    /*static*/ const std::string DistanceTrigger::beaconModeOff_s = "off";
+    /*static*/ const std::string DistanceTrigger::beaconModeIdentify_s = "identify";
+    /*static*/ const std::string DistanceTrigger::beaconModeExlcude_s = "exclude";
+
+    RegisterClass(DistanceTrigger);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    DistanceTrigger::DistanceTrigger(Context* context) : Trigger(context)
+    {
+        RegisterObject(DistanceTrigger);
+
+        this->distance_ = 100;
+        this->targetMask_.exclude(Class(BaseObject));
+        this->targetName_ = "";
+        this->beaconMask_.exclude(Class(BaseObject));
+        this->beaconMask_.include(Class(DistanceTriggerBeacon));
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    DistanceTrigger::~DistanceTrigger()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a DistanceTrigger object through XML.
+    */
+    void DistanceTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(DistanceTrigger, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DistanceTrigger, "distance", setDistance, getDistance, xmlelement, mode).defaultValues(100.0f);
+        XMLPortParamLoadOnly(DistanceTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn");
+        XMLPortParam(DistanceTrigger, "beaconMode", setBeaconMode, getBeaconMode, xmlelement, mode);
+        XMLPortParam(DistanceTrigger, "targetname", setTargetName, getTargetName, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Add some target to the DistanceTrigger.
+    @param targetStr
+        The target class name as a string.
+    */
+    void DistanceTrigger::addTarget(const std::string& targetStr)
+    {
+        Identifier* targetId = ClassByString(targetStr);
+
+        // Checks whether the target is (or is derived from) a Pawn and if so set the PlayerTrigger aspect of this trigger to be for the player, meaning, that from this Trigger one can derive the Pawn that caused it to trigger.
+        Identifier* pawnId = Class(Pawn);
+        if(targetId->isA(pawnId))
+            this->setForPlayer(true);
+
+        if (targetId == nullptr)
+        {
+            orxout(internal_error, context::triggers) << "\"" << targetStr << "\" is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ')' << endl;
+            return;
+        }
+
+        // Add the target to the target mask.
+        this->targetMask_.include(targetId);
+
+        // The DistanceTrigger shouldn't react to itself or other triggers.
+        this->targetMask_.exclude(Class(TriggerBase), true);
+
+        // We only want WorldEntities (since only they have a position)
+        ClassTreeMask WEMask;
+        WEMask.include(Class(WorldEntity));
+        this->targetMask_ *= WEMask;
+
+        this->notifyMaskUpdate(); // Inform interested parties that the target mask has been updated.
+    }
+
+    /**
+    @brief
+        Remove some target from the DistanceTrigger.
+    @param targetStr
+        The target class name as a string.
+    */
+    void DistanceTrigger::removeTarget(const std::string& targetStr)
+    {
+        Identifier* targetId = ClassByString(targetStr);
+        this->targetMask_.exclude(targetId);
+    }
+
+    /**
+    @brief
+        Check, whether there are entities that are targets of this DistanceTrigger in its range.
+    @return
+        Returns true if there are valid entities in its range.
+    */
+    bool DistanceTrigger::checkDistance()
+    {
+        // Check whether there is a cached object, it still exists and whether it is still in range, if so nothing further needs to be done.
+        if(this->cache_ != nullptr)
+        {
+            if((this->cache_->getWorldPosition() - this->getWorldPosition()).length() < this->distance_)
+                return true;
+            else
+                this->cache_.reset();
+        }
+        
+        // Check for new objects that are in range
+        ClassTreeMask targetMask = this->targetMask_;
+        // If we are in identify-mode another target mask has to be applies to find the DistanceTriggerBeacons.
+        if(this->beaconMode_ == DistanceTriggerBeaconMode::identify)
+            targetMask = this->beaconMask_;
+
+        // Iterate through all objects that are targets of the DistanceTrigger.
+        for (ClassTreeMaskObjectIterator it = targetMask.begin(); it != targetMask.end(); ++it)
+        {
+            WorldEntity* entity = static_cast<WorldEntity*>(*it);
+
+            // If the DistanceTrigger is in identify-mode and the DistanceTriggerBeacon attached to the object has the wrong name we ignore it.
+            if(this->beaconMode_ == DistanceTriggerBeaconMode::identify)
+            {
+                if(entity->getName() != this->targetName_)
+                    continue;
+                // If the object, the DistanceTriggerBeacon is attached to, is not a target of this DistanceMultiTrigger.
+                else if(this->targetMask_.isExcluded(entity->getParent()->getIdentifier()))
+                    continue;
+            }
+
+            // If the DistanceTrigger is in exclude mode and the DistanceTriggerBeacon attached to the object has the right name, we ignore it.
+            if(this->beaconMode_ == DistanceTriggerBeaconMode::exclude)
+            {
+
+                const std::set<WorldEntity*> attachedObjects = entity->getAttachedObjects();
+                bool found = false;
+                for(WorldEntity* attachedObject : attachedObjects)
+                {
+                    if(attachedObject->isA(ClassIdentifier<DistanceTriggerBeacon>::getIdentifier()) && static_cast<DistanceTriggerBeacon*>(attachedObject)->getName() == this->targetName_)
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+                if(found)
+                    continue;
+            }
+
+            // Check if the entity is in range.
+            Vector3 distanceVec = entity->getWorldPosition() - this->getWorldPosition();
+            if (distanceVec.length() < this->distance_)
+            {
+                // If the target is a player (resp. is a, or is derived from a, Pawn) the triggeringPlayer is set to the target entity.
+                if(this->isForPlayer())
+                {
+                    // Change the entity to the parent of the DistanceTriggerBeacon (if in identify-mode), which is the entity to which the beacon is attached.
+                    if(this->beaconMode_ == DistanceTriggerBeaconMode::identify)
+                        entity = entity->getParent();
+
+                    Pawn* pawn = orxonox_cast<Pawn*>(entity);
+                    if(pawn != nullptr)
+                        this->setTriggeringPawn(pawn);
+                    else
+                        orxout(internal_warning, context::triggers) << "Pawn was nullptr." << endl;
+                }
+                
+                // Add the entity to the cache.
+                this->cache_ = entity;
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as an enum.
+    */
+    void DistanceTrigger::setBeaconModeDirect(DistanceTriggerBeaconMode mode)
+    {
+        this->beaconMode_ = mode;
+    }
+
+    /**
+    @brief
+        Get the beacon mode.
+    @return
+        Returns the mode as a string.
+    */
+    const std::string& DistanceTrigger::getBeaconMode(void) const
+    {
+        switch(this->getBeaconModeDirect())
+        {
+            case DistanceTriggerBeaconMode::off :
+                return DistanceTrigger::beaconModeOff_s;
+            case DistanceTriggerBeaconMode::identify:
+                return DistanceTrigger::beaconModeIdentify_s;
+            case DistanceTriggerBeaconMode::exclude:
+                return DistanceTrigger::beaconModeExlcude_s;
+            default :
+                assert(0); // This is impossible.
+                return BLANKSTRING;
+        }
+    }
+
+    /**
+    @brief
+        Set the beacon mode.
+    @param mode
+        The mode as a string.
+    */
+    void DistanceTrigger::setBeaconMode(const std::string& mode)
+    {
+        if(mode == DistanceTrigger::beaconModeOff_s)
+            this->setBeaconModeDirect(DistanceTriggerBeaconMode::off);
+        else if(mode == DistanceTrigger::beaconModeIdentify_s)
+            this->setBeaconModeDirect(DistanceTriggerBeaconMode::identify);
+        else if(mode == DistanceTrigger::beaconModeExlcude_s)
+            this->setBeaconModeDirect(DistanceTriggerBeaconMode::exclude);
+        else
+            orxout(internal_error, context::triggers) << "Invalid beacon mode in DistanceTrigger." << endl;
+    }
+
+    /**
+    @brief
+        Check whether the DistanceTrigger is triggered.
+        It is triggered if it is triggered according only to its mode (i.e. its sub-triggers) and if a target is in range.
+    @param mode
+        The mode for which it is tested, whether the DistanceTrigger is triggered.
+    @return
+        Returns true if it is triggered ,false if not.
+    */
+    bool DistanceTrigger::isTriggered(TriggerMode mode)
+    {
+        if (Trigger::isTriggered(mode))
+            return checkDistance();
+        else
+            return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTrigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTrigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTrigger.h	(revision 11817)
@@ -0,0 +1,167 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file DistanceTrigger.h
+    @brief Definition of the DistanceTrigger class.
+    @ingroup NormalTrigger
+*/
+
+#ifndef _DistanceTrigger_H__
+#define _DistanceTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <set>
+
+#include "core/ClassTreeMask.h"
+
+#include "interfaces/PlayerTrigger.h"
+
+#include "Trigger.h"
+
+namespace orxonox
+{
+    
+  /**
+  @brief
+      Enum for the beacon mode of the DistanceTrigger.
+      
+  @ingroup NormalTrigger
+  */
+  enum class DistanceTriggerBeaconMode {
+      off,
+      identify,
+      exclude
+  };
+
+    /**
+    @brief
+        The DistanceTrigger is a Trigger that triggers whenever an object (that is of the specified target type) is in a specified range of the DistanceTrigger. The object can be specified further by setting the <em>beaconMode</em> and attaching a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" to the object.
+        Parameters are (additional to the ones of Trigger):
+        - @b distance Which specifies the maximum distance at which the DistanceTrigger still triggers, i.e. its range. Default is <code>100</code>.
+        - @b target Which specifies the class of objects that can trigger the DistanceTrigger. Default is <code>"Pawn"</code>.
+        - @b beaconMode Which specifies, whether the DistanceTrigger operates on @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" or not. If <em>off</em> the DistanceMultiTrigger works as usual. If set to <em>identify</em> the DistanceTrigger is only triggered by objects that have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. If set to <em>exclude</em> the DistanceTrigger is only triggered by objects that don't have a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon", with the same name as specified in <em>targetname</em>, attached to them. Default is <em>off</em>.
+        - @b targetname Which specifies the name @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacons" need to have to make the DistanceTrigger react to them if it is in <em>beacon-mode</em> (the beaconMode is not <em>off</em>).
+
+        A simple DistanceTrigger could look like this:
+        @code
+        <DistanceTrigger position="0,0,0" switch="true" target="Pawn" distance="20" />
+        @endcode
+
+        An implementation that only reacts to objects with a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" attached would look like this:
+        @code
+        <DistanceTrigger position="0,0,0" target="Pawn" beaconMode="identify" targetname="beacon1" distance="30" />
+        @endcode
+        This particular DistanceTrigger would only react if an object was in range, that had a @ref orxonox::DistanceTriggerBeacon "DistanceTriggerBeacon" with the name <em>beacon1</em> attached.
+
+    @see Trigger
+        For more information on @ref orxonox::Trigger "Triggers".
+
+    @author
+        Benjamin Knecht
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup NormalTrigger
+    */
+    class _ObjectsExport DistanceTrigger : public Trigger, public PlayerTrigger
+    {
+        public:
+            DistanceTrigger(Context* context); // Constructor. Registers and initializes the object.
+            virtual ~DistanceTrigger();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; // Method for creating a DistanceTrigger object through XML.
+
+            void addTarget(const std::string& targets); // Add some target to the DistanceTrigger.
+            void removeTarget(const std::string& targets); // Remove some target from the DistanceTrigger.
+
+            /**
+            @brief Set the range of the DistanceTrigger.
+            @param distance The range to be set.
+            */
+            inline void setDistance(float distance)
+                { this->distance_ = distance; }
+            /**
+            @brief Get the range of the DistanceTrigger.
+            @return Returns the range of the distance trigger.
+            */
+            inline float getDistance() const
+                { return this->distance_; }
+
+            void setBeaconModeDirect(DistanceTriggerBeaconMode mode); // Set the beacon mode.
+            /**
+            @brief Get the beacon mode.
+            @return Returns the mode as an enum.
+            */
+            inline DistanceTriggerBeaconMode getBeaconModeDirect(void) const
+            { return this->beaconMode_; }
+            void setBeaconMode(const std::string& mode); // Set the beacon mode.
+            const std::string& getBeaconMode(void) const; // Get the beacon mode.
+
+            /**
+            @brief Set the name a DistanceTriggerBeacon needs to have to make the DistanceTrigger react to it if in beacon-mode.
+            @param targetname The name as a string.
+            */
+            inline void setTargetName(const std::string& targetname)
+                { this->targetName_ = targetname; }
+            /**
+            @brief Get the target name.
+            @return Returns the target name as a string.
+            */
+            inline const std::string& getTargetName(void)
+                { return this->targetName_; }
+
+            bool checkDistance(); // Check, whether there are entities that are targets of this DistanceTrigger in its range.
+
+        protected:
+            virtual bool isTriggered(TriggerMode mode) override; // Check whether the DistanceTrigger is triggered.
+            /**
+            @brief Notifies interested parties about a change of the DistanceTrigger's target mask.
+            */
+            virtual void notifyMaskUpdate() {}
+
+            ClassTreeMask targetMask_; //!< The target mask, specifies by which types of objects the DistanceTrigger can be triggered. 
+
+        private:
+            //! Strings for the beacon modes.
+            static const std::string beaconModeOff_s;
+            static const std::string beaconModeIdentify_s;
+            static const std::string beaconModeExlcude_s;
+
+            float distance_; //!< The range of the DistanceTrigger.
+            
+            DistanceTriggerBeaconMode beaconMode_; //!< The beacon mode.
+            std::string targetName_; //!< The name a DistanceTriggerBeacon needs to have to make the DistanceTrigger react to it if in beacon-mode.
+            ClassTreeMask beaconMask_; //!< A mask, that only accepts DistanceTriggerBeacons.
+            
+            WeakPtr<WorldEntity> cache_; //!< Caches the entity that triggered the DistanceTrigger last.
+    };
+}
+
+#endif /* _DistanceTrigger_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTriggerBeacon.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTriggerBeacon.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTriggerBeacon.cc	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file DistanceTriggerBeacon.cc
+    @brief Implementation of the DistanceTriggerBeacon class.
+    @ingroup Triggers
+*/
+
+#include "DistanceTriggerBeacon.h"
+
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+
+    RegisterClass(DistanceTriggerBeacon);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    DistanceTriggerBeacon::DistanceTriggerBeacon(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(DistanceTriggerBeacon);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTriggerBeacon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTriggerBeacon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/DistanceTriggerBeacon.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file DistanceTriggerBeacon.h
+    @brief Definition of the DistanceTriggerBeacon class.
+    @ingroup Triggers
+*/
+
+#ifndef _DistanceTriggerBeacon_H__
+#define _DistanceTriggerBeacon_H__
+
+#include "objects/ObjectsPrereqs.h"
+#include "core/XMLPort.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A DistanceTriggerBeacon can be used together with a @ref orxonox::DistanceTrigger "DistanceTrigger" or a @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger" to make them only react to specific objects.
+        This can be done by attaching a DistanceTriggerBeacon to an object, giving it a unique name and setting the targetname in the @ref orxonox::DistanceTrigger "DistanceTrigger" (or @ref orxonox::DistanceMultiTrigger "DistanceMultiTrigger") to that name and the target to DistanceTriggerBeacon.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Triggers
+    */
+    class _ObjectsExport DistanceTriggerBeacon : public StaticEntity
+    {
+
+        public:
+            DistanceTriggerBeacon(Context* context); //!< Constructor.
+            virtual ~DistanceTriggerBeacon() {} //!< Destructor.
+
+    };
+
+}
+
+#endif // _DistanceTriggerBeacon_H__
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventMultiTrigger.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventMultiTrigger.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventMultiTrigger.cc	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventMultiTrigger.cc
+    @brief Implementation of the EventMultiTrigger class.
+    @ingroup MultiTrigger
+*/
+
+#include "EventMultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+#include "MultiTriggerContainer.h"
+
+namespace orxonox
+{
+
+    RegisterClass(EventMultiTrigger);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    EventMultiTrigger::EventMultiTrigger(Context* context) : MultiTrigger(context)
+    {
+        RegisterObject(EventMultiTrigger);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    EventMultiTrigger::~EventMultiTrigger()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating an EventMultiTrigger object through XML.
+    */
+    void EventMultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventMultiTrigger, XMLPort, xmlelement, mode);
+
+        this->setBroadcast(true);
+    }
+
+    /**
+    @brief
+        Creates an event port.
+    */
+    void EventMultiTrigger::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventMultiTrigger, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(EventMultiTrigger, BaseObject, "trigger", trigger, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Method that causes the EventMultiTrigger to trigger upon receiving an event.
+    @param bTriggered
+        Whether the event is a triggering or an un-triggering event.
+    @param originator
+        A pointer to the entity the event originates from.
+    */
+    void EventMultiTrigger::trigger(bool bTriggered, BaseObject* originator)
+    {
+        // If the originator is a MultiTriggerContainer, the event originates from a MultiTrigger and thus the event only triggers the EventMultiTrigger for the originator that caused the MultiTrigger to trigger.
+        if(originator != nullptr && originator->isA(ClassIdentifier<MultiTriggerContainer>::getIdentifier()))
+        {
+            MultiTriggerContainer* container = static_cast<MultiTriggerContainer*>(originator);
+            // If the entity that triggered the MultiTrigger is no target of this EventMultiTrigger we process it as it weren't an event caused by a MultiTrigger.
+            // But if it is the EventMultiTrigger only triggers for the entity tha caused the MultiTrigger to trigger.
+            if(this->isTarget(container->getData()))
+            {
+                if(this->isTriggered(container->getData()) ^ bTriggered)
+                    this->changeTriggered(container->getData());
+
+                return;
+            }
+        }
+
+        // If we don't know who exactly caused the event we just send a broadcast.
+        if(this->isTriggered() ^ bTriggered)
+            this->changeTriggered();
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventMultiTrigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventMultiTrigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventMultiTrigger.h	(revision 11817)
@@ -0,0 +1,88 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventMultiTrigger.h
+    @brief Definition of the EventMultiTrigger class.
+    @ingroup MultiTrigger
+*/
+
+#ifndef _EventMultiTrigger_H__
+#define _EventMultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "MultiTrigger.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The EventMultiTrigger class is the equivalent of the @ref orxonox::EventTrigger "EventTrigger" class for MultiTriggers.
+        Consequentially what it does is it provides a way to have a MultiTrigger triggered by any kinds of @ref orxonox::Event "Events".
+        @ref orxonox::Event "Events" that are not caused by a MultiTrigger, or that are caused by a MultiTrigger with an originator that is no target of this EventMultiTrigger, are broadcasted to all entities that are the target of this EventMultiTrigger. @ref orxonox::Event "Events" that are caused by @ref orxonox::MultiTrigger "MultiTriggers" with an originator that is a target of this EventMultiTrigger just trigger the EventMultiTrigger for the originator that caused the MultiTrigger to trigger. Thus showing the equivalent behavior to the @ref orxonox::EventTrigger "EventTrigger".
+
+        Example:
+        @code
+        <EventMultiTrigger invert="true">
+            <events>
+                <trigger>
+                    <MultiTrigger ... />
+                    <EventListener ... />
+                </trigger>
+            </events>
+        </EventMultiTrigger>
+        @endcode
+
+    @see MultiTrigger
+        For more information on @ref orxonox::MultiTrigger "MultiTriggers".
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup MultiTrigger
+    */
+    class _ObjectsExport EventMultiTrigger : public MultiTrigger
+    {
+
+        public:
+            EventMultiTrigger(Context* context); //!< Constructor. Registers the object.
+            virtual ~EventMultiTrigger(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating an EventMultiTrigger object through XML.
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode);
+
+        private:
+            void trigger(bool bTriggered, BaseObject* originator); //!< Method that causes the EventMultiTrigger to trigger upon receiving an @ref orxonox::Event "Event".
+
+    };
+
+}
+
+#endif // _EventMultiTrigger_H__
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventTrigger.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventTrigger.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventTrigger.cc	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventTrigger.cc
+    @brief Implementation of the EventTrigger class.
+    @ingroup NormalTrigger
+*/
+
+#include "EventTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(EventTrigger);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    EventTrigger::EventTrigger(Context* context) : Trigger(context)
+    {
+        RegisterObject(EventTrigger);
+
+        this->bEventTriggered_ = false;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    EventTrigger::~EventTrigger()
+    {
+    }
+
+    /**
+    @brief
+        Creates an event port.
+    */
+    void EventTrigger::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EventTrigger, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(EventTrigger, BaseObject, "trigger", trigger, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Check whether the EventTrigger should be triggered.
+        It should be triggered if it is triggered according just to its sub-triggers and if the last event that came in was an event that changed from not triggered to triggered.
+    */
+    bool EventTrigger::isTriggered(TriggerMode mode)
+    {
+        if (Trigger::isTriggered(mode))
+            return this->bEventTriggered_;
+        else
+            return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventTrigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventTrigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/EventTrigger.h	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EventTrigger.h
+    @brief Definition of the EventTrigger class.
+    @ingroup NormalTrigger
+*/
+
+#ifndef _EventTrigger_H__
+#define _EventTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "Trigger.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The EventTrigger class provides a way to have a Trigger triggered by any kinds of @ref orxonox::Event "Events".
+
+        Example:
+        @code
+        <EventTrigger invert="true">
+            <events>
+                <trigger>
+                    <TriggerBase ... />
+                    <EventListener ... />
+                </trigger>
+            </events>
+        </EventTrigger>
+        @endcode
+
+    @see Trigger
+        For more information on @ref orxonox::Trigger "Triggers".
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup NormalTrigger
+    */
+    class _ObjectsExport EventTrigger : public Trigger
+    {
+        public:
+            EventTrigger(Context* context); // Constructor. Registers and initializes the object.
+            virtual ~EventTrigger();
+
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override; // Creates an event port.
+
+            /**
+            @brief Method that is called when a new event comes in.
+                   The tick call makes sure the state change takes effect immediately.
+            @param bTriggered The state of the incoming event.
+            */
+            inline void trigger(bool bTriggered)
+                { this->bEventTriggered_ = bTriggered; this->tick(0); }
+
+        protected:
+            virtual bool isTriggered(TriggerMode mode) override; // Check whether the EventTrigger should be triggered.
+
+        private:
+            bool bEventTriggered_; //!< Boolean to keep track of what the state of the last event was.
+    };
+}
+
+#endif /* _EventTrigger_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTrigger.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTrigger.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTrigger.cc	(revision 11817)
@@ -0,0 +1,587 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file MultiTrigger.cc
+    @brief Implementation of the MultiTrigger class.
+    @ingroup MultiTrigger
+*/
+
+#include "MultiTrigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "MultiTriggerContainer.h"
+
+namespace orxonox
+{
+
+    RegisterClass(MultiTrigger);
+
+    /**
+    @brief
+        Constructor. Registers the objects and initializes default values.
+    */
+    MultiTrigger::MultiTrigger(Context* context) : TriggerBase(context)
+    {
+        RegisterObject(MultiTrigger);
+
+        this->maxNumSimultaneousTriggerers_ = INF_s;
+
+        this->bBroadcast_ = false;
+
+        this->targetMask_.exclude(Class(BaseObject));
+
+        this->bMultiTrigger_ = true;
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up the state queue.
+    */
+    MultiTrigger::~MultiTrigger()
+    {
+        orxout(verbose, context::triggers) << "Destroying MultiTrigger &" << this << ". " << this->stateQueue_.size() << " states still in queue. Deleting." << endl;
+        while(this->stateQueue_.size() > 0)
+        {
+            MultiTriggerState* state = this->stateQueue_.front().second;
+            this->stateQueue_.pop_front();
+            delete state;
+        }
+    }
+
+    /**
+    @brief
+        Method for creating a MultiTrigger object through XML.
+        For a detailed description of the parameters please see the class description in the header file.
+    */
+    void MultiTrigger::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MultiTrigger, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MultiTrigger, "simultaneousTriggerers", setSimultaneousTriggerers, getSimultaneousTriggerers, xmlelement, mode);
+        XMLPortParam(MultiTrigger, "broadcast", setBroadcast, getBroadcast, xmlelement, mode);
+        XMLPortParamLoadOnly(MultiTrigger, "target", addTarget, xmlelement, mode).defaultValues("Pawn"); //TODO: Remove load only
+
+        orxout(verbose, context::triggers) << "MultiTrigger '" << this->getName() << "' (&" << this << ") created." << endl;
+    }
+
+
+    /**
+    @brief
+        A method that is executed each tick.
+        Most of the magic of MultiTriggers happens here.
+    @param dt
+        The duration of the last tick.
+    */
+    //TODO: Segment into some helper methods?
+    void MultiTrigger::tick(float dt)
+    {
+        // If this is the first tick.
+        if(this->bFirstTick_)
+        {
+            this->bFirstTick_ = false;
+            // Fire for all objects that are targets.
+            this->broadcast(false);
+        }
+
+        // Check if the object is active (this is NOT MultiTrigger::isActive()!), it is whether the MultiTrigger actually does anything, ever.
+        if (!this->BaseObject::isActive())
+            return;
+
+        SUPER(MultiTrigger, tick, dt);
+
+        // Let the MultiTrigger return the states that trigger and process the new states if there are any.
+        std::queue<MultiTriggerState*>* queue  = this->letTrigger();
+        if(queue != nullptr)
+        {
+            while(queue->size() > 0)
+            {
+                MultiTriggerState* state = queue->front();
+                // If the state is nullptr. (This really shouldn't happen)
+                if(state == nullptr)
+                {
+                    orxout(internal_error, context::triggers) << "In MultiTrigger '" << this->getName() << "' (&" << this << "), Error: State of new states queue was nullptr. State ignored." << endl;
+                    queue->pop();
+                    continue;
+                }
+
+                // The new triggered state dependent on the requested state, the mode and the invert-mode.
+                bool bTriggered = (state->bTriggered & this->isModeTriggered(state->originator)) ^ this->getInvert();
+
+                // If the 'triggered' state has changed or the MultiTrigger has delay and thus we don't know whether this state will actually change the 'triggered' state, a new state is added to the state queue.
+                if(this->getDelay() > 0.0f || bTriggered ^ this->isTriggered(state->originator))
+                {
+                    state->bTriggered = bTriggered;
+                    this->addState(state);
+                }
+                // Else the change is irrelevant.
+                else
+                    delete state;
+
+                queue->pop();
+            }
+            delete queue;
+        }
+
+        // Go through the state queue and activate all pending states whose remaining time has expired.
+        if(this->stateQueue_.size() > 0)
+        {
+            MultiTriggerState* state;
+            float timeRemaining;
+
+            // Go through all pending states.
+            for(int size = this->stateQueue_.size(); size >= 1; size--)
+            {
+                timeRemaining = this->stateQueue_.front().first;
+                state = this->stateQueue_.front().second;
+
+                // If the remaining time has expired, the state has to be set as the state of the MultiTrigger.
+                if(timeRemaining <= dt)
+                {
+                    // If the maximum number of objects simultaneously triggering this MultiTrigger is not exceeded.
+                    if(this->getSimultaneousTriggerers() == TriggerBase::INF_s || this->triggered_.size() < (unsigned int)this->getSimultaneousTriggerers())
+                    {
+                        bool bStateChanged = false;
+                        // If the 'triggered' state is different from what it is now, change it.
+                        if(state->bTriggered ^ this->isTriggered(state->originator))
+                        {
+                            // Add the originator to the objects triggering this MultiTrigger.
+                            if(state->bTriggered == true)
+                                this->triggered_.insert(state->originator);
+                            // Remove the originator from the objects triggering this MultiTrigger.
+                            else
+                                this->triggered_.erase(state->originator);
+
+                            bStateChanged = true;
+                        }
+
+                        // Get the activity of the new state.
+                        bool bActive;
+                        // If the MultiTrigger is in switch mode the 'active'-state only changes of the state changed to triggered.
+                        if(this->getSwitch() && !state->bTriggered)
+                            bActive = this->isActive(state->originator);
+                        else
+                            bActive = !this->isActive(state->originator);
+
+                        // If the activity is different from what it is now, change it and fire an Event.
+                        if(bActive ^ this->isActive(state->originator))
+                        {
+                            bool bFire = true;
+
+                            // Add the originator to the objects activating this MultiTrigger.
+                            if(bActive == true)
+                            {
+                                // If the MultiTrigger has not exceeded its remaining activations.
+                                if(this->hasRemainingActivations())
+                                {
+                                    this->active_.insert(state->originator);
+                                    if(this->remainingActivations_ != INF_s)
+                                        this->remainingActivations_--; // Decrement the remaining activations.
+                                }
+                                else
+                                    bFire = false;
+                            }
+                            // Remove the originator from the objects activating this MultiTrigger.
+                            else
+                            {
+                                // If the MultiTrigger doesn't stay active or hasn't' exceeded its remaining activations.
+                                if(!this->getStayActive() || this->hasRemainingActivations())
+                                    this->active_.erase(state->originator);
+                                else
+                                    bFire = false;
+                            }
+
+                            // Fire the Event if the activity has changed.
+                            if(bFire)
+                            {
+                                // If the MultiTrigger is set to broadcast and has no originator a boradcast is fired.
+                                if(this->getBroadcast() && state->originator == nullptr)
+                                    this->broadcast(bActive);
+                                // Else a normal event is fired.
+                                else
+                                    this->fire(bActive, state->originator);
+
+                                bStateChanged = true;
+                            }
+                        }
+
+                        if(bStateChanged)
+                        {
+                            // Print some debug output if the state has changed.
+                            if(state->originator != nullptr)
+                                orxout(verbose, context::triggers) << "MultiTrigger '" << this->getName() << "' (&" << this << ") changed state. originator: " << state->originator->getIdentifier()->getName() << " (&" << state->originator << "), active: " << bActive << ", triggered: " << state->bTriggered << "." << endl;
+                            else
+                                orxout(verbose, context::triggers) << "MultiTrigger '" << this->getName() << "' (&" << this << ") changed state. originator: nullptr, active: " << bActive << ", triggered: " << state->bTriggered << "." << endl;
+
+                            // If the MultiTrigger has a parent trigger, that is itself a MultiTrigger, it needs to call a method to notify him, that its activity has changed.
+                            if(this->parent_ != nullptr && this->parent_->isMultiTrigger())
+                                static_cast<MultiTrigger*>(this->parent_)->childActivityChanged(state->originator);
+                        }
+
+                        // If the MultiTrigger has exceeded its amount of activations and it doesn't stay active, it has to be deactivated.
+                        if(this->remainingActivations_ == 0 && !bActive)
+                        {
+                            this->BaseObject::setActive(false);
+                            orxout(verbose, context::triggers) << "MultiTrigger '" << this->getName() << "' (&" << this << ") ran out of activations. Setting it to inactive." << endl;
+                        }
+                    }
+
+                    // Remove the state from the state queue.
+                    this->stateQueue_.pop_front();
+                    delete state;
+                }
+                // If the remaining time has not yet expired. Decrement the remainig time and put the state at the end of the queue.
+                else
+                {
+                    this->stateQueue_.emplace_back(timeRemaining-dt, state);
+                    this->stateQueue_.pop_front();
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        Check whether the MultiTrigger is active for a given object.
+    @param triggerer
+        A pointer to the object.
+    @return
+        Returns true if the MultiTrigger is active, false if not.
+    */
+    bool MultiTrigger::isActive(BaseObject* triggerer) const
+    {
+        std::set<BaseObject*>::const_iterator it = this->active_.find(triggerer);
+        if(it == this->active_.end())
+            return false;
+        return true;
+    }
+
+    /**
+    @brief
+        Add some target to the MultiTrigger.
+    @param targetStr
+        The target class name as a string.
+    */
+    void MultiTrigger::addTarget(const std::string& targetStr)
+    {
+        Identifier* target = ClassByString(targetStr);
+
+        // If the target is not a valid class name display an error.
+        if (target == nullptr)
+        {
+            orxout(internal_error, context::triggers) << "'" << targetStr << "' is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ")" << endl;
+            return;
+        }
+
+        this->targetMask_.include(target);
+
+        // A MultiTrigger shouldn't react to itself or other triggers.
+        this->targetMask_.exclude(Class(TriggerBase), true);
+
+        // We only want WorldEntities
+        ClassTreeMask WEMask;
+        WEMask.include(Class(WorldEntity));
+        this->targetMask_ *= WEMask;
+    }
+
+    /**
+    @brief
+        Remove some target from the MultiTrigger.
+    @param targetStr
+        The target to be removed as a string.
+    */
+    void MultiTrigger::removeTarget(const std::string& targetStr)
+    {
+        Identifier* target = ClassByString(targetStr);
+
+        // If the target is not a valid class name display an error.
+        if (target == nullptr)
+        {
+            orxout(internal_error, context::triggers) << "'" << targetStr << "' is not a valid class name to include in ClassTreeMask (in " << this->getName() << ", class " << this->getIdentifier()->getName() << ")" << endl;
+            return;
+        }
+
+        this->targetMask_.exclude(target);
+    }
+
+    /**
+    @brief
+        This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
+        This method is the device for the behavior (the conditions under which the MultiTrigger triggers) of any derived class of MultiTrigger.
+    @return
+        Returns a pointer to a queue of MultiTriggerState pointers, containing all the necessary information to decide whether these states should indeed become new states of the MultiTrigger.
+        Please be aware that both the queue and the states in the queue need to be deleted once they have been used. This is already done in the tick() method of this class but would have to be done by any method calling this method.
+    */
+    std::queue<MultiTriggerState*>* MultiTrigger::letTrigger(void)
+    {
+        return nullptr;
+    }
+
+    /**
+    @brief
+        This method can be called by any class inheriting from MultiTrigger to change it's triggered status for a specified originator.
+
+        Compared to the letTrigger mode, which just polls and lets the pollee send it's state changed back, the changeTriggered method lets the trigger advertise its state changes just as they happen so it's much like the interrupt version of letTrigger.
+    @param originator
+        The originator which triggered the state change.
+    */
+    void MultiTrigger::changeTriggered(BaseObject* originator)
+    {
+        MultiTriggerState* state = new MultiTriggerState;
+        state->bTriggered = (!this->isTriggered(originator) & this->isModeTriggered(originator)) ^ this->getInvert();
+        state->originator = originator;
+        this->addState(state);
+    }
+
+    /**
+    @brief
+        This method is called by any child to advertise changes in its state to its parent.
+    @param originator
+        The object that caused the change in activity.
+    */
+    void MultiTrigger::childActivityChanged(BaseObject* originator)
+    {
+        MultiTriggerState* state = new MultiTriggerState;
+        state->bTriggered = (this->isTriggered(originator) & this->isModeTriggered(originator)) ^ this->getInvert();
+        state->originator = originator;
+        this->addState(state);
+    }
+
+    /**
+    @brief
+        Checks whether the children are in such a way that, according to the mode of the MultiTrigger, the MultiTrigger is triggered (only considering the children, not the state of MultiTrigger itself), for a given object.
+        To make an example: When the mode is <em>and</em>, then this would be true or a given object if all the children were triggered for the given object.
+    @param triggerer
+        The object.
+    @return
+        Returns true if the MultiTrigger is triggered concerning it's children.
+    */
+    bool MultiTrigger::isModeTriggered(BaseObject* triggerer)
+    {
+        if(this->children_.size() != 0)
+        {
+            bool triggered = false;
+
+            switch(this->mode_)
+            {
+                case TriggerMode::EventTriggerAND:
+                    triggered = checkAnd(triggerer);
+                    break;
+                case TriggerMode::EventTriggerOR:
+                    triggered = checkOr(triggerer);
+                    break;
+                case TriggerMode::EventTriggerXOR:
+                    triggered = checkXor(triggerer);
+                    break;
+                default: // This will never happen.
+                    triggered = false;
+                    break;
+            }
+
+            return triggered;
+        }
+
+        return true;
+    }
+
+    /**
+    @brief
+        Get whether the MultiTrigger is triggered for a given object.
+    @param triggerer
+        The object.
+    @return
+        Returns true if the MultiTrigger is triggered for the given object.
+    */
+    bool MultiTrigger::isTriggered(BaseObject* triggerer)
+    {
+        std::set<BaseObject*>::iterator it = this->triggered_.find(triggerer);
+        if(it == this->triggered_.end())
+            return false;
+        return true;
+    }
+
+    /**
+    @brief
+        Helper method. Creates an Event for the given status and originator and fires it.
+        Or more precisely creates a MultiTriggerContainer to encompass all neccesary information, creates an Event from that and sends it.
+    @param status
+        The status of the Event to be fired. This is equivalent to the activity of the MultiTrigger.
+    @param originator
+        The object that triggered the MultiTrigger to fire this Event.
+    */
+    void MultiTrigger::fire(bool status, BaseObject* originator)
+    {
+        // If the originator is nullptr, a normal event without MultiTriggerContainer is sent.
+        if(originator == nullptr)
+        {
+            this->fireEvent(status);
+            orxout(verbose, context::triggers) << "MultiTrigger '" <<  this->getName() << "' (&" << this << "): Fired event. status: " << status << "." << endl;
+            return;
+        }
+
+        MultiTriggerContainer* container = new MultiTriggerContainer(this->getContext(), this, originator);
+        this->fireEvent(status, container);
+        orxout(verbose, context::triggers) << "MultiTrigger '" <<  this->getName() << "' (&" << this << "): Fired event. originator: " << originator->getIdentifier()->getName() << " (&" << originator << "), status: " << status << "." << endl;
+        container->destroy();
+    }
+
+    /**
+    @brief
+        Helper method. Broadcasts an Event for every object that is a target.
+    @param status
+        The status of the Events to be fired. This is equivalent to the activity of the MultiTrigger.
+    */
+    void MultiTrigger::broadcast(bool status)
+    {
+        for(ClassTreeMaskObjectIterator it = this->getTargetMask().begin(); it != this->getTargetMask().end(); ++it)
+            this->fire(status, static_cast<BaseObject*>(*it));
+    }
+
+    /**
+    @brief
+        Helper method. Adds a state to the state queue, where the state will wait to become active.
+    @param state
+        The state to be added.
+    @return
+        Returns true if the state has been added, false if not. If the state has not been added this method destroys it.
+    */
+    bool MultiTrigger::addState(MultiTriggerState* state)
+    {
+        assert(state); // The state really shouldn't be nullptr.
+
+        // If the originator is no target of this MultiTrigger.
+        if(!this->isTarget(state->originator))
+        {
+            delete state;
+            return false;
+        }
+
+        // Add it ot the state queue with the delay specified for the MultiTrigger.
+        this->stateQueue_.emplace_back(this->getDelay(), state);
+
+        return true;
+    }
+
+    /**
+    @brief
+        Checks whether the children amount to true for the <em>and</em> mode for a given object.
+    @param triggerer
+        The object.
+    @return
+        Returns true if all the sub-triggers are active.
+    */
+    bool MultiTrigger::checkAnd(BaseObject* triggerer)
+    {
+        for(TriggerBase* trigger : this->children_)
+        {
+            if(trigger->isMultiTrigger())
+            {
+                if(!static_cast<MultiTrigger*>(trigger)->isActive(triggerer))
+                    return false;
+            }
+            else
+            {
+                if(!trigger->isActive())
+                    return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+    @brief
+        Checks whether the children amount to true for the <em>or</em> mode for a given object.
+    @param triggerer
+        The object.
+    @return
+        Returns true if at least one sub-trigger is active.
+    */
+    bool MultiTrigger::checkOr(BaseObject* triggerer)
+    {
+        for(TriggerBase* trigger : this->children_)
+        {
+            if(trigger->isMultiTrigger())
+            {
+                if(static_cast<MultiTrigger*>(trigger)->isActive(triggerer))
+                    return true;
+            }
+            else
+            {
+                if(trigger->isActive())
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+    @brief
+        Checks whether the children amount to true for the <em>xor</em> mode for a given object.
+    @param triggerer
+        The object.
+    @return
+        Returns true if exactly one sub-trigger is active.
+    */
+    bool MultiTrigger::checkXor(BaseObject* triggerer)
+    {
+        bool triggered = false;
+        for(TriggerBase* trigger : this->children_)
+        {
+            if(triggered)
+            {
+                if(trigger->isMultiTrigger())
+                {
+                    if(static_cast<MultiTrigger*>(trigger)->isActive(triggerer))
+                        return false;
+                }
+                else
+                {
+                    if(trigger->isActive())
+                        return false;
+                }
+            }
+
+            if(trigger->isMultiTrigger())
+            {
+                if(static_cast<MultiTrigger*>(trigger)->isActive(triggerer))
+                    triggered = true;
+            }
+            else
+            {
+                if(trigger->isActive())
+                    triggered = true;
+            }
+        }
+        return triggered;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTrigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTrigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTrigger.h	(revision 11817)
@@ -0,0 +1,202 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file MultiTrigger.h
+    @brief Definition of the MultiTrigger class.
+    @ingroup MultiTrigger
+*/
+
+#ifndef _MultiTrigger_H__
+#define _MultiTrigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "core/ClassTreeMask.h"
+
+#include <set>
+#include <deque>
+
+#include "TriggerBase.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+    Struct to handle @ref orxonox::MultiTrigger "MultiTrigger" states internally.
+
+    @ingroup MultiTrigger
+    */
+    struct MultiTriggerState
+    {
+        BaseObject* originator;
+        bool bTriggered;
+    };
+
+    /**
+    @brief
+        The MultiTrigger class implements a trigger that has a distinct state for each object triggering it.
+        In more detail: A Trigger is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. A MultiTrigger generalizes that behavior for multiple objects triggering the trigger. A MultiTrigger can be <em>active</em> or <em>inactive</em> for any object triggering it, with the state for each object being completely independent of the state for other objects. Each time a switch occurs an @ref orxonox::Event "Event" is fired with as the originator a @ref orxonox::MultiTriggerContainer "MultiTriggerContainer", containing a pointer to the MultiTrigger that caused the @ref orxonox::Event "Event" and a pointer to the object that caused the trigger to change it's activity.
+
+        MultiTriggers also allow for additional complexity which can be added through the choice of the parameters explained (briefly) below:
+        But first you must understand a small implementation detail. There is a distinction between the MultiTrigger being triggered (there is the state <em>triggered</em> for that) and the MultiTrigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em>, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the MultiTrigger transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
+        The parameters are:
+        - @b delay The delay is the time that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled.
+        - @b switch Switch is a boolean, if true the MultiTrigger is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
+        - @b stayactive Stay active is also a boolean, if true the MultiTrigger stays active after it has been activated as many times as specified by the parameter <em>activations</em>. The default is <code>false</code>.
+        - @b activations The number of times the MultiTrigger can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+        - @b invert Invert is a boolean, if true the MultiTrigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the MultiTrigger will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it just inverts the behavior of the MultiTrigger. The default is <code>false</code>.
+        - @b simultaneousTriggerers The number of simultaneous triggerers limits the number of objects that are allowed to trigger the MultiTrigger at the same time. Or more precisely, the number of distinct objects the MultiTrigger has <em>triggered</em> states for, at each point in time. The default is <code>-1</code>, which denotes infinity.
+        - @b mode The mode describes how the MultiTrigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the MultiTrigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the MultiTrigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the MultiTrigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the <em>activity</em> of the MultiTrigger and that is the fulfillment of the triggering condition (the MultiTrigger itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a MultiTrigger is still coupled to the object that triggered it. The default is <em>and</em>.
+        - @b broadcast Broadcast is a boolean, if true the MutliTrigger is in <em>broadcast-mode</em>, meaning, that all trigger events that are caused by no originator (originator is nullptr) are broadcast as having come from every possible originator, or more precisely as having come from all objects that are specified targets of this MultiTrigger. The default is false.
+        - @b target The target describes the kind of objects that are allowed to trigger this MultiTrigger. The default is @ref orxonox::Pawn "Pawn".
+        - Also there is the possibility of appending triggers (as long as they inherit from TriggerBase) to the MultiTrigger just by adding them as children in the XML description of your MultiTrigger.
+
+        An example of a MultiTrigger created through XML would look like this:
+        @code
+        <MultiTrigger position="0,0,0" delay="1.3" switch="true" stayactive="true" activations="7" invert="true" simultaneousTriggerers="2" mode="xor" broadcast="false" target="Pawn">
+            <TriggerBase />
+            ...
+            <TriggerBase />
+        </MultiTrigger>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+        Many concepts and loads of inspiration from the @ref orxonox::Trigger "Trigger" class by Benjamin Knecht.
+
+    @ingroup MultiTrigger
+    */
+    class _ObjectsExport MultiTrigger : public TriggerBase
+    {
+        public:
+            MultiTrigger(Context* context); //!< Constructor. Registers the objects and initializes default values.
+            virtual ~MultiTrigger(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode); //!< Method for creating a MultiTrigger object through XML.
+            virtual void tick(float dt); //!< A method that is executed each tick.
+
+            /**
+            @brief Check whether the MultiTrigger is active.
+            @return Returns if the MultiTrigger is active.
+            */
+            inline bool isActive(void) const
+                { return this->isActive(nullptr); }
+            bool isActive(BaseObject* triggerer = nullptr) const; //!< Check whether the MultiTrigger is active for a given object.
+
+            /**
+            @brief Set the number of objects that are allowed to simultaneously trigger this MultiTrigger.
+            @param triggerers The number of objects. -1 denotes infinitely many.
+            */
+            inline void setSimultaneousTriggerers(int triggerers)
+                { if(triggerers >= 0 || triggerers == TriggerBase::INF_s) this->maxNumSimultaneousTriggerers_ = triggerers; }
+            /**
+            @brief Get the number of objects that are allowed to simultaneously trigger this MultiTriggger.
+            @return Returns the number of objects. -1 denotes infinity.
+            */
+            inline int getSimultaneousTriggerers(void)
+                { return this->maxNumSimultaneousTriggerers_; }
+
+            /**
+            @brief Set the broadcast-mode of the MultiTrigger.
+            @param bBroadcast If true the MultiTrigger is set to broadcast;
+            */
+            inline void setBroadcast(bool bBroadcast)
+                { this->bBroadcast_ = bBroadcast; }
+            /**
+            @brief Get the broadcast-mode of the MultiTrigger.
+            @return Returns true if the MultiTrigger is set to broadcast.
+            */
+            inline bool getBroadcast(void)
+                { return this->bBroadcast_; }
+
+            /**
+            @brief Get whether the input object is a target of the MultiTrigger.
+            @param target A pointer to the object.
+            @return Returns true if the input object is a target, false if not.
+            */
+            inline bool isTarget(BaseObject* target)
+                { if(target == nullptr) return true; else return targetMask_.isIncluded(target->getIdentifier()); }
+                
+            void addTarget(const std::string& targets); //!< Add some target to the MultiTrigger.
+
+        protected:
+            virtual std::queue<MultiTriggerState*>* letTrigger(void); //!< This method is called by the MultiTrigger to get information about new trigger events that need to be looked at.
+
+            void changeTriggered(BaseObject* originator = nullptr); //!< This method can be called by any class inheriting from MultiTrigger to change it's triggered status for a specified originator.
+
+            bool isModeTriggered(BaseObject* triggerer = nullptr); //!< Checks whether the MultiTrigger is triggered concerning it's children.
+            bool isTriggered(BaseObject* triggerer = nullptr); //!< Get whether the MultiTrigger is triggered for a given object.
+
+            virtual void fire(bool status, BaseObject* originator = nullptr);  //!< Helper method. Creates an Event for the given status and originator and fires it.
+            void broadcast(bool status); //!< Helper method. Broadcasts an Event for every object that is a target.
+
+            void removeTarget(const std::string& target); //!< Remove some target from the MultiTrigger.
+
+            /**
+            @brief Get the target mask used to identify the targets of this MultiTrigger.
+            @return Returns the target mask.
+            */
+            inline ClassTreeMask& getTargetMask(void)
+                { return this->targetMask_; }
+
+        private:
+            void childActivityChanged(BaseObject* originator); //!< This method is called by any child to advertise changes in it's state to it's parent.
+
+            bool addState(MultiTriggerState* state); //!< Helper method. Adds a state to the state queue, where the state will wait to become active.
+
+            bool checkAnd(BaseObject* triggerer); //!< Checks whether the children amount to true for the <em>and</em> mode for a given object.
+            bool checkOr(BaseObject* triggerer); //!< Checks whether the children amount to true for the <em>or</em> mode for a given object.
+            bool checkXor(BaseObject* triggerer); //!< Checks whether the children amount to true for the <em>xor</em> mode for a given object.
+
+            /**
+            @brief Get the objects for which this MultiTrigger is active.
+            @return Returns a set with all the object this MultiTrigger is active for.
+            */
+            std::set<BaseObject*>& getActive(void)
+                { return this->active_; }
+
+            int maxNumSimultaneousTriggerers_; //!< The maximum number of objects simultaneously trigggering this MultiTrigger.
+
+            bool bBroadcast_; //!< Bool for the broadcast-mode, if true all triggers go to all possible targets.
+
+            std::set<BaseObject*> active_; //!< The set of all objects the MultiTrigger is active for.
+            std::set<BaseObject*> triggered_; //!< The set of all objects the MultiTrigger is triggered for.
+
+            std::deque<std::pair<float, MultiTriggerState*>> stateQueue_; //!< The queue of states waiting to become active.
+
+            ClassTreeMask targetMask_; //!< The target mask, masking all objects that can trigger this MultiTrigger.
+
+    };
+
+}
+
+#endif // _MultiTrigger_H__
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTriggerContainer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTriggerContainer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTriggerContainer.cc	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file MultiTriggerContainer.cc
+    @brief Implementation of the MultiTriggerContainer class.
+    @ingroup MultiTrigger
+*/
+
+#include "MultiTriggerContainer.h"
+
+#include "core/CoreIncludes.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+
+    RegisterUnloadableClass(MultiTriggerContainer);
+
+    /**
+    @brief
+        Default constructor. Registers the object and creates an empty container.
+    */
+    MultiTriggerContainer::MultiTriggerContainer(Context* context) : BaseObject(context), originator_(nullptr), data_(nullptr)
+    {
+        RegisterObject(MultiTriggerContainer);
+    }
+
+    /**
+    @brief
+        Constructor. Registers the object and sets the input values.
+    @param context
+        The context.
+    @param originator
+        A pointer to the originator of the Event, i.e. the MultiTrigger that fired the Event. (or is about to fire)
+    @param data
+        A pointer to the data that should be sent with the container.
+    */
+    MultiTriggerContainer::MultiTriggerContainer(Context* context, MultiTrigger* originator, BaseObject* data) : BaseObject(context), originator_(originator), data_(data)
+    {
+        RegisterObject(MultiTriggerContainer);
+
+        Pawn* pawn = orxonox_cast<Pawn*>(data);
+        if(pawn != nullptr)
+        {
+            this->setForPlayer(true);
+            this->setTriggeringPawn(pawn);
+        }
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    MultiTriggerContainer::~MultiTriggerContainer()
+    {
+
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTriggerContainer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTriggerContainer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/MultiTriggerContainer.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file MultiTriggerContainer.h
+    @brief Definition of the MultiTriggerContainer class.
+    @ingroup MultiTrigger
+*/
+
+#ifndef _MultiTriggerContainer_H__
+#define _MultiTriggerContainer_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include "core/BaseObject.h"
+
+#include "interfaces/PlayerTrigger.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        This class is used by the MultiTrigger class to transport additional data via @ref orxonox::Event "Events".
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup MultiTrigger
+    */
+    class _ObjectsExport MultiTriggerContainer : public BaseObject, public PlayerTrigger
+    {
+
+        public:
+            MultiTriggerContainer(Context* context); //!< Default constructor. Registers the object and creates an empty container.
+            MultiTriggerContainer(Context* context, MultiTrigger* originator, BaseObject* data); //!< Constructor. Registers the object and sets the input values.
+            virtual ~MultiTriggerContainer(); //!< Destructor.
+
+            /**
+            @brief Get the originator of the Event. (The MultiTrigger that fired the Event)
+            @return Returns a pointer to the originator.
+            */
+            inline MultiTrigger* getOriginator(void)
+                { return this->originator_; }
+            /**
+            @brief Get the data of this container.
+            @return Returns a pointer ot the data.
+            */
+            inline BaseObject* getData(void)
+                { return this->data_; }
+
+        private:
+            MultiTrigger* originator_; //!< The originator.
+            BaseObject* data_; //!< The data.
+
+    };
+
+}
+
+#endif // _MultiTriggerContainer_H__
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/Trigger.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/Trigger.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/Trigger.cc	(revision 11817)
@@ -0,0 +1,361 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Trigger.cc
+    @brief Implementation of the Trigger class.
+    @ingroup NormalTrigger
+*/
+
+#include "Trigger.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "Scene.h"
+
+namespace orxonox
+{
+
+    SetConsoleCommand("Trigger", "debugFlares", &Trigger::debugFlares).defaultValues(false);
+
+    RegisterClass(Trigger);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Trigger::Trigger(Context* context) : TriggerBase(context)
+    {
+        RegisterObject(Trigger);
+
+        this->bActive_ = false;
+        this->bTriggered_ = false;
+        this->latestState_ = 0x0;
+
+        this->remainingTime_ = 0.0f;
+        this->timeSinceLastEvent_ = 0.0f;
+
+        // Set the debug billboard.
+        if (this->getScene() && GameMode::showsGraphics())
+        {
+            this->debugBillboard_.setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(1.0, 0.0, 0.0), 1);
+            this->debugBillboard_.setVisible(false);
+
+            if (this->debugBillboard_.getBillboardSet())
+                this->attachOgreObject(this->debugBillboard_.getBillboardSet());
+        }
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    Trigger::~Trigger()
+    {
+
+    }
+
+    /**
+    @brief
+
+    @param dt
+        The time elapsed since last tick.
+    */
+    void Trigger::tick(float dt)
+    {
+        // If this is the first tick, announce, that the trigger is not triggered.
+        // This is needed, e.g. for an inverted trigger, that needs to announce at the beginning, that it is active.
+        if (this->bFirstTick_)
+        {
+            this->bFirstTick_ = false;
+            this->triggered(false);
+        }
+
+        // Check if the object is active (this is NOT Trigger::isActive()!)
+        // If the object is not active we do nothing.
+        if (!this->BaseObject::isActive())
+            return;
+
+        SUPER(Trigger, tick, dt);
+
+        // Apply the invert operation.
+        bool newTriggered = this->isTriggered() ^ this->getInvert();
+
+        // Check if new triggering event is really new. (i.e. if the previous triggering state is not the same as the current)
+        if ((this->latestState_ & 0x1) != newTriggered)
+        {
+            // Create new state
+            if (newTriggered)
+            {
+                this->latestState_ |= 1; // Set triggered bit to 1.
+                this->switchState(); // Toggle the activity of the trigger.
+            }
+            else
+            {
+                this->latestState_ &= 0xFE; // Set triggered bit to 0.
+                // If this trigger is not in switched-mode (i.e. it switches its activity only if it changes from not triggered to triggered and not the other way around), the activity of the trigger is toggled.
+                if (!this->getSwitch())
+                    this->switchState();
+            }
+        }
+
+        // If there is time remaining, i.e. there are states in the queue waiting to take effect.
+        if (this->remainingTime_ > 0.0)
+        {
+            // Discount the last tick time from the time remaining.
+            this->remainingTime_ -= dt;
+            // Increase the time since the last event (the time since the last state took effect), but only when actually waiting for a state in the queue
+            if (this->timeSinceLastEvent_ >= 0.0)
+                this->timeSinceLastEvent_ += dt;
+        }
+
+        // If the remaining time has run out and there are states in the queue waiting to take effect.
+        while (this->remainingTime_ <= 0.0 && this->stateChanges_.size() > 0)
+        {
+            // Get the state to take effect and apply it.
+            char newState = this->stateChanges_.front().second;
+            this->bTriggered_ = (newState & 0x1);
+            this->bActive_ = newState & 0x2;
+
+            // Fire a triggered (or un-triggered, depending on the activity) event.
+            this->triggered(this->bActive_);
+
+            // Remove the state that was just applied from the queue.
+            this->stateChanges_.pop();
+
+            // If there are still states in the queue, set the remaining time to the time of the next state to take effect.
+            if (this->stateChanges_.size() != 0)
+                this->remainingTime_ = this->stateChanges_.front().first;
+            // Else the time since the last event is set to the delay.
+            else
+                this->timeSinceLastEvent_ = this->getDelay();
+        }
+
+        // Set the color of the debug billboard according to the current state of the trigger.
+        if (this->bTriggered_ && this->bActive_)
+            this->setBillboardColour(ColourValue(0.5, 1.0, 0.0));
+        else if (!this->bTriggered_ && this->bActive_)
+            this->setBillboardColour(ColourValue(0.0, 1.0, 0.0));
+        else if (this->bTriggered_ && !this->bActive_)
+            this->setBillboardColour(ColourValue(1.0, 0.5, 0.0));
+        else
+            this->setBillboardColour(ColourValue(1.0, 0.0, 0.0));
+    }
+
+    /**
+    @brief
+        Fires an event with the input triggered state.
+    @param bIsTriggered
+        The triggered state.
+    */
+    void Trigger::triggered(bool bIsTriggered)
+    {
+        this->fireEvent(bIsTriggered);
+    }
+
+    /**
+    @brief
+        Check whether the Trigger should be triggered, given only its sub-triggers, given a specific mode.
+    @param mode
+        The Trigger mode. Specifies how the sub-triggers are combined and how they affect the Trigger.
+    @return
+        Returns true if the Trigger should be triggered and false if not.
+    */
+    bool Trigger::isTriggered(TriggerMode mode)
+    {
+        // If the trigger has sub-triggers.
+        if (this->children_.size() > 0)
+        {
+            switch (mode)
+            {
+                case TriggerMode::EventTriggerAND:
+                    return checkAnd();
+                case TriggerMode::EventTriggerOR:
+                    return checkOr();
+                case TriggerMode::EventTriggerXOR:
+                    return checkXor();
+                default:
+                    return false;
+            }
+        }
+        // If the trigger has no sub-triggers, whether it is triggered should only depend on itself and nothing else, thus this returns true.
+        return true;
+    }
+
+    /**
+    @brief
+        Check whether all the sub-triggers of this Trigger are active.
+        This is in fact the conjunction (logical AND) of the activity of all its sub-triggers.
+    @return
+        Returns true if all the sub-triggers of this Trigger are active, false if at least one of them is not active.
+    */
+    bool Trigger::checkAnd()
+    {
+        // Iterate over all sub-triggers.
+        for (TriggerBase* child : this->children_)
+        {
+            if (!child->isActive())
+                return false;
+        }
+        return true;
+    }
+
+    /**
+    @brief
+        Check whether at least one of the sub-triggers of this Trigger is active.
+        This is in fact the disjunction (logical OR) of the activity of all its sub-triggers.
+    @return
+        Returns true if at least one of the sub-triggers of this Trigger is active, false if none of them is active.
+    */
+    bool Trigger::checkOr()
+    {
+        // Iterate over all sub-triggers.
+        for (TriggerBase* child : this->children_)
+        {
+            if (child->isActive())
+                return true;
+        }
+        return false;
+    }
+
+    /**
+    @brief
+        Check whether exactly one of the sub-triggers of this Trigger is active.
+        This is in fact the logical XOR of the activity of all its sub-triggers.
+    @return
+        Returns true if exactly one of the sub-triggers of this Trigger is active, false if none of them or two or more of them are active.
+    */
+    bool Trigger::checkXor()
+    {
+        bool test = false;
+        for (TriggerBase* child : this->children_)
+        {
+            if (test && child->isActive())
+                return false;
+            if (child->isActive())
+                test = true;
+        }
+        return test;
+    }
+
+    /**
+    @brief
+        Switch (toggle) the activity of the Trigger.
+    @return
+        Returns true if the activity of the Trigger has changed. False if not.
+    */
+    bool Trigger::switchState()
+    {
+        // If the previous state was active and there are no remaining activations, but the trigger stays active.
+        // or if the previous state was inactive and there are no remaining activations.
+        // the activity is not switched.
+        if (( (this->latestState_ & 0x2) && this->getStayActive() && (this->remainingActivations_ <= 0))
+           || (!(this->latestState_ & 0x2)                        && (this->remainingActivations_ == 0)))
+            return false;
+        // Else the activity is switched.
+        else
+        {
+            this->latestState_ ^= 0x2; // Toggle activity bit.
+
+            // If the activity has switched to active, decrease the remaining activations.
+            if (this->latestState_ & 0x2 && this->remainingActivations_ > 0)
+                this->remainingActivations_--;
+
+            // Store the new state in the queue.
+            this->storeState();
+
+            return true;
+        }
+    }
+
+    /**
+    @brief
+        Stores the state in the queue.
+        The queue is a list of states that are waiting to take effect paired with the time it has to wait after its preceding state takes effect.
+    */
+    void Trigger::storeState()
+    {
+        // Put the state change into the queue.
+        this->stateChanges_.push(std::pair<float, char>(this->timeSinceLastEvent_, this->latestState_));
+        // Reset time since last event
+        this->timeSinceLastEvent_ = 0.0;
+
+        // If there is just one state in the queue. (i.e. the one that we just added), The remaining time is set to the time it takes for the next state to take effect.
+        if (this->stateChanges_.size() == 1)
+            this->remainingTime_ = this->stateChanges_.front().first;
+    }
+
+    /**
+    @brief
+        React to a change in delay.
+        Only newly arriving states are affected by a change in delay.
+    */
+    void Trigger::delayChanged(void)
+    {
+        this->timeSinceLastEvent_ = this->getDelay();
+    }
+
+    /**
+    @brief
+        Set the visibility of all debug billboards of all Triggers.
+    @param bVisible
+        The visibility the billboards are set to.
+    */
+    void Trigger::debugFlares(bool bVisible)
+    {
+        // Iterate over all Triggers.
+        for (Trigger* trigger : ObjectList<Trigger>())
+            trigger->setVisible(bVisible);
+    }
+
+    /**
+    @brief
+        Set the colour of the debug billboard.
+    @param colour
+        The colour the billboard is set to.
+    */
+    void Trigger::setBillboardColour(const ColourValue& colour)
+    {
+        this->debugBillboard_.setColour(colour);
+    }
+
+    /**
+    @brief
+        React to a change of visibility of the trigger by adjusting the visibility of the debug billboards.
+    */
+    void Trigger::changedVisibility()
+    {
+        SUPER(Trigger, changedVisibility);
+
+        this->debugBillboard_.setVisible(this->isVisible());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/Trigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/Trigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/Trigger.h	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Trigger.h
+    @brief Definition of the Trigger class.
+    @ingroup NormalTrigger
+*/
+
+#ifndef _Trigger_H__
+#define _Trigger_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <set>
+#include <queue>
+
+#include "tools/BillboardSet.h"
+
+#include "TriggerBase.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+         A Trigger is an object that can either be <em>active</em> or <em>inactive</em>, with a specified behavior how to switch between the two. Each time a switch occurs an @ref orxonox::Event "Event" is fired with as the originator the Trigger that caused the @ref orxonox::Event "Event".
+         
+        Triggers also allow for additional complexity which can be added through the choice of the parameters explained below:
+        But first it is imperative to understand a small implementation detail. There is a distinction between the Trigger being triggered (there is the state <em>triggered</em> for that) and the Trigger being active (for that is the state <em>activity</em>). From the outside only the <em>activity</em> is visible. The state <em>triggered</em> tells us whether the trigger is actually triggered, but it could pretend (for some reason, some of which we will see shortly) to be <em>active</em>, while it in fact isn't. The standard behavior is, that the <em>activity</em> changes, when the Trigger transits from being <em>triggered</em> to being <em>not triggered</em> or the other way around.
+        The parameters are:
+        - @b delay The delay is the time that the trigger waits until it reacts (i.e. changes it's state) to the triggering condition being fulfilled.
+        - @b switch Switch is a boolean, if true the Trigger is in <em>switch-mode</em>, meaning, that the <em>activity</em> changes only when the trigger is triggered, this means, that now the <em>activity</em> only changes, when the trigger changes from not being triggered to being triggered but not the other way around. The default is <code>false</code>.
+        - @b stayactive Stay active is also a boolean, if true the Trigger stays active after it has been activated as many times as specified by the parameter <em>activations</em>. The default is <code>false</code>.
+        - @b activations The number of times the Trigger can be activated until the trigger can't be triggered anymore. The default is <code>-1</code>, which denotes infinity.
+        - @b invert Invert is a boolean, if true the Trigger is in <em>invert-mode</em>, meaning, that if the triggering condition is fulfilled the Trigger will have the state <em>not triggered</em> and and if the condition is not fulfilled it will have the state <em>triggered</em>. In short it just inverts the behavior of the Trigger. The default is <code>false</code>.
+        - @b mode The mode describes how the Trigger acts in relation to all the triggers, that are appended to it. There are 3 modes: <em>and</em>, meaning that the Trigger can only be triggered if all the appended triggers are active. <em>or</em>, meaning that the Trigger can only triggered if at least one of the appended triggers is active. And <em>xor</em>, meaning that the Trigger can only be triggered if one and only one appended trigger is active. Note, that I wrote <em>can only be active</em>, that implies, that there is an additional condition to the <em>activity</em> of the Trigger and that is the fulfillment of the triggering condition (the Trigger itself doesn't have one, but all derived classes should). Also bear in mind, that the <em>activity</em> of a Trigger is still coupled to the object that triggered it. The default is <em>and</em>.
+        - Also there is the possibility of appending triggers (as long as they inherit from TriggerBase) to the Trigger just by adding them as children in the XML description of your Trigger.
+
+        An example of a Trigger created through XML would look like this:
+        @code
+        <Trigger position="0,0,0" delay="1.3" switch="true" stayactive="true" activations="7" invert="true" mode="xor" broadcast="false" target="Pawn">
+            <TriggerBase />
+            ...
+            <TriggerBase />
+        </Trigger>
+        @endcode
+
+    @author
+        Benjamin Knecht
+
+    @ingroup NormalTrigger
+    */
+    class _ObjectsExport Trigger : public TriggerBase
+    {
+        public:
+            Trigger(Context* context); // Constructor. Registers and initializes the object.
+            virtual ~Trigger();
+
+            virtual void tick(float dt);
+
+            /**
+            @brief Check whether the Trigger is active.
+            @return Returns if the Trigger is active.
+            */
+            inline bool isActive(void) const
+                { return this->bActive_; }
+
+            void delayChanged(void); // React to a change in delay.
+
+            static void debugFlares(bool bVisible); // Set the visibility of all debug billboards of all Triggers.
+            virtual void changedVisibility(); // React to a change of visibility of the trigger by adjusting the visibility of the debug billboards.
+
+        protected:
+            /**
+            @brief Check whether the Trigger is triggered according to its mode.
+            @return Returns true if the Trigger is triggered, false if not.
+            */
+            inline bool isTriggered()
+                { return this->isTriggered(this->mode_); }
+            virtual bool isTriggered(TriggerMode mode); // Check whether the Trigger should be triggered, given only its sub-triggers, given a specific mode.
+            virtual void triggered(bool bIsTriggered); // Fires an event with the input triggered state.
+
+        private:
+            bool switchState(); // Switch (toggle) the activity (to the outside the triggered state) of the trigger.
+            void storeState(); // Stores the state in the queue.
+            
+            bool checkAnd(); // Check whether all the sub-triggers of this Trigger are active.
+            bool checkOr(); // Check whether at least one of the sub-triggers of this Trigger is active.
+            bool checkXor(); // Check whether exactly one of the sub-triggers of this Trigger is active.
+            
+            void setBillboardColour(const ColourValue& colour); // Set the colour of the debug billboard.
+
+            bool bActive_; //!< Whether the trigger is active (to the outside triggered).
+            bool bTriggered_; //!< Whether the trigger is triggered (to the inside).
+
+            char latestState_; //!< Temporarily stores a state consisting of whether the trigger is triggeres at the first bit (least significant bit) and its activity at the second bit.
+            float remainingTime_; //!< The time until the next state (in the queue) takes effect.
+            float timeSinceLastEvent_; //!< The time since the last event came in.
+
+            BillboardSet debugBillboard_; //!< A set of debug billboards to visualize the state of the trigger.
+
+            std::queue<std::pair<float, char>> stateChanges_; //!< A queue of state changes (in the same format as latestState_) paired with the time they will take effect since the last state change took effect.
+    };
+
+}
+
+#endif /* _Trigger_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/TriggerBase.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/TriggerBase.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/TriggerBase.cc	(revision 11817)
@@ -0,0 +1,178 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TriggerBase.cc
+    @brief Implementation of the TriggerBase class.
+    @ingroup Triggers
+*/
+
+#include "TriggerBase.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox {
+
+    // Initialization of some static (magic) variables.
+    /*static*/ const int TriggerBase::INF_s = -1;
+    /*static*/ const std::string TriggerBase::and_s = "and";
+    /*static*/ const std::string TriggerBase::or_s = "or";
+    /*static*/ const std::string TriggerBase::xor_s = "xor";
+
+    RegisterClass(TriggerBase);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes some values.
+    */
+    TriggerBase::TriggerBase(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(TriggerBase);
+
+        this->bFirstTick_ = true;
+
+        this->delay_ = 0.0f;
+        this->bSwitch_ = false;
+        this->bStayActive_ = false;
+
+        this->remainingActivations_ = INF_s;
+
+        this->bInvertMode_ = false;
+        this->mode_ = TriggerMode::EventTriggerAND;
+
+        this->parent_ = nullptr;
+
+        this->bMultiTrigger_ = false;
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    TriggerBase::~TriggerBase()
+    {
+        
+    }
+
+    /**
+    @brief
+        Method for creating a TriggerBase object through XML.
+        For a detailed description of the parameters please see the class description in the header file.
+    */
+    void TriggerBase::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TriggerBase, XMLPort, xmlelement, mode);
+
+        XMLPortParam(TriggerBase, "delay", setDelay, getDelay, xmlelement, mode);
+        XMLPortParam(TriggerBase, "switch", setSwitch, getSwitch, xmlelement, mode);
+        XMLPortParam(TriggerBase, "stayactive", setStayActive, getStayActive, xmlelement, mode);
+        XMLPortParam(TriggerBase, "activations", setActivations, getActivations, xmlelement, mode);
+        XMLPortParam(TriggerBase, "invert", setInvert, getInvert, xmlelement, mode);
+        XMLPortParamTemplate(TriggerBase, "mode", setMode, getModeString, xmlelement, mode, const std::string&);
+
+        XMLPortObject(TriggerBase, TriggerBase, "", addTrigger, getTrigger, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Set the mode of the trigger.
+    @param modeName
+        The name of the mode as a string.
+    */
+    void TriggerBase::setMode(const std::string& modeName)
+    {
+        if (modeName == TriggerBase::and_s)
+            this->setMode(TriggerMode::EventTriggerAND);
+        else if (modeName == TriggerBase::or_s)
+            this->setMode(TriggerMode::EventTriggerOR);
+        else if (modeName == TriggerBase::xor_s)
+            this->setMode(TriggerMode::EventTriggerXOR);
+        else
+            orxout(internal_warning, context::triggers) << "Invalid mode '" << modeName << "' in TriggerBase " << this->getName() << " &(" << this << "). Leaving mode at '" << this->getModeString() << "'." << endl;
+    }
+
+    /**
+    @brief
+        Get the mode of the MultiTrigger.
+    @return
+        Returns the mode as a string.
+    */
+    const std::string& TriggerBase::getModeString(void) const
+    {
+        if (this->mode_ == TriggerMode::EventTriggerAND)
+            return TriggerBase::and_s;
+        else if (this->mode_ == TriggerMode::EventTriggerOR)
+            return TriggerBase::or_s;
+        else if (this->mode_ == TriggerMode::EventTriggerXOR)
+            return TriggerBase::xor_s;
+        else // This can never happen, but the compiler needs it to feel secure.
+            return TriggerBase::and_s;
+    }
+
+    /**
+    @brief
+        Adds a trigger as a child to the trigger.
+        Beware: Loops are not prevented and potentially very bad, so just don't create any loops.
+    @param trigger
+        The trigger to be added.
+    */
+    void TriggerBase::addTrigger(TriggerBase* trigger)
+    {
+        assert(trigger);
+        if (this != trigger)
+            this->children_.insert(trigger);
+        trigger->addParentTrigger(this);
+    }
+
+    /**
+    @brief
+        Get the child of this trigger at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer ot the trigger. nullptr if no such trigger exists.
+    */
+    const TriggerBase* TriggerBase::getTrigger(unsigned int index) const
+    {
+        // If the index is greater than the number of children.
+        if (this->children_.size() <= index)
+            return nullptr;
+
+        std::set<TriggerBase*>::const_iterator it;
+        it = this->children_.begin();
+
+        for (unsigned int i = 0; i != index; ++i)
+            ++it;
+
+        return (*it);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/objects/triggers/TriggerBase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/objects/triggers/TriggerBase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/objects/triggers/TriggerBase.h	(revision 11817)
@@ -0,0 +1,219 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TriggerBase.h
+    @brief Definition of the TriggerBase class.
+    @ingroup Triggers
+*/
+
+#ifndef _TriggerBase_H__
+#define _TriggerBase_H__
+
+#include "objects/ObjectsPrereqs.h"
+
+#include <set>
+#include <string>
+
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        The different modes the trigger can be in.
+
+    @ingroup Triggers
+    */
+    enum class TriggerMode
+    {
+        EventTriggerAND, //!< The <em>and</em> mode. The trigger can only trigger if all the children are active.
+        EventTriggerOR, //!< The <em>or</em> mode. The trigger can only trigger if at least one child is active.
+        EventTriggerXOR, //!< The <em>xor</em> mode. The trigger can only trigger if exactly one child is active.
+    };
+
+    /**
+    @brief
+        The TriggerBase class is a base class for the two types of triggers, the (normal) @ref orxonox::Trigger "Triggers" and the @ref orxonox::MultiTrigger "MultiTriggers", it encompasses the shared data and functionality between these two types of triggers, but is in itself not a trigger that has any meaningful behavior and thus should not be instantiated.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Triggers
+    */
+    class _ObjectsExport TriggerBase : public StaticEntity, public Tickable
+    {
+        public:
+            TriggerBase(Context* context);
+            virtual ~TriggerBase();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);  //!< Method for creating a TriggerBase object through XML.
+
+            /**
+            @brief Check whether the trigger is active. (i.e. triggered to the outside)
+            @return Returns if the trigger is active.
+            */
+            virtual bool isActive(void) const
+                { return false; }
+
+            /**
+            @brief Set the delay of the trigger.
+            @param delay The delay to be set.
+            */
+            inline void setDelay(float delay)
+                { if(delay > 0.0f) this->delay_= delay; this->delayChanged(); }
+            /**
+            @brief Get the delay of the trigger.
+            @return The delay.
+            */
+            inline float getDelay(void) const
+                { return this->delay_; }
+            virtual void delayChanged(void) {}
+
+            /**
+            @brief Set switch-mode of the trigger.
+            @param bSwitch If true the trigger is set to switched.
+            */
+            inline void setSwitch(bool bSwitch)
+                { this->bSwitch_ = bSwitch; }
+            /**
+            @brief Get the switch-mode of the trigger.
+            @return Returns true if the trigger is in switch-mode.
+            */
+            inline bool getSwitch(void) const
+                { return this->bSwitch_; }
+
+            /**
+            @brief Set the stay-active-mode of the trigger.
+            @param bStayActive If true the trigger is set to stay active.
+            */
+            inline void setStayActive(bool bStayActive)
+                { this->bStayActive_ = bStayActive; }
+            /**
+            @brief Get the stay-active-mode of the trigger.
+            @return Returns true if the trigger stays active.
+            */
+            inline bool getStayActive(void) const
+                { return this->bStayActive_; }
+
+            /**
+            @brief Get the number of remaining activations of the trigger.
+            @return The number of activations. -1 denotes infinity.
+            */
+            inline int getActivations(void) const
+                { return this->remainingActivations_; }
+            /**
+            @brief Check whether the trigger has still at least one remaining activation.
+            @return Returns true if the trigger has remaining activations (i.e. the number of remaining activations is not zero).
+            */
+            inline bool hasRemainingActivations(void) const
+                { return this->remainingActivations_ > 0 || this->remainingActivations_ == INF_s; }
+
+            /**
+            @brief Set the invert-mode of triggerhe trigger.
+            @param bInvert If true the t is set to invert.
+            */
+            inline void setInvert(bool bInvert)
+                { this->bInvertMode_ = bInvert; }
+            /**
+            @brief Get the invert-mode of the trigger.
+            @return Returns true if the trigger is set to invert.
+            */
+            inline bool getInvert(void) const
+                { return this->bInvertMode_; }
+
+            void setMode(const std::string& modeName); //!< Set the mode of the trigger.
+            /**
+            @brief Set the mode of the trigger.
+            @param mode The mode of the trigger.
+            */
+            inline void setMode(TriggerMode mode) //!< Get the mode of the trigger.
+                { this->mode_ = mode; }
+            const std::string& getModeString(void) const;
+            /**
+            @brief Get the mode of the trigger.
+            @return Returns and Enum for the mode of the trigger.
+            */
+            inline TriggerMode getMode(void) const
+                { return mode_; }
+
+            void addTrigger(TriggerBase* trigger);
+            const TriggerBase* getTrigger(unsigned int index) const;
+
+            /**
+            @brief Check whether this trigger is a @ref orxonox::MultiTrigger "MultiTrigger".
+                This is done for performance reasons.
+            */
+            inline bool isMultiTrigger(void)
+                { return this->bMultiTrigger_; }
+
+        protected:
+            static const int INF_s; //!< Magic number for infinity.
+            //! Magic strings for the mode.
+            static const std::string and_s;
+            static const std::string or_s;
+            static const std::string xor_s;
+
+            /**
+            @brief Set the number of activations the trigger can go through.
+            @param activations The number of activations. -1 denotes infinitely many activations.
+            */
+            inline void setActivations(int activations)
+                { if(activations >= 0 || activations == INF_s) this->remainingActivations_ = activations; }
+                
+            inline bool hasRemainingActivations(void)
+                { return this->remainingActivations_ == INF_s || this->remainingActivations_  > 0; }
+
+            /**
+            @brief Adds the parent of a MultiTrigger.
+            @param parent A pointer to the parent MultiTrigger.
+            */
+            inline void addParentTrigger(TriggerBase* parent)
+                { this->parent_ = parent; }
+
+            bool bFirstTick_; //!< Bool to check whether this is the first tick.
+
+            float delay_; //!< The delay that is imposed on all new trigger events.
+            bool bSwitch_; //!< Bool for the switch-mode, if true the trigger behaves like a switch.
+            bool bStayActive_; //!< Bool for the stay-active-mode, if true the trigger stays active after its last activation.;
+
+            int remainingActivations_; //!< The remaining activations of this trigger.
+
+            bool bInvertMode_; //!< Bool for the invert-mode, if true the trigger is inverted.
+            TriggerMode mode_; //!< The mode of the trigger.
+
+            TriggerBase* parent_; //!< The parent of this trigger.
+            std::set<TriggerBase*> children_; //!< The children of this trigger.
+
+            bool bMultiTrigger_; //!< Specifies whether this trigger is a MultiTrigger.
+
+    };
+}
+
+#endif /* _Trigger_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,21 @@
+SET_SOURCE_FILES(OVERLAYS_SRC_FILES
+  OverlayText.cc
+  FadeoutText.cc
+  GUIOverlay.cc
+)
+
+ADD_SUBDIRECTORY(debugging)
+ADD_SUBDIRECTORY(hud)
+ADD_SUBDIRECTORY(stats)
+
+ORXONOX_ADD_LIBRARY(overlays
+  MODULE
+  FIND_HEADER_FILES
+  PCH_FILE
+    OverlaysPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+    pickup
+    weapons
+  SOURCE_FILES ${OVERLAYS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/overlays/FadeoutText.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/FadeoutText.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/FadeoutText.cc	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FadeoutText.h"
+
+#include <OgreTextAreaOverlayElement.h>
+#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(FadeoutText);
+
+    FadeoutText::FadeoutText(Context* context) : OverlayText(context)
+    {
+        RegisterObject(FadeoutText);
+
+        this->delay_ = 3.0f;
+        this->fadeouttime_ = 1.0f;
+
+        this->bFadingOut_ = false;
+        this->fadeouttimer_.setTimer(3.0f, false, createExecutor(createFunctor(&FadeoutText::fadeout, this)));
+        this->fadeouttimer_.stopTimer();
+
+        this->initialAlpha_ = 1.0f;
+    }
+
+    void FadeoutText::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FadeoutText, XMLPort, xmlelement, mode);
+
+        XMLPortParam(FadeoutText, "delay", setDelay, getDelay, xmlelement, mode);
+        XMLPortParam(FadeoutText, "fadeout", setFadeouttime, getFadeouttime, xmlelement, mode);
+    }
+
+    void FadeoutText::tick(float dt)
+    {
+        if (this->bFadingOut_)
+        {
+            ColourValue colour = this->getColour();
+
+            if (colour.a > 0)
+            {
+                float alpha = colour.a;
+
+                alpha -= dt / this->fadeouttime_;
+                if (alpha < 0)
+                    alpha = 0;
+                colour.a = alpha;
+
+                this->text_->setColour(colour);
+            }
+            else
+            {
+                this->text_->setCaption("");
+                this->reset();
+            }
+        }
+    }
+
+    void FadeoutText::fadeout()
+    {
+        this->bFadingOut_ = true;
+    }
+
+    void FadeoutText::reset()
+    {
+        this->bFadingOut_ = false;
+
+        ColourValue colour = this->getColour();
+        colour.a = this->initialAlpha_;
+        this->text_->setColour(colour);
+    }
+
+    void FadeoutText::changedColour()
+    {
+        OverlayText::changedColour();
+
+        this->initialAlpha_ = this->getColour().a;
+    }
+
+    void FadeoutText::changedCaption()
+    {
+        OverlayText::changedCaption();
+
+        this->reset();
+        this->fadeouttimer_.setInterval(this->delay_);
+        this->fadeouttimer_.startTimer();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/FadeoutText.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/FadeoutText.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/FadeoutText.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FadeoutText_H__
+#define _FadeoutText_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/Timer.h"
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport FadeoutText : public OverlayText, public Tickable
+    {
+        public:
+            FadeoutText(Context* context);
+            virtual ~FadeoutText() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+            inline void setDelay(float delay)
+                { this->delay_ = delay; }
+            inline float getDelay() const
+                { return this->delay_; }
+
+            inline void setFadeouttime(float fadeouttime)
+                { this->fadeouttime_ = fadeouttime; }
+            inline float getFadeouttime() const
+                { return this->fadeouttime_; }
+
+        private:
+            virtual void changedColour() override;
+            virtual void changedCaption() override;
+
+            void fadeout();
+            void reset();
+
+            float delay_;
+            float fadeouttime_;
+
+            bool bFadingOut_;
+            Timer fadeouttimer_;
+
+            float initialAlpha_;
+    };
+}
+#endif /* _FadeoutText_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/GUIOverlay.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/GUIOverlay.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/GUIOverlay.cc	(revision 11817)
@@ -0,0 +1,104 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GUIOverlay.h"
+
+#include <string>
+
+#include "util/Convert.h"
+#include "core/input/InputManager.h"
+#include "core/CoreIncludes.h"
+#include "core/GUIManager.h"
+#include "core/XMLPort.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(GUIOverlay);
+
+    GUIOverlay::GUIOverlay(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(GUIOverlay);
+    }
+
+    GUIOverlay::~GUIOverlay()
+    {
+    }
+
+    void GUIOverlay::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(GUIOverlay, XMLPort, xmlelement, mode);
+
+        XMLPortParam(GUIOverlay, "guiname", setGUIName, getGUIName, xmlelement, mode);
+    }
+
+    void GUIOverlay::changedVisibility()
+    {
+        SUPER(GUIOverlay, changedVisibility);
+
+        //Setting player now.
+        if (this->getOwner())
+        {
+            ControllableEntity* entity = orxonox_cast<ControllableEntity*>(this->getOwner());
+            if (entity)
+                GUIManager::getInstance().setPlayer(this->guiName_, entity->getPlayer());
+        }
+
+        if (this->isVisible())
+        {
+            const std::string& str = multi_cast<std::string>(reinterpret_cast<long long>(this));
+            GUIManager::getInstance().showGUIExtra(this->guiName_, str);
+
+            orxout(verbose, context::misc::gui) << "Showing GUI " << this->guiName_ << endl;
+        }
+        else
+        {
+            GUIManager::hideGUI(this->guiName_);
+            orxout(verbose, context::misc::gui) << "Hiding GUI " << this->guiName_ << endl;
+        }
+    }
+
+    void GUIOverlay::setGUIName(const std::string& name)
+    {
+        this->guiName_ = name;
+        if (this->getOwner())
+        {
+            ControllableEntity* entity = orxonox_cast<ControllableEntity*>(this->getOwner());
+            if (entity)
+                GUIManager::getInstance().setPlayer(name, entity->getPlayer()); //Set Player is going to be nullptr, so it needs to be set in changedVisibility() as well.
+        }
+    }
+
+    void GUIOverlay::changedOwner()
+    {
+        SUPER(GUIOverlay, changedOwner);
+        if (!this->getGUIName().empty())
+            this->setGUIName(this->getGUIName());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/GUIOverlay.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/GUIOverlay.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/GUIOverlay.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GUIOverlay_H__
+#define _GUIOverlay_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <string>
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport GUIOverlay : public OrxonoxOverlay
+    {
+        public:
+
+            GUIOverlay(Context* context);
+            virtual ~GUIOverlay();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setGUIName(const std::string& name);
+            inline const std::string& getGUIName() const { return this->guiName_; }
+
+            virtual void changedVisibility() override;
+            virtual void changedOwner() override;
+
+        private:
+            std::string guiName_;
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/overlays/OverlayText.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/OverlayText.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/OverlayText.cc	(revision 11817)
@@ -0,0 +1,169 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "OverlayText.h"
+
+#include <OgreOverlayManager.h>
+#include <OgrePanelOverlayElement.h>
+#include <OgreTextAreaOverlayElement.h>
+
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+
+namespace orxonox
+{
+    RegisterClass(OverlayText);
+
+    static_assert((int)Ogre::TextAreaOverlayElement::Left   == (int)OverlayText::Alignment::Left,   "check enum");
+    static_assert((int)Ogre::TextAreaOverlayElement::Center == (int)OverlayText::Alignment::Center, "check enum");
+    static_assert((int)Ogre::TextAreaOverlayElement::Right  == (int)OverlayText::Alignment::Right,  "check enum");
+
+    OverlayText::OverlayText(Context* context)
+        : OrxonoxOverlay(context)
+    {
+        RegisterObject(OverlayText);
+
+        this->text_ = static_cast<Ogre::TextAreaOverlayElement*>(Ogre::OverlayManager::getSingleton()
+            .createOverlayElement("TextArea", "OverlayText_text_" + getUniqueNumberString()));
+        this->text_->setCharHeight(1.0);
+
+        this->setFont("Monofur");
+        this->setColour(ColourValue(1.0, 1.0, 1.0, 1.0));
+        this->setCaption("");
+        this->setTextSize(1.0f);
+        this->setAlignmentString("left");
+
+        this->background_->addChild(this->text_);
+    }
+
+    OverlayText::~OverlayText()
+    {
+        if (this->isInitialized())
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->text_);
+    }
+
+    void OverlayText::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(OverlayText, XMLPort, xmlelement, mode);
+
+        XMLPortParam(OverlayText, "font",       setFont,            getFont,            xmlelement, mode);
+        XMLPortParam(OverlayText, "colour",     setColour,          getColour,          xmlelement, mode);
+        XMLPortParam(OverlayText, "caption",    setCaption,         getCaption,         xmlelement, mode);
+        XMLPortParam(OverlayText, "textsize",   setTextSize,        getTextSize,        xmlelement, mode);
+        XMLPortParam(OverlayText, "align",      setAlignmentString, getAlignmentString, xmlelement, mode);
+        XMLPortParam(OverlayText, "spacewidth", setSpaceWidth,      getSpaceWidth,      xmlelement, mode);
+    }
+
+    void OverlayText::setAlignmentString(const std::string& alignment)
+    {
+        if (alignment == "right")
+            this->setAlignment(OverlayText::Alignment::Right);
+        else if (alignment == "center")
+            this->setAlignment(OverlayText::Alignment::Center);
+        else // "left" and default
+            this->setAlignment(OverlayText::Alignment::Left);
+    }
+
+    std::string OverlayText::getAlignmentString() const
+    {
+        Ogre::TextAreaOverlayElement::Alignment alignment = this->text_->getAlignment();
+
+        switch (alignment)
+        {
+            case Ogre::TextAreaOverlayElement::Right:
+                return "right";
+            case Ogre::TextAreaOverlayElement::Center:
+                return "center";
+            case Ogre::TextAreaOverlayElement::Left:
+                return "left";
+            default:
+                assert(false); return "";
+        }
+    }
+
+    void OverlayText::sizeChanged()
+    {
+        if (this->rotState_ == RotationState::Horizontal)
+            this->overlay_->setScale(size_.y * sizeCorrection_.y, size_.y * sizeCorrection_.y);
+        else if (this->rotState_ == RotationState::Vertical)
+            this->overlay_->setScale(size_.y / (sizeCorrection_.y * sizeCorrection_.y), size_.y * sizeCorrection_.y);
+        else
+            this->overlay_->setScale(size_.y, size_.y);
+
+        positionChanged();
+    }
+
+    void OverlayText::setCaption(const std::string& caption)
+    {
+        this->text_->setCaption(caption);
+        this->changedCaption();
+    }
+    std::string OverlayText::getCaption() const
+    {
+        return this->text_->getCaption();
+    }
+
+    void OverlayText::setFont(const std::string& font)
+    {
+        if (!font.empty())
+            this->text_->setFontName(font);
+    }
+    const std::string& OverlayText::getFont() const
+    {
+        return this->text_->getFontName();
+    }
+
+    void OverlayText::setSpaceWidth(float width)
+    {
+        this->text_->setSpaceWidth(width);
+    }
+    float OverlayText::getSpaceWidth() const
+    {
+        return this->text_->getSpaceWidth();
+    }
+
+    void OverlayText::setColour(const ColourValue& colour)
+    {
+        this->text_->setColour(colour); this->changedColour();
+    }
+    const ColourValue& OverlayText::getColour() const
+    {
+        return this->text_->getColour();
+    }
+
+    void OverlayText::setAlignment(OverlayText::Alignment alignment)
+    {
+        this->text_->setAlignment(static_cast<Ogre::TextAreaOverlayElement::Alignment>(alignment));
+    }
+    OverlayText::Alignment OverlayText::getAlignment() const
+    {
+        return static_cast<OverlayText::Alignment>(this->text_->getAlignment());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/OverlayText.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/OverlayText.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/OverlayText.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _OverlayText_H__
+#define _OverlayText_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <string>
+#include "util/Math.h"
+#include "util/OgreForwardRefs.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport OverlayText : public OrxonoxOverlay
+    {
+    public:
+        enum class Alignment
+        {
+            Left,
+            Right,
+            Center
+        };
+
+        OverlayText(Context* context);
+        virtual ~OverlayText();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        void setCaption(const std::string& caption);
+        std::string getCaption() const;
+
+        void setFont(const std::string& font);
+        const std::string& getFont() const;
+
+        void setSpaceWidth(float width);
+        float getSpaceWidth() const;
+
+        void setColour(const ColourValue& colour);
+        const ColourValue& getColour() const;
+
+        void setAlignment(OverlayText::Alignment alignment);
+        OverlayText::Alignment getAlignment() const;
+
+        void setAlignmentString(const std::string& alignment);
+        std::string getAlignmentString() const;
+
+        inline void setTextSize(float size) { this->setSize(Vector2(size, size)); }
+        inline float getTextSize() const    { return this->getSize().y; }
+
+    protected:
+        virtual void sizeChanged() override;
+        virtual void changedColour() {}
+        virtual void changedCaption() {}
+
+        Ogre::TextAreaOverlayElement* text_;
+    };
+}
+#endif /* _OverlayText_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/OverlaysPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/OverlaysPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/OverlaysPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the overlays module
+@details
+    Updated: 19. September 2009
+    Total Files: 21
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <tinyxml/ticpp.h> // 14
+//#include <OgreOverlayelement.h> // 7, 7.2MB
+#include <bullet/LinearMath/btMotionState.h> // 6
+//#include <OgrePanelOverlayelement.h> // 5
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "overlays/OrxonoxOverlay.h" // 21
+#include "core/CoreIncludes.h"       // 20
+
+///////////////////////////////////////////
+/////      Not so Stable Headers      /////
+///////////////////////////////////////////
+
+#include "core/command/Executor.h"     // 13
+//#include "network/synchronisable/Synchronisable.h" // 13
+//#include "core/XMLPort.h"    // 9
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/overlays/OverlaysPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/OverlaysPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/OverlaysPrereqs.h	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the overlays module
+*/
+
+#ifndef _OverlaysPrereqs_H__
+#define _OverlaysPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(OVERLAYS_STATIC_BUILD)
+#  ifdef OVERLAYS_SHARED_BUILD
+#    define _OverlaysExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _OverlaysExport
+#    else
+#      define _OverlaysExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _OverlaysPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _OverlaysExport  __attribute__ ((visibility("default")))
+#  define _OverlaysPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _OverlaysExport
+#  define _OverlaysPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class FadeoutText;
+    class GUIOverlay;
+    class OverlayText;
+
+    // debugging
+    class DebugFPSText;
+    class DebugRTRText;
+
+    // hud
+    class AnnounceMessage;
+    class BarColour;
+    class ChatOverlay;
+    class CountDown;
+    class DeathMessage;
+    class GametypeFadingMessage;
+    class GametypeStaticMessage;
+    class GametypeStatus;
+    class HUDBar;
+    class HUDHealthBar;
+    class HUDNavigation;
+    class HUDRadar;
+    class HUDSpeedBar;
+    class HUDShieldBar;
+    class HUDBoostBar;
+    class HUDRocketFuelBar;
+    class HUDEnemyHealthBar;
+    class HUDEnemyShieldBar;
+    class HUDWeaponSystem;
+    class HUDWeapon;
+    class HUDWeaponMode;
+    class HUDTimer;
+    class HUDAimAssistant;
+    class KillMessage;
+    class LastManStandingInfos;
+    class PauseNotice;
+    class TeamBaseMatchScore;
+    class HUDPickupSystem;
+
+    // stats
+    class CreateLines;
+    class Scoreboard;
+    class Stats;
+}
+
+#endif /* _OverlaysPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,5 @@
+ADD_SOURCE_FILES(OVERLAYS_SRC_FILES
+  DebugFPSText.cc
+  DebugRTRText.cc
+  DebugPositionText.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugFPSText.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugFPSText.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugFPSText.cc	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DebugFPSText.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/Game.h"
+
+namespace orxonox
+{
+    RegisterClass(DebugFPSText);
+
+    DebugFPSText::DebugFPSText(Context* context) : OverlayText(context)
+    {
+        RegisterObject(DebugFPSText);
+    }
+
+    DebugFPSText::~DebugFPSText()
+    {
+    }
+
+    void DebugFPSText::tick(float dt)
+    {
+        SUPER(DebugFPSText, tick, dt);
+
+        float fps = Game::getInstance().getAvgFPS();
+        this->setCaption(multi_cast<std::string>(fps));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugFPSText.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugFPSText.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugFPSText.h	(revision 11817)
@@ -0,0 +1,48 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DebugFPSText_H__
+#define _DebugFPSText_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport DebugFPSText : public OverlayText, public Tickable
+    {
+    public:
+        DebugFPSText(Context* context);
+        virtual ~DebugFPSText();
+
+        virtual void tick(float dt) override;
+    };
+}
+#endif /* _DebugFPSText_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugPositionText.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugPositionText.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugPositionText.cc	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DebugPositionText.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/Game.h"
+
+#include "controllers/NewHumanController.h"
+
+namespace orxonox
+{
+    RegisterClass(DebugPositionText);
+
+    DebugPositionText::DebugPositionText(Context* context) : OverlayText(context)
+    {
+        RegisterObject(DebugPositionText);
+    }
+
+    DebugPositionText::~DebugPositionText()
+    {
+    }
+
+    void DebugPositionText::tick(float dt)
+    {
+        SUPER(DebugPositionText, tick, dt);
+        
+        ObjectList<NewHumanController>::iterator it = ObjectList<NewHumanController>().begin();
+        if (it && it->getControllableEntity() )
+        {
+            Vector3 pos = it->getControllableEntity()->getPosition();
+            this->setCaption(multi_cast<std::string>(pos));
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugPositionText.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugPositionText.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugPositionText.h	(revision 11817)
@@ -0,0 +1,48 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DebugPositionText_H__
+#define _DebugPositionText_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport DebugPositionText : public OverlayText, public Tickable
+    {
+    public:
+        DebugPositionText(Context* context);
+        virtual ~DebugPositionText();
+
+        virtual void tick(float dt) override;
+    };
+}
+#endif /* _DebugPositionText_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugRTRText.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugRTRText.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugRTRText.cc	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DebugRTRText.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/Game.h"
+
+namespace orxonox
+{
+    RegisterClass(DebugRTRText);
+
+    DebugRTRText::DebugRTRText(Context* context) : OverlayText(context)
+    {
+        RegisterObject(DebugRTRText);
+    }
+
+    DebugRTRText::~DebugRTRText()
+    {
+    }
+
+    void DebugRTRText::tick(float dt)
+    {
+        SUPER(DebugRTRText, tick, dt);
+
+        float rtr = Game::getInstance().getAvgTickTime();
+        this->setCaption(multi_cast<std::string>(rtr));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugRTRText.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugRTRText.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/debugging/DebugRTRText.h	(revision 11817)
@@ -0,0 +1,48 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DebugRTRText_H__
+#define _DebugRTRText_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport DebugRTRText : public OverlayText, public Tickable
+    {
+    public:
+        DebugRTRText(Context* context);
+        virtual ~DebugRTRText();
+
+        virtual void tick(float dt) override;
+    };
+}
+#endif /* _DebugRTRText_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/AnnounceMessage.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/AnnounceMessage.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/AnnounceMessage.cc	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "AnnounceMessage.h"
+
+#include "core/CoreIncludes.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(AnnounceMessage);
+
+    AnnounceMessage::AnnounceMessage(Context* context) : FadeoutText(context)
+    {
+        RegisterObject(AnnounceMessage);
+
+        this->owner_ = nullptr;
+
+        this->setDelay(3.0f);
+        this->setFadeouttime(1.0f);
+    }
+
+    void AnnounceMessage::announcemessage(const GametypeInfo* gtinfo, const std::string& message)
+    {
+        if (this->owner_ && this->owner_->getGametypeInfo() == gtinfo)
+            this->setCaption(message);
+    }
+
+    void AnnounceMessage::changedOwner()
+    {
+        SUPER(AnnounceMessage, changedOwner);
+
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/AnnounceMessage.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/AnnounceMessage.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/AnnounceMessage.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _AnnounceMessage_H__
+#define _AnnounceMessage_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "interfaces/GametypeMessageListener.h"
+#include "overlays/FadeoutText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport AnnounceMessage : public FadeoutText, public GametypeMessageListener
+    {
+        public:
+            AnnounceMessage(Context* context);
+            virtual ~AnnounceMessage() {}
+
+            virtual void changedOwner() override;
+
+            virtual void announcemessage(const GametypeInfo* gtinfo, const std::string& message) override;
+
+        private:
+            PlayerInfo* owner_;
+    };
+}
+#endif /* _AnnounceMessage_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,29 @@
+ADD_SOURCE_FILES(OVERLAYS_SRC_FILES
+  HUDBar.cc
+  HUDNavigation.cc
+  HUDRadar.cc
+  HUDSpeedBar.cc
+  HUDBoostBar.cc
+  HUDShieldBar.cc
+  HUDHealthBar.cc
+  HUDRocketFuelBar.cc
+  HUDTimer.cc
+  HUDEnemyHealthBar.cc
+  HUDEnemyShieldBar.cc
+  HUDWeaponMode.cc
+  HUDWeapon.cc
+  HUDWeaponSystem.cc
+  HUDPickupSystem.cc
+  ChatOverlay.cc
+  AnnounceMessage.cc
+  KillMessage.cc
+  DeathMessage.cc
+  TeamBaseMatchScore.cc
+  GametypeStaticMessage.cc
+  GametypeFadingMessage.cc
+  LastManStandingInfos.cc
+  PauseNotice.cc
+  LastTeamStandingInfos.cc
+  CountDown.cc
+  StoryModeHUD.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/ChatOverlay.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/ChatOverlay.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/ChatOverlay.cc	(revision 11817)
@@ -0,0 +1,99 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ChatOverlay.h"
+
+#include <string>
+#include <OgreTextAreaOverlayElement.h>
+
+#include "util/Convert.h"
+#include "util/DisplayStringConversions.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/command/Executor.h"
+
+#include "tools/Timer.h"
+#include "infos/PlayerInfo.h"
+#include "PlayerManager.h"
+
+namespace orxonox
+{
+    RegisterClass(ChatOverlay);
+
+    ChatOverlay::ChatOverlay(Context* context)
+        : OverlayText(context)
+    {
+        RegisterObject(ChatOverlay);
+
+        this->displayTime_ = 0.0;
+
+        this->setConfigValues();
+    }
+
+    ChatOverlay::~ChatOverlay()
+    {
+        for (Timer* timer : this->timers_)
+            delete timer;
+    }
+
+    void ChatOverlay::setConfigValues()
+    {
+        SetConfigValue(displayTime_, 6.0f);
+    }
+
+    void ChatOverlay::incomingChat(const std::string& message, const std::string& /*name*/)
+    {
+        this->messages_.push_back(multi_cast<Ogre::DisplayString>(message));
+
+        Timer* timer = new Timer();
+        this->timers_.insert(timer); // store the timer in a set to destroy it in the destructor
+        const ExecutorPtr executor = createExecutor(createFunctor(&ChatOverlay::dropMessage, this));
+        executor->setDefaultValues(timer);
+        timer->setTimer(this->displayTime_, false, executor, true);
+
+        this->updateOverlayText();
+    }
+
+    void ChatOverlay::dropMessage(Timer* timer)
+    {
+        if (this->messages_.size() > 0)
+            this->messages_.pop_front();
+        this->updateOverlayText();
+        this->timers_.erase(timer); // the timer destroys itself, but we have to remove it from the set
+    }
+
+    void ChatOverlay::updateOverlayText()
+    {
+        this->text_->setCaption("");
+
+        for (const Ogre::DisplayString& message : this->messages_)
+        {
+            this->text_->setCaption(this->text_->getCaption() + "\n" + message);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/ChatOverlay.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/ChatOverlay.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/ChatOverlay.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ChatOverlay_H__
+#define _ChatOverlay_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <list>
+#include <OgreOverlayElement.h>
+
+#include "chat/ChatListener.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport ChatOverlay : public OverlayText, public ChatListener
+    {
+        public:
+            ChatOverlay(Context* context);
+            virtual ~ChatOverlay();
+
+            void setConfigValues();
+
+        protected:
+            virtual void incomingChat(const std::string& message, const std::string& name) override;
+
+            std::list<Ogre::DisplayString> messages_;
+
+        private:
+            void updateOverlayText();
+            void dropMessage(Timer* timer);
+
+            float displayTime_;
+            std::set<Timer*> timers_;
+    };
+}
+#endif /* _DebugFPSText_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/CountDown.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/CountDown.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/CountDown.cc	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CountDown.cc
+    @brief Countdown HUD element, counting down from CountDown::counter_ to zero.
+    
+    In use it would like this:
+        @code
+        <OverlayGroup name="spacefightHUD" scale = "1, 1">
+          <CountDown
+              position    = "0.49, 0.05"
+              pickpoint   = "0.0, 0.0"
+              font        = "ShareTechMono"
+              textsize    = 0.06
+              colour      = "1.0, 1.0, 1.0, 1.0"
+              align       = "right"                  
+              counter     = "10.0"
+              speedfactor = "1.0"
+              active      = "false"
+           >
+            <events>
+              <activity>
+                <EventListener event="startcounting" />
+              </activity>
+            </events>
+          </CountDown>
+        </OverlayGroup>
+        @endcode
+        The counter is triggered by an event called "startcounting" and counts from 10 to 0.
+*/
+
+#include "CountDown.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "infos/PlayerInfo.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    RegisterClass(CountDown);
+
+    CountDown::CountDown(Context* context) : OverlayText(context)
+    {
+        RegisterObject(CountDown);
+
+        this->owner_ = nullptr;
+        this->hasStopped_ = false;
+    }
+    
+    CountDown::~CountDown()
+    {
+    }
+    
+    void CountDown::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CountDown, XMLPort, xmlelement, mode);
+        XMLPortParam(CountDown, "counter", setCounter, getCounter, xmlelement, mode).defaultValues(10);
+        XMLPortParam(CountDown, "speedfactor", setSpeed, getSpeed, xmlelement, mode).defaultValues(1);
+    }
+    
+    void CountDown::tick(float dt)
+    {
+        SUPER(CountDown, tick, dt);
+        if (this->isActive() && !this->hasStopped_)
+        {
+            if (this->counter_ <= 0)
+            {
+                this->counter_ = 0;
+                this->hasStopped_ = true;
+                this->setCaption("");
+            }
+            else
+            {
+                this->counter_ -= dt*speed_;
+                this->setCaption(multi_cast<std::string>((int)this->counter_)); //TODO: evtl. initialize with +0.5f
+            }
+        }
+    }
+
+    void CountDown::changedOwner()
+    {
+        SUPER(CountDown, changedOwner);
+
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/CountDown.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/CountDown.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/CountDown.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _CountDown_H__
+#define _CountDown_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/TimeFactorListener.h"
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport CountDown : public OverlayText, public Tickable
+    {
+        public:
+            CountDown(Context* context);
+            virtual ~CountDown();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+            virtual void tick(float dt) override;
+
+            inline void setCounter(float value)
+                { this->counter_ = value + 0.99f; }
+            inline float getCounter() const
+                { return this->counter_; }
+            inline void setSpeed(float value)
+                { this->speed_ = value; }
+            inline float getSpeed() const
+                { return this->speed_; }
+                
+        protected:
+
+        private:
+            PlayerInfo* owner_;
+            float counter_;
+            float speed_;
+            bool hasStopped_;
+    };
+}
+#endif /* _CountDown_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/DeathMessage.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/DeathMessage.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/DeathMessage.cc	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DeathMessage.h"
+
+#include "core/CoreIncludes.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(DeathMessage);
+
+    DeathMessage::DeathMessage(Context* context) : FadeoutText(context)
+    {
+        RegisterObject(DeathMessage);
+
+        this->owner_ = nullptr;
+
+        this->setDelay(2.0f);
+        this->setFadeouttime(0.5f);
+    }
+
+    void DeathMessage::deathmessage(const GametypeInfo* gtinfo, const std::string& message)
+    {
+        if (this->owner_ && this->owner_->getGametypeInfo() == gtinfo)
+            this->setCaption(message);
+    }
+
+    void DeathMessage::changedOwner()
+    {
+        SUPER(DeathMessage, changedOwner);
+
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/DeathMessage.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/DeathMessage.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/DeathMessage.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DeathMessage_H__
+#define _DeathMessage_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "interfaces/GametypeMessageListener.h"
+#include "overlays/FadeoutText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport DeathMessage : public FadeoutText, public GametypeMessageListener
+    {
+        public:
+            DeathMessage(Context* context);
+            virtual ~DeathMessage() {}
+
+            virtual void changedOwner() override;
+
+            virtual void deathmessage(const GametypeInfo* gtinfo, const std::string& message) override;
+
+        private:
+            PlayerInfo* owner_;
+    };
+}
+#endif /* _DeathMessage_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeFadingMessage.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeFadingMessage.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeFadingMessage.cc	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GametypeFadingMessage.h"
+
+#include "core/CoreIncludes.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(GametypeFadingMessage);
+
+    GametypeFadingMessage::GametypeFadingMessage(Context* context) : FadeoutText(context)
+    {
+        RegisterObject(GametypeFadingMessage);
+
+        this->owner_ = nullptr;
+        this->setDelay(2.0f);
+        this->setFadeouttime(0.5f);
+    }
+
+    GametypeFadingMessage::~GametypeFadingMessage()
+    {
+    }
+
+    void GametypeFadingMessage::fadingmessage(const GametypeInfo* gtinfo, const std::string& message)
+    {
+        if (this->owner_ && this->owner_->getGametypeInfo() == gtinfo)
+            this->setCaption(message);
+    }
+
+    void GametypeFadingMessage::changedOwner()
+    {
+        SUPER(GametypeFadingMessage, changedOwner);
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeFadingMessage.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeFadingMessage.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeFadingMessage.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GametypeFadingMessage_H__
+#define _GametypeFadingMessage_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "interfaces/GametypeMessageListener.h"
+#include "overlays/FadeoutText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport GametypeFadingMessage : public FadeoutText, GametypeMessageListener
+    {
+        public:
+            GametypeFadingMessage(Context* context);
+            virtual ~GametypeFadingMessage();
+
+            virtual void changedOwner() override;
+
+            virtual void fadingmessage(const GametypeInfo* gtinfo, const std::string& message) override;
+
+        private:
+            PlayerInfo* owner_;
+    };
+}
+#endif /* _GametypeFadingMessage_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeStaticMessage.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeStaticMessage.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeStaticMessage.cc	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GametypeStaticMessage.h"
+
+#include "core/CoreIncludes.h"
+#include "infos/GametypeInfo.h"
+#include "infos/PlayerInfo.h"
+
+
+namespace orxonox
+{
+    RegisterClass(GametypeStaticMessage);
+
+
+    GametypeStaticMessage::GametypeStaticMessage(Context* context) : OverlayText(context)
+    {
+        RegisterObject(GametypeStaticMessage);
+        this->owner_ = nullptr;
+    }
+
+    GametypeStaticMessage::~GametypeStaticMessage()
+    {
+    }
+
+    void GametypeStaticMessage::staticmessage(const GametypeInfo* gtinfo, const std::string& message, const ColourValue& colour)
+    {
+    if (this->owner_ && this->owner_->getGametypeInfo() == gtinfo)
+    {
+        this->setColour(colour);
+        this->setCaption(message);
+    }
+    }
+
+    void GametypeStaticMessage::changedOwner()
+    {
+        SUPER(GametypeStaticMessage, changedOwner);
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeStaticMessage.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeStaticMessage.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/GametypeStaticMessage.h	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GametypeInfoMessage_H__
+#define _GametypeInfoMessage_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "interfaces/GametypeMessageListener.h"
+#include "overlays/OverlayText.h"
+/*Goal: Every Gametype could add a hud-element that displays text in the gametype. For example instructions for newbies.
+-> you have to add a "GametypeInfoMessage"-object that displays text. How the message change has to be defined in the gametype.
+*/
+
+namespace orxonox
+{
+    class _OverlaysExport GametypeStaticMessage : public OverlayText, GametypeMessageListener
+    {
+        public:
+            GametypeStaticMessage(Context* context);
+            virtual ~GametypeStaticMessage();
+
+            virtual void changedOwner() override;
+
+            virtual void staticmessage(const GametypeInfo* gtinfo, const std::string& message, const ColourValue& colour) override;
+
+        private:
+            PlayerInfo* owner_;
+    };
+}
+#endif /* _GametypeInfoMessage_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBar.cc	(revision 11817)
@@ -0,0 +1,250 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Yuning Chai
+ *   Co-authors:
+ *      Felix Schulthess
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *      Benjamin Knecht
+ *
+ */
+
+#include "HUDBar.h"
+
+#include <OgreOverlayManager.h>
+#include <OgreMaterialManager.h>
+#include <OgreTechnique.h>
+#include <OgrePass.h>
+#include <OgrePanelOverlayElement.h>
+
+#include "util/Convert.h"
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(BarColour);
+
+    BarColour::BarColour(Context* context) : BaseObject(context)
+    {
+        RegisterObject(BarColour);
+        
+        this->setColour(ColourValue(1.0, 1.0, 1.0, 1.0));
+        this->setPosition(0.0);
+    }
+
+    void BarColour::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(BarColour, XMLPort, xmlelement, mode);
+
+        XMLPortParam(BarColour, "colour", setColour, getColour, xmlelement, mode);
+        XMLPortParam(BarColour, "position", setPosition, getPosition, xmlelement, mode);
+    }
+
+
+    unsigned int HUDBar::materialcount_s = 0;
+
+    RegisterClass(HUDBar);
+
+    HUDBar::HUDBar(Context* context) : OrxonoxOverlay(context), right2Left_(false), autoColour_(false)
+    {
+        RegisterObject(HUDBar);
+
+        // create new material
+        const std::string& materialname = "barmaterial" + multi_cast<std::string>(materialcount_s++);
+        Ogre::MaterialPtr material = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().create(materialname, "General"));
+        material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
+        this->textureUnitState_ = material->getTechnique(0)->getPass(0)->createTextureUnitState();
+        this->textureUnitState_->setTextureName("bar2.png");
+        this->textureUnitState_->setNumMipmaps(0);
+        // use the default colour
+        this->textureUnitState_->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, ColourValue(0.2f, 0.7f, 0.2f));
+
+        this->bar_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+            .createOverlayElement("Panel", "HUDBar_bar_" + getUniqueNumberString()));
+        this->bar_->setMaterialName(materialname);
+
+        this->bar_->setPosition(0.0f,0.0f);
+        this->bar_->setDimensions(1.0f,1.0f);
+
+        this->bUseIcon_ = false;
+        this->value_ = 1.0f;  // initialize with 1.0f to trigger a change when calling setValue(0.0f) on the line below
+        this->setAutoColour(true);
+        this->setValue(0.0f); // <--
+        this->setRightToLeft(false);
+        this->currentColour_ = ColourValue::White;
+
+        this->background_->addChild(bar_);
+
+        this->icon_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDBar_icon_" + getUniqueNumberString()));
+        this->icon_->setPosition(0.06f,0.0f);
+        this->icon_->setDimensions(0.1f,1.0f);
+        this->background_->addChild(this->icon_);
+    }
+
+    HUDBar::~HUDBar()
+    {
+        if (this->isInitialized())
+        {
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->bar_);
+            for (std::vector<BarColour*>::const_iterator it = this->barColours_.begin(); it != this->barColours_.end(); )
+                (*it++)->destroy();
+        }
+    }
+
+    void HUDBar::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HUDBar, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HUDBar, "initialvalue", setValue,       getValue,       xmlelement, mode);
+        XMLPortParam(HUDBar, "righttoleft",  setRightToLeft, getRightToLeft, xmlelement, mode);
+        XMLPortParam(HUDBar, "autocolour",   setAutoColour,  getAutoColour,  xmlelement, mode);
+        XMLPortParam(HUDBar, "bartexture",   setBarTexture,  getBarTexture, xmlelement, mode);
+        XMLPortParam(HUDBar, "iconmaterial", setIconMaterial, getIconMaterial, xmlelement, mode);
+        XMLPortObject(HUDBar, BarColour, "", addColour, getColour, xmlelement, mode);
+    }
+
+    void HUDBar::valueChanged()
+    {
+        if (this->autoColour_ && this->textureUnitState_)
+        {
+            // set colour
+            if (this->colours_.size() > 0)
+            {
+                ColourValue colour1(0, 0, 0, 1);
+                ColourValue colour2 = this->colours_.rbegin()->second;
+                float value1(0);
+                float value2 = this->colours_.rbegin()->first;
+                for (std::map<float, ColourValue>::reverse_iterator it = this->colours_.rbegin(); it != this->colours_.rend(); ++it)
+                {
+                    colour1 = colour2;
+                    value1 = value2;
+                    colour2 = it->second;
+                    value2 = it->first;
+
+                    if (value2 < this->value_)
+                        break;
+                }
+
+                if (value2 > this->value_)
+                {
+                    this->textureUnitState_->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, colour2);
+                    this->currentColour_ = colour2;
+                }
+                else if (value1 < this->value_)
+                {
+                    this->textureUnitState_->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, colour1);
+                    this->currentColour_ = colour1;
+                }
+                else
+                {
+                    //float interpolationfactor = (this->value_ - value2) / (value1 - value2);
+                    float interpolationfactor = interpolateSmooth((this->value_ - value2) / (value1 - value2), 0.0f, 1.0f);
+                    this->currentColour_ = colour1 * interpolationfactor + colour2 * (1 - interpolationfactor);
+                    this->textureUnitState_->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, this->currentColour_);
+
+                }
+            }
+        }
+
+        float height = this->bar_->getHeight();
+        float top = this->bar_->getTop();
+
+        // set value
+        if (this->right2Left_)
+        {
+            // backward case
+            if (this->bUseIcon_)
+            {
+                this->bar_->setPosition(0.16f + 0.78f * (1 - this->value_), top);
+                this->bar_->setDimensions(0.78f * this->value_, height);
+            }
+            else
+            {
+                this->bar_->setPosition(0.06f + 0.88f * (1 - this->value_), top);
+                this->bar_->setDimensions(0.88f * this->value_, height);
+            }
+        }
+        else
+        {
+            // default case
+            if (this->bUseIcon_)
+            {
+                this->bar_->setPosition(0.16f, top);
+                this->bar_->setDimensions(0.78f * this->value_, height);
+            }
+            else
+            {
+                this->bar_->setPosition(0.06f, top);
+                this->bar_->setDimensions(0.88f * this->value_, height);
+            }
+        }
+
+        if (this->value_ != 0)
+            this->bar_->setTiling(this->value_, 1.0);
+    }
+
+    void HUDBar::addColour(BarColour* colour)
+    {
+        float value = clamp<float>(colour->getPosition(), 0.0, 1.0);
+        this->colours_[value] = colour->getColour();
+
+        this->barColours_.push_back(colour);
+    }
+
+    BarColour* HUDBar::getColour(unsigned int index)
+    {
+        if (index < this->barColours_.size())
+            return barColours_[index];
+        else
+            return nullptr;
+    }
+
+    void HUDBar::clearColours()
+    {
+        this->colours_.clear();
+    }
+
+    void HUDBar::setBarTexture(const std::string& texture)
+    {
+        this->textureUnitState_->setTextureName(texture);
+    }
+
+    const std::string& HUDBar::getBarTexture() const
+    {
+        return this->textureUnitState_->getTextureName();
+    }
+
+    void HUDBar::setIconMaterial(const std::string& iconMaterial)
+    {
+        this->bUseIcon_ = true;
+        this->icon_->setMaterialName(iconMaterial);
+        valueChanged();
+    }
+
+    const std::string& HUDBar::getIconMaterial() const
+    {
+        return this->icon_->getMaterialName();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBar.h	(revision 11817)
@@ -0,0 +1,150 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Yuning Chai
+ *   Co-authors:
+ *      Felix Schulthess
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *      Benjamin Knecht
+ *
+ */
+
+#ifndef _HUDBar_H__
+#define _HUDBar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <vector>
+#include <OgrePanelOverlayElement.h>
+
+#include "util/Math.h"
+#include "util/OgreForwardRefs.h"
+#include "core/BaseObject.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport BarColour : public BaseObject
+    {
+    public:
+        BarColour(Context* context);
+        virtual ~BarColour() { }
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        void setColour(const ColourValue& colour) { this->colour_ = colour; }
+        const ColourValue& getColour() const { return this->colour_; }
+
+        void setPosition(float pos) { this->position_ = pos; }
+        float getPosition() const    { return this->position_; }
+
+    private:
+        ColourValue colour_;
+        float position_;
+    };
+
+
+    class _OverlaysExport HUDBar : public OrxonoxOverlay
+    {
+    public:
+        HUDBar(Context* context);
+        virtual ~HUDBar();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        void clearColours();
+
+        inline void setRightToLeft(bool r2l)
+        {
+            if (r2l != this->right2Left_)
+            {
+                this->right2Left_ = r2l;
+                this->valueChanged();
+            }
+        }
+        inline bool getRightToLeft() const
+            { return this->right2Left_; }
+
+        inline void setValue(float value)
+        {
+            float temp = clamp(value, 0.0f, 1.0f);
+            if (temp != this->value_)
+            {
+                this->value_ = temp;
+                this->valueChanged();
+            }
+        }
+        inline float getValue() const
+            { return this->value_; }
+
+        inline void setAutoColour(bool val)
+        {
+            if (val != this->autoColour_)
+            {
+                this->autoColour_ = val;
+                this->valueChanged();
+
+                if (!val)
+                    this->currentColour_ = ColourValue::White;
+            }
+        }
+        inline bool getAutoColour() const
+            { return this->autoColour_; }
+
+        void setBarTexture(const std::string& texture);
+        const std::string& getBarTexture() const;
+
+        void setIconMaterial(const std::string& iconMaterial);
+        const std::string& getIconMaterial() const;
+
+        inline const ColourValue& getCurrentBarColour() const
+            { return this->currentColour_; }
+
+        inline void setIconPosition(Vector2 position)
+            { this->icon_->setPosition(position.x, position.y); }
+        inline void setIconDimensions(Vector2 dimensions)
+            { this->icon_->setDimensions(dimensions.x, dimensions.y); }
+
+    protected:
+        virtual void valueChanged();
+    private:
+        void addColour(BarColour* colour);
+        BarColour* getColour(unsigned int index);
+
+        bool right2Left_;
+        bool autoColour_;                   //!< whether bar changes colour automatically
+        float value_;                       //!< progress of bar
+        ColourValue currentColour_;
+        bool bUseIcon_;
+
+        Ogre::PanelOverlayElement* bar_;
+        Ogre::TextureUnitState* textureUnitState_;
+        Ogre::PanelOverlayElement* icon_;
+        std::map<float, ColourValue> colours_;
+        std::vector<BarColour*> barColours_;
+
+        static unsigned int materialcount_s;
+    };
+}
+#endif /* _HUDBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBoostBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBoostBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBoostBar.cc	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDBoostBar.h"
+
+#include "core/CoreIncludes.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "items/Engine.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDBoostBar);
+
+    HUDBoostBar::HUDBoostBar(Context* context)
+        : HUDBar(context)
+    {
+        RegisterObject(HUDBoostBar);
+
+        this->owner_ = nullptr;
+        this->flashInterval_ = 0.25f;
+        this->flashDt_ = 0.0f;
+    }
+
+    HUDBoostBar::~HUDBoostBar()
+    {
+    }
+
+    void HUDBoostBar::tick(float dt)
+    {
+        SUPER(HUDBoostBar, tick, dt);
+
+        if (this->owner_)
+        {
+            if (this->owner_->isBoostCoolingDown())
+            {
+                //this->setBackgroundColour(ColourValue(0.7f, 0.2f, 0.2f));
+                if (this->flashDt_ <= 0.0f)
+                {
+                    this->flashDt_ = this->flashInterval_;
+                    this->setVisible(!this->isVisible());
+                }
+                else
+                    this->flashDt_ -= dt;
+            }
+            else
+            {
+                this->flashDt_ = 0.0f;
+                this->show();
+                //this->setBackgroundColour(ColourValue(0.2f, 0.7f, 0.2f));
+            }
+
+            float value = this->owner_->getBoostPower() / this->owner_->getInitialBoostPower();
+            this->setValue(value);
+        }
+    }
+
+    void HUDBoostBar::changedOwner()
+    {
+        SUPER(HUDBoostBar, changedOwner);
+
+        this->owner_ = orxonox_cast<SpaceShip*>(this->getOwner());
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBoostBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBoostBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDBoostBar.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDBoostBar_H__
+#define _HUDBoostBar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "HUDBar.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDBoostBar : public HUDBar, public Tickable
+    {
+    public:
+        HUDBoostBar(Context* context);
+        virtual ~HUDBoostBar();
+
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+
+    private:
+        SpaceShip*  owner_;
+        float       flashInterval_;
+        float       flashDt_;
+    };
+}
+#endif /* _HUDBoostBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyHealthBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyHealthBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyHealthBar.cc	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Matthias Spalinger
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "HUDEnemyHealthBar.h"
+
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDEnemyHealthBar);
+
+    HUDEnemyHealthBar::HUDEnemyHealthBar(Context* context) : HUDHealthBar(context)
+    {
+        RegisterObject(HUDEnemyHealthBar);
+
+        this->setConfigValues();
+        this->owner_ = nullptr;
+    }
+
+    HUDEnemyHealthBar::~HUDEnemyHealthBar()
+    {
+    }
+
+    void HUDEnemyHealthBar::setConfigValues()
+    {
+        SetConfigValue(useEnemyBar_, true);
+    }
+
+    void HUDEnemyHealthBar::tick(float dt)
+    {
+        this->updateTarget();
+
+        SUPER(HUDEnemyHealthBar, tick, dt);
+    }
+
+    void HUDEnemyHealthBar::updateTarget()
+    {
+        Pawn* pawn = nullptr;
+        if (this->owner_ && this->useEnemyBar_)
+        {
+            // Get the owner's current target (target is usually a Model)
+            WorldEntity* target = this->owner_->getTarget();
+            // Find the Pawn that belongs to this target (if any)
+            while (target && !target->isA(Class(Pawn)))
+                target = target->getParent();
+            pawn = orxonox_cast<Pawn*>(target);
+            // Don't show the HealthBar if the pawn is invisible
+            if (pawn && !pawn->isVisible())
+                pawn = nullptr;
+        }
+        // Set the pawn as owner of the HealthBar
+        this->setHealthBarOwner(pawn);
+        this->setVisible(pawn != nullptr);
+    }
+
+    void HUDEnemyHealthBar::changedOwner()
+    {
+        SUPER(HUDEnemyHealthBar, changedOwner);
+
+        this->owner_ = orxonox_cast<ControllableEntity*>(this->getOwner());
+        this->updateTarget();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyHealthBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyHealthBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyHealthBar.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Matthias Spalinger
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#ifndef _HUDEnemyHealthBar_H__
+#define _HUDEnemyHealthBar_H__
+
+#include "HUDHealthBar.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDEnemyHealthBar : public HUDHealthBar
+    {
+        public:
+            HUDEnemyHealthBar(Context* context);
+            virtual ~HUDEnemyHealthBar();
+
+            void setConfigValues();
+            virtual void tick(float dt) override;
+
+            virtual void changedOwner() override;
+
+        private:
+            void updateTarget();
+
+            ControllableEntity* owner_;
+            bool useEnemyBar_;
+    };
+}
+#endif /* _HUDEnemyHealthBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyShieldBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyShieldBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyShieldBar.cc	(revision 11817)
@@ -0,0 +1,89 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDEnemyShieldBar.h"
+
+#include "core/config/ConfigValueIncludes.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDEnemyShieldBar);
+
+    HUDEnemyShieldBar::HUDEnemyShieldBar(Context* context) : HUDShieldBar(context)
+    {
+        RegisterObject(HUDEnemyShieldBar);
+
+        this->setConfigValues();
+        this->owner_ = nullptr;
+    }
+
+    HUDEnemyShieldBar::~HUDEnemyShieldBar()
+    {
+    }
+
+    void HUDEnemyShieldBar::setConfigValues()
+    {
+        SetConfigValue(useEnemyBar_, true);
+    }
+
+    void HUDEnemyShieldBar::tick(float dt)
+    {
+        this->updateTarget();
+
+        SUPER(HUDEnemyShieldBar, tick, dt);
+    }
+
+    void HUDEnemyShieldBar::updateTarget()
+    {
+        Pawn* pawn = nullptr;
+        if (this->owner_ && this->useEnemyBar_)
+        {
+            // Get the owner's current target (target is usually a Model)
+            WorldEntity* target = this->owner_->getTarget();
+            // Find the Pawn that belongs to this target (if any)
+            while (target && !target->isA(Class(Pawn)))
+                target = target->getParent();
+            pawn = orxonox_cast<Pawn*>(target);
+            // Don't show the EnemyShieldBar if the pawn is invisible
+            if (pawn && !pawn->isVisible())
+                pawn = nullptr;
+        }
+        // Set the pawn as owner of the EnemyShieldBar
+        this->setShieldBarOwner(pawn);
+        this->setVisible(pawn != nullptr);
+    }
+
+    void HUDEnemyShieldBar::changedOwner()
+    {
+        SUPER(HUDEnemyShieldBar, changedOwner);
+
+        this->owner_ = orxonox_cast<ControllableEntity*>(this->getOwner());
+        this->updateTarget();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyShieldBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyShieldBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDEnemyShieldBar.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDEnemyShieldBar_H__
+#define _HUDEnemyShieldBar_H__
+
+#include "HUDShieldBar.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        This class displays the shield status of the target enemy of it's owner.
+    */
+    class _OverlaysExport HUDEnemyShieldBar : public HUDShieldBar
+    {
+        public:
+            HUDEnemyShieldBar(Context* context);
+            virtual ~HUDEnemyShieldBar();
+
+            void setConfigValues();
+            virtual void tick(float dt) override;
+
+            virtual void changedOwner() override;
+
+        private:
+            void updateTarget();
+
+            ControllableEntity* owner_;
+            bool useEnemyBar_;
+    };
+}
+#endif /* _HUDEnemyShieldBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDHealthBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDHealthBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDHealthBar.cc	(revision 11817)
@@ -0,0 +1,166 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDHealthBar.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "worldentities/pawns/Pawn.h"
+#include "overlays/OverlayGroup.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDHealthBar);
+
+    HUDHealthBar::HUDHealthBar(Context* context) : HUDBar(context)
+    {
+        RegisterObject(HUDHealthBar);
+
+        this->owner_ = nullptr;
+        this->bUseBarColour_ = false;
+        this->textOffset_ = Vector2(0.0f, 0.0f);
+        this->textScale_ = 1.0f;
+
+        this->setIconPosition(Vector2(0.05f,0.5f));
+        this->setIconDimensions(Vector2(0.1f,0.5f));
+
+        this->textoverlay_ = new OverlayText(this->getContext());
+
+        assert(this->textoverlay_.get());
+
+        this->textoverlay_->setCaption("");
+        this->textoverlay_->setAspectCorrection(false);
+
+        positionText();
+    }
+
+    HUDHealthBar::~HUDHealthBar()
+    {
+        if (this->isInitialized())
+        {
+            this->textoverlay_->destroy();
+            this->textoverlay_ = nullptr;
+        }
+    }
+
+    void HUDHealthBar::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HUDHealthBar, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HUDHealthBar, "showtext",          setTextVisible,          getTextVisible,          xmlelement, mode).defaultValues(true);
+        XMLPortParam(HUDHealthBar, "textfont",          setTextFont,             getTextFont,             xmlelement, mode).defaultValues("Monofur");
+        XMLPortParam(HUDHealthBar, "textusebarcolour",  setTextUseBarColour,     getTextUseBarColour,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(HUDHealthBar, "textcolour",        setTextColour,           getTextColour,           xmlelement, mode).defaultValues(ColourValue(1.0, 1.0, 1.0, 1.0));
+        XMLPortParam(HUDHealthBar, "textalign",         setTextAlignmentString,  getTextAlignmentString,  xmlelement, mode).defaultValues("left");
+        XMLPortParam(HUDHealthBar, "textoffset",        setTextOffset,           getTextOffset,           xmlelement, mode).defaultValues(Vector2::ZERO);
+        XMLPortParam(HUDHealthBar, "textscale",         setTextScale,            getTextScale,            xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(HUDHealthBar, "textpickpoint",     setTextPickPoint,        getTextPickPoint,        xmlelement, mode).defaultValues(Vector2::ZERO);
+        XMLPortParam(HUDHealthBar, "textrotation",      setTextRotation,         getTextRotation,         xmlelement, mode).defaultValues(0.0f);
+        XMLPortParam(HUDHealthBar, "textspacewidth",    setTextSpaceWidth,       getTextSpaceWidth,       xmlelement, mode).defaultValues(true);
+    }
+
+    void HUDHealthBar::tick(float dt)
+    {
+        SUPER(HUDHealthBar, tick, dt);
+
+        if (this->owner_)
+        {
+            this->setValue(this->owner_->getHealth() / this->owner_->getInitialHealth());
+            this->textoverlay_->setCaption(multi_cast<std::string>(static_cast<int>(this->owner_->getHealth())));
+        }
+        else
+        {
+            this->setValue(0);
+            this->textoverlay_->setCaption("0");
+        }
+
+        if (this->bUseBarColour_)
+            this->textoverlay_->setColour(this->getCurrentBarColour());
+    }
+
+    void HUDHealthBar::changedOwner()
+    {
+        SUPER(HUDHealthBar, changedOwner);
+
+        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());
+    }
+
+    void HUDHealthBar::changedOverlayGroup()
+    {
+        SUPER(HUDHealthBar, changedOverlayGroup);
+
+        this->getOverlayGroup()->addElement(this->textoverlay_.get());
+    }
+
+    void HUDHealthBar::changedVisibility()
+    {
+        SUPER(HUDHealthBar, changedVisibility);
+
+        this->textoverlay_->setVisible(this->isVisible());
+    }
+
+    void HUDHealthBar::changedName()
+    {
+        SUPER(HUDHealthBar, changedName);
+
+        this->textoverlay_->setName(this->getName() + "text");
+    }
+
+    void HUDHealthBar::setTextColour(const ColourValue& colour)
+    {
+        this->textColour_ = colour;
+        if (!this->bUseBarColour_)
+            this->textoverlay_->setColour(colour);
+    }
+
+    void HUDHealthBar::setTextUseBarColour(bool bUseBarColour)
+    {
+        this->bUseBarColour_ = bUseBarColour;
+        if (!bUseBarColour)
+            this->textoverlay_->setColour(this->textColour_);
+    }
+
+    void HUDHealthBar::positionText()
+    {
+        this->textoverlay_->setPosition(this->getPosition() + this->textOffset_*this->getActualSize());
+        this->textoverlay_->setTextSize(this->getActualSize().y*this->textScale_);
+    }
+
+    void HUDHealthBar::positionChanged()
+    {
+        HUDBar::positionChanged();
+        positionText();
+    }
+
+    void HUDHealthBar::sizeChanged()
+    {
+        HUDBar::sizeChanged();
+        positionText();
+    }    
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDHealthBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDHealthBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDHealthBar.h	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDHealthBar_H__
+#define _HUDHealthBar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "util/Math.h"
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+#include "HUDBar.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDHealthBar : public HUDBar, public Tickable
+    {
+        public:
+            HUDHealthBar(Context* context);
+            virtual ~HUDHealthBar();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+            virtual void changedOwner() override;
+            virtual void changedOverlayGroup() override;
+            virtual void changedVisibility() override;
+            virtual void changedName() override;
+
+            inline void setTextFont(const std::string& font)
+                { if (!font.empty()) { this->textoverlay_->setFont(font); } }
+            inline const std::string& getTextFont() const
+                { return this->textoverlay_->getFont(); }
+
+            void setTextColour(const ColourValue& colour);
+            inline const ColourValue& getTextColour() const
+                { return this->textoverlay_->getColour(); }
+
+            void setTextUseBarColour(bool bUseBarColour);
+            inline bool getTextUseBarColour() const
+                { return this->bUseBarColour_; }
+
+            inline void setTextAlignment(OverlayText::Alignment alignment)
+                { this->textoverlay_->setAlignment(alignment); }
+            inline OverlayText::Alignment getTextAlignment() const
+                { return this->textoverlay_->getAlignment(); }
+
+            void setTextAlignmentString(const std::string& alignment)
+                { this->textoverlay_->setAlignmentString(alignment); }
+            std::string getTextAlignmentString() const
+                { return this->textoverlay_->getAlignmentString(); }
+
+            inline void setTextVisible(bool bVisible)
+                { this->textoverlay_->setVisible(bVisible); }
+            inline bool getTextVisible() const
+                { return this->textoverlay_->isVisible(); }
+
+            inline void setTextScale(float scale)
+                { this->textScale_ = scale;
+                  positionText();
+                }
+            inline float getTextScale() const
+                { return this->textScale_; }
+
+            inline void setTextPickPoint(const Vector2& pickpoint)
+                { this->textoverlay_->setPickPoint(pickpoint); }
+            inline Vector2 getTextPickPoint() const
+                { return this->textoverlay_->getPickPoint(); }
+
+            inline void setTextOffset(const Vector2& position)
+                { this->textOffset_ = position;
+                  this->positionText();
+                }
+            inline Vector2 getTextOffset() const
+                { return this->textOffset_; }
+
+            inline void setTextRotation(const Degree& angle)
+                { this->textoverlay_->setRotation(angle); }
+            inline const Degree& getTextRotation() const
+                { return this->textoverlay_->getRotation(); }
+
+            inline void setTextSpaceWidth(float width)
+                { this->textoverlay_->setSpaceWidth(width); }
+            inline float getTextSpaceWidth() const
+                { return this->textoverlay_->getSpaceWidth(); }
+
+            inline void setHealthBarOwner(Pawn* owner)
+                { this->owner_ = owner; }
+        protected:
+            virtual void positionChanged() override;
+            virtual void sizeChanged() override;
+        private:
+            void positionText();
+            WeakPtr<Pawn> owner_;
+            StrongPtr<OverlayText> textoverlay_;
+            bool bUseBarColour_;
+            ColourValue textColour_;
+            Vector2 textOffset_;
+            float textScale_;
+    };
+}
+#endif /* _HUDHealthBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDNavigation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDNavigation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDNavigation.cc	(revision 11817)
@@ -0,0 +1,696 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Reto Grieder
+ *      Oliver Scheuss
+ *      Matthias Spalinger
+ *
+ */
+
+#include "HUDNavigation.h"
+
+#include <OgreCamera.h>
+#include <OgreFontManager.h>
+#include <OgreOverlayManager.h>
+#include <OgreTextAreaOverlayElement.h>
+#include <OgrePanelOverlayElement.h>
+
+#include <typeinfo>
+
+#include "util/Math.h"
+#include "util/Convert.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "CameraManager.h"
+#include "Scene.h"
+#include "Radar.h"
+#include "graphics/Camera.h"
+#include "controllers/HumanController.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/WorldEntity.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "tools/TextureGenerator.h"
+
+
+namespace orxonox
+{
+
+    SetConsoleCommand("HUDNavigation","selectClosest", &HUDNavigation::selectClosestTarget).addShortcut().keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("HUDNavigation","selectNext", &HUDNavigation::selectNextTarget).addShortcut().keybindMode(KeybindMode::OnPress);
+
+    static bool compareDistance(std::pair<RadarViewable*, unsigned int> a,
+            std::pair<RadarViewable*, unsigned int> b)
+    {
+        return a.second < b.second;
+    }
+    RegisterClass ( HUDNavigation );
+
+    HUDNavigation* HUDNavigation::localHUD_s = nullptr;
+
+    HUDNavigation::HUDNavigation(Context* context) :
+        OrxonoxOverlay(context)
+    {
+        RegisterObject(HUDNavigation);
+        this->setConfigValues();
+
+        // Set default values
+        this->setFont("Monofur");
+        this->setTextSize(0.05f);
+        this->setNavMarkerSize(0.03f);
+        this->setAimMarkerSize(0.02f);
+        this->setHealthMarkerSize(0.06f);
+        this->setHealthLevelMarkerSize(0.06f);
+
+        this->setDetectionLimit(10000.0f);
+        this->currentMunitionSpeed_ = 750.0f;
+
+        this->closestTarget_ = true;
+        this->nextTarget_ = false;
+        HUDNavigation::localHUD_s = this;
+    }
+
+    HUDNavigation::~HUDNavigation()
+    {
+        if (this->isInitialized())
+        {
+            for (std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.begin(); it != this->activeObjectList_.end();)
+            removeObject((it++)->first);
+        }
+        this->sortedObjectList_.clear();
+    }
+
+    void HUDNavigation::setConfigValues()
+    {
+        SetConfigValue(markerLimit_, 3);
+        SetConfigValue(showDistance_, false);
+    }
+
+    void HUDNavigation::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HUDNavigation, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HUDNavigation, "font", setFont, getFont, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "textSize", setTextSize, getTextSize, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "navMarkerSize", setNavMarkerSize, getNavMarkerSize, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "aimMarkerSize", setAimMarkerSize, getAimMarkerSize, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "healthMarkerSize", setHealthMarkerSize, getHealthMarkerSize, xmlelement, mode);
+        XMLPortParam(HUDNavigation, "healthLevelMarkerSize", setHealthLevelMarkerSize, getHealthLevelMarkerSize, xmlelement, mode);
+
+    }
+
+    void HUDNavigation::setFont(const std::string& font)
+    {
+        const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font);
+        if (fontPtr.isNull())
+        {
+            orxout(internal_warning) << "HUDNavigation: Font '" << font << "' not found" << endl;
+            return;
+        }
+        this->fontName_ = font;
+        for (const auto& mapEntry : this->activeObjectList_)
+        {
+            if (mapEntry.second.text_ != nullptr)
+                mapEntry.second.text_->setFontName(this->fontName_);
+        }
+    }
+
+    const std::string& HUDNavigation::getFont() const
+    {
+        return this->fontName_;
+    }
+
+    void HUDNavigation::setTextSize(float size)
+    {
+        if (size <= 0.0f)
+        {
+            orxout(internal_warning) << "HUDNavigation: Negative font size not allowed" << endl;
+            return;
+        }
+        this->textSize_ = size;
+        for (const auto& mapEntry : this->activeObjectList_)
+        {
+            if (mapEntry.second.text_)
+                mapEntry.second.text_->setCharHeight(size);
+        }
+    }
+
+    float HUDNavigation::getTextSize() const
+    {
+        return this->textSize_;
+    }
+
+    float HUDNavigation::getArrowSizeX(int dist) const
+    {
+        if (dist < 600)
+        dist = 600;
+        return this->getActualSize().x * 900 * this->navMarkerSize_ / dist;
+    }
+
+    float HUDNavigation::getArrowSizeY(int dist) const
+    {
+        if (dist < 600)
+        dist = 600;
+        return this->getActualSize().y * 900 * this->navMarkerSize_ / dist;
+    }
+
+    void HUDNavigation::tick(float dt)
+    {
+        SUPER(HUDNavigation, tick, dt);
+
+        Camera* cam = CameraManager::getInstance().getActiveCamera();
+        if (cam == nullptr)
+        return;
+        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
+
+        for (std::pair<RadarViewable*, unsigned int>& pair : this->sortedObjectList_)
+        pair.second = (int)((pair.first->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f);
+
+        this->sortedObjectList_.sort(compareDistance);
+
+        unsigned int markerCount = 0;
+        bool closeEnough = false; // only display objects that are close enough to be relevant for the player
+
+        // if the selected object doesn't exist any more or is now out of range select the closest object
+        std::map<RadarViewable*, ObjectInfo>::iterator selectedActiveObject = this->activeObjectList_.find(this->selectedTarget_);
+        if(selectedActiveObject == this->activeObjectList_.end())
+        {
+            this->closestTarget_ = true;
+        }
+        else if(this->detectionLimit_ < (this->selectedTarget_->getRVWorldPosition() - HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition()).length() + 0.5f)
+        {
+            this->closestTarget_ = true;
+            selectedActiveObject->second.selected_ = false;
+        }
+
+        bool nextHasToBeSelected = false;
+
+        for (std::list<std::pair<RadarViewable*, unsigned int>>::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++markerCount, ++listIt)
+        {
+
+            std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(listIt->first);
+            closeEnough = listIt->second < this->detectionLimit_;
+            // display radarviewables on HUD if the marker limit and max-distance is not exceeded
+            if (markerCount < this->markerLimit_ && (closeEnough || this->detectionLimit_ < 0))
+            {
+                // Get Distance to HumanController and save it in the TextAreaOverlayElement.
+                int dist = listIt->second;
+                float textLength = 0.0f;
+
+                if (this->showDistance_)
+                {
+                    //display distance next to cursor
+                    it->second.text_->setCaption(multi_cast<std::string>(dist));
+                    textLength = multi_cast<std::string>(dist).size() * it->second.text_->getCharHeight() * 0.3f;
+                }
+                else
+                {
+                    //display name next to cursor
+                    it->second.text_->setCaption(it->first->getRadarName());
+                    textLength = it->first->getRadarName().size() * it->second.text_->getCharHeight() * 0.3f;
+                }
+
+                // select the object that aim-assistant indicates
+                if(this->closestTarget_)
+                // select the closest object
+                {
+                    if(listIt == this->sortedObjectList_.begin())
+                    {
+                        it->second.selected_ = true;
+                        this->selectedTarget_ = it->first;
+                    }
+                    else if(it->second.selected_)
+                    {
+                        it->second.selected_ = false;
+                    }
+
+                }
+                else if(this->nextTarget_)
+                // select the next object in sortedObjectList
+                {
+                    if(nextHasToBeSelected){
+                        it->second.selected_ = true;
+                        this->selectedTarget_ = it->first;
+                        nextHasToBeSelected = false;
+                    }
+                    else if(it->second.selected_)
+                    {
+                        nextHasToBeSelected = true;
+                        it->second.selected_ = false;
+
+                        // check if there's a next object
+                        listIt++;
+                        if(listIt != this->sortedObjectList_.end())
+                        {
+                            // and if the marker limit and max-distance are not exceeded for it
+                            if (markerCount + 1 >= this->markerLimit_ ||
+                                    (listIt->second > this->detectionLimit_ && detectionLimit_ >= 0))
+                            {
+                                // otherwise select the closest object
+                                this->activeObjectList_.find(this->sortedObjectList_.begin()->first)->second.selected_ = true;
+                                this->selectedTarget_ = it->first;
+                                nextHasToBeSelected = false;
+                            }
+                        }
+                        listIt--;
+                    }
+                }
+
+
+
+
+                // Transform to screen coordinates
+                Vector3 pos = camTransform * it->first->getRVWorldPosition();
+
+                bool outOfView = true;
+                if (pos.z > 1.0)
+                {
+                    // z > 1.0 means that the object is behind the camera
+                    outOfView = true;
+                    // we have to switch all coordinates (if you don't know why,
+                    // try linear algebra lectures, because I can't explain..)
+                    pos.x = -pos.x;
+                    pos.y = -pos.y;
+                }
+                else
+                    outOfView = pos.x < -1.0 || pos.x > 1.0 || pos.y < -1.0 || pos.y > 1.0;
+
+                if (outOfView)
+                {
+                    // Object is not in view
+
+                    // Change material only if outOfView changed
+                    if (!it->second.wasOutOfView_)
+                    {
+                        it->second.health_->hide();
+                        it->second.healthLevel_->hide();
+                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("arrows.png", it->first->getRadarObjectColour()));
+                        it->second.wasOutOfView_ = true;
+                        it->second.target_->hide();
+                    }
+
+                    //float xDistScale = this->getActualSize().x * 1000.0f * this->navMarkerSize_ / dist;
+                    //float yDistScale = this->getActualSize().y * 1000.0f * this->navMarkerSize_ / dist;
+
+                    // Adjust Arrowsize according to distance
+                    it->second.panel_->setDimensions(getArrowSizeX(dist), getArrowSizeY(dist));
+
+                    // Switch between top, bottom, left and right position of the arrow at the screen border
+                    if (pos.x < pos.y)
+                    {
+                        if (pos.y > -pos.x)
+                        {
+                            // Top
+                            float position = pos.x / pos.y + 1.0f;
+                            it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 0.0f);
+                            it->second.panel_->setUV(0.5f, 0.0f, 1.0f, 0.5f);
+                            it->second.text_->setLeft((position - textLength) * 0.5f);
+                            it->second.text_->setTop(it->second.panel_->getHeight());
+                        }
+                        else
+                        {
+                            // Left
+                            float position = pos.y / pos.x + 1.0f;
+                            it->second.panel_->setPosition(0.0f, (position - it->second.panel_->getWidth()) * 0.5f);
+                            it->second.panel_->setUV(0.0f, 0.0f, 0.5f, 0.5f);
+                            it->second.text_->setLeft(it->second.panel_->getWidth() + 0.01f);
+                            it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
+                        }
+                    }
+                    else
+                    {
+                        if (pos.y < -pos.x)
+                        {
+                            // Bottom
+                            float position = -pos.x / pos.y + 1.0f;
+                            it->second.panel_->setPosition((position - it->second.panel_->getWidth()) * 0.5f, 1.0f - it->second.panel_->getHeight());
+                            it->second.panel_->setUV(0.0f, 0.5f, 0.5f, 1.0f );
+                            it->second.text_->setLeft((position - textLength) * 0.5f);
+                            it->second.text_->setTop(1.0f - it->second.panel_->getHeight() - it->second.text_->getCharHeight());
+                        }
+                        else
+                        {
+                            // Right
+                            float position = -pos.y / pos.x + 1.0f;
+                            it->second.panel_->setPosition(1.0f - it->second.panel_->getWidth(), (position - it->second.panel_->getHeight()) * 0.5f);
+                            it->second.panel_->setUV(0.5f, 0.5f, 1.0f, 1.0f);
+                            it->second.text_->setLeft(1.0f - it->second.panel_->getWidth() - textLength - 0.01f);
+                            it->second.text_->setTop((position - it->second.text_->getCharHeight()) * 0.5f);
+                        }
+                    }
+                }
+                else
+                {
+                    // Object is in view
+
+                    //calculate the health of the actual selected radarViewable (relativHealthScale: while (0) is no health left, (1) is the initial health)
+                    const Pawn* pawnPtr = orxonox_cast<const Pawn*>(it->first->getWorldEntity());
+                    if (pawnPtr)
+                    {
+                        float health = pawnPtr->getHealth();
+                        float initHealth = pawnPtr->getMaxHealth();
+                        float relativHealthScale = health/initHealth;
+
+                        //integer values from 0 to 10 (0 is no health and 10 is full health)
+                        int discreteHealthScale = (int)(10*relativHealthScale);
+
+                        //calculate the HealthLevel (= OponentLevel or Strength) there are 5 Levels
+                        //Level 1, Level 2,... , Level 5
+                        int HealthLevel = 1;
+
+                        if(initHealth < 200)
+                            HealthLevel = 1;
+                        if(200 <= initHealth && initHealth < 500)
+                            HealthLevel = 2;
+                        if(500 <= initHealth && initHealth < 1000)
+                            HealthLevel = 3;
+                        if(1000 <= initHealth && initHealth < 2500)
+                            HealthLevel = 4;
+                        if(2500 <= initHealth)
+                            HealthLevel = 5;
+
+                        // Change material only if outOfView changed
+                        if (it->second.wasOutOfView_)
+                        {
+                            //it->second.health_->setMaterialName(TextureGenerator::getMaterialName("bar2_1.png", it->first->getRadarObjectColour()));
+                            it->second.health_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
+                            it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x , 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
+
+                            // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the
+                            // spaceship is still intact there should be at least one part of the bar left.
+                            if(1<=discreteHealthScale){
+                                it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
+                                it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
+                            }
+
+                            //healthLevel
+                            it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
+                            it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x , 0.75f*this->healthLevelMarkerSize_ * this->getActualSize().y);
+                            it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
+                            it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
+                        }
+
+                        // sets Position and Dimensions (amount) health
+                        it->second.health_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
+                        it->second.health_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
+                        it->second.health_->setTop((-pos.y + 1.04f - it->second.panel_->getHeight()) * 0.5f);
+
+                        // because as soon as relative health drops below 10% (0.1) the descrete value is 0 but as long as the
+                        // spaceship is still intact there should be at least one part of the bar left.
+                        if(1<=discreteHealthScale){
+                            it->second.health_->setTiling((float)discreteHealthScale , 1 ,0);
+                            it->second.health_->setDimensions(this->healthMarkerSize_ * this->getActualSize().x *0.1f*discreteHealthScale, 0.75f*this->healthMarkerSize_ * this->getActualSize().y);
+                        }
+
+                        //sets Position and Dimensions (level) of healthLevel
+                        it->second.healthLevel_->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", it->first->getRadarObjectColour()));
+                        it->second.healthLevel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
+                        it->second.healthLevel_->setLeft((pos.x + 0.975f - it->second.panel_->getWidth()) * 0.5f);
+                        it->second.healthLevel_->setTop((-pos.y + 1.125f - it->second.panel_->getHeight()) * 0.5f);
+
+                        it->second.healthLevel_->setTiling((float)HealthLevel , 1 ,0);
+                        it->second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * this->getActualSize().x *0.1f*HealthLevel, 0.25f*this->healthLevelMarkerSize_ * this->getActualSize().y);
+
+                        // Make sure the overlays are shown
+                        it->second.health_->show();
+                        it->second.healthLevel_->show();
+                    }
+
+
+                    // Change material only if outOfView changed
+                    if (it->second.wasOutOfView_)
+                    {
+                        //it->second.panel_->setMaterialName("Orxonox/NavTDC");
+                        it->second.panel_->setMaterialName(TextureGenerator::getMaterialName("tdc.png", it->first->getRadarObjectColour()));
+                        it->second.panel_->setDimensions(this->navMarkerSize_ * this->getActualSize().x, this->navMarkerSize_ * this->getActualSize().y);
+                        it->second.target_->setDimensions(this->aimMarkerSize_ * this->getActualSize().x, this->aimMarkerSize_ * this->getActualSize().y);
+                        it->second.wasOutOfView_ = false;
+                    }
+
+                    // Position marker
+                    it->second.panel_->setUV(0.0f, 0.0f, 1.0f, 1.0f);
+                    it->second.panel_->setLeft((pos.x + 1.0f - it->second.panel_->getWidth()) * 0.5f);
+                    it->second.panel_->setTop((-pos.y + 1.0f - it->second.panel_->getHeight()) * 0.5f);
+
+                    // Position text
+                    it->second.text_->setLeft((pos.x + 1.0f + it->second.panel_->getWidth()) * 0.5f);
+                    it->second.text_->setTop((-pos.y + 1.0f + it->second.panel_->getHeight()) * 0.5f);
+
+                    // Make sure the overlays are shown
+                    it->second.panel_->show();
+                    it->second.text_->show();
+
+                    // Target marker
+                    const Pawn* pawn = dynamic_cast<const Pawn*>(it->first->getWorldEntity());
+                    /* Pawn* humanPawn = HumanController::getLocalControllerEntityAsPawn();*/
+                    if(!it->second.selected_
+                            || it->first->getRVVelocity().squaredLength() == 0
+                            || pawn == nullptr
+                            /* TODO : improve getTeam in such a way that it works
+                             * || humanPawn == nullptr
+                             * || pawn->getTeam() == humanPawn->getTeam()*/)
+                    {
+                        // don't show marker for not selected enemies nor if the selected doesn't move
+                        it->second.target_->hide();
+                    }
+                    else // object is selected and moves
+                    {
+                        // get the aim position
+                        const Vector3& targetPos = this->toAimPosition(it->first);
+                        // Transform to screen coordinates
+                        Vector3 screenPos = camTransform * targetPos;
+                        // Check if the target marker is in view too
+                        if(screenPos.z > 1 || screenPos.x < -1.0 || screenPos.x > 1.0
+                                || screenPos.y < -1.0 || screenPos.y > 1.0)
+                        {
+                            it->second.target_->hide();
+                        }
+                        else
+                        {
+                            it->second.target_->setLeft((screenPos.x + 1.0f - it->second.target_->getWidth()) * 0.5f);
+                            it->second.target_->setTop((-screenPos.y + 1.0f - it->second.target_->getHeight()) * 0.5f);
+                            it->second.target_->show();
+                        }
+                    }
+
+                }
+            }
+            else // do not display on HUD
+
+            {
+                it->second.health_->hide();
+                it->second.healthLevel_->hide();
+                it->second.panel_->hide();
+                it->second.text_->hide();
+                it->second.target_->hide();
+            }
+        }
+
+        this->closestTarget_ = false;
+        this->nextTarget_ = false;
+    }
+
+    /** Overridden method of OrxonoxOverlay.
+     @details
+     Usually the entire overlay scales with scale().
+     Here we obviously have to adjust this.
+     */
+    void HUDNavigation::sizeChanged()
+    {
+        // Use size to compensate for aspect ratio if enabled.
+        float xScale = this->getActualSize().x;
+        float yScale = this->getActualSize().y;
+
+        for (const auto& mapEntry : this->activeObjectList_)
+        {
+            if (mapEntry.second.health_ != nullptr)
+                mapEntry.second.health_->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
+            if (mapEntry.second.healthLevel_ != nullptr)
+                mapEntry.second.healthLevel_->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
+            if (mapEntry.second.panel_ != nullptr)
+                mapEntry.second.panel_->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
+            if (mapEntry.second.text_ != nullptr)
+                mapEntry.second.text_->setCharHeight(this->textSize_ * yScale);
+            if (mapEntry.second.target_ != nullptr)
+                mapEntry.second.target_->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
+        }
+    }
+
+    void HUDNavigation::addObject(RadarViewable* object)
+    {
+        if (showObject(object) == false)
+        return;
+
+        if (this->activeObjectList_.size() >= this->markerLimit_)
+        if (object == nullptr)
+        return;
+
+        // Object hasn't been added yet (we know that)
+        assert(this->activeObjectList_.find(object) == this->activeObjectList_.end());
+
+        // Scales used for dimensions and text size
+        float xScale = this->getActualSize().x;
+        float yScale = this->getActualSize().y;
+
+        // Create everything needed to display the object on the radar and add it to the map
+
+        // Create health
+        Ogre::PanelOverlayElement* health = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthMarker_" + getUniqueNumberString()));
+        //panel->setMaterialName("Orxonox/NavTDC");
+        health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour()));
+        health->setDimensions(this->healthMarkerSize_ * xScale, this->healthMarkerSize_ * yScale);
+        //panel->setColour(object->getRadarObjectColour());
+
+        // Create healthLevel
+        Ogre::PanelOverlayElement* healthLevel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDNavigation_healthLevelMarker_" + getUniqueNumberString()));
+        //panel->setMaterialName("Orxonox/NavTDC");
+        health->setMaterialName(TextureGenerator::getMaterialName("barSquare.png", object->getRadarObjectColour()));
+        health->setDimensions(this->healthLevelMarkerSize_ * xScale, this->healthLevelMarkerSize_ * yScale);
+
+
+        // Create arrow/marker
+        Ogre::PanelOverlayElement* panel = static_cast<Ogre::PanelOverlayElement*>( Ogre::OverlayManager::getSingleton()
+                .createOverlayElement("Panel", "HUDNavigation_navMarker_" + getUniqueNumberString()));
+        //panel->setMaterialName("Orxonox/NavTDC");
+        panel->setMaterialName(TextureGenerator::getMaterialName("tdc.png", object->getRadarObjectColour()));
+        panel->setDimensions(this->navMarkerSize_ * xScale, this->navMarkerSize_ * yScale);
+        //panel->setColour(object->getRadarObjectColour());
+
+        // Create target marker
+        Ogre::PanelOverlayElement* target = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+                    .createOverlayElement("Panel", "HUDNavigation_targetMarker_" + getUniqueNumberString()));
+        target->setMaterialName(TextureGenerator::getMaterialName("target.png", object->getRadarObjectColour()));
+        target->setDimensions(this->aimMarkerSize_ * xScale, this->aimMarkerSize_ * yScale);
+
+        // Create text
+        Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>( Ogre::OverlayManager::getSingleton()
+                .createOverlayElement("TextArea", "HUDNavigation_navText_" + getUniqueNumberString()));
+        text->setFontName(this->fontName_);
+        text->setCharHeight(this->textSize_ * yScale);
+        text->setColour(object->getRadarObjectColour());
+
+        health->hide();
+        healthLevel->hide();
+        panel->hide();
+        target->hide();
+        text->hide();
+
+        ObjectInfo tempStruct =
+        {   health, healthLevel, panel, target, text, false, false, false};
+        this->activeObjectList_[object] = tempStruct;
+
+        this->background_->addChild(health);
+        this->background_->addChild(healthLevel);
+        this->background_->addChild(panel);
+        this->background_->addChild(target);
+        this->background_->addChild(text);
+
+        this->sortedObjectList_.push_front(std::make_pair(object, (unsigned int)0));
+    }
+
+    void HUDNavigation::removeObject(RadarViewable* viewable)
+    {
+        std::map<RadarViewable*, ObjectInfo>::iterator it = this->activeObjectList_.find(viewable);
+
+        if (this->activeObjectList_.find(viewable) != this->activeObjectList_.end())
+        {
+            // Detach overlays
+            this->background_->removeChild(it->second.health_->getName());
+            this->background_->removeChild(it->second.healthLevel_->getName());
+            this->background_->removeChild(it->second.panel_->getName());
+            this->background_->removeChild(it->second.target_->getName());
+            this->background_->removeChild(it->second.text_->getName());
+            // Properly destroy the overlay elements (do not use delete!)
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.health_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.healthLevel_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.panel_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.target_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second.text_);
+            // Remove from the list
+            this->activeObjectList_.erase(viewable);
+        }
+
+        for (std::list<std::pair<RadarViewable*, unsigned int>>::iterator listIt = this->sortedObjectList_.begin(); listIt != this->sortedObjectList_.end(); ++listIt)
+        {
+            if ((listIt->first) == viewable)
+            {
+                this->sortedObjectList_.erase(listIt);
+                break;
+            }
+        }
+    }
+
+    void HUDNavigation::objectChanged(RadarViewable* viewable)
+    {
+        // TODO: niceification neccessary ;)
+        removeObject(viewable);
+        addObject(viewable);
+    }
+
+    bool HUDNavigation::showObject(RadarViewable* rv)
+    {
+        if (rv == orxonox_cast<RadarViewable*>(this->getOwner()))
+        return false;
+        assert(rv->getWorldEntity());
+        if (rv->getWorldEntity()->isVisible() == false || rv->getRadarVisibility() == false)
+        return false;
+        return true;
+    }
+
+    void HUDNavigation::changedOwner()
+    {
+        const std::set<RadarViewable*>& respawnObjects = this->getOwner()->getScene()->getRadar()->getRadarObjects();
+        for (RadarViewable* respawnObject : respawnObjects)
+        {
+            if (!respawnObject->isHumanShip_)
+            this->addObject(respawnObject);
+        }
+    }
+
+    Vector3 HUDNavigation::toAimPosition(RadarViewable* target) const
+    {
+        Vector3 wePosition = HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition();
+        Vector3 targetPosition = target->getRVWorldPosition();
+        Vector3 targetSpeed = target->getRVVelocity();
+
+        return getPredictedPosition(wePosition, this->currentMunitionSpeed_, targetPosition, targetSpeed);
+    }
+
+    void HUDNavigation::selectClosestTarget()
+    {
+        if(HUDNavigation::localHUD_s)
+        {
+            HUDNavigation::localHUD_s->closestTarget_ = true;
+        }
+    }
+
+    void HUDNavigation::selectNextTarget()
+    {
+        if(HUDNavigation::localHUD_s)
+        {
+            HUDNavigation::localHUD_s->nextTarget_ = true;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDNavigation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDNavigation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDNavigation.h	(revision 11817)
@@ -0,0 +1,168 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Reto Grieder
+ *      Matthias Spalinger
+ *
+ */
+
+#ifndef _HUDNavigation_H__
+#define _HUDNavigation_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <string>
+
+#include "util/OgreForwardRefs.h"
+#include "tools/interfaces/Tickable.h"
+#include "interfaces/RadarListener.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDNavigation : public OrxonoxOverlay, public Tickable, public RadarListener
+    {
+        public:
+            HUDNavigation(Context* context);
+            virtual ~HUDNavigation();
+
+            void setConfigValues();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+            // RadarListener interface
+            virtual void addObject(RadarViewable* object) override;
+            virtual void removeObject(RadarViewable* viewable) override;
+            virtual void objectChanged(RadarViewable* viewable) override;
+
+            virtual void changedOwner() override;
+            virtual void sizeChanged() override;
+            virtual void angleChanged() override { }
+            virtual void positionChanged() override { }
+            virtual void radarTick(float dt) override {}
+
+            virtual inline float getRadarSensitivity() const override
+                { return 1.0f; }
+
+            inline unsigned int getMarkerLimit() const
+                { return this->markerLimit_; }
+
+            static void selectClosestTarget();
+            static void selectNextTarget();
+
+        private:
+            struct ObjectInfo
+            {
+
+
+
+                Ogre::PanelOverlayElement* health_;
+                Ogre::PanelOverlayElement* healthLevel_;
+                Ogre::PanelOverlayElement* panel_;
+                Ogre::PanelOverlayElement* target_;
+                Ogre::TextAreaOverlayElement* text_;
+                bool outOfView_;
+                bool wasOutOfView_;
+                bool selected_;
+            };
+
+            bool showObject(RadarViewable* rv);
+
+            // XMLPort accessors
+            inline void setHealthMarkerSize(float size)
+                        {
+                            this->healthMarkerSize_ = size;
+                            this->sizeChanged();
+                        }
+            inline float getHealthMarkerSize() const
+                            { return healthMarkerSize_; }
+
+            inline void setHealthLevelMarkerSize(float size)
+                                    {
+                                        this->healthLevelMarkerSize_ = size;
+                                        this->sizeChanged();
+                                    }
+                        inline float getHealthLevelMarkerSize() const
+                                        { return healthLevelMarkerSize_; }
+
+            inline void setNavMarkerSize(float size)
+            {
+                this->navMarkerSize_ = size;
+                this->sizeChanged();
+            }
+            inline float getNavMarkerSize() const
+                { return navMarkerSize_; }
+            inline void setAimMarkerSize(float size)
+            {
+                this->aimMarkerSize_ = size;
+                this->sizeChanged();
+            }
+
+            inline float getAimMarkerSize() const
+                { return aimMarkerSize_; }
+            inline void setDetectionLimit(float limit)
+                { this->detectionLimit_ = limit; }
+            inline float getDetectionLimit() const
+                { return this->detectionLimit_; }
+
+            void setTextSize(float size);
+            float getTextSize() const;
+
+            void setFont(const std::string& font);
+            const std::string& getFont() const;
+
+            float getArrowSizeX(int dist) const;
+            float getArrowSizeY(int dist) const;
+
+            Vector3 toAimPosition(RadarViewable* target) const;
+
+            std::map<RadarViewable*, ObjectInfo> activeObjectList_;
+            std::list<std::pair<RadarViewable*, unsigned int>> sortedObjectList_;
+
+            float healthMarkerSize_;
+            float healthLevelMarkerSize_;
+            float navMarkerSize_;
+            float aimMarkerSize_;
+            std::string fontName_;
+            float textSize_;
+            bool showDistance_;
+
+            RadarViewable* selectedTarget_;
+
+            bool closestTarget_;
+            bool nextTarget_;
+
+            static HUDNavigation* localHUD_s; //!< This is used as a filter. Only the local HUD should be influenced by the static Console Command functions.
+
+
+            float currentMunitionSpeed_;
+
+            unsigned int markerLimit_;
+            float detectionLimit_; //!< Objects that are more far away than detectionLimit_ are not displayed on the HUD. 10000.0f is the default value.
+    };
+}
+
+#endif /* _HUDNavigation_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDPickupSystem.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDPickupSystem.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDPickupSystem.cc	(revision 11817)
@@ -0,0 +1,136 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Patrick Wintermeyer
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <vector>
+#include <string>
+
+#include <OgreOverlayManager.h>
+#include <OgreOverlayElement.h>
+#include <OgrePanelOverlayElement.h>
+
+#include "HUDPickupSystem.h"
+
+#include "core/CoreIncludes.h"
+#include "core/class/Super.h"
+#include "util/Convert.h"
+#include "pickup/PickupManager.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDPickupSystem);
+
+    HUDPickupSystem::HUDPickupSystem(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(HUDPickupSystem);
+
+        const float offsetX = 0.02f;
+        const float offsetY = 0.05f;
+        const float x = 0.2;
+        const float y = 0.5f;
+
+        for (int index = 0; index < 10; ++index)
+        {
+            int row = index / 5;
+            int column = index % 5;
+
+            std::string name = "HUDPickupItem" + multi_cast<std::string>(index);
+            Ogre::OverlayElement* item = Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", name);
+
+            item->setDimensions(0.16, 0.4);
+            item->setPosition(offsetX + column*x, offsetY + row*y);
+            this->items_.push_back(item);
+        }
+    }
+
+    HUDPickupSystem::~HUDPickupSystem()
+    {
+        for (Ogre::OverlayElement* item : items_)
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(item);
+    }
+
+    void HUDPickupSystem::changedOwner()
+    {
+        SUPER(HUDPickupSystem, changedOwner);
+
+        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());
+    }
+
+    void HUDPickupSystem::tick(float dt)
+    {
+        SUPER(HUDPickupSystem, tick, dt);
+
+        std::vector<const PickupInventoryContainer*> containers = this->getPickupsForOwner();
+
+        for (size_t index = 0; index < this->items_.size(); ++index)
+        {
+            Ogre::OverlayElement* item = this->items_[index];
+
+            if (index < containers.size())
+            {
+                item->setMaterialName(this->getIcon(containers[index]->representationName));
+                if (!item->getParent())
+                    this->background_->addChild(item);
+            }
+            else
+            {
+                if (item->getParent())
+                    this->background_->removeChild(item->getName());
+            }
+        }
+    }
+
+    std::vector<const PickupInventoryContainer*> HUDPickupSystem::getPickupsForOwner() const
+    {
+        std::vector<const PickupInventoryContainer*> containers;
+
+        int numPickups = PickupManager::getInstance().getNumPickups();
+        for (int i = 0; i < numPickups; ++i)
+        {
+            const PickupInventoryContainer* container = PickupManager::getInstance().popPickup();
+            if (this->owner_ && this->owner_->getObjectID() == container->carrierPawnId)
+                containers.push_back(container);
+        }
+
+        return containers;
+    }
+
+    std::string HUDPickupSystem::getIcon(const std::string& repName) const
+    {
+        if(repName.find("invisible", 0)!=std::string::npos) return "Eye";
+        else if(repName.find("tri", 0)!=std::string::npos) return "Asterisk";
+        else if(repName.find("health", 0)!=std::string::npos || repName.find("Health", 0)!=std::string::npos) return "Cross";
+        else if(repName.find("shield", 0)!=std::string::npos) return "Shield";
+        else if(repName.find("munition", 0)!=std::string::npos) return "Munition";
+        else if(repName.find("shrink", 0)!=std::string::npos) return "Shrink";
+        else if(repName.find("boost", 0)!=std::string::npos) return "Flash";
+        else if(repName.find("speed", 0)!=std::string::npos) return "3arrowsup";
+        else if(repName.find("drone", 0)!=std::string::npos) return "Damage";
+        else return "Unknown";
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDPickupSystem.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDPickupSystem.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDPickupSystem.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Patrick Wintermeyer
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _HUDPickupSystem_H__
+#define _HUDPickupSystem_H__
+
+#include "overlays/OverlaysPrereqs.h"
+#include "pickup/PickupPrereqs.h"
+
+#include <vector>
+
+#include "util/OgreForwardRefs.h"
+#include "overlays/OrxonoxOverlay.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDPickupSystem : public OrxonoxOverlay, public Tickable
+    {
+    public:
+        HUDPickupSystem(Context* context);
+        virtual ~HUDPickupSystem();
+
+        virtual void tick(float dt) override;
+
+        virtual void changedOwner() override;
+
+    private:
+        std::vector<const PickupInventoryContainer*> getPickupsForOwner() const;
+        std::string getIcon(const std::string& repName) const;
+
+        std::vector<Ogre::OverlayElement*> items_;
+        WeakPtr<Pawn> owner_;
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRadar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRadar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRadar.cc	(revision 11817)
@@ -0,0 +1,279 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Yuning Chai
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Reto Grieder
+ *      Wolfgang Roenninger
+ *
+ */
+
+#include "HUDRadar.h"
+
+#include <OgreOverlayManager.h>
+#include <OgrePanelOverlayElement.h>
+
+#include "util/Math.h"
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "tools/TextureGenerator.h"
+#include "worldentities/ControllableEntity.h"
+#include "Scene.h"
+#include "Radar.h"
+#include "core/config/ConfigValueIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDRadar);
+
+    HUDRadar::HUDRadar(Context* context)
+        : OrxonoxOverlay(context)
+    {
+        RegisterObject(HUDRadar);
+        this->setConfigValues();
+
+        this->marker_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+            .createOverlayElement("Panel", "HUDRadar_marker_" + getUniqueNumberString()));
+        this->marker_->setMaterialName("Orxonox/RadarMarker");
+        this->overlay_->add2D(this->marker_);
+        this->marker_->hide();
+
+        this->setRadarSensitivity(1.0f);
+        this->setHalfDotSizeDistance(3000.0f);
+        this->setMaximumDotSize(0.1f);
+        this->setMaximumDotSize3D(0.07f);
+
+        this->shapeMaterials_[RadarViewable::Shape::Dot]      = "RadarDot.png";
+        this->shapeMaterials_[RadarViewable::Shape::Triangle] = "RadarTriangle.png";
+        this->shapeMaterials_[RadarViewable::Shape::Square]   = "RadarSquare.png";
+        this->owner_ = nullptr;
+
+        this->map3DFront_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+            .createOverlayElement("Panel", "HUDRadar_mapDreiDFront_" + getUniqueNumberString()));
+        this->map3DFront_->setMaterialName("Orxonox/Radar3DFront");
+        this->overlay_->add2D(this->map3DFront_);
+        this->map3DFront_->hide();
+
+        this->map3DBack_ = static_cast<Ogre::PanelOverlayElement*>(Ogre::OverlayManager::getSingleton()
+            .createOverlayElement("Panel", "HUDRadar_mapDreiDBack_" + getUniqueNumberString()));
+        this->map3DBack_->setMaterialName("Orxonox/Radar3DBack");
+        this->overlay_->add2D(this->map3DBack_);
+        this->map3DBack_->hide();
+
+    }
+
+    HUDRadar::~HUDRadar()
+    {
+        if (this->isInitialized())
+        {
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->marker_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->map3DFront_);
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->map3DBack_);
+
+            for (const auto& mapEntry : this->radarObjects_)
+            {
+                Ogre::OverlayManager::getSingleton().destroyOverlayElement(mapEntry.second);
+            }
+        }
+    }
+
+
+
+    void HUDRadar::setConfigValues()
+       {
+           SetConfigValue(RadarMode_, true);
+       }
+
+    void HUDRadar::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HUDRadar, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HUDRadar, "sensitivity", setRadarSensitivity, getRadarSensitivity, xmlelement, mode);
+        XMLPortParam(HUDRadar, "halfDotSizeDistance", setHalfDotSizeDistance, getHalfDotSizeDistance, xmlelement, mode);
+        XMLPortParam(HUDRadar, "maximumDotSize", setMaximumDotSize, getMaximumDotSize, xmlelement, mode);
+        XMLPortParam(HUDRadar, "maximumDotSize3D", setMaximumDotSize3D, getMaximumDotSize3D, xmlelement, mode);
+        XMLPortParam(HUDRadar, "material2D", set2DMaterial, get2DMaterial, xmlelement, mode);
+        XMLPortParam(HUDRadar, "material3DMiddle", set3DMaterial, get3DMaterial, xmlelement, mode);
+        XMLPortParam(HUDRadar, "material3DFront", set3DMaterialFront, get3DMaterialFront, xmlelement, mode);
+        XMLPortParam(HUDRadar, "material3DBack", set3DMaterialBack, get3DMaterialBack, xmlelement, mode);
+        XMLPortParam(HUDRadar, "mapAngle3D", setMapAngle, getMapAngle, xmlelement, mode);
+        XMLPortParam(HUDRadar, "detectionLimit", setDetectionLimit, getDetectionLimit, xmlelement, mode);
+    }
+
+    void HUDRadar::addObject(RadarViewable* object)
+    {
+        if (object == orxonox_cast<RadarViewable*>(this->owner_))
+            return;
+        if( showObject(object) == false ) //do not show objects that are "invisible" or "radar invisible"
+            return;
+
+        // Make sure the object hasn't been added yet
+        assert( this->radarObjects_.find(object) == this->radarObjects_.end() );
+
+        // Create everything needed to display the object on the radar and add it to the map
+        Ogre::PanelOverlayElement* panel;
+        panel = static_cast<Ogre::PanelOverlayElement*>(
+            Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "RadarDot" + getUniqueNumberString()));
+        this->overlay_->add2D(panel);
+        // get right material
+        panel->setMaterialName(TextureGenerator::getMaterialName(
+            shapeMaterials_[object->getRadarObjectShape()], object->getRadarObjectColour()));
+        panel->hide();
+        this->radarObjects_[object] = panel;
+    }
+
+    void HUDRadar::removeObject(RadarViewable* object)
+    {
+        // If object was added at all then remove it
+        std::map<RadarViewable*,Ogre::PanelOverlayElement*>::iterator it;
+        it = this->radarObjects_.find( object );
+        if( it != this->radarObjects_.end() )
+        {
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(it->second);
+            this->radarObjects_.erase(it);
+        }
+    }
+
+    void HUDRadar::objectChanged( RadarViewable* rv )
+    {// The new implementation behaves more precisely, since inactive RadarViewables are not displayed anymore.
+        this->removeObject(rv);
+        this->addObject(rv);
+    }
+
+    void HUDRadar::gatherObjects()
+    {
+        const std::set<RadarViewable*>& objectSet = this->getCreator()->getScene()->getRadar()->getRadarObjects();
+        for( RadarViewable* viewable : objectSet )
+            this->addObject(viewable);
+        this->radarTick(0);
+    }
+
+    void HUDRadar::radarTick(float dt)
+    {
+        // Make sure the owner of the radar was defined
+        if( !this->owner_ )
+            return;
+
+        this->marker_->hide();      // in case that no object is in focus
+        // get the focus object
+        Radar* radar = this->getOwner()->getScene()->getRadar();
+        const RadarViewable* focusObject = radar->getFocus();
+
+        // update the distances for all objects
+
+        if(RadarMode_)
+        {
+            this->setBackgroundMaterial(material3D_);
+            this->map3DFront_->_notifyZOrder(this->overlay_->getZOrder() * 100 + 250); // it seems that the ZOrder of overlayelements is 100 times the ZOrder of the overlay
+            this->map3DBack_->_notifyZOrder(this->overlay_->getZOrder() * 100 - 250); // 250 a little bit buffer so that the two shels are displayed all in the front / in the back
+            this->map3DFront_->show();
+            this->map3DBack_->show();
+        }
+        else
+        {
+            this->setBackgroundMaterial(material2D_);
+            this->map3DFront_->hide();
+            this->map3DBack_->hide();
+        }
+
+        for( const auto& mapEntry : this->radarObjects_ )
+        {
+            // Make sure the object really is a WorldEntity
+            const WorldEntity* wePointer = mapEntry.first->getWorldEntity();
+            if( !wePointer )
+            {
+                orxout(internal_error) << "Cannot display a non-WorldEntitiy on the radar" << endl;
+                assert(0);
+            }
+            bool isFocus = (mapEntry.first == focusObject);
+            // set size to fit distance...
+            float distance = (wePointer->getWorldPosition() - this->owner_->getPosition()).length();
+            // calculate the size with 1/distance dependency for simplicity (instead of exp(-distance * lambda)
+
+            float size;
+            if(RadarMode_)
+                size = maximumDotSize3D_ * halfDotSizeDistance_ / (halfDotSizeDistance_ + distance) * mapEntry.first->getRadarObjectScale();
+            else
+                size = maximumDotSize_ * halfDotSizeDistance_ / (halfDotSizeDistance_ + distance) * mapEntry.first->getRadarObjectScale();
+            mapEntry.second->setDimensions(size, size);
+
+            // calc position on radar...
+            Vector2 coord;
+
+            if(RadarMode_)
+            {
+                coord = get3DProjection(this->owner_->getPosition(), this->owner_->getOrientation() * WorldEntity::FRONT, this->owner_->getOrientation() * WorldEntity::UP, wePointer->getWorldPosition(), 0.6435011, detectionLimit_);
+
+                // set zOrder on screen
+                bool overXZPlain = isObjectHigherThanShipOnMap(this->owner_->getPosition(), this->owner_->getOrientation() * WorldEntity::FRONT, this->owner_->getOrientation() * WorldEntity::UP, wePointer->getWorldPosition(), this->mapAngle_);
+
+                int zOrder = determineMap3DZOrder(this->owner_->getPosition(), this->owner_->getOrientation() * WorldEntity::FRONT, this->owner_->getOrientation() * WorldEntity::UP, wePointer->getWorldPosition(), detectionLimit_);
+                if(overXZPlain == false /*&& (it->second->getZOrder() >  100 * this->overlay_->getZOrder())*/) // it appears that zOrder of attached Overlayelements is 100 times the zOrder of the Overlay
+                    mapEntry.second->_notifyZOrder(this->overlay_->getZOrder() * 100 - 70 + zOrder);
+                if(overXZPlain == true /*&& (it->second->getZOrder() <= 100 * this->overlay_->getZOrder())*/)
+                    mapEntry.second->_notifyZOrder(this->overlay_->getZOrder() * 100 + 70 + zOrder);
+            }
+            else
+                coord = get2DViewCoordinates(this->owner_->getPosition(), this->owner_->getOrientation() * WorldEntity::FRONT, this->owner_->getOrientation() * WorldEntity::UP, wePointer->getWorldPosition());
+
+            coord *= math::pi / 3.5f; // small adjustment to make it fit the texture
+            mapEntry.second->setPosition((1.0f + coord.x - size) * 0.5f, (1.0f - coord.y - size) * 0.5f);
+
+            if( distance < detectionLimit_ || detectionLimit_ < 0 )
+                mapEntry.second->show();
+            else
+                mapEntry.second->hide();
+
+            // if this object is in focus, then set the focus marker
+            if (isFocus)
+            {
+                this->marker_->setDimensions(size * 1.5f, size * 1.5f);
+                this->marker_->setPosition((1.0f + coord.x - size * 1.5f) * 0.5f, (1.0f - coord.y - size * 1.5f) * 0.5f);
+                if(RadarMode_)
+                    this->marker_->_notifyZOrder(mapEntry.second->getZOrder() -1);
+                this->marker_->show();
+            }
+        }
+    }
+
+    bool HUDRadar::showObject(RadarViewable* rv)
+    {
+        if ( rv == orxonox_cast<RadarViewable*> ( this->getOwner() ) )
+            return false;
+        assert( rv->getWorldEntity() );
+        if ( rv->getWorldEntity()->isVisible()==false || rv->getRadarVisibility()==false )
+            return false;
+        return true;
+    }
+
+
+    void HUDRadar::changedOwner()
+    {
+        SUPER(HUDRadar, changedOwner);
+
+        this->owner_ = orxonox_cast<ControllableEntity*>(this->getOwner());
+        assert(this->radarObjects_.size() == 0);
+        this->gatherObjects();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRadar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRadar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRadar.h	(revision 11817)
@@ -0,0 +1,127 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Yuning Chai
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#ifndef _HUDRadar_H__
+#define _HUDRadar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "util/OgreForwardRefs.h"
+#include "interfaces/RadarListener.h"
+#include "interfaces/RadarViewable.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDRadar : public OrxonoxOverlay, public RadarListener
+    {
+    public:
+        HUDRadar(Context* context);
+        virtual ~HUDRadar();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void changedOwner() override;
+        void setConfigValues();
+
+    private:
+        // XML accessors
+        float getHalfDotSizeDistance() const { return this->halfDotSizeDistance_; }
+        void setHalfDotSizeDistance(float distance) { this->halfDotSizeDistance_ = distance; }
+
+        void setDetectionLimit( float limit ) { this->detectionLimit_ = limit; }
+        float getDetectionLimit() const { return this->detectionLimit_; }
+
+        float getMaximumDotSize() const { return this->maximumDotSize_; }
+        void setMaximumDotSize(float size) { this->maximumDotSize_ = size; }
+
+        float getMaximumDotSize3D() const { return this->maximumDotSize3D_; }
+        void setMaximumDotSize3D(float size) { this->maximumDotSize3D_ = size;}
+
+        std::string get2DMaterial() const {return this->material2D_; }
+        void set2DMaterial(std::string material2D) { this->material2D_ = material2D; }
+
+        std::string get3DMaterial() const {return this->material3D_; }
+        void set3DMaterial(std::string material3D) { this->material3D_ = material3D; }
+
+        std::string get3DMaterialFront() const {return this->material3DFront_; }
+        void set3DMaterialFront(std::string material3DFront) { this->material3DFront_ = material3DFront; }
+
+        std::string get3DMaterialBack() const {return this->material3DBack_; }
+        void set3DMaterialBack(std::string material3DBack) { this->material3DBack_ = material3DBack; }
+
+        virtual float getRadarSensitivity() const override { return this->sensitivity_; }
+        // used also by RadarListener interface!
+        void setRadarSensitivity(float sensitivity) { this->sensitivity_ = sensitivity; }
+
+        // Determines angle between line of sight and x/z-plain on the 3D minimap
+        float getMapAngle() const { return this->mapAngle_; }
+        void setMapAngle(float mapAngle) { this->mapAngle_ = mapAngle; }
+
+        // RadarListener interface
+        virtual void addObject(RadarViewable* viewable) override;
+        virtual void removeObject(RadarViewable* viewable) override;
+        virtual void objectChanged( RadarViewable* rv ) override;
+        virtual void radarTick(float dt) override;
+        bool showObject( RadarViewable* rv ); //!< Do not display an object on radar, if showObject(.) is false.
+
+        void gatherObjects();
+
+        std::map<RadarViewable::Shape, std::string> shapeMaterials_;
+
+//         std::vector<Ogre::PanelOverlayElement*> radarDots_;
+//         std::vector<Ogre::PanelOverlayElement*>::iterator itRadarDots_;
+        std::map<RadarViewable*, Ogre::PanelOverlayElement*> radarObjects_;
+        Ogre::PanelOverlayElement* marker_;
+
+        bool RadarMode_; // Determines, if Radar runs in 3D or 2D Mode
+
+        float halfDotSizeDistance_;
+        float maximumDotSize_;
+        float maximumDotSize3D_;
+        float mapAngle_;
+
+        std::string material2D_;        //Material name for 2D map
+        std::string material3D_;        //Material names For the 3D minimap
+        std::string material3DFront_;
+        std::string material3DBack_;
+
+        Ogre::PanelOverlayElement* map3DFront_; //Overlayelements for the 3D minimap to be able to draw the points in a semi 3D matter
+        Ogre::PanelOverlayElement* map3DBack_;
+
+        float sensitivity_;
+        float detectionLimit_;
+        ControllableEntity* owner_;
+    };
+}
+
+#endif /* _HUDRadar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRocketFuelBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRocketFuelBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRocketFuelBar.cc	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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 2src/libraries/core/class/Identifier.h
+ *   of the License, or (at your option) any later version.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDRocketFuelBar.h"
+
+#include "core/CoreIncludes.h"
+#include "weapons/projectiles/Rocket.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDRocketFuelBar);
+
+    HUDRocketFuelBar::HUDRocketFuelBar(Context* context) : HUDBar(context)
+    {
+        RegisterObject(HUDRocketFuelBar);
+
+        this->owner_ = nullptr;
+    }
+
+    HUDRocketFuelBar::~HUDRocketFuelBar()
+    {
+    }
+
+    void HUDRocketFuelBar::tick(float dt)
+    {
+        SUPER(HUDRocketFuelBar, tick, dt);
+
+        if (this->owner_)
+        {
+            float maxFuel = this->owner_->getMaxFuel();
+            if (maxFuel > 0.0)
+            {
+                this->setValue(this->owner_->getFuel()/maxFuel);
+            }
+            else
+            {
+                this->setValue(0.0);
+            }
+        }
+    }
+
+    void HUDRocketFuelBar::changedOwner()
+    {
+        SUPER(HUDRocketFuelBar, changedOwner);
+
+        this->owner_ = orxonox_cast<Rocket*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRocketFuelBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRocketFuelBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDRocketFuelBar.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+ /**
+    @file HUDRocketFuelBar.h
+    @brief Definition of the HUDRocketFuelBar class. This HUDBar displays the the amount of fuel  that a rocket has.
+*/
+
+#ifndef _HUDRocketFuelBar_H__
+#define _HUDRocketFuelBar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "weapons/projectiles/Rocket.h"
+#include "HUDBar.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDRocketFuelBar : public HUDBar, public Tickable
+    {
+    public:
+        HUDRocketFuelBar(Context* context);
+        virtual ~HUDRocketFuelBar();
+
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+
+    private:
+        Rocket* owner_;
+    };
+}
+#endif /* _HUDRocketFuelBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDShieldBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDShieldBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDShieldBar.cc	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDShieldBar.h"
+
+#include "core/CoreIncludes.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDShieldBar);
+
+    HUDShieldBar::HUDShieldBar(Context* context)
+        : HUDBar(context)
+    {
+        RegisterObject(HUDShieldBar);
+
+        this->owner_ = nullptr;
+    }
+
+    HUDShieldBar::~HUDShieldBar()
+    {
+    }
+
+    void HUDShieldBar::tick(float dt)
+    {
+        SUPER(HUDShieldBar, tick, dt);
+
+        if (this->owner_)
+        {
+            float maxShieldHealth = this->owner_->getMaxShieldHealth();
+            float shieldHealth = this->owner_->getShieldHealth();
+
+            if (maxShieldHealth > 0.0f)
+            {
+                this->setValue(shieldHealth/maxShieldHealth);
+            }
+            else
+            {
+                this->setValue(0.0f);
+            }
+        }
+        else
+        {
+            this->setValue(0.0f);
+        }
+    }
+
+    void HUDShieldBar::changedOwner()
+    {
+        SUPER(HUDShieldBar, changedOwner);
+
+        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDShieldBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDShieldBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDShieldBar.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDShieldBar_H__
+#define _HUDShieldBar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "HUDBar.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The HUDShieldBar displays the the status of the shield of its owner (a @ref Pawn).
+        The length of the bar is given by the ratio of the shield health and the maximal shield health of the @ref Pawn.
+    */
+
+    class _OverlaysExport HUDShieldBar : public HUDBar, public Tickable
+    {
+    public:
+        HUDShieldBar(Context* context);
+        virtual ~HUDShieldBar();
+
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+
+        inline void setShieldBarOwner(Pawn* owner)
+            { this->owner_ = owner; }
+    private:
+        Pawn* owner_;
+    };
+}
+#endif /* _HUDShieldBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDSpeedBar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDSpeedBar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDSpeedBar.cc	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDSpeedBar.h"
+
+#include "core/CoreIncludes.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "items/Engine.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDSpeedBar);
+
+    HUDSpeedBar::HUDSpeedBar(Context* context)
+        : HUDBar(context)
+    {
+        RegisterObject(HUDSpeedBar);
+
+        this->owner_ = nullptr;
+    }
+
+    HUDSpeedBar::~HUDSpeedBar()
+    {
+    }
+
+    void HUDSpeedBar::tick(float dt)
+    {
+        SUPER(HUDSpeedBar, tick, dt);
+
+        if (this->owner_)
+        {
+            float value = this->owner_->getVelocity().length() / (this->owner_->getMaxSpeedFront() * this->owner_->getSpeedFactor() * this->owner_->getBoostFactor());
+            this->setValue(value);
+        }
+    }
+
+    void HUDSpeedBar::changedOwner()
+    {
+        SUPER(HUDSpeedBar, changedOwner);
+
+        this->owner_ = orxonox_cast<SpaceShip*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDSpeedBar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDSpeedBar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDSpeedBar.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDSpeedBar_H__
+#define _HUDSpeedBar_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "HUDBar.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDSpeedBar : public HUDBar, public Tickable
+    {
+    public:
+        HUDSpeedBar(Context* context);
+        virtual ~HUDSpeedBar();
+
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+
+    private:
+        SpaceShip* owner_;
+    };
+}
+#endif /* _HUDSpeedBar_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDTimer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDTimer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDTimer.cc	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDTimer.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "worldentities/ControllableEntity.h"
+#include "gametypes/Gametype.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDTimer);
+
+    HUDTimer::HUDTimer(Context* context) : OverlayText(context)
+    {
+        RegisterObject(HUDTimer);
+
+        this->owner_ = nullptr;
+    }
+
+    HUDTimer::~HUDTimer()
+    {
+    }
+
+    void HUDTimer::tick(float dt)
+    {
+        SUPER(HUDTimer, tick, dt);
+
+        Gametype* gametype = this->getGametype();
+
+        if (gametype)
+        {
+            if (gametype->getTimerIsActive())
+            {
+                this->setCaption(multi_cast<std::string>(static_cast<int>(gametype->getTime()) + 1));
+            }
+        }
+    }
+
+    void HUDTimer::changedOwner()
+    {
+        SUPER(HUDTimer, changedOwner);
+
+        this->owner_ = orxonox_cast<ControllableEntity*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDTimer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDTimer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDTimer.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDTimer_H__
+#define _HUDTimer_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDTimer : public OverlayText, public Tickable
+    {
+    public:
+        HUDTimer(Context* context);
+        virtual ~HUDTimer();
+
+        virtual void tick(float dt) override;
+
+        virtual void changedOwner() override;
+
+    private:
+        ControllableEntity* owner_;
+    };
+}
+#endif /* _HUDTimer_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeapon.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeapon.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeapon.cc	(revision 11817)
@@ -0,0 +1,221 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDWeapon.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "core/class/Super.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDWeapon);
+
+    HUDWeapon::HUDWeapon(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(HUDWeapon);
+
+        weaponModeHUDActualSize_ = Vector2(0.0f,0.0f);
+
+        weaponIndex_ = 0;
+        hudWeaponModes_.clear();
+
+        overlayElement_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeapon" + getUniqueNumberString()));
+        overlayElement_->setMaterialName("Orxonox/WSHUD_Weapon");
+        overlayElement_->setPosition(0.0f,0.0f);
+        overlayElement_->setDimensions(1.0f,1.0f);
+        this->background_->addChild(overlayElement_);
+    }
+
+    HUDWeapon::~HUDWeapon()
+    {
+        if (this->isInitialized())
+        {
+            destroyHUDChilds();
+        }
+    }
+
+    void HUDWeapon::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HUDWeapon, XMLPort, xmlelement, mode);
+
+        /*XMLPortParam(HUDWeapons, "sensitivity", setRadarSensitivity, getRadarSensitivity, xmlelement, mode);
+        XMLPortParam(HUDWeapons, "halfDotSizeDistance", setHalfDotSizeDistance, getHalfDotSizeDistance, xmlelement, mode);*/
+    }
+
+    void HUDWeapon::tick(float dt)
+    {
+        SUPER(HUDWeapon, tick, dt);
+
+        if (!weapon_)
+        {
+            // TODO: destroy this HUD id the Weapon does no more exist. (Wehen the weak pointer is null)
+        }
+    }    
+
+    void HUDWeapon::positionChanged()
+    {
+        OrxonoxOverlay::positionChanged();
+
+        positionHUDChilds();
+    }
+
+    void HUDWeapon::sizeChanged()
+    {
+        OrxonoxOverlay::sizeChanged();
+
+        positionHUDChilds();
+    }
+
+    void HUDWeapon::changedOwner()
+    {
+        SUPER(HUDWeapon, changedOwner);
+
+        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());
+
+        updateWeaponModeList();
+    }
+
+    void HUDWeapon::changedOverlayGroup()
+    {
+        SUPER(HUDWeapon, changedOverlayGroup);
+    }   
+
+    void HUDWeapon::changedVisibility()
+    {
+        SUPER(HUDWeapon, changedVisibility);
+
+        bool visible = this->isVisible();
+
+        for (HUDWeaponMode* hudWeaponMode : hudWeaponModes_)
+        {
+            hudWeaponMode->changedVisibility(); //inform all Child Overlays that our visibility has changed
+            hudWeaponMode->setVisible(visible);
+        }
+    }
+
+    void HUDWeapon::changedName()
+    {
+        SUPER(HUDWeapon, changedName);
+    }
+
+    void HUDWeapon::setWeapon(Weapon* weapon)
+    {
+        weapon_ = weapon;
+
+        if (!weapon_)
+        {
+            return;
+        }
+
+        updateWeaponModeList();
+    }
+
+    void HUDWeapon::updateWeaponModeList()
+    {
+        if (owner_ == nullptr || weapon_ == nullptr)
+        {
+            return;
+        }
+            
+        destroyHUDChilds();
+
+        updateSize();
+        createHUDChilds();
+        positionHUDChilds();
+    }  
+
+    void HUDWeapon::createHUDChilds()
+    {
+        if (weapon_ == nullptr)
+        {
+            return;
+        }
+
+        int positionIndex = 0;
+
+        for (const auto& mapEntry : weapon_->getAllWeaponmodes())
+        {
+            HUDWeaponMode* hudWeaponMode = new HUDWeaponMode(this->getContext());
+            hudWeaponMode->setOwner(owner_);
+            hudWeaponMode->setOverlayGroup(this->getOverlayGroup());
+            hudWeaponMode->setVisible(this->isVisible());
+            hudWeaponMode->setWeaponMode(mapEntry.second);
+            hudWeaponMode->setWeaponIndex(this->weaponIndex_);                    
+            hudWeaponMode->setAspectCorrection(false);
+            hudWeaponMode->setPickPoint(Vector2(0.0f,0.0f));
+
+            hudWeaponModes_.push_back(hudWeaponMode);
+
+            ++ positionIndex;
+        }
+    }      
+
+    void HUDWeapon::positionHUDChilds()
+    {
+        int positionIndex = 0;
+
+        for (HUDWeaponMode* hudWeaponMode : hudWeaponModes_)
+        {
+            hudWeaponMode->setPositionOffset(this->positionOffset_);
+            hudWeaponMode->setWeaponModeIndex(positionIndex);
+            hudWeaponMode->setWeaponIndex(this->weaponIndex_);
+            hudWeaponMode->setWeaponModeHUDActualSize(this->weaponModeHUDActualSize_);
+
+            ++ positionIndex;
+        }
+    }  
+
+    void HUDWeapon::destroyHUDChilds()
+    {
+        for (HUDWeaponMode* hudWeaponMode : hudWeaponModes_)
+        {
+            hudWeaponMode->destroy();
+        } 
+
+        hudWeaponModes_.clear();
+    }
+
+    void HUDWeapon::updateSize()
+    {
+        if (weapon_ != nullptr)
+        {
+            this->setSize(Vector2(weaponModeHUDActualSize_.x,weaponModeHUDActualSize_.y*weapon_->getAllWeaponmodes().size()));
+            updatePosition();
+        }        
+    }
+
+    void HUDWeapon::updatePosition()
+    {
+        if (weapon_ != nullptr)
+        {
+            this->setPosition(Vector2(weaponModeHUDActualSize_.x*weaponIndex_,0.0f) + this->positionOffset_);
+        }        
+    }       
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeapon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeapon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeapon.h	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDWeapon_H__
+#define _HUDWeapon_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include <OgreOverlayManager.h>
+#include <OgrePanelOverlayElement.h> 
+
+#include "overlays/OrxonoxOverlay.h"
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/pawns/Pawn.h"
+#include "overlays/OverlayGroup.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponMode.h"
+#include "HUDWeaponMode.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDWeapon : public OrxonoxOverlay, public Tickable
+    {
+    public:
+        HUDWeapon(Context* context);
+        virtual ~HUDWeapon();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+        virtual void changedOverlayGroup() override;
+        virtual void changedVisibility() override;
+        virtual void changedName() override;
+        virtual void positionChanged() override;
+        virtual void sizeChanged() override;
+
+        void setWeapon(Weapon* weapon);
+
+        inline void setWeaponModeHUDActualSize(Vector2 vector)
+            { weaponModeHUDActualSize_ = vector;
+              this->updateSize();
+            }
+        inline Vector2 getWeaponModeHUDActualSize() const
+            { return weaponModeHUDActualSize_; }
+        inline void setPositionOffset(Vector2 positionOffset)
+            {
+                this->positionOffset_ = positionOffset;
+                this->updatePosition();
+            }            
+        inline void setWeaponIndex(int index)
+            {
+                weaponIndex_ = index;
+                this->updatePosition();
+            }        
+
+    private:
+        void createHUDChilds();
+        void positionHUDChilds();
+        void destroyHUDChilds();
+        void updateWeaponModeList();
+        void updateSize();
+        void updatePosition();
+
+        WeakPtr<Pawn> owner_;
+        WeakPtr<Weapon> weapon_;
+
+        std::vector<WeakPtr<HUDWeaponMode>> hudWeaponModes_;
+
+        Ogre::PanelOverlayElement* overlayElement_;
+
+        Vector2 weaponModeHUDActualSize_;
+        Vector2 positionOffset_;
+        int weaponIndex_;
+    };
+}
+
+#endif /* _HUDWeapon_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponMode.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponMode.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponMode.cc	(revision 11817)
@@ -0,0 +1,284 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDWeaponMode.h"
+
+#include "util/Convert.h"
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/class/Super.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDWeaponMode);
+
+    HUDWeaponMode::HUDWeaponMode(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(HUDWeaponMode);
+
+        weaponIndex_ = 0;
+        weaponModeIndex_ = 0;
+
+        overlayElementIcon_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
+        overlayElementIcon_->setPosition(0.0f,0.0f);
+        overlayElementIcon_->setDimensions(1.0f,1.0f);
+        this->background_->addChild(overlayElementIcon_);
+
+        overlayElementReplenish_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
+        overlayElementReplenish_->setPosition(0.0f,0.0f);
+        overlayElementReplenish_->setDimensions(1.0f,1.0f);
+        this->background_->addChild(overlayElementReplenish_);
+
+        overlayElementMunition_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
+        overlayElementMunition_->setPosition(0.0f,0.0f);
+        overlayElementMunition_->setDimensions(1.0f,1.0f);
+        this->background_->addChild(overlayElementMunition_);
+
+        overlayElementState_ = static_cast<Ogre::PanelOverlayElement* >(Ogre::OverlayManager::getSingleton().createOverlayElement("Panel", "HUDWeaponMode" + getUniqueNumberString()));
+        overlayElementState_->setPosition(0.0f,0.0f);
+        overlayElementState_->setDimensions(1.0f,1.0f);
+        this->background_->addChild(overlayElementState_);
+
+        overlayElementIcon_->show();
+        overlayElementReplenish_->show();
+        overlayElementMunition_->show();
+        overlayElementState_->show();
+
+        // Create two text overlays
+        this->textOverlayLeft_ = new OverlayText(this->getContext());
+        assert(this->textOverlayLeft_.get());
+        this->textOverlayLeft_->setCaption("?");
+        textOverlayLeft_->setPickPoint(Vector2(0.0f,0.0f));
+        textOverlayLeft_->setVisible(true);
+        textOverlayLeft_->setAlignment(OverlayText::Alignment::Center);
+        textOverlayLeft_->setTextSize(0.02f);
+        textOverlayLeft_->setColour(ColourValue(0.21,0.70,0.21,1.0));
+        textOverlayLeft_->setAspectCorrection(false);
+        textOverlayLeft_->setZOrder(600);
+        
+        this->textOverlayRight_ = new OverlayText(this->getContext());
+        assert(this->textOverlayRight_.get());
+        this->textOverlayRight_->setCaption("?");
+        textOverlayRight_->setPickPoint(Vector2(0.0f,0.0f));
+        textOverlayRight_->setVisible(true);
+        textOverlayRight_->setAlignment(OverlayText::Alignment::Center);
+        textOverlayRight_->setTextSize(0.02f);
+        textOverlayRight_->setColour(ColourValue(0.21,0.70,0.21,1.0));
+        textOverlayRight_->setAspectCorrection(false);
+        textOverlayRight_->setZOrder(600);
+
+        materialNameState_ = "";
+
+        overlayElementReplenish_->setMaterialName("Orxonox/WSHUD_Replenish");
+    }
+
+    HUDWeaponMode::~HUDWeaponMode()
+    {
+        if (this->isInitialized())
+        {
+            this->textOverlayLeft_->destroy();
+            this->textOverlayRight_->destroy();
+        }
+    }
+
+    void HUDWeaponMode::tick(float dt)
+    {
+        SUPER(HUDWeaponMode, tick, dt);
+
+        if (this->owner_ && this->weaponMode_)
+        {
+            std::string lastMaterialNameState = materialNameState_;
+
+            if (weaponMode_->getReloading())
+            {
+                materialNameState_ = "Orxonox/WSHUD_Reloading";
+            }
+            else
+            {
+                materialNameState_ = "Orxonox/WSHUD_Ready";
+            }            
+
+            Munition* munition = this->weaponMode_->getMunition();
+
+            if (munition != nullptr)
+            {
+                MunitionDeployment deployment = munition->getMunitionDeployment();
+
+                if (deployment == MunitionDeployment::Share)
+                {
+                    this->textOverlayLeft_->setCaption(multi_cast<std::string>(munition->getNumMunitionInCurrentMagazine(weaponMode_)));
+                    this->textOverlayRight_->setCaption(multi_cast<std::string>(munition->getNumMagazines()));
+                }
+                else if (deployment == MunitionDeployment::Stack)
+                {
+                    this->textOverlayLeft_->setCaption(multi_cast<std::string>(munition->getNumMunition(weaponMode_)));
+                    this->textOverlayRight_->setCaption("");
+                }
+                else if (deployment == MunitionDeployment::Separate)
+                {
+                    this->textOverlayLeft_->setCaption(multi_cast<std::string>(munition->getNumMunitionInCurrentMagazine(weaponMode_)));
+                    this->textOverlayRight_->setCaption(multi_cast<std::string>(munition->getNumMagazines()));
+                }
+
+                if (munition->getNumMunition(weaponMode_) == 0)
+                {
+                    materialNameState_ = "Orxonox/WSHUD_Empty";
+                }
+
+                if (munition->isA(Class(ReplenishingMunition)))
+                {
+                    ReplenishingMunition* replenishingMunition = dynamic_cast<ReplenishingMunition*>(munition);
+
+                    if (replenishingMunition->canAddMagazines(1))
+                    {
+                        float progress = 1.0f - replenishingMunition->getProgress();
+                        overlayElementReplenish_->setDimensions(1.0f,progress);                    
+                    }
+                    else
+                    {
+                        overlayElementReplenish_->setDimensions(1.0f,1.0f);
+                    }
+                }
+            }
+
+            if (materialNameState_ != lastMaterialNameState)
+            {
+                overlayElementState_->setMaterialName(materialNameState_);
+            }
+        }
+    }    
+
+    void HUDWeaponMode::positionChanged()
+    {
+        OrxonoxOverlay::positionChanged();
+
+        positionHUDChilds();
+    }
+
+    void HUDWeaponMode::sizeChanged()
+    {
+        OrxonoxOverlay::sizeChanged();
+
+        positionHUDChilds();
+    }
+
+    void HUDWeaponMode::changedOwner()
+    {
+        SUPER(HUDWeaponMode, changedOwner);
+
+        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());
+
+        materialNameState_ = ""; // Needed to set the material in the tick after a change of the owner.
+    }
+
+    void HUDWeaponMode::changedOverlayGroup()
+    {
+        SUPER(HUDWeaponMode, changedOverlayGroup);
+
+        this->getOverlayGroup()->addElement(this->textOverlayLeft_.get());
+        this->getOverlayGroup()->addElement(this->textOverlayRight_.get());
+    }   
+
+    void HUDWeaponMode::changedVisibility()
+    {
+        SUPER(HUDWeaponMode, changedVisibility);
+
+        bool visible = this->isVisible();
+
+        this->textOverlayLeft_->setVisible(visible);
+        this->textOverlayRight_->setVisible(visible);
+    }
+
+    void HUDWeaponMode::changedName()
+    {
+        SUPER(HUDWeaponMode, changedName);
+
+        //this->textOverlay_->setName(this->getName() + "text");
+    }  
+
+    void HUDWeaponMode::setWeaponMode(WeaponMode* weaponMode)
+    {
+        weaponMode_ = weaponMode;
+
+        if (!weaponMode_)
+        {
+            return;
+        }
+
+        std::string materialName = weaponMode_->getHUDImageString();
+
+        overlayElementIcon_->setMaterialName(materialName);
+
+        Munition* munition = this->weaponMode_->getMunition();
+
+        if (munition != nullptr)
+        {
+            MunitionDeployment deployment = munition->getMunitionDeployment();
+
+            if (deployment == MunitionDeployment::Share)
+            {
+                overlayElementMunition_->setMaterialName("Orxonox/WSHUD_MunitionShare");
+            }
+            else if (deployment == MunitionDeployment::Stack)
+            {
+                overlayElementMunition_->setMaterialName("Orxonox/WSHUD_MunitionStack");
+            }
+            else if (deployment == MunitionDeployment::Separate)
+            {
+                overlayElementMunition_->setMaterialName("Orxonox/WSHUD_MunitionSeparate");
+            }
+        }
+    }
+
+    void HUDWeaponMode::positionHUDChilds()
+    {
+        Vector2 size = Vector2(getSize().x*45.0f/150.0f, getSize().y);
+        Vector2 offset1 = Vector2(getSize().x*82.5f/150.0f, 0.0f);
+        Vector2 offset2 = Vector2(getSize().x*127.5f/150.0f, 0.0f);
+
+        textOverlayLeft_->setPosition(getPosition() + offset1);
+        textOverlayRight_->setPosition(getPosition() + offset2);
+
+        textOverlayLeft_->setSize(size);
+        textOverlayRight_->setSize(size);
+
+        textOverlayLeft_->setTextSize(getSize().y);
+        textOverlayRight_->setTextSize(getSize().y);
+    }
+
+    void HUDWeaponMode::updateSize()
+    {
+        this->setSize(weaponModeHUDActualSize_);
+        updatePosition();
+    }
+
+    void HUDWeaponMode::updatePosition()
+    {
+        this->setPosition(Vector2(weaponModeHUDActualSize_.x*weaponIndex_,weaponModeHUDActualSize_.y*weaponModeIndex_) + this->positionOffset_);
+    }      
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponMode.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponMode.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponMode.h	(revision 11817)
@@ -0,0 +1,114 @@
+
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDWeaponMode_H__
+#define _HUDWeaponMode_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include <OgreOverlayManager.h>
+#include <OgrePanelOverlayElement.h> 
+
+#include "overlays/OrxonoxOverlay.h"
+#include "overlays/OverlayText.h"
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/pawns/Pawn.h"
+#include "overlays/OverlayGroup.h"
+#include "weaponsystem/ReplenishingMunition.h"
+#include "weaponsystem/WeaponMode.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDWeaponMode : public OrxonoxOverlay, public Tickable
+    {
+    public:
+        HUDWeaponMode(Context* context);
+        virtual ~HUDWeaponMode();
+
+        virtual void tick(float dt) override;
+        virtual void changedOwner() override;
+        virtual void changedOverlayGroup() override;
+        virtual void changedVisibility() override;
+        virtual void changedName() override;
+        virtual void positionChanged() override;
+        virtual void sizeChanged() override;
+
+        void setWeaponMode(WeaponMode* weaponMode);
+
+        inline void setWeaponModeHUDActualSize(Vector2 vector)
+            { weaponModeHUDActualSize_ = vector;
+              this->updateSize();
+            }
+        inline Vector2 getWeaponModeHUDActualSize() const
+            { return weaponModeHUDActualSize_; }
+        inline void setWeaponIndex(int index)
+            { weaponIndex_ = index;
+              this->updatePosition();
+            }
+        inline void setWeaponModeIndex(int index)
+            { weaponModeIndex_ = index;
+              this->updatePosition();
+            }
+        inline void setPositionOffset(Vector2 positionOffset)
+            {
+                this->positionOffset_ = positionOffset;
+                this->updatePosition();
+            }
+
+    private:
+        void updateSize();
+        void updatePosition();
+        void positionHUDChilds();
+
+        WeakPtr<Pawn> owner_;
+        WeakPtr<WeaponMode> weaponMode_;
+
+        Ogre::PanelOverlayElement* overlayElementIcon_;
+        Ogre::PanelOverlayElement* overlayElementReplenish_;
+        Ogre::PanelOverlayElement* overlayElementMunition_;
+        Ogre::PanelOverlayElement* overlayElementState_;
+
+        std::string materialNameState_;
+
+        StrongPtr<OverlayText> textOverlayLeft_;
+        StrongPtr<OverlayText> textOverlayRight_;
+
+        Vector2 weaponModeHUDActualSize_;
+        Vector2 positionOffset_;
+        int weaponIndex_;
+        int weaponModeIndex_;
+    };
+}
+
+#endif /* _HUDWeaponMode_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponSystem.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponSystem.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponSystem.cc	(revision 11817)
@@ -0,0 +1,189 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HUDWeaponSystem.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/Weapon.h"
+#include "util/Convert.h"
+#include "core/class/Super.h"
+
+namespace orxonox
+{
+    RegisterClass(HUDWeaponSystem);
+
+    HUDWeaponSystem::HUDWeaponSystem(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(HUDWeaponSystem);
+
+        weaponModeHUDSize_ = Vector2(0.0f,0.0f);
+        weaponModeHUDActualSize_ = Vector2(0.0f,0.0f);        
+
+        weapons_.clear();
+        hudWeapons_.clear();
+    }
+
+    HUDWeaponSystem::~HUDWeaponSystem()
+    {
+        if (this->isInitialized())
+        {
+            destroyHUDChilds();
+        }
+    }
+
+    void HUDWeaponSystem::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HUDWeaponSystem, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HUDWeaponSystem, "weaponModeHUDSize", setWeaponModeHUDSize, getWeaponModeHUDSize, xmlelement, mode);
+    }
+
+    void HUDWeaponSystem::positionChanged()
+    {
+        OrxonoxOverlay::positionChanged();
+
+        positionHUDChilds();
+    }
+
+    void HUDWeaponSystem::sizeChanged()
+    {
+        OrxonoxOverlay::sizeChanged();
+
+        weaponModeHUDActualSize_ = this->getActualSize();
+
+        positionHUDChilds();
+    }
+
+    void HUDWeaponSystem::changedOwner()
+    {
+        SUPER(HUDWeaponSystem, changedOwner);
+
+        this->owner_ = orxonox_cast<Pawn*>(this->getOwner());
+
+        updateWeaponList();
+    }
+
+    void HUDWeaponSystem::changedOverlayGroup()
+    {
+        SUPER(HUDWeaponSystem, changedOverlayGroup);
+    }   
+
+    void HUDWeaponSystem::changedVisibility()
+    {
+        SUPER(HUDWeaponSystem, changedVisibility);
+
+        bool visible = this->isVisible();
+
+        for (HUDWeapon* hudWeapon : hudWeapons_)
+        {
+            hudWeapon->changedVisibility(); //inform all Child Overlays that our visibility has changed
+            hudWeapon->setVisible(visible);
+        }
+    }
+
+    void HUDWeaponSystem::changedName()
+    {
+        SUPER(HUDWeaponSystem, changedName);
+    }  
+
+    void HUDWeaponSystem::updateWeaponList()
+    {
+        if (owner_ == nullptr)
+        {
+            return;
+        }
+
+        weapons_.clear();
+
+        destroyHUDChilds();
+
+        if (owner_->getWeaponSystem())
+        {
+            const std::vector<WeaponPack*>& weaponPacks = owner_->getWeaponSystem()->getAllWeaponPacks();
+            for (WeaponPack* weaponPack : weaponPacks)
+            {
+                const std::vector<Weapon*>& weapons = weaponPack->getAllWeapons();
+                for (Weapon* weapon : weapons)
+                {
+                    this->weapons_.push_back(weapon);
+                }
+            }
+
+            createHUDChilds();
+            positionHUDChilds();
+        }
+    }
+
+    void HUDWeaponSystem::createHUDChilds()
+    {
+        int positionIndex = 0;
+
+        for (Weapon* weapon : weapons_)
+        {
+            HUDWeapon* hudWeapon = new HUDWeapon(this->getContext());
+            hudWeapon->setOwner(owner_);
+            hudWeapon->setOverlayGroup(this->getOverlayGroup());
+            hudWeapon->setVisible(this->isVisible());
+            hudWeapon->setWeapon(weapon);
+            hudWeapon->setAspectCorrection(false);
+            hudWeapon->setPickPoint(Vector2(0.0f,0.0f));
+
+            hudWeapons_.push_back(hudWeapon);
+
+            ++ positionIndex;
+        }
+    }      
+
+    void HUDWeaponSystem::positionHUDChilds()
+    {
+        int positionIndex = 0;
+        Vector2 offset = this->getPosition();
+
+        for (HUDWeapon* hudWeapon : hudWeapons_)
+        {
+            hudWeapon->setPositionOffset(offset);
+            hudWeapon->setWeaponIndex(positionIndex);
+            hudWeapon->setWeaponModeHUDActualSize(this->weaponModeHUDActualSize_);
+
+            ++ positionIndex;
+        }
+    }  
+
+    void HUDWeaponSystem::destroyHUDChilds()
+    {
+        for (HUDWeapon* hudWeapon : hudWeapons_)
+        {
+            hudWeapon->destroy();
+        } 
+
+        hudWeapons_.clear();     
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponSystem.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponSystem.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/HUDWeaponSystem.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HUDWeaponSystem_H__
+#define _HUDWeaponSystem_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "overlays/OrxonoxOverlay.h"
+#include "worldentities/pawns/Pawn.h"
+#include "overlays/OverlayGroup.h"
+#include "HUDWeapon.h"
+
+namespace orxonox
+{
+    class _OverlaysExport HUDWeaponSystem : public OrxonoxOverlay
+    {
+    public:
+        HUDWeaponSystem(Context* context);
+        virtual ~HUDWeaponSystem();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void changedOwner() override;
+        virtual void changedOverlayGroup() override;
+        virtual void changedVisibility() override;
+        virtual void changedName() override;
+        virtual void positionChanged() override;
+        virtual void sizeChanged() override;
+    protected:
+        inline void setWeaponModeHUDSize(Vector2 vector)
+            { weaponModeHUDSize_ = vector;
+                this->setSize(weaponModeHUDSize_);
+            }
+        inline Vector2 getWeaponModeHUDSize() const
+            { return weaponModeHUDSize_; }
+    private:
+        void updateWeaponList();
+        void createHUDChilds();
+        void positionHUDChilds();
+        void destroyHUDChilds();
+
+        WeakPtr<Pawn> owner_;
+
+        std::vector<WeakPtr<Weapon>> weapons_;
+        std::vector<WeakPtr<HUDWeapon>> hudWeapons_;
+
+        Vector2 weaponModeHUDSize_;
+        Vector2 weaponModeHUDActualSize_;
+    };
+}
+
+#endif /* _HUDWeaponSystem_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/KillMessage.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/KillMessage.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/KillMessage.cc	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "KillMessage.h"
+
+#include "core/CoreIncludes.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(KillMessage);
+
+    KillMessage::KillMessage(Context* context) : FadeoutText(context)
+    {
+        RegisterObject(KillMessage);
+
+        this->owner_ = nullptr;
+
+        this->setDelay(2.0f);
+        this->setFadeouttime(0.5f);
+    }
+
+    void KillMessage::killmessage(const GametypeInfo* gtinfo, const std::string& message)
+    {
+        if (this->owner_ && this->owner_->getGametypeInfo() == gtinfo)
+            this->setCaption(message);
+    }
+
+    void KillMessage::changedOwner()
+    {
+        SUPER(KillMessage, changedOwner);
+
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/KillMessage.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/KillMessage.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/KillMessage.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _KillMessage_H__
+#define _KillMessage_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "interfaces/GametypeMessageListener.h"
+#include "overlays/FadeoutText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport KillMessage : public FadeoutText, public GametypeMessageListener
+    {
+        public:
+            KillMessage(Context* context);
+            virtual ~KillMessage() {}
+
+            virtual void changedOwner() override;
+
+            virtual void killmessage(const GametypeInfo* gtinfo, const std::string& message) override;
+
+        private:
+            PlayerInfo* owner_;
+    };
+}
+#endif /* _KillMessage_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastManStandingInfos.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastManStandingInfos.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastManStandingInfos.cc	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "LastManStandingInfos.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "gametypes/LastManStanding.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(LastManStandingInfos);
+
+    LastManStandingInfos::LastManStandingInfos(Context* context) : OverlayText(context)
+    {
+        RegisterObject(LastManStandingInfos);
+
+        this->lms_ = nullptr;
+        this->player_ = nullptr;
+        this->bShowLives_ = false;
+        this->bShowPlayers_ = false;
+    }
+
+    LastManStandingInfos::~LastManStandingInfos()
+    {
+    }
+
+    void LastManStandingInfos::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(LastManStandingInfos, XMLPort, xmlelement, mode);
+
+        XMLPortParam(LastManStandingInfos, "showlives",     setShowLives,     getShowLives,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(LastManStandingInfos, "showplayers",     setShowPlayers,     getShowPlayers,     xmlelement, mode).defaultValues(false);
+    }
+
+    void LastManStandingInfos::tick(float dt)
+    {
+        SUPER(LastManStandingInfos, tick, dt);
+
+        if (this->player_ && this->lms_)
+        {
+            if (this->bShowLives_)
+            {
+                const std::string& lives = multi_cast<std::string>(this->lms_->playerGetLives(this->player_));
+                this->setCaption(lives);
+            }
+            else if(this->bShowPlayers_)
+            {
+                const std::string& players = multi_cast<std::string>(this->lms_->getNumPlayersAlive());
+                this->setCaption(players);
+            }
+        }
+    }
+
+    void LastManStandingInfos::changedOwner()
+    {
+        SUPER(LastManStandingInfos, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->player_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+            this->lms_ = orxonox_cast<LastManStanding*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->player_ = nullptr;
+            this->lms_ = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastManStandingInfos.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastManStandingInfos.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastManStandingInfos.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#ifndef _LastManStandingInfos_H__
+#define _LastManStandingInfos_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport LastManStandingInfos : public OverlayText, public Tickable
+    {
+        public:
+            LastManStandingInfos(Context* context);
+            virtual ~LastManStandingInfos();
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowLives(bool value)
+                { this->bShowLives_ = value; }
+            inline bool getShowLives() const
+                { return this->bShowLives_; }
+
+            inline void setShowPlayers(bool value)
+                { this->bShowPlayers_ = value; }
+            inline bool getShowPlayers() const
+                { return this->bShowPlayers_; }
+
+        private:
+            LastManStanding* lms_;
+            PlayerInfo* player_;
+            bool bShowLives_;
+            bool bShowPlayers_;
+    };
+}
+#endif /* _LastManStandingInfos_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastTeamStandingInfos.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastTeamStandingInfos.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastTeamStandingInfos.cc	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      
+ *
+ */
+
+#include "LastTeamStandingInfos.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "gametypes/LastTeamStanding.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(LastTeamStandingInfos);
+
+    LastTeamStandingInfos::LastTeamStandingInfos(Context* context) : OverlayText(context)
+    {
+        RegisterObject(LastTeamStandingInfos);
+
+        this->lts_ = nullptr;
+        this->player_ = nullptr;
+        this->bShowLives_ = false;
+        this->bShowTeams_ = false;
+    }
+
+    LastTeamStandingInfos::~LastTeamStandingInfos()
+    {
+    }
+
+    void LastTeamStandingInfos::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(LastTeamStandingInfos, XMLPort, xmlelement, mode);
+
+        XMLPortParam(LastTeamStandingInfos, "showlives",     setShowLives,     getShowLives,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(LastTeamStandingInfos, "showTeams",     setShowTeams,     getShowTeams,     xmlelement, mode).defaultValues(false);
+    }
+
+    void LastTeamStandingInfos::tick(float dt)
+    {
+        SUPER(LastTeamStandingInfos, tick, dt);
+
+        if (this->player_ && this->lts_)
+        {
+            if (this->bShowLives_)
+            {
+                const std::string& lives = multi_cast<std::string>(this->lts_->playerGetLives(this->player_));
+                this->setCaption(lives);
+            }
+            else if(this->bShowTeams_)
+            {
+                const std::string& Teams = multi_cast<std::string>(this->lts_->getNumTeamsAlive());
+                this->setCaption(Teams);
+            }
+        }
+    }
+
+    void LastTeamStandingInfos::changedOwner()
+    {
+        SUPER(LastTeamStandingInfos, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+        {
+            this->player_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+            this->lts_ = orxonox_cast<LastTeamStanding*>(this->getOwner()->getGametype());
+        }
+        else
+        {
+            this->player_ = nullptr;
+            this->lts_ = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastTeamStandingInfos.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastTeamStandingInfos.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/LastTeamStandingInfos.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      
+ *
+ */
+
+#ifndef _LastTeamStandingInfos_H__
+#define _LastTeamStandingInfos_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport LastTeamStandingInfos : public OverlayText, public Tickable
+    {
+        public:
+            LastTeamStandingInfos(Context* context);
+            virtual ~LastTeamStandingInfos();
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowLives(bool value)
+                { this->bShowLives_ = value; }
+            inline bool getShowLives() const
+                { return this->bShowLives_; }
+
+            inline void setShowTeams(bool value)
+                { this->bShowTeams_ = value; }
+            inline bool getShowTeams() const
+                { return this->bShowTeams_; }
+
+        private:
+            LastTeamStanding* lts_;
+            PlayerInfo* player_;
+            bool bShowLives_;
+            bool bShowTeams_;
+    };
+}
+#endif /* _LastTeamStandingInfos_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/PauseNotice.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/PauseNotice.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/PauseNotice.cc	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PauseNotice.h"
+
+#include "core/CoreIncludes.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(PauseNotice);
+
+    PauseNotice::PauseNotice(Context* context) : OverlayText(context)
+    {
+        RegisterObject(PauseNotice);
+
+        this->owner_ = nullptr;
+    }
+
+    void PauseNotice::changedOwner()
+    {
+        SUPER(PauseNotice, changedOwner);
+
+        this->owner_ = orxonox_cast<PlayerInfo*>(this->getOwner());
+    }
+
+    void PauseNotice::changedTimeFactor(float factor_new, float factor_old)
+    {
+        if (factor_new == 0)
+            this->setCaption("Paused");
+        else
+            this->setCaption("");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/PauseNotice.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/PauseNotice.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/PauseNotice.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PauseNotice_H__
+#define _PauseNotice_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/TimeFactorListener.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport PauseNotice : public OverlayText, public TimeFactorListener
+    {
+        public:
+            PauseNotice(Context* context);
+
+            virtual void changedOwner() override;
+
+        protected:
+            virtual void changedTimeFactor(float factor_new, float factor_old) override;
+
+        private:
+            PlayerInfo* owner_;
+    };
+}
+#endif /* _PauseNotice_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/StoryModeHUD.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/StoryModeHUD.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/StoryModeHUD.cc	(revision 11817)
@@ -0,0 +1,198 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   
+ *   This HUD is used for the implementation of the campaign map.
+ *   So far it can only be used to give names to an object planet.
+ *
+ *   Author:
+ *      Nikola Bolt
+ *   Co-authors:
+ *      Claudio Fanconi
+ */
+
+
+// Header file of this cc file
+#include "StoryModeHUD.h"
+
+// Ogre stuff
+#include <OgreCamera.h>
+#include <OgreFontManager.h>
+#include <OgreOverlayManager.h>
+#include <OgreTextAreaOverlayElement.h>
+#include <OgrePanelOverlayElement.h>
+
+// Other stuff
+#include <typeinfo>
+
+#include "util/Convert.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "CameraManager.h"
+#include "graphics/Camera.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/WorldEntity.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "tools/TextureGenerator.h"
+#include "controllers/NewHumanController.h"
+
+#include "worldentities/NameableStaticEntity.h"
+
+namespace orxonox
+{
+    RegisterClass ( StoryModeHUD );
+
+    // Constructor of the StoryMode HUD
+    StoryModeHUD::StoryModeHUD(Context* context) : OrxonoxOverlay(context)
+    {
+        RegisterObject(StoryModeHUD);
+
+        this->textSize_ = 1.0;
+    }
+
+    // Destructor of the StoryMode HUD
+    StoryModeHUD::~StoryModeHUD()
+    {
+        for(Ogre::TextAreaOverlayElement* text : texts)
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(text);
+    }
+
+    // Functions of the StoryMode HUD
+
+    // XML Port for Level construction.
+    void StoryModeHUD::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(StoryModeHUD, XMLPort, xmlelement, mode);
+
+        XMLPortParam(StoryModeHUD, "font", setFont, getFont, xmlelement, mode);
+        XMLPortParam(StoryModeHUD, "textSize", setTextSize, getTextSize, xmlelement, mode);
+    }
+
+    void StoryModeHUD::initialize(){
+        firstTick = false;
+        // Scales used for dimensions and text size
+        float xScale = this->getActualSize().x;
+        float yScale = this->getActualSize().y;
+
+        //Sets the Camera angle at 30 degrees above it, so levels can be seen better    
+        CameraManager::getInstance().getActiveCamera()->setOrientation(Vector3::UNIT_X, Degree(-30));
+
+        for(NameableStaticEntity* planet : ObjectList<NameableStaticEntity>()){
+
+
+            Ogre::TextAreaOverlayElement* text = static_cast<Ogre::TextAreaOverlayElement*>( Ogre::OverlayManager::getSingleton()
+                    .createOverlayElement("TextArea", "StoryModeHUD_navText_" + getUniqueNumberString()));
+
+            texts.push_back(text);
+            text->setDimensions(xScale, yScale);
+
+            //font name of the text needs to be set here, not in the xml setter function
+            text->setFontName(this->fontName_);
+            text->setCharHeight(this->textSize_ * yScale);
+
+            //set text
+            text->setCaption(planet->getLevelName());
+
+            text->hide();
+        
+            this->background_->addChild(text);
+        }
+    }
+
+    // Set the Font of this HUD.
+    void StoryModeHUD::setFont(const std::string& font)
+    {
+        const Ogre::ResourcePtr& fontPtr = Ogre::FontManager::getSingleton().getByName(font);
+        if (fontPtr.isNull())
+        {
+            this->fontName_ = "Monofur";
+            orxout(internal_warning) << "StoryModeHUD: Font '" << font << "' not found. Font has been set to Monofur." << endl;
+            return;
+        }
+        this->fontName_ = font;
+    }
+   
+    // Gets the Font of this HUD    
+    const std::string& StoryModeHUD::getFont() const
+    {
+        return this->fontName_;
+    }
+
+    // Set the size of the Text
+    void StoryModeHUD::setTextSize(float size)
+    {
+        if (size <= 0.0f)
+        {
+            this->textSize_ = 0.05f;
+            orxout(internal_warning) << "StoryModeHUD: Non positive font size not allowed. Font size has been set to 0.05" << endl;
+            return;
+        }
+        this->textSize_ = size;
+        
+    }
+
+    // returns the Size of the Text
+    float StoryModeHUD::getTextSize() const
+    {
+        return this->textSize_;
+    }
+
+    // Tick: this is the most important function. It's recalled every frame and makes sure things happen on the screen.
+    void StoryModeHUD::tick(float dt)
+    {
+        SUPER(StoryModeHUD, tick, dt);
+
+        if(firstTick)
+            this->initialize();
+
+        // cam is the pointer which represents your camera
+        Camera* cam = CameraManager::getInstance().getActiveCamera();
+        if (cam == nullptr)
+            return;
+
+        // camTransform is a Matrix, which converts 3D world of the game into 2D on your screen
+        const Matrix4& camTransform = cam->getOgreCamera()->getProjectionMatrix() * cam->getOgreCamera()->getViewMatrix();
+
+        size_t i = 0;
+        for(NameableStaticEntity* planet : ObjectList<NameableStaticEntity>()){
+            if (i >= texts.size()) {
+                break;
+            }
+            Ogre::TextAreaOverlayElement* text = texts[i];
+            i++;
+
+            // Transform to screen coordinates
+            Vector3 pos = camTransform * planet->getWorldPosition();
+
+            // If you fly passed the description, it gets out of sight
+            if (!(pos.z > 1.0)){
+                    
+                // Position text
+                text->setLeft((pos.x+1)/2); // The (0,0) Coordinate is in the upper left corner.
+                text->setTop((-pos.y+1)/2);  // With those two calculations we set the desired positions
+
+                // Make sure the overlays are shown
+                text->show();
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/StoryModeHUD.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/StoryModeHUD.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/StoryModeHUD.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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.  S
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Nikola Bolt
+ *   Co-authors:
+ *      Claudio Fanconi
+ *
+ */
+
+#ifndef _StoryModeHUD_H__
+#define _StoryModeHUD_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <map>
+#include <string>
+
+#include "util/OgreForwardRefs.h"
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport StoryModeHUD : public OrxonoxOverlay, public Tickable
+    {
+    public:
+            StoryModeHUD(Context* context);
+            virtual ~StoryModeHUD();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+        private:
+            void initialize();
+
+            void setTextSize(float size);
+            float getTextSize() const;
+
+            void setFont(const std::string& font);
+            const std::string& getFont() const;
+
+            std::vector<Ogre::TextAreaOverlayElement*> texts;
+            std::string fontName_;
+            float textSize_;
+            bool firstTick = true;
+   
+    };
+}
+
+#endif /* _StoryModeHUD_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/TeamBaseMatchScore.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/TeamBaseMatchScore.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/TeamBaseMatchScore.cc	(revision 11817)
@@ -0,0 +1,124 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TeamBaseMatchScore.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "gametypes/TeamBaseMatch.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterClass(TeamBaseMatchScore);
+
+    TeamBaseMatchScore::TeamBaseMatchScore(Context* context) : OverlayText(context)
+    {
+        RegisterObject(TeamBaseMatchScore);
+
+        this->owner_ = nullptr;
+
+        this->bShowBases_ = false;
+        this->bShowScore_ = false;
+        this->bShowLeftTeam_ = false;
+        this->bShowRightTeam_ = false;
+    }
+
+    TeamBaseMatchScore::~TeamBaseMatchScore()
+    {
+    }
+
+    void TeamBaseMatchScore::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TeamBaseMatchScore, XMLPort, xmlelement, mode);
+
+        XMLPortParam(TeamBaseMatchScore, "showbases",     setShowBases,     getShowBases,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(TeamBaseMatchScore, "showscore",     setShowScore,     getShowScore,     xmlelement, mode).defaultValues(false);
+        XMLPortParam(TeamBaseMatchScore, "showleftteam",  setShowLeftTeam,  getShowLeftTeam,  xmlelement, mode).defaultValues(false);
+        XMLPortParam(TeamBaseMatchScore, "showrightteam", setShowRightTeam, getShowRightTeam, xmlelement, mode).defaultValues(false);
+    }
+
+    void TeamBaseMatchScore::tick(float dt)
+    {
+        SUPER(TeamBaseMatchScore, tick, dt);
+
+        if (this->owner_)
+        {
+            const std::string& bases1 = '(' + multi_cast<std::string>(this->owner_->getTeamBases(0)) + ')';
+            const std::string& bases2 = '(' + multi_cast<std::string>(this->owner_->getTeamBases(1)) + ')';
+
+            const std::string& score1 = multi_cast<std::string>(this->owner_->getTeamPoints(0));
+            const std::string& score2 = multi_cast<std::string>(this->owner_->getTeamPoints(1));
+
+            std::string output1;
+            if (this->bShowLeftTeam_)
+            {
+                if (this->bShowBases_ && this->bShowScore_)
+                    output1 = bases1 + " - " + score1;
+                else if (this->bShowScore_)
+                    output1 = score1;
+                else if (this->bShowBases_)
+                    output1 = bases1;
+            }
+
+            std::string output2;
+            if (this->bShowRightTeam_)
+            {
+                if (this->bShowBases_ && this->bShowScore_)
+                    output2 = score2 + " - " + bases2;
+                else if (this->bShowScore_)
+                    output2 = score2;
+                else if (this->bShowBases_)
+                    output2 = bases2;
+            }
+
+            std::string output;
+            if (this->bShowBases_ || this->bShowScore_)
+            {
+                if (this->bShowLeftTeam_ && this->bShowRightTeam_)
+                    output = output1 + ':' + output2;
+                else if (this->bShowLeftTeam_ || this->bShowRightTeam_)
+                    output = output1 + output2;
+            }
+
+            this->setCaption(output);
+        }
+    }
+
+
+    void TeamBaseMatchScore::changedOwner()
+    {
+        SUPER(TeamBaseMatchScore, changedOwner);
+
+        if (this->getOwner() && this->getOwner()->getGametype())
+            this->owner_ = orxonox_cast<TeamBaseMatch*>(this->getOwner()->getGametype());
+        else
+            this->owner_ = nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/hud/TeamBaseMatchScore.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/hud/TeamBaseMatchScore.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/hud/TeamBaseMatchScore.h	(revision 11817)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamBaseMatchScore_H__
+#define _TeamBaseMatchScore_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _OverlaysExport TeamBaseMatchScore : public OverlayText, public Tickable
+    {
+        public:
+            TeamBaseMatchScore(Context* context);
+            virtual ~TeamBaseMatchScore();
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setShowBases(bool value)
+                { this->bShowBases_ = value; }
+            inline bool getShowBases() const
+                { return this->bShowBases_; }
+
+            inline void setShowScore(bool value)
+                { this->bShowScore_ = value; }
+            inline bool getShowScore() const
+                { return this->bShowScore_; }
+
+            inline void setShowLeftTeam(bool value)
+                { this->bShowLeftTeam_ = value; }
+            inline bool getShowLeftTeam() const
+                { return this->bShowLeftTeam_; }
+
+            inline void setShowRightTeam(bool value)
+                { this->bShowRightTeam_ = value; }
+            inline bool getShowRightTeam() const
+                { return this->bShowRightTeam_; }
+
+        private:
+            TeamBaseMatch* owner_;
+            bool bShowBases_;
+            bool bShowScore_;
+            bool bShowLeftTeam_;
+            bool bShowRightTeam_;
+    };
+}
+#endif /* _TeamBaseMatchScore_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,5 @@
+ADD_SOURCE_FILES(OVERLAYS_SRC_FILES
+  CreateLines.cc
+  Scoreboard.cc
+  Stats.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/CreateLines.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/CreateLines.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/CreateLines.cc	(revision 11817)
@@ -0,0 +1,140 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Hildebrandt
+ *
+ */
+
+#include "CreateLines.h"
+
+#include "overlays/OverlayText.h"
+#include "overlays/stats/Stats.h"
+
+namespace orxonox
+{
+    /**
+        @brief Constructor: Creates a line.
+    */
+    CreateLines::CreateLines(float leftOffset, float topOffset, float width, float height)
+    {
+        playerNameText_ = new OverlayText(nullptr);
+        playerNameText_->setTextSize(0.04f);
+        playerNameText_->setColour(ColourValue(0.0f, 0.75f, 0.2f, 1.0f));
+        playerNameText_->setPosition(Vector2(0.1f, topOffset + 0.01f));
+
+        scoreText_ = new OverlayText(nullptr);
+        scoreText_->setTextSize(0.04f);
+        scoreText_->setColour(ColourValue(0.0f, 0.75f, 0.2f, 1.0f));
+        scoreText_->setPosition(Vector2(0.6f, topOffset + 0.01f));
+
+        deathsText_ = new OverlayText(nullptr);
+        deathsText_->setTextSize(0.04f);
+        deathsText_->setColour(ColourValue(0, 0.75f, 0.2f, 1.0f));
+        deathsText_->setPosition(Vector2(0.8f, topOffset + 0.01f));
+
+        background_ = new Stats(nullptr);
+        background_->setPosition(Vector2(leftOffset, topOffset));
+        background_->setSize(Vector2(width, height));
+    }
+
+    CreateLines::~CreateLines()
+    {
+        this->playerNameText_->destroy();
+        this->scoreText_->destroy();
+        this->deathsText_->destroy();
+        this->background_->destroy();
+    }
+
+    void CreateLines::setPlayerName(const std::string& str)
+    {
+        this->playerNameText_->setCaption(str);
+    }
+
+    void CreateLines::setScore(const std::string& str)
+    {
+        this->scoreText_->setCaption(str);
+    }
+
+    void CreateLines::setDeaths(const std::string& str)
+    {
+        this->deathsText_->setCaption(str);
+    }
+
+    void CreateLines::setVisibility(bool visible)
+    {
+        this->scoreText_->setVisible(visible);
+        this->deathsText_->setVisible(visible);
+        this->playerNameText_->setVisible(visible);
+        this->background_->setVisible(visible);
+    }
+    void CreateLines::changedVisibility()
+    {
+        this->scoreText_->changedVisibility();
+        this->deathsText_->changedVisibility();
+        this->playerNameText_->changedVisibility();
+        this->background_->changedVisibility();
+    }
+
+    void CreateLines::setOverlayGroup( OverlayGroup* group )
+    {
+        this->scoreText_->setOverlayGroup( group );
+        this->deathsText_->setOverlayGroup( group );
+        this->playerNameText_->setOverlayGroup( group );
+        this->background_->setOverlayGroup( group );
+    }
+
+    /**
+        @brief Ensures that the number of OverlayElements is equal to numberOfColumns.
+    */
+    //void CreateLines::setNumberOfColumns(unsigned int numberOfColumns, unsigned int lineIndex) {
+
+    //    Ogre::OverlayManager* ovMan = Ogre::OverlayManager::getSingletonPtr();
+
+    //    unsigned int colIndex = 0;
+
+    //    while (textColumns_.size() < numberOfColumns)
+    //    {
+    //        Ogre::TextAreaOverlayElement* tempTextArea = static_cast<Ogre::TextAreaOverlayElement*>(ovMan->createOverlayElement("TextArea", "StatsLineTextArea" + getName() + multi_cast<std::string>(lineIndex) + multi_cast<std::string>(colIndex)));
+    //        textColumns_.push_back(tempTextArea);
+    //        this->background_->addChild(tempTextArea);
+
+    //        colIndex++;
+    //    }
+
+    //    while (textColumns_.size() > numberOfColumns)
+    //    {
+    //        this->background_->_removeChild(textColumns_.back());
+    //        ovMan->destroyOverlayElement(textColumns_.back());
+    //        textColumns_.pop_back();
+    //    }
+    //}
+
+    //void CreateLines::alignColumn(int columnIndex, float leftOffset, float topOffset)
+    //{
+    //    this->textColumns_[columnIndex]->setPosition(leftOffset, topOffset);
+    //}
+
+    //void CreateLines::setColumnText(int columnIndex, std::string columnText)
+    //{
+    //    this->textColumns_[columnIndex]->setCaption(columnText);
+    //}
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/CreateLines.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/CreateLines.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/CreateLines.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Hildebrandt
+ *
+ */
+
+#ifndef _CreateLines_H__
+#define _CreateLines_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <string>
+
+namespace orxonox
+{
+    class _OverlaysExport CreateLines
+    {
+
+    public: // functions
+        CreateLines(float, float, float, float);
+        virtual ~CreateLines();
+
+        void setPlayerName(const std::string&);
+        void setScore(const std::string&);
+        void setDeaths(const std::string&);
+
+        void setVisibility(bool);
+        void changedVisibility();
+        void setOverlayGroup( OverlayGroup* group );
+
+        //void setNumberOfColumns(unsigned int numberOfColumns, unsigned int lineIndex);
+        //void alignColumn(int columnIndex, float leftOffset, float topOffset);
+        //void setColumnText(int columnIndex, std::string columnText);
+
+    private: // functions
+
+    private: // variables
+        //std::vector<OverlayText*> textColumns_;
+        OverlayText* playerNameText_;
+        OverlayText* scoreText_;
+        OverlayText* deathsText_;
+
+        Stats* background_;
+
+    };
+}
+
+#endif /* _CreateLines_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/Scoreboard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/Scoreboard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/Scoreboard.cc	(revision 11817)
@@ -0,0 +1,132 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Hildebrandt
+ *
+ */
+
+#include "Scoreboard.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "gametypes/Gametype.h"
+#include "infos/PlayerInfo.h"
+#include "CreateLines.h"
+
+namespace orxonox
+{
+    RegisterClass(Scoreboard);
+
+    /**
+        @brief Constructor: Creates the scoreboard.
+    */
+    Scoreboard::Scoreboard(Context* context)
+        : OrxonoxOverlay(context)
+    {
+        RegisterObject(Scoreboard);
+    }
+
+    Scoreboard::~Scoreboard()
+    {
+        while (this->lines_.size() > 0)
+        {
+            // destroy lines
+            delete this->lines_.back();
+            this->lines_.pop_back();
+        }
+    }
+
+    void Scoreboard::changedVisibility()
+    {
+        SUPER(Scoreboard, changedVisibility);
+
+        for (CreateLines* line : this->lines_)
+            line->changedVisibility();
+    }
+
+    /**
+        @brief Prints the scoreboard on the screen.
+    */
+    void Scoreboard::tick(float dt)
+    {
+        const std::map<PlayerInfo*, Player>& playerList = this->getGametype()->getPlayers();
+
+        const float topOffset  = 0.2f;
+        const float leftOffset = 0.075f;
+        const float distance   = 0.01f;
+        const float width      = 0.85f;
+        const float height     = 0.05f;
+        while (playerList.size() > this->lines_.size())
+        {
+            // create new lines
+            CreateLines* lines = new CreateLines(leftOffset, topOffset + (distance + height) * lines_.size(), width, height);
+            lines->setVisibility(this->isVisible());
+            lines->setOverlayGroup( this->getOverlayGroup() );
+            this->lines_.push_back(lines);
+        }
+        while (playerList.size() < this->lines_.size())
+        {
+            // destroy lines
+            delete this->lines_.back();
+            this->lines_.pop_back();
+        }
+
+        // update board
+
+        unsigned int index = 0;
+        for (const auto& mapEntry : playerList)
+        {
+            this->lines_[index]->setPlayerName(multi_cast<std::string>(mapEntry.first->getName()));
+            this->lines_[index]->setScore(multi_cast<std::string>(mapEntry.second.frags_));
+            this->lines_[index]->setDeaths(multi_cast<std::string>(mapEntry.second.killed_));
+            index++;
+        }
+
+        //numberOfColumns = 2;
+        //numberOfLines = 3;
+        //topOffset = 0.1;
+        //lineSpacing = 0.1;
+
+        //for (unsigned int i = 0; i < this->lines_.size(); ++i)
+        //{
+        //    columnIndex = 0;
+        //    leftOffset = 0.1;
+
+        //    this->createlines_->setNumberOfColumns(numberOfColumns, i);
+
+        //    // columnText = this->getGametype()->getPlayersName();
+        //    columnText = "PlayerName";
+        //    this->createlines_->alignColumn(columnIndex, topOffset, leftOffset);
+        //    this->createlines_->setColumnText(columnIndex, columnText);
+
+        //    columnIndex++;
+        //    leftOffset = leftOffset + 0.3;
+
+        //    // columnText = this->getGametype()->getPlayersFrags();
+        //    columnText = "PlayerFrags";
+        //    this->createlines_->alignColumn(columnIndex, topOffset, leftOffset);
+        //    this->createlines_->setColumnText(columnIndex, columnText);
+
+        //    topOffset = topOffset + lineSpacing;
+        //}
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/Scoreboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/Scoreboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/Scoreboard.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Hildebrandt
+ *
+ */
+
+#ifndef _Scoreboard_H__
+#define _Scoreboard_H__
+
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include <string>
+#include <vector>
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport Scoreboard : public OrxonoxOverlay, public Tickable
+    {
+    public: // functions
+        Scoreboard(Context* context);
+        virtual ~Scoreboard();
+
+        virtual void tick(float dt) override;
+
+        inline void setCreateLines(CreateLines* cl)
+            { this->createlines_ = cl; }
+        inline CreateLines* getCreateLines() const
+            { return this->createlines_; }
+
+        virtual void changedVisibility() override;
+
+    private: // functions
+        void printLines();
+
+    private: // variables
+        std::vector<CreateLines*> lines_;
+
+        unsigned int numberOfColumns;
+        unsigned int numberOfLines;
+        unsigned int columnIndex;
+        float topOffset;
+        float leftOffset;
+        float lineSpacing;
+        std::string columnText;
+        CreateLines* createlines_;
+    };
+}
+
+#endif /* _Scoreboard_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/Stats.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/Stats.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/Stats.cc	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Fabian 'x3n' Landau, Benjamin Hildebrandt
+ *
+ */
+
+#include "Stats.h"
+
+#include <string>
+#include <OgreOverlayManager.h>
+#include <OgreBorderPanelOverlayElement.h>
+
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(Stats);
+
+    /**
+        @brief Constructor: Creates and initializes the Stats panel.
+    */
+    Stats::Stats(Context* context)
+        : OrxonoxOverlay(context)
+        , statsOverlayNoise_(nullptr)
+        , statsOverlayBorder_(nullptr)
+    {
+        RegisterObject(Stats);
+
+        this->setConfigValues();
+
+        // create overlay and elements
+        Ogre::OverlayManager* ovMan = Ogre::OverlayManager::getSingletonPtr();
+
+        // create BorderPanel
+        this->statsOverlayBorder_ = static_cast<Ogre::BorderPanelOverlayElement*>(ovMan->createOverlayElement("BorderPanel", "StatsBorderPanel" + getUniqueNumberString()));
+        //this->statsOverlayBorder_->setMaterialName("StatsCenter");
+        this->statsOverlayBorder_->setBorderSize(0.003f, 16.0f * 0.003f);
+        this->statsOverlayBorder_->setBorderMaterialName("StatsBorder");
+        this->statsOverlayBorder_->setTopBorderUV(0.49f, 0.0f, 0.51f, 0.5f);
+        this->statsOverlayBorder_->setTopLeftBorderUV(0.0f, 0.0f, 0.5f, 0.5f);
+        this->statsOverlayBorder_->setTopRightBorderUV(0.5f, 0.0f, 1.0f, 0.5f);
+        this->statsOverlayBorder_->setLeftBorderUV(0.0f, 0.49f, 0.5f, 0.51f);
+        this->statsOverlayBorder_->setRightBorderUV(0.5f, 0.49f, 1.0f, 0.5f);
+        this->statsOverlayBorder_->setBottomBorderUV(0.49f, 0.5f, 0.51f, 1.0f);
+        this->statsOverlayBorder_->setBottomLeftBorderUV(0.0f, 0.5f, 0.5f, 1.0f);
+        this->statsOverlayBorder_->setBottomRightBorderUV(0.5f, 0.5f, 1.0f, 1.0f);
+
+        background_->addChild(statsOverlayBorder_);
+
+        // create noise
+        //this->statsOverlayNoise_ = static_cast<Ogre::PanelOverlayElement*>(ovMan->createOverlayElement("Panel", "StatsNoise" + getUniqueNumberString()));
+        //this->statsOverlayNoise_->setPosition(0,0);
+        //this->statsOverlayNoise_->setMaterialName("StatsNoiseSmall");
+        // comment following line to disable noise
+        //background_->addChild(this->statsOverlayNoise_);
+    }
+
+    Stats::~Stats()
+    {
+        if (this->isInitialized())
+        {
+            Ogre::OverlayManager* ovMan = Ogre::OverlayManager::getSingletonPtr();
+            ovMan->destroyOverlayElement(this->statsOverlayBorder_);
+            //ovMan->destroyOverlayElement(this->statsOverlayNoise_);
+        }
+    }
+
+    /**
+        @brief Sets the config values, describing the size of the Stats panel.
+    */
+    void Stats::setConfigValues()
+    {
+        SetConfigValue(noiseSize_, 1.0f);
+    }
+
+    void Stats::tick(float dt)
+    {
+        // SUPER(Stats, tick, dt);
+
+            // this creates a flickering effect (extracts exactly 80% of the texture at a random location)
+            //float uRand = (rand() & 1023) / 1023.0f * 0.2f;
+            //float vRand = (rand() & 1023) / 1023.0f * 0.2f;
+            //this->statsOverlayNoise_->setUV(uRand, vRand, 7.5f + uRand, 7.5f + vRand);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/overlays/stats/Stats.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/overlays/stats/Stats.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/overlays/stats/Stats.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Fabian 'x3n' Landau, Benjamin Hildebrandt
+ *
+ */
+
+#ifndef _Stats_H__
+#define _Stats_H__
+
+#include "overlays/OverlaysPrereqs.h"
+
+#include "util/OgreForwardRefs.h"
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OrxonoxOverlay.h"
+
+namespace orxonox
+{
+    class _OverlaysExport Stats : public OrxonoxOverlay, public Tickable
+    {
+    public: // functions
+        Stats(Context* context);
+        virtual ~Stats();
+
+        void setConfigValues();
+
+        virtual void tick(float dt) override;
+
+    private: // variables
+        Ogre::PanelOverlayElement* statsOverlayNoise_;
+        Ogre::BorderPanelOverlayElement* statsOverlayBorder_;
+        float noiseSize_;
+    };
+}
+
+#endif /* _Stats_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pickup/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,23 @@
+SET_SOURCE_FILES(PICKUP_SRC_FILES
+  CollectiblePickup.cc
+  Pickup.cc
+  PickupCollection.cc
+  PickupManager.cc
+  PickupRepresentation.cc
+  PickupSpawner.cc
+)
+
+ADD_SUBDIRECTORY(items)
+
+ORXONOX_ADD_LIBRARY(pickup
+  MODULE
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    PickupManager.h
+    PickupRepresentation.h
+  PCH_FILE
+    PickupPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${PICKUP_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/pickup/CollectiblePickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/CollectiblePickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/CollectiblePickup.cc	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CollectiblePickup.cc
+    @brief Implementation of the CollectiblePickup class.
+*/
+
+#include "CollectiblePickup.h"
+
+#include "core/CoreIncludes.h"
+
+#include "PickupCollection.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(CollectiblePickup).inheritsFrom<Pickupable>();
+
+    /**
+    @brief
+        Constructor.
+        Registers the object and initializes variables.
+    */
+    CollectiblePickup::CollectiblePickup() : collection_(nullptr)
+    {
+        RegisterObject(CollectiblePickup);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    CollectiblePickup::~CollectiblePickup()
+    {
+        if (this->isInCollection())
+            this->collection_->removePickupable(this);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
+    void CollectiblePickup::changedUsed(void)
+    {
+        SUPER(CollectiblePickup, changedUsed);
+
+        if(this->isInCollection())
+            this->collection_->pickupChangedUsed(this->isUsed());
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from picked up to dropped or the other way around.
+    */
+    void CollectiblePickup::changedPickedUp(void)
+    {
+        SUPER(CollectiblePickup, changedPickedUp);
+
+        if(this->isInCollection())
+            this->collection_->pickupChangedPickedUp(this->isPickedUp());
+    }
+
+    /**
+    @brief
+        Notifies this CollectiblePickup that it was added to a PickupCollection.
+    @param collection
+        A pointer to the PickupCollection to which the CollectiblePickup should be added.
+    */
+    void CollectiblePickup::wasAddedToCollection(PickupCollection* collection)
+    {
+        this->collection_ = collection;
+    }
+
+    /**
+    @brief
+        Notifies this CollectiblePickup that it was removed from its PickupCollection.
+    */
+    void CollectiblePickup::wasRemovedFromCollection(void)
+    {
+        this->collection_ = nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/CollectiblePickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/CollectiblePickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/CollectiblePickup.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CollectiblePickup.h
+    @brief Definition of the CollectiblePickup class.
+    @ingroup Pickup
+*/
+
+#ifndef _CollectiblePickup_H__
+#define _CollectiblePickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include "interfaces/Pickupable.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        The CollectiblePickup class encompasses all @ref orxonox::Pickupable "Pickupables" that can be added to a @ref orxonox::PickupCollection "PickupCollection" and thus be part of such.
+
+        All you need to do to make your @ref orxonox::Pickupable "Pickupable" a CollectiblePickup is to, in some way, inherit from it. (The @ref orxonox::Pickup "Pickup" class, for example, is already a CollectiblePickup).
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _PickupExport CollectiblePickup : public Pickupable
+    {
+        friend class PickupCollection;
+
+        public:
+            CollectiblePickup(); //!< Constructor.
+            virtual ~CollectiblePickup(); //! Destructor.
+
+            virtual void changedUsed(void) override; //!< Is called when the pickup has transited from used to unused or the other way around.
+            virtual void changedPickedUp(void) override; //!< Is called when the pickup has transited from picked up to dropped or the other way around.
+
+            /**
+            @brief Check whether the given CollectiblePickup is par of a PickupCollection.
+            @return Returns true if the CollectiblePickup is part of a PickupCollection.
+            */
+            bool isInCollection(void) const
+                { return this->collection_ != nullptr; }
+
+        private:
+            void wasAddedToCollection(PickupCollection* collection);
+            void wasRemovedFromCollection(void);
+
+            PickupCollection* collection_; //!< A pointer to the PickupCollection this CollectiblePickup is in.
+    };
+}
+
+#endif // _CollectiblePickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/Pickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/Pickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/Pickup.cc	(revision 11817)
@@ -0,0 +1,191 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file Pickup.cc
+    @brief Implementation of the Pickup class.
+*/
+
+#include "Pickup.h"
+
+#include "core/CoreIncludes.h"
+#include "util/StringUtils.h"
+
+#include "PickupSpawner.h"
+
+namespace orxonox
+{
+
+    //! Initializing the static strings.
+    /*static*/ const std::string Pickup::activationTypeImmediate_s = "immediate";
+    /*static*/ const std::string Pickup::activationTypeOnUse_s = "onUse";
+    /*static*/ const std::string Pickup::durationTypeOnce_s = "once";
+    /*static*/ const std::string Pickup::durationTypeContinuous_s = "continuous";
+
+    RegisterUnloadableClass(Pickup);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Pickup::Pickup(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Pickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    Pickup::~Pickup()
+    {
+
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void Pickup::initialize(void)
+    {
+        this->activationType_ = PickupActivationType::immediate;
+        this->durationType_ = PickupDurationType::once;
+    }
+
+    /**
+    @brief
+        Method for creating a Pickup object through XML.
+    */
+    void Pickup::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Pickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Pickup, "representation", setRepresentationName, getRepresentationName, xmlelement, mode);
+        XMLPortParam(Pickup, "activationType", setActivationTypeAsString, getActivationTypeAsString, xmlelement, mode);
+        XMLPortParam(Pickup, "durationType", setDurationTypeAsString, getDurationTypeAsString, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Get the activation type of the pickup.
+    @return
+        Returns a string containing the activation type.
+    */
+    const std::string& Pickup::getActivationTypeAsString(void) const
+    {
+        switch(this->getActivationType())
+        {
+            case PickupActivationType::immediate:
+                return activationTypeImmediate_s;
+            case PickupActivationType::onUse:
+                return activationTypeOnUse_s;
+            default:
+                return BLANKSTRING;
+        }
+    }
+
+    /**
+    @brief
+        Get the duration type of the pickup.
+    @return
+        Returns a string containing the duration type.
+    */
+    const std::string& Pickup::getDurationTypeAsString(void) const
+    {
+        switch(this->getDurationType())
+        {
+            case PickupDurationType::once:
+                return durationTypeOnce_s;
+            case PickupDurationType::continuous:
+                return durationTypeContinuous_s;
+            default:
+                return BLANKSTRING;
+        }
+    }
+
+    /**
+    @brief
+        Set the activation type of the Pickup.
+    @param type
+        The activation type of the Pickup as a string.
+    */
+    void Pickup::setActivationTypeAsString(const std::string& type)
+    {
+        if(type == Pickup::activationTypeImmediate_s)
+            this->setActivationType(PickupActivationType::immediate);
+        else if(type == Pickup::activationTypeOnUse_s)
+            this->setActivationType(PickupActivationType::onUse);
+        else
+            orxout(internal_error, context::pickups) << "Invalid activationType '" << type << "' in " << this->getIdentifier()->getName() << "." << endl;
+    }
+
+    /**
+    @brief
+        Set the duration type of the Pickup.
+    @param type
+        The duration type of the Pickup as a string.
+    */
+    void Pickup::setDurationTypeAsString(const std::string& type)
+    {
+        if(type == Pickup::durationTypeOnce_s)
+            this->setDurationType(PickupDurationType::once);
+        else if(type == Pickup::durationTypeContinuous_s)
+            this->setDurationType(PickupDurationType::continuous);
+        else
+            orxout(internal_error, context::pickups) << "Invalid durationType '" << type << "' in " << this->getIdentifier()->getName() << "." << endl;
+    }
+
+    /**
+    @brief
+        Should be called when the pickup has transited from picked up to dropped or the other way around.
+        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedPickedUp); to their changedPickedUp method.
+    */
+    void Pickup::changedPickedUp(void)
+    {
+        SUPER(Pickup, changedPickedUp);
+
+        // Sets the Pickup to used if the Pickup has activation type 'immediate' and gets picked up.
+        if(this->isPickedUp() && this->isImmediate())
+            this->setUsed(true);
+    }
+
+    /**
+    @brief
+        Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
+    @return
+        Returns true if a spawner was created, false if not.
+    */
+    bool Pickup::createSpawner(void)
+    {
+        PickupSpawner::createDroppedPickup(this->getContext(), this, this->getCarrier());
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/Pickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/Pickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/Pickup.h	(revision 11817)
@@ -0,0 +1,187 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file Pickup.h
+    @brief Declaration of the Pickup class.
+    @ingroup Pickup
+*/
+
+#ifndef _Pickup_H__
+#define _Pickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "core/XMLPort.h"
+#include "tools/Timer.h"
+
+#include "CollectiblePickup.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Enum for the @ref orxonox::Pickup "Pickup" activation type.
+
+    @ingroup Pickup
+    */
+    enum class PickupActivationType
+    {
+        immediate, //!< Means that the @ref orxonox::Pickup "Pickup" will be used immediately after pickup.
+        onUse, //!< Means that the @ref orxonox::Pickup "Pickup" will be used at a later point trough some external influence.
+    };
+
+    /**
+    @brief
+        Enum for the @ref orxonox::Pickup "Pickup" duration type.
+
+    @ingroup Pickup
+    */
+    enum class PickupDurationType
+    {
+        once, //!< Means that the @ref orxonox::Pickup "Pickup" will be used only once at a singular time instant.
+        continuous, //!< Means that the @ref orxonox::Pickup "Pickup" will be used over a continuous timespan.
+    };
+
+    /**
+    @brief
+        The Pickup class offers (useful) base functionality for a wide range of pickups.
+
+        Pickups inheriting from this class can choose an activation type and a duration type.
+        - The <b>activationType</b> deals with what happens to the Pickup as soon as it is picked up. It can either be set to <em>immediate</em>, which means that the Pickup is activated/used immediately upon being picked up. Or to <em>onUse</em>, which means, that the Pickup will be activated/used if some outside entity (most commonly the player through the PickupInventory) decides to use it. Default is <em>immediate</em>.
+        - The <b>durationType</b> deals with whether the Pickup has a continuous effect or whether its effect is focused on a singular instant. It can either be set to <em>once</em>, which means, that the Pickup just has an effect (at a singular instant in time) and is done once that effect has been applied. Or to <em>continuous</em>, which means that the effect of the Pickup unfolds over some timespan. Default is <em>once</em>.
+
+        If it were not an abstract class it could for example be used as follows in XML.
+        @code
+        <Pickup activationType="onUse" durationType="continuous" />
+        @endcode
+        In reality you can (naturally) use the parameters <b>activation type</b> and <b>duration type</b> in any pickup inheriting from Pickup, unless the pickup already specifies one (or both) of the parameters.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _PickupExport Pickup : public CollectiblePickup, public BaseObject
+    {
+
+        public:
+            Pickup(Context* context); //!< Constructor.
+            virtual ~Pickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual const std::string& getRepresentationName() const override
+                { return this->representationName_; }
+
+            /**
+            @brief Get the activation type of the Pickup.
+            @return Returns the activation type of the Pickup.
+            */
+            inline PickupActivationType getActivationType(void) const
+                { return this->activationType_; }
+            /**
+            @brief Get the duration type of the Pickup.
+            @return Returns the duration type of the Pickup.
+            */
+            inline PickupDurationType getDurationType(void) const
+                { return this->durationType_; }
+
+            const std::string& getActivationTypeAsString(void) const; //!< Get the activation type of the Pickup.
+            const std::string& getDurationTypeAsString(void) const; //!< Get the duration type of the Pickup.
+
+            /**
+            @brief Get whether the activation type is 'immediate'.
+            @return Returns true if the activation type is 'immediate'.
+            */
+            inline bool isImmediate(void) const
+                { return this->getActivationType() == PickupActivationType::immediate; }
+            /**
+            @brief Get whether the activation type is 'onUse'.
+            @return Returns true if the activation type is 'onUse'.
+            */
+            inline bool isOnUse(void) const
+                { return this->getActivationType() == PickupActivationType::onUse; }
+            /**
+            @brief Get whether the duration type is 'once'.
+            @return Returns true if the duration type is 'once'.
+            */
+            inline bool isOnce(void) const
+                { return this->getDurationType() == PickupDurationType::once; }
+            /**
+            @brief Get whether the duration type is 'continuous'.
+            @return Returns true if the duration type is 'continuous'.
+            */
+            inline bool isContinuous(void) const
+                { return this->getDurationType() == PickupDurationType::continuous; }
+
+            virtual void changedPickedUp(void) override; //!< Should be called when the pickup has transited from picked up to dropped or the other way around.
+
+        protected:
+            virtual bool createSpawner(void) override; //!< Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
+
+            /**
+            @brief Sets the representation name which refers to the name of the PickupRepresentation that is used to represent this pickup.
+            */
+            inline void setRepresentationName(const std::string& name)
+                { this->representationName_ = name; }
+
+            /**
+            @brief Set the activation type of the Pickup.
+            @param type The activation type of the Pickup.
+            */
+            inline void setActivationType(PickupActivationType type)
+                { this->activationType_ = type; }
+            /**
+            @brief Set the duration type of the Pickup.
+            @param type The duration type of the Pickup.
+            */
+            inline void setDurationType(PickupDurationType type)
+                { this->durationType_ = type; }
+
+            void setActivationTypeAsString(const std::string& type); //!< Set the activation type of the Pickup.
+            void setDurationTypeAsString(const std::string& type); //!< Set the duration type of the Pickup.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+
+            std::string representationName_; //!< The name of the associated PickupRepresentation.
+            PickupActivationType activationType_; //!< The activation type of the Pickup.
+            PickupDurationType durationType_; //!< The duration type of the Pickup.
+
+            //! Strings for the activation and duration types.
+            static const std::string activationTypeImmediate_s;
+            static const std::string activationTypeOnUse_s;
+            static const std::string durationTypeOnce_s;
+            static const std::string durationTypeContinuous_s;
+    };
+
+}
+#endif // _Pickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupCollection.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupCollection.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupCollection.cc	(revision 11817)
@@ -0,0 +1,332 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PickupCollection.cc
+    @brief Implementation of PickupCollection.
+*/
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "interfaces/PickupCarrier.h"
+
+#include "CollectiblePickup.h"
+#include "PickupSpawner.h"
+
+#include "PickupCollection.h"
+
+namespace orxonox
+{
+
+    RegisterClass(PickupCollection);
+
+    /**
+    @brief
+        Default Constructor.
+    */
+    PickupCollection::PickupCollection(Context* context) : BaseObject(context)
+    {
+        RegisterObject(PickupCollection);
+
+        this->processingUsed_ = false;
+        this->processingPickedUp_ = false;
+    }
+
+    /**
+    @brief
+        Destructor. Iterates through all Pickupables this PickupCollection consists of and destroys them if they haven't been already.
+    */
+    PickupCollection::~PickupCollection()
+    {
+        // Destroy all Pickupables constructing this PickupCollection.
+        for(CollectiblePickup* pickup : this->pickups_)
+        {
+            pickup->wasRemovedFromCollection();
+            pickup->destroy();
+        }
+        this->pickups_.clear();
+    }
+
+    /**
+    @brief
+        Creates an instance of this Class through XML.
+    */
+    void PickupCollection::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PickupCollection, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PickupCollection, "representation", setRepresentationName, getRepresentationName, xmlelement, mode);
+        XMLPortObject(PickupCollection, CollectiblePickup, "pickupables", addPickupable, getPickupable, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedUsed); to their changdeUsed method.
+    */
+    void PickupCollection::changedUsed(void)
+    {
+        SUPER(PickupCollection, changedUsed);
+
+        this->processingUsed_ = true;
+        // Change used for all Pickupables this PickupCollection consists of.
+        for(CollectiblePickup* pickup : this->pickups_)
+            pickup->setUsed(this->isUsed());
+
+        this->processingUsed_ = false;
+
+        this->changedUsedAction();
+    }
+
+    /**
+    @brief
+        Helper method.
+        Checks whether due to changes in the used status of the pickups of this PickupCollection the used status of this PickupCollection has to change as well.
+    */
+    void PickupCollection::changedUsedAction(void)
+    {
+        if(this->processingUsed_)
+            return;
+
+        size_t numPickupsEnabled = 0;
+        size_t numPickupsInUse = 0;
+        for(CollectiblePickup* pickup : this->pickups_)
+        {
+            if (pickup->isEnabled())
+                ++numPickupsEnabled;
+            if (pickup->isUsed())
+                ++numPickupsInUse;
+        }
+
+        // If all the pickups are not in use but the PickupCollection is.
+        if(numPickupsInUse == 0 && this->isUsed())
+            this->setUsed(false);
+
+        // If all the enabled pickups are in use but the PickupCollection is not.
+        if(numPickupsInUse > 0 && numPickupsInUse == numPickupsEnabled && !this->isUsed())
+            this->setUsed(true);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has changed its PickupCarrier.
+        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedCarrier); to their changedCarrier method.
+    */
+    void PickupCollection::changedCarrier(void)
+    {
+        SUPER(PickupCollection, changedCarrier);
+
+        // Change the PickupCarrier for all Pickupables this PickupCollection consists of.
+        for(CollectiblePickup* pickup : this->pickups_)
+        {
+            if(this->getCarrier() == nullptr)
+                pickup->setCarrier(nullptr);
+            else
+                pickup->setCarrier(this->getCarrier()->getTarget(pickup));
+        }
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from picked up to dropped or the other way around.
+        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedPickedUp); to their changedPickedUp method.
+    */
+    void PickupCollection::changedPickedUp()
+    {
+        SUPER(PickupCollection, changedPickedUp);
+
+        this->processingPickedUp_ = true;
+        // Change the pickedUp status for all Pickupables this PickupCollection consists of.
+        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); )
+            (*(it++))->setPickedUp(this->isPickedUp());
+
+        this->processingPickedUp_ = false;
+
+        this->changedPickedUpAction();
+    }
+
+    /**
+    @brief
+        Helper method.
+        Checks whether due to changes in the picked up status of the pickups of this PickupCollection the picked up status of this PickupCollection has to change as well.
+    */
+    void PickupCollection::changedPickedUpAction(void)
+    {
+        if(this->processingPickedUp_)
+            return;
+
+        // If at least all the enabled pickups of this PickupCollection are no longer picked up.
+        bool isOnePickupEnabledAndPickedUp = false;
+        for(CollectiblePickup* pickup : this->pickups_)
+        {
+            if (pickup->isEnabled() && pickup->isPickedUp())
+            {
+                isOnePickupEnabledAndPickedUp = true;
+                break;
+            }
+        }
+        if(!isOnePickupEnabledAndPickedUp && this->isPickedUp())
+            this->Pickupable::destroy();
+    }
+
+    /**
+    @brief
+        Get whether a given class, represented by the input Identifier, is a target of this PickupCollection.
+    @param carrier
+        A pointer to the PickupCarrier we want to know of, whether it is a target of this PickupCollection.
+    @return
+        Returns true if the PickupCarrier identified by the input PickupIdentififer it is a target of this PickupCollection, false if not.
+    */
+    bool PickupCollection::isTarget(const PickupCarrier* carrier) const
+    {
+        for(CollectiblePickup* pickup : this->pickups_)
+        {
+            if(!carrier->isTarget(pickup))
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+    @brief
+        Add the input Pickupable to list of Pickupables combined by this PickupCollection.
+    @param pickup
+        The Pickupable to be added.
+    @return
+        Returns true if successful,
+    */
+    bool PickupCollection::addPickupable(CollectiblePickup* pickup)
+    {
+        if(pickup == nullptr)
+            return false;
+
+        this->pickups_.push_back(pickup);
+        pickup->wasAddedToCollection(this);
+        this->pickupsChanged();
+        return true;
+    }
+
+    /**
+    @brief
+        Get the Pickupable at the given index.
+    @param index
+        The index the Pickupable is fetched from.
+    @return
+        Returns a pointer to the Pickupable at the index given by index.
+    */
+    const Pickupable* PickupCollection::getPickupable(unsigned int index) const
+    {
+        if(this->pickups_.size() >= index)
+            return nullptr;
+
+        std::list<CollectiblePickup*>::const_iterator it = this->pickups_.begin();
+        std::advance(it, index);
+        return *it;
+    }
+
+    /**
+    @brief
+        Removes the Pickup from the Collection.
+    @param pickup
+        The Pickup to be removed.
+    @return
+        Returns true if the pickup was in the collection.
+    */
+    bool PickupCollection::removePickupable(CollectiblePickup* pickup)
+    {
+        for(std::list<CollectiblePickup*>::iterator it = this->pickups_.begin(); it != this->pickups_.end(); ++it)
+        {
+            if (*it == pickup)
+            {
+                this->pickups_.erase(it);
+                pickup->wasRemovedFromCollection();
+                this->pickupsChanged();
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+    @brief
+        Informs the PickupCollection, that one of its pickups has changed its used status to the input value.
+        This is used internally by the CollectiblePickup class.
+    @param changed
+        The value the used status has changed to.
+    */
+    void PickupCollection::pickupChangedUsed(bool changed)
+    {
+        this->changedUsedAction();
+    }
+
+    /**
+    @brief
+        Informs the PickupCollection, that one of its pickups has changed its picked up status to the input value.
+        This is used internally by the CollectiblePickup class.
+    @param changed
+        The value the picked up status has changed to.
+    */
+    void PickupCollection::pickupChangedPickedUp(bool changed)
+    {
+        this->changedPickedUpAction();
+    }
+
+    /**
+    @brief
+        Informs the PickupCollection, that one of its pickups has been disabled.
+        This is used internally by the CollectiblePickup class.
+    */
+    void PickupCollection::pickupDisabled(void)
+    {
+    }
+
+    /**
+    @brief
+        Helpfer function if the number of pickups in this collection has changed.
+    */
+    void PickupCollection::pickupsChanged(void)
+    {
+        this->changedUsedAction();
+        this->changedPickedUpAction();
+    }
+
+    /**
+    @brief
+        Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
+    @return
+        Returns true if a spawner was created, false if not.
+    */
+    bool PickupCollection::createSpawner(void)
+    {
+        PickupSpawner::createDroppedPickup(this->getContext(), this, this->getCarrier());
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupCollection.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupCollection.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupCollection.h	(revision 11817)
@@ -0,0 +1,117 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PickupCollection.h
+    @brief Declaration of PickupCollection.
+    @ingroup Pickup
+*/
+
+#ifndef _PickupCollection_H__
+#define _PickupCollection_H__
+
+#include "PickupPrereqs.h"
+
+#include <list>
+
+#include "CollectiblePickup.h"
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The PickupCollection combines different @ref orxonox::Pickupable "Pickupables" (more precisely @ref orxonox::CollectiblePickup "CollectiblePickups") to a coherent, single pickup and makes them seem (from the outside looking in) just as if they were just one @ref orxonox::Pickupable "Pickupable".
+
+        A PickupCollection can be created in XML as follows:
+        @code
+        <PickupCollection>
+            <pickupables>
+                <CollectiblePickup ... />
+                ...
+                <CollectiblePickup ... />
+            </pickupables>
+        </PickupCollection>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _PickupExport PickupCollection : public CollectiblePickup, public BaseObject
+    {
+
+        public:
+            PickupCollection(Context* context); //!< Default Constructor.
+            virtual ~PickupCollection(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Creates an instance of this Class through XML.
+
+            virtual void changedUsed(void) override; //!< Is called when the pickup has transited from used to unused or the other way around.
+            virtual void changedCarrier(void) override; //!< Is called when the pickup has changed its PickupCarrier.
+            virtual void changedPickedUp(void) override; //!< Is called when the pickup has transited from picked up to dropped or the other way around.
+
+            virtual bool isTarget(const PickupCarrier* carrier) const override; //!< Get whether a given class, represented by the input Identifier, is a target of this PickupCollection.
+
+            inline void setRepresentationName(const std::string& name)
+                { this->representationName_ = name; }
+            virtual const std::string& getRepresentationName() const override
+                { return this->representationName_; }
+
+            bool addPickupable(CollectiblePickup* pickup); //!< Add the input Pickupable to list of Pickupables combined by this PickupCollection.
+            const Pickupable* getPickupable(unsigned int index) const; //!< Get the Pickupable at the given index.
+            bool removePickupable(CollectiblePickup* pickup); //!< Removes the input Pickupable from the list of Pickupables in this PickupCollection.
+
+            inline const std::list<CollectiblePickup*>& getPickups() const
+                { return this->pickups_; }
+
+            void pickupChangedUsed(bool changed); //!< Informs the PickupCollection, that one of its pickups has changed its used status to the input value.
+            void pickupChangedPickedUp(bool changed); //!< Informs the PickupCollection, that one of its pickups has changed its picked up status to the input value.
+            void pickupDisabled(void); //!< Informs the PickupCollection, that one of its pickups has been disabled.
+
+        protected:
+            virtual bool createSpawner(void) override; //!< Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
+
+        private:
+            void changedUsedAction(void); //!< Helper method.
+            void changedPickedUpAction(void); //!< Helper method.
+            void pickupsChanged(void); //!< Helper method.
+
+            std::string representationName_; //!< The name of the associated PickupRepresentation.
+            std::list<CollectiblePickup*> pickups_; //!< The list of the pointers of all the Pickupables this PickupCollection consists of. They are weak pointers to facilitate testing, whether the pointers are still valid.
+
+            bool processingUsed_; //!< Boolean to ensure, that the PickupCollection doesn't update its used status while its internal state is inconsistent.
+            bool processingPickedUp_; //!< Boolean to ensure, that the PickupCollection doesn't update its picked upp status while its internal state is inconsistent.
+
+    };
+
+}
+
+#endif /* _PickupCollection_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupManager.cc	(revision 11817)
@@ -0,0 +1,496 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file PickupManager.cc
+    @brief Implementation of the PickupManager class.
+*/
+
+#include "PickupManager.h"
+
+#include "core/CoreIncludes.h"
+#include "core/LuaState.h"
+#include "core/GUIManager.h"
+#include "core/class/Identifier.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "network/Host.h"
+#include "network/NetworkFunctionIncludes.h"
+
+#include "infos/PlayerInfo.h"
+#include "interfaces/PickupCarrier.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "CollectiblePickup.h"
+#include "PickupRepresentation.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(PickupManager, ScopeID::ROOT, false);
+
+    // Initialization of the name of the PickupInventory GUI.
+    /*static*/ const std::string PickupManager::guiName_s = "PickupInventory";
+
+    // Register static network functions that are used to communicate changes to pickups over the network, such that the PickupInventory can display the information about the pickups properly.
+    registerStaticNetworkFunction(PickupManager::pickupChangedUsedNetwork);
+    registerStaticNetworkFunction(PickupManager::pickupChangedPickedUpNetwork);
+    registerStaticNetworkFunction(PickupManager::dropPickupNetworked);
+    registerStaticNetworkFunction(PickupManager::usePickupNetworked);
+
+    RegisterAbstractClass(PickupManager).inheritsFrom<PickupListener>();
+
+    /**
+    @brief
+        Constructor. Registers the PickupManager and creates the default PickupRepresentation.
+    */
+    PickupManager::PickupManager() : guiLoaded_(false), pickupHighestIndex_(0), defaultRepresentation_(nullptr)
+    {
+        RegisterObject(PickupManager);
+
+        this->defaultRepresentation_ = new PickupRepresentation();
+
+        orxout(internal_info, context::pickups) << "PickupManager created." << endl;
+    }
+
+    /**
+    @brief
+        Destructor.
+        Destroys the default PickupRepresentation and does some cleanup.
+    */
+    PickupManager::~PickupManager()
+    {
+        // Destroying the default representation.
+        if(this->defaultRepresentation_ != nullptr)
+            this->defaultRepresentation_->destroy();
+
+        this->representations_.clear();
+
+        // Destroying all the PickupInventoryContainers that are still there.
+        for(const auto& mapEntry : this->pickupInventoryContainers_)
+            delete mapEntry.second;
+        this->pickupInventoryContainers_.clear();
+
+        // Destroying all the WeakPointers that are still there.
+        this->pickups_.clear();
+        this->indexes_.clear();
+
+        orxout(internal_info, context::pickups) << "PickupManager destroyed." << endl;
+    }
+
+    /**
+    @brief
+        Registers a PickupRepresentation.
+    @param name
+        The representation's name.
+    @param representation
+        A pointer to the PickupRepresentation.
+    @return
+        Returns true if successful and false if not.
+    */
+    bool PickupManager::registerRepresentation(const std::string& name, PickupRepresentation* representation)
+    {
+        assert(representation);
+
+        // If the list is not empty and Pickupable already has a Representation registered.
+        if(!this->representations_.empty() && this->representations_.find(name) != this->representations_.end())
+            return false;
+
+        this->representations_[name] = representation;
+
+        orxout(verbose, context::pickups) << "PickupRepresentation &" << representation << " registered with the PickupManager." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Unegisters a PickupRepresentation.
+    @param name
+        The representation's name.
+    @return
+        Returns true if successful and false if not.
+    */
+    bool PickupManager::unregisterRepresentation(const std::string& name)
+    {
+        std::map<std::string, PickupRepresentation*>::iterator it = this->representations_.find(name);
+        if(it == this->representations_.end()) // If the Pickupable is not registered in the first place.
+            return false;
+
+        this->representations_.erase(it);
+
+        orxout(verbose, context::pickups) << "PickupRepresentation &" << name << " unregistered with the PickupManager." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Get the PickupRepresentation with the given name.
+    @param name
+        The name of the PickupRepresentation.
+    @return
+        Returns a pointer to the PickupRepresentation.
+    */
+    PickupRepresentation* PickupManager::getRepresentation(const std::string& name)
+    {
+        std::map<std::string, PickupRepresentation*>::iterator it = this->representations_.find(name);
+        if(it == this->representations_.end()) // If there is no PickupRepresentation associated with the input name.
+        {
+            orxout(verbose, context::pickups) << "PickupManager::getRepresentation() returned default representation." << endl;
+            return this->defaultRepresentation_;
+        }
+
+        return it->second;
+    }
+
+    /**
+    @brief
+        Is called by the PickupListener to notify the PickupManager, that the input Pickupable has transited to the input used state.
+    @param pickup
+        The Pickupable whose used status changed.
+    @param used
+        The used status the Pickupable changed to.
+    */
+    void PickupManager::pickupChangedUsed(Pickupable* pickup, bool used)
+    {
+        assert(pickup);
+
+        if(!GameMode::isMaster()) // If this is neither standalone nor the server.
+            return;
+
+        CollectiblePickup* collectible = orxonox_cast<CollectiblePickup*>(pickup);
+        // If the Pickupable is part of a PickupCollection it isn't displayed in the PickupInventory, just the PickupCollection is.
+        if(collectible != nullptr && collectible->isInCollection())
+            return;
+
+        // Getting clientId of the host this change of the pickup's used status concerns.
+        PickupCarrier* carrier = pickup->getCarrier();
+        while(carrier->getCarrierParent() != nullptr)
+            carrier = carrier->getCarrierParent();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+        if(pawn == nullptr)
+            return;
+        PlayerInfo* info = pawn->getPlayer();
+        if(info == nullptr)
+            return;
+        unsigned int clientId = info->getClientID();
+
+        // Get the number identifying the pickup.
+        std::map<Pickupable*, uint32_t>::iterator it = this->indexes_.find(pickup);
+        assert(it != this->indexes_.end());
+        uint32_t index = it->second;
+
+        // If we're either in standalone mode or this is the host whom the change of the pickup's status concerns.
+        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
+        {
+            PickupManager::pickupChangedUsedNetwork(index, used, pickup->isUsable(), pickup->isUnusable());
+        }
+        // If the concerned host is somewhere in the network, we call pickupChangedUsedNetwork() on its PickupManager.
+        else
+        {
+            callStaticNetworkFunction(&PickupManager::pickupChangedUsedNetwork, clientId, index, used, pickup->isUsable(), pickup->isUnusable());
+        }
+    }
+
+    /**
+    @brief
+        Helper method to react to the change in the used status of a Pickupable.
+        Static method that is used by the server to inform the client it concerns about the status change.
+        The parameters that are given are used to update the information (i.e. the PickupInventoryContainer) the concerning PickupManager has about the Pickupable that changed.
+    @param pickup
+        A number identifying the Pickupable that changed its used status.
+    @param inUse
+        The used status the Pickupable changed to. (i.e. whether the Pickupable is in use or not).
+    @param usable
+        Whether the Pickupable's used status can be changed used in the PickupInventory.
+    @param unusable
+        Whether the Pickupable's used status can be changed to unused in the PickupInventory.
+    */
+    /*static*/ void PickupManager::pickupChangedUsedNetwork(uint32_t pickup, bool inUse, bool usable, bool unusable)
+    {
+        PickupManager& manager = PickupManager::getInstance(); // Get the PickupManager singleton on this host.
+        // If the input Pickupable (i.e its identifier) is not present in the list the PickupManager has.
+        if(manager.pickupInventoryContainers_.find(pickup) == manager.pickupInventoryContainers_.end())
+        {
+            orxout(internal_error, context::pickups) << "Pickupable &(" << pickup << ") was not registered with PickupManager for the PickupInventory, when it changed used." << endl;
+            return;
+        }
+
+        // Update the Pickupable's container with the information transferred.
+        manager.pickupInventoryContainers_[pickup]->inUse = inUse;
+        manager.pickupInventoryContainers_[pickup]->usable = usable;
+        manager.pickupInventoryContainers_[pickup]->unusable = unusable;
+
+        manager.updateGUI(); // Tell the PickupInventory that something has changed.
+    }
+
+    /**
+    @brief
+        Is called by the PickupListener to notify the PickupManager, that the input Pickupable has transited to the input pickedUp state.
+    @param pickup
+        The Pickupable whose pickedUp status changed.
+    @param pickedUp
+        The pickedUp status the Pickupable changed to.
+    */
+    void PickupManager::pickupChangedPickedUp(Pickupable* pickup, bool pickedUp)
+    {
+        assert(pickup);
+
+        if(!GameMode::isMaster()) // If this is neither standalone nor the server.
+            return;
+
+        CollectiblePickup* collectible = orxonox_cast<CollectiblePickup*>(pickup);
+        // If the Pickupable is part of a PickupCollection it isn't displayed in the PickupInventory, just the PickupCollection is.
+        if(collectible != nullptr && collectible->isInCollection())
+            return;
+
+        // Getting clientId of the host this change of the pickup's pickedUp status concerns.
+        PickupCarrier* carrier = pickup->getCarrier();
+        while(carrier->getCarrierParent() != nullptr)
+            carrier = carrier->getCarrierParent();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+        if(pawn == nullptr)
+            return;
+        PlayerInfo* info = pawn->getFormerPlayer();
+        if(info == nullptr)
+            return;
+        unsigned int clientId = info->getClientID();
+
+        uint32_t index = 0;
+        if(pickedUp) // If the Pickupable has changed to picked up, it is added to the required lists.
+        {
+            index = this->getPickupIndex(); // Get a new identifier (index) for the Pickupable.
+            // Add the Pickupable to the indexes_ and pickups_ lists.
+            this->indexes_[pickup] = index;
+            this->pickups_[index] = pickup;
+        }
+        else // If it was dropped, it is removed from the required lists.
+        {
+            // Get the indentifier (index) that identifies the input Pickupable.
+            std::map<Pickupable*, uint32_t>::iterator it = this->indexes_.find(pickup);
+            index = it->second;
+
+            // Remove the Pickupable from the indexes_ and pickups_ list.
+            this->indexes_.erase(it);
+            this->pickups_.erase(index);
+        }
+
+        // If we're either in standalone mode or this is the host whom the change of the pickup's status concerns.
+        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
+        {
+            PickupManager::pickupChangedPickedUpNetwork(index, pickup->isUsable(), pickup->getRepresentationName(), pickedUp, pawn->getObjectID());
+        }
+        // If the concerned host is somewhere in the network, we call pickupChangedPickedUpNetwork() on its PickupManager.
+        else
+        {
+            callStaticNetworkFunction(&PickupManager::pickupChangedPickedUpNetwork, clientId, index, pickup->isUsable(), pickedUp, pawn->getObjectID());
+        }
+
+    }
+
+    /**
+    @brief
+        Helper method to react to the change in the pickedUp status of a Pickupable.
+        Static method that is used by the server to inform the client it concerns about the status change.
+        The parameters that are given are used to update the information (i.e. the PickupInventoryContainer) the concerning PickupManager has about the Pickupable that changed.
+    @param pickup
+        A number identifying the Pickupable that changed its pickedUp status.
+    @param usable
+        Whether the Pickupable's used status can be changed to used in the PickupInventory.
+    @param representationName
+        The name of the associated PickupRepresentation
+    @param pickedUp
+        The pickedUp status the Pickupable changed to.
+    @param carrierPawnId
+        The objectId identifier (over the network) the Pawn that carries this Pickupable
+    */
+    /*static*/ void PickupManager::pickupChangedPickedUpNetwork(uint32_t pickup, bool usable, const std::string& representationName, bool pickedUp, uint32_t carrierPawnId)
+    {
+        PickupManager& manager = PickupManager::getInstance(); // Get the PickupManager singleton on this host.
+        // If the Pickupable has been picked up, we create a new PickupInventoryContainer for it.
+        if(pickedUp)
+        {
+            // Create a new PickupInventoryContainer for the Pickupable and set all the necessary information.
+            PickupInventoryContainer* container = new PickupInventoryContainer;
+            container->pickup = pickup;
+            container->inUse = false;
+            container->pickedUp = pickedUp;
+            container->usable = usable;
+            container->unusable = false;
+            container->representationName = representationName;
+            container->carrierPawnId = carrierPawnId;
+            // Insert the container into the pickupInventoryContainers_ list.
+            manager.pickupInventoryContainers_.insert(std::pair<uint32_t, PickupInventoryContainer*>(pickup, container));
+
+            manager.updateGUI(); // Tell the PickupInventory that something has changed.
+        }
+        // If the Pickupable has been dropped, we remove it from the pickupInventoryContainers_ list.
+        else
+        {
+            std::map<uint32_t, PickupInventoryContainer*>::iterator it = manager.pickupInventoryContainers_.find(pickup);
+            if(it != manager.pickupInventoryContainers_.end())
+                delete it->second;
+            manager.pickupInventoryContainers_.erase(pickup);
+
+            manager.updateGUI(); // Tell the PickupInventory that something has changed.
+        }
+    }
+
+    /**
+    @brief
+        Get the number of pickups currently picked up by the player.
+        This method is used in lua to populate the PickupInventory. The intended usage is to call this method to reset the iterator of the list of PickupInventoryContainers and then use popPickup() to get the individual PickupInventoryContainers.
+    @return
+        Returns the number of the players picked up Pickupables.
+    */
+    int PickupManager::getNumPickups(void)
+    {
+        this->pickupsIterator_ = this->pickupInventoryContainers_.begin(); // Reset iterator.
+
+        return this->pickupInventoryContainers_.size();
+    }
+
+    /**
+    @brief
+        Drop the input Pickupable.
+        This method checks whether the input Pickupable still exists and drops it, if so.
+    @param pickup
+        The identifier of the Pickupable to be dropped.
+    */
+    void PickupManager::dropPickup(uint32_t pickup)
+    {
+        // If we're either server or standalone and the list of pickups is not empty, we find and drop the input pickup.
+        if(GameMode::isMaster())
+        {
+            if(this->pickups_.empty())
+                return;
+            Pickupable* pickupable = this->pickups_.find(pickup)->second;
+            if(pickupable != nullptr)
+                pickupable->drop();
+        }
+        // If we're neither server nor standalone we drop the pickup by calling dropPickupNetworked() of the PickupManager on the server.
+        else
+        {
+            callStaticNetworkFunction(&PickupManager::dropPickupNetworked, 0, pickup);
+        }
+    }
+
+    /**
+    @brief
+        Helper method to drop the input pickup on the server.
+        Static method that is used by clients to instruct the server to drop the input pickup.
+    @param pickup
+        The identifier of the Pickupable to be dropped.
+    */
+    /*static*/ void PickupManager::dropPickupNetworked(uint32_t pickup)
+    {
+        if(GameMode::isServer()) // Obviously we only want to do this on the server.
+        {
+            PickupManager& manager = PickupManager::getInstance();
+            manager.dropPickup(pickup);
+        }
+    }
+
+    /**
+    @brief
+        Use (or unuse) the input Pickupable.
+        This method checks whether the input Pickupable still exists and uses (or unuses) it, if so,
+    @param pickup
+        The identifier of the Pickupable to be used (or unused).
+    @param use
+        If true the input Pickupable is used, if false it is unused.
+    */
+    void PickupManager::usePickup(uint32_t pickup, bool use)
+    {
+        // If we're either server or standalone and the list of pickups is not empty, we find and change the used status of the input pickup.
+        if(GameMode::isMaster())
+        {
+            if(this->pickups_.empty())
+                return;
+            Pickupable* pickupable = this->pickups_.find(pickup)->second;
+            if(pickupable != nullptr)
+                pickupable->setUsed(use);
+        }
+        // If we're neither server nor standalone we change the used status of the pickup by calling usePickupNetworked() of the PickupManager on the server.
+        else
+        {
+            callStaticNetworkFunction(&PickupManager::usePickupNetworked, 0, pickup, use);
+        }
+    }
+
+    /**
+    @brief
+        Helper method to use (or unuse) the input Pickupable on the server.
+        Static method that is used by clients to instruct the server to use (or unuse) the input pickup.
+    @param pickup
+        The identifier of the Pickupable to be used (or unused).
+    @param use
+        If true the input Pickupable is used, if false it is unused.
+    */
+    /*static*/ void PickupManager::usePickupNetworked(uint32_t pickup, bool use)
+    {
+        if(GameMode::isServer())
+        {
+            PickupManager& manager = PickupManager::getInstance();
+            manager.usePickup(pickup, use);
+        }
+    }
+
+    /**
+    @brief
+        Updates the PickupInventory GUI.
+        Also loads the PickupInventory GUI if is hasn't been done already.
+    */
+    inline void PickupManager::updateGUI(void)
+    {
+        // We only need to update (and load) the GUI if this host shows graphics.
+        if(GameMode::showsGraphics())
+        {
+            if(!this->guiLoaded_) // If the GUI hasn't been loaded, yet, we load it.
+            {
+                GUIManager::getInstance().loadGUI(PickupManager::guiName_s);
+                this->guiLoaded_ = true;
+            }
+
+            // Update the GUI.
+            GUIManager::getInstance().getLuaState()->doString(PickupManager::guiName_s + ".update()");
+        }
+    }
+
+    /**
+    @brief
+        Get a new index for a Pickupable.
+        This will work as long as the number of Pickupables that are picked up is sufficiently small and as long as they don't exist forever.
+    @return
+        Returns the new index.
+    */
+    uint32_t PickupManager::getPickupIndex(void)
+    {
+        if(this->pickupHighestIndex_ == uint32_t(~0x0)-1) // If we've reached the highest possible number, we wrap around.
+            this->pickupHighestIndex_ = 0;
+        return this->pickupHighestIndex_++;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupManager.h	(revision 11817)
@@ -0,0 +1,173 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file PickupManager.h
+    @brief Definition of the PickupManager class.
+    @ingroup Pickup
+*/
+
+#ifndef _PickupManager_H__
+#define _PickupManager_H__
+
+#include "PickupPrereqs.h"
+
+#include <map>
+#include "core/object/WeakPtr.h"
+
+#include "PickupRepresentation.h"
+
+#include "util/Singleton.h"
+#include "interfaces/PickupListener.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    // tolua_begin
+    /**
+    @brief
+        Data structure to store collected data for one specific @ref orxonox::Pickupable "Pickupable".
+        This is used to not have to synchronise @ref orxonox::Pickupable "Pickupable" just to have the needed information for the PickupInventory available on all clients. Instead the information is sent over the network and stored in a PickupInventoryContainer.
+
+    @ingroup Pickup
+    */
+    struct PickupInventoryContainer
+    {
+        uint32_t pickup; //!< An indentifier for the @ref orxonox::Pickupable "Pickupable" that is associated with the information stored here.
+        bool inUse; //!< Whether the @ref orxonox::Pickupable "Pickupable" is currently in use.
+        bool pickedUp; //!< Whether the @ref orxonox::Pickupable "Pickupable" is currently picked up.
+        bool usable; //!< Whether the @ref orxonox::Pickupable "Pickupable" is usable.
+        bool unusable; //!< Whether the @ref orxonox::Pickupable "Pickupable" is droppable.
+        std::string representationName; //!< The name of the associated PickupRepresentation
+        uint32_t carrierPawnId; //!< The objectId of the @ref orxonox::Pawn "Pawn" that carries the @ref orxonox::Pickupable "Pickupable".
+    };
+    // tolua_end
+
+    /**
+    @brief
+        The PickupManager class manages @ref orxonox::Pickupable "Pickupables".
+
+        It has in essence two tasks to fulfill. Firstly it must link @ref orxonox::Pickupable "Pickupables" (through their representation-name attribute) to the respective @ref orxonox::PickupRepresentation "PickupRepresentations". Secondly it manages the PickupInventory. (The PickupInventory is the GUI that displays @ref orxonox::Pickupable "Pickupables" for the covenience of the user.)
+
+        @section PickupManagerTechnicalDetails Technical details
+        Unfortunately <em>under the hood</em> it isn't just as easy. At least the PickupInventory part isn't. To grasp why this is we need to have a brief look at how the pickups module works over the network:
+
+        The pickups module essentially just exists on the @ref orxonox::Server "Server", since it's all game logic. That means, a @ref orxonox::PickupSpawner "PickupSpawner" is always triggered on the server, the @ref orxonox::Pickupable "Pickupable" is then picked up (and maybe used already) on the server. The effects the pickup has are synchronised over the network, if they have to be, but this is the responsibility of the entities that are affected, not the pickups module, and normally this is already implemented. The only two things that need to be communicated over the network are the graphical component of the @ref orxonox::PickupSpawner "PickupSpawner", since it needs to be displayed on the @ref orxonox::Client "Clients" as well, and anything that is needed for the PickupInventory, since it exists for each @ref orxonox::Host "Host" seperatly.
+
+        Fortunately synchronising the @ref orxonox::PickupSpawner "PickupSpawner" is already being taken care of by the synchronisation of the @ref orxonox::StaticEntity "StaticEntity" (or parents thereof).
+
+        This leaves us with the PickupInventory component (and this is really the source of all the complexity).
+
+        Firstly there are a number of lists (where by list I really mean any kind of ordered data structure) kept.
+        - The @ref orxonox::PickupManager::representations_ "representations_" list links @ref orxonox::PickupRepresentation "PickupRepresentations" with its name and can be used to get the @ref orxonox::PickupRepresentation "PickupRepresentation" for a given @ref orxonox::Pickupable "Pickupable". It is only populated on the server (or in standalone mode). Each @ref orxonox::PickupRepresentation "PickupRepresentation" that is generated through XML registers itself with the PickupManager and is thereby added to the list.
+        - The @ref orxonox::PickupManager::pickupInventoryContainers_ "pickupInventoryContainers_" list links a number identifying a @ref orxonox::Pickupable "Pickupable" to a data structure (the @ref orxonox::PickupInventoryContainer "PickupInventoryContainer"), which contains all necessary information about that @ref orxonox::Pickupable "Pickupable". This list is maintained on all hosts, a new container is inserted when a @ref orxonox::Pickupable "Pickupable" is picked up, but only if it has been picked up by the repsective host. This list is then used by the PickupInventory to access the required information and to get the correct @ref orxonox::PickupRepresentation "PickupRepresentation".
+        - The @ref orxonox::PickupManager::pickups_ "pickups_" list links a number identifiying a @ref orxonox::Pickupable "Pickupable" to a (weak pointer to a) @ref orxonox::Pickupable "Pickupable". It is only maintained by the server (or in standalone mode), to be able to use, unuse and drop @ref orxonox::Pickupable "Pickupables" through the PickupInventory. Since @ref orxonox::Pickupable "Pickupables" only exist on the server a client that wants to change a pickups status has so send a request over the network (with the number identifying the pickup) to the server and then the server facilitates the change, using this list to map from the identifyer to the actual @ref orxonox::Pickupable "Pickupable".
+        - The @ref orxonox::PickupManager::indexes_ "indexes_" list links a @ref orxonox::Pickupable "Pickupable" to the number identifying it. This is only maintained on the server (or in standalone mode), and is used for the inverse mapping of the previous list, which means the server uses it identify pickups on clients when it communicates changes in pickups to clients.
+
+        There is communication in both directions. From server to client, when the server informs the client that the state of some @ref orxonox::Pickupable "Pickupable" has changed, during which all necessary information to create or update the PickupInventoryContainer for that pickup on the client is sent as well. Or from client to server, when the client wants the server to change the state of some @ref orxonox::Pickupable "Pickupable".
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _PickupExport PickupManager // tolua_export
+        : public Singleton<PickupManager>, public PickupListener
+    { // tolua_export
+        friend class Singleton<PickupManager>;
+
+        public:
+            PickupManager(); //!< Constructor.
+            virtual ~PickupManager(); //!< Destructor.
+
+            /**
+            @brief Get the instance of the PickupManager singleton.
+            @return Returns the instance of the PickupManager singleton.
+            */
+            static PickupManager& getInstance() { return Singleton<PickupManager>::getInstance(); } // tolua_export
+
+            bool registerRepresentation(const std::string& name, PickupRepresentation* representation);
+            bool unregisterRepresentation(const std::string& name);
+
+            PickupRepresentation* getRepresentation(const std::string& name); // tolua_export
+
+            virtual void pickupChangedUsed(Pickupable* pickup, bool used) override; //!< Is called by the PickupListener to notify the PickupManager, that the input Pickupable has transited to the input used state.
+            static void pickupChangedUsedNetwork(uint32_t pickup, bool inUse, bool usable, bool unusable); //!< Helper method to react to the change in the used status of a Pickupable.
+            virtual void pickupChangedPickedUp(Pickupable* pickup, bool pickedUp) override; //!< Is called by the PickupListener to notify the PickupManager, that the input Pickupable has transited to the input pickedUp state.
+            static void pickupChangedPickedUpNetwork(uint32_t pickup, bool usable, const std::string& representationName, bool pickedUp, uint32_t carrierPawnId); //!< Helper method to react to the change in the pickedUp status of a Pickupable.
+
+        // Methods to be used by the PickupInventory.
+        public:
+            // tolua_begin
+            int getNumPickups(void); //!< Get the number of pickups currently picked up by the player.
+            /**
+            @brief Get the next PickupInventoryContainer in the list.
+                   Use this, after having called getNumPickups() to access all the PickupInventoryContainers individually and in succession.
+            @return Returns the next PickupInventoryContainer in the list.
+            */
+            const orxonox::PickupInventoryContainer* popPickup(void)
+                { return (this->pickupsIterator_++)->second; }
+
+            void dropPickup(uint32_t pickup); //!< Drop the input Pickupable.
+            void usePickup(uint32_t pickup, bool use); //!< Use (or unuse) the input Pickupable.
+             /**
+            @brief Check whether the input Pickupable is valid, meaning that it is in the PickupManager's list and still exists.
+            @param pickup The Pickupable.
+            @return Returns true if the input Pickupable is still valid, false if not.
+            */
+            bool isValidPickup(uint32_t pickup) const
+                { return this->pickups_.find(pickup) != this->pickups_.end(); }
+            // tolua_end
+
+            static void dropPickupNetworked(uint32_t pickup); //!< Helper method to drop the input pickup on the server.
+            static void usePickupNetworked(uint32_t pickup, bool use); //!< Helper method to use (or unuse) the input Pickupable on the server.
+
+        private:
+            static PickupManager* singletonPtr_s;
+            static const std::string guiName_s; //!< The name of the PickupInventory
+            bool guiLoaded_; //!< Whether the PickupInventory GUI has been loaded, yet.
+            uint32_t pickupHighestIndex_; //!< The highest pickup index currently in use. (not taking wrap-around into account)
+
+            PickupRepresentation* defaultRepresentation_; //!< The default PickupRepresentation.
+
+            std::map<std::string, PickupRepresentation*> representations_; //!< Map linking PickupRepresentations and their names.
+
+            std::map<uint32_t, PickupInventoryContainer*> pickupInventoryContainers_; //!< Map linking a number identifying a Pickupable to a PickupInventoryContainer, which contains all necessary information about that Pickupable.
+            std::map<uint32_t, PickupInventoryContainer*>::iterator pickupsIterator_; //!< An iterator pointing to the current Pickupable in pickupsList_.
+
+            std::map<uint32_t, WeakPtr<Pickupable>> pickups_; //!< Map linking a number identifying a Pickupable to a weak pointer of a Pickupable.
+            std::map<Pickupable*, uint32_t> indexes_;//!< Map linking Pickupable to the number identifying it.
+
+            void updateGUI(void); //!< Updates the PickupInventory GUI.
+            uint32_t getPickupIndex(void); //!< Get a new index for a Pickupable.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif // _PickupManager_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btTransform.h>
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupPrereqs.h	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _PickupPrereqs_H__
+#define _PickupPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(PICKUP_STATIC_BUILD)
+#  ifdef PICKUP_SHARED_BUILD
+#    define _PickupExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _PickupExport
+#    else
+#      define _PickupExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _PickupPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _PickupExport  __attribute__ ((visibility("default")))
+#  define _PickupPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _PickupExport
+#  define _PickupPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+
+    class CollectiblePickup;
+    class Pickup;
+    class PickupCollection;
+    struct PickupInventoryContainer;
+    class PickupManager;
+    class PickupRepresentation;
+    class PickupSpawner;
+
+    //items
+    class DronePickup;
+    class HealthPickup;
+    class InvisiblePickup;
+    class MetaPickup;
+    class SpeedPickup;
+    class ShieldPickup;
+    class ShrinkPickup;
+    class DamageBoostPickup;
+    class MunitionPickup;
+    class MunitionContainer;
+}
+
+#endif /* _PickupPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupRepresentation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupRepresentation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupRepresentation.cc	(revision 11817)
@@ -0,0 +1,196 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file PickupRepresentation.cc
+    @brief Implementation of the PickupRepresentation class.
+*/
+
+#include "PickupRepresentation.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "util/StringUtils.h"
+
+#include "graphics/Billboard.h"
+
+#include "PickupManager.h"
+
+namespace orxonox
+{
+
+    RegisterClass(PickupRepresentation);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes its member variables.
+        This is primarily for use of the PickupManager in creating a default PickupRepresentation.
+    */
+    PickupRepresentation::PickupRepresentation() : BaseObject(nullptr), Synchronisable(nullptr), spawnerRepresentation_(nullptr)
+    {
+        RegisterObject(PickupRepresentation);
+
+        this->initialize();
+        this->setSyncMode(ObjectDirection::None); // The default PickupRperesentation created by each PickupManager is not synchronised, since it only exists locally.
+    }
+
+    /**
+    @brief
+        Default Constructor. Registers the object and initializes its member variables.
+    */
+    PickupRepresentation::PickupRepresentation(Context* context) : BaseObject(context), Synchronisable(context), spawnerRepresentation_(nullptr)
+    {
+        RegisterObject(PickupRepresentation);
+
+        this->initialize();
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    PickupRepresentation::~PickupRepresentation()
+    {
+        if(this->spawnerRepresentation_ != nullptr)
+            this->spawnerRepresentation_->destroy();
+
+        if(this->isInitialized())
+            PickupManager::getInstance().unregisterRepresentation(this->getName());
+    }
+
+    /**
+    @brief
+        Initializes the member variables of this PickupRepresentation.
+    */
+    void PickupRepresentation::initialize(void)
+    {
+        this->description_ = "This is a pickup.";
+        this->name_ = "Pickup";
+        this->spawnerTemplate_ = "";
+        this->inventoryRepresentation_ = "Default";
+    }
+
+    /**
+    @brief
+        Registers the variables that need to be synchornised.
+    */
+    void PickupRepresentation::registerVariables(void)
+    {
+        registerVariable(this->description_, VariableDirection::ToClient);
+        registerVariable(this->name_, VariableDirection::ToClient);
+        registerVariable(this->inventoryRepresentation_, VariableDirection::ToClient);
+    }
+
+    /**
+    @brief
+        Method for creating a PickupRepresentation object through XML.
+    */
+    void PickupRepresentation::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PickupRepresentation, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PickupRepresentation, "pickupName", setPickupName, getPickupName, xmlelement, mode);
+        XMLPortParam(PickupRepresentation, "pickupDescription", setPickupDescription, getPickupDescription, xmlelement, mode);
+        XMLPortParam(PickupRepresentation, "spawnerTemplate", setSpawnerTemplate, getSpawnerTemplate, xmlelement, mode);
+        XMLPortParam(PickupRepresentation, "inventoryRepresentation", setInventoryRepresentation, getInventoryRepresentation, xmlelement, mode);
+        XMLPortObject(PickupRepresentation, StaticEntity, "spawner-representation", setSpawnerRepresentation, getSpawnerRepresentationIndex, xmlelement, mode);
+
+        orxout(verbose, context::pickups) << "PickupRepresentation created: name: '" << this->name_ << "', description: '" << this->description_ << "', spawnerTemplate: '" << this->spawnerTemplate_ << "'." << endl;
+    }
+
+    /**
+    @brief
+        Get a spawnerRepresentation for a specific PickupSpawner.
+    @param spawner
+        A pointer to the PickupSpawner.
+    @return
+        Returns a pointer to the StaticEntity.
+    */
+    StaticEntity* PickupRepresentation::createSpawnerRepresentation(PickupSpawner* spawner)
+    {
+        if(this->spawnerRepresentation_ == nullptr)
+        {
+            orxout(verbose, context::pickups) << "PickupRepresentation: No spawner representation found." << endl;
+            if(this->spawnerTemplate_ == "")
+            {
+                orxout(internal_warning, context::pickups) << "PickupRepresentation: Spawner template is empty." << endl;
+                // If neither spawnerRepresentation nor spawnerTemplate was specified
+                return this->getDefaultSpawnerRepresentation(spawner);
+            }
+            this->addTemplate(this->spawnerTemplate_);
+        }
+
+        this->spawnerRepresentation_->setVisible(true);
+        StaticEntity* temp = this->spawnerRepresentation_;
+        this->spawnerRepresentation_ = nullptr;
+
+        return temp;
+    }
+
+    void PickupRepresentation::changedName()
+    {
+        // Registers the PickupRepresentation with the PickupManager.
+        PickupManager::getInstance().unregisterRepresentation(this->getOldName());
+        PickupManager::getInstance().registerRepresentation(this->getName(), this);
+    }
+
+    void PickupRepresentation::setSpawnerRepresentation(StaticEntity* representation)
+    {
+        this->spawnerRepresentation_ = representation;
+        if(this->spawnerRepresentation_ != nullptr)
+            this->spawnerRepresentation_->setVisible(false);
+    }
+
+    /**
+    @brief
+        Get the default spawnerRepresentation for a specific PickupSpawner.
+        Helper method of internal use.
+    @param spawner
+        A pointer to the PickupSpawner.
+    @return
+        Returns a pointer to the StaticEntity.
+    */
+    //TODO: Possibility to define default representation through XML?
+    StaticEntity* PickupRepresentation::getDefaultSpawnerRepresentation(PickupSpawner* spawner)
+    {
+        StaticEntity* representation = new StaticEntity(spawner->getContext());
+        Billboard* sphere = new Billboard(spawner->getContext());
+        sphere->setColour(ColourValue(0.95f, 0.85f, 0.27f));
+        sphere->setMaterial("Sphere2");
+        sphere->setScale(0.1f);
+        Billboard* icon = new Billboard(spawner->getContext());
+        icon->setColour(ColourValue(0.89f, 0.79f, 0.08f));
+        icon->setMaterial("Unknown");
+        icon->setScale(0.5);
+        sphere->attach(icon);
+        representation->attach(sphere);
+        return representation;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupRepresentation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupRepresentation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupRepresentation.h	(revision 11817)
@@ -0,0 +1,185 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file PickupRepresentation.h
+    @brief Definition of the PickupRepresentation class.
+    @ingroup Pickup
+*/
+
+#ifndef _PickupRepresentation_H__
+#define _PickupRepresentation_H__
+
+#include "PickupPrereqs.h"
+
+#include "core/XMLPort.h"
+
+#include "interfaces/Pickupable.h"
+#include "worldentities/StaticEntity.h"
+
+#include "PickupSpawner.h"
+
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        The PickupRepresentation class represents a specific pickup type. It defines the information displayed in the GUI (PickupInventory) and how @ref orxonox::PickupSpawner "PickupSpawners" that spawn the pickup type look like.
+        They are created through XML and are registered with the @ref orxonox::PickupManager "PickupManager".
+
+        Creating a PickupRepresentation in XML could look as follows:
+        @code
+        <PickupRepresentation
+            name = "My awesome Pickup"
+            description = "This is the most awesome Pickup ever to exist."
+            spawnerTemplate = "awesomePickupRepresentation"
+            inventoryRepresentation = "AwesomePickup"
+        />
+        @endcode
+        As you might have noticed, there is a parameter called <em>spawnerTemplate</em> and also another parameter called <em>inventoryRepresentation</em>. Let's first explain the second one, <em>inventoryRepresentation</em>.
+        - The <b>inventoryRepresentation</b> specifies the image that is displayed in the PickupInventory for the specific type of @ref orxonox::Pickupable "Pickupable". More technically, it is the name of an image located in the <code>PickupInventory.imageset</code>, which in turn is located in <code>data_extern/gui/imagesets/</code>.
+        - The <b>spawnerTemplate</b> specifies how the type of @ref orxonox::Pickupable "Pickupable" (or more precisely the @ref orxonox::PickupSpawner "PickupSpawner", that spawns that type of @ref orxonox::Pickupable "Pickupable") is displayed ingame. It is a @ref orxonox::Template "Template" defined in XML. The <em>spawnerTemplate</em> can be specified as follows (keep in mind, that the template needs to have been specified before the definition of the PickupRepresentation that uses it).
+        @code
+        <Template name="awesomePickupRepresentation">
+            <PickupRepresentation>
+                <spawner-representation>
+                    <StaticEntity>
+                        <attached>
+                            <!-- Here you can put all the objects which define the look of the spawner. -->
+                        </attached>
+                    </StaticEntity>
+                </spawner-representation>
+            </PickupRepresentation>
+        </Template>
+        @endcode
+
+        For the purpose of them working over the network, they are synchronised.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _PickupExport PickupRepresentation // tolua_export
+        : public BaseObject, public Synchronisable
+    { // tolua_export
+
+        public:
+            PickupRepresentation(); //!< Constructor
+            PickupRepresentation(Context* context); //!< Default constructor.
+            virtual ~PickupRepresentation(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a PickupRepresentation object through XML.
+
+            /**
+            @brief Get the name of the Pickupable represented by this PickupRepresentation.
+            @return Returns the name.
+            */
+            inline const std::string& getPickupName(void) const { return this->name_; } // tolua_export
+            /**
+            @brief Get the description of the Pickupable represented by this PickupRepresentation.
+            @return Returns the description.
+            */
+            inline const std::string& getPickupDescription(void) const { return this->description_; } // tolua_export
+            /**
+            @brief Get the name of spawnerTemplate the Pickupable represented by this PickupRepresentation.
+            @return Returns the name of the spawnerTemplate.
+            */
+            inline const std::string& getSpawnerTemplate(void) const
+                { return this->spawnerTemplate_; }
+            /**
+            @brief Get the StaticEntity that defines how the PickupSpawner of the Pickupable represented by this PickupRepresentation looks like.
+            @param index The index.
+            @return Returns (for index = 0) a pointer to the StaticEntity. For index > 0 it returns nullptr.
+            */
+            inline const StaticEntity* getSpawnerRepresentationIndex(unsigned int index) const
+                { if(index == 0) return this->spawnerRepresentation_; return nullptr; }
+            /**
+            @brief Get the name of the image representing the pickup in the PickupInventory.
+            @return Returns the name of the image as a string.
+            */
+            inline const std::string& getInventoryRepresentation(void) const { return this->inventoryRepresentation_; } // tolua_export
+
+            virtual void changedName() override;
+
+            StaticEntity* createSpawnerRepresentation(PickupSpawner* spawner); //!< Create a spawnerRepresentation for a specific PickupSpawner.
+
+        protected:
+            /**
+            @brief Set the name of the Pickupable represented by this PickupRepresentation.
+            @param name The name.
+            */
+            inline void setPickupName(const std::string& name)
+                { this->name_ = name; }
+            /**
+            @brief Set the description of the Pickupable represented by this PickupRepresentation.
+            @param description The Description.
+            */
+            inline void setPickupDescription(const std::string& description)
+                { this->description_ = description; }
+            /**
+            @brief Set the spawnerTemplate of the Pickupable represented by this PickupRepresentation.
+                   The spawnerTemplate is a name of a template defined in XML that defines the StaticEntity that is the spawnerRepresentation of this PickupRepresentation.
+            @param spawnerTemplate The name of the template.
+            */
+            inline void setSpawnerTemplate(const std::string& spawnerTemplate)
+                { this->spawnerTemplate_ = spawnerTemplate; }
+            /**
+            @brief Set the StaticEntity that defines how the PickupSpawner of the Pickupable represented by this PickupRepresentation looks like.
+                   This will be set by the spawnerTemplate. Setting it when creating the PickupRepresentation without creating a template and specifying its name will be futile, because through the course of the game many PickupSpawners for one specific pickup type may have to be created, thus the StaticEntity that is the spawnerRepresentation has to be generated (with the template) for every new PickupSpawner spawning the Pickupable represented by this PickupRepresentation. The spawnerRepresentation that is set here, however can only be used once.
+            @param representation A pointer to the StaticEntity that is the spawnerRepresentation of this PickupRepresentation.
+            */
+            void setSpawnerRepresentation(StaticEntity* representation);
+
+            /**
+            @brief Set the image representing the pickup in the PickupInventory.
+            @param image A string with the name of the image representing the pickup.
+            */
+            inline void setInventoryRepresentation(const std::string& image)
+                { this->inventoryRepresentation_ = image; }
+
+        private:
+            void initialize(void); //!< Initializes the member variables of this PickupRepresentation.
+            StaticEntity* getDefaultSpawnerRepresentation(PickupSpawner* spawner); //!< Get the default spawnerRepresentation for a specific PickupSpawner.
+
+            void registerVariables(void); //!< Registers the variables that need to be synchronised.
+
+            std::string name_; //!< The name of the Pickupable represented by this PickupRepresentation.
+            std::string description_; //!< The description of the Pickupable represented by this PickupRepresentation.
+            std::string spawnerTemplate_; //!<  The name of the template of this PickupRepresentation.
+            StaticEntity* spawnerRepresentation_; //!< The spawnerRepresentation of this PickupRepresentation.
+            std::string inventoryRepresentation_; //!< The name of an image representing the pickup in the PickupInventory.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif // _PickupRepresentation_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupSpawner.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupSpawner.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupSpawner.cc	(revision 11817)
@@ -0,0 +1,334 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Daniel 'Huty' Haggenmueller
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file PickupSpawner.cc
+    @brief Implementation of the PickupSpawner class.
+*/
+
+#include "PickupSpawner.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+#include "PickupManager.h"
+#include "PickupRepresentation.h"
+
+namespace orxonox
+{
+
+    RegisterClass(PickupSpawner);
+
+    /**
+    @brief
+        Constructor. Creates a blank PickupSpawner.
+    */
+    PickupSpawner::PickupSpawner(Context* context) : StaticEntity(context), pickup_(nullptr), representation_(nullptr), pickupTemplate_(nullptr)
+    {
+        RegisterObject(PickupSpawner);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Registers the object and sets some default values.
+    */
+    void PickupSpawner::initialize(void)
+    {
+        this->triggerDistance_ = 10;
+        this->respawnTime_ = 5.0f;
+        this->maxSpawnedItems_ = INF;
+        this->spawnsRemaining_ = INF;
+        this->selfDestruct_ = false;
+
+        this->setPickupable(nullptr);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    PickupSpawner::~PickupSpawner()
+    {
+        if(this->isInitialized() && this->selfDestruct_ && this->pickup_ != nullptr)
+            this->pickup_->destroy();
+    }
+
+    /**
+    @brief
+        Factory method, Creates a fully functional PickupSpawner.
+    @param context
+        The context of this PickupSpawner.
+    @param pickup
+        The Pickupable to be spawned by this PickupSpawner.
+    @param carrier
+        The PickupCarrier that carried the input pickup before it was dropped.
+    @param triggerDistance
+        The distance at which the PickupSpawner will trigger.
+    */
+    /*static*/ PickupSpawner* PickupSpawner::createDroppedPickup(Context* context, Pickupable* pickup, PickupCarrier* carrier, float triggerDistance)
+    {
+        PickupSpawner* spawner = new PickupSpawner(context);
+
+        spawner->setPickupable(pickup);
+        spawner->setTriggerDistance(triggerDistance);
+        spawner->setMaxSpawnedItems(1);
+
+        spawner->setPosition(carrier->getCarrierPosition());
+        spawner->block(carrier);
+
+        return spawner;
+    }
+
+    /**
+    @brief
+        Method for creating a PickupSpawner through XML.
+    @param xmlelement
+        XML element which contains the PickupSpawner.
+    @param mode
+        XMLPort mode.
+    */
+    void PickupSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PickupSpawner, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PickupSpawner, "pickup", setPickupTemplateName, getPickupTemplateName, xmlelement, mode);
+        XMLPortParam(PickupSpawner, "triggerDistance", setTriggerDistance, getTriggerDistance, xmlelement, mode);
+        XMLPortParam(PickupSpawner, "respawnTime", setRespawnTime, getRespawnTime, xmlelement, mode);
+        XMLPortParam(PickupSpawner, "maxSpawnedItems", setMaxSpawnedItems, getMaxSpawnedItems, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Tick, checks if any Pawn is close enough to trigger.
+    @param dt
+        Time since last tick.
+    */
+    //TODO: Replace with collisions?
+    void PickupSpawner::tick(float dt)
+    {
+        SUPER(PickupSpawner, tick, dt);
+
+        // If the PickupSpawner is active.
+        if(GameMode::isMaster() && this->isActive())
+        {
+            // TODO: why is this a WeakPtr when the comment says StrongPtr?
+            WeakPtr<PickupSpawner> spawner = this; // Create a strong pointer to keep the PickupSpawner alive until we iterated through all Pawns (in case a Pawn takes the last pickup)
+
+            // Remove PickupCarriers from the blocked list if they have exceeded their time.
+            for(std::map<PickupCarrier*, std::time_t>::iterator it = this->blocked_.begin(); it != this->blocked_.end(); )
+            {
+                std::map<PickupCarrier*, std::time_t>::iterator temp = it;
+                it++;
+                if(temp->second < std::time(0))
+                    this->blocked_.erase(temp);
+            }
+
+            // Iterate trough all Pawns.
+            for(Pawn* pawn : ObjectList<Pawn>())
+            {
+                if(!(pawn->doesAcceptPickups())){continue;} // skip those pawns, e.g. AsteroidMinables. 
+
+                Vector3 distance = pawn->getWorldPosition() - this->getWorldPosition();
+                PickupCarrier* carrier = static_cast<PickupCarrier*>(pawn);
+                // If a PickupCarrier, that fits the target-range of the Pickupable spawned by this PickupSpawner, is in trigger-distance and the carrier is not blocked.
+                if(distance.length() < this->triggerDistance_ && carrier != nullptr && this->blocked_.find(carrier) == this->blocked_.end())
+                {
+                    if(carrier->isTarget(this->pickup_))
+                    {
+                        this->trigger(pawn); // Attention: after this line, pickup_ is probably nullptr (because it was taken) and even spawner can be nullptr (if it run out of pickups)!
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        Trigger the PickupSpawner.
+        Adds the pickup to the Pawn that triggered, sets the timer to re-activate and deactives the PickupSpawner.
+    @param carrier
+        Carrier which triggered the PickupSpawner.
+    */
+    void PickupSpawner::trigger(PickupCarrier* carrier)
+    {
+        orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") triggered and active." << endl;
+
+        PickupCarrier* target = carrier->getTarget(this->pickup_);
+
+        this->block(carrier);
+
+        assert(target);
+        bool pickedUp = this->pickup_->pickup(target);
+        assert(pickedUp);
+        (void)pickedUp; // To avoid compiler warning.
+
+        this->setPickupable(nullptr);
+        this->decrementSpawnsRemaining();
+    }
+
+    void PickupSpawner::setPickupTemplateName(const std::string& name)
+    {
+        Template* temp = Template::getTemplate(name);
+        if (temp)
+            this->setPickupTemplate(temp);
+    }
+
+    void PickupSpawner::setPickupTemplate(Template* temp)
+    {
+        this->pickupTemplate_ = temp;
+        this->pickupTemplateName_ = temp->getName();
+
+        this->setPickupable(this->createPickup());
+    }
+
+    /**
+    @brief
+        Sets the maximum number of spawned items.
+    @param items
+        The maximum number of spawned items to be set.
+    */
+    void PickupSpawner::setMaxSpawnedItems(int items)
+    {
+        this->maxSpawnedItems_ = items;
+        this->spawnsRemaining_ = items;
+    }
+
+    /**
+    @brief
+        Decrements the number of remaining spawns.
+        Sets the PickupSpawner to inactive for the duration of the respawnTime.
+        Destroys the PickupSpawner if the number of remaining spawns has reached zero.
+    */
+    void PickupSpawner::decrementSpawnsRemaining(void)
+    {
+        if(this->spawnsRemaining_ != INF)
+            this->spawnsRemaining_--;
+
+        this->setActive(false);
+
+        if(this->spawnsRemaining_ != 0 && this->respawnTime_ > 0)
+        {
+            this->startRespawnTimer();
+            this->fireEvent();
+        }
+        else
+        {
+            orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") empty, selfdestruct initialized." << endl;
+            this->destroy();
+        }
+    }
+
+    /**
+    @brief
+        Starts the respawn timer.
+    */
+    void PickupSpawner::startRespawnTimer(void)
+    {
+        this->respawnTimer_.setTimer(this->respawnTime_, false, createExecutor(createFunctor(&PickupSpawner::respawnTimerCallback, this)));
+    }
+
+    /**
+    @brief
+        Invoked by the timer, re-activates the PickupSpawner.
+    */
+    void PickupSpawner::respawnTimerCallback()
+    {
+        orxout(verbose, context::pickups) << "PickupSpawner (&" << this << ") reactivated." << endl;
+
+        this->setPickupable(this->createPickup());
+    }
+
+    /**
+    @brief
+        Creates a new Pickupable.
+    @return
+        The Pickupable created.
+    */
+    Pickupable* PickupSpawner::createPickup(void)
+    {
+        if(this->spawnsRemaining_ == 0)
+        {
+            orxout(internal_error, context::pickups) << "Massive Error: PickupSpawner still alive until having spawned last item." << endl;
+            return nullptr;
+        }
+
+        if (this->pickupTemplate_ != nullptr)
+        {
+            Identifier* identifier = this->pickupTemplate_->getBaseclassIdentifier();
+            if (identifier != nullptr)
+            {
+                Pickupable* pickup = orxonox_cast<Pickupable*>(identifier->fabricate(this->getContext()));
+                orxonox_cast<BaseObject*>(pickup)->addTemplate(this->pickupTemplate_);
+                return pickup;
+            }
+            else
+                orxout(internal_error, context::pickups) << "No base class defined in pickup-template " << this->pickupTemplateName_ << endl;
+        }
+
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Sets a Pickupable for the PickupSpawner to spawn.
+    @param pickup
+        The Pickupable to be set.
+    */
+    void PickupSpawner::setPickupable(Pickupable* pickup)
+    {
+        if (this->representation_ != nullptr)
+        {
+            this->representation_->destroy();
+            this->representation_ = nullptr;
+        }
+
+        if (pickup != nullptr)
+        {
+            if (this->pickup_ != nullptr)
+                this->pickup_->destroy();
+
+            PickupRepresentation* representation = PickupManager::getInstance().getRepresentation(pickup->getRepresentationName());
+            this->representation_ = representation->createSpawnerRepresentation(this);
+            this->attach(this->representation_);
+            this->setActive(true);
+        }
+        else
+        {
+            this->setActive(false);
+        }
+
+        this->pickup_ = pickup;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/PickupSpawner.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/PickupSpawner.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/PickupSpawner.h	(revision 11817)
@@ -0,0 +1,174 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Daniel 'Huty' Haggenmueller
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file PickupSpawner.h
+    @brief Definition of the PickupSpawner class.
+    @ingroup Pickup
+*/
+
+#ifndef _PickupSpawner_H__
+#define _PickupSpawner_H__
+
+#include "PickupPrereqs.h"
+
+#include <map>
+#include <string>
+#include "tools/Timer.h"
+
+#include "interfaces/Pickupable.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    /**
+        @brief
+            The PickupSpawner class is responsible for spawning @ref orxonox::Pickupable "Pickupables" of a specific type.
+            Furthermore it can be specified how long the time interval between spawning two items is and how many @ref orxonox::Pickupable "Pickupables" are spawned at maximum, amongst other things. The parameters that can be used to further specify the behaviour of the PickupSpawner are:
+            - The <b>triggerDistance</b> can be used to specify how far away an entity has to be to still trigger the PickupSPawner (and thus receive a @ref orxonox::Pickupable "Pickupable" form it). The default is 10.
+            - The <b>respawnTime</b> is the time in seconds that passes until the PickupSpawner is enabled again, after having spawned a @ref orxonox::Pickupable "Pickupable". The default is 0.
+            - The <b>maxSpawnedItems</b> is the number of @ref orxonox::Pickupable "Pickupables" that are spawned by this PickupSpawner at the most. The default is -1, which denotes infinity.
+
+            A PickupSpawner is created in XML, which can be done in the following fashion:
+            @code
+            <PickupSpawner position="-100,0,-100" respawnTime="30" maxSpawnedItems="10">
+                <pickup>
+                    <SomePickup >
+                </pickup>
+            </PickupSpawner>
+            @endcode
+            As we can see, since the PickupSpawner is a StaticEntity, it also has spatial coordinates. We can also see, that the type of @ref orxonox::Pickupable "Pickupable" which is spawned hast to be specified as well.
+
+        @author
+            Daniel 'Huty' Haggenmueller
+        @author
+            Damian 'Mozork' Frick
+
+        @ingroup Pickup
+    */
+    class _PickupExport PickupSpawner : public StaticEntity, public Tickable
+    {
+        public:
+            PickupSpawner(Context* context); //!< Default Constructor.
+            virtual ~PickupSpawner(); //!< Destructor.
+
+            static PickupSpawner* createDroppedPickup(Context* context, Pickupable* pickup, PickupCarrier* carrier, float triggerDistance = 10.0);
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;  //!< Method for creating a PickupSpawner through XML.
+            virtual void tick(float dt) override; //!< Tick, checks if any Pawn is close enough to trigger.
+
+            /**
+            @brief Get the distance in which to trigger.
+            @return Returns the distance in which this gets triggered.
+            */
+            inline float getTriggerDistance() const
+                { return this->triggerDistance_; }
+            /**
+            @brief Set the distance in which to trigger.
+            @param value The new distance in which to trigger.
+            */
+            inline void setTriggerDistance(float value)
+                { this->triggerDistance_ = value; }
+            /**
+            @brief Get the time to respawn.
+            @returns Returns the time after which this gets re-actived.
+            */
+            inline float getRespawnTime() const
+                { return this->respawnTime_; }
+            /**
+            @brief Set the time to respawn.
+            @param time New time after which this gets re-actived.
+            */
+            inline void setRespawnTime(float time)
+                { this->respawnTime_ = time; }
+            /**
+            @brief Get the maximum number of items that will be spawned by this PickupSpawner.
+            @return Returns the maximum number of items spawned by this PickupSpawner.
+            */
+            inline int getMaxSpawnedItems(void) const
+                { return this->maxSpawnedItems_; }
+            void setMaxSpawnedItems(int items); //!< Sets the maximum number of spawned items.
+
+            /**
+            @brief Returns the name of the template which is used to create a pickup for this spawner.
+            */
+            inline const std::string& getPickupTemplateName() const
+                { return this->pickupTemplateName_; }
+            /**
+            @brief Returns the template which is used to create a pickup for this spawner.
+            */
+            inline Template* getPickupTemplate() const
+                {return this->pickupTemplate_; }
+
+            void setPickupTemplateName(const std::string& name);
+            void setPickupTemplate(Template* temp);
+
+        private:
+            void initialize(void);
+
+            void trigger(PickupCarrier* carrier); //!< Method called when a carrier is close enough.
+            void respawnTimerCallback(); //!< Method called when the timer runs out.
+
+            void decrementSpawnsRemaining(void); //!< Decrements the number of remaining spawns.
+            void startRespawnTimer(void); //!< Invoked by the timer, re-activates the PickupSpawner.
+
+            /**
+            @brief Helper method. Adds a PickupCarrier to the list of PickupCarrier that are blocked form getting a Pickupable from the PickupSpawner for a specified time.
+            @param carrier A pointer to the PickupCarrier to be blocked.
+            @param time The time for which the Pawn is blocked. Default is 5.
+            */
+            void block(PickupCarrier* carrier, unsigned int time = DEFAULT_BLOCKED_TIME)
+                { this->blocked_.insert(std::pair<PickupCarrier*, std::time_t>(carrier, std::time(0)+time)); }
+
+            Pickupable* createPickup(void); //!< Creates a new Pickupable.
+            void setPickupable(Pickupable* pickup); //!< Sets a Pickupable for the PickupSpawner to spawn.
+
+            Pickupable* pickup_; //!< The pickup to be spawned.
+            StaticEntity* representation_; //!< The active representation of the spawner.
+            std::string pickupTemplateName_; //!< The name of the pickup template.
+            Template* pickupTemplate_; //!< The template to be used to create a pickupable.
+
+            int maxSpawnedItems_; //!< Maximum number of items spawned by this PickupSpawner.
+            int spawnsRemaining_; //!< Number of items that can be spawned by this PickupSpawner until it selfdestructs.
+
+            float triggerDistance_; //!< Distance in which this gets triggered.
+
+            float respawnTime_; //!< Time after which this gets re-actived.
+            Timer respawnTimer_; //!< Timer used for re-activating.
+            std::map<PickupCarrier*, std::time_t> blocked_;
+
+            bool selfDestruct_; //!< True if the PickupSpawner is selfdestructing.
+
+            static const int INF = -1; //!< Constant for infinity.
+            static const unsigned int DEFAULT_BLOCKED_TIME = 5; //!< The default time a PickupCarrier is blocked after picking up a Pickupable.
+    };
+}
+
+#endif /* _PickupSpawner_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/BoostPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/BoostPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/BoostPickup.cc	(revision 11817)
@@ -0,0 +1,147 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BoostPickup.cc
+    @brief Implementation of the BoostPickup class.
+*/
+
+#include "BoostPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    RegisterClass(BoostPickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    BoostPickup::BoostPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(BoostPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    BoostPickup::~BoostPickup()
+    {
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void BoostPickup::initialize(void)
+    {
+        this->boostRefill_ = 0.0f;
+        //Defines who is allowed to pick up the pickup.
+        this->addTarget(ClassIdentifier<SpaceShip>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a BoostPickup object through XML.
+    */
+    void BoostPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(BoostPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(BoostPickup, "boostrefill", setBoostRefill, getBoostRefill, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Set the boost refill of this pickup.
+    */
+    void BoostPickup::setBoostRefill(float boostRefill)
+    {
+        if(boostRefill >= 0.0f && boostRefill <= 1.0f)
+        {
+            this->boostRefill_ = boostRefill;
+        }
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transisted from used to unused or the other way around.
+    */
+    void BoostPickup::changedUsed(void)
+    {
+        SUPER(BoostPickup, changedUsed);
+
+        SpaceShip* ship = this->carrierToSpaceShipHelper();
+        if(ship == nullptr) // If the PickupCarrier is no SpaceShip, then this pickup is useless and therefore is destroyed.
+            this->Pickupable::destroy();
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+            float gainedBoostPower = ship->getInitialBoostPower() * boostRefill_;
+            ship->gainBoostPower(gainedBoostPower);
+
+            // This will destroy the pickp
+            this->setUsed(false);
+        }
+        else
+        {
+            this->Pickupable::destroy();
+        }
+    }
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a SpaceShip, and throw an error message if the conversion fails.
+    @return
+        A pointer to the SpaceShip, or nullptr if the conversion failed.
+    */
+    SpaceShip* BoostPickup::carrierToSpaceShipHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        SpaceShip* ship = orxonox_cast<SpaceShip*>(carrier);
+
+        if(ship == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in BoostPickup." << endl;
+        }
+
+        return ship;
+    }
+
+
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/BoostPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/BoostPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/BoostPickup.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BoostPickup.h
+    @brief Declaration of the BoostPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _BoostPickup_H__
+#define _BoostPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+
+namespace orxonox
+{
+
+    class _PickupExport BoostPickup : public Pickup
+    {
+        public:
+
+            BoostPickup(Context* context); //!< Constructor.
+            virtual ~BoostPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode) override; //!< Method for creating a BoostPickup object through XML.
+
+            virtual void changedUsed(void) override; //!< Is called when the pickup has transited from used to unused or the other way around.
+            inline float getBoostRefill()
+                { return this->boostRefill_; }
+
+        protected:
+            void setBoostRefill(float boostRefill); //!< Sets the boost refill according to the XML.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+            SpaceShip* carrierToSpaceShipHelper(void); //!< Helper to transform the PickupCarrier to a SpaceShip, and throw an error message if the conversion fails.
+
+            float boostRefill_; //!< The amount of boost refilled by the user of the pickup. 1.0 means full refill, 0.5 means half refill.
+    };
+}
+
+#endif /* _BoostPickup_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,13 @@
+ADD_SOURCE_FILES(PICKUP_SRC_FILES
+  HealthPickup.cc
+  InvisiblePickup.cc
+  MetaPickup.cc
+  DronePickup.cc
+  SpeedPickup.cc
+  ShieldPickup.cc
+  ShrinkPickup.cc
+  DamageBoostPickup.cc
+  BoostPickup.cc
+  MunitionPickup.cc
+  MunitionContainer.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/DamageBoostPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/DamageBoostPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/DamageBoostPickup.cc	(revision 11817)
@@ -0,0 +1,198 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin Lengauer
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DamageBoostPickup.cc
+    @brief Implementation of the DamageBoostPickup class.
+*/
+
+#include "DamageBoostPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    RegisterClass(DamageBoostPickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    DamageBoostPickup::DamageBoostPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(DamageBoostPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    DamageBoostPickup::~DamageBoostPickup()
+    {
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void DamageBoostPickup::initialize(void)
+    {
+        this->duration_ = 0.0f;
+        this->damageMultiplier_ = 1.0f; //The default damage multiplier.
+        //Defines who is allowed to pick up the pickup.
+        this->addTarget(ClassIdentifier<SpaceShip>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a DamageBoostPickup object through XML.
+    */
+    void DamageBoostPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(DamageBoostPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DamageBoostPickup, "duration", setDuration, getDuration, xmlelement, mode);
+        XMLPortParam(DamageBoostPickup, "damageMultiplier", setDamageMultiplier, getDamageMultiplier, xmlelement, mode);
+    }
+
+    // Work in Progress setDamage Function
+    void DamageBoostPickup::setDamageMultiplier(float damageMultiplier)
+    {
+        if(damageMultiplier >= 1.0f)
+        {
+            this->damageMultiplier_ = damageMultiplier;
+        }
+    }
+
+
+    /**
+    @brief
+        Is called when the pickup has transisted from used to unused or the other way around.
+    */
+    void DamageBoostPickup::changedUsed(void)
+    {
+        SUPER(DamageBoostPickup, changedUsed);
+
+        SpaceShip* ship = this->carrierToSpaceShipHelper();
+        if(ship == nullptr) // If the PickupCarrier is no SpaceShip, then this pickup is useless and therefore is destroyed.
+            this->Pickupable::destroy();
+
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+            // If its durationType is continuous, we set a Timer to be reminded, when the time has run out.
+            if(this->isContinuous())
+            {
+                if(!this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() > 0.0f)
+                {
+                    this->durationTimer_.unpauseTimer();
+                }
+                else
+                {
+                    this->durationTimer_.setTimer(this->getDuration(), false, createExecutor(createFunctor(&DamageBoostPickup::pickupTimerCallback, this)));
+                }
+            }
+
+            // Saves the old default Damage that is needed to restore the original damage
+            this->olddamageMultiplier_ = 1.0f;
+            // Sets the new Damage with the damage multiplier
+            ship->setDamageMultiplier(this->getDamageMultiplier());
+        }
+        else
+        {
+
+            // We destroy the pickup if either, the pickup has activationType immediate and durationType once or it has durationType continuous and the duration was exceeded.
+            if((!this->isContinuous() && this->isImmediate()) || (this->isContinuous() && !this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() == this->getDuration()))
+            {
+                this->Pickupable::destroy();
+                ship->setDamageMultiplier ( this->olddamageMultiplier_);
+            }
+            // We pause the Timer if the pickup is continuous and the duration is not yet exceeded,
+            else if(this->isContinuous() && this->durationTimer_.isActive())
+            {
+                this->durationTimer_.pauseTimer();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a SpaceShip, and throw an error message if the conversion fails.
+    @return
+        A pointer to the SpaceShip, or nullptr if the conversion failed.
+    */
+    SpaceShip* DamageBoostPickup::carrierToSpaceShipHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        SpaceShip* ship = orxonox_cast<SpaceShip*>(carrier);
+
+        if(ship == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in DamageBoostPickup." << endl;
+        }
+
+        return ship;
+    }
+
+    /**
+    @brief
+        Sets the duration for which the DamageBoostPickup stays active.
+    @param duration
+        The duration in seconds.
+    */
+    void DamageBoostPickup::setDuration(float duration)
+    {
+        if(duration >= 0.0f)
+        {
+            this->duration_ = duration;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid duration in DamagePickup." << endl;
+            this->duration_ = 0.0f;
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Is called by the Timer as soon as it expires.
+    */
+    void DamageBoostPickup::pickupTimerCallback(void)
+    {
+        this->setUsed(false);
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/DamageBoostPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/DamageBoostPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/DamageBoostPickup.h	(revision 11817)
@@ -0,0 +1,99 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin Lengauer
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DamageBoostPickup.h
+    @brief Declaration of the DamageBoostPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _DamageBoostPickup_H__
+#define _DamageBoostPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox {
+
+    class _PickupExport DamageBoostPickup : public Pickup, public Tickable
+    {
+        public:
+
+            DamageBoostPickup(Context* context); //!< Constructor.
+            virtual ~DamageBoostPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a DamageBoostPickup object through XML.
+
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            /**
+            @brief Get the time the DamagePickup lasts.
+            @return Returns the time in seconds the DamagePickup lasts.
+            */
+            inline float getDuration(void) const
+                { return this->duration_; }
+
+            inline void setDuration( float duration );
+
+
+
+            /**
+             @brief Get Damage multiplier
+             */
+            inline float getDamageMultiplier()
+                { return this->damageMultiplier_; }
+
+
+
+
+        protected:
+            void setDamageMultiplier(float damageMultiplier); //!< Sets the DamageMultiplier according to the XML.
+
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+            SpaceShip* carrierToSpaceShipHelper(void); //!< Helper to transform the PickupCarrier to a SpaceShip, and throw an error message if the conversion fails.
+            void pickupTimerCallback(void);
+
+
+
+            float damageMultiplier_; //!< The damage boost that is transferred to the Pawn.
+            float olddamageMultiplier_; //!< Helper to remember what the actual damage of the Pawn was before we changed it.
+
+            Timer durationTimer_; //!< Timer.
+            float duration_; //! Duration of damage boost.
+
+    };
+}
+
+#endif // _DamageBoostPickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/DronePickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/DronePickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/DronePickup.cc	(revision 11817)
@@ -0,0 +1,172 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Lukas Gasser
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DronePickup.cc
+    @brief Implementation of the DronePickup class.
+*/
+
+#include "DronePickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "controllers/DroneController.h"
+#include "worldentities/Drone.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+
+    RegisterClass(DronePickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    DronePickup::DronePickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(DronePickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    DronePickup::~DronePickup()
+    {
+
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void DronePickup::initialize(void)
+    {
+        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
+        this->setDurationType(PickupDurationType::once);
+        this->droneTemplate_ = "";
+    }
+
+    /**
+    @brief
+        Method for creating a DronePickup object through XML.
+    */
+    void DronePickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(DronePickup, XMLPort, xmlelement, mode);
+        XMLPortParam(DronePickup, "droneTemplate", setDroneTemplate, getDroneTemplate, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Set the droneTemplate.
+    @param templatename
+        The name of the Template to e set.
+    */
+    void DronePickup::setDroneTemplate(const std::string& templatename){
+        droneTemplate_ = templatename;
+    }
+
+    /**
+    @brief
+        Get the name of the droneTemplate.
+    @return
+        Returns the name of the droneTemplate.
+    */
+    const std::string& DronePickup::getDroneTemplate() const
+    {
+        return droneTemplate_;
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
+    void DronePickup::changedUsed(void)
+    {
+        SUPER(DronePickup, changedUsed);
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+
+                Pawn* pawn = this->carrierToPawnHelper();
+                if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                    this->Pickupable::destroy();
+
+                //Attach to pawn
+                Drone* drone = new Drone(pawn->getContext()); // this is neccessary because the projectiles fired need a valid creator for the particlespawner (when colliding against something)
+                drone->addTemplate(this->getDroneTemplate());
+
+                Controller* controller = drone->getController();
+                DroneController* droneController = orxonox_cast<DroneController*>(controller);
+                if(droneController != nullptr)
+                {
+                    droneController->setOwner(pawn);
+                }
+
+                Vector3 spawnPosition = pawn->getWorldPosition() + Vector3(30,0,-30);
+                drone->setPosition(spawnPosition);
+
+                // The pickup has been used up.
+                this->setUsed(false);
+        }
+        else
+        {
+            // If either the pickup can only be used once or it is continuous and used up, it is destroyed upon setting it to unused.
+            if(this->isOnce() || (this->isContinuous() ))
+            {
+                this->Pickupable::destroy();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    @return
+        A pointer to the Pawn, or nullptr if the conversion failed.
+    */
+    Pawn* DronePickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+        if(pawn == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in DronePickup." << endl;
+        }
+
+        return pawn;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/DronePickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/DronePickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/DronePickup.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Lukas Gasser
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file DronePickup.h
+    @brief Declaration of the DronePickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _DronePickup_H__
+#define _DronePickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The DronePickup adds a Drone to the Pawn upon being picked up.
+
+        It can be used in XML as follows:
+        @code
+        <DronePickup droneTemplate="myDroneTemplate" />
+        @endcode
+        Where <em>droneTemplate</em> specifies a @ref orxonox::Template "Template" based on which the Drone is created.
+
+    @author
+        Lukas Gassner
+
+    @ingroup PickupItems
+    */
+    class _PickupExport DronePickup : public Pickup, public Tickable
+    {
+        public:
+
+            DronePickup(Context* context); //!< Constructor.
+            virtual ~DronePickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a DronePickup object through XML.
+
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            const std::string& getDroneTemplate() const; //!< Get the name of the droneTemplate.
+
+        protected:
+            void setDroneTemplate(const std::string& templatename); //!< Set the droneTemplate.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            std::string droneTemplate_; //!< The name of the template, based upon which the Drone is created.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    };
+}
+
+#endif // _DronePickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/HealthPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/HealthPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/HealthPickup.cc	(revision 11817)
@@ -0,0 +1,319 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HealthPickup.cc
+    @brief Implementation of the HealthPickup class.
+*/
+
+#include "HealthPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+
+    /*static*/ const std::string HealthPickup::healthTypeLimited_s = "limited";
+    /*static*/ const std::string HealthPickup::healthTypeTemporary_s = "temporary";
+    /*static*/ const std::string HealthPickup::healthTypePermanent_s = "permanent";
+
+    RegisterClass(HealthPickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    HealthPickup::HealthPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(HealthPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    HealthPickup::~HealthPickup()
+    {
+
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void HealthPickup::initialize(void)
+    {
+        this->health_ = 0.0f;
+        this->healthRate_ = 0.0f;
+        this->healthType_ = PickupHealthType::limited;
+        this->maxHealthSave_ = 0.0f;
+        this->maxHealthOverwrite_ = 0.0f;
+
+        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a HealthPickup object through XML.
+    */
+    void HealthPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(HealthPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HealthPickup, "health", setHealth, getHealth, xmlelement, mode);
+        XMLPortParam(HealthPickup, "healthRate", setHealthRate, getHealthRate, xmlelement, mode);
+        XMLPortParam(HealthPickup, "healthType", setHealthTypeAsString, getHealthTypeAsString, xmlelement, mode);
+
+        if(!this->isContinuous())
+            this->setHealthRate(0.0f); // TODO: this logic should be inside tick(), not in XMLPort
+    }
+
+    /**
+    @brief
+        Is called every tick.
+        Does all the continuous stuff of this HealthPickup.
+    @param dt
+        The duration of the last tick.
+    */
+    void HealthPickup::tick(float dt)
+    {
+        SUPER(HealthPickup, tick, dt);
+
+        if(this->isContinuous() && this->isUsed())
+        {
+            Pawn* pawn = this->carrierToPawnHelper();
+            if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                this->Pickupable::destroy();
+
+            // Calculate the health that is added this tick.
+            float health = dt*this->getHealthRate();
+            if(health > this->getHealth())
+                health = this->getHealth();
+            // Calculate the health the Pawn will have once the health is added.
+            float fullHealth = pawn->getHealth() + health;
+            this->setHealth(this->getHealth()-health);
+
+            switch(this->getHealthType())
+            {
+                case PickupHealthType::permanent:
+                    if(pawn->getMaxHealth() < fullHealth)
+                        pawn->setMaxHealth(fullHealth);
+                case PickupHealthType::limited:
+                    pawn->addHealth(health);
+                    break;
+                case PickupHealthType::temporary:
+                    if(pawn->getMaxHealth() > fullHealth)
+                    {
+                        this->maxHealthSave_ = pawn->getMaxHealth();
+                        this->maxHealthOverwrite_ = fullHealth;
+                        pawn->setMaxHealth(fullHealth);
+                    }
+                    pawn->addHealth(health);
+                    break;
+                default:
+                    orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
+            }
+
+            // If all health has been transferred.
+            if(this->getHealth() == 0.0f)
+            {
+                this->setUsed(false);
+            }
+        }
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
+    void HealthPickup::changedUsed(void)
+    {
+        SUPER(HealthPickup, changedUsed);
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+            if(this->isOnce())
+            {
+                Pawn* pawn = this->carrierToPawnHelper();
+                if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                    this->Pickupable::destroy();
+
+                float health = 0.0f;
+                switch(this->getHealthType())
+                {
+                    case PickupHealthType::permanent:
+                        health = pawn->getHealth()+this->getHealth();
+                        if(pawn->getMaxHealth() < health)
+                            pawn->setMaxHealth(health);
+                    case PickupHealthType::limited:
+                        pawn->addHealth(this->getHealth());
+                        break;
+                    case PickupHealthType::temporary:
+                        health = pawn->getHealth()+this->getHealth();
+                        if(pawn->getMaxHealth() < health)
+                        {
+                            this->maxHealthSave_ = pawn->getMaxHealth();
+                            this->maxHealthOverwrite_ = health;
+                            pawn->setMaxHealth(health);
+                        }
+                        pawn->addHealth(this->getHealth());
+                        break;
+                    default:
+                        orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
+                }
+
+                // The pickup has been used up.
+                this->setUsed(false);
+            }
+        }
+        else
+        {
+            if(this->getHealthType() == PickupHealthType::temporary)
+            {
+                PickupCarrier* carrier = this->getCarrier();
+                Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+                if(pawn == nullptr)
+                {
+                    orxout(internal_error, context::pickups) << "Something went horribly wrong in Health Pickup. PickupCarrier is '" << carrier->getIdentifier()->getName() << "' instead of Pawn." << endl;
+                    this->Pickupable::destroy();
+                    return;
+                }
+
+                if(pawn->getMaxHealth() == this->maxHealthOverwrite_)
+                {
+                    pawn->setMaxHealth(this->maxHealthSave_);
+                    this->maxHealthOverwrite_ = 0;
+                    this->maxHealthSave_ = 0;
+                }
+            }
+
+            // If either the pickup can only be used once or it is continuous and used up, it is destroyed upon setting it to unused.
+            if(this->isOnce() || (this->isContinuous() && this->getHealth() == 0.0f))
+            {
+                this->Pickupable::destroy();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    @return
+        A pointer to the Pawn, or nullptr if the conversion failed.
+    */
+    Pawn* HealthPickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+        if(pawn == nullptr)
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in HealthPickup." << endl;
+
+        return pawn;
+    }
+
+    /**
+    @brief
+        Get the health type of this pickup.
+    @return
+        Returns the health type as a string.
+    */
+    const std::string& HealthPickup::getHealthTypeAsString(void) const
+    {
+        switch(this->getHealthType())
+        {
+            case PickupHealthType::limited:
+                return HealthPickup::healthTypeLimited_s;
+            case PickupHealthType::temporary:
+                return HealthPickup::healthTypeTemporary_s;
+            case PickupHealthType::permanent:
+                return HealthPickup::healthTypePermanent_s;
+            default:
+                orxout(internal_error, context::pickups) << "Invalid healthType in HealthPickup." << endl;
+                return BLANKSTRING;
+        }
+    }
+
+    /**
+    @brief
+        Sets the health.
+    @param health
+        The health.
+    */
+    void HealthPickup::setHealth(float health)
+    {
+        if(health >= 0.0f)
+            this->health_ = health;
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid health '" << health << "' in HealthPickup. The health must be non.negative." << endl;
+            this->health_ = 0.0f;
+        }
+    }
+
+    /**
+    @brief
+        Set the rate at which health is transferred if the pickup is continuous.
+    @param rate
+        The rate.
+    */
+    void HealthPickup::setHealthRate(float rate)
+    {
+        if(rate >= 0.0f)
+            this->healthRate_ = rate;
+        else
+            orxout(internal_error, context::pickups) << "Invalid healthRate '" << rate << "' in HealthPickup. The healthRate must be non-negative." << endl;
+    }
+
+    /**
+    @brief
+        Set the type of the HealthPickup.
+    @param type
+        The type as a string.
+    */
+    void HealthPickup::setHealthTypeAsString(const std::string& type)
+    {
+        if(type == HealthPickup::healthTypeLimited_s)
+            this->setHealthType(PickupHealthType::limited);
+        else if(type == HealthPickup::healthTypeTemporary_s)
+            this->setHealthType(PickupHealthType::temporary);
+        else if(type == HealthPickup::healthTypePermanent_s)
+            this->setHealthType(PickupHealthType::permanent);
+        else
+            orxout(internal_error, context::pickups) << "Invalid healthType '" << type << "' in HealthPickup." << endl;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/HealthPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/HealthPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/HealthPickup.h	(revision 11817)
@@ -0,0 +1,148 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HealthPickup.h
+    @brief Declaration of the HealthPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _HealthPickup_H__
+#define _HealthPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        Enum for the type of the @ref orxonox::HealthPickup "HealthPickup".
+
+    @ingroup PickupItems
+    */
+    enum class PickupHealthType
+    {
+        limited, //!< Means that the @ref orxonox::HealthPickup "HealthPickup" only increases the users health to its maximum health.
+        temporary, //!< Means that the @ref orxonox::HealthPickup "HealthPickup" temporarily increases the users health even above its maximum health, but only as long as it is in use.
+        permanent //!< Means that the @ref orxonox::HealthPickup "HealthPickup" increases the users health even above its maximum health and increases the maximum health permanently such that it matches the new health.
+    };
+
+    /**
+    @brief
+        The HealthPickup is a Pickupable that can do (dependent upon the parameters) lots of different things to the health of a Pawn.
+        There are 5 parameters that can be chosen:
+        - The @b activationType It can be chosen to be either <em>immediate</em> or <em>onUse</em>. The activation type essentially (as indicated by the name) defines when the health is transferred, either immediately after being picked up or only after the player uses it. The default is <em>immediate</em>.
+        - The @b durationType It can be chosen to be either <em>once</em> or <em>continuous</em>. For <em>once</em> the specified health is transferred once to the Pawn, for <em>continuous</em> the set health is transferred over a span of time at a rate defined by the health rate parameter. The default is <em>once</em>.
+        - The @b health The amount of health that (in a way dependent on the other parameters) is transferred to the Pawn. Default is 0.
+        - The @b healthType The health type can be chosen to be <em>limited</em>, <em>temporary</em> or <em>permanent</em>. <em>limited</em> means that the health is increased only to the maximum health of the Pawn. 'temporary' means that the maximum health is temporarily elevated but will be set back as soon as the pickup is no longer in use. <em>permanent</em> means that the maximum health of the Pawn is increased such that the health provided by the pickup will fit in and the maximum health stays that way. The default is <em>limited</em>.
+        - The @b healthRate If set to continuous, the health that is transferred per second is the <em>healthRate</em>. There is health transferred until the health set by <em>health</em> is depleted. The default is 0.
+
+        An example of a XML implementation of a HealthPickup would be:
+        @code
+        <HealthPickup
+            health = 50
+            healthType = "limited"
+            activationType = "immediate"
+            durationType = "once"
+        />
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup PickupItems
+    */
+    class _PickupExport HealthPickup : public Pickup, public Tickable
+    {
+        public:
+
+            HealthPickup(Context* context); //!< Constructor.
+            virtual ~HealthPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a HealthPickup object through XML.
+            virtual void tick(float dt); //!< Is called every tick.
+
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            /**
+            @brief Get the health that is transferred to the Pawn upon usage of this pickup.
+            @return Returns the health.
+            */
+            inline float getHealth(void) const
+                { return this->health_; }
+            /**
+            @brief Get the rate at which the health is transferred to the Pawn, if this pickup has duration type 'continuous'.
+            @return Returns the rate.
+            */
+            inline float getHealthRate(void) const
+                { return this->healthRate_; }
+
+            /**
+            @brief Get the type of HealthPickup, this pickup is.
+            @return Returns the health type as an enum.
+            */
+            inline PickupHealthType getHealthType(void) const
+                { return this->healthType_; }
+            const std::string& getHealthTypeAsString(void) const; //!< Get the health type of this pickup.
+
+        protected:
+            void setHealth(float health); //!< Sets the health.
+            void setHealthRate(float speed); //!< Set the rate at which health is transferred if the pickup is continuous.
+
+            /**
+            @brief Set the health type of this pickup.
+            @param type The type of this pickup as an enum.
+            */
+            inline void setHealthType(PickupHealthType type)
+                { this->healthType_ = type; }
+            void setHealthTypeAsString(const std::string& type); //!< Set the type of the HealthPickup.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+
+            float health_; //!< The health that is transferred to the Pawn.
+            float healthRate_; //!< The rate at which the health is transferred.
+            float maxHealthSave_; //!< Helper to remember what the actual maxHealth of the Pawn was before we changed it.
+            float maxHealthOverwrite_; //!< Helper to remember with which value we overwrote the maxHealh, to detect if someone else changed it as well.
+            PickupHealthType healthType_; //!< The type of the HealthPickup.
+
+            //! Strings for the health types.
+            static const std::string healthTypeLimited_s;
+            static const std::string healthTypeTemporary_s;
+            static const std::string healthTypePermanent_s;
+
+    };
+}
+
+#endif // _HealthPickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/InvisiblePickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/InvisiblePickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/InvisiblePickup.cc	(revision 11817)
@@ -0,0 +1,207 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benedict Simlinger
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvisiblePickup.cc
+    @brief Implementation of the InvisiblePickup class.
+*/
+
+#include "InvisiblePickup.h"
+
+#include <sstream>
+//#include <OgreEntity.h>
+//#include <OgreAnimationState.h>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+
+    RegisterClass(InvisiblePickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    InvisiblePickup::InvisiblePickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(InvisiblePickup);
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    InvisiblePickup::~InvisiblePickup()
+    {
+    }
+
+    /**
+    @brief
+    Initializes the member variables.
+    */
+    void InvisiblePickup::initialize(void)
+    {
+        this->duration_ = 0.0f;
+        // Defines who is allowed to pick up the pickup.
+        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a HealthPickup object through XML.
+    */
+    void InvisiblePickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(InvisiblePickup, XMLPort, xmlelement, mode);
+        XMLPortParam(InvisiblePickup, "duration", setDuration, getDuration, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
+    void InvisiblePickup::changedUsed(void)
+    {
+        SUPER(InvisiblePickup, changedUsed);
+
+        // If the pickup has transited to used.
+        if (this->isUsed())
+        {
+            // If its durationType is continuous, we set a Timer to be reminded, when the time has run out.
+            if(this->isContinuous())
+            {
+                if(!this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() > 0.0f)
+                {
+                    this->durationTimer_.unpauseTimer();
+                }
+                else
+                {
+                    this->durationTimer_.setTimer(this->getDuration(), false, createExecutor(createFunctor(&InvisiblePickup::pickupTimerCallback, this)));
+                }
+            }
+
+            this->setInvisible(true);
+
+        }
+        else
+        {
+            this->setInvisible(false);
+
+            // We destroy the pickup if either, the pickup has activationType immediate and durationType once or it has durationType continuous and the duration was exceeded.
+            if((!this->isContinuous() && this->isImmediate()) || (this->isContinuous() && !this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() == this->getDuration()))
+            {
+                this->Pickupable::destroy();
+            }
+            // We pause the Timer if the pickup is continuous and the duration is not yet exceeded,
+            else if(this->isContinuous() && this->durationTimer_.isActive())
+            {
+                this->durationTimer_.pauseTimer();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Sets the invisibility.
+    @param invisibility
+        The invisibility.
+    */
+    bool InvisiblePickup::setInvisible(bool invisibility)
+    {
+        Pawn* pawn = this->carrierToPawnHelper();
+        if(pawn == nullptr)
+            return false;
+
+        pawn->setVisible(!invisibility);
+        //TODO: Invisibility should imply radar invisibility as well, thus this should be solved in Pawn.
+        pawn->setRadarVisibility(!invisibility);
+
+// Test to change Material at runtime!
+
+//      Ogre::MaterialPtr mat = this->mesh_.getEntity()->getSubEntity(0)->getMaterial();
+//      mat->setDiffuse(0.4, 0.3, 0.1, 0.1);
+//      mat->setAmbient(0.3, 0.7, 0.8);
+//      mat->setSpecular(0.5, 0.5, 0.5, 0.1);
+//      Ogre::SceneBlendType sbt = Ogre::SBT_ADD;
+//
+//      mat->setSceneBlending(sbt);
+
+        return true;
+    }
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    @return
+        A pointer to the Pawn, or nullptr if the conversion failed.
+    */
+    Pawn* InvisiblePickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+        if(pawn == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in InvisiblePickup." << endl;
+        }
+        return pawn;
+    }
+
+    /**
+    @brief
+        Sets the time the InvisibilityPickup will last.
+    @param duration
+        The duration in seconds.
+    */
+    void InvisiblePickup::setDuration(float duration)
+    {
+        if(duration >= 0.0f)
+        {
+            this->duration_ = duration;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid duration in InvisiblePickup." << endl;
+            this->duration_ = 0.0f;
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Is called by the Timer as soon as it expires.
+    */
+    void InvisiblePickup::pickupTimerCallback(void)
+    {
+        this->setUsed(false);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/InvisiblePickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/InvisiblePickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/InvisiblePickup.h	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benedict Simlinger
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file InvisiblePickup.h
+    @brief Declaration of the InvisiblePickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _InvisiblePickup_H__
+#define _InvisiblePickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        A pickup that makes the Pawn invisible.
+        There are 3 parameters that can be chosen:
+        - The @b activationType It can be chosen to be either <em>immediate</em> or <em>onUse</em>. The activation type essentially (as indicated by the name) defines when the Pawn will be invisible, either immediately after being picked up or only after the player uses it. The default is <em>immediate</em>.
+        - The @b durationType< It can be chosen to be either <em>once</em> or <em>continuous</em>. For <em>once</em> the InvisiblePickup just makes the Pawn invisible for as long as it is used, for <em>continuous</em> the Pawn is invisible for the specified duration. The default is <em>once</em>.
+        - The @b duration Specifies how long (in seconds) the invisibility lasts. The default is 0.
+
+        An example of a XML implementation of a InvisiblePickup would be:
+        @code
+        <InvisiblePickup
+            activationType = "immediate"
+            durationType = "continuous"
+            duration = 30.0
+        />
+        @endcode
+
+    @author
+        Benedict Simlinger
+
+    @ingroup PickupItems
+    */
+    class _PickupExport InvisiblePickup : public Pickup
+    {
+        public:
+
+            InvisiblePickup(Context* context); //!< Constructor.
+            virtual ~InvisiblePickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a HealthPickup object through XML.
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            /**
+            @brief Checks whether the Pawn is invisible.
+            @return Returns if the Pawn is invisible.
+            */
+            inline bool getInvisibility(bool) const
+                { return this->invisible_; }
+            /**
+            @brief Get the time the InvisibilityPickup lasts.
+            @return Returns the time in seconds the InvisibiltyPickup lasts.
+            */
+            inline float getDuration(void) const
+                { return this->duration_; }
+
+        protected:
+            bool setInvisible(bool invisibility); //!< Set the Pawn to be invisible or visible again.
+            void setDuration(float duration); //!< Sets the time the InvisibilityPickup will last.
+
+            void pickupTimerCallback(void); //!< Helper method. Is called by the Timer as soon as it expires.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+
+            Timer durationTimer_; //!< Timer.
+
+            bool invisible_; //!< Helper to remember wether the Pawn is invisible.
+            float duration_; //! Duration of invisibility.
+    };
+}
+
+#endif // _InvisiblePickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/MetaPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/MetaPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/MetaPickup.cc	(revision 11817)
@@ -0,0 +1,203 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file MetaPickup.cc
+    @brief Implementation of the MetaPickup class.
+*/
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "interfaces/PickupCarrier.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "MetaPickup.h"
+
+namespace orxonox {
+
+    RegisterClass(MetaPickup);
+
+    //! Setting the static variables to their values.
+    /*static*/ const std::string MetaPickup::metaTypeNone_s = "none";
+    /*static*/ const std::string MetaPickup::metaTypeUse_s = "use";
+    /*static*/ const std::string MetaPickup::metaTypeDrop_s = "drop";
+    /*static*/ const std::string MetaPickup::metaTypeDestroy_s = "destroy";
+    /*static*/ const std::string MetaPickup::metaTypeDestroyCarrier_s = "destroyCarrier";
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    MetaPickup::MetaPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(MetaPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    MetaPickup::~MetaPickup()
+    {
+
+    }
+
+    /**
+    @brief
+        Initializes the object.
+    */
+    void MetaPickup::initialize(void)
+    {
+        this->addTarget(ClassIdentifier<PickupCarrier>::getIdentifier());
+
+        this->setDurationType(PickupDurationType::once);
+        this->metaType_ = PickupMetaType::none;
+    }
+
+    /**
+    @brief
+        Method for creating a MetaPickup object through XML.
+    */
+    void MetaPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(MetaPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MetaPickup, "metaType", setMetaTypeAsString, getMetaTypeAsString, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+        Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedUsed); to their changdeUsed method.
+    */
+    void MetaPickup::changedUsed(void)
+    {
+        SUPER(MetaPickup, changedUsed);
+
+        // If the MetaPickup transited to used, and the metaType is not none.
+        if(this->isUsed() && this->metaType_ != PickupMetaType::none)
+        {
+            PickupCarrier* carrier = this->getCarrier();
+            if(this->getMetaType() != PickupMetaType::none && carrier != nullptr)
+            {
+                // If the metaType is destroyCarrier, then the PickupCarrier is destroyed.
+                if(this->getMetaType() == PickupMetaType::destroyCarrier)
+                {
+                    Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+                    pawn->kill();
+                    return;
+                }
+                std::set<Pickupable*> pickups = carrier->getPickups();
+                // Iterate over all Pickupables of the PickupCarrier.
+                for(Pickupable* pickup : pickups)
+                {
+                    if(pickup == nullptr || pickup == this)
+                        continue;
+
+                    // If the metaType is use, then the Pickupable is set to used.
+                    if(this->getMetaType() == PickupMetaType::use && !pickup->isUsed())
+                    {
+                        pickup->setUsed(true);
+                    }
+                    // If the metaType is drop, then the Pickupable is dropped.
+                    else if(this->getMetaType() == PickupMetaType::drop)
+                    {
+                        pickup->drop();
+                    }
+                    // If the metaType is destroy, then the Pickupable is destroyed.
+                    else if(this->getMetaType() == PickupMetaType::destroy)
+                    {
+                        pickup->Pickupable::destroy();
+                    }
+                }
+            }
+            this->Pickupable::destroy();
+        }
+    }
+
+    /**
+    @brief
+        Get the meta type of this MetaPickup.
+    @return
+        Returns a string with the meta type of the MetaPickup.
+    */
+    const std::string& MetaPickup::getMetaTypeAsString(void) const
+    {
+        switch(this->getMetaType())
+        {
+            case PickupMetaType::none:
+                return MetaPickup::metaTypeNone_s;
+            case PickupMetaType::use:
+                return MetaPickup::metaTypeUse_s;
+            case PickupMetaType::drop:
+                return MetaPickup::metaTypeDrop_s;
+            case PickupMetaType::destroy:
+                return MetaPickup::metaTypeDestroy_s;
+            case PickupMetaType::destroyCarrier:
+                return MetaPickup::metaTypeDestroyCarrier_s;
+            default:
+                return BLANKSTRING;
+        }
+    }
+
+    /**
+    @brief
+        Set the meta type of this MetaPickup.
+    @param type
+        A string with the type to be set.
+    */
+    void MetaPickup::setMetaTypeAsString(const std::string& type)
+    {
+        if(type == MetaPickup::metaTypeNone_s)
+        {
+            this->setMetaType(PickupMetaType::none);
+        }
+        else if(type == MetaPickup::metaTypeUse_s)
+        {
+            this->setMetaType(PickupMetaType::use);
+        }
+        else if(type == MetaPickup::metaTypeDrop_s)
+        {
+            this->setMetaType(PickupMetaType::drop);
+        }
+        else if(type == MetaPickup::metaTypeDestroy_s)
+        {
+            this->setMetaType(PickupMetaType::destroy);
+        }
+        else if(type == MetaPickup::metaTypeDestroyCarrier_s)
+        {
+            this->setMetaType(PickupMetaType::destroyCarrier);
+        }
+        else
+            orxout(internal_warning, context::pickups) << "Invalid metaType '" << type << "' in MetaPickup." << endl;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/MetaPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/MetaPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/MetaPickup.h	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file MetaPickup.h
+    @brief Definition of the MetaPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _MetaPickup_H__
+#define _MetaPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include "pickup/Pickup.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        The meta type, specifying what the @ref orxonox::MetaPickup "MetaPickup" does exactly.
+
+    @ingroup PickupItems
+    */
+    enum class PickupMetaType
+    {
+        none, //!< The @ref orxonox::MetaPickup "MetaPickup" does nothing.
+        use, //!< The @ref orxonox::MetaPickup "MetaPickup" uses all the @ref orxonox::PickupCarrier "PickupCarriers'" @ref orxonox::Pickupable "Pickupables".
+        drop, //!< The @ref orxonox::MetaPickup "MetaPickup" drops all the @ref orxonox::PickupCarrier "PickupCarriers'" @ref orxonox::Pickupable "Pickupables".
+        destroy, //!< The @ref orxonox::MetaPickup "MetaPickup" destroys all the @ref orxonox::PickupCarrier "PickupCarriers'" @ref orxonox::Pickupable "Pickupables".
+        destroyCarrier //!< The @ref orxonox::MetaPickup "MetaPickup" destroys the @ref orxonox::PickupCarrier "PickupCarrier".
+    };
+
+    /**
+    @brief
+        The MetaPickup is a Pickupable that can, depending on the parameter <em>metaTye</em>, do different things. If the <em>metaTye</em> is set to
+        - @b use All the @ref orxonox::Pickupable "Pickupables", the PickupCarrier has, are immediately set to used upon using the MetaPickup.
+        - @b drop All the @ref orxonox::Pickupable "Pickupables", the PickupCarrier has, are immediately dropped upon using the MetaPickup.
+        - @b destroy All the @ref orxonox::Pickupable "Pickupables", the PickupCarrier has, are immediately destroyed upon using the MetaPickup.
+        - @b destroyCarrier The PickupCarrier is immediately destroyed upon using the MetaPickup.
+
+        The default value is <em>none</em>, which basically does nothing.
+
+        The parameter <b>activation type</b> can be used to specify, whether the MetaPickup is used upon pickup (<em>immediate</em>) or not (<em>onUse</em>). With <em>immediate</em> being the default.
+
+        An example of a XML implementation of a MetaPickup would be:
+        @code
+        <MetaPickup
+            activationType = "immediate"
+            metaType = "use"
+        />
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup PickupItems
+    */
+    class _PickupExport MetaPickup : public Pickup
+    {
+
+        public:
+            MetaPickup(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~MetaPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a MetaPickup object through XML.
+
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            /**
+            @brief Returns the meta type of the MetaPickup.
+            @return Returns an enum with the meta type of the MetaPickup.
+            */
+            inline PickupMetaType getMetaType(void) const
+                { return this->metaType_; }
+            const std::string& getMetaTypeAsString(void) const; //!< Get the meta type of this MetaPickup.
+
+        protected:
+            /**
+            @brief Set the meta type of the MetaPickup.
+            @param type The meta type as an enum.
+            */
+            inline void setMetaType(PickupMetaType type)
+                { this->metaType_ =  type; }
+            void setMetaTypeAsString(const std::string& type); //!< Set the meta type of this MetaPickup.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+
+            PickupMetaType metaType_; //!< The meta type of the MetaPickup, determines which actions are taken.
+
+            //! Static strings for the meta types.
+            static const std::string metaTypeNone_s;
+            static const std::string metaTypeUse_s;
+            static const std::string metaTypeDrop_s;
+            static const std::string metaTypeDestroy_s;
+            static const std::string metaTypeDestroyCarrier_s;
+
+    };
+
+}
+
+#endif // _TestPickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionContainer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionContainer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionContainer.cc	(revision 11817)
@@ -0,0 +1,117 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MunitionContainer.cc
+    @brief Implementation of the MunitionContainer class. This class is only used by the MunitionPickup class to defines  how much munition of what type the pickup contains.
+*/
+
+#include "MunitionContainer.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(MunitionContainer);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    MunitionContainer::MunitionContainer(Context* context) : BaseObject(context)
+    {
+        RegisterObject(MunitionContainer);
+
+        this->munitionName_ = "";
+        this->munitionAmount_ = 1;
+        this->magazinesAmount_ = 1;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    MunitionContainer::~MunitionContainer()
+    {
+    }    
+
+    /**
+    @brief
+        Method for creating a MunitionContainer object through XML.
+    */
+    void MunitionContainer::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(MunitionContainer, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MunitionContainer, "munitiontype", setMunitionName, getMunitionName, xmlelement, mode).defaultValues("LaserMunition");
+        XMLPortParam(MunitionContainer, "munitionamount", setMunitionAmount, getMunitionAmount, xmlelement, mode).defaultValues(1);
+        XMLPortParam(MunitionContainer, "magazinesamount", setMagazinesAmount, getMagazinesAmount, xmlelement, mode).defaultValues(0);
+    }
+
+    void MunitionContainer::setMunitionName(const std::string& munitionName)
+    {
+        Identifier* identifier = ClassByString(munitionName);
+        if (identifier)
+        {
+            this->munitionName_ = munitionName;
+            this->munitionType_ = identifier;
+        }
+        else
+        {
+            this->munitionName_ = "";            
+            orxout(internal_warning) << "Invalid munition class defined in MunitionContainer." << endl;
+        }
+    }   
+
+    void MunitionContainer::setMunitionAmount(int munitionAmount)
+    {
+        if (munitionAmount > 0)
+        {
+            munitionAmount_ = munitionAmount;
+        }
+        else
+        {
+            munitionAmount_ = 0;
+        }
+    }
+
+    void MunitionContainer::setMagazinesAmount(int magazinesAmount)
+    {
+        if (magazinesAmount > 0)
+        {
+            magazinesAmount_ = magazinesAmount;
+        }
+        else
+        {
+            magazinesAmount_ = 0;
+        }
+    }         
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionContainer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionContainer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionContainer.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MunitionContainer.h
+    @brief Declaration of the MunitionContainer class.
+    @ingroup PickupItems
+*/
+
+#ifndef _MunitionContainer_H__
+#define _MunitionContainer_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+#include "core/class/SubclassIdentifier.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+    class _PickupExport MunitionContainer : public BaseObject
+    {
+        public:
+
+            MunitionContainer(Context* context);
+            virtual ~MunitionContainer();
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode) override;
+
+            inline const std::string& getMunitionName() const
+                { return this->munitionName_; }
+            inline int getMunitionAmount() const
+                { return this->munitionAmount_; }
+            inline int getMagazinesAmount() const
+                { return this->magazinesAmount_; }
+            inline SubclassIdentifier<Munition> getMunitionType() const
+                { return munitionType_; }            
+
+        protected:
+            void setMunitionName(const std::string& munitionName);
+            void setMunitionAmount(int munitionAmount);
+            void setMagazinesAmount(int magazinesAmount_);
+
+        private:
+            SubclassIdentifier<Munition> munitionType_; //!< Indentifier of the munition type.
+            std::string munitionName_; //!< String containing the class name of the munition type (e.g. "LaserMunition")
+            int munitionAmount_; //!< The amount of singe bullets added
+            int magazinesAmount_; //!< The amount of full magazines added
+
+    };    
+}
+
+#endif // _MunitionContainer_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionPickup.cc	(revision 11817)
@@ -0,0 +1,156 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MunitionPickup.cc
+    @brief Implementation of the MunitionPickup class.
+*/
+
+#include "MunitionPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(MunitionPickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    MunitionPickup::MunitionPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(MunitionPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    MunitionPickup::~MunitionPickup()
+    {
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void MunitionPickup::initialize(void)
+    {
+        //Defines who is allowed to pick up the pickup.
+        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a MunitionPickup object through XML.
+    */
+    void MunitionPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(MunitionPickup, XMLPort, xmlelement, mode);
+
+        XMLPortObject(MunitionPickup, MunitionContainer, "munitioncontainers", addMunitionContainer, getMunitionContainer, xmlelement, mode);
+    }
+
+    void MunitionPickup::addMunitionContainer(MunitionContainer* munitionContainer)
+    {
+        OrxAssert(munitionContainer != nullptr, "The munitionContainer cannot be nullptr.");
+        this->munitionContainers_.push_back(munitionContainer);
+    }
+
+    MunitionContainer* MunitionPickup::getMunitionContainer(unsigned int index)
+    {
+        if(this->munitionContainers_.size() >= index)
+            return nullptr;
+        else
+            return this->munitionContainers_[index];
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transisted from used to unused or the other way around.
+    */
+    void MunitionPickup::changedUsed(void)
+    {
+        SUPER(MunitionPickup, changedUsed);
+
+        Pawn* pawn = this->carrierToPawnHelper();
+
+        if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+            this->Pickupable::destroy();
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+            for(MunitionContainer* container : this->munitionContainers_)
+            {
+                //Get pointer to the appropriate munition
+                SubclassIdentifier<Munition> identifier = container->getMunitionType();
+                Munition* munition = pawn->getMunition(&identifier);
+                if (munition)
+                {
+                    // Add munition and magzines
+                    munition->addMunition(container->getMunitionAmount());
+                    munition->addMagazines(container->getMagazinesAmount());
+                }
+                container->destroy();
+            }
+            // This will destroy the pickp
+            this->setUsed(false);
+        }
+        else
+        {
+            this->Pickupable::destroy();
+        }
+    }    
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    @return
+        A pointer to the Pawn, or nullptr if the conversion failed.
+    */
+    Pawn* MunitionPickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+        if(pawn == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in MunitionPickup." << endl;
+        }
+        return pawn;
+    }      
+}
+
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/MunitionPickup.h	(revision 11817)
@@ -0,0 +1,77 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MunitionPickup.h
+    @brief Declaration of the MunitionPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _MunitionPickup_H__
+#define _MunitionPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+#include <vector>
+
+#include "pickup/Pickup.h"
+#include "pickup/items/MunitionContainer.h"
+#include "core/class/SubclassIdentifier.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The MunitionPickup gives munition to the user (a @ref Pawn).
+    */
+    class _PickupExport MunitionPickup : public Pickup
+    {
+        public:
+
+            MunitionPickup(Context* context); //!< Constructor.
+            virtual ~MunitionPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode) override; //!< Method for creating a MunitionPickup object through XML.
+
+            virtual void changedUsed(void) override; //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            void addMunitionContainer(MunitionContainer* munitionContainer);
+            MunitionContainer* getMunitionContainer(unsigned int index);
+
+        private:            
+            void initialize(void); //!< Initializes the member variables.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+            
+            std::vector<MunitionContainer*> munitionContainers_;
+
+    };
+}
+
+#endif // _MunitionPickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/ShieldPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/ShieldPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/ShieldPickup.cc	(revision 11817)
@@ -0,0 +1,224 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Eric Beier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ShieldPickup.cc
+    @brief Implementation of the ShieldPickup class.
+*/
+
+#include "ShieldPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(ShieldPickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    ShieldPickup::ShieldPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(ShieldPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    ShieldPickup::~ShieldPickup()
+    {
+
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void ShieldPickup::initialize(void)
+    {
+        this->duration_ = 0.0f;
+        this->shieldAbsorption_ = 0.0f;
+        this->shieldHealth_ = 0.0f;
+
+        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a ShieldPickup object through XML.
+    */
+    void ShieldPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(ShieldPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ShieldPickup, "shieldhealth", setShieldHealth, getShieldHealth, xmlelement, mode);
+        XMLPortParam(ShieldPickup, "shieldabsorption", setShieldAbsorption, getShieldAbsorption, xmlelement, mode);
+        XMLPortParam(ShieldPickup, "duration", setDuration, getDuration, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
+    void ShieldPickup::changedUsed(void)
+    {
+        SUPER(ShieldPickup, changedUsed);
+
+        Pawn* pawn = this->carrierToPawnHelper();
+        if(pawn == nullptr)
+            this->Pickupable::destroy();
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+            // If its durationType is continuous, we set a Timer to be reminded, when the time has run out.
+            if(this->isContinuous())
+            {
+                if(!this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() > 0.0f)
+                {
+                    this->durationTimer_.unpauseTimer();
+                }
+                else
+                {
+                    this->durationTimer_.setTimer(this->getDuration(), false, createExecutor(createFunctor(&ShieldPickup::pickupTimerCallback, this)));
+                }
+            }
+            pawn->setShieldAbsorption(this->getShieldAbsorption());
+            pawn->setShieldHealth(this->getShieldHealth());
+        }
+        else
+        {
+            pawn->setShieldAbsorption(0.0f);
+            this->setShieldHealth(pawn->getShieldHealth());
+            pawn->setShieldHealth(0.0f);
+
+            // We destroy the pickup if either, the pickup has activationType immediate and durationType once or it has durationType continuous and the duration was exceeded.
+            if((!this->isContinuous() && this->isImmediate()) || (this->isContinuous() && !this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() == this->getDuration()))
+            {
+                this->Pickupable::destroy();
+            }
+            // We pause the Timer if the pickup is continuous and the duration is not yet exceeded,
+            else if(this->isContinuous() && this->durationTimer_.isActive())
+            {
+                this->durationTimer_.pauseTimer();
+            }
+        }
+    }
+
+    /**
+    @brief
+    Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+    @return
+    A pointer to the Pawn, or nullptr if the conversion failed.
+    */
+    Pawn* ShieldPickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+        if(pawn == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in ShieldPickup." << endl;
+        }
+        return pawn;
+    }
+
+    /**
+    @brief
+        Sets the duration.
+    @param duration
+        The duration in seconds.
+    */
+    void ShieldPickup::setDuration(float duration)
+    {
+        if(duration >= 0.0f)
+        {
+            this->duration_ = duration;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid duration in ShieldPickup." << endl;
+            this->duration_ = 0.0f;
+        }
+    }
+
+    /**
+    @brief
+        Sets the health of the shield.
+    @param shieldHealth
+        The shieldHealth.
+    */
+    void ShieldPickup::setShieldHealth(float shieldHealth)
+    {
+        if (shieldHealth>=0)
+        {
+            this->shieldHealth_=shieldHealth;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid Shieldhealth in ShieldPickup." << endl;
+            this->shieldHealth_=0;
+        }
+    }
+
+    /**
+    @brief
+        Sets the percentage the shield absorbs of the dealt damage.
+    @param shieldAbsorption
+        The shieldAbsorption. Has to be between 0 and 1.
+    */
+    void ShieldPickup::setShieldAbsorption(float shieldAbsorption)
+    {
+        if (shieldAbsorption>=0 && shieldAbsorption<=1)
+        {
+            this->shieldAbsorption_=shieldAbsorption;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid Absorption in ShieldPickup." << endl;
+            this->shieldAbsorption_=0;
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Is called by the Timer as soon as it expires.
+    */
+    void ShieldPickup::pickupTimerCallback(void)
+    {
+        this->setUsed(false);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/ShieldPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/ShieldPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/ShieldPickup.h	(revision 11817)
@@ -0,0 +1,124 @@
+
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Eric Beier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ShieldPickup.h
+    @brief Declaration of the ShieldPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _ShieldPickup_H__
+#define _ShieldPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        A Pickup which can add a Shield to the Pawn.
+
+        There are 5 parameters that can be cosen.
+        - The @b shieldhealth< The amount of damage points a shield can take before collapsing. The default is 0.
+        - The @b shieldabsorption The percentage the shield takes from the damage dealt to a Pawn. The default is 0.
+        - The @b activationType, <em>immediate</em> or <em>onUse</em>. defines if the ShiedlPickup is used when it's picked up or only after the player chooses to use it. The default is <em>immediate</em>.
+        - The @b durationType, <em>once</em> means, that the shield will stay until it collapses, <em>continuous</em> means, that the shield only stays for a limited amount of time, specifiey by the duration. The default is <em>once</em>.
+        - The @b duration the time in seconds the shield is active at the most. The default is 0.
+
+        An example of a XML implementation of a ShieldPickup would be:
+        @code
+        <ShieldPickup
+            shieldhealth = 30
+            shieldabsorption = 0.8
+            activationType = "immediate"
+            durationtype = "continuous"
+            duration = 20.0
+        />
+        @endcode
+
+    @author
+        Eric Beier
+
+    @ingroup PickupItems
+    */
+    class _PickupExport ShieldPickup : public Pickup
+    {
+        public:
+
+            ShieldPickup(Context* context); //!< Constructor.
+            virtual ~ShieldPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a HealthPickup object through XML.
+
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            /**
+            @brief Get the duration, the time the shield is actvie at the most.
+            @return Returns the duration in seconds.
+            */
+            inline float getDuration(void) const
+                { return this->duration_; }
+            /**
+            @brief Get the shield health, the amount of damage the shield can sustain.
+            @return Returns the shield health.
+            */
+            inline float getShieldHealth() const
+                { return this->shieldHealth_; }
+            /**
+            @brief Get the shield absorption, the percentage of damage that is absorbed by the shield.
+            @return Returns the shield absorption.
+            */
+            inline float getShieldAbsorption() const
+                { return this->shieldAbsorption_; }
+
+        protected:
+            void pickupTimerCallback(void); //!< Helper method. Is called by the Timer as soon as it expires.
+
+            void setDuration(float duration); //!< Sets the duration.
+            void setShieldHealth(float shieldHealth); //!< Sets the health of the shield.
+            void setShieldAbsorption(float shieldAbsorption); //!< Sets the percentage the shield absorbs of the dealt damage.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            Pawn* carrierToPawnHelper(void); //!< Helper to transform the PickupCarrier to a Pawn, and throw an error message if the conversion fails.
+
+            Timer durationTimer_; //!< Timer.
+
+            float duration_; //!< The health that is transferred to the Pawn.
+            float shieldHealth_; //!< The amount of damage the shield can sustain.
+            float shieldAbsorption_; //!< The percentage of damage that is absorbed by the shield.
+
+    };
+}
+
+#endif // _ShieldPickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/ShrinkPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/ShrinkPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/ShrinkPickup.cc	(revision 11817)
@@ -0,0 +1,341 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro Sgier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+/**
+    @file ShrinkPickup.cc
+    @brief Implementation of the HealthPickup class.
+*/
+
+
+#include "ShrinkPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+#include "worldentities/CameraPosition.h"
+
+namespace orxonox
+{
+    RegisterClass(ShrinkPickup);
+
+    /**
+    @brief
+        Constructor: Initializes the Pickup.
+    */
+    ShrinkPickup::ShrinkPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(ShrinkPickup);
+
+        this->initialize();
+    }
+
+    ShrinkPickup::~ShrinkPickup()
+    {
+
+    }
+
+    void ShrinkPickup::initialize(void)
+    {
+        this->addTarget(ClassIdentifier<Pawn>::getIdentifier());
+
+        this->shrinkFactor_ = 5.0f;
+        this->shrinkDuration_ = 5.0f;
+        this->duration_ = 5.0f;
+
+        this->isActive_ = false;
+        this->isShrinking_ = false;
+        this->isTerminating_ = false;
+
+        this->timeRemainig_ = 0.0f;
+        this->currentFactor_ = 1.0f;
+    }
+
+   /**
+    @brief
+        Method for creating a ShrinkPickup object through XML.
+    */
+    void ShrinkPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(ShrinkPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ShrinkPickup, "shrinkFactor", setShrinkFactor, getShrinkFactor, xmlelement, mode);
+        XMLPortParam(ShrinkPickup, "duration", setDuration, getDuration, xmlelement, mode);
+        XMLPortParam(ShrinkPickup, "shrinkDuration", setShrinkDuration, getShrinkDuration, xmlelement, mode);
+    }
+
+    /**
+    @brief Sets the shrinking factor.
+    @param factor The factor, needs to greater than 1.
+    */
+    void ShrinkPickup::setShrinkFactor(float factor)
+    {
+        if(factor <= 1.0f)
+        {
+            orxout(internal_warning, context::pickups) << "Invalid shrinking factor in ShrinkPickup. Ignoring.." << endl;
+            return;
+        }
+        this->shrinkFactor_ = factor;
+    }
+
+    /**
+    @brief Set the duration for which the ship remains shrunken.
+    @param duration The duration, needs to be non-negative.
+    */
+    void ShrinkPickup::setDuration(float duration)
+    {
+        if(duration < 0.0f)
+        {
+            orxout(internal_warning, context::pickups) << "Invalid duration in ShrinkPickup. Ignoring.." << endl;
+            return;
+        }
+        this->duration_ = duration;
+    }
+
+    /**
+    @brief Set the shrink duration.
+    @param speed The shrink duration, needs to be positive.
+    */
+    void ShrinkPickup::setShrinkDuration(float speed)
+    {
+        if(speed <= 0.0f)
+        {
+            orxout(internal_warning, context::pickups) << "Invalid shrink duration in ShrinkPickup. Ignoring.." << endl;
+            return;
+        }
+        this->shrinkDuration_ = speed;
+    }
+
+    /**
+    @brief
+        Prepares for shrinking.
+    */
+    void ShrinkPickup::changedUsed(void)
+    {
+        SUPER(ShrinkPickup, changedUsed);
+
+        if(this->isUsed())
+        {
+            Pawn* pawn = this->carrierToPawnHelper();
+            if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+            {
+                this->Pickupable::destroy();
+                return;
+            }
+
+            this->currentFactor_ = 1.0f;
+            this->timeRemainig_ = this->shrinkDuration_;
+
+            this->isActive_ = true; // Start shrinking now.
+            this->isShrinking_ = true;
+            this->durationTimer_.setTimer(this->duration_, false, createExecutor(createFunctor(&ShrinkPickup::terminate, this))); //Set timer for termination.
+        }
+        if(!this->isUsed() && this->isActive_)
+             this->isTerminating_ = true;
+    }
+
+    void ShrinkPickup::changedPickedUp(void)
+    {
+        SUPER(ShrinkPickup, changedPickedUp);
+
+        if(!this->isPickedUp() && this->isActive_)
+        {
+            if(this->isShrinking_ || this->isTerminating_)
+            {
+                //TODO: Deploy particle effect.
+                Pawn* pawn = this->carrierToPawnHelper();
+                if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                    return;
+
+                float factor = 1.0f/this->currentFactor_;
+
+                pawn->setScale3D(pawn->getScale3D()*factor);
+                pawn->setMass(pawn->getMass()*factor);
+
+                // Iterate over all camera positions and inversely move the camera to create a shrinking sensation.
+                const std::list<StrongPtr<CameraPosition>>& cameraPositions = pawn->getCameraPositions();
+                int size = cameraPositions.size();
+                for(int index = 0; index < size; index++)
+                {
+                    CameraPosition* cameraPos = pawn->getCameraPosition(index);
+                    if(cameraPos == nullptr)
+                        continue;
+                    cameraPos->setPosition(cameraPos->getPosition()/factor);
+                }
+                this->currentFactor_ = 1.0f;
+                this->timeRemainig_ = this->shrinkDuration_;
+                this->isActive_ = false;
+                this->isShrinking_ = false;
+                this->isTerminating_ = false;
+            }
+            else
+            {
+                //TODO: Deploy particle effect.
+                Pawn* pawn = this->carrierToPawnHelper();
+                if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                    return;
+
+                pawn->setScale3D(pawn->getScale3D()*this->shrinkFactor_);
+                pawn->setMass(pawn->getMass()*this->shrinkFactor_);
+
+                // Iterate over all camera positions and inversely move the camera to create a shrinking sensation.
+                const std::list<StrongPtr<CameraPosition>>& cameraPositions = pawn->getCameraPositions();
+                int size = cameraPositions.size();
+                for(int index = 0; index < size; index++)
+                {
+                    CameraPosition* cameraPos = pawn->getCameraPosition(index);
+                    if(cameraPos == nullptr)
+                        continue;
+                    cameraPos->setPosition(cameraPos->getPosition()/this->shrinkFactor_);
+                }
+                this->currentFactor_ = 1.0f;
+                this->timeRemainig_ = this->shrinkDuration_;
+                this->isActive_ = false;
+            }
+        }
+    }
+
+    /**
+    @brief
+        Updates the scales of the ship.
+    @param dt
+        Time since last call.
+    */
+    void ShrinkPickup::tick(float dt)
+    {
+        if(this->isActive_)
+        {
+            if(this->isShrinking_)    // If the ship has not reached the target scale, continue shrinking
+            {
+                Pawn* pawn = this->carrierToPawnHelper();
+                if(pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                {
+                    this->Pickupable::destroy();
+                    return;
+                }
+
+                this->timeRemainig_ -= dt;
+
+                // Calculate the scaling factor by which the initial size would have to be scaled to have the current scale.
+                float currentFactor = std::max(1 - (1-std::max(this->timeRemainig_, 0.0f)/this->shrinkDuration_)*(1-1/this->shrinkFactor_), 1/this->shrinkFactor_);
+                // Calculate the factor by which the previous size has to be scaled to be the current scale.
+                float factor = currentFactor/this->currentFactor_;
+                this->currentFactor_ = currentFactor;
+
+                // Stop shrinking if the desired size is reached.
+                if(this->timeRemainig_ <= 0.0f)
+                {
+                    this->timeRemainig_ = this->shrinkDuration_; // Reset the time remaining for when we start to grow the ship again.
+                    this->currentFactor_ = 1/this->shrinkFactor_;
+                    this->isShrinking_ = false;
+                }
+
+                pawn->setScale3D(pawn->getScale3D()*factor);
+                pawn->setMass(pawn->getMass()*factor);
+
+                // Iterate over all camera positions and inversely move the camera to create a shrinking sensation.
+                const std::list<StrongPtr<CameraPosition>>& cameraPositions = pawn->getCameraPositions();
+                int size = cameraPositions.size();
+                for(int index = 0; index < size; index++)
+                {
+                    CameraPosition* cameraPos = pawn->getCameraPosition(index);
+                    if(cameraPos == nullptr)
+                        continue;
+                    cameraPos->setPosition(cameraPos->getPosition()/factor);
+                }
+
+            }
+            else if(this->isTerminating_)    // Grow until the ship reaches its default scale.
+            {
+                Pawn* pawn = this->carrierToPawnHelper();
+                if (pawn == nullptr) // If the PickupCarrier is no Pawn, then this pickup is useless and therefore is destroyed.
+                {
+                    this->Pickupable::destroy();
+                    return;
+                }
+
+                this->timeRemainig_ -= dt;
+
+                // Calculate the scaling factor by which the initial size would have to be scaled to have the current scale.
+                float currentFactor = std::min(1/this->shrinkFactor_ + (1-std::max(this->timeRemainig_, 0.0f)/this->shrinkDuration_)*(1-1/this->shrinkFactor_), 1.0f);
+                // Calculate the factor by which the previous size has to be scaled to be the current scale.
+                float factor = currentFactor/this->currentFactor_;
+                this->currentFactor_ = currentFactor;
+
+                bool destroy = false;
+
+                // Stop shrinking if the desired size is reached.
+                if(this->timeRemainig_ <= 0.0f)
+                {
+                    this->timeRemainig_ = shrinkDuration_; // Reset the time remaining for when we start to grow the ship again.
+                    this->currentFactor_ = 1.0f;
+                    this->isTerminating_ = false;
+                    this->isActive_ = false;
+                    destroy = true;
+                }
+
+                pawn->setScale3D(pawn->getScale3D()*factor);
+                pawn->setMass(pawn->getMass()*factor);
+
+                // Iterate over all camera positions and inversely move the camera to create a shrinking sensation.
+                const std::list<StrongPtr<CameraPosition>>& cameraPositions = pawn->getCameraPositions();
+                int size = cameraPositions.size();
+                for(int index = 0; index < size; index++)
+                {
+                    CameraPosition* cameraPos = pawn->getCameraPosition(index);
+                    if(cameraPos == nullptr)
+                        continue;
+                    cameraPos->setPosition(cameraPos->getPosition()/factor);
+                }
+
+                if(destroy)
+                    this->Pickupable::destroy();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Initializes the termination.
+    */
+    void ShrinkPickup::terminate(void)
+    {
+        this->setUsed(false);
+    }
+
+    Pawn* ShrinkPickup::carrierToPawnHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
+
+        return pawn;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/ShrinkPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/ShrinkPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/ShrinkPickup.h	(revision 11817)
@@ -0,0 +1,127 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro Sgier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ShrinkPickup.h
+    @brief Declaration of the ShrinkPickup class.
+    @ingroup PickupItems
+*/
+
+
+#ifndef _ShrinkPickup_H__
+#define _ShrinkPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+#include <vector>
+
+#include "pickup/Pickup.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        The ShrinkPickup is a Pickupable that causes the pawn to shrink to a certain size for a certain time with a certain speed, all of them specified in the following variables:
+        - The @b shrinkFactor It determines how much the ship is going to shrink (e.g. the factor 2 would make the ship shrinking to half its size).
+        - The @b duration Specifies how long the ship will stay small.
+        - The @b shrinkDuration Defines how fast the ship shrinks and grows in seconds.
+
+        An example of a XML implementation of a ShrinkPickup would be:
+        @code
+        <ShrinkPickup
+            shrinkFactor = "5.0"
+            duration = "5.0"
+            shrinkSpeed = "5.0"
+        />
+        @endcode
+
+    @author
+        Sandro Sgier
+
+    @ingroup PickupItems
+    */
+
+    class _PickupExport ShrinkPickup : public Pickup, public Tickable
+    {
+        public:
+            ShrinkPickup(Context* context); // Constructor.
+            virtual ~ShrinkPickup(); // Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode);
+            virtual void tick(float dt);
+
+            virtual void changedUsed(void); // Is called when the pickup has transited from used to unused or the other way around.
+            virtual void changedPickedUp(void);
+
+            /**
+            @brief Get the shrinking factor.
+            @return Returns the shrinking factor,
+            */
+            inline float getShrinkFactor(void) const
+                { return this->shrinkFactor_; }
+            void setShrinkFactor(float factor);
+
+            /**
+            @brief Get the duration for which the ship remains shrunken.
+            @return Returns the duration.
+            */
+            inline float getDuration(void) const
+                { return this->duration_; }
+            void setDuration(float duration);
+
+            /**
+            @brief Get the shrink speed.
+            @return Returns the shrink speed.
+            */
+            inline float getShrinkDuration(void) const
+                { return this->shrinkDuration_; }
+            void setShrinkDuration(float speed);
+
+        private:
+            void initialize(void);
+
+            float duration_;            //!< Determines how long the pickup will be active
+            float shrinkFactor_;        //!< Shrink factor of the space ship
+            float shrinkDuration_;      //!< Duration of shrinking
+
+            bool isActive_;             //!< True if ship is shrinking, small, or growing back.
+            bool isShrinking_;          //!< True if ship is shrinking
+            bool isTerminating_;        //!< True if ship is growing back to the original size
+
+            float currentFactor_;       //!< The shrink factor that is currently applied.
+            float timeRemainig_;        //!< The remaining shrink time.
+
+            Pawn* carrierToPawnHelper(void);
+            Timer durationTimer_;
+            void terminate(void);
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/SpeedPickup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/SpeedPickup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/SpeedPickup.cc	(revision 11817)
@@ -0,0 +1,221 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Eric Beier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SpeedPickup.cc
+    @brief Implementation of the SpeedPickup class.
+*/
+
+#include "SpeedPickup.h"
+
+#include <sstream>
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    RegisterClass(SpeedPickup);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes the member variables.
+    */
+    SpeedPickup::SpeedPickup(Context* context) : Pickup(context)
+    {
+        RegisterObject(SpeedPickup);
+
+        this->initialize();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    SpeedPickup::~SpeedPickup()
+    {
+
+    }
+
+    /**
+    @brief
+        Initializes the member variables.
+    */
+    void SpeedPickup::initialize(void)
+    {
+        this->duration_ = 0.0f;
+        this->speedAdd_ = 0.0f;
+        this->speedMultiply_ = 1.0f;
+
+        this->addTarget(ClassIdentifier<SpaceShip>::getIdentifier());
+    }
+
+    /**
+    @brief
+        Method for creating a SpeedPickup object through XML.
+    */
+    void SpeedPickup::XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode)
+    {
+        SUPER(SpeedPickup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SpeedPickup, "duration", setDuration, getDuration, xmlelement, mode);
+        XMLPortParam(SpeedPickup, "speedAdd", setSpeedAdd, getSpeedAdd, xmlelement, mode);
+        XMLPortParam(SpeedPickup, "speedMultiply", setSpeedMultiply, getSpeedMultiply, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the pickup has transited from used to unused or the other way around.
+    */
+    void SpeedPickup::changedUsed(void)
+    {
+        SUPER(SpeedPickup, changedUsed);
+
+        SpaceShip* ship = this->carrierToSpaceShipHelper();
+        if(ship == nullptr) // If the PickupCarrier is no SpaceShip, then this pickup is useless and therefore is destroyed.
+            this->Pickupable::destroy();
+
+        // If the pickup has transited to used.
+        if(this->isUsed())
+        {
+            // If its durationType is continuous, we set a Timer to be reminded, when the time has run out.
+            if(this->isContinuous())
+            {
+                if(!this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() > 0.0f)
+                {
+                    this->durationTimer_.unpauseTimer();
+                }
+                else
+                {
+                    this->durationTimer_.setTimer(this->getDuration(), false, createExecutor(createFunctor(&SpeedPickup::pickupTimerCallback, this)));
+                }
+            }
+
+            ship->addSpeed(this->getSpeedAdd());
+            ship->addSpeedFactor(this->getSpeedMultiply());
+        }
+        else
+        {
+            ship->addSpeed(-this->getSpeedAdd());
+            ship->addSpeedFactor(1.0f/this->getSpeedMultiply());
+
+            // We destroy the pickup if either, the pickup has activationType immediate and durationType once or it has durationType continuous and the duration was exceeded.
+            if((!this->isContinuous() && this->isImmediate()) || (this->isContinuous() && !this->durationTimer_.isActive() && this->durationTimer_.getRemainingTime() == this->getDuration()))
+            {
+                this->Pickupable::destroy();
+            }
+            // We pause the Timer if the pickup is continuous and the duration is not yet exceeded,
+            else if(this->isContinuous() && this->durationTimer_.isActive())
+            {
+                this->durationTimer_.pauseTimer();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper to transform the PickupCarrier to a SpaceShip, and throw an error message if the conversion fails.
+    @return
+        A pointer to the SpaceShip, or nullptr if the conversion failed.
+    */
+    SpaceShip* SpeedPickup::carrierToSpaceShipHelper(void)
+    {
+        PickupCarrier* carrier = this->getCarrier();
+        SpaceShip* ship = orxonox_cast<SpaceShip*>(carrier);
+
+        if(ship == nullptr)
+        {
+            orxout(internal_error, context::pickups) << "Invalid PickupCarrier in SpeedPickup." << endl;
+        }
+
+        return ship;
+    }
+
+    /**
+    @brief
+        Sets the duration for which the SpeedPickup stays active.
+    @param duration
+        The duration in seconds.
+    */
+    void SpeedPickup::setDuration(float duration)
+    {
+        if(duration >= 0.0f)
+        {
+            this->duration_ = duration;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid duration in SpeedPickup." << endl;
+            this->duration_ = 0.0f;
+        }
+    }
+
+    /**
+    @brief
+        Sets the speedAdd, the value that is added to the speed of the Pawn.
+    @param speedAdd
+        The added speed.
+    */
+    void SpeedPickup::setSpeedAdd(float speedAdd)
+    {
+        if(speedAdd >= 0.0f)
+        {
+            this->speedAdd_ = speedAdd;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid speedAdd in SpeedPickup." << endl;
+            this->speedAdd_ = 0.0f;
+        }
+    }
+
+    /**
+    @brief
+        Sets the speedMultiply, the factor by which the speed of the Pawn is multiplied.
+    @param speedMultiply
+        The factor by which the speed is mutiplied.
+    */
+    void SpeedPickup::setSpeedMultiply(float speedMultiply)
+    {
+        if(speedMultiply != 0)
+        {
+            this->speedMultiply_ = speedMultiply;
+        }
+        else
+        {
+            orxout(internal_error, context::pickups) << "Invalid speedMultiply in SpeedPickup." << endl;
+            this->speedMultiply_ = 1.0f;
+        }
+    }
+
+    void SpeedPickup::pickupTimerCallback(void)
+    {
+        this->setUsed(false);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pickup/items/SpeedPickup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pickup/items/SpeedPickup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pickup/items/SpeedPickup.h	(revision 11817)
@@ -0,0 +1,122 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Eric Beier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SpeedPickup.h
+    @brief Declaration of the SpeedPickup class.
+    @ingroup PickupItems
+*/
+
+#ifndef _SpeedPickup_H__
+#define _SpeedPickup_H__
+
+#include "pickup/PickupPrereqs.h"
+
+#include <string>
+
+#include "pickup/Pickup.h"
+
+namespace orxonox {
+
+    /**
+    @brief
+        A Pickup which can manipulate the Speed of a Pawn.
+
+        There are 5 parameters that can be chosen:
+        - The @b speedMultiply, specifies a factor by which the Spaceships speed is multiplied. The default is 1.
+        - The @b speedAdd, specifies a value that is added to the speed of the Spaceship. The default is 0.
+        - The @b activationType <em>immediate</em> or <em>onUse</em>, defines if the SpeedPickup is used when it's picked up or only after the player chooses to use it. The default is <em>immediate</em>.
+        - The @b durationType Can be either <em>once</em> or <em>continuous</em>. For <em>once</em> the SpeedPickup is just active for as long as it is used, for <em>continuous</em> the SpeedPickup is active only for the specified duration. The default is <em>once</em>.
+        - The @b duration The time in seconds the SpeedPickup is active at the most. The default is 0.
+
+        An example, how a SpeedPickup could be defined in XML could be:
+        @code
+        <SpeedPickup
+            speedMultiply = 2.0
+            speedAdd = 10.0
+            activationType = "immediate"
+            durationType = "continuous"
+            duration = 30.0
+        />
+        @endcode
+
+    @author
+        Eric Beier
+
+    @ingroup PickupItems
+    */
+    class _PickupExport SpeedPickup : public Pickup
+    {
+        public:
+
+            SpeedPickup(Context* context); //!< Constructor.
+            virtual ~SpeedPickup(); //!< Destructor.
+
+            virtual void XMLPort(Element& xmlelement, orxonox::XMLPort::Mode mode); //!< Method for creating a HealthPickup object through XML.
+
+            virtual void changedUsed(void); //!< Is called when the pickup has transited from used to unused or the other way around.
+
+            /**
+            @brief Get the duration, the time the SpeedPickup is active.
+            @return Returns the duration in seconds.
+            */
+            inline float getDuration(void) const
+                { return this->duration_; }
+            /**
+            @brief Get the value that is added to the speed of the Pawn.
+            @return Returns the speedAdd.
+            */
+            inline float getSpeedAdd(void) const
+                { return this->speedAdd_; }
+            /**
+            @brief Get the factor by wich the speed of the Pawn is multplied.
+            @return Returns the speedMultiply.
+            */
+            inline float getSpeedMultiply(void) const
+                { return this->speedMultiply_; }
+
+        protected:
+            void pickupTimerCallback(void); //!< Function that gets called when timer ends.
+
+            void setDuration(float duration); //!< Sets the duration.
+            void setSpeedAdd(float speedAdd); //!< Sets the SpeedAdd, the value that is added to the speed of the Pawn.
+            void setSpeedMultiply(float speedMultiply); //!< Sets the speedMultiply, the factor by which the speed of the Pawn is multiplied.
+
+        private:
+            void initialize(void); //!< Initializes the member variables.
+            SpaceShip* carrierToSpaceShipHelper(void); //!< Helper to transform the PickupCarrier to a SpaceShip, and throw an error message if the conversion fails.
+
+            Timer durationTimer_; //!< Timer.
+
+            float duration_; //!< The time in seconds for which the SpeedPickup stays active.
+            float speedAdd_; //!< The value that is added to the speed of the Pawn.
+            float speedMultiply_; //!< The factor by which the speed of the Pawn is multiplied.
+    };
+}
+
+#endif // _SpeedPickup_H__
Index: /code/branches/RacingBots_FS18/src/modules/pong/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,20 @@
+SET_SOURCE_FILES(PONG_SRC_FILES
+BUILD_UNIT PongBuildUnit.cc
+  Pong.cc
+  PongAI.cc
+  PongBall.cc
+  PongBat.cc
+  PongBot.cc
+  PongCenterpoint.cc
+  PongScore.cc
+END_BUILD_UNIT
+)
+
+ORXONOX_ADD_LIBRARY(pong
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+  SOURCE_FILES ${PONG_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/pong/Pong.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/Pong.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/Pong.cc	(revision 11817)
@@ -0,0 +1,347 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Pong.cc
+    @brief Implementation of the Pong class.
+*/
+
+#include "Pong.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+#include "core/config/ConfigValueIncludes.h"
+
+#include "gamestates/GSLevel.h"
+#include "chat/ChatManager.h"
+
+#include "PongCenterpoint.h"
+#include "PongBall.h"
+#include "PongBat.h"
+#include "PongBot.h"
+#include "PongAI.h"
+
+namespace orxonox
+{
+    // Events to allow to react to scoring of a player, in the level-file.
+    CreateEventName(PongCenterpoint, right);
+    CreateEventName(PongCenterpoint, left);
+
+    RegisterUnloadableClass(Pong);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Pong::Pong(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(Pong);
+
+        this->center_ = nullptr;
+        this->ball_ = nullptr;
+        this->bat_[0] = nullptr;
+        this->bat_[1] = nullptr;
+
+        this->setHUDTemplate("PongHUD");
+
+        // Pre-set the timer, but don't start it yet.
+        this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Pong::startBall, this)));
+        this->starttimer_.stopTimer();
+
+        // Set the type of Bots for this particular Gametype.
+        this->botclass_ = Class(PongBot);
+
+        this->scoreLimit_ = 10;
+        this->setConfigValues();
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up, if initialized.
+    */
+    Pong::~Pong()
+    {
+        if (this->isInitialized())
+            this->cleanup();
+    }
+
+    void Pong::setConfigValues()
+    {
+        SetConfigValue(scoreLimit_, 10).description("The player first reaching those points wins.");
+    }
+
+    /**
+    @brief
+        Cleans up the Gametype by destroying the ball and the bats.
+    */
+    void Pong::cleanup()
+    {
+        if (this->ball_ != nullptr) // Destroy the ball, if present.
+        {
+            this->ball_->destroy();
+            this->ball_ = nullptr;
+        }
+
+        // Destroy both bats, if present.
+        for (size_t i = 0; i < 2; ++i)
+        {
+            if (this->bat_[0] != nullptr)
+            {
+                this->bat_[0]->destroy();
+                this->bat_[0] = nullptr;
+            }
+        }
+
+    }
+
+    /**
+    @brief
+        Starts the Pong minigame.
+    */
+    void Pong::start()
+    {
+        if (this->center_ != nullptr) // There needs to be a PongCenterpoint, i.e. the area the game takes place.
+        {
+            if (this->ball_ == nullptr) // If there is no ball, create a new ball.
+            {
+                this->ball_ = new PongBall(this->center_->getContext());
+                // Apply the template for the ball specified by the centerpoint.
+                this->ball_->addTemplate(this->center_->getBalltemplate());
+            }
+
+            // Attach the ball to the centerpoint and set the parameters as specified in the centerpoint, the ball is attached to.
+            this->center_->attach(this->ball_);
+            this->ball_->setPosition(0, 0, 0);
+            this->ball_->setFieldDimension(this->center_->getFieldDimension());
+            this->ball_->setSpeed(0);
+            this->ball_->setAccelerationFactor(this->center_->getBallAccelerationFactor());
+            this->ball_->setBatLength(this->center_->getBatLength());
+
+            // If one of the bats is missing, create it. Apply the template for the bats as specified in the centerpoint.
+            for (WeakPtr<orxonox::PongBat>& bat : this->bat_)
+            {
+                if (bat == nullptr)
+                {
+                    bat = new PongBat(this->center_->getContext());
+                    bat->addTemplate(this->center_->getBattemplate());
+                }
+            }
+
+            // Attach the bats to the centerpoint and set the parameters as specified in the centerpoint, the bats are attached to.
+            this->center_->attach(this->bat_[0]);
+            this->center_->attach(this->bat_[1]);
+            this->bat_[0]->setPosition(-this->center_->getFieldDimension().x / 2, 0, 0);
+            this->bat_[1]->setPosition( this->center_->getFieldDimension().x / 2, 0, 0);
+            this->bat_[0]->yaw(Degree(-90));
+            this->bat_[1]->yaw(Degree(90));
+            this->bat_[0]->setSpeed(this->center_->getBatSpeed());
+            this->bat_[1]->setSpeed(this->center_->getBatSpeed());
+            this->bat_[0]->setFieldHeight(this->center_->getFieldDimension().y);
+            this->bat_[1]->setFieldHeight(this->center_->getFieldDimension().y);
+            this->bat_[0]->setLength(this->center_->getBatLength());
+            this->bat_[1]->setLength(this->center_->getBatLength());
+
+            // Set the bats for the ball.
+            this->ball_->setBats(this->bat_);
+        }
+        else // If no centerpoint was specified, an error is thrown and the level is exited.
+        {
+            orxout(internal_error) << "Pong: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+
+        // Start the timer. After it has expired the ball is started.
+        this->starttimer_.startTimer();
+
+        // Set variable to temporarily force the player to spawn.
+        bool temp = this->bForceSpawn_;
+        this->bForceSpawn_ = true;
+
+        // Call start for the parent class.
+        Deathmatch::start();
+
+        // Reset the variable.
+        this->bForceSpawn_ = temp;
+    }
+
+    /**
+    @brief
+        Ends the Pong minigame.
+    */
+    void Pong::end()
+    {
+        this->cleanup();
+
+        // Call end for the parent class.
+        Deathmatch::end();
+    }
+
+    /**
+    @brief
+        Spawns players, and fills the rest up with bots.
+    */
+    void Pong::spawnPlayersIfRequested()
+    {
+        // first spawn human players to assign always the left bat to the player in singleplayer
+        for (const auto& mapEntry : this->players_)
+            if (mapEntry.first->isHumanPlayer() && (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                this->spawnPlayer(mapEntry.first);
+        // now spawn bots
+        for (const auto& mapEntry : this->players_)
+            if (!mapEntry.first->isHumanPlayer() && (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                this->spawnPlayer(mapEntry.first);
+    }
+
+    /**
+    @brief
+        Spawns the input player.
+    @param player
+        The player to be spawned.
+    */
+    void Pong::spawnPlayer(PlayerInfo* player)
+    {
+        assert(player);
+
+        // If the first (left) bat has no player.
+        if (this->bat_[0]->getPlayer() == nullptr)
+        {
+            player->startControl(this->bat_[0]);
+            this->players_[player].state_ = PlayerState::Alive;
+        }
+        // If the second (right) bat has no player.
+        else if (this->bat_[1]->getPlayer() == nullptr)
+        {
+            player->startControl(this->bat_[1]);
+            this->players_[player].state_ = PlayerState::Alive;
+        }
+        // If both bats are taken.
+        else
+            return;
+
+        // If the player is an AI, it receives a pointer to the ball.
+        if (player->getController() != nullptr && player->getController()->isA(Class(PongAI)))
+        {
+            PongAI* ai = orxonox_cast<PongAI*>(player->getController());
+            ai->setPongBall(this->ball_);
+        }
+    }
+
+    /**
+    @brief
+        Is called when the player scored.
+    */
+    void Pong::playerScored(PlayerInfo* player, int score)
+    {
+        Deathmatch::playerScored(player, score);
+
+        if (this->center_ != nullptr) // If there is a centerpoint.
+        {
+            // Fire an event for the player that has scored, to be able to react to it in the level, e.g. by displaying fireworks.
+            if (player == this->getRightPlayer())
+                this->center_->fireEvent(FireEventName(PongCenterpoint, right));
+            else if (player == this->getLeftPlayer())
+                this->center_->fireEvent(FireEventName(PongCenterpoint, left));
+
+            // Also announce, that the player has scored.
+            if (player != nullptr)
+                this->gtinfo_->sendAnnounceMessage(player->getName() + " scored");
+        }
+
+        // If there is a ball present, reset its position, velocity and acceleration.
+        if (this->ball_ != nullptr)
+        {
+            this->ball_->setPosition(Vector3::ZERO);
+            this->ball_->setVelocity(Vector3::ZERO);
+            this->ball_->setAcceleration(Vector3::ZERO);
+            this->ball_->setSpeed(0);
+        }
+
+        // If there are bats reset them to the middle position.
+        if (this->bat_[0] != nullptr && this->bat_[1] != nullptr)
+        {
+            this->bat_[0]->setPosition(-this->center_->getFieldDimension().x / 2, 0, 0);
+            this->bat_[1]->setPosition( this->center_->getFieldDimension().x / 2, 0, 0);
+        }
+
+        // If a player gets enough points, he won the game -> end of game
+        PlayerInfo* winningPlayer = nullptr;
+        if (this->getLeftPlayer() && this->getScore(this->getLeftPlayer()) >= scoreLimit_)
+            winningPlayer = this->getLeftPlayer();
+        else if (this->getRightPlayer() && this->getScore(this->getRightPlayer()) >= scoreLimit_)
+            winningPlayer = this->getRightPlayer();
+
+        if (winningPlayer)
+        {
+             ChatManager::message(winningPlayer->getName() + " has won!");
+             this->end();
+        }
+
+        // Restart the timer to start the ball.
+        this->starttimer_.startTimer();
+    }
+
+    /**
+    @brief
+        Starts the ball with some default speed.
+    */
+    void Pong::startBall()
+    {
+        if (this->ball_ != nullptr && this->center_ != nullptr)
+            this->ball_->setSpeed(this->center_->getBallSpeed());
+    }
+
+    /**
+    @brief
+        Get the left player.
+    @return
+        Returns a pointer to the player playing on the left. If there is no left player, nullptr is returned.
+    */
+    PlayerInfo* Pong::getLeftPlayer() const
+    {
+        if (this->bat_[0] != nullptr)
+            return this->bat_[0]->getPlayer();
+        else
+            return nullptr;
+    }
+
+    /**
+    @brief
+        Get the right player.
+    @return
+        Returns a pointer to the player playing on the right. If there is no right player, nullptr is returned.
+    */
+    PlayerInfo* Pong::getRightPlayer() const
+    {
+        if (this->bat_[1] != nullptr)
+            return this->bat_[1]->getPlayer();
+        else
+            return nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/Pong.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/Pong.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/Pong.h	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Pong.h
+    @brief Declaration of the Pong class.
+    @ingroup Pong
+*/
+
+#ifndef _Pong_H__
+#define _Pong_H__
+
+#include "pong/PongPrereqs.h"
+
+#include "tools/Timer.h"
+
+#include "gametypes/Deathmatch.h"
+#include "PongCenterpoint.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Implements a Pong minigame (<a href="http://en.wikipedia.org/wiki/Pong">Wikipedia::Pong</a>).
+        It connects the different entities present in a game of Pong.
+
+        - The @ref orxonox::PongCenterpoint "PongCenterpoint" is the playing field for the Pong minigame, it allows for configuration of the minigame, e.g. by setting the size of the playing field, or the length of the @ref orxonox::PongBat "PongBats". The playing field is always in the x,y-plane, the x-axis being the horizontal and the z-axis being the vertical axis.<br />
+        The Pong class redistributes the important parameters defined in @ref orxonox::PongCenterpoint "PongCenterpoint" to the other entities, that need to know them, e.g. the @ref orxonox::PongBall "PongBall" and the @ref orxonox::PongBat "PongBats".<br />
+        The @ref orxonox::PongCenterpoint "PongCenterpoint" needs to exist in a level with the @ref orxonox::Gametype "Gametype" <em>Pong</em>.
+        - The @ref orxonox::PongBall "PongBall" is the ball both players play with. The @ref orxonox::PongBall "PongBall" both implements the movement of the ball, as well as the influence of the boundaries and consequently, also the bouncing (off the upper and lower delimiters, and as off the @ref orxonox::PongBat "PongBats") of the ball and the effects of the failure of a player to catch the ball (i.e. the scoring of the other player).
+        - The two @ref orxonox::PongBat "PongBats" are the entities through which the players can actively participate in the game, by controlling them. The @ref orxonox::PongBat "PongBat" class manages the movement (and restrictions thereof) and the influence of the players on the bats.
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup Pong
+    */
+    class _PongExport Pong : public Deathmatch
+    {
+        public:
+            Pong(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~Pong(); //!< Destructor. Cleans up, if initialized.
+
+            virtual void start() override; //!< Starts the Pong minigame.
+            virtual void end() override; ///!< Ends the Pong minigame.
+
+            virtual void spawnPlayer(PlayerInfo* player) override; //!< Spawns the input player.
+
+            virtual void playerScored(PlayerInfo* player, int score = 1) override; //!< Is called when the player scored.
+
+            /**
+            @brief Set the PongCenterpoint (the playing field).
+            @param center A pointer to the PongCenterpoint to be set.
+            */
+            void setCenterpoint(PongCenterpoint* center)
+                { this->center_ = center; }
+            void setConfigValues(); //!< Makes scoreLimit configurable.
+
+            PlayerInfo* getLeftPlayer() const; //!< Get the left player.
+            PlayerInfo* getRightPlayer() const; //!< Get the right player.
+
+        protected:
+            virtual void spawnPlayersIfRequested() override; //!< Spawns players, and fills the rest up with bots.
+
+            void startBall(); //!< Starts the ball with some default speed.
+            void cleanup(); //!< Cleans up the Gametype by destroying the ball and the bats.
+
+            WeakPtr<PongCenterpoint> center_; //!< The playing field.
+            WeakPtr<PongBall> ball_; //!< The Pong ball.
+            WeakPtr<PongBat> bat_[2]; //!< The two bats.
+            Timer starttimer_; //!< A timer to delay the start of the game.
+            int scoreLimit_; //!< If a player scored that much points, the game is ended.
+    };
+}
+
+#endif /* _Pong_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongAI.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongAI.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongAI.cc	(revision 11817)
@@ -0,0 +1,385 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongAI.cc
+    @brief Implementation of the PongAI class.
+*/
+
+#include "PongAI.h"
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/command/Executor.h"
+#include "tools/Timer.h"
+
+#include "worldentities/ControllableEntity.h"
+
+#include "PongBall.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(PongAI);
+
+    const static float MAX_REACTION_TIME = 0.4f;
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    PongAI::PongAI(Context* context) : Controller(context)
+    {
+        RegisterObject(PongAI);
+
+        this->ball_ = nullptr;
+        this->ballDirection_ = Vector2::ZERO;
+        this->ballEndPosition_ = 0;
+        this->randomOffset_ = 0;
+        this->bChangedRandomOffset_ = false;
+        this->relHysteresisOffset_ = 0.02f;
+        this->strength_ = 0.5f;
+        this->movement_ = 0;
+        this->oldMove_ = 0;
+        this->bOscillationAvoidanceActive_ = false;
+
+        this->setConfigValues();
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up the list fo reaction timers.
+    */
+    PongAI::~PongAI()
+    {
+        for (std::pair<Timer*, char>& pair : this->reactionTimers_)
+            delete pair.first;
+    }
+
+    /**
+    @brief
+        Sets config values.
+    */
+    void PongAI::setConfigValues()
+    {
+        // Sets the strength of the PongAi as a config value.
+        SetConfigValue(strength_, 0.5).description("A value from 0 to 1 where 0 is weak and 1 is strong.");
+    }
+
+    /**
+    @brief
+        Is called each tick.
+        Implements the behavior of the PongAI (i.e. its intelligence).
+    @param dt
+        The time that has elapsed since the last tick.
+    */
+    void PongAI::tick(float dt)
+    {
+        // If either the ball, or the controllable entity (i.e. the bat) don't exist (or aren't set).
+        if (this->ball_  == nullptr || this->getControllableEntity() == nullptr)
+            return;
+
+        Vector3 mypos = this->getControllableEntity()->getPosition();
+        Vector3 ballpos = this->ball_->getPosition();
+        Vector3 ballvel = this->ball_->getVelocity();
+        float hysteresisOffset = this->relHysteresisOffset_ * this->ball_->getFieldDimension().y;
+
+        char move = 0;
+        bool delay = false;
+
+        // Check in which direction the ball is flying
+        if ((mypos.x > 0 && ballvel.x < 0) || (mypos.x < 0 && ballvel.x > 0))
+        {
+            // The ball is flying away
+            this->ballDirection_.x = -1;
+            this->ballDirection_.y = 0;
+            this->bOscillationAvoidanceActive_ = false;
+
+            // Move to the middle
+            if (mypos.z > hysteresisOffset)
+                move = 1;
+            else if (mypos.z < -hysteresisOffset)
+                move = -1;
+        }
+        else if (ballvel.x == 0)
+        {
+            // The ball is standing still
+            this->ballDirection_.x = 0;
+            this->ballDirection_.y = 0;
+            this->bOscillationAvoidanceActive_ = false;
+        }
+        else
+        {
+            // The ball is approaching
+            if (this->ballDirection_.x != 1)
+            {
+                // The ball just started to approach, initialize all values
+                this->ballDirection_.x = 1;
+                this->ballDirection_.y = sgn(ballvel.z);
+                this->ballEndPosition_ = 0;
+                this->randomOffset_ = 0;
+                this->bChangedRandomOffset_ = false;
+
+                this->calculateRandomOffset();
+                this->calculateBallEndPosition();
+                delay = true;
+                this->bOscillationAvoidanceActive_ = false;
+            }
+
+            if (this->ballDirection_.y != sgn(ballvel.z))
+            {
+                // The ball just bounced from a bound, recalculate the predicted end position
+                this->ballDirection_.y = sgn(ballvel.z);
+
+                this->calculateBallEndPosition();
+                delay = true;
+                this->bOscillationAvoidanceActive_ = false;
+            }
+
+            // If the ball is close enough, calculate another random offset to accelerate the ball
+            if (!this->bChangedRandomOffset_)
+            {
+                float timetohit = (-ballpos.x + this->ball_->getFieldDimension().x / 2 * sgn(ballvel.x)) / ballvel.x;
+                if (timetohit < 0.05)
+                {
+                    this->bChangedRandomOffset_ = true;
+                    if (rnd() < this->strength_)
+                        this->calculateRandomOffset();
+                }
+            }
+
+            // Move to the predicted end position with an additional offset (to hit the ball with the side of the bat)
+            if (!this->bOscillationAvoidanceActive_)
+            {
+                float desiredZValue = this->ballEndPosition_ + this->randomOffset_;
+
+                if (mypos.z > desiredZValue + hysteresisOffset * (this->randomOffset_ < 0))
+                    move = 1;
+                else if (mypos.z < desiredZValue - hysteresisOffset * (this->randomOffset_ > 0))
+                    move = -1;
+            }
+
+            if (move != 0 && this->oldMove_ != 0 && move != this->oldMove_ && !delay)
+            {
+                // We had to correct our position because we moved too far
+                // (and delay is false, so we're not in the wrong place because of a new end-position prediction)
+                if (fabs(mypos.z - this->ballEndPosition_) < 0.5 * this->ball_->getBatLength() * this->ball_->getFieldDimension().y)
+                {
+                    // We're not at the right position, but we still hit the ball, so just stay there to avoid oscillation
+                    move = 0;
+                    this->bOscillationAvoidanceActive_ = true;
+                }
+            }
+        }
+
+        this->oldMove_ = move;
+        this->move(move, delay);
+        this->getControllableEntity()->moveFrontBack(this->movement_);
+    }
+
+    /**
+    @brief
+        Calculates the random offset, that accounts for random errors the AI makes in order to be beatable.
+        The higher the strength of the AI, the smaller the (expected value of the) error.
+        The result of this method is stored in this->randomOffset_.
+    */
+    void PongAI::calculateRandomOffset()
+    {
+        // Calculate the exponent for the position-formula
+        float exp = pow(10.0f, 1.0f - 2.0f*this->strength_); // strength: 0   -> exp = 10
+                                                             // strength: 0.5 -> exp = 1
+                                                             // strength: 1   -> exp = 0.1
+
+        // Calculate the relative position where to hit the ball with the bat
+        float position = pow(rnd(), exp); // exp > 1 -> position is more likely a small number
+                                          // exp < 1 -> position is more likely a large number
+
+        // The position shouldn't be larger than 0.5 (50% of the bat-length from the middle is the end)
+        position *= 0.48f;
+
+        // Both sides are equally probable
+        position *= rndsgn();
+
+        // Calculate the offset in world units
+        this->randomOffset_ = position * this->ball_->getBatLength() * this->ball_->getFieldDimension().y;
+    }
+
+    /**
+    @brief
+        Calculate the end position the ball will be in.
+        The result of this calculation is stored in this->ballEndPosition_.
+    */
+    void PongAI::calculateBallEndPosition()
+    {
+        Vector3 position = this->ball_->getPosition();
+        Vector3 velocity = this->ball_->getVelocity();
+        Vector3 acceleration = this->ball_->getAcceleration();
+        Vector2 dimension = this->ball_->getFieldDimension();
+
+        // Calculate bounces. The number of predicted bounces is limited by the AIs strength
+        for (float limit = -0.05f; limit < this->strength_ || this->strength_ > 0.99f; limit += 0.4f)
+        {
+            // calculate the time until the ball reaches the other side
+            float totaltime = (-position.x + dimension.x / 2 * sgn(velocity.x)) / velocity.x;
+
+            // calculate wall bounce position (four possible solutions of the equation: pos.z + vel.z*t + acc.z/2*t^2 = +/- dim.z/2)
+            float bouncetime = totaltime;
+            bool bUpperWall = false;
+
+            if (acceleration.z == 0)
+            {
+                if (velocity.z > 0)
+                {
+                    bUpperWall = true;
+                    bouncetime = (dimension.y/2 - position.z) / velocity.z;
+                }
+                else if (velocity.z < 0)
+                {
+                    bUpperWall = false;
+                    bouncetime = (-dimension.y/2 - position.z) / velocity.z;
+                }
+            }
+            else
+            {
+                // upper wall
+                float temp = velocity.z*velocity.z + 2*acceleration.z*(dimension.y/2 - position.z);
+                if (temp >= 0)
+                {
+                    float t1 = (sqrt(temp) - velocity.z) / acceleration.z;
+                    float t2 = (sqrt(temp) + velocity.z) / acceleration.z * (-1);
+                    if (t1 > 0 && t1 < bouncetime)
+                    {
+                        bouncetime = t1;
+                        bUpperWall = true;
+                    }
+                    if (t2 > 0 && t2 < bouncetime)
+                    {
+                        bouncetime = t2;
+                        bUpperWall = true;
+                    }
+                }
+                // lower wall
+                temp = velocity.z*velocity.z - 2*acceleration.z*(dimension.y/2 + position.z);
+                if (temp >= 0)
+                {
+                    float t1 = (sqrt(temp) - velocity.z) / acceleration.z;
+                    float t2 = (sqrt(temp) + velocity.z) / acceleration.z * (-1);
+                    if (t1 > 0 && t1 < bouncetime)
+                    {
+                        bouncetime = t1;
+                        bUpperWall = false;
+                    }
+                    if (t2 > 0 && t2 < bouncetime)
+                    {
+                        bouncetime = t2;
+                        bUpperWall = false;
+                    }
+                }
+            }
+
+            if (bouncetime < totaltime)
+            {
+                // Calculate a random prediction error, based on the vertical speed of the ball and the strength of the AI
+                float randomErrorX = rnd(-1, 1) * dimension.y * (velocity.z / velocity.x / PongBall::MAX_REL_Z_VELOCITY) * (1 - this->strength_);
+                float randomErrorZ = rnd(-1, 1) * dimension.y * (velocity.z / velocity.x / PongBall::MAX_REL_Z_VELOCITY) * (1 - this->strength_);
+
+                // ball bounces after <bouncetime> seconds, update the position and continue
+                velocity.z = velocity.z + acceleration.z * bouncetime;
+
+                if (bUpperWall)
+                {
+                    position.z = dimension.y / 2;
+                    velocity.z = -fabs(velocity.z) + fabs(randomErrorZ);
+                }
+                else
+                {
+                    position.z = -dimension.y / 2;
+                    velocity.z = fabs(velocity.z) - fabs(randomErrorZ);
+                }
+
+                position.x = position.x + velocity.x * bouncetime + randomErrorX;
+                this->ballEndPosition_ = position.z;
+            }
+            else
+            {
+                // ball doesn't bounce, calculate the end position and return
+                // calculate end-height: current height + slope * distance incl. acceleration
+                this->ballEndPosition_ = position.z + velocity.z * totaltime + acceleration.z / 2 * totaltime * totaltime;
+                return;
+            }
+        }
+    }
+
+    /**
+    @brief
+        Determine the movement the AI will undertake. (Either -1, 0 or 1)
+        The result of this calculation is stored in this->movement_;
+    @param direction
+        The current direction of movement.
+    @param bUseDelay
+        The time by which this move is delayed. (Again, to make the AI less efficient)
+    */
+    void PongAI::move(char direction, bool bUseDelay)
+    {
+        // The current direction is either what we're doing right now (movement_) or what is last in the queue
+        char currentDirection = this->movement_;
+        if (this->reactionTimers_.size() > 0)
+            currentDirection = this->reactionTimers_.back().second;
+
+        // Only add changes of direction
+        if (direction == currentDirection)
+            return;
+
+        if (bUseDelay)
+        {
+            // Calculate delay
+            float delay = MAX_REACTION_TIME * (1 - this->strength_);
+
+            // Add a new Timer
+            Timer* timer = new Timer(delay, false, createExecutor(createFunctor(&PongAI::delayedMove, this)));
+            this->reactionTimers_.emplace_back(timer, direction);
+        }
+        else
+        {
+            this->movement_ = direction;
+        }
+    }
+
+    /**
+    @brief
+        Is called, when a delayed move takes effect.
+    */
+    void PongAI::delayedMove()
+    {
+        // Get the new movement direction from the timer list
+        this->movement_ = this->reactionTimers_.front().second;
+
+        // Destroy the timer and remove it from the list
+        delete this->reactionTimers_.front().first;
+        this->reactionTimers_.pop_front();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongAI.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongAI.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongAI.h	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongAI.h
+    @brief Declaration of the PongAI class.
+    @ingroup Pong
+*/
+
+#ifndef _PongAI_H__
+#define _PongAI_H__
+
+#include "pong/PongPrereqs.h"
+
+#include <list>
+
+#include "util/Math.h"
+#include "tools/interfaces/Tickable.h"
+
+#include "controllers/Controller.h"
+#include "PongBall.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The PongAI is an artificial intelligence for the @ref orxonox::Pong "Pong" gametype.
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup Pong
+    */
+    class _PongExport PongAI : public Controller, public Tickable
+    {
+        public:
+            PongAI(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~PongAI();
+
+            void setConfigValues();
+
+            virtual void tick(float dt) override; //!< Implements the behavior of the PongAI (i.e. its intelligence).
+
+            /**
+            @brief Set the ball for the AI.
+            @param ball A pointer to the ball.
+            */
+            void setPongBall(PongBall* ball)
+                { this->ball_ = ball; }
+
+        protected:
+            void calculateRandomOffset(); //!< Calculates the random offset, that accounts for random errors the AI makes in order to be beatable.
+            void calculateBallEndPosition(); //!< Calculate the end position the ball will be in.
+            void move(char direction, bool bUseDelay); //!< Determine the movement the AI will undertake.
+            void delayedMove(); //!< Is called, when a delayed move takes effect.
+
+            WeakPtr<PongBall> ball_; //!< A weak pointer to the ball.
+            Vector2 ballDirection_; //!< Vector to store the (x,z) direction in which the ball is flying.
+            float ballEndPosition_; //!< The calculated end position of the ball.
+            float randomOffset_; //!< A random offset to introduce random errors (weighted by the strength of the AI) into the AI's behavior.
+            bool bChangedRandomOffset_; //!< Helper boolean, to change the random offset more often.
+            float relHysteresisOffset_; //!< A hysteresis offset.
+            float strength_; //!< The strength of the AI. Ranging from 0 to 1.
+
+            std::list<std::pair<Timer*, char>> reactionTimers_; //!< A list of reaction timers and the directions that take effect when their timer expires.
+            char movement_; //!< The planned movement.
+            char oldMove_; //!< The previous movement.
+            bool bOscillationAvoidanceActive_; //!< Boolean, to avoid oscillations.
+    };
+}
+
+#endif /* _PongAI_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongBall.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongBall.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongBall.cc	(revision 11817)
@@ -0,0 +1,349 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBall.cc
+    @brief Implementation of the PongBall class.
+*/
+
+#include "PongBall.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+
+#include "gametypes/Gametype.h"
+
+#include "PongBat.h"
+
+#include "sound/WorldSound.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(PongBall);
+
+    const float PongBall::MAX_REL_Z_VELOCITY = 1.5;
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    PongBall::PongBall(Context* context)
+        : MovableEntity(context)
+    {
+        RegisterObject(PongBall);
+
+        this->speed_ = 0;
+        this->accelerationFactor_ = 1.0f;
+        this->bat_ = nullptr;
+        this->bDeleteBats_ = false;
+        this->batID_ = new unsigned int[2];
+        this->batID_[0] = OBJECTID_UNKNOWN;
+        this->batID_[1] = OBJECTID_UNKNOWN;
+        this->relMercyOffset_ = 0.05f;
+
+        this->registerVariables();
+
+        //initialize sound
+        if (GameMode::isMaster())
+             {
+                 this->defScoreSound_ = new WorldSound(this->getContext());
+                 this->defScoreSound_->setVolume(1.0f);
+                 this->defBatSound_ = new WorldSound(this->getContext());
+                 this->defBatSound_->setVolume(0.4f);
+                 this->defBoundarySound_ = new WorldSound(this->getContext());
+                 this->defBoundarySound_->setVolume(0.5f);
+             }
+             else
+             {
+                 this->defScoreSound_ = nullptr;
+                 this->defBatSound_ = nullptr;
+                 this->defBoundarySound_ = nullptr;
+             }
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    PongBall::~PongBall()
+    {
+        if (this->isInitialized())
+        {
+            if (this->bDeleteBats_)
+                delete[] this->bat_;
+
+            delete[] this->batID_;
+        }
+    }
+
+    //xml port for loading sounds
+    void PongBall::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PongBall, XMLPort, xmlelement, mode);
+        XMLPortParam(PongBall, "defScoreSound",  setDefScoreSound,  getDefScoreSound,  xmlelement, mode);
+        XMLPortParam(PongBall, "defBatSound",  setDefBatSound,  getDefBatSound,  xmlelement, mode);
+        XMLPortParam(PongBall, "defBoundarySound",  setDefBoundarySound,  getDefBoundarySound,  xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Register variables to synchronize over the network.
+    */
+    void PongBall::registerVariables()
+    {
+        registerVariable( this->fieldWidth_ );
+        registerVariable( this->fieldHeight_ );
+        registerVariable( this->batlength_ );
+        registerVariable( this->speed_ );
+        registerVariable( this->relMercyOffset_ );
+        registerVariable( this->batID_[0] );
+        registerVariable( this->batID_[1], VariableDirection::ToClient, new NetworkCallback<PongBall>( this, &PongBall::applyBats) );
+    }
+
+    /**
+    @brief
+        Is called every tick.
+        Handles the movement of the ball and its interaction with the boundaries and bats.
+    @param dt
+        The time since the last tick.
+    */
+    void PongBall::tick(float dt)
+    {
+        SUPER(PongBall, tick, dt);
+
+        // Get the current position, velocity and acceleration of the ball.
+        Vector3 position = this->getPosition();
+        Vector3 velocity = this->getVelocity();
+        Vector3 acceleration = this->getAcceleration();
+
+        // If the ball has gone over the top or bottom boundary of the playing field (i.e. the ball has hit the top or bottom delimiters).
+        if (position.z > this->fieldHeight_ / 2 || position.z < -this->fieldHeight_ / 2)
+        {
+            defBoundarySound_->play(); //play boundary sound
+            // Its velocity in z-direction is inverted (i.e. it bounces off).
+            velocity.z = -velocity.z;
+            // And its position is set as to not overstep the boundary it has just crossed.
+            if (position.z > this->fieldHeight_ / 2)
+                position.z = this->fieldHeight_ / 2;
+            if (position.z < -this->fieldHeight_ / 2)
+                position.z = -this->fieldHeight_ / 2;
+
+            this->fireEvent();
+        }
+
+        // If the ball has crossed the left or right boundary of the playing field (i.e. a player has just scored, if the bat isn't there to parry).
+        if (position.x > this->fieldWidth_ / 2 || position.x < -this->fieldWidth_ / 2)
+        {
+            float distance = 0;
+
+            if (this->bat_ != nullptr) // If there are bats.
+            {
+                // If the right boundary has been crossed.
+                if (position.x > this->fieldWidth_ / 2 && this->bat_[1] != nullptr)
+                {
+                    // Calculate the distance (in z-direction) between the ball and the center of the bat, weighted by half of the effective length of the bat (with additional 10%)
+                    distance = (position.z - this->bat_[1]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10f) / 2);
+                    if (fabs(distance) <= 1) // If the bat is there to parry.
+                    {
+                        defBatSound_->play(); //play bat sound
+                        // Set the ball to be exactly at the boundary.
+                        position.x = this->fieldWidth_ / 2;
+                        // Invert its velocity in x-direction (i.e. it bounces off).
+                        velocity.x = -velocity.x;
+                        // Adjust the velocity in the z-direction, depending on where the ball hit the bat.
+                        velocity.z = distance * distance * sgn(distance) * PongBall::MAX_REL_Z_VELOCITY * this->speed_;
+                        acceleration = this->bat_[1]->getVelocity() * this->accelerationFactor_ * -1;
+
+                        this->fireEvent();
+                    }
+                    // If the left player scores.
+                    else if (GameMode::isMaster() && position.x > this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
+                    {
+                        defScoreSound_->play();//play score sound
+                        if (this->getGametype() && this->bat_[0])
+                        {
+                            this->getGametype()->playerScored(this->bat_[0]->getPlayer());
+                            return;
+                        }
+                    }
+                }
+                // If the left boundary has been crossed.
+                else if (position.x < -this->fieldWidth_ / 2 && this->bat_[0] != nullptr)
+                {
+                    // Calculate the distance (in z-direction) between the ball and the center of the bat, weighted by half of the effective length of the bat (with additional 10%)
+                    distance = (position.z - this->bat_[0]->getPosition().z) / (this->fieldHeight_ * (this->batlength_ * 1.10f) / 2);
+                    if (fabs(distance) <= 1) // If the bat is there to parry.
+                    {
+                        defBatSound_->play(); //play bat sound
+                        // Set the ball to be exactly at the boundary.
+                        position.x = -this->fieldWidth_ / 2;
+                        // Invert its velocity in x-direction (i.e. it bounces off).
+                        velocity.x = -velocity.x;
+                        // Adjust the velocity in the z-direction, depending on where the ball hit the bat.
+                        velocity.z = distance * distance * sgn(distance) * PongBall::MAX_REL_Z_VELOCITY * this->speed_;
+                        acceleration = this->bat_[0]->getVelocity() * this->accelerationFactor_ * -1;
+
+                        this->fireEvent();
+                    }
+                    // If the right player scores.
+                    else if (GameMode::isMaster() && position.x < -this->fieldWidth_ / 2 * (1 + this->relMercyOffset_))
+                    {
+                        defScoreSound_->play();//play score sound
+                        if (this->getGametype() && this->bat_[1])
+                        {
+                            this->getGametype()->playerScored(this->bat_[1]->getPlayer());
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
+        // Set the position, velocity and acceleration of the ball, if they have changed.
+        if (acceleration != this->getAcceleration())
+            this->setAcceleration(acceleration);
+        if (velocity != this->getVelocity())
+            this->setVelocity(velocity);
+        if (position != this->getPosition())
+            this->setPosition(position);
+    }
+
+    /**
+    @brief
+        Set the speed of the ball (in x-direction).
+    @param speed
+        The speed to be set.
+    */
+    void PongBall::setSpeed(float speed)
+    {
+        if (speed != this->speed_) // If the speed changes
+        {
+            this->speed_ = speed;
+
+            // Set the speed in the direction of the balls current velocity.
+            Vector3 velocity = this->getVelocity();
+            if (velocity.x != 0)
+                velocity.x = sgn(velocity.x) * this->speed_;
+            else // If the balls current velocity is zero, the speed is set in a random direction.
+                velocity.x = this->speed_ * sgn(rnd(-1,1));
+
+            this->setVelocity(velocity);
+        }
+    }
+
+    /**
+    @brief
+        Set the bats for the ball.
+    @param bats
+        An array (of size 2) of weak pointers, to be set as the new bats.
+    */
+    void PongBall::setBats(WeakPtr<PongBat>* bats)
+    {
+        if (this->bDeleteBats_) // If there are already some bats, delete them.
+        {
+            delete[] this->bat_;
+            this->bDeleteBats_ = false;
+        }
+
+        this->bat_ = bats;
+        // Also store their object IDs, for synchronization.
+        this->batID_[0] = this->bat_[0]->getObjectID();
+        this->batID_[1] = this->bat_[1]->getObjectID();
+    }
+
+    /**
+    @brief
+        Get the bats over the network.
+    */
+    void PongBall::applyBats()
+    {
+        // Make space for the bats, if they don't exist, yet.
+        if (this->bat_ == nullptr)
+        {
+            this->bat_ = new WeakPtr<PongBat>[2];
+            this->bDeleteBats_ = true;
+        }
+
+        if (this->batID_[0] != OBJECTID_UNKNOWN)
+            this->bat_[0] = orxonox_cast<PongBat*>(Synchronisable::getSynchronisable(this->batID_[0]));
+        if (this->batID_[1] != OBJECTID_UNKNOWN)
+            this->bat_[1] = orxonox_cast<PongBat*>(Synchronisable::getSynchronisable(this->batID_[1]));
+    }
+
+    void PongBall::setDefScoreSound(const std::string &pongSound)
+    {
+        if( defScoreSound_ )
+            defScoreSound_->setSource(pongSound);
+        else
+            assert(0); // This should never happen, because soundpointer is only available on master
+    }
+
+    const std::string& PongBall::getDefScoreSound()
+    {
+        if( defScoreSound_ )
+            return defScoreSound_->getSource();
+        else
+            assert(0);
+        return BLANKSTRING;
+    }
+
+    void PongBall::setDefBatSound(const std::string &pongSound)
+    {
+        if( defBatSound_ )
+            defBatSound_->setSource(pongSound);
+        else
+            assert(0); // This should never happen, because soundpointer is only available on master
+    }
+
+    const std::string& PongBall::getDefBatSound()
+    {
+        if( defBatSound_ )
+            return defBatSound_->getSource();
+        else
+            assert(0);
+        return BLANKSTRING;
+    }
+
+    void PongBall::setDefBoundarySound(const std::string &pongSound)
+    {
+        if( defBoundarySound_ )
+            defBoundarySound_->setSource(pongSound);
+        else
+            assert(0); // This should never happen, because soundpointer is only available on master
+    }
+
+    const std::string& PongBall::getDefBoundarySound()
+    {
+        if( defBoundarySound_ )
+            return defBoundarySound_->getSource();
+        else
+            assert(0);
+        return BLANKSTRING;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongBall.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongBall.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongBall.h	(revision 11817)
@@ -0,0 +1,153 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBall.h
+    @brief Declaration of the PongBall class.
+    @ingroup Pong
+*/
+
+#ifndef _PongBall_H__
+#define _PongBall_H__
+
+#include "pong/PongPrereqs.h"
+
+#include "util/Math.h"
+
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        This class manages the ball for @ref orxonox::Pong "Pong".
+
+        It is responsible for both the movement of the ball in the x,z-plane as well as its interaction with the boundaries of the playing field (defined by the @ref orxonox::PongCenterpoint "PongCenterpoint") and the @ref orxonox::PongBat "PongBats". Or more precisely, it makes the ball bounce off then upper and lower delimiters of the playing field, it makes the ball bounce off the bats and also detects when a player scores and takes appropriate measures.
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup Pong
+    */
+    class _PongExport PongBall : public MovableEntity
+    {
+        public:
+            PongBall(Context* context);
+            virtual ~PongBall();
+
+            virtual void tick(float dt) override;
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            /**
+            @brief Set the dimensions of the playing field.
+            @param width The width of the playing field.
+            @param height The height of the playing field.
+            */
+            void setFieldDimension(float width, float height)
+                { this->fieldWidth_ = width; this->fieldHeight_ = height; }
+            /**
+            @brief Get the dimensions of the playing field.
+            @param dimension A vector with the width as the first and height as the second component.
+            */
+            void setFieldDimension(const Vector2& dimension)
+                { this->setFieldDimension(dimension.x, dimension.y); }
+            /**
+            @brief Get the dimensions of the playing field.
+            @return Returns a vector with the width as the first and height as the second component.
+            */
+            Vector2 getFieldDimension() const
+                { return Vector2(this->fieldWidth_, this->fieldHeight_); }
+
+            void setSpeed(float speed); //!< Set the speed of the ball (in x-direction).
+            /**
+            @brief Get the speed of the ball (in x-direction).
+            @return Returns the speed of the ball (in x-direction).
+            */
+            float getSpeed() const
+                { return this->speed_; }
+
+            /**
+            @brief Set the acceleration factor of the ball.
+            @param factor The factor the acceleration of the ball is set to.
+            */
+            void setAccelerationFactor(float factor)
+                { this->accelerationFactor_ = factor; }
+            /**
+            @brief Get the acceleration factor of the ball.
+            @return Returns the acceleration factor of the ball.
+            */
+            float getAccelerationFactor() const
+                { return this->accelerationFactor_; }
+
+            /**
+            @brief Set the length of the bats.
+            @param batlength The length of the bats (in z-direction) as percentage of the height of the playing field.
+            */
+            void setBatLength(float batlength)
+                { this->batlength_ = batlength; }
+            /**
+            @brief Get the length of the bats.
+            @return Returns the length of the bats (in z-direction) as percentage of the height of the playing field.
+            */
+            float getBatLength() const
+                { return this->batlength_; }
+
+            void setBats(WeakPtr<PongBat>* bats); //!< Set the bats for the ball.
+            void applyBats(); //!< Get the bats over the network.
+
+            static const float MAX_REL_Z_VELOCITY;
+
+            void setDefScoreSound(const std::string& engineSound);
+            const std::string& getDefScoreSound();
+            void setDefBatSound(const std::string& engineSound);
+            const std::string& getDefBatSound();
+            void setDefBoundarySound(const std::string& engineSound);
+            const std::string& getDefBoundarySound();
+
+        private:
+            void registerVariables();
+
+            float fieldWidth_; //!< The width of the playing field.
+            float fieldHeight_; //!< The height of the playing field.
+            float speed_; //!< The speed (in x-direction) of the ball.
+            float accelerationFactor_; //!< The acceleration factor of the ball.
+            float batlength_; //!< The length of the bats (in z-direction) as percentage of the height of the playing field.
+            WeakPtr<PongBat>* bat_; //!< An array with the two bats.
+            bool bDeleteBats_; //!< Bool, to keep track, of whether this->bat_ exists or not.
+            unsigned int* batID_; //!< The object IDs of the bats, to be able to synchronize them over the network.
+            float relMercyOffset_; //!< Offset, that makes the player not loose, when, in all fairness, he would have.
+            WorldSound* defScoreSound_;
+            WorldSound* defBatSound_;
+            WorldSound* defBoundarySound_;
+    };
+}
+
+#endif /* _PongBall_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongBat.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongBat.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongBat.cc	(revision 11817)
@@ -0,0 +1,155 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBat.cc
+    @brief Implementation of the PongBat class.
+*/
+
+#include "PongBat.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(PongBat);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    PongBat::PongBat(Context* context) : ControllableEntity(context)
+    {
+        RegisterObject(PongBat);
+
+        this->movement_ = 0;
+        this->bMoveLocal_ = false;
+        this->speed_ = 60;
+        this->length_ = 0.25;
+        this->fieldHeight_ = 100;
+        this->bSteadiedPosition_ = false;
+
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Registers variables to be synchronized over the network.
+    */
+    void PongBat::registerVariables()
+    {
+        registerVariable(this->speed_);
+        registerVariable(this->fieldHeight_);
+        registerVariable(this->length_);
+    }
+
+    /**
+    @brief
+        Is called each tick.
+        Moves the bat.
+    @param dt
+        The time since last tick.
+    */
+    void PongBat::tick(float dt)
+    {
+        // If the bat is controlled (but not over the network).
+        if (this->hasLocalController())
+        {
+            if (this->movement_ != 0)
+            {
+                // The absolute value of the movement is restricted to be lesser or equal than the speed of the bat.
+                this->movement_ = clamp(this->movement_, -1.0f, 1.0f) * this->speed_;
+
+                // If moveRightLeft() is used the movement is dependento on wehther it is the right or the left bat, so, it is i.e. dependent on the orientation of the bat.
+                if (this->bMoveLocal_)
+                    this->setVelocity(this->getOrientation() * Vector3(this->movement_, 0, 0));
+                else
+                    this->setVelocity(0, 0, this->movement_);
+
+                this->movement_ = 0;
+                this->bSteadiedPosition_ = false;
+            }
+            // If there is no movement but the position has not been steadied, the velocity is set to zero and the position is reaffirmed.
+            else if (!this->bSteadiedPosition_)
+            {
+                // To ensure network synchronicity
+                this->setVelocity(0, 0, 0);
+                this->setPosition(this->getPosition());
+                this->bSteadiedPosition_ = true;
+            }
+        }
+
+        SUPER(PongBat, tick, dt);
+
+        // Restrict the position of the bats, for them to always be between the upper and lower delimiters. i.e. the bats stall if they reach the upper or lower boundary.
+        Vector3 position = this->getPosition();
+        if (position.z > this->fieldHeight_ / 2 - this->fieldHeight_ * this->length_ / 2)
+            position.z = this->fieldHeight_ / 2 - this->fieldHeight_ * this->length_ / 2;
+        if (position.z < -this->fieldHeight_ / 2 + this->fieldHeight_ * this->length_ / 2)
+            position.z = -this->fieldHeight_ / 2 + this->fieldHeight_ * this->length_ / 2;
+        if (position != this->getPosition())
+        {
+            this->setPosition(position);
+            this->setVelocity( Vector3::ZERO );
+        }
+    }
+
+    /**
+    @brief
+        Overloaded the function to steer the bat up and down.
+    @param value
+        A vector whose first component is the inverse direction in which we want to steer the bat.
+    */
+    void PongBat::moveFrontBack(const Vector2& value)
+    {
+        this->bMoveLocal_ = false;
+        this->movement_ = -value.x;
+    }
+
+    /**
+    @brief
+        Overloaded the function to steer the bat up and down.
+    @param value
+        A vector whose first component is the direction in which we wnat to steer the bat.
+    */
+    void PongBat::moveRightLeft(const Vector2& value)
+    {
+        this->bMoveLocal_ = true;
+        this->movement_ = value.x;
+    }
+
+    /**
+    @brief
+        Is called when the player changed.
+    */
+    void PongBat::changedPlayer()
+    {
+        this->setVelocity(0, 0, 0);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongBat.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongBat.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongBat.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBat.h
+    @brief Declaration of the PongBat class.
+    @ingroup Pong
+*/
+
+#ifndef _PongBat_H__
+#define _PongBat_H__
+
+#include "pong/PongPrereqs.h"
+
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The PongBat class manages the bats for @ref orxonox::Pong "Pong", which are the elements controlled by the players.
+
+        It is responsible for the movement (controlled by the players) of the bat.
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup Pong
+    */
+    class _PongExport PongBat : public ControllableEntity
+    {
+        public:
+            PongBat(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~PongBat() {}
+
+            virtual void tick(float dt) override;
+
+            virtual void moveFrontBack(const Vector2& value) override; //!< Overloaded the function to steer the bat up and down.
+            virtual void moveRightLeft(const Vector2& value) override; //!< Overloaded the function to steer the bat up and down.
+
+            virtual void changedPlayer() override; //!< Is called when the player changed.
+
+            /**
+            @brief Set the speed of the bat.
+            @param speed The speed to be set.
+            */
+            void setSpeed(float speed)
+                { this->speed_ = speed; }
+            /**
+            @brief Get the speed of the bat.
+            @return Returns the speed of the bat.
+            */
+            float getSpeed() const
+                { return this->speed_; }
+
+            /**
+            @brief Set the height of the playing field.
+            @param height The height of the playing field.
+            */
+            void setFieldHeight(float height)
+                { this->fieldHeight_ = height; }
+            /**
+            @brief Get the height of the playing field.
+            @return Returns the height of the playing field.
+            */
+            float getFieldHeight() const
+                { return this->fieldHeight_; }
+
+            /**
+            @brief Set the length of the bat.
+            @param length The length of the bat (in z-direction) as percentage of the height of the playing field.
+            */
+            void setLength(float length)
+                { this->length_ = length; }
+            /**
+            @brief Get the length of the bat.
+            @return Returns the length of the bat (in z-direction) as percentage of the height of the playing field.
+            */
+            float getLength() const
+                { return this->length_; }
+
+        private:
+            void registerVariables(); //!< Registers variables to be synchronized over the network.
+
+            float movement_; //!< The amount (and direction), in z-direction, of movement of the bat.
+            bool bMoveLocal_; //!< Helper to know whether the movement is caused by moveFrontBack() or moveRightLeft().
+            float speed_; //!< The movement speed of the bat.
+            float length_; //!< The length of the bat (in z-direction) as percentage of the height of the playing field.
+            float fieldHeight_; //!< The height of the playing field.
+            bool bSteadiedPosition_; //!< Helper boolean, to keep track of when to steady the position, to ensure network synchronicity.
+    };
+}
+
+#endif /* _PongBat_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongBot.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongBot.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongBot.cc	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBot.cc
+    @brief Implementation of the PongBot class.
+*/
+
+#include "PongBot.h"
+
+#include "core/CoreIncludes.h"
+#include "PongAI.h"
+
+namespace orxonox
+{
+    RegisterClass(PongBot);
+
+    /**
+    @brief
+        Constructor. Registers the object and creates a PongAI controller.
+    */
+    PongBot::PongBot(Context* context) : Bot(context)
+    {
+        RegisterObject(PongBot);
+
+        this->defaultController_ = Class(PongAI);
+        this->createController();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongBot.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongBot.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongBot.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongBot.h
+    @brief Declaration of the PongBot class.
+    @ingroup Pong
+*/
+
+#ifndef _PongBot_H__
+#define _PongBot_H__
+
+#include "pong/PongPrereqs.h"
+#include "infos/Bot.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A bot especially for @ref orxonox::Pong "Pong".
+
+        Uses the @ref orxonox::PongAI "PongAI".
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup Pong
+    */
+    class _PongExport PongBot : public Bot
+    {
+        public:
+            PongBot(Context* context);
+            virtual ~PongBot() {}
+    };
+}
+
+#endif /* _PongBot_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongCenterpoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongCenterpoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongCenterpoint.cc	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongCenterpoint.cc
+    @brief Implementation of the PongCenterpoint class.
+*/
+
+#include "PongCenterpoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Pong.h"
+
+namespace orxonox
+{
+    RegisterClass(PongCenterpoint);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object and checks whether the gametype is actually Pong.
+    */
+    PongCenterpoint::PongCenterpoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(PongCenterpoint);
+
+        this->width_ = 200;
+        this->height_ = 120;
+        this->ballspeed_ = 100;
+        this->ballaccfactor_ = 1.0;
+        this->batspeed_ = 60;
+        this->batlength_ = 0.25;
+
+        this->checkGametype();
+    }
+
+    /**
+    @brief
+        Method to create a PongCenterpoint through XML.
+    */
+    void PongCenterpoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PongCenterpoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PongCenterpoint, "dimension", setFieldDimension, getFieldDimension, xmlelement, mode);
+        XMLPortParam(PongCenterpoint, "balltemplate", setBalltemplate, getBalltemplate, xmlelement, mode);
+        XMLPortParam(PongCenterpoint, "battemplate", setBattemplate, getBattemplate, xmlelement, mode);
+        XMLPortParam(PongCenterpoint, "ballspeed", setBallSpeed, getBallSpeed, xmlelement, mode);
+        XMLPortParam(PongCenterpoint, "ballaccfactor", setBallAccelerationFactor, getBallAccelerationFactor, xmlelement, mode);
+        XMLPortParam(PongCenterpoint, "batspeed", setBatSpeed, getBatSpeed, xmlelement, mode);
+        XMLPortParam(PongCenterpoint, "batlength", setBatLength, getBatLength, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Checks whether the gametype is Pong and if it is, sets its centerpoint.
+    */
+    void PongCenterpoint::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Pong)))
+        {
+            Pong* pongGametype = orxonox_cast<Pong*>(this->getGametype());
+            pongGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongCenterpoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongCenterpoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongCenterpoint.h	(revision 11817)
@@ -0,0 +1,235 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongCenterpoint.h
+    @brief Declaration of the PongCenterpoint class.
+    @ingroup Pong
+*/
+
+#ifndef _PongCenterpoint_H__
+#define _PongCenterpoint_H__
+
+#include "pong/PongPrereqs.h"
+
+#include <string>
+
+#include <util/Math.h>
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    
+    /**
+    @brief
+        The PongCenterpoint implements the playing field @ref orxonox::Pong "Pong" takes place in and allows for many parameters of the minigame to be set.
+        The playing field resides in the x,z-plane, with the x-axis being the horizontal axis and the z-axis being the vertical axis.
+        
+        Various parameters can be set:
+        - The <b>dimension</b> is a vector, that defines the width and height of the playing field. The default is <em>(200, 120)</em>.
+        - The <b>balltemplate</b> is a template that is applied to the @ref orxonox::PongBall "PongBall", it can be used to attach different things to it, e.g. its @ref orxonox::Model "Model". See below for a usage example.
+        - The <b>battemplate</b> is a template that is applied to the @ref orxonox::PongBall "PongBat", it can be used to attach different things to it, e.g. its @ref orxonox::Model "Model". See below for a usage example.
+        - The <b>ballspeed</b> is the speed with which the @ref orxonox::PongBall "PongBall" moves. The default is <em>100</em>.
+        - The <b>ballaccfactor</b> is the acceleration factor for the @ref orxonox::PongBall "PongBall". The default is <em>1.0</em>.
+        - The <b>batspeed</b> is the speed with which the @ref orxonox::PongBat "PongBats" move. The default is <em>60</em>.
+        - The <b>batlength</b> is the length of the @ref orxonox::PongBat "PongBats" as the percentage of the height of the playing field. The default is <em>0.25</em>.
+        
+        An example in XML of the PongCenterpoint would be:
+        
+        First the needed templates:
+        The template for the @ref orxonox::PongBall "PongBall".
+        @code
+        <Template name="pongball">
+          <PongBall>
+            <attached>
+              <Model mesh="sphere.mesh" scale="2" />
+              <ParticleSpawner name="hiteffect" position="0,0,0" source="Orxonox/sparks2" lifetime="0.01" autostart="0" mainstate="spawn" />
+            </attached>
+            <eventlisteners>
+              <EventTarget target="hiteffect" />
+            </eventlisteners>
+          </PongBall>
+        </Template>
+        @endcode
+        As can be seen, a sphere is attached as the @ref orxonox::Model "Model" for the @ref orxonox::PongBall "PongBall", and also an @ref orxonox::EventListener "EventListener" that triggers a @ref orxonox::ParticleSpawner "ParticleSpawner", whenever the ball hits the boundaries is attached.
+        
+        Additionally the template for the @ref orxonox::PongBat "PongBat".
+        @code
+        <Template name="pongbatcameras" defaults="0">
+          <PongBat>
+            <camerapositions>
+              <CameraPosition position="0,200,0" pitch="-90" absolute="true" />
+            </camerapositions>
+          </PongBat>
+        </Template>
+
+        <Template name="pongbat">
+          <PongBat camerapositiontemplate=pongbatcameras>
+            <attached>
+              <Model position="0,0,3" mesh="cube.mesh" scale3D="14,2,2" />
+            </attached>
+          </PongBat>
+        </Template>
+        @endcode
+        As can be seen, there are actually two templates. The first template is needed to set the camera for the @ref orxonox::PongBat "PongBat". The second template ist the actual template for the @ref orxonox::PongBat "PongBat", the template for the camera position is added and a @ref orxonox::Model "Model" for the @ref orxonox::PongBat "PongBat" is attached.
+        
+        Finally the PongCenterpoint is created.
+        @code
+        <PongCenterpoint name="pongcenter" dimension="200,120" balltemplate="pongball" battemplate="pongbat" ballspeed="200" ballaccfactor="1.0" batspeed="130" batlength="0.25">
+          <attached>
+            <Model position="0,0,60" mesh="cube.mesh" scale3D="105,1,1" />
+            <Model position="0,0,-60" mesh="cube.mesh" scale3D="105,1,1" />
+          </attached>
+        </PongCenterpoint>
+        @endcode
+        All parameters are specified. And also two @ref orxonox::Model "Models" (for the upper and lower boundary) are attached.
+        
+        For a more elaborate example, have a look at the <code>pong.oxw</code> level file.
+    
+    @author
+        Fabian 'x3n' Landau
+        
+    @ingroup Pong
+    */
+    class _PongExport PongCenterpoint : public StaticEntity
+    {
+        public:
+            PongCenterpoint(Context* context); //!< Constructor. Registers and initializes the object and checks whether the gametype is actually Pong.
+            virtual ~PongCenterpoint() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method to create a PongCenterpoint through XML.
+
+            /**
+            @brief Set the template for the ball. (e.g. to attach the model of the ball, but also to attach an EventListener to it to detect, when it hits the boundaries, and e.g. display some ParticleEffets, when it does.)
+            @param balltemplate The name of the template to be set.
+            */
+            void setBalltemplate(const std::string& balltemplate)
+                { this->balltemplate_ = balltemplate; }
+            /**
+            @brief Get the template of the ball.
+            @return Returns the name of the template of the ball. 
+            */
+            const std::string& getBalltemplate() const
+                { return this->balltemplate_; }
+
+            /**
+            @brief Set the template for the bats. (e.g. to attach the model of the bat, but also to attach CameraPositions to it, to be able to view the game from the bats perspective)
+            @param battemplate The name of the template to be set.
+            */
+            void setBattemplate(const std::string& battemplate)
+                { this->battemplate_ = battemplate; }
+            /**
+            @brief Get the template of the bats.
+            @return Returns the name of the template of the bats.
+            */
+            const std::string& getBattemplate() const
+                { return this->battemplate_; }
+
+            /**
+            @brief Set the dimensions of the playing field.
+            @param dimension A vector with the width of the playing field as first component and the height as second.
+            */
+            void setFieldDimension(const Vector2& dimension)
+                { this->width_ = dimension.x; this->height_ = dimension.y; }
+            /**
+            @brief Get the dimensions of the playing field.
+            @return Returns a vector with the width of the playing field as first component and the height as second.
+            */
+            Vector2 getFieldDimension() const
+                { return Vector2(this->width_, this->height_); }
+
+            /**
+            @brief Set the speed of the ball.
+            @param ballspeed The speed of the ball.
+            */
+            void setBallSpeed(float ballspeed)
+                { this->ballspeed_ = ballspeed; }
+            /**
+            @brief Get the speed of the ball.
+            @return Returns the speed of the ball.
+            */
+            float getBallSpeed() const
+                { return this->ballspeed_; }
+
+            /**
+            @brief Set the ball's acceleration factor.
+            @param ballaccfactor The ball's acceleration factor.
+            */
+            void setBallAccelerationFactor(float ballaccfactor)
+                { this->ballaccfactor_ = ballaccfactor; }
+            /**
+            @brief Get the ball's acceleration factor
+            @return Returns the ball's acceleration factor.
+            */
+            float getBallAccelerationFactor() const
+                { return this->ballaccfactor_; }
+
+            /**
+            @brief Set the speed of the bats.
+            @param batspeed The speed of the bats.
+            */
+            void setBatSpeed(float batspeed)
+                { this->batspeed_ = batspeed; }
+            /**
+            @brief Get the speed of the bats.
+            @return Returns the speed of the bats.
+            */
+            float getBatSpeed() const
+                { return this->batspeed_; }
+
+            /**
+            @brief Set the length of the bats.
+            @param batlength The length of the bats (in z-direction) as a percentage of the height of the playing field.
+            */
+            void setBatLength(float batlength)
+                { this->batlength_ = batlength; }
+            /**
+            @brief Get the length of the bats.
+            @return Returns the length of the bats (in z-direction) as a percentage of the height of the playing field.
+            */
+            float getBatLength() const
+                { return this->batlength_; }
+
+        private:
+            void checkGametype(); //!< Checks whether the gametype is Pong and if it is, sets its centerpoint.
+
+            std::string balltemplate_; //!< The template for the ball.
+            std::string battemplate_; //!< The template for the bats.
+
+            float ballspeed_; //!< The speed of then ball.
+            float ballaccfactor_; //!< The acceleration factor of the ball.
+            float batspeed_; //!< The speed of the bat.
+            float batlength_; //!< The length of the bat (in z-direction) as a percentage of the height of the playing field.
+
+            float width_; //!< The height of the playing field.
+            float height_; //!< The width of the playing field.
+    };
+}
+
+#endif /* _PongCenterpoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongPrereqs.h	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the pong module
+*/
+
+#ifndef _PongPrereqs_H__
+#define _PongPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(PONG_STATIC_BUILD)
+#  ifdef PONG_SHARED_BUILD
+#    define _PongExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _PongExport
+#    else
+#      define _PongExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _PongPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _PongExport  __attribute__ ((visibility("default")))
+#  define _PongPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _PongExport
+#  define _PongPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Pong;
+    class PongAI;
+    class PongBall;
+    class PongBat;
+    class PongBot;
+    class PongCenterpoint;
+    class PongScore;
+}
+
+#endif /* _PongPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongScore.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongScore.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongScore.cc	(revision 11817)
@@ -0,0 +1,176 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongScore.cc
+    @brief Implementation of the PongScore class.
+*/
+
+#include "PongScore.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+
+#include "infos/PlayerInfo.h"
+
+#include "Pong.h"
+#include "sound/WorldSound.h" /////////////////////////////
+
+namespace orxonox
+{
+    RegisterClass(PongScore);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    PongScore::PongScore(Context* context) : OverlayText(context)
+    {
+        RegisterObject(PongScore);
+
+        this->owner_ = nullptr;
+
+        this->bShowName_ = false;
+        this->bShowScore_ = false;
+        this->bShowLeftPlayer_ = false;
+        this->bShowRightPlayer_ = false;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    PongScore::~PongScore()
+    {
+    }
+
+    /**
+    @brief
+        Method to create a PongScore through XML.
+    */
+    void PongScore::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PongScore, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PongScore, "showname",        setShowName,        getShowName,        xmlelement, mode).defaultValues(false);
+        XMLPortParam(PongScore, "showscore",       setShowScore,       getShowScore,       xmlelement, mode).defaultValues(false);
+        XMLPortParam(PongScore, "showleftplayer",  setShowLeftPlayer,  getShowLeftPlayer,  xmlelement, mode).defaultValues(false);
+        XMLPortParam(PongScore, "showrightplayer", setShowRightPlayer, getShowRightPlayer, xmlelement, mode).defaultValues(false);
+    }
+
+    /**
+    @brief
+        Is called each tick.
+        Creates and sets the caption to be displayed by the PongScore.
+    @param dt
+        The time that has elapsed since the last tick.
+    */
+    void PongScore::tick(float dt)
+    {
+        SUPER(PongScore, tick, dt);
+
+        // If the owner is set. The owner being a Pong game.
+        if (this->owner_ != nullptr)
+        {
+            if (!this->owner_->hasEnded())
+            {
+                // Get the two players.
+                player1_ = this->owner_->getLeftPlayer();
+                player2_ = this->owner_->getRightPlayer();
+            }
+
+            std::string name1;
+            std::string name2;
+
+            std::string score1("0");
+            std::string score2("0");
+
+            // Save the name and score of each player as a string.
+            if (player1_ != nullptr)
+            {
+                name1 = player1_->getName();
+                score1 = multi_cast<std::string>(this->owner_->getScore(player1_));
+            }
+            if (player2_ != nullptr)
+            {
+                name2 = player2_->getName();
+                score2 = multi_cast<std::string>(this->owner_->getScore(player2_));
+            }
+
+            // Assemble the strings, depending on what should all be displayed.
+            std::string output1;
+            if (this->bShowLeftPlayer_)
+            {
+                if (this->bShowName_ && this->bShowScore_ && player1_ != nullptr)
+                    output1 = name1 + " - " + score1;
+                else if (this->bShowScore_)
+                    output1 = score1;
+                else if (this->bShowName_)
+                    output1 = name1;
+            }
+
+            std::string output2;
+            if (this->bShowRightPlayer_)
+            {
+                if (this->bShowName_ && this->bShowScore_ && player2_ != nullptr)
+                    output2 = score2 + " - " + name2;
+                else if (this->bShowScore_)
+                    output2 = score2;
+                else if (this->bShowName_)
+                    output2 = name2;
+            }
+
+            std::string output("PONG");
+            if (this->bShowName_ || this->bShowScore_)
+            {
+                if (this->bShowLeftPlayer_ && this->bShowRightPlayer_)
+                    output = output1 + ':' + output2;
+                else if (this->bShowLeftPlayer_ || this->bShowRightPlayer_)
+                    output = output1 + output2;
+            }
+
+            this->setCaption(output);
+        }
+    }
+
+    /**
+    @brief
+        Is called when the owner changes.
+        Sets the owner to nullptr, if it is not a pointer to a Pong game.
+    */
+    void PongScore::changedOwner()
+    {
+        SUPER(PongScore, changedOwner);
+
+        if (this->getOwner() != nullptr && this->getOwner()->getGametype())
+            this->owner_ = orxonox_cast<Pong*>(this->getOwner()->getGametype());
+        else
+            this->owner_ = nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/pong/PongScore.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/pong/PongScore.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/pong/PongScore.h	(revision 11817)
@@ -0,0 +1,130 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PongScore.h
+    @brief Declaration of the PongScore class.
+    @ingroup Pong
+*/
+
+#ifndef _PongScore_H__
+#define _PongScore_H__
+
+#include "pong/PongPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The PongScore class displays the score for a game of @ref orxonox::Pong "Pong".
+
+    @author
+        Fabian 'x3n' Landau
+
+    @ingroup Pong
+    */
+    class _PongExport PongScore : public OverlayText, public Tickable
+    {
+        public:
+            PongScore(Context* context);
+            virtual ~PongScore();
+
+            virtual void tick(float dt) override; //!< Creates and sets the caption to be displayed by the PongScore.
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override; //!< Is called when the owner changes.
+
+            /**
+            @brief Set whether the PongScore displays the players' names.
+            @param value If true the players' names are displayed.
+            */
+            inline void setShowName(bool value)
+                { this->bShowName_ = value; }
+            /**
+            @brief Get whether the PongScore displays the players' names.
+            @return Returns true if the players' names are displayed, false otherwise.
+            */
+            inline bool getShowName() const
+                { return this->bShowName_; }
+
+            /**
+            @brief Set whether the PongScore displays the players' scores.
+            @param value If true the players' scores are displayed.
+            */
+            inline void setShowScore(bool value)
+                { this->bShowScore_ = value; }
+            /**
+            @brief Get whether the PongScore displays the players' scores.
+            @return Returns true if the players' scores are displayed, false otherwise.
+            */
+            inline bool getShowScore() const
+                { return this->bShowScore_; }
+
+            /**
+            @brief Set whether the PongScore displays the left player.
+            @param value If true the left player is displayed.
+            */
+            inline void setShowLeftPlayer(bool value)
+                { this->bShowLeftPlayer_ = value; }
+            /**
+            @brief Get whether the PongScore displays the left player.
+            @return Returns true if the left player is displayed, false otherwise.
+            */
+            inline bool getShowLeftPlayer() const
+                { return this->bShowLeftPlayer_; }
+
+            /**
+            @brief Set whether the PongScore displays the right player.
+            @param value If true the right player is displayed.
+            */
+            inline void setShowRightPlayer(bool value)
+                { this->bShowRightPlayer_ = value; }
+            /**
+            @brief Get whether the PongScore displays the right player.
+            @return Returns true if the right player is displayed, false otherwise.
+            */
+            inline bool getShowRightPlayer() const
+                { return this->bShowRightPlayer_; }
+
+        private:
+            Pong* owner_; //!< The Pong game that owns this PongScore.
+            bool bShowName_; //!< Whether the names of the players are shown.
+            bool bShowScore_; //!< Whether the score of the players is shown.
+            bool bShowLeftPlayer_; //!< Whether the left player is shown.
+            bool bShowRightPlayer_; //!< Whether the right player is shown.
+            WeakPtr<PlayerInfo> player1_; //!< Store information about left player permanently.
+            WeakPtr<PlayerInfo> player2_; //!< Same for the right player. To end the game properly.
+            WorldSound* scoreSound_;
+
+    };
+}
+#endif /* _PongScore_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/portals/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,16 @@
+SET_SOURCE_FILES(PORTALS_SRC_FILES
+  PortalEndPoint.cc
+  PortalLink.cc
+)
+
+ORXONOX_ADD_LIBRARY(portals
+  MODULE
+  FIND_HEADER_FILES
+  TOLUA_FILES
+  PCH_FILE
+    PortalsPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+    objects
+  SOURCE_FILES ${PORTALS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/portals/PortalEndPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/PortalEndPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/PortalEndPoint.cc	(revision 11817)
@@ -0,0 +1,182 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Andreas Büchel
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PortalEndPoint.h"
+#include "portals/PortalLink.h"
+
+#include <ctime>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/MobileEntity.h"
+#include "objects/triggers/MultiTriggerContainer.h"
+
+#include "sound/WorldSound.h"
+
+namespace orxonox
+{
+    RegisterClass(PortalEndPoint);
+
+    /*static*/ const std::string PortalEndPoint::EVENTFUNCTIONNAME = "execute";
+
+    std::map<unsigned int, PortalEndPoint *> PortalEndPoint::idMap_s;
+
+    PortalEndPoint::PortalEndPoint(Context* context) : StaticEntity(context), RadarViewable(this, static_cast<WorldEntity*>(this)), id_(0), trigger_(nullptr), reenterDelay_(0)
+    {
+        RegisterObject(PortalEndPoint);
+
+        this->trigger_ = new DistanceMultiTrigger(this->getContext());
+        this->trigger_->setName("portal");
+        this->attach(this->trigger_);
+
+        this->setRadarObjectColour(ColourValue::White);
+        this->setRadarObjectShape(RadarViewable::Shape::Dot);
+        this->setRadarVisibility(true);
+        if( GameMode::isMaster() )
+        {
+            this->portalSound_ = new WorldSound(this->getContext());
+            this->portalSound_->setLooping(false);
+            this->attach(this->portalSound_);
+            this->portalSound_->setSource("sounds/Portal_1_cut.ogg");
+            this->portalSound_->setVolume(1.0f);
+        }
+    }
+
+    PortalEndPoint::~PortalEndPoint()
+    {
+        if (this->isInitialized()) {
+            if (this->trigger_ != nullptr)
+                this->trigger_->destroy();
+
+            if (this->portalSound_ != nullptr)
+                this->portalSound_->destroy();
+        }
+    }
+
+    void PortalEndPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PortalEndPoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PortalEndPoint, "id", setID, getID, xmlelement, mode);
+        XMLPortParam(PortalEndPoint, "design", setTemplate, getTemplate, xmlelement, mode);
+        XMLPortParam(PortalEndPoint, "reenterDelay", setReenterDelay, getReenterDelay, xmlelement, mode);
+        XMLPortParamExtern(PortalEndPoint, DistanceMultiTrigger, this->trigger_, "distance", setDistance, getDistance, xmlelement, mode);
+        XMLPortParamLoadOnly(PortalEndPoint, "target", setTarget, xmlelement, mode).defaultValues("Pawn");
+
+        // Add the DistanceMultiTrigger as event source.
+        this->addEventSource(this->trigger_, EVENTFUNCTIONNAME);
+
+        if(mode == XMLPort::LoadObject)
+        {
+            PortalEndPoint::idMap_s[this->id_] = this;
+        }
+    }
+
+    void PortalEndPoint::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PortalEndPoint, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventSink(PortalEndPoint, BaseObject, EVENTFUNCTIONNAME, execute, xmlelement, mode);
+    }
+
+    bool PortalEndPoint::execute(bool bTriggered, BaseObject* trigger)
+    {
+        if(!this->isActive())
+            return true;
+
+        MultiTriggerContainer * cont = orxonox_cast<MultiTriggerContainer *>(trigger);
+        if(cont == nullptr)
+            return true;
+
+        DistanceMultiTrigger * originatingTrigger = orxonox_cast<DistanceMultiTrigger *>(cont->getOriginator());
+        if(originatingTrigger == nullptr)
+        {
+            return true;
+        }
+
+        MobileEntity * entity = orxonox_cast<MobileEntity *>(cont->getData());
+        if(entity == nullptr)
+            return true;
+
+        if(bTriggered)
+        {
+            if(this->letsEnter(entity))  // only enter the portal if not just (this very moment) jumped out of it, or if the reenterDelay expired
+            {
+                PortalLink::use(entity, this);
+            }
+        }
+        else
+        {
+            this->recentlyJumpedOut_.erase(entity);
+        }
+
+        return true;
+    }
+
+    void PortalEndPoint::changedActivity(void)
+    {
+        SUPER(PortalEndPoint, changedActivity);
+
+        this->setRadarVisibility(this->isActive());
+    }
+
+    bool PortalEndPoint::letsEnter(MobileEntity* entity)
+    {
+        // not allowed to enter if reenterDelay hasn't expired yet
+        std::map<MobileEntity *, time_t>::const_iterator time = this->jumpOutTimes_.find(entity);
+        if(time != this->jumpOutTimes_.end() && std::difftime(std::time(0),time->second) < this->reenterDelay_)
+            return false;
+
+        // not allowed to enter if jumped out of this portal and not left its activation radius yet
+        std::set<MobileEntity *>::const_iterator recent = this->recentlyJumpedOut_.find(entity);
+        if(recent != this->recentlyJumpedOut_.end())
+            return false;
+        
+        return true;
+    }
+
+    void PortalEndPoint::jumpOut(MobileEntity* entity)
+    {
+        this->jumpOutTimes_[entity] = std::time(0);
+        this->recentlyJumpedOut_.insert(entity);
+
+        // adjust
+        entity->setPosition(this->getWorldPosition());
+        entity->rotate(this->getWorldOrientation());
+        entity->setVelocity(this->getWorldOrientation() * entity->getVelocity());
+        //play Sound
+        if (this->portalSound_)
+        {
+            if (this->portalSound_->isPlaying())
+                this->portalSound_->stop();
+            this->portalSound_->play();
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/portals/PortalEndPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/PortalEndPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/PortalEndPoint.h	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Andreas Büchel
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+ *  @file PortalEndPoint.h
+ *  @brief Declaration of the PortalEndPoint class.
+ *  @ingroup Portals
+ */
+
+#ifndef _PortalEndPoint_H__
+#define _PortalEndPoint_H__
+
+#include "portals/PortalsPrereqs.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "core/EventIncludes.h"
+
+#include "worldentities/StaticEntity.h"
+#include "interfaces/RadarViewable.h"
+#include "objects/triggers/DistanceMultiTrigger.h"
+
+namespace orxonox
+{
+    /**
+     @brief
+     A PortalEndPoint serves as portal entrance and/or exit.
+
+     @ingroup Portals
+     */
+
+    class _PortalsExport PortalEndPoint : public StaticEntity, public RadarViewable
+    {
+        public:
+            PortalEndPoint(Context* context);
+            virtual ~PortalEndPoint();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedActivity(void) override;
+
+            inline void setTarget(const std::string & target)                 //!< add types which are allowed to activate the PortalEndPoint
+                { this->trigger_->addTarget(target); }
+
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+            static std::map<unsigned int, PortalEndPoint *> idMap_s; //!< Maps the id of each PortalEndPoint to a pointer to that PortalEndPoint
+            inline void setReenterDelay(unsigned int seconds)
+                { this->reenterDelay_ = seconds; }
+            inline unsigned int getReenterDelay()
+                { return this->reenterDelay_; }
+            inline void setID(unsigned int id)
+                { this->id_ = id; }
+
+            inline unsigned int getID() const
+                { return this->id_; }
+
+            /// \brief Set templateName_ (the name of the design Template) and add that Template to this Object
+            inline void setTemplate(const std::string & name)
+                { this->templateName_ = name; this->addTemplate(name); }
+
+            /// \brief Get the name of the attached design template
+            inline const std::string & getTemplate()
+                { return this->templateName_; }
+
+            /*! \brief This function is called each time the DistanceMultiTrigger of this PortalEndPoint changed
+                \param bTriggered true if the trigger was triggered on, false if the trigger has switched to off
+                \param trigger the MultiTriggerContainer containing the triggering BaseObject (and trigger_ the portal's MultiDistanceTrigger which we already know)
+            */
+            bool execute(bool bTriggered, BaseObject* trigger);
+
+            /*! \brief Let an Entity jump out of this portal no matter where it was before
+             * \param entity The Entity which should jump out of this portal */
+            void jumpOut(MobileEntity * entity);
+
+            /** \brief Tells wether a certain Entity is allowed to enter the PortalEndPoint?
+                @return @c true if the entity not just came out of this portal and the reenterDelay has expired for it, @c false otherwise
+            */
+            bool letsEnter(MobileEntity* entity);
+        protected:
+
+        private:
+            static const std::string EVENTFUNCTIONNAME; //!< = "execute"
+
+            unsigned int id_;            //!< the hopefully (depends on the writer of the levelfile) unique id, which is used to establish links between PortalEndPoints
+            DistanceMultiTrigger * trigger_;      //!< the DistanceMultiTrigger which notices near entities of the defined type
+            std::string templateName_;            //!< The name of the design template used for this endpoint
+
+            int reenterDelay_;
+            std::map<MobileEntity *, time_t> jumpOutTimes_;   //!< Stores the time at which a certain MobileEntity @ref jumpOut "jumped out" of this PortalEndPoint
+            std::set<MobileEntity *> recentlyJumpedOut_;   //!< Stores the entities witch recently jumped out of this PortalEndPoint and haven't left the activation radius yet. This is needed in order to prevent them from beeing pulled into the PortalEndPoint they have just come out of.
+
+            WorldSound* portalSound_;
+    };
+
+}
+
+#endif /* _Portals_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/portals/PortalLink.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/PortalLink.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/PortalLink.cc	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Andreas Büchel
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PortalLink.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "worldentities/MobileEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(PortalLink);
+
+    std::map<PortalEndPoint *, PortalEndPoint *> PortalLink::links_s;
+
+    PortalLink::PortalLink(Context* context) : BaseObject(context), fromID_(0), toID_(0), from_(nullptr), to_(nullptr)
+    {
+        RegisterObject(PortalLink);
+    }
+
+    PortalLink::~PortalLink()
+    {
+
+    }
+
+    void PortalLink::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PortalLink, XMLPort, xmlelement, mode);
+        XMLPortParam(PortalLink, "fromID", setFromID, getFromID, xmlelement, mode);
+        XMLPortParam(PortalLink, "toID", setToID, getToID, xmlelement, mode);
+
+        // Beware: This means, that the PortalEndPoints must exist before the PortalLink is created.
+        if(mode == XMLPort::LoadObject)
+        {
+            PortalEndPoint * from = PortalEndPoint::idMap_s[this->fromID_];
+            PortalEndPoint * to   = PortalEndPoint::idMap_s[this->toID_];
+            PortalLink::links_s[from] = to;
+        }
+    }
+
+    void PortalLink::use(MobileEntity* entity, PortalEndPoint * entrance)
+    {
+        if(entrance == nullptr)
+            return;
+
+        std::map<PortalEndPoint *, PortalEndPoint *>::iterator endpoints = PortalLink::links_s.find(entrance);
+        if(endpoints == PortalLink::links_s.end())  // entrance has no corresponding exit
+            return;
+
+        endpoints->second->jumpOut(entity);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/portals/PortalLink.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/PortalLink.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/PortalLink.h	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Andreas Büchel
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PortalLink.h
+    @brief Declaration of the PortalLink class
+    @ingroup Portals
+ */
+
+#ifndef _PortalLink_H__
+#define _PortalLink_H__
+
+#include "portals/PortalsPrereqs.h"
+
+#include <map>
+
+#include "PortalEndPoint.h"
+
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    /**
+        @brief
+            A PortalLink represents the connection between two @ref orxonox::PortalEndPoint "PortalEndPoints"
+        @ingroup Portals
+     */
+    class _PortalsExport PortalLink : public BaseObject
+    {
+        public:
+            PortalLink(Context* context);
+            virtual ~PortalLink();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setFromID(unsigned int from)    //!< set the ID of the PortalEndPoint which should act as the entrance of this link
+                { this->fromID_ = from; }
+            inline unsigned int getFromID(unsigned int) const
+                { return this->fromID_; }
+            inline void setToID(unsigned int to)     //!< set the ID of the PortalEndPoint which should act as the exit of this link
+                { this->toID_ = to; }
+            inline unsigned int getToID(unsigned int) const
+                { return this->toID_; }
+            /*! \brief Let an entity enter a certain PortalEndPoint
+                \param entity pointer to the entity which is entering a PortalEndPoint
+                \param entrance pointer to the PortalEndPoint to enter
+             */
+            static void use(MobileEntity * entity, PortalEndPoint * entrance);   //!< let entity enter the PortalEndPoint pointed to by entrance
+        protected:
+        private:
+            static std::map<PortalEndPoint *, PortalEndPoint *> links_s;   //!< maps entrances to exits
+            unsigned int fromID_;   //!< id of the entrance of this Link
+            unsigned int toID_;   //!< id of the exit of this Link
+            PortalEndPoint* from_;   //!< pointer to this Link's entrance
+            PortalEndPoint* to_;   //!< pointer to this Link's exit
+    };
+}
+
+#endif /* _Portals_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/portals/PortalsPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/PortalsPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/PortalsPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btTransform.h>
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/portals/PortalsPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/portals/PortalsPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/portals/PortalsPrereqs.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _PortalsPrereqs_H__
+#define _PortalsPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(PORTALS_STATIC_BUILD)
+#  ifdef PORTALS_SHARED_BUILD
+#    define _PortalsExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _PortalsExport
+#    else
+#      define _PortalsExport __declspec(dllimport)
+#    endif
+#  endif
+#elif defined ( ORXONOX_GCC_VISIBILITY )
+#  define _PortalsExport  __attribute__ ((visibility("default")))
+#else
+#  define _PortalsExport
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+
+    class PortalEndPoint;
+    class PortalLink;
+
+}
+
+#endif /* _PortalsPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,29 @@
+SET_SOURCE_FILES(QUESTSYSTEM_SRC_FILES
+  GlobalQuest.cc
+  LocalQuest.cc
+  Quest.cc
+  QuestDescription.cc
+  QuestEffect.cc
+  QuestEffectBeacon.cc
+  QuestHint.cc
+  QuestItem.cc
+  QuestListener.cc
+  QuestManager.cc
+)
+
+ADD_SUBDIRECTORY(effects)
+
+ORXONOX_ADD_LIBRARY(questsystem
+  MODULE
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    QuestManager.h
+    QuestDescription.h
+    Quest.h
+    QuestHint.h
+  PCH_FILE
+    QuestsystemPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+  SOURCE_FILES ${QUESTSYSTEM_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/GlobalQuest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/GlobalQuest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/GlobalQuest.cc	(revision 11817)
@@ -0,0 +1,254 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file GlobalQuest.cc
+    @brief Implementation of the GlobalQuest class.
+*/
+
+#include "GlobalQuest.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "QuestEffect.h"
+
+namespace orxonox
+{
+    RegisterClass(GlobalQuest);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    GlobalQuest::GlobalQuest(Context* context) : Quest(context)
+    {
+        RegisterObject(GlobalQuest);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    GlobalQuest::~GlobalQuest()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a GlobalQuest object through XML.
+    */
+    void GlobalQuest::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(GlobalQuest, XMLPort, xmlelement, mode);
+
+        XMLPortObject(GlobalQuest, QuestEffect, "reward-effects", addRewardEffect, getRewardEffects, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New GlobalQuest {" << this->getId() << "} created." << endl;
+    }
+
+    /**
+    @brief
+        Fails the Quest for all players.
+        Invokes the fail QuestEffects on all the players possessing this Quest.
+    @param player
+        The player failing it.
+    @return
+        Returns true if the Quest could be failed, false if not.
+    */
+    bool GlobalQuest::fail(PlayerInfo* player)
+    {
+        if(!this->isFailable(player)) // Check whether the Quest can be failed.
+        {
+            orxout(verbose, context::quests) << "A non-completable quest was trying to be failed." << endl;
+            return false;
+        }
+
+        Quest::fail(player);
+
+        // Iterate through all players possessing this Quest.
+        for(PlayerInfo* questPlayer : players_)
+            QuestEffect::invokeEffects(questPlayer, this->getFailEffectList());
+
+        return true;
+    }
+
+    /**
+    @brief
+        Completes the Quest for all players.
+        Invokes the complete QuestEffects on all the players possessing this Quest.
+        Invokes the reward QuestEffects on the player completing the Quest.
+    @param player
+        The player completing it.
+    @return
+        Returns true if the Quest could be completed, false if not.
+    */
+    bool GlobalQuest::complete(PlayerInfo* player)
+    {
+        if(!this->isCompletable(player)) // Check whether the Quest can be completed.
+        {
+            orxout(verbose, context::quests) << "A non-completable quest was trying to be completed." << endl;
+            return false;
+        }
+
+        // Iterate through all players possessing the Quest.
+        for(PlayerInfo* questPlayer : players_)
+            QuestEffect::invokeEffects(questPlayer, this->getCompleteEffectList());
+
+        Quest::complete(player);
+
+        QuestEffect::invokeEffects(player, this->rewards_); // Invoke reward QuestEffects on the player completing the Quest.
+        return true;
+    }
+
+    /**
+    @brief
+        Checks whether the Quest can be started.
+    @param player
+        The player for whom is to be checked.
+    @return
+        Returns true if the quest can be started, false if not.
+    */
+    bool GlobalQuest::isStartable(const PlayerInfo* player) const
+    {
+        if(!(this->getParentQuest() == nullptr || this->getParentQuest()->isActive(player)))
+            return false;
+
+        return (this->isInactive(player) && !(this->status_ == QuestStatus::Completed || this->status_ == QuestStatus::Failed));
+    }
+
+    /**
+    @brief
+        Checks whether the Quest can be failed.
+    @param player
+        The player for whom is to be checked.
+    @return
+        Returns true if the Quest can be failed, false if not.
+    */
+    bool GlobalQuest::isFailable(const PlayerInfo* player) const
+    {
+        return this->isActive(player);
+
+    }
+
+    /**
+    @brief
+        Checks whether the Quest can be completed.
+    @param player
+        The player for whom is to be checked.
+    @return
+        Returns true if the Quest can be completed, false if not.
+    */
+    bool GlobalQuest::isCompletable(const PlayerInfo* player) const
+    {
+        return this->isActive(player);
+    }
+
+    /**
+    @brief
+        Returns the status of the Quest for a specific player.
+    @param player
+        The player.
+    */
+    QuestStatus GlobalQuest::getStatus(const PlayerInfo* player) const
+    {
+        assert(player);
+
+        // Find the player.
+        std::set<PlayerInfo*>::const_iterator it = this->players_.find((PlayerInfo*)(void*)player);
+        if (it != this->players_.end()) // If the player was found.
+            return this->status_;
+
+        return QuestStatus::Inactive;
+    }
+
+    /**
+    @brief
+        Sets the status for a specific player.
+        But be careful wit this one, the status will just be set without checking for its validity. You have to know what you're doing.
+    @param player
+        The player.
+    @param status
+        The status to be set.
+    @return
+        Returns false if player is nullptr.
+    */
+    bool GlobalQuest::setStatus(PlayerInfo* player, const QuestStatus & status)
+    {
+        assert(player);
+
+        // Find the player.
+        std::set<PlayerInfo*>::const_iterator it = this->players_.find(player);
+        if (it == this->players_.end()) // Player is not yet in the list.
+            this->players_.insert(player); // Add the player to the set.
+
+        this->status_ = status; // Set the status, which is global, remember...?
+        return true;
+    }
+
+    /**
+    @brief
+        Adds a reward QuestEffect to the list of reward QuestEffects.
+    @param effect
+        The QuestEffect to be added.
+    @return
+        Returns true if successful.
+    */
+    bool GlobalQuest::addRewardEffect(QuestEffect* effect)
+    {
+        assert(effect);
+
+        this->rewards_.push_back(effect); // Add the QuestEffect to the list.
+
+        orxout(verbose, context::quests) << "Reward effect was added to Quest {" << this->getId() << "}." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Returns the reward QuestEffect at the given index.
+    @param index
+        The index.
+    @return
+        Returns the QuestEffect at the given index.
+    */
+    const QuestEffect* GlobalQuest::getRewardEffects(unsigned int index) const
+    {
+        int i = index;
+        for (QuestEffect* reward : this->rewards_)
+        {
+            if(i == 0)
+               return reward;
+
+            i--;
+        }
+        return nullptr;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/GlobalQuest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/GlobalQuest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/GlobalQuest.h	(revision 11817)
@@ -0,0 +1,121 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file GlobalQuest.h
+    @brief Definition of the GlobalQuest class.
+    @ingroup Questsystem
+*/
+
+#ifndef _GlobalQuest_H__
+#define _GlobalQuest_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <list>
+#include <set>
+#include "Quest.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        GlobalQuests are @ref orxonox::Quest "Quests", that have the same status for all players.
+        This means, that when a player successfully completes a GlobalQuest, it is completed for all players that have it.
+
+        Creating a GlobalQuest through XML goes as follows:
+        @code
+        <GlobalQuest id="questId">
+            <QuestDescription title="Title" description="Description." /> //The description of the quest.
+            <subquests>
+                <Quest id ="questId1" /> //A list of n subquest, be aware, each of the <Quest /> tags must have a description and so on and so forth as well.
+                ...
+                <Quest id="questIdn" />
+            </subquests>
+            <hints>
+                <QuestHint id="hintId1" /> //A list of n QuestHints, see QuestHint for the full XML representation of those.
+                ...
+                <QuestHint id="hintIdn" />
+            </hints>
+            <fail-effects>
+                <QuestEffect /> //A list of QuestEffects, invoked on all players possessing this quest, when the Quest is failed, see QuestEffect for the full XML representation.
+                ...
+                <QuestEffect />
+            </fail-effects>
+            <complete-effects>
+                <QuestEffect /> //A list of QuestEffects, invoked on all players possessing this quest, when the Quest is completed, see QuestEffect for the full XML representation.
+                ...
+                <QuestEffect />
+            </complete-effects>
+            <reward-effects>
+                <QuestEffect /> //A list of QuestEffects, invoked on the player completing this quest. See QuestEffect for the full XML representation.
+                ...
+                <QuestEffect />
+            </reward-effects>
+        </GlobalQuest>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport GlobalQuest : public Quest
+    {
+        public:
+            GlobalQuest(Context* context);
+            virtual ~GlobalQuest();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a GlobalQuest object through XML.
+
+            virtual bool fail(PlayerInfo* player) override; //!< Fails the Quest.
+            virtual bool complete(PlayerInfo* player) override; //!< Completes the Quest.
+
+        protected:
+            virtual bool isStartable(const PlayerInfo* player) const override; //!< Checks whether the Quest can be started.
+            virtual bool isFailable(const PlayerInfo* player) const override; //!< Checks whether the Quest can be failed.
+            virtual bool isCompletable(const PlayerInfo* player) const override; //!< Checks whether the Quest can be completed.
+
+            virtual QuestStatus getStatus(const PlayerInfo* player) const override; //!< Returns the status of the Quest for a specific player.
+
+            virtual bool setStatus(PlayerInfo* player, const QuestStatus & status) override; //!< Sets the status for a specific player.
+
+        private:
+            std::set<PlayerInfo*> players_; //!< The set of players which possess this Quest.
+            QuestStatus status_; //!< The status of this Quest.
+            std::list<QuestEffect*> rewards_; //!< Reward QuestEffects only invoked on the player completing the Quest.
+
+            bool addRewardEffect(QuestEffect* effect); //!< Adds a reward QuestEffect to the list of reward QuestEffects.
+            const QuestEffect* getRewardEffects(unsigned int index) const; //!< Returns the reward QuestEffect at the given index.
+
+    };
+
+}
+
+#endif /* _GlobalQuest_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/LocalQuest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/LocalQuest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/LocalQuest.cc	(revision 11817)
@@ -0,0 +1,200 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LocalQuest.cc
+    @brief Implementation of the LocalQuest class.
+*/
+
+#include "LocalQuest.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "QuestEffect.h"
+
+namespace orxonox
+{
+    RegisterClass(LocalQuest);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    LocalQuest::LocalQuest(Context* context) : Quest(context)
+    {
+        RegisterObject(LocalQuest);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    LocalQuest::~LocalQuest()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a LocalQuest object through XML.
+    */
+    void LocalQuest::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(LocalQuest, XMLPort, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New LocalQuest {" << this->getId() << "} created." << endl;
+    }
+
+    /**
+    @brief
+        Fails the Quest for a given player.
+        Invokes all the failEffects on the player.
+    @param player
+        The player.
+    @return
+        Returns true if the Quest could be failed, false if not.
+    */
+    bool LocalQuest::fail(PlayerInfo* player)
+    {
+        if(!this->isFailable(player)) // Checks whether the quest can be failed.
+        {
+            orxout(verbose, context::quests) << "A non-failable quest was trying to be failed." << endl;
+            return false;
+        }
+
+        Quest::fail(player);
+
+        QuestEffect::invokeEffects(player, this->getFailEffectList()); // Invoke the failEffects.
+        return true;
+    }
+
+    /**
+    @brief
+        Completes the Quest for a given player.
+    Invokes all the complete QuestEffects on the player.
+    @param player
+        The player.
+    @return
+        Returns true if the Quest could be completed, false if not.
+    */
+    bool LocalQuest::complete(PlayerInfo* player)
+    {
+        if(!this->isCompletable(player)) // Checks whether the Quest can be completed.
+        {
+            orxout(verbose, context::quests) << "A non-completable quest was trying to be completed." << endl;
+            return false;
+        }
+
+        Quest::complete(player);
+
+        QuestEffect::invokeEffects(player, this->getCompleteEffectList()); // Invoke the complete QuestEffects.
+        return true;
+    }
+
+    /**
+    @brief
+        Checks whether the Quest can be started.
+    @param player
+        The player for whom is to be checked.
+    @return
+        Returns true if the Quest can be started, false if not.
+    */
+    bool LocalQuest::isStartable(const PlayerInfo* player) const
+    {
+        if(!(this->getParentQuest() == nullptr || this->getParentQuest()->isActive(player)))
+            return false;
+
+        return this->isInactive(player);
+    }
+
+    /**
+    @brief
+        Checks whether the Quest can be failed.
+    @param player
+        The player for whom is to be checked.
+    @return
+        Returns true if the Quest can be failed, false if not.
+    */
+    bool LocalQuest::isFailable(const PlayerInfo* player) const
+    {
+        return this->isActive(player);
+    }
+
+    /**
+    @brief
+        Checks whether the Quest can be completed.
+    @param player
+        The player for whom is to be checked.
+    @return
+        Returns true if the Quest can be completed, false if not.
+    */
+    bool LocalQuest::isCompletable(const PlayerInfo* player) const
+    {
+        return this->isActive(player);
+    }
+
+    /**
+    @brief
+        Returns the status of the Quest for a specific player.
+    @param player
+        The player.
+    @return
+        Returns the status of the Quest for the input player.
+    */
+    QuestStatus LocalQuest::getStatus(const PlayerInfo* player) const
+    {
+        assert(player);
+
+        std::map<const PlayerInfo*, QuestStatus>::const_iterator it = this->playerStatus_.find(player);
+        if (it != this->playerStatus_.end()) // If there is a player in the map.
+            return it->second;
+
+        return QuestStatus::Inactive; // If the player is not yet in the map, that means the status of the quest form him is 'inactive'.
+    }
+
+    /**
+    @brief
+        Sets the status for a specific player.
+        But be careful wit this one, the status will just be set without checking for its validity. You have to know what you're doing. Really!
+    @param player
+        The player the status should be set for.
+    @param status
+        The status to be set.
+    @return
+        Returns false if player is nullptr.
+    */
+    bool LocalQuest::setStatus(PlayerInfo* player, const QuestStatus & status)
+    {
+        assert(player);
+
+        this->playerStatus_[player] = status;
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/LocalQuest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/LocalQuest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/LocalQuest.h	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LocalQuest.h
+    @brief Definition of the LocalQuest class.
+    @ingroup Questsystem
+*/
+
+#ifndef _LocalQuest_H__
+#define _LocalQuest_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <map>
+#include "Quest.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Handles @ref orxonox::Quest "Quests" which have different states for different players.
+        LocalQuests have (as opposed to @ref orxonox::GlobalQuest "GlobalQuests") a different state for each player, that means if for one player the status of the @ref orxonox::Quest "Quest" changes it does not for all the other players which also possess this quest.
+
+        Creating a LocalQuest through XML goes as follows:
+        @code
+        <LocalQuest id="questId">
+            <QuestDescription title="Title" description="Description." /> //The description of the quest.
+            <subquests>
+                <Quest id ="questId1" /> //A list of n subquest, be aware, each of the <Quest /> tags must have a description and so on and so forth as well.
+                ...
+                <Quest id="questIdn" />
+                </subquests>
+                <hints>
+                <QuestHint id="hintId1" /> //A list of n QuestHints, see QuestHint for the full XML representation of those.
+                ...
+                <QuestHint id="hintIdn" />
+                </hints>
+            <fail-effects>
+                <QuestEffect /> //A list of QuestEffects, invoked when the Quest is failed, see QuestEffect for the full XML representation.
+                ...
+                <QuestEffect />
+            </fail-effects>
+            <complete-effects>
+                <QuestEffect /> //A list of QuestEffects, invoked when the Quest is completed, see QuestEffect for the full XML representation.
+                ...
+                <QuestEffect />
+            </complete-effects>
+        </LocalQuest>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport LocalQuest : public Quest
+    {
+        public:
+            LocalQuest(Context* context);
+            virtual ~LocalQuest();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a LocalQuest object through XML.
+
+            virtual bool fail(PlayerInfo* player) override; //!< Fails the Quest.
+            virtual bool complete(PlayerInfo* player) override; //!< Completes the Quest.
+
+        protected:
+            virtual bool isStartable(const PlayerInfo* player) const override; //!< Checks whether the Quest can be started.
+            virtual bool isFailable(const PlayerInfo* player) const override; //!< Checks whether the Quest can be failed.
+            virtual bool isCompletable(const PlayerInfo* player) const override; //!< Checks whether the Quest can be completed.
+
+            virtual QuestStatus getStatus(const PlayerInfo* player) const override; //!< Returns the status of the Quest for a specific player.
+            virtual bool setStatus(PlayerInfo* player, const QuestStatus & status) override; //!< Sets the status for a specific player.
+
+        private:
+            std::map<const PlayerInfo*, QuestStatus> playerStatus_; //!< List of the status for each player, with the Player-pointer as key.
+
+    };
+
+}
+
+#endif /* _LocalQuest_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/Quest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/Quest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/Quest.cc	(revision 11817)
@@ -0,0 +1,412 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Quest.cc
+    @brief Implementation of the Quest class.
+*/
+
+#include "Quest.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "QuestDescription.h"
+#include "QuestEffect.h"
+#include "QuestHint.h"
+#include "QuestListener.h"
+#include "QuestManager.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(Quest).inheritsFrom<QuestItem>();
+
+    /**
+    @brief
+        Constructor. Registers and initializes object.
+    */
+    Quest::Quest(Context* context) : QuestItem(context)
+    {
+        RegisterObject(Quest);
+
+        this->parentQuest_ = nullptr;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    Quest::~Quest()
+    {
+        if(this->isRegistered())
+            QuestManager::getInstance().unregisterQuest(this);
+    }
+
+    /**
+    @brief
+        Method for creating a Quest object through XML.
+    */
+    void Quest::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Quest, XMLPort, xmlelement, mode);
+
+        XMLPortObject(Quest, Quest, "subquests", addSubQuest, getSubQuest, xmlelement, mode);
+        XMLPortObject(Quest, QuestHint, "hints", addHint, getHint, xmlelement, mode);
+        XMLPortObject(Quest, QuestEffect, "fail-effects", addFailEffect, getFailEffect, xmlelement, mode);
+        XMLPortObject(Quest, QuestEffect, "complete-effects", addCompleteEffect, getCompleteEffect, xmlelement, mode);
+
+        QuestManager::getInstance().registerQuest(this); // Registers the Quest with the QuestManager.
+    }
+
+    /**
+    @brief
+        Sets the parent-quest of the Quest.
+    @param quest
+        A pointer to the Quest to be set as parent-quest.
+    @return
+        Returns true if the parent-quest could be set.
+    */
+    bool Quest::setParentQuest(Quest* quest)
+    {
+        assert(quest);
+
+        this->parentQuest_ = quest;
+
+        orxout(verbose, context::quests) << "Parent Quest {" << quest->getId() << "} was added to Quest {" << this->getId() << "}." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Adds a sub-quest to the Quest.
+    @param quest
+        A pointer to the Quest to be set as sub-quest.
+    @return
+        Returns true if the sub-quest could be set.
+    */
+    bool Quest::addSubQuest(Quest* quest)
+    {
+        assert(quest);
+
+        quest->setParentQuest(this); // Sets the currentQuest (this) as parent-quest for the added sub-quest.
+        this->subQuests_.push_back(quest); // Adds the Quest to the end of the list of sub-quests.
+
+        orxout(verbose, context::quests) << "Sub Quest {" << quest->getId() << "} was added to Quest {" << this->getId() << "}." << endl;
+        return true;
+    }
+
+
+    /**
+    @brief
+        Adds a QuestHint to the list of QuestHints
+    @param hint
+        The QuestHint that should be added to the list of QuestHints.
+    @return
+        Returns true if the hint was successfully added.
+    */
+    bool Quest::addHint(QuestHint* hint)
+    {
+        assert(hint);
+
+        hint->setQuest(this); // Sets the current Quest (this) as Quest for the added QuestHint.
+        this->hints_.push_back(hint); // Adds the QuestHint to the end of the list of QuestHints.
+
+        orxout(verbose, context::quests) << "QuestHint {" << hint->getId() << "} was added to Quest {" << this->getId() << "}." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Adds an QuestEffect to the list of fail QuestEffects.
+    @param effect
+        The QuestEffect to be added.
+    @return
+        Returns true if successful.
+    */
+    bool Quest::addFailEffect(QuestEffect* effect)
+    {
+        assert(effect);
+
+        this->failEffects_.push_back(effect); // Adds the QuestEffect to the end of the list of fail QuestEffects.
+
+        orxout(verbose, context::quests) << "A FailEffect was added to Quest {" << this->getId() << "}." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Adds an QuestEffect to the list of complete QuestEffects.
+    @param effect
+        The QuestEffect to be added.
+    @return
+        Returns true if successful.
+    */
+    bool Quest::addCompleteEffect(QuestEffect* effect)
+    {
+        assert(effect);
+
+        this->completeEffects_.push_back(effect); // Adds the QuestEffect to the end of the list of complete QuestEffects.
+
+        orxout(verbose, context::quests) << "A CompleteEffect was added to Quest {" << this->getId() << "}." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Returns the sub-quest at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer to the sub-quest at the given index. nullptr if there is no element at the given index.
+    */
+    const Quest* Quest::getSubQuest(unsigned int index) const
+    {
+        int i = index;
+
+        // Iterate through all subquests.
+        for (Quest* quest : this->subQuests_)
+        {
+            if(i == 0) // We're counting down...
+               return quest;
+
+            i--;
+        }
+
+        return nullptr; // If the index is greater than the number of elements in the list.
+    }
+
+    /**
+    @brief
+        Returns the QuestHint at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer to the QuestHint at the given index. nullptr if there is no element at the given index.
+    */
+    const QuestHint* Quest::getHint(unsigned int index) const
+    {
+        int i = index;
+
+        // Iterate through all QuestHints.
+        for (QuestHint* hint : this->hints_)
+        {
+            if(i == 0) // We're counting down...
+               return hint;
+
+            i--;
+        }
+        return nullptr; // If the index is greater than the number of elements in the list.
+    }
+
+    /**
+    @brief
+        Returns the fail QuestEffect at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer to the fail QuestEffect at the given index. nullptr if there is no element at the given index.
+    */
+    const QuestEffect* Quest::getFailEffect(unsigned int index) const
+    {
+        int i = index;
+
+        // Iterate through all fail QuestEffects.
+        for (QuestEffect* effect : this->failEffects_)
+        {
+            if(i == 0) // We're counting down...
+               return effect;
+
+            i--;
+        }
+        return nullptr; // If the index is greater than the number of elements in the list.
+    }
+
+    /**
+    @brief
+        Returns the complete QuestEffect at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer to the complete QuestEffect at the given index. nullptr if there is no element at the given index.
+    */
+    const QuestEffect* Quest::getCompleteEffect(unsigned int index) const
+    {
+        int i = index;
+
+        // Iterate through all complete QuestEffects.
+        for (QuestEffect* effect : this->completeEffects_)
+        {
+            if(i == 0) // We're counting down...
+               return effect;
+
+            i--;
+        }
+        return nullptr; // If the index is greater than the number of elements in the list.
+    }
+
+    /**
+    @brief
+        Returns true if the quest status for the specific player is 'inactive'.
+    @param player
+        The player.
+    @return
+        Returns true if the quest status for the specific player is 'inactive'.
+    */
+    bool Quest::isInactive(const PlayerInfo* player) const
+    {
+        if(player == nullptr)
+            return true;
+        return this->getStatus(player) == QuestStatus::Inactive;
+    }
+
+    /**
+    @brief
+        Returns true if the quest status for the specific player is 'active'.
+    @param player
+        The player.
+    @return
+        Returns true if the quest status for the specific player is 'active'.
+    */
+    bool Quest::isActive(const PlayerInfo* player) const
+    {
+        if(player == nullptr)
+            return false;
+        return this->getStatus(player) == QuestStatus::Active;
+    }
+
+    /**
+    @brief
+        Returns true if the quest status for the specific player is 'failed'.
+    @param player
+        The player.
+    @return
+        Returns true if the quest status for the specific player is 'failed'.
+    */
+    bool Quest::isFailed(const PlayerInfo* player) const
+    {
+        if(player == nullptr)
+            return false;
+        return this->getStatus(player) == QuestStatus::Failed;
+    }
+
+    /**
+    @brief
+        Returns true if the quest status for the specific player is 'completed'.
+    @param player
+        The player.
+    @return
+        Returns true if the quest status for the specific player is 'completed'.
+    */
+    bool Quest::isCompleted(const PlayerInfo* player) const
+    {
+        if(player == nullptr)
+            return false;
+        return this->getStatus(player) == QuestStatus::Completed;
+    }
+
+    /**
+    @brief
+        Fails the Quest for an input player.
+    @param player
+        The player.
+    @return
+        Returns true if the Quest could be failed, false if not.
+    */
+    bool Quest::fail(PlayerInfo* player)
+    {
+        QuestListener::advertiseStatusChange(this->listeners_, "fail"); // Tells the QuestListeners, that the status has changed to failed.
+        this->setStatus(player, QuestStatus::Failed);
+
+        orxout(verbose, context::quests) << "Quest {" << this->getId() << "} is failed for player: " << player << " ." << endl;
+
+        this->getDescription()->sendFailQuestNotification(player);
+        return true;
+    }
+
+    /**
+    @brief
+        Completes the Quest for an input player.
+    @param player
+        The player.
+    @return
+        Returns true if the Quest could be completed, false if not.
+    */
+    bool Quest::complete(PlayerInfo* player)
+    {
+        QuestListener::advertiseStatusChange(this->listeners_, "complete"); // Tells the QuestListeners, that the status has changed to completed.
+        this->setStatus(player, QuestStatus::Completed);
+
+        orxout(verbose, context::quests) << "Quest {" << this->getId() << "} is completed for player: " << player << " ." << endl;
+
+        this->getDescription()->sendCompleteQuestNotification(player);
+        return true;
+    }
+
+    /**
+    @brief
+        Starts the Quest for an input player.
+    @param player
+        The player.
+    @return
+        Returns true if the Quest could be started, false if not.
+    */
+    bool Quest::start(PlayerInfo* player)
+    {
+        if(!this->isStartable(player)) // Checks whether the quest can be started.
+        {
+            orxout(verbose, context::quests) << "A non-startable quest was trying to be started." << endl;
+            return false;
+        }
+
+        orxout(verbose, context::quests) << "Quest {" << this->getId() << "} is started for player: " << player << " ." << endl;
+
+        QuestListener::advertiseStatusChange(this->listeners_, "start"); // Tells the QuestListeners, that the status has changed to active.
+
+        this->setStatus(player, QuestStatus::Active);
+
+        this->getDescription()->sendAddQuestNotification(player);
+        return true;
+    }
+
+    /**
+    @brief
+        Adds a QuestListener to the list of QuestListeners listening to this Quest.
+    @param listener
+        The QuestListener to be added.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool Quest::addListener(QuestListener* listener)
+    {
+        assert(listener);
+
+        this->listeners_.push_back(listener);
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/Quest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/Quest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/Quest.h	(revision 11817)
@@ -0,0 +1,166 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Quest.h
+    @brief Definition of the Quest class.
+        The Quest class is the parent class of @ref orxonox::LocalQuest "LocalQuest" and @ref orxonox::GlobalQuest "GlobalQuest".
+    @ingroup Questsystem
+*/
+
+#ifndef _Quest_H__
+#define _Quest_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <list>
+#include "QuestItem.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        Different states of a @ref orxonox::Quest "Quest".
+
+    @ingroup Questsystem
+    */
+    enum class QuestStatus
+    {
+        Inactive, //!< The @ref orxonox::Quest "Quest" is inactive.
+        Active, //!< The @ref orxonox::Quest "Quest" is active.
+        Failed, //!< The @ref orxonox::Quest "Quest" has been failed.
+        Completed //!< The @ref orxonox::Quest "Quest" has been completed.
+    };
+
+    /**
+    @brief
+        Represents a Quest in the game. A Quest is a task that the player can (or has to) fulfill upon which he will (possibly) receive some kind of reward.
+
+        A Quest can have a list of sub-quests and has a parent-quest (if it is not a root-quest).
+        Each Quest exists only once but it has a different status (inactive, active, failed or completed) for each player.
+        A Quest can have several hints (QuestHint) that can be unlocked through @ref orxonox::QuestEffect "QuestEffects" and then display aid in solving the Quest.
+        A Quest can have a list of @ref orxonox::QuestEffect "QuestEffects" that are invoked when the quest is failed and also a list of @ref orxonox::QuestEffect "QuestEffects" that are invoked, when the Quest is completed.
+
+        Quest itself should not be instantiated, if you want to create a quest either use LocalQuest or GlobalQuest, whichever suits you needs better.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport Quest // tolua_export
+        : public QuestItem
+    { // tolua_export
+        public:
+            Quest(Context* context);
+            virtual ~Quest();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a Quest object through XML.
+
+            /**
+            @brief Returns the parent-quest of the Quest.
+            @return Returns a pointer to the parent-quest of the Quest.
+            */
+            inline Quest* getParentQuest(void) const
+                { return this->parentQuest_; }
+
+            /**
+            @brief Returns the list of sub-quests.
+            @return Returns a reference to the list of sub-quests of the quest.
+            */
+            inline const std::list<Quest*> & getSubQuestList(void) const
+                { return this->subQuests_; }
+
+            /**
+            @brief Returns the list of all QuestHints of this Quest.
+            @return Returns a reference to the list of QuestHints of the Quest.
+            */
+            inline const std::list<QuestHint*> & getHintsList(void) const
+                { return this->hints_; }
+
+            bool isInactive(const PlayerInfo* player) const; //!< Returns true if the quest status for the specific player is 'inactive'.
+            bool isActive(const orxonox::PlayerInfo* player) const; // tolua_export //!< Returns true if the quest status for the specific player is 'active'.
+            bool isFailed(const orxonox::PlayerInfo* player) const; // tolua_export //!< Returns true if the quest status for the specific player is 'failed'.
+            bool isCompleted(const orxonox::PlayerInfo* player) const; // tolua_export //!< Returns true if the quest status for the specific player is 'completed'.
+
+            bool start(PlayerInfo* player); //!< Sets a Quest to active.
+            virtual bool fail(PlayerInfo* player); //!< Fails the Quest.
+            virtual bool complete(PlayerInfo* player); //!< Completes the Quest.
+
+            bool addListener(QuestListener* listener); //!< Adds a QuestListener to the list of QuestListeners listening to this Quest.
+
+        protected:
+            virtual bool isStartable(const PlayerInfo* player) const = 0; //!< Checks whether the Quest can be started.
+            virtual bool isFailable(const PlayerInfo* player) const = 0; //!< Checks whether the Quest can be failed.
+            virtual bool isCompletable(const PlayerInfo* player) const = 0; //!< Checks whether the Quest can be completed.
+
+            const Quest* getSubQuest(unsigned int index) const; //!<Returns the sub-quest at the given index.
+            const QuestHint* getHint(unsigned int index) const; //!< Returns the QuestHint at the given index.
+            const QuestEffect* getFailEffect(unsigned int index) const; //!< Returns the fail QuestEffect at the given index.
+            const QuestEffect* getCompleteEffect(unsigned int index) const; //!< Returns the complete QuestEffect at the given index.
+
+            /**
+            @brief Returns the list of fail QuestEffects.
+            @return Returns a reference to the list of fail QuestEffects.
+            */
+            inline std::list<QuestEffect*> & getFailEffectList(void)
+                { return this->failEffects_; }
+
+            /**
+            @brief Returns the list of complete QuestEffects.
+            @return Returns a reference to the list of complete QuestEffects.
+            */
+            inline std::list<QuestEffect*> & getCompleteEffectList(void)
+                { return this->completeEffects_; }
+
+            virtual QuestStatus getStatus(const PlayerInfo* player) const = 0; //!< Returns the status of the Quest for a specific player.
+            virtual bool setStatus(PlayerInfo* player, const QuestStatus & status) = 0; //!< Changes the status for a specific player.
+
+        private:
+            Quest* parentQuest_; //!< Pointer to the parent-quest.
+            std::list<Quest*> subQuests_; //!< List of all the sub-quests.
+
+            std::list<QuestHint*> hints_; //!< A list of all the QuestHints tied to this Quest.
+
+            std::list<QuestEffect*> failEffects_; //!< A list of all QuestEffects to be invoked, when the Quest has been failed.
+            std::list<QuestEffect*> completeEffects_; //!< A list of QuestEffects to be invoked, when the Quest has been completed.
+
+            std::list<QuestListener*> listeners_; //!< A list of QuestListeners, that listen to what exactly happens with this Quest.
+
+            bool setParentQuest(Quest* quest); //!< Sets the parent-quest of the Quest.
+            bool addSubQuest(Quest* quest); //!< Adds a sub-quest to the Quest.
+            bool addHint(QuestHint* hint); //!< Add a QuestHint to the list of QuestHints.
+            bool addFailEffect(QuestEffect* effect); //!< Adds an QuestEffect to the list of fail QuestEffects.
+            bool addCompleteEffect(QuestEffect* effect); //!< Adds an QuestEffect to the list of complete QuestEffects.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _Quest_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestDescription.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestDescription.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestDescription.cc	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestDescription.cc
+    @brief Implementation of the QuestDescription class.
+*/
+
+
+#include "QuestDescription.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "infos/PlayerInfo.h"
+
+#include "interfaces/NotificationListener.h"
+
+namespace orxonox
+{
+    RegisterClass(QuestDescription);
+
+    /*static*/ const std::string QuestDescription::SENDER = "questsystem";
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    QuestDescription::QuestDescription(Context* context) : BaseObject(context)
+    {
+        RegisterObject(QuestDescription);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    QuestDescription::~QuestDescription()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a QuestDescription object through XML.
+    */
+    void QuestDescription::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(QuestDescription, XMLPort, xmlelement, mode);
+
+        XMLPortParam(QuestDescription, "title", setTitle, getTitle, xmlelement, mode);
+        XMLPortParam(QuestDescription, "description", setDescription, getDescription, xmlelement, mode);
+        XMLPortParam(QuestDescription, "failMessage", setFailMessage, getFailMessage, xmlelement, mode);
+        XMLPortParam(QuestDescription, "completeMessage", setCompleteMessage, getCompleteMessage, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New QuestDescription with title '" << this->getTitle() << "' created." << endl;
+    }
+
+    /**
+    @brief
+        This method is a helper for sending QuestDescriptions as Notifications.
+    @param item
+        The item the QuestDescription is for.
+    @param status
+        The status the QuestDescription us for.
+    @param player
+        The player the Notification is sent to.
+    @return
+        Returns true if successful.
+    */
+    bool QuestDescription::notificationHelper(const std::string & item, const std::string & status, PlayerInfo* player)
+    {
+        std::string message;
+        if(item == "hint")
+            message = "You received a hint: '" + this->title_ + '\'';
+        else if(item == "quest")
+        {
+            if(status == "start")
+                message = "You received a new quest: '" + this->title_ + '\'';
+            else if(status == "fail")
+                message = "You failed the quest: '" + this->title_ + '\'';
+            else if(status == "complete")
+                message = "You successfully completed the quest: '" + this->title_ + '\'';
+            else
+            {
+                orxout(internal_warning, context::quests) << "Bad input in notificationHelper, this should not be happening!" << endl;
+                return false;
+            }
+        }
+        else
+        {
+            orxout(internal_warning, context::quests) << "Bad input in notificationHelper, this should not be happening!" << endl;
+            return false;
+        }
+
+        NotificationListener::sendNotification(message, QuestDescription::SENDER, NotificationMessageType::info, NotificationSendMode::network, player->getClientID());
+        return true;
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestDescription.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestDescription.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestDescription.h	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestDescription.h
+    @brief Definition of the QuestDescription class.
+    @ingroup Questsystem
+*/
+
+#ifndef _QuestDescription_H__
+#define _QuestDescription_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <string>
+#include "core/BaseObject.h"
+
+// tolua_begin
+namespace orxonox
+{
+
+    /**
+    @brief
+        This class is a description of a QuestItem (@ref orxonox::Quest "Quest" and @ref orxonox::QuestHint "QuestHint").
+        It holds a title and a description. For quests also messages that are sent, when failing or completing the quest can be added.
+
+        Creating a QuestDescription through XML goes as follows:
+        @code
+        <QuestDescription title="Title" description="Description Text" failMessage="You fail." completeMessage="You win!" />
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestDescription : public BaseObject
+    {
+// tolua_end
+        public:
+            QuestDescription(Context* context);
+            virtual ~QuestDescription();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a QuestDescription object through XML.
+
+// tolua_begin
+            /**
+            @brief Returns the title.
+            @return Returns a string containing the title of the QuestDescription.
+            */
+            inline const std::string & getTitle(void) const
+                { return this->title_; }
+
+            /**
+            @brief Returns the description text.
+            @return Returns a string containing the description text of the QuestDescription.
+            */
+            inline const std::string & getDescription(void) const
+                { return this->description_; }
+// tolua_end
+
+            /**
+            @brief Returns the fail message.
+            @return Returns a string containing the fail message of the QuestDescription.
+            */
+            inline const std::string & getFailMessage(void)
+                { return this->failMessage_; }
+
+            /**
+            @brief Returns the complete message.
+            @return Returns a string containing the complete message of the QuestDescription.
+            */
+            inline const std::string & getCompleteMessage(void)
+                { return this->completeMessage_; }
+
+            /**
+            @brief Sends a Notification displaying that a QuestHint was added.
+            @param player The player the Notification is sent to.
+            @return Returns true if successful.
+            */
+            inline bool sendAddHintNotification(PlayerInfo* player)
+                { return notificationHelper("hint", "", player); }
+
+            /**
+            @brief Sends a Notification displaying that a Quest was added.
+            @param player The player the Notification is sent to.
+            @return Returns true if successful.
+            */
+            inline bool sendAddQuestNotification(PlayerInfo* player)
+                { return notificationHelper("quest", "start", player); }
+
+            /**
+            @brief Sends a Notification displaying that a Quest was failed.
+            @param player The player the Notification is sent to.
+            @return Returns true if successful.
+            */
+            inline bool sendFailQuestNotification(PlayerInfo* player)
+                { return notificationHelper("quest", "fail", player); }
+
+            /**
+            @brief Sends a Notification displaying that a Quest was completed.
+            @param player The player the Notification is sent to.
+            @return Returns true if successful.
+            */
+            inline bool sendCompleteQuestNotification(PlayerInfo* player)
+                { return notificationHelper("quest", "complete", player); }
+
+        private:
+            static const std::string SENDER;
+
+            std::string title_; //!< The title.
+            std::string description_; //!< The description.
+            std::string failMessage_; //!< The message displayed when the Quest is failed.
+            std::string completeMessage_; //!< The message displayed when the Quest is completed.
+
+            bool notificationHelper(const std::string & item, const std::string & status, PlayerInfo* player); //!< Helper for sending QuestDescriptions as Notifications.
+
+            /**
+            @brief Sets the title.
+            @param title The title to be set.
+            */
+            inline void setTitle(const std::string & title)
+                { this->title_ = title; }
+
+            /**
+            @brief Sets the description text.
+            @param description The description text to be set.
+            */
+            inline void setDescription(const std::string & description)
+                { this->description_ = description; }
+
+            /**
+            @brief Sets the fail message.
+            @param message The fail message to be set.
+            */
+            inline void setFailMessage(const std::string & message)
+                { this->failMessage_ = message; }
+
+            /**
+            @brief Sets the complete message.
+            @param message The complete message to be set.
+            */
+            inline void setCompleteMessage(const std::string & message)
+                { this->completeMessage_ = message; }
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _QuestDescription_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffect.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffect.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffect.cc	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestEffect.cc
+    @brief Implementation of the QuestEffect class.
+*/
+
+#include "QuestEffect.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(QuestEffect).inheritsFrom<BaseObject>();
+
+    /**
+    @brief
+        Constructor. Creates a new QuestEffect.
+        Is not meant to be invoked directly, since this is only an interface.
+    */
+    QuestEffect::QuestEffect(Context* context) : BaseObject(context)
+    {
+        RegisterObject(QuestEffect);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    QuestEffect::~QuestEffect()
+    {
+
+    }
+
+    /**
+    @brief
+        Static method. Invoke all QuestEffects in an QuestEffect-list on a given player.
+    @param player
+        The player the QuestEffects are invoked on.
+    @param effects
+        A list of all the QuestEffects to be invoked.
+    @return
+        Returns false if there was an error, view console or log for further details.
+    */
+    /*static*/ bool QuestEffect::invokeEffects(PlayerInfo* player, std::list<QuestEffect*> & effects)
+    {
+        bool temp = true;
+
+        orxout(verbose, context::quests) << "Invoking QuestEffects on player: " << player << " ."  << endl;
+
+        for (QuestEffect* effect : effects)
+            temp = temp && effect->invoke(player);
+
+        return temp;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffect.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffect.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffect.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestEffect.h
+    @brief Definition of the QuestEffect class.
+    @ingroup Questsystem
+*/
+
+#ifndef _QuestEffect_H__
+#define _QuestEffect_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <list>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Handles QuestEffects for @ref orxonox::Quest "Quests".
+        QuestEffects are one of the ways for @ref orxonox::Quest "Quests" to have any side effects on the game world and for the game world to influence the @ref orxonox::Quest "Quests".
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestEffect : public BaseObject
+    {
+        public:
+            QuestEffect(Context* context);
+            virtual ~QuestEffect();
+
+            virtual bool invoke(PlayerInfo* player) = 0; //!< Invokes the QuestEffect.
+            static bool invokeEffects(PlayerInfo* player, std::list<QuestEffect*> & effects); //!< Invokes all QuestEffects in the list.
+
+    };
+
+}
+
+#endif /* _QuestEffect_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffectBeacon.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffectBeacon.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffectBeacon.cc	(revision 11817)
@@ -0,0 +1,248 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestEffectBeacon.cc
+    @brief Implementation of the QuestEffectBeacon class.
+*/
+
+#include "QuestEffectBeacon.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/EventIncludes.h"
+
+#include "interfaces/PlayerTrigger.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "QuestEffect.h"
+
+namespace orxonox
+{
+    RegisterClass(QuestEffectBeacon);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes defaults.
+    */
+    QuestEffectBeacon::QuestEffectBeacon(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(QuestEffectBeacon);
+
+        this->status_ = QuestEffectBeaconStatus::Active;
+        this->times_ = INFINITE_TIME;
+    }
+
+    /**
+        Destructor.
+    */
+    QuestEffectBeacon::~QuestEffectBeacon()
+    {
+    }
+
+    /**
+    @brief
+        Method for creating a QuestEffectBeacon object through XML.
+    */
+    void QuestEffectBeacon::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(QuestEffectBeacon, XMLPort, xmlelement, mode);
+
+        XMLPortParam(QuestEffectBeacon, "times", setTimes, getTimes, xmlelement, mode);
+        XMLPortObject(QuestEffectBeacon, QuestEffect, "effects", addEffect, getEffect, xmlelement, mode);
+
+        XMLPortEventSink(QuestEffectBeacon, BaseObject, "execute", execute, xmlelement, mode); //TODO: Change BaseObject to MultiTrigger as soon as MultiTrigger is the base of all triggers.
+
+        orxout(verbose, context::quests) << "New QuestEffectBeacon created." << endl;
+    }
+
+    void QuestEffectBeacon::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(QuestEffectBeacon, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventSink(QuestEffectBeacon, BaseObject, "execute", execute, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Executes the QuestEffectBeacon.
+        This means extracting the Pawn from the PlayerTrigger, provided by the Event causing the execution, and the extracting the PlayerInfo from the received Pawn and invoking the QuestEffectbeacon's QuestEffects on the received PlayerInfo.
+    @param bTriggered
+        true means the trigger was activated while false means it was deactivated
+    @param trigger
+        A pointer to the PlayerTrigger that threw the Event.
+    @return
+        Returns true if successfully executed, false if not.
+    */
+    bool QuestEffectBeacon::execute(bool bTriggered, BaseObject* trigger)
+    {
+        if(!bTriggered)
+        {
+            return false;
+        }
+        if(!(this->isActive())) // If the QuestEffectBeacon is inactive it cannot be executed.
+        {
+            orxout(verbose, context::quests) << "The QuestEffectBeacon is inactive." << endl;
+            return false;
+        }
+
+        PlayerTrigger* pTrigger = orxonox_cast<PlayerTrigger*>(trigger);
+        PlayerInfo* player = nullptr;
+
+        // If the trigger is a PlayerTrigger.
+        if(pTrigger != nullptr)
+        {
+            if(!pTrigger->isForPlayer())  // The PlayerTrigger is not exclusively for Pawns which means we cannot extract one.
+                return false;
+            else
+                player = pTrigger->getTriggeringPlayer();
+        }
+        else
+            return false;
+
+        if(player == nullptr)
+        {
+            orxout(verbose, context::quests) << "The QuestEffectBeacon was triggered by an entity other than a Pawn. (" << trigger->getIdentifier()->getName() << ")" << endl;
+            return false;
+        }
+
+        orxout(verbose, context::quests) << "QuestEffectBeacon executed on player: " << player << " ." << endl;
+
+        bool temp = QuestEffect::invokeEffects(player, this->effects_); // Invoke the QuestEffects on the PlayerInfo.
+        if(temp)
+        {
+            this->decrementTimes(); // Decrement the number of times the beacon can be used.
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+    @brief
+        Set the status of the QuestEffectBeacon.
+    @param activate
+        If true the QuestEffectBeacon is activated, if false it is deactivated.
+    @return
+        Returns whether the activation/deactivation was successful.
+    */
+    bool QuestEffectBeacon::setActive(bool activate)
+    {
+        if(this->getTimes() == 0 && activate) // A QuestEffectBeacon that can be executed only 0 times is always inactive.
+            return false;
+
+        if(activate)
+        {
+            this->status_ = QuestEffectBeaconStatus::Active;
+            return true;
+        }
+
+        this->status_ = QuestEffectBeaconStatus::Inactive;
+        return true;
+    }
+
+    /**
+    @brief
+        Decrement the number of times the QuestEffectBeacon can be executed.
+    @return
+        Returns true if successful.
+    */
+    bool QuestEffectBeacon::decrementTimes(void)
+    {
+        if(!(this->isActive())) // The QuestEffectBeacon mus be active to decrement the number of times it can be executed.
+            return false;
+
+        if(this->getTimes() == INFINITE_TIME) // If times is infinity the QuestEffectBeacon can be executed an infinite number fo times.
+            return true;
+
+        this->times_ = this->times_ - 1; // Decrement number of times the QuestEffectBeacon can be executed.
+        if(this->getTimes() == 0) // Set the QuestEffectBeacon to inactive when the number of times it can be executed is reduced to 0.
+            this->status_ = QuestEffectBeaconStatus::Inactive;
+
+        return true;
+    }
+
+    /**
+    @brief
+        Set the number of times the QuestEffectBeacon can be executed.
+        The number must be eighter <= 0, or INFINITY which is '-1'.
+    @param n
+        The number of times the QuestEffectBeacon can be executed.
+        The number must be eighter <= 0, or INFINITY which is '-1'.
+    @return
+        Returns true if successful.
+    */
+    bool QuestEffectBeacon::setTimes(const int & n)
+    {
+        if(n < 0 && n != INFINITE_TIME)
+            return false;
+
+        this->times_ = n;
+        return true;
+    }
+
+    /**
+    @brief
+        Adds a QuestEffect to the QuestEffectBeacon.
+    @param effect
+        A pointer to the QuestEffect to be added.
+    @return
+        Returns true if successful.
+    */
+    bool QuestEffectBeacon::addEffect(QuestEffect* effect)
+    {
+        assert(effect);
+
+        this->effects_.push_back(effect);
+
+        orxout(verbose, context::quests) << "A QuestEffect was added to a QuestEffectBeacon." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Returns the QuestEffect at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer to the QuestEffect at the given index.
+    */
+    const QuestEffect* QuestEffectBeacon::getEffect(unsigned int index) const
+    {
+        int i = index;
+        for (QuestEffect* effect : this->effects_)
+        {
+            if(i == 0)
+               return effect;
+
+            i--;
+        }
+        return nullptr;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffectBeacon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffectBeacon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestEffectBeacon.h	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestEffectBeacon.h
+    @brief Definition of the QuestEffectBeacon class.
+    @ingroup Questsystem
+*/
+
+#ifndef _QuestEffectBeacon_H__
+#define _QuestEffectBeacon_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <list>
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The status of the @ref orxonox::QuestEffectBeacon "QuestEffectBeacon", can be either active or inactive.
+
+    @ingroup Questsystem
+    */
+    enum class QuestEffectBeaconStatus
+    {
+        Inactive, //!< The @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" is inactive.
+        Active //!< The @ref orxonox::QuestEffectBeacon "QuestEffectBeacon" is active.
+    };
+
+    /**
+    @brief
+        A QuestEffectBeacon is a physical entity in the game which can (under some condition(s)) invoke a number of @ref orxonox::QuestEffect "QuestEffects" on players meeting the condition(s).
+        The conditions under which the @ref orxonox::QuestEffect "QuestEffects" are invoked on the player are defined by @ref orxonox::Trigger "Triggers" (or really any kind of entity firing events, e.g. @ref orxonox::EventListener "EventListeners"). The trigger the event originates from, however has to be a @ref orxonox::PlayerTrigger PlayerTrigger.
+        A QuestEffectBeacon can be executed a defined number of times.
+        A QuestEffectBeacon can be inactive or active. While inactive it can't be executed.
+
+        Creating a QuestEffectBeacon through XML goes as follows:
+        @code
+        <QuestEffectBeacon times=n> //Where 'n' is eighter a number >= 0, which means the QuestEffectBeacon can be executed n times. Or n = -1, which means the QuestEffectBeacon can be executed an infinite number of times.
+            <effects>
+                <QuestEffect /> //A list of QuestEffects, invoked when the QuestEffectBeacon is executed, see QuestEffect for the full XML representation.
+                ...
+                <QuestEffect />
+            </effects>
+            <events>
+                <execute>
+                    <EventListener event=eventIdString />
+                </execute>
+            </events>
+            <attached>
+                <PlayerTrigger name=eventIdString /> //A PlayerTrigger triggering the execution of the QuestEffectBeacon.
+            </attached>
+        </QuestEffectBeacon>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestEffectBeacon : public StaticEntity
+    {
+        public:
+            QuestEffectBeacon(Context* context);
+            virtual ~QuestEffectBeacon();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a QuestEffectBeacon object through XML.
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            bool execute(bool bTriggered, BaseObject* trigger); //!< Executes the QuestEffects of the QuestEffectBeacon.
+
+            /**
+            @brief Tests whether the QuestEffectBeacon is active.
+            @return Returns true if the QuestEffectBeacon is active, fals if not.
+            */
+            inline bool isActive(void)
+            { return this->status_ == QuestEffectBeaconStatus::Active; }
+
+            bool setActive(bool activate); //!< Set the status of the QuestEffectBeacon.
+
+        protected:
+            bool decrementTimes(void); //!< Decrement the number of times the QuestEffectBeacon can still be executed.
+
+            /**
+            @brief Returns the number of times the QUestEffectBeacon can still be executed.
+            @return Returns the number of times the QUestEffectBeacon can still be executed.
+            */
+            inline const int & getTimes(void) const
+                { return this->times_; }
+
+        private:
+            static const int INFINITE_TIME = -1; //!< Constant to avoid using magic numbers.
+
+            std::list<QuestEffect*> effects_; //!< The list of QuestEffects to be invoked on the executing player.
+            int times_; //!< Number of times the beacon can be exectued.
+            QuestEffectBeaconStatus status_; //!< The status of the QuestEffectBeacon, Can be eighter active or inactive.
+
+            bool setTimes(const int & n); //!< Set the number of times the QuestEffectBeacon can be executed.
+            bool addEffect(QuestEffect* effect); //!< Add a QuestEffect to the QuestEffectBeacon.
+
+            const QuestEffect* getEffect(unsigned int index) const; //!< Get the QuestEffect at a given index.
+
+    };
+
+}
+
+#endif /* _QuestEffectBeacon_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestHint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestHint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestHint.cc	(revision 11817)
@@ -0,0 +1,147 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestHint.cc
+    @brief Implementation of the QuestHint class.
+*/
+
+#include "QuestHint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Quest.h"
+#include "QuestDescription.h"
+#include "QuestManager.h"
+
+namespace orxonox
+{
+    RegisterClass(QuestHint);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    QuestHint::QuestHint(Context* context) : QuestItem(context)
+    {
+        RegisterObject(QuestHint);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    QuestHint::~QuestHint()
+    {
+        if(this->isRegistered())
+            QuestManager::getInstance().unregisterHint(this);
+    }
+
+    /**
+    @brief
+        Method for creating a QuestHint object through XML.
+    */
+    void QuestHint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(QuestHint, XMLPort, xmlelement, mode);
+
+        QuestManager::getInstance().registerHint(this); // Registers the QuestHint with the QuestManager.
+
+        orxout(verbose, context::quests) << "New QuestHint {" << this->getId() << "} created." << endl;
+    }
+
+
+    /**
+    @brief
+        Checks whether the QuestHint is active for a specific player.
+    @param player
+        The player.
+    @return
+        Returns true if the QuestHint is active for the specified player.
+    */
+    bool QuestHint::isActive(const PlayerInfo* player) const
+    {
+        if(player == nullptr) // If the player is nullptr, the Quest obviously can't be active.
+            return false;
+
+        // Find the player.
+        std::map<const PlayerInfo*, QuestHintStatus>::const_iterator it = this->playerStatus_.find(player);
+        if (it != this->playerStatus_.end()) // If the player is in the map.
+            return (it->second == QuestHintStatus::Active);
+
+        return false;
+    }
+
+    /**
+    @brief
+        Activates a QuestHint for a given player.
+    @param player
+        The player.
+    @return
+        Returns true if the activation was successful, false if there were problems.
+    */
+    bool QuestHint::setActive(PlayerInfo* player)
+    {
+        if(this->quest_->isActive(player)) // For a hint to get activated the quest must be active.
+        {
+            if(!(this->isActive(player)))  // If the hint is already active, activation is pointless.
+            {
+                this->playerStatus_[player] = QuestHintStatus::Active;
+
+                this->getDescription()->sendAddHintNotification(player);
+                return true;
+            }
+            else
+            {
+                orxout(verbose, context::quests) << "An already active questHint was trying to get activated." << endl;
+                return false;
+            }
+        }
+
+        orxout(verbose, context::quests) << "A hint of a non-active quest was trying to get activated." << endl;
+        return false;
+    }
+
+    /**
+    @brief
+        Sets the Quest the QuestHint belongs to.
+    @param quest
+        The Quest to be set as Quest the QuestHint is attached to.
+    @return
+        Returns true if successful.
+    */
+    bool QuestHint::setQuest(Quest* quest)
+    {
+        assert(quest);
+
+        this->quest_ = quest;
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestHint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestHint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestHint.h	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestHint.h
+    @brief Definition of the QuestHint class.
+    @ingroup Questsystem
+*/
+
+#ifndef _QuestHint_H__
+#define _QuestHint_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <map>
+#include "QuestItem.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        The state of the @ref orxonox::QuestHint "QuestHint".
+
+    @ingroup Questsystem
+    */
+    enum class QuestHintStatus
+    {
+        Inactive, //!< The @ref orxonox::QuestHint "QuestHint" is inactive.
+        Active //!< The @ref orxonox::QuestHint "QuestHint" is active.
+    };
+
+    /**
+    @brief
+        Represents a hint in the game that gives aid towards completing a @ref orxonox::Quest "Quest".
+        Consists of title and description (which is stored in a @ref orxonox::QuestDescription "QuestDescription" object) in textual form and must belong to a quest.
+        A QuestHint has a defined status (inactive or active, where inactive is default) for each player, which means each a QuestHint exists only once for all players, it doesn't belong to a player, it just has different states for each of them.
+
+        Creating a QuestHint through XML goes as follows:
+        @code
+        <QuestHint id="hintId">
+            <QuestDesctription title="" description="" />
+        </QuestHint>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestHint // tolua_export
+        : public QuestItem
+    { // tolua_export
+
+        public:
+            QuestHint(Context* context);
+            virtual ~QuestHint();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a QuestHint object through XML.
+
+            bool isActive(const PlayerInfo* player) const; //!< Returns true if the QuestHint is active for the input player.
+
+            bool setActive(PlayerInfo* player); //!< Activates the QuestHint for the input player.
+            bool setQuest(Quest* quest); //!< Sets the Quest the QuestHint belongs to.
+
+            /**
+            @brief Returns the Quest the QuestHint is attached to.
+            @return  Returns a pointer to the Quest the QuestHint is attached to.
+            */
+            inline Quest* getQuest(void)
+               { return this->quest_; }
+
+        private:
+            Quest* quest_; //!< The Quest the QuestHint belongs to.
+            std::map<const PlayerInfo*, QuestHintStatus> playerStatus_; //!< List of the states for each player, with the Player-pointer as key.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _QuestHint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestItem.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestItem.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestItem.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestItem.cc
+    @brief Implementation of the QuestItem class.
+*/
+
+#include "QuestItem.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "QuestDescription.h"
+
+namespace orxonox
+{
+
+    RegisterUnloadableClass(QuestItem);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    QuestItem::QuestItem(Context* context) : BaseObject(context)
+    {
+        this->registered_ = false;
+
+        RegisterObject(QuestItem);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    QuestItem::~QuestItem()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a QuestItem object through XML.
+    */
+    void QuestItem::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(QuestItem, XMLPort, xmlelement, mode);
+
+        XMLPortParam(QuestItem, "id", setId, getId, xmlelement, mode);
+        XMLPortObject(QuestItem, QuestDescription, "", setDescription, getDescription, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Sets the id of the QuestItem.
+        The id can be any string and must be unique in the context it is used (commonly a level file). To ensure uniqueness one could use GUIDs, however they are in general less readable, so make your own choice.
+    @see
+        http://en.wikipedia.org/wiki/Globally_Unique_Identifier#Basic_structure
+    @param id
+        The id to be set.
+    */
+    void QuestItem::setId(const std::string & id)
+    {
+        if(id == "") // Checks whether the id is a valid id.
+        {
+            orxout(internal_warning, context::quests) << "Invalid id. QuestItem id {" << id << "} could not be set." << endl;
+            return;
+        }
+
+        this->id_ = id;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestItem.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestItem.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestItem.h	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestItem.h
+    @brief Definition of the QuestItem class.
+        The @ref orxonox::QuestItem "QuestItem" is the parent class of @ref orxonox::Quest "Quest" and @ref orxonox::QuestHint "QuestHint".
+    @ingroup Questsystem
+*/
+
+
+#ifndef _QuestItem_H__
+#define _QuestItem_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <string>
+#include "core/BaseObject.h"
+#include "QuestManager.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Functions as a base class for quest classes such as @ref orxonox::Quest "Quest" or @ref orxonox::QuestHint "QuestHint".
+        Has a unique identifier and a @ref orxonox::QuestDescription "QuestDescription".
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestItem : public BaseObject
+    {
+
+        public:
+            QuestItem(Context* context);
+            virtual ~QuestItem();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a QuestItem object through XML.
+
+            /**
+            @brief Returns the id of this QuestItem.
+            @return Returns the id of the QuestItem.
+            */
+            inline const std::string & getId(void) const
+                { return this->id_; }
+
+            /**
+            @brief Returns the QuestDescription of the QuestItem.
+            @return Returns a pointer to the QuestDescription object of the QuestItem.
+            */
+            inline QuestDescription* getDescription(void) const
+                { return this->description_; }
+
+            /**
+            @brief Check whether the QuestItem is registered with the QuestManager.
+            @return Returns true if the QuestItem is registered with the QuestManager.
+            */
+            inline bool isRegistered(void)
+                { return this->registered_; }
+            /**
+            @brief Set the QuestItem as being registered with the QuestManager.
+            */
+            inline void setRegistered(void)
+                { this->registered_ = true; }
+
+        protected:
+            void setId(const std::string & id); //!< Sets the id of the QuestItem.
+
+            /**
+            @brief Sets the description of the QuestItem.
+            @param description The QuestDescription to be set.
+            */
+            inline void setDescription(QuestDescription* description)
+                { this->description_ = description; }
+
+        private:
+            std::string id_; //!< Identifier. Must be unique.
+            QuestDescription* description_; //!< The QuestDescription of the QuestItem.
+
+            bool registered_; //!< Whether the QuestItem is registered with the QuestManager.
+
+    };
+
+}
+
+#endif /* _QuestItem_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestListener.cc	(revision 11817)
@@ -0,0 +1,206 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestListener.cc
+    @brief Implementation of the QuestListener class.
+*/
+
+#include "QuestListener.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Quest.h"
+#include "QuestManager.h"
+
+namespace orxonox
+{
+    RegisterClass(QuestListener);
+
+    // Initialization of the static variables for the modes as strings.
+    /*static*/ const std::string QuestListener::ALL = "all";
+    /*static*/ const std::string QuestListener::START = "start";
+    /*static*/ const std::string QuestListener::FAIL = "fail";
+    /*static*/ const std::string QuestListener::COMPLETE = "complete";
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes variables.
+    */
+    QuestListener::QuestListener(Context* context) : BaseObject(context)
+    {
+        RegisterObject(QuestListener);
+
+        this->mode_ = QuestListenerMode::All;
+        this->quest_ = nullptr;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    QuestListener::~QuestListener()
+    {
+    }
+
+    /**
+    @brief
+        Method for creating a Quest object through XML.
+    */
+    void QuestListener::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(QuestListener, XMLPort, xmlelement, mode);
+
+        XMLPortParam(QuestListener, "questId", setQuestId, getQuestId, xmlelement, mode);
+        XMLPortParam(QuestListener, "mode", setMode, getMode, xmlelement, mode);
+
+        std::string questid;
+
+        if (this->quest_ != nullptr)
+        {
+            this->quest_->addListener(this); // Adds the QuestListener to the Quests list of listeners.
+            questid = this->quest_->getId();
+        }
+
+        orxout(verbose, context::quests) << "QuestListener created for quest: {" << questid << "} with mode '" << this->getMode() << "'." << endl;
+    }
+
+    /**
+    @brief
+        Makes all QuestListener in the list aware that a certain status change has occurred and executes them if the status change affects them.
+    @param listeners
+        The list of QuestListeners that have to be made aware of the status change.
+    @param status
+        The status that has changed. Can be 'start' (if the Quest was started), 'complete' (if the Quest was completed) or 'fail' (if the Quest was failed).
+    */
+    /* static */ void QuestListener::advertiseStatusChange(std::list<QuestListener*> & listeners, const std::string & status)
+    {
+        for (QuestListener* listener : listeners) // Iterate through all QuestListeners
+        {
+            if(listener->getMode() == status || listener->getMode() == QuestListener::ALL) // Check whether the status change affects the give QuestListener.
+                listener->execute();
+        }
+    }
+
+    /**
+    @brief
+        Sets the questId of the Quest the QuestListener reacts to.
+    @param id
+        The questId of the Quest the QUestListener reacts to.
+    @return
+        Returns true if successful.
+    */
+    bool QuestListener::setQuestId(const std::string & id)
+    {
+        this->quest_ = QuestManager::getInstance().findQuest(id); // Find the Quest corresponding to the given questId.
+
+        if(this->quest_ == nullptr) // If there is no such Quest.
+        {
+            ThrowException(Argument, "This is bad! The QuestListener has not found a Quest with a corresponding id..");
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+    @brief
+        Sets the mode of the QuestListener.
+    @param mode
+        The mode to be set. Can be eighter 'all', 'start', 'fail' or 'complete'.
+    @return
+        Returns true if successful.
+    */
+    bool QuestListener::setMode(const std::string & mode)
+    {
+        if(mode == QuestListener::ALL)
+            this->mode_ = QuestListenerMode::All;
+        else if(mode == QuestListener::START)
+            this->mode_ = QuestListenerMode::Start;
+        else if(mode == QuestListener::FAIL)
+            this->mode_ = QuestListenerMode::Fail;
+        else if(mode == QuestListener::COMPLETE)
+            this->mode_ = QuestListenerMode::Complete;
+        else
+        {
+            orxout(internal_warning, context::quests) << "QuestListener with invalid mode '" << mode << "' created. Mode set to 'all'." << endl;
+            this->mode_ = QuestListenerMode::All;
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+    @brief
+        Get the mode of the QuestListener.
+    @return
+        Return the mode of the QuestListener. Can be either 'all', 'start', 'fail' or 'complete'.
+    */
+    std::string QuestListener::getMode(void)
+    {
+        switch(this->mode_)
+        {
+            case QuestListenerMode::All:
+                return QuestListener::ALL;
+            case QuestListenerMode::Start:
+                return QuestListener::START;
+            case QuestListenerMode::Fail:
+                return QuestListener::FAIL;
+            case QuestListenerMode::Complete:
+                return QuestListener::COMPLETE;
+            default: // This will never happen.
+                return QuestListener::ALL;
+        }
+    }
+
+    /**
+    @brief
+        Get the questId of the Quest the QuestListener reacts to.
+    @return
+        Returns the questId of the Quest the QuestListener reacts to.
+    */
+    const std::string & QuestListener::getQuestId(void)
+    {
+        return this->quest_->getId();
+    }
+
+    /**
+    @brief
+        Executes the QuestListener, resp. fires an Event.
+    @return
+        Returns true if successful.
+    */
+    bool QuestListener::execute()
+    {
+        this->fireEvent(true);
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestListener.h	(revision 11817)
@@ -0,0 +1,115 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestListener.h
+    @brief Definition of the QuestListener class.
+    @ingroup Questsystem
+*/
+
+#ifndef _QuestListener_H__
+#define _QuestListener_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <string>
+#include <list>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The mode of the @ref orxonox::QuestListener "QuestListener".
+
+    @ingroup Questsystem
+    */
+    enum class QuestListenerMode
+    {
+        All, //!< Listens to all events.
+        Start, //!< Only listens to events pertaining the starting of @ref orxonox::Quest "Quests".
+        Fail, //!< Only listens to events pertaining the failing of @ref orxonox::Quest "Quests".
+        Complete //!< Only listens to events pertaining the completing of @ref orxonox::Quest "Quests".
+    };
+
+    /**
+    @brief
+        Provides a way to react to the starting, completing and failing of @ref orxonox::Quest "Quests".
+
+        The XML representation goes as follows:
+        @code
+        <BaseObject> // The object that should react to the status change of a Quest.
+            <events>
+                <function> // Where function is the method of the object that should be executed. Normally this would be visibility or activity.
+                    <QuestListener questId="someQuestId" mode="someMode" /> // Where someQuestId is the identifier for the Quest the QuestListener is reacting to, and someMode is the kind of status change the QUestListener reacts to (all, start, complete or fail).
+                </function>
+            </events>
+        </BaseObject>
+        @endcode
+
+        You can use the QuestListener as if it were a @ref orxonox::Trigger "Trigger" or @ref orxonox::EventListener "EventListener", that fires an Event when the status (depending on the set mode) of the given @ref orxonox::Quest "Quest" changes.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestListener : public BaseObject
+    {
+
+        public:
+            QuestListener(Context* context);
+            virtual ~QuestListener();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a QuestListener object through XML.
+
+            static void advertiseStatusChange(std::list<QuestListener*> & listeners, const std::string & status); //!< Makes all QuestListener in the list aware that a certain status change has occured.
+
+            bool setQuestId(const std::string & id); //!< Sets the questId of the Quest the QuestListener reacts to.
+            bool setMode(const std::string & mode); //!< Sets the mode of the QuestListener.
+
+            std::string getMode(void); //!< Get the mode of the QuestListener.
+
+            const std::string & getQuestId(void);
+            bool execute(void); //!< Executes the QuestListener, resp. fires an Event.
+
+        private:
+            QuestListenerMode mode_; //!< The mode of the QuestListener.
+            Quest* quest_; //!< A pointer to the Quest the QuestListener is reacting to.
+
+            //! Static variables for the modes as strings.
+            static const std::string ALL;
+            static const std::string START;
+            static const std::string FAIL;
+            static const std::string COMPLETE;
+
+    };
+
+}
+
+#endif /* _QuestListener_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestManager.cc	(revision 11817)
@@ -0,0 +1,451 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestManager.cc
+    @brief Implementation of the QuestManager class.
+*/
+
+#include "QuestManager.h"
+
+#include "util/Exception.h"
+#include "util/OrxAssert.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/command/ConsoleCommand.h"
+#include "core/GUIManager.h"
+#include "core/LuaState.h"
+
+#include "infos/PlayerInfo.h"
+
+#include "Quest.h"
+#include "QuestHint.h"
+#include "QuestItem.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(QuestManager, ScopeID::ROOT, false);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    @todo
+        Is inheriting from BaseObject proper?
+    */
+    QuestManager::QuestManager()
+    {
+        orxout(internal_info, context::quests) << "QuestManager created." << endl;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    QuestManager::~QuestManager()
+    {
+        orxout(internal_info, context::quests) << "QuestManager destroyed." << endl;
+    }
+
+    /**
+    @brief
+        Retreive all Quests.
+    @return
+        Returns a map with all Quests indexed by their id's.
+    */
+    std::map<std::string, Quest*> & QuestManager::getQuests(void)
+    {
+        return this->questMap_;
+    }
+
+    /**
+    @brief
+        Registers a Quest with the QuestManager to make it globally accessible.
+        Uses it's id to make sure to be able to be identify and retrieve it later.
+    @param quest
+        The Quest that is to be registered.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool QuestManager::registerQuest(Quest* quest)
+    {
+        if(quest == nullptr)
+        {
+            orxout(internal_error, context::quests) << "Quest pointer is nullptr." << endl;
+            return false;
+        }
+
+        std::pair<std::map<std::string, Quest*>::iterator,bool> result;
+        result = this->questMap_.insert( std::pair<std::string,Quest*>(quest->getId(),quest) ); // Inserting the Quest.
+
+        if(result.second) // If inserting was a success.
+        {
+            quest->setRegistered();
+            orxout(verbose, context::quests) << "Quest with questId {" << quest->getId() << "} successfully inserted." << endl;
+            return true;
+        }
+        else
+        {
+           orxout(internal_warning, context::quests) << "Quest with the same id was already present." << endl;
+           return false;
+        }
+    }
+
+    /**
+    @brief
+        Unregisters a Quest in the QuestManager.
+    */
+    bool QuestManager::unregisterQuest(Quest* quest)
+    {
+        return this->questMap_.erase(quest->getId()) == 1;
+    }
+
+    /**
+    @brief
+        Registers a QuestHint with the QuestManager to make it globally accessible.
+        Uses it's id to make sure to be able to be identify and retrieve it later.
+    @param hint
+        The QuestHint to be registered.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool QuestManager::registerHint(QuestHint* hint)
+    {
+        if(hint == nullptr)
+        {
+            orxout(internal_error, context::quests) << "Quest pointer is nullptr." << endl;
+            return false;
+        }
+
+        std::pair<std::map<std::string, QuestHint*>::iterator,bool> result;
+        result = this->hintMap_.insert ( std::pair<std::string,QuestHint*>(hint->getId(),hint) ); // Inserting the QuestHSint.
+
+        if(result.second) // If inserting was a success.
+        {
+            hint->setRegistered();
+            orxout(verbose, context::quests) << "QuestHint with hintId {" << hint->getId() << "} successfully inserted." << endl;
+            return true;
+        }
+        else
+        {
+           orxout(internal_warning, context::quests) << "QuestHint with the same id was already present." << endl;
+           return false;
+        }
+    }
+
+    /**
+    @brief
+        Unregisters a QuestHint in the QuestManager.
+    */
+    bool QuestManager::unregisterHint(QuestHint* hint)
+    {
+        return this->hintMap_.erase(hint->getId()) == 1;
+    }
+
+    /**
+    @brief
+        Finds a Quest with the given id.
+    @param questId
+        The id of the Quest sought for.
+    @return
+        Returns a pointer to the Quest with the input id.
+        Returns nullptr if there is no Quest with the given questId.
+    @throws
+        Throws an exception if the given questId is invalid.
+    */
+    Quest* QuestManager::findQuest(const std::string & questId)
+    {
+        if(questId == "") // Check for validity of the given id.
+            ThrowException(Argument, "Invalid questId.");
+
+        Quest* quest;
+        std::map<std::string, Quest*>::iterator it = this->questMap_.find(questId);
+        if (it != this->questMap_.end()) // If the Quest is registered.
+            quest = it->second;
+        else
+        {
+           quest = nullptr;
+           orxout(internal_warning, context::quests) << "The quest with id {" << questId << "} is nowhere to be found." << endl;
+        }
+
+        return quest;
+    }
+
+    /**
+    @brief
+        Finds a QuestHint with the given id.
+    @param hintId
+        The id of the QuestHint sought for.
+    @return
+        Returns a pointer to the QuestHint with the input id.
+        Returns nullptr if there is no QuestHint with the given hintId.
+    @throws
+        Throws an exception if the given hintId is invalid.
+    */
+    QuestHint* QuestManager::findHint(const std::string & hintId)
+    {
+        if(hintId == "") // Check for validity of the given id.
+            ThrowException(Argument, "Invalid hintId.");
+
+        QuestHint* hint;
+        std::map<std::string, QuestHint*>::iterator it = this->hintMap_.find(hintId);
+        if (it != this->hintMap_.end()) // If the QuestHint is registered.
+            hint = it->second;
+        else
+        {
+           hint = nullptr;
+           orxout(internal_warning, context::quests) << "The hint with id {" << hintId << "} is nowhere to be found." << endl;
+        }
+
+        return hint;
+    }
+
+    /**
+    @brief
+        Get the number of Quests the input player has, that are root quests.
+    @param player
+        The player.
+    @return
+        Returns the number of Quests the input player has, that are root quests.
+    */
+    int QuestManager::getNumRootQuests(PlayerInfo* player)
+    {
+        int numQuests = 0;
+        for(const auto& mapEntry : this->questMap_)
+        {
+            if(mapEntry.second->getParentQuest() == nullptr && !mapEntry.second->isInactive(player))
+                numQuests++;
+        }
+        return numQuests;
+    }
+
+    /**
+    @brief
+        Get the index-th root quest of the input player.
+    @param player
+        The player.
+    @param index
+        The index of the root quest.
+    @return
+        Returns the index-th root quest of the input player.
+    */
+    Quest* QuestManager::getRootQuest(PlayerInfo* player, int index)
+    {
+        for(const auto& mapEntry : this->questMap_)
+        {
+            if(mapEntry.second->getParentQuest() == nullptr && !mapEntry.second->isInactive(player) && index-- == 0)
+                return mapEntry.second;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Get the number of sub-quest of an input Quest for the input player.
+    @param quest
+        The quest to get the sub-quests of.
+    @param player
+        The player.
+    @return
+        Returns the number of sub-quest of an input Quest for the input player.
+    */
+    int QuestManager::getNumSubQuests(Quest* quest, PlayerInfo* player)
+    {
+        if(quest == nullptr)
+            return this->getNumRootQuests(player);
+
+        std::list<Quest*> quests = quest->getSubQuestList();
+        int numQuests = 0;
+        for(Quest* subquest : quests)
+        {
+            if(!subquest->isInactive(player))
+                numQuests++;
+        }
+        return numQuests;
+    }
+
+    /**
+    @brief
+        Get the index-th sub-quest of the input Quest for the input player.
+    @param quest
+        The Quest to get the sub-quest of.
+    @param player
+        The player.
+    @param index
+        The index of the sub-quest.
+    */
+    Quest* QuestManager::getSubQuest(Quest* quest, PlayerInfo* player, int index)
+    {
+        if(quest == nullptr)
+            return this->getRootQuest(player, index);
+
+        std::list<Quest*> quests = quest->getSubQuestList();
+        for(Quest* subquest : quests)
+        {
+            if(!subquest->isInactive(player) && index-- == 0)
+                return quest;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Get the number of QuestHints of the input Quest for the input player.
+    @param quest
+        The quest to get the hints of.
+    @param player
+        The player.
+    @return
+        Returns the number of QuestHints of the input Quest for the input player.
+    */
+    int QuestManager::getNumHints(Quest* quest, PlayerInfo* player)
+    {
+        std::list<QuestHint*> hints = quest->getHintsList();
+        int numHints = 0;
+        for(QuestHint* hint : hints)
+        {
+            if(hint->isActive(player))
+                numHints++;
+        }
+        return numHints;
+    }
+
+    /**
+    @brief
+        Get the index-th QuestHint of the input Quest for the input player.
+    @param quest
+        The Quest to get the QuestHint of.
+    @param player
+        The player.
+    @param index
+        The index of the QuestHint.
+    @return
+        Returns a pointer to the index-th QuestHint of the input Quest for the input player.
+    */
+    QuestHint* QuestManager::getHints(Quest* quest, PlayerInfo* player, int index)
+    {
+        std::list<QuestHint*> hints = quest->getHintsList();
+        for(QuestHint* hint : hints)
+        {
+            if(hint->isActive(player) && index-- == 0)
+                return hint;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Get the parent-quest of the input Quest.
+    @param quest
+        The Quest to get the parent-quest of.
+    @return
+        Returns a pointer to the parent-quest of the input Quest.
+    */
+    Quest* QuestManager::getParentQuest(Quest* quest)
+    {
+        OrxAssert(quest, "The input Quest is nullptr.");
+        return quest->getParentQuest();
+    }
+
+    /**
+    @brief
+        Get the QuestDescription of the input Quest.
+    @param item
+        The Quest to get the QuestDescription of.
+    @return
+        Return a pointer ot the QuestDescription of the input Quest.
+    */
+    QuestDescription* QuestManager::getDescription(Quest* item)
+    {
+        OrxAssert(item, "The input Quest is nullptr.");
+        return item->getDescription();
+    }
+
+    /**
+    @brief
+        Get the QuestDescription of the input QuestHint.
+    @param item
+        The QuestHint to get the QuestDescription of.
+    @return
+        Returns a pointer to the QuestDescription of the input QuestHint.
+    */
+    QuestDescription* QuestManager::getDescription(QuestHint* item)
+    {
+        OrxAssert(item, "The input QuestHint is nullptr.");
+        return item->getDescription();
+    }
+
+    /**
+    @brief
+        Get the id of the input Quest.
+    @param item
+        The Quest to get the id of.
+    @return
+        Returns the id of the input Quest.
+    */
+    const std::string QuestManager::getId(Quest* item) const
+    {
+        OrxAssert(item, "The input Quest is nullptr.");
+        return item->getId();
+    }
+
+    /**
+    @brief
+        Get the id of the input QuestHint.
+    @param item
+        The QuestHint to get the id of.
+    @return
+        Returns the id of the input QuestHint.
+    */
+    const std::string QuestManager::getId(QuestHint* item) const
+    {
+        OrxAssert(item, "The input QuestHint is nullptr.");
+        return item->getId();
+    }
+
+    /**
+    @brief
+        Retrieve the player for a certain GUI.
+    @param guiName
+        The name of the GUI the player is retrieved for.
+    @return
+        Returns the player.
+    @todo
+        This very well might be outdated. So: Check if still needed, and update if necessary.
+    */
+    PlayerInfo* QuestManager::retrievePlayer(const std::string & guiName)
+    {
+        PlayerInfo* player = GUIManager::getInstance().getPlayer(guiName);
+        if(player == nullptr)
+        {
+            orxout(internal_error, context::quests) << "GUIOverlay with name '" << guiName << "' has no player." << endl;
+            return nullptr;
+        }
+
+        return player;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestManager.h	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file QuestManager.h
+    @brief Definition of the QuestManager class.
+    @ingroup Questsystem
+*/
+
+#ifndef _QuestManager_H__
+#define _QuestManager_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <list>
+#include <map>
+#include <string>
+
+#include "util/Singleton.h"
+
+namespace orxonox  // tolua_export
+{  // tolua_export
+
+    /**
+    @brief
+        Is a Singleton and manages @ref orxonox::Quest "Quests", by registering every @ref orxonox::Quest "Quest" / @ref orxonox::QuestHint "QuestHint" (through registerX()) and making them globally accessible (through findX()).
+        @ref orxonox::Quest "Quests" (and @ref orxonox::QuestHint "QuestHints") are registered in the QuestManager with their id, and can be accessed in the same way.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Questsystem
+    */
+    class _QuestsystemExport QuestManager  // tolua_export
+        : public Singleton<QuestManager>
+    { // tolua_export
+
+            friend class Singleton<QuestManager>;
+
+        public:
+            QuestManager();
+            virtual ~QuestManager();
+
+            //! Returns a reference to the single instance of the QuestManager.
+            static QuestManager& getInstance() { return Singleton<QuestManager>::getInstance(); } // tolua_export
+
+            // tolua_begin
+            int getNumRootQuests(orxonox::PlayerInfo* player); //!< Get the number of Quests the input player has, that are root quests.
+            Quest* getRootQuest(orxonox::PlayerInfo* player, int index); //!< Get the index-th root quest of the input player.
+
+            int getNumSubQuests(Quest* quest, orxonox::PlayerInfo* player); //!< Get the number of sub-quest of an input Quest for an input player.
+            Quest* getSubQuest(Quest* quest, orxonox::PlayerInfo* player, int index); //!< Get the index-th sub-quest of the input Quest for the input player.
+
+            int getNumHints(Quest* quest, orxonox::PlayerInfo* player); //!< Get the number of QuestHints of the input Quest for the input player.
+            QuestHint* getHints(Quest* quest, orxonox::PlayerInfo* player, int index); //!< Get the index-th QuestHint of the input Quest for the input player.
+
+            Quest* getParentQuest(Quest* quest); //!< Get the parent-quest of the input Quest.
+
+            QuestDescription* getDescription(Quest* item); //!< Get the QuestDescription of the input Quest.
+            QuestDescription* getDescription(QuestHint* item); //!< Get the QuestDescription of the input QuestHint.
+
+            const std::string getId(Quest* item) const; //!< Get the id of the input Quest.
+            const std::string getId(QuestHint* item) const; //!< Get the id of the input QuestHint.
+            // tolua_end
+
+            bool registerQuest(Quest* quest); //!< Registers a Quest in the QuestManager.
+            bool unregisterQuest(Quest* quest); //!< Unregisters a Quest in the QuestManager.
+            bool registerHint(QuestHint* hint); //!< Registers a QuestHint in the QuestManager.
+            bool unregisterHint(QuestHint* hint); //!< Unregisters a QuestHint in the QuestManager.
+
+            Quest* findQuest(const std::string & questId); //!< Returns the Quest with the input id.
+            QuestHint* findHint(const std::string & hintId); //!< Returns the QuestHint with the input id.
+
+        protected:
+            std::map<std::string, Quest*> & getQuests(void); //!< Retrieve all Quests.
+
+        private:
+            static QuestManager* singletonPtr_s;
+            PlayerInfo* retrievePlayer(const std::string & guiName); //!< Retrieve the player for a certain GUI.
+
+            std::map<std::string, Quest*> questMap_; //!< All Quests registered by their id's.
+            std::map<std::string, QuestHint*> hintMap_; //!< All QuestHints registered by their id's.
+
+    }; // tolua_export
+
+} // tolua_export
+
+#endif /* _QuestManager_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestsystemPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestsystemPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestsystemPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the quest system module
+@details
+    Updated: 19. September 2009
+    Total Files: 24
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <ctime> // 18
+
+#include <OgreMath.h>        // 16
+#include <OgreVector2.h>     // 16
+#include <OgreVector3.h>     // 16
+#include <OgreVector4.h>     // 16
+#include <OgreQuaternion.h>  // 16
+#include <OgreColourValue.h> // 16
+
+#include <tinyxml/ticpp.h>   // 14
+#include "util/Singleton.h"  // 13
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"   // 24
+#include "core/CoreIncludes.h" // 23
+
+///////////////////////////////////////////
+/////      Not so Stable Headers      /////
+///////////////////////////////////////////
+
+#include "core/command/Executor.h"     // 15
+//#include "core/XMLPort.h"    // 14
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/QuestsystemPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/QuestsystemPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/QuestsystemPrereqs.h	(revision 11817)
@@ -0,0 +1,88 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the questsystem module
+*/
+
+#ifndef _QuestsystemPrereqs_H__
+#define _QuestsystemPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(QUESTSYSTEM_STATIC_BUILD)
+#  ifdef QUESTSYSTEM_SHARED_BUILD
+#    define _QuestsystemExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _QuestsystemExport
+#    else
+#      define _QuestsystemExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _QuestsystemPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _QuestsystemExport  __attribute__ ((visibility("default")))
+#  define _QuestsystemPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _QuestsystemExport
+#  define _QuestsystemPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class AddQuest;
+    class AddQuestHint;
+    class AddReward;
+    class ChangeQuestStatus;
+    class CompleteQuest;
+    class FailQuest;
+    class GlobalQuest;
+    class LocalQuest;
+    class Quest;
+    class QuestDescription;
+    class QuestEffect;
+    class QuestEffectBeacon;
+    class QuestHint;
+    class QuestItem;
+    class QuestListener;
+    class QuestManager;
+}
+
+#endif /* _QuestsystemPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuest.cc	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file AddQuest.cc
+    @brief Implementation of the AddQuest class.
+*/
+
+#include "AddQuest.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Exception.h"
+
+#include "questsystem/Quest.h"
+#include "questsystem/QuestManager.h"
+
+namespace orxonox
+{
+    RegisterClass(AddQuest);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    AddQuest::AddQuest(Context* context) : ChangeQuestStatus(context)
+    {
+        RegisterObject(AddQuest);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    AddQuest::~AddQuest()
+    {
+    }
+
+    /**
+    @brief
+        Method for creating a AddQuest object through XML.
+    */
+    void AddQuest::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(AddQuest, XMLPort, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New AddQuest, with target Quest {" << this->getQuestId() << "}, created." << endl;
+    }
+
+    /**
+    @brief
+        Invokes the QuestEffect.
+    @param player
+        The player the QuestEffect is invoked on.
+    @return
+        Returns true if the QuestEffect was successfully invoked.
+    */
+    bool AddQuest::invoke(PlayerInfo* player)
+    {
+        assert(player);
+
+        orxout(verbose_more, context::quests) << "AddQuest on player: " << player << " ." << endl;
+
+        try
+        {
+            Quest* quest = QuestManager::getInstance().findQuest(this->getQuestId());
+            if(quest == nullptr || !quest->start(player))
+               return false;
+        }
+        catch(const orxonox::Exception& ex)
+        {
+            orxout(internal_warning, context::quests) << ex.getFullDescription() << endl;
+            return false;
+        }
+
+        orxout(verbose, context::quests) << "Quest {" << this->getQuestId() << "} successfully added to player: " << player << " ." << endl;
+        return true;
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuest.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file AddQuest.h
+    @brief Definition of the AddQuest class.
+    @ingroup QuestEffects
+*/
+
+#ifndef _AddQuest_H__
+#define _AddQuest_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+#include "ChangeQuestStatus.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Adds a @ref orxonox::Quest "Quest", resp. changes the @ref orxonox::Quest "Quests" status to active for the player invoking the @ref orxonox::Quest "Quest".
+
+        Creating an AddQuest through XML goes as follows:
+        @code
+        <AddQuest questId="id" />  //Where id identifies the Quest that should be added.
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup QuestEffects
+    */
+    class _QuestsystemExport AddQuest : public ChangeQuestStatus
+    {
+        public:
+        AddQuest(Context* context);
+        virtual ~AddQuest();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a AddQuest object through XML.
+
+        virtual bool invoke(PlayerInfo* player) override; //!< Invokes the QuestEffect.
+
+    };
+
+}
+
+#endif /* _AddQuest_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuestHint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuestHint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuestHint.cc	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file AddQuestHint.cc
+    @brief Implementation of the AddQuestHint class.
+*/
+
+#include "AddQuestHint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Exception.h"
+
+#include "questsystem/QuestHint.h"
+#include "questsystem/QuestManager.h"
+#include "questsystem/QuestItem.h"
+
+namespace orxonox
+{
+    RegisterClass(AddQuestHint);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    AddQuestHint::AddQuestHint(Context* context) : QuestEffect(context)
+    {
+        RegisterObject(AddQuestHint);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    AddQuestHint::~AddQuestHint()
+    {
+    }
+
+    /**
+    @brief
+        Method for creating a AddQuestHint object through XML.
+    */
+    void AddQuestHint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(AddQuestHint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(AddQuestHint, "hintId", setHintId, getHintId, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New AddQuestHint, with target QuestHint {" << this->getHintId() << "}, created." << endl;
+    }
+
+    /**
+    @brief
+        Sets the id of the QuestHint to be added to the player the QuestEffect is invoked on.
+    @param id
+        The QuestHint id.
+    @return
+        Returns true if successful.
+    */
+    bool AddQuestHint::setHintId(const std::string & id)
+    {
+        if(id == "")
+        {
+            orxout(internal_warning, context::quests) << "Invalid id. QuestItem id {" << id << "} could not be set." << endl;
+            return false;
+        }
+
+        this->hintId_ = id;
+        return true;
+    }
+
+    /**
+    @brief
+        Invokes the QuestEffect.
+    @param player
+        The player.
+    @return
+        Returns true if the QuestEffect was successfully invoked.
+    */
+    bool AddQuestHint::invoke(PlayerInfo* player)
+    {
+        assert(player);
+
+        orxout(verbose_more, context::quests) << "AddQuestHint on player: " << player << " ." << endl;
+
+        try
+        {
+            QuestHint* hint = QuestManager::getInstance().findHint(this->hintId_);
+            if(hint == nullptr || !hint->setActive(player))
+                return false;
+        }
+        catch(const Exception& e)
+        {
+           orxout(internal_warning, context::quests) << e.getFullDescription() << endl;
+           return false;
+        }
+
+        orxout(verbose, context::quests) << "QuestHint {" << this->getHintId() << "} successfully added to player: " << player << " ." << endl;
+        return true;
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuestHint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuestHint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddQuestHint.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file AddQuestHint.h
+    @brief Definition of the AddQuestHint class.
+    @ingroup QuestEffects
+*/
+
+#ifndef _AddQuestHint_H__
+#define _AddQuestHint_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <string>
+#include "questsystem/QuestEffect.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Adds a @ref orxonox::QuestHint "QuestHint", resp. activates the @ref orxonox::QuestHint "QuestHint" of the given id for the player the QuestEffect is invoked on.
+
+        Creating a AddQuestHint through XML goes as follows:
+        @code
+        <AddQuestHint hintId="id" />  //Where id identifies the QuestHint that should be added.
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup QuestEffects
+    */
+    class _QuestsystemExport AddQuestHint : public QuestEffect
+    {
+        public:
+            AddQuestHint(Context* context);
+            virtual ~AddQuestHint();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a AddQuestHint object through XML.
+
+            virtual bool invoke(PlayerInfo* player) override; //!< Invokes the QuestEffect.
+
+        private:
+            std::string hintId_; //!< The id of the QuestHint.
+
+            /**
+            @brief Returns the id of the QuestHint.
+            @return Returns the id of the QuestHint.
+            */
+            inline const std::string & getHintId(void) const
+                { return this->hintId_; }
+
+            bool setHintId(const std::string & id); //!< Sets the id of the QuestHint.
+
+    };
+
+}
+
+#endif /* _AddQuestHint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddReward.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddReward.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddReward.cc	(revision 11817)
@@ -0,0 +1,116 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file AddReward.cc
+    @brief Implementation of the AddReward class.
+*/
+
+#include "AddReward.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "interfaces/Rewardable.h"
+
+namespace orxonox
+{
+    RegisterClass(AddReward);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    AddReward::AddReward(Context* context) : QuestEffect(context)
+    {
+        RegisterObject(AddReward);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    AddReward::~AddReward()
+    {
+
+    }
+
+    /**
+        Method for creating a AddReward object through XML.
+    */
+    void AddReward::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(AddReward, XMLPort, xmlelement, mode);
+
+        XMLPortObject(AddReward, Rewardable, "", addRewardable, getRewardables, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New AddReward, with " << this->rewards_.size() << " Rewardables created." << endl;
+    }
+
+    /**
+    @brief
+        Returns the Rewardable object at the given index.
+    @param index
+        The index.
+    @return
+        Returns a pointer to the Rewardable object at the given index.
+    */
+    const Rewardable* AddReward::getRewardables(unsigned int index) const
+    {
+        int i = index;
+        for (Rewardable* reward : this->rewards_)
+        {
+            if(i == 0)
+               return reward;
+            i--;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Invokes the QuestEffect.
+    @param player
+        The player.
+    @return
+        Returns true if the QuestEffect was invoked successfully.
+    */
+    bool AddReward::invoke(PlayerInfo* player)
+    {
+        orxout(verbose_more, context::quests) << "AddReward on player: " << player << " ." << endl;
+
+        bool temp = true;
+        for (Rewardable* reward : this->rewards_)
+            temp = temp && reward->reward(player);
+
+        orxout(verbose, context::quests) << "Rewardable successfully added to player." << player << " ." << endl;
+
+        return temp;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddReward.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddReward.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/AddReward.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file AddReward.h
+    @brief Definition of the AddReward class.
+    @ingroup QuestEffects
+*/
+
+#ifndef _AddReward_H__
+#define _AddReward_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <list>
+#include "questsystem/QuestEffect.h"
+
+namespace orxonox
+{
+    
+    /**
+    @brief
+        Adds a list of @ref orxonox::Rewardable "Rewardables" to a player.
+
+        Creating a AddReward through XML goes as follows:
+        @code
+        <AddReward>
+            <Rewardable /> //A list of Rewardable objects to be rewarded the player, see the specific Rewardables for their respective XML representations.
+            ...
+            <Rewardable />
+        </AddReward>
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup QuestEffects
+    */
+    class _QuestsystemExport AddReward : public QuestEffect
+    {
+        public:
+            AddReward(Context* context);
+            virtual ~AddReward();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a AddReward object through XML.
+
+            virtual bool invoke(PlayerInfo* player) override; //!< Invokes the QuestEffect.
+
+        private:
+            std::list<Rewardable*> rewards_; //!< A list of Rewardables to be added to the player invoking the QuestEffect.
+
+            /**
+            @brief Add a Rewardable object to the list of objects to be awarded to the player invoking the QuestEffect.
+            @param reward Pointer to the Rewardable to be added.
+            */
+            inline void addRewardable(Rewardable* reward)
+                { this->rewards_.push_back(reward); }
+
+            const Rewardable* getRewardables(unsigned int index) const; //!< Returns the Rewardable object at the given index.
+
+    };
+
+}
+
+#endif /* _AddReward_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,9 @@
+ADD_SOURCE_FILES(QUESTSYSTEM_SRC_FILES
+  AddQuest.cc
+  AddQuestHint.cc
+  AddReward.cc
+  ChangeQuestStatus.cc
+  CompleteQuest.cc
+  FailQuest.cc
+)
+
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/ChangeQuestStatus.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/ChangeQuestStatus.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/ChangeQuestStatus.cc	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ChangeQuestStatus.cc
+    @brief Implementation of the ChangeQuestStatus class.
+    @ingroup QuestEffects
+*/
+
+#include "ChangeQuestStatus.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "questsystem/QuestItem.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(ChangeQuestStatus).inheritsFrom<QuestEffect>();
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    ChangeQuestStatus::ChangeQuestStatus(Context* context) : QuestEffect(context)
+    {
+        RegisterObject(ChangeQuestStatus);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    ChangeQuestStatus::~ChangeQuestStatus()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a ChangeQuestStatus object through XML.
+    */
+    void ChangeQuestStatus::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ChangeQuestStatus, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ChangeQuestStatus, "questId", setQuestId, getQuestId, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Sets the id of the Quest the Questffect changes the status of.
+    @param id
+        The id of the Quest.
+    @return
+        Returns true if successful.
+    */
+    bool ChangeQuestStatus::setQuestId(const std::string & id)
+    {
+        if(id == "")
+        {
+            orxout(internal_warning, context::quests) << "Invalid id. QuestItem id {" << id << "} could not be set." << endl;
+            return false;
+        }
+
+        this->questId_ = id;
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/ChangeQuestStatus.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/ChangeQuestStatus.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/ChangeQuestStatus.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ChangeQuestStatus.h
+    @brief Definition of the ChangeQuestStatus class.
+    @ingroup QuestEffects
+*/
+
+#ifndef _ChangeQuestStatus_H__
+#define _ChangeQuestStatus_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+
+#include <string>
+#include "questsystem/QuestEffect.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A QuestEffect which changes the status of a specified @ref orxonox::Quest "Quest" for the player invoking the QuestEffect.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup QuestEffects
+    */
+    class _QuestsystemExport ChangeQuestStatus : public QuestEffect
+    {
+        public:
+            ChangeQuestStatus(Context* context);
+            virtual ~ChangeQuestStatus();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a ChangeQuestStatus object through XML.
+
+        protected:
+            /**
+            @brief Returns the id of the Quest.
+            @return Returns the id of the Quest.
+            */
+            inline const std::string & getQuestId(void) const
+                { return this->questId_; }
+
+        private:
+            std::string questId_; //!< The id of the Quest the status should be changed of.
+
+            bool setQuestId(const std::string & id); //!< Sets the id of the Quest.
+
+    };
+
+}
+
+#endif /* _ChangeQuestStatus_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CompleteQuest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CompleteQuest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CompleteQuest.cc	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CompleteQuest.cc
+    @brief Implementation of the CompleteQuest class.
+*/
+
+#include "CompleteQuest.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "questsystem/Quest.h"
+#include "questsystem/QuestManager.h"
+
+namespace orxonox
+{
+    RegisterClass(CompleteQuest);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    CompleteQuest::CompleteQuest(Context* context) : ChangeQuestStatus(context)
+    {
+        RegisterObject(CompleteQuest);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    CompleteQuest::~CompleteQuest()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a CompleteQuest object through XML.
+    */
+    void CompleteQuest::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CompleteQuest, XMLPort, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New CompleteQuest, with target Quest {" << this->getQuestId() << "}, created." << endl;
+    }
+
+    /**
+    @brief
+        Invokes the QuestEffect.
+    @param player
+        The player the QuestEffect is invoked on.
+    @return
+        Returns true if the QuestEffect was invoked successfully.
+    */
+    bool CompleteQuest::invoke(PlayerInfo* player)
+    {
+        assert(player);
+
+        orxout(verbose_more, context::quests) << "CompleteQuest on player: " << player << " ." << endl;
+
+        Quest* quest;
+
+        try
+        {
+            quest = QuestManager::getInstance().findQuest(this->getQuestId());
+            if(quest == nullptr || !quest->complete(player))
+               return false;
+        }
+        catch(const Exception& e)
+        {
+            orxout(internal_warning, context::quests) << e.getFullDescription() << endl;
+            return false;
+        }
+
+        orxout(verbose, context::quests) << "Quest {" << quest->getId() << "} successfully completed by player: " << player << " ." << endl;
+        return true;
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CompleteQuest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CompleteQuest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/CompleteQuest.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CompleteQuest.h
+    @brief Definition of the CompleteQuest class.
+    @ingroup QuestEffects
+*/
+
+#ifndef _CompleteQuest_H__
+#define _CompleteQuest_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+#include "ChangeQuestStatus.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Completes a @ref orxonox::Quest "Quest" (with a specified id) for the player invoking the QuestEffect.
+
+        Creating a CompleteQuest through XML goes as follows:
+        @code
+        <CompleteQuest questId="id" />  //Where id identifies the Quest that should be completed.
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup QuestEffects
+    */
+    class _QuestsystemExport CompleteQuest : public ChangeQuestStatus
+    {
+        public:
+            CompleteQuest(Context* context);
+            virtual ~CompleteQuest();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a CompleteQuest object through XML.
+
+            virtual bool invoke(PlayerInfo* player) override; //!< Invokes the QuestEffect.
+
+    };
+
+}
+
+#endif /* _CompleteQuest_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/FailQuest.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/FailQuest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/FailQuest.cc	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FailQuest.cc
+    @brief Implementation of the FailQuest class.
+*/
+
+#include "FailQuest.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "questsystem/Quest.h"
+#include "questsystem/QuestManager.h"
+
+namespace orxonox
+{
+    RegisterClass(FailQuest);
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    FailQuest::FailQuest(Context* context) : ChangeQuestStatus(context)
+    {
+        RegisterObject(FailQuest);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    FailQuest::~FailQuest()
+    {
+
+    }
+
+    /**
+    @brief
+        Method for creating a FailQuest object through XML.
+    */
+    void FailQuest::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FailQuest, XMLPort, xmlelement, mode);
+
+        orxout(verbose, context::quests) << "New FailQuest, with target Quest {" << this->getQuestId() << "}, created." << endl;
+    }
+
+    /**
+    @brief
+        Invokes the QuestEffect.
+    @param player
+        The player the QuestEffect is invoked on.
+    @return
+        Returns true if the QuestEffect was invoked successfully.
+    */
+    bool FailQuest::invoke(PlayerInfo* player)
+    {
+        assert(player);
+
+        orxout(verbose, context::quests) << "FailQuest on player: " << player << " ." << endl;
+
+        Quest* quest;
+        try
+        {
+            quest = QuestManager::getInstance().findQuest(this->getQuestId());
+            if(quest == nullptr || !quest->fail(player))
+               return false;
+        }
+        catch(const Exception& e)
+        {
+            orxout(internal_warning, context::quests) << e.getFullDescription() << endl;
+            return false;
+        }
+
+        orxout(verbose, context::quests) << "Quest {" << quest->getId() << "} failed by player: " << player << " ." << endl;
+        return true;
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/questsystem/effects/FailQuest.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/questsystem/effects/FailQuest.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/questsystem/effects/FailQuest.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FailQuest.h
+    @brief Definition of the FailQuest class.
+    @ingroup QuestEffects
+*/
+
+#ifndef _FailQuest_H__
+#define _FailQuest_H__
+
+#include "questsystem/QuestsystemPrereqs.h"
+#include "ChangeQuestStatus.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Fails a @ref orxonox::Quest "Quest" (with a specified id) for the player invoking the QuestEffect.
+
+        Creating a FailQuest through XML goes as follows:
+        @code
+        <FailQuest questId="id" />  //Where id identifies the Quest that should be failed.
+        @endcode
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup QuestEffects
+    */
+    class _QuestsystemExport FailQuest : public ChangeQuestStatus
+    {
+        public:
+            FailQuest(Context* context);
+            virtual ~FailQuest();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a FailQuest object through XML.
+
+            virtual bool invoke(PlayerInfo* player) override; //!< Invokes the QuestEffect.
+
+    };
+
+}
+
+#endif /* _FailQuest_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,26 @@
+SET_SOURCE_FILES(SOB_SRC_FILES
+
+  SOBCenterpoint.cc
+  SOB.cc
+  SOBFigure.cc
+  SOBItem.cc
+  SOBQBlock.cc
+  SOBMushroom.cc
+  SOBHUDInfo.cc
+  SOBGumba.cc
+  SOBFireball.cc
+  SOBFlagstone.cc
+  SOBCastlestone.cc
+  SOBCoin.cc
+  SOBGumbaBoss.cc
+
+)
+
+ORXONOX_ADD_LIBRARY(superorxobros
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+  SOURCE_FILES ${SOB_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOB.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOB.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOB.cc	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOB.cc
+    @brief Implementation of the SOB class.
+*/
+
+#include "SOB.h"
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Game.h"
+#include "gamestates/GSLevel.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "SOBCenterpoint.h"
+#include "SOBFigure.h"
+#include "graphics/Camera.h"
+#include "Highscore.h"
+
+
+
+namespace orxonox
+{
+    bool newHighscore=0;
+    RegisterUnloadableClass(SOB);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    SOB::SOB(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(SOB);
+
+        this->center_ = nullptr;
+        figure_ = nullptr;
+        setHUDTemplate("SOBHUD");
+        coins_=0;
+        points_=0;
+        timeLeft_=400.0;
+        done_ = true;
+        newHighscore = false;
+        lvl_ = 1;
+
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up, if initialized.
+    */
+    SOB::~SOB()
+    {
+    }
+
+    void SOB::start()
+    {
+        if (center_ != nullptr) // There needs to be a SOBCenterpoint, i.e. the area the game takes place.
+        {
+            if (figure_ == nullptr)
+            {
+                figure_ = new SOBFigure(center_->getContext());     //add a new instance of a player to the game
+                figure_->addTemplate(center_->getFigureTemplate());
+            }
+
+            figure_->setPosition(0, 0, 0);
+        }
+        else // If no centerpoint was specified, an error is thrown and the level is exited.
+        {
+            orxout(internal_error) << "SOB: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+
+        // Call start for the parent class.
+        Gametype::start();
+
+    }
+
+    void SOB::end()
+    {
+        GSLevel::startMainMenu();
+        Deathmatch::end();
+}
+
+    void SOB::restart() {
+        // HACK - only method I found to simply reload the level
+        Game::getInstance().popState();
+        Game::getInstance().popState();
+        Game::getInstance().requestStates("standalone, level");
+
+        
+    }
+    void SOB::spawnPlayer(PlayerInfo* player)
+    {
+        assert(player);
+
+        if (figure_->getPlayer() == nullptr)
+        {
+            player->startControl(figure_); //Give the control of the instance player to the real person
+            players_[player].state_ = PlayerState::Alive;
+            done_ = false;
+        }
+    }
+
+    PlayerInfo* SOB::getPlayer() const
+    {
+        if (this->figure_ != nullptr)
+        {
+            return this->figure_->getPlayer();
+        }
+        else
+        {
+            return nullptr;
+        }
+    }
+
+    void SOB::tick(float dt)
+    {
+        SUPER(SOB, tick, dt);
+
+        //If player has reached end of level
+        if (this->figure_ != nullptr && figure_->lvlEnded_) {
+            std::stringstream a;
+            if(!newHighscore){
+                a << "Nice! " << getPoints() << " Points in " << (400-getTimeLeft())/2 <<"s.\n\nPress <Space> to restart";
+            }
+            else{
+                a << "Congrats, new Highscore! " << getPoints() << " Points in " << (400-getTimeLeft())/2 <<"s.\n\nPress <Space> to restart";
+            }
+            info_ =a.str();
+
+        //If player has died
+        } else if (this->figure_ != nullptr && figure_->dead_) {
+            info_ = "Game over. Press <Space> to restart";
+        }
+        
+
+        //Kill the player if time is up
+        if (this->figure_ != nullptr && timeLeft_ <= 0)
+            this->figure_->dead_ = true;
+        //The time on the HUD
+        if (!done_)
+            timeLeft_-=dt*2.5f;
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOB.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOB.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOB.h	(revision 11817)
@@ -0,0 +1,125 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOB.h
+    @brief Declaration of the SOB class.
+*/
+
+#ifndef _SOB_H__
+#define _SOB_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "gametypes/Deathmatch.h"
+#include "SOBCenterpoint.h"
+
+namespace orxonox
+{
+
+    class _SOBExport SOB : public Deathmatch
+    {
+    public:
+            SOB(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~SOB(); //!< Destructor. Cleans up, if initialized.
+            virtual void tick(float dt) override;
+
+
+            void setCenterpoint(SOBCenterpoint* center)
+            { this->center_ = center; }
+            virtual void start() override;
+            virtual void end() override;
+            virtual void spawnPlayer(PlayerInfo* player) override;
+            PlayerInfo* getPlayer() const;
+
+            void restart();
+
+            //Functions for points and coins
+            int getPoints() {
+                return points_;
+            }
+            int getCoins() {
+                return coins_;
+            }
+            void addCoin() {
+                ++coins_;
+                points_+=200;
+            }
+            void addMushroom() {
+                points_+=1000;
+            }
+            void addGumba() {
+                points_+=100;
+            }
+            void addGumbaBoss() {
+                points_+=5000;
+            }
+            void addPoints(int poi) {
+                points_+=poi;
+            }
+            int getTimeLeft() {
+                return (int) timeLeft_;
+            }
+            std::string getInfoText() {
+                return info_;
+            }    
+            void setDone(bool tr) {
+                done_ = tr;
+            }
+
+
+            //Not used yet - placed if somebody wants to develop lvl 1-2 etc
+            void setLvl(int lvl) {
+                lvl_ = lvl;
+            }
+            int getLvl() {
+                return lvl_;
+            }
+            virtual void playerEntered(PlayerInfo* player) override
+            {
+                Gametype::playerEntered(player);
+            }  
+
+            WeakPtr<SOBCenterpoint> center_;
+            bool newHighscore;
+
+        protected:
+
+
+            WeakPtr<SOBFigure> figure_;
+            int points_;
+            int coins_;
+            float timeLeft_;
+            bool done_;
+            int lvl_;
+            std::string info_;
+
+
+        };
+    }
+
+#endif /* _SOB_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCastlestone.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCastlestone.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCastlestone.cc	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBCastlestone.cc
+    @brief Mainly used to guide the player into the castle after he has touched the flag and the control goes to the game
+*/
+
+#include "SOBCastlestone.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "util/Output.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SOBCastlestone);
+
+    SOBCastlestone::SOBCastlestone(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(SOBCastlestone);
+        setAngularFactor(0.0);
+        this->enableCollisionCallback();
+        hasCollided_=false;
+    
+    }
+
+    bool SOBCastlestone::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+        return true;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCastlestone.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCastlestone.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCastlestone.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBCastlestone.h
+    @brief Declaration of the SOBCastlestone class.
+*/
+
+#ifndef _SOBCastlestone_H__
+#define _SOBCastlestone_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBCastlestone : public StaticEntity
+    {
+    public:
+        SOBCastlestone(Context* context);
+        virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+        bool hasCollided_;
+        
+    };
+}
+
+#endif /* _SOBCastlestone_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCenterpoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCenterpoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCenterpoint.cc	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBCenterpoint.cc
+    @brief The SOBCenterpoint is a StaticEntity which represents the level of the minigame. 
+*/
+
+#include "SOBCenterpoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOB.h"
+
+namespace orxonox
+{
+    RegisterClass(SOBCenterpoint);
+
+    SOBCenterpoint::SOBCenterpoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(SOBCenterpoint);
+        checkGametype();
+    }
+
+    void SOBCenterpoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBCenterpoint, XMLPort, xmlelement, mode);
+
+      
+        
+        XMLPortParam(SOBCenterpoint, "cameraOffset", setCameraOffset, getCameraOffset, xmlelement, mode);
+        
+        XMLPortParam(SOBCenterpoint, "figureTemplate", setFigureTemplate, getFigureTemplate, xmlelement, mode);
+        
+    }
+
+    void SOBCenterpoint::checkGametype()
+    {
+        if (getGametype() != nullptr && this->getGametype()->isA(Class(SOB)))
+        {
+            SOB* SOBGametype = orxonox_cast<SOB*>(this->getGametype());
+            SOBGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCenterpoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCenterpoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCenterpoint.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+#ifndef _SOBCenterpoint_H__
+#define _SOBCenterpoint_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    
+    /**
+    @brief
+        @brief The SOBCenterpoint is a StaticEntity which represents the level of the minigame. Everybody used it so I used it too, do not ask my why..
+    */
+    class _SOBExport SOBCenterpoint : public StaticEntity
+    {
+        public:
+            SOBCenterpoint(Context* context); //!< Constructor. Registers and initializes the object and checks whether the gametype is actually SOB.
+            virtual ~SOBCenterpoint() {}
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method to create a SOBCenterpoint through XML.
+            
+            void setFigureTemplate(const std::string& newTemplate)
+                { this->figureTemplate_ = newTemplate;
+                }
+            const std::string& getFigureTemplate() const
+                { return this->figureTemplate_; }
+            
+
+            void setCameraOffset(const float cameraOffset)
+                { this->cameraOffset_ = cameraOffset; }
+            float getCameraOffset() const
+                { return cameraOffset_; }
+
+
+        private:
+            void checkGametype();
+           
+            std::string figureTemplate_;
+    
+       
+            float cameraOffset_;
+    };
+}
+
+#endif /* _SOBCenterpoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCoin.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCoin.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCoin.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBCoin.cc
+    @brief This is the object that appears when player hits a QBlock with type coin - it should be a coin floating ontop of the QBlock
+*/
+
+#include "SOBCoin.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "util/Output.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SOBCoin);
+
+    SOBCoin::SOBCoin(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(SOBCoin);
+        setAngularFactor(0.0);
+
+        speed_ = 0;
+        lifetime_ = 0;
+    }
+
+    
+    void SOBCoin::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBCoin, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBCoin, "lifetime", setLifetime, getLifetime, xmlelement, mode);
+        XMLPortParam(SOBCoin, "speed", setSpeed, getSpeed, xmlelement, mode);
+
+    }
+
+
+    void SOBCoin::tick(float dt)
+    {
+        SUPER(SOBCoin, tick, dt);
+
+        lifetime_-=dt;
+
+        if (lifetime_ < 0) {
+            destroyLater();
+        }
+
+        Vector3 velocity = getVelocity();
+        velocity.z = speed_;
+        setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() + 2*dt*Radian(6));
+        setVelocity(velocity);
+
+
+
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCoin.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCoin.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBCoin.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBCoin.h
+    @brief Declaration of the SOBCoin class.
+    @ingroup SOB
+*/
+
+#ifndef _SOBCoin_H__
+#define _SOBCoin_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBCoin : public MovableEntity
+    {
+    public:
+        SOBCoin(Context* context);
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void tick(float dt) override;
+
+
+        void setLifetime(const float lt)
+        { this->lifetime_ = lt; }
+        float getLifetime() const
+        { return lifetime_; }
+        void setSpeed(const float lt)
+        { this->speed_ = lt; }
+        float getSpeed() const
+        { return speed_; }
+
+
+    protected:
+
+        float lifetime_;
+        float speed_;
+
+    };
+}
+
+#endif /* _SOBCoin_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFigure.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFigure.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFigure.cc	(revision 11817)
@@ -0,0 +1,497 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      Noah Zarro
+ *      Theo von Arx
+ *      
+ *
+ */
+
+/**
+    @file SOBFigure.cc
+    @brief This class represents your figure when you play the minigame. Here the movement of the figure, activating items, ... are handled.
+*/
+
+#include "SOBFigure.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/Model.h"
+#include "graphics/Camera.h"
+#include "graphics/ParticleSpawner.h"
+#include <OgreMath.h>
+
+#include "SOBMushroom.h"
+#include "SOBGumba.h"
+#include "SOBGumbaBoss.h"
+#include "SOBFireball.h"
+#include "SOB.h"
+#include "SOBFlagstone.h"
+#include "SOBCastlestone.h"
+#include "SOBFireball.h"
+#include "Highscore.h"
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+
+namespace orxonox
+{
+    RegisterClass(SOBFigure);
+
+    SOBFigure::SOBFigure(Context* context) : ControllableEntity(context)
+    {
+        RegisterObject(SOBFigure);
+
+        // initialize variables
+        gravityAcceleration_ = 350.0;
+
+        //Vars for movement of player
+        moveUpPressed_      = false;
+        moveDownPressed_    = false;
+        moveLeftPressed_    = false;
+        moveRightPressed_    = false;
+        firePressed_        = false;
+        collDisZ_           = 0;
+
+        //Times and turning
+        timeSinceLastFire_  = 0.0;
+        lastSpeed_z         = 0.0;
+        timeCounter_        = 0;
+
+        //Properties of player
+
+        isColliding_        = true;
+        particlespawner_    = NULL;
+
+        //Properties of players life
+        predead_            = false;
+        dead_               = false;
+        lvlEnded_           = false;
+        reachedLvlEndState_ = 0;
+
+        // Properties concerning PowerUps and items
+        PowerUpCounter_     = 0;
+        maxPowerUp_         = 2;
+        FireballPower       = 2;
+        //Properties of fireing Fireballs, NOTE! fireballs are fired with the moveUP Key, not with the fire key
+        fireallowed_        = true;
+        firecooldown_       = 0;
+
+        
+        setAngularFactor(0.0); //Means player doesn't turn on collision, so he doesn't fall over while walking over the ground
+        this->enableCollisionCallback(); // Turns on that on every collision function collidesAgainst is executed
+    }
+
+
+
+    bool SOBFigure::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+        //Inform tick fct that player is colliding and tell him how far away the collision point is from player middle point in z dir
+        isColliding_ = true;
+        collDisZ_ = getPosition().z - contactPoint.getPositionWorldOnB().getZ();
+
+
+        //Orxocast returns object with casted type if otherObject has that class, and if not a nullptr
+        SOBMushroom*    mush        = orxonox_cast<SOBMushroom*>    (otherObject);
+        SOBGumba*       gumba       = orxonox_cast<SOBGumba*>       (otherObject);
+        SOBGumbaBoss*   gumbaBoss   = orxonox_cast<SOBGumbaBoss*>   (otherObject);
+        SOBFlagstone*   flagstone   = orxonox_cast<SOBFlagstone*>   (otherObject);
+        SOBCastlestone* castlestone = orxonox_cast<SOBCastlestone*> (otherObject);
+        SOBFireball*    fireball    = orxonox_cast<SOBFireball*>    (otherObject);
+        SOB* SOBGame                = orxonox_cast<SOB*>            (getGametype()); 
+
+
+        //Check if otherObject is a powerup-mushroom
+        if (mush != nullptr && !(mush->hasCollided_)) {
+            otherObject->destroyLater();
+
+            PowerUpCounter_++;
+            if(PowerUpCounter_ > maxPowerUp_)   PowerUpCounter_ = maxPowerUp_; // you had already the max
+            else                                this->changeClothes();
+
+            SOBGame->addMushroom(); // Tell the gametype to increase points
+            mush->hasCollided_ = true; // needed because of destroyLater takes some time and player should receive points only once
+            
+            
+        }
+
+        
+
+        //Check if otherObject is a Gumba (that walking enemies)
+
+         else if (gumba != nullptr && gumbaBoss == nullptr && !(gumba->hasCollided_)) {
+
+            //If player jumps on its head, kill the Gumba, else, kill the player
+            if (getVelocity().z >= -20) {
+                // If player hasn't a power up, he dies. Else he shrinks and the gumba dies.
+                if(PowerUpCounter_ == 0){
+                    this->die();
+                } 
+                else{
+                    PowerUpCounter_--;
+                    this->changeClothes();
+
+                    gumba->destroyLater();
+                    gumba->hasCollided_ = true;
+                }
+
+          } else {
+            gumba->destroyLater();
+            gumba->hasCollided_ = true;
+            SOBGame->addGumba();
+
+
+            }
+        }
+        else if (gumbaBoss != nullptr && !(gumbaBoss->hasCollided_)) {
+            if (getVelocity().z >= -20) {
+                // If player hasn't a power up, he dies. Else he dies directly.
+                this->die(); 
+            }
+
+            else {
+                gumbaBoss->destroyLater();
+                gumbaBoss->hasCollided_ = true;
+                SOBGame->addGumbaBoss();
+                }
+        }
+        else if (fireball != nullptr && !(fireball->hasCollided_)){
+            if(PowerUpCounter_ == 0){
+                    this->die();
+                } 
+            PowerUpCounter_--;
+            this->changeClothes();
+            fireball->destroyLater();
+        }
+
+    //Purpose is that if player hits the flag, he should walk into the castle at the end of the level. For that we use SOBCastlestone
+    if (reachedLvlEndState_ == 0 && flagstone != nullptr && !(flagstone->hasCollided_)) {
+        flagstone->hasCollided_ = true;
+        reachedLvlEndState_ = 1;
+
+        SOBGame->setDone(true);
+        SOBGame->addPoints(flagstone->getPoints());
+        
+
+    }
+    if (castlestone != nullptr && !(castlestone->hasCollided_)) {
+        castlestone->hasCollided_ = true;
+        reachedLvlEndState_++;
+
+    }
+
+    return true;
+}
+
+
+//Self implemented sign function that returns either 1 or -1 (and never 0)
+int SOBFigure::sgn(float x) {
+    if (x < 0.0) return -1;
+    return 1;
+}
+
+//Function to spawn the Fireball
+void SOBFigure::spawnFireball() {
+        SOBCenterpoint* center_ = ((SOB*)getGametype())->center_;
+
+         SOBFireball* ball = new SOBFireball(center_->getContext());
+         Vector3 spawnpos = this->getWorldPosition();
+         spawnpos.z += 0;
+
+        if (ball != nullptr && center_ != nullptr)
+        {
+            ball->addTemplate("fireball");
+            bool direction = ((this->getWorldOrientation().getRoll().valueRadians())>-1.6&&(this->getWorldOrientation().getRoll().valueRadians()<1.6));
+            ball->setDirection(direction);
+            if(direction)
+            {
+                spawnpos.x+=10;
+            }
+            else
+            {
+                spawnpos.x-=10;
+            }
+            ball->setPosition(spawnpos);
+
+        }
+     }
+
+//For those of you who don't have an idea: the tick function is called about 50 times/sec
+void SOBFigure::tick(float dt)
+{
+    SUPER(SOBFigure, tick, dt);
+
+
+    bool inputAllowed = true;
+    //SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
+
+    //the particle spawner that generates the fire from the backpack when pressed
+    if (particlespawner_ == NULL) {
+        for (WorldEntity* object : this->getAttachedObjects())
+        {
+           if (object->isA(Class(ParticleSpawner)))
+            particlespawner_ = object;
+        }
+
+    }
+    
+
+
+    //Behavior on level end - this is like described above for the movement from the player when hit the flag. He moves then into the castle
+    if (reachedLvlEndState_ != 0) {
+        timeCounter_+= dt;
+        inputAllowed = false;
+    }
+    if (reachedLvlEndState_ == 1 && timeCounter_ >= 1.5) {
+        timeCounter_ = 0;
+        reachedLvlEndState_ = 2;
+    }
+
+
+    //if input blocked, then cancel every movement operation
+    if (!inputAllowed) {
+        moveUpPressed_      = false;
+        moveDownPressed_    = false;
+        moveLeftPressed_    = false;
+        moveRightPressed_   = false;
+    }
+
+    //set the gravityto standard 350
+    if (firePressed_ == false) {
+        gravityAcceleration_ = 350.0;
+
+    }
+
+    if (hasLocalController())
+    {
+        SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
+        Vector3 velocity = getVelocity();
+        Vector3 position = getPosition();
+
+        if (!predead_)
+            velocity.y = 0;
+        //If player falls in a hole
+        if (position.z < -100) {
+            dead_ = true;
+            SOBGame->setDone(true);
+        }
+
+
+        if (dead_) {
+            velocity.x = 0;
+            velocity.z = 0;
+            setVelocity(velocity);
+           
+            if (firePressed_)
+                SOBGame->restart();
+            return;
+        }
+
+
+        int maxvelocity_x = 100;
+        int speedAddedPerTick = 5;
+        int camMaxOffset = 25;
+
+        timeSinceLastFire_ += dt;
+        lastSpeed_z = velocity.z;
+
+
+
+        //Handle the rocket fire from the jetpack
+        if (velocity.z > 40)
+            particlespawner_->setVisible(true); 
+        else
+            particlespawner_->setVisible(false); 
+        
+
+        //If player hits space and collides against an object under him then jump
+        if (inputAllowed && firePressed_ && isColliding_ && (collDisZ_ >= 0 && collDisZ_ <+ 10)) {
+            gravityAcceleration_ = 350;
+            velocity.z = 175; 
+        }
+
+
+        //Left-right movement with acceleration and rotation
+        float rot = getOrientation().getRoll().valueDegrees();
+        if (moveRightPressed_) {
+            if (!(rot < 5.0 && -5.0 < rot))
+                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() - sgn(rot)*dt*Radian(6));
+
+            if (std::abs(velocity.x) < maxvelocity_x) {
+                velocity.x += speedAddedPerTick;
+
+            }
+        } else if (moveLeftPressed_) {
+            if (!(abs(rot) > 175.0 ))
+                setOrientation(Vector3::UNIT_Z, getOrientation().getRoll() + sgn(rot)*dt*Radian(6));
+
+
+
+            if (std::abs(velocity.x) < maxvelocity_x) {
+                velocity.x -= speedAddedPerTick;
+            }
+        } else {
+            velocity.x /= 1.1;
+        }
+
+        //If moveUp pressed, fire a fireball
+        if(moveUpPressed_ && (PowerUpCounter_ >= FireballPower) && fireallowed_)
+        {
+            spawnFireball();
+            fireallowed_  = false;
+            firecooldown_ = 0;
+        }
+
+        //Increase the firecooldown
+        if(firecooldown_> 0.5)
+        {
+            fireallowed_ = true;
+        }
+        if(!fireallowed_)
+        {
+            firecooldown_ += dt;
+        }
+
+        //Again another EndOfLevel behavior
+        if (reachedLvlEndState_ == 1)
+            velocity.x = -2;
+        if (reachedLvlEndState_ == 2)
+            velocity.x = 30;
+        if (reachedLvlEndState_ == 3) {
+            velocity.x = 0;
+            velocity.y = 20;
+            setOrientation(Vector3::UNIT_Z, Degree(90));
+        }
+        if (reachedLvlEndState_ == 4) {
+            //Highscore
+            if (Highscore::exists())
+            {
+                int score = SOBGame->getPoints();
+                bool isHighScore = Highscore::getInstance().storeScore("Super Orxo Bros.", score, this->getPlayer());
+                SOBGame->newHighscore = isHighScore;
+            }
+            lvlEnded_ = true;
+            dead_ = true;
+        }
+
+        //velocity = acc. * time
+        velocity.z -= gravityAcceleration_*dt;
+        setVelocity(velocity);
+
+
+        //Camera operation - the camera should always follow the player in a specific region
+        Camera* cam = getCamera();
+        Vector3 campos = cam->getPosition();
+
+        if (campos.x + camMaxOffset < position.x) {
+            campos.x = position.x - camMaxOffset;
+            cam->setPosition(campos);
+        }
+        if (campos.x - camMaxOffset > position.x) {
+            campos.x = position.x + camMaxOffset;
+            cam->setPosition(campos);
+        }
+
+    }
+
+    // Reset key variables
+    moveUpPressed_      = false;
+    moveDownPressed_    = false;
+    moveLeftPressed_    = false;
+    moveRightPressed_   = false;
+
+    isColliding_ = false;
+    collDisZ_ = 0;
+
+}
+
+
+
+
+
+//The following functions read the input of the player and then set the bools for the movement
+void SOBFigure::moveFrontBack(const Vector2& value)
+{
+    if (value.x > 0)
+    {
+        moveUpPressed_ = true;
+        moveDownPressed_ = false;
+    }
+    else
+    {
+        moveUpPressed_ = false;
+        moveDownPressed_ = true;
+    }
+}
+
+void SOBFigure::moveRightLeft(const Vector2& value)
+{
+    if (value.x > 0)
+    {
+        moveLeftPressed_ = false;
+        moveRightPressed_ = true;
+    }
+    else
+    {
+        moveLeftPressed_ = true;
+        moveRightPressed_ = false;
+    }
+}
+
+void SOBFigure::boost(bool boost)
+{
+    firePressed_ = boost;
+}
+
+
+
+// PRE: name is an existing name of a material. Example orxo_material for orxo_material.material in data_extern/materials
+//      !!! PowerUpCounter_ has to be modified before changing the clothes!!!
+// POST: clothes of body of player are changed to name
+void SOBFigure::changeClothes(){
+            // clothes: white (basic), red (one PowerUp), orange (Fireball enabled)
+            std::string clothes[] = {"orxo_material", "orxo_material_gross", "orxo_material_fire"};
+
+            std::set<WorldEntity*> attachedObjects = this->getAttachedObjects();
+            std::set<WorldEntity*>::iterator it;
+            for (it = attachedObjects.begin(); it != attachedObjects.end(); ++it)
+            {
+                Model* FiguresModel = orxonox_cast<Model*>(*it);
+                if (FiguresModel != nullptr)
+                {
+                    FiguresModel->setSubMaterial(clothes[PowerUpCounter_] , 4); // 4 is the body
+                }
+            }   
+}
+// PRE:
+// POST: Player jumps out of the game, game is finished and can be restarted.
+void SOBFigure::die(){
+    Vector3 vel = getVelocity();
+    vel.y = -80;
+    vel.z = 200;
+    setVelocity(vel);
+    predead_= true; 
+    SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
+    SOBGame->setDone(true);
+}
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFigure.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFigure.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFigure.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+#ifndef _SOBFigure_H__
+#define _SOBFigure_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/ControllableEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBFigure : public ControllableEntity
+    {
+    public:
+            SOBFigure(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~SOBFigure() {}
+            virtual void tick(float dt) override;
+            virtual void moveFrontBack(const Vector2& value) override; //!< Overloaded the function to steer the figure up and down.
+            virtual void moveRightLeft(const Vector2& value) override; //!< Overloaded the function to steer the figure up and down.
+            virtual void boost(bool boost) override;
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            void changeClothes();
+            void spawnFireball();
+            void die();
+
+            bool dead_;
+            bool predead_;
+            bool lvlEnded_;
+
+        private:
+
+            //Soooo many declarations
+            bool fireallowed_;
+
+            bool moveUpPressed_;
+            bool moveDownPressed_;
+            bool moveLeftPressed_;
+            bool moveRightPressed_;
+            bool firePressed_;
+            float gravityAcceleration_;
+            float timeSinceLastFire_;
+            float lastSpeed_z;
+            float firecooldown_;
+            bool isColliding_;
+            WorldEntity* particlespawner_;
+            int PowerUpCounter_;
+            int maxPowerUp_;
+            int FireballPower;
+            int sgn(float x);
+            int reachedLvlEndState_;
+            float timeCounter_;
+            float collDisZ_;
+
+
+            
+
+        };
+    }
+
+#endif /* _SOBFigure_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFireball.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFireball.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFireball.cc	(revision 11817)
@@ -0,0 +1,191 @@
+    /*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Theo von Arx
+ *      Noah Zarro
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBFireball.cc
+    @brief Fireballs are the Projectile of the Fireflower Powerup
+*/
+
+#include "SOBFireball.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "SOBGumba.h"
+#include "SOBGumbaBoss.h"    
+#include "SOB.h"    
+#include "util/Output.h"
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+#include "graphics/ParticleSpawner.h"
+
+
+
+
+namespace orxonox
+{
+    RegisterClass(SOBFireball);
+
+    SOBFireball::SOBFireball(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(SOBFireball);
+
+        setAngularFactor(0.0);
+        this->enableCollisionCallback();
+        gravityAcceleration_ = 350.0;
+
+        speed_ = 0;
+        hasCollided_=false;
+        changeAllowed_ = true;
+        changedOn_ = 0.0;
+        goesRight_ = true;
+        hitCounter_ = 0;
+        particlespawner_ = NULL ;
+
+
+
+   
+
+    }
+
+    
+
+    void SOBFireball::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBFireball, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBFireball, "speed", setSpeed, getSpeed, xmlelement, mode);
+
+
+    }
+
+    void SOBFireball::setDirection(const bool direction)
+    {
+        if(direction)
+        {
+            goesRight_=true;
+        }
+        else
+        {
+            goesRight_=false;
+        }
+    }
+
+    
+    bool SOBFireball::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+        float collDisX_ = getPosition().x - contactPoint.getPositionWorldOnB().getX();
+        float collDisZ_ = getPosition().z - contactPoint.getPositionWorldOnB().getZ();
+
+        SOBGumba*       gumba       = orxonox_cast<SOBGumba*>       (otherObject);
+        SOBGumbaBoss*   gumbaBoss   = orxonox_cast<SOBGumbaBoss*>   (otherObject);
+
+        if(gumbaBoss != nullptr && !(gumba->hasCollided_))  //Fireballs can't destroy GumbaBosses, they get destroyed themselves instead
+        {
+            this->destroyLater();
+            this->hasCollided_ = true;
+        }
+
+
+        if(gumba!=nullptr && gumbaBoss == nullptr && !(gumba->hasCollided_)) //if other object is a Gumba, kill the Gumba and add score and destroy the fireball
+        {
+            gumba->destroyLater();
+            gumba->hasCollided_ = true;
+            SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
+            SOBGame->addGumba();
+            this->destroyLater();
+            this->hasCollided_ = true;
+        }
+
+
+         //collision with either top or bottom of a block
+        else if(changeAllowed_ && (abs(collDisX_)<=abs(collDisZ_)))
+        {
+            changeAllowed_ = false;
+            Vector3 velocity = getVelocity();
+            velocity.z = -velocity.z;
+     
+
+            setVelocity(velocity);
+        }
+
+        //collision with the vertical side of a block 
+        else if(changeAllowed_ && (abs(collDisX_)>abs(collDisZ_))) 
+        {
+            changeAllowed_ = false;
+            goesRight_=!goesRight_;
+        }
+
+        hitCounter_++;
+        
+        return true;
+    }
+
+
+    void SOBFireball::tick(float dt)
+    {
+        SUPER(SOBFireball, tick, dt);
+
+        //the particle spawner that generates the fire from the backpack when pressed
+        if (particlespawner_ == NULL) {
+            for (WorldEntity* object : this->getAttachedObjects())
+            {
+               if (object->isA(Class(ParticleSpawner)))
+                particlespawner_ = object;
+            }
+
+        }
+
+        if(particlespawner_ != NULL)
+            particlespawner_->setVisible(true);
+        if (!changeAllowed_) {
+            changedOn_+= dt;
+            // After a collision, we don't listen for collisions for 200ms - that's because one wall can cause several collisions!
+            if (changedOn_> 0.2) {
+                changeAllowed_ = true;
+                changedOn_ = 0.0;
+
+            }
+        
+        }
+            int dir = 1;
+            if (!goesRight_)
+                dir = -1;
+
+            Vector3 velocity = getVelocity();
+            velocity.z -= gravityAcceleration_*dt;
+            velocity.x = dir*speed_;
+            velocity.y = 0;
+            if(hitCounter_ >= 3) velocity.y = 0.1f*speed_;
+            setVelocity(velocity);
+
+            if(abs(this->getPosition().z) > 1000) this->destroyLater();
+        
+    }
+    
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFireball.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFireball.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFireball.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Theo von Arx
+        Noah Zarro
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBFireball.h
+    @brief Declaration of the SOBFireball class. Fireballs are the Projectile of the Fireflower Powerup
+    @ingroup SOB
+*/
+
+#ifndef _SOBFireball_H__
+#define _SOBFireball_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBFireball : public MovableEntity
+    {
+        public:
+            SOBFireball(Context* context);
+            virtual ~SOBFireball() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void tick(float dt) override;
+            void setDirection(const bool direction);
+          
+            void setSpeed(const float speed)
+                { this->speed_ = speed; }
+            float getSpeed() const
+                { return speed_; }
+
+            bool hasCollided_;
+        protected:
+            float gravityAcceleration_;
+            float speed_;
+            bool goesRight_;
+            bool changeAllowed_;
+            float changedOn_;
+            int hitCounter_;
+            WorldEntity* particlespawner_;
+           
+    };
+}
+
+#endif /* _SOBFireball_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFlagstone.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFlagstone.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFlagstone.cc	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBFlagstone.cc
+    @brief The flagstone, as described in the h file
+*/
+
+#include "SOBFlagstone.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "util/Output.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SOBFlagstone);
+
+    SOBFlagstone::SOBFlagstone(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(SOBFlagstone);
+
+        setAngularFactor(0.0);
+        this->enableCollisionCallback();
+        
+        hasCollided_=false;
+        points_=0;
+        
+    }
+
+    
+
+    void SOBFlagstone::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBFlagstone, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBFlagstone, "points", setPoints, getPoints, xmlelement, mode);
+
+
+    }
+
+    
+    bool SOBFlagstone::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+        return true;
+    }
+
+
+    
+
+
+    
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFlagstone.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFlagstone.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBFlagstone.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBFlagstone.h
+    @brief Declaration of the SOBFlagstone class. 
+            This class is used for the flag - for every 10x10x10 stone we added a flagstone with different points. The higher you touch the flag, the more points you get.
+    @ingroup SOB
+*/
+
+#ifndef _SOBFlagstone_H__
+#define _SOBFlagstone_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBFlagstone : public StaticEntity
+    {
+        public:
+            SOBFlagstone(Context* context);
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+
+            void setPoints(int points) {
+                points_ = points;
+            }
+            int getPoints() {
+                return points_;
+            }
+
+      
+            bool hasCollided_;
+        protected:
+            int points_;
+    };
+}
+
+#endif /* _SOBFlagstone_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumba.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumba.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumba.cc	(revision 11817)
@@ -0,0 +1,145 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBGumba.cc
+    @brief All items in this minigame inherit from this class. Items can move around like platforms and enemies.
+*/
+
+#include "SOBGumba.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "util/Output.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SOBGumba);
+
+    SOBGumba::SOBGumba(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(SOBGumba);
+
+        setAngularFactor(0.0);
+        this->enableCollisionCallback();
+        gravityAcceleration_ = 350.0;
+        speed_ = 0.0;
+        hasCollided_=false;
+        goesRight_ = true;
+        changeAllowed_ = true;
+        changedOn_ = 0.0;
+        creator_ = nullptr;
+        maxLifetime_ = 10;
+        lifetime_ = 0;
+        
+    }
+
+    
+
+    void SOBGumba::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBGumba, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBGumba, "speed", setSpeed, getSpeed, xmlelement, mode);
+
+
+    }
+
+    
+    bool SOBGumba::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+        //Every object with mass -1 does not change the direction of the Gumba. For example the ground floor! The other objects switch the direction of the gumba.
+        if (changeAllowed_ && otherObject->getMass() != -1) {
+            goesRight_ = !goesRight_;
+            changeAllowed_ = false;
+        }
+
+        return true;
+    }
+
+
+    void SOBGumba::setDirection(const bool direction)
+    {
+        if(direction)
+        {
+            goesRight_=true;
+        }
+        else
+        {
+            goesRight_=false;
+        }
+    }
+
+    void SOBGumba::die(){
+        Vector3 velocity = this->getVelocity();
+        velocity.y = speed_;
+        this->setVelocity(velocity);
+    }
+
+    void SOBGumba::tick(float dt)
+    {
+        SUPER(SOBGumba, tick, dt);
+
+        if (!changeAllowed_) {
+            changedOn_+= dt;
+            // After a collision, we don't listen for collisions for 200ms - that's because one wall can cause several collisions!
+            if (changedOn_> 0.400) {
+                changeAllowed_ = true;
+                changedOn_ = 0.0;
+
+            }
+        }
+    
+
+        int dir = 1;
+        if (!goesRight_)
+            dir = -1;
+
+        Vector3 velocity = getVelocity();
+        if(velocity.z > -1 && velocity.z < 1)
+        {
+            velocity.x = dir*speed_;
+        }      
+
+        velocity.z -= gravityAcceleration_*dt;
+        setVelocity(velocity);
+
+        if (creator_ != nullptr)
+        {
+            lifetime_ += dt;
+            if(lifetime_>maxLifetime_)
+            {
+                
+            }
+        }
+
+        if(abs(this->getPosition().z) > 1000) this->destroyLater();
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumba.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumba.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumba.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBGumba.h
+    @brief Declaration of the SOBGumba class. Gumbas are the enemie mushrooms - pretty sure it's written Goomba but, naaah
+    @ingroup SOB
+*/
+
+#ifndef _SOBGumba_H__
+#define _SOBGumba_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBGumba : public MovableEntity
+    {
+        public:
+            SOBGumba(Context* context);
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void tick(float dt) override;
+
+            void setDirection(const bool direction);
+            void die();
+          
+            void setSpeed(const float speed)
+                { this->speed_ = speed; }
+            float getSpeed() const
+                { return speed_; }
+
+            bool hasCollided_;
+            SOBGumbaBoss* creator_;
+        protected:
+            float gravityAcceleration_;
+            float speed_;
+            bool goesRight_;
+            bool changeAllowed_;
+            float changedOn_;
+            float maxLifetime_;
+            float lifetime_;
+
+           
+    };
+}
+
+#endif /* _SOBGumba_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumbaBoss.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumbaBoss.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumbaBoss.cc	(revision 11817)
@@ -0,0 +1,187 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Noah Zarro
+ *      Theo von Arx
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBGumbaBoss.cc
+    @brief A Boss Gumba, which shoots small Gumbas
+**/
+
+#include "SOB.h"
+#include "SOBGumba.h"
+#include "SOBGumbaBoss.h"
+#include "SOBFireball.h"
+#include "SOBFigure.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Output.h"
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+
+
+
+namespace orxonox
+{
+    RegisterClass(SOBGumbaBoss);
+
+    SOBGumbaBoss::SOBGumbaBoss(Context* context) : SOBGumba(context)
+    {
+        RegisterObject(SOBGumbaBoss);
+
+        gumbaMaxTime_   = 1;  // time after which a Gumba is shot
+        gumbaTime_      = 0;  // time since last gumba was shot
+        maxGumbas_      = 50; // Max Gumbas spawnable by a Boss
+        jumpTimeMax_    = 5;  // time after which the gumba boss jumps
+        jumpTime_       = 0;  // time since last jump of gumba boss
+        
+    }
+
+    // PRE: otherObject collides with this.
+    // POST: collision is handled: velocity changed, small gumbas murdered
+    bool SOBGumbaBoss::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+        SOBGumba*       gumba       = orxonox_cast<SOBGumba*>(otherObject);
+        SOBGumbaBoss*   gumbaBoss   = orxonox_cast<SOBGumbaBoss*>(otherObject);
+
+        // if boss collides with small gumbas, destroy them.
+        if (gumba != nullptr && gumbaBoss == nullptr && !(gumba->hasCollided_)) {
+            gumba->die();
+        }
+
+
+        //Every object with mass -1 does not change the direction of the GumbaBoss. For example the ground floor! The other objects switch the direction of the GumbaBoss.
+        else if (changeAllowed_ && otherObject->getMass() != -1) {
+            goesRight_ = !goesRight_;
+            changeAllowed_ = false;
+        }
+
+        return true;
+    }
+
+
+
+    // POST: done what was to do in a time dt
+    void SOBGumbaBoss::tick(float dt)
+    {
+        SUPER(SOBGumbaBoss, tick, dt);
+
+        // increase timers:
+        gumbaTime_ += dt;
+        jumpTime_  += dt; 
+
+        // set y-component of position of gumba boss to 0, so he doesn't fall in to the nothing
+        Vector3 position = getPosition();
+        position.y = 0;
+        setPosition(position);
+
+
+        if (!changeAllowed_) {
+            changedOn_+= dt;
+            // After a collision, we don't listen for collisions for 200ms - that's because one wall can cause several collisions!
+            if (changedOn_> 0.200) {
+                changeAllowed_ = true;
+                changedOn_ = 0.0;
+
+            }
+        }
+    
+
+        if(gumbaTime_ > gumbaMaxTime_){ //Spawn Gumba
+            int gumbaCounter=0;
+
+            for (SOBGumba*  gumbaInstance : ObjectList<SOBGumba>())
+            {
+                if (gumbaInstance != nullptr && gumbaInstance->creator_==this)
+                {
+                    gumbaCounter++;
+                }
+            } 
+
+
+            if(gumbaCounter<maxGumbas_){    //only maxGumbas are allowed at one time per Gumbaboss
+                spawnGumba();
+                gumbaTime_ = 0;
+            }
+        }
+
+        int dir = 1;
+        if (!goesRight_)
+            dir = -1;
+
+        // 
+        if(getPosition().x < 1640)
+            dir = 1;
+        else if (getPosition().x > 1750)
+            dir = -1;
+
+        //change velocity
+        Vector3 velocity = getVelocity();
+        if(jumpTime_ > jumpTimeMax_){ // jump if the time has come.
+            velocity.z = speed_*15;
+            jumpTime_ = 0;
+        }
+        else{
+            velocity.z -= gravityAcceleration_*dt;
+        }
+        velocity.x = dir*speed_;
+        setVelocity(velocity);
+
+    }
+
+    // spawn gumbas
+    void SOBGumbaBoss::spawnGumba() {
+        SOBCenterpoint* center_ = ((SOB*)getGametype())->center_;
+
+         SOBGumba* gumba = new SOBGumba(center_->getContext());
+         Vector3 spawnpos = this->getWorldPosition();
+         gumba->creator_=this;
+
+         // we can shoot a gumba!
+        if (gumba != nullptr && center_ != nullptr)
+        {
+            gumba->addTemplate("gumbaShootable");
+            gumba->setDirection(goesRight_);
+            if(goesRight_)
+            {
+                spawnpos.x+=20;
+            }
+            else
+            {
+                spawnpos.x-=20;
+            }
+            spawnpos.z+=15;
+            gumba->setPosition(spawnpos);
+
+        }
+
+        Vector3 velocity = gumba->getVelocity();
+        velocity.x += (2*goesRight_ -1) * 100;
+        velocity.z += 200;
+        gumba->setVelocity(velocity);
+     }
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumbaBoss.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumbaBoss.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBGumbaBoss.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Noah Zarro
+ *      Theo von Arx
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBGumbaBoss.h
+    @brief Declaration of the SOBGumbaBoss class. GumbaBosss are the enemie mushrooms - pretty sure it's written Goomba but, naaah
+    @ingroup SOB
+*/
+
+#ifndef _SOBGumbaBoss_H__
+#define _SOBGumbaBoss_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBGumbaBoss : public SOBGumba
+    {
+        public:
+            SOBGumbaBoss(Context* context);
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void tick(float dt) override;
+
+            void spawnGumba();
+
+
+        protected:
+            float gumbaTime_;
+            float gumbaMaxTime_;
+            float jumpTimeMax_;
+            float jumpTime_;
+            int maxGumbas_;
+
+
+
+           
+    };
+}
+
+#endif /* _SOBGumbaBoss_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBHUDInfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBHUDInfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBHUDInfo.cc	(revision 11817)
@@ -0,0 +1,113 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *
+ */
+
+#include "SOBHUDInfo.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+#include "SOB.h"
+#include <sstream>
+#include <iomanip>
+
+
+
+namespace orxonox
+{
+    RegisterClass(SOBHUDInfo);
+
+    SOBHUDInfo::SOBHUDInfo(Context* context) : OverlayText(context)
+    {
+        RegisterObject(SOBHUDInfo);
+
+        this->SOBGame = nullptr;
+        
+    }
+
+    void SOBHUDInfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBHUDInfo, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBHUDInfo, "type",     setType,     getType,     xmlelement, mode).defaultValues(false);
+
+
+    }
+
+    void SOBHUDInfo::tick(float dt)
+    {
+        SUPER(SOBHUDInfo, tick, dt);
+
+        //If you have a look at the HUD xml file, you can see there are several elements with different types.
+        if (this->SOBGame)
+        {
+          
+          if (this->type_ == "Coins") {            
+            
+            std::stringstream ss;
+            ss << "cc x " << std::setw(2) << std::setfill('0') << SOBGame->getCoins();
+            std::string s = ss.str();
+
+            this->setCaption(s);
+            
+        }
+        if (this->type_ == "Points") {
+            std::stringstream ss;
+            ss << std::setw(6) << std::setfill('0') << SOBGame->getPoints();
+            std::string s = ss.str();
+            this->setCaption(s);
+        }
+        if (this->type_ == "Time") {
+            std::stringstream ss;
+            ss << SOBGame->getTimeLeft();
+            std::string s = ss.str();
+            this->setCaption(s);
+        }
+        if (this->type_ == "Info") {
+            std::stringstream ss;
+            ss << SOBGame->getInfoText();
+            std::string s = ss.str();
+            this->setCaption(s);
+        }
+        
+
+        
+    }
+}
+
+//No idea why, just implement this method
+void SOBHUDInfo::changedOwner()
+{
+    SUPER(SOBHUDInfo, changedOwner);
+
+    if (this->getOwner() && this->getOwner()->getGametype())
+    {
+        this->SOBGame = orxonox_cast<SOB*>(this->getOwner()->getGametype());
+    }
+    else
+    {
+        this->SOBGame = nullptr;
+    }
+}
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBHUDInfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBHUDInfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBHUDInfo.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *
+ */
+
+#ifndef _SOBHUDInfo_H__
+#define _SOBHUDInfo_H__
+
+#include "superorxobros/SOBPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+    class _SOBExport SOBHUDInfo : public OverlayText, public Tickable
+    {
+        public:
+            SOBHUDInfo(Context* context);
+
+            virtual void tick(float dt) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void changedOwner() override;
+
+            inline void setType(std::string type)
+                { this->type_ = type; }
+            inline std::string getType() const
+                { return this->type_; }
+        
+
+        private:
+            SOB* SOBGame;
+            std::string type_;
+      
+    };
+}
+#endif /* _SOBHUDInfo_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBItem.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBItem.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBItem.cc	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBItem.cc
+    @brief Not sure if ever used
+*/
+
+#include "SOBItem.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "util/Output.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SOBItem);
+
+    SOBItem::SOBItem(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(SOBItem);
+
+        attachedToFigure_ = false;
+
+        figure_ = nullptr;
+     this->enableCollisionCallback();
+       
+    }
+
+    
+
+    void SOBItem::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBItem, XMLPort, xmlelement, mode);
+
+
+     }
+
+   
+    bool SOBItem::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+        return true;
+    }
+
+
+    void SOBItem::setFigure(SOBFigure* newFigure)
+    {
+        figure_ = newFigure;
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBItem.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBItem.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBItem.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBItem.h
+    @brief Declaration of the SOBItem class.
+    @ingroup SOB
+*/
+
+#ifndef _SOBItem_H__
+#define _SOBItem_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBItem : public StaticEntity
+    {
+        public:
+            SOBItem(Context* context);
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void setFigure(SOBFigure* newFigure);
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+
+          
+            bool attachedToFigure_;
+
+        protected:
+          
+            WeakPtr<SOBFigure> figure_;
+           
+    };
+}
+
+#endif /* _SOBItem_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBMushroom.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBMushroom.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBMushroom.cc	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBMushroom.cc
+    @brief This is the class for the powerup mushroom
+*/
+
+#include "SOBMushroom.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOBFigure.h"
+#include "util/Output.h"
+
+
+namespace orxonox
+{
+    RegisterClass(SOBMushroom);
+
+    SOBMushroom::SOBMushroom(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(SOBMushroom);
+
+        setAngularFactor(0.0);
+        this->enableCollisionCallback();
+        gravityAcceleration_ = 350.0;
+        speed_ = 0.0;
+        hasCollided_=false;
+        goesRight_ = true;
+        changeAllowed_ = true;
+        changedOn_ = 0.0;
+       
+    }
+
+    
+
+    void SOBMushroom::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBMushroom, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBMushroom, "speed", setSpeed, getSpeed, xmlelement, mode);
+
+
+     }
+
+   
+    bool SOBMushroom::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+
+        if (changeAllowed_ && otherObject->getMass() != -1) {
+                goesRight_ = !goesRight_;
+                changeAllowed_ = false;
+        }
+
+        return true;
+    }
+
+
+    void SOBMushroom::tick(float dt)
+    {
+        SUPER(SOBMushroom, tick, dt);
+
+        //Exactly like the Gumba class, if collided, turn direction of Mushroom and wait 200ms so we don't get two collisions from the same wall
+        if (!changeAllowed_) {
+            changedOn_+= dt;
+            if (changedOn_> 0.200) {
+                changeAllowed_ = true;
+                changedOn_ = 0.0;
+
+            }
+        }
+        
+
+        int dir = 1;
+        if (!goesRight_)
+            dir = -1;
+
+        Vector3 velocity = getVelocity();
+        velocity.z -= gravityAcceleration_*dt;
+        velocity.x = dir*speed_;
+        setVelocity(velocity);
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBMushroom.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBMushroom.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBMushroom.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SOBMushroom.h
+    @brief Declaration of the SOBMushroom class.
+    @ingroup SOB
+*/
+
+#ifndef _SOBMushroom_H__
+#define _SOBMushroom_H__
+
+#include "superorxobros/SOBPrereqs.h"
+#include "worldentities/MovableEntity.h"
+
+
+namespace orxonox
+{
+    class _SOBExport SOBMushroom : public MovableEntity
+    {
+        public:
+            SOBMushroom(Context* context);
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void tick(float dt) override;
+
+          
+            void setSpeed(const float speed)
+                { this->speed_ = speed; }
+            float getSpeed() const
+                { return speed_; }
+
+            bool hasCollided_;
+        protected:
+            float gravityAcceleration_;
+            float speed_;
+            bool goesRight_;
+            bool changeAllowed_;
+            float changedOn_;
+           
+    };
+}
+
+#endif /* _SOBMushroom_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBPrereqs.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the SOB module
+*/
+
+#ifndef _SOBPrereqs_H__
+#define _SOBPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(SOB_STATIC_BUILD)
+#  ifdef SUPERORXOBROS_SHARED_BUILD
+#    define _SOBExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _SOBExport
+#    else
+#      define _SOBExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _SOBPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _SOBExport  __attribute__ ((visibility("default")))
+#  define _SOBPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _SOBExport
+#  define _SOBPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class SOBCenterpoint;
+    class SOB;
+    class SOBFigure;
+    class SOBItem;
+    class SOBQBlock;
+    class SOBMushroom;
+    class SOBHUDInfo;
+    class SOBGumba;
+    class SOBGumbaBoss;
+    class SOBFlagstone;
+    class SOBCastlestone;
+    class SOBCoin;
+
+}
+
+#endif /* _SOBPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBQBlock.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBQBlock.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBQBlock.cc	(revision 11817)
@@ -0,0 +1,131 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+/**
+    @file SOBQBlock.cc
+    @brief If this QBlock is created, attachedToFigure_ is set to false. When the figure picks it up, the variable is set to true and the figure starts flying fast until the fuel is reduced to zero.
+*/
+
+#include "SOBQBlock.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "SOB.h"
+#include "SOBMushroom.h"
+#include "SOBCoin.h"
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+
+
+namespace orxonox
+{
+    RegisterClass(SOBQBlock);
+
+    SOBQBlock::SOBQBlock(Context* context) : SOBItem(context)
+    {
+        RegisterObject(SOBQBlock);
+        used_ = false;
+
+    }
+
+    SOBQBlock::~SOBQBlock()
+    {
+
+    }
+
+   
+    bool SOBQBlock::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) {
+
+
+        //If you hit the QBlock, the visibility of all attached objects get inverted! Pretty easy way to create changing blocks :)
+        float v_z = otherObject->getVelocity().z;
+        float collDisZ_ = getPosition().z - contactPoint.getPositionWorldOnB().getZ();
+        if (!used_ && v_z > 50.0 && collDisZ_ > 0) {
+            used_ = true;
+
+            for (WorldEntity* object : this->getAttachedObjects())
+                object->setVisible(!object->isVisible());            
+
+            SOB* SOBGame = orxonox_cast<SOB*>(getGametype());
+
+            //Spawn either a powerup mushroom or a coin animation (also just an object, have a look at the SOBCoin class)
+            //The spawn methods are declared at the bottom of this file
+            if (type_ == "Coin") {
+                SOBGame->addCoin();
+                spawnCoin();
+            }
+            if (type_ == "Mushroom") {
+                spawnMushroom();
+            }
+
+        }
+        return true;
+    }
+
+
+    void SOBQBlock::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SOBQBlock, XMLPort, xmlelement, mode);
+        XMLPortParam(SOBQBlock, "type",     setType,     getType,     xmlelement, mode).defaultValues(false);
+
+
+     }
+
+
+     //The spawnmethods from above
+     void SOBQBlock::spawnMushroom() {
+        SOBCenterpoint* center_ = ((SOB*)getGametype())->center_;
+
+         SOBMushroom* mush = new SOBMushroom(center_->getContext());
+         Vector3 spawnpos = this->getWorldPosition();
+         spawnpos.z += 0;
+
+        if (mush != nullptr && center_ != nullptr)
+        {
+            mush->addTemplate("mushroom");
+            mush->setPosition(spawnpos);
+            
+        }
+     }
+
+          void SOBQBlock::spawnCoin() {
+        SOBCenterpoint* center_ = ((SOB*)getGametype())->center_;
+
+         SOBCoin* mush = new SOBCoin(center_->getContext());
+         Vector3 spawnpos = this->getWorldPosition();
+         spawnpos.z += 0;
+
+        if (mush != nullptr && center_ != nullptr)
+        {
+            mush->addTemplate("coin");
+            mush->setPosition(spawnpos);
+       
+        }
+     }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBQBlock.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBQBlock.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/superorxobros/SOBQBlock.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julien Kindle
+ *   Co-authors:
+ *      
+ *
+ */
+
+#ifndef _SOBQBlock_H__
+#define _SOBQBlock_H__
+
+#include "SOBPrereqs.h"
+#include "SOBItem.h"
+
+namespace orxonox
+{
+    class _SOBExport SOBQBlock : public SOBItem
+    {
+        public:
+            SOBQBlock(Context* context);
+            virtual ~SOBQBlock();
+            virtual  bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setType(std::string type) {
+                this->type_=type;
+            }
+            std::string getType() {
+                return this->type_;
+            }
+        protected:
+            bool used_;
+            std::string type_;
+            void spawnMushroom();
+            void spawnCoin();
+    };
+           
+}
+
+#endif /* _SOBQBlock_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/tetris/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,16 @@
+SET_SOURCE_FILES(TETRIS_SRC_FILES
+  Tetris.cc
+  TetrisCenterpoint.cc
+  TetrisStone.cc
+  TetrisBrick.cc
+  TetrisScore.cc
+)
+
+ORXONOX_ADD_LIBRARY(tetris
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+  SOURCE_FILES ${TETRIS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/tetris/Tetris.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/Tetris.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/Tetris.cc	(revision 11817)
@@ -0,0 +1,518 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      Johannes Ritz
+ *
+ *
+ *
+ *
+ *TASK c) end the game in a nicer way
+ *TASK d) save the highscore
+ *TASK e) eye candy
+ */
+
+/**
+    @file Tetris.cc
+    @brief Implementation of the Tetris class.
+*/
+
+#include "Tetris.h"
+#include "Highscore.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/command/Executor.h"
+
+#include "gamestates/GSLevel.h"
+
+#include "TetrisCenterpoint.h"
+#include "TetrisStone.h"
+#include "TetrisBrick.h"
+#include "infos/PlayerInfo.h"
+#include <cmath>
+
+namespace orxonox
+{
+
+    RegisterUnloadableClass(Tetris);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    @ingroup Tetris
+    */
+    Tetris::Tetris(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(Tetris);
+
+        this->activeBrick_ = nullptr;
+
+        // Pre-set the timer, but don't start it yet.
+        this->starttimer_.setTimer(1.0, false, createExecutor(createFunctor(&Tetris::startBrick, this)));
+        this->starttimer_.stopTimer();
+
+        this->player_ = nullptr;
+        this->setHUDTemplate("TetrisHUD");
+        this->futureBrick_ = nullptr;
+    }
+
+    /**
+    @brief
+        Destructor. Cleans up, if initialized.
+    */
+    Tetris::~Tetris()
+    {
+        if (this->isInitialized())
+            this->cleanup();
+    }
+
+    /**
+    @brief
+        Cleans up the Gametype.
+    */
+    void Tetris::cleanup()
+    {
+        if (this->activeBrick_)
+        {
+            this->activeBrick_->destroy();
+            this->activeBrick_ = nullptr;
+        }
+        if (this->futureBrick_)
+        {
+            this->futureBrick_->destroy();
+            this->futureBrick_ = nullptr;
+        }
+
+        for (TetrisStone* stone : this->stones_)
+            stone->destroy();
+        this->stones_.clear();
+    }
+
+    void Tetris::tick(float dt)
+    {
+        SUPER(Tetris, tick, dt);
+
+        if((this->activeBrick_ != nullptr)&&(!this->hasEnded()))
+        {
+            if(!this->isValidBrickPosition(this->activeBrick_))
+            {
+                for (unsigned int i = 0; i < this->activeBrick_->getNumberOfStones(); i++)
+                    this->stones_.push_back(this->activeBrick_->getStone(i));
+                this->activeBrick_->setVelocity(Vector3::ZERO);
+                this->activeBrick_->releaseStones(this->center_);
+                this->findFullRows();
+                this->startBrick();
+            }
+        } 
+    }
+
+    bool Tetris::isValidMove(TetrisStone* stone, const Vector3& position)
+    {
+        assert(stone);
+
+        if(position.x < this->center_->getStoneSize()/2.0)  //!< If the stone touches the left edge of the level
+            return false;
+        else if(position.x > (this->center_->getWidth()-0.5)*this->center_->getStoneSize()) //!< If the stone touches the right edge of the level
+            return false;
+
+        for(TetrisStone* someStone : this->stones_)
+        {
+            const Vector3& currentStonePosition = someStone->getPosition(); //!< Saves the position of the currentStone
+
+            if((position.x == currentStonePosition.x) && std::abs(position.y-currentStonePosition.y) < this->center_->getStoneSize())
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
+    @brief
+        Check for each stone in a brick if it is moved the right way.
+    */
+    bool Tetris::isValidMove(TetrisBrick* brick, const Vector3& position, bool isRotation = false)
+    {
+        assert(brick);
+
+        for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ )
+        {
+            TetrisStone* stone = brick->getStone(i);
+            Vector3 stonePosition; //the current stone's offset to position
+            if(isRotation)
+                stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount()+1);
+            else
+                stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount());
+
+            if(! this->isValidMove(stone, position + stonePosition ))
+            {
+                return false;
+            }
+
+            //catch illegal rotation (such that collisions with ground are not permitted)
+            if(isRotation)
+            {
+                if((position + stonePosition).y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level
+                {
+                    return false;
+                }
+            }
+        }
+        return true;
+
+    }
+
+
+    /**
+     * @brief Returns true, if NO collision was detected.
+     * Else returns false and the active brick is repositioned as side-effect.
+     */
+    bool Tetris::checkStoneStoneCollision(TetrisStone* stone, const Vector3& position)
+    {
+        assert(stone);
+
+        // check for collisions with all stones
+        for(TetrisStone* someStone : this->stones_)
+        {
+            //Vector3 currentStonePosition = rotateVector((*it)->getPosition(), this->activeBrick_->getRotationCount());
+            const Vector3& currentStonePosition = someStone->getPosition(); //!< Saves the position of the currentStone
+
+            //filter out cases where the falling stone is already below a steady stone
+            if(position.y < currentStonePosition.y - this->center_->getStoneSize()/2.0f)
+                continue;
+            if((position.x == currentStonePosition.x) && (position.y < currentStonePosition.y + this->center_->getStoneSize()))
+            {
+                float y_offset = static_cast<int>((this->activeBrick_->getPosition().y-currentStonePosition.y+10)/10)*10 + currentStonePosition.y;
+                if(y_offset < 0) //filter out extreme cases (very rare bug)
+                    y_offset = 0;
+                this->activeBrick_->setPosition(Vector3(this->activeBrick_->getPosition().x, y_offset, this->activeBrick_->getPosition().z));
+                return false;
+            }// This case applies if the stones overlap partially vertically
+        }
+
+        return true;
+    }
+    
+    /**
+     * @brief Returns true, if NO collision was detected.
+     * Else returns false and the active brick is repositioned as side-effect.
+     */
+    bool Tetris::checkStoneBottomCollision(TetrisStone* stone, const Vector3& position)
+    {
+        assert(stone);
+        if(position.y < this->center_->getStoneSize()/2.0f) //!< If the stone has reached the bottom of the level
+        {
+            float baseOffset = std::abs(stone->getPosition().y);
+            if (this->activeBrick_->getRotationCount() == 1 || this->activeBrick_->getRotationCount() == 3)
+                baseOffset = std::abs(stone->getPosition().x);
+            float yOffset = baseOffset + this->center_->getStoneSize()/2.0f;//calculate offset
+            if(yOffset < 0) //catch brake-throughs
+                yOffset = 0;
+            this->activeBrick_->setPosition(Vector3(this->activeBrick_->getPosition().x, yOffset, this->activeBrick_->getPosition().z));
+            return false;
+        }
+        return true;
+    }
+    
+    /**
+     * @brief This function determines wether a brick touches another brick or the ground.
+     *
+     */
+    bool Tetris::isValidBrickPosition(TetrisBrick* brick)
+    {
+        assert(brick);
+
+        const Vector3& brickPosition = this->activeBrick_->getPosition();
+
+        // check all stones in the brick
+        for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ )
+        {
+            TetrisStone* stone = brick->getStone(i);
+            const Vector3& stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount());
+            if(! this->checkStoneStoneCollision(stone, brickPosition + stonePosition) )
+            {
+                return false;
+            }
+        }
+        // check all stones in the brick
+        for (unsigned int i = 0; i < brick->getNumberOfStones(); i++ )
+        {
+            TetrisStone* stone = brick->getStone(i);
+            const Vector3& stonePosition = rotateVector(stone->getPosition(), brick->getRotationCount());
+            if(! this->checkStoneBottomCollision(stone, brickPosition + stonePosition) )
+            {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    /**
+    @brief
+        A Vector3 is rolled 90 * degrees * amount (anticlockwise rotation)
+    */
+    Vector3 Tetris::rotateVector(Vector3 position, unsigned int amount)
+    {
+        float temp = 0;
+        for(unsigned int i = 0; i < amount; i++)
+        {
+            temp = position.x;
+            position.x = -position.y;
+            position.y = temp;
+        }
+        return position;
+    }
+
+    /**
+    @brief
+        Starts the Tetris minigame.
+    */
+    void Tetris::start()
+    {
+        if (this->center_ != nullptr) // There needs to be a TetrisCenterpoint, i.e. the area the game takes place.
+        {
+            // Create the first brick.
+            this->createBrick();
+        }
+        else // If no centerpoint was specified, an error is thrown and the level is exited.
+        {
+            orxout(internal_error) << "Tetris: No Centerpoint specified." << endl;
+            GSLevel::startMainMenu();
+            return;
+        }
+
+        // Start the timer. After it has expired the stone is started.
+        this->starttimer_.startTimer();
+
+        // Set variable to temporarily force the player to spawn.
+        bool temp = this->bForceSpawn_;
+        this->bForceSpawn_ = true;
+
+        // Call start for the parent class.
+        Deathmatch::start();
+
+        // Reset the variable.
+        this->bForceSpawn_ = temp;
+    }
+
+    /**
+    @brief
+        Ends the Tetris minigame.
+    */
+    void Tetris::end()
+    {
+        this->activeBrick_->setVelocity(Vector3::ZERO);
+        if(this->activeBrick_ != nullptr)
+        {
+            this->player_->stopControl();
+        }
+        if (Highscore::exists())
+        {
+            int score = this->getScore(this->getPlayer());
+            Highscore::getInstance().storeScore("Tetris", score, this->getPlayer());
+        }
+        this->cleanup();
+
+        // Call end for the parent class.
+        Deathmatch::end();
+    }
+
+    /**
+    @brief
+        Spawns player.
+    */
+    void Tetris::spawnPlayersIfRequested()
+    {
+        // Spawn a human player.
+        for (const auto& mapEntry : this->players_)
+            if (mapEntry.first->isHumanPlayer() && (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                this->spawnPlayer(mapEntry.first);
+    }
+    
+    bool Tetris::playerLeft(PlayerInfo* player)
+    {
+        bool left = Gametype::playerLeft(player);
+        if(player && player->isHumanPlayer())
+        {
+            if(this->activeBrick_ != nullptr)
+            {
+                this->player_->stopControl();
+            }
+            this->cleanup();
+        }
+        return left;
+    }
+
+    /**
+    @brief
+        Spawns the input player.
+    @param player
+        The player to be spawned.
+    */
+    void Tetris::spawnPlayer(PlayerInfo* player)
+    {
+        assert(player);
+
+        if(this->player_ == nullptr)
+        {
+            this->player_ = player;
+            this->players_[player].state_ = PlayerState::Alive;
+        }
+    }
+
+
+
+    void Tetris::startBrick(void)
+    {
+        if(this->player_ == nullptr)
+            return;
+
+        unsigned int cameraIndex = 0;
+        if(this->activeBrick_ != nullptr)
+        {
+            // Get camera settings
+            cameraIndex = this->activeBrick_->getCurrentCameraIndex();
+            this->player_->stopControl();
+            // destroy old active brick
+            this->activeBrick_->destroy();
+        }
+
+        // Make the last brick to be created the active brick.
+        this->activeBrick_ = this->futureBrick_;
+        this->futureBrick_ = nullptr;
+
+        // set its position
+        this->player_->startControl(this->activeBrick_);
+        float xPos = (this->center_->getWidth()/2 + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize();
+        float yPos = (this->center_->getHeight()-0.5f)*this->center_->getStoneSize();
+        this->activeBrick_->setPosition(xPos, yPos, 0.0f);
+        this->activeBrick_->setVelocity(0.0f, -this->center_->getStoneSpeed(), 0.0f);
+        this->activeBrick_->setCameraPosition(cameraIndex);
+
+        // create a new future brick
+        this->createBrick();
+
+        // check if the new brick is in a valid position, otherwise end the game
+        if (!this->isValidBrickPosition(this->activeBrick_))
+            this->end();
+    }
+
+    void Tetris::createBrick(void)             //TODO: random rotation offset between 0 and 3 (times 90°)
+    {
+        // create new futureBrick_
+        this->futureBrick_ = new TetrisBrick(this->center_->getContext());
+
+
+        // Apply the stone template to the stone.
+        this->futureBrick_->addTemplate(this->center_->getBrickTemplate());
+
+        // Attach the brick to the Centerpoint and set the position of the brick to be at the left side.
+        this->center_->attach(this->futureBrick_);
+        float xPos = (this->center_->getWidth()*1.6f + ((this->center_->getWidth() % 2)*2-1)/2.0f)*this->center_->getStoneSize();
+        float yPos = (this->center_->getHeight()-5.1f)*this->center_->getStoneSize();
+        
+        this->futureBrick_->setPosition(xPos, yPos, 0.0f);
+        this->futureBrick_->setGame(this);
+    }
+
+
+    /**
+    @brief
+        Get the player.
+    @return
+        Returns a pointer to the player. If there is no player, nullptr is returned.
+    */
+    PlayerInfo* Tetris::getPlayer(void) const
+    {
+        return this->player_;
+    }
+
+    /*TetrisCenterpoint* Tetris::getCenterpoint(void) const
+    {
+        return this->center_;
+    }*/
+
+    /**
+    @brief Set the TetrisCenterpoint (the playing field).
+    @param center A pointer to the TetrisCenterpoint to be set.
+    */
+    void Tetris::setCenterpoint(TetrisCenterpoint* center)
+    {
+        this->center_ = center;
+    }
+
+    /**
+    @brief Check each row if it is full. Removes all full rows. Update
+    @brief Manages score.
+    */
+    void Tetris::findFullRows()
+    {
+        unsigned int correctPosition = 0;
+        unsigned int stonesPerRow = 0;
+        for (unsigned int row = 0; row < this->center_->getHeight(); row++)
+        {
+            stonesPerRow = 0;
+            for(std::list<StrongPtr<TetrisStone>>::iterator it = this->stones_.begin(); it != this->stones_.end(); )
+            {
+                std::list<StrongPtr<TetrisStone>>::iterator it_temp = it++;
+                correctPosition = static_cast<unsigned int>(((*it_temp)->getPosition().y - 5)/this->center_->getStoneSize());
+                if(correctPosition == row)
+                {
+                    stonesPerRow++;
+                    if(stonesPerRow == this->center_->getWidth())
+                    {
+                        clearRow(row);
+                        row--; //the row counter has to be decreased in order to detect multiple rows!
+                        this->playerScored(this->player_);// add points
+                        //increase the stone's speed
+                        this->center_->setStoneSpeed(this->center_->getStoneSpeed()+1.0f);
+                    }
+                }
+            }
+        }
+    }
+
+    void Tetris::clearRow(unsigned int row)
+    {// clear the full row
+        for(std::list<StrongPtr<TetrisStone>>::iterator it = this->stones_.begin(); it != this->stones_.end(); )
+        {
+            if(static_cast<unsigned int>(((*it)->getPosition().y - 5)/this->center_->getStoneSize()) == row)
+            {
+                (*it)->destroy();
+                this->stones_.erase(it++);
+            }
+            else
+                ++it;
+        }
+      // adjust height of stones above the deleted row //TODO: check if this could be a source of a bug.
+        for(TetrisStone* stone : this->stones_)
+        {
+            if(static_cast<unsigned int>((stone->getPosition().y - 5)/this->center_->getStoneSize()) > row)
+                stone->setPosition(stone->getPosition()-Vector3(0,10,0));
+        }
+
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/tetris/Tetris.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/Tetris.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/Tetris.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Tetris.h
+    @brief Declaration of the Tetris class.
+    @ingroup Tetris
+*/
+
+#ifndef _Tetris_H__
+#define _Tetris_H__
+
+#include "tetris/TetrisPrereqs.h"
+
+#include "tools/Timer.h"
+
+#include "gametypes/Deathmatch.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+
+    @author
+
+    @ingroup Tetris
+    */
+    class _TetrisExport Tetris : public Deathmatch
+    {
+        public:
+            Tetris(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~Tetris(); //!< Destructor. Cleans up, if initialized.
+
+            virtual void start(void) override; //!< Starts the Tetris minigame.
+            virtual void end(void) override; ///!< Ends the Tetris minigame.
+
+            virtual void tick(float dt) override;
+
+            virtual void spawnPlayer(PlayerInfo* player) override; //!< Spawns the input player.
+            virtual bool playerLeft(PlayerInfo* player) override;
+
+            void setCenterpoint(TetrisCenterpoint* center);
+
+            PlayerInfo* getPlayer(void) const; //!< Get the player.
+            TetrisCenterpoint* getCenterpoint(void)
+                { return this->center_; }
+
+            bool isValidMove(TetrisStone* stone, const Vector3& position);
+            bool isValidMove(TetrisBrick* brick, const Vector3& position, bool isRotation);
+            Vector3 rotateVector(Vector3 position, unsigned int amount);
+
+        protected:
+            virtual void spawnPlayersIfRequested() override; //!< Spawns player.
+
+
+        private:
+            void startBrick(void);
+            void createBrick(void);
+            void cleanup(void); //!< Cleans up the Gametype by destroying the ball and the bats.
+            bool checkStoneStoneCollision(TetrisStone* stone, const Vector3& position);
+            bool checkStoneBottomCollision(TetrisStone* stone, const Vector3& position);
+            bool isValidBrickPosition(TetrisBrick* brick);
+            void findFullRows(void);
+            void clearRow(unsigned int row);
+
+            PlayerInfo* player_;
+
+            WeakPtr<TetrisCenterpoint> center_; //!< The playing field.
+            std::list<StrongPtr<TetrisStone>> stones_; //!< A list of all stones in play.
+            WeakPtr<TetrisBrick> activeBrick_;
+            WeakPtr<TetrisBrick> futureBrick_;
+
+            Timer starttimer_; //!< A timer to delay the start of the game.
+    };
+}
+
+#endif /* _Tetris_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisBrick.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisBrick.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisBrick.cc	(revision 11817)
@@ -0,0 +1,250 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisBrick.cc
+    @brief Implementation of the TetrisBrick class.
+*/
+
+#include "TetrisBrick.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "TetrisCenterpoint.h"
+#include "TetrisStone.h"
+#include "Tetris.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    RegisterClass(TetrisBrick);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    @ingroup Tetris
+    */
+    TetrisBrick::TetrisBrick(Context* context): ControllableEntity(context)
+    {
+        RegisterObject(TetrisBrick);
+        this->shapeIndex_ = 1 + static_cast<unsigned int>(rnd(6.0f)); //<! random number between 0 and 7
+        this->stonesPerBrick_ = 4; //<! most tetris bricks is formed by 4 stones
+        this->delay_ = false;
+        this->delayTimer_.setTimer(0.2f, false, createExecutor(createFunctor(&TetrisBrick::enableMovement, this)));
+        this->lockRotation_ = false;
+        this->tetris_ = this->getTetris();
+        this->size_ = 10.0f; //TODO: fix this via this->tetris_->center_->getStoneSize();
+        this->rotationCount_ = 0;
+        this->createBrick(); //<! create a whole new Brick;
+    }
+
+    /**
+    @brief
+        This function partly initializes a TetrisBrick as an array of TetrisStones
+    */
+    void TetrisBrick::createBrick(void)
+    { //Index 0 : single stone, 1 : 4 in a row; 2: 4-Block right shifted; 3: 'T' 4: 4-Block left shifted;
+      //Index 5 : 4-Block; 6 : 'L'; 7 : mirrored 'L';
+        if(this->shapeIndex_ == 0)
+            this->stonesPerBrick_ = 1;
+        for (unsigned int i = 0; i < this->stonesPerBrick_; i++)
+        {
+            // Create a new stone and add it to the brick.
+            TetrisStone* stone = new TetrisStone(this->getContext());
+            this->brickStones_.push_back(stone);
+            this->attach(stone);
+            this->formBrick(stone, i);
+            if(this->tetris_ != nullptr)
+            {
+                stone->setGame(this->tetris_);
+                if(this->tetris_->getCenterpoint() != nullptr)
+                    stone->addTemplate(this->tetris_->getCenterpoint()->getStoneTemplate());
+                else
+                    orxout()<< "tetris_->getCenterpoint == nullptr in TetrisBrick.cc"<< endl;
+            }
+            else
+                orxout()<< "tetris_ == nullptr in TetrisBrick.cc"<< endl;
+        }
+    }
+
+    /**
+    @brief
+        This function creates the shape of a TetrisBrick. ! Spaghetti-Code !
+    @param i
+        The stone's number.
+    @param stone
+        The TetrisStone that is placed relative to the brick's position.
+    */
+    void TetrisBrick::formBrick(TetrisStone* stone, unsigned int i)
+    {
+        if(i == 0) //setting the first stone as
+        {
+            stone->setPosition(0.0f, 0.0f, 0.0f);
+        }
+        else if(i == 1)
+        {
+            stone->setPosition(0.0f, size_, 0.0f);
+        }
+        else if(i == 2)
+        {
+            if(this->shapeIndex_ == 1 || this->shapeIndex_ == 6 || this->shapeIndex_ == 7)
+            {
+                stone->setPosition(0.0f, 2*size_, 0.0f);
+            }
+            else if(this->shapeIndex_ == 3 || this->shapeIndex_ == 4|| this->shapeIndex_ == 5)
+            {
+                stone->setPosition(size_, 0, 0.0f);
+            }
+            else if(this->shapeIndex_ == 2)
+            {
+                stone->setPosition(-size_, 0, 0.0f);
+            }
+        }
+        else if(i == 3)
+        {
+            if(this->shapeIndex_ == 2 || this->shapeIndex_ == 5)
+            {
+                stone->setPosition(size_, size_, 0.0f);
+            }
+            else if(this->shapeIndex_ == 1)
+            {
+                stone->setPosition(0, 3*size_, 0.0f);
+            }
+            else if(this->shapeIndex_ == 3 || this->shapeIndex_ == 7)
+            {
+                stone->setPosition(-size_, 0, 0.0f);
+            }
+            else if(this->shapeIndex_ == 4)
+            {
+                stone->setPosition(-size_, size_, 0.0f);
+            }
+            else if(this->shapeIndex_ == 6)
+            {
+                stone->setPosition(size_, 0, 0.0f);
+            }
+        }
+    }
+
+    bool TetrisBrick::isValidMove(const Vector3& position, bool isRotation = false)
+    {
+        return this->tetris_->isValidMove(this,position, isRotation);
+    }
+
+    TetrisStone* TetrisBrick::getStone(unsigned int i)
+    {
+        if(i < this->brickStones_.size())
+            return this->brickStones_[i];
+        else return nullptr;
+    }
+
+
+    Tetris* TetrisBrick::getTetris()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Tetris)))
+        {
+            Tetris* tetrisGametype = orxonox_cast<Tetris*>(this->getGametype());
+            return tetrisGametype;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Overloaded the function to rotate the Brick.
+    @param value
+        A vector whose first component is the angle by which to rotate.
+    */
+    void TetrisBrick::moveFrontBack(const Vector2& value)
+    {
+        if(value.x < 0) //speedup on key down
+        {
+            Vector3 v_new = this->getVelocity()*1.2;
+            if (v_new.y < -400.0f) //limiting the speed to prevent break throughs.
+                v_new.y = -400.0f;
+            this->setVelocity(v_new);
+        }
+        else if(!this->lockRotation_) //rotate when key up is pressed
+        {
+            if(!isValidMove(this->getPosition(), true)) //catch illegal rotations
+                return;
+            this->lockRotation_ = true; // multiple calls of this function have to be filtered out.
+            this->rotationTimer_.setTimer(0.1f, false, createExecutor(createFunctor(&TetrisBrick::unlockRotation, this)));
+            Quaternion q(Degree(90), Vector3::UNIT_Z);
+            this->setOrientation(this->getOrientation()*q); //rotation: roll 90°
+            this->rotationCount_ = (this->rotationCount_ + 1) % 4;
+        }
+    }
+
+    /**
+    @brief
+        Overloaded the function to steer the Brick right and left
+    @param value
+        A vector whose first component is the direction in which we want to steer the Brick.
+    */
+    void TetrisBrick::moveRightLeft(const Vector2& value)
+    {
+        if(!this->delay_)
+        {
+            const Vector3& position = this->getPosition();
+            Vector3 newPos = Vector3(position.x+value.x/std::abs(value.x)*this->size_, position.y, position.z);
+            if(!this->isValidMove(newPos))
+                return;
+
+            this->setPosition(newPos);
+            this->delay_ = true;
+            this->delayTimer_.startTimer();
+        }
+    }
+
+    /**
+    @brief
+        Is called when the player changed.
+    */
+    void TetrisBrick::changedPlayer()
+    {
+        this->setVelocity(0.0f, 0.0f, 0.0f);
+    }
+
+    /**
+    @brief
+        Attaches stones to the Centerpoint.
+    */
+    void TetrisBrick::releaseStones(TetrisCenterpoint* center)
+    {
+        assert(this->tetris_);
+        for(TetrisStone* stone : this->brickStones_)
+        {
+            stone->detachFromParent();
+            stone->attachToParent(center);
+            stone->setPosition(this->getPosition()+this->tetris_->rotateVector(stone->getPosition(),this->rotationCount_ ));
+        }
+        this->brickStones_.clear();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisBrick.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisBrick.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisBrick.h	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisBrick.h
+    @brief Declaration of the TetrisBrick class.
+    @ingroup Tetris
+*/
+
+#ifndef _TetrisBrick_H__
+#define _TetrisBrick_H__
+
+#include "tetris/TetrisPrereqs.h"
+
+#include "worldentities/ControllableEntity.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        ContainerClass in order to create TetrisBricks by combining TetrisStones.
+    @author
+
+    @ingroup Tetris
+    */
+    class _TetrisExport TetrisBrick : public ControllableEntity
+    {
+        public:
+            TetrisBrick(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~TetrisBrick() {}
+
+            virtual void moveFrontBack(const Vector2& value) override; //!< Overloaded the function to steer the bat up and down.
+            virtual void moveRightLeft(const Vector2& value) override; //!< Overloaded the function to steer the bat up and down.
+            virtual void changedPlayer() override; //!< Is called when the player changed.
+
+            bool isValidMove(const Vector3& position, bool isRotation);
+            unsigned int getNumberOfStones(void) const
+                { return this->brickStones_.size(); }
+            TetrisStone* getStone(unsigned int i);
+
+            void setGame(Tetris* tetris)
+                { assert(tetris); tetris_ = tetris; }
+            unsigned int getRotationCount(void)
+                { return this->rotationCount_;}
+
+            void releaseStones(TetrisCenterpoint* center);
+
+        protected:
+            void createBrick(void); //!< Create a cluster of TetrisStones
+            void formBrick(TetrisStone* stone, unsigned int i);
+            Tetris* getTetris();
+
+            unsigned int shapeIndex_; //!< My way to represent the different brick shapes.
+            unsigned int stonesPerBrick_; //!< So many stones are contained in this brick.
+            std::vector<TetrisStone*> brickStones_; //!< A list of all stones in a brick.
+
+
+            void enableMovement(void)
+                { this->delay_ = false; }
+            void unlockRotation(void)
+                { this->lockRotation_ = false; }
+
+            float getSize(void) const
+                { return this->size_; }
+
+
+            float size_; //!< The dimensions a stone has in the game world. //TODO: get stone dimensions
+            bool delay_;
+            bool lockRotation_;
+
+            unsigned int rotationCount_; //!< Stores the bricks orientation
+            Timer delayTimer_;
+            Timer rotationTimer_; ///!< This timer is used to filter out multiple rotation inputs.
+            Tetris* tetris_; //<! The Tetris class is responsible to initialize this value.
+
+    };
+}
+
+#endif /* _TetrisBrick_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisCenterpoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisCenterpoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisCenterpoint.cc	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisCenterpoint.cc
+    @brief Implementation of the TetrisCenterpoint class.
+    @ingroup Tetris
+*/
+
+#include "TetrisCenterpoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Tetris.h"
+
+namespace orxonox
+{
+    RegisterClass(TetrisCenterpoint);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object and checks whether the gametype is actually Tetris.
+    */
+    TetrisCenterpoint::TetrisCenterpoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(TetrisCenterpoint);
+
+        this->width_ = 10;
+        this->height_ = 11;
+        this->stoneSize_ = 10.0f;
+        this->stoneTemplate_ = "";
+        this->brickTemplate_ = "";
+        this->stoneSpeed_ = 20.0f;
+        
+        this->checkGametype();
+    }
+
+    /**
+    @brief
+        Method to create a TetrisCenterpoint through XML.
+    */
+    void TetrisCenterpoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TetrisCenterpoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(TetrisCenterpoint, "width", setWidth, getWidth, xmlelement, mode); // die Breite
+        XMLPortParam(TetrisCenterpoint, "height", setHeight, getHeight, xmlelement, mode); // die Grösse //was sollte das mit setWidth??
+        XMLPortParam(TetrisCenterpoint, "stoneSize", setStoneSize, getStoneSize, xmlelement, mode); 
+        XMLPortParam(TetrisCenterpoint, "stoneTemplate", setStoneTemplate, getStoneTemplate, xmlelement, mode);
+        XMLPortParam(TetrisCenterpoint, "brickTemplate", setBrickTemplate, getBrickTemplate, xmlelement, mode);
+        XMLPortParam(TetrisCenterpoint, "stoneSpeed", setStoneSpeed, getStoneSpeed, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Checks whether the gametype is Tetris and if it is, sets its centerpoint.
+    */
+    void TetrisCenterpoint::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(Tetris)))
+        {
+            Tetris* tetrisGametype = orxonox_cast<Tetris*>(this->getGametype());
+            tetrisGametype->setCenterpoint(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisCenterpoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisCenterpoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisCenterpoint.h	(revision 11817)
@@ -0,0 +1,157 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisCenterpoint.h
+    @brief Declaration of the TetrisCenterpoint class.
+    @ingroup Tetris
+*/
+
+#ifndef _TetrisCenterpoint_H__
+#define _TetrisCenterpoint_H__
+
+#include "tetris/TetrisPrereqs.h"
+
+#include <string>
+
+#include <util/Math.h>
+
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{//idea: add 2 triggers to the centerpoint (one to determine when a box would go above the centerpoint;
+//the other to find out when the lowest row is filled totally)
+    
+    /**
+    @brief
+        
+    
+    @author
+        
+    @ingroup Tetris
+    */
+    class _TetrisExport TetrisCenterpoint : public StaticEntity
+    {
+        public:
+            TetrisCenterpoint(Context* context); //!< Constructor. Registers and initializes the object and checks whether the gametype is actually Tetris.
+            virtual ~TetrisCenterpoint() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method to create a TetrisCenterpoint through XML.
+
+            /**
+            @brief Set the width of the playing field.
+            @param width The width in number of tiles.
+            */
+            void setWidth(unsigned int width)
+                { this->width_ = width; }
+            /**
+            @brief Get the width of the playing field.
+            @return Returns the width in number of tiles.
+            */
+            unsigned int getWidth(void) const
+                { return this->width_; }
+                
+            /**
+            @brief Set the height of the playing field.
+            @param height The height in number of tiles.
+            */
+            void setHeight(unsigned int height)
+                { this->height_ = height; }
+            /**
+            @brief Get the height of the playing field.
+            @return Returns the height in number of tiles.
+            */
+            unsigned int getHeight(void) const
+                { return this->height_; }
+                
+            /**
+            @brief Set the size of a single stone.
+            @param size The dimensions a stone has in the game world. (A stone is a cube)
+            */
+            void setStoneSize(float size)
+                { this->stoneSize_ = size; }
+            /**
+            @brief Get the size of a single stone.
+            @return Returns the dimensions a stone has in the game world.
+            */
+            float getStoneSize(void) const
+                { return this->stoneSize_; }
+                
+            /**
+            @brief Set the template for the stones.
+            @param templateName The template name to be applied to each stone.
+            */
+            void setStoneTemplate(const std::string& templateName)
+                { this->stoneTemplate_ = templateName; }
+            /**
+            @brief Get the template for the stones.
+            @return Returns the template name to be applied to each stone.
+            */
+            const std::string& getStoneTemplate(void) const
+                { return this->stoneTemplate_; }
+            
+            /**
+            @brief Set the template for the bricks.
+            @param templateName The template name to be applied to each brick.
+            */
+            void setBrickTemplate(const std::string& templateName)
+                { this->brickTemplate_ = templateName; }
+            /**
+            @brief Get the template for the bricks.
+            @return Returns the template name to be applied to each brick.
+            */
+            const std::string& getBrickTemplate(void) const
+                { return this->brickTemplate_; }
+
+            /**
+            @brief Set the speed of the stones.
+            @param speed The speed to be set.
+            */
+            void setStoneSpeed(float speed)
+                { this->stoneSpeed_ = speed; }
+            /**
+            @brief Get the speed of the stones.
+            @return Returns the speed a moving stone has.
+            */
+            float getStoneSpeed(void)
+                { return this->stoneSpeed_; }
+
+        private:
+            void checkGametype(); //!< Checks whether the gametype is Tetris and if it is, sets its centerpoint.
+            
+            unsigned int width_;
+            unsigned int height_;
+            float stoneSize_;
+            std::string stoneTemplate_;
+            std::string brickTemplate_;
+            float stoneSpeed_;
+
+    };
+}
+
+#endif /* _TetrisCenterpoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisPrereqs.h	(revision 11817)
@@ -0,0 +1,74 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the tetris module
+*/
+
+#ifndef _TetrisPrereqs_H__
+#define _TetrisPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(TETRIS_STATIC_BUILD)
+#  ifdef TETRIS_SHARED_BUILD
+#    define _TetrisExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _TetrisExport
+#    else
+#      define _TetrisExport __declspec(dllimport)
+#    endif
+#  endif
+#elif defined ( ORXONOX_GCC_VISIBILITY )
+#  define _TetrisExport  __attribute__ ((visibility("default")))
+#else
+#  define _TetrisExport
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class Tetris;
+    class TetrisCenterpoint;
+    class TetrisStone;
+    class TetrisBrick;
+    class TetrisScore;
+}
+
+#endif /* _TetrisPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisScore.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisScore.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisScore.cc	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisScore.cc
+    @brief Implementation of the TetrisScore class.
+    @ingroup Tetris
+*/
+
+#include "TetrisScore.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Convert.h"
+
+#include "infos/PlayerInfo.h"
+
+#include "Tetris.h"
+
+namespace orxonox
+{
+    RegisterClass(TetrisScore);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    @ingroup Tetris
+    */
+    TetrisScore::TetrisScore(Context* context) : OverlayText(context)
+    {
+        RegisterObject(TetrisScore);
+
+        this->owner_ = nullptr;
+        this->player_ = nullptr;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    TetrisScore::~TetrisScore()
+    {
+    }
+
+    /**
+    @brief
+        Is called each tick.
+        Creates and sets the caption to be displayed by the TetrisScore.
+    @param dt
+        The time that has elapsed since the last tick.
+    */
+    void TetrisScore::tick(float dt)
+    {
+        SUPER(TetrisScore, tick, dt);
+
+        // If the owner is set. The owner being a Tetris game.
+        if (this->owner_ != nullptr)
+        {
+            std::string score("0");
+            if(!this->owner_->hasEnded())
+            {
+                //get the player
+                player_ = this->owner_->getPlayer();
+            }
+
+            if(this->owner_->hasStarted())
+            {
+                // Save the name and score of each player as a string.
+                if (player_ != nullptr)
+                    score = multi_cast<std::string>(this->owner_->getScore(player_));
+            }
+            this->setCaption(score);
+        }
+    }
+
+    /**
+    @brief
+        Is called when the owner changes.
+        Sets the owner to nullptr, if it is not a pointer to a Tetris game.
+    */
+    void TetrisScore::changedOwner()
+    {
+        SUPER(TetrisScore, changedOwner);
+
+        if (this->getOwner() != nullptr && this->getOwner()->getGametype())
+            this->owner_ = orxonox_cast<Tetris*>(this->getOwner()->getGametype());
+        else
+            this->owner_ = nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisScore.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisScore.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisScore.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisScore.h
+    @brief Declaration of the TetrisScore class.
+    @ingroup Tetris
+*/
+
+#ifndef _TetrisScore_H__
+#define _TetrisScore_H__
+
+#include "tetris/TetrisPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+
+#include "overlays/OverlayText.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The TetrisScore class displays the score for a game of @ref orxonox::Tetris "Tetris".
+
+    @author
+        Johannes Ritz
+
+    @ingroup Tetris
+    */
+    class _TetrisExport TetrisScore : public OverlayText, public Tickable
+    {
+        public:
+            TetrisScore(Context* context);
+            virtual ~TetrisScore();
+
+            virtual void tick(float dt) override; //!< Creates and sets the caption to be displayed by the TetrisScore.
+            virtual void changedOwner() override; //!< Is called when the owner changes.
+
+        private:
+            Tetris* owner_; //!< The Tetris game that owns this TetrisScore.
+            PlayerInfo* player_; //!< Store information about the player permanently.
+    };
+}
+#endif /* _TetrisScore_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisStone.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisStone.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisStone.cc	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisStone.cc
+    @brief Implementation of the TetrisStone class.
+    @ingroup Tetris
+*/
+
+#include "TetrisStone.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Tetris.h"
+
+namespace orxonox
+{
+    RegisterClass(TetrisStone);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    TetrisStone::TetrisStone(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(TetrisStone);
+
+        this->size_ = 10.0f;
+        this->delay_ = false;
+        this->delayTimer_.setTimer(0.2f, false, createExecutor(createFunctor(&TetrisStone::enableMovement, this)));
+        this->lockRotation_ = false;
+
+    }
+
+    /**
+    @brief
+        Overloaded the function to rotate the stone.
+    @param value
+        A vector whose first component is the angle by which to rotate.
+    */
+    void TetrisStone::moveFrontBack(const Vector2& value)
+    {
+        if(value.x < 0) //speedup on key down
+        {
+            this->setVelocity(this->getVelocity()*1.1);
+        }
+        else if(!this->lockRotation_) //rotate when key up is pressed
+        {
+            this->lockRotation_ = true; // multiple calls of this function have to be filtered out.
+            this->rotationTimer_.setTimer(0.1f, false, createExecutor(createFunctor(&TetrisStone::unlockRotation, this)));
+            Quaternion q(Degree(90), Vector3::UNIT_Z);
+            this->setOrientation(this->getOrientation()*q); //rotation: roll 90°
+
+        }
+    }
+
+    /**
+    @brief
+        Overloaded the function to steer the stone right and left
+    @param value
+        A vector whose first component is the direction in which we want to steer the stone.
+    */
+    void TetrisStone::moveRightLeft(const Vector2& value)
+    {
+        if(!this->delay_)
+        {
+            const Vector3& position = this->getPosition();
+            Vector3 newPos = Vector3(position.x+value.x/std::abs(value.x)*this->size_, position.y, position.z);
+            if(!this->tetris_->isValidMove(this, newPos))
+                return;
+
+            this->setPosition(newPos);
+            this->delay_ = true;
+            this->delayTimer_.startTimer();
+        }
+    }
+
+    /**
+    @brief
+        Is called when the player changed.
+    */
+    void TetrisStone::changedPlayer()
+    {
+        this->setVelocity(0, 0, 0);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/tetris/TetrisStone.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/tetris/TetrisStone.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/tetris/TetrisStone.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TetrisStone.h
+    @brief Declaration of the TetrisStone class.
+    @ingroup Tetris
+*/
+
+#ifndef _TetrisStone_H__
+#define _TetrisStone_H__
+
+#include "tetris/TetrisPrereqs.h"
+
+#include "worldentities/MovableEntity.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+
+    @author
+
+    @ingroup Tetris
+    */
+    class _TetrisExport TetrisStone : public MovableEntity
+    {
+        public:
+            TetrisStone(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~TetrisStone() {}
+
+            virtual void moveFrontBack(const Vector2& value); //!< Overloaded the function to steer the bat up and down.
+            virtual void moveRightLeft(const Vector2& value); //!< Overloaded the function to steer the bat up and down.
+
+            virtual void changedPlayer(); //!< Is called when the player changed.
+
+            /**
+            @brief Set the size of the stone.
+            @param size The dimensions a stone has in the game world. (A stone is a cube)
+            */
+            void setSize(float size)
+                { this->size_ = size; }
+            /**
+            @brief Get the size of the stone.
+            @return Returns the dimensions a stone has in the game world. (A stone is a cube)
+            */
+            float getSize(void) const
+                { return this->size_; }
+
+            void setGame(Tetris* tetris)
+                { assert(tetris); tetris_ = tetris; }
+
+        private:
+            void enableMovement(void)
+                { this->delay_ = false; }
+            void unlockRotation(void)
+                { this->lockRotation_ = false; }
+
+            float size_; //!< The dimensions a stone has in the game world.
+            bool delay_;
+            bool lockRotation_;
+            Timer delayTimer_;
+            Timer rotationTimer_; ///!< This timer is used to filter out multiple rotation inputs.
+
+            Tetris* tetris_;
+    };
+}
+
+#endif /* _TetrisStone_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,22 @@
+SET_SOURCE_FILES(TOWERDEFENSE_SRC_FILES
+  TowerDefense.cc
+  TowerDefenseTower.cc
+  TowerDefenseCenterpoint.cc
+  TowerDefenseHUDController.cc
+  TowerDefensePlayerStats.cc
+  TDCoordinate.cc
+  TowerDefenseEnemy.cc
+  TowerDefenseSelecter.cc
+  TowerDefenseField.cc
+  TDCoordinate.cc
+)
+
+ORXONOX_ADD_LIBRARY(towerdefense
+  PLUGIN
+  FIND_HEADER_FILES
+  LINK_LIBRARIES
+    orxonox
+    overlays
+    objects
+  SOURCE_FILES ${TOWERDEFENSE_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TDCoordinate.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TDCoordinate.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TDCoordinate.cc	(revision 11817)
@@ -0,0 +1,75 @@
+#include "TDCoordinate.h"
+
+#include "towerdefense/TowerDefensePrereqs.h"
+
+
+
+
+namespace orxonox
+{
+    /**
+    @brief
+        Constructor. Sets the default coordinates: (0,0)
+    */
+    TDCoordinate::TDCoordinate()
+    {
+        Set(0,0);
+    }
+
+    TDCoordinate::TDCoordinate(int x, int y)
+    {        
+        Set(x,y);
+    }
+
+    void TDCoordinate::Set(int x, int y)
+    {        
+        if (x < 0)
+        {
+            _x = 0;
+        }
+        else if (x > 15)
+        {
+            _x = 15;
+        }
+        else
+        {
+            _x = x;
+        }
+
+        if (y < 0)
+        {
+            _y = 0;
+        }
+        else if (y > 15)
+        {
+            _y = 15;
+        }
+        else
+        {
+            _y = y;
+        }
+    }
+
+    int TDCoordinate::GetX()
+    {        
+        return _x;
+    }
+
+    int TDCoordinate::GetY()
+    {        
+        return _y;
+    }
+
+
+    Vector3 TDCoordinate::get3dcoordinate()
+    {
+        float tileScale = 100;
+
+        Vector3 coord;
+        coord.x= (_x-8) * tileScale;
+        coord.y= (_y-8) * tileScale;
+        coord.z=0;
+
+        return coord;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TDCoordinate.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TDCoordinate.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TDCoordinate.h	(revision 11817)
@@ -0,0 +1,33 @@
+#ifndef _TDCoordinate_H__
+#define _TDCoordinate_H__
+
+#include "core/CoreIncludes.h"
+#include "TDCoordinate.h"
+//#include "towerdefense/TowerDefense.h"
+#include "gametypes/Deathmatch.h"
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "worldentities/pawns/SpaceShip.h"
+namespace orxonox
+{
+
+//Class to save the Coordinates in a class instead of struct
+//Convert 2d coordinates to 3d in order to set waypoints
+    class _TowerDefenseExport TDCoordinate
+    {
+        public:
+            TDCoordinate();
+            TDCoordinate(int x, int y);
+            virtual ~TDCoordinate() {};
+            virtual void Set(int x, int y);
+            virtual int GetX();
+            virtual int GetY();
+            virtual Vector3 get3dcoordinate();
+
+        private:
+            int _x;
+            int _y;
+    };
+
+}
+
+#endif /* _TDCoordinate_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefense.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefense.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefense.cc	(revision 11817)
@@ -0,0 +1,417 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *  Author:
+ *
+ *   Co-authors:
+ *      ...
+ *
+ *NACHRICHT:
+ *
+ * Hier empfehle ich euch die gesamte Spielogik unter zu bringen. Viele Funktionen werden automatisch
+ * bei gewissen Ereignissen aufgerufen bzw. lösen Ereignisse aus
+ *
+ *Z.B:
+ * start() //wird aufgerufen, bevor das Spiel losgeht
+ * end() //wenn man diese Funktion aufruft wird
+ * pawnKilled() // wird aufgerufen, wenn ein Pawn stirbt (z.B: wenn )
+ * playerScored() // kann man aufrufen um dem Spieler Punkte zu vergeben.
+ *
+ *
+ *TIPP: Eclipse hilft euch schnell auf bereits vorhanden Funktionen zuzugreifen:
+ * einfach "this->" eingeben und kurz warten. Dann tauch eine Liste mit Vorschlägen auf. Wenn ihr jetzt weiter
+ * tippt, werden die Vorschläge entsprechend gefiltert.
+ *
+ *
+ *TIPP: schaut euch mal Tetris::createStone() an. Dort wird ein TetrisStone-Objekt (ControllableEntity) erzeugt,
+ * ihm ein Template zugewiesen (welches vorher im Level definiert wurde und dem CenterPoint übergeben wurde)
+ * Ähnlich könnt ihr vorgehen, um einen Turm zu erzeugen. (Zusätzlich braucht ein Turm noch einen Controller)
+ * z.B: WaypointPatrolController. Wenn kein Team zugewiesen wurde bekämpft ein WaypointPatrolController alles,
+ * was in seiner Reichweite liegt.
+ *
+ *
+ *HUD:
+ * Ein Gametype kann ein HUD (Head up Display haben.) Z.B: hat Pong eine Anzeige welcher Spieler wieviele Punkte hat.
+ * Generell kann man a) Grafiken oder b) Zeichen in einer HUD anzeigen.
+ * Fuer den ersten Schritt reicht reiner Text.
+ *
+ * a)
+ * PongScore.cc uebernehmen und eigene Klasse draus machen.
+ * Wenn ihr bloss anzeigen wollt wieviele Punkte der Spieler bereits erspielt hat (Punkte = Kapital fuer neue Tuerme) dann orientiert ihr euch an
+ * TetrisScore.cc (im pCuts branch): http://www.orxonox.net/browser/code/branches/pCuts/src/modules/tetris/TetrisScore.cc
+ * Ich habe TetrisScore lediglich dazu gebraucht, um eine Variable auf dem HUD auszugeben. Ein Objekt fuer statischen Text gibt es bereits.
+ *
+ * b)
+ * Im naesten Schritt erstellt man die Vorlage fuer das HUD-Objekt: siehe /data/overlays/pongHUD
+ * OverlayText ist eine Vorlage fuer statischen text zb: "Points Scored:". Aus mir nicht erklaerlichen Gruenden sollte man die OverlayText
+ * Objekte immer erst nach dem PongScore anlegen.
+ *
+ * c)  Im TowerDefense gamtype muss im Constructor noch das HUD-Template gesetzt werden.
+ *
+ * d) in CMakeLists.txt noch das Module includen das fuer die Overlays zustaendig ist. Siehe das gleiche File im Pong module.
+ *
+ *
+ *
+ */
+#include "TowerDefense.h"
+#include "TowerDefenseTower.h"
+#include "TowerDefenseCenterpoint.h"
+#include "worldentities/SpawnPoint.h"
+#include "controllers/WaypointController.h"
+#include "graphics/Model.h"
+#include "infos/PlayerInfo.h"
+#include "chat/ChatManager.h"
+#include "core/CoreIncludes.h"
+#include "Highscore.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(TowerDefense);
+
+    TowerDefense::TowerDefense(Context* context) : TeamDeathmatch(context)
+    {
+        RegisterObject(TowerDefense);
+
+        selecter = nullptr;
+        this->player_ = nullptr;
+        this->setHUDTemplate("TowerDefenseHUD");
+        this->waveNumber_ = 0;
+        this->timeSinceLastSpawn_ = 0.0;
+        this->timeUntilNextWave_ = 0.0;
+        this->credit_ = 0;
+        this->lifes_ = 0;
+        this->waveSize_ = 0;
+        offset_ = Vector3(0,0,10);
+    }
+
+    TowerDefense::~TowerDefense()
+    {
+        if (this->isInitialized())
+        {
+
+        }
+    }
+
+    void TowerDefense::setCenterpoint(TowerDefenseCenterpoint *centerpoint)
+    {
+        this->center_ = centerpoint;
+    }
+
+    void TowerDefense::start()
+    {        
+        if (center_ != nullptr) // There needs to be a TowerDefenseCenterpoint, i.e. the area the game takes place.
+        {
+            if (selecter == nullptr)
+            {
+                selecter = new TowerDefenseSelecter(this->center_->getContext());                
+            }
+            selecter->addTemplate(center_->getSelecterTemplate());
+            center_->attach(selecter);
+        }
+        else // If no centerpoint was specified, an error is thrown and the level is exited.
+        {
+            orxout(internal_error) << "Jump: No Centerpoint specified." << endl;
+            return;
+        }
+
+        enemies_.clear();
+
+        createFields();
+        TeamDeathmatch::start();
+
+        //set initial credits, lifes and WaveNumber
+        this->setCredit(1000);
+        this->setLifes(100);        
+        this->timeSinceLastSpawn_ = 0.0;
+        this->timeUntilNextWave_ = 5.0;
+        this->waveSize_ = 0;
+        this->setWaveNumber(0);
+    }
+
+    // Generates a TowerDefenseEnemy. Uses Template "enemytowerdefense". Sets position at first waypoint of path.
+    void TowerDefense::addTowerDefenseEnemy(int templatenr)
+    {
+        TowerDefenseEnemy* en1 = new TowerDefenseEnemy(this->center_->getContext());
+        
+        switch(templatenr)
+        {
+        case 1 :
+            en1->addTemplate("enemytowerdefense1");
+            en1->setScale(3);
+            en1->setHealth(en1->getHealth() + this->getWaveNumber()*4);
+            break;
+
+        case 2 :
+            en1->addTemplate("enemytowerdefense2");
+            en1->setScale(2);
+            en1->setHealth(en1->getHealth() + this->getWaveNumber()*4);
+            break;
+
+        case 3 :
+            en1->addTemplate("enemytowerdefense3");
+            en1->setScale(1);
+            en1->setHealth(en1->getHealth() + this->getWaveNumber()*4);
+            break;
+        }        
+
+        en1->setTeam(2);
+
+        WaypointController* controller = (WaypointController*)(en1->getXMLController());
+
+        if (controller != nullptr && waypoints_.size() > 1)
+        {
+            en1->setPosition(waypoints_.at(0)->getPosition() + offset_);
+            en1->setOrientation(Vector3(0,0,10), Degree(0));
+            en1->setDirection(Vector3(0,1,0));
+            en1->lookAt(waypoints_.at(1)->getPosition() + offset_);
+
+            for (TowerDefenseField* field : waypoints_)
+            {
+                orxonox::WeakPtr<MovableEntity> waypoint = new MovableEntity(this->center_->getContext());
+                waypoint->setPosition(field->getPosition() + offset_);
+                controller->addWaypoint(waypoint);
+            }
+        }
+
+        enemies_.push_back(en1);
+    }
+
+
+    void TowerDefense::end()
+    {
+        if (Highscore::exists())
+        {
+            int score = this->getWaveNumber();
+            Highscore::getInstance().storeScore("Tower Defense", score, this->getPlayer());
+        }
+        TeamDeathmatch::end();
+        ChatManager::message("Match is over! Gameover!");
+
+    }
+
+    void TowerDefense::spawnPlayer(PlayerInfo* player)
+    {
+        assert(player);
+        player_ = player;
+
+        if (selecter->getPlayer() == nullptr)
+        {
+            player_->startControl(selecter);
+            players_[player].state_ = PlayerState::Alive;
+        } 
+    }
+
+    /**
+    @brief
+        Get the player.
+    @return
+        Returns a pointer to the player. If there is no player, nullptr is returned.
+    */
+    PlayerInfo* TowerDefense::getPlayer(void) const
+    {
+        return this->player_;
+    }
+
+    //not working yet
+    void TowerDefense::addTower(int x,int y)
+    {
+        TDCoordinate* coord = new TDCoordinate(x,y);
+        x = coord->GetX();
+        y = coord->GetY();
+
+        int cost = center_->getTowerCost(1);
+
+        if (fields_[x][y]->isFree() == true && getCredit() >= cost)
+        {
+            payCredit(cost);
+            fields_[x][y]->createTower(1);
+        }
+    }
+
+    /*adds Tower at Position (x,y) and reduces credit and adds the point to the towermatrix. template ("towerturret")
+    so towers have ability if the turrets
+    */
+
+    void TowerDefense::upgradeTower(int x, int y)
+    {    
+        TDCoordinate* coord = new TDCoordinate(x,y);
+        x = coord->GetX();
+        y = coord->GetY();     
+
+        int cost = center_->getTowerCost(fields_[x][y]->getUpgrade() + 1);
+
+        if (fields_[x][y]->isFree() == false && fields_[x][y]->canUpgrade() == true && getCredit() >= cost)
+        {
+            payCredit(cost);
+            fields_[x][y]->upgrade();
+        }
+    }    
+
+    void TowerDefense::tick(float dt)
+    {
+        SUPER(TowerDefense, tick, dt);
+
+        if (hasStarted() == false || player_ == nullptr)
+        {
+            return;
+        }
+        timeUntilNextWave_ -= dt;
+        timeSinceLastSpawn_ += dt;
+
+        //build/upgrade tower at selecter position
+        if (selecter != nullptr && selecter->buildTower_ == true)
+        {
+            selecter->buildTower_ = false;
+
+            if (getField(selecter->selectedPos_)->canUpgrade() == true)
+            {
+                upgradeTower(selecter->selectedPos_->GetX(), selecter->selectedPos_->GetY());
+            }
+            else
+            {
+                addTower(selecter->selectedPos_->GetX(), selecter->selectedPos_->GetY());
+            }            
+        }
+        
+        for (std::list<WeakPtr<TowerDefenseEnemy>>::iterator it = enemies_.begin(); it != enemies_.end(); )
+        {
+            if (*it == nullptr)
+            {
+                // the enemy was destroyed by a tower - remove it from the list
+                enemies_.erase(it++);
+                addCredit(1);
+            }
+            else
+            {
+                //if ships are at the end they get destroyed
+                Vector3 ship = (*it)->getRVWorldPosition();
+                float distance = ship.distance(endpoint_);
+                if(distance < 40)
+                {
+                    (*it)->destroy();
+                    enemies_.erase(it++);
+                    this->reduceLifes(1);
+                    if (this->getLifes() == 0)
+                    {
+                        this->end();
+                    }
+                }
+                else
+                {
+                    ++ it;
+                }
+            }
+        }  
+
+        // Add new enemy?
+        if (timeSinceLastSpawn_ >= 1.0 && waveSize_ > 0)
+        {
+            // Add new enemy
+            timeSinceLastSpawn_ -= 1.0;
+            -- waveSize_;
+            addTowerDefenseEnemy(this->getWaveNumber() % 3 + 1);
+        }
+        else if (timeUntilNextWave_ <= 0.0 && waveSize_ <= 0)
+        {
+            //New wave
+            ++ waveNumber_;
+            timeSinceLastSpawn_ = 0.0;
+
+            timeUntilNextWave_ = waveNumber_+20.0f;
+            waveSize_ = waveNumber_+5;
+        }
+
+    }
+
+    void TowerDefense::createFields()
+    {
+        assert(center_);
+        TDCoordinate coord(0,0);
+        TDCoordinate startCoord(0,0);
+        std::string fields = center_->getFields();
+        int pos = 0;
+        for (int j = 15; j >= 0; --j)
+        {
+            for (int i = 0; i < 16; ++i)
+            {
+                coord.Set(i,j);
+                fields_[i][j] = new TowerDefenseField(center_->getContext());
+                fields_[i][j]->setCenterpoint(center_);
+                center_->attach(fields_[i][j]);
+                fields_[i][j]->setPosition(coord.get3dcoordinate()); 
+                fields_[i][j]->create(fields.at(pos), fields.at(pos+1));
+                pos += 2;
+                if (fields_[i][j]->getType() == TowerDefenseFieldType::START)
+                {
+                    startCoord.Set(i,j);
+                    waypoints_.push_back(fields_[i][j]);
+                }
+            }
+        }
+        //Place waypoints along the street for the waypoint controllers of the enemies
+        TDCoordinate* thisCoord = &startCoord;
+        TDCoordinate* nextCoord;
+        while ((nextCoord = getNextStreetCoord(thisCoord)) != nullptr)
+        {
+            waypoints_.push_back(fields_[nextCoord->GetX()][nextCoord->GetY()]);            
+            thisCoord = nextCoord;
+            endpoint_ = nextCoord->get3dcoordinate();
+        }
+
+    }
+
+    TDCoordinate* TowerDefense::getNextStreetCoord(TDCoordinate* thisCoord)
+    {        
+        TowerDefenseField* thisField = fields_[thisCoord->GetX()][thisCoord->GetY()];
+
+        if (thisField->getType() != TowerDefenseFieldType::STREET && thisField->getType() != TowerDefenseFieldType::START)
+        {
+            return nullptr;
+        }
+
+        TDCoordinate* nextCoord = new TDCoordinate(0, 0);
+
+        if (thisField->getAngle() == 0)
+        {
+            nextCoord->Set(thisCoord->GetX(), thisCoord->GetY() - 1);
+        }
+        else if (thisField->getAngle() == 1)
+        {
+            nextCoord->Set(thisCoord->GetX() + 1, thisCoord->GetY());
+        }
+        else if (thisField->getAngle() == 2)
+        {
+            nextCoord->Set(thisCoord->GetX(), thisCoord->GetY() + 1);
+        }
+        else if (thisField->getAngle() == 3)
+        {
+            nextCoord->Set(thisCoord->GetX() - 1, thisCoord->GetY());
+        }
+
+        if (thisCoord->GetX() != nextCoord->GetX() || thisCoord->GetY() != nextCoord->GetY())
+        {
+            return nextCoord;
+        }
+
+        delete nextCoord;
+        return nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefense.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefense.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefense.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _TowerDefense_H__
+#define _TowerDefense_H__
+#include "TDCoordinate.h"
+#include "TowerDefenseSelecter.h"
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "gametypes/TeamDeathmatch.h"
+#include "TowerDefenseEnemy.h"
+#include "util/Output.h"
+#include "TowerDefenseField.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+    GameType class for TowerDefense. See TowerDefenseReadme.txt for Information.
+
+    @ingroup TowerDefense
+    */
+    class _TowerDefenseExport TowerDefense : public TeamDeathmatch
+    {
+    public:
+        TowerDefense(Context* context);
+        virtual ~TowerDefense();        
+        void addTowerDefenseEnemy(int templatenr);
+        virtual void start() override; //<! The function is called when the gametype starts
+        virtual void end() override;
+        virtual void tick(float dt) override;
+        virtual void spawnPlayer(PlayerInfo* player) override;
+        PlayerInfo* getPlayer(void) const;
+        int getCredit(){ return this->credit_; }
+        void payCredit(int pay){ this->credit_ -= pay; }
+        int getLifes(){ return this->lifes_; }
+        int getWaveNumber(){ return this->waveNumber_; }
+        void setWaveNumber(int wavenumber){ waveNumber_=wavenumber; }
+        void setCredit(int credit){ credit_ = credit; }
+        void setLifes(int lifes){ lifes_ = lifes; }        
+        void buyTower(int cost){ cost -= cost;}
+        void addCredit(int credit) { credit_+=credit; }
+        int reduceLifes(int NumberofLifes){ return lifes_-=NumberofLifes; }
+        TowerDefenseField* getField(TDCoordinate* coord){ return fields_[coord->GetX()][coord->GetY()]; }
+        void setCenterpoint(TowerDefenseCenterpoint* centerpoint);        
+        void addTower(int x, int y);
+        void upgradeTower(int x, int y); 
+        virtual TDCoordinate* getNextStreetCoord(TDCoordinate*);
+        
+        TowerDefenseSelecter* selecter;        
+
+    private:
+        void createFields();
+
+        orxonox::WeakPtr<TowerDefenseCenterpoint> center_;
+        PlayerInfo* player_;
+        float timeSinceLastSpawn_;
+        float timeUntilNextWave_;
+        int waveSize_;
+        int credit_;
+        int waveNumber_;
+        int lifes_;
+        std::list<orxonox::WeakPtr<TowerDefenseEnemy>> enemies_;
+        TowerDefenseField* fields_[16][16];
+        std::vector<orxonox::WeakPtr<TowerDefenseField>> waypoints_;
+        Vector3 endpoint_;
+        Vector3 offset_;        
+    };
+}
+
+#endif /* _TowerDefense_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseCenterpoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseCenterpoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseCenterpoint.cc	(revision 11817)
@@ -0,0 +1,127 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TowerDefenseCenterpoint.cc
+    @brief Implementation of the TowerDefenseCenterpoint class.
+*/
+
+#include "TowerDefenseCenterpoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/class/Super.h"
+
+#include "TowerDefense.h"
+
+namespace orxonox
+{
+    RegisterClass(TowerDefenseCenterpoint);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object and checks whether the gametype is actually TowerDefense.
+    */
+    TowerDefenseCenterpoint::TowerDefenseCenterpoint(Context* context) : MobileEntity(context)
+    {
+        RegisterObject(TowerDefenseCenterpoint);
+
+        this->width_ = 15;
+        this->height_ = 15;
+
+        //this->setCollisionType(Static);
+
+        this->checkGametype();
+
+    }
+
+    /**
+    @brief
+        Method to create a TowerDefenseCenterpoint through XML.
+    */
+    void TowerDefenseCenterpoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TowerDefenseCenterpoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(TowerDefenseCenterpoint, "width", setWidth, getWidth, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "height", setHeight, getHeight, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tileScale", setTileScale, getTileScale, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "selecterTemplate", setSelecterTemplate, getSelecterTemplate, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower1Template", setTower1Template, getTower1Template, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower2Template", setTower2Template, getTower2Template, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower3Template", setTower3Template, getTower3Template, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower4Template", setTower4Template, getTower4Template, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower5Template", setTower5Template, getTower5Template, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "fields", setFields, getFields, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower1Cost", setTower1Cost, getTower1Cost, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower2Cost", setTower2Cost, getTower2Cost, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower3Cost", setTower3Cost, getTower3Cost, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower4Cost", setTower4Cost, getTower4Cost, xmlelement, mode);
+        XMLPortParam(TowerDefenseCenterpoint, "tower5Cost", setTower5Cost, getTower5Cost, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Checks whether the gametype is TowerDefense and if it is, sets its centerpoint.
+    */
+    void TowerDefenseCenterpoint::checkGametype()
+    {
+        if (this->getGametype() != nullptr && this->getGametype()->isA(Class(TowerDefense)))
+        {
+            // Sets the centerpoint of the gametype. The gametype uses this to later spawn in towers, he needs the tower template stored in the center point
+            TowerDefense* towerDefenseGametype = orxonox_cast<TowerDefense*>(this->getGametype());
+            towerDefenseGametype->setCenterpoint(this);
+        }
+    }
+
+    /**
+    @brief
+        Removes all blanks, tabs and returns from the string passed.
+    */
+    void TowerDefenseCenterpoint::trimString(std::string* str)
+    {
+        std::string* trimmed = new std::string("");
+        int length = str->size();
+        char temp;
+        for (int i = 0; i < length; ++ i)
+        {
+            temp = str->at(i);
+            if (temp != ' ' && temp != '\t' && temp != '\n')
+            {
+                trimmed->push_back(temp);
+            }
+        }
+
+        *str = *trimmed;
+    }
+
+    const int TowerDefenseCenterpoint::getTowerCost(int upgrade) const
+    {
+        return towerCosts_[(upgrade%5)];
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseCenterpoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseCenterpoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseCenterpoint.h	(revision 11817)
@@ -0,0 +1,142 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _TowerDefenseCenterpoint_H__
+#define _TowerDefenseCenterpoint_H__
+
+#include "towerdefense/TowerDefensePrereqs.h"
+
+#include <string>
+#include <util/Math.h>
+#include "TowerDefenseTower.h"
+#include "worldentities/MobileEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+    See TowerDefenseReadme.txt for Information.
+    @ingroup TowerDefense
+    */
+    class _TowerDefenseExport TowerDefenseCenterpoint : public MobileEntity
+    {
+        public:
+            TowerDefenseCenterpoint(Context* context);
+            virtual ~TowerDefenseCenterpoint() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            /**
+            @brief The width and hight in number of tiles. Default is 15 for both.
+            */
+            void setWidth(unsigned int width)
+                { this->width_ = width; }
+            unsigned int getWidth(void) const
+                { return this->width_; }
+            void setHeight(unsigned int height)
+                { this->height_ = height; }
+            unsigned int getHeight(void) const
+                { return this->height_; }
+            void setFields(const std::string& newFields)
+                { this->fields_ = newFields; trimString(&fields_); }
+            const std::string& getFields() const
+                { return this->fields_; }                    
+            void setSelecterTemplate(const std::string& newTemplate)
+                { this->selecterTemplate_ = newTemplate; }
+            const std::string& getSelecterTemplate() const
+                { return this->selecterTemplate_; }   
+
+            void setTower1Template(const std::string& newTemplate)
+                { this->towerTemplates_[0] = newTemplate;}
+            const std::string& getTower1Template() const
+                { return this->towerTemplates_[0]; }  
+            void setTower2Template(const std::string& newTemplate)
+                { this->towerTemplates_[1] = newTemplate; }
+            const std::string& getTower2Template() const
+                { return this->towerTemplates_[1]; }
+            void setTower3Template(const std::string& newTemplate)
+                { this->towerTemplates_[2] = newTemplate; }
+            const std::string& getTower3Template() const
+                { return this->towerTemplates_[2]; } 
+            void setTower4Template(const std::string& newTemplate)
+                { this->towerTemplates_[3] = newTemplate; }
+            const std::string& getTower4Template() const
+                { return this->towerTemplates_[3]; }
+            void setTower5Template(const std::string& newTemplate)
+                { this->towerTemplates_[4] = newTemplate; }
+            const std::string& getTower5Template() const
+                { return this->towerTemplates_[4]; }  
+
+            void setTower1Cost(const int& newCost)
+                { this->towerCosts_[0] = newCost;}
+            const int& getTower1Cost() const
+                { return this->towerCosts_[0]; }  
+            void setTower2Cost(const int& newCost)
+                { this->towerCosts_[1] = newCost; }
+            const int& getTower2Cost() const
+                { return this->towerCosts_[1]; }
+            void setTower3Cost(const int& newCost)
+                { this->towerCosts_[2] = newCost; }
+            const int& getTower3Cost() const
+                { return this->towerCosts_[2]; } 
+            void setTower4Cost(const int& newCost)
+                { this->towerCosts_[3] = newCost; }
+            const int& getTower4Cost() const
+                { return this->towerCosts_[3]; }
+            void setTower5Cost(const int& newCost)
+                { this->towerCosts_[4] = newCost; }
+            const int& getTower5Cost() const
+                { return this->towerCosts_[4]; }
+
+            const int getTowerCost(int upgrade) const;
+                                            
+
+            /**
+                @brief How to convert to world coordinates, e.g. that 0,15 is not at -8,-8 but at -80,-80 (if scale would be 10)
+            */
+            void setTileScale(unsigned int tileScale)
+                { this->tileScale_ = tileScale; }
+
+            unsigned int getTileScale(void) const
+                { return this->tileScale_; }
+
+        private:
+            void checkGametype();
+            void trimString(std::string*);
+            std::string selecterTemplate_;
+            std::string towerTemplates_[5];
+            int towerCosts_[5];
+            std::string fields_;
+            unsigned int width_;
+            unsigned int height_;
+            unsigned int tileScale_;
+    };
+}
+
+#endif /* _TowerDefenseCenterpoint_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseEnemy.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseEnemy.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseEnemy.cc	(revision 11817)
@@ -0,0 +1,54 @@
+//
+//  TowerDefenseEnemy.cc
+//  Orxonox
+//
+//  Created by Jonas Erb on 22.10.14.
+
+#include "TowerDefenseEnemy.h"
+#include "core/CoreIncludes.h"
+//#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(TowerDefenseEnemy);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    TowerDefenseEnemy::TowerDefenseEnemy(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(TowerDefenseEnemy);
+
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+        //needed to keep track of the PlayerStats coded in TowerDefense.h
+        this->td = orxonox_cast<TowerDefense*>(this->getGametype());
+        once_ = false;
+    }
+
+    TowerDefenseEnemy::~TowerDefenseEnemy()
+    {
+
+    }
+
+    WeakPtr<TowerDefense> TowerDefenseEnemy::getGame()
+    {
+        if (game == nullptr)
+        {
+            for (TowerDefense* towerDefense : ObjectList<TowerDefense>())
+                game = towerDefense;
+        }
+        return game;
+    }
+
+    void TowerDefenseEnemy::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        Pawn::damage(damage, healthdamage, shielddamage, originator);
+        
+        if (getGame() && once_ == false && getHealth() <= 0)
+        {
+            getGame()->addCredit(1);
+            once_ = true;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseEnemy.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseEnemy.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseEnemy.h	(revision 11817)
@@ -0,0 +1,50 @@
+//
+//  TowerDefenseEnemy.h
+//  Orxonox
+//
+//  Created by Jonas Erb on 22.10.14.
+
+
+
+
+
+#ifndef Orxonox_Tower_h
+#define Orxonox_Tower_h
+
+#include "TDCoordinate.h"
+#include "gametypes/Deathmatch.h"
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "util/Output.h"
+#include "TowerDefense.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+    See TowerDefenseReadme.txt for Information.
+
+    @ingroup TowerDefense
+    */
+    class _TowerDefenseExport TowerDefenseEnemy : public SpaceShip
+    {
+    public:
+        TowerDefenseEnemy(Context* context);
+        virtual ~TowerDefenseEnemy();
+
+        //health gibt es unter: health_
+
+        virtual void damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs) override;
+
+    private:
+        WeakPtr<TowerDefense> getGame();
+        WeakPtr<TowerDefense> game;
+        TowerDefense* td;
+        bool once_;
+    };
+
+
+
+}
+
+#endif /* _TowerDefense_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseField.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseField.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseField.cc	(revision 11817)
@@ -0,0 +1,327 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TowerDefenseField.cc
+    @brief Implementation of the TowerDefenseField class.
+*/
+
+#include "TowerDefenseField.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "TowerDefense.h"
+
+namespace orxonox
+{
+    RegisterClass(TowerDefenseField);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object and checks whether the gametype is actually TowerDefense.
+    */
+    TowerDefenseField::TowerDefenseField(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(TowerDefenseField);
+
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::FREE;
+        center_ = nullptr;
+        upgrade_ = 0;
+        setPosition(0,0,0);                            
+        modelGround_ = new Model(getContext());
+        modelGround_->setScale(25);
+        modelGround_->pitch(Degree(90));
+        attach(modelGround_);
+        modelObject_ = new Model(getContext());
+        modelObject_->setScale(25);
+        modelObject_->pitch(Degree(90));
+        attach(modelObject_);
+        setAngle(0);
+    }
+
+    /**
+    @brief
+        Method to create a TowerDefenseField through XML.
+    */
+    void TowerDefenseField::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TowerDefenseField, XMLPort, xmlelement, mode);
+
+        //XMLPortParam(TowerDefenseField, "width", setWidth, getWidth, xmlelement, mode);
+
+    }
+
+    void TowerDefenseField::setCenterpoint(TowerDefenseCenterpoint* center)
+    {
+        center_ = center;
+    }
+
+    void TowerDefenseField::upgrade()
+    {
+        if (canUpgrade() == true)
+        {
+            destroyTower();
+            createTower(getUpgrade() + 1);
+        }
+    }
+
+    int TowerDefenseField::getUpgrade()
+    {
+        return upgrade_;
+    }
+
+    TowerDefenseFieldType TowerDefenseField::getType()
+    {
+        return type_;
+    }
+
+    void TowerDefenseField::setUpgrade(int upgrade)
+    {
+        if (upgrade < 0)
+        {
+            upgrade_ = 0;
+        }   
+        else if (upgrade > 5)
+        {
+            upgrade = 5;
+        }
+        else
+        {
+            upgrade_ = upgrade;
+        }                            
+    }
+
+    bool TowerDefenseField::canUpgrade()
+    {
+        if (tower_ != nullptr && upgrade_ < 5)
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    void TowerDefenseField::setAngle(int newAngle)
+    {
+        if (modelGround_ != nullptr)
+        {
+            switch (newAngle)
+            {
+            case 0:
+                modelGround_->yaw(Degree(0));
+                angle_ = 0;
+                break;
+            case 1:
+                modelGround_->yaw(Degree(90));
+                angle_ = 1;
+                break;    
+            case 2:
+                modelGround_->yaw(Degree(180));
+                angle_ = 2;
+                break;   
+            case 3:
+                modelGround_->yaw(Degree(270));
+                angle_ = 3;
+                break;                                           
+            }
+        }
+
+        if (modelObject_ != nullptr)
+        {
+            switch (newAngle)
+            {
+            case 0:
+                modelObject_->yaw(Degree(0));
+                angle_ = 0;
+                break;
+            case 1:
+                modelObject_->yaw(Degree(90));
+                angle_ = 1;
+                break;    
+            case 2:
+                modelObject_->yaw(Degree(180));
+                angle_ = 2;
+                break;   
+            case 3:
+                modelObject_->yaw(Degree(270));
+                angle_ = 3;
+                break;                                           
+            }
+        }
+        
+    }
+
+    int TowerDefenseField::getAngle()
+    {
+        return angle_;
+    }
+
+    void TowerDefenseField::createFree(int orientation)
+    {            
+        modelGround_->setMeshSource("TD_F1.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::FREE;
+        setUpgrade(0);
+        setAngle(orientation);
+    }
+
+    void TowerDefenseField::createStart(int orientation)
+    {      
+        modelGround_->setMeshSource("TD_S5.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::START;
+        setUpgrade(0);
+        setAngle(orientation);    
+    }
+
+
+    void TowerDefenseField::createEnd(int orientation)
+    {     
+        modelGround_->setMeshSource("TD_S4.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::END;
+        setUpgrade(0);
+        setAngle(orientation);
+    }   
+
+    void TowerDefenseField::createStraight(int orientation)
+    {      
+        modelGround_->setMeshSource("TD_S1.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::STREET;
+        setUpgrade(0);
+        setAngle(orientation);
+    }  
+
+    void TowerDefenseField::createRCurve(int orientation)
+    {     
+        modelGround_->setMeshSource("TD_S2.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::STREET;
+        setUpgrade(0);
+        setAngle(orientation);
+    }  
+
+    void TowerDefenseField::createLCurve(int orientation)
+    {    
+        modelGround_->setMeshSource("TD_S3.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::STREET;
+        setUpgrade(0);
+        setAngle(orientation);
+    } 
+
+    void TowerDefenseField::createObstacle(int orientation)
+    {    
+        modelGround_->setMeshSource("TD_F1.mesh");
+        modelObject_->setMeshSource("TD_O1.mesh");
+        tower_ = nullptr;
+        type_ = TowerDefenseFieldType::OBSTACLE;
+        setUpgrade(0);
+        setAngle(orientation);
+    }
+
+    void TowerDefenseField::createTower(int upgrade)
+    {        
+        if (tower_ == nullptr)
+        {
+            modelGround_->setMeshSource("TD_F1.mesh");
+            tower_ = new TowerDefenseTower(center_->getContext());
+            attach(tower_);
+            type_ = TowerDefenseFieldType::TOWER;
+            setUpgrade(upgrade);
+            if (upgrade_ > 0 && modelObject_ != nullptr)
+            {
+                switch (upgrade_)
+                {
+                    case 1:
+                        modelObject_->setMeshSource("TD_T1.mesh");                    
+                        tower_->addTemplate(center_->getTower1Template());
+                        break;
+                    case 2:
+                        modelObject_->setMeshSource("TD_T2.mesh");
+                        tower_->addTemplate(center_->getTower2Template());
+                        break;
+                    case 3:
+                        modelObject_->setMeshSource("TD_T3.mesh");
+                        tower_->addTemplate(center_->getTower3Template());
+                        break;
+                    case 4:
+                        modelObject_->setMeshSource("TD_T4.mesh");
+                        tower_->addTemplate(center_->getTower4Template());
+                        break;
+                    case 5:
+                        modelObject_->setMeshSource("TD_T5.mesh");
+                        tower_->addTemplate(center_->getTower5Template());
+                        break;
+                }
+            }
+        }                           
+    }
+
+    void TowerDefenseField::destroyTower()
+    {
+        if (tower_ != nullptr)
+        {
+            tower_->destroy();
+            tower_ = nullptr;
+        }
+    }
+
+    void TowerDefenseField::create(char object, char param)
+    {
+        int paramInt = atoi(&param);
+        switch (object)
+        {
+            case 'F':
+                createFree(paramInt);
+                break;
+            case 'I':                
+                createStraight(paramInt);
+                break;
+            case 'R':                
+                createRCurve(paramInt);
+                break;  
+            case 'L':               
+                createLCurve(paramInt);
+                break;
+            case 'X':               
+                createStart(paramInt);
+                break;     
+            case 'O':               
+                createEnd(paramInt);
+                break;
+            case 'Y':               
+                createObstacle(paramInt);
+                break;                 
+            case 'T':                               
+                createTower(paramInt);               
+                break;                                                                                                         
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseField.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseField.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseField.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+
+#ifndef _TowerDefenseField_H__
+#define _TowerDefenseField_H__
+
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "TowerDefenseTower.h"
+ #include "TowerDefenseCenterpoint.h"
+#include <string>
+#include "graphics/Model.h"
+#include "worldentities/MovableEntity.h"
+
+namespace orxonox
+{
+    enum class TowerDefenseFieldType
+    { 
+        FREE,
+        STREET, 
+        START, 
+        END,
+        OBSTACLE,
+        TOWER
+    };
+
+    /**
+    @brief
+    See TowerDefenseReadme.txt for Information.
+    @ingroup TowerDefense
+    */
+    class _TowerDefenseExport TowerDefenseField : public MovableEntity
+    {
+        public:
+            TowerDefenseField(Context* context);
+            virtual ~TowerDefenseField() {}
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            const bool isFree() const
+                { return type_==TowerDefenseFieldType::FREE; }
+            virtual void create(char object, char param);
+            virtual void setCenterpoint(TowerDefenseCenterpoint* center);
+            virtual void upgrade();
+            virtual int getUpgrade();
+            virtual TowerDefenseFieldType getType();
+            virtual void setUpgrade(int upgrade);
+            virtual bool canUpgrade();
+            virtual void createFree(int orientation);
+            virtual void createStart(int orientation);
+            virtual void createEnd(int orientation);
+            virtual void createStraight(int orientation);
+            virtual void createLCurve(int orientation);
+            virtual void createRCurve(int orientation);
+            virtual void createObstacle(int orientation);
+            virtual void createTower(int upgrade);
+            virtual int getAngle();            
+        private:
+            virtual void setAngle(int newAngle);            
+            virtual void destroyTower();
+            int angle_;
+            TowerDefenseFieldType type_;
+            Model* modelGround_;
+            Model* modelObject_;
+            TowerDefenseTower* tower_;
+            TowerDefenseCenterpoint* center_;
+            int upgrade_;
+
+    };    
+}
+
+#endif /* _TowerDefenseField_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseHUDController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseHUDController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseHUDController.cc	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *
+ *   Co-authors:
+ *      ...
+ */
+
+#include "TowerDefenseHUDController.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    RegisterClass(TowerDefenseHUDController);
+
+    TowerDefenseHUDController::TowerDefenseHUDController(Context* context) : OverlayText(context)
+    {
+        RegisterObject(TowerDefenseHUDController);
+        this->td = nullptr;
+    }
+
+    TowerDefenseHUDController::~TowerDefenseHUDController()
+    {
+
+    }
+
+    void TowerDefenseHUDController::tick(float dt)
+    {
+        SUPER(TowerDefenseHUDController, tick, dt);
+
+        const std::string& lifes = multi_cast<std::string>(this->td->getLifes());
+        const std::string& credits = multi_cast<std::string>(this->td->getCredit());
+        const std::string& wave = multi_cast<std::string>(this->td->getWaveNumber());
+
+        if(showlives == true)
+        {
+            this->setCaption(multi_cast<std::string>(lifes));
+        }          
+        else if(showcredits == true)
+        {
+            this->setCaption(multi_cast<std::string>(credits));
+        }          
+        else if(showwaves == true)
+        {
+            this->setCaption(multi_cast<std::string>(wave));
+        }          
+    }
+
+    void TowerDefenseHUDController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TowerDefenseHUDController, XMLPort, xmlelement, mode);
+
+        XMLPortParam(TowerDefenseHUDController, "showlives", setShowlives, getShowlives, xmlelement, mode);
+        XMLPortParam(TowerDefenseHUDController, "showcredits", setShowcredits, getShowcredits, xmlelement, mode);
+        XMLPortParam(TowerDefenseHUDController, "showwaves", setShowwaves, getShowwaves, xmlelement, mode);
+
+    }
+
+    void TowerDefenseHUDController::changedOwner()
+        {
+            SUPER(TowerDefenseHUDController, changedOwner);
+
+            if (this->getOwner() && this->getOwner()->getGametype())
+                    {
+                        this->td = orxonox_cast<TowerDefense*>(this->getOwner()->getGametype());
+                    }
+                    else
+                    {
+                        this->td = nullptr;
+                    }
+                }
+        }
+
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseHUDController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseHUDController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseHUDController.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _TowerDefenseHUDController_H__
+#define _TowerDefenseHUDController_H__
+
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "TowerDefensePlayerStats.h"
+#include "tools/interfaces/Tickable.h"
+#include "overlays/OverlayText.h"
+#include "TowerDefense.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+    This subclass of OverlayText is used to display the stats of the player in the HUD
+
+    @ingroup TowerDefense
+    */
+    class _TowerDefenseExport TowerDefenseHUDController : public OverlayText, public Tickable
+    {
+    public:
+        TowerDefenseHUDController(Context* context);
+        virtual ~TowerDefenseHUDController();
+
+
+        virtual void tick(float dt) override;
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void changedOwner() override;
+        void setShowlives(bool temp)
+            { this->showlives = temp; }
+        unsigned int getShowlives(void) const
+            { return this->showlives; }
+
+        void setShowcredits(bool temp)
+            { this->showcredits = temp; }
+        unsigned int getShowcredits(void) const
+            { return this->showcredits; }
+
+        void setShowwaves(bool temp)
+            { this->showwaves = temp; }
+        unsigned int getShowwaves(void) const
+            { return this->showwaves; }
+
+    private:
+        TowerDefense* td;
+        bool showcredits;
+        bool showlives;
+        bool showwaves;
+    };
+}
+
+#endif /* _TowerDefenseHUDController_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePlayerStats.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePlayerStats.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePlayerStats.cc	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *
+ *   Co-authors:
+ *      ...
+ */
+/*
+#include "TowerDefensePlayerStats.h"
+
+namespace orxonox
+{
+    const int kDefaultCredit = 200;
+    const int kDefaultLifes=20;
+    TowerDefensePlayerStats::TowerDefensePlayerStats()
+    {
+        this->credit_ = kDefaultCredit;
+        this->waveNumber_ = 0;
+        this->lifes_=kDefaultLifes;
+    }
+
+    TowerDefensePlayerStats::~TowerDefensePlayerStats()
+    {
+    }
+
+}
+*/
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePlayerStats.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePlayerStats.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePlayerStats.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+ /*
+    @brief
+        This manages the stats of the player. It is used by 'TowerDefense', the gametype
+
+    @ingroup TowerDefense
+
+
+
+#ifndef _TowerDefensePlayerStats_H__
+#define _TowerDefensePlayerStats_H__
+
+#include "towerdefense/TowerDefensePrereqs.h"
+
+namespace orxonox
+{
+    typedef enum _TowerCosts {
+        // Set to 0 for debug...
+        TDDefaultTowerCost = 20 ,
+        TDDefaultUpgradeCost = 15
+    } TowerCost;
+
+    class _TowerDefenseExport TowerDefensePlayerStats
+    {
+    public:
+        TowerDefensePlayerStats();
+
+        inline int getCredit()
+            { return credit_; }
+
+        inline void setCredit(int credit)
+            { credit_ = credit; }
+
+        inline void buyTower(TowerCost cost)
+            { credit_ -= cost;}
+
+        inline int getWaveNumber()
+            { return waveNumber_; }
+
+        inline void didLoadNextWave()
+            { waveNumber_++; }
+
+        inline int getLifes()
+            {return lifes_; }
+
+        inline void reduceLifes(int NumberofLifes)
+        {lifes_-=NumberofLifes; }
+
+        inline void upgradeTower(int upgradecost)
+            { credit_ -= upgradecost;}
+
+
+
+    private:
+        int credit_;
+        int waveNumber_;
+        int upgradecost;
+        int lifes_;
+        //int baseHealth_;
+    };
+}
+
+#endif  _TowerDefensePlayerStats_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefensePrereqs.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the TowerDefense module
+*/
+
+#ifndef _TowerDefensePrereqs_H__
+#define _TowerDefensePrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(TOWERDEFENSE_STATIC_BUILD)
+#  ifdef TOWERDEFENSE_SHARED_BUILD
+#    define _TowerDefenseExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _TowerDefenseExport
+#    else
+#      define _TowerDefenseExport __declspec(dllimport)
+#    endif
+#  endif
+#elif defined ( ORXONOX_GCC_VISIBILITY )
+#  define _TowerDefenseExport  __attribute__ ((visibility("default")))
+#else
+#  define _TowerDefenseExport
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class TowerDefense;
+
+    class TowerDefenseTower;
+
+    class TowerDefenseCenterpoint;
+    class TowerDefenseHUDController;
+    class TowerDefensePlayerStats;
+    class TowerDefenseEnemy;
+    class TDCoordinate;
+    class TowerTurret;
+    class TowerDefenseTower;
+}
+
+#endif /* _TowerDefensePrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseSelecter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseSelecter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseSelecter.cc	(revision 11817)
@@ -0,0 +1,180 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file TowerDefenseSelecter.cc
+    @brief This class represents your figure when you play the minigame. Here the movement of the figure, activating items, ... are handled.
+*/
+
+#include "TowerDefenseSelecter.h"
+
+#include "core/CoreIncludes.h"
+#include "graphics/Model.h"
+
+namespace orxonox
+{
+    RegisterClass(TowerDefenseSelecter);
+
+    TowerDefenseSelecter::TowerDefenseSelecter(Context* context) : ControllableEntity(context)
+    {
+        RegisterObject(TowerDefenseSelecter);
+
+        // initialize variables
+        moveUpPressed_ = false;
+        moveDownPressed_ = false;
+        moveLeftPressed_ = false;
+        moveRightPressed_ = false;
+        boostPressed_ = false;
+        buildTower_ = false;
+        setSelectedPosition(0,0);     
+    }
+
+    TowerDefenseSelecter::~TowerDefenseSelecter()
+    {
+
+    }
+
+    void TowerDefenseSelecter::tick(float dt)
+    {
+        SUPER(TowerDefenseSelecter, tick, dt);
+
+        time_ += dt;
+
+        if (hasLocalController() && time_ >= 0.25)
+        {    
+            time_ = 0;
+
+            int selecterPosX = selectedPos_->GetX();
+            int selecterPosY = selectedPos_->GetY();
+
+            if (moveUpPressed_ == true)
+            {                
+                moveUpPressed_ = false;
+                selectedPos_->Set(selecterPosX, selecterPosY + 1);
+                updatePosition();
+            }
+            if (moveDownPressed_ == true)
+            {
+                moveDownPressed_ = false;
+                selectedPos_->Set(selecterPosX, selecterPosY - 1);
+                updatePosition();
+            }
+            if (moveLeftPressed_ == true)
+            {
+                moveLeftPressed_ = false;
+                selectedPos_->Set(selecterPosX - 1, selecterPosY);
+                updatePosition();
+            }
+            if (moveRightPressed_ == true)
+            {
+                moveRightPressed_ = false;
+                selectedPos_->Set(selecterPosX + 1, selecterPosY);
+                updatePosition();
+            }
+            if (boostPressed_ == true)
+            {
+                boostPressed_ = false;
+                buildTower_ = true;
+            }
+        }         
+    }
+
+
+    void TowerDefenseSelecter::moveFrontBack(const Vector2& value)
+    {
+        if (value.x > 0)
+        {
+            moveUpPressed_ = true;
+            moveDownPressed_ = false;
+        }
+        else
+        {
+            moveUpPressed_ = false;
+            moveDownPressed_ = true;
+        }
+    }
+
+    void TowerDefenseSelecter::moveRightLeft(const Vector2& value)
+    {
+        if (value.x > 0)
+        {
+            moveLeftPressed_ = false;
+            moveRightPressed_ = true;
+        }
+        else
+        {
+            moveLeftPressed_ = true;
+            moveRightPressed_ = false;
+        }
+    }
+
+    void TowerDefenseSelecter::rotateYaw(const Vector2& value)
+    {
+    }
+
+    void TowerDefenseSelecter::rotatePitch(const Vector2& value)
+    {
+    }
+
+    void TowerDefenseSelecter::rotateRoll(const Vector2& value)
+    {
+    }
+
+    void TowerDefenseSelecter::fire(unsigned int firemode)
+    {
+    }
+
+    void TowerDefenseSelecter::fired(unsigned int firemode)
+    {
+        
+    }
+
+    void TowerDefenseSelecter::boost(bool bBoost)
+    {
+        if (bBoost == true)
+        {
+            boostPressed_ = true;
+        }
+    }
+
+    void TowerDefenseSelecter::updatePosition()
+    {
+        setPosition(selectedPos_->get3dcoordinate());
+    }
+
+    void TowerDefenseSelecter::setSelectedPosition(TDCoordinate* newPos)
+    {
+        selectedPos_ = newPos;
+        updatePosition();
+    }
+
+    void TowerDefenseSelecter::setSelectedPosition(int x,  int y)
+    {
+        setSelectedPosition(new TDCoordinate(x,y));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseSelecter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseSelecter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseSelecter.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TowerDefenseSelecter_H__
+#define _TowerDefenseSelecter_H__
+
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "worldentities/ControllableEntity.h"
+#include "TDCoordinate.h"
+
+namespace orxonox
+{
+class _TowerDefenseExport TowerDefenseSelecter : public ControllableEntity
+    {
+        public:
+            TowerDefenseSelecter(Context* context); //!< Constructor. Registers and initializes the object.
+            virtual ~TowerDefenseSelecter();
+            virtual void tick(float dt) override;            
+            virtual void moveFrontBack(const Vector2& value) override; //!< Overloaded the function to steer the bat up and down.
+            virtual void moveRightLeft(const Vector2& value) override; //!< Overloaded the function to steer the bat up and down.
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+            void fire(unsigned int firemode);
+            virtual void fired(unsigned int firemode) override;
+            virtual void boost(bool bBoost) override;
+            virtual void setSelectedPosition(TDCoordinate* newPos);
+            virtual void setSelectedPosition(int x, int y);
+
+            bool buildTower_;
+            TDCoordinate* selectedPos_;
+        private:            
+            virtual void updatePosition();                        
+            float time_;
+            bool moveUpPressed_;
+            bool moveDownPressed_;
+            bool moveLeftPressed_;
+            bool moveRightPressed_;                        
+            bool boostPressed_;            
+    };
+}
+
+#endif /* _TowerDefenseSelecter_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseTower.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseTower.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseTower.cc	(revision 11817)
@@ -0,0 +1,126 @@
+//
+//  TowerDefenseTower.cc
+//  Orxonox
+//
+//  Created by Fabian Mentzer on 29.04.12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+/* Not implemented fully */
+
+#include "TowerDefenseTower.h"
+
+#include "core/CoreIncludes.h"
+//#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(TowerDefenseTower);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    TowerDefenseTower::TowerDefenseTower(Context* context) : Turret(context)
+    {
+        RegisterObject(TowerDefenseTower);
+        game_ =nullptr;
+        this->setCollisionType(WorldEntity::CollisionType::None);
+        upgrade = 1;
+
+        //this->removeAllEngines();
+
+        /*
+        this->size_ = 10.0f;
+        this->delay_ = false;
+        this->delayTimer_.setTimer(0.2f, false, createExecutor(createFunctor(&TetrisStone::enableMovement, this)));
+        */
+    }
+
+    /*
+    void TowerDefenseTower::setOrientation(const Quaternion& orientation)
+    {
+    }
+
+    void TowerDefenseTower::rotateYaw(const Vector2& value)
+    {
+    }
+
+    void TowerDefenseTower::rotatePitch(const Vector2& value)
+    {
+    }
+
+    void TowerDefenseTower::rotateRoll(const Vector2& value)
+    {
+    }
+    */
+
+    bool TowerDefenseTower::upgradeTower()
+    {
+        if(upgrade < 5)
+        {
+            upgrade++;
+            this->setDamageMultiplier((upgrade+1)*2.0f);
+
+            //this->setRotationThrust(2*this->getRotationThrust());
+            //this->addTemplate("towerturret1");
+        }
+        else
+        {
+            orxout() << "Tower fully upgraded" << endl;
+            return false;
+        }
+        return true;
+    }
+
+    // This function is called whenever a player presses the up or the down key.
+    // You have to implement what happens when the up or the down key is pressed.
+    // value.x < 0 means: down key is pressed.
+    // I suggest to create a new class which is a controllable entity I will refer to as "TowerDefenseTowerMover". This is the controllable entity that the
+    // player controls in order to move the TowerDefenseTower along the centerpoint and in order to place the TowerDefenseTower at the appropriate position.
+    //
+
+    // The TowerDefenseTower itsself is controlled by a WayPointPatroController at the instance you place it on the centerpoint.
+    //(don't forget to set the team_ parameter such that all TowerDefenseTower are in the same team)
+
+    //How to move a TowerDefenseTower: simply attach the TowerDefenseTower to the TowerDefenseTowerMover
+    //How to place a TowerDefenseTower: detach the TowerDefenseTower from the TowerDefenseTowerMover
+
+    /**
+    @brief
+        Overloaded the function to rotate the stone.
+    @param value
+        A vector whose first component is the angle by which to rotate.
+    */
+    /*
+    void TowerDefenseTower::moveFrontBack(const Vector2& value)
+    {
+        //orxout() << "frontBack.x: " << value.x << endl;
+    }
+    */
+
+    /**
+    @brief
+        Overloaded the function to steer the stone right and left
+    @param value
+        A vector whose first component is the direction in which we want to steer the stone.
+    */
+    /*
+    void TowerDefenseTower::moveRightLeft(const Vector2& value)
+    {
+        //orxout() << "rightLeft.x: " << value.x << endl;
+
+        if(!this->delay_)
+        {
+            const Vector3& position = this->getPosition();
+            Vector3 newPos = Vector3(position.x+value.x/abs(value.x)*this->size_, position.y, position.z);
+            if(!this->tetris_->isValidMove(this, newPos))
+                return;
+
+            this->setPosition(newPos);
+            this->delay_ = true;
+            this->delayTimer_.startTimer();
+        }
+    }
+    */
+}
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseTower.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseTower.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/TowerDefenseTower.h	(revision 11817)
@@ -0,0 +1,54 @@
+//
+//  TowerDefenseTower.h
+//  Orxonox
+//
+//  Created by Fabian Mentzer on 29.04.12.
+//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
+//
+
+
+#ifndef Orxonox_TowerDefenseTower_h
+#define Orxonox_TowerDefenseTower_h
+
+#include "towerdefense/TowerDefensePrereqs.h"
+#include "objects/Turret.h"
+
+
+namespace orxonox
+{
+    /**
+    @brief
+    See TowerDefenseTowerDefenseReadme.txt for Information.
+
+    @ingroup TowerDefenseTowerDefense
+    */
+    class _TowerDefenseExport TowerDefenseTower : public Turret
+    {
+    public:
+        TowerDefenseTower(Context* context);
+        virtual ~TowerDefenseTower() {};
+
+        // Maybe later override these to move TowerDefenseTowers with cursor keys
+        /*
+        virtual void moveFrontBack(const Vector2& value);
+        virtual void moveRightLeft(const Vector2& value);
+        */
+
+        // Overriding these to stop TowerDefenseTowers from spasing out
+        //void setOrientation(const Quaternion& orientation);
+        //virtual void rotateYaw(const Vector2& value);
+        //virtual void rotatePitch(const Vector2& value);
+        //virtual void rotateRoll(const Vector2& value);
+        virtual bool upgradeTower();
+
+
+        void setGame(TowerDefense* Towerdefense)
+        { assert(Towerdefense); game_ = Towerdefense; }
+    private:
+        TowerDefense* game_;
+        int upgrade;
+    };
+}
+
+
+#endif
Index: /code/branches/RacingBots_FS18/src/modules/towerdefense/towerdefensereadme.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/towerdefense/towerdefensereadme.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/towerdefense/towerdefensereadme.txt	(revision 11817)
@@ -0,0 +1,38 @@
+===============================================================================
+Classes
+===============================================================================
+
+TowerDefense:
+GameType class
+
+TowerDefenseCenterpoint
+Centerpoint class. Store tower template
+
+Tower
+Represents a Tower
+I'm not actually sure if you have to code C++ in order to have your result. I would suggest to simply create a new spaceship template or maybe better a
+new template for a pawn. (The tower don't need to be spaceships; pawn is just fine.)
+Example for a template: /data/levels/templates/assff.oxt && /data/levels/include/weaponSettingsAssff.oxi
+@ assff.oxt: you don't need an engine (or your towers could fly away :-) and probably no Cameras. (just try what happens if you leave them out.) 
+@ weaponSettingsAssff.oxi:
+<weaponslots>: location where you want to have your tower to be equiped with weapons
+<weaponsets> : if you press fire, you actually always fire a whole set of weapons. The amount of weaponsets is defined here. (I'm not 100% sure whether this explanation is right.)
+
+There are three <Weapon> tags - one for each weaponslot. Each weapon can contain several objects which you would probably
+refer to as "weapons":
+
+LightningGun: Shoots a slow, rotation, yellow "ball".
+HsW01: the default laser weapon
+SimpleRocketFire: a weak (self steering) rocket
+RocketFire: a strong rocket
+                         
+About your Tower's Template location - either keep it in the level or do it similarly to the Assff templates.
+(If your towers behave & look nicely, I'm quite sure others want to include them in other levels, too.)
+
+
+===============================================================================
+Other files
+===============================================================================
+
+/data/levels/towerdefense.oxw
+Loads the level. In <Level>, we first create a SpawnPoint. It spawns a cylinder using the 'centerpointmark' Template, which uses the 'centerpointmarkcamera' Template to create a static camera. Then, we create an instance of TowerDefenseCenterpoint and pass the 'towertemplate' Template, so that we can later create towers using this template. We also plase the playfield.mesh in a way that maps every field on the playfield.mesh to nice coordinates: the playfield spans as a square from -8,-8 to 8,8.
Index: /code/branches/RacingBots_FS18/src/modules/weapons/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,21 @@
+SET_SOURCE_FILES(WEAPONS_SRC_FILES
+  MuzzleFlash.cc
+  RocketController.cc
+  IceGunFreezer.cc
+)
+
+ADD_SUBDIRECTORY(munitions)
+ADD_SUBDIRECTORY(projectiles)
+ADD_SUBDIRECTORY(weaponmodes)
+
+ORXONOX_ADD_LIBRARY(weapons
+  MODULE
+  FIND_HEADER_FILES
+  PCH_FILE
+    WeaponsPrecompiledHeaders.h
+  LINK_LIBRARIES
+    orxonox
+    # TODO: Remove this as soon as projectiles aren't hardcoded anymore buth rather defined in XML
+    objects
+  SOURCE_FILES ${WEAPONS_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/modules/weapons/IceGunFreezer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/IceGunFreezer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/IceGunFreezer.cc	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+*   ORXONOX - the hottest 3D action shooter ever to exist
+*                    > www.orxonox.net <
+*
+*
+*   License notice:
+*
+*   This program 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.
+*
+*   This program 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 this program; if not, write to the Free Software
+*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*
+*   Author:
+*     Fabien Vultier
+*   Co-authors:
+*      ...
+*
+*/
+
+/**
+    @file IceGunFreezer.h
+    @brief Implementation of the IceGunFreezer class.
+*/
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+
+#include "IceGunFreezer.h"
+
+namespace orxonox
+{
+    RegisterClass(IceGunFreezer);
+
+    /**
+    @brief
+        Constructor.
+    */
+    IceGunFreezer::IceGunFreezer(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(IceGunFreezer);
+
+        model = new Model(this->getContext());
+        model->setMeshSource("IceStar.mesh");
+        model->setScale(4.0);
+        this->attach(model);
+        model->setPosition(Vector3(0,0,0));
+    }
+
+    IceGunFreezer::~IceGunFreezer()
+    {
+
+    }
+
+    /**
+    @brief
+        Sets the freeze time variable to the passed value.
+    */
+    void IceGunFreezer::setFreezeTime(float freezeTime)
+    {
+        freezeTime_ = freezeTime;
+    }
+
+    /**
+    @brief
+        Sets the freeze factor variable to the passed value.
+    */
+    void IceGunFreezer::setFreezeFactor(float freezeFactor)
+    {
+        freezeFactor_ = freezeFactor;
+    }    
+
+    /**
+    @brief
+        Try to slow down the WorldEntity where this is attached to. It is only possible to slow down a SpaceShip.
+    */
+    void IceGunFreezer::startFreezing()
+    {
+        WorldEntity* parent = this->getParent();
+
+        // Check if the freezer is attached to a parent and check if the parent is a SpaceShip
+        if (parent != nullptr && parent->isA(Class(SpaceShip)))
+        {
+            freezedSpaceShip_ = orxonox_cast<SpaceShip*>(parent);
+            //Slow down the SpaceShip
+            freezedSpaceShip_->addSpeedFactor(freezeFactor_);
+        }
+
+        // Start timer even if the victim is not a SpaceShip to avoid that the IceGunFreezer gets never destroyed if it collided against a Pawn
+        this->freezeTimer_.setTimer(this->freezeTime_, false, createExecutor(createFunctor(&IceGunFreezer::stopFreezing, this)));
+    }
+
+    /**
+    @brief
+        This method is called by the timer. It gives back the original engine strength to the hit SpaceShip.
+    */
+    void IceGunFreezer::stopFreezing()
+    {
+        if (freezedSpaceShip_ != nullptr && freezeFactor_ != 0.0)
+        {
+            freezedSpaceShip_->addSpeedFactor(1/freezeFactor_);
+        }
+
+        this->destroy();
+    }    
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/IceGunFreezer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/IceGunFreezer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/IceGunFreezer.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceGunFreezer.h
+    @brief Definition of the IceGunFreezer class.
+*/
+
+#ifndef _IceGunFreezer_H__
+#define _IceGunFreezer_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "worldentities/StaticEntity.h"
+#include "graphics/Model.h"
+#include "tools/Timer.h"  
+#include "worldentities/pawns/SpaceShip.h"  
+
+namespace orxonox
+{
+    /**
+    @brief
+        This is the WorldEntity that gets attached to a victim hit by a IceGunProjectile. It slows down the hit SpaceShip by a defined amount and time.
+    @ingroup Weapons
+    */
+    class _WeaponsExport IceGunFreezer : public StaticEntity
+    {
+        public:
+            IceGunFreezer(Context* context);
+            virtual ~IceGunFreezer();
+            virtual void startFreezing();
+            virtual void stopFreezing();
+            virtual void setFreezeTime(float freezeTime);
+            virtual void setFreezeFactor(float freezeFactor);
+        private:
+            float freezeTime_; //The duration of the freezing effect on a target
+            float freezeFactor_; //The strength of the freezing effect            
+            Model* model;
+            Timer freezeTimer_;
+            WeakPtr<SpaceShip> freezedSpaceShip_;
+    };
+}
+
+#endif /* _IceGunFreezer_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/MuzzleFlash.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/MuzzleFlash.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/MuzzleFlash.cc	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Hagen Seifert
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MuzzleFlash.h
+    @brief Implementation of the MuzzleFlash class.
+*/
+
+#include "MuzzleFlash.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+
+namespace orxonox
+{
+    RegisterClass(MuzzleFlash);
+
+    MuzzleFlash::MuzzleFlash(Context* context) : Billboard(context)
+    {
+        RegisterObject(MuzzleFlash);
+        this->setScale(0.1f);
+
+        if( GameMode::isMaster() )
+            this->delayTimer_.setTimer(0.1f, false, createExecutor(createFunctor(&MuzzleFlash::destroy, this)));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/MuzzleFlash.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/MuzzleFlash.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/MuzzleFlash.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Hagen Seifert
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MuzzleFlash.h
+    @brief Definition of the MuzzleFlash class.
+*/
+
+#ifndef _MuzzleFlash_H__
+#define _MuzzleFlash_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+#include "graphics/Billboard.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A muzzle flash that destroys itself after some time.
+    @author
+        Hagen Seifert
+    @ingroup Weapons
+    @todo
+        Remove because it's unused?
+    */
+    class _WeaponsExport MuzzleFlash : public Billboard
+    {
+        public:
+            MuzzleFlash(Context* context);
+            virtual ~MuzzleFlash() {}
+
+        private:
+            Timer delayTimer_; //!< Timer to destroy the object.
+    };
+}
+
+#endif /* _MuzzleFlash_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/RocketController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/RocketController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/RocketController.cc	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+*   ORXONOX - the hottest 3D action shooter ever to exist
+*                    > www.orxonox.net <
+*
+*
+*   License notice:
+*
+*   This program 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.
+*
+*   This program 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 this program; if not, write to the Free Software
+*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*
+*   Author:
+*     Gabriel Nadler
+*   Co-authors:
+*      ...
+*
+*/
+
+/**
+    @file BasicProjectile.h
+    @brief Implementation of the BasicProjectile class.
+*/
+
+#include "RocketController.h"
+
+#include "util/Math.h"
+#include "worldentities/pawns/Pawn.h"
+#include "projectiles/SimpleRocket.h"
+#include "weaponmodes/SimpleRocketFire.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(RocketController);
+
+    /**
+    @brief
+        Constructor.
+    */
+    RocketController::RocketController(Context* context) : Controller(context)
+    {
+        RegisterObject(RocketController);
+//        orxout() << "RocketController constructed" << endl;
+
+        // Create a rocket for the controller.
+        this->rocket_ = new SimpleRocket(this->getContext());
+        this->rocket_->setController(this);
+        this->setControllableEntity(orxonox_cast<ControllableEntity*>(this->rocket_));
+    }
+
+
+    /**
+    @brief
+        The controlling happens here. This method defines what the controller has to do each tick.
+    @param dt
+        The duration of the tick.
+    */
+    void RocketController::tick(float dt)
+    {
+        if (this->target_ && this->rocket_->hasFuel()) {
+            this->updateTargetPosition();
+            this->moveToPosition(this->targetPosition_);
+        }
+    }
+
+    RocketController::~RocketController()
+    {
+//        orxout() << "RocketController destroyed" << endl;
+    }
+
+    /**
+    @brief
+        Update the position of the target.
+    */
+    void RocketController::updateTargetPosition()
+    {
+        this->targetPosition_ = this->target_->getWorldPosition(); //don't really note a difference in the rocket behaviour xD
+        //this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getWorldPosition(),this->getControllableEntity()->getVelocity().length() , this->target_->getWorldPosition(), this->target_->getVelocity());
+    }
+
+    void RocketController::moveToPosition(const Vector3& target)
+    {
+        if (!this->getControllableEntity())
+            return;
+
+        Vector2 coord = get2DViewdirection(this->rocket_->getPosition(), this->rocket_->getOrientation() * WorldEntity::FRONT, this->rocket_->getOrientation() * WorldEntity::UP, target);
+        float distance = (target - this->rocket_->getWorldPosition()).length();
+
+
+        if (distance > 1000 && this->rocket_->getVelocity().squaredLength()<160000)
+            this->rocket_->setAcceleration(this->rocket_->getOrientation()*Vector3(-20,-20,-20));
+        if (distance < 1000) this->rocket_->setAcceleration(0,0,0);
+
+        this->rocket_->rotateYaw(-sgn(coord.x)*coord.x*coord.x);
+        this->rocket_->rotatePitch(sgn(coord.y)*coord.y*coord.y);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/RocketController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/RocketController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/RocketController.h	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gabriel Nadler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file RocketController.h
+    @brief Definition of the RocketController class.
+*/
+
+#ifndef _RocketController_H__
+#define _RocketController_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "controllers/Controller.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Controller for the SimpleRocket (target seeking)
+    @author
+        Gabriel Nadler
+    @ingroup Weapons
+    */
+    class _WeaponsExport RocketController : public Controller, public Tickable
+    {
+        public:
+            RocketController(Context* context);
+            virtual ~RocketController();
+
+            virtual void tick(float dt) override;
+            /**
+            @brief Get the rocket that is controlled by this controller.
+            @return Returns a pointer to the rocket.
+            */
+            SimpleRocket* getRocket() const
+                { return this->rocket_; };
+
+            /**
+            @brief Set the target of the rocket.
+            @param target A pointer to the target.
+            */
+            void setTarget(WorldEntity* target)
+                { this->target_ = target; }
+
+        protected:
+            void updateTargetPosition();
+            void moveToPosition(const Vector3& target);
+
+        private:
+            SimpleRocket* rocket_; //!< The Rocket it controls.
+            Vector3 targetPosition_; //!< The position of the target.
+            WeakPtr<PlayerInfo> player_; //!< The player the rocket belongs to.
+
+            WeakPtr<WorldEntity> target_; //!< The target.
+    };
+}
+
+#endif /* _RocketController_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/WeaponsPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/WeaponsPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/WeaponsPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the weapons module
+@details
+    Updated: 13. September 2009
+    Total Files: 13
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <LinearMath/btMotionState.h> // 10
+#include "util/OgreForwardRefs.h"     // 10
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/CoreIncludes.h" // 13
+#include "core/BaseObject.h" // 13
+#include "tools/Timer.h" // 13
+
+///////////////////////////////////////////
+/////      Not so Stable Headers      /////
+///////////////////////////////////////////
+
+#include "network/synchronisable/Synchronisable.h" // 10
+//#include "worldentities/WorldEntity.h"      // 10
+//#include "weapons/projectiles/Projectile.h" // 9
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/modules/weapons/WeaponsPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/WeaponsPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/WeaponsPrereqs.h	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the weapons module
+*/
+
+#ifndef _WeaponsPrereqs_H__
+#define _WeaponsPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "OrxonoxPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(WEAPONS_STATIC_BUILD)
+#  ifdef WEAPONS_SHARED_BUILD
+#    define _WeaponsExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _WeaponsExport
+#    else
+#      define _WeaponsExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _WeaponsPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _WeaponsExport  __attribute__ ((visibility("default")))
+#  define _WeaponsPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _WeaponsExport
+#  define _WeaponsPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class MuzzleFlash;
+    class IceGunFreezer;
+    class RocketController;
+
+    // munitions
+    class FusionMunition;
+    class LaserMunition;
+    class RocketMunition;
+    class GravityBombMuntion;
+    class IceMunition;
+    class LightningMunition;
+    class SplitMunition;
+
+    // projectiles
+    class BillboardProjectile;
+    class LightningGunProjectile;
+    class ParticleProjectile;
+    class IceProjectile;
+    class SplitProjectile;
+    class Projectile;
+    class BasicProjectile;
+    class Rocket;
+    class RocketOld;
+    class SimpleRocket;
+    class GravityBomb;
+
+    // weaponmodes
+    class EnergyDrink;
+    class FusionFire;
+    class HsW01;
+    class IceGun;
+    class SplitGun;
+    class LaserFire;
+    class LightningGun;
+    class MineGun;
+    class RocketFire;
+    class RocketFireOld;
+    class SimpleRocketFire;
+    class GravityBombFire;
+}
+
+#endif /* _WeaponsPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,11 @@
+ADD_SOURCE_FILES(WEAPONS_SRC_FILES
+  LaserMunition.cc
+  LightningMunition.cc
+  FusionMunition.cc
+  RocketMunition.cc
+  GravityBombMunition.cc
+  IceMunition.cc
+  FlameMunition.cc
+  SplitMunition.cc
+  MineMunition.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FlameMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FlameMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FlameMunition.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlameMunition.h
+    @brief Implementation of the FlameMunition class.
+*/
+
+#include "FlameMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(FlameMunition);
+
+    FlameMunition::FlameMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(FlameMunition);
+
+        this->maxMunitionPerMagazine_ = 90;
+        this->maxMagazines_ = 3;
+        this->unassignedMagazines_ = 3;
+
+        this->deployment_ = MunitionDeployment::Share;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = false;
+
+        this->reloadTime_ = 0.5f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FlameMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FlameMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FlameMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlameMunition.h
+    @brief Definition of the FlameMunition class.
+*/
+
+#ifndef _FlameMunition_H__
+#define _FlameMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        FlameMunition.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport FlameMunition : public Munition
+    {
+        public:
+            FlameMunition(Context* context);
+            virtual ~FlameMunition() = default;
+    };
+}
+
+#endif /* _FlameMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FusionMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FusionMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FusionMunition.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FusionMunition.cc
+    @brief Implementation of the FusionMunition class.
+*/
+
+#include "FusionMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(FusionMunition);
+
+    FusionMunition::FusionMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(FusionMunition);
+
+        this->maxMunitionPerMagazine_ = 10;
+        this->maxMagazines_ = 10;
+        this->unassignedMagazines_ = 10;
+
+        this->deployment_ = MunitionDeployment::Separate;
+
+        this->reloadTime_ = 1.0f;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = true;
+
+        this->reloadTime_ = 0.5f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FusionMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FusionMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/FusionMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FusionMunition.h
+    @brief Definition of the FusionMunition class.
+*/
+
+#ifndef _FusionMunition_H__
+#define _FusionMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        FusionMunition.
+    @author
+        Martin Polak
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport FusionMunition : public Munition
+    {
+        public:
+            FusionMunition(Context* context);
+            virtual ~FusionMunition() = default;
+    };
+}
+
+#endif /* _FusionMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/GravityBombMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/GravityBombMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/GravityBombMunition.cc	(revision 11817)
@@ -0,0 +1,32 @@
+/*
+ * GravityBombMunition.cc
+ *
+ *  Created on: Apr 16, 2015
+ *      Author: Manuel Eggimann
+ */
+#include "GravityBombMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+RegisterClass(GravityBombMunition);
+
+    GravityBombMunition::GravityBombMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(GravityBombMunition);
+        this->maxMunitionPerMagazine_ = 1;
+        this->maxMagazines_ = 30;
+        this->unassignedMagazines_ = 15;
+
+        this->deployment_ = MunitionDeployment::Stack;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = false;
+
+        this->reloadTime_ = 0.0f;
+    }
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/GravityBombMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/GravityBombMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/GravityBombMunition.h	(revision 11817)
@@ -0,0 +1,35 @@
+/*
+ * GravityBombMunition.h
+ *
+ *  Created on: Apr 16, 2015
+ *      Author: meggiman
+ */
+
+#ifndef GRAVITYBOMBMUNITION_H_
+#define GRAVITYBOMBMUNITION_H_
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+    /**
+     * @class   GravityBombMunition
+     *
+     * @brief   This class is used to set the behaviour of various 
+     *          munition specific attributes of the GravityBomb like max count of munition per magazine.
+     *
+     * @author  Manuel
+     * @date    23.05.2015
+     */
+    class _WeaponsExport GravityBombMunition : public Munition
+    {
+        public:
+            GravityBombMunition(Context* context);
+            virtual ~GravityBombMunition() = default;
+    };
+
+}
+
+
+#endif /* GRAVITYBOMBMUNITION_H_ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/IceMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/IceMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/IceMunition.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceMunition.cc
+    @brief Implementation of the IceMunition class.
+*/
+
+#include "IceMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(IceMunition);
+
+    IceMunition::IceMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(IceMunition);
+
+        this->maxMunitionPerMagazine_ = 1;
+        this->maxMagazines_ = 50;
+        this->unassignedMagazines_ = 25;
+
+        this->deployment_ = MunitionDeployment::Stack;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = false;
+
+        this->reloadTime_ = 0.5f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/IceMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/IceMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/IceMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceMunition.h
+    @brief Definition of the IceMunition class.
+*/
+
+#ifndef _IceMunition_H__
+#define _IceMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        IceMunition.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport IceMunition : public Munition
+    {
+        public:
+            IceMunition(Context* context);
+            virtual ~IceMunition() = default;
+    };
+}
+
+#endif /* _SplitMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LaserMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LaserMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LaserMunition.cc	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LaserMunition.cc
+    @brief Implementation of the LaserMunition class.
+*/
+
+#include "LaserMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(LaserMunition);
+
+    LaserMunition::LaserMunition(Context* context) : ReplenishingMunition(context)
+    {
+        RegisterObject(LaserMunition);
+
+        this->maxMunitionPerMagazine_ = 20;
+        this->maxMagazines_ = 10;
+        this->unassignedMagazines_ = 10;
+
+        this->deployment_ = MunitionDeployment::Separate;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = true;
+
+        this->replenishInterval_ = 7.0f;
+        this->replenishAmount_ = 1;
+
+        this->reloadTime_ = 0.6f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LaserMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LaserMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LaserMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LaserMunition.h
+    @brief Definition of the LaserMunition class.
+*/
+
+#ifndef _LaserMunition_H__
+#define _LaserMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/ReplenishingMunition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        LaserMunition.
+    @author
+        Martin Polak
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport LaserMunition : public ReplenishingMunition
+    {
+        public:
+            LaserMunition(Context* context);
+            virtual ~LaserMunition() = default;
+    };
+}
+
+#endif /* _LaserMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LightningMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LightningMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LightningMunition.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LightningMunition.cc
+    @brief Implementation of the LightningMunition class.
+*/
+
+#include "LightningMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(LightningMunition);
+
+    LightningMunition::LightningMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(LightningMunition);
+
+        this->maxMunitionPerMagazine_ = 20;
+        this->maxMagazines_ = 1;
+        this->unassignedMagazines_ = 1;
+
+        this->deployment_ = MunitionDeployment::Share;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = true;
+
+        this->reloadTime_ = 0.5f;    
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LightningMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LightningMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/LightningMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LightningMunition.h
+    @brief Definition of the LightningMunition class.
+*/
+
+#ifndef _LightningMunition_H__
+#define _LightningMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        LightningMunition.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport LightningMunition : public Munition
+    {
+        public:
+            LightningMunition(Context* context);
+            virtual ~LightningMunition() = default;
+    };
+}
+
+#endif /* _LightningMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/MineMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/MineMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/MineMunition.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MineMunition.h
+    @brief Implementation of the MineMunition class.
+*/
+
+#include "MineMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(MineMunition);
+
+    MineMunition::MineMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(MineMunition);
+
+        this->maxMunitionPerMagazine_ = 1;
+        this->maxMagazines_ = 100;
+        this->unassignedMagazines_ = 25;
+
+        this->deployment_ = MunitionDeployment::Stack;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = false;
+
+        this->reloadTime_ = 0.5f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/MineMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/MineMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/MineMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MineMunition.h
+    @brief Definition of the MineMunition class.
+*/
+
+#ifndef _MineMunition_H__
+#define _MineMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        MineMunition.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport MineMunition : public Munition
+    {
+        public:
+            MineMunition(Context* context);
+            virtual ~MineMunition() = default;
+    };
+}
+
+#endif /* _MineMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/RocketMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/RocketMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/RocketMunition.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file RocketMunition.cc
+    @brief Implementation of the RocketMunition class.
+*/
+
+#include "RocketMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(RocketMunition);
+
+    RocketMunition::RocketMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(RocketMunition);
+
+        this->maxMunitionPerMagazine_ = 1;
+        this->maxMagazines_ = 30;
+        this->unassignedMagazines_ = 10;
+
+        this->deployment_ = MunitionDeployment::Stack;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = false;
+
+        this->reloadTime_ = 0.5f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/RocketMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/RocketMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/RocketMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file RocketMunition.h
+    @brief Definition of the RocketMunition class.
+*/
+
+#ifndef _RocketMunition_H__
+#define _RocketMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Munition for the Rocket.
+    @author
+        Fabian 'x3n' Landau
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport RocketMunition : public Munition
+    {
+        public:
+            RocketMunition(Context* context);
+            virtual ~RocketMunition() = default;
+    };
+}
+
+#endif /* _RocketMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/SplitMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/SplitMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/SplitMunition.cc	(revision 11817)
@@ -0,0 +1,56 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SplitMunition.cc
+    @brief Implementation of the SplitMunition class.
+*/
+
+#include "SplitMunition.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(SplitMunition);
+
+    SplitMunition::SplitMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(SplitMunition);
+
+        this->maxMunitionPerMagazine_ = 5;
+        this->maxMagazines_ = 10;
+        this->unassignedMagazines_ = 5;
+
+        this->deployment_ = MunitionDeployment::Share;
+
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = false;
+
+        this->reloadTime_ = 0.5f;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/munitions/SplitMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/munitions/SplitMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/munitions/SplitMunition.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SplitMunition.h
+    @brief Definition of the SplitMunition class.
+*/
+
+#ifndef _SplitMunition_H__
+#define _SplitMunition_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        SplitMunition.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsMunitions
+    */
+    class _WeaponsExport SplitMunition : public Munition
+    {
+        public:
+            SplitMunition(Context* context);
+            virtual ~SplitMunition() = default;
+    };
+}
+
+#endif /* _SplitMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BasicProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BasicProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BasicProjectile.cc	(revision 11817)
@@ -0,0 +1,187 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      simonmie
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BasicProjectile.h
+    @brief Implementation of the BasicProjectile class.
+*/
+
+#include "BasicProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/command/Executor.h"
+
+#include "graphics/ParticleSpawner.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(BasicProjectile);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes some default values.
+    */
+    BasicProjectile::BasicProjectile()
+    {
+        RegisterObject(BasicProjectile);// Register the BasicProjectile class to the core
+
+        this->bDestroy_ = false;
+
+        // Default is destroying the projectile after collision
+        this->destroyAfterCollision_ = true;
+
+        // Default damage must be zero, otherwise it would be above zero if no settings are made in the weaponsettings xml file.
+        // same thing for all weaponmodes files
+        this->damage_ = 0.0f;
+        this->healthdamage_ = 0.0f;
+        this->shielddamage_ = 0.0f;
+    }
+
+    BasicProjectile::~BasicProjectile()
+    {
+    }
+
+    /**
+    @brief
+        The function called when a projectile hits another thing.
+        Calls the hit-function, starts the shield recharge countdown, displays visual hit effects defined in Pawn.
+        Needs to be called in the collidesAgainst() function by every Class directly inheriting from BasicProjectile.
+    @param otherObject
+        A pointer to the object the Projectile has collided against.
+    @param contactPoint
+        A btManifoldPoint indicating the point of contact/impact.
+    @param cs
+        The btCollisionShape of the other object
+    @return
+        Returns true if the collision resulted in a successful hit.
+    @see Pawn.h
+    */
+    bool BasicProjectile::processCollision(WorldEntity* otherObject, btManifoldPoint& contactPoint, const btCollisionShape* cs)
+    {
+        if (!this->bDestroy_ && GameMode::isMaster())
+        {
+            if (this->isObjectRelatedToShooter(otherObject) || otherObject->isA(Class(BasicProjectile))) // Prevents you from shooting yourself or other projectiles
+                return false;
+
+            if (getDestroyAfterCollision())
+            {
+                this->bDestroy_ = true; // If something is hit, the object is destroyed and can't hit something else.
+                                        // The projectile is destroyed by its tick()-function (in the following tick).
+                                        // TODO: Use destroyLater() for this
+            }
+
+            Pawn* victim = orxonox_cast<Pawn*>(otherObject); // If otherObject isn't a Pawn, then victim is nullptr
+
+            WorldEntity* entity = orxonox_cast<WorldEntity*>(this);
+            assert(entity); // The projectile must not be a WorldEntity.
+
+            // If visual effects after destruction cause problems, put this block below the effects code block
+            if (victim)
+            {
+                victim->hit(this->getShooter(), contactPoint, cs, this->getDamage(), this->getHealthDamage(), this->getShieldDamage());
+                victim->startShieldRechargeCountdown();
+            }
+
+            // Visual effects for being hit, depending on whether the shield is hit or not
+            if (this->getShooter()) // If the owner does not exist (anymore?), no effects are displayed.
+            {
+                // Damping and explosion effect is only played if the victim is no Pawn (see cast above)
+                // or if the victim is a Pawn, has no shield left, is still alive and any damage goes to the health
+                if (!victim || (victim && !victim->hasShield() && victim->getHealth() > 0.0f && (this->getDamage() > 0.0f || this->getHealthDamage() > 0.0f)))
+                {
+                    {
+                        ParticleSpawner* effect = new ParticleSpawner(this->getShooter()->getContext());
+                        effect->setPosition(entity->getPosition());
+                        effect->setOrientation(entity->getOrientation());
+                        effect->setDestroyAfterLife(true);
+                        effect->setSource("Orxonox/explosion3");
+                        effect->setLifetime(2.0f);
+                    }
+                    // Second effect with same condition
+                    {
+                        ParticleSpawner* effect = new ParticleSpawner(this->getShooter()->getContext());
+                        effect->setPosition(entity->getPosition());
+                        effect->setOrientation(entity->getOrientation());
+                        effect->setDestroyAfterLife(true);
+                        effect->setSource("Orxonox/smoke4");
+                        effect->setLifetime(3.0f);
+                    }
+                }
+
+                // victim->isAlive() is not false until the next tick, so getHealth() > 0 is used instead
+                if (victim && victim->hasShield() && (this->getDamage() > 0.0f || this->getShieldDamage() > 0.0f) && victim->getHealth() > 0.0f)
+                {
+                    ParticleSpawner* effect = new ParticleSpawner(this->getShooter()->getContext());
+                    effect->setDestroyAfterLife(true);
+                    effect->setSource("Orxonox/Shield");
+                    effect->setLifetime(0.5f);
+                    victim->attach(effect);
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if otherObject is equal to the shooter or if one of otherObject's parents is equal to the shooter or if one of the shooter's parent is equal to otherObject.
+     */
+    bool BasicProjectile::isObjectRelatedToShooter(WorldEntity* otherObject)
+    {
+        for (WorldEntity* shooter = this->getShooter(); shooter != nullptr; shooter = shooter->getParent())
+            if (otherObject == shooter)
+                return true;
+        for (WorldEntity* object = otherObject; object != nullptr; object = object->getParent())
+            if (otherObject == this->getShooter())
+                return true;
+
+        return false;
+    }
+
+    /**
+    @brief
+        Check whether the projectile needs to be destroyed and destroys it if so.
+        Needs to be called in the tick() by every Class directly inheriting from BasicProjectile, to make sure the projectile is destroyed after it has hit something.
+    */
+    void BasicProjectile::destroyCheck(void)
+    {
+        if(GameMode::isMaster() && this->bDestroy_)
+            this->destroy();
+    }
+
+    /**
+    @brief
+        Destroys the object.
+    */
+    void BasicProjectile::destroyObject(void)
+    {
+        if(GameMode::isMaster())
+            this->destroy();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BasicProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BasicProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BasicProjectile.h	(revision 11817)
@@ -0,0 +1,140 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      simonmie
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BasicProjectile.h
+    @brief Definition of the BasicProjectile class.
+*/
+
+#ifndef _BasicProjectile_H__
+#define _BasicProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Baseclass of all projectiles. Defines the damage the projectile does.
+
+    @author
+        Simon Miescher
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport BasicProjectile : public virtual OrxonoxInterface
+    {
+        public:
+            BasicProjectile();
+            virtual ~BasicProjectile();
+
+            /**
+            @brief Set the normal damage done by this projectile.
+                   Normal damage can be (partially) absorbed by shields.
+            @param damage The amount of damage. Must be non-negative.
+            */
+            inline void setDamage(float damage)
+                { if(damage >= 0.0f)  { this->damage_ = damage; return; } orxout(internal_warning) << "The input projectile damage must be non-negative. Ignoring..." << endl; }
+            /**
+            @brief Get the normal damage done by this projectile.
+                   Normal damage can be (partially) absorbed by shields.
+            @return Returns the amount of damage. Is non-negative.
+            */
+            inline float getDamage() const
+                { return this->damage_; }
+
+            /**
+            @brief Set the health-damage done by this projectile.
+                   Health-damage cannot be absorbed by shields.
+            @param healthdamage The amount of damage. Must be non-negative.
+            */
+            inline void setHealthDamage(float healthdamage)
+                { if(healthdamage >= 0.0f)  { this->healthdamage_ = healthdamage; return; } orxout(internal_warning) << "The input projectile health-damage must be non-negative. Ignoring..." << endl; }
+            /**
+            @brief Get the health-damage done by this projectile.
+                   Health-damage cannot be absorbed by shields.
+            @return healthdamage The amount of damage. Is non-negative.
+            */
+            inline float getHealthDamage() const
+                { return this->healthdamage_; }
+
+            /**
+            @brief Set the shield-damage done by this projectile.
+                   Shield-damage only reduces shield health.
+            @param shielddamage The amount of damage. Must be non-negative.
+            */
+            inline void setShieldDamage(float shielddamage)
+                { if(shielddamage >= 0.0f)  { this->shielddamage_ = shielddamage; return; } orxout(internal_warning) << "The input projectile shield-damage must be non-negative. Ignoring..." << endl; }
+            /**
+            @brief Get the shield-damage done by this projectile.
+            */
+            inline float getShieldDamage() const
+                { return this->shielddamage_; }
+
+            /**
+            @brief Set the entity that fired the projectile.
+            @param shooter A pointer to the Pawn that fired the projectile.
+            */
+            virtual void setShooter(Pawn* shooter)
+                { this->shooter_ = shooter; }
+            /**
+            @brief Get the entity that fired the projectile.
+            @return Returns a pointer to the Pawn that fired the projectile.
+            */
+            inline Pawn* getShooter(void)
+                { return this->shooter_; }
+
+            virtual void destroyObject(void);
+
+        protected:
+            bool processCollision(WorldEntity* otherObject, btManifoldPoint& contactPoint, const btCollisionShape* cs);
+            void destroyCheck(void);
+            inline void setDestroyAfterCollision(bool destroyAfterCollision)
+                { destroyAfterCollision_ = destroyAfterCollision; }
+            inline bool getDestroyAfterCollision() const
+                { return destroyAfterCollision_; }
+
+        private:
+            bool isObjectRelatedToShooter(WorldEntity* otherObject);
+
+            WeakPtr<Pawn> shooter_; //!< The entity that fired the projectile.
+
+            float damage_; //!< The amount of normal damage. Normal damage can be (partially) absorbed by shields.
+            float healthdamage_; //!< The amount of health-damage. Health-damage cannot be absorbed by shields.
+            float shielddamage_; //!< The amount of shield-damage. Shield-damage only reduces shield health.
+
+            bool bDestroy_; //!< Boolean, to check whether a projectile should be destroyed.
+            bool destroyAfterCollision_; //!< Boolean, defines whether the projectile gets detroyed after a collision.
+    };
+}
+
+#endif /* _BasicProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BillboardProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BillboardProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BillboardProjectile.cc	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BillboardProjectile.h
+    @brief Implementation of the BillboardProjectile class.
+*/
+
+#include "BillboardProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(BillboardProjectile);
+
+    BillboardProjectile::BillboardProjectile(Context* context) : Projectile(context)
+    {
+        RegisterObject(BillboardProjectile);
+
+        if (GameMode::showsGraphics())
+        {
+            assert(this->getScene()->getSceneManager()); // getScene() was already checked by WorldEntity
+
+            // Create the billboard.
+            this->billboard_.setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(0.5f, 0.5f, 0.7f, 0.8f), 1);
+            this->attachOgreObject(this->billboard_.getBillboardSet());
+        }
+
+        this->setScale(0.2f);
+    }
+
+    BillboardProjectile::~BillboardProjectile()
+    {
+        if (this->isInitialized() && GameMode::showsGraphics() && this->billboard_.getBillboardSet())
+            this->detachOgreObject(this->billboard_.getBillboardSet());
+    }
+
+    /**
+    @brief
+        Set the colour of the BillboardProjectile.
+    @param colour
+        The colour to be set.
+    */
+    void BillboardProjectile::setColour(const ColourValue& colour)
+    {
+        this->billboard_.setColour(colour);
+    }
+
+    /**
+    @brief
+        Set the material of the BillboardProjectile.
+    @param material
+        The material name.
+    */
+    void BillboardProjectile::setMaterial(const std::string& material)
+    {
+        this->billboard_.setMaterial(material);
+    }
+
+    /**
+    @brief
+        Get the material of the BillboardProjectile.
+    @return
+        The material name.
+    */
+    const std::string& BillboardProjectile::getMaterial()
+    {
+        return this->billboard_.getMaterial();
+    }
+
+    /**
+    @brief
+        Is called when the visibility of the BillboardProjectile has changed.
+    */
+    void BillboardProjectile::changedVisibility()
+    {
+        SUPER(BillboardProjectile, changedVisibility);
+
+        // Also change the visibility of the billboard.
+        this->billboard_.setVisible(this->isVisible());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BillboardProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BillboardProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/BillboardProjectile.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file BillboardProjectile.h
+    @brief Definition of the BillboardProjectile class.
+*/
+
+#ifndef _BillboardProjectile_H__
+#define _BillboardProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "util/Math.h"
+#include "tools/BillboardSet.h"
+#include "Projectile.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A BillboardProjectile is a projectile that is represented by a Billboard.
+
+    @author
+        Fabian 'x3n' Landau
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport BillboardProjectile : public Projectile
+    {
+        public:
+            BillboardProjectile(Context* context);
+            virtual ~BillboardProjectile();
+
+            virtual void setColour(const ColourValue& colour);
+            virtual void setMaterial(const std::string& material);
+            virtual const std::string& getMaterial();
+            virtual void changedVisibility() override;
+
+        private:
+            BillboardSet billboard_; //!< The billboard that represents the projectile.
+    };
+}
+
+#endif /* _BillboardProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,16 @@
+ADD_SOURCE_FILES(WEAPONS_SRC_FILES
+  BasicProjectile.cc
+  BillboardProjectile.cc
+  ParticleProjectile.cc
+  Projectile.cc
+  LightningGunProjectile.cc
+  SplitGunProjectile.cc
+  IceGunProjectile.cc
+  FlameGunProjectile.cc
+  Rocket.cc
+  RocketOld.cc
+  SimpleRocket.cc
+  GravityBomb.cc
+  GravityBombField.cc
+  MineProjectile.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/FlameGunProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/FlameGunProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/FlameGunProjectile.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlameGunProjectile.h
+    @brief Implementation of the FlameGunProjectile class.
+*/
+
+#include "FlameGunProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "util/Convert.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    RegisterClass(FlameGunProjectile);
+
+    FlameGunProjectile::FlameGunProjectile(Context* context) : ParticleProjectile(context)
+    {
+        RegisterObject(FlameGunProjectile);
+
+        this->lifetime_ = 1.0f;
+        this->spread_ = 0.1f;
+
+        setDestroyAfterCollision(false);
+        setEffect("Orxonox/fire3");
+    }
+
+    void FlameGunProjectile::setLifetime(float lifetime)
+    {
+        if (lifetime >= 0.0)
+        {
+            this->lifetime_ = lifetime;
+            this->flameTimer_.setTimer(this->lifetime_, false, createExecutor(createFunctor(&FlameGunProjectile::destroy, this)));
+        }
+        else
+        {
+            this->lifetime_ = 0.0;
+        }
+    }
+
+    void FlameGunProjectile::setSpread(float spread)
+    {
+        spread_ = spread;
+    }
+
+    bool FlameGunProjectile::processCollision(WorldEntity* otherObject, btManifoldPoint& contactPoint, const btCollisionShape* cs)
+    {
+        bool result = ParticleProjectile::processCollision(otherObject, contactPoint, cs);
+
+        // Every projectile can only deal damage once.
+        setDamage(0.0);
+        setHealthDamage(0.0);
+        setShieldDamage(0.0);
+
+        return result;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/FlameGunProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/FlameGunProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/FlameGunProjectile.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlameGunProjectile.h
+    @brief Definition of the FlameGunProjectile class.
+*/
+
+#ifndef _FlameGunProjectile_H__
+#define _FlameGunProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include <string>
+#include "tools/Timer.h"
+#include "ParticleProjectile.h"
+
+namespace orxonox
+{
+
+    /**
+    @author
+        Fabien Vultier
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport FlameGunProjectile : public ParticleProjectile
+    {
+        public:
+            FlameGunProjectile(Context* context);
+            virtual ~FlameGunProjectile() {}
+
+            virtual void setLifetime(float lifetime);
+            virtual void setSpread(float spread);
+        protected:
+            bool processCollision(WorldEntity* otherObject, btManifoldPoint& contactPoint, const btCollisionShape* cs);
+
+        private:            
+            float lifetime_;
+            float spread_;
+            Timer flameTimer_;
+    };
+}
+
+#endif /* _FlameGunProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBomb.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBomb.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBomb.cc	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ * GravityBomb.cc
+ *
+ *  Created on: Mar 26, 2015
+ *      Author: Manuel Eggimann
+ */
+#include "GravityBomb.h"
+#include "graphics/Model.h"
+
+
+namespace orxonox{
+    RegisterClass(GravityBomb);
+
+    const float GravityBomb::LIFETIME = 2.5;  ///< The gravity bomb lifetime in seconds.
+
+    GravityBomb::GravityBomb(Context* context):
+                BasicProjectile(),
+                MovableEntity(context),
+                RadarViewable(this,static_cast<WorldEntity*>(this))
+        {
+            RegisterObject(GravityBomb);
+
+            this->setMass(10.0);
+            this->hasCollided_ = false;
+            if (GameMode::isMaster())
+            {
+                //Define CollisionType of the bomb
+                this->timeToLife_= LIFETIME;
+                this->setCollisionResponse(false);
+                this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+                this->enableCollisionCallback();
+
+                //Add Collision Shape
+                SphereCollisionShape* collisionShape = new SphereCollisionShape(context);
+                collisionShape->setRadius(1.0);
+                this->attachCollisionShape(collisionShape);
+
+                //Create Bomb Model
+                Model* rocketModel = new Model(this->getContext());
+                rocketModel->setMeshSource("GravityBombRocket.mesh"); //Demo Model from SimpleRocket
+                rocketModel->scale(3.0f);
+                this->attach(rocketModel);
+                //Add second model because the bomb consists of the bomb and attached rockets (2 separate models)
+                Model* bombModel =  new Model(this->getContext());
+                bombModel->setMeshSource("GravityBomb.mesh"); //Demo Model from SimpleRocket
+                bombModel->scale(3.0f);
+                this->attach(bombModel);
+
+                //Add particle effect to the flying rockets.
+                ParticleEmitter* fire = new ParticleEmitter(this->getContext());
+                fire->setOrientation(this->getOrientation());
+                fire->setSource("Orxonox/simplerocketfire");
+                this->attach(fire);
+
+                //Add sound effect while the bomb is flying.
+                WorldSound* bombSound = new WorldSound(context);
+                bombSound->setSource("sounds/GravityBombFlight.ogg");
+                bombSound->setLooping(true);
+                bombSound->setVolume(1.0);
+                this->attach(bombSound);
+                bombSound->play();
+            }
+        }
+
+    GravityBomb::~GravityBomb(){}
+
+    void GravityBomb::tick(float dt)
+    {
+        SUPER(GravityBomb, tick, dt);
+        timeToLife_ -= dt;
+        if (timeToLife_ < 0)
+        {
+            //orxout(debug_output) << "bomb has stoped moving" <<endl;
+            setVelocity(Vector3::ZERO); //Stop the bomb.
+            detonate();
+            this->destroy();
+        }
+        else 
+        {
+            if (hasCollided_) detonate();
+            destroyCheck(); //Bomb is going to be destroyed by destroyCheck(). As written in BasicProectile, this Method should be called by every Projectile.
+        }
+    }
+
+    bool GravityBomb::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {
+        hasCollided_ = processCollision(otherObject, contactPoint, cs);
+        return hasCollided_;
+    }
+
+    void GravityBomb::detonate()
+    {
+        //Create the GravityBombField and destroy the Projectil.
+        GravityBombField* field = new GravityBombField(this->getContext());
+        field->setShooter(this->getShooter());
+        field->setPosition(getPosition());
+        //orxout(debug_output) << "detonating. Creating GravityBombField." <<endl;
+        //orxout(debug_output) << "Field is at Position: " << getPosition() << endl;
+    }
+}
+
+
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBomb.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBomb.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBomb.h	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ * GravityBomb.h
+ *
+ *  Created on: Mar 19, 2015
+ *      Author: meggiman
+ */
+
+#ifndef GravityBOMB_H_
+#define GravityBOMB_H_
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+
+#include "graphics/ParticleSpawner.h"
+#include "interfaces/RadarViewable.h"
+#include "objects/ForceField.h"
+#include "BasicProjectile.h"
+#include "worldentities/MovableEntity.h"
+#include "core/CoreIncludes.h"
+#include "objects/collisionshapes/SphereCollisionShape.h"
+#include "worldentities/WorldEntity.h"
+#include "GravityBombField.h"
+#include "sound/WorldSound.h"
+
+namespace orxonox
+{
+    /**
+     * @class   GravityBomb
+     *
+     * @brief   This class implements how long the bomb flies before it places the GravityField at it's last possition.
+     *          The field will be created either because the timelimit of the bomb expired or it hit something. After creation of the field,
+     *          the projectile (this object) is destroyed.
+     *
+     * @author  Manuel Eggimann
+     * @date    23.05.2015
+     */
+    class _WeaponsExport GravityBomb : public BasicProjectile , public MovableEntity, public RadarViewable
+    {
+        public:
+            GravityBomb(Context* context);
+            virtual ~GravityBomb();
+            virtual void tick(float dt) override;
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+            void detonate();
+        private:
+        static const float LIFETIME;
+
+        bool hasCollided_;
+        float timeToLife_; //Time the bomb flies before it explodes.
+        WorldSound* bombSound_;
+    };
+}
+#endif /* GravityBOMB_H_ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBombField.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBombField.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBombField.cc	(revision 11817)
@@ -0,0 +1,175 @@
+/*
+ * GravityBombField.cc
+ *
+ *  Created on: Apr 2, 2015
+ *      Author: Manuel Eggimann
+ */
+
+#include "GravityBombField.h"
+#include "graphics/Model.h"
+
+namespace orxonox{
+    RegisterClass(GravityBombField);
+
+    //Change these constants to alter the behaviour of the field.
+    
+    const float GravityBombField::FORCE_FIELD_LIFETIME = 15;
+    const float GravityBombField::FORCE_SPHERE_START_RADIUS = 250;
+    const float GravityBombField::FORCE_SPHERE_START_STRENGTH = -700;
+    const float GravityBombField::PEAK_EXPLOSION_FORCE = 5e4;
+    const float GravityBombField::FORCE_FIELD_EXPLOSION_DAMMAGE = 100;
+    const float GravityBombField::EXPLOSION_DURATION = 1;
+    const float GravityBombField::EXPLOSION_RADIUS = 600;
+    const float GravityBombField::PEAK_ANGULAR_VELOCITY = 20;
+    const float GravityBombField::CENTRE_MODEL_END_SIZE = 1.5;
+
+    GravityBombField::GravityBombField(Context* context) : ForceField(context),RadarViewable(this, static_cast<WorldEntity*>(this))
+    {
+        RegisterObject(GravityBombField);
+        //Initialize variable with their initial values.
+        lifetime_=FORCE_FIELD_LIFETIME;
+        forceStrength_ = FORCE_SPHERE_START_STRENGTH;
+        forceSphereRadius_ = FORCE_SPHERE_START_RADIUS;
+        modelScaling_ = 1;
+        fieldExploded_ = false;
+
+        setFieldVelocity(FORCE_SPHERE_START_STRENGTH);
+        setDiameter(2*FORCE_SPHERE_START_RADIUS);
+        setMode(modeSphere_s);
+        setCollisionResponse(false);
+
+        //Make the Field visible on Radar and minimap.
+        this->setRadarObjectColour(ColourValue(1.0, 0.0, 0.2,1)); // Red
+        this->setRadarObjectShape(RadarViewable::Shape::Dot);
+        this->setRadarObjectScale(1.0f);
+        
+
+        //Attach Model
+        Model* model = new Model(this->getContext());
+        model->setMeshSource("GravityBomb.mesh"); //Demo Model from SimpleRocket
+        model->scale(2.5f);
+        bombModel_ = new MovableEntity(context);
+        bombModel_->attach(model);
+        this->attach(bombModel_);
+
+        //Add a Backlight to the centre.
+        centreLight_ = new Backlight(context);
+        centreLight_->setColour(ColourValue(0.2,0.9,0.2,1));
+        centreLight_->setScale(0.3);
+        centreLight_->setTrailMaterial("Trail/backlighttrail");
+        centreLight_->setMaterial("Examples/Flare");
+        centreLight_->setLifetime(20);
+        bombModel_->attach(centreLight_);
+
+        //Let the Bomb Modell in the centre rotate in a random direction.
+        Vector3 randomRotation;
+        randomRotation.x = rnd();
+        randomRotation.y = rnd();
+        randomRotation.z = rnd();
+        randomRotation.normalise();
+        bombModel_->setAngularAcceleration(randomRotation*(PEAK_ANGULAR_VELOCITY/FORCE_FIELD_LIFETIME));
+
+        //Add Collision Shape
+        SphereCollisionShape* collisionShape = new SphereCollisionShape(context);
+        collisionShape->setRadius(10.0);
+        this->attachCollisionShape(collisionShape);
+
+        //Add particle effect to visualize the force field.
+        this->particleSphere_ = new ParticleEmitter(this->getContext());
+        this->attach(this->particleSphere_);
+        particleSphere_->setSource("Orxonox/GravityBombField");
+
+        //Add a sound effect to the field.
+        WorldSound* fieldSound = new WorldSound(context);
+        fieldSound->setSource("sounds/GravityField.ogg");
+        fieldSound->setLooping(true);
+        fieldSound->setVolume(1.0);
+        this->attach(fieldSound);
+        fieldSound->play();
+    }
+
+    GravityBombField::~GravityBombField(){}
+
+    
+    void GravityBombField::tick(float dt)
+    {
+        SUPER(GravityBombField,tick,dt);
+        lifetime_-=dt;
+
+        if(lifetime_ > EXPLOSION_DURATION)//If field is still alive, make it smaller and stronger.
+        {
+            modelScaling_ += ((CENTRE_MODEL_END_SIZE-1) / FORCE_FIELD_LIFETIME)*dt;
+            forceStrength_ *= (1+dt/10);
+            forceSphereRadius_ = FORCE_SPHERE_START_RADIUS*(1-((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME)*((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME)*((FORCE_FIELD_LIFETIME-lifetime_)/FORCE_FIELD_LIFETIME));
+        }
+        else if(lifetime_ > 0)
+        {
+            if (!fieldExploded_) // Start the field explosion if it has not been started yet.
+            {
+                forceStrength_ = pow((EXPLOSION_DURATION + lifetime_),4)/EXPLOSION_DURATION * PEAK_EXPLOSION_FORCE;
+                fieldExploded_ = true;
+
+                //Add particle effect to visualize explosion
+                explosionCross_ = new ParticleEmitter(this->getContext());
+                explosionCross_->setSource("Orxonox/FieldExplosion");
+                explosionCross_->setOrientation(rnd(), rnd(), rnd(), rnd());
+                explosionCross_->setScale(0.7);
+                this->attach(explosionCross_);
+
+                //Add explosion sound effect.
+                explosionSound_ = new WorldSound(getContext());
+                explosionSound_->setSource("sounds/GravityFieldExplosion.ogg");
+                explosionSound_->setVolume(1.0);
+                explosionSound_->play();
+            }
+
+            //Check if any pawn is inside the shockwave and hit it with dammage proportional to the distance between explosion centre and pawn. Make sure, the same pawn is damaged only once.
+            for (Pawn* pawn : ObjectList<Pawn>())
+            {
+                Vector3 distanceVector = pawn->getWorldPosition()-this->getWorldPosition();
+                 //orxout(debug_output) << "Found Pawn:" << it->getWorldPosition() << endl;
+                if(distanceVector.length()< forceSphereRadius_)
+                {
+                    //orxout(debug_output) << "Force sphere radius is: " << forceSphereRadius_ << " Distance to Pawn is: " << distanceVector.length();
+                    if (std::find(victimsAlreadyDamaged_.begin(),victimsAlreadyDamaged_.end(),pawn) == victimsAlreadyDamaged_.end())
+                    {
+                        //orxout(debug_output) << "Found Pawn to damage: " << it->getWorldPosition() << endl;
+                        float damage = FORCE_FIELD_EXPLOSION_DAMMAGE*(1-distanceVector.length()/EXPLOSION_RADIUS);
+                        //orxout(debug_output) << "Damage: " << damage << endl;
+                        pawn->hit(shooter_, pawn->getWorldPosition(), nullptr, damage, 0,0);
+                        victimsAlreadyDamaged_.push_back(pawn);
+                    }
+                }
+            }
+
+            forceSphereRadius_ = EXPLOSION_RADIUS*(1-lifetime_/EXPLOSION_DURATION);
+            explosionCross_->setScale(forceSphereRadius_/FORCE_SPHERE_START_RADIUS);
+        }
+        else if (lifetime_ > -6) //The field has to exist for 6 more seconds for the particles of the particle effect to vanish smoothly.
+        {
+            //Make the bomb model invisible, let the strength of the field be zero and remove all particle emitters so the particle effect will slowly vanish.
+            bombModel_->setVisible(false);
+            this->setRadarVisibility(false);
+            forceStrength_ = 0;
+            forceSphereRadius_ = 0.00001;
+            particleSphere_->getParticleInterface()->removeAllEmitters();
+            explosionCross_->getParticleInterface()->removeAllEmitters();
+        }
+        
+        setDiameter(forceSphereRadius_*2);
+        setFieldVelocity(forceStrength_);
+        if(lifetime_>0) particleSphere_->setScale(forceSphereRadius_/FORCE_SPHERE_START_RADIUS);
+        bombModel_->setScale(modelScaling_);
+
+        if (lifetime_ <= -4)
+        {
+            this->destroy();
+        }
+    }
+
+    void GravityBombField::destroy()
+    {
+        ForceField::destroy();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBombField.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBombField.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/GravityBombField.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ * GravityBombField.h
+ *
+ *  Created on: Apr 2, 2015
+ *      Author: meggiman
+ */
+
+#ifndef GRAVITYBOMBFIELD_H_
+#define GRAVITYBOMBFIELD_H_
+
+#include "graphics/ParticleSpawner.h"
+#include "interfaces/RadarViewable.h"
+#include "objects/ForceField.h"
+#include "BasicProjectile.h"
+#include "worldentities/MovableEntity.h"
+#include "core/CoreIncludes.h"
+#include "GravityBomb.h"
+#include "graphics/ParticleSpawner.h"
+#include "tools/ParticleInterface.h"
+#include <stdlib.h>
+#include <time.h>
+#include <math.h>
+#include "graphics/Backlight.h"
+#include "sound/WorldSound.h"
+
+namespace orxonox {
+
+/**
+ * @class   GravityBombField
+ *
+ * @brief   This class is used by GravityBomb to place the ForceField and Visual effect to the environment.
+ *          The field has a maximum lifetime and gets smaller and stronger the more time passes. In the end, the field explodes and damages all pawns nearby.
+ *
+ * @author  Manuel Eggimann
+ * @date    23.05.2015
+ */
+class GravityBombField: public ForceField, public RadarViewable {
+public:
+    GravityBombField(Context* context);
+    virtual ~GravityBombField();
+    virtual void tick(float dt) override;
+    virtual void destroy();
+
+    /**
+     * @fn  void GravityBombField::setShooter(Pawn* shooter)
+     *
+     * @brief   This function is used to determine save the pawn who created the field and is used inside the GravityBomb class.
+     *
+     * @author  Manuel Eggimann
+     * @date    23.05.2015
+     *
+     * @param [in,out] shooter the Pawn that created the field.
+     */
+    void setShooter(Pawn* shooter)
+    { this->shooter_ = shooter; }
+
+    Pawn* getShooter()
+    { return this->shooter_; }
+
+private:
+    //Set these constants inside GravityBombField.cc to alter the behaviour of the field.
+    
+    static const float FORCE_FIELD_LIFETIME;    ///< The lifetime of the ForceField in seconds. After lifetime seconds, has already exploded and the particle effects will start to vanish. 
+    static const float FORCE_SPHERE_START_RADIUS;   ///< The initial sphere radius of the Force Field. The forcefield gets smaller by time.
+    static const float FORCE_SPHERE_START_STRENGTH; ///< The initial Force the Field exerts on every object with non-zero mass.
+    static const float FORCE_FIELD_EXPLOSION_DAMMAGE;   ///< The maximum dammage a pawn gets nearby an exploding field. The farer away from explosion center the smaller the dammage.
+    static const float EXPLOSION_DURATION;  ///< Determines how fast the shockwave of the Explosion expands. It takes GravityBombField::EXPLOSION_DURATION seconds for the field to expand from 0 radius to GravityBombField::EXPLOSION_RADIUS.
+    static const float EXPLOSION_RADIUS;    ///< How far does the shockwave reach. All pawns which outside of a sphere witch this radius rest unharmed by the explosion.
+    static const float PEAK_ANGULAR_VELOCITY;   ///< The model of the bomb in the center of the Field does rotate faster and faster as time passes until it reaches PEAK_ANGULAR_VELOCITY at the fields end of life.
+    static const float PEAK_EXPLOSION_FORCE;    ///< The peak force the explosion exerts on the pawns nearby.
+    static const float CENTRE_MODEL_END_SIZE;   ///< Size of the 3d-model of the bomb in the fields centre.
+
+    float forceSphereRadius_;
+    float forceStrength_;
+    float lifetime_;
+    float modelScaling_;
+    Vector3 rotationVector_;
+    bool fieldExploded_;
+    ParticleEmitter * particleSphere_;
+    ParticleEmitter * explosionCross_;
+    std::vector<Pawn*> victimsAlreadyDamaged_;
+    MovableEntity * bombModel_;
+    Pawn* shooter_;
+    Backlight* centreLight_;
+    WorldSound* explosionSound_;
+};
+
+}
+#endif /* GRAVITYBOMBFIELD_H_ */
+
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/IceGunProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/IceGunProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/IceGunProjectile.cc	(revision 11817)
@@ -0,0 +1,129 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceGunProjectile.cc
+    @brief Implementation of the IceGunProjectile class.
+*/
+
+#include "IceGunProjectile.h"
+
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+
+#include "core/CoreIncludes.h"
+#include "graphics/Model.h"
+#include "graphics/ParticleSpawner.h"
+#include "Scene.h"
+#include "core/command/Executor.h"
+#include "tools/ParticleInterface.h"
+
+namespace orxonox
+{
+    RegisterClass(IceGunProjectile);
+
+    const float IceGunProjectile::particleDestructionDelay_ = 15.0f;
+
+    IceGunProjectile::IceGunProjectile(Context* context) : Projectile(context)
+    {
+        RegisterObject(IceGunProjectile);
+
+        this->setCollisionShapeRadius(8.0f);
+
+        this->setFreezeTime(3.0);
+        this->setFreezeFactor(0.5);
+
+        Model* model = new Model(this->getContext());
+        model->setMeshSource("IceBolt.mesh");
+        model->setScale(15.0);
+        this->attach(model);
+        model->setPosition(Vector3(0,0,0));
+
+        // Add effect.
+        spawner_ = new ParticleSpawner(this->getContext());
+        this->attach(spawner_);
+        spawner_->setOrientation(this->getOrientation());
+        spawner_->setSource("Orxonox/ice");
+        spawner_->setDeleteWithParent(false);
+        spawner_->setDestroydelay(particleDestructionDelay_);
+    }
+
+    IceGunProjectile::~IceGunProjectile()
+    {
+        if (this->isInitialized())
+        {
+            const Vector3& pos = spawner_->getWorldPosition();
+            const Quaternion& rot = spawner_->getWorldOrientation();
+            this->detach(spawner_);
+            spawner_->setPosition(pos);
+            spawner_->setOrientation(rot);
+            this->getScene()->getRootSceneNode()->addChild(const_cast<Ogre::SceneNode*>(spawner_->getNode()));
+            this->spawner_->stop(true);
+        }
+    }
+
+    /**
+    @brief
+        Sets the freeze time variable to the passed value.
+    */
+    void IceGunProjectile::setFreezeTime(float freezeTime)
+    {
+        freezeTime_ = freezeTime;
+    }
+
+    /**
+    @brief
+        Sets the freeze factor variable to the passed value.
+    */
+    void IceGunProjectile::setFreezeFactor(float freezeFactor)
+    {
+        freezeFactor_ = freezeFactor;
+    }
+
+    bool IceGunProjectile::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {        
+        bool bCollision = Projectile::collidesAgainst(otherObject, cs, contactPoint);
+
+        if (bCollision)
+        {
+            // If there was a collision, attach a IceGunFreezer to the hit object.
+            IceGunFreezer* freezer = new IceGunFreezer(this->getContext());
+            freezer->setFreezeTime(freezeTime_);
+            freezer->setFreezeFactor(freezeFactor_);
+            otherObject->attach(freezer);            
+
+            Vector3 offset = this->getWorldPosition() - otherObject->getWorldPosition();
+            freezer->setPosition(Vector3(0,0,0));
+            freezer->translate(offset, WorldEntity::TransformSpace::World);
+            // Start the freezing effect.
+            freezer->startFreezing();
+        }
+
+        return bCollision;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/IceGunProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/IceGunProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/IceGunProjectile.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceGunProjectile.h
+    @brief Definition of the IceGunProjectile class.
+*/
+
+#ifndef _IceGunProjectile_H__
+#define _IceGunProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include <string>
+#include "tools/Timer.h"
+#include "BillboardProjectile.h"
+#include "weapons/IceGunFreezer.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The IceGunProjectile is a projectile that attaches a IceGunFreezer to the hit object. This object gets slowed down by the IceGunFreezer.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport IceGunProjectile : public Projectile
+    {
+        public:
+            IceGunProjectile(Context* context);
+            virtual ~IceGunProjectile();
+
+            virtual void setFreezeTime(float freezeTime);
+            virtual void setFreezeFactor(float freezeFactor);
+
+        protected:
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+            static const float particleDestructionDelay_;
+        private:
+            ParticleSpawner* spawner_;
+            float freezeTime_; //The duration of the freezing effect on a target
+            float freezeFactor_; //The strength of the freezing effect
+    };
+}
+
+#endif /* _IceGunProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/LightningGunProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/LightningGunProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/LightningGunProjectile.cc	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Joel Smely
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LightningGunProjectile.h
+    @brief Implementation of the LightningGunProjectile class.
+*/
+
+#include "LightningGunProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    RegisterClass(LightningGunProjectile);
+
+    LightningGunProjectile::LightningGunProjectile(Context* context) : BillboardProjectile(context)
+    {
+        RegisterObject(LightningGunProjectile);
+
+        this->textureIndex_ = 1;
+        this->setMass(0.1f);
+        this->setCollisionType(CollisionType::Dynamic);
+        this->maxTextureIndex_ = 8;
+        this->textureTimer_.setTimer(0.01f, true, createExecutor(createFunctor(&LightningGunProjectile::changeTexture, this)));
+
+        registerVariables();
+    }
+
+    void LightningGunProjectile::registerVariables()
+    {
+        registerVariable(this->materialBase_);
+    }
+
+    /**
+    @brief
+        Set the material.
+    @param material
+        The name of the material. Material names with 1 to 8 appended must exist.
+    */
+    void LightningGunProjectile::setMaterial(const std::string& material)
+    {
+        this->materialBase_ = material;
+
+        BillboardProjectile::setMaterial(material + multi_cast<std::string>(this->textureIndex_));
+    }
+
+    /**
+    @brief
+        Change the texture.
+    */
+    void LightningGunProjectile::changeTexture()
+    {
+        this->textureIndex_++;
+        if (this->textureIndex_ > this->maxTextureIndex_)
+            this->textureIndex_ = 1;
+
+        this->setMaterial(this->materialBase_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/LightningGunProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/LightningGunProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/LightningGunProjectile.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Joel Smely
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LightningGunProjectile.h
+    @brief Definition of the LightningGunProjectile class.
+*/
+
+#ifndef _LightningGunProjectile_H__
+#define _LightningGunProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include <string>
+#include "tools/Timer.h"
+#include "BillboardProjectile.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The LightningGunProjectile is a projectile that is represented by a looped series of billboards.
+        
+    @author
+        Joel Smely
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport LightningGunProjectile : public BillboardProjectile
+    {
+        public:
+            LightningGunProjectile(Context* context);
+            virtual ~LightningGunProjectile() {}
+
+            virtual void setMaterial(const std::string& material) override;
+
+        private:
+            void registerVariables();
+            void changeTexture();
+            
+            unsigned int textureIndex_; //!< The current index of the texture. (i.e. the index of the currently displayed texture)
+            unsigned int maxTextureIndex_; //!< The maximal index.
+            Timer textureTimer_; //!< A timer that loops and changes textures each time it expires.
+            std::string materialBase_; //!< The base name of the material.
+    };
+}
+
+#endif /* _LightningGunProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/MineProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/MineProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/MineProjectile.cc	(revision 11817)
@@ -0,0 +1,281 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Jannis Holzer
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MineProjectile.h
+    @brief Implementation of the MineProjectile class.
+*/
+
+#include "MineProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "graphics/Model.h"
+#include "core/command/Executor.h"
+#include "graphics/ParticleSpawner.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/EventIncludes.h"
+#include "sound/WorldSound.h"
+
+namespace orxonox
+{
+    RegisterClass(MineProjectile);
+
+    const float MineProjectile::collisionShapeRadius_ = 15.0f;
+    const float MineProjectile::damageRadius_ = 200.0f;
+    const float MineProjectile::triggerRadius_ = 100.0f;
+
+    MineProjectile::MineProjectile(Context* context) : MovableEntity(context), BasicProjectile()
+    {
+        RegisterObject(MineProjectile);
+
+        this->bAllowExplosion_ = false;
+        this->maxTimeUntilExplosion_ = 10.0f;
+        this->timeUntilActivation_ = 1.0f;
+
+        //Create movable entities
+        rings1_ = new MovableEntity(this->getContext());
+        this->attach(rings1_);
+        rings1_->setPosition(Vector3(0.0,0.0,0.0));
+        rings1_->setAngularVelocity(Vector3(0.0,5.0,0.0));
+
+        rings2_ = new MovableEntity(this->getContext());
+        this->attach(rings2_);
+        rings2_->setPosition(Vector3(0.0,0.0,0.0));
+        rings2_->setAngularVelocity(Vector3(0.0,0.0,5.0));
+
+        core_ = new MovableEntity(this->getContext());
+        this->attach(core_);
+        core_->setPosition(Vector3(0.0,0.0,0.0));
+        core_->setAngularVelocity(Vector3(2.5,2.5,0.0));
+
+        //Create Models
+        //Core
+        modelCore_ = new Model(this->getContext());
+        modelCore_->setMeshSource("Mine_Core.mesh");
+        modelCore_->setScale(15.0);
+        core_->attach(modelCore_);
+        modelCore_->setPosition(Vector3(0,0,0));
+
+        //Ring 1
+        modelRing1_ = new Model(this->getContext());
+        modelRing1_->setMeshSource("Mine_Ring.mesh");
+        modelRing1_->setScale(15.0);
+        rings1_->attach(modelRing1_);
+        modelRing1_->setPosition(Vector3(0,0,0));
+        modelRing1_->yaw(Degree(0));
+        //Ring 2
+        modelRing2_ = new Model(this->getContext());
+        modelRing2_->setMeshSource("Mine_Ring.mesh");
+        modelRing2_->setScale(15.0);
+        rings1_->attach(modelRing2_);
+        modelRing2_->setPosition(Vector3(0,0,0));
+        modelRing2_->yaw(Degree(180));
+        //Ring 3
+        modelRing3_ = new Model(this->getContext());
+        modelRing3_->setMeshSource("Mine_Ring.mesh");
+        modelRing3_->setScale(15.0);
+        rings2_->attach(modelRing3_);
+        modelRing3_->setPosition(Vector3(0,0,0));
+        modelRing3_->yaw(Degree(90));
+        //Ring 4
+        modelRing4_ = new Model(this->getContext());
+        modelRing4_->setMeshSource("Mine_Ring.mesh");
+        modelRing4_->setScale(15.0);
+        rings2_->attach(modelRing4_);
+        modelRing4_->setPosition(Vector3(0,0,0));
+        modelRing4_->yaw(Degree(270));
+
+        emitter_ = nullptr;
+
+        if (GameMode::isMaster())
+        {
+            this->setMass(10.0f);
+            this->setLinearDamping(0.5f);
+            this->setAngularDamping(0.1f);
+            this->enableCollisionCallback();
+            this->setCollisionResponse(true);
+            this->setCollisionType(CollisionType::Dynamic);
+
+            // Create a sphere collision shape and attach it to the projectile.
+            collisionShape_ = new SphereCollisionShape(this->getContext());
+            collisionShape_->setRadius(collisionShapeRadius_);
+            this->attachCollisionShape(collisionShape_);
+            collisionShape_->setPosition(Vector3(0,0,0));
+
+            // Create a distance trigger and attach it to the projectile.
+            distanceTrigger_ = new DistanceTrigger(this->getContext());
+            this->attach(distanceTrigger_);
+            distanceTrigger_->setPosition(Vector3(0,0,0));
+            distanceTrigger_->setDistance(triggerRadius_);
+            distanceTrigger_->addTarget("Pawn");
+            distanceTrigger_->setStayActive(false);
+
+            this->addEventSource(distanceTrigger_, "explode");
+        }
+    }
+
+    MineProjectile::~MineProjectile()
+    {
+        if (this->isInitialized())
+        {
+            modelCore_->destroy();
+            modelRing1_->destroy();
+            modelRing2_->destroy();
+            modelRing3_->destroy();
+            modelRing4_->destroy();
+
+            if (distanceTrigger_)
+            {
+                distanceTrigger_->destroy();
+            }
+            if (emitter_)
+            {
+                emitter_->destroy();
+            }
+        }
+    }
+
+    /**
+    @brief
+        XMLPort for MineProjectile.
+    */
+    void MineProjectile::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MineProjectile, XMLEventPort, xmlelement, mode);
+        XMLPortEventState(MineProjectile, BaseObject, "explode", explode, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Max Time; after this time runs out,the Mine explodes.
+    */
+    void MineProjectile::setMaxTimeUntilExplosion(float maxTimeUntilExplosion)
+    {
+        if (maxTimeUntilExplosion >= 0)
+        {
+            this->maxTimeUntilExplosion_ = maxTimeUntilExplosion;
+            if (GameMode::isMaster())
+            {
+                this->explodeTimer_.setTimer(this->maxTimeUntilExplosion_, false, createExecutor(createFunctor(&MineProjectile::explode, this)));
+            }
+        }
+        else
+        {
+            this->maxTimeUntilExplosion_ = 0;
+        }
+    }
+
+    /**
+    @brief
+        The mine can only explode when the activation time has run out.
+    */
+    void MineProjectile::setTimeUntilActivation(float timeUntilActivation)
+    {
+        timeUntilActivation_ = timeUntilActivation;
+
+        if (GameMode::isMaster())
+        {
+            this->activationTimer_.setTimer(this->timeUntilActivation_, false, createExecutor(createFunctor(&MineProjectile::allowExplosion, this)));
+        }
+    }
+
+    /**
+    @brief
+        Mine explodes, deals damage to pawn within range and destroys itself.
+    */
+    void MineProjectile::explode()
+    {
+        if (bAllowExplosion_)
+        {
+            if (GameMode::isMaster())
+            {
+                // Damage all pawns within the damage radius
+                for (Pawn* pawn : ObjectList<Pawn>())
+                {
+                    Vector3 distanceVector = pawn->getWorldPosition()-this->getWorldPosition();
+                    if(distanceVector.length()< damageRadius_)
+                    {
+                        pawn->hit(this->getShooter(), pawn->getWorldPosition(), nullptr, this->getDamage(), this->getHealthDamage(), this->getShieldDamage());
+                    }
+                }
+            }
+
+            this->destructionEffect();
+            this->destroyLater();
+        }
+    }
+
+    /**
+    @brief
+        Mine is ready to explode.
+    */
+    void MineProjectile::allowExplosion()
+    {
+        // Allow explosion
+        bAllowExplosion_ = true;
+        // Add particle effect
+        emitter_ = new ParticleEmitter(this->getContext());
+        this->attach(emitter_);
+        emitter_->setOrientation(this->getOrientation());
+        emitter_->setSource("Orxonox/mineparticle");  
+    }
+
+    void MineProjectile::destructionEffect()
+    {
+        ParticleSpawner *effect1, *effect2, *effect3;
+       
+        effect1 = new ParticleSpawner(this->getContext());
+        effect2 = new ParticleSpawner(this->getContext());
+        effect3 = new ParticleSpawner(this->getContext());
+
+        effect1->setPosition(this->getPosition());
+        effect1->setOrientation(this->getOrientation());
+        effect1->setDestroyAfterLife(true);
+        effect1->setSource("Orxonox/MineExpl");
+        effect1->setLifetime(2.5f);
+
+        effect2->setPosition(this->getPosition());
+        effect2->setOrientation(this->getOrientation());
+        effect2->setDestroyAfterLife(true);
+        effect2->setSource("Orxonox/MineExpl1");
+        effect2->setLifetime(2.5f);
+
+        effect3->setPosition(this->getPosition());
+        effect3->setOrientation(this->getOrientation());
+        effect3->setDestroyAfterLife(true);
+        effect3->setSource("Orxonox/MineExpl2");
+        effect3->setLifetime(2.5f);
+
+        // Explosion sound effect.
+        WeakPtr<WorldSound> explosionSound_ = new WorldSound(getContext());
+        explosionSound_->setSource("sounds/minesound.ogg");
+        explosionSound_->setVolume(1.0);
+        explosionSound_->play();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/MineProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/MineProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/MineProjectile.h	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Jannis Holzer
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MineProjectile.h
+    @brief Definition of the MineProjectile class.
+*/
+
+#ifndef _MineProjectile_H__
+#define _MineProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "tools/Timer.h"
+#include "worldentities/MovableEntity.h"
+#include "objects/collisionshapes/SphereCollisionShape.h"
+#include "objects/triggers/DistanceTrigger.h"
+#include "BasicProjectile.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        TODO
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport MineProjectile : public MovableEntity, public BasicProjectile
+    {
+        public:
+            MineProjectile(Context* context);
+            virtual ~MineProjectile();
+
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setMaxTimeUntilExplosion(float maxTimeUntilExplosion);
+            void setTimeUntilActivation(float timeUntilActivation);
+        protected:
+            static const float triggerRadius_;
+            static const float damageRadius_;
+            static const float collisionShapeRadius_;
+        private:
+            bool bAllowExplosion_; // The mine can only explode if it is active
+            float maxTimeUntilExplosion_;
+            float timeUntilActivation_;
+            Timer activationTimer_;
+            Timer explodeTimer_;
+            Model* modelCore_;
+            Model* modelRing1_;
+            Model* modelRing2_;
+            Model* modelRing3_;
+            Model* modelRing4_;
+            MovableEntity* rings1_;
+            MovableEntity* rings2_;
+            MovableEntity* core_;
+            ParticleEmitter* emitter_;
+
+            WeakPtr<SphereCollisionShape> collisionShape_; // The collision shape of the projectile.
+            WeakPtr<DistanceTrigger> distanceTrigger_;
+
+            void destructionEffect();
+            void allowExplosion();
+            void explode();
+    };
+}
+
+#endif /* _MineProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/ParticleProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/ParticleProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/ParticleProjectile.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ParticleProjectile.h
+    @brief Implementation of the ParticleProjectile class.
+*/
+
+#include "ParticleProjectile.h"
+
+#include <OgreParticleEmitter.h>
+#include "core/CoreIncludes.h"
+#include "tools/ParticleInterface.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(ParticleProjectile);
+
+    ParticleProjectile::ParticleProjectile(Context* context) : Projectile(context)
+    {
+        RegisterObject(ParticleProjectile);
+
+        this->particles_ = nullptr;
+
+        //setEffect("Orxonox/sparks2");
+    }
+
+    ParticleProjectile::~ParticleProjectile()
+    {
+        if (this->isInitialized() && this->particles_)
+        {
+            this->detachOgreObject(this->particles_->getParticleSystem());
+            delete this->particles_;
+        }
+    }
+
+    /**
+    @brief
+        Is called when the visibility of the ParticleProjectile has changed.
+    */
+    void ParticleProjectile::changedVisibility()
+    {
+        SUPER(ParticleProjectile, changedVisibility);
+
+        // Change the visibility of the particles.
+        if (this->particles_)
+            this->particles_->setEnabled(this->isVisible());
+    }
+
+    void ParticleProjectile::setEffect(const std::string& effect)
+    {
+        // If we already have a particle interface, delete it
+        if (this->particles_)
+        {
+            this->detachOgreObject(this->particles_->getParticleSystem());
+            delete this->particles_;
+            this->particles_ = nullptr;
+        }
+
+        if (GameMode::showsGraphics())
+        {
+            // Create the particles.
+            this->particles_ = new ParticleInterface(this->getScene()->getSceneManager(), effect, LODParticle::Normal);
+            this->attachOgreObject(this->particles_->getParticleSystem());
+            this->particles_->setKeepParticlesInLocalSpace(0);
+
+            for (unsigned int i = 0; i < this->particles_->getNumEmitters(); ++i)
+                this->particles_->getEmitter(i)->setDirection(-WorldEntity::FRONT);
+        }
+        else
+        {
+            this->particles_ = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/ParticleProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/ParticleProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/ParticleProjectile.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ParticleProjectile.h
+    @brief Definition of the ParticleProjectile class.
+*/
+
+#ifndef _ParticleProjectile_H__
+#define _ParticleProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "BillboardProjectile.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A projectile that is represented by particles.
+    @author
+        Fabian 'x3n' Landau
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport ParticleProjectile : public Projectile
+    {
+        public:
+            ParticleProjectile(Context* context);
+            virtual ~ParticleProjectile();
+            virtual void changedVisibility() override;
+            virtual void setEffect(const std::string& effect);
+
+        private:
+            ParticleInterface* particles_; //!< The particles.
+    };
+}
+
+#endif /* _ParticleProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Projectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Projectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Projectile.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file Projectile.h
+    @brief Implementation of the Projectile class.
+*/
+
+#include "Projectile.h"
+
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/command/Executor.h"
+
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(Projectile);
+
+    Projectile::Projectile(Context* context) : MovableEntity(context), BasicProjectile()
+    {
+        RegisterObject(Projectile);
+
+        this->setConfigValues();
+
+        // Get notification about collisions
+        if (GameMode::isMaster())
+        {
+            this->setMass(0.1f);
+            this->enableCollisionCallback();
+            this->setCollisionResponse(false);
+            this->setCollisionType(CollisionType::Dynamic);
+
+            // Create a sphere collision shape and attach it to the projectile.
+            collisionShape_ = new SphereCollisionShape(this->getContext());
+            setCollisionShapeRadius(20.0f);
+            this->attachCollisionShape(collisionShape_);
+
+            this->destroyTimer_.setTimer(this->lifetime_, false, createExecutor(createFunctor(&BasicProjectile::destroyObject, this)));
+        }
+    }
+
+    Projectile::~Projectile()
+    {
+    }
+
+    void Projectile::setConfigValues()
+    {
+        SetConfigValue(lifetime_, 4.0f).description("The time in seconds a projectile stays alive");
+    }
+
+    void Projectile::tick(float dt)
+    {
+        SUPER(Projectile, tick, dt);
+
+        if (!this->isActive())
+            return;
+
+        this->destroyCheck();
+    }
+
+    bool Projectile::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {
+        return this->processCollision(otherObject, contactPoint, cs);
+    }
+
+    void Projectile::setCollisionShapeRadius(float radius)
+    {
+        if (collisionShape_ != nullptr && radius > 0)
+        {
+            collisionShape_->setRadius(radius);
+        }        
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Projectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Projectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Projectile.h	(revision 11817)
@@ -0,0 +1,79 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file Projectile.h
+    @brief Definition of the Projectile class.
+*/
+
+#ifndef _Projectile_H__
+#define _Projectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+#include "worldentities/MovableEntity.h"
+#include "objects/collisionshapes/SphereCollisionShape.h"
+
+#include "BasicProjectile.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Represents all 'standard' projectiles.
+
+    @author
+        Fabian 'x3n' Landau
+    @author
+        Simon Miescher
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport Projectile : public MovableEntity, public BasicProjectile
+    {
+        public:
+            Projectile(Context* context);
+            virtual ~Projectile();
+
+            void setConfigValues();
+
+            virtual void tick(float dt) override;
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+
+        protected:
+            virtual void setCollisionShapeRadius(float radius);
+            float lifetime_; //!< The time the projectile exists.
+
+        private:
+            Timer destroyTimer_; //!< Timer to destroy the projectile after its lifetime has run out.
+            WeakPtr<SphereCollisionShape> collisionShape_; // The collision shape of the projectile.
+    };
+}
+
+#endif /* _Projectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Rocket.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Rocket.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Rocket.cc	(revision 11817)
@@ -0,0 +1,332 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file Rocket.h
+    @brief Implementation of the Rocket class.
+*/
+
+#include "Rocket.h"
+
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Scene.h"
+#include "controllers/Controller.h"
+#include "graphics/Model.h"
+#include "graphics/ParticleSpawner.h"
+#include "infos/PlayerInfo.h"
+#include "objects/collisionshapes/ConeCollisionShape.h"
+#include "sound/WorldSound.h"
+#include "worldentities/CameraPosition.h"
+#include "worldentities/pawns/Pawn.h"
+//#include "particleuniverse/include/ParticleUniverseSystemManager.h"
+
+namespace orxonox
+{
+    RegisterClass(Rocket);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes some default values.
+    */
+    Rocket::Rocket(Context* context)
+        : ControllableEntity(context)
+        , BasicProjectile()
+        , RadarViewable(this, static_cast<WorldEntity*>(this))
+    {
+        RegisterObject(Rocket);// Register the Rocket class to the core
+
+        this->localAngularVelocity_ = 0;
+        this->lifetime_ = 20.0f;
+
+        if (GameMode::isMaster())
+        {
+            this->setCollisionType(WorldEntity::CollisionType::Kinematic);
+            this->setVelocity(0,0,-100);
+
+            // Create rocket model
+            Model* model = new Model(this->getContext());
+            model->setMeshSource("rocket.mesh");
+            model->scale(1.0f);
+            this->attach(model);
+
+            // Add effects.
+            ParticleEmitter* fire = new ParticleEmitter(this->getContext());
+            this->attach(fire);
+            fire->setOrientation(this->getOrientation());
+            fire->setSource("Orxonox/rocketfire");
+            
+            // Add Particle Universe Effects
+            //ParticleUniverse::ParticleSystemManager* pManager = ParticleUniverse::ParticleSystemManager::getSingletonPtr();
+            //ParticleUniverse::ParticleSystem* pSys1 = pManager->createParticleSystem("pSys1", "bubbles", this->getScene()->getSceneManager());
+            //this->attachOgreObject(pSys1);
+
+            this->enableCollisionCallback();
+            this->setCollisionResponse(false);
+            this->setCollisionType(CollisionType::Kinematic);
+
+            // Add collision shape
+            ConeCollisionShape* collisionShape = new ConeCollisionShape(this->getContext());
+            collisionShape->setRadius(3);
+            collisionShape->setHeight(500);
+            this->attachCollisionShape(collisionShape);
+
+            // Add sound
+            this->defSndWpnEngine_ = new WorldSound(this->getContext());
+            this->defSndWpnEngine_->setLooping(true);
+            this->defSndWpnEngine_->setSource("sounds/Rocket_engine.ogg");
+            this->defSndWpnEngine_->setVolume(1.0f);
+            this->attach(defSndWpnEngine_);
+
+            this->defSndWpnLaunch_ = new WorldSound(this->getContext());
+            this->defSndWpnLaunch_->setLooping(false);
+            this->defSndWpnLaunch_->setSource("sounds/Rocket_launch.ogg");
+            this->defSndWpnLaunch_->setVolume(1.0f);
+            this->attach(defSndWpnLaunch_);
+
+            this->setHudTemplate("rockethud");
+        }
+        else
+        {
+            this->defSndWpnEngine_ = nullptr;
+            this->defSndWpnLaunch_ = nullptr;
+        }
+
+        // Add camera
+        CameraPosition* camPosition = new CameraPosition(this->getContext());
+        camPosition->setPosition(0,4,15);
+        camPosition->setAllowMouseLook(true);
+        this->addCameraPosition(camPosition);
+
+        this->setRadarObjectColour(ColourValue(1.0, 0.5, 0.0)); // orange
+        this->setRadarObjectShape(RadarViewable::Shape::Triangle);
+        this->setRadarObjectScale(0.5f);
+    }
+
+    /**
+    @brief
+        Destructor. Destroys controller, if present and kills sounds, if playing.
+    */
+    Rocket::~Rocket()
+    {
+        if(this->isInitialized())
+        {
+            if (GameMode::isMaster())
+            {
+                this->destructionEffect();
+
+                if (this->getPlayer() && this->getController())
+                    this->player_->stopTemporaryControl();
+            }
+
+            if ( this->defSndWpnEngine_ )
+                this->defSndWpnEngine_->destroy();
+
+            if ( this->defSndWpnLaunch_ )
+                this->defSndWpnLaunch_->destroy();
+        }
+    }
+
+    /**
+    @brief
+        Sets the entity that fired the Rocket.
+    @param shooter
+        A pointer to the Pawn that fired the Rocket.
+    */
+    void Rocket::setShooter(Pawn* shooter)
+    {
+        this->BasicProjectile::setShooter(shooter);
+        
+        this->player_ = this->getShooter()->getPlayer();
+        if(this->player_)
+            this->player_->startTemporaryControl(this);
+
+        if( GameMode::isMaster() )
+        {
+            this->defSndWpnEngine_->play();
+            this->defSndWpnLaunch_->play();
+        }
+    }
+
+    /**
+    @brief
+        Defines which actions the Rocket has to take in each tick.
+    @param dt
+        The length of the tick.
+    */
+    void Rocket::tick(float dt)
+    {
+        SUPER(Rocket, tick, dt);
+
+        if( this->hasLocalController() )
+        {
+            this->setAngularVelocity(this->getOrientation() * this->localAngularVelocity_);
+            this->setVelocity( this->getOrientation()*WorldEntity::FRONT*this->getVelocity().length() );
+            this->localAngularVelocity_ = 0;
+        }
+
+       this->destroyCheck();
+    }
+
+    bool Rocket::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {
+        return this->processCollision(otherObject, contactPoint, cs);
+    }
+
+    /**
+    @brief
+        Destroys the Rocket and stops the sound,
+    */
+    void Rocket::destroyObject(void)
+    {
+        if (GameMode::isMaster() && this->defSndWpnEngine_->isPlaying())
+            this->defSndWpnEngine_->stop();
+
+        this->BasicProjectile::destroyObject();
+    }
+
+    /**
+    @brief
+        Destroys the Rocket upon pressing "fire".
+    */
+    void Rocket::fired(unsigned int firemode)
+    {
+        this->destroyObject();
+    }
+
+    /**
+    @brief
+        The effects that are displayed, when the Rocket is destroyed.
+    */
+    void Rocket::destructionEffect()
+    {
+        ParticleSpawner *effect1, *effect2, *effect3, *effect4, *effect5;
+        if(this->getShooter())
+        {
+            effect1 = new ParticleSpawner(this->getShooter()->getContext());
+            effect2 = new ParticleSpawner(this->getShooter()->getContext());
+            effect3 = new ParticleSpawner(this->getShooter()->getContext());
+            effect4 = new ParticleSpawner(this->getShooter()->getContext());
+            effect5 = new ParticleSpawner(this->getShooter()->getContext());
+        }
+        else
+        {
+            effect1 = new ParticleSpawner(this->getContext());
+            effect2 = new ParticleSpawner(this->getContext());
+            effect3 = new ParticleSpawner(this->getContext());
+            effect4 = new ParticleSpawner(this->getContext());
+            effect5 = new ParticleSpawner(this->getContext());
+        }
+
+        effect1->setPosition(this->getPosition());
+        effect1->setOrientation(this->getOrientation());
+        effect1->setDestroyAfterLife(true);
+        effect1->setSource("orxonox/explosion_flash");
+        effect1->setLifetime(2.0f);
+
+        effect2->setPosition(this->getPosition());
+        effect2->setOrientation(this->getOrientation());
+        effect2->setDestroyAfterLife(true);
+        effect2->setSource("orxonox/explosion_flame");
+        effect2->setLifetime(3.0f);
+
+        effect3->setPosition(this->getPosition());
+        effect3->setOrientation(this->getOrientation());
+        effect3->setDestroyAfterLife(true);
+        effect3->setSource("orxonox/explosion_shockwave");
+        effect3->setLifetime(3.0f);
+
+        effect4->setPosition(this->getPosition());
+        effect4->setOrientation(this->getOrientation());
+        effect4->setDestroyAfterLife(true);
+        effect4->setSource("orxonox/explosion_sparks");
+        effect4->setLifetime(3.0f);
+
+        effect5->setPosition(this->getPosition());
+        effect5->setOrientation(this->getOrientation());
+        effect5->setDestroyAfterLife(true);
+        effect5->setSource("orxonox/explosion_streak1");
+        effect5->setLifetime(3.0f);
+    }
+
+    /**
+    @brief
+        Rotates the Rocket around the y-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void Rocket::rotateYaw(const Vector2& value)
+    {
+        ControllableEntity::rotateYaw(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.y += value.x;
+    }
+
+    /**
+    @brief
+        Rotates the Rocket around the x-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void Rocket::rotatePitch(const Vector2& value)
+    {
+        ControllableEntity::rotatePitch(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.x += value.x;
+    }
+
+    /**
+    @brief
+        Rotates the Rocket around the z-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void Rocket::rotateRoll(const Vector2& value)
+    {
+        ControllableEntity::rotateRoll(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.z += value.x;
+    }
+
+    float Rocket::getFuel() const
+    {
+        return this->destroyTimer_.getRemainingTime();
+    }
+
+    void Rocket::setMaxFuel(float fuel)
+    {
+        this->lifetime_ = fuel;
+        this->destroyTimer_.setTimer(this->lifetime_, false, createExecutor(createFunctor(&BasicProjectile::destroyObject, this)));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Rocket.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Rocket.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/Rocket.h	(revision 11817)
@@ -0,0 +1,145 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file Rocket.h
+    @brief Definition of the Rocket class.
+*/
+
+#ifndef _Rocket_H__
+#define _Rocket_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+
+#include "interfaces/RadarViewable.h"
+#include "worldentities/ControllableEntity.h"
+
+#include "BasicProjectile.h"
+
+namespace orxonox
+{
+    class ConeCollisionShape;
+
+    /**
+    @brief
+        Rocket that can be steered by the player.
+
+    @author
+        Oli Scheuss
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport Rocket : public ControllableEntity, public BasicProjectile, public RadarViewable
+    {
+        public:
+            Rocket(Context* context);
+            virtual ~Rocket();
+
+            virtual void tick(float dt) override; //!< Defines which actions the Rocket has to take in each tick.
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+            virtual void destroyObject(void) override;
+            void destructionEffect();
+
+            virtual void moveFrontBack(const Vector2& value) override {}
+            virtual void moveRightLeft(const Vector2& value) override {}
+            virtual void moveUpDown(const Vector2& value) override {}
+
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+
+            /**
+            @brief Moves the Rocket in the Front/Back-direction by the specifed amount.
+            @param value  The amount by which the Rocket is to be moved.
+            */
+            inline void moveFrontBack(float value)
+                { this->moveFrontBack(Vector2(value, 0)); }
+            /**
+            @brief Moves the Rocket in the Right/Left-direction by the specifed amount.
+            @param value  The amount by which the Rocket is to be moved.
+            */
+            inline void moveRightLeft(float value)
+                { this->moveRightLeft(Vector2(value, 0)); }
+            /**
+            @brief Moves the Rocket in the Up/Down-direction by the specifed amount.
+            @param value  The amount by which the Rocket is to be moved.
+            */
+            inline void moveUpDown(float value)
+                { this->moveUpDown(Vector2(value, 0)); }
+
+            /**
+            @brief Rotates the Rocket around the y-axis by the specifed amount.
+            @param value  The amount by which the Rocket is to be rotated.
+            */
+            inline void rotateYaw(float value)
+                { this->rotateYaw(Vector2(value, 0)); }
+            /**
+            @brief Rotates the Rocket around the x-axis by the specifed amount.
+            @param value  The amount by which the Rocket is to be rotated.
+            */
+            inline void rotatePitch(float value)
+                { this->rotatePitch(Vector2(value, 0)); }
+            /**
+            @brief Rotates the Rocket around the z-axis by the specifed amount.
+            @param value  The amount by which the Rocket is to be rotated.
+            */
+            inline void rotateRoll(float value)
+                { this->rotateRoll(Vector2(value, 0)); }
+
+            virtual void setShooter(Pawn* shooter) override;
+
+            virtual void fired(unsigned int firemode) override;
+
+            /**
+            @brief Set the maximum lifetime of the rocket.
+            */
+            void setMaxFuel(float fuel);
+            /**
+            @brief Get the maximum lifetime of the rocket.
+            */
+            inline float getMaxFuel() const
+                { return lifetime_; }
+            float getFuel() const;
+
+        private:
+            Vector3 localAngularVelocity_; //!< Variable to temporarily store accumulated steering command input.
+
+            WeakPtr<PlayerInfo> player_; //!< The player that controls the Rocket.
+            //WeakPtr<Pawn> pawn_; //!< The pawn that controls the Rocket. TODO
+            Timer destroyTimer_; //!< Timer to destroy the projectile after its lifetime has run out.
+            float lifetime_; //!< The time the projectile exists.
+
+            WorldSound* defSndWpnEngine_; //!< Engine sound.
+            WorldSound* defSndWpnLaunch_; //!< Launch sound.
+    };
+
+}
+
+#endif /* _Rocket_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/RocketOld.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/RocketOld.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/RocketOld.cc	(revision 11817)
@@ -0,0 +1,298 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file RocketOld.h
+    @brief Implementation of the RocketOld class.
+*/
+
+#include "RocketOld.h"
+
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Scene.h"
+#include "controllers/Controller.h"
+#include "graphics/Model.h"
+#include "graphics/ParticleSpawner.h"
+#include "infos/PlayerInfo.h"
+#include "objects/collisionshapes/ConeCollisionShape.h"
+#include "sound/WorldSound.h"
+#include "worldentities/CameraPosition.h"
+#include "worldentities/pawns/Pawn.h"
+//#include "particleuniverse/include/ParticleUniverseSystemManager.h"
+
+namespace orxonox
+{
+    RegisterClass(RocketOld);
+
+    /**
+    @brief
+        Constructor. Registers the object and initializes some default values.
+    */
+    RocketOld::RocketOld(Context* context)
+        : ControllableEntity(context)
+        , BasicProjectile()
+        , RadarViewable(this, static_cast<WorldEntity*>(this))
+    {
+        RegisterObject(RocketOld);// Register the RocketOld class to the core
+
+        this->localAngularVelocity_ = 0;
+        this->lifetime_ = 100.0f;
+
+        if (GameMode::isMaster())
+        {
+            this->setCollisionType(WorldEntity::CollisionType::Kinematic);
+            this->setVelocity(0,0,-100);
+
+            // Create RocketOld model
+            Model* model = new Model(this->getContext());
+            model->setMeshSource("rocket.mesh");
+            model->scale(0.7f);
+            this->attach(model);
+
+            // Add effects.
+            ParticleEmitter* fire = new ParticleEmitter(this->getContext());
+            this->attach(fire);
+            fire->setOrientation(this->getOrientation());
+            fire->setSource("Orxonox/rocketfire");
+            
+            // Add Particle Universe Effects
+            //ParticleUniverse::ParticleSystemManager* pManager = ParticleUniverse::ParticleSystemManager::getSingletonPtr();
+            //ParticleUniverse::ParticleSystem* pSys1 = pManager->createParticleSystem("pSys1", "bubbles", this->getScene()->getSceneManager());
+            //this->attachOgreObject(pSys1);
+
+            this->enableCollisionCallback();
+            this->setCollisionResponse(false);
+            this->setCollisionType(CollisionType::Kinematic);
+
+            // Add collision shape
+            ConeCollisionShape* collisionShape = new ConeCollisionShape(this->getContext());
+            collisionShape->setRadius(3);
+            collisionShape->setHeight(500);
+            this->attachCollisionShape(collisionShape);
+
+            this->destroyTimer_.setTimer(this->lifetime_, false, createExecutor(createFunctor(&BasicProjectile::destroyObject, this)));
+
+            // Add sound
+            this->defSndWpnEngine_ = new WorldSound(this->getContext());
+            this->defSndWpnEngine_->setLooping(true);
+            this->defSndWpnEngine_->setSource("sounds/Rocket_engine.ogg");
+            this->defSndWpnEngine_->setVolume(1.0f);
+            this->attach(defSndWpnEngine_);
+
+            this->defSndWpnLaunch_ = new WorldSound(this->getContext());
+            this->defSndWpnLaunch_->setLooping(false);
+            this->defSndWpnLaunch_->setSource("sounds/Rocket_launch.ogg");
+            this->defSndWpnLaunch_->setVolume(1.0f);
+            this->attach(defSndWpnLaunch_);
+        }
+        else
+        {
+            this->defSndWpnEngine_ = nullptr;
+            this->defSndWpnLaunch_ = nullptr;
+        }
+
+        // Add camera
+        CameraPosition* camPosition = new CameraPosition(this->getContext());
+        camPosition->setPosition(0,4,15);
+        camPosition->setAllowMouseLook(true);
+        this->addCameraPosition(camPosition);
+
+        this->setRadarObjectColour(ColourValue(1.0, 0.5, 0.0)); // orange
+        this->setRadarObjectShape(RadarViewable::Shape::Triangle);
+        this->setRadarObjectScale(0.5f);
+    }
+
+    /**
+    @brief
+        Destructor. Destroys controller, if present and kills sounds, if playing.
+    */
+    RocketOld::~RocketOld()
+    {
+        if(this->isInitialized())
+        {
+            if (GameMode::isMaster())
+            {
+                this->destructionEffect();
+
+                if (this->getPlayer() && this->getController())
+                    this->player_->stopTemporaryControl();
+            }
+
+            if ( this->defSndWpnEngine_ )
+                this->defSndWpnEngine_->destroy();
+
+            if ( this->defSndWpnLaunch_ )
+                this->defSndWpnLaunch_->destroy();
+        }
+    }
+
+    /**
+    @brief
+        Sets the entity that fired the RocketOld.
+    @param shooter
+        A pointer to the Pawn that fired the RocketOld.
+    */
+    void RocketOld::setShooter(Pawn* shooter)
+    {
+        this->BasicProjectile::setShooter(shooter);
+        
+        this->player_ = this->getShooter()->getPlayer();
+        if(this->player_)
+            this->player_->startTemporaryControl(this);
+
+        if( GameMode::isMaster() )
+        {
+            this->defSndWpnEngine_->play();
+            this->defSndWpnLaunch_->play();
+        }
+    }
+
+    /**
+    @brief
+        Defines which actions the RocketOld has to take in each tick.
+    @param dt
+        The length of the tick.
+    */
+    void RocketOld::tick(float dt)
+    {
+        SUPER(RocketOld, tick, dt);
+
+        if( this->hasLocalController() )
+        {
+            this->setAngularVelocity(this->getOrientation() * this->localAngularVelocity_);
+            this->setVelocity( this->getOrientation()*WorldEntity::FRONT*this->getVelocity().length() );
+            this->localAngularVelocity_ = 0;
+        }
+
+       this->destroyCheck();
+    }
+
+    bool RocketOld::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {
+        return this->processCollision(otherObject, contactPoint, cs);
+    }
+
+    /**
+    @brief
+        Destroys the RocketOld and stops the sound,
+    */
+    void RocketOld::destroyObject(void)
+    {
+        if (GameMode::isMaster() && this->defSndWpnEngine_->isPlaying())
+            this->defSndWpnEngine_->stop();
+
+        this->BasicProjectile::destroyObject();
+    }
+
+    /**
+    @brief
+        Destroys the RocketOld upon pressing "fire".
+    */
+    void RocketOld::fired(unsigned int firemode)
+    {
+        this->destroyObject();
+    }
+
+    /**
+    @brief
+        The effects that are displayed, when the RocketOld is destroyed.
+    */
+    void RocketOld::destructionEffect()
+    {
+        ParticleSpawner *effect1, *effect2;
+        if(this->getShooter())
+        {
+            effect1 = new ParticleSpawner(this->getShooter()->getContext());
+            effect2 = new ParticleSpawner(this->getShooter()->getContext());
+        }
+        else
+        {
+            effect1 = new ParticleSpawner(this->getContext());
+            effect2 = new ParticleSpawner(this->getContext());
+        }
+
+        effect1->setPosition(this->getPosition());
+        effect1->setOrientation(this->getOrientation());
+        effect1->setDestroyAfterLife(true);
+        effect1->setSource("Orxonox/explosion4");
+        effect1->setLifetime(2.0f);
+
+        effect2->setPosition(this->getPosition());
+        effect2->setOrientation(this->getOrientation());
+        effect2->setDestroyAfterLife(true);
+        effect2->setSource("Orxonox/smoke4");
+        effect2->setLifetime(3.0f);
+    }
+
+    /**
+    @brief
+        Rotates the RocketOld around the y-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void RocketOld::rotateYaw(const Vector2& value)
+    {
+        ControllableEntity::rotateYaw(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.y += value.x;
+    }
+
+    /**
+    @brief
+        Rotates the RocketOld around the x-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void RocketOld::rotatePitch(const Vector2& value)
+    {
+        ControllableEntity::rotatePitch(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.x += value.x;
+    }
+
+    /**
+    @brief
+        Rotates the RocketOld around the z-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void RocketOld::rotateRoll(const Vector2& value)
+    {
+        ControllableEntity::rotateRoll(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.z += value.x;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/RocketOld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/RocketOld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/RocketOld.h	(revision 11817)
@@ -0,0 +1,134 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file RocketOld.h
+    @brief Definition of the RocketOld class.
+*/
+
+#ifndef _RocketOld_H__
+#define _RocketOld_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+
+#include "interfaces/RadarViewable.h"
+#include "worldentities/ControllableEntity.h"
+
+#include "BasicProjectile.h"
+
+namespace orxonox
+{
+    class ConeCollisionShape;
+
+    /**
+    @brief
+        RocketOld that can be steered by the player.
+
+    @author
+        Oli Scheuss
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport RocketOld : public ControllableEntity, public BasicProjectile, public RadarViewable
+    {
+        public:
+            RocketOld(Context* context);
+            virtual ~RocketOld();
+
+            virtual void tick(float dt) override; //!< Defines which actions the RocketOld has to take in each tick.
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+            virtual void destroyObject(void) override;
+            void destructionEffect();
+
+            virtual void moveFrontBack(const Vector2& value) override {}
+            virtual void moveRightLeft(const Vector2& value) override {}
+            virtual void moveUpDown(const Vector2& value) override {}
+
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+
+            /**
+            @brief Moves the RocketOld in the Front/Back-direction by the specifed amount.
+            @param value  The amount by which the RocketOld is to be moved.
+            */
+            inline void moveFrontBack(float value)
+                { this->moveFrontBack(Vector2(value, 0)); }
+            /**
+            @brief Moves the RocketOld in the Right/Left-direction by the specifed amount.
+            @param value  The amount by which the RocketOld is to be moved.
+            */
+            inline void moveRightLeft(float value)
+                { this->moveRightLeft(Vector2(value, 0)); }
+            /**
+            @brief Moves the RocketOld in the Up/Down-direction by the specifed amount.
+            @param value  The amount by which the RocketOld is to be moved.
+            */
+            inline void moveUpDown(float value)
+                { this->moveUpDown(Vector2(value, 0)); }
+
+            /**
+            @brief Rotates the RocketOld around the y-axis by the specifed amount.
+            @param value  The amount by which the RocketOld is to be rotated.
+            */
+            inline void rotateYaw(float value)
+                { this->rotateYaw(Vector2(value, 0)); }
+            /**
+            @brief Rotates the RocketOld around the x-axis by the specifed amount.
+            @param value  The amount by which the RocketOld is to be rotated.
+            */
+            inline void rotatePitch(float value)
+                { this->rotatePitch(Vector2(value, 0)); }
+            /**
+            @brief Rotates the RocketOld around the z-axis by the specifed amount.
+            @param value  The amount by which the RocketOld is to be rotated.
+            */
+            inline void rotateRoll(float value)
+                { this->rotateRoll(Vector2(value, 0)); }
+
+            virtual void setShooter(Pawn* shooter) override;
+
+            virtual void fired(unsigned int firemode) override;
+
+        private:
+            Vector3 localAngularVelocity_; //!< Variable to temporarily store accumulated steering command input.
+
+            WeakPtr<PlayerInfo> player_; //!< The player that controls the RocketOld.
+            //WeakPtr<Pawn> pawn_; //!< The pawn that controls the RocketOld. TODO
+            Timer destroyTimer_; //!< Timer to destroy the projectile after its lifetime has run out.
+            float lifetime_; //!< The time the projectile exists.
+
+            WorldSound* defSndWpnEngine_; //!< Engine sound.
+            WorldSound* defSndWpnLaunch_; //!< Launch sound.
+    };
+
+}
+
+#endif /* _RocketOld_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SimpleRocket.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SimpleRocket.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SimpleRocket.cc	(revision 11817)
@@ -0,0 +1,222 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gabriel Nadler
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file SimpleRocket.h
+    @brief Implementation of the SimpleRocket class.
+*/
+
+
+#include "SimpleRocket.h"
+
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "controllers/Controller.h"
+#include "graphics/Model.h"
+#include "graphics/ParticleSpawner.h"
+#include "infos/PlayerInfo.h"
+#include "objects/collisionshapes/ConeCollisionShape.h"
+#include "worldentities/pawns/Pawn.h"
+#include "sound/WorldSound.h"
+
+#include "weapons/RocketController.h"
+
+namespace orxonox
+{
+    RegisterClass(SimpleRocket);
+
+    const float SimpleRocket::FUEL_PERCENTAGE = 0.8f;
+
+    SimpleRocket::SimpleRocket(Context* context)
+        : ControllableEntity(context)
+        , BasicProjectile()
+        , RadarViewable(this, static_cast<WorldEntity*>(this))
+    {
+        RegisterObject(SimpleRocket);// Register the SimpleRocket class to the core
+
+        this->localAngularVelocity_ = 0;
+        this->lifetime_ = 10.f;
+
+        this->setMass(15.0);
+
+        if (GameMode::isMaster())
+        {
+            this->setCollisionType(WorldEntity::CollisionType::Kinematic);
+            this->fuel_ = true;
+
+            // Create rocket model.
+            Model* model = new Model(this->getContext());
+            model->setMeshSource("rocket.mesh");
+            model->scale(1.0f);
+            this->attach(model);
+
+            // Add effects.
+            this->fire_ = new ParticleEmitter(this->getContext());
+            this->attach(this->fire_);
+
+            this->fire_->setOrientation(this->getOrientation());
+            this->fire_->setSource("Orxonox/simplerocketfire");
+            this->enableCollisionCallback();
+            this->setCollisionResponse(false);
+            this->setCollisionType(CollisionType::Kinematic);
+
+            // Add collision shape.
+            // TODO: fix the orientation and size of this collision shape to match the rocket
+            ConeCollisionShape* collisionShape = new ConeCollisionShape(this->getContext());
+            collisionShape->setOrientation(this->getOrientation());
+            collisionShape->setRadius(1.5f);
+            collisionShape->setHeight(5);
+            this->attachCollisionShape(collisionShape);
+
+            this->destroyTimer_.setTimer(this->lifetime_, false, createExecutor(createFunctor(&BasicProjectile::destroyObject, this)));
+        }
+
+        this->setRadarObjectColour(ColourValue(1.0, 1.0, 0.0)); // yellow
+        this->setRadarObjectShape(RadarViewable::Shape::Triangle);
+        this->setRadarObjectScale(0.5f);
+    }
+
+
+
+    /**
+    @brief
+        Updates state of rocket, disables fire if no fuel
+    @param dt
+        tick-length
+    */
+    void SimpleRocket::tick(float dt)
+    {
+        SUPER(SimpleRocket, tick, dt);
+
+        if (GameMode::isMaster())
+        {
+            this->setAngularVelocity(this->getOrientation() * this->localAngularVelocity_);
+            this->setVelocity( this->getOrientation()*WorldEntity::FRONT*this->getVelocity().length() );
+            this->localAngularVelocity_ = 0;
+
+            if (this->fuel_)
+            {
+                if (this->destroyTimer_.getRemainingTime() < this->FUEL_PERCENTAGE*this->lifetime_ )
+                    this->fuel_ = false;
+            } else
+                this->disableFire();
+        }
+
+        this->destroyCheck();
+    }
+
+    /**
+    @brief
+        Sets the Acceleration to 0 and detaches the fire.
+    */
+    void SimpleRocket::disableFire()
+    {
+        this->setAcceleration(0,0,0);
+        this->fire_->detachFromParent();
+    }
+
+    /**
+    @brief
+        Destructor. Destroys controller, if present and kills sounds, if playing.
+    */
+    SimpleRocket::~SimpleRocket()
+    {
+        if (this->isInitialized())
+        {
+            if( GameMode::isMaster() )
+            {
+                if (this->getController())
+                    this->getController()->destroy();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Set the entity that fired the SimpleRocket.
+    @param shooter
+        A pointer to the Pawn that fired the SimpleRocket.
+    */
+    void SimpleRocket::setShooter(Pawn* shooter)
+    {
+        BasicProjectile::setShooter(shooter);
+
+        this->player_ = this->getShooter()->getPlayer();
+    }
+
+    bool SimpleRocket::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint)
+    {
+        return this->processCollision(otherObject, contactPoint, cs);
+    }
+
+    /**
+    @brief
+        Rotates the SimpleRocket around the y-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void SimpleRocket::rotateYaw(const Vector2& value)
+    {
+        ControllableEntity::rotateYaw(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.y += value.x;
+    }
+
+    /**
+    @brief
+        Rotates the SimpleRocket around the x-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void SimpleRocket::rotatePitch(const Vector2& value)
+    {
+        ControllableEntity::rotatePitch(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.x += value.x;
+    }
+
+    /**
+    @brief
+        Rotates the SimpleRocket around the z-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void SimpleRocket::rotateRoll(const Vector2& value)
+    {
+        ControllableEntity::rotateRoll(value);
+
+        if( !this->isInMouseLook() )
+            this->localAngularVelocity_.z += value.x;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SimpleRocket.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SimpleRocket.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SimpleRocket.h	(revision 11817)
@@ -0,0 +1,138 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gabriel Nadler
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file SimpleRocket.h
+    @brief Definition of the SimpleRocket class.
+*/
+
+#ifndef _SimpleRocket_H__
+#define _SimpleRocket_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+
+#include "graphics/ParticleSpawner.h"
+#include "interfaces/RadarViewable.h"
+#include "worldentities/ControllableEntity.h"
+
+#include "BasicProjectile.h"
+
+namespace orxonox
+{
+    class ConeCollisionShape;
+
+    /**
+    @brief
+        SimpleRocket is a target seeking, intelligent rocket. It follows its target until it either hits something or runs out of fuel.
+        The steering is done by the RocketController.
+    @author
+       Gabriel Nadler
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport SimpleRocket : public ControllableEntity, public BasicProjectile, public RadarViewable
+    {
+        public:
+            SimpleRocket(Context* context);
+            virtual ~SimpleRocket();
+            virtual void tick(float dt) override;
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+
+            void disableFire(); //!< Method to disable the fire and stop all acceleration
+
+            virtual void moveFrontBack(const Vector2& value) override{}
+            virtual void moveRightLeft(const Vector2& value) override{}
+            virtual void moveUpDown(const Vector2& value) override{}
+
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+            void setDestroy();
+
+            /**
+            @brief Moves the SimpleRocket in the Front/Back-direction by the specifed amount.
+            @param value  The amount by which the SimpleRocket is to be moved.
+            */
+            inline void moveFrontBack(float value)
+                { this->moveFrontBack(Vector2(value, 0)); }
+            /**
+            @brief Moves the SimpleRocket in the Right/Left-direction by the specifed amount.
+            @param value  The amount by which the SimpleRocket is to be moved.
+            */
+            inline void moveRightLeft(float value)
+                { this->moveRightLeft(Vector2(value, 0)); }
+            /**
+            @brief Moves the SimpleRocket in the Up/Down-direction by the specifed amount.
+            @param value  The amount by which the SimpleRocket is to be moved.
+            */
+            inline void moveUpDown(float value)
+                { this->moveUpDown(Vector2(value, 0)); }
+
+            /**
+            @brief Rotates the SimpleRocket around the y-axis by the specifed amount.
+            @param value  The amount by which the SimpleRocket is to be rotated.
+            */
+            inline void rotateYaw(float value)
+                { this->rotateYaw(Vector2(value, 0)); }
+            /**
+            @brief Rotates the SimpleRocket around the x-axis by the specifed amount.
+            @param value  The amount by which the SimpleRocket is to be rotated.
+            */
+            inline void rotatePitch(float value)
+                { this->rotatePitch(Vector2(value, 0)); }
+            /**
+            @brief Rotates the SimpleRocket around the z-axis by the specifed amount.
+            @param value  The amount by which the SimpleRocket is to be rotated.
+            */
+            inline void rotateRoll(float value)
+                { this->rotateRoll(Vector2(value, 0)); }
+
+            virtual void setShooter(Pawn* shooter) override;
+
+            inline bool hasFuel() const
+                { return this->fuel_; }
+
+
+        private:
+            static const float FUEL_PERCENTAGE; //!< Percentage of lifetime the rocket has fuel
+
+            Vector3 localAngularVelocity_; //!< Variable to temporarily store accumulated steering command input.
+            bool fuel_; //!< Bool is true while the rocket "has fuel"
+
+            WeakPtr<PlayerInfo> player_; //!< The player the SimpleRocket belongs to.
+            Timer destroyTimer_; //!< Timer to destroy the projectile after its lifetime has run out.
+            float lifetime_; //!< The time the projectile exists.
+
+            ParticleEmitter* fire_; //!< Fire-Emittor
+    };
+
+}
+
+#endif /* _SimpleRocket_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SplitGunProjectile.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SplitGunProjectile.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SplitGunProjectile.cc	(revision 11817)
@@ -0,0 +1,194 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SplitGunProjectile.h
+    @brief Implementation of the SplitGunProjectile class.
+*/
+
+#include "SplitGunProjectile.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "util/Convert.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    RegisterClass(SplitGunProjectile);
+
+    SplitGunProjectile::SplitGunProjectile(Context* context) : BillboardProjectile(context)
+    {
+        RegisterObject(SplitGunProjectile);
+
+        this->numberOfSplits_ = 0;
+        this->numberOfChilds_ = 0;
+        this->splitTime_ = 1.0f;
+        this->spread_ = 0.2f;
+        this->damageReduction_ = 1.0f;
+        this->splitSound_ = nullptr;
+
+        this->setSplitSound("sounds/Weapon_SplitGun.ogg", 0.8);
+    }
+
+    SplitGunProjectile::~SplitGunProjectile()
+    {
+        if (this->isInitialized())
+        {
+            if (splitSound_)
+            {
+                splitSound_->destroy();
+            }
+        }
+    }
+
+    void SplitGunProjectile::setNumberOfSplits(int numberOfSplits)
+    {
+        if (numberOfSplits >= 0)
+        {
+            this->numberOfSplits_ = numberOfSplits;
+        }
+        else
+        {
+            this->numberOfSplits_ = 0;
+        }
+    }
+
+    void SplitGunProjectile::setNumberOfChilds(int numberOfChilds)
+    {
+        if (numberOfChilds >= 0)
+        {
+            this->numberOfChilds_ = numberOfChilds;
+        }
+        else
+        {
+            this->numberOfChilds_ = 0;
+        }
+    }
+
+    /**
+    @brief
+        This function starts a timer that will cause the projectile to split after a time defined by the argument @p splitTime.
+    @param splitTime The time
+    */
+    void SplitGunProjectile::setSplitTime(float splitTime)
+    {
+        if (splitTime >= 0)
+        {
+            this->splitTime_ = splitTime;
+            this->splitTimer_.setTimer(this->splitTime_, false, createExecutor(createFunctor(&SplitGunProjectile::split, this)));
+        }
+        else
+        {
+            this->splitTime_ = 0;
+        }
+    }
+
+    void SplitGunProjectile::setSpread(float spread)
+    {
+        this->spread_ = spread;
+    }
+
+    /**
+    @brief
+        This is the setter function for the damageReduction_ variable. The value of the variable is bounded between 0 and 1.
+    */
+    void SplitGunProjectile::setDamageReduction(float damageReduction)
+    {
+        this->damageReduction_ = (damageReduction >= 0.0f ? damageReduction : 1.0f);
+    }
+
+    /**
+    @brief
+        If this function is called the projectile splits up into many child projectiles. The original projectiles does not get destroyed but it will never split up again.
+    */
+    void SplitGunProjectile::split()
+    {
+        if (numberOfSplits_ > 0)
+        {
+            -- numberOfSplits_;
+
+            // Reduce damage of this projectile
+            this->setDamage(this->getDamage() * this->damageReduction_ / (this->numberOfChilds_+1));
+
+            // Calculate a normalized vector (velocityOffset) that is perpendicluar to the velocity of this projectile. Since there are infinitly many perpendicular vectors a random one is chosen.
+            Vector3 velocityInitial = this->getVelocity();
+            Vector3 velocityOffset = velocityInitial.perpendicular();
+            velocityOffset.normalise();
+            Degree angle = Degree(rnd(0,360));
+            velocityOffset = Quaternion(angle, velocityInitial.normalisedCopy()) * velocityOffset;
+            velocityOffset.normalise();
+
+            // Create as many childs as defined by numberOfChilds_
+            for (int i = 0; i < numberOfChilds_; ++i)
+            {
+                // Every child projectile should fly uniform in different directions -> Rotate the velocityOffset in every iteration
+                velocityOffset = Quaternion(Degree(360.0f/numberOfChilds_), velocityInitial.normalisedCopy()) * velocityOffset;
+                velocityOffset.normalise();
+
+                SplitGunProjectile* projectile = new SplitGunProjectile(this->getContext());                
+
+                projectile->setMaterial(this->getMaterial());
+                projectile->setOrientation(this->getOrientation());
+                projectile->setPosition(this->getPosition());
+                projectile->setVelocity(velocityInitial + spread_*velocityOffset*velocityInitial.length());
+
+                projectile->setNumberOfSplits(this->numberOfSplits_);
+                projectile->setNumberOfChilds(this->numberOfChilds_);
+                projectile->setSplitTime(this->splitTime_);
+                projectile->setSpread(this->spread_);
+                projectile->setDamageReduction(this->damageReduction_);
+
+                projectile->setShooter(this->getShooter());
+                projectile->setDamage(this->getDamage());
+                projectile->setShieldDamage(this->getShieldDamage());
+                projectile->setHealthDamage(this->getHealthDamage());
+            }
+
+            numberOfSplits_ = 0;
+
+            if (splitSound_)
+            {
+                splitSound_->play();
+            }
+        }
+    }
+
+    void SplitGunProjectile::setSplitSound(const std::string& soundPath, const float soundVolume)
+    {
+        if (!splitSound_)
+        {
+            this->splitSound_ = new WorldSound(this->getContext());
+            this->splitSound_->setLooping(false);
+            this->attach(splitSound_);
+        }
+
+        this->splitSound_->setSource(soundPath);
+        this->splitSound_->setVolume(soundVolume);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SplitGunProjectile.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SplitGunProjectile.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/projectiles/SplitGunProjectile.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SplitGunProjectile.h
+    @brief Definition of the SplitGunProjectile class.
+*/
+
+#ifndef _SplitGunProjectile_H__
+#define _SplitGunProjectile_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include <string>
+#include "tools/Timer.h"
+#include "BillboardProjectile.h"
+#include "sound/WorldSound.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The SplitGunProjectile is a projectile that may split up into many child projectiles.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsProjectiles
+    */
+    class _WeaponsExport SplitGunProjectile : public BillboardProjectile
+    {
+        public:
+            SplitGunProjectile(Context* context);
+            virtual ~SplitGunProjectile();
+
+            virtual void setNumberOfSplits(int numberOfSplits);
+            virtual void setNumberOfChilds(int numberOfChilds);
+            virtual void setSplitTime(float splitTime);
+            virtual void setSpread(float spread);
+            virtual void setDamageReduction(float damageReduction);
+            virtual void setSplitSound(const std::string& soundPath, const float soundVolume = 1.0);
+
+        private:            
+            int numberOfSplits_;
+            int numberOfChilds_;
+            float splitTime_;
+            float spread_;
+            float damageReduction_; //The damage of a child projectile is reduced by this factor
+            Timer splitTimer_;
+            WorldSound* splitSound_; //Sound played if the projectile splits
+
+            virtual void split();            
+    };
+}
+
+#endif /* _SplitGunProjectile_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,15 @@
+ADD_SOURCE_FILES(WEAPONS_SRC_FILES
+  EnergyDrink.cc
+  FusionFire.cc
+  LaserFire.cc
+  HsW01.cc
+  LightningGun.cc
+  SplitGun.cc
+  IceGun.cc
+  FlameGun.cc
+  RocketFire.cc
+  RocketFireOld.cc
+  SimpleRocketFire.cc
+  GravityBombFire.cc
+  MineGun.cc
+)
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/EnergyDrink.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/EnergyDrink.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/EnergyDrink.cc	(revision 11817)
@@ -0,0 +1,155 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Hagen Seifert
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file EnergyDrink.h
+    @brief Implementation of the EnergyDrink class.
+*/
+
+#include "EnergyDrink.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/command/Executor.h"
+
+#include "graphics/Model.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/Projectile.h"
+#include "weapons/MuzzleFlash.h"
+
+namespace orxonox
+{
+    RegisterClass(EnergyDrink);
+
+    EnergyDrink::EnergyDrink(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(EnergyDrink);
+
+        this->reloadTime_ = 0.25f;
+        this->damage_ = 0.0f;
+        this->speed_ = 750.0f;
+        this->delay_ = 0.0f;
+        this->timerStarted_ = false;
+        this->setMunitionName("FusionMunition");
+        this->setFireSound("sounds/Weapon_EnergyDrink.ogg");
+
+        this->delayTimer_.setTimer(1.0f, false, createExecutor(createFunctor(&EnergyDrink::shot, this)));
+        this->delayTimer_.stopTimer();
+
+        hudImageString_ = "Orxonox/WSHUD_WM_EnergyDrink";
+    }
+
+    void EnergyDrink::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EnergyDrink, XMLPort, xmlelement, mode);
+
+        XMLPortParam(EnergyDrink, "delay", setDelay, getDelay, xmlelement, mode);
+        XMLPortParam(EnergyDrink, "material", setMaterial, getMaterial, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Sets the delay with which is fired.
+    @param delay
+        The delay in seconds.
+    */
+    void EnergyDrink::setDelay(float delay)
+    {
+        this->delay_ = delay;
+        this->delayTimer_.setInterval(this->delay_);
+    }
+
+    /**
+    @brief
+        Fires the weapon.
+    */
+    void EnergyDrink::fire()
+    {
+        if (!timerStarted_)
+        {
+            this->delayTimer_.startTimer();
+            this->timerStarted_ = true;
+        }
+    }
+
+    bool EnergyDrink::fire(float* reloadTime)
+    {
+        if (!timerStarted_)
+        {
+            return WeaponMode::fire(reloadTime);
+        }
+
+        return false;
+    }
+
+    /**
+    @brief
+        Executes the shot, be creating the projectile and sending it on its way.
+    */
+    void EnergyDrink::shot()
+    {
+        this->timerStarted_ = false;
+
+        // Create the projectile
+        Projectile* projectile = new Projectile(this->getContext());
+        Model* model = new Model(projectile->getContext());
+        model->setMeshSource("can.mesh");
+        model->setCastShadows(false);
+        projectile->attach(model);
+        model->setScale(5);
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+
+        // Display a muzzle flash.
+        this->muzzleflash();
+    }
+
+    /**
+    @brief
+        Displays a muzzle flash.
+    */
+    void EnergyDrink::muzzleflash()
+    {
+        MuzzleFlash *muzzleFlash = new MuzzleFlash(this->getContext());
+        this->getWeapon()->attach(muzzleFlash);
+        muzzleFlash->setPosition(this->getMuzzleOffset());
+        muzzleFlash->setMaterial(this->material_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/EnergyDrink.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/EnergyDrink.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/EnergyDrink.h	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Hagen Seifert
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file EnergyDrink.h
+    @brief Definition of the EnergyDrink class.
+*/
+
+#ifndef _EnergyDrink_H__
+#define _EnergyDrink_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include <string>
+#include "tools/Timer.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Shoots a can.
+    @author
+        Hagen Seifert
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport EnergyDrink : public WeaponMode
+    {
+        public:
+            EnergyDrink(Context* context);
+            virtual ~EnergyDrink() {}
+
+            virtual bool fire(float* reloadTime) override;
+            virtual void fire() override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        private:
+            /**
+            @brief Set the material of the EnergyDrink.
+            @param material The name of the material.
+            */
+            void setMaterial(const std::string& material)
+                { this->material_ = material; }
+            /**
+            @brief Get the material of the EnergyDrink.
+            @return Returns the material name.
+            */
+            inline const std::string& getMaterial() const
+                { return this->material_; }
+
+            void setDelay(float delay);
+            /**
+            @brief Get the firing delay.
+            @return Returns the delay in seconds.
+            */
+            float getDelay() const
+                { return this->delay_; }
+
+            void shot();
+            void muzzleflash();
+
+            std::string material_; //!< The material.
+            float speed_; //!< The speed of the EnergyDrink.
+            float delay_; //!< The firing delay.
+            Timer delayTimer_; //!< The timer to delay the firing.
+            bool timerStarted_;
+    };
+}
+
+#endif /* _EnergyDrink_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FlameGun.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FlameGun.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FlameGun.cc	(revision 11817)
@@ -0,0 +1,136 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlameGun.cc
+    @brief Implementation of the FlameGun class.
+*/
+
+#include "FlameGun.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/FlameGunProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(FlameGun);
+
+    const int FlameGun::PROJECTILES_PER_FIRE = 3;
+
+    FlameGun::FlameGun(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(FlameGun);
+
+        this->reloadTime_ = 0.1f;
+        this->damage_ = 0.0f;
+        this->speed_ = 550.0f;
+        this->lifetime_ = 1.0;
+        this->sideAcceleration_ = 2000.0;
+
+        this->setMunitionName("FlameMunition");
+        this->setFireSound("sounds/Weapon_FlameGun.ogg");
+
+        hudImageString_ = "Orxonox/WSHUD_WM_FlameGun";
+    }
+
+    FlameGun::~FlameGun()
+    {
+    }
+
+    /**
+    @brief
+        XMLPort for the FlameGun. You can define how often the projectiles Flame, how many childs should be created per Flame, the spread and the time between two Flames.
+    */
+    void FlameGun::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FlameGun, XMLPort, xmlelement, mode);
+
+        XMLPortParam(FlameGun, "Lifetime", setLifetime, getLifetime, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void FlameGun::fire()
+    {
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+
+        Vector3 muzzleDirection = this->getMuzzleDirection();
+        Vector3 directionOffset = muzzleDirection.perpendicular();
+        directionOffset.normalise();
+        Degree angle = Degree(rnd(0,360));
+        directionOffset = Quaternion(angle, muzzleDirection.normalisedCopy()) * directionOffset;
+        directionOffset.normalise();
+
+        FlameGunProjectile* projectile = new FlameGunProjectile(this->getContext());
+
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(muzzleDirection * this->speed_);
+
+        projectile->setLifetime(getLifetime());
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+
+        angle = Degree(360.0/PROJECTILES_PER_FIRE);
+
+        for (int i = 0; i < PROJECTILES_PER_FIRE; ++i)
+        {
+            FlameGunProjectile* projectile = new FlameGunProjectile(this->getContext());
+
+            projectile->setOrientation(this->getMuzzleOrientation());
+            projectile->setPosition(this->getMuzzlePosition());
+            projectile->setVelocity(muzzleDirection * this->speed_);
+            projectile->setAcceleration(directionOffset*sideAcceleration_);
+
+            projectile->setLifetime(getLifetime());
+
+            projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+            projectile->setDamage(this->getDamage());
+            projectile->setShieldDamage(this->getShieldDamage());
+            projectile->setHealthDamage(this->getHealthDamage());
+
+            directionOffset = Quaternion(angle, muzzleDirection.normalisedCopy()) * directionOffset;
+            directionOffset.normalise();
+        }
+
+
+
+        
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FlameGun.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FlameGun.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FlameGun.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FlameGun.h
+    @brief Definition of the FlameGun class.
+*/
+
+#ifndef _FlameGun_H__
+#define _FlameGun_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A WeaponMode that fires burning projectiles.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport FlameGun : public WeaponMode
+    {
+        public:
+            FlameGun(Context* context);
+            virtual ~FlameGun();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void fire() override;
+
+            inline void setLifetime(float lifetime)
+                { this->lifetime_ = lifetime; }
+            inline float getLifetime() const
+                { return this->lifetime_; }
+
+       private:
+            float speed_; //The speed of the fired projectile.
+            float lifetime_; //The lifetime of the fired projectile.
+            float sideAcceleration_;
+
+            static const int PROJECTILES_PER_FIRE;
+    };
+}
+
+#endif /* _FlameGun_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FusionFire.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FusionFire.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FusionFire.cc	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file FusionFire.h
+    @brief Implementation of the FusionFire class.
+*/
+
+#include "FusionFire.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Math.h"
+
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/BillboardProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(FusionFire);
+
+    FusionFire::FusionFire(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(FusionFire);
+
+        this->reloadTime_ = 1.0f;
+        this->bParallelReload_ = false;
+        this->damage_ = 0.0f;
+        this->speed_ = 750.0f;
+
+        this->setMunitionName("FusionMunition");
+        this->setFireSound("sounds/Weapon_FusionFire.ogg");
+
+        hudImageString_ = "Orxonox/WSHUD_WM_FusionFire";
+    }
+
+    /**
+    @brief
+        Fires the weapon, by creating a projectile.
+    */
+    void FusionFire::fire()
+    {
+        BillboardProjectile* projectile = new BillboardProjectile(this->getContext());
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+        projectile->scale(5);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+
+        projectile->setColour(ColourValue(1.0f, 0.7f, 0.3f, 1.0f));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FusionFire.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FusionFire.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/FusionFire.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file FusionFire.h
+    @brief Definition of the FusionFire class.
+*/
+
+#ifndef _FusionFire_H__
+#define _FusionFire_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        FusionFire.
+    @author
+        Martin Polak
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport FusionFire : public WeaponMode
+    {
+        public:
+            FusionFire(Context* context);
+            virtual ~FusionFire() {}
+
+            virtual void fire() override;
+
+        private:
+            float speed_; //!< The speed of the fusion fire weapon.
+    };
+}
+
+#endif /* _FusionFire_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/GravityBombFire.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/GravityBombFire.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/GravityBombFire.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ * GravityBombFire.cc
+ *
+ *  Created on: Apr 16, 2015
+ *      Author: Manuel Eggimann
+ */
+#include "GravityBombFire.h"
+
+#include "core/CoreIncludes.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/GravityBomb.h"
+
+namespace orxonox
+{
+    RegisterClass(GravityBombFire);
+
+    const float GravityBombFire::BOMB_VELOCITY = 600.0; ///< The velocity of the bomb after launch
+
+    GravityBombFire::GravityBombFire(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(GravityBombFire);
+
+        this->reloadTime_ = 0.50f; 
+        this->bParallelReload_ = false;
+        this->damage_ = 20.0f;  ///< The damage of the Bomb if it hits a pawn.
+
+        this->setMunitionName("GravityBombMunition");
+        this->setFireSound("sounds/Rocket_launch.ogg",0.8);    ///< sets sound of the bomb as it is fired.
+
+        hudImageString_ = "Orxonox/WSHUD_WM_GravityBombFire";
+    }
+
+    GravityBombFire::~GravityBombFire(){};
+
+    void GravityBombFire::fire()
+    {
+        GravityBomb* bomb = new GravityBomb(this->getContext());
+        //Create a new Bomb in 3D-Space and set the right direction speed and orientation.
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        bomb->setOrientation(this->getMuzzleOrientation());
+        bomb->setPosition(this->getMuzzlePosition());
+        bomb->setVelocity(this->getMuzzleDirection() * (this->BOMB_VELOCITY+this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getVelocity().length()));
+
+        //Set the shooter of the bomb so it is possible to determine the pawn that killed another one and define damage to shield and healt the bomb does.
+        bomb->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        bomb->setDamage(this->getDamage());
+        bomb->setShieldDamage(this->getShieldDamage());
+        bomb->setHealthDamage(this->getHealthDamage());
+    }
+
+
+}
+
+
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/GravityBombFire.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/GravityBombFire.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/GravityBombFire.h	(revision 11817)
@@ -0,0 +1,43 @@
+/*
+* GravityBombFire.h
+*
+*  Created on: Apr 16, 2015
+*      Author: Manuel Eggimann
+*/
+
+/**
+    @file GravityBombFire.h
+    @brief Definition of the GravityBombFire class.
+*/
+
+#ifndef _GravityBombFire_H__
+#define _GravityBombFire_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    *@brief
+    *   Fires the GravityBomb. This class implements everything needed to fire the BasicProjectile GravityBomb.
+    *   Everything that has to do with the bombs behaviour after launching it is implemented in GravityBomb and GravityBombField.
+    *@author
+    *    Manuel Eggimann
+    *@ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport GravityBombFire : public WeaponMode
+    {
+        public:
+            GravityBombFire(Context* context);
+            virtual ~GravityBombFire();
+
+            virtual void fire() override;
+
+        private:
+            static const float BOMB_VELOCITY; //!< The initial speed of the bomb when it is launched.
+    };
+}
+
+#endif /* _GravityBombFire_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/HsW01.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/HsW01.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/HsW01.cc	(revision 11817)
@@ -0,0 +1,147 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Hagen Seifert
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file HsW01.h
+    @brief Implementation of the HsW01 class.
+*/
+
+#include "HsW01.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/command/Executor.h"
+
+#include "graphics/Model.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/WorldEntity.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/Projectile.h"
+#include "weapons/MuzzleFlash.h"
+
+namespace orxonox
+{
+    RegisterClass(HsW01);
+
+    HsW01::HsW01(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(HsW01);
+
+        this->reloadTime_ = 0.25f;
+        this->damage_ = 0.0f; //default 15
+        this->speed_ = 750.0f;
+        this->delay_ = 0.0f;
+        this->setMunitionName("LaserMunition");
+        this->mesh_ = "laserbeam.mesh";
+
+
+        this->delayTimer_.setTimer(this->delay_, false, createExecutor(createFunctor(&HsW01::shot, this)));
+        this->delayTimer_.stopTimer();
+
+        this->setFireSound("sounds/Weapon_HsW01.ogg");
+        this->setReloadSound("sounds/Reload_HsW01.ogg", 0.5);
+
+        hudImageString_ = "Orxonox/WSHUD_WM_HsW01";
+    }
+
+    HsW01::~HsW01()
+    {
+    }
+
+    void HsW01::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(HsW01, XMLPort, xmlelement, mode);
+
+        XMLPortParam(HsW01, "delay", setDelay, getDelay, xmlelement, mode);
+        XMLPortParam(HsW01, "material", setMaterial, getMaterial, xmlelement, mode);
+        XMLPortParam(HsW01, "projectileMesh", setMesh, getMesh, xmlelement, mode);
+        XMLPortParam(HsW01, "sound", setSound, getSound, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Set the firing delay.
+    @param delay
+        The firing delay in seconds.
+    */
+    void HsW01::setDelay(float delay)
+    {
+        this->delay_ = delay;
+        this->delayTimer_.setInterval(this->delay_);
+    }
+
+    void HsW01::fire()
+    {
+        this->delayTimer_.startTimer();
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void HsW01::shot()
+    {
+        assert( this->getWeapon() && this->getWeapon()->getWeaponPack() && this->getWeapon()->getWeaponPack()->getWeaponSystem() && this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn() );
+
+        // Create the projectile.
+        Projectile* projectile = new Projectile(this->getContext());
+        Model* model = new Model(projectile->getContext());
+        model->setMeshSource(mesh_);
+        model->setCastShadows(false);
+        projectile->attach(model);
+        model->setScale(5);
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+
+        // Display the muzzle flash.
+        this->HsW01::muzzleflash();
+    }
+
+    /**
+    @brief
+        Displays the muzzle flash.
+    */
+    void HsW01::muzzleflash()
+    {
+        MuzzleFlash *muzzleFlash = new MuzzleFlash(this->getContext());
+        this->getWeapon()->attach(muzzleFlash);
+        muzzleFlash->setPosition(this->getMuzzleOffset());
+        muzzleFlash->setMaterial(this->material_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/HsW01.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/HsW01.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/HsW01.h	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Hagen Seifert
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file HsW01.h
+    @brief Definition of the HsW01 class.
+*/
+
+#ifndef _HsW01_H__
+#define _HsW01_H__
+
+#include "weapons/WeaponsPrereqs.h"
+
+#include "tools/Timer.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Shoots laser beams.
+    @author
+        Hagen Seifert
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport HsW01 : public WeaponMode
+    {
+        public:
+            HsW01(Context* context);
+            virtual ~HsW01();
+
+            virtual void fire() override;
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        protected:
+            /**
+            @brief Set the mesh.
+            @param mesh The mesh name.
+            */
+            void setMesh(const std::string& mesh)
+                { this->mesh_ = mesh; }
+
+            /**
+            @brief Get the mesh.
+            @return Returns the mesh name.
+            */
+            const std::string& getMesh() const
+                { return this->mesh_; }
+
+            /**
+            @brief Set the sound.
+            @param sound The Sound name.
+            */
+            void setSound(const std::string& sound)
+                { this->sound_ = sound; }
+
+            /**
+            @brief Get the sound.
+            @return Returns the sound name.
+            */
+            const std::string& getSound() const
+                { return this->sound_; }
+
+            /**
+            @brief Set the material.
+            @param material The material name.
+            */
+            void setMaterial(const std::string& material)
+                { this->material_ = material; }
+            /**
+            @brief Get the material.
+            @return Returns the material name.
+            */
+            const std::string& getMaterial() const
+                { return this->material_; }
+
+            void setDelay(float delay);
+            /**
+            @brief Get the firing delay.
+            @return Returns the firing delay in seconds.
+            */
+            float getDelay() const
+                { return this->delay_; }
+
+            virtual void shot();
+            void muzzleflash();
+
+            std::string material_; //!< The material.
+            std::string mesh_; //!< The mesh.
+            std::string sound_; //!< The sound.
+
+
+
+            float speed_; //!< The speed of the fired projectile.
+            float delay_; //!< The firing delay.
+            Timer delayTimer_; //!< A timer to delay the firing.
+    };
+}
+
+#endif /* _HsW01_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/IceGun.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/IceGun.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/IceGun.cc	(revision 11817)
@@ -0,0 +1,106 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceGun.cc
+    @brief Implementation of the IceGun class.
+*/
+
+#include "IceGun.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"    
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/IceGunProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(IceGun);
+
+    IceGun::IceGun(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(IceGun);
+
+        // Default values
+        this->reloadTime_ = 1.0f;
+        this->damage_ = 0.0f;
+        this->speed_ = 1200.0f;
+
+        this->setFreezeTime(3.0);
+        this->setFreezeFactor(0.5);
+
+        this->setMunitionName("IceMunition");
+        this->setFireSound("sounds/Weapon_LightningGun.ogg");
+        this->setReloadSound("sounds/Reload_IceGun.ogg", 0.4);
+
+        hudImageString_ = "Orxonox/WSHUD_WM_IceGun";
+    }
+
+    IceGun::~IceGun()
+    {
+    }
+
+    /**
+    @brief
+        XMLPort for the IceGun. You can define how often the projectiles split, how many childs should be created per split, the spread and the time between two splits.
+    */
+    void IceGun::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(IceGun, XMLPort, xmlelement, mode);
+
+        XMLPortParam(IceGun, "freezetime", setFreezeTime, getFreezeTime, xmlelement, mode);
+        XMLPortParam(IceGun, "freezefactor", setFreezeFactor, getFreezeFactor, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void IceGun::fire()
+    {
+        IceGunProjectile* projectile = new IceGunProjectile(this->getContext());
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        // Pass important information to the projectile: Freeze time and freeze factor
+        projectile->setFreezeTime(getFreezeTime());
+        projectile->setFreezeFactor(getFreezeFactor());
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/IceGun.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/IceGun.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/IceGun.h	(revision 11817)
@@ -0,0 +1,75 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file IceGun.h
+    @brief Definition of the IceGun class.
+*/
+
+#ifndef _IceGun_H__
+#define _IceGun_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A Gun that fires ice arrows that slow down any SpaceShip object that gets hit.
+    @author
+        Fabien Vultier
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport IceGun : public WeaponMode
+    {
+        public:
+            IceGun(Context* context);
+            virtual ~IceGun();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void fire() override;
+            
+            inline void setFreezeTime(float freezeTime)
+                { this->freezeTime_ = freezeTime; }
+            inline float getFreezeTime() const
+                { return this->freezeTime_; }
+            inline void setFreezeFactor(float freezeFactor)
+                { this->freezeFactor_ = freezeFactor; }
+            inline float getFreezeFactor() const
+                { return this->freezeFactor_; }
+
+       private:
+            float speed_; //The speed of the fired projectile.
+            float freezeTime_; //The duration of the freezing effect on a target
+            float freezeFactor_; //The strength of the freezing effect
+    };
+}
+
+#endif /* _IceGun_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LaserFire.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LaserFire.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LaserFire.cc	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file LaserFire.h
+    @brief Implementation of the LaserFire class.
+*/
+
+#include "LaserFire.h"
+
+#include "core/CoreIncludes.h"
+
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/BillboardProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(LaserFire);
+
+    LaserFire::LaserFire(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(LaserFire);
+
+        this->reloadTime_ = 0.25f;
+        this->damage_ = 0.0f;
+        this->speed_ = 750.0f;
+
+        this->setMunitionName("LaserMunition");
+        this->setFireSound("sounds/Weapon_LaserFire.ogg");
+        this->setReloadSound("sounds/Reload_LaserFire.ogg", 0.8);
+
+        hudImageString_ = "Orxonox/WSHUD_WM_LaserFire";
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void LaserFire::fire()
+    {
+        BillboardProjectile* projectile = new BillboardProjectile(this->getContext());
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LaserFire.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LaserFire.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LaserFire.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LaserFire.h
+    @brief Definition of the LaserFire class.
+*/
+
+#ifndef _LaserFire_H__
+#define _LaserFire_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Shoots a particle laser.
+    @author
+        Martin Polak
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport LaserFire : public WeaponMode
+    {
+        public:
+            LaserFire(Context* context);
+            virtual ~LaserFire() {}
+
+            virtual void fire() override;
+
+        private:
+            float speed_; //!< The speed of the fired projectile.
+    };
+}
+
+#endif /* _LaserFire_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LightningGun.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LightningGun.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LightningGun.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Joel Smely
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file LightningGun.h
+    @brief Implementation of the LightningGun class.
+*/
+
+#include "LightningGun.h"
+
+#include "core/CoreIncludes.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/LightningGunProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(LightningGun);
+
+    LightningGun::LightningGun(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(LightningGun);
+
+        this->reloadTime_ = 1.0f;
+        this->damage_ = 0.0f;
+        this->speed_ = 750.0f;
+
+        this->setMunitionName("LightningMunition");
+        this->setFireSound("sounds/Weapon_LightningGun.ogg");
+
+        hudImageString_ = "Orxonox/WSHUD_WM_LightningGun";
+    }
+
+    LightningGun::~LightningGun()
+    {
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void LightningGun::fire()
+    {
+        LightningGunProjectile* projectile = new LightningGunProjectile(this->getContext());
+        projectile->setMaterial("Flares/LightningBall_");
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LightningGun.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LightningGun.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/LightningGun.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Joel Smely
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LightningGun.h
+    @brief Definition of the LightningGun class.
+*/
+
+#ifndef _LightningGun_H__
+#define _LightningGun_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A slow ball of lightning.
+    @author
+        Joel Smely
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport LightningGun : public WeaponMode
+    {
+        public:
+            LightningGun(Context* context);
+            virtual ~LightningGun();
+
+            virtual void fire() override;
+
+       private:
+            float speed_; //!< The speed of the fired projectile.
+    };
+}
+
+#endif /* _LightningGun_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/MineGun.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/MineGun.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/MineGun.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MineGun.cc
+    @brief Implementation of the MineGun class.
+*/
+
+#include "MineGun.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"    
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/MineProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(MineGun);
+
+    MineGun::MineGun(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(MineGun);
+
+        this->speed_ = 1000.0f;
+        this->reloadTime_ = 1.0f;
+        this->damage_ = 0.0f;
+        this->maxTimeUntilExplosion_ = 0.0f;
+
+        this->setMunitionName("MineMunition");
+        this->setFireSound("sounds/mineactivate.ogg");
+
+        hudImageString_ = "Orxonox/WSHUD_WM_MineGun";
+    }
+
+    MineGun::~MineGun()
+    {
+    }
+
+    /**
+    @brief
+        XMLPort for the MineGun.
+    */
+    void MineGun::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MineGun, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MineGun, "maxtimeuntilexplosion", setMaxTimeUntilExplosion, getMaxTimeUntilExplosion, xmlelement, mode).defaultValues(10.0f);
+        XMLPortParam(MineGun, "timeuntilactivation", setTimeUntilActivation, getTimeUntilActivation, xmlelement, mode).defaultValues(3.0f);
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void MineGun::fire()
+    {
+        MineProjectile* projectile = new MineProjectile(this->getContext());
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        projectile->setMaxTimeUntilExplosion(getMaxTimeUntilExplosion());
+        projectile->setTimeUntilActivation(getTimeUntilActivation());
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/MineGun.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/MineGun.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/MineGun.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *      Jannis Holzer
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file MineGun.h
+    @brief
+
+    Mine is a weapon that explodes if a spaceship goes bellow the mines trigger radius. The mine deals damage too all
+    spaceships within the damageradius.
+
+    The activation time regulates when the mine is live and ready to explode.
+    The mine destroys itself after it exceeds a certain life time.
+*/
+
+#ifndef _MineGun_H__
+#define _MineGun_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A Weapon that drops mines to space.
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport MineGun : public WeaponMode
+    {
+        public:
+            MineGun(Context* context);
+            virtual ~MineGun();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void fire() override;
+
+            inline float getMaxTimeUntilExplosion() const
+                { return this->maxTimeUntilExplosion_; }
+            inline float getTimeUntilActivation() const
+                { return this->timeUntilActivation_; }
+        protected:
+            inline void setMaxTimeUntilExplosion(float maxTimeUntilExplosion)
+                { this->maxTimeUntilExplosion_ = maxTimeUntilExplosion; }
+            inline void setTimeUntilActivation(float timeUntilActivation)
+                { this->timeUntilActivation_ = timeUntilActivation; }
+        private:
+            float speed_; //The speed of the fired projectile.
+            float maxTimeUntilExplosion_;
+            float timeUntilActivation_;
+    };
+}
+
+#endif /* _MineGun_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFire.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFire.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFire.cc	(revision 11817)
@@ -0,0 +1,101 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file RocketFire.h
+    @brief Implementation of the RocketFire class.
+*/
+
+#include "RocketFire.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Math.h"
+
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/XMLPort.h"
+#include "weapons/projectiles/Rocket.h"
+
+namespace orxonox
+{
+    RegisterClass(RocketFire);
+
+    RocketFire::RocketFire(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(RocketFire);
+
+        this->reloadTime_ = 0.20f;
+        this->bParallelReload_ = false;
+        this->damage_ = 0.0f;
+        this->speed_ = 500.0f;
+        this->fuel_ = 10.0f;
+
+        this->setMunitionName("RocketMunition");
+        // The firing sound of the Rocket is played in Rocket.cc (because of OpenAl sound positioning)
+
+        hudImageString_ = "Orxonox/WSHUD_WM_RocketFire";
+    }
+
+    RocketFire::~RocketFire()
+    {
+    }
+
+    /**
+    @brief
+        XMLPort for the RocketFire. You can define the maximum lifetime of the rockets
+    */
+    void RocketFire::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(RocketFire, XMLPort, xmlelement, mode);
+
+        XMLPortParam(RocketFire, "fuel", setFuel, getFuel, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates the Rocket and fires it.
+    */
+    void RocketFire::fire()
+    {
+        Rocket* rocket = new Rocket(this->getContext());
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        rocket->setOrientation(this->getMuzzleOrientation());
+        rocket->setPosition(this->getMuzzlePosition());
+        rocket->setVelocity(this->getMuzzleDirection() * this->speed_);
+        rocket->scale(1.0f);
+
+        rocket->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        rocket->setDamage(this->getDamage());
+        rocket->setShieldDamage(this->getShieldDamage());
+        rocket->setHealthDamage(this->getHealthDamage());
+        rocket->setMaxFuel(this->fuel_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFire.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFire.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFire.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file RocketFire.h
+    @brief Definition of the RocketFire class.
+*/
+
+#ifndef _RocketFire_H__
+#define _RocketFire_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Fires the (steerable) Rocket.
+    @author
+        Oliver Scheuss
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport RocketFire : public WeaponMode
+    {
+        public:
+            RocketFire(Context* context);
+            virtual ~RocketFire();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void fire() override;
+            inline void setFuel(float fuel)
+                { this->fuel_ = fuel; }
+            inline float getFuel() const
+                { return this->fuel_; }
+
+        private:
+            float speed_; //!< The speed of the Rocket.
+            float fuel_; //!< The maximum lifetime of the rocket
+    };
+}
+
+#endif /* _RocketFire_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFireOld.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFireOld.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFireOld.cc	(revision 11817)
@@ -0,0 +1,88 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      simonmie
+ *
+ */
+
+/**
+    @file RocketFire.h
+    @brief Implementation of the RocketFire class.
+*/
+
+#include "RocketFireOld.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Math.h"
+
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/RocketOld.h"
+
+namespace orxonox
+{
+    RegisterClass(RocketFireOld);
+
+    RocketFireOld::RocketFireOld(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(RocketFireOld);
+
+        this->reloadTime_ = 0.20f;
+        this->bParallelReload_ = false;
+        this->damage_ = 0.0f;
+        this->speed_ = 500.0f;
+
+        this->setMunitionName("RocketMunition");
+        // The firing sound of the Rocket is played in Rocket.cc (because of OpenAl sound positioning)
+
+        hudImageString_ = "Orxonox/WSHUD_WM_SimpleRocketFire";
+    }
+
+    RocketFireOld::~RocketFireOld()
+    {
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates the Rocket and fires it.
+    */
+    void RocketFireOld::fire()
+    {
+        RocketOld* rocket = new RocketOld(this->getContext());
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        rocket->setOrientation(this->getMuzzleOrientation());
+        rocket->setPosition(this->getMuzzlePosition());
+        rocket->setVelocity(this->getMuzzleDirection() * this->speed_);
+        rocket->scale(2);
+
+        rocket->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        rocket->setDamage(this->getDamage());
+        rocket->setShieldDamage(this->getShieldDamage());
+        rocket->setHealthDamage(this->getHealthDamage());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFireOld.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFireOld.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/RocketFireOld.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oliver Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file RocketFireOld.h
+    @brief Definition of the RocketFire class.
+*/
+
+#ifndef _RocketFireOld_H__
+#define _RocketFireOld_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Fires the (steerable) RocketOld.
+    @author
+        Oliver Scheuss
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport RocketFireOld : public WeaponMode
+    {
+        public:
+            RocketFireOld(Context* context);
+            virtual ~RocketFireOld();
+
+            virtual void fire() override;
+
+        private:
+            float speed_; //!< The speed of the Rocket.
+    };
+}
+
+#endif /* _RocketFireOld_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SimpleRocketFire.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SimpleRocketFire.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SimpleRocketFire.cc	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gabriel Nadler
+ *   Co-authors:
+ *      Oliver Scheuss
+ *      simonmie
+ *
+ */
+
+/**
+    @file BasicProjectile.h
+    @brief Implementation of the BasicProjectile class.
+*/
+
+#include "SimpleRocketFire.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Math.h"
+
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+#include "sound/WorldSound.h"
+
+#include "weapons/RocketController.h"
+#include "weapons/projectiles/SimpleRocket.h"
+
+namespace orxonox
+{
+
+    RegisterClass(SimpleRocketFire);
+
+    SimpleRocketFire::SimpleRocketFire(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(SimpleRocketFire);
+
+        this->reloadTime_ = 1.0f;
+        this->bParallelReload_ = false;
+        this->damage_ = 0.0f;
+        this->speed_ = 500.0f;
+
+        this->setMunitionName("RocketMunition");
+        this->setFireSound("sounds/Rocket_launch.ogg",0.4f);
+        // The firing sound of the Rocket is played in Rocket.cc (because of OpenAl sound positioning)
+
+        hudImageString_ = "Orxonox/WSHUD_WM_SimpleRocketFire";
+    }
+
+    SimpleRocketFire::~SimpleRocketFire()
+    {
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates the SimpleRocket and a RocketController to steer it and fires it.
+    */
+    void SimpleRocketFire::fire()
+    {
+        RocketController* controller = new RocketController(this->getContext());
+        SimpleRocket* rocket = controller->getRocket();
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        rocket->setOrientation(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getWorldOrientation());
+        rocket->setPosition(this->getMuzzlePosition());
+        rocket->setVelocity(this->getMuzzleDirection()*this->speed_);
+        rocket->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        rocket->scale(1.0f);
+
+        rocket->setDamage(this->damage_);
+        rocket->setShieldDamage(this->getShieldDamage());
+        rocket->setHealthDamage(this->getHealthDamage());
+
+        WorldEntity* pawn = static_cast<ControllableEntity*>(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn())->getTarget();
+        if (pawn)
+            controller->setTarget(pawn);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SimpleRocketFire.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SimpleRocketFire.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SimpleRocketFire.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gabriel Nadler
+ *   Co-authors:
+ *      Oliver Scheuss
+ *
+ */
+
+/**
+    @file SimpleRocketFire.h
+    @brief Definition of the SimpleRocketFire class.
+*/
+
+#ifndef _SimpleRocketFire_H__
+#define _SimpleRocketFire_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        FireMode for target-seeking Rocket
+    @author
+        Gabriel Nadler
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport SimpleRocketFire : public WeaponMode
+    {
+        public:
+            SimpleRocketFire(Context* context);
+            virtual ~SimpleRocketFire();
+            void deactivateFire();
+            virtual void fire() override;
+
+        private:
+            float speed_; //!< The speed of the SimpleRocket.
+
+    };
+}
+
+#endif /* _SimpleRocketFire_H__ */
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SplitGun.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SplitGun.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SplitGun.cc	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SplitGun.cc
+    @brief Implementation of the SplitGun class.
+*/
+
+#include "SplitGun.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "weapons/projectiles/SplitGunProjectile.h"
+
+namespace orxonox
+{
+    RegisterClass(SplitGun);
+
+    SplitGun::SplitGun(Context* context) : WeaponMode(context)
+    {
+        RegisterObject(SplitGun);
+
+        this->reloadTime_ = 1.0f;
+        this->damage_ = 0.0f;
+        this->speed_ = 750.0f;
+        this->numberOfSplits_ = 2;
+        this->numberOfChilds_ = 3;
+        this->splitTime_ = 0.3f;
+        this->spread_ = 0.1f;
+        this->damageReduction_ = 1.0f;
+
+        this->setMunitionName("SplitMunition");
+        this->setFireSound("sounds/Weapon_SplitGun.ogg", 0.5);
+        this->setReloadSound("sounds/Reload_SplitGun.ogg", 0.8);
+
+        hudImageString_ = "Orxonox/WSHUD_WM_SplitGun";
+    }
+
+    SplitGun::~SplitGun()
+    {
+    }
+
+    /**
+    @brief
+        XMLPort for the SplitGun. You can define how often the projectiles split, how many childs should be created per split, the spread and the time between two splits.
+    */
+    void SplitGun::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SplitGun, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SplitGun, "numberofsplits", setNumberOfSplits, getNumberOfSplits, xmlelement, mode);
+        XMLPortParam(SplitGun, "numberofchilds", setNumberOfChilds, getNumberOfChilds, xmlelement, mode);
+        XMLPortParam(SplitGun, "splittime", setSplitTime, getSplitTime, xmlelement, mode);
+        XMLPortParam(SplitGun, "spread", setSpread, getSpread, xmlelement, mode);
+        XMLPortParam(SplitGun, "damagereduction", setDamageReduction, getDamageReduction, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Fires the weapon. Creates a projectile and fires it.
+    */
+    void SplitGun::fire()
+    {
+        SplitGunProjectile* projectile = new SplitGunProjectile(this->getContext());
+        projectile->setMaterial("Flares/energyflare");
+
+        this->computeMuzzleParameters(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn()->getAimPosition());
+        projectile->setOrientation(this->getMuzzleOrientation());
+        projectile->setPosition(this->getMuzzlePosition());
+        projectile->setVelocity(this->getMuzzleDirection() * this->speed_);
+
+        // Pass important information to the projectile: Number of splits, Number of childs, split time, spread and the damage reduction
+        projectile->setNumberOfSplits(getNumberOfSplits());
+        projectile->setNumberOfChilds(getNumberOfChilds());
+        projectile->setSplitTime(getSplitTime());
+        projectile->setSpread(getSpread());
+        projectile->setDamageReduction(getDamageReduction());
+
+        projectile->setShooter(this->getWeapon()->getWeaponPack()->getWeaponSystem()->getPawn());
+        projectile->setDamage(this->getDamage());
+        projectile->setShieldDamage(this->getShieldDamage());
+        projectile->setHealthDamage(this->getHealthDamage());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SplitGun.h
===================================================================
--- /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SplitGun.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/modules/weapons/weaponmodes/SplitGun.h	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabien Vultier
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file SplitGun.h
+    @brief Definition of the SplitGun class.
+*/
+
+#ifndef _SplitGun_H__
+#define _SplitGun_H__
+
+#include "weapons/WeaponsPrereqs.h"
+#include "weaponsystem/WeaponMode.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        A WeaponMode that fires projectiles that may split up into many other projectiles, that may again split up ...
+    @author
+        Fabien Vultier
+    @ingroup WeaponsWeaponModes
+    */
+    class _WeaponsExport SplitGun : public WeaponMode
+    {
+        public:
+            SplitGun(Context* context);
+            virtual ~SplitGun();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void fire() override;
+
+            inline void setNumberOfSplits(int numberOfSplits)
+                { this->numberOfSplits_ = numberOfSplits; }
+            inline int getNumberOfSplits() const
+                { return this->numberOfSplits_; }
+            inline void setNumberOfChilds(int numberOfChilds)
+                { this->numberOfChilds_ = numberOfChilds; }
+            inline int getNumberOfChilds() const
+                { return this->numberOfChilds_; }
+            inline void setSplitTime(float splitTime)
+                { this->splitTime_ = splitTime; }
+            inline float getSplitTime() const
+                { return this->splitTime_; }
+            inline void setSpread(float spread)
+                { this->spread_ = spread; }
+            inline float getSpread() const
+                { return this->spread_; }
+            inline void setDamageReduction(float damageReduction)
+                { this->damageReduction_ = (damageReduction >= 0.0f ? damageReduction : 1.0f); }
+            inline float getDamageReduction() const
+                { return this->damageReduction_; }
+
+       private:
+            float speed_; //The speed of the fired projectile.
+            int numberOfSplits_; //The number of times the projectile will split into child projectiles
+            int numberOfChilds_; //The number of child projectiles that are created if the projectile splits
+            float splitTime_; //The time between creation of the projectile and the split of the projectile
+            float spread_; //Low spread means that the child projectiles are concentrated in a small area
+            float damageReduction_; //The damage of a child projectile is reduced by this factor
+    };
+}
+
+#endif /* _SplitGun_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,89 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+
+INCLUDE_DIRECTORIES(
+  ${CMAKE_SOURCE_DIR}/src/libraries
+  ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+SET_SOURCE_FILES(ORXONOX_SRC_FILES
+  Level.cc
+  LevelInfo.cc
+  LevelManager.cc
+  Highscore.cc
+  Main.cc
+  MoodManager.cc
+  PlayerManager.cc
+  Radar.cc
+#  Test.cc
+
+BUILD_UNIT SceneBuildUnit.cc
+  CameraManager.cc
+  Scene.cc
+  RenderQueueListener.cc
+END_BUILD_UNIT
+)
+
+ADD_SUBDIRECTORY(chat)
+ADD_SUBDIRECTORY(collisionshapes)
+ADD_SUBDIRECTORY(controllers)
+ADD_SUBDIRECTORY(gamestates)
+ADD_SUBDIRECTORY(gametypes)
+ADD_SUBDIRECTORY(graphics)
+ADD_SUBDIRECTORY(infos)
+ADD_SUBDIRECTORY(interfaces)
+ADD_SUBDIRECTORY(items)
+ADD_SUBDIRECTORY(overlays)
+ADD_SUBDIRECTORY(sound)
+ADD_SUBDIRECTORY(weaponsystem)
+ADD_SUBDIRECTORY(worldentities)
+
+ORXONOX_ADD_LIBRARY(orxonox
+  FIND_HEADER_FILES
+  TOLUA_FILES
+    chat/ChatInputHandler.h
+    LevelInfo.h
+    LevelManager.h
+    Highscore.h
+    MoodManager.h
+    controllers/HumanController.h
+    infos/PlayerInfo.h
+    sound/SoundManager.h
+    controllers/ScriptController.h
+  PCH_FILE
+    OrxonoxPrecompiledHeaders.h
+  LINK_LIBRARIES
+    ${OGRE_LIBRARY}
+    ${CEGUI}
+    ${LUA5.1_LIBRARY}
+    ${CEGUI_TOLUA_LIBRARY}
+    ${OPENAL_LIBRARY}
+    ${ALUT_LIBRARY}
+    ${OGG_LIBRARY}
+    ${VORBIS_LIBRARY}
+    ${VORBISFILE_LIBRARY}
+    tinyxml_orxonox
+    bullet_orxonox
+    util
+    core
+    network
+    tools
+  SOURCE_FILES
+    ${ORXONOX_SRC_FILES}
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/CameraManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/CameraManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/CameraManager.cc	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "CameraManager.h"
+
+#include <cassert>
+
+#include <OgreSceneManager.h>
+#include <OgreViewport.h>
+#include <OgreCompositorManager.h>
+
+#include "core/GameMode.h"
+#include "core/GraphicsManager.h"
+#include "core/object/ObjectList.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "tools/Shader.h"
+#include "graphics/Camera.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(CameraManager, ScopeID::GRAPHICS, false);
+
+    CameraManager::CameraManager()
+    {
+        assert(GameMode::showsGraphics());
+    }
+
+    CameraManager::~CameraManager()
+    {
+    }
+
+    Camera* CameraManager::getActiveCamera() const
+    {
+        if (!this->cameraList_.empty())
+            return this->cameraList_.front();
+        else
+            return nullptr;
+    }
+
+    void CameraManager::requestFocus(Camera* camera)
+    {
+        // notify old camera (if it exists)
+        if (!this->cameraList_.empty())
+            this->cameraList_.front()->removeFocus();
+
+        camera->setFocus();
+
+        // make sure we don't add it twice
+        for (std::list<Camera*>::iterator it = this->cameraList_.begin(); it != this->cameraList_.end();)
+            if ((*it) == camera)
+                this->cameraList_.erase(it++);
+            else
+                ++it;
+        // add to list
+        this->cameraList_.push_front(camera);
+    }
+
+    void CameraManager::releaseFocus(Camera* camera)
+    {
+        // notify the cam of releasing the focus
+        if (!this->cameraList_.empty() && this->cameraList_.front() == camera)
+        {
+            camera->removeFocus();
+            this->cameraList_.pop_front();
+
+            // set new focus if possible
+            if (!this->cameraList_.empty())
+                this->cameraList_.front()->setFocus();
+            else
+                this->useCamera(nullptr);
+        }
+        else
+            this->cameraList_.remove(camera);
+    }
+
+    void CameraManager::useCamera(Ogre::Camera* camera)
+    {
+        GraphicsManager::getInstance().setCamera(camera);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/CameraManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/CameraManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/CameraManager.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+ /**
+ @file
+ @brief Handles the instances of Camera class
+ @author Benjamin Knecht <beni_at_orxonox.net>
+  */
+
+#ifndef _CameraManager_H__
+#define _CameraManager_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include "util/OgreForwardRefs.h"
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport CameraManager : public Singleton<CameraManager>
+    {
+            friend class Singleton<CameraManager>;
+        public:
+            CameraManager();
+            ~CameraManager();
+
+            Camera* getActiveCamera() const;
+
+            void requestFocus(Camera* camera);
+            void releaseFocus(Camera* camera);
+
+            void useCamera(Ogre::Camera* camera);
+
+        private:
+            // non-copyable:
+            CameraManager(const CameraManager&) = delete;
+            CameraManager& operator=(const CameraManager&) = delete;
+
+            std::list<Camera*>    cameraList_;
+
+            static CameraManager* singletonPtr_s;
+    };
+}
+
+#endif /* _CameraManager_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/Highscore.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Highscore.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Highscore.cc	(revision 11817)
@@ -0,0 +1,96 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      kappenh
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Highscore.h"
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "infos/PlayerInfo.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(Highscore, ScopeID::ROOT, false);
+    RegisterClassNoArgs(Highscore);
+
+    Highscore::Highscore()
+    {
+        RegisterObject(Highscore);
+        this->setConfigValues();
+    }
+
+    /**
+     * @brief set the config values in the orxonox.ini file
+     */
+    void Highscore::setConfigValues()
+    {
+        SetConfigValue(highscores_, std::vector<std::string>()).description("Highscores saved as vector");
+    }
+
+    /**
+     * @brief Returns highest score of given game, if exists.
+     * Else returns -1.
+     */
+    int Highscore::getHighestScoreOfGame(const std::string& game)
+    {
+        const std::string delimiter = "./."; //score save as "Playername./.game./.score"
+        int best = -1;
+        //check for the highest Score of given game
+        for (std::string score : this->highscores_)
+        {
+            //filter the game string from given highscore
+            score.erase(0, score.find(delimiter) + delimiter.length());
+            if (game.compare(score.substr(0,score.find(delimiter))) == 0)
+            {
+                score.erase(0, score.find(delimiter) + delimiter.length());
+                int possibleBest = multi_cast<int>(score);
+                if (possibleBest > best)
+                    best = possibleBest;
+            }
+        }
+        
+        return best;
+        
+    }
+
+    /**
+     * @brief stores a new highscore in the orxonox.ini file if the new score is better than the highest score so far.
+     * @returns true if the given score marks a new high score
+     */
+    bool Highscore::storeScore(const std::string& level, int points, PlayerInfo* player)
+    {
+        if (points > this->getHighestScoreOfGame(level))
+        {
+            ModifyConfigValue(highscores_, add, player->getName() + "./." + level + "./." + multi_cast<std::string>(points));
+            return true;
+        }
+        else
+            return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/Highscore.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Highscore.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Highscore.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      kappenh
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Highscore_H__
+#define _Highscore_H__
+
+#include <string>
+#include <vector>
+
+#include "OrxonoxPrereqs.h"
+#include "core/config/Configurable.h"
+#include "util/Singleton.h"
+
+// tolua_begin
+namespace orxonox
+{
+    class _OrxonoxExport Highscore
+    // tolua_end
+     : public Singleton<Highscore>, public Configurable
+    { //tolua_export
+        friend class Singleton<Highscore>;
+        public:
+            Highscore();              // Constructor
+            void setConfigValues(); // Inherited function
+
+            bool storeScore(const std::string& level, int points, PlayerInfo* player);
+            int getHighestScoreOfGame(const std::string& game);
+
+            // tolua_begin
+            inline unsigned int getNumberOfHighscores()
+                { return this->highscores_.size(); }
+            inline const std::string& getHighscore(unsigned int index)
+                { return this->highscores_[index]; }
+
+            static Highscore& getInstance()
+                { return Singleton<Highscore>::getInstance(); }
+            // tolua_end
+
+        private:
+            std::vector<std::string> highscores_;
+            static Highscore* singletonPtr_s;
+    }; //tolua_export
+
+} //tolua_export
+
+#endif /* _Highscore_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/Level.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Level.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Level.cc	(revision 11817)
@@ -0,0 +1,212 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Level.h"
+
+#include "util/Math.h"
+#include "util/SubString.h"
+#include "core/CoreIncludes.h"
+#include "core/Loader.h"
+#include "core/Template.h"
+#include "core/XMLFile.h"
+#include "core/XMLPort.h"
+#include "core/module/PluginReference.h"
+
+#include "infos/PlayerInfo.h"
+#include "gametypes/Gametype.h"
+#include "overlays/OverlayGroup.h"
+#include "LevelManager.h"
+
+namespace orxonox
+{
+    RegisterClass(Level);
+
+    Level::Level(Context* context) : BaseObject(context), Synchronisable(context), Context(context)
+    {
+        RegisterObject(Level);
+
+        this->setLevel(WeakPtr<Level>(this)); // store a weak-pointer to itself (a strong-pointer would create a recursive dependency)
+
+        this->registerVariables();
+        this->xmlfilename_ = this->getFilename();
+        this->xmlfile_ = nullptr;
+    }
+
+    Level::~Level()
+    {
+        if (this->isInitialized())
+        {
+            if (LevelManager::exists())
+                LevelManager::getInstance().releaseActivity(this);
+
+            if (this->xmlfile_)
+                Loader::getInstance().unload(this->xmlfile_);
+
+            this->unloadPlugins();
+        }
+    }
+
+    void Level::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Level, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Level, "plugins",  setPluginsString,  getPluginsString,  xmlelement, mode);
+        XMLPortParam(Level, "gametype", setGametypeString, getGametypeString, xmlelement, mode).defaultValues("Gametype");
+
+        XMLPortObject(Level, MeshLodInformation, "lodinformation", addLodInfo, getLodInfo, xmlelement, mode);
+        XMLPortObjectExtended(Level, BaseObject, "", addObject, getObject, xmlelement, mode, true, false);
+    }
+
+    void Level::registerVariables()
+    {
+        registerVariable(this->xmlfilename_,            VariableDirection::ToClient, new NetworkCallback<Level>(this, &Level::networkcallback_applyXMLFile));
+        registerVariable(this->name_,                   VariableDirection::ToClient, new NetworkCallback<Level>(this, &Level::changedName));
+        registerVariable(this->networkTemplateNames_,   VariableDirection::ToClient, new NetworkCallback<Level>(this, &Level::networkCallbackTemplatesChanged));
+    }
+
+    void Level::networkcallback_applyXMLFile()
+    {
+        orxout(user_status) << "Loading level \"" << this->xmlfilename_ << "\"..." << endl;
+
+        ClassTreeMask mask;
+        mask.exclude(Class(BaseObject));
+        mask.include(Class(Template));
+        mask.include(Class(OverlayGroup)); // HACK to include the ChatOverlay
+
+        this->xmlfile_ = new XMLFile(mask, this->xmlfilename_);
+
+        Loader::getInstance().load(this->xmlfile_);
+    }
+
+    void Level::networkCallbackTemplatesChanged()
+    {
+        for(const std::string& name : this->networkTemplateNames_)
+        {
+            assert(Template::getTemplate(name));
+            Template::getTemplate(name)->applyOn(this);
+        }
+    }
+
+    void Level::setPluginsString(const std::string& pluginsString)
+    {
+        // unload old plugins
+        this->unloadPlugins();
+
+        // load new plugins
+        this->pluginsString_ = pluginsString;
+        SubString tokens(pluginsString, ",");
+        for (size_t i = 0; i < tokens.size(); ++i)
+            this->plugins_.push_back(new PluginReference(tokens[i]));
+    }
+
+    void Level::unloadPlugins()
+    {
+        // use destroyLater() - this ensures that plugins are not unloaded too early.
+        // Note: When a level gets unloaded, the Level object is usually the last object that gets destroyed. This is because all other
+        //       objects inside a level have a StrongPtr (in BaseObject) that references the Level object. This means that the Level
+        //       object is only destroyed, when all StrongPtrs that pointed to it were destroyed. But at the time when the last StrongPtr
+        //       is destroyed, the other object is not yet fully destroyed because the StrongPtr is destroyed in ~BaseObject (and this
+        //       means that e.g. ~Identifiable was not yet called for this object). This means that technically there are still other
+        //       objects alive when ~Level is called. This is the reason why we cannot directly destroy() the Plugins - instead we need
+        //       to call destroyLater() to ensure that no instances from this plugin exist anymore.
+        for (PluginReference* plugin : this->plugins_)
+            plugin->destroyLater();
+        this->plugins_.clear();
+    }
+
+    void Level::setGametypeString(const std::string& gametype)
+    {
+        Identifier* identifier = ClassByString(gametype);
+
+        if (!identifier || !identifier->isA(Class(Gametype)))
+        {
+            orxout(internal_error) << "\"" << gametype << "\" is not a valid gametype." << endl;
+            identifier = Class(Gametype);
+            this->gametype_ = "Gametype";
+        }
+        else
+            this->gametype_ = gametype;
+
+        Gametype* rootgametype = orxonox_cast<Gametype*>(identifier->fabricate(this));
+
+        // store a weak-pointer to the gametype to avoid a circular dependency between this level and the gametype (which has a strong-reference on this level)
+        this->setGametype(WeakPtr<Gametype>(rootgametype));
+
+        rootgametype->init(); // call init() AFTER the gametype was set
+
+        if (LevelManager::exists())
+            LevelManager::getInstance().requestActivity(this);
+    }
+
+
+    void Level::addObject(BaseObject* object)
+    {
+        this->objects_.push_back(object);
+    }
+
+    BaseObject* Level::getObject(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (BaseObject* object : this->objects_)
+        {
+            if (i == index)
+                return object;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    void Level::addLodInfo(MeshLodInformation* lodInformation)
+    {
+        std::string meshName = lodInformation->getMeshName();
+//         this->lodInformation_.insert(std::make_pair(meshName,lodInformation));
+        if( this->lodInformation_.find(meshName) != this->lodInformation_.end())
+            orxout(verbose, context::lod) << "replacing lod information for " << meshName << endl;
+        this->lodInformation_[meshName] = lodInformation;
+    }
+
+    MeshLodInformation* Level::getLodInfo(std::string meshName) const
+    {
+        if(this->lodInformation_.find(meshName)!=this->lodInformation_.end())
+            return this->lodInformation_.find(meshName)->second;
+
+        return nullptr;
+    }
+
+    void Level::playerEntered(PlayerInfo* player)
+    {
+        orxout(internal_info) << "player entered level (id: " << player->getClientID() << ", name: " << player->getName() << ')' << endl;
+        player->switchGametype(this->getGametype());
+    }
+
+    void Level::playerLeft(PlayerInfo* player)
+    {
+        orxout(internal_info) << "player left level (id: " << player->getClientID() << ", name: " << player->getName() << ')' << endl;
+        player->switchGametype(nullptr);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/Level.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Level.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Level.h	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Level_H__
+#define _Level_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include <string>
+#include <map>
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+#include "core/object/Context.h"
+#include "graphics/MeshLodInformation.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Level : public BaseObject, public Synchronisable, public Context
+    {
+        public:
+            Level(Context* context);
+            virtual ~Level();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void playerEntered(PlayerInfo* player);
+            void playerLeft(PlayerInfo* player);
+
+            MeshLodInformation* getLodInfo(std::string meshName) const;
+
+
+        private:
+            void registerVariables();
+            void addObject(BaseObject* object);
+            BaseObject* getObject(unsigned int index) const;
+
+            void addLodInfo(MeshLodInformation* object);
+            void networkCallbackTemplatesChanged();
+//            const MeshLodInformation* getLodInfo(std::string meshName) const;
+//            MeshLodInformation* getLodInfo(unsigned int index) const;
+
+            void setPluginsString(const std::string& pluginsString);
+            inline const std::string& getPluginsString() const
+                { return this->pluginsString_; }
+
+            void unloadPlugins();
+
+            void setGametypeString(const std::string& gametype);
+            inline const std::string& getGametypeString() const
+                { return this->gametype_; }
+
+            void networkcallback_applyXMLFile();
+
+            std::string                    pluginsString_;
+            std::list<PluginReference*>    plugins_;
+
+            std::string                    gametype_;
+            std::string                    xmlfilename_;
+            XMLFile*                       xmlfile_;
+            std::list<BaseObject*>         objects_;
+            std::map<std::string,MeshLodInformation*>  lodInformation_;
+    };
+}
+
+#endif /* _Level_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/LevelInfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/LevelInfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/LevelInfo.cc	(revision 11817)
@@ -0,0 +1,294 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LevelInfo.h"
+
+#include <sstream>
+#include <vector>
+
+#include "util/SubString.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "LevelManager.h"
+
+namespace orxonox
+{
+
+    // LevelInfoItem
+
+    //! The list of allowed tags.
+    /*static*/ std::set<std::string> LevelInfoItem::possibleTags_s = std::set<std::string>();
+
+    /**
+    @brief
+        Default constructor.
+    */
+    LevelInfoItem::LevelInfoItem()
+    {
+
+    }
+
+    /**
+    @brief
+        Constructor. Initializes the object.
+    @param name
+        The name of the Level.
+    @param filename
+        The XML-filename of the Level.
+    */
+    LevelInfoItem::LevelInfoItem(const std::string& name, const std::string filename)
+    {
+        this->setName(name);
+        this->setXMLFilename(filename);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    LevelInfoItem::~LevelInfoItem()
+    {
+
+    }
+
+    /**
+    @brief
+        Initialize the set of allowed tags.
+    */
+    /*static*/ void LevelInfoItem::initializeTags(void)
+    {
+        if(!LevelInfoItem::initialized_s)
+        {
+            LevelInfoItem::possibleTags_s.insert("test");
+            LevelInfoItem::possibleTags_s.insert("showcase");
+            LevelInfoItem::possibleTags_s.insert("tutorial");
+            LevelInfoItem::possibleTags_s.insert("presentation");
+            LevelInfoItem::possibleTags_s.insert("mission");
+            LevelInfoItem::possibleTags_s.insert("gametype");
+            LevelInfoItem::possibleTags_s.insert("minigame");
+            LevelInfoItem::possibleTags_s.insert("shipselection");
+        }
+    }
+
+    /**
+    @brief
+        Set the tags the Level is tagged with.
+    @param tags
+        A comma-seperated string of all the tags to be set.
+    */
+    void LevelInfoItem::setTags(const std::string& tags)
+    {
+        SubString substr = SubString(tags, ",", " "); // Split the string into tags.
+        const std::vector<std::string>& tokens = substr.getAllStrings();
+        for (const std::string& token : tokens)
+            this->addTag(token, false);
+
+        this->tagsUpdated();
+    }
+    /**
+    @brief
+        Set the starting ship models of the level
+    @param ships
+        A comma-seperated string of all the allowed ship models for the shipselection.
+    */
+    void LevelInfoItem::setStartingShips(const std::string& ships)
+    {
+        SubString substr = SubString(ships, ",", " "); // Split the string into tags.
+        const std::vector<std::string>& tokens = substr.getAllStrings();
+        for(const std::string& token : tokens)
+            this->addStartingShip(token, false);
+
+        this->startingshipsUpdated();
+    }
+
+    /**
+    @brief
+        Add a tag to the set of tags the Level is tagged with.
+    @param tag
+        The tag to be added.
+    @param update
+        Whether the comma-seperated string of all tags should be updated. Default is true.
+    @return
+        Returns true if the tag was successfully added, if the tag was already present it returns false.
+    */
+    bool LevelInfoItem::addTag(const std::string& tag, bool update)
+    {
+        if(!this->validateTag(tag))
+        {
+            orxout(internal_warning) << "Bad LevelInfo tag '" << tag << "' in " << this->getXMLFilename() << ". Ignoring..." << endl;
+            return false;
+        }
+        bool success = this->tags_.insert(*LevelInfoItem::possibleTags_s.find(tag)).second;
+        if(update && success)
+            this->tagsUpdated();
+        return success;
+    }
+
+    /**
+    @brief
+        Add a ship model to allowed models for the shipselection
+    @param ship
+        The ship model to be added.
+    @param update
+        Whether the comma-seperated string of all ship models should be updated. Default is true.
+    @return
+        Returns true if the ship was successfully added, if the ship was already present it returns false.
+    */
+    bool LevelInfoItem::addStartingShip(const std::string& ship, bool update)
+    {
+        bool success = this->startingShips_.insert(ship).second;
+        if(update && success)
+            this->startingshipsUpdated();
+
+        return success;
+    }
+
+
+    /**
+    @brief
+        Updates the comma-seperated string of all tags, if the set of tags has changed.
+    */
+    void LevelInfoItem::tagsUpdated(void)
+    {
+        std::stringstream stream;
+        std::set<std::string>::iterator temp;
+        for(std::set<std::string>::iterator it = this->tags_.begin(); it != this->tags_.end(); )
+        {
+            temp = it;
+            if(++it == this->tags_.end()) // If this is the last tag we don't add a comma.
+                stream << *temp;
+            else
+                stream << *temp << ", ";
+        }
+
+        this->tagsString_ = std::string(stream.str());
+    }
+
+    /**
+    @brief
+        Updates the comma-seperated string of all ships, if the set of tags has changed.
+    */
+    void LevelInfoItem::startingshipsUpdated(void)
+    {
+        std::stringstream stream;
+        std::set<std::string>::iterator temp;
+        for(std::set<std::string>::iterator it = this->startingShips_.begin(); it != this->startingShips_.end(); )
+        {
+            temp = it;
+            if(++it == this->startingShips_.end()) // If this is the last ship we don't add a comma.
+                stream << *temp;
+            else
+                stream << *temp << ", ";
+        }
+
+        this->startingShipsString_ = std::string(stream.str());
+    }
+
+    void LevelInfoItem::changeStartingShip(const std::string& model)
+    {
+        static std::string shipSelectionTag = "shipselection";
+        //HACK: Read Level XML File, find "shipselection", replace with ship model
+        std::string levelPath = "../levels/";
+        levelPath.append(this->getXMLFilename());
+        std::string tempPath = "../levels/";
+        tempPath.append("_temp.oxw");
+        orxout(user_status) << levelPath << endl;
+        orxout(user_status) << tempPath << endl;
+        std::ifstream myLevel (levelPath.c_str());
+        std::ofstream tempLevel (tempPath.c_str());
+        while(!myLevel.eof())
+        {
+            std::string buff;
+            std::getline(myLevel, buff);
+            std::string pawndesignString = "pawndesign=";
+            size_t found = buff.find(pawndesignString.append(shipSelectionTag));
+            if (found!= std::string::npos)
+                buff = buff.substr(0, found + 11) + model + buff.substr(found+11+shipSelectionTag.length(), std::string::npos);
+            tempLevel.write(buff.c_str(), buff.length());
+            tempLevel << std::endl;
+        }
+        myLevel.close();
+        tempLevel.close();
+        orxout(user_status) << "done" << endl;
+    }
+
+
+    // LevelInfo
+
+    RegisterClass(LevelInfo);
+
+    LevelInfo::LevelInfo(Context* context) : BaseObject(context)
+    {
+        RegisterObject(LevelInfo);
+
+        this->xmlfilename_ = this->getFilename();
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    LevelInfo::~LevelInfo()
+    {
+
+    }
+
+    /**
+    @brief
+        Creates a LevelInfo object through XML.
+    */
+    void LevelInfo::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(LevelInfo, XMLPort, xmlelement, mode);
+
+        XMLPortParam(LevelInfo, "description", setDescription, getDescription, xmlelement, mode);
+        XMLPortParam(LevelInfo, "screenshot", setScreenshot, getScreenshot, xmlelement, mode);
+        XMLPortParam(LevelInfo, "tags", setTags, getTags, xmlelement, mode);
+        XMLPortParam(LevelInfo, "startingships", setStartingShips, getStartingShips, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Copies the contents of this LevelInfo object to a new LevelInfoItem object.
+        This is needed, because a LeveInfo object is only created within the scope of the XML-file it is loaded with and is destroyed once that is unloaded.
+    @return
+        Returns a new LevelInfoItem with the same contents as the LevelInfo object.
+    */
+    LevelInfoItem* LevelInfo::copy(void)
+    {
+        LevelInfoItem* info = new LevelInfoItem(this->BaseObject::getName(), this->getXMLFilename());
+        info->setDescription(this->getDescription());
+        info->setScreenshot(this->getScreenshot());
+        info->setTags(this->getTags());
+        info->setStartingShips(this->getStartingShips());
+        return info;
+    }
+
+}
+
Index: /code/branches/RacingBots_FS18/src/orxonox/LevelInfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/LevelInfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/LevelInfo.h	(revision 11817)
@@ -0,0 +1,280 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file LevelInfo.h
+    @brief Definition of the LevelInfo and LevelInfoItem class.
+    @ingroup Orxonox
+*/
+
+#ifndef _LevelInfo_H__
+#define _LevelInfo_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <set>
+#include <string>
+#include "util/StringUtils.h"
+
+#include "core/BaseObject.h"
+#include <iostream>
+#include <fstream>
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+    /**
+    @brief
+        The LevelInfoItem class stores information regarding a @ref orxonox::Level "Level" and makes that information accessible through the @ref orxonox::LevelManager "LevelManager".
+        A LevelInfoItem object is commonly created from a @ref orxonox::LevelInfo "LevelInfo" object, using its <code>copy()</code> method.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Orxonox
+    */
+    class _OrxonoxExport LevelInfoItem // tolua_export
+        : virtual public OrxonoxInterface
+    { // tolua_export
+        public:
+            LevelInfoItem(); //!< Default constructor.
+            LevelInfoItem(const std::string& name, const std::string filename); //!< Constructor. Initializes the object.
+            virtual ~LevelInfoItem(); //!< Destructor.
+
+            /**
+            @brief Set the name of the Level.
+            @param name The name to be set.
+            */
+            inline void setName(const std::string& name)
+                { this->name_ = std::string(name); }
+            /**
+            @brief Get the name of the Level.
+            @return Returns the name of the Level.
+            */
+            inline const std::string& getName(void) const { return this->name_; } // tolua_export
+
+            /**
+            @brief Set the screenshot of the Level.
+            @param screenshot The screenshot to be set.
+            */
+            inline void setScreenshot(const std::string& screenshot) { this->screenshot_ = std::string(screenshot); }
+            /**
+            @brief Get the screenshot of the Level.
+            @return Returns the screenshot of the Level.
+            */
+            inline const std::string& getScreenshot() const { return this->screenshot_; } // tolua_export
+
+            /**
+            @brief Set the description of the Level.
+            @param description The description to be set.
+            */
+            inline void setDescription(const std::string& description)
+                { this->description_ = std::string(description); }
+            /**
+            @brief Get the description of the Level.
+            @return Returns the description of the Level.
+            */
+            inline const std::string& getDescription() const { return this->description_; } // tolua_export
+
+            void setTags(const std::string& tags); //!< Set the tags the Level is tagged with.
+            bool addTag(const std::string& tag, bool update = true); //!< Add a tag to the set of tags the Level is tagged with.
+            /**
+            @brief Get the lis of the tags the Level is tagged with.
+            @return Returns a comma-seperated string of all the tags the Level is tagged with.
+            */
+            inline const std::string& getTags(void) const
+                { return this->tagsString_; }
+            /**
+            @brief Get whether the Level has a specific tag.
+            @param tag The tag for which is checked.
+            @return Returns true if the Level is tagged with the input tag.
+            */
+            inline bool hasTag(const std::string& tag) const { return this->tags_.find(tag) != this->tags_.end(); } // tolua_export
+
+            void setStartingShips(const std::string& ships); //!< Set the starting ship models of the level
+            bool addStartingShip(const std::string& ship, bool update = true); //!< Add a model to shipselection
+            /**
+            @brief Get the set of starting ship models the Level allows
+            @return Returns a comma-seperated string of all the allowed ship models for the shipselection.
+            */
+            inline const std::string& getStartingShips(void) const
+                { return this->startingShipsString_; }
+            /**
+            @brief Get whether the Level allows a specific starting ship model
+            @param ship The ship model for which is checked.
+            @return Returns true if the Level allows the input ship model
+            */
+            inline bool hasStartingShip(const std::string& ship) const { return this->startingShips_.find(ship) != this->startingShips_.end(); } // tolua_export
+            inline void selectStartingShip(const std::string& ship) { this->changeStartingShip(ship); } // tolua_export
+            /**
+            @brief Get the XML-filename of the Level.
+            @return Returns the XML-filename (including *.oxw extension) of the Level.
+            */
+            inline const std::string& getXMLFilename(void) const { return this->xmlfilename_; } // tolua_export
+
+
+        protected:
+            /**
+            @brief Set the XML-filename of the Level.
+            @param filename The XML-filename to be set.
+            */
+            inline void setXMLFilename(const std::string& filename)
+                { this->xmlfilename_ = std::string(filename); }
+
+            std::string xmlfilename_; //!< The XML-filename of the Level.
+
+        private:
+            void changeStartingShip (const std::string& model);
+            void startingshipsUpdated(void); //!< Updates the comma-seperated string of all possible starting ships.
+            void tagsUpdated(void); //!< Updates the comma-seperated string of all tags, if the set of tags has changed.
+            static void initializeTags(void); //!< Initialize the set of allowed tags.
+            /**
+            @brief Check whether an input tag is allowed.
+            @param tag The tag to check.
+            @return Returns true if the input tag is allowed, false if not.
+            */
+            static bool validateTag(const std::string& tag)
+                { LevelInfoItem::initializeTags(); return LevelInfoItem::possibleTags_s.find(tag) != LevelInfoItem::possibleTags_s.end(); }
+
+            static std::set<std::string> possibleTags_s; //!< The set of allowed tags.
+            static const bool initialized_s = false; //!< Whether the set of allowed tags has been inizialized.
+
+            std::string name_; //!< The name of the Level.
+            std::string description_; //!< The description of the Level.
+            std::string screenshot_; //!< The screenshot of the Level.
+            std::set<std::string> tags_; //!< The set of tags the Level is tagged with.
+            std::string tagsString_; //!< The comma-seperated string of all the tags the Level is tagged with.
+            std::set<std::string> startingShips_; //!< The set of starting ship models the Level allows.
+            std::string startingShipsString_; //!< The comma-seperated string of all the allowed ship models for the shipselection.
+    }; // tolua_export
+
+    /**
+    @brief
+        The LevelInfo class can be used to store information regarding a @ref orxonox::Level "Level" in its level file.
+        The following parameters can be specified:
+        - @b name The name of the level.
+        - @b description The description of the level.
+        - @b screenshot The screenshot of the level.
+        - @b tags A comma-seperated string of tags. Allowed tags are: <em>test</em>, <em>singleplayer</em>, <em>multiplayer</em>, <em>showcase</em>, <em>tutorial</em>, <em>presentation</em>, <em>shipselection</em>.
+        - @b (optional) startingships The comma-seperated string of starting ship models
+        An example would be:
+        @code
+        <LevelInfo
+            name = "Levelname"lhs->compare(rhs) < 0
+            description = "This is just some awesome level."
+            screenshot = "Screenshot.png"
+            tags = "test, awesome"
+        />
+        @endcode
+        The LevelInfo is best located at the top of the level file.
+
+    @author
+        Damian 'Mozork' Frick
+        Matthias Hutter
+    @ingroup Orxonox
+    */
+    class _OrxonoxExport LevelInfo : public BaseObject, public LevelInfoItem
+    {
+        public:
+            LevelInfo(Context* context);
+            virtual ~LevelInfo();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Creates a LevelInfo object through XML.
+
+            /**
+            @brief Set the screenshot of the Level.
+            @param screenshot The screenshot to be set.
+            */
+            inline void setScreenshot(const std::string& screenshot) { this->LevelInfoItem::setScreenshot(screenshot); }
+            /**
+            @brief Get the screenshot of the Level.
+            @return Returns the screenshot of the Level.
+            */
+            inline const std::string& getScreenshot() const { return this->LevelInfoItem::getScreenshot(); }
+
+            /**
+            @brief Set the description of the Level.
+            @param description The description to be set.
+            */
+            inline void setDescription(const std::string& description)
+                { this->LevelInfoItem::setDescription(description); }
+            /**
+            @brief Get the description of the Level.
+            @return Returns the description of the Level.
+            */
+            inline const std::string& getDescription() const
+                { return this->LevelInfoItem::getDescription(); }
+
+            /**
+            @brief Set the tags the Level is tagged with.
+            @param tags A comma-seperated string of all the tags to be set.
+            */
+            inline void setTags(const std::string& tags)
+                { this->LevelInfoItem::setTags(tags); }
+            /**
+            @brief Get the lis of the tags the Level is tagged with.
+            @return Returns a comma-seperated string of all the tags the Level is tagged with.
+            */
+            inline const std::string& getTags(void) const
+                { return this->LevelInfoItem::getTags(); }
+            /**
+            @brief Set the starting ship models of the level
+            @param ships A comma-seperated string of all the allowed ship models for the shipselection.
+            */
+            inline void setStartingShips(const std::string& ships)
+                { this->LevelInfoItem::setStartingShips(ships); }
+            /**
+            @brief Get the starting ship models of the level
+            @return Returns a comma-seperated string of all the allowed ship models for the shipselection.
+            */
+            inline const std::string& getStartingShips(void) const
+                { return this->LevelInfoItem::getStartingShips(); }
+
+            LevelInfoItem* copy(void); //!< Copies the contents of this LevelInfo object to a new LevelInfoItem object.
+    };
+
+    /**
+    @brief
+        Struct that overloads the compare operation between two @ref orxonox::LevelInfoItem "LevelInfoItem" pointers.
+
+    @ingroup Orxonox
+    */
+    struct LevelInfoCompare
+    {
+        bool operator() (const LevelInfoItem* lhs, const LevelInfoItem* rhs) const
+            {
+                if(getLowercase(lhs->getName()).compare(getLowercase(rhs->getName())) == 0)
+                    return getLowercase(lhs->getXMLFilename()).compare(getLowercase(rhs->getXMLFilename())) < 0;
+                return getLowercase(lhs->getName()).compare(getLowercase(rhs->getName())) < 0;
+            }
+    };
+
+} // tolua_export
+
+#endif /* _LevelInfo_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/LevelManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/LevelManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/LevelManager.cc	(revision 11817)
@@ -0,0 +1,319 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file LevelManager.cc
+    @brief Implementation of the LevelManager singleton.
+*/
+
+#include "LevelManager.h"
+
+#include <map>
+
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/commandline/CommandLineIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/ClassTreeMask.h"
+#include "core/Loader.h"
+#include "core/Resource.h"
+#include "core/XMLFile.h"
+#include "Level.h"
+#include "PlayerManager.h"
+
+namespace orxonox
+{
+    SetCommandLineArgument(level, "").shortcut("l").information("Default level file (overrides LevelManager::defaultLevelName_ configValue)");
+
+    ManageScopedSingleton(LevelManager, ScopeID::ROOT, false);
+
+    RegisterAbstractClass(LevelManager).inheritsFrom<Configurable>();
+
+    /**
+    @brief
+        Constructor. Registers the object, sets config values and initializes variables.
+    */
+    LevelManager::LevelManager()
+    {
+        RegisterObject(LevelManager);
+        this->setConfigValues();
+
+        // check override
+        if (!CommandLineParser::getArgument("level")->hasDefaultValue())
+        {
+            ModifyConfigValue(defaultLevelName_, tset, CommandLineParser::getValue("level").get<std::string>());
+        }
+
+        this->compileAvailableLevelList();
+        this->nextIndex_ = 0;
+        this->nextLevel_ = this->availableLevels_.begin();
+    }
+
+    LevelManager::~LevelManager()
+    {
+        // Delete all the LevelInfoItem objects because the LevelManager created them
+        for (LevelInfoItem* info : availableLevels_)
+            info->destroy();
+    }
+
+    /**
+    @brief
+        Set the config values for this object.
+    */
+    void LevelManager::setConfigValues()
+    {
+        SetConfigValue(defaultLevelName_, "missionOne.oxw")
+            .description("Sets the pre selection of the level in the main menu.");
+        SetConfigValue(lastFinishedCampaignMission_,  "")
+            .description("The last finished mission of a campaign");
+        SetConfigValue(campaignMissions_,  std::vector<std::string>())
+            .description("The list of missions in the campaign");
+    }
+
+    /**
+     * @brief Stores the argument in the corresponding config value.
+     */
+    void LevelManager::setLastFinishedCampaignMission(const std::string& lastFinishedCampaignMission)
+    {
+        ModifyConfigValue(lastFinishedCampaignMission_, set, lastFinishedCampaignMission);
+    }
+
+    /**
+    @brief
+        Request activity for the input Level.
+        The Level will be added to the list of Levels whose activity is requested. The list is accessed in a FIFO manner.
+        If the Level is the only Level in the list it will be immediately activated. If not it will be activated as soon as it reaches the front of the list.
+    @param level
+        A pointer to the Level whose activity is requested.
+    */
+    void LevelManager::requestActivity(Level* level)
+    {
+        assert( std::find(this->levels_.begin(), this->levels_.end(), level)==this->levels_.end() );
+        // If the level is already in list.
+        if( std::find(this->levels_.begin(), this->levels_.end(), level)!=this->levels_.end() )
+            return;
+        // If it isn't insert it at the back.
+        this->levels_.push_back(level);
+        // If it is the only level in the list activate it.
+        if (this->levels_.size() == 1)
+            this->activateNextLevel();
+    }
+
+    /**
+    @brief
+        Release activity for the input Level.
+        Removes the Level from the list. If the Level was the one currently active, it is deactivated and the next Level in line is activated.
+    @param level
+        A pointer to the Level whose activity is to be released.
+    */
+    void LevelManager::releaseActivity(Level* level)
+    {
+        if (this->levels_.size() > 0)
+        {
+            // If the level is the active level in the front of the list.
+            if (this->levels_.front() == level)
+            {
+                // Deactivate it, remove it from the list and activate the next level in line.
+                level->setActive(false);
+                this->levels_.pop_front();
+                this->activateNextLevel();
+            }
+            else // Else just remove it from the list.
+                this->levels_.erase(std::find(this->levels_.begin(), this->levels_.end(), level));
+        }
+    }
+
+    /**
+    @brief
+        Get the currently active Level.
+    @return
+        Returns a pointer to the currently active level or nullptr if there currently are no active Levels.
+    */
+    Level* LevelManager::getActiveLevel()
+    {
+        if (this->levels_.size() > 0)
+            return this->levels_.front();
+        else
+            return nullptr;
+    }
+
+    /**
+    @brief
+        Activate the next Level.
+    */
+    void LevelManager::activateNextLevel()
+    {
+        if (this->levels_.size() > 0)
+        {
+            // Activate the level that is the first in the list of levels whose activity has been requested.
+            this->levels_.front()->setActive(true);
+            // Make every player enter the newly activated level.
+            for (const auto& mapEntry : PlayerManager::getInstance().getClients())
+                this->levels_.front()->playerEntered(mapEntry.second);
+        }
+    }
+
+    /**
+    @brief
+        Set the default Level.
+    @param levelName
+        The filename of the default Level.
+    */
+    void LevelManager::setDefaultLevel(const std::string& levelName)
+    {
+        ModifyConfigValue(defaultLevelName_, set, levelName);
+    }
+
+    /**
+    @brief
+        Get the number of available Levels.
+        Also updates the list of available Levels.
+    @return
+        Returns the number of available Levels.
+    */
+    unsigned int LevelManager::getNumberOfLevels()
+    {
+        this->updateAvailableLevelList();
+
+        return this->availableLevels_.size();
+    }
+
+    /**
+    @brief
+        Get the LevelInfoItem at the given index in the list of available Levels.
+        The LevelInfoItems are sorted in alphabetical order accoridng to the name of the Level.
+        This method is most efficiently called with consecutive indices (or at least ascending indices).
+    @param index
+        The index of the item that should be returned.
+    @return
+        Returns a pointer to the LevelInfoItem at the given index.
+    */
+    LevelInfoItem* LevelManager::getAvailableLevelListItem(unsigned int index)
+    {
+        if(index >= this->availableLevels_.size())
+            return nullptr;
+
+        // If this index directly follows the last we can optimize a lot.
+        if(index == this->nextIndex_)
+        {
+            this->nextIndex_++;
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
+            this->nextLevel_++;
+            return *it;
+        }
+        else
+        {
+            // If this index is bigger than the last, we can optimize a little.
+            if(index < this->nextIndex_)
+            {
+                this->nextIndex_ = 0;
+                this->nextLevel_ = this->availableLevels_.begin();
+            }
+
+            while(this->nextIndex_ != index)
+            {
+                this->nextIndex_++;
+                this->nextLevel_++;
+            }
+            this->nextIndex_++;
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator it = this->nextLevel_;
+            this->nextLevel_++;
+            return *it;
+        }
+    }
+
+    /**
+    @brief
+        Compile the list of available Levels.
+        Iterates over all *.oxw files, loads the LevelInfo objects in them and from that it creates the LevelInfoItems which are inserted in a list.
+    */
+    void LevelManager::compileAvailableLevelList()
+    {
+        // Get all files matching the level criteria
+        Ogre::StringVectorPtr levels = Resource::findResourceNames("*.oxw");
+
+        // We only want to load as little as possible
+        ClassTreeMask mask;
+        mask.exclude(Class(BaseObject));
+        mask.include(Class(LevelInfo));
+
+        // Iterate over all the found *.oxw files
+        orxout(internal_info) << "Loading LevelInfos..." << endl;
+        std::set<std::string> names;
+        for (Ogre::StringVector::const_iterator it = levels->begin(); it != levels->end(); ++it)
+        {
+            // TODO: Replace with tag?
+            if (it->find("old/") != 0)
+            {
+                LevelInfoItem* info = nullptr;
+
+                // Load the LevelInfo object from the level file.
+                XMLFile file = XMLFile(*it);
+                Loader::getInstance().load(&file, mask, false, true);
+
+                // Find the LevelInfo object we've just loaded (if there was one)
+                for(LevelInfo* levelInfo : ObjectList<LevelInfo>())
+                    if(levelInfo->getXMLFilename() == *it)
+                        info = levelInfo->copy();
+
+                // We don't need the loaded stuff anymore
+                Loader::getInstance().unload(&file);
+
+                if(info == nullptr)
+                {
+                    // Create a default LevelInfoItem object that merely contains the name
+                    std::string filenameWOExtension = it->substr(0, it->find(".oxw"));
+                    info = new LevelInfoItem(filenameWOExtension, *it);
+                }
+
+                // Warn about levels with the same name.
+                if(!names.insert(info->getName()).second)
+                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with name '" << info->getName() << "' found!" << endl;
+
+                // Warn about multiple items so that it gets fixed quickly
+                if(availableLevels_.find(info) != availableLevels_.end())
+                {
+                    orxout(internal_warning) << "Multiple levels (" << info->getXMLFilename() << ") with same name '" << info->getName() << "' and filename found! Exluding..." << endl;
+                    // Delete LevelInfoItem to avoid a dangling pointer
+                    delete info;
+                }
+                else
+                    this->availableLevels_.insert(info);
+            }
+        }
+    }
+
+    /**
+    @brief
+        Update the list of available Levels.
+    */
+    void LevelManager::updateAvailableLevelList(void)
+    {
+        //TODO: Implement some kind of update?
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/LevelManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/LevelManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/LevelManager.h	(revision 11817)
@@ -0,0 +1,136 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file LevelManager.h
+    @brief Definition of the LevelManager singleton.
+    @ingroup Orxonox
+*/
+
+#ifndef _LevelManager_H__
+#define _LevelManager_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <cassert>
+#include <list>
+#include <map>
+#include <string>
+
+#include "LevelInfo.h"
+
+#include "util/Singleton.h"
+#include "core/config/Configurable.h"
+
+// tolua_begin
+namespace orxonox
+{
+
+    /**
+    @brief
+        The LevelManager keeps track of @ref orxonox::Level "Levels" whose activity has been requested and activates the @ref orxonox::Level "Levels" in the list in a FIFO manner with exactly one Level (the first in the list) being active at all times (unless the list is empty).
+        It also serves as an access point to get a list of all available @ref orxonox::Level "Levels" (or rather their respective @ref orxonox::LevelInfoItem "LevelInfoItems").
+
+    @author
+        Fabian 'x3n' Landau
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Orxonox
+    */
+    class _OrxonoxExport LevelManager
+    // tolua_end
+        : public Singleton<LevelManager>, public Configurable
+    { // tolua_export
+            friend class Singleton<LevelManager>;
+        public:
+            LevelManager();
+            virtual ~LevelManager();
+
+            void setConfigValues(); //!< Set the config values for this object.
+
+            void requestActivity(Level* level); //!< Request activity for the input Level.
+            void releaseActivity(Level* level); //!< Release activity for the input Level.
+            Level* getActiveLevel(); //!< Get the currently active Level.
+
+            // tolua_begin
+            void setDefaultLevel(const std::string& levelName); //!< Set the default Level.
+            /**
+            @brief Get the default level.
+            @return Returns the filename of the default level.
+            */
+            const std::string& getDefaultLevel() const
+                { return defaultLevelName_; }
+            unsigned int getNumberOfLevels(void);
+            LevelInfoItem* getAvailableLevelListItem(unsigned int index); //!< Get the LevelInfoItem at the given index in the list of available Levels.
+
+            void setLastFinishedCampaignMission(const std::string& lastFinishedCampaignMission);
+            inline const std::string& getLastFinishedCampaignMission() const
+                { return this->lastFinishedCampaignMission_; }
+
+            inline unsigned int getNumberOfCampaignMissions()
+                { return this->campaignMissions_.size(); }
+            inline const std::string& getCampaignMission(unsigned int index)
+                { return this->campaignMissions_[index]; }
+
+            /**
+            @brief Get the instance of the LevelManager.
+            @return Returns the instance of the LevelManager.
+            */
+            static LevelManager& getInstance()
+                { return Singleton<LevelManager>::getInstance(); }
+            // tolua_end
+
+        private:
+            // non-copyable:
+            LevelManager(const LevelManager&) = delete;
+            LevelManager& operator=(const LevelManager&) = delete;
+
+            void activateNextLevel(); //!< Activate the next level.
+
+            void compileAvailableLevelList(void); //!< Compile the list of available Levels.
+            void updateAvailableLevelList(void); //!< Update the list of available Levels.
+
+            std::list<Level*> levels_; //!< A list of all the Levels whose activity has been requested, in the order in which they will become active.
+            std::set<LevelInfoItem*, LevelInfoCompare> availableLevels_; //!< The set of available Levels sorted alphabetically according to the name of the Level.
+
+            // Helpers to allow fast access to the availableLevels list.
+            unsigned int nextIndex_; //! The next expected index to be accessed.
+            std::set<LevelInfoItem*, LevelInfoCompare>::iterator nextLevel_; //! The next expected Level to be accessed.
+
+            // config values
+            std::string defaultLevelName_;
+            std::string lastFinishedCampaignMission_;
+            std::vector<std::string> campaignMissions_;
+
+            static LevelManager* singletonPtr_s;
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _LevelManager_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/Main.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Main.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Main.cc	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    The main function of Orxonox (but not the entry point of the program!)
+*/
+
+#include "Main.h"
+
+#include "core/commandline/CommandLineIncludes.h"
+#include "core/Game.h"
+#include "core/LuaState.h"
+
+namespace orxonox
+{
+    SetCommandLineSwitch(console).information("Start in console mode (text IO only)");
+    SetCommandLineSwitch(server).information("Start in server mode");
+    SetCommandLineSwitch(client).information("Start in client mode");
+    SetCommandLineSwitch(dedicated).information("Start in dedicated server mode");
+    SetCommandLineSwitch(standalone).information("Start in standalone mode");
+    SetCommandLineSwitch(dedicatedClient).information("Start in dedicated client mode");
+
+    /* ADD masterserver command */
+    SetCommandLineSwitch(masterserver).information("Start in masterserver mode");
+
+    /**
+    @brief
+        Starting point of orxonox (however not the entry point of the program!)
+    */
+    int main(const std::string& strCmdLine)
+    {
+        orxout(internal_status) << "entering orxonox::main()" << endl;
+        orxout(internal_info) << "command line: " << strCmdLine << endl;
+
+        orxout(internal_info) << "creating Game object:" << endl;
+        Game* game = new Game(strCmdLine);
+        orxout(user_status) << "Finished initialization" << endl;
+
+        if (CommandLineParser::getValue("generateDoc").get<std::string>().empty())
+        {
+            orxout(internal_info) << "preparing game states" << endl;
+
+            /* TODO make this clear */
+            game->setStateHierarchy(
+            "root"
+            " graphics"
+            "  mainMenu"
+            "  standalone,server,client"
+            "   level"
+            " server,client,masterserver"
+            "  level"
+            );
+
+            game->requestState("root");
+
+            // Some development hacks (not really, but in the future, these calls won't make sense anymore)
+            if (CommandLineParser::getValue("standalone").get<bool>())
+                Game::getInstance().requestStates("graphics, standalone, level");
+            else if (CommandLineParser::getValue("server").get<bool>())
+                Game::getInstance().requestStates("graphics, server, level");
+            else if (CommandLineParser::getValue("client").get<bool>())
+                Game::getInstance().requestStates("graphics, client, level");
+            else if (CommandLineParser::getValue("dedicated").get<bool>())
+                Game::getInstance().requestStates("server, level");
+            else if (CommandLineParser::getValue("dedicatedClient").get<bool>())
+                Game::getInstance().requestStates("client, level");
+            /* ADD masterserver command */
+            else if (CommandLineParser::getValue("masterserver").get<bool>())
+                Game::getInstance().requestStates("masterserver");
+            else
+            {
+                if (!CommandLineParser::getValue("console").get<bool>())
+                    Game::getInstance().requestStates("graphics, mainMenu");
+            }
+
+            orxout(internal_info) << "starting game" << endl;
+            game->run();
+        }
+
+        delete game;
+
+        return 0;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/Main.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Main.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Main.h	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin Knecht <beni_at_orxonox.net>, (C) 2007
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Main_H__
+#define _Main_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+
+namespace orxonox
+{
+    _OrxonoxExport int main(const std::string& strCmdLine);
+}
+
+#endif /* _Main_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/MoodManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/MoodManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/MoodManager.cc	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin 'youngk' Young
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MoodManager.h"
+
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/Resource.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(MoodManager, ScopeID::ROOT, false);
+
+    // Note: I'm (Kevin Young) not entirely sure whether that's good code style:
+    const std::string MoodManager::defaultMood_ = "default";
+
+    RegisterAbstractClass(MoodListener).inheritsFrom<OrxonoxInterface>();
+    RegisterAbstractClass(MoodManager).inheritsFrom<Configurable>();
+
+    MoodManager::MoodManager()
+    {
+        RegisterObject(MoodManager);
+        this->setConfigValues();
+
+        // Need to use a variable to store old data because ResetConfigValues() doesn't seem to work.
+        oldMood_ = MoodManager::defaultMood_;
+
+        // Checking for the existence of the folder for the default mood
+        const std::string& path = "ambient/" + MoodManager::defaultMood_ + "/.";
+        if (!Resource::exists(path))
+        {
+            // TODO: Non-fatal error handling (non-critical resource missing)
+            orxout(internal_warning) << "Mood Warning: Folder for default mood (" << MoodManager::defaultMood_ << ") does not exist!" << endl;
+        }
+        
+        // @TODO
+        // Creating a vector of the available moods to enable easy mood selection by Lua/CEGUI        
+    }
+
+    void MoodManager::setConfigValues()
+    {
+        SetConfigValue(mood_, MoodManager::defaultMood_)
+            .description("Sets the mood for the current level.")
+            .callback(this, &MoodManager::checkMoodValidity);
+    }
+
+    /** Set a new mood
+     */
+    void MoodManager::setMood(const std::string& mood)
+    {
+        oldMood_ = mood_;
+        ModifyConfigValue(mood_, set, mood);
+    }
+
+    void MoodManager::checkMoodValidity()
+    {
+        //  Generic mood validation
+        const std::string& path = "ambient/" + mood_ + "/.";
+        if (!Resource::exists(path))
+        {
+            orxout(internal_warning) << "Mood " << mood_ << " does not exist. Will not change." << endl;
+            this->setMood(oldMood_);
+        }
+        else
+        {
+            orxout(internal_info) << "Mood changed to " << mood_ << endl;
+            MoodListener::changedMood(mood_);
+        }
+    }
+
+
+    MoodListener::MoodListener()
+    {
+        RegisterObject(MoodListener);
+    }
+
+    /*static*/ void MoodListener::changedMood(const std::string& mood)
+    {
+        for (MoodListener* listener : ObjectList<MoodListener>())
+            listener->moodChanged(mood);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/MoodManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/MoodManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/MoodManager.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Kevin 'youngk' Young
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MoodManager_H__
+#define _MoodManager_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "util/Singleton.h"
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    /*
+    @brief
+        The MoodListener class is aware of a change in themes and directs that info to dependent classes.
+    */
+    class _OrxonoxExport MoodListener : virtual public OrxonoxInterface
+    {
+        friend class MoodManager;
+
+        protected:
+            MoodListener();
+            virtual ~MoodListener() {}
+
+        private:
+            virtual bool moodChanged(const std::string& mood) = 0;
+
+            static void changedMood(const std::string& mood);
+    };
+
+    /*
+    @brief
+        The MoodManager class serves to allow for different musical themes in the game.
+    */
+    class _OrxonoxExport MoodManager : public Singleton<MoodManager>, public Configurable
+    {
+            friend class Singleton<MoodManager>;
+        public:
+            MoodManager();
+
+            void setConfigValues();
+
+            void setMood(const std::string& mood);
+            inline const std::string& getMood() const { return this->mood_; }
+
+            static MoodManager& getInstance() { return Singleton<MoodManager>::getInstance(); }
+
+        private:
+            void checkMoodValidity();
+
+            // config values
+            std::string mood_;
+            std::string oldMood_;
+            static const std::string defaultMood_;
+
+            static MoodManager* singletonPtr_s;
+    };
+}
+
+#endif /* _MoodManager_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/OrxonoxPrecompiledHeaders.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/OrxonoxPrecompiledHeaders.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/OrxonoxPrecompiledHeaders.h	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compilation of the most often used header files in the orxonox library
+@details
+    Updated: 13. September 2009
+    Total Files: 88
+*/
+
+#include "OrxonoxConfig.h"
+
+///////////////////////////////////////////
+/////          Stable Headers         /////
+///////////////////////////////////////////
+
+#include <cassert>  // 87
+#include <cstring>  // 87
+#include <fstream>  // 87
+#include <iostream> // 87
+#include <map>      // 87
+#include <set>      // 87
+#include <sstream>  // 87
+#include <string>   // 87
+#include <vector>   // 87
+#include <list>     // 86
+#include <ctime>    // 82
+#include <cmath>    // 81
+#include <deque>    // 81
+#include <queue>    // 81
+
+#include <OgreMath.h>        // 81
+#include <OgreVector2.h>     // 81
+#include <OgreVector3.h>     // 81
+#include <OgreVector4.h>     // 81
+#include <OgreQuaternion.h>  // 81
+#include <OgreColourValue.h> // 81
+
+#include "util/OgreForwardRefs.h"     // 67
+#include <LinearMath/btMotionState.h> // 60
+#include "util/SubString.h" // 55
+#include <tinyxml/ticpp.h>  // 41
+
+//#include <OgreRenderable.h> // 14, 5.1MB
+//#include <OgreSceneNode.h>  // 13, 1MB
+//#include <OgreResourceGroupManager.h> // 12, 1.5MB
+//#include <OgreTexture.h>       // 11, 0.6MB
+//#include <OgreMovableObject.h> // 10, 1.6MB
+//#include <OgreSceneManager.h>  // 9, 8.7MB
+
+///////////////////////////////////////////
+/////       All Rebuild Headers       /////
+///////////////////////////////////////////
+
+#include "core/BaseObject.h"   // 82
+#include "core/CoreIncludes.h" // 80
+
+///////////////////////////////////////////
+/////      Not so Stable Headers      /////
+///////////////////////////////////////////
+
+#include "network/synchronisable/Synchronisable.h" // 70
+#include "util/MultiType.h"    // 65
+#include "core/command/Executor.h"     // 55
+//#include "core/XMLPort.h"     // 41
+
+
+// Just in case some header included windows.h
+#undef min
+#undef max
Index: /code/branches/RacingBots_FS18/src/orxonox/OrxonoxPrereqs.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/OrxonoxPrereqs.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/OrxonoxPrereqs.h	(revision 11817)
@@ -0,0 +1,226 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Shared library macros, enums, constants and forward declarations for the orxonox library
+*/
+
+#ifndef _OrxonoxPrereqs_H__
+#define _OrxonoxPrereqs_H__
+
+#include "OrxonoxConfig.h"
+#include "tools/ToolsPrereqs.h"
+
+//-----------------------------------------------------------------------
+// Shared library settings
+//-----------------------------------------------------------------------
+
+#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_STATIC_BUILD)
+#  ifdef ORXONOX_SHARED_BUILD
+#    define _OrxonoxExport __declspec(dllexport)
+#  else
+#    if defined( __MINGW32__ )
+#      define _OrxonoxExport
+#    else
+#      define _OrxonoxExport __declspec(dllimport)
+#    endif
+#  endif
+#  define _OrxonoxPrivate
+#elif defined (ORXONOX_GCC_VISIBILITY)
+#  define _OrxonoxExport  __attribute__ ((visibility("default")))
+#  define _OrxonoxPrivate __attribute__ ((visibility("hidden")))
+#else
+#  define _OrxonoxExport
+#  define _OrxonoxPrivate
+#endif
+
+//-----------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------
+
+namespace orxonox
+{
+    class CameraManager;
+    class Level;
+    class LevelInfo;
+    class LevelInfoItem;
+    class LevelManager;
+    class PlayerManager;
+    class Radar;
+    class RenderQueueListener;
+    class Scene;
+    class GSLevelMemento;
+    struct GSLevelMementoState;
+
+    // chat
+    class ChatHistory;
+    class ChatInputHandler;
+    class ChatListener;
+    class ChatManager;
+
+    // collisionshapes
+    class CollisionShape;
+    class CompoundCollisionShape;
+    class WorldEntityCollisionShape;
+
+    // controllers
+    class AIController;
+    class ArtificialController;
+    class Controller;
+    class DroneController;
+    class HumanController;
+    class ScriptController;
+    class WaypointController;
+    class WaypointPatrolController;
+
+    // gametypes
+    class Asteroids;
+    class Deathmatch;
+    class Dynamicmatch;
+    class Gametype;
+    class LastManStanding;
+    class LastTeamStanding;
+    class TeamBaseMatch;
+    class TeamDeathmatch;
+    class UnderAttack;
+    class TeamGametype;
+
+    // graphics
+    class Backlight;
+    class Billboard;
+    class BlinkingBillboard;
+    class Camera;
+    class FadingBillboard;
+    class GlobalShader;
+    class Light;
+    class Model;
+    class ParticleEmitter;
+    class ParticleSpawner;
+
+    // infos
+    class Bot;
+    class GametypeInfo;
+    class HumanPlayer;
+    class Info;
+    class PlayerInfo;
+
+    // interfaces
+    class GametypeMessageListener;
+    class NotificationListener;
+    class Pickupable;
+    class PickupCarrier;
+    class PlayerTrigger;
+    class RadarListener;
+    class RadarViewable;
+    class Rewardable;
+    class TeamColourable;
+
+    // items
+    class ShipPart;
+    class PartDestructionEvent;
+    class Engine;
+    class Item;
+    class MultiStateEngine;
+
+    // overlays
+    class InGameConsole;
+    class OrxonoxOverlay;
+    class OverlayGroup;
+
+    //sound
+    class AmbientSound;
+    class BaseSound;
+    class SoundBuffer;
+    class SoundManager;
+    class SoundStreamer;
+    class WorldSound;
+    class WorldAmbientSound;
+
+    // weaponsystem
+    class DefaultWeaponmodeLink;
+    class Munition;
+    class ReplenishingMunition;
+    class Weapon;
+    class WeaponMode;
+    class WeaponPack;
+    class WeaponSet;
+    class WeaponSlot;
+    class WeaponSystem;
+
+    // worldentities
+    class CameraPosition;
+    class ControllableEntity;
+    class Drone;
+    class EffectContainer;
+    class ExplosionChunk;
+    class MobileEntity;
+    class MovableEntity;
+    class SpawnPoint;
+    class StaticEntity;
+    class TeamSpawnPoint;
+    class WorldEntity;
+    class Rocket;
+    // worldentities, pawns
+    class Destroyer;
+    class Pawn;
+    class SpaceShip;
+    class ModularSpaceShip;
+    class Spectator;
+    class TeamBaseMatchBase;
+}
+
+// Bullet Physics Engine
+class btTransform;
+class btVector3;
+
+class btRigidBody;
+class btCollisionObject;
+class btGhostObject;
+class btManifoldPoint;
+
+class btCollisionShape;
+class btSphereShape;
+class btCompoundShape;
+class btStaticPlaneShape;
+
+class btDiscreteDynamicsWorld;
+class bt32BitAxisSweep3;
+class btDefaultCollisionConfiguration;
+class btCollisionDispatcher;
+class btSequentialImpulseConstraintSolver;
+
+// ALUT
+typedef struct ALCcontext_struct ALCcontext;
+typedef struct ALCdevice_struct ALCdevice;
+typedef unsigned int ALuint;
+typedef int ALint;
+typedef int ALenum;
+
+#endif /* _OrxonoxPrereqs_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/PlayerManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/PlayerManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/PlayerManager.cc	(revision 11817)
@@ -0,0 +1,119 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PlayerManager.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+#include "Level.h"
+#include "LevelManager.h"
+#include "infos/HumanPlayer.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(PlayerManager, ScopeID::ROOT, false);
+
+    RegisterAbstractClass(PlayerManager).inheritsFrom<ClientConnectionListener>();
+
+    PlayerManager::PlayerManager()
+    {
+        RegisterObject(PlayerManager);
+
+//         this->getConnectedClients();
+    }
+
+    PlayerManager::~PlayerManager()
+    {
+    }
+
+    void PlayerManager::clientConnected(unsigned int clientID)
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID != 0)
+                orxout(internal_info) << "client connected" << endl;
+
+            // create new HumanPlayer instance
+            HumanPlayer* player = new HumanPlayer(nullptr);
+            player->setClientID(clientID);
+
+            // add to clients-map
+            assert(!this->clients_[clientID]);
+            this->clients_[clientID] = player;
+
+            if (LevelManager::exists() && LevelManager::getInstance().getActiveLevel())
+                LevelManager::getInstance().getActiveLevel()->playerEntered(player);
+        }
+    }
+
+    void PlayerManager::clientDisconnected(unsigned int clientID)
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID != 0)
+                orxout(internal_info) << "client disconnected" << endl;
+
+            // remove from clients-map
+            PlayerInfo* player = this->clients_[clientID];
+            this->clients_.erase(clientID);
+
+            if (LevelManager::exists() && LevelManager::getInstance().getActiveLevel())
+                LevelManager::getInstance().getActiveLevel()->playerLeft(player);
+
+            // delete PlayerInfo instance
+            if (player)
+                player->destroy();
+        }
+    }
+
+    void PlayerManager::disconnectAllClients()
+    {
+        for( std::map<unsigned int, PlayerInfo*>::iterator it = this->clients_.begin(); it != this->clients_.end(); )
+            this->clientDisconnected( (it++)->first );
+    }
+
+
+    PlayerInfo* PlayerManager::getClient(unsigned int clientID) const
+    {
+        if (GameMode::isMaster())
+        {
+            std::map<unsigned int, PlayerInfo*>::const_iterator it = this->clients_.find(clientID);
+            if (it != this->clients_.end())
+                return it->second;
+        }
+        else
+        {
+            for (PlayerInfo* info : ObjectList<PlayerInfo>())
+                if (info->getClientID() == clientID)
+                    return info;
+        }
+        return nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/PlayerManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/PlayerManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/PlayerManager.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PlayerManager_H__
+#define _PlayerManager_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <cassert>
+#include <map>
+#include "util/Singleton.h"
+#include "network/ClientConnectionListener.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport PlayerManager : public Singleton<PlayerManager>, public ClientConnectionListener
+    {
+            friend class Singleton<PlayerManager>;
+        public:
+            PlayerManager();
+            virtual ~PlayerManager();
+
+            PlayerInfo* getClient(unsigned int clientID) const;
+            inline const std::map<unsigned int, PlayerInfo*>& getClients() const
+                { return this->clients_; }
+
+            virtual void clientConnected(unsigned int clientID) override;
+            virtual void clientDisconnected(unsigned int clientID) override;
+            void disconnectAllClients();
+
+        private:
+            std::map<unsigned int, PlayerInfo*> clients_;
+
+            static PlayerManager* singletonPtr_s;
+    };
+}
+
+#endif /* _PlayerManager_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/Radar.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Radar.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Radar.cc	(revision 11817)
@@ -0,0 +1,217 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Felix Schulthess
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#include "Radar.h"
+
+#include <cassert>
+
+//#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/object/ObjectList.h"
+#include "core/command/ConsoleCommand.h"
+#include "interfaces/RadarListener.h"
+#include "controllers/HumanController.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(Radar).inheritsFrom<Tickable>();
+
+    Radar::Radar()
+        : itFocus_(nullptr)
+        , focus_(nullptr)
+        , objectTypeCounter_(0)
+    {
+        // TODO: make this mapping configurable. Maybe there's a possibility with self configured
+        //       configValues..
+        this->objectTypes_["Asteroid"] = RadarViewable::Shape::Dot;
+        this->objectTypes_["SpaceShip"] = RadarViewable::Shape::Square;
+        this->objectTypes_["AsdfQwerty"] = RadarViewable::Shape::Triangle;
+
+        /*WorldEntity* object;
+        object = new WorldEntity();
+        object->setPosition(2000.0, 0.0, 0.0);
+        addRadarObject(object, ColourValue(0.5, 0, 0, 1));
+        object = new WorldEntity();
+        object->setPosition(0.0, 2000.0, 0.0);
+        addRadarObject(object, ColourValue(0.5, 0, 0, 1));
+        object = new WorldEntity();
+        object->setPosition(0.0, 0.0, 2000.0);
+        addRadarObject(object, ColourValue(0.5, 0, 0, 1));
+        object = new WorldEntity();
+        object->setPosition(10000.0,16000.0,0.0);
+        addRadarObject(object);*/
+
+    }
+
+    Radar::~Radar()
+    {
+    }
+
+    void Radar::addRadarObject(RadarViewable* rv)
+    {
+        assert( this->radarObjects_.find(rv) == this->radarObjects_.end() );
+        this->radarObjects_.insert(rv);
+        // iterate through all radarlisteners and notify them
+        for (RadarListener* listener : ObjectList<RadarListener>())
+        {
+            listener->addObject(rv);
+        }
+    }
+
+    void Radar::removeRadarObject(RadarViewable* rv)
+    {
+        assert( this->radarObjects_.find(rv) != this->radarObjects_.end() );
+        this->radarObjects_.erase(rv);
+        // iterate through all radarlisteners and notify them
+        for (RadarListener* listener : ObjectList<RadarListener>())
+        {
+            listener->removeObject(rv);
+        }
+    }
+
+    const RadarViewable* Radar::getFocus()
+    {
+        if (this->itFocus_)
+            return *(this->itFocus_);
+        else
+            return nullptr;
+    }
+
+    RadarViewable::Shape Radar::addObjectDescription(const std::string& name)
+    {
+        std::map<std::string, RadarViewable::Shape>::iterator it = this->objectTypes_.find(name);
+        if (it == this->objectTypes_.end())
+            return this->objectTypes_[name] = RadarViewable::Shape::Square; // default, configure!!
+        else
+            return this->objectTypes_[name];
+    }
+
+
+    void Radar::tick(float dt)
+    {
+        SUPER(Radar, tick, dt);
+
+        if (this->itFocus_ && (this->focus_ != *(this->itFocus_)))
+        {
+            // focus object was deleted, release focus
+            this->focus_ = nullptr;
+            this->itFocus_ = nullptr;
+        }
+
+        for (RadarListener* listener : ObjectList<RadarListener>())
+        {
+            listener->radarTick(dt);
+        }
+    }
+
+    void Radar::cycleFocus()
+    {
+        ObjectList<RadarViewable> listRadarViewable;
+        if (listRadarViewable.size() == 0)
+        {
+            // list is empty
+            this->itFocus_ = nullptr;
+            this->focus_ = nullptr;
+        }
+
+        else if (HumanController::getLocalControllerEntityAsPawn())
+        {
+            Vector3 localPosition = HumanController::getLocalControllerEntityAsPawn()->getWorldPosition();
+            Vector3 targetPosition = localPosition;
+            if (this->itFocus_ && *(this->itFocus_))
+                targetPosition = this->itFocus_->getRVWorldPosition();
+
+            // find the closest object further away than targetPosition
+            float currentDistance = localPosition.squaredDistance(targetPosition);
+            float nextDistance = FLT_MAX;
+            float minimumDistance = FLT_MAX;
+            ObjectList<RadarViewable>::iterator itFallback = nullptr;
+
+            for (ObjectList<RadarViewable>::iterator it = listRadarViewable.begin(); it; ++it)
+            {
+                if (*it == static_cast<RadarViewable*>(HumanController::getLocalControllerEntityAsPawn()))
+                    continue;
+
+                float targetDistance = localPosition.squaredDistance((*it)->getRVWorldPosition());
+                if (targetDistance > currentDistance && targetDistance < nextDistance)
+                {
+                    this->itFocus_ = it;
+                    nextDistance = targetDistance;
+                }
+                if (targetDistance < minimumDistance)
+                {
+                    itFallback = it;
+                    minimumDistance = targetDistance;
+                }
+            }
+
+            if (nextDistance == FLT_MAX)
+            {
+                // we already had the furthest object
+                this->itFocus_ = itFallback;
+                this->focus_ = *itFallback;
+            }
+            else
+            {
+                this->focus_ = *(this->itFocus_);
+            }
+        }
+    }
+
+    void Radar::releaseFocus()
+    {
+        this->itFocus_ = nullptr;
+        this->focus_ = nullptr;
+    }
+
+    void Radar::listObjects() const
+    {
+        orxout(debug_output) << "List of RadarObjects:" << endl;
+        // iterate through all Radar Objects
+        unsigned int i = 0;
+        for (RadarViewable* viewable : ObjectList<RadarViewable>())
+        {
+            orxout(debug_output) << i++ << ": " << viewable->getRVWorldPosition() << endl;
+            ++i;
+        }
+    }
+
+    void Radar::radarObjectChanged(RadarViewable* rv)
+    {
+        for (RadarListener* listener : ObjectList<RadarListener>())
+        {
+            listener->objectChanged(rv);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/Radar.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Radar.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Radar.h	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Felix Schulthess
+ *
+ */
+
+/**
+@file
+@brief
+*/
+
+#ifndef _Radar_H__
+#define _Radar_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "core/object/ObjectListIterator.h"
+#include "interfaces/RadarViewable.h"
+#include "tools/interfaces/Tickable.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Radar : public Tickable
+    {
+        friend class RadarViewable;
+    public:
+        Radar();
+        virtual ~Radar();
+
+        virtual void tick(float dt) override;
+
+        const RadarViewable* getFocus();
+        RadarViewable::Shape addObjectDescription(const std::string& name);
+
+        void listObjects() const;
+        const std::set<RadarViewable*>& getRadarObjects() const
+            { return this->radarObjects_; }
+
+        void releaseFocus();
+        void cycleFocus();
+
+    private:
+        Radar(Radar& instance);
+
+        void updateFocus();
+        void addRadarObject(RadarViewable* rv);
+        void removeRadarObject(RadarViewable* rv);
+        void radarObjectChanged(RadarViewable* rv);
+
+        ObjectList<RadarViewable>::iterator itFocus_;
+        RadarViewable* focus_;
+        std::map<std::string, RadarViewable::Shape> objectTypes_;
+        std::set<RadarViewable*> radarObjects_;
+        int objectTypeCounter_;
+    };
+}
+#endif /* _Radar_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/RenderQueueListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/RenderQueueListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/RenderQueueListener.cc	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      David 'davidsa' Salvisberg
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+  @file RenderQueueListener.cc
+  @brief Implementation of the RenderQueueListener class.
+*/
+
+#include "RenderQueueListener.h"
+
+#include <OgreRoot.h>
+#include <OgreRenderQueueListener.h>
+#include <OgreHardwareOcclusionQuery.h>
+
+namespace orxonox
+{
+    RenderQueueListener::RenderQueueListener() : pixelCount_(0), pixelState_(PixelState::READY_FOR_RENDER)
+    {
+        hardwareOcclusionQuery_ = Ogre::Root::getSingleton().getRenderSystem()->createHardwareOcclusionQuery(); //create a new HOQ for the scene this listener is used in
+    }
+    
+    RenderQueueListener::~RenderQueueListener()
+    {
+        Ogre::Root::getSingleton().getRenderSystem()->destroyHardwareOcclusionQuery(hardwareOcclusionQuery_); //destroy the created HOQ
+    }
+    
+    /**
+    @brief
+    This function is returning the current pixel count and resets the pixel state if we're ready to do another Hardware Occlusion Query
+    
+    @return
+    current pixel count taken from the last Hardware Occlusion Query
+    */
+    unsigned int RenderQueueListener::getPixelCount()
+    {
+        if(this->pixelState_==PixelState::READY_FOR_ACCESS)
+        {
+            this->hardwareOcclusionQuery_->pullOcclusionQuery(&(this->pixelCount_));
+            this->pixelState_=PixelState::READY_FOR_RENDER;
+        }
+        return this->pixelCount_;
+    }
+    
+    /**
+    @brief
+    This function is called just before a RenderQueueGroup is rendered, this function is called by Ogre automatically with the correct parameters.
+
+    In this case we use it to set the stencil buffer parameters of the render system and issue a Hardware Occlusion Query
+    */
+    void RenderQueueListener::renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation)
+    {
+        if (queueGroupId == RENDER_QUEUE_STENCIL_OBJECTS)
+        { 
+            Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem(); 
+
+            renderSystem->clearFrameBuffer(Ogre::FBT_STENCIL); 
+            renderSystem->setStencilCheckEnabled(true); 
+            renderSystem->setStencilBufferParams(Ogre::CMPF_ALWAYS_PASS,
+                STENCIL_VALUE_FOR_GLOW, STENCIL_FULL_MASK, 
+                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
+        } 
+        if (queueGroupId == RENDER_QUEUE_STENCIL_GLOW)
+        { 
+            Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem(); 
+            renderSystem->setStencilCheckEnabled(true); 
+            renderSystem->setStencilBufferParams(Ogre::CMPF_NOT_EQUAL,
+                STENCIL_VALUE_FOR_GLOW, STENCIL_FULL_MASK, 
+                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
+        }
+        if (queueGroupId == RENDER_QUEUE_HOQ && this->pixelState_==PixelState::READY_FOR_RENDER)
+        { 
+            this->hardwareOcclusionQuery_->beginOcclusionQuery();
+            this->pixelState_=PixelState::QUERY_STARTED;
+            //TODO: Skip this rendering step altogheter if we haven't requested the pixel count yet, not sure if this is possible without a custom SceneManager
+        }
+    }
+    
+    /**
+    @brief
+        This function is called just after a RenderQueueGroup has been rendered, this function is called by Ogre automatically with the correct parameters.
+        
+        in this case we use it to unset the stencil buffer parameters, so the rest of the render queue is unaffected by it.
+    */
+    void RenderQueueListener::renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation)
+    {
+        if (queueGroupId == RENDER_QUEUE_STENCIL_LAST) 
+        {
+            Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem(); 
+            renderSystem->setStencilCheckEnabled(false); 
+            renderSystem->setStencilBufferParams(); 
+        }
+        if (queueGroupId == RENDER_QUEUE_HOQ && this->pixelState_==PixelState::QUERY_STARTED)
+        {
+            this->hardwareOcclusionQuery_->endOcclusionQuery();
+            this->pixelState_=PixelState::READY_FOR_ACCESS;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/RenderQueueListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/RenderQueueListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/RenderQueueListener.h	(revision 11817)
@@ -0,0 +1,110 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      David 'davidsa' Salvisberg
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+  @file RenderQueueListener.h
+  @brief Definition of the RenderQueueListener class.
+*/
+
+#ifndef _ORenderQueueListener_H__
+#define _ORenderQueueListener_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <OgreRenderQueueListener.h>
+#include <OgreHardwareOcclusionQuery.h>
+
+namespace orxonox
+{
+    enum RenderQueueGroupID //!< these are IDs for render queues that are executed just after the main render queue defined by Ogre, we need more than one for Stencil Glow
+    {
+        RENDER_QUEUE_MAIN = Ogre::RENDER_QUEUE_MAIN, //reference to the main render queue
+        RENDER_QUEUE_STENCIL_OBJECTS = RENDER_QUEUE_MAIN+1,
+        RENDER_QUEUE_STENCIL_GLOW = RENDER_QUEUE_MAIN+2,
+        RENDER_QUEUE_STENCIL_LAST = RENDER_QUEUE_STENCIL_GLOW, //this is a reference to the last render queue to be affected by stencil glow effects
+        RENDER_QUEUE_HOQ = RENDER_QUEUE_STENCIL_LAST+1 //this is where we render the objects for occlusion queries (use transparent material)
+    };
+
+    constexpr int STENCIL_VALUE_FOR_GLOW = 1; //!< this is a reference value for our mask, 
+                                          //!< if more than one type of stencil mask is to be used, each of them need their own value
+    constexpr int STENCIL_FULL_MASK = 0xFFFFFFFF; //!< this is a reference mask used in our stencil buffer
+    
+    /**
+    @brief
+        This class derives from the Ogre-Class RenderQueueListener and provides a way to define new rendering stages to enable use of e.g. stencil buffers
+        to increase the number of shader effects we can create. Especially important for shader-based alpha blending.
+
+    @author
+        David 'davidsa' Salvisberg
+    */
+    class _OrxonoxExport RenderQueueListener : public Ogre::RenderQueueListener
+    {
+        public:
+            RenderQueueListener();
+            ~RenderQueueListener();
+    
+            /**
+            @brief
+            This function is returning the current pixel count and resets the pixel state if we're ready to do another Hardware Occlusion Query
+            
+            @return
+            current pixel count taken from the last Hardware Occlusion Query
+            */
+            unsigned int getPixelCount();
+            
+            /**
+            @brief
+                This function is called just before a RenderQueueGroup is rendered, this function is called by Ogre automatically with the correct parameters.
+                
+                In this case we use it to set the stencil buffer parameters of the render system
+            */
+            virtual void renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation) override;
+            /**
+            @brief
+                This function is called just after a RenderQueueGroup has been rendered, this function is called by Ogre automatically with the correct parameters.
+                
+                in this case we use it to unset the stencil buffer parameters, so the rest of the render queue is unaffected by it.
+            */
+            virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation) override;
+            
+        private:
+            Ogre::HardwareOcclusionQuery* hardwareOcclusionQuery_; //!< this stores the current instance of the HOQ used in the render system
+            unsigned int pixelCount_; //!< this stores the last pixel count returned by the last HOQ in the corresponding render group
+            
+            enum class PixelState //!< enum to distinguish the several HOQ pixel count states
+            {
+                READY_FOR_RENDER,
+                QUERY_STARTED,
+                READY_FOR_ACCESS
+            };
+            
+            PixelState pixelState_; //!< this stores the current state of the Hardware Occlusion Query
+    };
+}
+
+#endif /* _ORenderQueueListener_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/Scene.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Scene.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Scene.cc	(revision 11817)
@@ -0,0 +1,420 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder (physics)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file Scene.cc
+@brief Implementation of Scene Class
+*/
+
+
+#include "Scene.h"
+
+#include <OgreRoot.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneManagerEnumerator.h>
+#include <OgreSceneNode.h>
+
+#include <BulletCollision/BroadphaseCollision/btAxisSweep3.h>
+#include <BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h>
+#include <BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h>
+#include <BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/GUIManager.h"
+#include "core/XMLPort.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "tools/BulletConversions.h"
+#include "tools/BulletDebugDrawer.h"
+#include "tools/DebugDrawer.h"
+#include "Radar.h"
+#include "worldentities/WorldEntity.h"
+#include "Level.h"
+#include "RenderQueueListener.h"
+#include "graphics/GlobalShader.h"
+
+namespace orxonox
+{
+    RegisterClass(Scene);
+    
+    /**
+    @brief 
+        Constructor, it sets common standard paramters for a scene depending on whether it will be rendered or not.
+        It also makes sure we user our own render queue listener for rendering instead of the standard listener provided by Ogre
+    */
+    SetConsoleCommand("Scene", "debugDrawPhysics", &Scene::consoleCommand_debugDrawPhysics).addShortcut().defaultValue(1, true).defaultValue(2, 0.5f);
+
+    Scene::Scene(Context* context) : BaseObject(context), Synchronisable(context), Context(context)
+    {
+        RegisterObject(Scene);
+
+        this->setScene(WeakPtr<Scene>(this), this->getObjectID()); // store a weak-pointer to itself (a strong-pointer would create a recursive dependency)
+
+        this->bShadows_ = true;
+        this->bDebugDrawPhysics_ = false;
+        this->debugDrawer_ = nullptr;
+        this->soundReferenceDistance_ = 20.0;
+        this->bIsUpdatingPhysics_ = false;
+
+        if (GameMode::showsGraphics())
+        {
+            assert(Ogre::Root::getSingletonPtr());
+            this->sceneManager_ = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
+            this->rootSceneNode_ = this->sceneManager_->getRootSceneNode();
+            this->renderQueueListener_ = new RenderQueueListener();
+            this->sceneManager_->addRenderQueueListener(this->renderQueueListener_);//add our own renderQueueListener
+
+            this->radar_ = new Radar();
+            this->glowShader_ = new GlobalShader(this);
+            this->glowShader_->setScene(WeakPtr<Scene>(this), this->getObjectID()); // avoid circular reference
+            this->glowShader_->getShader().setCompositorName("Glow");
+        }
+        else
+        {
+            // create a dummy SceneManager of our own since we don't have Ogre::Root.
+            this->sceneManager_ = new Ogre::DefaultSceneManager("");
+            this->rootSceneNode_ = this->sceneManager_->getRootSceneNode();
+
+            this->renderQueueListener_ = nullptr;
+            this->radar_ = nullptr;
+            this->glowShader_ = nullptr;
+        }
+
+        // No physics yet, XMLPort will do that.
+        const float defaultMaxWorldSize = 100000.0f;
+        this->negativeWorldRange_ = Vector3::UNIT_SCALE * -defaultMaxWorldSize;
+        this->positiveWorldRange_ = Vector3::UNIT_SCALE *  defaultMaxWorldSize;
+        this->gravity_ = Vector3::ZERO;
+        this->physicalWorld_   = nullptr;
+        this->solver_          = nullptr;
+        this->dispatcher_      = nullptr;
+        this->collisionConfig_ = nullptr;
+        this->broadphase_      = nullptr;
+
+        this->registerVariables();
+    }
+
+    Scene::~Scene()
+    {
+        if (this->isInitialized())
+        {
+            this->setPhysicalWorld(false);
+
+            if (this->radar_)
+                this->radar_->destroy();
+            if (this->glowShader_)
+                this->glowShader_->destroy();
+
+            if (GameMode::showsGraphics())
+            {
+                this->sceneManager_->removeRenderQueueListener(this->renderQueueListener_);
+                delete this->renderQueueListener_;
+                Ogre::Root::getSingleton().destroySceneManager(this->sceneManager_);
+            }
+            else
+                delete this->sceneManager_;
+        }
+    }
+
+    void Scene::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Scene, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Scene, "skybox", setSkybox, getSkybox, xmlelement, mode);
+        XMLPortParam(Scene, "ambientlight", setAmbientLight, getAmbientLight, xmlelement, mode).defaultValues(ColourValue(0.2f, 0.2f, 0.2f, 1.0f));
+        XMLPortParam(Scene, "shadow", setShadow, getShadow, xmlelement, mode).defaultValues(true);
+        XMLPortParam(Scene, "soundReferenceDistance", setSoundReferenceDistance, getSoundReferenceDistance, xmlelement, mode);
+
+        XMLPortParam(Scene, "gravity", setGravity, getGravity, xmlelement, mode);
+        XMLPortParam(Scene, "negativeWorldRange", setNegativeWorldRange, getNegativeWorldRange, xmlelement, mode);
+        XMLPortParam(Scene, "positiveWorldRange", setPositiveWorldRange, getPositiveWorldRange, xmlelement, mode);
+        XMLPortParam(Scene, "hasPhysics", setPhysicalWorld, hasPhysics, xmlelement, mode).defaultValues(true);
+
+        XMLPortObjectExtended(Scene, BaseObject, "", addObject, getObject, xmlelement, mode, true, false);
+    }
+
+    void Scene::registerVariables()
+    {
+        registerVariable(this->skybox_,             VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_applySkybox));
+        registerVariable(this->ambientLight_,       VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_applyAmbientLight));
+        registerVariable(this->negativeWorldRange_, VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_negativeWorldRange));
+        registerVariable(this->positiveWorldRange_, VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_positiveWorldRange));
+        registerVariable(this->gravity_,            VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_gravity));
+        registerVariable(this->bHasPhysics_,        VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_hasPhysics));
+        registerVariable(this->bShadows_,           VariableDirection::ToClient, new NetworkCallback<Scene>(this, &Scene::networkcallback_applyShadows));
+    }
+
+    void Scene::setNegativeWorldRange(const Vector3& range)
+    {
+        if (range.length() < 10.0f)
+        {
+            orxout(internal_warning) << "Setting the negative world range to a very small value: "
+                                     << multi_cast<std::string>(range) << endl;
+        }
+        if (this->hasPhysics())
+        {
+            orxout(internal_warning) << "Attempting to set the physical world range at run time. "
+                                     << "This causes a complete physical reload which might take some time." << endl;
+            this->setPhysicalWorld(false);
+            this->negativeWorldRange_ = range;
+            this->setPhysicalWorld(true);
+        }
+        else
+            this->negativeWorldRange_ = range;
+    }
+
+    void Scene::setPositiveWorldRange(const Vector3& range)
+    {
+        if (range.length() < 10.0f)
+        {
+            orxout(internal_warning) << "Setting the positive world range to a very small value: "
+                                     << multi_cast<std::string>(range) << endl;
+        }
+        if (this->hasPhysics())
+        {
+            orxout(internal_warning) << "Attempting to set the physical world range at run time. "
+                                     << "This causes a complete physical reload which might take some time." << endl;
+            this->setPhysicalWorld(false);
+            this->positiveWorldRange_ = range;
+            this->setPhysicalWorld(true);
+        }
+        else
+            this->positiveWorldRange_ = range;
+    }
+
+    void Scene::setGravity(const Vector3& gravity)
+    {
+        this->gravity_ = gravity;
+        if (this->hasPhysics())
+            this->physicalWorld_->setGravity(multi_cast<btVector3>(this->gravity_));
+    }
+
+    void Scene::setPhysicalWorld(bool wantPhysics)
+    {
+        this->bHasPhysics_ = wantPhysics;
+        if (wantPhysics && !hasPhysics())
+        {
+            // Note: These are all little known default classes and values.
+            //       It would require further investigation to properly dertermine the right choices.
+            this->broadphase_      = new bt32BitAxisSweep3(
+                multi_cast<btVector3>(this->negativeWorldRange_), multi_cast<btVector3>(this->positiveWorldRange_));
+            this->collisionConfig_ = new btDefaultCollisionConfiguration();
+            this->dispatcher_      = new btCollisionDispatcher(this->collisionConfig_);
+            this->solver_          = new btSequentialImpulseConstraintSolver();
+
+            this->physicalWorld_   = new btDiscreteDynamicsWorld(this->dispatcher_, this->broadphase_, this->solver_, this->collisionConfig_);
+            this->physicalWorld_->setGravity(multi_cast<btVector3>(this->gravity_));
+
+            if (GameMode::showsGraphics() && this->sceneManager_)
+            {
+                this->debugDrawer_ = new BulletDebugDrawer(this->sceneManager_);
+                this->physicalWorld_->setDebugDrawer(this->debugDrawer_);
+            }
+
+            // also set the collision callback variable.
+            // Note: This is a global variable which we assign a static function.
+            // TODO: Check whether this (or anything about Bullet) works with multiple physics engine instances.
+            gContactAddedCallback = &Scene::collisionCallback;
+        }
+        else if (!wantPhysics && hasPhysics())
+        {
+            // Remove all WorldEntities and shove them to the queue since they would still like to be in a physical world.
+            for (WorldEntity* object : this->physicalObjects_)
+            {
+                this->physicalWorld_->removeRigidBody(object->physicalBody_);
+                this->physicalObjectQueue_.insert(object);
+            }
+            this->physicalObjects_.clear();
+
+            delete this->debugDrawer_;
+            delete this->physicalWorld_;
+            delete this->solver_;
+            delete this->dispatcher_;
+            delete this->collisionConfig_;
+            delete this->broadphase_;
+            this->physicalWorld_   = nullptr;
+            this->solver_          = nullptr;
+            this->dispatcher_      = nullptr;
+            this->collisionConfig_ = nullptr;
+            this->broadphase_      = nullptr;
+        }
+    }
+
+    void Scene::tick(float dt)
+    {
+        if (!GameMode::showsGraphics())
+        {
+            // We need to update the scene nodes if we don't render
+            this->rootSceneNode_->_update(true, false);
+        }
+        if (this->hasPhysics())
+        {
+            // TODO: This here is bad practice! It will slow down the first tick() by ages.
+            //       Rather have an initialise() method as well, called by the Level after everything has been loaded.
+            if (this->physicalObjectQueue_.size() > 0)
+            {
+                // Add all scheduled WorldEntities
+                for (WorldEntity* object : this->physicalObjectQueue_)
+                {
+                    this->physicalWorld_->addRigidBody(object->physicalBody_);
+                    this->physicalObjects_.insert(object);
+                }
+                this->physicalObjectQueue_.clear();
+            }
+
+            // Note: 60 means that Bullet will do physics correctly down to 1 frames per seconds.
+            //       Under that mark, the simulation will "loose time" and get unusable.
+            this->bIsUpdatingPhysics_ = true;
+            this->physicalWorld_->stepSimulation(dt, 60);
+            this->bIsUpdatingPhysics_ = false;
+
+            if (this->bDebugDrawPhysics_)
+                this->physicalWorld_->debugDrawWorld();
+        }
+    }
+
+    void Scene::setSkybox(const std::string& skybox)
+    {
+        try
+        {
+            if (GameMode::showsGraphics() && this->sceneManager_)
+                this->sceneManager_->setSkyBox(true, skybox);
+        }
+        catch (const Ogre::Exception&)
+        {
+            orxout(internal_error) << "Could not load skybox '" << skybox << "':" << endl;
+            orxout(internal_error) << Exception::handleMessage() << endl;
+        }
+
+        this->skybox_ = skybox;
+    }
+
+    void Scene::setAmbientLight(const ColourValue& colour)
+    {
+        if (GameMode::showsGraphics() && this->sceneManager_)
+            this->sceneManager_->setAmbientLight(colour);
+
+        this->ambientLight_ = colour;
+    }
+
+    void Scene::setShadow(bool bShadow)
+    {
+        if (GameMode::showsGraphics() && this->sceneManager_)
+        {
+            if (bShadow)
+                this->sceneManager_->setShadowTechnique(Ogre::SHADOWTYPE_STENCIL_ADDITIVE);
+            else
+                this->sceneManager_->setShadowTechnique(Ogre::SHADOWTYPE_NONE);
+        }
+
+        this->bShadows_ = bShadow;
+    }
+
+    void Scene::addObject(BaseObject* object)
+    {
+        this->objects_.push_back(object);
+    }
+
+    BaseObject* Scene::getObject(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (BaseObject* object : this->objects_)
+        {
+            if (i == index)
+                return object;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    void Scene::addPhysicalObject(WorldEntity* object)
+    {
+        if (object)
+        {
+            std::set<WorldEntity*>::iterator it = this->physicalObjects_.find(object);
+            if (it != this->physicalObjects_.end())
+                return;
+
+            this->physicalObjectQueue_.insert(object);
+        }
+    }
+
+    void Scene::removePhysicalObject(WorldEntity* object)
+    {
+        // check queue first
+        std::set<WorldEntity*>::iterator it = this->physicalObjectQueue_.find(object);
+        if (it != this->physicalObjectQueue_.end())
+        {
+            this->physicalObjectQueue_.erase(it);
+            return;
+        }
+
+        it = this->physicalObjects_.find(object);
+        if (it == this->physicalObjects_.end())
+            return;
+        this->physicalObjects_.erase(it);
+
+        if (this->hasPhysics())
+            this->physicalWorld_->removeRigidBody(object->physicalBody_);
+    }
+
+    /*static*/ bool Scene::collisionCallback(btManifoldPoint& cp, const btCollisionObject* colObj0, int partId0,
+                                             int index0, const btCollisionObject* colObj1, int partId1, int index1)
+    {
+        // get the WorldEntity pointers
+        StrongPtr<WorldEntity> object0 = static_cast<WorldEntity*>(colObj0->getUserPointer());
+        StrongPtr<WorldEntity> object1 = static_cast<WorldEntity*>(colObj1->getUserPointer());
+
+        // get the CollisionShape pointers
+        const btCollisionShape* cs0 = colObj0->getCollisionShape();
+        const btCollisionShape* cs1 = colObj1->getCollisionShape();
+
+        // false means that bullet will assume we didn't modify the contact
+        bool modified = false;
+        if (object0->isCollisionCallbackActive())
+            modified |= object0->collidesAgainst(object1, cs1, cp);
+        if (object1->isCollisionCallbackActive())
+            modified |= object1->collidesAgainst(object0, cs0, cp);
+
+        return modified;
+    }
+
+    void Scene::setDebugDrawPhysics(bool bDraw, bool bFill, float fillAlpha)
+    {
+        this->bDebugDrawPhysics_ = bDraw;
+        if (this->debugDrawer_)
+            this->debugDrawer_->configure(bFill, fillAlpha);
+    }
+
+    /*static*/ void Scene::consoleCommand_debugDrawPhysics(bool bDraw, bool bFill, float fillAlpha)
+    {
+        for (Scene* scene : ObjectList<Scene>())
+            scene->setDebugDrawPhysics(bDraw, bFill, fillAlpha);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/Scene.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Scene.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Scene.h	(revision 11817)
@@ -0,0 +1,189 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder (physics)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file Scene.h
+@brief Definition of Scene Class
+*/
+
+#ifndef _Scene_H__
+#define _Scene_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include <set>
+#include <string>
+
+#include "util/Math.h"
+#include "util/OgreForwardRefs.h"
+#include "core/BaseObject.h"
+#include "core/object/Context.h"
+#include "network/synchronisable/Synchronisable.h"
+#include "tools/interfaces/Tickable.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Scene : public BaseObject, public Synchronisable, public Tickable, public Context
+    {
+        public:
+            /**
+            @brief 
+                This class holds a Scene which is a collection of all kinds of objects to be rendered in the same space,
+                with the same physics and the same light properties. Objects can be anything from a light source, over non physical objects
+                like Billboards to just plain Models with an attached Mesh
+            */
+            Scene(Context* context);
+            virtual ~Scene();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            void registerVariables();
+
+            inline Ogre::SceneManager* getSceneManager() const
+                { return this->sceneManager_; }
+            inline Ogre::SceneNode* getRootSceneNode() const
+                { return this->rootSceneNode_; }
+            inline RenderQueueListener* getRenderQueueListener() const
+                { return this->renderQueueListener_; }
+
+            void setSkybox(const std::string& skybox);
+            inline const std::string& getSkybox() const
+                { return this->skybox_; }
+
+            void setAmbientLight(const ColourValue& colour);
+            inline const ColourValue& getAmbientLight() const
+                { return this->ambientLight_; }
+
+            void setShadow(bool bShadow);
+            inline bool getShadow() const
+                { return this->bShadows_; }
+
+            inline void setSoundReferenceDistance(float distance)
+                { this->soundReferenceDistance_ = distance; }
+            inline float getSoundReferenceDistance() const
+                { return this->soundReferenceDistance_; }
+
+            inline Radar* getRadar()
+                { return this->radar_; }
+
+            virtual inline uint32_t getSceneID() const override { return this->getObjectID(); }
+
+            virtual void tick(float dt) override;
+
+        private:
+            void addObject(BaseObject* object);
+            BaseObject* getObject(unsigned int index) const;
+
+            void networkcallback_applySkybox()
+                { this->setSkybox(this->skybox_); }
+            void networkcallback_applyAmbientLight()
+                { this->setAmbientLight(this->ambientLight_); }
+            void networkcallback_applyShadows()
+                { this->setShadow(this->bShadows_); }
+
+            Ogre::SceneManager*      sceneManager_; //!< This is a pointer to the Ogre SceneManager we're using to render the Scene
+            Ogre::SceneNode*         rootSceneNode_; //!< This is a pointer to the root node of the Scene tree
+            RenderQueueListener*     renderQueueListener_; //!< this is a pointer to the RenderQueueListener we're using for this Scene
+
+            std::string              skybox_; //!< This string holds information about the skybox we're using
+            ColourValue              ambientLight_; //!< This variable holds the color value for the ambient light in our scene, usually black in space
+            std::list<BaseObject*>   objects_; //!< This list holds all the objects created in our scene
+            bool                     bShadows_; //!< Do we want shadows in our scene?
+            float                    soundReferenceDistance_; //!< This holds a reference distance, which represents the distance between our scene and the listener
+            Radar*                   radar_; //!< This is a pointer to a Radar object assigned with this scene
+            WeakPtr<GlobalShader>    glowShader_;
+
+
+        /////////////
+        // Physics //
+        /////////////
+
+        public:
+            inline bool hasPhysics() const
+                { return this->physicalWorld_ != nullptr; }
+            void setPhysicalWorld(bool wantsPhysics);
+
+            void setNegativeWorldRange(const Vector3& range);
+            inline const Vector3& getNegativeWorldRange() const
+                { return this->negativeWorldRange_; }
+
+            void setPositiveWorldRange(const Vector3& range);
+            inline const Vector3& getPositiveWorldRange() const
+                { return this->positiveWorldRange_; }
+
+            void setGravity(const Vector3& gravity);
+            inline const Vector3& getGravity() const
+                { return this->gravity_; }
+
+            void addPhysicalObject(WorldEntity* object);
+            void removePhysicalObject(WorldEntity* object);
+
+            inline bool isUpdatingPhysics() const
+                { return this->bIsUpdatingPhysics_; }
+
+            void setDebugDrawPhysics(bool bDraw, bool bFill, float fillAlpha);
+
+            static void consoleCommand_debugDrawPhysics(bool bDraw, bool bFill, float fillAlpha);
+
+        private:
+            inline void networkcallback_hasPhysics()
+                { this->setPhysicalWorld(this->bHasPhysics_); }
+            inline void networkcallback_negativeWorldRange()
+                { this->setNegativeWorldRange(this->negativeWorldRange_); }
+            inline void networkcallback_positiveWorldRange()
+                { this->setPositiveWorldRange(this->positiveWorldRange_); }
+            inline void networkcallback_gravity()
+                { this->setGravity(this->gravity_); }
+
+            // collision callback from bullet
+            static bool collisionCallback(btManifoldPoint& cp, const btCollisionObject* colObj0, int partId0,
+                                          int index0, const btCollisionObject* colObj1, int partId1, int index1);
+
+            // Bullet objects
+            btDiscreteDynamicsWorld*             physicalWorld_;
+            bt32BitAxisSweep3*                   broadphase_;
+            btDefaultCollisionConfiguration*     collisionConfig_;
+            btCollisionDispatcher*               dispatcher_;
+            btSequentialImpulseConstraintSolver* solver_;
+
+            std::set<WorldEntity*>               physicalObjectQueue_;
+            std::set<WorldEntity*>               physicalObjects_;
+            bool                                 bHasPhysics_;
+            Vector3                              negativeWorldRange_;
+            Vector3                              positiveWorldRange_;
+            Vector3                              gravity_;
+
+            BulletDebugDrawer*                   debugDrawer_;
+            bool                                 bDebugDrawPhysics_;
+            bool                                 bIsUpdatingPhysics_;
+    };
+}
+
+#endif /* _Scene_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/Test.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Test.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Test.cc	(revision 11817)
@@ -0,0 +1,152 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oli Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "network/NetworkFunctionIncludes.h"
+#include "Test.h"
+#include "util/MultiType.h"
+
+namespace orxonox
+{
+    RegisterClass ( Test );
+
+    SetConsoleCommand("Test", "printV1", &Test::printV1).addShortcut();
+    SetConsoleCommand("Test", "printV2", &Test::printV2).addShortcut();
+    SetConsoleCommand("Test", "printV3", &Test::printV3).addShortcut();
+    SetConsoleCommand("Test", "printV4", &Test::printV4).addShortcut();
+    SetConsoleCommand("Test", "call",    &Test::call).addShortcut();
+    SetConsoleCommand("Test", "call2",   &Test::call2).addShortcut();
+
+
+  //void=* aaaaa = copyPtr<sizeof(&Test::printV1)>( &NETWORK_FUNCTION_POINTER, &Test::printV1 );
+  //void* NETWORK_FUNCTION_TEST_B = memcpy(&NETWORK_FUNCTION_POINTER, &a, sizeof(a));
+//   NetworkFunctionBase* NETWORK_FUNCTION_TEST_C = new NetworkFunctionStatic( createFunctor(&Test::printV1), "bla", NETWORK_FUNCTION_POINTER );
+
+    registerStaticNetworkFunction( &Test::printV1 );
+    registerMemberNetworkFunction( Test, checkU1 );
+    registerMemberNetworkFunction( Test, printBlaBla );
+
+    Test* Test::instance_ = nullptr;
+
+    Test::Test(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        assert(instance_==nullptr);
+        instance_=this;
+        RegisterObject ( Test );
+        setConfigValues();
+        registerVariables();
+        setSyncMode(0x3);
+        this->pointer_ = nullptr;
+    }
+
+    Test::~Test()
+    {
+        instance_=nullptr;
+    }
+
+    void Test::setConfigValues()
+    {
+        SetConfigValue ( u1, 1 )/*.callback ( this, &Test::checkV1 )*/;
+        SetConfigValue ( u2, 2 )/*.callback ( this, &Test::checkV2 )*/;
+        SetConfigValue ( u3, 3 )/*.callback ( this, &Test::checkV3 )*/;
+        SetConfigValue ( u4, 4 )/*.callback ( this, &Test::checkV4 )*/;
+
+        SetConfigValue ( s1, 1 )/*.callback ( this, &Test::checkV1 )*/;
+        SetConfigValue ( s2, 2 )/*.callback ( this, &Test::checkV2 )*/;
+        SetConfigValue ( s3, 3 )/*.callback ( this, &Test::checkV3 )*/;
+        SetConfigValue ( s4, 4 )/*.callback ( this, &Test::checkV4 )*/;
+    }
+
+
+    void Test::registerVariables()
+    {
+        registerVariable ( this->mySet_, VariableDirection::ToClient );
+
+//         registerVariable ( u1, VariableDirection::ToClient, new NetworkCallback<Test> ( this, &Test::checkU1 ));
+//         registerVariable ( u2, VariableDirection::ToServer, new NetworkCallback<Test> ( this, &Test::checkU2 ));
+//         registerVariable ( u3, Bidirectionality::ServerMaster, new NetworkCallback<Test> ( this, &Test::checkU3 ), true );
+//         registerVariable ( u4, Bidirectionality::ClientMaster, new NetworkCallback<Test> ( this, &Test::checkU4 ), true );
+
+//         registerVariable ( s1, VariableDirection::ToClient, new NetworkCallback<Test> ( this, &Test::checkS1 ));
+//         registerVariable ( s2, VariableDirection::ToServer, new NetworkCallback<Test> ( this, &Test::checkS2 ));
+//         registerVariable ( s3, Bidirectionality::ServerMaster, new NetworkCallback<Test> ( this, &Test::checkS3 ), true );
+//         registerVariable ( s4, Bidirectionality::ClientMaster, new NetworkCallback<Test> ( this, &Test::checkS4 ), true );
+
+//         registerVariable ( pointer_, VariableDirection::ToClient, new NetworkCallback<Test> ( this, &Test::printPointer ) );
+    }
+
+  void Test::call(unsigned int clientID)
+    {
+        callStaticNetworkFunction(&Test::printV1, clientID );
+        callStaticNetworkFunction(&Test::printV1, clientID );
+    }
+
+    void Test::call2(unsigned int clientID, std::string s1, std::string s2, std::string s3, std::string s4)
+    {
+        callMemberNetworkFunction( &Test::printBlaBla, this->getObjectID(), clientID, s1, s2, s3, s4, s4 );
+    }
+
+    void Test::tick(float dt)
+    {
+    //     std::string str1 = "blub";
+    //     //MultiType mt1(std::string("blub"));
+    //     MultiType mt1(str1);
+    //     uint8_t* mem = new uint8_t[mt1.getNetworkSize()];
+    //     uint8_t* temp = mem;
+    //     mt1.exportData( temp );
+    //     assert( temp-mem == mt1.getNetworkSize() );
+    //     MultiType mt2;
+    //     temp = mem;
+    //     mt2.importData( temp );
+    //     assert( temp-mem == mt1.getNetworkSize() );
+    //     orxout() << mt2 << endl;
+    //     if(!Core::isMaster())
+    //       call2(0, "bal", "a", "n", "ce");
+    //       callMemberNetworkFunction( &Test::checkU1, this->getObjectID(), 0 );
+    }
+
+    void Test::printBlaBla(std::string s1, std::string s2, std::string s3, std::string s4, std::string s5)
+    {
+        orxout() << s1 << s2 << s3 << s4 << s5 << endl;
+    }
+
+    void Test::checkU1(){ orxout() << "U1 changed: " << u1 << endl; }
+    void Test::checkU2(){ orxout() << "U2 changed: " << u2 << endl; }
+    void Test::checkU3(){ orxout() << "U3 changed: " << u3 << endl; }
+    void Test::checkU4(){ orxout() << "U4 changed: " << u4 << endl; }
+
+    void Test::checkS1(){ orxout() << "S1 changed: " << s1 << endl; }
+    void Test::checkS2(){ orxout() << "S2 changed: " << s2 << endl; }
+    void Test::checkS3(){ orxout() << "S3 changed: " << s3 << endl; }
+    void Test::checkS4(){ orxout() << "S4 changed: " << s4 << endl; }
+
+    void Test::printPointer(){ orxout() << "pointer: " << this->pointer_ << endl; }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/Test.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/Test.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/Test.h	(revision 11817)
@@ -0,0 +1,114 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oli Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Test_H__
+#define _Test_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+#include "tools/interfaces/Tickable.h"
+
+#include <set>
+
+typedef int TYPE;
+typedef unsigned int UTYPE;
+
+
+namespace orxonox
+{
+  class _OrxonoxExport Test: public BaseObject, public Synchronisable, public Tickable
+  {
+    public:
+      Test(Context* context);
+      virtual ~Test();
+
+      void setConfigValues();
+
+      static void call(unsigned int clientID);
+      void call2(unsigned int clientID, std::string s1, std::string s2, std::string s3, std::string s4);
+      virtual void tick(float dt);
+
+
+      //unsigned functions
+      void setU1(UTYPE value){ u1 = value; }
+      void setU2(UTYPE value){ u2 = value; }
+      void setU3(UTYPE value){ u3 = value; }
+      void setU4(UTYPE value){ u4 = value; }
+      void checkU1();
+      void checkU2();
+      void checkU3();
+      void checkU4();
+
+      //signed functions
+      void setS1(TYPE value){ s1 = value; }
+      void setS2(TYPE value){ s2 = value; }
+      void setS3(TYPE value){ s3 = value; }
+      void setS4(TYPE value){ s4 = value; }
+      void checkS1();
+      void checkS2();
+      void checkS3();
+      void checkS4();
+
+      void printPointer();
+
+      static void printV1(){ instance_->blub(); }
+      static void printV2(){ instance_->blub2(); }
+      static void printV3(){ instance_->checkU3(); }
+      static void printV4(){ instance_->checkU4(); }
+
+      void printBlaBla(std::string s1, std::string s2, std::string s3, std::string s4, std::string s5);
+
+    private:
+      void registerVariables();
+
+      UTYPE u1;
+      UTYPE u2;
+      UTYPE u3;
+      UTYPE u4;
+
+      TYPE s1;
+      TYPE s2;
+      TYPE s3;
+      TYPE s4;
+
+      Test* pointer_;
+      
+      std::set<uint32_t> mySet_;
+
+      static Test* instance_;
+      
+      void blub()
+      { mySet_.insert(2); }
+      
+      void blub2()
+      { for( std::set<uint32_t>::iterator it=mySet_.begin(); it!=mySet_.end(); ++it ) orxout() << *it << endl; }
+  };
+}
+
+#endif /* _Test_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,5 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  ChatHistory.cc
+  ChatInputHandler.cc
+  ChatManager.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatHistory.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatHistory.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatHistory.cc	(revision 11817)
@@ -0,0 +1,172 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ChatHistory.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/ConfigurablePaths.h"
+#include "core/CoreIncludes.h"
+
+#ifndef CHATTEST
+namespace orxonox
+{
+  /* singleton */
+  ManageScopedSingleton( ChatHistory, ScopeID::ROOT, false );
+
+  RegisterAbstractClass(ChatHistory).inheritsFrom<ChatListener>();
+
+#endif
+
+  /* constructor */
+#ifndef CHATTEST
+  ChatHistory::ChatHistory()
+#else
+  ChatHistory::ChatHistory()
+#endif
+  {
+    /* register the object */
+#ifndef CHATTEST
+    RegisterObject(ChatHistory);
+#endif
+
+    this->hist_log_enabled = true;
+
+    /* Read setting for logfiles */
+    if( hist_log_enabled ) /* NOTE Make this a check for the logfile setting */
+    { this->chat_hist_openlog();
+
+      /* push starting line */
+      this->chat_hist_logline( "--- Logfile opened ---" );
+    }
+
+    /* Read setting for maximum number of lines and set limit */
+    this->hist_maxlines = 200; /* NOTE to be changed, 200 is just for testing */
+  }
+
+  /* destructor */
+  ChatHistory::~ChatHistory()
+  {
+    chat_hist_closelog();
+
+    /* clear list */
+    this->hist_buffer.clear();
+  }
+
+  /* react to incoming chat */
+  void ChatHistory::incomingChat(const std::string& message, const std::string& /*name*/)
+  {
+    /* add the line to the history */
+    this->chat_hist_addline( message );
+
+    /* add the line to the log */
+    this->chat_hist_logline( message );
+  }
+
+  /* Synchronize logfile onto the hard drive */ /* MARK MARK */
+  int ChatHistory::syncLog()
+  {
+    //if( this->hist_logfile )
+      //this->hist_logfile.sync();
+    return 0;
+  }
+
+  /* add a line to this history */
+  int ChatHistory::chat_hist_addline( const std::string& toadd )
+  {
+    /* crop history at the end if it's too large */
+    while( this->hist_buffer.size() > this->hist_maxlines+1 )
+      this->hist_buffer.pop_front();
+
+    /* push to the front of the history */
+    this->hist_buffer.push_back( toadd );
+    return 0;
+  }
+
+  /* log a line to a logfile */
+  int ChatHistory::chat_hist_logline( const std::string& toadd )
+  {
+    /* output the line to the file if logging is enabled */
+    if( this->hist_log_enabled )
+      this->hist_logfile << toadd << endl;
+    return 0;
+  }
+
+  /* open logfile */
+  int ChatHistory::chat_hist_openlog()
+  {
+    /* TODO: find out the name of the file to log to via settings
+     *       and set the this->hist_logfile_path variable to it
+     */
+#ifndef CHATTEST
+    this->hist_logfile.open( (ConfigurablePaths::getLogPathString() +
+      "chatlog.log").c_str(),
+      std::fstream::out | std::fstream::app );
+#else
+    this->hist_logfile.open( "/tmp/chatlog.log",
+      std::fstream::out | std::fstream::app );
+#endif
+
+    /* TODO check whether this works (not sure how you'd like it?) */
+    if( !this->hist_logfile )
+    { this->hist_log_enabled = false;
+#ifndef CHATTEST
+      orxout(internal_warning) << "Could not open logfile." << endl;
+#endif
+    }
+
+    /* if it worked */
+    return 0;
+  }
+
+  /* close logfile */
+  void ChatHistory::chat_hist_closelog()
+  {
+    /* see if we've actually got a logfile */
+    if( this->hist_logfile )
+    {
+      /* yes, we've got one, add a line that shows we're closing it */
+      this->chat_hist_logline( "--- Logfile closed ---" );
+
+      /* actually close down the file */
+      this->hist_logfile.close();
+    }
+  }
+
+  /* output history for debugging */
+  void ChatHistory::debug_printhist()
+  {
+    /* output all the strings */
+    for( const std::string& hist : this->hist_buffer )
+      orxout(debug_output) << hist << endl;
+
+    /* output size */
+    orxout(debug_output) << "Size: " << hist_buffer.size() << endl;
+  }
+
+#ifndef CHATTEST
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatHistory.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatHistory.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatHistory.h	(revision 11817)
@@ -0,0 +1,148 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <deque>
+#include <string>
+#include <fstream>
+#include <iostream>
+#include <cassert>
+
+/* define this if you're unit testing */
+//#define CHATTEST
+
+#ifndef CHATTEST
+#include "OrxonoxPrereqs.h"
+
+#include "util/Singleton.h"
+#include "core/BaseObject.h"
+#include "chat/ChatListener.h"
+#include "infos/PlayerInfo.h"
+#include "PlayerManager.h"
+#endif
+
+#ifndef _ChatHistory_H__
+#define _ChatHistory_H__
+
+
+/* Class to implement chat history */
+#ifndef CHATTEST
+namespace orxonox
+{
+#endif
+
+  /* constructor */
+#ifndef CHATTEST
+  class _OrxonoxExport ChatHistory : public ChatListener,
+    public Singleton<ChatHistory>
+
+#else
+  class ChatHistory
+#endif
+  {
+    public:
+      /* constructors, destructors */
+#ifndef CHATTEST
+      ChatHistory();
+      friend class Singleton<ChatHistory>;
+#else
+      ChatHistory();
+#endif
+      virtual ~ChatHistory();
+
+
+    //protected:
+      /** what to do with incoming chat
+       *
+       * \param message The incoming message
+       * \param name Name of the sender
+       */
+      virtual void incomingChat(const std::string& message, const std::string& name) override;
+
+      /** Synchronize logfile onto the hard drive
+       *
+       * \return 0 for success, other for error
+       */
+      int syncLog();
+
+      /** debug-print: output the whole history to stdout */
+      void debug_printhist();
+
+    private:
+      /* FIELDS */
+      /** Vector to store the history in */
+      std::deque<std::string> hist_buffer;
+
+      /** Maximum number of lines stored in this history */
+      unsigned int hist_maxlines;
+
+      /** is logging enabled? */
+      bool hist_log_enabled;
+
+      /** path of logfile on the file system */
+      std::string hist_logfile_path;
+
+      /** Output file stream for logfile */
+      std::ofstream hist_logfile;
+
+#ifndef CHATTEST
+      static ChatHistory* singletonPtr_s;
+#endif
+
+
+
+      /* METHODS */
+      /** Append line to chat history
+       *
+       * \param toadd The line to add to the history
+       * \return 0 for success, other for error TODO: Throw exception
+       */
+      int chat_hist_addline( const std::string& toadd );
+
+      /** Append line to logfile
+       *
+       * \param toadd The line to add to the logfile
+       * \return 0 for success, other for error TODO: Throw exception
+       */
+      int chat_hist_logline( const std::string& toadd );
+
+      /** open logfile to log to
+       *
+       * \return 0 for success,s other for error
+       */
+      int chat_hist_openlog();
+
+
+      /** close logfile */
+      void chat_hist_closelog();
+  };
+
+#ifndef CHATTEST
+}
+#endif
+
+#endif /* _ChatHistory_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatInputHandler.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatInputHandler.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatInputHandler.cc	(revision 11817)
@@ -0,0 +1,367 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ChatInputHandler.h"
+
+#include <cassert>
+#include <cstddef>
+#include <string>
+
+#if CEGUI_VERSION >= 0x000800
+#   include <CEGUI/Window.h>
+#   include <CEGUI/WindowManager.h>
+#   include <CEGUI/widgets/Listbox.h>
+#   include <CEGUI/widgets/ListboxItem.h>
+#   include <CEGUI/widgets/ListboxTextItem.h>
+#else
+#   include <CEGUIWindow.h>
+#   include <CEGUIWindowManager.h>
+#   include <elements/CEGUIListbox.h>
+#   include <elements/CEGUIListboxItem.h>
+#   include <elements/CEGUIListboxTextItem.h>
+#endif
+
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/GUIManager.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/input/InputBuffer.h"
+#include "core/input/InputManager.h"
+#include "core/input/InputState.h"
+
+#include "chat/ChatManager.h"
+#include "PlayerManager.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+  /* singleton */
+  ManageScopedSingleton( ChatInputHandler, ScopeID::GRAPHICS, false );
+
+  /* add commands to console */
+  SetConsoleCommand( "startchat", &ChatInputHandler::activate_static );
+  SetConsoleCommand( "startchat_small", &ChatInputHandler::activate_small_static );
+
+  RegisterAbstractClass(ChatInputHandler).inheritsFrom<ChatListener>();
+
+  /* constructor */
+  ChatInputHandler::ChatInputHandler()
+  {
+    /* register the object  */
+    RegisterObject(ChatInputHandler);
+
+    /* create necessary objects */
+    this->inpbuf = new InputBuffer();
+    this->disp_offset = 0;
+    assert( this->inpbuf != nullptr );
+
+    /* generate chatbox ui and chatbox-inputonly ui */
+    GUIManager::getInstance().loadGUI( "ChatBox" );
+    GUIManager::getInstance().loadGUI( "ChatBox-inputonly" );
+
+    /* setup colors */
+    setupColors();
+
+    /* configure the input buffer */
+    configureInputBuffer();
+
+    this->inputState = InputManager::getInstance().createInputState( "chatinput", false, false, InputStatePriority::Dynamic );
+    this->inputState->setKeyHandler(this->inpbuf);
+  }
+
+  ChatInputHandler::~ChatInputHandler()
+  {
+    /* Clean up */
+    InputManager::getInstance().destroyState("chatinput");
+    delete this->inpbuf;
+  }
+
+  /* configure input buffer, sub for the constructor */
+  void ChatInputHandler::configureInputBuffer()
+  {
+    /* INSTALL CALLBACKS */
+    /* input has changed */
+    this->inpbuf->registerListener(this, &ChatInputHandler::inputChanged, true);
+
+    /* add a line */
+    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\r',   false);
+    this->inpbuf->registerListener(this, &ChatInputHandler::addline,         '\n',   false);
+
+    /* backspace */
+    this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\b',   true);
+    //this->inpbuf->registerListener(this, &ChatInputHandler::backspace,       '\177', true);
+
+    /* exit the chatinputhandler thingy (tbd) */
+    this->inpbuf->registerListener(this, &ChatInputHandler::exit,            '\033', true); // escape
+
+    /* delete character */
+    this->inpbuf->registerListener(this, &ChatInputHandler::deleteChar,      KeyCode::Delete);
+
+    /* cursor movement */
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorRight,     KeyCode::Right);
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorLeft,      KeyCode::Left);
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorEnd,       KeyCode::End);
+    this->inpbuf->registerListener(this, &ChatInputHandler::cursorHome,      KeyCode::Home);
+
+    /* GET WINDOW POINTERS */
+#if CEGUI_VERSION >= 0x000800
+    input = CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild( "orxonox/ChatBox/input" );
+    inputonly = CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild( "orxonox/ChatBox-inputonly/input" );
+    CEGUI::Window *history = CEGUI::System::getSingleton().getDefaultGUIContext().getRootWindow()->getChild( "orxonox/ChatBox/history" );
+#else
+    input = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox/input" );
+    inputonly = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox-inputonly/input" );
+    CEGUI::Window *history = CEGUI::WindowManager::getSingleton().getWindow( "orxonox/ChatBox/history" );
+#endif
+
+    /* cast it to a listbox */
+    lb_history = dynamic_cast<CEGUI::Listbox*>(history);
+
+    /* assert wee */
+    assert( lb_history );
+  }
+
+  /* setup the colors, sub for the constructor */
+  void ChatInputHandler::setupColors()
+  {
+    /* auto variables */
+    float red = 1.0, green = 0.5, blue = 0.5;
+    int i = 0;
+
+    // three loops: red tones, blue tones and green tones
+    // reds
+    for( i = 0; i < NumberOfColors/3; ++i )
+    { this->text_colors[ i ] = CEGUIColour( red, green, blue );
+      green += 0.2f, blue += 0.2f;
+    }
+
+    // greens
+    red = 0.5, green = 1, blue = 0.5;
+    for( ; i < NumberOfColors*2/3; ++i )
+    { this->text_colors[ i ] = CEGUIColour( red, green, blue );
+      red += 0.2f, blue += 0.2f;
+    }
+
+    // blues
+    red = 0.5, green = 0.5, blue = 1;
+    for( ; i < NumberOfColors; ++i )
+    { this->text_colors[ i ] = CEGUIColour( red, green, blue );
+      red += 0.2f, green += 0.2f;
+    }
+  }
+
+
+  /* activate, deactivate */
+  void ChatInputHandler::activate_static()
+  { ChatInputHandler::getInstance().activate( true ); }
+
+  void ChatInputHandler::activate_small_static()
+  { ChatInputHandler::getInstance().activate( false ); }
+
+  void ChatInputHandler::activate( bool full )
+  {
+    /* start listening */
+    InputManager::getInstance().enterState("chatinput");
+
+    /* MARK add spawning of chat widget stuff here.*/
+    if( full )
+      GUIManager::getInstance().showGUI( "ChatBox" );
+    else
+      GUIManager::getInstance().showGUI( "ChatBox-inputonly" );
+
+    this->fullchat = full;
+  }
+
+  void ChatInputHandler::deactivate()
+  {
+    /* stop listening */
+    InputManager::getInstance().leaveState("chatinput");
+
+    /* un-spawning of chat widget stuff */
+    GUIManager::getInstance().hideGUI( "ChatBox" );
+    GUIManager::getInstance().hideGUI( "ChatBox-inputonly" );
+  }
+
+
+  /* subs for incomingChat */
+  void ChatInputHandler::sub_setcolor( CEGUI::ListboxTextItem *tocolor,
+    std::string name )
+  {
+    /* sanity checks */
+    if (!tocolor)
+    {
+        orxout(internal_warning) << "Empty ListBoxTextItem given to "
+            "ChatInputhandler::sub_setcolor()." << endl;
+        return;
+    }
+
+    /* "hash" the name */
+    int hash = 0;
+    for( int i = name.length(); i > 0; --i )
+      hash += name[i-1];
+    hash = hash % this->NumberOfColors;
+
+    /* set the color according to the hash */
+    tocolor->setTextColours( this->text_colors[ hash ] );
+  }
+
+  /* handle incoming chat */
+  void ChatInputHandler::incomingChat(const std::string& message, const std::string& name)
+  {
+    /* create item */
+    CEGUI::ListboxTextItem *toadd = new CEGUI::ListboxTextItem( message );
+
+    /* setup colors */
+    if (name != "")
+      sub_setcolor( toadd, name );
+
+    /* now add */
+    this->lb_history->addItem( dynamic_cast<CEGUI::ListboxItem*>(toadd) );
+    this->lb_history->ensureItemIsVisible(
+      dynamic_cast<CEGUI::ListboxItem*>(toadd) );
+
+    /* make sure the history handles it */
+    this->lb_history->handleUpdatedItemData();
+  }
+
+
+  /* sub for inputchanged */
+  void ChatInputHandler::sub_adjust_dispoffset( int maxlen,
+    int cursorpos,
+    int inplen )
+  {
+    /* already start offsetting 5 characters before end */
+    if( cursorpos+5 > maxlen )
+    {
+      /* always stay 5 characters ahead of end, looks better */
+      ((disp_offset = cursorpos-maxlen+5) >= 0) ? 1 : disp_offset = 0;
+
+      /* enforce visibility of cursor */
+      (disp_offset > cursorpos ) ? disp_offset = 0 : 1;
+    }
+
+    /* make sure we don't die at substr */
+    if( inplen <= disp_offset ) disp_offset = 0;
+  }
+
+  /* callbacks for InputBuffer */
+  void ChatInputHandler::inputChanged()
+  {
+    /* update the cursor and the window */
+    std::string raw = this->inpbuf->get();
+    int cursorpos = this->inpbuf->getCursorPosition();
+
+    /* get string before cursor */
+    std::string left = raw.substr( 0, cursorpos );
+
+    /* see if there's a string after the cursor */
+    std::string right = "";
+    if( raw.length() >= left.length()+1 )
+      right = raw.substr( cursorpos );
+
+    /* set the text */
+    std::string assembled = "$ " + left + "|" + right;
+
+    if( this->fullchat )
+    {
+      /* adjust curser position - magic number 5 for font width */
+#if CEGUI_VERSION >= 0x000800
+      sub_adjust_dispoffset( (int)(this->input->getUnclippedInnerRect().get().getWidth()/6), cursorpos, assembled.length() );
+#else
+      sub_adjust_dispoffset( (int)(this->input->getUnclippedInnerRect().getWidth()/6), cursorpos, assembled.length() );
+#endif
+      this->input->setProperty( "Text", assembled.substr( disp_offset ) );
+    }
+    else
+    {
+      /* adjust curser position - magic number 5 for font width */
+#if CEGUI_VERSION >= 0x000800
+      sub_adjust_dispoffset( (int)(this->inputonly->getUnclippedInnerRect().get().getWidth()/6), cursorpos, assembled.length() );
+#else
+      sub_adjust_dispoffset( (int)(this->inputonly->getUnclippedInnerRect().getWidth()/6), cursorpos, assembled.length() );
+#endif
+      this->inputonly->setProperty( "Text", assembled.substr( disp_offset) );
+    }
+
+    /* reset display offset */
+    disp_offset = 0;
+  }
+
+  void ChatInputHandler::addline()
+  {
+    /* actually do send what was input */
+    /* a) get the string out of the inputbuffer */
+    std::string msgtosend = this->inpbuf->get();
+
+    if( msgtosend.length() == 0 )
+    { this->deactivate();
+      return;
+    }
+
+    /* b) clear the input buffer */
+    if (this->inpbuf->getSize() > 0)
+      this->inpbuf->clear();
+
+    /* c) send the chat via some call */
+    ChatManager::chat( msgtosend );
+
+    /* d) stop listening to input - only if this is not fullchat */
+    if( !this->fullchat )
+      this->deactivate();
+
+  }
+
+  void ChatInputHandler::backspace()
+  { this->inpbuf->removeBehindCursor(); }
+
+  void ChatInputHandler::deleteChar()
+  { this->inpbuf->removeAtCursor(); }
+
+  void ChatInputHandler::cursorRight()
+  { this->inpbuf->increaseCursor(); }
+
+  void ChatInputHandler::cursorLeft()
+  { this->inpbuf->decreaseCursor(); }
+
+  void ChatInputHandler::cursorEnd()
+  { this->inpbuf->setCursorToEnd(); }
+
+  void ChatInputHandler::cursorHome()
+  { this->inpbuf->setCursorToBegin(); }
+
+  void ChatInputHandler::exit()
+  {
+    /* b) clear the input buffer */
+    if (this->inpbuf->getSize() > 0)
+      this->inpbuf->clear();
+
+    /* d) stop listening to input  */
+    this->deactivate();
+  }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatInputHandler.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatInputHandler.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatInputHandler.h	(revision 11817)
@@ -0,0 +1,146 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ChatInputHandler_H__
+#define _ChatInputHandler_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+
+#if CEGUI_VERSION >= 0x000800
+#   include <CEGUI/ForwardRefs.h>
+#   include <CEGUI/Colour.h>
+#else
+#   include <CEGUIForwardRefs.h>
+#   include <CEGUIcolour.h>
+#endif
+
+#include "util/Singleton.h"
+#include "chat/ChatListener.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+
+#if CEGUI_VERSION >= 0x000800
+  typedef CEGUI::Colour CEGUIColour;
+#else
+  typedef CEGUI::colour CEGUIColour;
+#endif
+
+  /* class to handle chat using an InputBuffer */
+  class _OrxonoxExport ChatInputHandler  // tolua_export
+    : public Singleton<ChatInputHandler>, public ChatListener
+  { // tolua_export
+    private:
+      /** Input buffer, to be used to catch input from the
+       * keyboard
+       */
+      InputBuffer *inpbuf;
+      int disp_offset, width;
+      bool fullchat;
+
+      /* colors for nickname coloring */
+      static const int NumberOfColors = 10;
+      CEGUIColour text_colors[ NumberOfColors ];
+
+      /** input state */
+      InputState *inputState;
+
+      /** setup input buffer, the constructor calls this */
+      void configureInputBuffer();
+
+      /** adjust display offset depending on cursor position */
+      void sub_adjust_dispoffset( int maxlen, int cursorpos, int inplen );
+
+      /** singleton pointer */
+      static ChatInputHandler* singletonPtr_s;
+
+      /** cegui window handles */
+      CEGUI::Window *input, *inputonly;
+
+      /** cegui handle for the history window */
+      CEGUI::Listbox *lb_history;
+
+      /* methods to deal with colors */
+      void sub_setcolor( CEGUI::ListboxTextItem *tocolor,
+        std::string name );
+
+      void setupColors();
+
+      /* callbacks for input handler */
+      void inputChanged();
+      void addline();
+      void backspace();
+      void deleteChar();
+      void cursorRight();
+      void cursorLeft();
+      void cursorEnd();
+      void cursorHome();
+      void exit();
+
+    public:
+      /** constructor */
+      ChatInputHandler();
+      ~ChatInputHandler();
+      friend class Singleton<ChatInputHandler>;
+
+      static ChatInputHandler& getInstance(void) { return Singleton<ChatInputHandler>::getInstance(); }  // tolua_export
+
+      /** start listening */
+      static void activate_static();
+
+      /** stop listening */
+      static void activate_small_static();
+
+      /** \param message the message text
+       * \param name Name of the player who sent the message
+       *
+       * Deal with incoming chat (which means in our case: Add it to the
+       * history window of the full chat window)
+       */
+      virtual void incomingChat(const std::string& message, const std::string& name) override;
+
+      /** \param full true means show full chat window with history,
+            false means show only an input line
+       *
+       * Show the chat window and redirect the game's keyboard input
+       * into it.
+       */
+      void activate( bool full );
+
+      /** Deactivate the chat window, meaning: hide it. */
+      void deactivate();  // tolua_export
+
+  };  // tolua_export
+
+
+}  // tolua_export
+
+
+#endif /*_ChatInputHandler_H__*/
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatListener.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ChatListener_H__
+#define _ChatListener_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    /**
+        @brief Classes inheriting from this interface get a notification whenever a chat
+        message was sent through ChatManager.
+    */
+    class _OrxonoxExport ChatListener : virtual public Listable
+    {
+        friend class ChatManager;
+
+        public:
+            ChatListener(); // implemented in ChatManager.cc
+            virtual ~ChatListener() {}
+
+        protected:
+            /**
+                @brief Gets called whenever a chat message was sent through ChatManager.
+                @param message The whole message (including name of the sender if available)
+                @param name The name of the sender (if available, otherwise "")
+            */
+            virtual void incomingChat(const std::string& message, const std::string& name) = 0;
+    };
+}
+
+#endif /* _ChatListener_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatManager.cc	(revision 11817)
@@ -0,0 +1,123 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ChatManager.h"
+#include "ChatListener.h"
+
+#include "core/CoreIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "network/Host.h"
+
+#include "PlayerManager.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(ChatManager, ScopeID::ROOT, false);
+
+    SetConsoleCommand("chat", &ChatManager::chat).defaultValue(1, NETWORK_PEER_ID_BROADCAST);
+
+    RegisterAbstractClass(ChatManager).inheritsFrom<NetworkChatListener>();
+
+    ChatManager::ChatManager()
+    {
+        RegisterObject(ChatManager);
+    }
+
+    /**
+        @brief Sends a message (usually gameplay related) without explicit sender to the chat.
+        @param message The message
+        @param targetID The client ID (network) of the receiver. Usually the broadcast ID
+    */
+    /*static*/ void ChatManager::message(const std::string& message, unsigned int targetID)
+    {
+        unsigned int sourceID = NETWORK_PEER_ID_UNKNOWN;
+
+        // only the server should send gameplay messages through the network. otherwise display the message locally
+        if (GameMode::isServer())
+            Host::sendChat(message, sourceID, targetID);
+        else
+            ChatManager::getInstance().incomingChat(message, sourceID);
+    }
+
+    /**
+        @brief Sends a chat message with the client as its sender to the chat.
+        @param message The message
+        @param targetID The client ID (network) of the receiver. Usually the broadcast ID
+    */
+    /*static*/ void ChatManager::chat(const std::string& message, unsigned int targetID)
+    {
+        unsigned int sourceID = Host::getPlayerID();
+
+        // if connected to the network, send chat messages online. otherwise display chat locally
+        if (GameMode::isServer() || GameMode::isClient())
+            Host::sendChat(message, sourceID, targetID);
+        else
+            ChatManager::getInstance().incomingChat(message, sourceID);
+    }
+
+    /**
+        @brief Inherited callback from NetworkChatListener, but gets also called directly
+        by ChatManager itself if the client is offline. Distributes an incoming chat message
+        to all ChatListeners.
+        @param message The message
+        @param sourceID The client ID (network) of the sender
+    */
+    void ChatManager::incomingChat(const std::string& message, unsigned int sourceID)
+    {
+        std::string text = message;
+        std::string name;
+
+        // get the name of the sender and prepend it to the text message
+        if (sourceID != NETWORK_PEER_ID_UNKNOWN)
+        {
+            PlayerInfo* player = PlayerManager::getInstance().getClient(sourceID);
+            if (player)
+            {
+                name = player->getName();
+                text = name + ": " + message;
+            }
+        }
+
+        // notify all listeners
+        for (ChatListener* listener : ObjectList<ChatListener>())
+            listener->incomingChat(text, name);
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////
+    // ChatListener                                                         //
+    //////////////////////////////////////////////////////////////////////////
+    RegisterAbstractClass(ChatListener).inheritsFrom<Listable>();
+
+    ChatListener::ChatListener()
+    {
+        RegisterObject(ChatListener);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/chat/ChatManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/chat/ChatManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/chat/ChatManager.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ChatManager_H__
+#define _ChatManager_H__
+
+#include "OrxonoxPrereqs.h"
+#include "util/Singleton.h"
+#include "network/NetworkChatListener.h"
+
+namespace orxonox
+{
+    /**
+        @brief This class collects and distributes chat messages. If the client is online,
+        all chat messages are sent and received through the network. Otherwise chat is handled
+        directly by this class.
+    */
+    class _OrxonoxExport ChatManager : public Singleton<ChatManager>, public NetworkChatListener
+    {
+        friend class Singleton<ChatManager>;
+
+        public:
+            ChatManager();
+            virtual ~ChatManager() = default;
+
+            static void message(const std::string& message, unsigned int targetID = NETWORK_PEER_ID_BROADCAST);
+            static void chat(const std::string& message, unsigned int targetID = NETWORK_PEER_ID_BROADCAST);
+
+        protected:
+            // non-copyable:
+            ChatManager(const ChatManager&) = delete;
+            ChatManager& operator=(const ChatManager&) = delete;
+
+            virtual void incomingChat(const std::string& message, unsigned int sourceID) override;
+
+            static ChatManager* singletonPtr_s;
+    };
+}
+
+#endif /* _ChatManager_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,5 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  CollisionShape.cc
+  CompoundCollisionShape.cc
+  WorldEntityCollisionShape.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CollisionShape.cc	(revision 11817)
@@ -0,0 +1,294 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CollisionShape.cc
+    @brief Implementation of the CollisionShape class.
+*/
+
+#include "CollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btCollisionShape.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "worldentities/WorldEntity.h"
+#include "CompoundCollisionShape.h"
+#include "WorldEntityCollisionShape.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(CollisionShape).inheritsFrom<BaseObject>().inheritsFrom<Synchronisable>();
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    CollisionShape::CollisionShape(Context* context)
+        : BaseObject(context)
+        , Synchronisable(context)
+    {
+        RegisterObject(CollisionShape);
+
+        this->parent_ = nullptr;
+        this->parentID_ = OBJECTID_UNKNOWN;
+        this->collisionShape_ = nullptr;
+        this->position_ = Vector3::ZERO;
+        this->orientation_ = Quaternion::IDENTITY;
+        this->scale_ = Vector3::UNIT_SCALE;
+        this->uniformScale_ = true;
+
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor. Detaches the CollisionShape from its parent.
+    */
+    CollisionShape::~CollisionShape()
+    {
+        // Detach from parent CompoundCollisionShape.
+        if (this->isInitialized())
+        {
+            if (this->getScene() && this->getScene()->isUpdatingPhysics())
+                orxout(internal_error) << "Don't destroy collision shapes while the physics is updated! This will lead to crashes. Try to use destroyLater() instead" << endl;
+
+            if (this->parent_)
+                this->parent_->detach(this);
+
+            if (this->collisionShape_)
+                delete this->collisionShape_;
+        }
+    }
+
+    void CollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CollisionShape, XMLPort, xmlelement, mode);
+
+        XMLPortParamTemplate(CollisionShape, "position", setPosition, getPosition, xmlelement, mode, const Vector3&);
+        XMLPortParamTemplate(CollisionShape, "orientation", setOrientation, getOrientation, xmlelement, mode, const Quaternion&);
+        XMLPortParamTemplate(CollisionShape, "scale3D", setScale3D, getScale3D, xmlelement, mode, const Vector3&);
+        XMLPortParamLoadOnly(CollisionShape, "scale", setScale, xmlelement, mode);
+        XMLPortParamLoadOnly(CollisionShape, "yaw",   yaw,   xmlelement, mode);
+        XMLPortParamLoadOnly(CollisionShape, "pitch", pitch, xmlelement, mode);
+        XMLPortParamLoadOnly(CollisionShape, "roll",  roll,  xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Register variables that need synchronizing over the network.
+    */
+    void CollisionShape::registerVariables()
+    {
+        // Keep the shape's parent (can be either a CompoundCollisionShape or a WorldEntity) consistent over the network.
+        registerVariable(this->parentID_, VariableDirection::ToClient, new NetworkCallback<CollisionShape>(this, &CollisionShape::parentChanged));
+    }
+
+    /**
+    @brief
+        Notifies the CollisionShape of being attached to a CompoundCollisionShape.
+    @param newParent
+        A pointer to the CompoundCollisionShape the CollisionShape was attached to.
+    @return
+        Returns 
+    */
+    bool CollisionShape::notifyBeingAttached(CompoundCollisionShape* newParent)
+    {
+        // If the CollisionShape is attached to a CompoundCollisionShapes, detach it.
+        if (this->parent_)
+            this->parent_->detach(this);
+
+        this->parent_ = newParent;
+
+        // If the new parent is a WorldEntityCollisionShape, the parentID is set to the objectID of the WorldEntity that is its owner.
+        // TODO: Why?
+        WorldEntityCollisionShape* parentWECCS = orxonox_cast<WorldEntityCollisionShape*>(newParent);
+        if (parentWECCS)
+        {
+            this->parentID_ = parentWECCS->getWorldEntityOwner()->getObjectID();
+
+            // If this shape is not a CompoundCollisionShape (thus an actual physical shape) & the parent is a WorldEntity's CollisionShape,
+            // set it's userPointer to the WorldEntity this CompoundCollisionShape belongs to.
+            if (!orxonox_cast<CompoundCollisionShape*>(this))
+                this->getCollisionShape()->setUserPointer(parentWECCS->getWorldEntityOwner());
+        }
+        else
+        {
+            // Else it is set to the objectID of the CompoundCollisionShape.
+            this->parentID_ = newParent->getObjectID();
+        }
+
+        return true;
+    }
+
+    /**
+    @brief
+        Notifies the CollisionShape of being detached from a CompoundCollisionShape.
+    */
+    void CollisionShape::notifyDetached()
+    {
+        this->parent_ = nullptr;
+        this->parentID_ = OBJECTID_UNKNOWN;
+    }
+
+    /**
+    @brief
+        Updates the CompoundCollisionShape the CollisionShape belongs to (if it belongs to one), after the CollisionShape has changed.
+    */
+    void CollisionShape::updateParent()
+    {
+        if (this->parent_)
+            this->parent_->updateAttachedShape(this);
+    }
+
+    /**
+    @brief
+        Is called when the parentID of the CollisionShape has changed.
+        Attaches it to the object with the changed parentID, which can either be a CompoundCollisionShape or a WorldEntity.
+    */
+    void CollisionShape::parentChanged()
+    {
+        // Get the parent object from the network.
+        Synchronisable* parent = Synchronisable::getSynchronisable(this->parentID_);
+
+        // Parent can either be a WorldEntity or a CompoundCollisionShape. The reason is that the
+        // internal collision shape (which is compound) of a WE doesn't get synchronised.
+        CompoundCollisionShape* parentCCS = orxonox_cast<CompoundCollisionShape*>(parent);
+
+        // If the parent is a CompoundCollisionShape, attach the CollisionShape to it.
+        if (parentCCS)
+            parentCCS->attach(this);
+        else
+        {
+            // If the parent is a WorldEntity, attach the CollisionShape to its collision shapes.
+            WorldEntity* parentWE = orxonox_cast<WorldEntity*>(parent);
+            if (parentWE)
+                parentWE->attachCollisionShape(this);
+        }
+    }
+
+    /**
+    @brief
+        Check whether the CollisionShape has been either moved or rotated or both. (i.e. it doesn't have position zero and identity orientation any more)
+    @return
+        Returns true if it has been moved.
+    */
+    bool CollisionShape::hasTransform() const
+    {
+        return (!this->position_.positionEquals(Vector3(0, 0, 0), 0.001f) ||
+                !this->orientation_.equals(Quaternion(1,0,0,0), Degree(0.1f)));
+    }
+
+    /**
+    @brief
+        Set the scale of the CollisionShape.
+        Since the scale is a vector the CollisionShape can be scaled independently in each direction, allowing for linear distortions.
+        If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+        Beware, non-uniform scaling (i.e. distortions) might not be supported by all CollisionShapes.
+    @param scale
+        The new scale to be set. Vector3::UNIT_SCALE is the initial scale.
+    */
+    void CollisionShape::setScale3D(const Vector3& scale)
+    {
+        if(this->scale_ == scale)
+            return;
+
+        // If the vectors are not in the same direction, then this is no longer a uniform scaling.
+        if(scale_.crossProduct(scale).squaredLength() != 0.0f)
+        {
+            orxout(internal_warning) << "Non-uniform scaling is not yet supported." << endl;
+            return;
+        }
+
+        this->scale_ = scale;
+
+        this->changedScale();
+        this->updateParent();
+    }
+
+    /**
+    @brief
+        Set the (uniform) scale of the CollisionShape.
+        If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+    @param scale
+        The scale to scale the CollisionShape with. 1.0f is the initial scale.
+    */
+    void CollisionShape::setScale(float scale)
+    {
+        if(this->scale_.length() == scale)
+            return;
+
+        this->scale_ = Vector3::UNIT_SCALE*scale;
+
+        this->changedScale();
+        this->updateParent();
+    }
+
+    /**
+    @brief
+        Is called when the scale of the CollisionShape has changed.
+    */
+    void CollisionShape::changedScale()
+    {
+        // Adjust the position of the CollisionShape.
+        this->position_ *= this->getScale3D();
+    }
+
+    /**
+    @brief
+        Updates the shape.
+        Is called when the internal parameters of the shape have changed such that a new shape needs to be created.
+    */
+    void CollisionShape::updateShape()
+    {
+        btCollisionShape* oldShape = this->collisionShape_;
+        this->collisionShape_ = this->createNewShape();
+        // If the CollisionShape has been rescaled, scale the shape to fit the current scale.
+        if(this->scale_ != Vector3::UNIT_SCALE)
+            this->changedScale();
+        // When we recreate the shape, we have to inform the parent about this to update the shape
+        this->updateParent();
+        if (oldShape)
+            delete oldShape;
+    }
+
+    /**
+    @brief
+        Calculates the local inertia of the collision shape.
+    @todo
+        Document.
+    */
+    void CollisionShape::calculateLocalInertia(float mass, btVector3& inertia) const
+    {
+        if (this->collisionShape_)
+            this->collisionShape_->calculateLocalInertia(mass, inertia);
+        else
+            inertia.setValue(0, 0, 0);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CollisionShape.h	(revision 11817)
@@ -0,0 +1,196 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CollisionShape.h
+    @brief Definition of the CollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _CollisionShape_H__
+#define _CollisionShape_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for bullet collision shape class btCollisionShape.
+
+    @author
+        Reto Grieder
+
+    @see btCollisionShape
+    @ingroup Collisionshapes
+    */
+    class _OrxonoxExport CollisionShape : public BaseObject, public Synchronisable
+    {
+        public:
+            CollisionShape(Context* context);
+            virtual ~CollisionShape();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            /**
+            @brief Set the position of the CollisionShape.
+                   If the position changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+            @param position A vector indicating the new position.
+            */
+            inline void setPosition(const Vector3& position)
+                { if(this->position_ == position) return; this->position_ = position; this->updateParent(); }
+            /**
+            @brief Get the position of the CollisionShape.
+            @return Returns the position of the CollisionShape as a vector.
+            */
+            inline const Vector3& getPosition() const
+                { return this->position_; }
+
+            /**
+            @brief Set the orientation of the CollisionShape.
+                   If the orientation changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+            @param orientation A quaternion indicating the new orientation.
+            */
+            inline void setOrientation(const Quaternion& orientation)
+                { if(this->orientation_ == orientation) return; this->orientation_ = orientation; this->updateParent(); }
+            /**
+            @brief Get the orientation of the CollisionShape.
+            @return Returns the orientation of the CollisionShape as a quaternion.
+            */
+            inline const Quaternion& getOrientation() const
+                { return this->orientation_; }
+
+            /**
+            @brief Rotate the CollisionShape around the y-axis by the specified angle.
+                   If the orientation changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+            @param angle The angle by which the CollisionShape is rotated.
+            */
+            void yaw(const Degree& angle)
+                { this->setOrientation(this->orientation_ * Quaternion(angle, Vector3::UNIT_Y)); }
+            /**
+            @brief Rotate the CollisionShape around the x-axis by the specified angle.
+                   If the orientation changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+            @param angle The angle by which the CollisionShape is rotated.
+            */
+            void pitch(const Degree& angle)
+                { this->setOrientation(this->orientation_ * Quaternion(angle, Vector3::UNIT_X)); }
+            /**
+            @brief Rotate the CollisionShape around the z-axis by the specified angle.
+                   If the orientation changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+            @param angle The angle by which the CollisionShape is rotated.
+            */
+            void roll(const Degree& angle)
+                { this->setOrientation(this->orientation_ * Quaternion(angle, Vector3::UNIT_Z)); }
+
+            /**
+            @brief Scale the CollisionShape by the input vector.
+                   Since the scale is a vector the CollisionShape can be scaled independently in each direction, allowing for linear distortions.
+                   If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+                   Beware, non-uniform scaling (i.e. distortions) might not be supported by all CollisionShapes.
+            @param scale The scaling vector by which the CollisionShape is scaled.
+            */
+            inline void scale3D(const Vector3& scale)
+                { this->setScale3D(this->getScale3D()*scale); }
+            void setScale3D(const Vector3& scale); // Set the scale of the CollisionShape.
+            /**
+            @brief Get the scale of the CollisionShape.
+            @return Returns a vector indicating the scale of the CollisionShape.
+            */
+            inline const Vector3& getScale3D() const
+                { return this->scale_; }
+
+            /**
+            @brief (Uniformly) scale the CollisionShape by the input scale.
+                   If the scale changes, this causes the parent CompoundCollisionShape (if there is one) to be updated.
+            @param scale The value by which the CollisionShape is scaled.
+            */
+            inline void scale(float scale)
+                { this->setScale3D(this->getScale3D()*scale); }
+            void setScale(float scale); // Set the (uniform) scale of the CollisionShape.
+            /**
+            @brief Get the (uniform) scale of the CollisionShape.
+                   This is only meaningful if the CollisionShape has uniform scaling.
+            @return Returns the (uniform) scale of the CollisionShape. Returns 0.0f if the scaling is non-uniform.
+            */
+            inline float getScale()
+                { if(this->hasUniformScaling()) return this->scale_.x; return 0.0f; }
+
+            /**
+            @brief Check whether the CollisionShape is uniformly scaled.
+            @return Returns true if the CollisionShape is uniformly scaled, false if not.
+            */
+            inline bool hasUniformScaling()
+                { return this->uniformScale_; }
+            virtual void changedScale(); // Is called when the scale of the CollisionShape has changed.
+
+            void updateShape(); // Updates the shape.
+
+            void calculateLocalInertia(float mass, btVector3& inertia) const; // Calculates the local inertia of the collision shape.
+
+            /**
+            @brief Get the bullet collision shape of this CollisionShape.
+            @return Returns a pointer to the bullet collision shape of this CollisionShape.
+            */
+            inline btCollisionShape* getCollisionShape() const
+                { return this->collisionShape_; }
+
+            bool hasTransform() const; // Check whether the CollisionShape has been either moved or rotated or both.
+
+            bool notifyBeingAttached(CompoundCollisionShape* newParent); // Notifies the CollisionShape of being attached to a CompoundCollisionShape.
+            void notifyDetached(); // Notifies the CollisionShape of being detached from a CompoundCollisionShape.
+
+        protected:
+            virtual void updateParent(); // Updates the CompoundCollisionShape the CollisionShape belongs to, after the CollisionShape has changed.
+            virtual void parentChanged(); // Is called when the parentID of the CollisionShape has changed.
+
+            /**
+            @brief Create a new bullet collision shape depending on the internal parameters of the specific CollisionShape.
+            @return Returns a pointer to the new bullet collision shape.
+            */
+            virtual btCollisionShape* createNewShape() const = 0;
+
+            btCollisionShape*       collisionShape_; //!< The bullet collision shape of this CollisionShape.
+            CompoundCollisionShape* parent_; //!< The CompoundCollisionShape this CollisionShape belongs to, nullptr if it doesn't belong to one.
+            unsigned int            parentID_; //!< The objectID of the parent of this CollisionShape, which can either be a CompoundCollisionShape or a WorldEntity.
+
+        private:
+            void registerVariables();
+
+            Vector3                 position_; //!< The position of the CollisionShape.
+            Quaternion              orientation_; //!< The orientation of the CollisionShape.
+            Vector3                 scale_; //!< The scale of the CollisionShape.
+            bool                    uniformScale_; //!< Whether the scale is uniform.
+    };
+}
+
+#endif /* _CollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CompoundCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CompoundCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CompoundCollisionShape.cc	(revision 11817)
@@ -0,0 +1,301 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CompoundCollisionShape.cc
+    @brief Implementation of the CompoundCollisionShape class.
+*/
+
+#include "CompoundCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btCompoundShape.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "tools/BulletConversions.h"
+
+namespace orxonox
+{
+    RegisterClass(CompoundCollisionShape);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    CompoundCollisionShape::CompoundCollisionShape(Context* context) : CollisionShape(context)
+    {
+        RegisterObject(CompoundCollisionShape);
+
+        this->compoundShape_  = new btCompoundShape();
+    }
+
+    /**
+    @brief
+        Destructor.
+        Deletes all its children.
+    */
+    CompoundCollisionShape::~CompoundCollisionShape()
+    {
+        if (this->isInitialized())
+        {
+            // Delete all children
+            for (const auto& mapEntry : this->attachedShapes_)
+            {
+                // make sure that the child doesn't want to detach itself --> speedup because of the missing update
+                mapEntry.first->notifyDetached();
+                mapEntry.first->destroy();
+                if (this->collisionShape_ == mapEntry.second)
+                    this->collisionShape_ = nullptr; // don't destroy it twice
+            }
+
+            delete this->compoundShape_;
+            if (this->collisionShape_ == this->compoundShape_)
+                this->collisionShape_ = nullptr; // don't destroy it twice
+        }
+    }
+
+    void CompoundCollisionShape::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CompoundCollisionShape, XMLPort, xmlelement, mode);
+        // Attached collision shapes
+        XMLPortObject(CompoundCollisionShape, CollisionShape, "", attach, detach, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Attach the input CollisionShape to the CompoundCollisionShape.
+    @param shape
+        A pointer to the CollisionShape that is to be attached.
+    */
+    void CompoundCollisionShape::attach(CollisionShape* shape)
+    {
+        // If either the input shape is nullptr or we try to attach the CollisionShape to itself.
+        if (!shape || static_cast<CollisionShape*>(this) == shape)
+            return;
+
+        if (this->attachedShapes_.find(shape) != this->attachedShapes_.end())
+        {
+            orxout(internal_warning) << "Attaching a CollisionShape twice is not yet supported." << endl;
+            return;
+        }
+
+        // Notify the CollisionShape that it is being attached to the CompoundCollisionShape.
+        if (!shape->notifyBeingAttached(this))
+            return;
+
+        // Attach it.
+        this->attachedShapes_[shape] = shape->getCollisionShape();
+
+        // Only actually attach if we didn't pick a CompoundCollisionShape with no content.
+        if (shape->getCollisionShape())
+        {
+            btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
+            // Add the btCollisionShape of the CollisionShape as a child shape to the btCompoundShape of the CompoundCollisionShape.
+            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
+
+            this->updatePublicShape();
+        }
+    }
+
+    /**
+    @brief
+        Detach the input CollisionShape form the CompoundCollisionShape.
+    @param shape
+        A pointer to the CollisionShape to be detached.
+    */
+    void CompoundCollisionShape::detach(CollisionShape* shape)
+    {
+        // If the input CollisionShape is actually attached.
+        if (this->attachedShapes_.find(shape) != this->attachedShapes_.end())
+        {
+            this->attachedShapes_.erase(shape);
+            if (shape->getCollisionShape())
+                this->compoundShape_->removeChildShape(shape->getCollisionShape()); // TODO: Apparently this is broken?
+            shape->notifyDetached();
+
+            this->updatePublicShape();
+        }
+        else
+            orxout(internal_warning) << "Cannot detach non child collision shape" << endl;
+    }
+
+    /**
+    @brief
+        Detach all attached CollisionShapes.
+    */
+    void CompoundCollisionShape::detachAll()
+    {
+        while (this->attachedShapes_.size() > 0)
+            this->detach(this->attachedShapes_.begin()->first);
+    }
+
+    /**
+    @brief
+        Update the input CollisionShape that is attached to the CompoundCollisionShape.
+        This is called when the input shape's internal collision shape (a btCollisionShape) has changed.
+    @param shape
+        A pointer to the CollisionShape to be updated.
+    */
+    void CompoundCollisionShape::updateAttachedShape(CollisionShape* shape)
+    {
+        if (!shape)
+            return;
+
+        std::map<CollisionShape*, btCollisionShape*>::iterator it = this->attachedShapes_.find(shape);
+        // Check whether the input shape belongs to this CompoundCollisionShape.
+        if (it == this->attachedShapes_.end())
+        {
+            orxout(internal_warning) << "Cannot update child shape: Instance not a child." << endl;
+            return;
+        }
+
+        // Remove old btCollisionShape, stored in the children map
+        if (it->second)
+            this->compoundShape_->removeChildShape(it->second); // TODO: Apparently this is broken?
+
+        // Only actually attach if we didn't pick a CompoundCollisionShape with no content
+        if (shape->getCollisionShape())
+        {
+            btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
+            this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
+            it->second = shape->getCollisionShape();
+        }
+
+        this->updatePublicShape();
+    }
+
+    /**
+    @brief
+        Updates the public shape, the collision shape this CompoundCollisionShape has to the outside.
+    */
+    void CompoundCollisionShape::updatePublicShape()
+    {
+        btCollisionShape* primitive = nullptr; // The primitive shape, if there is one.
+        bool bPrimitive = true; // Whether the CompoundCollisionShape has just one non-empty CollisionShape. And that shape also has no transformation.
+        bool bEmpty = true; // Whether the CompoundCollisionShape is empty.
+        // Iterate over all CollisionShapes that belong to this CompoundCollisionShape.
+        for (const auto& mapEntry : this->attachedShapes_)
+        {
+            // TODO: Make sure this is correct.
+            if (mapEntry.second)
+            {
+                bEmpty = false;
+                if (!mapEntry.first->hasTransform() && bPrimitive)
+                    primitive = mapEntry.second;
+                else
+                {
+                    bPrimitive = false;
+                    break;
+                }
+            }
+        }
+
+        // If there is no non-empty CollisionShape.
+        if (bEmpty)
+        {
+            // If there was none all along, nothing needs to be changed.
+            if (this->collisionShape_ == nullptr)
+                return;
+            this->collisionShape_ = nullptr;
+        }
+        // If the CompoundCollisionShape is just a primitive.
+        // Only one shape to be added, no transform; return it directly.
+        else if (bPrimitive)
+            this->collisionShape_ = primitive;
+        // Make sure we use the compound shape when returning a btCollisionShape.
+        else
+            this->collisionShape_ = this->compoundShape_;
+
+        this->updateParent();
+    }
+
+    /**
+    @brief
+        Get the attached CollisionShape at the given index.
+    @param index
+        The index of the desired CollisionShape.
+    @return
+        Returns a pointer to the attached CollisionShape at the given index.
+    */
+    CollisionShape* CompoundCollisionShape::getAttachedShape(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (const auto& mapEntry : this->attachedShapes_)
+        {
+            if (i == index)
+                return mapEntry.first;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Is called when the scale of the CompoundCollisionShape has changed.
+        Iterates over all attached CollisionShapes and scales them, then recomputes their compound shape.
+    */
+    void CompoundCollisionShape::changedScale()
+    {
+        CollisionShape::changedScale();
+
+        std::vector<CollisionShape*> shapes;
+        // Iterate through all attached CollisionShapes and add them to the list of shapes.
+        for(const auto& mapEntry : this->attachedShapes_)
+            shapes.push_back(mapEntry.first);
+
+        // Delete the compound shape and create a new one.
+        delete this->compoundShape_;
+        this->compoundShape_ = new btCompoundShape();
+
+        // Re-attach all CollisionShapes.
+        for(CollisionShape* shape : shapes)
+        {
+            shape->setScale3D(this->getScale3D());
+            // Only actually attach if we didn't pick a CompoundCollisionShape with no content.
+            if (shape->getCollisionShape())
+            {
+                btTransform transf(multi_cast<btQuaternion>(shape->getOrientation()), multi_cast<btVector3>(shape->getPosition()));
+                // Add the btCollisionShape of the CollisionShape as a child shape to the btCompoundShape of the CompoundCollisionShape.
+                this->compoundShape_->addChildShape(transf, shape->getCollisionShape());
+            }
+        }
+
+        this->updatePublicShape();
+
+        /*
+        // Iterate through all attached CollisionShapes
+        for(std::map<CollisionShape*, btCollisionShape*>::const_iterator it = this->attachedShapes_.begin(); it != this->attachedShapes_.end(); it++)
+        {
+            // Rescale the CollisionShape.
+            it->first->setScale3D(this->getScale3D());
+            this->updateAttachedShape(it->first);
+        }
+
+        this->updatePublicShape();*/
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CompoundCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CompoundCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/CompoundCollisionShape.h	(revision 11817)
@@ -0,0 +1,84 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file CompoundCollisionShape.h
+    @brief Definition of the CompoundCollisionShape class.
+    @ingroup Collisionshapes
+*/
+
+#ifndef _CompoundCollisionShape_H__
+#define _CompoundCollisionShape_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <cassert>
+#include <map>
+#include "CollisionShape.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Wrapper for the bullet compound collision shape class btCompoundShape.
+
+    @author
+        Reto Grieder
+
+    @see btCompoundShape
+    @ingroup Collisionshapes
+    */
+    class _OrxonoxExport CompoundCollisionShape : public CollisionShape
+    {
+        public:
+            CompoundCollisionShape(Context* context);
+            virtual ~CompoundCollisionShape();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void attach(CollisionShape* shape);
+            void detach(CollisionShape* shape);
+            void detachAll();
+            CollisionShape* getAttachedShape(unsigned int index) const;
+
+            void updateAttachedShape(CollisionShape* shape);
+
+            virtual void changedScale() override;
+
+        private:
+            void updatePublicShape();
+            virtual inline btCollisionShape* createNewShape() const override
+                { assert(false); return nullptr; }
+
+            btCompoundShape* compoundShape_;
+            std::map<CollisionShape*, btCollisionShape*> attachedShapes_;
+    };
+}
+
+#endif /* _CompoundCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/WorldEntityCollisionShape.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/WorldEntityCollisionShape.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/WorldEntityCollisionShape.cc	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WorldEntityCollisionShape.h"
+
+#include <BulletCollision/CollisionShapes/btCompoundShape.h>
+
+#include "util/OrxAssert.h"
+#include "core/CoreIncludes.h"
+#include "worldentities/WorldEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(WorldEntityCollisionShape);
+
+    WorldEntityCollisionShape::WorldEntityCollisionShape(Context* context) : CompoundCollisionShape(context)
+    {
+        RegisterObject(WorldEntityCollisionShape);
+
+        this->worldEntityOwner_ = nullptr;
+        // suppress synchronisation
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    void WorldEntityCollisionShape::updateParent()
+    {
+        // Note: This shape may also be attached to a CompoundCollisionShape because it's hosting
+        // WorldEntity has been attached to another one.
+        CollisionShape::updateParent();
+
+        assert(this->worldEntityOwner_ != nullptr);
+        this->worldEntityOwner_->notifyCollisionShapeChanged();
+    }
+
+    void WorldEntityCollisionShape::parentChanged()
+    {
+        // This object does not get synchronised. This method should never be called then!
+        OrxAssert(false, "parentChanged has been called on a non synchronised WorldEntityCollisionShape!");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/WorldEntityCollisionShape.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/WorldEntityCollisionShape.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/collisionshapes/WorldEntityCollisionShape.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WorldEntityCollisionShape_H__
+#define _WorldEntityCollisionShape_H__
+
+#include "OrxonoxPrereqs.h"
+#include "CompoundCollisionShape.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport WorldEntityCollisionShape : public CompoundCollisionShape
+    {
+        public:
+            WorldEntityCollisionShape(Context* context);
+
+            inline void setWorldEntityOwner(WorldEntity* worldEntityOwner)
+                { this->worldEntityOwner_ = worldEntityOwner; }
+            inline WorldEntity* getWorldEntityOwner() const
+                { return this->worldEntityOwner_; }
+
+        protected:
+            virtual void updateParent() override;
+
+        private:
+            virtual void parentChanged() override;
+
+            WorldEntity* worldEntityOwner_;
+    };
+}
+
+#endif /* _WorldEntityCollisionShape_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/AIController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/AIController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/AIController.cc	(revision 11817)
@@ -0,0 +1,325 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Dominik Solenicki
+ *
+ */
+
+#include "AIController.h"
+
+#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    const float AIController::ACTION_INTERVAL = 1.0f;
+
+    RegisterClass(AIController);
+
+    AIController::AIController(Context* context) : ArtificialController(context)
+    {
+        RegisterObject(AIController);
+
+        this->actionTimer_.setTimer(ACTION_INTERVAL, true, createExecutor(createFunctor(&AIController::action, this)));
+    }
+
+    AIController::~AIController()
+    {
+    }
+
+    void AIController::action()
+    {
+        float random;
+        float maxrand = 100.0f / ACTION_INTERVAL;
+
+        if (this->state_ == FREE)
+        {
+            
+            if (this->formationFlight_)
+            {
+
+                //changed order -> searchNewMaster MUSTN'T be called in SLAVE-state (bugfix for internal-error messages at quit)
+                random = rnd(maxrand);
+                if (random < 90 && (((!this->target_) || (random < 50 && this->target_)) && !this->forcedFree()))
+                       this->searchNewMaster();
+
+                // return to Master after being forced free
+                if (this->freedomCount_ == 1)
+                {
+                    this->state_ = SLAVE;
+                    this->freedomCount_ = 0;
+                }
+            }
+
+            this->defaultBehaviour(maxrand);
+
+        }
+
+        if (this->state_ == SLAVE && this->formationMode_ == ATTACK) 
+        {
+            // search enemy
+            random = rnd(maxrand);
+            if (random < (botlevel_*100) && (!this->target_))
+                this->searchNewTarget();
+
+            // next enemy
+            random = rnd(maxrand);
+            if (random < (botlevel_*30) && (this->target_))
+                this->searchNewTarget();
+
+            // shoot
+            random = rnd(maxrand);
+            if (!(this->passive_) && random < (botlevel_*100) && (this->target_ && !this->bShooting_))
+                this->bShooting_ = true;
+
+            // stop shooting
+            random = rnd(maxrand);
+            if (random < (1-botlevel_)*50 && (this->bShooting_))
+                this->bShooting_ = false;
+
+        }
+
+        if (this->state_ == MASTER)
+        {
+            this->commandSlaves();
+
+            if  (this->specificMasterAction_ != NONE)
+                    this->specificMasterActionHold();
+
+            else {
+
+                 // make 180 degree turn - a specific Master Action
+                random = rnd(1000.0f);
+                if (random < 5)
+                   this->turn180Init();
+
+                // spin around - a specific Master Action
+                random = rnd(1000.0f);
+                if (random < 5)
+                   this->spinInit();
+
+                /*// follow a randomly chosen human - a specific Master Action
+                random = rnd(1000.0f);
+                if (random < 1)
+                   this->followRandomHumanInit();
+*/
+                 // lose master status (only if less than 4 slaves in formation)
+                random = rnd(maxrand);
+                if(random < 15/(this->slaves_.size()+1) && this->slaves_.size() < 4 )
+                   this->loseMasterState();
+
+                // look out for outher masters if formation is small
+                random = rnd(maxrand);
+                if(this->slaves_.size() < 3 && random < 20)
+                    this->searchNewMaster();
+
+                this->defaultBehaviour(maxrand);
+
+            }
+        }
+
+    }
+
+    void AIController::tick(float dt)
+    {
+        if (!this->isActive())
+            return;
+
+        float random;
+        float maxrand = 100.0f / ACTION_INTERVAL;
+        ControllableEntity* controllable = this->getControllableEntity();
+        //DOES: Either move to the waypoint or search for a Point of interest
+        if (controllable && this->mode_ == DEFAULT)// bot is ready to move to a target
+        {
+            if (this->waypoints_.size() > 0 ) //Waypoint functionality.
+            {
+                WorldEntity* wPoint = this->waypoints_[this->waypoints_.size()-1];
+                if(wPoint)
+                {
+                    this->moveToPosition(wPoint->getWorldPosition()); //BUG ?? sometime wPoint->getWorldPosition() causes crash
+                    if (wPoint->getWorldPosition().squaredDistance(controllable->getPosition()) <= this->squaredaccuracy_)
+                        this->waypoints_.pop_back(); // if goal is reached, remove it from the list
+                }
+                else
+                    this->waypoints_.pop_back(); // remove invalid waypoints
+
+            }
+            else if(this->defaultWaypoint_ && ((this->defaultWaypoint_->getPosition()-controllable->getPosition()).length()  > 200.0f))
+            {
+                this->moveToPosition(this->defaultWaypoint_->getPosition()); // stay within a certain range of the defaultWaypoint_
+                random = rnd(maxrand);
+            }
+        }
+
+        if (this->mode_ == DEFAULT)
+        {
+            if (this->state_ == MASTER)
+            {
+                if (this->specificMasterAction_ ==  NONE)
+                {
+                    if (this->target_)
+                    {
+                        if (!this->target_->getRadarVisibility()) /* So AI won't shoot invisible Spaceships */
+                            this->forgetTarget();
+                        else
+                        {
+                            this->aimAtTarget();
+                            random = rnd(maxrand);
+                            if(this->botlevel_*70 > random && !this->isCloseAtTarget(100))
+                                this->follow();  //If a bot is shooting a player, it shouldn't let him go away easily.
+                        }
+                    }
+
+                    if (this->bHasTargetPosition_)
+                        this->moveToTargetPosition();
+                    this->doFire();
+                }
+
+                if (this->specificMasterAction_  == TURN180)
+                    this->turn180();
+
+                if (this->specificMasterAction_ == SPIN)
+                    this->spin();
+                if (this->specificMasterAction_ == FOLLOW)
+                    this->follow();
+            }
+
+            if (this->state_ == SLAVE && this->formationMode_ != ATTACK)
+            {
+                if (this->bHasTargetPosition_)
+                    this->moveToTargetPosition();
+            }
+
+            if (this->state_ == FREE || (this->state_==SLAVE && this->formationMode_ == ATTACK) )
+            {
+                if (this->target_)
+                {
+                    if (!this->target_->getRadarVisibility()) /* So AI won't shoot invisible Spaceships */
+                        this->forgetTarget();
+                    else this->aimAtTarget();
+                }
+
+                if (this->bHasTargetPosition_)
+                    this->moveToTargetPosition();
+
+                    this->doFire();
+            }
+        }
+        else if (this->mode_ == ROCKET)//Rockets do not belong to a group of bots -> bot states are not relevant.
+        {   //Vector-implementation: mode_.back() == ROCKET;
+            if(controllable)
+            {//Check wether the bot is controlling the rocket and if the timeout is over.
+                if(controllable->getIdentifier() == ClassByString("Rocket"))
+
+                {
+                    this->follow();
+                    this->timeout_ -= dt;
+                    if((timeout_< 0)||(!target_))//Check if the timeout is over or target died.
+                    {
+                       controllable->fire(0);//kill the rocket
+                       this->setPreviousMode();//get out of rocket mode
+                    }
+                }
+                else
+                    this->setPreviousMode();//no rocket entity -> get out of rocket mode
+            }
+            else
+                this->setPreviousMode();//If bot dies -> getControllableEntity == nullptr -> get out of ROCKET mode
+        }//END_OF ROCKET MODE
+
+        SUPER(AIController, tick, dt);
+    }
+//**********************************************NEW
+    void AIController::defaultBehaviour(float maxrand)
+    {       float random;
+            // search enemy
+            random = rnd(maxrand);
+            if (random < (botlevel_* 100) && (!this->target_))
+                this->searchNewTarget();
+
+            // forget enemy
+            random = rnd(maxrand);
+            if (random < ((1-botlevel_)*20) && (this->target_))
+                this->forgetTarget();
+
+            // next enemy
+            random = rnd(maxrand);
+            if (random < (botlevel_*30) && (this->target_))
+                this->searchNewTarget();
+
+            // fly somewhere
+            random = rnd(maxrand);
+            if (random < 50 && (!this->bHasTargetPosition_ && !this->target_))
+                this->searchRandomTargetPosition();
+
+            // stop flying
+            random = rnd(maxrand);
+            if (random < 10 && (this->bHasTargetPosition_ && !this->target_))
+                this->bHasTargetPosition_ = false;
+
+            // fly somewhere else
+            random = rnd(maxrand);
+            if (random < 30 && (this->bHasTargetPosition_ && !this->target_))
+                this->searchRandomTargetPosition();
+
+            if (this->state_ == MASTER) // master: shoot
+            {
+                random = rnd(maxrand);
+                if (!(this->passive_) && random < (100*botlevel_) && (this->target_ && !this->bShooting_))
+                {
+                    this->bShooting_ = true;
+                    this->forceFreeSlaves();
+                }
+            }
+            else
+            {
+                // shoot
+                random = rnd(maxrand);
+                if (!(this->passive_) && random < (botlevel_*100) && (this->target_ && !this->bShooting_))
+                    this->bShooting_ = true;
+            }
+
+            // stop shooting
+            random = rnd(maxrand);
+            if (random < ((1 - botlevel_)*50) && (this->bShooting_))
+                this->bShooting_ = false;
+
+            // boost
+            random = rnd(maxrand);
+            if (random < botlevel_*50 )
+                this->boostControl();
+
+            // update Checkpoints
+            /*random = rnd(maxrand);
+            if (this->defaultWaypoint_ && random > (maxrand-10))
+                this->manageWaypoints();
+            else //if(random > maxrand-10) //CHECK USABILITY!!*/
+            if (this->waypoints_.size() == 0 )
+                this->manageWaypoints();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/AIController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/AIController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/AIController.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _AIController_H__
+#define _AIController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "tools/Timer.h"
+#include "tools/interfaces/Tickable.h"
+#include "ArtificialController.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport AIController : public ArtificialController, public Tickable
+    {
+        public:
+            AIController(Context* context);
+            virtual ~AIController();
+
+            virtual void tick(float dt) override; //<! Carrying out the targets set in action().
+
+        protected:
+            virtual void action(); //<! action() is called in regular intervals managing the bot's behaviour ~ setting targets.
+            void defaultBehaviour(float maxrand); //<! Helper function for code reusage. Some concrete commands for a bot.
+
+        private:
+            static const float ACTION_INTERVAL;
+
+            Timer actionTimer_; //<! Regularly calls action().
+    };
+}
+
+#endif /* _AIController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ActionpointController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ActionpointController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ActionpointController.cc	(revision 11817)
@@ -0,0 +1,670 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ActionpointController.h"
+
+#include "core/XMLPort.h"
+#include <algorithm>
+#include "worldentities/Actionpoint.h"
+namespace orxonox
+{
+
+    RegisterClass(ActionpointController);
+
+    ActionpointController::ActionpointController(Context* context) : FightingController(context)
+    {
+        this->ticks_ = 0;
+        this->bPatrolling_ = false;
+        this->bInLoop_ = false;
+        this->bLoop_ = false;
+        this->bEndLoop_ = false;
+        loopActionpoints_.clear();
+        parsedActionpoints_.clear();
+        actionpoints_.clear();
+        this->bTakenOver_ = false;
+        this->action_ = Action::NONE;
+        this->squaredaccuracy_ = 2500;
+        this->bStartedDodging_ = false;
+        this->bDefaultPatrol_ = true;
+        this->bDefaultFightAll_ = true;
+        RegisterObject(ActionpointController);
+
+    }
+    void ActionpointController::XMLPort( Element& xmlelement, XMLPort::Mode mode )
+    {
+        SUPER( ActionpointController, XMLPort, xmlelement, mode );
+
+        XMLPortObject(ActionpointController, WorldEntity, "actionpoints", addActionpoint, getActionpoint,  xmlelement, mode);
+        XMLPortParam(ActionpointController, "defaultFightAll", setDefaultFightAll, getDefaultFightAll, xmlelement, mode).defaultValues(true);
+        XMLPortParam(ActionpointController, "defaultPatrol", setDefaultPatrol, getDefaultPatrol, xmlelement, mode).defaultValues(true);
+    }
+
+    ActionpointController::~ActionpointController()
+    {
+        loopActionpoints_.clear();
+        parsedActionpoints_.clear();
+        actionpoints_.clear();
+
+    }
+    void ActionpointController::tick(float dt)
+    {
+        if (!this->getControllableEntity() || !this->isActive())
+            return;
+
+        //count ticks, ticks_ is unsigned, so overflow is not a problem
+        ++this->ticks_;
+        if (this->ticks_ == 1)
+        {
+            //those vectors are in reversed order after being set by XML.
+            std::reverse(parsedActionpoints_.begin(), parsedActionpoints_.end());
+            std::reverse(actionpoints_.begin(), actionpoints_.end());
+        }
+
+        //fly
+        if (this->bHasTargetPosition_)
+        {
+            this->moveToTargetPosition(dt);
+        }//or just rotate
+        else if (this->bLookAtTarget_)
+        {
+            this->lookAtTarget(dt);
+        }
+        
+        //don't fire rocket each tick
+        if (timeout_ <= 0)
+        {    
+            this->bFiredRocket_ = false;
+        }
+        else if (this->bFiredRocket_)
+        {
+            --this->timeout_;
+        }
+
+        //sometimes dodge, sometimes attack
+        if (this->ticks_ % 80 <= 10)
+        {
+            this->bDodge_ = false;
+        }
+        else
+        {
+            this->bDodge_ = true;
+        }
+
+        //fire if you can
+        if (this->bShooting_)
+        {
+            this->doFire();
+        }
+        SUPER(ActionpointController, tick, dt);
+    }
+     
+    /**
+    @brief
+        action() manages the state machine.
+    */
+
+    void ActionpointController::action()
+    {
+        if (!this->getControllableEntity() || !this->isActive())
+            return;
+
+        //deltaHp is used to know if this got attacked
+        this->deltaHp = orxonox_cast<Pawn*> (this->getControllableEntity())->getHealth() - this->previousHp;
+        this->previousHp = orxonox_cast<Pawn*> (this->getControllableEntity())->getHealth();
+
+        //look out for enemies
+        if (this->bDefaultPatrol_ || (this->action_ != Action::FLY && this->action_ != Action::NONE))
+        {
+            this->startAttackingEnemiesThatAreClose();
+        }
+
+        //No action -> pop one from stack
+        if (this->action_ == Action::NONE || this->bTakenOver_)
+        {
+            //if default behaviour is fighting all, push it onto the stack
+            if (this->parsedActionpoints_.empty() && this->loopActionpoints_.empty() && this->bDefaultFightAll_)
+            {
+                Point p = { Action::FIGHTALL, "", Vector3::ZERO, false };
+                this->parsedActionpoints_.push_back (p);
+            }
+            this->executeActionpoint();
+            this->bTakenOver_ = false;
+        }
+
+        //Action fightall -> fight till nobody alive
+        if (this->action_ == Action::FIGHTALL)
+        {
+
+            if (!this->hasTarget())
+            {
+                ControllableEntity* newTarget = this->closestTarget();    
+                if (newTarget)
+                {
+                    this->setAction (Action::FIGHTALL, newTarget);
+                }
+                else
+                {
+                    this->nextActionpoint();
+                    this->executeActionpoint();
+    
+                }
+            }
+        }
+        //Action fight -> fight as long as enemies in range
+        else if (this->action_ == Action::FIGHT)
+        {
+            if (!this->hasTarget() )
+            {
+                //----find a target----
+                ControllableEntity* newTarget = this->closestTarget();
+                if (newTarget && 
+                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
+                {
+                    this->setAction (Action::FIGHT, newTarget);
+                }
+                else
+                {
+                    this->nextActionpoint();
+                    this->executeActionpoint();
+                }
+            }
+            else if (this->hasTarget())
+            {
+                //----fly in formation if far enough----
+                Vector3 diffVector = this->positionOfTarget_ - this->getControllableEntity()->getWorldPosition();         
+                    
+                if (diffVector.length() > this->attackRange_)
+                {
+                    ControllableEntity* newTarget = this->closestTarget();
+                    if (newTarget && 
+                        CommonController::distance (this->getControllableEntity(), newTarget) < this->attackRange_)
+                    {
+                        this->setAction (Action::FIGHT, newTarget);
+                    }
+                    else
+                    {
+                        this->nextActionpoint();
+                        this->executeActionpoint();
+                    }
+                }
+            }
+        }
+        else if (this->action_ == Action::FLY)
+        {
+            if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
+            {
+                this->nextActionpoint();   
+                this->executeActionpoint();
+            }
+        }
+        else if (this->action_ == Action::PROTECT)
+        {
+            if (!this->getProtect())
+            {
+                this->nextActionpoint();
+                this->executeActionpoint(); 
+            }
+            this->stayNearProtect();
+        }
+        else if (this->action_ == Action::ATTACK)
+        {   
+            if (!this->hasTarget())
+            {
+                this->nextActionpoint();
+                this->executeActionpoint();
+            }
+        }
+    }
+    /**
+    @brief
+        if action is protect, this follows protect_ and fights enemies that are close
+    */
+    void ActionpointController::setProtect (ControllableEntity* protect)
+    {
+        this->protect_ = protect;
+    }
+    ControllableEntity* ActionpointController::getProtect ()
+    {
+        return this->protect_;
+    }
+    //XML method
+    void ActionpointController::addActionpoint(WorldEntity* actionpoint)
+    {
+        std::string actionName;
+        Vector3 position;
+        std::string targetName;
+        bool inLoop = false;
+        Point p;
+        if (actionpoint->getIdentifier()->getName() == "Actionpoint")
+        {
+            Actionpoint* ap = orxonox_cast<Actionpoint*> (actionpoint);
+            actionName = ap->getActionXML();
+            targetName = ap->getName();
+            position = ap->getWorldPosition();
+
+            if (this->bEndLoop_)
+            {
+                this->bInLoop_ = false;
+            }
+            if (!this->bInLoop_ && ap->getLoopStart())
+            {
+                this->bInLoop_ = true;
+            }
+            if (this->bInLoop_ && ap->getLoopEnd())
+            {
+                this->bEndLoop_ = true;
+            }
+            inLoop = this->bInLoop_;
+
+            Action value;
+            
+            if ( actionName == "FIGHT" )
+            { value = Action::FIGHT; }
+            else if ( actionName == "FLY" )
+            { value = Action::FLY; }
+            else if ( actionName == "PROTECT" )
+            { value = Action::PROTECT; }
+            else if ( actionName == "NONE" )
+            { value = Action::NONE; }
+            else if ( actionName == "FIGHTALL" )
+            { value = Action::FIGHTALL; }
+            else if ( actionName == "ATTACK" )
+            { value = Action::ATTACK; }
+            else
+                ThrowException( ParseError, std::string( "Attempting to set an unknown Action: '" )+ actionName + "'." );
+            p.action = value; p.name = targetName; p.position = position; p.inLoop = inLoop;
+        }
+        else
+        {
+            inLoop = true;
+            p.action = Action::FLY; p.name = ""; p.position = actionpoint->getWorldPosition(); p.inLoop = inLoop;
+        }
+            parsedActionpoints_.push_back(p);
+            this->actionpoints_.push_back(actionpoint);
+    }
+    //XML method
+    WorldEntity* ActionpointController::getActionpoint(unsigned int index) const
+    {
+        if (index < this->actionpoints_.size())
+            return this->actionpoints_[index];
+        else
+            return nullptr;
+    }
+    //XML method
+    Action ActionpointController::getAction ()
+    {
+        return this->action_;
+    }
+    //XML method
+    std::string ActionpointController::getActionName()
+    {
+        switch ( this->action_ )
+        {
+            case Action::FIGHT:
+            { return "FIGHT"; }
+            case Action::FLY:
+            { return "FLY"; }
+            case Action::PROTECT:
+            { return "PROTECT"; }
+            case Action::NONE:
+            { return "NONE"; }
+            case Action::FIGHTALL:
+            { return "FIGHTALL"; }
+            case Action::ATTACK:
+            { return "ATTACK"; }
+            default:
+                return "NONE";
+                break;
+        }
+    }
+    //XML method
+    void ActionpointController::setAction (Action action)
+    {
+        this->action_ = action;
+    }
+    //set action and target/protect
+    void ActionpointController::setAction (Action action, ControllableEntity* target)
+    {
+        if (!this->getControllableEntity())
+            return;
+        this->action_ = action;
+        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
+        {   
+            if (target)
+                this->setTarget (target);
+        }
+        else if (action == Action::PROTECT)
+        {
+            if (target)
+                this->setProtect (target);
+        }
+    }
+    //set action and target position
+    void ActionpointController::setAction (Action action, const Vector3& target)
+    {
+        if (!this->getControllableEntity())
+            return;
+        this->action_ = action;
+        if (action == Action::FLY)
+        {
+            this->setTargetPosition (target);
+        }
+    }
+    //set action and target position and orientation
+    void ActionpointController::setAction (Action action, const Vector3& target,  const Quaternion& orient )
+    {
+        if (!this->getControllableEntity())
+            return;
+        this->action_ = action;
+        if (action == Action::FLY)
+        {
+            this->setTargetPosition (target);
+            this->setTargetOrientation (orient);
+        }  
+    }
+    
+    //------------------------------------------------------------------------------
+    //------------------------------Actionpoint methods-----------------------------
+    //------------------------------------------------------------------------------
+
+    //POST: this starts doing what was asked by the last element of parsedActionpoints_,
+    //if last element was failed to be parsed, next element will be executed.
+    void ActionpointController::executeActionpoint()
+    {
+        if (!this->getControllableEntity())
+            return;
+
+        Point p;
+        if (this->bLoop_ && !loopActionpoints_.empty())
+        {
+            p = loopActionpoints_.back();
+        }
+        else if (this->bLoop_)
+        {
+            this->bLoop_ = false;
+            return;
+        }
+        else if (!this->bLoop_ && !parsedActionpoints_.empty())
+        {
+            p = parsedActionpoints_.back();
+        }
+        else
+        {
+            this->setTarget(nullptr);
+            this->setTargetPosition(this->getControllableEntity()->getWorldPosition());
+            this->action_ = Action::NONE;
+            return;
+        }
+        if (!this->bLoop_ && this->parsedActionpoints_.back().inLoop)
+        {
+            //MOVES all points that are in loop to a loop vector
+            this->fillLoop();
+            this->bLoop_ = true;
+            executeActionpoint();
+            return;
+        }
+        this->setAction (p.action);
+
+        switch (this->action_)
+        {
+            case Action::FIGHT:
+            {
+                std::string targetName = p.name;
+                if (targetName == "")
+                    break;
+                for (Pawn* pawn : ObjectList<Pawn>())
+                {
+                    if (CommonController::getName(pawn) == targetName)
+                    {
+                        this->setTarget (static_cast<ControllableEntity*>(pawn));
+                    }
+                }
+                break;
+            }
+            case Action::FLY:
+            {
+                this->setTargetPosition( p.position );
+                if (this->squaredDistanceToTarget() <= this->squaredaccuracy_)
+                {
+                    this->nextActionpoint();
+                    this->executeActionpoint();
+                }
+                break;
+            }
+            case Action::PROTECT:
+            {
+
+                std::string protectName = p.name;
+                if (protectName == "reservedKeyword:human")
+                {
+                    for (Pawn* pawn : ObjectList<Pawn>())
+                    {
+                        if (orxonox_cast<ControllableEntity*>(pawn) && (pawn->getController()) && (pawn->getController()->getIdentifier()->getName() == "NewHumanController"))
+                        {
+                            this->setProtect (static_cast<ControllableEntity*>(pawn));
+                        }
+                    }
+                }
+                else
+                {
+                    for (Pawn* pawn : ObjectList<Pawn>())
+                    {
+                        if (CommonController::getName(pawn) == protectName)
+                        {
+                            this->setProtect (static_cast<ControllableEntity*>(pawn));
+                        }
+                    }                            
+                }
+                if (!this->getProtect())
+                {
+                    this->nextActionpoint();
+                    this->executeActionpoint();
+                }
+                break;
+            }
+            case Action::NONE:
+            {
+                break;
+            }
+            case Action::FIGHTALL:
+            {
+                break;
+            }
+            case Action::ATTACK:
+            {
+                std::string targetName = p.name;
+
+                for (Pawn* pawn : ObjectList<Pawn>())
+                {
+                    if (CommonController::getName(pawn) == targetName)
+                    {
+                        this->setTarget (static_cast<ControllableEntity*>(pawn));
+                    }
+                }
+                if (!this->hasTarget())
+                {
+                    this->nextActionpoint();
+                    this->executeActionpoint();
+                }
+                break;
+            }
+            default:
+                break;
+        }   
+    }
+
+    //calculate where in world coordinates this ship has to be, so that it keeps distance to protect_, and fly there
+    void ActionpointController::stayNearProtect()
+    {
+        if (!this->getControllableEntity())
+            return;
+
+        Vector3 targetRelativePosition(0, 300, 300);
+        if (!this->getProtect())
+        {
+            this->nextActionpoint();
+            return;
+        }  
+        Vector3 targetAbsolutePosition = ((this->getProtect()->getWorldPosition()) + 
+            (this->getProtect()->getWorldOrientation()* (targetRelativePosition)));
+        this->setTargetPosition(targetAbsolutePosition);
+        if (!this->getProtect())
+        {
+            this->nextActionpoint();
+            return;
+        }  
+        this->setTargetOrientation(this->getProtect()->getWorldOrientation());
+    }
+    //remove current point from the stack
+    void ActionpointController::nextActionpoint()
+    {
+        if (this->bLoop_)
+        {
+            if (this->bPatrolling_)
+            {
+                this->loopActionpoints_.pop_back();
+                this->bPatrolling_ = false;
+            }
+            else if (!this->loopActionpoints_.empty())
+            {
+                this->moveBackToTop();
+            }
+        }
+        else
+        {
+            if (!this->parsedActionpoints_.empty())
+            {
+                this->parsedActionpoints_.pop_back();
+            }            
+        }
+        this->setAction(Action::NONE);
+        this->bHasTargetPosition_ = false;
+    }
+    //if looping, instead of erasing point, move it to the top (back is what gets executed, so it's kinda reversed stack)
+    void ActionpointController::moveBackToTop()
+    {
+        if (!this->getControllableEntity())
+            return;
+
+        Point temp = loopActionpoints_.back();
+        loopActionpoints_.pop_back();
+        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
+        loopActionpoints_.push_back(temp);
+        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
+    }
+    //POST: moves all consecutive points that are in loop to the loop stack
+    void ActionpointController::fillLoop()
+    {
+        loopActionpoints_.clear();
+        fillLoopReversed();
+        std::reverse (loopActionpoints_.begin(), loopActionpoints_.end());
+    }
+    void ActionpointController::fillLoopReversed()
+    {
+        if (parsedActionpoints_.back().inLoop)
+        {
+            loopActionpoints_.push_back(parsedActionpoints_.back());
+            parsedActionpoints_.pop_back();
+        }
+        if (parsedActionpoints_.back().inLoop)
+        {
+            fillLoopReversed();
+        }
+    }
+    //copy other ship's stacks so that if it dies, this can finish that ship's actions
+    void ActionpointController::takeActionpoints (const std::vector<Point>& vector, const std::vector<Point>& loop, bool b)
+    {
+        if (!this->getControllableEntity())
+            return;
+        this->parsedActionpoints_ = vector;
+        this->loopActionpoints_ = loop;
+        this->bLoop_ = b;
+        this->bTakenOver_ = true;
+    }
+    //attack closest target
+    void ActionpointController::setClosestTarget()
+    {
+        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
+    }
+    //find closest target
+    Pawn* ActionpointController::closestTarget()
+    {
+        if (!this->getControllableEntity())
+            return nullptr;
+
+        Pawn* closestTarget = nullptr;
+        float minDistance =  std::numeric_limits<float>::infinity();
+        Gametype* gt = this->getGametype();
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(pawn), gt) )
+                continue;
+
+            float distance = CommonController::distance (pawn, this->getControllableEntity());
+            if (distance < minDistance)
+            {
+                closestTarget = pawn;
+                minDistance = distance;
+            }
+        }
+        if (closestTarget)
+        {
+           return closestTarget;
+        } 
+        return nullptr;
+    }
+    //push action FIGHT to the stack and set target to the closest enemy
+    void ActionpointController::startAttackingEnemiesThatAreClose()
+    {
+        if (!this->getControllableEntity())
+            return;
+        
+        if (!this->target_ || (this->target_ && CommonController::distance (this->getControllableEntity(), this->target_) > this->attackRange_))
+        {
+            Pawn* newTarget = this->closestTarget();
+            if ( newTarget && 
+                CommonController::distance (this->getControllableEntity(), static_cast<ControllableEntity*>(newTarget))
+                    <= this->attackRange_ )
+            {
+                this->setTarget(newTarget);
+                if (this->bLoop_ && !this->bPatrolling_)
+                {
+                    Point p = { Action::FIGHT, "", Vector3::ZERO, true };
+                    this->loopActionpoints_.push_back(p);
+                }
+                else if (!this->bPatrolling_)
+                {
+                    Point p = { Action::FIGHT, "", Vector3::ZERO, false };
+                    this->parsedActionpoints_.push_back(p);
+                }
+                this->bPatrolling_ = true;
+                this->executeActionpoint();
+            }
+        }
+    }
+}   
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ActionpointController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ActionpointController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ActionpointController.h	(revision 11817)
@@ -0,0 +1,255 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ActionpointController_H__
+#define _ActionpointController_H__
+
+#include "controllers/FightingController.h"
+#include "tools/Timer.h"
+#include "tools/interfaces/Tickable.h"
+#include <map>
+
+namespace orxonox
+{
+    /**
+    @brief
+        ActionpointController is a state machine with states:
+            1) NONE
+            2) FLY: fly towards a point
+            3) FIGHT: fight enemies that are in attackRange_ (see FightingController)
+            4) PROTECT: follow this->protect_
+            5) FIGHTALL: fight all enemies on the map
+            6) ATTACK: fight a specific spaceship
+        This controller always executes an action that is in the back of the vector being used.
+        After current this->action_ is completed, next action becomes the top action (one that will
+        be returned by someVector.back()), and current action either will be removed (if not looping),
+        or moved to the top (if looping).
+
+        Every second action(), which is once in two seconds, this searches the area for enemies that are in attack range, if finds anyone,
+        pushes Action::FIGHT to the stack. That makes spaceship fight enemies inside of a sphere, and when all enemies in range are dead,
+        Action::FIGHT is removed from the stack, and spaceship resumes doing whatever action was being executed before.
+
+        In XML one has to attack Actionpoints in order to achieve any complex behaviour, but in Controller all actionpoints are effectively 
+        being stored in an array of type Point::Value.
+    @note
+        ActionpointController will not work, if there is no MasterController in the level!
+        All the demos are in a file called AITest.oxw. In the menu look for New AI Testing Level.
+    */
+    enum class Action
+    {  
+        NONE, FLY, FIGHT, PROTECT, FIGHTALL, ATTACK
+    };
+    
+    struct Point {
+        Action action;
+        std::string name;
+        Vector3 position;
+        bool inLoop;
+    };
+
+    class _OrxonoxExport ActionpointController : public FightingController, public Tickable
+    {
+        public:
+           
+            ActionpointController(Context* context);
+            virtual ~ActionpointController();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+               
+            /**
+            @brief
+                tick is called every tick by Game (?).
+                In tick ship flies and fires.
+            */
+            virtual void tick(float dt) override;
+            /**
+            @brief
+                XML method, example XML usage:
+
+                @code
+                <SpaceShip position="-2000, 1500, -1000" lookat="0,0,0" team=0 name="ss2">
+                  <templates>
+                    <Template link=spaceshipassff />
+                  </templates>
+                  <controller>
+                    <DivisionController team=0 formationMode="finger4">
+                      <actionpoints>
+                        <Actionpoint position="0,0,0" action="FLY" /> 
+                        <Actionpoint position="-1000,750,-500" action="ATTACK" attack="attack" />
+                        <Actionpoint position="-1000,750,-500" action="PROTECt" protectMe=true />
+                        <Actionpoint position="-1000,750,-500" action="PROTECt" protect="protect" /> 
+                        <Actionpoint position="-1000,750,-500" action="FIGHTALL" />
+                       </actionpoints>
+                    </DivisionController>
+                  </controller>
+                </SpaceShip>
+                @endcode
+                
+                Full description:
+                Adds an Actionpoint to this->actionpoints_. Actionpoint can take arguments like action="attack" attack="name".
+                For documentation on Actionpoint XML arguments, check out Actionpoint.h class
+                If any WorldEntity that is not Actionpoint or its child being sent to actionpoints through XML,
+                action would be assumed to be Action::FLY and target position to be position of the entity. Also, if not Actionpoint
+                is passed, it is assumed to be in a loop. How it works is: in \<actionpoints\> first all Actionpoints between 
+                first Actionpoint with loopStart=true and first following Actionpoint with loopEnd=true are included in a single loop.
+                If they are adjacent (in the input array) with WorldEntity, then WorldEntity is also in a loop.
+                All the Worldentities are assumed to be in loop. 
+               
+                Loop example:
+
+                @code
+                <SpaceShip position="-1500, 1500, -1000" lookat="0,0,0" team=0 name="ss1">
+                  <templates>
+                    <Template link=spaceshipassff />
+                  </templates>
+                  <controller>
+                    <DivisionController team=0 formationMode="wall">
+                      <actionpoints>
+                        <Actionpoint position="  0,2000,-600" action="FLY" loopStart=true/>
+                        <Actionpoint position="  0,2000,-1000" action="FLY"  />
+                        <Actionpoint position="400,2000,-1000" action="FLY" />
+                        <Actionpoint position="400,2000,-600" action="FLY" loopEnd=true />
+                      </actionpoints>
+                    </DivisionController>
+                  </controller>
+                </SpaceShip>
+                @endcode
+               
+                other loop example:
+
+                @code
+                <SpaceShip position="-1500, -1500, -1500" lookat="0,0,0" team=0 name="ss1">
+                  <templates>
+                    <Template link=spaceshipassff />
+                  </templates>
+                  <controller>
+                    <DivisionController team=0 formationMode="diamond">
+                      <actionpoints>
+                        <Model mesh="cube.mesh" scale=8 position="  0,2000,-600" />
+                        <Model mesh="cube.mesh" scale=8 position="  0,2000,-1000" />
+                        <Model mesh="cube.mesh" scale=8 position="400,2000,-1000" />
+                        <Model mesh="cube.mesh" scale=8 position="400,2000,-600" />
+                      </actionpoints>
+                    </DivisionController>
+                  </controller>
+                </SpaceShip>
+                @endcode
+
+            @note
+                Don't use several loops, and don't use WorldEntities as input to \<actionpoints\> as I didn't test it well, but you
+                can try if feeling lucky.  
+            */
+            void addActionpoint(WorldEntity* actionpoint); 
+            WorldEntity* getActionpoint(unsigned int index) const;    
+            void setDefaultFightAll(bool value)
+                { this->bDefaultFightAll_ = value; }
+            bool getDefaultFightAll ()
+                { return this->bDefaultFightAll_; }
+            void setDefaultPatrol(bool value)
+                { this->bDefaultPatrol_ = value; }
+            bool getDefaultPatrol ()
+                { return this->bDefaultPatrol_; }
+               
+
+            virtual void stayNearProtect();
+            virtual void action(); //<! action() is called in regular intervals managing the bot's behaviour. Only gets called by MasterController
+            virtual void takeActionpoints (const std::vector<Point>& vector, const std::vector<Point>& loop, bool b);
+
+            virtual Action getAction ();
+            virtual std::string getActionName();
+
+            void setAction (Action action);
+            void setAction (Action action, ControllableEntity* target);
+            void setAction (Action action, const Vector3& target);
+            void setAction (Action action, const Vector3& target,  const Quaternion& orient );
+
+            virtual bool setWingman(ActionpointController* wingman)
+                { return false; }
+            virtual bool hasWingman()
+                { return true; }
+            virtual bool setFollower(ActionpointController* myFollower)
+                { return false; }
+            virtual bool hasFollower()
+                { return true; }
+
+
+        protected:
+                void startAttackingEnemiesThatAreClose();
+                WeakPtr<ActionpointController> myWingman_;
+                WeakPtr<ActionpointController> myFollower_;
+                WeakPtr<ActionpointController> myDivisionLeader_;
+            //----[Actionpoint information]----
+                Action action_;
+                std::string protectName_;
+                std::string targetName_;
+                std::vector<WeakPtr<WorldEntity>> actionpoints_;
+                float squaredaccuracy_;
+                std::vector<Point> parsedActionpoints_; //<! actionpoints as they are stored here after being parsed from XML
+                std::vector<Point> loopActionpoints_;   //<! actionpoints that are to be looped
+                bool bInLoop_;                          //<! variable for addActionpoint method
+                bool bLoop_;                            //<! is state machine looping?
+                bool bEndLoop_;                         //<! variable for addActionpoint method
+                bool bTakenOver_;                       //<! are actionpoints taken over from the leader when he died? if yes, top actionpoint 
+                                                        //<! is to be executed for the state machine to start working
+            //----[/Actionpoint information]----
+                void setProtect (ControllableEntity* protect);
+                ControllableEntity* getProtect (); 
+                WeakPtr<ControllableEntity> protect_;   //<! entity that is to be protected if this->action_ == Action::PROTECT
+                void fillLoop();                        //<! moves actionpoints that are should be in loop from parsedActionpoints_ to loopActionpoints_
+                void fillLoopReversed();
+                void moveBackToTop();                   //<! analog of removing back actionpoint for loopActionpoints_: instead of removing it, 
+                                                        //<! move it to the top, so that it will be executed later on.
+                void setClosestTarget();
+                Pawn* closestTarget();
+            //----[Actionpoint methods]----
+                /**
+                @brief
+                    Sets this->target_, this->targetPosition_, this->protect_ and this->action_ depending
+                    on the current actionpoint in the vector parsedActionpoints_ if not looping or
+                    loopActionpoints_ if looping.
+                @note
+                */
+                void executeActionpoint();  
+                /**
+                @brief
+                    If this->bLoop_, move back action to top (back is the current one, top is the last),
+                    otherwise remove back actionpoint.
+                @note
+                    actionpoints_ is only used for XML, real state stacks are parsedActionpoints_ and loopActionpoints_
+                */            
+                void nextActionpoint();                 
+            //----[Actionpoint methods]----          
+
+                bool bDefaultFightAll_;     //<! if true, when no action set, this will fight all
+
+                bool bPatrolling_;        //<! true if current action_ is FIGHT because this found enemies that are close, need this to correctly go back to looping if was looping
+                bool bDefaultPatrol_;       //<! if true, this will look out for enemies that are close if this is just flying or doing nothing
+                unsigned int ticks_;     //<! local tick counter            
+    };
+}
+
+#endif /* _ActionpointController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ArrowController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ArrowController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ArrowController.cc	(revision 11817)
@@ -0,0 +1,135 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      jostoffe
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ArrowController.h"
+#include "HumanController.h"
+#include "worldentities/ControllableEntity.h"
+
+#include "core/CoreIncludes.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+
+    RegisterClass(ArrowController);
+
+    ArrowController::ArrowController(Context* context) : Controller(context)
+    {
+
+        RegisterObject(ArrowController);
+
+        this->currentGPSPoint_ = 0;
+        this->accuracy_ = 1000.0f;
+    }
+
+    ArrowController::~ArrowController()
+    {
+      for (WorldEntity* gpspoint : this->gpspoints_)
+        {
+            if(gpspoint)
+                gpspoint->destroy();
+        }
+
+    }
+
+    //Set the distance you need to reach before the next waypoint will be selected
+    void ArrowController::setAccuracy(float accuracy){
+      this->accuracy_ = accuracy;
+    }
+
+    float ArrowController::getAccuracy(){
+      return this->accuracy_;
+    };
+    
+    void ArrowController::addGPSPoint(WorldEntity* gpspoint)
+    {
+        this->gpspoints_.push_back(gpspoint);
+    }
+
+    WorldEntity* ArrowController::getGPSPoint(unsigned int index) const
+    {
+        if (index < this->gpspoints_.size())
+            return this->gpspoints_[index];
+        else
+            return nullptr;
+    }
+
+    void ArrowController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ArrowController, XMLPort, xmlelement, mode);
+
+        XMLPortObject(ArrowController, WorldEntity, "gpspoints", addGPSPoint, getGPSPoint,  xmlelement, mode);
+        XMLPortParam(ArrowController, "accuracy", setAccuracy, getAccuracy, xmlelement, mode);
+    }
+
+    void ArrowController::tick(float dt)
+    {
+        if (!this->isActive())
+            return;
+
+        if (this->gpspoints_.size() == 0 || !this->getControllableEntity())
+            return;
+        //Set all waypoint to invisible at the beginning  
+        if (this->currentGPSPoint_ == 0){
+          for(unsigned int i = 0; i < this->gpspoints_.size(); i++ )
+            this->gpspoints_[i]->setVisible(false);
+        }
+        //Make the arrow inivisible as soon as you reached the last Waypoint, otherwise make the next waypoint visible 
+        if(currentGPSPoint_ >= gpspoints_.size()){
+          this->getControllableEntity()->setVisible(false);
+          return;
+        }
+        else this->gpspoints_[this->currentGPSPoint_]->setVisible(true);
+
+        //Set the next waypoint as target as soon as you reached the previous one
+        if (this->gpspoints_[this->currentGPSPoint_]->getWorldPosition().squaredDistance(this->getControllableEntity()->getPosition()) <= this->accuracy_){
+            this->gpspoints_[this->currentGPSPoint_]->setVisible(false);
+            this->currentGPSPoint_ = (this->currentGPSPoint_ + 1);
+            return;
+          }
+  
+        Vector3 target = gpspoints_[currentGPSPoint_]->getWorldPosition();
+        WorldEntity::TransformSpace trans = WorldEntity::TransformSpace::World;
+
+        //Get the position and orientation of the Spaceship
+        Vector3 spaceShipPosition = HumanController::getLocalControllerSingleton()->getControllableEntity()->getWorldPosition();
+        Quaternion spaceShipOrientation = HumanController::getLocalControllerSingleton()->getControllableEntity()->getOrientation();
+        
+        //Calculate the new arrow position
+        Vector3 ss_y = spaceShipOrientation.yAxis();
+        spaceShipPosition.x += 20 * ss_y.x;
+        spaceShipPosition.y += 20 * ss_y.y;
+        spaceShipPosition.z += 20 * ss_y.z;
+        
+        //Update Arrow position and orientation  
+        this->getControllableEntity()->setPosition(spaceShipPosition);
+        this->getControllableEntity()->lookAt(target, trans, Vector3(0,0,1));
+        
+        
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ArrowController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ArrowController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ArrowController.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      jostoffe
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ArrowController_H__
+#define _ArrowController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "Controller.h"
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/Arrow.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport ArrowController : public Controller, public Tickable
+    {
+        public:
+            ArrowController(Context* context);
+            virtual ~ArrowController();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            
+            void addGPSPoint(WorldEntity* gpspoint);
+            WorldEntity* getGPSPoint(unsigned int index) const;
+            void setAccuracy(float accuracy);
+            float getAccuracy();
+
+            virtual void tick(float dt); //!< The controlling happens here. This method defines what the controller has to do each tick.
+
+        private:
+            std::vector<WeakPtr<WorldEntity>> gpspoints_;
+            size_t currentGPSPoint_;
+            float accuracy_;
+    };
+}
+
+#endif /* _ArrowController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ArtificialController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ArtificialController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ArtificialController.cc	(revision 11817)
@@ -0,0 +1,294 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Dominik Solenicki
+ *
+ */
+
+#include "ArtificialController.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/pawns/SpaceShip.h"
+
+#include "weaponsystem/WeaponMode.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponSlot.h"
+#include "weaponsystem/WeaponSlot.h"
+
+
+namespace orxonox
+{
+    SetConsoleCommand("ArtificialController", "setbotlevel",      &ArtificialController::setAllBotLevel);
+
+    RegisterClass(ArtificialController);
+
+    ArtificialController::ArtificialController(Context* context) : FormationController(context)
+    {
+        RegisterObject(ArtificialController);
+
+        this->bSetupWorked = false;
+        this->botlevel_ = 0.5f;
+        this->timeout_ = 0;
+        this->currentWaypoint_ = 0;
+        this->setAccuracy(5);
+        this->defaultWaypoint_ = nullptr;
+        this->mode_ = DEFAULT;//Vector-implementation: mode_.push_back(DEFAULT);
+    }
+
+    ArtificialController::~ArtificialController()
+    {
+        if (this->isInitialized())
+        {//Vector-implementation: mode_.erase(mode_.begin(),mode_.end());
+            this->waypoints_.clear();
+            this->weaponModes_.clear();
+        }
+    }
+
+    void ArtificialController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ArtificialController, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ArtificialController, "accuracy", setAccuracy, getAccuracy, xmlelement, mode).defaultValues(100.0f);
+        XMLPortObject(ArtificialController, WorldEntity, "waypoints", addWaypoint, getWaypoint,  xmlelement, mode);
+    }
+
+    /**
+        @brief Gets called when ControllableEntity is being changed. Resets the bot when it dies.
+    */
+    void ArtificialController::changedControllableEntity()
+    {
+        FormationController::changedControllableEntity(); // super
+
+        if (!this->getControllableEntity())
+            this->removeFromFormation();
+    }
+
+
+    void ArtificialController::aimAtTarget()
+    {
+        if (!this->target_ || !this->getControllableEntity())
+            return;
+
+        static const float HARDCODED_PROJECTILE_SPEED = 750;
+
+        this->targetPosition_ = getPredictedPosition(this->getControllableEntity()->getWorldPosition(), HARDCODED_PROJECTILE_SPEED, this->target_->getWorldPosition(), this->target_->getVelocity());
+        this->bHasTargetPosition_ = (this->targetPosition_ != Vector3::ZERO);
+
+        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
+        if (pawn)
+            pawn->setAimPosition(this->targetPosition_);
+    }
+
+    bool ArtificialController::isCloseAtTarget(float distance) const
+    {
+        if (!this->getControllableEntity())
+            return false;
+
+        if (!this->target_)
+            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_) < distance*distance);
+        else
+            return (this->getControllableEntity()->getPosition().squaredDistance(this->target_->getPosition()) < distance*distance);
+    }
+
+    bool ArtificialController::isLookingAtTarget(float angle) const
+    {
+        if (!this->getControllableEntity())
+            return false;
+
+        return (getAngle(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->targetPosition_) < angle);
+    }
+
+    void ArtificialController::abandonTarget(Pawn* target)
+    {
+        if (target == this->target_)
+            this->targetDied();
+    }
+
+    /**
+        @brief DoFire is called when a bot should shoot and decides which weapon is used and whether the bot shoots at all.
+    */
+    void ArtificialController::doFire()
+    {
+        if(!this->bSetupWorked)//setup: find out which weapons are active ! hard coded: laser is "0", lens flare is "1", ...
+        {
+            this->setupWeapons();
+        }
+        else if(this->getControllableEntity() && weaponModes_.size()&&this->bShooting_ && this->isCloseAtTarget((1 + 2*botlevel_)*1000) && this->isLookingAtTarget(math::pi / 20.0f))
+        {
+            int firemode;
+            float random = rnd(1);//
+            if (this->isCloseAtTarget(130) && (firemode = getFiremode("LightningGun")) > -1 )
+            {//LENSFLARE: short range weapon
+                this->getControllableEntity()->fire(firemode); //ai uses lens flare if they're close enough to the target
+            }
+            else if( this->isCloseAtTarget(400) && (random < this->botlevel_) && (firemode = getFiremode("RocketFire")) > -1 )
+            {//ROCKET: mid range weapon
+                this->mode_ = ROCKET; //Vector-implementation: mode_.push_back(ROCKET);
+                this->getControllableEntity()->fire(firemode); //launch rocket
+                if(this->getControllableEntity() && this->target_) //after fire(3) is called, getControllableEntity() refers to the rocket!
+                {
+                    float speed = this->getControllableEntity()->getVelocity().length() - target_->getVelocity().length();
+                    if(!speed) speed = 0.1f;
+                    float distance = target_->getPosition().length() - this->getControllableEntity()->getPosition().length();
+                    this->timeout_= distance/speed*sgn(speed*distance) + 1.8f; //predicted time of target hit (+ tolerance)
+                }
+                else
+                    this->timeout_ = 4.0f; //TODO: find better default value
+            }
+            else if ((firemode = getFiremode("HsW01")) > -1 ) //LASER: default weapon
+                this->getControllableEntity()->fire(firemode);
+        }
+    }
+
+    /**
+        @brief Information gathering: Which weapons are ready to use?
+    */
+    void ArtificialController::setupWeapons() //TODO: Make this function generic!! (at the moment is is based on conventions)
+    {
+        this->bSetupWorked = false;
+        if(this->getControllableEntity())
+        {
+            Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
+            if(pawn && pawn->isA(Class(SpaceShip))) //fix for First Person Mode: check for SpaceShip
+            {
+                this->weaponModes_.clear(); // reset previous weapon information
+                WeaponSlot* wSlot = nullptr;
+                for(int l=0; (wSlot = pawn->getWeaponSlot(l)) ; l++)
+                {
+                    WeaponMode* wMode = nullptr;
+                    for(int i=0; (wMode = wSlot->getWeapon()->getWeaponmode(i)) ; i++)
+                    {
+                        std::string wName = wMode->getIdentifier()->getName();
+                        if(this->getFiremode(wName) == -1) //only add a weapon, if it is "new"
+                            weaponModes_[wName] = wMode->getMode();
+                    }
+                }
+                if(weaponModes_.size())//at least one weapon detected
+                    this->bSetupWorked = true;
+            }//pawn->weaponSystem_->getMunition(SubclassIdentifier< Munition > *identifier)->getNumMunition (WeaponMode *user);
+        }
+    }
+
+
+    void ArtificialController::setBotLevel(float level)
+    {
+        if (level < 0.0f)
+            this->botlevel_ = 0.0f;
+        else if (level > 1.0f)
+            this->botlevel_ = 1.0f;
+        else
+            this->botlevel_ = level;
+    }
+
+    void ArtificialController::setAllBotLevel(float level)
+    {
+        for (ArtificialController* controller : ObjectList<ArtificialController>())
+            controller->setBotLevel(level);
+    }
+
+    void ArtificialController::setPreviousMode()
+    {
+        this->mode_ = DEFAULT; //Vector-implementation: mode_.pop_back();
+    }
+
+    /**
+        @brief Manages boost. Switches between boost usage and boost safe mode.
+    */
+    void ArtificialController::boostControl()
+    {
+        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
+        if(ship == nullptr) return;
+        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower() ) //upper limit ->boost
+            this->getControllableEntity()->boost(true);
+        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
+            this->getControllableEntity()->boost(false);
+    }
+
+    int ArtificialController::getFiremode(std::string name)
+    {
+        for (const auto& mapEntry : this->weaponModes_)
+        {
+            if (mapEntry.first == name)
+                return mapEntry.second;
+        }
+        return -1;
+    }
+
+    void ArtificialController::addWaypoint(WorldEntity* waypoint)
+    {
+        this->waypoints_.push_back(waypoint);
+    }
+
+    WorldEntity* ArtificialController::getWaypoint(unsigned int index) const
+    {
+        if (index < this->waypoints_.size())
+            return this->waypoints_[index];
+        else
+            return nullptr;
+    }
+
+    /**
+        @brief Adds first waypoint of type name to the waypoint stack, which is within the searchDistance
+        @param name object-name of a point of interest (e.g. "PickupSpawner", "ForceField")
+        @param searchDistance The maximum distance to search
+    */
+    void ArtificialController::updatePointsOfInterest(std::string name, float searchDistance)
+    {
+        WorldEntity* waypoint = nullptr;
+        for (WorldEntity* we : ObjectList<WorldEntity>())
+        {
+            if(we->getIdentifier() == ClassByString(name))
+            {
+                ControllableEntity* controllable = this->getControllableEntity();
+                if(!controllable) continue;
+                float actualDistance = ( we->getPosition() - controllable->getPosition() ).length();
+                if(actualDistance > searchDistance || actualDistance < 5.0f) continue;
+                    // TODO: PickupSpawner: adjust waypoint accuracy to PickupSpawner's triggerdistance
+                    // TODO: ForceField: analyze is angle between forcefield boost and own flying direction is acceptable
+                else
+                {
+                    waypoint = we;
+                    break;
+                }
+            }
+        }
+        if(waypoint)
+            this->waypoints_.push_back(waypoint);
+    }
+
+    /**
+        @brief Adds point of interest depending on context.  TODO: Further Possibilites: "ForceField", "PortalEndPoint", "MovableEntity", "Dock"
+    */
+    void ArtificialController::manageWaypoints()
+    {
+        if(!defaultWaypoint_)
+            this->updatePointsOfInterest("PickupSpawner", 200.0f); // long search radius if there is no default goal
+        else
+            this->updatePointsOfInterest("PickupSpawner", 20.0f); // take pickup en passant if there is a default waypoint
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ArtificialController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ArtificialController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ArtificialController.h	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Dominik Solenicki
+ *
+ */
+
+#ifndef _ArtificialController_H__
+#define _ArtificialController_H__
+
+#include "OrxonoxPrereqs.h"
+#include "controllers/FormationController.h"
+
+
+namespace orxonox
+{
+    class _OrxonoxExport ArtificialController : public FormationController
+    {
+        public:
+            ArtificialController(Context* context);
+            virtual ~ArtificialController();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void abandonTarget(Pawn* target);
+
+            virtual void changedControllableEntity() override;
+
+            virtual void doFire();
+            void setBotLevel(float level=1.0f);
+            inline float getBotLevel() const
+                { return this->botlevel_; }
+            static void setAllBotLevel(float level);
+            //WAYPOINT FUNCTIONS
+            void addWaypoint(WorldEntity* waypoint);
+            WorldEntity* getWaypoint(unsigned int index) const;
+
+            inline void setAccuracy(float accuracy)
+                { this->squaredaccuracy_ = accuracy*accuracy; }
+            inline float getAccuracy() const
+                { return sqrt(this->squaredaccuracy_); }
+            void updatePointsOfInterest(std::string name, float distance);
+            void manageWaypoints();
+
+
+
+        protected:
+
+            void aimAtTarget();
+
+            bool isCloseAtTarget(float distance) const;
+            bool isLookingAtTarget(float angle) const;
+
+            float botlevel_; //<! Makes the level of a bot configurable.
+            enum Mode {DEFAULT, ROCKET, DEFENCE, MOVING};//TODO; implement DEFENCE, MOVING modes
+            Mode mode_; //TODO: replace single value with stack-like implementation: std::vector<Mode> mode_;
+            void setPreviousMode();
+
+
+            //WEAPONSYSTEM DATA
+            std::map<std::string, int> weaponModes_; //<! Links each "weapon" to it's weaponmode - managed by setupWeapons()
+            //std::vector<int> projectiles_; //<! Displays amount of projectiles of each weapon. - managed by setupWeapons()
+            float timeout_; //<! Timeout for rocket usage. (If a rocket misses, a bot should stop using it.)
+            void setupWeapons(); //<! Defines which weapons are available for a bot. Is recalled whenever a bot was killed.
+            bool bSetupWorked; //<! If false, setupWeapons() is called.
+            int getFiremode(std::string name);
+
+
+            //WAYPOINT DATA
+            std::vector<WeakPtr<WorldEntity>> waypoints_;
+            size_t currentWaypoint_;
+            float squaredaccuracy_;
+            WorldEntity* defaultWaypoint_;
+
+            void boostControl(); //<! Sets and resets the boost parameter of the spaceship. Bots alternate between boosting and saving boost.
+
+        private:
+    };
+}
+
+#endif /* _ArtificialController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,22 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  Controller.cc
+  HumanController.cc
+  NewHumanController.cc
+  ArtificialController.cc
+  AIController.cc
+  ScriptController.cc
+  WaypointController.cc
+  WaypointPatrolController.cc
+  DroneController.cc
+  FormationController.cc
+  ControllerDirector.cc
+  DivisionController.cc
+  WingmanController.cc
+  SectionController.cc
+  CommonController.cc
+  ActionpointController.cc
+  FlyingController.cc
+  FightingController.cc
+  MasterController.cc
+  ArrowController.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/CommonController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/CommonController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/CommonController.cc	(revision 11817)
@@ -0,0 +1,216 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+#include "controllers/CommonController.h"
+
+//here starts stuff for sameTeam function copied from FormationController
+#include "gametypes/TeamDeathmatch.h"
+#include "gametypes/Gametype.h"
+#include "controllers/DroneController.h"
+#include "gametypes/Dynamicmatch.h"
+
+#include "worldentities/pawns/TeamBaseMatchBase.h"
+
+namespace orxonox
+{
+    const float CommonController::HARDCODED_PROJECTILE_SPEED = 750;
+
+    RegisterClass(CommonController);
+    CommonController::CommonController(Context* context): Controller(context)
+    {
+        RegisterObject(CommonController);
+    }
+    CommonController::~CommonController() 
+    {
+        //no member variables - nothing to destroy
+    }
+    /**
+    @brief
+      PRE: a < b.
+      returns random float between a and b.
+    */
+    float CommonController::randomInRange(float a, float b)
+    {
+        return a + rnd(1.0f) * (b - a);
+    }
+    /**
+    @brief
+      returns distance between two entities, if either is zero pointer, returns infinity
+    */    
+    float CommonController::distance (const ControllableEntity* entity1, const ControllableEntity* entity2)
+    {
+        if (!entity1 || !entity2)
+            return std::numeric_limits<float>::infinity();
+        return (entity1->getPosition() - entity2->getPosition()).length();
+    }
+    /**
+    @brief
+      bad function from FormationController that returns true if both entities have same team
+    */    
+    bool CommonController::sameTeam (ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
+    {
+        
+        if (!entity1 || !entity2)
+            return false;
+        if (entity1 == entity2)
+            return true;
+
+        int team1 = entity1->getTeam();
+        int team2 = entity2->getTeam();
+
+        Controller* controller = nullptr;
+        if (entity1->getController())
+            controller = entity1->getController();
+        else
+            controller = entity1->getXMLController();
+        if (controller)
+        {
+            if (controller->getIdentifier()->getName() == "MasterController")
+                return true;
+            CommonController* ac = orxonox_cast<CommonController*>(controller);
+            if (ac)
+                team1 = ac->getTeam();
+        }
+
+        if (entity2->getController())
+            controller = entity2->getController();
+        else
+            controller = entity2->getXMLController();
+        if (controller)
+        {
+            if (controller->getIdentifier()->getName() == "MasterController")
+                return true;
+            CommonController* ac = orxonox_cast<CommonController*>(controller);
+            if (ac)
+                team2 = ac->getTeam();
+        }
+
+        TeamGametype* tdm = orxonox_cast<TeamGametype*>(gametype);
+        if (tdm)
+        {
+            if (entity1->getPlayer())
+                team1 = tdm->getTeam(entity1->getPlayer());
+
+            if (entity2->getPlayer())
+                team2 = tdm->getTeam(entity2->getPlayer());
+        }
+
+        TeamBaseMatchBase* base = nullptr;
+        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
+        if (base)
+        {
+            switch (base->getState())
+            {
+                case BaseState::ControlTeam1:
+                    team1 = 0;
+                    break;
+                case BaseState::ControlTeam2:
+                    team1 = 1;
+                    break;
+                case BaseState::Uncontrolled:
+                default:
+                    team1 = -1;
+            }
+        }
+        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
+        if (base)
+        {
+            switch (base->getState())
+            {
+                case BaseState::ControlTeam1:
+                    team2 = 0;
+                    break;
+                case BaseState::ControlTeam2:
+                    team2 = 1;
+                    break;
+                case BaseState::Uncontrolled:
+                default:
+                    team2 = -1;
+            }
+        }
+
+        DroneController* droneController = nullptr;
+        droneController = orxonox_cast<DroneController*>(entity1->getController());
+        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
+            return true;
+        droneController = orxonox_cast<DroneController*>(entity2->getController());
+        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
+            return true;
+        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
+        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
+        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
+            return true;
+
+        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
+        if (dynamic)
+        {
+            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
+
+            if (entity1->getPlayer())
+                team1 = dynamic->getParty(entity1->getPlayer());
+
+            if (entity2->getPlayer())
+                team2 = dynamic->getParty(entity2->getPlayer());
+
+            if (team1 ==-1 ||team2 ==-1) {return false;}
+            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
+            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
+            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
+            else return true;
+        }
+
+        return (team1 == team2 && team1 != -1);
+    }
+    /**
+    @brief
+      returns true if entityThatLooks does look at entityBeingLookeAt with a tolerance of angle.
+    */    
+    bool CommonController::isLooking(const ControllableEntity* entityThatLooks, const ControllableEntity* entityBeingLookedAt, float angle)
+    {
+        if (!entityThatLooks || !entityBeingLookedAt)
+            return false;
+        return (getAngle(entityThatLooks ->getPosition() , 
+            entityThatLooks->getOrientation()  * WorldEntity::FRONT, 
+            entityBeingLookedAt->getWorldPosition()) < angle);
+    }
+    /**
+    @brief
+      returns a name of a Pawn entity, if no name set, returns string representing address of the Pawn.
+    */    
+    std::string CommonController::getName(const Pawn* entity)
+    {
+        std::string name = entity->getName();
+        if (name == "")
+        {
+            const void * address = static_cast<const void*>(entity);
+            std::stringstream ss;
+            ss << address;  
+            name = ss.str();            
+        }
+        return name;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/CommonController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/CommonController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/CommonController.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _CommonController_H__
+#define _CommonController_H__
+
+
+#include "controllers/Controller.h"                 //that's what I inherit from
+
+#include <limits>                                   //I use limits pretty much in every class, so might as well include it in the parent class
+
+#include "worldentities/ControllableEntity.h"       //same for ControllableEntity
+#include "worldentities/pawns/Pawn.h"               //and Pawn
+
+
+namespace orxonox
+{
+    class _OrxonoxExport CommonController : public Controller
+    {
+
+        public:
+            static const float HARDCODED_PROJECTILE_SPEED; //<! FightingController uses it to predict enemy position
+
+            CommonController(Context* context);
+            virtual ~CommonController();
+            static float randomInRange(float a, float b);   //<! returns random number from a to b
+            static float distance(const ControllableEntity* entity1, const ControllableEntity* entity2);    //<! returns distance between arguments
+            static bool sameTeam (ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gt);
+            static bool isLooking(const ControllableEntity* entityThatLooks, const ControllableEntity* entityBeingLookedAt, float angle) ;
+            static std::string getName(const Pawn* entity) ;           
+    };
+}
+
+#endif /* _CommonController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/Controller.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/Controller.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/Controller.cc	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Controller.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Controller);
+
+    Controller::Controller(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Controller);
+
+        this->player_ = nullptr;
+        this->controllableEntity_ = nullptr;
+        this->bGodMode_ = false;
+        this->team_=-1;
+    }
+
+    Controller::~Controller()
+    {
+    }
+    void Controller::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Controller, XMLPort, xmlelement, mode);
+        XMLPortParam(Controller, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/Controller.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/Controller.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/Controller.h	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Controller_H__
+#define _Controller_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/BaseObject.h"
+#include "core/class/Super.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Controller : public BaseObject
+    {
+        // set friend classes to access setControllableEntity
+        friend class PlayerInfo;
+        friend class ControllableEntity;
+
+        public:
+            Controller(Context* context);
+            virtual ~Controller();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            inline void setPlayer(PlayerInfo* player)
+                { this->player_ = player; }
+            inline PlayerInfo* getPlayer() const
+                { return this->player_; }
+            inline void setTeam(int team)
+                { this->team_ = team; }
+            inline int getTeam() const
+                { return this->team_; }
+
+            virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, float damage) {};
+
+/* Override needed for different visual effects (e.g. in "NewHumanController.cc") depending on
+   the DIFFERENT AMOUNT OF DAMAGE done to the shield and to the health of "victim" (see Projectile.cc, Pawn.cc)
+
+//            virtual inline void hit(Pawn* originator, btManifoldPoint& contactpoint, float damage, float healthdamage, float shielddamage) {};
+*/
+
+            void setGodMode( bool mode ){ this->bGodMode_ = mode; }
+            bool getGodMode(){ return this->bGodMode_; }
+
+            inline ControllableEntity* getControllableEntity() const
+                { return this->controllableEntity_; }
+            virtual void changedControllableEntity() {}
+
+//        protected:
+            // don't use this directly, use getPlayer()->startControl(entity) (unless you know exactly what you do)
+            inline void setControllableEntity(ControllableEntity* entity)
+            {
+                if (entity != this->controllableEntity_)
+                {
+                    this->controllableEntity_ = entity;
+                    this->changedControllableEntity();
+                }
+            }
+
+        protected:
+            PlayerInfo* player_;
+            ControllableEntity* controllableEntity_;
+            int team_;
+        private:
+            bool bGodMode_;
+    };
+}
+
+#endif /* _Controller_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ControllerDirector.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ControllerDirector.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ControllerDirector.cc	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ * First try of a ControllerDirector. Target: An event occurs in the levelTry.oxw
+ * file, which is "heard" by an object of the type of this class. It then SHOULD
+ * (because it is not working) execute the party function.
+ */
+
+#include "ControllerDirector.h"
+#include "ScriptController.h"
+#include "core/CoreIncludes.h"
+
+//#include "network/NetworkFunction.h"
+
+#include "infos/HumanPlayer.h"
+#include "interfaces/PlayerTrigger.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/LuaState.h"
+
+
+namespace orxonox
+{
+    RegisterClass(ControllerDirector);
+
+    ControllerDirector::ControllerDirector(Context* context) : ArtificialController(context)
+    {
+        // Register the object with the framework
+        RegisterObject(ControllerDirector);
+
+        // output a message to ensure we know the constructor was run
+        orxout(verbose)<<"hello universe constructor blablub"<< endl;
+
+
+
+        // Initialize member variables
+        this->player_ = nullptr;
+        this->entity_ = nullptr;
+        this->pTrigger_ = nullptr;
+        this->context_ = context;
+    }
+
+    void ControllerDirector::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ControllerDirector, XMLPort, xmlelement, mode);
+        XMLPortParam(ControllerDirector, "scriptname", setScriptName, getScriptName, xmlelement, mode).defaultValues("testscript");
+
+        orxout(verbose)<< "ControllerDirector::XMLPort " 
+          << "An instance of ControllerDirector has been created." << endl;
+    }
+
+    void ControllerDirector::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        // Call the xmleventport functions of the classes we derive from
+        SUPER(ControllerDirector, XMLEventPort, xmlelement, mode);
+
+        // Add an event sink for a "takeControl" event, which leads to the
+        // function takeControl() being called.
+        XMLPortEventSink(ControllerDirector, BaseObject, "takeControl", 
+          takeControl, xmlelement, mode);
+    }
+
+
+
+
+    void ControllerDirector::takeControl(Controller * controller, BaseObject * trigger) 
+    {
+       /* Output a message confirming that the function was called */
+       orxout(verbose)<<"test takecontrol."<< endl;
+
+       /* First, we set up a new controller to attach to the unit that
+        * triggered our event. 
+        */
+       static int ctrlid = 1;
+       bool prepok = preparationToTakeControl(trigger);
+       if( prepok == true) 
+       {
+         /* Create a scriptcontroller object */
+         ScriptController *newctrl = new ScriptController(this->context_);
+
+         /* Make the player we were given its slave */
+         newctrl->setPlayer(this->player_);
+
+         /* Start controlling that object */
+         newctrl->takeControl(ctrlid);
+       }
+       else
+         return;
+
+       /* Set up a luastate to use for running the scripts */
+       LuaState * ls = new LuaState();
+       
+       /* Assemble a string to define a controller id variable in lua space */
+       std::stringstream tmp;
+       tmp << "newctrlid = " << ctrlid << endl;
+       std::string todo = tmp.str();
+       
+       /* Run the string using the luastate created earlier */
+       ls->doString(todo);
+
+       /* Now run the script on this controller. This will still have the above
+        * variable "newctrlid" defined, which means it can make use of it.
+        */
+       std::string scr = this->scriptname_ + ".lua";
+       ls->doFile(scr);
+
+       /* Increase the controller ID so we have a different one for
+        * the next time it is triggered */
+       ctrlid += 1;
+    } 
+
+    bool ControllerDirector::preparationToTakeControl(BaseObject * trigger) 
+    {
+        this->pTrigger_ = orxonox_cast<PlayerTrigger*>(trigger);
+        this->player_ = nullptr;
+
+        orxout(verbose) << "Preparation to take Control!" << endl; 
+
+        // Check whether it is a player trigger and extract pawn from it
+        if(this->pTrigger_ != nullptr)
+        {
+            // Get the object which triggered the event.
+            this->player_ = this->pTrigger_->getTriggeringPlayer();  
+
+            // Check if there actually was a player returned.
+            if( this->player_ == nullptr) return false;
+        }
+        else
+        {
+            orxout(verbose) << "ControllerDirector::preparationToTakeControl " 
+              << "Not a player trigger, can't extract pawn from it.." << endl;
+            return false;
+        }
+
+        this->entity_ = this->player_->getControllableEntity();
+        assert(this->entity_);
+
+        return true;
+    }
+
+    /* // Currently unused
+    void ControllerDirector::setNewController(Controller * controller) {
+
+
+        orxout() << "New Controller is going to be set!" << endl;
+
+        this->entity_->setDestroyWhenPlayerLeft(false);
+        this->player_->pauseControl();
+        this->entity_->setController(controller);
+        this->player_->startControl(this->entity_);
+        //this->setControllableEntity(this->entity_);
+    }
+    */
+       
+    
+
+}
+
+
+
+
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ControllerDirector.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ControllerDirector.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ControllerDirector.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ControllerDirector_H__
+#define _ControllerDirector_H__
+
+#include "OrxonoxPrereqs.h"
+#include "ArtificialController.h"
+#include "core/EventIncludes.h"
+
+
+namespace orxonox
+{
+    class _OrxonoxExport ControllerDirector : public ArtificialController
+    {
+        public:
+            ControllerDirector(Context* context);
+            virtual ~ControllerDirector() { }
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            bool party(bool bTriggered, BaseObject* trigger);
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setScriptName(const std::string& name) { this->scriptname_ = name; }
+            inline const std::string& getScriptName() const { return this->scriptname_; }
+
+
+            /* Take over control of a given object */
+            void takeControl(Controller * controller, BaseObject * trigger);
+            bool preparationToTakeControl(BaseObject * trigger);
+
+            // currently unused
+            //void setNewController(Controller * controller);
+
+        protected:
+            std::string scriptname_;   
+            PlayerInfo* player_;
+            ControllableEntity* entity_; 
+            PlayerTrigger * pTrigger_;
+            Context* context_;
+    };
+}
+
+#endif /* _ControllerDirector_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/DivisionController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/DivisionController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/DivisionController.cc	(revision 11817)
@@ -0,0 +1,132 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DivisionController.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+
+    RegisterClass(DivisionController);
+
+    //Leaders share the fact that they have Wingmans
+    DivisionController::DivisionController(Context* context) : ActionpointController(context)
+    {
+        RegisterObject(DivisionController);
+        this->setFormationMode(FormationMode::DIAMOND);
+        this->target_ = nullptr;
+        this->myFollower_ = nullptr;
+        this->myWingman_ = nullptr;
+    }
+
+    DivisionController::~DivisionController()
+    {
+        for (WorldEntity* actionpoint : this->actionpoints_)
+        {
+            if (actionpoint)
+                actionpoint->destroy();
+        }
+        this->parsedActionpoints_.clear();
+        this->actionpoints_.clear();
+    } 
+    void DivisionController::action()
+    {   
+        if (!this->getControllableEntity() || !this->isActive())
+            return;
+        
+        ActionpointController::action();
+        if (!(this->parsedActionpoints_.empty() && this->loopActionpoints_.empty()))
+        {
+            //when this dies, its follower will execute all its actionpoints, if follower dies before this, wingman will do this
+            if (this->myFollower_)
+            {
+                this->myFollower_->takeActionpoints(this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
+            }
+            else if (this->myWingman_)
+            {
+                this->myWingman_->takeActionpoints(this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
+            }    
+        }
+
+        
+    }
+    //I wanted to do it different here, but at this point I think nothing will change if I delete that method
+    void DivisionController::stayNearProtect()
+    {
+        ActionpointController::stayNearProtect();
+    }
+    
+    bool DivisionController::setWingman(ActionpointController* newWingman)
+    {
+        if (!this->myWingman_)
+        {
+            this->myWingman_ = newWingman;
+            if (!this->hasFollower())
+                newWingman->takeActionpoints (this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    bool DivisionController::setFollower(ActionpointController* newFollower)
+    {
+        if (!this->myFollower_)
+        {
+            this->myFollower_ = newFollower;
+            if (this->hasWingman())
+            {
+                this->myWingman_->takeActionpoints (std::vector<Point>(), std::vector<Point>(), false);
+            }
+
+            newFollower->takeActionpoints (this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
+            
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    bool DivisionController::hasWingman()
+    {
+        if (this->myWingman_)
+            return true;
+        else
+            return false;
+    }
+    bool DivisionController::hasFollower()
+    {
+        if (this->myFollower_)
+            return true;
+        
+        return false;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/DivisionController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/DivisionController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/DivisionController.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DivisionController_H__
+#define _DivisionController_H__
+
+#include "controllers/ActionpointController.h"
+
+
+
+namespace orxonox
+{
+    /**
+        @note
+        ActionpointController will not work, if there is no MasterController in the level!
+        All the demos are in a file called AITest.oxw. In the menu look for New AI Testing Level.
+    */
+    class _OrxonoxExport DivisionController : public ActionpointController
+    {
+        public:
+            //----[language demanded functions]----            
+                DivisionController(Context* context);
+
+                virtual ~DivisionController();
+            //----[/language demanded functions]----            
+
+            //----[own functions]----
+                virtual bool setFollower(ActionpointController* newFollower) override;
+                virtual bool setWingman(ActionpointController* newWingman) override;
+                virtual bool hasWingman() override;
+                virtual bool hasFollower() override;
+                
+            //----[/own functions]----
+            virtual void stayNearProtect() override;
+
+        protected:
+            //----action must only be managed by this----
+            virtual void action() override; //<! action() is called in regular intervals managing the bot's behaviour.
+
+        private:
+            //----private variables-----
+            Timer actionTimer_; //<! Regularly calls action().
+   
+
+    };
+}
+
+#endif /* _DivisionController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/DroneController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/DroneController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/DroneController.cc	(revision 11817)
@@ -0,0 +1,201 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oli Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DroneController.h"
+#include "worldentities/Drone.h"
+#include "util/Math.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Constructor.
+    */
+    RegisterClass(DroneController);
+
+    const float DroneController::ACTION_INTERVAL = 1.0f;
+
+    DroneController::DroneController(Context* context) : ArtificialController(context)
+    {
+        RegisterObject(DroneController);
+
+        this->setTeam(0);
+        this->owner_ = nullptr;
+        this->drone_ = nullptr;
+        this->isShooting_ = false;
+        this->setAccuracy(10);
+
+        this->actionTimer_.setTimer(ACTION_INTERVAL, true, createExecutor(createFunctor(&DroneController::action, this)));
+
+        this->owner_.setCallback(createFunctor(&DroneController::ownerDied, this));
+    }
+
+    DroneController::~DroneController()
+    {
+    }
+
+    void DroneController::setOwner(Pawn* owner){
+        this->owner_ = owner;
+    }
+
+    void DroneController::setDrone(Drone* drone)
+    {
+        this->drone_ = drone;
+        this->setControllableEntity(drone);
+    }
+
+    void DroneController::action()
+    {
+        float random;
+        float maxrand = 100.0f / ACTION_INTERVAL;
+        float distanceToTargetSquared = 0;
+
+        if (this->target_)
+            distanceToTargetSquared = (getDrone()->getWorldPosition() - this->target_->getWorldPosition()).squaredLength();
+
+        random = rnd(maxrand);
+        if ( random < 30 || (!this->target_) || distanceToTargetSquared > (this->getDrone()->getMaxShootingRange()*this->getDrone()->getMaxShootingRange()))
+            this->searchNewTarget();
+    }
+
+    /**
+    @brief
+        The controlling happens here. This method defines what the controller has to do each tick.
+    @param dt
+        The duration of the tick.
+    */
+    /* PORTALS workaround:
+    if the owner uses a portal -> distance between owner and drone is huge -> is detected by drone
+    -> drone searches for portal -> drone adds portal as waypoint -> drone flies towards portal //ignores owner
+    -> if the drone used a portal, then the distance to the owner is small -> remove waypoint // back to normal mode
+
+    */
+    void DroneController::tick(float dt)
+    {
+        if (this->getDrone() && this->getOwner())
+        {
+            if (this->waypoints_.size() > 0 ) //Waypoint functionality: Drone should follow it's master through portals
+            {// Idea: after using the the portal, the master is far away.
+                WorldEntity* wPoint = this->waypoints_[this->waypoints_.size()-1];
+                if(wPoint)
+                {
+                    float distanceToOwnerSquared = (this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength();
+                    this->absoluteMoveToPosition(wPoint->getWorldPosition()); //simplified function - needs WORKAROUND
+                    if (distanceToOwnerSquared <= 90000.0f) //WORKAROUND: if the Drone is again near its owner, the portal has been used correctly.
+                    {
+                        this->waypoints_.pop_back(); // if goal is reached, remove it from the list
+                        this->positionReached(); //needed??
+                    }
+
+                }
+                else
+                    this->waypoints_.pop_back(); // remove invalid waypoints
+            }
+            else
+            {
+                if (this->target_)
+                {
+                    float distanceToTargetSquared = (this->getDrone()->getWorldPosition() - this->target_->getWorldPosition()).squaredLength();
+                    if (distanceToTargetSquared < (this->getDrone()->getMaxShootingRange()*this->getDrone()->getMaxShootingRange()))
+                    {
+                       this->isShooting_ = true;
+                       this->aimAtTarget();
+                       if(!this->friendlyFire())
+                           this->getDrone()->fire(0);
+                    }
+               }
+
+
+                float maxDistanceSquared = this->getDrone()->getMaxDistanceToOwner()*this->getDrone()->getMaxDistanceToOwner();
+                float minDistanceSquared = this->getDrone()->getMinDistanceToOwner()*this->getDrone()->getMinDistanceToOwner();
+                if((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength()  > 20.0f*maxDistanceSquared)
+                {//FIX: if the drone's owner uses portal, the drone searches for the portal & adds it as a waypoint.
+                    this->updatePointsOfInterest("PortalEndPoint", 500.0f); //possible conflict: speed-pickup
+                }
+                if ((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength()  > maxDistanceSquared)
+                {
+                    this->moveToPosition(this->getOwner()->getWorldPosition()); //fly towards owner
+                }
+                else if((this->getDrone()->getWorldPosition() - this->getOwner()->getWorldPosition()).squaredLength() < minDistanceSquared)
+                {
+                    this->moveToPosition(-this->getOwner()->getWorldPosition()); //fly away from owner
+                }
+                else if (!this->isShooting_)
+                {
+                    float random = rnd(2.0f);
+                    float randomSelection = rnd(6.0f);
+                    if((int)randomSelection==0) drone_->moveUpDown(random);
+                    else if((int)randomSelection==1) drone_->moveRightLeft(random);
+                    else if((int)randomSelection==2) drone_->moveFrontBack(random);
+                    else if((int)randomSelection==3) drone_->rotateYaw(random);
+                    else if((int)randomSelection==4) drone_->rotatePitch(random);
+                    else if((int)randomSelection==5) drone_->rotateRoll(random);
+                }
+
+                this->isShooting_ = false;
+            }
+        }
+        
+        SUPER(AIController, tick, dt);
+    }
+
+    void DroneController::ownerDied()
+    {
+//         if (this->target_) {            //Drone has some kind of Stockholm-Syndrom --> gets attached to Owners Killer
+//             this->setOwner(target_);
+//             this->searchNewTarget();
+//         }
+        if (this->drone_)
+            this->drone_->destroy();
+        else
+            this->destroy();
+    }
+
+    bool DroneController::friendlyFire()
+    {   ControllableEntity* droneEntity_ = this->getControllableEntity();
+        if (!droneEntity_) return false;
+        if(!owner_) return false;
+        if(this->bHasTargetPosition_)
+        {
+            Vector3 ownerPosition_ = owner_->getPosition();
+            Vector3 toOwner_ = owner_->getPosition() - droneEntity_->getPosition();
+            Vector3 toTarget_ = targetPosition_ - droneEntity_->getPosition();
+            if(toTarget_.length() < toOwner_.length()) return false; //owner is far away = in safty
+            float angleToOwner = getAngle(droneEntity_->getPosition(), droneEntity_->getOrientation() * WorldEntity::FRONT, ownerPosition_);
+            float angleToTarget = getAngle(droneEntity_->getPosition(), droneEntity_->getOrientation() * WorldEntity::FRONT, targetPosition_);
+            float angle = angleToOwner - angleToTarget;//angle between target and owner, observed by the drone
+            if(std::sin(angle)*toOwner_.length() < 5.0f)//calculate owner's distance to shooting line
+            return true;
+        }
+        return false;//Default return value: Usually there is no friendlyFire
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/DroneController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/DroneController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/DroneController.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oli Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _DroneController_H__
+#define _DroneController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "AIController.h"
+#include "core/object/WeakPtr.h"
+#include "tools/interfaces/Tickable.h"
+
+#include "tools/Timer.h"
+
+
+namespace orxonox
+{
+    /**
+    @brief
+        Controller for the Drone of the PPS tutorial.
+    @author
+        Oli Scheuss
+    */
+    class _OrxonoxExport DroneController : public ArtificialController, public Tickable
+    {
+        public:
+            DroneController(Context* context);
+            virtual ~DroneController();
+
+            virtual void tick(float dt) override; //!< The controlling happens here. This method defines what the controller has to do each tick.
+
+            void setOwner(Pawn* owner);
+            inline Pawn* getOwner() const
+                { return this->owner_; }
+
+            void setDrone(Drone*  drone);
+            inline Drone* getDrone() const
+                { return this->drone_; }
+
+        protected:
+            virtual void action();
+            void ownerDied();
+            bool friendlyFire(); //<! returns true if the owner_ would be hit.
+            bool isShooting_;
+
+        private:
+            static const float ACTION_INTERVAL;
+
+            Timer actionTimer_;
+            WeakPtr<Pawn> owner_;
+            Drone* drone_;
+    };
+}
+
+#endif /* _DroneController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/FightingController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/FightingController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/FightingController.cc	(revision 11817)
@@ -0,0 +1,362 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      Fabian 'x3n' Landau, Dominik Solenicki
+ *
+ */
+#include "controllers/FightingController.h"
+#include "util/Math.h"
+
+
+#include "worldentities/pawns/SpaceShip.h"
+
+#include "weaponsystem/WeaponMode.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/Weapon.h"
+#include "weaponsystem/WeaponSlot.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "weaponsystem/Munition.h"
+
+namespace orxonox
+{
+
+    RegisterClass (FightingController);
+    
+    FightingController::FightingController( Context* context ): FlyingController( context )
+    {
+        this->attackRange_ = 2500;
+        this->stopLookingAtTarget();
+        this->bSetupWorked = false;
+        this->timeout_ = 0;
+        RegisterObject( FightingController );
+    }
+    FightingController::~FightingController() 
+    {
+        
+    }
+    void FightingController::lookAtTarget(float dt)
+    {
+        if (!this->getControllableEntity())
+            return;
+        ControllableEntity* entity = this->getControllableEntity();
+        if ( !entity )
+            return;
+        Vector2 coord = get2DViewCoordinates
+            ( entity->getPosition() , 
+            entity->getOrientation()  * WorldEntity::FRONT, 
+            entity->getOrientation()  * WorldEntity::UP, 
+            positionOfTarget_ );
+
+        //rotates should be in range [-1,+1], clamp cuts off all that is not
+        float rotateX = -clamp( coord.x * 10, -1.0f, 1.0f );
+        float rotateY = clamp( coord.y * 10, -1.0f, 1.0f ); 
+   
+        //Yaw and Pitch are enough to start facing the target
+        this->getControllableEntity() ->rotateYaw( ROTATEFACTOR * rotateX * dt );
+        this->getControllableEntity() ->rotatePitch( ROTATEFACTOR * rotateY * dt );
+    }
+    void FightingController::stopLookingAtTarget()
+    {
+        this->bLookAtTarget_ = false;
+    }
+    void FightingController::startLookingAtTarget()
+    {
+        this->bLookAtTarget_ = true;
+    }
+    bool FightingController::hasTarget() const
+    {
+        if ( this->target_ )
+            return true;
+        return false;
+    }
+
+    void FightingController::setTarget( ControllableEntity* target )
+    {
+        this->target_ = target;        
+        if ( this->target_ )
+        {
+            this->setPositionOfTarget( target_->getWorldPosition() );
+        }
+    }
+    void FightingController::setPositionOfTarget( const Vector3& target )
+    {
+        this->positionOfTarget_ = target;
+        this->bHasPositionOfTarget_ = true;
+    }
+    void FightingController::setOrientationOfTarget( const Quaternion& orient )
+    {
+        this->orientationOfTarget_=orient;
+        this->bHasOrientationOfTarget_=true;
+    }
+    
+    void FightingController::maneuver() 
+    {
+        if ( !this->target_ || !this->getControllableEntity())
+            return;
+
+
+        Vector3 thisPosition = this->getControllableEntity()->getWorldPosition();
+        this->setPositionOfTarget(this->target_->getWorldPosition());
+        //this->setOrientationOfTarget(this->target_->getOrientation());
+        Vector3 diffVector = this->positionOfTarget_ - thisPosition;
+        float diffLength = diffVector.length();
+        Vector3 diffUnit = diffVector/diffLength;
+
+        //too far? well, come closer then
+        if (diffLength > this->attackRange_)
+        {
+            this->spread_ = 400;
+            this->formationMode_ = FormationMode::DIAMOND;
+            this->bKeepFormation_ = true;
+            
+            this->setTargetPosition(this->positionOfTarget_ - diffUnit * 100.0f);
+        }
+        else
+        {   
+            bool bTargetIsLookingAtThis = CommonController::isLooking (this->target_, this->getControllableEntity(), math::pi/20.0f)
+                || this->deltaHp < 0;
+            this->bKeepFormation_ = false;
+
+            if (!this->bDodge_)
+            {
+                this->bStartedDodging_ = false;
+
+                this->setTargetPosition(this->positionOfTarget_ - diffUnit * 50.0f);   
+                return;
+            }
+            else if (bTargetIsLookingAtThis || diffLength < 700.0f)
+            {
+                if (!this->bStartedDodging_)
+                {
+                    this->bStartedDodging_ = true;
+                    dodge(thisPosition, diffLength, diffUnit);        
+                }
+            }
+            else
+            {
+                if (diffLength < 1000)
+                {
+                    this->stopMoving();
+                    this->startLookingAtTarget();
+
+                }
+                else
+                {
+                    this->setTargetPosition(this->positionOfTarget_ - diffUnit * 300.0f);
+                }
+            }
+        }
+    }
+    
+    void FightingController::dodge(const Vector3& thisPosition, float diffLength, Vector3& diffUnit)
+    {
+        //d.x*x + d.y*y + d.z*z == 0
+        //z = 1/d.z * (-d.y*y - d.x * x)
+        float x = CommonController::randomInRange (300, 800) * (CommonController::randomInRange(0,1) <= 0.5 ? 1 : -1);
+        float y = CommonController::randomInRange (300, 800) * (CommonController::randomInRange(0,1) <= 0.5 ? 1 : -1);
+        float z = diffUnit.z == 0 ? 0 : (1/diffUnit.z) * (-x * diffUnit.x - y * diffUnit.y);
+        if (diffLength < 150.0f)
+        {
+            this->setTargetPosition(this->positionOfTarget_ + Vector3(z,x,y));
+        }
+        else
+        {
+        this->setTargetPosition(thisPosition + Vector3(x,y,z) + (this->deltaHp < 0 ? -diffUnit * 450.0f : 
+            (diffLength < 700.0f ? -diffUnit*700.0f : diffUnit * 50.0f)));
+
+        }
+        this->boostControl();
+
+    }
+    bool FightingController::canFire() 
+    {
+        //no target? why fire?
+        if (!this->target_ || !this->getControllableEntity())
+            return false;
+        Vector3 newPositionOfTarget = getPredictedPosition(this->getControllableEntity()->getWorldPosition(), 
+                                                           HARDCODED_PROJECTILE_SPEED, this->target_->getWorldPosition(),
+                                                           this->target_->getVelocity());
+        if (!this->target_ || !this->getControllableEntity())
+            return false;
+        //Vector3.isNaN() is what I used on my machine and it worked...
+        if (!(std::isnan(newPositionOfTarget.x) || std::isnan(newPositionOfTarget.y) || std::isnan(newPositionOfTarget.z)))
+        {
+            this->setPositionOfTarget(newPositionOfTarget);
+        }
+
+        return squaredDistanceToTarget() < this->attackRange_*this->attackRange_ && this->isLookingAtTarget(math::pi / 20.0f);
+    }
+
+
+    float FightingController::squaredDistanceToTarget()  const
+    {
+        if (!this->getControllableEntity())
+            return 0;
+        if (!this->target_ || !this->getControllableEntity())
+            return (this->getControllableEntity()->getPosition().squaredDistance(this->targetPosition_));
+        else
+            return (this->getControllableEntity()->getPosition().squaredDistance(this->positionOfTarget_));
+    }
+    bool FightingController::isLookingAtTarget( float angle ) const
+    {
+        if ( !this->getControllableEntity()  || !this->target_ )
+            return false;
+        return CommonController::isLooking(this->getControllableEntity(), this->getTarget(), angle);
+    }
+    void FightingController::setClosestTarget()
+    {
+        this->setTarget (static_cast<ControllableEntity*>( closestTarget() ) ); 
+    }
+    
+    Pawn* FightingController::closestTarget() const
+    {
+        if (!this->getControllableEntity())
+            return nullptr;
+
+        Pawn* closestTarget = nullptr;
+        float minDistance =  std::numeric_limits<float>::infinity();
+        Gametype* gt = this->getGametype();
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(pawn), gt) )
+                continue;
+
+            float distance = CommonController::distance (pawn, this->getControllableEntity());
+            if (distance < minDistance)
+            {
+                closestTarget = pawn;
+                minDistance = distance;
+            }
+        }
+        if (closestTarget)
+        {
+           return closestTarget;
+        } 
+        return nullptr;
+    }
+    //I checked it out, rockets DO NOT cause any problems! this->getControllableEntity() is always a SpaceShip
+    void FightingController::doFire()
+    {
+        if (!this->bSetupWorked)
+        {
+            this->setupWeapons();
+        }
+        if (!this->target_ || !this->getControllableEntity())
+        {
+            return;
+        }
+
+        Pawn* pawn = orxonox_cast<Pawn*> (this->getControllableEntity());
+        if (pawn)
+            pawn->setAimPosition (this->positionOfTarget_);
+
+        int firemode;
+        float distance = CommonController::distance (this->getControllableEntity(), this->target_);
+
+
+       
+        if (distance < 1500)
+        {
+            if (this->rocketsLeft_ > 0 && !this->bFiredRocket_)
+            {
+                firemode = getFiremode ("RocketFire");
+            }
+            else
+            {
+                if (distance > 800)
+                    firemode = getFiremode ("HsW01");
+                else
+                    firemode = getFiremode ("LightningGun");
+            }
+
+        } 
+    
+
+        else if (distance < 2000)
+        {
+            firemode = getFiremode ("HsW01");
+        }
+        else
+        {
+            firemode = getFiremode ("LightningGun");
+        }
+        if (firemode < 0)
+        {
+            //assuming there is always some weapon with index 0
+            firemode = 0;
+        }
+        if (firemode == getFiremode("RocketFire"))
+        {
+            this->timeout_ = 5;
+            this->rocketsLeft_--;
+            this->bFiredRocket_ = true;
+        }
+        if (firemode == getFiremode("SimpleRocketFire"))
+        {
+            this->rocketsLeft_--;
+        }
+              
+        this->getControllableEntity()->fire(firemode);
+        
+    }
+    void FightingController::setupWeapons() //TODO: Make this function generic!! (at the moment is is based on conventions)
+    {
+        this->bSetupWorked = false;
+        if(this->getControllableEntity())
+        {
+            Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
+            if(pawn && pawn->isA(Class(SpaceShip))) //fix for First Person Mode: check for SpaceShip
+            {
+                this->weaponModes_.clear(); // reset previous weapon information
+                WeaponSlot* wSlot = nullptr;
+                for(int l=0; (wSlot = pawn->getWeaponSlot(l)) ; l++)
+                {
+                    WeaponMode* wMode = nullptr;
+                    for(int i=0; (wMode = wSlot->getWeapon()->getWeaponmode(i)) ; i++)
+                    {
+                        std::string wName = wMode->getIdentifier()->getName();
+                        // SubclassIdentifier<Munition> munition =  ClassByString(wName);
+                        if (wName == "RocketFire")
+                            this->rocketsLeft_ = 10;
+                        if(this->getFiremode(wName) == -1) //only add a weapon, if it is "new"
+                            weaponModes_[wName] = wMode->getMode();
+                    }
+                }
+                if(weaponModes_.size())//at least one weapon detected
+                    this->bSetupWorked = true;
+            }
+        }
+
+    }
+
+    int FightingController::getFiremode(const std::string& name)
+    {
+        for (const auto& mapEntry : this->weaponModes_)
+        {
+            if (mapEntry.first == name)
+                return mapEntry.second;
+        }
+        return -1;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/FightingController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/FightingController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/FightingController.h	(revision 11817)
@@ -0,0 +1,103 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      Fabian 'x3n' Landau, Dominik Solenicki
+ *
+ */
+
+#ifndef _FightingController_H__
+#define _FightingController_H__
+
+
+#include "controllers/FlyingController.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        FightingController stores all the fighting methods and member variables of AI.
+        Main methods here are maneuver() and dodge().
+    
+    @note
+        ActionpointController will not work, if there is no MasterController in the level!
+    */
+    class _OrxonoxExport FightingController : public FlyingController
+    {
+
+        public:
+            FightingController(Context* context);
+            virtual ~FightingController();
+            
+            float squaredDistanceToTarget() const;
+            bool isLookingAtTarget(float angle) const;
+            bool hasTarget() const;
+            ControllableEntity* getTarget() const
+                { return this->target_; }
+            bool bKeepFormation_;   //even if action_ == FIGHT, you might still want to keep formation if far enough form the target
+            virtual void maneuver(); //<! sets this->targetPosition_, which is a Vector3 of where this ship flies. Decision is made based on
+                             //<! the distance to enemy, if being attacked, dodge() is called, otherwise ship just flies towards this->target_.
+            bool bShooting_;    //<! if true, ship shoots each tick
+            bool canFire(); //<! check if target_ is in radius and if this is looking at target_
+        protected:
+            void setTarget(ControllableEntity* target); //set a target to shoot at
+
+            void setPositionOfTarget(const Vector3& target);    //good to know where target is
+            void setOrientationOfTarget(const Quaternion& orient);  //I don't really use that
+            void stopLookingAtTarget();     //<! target dead -> you need to be able to fly
+            void startLookingAtTarget();    //<! if close to target, no need to fly, just rotate yourself
+            void lookAtTarget(float dt);    //<! rotate yourself towards target
+
+            void dodge(const Vector3& thisPosition, float diffLength,  Vector3& diffUnit); //<! choose a random Vector3 perpendicular to the difference vector between
+                                                                        //<! this and target_ plus or minus some amount in difference vector direction,
+                                                                        //<! depending on whether it is better to close up or survive.
+            void doFire();  //<! choose weapon, set aim at target_ and fire
+            WeakPtr<ControllableEntity> target_;
+            void setClosestTarget();
+         
+            bool bHasPositionOfTarget_;
+            Vector3 positionOfTarget_;
+            bool bHasOrientationOfTarget_;
+            Quaternion orientationOfTarget_;
+            Pawn* closestTarget() const;
+
+            bool bDodge_;
+            int attackRange_;
+            bool bLookAtTarget_; 
+            float deltaHp;
+            float previousHp;
+            bool bStartedDodging_;
+            //WEAPONSYSTEM DATA
+            int rocketsLeft_;
+            int timeout_;
+            bool bFiredRocket_;
+            std::map<std::string, int> weaponModes_; //<! Links each "weapon" to it's weaponmode - managed by setupWeapons()
+            //std::vector<int> projectiles_; //<! Displays amount of projectiles of each weapon. - managed by setupWeapons()
+            void setupWeapons(); //<! Defines which weapons are available for a bot. Is recalled whenever a bot was killed.
+            bool bSetupWorked; //<! If false, setupWeapons() is called.
+            int getFiremode(const std::string& name);
+          
+    };
+}
+
+#endif /* _FightingController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/FlyingController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/FlyingController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/FlyingController.cc	(revision 11817)
@@ -0,0 +1,289 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+
+ *   Co-authors:
+ *   ...
+ *
+ */
+#include <OgreMatrix3.h>                        //for Quaternion manipulations
+
+#include "util/Math.h"                          
+#include "core/XMLPort.h"
+#include "controllers/FlyingController.h"
+
+#include "worldentities/pawns/SpaceShip.h"      //for boosting
+
+namespace orxonox
+{    
+    const float FlyingController::SPEED = 0.9f/0.02f;
+    const float FlyingController::ROTATEFACTOR = 0.6f/0.02f;
+
+    RegisterClass (FlyingController);
+    
+    FlyingController::FlyingController(Context* context): CommonController(context)
+    {
+        RegisterObject(FlyingController);        
+        this->rotationProgress_ = 0;
+        this->spread_ = 200;
+        this->tolerance_ = 80;
+        this->bCopyOrientation_ = true;
+    }
+    FlyingController::~FlyingController() 
+    {
+    }
+
+    void FlyingController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(FlyingController, "spread", setSpread, getSpread,  xmlelement, mode);
+        XMLPortParam(FlyingController, "formationMode", setFormationModeXML, getFormationModeXML,  xmlelement, mode);
+        SUPER(FlyingController, XMLPort, xmlelement, mode);
+    }
+   
+    void FlyingController::setFormationModeXML(const std::string& val)
+    {
+        const std::string valUpper = getUppercase(val);
+        FormationMode value;
+        
+        if (valUpper == "WALL")
+            value = FormationMode::WALL;
+        else if (valUpper == "FINGER4")
+            value = FormationMode::FINGER4;
+        else if (valUpper == "DIAMOND")
+            value = FormationMode::DIAMOND;
+        else
+            ThrowException(ParseError, std::string("Attempting to set an unknown FormationMode: '")+ val + "'.");
+        this->setFormationMode(value);
+    }
+    std::string FlyingController::getFormationModeXML() const
+    {
+        switch (this->formationMode_)
+        {
+            case FormationMode::WALL:
+            { return "WALL"; }
+            case FormationMode::FINGER4:
+            { return "FINGER4"; }
+            case FormationMode::DIAMOND:
+            { return "DIAMOND"; }
+            default:
+                return "DIAMOND";
+        }
+    }
+    void FlyingController::stopMoving()
+    {
+        this->bHasTargetPosition_ = false;
+    }
+    /**
+    @brief
+      if distance to targetPosition is smaller than this->tolerance_, no moving should be made, otherwise
+      find amount of yaw and pitch that have to be applied, so that ship looks at targetPosition, then
+      ship is moved forward towards targetPosition. Also target orientation is being applied.
+    */
+    void FlyingController::moveToPosition(const Vector3& targetPosition, float dt)
+    {
+        if (!this->getControllableEntity())
+            return;
+        ControllableEntity* entity = this->getControllableEntity();
+
+        float distance = (targetPosition - entity->getPosition()).length();
+
+        if (distance >= this->tolerance_)
+        {
+            //function that calculates how much yaw and pitch are to be applied
+            Vector2 coord = get2DViewCoordinates
+                (entity->getPosition() , 
+                entity->getOrientation()  * WorldEntity::FRONT, 
+                entity->getOrientation()  * WorldEntity::UP, 
+                targetPosition);
+            //limit yaw and pitch by [-1,1]
+            float rotateX = -clamp(coord.x * 10, -1.0f, 1.0f);
+            float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
+
+            if (!entity)
+                return;
+
+            //apply yaw and pitch
+            entity->rotateYaw(ROTATEFACTOR * rotateX * dt);
+            entity->rotatePitch(ROTATEFACTOR * rotateY * dt);
+            
+            if (!entity)
+                return;
+           
+            //only move either if ship looks at target with a certain tolerance, or if ship is far enough for it to be ok to move in a curve.
+            if (distance > this->tolerance_*1.5f || (rotateX > -0.03 && rotateX < 0.03 && rotateY > -0.03 && rotateY < 0.03))
+                entity->moveFrontBack(SPEED * dt);
+            //roll
+            copyTargetOrientation(dt);
+        }
+        else
+        {      
+            bHasTargetPosition_ = false;
+        }
+    }
+    /**
+    @brief
+      fly towards a preset targetPosition_
+    */
+    void FlyingController::moveToTargetPosition(float dt)
+    {
+        this->moveToPosition (this->targetPosition_, dt);
+    }
+    /**
+    @brief
+      roll ship so that it has same roll as orient
+    */
+    void FlyingController::copyOrientation(const Quaternion& orient, float dt)
+    {
+        //copied from
+        //http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Quaternion+and+Rotation+Primer&structure=Tutorials#Q._How_can_I_make_my_objects_rotate_smoothly_You_mentioned_slerp_etc_
+        //how can I make my objects rotate smoothly?
+        if (!this->getControllableEntity())
+            return;
+        Quaternion myOrient = this->getControllableEntity()->getOrientation();
+        this->rotationProgress_ += dt;
+
+        if (this->rotationProgress_ > 1)
+        {
+            this->rotationProgress_ = 0;
+            this->bHasTargetOrientation_ = false;
+        }
+        else
+        {
+            Quaternion deltaOrientation = Quaternion::Slerp(rotationProgress_, myOrient, orient, true);
+            
+            Matrix3 deltaMatrix, myMatrix;
+
+            deltaOrientation.ToRotationMatrix(deltaMatrix);
+            myOrient.ToRotationMatrix (myMatrix);
+
+            Radian yawDelta, pitchDelta, rollDelta, yawMy, pitchMy, rollMy;
+            deltaMatrix.ToEulerAnglesYXZ(yawDelta, pitchDelta, rollDelta);
+            myMatrix.ToEulerAnglesYXZ (yawMy, pitchMy, rollMy);
+
+            if (!this->getControllableEntity())
+                return;
+            this->getControllableEntity()->rotateRoll ((rollDelta.valueRadians() - rollMy.valueRadians())*ROTATEFACTOR*dt);
+        }
+    }
+    /**
+    @brief
+      roll ship so that it has same roll as a preset targetOrientation_
+    */
+    void FlyingController::copyTargetOrientation(float dt)
+    {
+        if (bHasTargetOrientation_)
+        {   
+            this->copyOrientation(targetOrientation_, dt);
+        }
+    }
+    /**
+    @brief
+      set Vector to fly to
+    */
+    void FlyingController::setTargetPosition(const Vector3& target)
+    {
+        this->targetPosition_ = target;
+        this->bHasTargetPosition_ = true;
+    }
+    /**
+    @brief
+      set orientation to apply
+    */
+    void FlyingController::setTargetOrientation(const Quaternion& orient)
+    {
+        this->targetOrientation_=orient;
+        this->bHasTargetOrientation_=true;
+    }
+    /**
+    @brief
+      set orientation to apply
+    */
+    void FlyingController::setTargetOrientation(ControllableEntity* target)
+    {
+        if (target)
+            this->setTargetOrientation(target->getOrientation());
+    }
+    /**
+    @brief
+      boost if you can
+    */
+    void FlyingController::boostControl()
+    {
+        if (!this->getControllableEntity())
+            return;
+        SpaceShip* ship = orxonox_cast<SpaceShip*>(this->getControllableEntity());
+        if(ship == nullptr) return;
+        if(ship->getBoostPower()*1.5f > ship->getInitialBoostPower()) //upper limit ->boost
+        {
+            this->getControllableEntity()->boost(true);
+        }
+        else if(ship->getBoostPower()*4.0f < ship->getInitialBoostPower()) //lower limit ->do not boost
+        {
+           this->getControllableEntity()->boost(false);
+        }
+    }
+    /**
+    @brief
+      keep this ship in a formation with its division
+    */
+    void FlyingController::keepFormation(const ControllableEntity* leaderEntity, Vector3& targetRelativePosition)
+    {
+        if (!this->getControllableEntity())
+            return;
+        ControllableEntity* myEntity = this->getControllableEntity();
+        Vector3 myPosition = myEntity->getWorldPosition();
+
+        if (!leaderEntity)
+        {
+            return;
+        }
+        Quaternion orient = leaderEntity->getWorldOrientation();
+        Vector3 leaderPosition = leaderEntity->getWorldPosition();
+
+        if (!leaderEntity)
+        {
+            return;
+        }
+        //calculate where in world coordinates this ship should fly
+        Vector3 targetAbsolutePosition = 
+            (leaderPosition + (orient*WorldEntity::FRONT) * (leaderEntity->getVelocity().length()/5)
+             + (orient* (targetRelativePosition)));
+        //let ship finish rotating. also don't call copyOrientation too often as it is a slow function. Don't know how to do it different
+        if (this->bCopyOrientation_)
+            this->setTargetOrientation (orient);
+        //set a position to fly to
+        this->setTargetPosition (targetAbsolutePosition);
+
+        //boost if too far
+        if ((targetAbsolutePosition - myPosition).length() > this->tolerance_ * 1.5f)
+        {
+            this->boostControl();
+        }
+        else
+        {
+            if (!this->getControllableEntity())
+                return;
+            this->getControllableEntity()->boost(false);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/FlyingController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/FlyingController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/FlyingController.h	(revision 11817)
@@ -0,0 +1,102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      Dominik Solenicki
+ *
+ */
+
+#ifndef _FlyingController_H__
+#define _FlyingController_H__
+
+
+#include "controllers/CommonController.h"
+
+namespace orxonox
+{   
+    /**
+    @brief
+        FlyingController stores all the flying methods and member variables of AI.
+    */
+
+    //Formation mode for the divisions
+    enum class FormationMode
+    {
+        FINGER4, DIAMOND, WALL
+    };
+
+    class _OrxonoxExport FlyingController : public CommonController
+    {
+
+        public:
+            static const float SPEED;              //<! ship's speed
+            static const float ROTATEFACTOR;       //<! ship's rotation factor
+ 
+            FlyingController(Context* context);
+            virtual ~FlyingController();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setSpread (int spread)                         //<! spread is a multiplier for formation flight, should be bigger than 100
+                { this->spread_ = spread; }
+            int getSpread () const                              
+                { return this->spread_; }
+
+            void setFormationModeXML(const std::string& val);
+            std::string getFormationModeXML() const;
+
+            void setFormationMode(FormationMode val)
+                { this->formationMode_ = val; }
+            FormationMode getFormationMode() const
+                { return this->formationMode_; }
+            bool bCopyOrientation_;                             //<! set to true by default, MasterController sets it in its tick(),
+                                                                //<! if true, this will set its leader orientation as target orientation in action()
+        protected:
+            void stopMoving();                                  //<! don't call moveToTargetPosition() in tick, call lookAtTarget() from FightingController instead
+
+            void moveToPosition(const Vector3& target, float dt);   //<! move towards a vector
+            void moveToTargetPosition(float dt);                    //<! move to the preset position. Don't mix with positionOfTarget!
+
+            void copyOrientation(const Quaternion& orient, float dt);   //<! roll to have same roll as orient
+            void copyTargetOrientation(float dt);                       //<! roll to have a preset orient
+
+            void setTargetPosition(const Vector3& target);              //<! preset a Vector to fly to
+            void setTargetOrientation(const Quaternion& orient);        //<! preset a desired orientation
+            void setTargetOrientation(ControllableEntity* target);      //<! preset a desired orientation
+            virtual void boostControl();                                //<! boost if you can
+            void keepFormation (const ControllableEntity* leaderEntity, 
+                                Vector3& targetRelativePosition);   //<! preset targetPosition, so that 
+                                                                    //<! this stays in a certain position relative to leader      
+            
+            FormationMode formationMode_;
+          
+            float rotationProgress_;    //<! for slerping 
+            bool bHasTargetPosition_;
+            Vector3 targetPosition_;    //<! vector to fly to
+            bool bHasTargetOrientation_;
+            Quaternion targetOrientation_;  //<! orientation to take
+            int spread_;                //<! spread is a multiplier for formation flight, should be bigger than 100
+            int tolerance_;             //<! if this ship is tolerance_ away from targetPosition_, ship decides that it finished moving
+    };
+}
+
+#endif /* _FlyingController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/FormationController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/FormationController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/FormationController.cc	(revision 11817)
@@ -0,0 +1,1102 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      Dominik Solenicki
+ *
+ */
+
+#include <climits>
+#include "controllers/FormationController.h"
+
+#include "core/CoreIncludes.h"
+
+#include "core/XMLPort.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/pawns/TeamBaseMatchBase.h"
+#include "gametypes/TeamDeathmatch.h"
+#include "gametypes/Dynamicmatch.h"
+#include "gametypes/Mission.h"
+#include "gametypes/Gametype.h"
+#include "controllers/WaypointPatrolController.h"
+#include "controllers/NewHumanController.h"
+#include "controllers/DroneController.h"
+
+
+namespace orxonox
+{
+
+    SetConsoleCommand("FormationController", "formationflight",  &FormationController::formationflight);
+    SetConsoleCommand("FormationController", "masteraction",     &FormationController::masteraction);
+    SetConsoleCommand("FormationController", "followme",         &FormationController::followme);
+    SetConsoleCommand("FormationController", "passivebehaviour", &FormationController::passivebehaviour);
+    SetConsoleCommand("FormationController", "formationsize",    &FormationController::formationsize);
+
+    RegisterClass(FormationController);
+
+    static constexpr unsigned int STANDARD_MAX_FORMATION_SIZE = 9;
+    static constexpr int RADIUS_TO_SEARCH_FOR_MASTERS = 5000;
+    static constexpr float FORMATION_LENGTH =  110;
+    static constexpr float FORMATION_WIDTH =  110;
+    static constexpr int FREEDOM_COUNT = 4; //seconds the slaves in a formation will be set free when master attacks an enemy
+    static constexpr float SPEED_MASTER = 0.6f;
+    static constexpr float ROTATEFACTOR_MASTER = 0.2f;
+    static constexpr float SPEED_FREE = 0.8f;
+    static constexpr float ROTATEFACTOR_FREE = 0.8f;
+
+    FormationController::FormationController(Context* context) : Controller(context)
+    {
+        RegisterObject(FormationController);
+
+        this->target_ = nullptr;
+        this->formationFlight_ = false;
+        this->passive_ = false;
+        this->maxFormationSize_ = STANDARD_MAX_FORMATION_SIZE;
+        this->myMaster_ = nullptr;
+        this->freedomCount_ = 0;
+
+        this->state_ = FREE;
+        this->formationMode_ = NORMAL;
+        this->specificMasterAction_ = NONE;
+        this->specificMasterActionHoldCount_  = 0;
+        this->bShooting_ = false;
+        this->bHasTargetPosition_ = false;
+        this->bHasTargetOrientation_=false;
+        this->speedCounter_ = 0.2f;
+        this->targetPosition_ = Vector3::ZERO;
+        this->target_.setCallback(createFunctor(&FormationController::targetDied, this));
+    }
+
+    FormationController::~FormationController()
+    {
+        if (this->isInitialized())
+        {
+            this->removeFromFormation();
+
+            for (FormationController* controller : ObjectList<FormationController>())
+            {
+                if (controller != this)
+                {
+                    if (controller->myMaster_ == this)
+                    {
+                        orxout(internal_error) << this << " is still master in " << controller << endl;
+                        controller->myMaster_ = nullptr;
+                    }
+
+                    while (true)
+                    {
+                        std::vector<FormationController*>::iterator it2 = std::find(controller->slaves_.begin(), controller->slaves_.end(), this);
+                        if (it2 != controller->slaves_.end())
+                        {
+                            orxout(internal_error) << this << " is still slave in " << controller << endl;
+                            controller->slaves_.erase(it2);
+                        }
+                        else
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    void FormationController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FormationController, XMLPort, xmlelement, mode);
+
+        XMLPortParam(FormationController, "formationFlight", setFormationFlight, getFormationFlight, xmlelement, mode).defaultValues(false);
+        XMLPortParam(FormationController, "formationSize", setFormationSize, getFormationSize, xmlelement, mode).defaultValues(STANDARD_MAX_FORMATION_SIZE);
+        XMLPortParam(FormationController, "passive", setPassive, getPassive, xmlelement, mode).defaultValues(false);
+    }
+
+
+
+    /**
+        @brief Activates / deactivates formationflight behaviour
+        @param form activate formflight if form is true
+    */
+    void FormationController::formationflight(const bool form)
+    {
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            Controller* controller = nullptr;
+
+            if (pawn->getController())
+                controller = pawn->getController();
+            else if (pawn->getXMLController())
+                controller = pawn->getXMLController();
+
+            if (!controller)
+                continue;
+
+            FormationController *aiController = orxonox_cast<FormationController*>(controller);
+
+            if (aiController)
+            {
+                aiController->formationFlight_ = form;
+                if (!form)
+                {
+                    aiController->removeFromFormation();
+                }
+            }
+        }
+    }
+
+    /**
+        @brief Get all masters to do a "specific master action"
+        @param action which action to perform (integer, so it can be called with a console command (tmp solution))
+    */
+    void FormationController::masteraction(const int action)
+    {
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            Controller* controller = nullptr;
+
+            if (pawn->getController())
+                controller = pawn->getController();
+            else if (pawn->getXMLController())
+                controller = pawn->getXMLController();
+
+            if (!controller)
+                continue;
+
+            FormationController *aiController = orxonox_cast<FormationController*>(controller);
+
+            if(aiController && aiController->state_ == MASTER)
+            {
+                if (action == 1)
+                    aiController->spinInit();
+                if (action == 2)
+                    aiController->turn180Init();
+            }
+        }
+    }
+
+    /**
+        @brief Sets shooting behaviour of pawns.
+        @param passive if true, bots won't shoot.
+    */
+    void FormationController::passivebehaviour(const bool passive)
+    {
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            Controller* controller = nullptr;
+
+            if (pawn->getController())
+                controller = pawn->getController();
+            else if (pawn->getXMLController())
+                controller = pawn->getXMLController();
+
+            if (!controller)
+                continue;
+
+            FormationController *aiController = orxonox_cast<FormationController*>(controller);
+
+            if(aiController)
+            {
+                aiController->passive_ = passive;
+            }
+        }
+    }
+
+    /**
+        @brief Sets maximal formation size
+        @param size maximal formation size.
+    */
+    void FormationController::formationsize(const int size)
+    {
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            Controller* controller = nullptr;
+
+            if (pawn->getController())
+                controller = pawn->getController();
+            else if (pawn->getXMLController())
+                controller = pawn->getXMLController();
+
+            if (!controller)
+                continue;
+
+            FormationController *aiController = orxonox_cast<FormationController*>(controller);
+
+            if(aiController)
+            {
+                aiController->maxFormationSize_ = size;
+            }
+        }
+    }
+
+    //used, when slaves are in DEFEND mode.
+    void FormationController::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage)
+    {
+        if (!this->formationFlight_ || this->state_ != MASTER || this->formationMode_ != DEFEND)
+            return;
+        this->masterAttacked(originator);
+    }
+
+    void FormationController::removeFromFormation()
+    {
+        if (this->state_ == SLAVE || this->myMaster_) // slaves can also be temporary free, so check if myMaster_ is set
+            this->unregisterSlave();
+        else if (this->state_ == MASTER)
+            this->setNewMasterWithinFormation();
+    }
+
+    void FormationController::moveToPosition(const Vector3& target)
+    {
+        if (!this->getControllableEntity())
+            return;
+
+        // Slave uses special movement if its master is in FOLLOW mode
+        if(this->state_ == SLAVE && this->myMaster_ && this->myMaster_->specificMasterAction_ == FOLLOW)
+        {
+//             this->followForSlaves(target);
+//             return;
+        }
+
+        Vector2 coord = get2DViewCoordinates(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
+        float distance = (target - this->getControllableEntity()->getPosition()).length();
+        float rotateX = clamp(coord.x * 10, -1.0f, 1.0f);
+        float rotateY = clamp(coord.y * 10, -1.0f, 1.0f);
+
+        if(this->state_ == FREE)
+        {
+            if (this->target_ || distance > 10)
+            {
+                // Multiply with ROTATEFACTOR_FREE to make them a bit slower
+                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * rotateX);
+                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * rotateY);
+            }
+
+            if (this->target_ && distance <  200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
+            {
+              this->getControllableEntity()->moveFrontBack(-0.05f); // They don't brake with full power to give the player a chance
+            } else this->getControllableEntity()->moveFrontBack(SPEED_FREE);
+        }
+
+
+
+        if(this->state_ == MASTER)
+        {
+            if (this->target_ || distance > 10)
+            {
+                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_MASTER * rotateX);
+                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_MASTER * rotateY);
+            }
+
+            if (this->target_ && distance < 200 && this->getControllableEntity()->getVelocity().squaredLength() > this->target_->getVelocity().squaredLength())
+            {
+                this->getControllableEntity()->moveFrontBack(-0.05f);
+            } else this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
+        }
+
+
+
+        if(this->state_ == SLAVE)
+        {
+
+            this->getControllableEntity()->rotateYaw(-2.0f * ROTATEFACTOR_MASTER * rotateX);
+            this->getControllableEntity()->rotatePitch(2.0f * ROTATEFACTOR_MASTER * rotateY);
+
+            if (distance < 300)
+            {
+                if (bHasTargetOrientation_)
+                {
+                    copyTargetOrientation();
+                }
+                if (distance < 100)
+                { //linear speed reduction
+                    this->getControllableEntity()->moveFrontBack(distance/100.0f*0.4f*SPEED_MASTER);
+                }
+                else
+                    this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER);
+            }
+            else
+                this->getControllableEntity()->moveFrontBack(1.2f*SPEED_MASTER + distance/300.0f);
+        }
+
+        if (distance < 10)
+        {
+            this->positionReached();
+            bHasTargetOrientation_=false;
+        }
+    }
+
+
+
+    void FormationController::moveToTargetPosition()
+    {
+        this->moveToPosition(this->targetPosition_);
+    }
+
+    //copy the Roll orientation of given Quaternion.
+    void FormationController::copyOrientation(const Quaternion& orient)
+    {
+        //roll angle difference in radian
+        float diff=orient.getRoll(false).valueRadians()-(this->getControllableEntity()->getOrientation().getRoll(false).valueRadians());
+        while(diff>math::twoPi) diff-=math::twoPi;
+        while(diff<-math::twoPi) diff+=math::twoPi;
+        this->getControllableEntity()->rotateRoll(diff*ROTATEFACTOR_MASTER);
+    }
+
+    void FormationController::copyTargetOrientation()
+    {
+        if (bHasTargetOrientation_)
+        {
+            copyOrientation(targetOrientation_);
+        }
+    }
+
+
+    /**
+        @brief Unregisters a slave from its master. Initiated by a slave.
+    */
+    void FormationController::unregisterSlave()
+    {
+        if (this->myMaster_)
+        {
+            std::vector<FormationController*>::iterator it = std::find(this->myMaster_->slaves_.begin(), this->myMaster_->slaves_.end(), this);
+            if (it != this->myMaster_->slaves_.end())
+                this->myMaster_->slaves_.erase(it);
+        }
+
+        this->myMaster_ = nullptr;
+        this->state_ = FREE;
+    }
+
+    void FormationController::searchNewMaster()
+    {
+        if (this->state_==SLAVE)
+           return;
+        if (!this->getControllableEntity())
+            return;
+
+        this->targetPosition_ = this->getControllableEntity()->getPosition();
+        this->forgetTarget();
+        int teamSize = 0;
+        //go through all pawns
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+
+            //same team?
+            Gametype* gt=this->getGametype();
+            if (!gt)
+            {
+                gt=pawn->getGametype();
+            }
+            if (!FormationController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(pawn),gt))
+                continue;
+
+            //has it an FormationController?
+            Controller* controller = nullptr;
+
+            if (pawn->getController())
+                controller = pawn->getController();
+            else if (pawn->getXMLController())
+                controller = pawn->getXMLController();
+
+            if (!controller)
+                continue;
+
+            //is pawn oneself?
+            if (orxonox_cast<ControllableEntity*>(pawn) == this->getControllableEntity())
+                continue;
+
+            teamSize++;
+
+            FormationController *newMaster = orxonox_cast<FormationController*>(controller);
+
+            //is it a master?
+            if (!newMaster || newMaster->state_ != MASTER)
+                continue;
+
+            float distance = (pawn->getPosition() - this->getControllableEntity()->getPosition()).length();
+
+            // is pawn in range?
+            if (distance < RADIUS_TO_SEARCH_FOR_MASTERS)
+            {
+                if(newMaster->slaves_.size() > this->maxFormationSize_) continue;
+
+                for(FormationController* slave : this->slaves_)
+                {
+                    slave->myMaster_ = newMaster;
+                    newMaster->slaves_.push_back(slave);
+                }
+                this->slaves_.clear();
+                this->state_ = SLAVE;
+
+                this->myMaster_ = newMaster;
+                newMaster->slaves_.push_back(this);
+
+                break;
+            }
+        }
+
+        if (this->state_ != SLAVE  && teamSize != 0)
+        {
+            this->state_ = MASTER;
+            this->myMaster_ = nullptr;
+        }
+    }
+
+    /**
+        @brief Commands the slaves of a master into a formation. Sufficiently fast not to be called within tick. Initiated by a master.
+    */
+    void FormationController::commandSlaves()
+    {
+        if(this->state_ != MASTER) return;
+
+        Quaternion orient = this->getControllableEntity()->getOrientation();
+        Vector3 dest = this->getControllableEntity()->getPosition();
+
+        // 1 slave: follow
+        if (this->slaves_.size() == 1)
+        {
+            dest += 4*orient*WorldEntity::BACK;
+            this->slaves_.front()->setTargetPosition(dest);
+        }
+        else
+        // formation:
+        {
+            dest += 1.0f*orient*WorldEntity::BACK;
+            Vector3 pos = Vector3::ZERO;
+            bool left=true;
+            int i = 1;
+
+            for(FormationController* slave : slaves_)
+            {
+                pos = Vector3::ZERO;
+                if (left)
+                {
+                    pos+=dest+i*FORMATION_WIDTH*(orient*WorldEntity::LEFT);
+                } else{
+                    pos+=dest+i*FORMATION_WIDTH*(orient*WorldEntity::RIGHT);
+                    i++;
+                    dest+=FORMATION_LENGTH*(orient*WorldEntity::BACK);
+                }
+                slave->setTargetOrientation(orient);
+                slave->setTargetPosition(pos);
+                left=!left;
+            }
+        }
+    }
+
+    /**
+        @brief Sets a new master within the formation. Called by a master.
+    */
+    void FormationController::setNewMasterWithinFormation()
+    {
+        if(this->state_ != MASTER) return;
+
+        if (!this->slaves_.empty())
+        {
+            FormationController *newMaster = this->slaves_.back();
+            this->slaves_.pop_back();
+
+            newMaster->state_ = MASTER;
+            newMaster->slaves_ = this->slaves_;
+            newMaster->myMaster_ = nullptr;
+
+            for(FormationController* slave : newMaster->slaves_)
+            {
+                slave->myMaster_ = newMaster;
+            }
+        }
+
+        this->slaves_.clear();
+        this->specificMasterAction_ = NONE;
+        this->state_ = FREE;
+    }
+
+
+    // Sets newMaster as the new master within the formation. Called by the master.
+    void FormationController::setNewMasterWithinFormation(FormationController* newMaster)
+        {
+            if(this->state_ != MASTER || newMaster->myMaster_ != this) return;
+
+            if (!this->slaves_.empty())
+            {
+                std::vector<FormationController*>::iterator it2 = std::find(this->slaves_.begin(), this->slaves_.end(), newMaster);
+                if (it2 != this->slaves_.end())
+                {
+                    this->slaves_.erase(it2);
+                }
+
+                newMaster->state_ = MASTER;
+                newMaster->slaves_ = this->slaves_;
+                newMaster->myMaster_ = nullptr;
+
+                for(FormationController* slave : newMaster->slaves_)
+                {
+                    slave->myMaster_ = newMaster;
+                }
+            }
+
+            this->slaves_.clear();
+            this->specificMasterAction_ = NONE;
+            this->state_ = FREE;
+        }
+
+
+
+  /**
+        @brief Frees all slaves from a master. Initiated by a master.
+    */
+    void FormationController::freeSlaves()
+    {
+        if(this->state_ != MASTER) return;
+
+        for(FormationController* slave : slaves_)
+        {
+            slave->state_ = FREE;
+            slave->myMaster_ = nullptr;
+        }
+        this->slaves_.clear();
+    }
+
+    /**
+        @brief Master sets its slaves free for @ref FREEDOM_COUNT seconds.
+    */
+    void FormationController::forceFreeSlaves()
+    {
+        if(this->state_ != MASTER) return;
+
+        for(FormationController* slave : slaves_)
+        {
+            slave->state_ = FREE;
+            slave->forceFreedom();
+            slave->targetPosition_ = this->targetPosition_;
+            slave->bShooting_ = true;
+//             (*it)->getControllableEntity()->fire(0);// fire once for fun
+        }
+    }
+
+    void FormationController::loseMasterState()
+    {
+        this->freeSlaves();
+        this->state_ = FREE;
+    }
+
+
+    void FormationController::forceFreedom()
+    {
+        this->freedomCount_ = FREEDOM_COUNT;
+    }
+
+    /**
+        @brief Checks wether caller has been forced free, decrements time to stay forced free.
+        @return true if forced free.
+    */
+    bool FormationController::forcedFree()
+    {
+        if(this->freedomCount_ > 0)
+        {
+            this->freedomCount_--;
+            return true;
+        } else return false;
+    }
+
+
+    /**
+        @brief Call to take the lead of formation (if free, become slave of nearest formation, then, if Slave, become Master)
+    */
+    void FormationController::takeLeadOfFormation()
+    {
+        if (!this->getControllableEntity() || this->state_==MASTER)
+            return;
+
+        //search new Master, then take lead
+        if (this->state_==FREE && this->myMaster_==nullptr)
+        {
+          searchNewMaster();
+        }
+
+        if (this->state_==SLAVE)  //become master of this formation
+        {
+            this->slaves_=this->myMaster_->slaves_;
+            this->myMaster_->slaves_.clear();
+            this->myMaster_->state_=SLAVE;
+            this->myMaster_->myMaster_=this;
+
+            //delete myself in slavelist
+            std::vector<FormationController*>::iterator it2 = std::find(this->slaves_.begin(), this->slaves_.end(), this);
+            if (it2 != this->slaves_.end())
+            {
+                 this->slaves_.erase(it2);
+            }
+            //add previous master
+            this->slaves_.push_back(this->myMaster_);
+            //set this as new master
+            for(FormationController* slave : slaves_)
+            {
+                 slave->myMaster_=this;
+            }
+            this->myMaster_=nullptr;
+            this->state_=MASTER;
+        }
+        /*/debug
+        if (this->state_==SLAVE)
+           {orxout(debug_output) << this << " is slave "<< endl;}
+        else if (this->state_==MASTER)
+           {orxout(debug_output) << this << " is now a master of "<<this->slaves_.size()<<" slaves."<< endl;}
+        if (this->state_==FREE)
+           {orxout(debug_output) << this << " is free "<< endl;}*/
+    }
+    /**
+      @brief if called, half of the formation will attack the originator
+    */
+    void FormationController::masterAttacked(Pawn* originator)
+    {
+       if (this->state_!=MASTER) return;
+       unsigned int i=0;
+       for(std::vector<FormationController*>::reverse_iterator it = slaves_.rbegin(); it != slaves_.rend(); it++)
+       {
+           if ((*it)->state_!=FREE)
+           {
+               (*it)->state_=FREE;
+               (*it)->forceFreedom();
+               (*it)->setTarget(originator);
+           }
+           i++;
+           if (i>=slaves_.size()/2) break; //half the formation should attack.
+       }
+    }
+
+
+    /**
+      @brief Sets the new mode. If master, set it for all slaves.
+    */
+    void FormationController::setFormationMode(FormationMode val)
+    {
+        this->formationMode_ = val;
+        if (this->state_ == MASTER)
+        {
+            for(FormationController* slave : slaves_)
+            {
+                 slave->formationMode_ = val;
+                 if (val == ATTACK)
+                     slave->forgetTarget();
+            }
+        }
+    }
+
+    /**
+        @brief Used to continue a "specific master action" for a certain time and resuming normal behaviour after.
+    */
+    void FormationController::specificMasterActionHold()
+    {
+        if(this->state_ != MASTER) return;
+
+        if (specificMasterActionHoldCount_ == 0)
+        {
+            this->specificMasterAction_ = NONE;
+            this->searchNewTarget();
+        }
+        else
+            specificMasterActionHoldCount_--;
+    }
+
+    /**
+        @brief Master initializes a 180 degree turn. Leads to a "specific master action".
+    */
+    void FormationController::turn180Init()
+    {
+        if(this->state_ != MASTER) return;
+
+        Quaternion orient = this->getControllableEntity()->getOrientation();
+
+        this->setTargetPosition(this->getControllableEntity()->getPosition() + 1000.0f*orient*WorldEntity::BACK);
+
+        this->specificMasterActionHoldCount_ = 4;
+
+        this->specificMasterAction_ = TURN180;
+    }
+
+    /**
+        @brief Execute the 180 degree turn. Called within tick.
+    */
+    void FormationController::turn180()
+    {
+        Vector2 coord = get2DViewdirection(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, this->targetPosition_);
+
+        this->getControllableEntity()->rotateYaw(-2.0f * sgn(coord.x) * coord.x*coord.x);
+        this->getControllableEntity()->rotatePitch(2.0f * sgn(coord.y) * coord.y*coord.y);
+
+        this->getControllableEntity()->moveFrontBack(SPEED_MASTER);
+    }
+
+    /**
+        @brief Master initializes a spin around its looking direction axis. Leads to a "specific master action".
+    */
+    void FormationController::spinInit()
+    {
+        if(this->state_ != MASTER) return;
+        this->specificMasterAction_ = SPIN;
+        this->specificMasterActionHoldCount_ = 10;
+    }
+
+    /**
+        @brief Execute the spin. Called within tick.
+    */
+    void FormationController::spin()
+    {
+        this->moveToTargetPosition();
+        this->getControllableEntity()->rotateRoll(0.8f);
+    }
+
+  /**
+        @brief A human player gets followed by its nearest master. Initiated by console command, so far intended for demonstration puproses (possible future pickup).
+    */
+    void FormationController::followme()
+    {
+
+        Pawn *humanPawn = nullptr;
+        NewHumanController *currentHumanController = nullptr;
+        std::vector<FormationController*> allMasters;
+
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            Controller* controller = nullptr;
+
+            if (pawn->getController())
+                controller = pawn->getController();
+            else if (pawn->getXMLController())
+                controller = pawn->getXMLController();
+
+            if (!controller)
+                continue;
+
+            currentHumanController = orxonox_cast<NewHumanController*>(controller);
+
+            if(currentHumanController) humanPawn = pawn;
+
+            FormationController *aiController = orxonox_cast<FormationController*>(controller);
+
+            if(aiController && aiController->state_ == MASTER)
+                allMasters.push_back(aiController);
+
+        }
+
+        if((humanPawn != nullptr) && (allMasters.size() != 0))
+        {
+            float posHuman = humanPawn->getPosition().length();
+            float distance = 0.0f;
+            float minDistance = FLT_MAX;
+            int index = 0;
+            int i = 0;
+
+            for(FormationController* master : allMasters)
+            {
+                if (!FormationController::sameTeam(master->getControllableEntity(), humanPawn, master->getGametype())) continue;
+                distance = posHuman - master->getControllableEntity()->getPosition().length();
+                if(distance < minDistance) index = i;
+                i++;
+            }
+            allMasters[index]->followInit(humanPawn);
+        }
+    }
+
+    /**
+        @brief Master begins to follow a pawn. Is a "specific master action".
+        @param pawn pawn to follow.
+        @param always follows pawn forever if true (false if omitted).
+        @param secondsToFollow seconds to follow the pawn if always is false. Will follow pawn 100 seconds if omitted (set in header).
+    */
+    void FormationController::followInit(Pawn* pawn, const bool always, const int secondsToFollow)
+    {
+        if (pawn == nullptr || this->state_ != MASTER)
+            return;
+        this->specificMasterAction_  =  FOLLOW;
+
+        this->setTarget(pawn);
+        if (!always)
+            this->specificMasterActionHoldCount_ = secondsToFollow;
+        else
+            this->specificMasterActionHoldCount_ = INT_MAX; //for now...
+
+    }
+
+    /**
+        @brief Master begins to follow a randomly chosen human player of the same team. Is a "specific master action".
+    */
+    void FormationController::followRandomHumanInit()
+    {
+
+        Pawn *humanPawn = nullptr;
+        NewHumanController *currentHumanController = nullptr;
+
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if (!pawn->getController())
+                continue;
+
+            currentHumanController = orxonox_cast<NewHumanController*>(pawn->getController());
+            if(currentHumanController)
+            {
+                if (!FormationController::sameTeam(this->getControllableEntity(), pawn, this->getGametype())) continue;
+                humanPawn = pawn;
+                break;
+            }
+        }
+
+        if((humanPawn != nullptr))
+                this->followInit(humanPawn);
+    }
+
+
+    /**
+        @brief Master follows target with adjusted speed. Called within tick.
+    */
+    void FormationController::follow()
+    {
+        if (this->target_)
+            this->moveToPosition(this->target_->getPosition());
+        else
+            this->specificMasterActionHoldCount_ = 0;
+    }
+
+
+    void FormationController::setTargetPosition(const Vector3& target)
+    {
+        this->targetPosition_ = target;
+        this->bHasTargetPosition_ = true;
+    }
+
+    void FormationController::searchRandomTargetPosition()
+    {
+        this->targetPosition_ = Vector3(rnd(-2000,2000), rnd(-2000,2000), rnd(-2000,2000));
+        this->bHasTargetPosition_ = true;
+    }
+
+    void FormationController::setTargetOrientation(const Quaternion& orient)
+    {
+        this->targetOrientation_=orient;
+        this->bHasTargetOrientation_=true;
+    }
+
+    void FormationController::setTargetOrientation(Pawn* target)
+    {
+        if (target)
+            setTargetOrientation(target->getOrientation());
+    }
+
+    void FormationController::setTarget(Pawn* target)
+    {
+        this->target_ = target;
+
+        if (target)
+            this->targetPosition_ = target->getPosition();
+    }
+
+    void FormationController::searchNewTarget()
+    {
+        if (!this->getControllableEntity())
+            return;
+
+        this->targetPosition_ = this->getControllableEntity()->getPosition();
+        this->forgetTarget();
+
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if (FormationController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(pawn), this->getGametype()))
+                continue;
+
+            /* So AI won't choose invisible Spaceships as target */
+            if (!pawn->getRadarVisibility())
+                continue;
+
+            if (static_cast<ControllableEntity*>(pawn) != this->getControllableEntity())
+            {
+                float speed = this->getControllableEntity()->getVelocity().length();
+                Vector3 distanceCurrent = this->targetPosition_ - this->getControllableEntity()->getPosition();
+                Vector3 distanceNew = pawn->getPosition() - this->getControllableEntity()->getPosition();
+                if (!this->target_ || pawn->getPosition().squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceNew) / speed / distanceNew.length()) / math::twoPi)
+                        < this->targetPosition_.squaredDistance(this->getControllableEntity()->getPosition()) * (1.5f + acos((this->getControllableEntity()->getOrientation() * WorldEntity::FRONT).dotProduct(distanceCurrent) / speed / distanceCurrent.length()) / math::twoPi) + rnd(-250, 250))
+                {
+                    this->setTarget(pawn);
+                }
+            }
+        }
+    }
+
+    void FormationController::forgetTarget()
+    {
+        this->target_ = nullptr;
+        this->bShooting_ = false;
+    }
+
+    void FormationController::targetDied()
+    {
+        this->forgetTarget();
+        this->searchRandomTargetPosition();
+    }
+
+    bool FormationController::sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype)
+    {
+
+
+        if (entity1 == entity2)
+            return true;
+
+        int team1 = entity1->getTeam();
+        int team2 = entity2->getTeam();
+
+        Controller* controller = nullptr;
+        if (entity1->getController())
+            controller = entity1->getController();
+        else
+            controller = entity1->getXMLController();
+        if (controller)
+        {
+            if (controller->getIdentifier()->getName() == "MasterController")
+                return true;
+            FormationController* ac = orxonox_cast<FormationController*>(controller);
+            if (ac)
+                team1 = ac->getTeam();
+        }
+
+        if (entity2->getController())
+            controller = entity2->getController();
+        else
+            controller = entity2->getXMLController();
+        if (controller)
+        {
+            if (controller->getIdentifier()->getName() == "MasterController")
+                return true;
+            FormationController* ac = orxonox_cast<FormationController*>(controller);
+            if (ac)
+                team2 = ac->getTeam();
+        }
+
+        TeamGametype* tdm = orxonox_cast<TeamGametype*>(gametype);
+        if (tdm)
+        {
+            if (entity1->getPlayer())
+                team1 = tdm->getTeam(entity1->getPlayer());
+
+            if (entity2->getPlayer())
+                team2 = tdm->getTeam(entity2->getPlayer());
+        }
+
+        TeamBaseMatchBase* base = nullptr;
+        base = orxonox_cast<TeamBaseMatchBase*>(entity1);
+        if (base)
+        {
+            switch (base->getState())
+            {
+                case BaseState::ControlTeam1:
+                    team1 = 0;
+                    break;
+                case BaseState::ControlTeam2:
+                    team1 = 1;
+                    break;
+                case BaseState::Uncontrolled:
+                default:
+                    team1 = -1;
+            }
+        }
+        base = orxonox_cast<TeamBaseMatchBase*>(entity2);
+        if (base)
+        {
+            switch (base->getState())
+            {
+                case BaseState::ControlTeam1:
+                    team2 = 0;
+                    break;
+                case BaseState::ControlTeam2:
+                    team2 = 1;
+                    break;
+                case BaseState::Uncontrolled:
+                default:
+                    team2 = -1;
+            }
+        }
+
+        DroneController* droneController = nullptr;
+        droneController = orxonox_cast<DroneController*>(entity1->getController());
+        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity2)
+            return true;
+        droneController = orxonox_cast<DroneController*>(entity2->getController());
+        if (droneController && static_cast<ControllableEntity*>(droneController->getOwner()) == entity1)
+            return true;
+        DroneController* droneController1 = orxonox_cast<DroneController*>(entity1->getController());
+        DroneController* droneController2 = orxonox_cast<DroneController*>(entity2->getController());
+        if (droneController1 && droneController2 && droneController1->getOwner() == droneController2->getOwner())
+            return true;
+
+        Dynamicmatch* dynamic = orxonox_cast<Dynamicmatch*>(gametype);
+        if (dynamic)
+        {
+            if (dynamic->notEnoughPigs||dynamic->notEnoughKillers||dynamic->notEnoughChasers) {return false;}
+
+            if (entity1->getPlayer())
+                team1 = dynamic->getParty(entity1->getPlayer());
+
+            if (entity2->getPlayer())
+                team2 = dynamic->getParty(entity2->getPlayer());
+
+            if (team1 ==-1 ||team2 ==-1 ) {return false;}
+            else if (team1 == dynamic->chaser && team2 != dynamic->chaser) {return false;}
+            else if (team1 == dynamic->piggy && team2 == dynamic->chaser) {return false;}
+            else if (team1 == dynamic->killer && team2 == dynamic->chaser) {return false;}
+            else return true;
+        }
+
+        return (team1 == team2 && team1 != -1);
+    }
+
+    void FormationController::absoluteMoveToPosition(const Vector3& target)
+    {
+        float minDistance = 40.0f;
+        if (!this->getControllableEntity())
+            return;
+
+        Vector2 coord = get2DViewCoordinates(this->getControllableEntity()->getPosition(), this->getControllableEntity()->getOrientation() * WorldEntity::FRONT, this->getControllableEntity()->getOrientation() * WorldEntity::UP, target);
+        float distance = (target - this->getControllableEntity()->getPosition()).length();
+
+            if (this->target_ || distance > minDistance)
+            {
+                // Multiply with ROTATEFACTOR_FREE to make them a bit slower
+                this->getControllableEntity()->rotateYaw(-1.0f * ROTATEFACTOR_FREE * clamp(coord.x * 10, -1.0f, 1.0f));
+                this->getControllableEntity()->rotatePitch(ROTATEFACTOR_FREE * clamp(coord.y * 10, -1.0f, 1.0f));
+                this->getControllableEntity()->moveFrontBack(SPEED_FREE);
+            }
+
+
+        if (distance < minDistance)
+        {
+            this->positionReached();
+        }
+    }
+
+    void FormationController::changedControllableEntity()
+    {
+        Controller::changedControllableEntity(); // super
+
+        // when changing the controllable entity, ensure that the controller does not use the new entity as target
+        if (this->target_ && this->getControllableEntity() == static_cast<ControllableEntity*>(this->target_))
+            this->forgetTarget();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/FormationController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/FormationController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/FormationController.h	(revision 11817)
@@ -0,0 +1,182 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FormationController_h__
+#define _FormationController_h__
+
+#include "OrxonoxPrereqs.h"
+
+#include <vector>
+#include "core/class/Super.h"
+
+#include "util/Math.h"
+#include "controllers/Controller.h"
+#include "worldentities/ControllableEntity.h"
+
+
+namespace orxonox {
+
+  class _OrxonoxExport FormationController : public Controller
+  {
+
+      public:
+      FormationController(Context* context);
+
+      virtual ~FormationController();
+
+      virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+
+      static void formationflight(const bool form);
+      static void masteraction(const int action);
+      static void followme();
+      static void passivebehaviour(const bool passive);
+      static void formationsize(const int size);
+      void setNewMasterWithinFormation(FormationController* newMaster);
+
+      inline void setFormationFlight(bool formation)
+           { this->formationFlight_ = formation; }
+      inline bool getFormationFlight() const
+           { return this->formationFlight_; }
+
+      inline void setFormationSize(int size)
+           { this->maxFormationSize_ = size; }
+      inline int getFormationSize() const
+           { return this->maxFormationSize_; }
+
+
+      inline void setPassive(bool passive)
+           { this->passive_ = passive; }
+      inline bool getPassive() const
+           { return this->passive_; }
+
+
+
+      /**
+        @brief Mode of the formation, behaviour of slaves
+               Normal-normal behaviour
+               Defend-just defend the master
+               Attack-leave formation, attack every target
+      */
+      enum FormationMode {NORMAL,DEFEND,ATTACK};
+
+      /**
+        @brief Sets the new mode. If master, set it for all slaves.
+      */
+      void setFormationMode(FormationMode val);
+      inline FormationMode getFormationMode() const
+           { return this->formationMode_; }
+
+      virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, float damage) override;
+
+      FormationController* getMaster( void ) { return myMaster_; }
+      FormationController* getController( void ) { return this; }
+      FormationController* getSlave( void ) { return this->slaves_.back(); }
+
+      virtual void changedControllableEntity() override;
+
+  protected:
+      bool formationFlight_;
+      bool passive_;
+      unsigned int maxFormationSize_;
+      int freedomCount_;
+      enum State {SLAVE, MASTER, FREE};
+
+      State state_;
+      std::vector<FormationController*> slaves_;
+      FormationController* myMaster_;
+
+      FormationMode formationMode_;
+
+      enum SpecificMasterAction {NONE, HOLD, SPIN, TURN180, FOLLOW};
+      SpecificMasterAction specificMasterAction_;
+      int specificMasterActionHoldCount_;
+      float speedCounter_; //for speed adjustment when following
+
+      void moveToPosition(const Vector3& target);
+      void moveToTargetPosition();
+      void absoluteMoveToPosition(const Vector3& target);
+      void copyOrientation(const Quaternion& orient);
+      void copyTargetOrientation();
+
+      void removeFromFormation();
+      void unregisterSlave();
+      void searchNewMaster();
+      void commandSlaves();
+      void takeLeadOfFormation();
+      void loseMasterState();
+      void setNewMasterWithinFormation();
+
+      void freeSlaves();
+      void forceFreeSlaves();
+      void forceFreedom();
+      bool forcedFree();
+
+      void masterAttacked(Pawn* originator);
+
+      void specificMasterActionHold();
+      void turn180Init();
+      void spinInit();
+      void spin();
+      void turn180();
+      void followInit(Pawn* pawn, const bool always = false, const int secondsToFollow = 100);
+      void followRandomHumanInit();
+      void follow();
+
+      void setTargetPosition(const Vector3& target);
+      void searchRandomTargetPosition();
+
+      void setTargetOrientation(const Quaternion& orient);
+      void setTargetOrientation(Pawn* target);
+
+      virtual void positionReached() {}
+
+      static bool sameTeam(ControllableEntity* entity1, ControllableEntity* entity2, Gametype* gametype); // hack
+
+
+      void setTarget(Pawn* target);
+
+      void searchNewTarget();
+      void forgetTarget();
+
+      void targetDied();
+
+      bool bHasTargetPosition_;
+      Vector3 targetPosition_;
+      bool bHasTargetOrientation_;
+      Quaternion targetOrientation_;
+
+      WeakPtr<Pawn> target_;
+      bool bShooting_;
+  };
+
+
+}
+#endif /* _FormationController_h__ */
+
+
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/HumanController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/HumanController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/HumanController.cc	(revision 11817)
@@ -0,0 +1,349 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HumanController.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/pawns/Pawn.h"
+#include "gametypes/Gametype.h"
+#include "infos/PlayerInfo.h"
+#include "Radar.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    extern const std::string __CC_fire_name = "fire";
+    extern const std::string __CC_suicide_name = "suicide";
+
+    SetConsoleCommand("HumanController", "moveFrontBack",          &HumanController::moveFrontBack ).addShortcut().setAsInputCommand();
+    SetConsoleCommand("HumanController", "moveRightLeft",          &HumanController::moveRightLeft ).addShortcut().setAsInputCommand();
+    SetConsoleCommand("HumanController", "moveUpDown",             &HumanController::moveUpDown    ).addShortcut().setAsInputCommand();
+    SetConsoleCommand("HumanController", "rotateYaw",              &HumanController::rotateYaw     ).addShortcut().setAsInputCommand();
+    SetConsoleCommand("HumanController", "rotatePitch",            &HumanController::rotatePitch   ).addShortcut().setAsInputCommand();
+    SetConsoleCommand("HumanController", "rotateRoll",             &HumanController::rotateRoll    ).addShortcut().setAsInputCommand();
+    SetConsoleCommand("HumanController", "toggleFormationFlight",  &HumanController::toggleFormationFlight).addShortcut().keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("HumanController", "FFChangeMode",           &HumanController::FFChangeMode).addShortcut().keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("HumanController", __CC_fire_name,           &HumanController::fire          ).addShortcut().keybindMode(KeybindMode::OnHold);
+    SetConsoleCommand("HumanController", "reload",                 &HumanController::reload        ).addShortcut();
+    SetConsoleCommand("HumanController", "boost",                  &HumanController::boost         ).addShortcut().setAsInputCommand().keybindMode(KeybindMode::OnPressAndRelease);
+    SetConsoleCommand("HumanController", "greet",                  &HumanController::greet         ).addShortcut();
+    SetConsoleCommand("HumanController", "switchCamera",           &HumanController::switchCamera  ).addShortcut();
+    SetConsoleCommand("HumanController", "mouseLook",              &HumanController::mouseLook     ).addShortcut();
+    SetConsoleCommand("HumanController", __CC_suicide_name,        &HumanController::suicide       ).addShortcut();
+    SetConsoleCommand("HumanController", "toggleGodMode",          &HumanController::toggleGodMode ).addShortcut();
+    SetConsoleCommand("HumanController", "cycleNavigationFocus",   &HumanController::cycleNavigationFocus).addShortcut();
+    SetConsoleCommand("HumanController", "releaseNavigationFocus", &HumanController::releaseNavigationFocus).addShortcut();
+    SetConsoleCommand("HumanController", "myposition",             &HumanController::myposition    ).addShortcut();
+
+    RegisterUnloadableClass(HumanController);
+
+    HumanController* HumanController::localController_s = nullptr;
+
+    HumanController::HumanController(Context* context) : FormationController(context)
+    {
+        RegisterObject(HumanController);
+
+        this->controlPaused_ = false;
+        HumanController::localController_s = this;
+    }
+
+    HumanController::~HumanController()
+    {
+        if (HumanController::localController_s)
+        {
+            HumanController::localController_s->removeFromFormation();
+        }
+        HumanController::localController_s = nullptr;
+    }
+
+    void HumanController::tick(float dt)
+    {
+        if (GameMode::playsSound() && HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+        {
+            Camera* camera = HumanController::localController_s->controllableEntity_->getCamera();
+            if (!camera)
+                orxout(internal_warning) << "HumanController, Warning: Using a ControllableEntity without Camera" << endl;
+        }
+
+        // commandslaves when Master of a formation
+        if (HumanController::localController_s && HumanController::localController_s->state_==MASTER && FormationController::slaves_.size() > 0)
+        {
+            if (HumanController::localController_s->formationMode_ != ATTACK)
+                HumanController::localController_s->commandSlaves();
+        }
+    }
+
+    void HumanController::moveFrontBack(const Vector2& value)
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->frontback(value);
+    }
+
+    void HumanController::frontback(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->moveFrontBack(value);
+    }
+
+    void HumanController::moveRightLeft(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->moveRightLeft(value);
+    }
+
+    void HumanController::moveUpDown(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->moveUpDown(value);
+    }
+
+    void HumanController::yaw(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->rotateYaw(value);
+    }
+
+    void HumanController::pitch(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->rotatePitch(value);
+    }
+
+    void HumanController::rotateYaw(const Vector2& value)
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->yaw(value);
+    }
+
+    void HumanController::rotatePitch(const Vector2& value)
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->pitch(value);
+    }
+
+    void HumanController::rotateRoll(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->rotateRoll(value);
+    }
+
+    void HumanController::fire(unsigned int firemode)
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->doFire(firemode);
+    }
+
+    void HumanController::doFire(unsigned int firemode)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+        {
+            HumanController::localController_s->controllableEntity_->fire(firemode);
+            //if human fires, set slaves free. See FormationController::forceFreeSlaves()
+            if (HumanController::localController_s->state_==MASTER && HumanController::localController_s->formationMode_ == NORMAL)
+            {
+                HumanController::localController_s->forceFreeSlaves();
+            }
+        }
+    }
+
+    void HumanController::reload()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->reload();
+    }
+
+    /**
+    @brief
+        Static method, controls boosting.
+    */
+    /*static*/ void HumanController::boost(const Vector2& value)
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+        {
+            float abs = value.x;
+            if (abs > 0)
+                HumanController::localController_s->startBoosting();
+            else
+                HumanController::localController_s->stopBoosting();
+        }
+    }
+
+    /**
+    @brief
+        Starts the boosting mode.
+        Resets the boosting timeout and tells the ControllableEntity to boost (or not boost anymore).
+    */
+    void HumanController::startBoosting(void)
+    {
+        if(this->controllableEntity_)
+            this->controllableEntity_->boost(true);
+    }
+
+    /**
+    @brief
+        Stops the boosting mode.
+    */
+    void HumanController::stopBoosting(void)
+    {
+        if(this->controllableEntity_)
+            this->controllableEntity_->boost(false);
+    }
+
+    void HumanController::greet()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->greet();
+    }
+
+    void HumanController::switchCamera()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->switchCamera();
+    }
+
+    void HumanController::mouseLook()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->mouseLook();
+    }
+
+    void HumanController::suicide()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+        {
+            Pawn* pawn = orxonox_cast<Pawn*>(HumanController::localController_s->controllableEntity_);
+            if (pawn)
+                pawn->kill();
+            else if (HumanController::localController_s->player_)
+                HumanController::localController_s->player_->stopControl();
+        }
+    }
+
+    void HumanController::toggleGodMode()
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->setGodMode(!HumanController::localController_s->getGodMode());
+    }
+
+    void HumanController::myposition()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+        {
+            const Vector3& position = HumanController::localController_s->controllableEntity_->getPosition();
+            const Quaternion& orientation = HumanController::localController_s->controllableEntity_->getOrientation();
+
+            orxout(message) << "position=\"" << position.x << ", " << position.y << ", " << position.z << "\" "
+                            << "orientation=\"" << orientation.w << ", " << orientation.x << ", " << orientation.y << ", " << orientation.z << "\"" << endl;
+        }
+    }
+
+    /**
+    @brief
+       toggle the formation. Not usable, if formationflight is disabled generally (formationFlight_)
+    */
+    void HumanController::toggleFormationFlight()
+    {
+        if (HumanController::localController_s)
+        {
+            if (!HumanController::localController_s->formationFlight_)
+            {
+                return; //dont use when formationFlight is disabled
+            }
+            if (HumanController::localController_s->state_==MASTER)
+            {
+                HumanController::localController_s->loseMasterState();
+                orxout(message) <<"FormationFlight disabled "<< endl;
+            } else //SLAVE or FREE
+            {
+                HumanController::localController_s->takeLeadOfFormation();
+                orxout(message) <<"FormationFlight enabled "<< endl;
+            }
+
+        }
+
+    }
+
+    /**
+    @brief
+       Switch through the different Modes of formationflight. You must be a master of a formation to use.
+    */
+    void HumanController::FFChangeMode()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->state_==MASTER)
+        {
+            switch (HumanController::localController_s->getFormationMode()) {
+                case NORMAL:
+                    HumanController::localController_s->setFormationMode(DEFEND);
+                    orxout(message) <<"Mode: DEFEND "<< endl;
+                    break;
+                case DEFEND:
+                    HumanController::localController_s->setFormationMode(ATTACK);
+                    orxout(message) <<"Mode: ATTACK "<< endl;
+                    break;
+                case ATTACK:
+                    HumanController::localController_s->setFormationMode(NORMAL);
+                    orxout(message) <<"Mode: NORMAL "<< endl;
+                    break;
+            }
+        }
+    }
+
+    Pawn* HumanController::getLocalControllerEntityAsPawn()
+    {
+        if (HumanController::localController_s)
+            return orxonox_cast<Pawn*>(HumanController::localController_s->getControllableEntity());
+        else
+            return nullptr;
+    }
+
+    void HumanController::cycleNavigationFocus()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->getScene()->getRadar()->cycleFocus();
+    }
+
+    void HumanController::releaseNavigationFocus()
+    {
+        if (HumanController::localController_s && HumanController::localController_s->controllableEntity_)
+            HumanController::localController_s->controllableEntity_->getScene()->getRadar()->releaseFocus();
+    }
+
+    void HumanController::pauseControl()
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->doPauseControl();
+    }
+
+    void HumanController::resumeControl()
+    {
+        if (HumanController::localController_s)
+            HumanController::localController_s->doResumeControl();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/HumanController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/HumanController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/HumanController.h	(revision 11817)
@@ -0,0 +1,100 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HumanController_H__
+#define _HumanController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "tools/Timer.h"
+#include "tools/interfaces/Tickable.h"
+#include "FormationController.h"
+
+// tolua_begin
+namespace orxonox
+{
+    class _OrxonoxExport HumanController
+// tolua_end
+        : public FormationController, public Tickable
+    { // tolua_export
+        public:
+            HumanController(Context* context);
+            virtual ~HumanController();
+
+            virtual void tick(float dt) override;
+
+            static void moveFrontBack(const Vector2& value);
+            static void moveRightLeft(const Vector2& value);
+            static void moveUpDown(const Vector2& value);
+
+            static void rotateYaw(const Vector2& value);
+            static void rotatePitch(const Vector2& value);
+            static void rotateRoll(const Vector2& value);
+
+            virtual void frontback(const Vector2& value);
+            virtual void yaw(const Vector2& value);
+            virtual void pitch(const Vector2& value);
+
+            static void fire(unsigned int firemode);
+            virtual void doFire(unsigned int firemode);
+            static void reload();
+
+            static void boost(const Vector2& value); // Static method, controls boosting.
+            void startBoosting(void);
+            void stopBoosting(void);
+
+            static void greet();
+            static void switchCamera();
+            static void mouseLook();
+            static void cycleNavigationFocus();
+            static void releaseNavigationFocus();
+
+            static void suicide();
+            static void toggleGodMode();
+            static void myposition();
+
+            static void toggleFormationFlight();
+            static void FFChangeMode();
+
+            static void pauseControl(); // tolua_export
+            static void resumeControl(); // tolua_export
+            virtual void doPauseControl() {};
+            virtual void doResumeControl() {};
+
+            static inline HumanController* getLocalControllerSingleton()
+                { return HumanController::localController_s; }
+            static Pawn* getLocalControllerEntityAsPawn();
+
+        protected:
+            static HumanController* localController_s;
+            bool controlPaused_;
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _HumanController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/MasterController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/MasterController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/MasterController.cc	(revision 11817)
@@ -0,0 +1,129 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MasterController.h"
+#include "controllers/ActionpointController.h"
+namespace orxonox
+{
+
+    RegisterClass(MasterController);
+
+    //Leaders share the fact that they have Wingmans
+    MasterController::MasterController(Context* context) : Controller(context)
+    {
+        RegisterObject(MasterController);
+        this->controllers_.clear();
+        this->numberOfTicksPassedSinceLastActionCall_ = 0;
+        this->indexOfCurrentController_ = 0;
+        this->ticks_ = 0;
+    }
+
+    MasterController::~MasterController()
+    {
+        this->controllers_.clear();
+    } 
+    /*HACK*/
+    //the whole idea is a hack
+    void MasterController::tick(float dt)
+    {   
+        if (!this->isActive())
+            return;  
+        ++this->ticks_;
+        if (this->ticks_ == 1)
+        {
+            //fill the vector in the first tick
+            for (ActionpointController* controller : ObjectList<ActionpointController>())
+            {
+                //----0ptr?----
+                if (!controller)
+                    continue;
+                this->controllers_.push_back(controller);
+            }
+        }
+        else
+        {
+            if (this->controllers_.empty())
+                return;
+
+            //iterate over vecotr with the index, keep index in boundaries 
+            if (this->indexOfCurrentController_ >= this->controllers_.size())
+            {
+                this->indexOfCurrentController_ = 0;
+            }
+            //each 9 ticks index is incremented
+            if (this->numberOfTicksPassedSinceLastActionCall_ >= 9)
+            {
+                this->numberOfTicksPassedSinceLastActionCall_ = 0;
+            }
+
+            if (this->numberOfTicksPassedSinceLastActionCall_ > 0)
+            {
+                if (this->numberOfTicksPassedSinceLastActionCall_ == 3)
+                {
+                    //check if 0ptr
+                    if (!this->controllers_.at(this->indexOfCurrentController_))
+                    {
+                        this->controllers_.erase(this->controllers_.begin() + this->indexOfCurrentController_);
+                        return;
+                    }
+                    //call maneuver for current index
+                    this->controllers_.at(this->indexOfCurrentController_)->maneuver();
+                }
+                else if (this->numberOfTicksPassedSinceLastActionCall_ == 6)
+                {
+                    //check if 0ptr
+                    if (!this->controllers_.at(this->indexOfCurrentController_))
+                    {
+                        this->controllers_.erase(this->controllers_.begin() + this->indexOfCurrentController_);
+                        return;
+                    }
+                    //call canFire for current index
+                    this->controllers_.at(this->indexOfCurrentController_)->bShooting_ = this->controllers_.at(this->indexOfCurrentController_)->canFire();   
+                }
+                ++this->numberOfTicksPassedSinceLastActionCall_;
+            }
+            else
+            {
+                //check if 0ptr
+                if (!this->controllers_.at(this->indexOfCurrentController_))
+                {
+                    this->controllers_.erase(this->controllers_.begin() + this->indexOfCurrentController_);
+                    return;
+                }
+                //call action for current index
+                this->controllers_.at(this->indexOfCurrentController_)->action();   
+                 
+                //bCopyOrientation makes ship oscillate like crazy if set to true all the time.s
+                this->controllers_.at(this->indexOfCurrentController_)->bCopyOrientation_ = this->ticks_ % 3 == 0;
+
+                ++this->numberOfTicksPassedSinceLastActionCall_;
+                ++this->indexOfCurrentController_;
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/MasterController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/MasterController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/MasterController.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MasterController_H__
+#define _MasterController_H__
+
+#include "controllers/Controller.h"
+#include "controllers/ActionpointController.h"
+#include "tools/interfaces/Tickable.h"
+
+
+
+namespace orxonox
+{
+    /**
+    @brief
+      calles action(), maneuver() and canFire() methods of all the ActionpointControllers in level.
+      Only one instance of MasterController is to be placed in level.
+      If no MasterController is initialized, none of ActionpointControllers will work.
+      Example:
+
+      @code
+      <Pawn position = "100000, 100000, 100000">
+        <controller>
+          <MasterController>
+          </MasterController>
+        </controller>
+      </Pawn>
+      @endcode
+    */
+    class _OrxonoxExport MasterController : public Controller, public Tickable
+    {
+        public:
+            //----[language demanded functions]----            
+                MasterController(Context* context);
+
+                virtual ~MasterController();
+            //----[/language demanded functions]----            
+
+            //----[orxonox demanded functions]----
+                virtual void tick(float dt) override;
+
+            //----[orxonox demanded functions]----
+
+        protected:
+          
+        private:
+            std::vector<WeakPtr<ActionpointController>> controllers_;//<! vector of controllers, which action(), canFire() and maneuver() methods are to be called
+            size_t indexOfCurrentController_;                        //<! index of current controller
+            unsigned int numberOfTicksPassedSinceLastActionCall_;
+            unsigned int ticks_;                                     //<! local tick counter            
+
+    };
+}
+
+#endif /* _MasterController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/NewHumanController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/NewHumanController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/NewHumanController.cc	(revision 11817)
@@ -0,0 +1,625 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Michael Wirth
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "NewHumanController.h"
+
+#include <cmath>
+#include <OgreRay.h>
+#include <OgreSceneQuery.h>
+#include <OgreCamera.h>
+#include <OgreSceneManager.h>
+#include <bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+
+#include "core/CoreIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/input/KeyBinder.h"
+#include "core/input/KeyBinderManager.h"
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/pawns/Pawn.h"
+#include "infos/PlayerInfo.h"
+#include "overlays/OrxonoxOverlay.h"
+#include "graphics/Camera.h"
+#include "sound/SoundManager.h"
+#include "tools/BulletConversions.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    SetConsoleCommand("NewHumanController", "changeMode", &NewHumanController::changeMode).keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("NewHumanController", "accelerate", &NewHumanController::accelerate).keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("NewHumanController", "decelerate", &NewHumanController::decelerate).keybindMode(KeybindMode::OnPress);
+    SetConsoleCommand("NewHumanController", "unfire",     &NewHumanController::unfire    ).keybindMode(KeybindMode::OnRelease).addShortcut();
+
+    RegisterUnloadableClass(NewHumanController);
+
+    NewHumanController* NewHumanController::localController_s = nullptr;
+
+    NewHumanController::NewHumanController(Context* context)
+        : HumanController(context)
+        , crossHairOverlay_(nullptr)
+        , centerOverlay_(nullptr)
+        , damageOverlayTop_(nullptr)
+        , damageOverlayRight_(nullptr)
+        , damageOverlayBottom_(nullptr)
+        , damageOverlayLeft_(nullptr)
+        , damageOverlayTT_(0)
+        , damageOverlayTR_(0)
+        , damageOverlayTB_(0)
+        , damageOverlayTL_(0)
+        , arrowsOverlay1_(nullptr)
+        , arrowsOverlay2_(nullptr)
+        , arrowsOverlay3_(nullptr)
+        , arrowsOverlay4_(nullptr)
+    {
+        RegisterObject(NewHumanController);
+
+        overlaySize_ = 0.08f;
+        arrowsSize_ = 0.4f;
+
+        damageOverlayTime_ = 0.6f;
+
+        controlMode_ = 0;
+        acceleration_ = 0;
+        accelerating_ = false;
+        firemode_ = -1;
+
+        showArrows_ = true;
+        showOverlays_ = false;
+        showDamageOverlay_ = true;
+
+        //currentPitch_ = 1;
+        //currentYaw_ = 1;
+
+        if (GameMode::showsGraphics())
+        {
+            crossHairOverlay_ = new OrxonoxOverlay(this->getContext());
+            crossHairOverlay_->setBackgroundMaterial("Orxonox/Crosshair3");
+            crossHairOverlay_->setSize(Vector2(overlaySize_, overlaySize_));
+            crossHairOverlay_->hide();
+            //crossHairOverlay_->setAspectCorrection(true); not working
+
+            centerOverlay_ = new OrxonoxOverlay(this->getContext());
+            centerOverlay_->setBackgroundMaterial("Orxonox/CenterOverlay");
+            centerOverlay_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
+            centerOverlay_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
+            centerOverlay_->hide();
+
+            if (showDamageOverlay_)
+            {
+                damageOverlayTop_ = new OrxonoxOverlay(this->getContext());
+                damageOverlayTop_->setBackgroundMaterial("Orxonox/DamageOverlayTop");
+                damageOverlayTop_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
+                damageOverlayTop_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
+                damageOverlayTop_->hide();
+
+                damageOverlayRight_ = new OrxonoxOverlay(this->getContext());
+                damageOverlayRight_->setBackgroundMaterial("Orxonox/DamageOverlayRight");
+                damageOverlayRight_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
+                damageOverlayRight_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
+                damageOverlayRight_->hide();
+
+                damageOverlayBottom_ = new OrxonoxOverlay(this->getContext());
+                damageOverlayBottom_->setBackgroundMaterial("Orxonox/DamageOverlayBottom");
+                damageOverlayBottom_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
+                damageOverlayBottom_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
+                damageOverlayBottom_->hide();
+
+                damageOverlayLeft_ = new OrxonoxOverlay(this->getContext());
+                damageOverlayLeft_->setBackgroundMaterial("Orxonox/DamageOverlayLeft");
+                damageOverlayLeft_->setSize(Vector2(overlaySize_ * 2.5f, overlaySize_ * 2.5f));
+                damageOverlayLeft_->setPosition(Vector2(0.5f - overlaySize_*2.5f/2.0f, 0.5f - overlaySize_*2.5f/2.0f));
+                damageOverlayLeft_->hide();
+            }
+
+            if (showArrows_)
+            {
+                arrowsOverlay1_ = new OrxonoxOverlay(this->getContext());
+                arrowsOverlay1_->setBackgroundMaterial("Orxonox/DirectionArrows1");
+                arrowsOverlay1_->setSize(Vector2(0.02727f, 0.36f * arrowsSize_));
+                arrowsOverlay1_->setPickPoint(Vector2(0.5f, 0.5f));
+                arrowsOverlay1_->setPosition(Vector2(0.5f, 0.5f));
+                arrowsOverlay1_->hide();
+
+                arrowsOverlay2_ = new OrxonoxOverlay(this->getContext());
+                arrowsOverlay2_->setBackgroundMaterial("Orxonox/DirectionArrows2");
+                arrowsOverlay2_->setSize(Vector2(0.02727f, 0.59f * arrowsSize_));
+                arrowsOverlay2_->setPickPoint(Vector2(0.5f, 0.5f));
+                arrowsOverlay2_->setPosition(Vector2(0.5f, 0.5f));
+                arrowsOverlay2_->hide();
+
+                arrowsOverlay3_ = new OrxonoxOverlay(this->getContext());
+                arrowsOverlay3_->setBackgroundMaterial("Orxonox/DirectionArrows3");
+                arrowsOverlay3_->setSize(Vector2(0.02727f, 0.77f * arrowsSize_));
+                arrowsOverlay3_->setPickPoint(Vector2(0.5f, 0.5f));
+                arrowsOverlay3_->setPosition(Vector2(0.5f, 0.5f));
+                arrowsOverlay3_->hide();
+
+                arrowsOverlay4_ = new OrxonoxOverlay(this->getContext());
+                arrowsOverlay4_->setBackgroundMaterial("Orxonox/DirectionArrows4");
+                arrowsOverlay4_->setSize(Vector2(0.02727f, arrowsSize_));
+                arrowsOverlay4_->setPickPoint(Vector2(0.5f, 0.5f));
+                arrowsOverlay4_->setPosition(Vector2(0.5f, 0.5f));
+                arrowsOverlay4_->hide();
+            }
+        }
+
+        // HACK: Define which objects are targetable when considering the creator of an orxonox::Model
+        this->targetMask_.exclude(ClassByString("BaseObject"));
+        this->targetMask_.include(ClassByString("WorldEntity"));
+        this->targetMask_.exclude(ClassByString("Projectile"));
+
+        NewHumanController::localController_s = this;
+
+        controlPaused_ = false;
+
+        //HumanController::localController_s->getControllableEntity()->getCamera()->setDrag(true);
+    }
+
+    NewHumanController::~NewHumanController()
+    {
+        if (this->isInitialized())
+        {
+            if (this->crossHairOverlay_)
+                this->crossHairOverlay_->destroy();
+            if (this->centerOverlay_)
+                this->centerOverlay_->destroy();
+
+            if (this->arrowsOverlay1_)
+                this->arrowsOverlay1_->destroy();
+            if (this->arrowsOverlay2_)
+                this->arrowsOverlay2_->destroy();
+            if (this->arrowsOverlay3_)
+                this->arrowsOverlay3_->destroy();
+            if (this->arrowsOverlay4_)
+                this->arrowsOverlay4_->destroy();
+            if (this->damageOverlayTop_)
+                this->damageOverlayTop_->destroy();
+            if (this->damageOverlayLeft_)
+                this->damageOverlayLeft_->destroy();
+            if (this->damageOverlayRight_)
+                this->damageOverlayRight_->destroy();
+            if (this->damageOverlayBottom_)
+                this->damageOverlayBottom_->destroy();
+        }
+    }
+
+    void NewHumanController::tick(float dt)
+    {
+        if (GameMode::showsGraphics())
+        {
+
+            if (this->controllableEntity_ && !this->controllableEntity_->isInMouseLook())
+            {
+                this->updateTarget();
+
+                if (!controlPaused_ )
+                {
+                    if (this->getControllableEntity() && ((this->getControllableEntity()->isExactlyA(ClassByString("SpaceShip")) || (this->getControllableEntity()->isExactlyA(ClassByString("ModularSpaceShip")))) || this->getControllableEntity()->isExactlyA(ClassByString("Rocket"))))
+                        this->showOverlays();
+                    else if (this->getControllableEntity() &&  this->getControllableEntity()->isExactlyA(ClassByString("FpsPlayer")))
+                    {
+                        this->showOverlays();
+                        this->hideArrows();
+                    }
+
+                    this->crossHairOverlay_->setPosition(Vector2(static_cast<float>(this->currentYaw_)/2*-1+.5f-overlaySize_/2, static_cast<float>(this->currentPitch_)/2*-1+.5f-overlaySize_/2));
+
+                    if (this->controlMode_ == 0 || (this->controlMode_ == 1 && this->firemode_ == 1))
+                    {
+                        if (this->showOverlays_ && this->showArrows_)
+                            alignArrows();
+                    }
+                    else
+                        hideArrows();
+
+                    if (this->showDamageOverlay_ && (this->damageOverlayTT_ > 0 || this->damageOverlayTR_ > 0 || this->damageOverlayTB_ > 0 || this->damageOverlayTL_ > 0))
+                    {
+                        this->damageOverlayTT_ -= dt;
+                        this->damageOverlayTR_ -= dt;
+                        this->damageOverlayTB_ -= dt;
+                        this->damageOverlayTL_ -= dt;
+                        if (this->damageOverlayTT_ <= 0)
+                            this->damageOverlayTop_->hide();
+                        if (this->damageOverlayTR_ <= 0)
+                            this->damageOverlayRight_->hide();
+                        if (this->damageOverlayTB_ <= 0)
+                            this->damageOverlayBottom_->hide();
+                        if (this->damageOverlayTL_ <= 0)
+                            this->damageOverlayLeft_->hide();
+                    }
+                }
+            }
+            else
+                this->hideOverlays();
+
+            if (this->acceleration_ > 0)
+            {
+                if (this->accelerating_)
+                    HumanController::moveFrontBack(Vector2(1, 0));
+                else
+                    HumanController::moveFrontBack(Vector2(this->acceleration_, 0));
+                this->accelerating_ = false;
+                //HumanController::moveFrontBack(Vector2(clamp(this->acceleration_ + this->currentAcceleration_, 0.0f, 1.0f), 0));
+            }
+        }
+
+        // Reset pitch and yaw rates
+        // TODO: Reactivate this to fix the game pad problem with 0 input
+        //this->currentPitch_ = 0;
+        //this->currentYaw_ = 0;
+
+        HumanController::tick(dt);
+    }
+
+    void NewHumanController::doFire(unsigned int firemode)
+    {
+        if (!this->controllableEntity_)
+            return;
+
+        this->firemode_ = firemode;
+
+        if (firemode == 1 && this->controlMode_ == 1)
+        {
+            //unlocked steering, steer on right mouse click
+            HumanController::yaw(Vector2(this->currentYaw_, 0));
+            HumanController::pitch(Vector2(this->currentPitch_, 0));
+        }
+        else
+            HumanController::doFire(firemode); //call for formationflight
+    }
+
+    void NewHumanController::hit(Pawn* originator, btManifoldPoint& contactpoint, float damage)
+    {
+        //Used in HumanController for formationFlight
+        HumanController::hit(originator,contactpoint,damage);
+
+        if (this->showDamageOverlay_ && !this->controlPaused_ && this->controllableEntity_ && !this->controllableEntity_->isInMouseLook())
+        {
+            Vector3 posA;
+            if (originator)
+                posA = originator->getWorldPosition();
+            else
+                posA = multi_cast<Vector3>(contactpoint.getPositionWorldOnA());
+            //Vector3 posB = multi_cast<Vector3>(contactpoint.getPositionWorldOnB());
+            //posA and posB are almost identical
+
+            Vector3 relativeHit = this->getControllableEntity()->getWorldOrientation().UnitInverse() * (this->getControllableEntity()->getWorldPosition() - posA);
+
+            //back is z positive
+            //x is left positive
+            //y is down positive
+            relativeHit.normalise();
+
+            float threshold = 0.3f;
+            if (relativeHit.x > threshold) // Left
+            {
+                this->damageOverlayLeft_->show();
+                this->damageOverlayTL_ = this->damageOverlayTime_;
+                //this->damageOverlayLeft_->setBackgroundAlpha(0.3);
+            }
+            if (relativeHit.x < -threshold) //Right
+            {
+                this->damageOverlayRight_->show();
+                this->damageOverlayTR_ = this->damageOverlayTime_;
+                //this->damageOverlayRight_->setBackgroundAlpha(0.3);
+            }
+            if (relativeHit.y > threshold) //Top
+            {
+                this->damageOverlayBottom_->show();
+                this->damageOverlayTB_ = this->damageOverlayTime_;
+                //this->damageOverlayTop_->setBackgroundAlpha(0.3);
+            }
+            if (relativeHit.y < -threshold) //Bottom
+            {
+                this->damageOverlayTop_->show();
+                this->damageOverlayTT_ = this->damageOverlayTime_;
+                //this->damageOverlayBottom_->setBackgroundAlpha(0.3);
+            }
+        }
+    }
+
+    void NewHumanController::unfire()
+    {
+        if (NewHumanController::localController_s)
+            NewHumanController::localController_s->doUnfire();
+    }
+
+    void NewHumanController::doUnfire()
+    {
+        this->firemode_ = -1;
+        hideArrows();
+    }
+
+    void NewHumanController::centerCursor()
+    {
+        this->currentYaw_ = 0;
+        this->currentPitch_ = 0;
+
+        if( KeyBinderManager::exists() )
+            KeyBinderManager::getInstance().getCurrent()->resetMouseAxes();
+    }
+
+    void NewHumanController::updateTarget()
+    {
+        Ogre::RaySceneQuery * rsq = HumanController::localController_s->getControllableEntity()->getScene()->getSceneManager()->createRayQuery(Ogre::Ray());
+
+        Ogre::Ray mouseRay = HumanController::localController_s->getControllableEntity()->getCamera()->getOgreCamera()->getCameraToViewportRay(static_cast<float>(this->currentYaw_)/2*-1+.5f, static_cast<float>(this->currentPitch_)/2*-1+.5f);
+
+        rsq->setRay(mouseRay);
+        rsq->setSortByDistance(true);
+
+        /*
+        Distance of objects:
+        ignore everything under 200 maybe even take 1000 as min distance to shoot at
+
+        shots are regularly traced and are entities!!!!!!!!! this is the biggest problem
+        they vanish only after a distance of 10'000
+        */
+
+
+        Ogre::RaySceneQueryResult& result = rsq->execute();
+        Pawn* pawn = orxonox_cast<Pawn*>(this->getControllableEntity());
+        WorldEntity* myWe = static_cast<WorldEntity*>(this->getControllableEntity());
+
+        Ogre::RaySceneQueryResult::iterator itr;
+        for (itr = result.begin(); itr != result.end(); ++itr)
+        {
+//             orxout() << "testing object as target" << endl;
+            if (itr->movable->isInScene() && itr->movable->getMovableType() == "Entity" && itr->distance > 200)
+            {
+                // Try to cast the user pointer
+                WorldEntity* wePtr;
+                try
+                {
+                    wePtr = orxonox_cast<WorldEntity*>(Ogre::any_cast<OrxonoxClass*>(itr->movable->getUserAny()));
+                }
+                catch (...)
+                {
+                    continue;
+                }
+
+                // make sure we don't shoot ourselves
+                if( wePtr==myWe )
+                    continue;
+
+                if (wePtr)
+                {
+                    // go through all parents of object and look whether they are sightable or not
+                    bool isSightable = false;
+                    WorldEntity* parent = wePtr->getParent();
+                    while (parent)
+                    {
+                        if (this->targetMask_.isExcluded(parent->getIdentifier()) || parent==myWe)
+                        {
+                            parent = parent->getParent();
+                            continue;
+                        }
+                        else
+                        {
+                            isSightable = true;
+                            break;
+                        }
+                    }
+                    if (!isSightable)
+                        continue;
+                }
+
+                if (this->getControllableEntity() && this->getControllableEntity()->getTarget() != wePtr)
+                    this->getControllableEntity()->setTarget(wePtr);
+
+                if (pawn)
+                    pawn->setAimPosition( mouseRay.getOrigin() + mouseRay.getDirection() * itr->distance );
+
+                //itr->movable->getParentSceneNode()->showBoundingBox(true);
+                //return mouseRay.getOrigin() + mouseRay.getDirection() * itr->distance; //or itr->movable->getParentSceneNode()->_getDerivedPosition()
+                return;
+            }
+        }
+
+        if (pawn)
+            pawn->setAimPosition( mouseRay.getOrigin() + mouseRay.getDirection() * 3000 );
+
+        if( this->getControllableEntity() && this->getControllableEntity()->getTarget() != nullptr )
+            this->getControllableEntity()->setTarget( nullptr );
+
+        //return this->controllableEntity_->getWorldPosition() + (this->controllableEntity_->getWorldOrientation() * Vector3::NEGATIVE_UNIT_Z * 2000);
+        //return this->controllableEntity_->getWorldPosition() + (this->controllableEntity_->getCamera()->getOgreCamera()->getOrientation() * Vector3::NEGATIVE_UNIT_Z);
+    }
+
+    void NewHumanController::frontback(const Vector2& value)
+    {
+        this->accelerating_ = true;
+
+        //if (this->acceleration_ == 0)
+        HumanController::frontback(value);
+    }
+
+    void NewHumanController::yaw(const Vector2& value)
+    {
+        //SUPER(NewHumanController, yaw, value);
+        if (this->controlMode_ == 0 || (this->controllableEntity_ && this->controllableEntity_->isInMouseLook()))
+            HumanController::yaw(value);
+
+        if (this->getControllableEntity() && !this->getControllableEntity()->isExactlyA(ClassByString("FpsPlayer")))
+            this->currentYaw_ = value.x;
+    }
+
+    void NewHumanController::pitch(const Vector2& value)
+    {
+        //SUPER(NewHumanController, pitch, value);
+        if (this->controlMode_ == 0 || (this->controllableEntity_ && this->controllableEntity_->isInMouseLook()))
+            HumanController::pitch(value);
+
+        if (this->getControllableEntity() && !this->getControllableEntity()->isExactlyA(ClassByString("FpsPlayer")))
+            this->currentPitch_ = value.x;
+    }
+
+    void NewHumanController::changeMode()
+    {
+        if (NewHumanController::localController_s)
+        {
+            if (NewHumanController::localController_s->controlMode_ == 0)
+            {
+                NewHumanController::localController_s->controlMode_ = 1;
+                NewHumanController::localController_s->hideArrows();
+            }
+            else
+                NewHumanController::localController_s->controlMode_ = 0;
+        }
+    }
+
+    void NewHumanController::changedControllableEntity()
+    {
+        HumanController::changedControllableEntity(); // super
+
+        this->controlMode_ = 0;
+        this->centerCursor();
+        if (this->getControllableEntity() && ((this->getControllableEntity()->isExactlyA(ClassByString("SpaceShip")) || (this->getControllableEntity()->isExactlyA(ClassByString("ModularSpaceShip")))) || this->getControllableEntity()->isExactlyA(ClassByString("Rocket"))))
+        {
+            this->showOverlays_ = true;
+            if (!this->controlPaused_)
+            {
+                this->showOverlays();
+                this->alignArrows();
+            }
+        }
+        else
+        {
+            this->showOverlays_ = false;
+            this->hideOverlays();
+        }
+    }
+
+    void NewHumanController::accelerate()
+    {
+        if (NewHumanController::localController_s)
+            NewHumanController::localController_s->acceleration_ = clamp(NewHumanController::localController_s->acceleration_ + 0.2f, 0.00f, 1.0f);
+    }
+
+    void NewHumanController::decelerate()
+    {
+        if (NewHumanController::localController_s)
+            NewHumanController::localController_s->acceleration_ = clamp(NewHumanController::localController_s->acceleration_ - 0.1f, 0.0f, 1.0f);
+    }
+
+    void NewHumanController::doResumeControl()
+    {
+        this->controlPaused_ = false;
+        if (this->showOverlays_)
+            this->showOverlays();
+    }
+
+    void NewHumanController::doPauseControl()
+    {
+        this->controlPaused_ = true;
+        this->hideOverlays();
+    }
+
+    void NewHumanController::alignArrows()
+    {
+        if (showArrows_)
+        {
+            hideArrows();
+
+            float distance = sqrt(pow(static_cast<float>(this->currentYaw_)/2*-1,2) + pow(static_cast<float>(this->currentPitch_)/2*-1,2));
+
+            if (distance > 0.04f && distance <= 0.59f * arrowsSize_ / 2.0f )
+            {
+                this->arrowsOverlay1_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / math::twoPi * 360.0f));
+                this->arrowsOverlay1_->show();
+            }
+            else if (distance > 0.59f * arrowsSize_ / 2.0f && distance <= 0.77f * arrowsSize_ / 2.0f )
+            {
+                this->arrowsOverlay2_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / math::twoPi * 360.0f));
+                this->arrowsOverlay2_->show();
+            }
+            else if (distance > 0.77f * arrowsSize_ / 2.0f && distance <= arrowsSize_ / 2.0f)
+            {
+                this->arrowsOverlay3_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / math::twoPi * 360.0f));
+                this->arrowsOverlay3_->show();
+            }
+            else if (distance > arrowsSize_ / 2.0f)
+            {
+                this->arrowsOverlay4_->setRotation(Degree(-90 + -1.0f * atan2(static_cast<float>(this->currentPitch_)/2*-1, static_cast<float>(this->currentYaw_)/2*-1) / math::twoPi * 360.0f));
+                this->arrowsOverlay4_->show();
+            }
+        }
+    }
+
+    void NewHumanController::showOverlays()
+    {
+        if (!GameMode::showsGraphics())
+            return;
+        this->crossHairOverlay_->show();
+        this->centerOverlay_->show();
+
+        if (showArrows_)
+        {
+            this->arrowsOverlay1_->show();
+            this->arrowsOverlay2_->show();
+            this->arrowsOverlay3_->show();
+            this->arrowsOverlay4_->show();
+        }
+    }
+
+    void NewHumanController::hideOverlays()
+    {
+        if (!GameMode::showsGraphics())
+            return;
+        this->crossHairOverlay_->hide();
+        this->centerOverlay_->hide();
+
+        if (showDamageOverlay_)
+        {
+            this->damageOverlayTop_->hide();
+            this->damageOverlayRight_->hide();
+            this->damageOverlayBottom_->hide();
+            this->damageOverlayLeft_->hide();
+        }
+
+        this->hideArrows();
+    }
+
+    void NewHumanController::hideArrows()
+    {
+        if(!GameMode::showsGraphics())
+            return;
+        if (showArrows_)
+        {
+            this->arrowsOverlay1_->hide();
+            this->arrowsOverlay2_->hide();
+            this->arrowsOverlay3_->hide();
+            this->arrowsOverlay4_->hide();
+        }
+    }
+
+
+
+
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/NewHumanController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/NewHumanController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/NewHumanController.h	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Michael Wirth
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _NewNewHumanController_H__
+#define _NewNewHumanController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+
+#include "core/ClassTreeMask.h"
+#include "HumanController.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport NewHumanController : public HumanController
+    {
+        public:
+            NewHumanController(Context* context);
+            virtual ~NewHumanController();
+
+            virtual void tick(float dt) override;
+
+            virtual void frontback(const Vector2& value) override;
+            virtual void yaw(const Vector2& value) override;
+            virtual void pitch(const Vector2& value) override;
+
+            static void accelerate();
+            static void decelerate();
+
+            virtual void doFire(unsigned int firemode) override;
+
+            virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, float damage) override;
+
+            static void unfire();
+            virtual void doUnfire();
+
+            void centerCursor();
+
+            static void changeMode();
+
+            virtual void changedControllableEntity() override;
+            virtual void doPauseControl() override;
+            virtual void doResumeControl() override;
+
+            float getCurrentYaw(){ return this->currentYaw_; }
+            float getCurrentPitch(){ return this->currentPitch_; }
+
+
+        protected:
+            void updateTarget();
+            void alignArrows();
+            void showOverlays();
+            void hideOverlays();
+            void hideArrows();
+
+            unsigned int                controlMode_;
+            static NewHumanController*  localController_s;
+
+        private:
+            float                       currentYaw_;
+            float                       currentPitch_;
+            OrxonoxOverlay*             crossHairOverlay_;
+            OrxonoxOverlay*             centerOverlay_;
+
+            OrxonoxOverlay*             damageOverlayTop_;
+            OrxonoxOverlay*             damageOverlayRight_;
+            OrxonoxOverlay*             damageOverlayBottom_;
+            OrxonoxOverlay*             damageOverlayLeft_;
+            float                       damageOverlayTime_;
+            float                       damageOverlayTT_;
+            float                       damageOverlayTR_;
+            float                       damageOverlayTB_;
+            float                       damageOverlayTL_;
+
+            OrxonoxOverlay*             arrowsOverlay1_;
+            OrxonoxOverlay*             arrowsOverlay2_;
+            OrxonoxOverlay*             arrowsOverlay3_;
+            OrxonoxOverlay*             arrowsOverlay4_;
+
+            float                       overlaySize_;
+            float                       arrowsSize_;
+            bool                        accelerating_;
+            float                       acceleration_;
+            int                         firemode_;
+            bool                        showArrows_;
+            bool                        showDamageOverlay_;
+            bool                        showOverlays_;
+            ClassTreeMask               targetMask_;
+    };
+}
+
+#endif /* _NewHumanController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ScriptController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ScriptController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ScriptController.cc	(revision 11817)
@@ -0,0 +1,343 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+ /*
+  * Currently available lua commands:
+  *
+  * IMPORTANT: ALL COMMANDS DO REQUIRE 7 PARAMETERS TO BE PROVIDED. FILL UP WITH ZEROES IN UNIMPORTANT PLACES.
+  *
+  * Command             | Abbreviation | Parameter 1          | '' 2     | '' 3    | '' 4                 | '' 5     | '' 6     | '' 7
+  *
+  * "Move And Look"     | mal          | GoTo X Coordinate    | '' Y ''  | '' Z '' | LookAt X Coordinate  |  '' Y '' |  '' Y '' | Duration
+  * "Rotate And Look"   | ral          | GoTo X Coordinate    | '' Y ''  | '' Z '' | Axis (1=x, 2=z, 3=z) |     -    |     -    | Duration
+  * "Spiral"            | spi          | GoTo X Coordinate    | '' Y ''  | '' Z '' |          -           |     -    |     -    | Duration
+  * "Transition Look"   | chl          | From X Coordinate    | '' Y ''  | '' Z '' | To X Coordinate      |  '' Y '' |  '' Y '' | Duration
+  * "Idle (Do nothing)" | idle         | Duration
+  */
+
+#include "ScriptController.h"
+#include "infos/PlayerInfo.h"
+#include "core/CoreIncludes.h"
+#include "worldentities/ControllableEntity.h"
+#include "core/LuaState.h"
+#include "core/LuaState.h"
+#include "util/Math.h"
+
+namespace orxonox
+{
+    RegisterClass(ScriptController);
+
+    ScriptController::ScriptController(Context* context) : ArtificialController(context)
+    {
+        RegisterObject(ScriptController);
+
+        /* By default, this controller has ID 0, which means it is not assigned
+         * to anything yet. 
+         */
+        this->ctrlid_ = 0;
+
+        /* Set default values for all variables */
+        /* - pointers to zero */
+        this->player_ = nullptr;
+        this->entity_ = nullptr;
+
+        /* - times */
+        this->scTime = 0.0f;
+        this->eventTime = 0.0f;
+
+        /* - Points in space */
+        this->startpos = Vector3(0,0,0);
+        //this->lookAtPosition = Vector3(0,0,0);
+
+        /* - Processing flag */
+        this->processing = false;
+
+        /* - Counters */
+        this->eventno = 0;
+
+        /* - First "previous event" scheduled at t=0 */
+        /* - Needed for automatically updating event times */
+        this->prevEventTime = 0;
+    }
+
+    void ScriptController::takeControl(int ctrlid)
+    {
+        /* Output some debugging information */
+        orxout(verbose) << "ScriptController: Taking control" << endl;
+        orxout(verbose) << "This-pointer: " << this << endl;
+
+        /* Set the controller ID (the argument here should be nonzero) */
+        this->ctrlid_ = ctrlid;
+
+        /* Store the entity pointer in a private variable */
+        this->entity_ = this->player_->getControllableEntity();
+        assert(this->entity_);
+         
+        /* Add the controller here to this entity. Apparently this still leaves
+         * any preexisting human controllers in place. 
+         */
+        this->entity_->setDestroyWhenPlayerLeft(false);
+        this->player_->pauseControl();
+        this->entity_->setController(this);
+        this->setControllableEntity(this->entity_);
+        this->entity_->mouseLook();
+        this->entity_->setVisible(false);
+    }
+
+    const Vector3& ScriptController::getPosition()
+    {
+      return this->entity_->getPosition();
+    }
+
+    ScriptController* ScriptController::getScriptController()
+    {
+      /* Output a message that confirms this function was called */
+      orxout(verbose) << "Great success!" << std::endl;
+
+      /* Debugging: print all the scriptcontroller object pointers */
+      for(ScriptController* controller : ObjectList<ScriptController>())
+      { orxout(verbose) << "Have object in list: " << controller << endl; }
+
+      /* Find the first one with a nonzero ID */
+      for(ScriptController* controller : ObjectList<ScriptController>())
+      { 
+        // TODO: do some selection here. Currently just returns the first one
+        if( controller->getID() > 0 )
+        { orxout(verbose) << "Controller to return: " << controller << endl;
+          return controller;
+        }
+      
+      }
+      return nullptr;
+    }
+
+    void ScriptController::execute(event ev)
+    {
+        /* Debugging output */
+        //orxout() << "Executing event " << ev.fctName 
+          //<< " with parameters:\n " 
+          //<< ev.x1 << " " << ev.y1 << " " << ev.z1 << "\n"
+          //<< ev.x2 << " " << ev.y2 << " " << ev.z2 << "\n"
+          //<< ev.duration << endl;
+
+        /* Event is starting, hence set the time to 0 */
+        this->eventTime = 0.0f;
+        this->processing = true;
+
+        /* Copy the event into the currentEvent holder */
+        this->currentEvent = ev;
+
+        /* Store starting position */
+        this->startpos = this->entity_->getPosition();
+    }
+
+
+    void ScriptController::tick(float dt)
+    {
+        /* Call the tick function of the classes we derive from */
+        SUPER(ScriptController, tick, dt);
+
+        /* If this controller has no entity entry, do nothing */
+        if( !(this->entity_) ) return;
+
+        /* See if time has come for the next event to be run */
+        if(this->eventList.size() > 0 && this->eventList[0].eventTime <= scTime)
+        { /* Execute the next event on the list */
+          this->execute(this->eventList[0]);
+          this->eventList.erase(this->eventList.begin());
+          this->eventno -= 1;
+        }
+
+        /* Update the local timers in this object */
+        scTime += dt; eventTime += dt;
+
+        /* If we've arrived at the target, stop processing */
+        if( eventTime > currentEvent.duration && this->processing == true)
+        { this->processing = false;
+
+          /* If we reached the last event, also reenable the normal movement
+           * and make the model visible again
+           */
+          if( this->eventno == 0 )
+          {
+            this->entity_->mouseLook();
+            this->entity_->setVisible(true);
+          }
+        }
+
+        /* Get a variable that specifies how far along the trajectory
+         * we are currently.
+         */
+        float dl = eventTime / currentEvent.duration; 
+
+        /* Depending on command */
+        /* Do some moving */
+        if( this->processing )
+        {
+          // Abbreviation for "spiral" (rotation + translation)
+          if (this->currentEvent.fctName == "spi") {
+
+            // Need to know a perpendicular basis to the translation vector:
+            // Given (a, b, c) we chose (b, -a, 0)norm and (0, c, -b)norm
+            // Currently we set a fix rotational radius of 400
+            // TODO: Add an option to adjust radius of spiral movement
+            Vector3 direction = this->currentEvent.v1 - startpos;
+
+            Vector3* ortho1 = new Vector3(direction.y, -direction.x, 0);
+            float absOrtho1 = sqrt(direction.y * direction.y + direction.x * direction.x);
+            *ortho1 = 400 * cos(2 * math::pi * dl) * (*ortho1)/absOrtho1;
+
+            Vector3* ortho2 = new Vector3(0, direction.z, -direction.y);
+            float absOrtho2 = sqrt(direction.y * direction.y + direction.z * direction.z);
+            *ortho2 = 400 * sin(2 * math::pi * dl) * (*ortho2)/absOrtho2;
+
+            this->entity_->setPosition( (1-dl)*startpos + dl * this->currentEvent.v1 + *ortho1 + *ortho2);
+
+            delete ortho1;
+            delete ortho2;
+          }
+
+          // Abbreviation for "rotate and look"
+          if (this->currentEvent.fctName == "ral")
+          { 
+            // Specify the axis
+            Vector3 a;
+              switch ((int) currentEvent.d) {
+                case 3:
+                  a = Vector3(this->currentEvent.v1.x + this->currentEvent.e*cos(2*math::pi*dl),
+                                  this->currentEvent.v1.y + this->currentEvent.e*sin(2*math::pi*dl),
+                                  this->currentEvent.v1.z);
+                break;
+                case 2:
+                  a = Vector3(this->currentEvent.v1.x + this->currentEvent.e*sin(2*math::pi*dl),
+                                  this->currentEvent.v1.y,
+                                  this->currentEvent.v1.z + this->currentEvent.e*cos(2*math::pi*dl));
+                break;
+                case 1:
+                  a = Vector3(this->currentEvent.v1.x,
+                                  this->currentEvent.v1.y + this->currentEvent.e*sin(2*math::pi*dl),
+                                  this->currentEvent.v1.z + this->currentEvent.e*cos(2*math::pi*dl));
+                break;
+              }
+
+            this->entity_->setPosition(a);
+
+            /* Look at the specified position */
+            this->entity_->lookAt(this->currentEvent.v1);
+          }
+          else if( this->currentEvent.fctName == "mal" )
+          {
+            /* Set the position to the correct place in the trajectory */
+            this->entity_->setPosition( (1-dl)*startpos + dl * this->currentEvent.v1);
+
+            /* Look at the specified position */
+            this->entity_->lookAt(this->currentEvent.v2);
+          }
+          else if( this->currentEvent.fctName == "chl" )
+          {
+            /* Sweep the look from v1 to v2 */
+            this->entity_->lookAt( (1-dl)*this->currentEvent.v1 + 
+              dl * this->currentEvent.v2 );
+          }
+
+
+          /* Force mouse look */
+          if( this->entity_->isInMouseLook() == false )
+            this->entity_->mouseLook();
+        }
+    }
+
+    void ScriptController::eventScheduler(std::string instruction, 
+      float x1, float y1, float z1, 
+      float x2, float y2, float z2, 
+      float duration, float executionTime)
+    {
+      /* put data (from LUA) into time-sorted eventList*/ 
+      /* Nimmt den befehl und die argumente aus luascript und ertellt einen
+       * struct pro event, diese structs werden sortiert nach eventTime
+       */
+      struct event tmp;
+
+      /* Fill the structure with all the provided information */
+      tmp.fctName = instruction;
+
+      //tmp.x1 = x1; tmp.y1 = y1; tmp.z1 = z1;
+      //tmp.x2 = x2; tmp.y2 = y2; tmp.z2 = z2;
+      tmp.v1 = Vector3(x1,y1,z1);
+      tmp.v2 = Vector3(x2,y2,z2);
+
+      // the parameters are not required to be vector coordinates!
+      // for convenience they are however stored twice if they have some kind of different meaning
+      tmp.a = x1;
+      tmp.b = y1;
+      tmp.c = z1;
+      tmp.d = x2;
+      tmp.e = y2;
+      tmp.f = z2;
+
+      tmp.duration = duration;
+
+      /* This is kind of a hack. If we hit the function idle all we want to do is
+         advance event execution time, not schedule anything */
+      if (instruction == "idle") {
+        tmp.eventTime = this->prevEventTime;
+        this->prevEventTime += x1;
+        return;
+      } else {
+        tmp.eventTime = this->prevEventTime;
+        this->prevEventTime += duration;
+      }
+
+      /* Add the created event to the event list */
+      if(eventList.size()==0)
+      { /* The list is still empty, just add it */
+        orxout(verbose) << "eventList empty (01)" << endl;
+        eventList.insert(eventList.begin(), tmp);
+        this->eventno += 1;
+        return; /* Nothing more to do, the event was added */
+      }
+
+      /* Event was not added yet since the list was not empty. Walk through
+       * the list of events and add it so that the events are correctly in
+       * order.
+       */
+      for (std::vector<event>::iterator it=eventList.begin(); it<eventList.end(); it++)
+      { if(tmp.eventTime < it->eventTime)
+        { eventList.insert(it,tmp);
+          this->eventno += 1;
+          //orxout()<<"new event added"<<endl;
+          return;
+        }
+      }
+
+      /* If the event was still not added here, it belongs in the end of the list */
+      eventList.insert(eventList.end(), tmp);
+      this->eventno += 1;
+
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/ScriptController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/ScriptController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/ScriptController.h	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      ...
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ScriptController_H__
+#define _ScriptController_H__
+
+#include "OrxonoxPrereqs.h"                 /* die ganzen tolua, kopiert aus Dock.h*/
+#include "ArtificialController.h"
+#include "core/EventIncludes.h"
+
+
+
+namespace orxonox  // tolua_export
+{  // tolua_export
+
+    /** Structure to describe a single event */
+    struct event 
+    {   
+        /** Instruction for this event */
+        std::string fctName;
+
+        /** Final position we want to be at **/
+        Vector3 v1;
+
+        /** Where we are looking **/
+        Vector3 v2;
+
+        /** The parameters are additionally stored as a set of 6 numerical values **/
+        float a, b, c, d, e, f;
+
+        /** Time span of the event */
+        float duration;
+
+        /** Start point in time of the event */
+        float eventTime;
+    }; 
+
+    class _OrxonoxExport ScriptController // tolua_export 
+       : public ArtificialController, public Tickable
+    {  // tolua_export
+        public:
+            ScriptController(Context* context);
+            virtual ~ScriptController() { }
+
+            void takeControl(int ctrlid);
+            void setPlayer(PlayerInfo* player) { this->player_ = player; }
+           
+            virtual void tick(float dt) override;
+
+            // LUA interface
+            // tolua_begin 
+            void eventScheduler(std::string instruction = "", 
+              float x1 = 0, float y1 = 0, float z1 = 0, 
+              float x2 = 0, float y2 = 0, float z2 = 0, 
+              float duration = 0, float executionTime = 0);
+
+            static ScriptController* getScriptController();
+
+            int getID() { return ctrlid_; }
+
+            // tolua_end
+            const Vector3& getPosition();
+
+            void execute(event ev);
+
+        private:
+            /* Information about the player that this ScriptController will
+             * control */
+            /* - Player pointer */
+            PlayerInfo* player_;
+
+            /* - Entity pointer, this is for convenience and will be the same as 
+             *   player_->getControllableEntity() 
+             */
+            ControllableEntity* entity_;
+
+            /* Controller ID, defaults to 0 and is set using takeControl() */
+            int ctrlid_;
+
+            /* List of events to walk through */
+            std::vector<event> eventList;
+            unsigned int eventno;
+
+            /* Time since the creation of this ScriptController object */
+            float scTime;  
+
+            /* Boolean that specifies whether we're processing an event right
+             * now */
+            bool processing;
+
+            /* Data about the event currently being processed */
+            /* - The event itself */
+            event currentEvent;
+
+            /* - Time this event has been going on for */
+            float eventTime;
+            Vector3 startpos;
+
+            /* Time of the previously scheduled event */
+            float prevEventTime;
+
+            /* - Position to look at during that transition */
+            //Vector3 lookAtPosition;
+
+    };// tolua_export
+} // tolua_export
+
+#endif /* _ScriptController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/SectionController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/SectionController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/SectionController.cc	(revision 11817)
@@ -0,0 +1,256 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SectionController.h"
+
+namespace orxonox
+{
+
+    RegisterClass(SectionController);
+
+    //Leaders share the fact that they have Wingmans
+    SectionController::SectionController(Context* context) : ActionpointController(context)
+    {
+        RegisterObject(SectionController);
+        this->setFormationMode(FormationMode::FINGER4);
+
+        this->myWingman_ = nullptr;
+        this->myDivisionLeader_ = nullptr;
+        this->bFirstAction_ = true;
+
+    }
+   
+    SectionController::~SectionController()
+    {
+        for (WorldEntity* actionpoint : this->actionpoints_)
+        {
+            if (actionpoint)
+                actionpoint->destroy();
+        }
+        this->parsedActionpoints_.clear();
+        this->actionpoints_.clear();
+    }
+
+    void SectionController::action()
+    {
+        if (!this->getControllableEntity() || !this->isActive())
+            return;
+
+        //----If no leader, find one----  
+        if (!myDivisionLeader_)
+        {
+            ActionpointController* newDivisionLeader = findNewDivisionLeader();
+
+            this->myDivisionLeader_ = newDivisionLeader;
+        }
+        //----If have leader----
+        else
+        {
+        }
+        if (!myDivisionLeader_)
+        {
+            ActionpointController::action();
+            if (!(this->parsedActionpoints_.empty() && this->loopActionpoints_.empty()))
+            {
+                if (this->myWingman_)
+                {
+                    this->myWingman_->takeActionpoints(this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
+                }    
+            }
+        }
+        else if (myDivisionLeader_)
+        {
+            if (this->myDivisionLeader_->bKeepFormation_ || !(this->myDivisionLeader_->getAction() == Action::FIGHT 
+                || this->myDivisionLeader_->getAction() == Action::FIGHTALL
+                || this->myDivisionLeader_->getAction() == Action::ATTACK))
+            {
+                this->keepFormation();
+            }
+            else if (!this->myDivisionLeader_->bKeepFormation_)
+            {
+
+                if (!this->hasTarget())
+                {
+                    this->chooseTarget(); 
+                }
+
+            }
+        }
+
+    }
+
+    
+    //PRE: myDivisionLeader_ != 0 && myDivisionLeader_->action_ == Action::FIGHT
+    //POST: this->target_ is set unless division leader doesn't have one
+    void SectionController::chooseTarget()
+    {
+        //----If division leader fights, cover him by fighting emenies close to his target----
+        Action action = this->myDivisionLeader_->getAction();
+
+        if (action == Action::FIGHT || action == Action::FIGHTALL || action == Action::ATTACK)
+        {
+            Pawn* target = nullptr;
+            //----if he has a target----
+            if (this->myDivisionLeader_->hasTarget())
+            {
+                //----try to find a new target if division leader has wingman (doing fine) and no good target already set----
+                if ( this->myDivisionLeader_->hasWingman() && 
+                    !( this->hasTarget() && this->getTarget() != this->myDivisionLeader_->getTarget() ) )
+                {
+                    bool foundTarget = false;
+                    //----new target should be close to division's target----
+                    Vector3 divisionTargetPosition = this->myDivisionLeader_->getTarget()->getWorldPosition();
+                    Gametype* gt = this->getGametype();
+                    for (Pawn* pawn : ObjectList<Pawn>())
+                    {
+                        //----is enemy?----
+                        if ( CommonController::sameTeam (this->getControllableEntity(), static_cast<ControllableEntity*>(pawn), gt) )
+                            continue;           
+                        //----in range?----
+                        if ((pawn->getWorldPosition() - divisionTargetPosition).length() < 3000 &&
+                            pawn != this->myDivisionLeader_->getTarget())
+                        {
+                            foundTarget = true;
+                            target = pawn;
+                            break; 
+                        }
+                    }
+                    //----no target? then attack same target as division leader----
+                    if (!foundTarget)
+                    {
+                        target = orxonox_cast<Pawn*>(this->myDivisionLeader_->getTarget());
+                    }
+                }
+                //----if division leader doesn't have a wingman, support his fire----
+                else
+                {
+                    target = orxonox_cast<Pawn*>(this->myDivisionLeader_->getTarget());
+                }
+            }
+            //----If he fights but doesn't have a target, wait for him to get one----
+            else
+            {
+
+            }
+            this->setTarget (orxonox_cast<ControllableEntity*>(target));
+        }
+        else
+        {
+        } 
+    }
+    Vector3 SectionController::getFormationPosition ()
+    {
+        this->setFormationMode( this->myDivisionLeader_->getFormationMode() );
+        this->spread_ = this->myDivisionLeader_->getSpread();
+        switch (this->formationMode_){
+            case FormationMode::WALL:
+                return Vector3 (-2.0f*this->spread_, 0, 0);
+
+            case FormationMode::FINGER4: 
+                return Vector3 (-2.0f*this->spread_, 0, 1.0f*this->spread_);
+            
+            case FormationMode::DIAMOND: 
+                return Vector3 (-2.0f*this->spread_, 0, 1.0f*this->spread_);
+
+            default:
+                return Vector3::ZERO;
+        }
+    }
+
+    void SectionController::keepFormation()
+    {
+        this->bKeepFormation_ = true;
+        ControllableEntity* leaderEntity = this->myDivisionLeader_->getControllableEntity();
+        Vector3 targetRelativePosition = this->getFormationPosition();
+        if (!leaderEntity)
+            return;
+        FlyingController::keepFormation(leaderEntity, targetRelativePosition);
+    }
+
+    ActionpointController* SectionController::findNewDivisionLeader()
+    {
+
+        if (!this->getControllableEntity())
+            return nullptr;
+
+        ActionpointController* closestLeader = nullptr;
+        float minDistance =  std::numeric_limits<float>::infinity();
+        //go through all pawns
+        for (ActionpointController* controller : ObjectList<ActionpointController>())
+        {
+            //0ptr or not DivisionController?
+            if (!controller || !(controller->getIdentifier()->getName() == "DivisionController") || !(controller->getControllableEntity()))
+                continue;
+            //same team?
+            if ((this->getControllableEntity()->getTeam() != controller->getControllableEntity()->getTeam()))
+                continue;
+
+            //is equal to this?
+            if (orxonox_cast<ControllableEntity*>(controller) == this->getControllableEntity())
+                continue;
+
+            float distance = CommonController::distance (controller->getControllableEntity(), this->getControllableEntity());
+            
+            if (distance < minDistance && !(controller->hasFollower()))
+            {
+                closestLeader = controller;
+                minDistance = distance;
+            }
+          
+        }
+        if (closestLeader)
+        {
+            if (closestLeader->setFollower(this))
+                return closestLeader;
+        }
+        return nullptr;
+    }
+
+    bool SectionController::setWingman(ActionpointController* newWingman)
+    {
+
+        if (!this->myWingman_)
+        {
+            this->myWingman_ = newWingman;
+            newWingman->takeActionpoints (this->parsedActionpoints_, this->loopActionpoints_, this->bLoop_);
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+    
+    bool SectionController::hasWingman()
+    {
+        if (this->myWingman_)
+            return true;
+        else
+            return false;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/SectionController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/SectionController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/SectionController.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SectionController_H__
+#define _SectionController_H__
+
+#include "controllers/ActionpointController.h"
+
+
+namespace orxonox
+{
+    /**
+        @note
+        ActionpointController will not work, if there is no MasterController in the level!
+        All the demos are in a file called AITest.oxw. In the menu look for New AI Testing Level.
+    */
+    class _OrxonoxExport SectionController : public ActionpointController
+    {
+        public:
+            //----[language demanded functions]----            
+                SectionController(Context* context);
+
+                virtual ~SectionController();
+            //----[/language demanded functions]----
+            
+            //----[own functions]----
+                ActionpointController* findNewDivisionLeader();
+
+                virtual bool setWingman(ActionpointController* newWingman) override;
+                virtual bool hasWingman() override;
+                virtual bool hasFollower() override
+                    { return false; }
+                void chooseTarget();
+            //----[/own functions]----
+
+        protected:       
+            //----action must only be managed by this----     
+                virtual void action() override; //<! action() is called in regular intervals by MasterController managing the bot's behaviour.
+                Vector3 getFormationPosition ();
+                void keepFormation();
+        private:
+            //----private variables-----
+                bool bFirstAction_;
+                
+    };
+}
+
+#endif /* _SectionController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointController.cc	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WaypointController.h"
+
+#include "core/CoreIncludes.h"
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(WaypointController);
+
+    WaypointController::WaypointController(Context* context) : ArtificialController(context)
+    {
+        RegisterObject(WaypointController);
+        this->setAccuracy(100);
+    }
+
+    WaypointController::~WaypointController()
+    {
+        for (WorldEntity* waypoint : this->waypoints_)
+        {
+            if(waypoint)
+                waypoint->destroy();
+        }
+    }
+
+    void WaypointController::tick(float dt)
+    {
+        if (!this->isActive())
+            return;
+
+        if (this->waypoints_.size() == 0 || !this->getControllableEntity())
+            return;
+
+        if (this->waypoints_[this->currentWaypoint_]->getWorldPosition().squaredDistance(this->getControllableEntity()->getPosition()) <= this->squaredaccuracy_)
+            this->currentWaypoint_ = (this->currentWaypoint_ + 1) % this->waypoints_.size();
+
+        this->moveToPosition(this->waypoints_[this->currentWaypoint_]->getWorldPosition());
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointController.h	(revision 11817)
@@ -0,0 +1,53 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WaypointController_H__
+#define _WaypointController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <vector>
+#include "tools/interfaces/Tickable.h"
+#include "ArtificialController.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport WaypointController : public ArtificialController, public Tickable
+    {
+        public:
+            WaypointController(Context* context);
+            virtual ~WaypointController();
+
+            virtual void tick(float dt) override;
+
+        protected:
+
+    };
+}
+
+#endif /* _WaypointController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointPatrolController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointPatrolController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointPatrolController.cc	(revision 11817)
@@ -0,0 +1,105 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WaypointPatrolController.h"
+
+#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(WaypointPatrolController);
+
+    WaypointPatrolController::WaypointPatrolController(Context* context) : WaypointController(context)
+    {
+        RegisterObject(WaypointPatrolController);
+
+        this->alertnessradius_ = 500.0f;
+        this->attackradius_ = 1000.0f;
+
+        this->patrolTimer_.setTimer(rnd(), true, createExecutor(createFunctor(&WaypointPatrolController::searchEnemy, this)));
+    }
+
+    void WaypointPatrolController::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WaypointPatrolController, XMLPort, xmlelement, mode);
+
+        XMLPortParam(WaypointPatrolController, "alertnessradius", setAlertnessRadius, getAlertnessRadius, xmlelement, mode).defaultValues(500.0f);
+        XMLPortParam(WaypointPatrolController, "attackradius", setAttackRadius, getAttackRadius, xmlelement, mode).defaultValues(1000.0f);
+    }
+
+    void WaypointPatrolController::tick(float dt)
+    {
+        if (!this->isActive())
+            return;
+
+        if (this->target_) //if there is a target, follow it and shoot it, if it is close enough
+        {
+            this->aimAtTarget();
+
+            if (this->bHasTargetPosition_)
+                this->moveToTargetPosition();
+
+            if (this->getControllableEntity() && this->isCloseAtTarget(this->attackradius_) && this->isLookingAtTarget(math::pi / 20.0f))
+                this->getControllableEntity()->fire(0);
+        }
+        else
+        {
+            SUPER(WaypointPatrolController, tick, dt);
+        }
+    }
+
+    void WaypointPatrolController::searchEnemy()
+    {
+        this->patrolTimer_.setInterval(rnd());
+
+        if (!this->getControllableEntity())
+            return;
+
+        Vector3 myposition = this->getControllableEntity()->getPosition();
+        float shortestsqdistance = (float)static_cast<unsigned int>(-1);
+
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if (ArtificialController::sameTeam(this->getControllableEntity(), static_cast<ControllableEntity*>(pawn), this->getGametype()))
+                continue;
+
+            float sqdistance = pawn->getPosition().squaredDistance(myposition);
+            if (sqdistance < shortestsqdistance)
+            {
+                shortestsqdistance = sqdistance;
+                this->target_ = pawn;
+            }
+        }
+
+        if (shortestsqdistance > (this->alertnessradius_ * this->alertnessradius_))
+            this->target_ = nullptr;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointPatrolController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointPatrolController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/WaypointPatrolController.h	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WaypointPatrolController_H__
+#define _WaypointPatrolController_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "tools/Timer.h"
+#include "WaypointController.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport WaypointPatrolController : public WaypointController
+    {
+        public:
+            WaypointPatrolController(Context* context);
+            virtual ~WaypointPatrolController() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+            inline void setAlertnessRadius(float radius)
+                { this->alertnessradius_ = radius; }
+            inline float getAlertnessRadius() const
+                { return this->alertnessradius_; }
+                
+            inline void setAttackRadius(float distance)
+                { this->attackradius_ = distance; }
+            inline float getAttackRadius() const
+                { return this->attackradius_; }
+
+        protected:
+            void searchEnemy();
+
+            float alertnessradius_; //!< Enemies within this radius are being followed and shot.
+            float attackradius_;    //!< Enemies only get shot, if they are within the attackradius_.
+            Timer patrolTimer_;
+    };
+}
+
+#endif /* _WaypointPatrolController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/WingmanController.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/WingmanController.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/WingmanController.cc	(revision 11817)
@@ -0,0 +1,188 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WingmanController.h"
+
+
+namespace orxonox
+{
+
+    RegisterClass(WingmanController);
+    
+    //ActionpointController contains all common functionality of AI Controllers
+    WingmanController::WingmanController(Context* context) : ActionpointController(context)
+    {
+        RegisterObject(WingmanController);
+        this->myLeader_ = nullptr;
+        this->bFirstAction_ = true;
+
+    }
+
+    WingmanController::~WingmanController()
+    {
+        for (WorldEntity* actionpoint : this->actionpoints_)
+        {
+            if (actionpoint)
+                actionpoint->destroy();
+        }
+        this->parsedActionpoints_.clear();
+        this->actionpoints_.clear();
+    }
+    
+    //----action for hard calculations----
+    void WingmanController::action()
+    {
+        if (!this->getControllableEntity() || !this->isActive())
+            return;
+        //----If no leader, find one----
+        if (!this->myLeader_)
+        {
+            ActionpointController* newLeader = (findNewLeader());
+
+            this->myLeader_ = newLeader;
+            if (this->myLeader_)
+            {
+               
+            }
+        }
+        //----If have leader, he will deal with logic----
+        else
+        {
+
+        }
+        if (!this->myLeader_)
+        {
+            ActionpointController::action();
+        }
+        else if (this->myLeader_)
+        {
+            if (this->myLeader_->bKeepFormation_ || !(this->myLeader_->getAction() == Action::FIGHT 
+                || this->myLeader_->getAction() == Action::FIGHTALL
+                || this->myLeader_->getAction() == Action::ATTACK))
+            {
+                this->keepFormation();
+            }
+            else if (!this->myLeader_->bKeepFormation_)
+            {
+
+                if (!this->hasTarget())
+                {
+                    this->setTarget(this->myLeader_->getTarget());
+                }
+                
+            }
+        }
+    }
+     
+   
+    Vector3 WingmanController::getFormationPosition ()
+    {
+        this->setFormationMode( this->myLeader_->getFormationMode() );
+        this->spread_ = this->myLeader_->getSpread();
+        if (this->myLeader_->getIdentifier()->getName() == "DivisionController")
+        {
+            switch (this->formationMode_){
+                case FormationMode::WALL:
+                    return Vector3 (2.0f*this->spread_, 0, 0 - 1.0f*this->tolerance_);
+                case FormationMode::FINGER4: 
+                    return Vector3 (2.0f*this->spread_, 0, this->spread_ - 1.0f*this->tolerance_);
+                case FormationMode::DIAMOND: 
+                    return Vector3 (2.0f*this->spread_, 0, this->spread_ - 1.0f*this->tolerance_);
+                default:
+                    return Vector3::ZERO;
+            }
+        }
+        else
+        {
+            switch (this->formationMode_){
+                case FormationMode::WALL:
+                    return Vector3 (-2.0f*this->spread_, 0, 0 - 1.0f*this->tolerance_);
+                case FormationMode::FINGER4: 
+                    return Vector3 (-2.0f*this->spread_, 0, this->spread_ - 1.0f*this->tolerance_);
+                case FormationMode::DIAMOND: 
+                    return Vector3 (2.0f*this->spread_, -1.0f*this->spread_, 0 - 1.0f*this->tolerance_);
+                default:
+                    return Vector3::ZERO;
+            }
+        }
+    }
+    void WingmanController::keepFormation()
+    {
+        this->bKeepFormation_ = true;
+        ControllableEntity* leaderEntity = this->myLeader_->getControllableEntity();
+        Vector3 targetRelativePosition = this->getFormationPosition();
+        if (!leaderEntity)
+            return;
+        FlyingController::keepFormation (leaderEntity, targetRelativePosition);
+    }
+    //----POST: closest leader that is ready to take a new wingman is returned----
+    ActionpointController* WingmanController::findNewLeader()
+    {
+
+        if (!this->getControllableEntity())
+            return nullptr;
+
+        //----vars for finding the closest leader----
+        ActionpointController* closestLeader = nullptr;
+        float minDistance =  std::numeric_limits<float>::infinity();
+        Gametype* gt = this->getGametype();
+
+        for (ActionpointController* controller : ObjectList<ActionpointController>())
+        {
+            //----0ptr or not a leader or dead?----
+            if (!controller ||
+                (controller->getIdentifier()->getName() != "SectionController" && controller->getIdentifier()->getName() != "DivisionController") ||
+                !(controller->getControllableEntity()))
+                continue;
+            
+            //----same team?----
+            if ( !CommonController::sameTeam (this->getControllableEntity(), controller->getControllableEntity(), gt) )
+                continue;
+            
+            //----check distance----
+            float distance = CommonController::distance (controller->getControllableEntity(), this->getControllableEntity());
+            if (distance < minDistance && !(controller->hasWingman()))
+            {
+                closestLeader = controller;
+                minDistance = distance;
+            }
+        }
+        if (closestLeader)
+        {
+            //----Racing conditions----
+            /*TODO: racing condition check is wrong and redundant, as there is no multithreading here, ticks get called one after another,
+            so it can be simplified to a check of whether leader got a wingman*/
+            if (closestLeader->setWingman(orxonox_cast<ActionpointController*>(this)))
+            {
+                return closestLeader;
+            }
+        }
+        return nullptr;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/WingmanController.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/WingmanController.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/WingmanController.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WingmanController_H__
+#define _WingmanController_H__
+
+
+#include "controllers/ActionpointController.h"
+
+
+namespace orxonox
+{
+    /**
+        @note
+        ActionpointController will not work, if there is no MasterController in the level!
+        All the demos are in a file called AITest.oxw. In the menu look for New AI Testing Level.
+    */
+    class _OrxonoxExport WingmanController : public ActionpointController
+    {
+        public:
+            //----[language demanded functions]----
+                WingmanController(Context* context);
+
+                virtual ~WingmanController();
+            //----[/language demanded functions]----
+            
+            //----[orxonox demanded functions]----
+                virtual bool hasWingman() override
+                    { return false; }
+                virtual bool hasFollower() override
+                    { return false; }
+            //----[/orxonox demanded functions]----
+
+            //----[own functions]----
+               ActionpointController* findNewLeader();
+            //----[/own functions]----
+
+        protected:
+            //----action must only be managed by this----
+                virtual void action() override; //<! action() is called in regular intervals managing the bot's behaviour.
+                Vector3 getFormationPosition ();
+                void keepFormation();
+                
+        private:
+            //----private variables-----
+                WeakPtr<ActionpointController> myLeader_;
+                bool bFirstAction_;
+
+
+    };
+}
+
+#endif /* _WingmanController_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/controllers/testscript.lua
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/controllers/testscript.lua	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/controllers/testscript.lua	(revision 11817)
@@ -0,0 +1,1 @@
+print ('1: Hello World')
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,10 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  GSClient.cc
+  GSGraphics.cc
+  GSLevel.cc
+  GSMainMenu.cc
+  GSRoot.cc
+  GSServer.cc
+  GSMasterServer.cc
+  GSStandalone.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSClient.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSClient.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSClient.cc	(revision 11817)
@@ -0,0 +1,83 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "GSClient.h"
+
+#include "util/Exception.h"
+#include "core/commandline/CommandLineIncludes.h"
+#include "core/Game.h"
+#include "core/GameMode.h"
+#include "network/Client.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSClient, "client", false, false);
+
+    SetCommandLineArgument(dest, "127.0.0.1").information("Server hostname/IP (IP in the form of #.#.#.#)");
+
+    GSClient::GSClient(const GameStateInfo& info)
+        : GameState(info)
+    {
+    }
+
+    GSClient::~GSClient()
+    {
+    }
+
+    void GSClient::activate()
+    {
+        orxout(user_status) << "Starting client" << endl;
+
+        GameMode::setIsClient(true);
+
+//         this->client_ = new Client();
+//         this->client_->setDestination(CommandLineParser::getValue("dest").getString(), CommandLineParser::getValue("port") );
+
+        if( !Client::getInstance()->establishConnection() )
+        {
+            ThrowException(InitialisationFailed, "Could not establish connection with server.");
+        }
+
+        Client::getInstance()->update(Game::getInstance().getGameClock());
+    }
+
+    void GSClient::deactivate()
+    {
+        Client::getInstance()->closeConnection();
+
+        // destroy client
+//         delete this->client_;
+
+        GameMode::setIsClient(false);
+    }
+
+    void GSClient::update(const Clock& time)
+    {
+        Client::getInstance()->update(time);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSClient.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSClient.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSClient.h	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GSClient_H__
+#define _GSClient_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/GameState.h"
+#include "network/NetworkPrereqs.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GSClient : public GameState
+    {
+    public:
+        GSClient(const GameStateInfo& info);
+        ~GSClient();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+    };
+}
+
+#endif /* _GSClient_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSGraphics.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSGraphics.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSGraphics.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Benjamin Knecht
+ *
+ */
+
+/**
+@file
+@brief
+    Implementation of Graphics GameState class.
+ */
+
+#include "GSGraphics.h"
+
+#include "core/Game.h"
+#include "core/GUIManager.h"
+#include "core/command/ConsoleCommand.h"
+#include "core/command/CommandExecutor.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSGraphics, "graphics", false, true);
+
+    GSGraphics::GSGraphics(const GameStateInfo& info)
+        : GameState(info)
+    {
+    }
+
+    GSGraphics::~GSGraphics()
+    {
+    }
+
+    /**
+    @brief
+        This function is called when we enter this game state.
+
+        There is only one thing to do here:
+        \li create console command to toggle GUI
+    */
+    void GSGraphics::activate()
+    {
+
+    }
+
+    /**
+    @brief
+        This function is called when the game state is left
+    */
+    void GSGraphics::deactivate()
+    {
+
+    }
+
+    void GSGraphics::update(const Clock& time)
+    {
+        if (this->getActivity().topState)
+        {
+            // This state can not 'survive' on its own.
+            // Load a user interface therefore
+            Game::getInstance().requestState("mainMenu");
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSGraphics.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSGraphics.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSGraphics.h	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Benjamin Knecht (documentation)
+ *
+ */
+
+/**
+@file
+@brief
+    Declaration of the Graphics GameState class.
+*/
+
+#ifndef _GSGraphics_H__
+#define _GSGraphics_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/GameState.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Game state used when displaying graphics of any kind. Another blubb resides here.
+
+        This game state is only left out if we start a dedicated server where no graphics are present.
+    */
+    class _OrxonoxExport GSGraphics : public GameState
+    {
+    public:
+        GSGraphics(const GameStateInfo& info);
+        ~GSGraphics();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+
+    private:
+    };
+}
+
+#endif /* _GSGraphics_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevel.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevel.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevel.cc	(revision 11817)
@@ -0,0 +1,298 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *      Benjamin Knecht
+ *
+ */
+
+#include "GSLevel.h"
+#include "GSLevelMemento.h"
+
+#include <OgreCompositorManager.h>
+
+#include "util/Clock.h"
+#include "core/input/InputManager.h"
+#include "core/input/InputState.h"
+#include "core/input/KeyBinderManager.h"
+#include "core/Core.h"
+#include "core/CoreIncludes.h"
+#include "core/Game.h"
+#include "core/GameMode.h"
+#include "core/GUIManager.h"
+#include "core/Loader.h"
+#include "core/XMLFile.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "LevelManager.h"
+#include "Level.h"
+#include "PlayerManager.h"
+#include "GSRoot.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSLevel, "level", false, false);
+
+    static const std::string __CC_startMainMenu_name = "startMainMenu";
+    static const std::string __CC_changeGame_name = "changeGame";
+    static const std::string __CC_reloadLevel_name = "reloadLevel";
+
+    SetConsoleCommand(__CC_startMainMenu_name, &GSLevel::startMainMenu).deactivate();
+    SetConsoleCommand(__CC_changeGame_name, &GSLevel::changeGame).defaultValues("").deactivate();
+    SetConsoleCommand(__CC_reloadLevel_name, &GSLevel::reloadLevel).deactivate();
+
+    GSLevel::GSLevel(const GameStateInfo& info)
+        : GameState(info)
+        , gameInputState_(nullptr)
+        , guiMouseOnlyInputState_(nullptr)
+        , guiKeysOnlyInputState_(nullptr)
+        , startFile_(nullptr)
+        , bShowIngameGUI_(false)
+    {
+    }
+
+    GSLevel::~GSLevel()
+    {
+    }
+
+    void GSLevel::activate()
+    {
+        orxout(user_status) << "Loading level" << endl;
+
+        if (GameMode::showsGraphics())
+        {
+            gameInputState_ = InputManager::getInstance().createInputState("game");
+            gameInputState_->setMouseExclusive(true);
+            gameInputState_->setHandler(KeyBinderManager::getInstance().getDefaultAsHandler());
+            KeyBinderManager::getInstance().setToDefault();
+
+            guiMouseOnlyInputState_ = InputManager::getInstance().createInputState("guiMouseOnly");
+            guiMouseOnlyInputState_->setMouseExclusive(true);
+            guiMouseOnlyInputState_->setMouseHandler(&GUIManager::getInstance());
+
+            guiKeysOnlyInputState_ = InputManager::getInstance().createInputState("guiKeysOnly");
+            guiKeysOnlyInputState_->setKeyHandler(&GUIManager::getInstance());
+        }
+
+        this->prepareObjectTracking();
+
+        if (GameMode::isMaster())
+        {
+            this->loadLevel();
+        }
+
+        if (GameMode::showsGraphics())
+        {
+            // level is loaded: we can start capturing the input
+            InputManager::getInstance().enterState("game");
+
+            // connect the HumanPlayer to the game
+            PlayerManager::getInstance().clientConnected(0);
+
+            ModifyConsoleCommand(__CC_startMainMenu_name).activate();
+        }
+
+        if (GameMode::isStandalone())
+        {
+            ModifyConsoleCommand(__CC_changeGame_name).activate();
+            ModifyConsoleCommand(__CC_reloadLevel_name).setObject(this).activate();
+        }
+    }
+
+    void GSLevel::deactivate()
+    {
+        if (GameMode::showsGraphics())
+            InputManager::getInstance().leaveState("game");
+
+        // disconnect all HumanPlayers
+        PlayerManager::getInstance().disconnectAllClients();
+
+        if (GameMode::isMaster())
+            this->unloadLevel();
+        else
+            this->unloadLevelAsClient();
+
+        this->performObjectTracking();
+
+        if (GameMode::showsGraphics())
+        {
+#if OGRE_VERSION < 0x010700
+            // unload all compositors (this is only necessary because we don't yet destroy all resources!)
+            Ogre::CompositorManager::getSingleton().removeAll();
+#endif
+
+            gameInputState_->setHandler(nullptr);
+            guiMouseOnlyInputState_->setHandler(nullptr);
+            guiKeysOnlyInputState_->setHandler(nullptr);
+            InputManager::getInstance().destroyState("game");
+            InputManager::getInstance().destroyState("guiKeysOnly");
+            InputManager::getInstance().destroyState("guiMouseOnly");
+
+            ModifyConsoleCommand(__CC_startMainMenu_name  ).deactivate();
+        }
+
+        if (GameMode::isStandalone())
+        {
+            ModifyConsoleCommand(__CC_changeGame_name).deactivate();
+            ModifyConsoleCommand(__CC_reloadLevel_name).setObject(nullptr).deactivate();
+        }
+    }
+
+    void GSLevel::update(const Clock& time)
+    {
+        // Note: Temporarily moved to GSRoot.
+        //// Call the scene objects
+        //for (Tickable* tickable : ObjectList<Tickable>())
+        //    tickable->tick(time.getDeltaTime() * this->timeFactor_);
+    }
+
+    void GSLevel::prepareObjectTracking()
+    {
+        for (BaseObject* baseObject : ObjectList<BaseObject>())
+            this->staticObjects_.insert(baseObject);
+    }
+
+    void GSLevel::performObjectTracking()
+    {
+        orxout(internal_info) << "Remaining objects:" << endl;
+        unsigned int i = 0;
+        for (BaseObject* baseObject : ObjectList<BaseObject>())
+        {
+            std::set<BaseObject*>::const_iterator find = this->staticObjects_.find(baseObject);
+            if (find == this->staticObjects_.end())
+            {
+                orxout(internal_warning) << ++i << ": " << baseObject->getIdentifier()->getName() << " (" << baseObject << "), references: " << baseObject->getReferenceCount() << endl;
+            }
+        }
+        if (i == 0)
+            orxout(internal_info) << i << " objects remaining. Well done!" << endl;
+        else
+            orxout(internal_warning) << i << " objects remaining. Try harder!" << endl;
+    }
+
+    void GSLevel::loadLevel()
+    {
+        // call the loader
+        startFile_ = new XMLFile(LevelManager::getInstance().getDefaultLevel());
+        bool loaded = Loader::getInstance().load(startFile_);
+
+        Core::getInstance().getConfig()->updateLastLevelTimestamp();
+        if(!loaded)
+            GSRoot::delayedStartMainMenu();
+    }
+
+    void GSLevel::unloadLevel()
+    {
+        Loader::getInstance().unload(startFile_);
+        delete startFile_;
+    }
+
+    /**
+     * Unloads a level when the game instance is (or was) a client in a multiplayer session.
+     * In this case, cleanup after unloading a level is done differently because certain things (e.g. the xml file) are unknown.
+     */
+    void GSLevel::unloadLevelAsClient()
+    {
+        ObjectList<Level> listLevel;
+        for (ObjectList<Level>::iterator it = listLevel.begin(); it != listLevel.end(); )
+        {
+            StrongPtr<Level> level = *(it++); // StrongPtr prevents that the Level gets destroyed while we loop over it
+            ObjectList<BaseObject> listBaseObject(level);
+            for (ObjectList<BaseObject>::iterator it = listBaseObject.begin(); it != listBaseObject.end(); )
+                (it++)->destroy();
+        }
+
+        ObjectList<Synchronisable> listSynchronisable;
+        for (ObjectList<Synchronisable>::iterator it = listSynchronisable.begin(); it != listSynchronisable.end(); )
+        {
+            if (it->getSyncMode() != 0x0)
+                (it++)->destroy();
+            else
+                ++it;
+        }
+    }
+
+    void GSLevel::reloadLevel()
+    {
+        // export all states
+        std::vector<GSLevelMementoState*> states;
+        for (GSLevelMemento* memento : ObjectList<GSLevelMemento>())
+        {
+            GSLevelMementoState* state = memento->exportMementoState();
+            if (state)
+                states.push_back(state);
+        }
+
+        // reload level (or better: reload the whole gamestate)
+        this->deactivate();
+        this->activate();
+
+        // import all states
+        for (GSLevelMemento* memento : ObjectList<GSLevelMemento>())
+            memento->importMementoState(states);
+
+        // delete states
+        for (GSLevelMementoState* state : states)
+            delete state;
+    }
+
+    /**
+    @brief
+        Starts the MainMenu.
+    */
+    /*static*/ void GSLevel::startMainMenu(void)
+    {
+        // HACK
+        Game::getInstance().popState();
+        Game::getInstance().popState();
+    }
+
+    /**
+    @brief
+        Terminates the current game and starts a new game.
+    @param level
+        The filename of the level to be started.
+    */
+    /*static*/ void GSLevel::changeGame(const std::string& level)
+    {
+        if(level != "")
+            LevelManager::getInstance().setDefaultLevel(level);
+
+        // HACK
+        Game::getInstance().popState();
+        Game::getInstance().popState();
+        Game::getInstance().requestStates("standalone, level");
+    }
+
+
+
+    ///////////////////////////////////////////////////////////////////////////
+
+    RegisterAbstractClass(GSLevelMemento).inheritsFrom<OrxonoxInterface>();
+
+    GSLevelMemento::GSLevelMemento()
+    {
+        RegisterObject(GSLevelMemento);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevel.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevel.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevel.h	(revision 11817)
@@ -0,0 +1,73 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Benjamin Knecht
+ *
+ */
+
+#ifndef _GSLevel_H__
+#define _GSLevel_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <set>
+#include "core/GameState.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GSLevel : public GameState
+    {
+    public:
+        GSLevel(const GameStateInfo& info);
+        ~GSLevel();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+
+        static void startMainMenu(void); //!< Starts the MainMenu
+        static void changeGame(const std::string& level); //!< Terminates the current game and starts a new game.
+
+        void reloadLevel();
+
+    private:
+        void loadLevel();
+        void unloadLevel();
+        void unloadLevelAsClient();
+
+        void prepareObjectTracking();
+        void performObjectTracking();
+
+        InputState*              gameInputState_;          //!< input state for normal ingame playing
+        InputState*              guiMouseOnlyInputState_;  //!< input state if we only need the mouse to use the GUI
+        InputState*              guiKeysOnlyInputState_;   //!< input state if we only need the keys to use the GUI
+
+        XMLFile* startFile_;
+        std::set<BaseObject*> staticObjects_;
+        bool bShowIngameGUI_;
+    };
+}
+
+#endif /* _GSLevel_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevelMemento.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevelMemento.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSLevelMemento.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GSLevelMemento_H__
+#define _GSLevelMemento_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    /**
+        @brief This class is an interface for all instances that want to maintain a state beyond the reloading of a level.
+    */
+    class _OrxonoxExport GSLevelMemento : virtual public OrxonoxInterface
+    {
+        friend class GSLevel;
+
+        public:
+            GSLevelMemento(); // Implemented in GSLevel.cc
+
+        protected:
+            /**
+             * Returns the state of this memento. Returns nullptr if no state needed to persist.
+             */
+            virtual GSLevelMementoState* exportMementoState() = 0;
+
+            /**
+             * A list of the states of all mementos. must find the correct one by itself.
+             */
+            virtual void importMementoState(const std::vector<GSLevelMementoState*>& states) = 0;
+    };
+
+    /**
+        @brief Represents the state of a memento. Needs to be inherited by the actual state.
+    */
+    struct _OrxonoxExport GSLevelMementoState
+    {
+        virtual ~GSLevelMementoState() {} // virtual destructor for RTTI
+    };
+}
+
+#endif /* _GSLevelMemento_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMainMenu.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMainMenu.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMainMenu.cc	(revision 11817)
@@ -0,0 +1,239 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GSMainMenu.h"
+
+#include <OgreSceneManager.h>
+
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/Game.h"
+#include "core/GraphicsManager.h"
+#include "core/GUIManager.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/input/KeyBinderManager.h"
+#include "network/Client.h"
+#include "util/StringUtils.h"
+#include "LevelManager.h"
+#include "Scene.h"
+#include "sound/AmbientSound.h"
+// HACK
+#include "core/input/InputManager.h"
+#include "core/input/InputState.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSMainMenu, "mainMenu", false, true);
+
+    static const std::string __CC_startStandalone_name      = "startGame";
+    static const std::string __CC_startServer_name          = "startServer";
+    static const std::string __CC_startClient_name          = "startClient";
+    static const std::string __CC_startDedicated_name       = "startDedicated";
+    static const std::string __CC_setMainMenuSoundPath_name = "setMMSoundPath";
+
+    SetConsoleCommand(__CC_startStandalone_name,      &GSMainMenu::startStandalone).defaultValues("").deactivate();
+    SetConsoleCommand(__CC_startServer_name,          &GSMainMenu::startServer    ).defaultValues("").deactivate();
+    SetConsoleCommand(__CC_startClient_name,          &GSMainMenu::startClient    ).defaultValues("").deactivate();
+    SetConsoleCommand(__CC_startDedicated_name,       &GSMainMenu::startDedicated ).defaultValues("").deactivate();
+    SetConsoleCommand(__CC_setMainMenuSoundPath_name, &GSMainMenu::setMainMenuSoundPath).hide();
+
+    RegisterAbstractClass(GSMainMenu).inheritsFrom<Configurable>();
+
+    GSMainMenu::GSMainMenu(const GameStateInfo& info)
+        : GameState(info)
+    {
+        RegisterObject(GSMainMenu);
+
+        InputManager::getInstance().createInputState("MainMenuHackery", true, true)->setKeyHandler(KeyBinderManager::getInstance().getDefaultAsHandler());
+
+        // create an empty Scene
+        this->scene_ = new Scene(nullptr);
+        this->scene_->setSyncMode( 0x0 );
+        // and a Camera
+        this->camera_ = this->scene_->getSceneManager()->createCamera("mainMenu/Camera");
+        if (GameMode::playsSound())
+        {
+            // Load sound
+            this->ambient_ = new AmbientSound();
+        }
+    }
+
+    GSMainMenu::~GSMainMenu()
+    {
+        if (GameMode::playsSound())
+            this->ambient_->destroy();
+
+        InputManager::getInstance().destroyState("MainMenuHackery");
+
+        this->scene_->getSceneManager()->destroyCamera(this->camera_);
+        this->scene_->destroy();
+    }
+
+    void GSMainMenu::activate()
+    {
+        orxout(user_status) << "Loading main menu" << endl;
+
+        // show main menu
+        GraphicsManager::getInstance().setCamera(this->camera_);
+        GUIManager::getInstance().showGUI("MainMenu", true);
+        GUIManager::getInstance().setBackgroundImage("MainMenuBackground", "Background");
+
+        InputManager::getInstance().enterState("MainMenuHackery");
+
+        ModifyConsoleCommand(__CC_startStandalone_name).activate();
+        ModifyConsoleCommand(__CC_startServer_name    ).activate();
+        ModifyConsoleCommand(__CC_startClient_name    ).activate();
+        ModifyConsoleCommand(__CC_startDedicated_name ).activate();
+        ModifyConsoleCommand(__CC_setMainMenuSoundPath_name).setObject(this);
+
+        KeyBinderManager::getInstance().setToDefault();
+
+        this->setConfigValues();
+
+        if (GameMode::playsSound())
+        {
+            this->ambient_->setLooping(true);
+            this->ambient_->play(); // works without source
+        }
+    }
+
+    void GSMainMenu::deactivate()
+    {
+        if (GameMode::playsSound())
+        {
+            this->ambient_->stop();
+        }
+
+        InputManager::getInstance().leaveState("MainMenuHackery");
+
+        GraphicsManager::getInstance().setCamera(nullptr);
+        GUIManager::getInstance().setBackgroundImage("");
+        GUIManager::hideGUI("MainMenu");
+
+        ModifyConsoleCommand(__CC_startStandalone_name).deactivate();
+        ModifyConsoleCommand(__CC_startServer_name    ).deactivate();
+        ModifyConsoleCommand(__CC_startClient_name    ).deactivate();
+        ModifyConsoleCommand(__CC_startDedicated_name ).deactivate();
+        ModifyConsoleCommand(__CC_setMainMenuSoundPath_name).setObject(nullptr);
+    }
+
+    void GSMainMenu::update(const Clock& time)
+    {
+    }
+
+    void GSMainMenu::setConfigValues()
+    {
+        SetConfigValue(soundPathMain_, "mainmenu.ogg")
+            .description("Contains the path to the main menu sound file.")
+            .callback(this, &GSMainMenu::reloadSound);
+    }
+
+    void GSMainMenu::reloadSound()
+    {
+        if (GameMode::playsSound())
+        {
+            this->ambient_->setAmbientSource(soundPathMain_);
+        }
+    }
+
+    const std::string& GSMainMenu::getMainMenuSoundPath()
+    {
+        return soundPathMain_;
+    }
+
+    void GSMainMenu::setMainMenuSoundPath(const std::string& path)
+    {
+        ModifyConfigValue(soundPathMain_, set, path);
+    }
+
+    /**
+    @brief
+        Start a level in standalone mode.
+    @param level
+        The filename of the level to be started. If empty, the default level is started.
+    */
+    void GSMainMenu::startStandalone(const std::string& level)
+    {
+        if(level != "")
+            LevelManager::getInstance().setDefaultLevel(level);
+
+        // HACK
+        Game::getInstance().popState();
+        Game::getInstance().requestStates("standalone, level");
+    }
+
+    /**
+    @brief
+        Start a level in server mode.
+    @param level
+        The filename of the level to be started. If empty, the default level is started.
+    */
+    void GSMainMenu::startServer(const std::string& level)
+    {
+        if(level != "")
+            LevelManager::getInstance().setDefaultLevel(level);
+
+        // HACK
+        Game::getInstance().popState();
+        Game::getInstance().requestStates("server, level");
+    }
+
+    /**
+    @brief
+        Connect to a game as client.
+    @param destination
+        The destination to connect to. If empty, the client connects to the default destination.
+    */
+    void GSMainMenu::startClient(const std::string& destination)
+    {
+        if(destination != "")
+            Client::getInstance()->setDestination(destination, NETWORK_PORT);
+
+        // HACK
+        Game::getInstance().popState();
+        Game::getInstance().requestStates("client, level");
+    }
+
+    /**
+    @brief
+        Start a level in dedicated mode.
+    @param level
+        The filename of the level to be started. If empty, the default level is started.
+    */
+    void GSMainMenu::startDedicated(const std::string& level)
+    {
+        if(level != "")
+            LevelManager::getInstance().setDefaultLevel(level);
+
+        // HACK
+        Game::getInstance().popState();
+        Game::getInstance().popState();
+        Game::getInstance().requestStates("server, level");
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMainMenu.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMainMenu.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMainMenu.h	(revision 11817)
@@ -0,0 +1,71 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GSMainMenu_H__
+#define _GSMainMenu_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/OgreForwardRefs.h"
+#include "core/GameState.h"
+#include "core/config/Configurable.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GSMainMenu : public GameState, public Configurable
+    {
+    public:
+        GSMainMenu(const GameStateInfo& info);
+        ~GSMainMenu();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+
+        void setConfigValues();
+        void reloadSound();
+        const std::string& getMainMenuSoundPath();
+        void setMainMenuSoundPath(const std::string& path);
+
+        static void startStandalone(const std::string& level = ""); //!< Start a level in standalone mode.
+        static void startServer(const std::string& level = ""); //!< Start a level in server mode.
+        static void startClient(const std::string& destination = ""); //!< Connect to a game as client.
+        static void startDedicated(const std::string& level = ""); //!< Start a level in dedicated mode.
+        static void startIOConsole();
+
+    private:
+        Scene*            scene_;
+        Ogre::Camera*     camera_;
+
+        // ambient sound for the main menu
+        AmbientSound*     ambient_;
+        std::string       soundPathMain_;
+    };
+}
+
+#endif /* _GSMainMenu_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMasterServer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMasterServer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMasterServer.cc	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli 
+ *   Co-authors:
+ *      Reto Grieder (original file for GSServer.cc)
+ *      Fabian 'x3n' Landau (original file for GSServer.cc)
+ *
+ */
+
+#include "GSMasterServer.h"
+
+#include "util/Output.h"
+#include "core/Game.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+  DeclareGameState(GSMasterServer, "masterserver", false, false);
+
+  GSMasterServer::GSMasterServer(const GameStateInfo& info)
+    : GameState(info)
+  {
+
+  }
+
+  GSMasterServer::~GSMasterServer()
+  {
+  }
+
+  void GSMasterServer::activate()
+  {
+    orxout(user_status) << "Starting masterserver" << endl;
+
+    /* TODO make this work for masterserver as well */
+    //GameMode::setIsServer(true);
+
+    this->mserver = new MasterServer();
+    this->mserver->run();
+  }
+
+  void GSMasterServer::deactivate()
+  { /* nothing so far */ }
+
+  void GSMasterServer::update(const Clock& time)
+  { 
+    this->mserver->run();
+  }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMasterServer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMasterServer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSMasterServer.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Sandro 'smerkli' Merkli 
+ *   Co-authors:
+ *      Reto Grieder (Original GSServer.h file this was adapted from)
+ *      ...
+ *
+ */
+
+#ifndef _GSMasterServer_H__
+#define _GSMasterServer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/GameState.h"
+#include "network/NetworkPrereqs.h"
+#include "network/MasterServer.h"
+
+namespace orxonox
+{
+  class _OrxonoxExport GSMasterServer : public GameState
+  {
+    public:
+      GSMasterServer(const GameStateInfo& info);
+      ~GSMasterServer();
+
+      virtual void activate() override;
+      virtual void deactivate() override;
+      virtual void update(const Clock& time) override;
+
+    private:
+      MasterServer *mserver;
+
+
+  };
+}
+
+#endif /* _GSServer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSRoot.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSRoot.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSRoot.cc	(revision 11817)
@@ -0,0 +1,208 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GSRoot.h"
+
+#include "util/Clock.h"
+#include "core/BaseObject.h"
+#include "core/Game.h"
+#include "core/GameMode.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/object/ObjectList.h"
+#include "network/NetworkFunctionIncludes.h"
+#include "tools/Timer.h"
+#include "tools/interfaces/Tickable.h"
+
+#include "GSLevel.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSRoot, "root", false, false);
+
+    static const std::string __CC_setTimeFactor_name = "setTimeFactor";
+    static const std::string __CC_getTimeFactor_name = "getTimeFactor";
+    static const std::string __CC_setPause_name = "setPause";
+    static const std::string __CC_pause_name = "pause";
+
+    /*static*/ bool GSRoot::startMainMenu_s = false;
+
+    SetConsoleCommand("printObjects", &GSRoot::printObjects).hide();
+    SetConsoleCommand(__CC_setTimeFactor_name, &GSRoot::setTimeFactor).accessLevel(AccessLevel::Master).defaultValues(1.0);
+    SetConsoleCommand(__CC_getTimeFactor_name, &GSRoot::getTimeFactor).accessLevel(AccessLevel::Master);
+    SetConsoleCommand(__CC_setPause_name,      &GSRoot::setPause     ).accessLevel(AccessLevel::Master).hide();
+    SetConsoleCommand(__CC_pause_name,         &GSRoot::pause        ).accessLevel(AccessLevel::Master);
+
+    registerStaticNetworkFunction(&TimeFactorListener::setTimeFactor);
+
+    GSRoot::GSRoot(const GameStateInfo& info)
+        : GameState(info)
+        , bPaused_(false)
+        , timeFactorPauseBackup_(1.0f)
+    {
+    }
+
+    GSRoot::~GSRoot()
+    {
+    }
+
+    void GSRoot::printObjects()
+    {
+        unsigned int nr=0;
+        for (BaseObject* baseObject : ObjectList<BaseObject>())
+        {
+            Synchronisable* synchronisable = orxonox_cast<Synchronisable*>(baseObject);
+            if (synchronisable)
+                orxout(debug_output) << "object: " << baseObject->getIdentifier()->getName() << " id: " << synchronisable->getObjectID() << endl;
+            else
+                orxout(debug_output) << "object: " << baseObject->getIdentifier()->getName() << endl;
+            nr++;
+        }
+        orxout(debug_output) << "currently got " << nr << " objects" << endl;
+    }
+
+    void GSRoot::activate()
+    {
+        // reset game speed to normal
+        TimeFactorListener::setTimeFactor(1.0f);
+
+        ModifyConsoleCommand(__CC_setTimeFactor_name).setObject(this);
+        ModifyConsoleCommand(__CC_getTimeFactor_name).setObject(this);
+        ModifyConsoleCommand(__CC_setPause_name).setObject(this);
+        ModifyConsoleCommand(__CC_pause_name).setObject(this);
+    }
+
+    void GSRoot::deactivate()
+    {
+        ModifyConsoleCommand(__CC_setTimeFactor_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_getTimeFactor_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_setPause_name).setObject(nullptr);
+        ModifyConsoleCommand(__CC_pause_name).setObject(nullptr);
+    }
+
+    void GSRoot::update(const Clock& time)
+    {
+        if(startMainMenu_s)
+        {
+            delayedStartMainMenu();
+            startMainMenu_s = false;
+        }
+
+        ObjectList<Timer> listTimer;
+        for (ObjectList<Timer>::iterator it = listTimer.begin(); it; )
+        {
+            Timer* object = *it;
+            ++it;
+            object->tick(time);
+        }
+
+        /*** HACK *** HACK ***/
+        // Call the Tickable objects
+        float leveldt = time.getDeltaTime();
+        if (leveldt > 1.0f)
+        {
+            // just loaded
+            leveldt = 0.0f;
+        }
+        float realdt = leveldt * TimeFactorListener::getTimeFactor();
+        ObjectList<Tickable> listTickable;
+        for (ObjectList<Tickable>::iterator it = listTickable.begin(); it; )
+        {
+            Tickable* object = *it;
+            ++it;
+            object->tick(realdt);
+        }
+        /*** HACK *** HACK ***/
+    }
+
+    /**
+    @brief
+        Changes the speed of Orxonox
+    @remark
+        This function is a hack when placed here!
+        Timefactor should be related to the scene (level or so), not the game
+    */
+    void GSRoot::setTimeFactor(float factor)
+    {
+        if (GameMode::isMaster())
+        {
+            if (!this->bPaused_)
+            {
+                TimeFactorListener::setTimeFactor(factor);
+            }
+            else
+                this->timeFactorPauseBackup_ = factor;
+        }
+    }
+
+    float GSRoot::getTimeFactor()
+    {
+        return TimeFactorListener::getTimeFactor();
+    }
+
+    void GSRoot::pause()
+    {
+        if (GameMode::isMaster())
+        {
+            if (!this->bPaused_)
+            {
+                this->timeFactorPauseBackup_ = TimeFactorListener::getTimeFactor();
+                this->setTimeFactor(0.0f);
+                this->bPaused_ = true;
+            }
+            else
+            {
+                this->bPaused_ = false;
+                this->setTimeFactor(this->timeFactorPauseBackup_);
+            }
+        }
+    }
+
+    void GSRoot::setPause(bool pause)
+    {
+        if (GameMode::isMaster())
+        {
+            if (pause != this->bPaused_)
+                this->pause();
+        }
+    }
+
+    void GSRoot::changedTimeFactor(float factor_new, float factor_old)
+    {
+        if (!GameMode::isStandalone())
+            callStaticNetworkFunction(&TimeFactorListener::setTimeFactor, NETWORK_PEER_ID_BROADCAST, factor_new);
+    }
+
+    /*static*/ void GSRoot::delayedStartMainMenu(void)
+    {
+        if(!startMainMenu_s)
+            startMainMenu_s = true;
+        else
+            GSLevel::startMainMenu();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSRoot.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSRoot.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSRoot.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GSRoot_H__
+#define _GSRoot_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/GameState.h"
+#include "tools/interfaces/TimeFactorListener.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GSRoot : public GameState, public TimeFactorListener
+    {
+    public:
+        GSRoot(const GameStateInfo& info);
+        ~GSRoot();
+
+        static void printObjects();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+
+        // this has to be public because proteced triggers a bug in msvc
+        // when taking the function address.
+        void setTimeFactor(float factor);
+        void setPause(bool pause);
+        void pause();
+
+        float getTimeFactor();
+
+        static void delayedStartMainMenu(void);
+
+    protected:
+        virtual void changedTimeFactor(float factor_new, float factor_old) override;
+
+    private:
+        bool                  bPaused_;
+        float                 timeFactorPauseBackup_;
+        static bool           startMainMenu_s;
+    };
+}
+
+#endif /* _GSRoot_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSServer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSServer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSServer.cc	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "GSServer.h"
+
+#include "util/Output.h"
+#include "core/commandline/CommandLineIncludes.h"
+#include "core/Game.h"
+#include "core/GameMode.h"
+#include "network/Server.h"
+#include "network/Connection.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSServer, "server", false, false);
+
+    SetCommandLineArgument(port, NETWORK_PORT).shortcut("p").information("Network communication port to be used 0-65535 (default: 55556)");
+
+    GSServer::GSServer(const GameStateInfo& info)
+        : GameState(info)
+        , server_(nullptr)
+    {
+    }
+
+    GSServer::~GSServer()
+    {
+    }
+
+    void GSServer::activate()
+    {
+        orxout(user_status) << "Starting server" << endl;
+
+        GameMode::setIsServer(true);
+
+        this->server_ = new Server(CommandLineParser::getValue("port").get<int>());
+        orxout(user_status) << "Loading scene in server mode" << endl;
+
+        server_->open();
+    }
+
+    void GSServer::deactivate()
+    {
+        this->server_->close();
+        delete this->server_;
+
+        GameMode::setIsServer(false);
+    }
+
+    void GSServer::update(const Clock& time)
+    {
+        server_->update(time);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSServer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSServer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSServer.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GSServer_H__
+#define _GSServer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/GameState.h"
+#include "network/NetworkPrereqs.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GSServer : public GameState
+    {
+    public:
+        GSServer(const GameStateInfo& info);
+        ~GSServer();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+
+    private:
+        Server* server_;
+    };
+}
+
+#endif /* _GSServer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSStandalone.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSStandalone.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSStandalone.cc	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#include "GSStandalone.h"
+
+#include "core/Game.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+    DeclareGameState(GSStandalone, "standalone", false, true);
+
+    GSStandalone::GSStandalone(const GameStateInfo& info)
+        : GameState(info)
+    {
+    }
+
+    GSStandalone::~GSStandalone()
+    {
+    }
+
+
+    void GSStandalone::activate()
+    {
+        GameMode::setIsStandalone(true);
+    }
+
+    void GSStandalone::deactivate()
+    {
+        GameMode::setIsStandalone(false);
+    }
+
+    void GSStandalone::update(const Clock& time)
+    {
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSStandalone.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSStandalone.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gamestates/GSStandalone.h	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GSStandalone_H__
+#define _GSStandalone_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/GameState.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GSStandalone : public GameState
+    {
+    public:
+        GSStandalone(const GameStateInfo& info);
+        ~GSStandalone();
+
+        virtual void activate() override;
+        virtual void deactivate() override;
+        virtual void update(const Clock& time) override;
+
+    private:
+    };
+}
+
+#endif /* _GSStandalone_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Asteroids.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Asteroids.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Asteroids.cc	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Asteroids.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Asteroids);
+
+    Asteroids::Asteroids(Context* context) : Gametype(context)
+    {
+        RegisterObject(Asteroids);
+        this->firstCheckpointReached_ = false;
+        this->numberOfBots_=0; //sets number of default bots temporarly to 0
+    }
+
+    void Asteroids::tick(float dt)
+    {
+        SUPER(Asteroids, tick, dt);
+
+        if (firstCheckpointReached_ && !this->timerIsActive_)
+        {
+            this->startTimer();
+        }
+
+        if (this->time_ < 0 && !this->hasEnded() && this->timerIsActive_)
+        {
+            this->gtinfo_->sendAnnounceMessage("Time's up - you have lost the match!");
+            this->end();
+        }
+    }
+
+    void Asteroids::pawnKilled(Pawn* victim, Pawn* killer)
+    {
+        if (victim && victim->getPlayer())
+        {
+            this->gtinfo_->sendAnnounceMessage("You're dead - you have lost the match!");
+            this->end();
+        }
+    }
+
+    void Asteroids::start()
+    {
+        Gametype::start();
+
+        std::string message("The match has started! Reach the first chekpoint within 15 seconds! But be aware, there may be pirates around...");
+        ChatManager::message(message);
+
+    }
+
+    void Asteroids::end()
+    {
+        Gametype::end();
+
+        std::string message("The match has ended.");
+        ChatManager::message(message);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Asteroids.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Asteroids.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Asteroids.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Aurelian Jaggi
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Asteroids_H__
+#define _Asteroids_H__
+
+#include "OrxonoxPrereqs.h"
+#include "Gametype.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Asteroids : public Gametype
+    {
+        public:
+            Asteroids(Context* context);
+            virtual ~Asteroids() {}
+
+            virtual void tick(float dt) override;
+
+            virtual void start() override;
+            virtual void end() override;
+
+            inline void firstCheckpointReached(bool reached)
+                { this->firstCheckpointReached_ = reached; }
+
+        protected:
+            virtual void pawnKilled(Pawn* victim, Pawn* killer = nullptr) override;
+
+        private:
+            bool firstCheckpointReached_;
+            bool gameEnded_;
+    };
+}
+
+#endif /* _Asteroids_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,14 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  Gametype.cc
+  Deathmatch.cc
+  TeamDeathmatch.cc
+  TeamBaseMatch.cc
+  UnderAttack.cc
+  Asteroids.cc
+  Dynamicmatch.cc
+  LastManStanding.cc
+  LastTeamStanding.cc
+  TeamGametype.cc
+  Mission.cc
+  StoryMode.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Deathmatch.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Deathmatch.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Deathmatch.cc	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Deathmatch.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Deathmatch);
+
+    Deathmatch::Deathmatch(Context* context) : Gametype(context)
+    {
+        RegisterObject(Deathmatch);
+    }
+
+    void Deathmatch::start()
+    {
+        Gametype::start();
+
+        std::string message("The match has started!");
+        ChatManager::message(message);
+    }
+
+    void Deathmatch::end()
+    {
+        Gametype::end();
+
+        std::string message("The match has ended.");
+        ChatManager::message(message);
+    }
+
+    void Deathmatch::playerEntered(PlayerInfo* player)
+    {
+        Gametype::playerEntered(player);
+
+        const std::string& message = player->getName() + " entered the game";
+        ChatManager::message(message);
+    }
+
+    bool Deathmatch::playerLeft(PlayerInfo* player)
+    {
+        bool valid_player = Gametype::playerLeft(player);
+
+        if (valid_player)
+        {
+            const std::string& message = player->getName() + " left the game";
+            ChatManager::message(message);
+        }
+
+        return valid_player;
+    }
+
+    bool Deathmatch::playerChangedName(PlayerInfo* player)
+    {
+        bool valid_player = Gametype::playerChangedName(player);
+
+        if (valid_player)
+        {
+            const std::string& message = player->getOldName() + " changed name to " + player->getName();
+            ChatManager::message(message);
+        }
+
+        return valid_player;
+    }
+
+    void Deathmatch::pawnKilled(Pawn* victim, Pawn* killer)
+    {
+        if (victim && victim->getPlayer())
+        {
+            std::string message;
+            if (killer)
+            {
+                if (killer->getPlayer())
+                    message = victim->getPlayer()->getName() + " was killed by " + killer->getPlayer()->getName();
+                else
+                    message = victim->getPlayer()->getName() + " was killed";
+            }
+            else
+                message = victim->getPlayer()->getName() + " died";
+
+            ChatManager::message(message);
+        }
+
+        Gametype::pawnKilled(victim, killer);
+    }
+
+    void Deathmatch::playerScored(PlayerInfo* player, int score)
+    {
+        Gametype::playerScored(player, score);
+
+        if (player)
+        {
+            const std::string& message = player->getName() + " scores!";
+            ChatManager::message(message);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Deathmatch.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Deathmatch.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Deathmatch.h	(revision 11817)
@@ -0,0 +1,54 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Deathmatch_H__
+#define _Deathmatch_H__
+
+#include "OrxonoxPrereqs.h"
+#include "Gametype.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Deathmatch : public Gametype
+    {
+        public:
+            Deathmatch(Context* context);
+            virtual ~Deathmatch() {}
+
+            virtual void start() override;
+            virtual void end() override;
+            virtual void playerEntered(PlayerInfo* player) override;
+            virtual bool playerLeft(PlayerInfo* player) override;
+            virtual bool playerChangedName(PlayerInfo* player) override;
+
+            virtual void pawnKilled(Pawn* victim, Pawn* killer = nullptr) override;
+            virtual void playerScored(PlayerInfo* player, int score = 1) override;
+    };
+}
+
+#endif /* _Deathmatch_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Dynamicmatch.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Dynamicmatch.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Dynamicmatch.cc	(revision 11817)
@@ -0,0 +1,683 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Dynamicmatch.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "interfaces/TeamColourable.h"
+#include "items/Engine.h"
+#include "tools/Timer.h"
+#include "worldentities/TeamSpawnPoint.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(Dynamicmatch);
+
+    Dynamicmatch::Dynamicmatch(Context* context) : Gametype(context)
+    {
+        RegisterObject(Dynamicmatch);
+        this->gameTime_ = 180;
+        this->setConfigValues();
+        this->chaser=0;
+        this->piggy=1;
+        this->killer=2;
+        this->notEnoughPigs=false;
+        this->notEnoughKillers=false;
+        this->notEnoughChasers=false;
+        this->gameEnded_ =false;
+        this->timesequence_ = static_cast<int>(this->gameTime_);
+        this->friendlyfire=true;
+        this->numberOf[chaser]=0;
+        this->numberOf[piggy]=0;
+        this->numberOf[killer]=0;
+        this->tutorial=true;
+        this->pointsPerTime=1.0f;
+        this->setHUDTemplate("DynamicmatchHUD");
+    }
+
+    Dynamicmatch::~Dynamicmatch()
+    {
+        for (Timer* timer : this->piggyTimers_)
+            delete timer;
+    }
+
+    void Dynamicmatch::setConfigValues()
+    {
+        SetConfigValue(gameTime_, 180);
+        SetConfigValue(friendlyfire, true);
+        SetConfigValue(tutorial, true);
+        static ColourValue colours[] =
+        {
+            ColourValue(1.0f, 0.3f, 0.3f),  //chasercolour
+            ColourValue(0.3f, 0.3f, 1.0f),  //piggycolour
+            ColourValue(0.3f, 1.0f, 0.3f)   //killercolour  what about black: 0.0f, 0.0f, 0.0f
+        };
+        static std::vector<ColourValue> defaultcolours(colours, colours + sizeof(colours) / sizeof(ColourValue));
+
+        SetConfigValue(partyColours_, defaultcolours);
+    }
+
+    bool Dynamicmatch::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        //TODO: static and fading message for the "human" player's
+        if (!originator||!victim)
+            return false;
+        if (!originator->getPlayer()||!victim->getPlayer())
+            return false;
+        if (victim && victim->getPlayer()) //&& originator && originator->getPlayer() ??
+        {
+            int target = playerParty_[victim->getPlayer()];
+            int source = playerParty_[originator->getPlayer()];
+
+            //Case: Not Enough Pigs: party change (= party management)
+            if (notEnoughPigs)
+            {
+                numberOf[target]--; //decrease numberof victims's party
+                playerParty_[victim->getPlayer()]=piggy; //victim's new party: pig
+                setPlayerColour(victim->getPlayer()); //victim's new colour
+                numberOf[piggy]++; //party switch: number of players is not affected (decrease and increase)
+
+                    if(tutorial) //announce party switch
+                    {
+                         std::map<PlayerInfo*, Player>::iterator it2 = this->players_.find(victim->getPlayer());
+                         if (it2 != this->players_.end())
+                         {
+                              this->gtinfo_->sendStaticMessage("Either hide or shoot a chaser.",it2->first->getClientID(), partyColours_[chaser]);
+                              this->gtinfo_->sendFadingMessage("You're now a victim.",it2->first->getClientID());
+                         }
+                    }
+                    if (notEnoughKillers) //reward the originator
+                    {
+                        numberOf[source]--; //decrease numberof originator's party
+                        playerParty_[originator->getPlayer()]=killer; //originator's new party: killer
+                        setPlayerColour(originator->getPlayer()); //originator's new colour
+                        numberOf[killer]++;
+
+                        if(tutorial) //announce party switch
+                        {
+                             std::map<PlayerInfo*, Player>::iterator it3 = this->players_.find(originator->getPlayer());
+                             if (it3 != this->players_.end())
+                             {
+                                  this->gtinfo_->sendStaticMessage("Take the chasers down.",it3->first->getClientID(), partyColours_[chaser]);
+                                  this->gtinfo_->sendFadingMessage("You're now a killer.",it3->first->getClientID());
+                             }
+                        }
+                    }
+                evaluatePlayerParties(); //check if the party change has to trigger futher party changes
+
+                //Give new pig boost
+                SpaceShip* spaceship = orxonox_cast<SpaceShip*>(victim);
+                this->grantPigBoost(spaceship);
+            }
+
+            //Case: notEnoughKillers: party change
+            else if (notEnoughKillers)
+            {
+                numberOf[source]--; //decrease numberof originator's party
+                playerParty_[originator->getPlayer()]=killer; //originator's new party: killer
+                setPlayerColour(originator->getPlayer()); //originator colour
+                numberOf[killer]++; //party switch: number of players is not affected (decrease and increase)
+
+
+                if(tutorial) //announce party switch
+                {
+                     std::map<PlayerInfo*, Player>::iterator it3 = this->players_.find(originator->getPlayer());
+                     if (it3 != this->players_.end())
+                     {
+                          this->gtinfo_->sendStaticMessage("Take the chasers down.",it3->first->getClientID(),partyColours_[chaser]);
+                          this->gtinfo_->sendFadingMessage("You're now a killer.",it3->first->getClientID());
+                     }
+                }
+                evaluatePlayerParties(); //check if the party change has to trigger futher party changes
+            }
+            //Case: notEnoughChasers: party change
+            else if (notEnoughChasers)
+            {
+                numberOf[target]--; //decrease numberof victims's party
+                playerParty_[victim->getPlayer()]=chaser; //victim's new party: chaser
+                setPlayerColour(victim->getPlayer()); //victim colour
+                numberOf[chaser]++; //party switch: number of players is not affected (decrease and increase)
+
+                if(tutorial) //announce party switch
+                {
+                     std::map<PlayerInfo*, Player>::iterator it3 = this->players_.find(originator->getPlayer());
+                     if (it3 != this->players_.end())
+                     {
+                          if (numberOf[killer]>0)
+                              this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible. Defend yourself against the killers.",it3->first->getClientID(),partyColours_[piggy]);
+
+                          else
+                              this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible.",it3->first->getClientID(),partyColours_[piggy]);
+                          this->gtinfo_->sendFadingMessage("You're now a chaser.",it3->first->getClientID());
+                     }
+                }
+                evaluatePlayerParties(); //check if the party change has to trigger futher party changes
+            }
+
+            //Case: chaser vs. killer
+            else if ((source == killer && target == chaser)||(target == killer && source == chaser ))
+            {
+                return true;
+            }
+
+            //Case: a chaser hits piggy
+            else if ((source==chaser)&&(target==piggy))
+            {
+                std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
+                if (it != this->players_.end())
+                    {
+                        it->second.frags_++;
+                    }
+            }
+            //Case: piggy hits chaser
+            else if (source==piggy&&target==chaser)
+            {
+                //partyswitch: victim bcomes piggy and the originator(piggy) becomes chaser
+                playerParty_[victim->getPlayer()]=piggy;
+                playerParty_[originator->getPlayer()]=chaser;
+
+                //party switch -> colour switch
+                setPlayerColour(victim->getPlayer()); //victim colour
+                setPlayerColour(originator->getPlayer());//originator colour
+
+                //Announce pary switch
+                if(tutorial)
+                {
+                     std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
+                     if (it != this->players_.end())
+                     {
+                          if (numberOf[killer]>0)
+                              this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible. Defend yourself against the killers.",it->first->getClientID(), partyColours_[piggy]);
+                          else
+                              this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible.",it->first->getClientID(),partyColours_[piggy]);
+                          this->gtinfo_->sendFadingMessage("You're now a chaser.",it->first->getClientID());
+                     }
+                     std::map<PlayerInfo*, Player>::iterator it2 = this->players_.find(victim->getPlayer());
+                     if (it2 != this->players_.end())
+                     {
+                          this->gtinfo_->sendStaticMessage("Either hide or shoot a chaser.",it2->first->getClientID(),partyColours_[chaser]);
+                          this->gtinfo_->sendFadingMessage("You're now a victim.",it2->first->getClientID());
+                     }
+                }
+                //Give new pig boost
+                SpaceShip* spaceship = orxonox_cast<SpaceShip*>(victim);
+                this->grantPigBoost(spaceship);
+            }
+            // killer vs piggy
+            else if (source==killer &&target==piggy) //party and colour switch
+            {
+            playerParty_[victim->getPlayer()]=killer;
+            playerParty_[originator->getPlayer()]=piggy;
+
+            setPlayerColour(victim->getPlayer()); //victim colour
+            setPlayerColour(originator->getPlayer()); //originator colour
+
+            if(tutorial) //Announce pary switch
+            {
+                 std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
+                 if (it != this->players_.end())
+                 {
+                      this->gtinfo_->sendStaticMessage("Either hide or shoot a chaser.",it->first->getClientID(),partyColours_[chaser]);
+                      this->gtinfo_->sendFadingMessage("You're now a victim.",it->first->getClientID());
+                 }
+                 std::map<PlayerInfo*, Player>::iterator it2 = this->players_.find(victim->getPlayer());
+                 if (it2 != this->players_.end())
+                 {
+                      this->gtinfo_->sendStaticMessage("Take the chasers down.",it2->first->getClientID(),partyColours_[chaser]);
+                      this->gtinfo_->sendFadingMessage("You're now a killer.",it2->first->getClientID());
+                 }
+                }
+            }
+            //Case: friendly fire
+            else if (friendlyfire && (source == target))
+            {
+                this->playerScored(originator->getPlayer(), -1);
+            }
+        }
+        return false; //default: no damage
+    }
+
+
+
+    bool Dynamicmatch::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        //killers can kill chasers and killers can be killed by chasers
+        if ((playerParty_[originator->getPlayer()] == killer && playerParty_[victim->getPlayer()] == chaser)||(playerParty_[victim->getPlayer()] == killer &&
+        playerParty_[originator->getPlayer()] == chaser ))
+        {
+            if (playerParty_[originator->getPlayer()] == killer) //reward the killer
+            {
+                this->playerScored(originator->getPlayer(), 25);
+            }
+            return true;
+        }
+        else return false;
+    }
+
+    /**
+    @brief
+        Grant the victim a boost.
+    @param spaceship
+        The SpaceShip to give the boost.
+    */
+    void Dynamicmatch::grantPigBoost(SpaceShip* spaceship)
+    {
+        // Give victim boost
+        if (spaceship)
+        {
+            spaceship->addSpeedFactor(5);
+            ExecutorPtr executor = createExecutor(createFunctor(&Dynamicmatch::resetSpeedFactor, this));
+            Timer* timer = new Timer(10, false, executor);
+            executor->setDefaultValue(0, spaceship); // TODO: use WeakPtr because spaceship can be destroyed in the meantime
+            executor->setDefaultValue(1, timer);
+            this->piggyTimers_.insert(timer);
+        }
+    }
+
+    void Dynamicmatch::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) //set party + colouring
+    {
+        if (!player)
+            return;
+
+        Dynamicmatch::setPlayerColour(player); //Set playercolour
+        evaluatePlayerParties();
+    }
+
+    void Dynamicmatch::playerEntered(PlayerInfo* player) //standardfunction
+    {
+        if (!player)// only for safety
+            return;
+        playerParty_[player]=chaser; //Set playerparty
+        numberOf[chaser]++;
+        Gametype::playerEntered(player);
+        const std::string& message = player->getName() + " entered the game";
+        ChatManager::message(message);
+    }
+
+    bool Dynamicmatch::playerLeft(PlayerInfo* player) //standardfunction
+    {
+        bool valid_player = Gametype::playerLeft(player);
+        if (valid_player)
+        {
+            switch (playerParty_[player])
+            {
+            case 0: numberOf[chaser]--; break;
+            case 1: numberOf[piggy]--; break;
+            case 2: numberOf[killer]--; break;
+            }
+            const std::string& message = player->getName() + " left the game";
+            ChatManager::message(message);
+            //remove player from map
+            playerParty_.erase (player);
+            //adjust player parties
+            evaluatePlayerParties();
+        }
+
+        return valid_player;
+    }
+
+
+    void Dynamicmatch::tick(float dt)
+    {
+        SUPER(Dynamicmatch, tick, dt);
+
+        if (this->hasStarted() && !gameEnded_)
+        {
+            pointsPerTime = pointsPerTime + dt; //increase points
+            gameTime_ = gameTime_ - dt; // decrease game time
+            if (pointsPerTime > 2.0f) //hard coded points for victim! should be changed
+            {
+                pointsPerTime = 0.0f;
+                rewardPig();
+            }
+            if (gameTime_<= 0)
+            {
+                this->gameEnded_ = true;
+                this->end();
+            }
+            if ( gameTime_ <= timesequence_ && gameTime_ > 0)
+            {
+                const std::string& message = multi_cast<std::string>(timesequence_) + " seconds left!";
+
+                this->gtinfo_->sendAnnounceMessage(message);
+
+                if (timesequence_ >= 30 && timesequence_ <= 60)
+                {
+                    timesequence_ = timesequence_ - 10;
+                }
+                else if (timesequence_ <= 30)
+                {
+                    timesequence_ = timesequence_ - 5;
+                }
+                else
+                {
+                    timesequence_ = timesequence_ - 30;
+                }
+            }
+        }
+    }
+
+/**
+    @brief The reward function is called every 2 seconds via the tick function and makes the victim score points.
+*/
+    void Dynamicmatch::rewardPig()
+    {
+        for (const auto& mapEntry : this->playerParty_) //durch alle Spieler iterieren und alle piggys finden
+        {
+            if (mapEntry.second==piggy)//Spieler mit der Pig-party frags++
+            {
+                 this->playerScored(mapEntry.first);
+            }
+        }
+    }
+    void Dynamicmatch::setPlayerColour(PlayerInfo* player) // sets a player's colour
+    {
+        std::map<PlayerInfo*, int>::const_iterator it_player = this->playerParty_.find(player);
+        Pawn* pawn = orxonox_cast<Pawn*>(player->getControllableEntity());
+            if (pawn)
+            {
+                pawn->setRadarObjectColour(this->partyColours_[it_player->second]);
+
+                std::set<WorldEntity*> pawnAttachments = pawn->getAttachedObjects();
+                for (WorldEntity* pawnAttachment : pawnAttachments)
+                {
+                    if (pawnAttachment->isA(Class(TeamColourable)))
+                    {
+                        TeamColourable* tc = orxonox_cast<TeamColourable*>(pawnAttachment);
+                        tc->setTeamColour(this->partyColours_[it_player->second]);
+                    }
+                }
+            }
+    }
+
+    void Dynamicmatch::evaluatePlayerParties() //manages the notEnough booleans (here the percentage of special players is implemented)
+    {
+        //pigs: 1 + every 6th player is a pig
+        if ( (1 + getPlayerCount()/6) > numberOf[piggy])
+        {
+            notEnoughPigs=true;
+            if (tutorial) // Announce selectionphase
+            {
+             for (const auto& mapEntry : this->playerParty_)
+                {
+                    if (!mapEntry.first)//in order to catch nullpointer
+                        continue;
+                    if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    this->gtinfo_->sendStaticMessage("Selection phase: Shoot at everything that moves.",mapEntry.first->getClientID(),ColourValue(1.0f, 1.0f, 0.5f));
+                }
+            }
+        }
+        else
+        {
+             notEnoughPigs=false;
+             if(tutorial&&(!notEnoughKillers)&&(!notEnoughChasers)) //Selection phase over
+             {
+                  for (const auto& mapEntry : this->playerParty_)
+                  {
+                       if (!mapEntry.first)//in order to catch nullpointer
+                           continue;
+                       if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                           continue;
+                       else if (mapEntry.second==chaser)
+                       {
+                           if (numberOf[killer]>0)
+                               this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible. Defend yourself against the killers.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           else
+                               this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           //this->gtinfo_->sendFadingMessage("You're now a chaser.",it->first->getClientID());
+                       }
+                       else if (mapEntry.second==piggy)
+                       {
+                           this->gtinfo_->sendStaticMessage("Either hide or shoot a chaser.",mapEntry.first->getClientID(),partyColours_[chaser]);
+                           //this->gtinfo_->sendFadingMessage("You're now a victim.",it->first->getClientID());
+                       }
+                       else if (mapEntry.second==killer)
+                       {
+                           this->gtinfo_->sendStaticMessage("Take the chasers down.",mapEntry.first->getClientID(),partyColours_[chaser]);
+                           //this->gtinfo_->sendFadingMessage("You're now a killer.",it->first->getClientID());
+                       }
+                  }
+
+             }
+        }
+        //killers: every 4th player is a killer
+        if ( static_cast<unsigned int>(getPlayerCount()/4) > numberOf[killer])
+        {
+            notEnoughKillers=true;
+            if (tutorial) // Announce selectionphase
+            {
+             for (const auto& mapEntry : this->playerParty_)
+                {
+                    if (!mapEntry.first)//in order to catch nullpointer
+                        continue;
+                    if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    this->gtinfo_->sendStaticMessage("Selection phase: Shoot at everything that moves.",mapEntry.first->getClientID(),ColourValue(1.0f, 1.0f, 0.5f));
+                }
+            }
+        }
+        else
+        {
+            notEnoughKillers=false;
+            if(tutorial&&(!notEnoughPigs)&&(!notEnoughChasers)) //Selection phase over
+             {
+                  for (const auto& mapEntry : this->playerParty_)
+                  {
+                       if (!mapEntry.first)
+                           continue;
+                       if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                           continue;
+                       else if (mapEntry.second==chaser)
+                       {
+                           if (numberOf[killer]>0)
+                               this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible. Defend yourself against the killers.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           else
+                               this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           //this->gtinfo_->sendFadingMessage("You're now a chaser.",it->first->getClientID());
+                       }
+                       else if (mapEntry.second==piggy)
+                       {
+                           this->gtinfo_->sendStaticMessage("Either hide or shoot a chaser.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           //this->gtinfo_->sendFadingMessage("You're now a victim.",it->first->getClientID());
+                       }
+                       else if (mapEntry.second==killer)
+                       {
+                           this->gtinfo_->sendStaticMessage("Take the chasers down.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           //this->gtinfo_->sendFadingMessage("You're now a killer.",it->first->getClientID());
+                       }
+                  }
+
+             }
+
+        }
+        //chasers: there are more chasers than killers + pigs
+        if (numberOf[piggy]+numberOf[killer] > numberOf[chaser])
+        {
+            notEnoughChasers=true;
+            if (tutorial) // Announce selectionphase
+            {
+             for (const auto& mapEntry : this->playerParty_)
+                {
+                    if (!mapEntry.first)//in order to catch nullpointer
+                        continue;
+                    if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    this->gtinfo_->sendStaticMessage("Selection phase: Shoot at everything that moves.",mapEntry.first->getClientID(),ColourValue(1.0f, 1.0f, 0.5f));
+                }
+            }
+        }
+        else
+        {
+             notEnoughChasers=false;
+             if(tutorial&&(!notEnoughPigs)&&(!notEnoughKillers)) //Selection phase over
+             {
+                  for (const auto& mapEntry : this->playerParty_)
+                  {
+                       if (!mapEntry.first)
+                           continue;
+                       if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                           continue;
+                       else if (mapEntry.second==chaser)
+                       {
+                           if (numberOf[killer]>0)
+                               this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible. Defend yourself against the killers.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           else
+                               this->gtinfo_->sendStaticMessage("Shoot at the victim as often as possible.",mapEntry.first->getClientID(),partyColours_[piggy]);
+                           //this->gtinfo_->sendFadingMessage("You're now a chaser.",it->first->getClientID());
+                       }
+                       else if (mapEntry.second==piggy)
+                       {
+                           this->gtinfo_->sendStaticMessage("Either hide or shoot a chaser.",mapEntry.first->getClientID(),partyColours_[chaser]);
+                           //this->gtinfo_->sendFadingMessage("You're now a victim.",it->first->getClientID());
+                       }
+                       else if (mapEntry.second==killer)
+                       {
+                           this->gtinfo_->sendStaticMessage("Take the chasers down.",mapEntry.first->getClientID(),partyColours_[chaser]);
+                           //this->gtinfo_->sendFadingMessage("You're now a killer.",it->first->getClientID());
+                       }
+                  }
+
+             }
+        }
+    }
+
+    int Dynamicmatch::getParty(PlayerInfo* player) // helper function for ArtificialController
+    {
+        return this->playerParty_[player];
+    }
+
+    void Dynamicmatch::resetSpeedFactor(SpaceShip* spaceship, Timer* timer)// helper function
+    {
+        if (spaceship)
+        {
+            spaceship->addSpeedFactor(1.0f/5.0f);
+        }
+
+        this->piggyTimers_.erase(timer);
+        delete timer;
+    }
+
+    bool Dynamicmatch::playerChangedName(PlayerInfo* player) //standardfunction
+    {
+        bool valid_player = Gametype::playerChangedName(player);
+        if (valid_player)
+        {
+            const std::string& message = player->getOldName() + " changed name to " + player->getName();
+            ChatManager::message(message);
+        }
+
+        return valid_player;
+    }
+
+    void Dynamicmatch::start()
+    {
+        Gametype::start();
+        if(!tutorial)
+        {
+            std::string message("Dynamicmatch started!");
+            ChatManager::message(message);
+        }
+        else if(tutorial) // Announce selectionphase
+        {
+            for (const auto& mapEntry : this->playerParty_)
+            {
+                if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                    continue;
+                this->gtinfo_->sendStaticMessage("Selection phase: Shoot at everything that moves.",mapEntry.first->getClientID(),ColourValue(1.0f, 1.0f, 0.5f));
+            }
+        }
+    }
+
+    /*void Dynamicmatch::instructions()
+    {
+        std::string message("Earn points:\n\n\n\tIf you're red: Chase the blue player!\n\n\tIf you're blue shoot at a red player or hide.\n\n\tIf you're green: You've got the licence to kill red players!");
+        ChatManager::message(message);
+        callInstructions_.setTimer(10, false, createExecutor(createFunctor(&Dynamicmatch::furtherInstructions, this)));
+    }
+
+    void Dynamicmatch::furtherInstructions()
+    {
+        std::string message("After 3 Minutes the game is over.");
+        ChatManager::message(message);
+    }*/
+    void Dynamicmatch::end()
+    {
+        Gametype::end();
+
+        std::string message("Time out. Press F2 to see the points you scored.");
+        ChatManager::message(message);
+    }
+    SpawnPoint* Dynamicmatch::getBestSpawnPoint(PlayerInfo* player) const
+    {
+        int desiredTeamNr = -1;
+        std::map<PlayerInfo*, int>::const_iterator it_player = this->playerParty_.find(player);
+        if (it_player != this->playerParty_.end())
+            desiredTeamNr = it_player->second;
+
+        // Only use spawnpoints of the own team (or non-team-spawnpoints)
+        std::set<SpawnPoint*> teamSpawnPoints = this->spawnpoints_;
+        for (std::set<SpawnPoint*>::iterator it = teamSpawnPoints.begin(); it != teamSpawnPoints.end(); )
+        {
+            if ((*it)->isA(Class(TeamSpawnPoint)))
+            {
+                TeamSpawnPoint* tsp = orxonox_cast<TeamSpawnPoint*>(*it);
+                if (tsp && static_cast<int>(tsp->getTeamNumber()) != desiredTeamNr)//getTeamNumber!!
+                {
+                    teamSpawnPoints.erase(it++);
+                    continue;
+                }
+            }
+
+            ++it;
+        }
+
+        if (teamSpawnPoints.size() > 0)
+        {
+            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(teamSpawnPoints.size())));
+            unsigned int index = 0;
+            for (SpawnPoint* teamSpawnPoint : teamSpawnPoints)
+            {
+                if (index == randomspawn)
+                    return teamSpawnPoint;
+
+                ++index;
+            }
+        }
+
+        return nullptr;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Dynamicmatch.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Dynamicmatch.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Dynamicmatch.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Dynamicmatch_H__
+#define _Dynamicmatch_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "tools/Timer.h"
+
+#include "Gametype.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Short Gaming Manual:
+        There are three different parties a player can belong to: victim, chaser or killer
+        Every player starts as chaser. As long as there are not enough victims and killers, you can change your and other player's parties by shooting them.
+        In order to win you have to earn as much points as possible:
+        - as victim by escaping the chasers
+        - as chaser by shooting the victim
+        - as killer by killing the chasers
+
+
+        What you shouldn't do is shooting at players of your own party. By doing so your score will decrease.
+        P.S: If you don't want to be a victim: Get rid of your part by shooting a chaser.
+
+        @todo:
+        pig punkte vergeben pro Zeit!
+        killerfarbe schwarz; evtl. eigenes Raumfahrzeug;
+        Low; Codeoptimierung und Dokumentation
+    */
+    class _OrxonoxExport Dynamicmatch : public Gametype
+    {
+        public:
+            Dynamicmatch(Context* context);
+            virtual ~Dynamicmatch();
+
+            bool notEnoughPigs;
+            bool notEnoughKillers;
+            bool notEnoughChasers;
+
+            //three different parties
+            int chaser;
+            int piggy;
+            int killer;
+
+            virtual void evaluatePlayerParties();
+            int getParty(PlayerInfo* player);
+            void setPlayerColour(PlayerInfo* player);//own function
+            void setConfigValues();//done
+
+            bool friendlyfire; //goal: player can switch it on/off
+            bool tutorial; //goal: new players receive messages how the new gametype works - later it can be switched off.
+
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator = nullptr) override; //ok - score function and management of parties
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr) override; //ok - simple
+            virtual void start() override;
+            virtual void end() override; //Wie geht das mit der Punkteausgabe aendern? Z.B: Persoenliche Nachricht?
+            virtual void playerEntered(PlayerInfo* player) override;
+            virtual void playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) override;//is used to initialize the player's party and colour
+            virtual bool playerLeft(PlayerInfo* player) override;
+            virtual bool playerChangedName(PlayerInfo* player) override;//unchanged
+
+            /*virtual void instructions();
+            virtual void furtherInstructions();*/
+            virtual void rewardPig();
+            void grantPigBoost(SpaceShip* spaceship); // Grant the piggy a boost.
+            void resetSpeedFactor(SpaceShip* spaceship, Timer* timer);
+            virtual void tick (float dt) override;// used to end the game
+            virtual SpawnPoint* getBestSpawnPoint(PlayerInfo* player) const override;
+
+
+        protected:
+            inline unsigned int getPlayerCount() const
+                 { return this->numberOf[chaser] + numberOf[piggy] + this->numberOf[killer]; }
+
+            std::map< PlayerInfo*, int > playerParty_; //player's parties are recorded here
+            std::vector<ColourValue> partyColours_; //aus TeamDeathmatch
+            std::set<Timer*> piggyTimers_;
+            unsigned int numberOf[3]; //array to count number of chasers, pigs, killers
+            float pointsPerTime;
+            float gameTime_;   // from UnderAttack
+            bool gameEnded_; // true if game is over
+            int timesequence_; //used for countdown
+            //Timer callInstructions_;
+    };
+}
+
+#endif /* _Dynamicmatch_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Gametype.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Gametype.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Gametype.cc	(revision 11817)
@@ -0,0 +1,602 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Gametype.h"
+
+#include "util/Math.h"
+#include "core/Core.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "gamestates/GSLevel.h"
+
+#include "infos/PlayerInfo.h"
+#include "infos/Bot.h"
+#include "graphics/Camera.h"
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/SpawnPoint.h"
+#include "worldentities/pawns/Spectator.h"
+#include "worldentities/pawns/Pawn.h"
+#include "overlays/OverlayGroup.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    static const std::string __CC_addBots_name  = "addBots";
+    static const std::string __CC_killBots_name = "killBots";
+
+    SetConsoleCommand("Gametype", __CC_addBots_name,  &Gametype::addBots ).addShortcut().defaultValues(1);
+    SetConsoleCommand("Gametype", __CC_killBots_name, &Gametype::killBots).addShortcut().defaultValues(0);
+
+    RegisterUnloadableClass(Gametype);
+
+    Gametype::Gametype(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Gametype);
+
+        this->setGametype(WeakPtr<Gametype>(this)); // store a weak-pointer to itself (a strong-pointer would create a recursive dependency)
+
+        this->gtinfo_ = new GametypeInfo(context);
+
+        this->defaultControllableEntity_ = Class(Spectator);
+        this->scoreboard_ = nullptr;
+
+        this->bAutoStart_ = false;
+        this->bForceSpawn_ = false;
+        this->bAutoEnd_ = true;
+        this->numberOfBots_ = 0;
+
+        this->timeLimit_ = 0;
+        this->time_ = 0;
+        this->timerIsActive_ = false;
+
+        this->initialStartCountdown_ = 3;
+
+        this->setConfigValues();
+
+        ModifyConsoleCommand(__CC_addBots_name).setObject(this);
+        ModifyConsoleCommand(__CC_killBots_name).setObject(this);
+    }
+
+    Gametype::~Gametype()
+    {
+        if (this->isInitialized())
+        {
+            if (this->gtinfo_)
+                this->gtinfo_->destroy();
+
+            ModifyConsoleCommand(__CC_addBots_name).setObject(nullptr);
+            ModifyConsoleCommand(__CC_killBots_name).setObject(nullptr);
+        }
+    }
+    
+    /**
+     * @brief Initializes sub-objects of the Gametype. This must be called after the constructor.
+     * At this point, the context is expected to have the current gametype. This allows to pass the current gametype to the sub-objects via constructor.
+     */
+    void Gametype::init()
+    {
+        // load the corresponding score board
+        if (GameMode::showsGraphics() && !this->scoreboardTemplate_.empty())
+        {
+            this->scoreboard_ = new OverlayGroup(this->getContext());
+            this->scoreboard_->addTemplate(this->scoreboardTemplate_);
+        }
+    }
+
+    void Gametype::setConfigValues()
+    {
+        SetConfigValue(initialStartCountdown_, 3.0f);
+        SetConfigValue(bAutoStart_, false);
+        SetConfigValue(bForceSpawn_, false);
+        SetConfigValue(bAutoEnd_, true);
+        SetConfigValue(numberOfBots_, 0);
+        SetConfigValue(scoreboardTemplate_, "defaultScoreboard");
+    }
+
+    void Gametype::tick(float dt)
+    {
+        SUPER(Gametype, tick, dt);
+
+        //count timer
+        if (timerIsActive_)
+        {
+            if (this->timeLimit_ == 0)
+                this->time_ += dt;
+            else
+                this->time_ -= dt;
+        }
+
+        if (this->gtinfo_->isStartCountdownRunning() && !this->gtinfo_->hasStarted())
+            this->gtinfo_->countdownStartCountdown(dt);
+
+        if (!this->gtinfo_->hasStarted())
+        {
+            for (const auto& mapEntry : this->players_)
+            {
+                // Inform the GametypeInfo that the player is ready to spawn.
+                if(mapEntry.first->isHumanPlayer() && mapEntry.first->isReadyToSpawn())
+                    this->gtinfo_->playerReadyToSpawn(mapEntry.first);
+            }
+
+            this->checkStart();
+        }
+        else if (!this->gtinfo_->hasEnded())
+            this->spawnDeadPlayersIfRequested();
+
+        this->assignDefaultPawnsIfNeeded();
+    }
+
+    void Gametype::start()
+    {
+        this->addBots(this->numberOfBots_);
+        this->gtinfo_->start();
+        this->spawnPlayersIfRequested();
+    }
+
+    void Gametype::end()
+    {
+        this->gtinfo_->end();
+        if (this->bAutoEnd_)
+        {
+            this->showMenuTimer_.setTimer(3.0f, true, createExecutor(createFunctor(&Gametype::showMenu, this)));
+        }
+
+        for (const auto& mapEntry : this->players_)
+        {
+            if (mapEntry.first->getControllableEntity())
+            {
+                ControllableEntity* oldentity = mapEntry.first->getControllableEntity();
+
+                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(oldentity->getContext());
+                if (oldentity->getCamera())
+                {
+                    entity->setPosition(oldentity->getCamera()->getWorldPosition());
+                    entity->setOrientation(oldentity->getCamera()->getWorldOrientation());
+                }
+                else
+                {
+                    entity->setPosition(oldentity->getWorldPosition());
+                    entity->setOrientation(oldentity->getWorldOrientation());
+                }
+                mapEntry.first->startControl(entity);
+            }
+            else
+                this->spawnPlayerAsDefaultPawn(mapEntry.first);
+        }
+    }
+
+    void Gametype::playerEntered(PlayerInfo* player)
+    {
+        this->players_[player].state_ = PlayerState::Joined;
+        this->gtinfo_->playerEntered(player);
+    }
+
+    bool Gametype::playerLeft(PlayerInfo* player)
+    {
+        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+        {
+            this->players_.erase(it);
+            return true;
+        }
+        return false;
+    }
+
+    void Gametype::playerSwitched(PlayerInfo* player, Gametype* newgametype)
+    {
+    }
+
+    void Gametype::playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype)
+    {
+    }
+
+    bool Gametype::playerChangedName(PlayerInfo* player)
+    {
+        if (this->players_.find(player) != this->players_.end())
+        {
+            if (player->getName() != player->getOldName())
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    void Gametype::pawnPreSpawn(Pawn* pawn)
+    {
+    }
+
+    void Gametype::pawnPostSpawn(Pawn* pawn)
+    {
+    }
+
+    void Gametype::playerPreSpawn(PlayerInfo* player)
+    {
+    }
+
+    void Gametype::playerPostSpawn(PlayerInfo* player)
+    {
+    }
+
+    void Gametype::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
+    {
+    }
+
+    void Gametype::playerStopsControllingPawn(PlayerInfo* player, Pawn* pawn)
+    {
+    }
+
+    bool Gametype::allowPawnHit(Pawn* victim, Pawn* originator)
+    {
+        return true;
+    }
+
+    bool Gametype::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        return true;
+    }
+
+    bool Gametype::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        return true;
+    }
+
+    void Gametype::pawnKilled(Pawn* victim, Pawn* killer)
+    {
+        if (victim && victim->getPlayer())
+        {
+            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(victim->getPlayer());
+            if (it != this->players_.end())
+            {
+                it->second.state_ = PlayerState::Dead;
+                it->second.killed_++;
+
+                // Reward killer
+                if (killer && killer->getPlayer())
+                {
+                    std::map<PlayerInfo*, Player>::iterator it = this->players_.find(killer->getPlayer());
+                    if (it != this->players_.end())
+                    {
+                        it->second.frags_++;
+
+                        if (killer->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
+                            this->gtinfo_->sendKillMessage("You killed " + victim->getPlayer()->getName(), killer->getPlayer()->getClientID());
+                        if (victim->getPlayer()->getClientID() != NETWORK_PEER_ID_UNKNOWN)
+                            this->gtinfo_->sendDeathMessage("You were killed by " + killer->getPlayer()->getName(), victim->getPlayer()->getClientID());
+                    }
+                }
+
+                if(victim->getPlayer()->isHumanPlayer())
+                    this->gtinfo_->pawnKilled(victim->getPlayer());
+
+                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(victim->getContext());
+                if (victim->getCamera())
+                {
+                    entity->setPosition(victim->getCamera()->getWorldPosition());
+                    entity->setOrientation(victim->getCamera()->getWorldOrientation());
+                }
+                else
+                {
+                    entity->setPosition(victim->getWorldPosition());
+                    entity->setOrientation(victim->getWorldOrientation());
+                }
+                it->first->startControl(entity);
+            }
+            else
+                orxout(internal_warning) << "Killed Pawn was not in the playerlist" << endl;
+        }
+    }
+
+    void Gametype::playerScored(PlayerInfo* player, int score)
+    {
+        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+            it->second.frags_ += score;
+    }
+
+    int Gametype::getScore(PlayerInfo* player) const
+    {
+        std::map<PlayerInfo*, Player>::const_iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+            return it->second.frags_;
+        else
+            return 0;
+    }
+
+    SpawnPoint* Gametype::getBestSpawnPoint(PlayerInfo* player) const
+    {
+        // If there is at least one SpawnPoint.
+        if (this->spawnpoints_.size() > 0)
+        {
+            // Fallback spawn point if there is no active one, choose a random one.
+            SpawnPoint* fallbackSpawnPoint = nullptr;
+            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(this->spawnpoints_.size())));
+            unsigned int index = 0;
+            std::vector<SpawnPoint*> activeSpawnPoints;
+            for (SpawnPoint* spawnpoint : this->spawnpoints_)
+            {
+                if (index == randomspawn)
+                    fallbackSpawnPoint = spawnpoint;
+
+                if (spawnpoint != nullptr && spawnpoint->isActive())
+                    activeSpawnPoints.push_back(spawnpoint);
+
+                ++index;
+            }
+
+            if(activeSpawnPoints.size() > 0)
+            {
+                randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(activeSpawnPoints.size())));
+                return activeSpawnPoints[randomspawn];
+            }
+
+            orxout(internal_warning) << "Fallback SpawnPoint was used because there were no active SpawnPoints." << endl;
+            return fallbackSpawnPoint;
+        }
+        return nullptr;
+    }
+
+    void Gametype::assignDefaultPawnsIfNeeded()
+    {
+        for (auto& mapEntry : this->players_)
+        {
+            if (!mapEntry.first->getControllableEntity())
+            {
+                mapEntry.second.state_ = PlayerState::Dead;
+
+                if (!mapEntry.first->isReadyToSpawn() || !this->gtinfo_->hasStarted())
+                {
+                    this->spawnPlayerAsDefaultPawn(mapEntry.first);
+                    mapEntry.second.state_ = PlayerState::Dead;
+                }
+            }
+        }
+    }
+
+    void Gametype::checkStart()
+    {
+        if (!this->gtinfo_->hasStarted())
+        {
+            if (this->gtinfo_->isStartCountdownRunning())
+            {
+                if (this->gtinfo_->getStartCountdown() <= 0.0f)
+                {
+                    this->gtinfo_->stopStartCountdown();
+                    this->gtinfo_->setStartCountdown(0.0f);
+                    this->start();
+                }
+            }
+            else if (this->players_.size() > 0)
+            {
+                if (this->bAutoStart_)
+                {
+                    this->start();
+                }
+                else
+                {
+                    bool allplayersready = true;
+                    bool hashumanplayers = false;
+                    for (const auto& mapEntry : this->players_)
+                    {
+                        if (!mapEntry.first->isReadyToSpawn())
+                            allplayersready = false;
+                        if (mapEntry.first->isHumanPlayer())
+                            hashumanplayers = true;
+                    }
+
+                    if (allplayersready && hashumanplayers)
+                    {
+                        // If in developer's mode, there is no start countdown.
+                        if(Core::getInstance().getConfig()->inDevMode())
+                            this->start();
+                        else
+                        {
+                            this->gtinfo_->setStartCountdown(this->initialStartCountdown_);
+                            this->gtinfo_->startStartCountdown();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    void Gametype::spawnPlayersIfRequested()
+    {
+        for (const auto& mapEntry : this->players_)
+        {
+            if (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_)
+                this->spawnPlayer(mapEntry.first);
+        }
+    }
+
+    void Gametype::spawnDeadPlayersIfRequested()
+    {
+        for (const auto& mapEntry : this->players_)
+            if (mapEntry.second.state_ == PlayerState::Dead)
+                if (mapEntry.first->isReadyToSpawn() || this->bForceSpawn_)
+                    this->spawnPlayer(mapEntry.first);
+    }
+
+    void Gametype::spawnPlayer(PlayerInfo* player)
+    {
+        SpawnPoint* spawnpoint = this->getBestSpawnPoint(player);
+        if (spawnpoint)
+        {
+            this->playerPreSpawn(player);
+            player->startControl(spawnpoint->spawn());
+            this->players_[player].state_ = PlayerState::Alive;
+
+            if(player->isHumanPlayer())
+                this->gtinfo_->playerSpawned(player);
+
+            this->playerPostSpawn(player);
+        }
+        else
+        {
+            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
+            abort();
+        }
+    }
+
+    void Gametype::spawnPlayerAsDefaultPawn(PlayerInfo* player)
+    {
+        SpawnPoint* spawn = this->getBestSpawnPoint(player);
+        if (spawn)
+        {
+            // force spawn at spawnpoint with default pawn
+            ControllableEntity* entity = this->defaultControllableEntity_.fabricate(spawn->getContext());
+            spawn->spawn(entity);
+            player->startControl(entity);
+        }
+        else
+        {
+            orxout(user_error) << "No SpawnPoints in current Gametype" << endl;
+            abort();
+        }
+    }
+
+    void Gametype::addBots(unsigned int amount)
+    {
+        for (unsigned int i = 0; i < amount; ++i)
+            this->botclass_.fabricate(this->getContext());
+    }
+
+    void Gametype::killBots(unsigned int amount)
+    {
+        unsigned int i = 0;
+        ObjectList<Bot> list;
+        for (ObjectList<Bot>::iterator it = list.begin(); (it != list.end()) && ((amount == 0) || (i < amount)); )
+        {
+            if (it->getGametype() == this)
+            {
+                (it++)->destroy();
+                ++i;
+            }
+            else
+                ++it;
+        }
+    }
+
+    void Gametype::addTime(float t)
+    {
+        if (this->timeLimit_ == 0)
+          this->time_ -= t;
+        else
+          this->time_ += t;
+    }
+
+    void Gametype::removeTime(float t)
+    {
+        if (this->timeLimit_ == 0)
+          this->time_ += t;
+        else
+          this->time_ -= t;
+    }
+
+    void Gametype::resetTimer()
+    {
+        this->resetTimer(timeLimit_);
+    }
+
+    void Gametype::resetTimer(float t)
+    {
+        this->timeLimit_ = t;
+        this->time_ = t;
+    }
+
+    void Gametype::showMenu()
+    {
+        GSLevel::startMainMenu();
+    }
+
+    GSLevelMementoState* Gametype::exportMementoState()
+    {
+        for (const auto& mapEntry : this->players_)
+        {
+            if (mapEntry.first->isHumanPlayer() && mapEntry.first->getControllableEntity() && mapEntry.first->getControllableEntity()->getCamera())
+            {
+                Camera* camera = mapEntry.first->getControllableEntity()->getCamera();
+
+                GametypeMementoState* state = new GametypeMementoState();
+                state->cameraPosition_ = camera->getWorldPosition();
+                state->cameraOrientation_ = camera->getWorldOrientation();
+                state->sceneName_ = camera->getScene()->getName();
+                return state;
+            }
+        }
+
+        return nullptr;
+    }
+
+    void Gametype::importMementoState(const std::vector<GSLevelMementoState*>& states)
+    {
+        // find correct memento state
+        GametypeMementoState* state = nullptr;
+        for (GSLevelMementoState* temp : states)
+        {
+            state = dynamic_cast<GametypeMementoState*>(temp);
+            if (state)
+                break;
+        }
+
+        if (!state)
+            return;
+
+        // find correct scene
+        Scene* scene = nullptr;
+        for (Scene* someScene : ObjectList<Scene>())
+        {
+            if (someScene->getName() == state->sceneName_)
+            {
+                scene = someScene;
+                break;
+            }
+        }
+
+        if (!scene)
+        {
+            orxout(internal_warning) << "Could not find scene with name " << state->sceneName_ << endl;
+            return;
+        }
+
+        // find correct player and assign default entity with original position & orientation
+        for (const auto& mapEntry : this->players_)
+        {
+            if (mapEntry.first->isHumanPlayer())
+            {
+                ControllableEntity* entity = this->defaultControllableEntity_.fabricate(scene->getContext());
+                entity->setPosition(state->cameraPosition_);
+                entity->setOrientation(state->cameraOrientation_);
+                mapEntry.first->startControl(entity);
+                break;
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Gametype.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Gametype.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Gametype.h	(revision 11817)
@@ -0,0 +1,214 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Gametype_H__
+#define _Gametype_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "core/BaseObject.h"
+#include "core/class/SubclassIdentifier.h"
+#include "tools/interfaces/Tickable.h"
+#include "infos/GametypeInfo.h"
+#include "tools/Timer.h"
+#include "gamestates/GSLevelMemento.h"
+
+namespace orxonox
+{
+    enum class PlayerState
+    {
+        Uninitialized,
+        Joined,
+        Alive,
+        Dead
+    };
+
+    struct Player
+    {
+        PlayerInfo* info_;
+        PlayerState state_;
+        int frags_;
+        int killed_;
+    };
+
+    class _OrxonoxExport Gametype : public BaseObject, public Tickable, public GSLevelMemento
+    {
+        friend class PlayerInfo;
+
+        public:
+            Gametype(Context* context);
+            virtual ~Gametype();
+
+            virtual void init();
+
+            void setConfigValues();
+
+            virtual void tick(float dt) override;
+
+            inline const GametypeInfo* getGametypeInfo() const
+                { return this->gtinfo_; }
+
+            inline bool hasStarted() const
+                { return this->gtinfo_->hasStarted(); }
+            inline bool hasEnded() const
+                { return this->gtinfo_->hasEnded(); }
+
+            virtual void start();
+            virtual void end();
+            virtual void playerEntered(PlayerInfo* player);
+            virtual bool playerLeft(PlayerInfo* player);
+            virtual void playerSwitched(PlayerInfo* player, Gametype* newgametype);
+            virtual void playerSwitchedBack(PlayerInfo* player, Gametype* oldgametype);
+            virtual bool playerChangedName(PlayerInfo* player);
+
+            virtual void playerScored(PlayerInfo* player, int score = 1);
+
+            virtual bool allowPawnHit(Pawn* victim, Pawn* originator = nullptr);
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator = nullptr);
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr);
+
+            virtual void pawnKilled(Pawn* victim, Pawn* killer = nullptr);
+            virtual void pawnPreSpawn(Pawn* pawn);
+            virtual void pawnPostSpawn(Pawn* pawn);
+            virtual void playerPreSpawn(PlayerInfo* player);
+            virtual void playerPostSpawn(PlayerInfo* player);
+
+            virtual void playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn);
+            virtual void playerStopsControllingPawn(PlayerInfo* player, Pawn* pawn);
+
+            inline const std::map<PlayerInfo*, Player>& getPlayers() const
+                { return this->players_; }
+
+            int getScore(PlayerInfo* player) const;
+
+            inline void registerSpawnPoint(SpawnPoint* spawnpoint)
+                { this->spawnpoints_.insert(spawnpoint); }
+
+            inline bool isStartCountdownRunning() const
+                { return this->gtinfo_->isStartCountdownRunning(); }
+            inline float getStartCountdown() const
+                { return this->gtinfo_->getStartCountdown(); }
+
+            inline void setHUDTemplate(const std::string& name)
+                { this->gtinfo_->setHUDTemplate(name); }
+            inline const std::string& getHUDTemplate() const
+                { return this->gtinfo_->getHUDTemplate(); }
+
+            virtual void addBots(unsigned int amount);
+            void killBots(unsigned int amount = 0);
+
+            virtual void addTime(float t);
+            virtual void removeTime(float t);
+
+            inline  void startTimer()
+            {
+                this->time_ = this->timeLimit_;
+                this->timerIsActive_ = true;
+            }
+
+            inline void stopTimer()
+              { this->timerIsActive_ = false; }
+
+            inline float getTime()
+              { return this->time_; }
+
+            inline bool getTimerIsActive()
+              { return timerIsActive_; }
+
+            inline void setTimeLimit(float t)
+              { this->timeLimit_ = t; }
+
+            //inline bool getForceSpawn()
+            //  { return this->bForceSpawn_; }
+
+            virtual void resetTimer();
+            virtual void resetTimer(float t);
+
+            /**
+            @brief Get number of Players in game.
+            */
+            inline unsigned int getNumberOfPlayers() const
+                { return this->players_.size(); }
+            void showMenu();
+
+
+        protected:
+            virtual SpawnPoint* getBestSpawnPoint(PlayerInfo* player) const;
+
+            virtual void assignDefaultPawnsIfNeeded();
+            virtual void checkStart();
+            virtual void spawnPlayer(PlayerInfo* player);
+            virtual void spawnPlayerAsDefaultPawn(PlayerInfo* player);
+            virtual void spawnPlayersIfRequested();
+            virtual void spawnDeadPlayersIfRequested();
+
+            virtual GSLevelMementoState* exportMementoState() override;
+            virtual void importMementoState(const std::vector<GSLevelMementoState*>& states) override;
+
+            WeakPtr<GametypeInfo> gtinfo_;
+
+            bool bAutoStart_;
+            bool bForceSpawn_;
+            bool bAutoEnd_;
+
+            float time_;
+            float timeLimit_;
+            bool timerIsActive_;
+
+            float initialStartCountdown_;
+            unsigned int numberOfBots_;
+            SubclassIdentifier<Bot> botclass_;
+
+            std::map<PlayerInfo*, Player> players_;
+            std::set<SpawnPoint*> spawnpoints_;
+            SubclassIdentifier<ControllableEntity> defaultControllableEntity_;
+
+            OverlayGroup* scoreboard_;
+
+            // Config Values
+            std::string scoreboardTemplate_;
+
+            Timer showMenuTimer_;
+    };
+
+    /**
+        @brief Keeps position and orientation of the camera, as well as the name of current scene.
+    */
+    struct _OrxonoxExport GametypeMementoState : public GSLevelMementoState
+    {
+        Vector3 cameraPosition_;
+        Quaternion cameraOrientation_;
+        std::string sceneName_;
+    };
+}
+
+#endif /* _Gametype_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastManStanding.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastManStanding.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastManStanding.cc	(revision 11817)
@@ -0,0 +1,279 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LastManStanding.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(LastManStanding);
+
+    LastManStanding::LastManStanding(Context* context) : Deathmatch(context)
+    {
+        RegisterObject(LastManStanding);
+        this->bForceSpawn_=true;
+        this->lives=4;
+        this->playersAlive=0;
+        this->timeRemaining=15.0f;
+        this->respawnDelay=4.0f;
+        this->bNoPunishment=false;
+        this->bHardPunishment=false;
+        this->punishDamageRate=0.4f;
+        this->setHUDTemplate("LastmanstandingHUD");
+    }
+
+    void LastManStanding::spawnDeadPlayersIfRequested()
+    {
+        for (const auto& mapEntry : this->players_)
+            if (mapEntry.second.state_ == PlayerState::Dead)
+            {
+                bool alive = (0<playerLives_[mapEntry.first]&&(inGame_[mapEntry.first]));
+                if (alive&&(mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                {
+                    this->spawnPlayer(mapEntry.first);
+                }
+            }
+    }
+
+
+    void LastManStanding::setConfigValues()
+    {
+        SetConfigValue(lives, 4);
+        SetConfigValue(timeRemaining, 15.0f);
+        SetConfigValue(respawnDelay, 4.0f);
+        SetConfigValue(bNoPunishment, false);
+        SetConfigValue(bHardPunishment, false);
+    }
+
+    bool LastManStanding::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        if (originator && originator->getPlayer())// only for safety
+        {
+            this->timeToAct_[originator->getPlayer()]=timeRemaining;
+
+            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
+            if (it != this->players_.end())
+            {
+                if (it->first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                    return true;
+                const std::string message = ""; // resets Camper-Warning-message
+                this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
+            }
+        }
+        return true;
+    }
+
+    bool LastManStanding::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        if (!victim||!victim->getPlayer())// only for safety
+            return true;
+        playerLives_[victim->getPlayer()]=playerLives_[victim->getPlayer()]-1;
+        this->inGame_[victim->getPlayer()]=false;//if player dies he, isn't allowed to respawn immediately
+        if (playerLives_[victim->getPlayer()]<=0)//if player lost all lives
+        {
+            this->playersAlive--;
+            const std::string& message = victim->getPlayer()->getName() + " has lost all lives";
+            ChatManager::message(message);
+        }
+
+        return true;
+    }
+
+    int LastManStanding::getMinLives()
+    {
+        int min=lives;
+        for (const auto& mapEntry : this->playerLives_)
+        {
+            if (mapEntry.second<=0)
+                continue;
+            if (mapEntry.second<lives)
+                min=mapEntry.second;
+        }
+        return min;
+    }
+
+    void LastManStanding::end()
+    {
+        Gametype::end();
+
+        for (const auto& mapEntry : this->playerLives_)
+        {
+            if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                continue;
+
+            if (mapEntry.second > 0)
+                this->gtinfo_->sendAnnounceMessage("You have won the match!", mapEntry.first->getClientID());
+            else
+                this->gtinfo_->sendAnnounceMessage("You have lost the match!", mapEntry.first->getClientID());
+        }
+    }
+
+    int LastManStanding::playerGetLives(PlayerInfo* player)
+    {
+        if (player)
+            return  playerLives_[player];
+        else
+            return 0;
+    }
+
+    int LastManStanding::getNumPlayersAlive() const
+    {
+        return this->playersAlive;
+    }
+
+    void LastManStanding::playerEntered(PlayerInfo* player)
+    {
+        if (!player)// only for safety
+            return;
+        Deathmatch::playerEntered(player);
+        if (playersAlive<=1)
+            playerLives_[player]=lives;
+        else
+            playerLives_[player]=getMinLives();//new players only get minimum of lives
+        this->playersAlive++;
+        this->timeToAct_[player]=timeRemaining;
+        this->playerDelayTime_[player]=respawnDelay;
+        this->inGame_[player]=true;
+    }
+
+    bool LastManStanding::playerLeft(PlayerInfo* player)
+    {
+        bool valid_player = Deathmatch::playerLeft(player);
+        if (valid_player)
+        {
+            this->playersAlive--;
+            this->playerLives_.erase (player);
+            this->playerDelayTime_.erase (player);
+            this->inGame_.erase (player);
+            this->timeToAct_.erase(player);
+        }
+
+        return valid_player;
+    }
+
+    void LastManStanding::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
+    {
+        if (!player)
+            return;
+        this->timeToAct_[player]=timeRemaining+3.0f+respawnDelay;//reset timer
+        this->playerDelayTime_[player]=respawnDelay;
+
+        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+        {
+            if (it->first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                return;
+            const std::string message = ""; // resets Camper-Warning-message
+            this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
+        }
+    }
+
+    void LastManStanding::punishPlayer(PlayerInfo* player)
+    {
+        if(!player)
+            return;
+        if(bNoPunishment)
+            return;
+        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+        {
+            if(!player->getControllableEntity())
+                return;
+            Pawn* pawn = orxonox_cast<Pawn*>(player->getControllableEntity());
+            if(!pawn)
+                return;
+            if(bHardPunishment)
+            {
+                pawn->kill();
+                this->timeToAct_[player]=timeRemaining+3.0f+respawnDelay;//reset timer
+            }
+            else
+            {
+                float damage=pawn->getMaxHealth()*punishDamageRate*0.5f;//TODO: Factor 0.5 is hard coded. Where is the ratio between MaxHealth actually defined?
+                pawn->removeHealth(damage);
+                this->timeToAct_[player]=timeRemaining;//reset timer
+            }
+        }
+    }
+
+    void LastManStanding::tick(float dt)
+    {
+        SUPER(LastManStanding, tick, dt);
+        if(this->hasStarted()&&(!this->hasEnded()))
+        {
+            if ((this->hasStarted()&&(playersAlive<=1)))//last player remaining
+            {
+                this->end();
+            }
+            for (auto& mapEntry : this->timeToAct_)
+            {
+                if (playerGetLives(mapEntry.first)<=0)//Players without lives shouldn't be affected by time.
+                    continue;
+                mapEntry.second-=dt;//Decreases punishment time.
+                if (!inGame_[mapEntry.first])//Manages respawn delay - player is forced to respawn after the delaytime is used up.
+                {
+                    playerDelayTime_[mapEntry.first]-=dt;
+                    if (playerDelayTime_[mapEntry.first]<=0)
+                    this->inGame_[mapEntry.first]=true;
+
+                    if (mapEntry.first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    int output=1+(int)playerDelayTime_[mapEntry.first];
+                    const std::string& message = "Respawn in " +multi_cast<std::string>(output)+ " seconds." ;//Countdown
+                    this->gtinfo_->sendFadingMessage(message,mapEntry.first->getClientID());
+                }
+                else if (mapEntry.second<0.0f)
+                {
+                    mapEntry.second=timeRemaining+3.0f;//reset punishment-timer
+                    if (playerGetLives(mapEntry.first)>0)
+                    {
+                        this->punishPlayer(mapEntry.first);
+                        if (mapEntry.first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                            return;
+                        const std::string message = ""; // resets Camper-Warning-message
+                        this->gtinfo_->sendFadingMessage(message,mapEntry.first->getClientID());
+                    }
+                }
+                else if (mapEntry.second<timeRemaining/5)//Warning message
+                {
+                    if (mapEntry.first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    const std::string message = "Camper Warning! Don't forget to shoot.";
+                    this->gtinfo_->sendFadingMessage(message,mapEntry.first->getClientID());
+                }
+            }
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastManStanding.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastManStanding.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastManStanding.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+/**
+    @file LastManStanding.h
+    @brief Declaration of the Gametype "Last Man Standing".
+*/
+
+#ifndef _LastManStanding_H__
+#define _LastManStanding_H__
+
+#include "OrxonoxPrereqs.h"
+#include "Deathmatch.h"
+#include <map>
+#include <vector>
+
+namespace orxonox
+{
+    class _OrxonoxExport LastManStanding : public Deathmatch
+    {
+    /**
+    @brief
+        Last Man Standing is a gametype where each player fights against each other, until one player remains. 
+    @author
+        Johannes Ritz
+    */
+        protected:
+            int lives; //!< Standard amount of lives. Each player starts a game with so many lives.
+            std::map< PlayerInfo*, int > playerLives_; //!< Each player's lives are stored here.
+            int playersAlive; //!< Counter counting players with more than 0 lives.
+            float timeRemaining; //!< Each player has a certain time where he or she has to hit an opponent or will be punished.
+            std::map<PlayerInfo*, float> timeToAct_; //!< Each player's time till she/he will be punished is stored here.
+            float respawnDelay; //!<Time in seconds when a player will respawn after death.
+            std::map<PlayerInfo*, float> playerDelayTime_; //!< Stores each Player's delay time.
+            std::map<PlayerInfo*, bool> inGame_; //!< Indicates each Player's state.
+            bool bNoPunishment; //!< Config value to switch off Punishment function if it is set to true.
+            bool bHardPunishment; //!< Switches between damage and death as punishment.
+            float punishDamageRate; //!< Makes Damage adjustable.
+            virtual void spawnDeadPlayersIfRequested() override; //!< Prevents dead players to respawn.
+            virtual int getMinLives(); //!< Returns minimum of each player's lives; players with 0 lives are skipped; 
+
+        public:
+            LastManStanding(Context* context); //!< Default Constructor.
+            virtual ~LastManStanding() {} //!< Default Destructor.
+            void setConfigValues(); //!< Makes values configurable.
+
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator = nullptr) override; //!< If a player shoot's an opponent, his punishment countdown will be resetted.
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr) override; //!< Manages each players lives.
+
+            virtual void end() override; //!< Sends an end message.
+            int playerGetLives(PlayerInfo* player); //!< getFunction for the map "playerLives_".
+            int getNumPlayersAlive() const; //!< Returns the number of players that are still alive.
+            virtual void playerEntered(PlayerInfo* player) override; //!< Initializes values.
+            virtual bool playerLeft(PlayerInfo* player) override; //!< Manages all local variables.
+            virtual void playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) override; //!< Resets punishment time and respawn delay.
+
+            void punishPlayer(PlayerInfo* player); //!< Function in order to kill a player. Punishment for hiding longer than "timeRemaining".
+            virtual void tick (float dt) override; //!< used to end the game
+    };
+}
+
+#endif /* _LastManStanding_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastTeamStanding.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastTeamStanding.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastTeamStanding.cc	(revision 11817)
@@ -0,0 +1,311 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "LastTeamStanding.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "util/Convert.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(LastTeamStanding);
+
+    LastTeamStanding::LastTeamStanding(Context* context) : TeamDeathmatch(context)
+    {
+        RegisterObject(LastTeamStanding);
+        this->bForceSpawn_ = true;
+        this->lives = 4;
+        this->eachTeamsPlayers.resize(teams_,0);
+        this->teamsAlive = 0;
+        this->bNoPunishment = false;
+        this->bHardPunishment = false;
+        this->punishDamageRate = 0.4f;
+        this->timeRemaining = 15.0f;
+        this->respawnDelay = 4.0f;
+        this->setHUDTemplate("lastTeamStandingHUD");
+    }
+
+    LastTeamStanding::~LastTeamStanding()
+    {
+    }
+
+    void LastTeamStanding::playerEntered(PlayerInfo* player)
+    {
+        if (!player)// only for safety
+            return;
+        TeamDeathmatch::playerEntered(player);
+        if (teamsAlive<=1)
+            playerLives_[player]=lives;
+        else
+            playerLives_[player]=getMinLives();//new players only get minimum of lives */
+
+        this->timeToAct_[player] = timeRemaining;
+        this->playerDelayTime_[player] = respawnDelay;
+        this->inGame_[player] = true;
+        unsigned int team = getTeam(player);
+        if(team >= eachTeamsPlayers.size()) // make sure getTeam returns a regular value
+            return;
+        if(this->eachTeamsPlayers[team]==0) //if a player is the first in his group, a new team is alive
+            this->teamsAlive++;
+        this->eachTeamsPlayers[team]++; //the number of player in this team is increased
+    }
+
+    bool LastTeamStanding::playerLeft(PlayerInfo* player)
+    {
+        bool valid_player = TeamDeathmatch::playerLeft(player);
+        if (valid_player)
+        {
+            this->playerLives_.erase(player);
+            this->timeToAct_.erase(player);
+            this->playerDelayTime_.erase(player);
+            this->inGame_.erase(player);
+            unsigned int team = getTeam(player);
+            if(team >= eachTeamsPlayers.size()) // make sure getTeam returns a regular value
+                return valid_player;
+            this->eachTeamsPlayers[team]--;       // a player left the team
+            if(this->eachTeamsPlayers[team] == 0) // if it was the last player a team died
+                this->teamsAlive--;
+        }
+
+        return valid_player;
+    }
+
+    bool LastTeamStanding::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        if (!victim||!victim->getPlayer())// only for safety
+            return true;
+        bool allow = TeamDeathmatch::allowPawnDeath(victim, originator);
+        if(!allow) {return allow;}
+
+        playerLives_[victim->getPlayer()] = playerLives_[victim->getPlayer()] - 1; //player lost a live
+        this->inGame_[victim->getPlayer()] = false; //if player dies, he isn't allowed to respawn immediately
+        if (playerLives_[victim->getPlayer()]<=0) //if player lost all lives
+        {
+            unsigned int team = getTeam(victim->getPlayer());
+            if(team >= eachTeamsPlayers.size()) // make sure getTeam returns a regular value
+                return allow;
+            this->eachTeamsPlayers[team]--;
+            if(eachTeamsPlayers[team] == 0) //last team member died
+                this->teamsAlive--;
+            const std::string& message = victim->getPlayer()->getName() + " has lost all lives";
+            ChatManager::message(message);
+        }
+        return allow;
+    }
+
+    bool LastTeamStanding::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        bool allow = TeamDeathmatch::allowPawnDamage(victim, originator);
+        if(!allow) {return allow;}
+        if (originator && originator->getPlayer())// only for safety
+        {
+            this->timeToAct_[originator->getPlayer()] = timeRemaining;
+
+            std::map<PlayerInfo*, Player>::iterator it = this->players_.find(originator->getPlayer());
+            if (it != this->players_.end())
+            {
+                if (it->first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                    return true;
+                const std::string message = ""; // resets Camper-Warning-message
+                this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
+            }
+        }
+        return allow;
+    }
+
+    void LastTeamStanding::spawnDeadPlayersIfRequested()
+    {
+        for (const auto& mapEntry : this->players_)
+            if (mapEntry.second.state_ == PlayerState::Dead)
+            {
+                bool alive = (0 < playerLives_[mapEntry.first]&&(inGame_[mapEntry.first]));
+                if (alive&&(mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                {
+                    this->spawnPlayer(mapEntry.first);
+                }
+            }
+    }
+
+    void LastTeamStanding::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
+    {
+        if (!player)
+            return;
+        TeamDeathmatch::playerStartsControllingPawn(player,pawn);
+
+        this->timeToAct_[player] = timeRemaining + 3.0f + respawnDelay;//reset timer
+        this->playerDelayTime_[player] = respawnDelay;
+
+        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+        {
+            if (it->first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                return;
+            const std::string message = ""; // resets Camper-Warning-message
+            this->gtinfo_->sendFadingMessage(message,it->first->getClientID());
+        }
+    }
+
+    void LastTeamStanding::tick(float dt)
+    {
+        SUPER(LastTeamStanding, tick, dt);
+        if(this->hasStarted()&&(!this->hasEnded()))
+        {
+            if ( this->hasStarted()&&(teamsAlive<=1) )//last team remaining -> game will end
+            {
+                this->end();
+            }
+            for (auto& mapEntry : this->timeToAct_)
+            {
+                if (playerGetLives(mapEntry.first) <= 0)//Players without lives shouldn't be affected by time.
+                    continue;
+                mapEntry.second -= dt;//Decreases punishment time.
+                if (!inGame_[mapEntry.first])//Manages respawn delay - player is forced to respawn after the delaytime is used up.
+                {
+                    playerDelayTime_[mapEntry.first] -= dt;
+                    if (playerDelayTime_[mapEntry.first] <= 0)
+                    this->inGame_[mapEntry.first] = true;
+
+                    if (mapEntry.first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    int output = 1 + (int)playerDelayTime_[mapEntry.first];
+                    const std::string& message = "Respawn in " +multi_cast<std::string>(output)+ " seconds." ;//Countdown
+                    this->gtinfo_->sendFadingMessage(message,mapEntry.first->getClientID());
+                }
+                else if (mapEntry.second < 0.0f)
+                {
+                    mapEntry.second = timeRemaining + 3.0f;//reset punishment-timer
+                    if (playerGetLives(mapEntry.first) > 0)
+                    {
+                        this->punishPlayer(mapEntry.first);
+                        if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                            return;
+                        const std::string message = ""; // resets Camper-Warning-message
+                        this->gtinfo_->sendFadingMessage(message, mapEntry.first->getClientID());
+                    }
+                }
+                else if (mapEntry.second < timeRemaining/5)//Warning message
+                {
+                  if (mapEntry.first->getClientID()== NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+                    const std::string message = "Camper Warning! Don't forget to shoot.";
+                    this->gtinfo_->sendFadingMessage(message, mapEntry.first->getClientID());
+                }
+            }
+        }
+    }
+
+    void LastTeamStanding::end()//TODO: Send the message to the whole team
+    {
+        Gametype::end();
+        int party = -1;
+        //find a player who survived
+        for (const auto& mapEntry : this->playerLives_)
+        {
+          if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                continue;
+
+            if (mapEntry.second > 0)//a player that is alive
+            {
+                //which party has survived?
+                std::map<PlayerInfo*, int>::iterator it2 = this->teamnumbers_.find(mapEntry.first);
+                if (it2 != this->teamnumbers_.end())
+                {
+                    party = it2->second;
+                }
+                if (party < 0) return; //if search failed
+                //victory message to all team members, loose message to everyone else
+                this->announceTeamWin(party);
+
+                return;
+            }
+        }
+    }
+
+
+    int LastTeamStanding::getMinLives()
+    {
+        int min = lives;
+        for (const auto& mapEntry : this->playerLives_)
+        {
+            if (mapEntry.second <= 0)
+                continue;
+            if (mapEntry.second < lives)
+                min = mapEntry.second;
+        }
+        return min;
+    }
+
+    void LastTeamStanding::punishPlayer(PlayerInfo* player)
+    {
+        if(!player)
+            return;
+        if(bNoPunishment)
+            return;
+        std::map<PlayerInfo*, Player>::iterator it = this->players_.find(player);
+        if (it != this->players_.end())
+        {
+            if(!player->getControllableEntity())
+                return;
+            Pawn* pawn = orxonox_cast<Pawn*>(player->getControllableEntity());
+            if(!pawn)
+                return;
+            if(bHardPunishment)
+            {
+                pawn->kill();
+                this->timeToAct_[player] = timeRemaining + 3.0f + respawnDelay;//reset timer
+            }
+            else
+            {
+                float damage = pawn->getMaxHealth()*punishDamageRate*0.5f;//TODO: Factor 0.5 is hard coded. Where is the ratio between MaxHealth actually defined?
+                pawn->removeHealth(damage);
+                this->timeToAct_[player] = timeRemaining;//reset timer
+            }
+        }
+    }
+
+    int LastTeamStanding::playerGetLives(PlayerInfo* player)
+    {
+        if (player)
+            return  playerLives_[player];
+        else
+            return 0;
+    }
+
+    void LastTeamStanding::setConfigValues()
+    {
+        SetConfigValue(lives, 4);
+        SetConfigValue(timeRemaining, 15.0f);
+        SetConfigValue(respawnDelay, 4.0f);
+        SetConfigValue(bNoPunishment, false);
+        SetConfigValue(bHardPunishment, false);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastTeamStanding.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastTeamStanding.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/LastTeamStanding.h	(revision 11817)
@@ -0,0 +1,93 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+/**
+    @file LastTeamStanding.h
+    @brief Declaration of the Gametype "Last Team Standing".
+*/
+
+#ifndef _LastTeamStanding_H__
+#define _LastTeamStanding_H__
+
+#include "OrxonoxPrereqs.h"
+#include "TeamDeathmatch.h"
+#include <map>
+#include <vector>
+
+//TODO: Hud doesn load; problem with destructor; teams are not assigned properly; 
+
+namespace orxonox
+{
+    class _OrxonoxExport LastTeamStanding : public TeamDeathmatch
+    {
+    /**
+    @brief
+        Last Team Standing is a gametype where each team fights against each other, until one team remains. 
+    @author
+        Johannes Ritz
+    */
+        protected:
+            int lives; //!< Standard amount of lives. Each player starts a game with so many lives.
+            std::map< PlayerInfo*, int > playerLives_; //!< Each player's lives are stored here.
+            std::vector<int> eachTeamsPlayers; //!<Number of players in each team.
+            int teamsAlive; //!< Counter counting teams with more than one player remaining.
+//Data for CamperPunishment
+            float timeRemaining; //!< Each player has a certain time where he or she has to hit an opponent or will be punished.
+            std::map<PlayerInfo*, float> timeToAct_; //!< Each player's time till she/he will be punished is stored here.
+            bool bNoPunishment; //!< Config value to switch off Punishment function if it is set to true.
+            bool bHardPunishment; //!< Switches between damage and death as punishment.
+            float punishDamageRate; //!< Makes Damage adjustable.
+//Data for RespawnDelay
+            float respawnDelay; //!<Time in seconds when a player will respawn after death.
+            std::map<PlayerInfo*, float> playerDelayTime_; //!< Stores each Player's delay time.
+            std::map<PlayerInfo*, bool> inGame_; //!< Indicates each Player's state.
+
+            virtual void spawnDeadPlayersIfRequested() override; //!< Prevents dead players to respawn.
+            virtual int getMinLives(); //!< Returns minimum of each player's lives; players with 0 lives are skipped;
+
+        public:
+            LastTeamStanding(Context* context); //!< Default Constructor.
+            virtual ~LastTeamStanding(); //!< Default Destructor.
+
+            virtual void playerEntered(PlayerInfo* player) override; //!< Initializes values.
+            virtual bool playerLeft(PlayerInfo* player) override; //!< Manages all local variables.
+
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr) override; //!< Manages each player's lost lives.
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator = nullptr) override; //!< If a player shoot's an opponent, his punishment countdown will be resetted.
+            virtual void playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) override; //!< Resets punishment time and respawn delay.
+            virtual void tick (float dt) override; //!< used to end the game
+            virtual void end() override; //!< Sends an end message.
+            void punishPlayer(PlayerInfo* player); //!< Function in order to kill a player. Punishment for hiding longer than "timeRemaining".
+            int playerGetLives(PlayerInfo* player); //!< getFunction for the map "playerLives_".
+            inline int getNumTeamsAlive() const//!< Returns the number of players that are still alive.
+            {return this->teamsAlive;}
+            void setConfigValues(); //!< Makes values configurable.
+
+    };
+}
+
+#endif /* _LastTeamStanding_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Mission.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Mission.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Mission.cc	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Mission.h"
+
+#include "items/Engine.h"
+#include "controllers/ArtificialController.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "infos/PlayerInfo.h"
+#include "network/Host.h"
+#include "worldentities/pawns/Pawn.h"
+#include "LevelManager.h"
+
+namespace orxonox
+{
+    SetConsoleCommand("Mission", "endMission", &Mission::endMission);
+    SetConsoleCommand("Mission", "setLives", &Mission::setLivesWrapper);
+    RegisterUnloadableClass(Mission);
+
+    Mission::Mission(Context* context) : TeamGametype(context)
+    {
+        RegisterObject(Mission);
+        this->missionAccomplished_ = false;
+        this->lives_ = 10; // should be 1 as default value
+        this->numberOfBots_ = 0; //sets number of default bots temporarly to 0
+    }
+
+    void Mission::tick(float dt)
+    {
+        SUPER(Mission, tick, dt);
+
+        if (missionAccomplished_)
+        {
+            this->gtinfo_->sendAnnounceMessage("Mission accomplished!");
+            this->end();
+        }
+        else if (this->lives_ == 0)
+        {
+            this->missionAccomplished_ = false;
+            this->end();
+        }
+    }
+
+    void Mission::pawnKilled(Pawn* victim, Pawn* killer)
+    {
+        if (victim && victim->getPlayer() && victim->getPlayer()->isHumanPlayer())
+        {
+            this->lives_--;
+        }
+    }
+
+    void Mission::start()
+    {
+        Gametype::start();
+        this->setTeams();
+
+        this->gtinfo_->sendAnnounceMessage("Your mission has started!");
+    }
+
+    void Mission::end()
+    {
+        if (this->missionAccomplished_ && !this->gtinfo_->hasEnded())
+        {
+            this->gtinfo_->sendAnnounceMessage("Mission accomplished!");
+
+            LevelManager::getInstance().setLastFinishedCampaignMission(this->getFilename());
+        }
+        else if (!this->gtinfo_->hasEnded())
+            this->gtinfo_->sendAnnounceMessage("Mission failed!");
+
+        Gametype::end();
+    }
+
+    void Mission::setTeams()
+    { //Set pawn-colours
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if (!pawn)
+                continue;
+            this->setDefaultObjectColour(pawn);
+        }
+    }
+    void Mission::endMission(bool accomplished)
+    {
+        for (Mission* mission : ObjectList<Mission>())
+        { //TODO: make sure that only the desired mission is ended !! This is a dirty HACK, that would end ALL missions!
+            mission->setMissionAccomplished(accomplished);
+            mission->end();
+        }
+    }
+
+    void Mission::setLivesWrapper(unsigned int amount)
+    {
+        for (Mission* mission : ObjectList<Mission>())
+        { //TODO: make sure that only the desired mission is ended !! This is a dirty HACK, that would affect ALL missions!
+            mission->setLives(amount);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/Mission.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/Mission.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/Mission.h	(revision 11817)
@@ -0,0 +1,68 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Mission_H__
+#define _Mission_H__
+
+#include "OrxonoxPrereqs.h"
+//#include "Gametype.h"
+#include "TeamGametype.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Mission : public TeamGametype
+    {
+        public:
+            Mission(Context* context);
+            virtual ~Mission() {}
+
+            virtual void tick(float dt) override;
+
+            virtual void start() override;
+            virtual void end() override;
+            virtual void setTeams();
+            virtual void addBots(unsigned int amount) override{} //<! overwrite function in order to bypass the addbots command
+            inline void setLives(unsigned int amount)
+                {this->lives_ = amount;}
+            inline unsigned int getLives()
+                {return this->lives_;}
+            inline void setMissionAccomplished(bool acc)
+                {this->missionAccomplished_ = acc;}
+            static void endMission(bool accomplished);
+            static void setLivesWrapper(unsigned int amount);
+
+        protected:
+            virtual void pawnKilled(Pawn* victim, Pawn* killer = nullptr) override;
+            bool missionAccomplished_; //<! indicates if player successfully finsihed the mission;
+            int lives_; //<! amount of player's lives <-> nr. of retries
+            //<! If the lives_ are set negative -> unlimited lives.
+    };
+}
+
+#endif /* _Mission_H__ */
+
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/StoryMode.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/StoryMode.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/StoryMode.cc	(revision 11817)
@@ -0,0 +1,100 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Marvin Haeberle & Julian Huwyler
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "StoryMode.h"
+
+#include "items/Engine.h"
+#include "controllers/ArtificialController.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "infos/PlayerInfo.h"
+#include "network/Host.h"
+#include "worldentities/pawns/Pawn.h"
+#include "LevelManager.h"
+
+namespace orxonox
+{
+
+    SetConsoleCommand("StoryMode", "exit", &StoryMode::exit);
+    RegisterUnloadableClass(StoryMode);
+    
+    StoryMode::StoryMode(Context* context) : Gametype(context)
+    {
+        RegisterObject(StoryMode);
+
+        this->gtinfo_ = new GametypeInfo(context);
+        this->bAutoStart_ = true;
+        this->bForceSpawn_ = true;
+    }
+
+    
+  /* 
+    void StoryMode::start()
+    {
+        Gametype::start();
+
+        this->gtinfo_->sendAnnounceMessage("Marvin isch Chef");
+    }
+*/
+    void StoryMode::exit()
+    {
+        orxout() << "s funktioniert"<< endl;
+        for (StoryMode* mission : ObjectList<StoryMode>())
+        { //TODO: make sure that only the desired mission is ended !! This is a dirty HACK, that would end ALL missions!
+            mission->end();
+        }
+        //Gametype::end();
+    }
+/*
+    void Mission::setTeams()
+    { //Set pawn-colours
+        for (Pawn* pawn : ObjectList<Pawn>())
+        {
+            if (!pawn)
+                continue;
+            this->setDefaultObjectColour(pawn);
+        }
+    }
+    void Mission::endMission(bool accomplished)
+    {
+        for (Mission* mission : ObjectList<Mission>())
+        { //TODO: make sure that only the desired mission is ended !! This is a dirty HACK, that would end ALL missions!
+            mission->setMissionAccomplished(accomplished);
+            mission->end();
+        }
+    }
+
+    void Mission::setLivesWrapper(unsigned int amount)
+    {
+        for (Mission* mission : ObjectList<Mission>())
+        { //TODO: make sure that only the desired mission is ended !! This is a dirty HACK, that would affect ALL missions!
+            mission->setLives(amount);
+        }
+    }*/
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/StoryMode.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/StoryMode.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/StoryMode.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Julian Huwyler & Marvin Haeberle
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Mission_H__
+#define _Mission_H__
+
+#include "OrxonoxPrereqs.h"
+#include "Gametype.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport StoryMode : public Gametype
+    {
+        public:
+            StoryMode(Context* context);
+            virtual ~StoryMode() {}
+            static void exit();
+
+            
+    };
+}
+
+#endif /* _Mission_H__ */
+
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamBaseMatch.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamBaseMatch.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamBaseMatch.cc	(revision 11817)
@@ -0,0 +1,271 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Val Mikos
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TeamBaseMatch.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "worldentities/pawns/TeamBaseMatchBase.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(TeamBaseMatch);
+
+    TeamBaseMatch::TeamBaseMatch(Context* context) : TeamDeathmatch(context)
+    {
+        RegisterObject(TeamBaseMatch);
+
+        this->scoreTimer_.setTimer(10, true, createExecutor(createFunctor(&TeamBaseMatch::winPoints, this)));
+        this->outputTimer_.setTimer(10, true, createExecutor(createFunctor(&TeamBaseMatch::showPoints, this)));
+
+        this->pointsTeam1_ = 0;
+        this->pointsTeam2_ = 0;
+
+        this->setHUDTemplate("TeamBaseMatchHUD");
+    }
+
+    // Change the control of the defeated base and respawn it with its initial health
+    bool TeamBaseMatch::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        TeamBaseMatchBase* base = orxonox_cast<TeamBaseMatchBase*>(victim);
+        if (base)
+        {
+            if (!originator)
+                return false;
+
+            std::set<TeamBaseMatchBase*>::const_iterator it = this->bases_.find(base);
+            if (it != this->bases_.end())
+            {
+                int teamnr = this->getTeam(originator->getPlayer());
+                if (teamnr == 0)
+                {
+                    base->setState(BaseState::ControlTeam1);
+                    this->gtinfo_->sendAnnounceMessage("The red team captured a base");
+                }
+                if (teamnr == 1)
+                {
+                    base->setState(BaseState::ControlTeam2);
+                    this->gtinfo_->sendAnnounceMessage("The blue team captured a base");
+                }
+            }
+
+            victim->setHealth(victim->getInitialHealth());
+            return false;
+        }
+
+        return TeamDeathmatch::allowPawnDeath(victim, originator);
+    }
+
+
+    // if the player is in the same team as the base, he can't make any damage to it
+    bool TeamBaseMatch::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        TeamBaseMatchBase* base = orxonox_cast<TeamBaseMatchBase*>(victim);
+        if (base)
+        {
+            std::set<TeamBaseMatchBase*>::const_iterator it = this->bases_.find(base);
+            if (it != this->bases_.end())
+                return (!this->pawnsAreInTheSameTeam(originator, base));
+        }
+        return TeamDeathmatch::allowPawnDamage(victim, originator);
+    }
+
+    bool TeamBaseMatch::pawnsAreInTheSameTeam(Pawn* pawn1, TeamBaseMatchBase* base)
+    {
+        if (pawn1 && base)
+        {
+            int teamnrbase = -1;
+            int teamnrplayer = this->getTeam(pawn1->getPlayer());
+
+            switch (base->getState())
+            {
+                case BaseState::ControlTeam1:
+                    teamnrbase = 0;
+                    break;
+                case BaseState::ControlTeam2:
+                    teamnrbase = 1;
+                    break;
+                case BaseState::Uncontrolled:
+                default:
+                    teamnrbase = -1;
+            }
+
+            if (teamnrbase == teamnrplayer)
+                return true;
+        }
+        return false;
+    }
+
+
+
+
+
+    // collect Points for killing oppenents
+    void TeamBaseMatch::playerScored(PlayerInfo* player, int score)
+    {
+        int teamnr = this->getTeam(player);
+        this->addTeamPoints(teamnr, 5);
+    }
+
+    // show points or each interval of time
+    void TeamBaseMatch::showPoints()
+    {
+        if (!this->hasStarted() || this->hasEnded())
+            return;
+
+        orxout(message) << "Points standing:" << '\n' << "Team 1: "<< pointsTeam1_ << '\n' << "Team 2: " << pointsTeam2_ << endl;
+        if(pointsTeam1_ >=1700 && pointsTeam1_ < 2000) orxout(message) << "Team 1 is near victory!" << endl;
+        if(pointsTeam2_ >=1700 && pointsTeam2_ < 2000) orxout(message) << "Team 2 is near victory!" << endl;
+    }
+
+
+    // collect Points while controlling Bases
+    void TeamBaseMatch::winPoints()
+    {
+        int amountControlled = 0;
+        int amountControlled2 = 0;
+
+        for (TeamBaseMatchBase* base : this->bases_)
+        {
+            if(base->getState() == BaseState::ControlTeam1)
+            {
+                amountControlled++;
+            }
+            if(base->getState() == BaseState::ControlTeam2)
+            {
+                amountControlled2++;
+            }
+        }
+
+        this->addTeamPoints(0, (amountControlled * 30));
+        this->addTeamPoints(1, (amountControlled2 * 30));
+    }
+
+
+    // end game if one team reaches 2000 points
+    void TeamBaseMatch::endGame()
+    {
+        if (this->pointsTeam1_ >= 2000 || this->pointsTeam2_ >= 2000)
+        {
+            int winningteam = -1;
+
+            if (this->pointsTeam1_ > this->pointsTeam2_)
+            {
+                orxout(message) << "Team 1 has won the match" << endl;
+                winningteam = 0;
+            }
+            else
+            {
+                orxout(message) << "Team 2 has won the match" << endl;
+                winningteam = 1;
+            }
+
+            for (const auto& mapEntry : this->teamnumbers_)
+            {
+                if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                    continue;
+
+                if (mapEntry.second == winningteam)
+                    this->gtinfo_->sendAnnounceMessage("You have won the match!", mapEntry.first->getClientID());
+                else
+                    this->gtinfo_->sendAnnounceMessage("You have lost the match!", mapEntry.first->getClientID());
+            }
+
+            this->end();
+            this->scoreTimer_.stopTimer();
+            this->outputTimer_.stopTimer();
+        }
+    }
+
+
+    // this function is called by the function winPoints() which adds points to the teams for every base and killed openents at a certain time
+    void TeamBaseMatch::addTeamPoints(int team, int points)
+    {
+        if(team == 0)
+        {
+            this->pointsTeam1_ += points;
+        }
+        if(team == 1)
+        {
+            this->pointsTeam2_ += points;
+        }
+
+        this->endGame();
+    }
+
+    int TeamBaseMatch::getTeamPoints(int team)
+    {
+        if(team == 0)
+        {
+            return this->pointsTeam1_;
+        }
+        if(team == 1)
+        {
+            return this->pointsTeam2_;
+        }
+
+        return 0;
+    }
+
+    int TeamBaseMatch::getTeamBases(int team)
+    {
+        int count = 0;
+
+        for (TeamBaseMatchBase* base : this->bases_)
+        {
+            if (base->getState() == BaseState::ControlTeam1 && team == 0)
+                count++;
+            if (base->getState() == BaseState::ControlTeam2 && team == 1)
+                count++;
+        }
+
+        return count;
+    }
+
+    void TeamBaseMatch::addBase(TeamBaseMatchBase* base)
+    {
+        this->bases_.insert(base);
+        base->setState(BaseState::Uncontrolled);
+    }
+
+    TeamBaseMatchBase* TeamBaseMatch::getBase(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (TeamBaseMatchBase* base : this->bases_)
+        {
+            i++;
+            if (i > index)
+                return base;
+        }
+        return nullptr;
+    }
+
+}
+
+
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamBaseMatch.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamBaseMatch.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamBaseMatch.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Val Mikos
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamBaseMatch_H__
+#define _TeamBaseMatch_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <set>
+#include "tools/Timer.h"
+#include "TeamDeathmatch.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport TeamBaseMatch : public TeamDeathmatch
+    {
+        public:
+            TeamBaseMatch(Context* context);
+            virtual ~TeamBaseMatch() {}
+
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr) override;
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator) override;
+
+            virtual void playerScored(PlayerInfo* player, int score = 1) override;
+            virtual void showPoints();
+            virtual void endGame();
+
+            void addBase(TeamBaseMatchBase* base);
+            TeamBaseMatchBase* getBase(unsigned int index) const;
+
+            void addTeamPoints(int team, int points);
+            int getTeamPoints(int team);
+            int getTeamBases(int team);
+
+        protected:
+            void winPoints();
+
+            bool pawnsAreInTheSameTeam(Pawn* pawn1, TeamBaseMatchBase* base);
+            using TeamDeathmatch::pawnsAreInTheSameTeam;
+
+            std::set<TeamBaseMatchBase*> bases_;
+            Timer scoreTimer_;
+            Timer outputTimer_;
+
+            //points for each team
+            int pointsTeam1_;
+            int pointsTeam2_;
+    };
+}
+
+#endif /* _TeamBaseMatch_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamDeathmatch.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamDeathmatch.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamDeathmatch.cc	(revision 11817)
@@ -0,0 +1,153 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TeamDeathmatch.h"
+
+#include "core/CoreIncludes.h"
+#include "chat/ChatManager.h"
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+#include "core/config/ConfigValueIncludes.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(TeamDeathmatch);
+
+    TeamDeathmatch::TeamDeathmatch(Context* context) : TeamGametype(context)
+    {
+        RegisterObject(TeamDeathmatch);
+
+        this->setConfigValues();
+    }
+
+    void TeamDeathmatch::setConfigValues()
+    {
+        SetConfigValue(maxScore_, 10);
+    }
+
+    void TeamDeathmatch::start()
+    {
+        TeamGametype::start();
+
+        std::string message("The match has started!");
+        ChatManager::message(message);
+    }
+
+    void TeamDeathmatch::end()
+    {
+        TeamGametype::end();
+
+        std::string message("The match has ended.");
+        ChatManager::message(message);
+        
+        //find team that won the match
+        int winnerTeam = 0;
+        int highestScore = 0;
+        for (const auto& mapEntry : this->players_)
+        {
+            if ( this->getTeamScore(mapEntry.first) > highestScore )
+            {
+                winnerTeam = this->getTeam(mapEntry.first);
+                highestScore = this->getTeamScore(mapEntry.first);
+            }
+        }
+
+        //announce win
+        this->announceTeamWin(winnerTeam);
+    }
+
+    void TeamDeathmatch::playerEntered(PlayerInfo* player)
+    {
+        TeamGametype::playerEntered(player);
+
+        const std::string& message = player->getName() + " entered the game";
+        ChatManager::message(message);
+    }
+
+    bool TeamDeathmatch::playerLeft(PlayerInfo* player)
+    {
+        bool valid_player = TeamGametype::playerLeft(player);
+
+        if (valid_player)
+        {
+            const std::string& message = player->getName() + " left the game";
+            ChatManager::message(message);
+        }
+
+        return valid_player;
+    }
+    bool TeamDeathmatch::playerChangedName(PlayerInfo* player)
+    {
+        bool valid_player = TeamGametype::playerChangedName(player);
+
+        if (valid_player)
+        {
+            const std::string& message = player->getOldName() + " changed name to " + player->getName();
+            ChatManager::message(message);
+        }
+
+        return valid_player;
+    }
+
+    void TeamDeathmatch::pawnKilled(Pawn* victim, Pawn* killer)
+    {
+        if (victim && victim->getPlayer())
+        {
+            std::string message;
+            if (killer)
+            {
+                if (killer->getPlayer())
+                {
+                    message = victim->getPlayer()->getName() + " was killed by " + killer->getPlayer()->getName();
+                    if(this->isExactlyA(Class(TeamDeathmatch)) && (this->getTeamScore(killer->getPlayer()) >= (this->maxScore_ -1)) )
+                        this->end();
+                }
+                else
+                    message = victim->getPlayer()->getName() + " was killed";
+            }
+            else
+                message = victim->getPlayer()->getName() + " died";
+
+            ChatManager::message(message);
+        }
+
+        Gametype::pawnKilled(victim, killer);
+    }
+
+    void TeamDeathmatch::playerScored(PlayerInfo* player, int score)
+    {
+        TeamGametype::playerScored(player, score);
+
+        if (player)
+        {
+            const std::string& message = player->getName() + " scores!";
+            ChatManager::message(message);
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamDeathmatch.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamDeathmatch.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamDeathmatch.h	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamDeathmatch_H__
+#define _TeamDeathmatch_H__
+
+#include "OrxonoxPrereqs.h"
+#include "TeamGametype.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport TeamDeathmatch : public TeamGametype
+    {
+        public:
+            TeamDeathmatch(Context* context);
+            virtual ~TeamDeathmatch() {}
+
+            void setConfigValues();
+            virtual void start() override;
+            virtual void end() override;
+            virtual void playerEntered(PlayerInfo* player) override;
+            virtual bool playerLeft(PlayerInfo* player) override;
+            virtual bool playerChangedName(PlayerInfo* player) override;
+
+            virtual void pawnKilled(Pawn* victim, Pawn* killer = nullptr) override;
+            virtual void playerScored(PlayerInfo* player, int score = 1) override;
+       protected:
+            int maxScore_; 
+    };
+}
+
+#endif /* _TeamDeathmatch_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamGametype.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamGametype.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamGametype.cc	(revision 11817)
@@ -0,0 +1,393 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TeamGametype.h"
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "infos/PlayerInfo.h"
+#include "interfaces/TeamColourable.h"
+#include "worldentities/TeamSpawnPoint.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/ControllableEntity.h"
+#include "controllers/ArtificialController.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(TeamGametype);
+
+    TeamGametype::TeamGametype(Context* context) : Gametype(context)
+    {
+        RegisterObject(TeamGametype);
+
+        this->teams_ = 2; //most team gametypes use two different teams
+        this->allowFriendlyFire_ = false;
+        //this->playersPerTeam_ = 0;
+        this->maxPlayers_ = 0; //Value "0": no limit is set.
+        this->setConfigValues();
+    }
+
+    void TeamGametype::setConfigValues()
+    {
+        SetConfigValue(teams_, 2);
+
+        static ColourValue colours[] =
+        {
+            ColourValue(0.2f, 0.2f, 1.0f),
+            ColourValue(1.0f, 0.1f, 0.1f),
+            ColourValue(0.3f, 1.0f, 0.3f),
+            ColourValue(1.0f, 1.0f, 0.0f),
+            ColourValue(0.0f, 1.0f, 1.0f),
+            ColourValue(1.0f, 0.0f, 1.0f),
+            ColourValue(7.0f, 7.0f, 7.0f),
+            ColourValue(2.0f, 2.0f, 2.0f)
+        };
+        static std::vector<ColourValue> defaultcolours(colours, colours + sizeof(colours) / sizeof(ColourValue));
+
+        SetConfigValue(teamcolours_, defaultcolours);
+    }
+
+    void TeamGametype::playerEntered(PlayerInfo* player)
+    {
+        if(player == nullptr) return; // catch null pointers
+        Gametype::playerEntered(player);
+        this->findAndSetTeam(player);
+        if( this->players_.size() <= maxPlayers_ || maxPlayers_  ==  0)
+        {
+            this->allowedInGame_[player]= true;
+        }
+        else
+        {
+            this->allowedInGame_[player]= false;
+            orxout() << "not allowed in game: players = " << this->players_.size() << " > maximum: " << maxPlayers_ << endl;
+        }
+    }
+
+    /**
+    @brief
+        Function that determines the player's team number when entering the game for the first time.
+        Override this function for other team structures.
+    */
+    void TeamGametype::findAndSetTeam(PlayerInfo* player)
+    {
+        if(player == nullptr) return; // catch null pointers
+        std::vector<unsigned int> playersperteam(this->teams_, 0);
+
+        for (const auto& mapEntry : this->teamnumbers_)
+            if (mapEntry.second < static_cast<int>(this->teams_) && mapEntry.second >= 0)
+                playersperteam[mapEntry.second]++;
+
+        unsigned int minplayers = static_cast<unsigned int>(-1);
+        size_t minplayersteam = 0;
+        for (size_t i = 0; i < this->teams_; ++i)
+        {
+            if (playersperteam[i] < minplayers)
+            {
+                minplayers = playersperteam[i];
+                minplayersteam = i;
+            }
+        }
+
+        this->teamnumbers_[player] = minplayersteam;
+
+    }
+
+    bool TeamGametype::playerLeft(PlayerInfo* player)
+    {
+        bool valid_player = Gametype::playerLeft(player);
+        if( (this->players_.size() >= maxPlayers_) && (allowedInGame_[player] == true) ) // if there's a "waiting list"
+        {
+            for (auto& mapEntry : this->allowedInGame_)
+            {
+                 if(mapEntry.second == false) // waiting player found
+                 {mapEntry.second = true; break;} // allow player to enter
+            }
+        }
+
+        if (valid_player)
+        {   // clean up the maps
+            this->teamnumbers_.erase(player);
+            this->allowedInGame_.erase(player);
+        }
+
+        return valid_player;
+    }
+
+    void TeamGametype::spawnDeadPlayersIfRequested()
+    {
+        for (const auto& mapEntry : this->players_)
+        {
+            if(allowedInGame_[mapEntry.first] == false)//check if dead player is allowed to enter
+            {
+                continue;
+            }
+            if (mapEntry.second.state_ == PlayerState::Dead)
+            {
+                if ((mapEntry.first->isReadyToSpawn() || this->bForceSpawn_))
+                {
+                   this->spawnPlayer(mapEntry.first);
+                }
+            }
+        }
+    }
+
+
+    bool TeamGametype::allowPawnHit(Pawn* victim, Pawn* originator)
+    {// hit allowed: if victim & originator are foes or if originator doesnot exist or if friendlyfire is allowed
+        return (!this->pawnsAreInTheSameTeam(victim, originator) || !originator || this->allowFriendlyFire_);
+    }
+
+    bool TeamGametype::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        return (!this->pawnsAreInTheSameTeam(victim, originator) || !originator || this->allowFriendlyFire_);
+    }
+
+    bool TeamGametype::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        return (!this->pawnsAreInTheSameTeam(victim, originator) || !originator || this->allowFriendlyFire_);
+    }
+
+    int TeamGametype::getTeamScore(PlayerInfo* player)
+    {
+        int teamscore = 0;
+        if(!player || this->getTeam(player) == -1)
+            return 0;
+        for (const auto& mapEntry : this->players_)
+        {
+            if ( this->getTeam(mapEntry.first) ==  this->getTeam(player) )
+            {
+                teamscore += mapEntry.second.frags_;
+            }
+        }
+        return teamscore;
+    }
+
+    int TeamGametype::getTeamSize(int team)
+    {
+        int teamSize = 0;
+        for (const auto& mapEntry : this->teamnumbers_)
+        {
+            if (mapEntry.second == team)
+                teamSize++;
+        }
+        return teamSize;
+    }
+
+    int TeamGametype::getHumansInTeam(int team)
+    {
+        int teamSize = 0;
+        for (const auto& mapEntry : this->teamnumbers_)
+        {
+            if (mapEntry.second == team  && mapEntry.first->isHumanPlayer())
+                teamSize++;
+        }
+        return teamSize;
+    }
+
+
+    SpawnPoint* TeamGametype::getBestSpawnPoint(PlayerInfo* player) const
+    {
+        int desiredTeamNr = -1;
+        std::map<PlayerInfo*, int>::const_iterator it_player = this->teamnumbers_.find(player);
+        if (it_player != this->teamnumbers_.end())
+            desiredTeamNr = it_player->second;
+
+        // Only use spawnpoints of the own team (or non-team-spawnpoints)
+        std::set<SpawnPoint*> teamSpawnPoints = this->spawnpoints_;
+        for (std::set<SpawnPoint*>::iterator it = teamSpawnPoints.begin(); it != teamSpawnPoints.end(); )
+        {
+            if ((*it)->isA(Class(TeamSpawnPoint)))
+            {
+                TeamSpawnPoint* tsp = orxonox_cast<TeamSpawnPoint*>(*it);
+                if (tsp && static_cast<int>(tsp->getTeamNumber()) != desiredTeamNr)
+                {
+                    teamSpawnPoints.erase(it++);
+                    continue;
+                }
+            }
+
+            ++it;
+        }
+
+        SpawnPoint* fallbackSpawnPoint = nullptr;
+        if (teamSpawnPoints.size() > 0)
+        {
+            unsigned int randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(teamSpawnPoints.size())));
+            unsigned int index = 0;
+            // Get random fallback spawnpoint in case there is no active SpawnPoint.
+            for (SpawnPoint* teamSpawnPoint : teamSpawnPoints)
+            {
+                if (index == randomspawn)
+                {
+                    fallbackSpawnPoint = teamSpawnPoint;
+                    break;
+                }
+
+                ++index;
+            }
+
+            // Remove all inactive SpawnPoints from the list.
+            for (std::set<SpawnPoint*>::iterator it = teamSpawnPoints.begin(); it != teamSpawnPoints.end(); )
+            {
+                if(!(*it)->isActive())
+                {
+                    teamSpawnPoints.erase(it++);
+                    continue;
+                }
+
+                ++it;
+            }
+
+            randomspawn = static_cast<unsigned int>(rnd(static_cast<float>(teamSpawnPoints.size())));
+            index = 0;
+            for (SpawnPoint* teamSpawnPoint : teamSpawnPoints)
+            {
+                if (index == randomspawn)
+                    return teamSpawnPoint;
+
+                ++index;
+            }
+
+            return fallbackSpawnPoint;
+        }
+
+        return nullptr;
+    }
+
+    void TeamGametype::playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn)
+    {
+        if (!player)
+            return;
+
+        this->setTeamColour(player,pawn);
+    }
+
+    bool TeamGametype::pawnsAreInTheSameTeam(Pawn* pawn1, Pawn* pawn2)
+    {
+        if (pawn1 && pawn2)
+        {
+            std::map<PlayerInfo*, int>::const_iterator it1 = this->teamnumbers_.find(pawn1->getPlayer());
+            std::map<PlayerInfo*, int>::const_iterator it2 = this->teamnumbers_.find(pawn2->getPlayer());
+
+            if (it1 != this->teamnumbers_.end() && it2 != this->teamnumbers_.end())
+                return (it1->second == it2->second);
+        }
+        return false;
+    }
+
+    int TeamGametype::getTeam(PlayerInfo* player)
+    {
+        std::map<PlayerInfo*, int>::const_iterator it_player = this->teamnumbers_.find(player);
+        if (it_player != this->teamnumbers_.end())
+            return it_player->second;
+        else
+            return -1;
+    }
+
+    void TeamGametype::setTeamColour(PlayerInfo* player, Pawn* pawn)
+    {
+        // Set the team colour
+        std::map<PlayerInfo*, int>::const_iterator it_player = this->teamnumbers_.find(player);
+        if (it_player != this->teamnumbers_.end() && it_player->second >= 0 && it_player->second < static_cast<int>(this->teamcolours_.size()))
+        {
+            this->colourPawn(pawn, it_player->second);
+        }
+    }
+
+    /**
+    @brief
+        Colours a pawn depending on the team values set in XML.
+        A pawn is coloured depending on it's team set via XML.
+        If there is a controller the pawn is coloured depending on its team which also can be set via XML.
+    */
+    void TeamGametype::setDefaultObjectColour(Pawn* pawn)
+    {
+        if(pawn == nullptr)
+            return;
+
+        int teamnumber = pawn->getTeam();
+
+        if(teamnumber >= 0)
+        {
+            this->colourPawn(pawn, teamnumber); return;
+        }
+        //get Pawn's controller
+        ControllableEntity* entity = orxonox_cast<ControllableEntity*>(pawn);
+
+        Controller* controller = nullptr;
+        if (entity->getController())
+            controller = entity->getController();
+        else if (entity->getXMLController())
+            controller = entity->getXMLController();
+        else
+            return;
+
+        ArtificialController* artificial =  orxonox_cast<ArtificialController*>(controller);
+        //get Teamnumber - get the data
+        if(artificial == nullptr)
+            return;
+        teamnumber= artificial->getTeam();
+
+        //set ObjectColour
+        this->colourPawn(pawn, teamnumber);
+    }
+
+    void TeamGametype::colourPawn(Pawn* pawn, int teamNr)
+    {// catch: no-colouring-case and wrong input
+        if(teamNr < 0 || teamNr+1 > int(this->teamcolours_.size()) ||pawn == nullptr) return;
+        pawn->setRadarObjectColour(this->teamcolours_[teamNr]);
+
+        std::set<WorldEntity*> pawnAttachments = pawn->getAttachedObjects();
+        for (WorldEntity* pawnAttachment : pawnAttachments)
+        {
+            if (pawnAttachment->isA(Class(TeamColourable)))
+            {
+                TeamColourable* tc = orxonox_cast<TeamColourable*>(pawnAttachment);
+                tc->setTeamColour(this->teamcolours_[teamNr]);
+            }
+         }
+    }
+
+    void TeamGametype::announceTeamWin(int winnerTeam)
+    {
+        for (const auto& mapEntry : this->teamnumbers_)
+        {
+            if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                continue;
+            if (mapEntry.second == winnerTeam)
+            {
+                this->gtinfo_->sendAnnounceMessage("Your team has won the match!", mapEntry.first->getClientID());
+            }
+            else
+            {
+                this->gtinfo_->sendAnnounceMessage("Your team has lost the match!", mapEntry.first->getClientID());
+            }
+        }   
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamGametype.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamGametype.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/TeamGametype.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Johannes Ritz
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamGametype_H__
+#define _TeamGametype_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include <vector>
+#include "Gametype.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport TeamGametype : public Gametype
+    {
+        public:
+            TeamGametype(Context* context);
+            virtual ~TeamGametype() {}
+
+            void setConfigValues();
+
+            virtual void playerEntered(PlayerInfo* player) override;
+            virtual void findAndSetTeam(PlayerInfo* player);
+            virtual bool playerLeft(PlayerInfo* player) override;
+            virtual void spawnDeadPlayersIfRequested() override; //!< Prevents players to respawn.
+
+            virtual bool allowPawnHit(Pawn* victim, Pawn* originator = nullptr) override;
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator = nullptr) override;
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr) override;
+
+            virtual void playerStartsControllingPawn(PlayerInfo* player, Pawn* pawn) override;
+
+
+            int getTeam(PlayerInfo* player);
+
+            inline const ColourValue& getTeamColour(int teamnr) const
+                { return this->teamcolours_[teamnr]; }
+            int getTeamScore(PlayerInfo* player);
+            int getTeamSize(int team);
+            int getHumansInTeam(int team);
+
+        protected:
+            virtual SpawnPoint* getBestSpawnPoint(PlayerInfo* player) const override;
+            bool pawnsAreInTheSameTeam(Pawn* pawn1, Pawn* pawn2);
+
+            bool allowFriendlyFire_; //!< friendlyfire is per default switched off: friendlyFire_ = false;
+            std::map<PlayerInfo*, int> teamnumbers_;
+            std::vector<ColourValue> teamcolours_;
+            unsigned int teams_; //!< Number  of teams. Value 0 : no teams!
+            //unsigned int playersPerTeam_; //!< Defines Maximum for players per team. Value 0: no maximum!
+            unsigned int maxPlayers_; //!< Defines Maximum for number of players. Value 0 : no maximum!
+            std::map<PlayerInfo*, bool> allowedInGame_; //!< Only those players are allowed to spawn which are listed here as 'true'.
+            void setTeamColour(PlayerInfo* player, Pawn* pawn);
+            void setDefaultObjectColour(Pawn* pawn);
+            void colourPawn(Pawn* pawn, int teamNr);
+            void announceTeamWin(int winnerTeam);
+
+    };
+}
+
+#endif /* _TeamGametype_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/UnderAttack.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/UnderAttack.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/UnderAttack.cc	(revision 11817)
@@ -0,0 +1,215 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Matthias Mock
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "UnderAttack.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "chat/ChatManager.h"
+#include "worldentities/pawns/Destroyer.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    const int attacker_ = 0; // teamnumber of the attacking team
+    const int defender_ = 1; // defender's teamnumber
+
+    RegisterUnloadableClass(UnderAttack);
+
+    UnderAttack::UnderAttack(Context* context) : TeamDeathmatch(context)
+    {
+        RegisterObject(UnderAttack);
+        this->gameTime_ = 180;
+        this->teams_ = 2;
+        this->destroyer_ = nullptr;
+        this->destroyer_.setCallback(createFunctor(&UnderAttack::killedDestroyer, this));
+        this->gameEnded_ = false;
+
+        this->setConfigValues();
+        this->timesequence_ = static_cast<int>(this->gameTime_);
+    }
+
+    void UnderAttack::setConfigValues()
+    {
+        SetConfigValue(gameTime_, 180);
+    }
+
+    void UnderAttack::addDestroyer(Destroyer* destroyer)
+    {
+        this->destroyer_ = destroyer;
+    }
+
+
+    void UnderAttack::killedDestroyer()
+    {
+        this->end(); //end gametype
+        std::string message("Ship destroyed! Team 0 has won!");
+        ChatManager::message(message);
+        this->gameEnded_ = true;
+
+        for (const auto& mapEntry : this->teamnumbers_)
+        {
+            if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                continue;
+
+            if (mapEntry.second == attacker_)
+                this->gtinfo_->sendAnnounceMessage("You have won the match!", mapEntry.first->getClientID());
+            else
+                this->gtinfo_->sendAnnounceMessage("You have lost the match!", mapEntry.first->getClientID());
+        }
+    }
+
+    bool UnderAttack::allowPawnHit(Pawn* victim, Pawn* originator)
+    {
+        if (victim == this->destroyer_)
+        {
+            if (originator && originator->getPlayer() && !gameEnded_)
+            {
+                if (this->getTeam(originator->getPlayer()) == 0)
+                    return true;
+                else
+                    return false;
+            }
+
+            return false;
+        }
+
+        return TeamDeathmatch::allowPawnHit(victim, originator);
+    }
+
+    bool UnderAttack::allowPawnDamage(Pawn* victim, Pawn* originator)
+    {
+        if (victim == this->destroyer_)
+        {
+            if (originator && originator->getPlayer() && !gameEnded_)
+            {
+                if (this->getTeam(originator->getPlayer()) == 0)
+                    return true;
+                else
+                    return false;
+            }
+
+            return false;
+        }
+
+        return TeamDeathmatch::allowPawnDamage(victim, originator);
+    }
+
+    bool UnderAttack::allowPawnDeath(Pawn* victim, Pawn* originator)
+    {
+        if (victim == this->destroyer_)
+        {
+            if (originator && originator->getPlayer() && !gameEnded_)
+            {
+                if (this->getTeam(originator->getPlayer()) == 0)
+                    return true;
+                else
+                    return false;
+            }
+
+            return false;
+        }
+
+        return TeamDeathmatch::allowPawnDeath(victim, originator);
+    }
+
+
+    void UnderAttack::tick(float dt)
+    {
+        SUPER(UnderAttack, tick, dt);
+
+        if (this->hasStarted() && !gameEnded_)
+        {
+            gameTime_ = gameTime_ - dt;
+            if (gameTime_<= 0)
+            {
+                this->gameEnded_ = true;
+                this->end();
+                std::string message("Time is up! Team 1 has won!");
+                ChatManager::message(message);
+
+                for (const auto& mapEntry : this->teamnumbers_)
+                {
+                    if (mapEntry.first->getClientID() == NETWORK_PEER_ID_UNKNOWN)
+                        continue;
+
+                    if (mapEntry.second == 1)
+                        this->gtinfo_->sendAnnounceMessage("You have won the match!", mapEntry.first->getClientID());
+                    else
+                        this->gtinfo_->sendAnnounceMessage("You have lost the match!", mapEntry.first->getClientID());
+                }
+            }
+
+             //prints gametime
+            if ( gameTime_ <= timesequence_ && gameTime_ > 0)
+            {
+                const std::string& message = multi_cast<std::string>(timesequence_) + " seconds left!";
+/*
+                ChatManager::message(message);
+*/
+                this->gtinfo_->sendAnnounceMessage(message);
+
+                if (timesequence_ >= 30 && timesequence_ <= 60)
+                {
+                    timesequence_ = timesequence_ - 10;
+                }
+                else if (timesequence_ <= 30)
+                {
+                    timesequence_ = timesequence_ - 5;
+                }
+                else
+                {
+                    timesequence_ = timesequence_ - 30;
+                }
+            }
+        }
+    }
+
+    void UnderAttack::playerEntered(PlayerInfo* player)
+    {
+        if (!player)
+            return;
+        TeamDeathmatch::playerEntered(player);
+        this->setTransporterHealth();
+    }
+
+    void UnderAttack::setTransporterHealth()
+    {
+        if (this->destroyer_ != nullptr)
+        {
+            //Calculation: Each attacker deals about 3500 damage. A human attacker deals 1500 damage additionally.
+            //Each defender prevents 500 damage. If human 2000 damage will be additionally be prevented.
+            //TODO: use gametime and the damage dealt so far in order to calculate the transporter's life more precisely
+            float health = this->getTeamSize(attacker_)*2000.0f + this->getHumansInTeam(attacker_)*3000.0f - this->getTeamSize(defender_)*500.0f - this->getHumansInTeam(defender_)*2000.0f ;
+            this->destroyer_->setHealth(std::max(health, 5000.0f)); //the destoyer should have at least 5000.0f life. 
+        }
+    }
+
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/gametypes/UnderAttack.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/gametypes/UnderAttack.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/gametypes/UnderAttack.h	(revision 11817)
@@ -0,0 +1,67 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Matthias Mock
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _UnderAttack_H__
+#define _UnderAttack_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "TeamDeathmatch.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport UnderAttack : public TeamDeathmatch
+    {
+        public:
+            UnderAttack(Context* context);
+            virtual ~UnderAttack() {}
+
+            void setConfigValues();
+            virtual void tick (float dt) override;
+            void addDestroyer(Destroyer* destroyer);
+            inline Destroyer* getDestroyer() const
+                { return this->destroyer_; }
+
+            virtual bool allowPawnHit(Pawn* victim, Pawn* originator = nullptr) override;
+            virtual bool allowPawnDamage(Pawn* victim, Pawn* originator = nullptr) override;
+            virtual bool allowPawnDeath(Pawn* victim, Pawn* originator = nullptr) override;
+            virtual void playerEntered(PlayerInfo* player) override;
+
+        protected:
+            virtual void killedDestroyer();
+            void setTransporterHealth();
+
+            WeakPtr<Destroyer> destroyer_;
+            unsigned int teams_;
+            float gameTime_;
+            int timesequence_;
+            bool gameEnded_;
+    };
+}
+
+#endif /* _TeamDeathmatch_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/AnimatedModel.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/AnimatedModel.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/AnimatedModel.cc	(revision 11817)
@@ -0,0 +1,127 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin de Capitani
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "AnimatedModel.h"
+
+#include <OgreEntity.h>
+#include <OgreAnimationState.h>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(AnimatedModel);
+
+    AnimatedModel::AnimatedModel(Context* context) : Model(context)
+    {
+        RegisterObject(AnimatedModel);
+    }
+
+
+    AnimatedModel::~AnimatedModel()
+    {
+        if (this->isInitialized() && this->mesh_.getEntity())
+            this->detachOgreObject(this->mesh_.getEntity());
+    }
+
+    void AnimatedModel::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(AnimatedModel, XMLPort, xmlelement, mode);
+        XMLPortParam(AnimatedModel,"anims",setAnims,getAnims, xmlelement,mode).defaultValues("");
+        XMLPortParam(AnimatedModel,"loop", setAnimLoop,getAnimLoop, xmlelement,mode).defaultValues(true);
+        XMLPortParam(AnimatedModel,"enabled", setAnimEnabled,getAnimEnabled, xmlelement,mode).defaultValues(true);
+    }
+
+
+    void AnimatedModel::changedMesh()
+    {
+        if (GameMode::showsGraphics())
+        {
+            if (this->mesh_.getEntity())
+                this->detachOgreObject(this->mesh_.getEntity());
+
+            this->mesh_.setMeshSource(this->getScene()->getSceneManager(), this->meshSrc_);
+
+            if (this->mesh_.getEntity())
+            {
+                this->attachOgreObject(this->mesh_.getEntity());
+                this->mesh_.getEntity()->setCastShadows(this->bCastShadows_);
+                this->setAnimationState(this->bAnimLoop_, this->bAnimEnabled_, this->anims_);
+                this->mesh_.setVisible(this->isVisible());
+            }
+        }
+    }
+
+    void AnimatedModel::changedAnimationState()
+    {
+        this->setAnimationState(this->bAnimLoop_, this->bAnimEnabled_, this->anims_);
+    }
+    void AnimatedModel::setAnimationState(bool loop, bool enabled, const std::string& state)
+    {
+        if(state!="")
+        {
+        if(this->mesh_.getEntity()->getAnimationState(state))
+        {
+        Ogre::AnimationState* as = this->mesh_.getEntity()->getAnimationState(state);
+        as->setLoop(loop);
+        as->setEnabled(enabled);
+        this->anims_ = state;
+        }
+        }
+    }
+
+    void AnimatedModel::setAnimLoop(bool loop)
+    {
+        this->bAnimLoop_ = loop;
+    }
+    void AnimatedModel::setAnimEnabled(bool enabled)
+    {
+        this->bAnimEnabled_ = enabled;
+    }
+    void AnimatedModel::tick(float dt)
+    {
+        if(this->mesh_.getEntity()->getAnimationState(anims_))
+        {
+// Test to change Material at runtime!
+
+//            Ogre::MaterialPtr mat = this->mesh_.getEntity()->getSubEntity(0)->getMaterial();
+//            mat->setDiffuse(0.4, 0.3, 0.1, 0.1);
+//            mat->setAmbient(0.3, 0.7, 0.8);
+//            mat->setSpecular(0.5, 0.5, 0.5, 0.1);
+//            Ogre::SceneBlendType sbt = Ogre::SBT_ADD;
+//
+//            mat->setSceneBlending(sbt);
+
+            Ogre::AnimationState* as = this->mesh_.getEntity()->getAnimationState(anims_);
+            as->addTime(dt);
+    }
+}
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/AnimatedModel.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/AnimatedModel.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/AnimatedModel.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Benjamin de Capitani
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _AnimatedModel_H__
+#define _AnimatedModel_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "tools/interfaces/Tickable.h"
+#include "Model.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport AnimatedModel : public Model, public Tickable
+    {
+        public:
+            AnimatedModel(Context* context);
+            virtual ~AnimatedModel();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            void registerVariables();
+
+            virtual void changedAnimationState();
+            virtual void setAnimationState(bool loop, bool enabled, const std::string& state);
+            virtual void setAnimEnabled(bool enabled);
+            virtual void setAnimLoop(bool loop);
+            virtual void tick(float dt) override;
+            virtual void changedMesh();
+
+
+            inline void setAnims(const std::string& anims)
+                { this->anims_ = anims; this->changedAnimationState(); }
+            inline const std::string& getAnims() const
+                { return this->anims_; }
+
+            inline const std::string& getAnimationState() const
+                { return this->anims_; }
+            inline const bool&  getAnimLoop() const
+                { return this->bAnimLoop_; }
+            inline const bool&  getAnimEnabled() const
+                { return this->bAnimEnabled_; }
+
+        private:
+            std::string anims_;
+            bool bAnimEnabled_;
+            bool bAnimLoop_;
+    };
+}
+
+#endif /* _AnimatedModel_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Backlight.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Backlight.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Backlight.cc	(revision 11817)
@@ -0,0 +1,237 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Backlight.h"
+
+#include <algorithm>
+#include <OgreRibbonTrail.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+// windows.h is getting included above on Windows...
+#undef max
+#undef min
+
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(Backlight);
+
+    Backlight::Backlight(Context* context) : FadingBillboard(context)
+    {
+        RegisterObject(Backlight);
+
+        this->ribbonTrail_ = nullptr;
+        this->ribbonTrailNode_ = nullptr;
+
+        this->width_ = 0;
+        this->length_ = 1.0f;
+        this->lifetime_ = 0.001f;
+        this->maxelements_ = 1;
+
+        this->tickcount_ = 0;
+
+        if (GameMode::showsGraphics())
+        {
+            if (!this->getScene())
+                ThrowException(AbortLoading, "Can't create Backlight, no scene given.");
+            if (!this->getScene()->getSceneManager())
+                ThrowException(AbortLoading, "Can't create Backlight, no scene manager given.");
+            if (!this->getScene()->getRootSceneNode())
+                ThrowException(AbortLoading, "Can't create Backlight, no root scene node given.");
+
+            this->ribbonTrail_ = this->getScene()->getSceneManager()->createRibbonTrail(this->getNode()->getName());
+
+            this->ribbonTrailNode_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
+            this->ribbonTrailNode_->attachObject(this->ribbonTrail_);
+
+            this->ribbonTrail_->setMaxChainElements(this->maxelements_);
+            this->ribbonTrail_->setTrailLength(this->length_);
+            this->ribbonTrail_->setInitialWidth(0, 0);
+        }
+
+        this->registerVariables();
+    }
+
+    Backlight::~Backlight()
+    {
+        if (this->isInitialized())
+        {
+            if (this->ribbonTrail_)
+            {
+                if (this->ribbonTrailNode_)
+                {
+                    this->ribbonTrailNode_->detachObject(this->ribbonTrail_);
+                    this->getScene()->getSceneManager()->destroySceneNode(this->ribbonTrailNode_->getName());
+                }
+                this->getScene()->getSceneManager()->destroyRibbonTrail(this->ribbonTrail_);
+            }
+        }
+    }
+
+    void Backlight::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Backlight, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Backlight, "length",        setLength,        getLength,        xmlelement, mode).defaultValues(100.0f);
+        XMLPortParam(Backlight, "width",         setWidth,         getWidth,         xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(Backlight, "elements",      setMaxElements,   getMaxElements,   xmlelement, mode).defaultValues(10);
+        XMLPortParam(Backlight, "lifetime",      setLifetime,      getLifetime,      xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(Backlight, "trailmaterial", setTrailMaterial, getTrailMaterial, xmlelement, mode);
+    }
+
+    void Backlight::registerVariables()
+    {
+        registerVariable(this->width_,         VariableDirection::ToClient, new NetworkCallback<Backlight>(this, &Backlight::update_width));
+        registerVariable(this->lifetime_,      VariableDirection::ToClient, new NetworkCallback<Backlight>(this, &Backlight::update_lifetime));
+        registerVariable(this->length_,        VariableDirection::ToClient, new NetworkCallback<Backlight>(this, &Backlight::update_length));
+        registerVariable(this->maxelements_,   VariableDirection::ToClient, new NetworkCallback<Backlight>(this, &Backlight::update_maxelements));
+        registerVariable(this->trailmaterial_, VariableDirection::ToClient, new NetworkCallback<Backlight>(this, &Backlight::update_trailmaterial));
+    }
+
+    void Backlight::changedColour()
+    {
+        FadingBillboard::changedColour();
+
+        if (this->ribbonTrail_ && this->tickcount_ >= 2)
+            this->ribbonTrail_->setInitialColour(0, this->getFadedColour());
+    }
+
+    void Backlight::update_width()
+    {
+        if (this->ribbonTrail_ && this->tickcount_ >= 2)
+            this->ribbonTrail_->setInitialWidth(0, this->width_ * this->getWorldScale());
+        this->update_lifetime();
+    }
+
+    void Backlight::update_lifetime()
+    {
+        if (this->ribbonTrail_ && this->tickcount_ >= 2)
+        {
+            this->ribbonTrail_->setWidthChange(0, this->width_ * this->getWorldScale() / this->lifetime_ * this->getTimeFactor());
+            this->ribbonTrail_->setColourChange(0, 0, 0, 0, 1.0f / this->lifetime_ * this->getTimeFactor());
+        }
+    }
+
+    void Backlight::update_length()
+    {
+        if (this->ribbonTrail_ && this->tickcount_ >= 2)
+            this->ribbonTrail_->setTrailLength(this->length_ * this->getWorldScale());
+    }
+
+    void Backlight::update_maxelements()
+    {
+        if (this->ribbonTrail_ && this->tickcount_ >= 2)
+            this->ribbonTrail_->setMaxChainElements(this->maxelements_);
+    }
+
+    void Backlight::update_trailmaterial()
+    {
+        if (this->ribbonTrail_ && this->tickcount_ >= 2)
+            this->ribbonTrail_->setMaterialName(this->trailmaterial_);
+    }
+
+    void Backlight::changedVisibility()
+    {
+        SUPER(Backlight, changedVisibility);
+
+        if (this->ribbonTrail_)
+            this->ribbonTrail_->setVisible(this->isVisible());
+    }
+
+    void Backlight::startturnonoff()
+    {
+        FadingBillboard::startturnonoff();
+
+        if (this->ribbonTrail_ && this->isActive() && this->isVisible())
+            this->ribbonTrail_->setVisible(true);
+    }
+
+    void Backlight::stopturnonoff()
+    {
+        this->postprocessingtime_ = std::max(0.0f, this->lifetime_ - this->turnofftime_);
+
+        FadingBillboard::stopturnonoff();
+
+        if (this->ribbonTrail_)
+            this->ribbonTrail_->setInitialColour(0, this->getFadedColour());
+    }
+
+    void Backlight::poststopturnonoff()
+    {
+        FadingBillboard::poststopturnonoff();
+
+        if (this->ribbonTrail_)
+            this->ribbonTrail_->setVisible(false);
+    }
+
+    void Backlight::changedScale()
+    {
+        SUPER(Backlight, changedScale);
+
+        this->update_width();
+        this->update_length();
+    }
+
+    void Backlight::tick(float dt)
+    {
+        if (this->tickcount_ < 2)
+        {
+            ++this->tickcount_;
+            if (this->tickcount_ == 2)
+            {
+                this->changedColour();
+                this->update_width();
+                this->update_lifetime();
+                this->update_length();
+                this->update_maxelements();
+                this->update_trailmaterial();
+                if (this->ribbonTrail_)
+                    this->ribbonTrail_->addNode(this->node_);
+            }
+        }
+
+        SUPER(Backlight, tick, dt);
+
+        if (this->ribbonTrail_ && this->changedirection_ != 0)
+        {
+            // we use alpha_blend, only adjust alpha
+            const ColourValue& colour = this->getColour();
+            this->ribbonTrail_->setInitialColour(0, colour.r, colour.g, colour.b, this->getFadedColour().a);
+        }
+    }
+
+    void Backlight::changedTimeFactor(float factor_new, float factor_old)
+    {
+        this->update_lifetime();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Backlight.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Backlight.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Backlight.h	(revision 11817)
@@ -0,0 +1,104 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Backlight_H__
+#define _Backlight_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "tools/interfaces/TimeFactorListener.h"
+#include "FadingBillboard.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Backlight : public FadingBillboard, public TimeFactorListener
+    {
+        public:
+            Backlight(Context* context);
+            virtual ~Backlight();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void tick(float dt) override;
+            virtual void changedVisibility() override;
+
+            inline void setWidth(float width)
+                { this->width_ = width; this->update_width(); }
+            inline float getWidth() const
+                { return this->width_; }
+
+            inline void setLifetime(float lifetime)
+                { this->lifetime_ = lifetime; this->update_lifetime(); }
+            inline float getLifetime() const
+                { return this->lifetime_; }
+
+            inline void setLength(float length)
+                { this->length_ = length; this->update_length(); }
+            inline float getLength() const
+                { return this->length_; }
+
+            inline void setMaxElements(size_t maxelements)
+                { this->maxelements_ = maxelements; this->update_maxelements(); }
+            inline size_t getMaxElements() const
+                { return this->maxelements_; }
+
+            inline void setTrailMaterial(const std::string& material)
+                { this->trailmaterial_ = material; this->update_trailmaterial(); }
+            inline const std::string& getTrailMaterial() const
+                { return this->trailmaterial_; }
+
+            virtual void changedScale() override;
+
+        protected:
+            virtual void changedTimeFactor(float factor_new, float factor_old) override;
+
+        private:
+            void registerVariables();
+            virtual void startturnonoff() override;
+            virtual void stopturnonoff() override;
+            virtual void poststopturnonoff() override;
+            virtual void changedColour() override;
+            void update_width();
+            void update_lifetime();
+            void update_length();
+            void update_maxelements();
+            void update_trailmaterial();
+
+            Ogre::RibbonTrail* ribbonTrail_;
+            Ogre::SceneNode* ribbonTrailNode_;
+            float width_;
+            float length_;
+            float lifetime_;
+            size_t maxelements_;
+            std::string trailmaterial_;
+            char tickcount_;
+    };
+}
+
+#endif /* _Backlight_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Billboard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Billboard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Billboard.cc	(revision 11817)
@@ -0,0 +1,191 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Maurus Kaufmann
+ *
+ */
+
+#include "Billboard.h"
+
+#include "OgreBillboard.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(Billboard);
+
+    Billboard::Billboard(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Billboard);
+
+        this->colour_ = ColourValue::White;
+        this->rotation_ = 0;
+
+        this->registerVariables();
+    }
+
+    Billboard::~Billboard()
+    {
+        if (this->isInitialized())
+        {
+            if (this->isInitialized() && this->billboard_.getBillboardSet())
+                this->detachOgreObject(this->billboard_.getBillboardSet());
+        }
+    }
+
+    void Billboard::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Billboard, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Billboard, "material", setMaterial, getMaterial, xmlelement, mode);
+        XMLPortParam(Billboard, "colour",   setColour,   getColour,   xmlelement, mode).defaultValues(ColourValue::White);
+        XMLPortParam(Billboard, "rotation", setRotation, getRotation, xmlelement, mode).defaultValues(0);
+    }
+
+    void Billboard::registerVariables()
+    {
+        registerVariable(this->material_, VariableDirection::ToClient, new NetworkCallback<Billboard>(this, &Billboard::changedMaterial));
+        registerVariable(this->colour_,   VariableDirection::ToClient, new NetworkCallback<Billboard>(this, &Billboard::changedColour));
+        registerVariable(this->rotation_, VariableDirection::ToClient, new NetworkCallback<Billboard>(this, &Billboard::changedRotation));
+    }
+
+    void Billboard::changedMaterial()
+    {
+        if (this->material_.empty())
+            return;
+
+        if (!this->billboard_.getBillboardSet())
+        {
+            if (this->getScene() && GameMode::showsGraphics())
+            {
+                this->billboard_.setBillboardSet(this->getScene()->getSceneManager(), this->material_, this->colour_, 1);
+                if (this->billboard_.getBillboardSet())
+                     this->attachOgreObject(this->billboard_.getBillboardSet());
+                this->billboard_.setVisible(this->isVisible());
+                this->changedRotation();
+            }
+        }
+        else
+            this->billboard_.setMaterial(this->material_);
+    }
+
+    void Billboard::changedColour()
+    {
+        if (!this->billboard_.getBillboardSet())
+        {
+/*
+            if (this->getScene() && GameMode::showsGraphics() && !this->material_.empty())
+            {
+                this->billboard_.setBillboardSet(this->getScene()->getSceneManager(), this->material_, this->colour_, 1);
+                if (this->billboard_.getBillboardSet())
+                    this->attachOgreObject(this->billboard_.getBillboardSet());
+                this->billboard_.setVisible(this->isVisible());
+            }
+*/
+        }
+        else
+            this->billboard_.setColour(this->colour_);
+    }
+
+
+    void Billboard::changedRotation()
+    {
+        if (this->billboard_.getBillboardSet())
+        {
+            Ogre::BillboardSet* set = this->billboard_.getBillboardSet();
+            set->setBillboardRotationType(Ogre::BBR_VERTEX);
+            unsigned int size = set->getPoolSize();
+            for(unsigned int i = 0; i < size; i++)
+            {
+                set->getBillboard(i)->setRotation(this->rotation_);
+            }
+        }
+    }
+
+
+    void Billboard::changedVisibility()
+    {
+        SUPER(Billboard, changedVisibility);
+
+        this->billboard_.setVisible(this->isVisible());
+    }
+    
+    void Billboard::setBillboardType(Ogre::BillboardType bbt)
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != nullptr )
+        {
+            bSet->setBillboardType(bbt);
+        }
+    }
+    
+    void Billboard::setCommonDirection(Vector3 vec)
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != nullptr )
+        {
+            bSet->setCommonDirection( vec );
+        }
+    }
+            
+    void Billboard::setCommonUpVector(Vector3 vec)
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != nullptr )
+        {
+            bSet->setCommonUpVector( vec );
+        }
+    }
+    
+    void Billboard::setDefaultDimensions(float width, float height)
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != nullptr )
+        {
+            bSet->setDefaultDimensions(width, height);
+        }
+    }
+    
+    void Billboard::setRenderQueueGroup(unsigned char groupID)
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != nullptr )
+        {
+            bSet->setRenderQueueGroup(groupID);
+        }
+    }
+    
+    void Billboard::disableFrustumCulling()
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != nullptr )
+        {
+            bSet->setBounds(Ogre::AxisAlignedBox(Ogre::AxisAlignedBox::EXTENT_INFINITE),0);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Billboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Billboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Billboard.h	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Maurus Kaufmann
+ *
+ */
+
+#ifndef _Billboard_H__
+#define _Billboard_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "OgreBillboardSet.h"
+
+#include "util/Math.h"
+#include "tools/BillboardSet.h"
+#include "interfaces/TeamColourable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Billboard : public StaticEntity, public TeamColourable
+    {
+        public:
+            Billboard(Context* context);
+            virtual ~Billboard();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedVisibility() override;
+
+            inline const BillboardSet& getBillboardSet() const
+                { return this->billboard_; }
+
+            inline void setMaterial(const std::string& material)
+                { this->material_ = material; this->changedMaterial(); }
+            inline const std::string& getMaterial() const
+                { return this->material_; }
+
+            inline void setColour(const ColourValue& colour)
+                { this->colour_ = colour; this->changedColour(); }
+            inline const ColourValue& getColour() const
+                { return this->colour_; }
+
+
+            inline void setRotation(const Radian& rotation)
+                { this->rotation_ = rotation; this->changedRotation(); }
+            inline const Radian& getRotation() const
+                { return this->rotation_; }
+
+
+            virtual void setTeamColour(const ColourValue& colour) override
+                { this->setColour(colour); }
+                
+            void setBillboardType(Ogre::BillboardType bbt);
+            
+            void setCommonDirection(Vector3 vec); //!< normalised Vector vec as argument
+            
+            void setCommonUpVector(Vector3 vec); //!< normalised Vector vec as argument
+            
+            void setDefaultDimensions(float width, float height);
+            
+            void setRenderQueueGroup(unsigned char groupID);
+            
+            void disableFrustumCulling();
+
+
+        protected:
+            inline BillboardSet& getBillboardSet()
+                { return this->billboard_; }
+
+            virtual void changedColour();
+
+        private:
+            void registerVariables();
+            void changedMaterial();
+            void changedRotation();
+
+            BillboardSet billboard_;
+            std::string material_;
+            ColourValue colour_;
+            Radian rotation_;
+    };
+}
+
+#endif /* _Billboard_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/BlinkingBillboard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/BlinkingBillboard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/BlinkingBillboard.cc	(revision 11817)
@@ -0,0 +1,90 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "BlinkingBillboard.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(BlinkingBillboard);
+
+    BlinkingBillboard::BlinkingBillboard(Context* context) : Billboard(context)
+    {
+        RegisterObject(BlinkingBillboard);
+
+        this->amplitude_ = 1.0f;
+        this->frequency_ = 1.0f;
+        this->phase_ = 0;
+        this->bQuadratic_ = false;
+        this->time_ = 0;
+
+        this->registerVariables();
+    }
+
+    BlinkingBillboard::~BlinkingBillboard()
+    {
+    }
+
+    void BlinkingBillboard::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(BlinkingBillboard, XMLPort, xmlelement, mode);
+
+        XMLPortParam(BlinkingBillboard, "amplitude", setAmplitude, getAmplitude, xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(BlinkingBillboard, "frequency", setFrequency, getFrequency, xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(BlinkingBillboard, "phase",     setPhase,     getPhase,     xmlelement, mode).defaultValues(Degree(0));
+        XMLPortParam(BlinkingBillboard, "quadratic", setQuadratic, isQuadratic,  xmlelement, mode).defaultValues(false);
+    }
+
+    void BlinkingBillboard::registerVariables()
+    {
+        unregisterVariable(this->getScale3D());
+        registerVariable(this->amplitude_,  VariableDirection::ToClient);
+        registerVariable(this->frequency_,  VariableDirection::ToClient);
+        registerVariable(this->phase_,      VariableDirection::ToClient);
+        registerVariable(this->bQuadratic_, VariableDirection::ToClient);
+    }
+
+    void BlinkingBillboard::tick(float dt)
+    {
+        SUPER(BlinkingBillboard, tick, dt);
+
+        if (this->isActive())
+        {
+            // Wrap around to avoid loosing floating point precision
+            this->time_ = std::fmod(this->time_ + dt, 1.0f / this->frequency_);
+            float value = sin((math::twoPi * this->time_ + this->phase_.valueRadians()) * this->frequency_);
+            if (this->bQuadratic_)
+                this->setScale(this->amplitude_ * square(value));
+            else
+                this->setScale(this->amplitude_ * std::abs(value));
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/BlinkingBillboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/BlinkingBillboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/BlinkingBillboard.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _BlinkingBillboard_H__
+#define _BlinkingBillboard_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+#include "tools/interfaces/Tickable.h"
+#include "Billboard.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport BlinkingBillboard : public Billboard, public Tickable
+    {
+        public:
+            BlinkingBillboard(Context* context);
+            virtual ~BlinkingBillboard();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void tick(float dt) override;
+
+            inline void setAmplitude(float amplitude)
+                { this->amplitude_ = amplitude; }
+            inline float getAmplitude() const
+                { return this->amplitude_; }
+
+            inline void setFrequency(float frequency)
+                { this->frequency_ = frequency; }
+            inline float getFrequency() const
+                { return this->frequency_; }
+
+            inline void setPhase(const Degree& phase)
+                { this->phase_ = phase; }
+            inline const Degree& getPhase() const
+                { return this->phase_; }
+
+            inline void setQuadratic(bool bQuadratic)
+                { this->bQuadratic_ = bQuadratic; }
+            inline bool isQuadratic() const
+                { return this->bQuadratic_; }
+
+        private:
+            void registerVariables();
+            
+            float amplitude_;
+            float frequency_;
+            Degree phase_;
+            bool bQuadratic_;
+            float time_;
+    };
+}
+
+#endif /* _BlinkingBillboard_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,18 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  Billboard.cc
+  BlinkingBillboard.cc
+  FadingBillboard.cc
+  GlobalShader.cc
+  MeshLodInformation.cc
+  Model.cc
+  AnimatedModel.cc
+  ParticleEmitter.cc
+  ParticleSpawner.cc
+
+BUILD_UNIT GraphicsBuildUnit.cc
+  Backlight.cc
+  Camera.cc
+  LensFlare.cc
+  Light.cc
+END_BUILD_UNIT
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Camera.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Camera.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Camera.cc	(revision 11817)
@@ -0,0 +1,228 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Benjamin Knecht
+ *
+ */
+
+#include "Camera.h"
+
+#include <algorithm>
+#include <OgreCamera.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+#include "core/GUIManager.h"
+#include "Scene.h"
+#include "CameraManager.h"
+#include "sound/SoundManager.h"
+
+namespace orxonox
+{
+    RegisterClass(Camera);
+
+    Camera::Camera(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Camera);
+
+        if (!GameMode::showsGraphics())
+            ThrowException(AbortLoading, "Can't create Camera, no graphics.");
+        if (!this->getScene())
+            ThrowException(AbortLoading, "Can't create Camera, no scene.");
+        if (!this->getScene()->getSceneManager())
+            ThrowException(AbortLoading, "Can't create Camera, no scene-manager given.");
+        if (!this->getScene()->getRootSceneNode())
+            ThrowException(AbortLoading, "Can't create Camera, no root-scene-node given.");
+
+        this->camera_ = this->getScene()->getSceneManager()->createCamera(getUniqueNumberString());
+        static_cast<Ogre::MovableObject*>(this->camera_)->setUserAny(Ogre::Any(static_cast<OrxonoxClass*>(this)));
+        this->cameraNode_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
+        this->attachNode(this->cameraNode_);
+        this->cameraNode_->attachObject(this->camera_);
+
+        this->bHasFocus_ = false;
+        this->bDrag_ = false;
+        this->lastDtLagged_ = false;
+
+        this->setSyncMode(ObjectDirection::None);
+
+        this->setConfigValues();
+
+        this->configvaluecallback_changedFovAndAspectRatio();
+        this->configvaluecallback_changedNearClipDistance();
+    }
+
+    Camera::~Camera()
+    {
+        if (this->isInitialized())
+        {
+            this->releaseFocus();
+
+            this->cameraNode_->detachAllObjects();
+            this->getScene()->getSceneManager()->destroyCamera(this->camera_);
+
+            if (this->bDrag_)
+                this->detachNode(this->cameraNode_);
+
+            if (this->getScene()->getSceneManager())
+                this->getScene()->getSceneManager()->destroySceneNode(this->cameraNode_->getName());
+        }
+    }
+
+    void Camera::setConfigValues()
+    {
+        SetConfigValue(fov_, 80.0f)
+            .description("Horizontal field of view in degrees")
+            .callback(this, &Camera::configvaluecallback_changedFovAndAspectRatio);
+        SetConfigValue(aspectRatio_, 1.0f)
+            .description("Aspect ratio of pixels (width / height)")
+            .callback(this, &Camera::configvaluecallback_changedFovAndAspectRatio);
+        SetConfigValue(nearClipDistance_, 1.0f)
+            .description("Distance from the camera where close objects will be clipped")
+            .callback(this, &Camera::configvaluecallback_changedNearClipDistance);
+    }
+
+    /**
+        @brief Update FOV and the aspect ratio of the camera after the config values or the window's size have changed.
+    */
+    void Camera::configvaluecallback_changedFovAndAspectRatio()
+    {
+        // the aspect ratio of the window (width / height) has to be multiplied with the pixels aspect ratio (this->aspectRatio_)
+        float aspectRatio = this->aspectRatio_ * this->getWindowWidth() / this->getWindowHeight();
+        this->camera_->setAspectRatio(aspectRatio);
+
+        // Since we use horizontal FOV, we have to calculate FOVy by dividing by the aspect ratio and using some tangents
+        Radian fovy(2 * atan(tan(Degree(this->fov_).valueRadians() / 2) / aspectRatio));
+        this->camera_->setFOVy(fovy);
+    }
+
+    void Camera::configvaluecallback_changedNearClipDistance()
+    {
+        this->camera_->setNearClipDistance(this->nearClipDistance_);
+    }
+
+    /**
+        @brief Inherited from WindowEventListener.
+    */
+    void Camera::windowResized(unsigned int newWidth, unsigned int newHeight)
+    {
+        this->configvaluecallback_changedFovAndAspectRatio();
+    }
+
+    void Camera::tick(float dt)
+    {
+        SUPER(Camera, tick, dt);
+
+        if (this->bDrag_ && this->getTimeFactor() != 0)
+        {
+            // this stuff here may need some adjustments
+            float poscoeff = 15.0f * dt / this->getTimeFactor();
+            float anglecoeff = 7.0f * dt / this->getTimeFactor();
+            // Only clamp if fps rate is actually falling. Occasional high dts should
+            // not be clamped to reducing lagging effects.
+            if (poscoeff > 1.0f)
+            {
+                if (this->lastDtLagged_)
+                    poscoeff = 1.0f;
+                else
+                    this->lastDtLagged_ = true;
+            }
+            else
+                this->lastDtLagged_ = false;
+
+            if (anglecoeff > 1.0f)
+            {
+                if (this->lastDtLagged_)
+                    anglecoeff = 1.0f;
+                else
+                    this->lastDtLagged_ = true;
+            }
+            else
+                this->lastDtLagged_ = false;
+
+            Vector3 offset = this->getWorldPosition() - this->cameraNode_->_getDerivedPosition();
+            this->cameraNode_->translate(poscoeff * offset);
+
+            this->cameraNode_->setOrientation(Quaternion::Slerp(anglecoeff, this->cameraNode_->_getDerivedOrientation(), this->getWorldOrientation(), true));
+        }
+
+        // Update sound listener transformation
+        if (GameMode::playsSound() && this->bHasFocus_)
+        {
+            SoundManager::getInstance().setListenerPosition(this->getWorldPosition());
+            SoundManager::getInstance().setListenerOrientation(this->getWorldOrientation());
+        }
+    }
+
+    void Camera::requestFocus()
+    {
+        CameraManager::getInstance().requestFocus(this);
+    }
+
+    void Camera::releaseFocus()
+    {
+        CameraManager::getInstance().releaseFocus(this);
+    }
+
+    /**
+        what to do when camera loses focus (do not request focus in this function!!)
+        this is called by the CameraManager singleton class to notify the camera
+    */
+    void Camera::removeFocus()
+    {
+        this->bHasFocus_ = false;
+    }
+
+    void Camera::setFocus()
+    {
+        this->bHasFocus_ = true;
+        CameraManager::getInstance().useCamera(this->camera_);
+    }
+
+    void Camera::setDrag(bool bDrag)
+    {
+        if (bDrag != this->bDrag_)
+        {
+            this->bDrag_ = bDrag;
+
+            if (!bDrag)
+            {
+                this->attachNode(this->cameraNode_);
+                this->cameraNode_->setPosition(Vector3::ZERO);
+                this->cameraNode_->setOrientation(Quaternion::IDENTITY);
+            }
+            else
+            {
+                this->detachNode(this->cameraNode_);
+                this->cameraNode_->setPosition(this->getWorldPosition());
+                this->cameraNode_->setOrientation(this->getWorldOrientation());
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Camera.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Camera.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Camera.h	(revision 11817)
@@ -0,0 +1,87 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Benjamin Knecht
+ *
+ */
+
+#ifndef _Camera_H__
+#define _Camera_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/OgreForwardRefs.h"
+#include "core/WindowEventListener.h"
+#include "tools/interfaces/Tickable.h"
+#include "tools/interfaces/TimeFactorListener.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+
+    class _OrxonoxExport Camera : public StaticEntity, public Tickable,  public TimeFactorListener, public WindowEventListener
+    {
+        friend class CameraManager;
+
+        public:
+            Camera(Context* context);
+            virtual ~Camera();
+
+            void setConfigValues();
+            virtual void tick(float dt) override;
+
+            void requestFocus();
+            void releaseFocus();
+
+            inline Ogre::Camera* getOgreCamera()
+               { return this->camera_; }
+
+            inline bool hasFocus()
+                { return this->bHasFocus_; }
+
+            void setDrag(bool bDrag);
+            inline bool getDrag() const
+                { return this->bDrag_; }
+
+        private:
+            void removeFocus();
+            void setFocus();
+
+            void configvaluecallback_changedFovAndAspectRatio();
+            void configvaluecallback_changedNearClipDistance();
+
+            virtual void windowResized(unsigned int newWidth, unsigned int newHeight) override;
+
+            Ogre::Camera*    camera_;
+            Ogre::SceneNode* cameraNode_;
+            float            nearClipDistance_;
+            bool             bHasFocus_;
+            bool             bDrag_;
+            bool             lastDtLagged_;
+            float            fov_;
+            float            aspectRatio_;
+    };
+}
+
+#endif /* _Camera_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/FadingBillboard.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/FadingBillboard.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/FadingBillboard.cc	(revision 11817)
@@ -0,0 +1,163 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FadingBillboard.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(FadingBillboard);
+
+    FadingBillboard::FadingBillboard(Context* context) : Billboard(context)
+    {
+        RegisterObject(FadingBillboard);
+
+        this->turnontime_ = 0.0f;
+        this->turnofftime_ = 0.0f;
+        this->postprocessingtime_ = 0.0f;
+        this->changedirection_ = 0;
+
+        this->fadedColour_ = ColourValue::White;
+
+        this->registerVariables();
+    }
+
+    FadingBillboard::~FadingBillboard()
+    {
+    }
+
+    void FadingBillboard::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FadingBillboard, XMLPort, xmlelement, mode);
+
+        XMLPortParam(FadingBillboard, "turnontime",  setTurnOnTime,  getTurnOnTime,  xmlelement, mode).defaultValues(0.5f);
+        XMLPortParam(FadingBillboard, "turnofftime", setTurnOffTime, getTurnOffTime, xmlelement, mode).defaultValues(0.5f);
+    }
+
+    void FadingBillboard::registerVariables()
+    {
+        registerVariable(this->turnontime_,  VariableDirection::ToClient);
+        registerVariable(this->turnofftime_, VariableDirection::ToClient);
+    }
+
+    void FadingBillboard::changedColour()
+    {
+        Billboard::changedColour();
+
+        if (this->isActive())
+            this->fadedColour_ = this->getColour();
+        else
+            this->fadedColour_ = ColourValue::ZERO;
+
+        this->getBillboardSet().setColour(this->fadedColour_);
+    }
+
+    void FadingBillboard::changedActivity()
+    {
+        SUPER(FadingBillboard, changedActivity);
+
+        this->startturnonoff();
+    }
+
+    void FadingBillboard::changedVisibility()
+    {
+        SUPER(FadingBillboard, changedVisibility);
+
+        if (this->isVisible() && !this->isActive() && this->changedirection_ == 0)
+        {
+            // Billboard shouldn't be visible
+            this->getBillboardSet().setVisible(false);
+        }
+    }
+
+    void FadingBillboard::startturnonoff()
+    {
+        if (this->isActive())
+        {
+            this->changedirection_ = 1;
+            this->turnonofftimer_.setTimer(this->turnontime_, false, createExecutor(createFunctor(&FadingBillboard::stopturnonoff, this)));
+
+            if (this->isVisible())
+                this->getBillboardSet().setVisible(true);
+        }
+        else
+        {
+            this->changedirection_ = -1;
+            this->turnonofftimer_.setTimer(this->turnofftime_, false, createExecutor(createFunctor(&FadingBillboard::stopturnonoff, this)));
+        }
+    }
+
+    void FadingBillboard::stopturnonoff()
+    {
+        if (this->changedirection_ > 0)
+        {
+            this->fadedColour_ = this->getColour();
+            this->getBillboardSet().setColour(this->fadedColour_);
+        }
+        else if (this->changedirection_ < 0)
+        {
+            this->fadedColour_ = ColourValue::ZERO;
+            this->getBillboardSet().setColour(this->fadedColour_);
+            this->turnonofftimer_.setTimer(this->postprocessingtime_, false, createExecutor(createFunctor(&FadingBillboard::poststopturnonoff, this)));
+        }
+        this->changedirection_ = 0;
+    }
+
+    void FadingBillboard::poststopturnonoff()
+    {
+        this->getBillboardSet().setVisible(false);
+    }
+
+    void FadingBillboard::tick(float dt)
+    {
+        SUPER(FadingBillboard, tick, dt);
+
+        if (this->changedirection_ > 0 && (this->fadedColour_.a < this->getColour().a))
+        {
+            ColourValue colour = this->fadedColour_ + this->getColour() / this->turnontime_ * dt;
+
+            if (colour.a < this->getColour().a)
+            {
+                this->fadedColour_ = colour;
+                this->getBillboardSet().setColour(this->fadedColour_);
+            }
+        }
+        else if (this->changedirection_ < 0 && (this->fadedColour_.a > 0))
+        {
+            ColourValue colour = this->fadedColour_ - this->getColour() / this->turnofftime_ * dt;
+
+            if (colour.a > 0)
+            {
+                this->fadedColour_ = colour;
+                this->getBillboardSet().setColour(this->fadedColour_);
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/FadingBillboard.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/FadingBillboard.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/FadingBillboard.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FadingBillboard_H__
+#define _FadingBillboard_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+#include "tools/Timer.h"
+#include "tools/interfaces/Tickable.h"
+#include "Billboard.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport FadingBillboard : public Billboard, public Tickable
+    {
+        public:
+            FadingBillboard(Context* context);
+            virtual ~FadingBillboard();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void tick(float dt) override;
+            virtual void changedActivity() override;
+            virtual void changedVisibility() override;
+
+            inline void setTurnOnTime(float turnontime)
+                { this->turnontime_ = turnontime; }
+            inline float getTurnOnTime() const
+                { return this->turnontime_; }
+
+            inline void setTurnOffTime(float turnofftime)
+                { this->turnofftime_ = turnofftime; }
+            inline float getTurnOffTime() const
+                { return this->turnofftime_; }
+
+            inline const ColourValue& getFadedColour() const
+                { return this->fadedColour_; }
+
+        protected:
+            void registerVariables();
+            virtual void startturnonoff();
+            virtual void stopturnonoff();
+            virtual void poststopturnonoff();
+            virtual void changedColour() override;
+
+            float turnontime_;
+            float turnofftime_;
+            float postprocessingtime_;
+            Timer turnonofftimer_;
+            char changedirection_;
+            ColourValue fadedColour_;
+    };
+}
+
+#endif /* _FadingBillboard_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/GlobalShader.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/GlobalShader.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/GlobalShader.cc	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GlobalShader.h"
+
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(GlobalShader);
+
+    GlobalShader::GlobalShader(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        RegisterObject(GlobalShader);
+
+        if (!this->getScene())
+            ThrowException(AbortLoading, "Can't create GlobalShader, no scene given.");
+//        if (!this->getScene()->getSceneManager())
+//            ThrowException(AbortLoading, "Can't create GlobalShader, no scene manager given.");
+
+        if (this->getScene()->getSceneManager())
+            this->shader_.setSceneManager(this->getScene()->getSceneManager());
+
+        this->registerVariables();
+    }
+
+    GlobalShader::~GlobalShader()
+    {
+    }
+
+    void GlobalShader::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(GlobalShader, XMLPort, xmlelement, mode);
+
+        XMLPortParamExtern(GlobalShader, Shader, &this->shader_, "compositor", setCompositorName, getCompositorName, xmlelement, mode);
+    }
+
+    void GlobalShader::registerVariables()
+    {
+        registerVariable(this->bVisible_,                                         VariableDirection::ToClient, new NetworkCallback<GlobalShader>(this, &GlobalShader::changedVisibility));
+        registerVariable(const_cast<std::string&>(this->shader_.getCompositorName()), VariableDirection::ToClient, new NetworkCallback<Shader>(&this->shader_, &Shader::changedCompositorName));
+    }
+
+    void GlobalShader::changedVisibility()
+    {
+        SUPER(GlobalShader, changedVisibility);
+
+        this->shader_.setVisible(this->isVisible());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/GlobalShader.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/GlobalShader.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/GlobalShader.h	(revision 11817)
@@ -0,0 +1,60 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GlobalShader_H__
+#define _GlobalShader_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+#include "tools/Shader.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GlobalShader : public BaseObject, public Synchronisable
+    {
+        public:
+            GlobalShader(Context* context);
+            virtual ~GlobalShader();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedVisibility() override;
+
+            inline Shader& getShader()
+                { return this->shader_; }
+
+        private:
+            void registerVariables();
+
+            Shader shader_;
+    };
+}
+
+#endif /* _GlobalShader_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/LensFlare.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/LensFlare.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/LensFlare.cc	(revision 11817)
@@ -0,0 +1,232 @@
+ /*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      David 'davidsa' Salvisberg
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+  @file LensFlare.cc
+  @brief Implementation of the LensFlare class.
+*/
+
+#include "LensFlare.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/Billboard.h"
+#include "CameraManager.h"
+#include "Camera.h"
+#include "RenderQueueListener.h"
+#include "Scene.h"
+
+#include <OgreSphere.h>
+#include <OgreRenderWindow.h>
+#include <OgreCamera.h>
+
+namespace orxonox
+{
+    RegisterClass(LensFlare);
+    
+    LensFlare::LensFlare(Context* context) : StaticEntity(context), scale_(1.0f), fadeOnViewBorder_(true), fadeResolution_(7), fadeExponent_(2.0f)
+    {
+        RegisterObject(LensFlare);
+        
+        this->lensConfiguration_.emplace_back("lensflare/burst",     1.0f,  1.0f, 1.0f); //main burst
+        this->lensConfiguration_.emplace_back("lensflare/burst",     0.7f,  1.2f, 1.05f); //secondary burst
+        this->lensConfiguration_.emplace_back("lensflare/bursthalo", 0.7f,  0.9f, 1.0f); //halo around main burst
+        this->lensConfiguration_.emplace_back("lensflare/ring",      0.1f,  2.5f, 0.9f); //all the different distanced lenses
+        this->lensConfiguration_.emplace_back("lensflare/iris",      0.1f,  0.2f, 0.5f);
+        this->lensConfiguration_.emplace_back("lensflare/halo5",     0.1f,  0.3f, 0.45f);
+        this->lensConfiguration_.emplace_back("lensflare/halo5",     0.4f,  0.2f, 0.35f);
+        this->lensConfiguration_.emplace_back("lensflare/iris",      0.1f,  0.4f, 0.25f);
+        this->lensConfiguration_.emplace_back("lensflare/halo4",     0.05f, 0.2f, 0.2f);
+        
+        this->createBillboards();
+        
+        this->registerVariables();
+    }
+
+    LensFlare::~LensFlare()
+    {
+    }
+
+    void LensFlare::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(LensFlare, XMLPort, xmlelement, mode);
+        XMLPortParam(LensFlare, "scale", setScale, getScale, xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(LensFlare, "fadeOnViewBorder", setFadeOnViewBorder, isFadeOnViewBorder, xmlelement, mode).defaultValues(true);
+        XMLPortParam(LensFlare, "fadeResolution", setFadeResolution, getFadeResolution, xmlelement, mode).defaultValues(7);
+        XMLPortParam(LensFlare, "fadeExponent", setFadeExponent, getFadeExponent, xmlelement, mode).defaultValues(2.0f);
+        XMLPortParam(LensFlare, "colour", setColour, getColour, xmlelement, mode);
+    }
+    
+    void LensFlare::registerVariables()
+    {
+        registerVariable(this->scale_, VariableDirection::ToClient);
+        registerVariable(this->fadeOnViewBorder_, VariableDirection::ToClient);
+        registerVariable(this->fadeResolution_, VariableDirection::ToClient);
+    }
+
+    /**
+    @brief
+        This function creates all the billboards needed for the flare effect
+    */
+    void LensFlare::createBillboards()
+    {
+        this->occlusionBillboard_ = new Billboard(this->getContext());
+        this->occlusionBillboard_->setMaterial("lensflare/hoq");
+        this->occlusionBillboard_->setVisible(false);
+        this->occlusionBillboard_->disableFrustumCulling();
+        this->occlusionBillboard_->setRenderQueueGroup(RENDER_QUEUE_HOQ);
+        this->attach(this->occlusionBillboard_);
+        
+        for (const LensFlare::Lens& lens : lensConfiguration_)
+        {
+            Billboard* lensPart = new Billboard(this->getContext());
+            lensPart->setMaterial(lens.material_);
+            lensPart->disableFrustumCulling();
+            lensPart->setVisible(true);
+            this->attach(lensPart);
+            this->billboards_.push_back(lensPart);
+        }
+    }
+
+    /**
+    @brief
+        This function updates the states of all the billboards, i.e. their positions, visibilty and dimensions
+    @param viewDirection
+        normalised vector pointing from the current camera to the point light center
+    @param dimension
+        the current dimension of the main billboard, we're always using square billboards
+    @param lightIsVisible
+        is the (point-)light source currently visible
+    */
+    void LensFlare::updateBillboardStates(const Vector3& viewDirection, float dimension, bool lightIsVisible)
+    { 
+        this->occlusionBillboard_->setDefaultDimensions(dimension * 0.5f, dimension * 0.5f);
+        this->occlusionBillboard_->setVisible(lightIsVisible);
+
+        int i = 0;
+        for (Billboard* billboard : this->billboards_)
+        {
+            const LensFlare::Lens& lens = lensConfiguration_.at(i);
+            billboard->setPosition(-viewDirection * (1.0f - lens.position_));
+            billboard->setVisible(lightIsVisible);
+            billboard->setDefaultDimensions(dimension * lens.scale_, dimension * lens.scale_);
+            i++;
+        }
+    }
+
+    /**
+    @brief
+        This function updates the alpha values for all billboards except for the one used for Hardware Occlusion Querying
+    @param alpha
+        the new alpha value all visible billboards should use
+    */
+    void LensFlare::updateBillboardAlphas(float alpha)
+    {
+        ColourValue cur = this->colour_;
+
+        int i = 0;
+        for (Billboard* billboard : this->billboards_)
+        {
+            cur.a = alpha * lensConfiguration_.at(i).alpha_;
+            billboard->setColour(cur);
+            i++;
+        }
+    }
+    
+    /**
+    @brief
+        This function generates point samples of the main burst billboard according to the fadeResolution and returns how many of them are in the view port
+    @param dimension
+        the current dimension of the main billboard, we're always using square billboards
+    @return
+        the absolute amount of point samples that are currently captured by the camera of the view port
+    */
+    unsigned int LensFlare::getPointCount(float dimension) const
+    {
+        Ogre::Camera* camera = CameraManager::getInstance().getActiveCamera()->getOgreCamera();
+        Vector3 position = this->getWorldPosition();
+        Vector3 nX = camera->getDerivedOrientation().xAxis().normalisedCopy();
+        Vector3 nY = camera->getDerivedOrientation().yAxis().normalisedCopy();
+        int halfRes = fadeResolution_ / 2;
+        float resDim = dimension / fadeResolution_;
+        unsigned int count = 0;
+        for (int i = -halfRes; i <= halfRes; i++)
+        {
+            for (int j = -halfRes; j <= halfRes; j++)
+            {
+                Vector3 point = position + (i*resDim) * nX + (j*resDim) * nY;//generate point samples
+                if (camera->isVisible(point))
+                {
+                    count++;
+                }
+            }
+        }
+        return count;
+    }
+
+    void LensFlare::tick(float dt)
+    {
+        if(this->isVisible())
+        {
+            // get the current distance of the lensflare center from the camera
+            Ogre::Camera* camera = CameraManager::getInstance().getActiveCamera()->getOgreCamera(); //get active Ogre Camera Instance, so we can check whether the light source is visible
+            float cameraDistance = camera->getDerivedPosition().distance(this->getPosition());
+            float dimension = cameraDistance * this->scale_;
+            if (!this->fadeOnViewBorder_)
+            {
+                this->fadeResolution_ = 3;//this is so we can still determine when the billboard has left the screen
+            }
+            unsigned int pointCount = this->getPointCount(dimension * 0.25f * this->scale_);
+            Vector3 viewDirection = this->getWorldPosition() - camera->getDerivedPosition() - camera->getDerivedDirection() * cameraDistance;
+            this->updateBillboardStates(viewDirection, dimension, pointCount > 0);
+            if (pointCount > 0)
+            {
+                Ogre::Sphere sphere(this->getPosition(), dimension * 0.25f * this->scale_);
+                float left, right, top, bottom;
+                camera->projectSphere(sphere, &left, &top, &right, &bottom);//approximate maximum pixel count of billboard with a sphere
+                
+                Ogre::RenderWindow* window = GraphicsManager::getInstance().getRenderWindow();
+                float maxCount = (right - left) * (top - bottom) * window->getWidth() * window->getHeight() * 0.25f;
+                unsigned int pixelCount = this->getScene()->getRenderQueueListener()->getPixelCount();//get pixel count
+                float ratio = (maxCount < 0.0f) ? 0.0f : (1.0f * pixelCount / maxCount);//prevent underflow and division by zero
+                float borderRatio = 1.0f;
+                if (this->fadeOnViewBorder_)
+                {
+                    borderRatio = ((float) pointCount) / (((float) fadeResolution_) * ((float) fadeResolution_));//ratio for the border fade
+                }
+                //update alpha values of all billboards except the HOQ billboard
+                this->updateBillboardAlphas(std::min(1.0f, std::pow(std::min(ratio, borderRatio), this->fadeExponent_)));
+            }
+        }
+    }
+
+    void LensFlare::changedVisibility()
+    {
+      
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/LensFlare.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/LensFlare.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/LensFlare.h	(revision 11817)
@@ -0,0 +1,191 @@
+ /*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      David 'davidsa' Salvisberg
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+  @file LensFlare.h
+  @brief Definition of the LensFlare class.
+*/
+
+#ifndef _LensFlare_H__
+#define _LensFlare_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "OgreBillboardSet.h"
+
+#include "core/GraphicsManager.h"
+#include "util/Math.h"
+#include "tools/interfaces/Tickable.h"
+#include "worldentities/StaticEntity.h"
+#include "graphics/Billboard.h"
+
+namespace orxonox
+{    
+      /**
+    @brief
+        This class adds a configurable LensFlare effect by adding multiple billboards for the several components of lens flare.
+        It uses orxonox::Billboard to render this effect, the used images can be changed in lensflare.material
+
+    @author
+        David 'davidsa' Salvisberg
+    */
+    //TODO: The Hardware Occlusion only works properly for a single Flare on the screen,
+    // if we have multiple strong lights it'll become way more complicated to determine how much of every object is occluded individually
+    // there's below a 100 render queue groups, so maybe we should take turns for each object to be tested, so we only have one of the objects rendered at a time
+    // obviously we shouldn't use too many of these effects anyways, since they use a lot of processing power, so not sure whether it's worth implementing a solution that works for multiple lens flares on screen 
+    class _OrxonoxExport LensFlare : public StaticEntity, public Tickable
+    {
+          /**
+          @brief
+              This is a nested Class used to easily set properties of the different sublenses of a LensFlare effect
+          */
+          class Lens
+          {
+              public:
+                  std::string material_;//!< Which material should the Lens use, current choices include burst, bursthalo, halo1, halo2, halo3
+                  float alpha_;//!< Which base alpha value should the Lens use
+                  float scale_;//!< Which base scale should the Lens Flare have
+                  float position_;//!< This defines how far along the view direction the flare should be positioned, e.g. 0.5 would position the flare halfway between the viewer and the base burst, 0 at the camera, 1 at the burst
+                  Lens (const std::string& material, float alpha, float scale, float position)
+                  {
+                      this->material_ = material;
+                      this->alpha_ = alpha;
+                      this->scale_ = scale;
+                      this->position_ = position;
+                  }
+          };
+          
+        public:
+            LensFlare(Context* context);
+            virtual ~LensFlare();
+            
+            inline void setScale(float scale)
+                { this->scale_ = scale; }
+            inline float getScale() const
+                { return this->scale_; }
+                
+            /**
+            @brief
+                This sets the base colour of the billboards
+            @param colour
+                Vector3 containing r,g,b values
+            */
+            inline void setColour(const ColourValue& colour)
+                { this->colour_ = colour; }
+            /**
+            @brief
+                This returns the current base colour of the billboards
+            @return a Vector3 containing r,g,b values
+            */
+            inline const ColourValue& getColour() const
+                { return this->colour_; }
+                
+            /**
+            @brief
+                This sets the resolution of the out-of-screen-fade-effect
+                
+                the higher the resolution, the smoother the transition, but it will also have a greater impact on the performance
+                this happens with O(n^2) since it's a two dimensional operation.
+            @param fadeResolution
+                how many point samples should be used per axis
+                
+                note: this will always be an odd number, so the center point is included in the samples
+            */
+            inline void setFadeResolution(unsigned int fadeResolution)
+                { this->fadeResolution_ = fadeResolution > 0 ? fadeResolution : 1; }
+            /**
+            @brief
+                This returns the resolution of the out-of-screen-fade-effect
+            @return how many point samples are being used per axis
+            */
+            inline unsigned int getFadeResolution() const
+                { return this->fadeResolution_; }
+                
+            /**
+            @brief
+                This sets the exponent of the fade-out function
+            @param exponent
+                how strong should the fade-out effect be
+            */
+            inline void setFadeExponent(float exponent)
+                { this->fadeExponent_ = exponent; }
+            /**
+            @brief
+                This returns the exponent of the fade-out function
+            @return the exponent of the fade-out function
+            */
+            inline float getFadeExponent() const
+                { return this->fadeExponent_; }
+                
+            /**
+            @brief
+               Turn the out-of-screen-fade-effect on or off
+            @param fadeOnViewBorder
+                true to turn the effect on, false to turn it off
+            */
+            inline void setFadeOnViewBorder(bool fadeOnViewBorder)
+                { this->fadeOnViewBorder_ = fadeOnViewBorder; }
+            /**
+            @brief
+               Determine whether the out-of-screen-fade-effect is on or off
+            @return
+                true if the effect is on, false if it is off
+            */
+            inline bool isFadeOnViewBorder() const
+                { return this->fadeOnViewBorder_; }
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void tick(float dt) override;
+
+            virtual void changedVisibility() override;
+
+        private:
+            void registerVariables();
+            
+            void createBillboards();
+            
+            void updateBillboardStates(const Vector3& viewDirection, float dimension, bool isLightVisible);
+            
+            void updateBillboardAlphas(float alpha);
+            
+            unsigned int getPointCount(float dimension) const;
+            
+            std::vector<Lens> lensConfiguration_;//!< this stores the lensConfiguration
+            Billboard* occlusionBillboard_;//!< this is a transparent billboard used solely for the Hardware Occlusion Query
+            std::vector<Billboard*> billboards_; //!< The visible billboards
+
+            float scale_;//!< this factor is used to scale the billboard to the desired size
+            bool fadeOnViewBorder_;//!< should the effect fade out on the border of the view?
+            unsigned int fadeResolution_;//!< how many points should be sampled per axis for the screen border fade. High number => smooth fade, but uses more processing power
+            float fadeExponent_;//!< this determines how fast the flare fades away as it gets obstructed
+            ColourValue colour_;//!< this stores the base colour of the light
+    };
+}
+
+#endif /* _LensFlare_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Light.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Light.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Light.cc	(revision 11817)
@@ -0,0 +1,184 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Light.h"
+
+#include <OgreSceneManager.h>
+#include <OgreLight.h>
+
+#include "util/StringUtils.h"
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(Light);
+
+    // Be sure we don't do bad conversions
+    static_assert((int)Ogre::Light::LT_POINT       == (int)Light::Type::Point,       "check enum");
+    static_assert((int)Ogre::Light::LT_DIRECTIONAL == (int)Light::Type::Directional, "check enum");
+    static_assert((int)Ogre::Light::LT_SPOTLIGHT   == (int)Light::Type::Spotlight,   "check enum");
+
+    Light::Light(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Light);
+
+        this->light_ = nullptr;
+        this->diffuse_ = ColourValue::White;
+        this->specular_ = ColourValue::White;
+        this->type_ = Type::Point;
+        this->attenuation_ = Vector4(100000, 1, 0, 0);
+        this->spotlightRange_ = Vector3(40.0f, 30.0f, 1.0f);
+
+        if (GameMode::showsGraphics())
+        {
+            if (!this->getScene())
+                ThrowException(AbortLoading, "Can't create Light, no scene given.");
+            if (!this->getScene()->getSceneManager())
+                ThrowException(AbortLoading, "Can't create Light, no scene manager given.");
+
+            if (this->getScene() && this->getScene()->getSceneManager())
+            {
+                this->light_ = this->getScene()->getSceneManager()->createLight("Light" + getUniqueNumberString());
+                this->light_->setDirection(WorldEntity::FRONT);
+                this->attachOgreObject(this->light_);
+
+                this->updateType();
+                this->updateDiffuseColour();
+                this->updateSpecularColour();
+                this->updateAttenuation();
+                this->updateSpotlightRange();
+            }
+        }
+
+        this->registerVariables();
+    }
+
+    Light::~Light()
+    {
+        if (this->isInitialized())
+        {
+            if (this->light_ && this->getScene() && this->getScene()->getSceneManager())
+                this->getScene()->getSceneManager()->destroyLight(this->light_);
+        }
+    }
+
+    void Light::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Light, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Light, "type",           setTypeString,     getTypeString,     xmlelement, mode).defaultValues("point");
+        XMLPortParam(Light, "diffuse",        setDiffuseColour,  getDiffuseColour,  xmlelement, mode).defaultValues(ColourValue::White);
+        XMLPortParam(Light, "specular",       setSpecularColour, getSpecularColour, xmlelement, mode).defaultValues(ColourValue::White);
+        XMLPortParam(Light, "attenuation",    setAttenuation,    getAttenuation,    xmlelement, mode).defaultValues(Vector4(100000, 1, 0, 0));
+        XMLPortParam(Light, "spotlightrange", setSpotlightRange, getSpotlightRange, xmlelement, mode).defaultValues(Vector3(40.0f, 30.0f, 1.0f));
+    }
+
+    void Light::registerVariables()
+    {
+        registerVariable(this->type_,           VariableDirection::ToClient, new NetworkCallback<Light>(this, &Light::updateType));
+        registerVariable(this->diffuse_,        VariableDirection::ToClient, new NetworkCallback<Light>(this, &Light::updateDiffuseColour));
+        registerVariable(this->specular_,       VariableDirection::ToClient, new NetworkCallback<Light>(this, &Light::updateSpecularColour));
+        registerVariable(this->attenuation_,    VariableDirection::ToClient, new NetworkCallback<Light>(this, &Light::updateAttenuation));
+        registerVariable(this->spotlightRange_, VariableDirection::ToClient, new NetworkCallback<Light>(this, &Light::updateSpotlightRange));
+    }
+
+    void Light::updateDiffuseColour()
+    {
+        if (this->light_)
+            this->light_->setDiffuseColour(this->diffuse_);
+    }
+
+    void Light::updateSpecularColour()
+    {
+        if (this->light_)
+            this->light_->setSpecularColour(this->specular_);
+    }
+
+    void Light::updateAttenuation()
+    {
+        if (this->light_ && this->type_ != Type::Directional)
+            this->light_->setAttenuation(this->attenuation_.x, this->attenuation_.y, this->attenuation_.z, this->attenuation_.w);
+    }
+
+    void Light::updateSpotlightRange()
+    {
+        if (this->light_ && this->type_ == Type::Spotlight)
+            this->light_->setSpotlightRange(Degree(this->spotlightRange_.x), Degree(this->spotlightRange_.y), this->spotlightRange_.z);
+    }
+
+    void Light::setTypeString(const std::string& type)
+    {
+        if (type == "point")
+            this->setType(Type::Point);
+        else if (type == "directional")
+            this->setType(Type::Directional);
+        else if (type == "spotlight")
+            this->setType(Type::Spotlight);
+        else
+            this->setType(Type::Point);
+    }
+
+    std::string Light::getTypeString() const
+    {
+        switch (this->type_)
+        {
+            case Type::Directional:
+                return "directional";
+            case Type::Spotlight:
+                return "spotlight";
+            case Type::Point:
+            default:
+                return "point";
+        }
+    }
+
+    void Light::updateType()
+    {
+        if (this->light_)
+        {
+            this->light_->setType(static_cast<Ogre::Light::LightTypes>(this->type_));
+
+            if (this->type_ != Type::Directional)
+                this->updateAttenuation();
+            if (this->type_ == Type::Spotlight)
+                this->updateSpotlightRange();
+        }
+    }
+
+    void Light::changedVisibility()
+    {
+        SUPER(Light, changedVisibility);
+
+        if (this->light_)
+            this->light_->setVisible(this->isVisible());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Light.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Light.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Light.h	(revision 11817)
@@ -0,0 +1,154 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Light_H__
+#define _Light_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "util/Math.h"
+#include "interfaces/TeamColourable.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Light : public StaticEntity, public TeamColourable
+    {
+        public:
+            enum class Type // Copy from the Ogre enum
+            {
+                /// Point light sources give off light equally in all directions, so require only position not direction
+                Point,
+                /// Directional lights simulate parallel light beams from a distant source, hence have direction but no position
+                Directional,
+                /// Spotlights simulate a cone of light from a source so require position and direction, plus extra values for falloff
+                Spotlight
+            };
+
+        public:
+            Light(Context* context);
+            virtual ~Light();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedVisibility() override;
+
+            inline Ogre::Light* getLight()
+                { return this->light_; }
+
+            inline void setType(Light::Type type)
+                { this->type_ = type; this->updateType(); }
+            inline Light::Type getType() const
+                { return this->type_; }
+
+            inline void setDiffuseColour(const ColourValue& colour)
+                { this->diffuse_ = colour; this->updateDiffuseColour(); }
+            inline const ColourValue& getDiffuseColour() const
+                { return this->diffuse_; }
+
+            inline void setSpecularColour(const ColourValue& colour)
+                { this->specular_ = colour; this->updateSpecularColour(); }
+            inline const ColourValue& getSpecularColour() const
+                { return this->specular_; }
+
+            virtual void setTeamColour(const ColourValue& colour) override
+                { this->setDiffuseColour(colour); this->setSpecularColour(colour); }
+
+            /**
+                @brief Sets the attenuation parameters of the light source i.e. how it diminishes with distance.
+                @param attenuation The parameters of the attenuation (see description)
+
+                 - @a attenuation.x range (The absolute upper range of the light in world units)
+                 - @a attenuation.y constant (The constant factor in the attenuation formula: 1.0 means never attenuate, 0.0 is complete attenuation)
+                 - @a attenuation.z linear (The linear factor in the attenuation formula: 1 means attenuate evenly over the distance)
+                 - @a attenuation.w quadratic (The quadratic factor in the attenuation formula: adds a curvature to the attenuation formula)
+
+                Quote from the Ogre API:
+                Lights normally get fainter the further they are away. Also, each light is given a maximum range beyond which it cannot affect any objects.
+                Light attenuation is not applicable to directional lights since they have an infinite range and constant intensity.
+                This follows a standard attenuation approach - see any good 3D text for the details of what they mean since i don't have room here!
+
+                Quote from the Ogre wiki:
+                "Using these numbers, the light has 100% intensity at 0 distance, and
+                trails off to near black at a distance equal to the Range. Keep in mind
+                that most of the light falls in the first 20% of the range."
+
+                Range   Constant   Linear     Quadratic
+                3250,     1.0,     0.0014,    0.000007
+                600,      1.0,     0.007,     0.0002
+                325,      1.0,     0.014,     0.0007
+                200,      1.0,     0.022,     0.0019
+                160,      1.0,     0.027,     0.0028
+                100,      1.0,     0.045,     0.0075
+                65,       1.0,     0.07,      0.017
+                50,       1.0,     0.09,      0.032
+                32,       1.0,     0.14,      0.07
+                20,       1.0,     0.22,      0.20
+                13,       1.0,     0.35,      0.44
+                7,        1.0,     0.7,       1.8
+            */
+            inline void setAttenuation(const Vector4& attenuation)
+                { this->attenuation_ = attenuation; this->updateAttenuation(); }
+            inline const Vector4& getAttenuation() const
+                { return this->attenuation_; }
+
+            /**
+                @brief Sets the range of a spotlight, i.e. the angle of the inner and outer cones and the rate of falloff between them.
+                @param spotlightRange The parameters of the spotlight (see description)
+                
+                 - @a spotlightRange.x innerAngle (The angle covered by the bright inner cone)
+                 - @a spotlightRange.x outerAngle (The angle covered by the outer cone)
+                 - @a spotlightRange.x falloff (The rate of falloff between the inner and outer cones. 1.0 means a linear falloff, less means slower falloff, higher means faster falloff.)
+            */
+            inline void setSpotlightRange(const Vector3& spotlightRange)
+                { this->spotlightRange_ = spotlightRange; this->updateSpotlightRange(); }
+            inline const Vector3& getSpotlightRange() const
+                { return this->spotlightRange_; }
+
+        private:
+            void registerVariables();
+            void setTypeString(const std::string& type);
+            std::string getTypeString() const;
+
+            void updateType();
+            void updateDiffuseColour();
+            void updateSpecularColour();
+            void updateAttenuation();
+            void updateSpotlightRange();
+
+            Ogre::Light* light_;
+            Light::Type type_;
+            ColourValue diffuse_;
+            ColourValue specular_;
+            Vector4 attenuation_;
+            Vector3 spotlightRange_;
+    };
+}
+
+#endif /* _Light_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/MeshLodInformation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/MeshLodInformation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/MeshLodInformation.cc	(revision 11817)
@@ -0,0 +1,85 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Jan Bernegger
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MeshLodInformation.h"
+
+#include <OgreEntity.h>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(MeshLodInformation);
+
+    MeshLodInformation::MeshLodInformation(Context* context)
+    : BaseObject(context), lodLevel_(5), bEnabled_(true), numLevels_(10), reductionRate_(0.15f)
+    {
+        RegisterObject(MeshLodInformation);
+    }
+
+    MeshLodInformation::~MeshLodInformation()
+    {    }
+
+    void MeshLodInformation::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MeshLodInformation, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MeshLodInformation, "mesh", setMeshSource, getMeshSource, xmlelement, mode);
+        XMLPortParam(MeshLodInformation, "lodQuality", setLodLevel, getLodLevel, xmlelement, mode);
+        XMLPortParam(MeshLodInformation, "enabled", setEnabled, getEnabled, xmlelement, mode);
+        XMLPortParam(MeshLodInformation, "numLevels", setNumLevels, getNumLevels, xmlelement, mode);
+        XMLPortParam(MeshLodInformation, "reductionRate", setReductionRate, getReductionRate, xmlelement, mode);
+    }
+
+    std::string MeshLodInformation::getMeshName()
+    {
+        return MeshLodInformation::getMeshSource();
+    }
+
+    void MeshLodInformation::setLodLevel(float lodLevel)
+    {
+        if(lodLevel>=0)
+            lodLevel_=lodLevel;
+    }
+    float MeshLodInformation::getLodLevel()
+    {
+        return lodLevel_;
+    }
+    void MeshLodInformation::setMeshSource(std::string meshSource)
+    {
+        meshSource_ = meshSource;
+    }
+    std::string MeshLodInformation::getMeshSource()
+    {
+        return meshSource_;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/MeshLodInformation.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/MeshLodInformation.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/MeshLodInformation.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Jan Bernegger
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MeshLodInformation_H__
+#define _MeshLodInformation_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "tools/Mesh.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport MeshLodInformation : public BaseObject
+    {
+        public:
+            MeshLodInformation(Context* context);
+            virtual ~MeshLodInformation();
+
+            float getLodLevel();
+            std::string getMeshName();
+            bool getEnabled(){ return this->bEnabled_; }
+            unsigned int getNumLevels(){ return this->numLevels_; }
+            float getReductionRate(){ return this->reductionRate_; }
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        private:
+            void setLodLevel(float lodLevel);
+            void setMeshSource(std::string meshSource);
+            void setEnabled( bool enabled ){ this->bEnabled_ = enabled; }
+            void setNumLevels( unsigned int num ){ this->numLevels_ = num; }
+            void setReductionRate( float rate ){ this->reductionRate_ = rate; }
+            std::string getMeshSource();
+            std::string meshSource_;
+            float lodLevel_;
+            bool bEnabled_;
+            unsigned int numLevels_;
+            float reductionRate_;
+
+    };
+}
+
+#endif /* _MeshLodInformation_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Model.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Model.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Model.cc	(revision 11817)
@@ -0,0 +1,272 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Model.h"
+
+#include <OgreEntity.h>
+#include <OgreProgressiveMesh.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+#include "RenderQueueListener.h"
+#include "graphics/MeshLodInformation.h"
+#include "Level.h"
+
+namespace orxonox
+{
+    RegisterClass(Model);
+
+    Model::Model(Context* context) :
+        StaticEntity(context), bCastShadows_(true), renderQueueGroup_(RENDER_QUEUE_MAIN), lodLevel_(5), bLodEnabled_(true), numLodLevels_(10), lodReductionRate_(.15f)
+    {
+        RegisterObject(Model);
+
+        this->setConfigValues();
+        this->registerVariables();
+    }
+
+    Model::~Model()
+    {
+        if (this->isInitialized() && this->mesh_.getEntity())
+            this->detachOgreObject(this->mesh_.getEntity());
+    }
+
+    void Model::setConfigValues()
+    {
+        SetConfigValueExternal(bGlobalEnableLod_, "GraphicsSettings", "enableMeshLoD", true)
+            .description("Enable level of detail for models");
+    }
+
+    void Model::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Model, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Model, "lodLevel", setLodLevel, getLodLevel, xmlelement, mode);
+
+        XMLPortParam(Model, "mesh", setMeshSource, getMeshSource, xmlelement, mode);
+        XMLPortParam(Model, "renderQueueGroup", setRenderQueueGroup, getRenderQueueGroup, xmlelement, mode);
+        XMLPortParam(Model, "material", setMaterial, getMaterial, xmlelement, mode);
+        XMLPortParam(Model, "shadow", setCastShadows, getCastShadows, xmlelement, mode).defaultValues(true);
+    }
+    
+    /**
+    @brief
+        This function turns a string from XML Port into a usable ID for the rendering system
+        It defaults to the main queue if the group isn't recognized.
+        
+    @param renderQueueGroup
+        This is a string representing the render queue group. Accepted values:
+        'main', 'stencil glow', 'stencil object'
+    */
+    const unsigned int Model::getRenderQueueGroupID(const std::string& renderQueueGroup) const
+    {
+        if(renderQueueGroup.compare("stencil glow")==0)
+        {
+            return RENDER_QUEUE_STENCIL_GLOW;
+        }
+        if(renderQueueGroup.compare("stencil object")==0)
+        {
+            return RENDER_QUEUE_STENCIL_OBJECTS;
+        }
+        return RENDER_QUEUE_MAIN;
+    }
+
+    void Model::registerVariables()
+    {
+        registerVariable(this->meshSrc_,    VariableDirection::ToClient, new NetworkCallback<Model>(this, &Model::changedMesh));
+        registerVariable(this->renderQueueGroup_,    VariableDirection::ToClient, new NetworkCallback<Model>(this, &Model::changedRenderQueueGroup));
+        registerVariable(this->materialName_,    VariableDirection::ToClient, new NetworkCallback<Model>(this, &Model::changedMaterial));
+        registerVariable(this->bCastShadows_, VariableDirection::ToClient, new NetworkCallback<Model>(this, &Model::changedShadows));
+    }
+
+    float Model::getBiggestScale(Vector3 scale3d)
+    {
+        float scaleFactor = scale3d.x;
+        if(scale3d.y>scaleFactor)
+            scaleFactor = scale3d.y;
+        if(scale3d.z>scaleFactor)
+            scaleFactor = scale3d.z;
+        return scaleFactor;
+    }
+
+    void Model::changedMesh()
+    {
+        if (GameMode::showsGraphics())
+        {
+            if (this->mesh_.getEntity())
+                this->detachOgreObject(this->mesh_.getEntity());
+
+            this->mesh_.setMeshSource(this->getScene()->getSceneManager(), this->meshSrc_);
+
+            if (this->mesh_.getEntity())
+            {
+                this->attachOgreObject(this->mesh_.getEntity());
+                this->mesh_.getEntity()->setCastShadows(this->bCastShadows_);
+                this->mesh_.getEntity()->setRenderQueueGroup(this->renderQueueGroup_);
+                this->mesh_.setVisible(this->isVisible());
+
+                if (this->bGlobalEnableLod_)
+                    this->enableLod();
+            }
+        }
+    }
+
+    void Model::changedRenderQueueGroup()
+    {
+        if (GameMode::showsGraphics())
+        {
+            if (this->mesh_.getEntity())
+            {
+                this->mesh_.getEntity()->setRenderQueueGroup(this->renderQueueGroup_);
+            }
+        }
+    }
+
+    void Model::changedMaterial()
+    {
+        this->mesh_.setMaterial(this->materialName_);
+    }
+
+    // PRE: a valid  Ogre::Entity* entity with a valid subentity at index
+    // POST: changed material of subentity at index to name
+    void Model::setSubMaterial(const std::string& name, const int index){
+        this->mesh_.setSubMaterial(name, index);
+    }
+
+
+    void Model::changedShadows()
+    {
+        this->mesh_.setCastShadows(this->bCastShadows_);
+    }
+
+    void Model::changedVisibility()
+    {
+        SUPER(Model, changedVisibility);
+
+        this->mesh_.setVisible(this->isVisible());
+    }
+
+    void Model::enableLod()
+    {
+#if defined(ORXONOX_COMPILER_MSVC) && OGRE_VERSION >= 0x010800 && OGRE_VERSION < 0x010900
+        // disable LOD for MSVC and ogre version 1.8 because it leads to crashes
+#else
+        //LOD
+        if( this->mesh_.getEntity()->getMesh()->getNumLodLevels()==1 )
+        {
+            Level* level = this->getLevel();
+
+            assert( level != nullptr );
+
+            MeshLodInformation* lodInfo = level->getLodInfo(this->meshSrc_);
+            if( lodInfo )
+            {
+                setLodLevel(lodInfo->getLodLevel());
+                this->bLodEnabled_ = lodInfo->getEnabled();
+                this->numLodLevels_ = lodInfo->getNumLevels();
+                this->lodReductionRate_ = lodInfo->getReductionRate();
+            }
+            if( this->numLodLevels_>10 )
+            {
+                orxout(internal_warning, context::lod) << "More than 10 LoD levels requested. Creating only 10." << endl;
+                this->numLodLevels_ = 10;
+            }
+            if( this->bLodEnabled_ )
+            {
+                float volume = this->mesh_.getEntity()->getBoundingBox().volume();
+/*
+                float scaleFactor = 1;
+
+                BaseObject* creatorPtr = this;
+
+                while(creatorPtr!=nullptr&&orxonox_cast<WorldEntity*>(creatorPtr))
+                {
+                    scaleFactor *= getBiggestScale(((WorldEntity*) creatorPtr)->getScale3D());
+                    creatorPtr = creatorPtr->getCreator();
+                }
+                orxout() << "name: " << this->meshSrc_ << "scaleFactor: " << scaleFactor << ", volume: " << volume << endl;
+*/
+                orxout(verbose, context::lod) << "Setting lodLevel for " << this->meshSrc_<< " with lodLevel_: " << this->lodLevel_ <<" and volume: "<< volume << ":" << endl;
+
+#if OGRE_VERSION >= 0x010800
+                Ogre::ProgressiveMesh::LodValueList distList;
+#elif OGRE_VERSION >= 0x010700
+                Ogre::Mesh::LodValueList distList;
+#else
+                Ogre::Mesh::LodDistanceList distList;
+#endif
+
+                if( lodLevel_>0 )
+                {
+//                    float factor = scaleFactor*5/lodLevel_;
+                    float factor = pow(volume, 2.0f / 3.0f) * 15.0f / lodLevel_;
+
+                    orxout(verbose, context::lod) << "LodLevel set with factor: " << factor << endl;
+
+                    distList.push_back(70.0f*factor);
+                    distList.push_back(140.0f*factor);
+                    distList.push_back(170.0f*factor);
+                    distList.push_back(200.0f*factor);
+                    distList.push_back(230.0f*factor);
+                    distList.push_back(250.0f*factor);
+                    distList.push_back(270.0f*factor);
+                    distList.push_back(290.0f*factor);
+                    distList.push_back(310.0f*factor);
+                    distList.push_back(330.0f*factor);
+                    while(distList.size()>this->numLodLevels_)
+                        distList.pop_back();
+
+
+                    //Generiert LOD-Levels
+#if OGRE_VERSION >= 0x010800
+                    Ogre::ProgressiveMesh::generateLodLevels(this->mesh_.getEntity()->getMesh().get(), distList, Ogre::ProgressiveMesh::VRQ_PROPORTIONAL,
+                        this->lodReductionRate_);
+#else
+                    this->mesh_.getEntity()->getMesh()->generateLodLevels(distList, Ogre::ProgressiveMesh::VRQ_PROPORTIONAL, this->lodReductionRate_);
+#endif
+                }
+                else
+                {
+                    std::string what;
+                    if(lodLevel_>5)
+                        what = ">5";
+                    else
+                        what = "<0";
+
+                    orxout(verbose, context::lod) << "LodLevel not set because lodLevel(" << lodLevel_ << ") was " << what << "." << endl;
+                }
+            }
+            else
+                orxout(verbose, context::lod) << "LodLevel for " << this->meshSrc_ << " not set because is disabled." << endl;
+        }
+#endif
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/Model.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/Model.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/Model.h	(revision 11817)
@@ -0,0 +1,133 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+  @file Model.h
+  @brief Definition of Model Class
+*/
+
+#ifndef _Model_H__
+#define _Model_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "tools/Mesh.h"
+#include "RenderQueueListener.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Model : public StaticEntity
+    {
+        /**
+        @brief
+            The class Model stores a Mesh and some additional properties, so you can easily render any Model and apply different effects to it.
+            
+            You can assign any Material to any Mesh to completely change the way it looks, to further add versatility you can also assign the Model
+            to a render queue group, to enable proper rendering of fancy effect like glowing edges around objects with alpha blending.
+        */
+        public:
+            Model(Context* context);
+            virtual ~Model();
+
+            void setConfigValues();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedVisibility() override;
+
+            inline const Mesh& getMesh() const
+                { return this->mesh_; }
+
+            inline void setMeshSource(const std::string& meshname)
+                { this->meshSrc_ = meshname; this->changedMesh(); }
+            inline const std::string& getMeshSource() const
+                { return this->meshSrc_; }
+
+            inline void setRenderQueueGroup(const std::string& renderQueueGroup)
+                { this->renderQueueGroup_ = getRenderQueueGroupID(renderQueueGroup); this->changedRenderQueueGroup(); }
+            inline const int getRenderQueueGroup() const
+                { return this->renderQueueGroup_; }
+
+            inline void setCastShadows(bool bCastShadows)
+                { this->bCastShadows_ = bCastShadows; this->changedShadows(); }
+            inline bool getCastShadows() const
+                { return this->bCastShadows_; }
+
+            inline void setMaterial(const std::string& materialname)
+                { this->materialName_ = materialname; this->changedMaterial(); }
+            inline const std::string& getMaterial() const
+                { return this->materialName_; }
+
+            void setSubMaterial(const std::string& name, const int index);
+
+        protected:
+            /**
+            @brief
+                This function turns a string from XML Port into a usable ID for the rendering system
+                It defaults to the main queue if the group isn't recognized.
+                
+            @param renderQueueGroup
+                This is a string representing the render queue group. Accepted values:
+                main, stencil glow, stencil object
+            */
+            const unsigned int getRenderQueueGroupID(const std::string& renderQueueGroup) const;
+
+            void registerVariables();
+            void changedMesh();
+            void changedRenderQueueGroup();
+            void changedMaterial();
+            void changedShadows();
+
+            //LoD
+            void enableLod();
+
+            inline void setLodLevel(float lodLevel)
+                { this->lodLevel_ =  lodLevel; }
+            inline float getLodLevel() const
+                { return this->lodLevel_; }
+            float getBiggestScale(Vector3 scale3d);
+
+            std::string meshSrc_; //!< This string stores the path where the mesh is stored
+            Mesh mesh_; //!< This is the mesh object linked to this Object, it stores the data from the mesh file in a usable format for the Ogre engine
+            bool bCastShadows_; //!< This value determines whether a Model is casting a shadow or not, turn it off to save performance, when not needed
+            unsigned int renderQueueGroup_; //!< This variable stores which render queue group this object is assigned to
+            std::string materialName_; //!< This string stores the name of the material to be applied to the mesh/model
+
+            //LoD
+            bool bGlobalEnableLod_; //!< Has LoD been turned on in the graphics configuration?
+            float lodLevel_; //!< Standard LoD Level
+            bool bLodEnabled_; //!< Is LoD to be used on this model?
+            unsigned int numLodLevels_; //!< How many LoD does this model feature
+            float lodReductionRate_; //!< How fast should be switched to lower LoDs
+
+    };
+}
+
+#endif /* _Model_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleEmitter.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleEmitter.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleEmitter.cc	(revision 11817)
@@ -0,0 +1,129 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+* @file
+* @brief class to control praticle effects
+*/
+
+#include "ParticleEmitter.h"
+
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "tools/ParticleInterface.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(ParticleEmitter);
+
+    ParticleEmitter::ParticleEmitter(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(ParticleEmitter);
+
+        if (GameMode::showsGraphics() && (!this->getScene() || !this->getScene()->getSceneManager()))
+            ThrowException(AbortLoading, "Can't create ParticleEmitter, no scene or no scene manager given.");
+
+        this->particles_ = nullptr;
+        this->LOD_ = LODParticle::Normal;
+
+        this->registerVariables();
+    }
+
+    ParticleEmitter::~ParticleEmitter()
+    {
+        if (this->isInitialized() && this->particles_)
+        {
+            this->detachOgreObject(this->particles_->getParticleSystem());
+            delete this->particles_;
+        }
+    }
+
+    void ParticleEmitter::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ParticleEmitter, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ParticleEmitter, "lod",    setLODxml, getLODxml, xmlelement, mode).defaultValues(static_cast<unsigned int>(LODParticle::Normal));
+        XMLPortParam(ParticleEmitter, "source", setSource, getSource, xmlelement, mode);
+    }
+
+    void ParticleEmitter::registerVariables()
+    {
+        registerVariable(this->source_, VariableDirection::ToClient, new NetworkCallback<ParticleEmitter>(this, &ParticleEmitter::sourceChanged));
+        registerVariable((int&)(this->LOD_),    VariableDirection::ToClient, new NetworkCallback<ParticleEmitter>(this, &ParticleEmitter::LODchanged));
+    }
+
+    void ParticleEmitter::changedVisibility()
+    {
+        SUPER(ParticleEmitter, changedVisibility);
+
+        if (this->particles_)
+            this->particles_->setVisible(this->isVisible());
+    }
+
+    void ParticleEmitter::changedActivity()
+    {
+        SUPER(ParticleEmitter, changedActivity);
+
+        if (this->particles_)
+            this->particles_->setEnabled(this->isActive());
+    }
+
+    void ParticleEmitter::sourceChanged()
+    {
+        if (this->particles_)
+        {
+            delete this->particles_;
+            this->particles_ = nullptr;
+        }
+
+        if (GameMode::showsGraphics() && this->getScene() && this->getScene()->getSceneManager())
+        {
+            try
+            {
+                this->particles_ = new ParticleInterface(this->getScene()->getSceneManager(), this->source_, this->LOD_);
+                this->attachOgreObject(this->particles_->getParticleSystem());
+                this->particles_->setVisible(this->isVisible());
+                this->particles_->setEnabled(this->isActive());
+            }
+            catch (const std::exception& ex)
+            {
+                orxout(internal_error) << "Couldn't load particle effect \"" << this->source_ << "\" because:" << endl
+                                       << ex.what() << endl;
+            }
+        }
+    }
+
+    void ParticleEmitter::LODchanged()
+    {
+        if (this->particles_)
+            this->particles_->setDetailLevel(this->LOD_);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleEmitter.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleEmitter.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleEmitter.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ParticleEmitter_H__
+#define _ParticleEmitter_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport ParticleEmitter : public StaticEntity
+    {
+        public:
+            ParticleEmitter(Context* context);
+            virtual ~ParticleEmitter();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedVisibility() override;
+            virtual void changedActivity() override;
+
+            inline ParticleInterface* getParticleInterface() const
+                { return this->particles_; }
+
+            inline void setSource(const std::string& source)
+                { this->source_ = source; this->sourceChanged(); }
+            inline const std::string& getSource() const
+                { return this->source_; }
+
+            inline void setLOD(LODParticle::Value level)
+                { this->LOD_ = level; this->LODchanged(); }
+            inline LODParticle::Value getLOD() const
+                { return this->LOD_; }
+
+        protected:
+            inline void setLODxml(unsigned int level)
+                { this->LOD_ = static_cast<LODParticle::Value>(level); this->LODchanged(); }
+            inline unsigned int getLODxml() const
+                { return static_cast<unsigned int>(this->LOD_); }
+
+            void sourceChanged();
+            void LODchanged();
+
+            ParticleInterface* particles_;
+            std::string        source_;
+            LODParticle::Value   LOD_;
+
+        private:
+            void registerVariables();
+    };
+}
+
+#endif /* _ParticleEmitter_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleSpawner.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleSpawner.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleSpawner.cc	(revision 11817)
@@ -0,0 +1,130 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ParticleSpawner.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+#include "core/command/Executor.h"
+#include "tools/ParticleInterface.h"
+
+namespace orxonox
+{
+    RegisterClass(ParticleSpawner);
+
+    ParticleSpawner::ParticleSpawner(Context* context) : ParticleEmitter(context)
+    {
+        RegisterObject(ParticleSpawner);
+
+        this->bAutostart_ = true;
+        this->bSuppressStart_ = false;
+        this->bAutoDestroy_ = true;
+        this->bForceDestroy_ = false;
+        this->bLoop_ = false;
+        this->startdelay_ = 0;
+        this->lifetime_ = 0;
+        this->destroydelay_ = 0;
+
+        this->startParticleSpawner();
+    }
+
+    ParticleSpawner::~ParticleSpawner()
+    {
+    }
+
+    void ParticleSpawner::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ParticleSpawner, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ParticleSpawner, "autostart",    setAutoStart,        getAutoStart,        xmlelement, mode).defaultValues(true);
+        XMLPortParam(ParticleSpawner, "autodestroy",  setDestroyAfterLife, getDestroyAfterLife, xmlelement, mode).defaultValues(false);
+        XMLPortParam(ParticleSpawner, "loop",         setLoop,             getLoop,             xmlelement, mode).defaultValues(false);
+        XMLPortParam(ParticleSpawner, "lifetime",     setLifetime,         getLifetime,         xmlelement, mode).defaultValues(0.0f);
+        XMLPortParam(ParticleSpawner, "startdelay",   setStartdelay,       getStartdelay,       xmlelement, mode).defaultValues(0.0f);
+        XMLPortParam(ParticleSpawner, "destroydelay", setDestroydelay,     getDestroydelay,     xmlelement, mode).defaultValues(0.0f);
+    }
+
+    void ParticleSpawner::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ParticleSpawner, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(ParticleSpawner, BaseObject, "spawn", spawn, xmlelement, mode);
+    }
+
+    void ParticleSpawner::configure(float lifetime, float startdelay, float destroydelay, bool autodestroy)
+    {
+        this->bAutoDestroy_ = autodestroy;
+        this->startdelay_ = startdelay;
+        this->lifetime_ = lifetime;
+        this->destroydelay_ = destroydelay;
+    }
+
+    void ParticleSpawner::startParticleSpawner()
+    {
+        this->setActive(false);
+
+        if (this->bForceDestroy_ || this->bSuppressStart_)
+        {
+            this->timer_.stopTimer();
+            return;
+        }
+
+        this->timer_.setTimer(this->startdelay_, false, createExecutor(createFunctor(&ParticleSpawner::fireParticleSpawner, this)));
+    }
+
+    void ParticleSpawner::fireParticleSpawner()
+    {
+        this->setActive(true);
+        if (this->lifetime_ != 0)
+            this->timer_.setTimer(this->lifetime_, false, createExecutor(createFunctor(&ParticleSpawner::stopParticleSpawner, this)));
+    }
+
+    void ParticleSpawner::stopParticleSpawner()
+    {
+        this->setActive(false);
+
+        if (this->bAutoDestroy_ || this->bForceDestroy_)
+        {
+            this->setPosition(this->getWorldPosition());
+            this->detachFromParent();
+
+            if (!this->timer_.isActive() || this->timer_.getRemainingTime() > this->destroydelay_)
+                this->timer_.setTimer(this->destroydelay_, false, createExecutor(createFunctor(&ParticleSpawner::destroyParticleSpawner, this)));
+        }
+        else if (this->bLoop_)
+        {
+            this->timer_.setTimer(this->destroydelay_, false, createExecutor(createFunctor(&ParticleSpawner::startParticleSpawner, this)));
+        }
+    }
+
+    void ParticleSpawner::destroyParticleSpawner()
+    {
+        this->destroy();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleSpawner.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleSpawner.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/graphics/ParticleSpawner.h	(revision 11817)
@@ -0,0 +1,104 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ParticleSpawner_H__
+#define _ParticleSpawner_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "tools/Timer.h"
+#include "ParticleEmitter.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport ParticleSpawner : public ParticleEmitter
+    {
+        public:
+            ParticleSpawner(Context* context);
+            virtual ~ParticleSpawner();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void stop(bool bDestroy)
+                { this->bForceDestroy_ = bDestroy; this->stopParticleSpawner(); }
+            inline void spawn()
+                { this->bSuppressStart_ = false; this->startParticleSpawner(); }
+
+            void configure(float lifetime = 0, float startdelay = 0, float destroydelay = 0, bool autodestroy = true);
+
+            inline void setAutoStart(bool autostart)
+                { this->bAutostart_ = autostart; this->bSuppressStart_ = !autostart; }
+            inline bool getAutoStart() const
+                { return this->bAutostart_; }
+
+            inline void setDestroyAfterLife(bool destroy)
+                { this->bAutoDestroy_ = destroy; }
+            inline bool getDestroyAfterLife() const
+                { return this->bAutoDestroy_; }
+
+            inline void setLoop(bool loop)
+                { this->bLoop_ = loop; }
+            inline bool getLoop() const
+                { return this->bLoop_; }
+
+            inline void setLifetime(float lifetime)
+                { this->lifetime_ = lifetime; this->startParticleSpawner(); }
+            inline float getLifetime() const
+                { return this->lifetime_; }
+
+            inline void setStartdelay(float startdelay)
+                { this->startdelay_ = startdelay; this->startParticleSpawner(); }
+            inline float getStartdelay() const
+                { return this->startdelay_; }
+
+            inline void setDestroydelay(float destroydelay)
+                { this->destroydelay_ = destroydelay; this->startParticleSpawner(); }
+            inline float getDestroydelay() const
+                { return this->destroydelay_; }
+
+        private:
+            void startParticleSpawner();
+            void fireParticleSpawner();
+            void stopParticleSpawner();
+            void destroyParticleSpawner();
+
+            Timer timer_;
+
+            bool  bSuppressStart_;
+            bool  bAutostart_;
+            bool  bForceDestroy_;
+            bool  bAutoDestroy_;
+            bool  bLoop_;
+            float startdelay_;
+            float lifetime_;
+            float destroydelay_;
+    };
+}
+
+#endif /* _ParticleSpawner_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/Bot.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/Bot.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/Bot.cc	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Bot.h"
+
+#include "util/Math.h"
+#include "core/GameMode.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "gametypes/Gametype.h"
+#include "controllers/AIController.h"
+
+namespace orxonox
+{
+    RegisterClass(Bot);
+
+    Bot::Bot(Context* context) : PlayerInfo(context)
+    {
+        RegisterObject(Bot);
+
+        this->bHumanPlayer_ = false;
+        this->bLocalPlayer_ = GameMode::isMaster();
+        this->bSetUnreadyAfterSpawn_ = false;
+        this->setReadyToSpawn(true);
+        this->defaultController_ = Class(AIController);
+
+        this->setConfigValues();
+
+        this->setName(this->names_[static_cast<size_t>(rnd() * this->names_.size())]);
+
+        if (this->getGametype())
+            this->getGametype()->playerEntered(this);
+
+        this->createController();
+    }
+
+    Bot::~Bot()
+    {
+    }
+
+    void Bot::setConfigValues()
+    {
+        static const std::string names[] =
+        {
+            "Dr. Julius No",
+            "Rosa Klebb",
+            "Auric Goldfinger",
+            "Emilio Largo",
+            "Ernst Stavro Blofeld",
+            "Dr. Kananga",
+            "Francisco Scaramanga",
+            "Karl Stromberg",
+            "Sir Hugo Drax",
+            "Aris Kristatos",
+            "Kamal Khan",
+            "General Orlov",
+            "Max Zorin",
+            "Brad Whitaker",
+            "General Georgi Koskov",
+            "Franz Sanchez",
+            "Alec Trevelyan",
+            "Elliot Carver",
+            "Elektra King",
+            "Viktor Zokas",
+            "Gustav Graves",
+            "Le Chiffre",
+            "Mr. White",
+            "Dominic Greene",
+            "Berkay Berabi",
+            "Louis  Meile",
+            "Muten Roshi",
+            "Abradolf Lincler",
+            "Lionel Messi",
+            "Karl the Llama",
+            "Thomas the Tankengine",
+            "Rick",
+            "Morty",
+            "Charlie the Unicorn",
+            "Kung Fury",
+            "Postman Pat"
+        };
+        static std::vector<std::string> defaultnames(names, names + sizeof(names) / sizeof(std::string));
+
+        SetConfigValue(names_, defaultnames);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/Bot.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/Bot.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/Bot.h	(revision 11817)
@@ -0,0 +1,59 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Bot_H__
+#define _Bot_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <vector>
+#include "PlayerInfo.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Bot : public PlayerInfo
+    {
+        public:
+            Bot(Context* context);
+            virtual ~Bot();
+
+            void setConfigValues();
+
+            virtual inline bool isInitialized() const override
+                { return true; }
+            virtual inline float getPing() const override
+                { return 0; }
+            virtual inline float getPacketLossRatio() const override
+                { return 0; }
+
+        private:
+            std::vector<std::string> names_;
+    };
+}
+
+#endif /* _Bot_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,7 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  Bot.cc
+  Info.cc
+  PlayerInfo.cc
+  HumanPlayer.cc
+  GametypeInfo.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/GametypeInfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/GametypeInfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/GametypeInfo.cc	(revision 11817)
@@ -0,0 +1,490 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file GametypeInfo.cc
+    @brief Implementation of the GametypeInfo class
+*/
+
+#include "GametypeInfo.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "network/Host.h"
+#include "network/NetworkFunctionIncludes.h"
+#include "util/Convert.h"
+
+#include "controllers/HumanController.h"
+#include "interfaces/GametypeMessageListener.h"
+#include "interfaces/NotificationListener.h"
+
+#include "PlayerInfo.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(GametypeInfo);
+
+    registerMemberNetworkFunction(GametypeInfo, dispatchAnnounceMessage);
+    registerMemberNetworkFunction(GametypeInfo, dispatchKillMessage);
+    registerMemberNetworkFunction(GametypeInfo, dispatchDeathMessage);
+    registerMemberNetworkFunction(GametypeInfo, dispatchStaticMessage);
+    registerMemberNetworkFunction(GametypeInfo, dispatchFadingMessage);
+
+    registerMemberNetworkFunction(GametypeInfo, changedReadyToSpawn);
+    registerMemberNetworkFunction(GametypeInfo, changedSpawned);
+
+    /*static*/ const std::string GametypeInfo::NOTIFICATION_SENDER("gameinfo");
+
+    /**
+    @brief
+        Registers and initializes the object.
+    */
+    GametypeInfo::GametypeInfo(Context* context) : Info(context)
+    {
+        RegisterObject(GametypeInfo);
+
+        this->bStarted_ = false;
+        this->bEnded_ = false;
+        this->startCountdown_ = 10.0f;
+        this->bStartCountdownRunning_ = false;
+        this->counter_ = 10;
+        this->spawned_ = false;
+        this->readyToSpawn_ = false;
+
+        this->registerVariables();
+    }
+
+    GametypeInfo::~GametypeInfo()
+    {
+    }
+
+    void GametypeInfo::registerVariables()
+    {
+        registerVariable(this->bStarted_,               VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedStarted));
+        registerVariable(this->bEnded_,                 VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedEnded));
+        registerVariable(this->bStartCountdownRunning_, VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedStartCountdownRunning));
+        registerVariable(this->startCountdown_,         VariableDirection::ToClient);
+        registerVariable(this->counter_,                VariableDirection::ToClient, new NetworkCallback<GametypeInfo>(this, &GametypeInfo::changedCountdownCounter));
+        registerVariable(this->hudtemplate_,            VariableDirection::ToClient);
+    }
+
+    /**
+    @brief
+        Is called when the game has changed to started.
+    */
+    void GametypeInfo::changedStarted(void)
+    {
+        NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the game has changed to ended.
+    */
+    void GametypeInfo::changedEnded(void)
+    {
+        // If the game has ended, a "Game has ended" notification is displayed.
+        if(this->hasEnded())
+            NotificationListener::sendNotification("Game has ended", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the start countdown has been either started or stopped.
+    */
+    void GametypeInfo::changedStartCountdownRunning(void)
+    {
+        // Send first countdown notification if the countdown has started.
+        if(this->isReadyToSpawn() && !this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Is called when the start countdown counter has changed.
+    */
+    void GametypeInfo::changedCountdownCounter(void)
+    {
+        // Send countdown notification if the counter has gone down.
+        if(this->isReadyToSpawn() &&  !this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the local player has changed its ready to spawn status.
+    @param ready
+        Whether the player has become ready to spawn or not.
+    */
+    void GametypeInfo::changedReadyToSpawn(bool ready)
+    {
+        if(this->readyToSpawn_ == ready)
+            return;
+
+        this->readyToSpawn_ = ready;
+
+        // Send "Waiting for other players" if the player is ready to spawn but the game has not yet started nor is the countdown running.
+        if(this->readyToSpawn_ && !this->hasStarted() && !this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification("Waiting for other players", GametypeInfo::NOTIFICATION_SENDER);
+        // Send current countdown if the player is ready to spawn and the countdown has already started.
+        else if(this->readyToSpawn_ && !this->hasStarted() && this->isStartCountdownRunning() && !this->hasEnded())
+            NotificationListener::sendNotification(multi_cast<std::string>(this->counter_), GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the game has started.
+    */
+    void GametypeInfo::start(void)
+    {
+        if(this->bStarted_)
+           { return;}
+
+        this->bStarted_ = true;
+        this->changedStarted();
+
+
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the game has ended.
+    */
+    void GametypeInfo::end(void)
+    {
+        if(this->bEnded_)
+            return;
+
+        this->bEnded_ = true;
+        this->changedEnded();
+    }
+
+    /**
+    @brief
+        Set the start countdown to the input value.
+    @param countdown
+        The countdown to be set.
+    */
+    void GametypeInfo::setStartCountdown(float countdown)
+    {
+        if(this->startCountdown_ == countdown || countdown < 0.0f)
+            return;
+
+        this->startCountdown_ = countdown;
+        // Set the counter to the ceiling of the current countdown.
+        this->counter_ = static_cast<unsigned int>(std::ceil(countdown));
+        this->changedCountdownCounter();
+    }
+
+    /**
+    @brief
+        Count down the start countdown by the specified value.
+    @param countDown
+        The amount by which we count down.
+    */
+    void GametypeInfo::countdownStartCountdown(float countDown)
+    {
+        float newCountdown = this->startCountdown_ - countDown;
+        // If we have switched integers or arrived at zero, we also count down the start countdown counter.
+        if(ceil(newCountdown) != ceil(this->startCountdown_) || newCountdown <= 0.0f)
+            this->countDown();
+        this->startCountdown_ = newCountdown;
+    }
+
+    /**
+    @brief
+        Count down the start countdown counter.
+    */
+    void GametypeInfo::countDown()
+    {
+        if(this->counter_ == 0)
+            return;
+
+        this->counter_--;
+        this->changedCountdownCounter();
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about the start of the start countdown.
+    */
+    void GametypeInfo::startStartCountdown(void)
+    {
+        if(GameMode::isMaster())
+        {
+            if(this->bStartCountdownRunning_)
+                return;
+
+            this->bStartCountdownRunning_ = true;
+            this->changedStartCountdownRunning();
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about the stop of the start countdown.
+    */
+    void GametypeInfo::stopStartCountdown(void)
+    {
+        if(GameMode::isMaster())
+        {
+            if(!this->bStartCountdownRunning_)
+                return;
+
+            this->bStartCountdownRunning_ = false;
+            this->changedStartCountdownRunning();
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that is ready to spawn.
+    @param player
+        The player that is ready to spawn.
+    */
+    void GametypeInfo::playerReadyToSpawn(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            // If the player has spawned already.
+            if(this->spawnedPlayers_.find(player) != this->spawnedPlayers_.end())
+                return;
+
+            this->spawnedPlayers_.insert(player);
+            this->setReadyToSpawnHelper(player, true);
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player whose Pawn has been killed.
+    @param player
+        The player whose Pawn has been killed.
+    */
+    void GametypeInfo::pawnKilled(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            NotificationListener::sendNotification("Press [Fire] to respawn", GametypeInfo::NOTIFICATION_SENDER, NotificationMessageType::info, NotificationSendMode::network, player->getClientID());
+            // Remove the player from the list of players that have spawned, since it currently is not.
+            this->spawnedPlayers_.erase(player);
+            this->setReadyToSpawnHelper(player, false);
+            this->setSpawnedHelper(player, false);
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that has spawned.
+    @param player
+        The player that has spawned.
+    */
+    void GametypeInfo::playerSpawned(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            if(this->hasStarted() && !this->hasEnded())
+
+                this->setSpawnedHelper(player, true);
+        }
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo that the local player has changed its spawned status.
+    @param spawned
+        Whether the local player has changed to spawned or to not spawned.
+    */
+    void GametypeInfo::changedSpawned(bool spawned)
+    {
+        if(this->spawned_ == spawned)
+            return;
+
+        this->spawned_ = spawned;
+        // Clear the notifications if the Player has spawned.
+        if(this->spawned_ && !this->hasEnded())
+            NotificationListener::sendCommand("clear", GametypeInfo::NOTIFICATION_SENDER);
+    }
+
+    /**
+    @brief
+        Inform the GametypeInfo about a player that has entered,
+    @param player
+        The player that has entered.
+    */
+    void GametypeInfo::playerEntered(PlayerInfo* player)
+    {
+        if(GameMode::isMaster())
+        {
+            if( player->isHumanPlayer() )
+            {
+                // Display "Press [Fire] to start the match" if the game has not yet ended.
+                if(!this->hasEnded())
+                    NotificationListener::sendNotification("Press [Fire] to start the match", GametypeInfo::NOTIFICATION_SENDER, NotificationMessageType::info, NotificationSendMode::network, player->getClientID());
+                // Else display "Game has ended".
+                else
+                    NotificationListener::sendNotification("Game has ended", GametypeInfo::NOTIFICATION_SENDER, NotificationMessageType::info, NotificationSendMode::network, player->getClientID());
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Sends changedReadyToSpawn notifiers over the network.
+    @param player
+        The player that has changed its ready to spawn status.
+    @param ready
+        The new ready to spawn status.
+    */
+    void GametypeInfo::setReadyToSpawnHelper(PlayerInfo* player, bool ready)
+    {
+        if(GameMode::isMaster())
+        {
+            if(player->getClientID() == CLIENTID_SERVER)
+                this->changedReadyToSpawn(ready);
+            else
+                callMemberNetworkFunction(&GametypeInfo::changedReadyToSpawn, this->getObjectID(), player->getClientID(), ready);
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Sends changedSpawned notifiers over the network.
+    @param player
+        The player that has changed its spawned status.
+    @param spawned
+        The new spawned status.
+    */
+    void GametypeInfo::setSpawnedHelper(PlayerInfo* player, bool spawned)
+    {
+        if(GameMode::isMaster())
+        {
+            if(player->getClientID() == CLIENTID_SERVER)
+                    this->changedSpawned(spawned);
+            else
+                callMemberNetworkFunction(&GametypeInfo::changedSpawned, this->getObjectID(), player->getClientID(), spawned);
+        }
+    }
+
+    // Announce messages.
+    // TODO: Replace with notifications.
+
+    void GametypeInfo::sendAnnounceMessage(const std::string& message) const
+    {
+        if (GameMode::isMaster())
+        {
+            callMemberNetworkFunction(&GametypeInfo::dispatchAnnounceMessage, this->getObjectID(), NETWORK_PEER_ID_BROADCAST, message);
+            this->dispatchAnnounceMessage(message);
+        }
+    }
+
+    void GametypeInfo::sendAnnounceMessage(const std::string& message, unsigned int clientID) const
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID == CLIENTID_SERVER)
+                this->dispatchAnnounceMessage(message);
+            else
+                callMemberNetworkFunction(&GametypeInfo::dispatchAnnounceMessage, this->getObjectID(), clientID, message);
+        }
+    }
+
+    void GametypeInfo::sendKillMessage(const std::string& message, unsigned int clientID) const
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID == CLIENTID_SERVER)
+                this->dispatchKillMessage(message);
+            else
+                callMemberNetworkFunction(&GametypeInfo::dispatchKillMessage, this->getObjectID(), clientID, message);
+        }
+    }
+
+    void GametypeInfo::sendDeathMessage(const std::string& message, unsigned int clientID) const
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID == CLIENTID_SERVER)
+                this->dispatchDeathMessage(message);
+            else
+                callMemberNetworkFunction(&GametypeInfo::dispatchDeathMessage, this->getObjectID(), clientID, message);
+        }
+    }
+
+    void GametypeInfo::sendStaticMessage(const std::string& message, unsigned int clientID, const ColourValue& colour) const
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID == CLIENTID_SERVER)
+                this->dispatchStaticMessage(message, colour);
+            else
+                callMemberNetworkFunction(&GametypeInfo::dispatchStaticMessage, this->getObjectID(), clientID, message, colour);
+        }
+    }
+
+    void GametypeInfo::sendFadingMessage(const std::string& message, unsigned int clientID) const
+    {
+        if (GameMode::isMaster())
+        {
+            if (clientID == CLIENTID_SERVER)
+                this->dispatchFadingMessage(message);
+            else
+                callMemberNetworkFunction(&GametypeInfo::dispatchFadingMessage, this->getObjectID(), clientID, message);
+        }
+    }
+
+    void GametypeInfo::dispatchAnnounceMessage(const std::string& message) const
+    {
+        for (GametypeMessageListener* listener : ObjectList<GametypeMessageListener>())
+            listener->announcemessage(this, message);
+    }
+
+    void GametypeInfo::dispatchKillMessage(const std::string& message) const
+    {
+        for (GametypeMessageListener* listener : ObjectList<GametypeMessageListener>())
+            listener->killmessage(this, message);
+    }
+
+    void GametypeInfo::dispatchDeathMessage(const std::string& message) const
+    {
+        for (GametypeMessageListener* listener : ObjectList<GametypeMessageListener>())
+            listener->deathmessage(this, message);
+    }
+
+     void GametypeInfo::dispatchStaticMessage(const std::string& message, const ColourValue& colour) const
+    {
+        for (GametypeMessageListener* listener : ObjectList<GametypeMessageListener>())
+            listener->staticmessage(this, message, colour);
+    }
+
+     void GametypeInfo::dispatchFadingMessage(const std::string& message) const
+    {
+        for (GametypeMessageListener* listener : ObjectList<GametypeMessageListener>())
+            listener->fadingmessage(this, message);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/GametypeInfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/GametypeInfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/GametypeInfo.h	(revision 11817)
@@ -0,0 +1,171 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Damian 'Mozork' Frick
+ *
+ */
+
+/**
+    @file GametypeInfo.h
+    @brief Definition of the GametypeInfo class
+*/
+
+#ifndef _GametypeInfo_H__
+#define _GametypeInfo_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+
+#include "Info.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The GametypeInfo class keeps track of the state of the game and provides facilities to inform the player about it.
+
+    @author
+        Fabian 'x3n' Landau
+    @author
+        Damian 'Mozork' Frick
+    */
+    class _OrxonoxExport GametypeInfo : public Info
+    {
+        friend class Gametype;
+
+        public:
+            GametypeInfo(Context* context);
+            virtual ~GametypeInfo();
+
+            /**
+            @brief Get whether the game has started yet.
+            @return Returns true if the game has started, false if not.
+            */
+            inline bool hasStarted() const
+                { return this->bStarted_; }
+            void changedStarted(void); // Is called when the game has changed to started.
+
+            /**
+            @brief Get whether the game has ended yet.
+            @return Returns true if the game has ended, false if not.
+            */
+            inline bool hasEnded() const
+                { return this->bEnded_; }
+            void changedEnded(void); // Is called when the game has changed to ended.
+
+            /**
+            @brief Get whether the start countdown is currently running.
+            @return Returns true if the countdown is running, false if not.
+            */
+            inline bool isStartCountdownRunning() const
+                { return this->bStartCountdownRunning_; }
+            void changedStartCountdownRunning(void); // Is called when the start countdown has been either started or stopped.
+
+            /**
+            @brief Get the current value of the start countdown.
+            @return Returns the current value of the start countdown.
+            */
+            inline float getStartCountdown() const
+                { return this->startCountdown_; }
+
+            /**
+            @brief Get the current start countdown counter.
+                   The start countdown counter only has integer values that correspond to the actually displayed countdown.
+            @return Returns the current integer countdown counter.
+            */
+            inline unsigned int getStartCountdownCounter() const
+                { return this->counter_; }
+            void changedCountdownCounter(void); // Is called when the start countdown counter has changed.
+
+            /**
+            @brief Get whether the local player is ready to spawn.
+            @return Returns true if the player is ready to spawn, false if not.
+            */
+            inline bool isReadyToSpawn() const
+                { return this->readyToSpawn_; }
+            void changedReadyToSpawn(bool ready); // Inform the GametypeInfo that the local player has changed its spawned status.
+
+            /**
+            @brief Get whether the local player is spawned.
+            @return Returns true if the local player is currently spawned, false if not.
+            */
+            inline bool isSpawned() const
+                { return this->spawned_; }
+            void changedSpawned(bool spawned); // Inform the GametypeInfo that the local player has changed its spawned status.
+
+            inline const std::string& getHUDTemplate() const
+                { return this->hudtemplate_; }
+
+            void sendAnnounceMessage(const std::string& message) const;
+            void sendAnnounceMessage(const std::string& message, unsigned int clientID) const;
+            void sendKillMessage(const std::string& message, unsigned int clientID) const;
+            void sendDeathMessage(const std::string& message, unsigned int clientID) const;
+            void sendStaticMessage(const std::string& message, unsigned int clientID, const ColourValue& colour) const;
+            void sendFadingMessage(const std::string& message, unsigned int clientID) const;
+
+            void dispatchAnnounceMessage(const std::string& message) const;
+            void dispatchKillMessage(const std::string& message) const;
+            void dispatchDeathMessage(const std::string& message) const;
+            void dispatchStaticMessage(const std::string& message,const ColourValue& colour) const;
+            void dispatchFadingMessage(const std::string& message) const;
+
+        protected:
+            void start(void); // Inform the GametypeInfo that the game has started.
+            void end(void); // Inform the GametypeInfo that the game has ended.
+            void setStartCountdown(float countdown); // Set the start countdown to the input value.
+            void countdownStartCountdown(float countDown); // Count down the start countdown by the specified value.
+            void countDown(); // Count down the start countdown counter.
+            void startStartCountdown(void); // Inform the GametypeInfo about the start of the start countdown.
+            void stopStartCountdown(void); // Inform the GametypeInfo about the stop of the start countdown.
+            void playerReadyToSpawn(PlayerInfo* player); // Inform the GametypeInfo about a player that is ready to spawn.
+            void pawnKilled(PlayerInfo* player); // Inform the GametypeInfo about a player whose Pawn has been killed.
+            void playerSpawned(PlayerInfo* player); // Inform the GametypeInfo about a player that has spawned.
+            void playerEntered(PlayerInfo* player); // Inform the GametypeInfo about a player that has entered,
+
+            inline void setHUDTemplate(const std::string& templateName)
+                { this->hudtemplate_ = templateName; };
+
+        private:
+            void registerVariables();
+            void setSpawnedHelper(PlayerInfo* player, bool spawned); // Helper method. Sends changedReadyToSpawn notifiers over the network.
+            void setReadyToSpawnHelper(PlayerInfo* player, bool ready); // Helper method. Sends changedSpawned notifiers over the network.
+
+            static const std::string NOTIFICATION_SENDER; //!< The name of the sender for the sending of notifications.
+
+            bool bStarted_; //!< Whether the game has started,
+            bool bEnded_; //!< Whether the game has ended.
+            bool bStartCountdownRunning_; //!< Whether the start countdown is running.
+            float startCountdown_; //!< The current value of the start countdown.
+            unsigned int counter_; //!< The current integer value of the start countdown, the start countdown counter.
+            std::string hudtemplate_;
+
+            std::set<PlayerInfo*> spawnedPlayers_; //!< A set of players that are currently spawned.
+            bool spawned_; //!< Whether the local Player is currently spawned.
+            bool readyToSpawn_; //!< Whether the local Player is ready to spawn.
+    };
+}
+
+#endif /* _GametypeInfo_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/HumanPlayer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/HumanPlayer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/HumanPlayer.cc	(revision 11817)
@@ -0,0 +1,206 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "HumanPlayer.h"
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+// #include "network/ClientInformation.h"
+#include "network/Host.h"
+#include "controllers/HumanController.h"
+#include "controllers/NewHumanController.h"
+#include "gametypes/Gametype.h"
+#include "overlays/OverlayGroup.h"
+
+namespace orxonox
+{
+    RegisterUnloadableClass(HumanPlayer);
+
+    HumanPlayer::HumanPlayer(Context* context) : PlayerInfo(context)
+    {
+        RegisterObject(HumanPlayer);
+
+        this->server_initialized_ = GameMode::isMaster();
+        this->client_initialized_ = false;
+
+        this->bHumanPlayer_ = true;
+        this->defaultController_ = Class(NewHumanController);
+
+        this->humanHud_ = nullptr;
+        this->gametypeHud_ = nullptr;
+
+        this->setConfigValues();
+        this->registerVariables();
+    }
+
+    HumanPlayer::~HumanPlayer()
+    {
+        if (this->BaseObject::isInitialized())
+        {
+            if (this->humanHud_)
+                this->humanHud_->destroy();
+
+            if (this->gametypeHud_)
+                this->gametypeHud_->destroy();
+        }
+    }
+
+    void HumanPlayer::setConfigValues()
+    {
+        SetConfigValue(nick_, "Player").callback(this, &HumanPlayer::configvaluecallback_changednick);
+        SetConfigValue(hudtemplate_, "defaultHUD").callback(this, &HumanPlayer::configvaluecallback_changedHUDTemplate);
+    }
+
+    void HumanPlayer::registerVariables()
+    {
+        registerVariable(this->synchronize_nick_, VariableDirection::ToServer, new NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_changednick));
+
+        registerVariable(this->clientID_,           VariableDirection::ToClient, new NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_clientIDchanged));
+        registerVariable(this->server_initialized_, VariableDirection::ToClient, new NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_server_initialized));
+        registerVariable(this->client_initialized_, VariableDirection::ToServer, new NetworkCallback<HumanPlayer>(this, &HumanPlayer::networkcallback_client_initialized));
+    }
+
+    void HumanPlayer::configvaluecallback_changednick()
+    {
+        if (this->isLocalPlayer())
+        {
+            this->synchronize_nick_ = this->nick_;
+
+            if (GameMode::isMaster())
+                this->setName(this->nick_);
+        }
+    }
+
+    void HumanPlayer::configvaluecallback_changedHUDTemplate()
+    {
+        this->setHumanHUDTemplate(this->hudtemplate_);
+    }
+
+    void HumanPlayer::networkcallback_changednick()
+    {
+        this->setName(this->synchronize_nick_);
+    }
+
+    void HumanPlayer::networkcallback_clientIDchanged()
+    {
+        if (this->clientID_ == Host::getPlayerID())
+        {
+            this->bLocalPlayer_ = true;
+            this->synchronize_nick_ = this->nick_;
+            this->client_initialized_ = true;
+
+            if (!GameMode::isMaster())
+                this->setSyncMode(ObjectDirection::Bidirectional);
+            else
+                this->setName(this->nick_);
+
+            this->createController();
+            this->updateHumanHUD();
+        }
+    }
+
+    void HumanPlayer::networkcallback_server_initialized()
+    {
+        this->client_initialized_ = true;
+    }
+
+    void HumanPlayer::networkcallback_client_initialized()
+    {
+        if (this->getGametype())
+            this->getGametype()->playerEntered(this);
+    }
+
+    bool HumanPlayer::isInitialized() const
+    {
+        return (this->server_initialized_ && this->client_initialized_);
+    }
+
+    float HumanPlayer::getPing() const
+    {
+//         return static_cast<float>(ClientInformation::findClient(this->getClientID())->getRTT());
+        return 0.; //TODO: reimplement this
+    }
+
+    float HumanPlayer::getPacketLossRatio() const
+    {
+      //         return static_cast<float>(ClientInformation::findClient(this->getClientID())->getPacketLoss());
+        return 0.; //TODO: reimplement this
+    }
+
+    void HumanPlayer::setClientID(unsigned int clientID)
+    {
+        this->clientID_ = clientID;
+        this->networkcallback_clientIDchanged();
+    }
+
+    void HumanPlayer::switchGametype(Gametype* gametype)
+    {
+        PlayerInfo::switchGametype(gametype);
+
+        if (this->isInitialized() && this->isLocalPlayer())
+        {
+            if (this->getGametype() && !this->getGametype()->getHUDTemplate().empty())
+                this->setGametypeHUDTemplate(this->getGametype()->getHUDTemplate());
+            else
+                this->setGametypeHUDTemplate("");
+        }
+    }
+
+    void HumanPlayer::updateHumanHUD()
+    {
+        if (this->humanHud_)
+        {
+            this->humanHud_->destroy();
+            this->humanHud_ = nullptr;
+        }
+
+        if (this->isLocalPlayer() && !this->humanHudTemplate_.empty() && GameMode::showsGraphics())
+        {
+            this->humanHud_ = new OverlayGroup(this->getContext());
+            this->humanHud_->addTemplate(this->humanHudTemplate_);
+            this->humanHud_->setOwner(this);
+        }
+    }
+
+    void HumanPlayer::updateGametypeHUD()
+    {
+        if (this->gametypeHud_)
+        {
+            this->gametypeHud_->destroy();
+            this->gametypeHud_ = nullptr;
+        }
+
+        if (this->isLocalPlayer() && !this->gametypeHudTemplate_.empty())
+        {
+            this->gametypeHud_ = new OverlayGroup(this->getContext());
+            this->gametypeHud_->addTemplate(this->gametypeHudTemplate_);
+            this->gametypeHud_->setOwner(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/HumanPlayer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/HumanPlayer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/HumanPlayer.h	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _HumanPlayer_H__
+#define _HumanPlayer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "PlayerInfo.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport HumanPlayer : public PlayerInfo
+    {
+        public:
+            HumanPlayer(Context* context);
+            virtual ~HumanPlayer();
+
+            void setConfigValues();
+
+            virtual bool isInitialized() const override;
+            virtual float getPing() const override;
+            virtual float getPacketLossRatio() const override;
+
+            void setClientID(unsigned int clientID);
+
+            virtual void switchGametype(Gametype* gametype) override;
+
+            inline void setHumanHUDTemplate(const std::string& name)
+            {
+                if (name != this->humanHudTemplate_)
+                {
+                    this->humanHudTemplate_ = name;
+                    this->updateHumanHUD();
+                }
+            }
+            inline const std::string& getHumanHUDTemplate() const
+                { return this->humanHudTemplate_; }
+            inline OverlayGroup* getHumanHUD() const
+                { return this->humanHud_; }
+
+            inline void setGametypeHUDTemplate(const std::string& name)
+            {
+                if (name != this->gametypeHudTemplate_)
+                {
+                    this->gametypeHudTemplate_ = name;
+                    this->updateGametypeHUD();
+                }
+            }
+            inline const std::string& getGametypeHUDTemplate() const
+                { return this->gametypeHudTemplate_; }
+            inline OverlayGroup* getGametypeHUD() const
+                { return this->gametypeHud_; }
+
+        protected:
+            void configvaluecallback_changednick();
+            void configvaluecallback_changedHUDTemplate();
+            void networkcallback_changednick();
+            void networkcallback_clientIDchanged();
+            void networkcallback_server_initialized();
+            void networkcallback_client_initialized();
+
+            void updateHumanHUD();
+            void updateGametypeHUD();
+
+            std::string nick_;
+            std::string synchronize_nick_;
+            std::string hudtemplate_;
+            bool server_initialized_;
+            bool client_initialized_;
+
+            std::string humanHudTemplate_;
+            OverlayGroup* humanHud_;
+            std::string gametypeHudTemplate_;
+            OverlayGroup* gametypeHud_;
+        private:
+            void registerVariables();
+    };
+}
+
+#endif /* _HumanPlayer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/Info.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/Info.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/Info.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Info.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(Info);
+
+    Info::Info(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        RegisterObject(Info);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/Info.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/Info.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/Info.h	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Info_H__
+#define _Info_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "network/synchronisable/Synchronisable.h"
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Info : public BaseObject, public Synchronisable
+    {
+        public:
+            Info(Context* context);
+            virtual ~Info() {}
+    };
+}
+
+#endif /* _Info_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/PlayerInfo.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/PlayerInfo.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/PlayerInfo.cc	(revision 11817)
@@ -0,0 +1,310 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include <cassert>
+
+#include "PlayerInfo.h"
+
+#include "core/CoreIncludes.h"
+// #include "network/ClientInformation.h"
+#include "gametypes/Gametype.h"
+#include "worldentities/ControllableEntity.h"
+#include "controllers/Controller.h"
+#include "interfaces/RadarViewable.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(PlayerInfo).inheritsFrom<Info>();
+
+    PlayerInfo::PlayerInfo(Context* context) : Info(context)
+    {
+        RegisterObject(PlayerInfo);
+
+        this->clientID_ = NETWORK_PEER_ID_UNKNOWN;
+        this->bHumanPlayer_ = false;
+        this->bLocalPlayer_ = false;
+        this->bReadyToSpawn_ = false;
+        this->bSetUnreadyAfterSpawn_ = true;
+        this->controller_ = nullptr;
+        this->controllableEntity_ = nullptr;
+        this->controllableEntityID_ = OBJECTID_UNKNOWN;
+
+        this->gtinfo_ = nullptr;
+        this->gtinfoID_ = OBJECTID_UNKNOWN;
+        this->updateGametypeInfo(this->getGametype());
+
+        this->registerVariables();
+
+    }
+
+    PlayerInfo::~PlayerInfo()
+    {
+        if (this->BaseObject::isInitialized())
+        {
+            this->stopControl();
+
+            if (this->controller_)
+            {
+                this->controller_->destroy();
+                this->controller_ = nullptr;
+            }
+
+            if (this->getGametype())
+                this->getGametype()->playerLeft(this);
+        }
+    }
+
+    void PlayerInfo::registerVariables()
+    {
+        registerVariable(this->name_,                 VariableDirection::ToClient, new NetworkCallback<PlayerInfo>(this, &PlayerInfo::changedName));
+        registerVariable(this->controllableEntityID_, VariableDirection::ToClient, new NetworkCallback<PlayerInfo>(this, &PlayerInfo::networkcallback_changedcontrollableentityID));
+        registerVariable(this->gtinfoID_,             VariableDirection::ToClient, new NetworkCallback<PlayerInfo>(this, &PlayerInfo::networkcallback_changedgtinfoID));
+    }
+
+    void PlayerInfo::changedName()
+    {
+        SUPER(PlayerInfo, changedName);
+
+        if (this->isInitialized() && this->getGametype())
+            this->getGametype()->playerChangedName(this);
+    }
+
+    void PlayerInfo::switchGametype(Gametype* gametype)
+    {
+        Gametype* oldGametype = this->getGametype();
+        this->setGametype(StrongPtr<Gametype>(gametype));
+        Gametype* newGametype = this->getGametype();
+
+
+        this->updateGametypeInfo(newGametype);
+
+        if (this->isInitialized())
+        {
+            if (oldGametype)
+            {
+                if (newGametype)
+                    oldGametype->playerSwitched(this, newGametype);
+                else
+                    oldGametype->playerLeft(this);
+            }
+
+            if (newGametype)
+            {
+                if (oldGametype)
+                    newGametype->playerSwitchedBack(this, oldGametype);
+                else
+                    newGametype->playerEntered(this);
+            }
+        }
+    }
+
+    void PlayerInfo::updateGametypeInfo(Gametype* gametype)
+    {
+        this->gtinfo_ = nullptr;
+        this->gtinfoID_ = OBJECTID_UNKNOWN;
+
+        if (gametype && gametype->getGametypeInfo())
+        {
+            this->gtinfo_ = gametype->getGametypeInfo();
+            this->gtinfoID_ = this->gtinfo_->getObjectID();
+        }
+    }
+
+    void PlayerInfo::createController()
+    {
+        if (this->controller_)
+        {
+            this->controller_->destroy();
+            this->controller_ = nullptr;
+        }
+        this->controller_ = this->defaultController_.fabricate(this->getContext());
+        assert(this->controller_);
+        this->controller_->setPlayer(this);
+        if (this->controllableEntity_)
+        {
+            this->controller_->setControllableEntity(this->controllableEntity_);
+            this->controllableEntity_->setController(this->controller_);
+        }
+        this->changedController();
+    }
+
+    void PlayerInfo::startControl(ControllableEntity* entity)
+    {
+        if (!entity || entity == this->controllableEntity_)
+            return;
+
+        while (this->previousControllableEntity_.size() > 0)
+            this->stopTemporaryControl();
+
+        if (this->controllableEntity_)
+            this->stopControl();
+
+        this->controllableEntity_ = entity;
+        this->controllableEntityID_ = entity->getObjectID();
+
+        entity->setPlayer(this);
+
+        this->bReadyToSpawn_ &= (!this->bSetUnreadyAfterSpawn_);
+
+        if (this->controller_)
+        {
+            this->controller_->setControllableEntity(entity);
+            this->controllableEntity_->setController(this->controller_);
+        }
+
+        this->changedControllableEntity();
+
+        RadarViewable* radarviewable = orxonox_cast<RadarViewable*>(entity);
+        if (radarviewable != nullptr)
+            radarviewable->setRadarName(this->getName());
+    }
+
+    void PlayerInfo::startTemporaryControl(ControllableEntity* entity)
+    {
+        if (!entity)
+            return;
+
+        this->controllableEntity_->destroyHud(); // HACK-ish
+        this->previousControllableEntity_.push_back(this->controllableEntity_);
+        this->controllableEntity_ = entity;
+        this->controllableEntityID_ = entity->getObjectID();
+
+        entity->setPlayer(this);
+        entity->setController(this->controller_);
+
+        if (this->controller_)
+            this->controller_->setControllableEntity(entity);
+
+        this->changedControllableEntity();
+
+         // HACK-ish
+        if(this->isHumanPlayer())
+            entity->createHud();
+    }
+
+    void PlayerInfo::stopControl()
+    {
+        while ( this->previousControllableEntity_.size() > 0)
+            this->stopTemporaryControl();
+
+        ControllableEntity* entity = this->controllableEntity_;
+
+        if (!entity)
+            return;
+
+        this->controllableEntity_->setController(nullptr);
+        this->controllableEntity_ = nullptr;
+        this->controllableEntityID_ = OBJECTID_UNKNOWN;
+
+        if (this->controller_)
+            this->controller_->setControllableEntity(nullptr);
+
+        if ( GameMode::isMaster() )
+            entity->removePlayer();
+
+        this->changedControllableEntity();
+    }
+
+    void PlayerInfo::pauseControl()
+    {
+        ControllableEntity* entity = this->controllableEntity_;
+
+        if (!entity)
+            return;
+
+        Controller* tmp =this->controllableEntity_->getController();
+        if (tmp == nullptr)
+        {
+            orxout(verbose) <<  "PlayerInfo: pauseControl, Controller is nullptr " << endl;
+            return;
+        }
+        tmp->setActive(false);
+        //this->controllableEntity_->getController()->setControllableEntity(nullptr);
+        this->controllableEntity_->setController(nullptr);
+    }
+
+    void PlayerInfo::stopTemporaryControl()
+    {
+        ControllableEntity* entity = this->controllableEntity_;
+
+        assert(this->controllableEntity_ != nullptr);
+        if( !entity || this->previousControllableEntity_.size() == 0 )
+            return;
+
+        entity->destroyHud(); // HACK-ish
+
+        this->controllableEntity_->setController(nullptr);
+        if(this->isHumanPlayer()) // TODO: Multiplayer?
+            this->controllableEntity_->destroyHud(); // HACK-ish
+
+//        this->controllableEntity_ = this->previousControllableEntity_.back();
+        do {
+            this->controllableEntity_ = this->previousControllableEntity_.back();
+        } while(this->controllableEntity_ == nullptr && this->previousControllableEntity_.size() > 0);
+        this->controllableEntityID_ = this->controllableEntity_->getObjectID();
+        this->previousControllableEntity_.pop_back();
+
+        if ( this->controllableEntity_ != nullptr && this->controller_ != nullptr)
+            this->controller_->setControllableEntity(this->controllableEntity_);
+
+         // HACK-ish
+        if(this->controllableEntity_ != nullptr && this->isHumanPlayer())
+            this->controllableEntity_->createHud();
+
+        if ( GameMode::isMaster() )
+            entity->removePlayer();
+
+        this->changedControllableEntity();
+    }
+
+    void PlayerInfo::networkcallback_changedcontrollableentityID()
+    {
+        if (this->controllableEntityID_ != OBJECTID_UNKNOWN)
+        {
+            Synchronisable* temp = Synchronisable::getSynchronisable(this->controllableEntityID_);
+            ControllableEntity* entity = orxonox_cast<ControllableEntity*>(temp);
+            this->startControl(entity);
+        }
+        else
+        {
+            this->stopControl();
+        }
+    }
+
+
+    void PlayerInfo::networkcallback_changedgtinfoID()
+    {
+        if (this->gtinfoID_ != OBJECTID_UNKNOWN)
+        {
+            this->gtinfo_ = orxonox_cast<GametypeInfo*>(Synchronisable::getSynchronisable(this->gtinfoID_));
+
+            if (!this->gtinfo_)
+                this->gtinfoID_ = OBJECTID_UNKNOWN;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/infos/PlayerInfo.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/infos/PlayerInfo.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/infos/PlayerInfo.h	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PlayerInfo_H__
+#define _PlayerInfo_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "Info.h"
+#include "core/class/SubclassIdentifier.h"
+
+namespace orxonox // tolua_export
+{ // tolua_export
+    class _OrxonoxExport PlayerInfo // tolua_export
+        : public Info
+    { // tolua_export
+        public:
+            PlayerInfo(Context* context);
+            virtual ~PlayerInfo();
+
+            virtual void changedName() override;
+            virtual void switchGametype(Gametype* gametype);
+
+            virtual void changedController() {}
+            virtual void changedControllableEntity() {}
+
+            inline bool isHumanPlayer() const
+                { return this->bHumanPlayer_; }
+            inline bool isLocalPlayer() const
+                { return this->bLocalPlayer_; }
+            inline unsigned int getClientID() const
+                { return this->clientID_; }
+
+            virtual bool isInitialized() const = 0;
+            virtual float getPing() const = 0;
+            virtual float getPacketLossRatio() const = 0;
+
+            inline void setReadyToSpawn(bool bReady)
+                { this->bReadyToSpawn_ = bReady; }
+            inline bool isReadyToSpawn() const
+                { return this->bReadyToSpawn_; }
+
+            void startControl(ControllableEntity* entity);
+            void stopControl();
+            void pauseControl();
+            void startTemporaryControl(ControllableEntity* entity);
+            void stopTemporaryControl();
+
+            inline ControllableEntity* getControllableEntity() const
+                { return this->controllableEntity_; }
+
+            inline Controller* getController() const
+                { return this->controller_; }
+
+            inline const GametypeInfo* getGametypeInfo() const
+                { return this->gtinfo_; }
+
+        protected:
+            void createController();
+
+            bool bHumanPlayer_;
+            bool bLocalPlayer_;
+            bool bSetUnreadyAfterSpawn_;
+            SubclassIdentifier<Controller> defaultController_;
+            unsigned int clientID_;
+
+        private:
+            void registerVariables();
+            void networkcallback_changedcontrollableentityID();
+            void networkcallback_changedgtinfoID();
+            void updateGametypeInfo(Gametype* gametype);
+
+            bool bReadyToSpawn_;
+            Controller* controller_;
+            ControllableEntity* controllableEntity_;
+            std::vector<WeakPtr<ControllableEntity>> previousControllableEntity_; //!< List of the previous ControllableEntities if repeatedly startTemporary control was called. The ControllableEntity at the back is the most recent.
+            unsigned int controllableEntityID_;
+
+            const GametypeInfo* gtinfo_;
+            unsigned int gtinfoID_;
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _PlayerInfo_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,8 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  InterfaceCompilation.cc
+  NotificationListener.cc
+  Pickupable.cc
+  PickupCarrier.cc
+  PickupListener.cc
+  RadarViewable.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/GametypeMessageListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/GametypeMessageListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/GametypeMessageListener.h	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GametypeMessageListener_H__
+#define _GametypeMessageListener_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport GametypeMessageListener : virtual public OrxonoxInterface
+    {
+        public:
+            GametypeMessageListener();
+            virtual ~GametypeMessageListener() {}
+
+            virtual void announcemessage(const GametypeInfo* gtinfo, const std::string& message) {}
+            virtual void killmessage(const GametypeInfo* gtinfo, const std::string& message) {}
+            virtual void deathmessage(const GametypeInfo* gtinfo, const std::string& message) {}
+            virtual void staticmessage(const GametypeInfo* gtinfo, const std::string& message, const ColourValue& colour) {}
+            virtual void fadingmessage(const GametypeInfo* gtinfo, const std::string& message) {}
+    };
+}
+
+#endif /* _GametypeMessageListener_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/InterfaceCompilation.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/InterfaceCompilation.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/InterfaceCompilation.cc	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief
+    Compiles all the interfaces in the orxonox library with mostly just a constructor.
+*/
+
+#include "GametypeMessageListener.h"
+#include "PlayerTrigger.h"
+#include "RadarListener.h"
+#include "Rewardable.h"
+#include "TeamColourable.h"
+#include "NotificationListener.h"
+
+#include "core/CoreIncludes.h"
+
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    //----------------------------
+    // GametypeMessageListener
+    //----------------------------
+    RegisterAbstractClass(GametypeMessageListener).inheritsFrom<OrxonoxInterface>();
+
+    GametypeMessageListener::GametypeMessageListener()
+    {
+        RegisterObject(GametypeMessageListener);
+    }
+
+    //----------------------------
+    // PlayerTrigger
+    //----------------------------
+    RegisterAbstractClass(PlayerTrigger).inheritsFrom<OrxonoxInterface>();
+
+    PlayerTrigger::PlayerTrigger()
+    {
+        RegisterObject(PlayerTrigger);
+
+        this->isForPlayer_ = false;
+    }
+
+    void PlayerTrigger::setTriggeringPawn(Pawn* pawn)
+    {
+        assert(pawn);
+        this->pawn_ = pawn;
+        if (pawn)
+            this->player_ = pawn->getPlayer();
+    }
+
+    //----------------------------
+    // RadarListener
+    //----------------------------
+    RegisterAbstractClass(RadarListener).inheritsFrom<OrxonoxInterface>();
+
+    RadarListener::RadarListener()
+    {
+        RegisterObject(RadarListener);
+    }
+
+    //----------------------------
+    // TeamColourable
+    //----------------------------
+    RegisterAbstractClass(TeamColourable).inheritsFrom<OrxonoxInterface>();
+
+    TeamColourable::TeamColourable()
+    {
+        RegisterObject(TeamColourable);
+    }
+
+    //----------------------------
+    // Rewardable
+    //----------------------------
+    RegisterAbstractClass(Rewardable).inheritsFrom<OrxonoxInterface>();
+
+    Rewardable::Rewardable()
+    {
+        RegisterObject(Rewardable);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/NotificationListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/NotificationListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/NotificationListener.cc	(revision 11817)
@@ -0,0 +1,163 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationListener.cc
+    @brief Implementation of the NotificationListener class.
+*/
+
+#include "core/CoreIncludes.h"
+#include "network/Host.h"
+#include "network/NetworkFunctionIncludes.h"
+#include "util/SubString.h"
+
+#include "interfaces/NotificationListener.h"
+
+namespace orxonox
+{
+    
+    /*static*/ const std::string NotificationListener::ALL("all");
+    /*static*/ const std::string NotificationListener::NONE("none");
+    
+    // Commands
+    /*static*/ const std::string NotificationListener::COMMAND_CLEAR("clear");
+    /*static*/ const std::string NotificationListener::COMMAND_NONE("none");
+    
+    registerStaticNetworkFunction(NotificationListener::sendHelper);
+    
+    RegisterAbstractClass(NotificationListener).inheritsFrom<OrxonoxInterface>();
+
+    NotificationListener::NotificationListener()
+    {
+        RegisterObject(NotificationListener);
+    }
+
+    /**
+    @brief
+        Helper method to send both notifications and commands over the network.
+    @param message
+        The message/command that should be sent.
+    @param sender
+        The sender that sent the notification/command.
+    @param sendMode
+        The mode in which the notification/command is sent, can be 'local' to send the notification to the client where this function is executed, 'network' if the notification is to be sent to the client with the specified clientID, or 'broadcast' if the notification should be sent to all hosts.
+    @param clientId
+        The id of the client the notification/command should be sent to.
+    @param isCommand
+        Whether the message is a notification or a command.
+    @param messageType
+        The type of the notification, can be either 'info' or 'important'.
+    */
+    /*static*/ void NotificationListener::sendNetworkHelper(const std::string& message, const std::string& sender, NotificationSendMode sendMode, unsigned int clientId, bool isCommand, NotificationMessageType messageType)
+    {
+        // If we're in standalone mode or we're already no the right client we create and send the notification/command.
+        if(GameMode::isStandalone() || sendMode == NotificationSendMode::local || (sendMode ==  NotificationSendMode::network && Host::getPlayerID() == clientId))
+        {
+            sendHelper(message, sender, isCommand, messageType);
+        }
+        // If we're on the server (and the server is not the intended recipient of the notification/command) we send it over the network.
+        else if(GameMode::isServer() && sendMode == NotificationSendMode::network && Host::getPlayerID() != clientId)
+        {
+            callStaticNetworkFunction(&NotificationListener::sendHelper, clientId, message, sender, isCommand, messageType);
+        }
+        else if(GameMode::isServer() && sendMode == NotificationSendMode::broadcast)
+        {
+            // TODO: Works as intended?
+            callStaticNetworkFunction(&NotificationListener::sendHelper, NETWORK_PEER_ID_BROADCAST, message, sender, isCommand, messageType);
+        }
+    }
+
+    /**
+    @brief
+        Helper method to register a notification/execute a command with all NotificationListeners after it has been sent over the network.
+    @param message
+        The notification/command to be sent/executed.
+    @param sender
+        The sender that sent the notification/command.
+    @param isCommand
+        Whether the message is a command or a notification.
+    @param type
+        The type of the notification.
+    */
+    /*static*/ void NotificationListener::sendHelper(const std::string& message, const std::string& sender, bool isCommand, NotificationMessageType type)
+    {
+        // Iterate through all NotificationListeners and notify them by calling the method they overloaded.
+        for(NotificationListener* listener : ObjectList<NotificationListener>())
+        {
+            // If the notification is a message.
+            if(!isCommand)
+                listener->registerNotification(message, sender, type);
+
+            // If the notification is a command.
+            if(isCommand)
+            {
+                NotificationCommand command = str2Command(message);
+                if(command != NotificationCommand::none)
+                    listener->executeCommand(command, sender);
+            }
+        }
+    }
+
+    /**
+    @brief
+        Helper method. Converts a string into the enum for a command.
+    @param string
+        The string to be converted.
+    @return
+        Returns the corresponding enum, NotificationCommand::none if the command doesn't exist.
+    */
+    /*static*/ NotificationCommand NotificationListener::str2Command(const std::string& string)
+    {
+        NotificationCommand command = NotificationCommand::none;
+
+        if(string == NotificationListener::COMMAND_CLEAR)
+            command = NotificationCommand::clear;
+
+        return command;
+    }
+
+    /**
+    @brief
+        Helper method. Converts a command enum into its corresponding string.
+    @param command
+        The command to be converted.
+    @return
+        Returns the corresponding string.
+    */
+    /*static*/ const std::string& NotificationListener::command2Str(NotificationCommand command)
+    {
+        switch(command)
+        {
+            case NotificationCommand::clear:
+                return NotificationListener::COMMAND_CLEAR;
+            default:
+                return NotificationListener::COMMAND_NONE;
+        }
+    }
+    
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/NotificationListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/NotificationListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/NotificationListener.h	(revision 11817)
@@ -0,0 +1,149 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file NotificationListener.h
+    @brief Definition of the NotificationListener class.
+    @ingroup Notifications
+*/
+
+#ifndef _NotificationListener_H__
+#define _NotificationListener_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <ctime>
+#include <set>
+#include <string>
+
+#include "util/StringUtils.h"
+
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    // TODO: Document.
+    enum class NotificationMessageType {
+        info,
+        important
+    };
+    
+    enum class NotificationSendMode {
+        local,
+        network,
+        broadcast
+    };
+    
+    enum class NotificationCommand {
+        none,
+        clear
+    };
+
+    // TODO: Update doc.
+    /**
+    @brief
+        NotificationListener interface.
+
+        The NotificationListener interface (or more precisely abstract class) presents a means of being informed when a new @ref orxonox::Notification "Notification" is sent.
+        The NotificationListener can be used to send a new notification message (with NotificationListener::sendNotification() ) or a new notification command (with NotificationListener::sendCommand() ). Each NotificationListener is then informed about the new @ref orxonox::Notification "Notification" and can take appropriate action. Currently the only NotificationListener ist the @ref orxonox::NotificationManager "NotificationManager" singleton.
+
+        When inheriting from a NotificationListener it is important to provide an appropriate implementation of registerNotification() and executeCommand().
+
+    @author
+        Damian 'Mozork' Frick
+        
+    @ingroup Notifications
+    @todo Consistent terminology between message, notification and command.
+    */
+    class _OrxonoxExport NotificationListener : virtual public OrxonoxInterface
+    {
+        public:
+            NotificationListener();
+            virtual ~NotificationListener() {}
+
+            /**
+            @brief Sends a Notification with the specified message to the specified client from the specified sender.
+            @param message The message that should be sent.
+            @param sender The sender that sent the notification. Default is 'none'.
+            @param messageType The type of the message, can be either 'info' or 'important'. Default is 'info'.
+            @param sendMode The mode in which the notification is sent, can be 'local' to send the notification to the client where this function is executed, 'network' if the notification is to be sent to the client with the specified clientID, or 'broadcast' if the notification should be sent to all hosts. Default is NotificationSendMode::local.
+            @param clientId The id of the client the notification should be sent to. Default is 0.
+            */
+            static void sendNotification(const std::string& message, const std::string& sender = NotificationListener::NONE, NotificationMessageType messageType = NotificationMessageType::info, NotificationSendMode sendMode = NotificationSendMode::local, unsigned int clientId = 0)
+                { NotificationListener::sendNetworkHelper(message, sender, sendMode, clientId, false, messageType); }
+            /**
+            @brief Sends a specified command to the specified client from the specified sender.
+            @param command The command that should be sent (and later executed).
+            @param sender The sender that sent the notification. Default is 'none'.
+            @param sendMode The mode in which the command is sent, can be 'local' to send the command to the client where this function is executed, 'network' if the command is to be sent to the client with the specified clientID, or 'broadcast' if the command should be sent to all hosts. Default is NotificationSendMode::local.
+            @param clientId The id of the client the command should be sent to. Default is 0.
+            */
+            static void sendCommand(const std::string& command, const std::string& sender = NotificationListener::NONE, NotificationSendMode sendMode = NotificationSendMode::local, unsigned int clientId = 0)
+                { NotificationListener::sendNetworkHelper(command, sender, sendMode, clientId, true); }
+
+            static void sendHelper(const std::string& message, const std::string& sender, bool isCommand, NotificationMessageType type); // Helper method to register a notification/execute a command with all NotificationListeners after it has been sent over the network.
+
+            //TODO: Make protected?
+            
+            /**
+            @brief Registers a notification with the NotificationListener.
+                   This needs to be overloaded by each class inheriting from NotificationListener.
+            @param message The notification's message.
+            @param sender The sender of the notification.
+            @param type The type of the notification.
+            @return Returns true if the notification was successfully registered, false if not.
+            */
+            virtual bool registerNotification(const std::string& message, const std::string& sender, NotificationMessageType type)
+                { return false; }
+            /**
+            @brief Executes a command with the NotificationListener
+                   This needs to be overloaded by each class inheriting from NotificationListener.
+            @param command The command to be executed.
+            @param sender The sender of the command.
+            @return Returns true if the command was successfully executed, false if not.
+            */
+            virtual bool executeCommand(NotificationCommand command, const std::string& sender) { return false; }
+
+        public:
+            
+            static const std::string ALL; //!< Static string to indicate a sender that sends to all NotificationQueues.
+            static const std::string NONE; //!< Static string to indicate a sender that sends to no specific NotificationQueues.
+            
+            //! Commands
+            static const std::string COMMAND_CLEAR;
+            static const std::string COMMAND_NONE;
+            
+        protected:
+            static void sendNetworkHelper(const std::string& message, const std::string& sender, NotificationSendMode sendMode, unsigned int clientId, bool isCommand = false, NotificationMessageType messageType = NotificationMessageType::info); // Helper method to send both notifications and commands over the network.
+
+            static NotificationCommand str2Command(const std::string& string); // Helper method. Converts a string into the enum for a command.
+            static const std::string& command2Str(NotificationCommand command); // Helper method. Converts a command enum into its corresponding string.
+    };
+}
+
+#endif /* _NotificationListener_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupCarrier.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupCarrier.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupCarrier.cc	(revision 11817)
@@ -0,0 +1,180 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PickupCarrier.cc
+    @brief Implementation of the PickupCarrier class.
+*/
+
+#include "PickupCarrier.h"
+
+#include "core/CoreIncludes.h"
+#include "core/class/Identifier.h"
+
+#include "Pickupable.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(PickupCarrier).inheritsFrom<OrxonoxInterface>();
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    PickupCarrier::PickupCarrier()
+    {
+        RegisterObject(PickupCarrier);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    PickupCarrier::~PickupCarrier()
+    {
+
+    }
+
+    /**
+    @brief
+        Is called before the PickupCarrier is effectively destroyed.
+    */
+    void PickupCarrier::preDestroy(void)
+    {
+        std::set<Pickupable*>::iterator it = this->pickups_.begin();
+        Pickupable* temp;
+        // Iterate over all pickups that are attached to this PickupCarrier and destroy them.
+        while(it != this->pickups_.end())
+        {
+            temp = *it;
+            (*it)->carrierDestroyed();
+            it = this->pickups_.begin();
+            if(it != this->pickups_.end() && temp == *it) // Infinite loop avoidance, in case the pickup wasn't removed from the carrier somewhere in the carrierDestroy() procedure.
+            {
+                orxout(internal_warning, context::pickups) << "Oops. In a PickupCarrier, while cleaning up, a Pickupable (&" << temp << ") didn't unregister itself as it should have." << endl;;
+                it++;
+            }
+        }
+
+        this->pickups_.clear();
+    }
+
+    /**
+    @brief
+        Can be used to check whether the PickupCarrier or a child of his is a target ot the input Pickupable.
+    @param pickup
+        A pointer to the Pickupable.
+    @return
+        Returns true if the PickupCarrier or one of its children is a target, false if not.
+    */
+    bool PickupCarrier::isTarget(const Pickupable* pickup) const
+    {
+        if(pickup->isTarget(this)) // If the PickupCarrier itself is a target.
+            return true;
+
+        bool isTarget = false;
+        // Go recursively through all children to check whether they are a target.
+        std::vector<PickupCarrier*>* children = this->getCarrierChildren();
+        for(PickupCarrier* carrier : *children)
+        {
+            if(carrier->isTarget(pickup))
+            {
+                isTarget = true;
+                break;
+            }
+        }
+
+        children->clear();
+        delete children;
+
+        return isTarget;
+    }
+
+    /**
+    @brief
+        Get the carrier that is both a child of the PickupCarrier (or the PickupCarrier itself) and a target of the input Pickupable.
+    @param pickup
+        A pounter to the Pickupable.
+    @return
+        Returns a pointer to the PickupCarrier that is the target of the input Pickupable.
+    */
+    PickupCarrier* PickupCarrier::getTarget(const Pickupable* pickup)
+    {
+        if(!this->isTarget(pickup))
+            return nullptr;
+
+        if(pickup->isTarget(this)) // If the PickupCarrier itself is a target.
+            return this;
+
+        PickupCarrier* target = nullptr;
+        // Go recursively through all children to check whether they are the target.
+        std::vector<PickupCarrier*>* children = this->getCarrierChildren();
+        for(PickupCarrier* child : *children)
+        {
+            if(pickup->isTarget(child))
+            {
+                target = child;
+                break;
+            }
+        }
+
+        children->clear();
+        delete children;
+
+        return target;
+    }
+
+    /**
+    @brief
+        Adds a Pickupable to the list of pickups that are carried by this PickupCarrier.
+    @param pickup
+        A pointer to the pickup to be added.
+    @return
+        Returns true if successfull, false if the Pickupable was already present.
+    */
+    bool PickupCarrier::addPickup(Pickupable* pickup)
+    {
+        orxout(verbose, context::pickups) << "Adding Pickupable (&" << pickup << ") to PickupCarrier (&" << this << ")" << endl;
+        return this->pickups_.insert(pickup).second;
+    }
+
+    /**
+    @brief
+        Removes a Pickupable from the list of pickups that are carried by this PickupCarrier.
+    @param pickup
+        A pointer to the pickup to be removed.
+    @return
+        Returns true if successfull, false if the Pickupable was not present in the list.
+    */
+    bool PickupCarrier::removePickup(Pickupable* pickup)
+    {
+        orxout(verbose, context::pickups) << "Removing Pickupable (&" << pickup << ") from PickupCarrier (&" << this << ")" << endl;
+        return this->pickups_.erase(pickup) == 1;
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupCarrier.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupCarrier.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupCarrier.h	(revision 11817)
@@ -0,0 +1,122 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PickupCarrier.h
+    @brief Definition of the PickupCarrier class.
+    @ingroup Pickup
+*/
+
+#ifndef _PickupCarrier_H__
+#define _PickupCarrier_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <set>
+#include <vector>
+
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+
+    // Forward-declarations.
+    class MetaPickup;
+
+    /**
+    @brief
+        The PickupCarrier interface provides the means, for any class implementing it, to possess @ref orxonox::Pickupable "Pickupables".
+
+        For a class to use the PickupCarrier interface it must implement the follwing three methods:
+        - <b>getCarrierPosition()</b> The getCarrierPosition() method returns the absolute position (in space) of the PickupCarrier.
+
+        Different PickupCarriers are structured hierarchically, a pickup can be picked up by a PickupCarrier that can't really carry that particular pickup but one of its children (or one of their children) can, and thus it gets "handed down" until it is at the right place.
+        But this structure has to be established first.
+        - <b>getCarrierChildren()</b> To this end a PickupCarrier needs to implement getCarrierChildren() which returns a list of its direct PickupCarrier children. If you need an example, have a look at @ref orxonox::Pawn "Pawn" and @ref orxonox::Engine "Engine".
+        - <b>getCarrierParent()</b> This is the method in the other direction. It returns the parent of this PickupCarrier, or nullptr if the PickupCarrier is a root node in this hierarchy.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _OrxonoxExport PickupCarrier : virtual public OrxonoxInterface
+    {
+        // So that the different Pickupables have full access to their PickupCarrier.
+        friend class Pickupable;
+        friend class PickupManager;
+        // Friends.
+        friend class MetaPickup;
+
+        public:
+            PickupCarrier(); //!< Constructor.
+            virtual ~PickupCarrier(); //!< Destructor.
+            virtual void preDestroy(void) override; //!< Is called before the PickupCarrier is effectively destroyed.
+
+            bool isTarget(const Pickupable* pickup) const; //!< Can be used to check whether the PickupCarrier or a child of his is a target ot the input Pickupable.
+            PickupCarrier* getTarget(const Pickupable* pickup); //!< Get the carrier that is both a child of the PickupCarrier (or the PickupCarrier itself) and a target of the input Pickupable.
+
+            /**
+            @brief Get the (absolute) position of the PickupCarrier.
+                   This method needs to be implemented by any direct derivative class of PickupCarrier.
+            @return Returns the position as a Vector3.
+            */
+            virtual const Vector3& getCarrierPosition(void) const = 0;
+
+        protected:
+            /**
+            @brief Get all direct children of this PickupSpawner.
+                   This method needs to be implemented by any direct derivative class of PickupCarrier.
+                   The returned list will be deleted by the methods calling this function.
+            @return Returns a pointer to a list of all direct children.
+            */
+            virtual std::vector<PickupCarrier*>* getCarrierChildren(void) const = 0;
+            /**
+            @brief Get the parent of this PickupSpawner.
+                   This method needs to be implemented by any direct derivative class of PickupCarrier.
+            @return Returns a pointer to the parent.
+            */
+            virtual PickupCarrier* getCarrierParent(void) const = 0;
+
+            /**
+            @brief Get all Pickupables this PickupCarrier has.
+            @return  Returns the set of all Pickupables this PickupCarrier has.
+            */
+            std::set<Pickupable*>& getPickups(void)
+                { return this->pickups_; }
+
+        private:
+            std::set<Pickupable*> pickups_; //!< The list of Pickupables carried by this PickupCarrier.
+
+            bool addPickup(Pickupable* pickup); //!< Adds a Pickupable to the list of pickups that are carried by this PickupCarrier.
+            bool removePickup(Pickupable* pickup); //!< Removes a Pickupable from the list of pickups that are carried by this PickupCarrier.
+
+    };
+}
+
+#endif /* _PickupCarrier_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupListener.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupListener.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupListener.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file PickupListener.cc
+    @brief Implementation of the PickupListener class.
+*/
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/CoreIncludes.h"
+
+#include "PickupListener.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(PickupListener).inheritsFrom<OrxonoxInterface>();
+
+    /**
+    @brief
+        Constructor. Registers the object.
+    */
+    PickupListener::PickupListener()
+    {
+        RegisterObject(PickupListener);
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    PickupListener::~PickupListener()
+    {
+
+    }
+
+    /**
+    @brief
+        Static method that is used to notify the PickupListener itself of the change in the used status of a Pickupable.
+        This is called in Pickupable.
+    @param pickup
+        The Pickupable that has changed its used status.
+    @param used
+        Thse value the status has changed to.
+    */
+    /*static*/ void PickupListener::broadcastPickupChangedUsed(Pickupable* pickup, bool used)
+    {
+        assert(pickup);
+
+        // Iterate through all PickupListeners and notify them by calling the method they overloaded.
+        for(PickupListener* listener : ObjectList<PickupListener>())
+            listener->pickupChangedUsed(pickup, used);
+    }
+
+    /**
+    @brief
+        Static method that is used to notify the PickupListener itself of the change in the pickedUp status of a Pickupable.
+        This is called in Pickupable.
+    @param pickup
+        The Pickupable that has changed its pickedUp status.
+    @param pickedUp
+        Thse value the status has changed to.
+    */
+    /*static*/ void PickupListener::broadcastPickupChangedPickedUp(Pickupable* pickup, bool pickedUp)
+    {
+        assert(pickup);
+
+        // Iterate through all PickupListeners and notify them by calling the method they overloaded.
+        for(PickupListener* listener : ObjectList<PickupListener>())
+            listener->pickupChangedPickedUp(pickup, pickedUp);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/PickupListener.h	(revision 11817)
@@ -0,0 +1,82 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+*/
+
+/**
+    @file PickupListener.h
+    @brief Definition of the PickupListener class.
+    @ingroup Pickup
+*/
+
+
+#ifndef _PickupListener_H__
+#define _PickupListener_H__
+
+#include "Pickupable.h"
+
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The PickupListener class facilitates the flow of information regarding the picking up, dropping, using and unusing of @ref orxonox::Pickupable "Pickupables" to interested parties (such as the @ref orxonox::PickupManager "PickupManager").
+
+        All you need to to do be notified is to inherit from PickupListener and implement the two methods <code>pickupChangedUsed()</code> and <code>pickupChangedPickedUp()</code>.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _OrxonoxExport PickupListener : virtual public OrxonoxInterface
+    {
+        public:
+            PickupListener();
+            virtual ~PickupListener();
+
+            static void broadcastPickupChangedUsed(Pickupable* pickup, bool used); //!< Static method that is used to notify the PickupListener itself of the change in the used status of a Pickupable.
+            static void broadcastPickupChangedPickedUp(Pickupable* pickup, bool pickedUp); //!< Static method that is used to notify the PickupListener itself of the change in the pickedUp status of a Pickupable.
+
+            /**
+            @brief Method that can be overloaded by any PickupListener to be notified of a change in the used status of a Pickupable.
+            @param pickup The Pickupable, whose used status has changed.
+            @param used The value the used status has changed to.
+            */
+            virtual void pickupChangedUsed(Pickupable* pickup, bool used) {}
+            /**
+            @brief Method that can be overloaded by any PickupListener to be notified of a change in the pickedUp status of a Pickupable.
+            @param pickup The Pickupable, whose pickedUp status has changed.
+            @param pickedUp The value the pickedUp status has changed to.
+            */
+            virtual void pickupChangedPickedUp(Pickupable* pickup, bool pickedUp) {}
+    };
+
+}
+
+#endif // _PickupListener_H__
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/Pickupable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/Pickupable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/Pickupable.cc	(revision 11817)
@@ -0,0 +1,339 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Pickupable.cc
+    @brief Implementation of the Pickupable class.
+*/
+
+#include "Pickupable.h"
+
+#include "core/class/Identifier.h"
+#include "core/CoreIncludes.h"
+#include "util/Convert.h"
+
+#include "infos/PlayerInfo.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "PickupCarrier.h"
+#include "PickupListener.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(Pickupable).inheritsFrom<OrxonoxInterface>().inheritsFrom<Rewardable>();
+
+    /**
+    @brief
+        Constructor. Registers the objects and initializes its member variables.
+    */
+    Pickupable::Pickupable() : used_(false), pickedUp_(false)
+    {
+        RegisterObject(Pickupable);
+
+        this->carrier_ = nullptr;
+
+        this->beingDestroyed_ = false;
+        this->enabled_ = true;
+    }
+
+    /**
+    @brief
+        Destructor.
+    */
+    Pickupable::~Pickupable()
+    {
+    }
+
+    /**
+    @brief
+        A method that is called by Destroyable::destroy() before the object is actually destroyed.
+    */
+    void Pickupable::preDestroy(void)
+    {
+        this->beingDestroyed_ = true;
+
+        if(this->isPickedUp())
+            this->drop(false); // Drops the pickup without creating a PickupSpawner.
+    }
+
+    /**
+    @brief
+        Is called internally within the pickup module to destroy pickups.
+    */
+    void Pickupable::destroy(void)
+    {
+        this->destroyPickup();
+    }
+
+    /**
+    @brief
+        Destroys a Pickupable.
+        If the Pickupable is already in the process of being destroyed a warning is displayed and this method is skipped.
+    */
+    void Pickupable::destroyPickup(void)
+    {
+        if(!this->isBeingDestroyed())
+            this->Destroyable::destroy();
+        else
+            orxout(internal_warning, context::pickups) << this->getIdentifier()->getName() << " may be unsafe. " << endl;
+    }
+
+    /**
+    @brief
+        Sets the Pickupable to used or unused, depending on the input.
+    @param used
+        If used is true the Pickupable is set to used, it is set to unused, otherwise.
+    @return
+        Returns true if the used state was changed, false if not.
+    */
+    bool Pickupable::setUsed(bool used)
+    {
+        if(this->used_ == used || !this->isPickedUp()) // If either the used status of the Pickupable doesn't change or it isn't picked up.
+            return false;
+
+        if((!this->isUsable() && used) || (!this->isUnusable() && !used)) // If either the Pickupable is requested to be used but it is not usable or the Pickupable is requested to be unused, while it is not unusable.
+            return false;
+
+        orxout(verbose, context::pickups) << "Pickupable (&" << this << ") set to used " << used << "." << endl;
+
+        this->used_ = used;
+
+        // Notify all the PickupListeners of the change.
+        PickupListener::broadcastPickupChangedUsed(this, used);
+
+        this->changedUsed();
+
+
+        return true;
+    }
+
+    /**
+    @brief
+        Get whether the given PickupCarrier is a target of this Pickupable.
+    @param carrier
+        The PickupCarrier of which it has to be determinde whether it is a target of this Pickupable.
+    @return
+        Returns true if the given PickupCarrier is a target.
+    */
+    bool Pickupable::isTarget(const PickupCarrier* carrier) const
+    {
+        if(carrier == nullptr)
+            return false;
+
+        return this->isTarget(carrier->getIdentifier());
+    }
+
+    /**
+    @brief
+        Get whether the given Identififer is a target of this Pickupable.
+    @param identifier
+        The PickupCarrier of which it has to be determinde whether it is a target of this Pickupable.
+    @return
+        Returns true if the given PickupCarrier is a target.
+    */
+    bool Pickupable::isTarget(const Identifier* identifier) const
+    {
+        // Iterate through all targets of this Pickupable.
+        for(Identifier* target : this->targets_)
+        {
+            if(identifier->isA(target))
+                return true;
+        }
+
+        return false;
+    }
+
+    /**
+    @brief
+        Add a PickupCarrier as target of this Pickupable.
+    @param target
+        The PickupCarrier to be added.
+    @return
+        Returns true if the target was added, false if not.
+    */
+    bool Pickupable::addTarget(PickupCarrier* target)
+    {
+        return this->addTarget(target->getIdentifier());
+    }
+
+    /**
+    @brief
+        Add a class, representetd by the input Identifier, as target of this Pickupable.
+    @param target
+        The Identifier to be added.
+    @return
+        Returns true if the target was added, false if not.
+    */
+    bool Pickupable::addTarget(Identifier* target)
+    {
+        if(this->isTarget(target)) // If the input target is already present in the list of targets.
+            return false;
+
+        orxout(verbose, context::pickups) << "Target " << target->getName() << " added to Pickupable (" << this->getIdentifier()->getName() << ") (&" << this << ")." << endl;
+        this->targets_.push_back(target);
+        return true;
+    }
+
+    /**
+    @brief
+        Can be called to pick up a Pickupable.
+    @param carrier
+        A pointer to the PickupCarrier that picks up the Pickupable.
+    @return
+        Returns true if the Pickupable was picked up, false if not.
+    */
+    bool Pickupable::pickup(PickupCarrier* carrier)
+    {
+        if(carrier == nullptr || this->isPickedUp()) // If carrier is nullptr or the Pickupable is already picked up.
+            return false;
+
+        if(!this->setCarrier(carrier))
+        {
+            orxout(internal_warning, context::pickups) << "A Pickupable (&" << this << ") was trying to be added to a PickupCarrier, but was already present." << endl;
+            return false;
+        }
+
+        this->setPickedUp(true);
+        orxout(verbose, context::pickups) << "Pickupable (&" << this << ") got picked up by a PickupCarrier (&" << carrier << ")." << endl;
+        return true;
+    }
+
+    /**
+    @brief
+        Can be called to drop a Pickupable.
+    @param createSpawner
+        If true a spawner is to be created for the dropped Pickupable. True is default.
+    @return
+        Returns true if the Pickupable has been dropped, false if not.
+    */
+    bool Pickupable::drop(bool createSpawner)
+    {
+        if(!this->isPickedUp()) // If the Pickupable is not picked up.
+            return false;
+
+        assert(this->getCarrier()); // The Carrier cannot be nullptr at this point.
+        if(!this->getCarrier()->removePickup(this)) //TODO Shouldn't this be a little later?
+            orxout(internal_warning, context::pickups) << "Pickupable (&" << this << ", " << this->getIdentifier()->getName() << ") is being dropped, but it was not present in the PickupCarriers list of pickups." << endl;
+
+        orxout(verbose, context::pickups) << "Pickupable (&" << this << ") got dropped up by a PickupCarrier (&" << this->getCarrier() << ")." << endl;
+        this->setUsed(false);
+        this->setPickedUp(false);
+
+        bool created = false;
+        if(createSpawner)
+            created = this->createSpawner();
+
+        this->setCarrier(nullptr);
+
+        if(!created && createSpawner) // If a PickupSpawner should have been created but wasn't.
+            this->destroy();
+
+        return true;
+    }
+
+    /**
+    @brief
+        Helper method to set the Pickupable to either picked up or not picked up.
+    @param pickedUp
+        The value this->pickedUp_ should be set to.
+    @return
+        Returns true if the pickedUp status was changed, false if not.
+    */
+    bool Pickupable::setPickedUp(bool pickedUp)
+    {
+        if(this->pickedUp_ == pickedUp) // If the picked up status has not changed.
+            return false;
+
+        orxout(verbose, context::pickups) << "Pickupable (&" << this << ") set to pickedUp " << pickedUp << "." << endl;
+
+        this->pickedUp_ = pickedUp;
+
+        // Notify all the PickupListeners of the change.
+        PickupListener::broadcastPickupChangedPickedUp(this, pickedUp);
+
+        if(!pickedUp) // if the Pickupable has been dropped it unregisters itself with its PickupCarrier.
+            this->getCarrier()->removePickup(this);
+        this->changedPickedUp();
+
+        return true;
+    }
+
+    /**
+    @brief
+        Sets the carrier of the Pickupable.
+    @param carrier
+        Sets the input PickupCarrier as the carrier of the pickup.
+    @param tell
+        If true (default) the pickup is added to the list of pickups in the PickupCarrier.
+    @return
+        Returns true if successful, false if not.
+    */
+    bool Pickupable::setCarrier(orxonox::PickupCarrier* carrier, bool tell)
+    {
+        if(this->carrier_ == carrier) // If the PickupCarrier doesn't change.
+            return false;
+
+        orxout(verbose, context::pickups) << "Pickupable (&" << this << ") changed Carrier (& " << carrier << ")." << endl;
+
+        if(carrier != nullptr && tell)
+        {
+            if(!carrier->addPickup(this))
+                return false;
+        }
+
+        this->carrier_ = carrier;
+        this->changedCarrier();
+        return true;
+    }
+
+    /**
+    @brief
+        Is called by the PickupCarrier when it is being destroyed.
+    */
+    void Pickupable::carrierDestroyed(void)
+    {
+        this->destroy();
+    }
+
+    /**
+    @brief
+        Method to transcribe a Pickupable as a Rewardable to the player.
+    @param player
+        A pointer to the PlayerInfo, do whatever you want with it.
+    @return
+        Return true if successful.
+    */
+    bool Pickupable::reward(PlayerInfo* player)
+    {
+        ControllableEntity* entity = player->getControllableEntity();
+        Pawn* pawn = static_cast<Pawn*>(entity);
+        PickupCarrier* carrier = static_cast<PickupCarrier*>(pawn);
+        return this->pickup(carrier);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/Pickupable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/Pickupable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/Pickupable.h	(revision 11817)
@@ -0,0 +1,194 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file Pickupable.h
+    @brief Definition of the Pickupable class.
+    @ingroup Pickup
+*/
+
+#ifndef _Pickupable_H__
+#define _Pickupable_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include "core/class/Super.h"
+
+#include "core/class/OrxonoxInterface.h"
+#include "Rewardable.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        An Interface (or more precisely an abstract class) to model and represent different (all kinds of) pickups.
+
+        Pickups (@ref orxonox::Pickupable "Pickupables") are objects that (quite unsurprisingly) can be picked up. Additionally they can be used and unused (transition from used to not used), and also dropped.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Pickup
+    */
+    class _OrxonoxExport Pickupable : virtual public OrxonoxInterface, public Rewardable
+    {
+        friend class PickupCarrier;
+
+        protected:
+            Pickupable(); //!< Default constructor.
+
+        public:
+            virtual ~Pickupable(); //!< Default destructor.
+
+            //! @brief Returns the representation name which refers to the name of the PickupRepresentation that is used to represent this pickup.
+            virtual const std::string& getRepresentationName() const = 0;
+
+            /**
+            @brief Get whether the Pickupable is currently in use or not.
+            @return Returns true if the Pickupable is currently in use.
+            */
+            inline bool isUsed(void) const
+                { return this->used_; }
+            /**
+            @brief  Should be called when the Pickupable has transited from used to unused or the other way around.
+                    Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedUsed); to their changdeUsed method.
+            */
+            virtual void changedUsed(void) {}
+
+            /**
+            @brief Get the carrier of the Pickupable.
+            @return Returns a pointer to the carrier of the Pickupable.
+            */
+            inline PickupCarrier* getCarrier(void)
+                { return this->carrier_; }
+            /**
+            @brief Should be called when the Pickupable has changed its PickupCarrier.
+                   Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedCarrier); to their changedCarrier method.
+            */
+            virtual void changedCarrier(void) {}
+
+            /**
+            @brief Returns whether the Pickupable is currently picked up.
+            @return Returns true if the Pickupable is currently picked up, false if not.
+            */
+            inline bool isPickedUp(void) const
+                { return this->pickedUp_; }
+            /**
+            @brief  Should be called when the Pickupable has transited from picked up to dropped or the other way around.
+                    Any Class overwriting this method must call its SUPER function by adding SUPER(Classname, changedPickedUp); to their changedPickedUp method.
+            */
+            virtual void changedPickedUp(void) {}
+
+            /**
+            @brief Returns whether the Pickupable can be used.
+            @return Returns true if it can be used.
+            */
+            inline bool isUsable(void) const
+                { return this->enabled_; }
+
+            /**
+            @brief Returns whether the Pickupable can be unused.
+            @return Returns true if it can be unused.
+            */
+            inline bool isUnusable(void) const
+                { return this->enabled_; }
+
+            /**
+            @brief Returns whether the Pickupable is enabled.
+                   Once a Pickupable is disabled it cannot be enabled again. A Pickupable that is disabled can neither be used nor unused.
+            @return Returns true if the Pickupable is enabled.
+            */
+            inline bool isEnabled(void) const
+                { return this->enabled_; }
+
+            bool pickup(PickupCarrier* carrier); //!< Can be called to pick up a Pickupable.
+            bool drop(bool createSpawner = true); //!< Can be called to drop a Pickupable.
+
+            virtual bool isTarget(const PickupCarrier* carrier) const; //!< Get whether the given PickupCarrier is a target of this Pickupable.
+            bool isTarget(const Identifier* identifier) const; //!< Get whether a given class, represented by the input Identifier, is a target of this Pickupable.
+            bool addTarget(PickupCarrier* target); //!< Add a PickupCarrier as target of this Pickupable.
+            bool addTarget(Identifier* identifier); //!< Add a class, representetd by the input Identifier, as target of this Pickupable.
+
+            bool setUsed(bool used); //!< Sets the Pickupable to used or unused, depending on the input.
+            bool setPickedUp(bool pickedUp); //!< Helper method to set the Pickupable to either picked up or not picked up.
+            bool setCarrier(PickupCarrier* carrier, bool tell = true); //!< Sets the carrier of the Pickupable.
+
+            void destroy(void); //!< Is called internally within the Pickupable module to destroy pickups.
+
+        protected:
+            virtual void preDestroy(void) override; //!< A method that is called by Destroyable::destroy() before the object is actually destroyed.
+            virtual void destroyPickup(void); //!< Destroys a Pickupable.
+            virtual void carrierDestroyed(void); //!< Is called by the PickupCarrier when it is being destroyed.
+
+            /**
+            @brief Sets the Pickuapble to disabled.
+            */
+            inline void setDisabled(void)
+                { this->enabled_ = false; }
+
+            /**
+            @brief Check whether the Pickupable is in the process of being destroyed.
+            @return Returns true if so.
+            */
+            inline bool isBeingDestroyed(void)
+                { return this->beingDestroyed_; }
+
+            /**
+            @brief Facilitates the creation of a PickupSpawner upon dropping of the Pickupable.
+                   This method must be implemented by any class directly inheriting from Pickupable.
+            @return Returns true if a spawner was created, false if not.
+            */
+            virtual bool createSpawner(void) = 0;
+
+        private:
+
+            bool used_; //!< Whether the Pickupable is currently in use or not.
+            bool pickedUp_; //!< Whether the Pickupable is currently picked up or not.
+
+            bool enabled_; //!< Whether the Pickupable is enabled or not.
+
+            PickupCarrier* carrier_; //!< The PickupCarrier of the Pickupable.
+            std::list<Identifier*> targets_; //!< The possible targets of this Pickupable.
+
+            bool beingDestroyed_; //!< Is true if the Pickupable is in the process of being destroyed.
+
+        // For implementing the Rewardable interface:
+        public:
+            virtual bool reward(PlayerInfo* player) override; //!< Method to transcribe a Pickupable as a Rewardable to the player.
+
+    };
+
+    //! SUPER functions.
+    SUPER_FUNCTION(9, Pickupable, changedUsed, false);
+    SUPER_FUNCTION(10, Pickupable, changedCarrier, false);
+    SUPER_FUNCTION(11, Pickupable, changedPickedUp, false);
+}
+
+#endif /* _Pickupable_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/PlayerTrigger.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/PlayerTrigger.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/PlayerTrigger.h	(revision 11817)
@@ -0,0 +1,104 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file PlayerTrigger.h
+    @brief Definition of the PlayerTrigger class.
+    @ingroup Triggers
+*/
+
+#ifndef _PlayerTrigger_H__
+#define _PlayerTrigger_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/class/OrxonoxInterface.h"
+#include "core/object/WeakPtr.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        PlayerTrigger is an interface if implemented by a specific trigger can be used to recover the Player (or the @ref orxonox::Pawn "Pawn") that triggered it.
+
+    @author
+        Damian 'Mozork' Frick
+
+    @ingroup Triggers
+    */
+    class _OrxonoxExport PlayerTrigger : virtual public OrxonoxInterface
+    {
+    public:
+        PlayerTrigger();
+        virtual ~PlayerTrigger() {}
+
+        /**
+        @brief Returns the Pawn that triggered the PlayerTrigger.
+        @return Returns a pointer to the Pawn that triggered the PlayerTrigger.
+        */
+        inline Pawn* getTriggeringPawn(void) const
+            { return this->pawn_; }
+
+        /**
+        @brief Returns the player that triggered the PlayerTrigger.
+        @return Returns a pointer to the PlayerInfo that triggered the PlayerTrigger.
+        */
+        inline PlayerInfo* getTriggeringPlayer(void) const
+            { return this->player_; }
+
+        /**
+        @brief Checks whether the PlayerTrigger normally returns a Pawn/PlayerInfo.
+        @return Returns true if the PlayerTrigger normally returns a Pawn/PlayerInfo.
+        */
+        inline bool isForPlayer(void) const
+           { return this->isForPlayer_; }
+
+    protected:
+        /**
+        @brief Set the player that triggered the PlayerTrigger. This is normally done by classes inheriting vom PlayerTrigger.
+        @param pawn A pointer to the Pawn that triggered the PlayerTrigger.
+        */
+        void setTriggeringPawn(Pawn* pawn);
+
+        /**
+        @brief Set whether the PlayerTrigger normally is triggered by Pawns.
+        @param isForPlayer Should be true when the PlayerTrigger should be set to normally be triggered by Pawns, false if not.
+        */
+        inline void setForPlayer(bool isForPlayer)
+           { this->isForPlayer_ = isForPlayer; }
+
+    private:
+        WeakPtr<PlayerInfo> player_; //!< The player that triggered the PlayerTrigger.
+        WeakPtr<Pawn> pawn_; //!< The Pawn that triggered the PlayerTrigger.
+        bool isForPlayer_; //!< Is true when the PlayerTrigger should be set to normally be triggered by Pawns.
+
+    };
+
+}
+
+#endif /* _PlayerTrigger_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarListener.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarListener.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarListener.h	(revision 11817)
@@ -0,0 +1,51 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _RadarListener_H__
+#define _RadarListener_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport RadarListener : virtual public OrxonoxInterface
+    {
+    public:
+        RadarListener();
+        virtual ~RadarListener() { }
+
+        virtual void addObject(RadarViewable* viewable) = 0;
+        virtual void removeObject(RadarViewable* viewable) = 0;
+        virtual void objectChanged(RadarViewable* viewable) = 0;
+        virtual float getRadarSensitivity() const = 0;
+        virtual void radarTick(float dt) = 0;
+    };
+}
+
+#endif /* _RadarListener_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarViewable.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarViewable.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarViewable.cc	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "RadarViewable.h"
+
+#include "util/StringUtils.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "worldentities/WorldEntity.h"
+#include "Radar.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(RadarViewable).inheritsFrom<OrxonoxInterface>();
+
+    /**
+        @brief Constructor.
+    */
+    RadarViewable::RadarViewable(BaseObject* creator, const WorldEntity* wePtr)
+        : isHumanShip_(false)
+        , bVisibility_(true)
+        , bInitialized_(false)
+        , wePtr_(wePtr)
+        , radarObjectCamouflage_(0.0f)
+        , radarObjectShape_(Shape::Dot)
+        , radarObjectDescription_("staticObject")
+        , scale_(1.0f)
+    {
+        RegisterObject(RadarViewable);
+
+        this->uniqueId_=getUniqueNumberString();
+        if( GameMode::showsGraphics() )
+        {
+            this->radar_ = creator->getScene()->getRadar();
+            this->radar_->addRadarObject(this);
+        }
+        this->bInitialized_ = true;
+    }
+
+
+    RadarViewable::~RadarViewable()
+    {
+
+        if( this->bInitialized_ )
+        {
+            if( GameMode::showsGraphics() )
+            {
+                this->radar_->removeRadarObject(this);
+            }
+        }
+    }
+
+//     void RadarViewable::setRadarObjectDescription(const std::string& str)
+//     {
+//         Radar* radar = this->getWorldEntity()->getScene()->getRadar();
+//         if (radar)
+//             this->radarObjectShape_ = radar->addObjectDescription(str);
+//         else
+//         {
+//             orxout(internal_warning) << "Attempting to access the radar, but the radar is non existent." << endl;
+//         }
+//         this->radarObjectDescription_ = str;
+//     }
+
+    const Vector3& RadarViewable::getRVWorldPosition() const
+    {
+        const WorldEntity* object = this->getWorldEntity();
+        validate(object);
+        return object->getWorldPosition();
+    }
+
+    Vector3 RadarViewable::getRVOrientedVelocity() const
+    {
+        const WorldEntity* object = this->getWorldEntity();
+        validate(object);
+        return object->getWorldOrientation() * object->getVelocity();
+    }
+
+    Vector3 RadarViewable::getRVVelocity() const
+    {
+        const WorldEntity* object = this->getWorldEntity();
+        validate(object);
+        return object->getVelocity();
+    }
+
+    void RadarViewable::validate(const WorldEntity* object) const
+    {
+        if (!object)
+        {
+            orxout(user_error) << "Assertion: Every RadarViewable has to be assigned a WorldEntity pointer!" << endl;
+            assert(0);
+        }
+    }
+
+    void RadarViewable::settingsChanged()
+    {
+        if( GameMode::showsGraphics() )
+        {
+            this->radar_->radarObjectChanged(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarViewable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarViewable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/RadarViewable.h	(revision 11817)
@@ -0,0 +1,174 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _RadarViewable_H__
+#define _RadarViewable_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <cassert>
+
+#include "util/Math.h"
+#include "core/class/OrxonoxInterface.h"
+#include "core/object/StrongPtr.h"
+
+namespace orxonox
+{
+    class BaseObject;
+
+    /**
+    @brief Interface for receiving window events.
+    */
+    class _OrxonoxExport RadarViewable : virtual public OrxonoxInterface
+    {
+    public:
+        enum class Shape
+        {
+            Square,
+            Dot,
+            Triangle
+        };
+
+
+    public:
+        RadarViewable(BaseObject* creator, const WorldEntity* wePtr);
+        virtual ~RadarViewable();
+
+        virtual void setRadarName(const std::string& name)
+            {
+            // The following if-clause hides objects with radarname "HIDDEN"
+                if (name == "HIDDEN")
+                {
+                    this->bVisibility_ = false;
+                    this->settingsChanged();
+                }
+                if (this->radarName_ != name)
+                {
+                    this->radarName_ = name;
+                    this->settingsChanged();
+                }
+            }
+        const std::string& getRadarName() const
+            { return this->radarName_; }
+
+        inline void setRadarObjectCamouflage(float camouflage)
+            {
+                if( this->radarObjectCamouflage_ != camouflage )
+                {
+                    this->radarObjectCamouflage_ = camouflage;
+                    this->settingsChanged();
+                }
+            }
+        inline float getRadarObjectCamouflage() const
+            { return this->radarObjectCamouflage_; }
+
+        inline void setRadarObjectColour(const ColourValue& colour)
+            {
+                if(this->radarObjectColour_ != colour)
+                {
+                    this->radarObjectColour_ = colour;
+                    this->settingsChanged();
+                }
+            }
+        inline const ColourValue& getRadarObjectColour() const
+            { return this->radarObjectColour_; }
+
+//         void setRadarObjectDescription(const std::string& str);
+//         inline const std::string& getRadarObjectDescription() const
+//             { return this->radarObjectDescription_; }
+
+        inline void setRadarVisibility(bool b)
+            {
+                if(b!=this->bVisibility_)
+                {
+                    this->bVisibility_ = b;
+                    this->settingsChanged();
+                }
+            }
+        inline bool getRadarVisibility() const
+            { return this->bVisibility_; }
+
+        virtual const WorldEntity* getWorldEntity() const{ return this->wePtr_; }
+
+        const Vector3& getRVWorldPosition() const;
+        Vector3 getRVOrientedVelocity() const;
+        Vector3 getRVVelocity() const;
+
+        inline void setRadarObjectShape(Shape shape)
+            {
+                if( this->radarObjectShape_ != shape )
+                {
+                    this->radarObjectShape_ = shape;
+                    this->settingsChanged();
+                }
+            }
+        inline Shape getRadarObjectShape() const
+            { return this->radarObjectShape_; }
+
+        inline void setRadarObjectScale(float scale)
+            {
+                if(this->scale_ != scale)
+                {
+                    this->scale_ = scale;
+                    this->settingsChanged();
+                }
+            }
+        inline float getRadarObjectScale() const
+            { return this->scale_; }
+
+        void settingsChanged();
+
+
+        bool isHumanShip_;
+        inline const std::string& getUniqueId()
+        {
+            return this->uniqueId_;
+        }
+
+    private:
+        void validate(const WorldEntity* object) const;
+        bool bVisibility_;
+        bool bInitialized_;
+        //Map
+        std::string uniqueId_;
+
+
+        //Radar
+        const WorldEntity* wePtr_;
+        StrongPtr<Radar> radar_;
+        float radarObjectCamouflage_;
+        Shape radarObjectShape_;
+        std::string radarObjectDescription_;
+        ColourValue radarObjectColour_;
+        float scale_;
+        std::string radarName_;
+    };
+}
+
+#endif /* _RadarViewable_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/Rewardable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/Rewardable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/Rewardable.h	(revision 11817)
@@ -0,0 +1,70 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Damian 'Mozork' Frick
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file
+    @brief Definition of the Rewardable class.
+*/
+
+#ifndef _Rewardable_H__
+#define _Rewardable_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Rewardable is an Interface, that can be implemented by any object to enable it to be given as reward to a player through QuestEffects. (With the AddReward effect.)
+
+        It just needs to inherit form Rewardable, and implement the reward() method.
+    @author
+        Damian 'Mozork' Frick
+    */
+    class _OrxonoxExport Rewardable : virtual public OrxonoxInterface
+    {
+        public:
+            Rewardable();
+            virtual ~Rewardable() {}
+
+            /**
+            @brief
+                Method to transcribe a rewardable object to the player.
+                Must be implemented by every class inheriting from Rewardable.
+            @param player
+                A pointer to the PlayerInfo, do whatever you want with it.
+            @return
+                Return true if successful.
+            */
+            virtual bool reward(PlayerInfo* player) = 0;
+
+    };
+}
+
+#endif /* _Rewardable_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/interfaces/TeamColourable.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/interfaces/TeamColourable.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/interfaces/TeamColourable.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamColourable_H__
+#define _TeamColourable_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/UtilPrereqs.h"
+#include "core/class/OrxonoxInterface.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport TeamColourable : virtual public OrxonoxInterface
+    {
+        public:
+            virtual void setTeamColour(const ColourValue& colour) = 0;
+
+        protected:
+            TeamColourable();
+    };
+}
+
+#endif /* _TeamColourable_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/items/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,7 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  Item.cc
+  Engine.cc
+  MultiStateEngine.cc
+  ShipPart.cc
+  PartDestructionEvent.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/items/Engine.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/Engine.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/Engine.cc	(revision 11817)
@@ -0,0 +1,272 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Engine.h"
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+#include "util/Math.h"
+
+#include "Scene.h"
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    RegisterClass(Engine);
+
+    /**
+    @brief
+        Constructor. Registers and initializes the object.
+    */
+    Engine::Engine(Context* context) : Item(context)
+    {
+        RegisterObject(Engine);
+
+        this->ship_ = nullptr;
+        this->shipID_ = OBJECTID_UNKNOWN;
+        this->relativePosition_ = Vector3::ZERO;
+
+        this->boostFactor_ = 1.5f;
+
+        this->maxSpeedFront_ = 0.0f;
+        this->maxSpeedBack_ = 0.0f;
+        this->maxSpeedLeftRight_ = 0.0f;
+        this->maxSpeedUpDown_ = 0.0f;
+
+        this->accelerationFront_ = 0.0f;
+        this->accelerationBrake_ = 0.0f;
+        this->accelerationBack_ = 0.0f;
+        this->accelerationLeftRight_ = 0.0f;
+        this->accelerationUpDown_ = 0.0f;
+
+        this->speedAdd_ = 0.0f;
+        this->speedMultiply_ = 1.0f;
+
+        this->setConfigValues();
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destructor. Destroys the object and removes it from the SpaceShip.
+    */
+    Engine::~Engine()
+    {
+        if (this->isInitialized())
+        {
+            // Remove the engine from the ShapeShip.
+            if (this->ship_ && this->ship_->hasEngine(this))
+                this->ship_->removeEngine(this);
+        }
+    }
+
+    void Engine::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Engine, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Engine, "boostfactor", setBoostFactor, getBoostFactor, xmlelement, mode);
+
+        XMLPortParam(Engine, "speedfront",     setMaxSpeedFront,     setMaxSpeedFront,     xmlelement, mode);
+        XMLPortParam(Engine, "speedback",      setMaxSpeedBack,      setMaxSpeedBack,      xmlelement, mode);
+        XMLPortParam(Engine, "speedleftright", setMaxSpeedLeftRight, setMaxSpeedLeftRight, xmlelement, mode);
+        XMLPortParam(Engine, "speedupdown",    setMaxSpeedUpDown,    setMaxSpeedUpDown,    xmlelement, mode);
+
+        XMLPortParam(Engine, "accelerationfront",     setAccelerationFront,     setAccelerationFront,     xmlelement, mode);
+        XMLPortParam(Engine, "accelerationbrake",     setAccelerationBrake,     setAccelerationBrake,     xmlelement, mode);
+        XMLPortParam(Engine, "accelerationback",      setAccelerationBack,      setAccelerationBack,      xmlelement, mode);
+        XMLPortParam(Engine, "accelerationleftright", setAccelerationLeftRight, setAccelerationLeftRight, xmlelement, mode);
+        XMLPortParam(Engine, "accelerationupdown",    setAccelerationUpDown,    setAccelerationUpDown,    xmlelement, mode);
+
+        XMLPortParam(Engine, "position", setRelativePosition, getRelativePosition, xmlelement, mode);
+        XMLPortParam(Engine, "template", setEngineTemplate, getEngineTemplate, xmlelement, mode);
+    }
+
+    void Engine::setConfigValues()
+    {
+    }
+
+    void Engine::registerVariables()
+    {
+        registerVariable(this->shipID_, VariableDirection::ToClient, new NetworkCallback<Engine>(this, &Engine::networkcallback_shipID));
+
+        registerVariable(this->boostFactor_, VariableDirection::ToClient);
+
+        registerVariable(this->maxSpeedFront_,     VariableDirection::ToClient);
+        registerVariable(this->maxSpeedBack_,      VariableDirection::ToClient);
+        registerVariable(this->maxSpeedLeftRight_, VariableDirection::ToClient);
+        registerVariable(this->maxSpeedUpDown_,    VariableDirection::ToClient);
+
+        registerVariable(this->accelerationFront_,     VariableDirection::ToClient);
+        registerVariable(this->accelerationBrake_,     VariableDirection::ToClient);
+        registerVariable(this->accelerationBack_,      VariableDirection::ToClient);
+        registerVariable(this->accelerationLeftRight_, VariableDirection::ToClient);
+        registerVariable(this->accelerationUpDown_,    VariableDirection::ToClient);
+
+        registerVariable(this->speedAdd_, VariableDirection::ToClient);
+        registerVariable(this->speedMultiply_, VariableDirection::ToClient);
+    }
+
+    void Engine::networkcallback_shipID()
+    {
+        this->ship_ = nullptr;
+
+        if (this->shipID_ != OBJECTID_UNKNOWN)
+        {
+            Synchronisable* object = Synchronisable::getSynchronisable(this->shipID_);
+            if (object)
+                this->addToSpaceShip(orxonox_cast<SpaceShip*>(object));
+        }
+    }
+
+    /**
+    @brief
+        Run the engine for a given time interval.
+        Is called each tick by SpaceShip.
+    @param dt
+        The time since last tick.
+    */
+    void Engine::run(float dt)
+    {
+        if (this->ship_ == nullptr)
+        {
+            if (this->shipID_ != 0)
+            {
+                this->networkcallback_shipID();
+
+                if (this->ship_ == nullptr)
+                    return;
+            }
+            else
+                return;
+        }
+
+        if (!this->isActive())
+            return;
+
+        // Get the desired steering direction and amount, clipped to length 1 at maximum.
+        Vector3 steering = (this->getSteering().length() > 1.0f ? this->getSteering().normalisedCopy() : this->getSteering());
+
+        // Get the ships velocity.
+        Vector3 velocity = this->ship_->getLocalVelocity();
+        Vector3 acceleration = Vector3::ZERO;
+
+        // If there is forward steering action.
+        if (steering.z < 0)
+        {
+            if (this->maxSpeedFront_ != 0)
+            {
+                float boostfactor = (this->ship_->isBoosting() ? this->boostFactor_ : 1.0f); // Boost factor is 1.0 if not boosting.
+                // Boosting can lead to velocities larger the maximal forward velocity.
+                acceleration.z = steering.z * this->accelerationFront_ * boostfactor * clamp((this->maxSpeedFront_ - -velocity.z/boostfactor) / this->maxSpeedFront_, 0.0f, 1.0f);
+            }
+        }
+        // If there is backward steering action.
+        else if (steering.z > 0)
+        {
+            // Either breaking
+            if (velocity.z < 0)
+                acceleration.z = steering.z * this->accelerationBrake_;
+            // or backward flight.
+            else if (this->maxSpeedBack_ != 0)
+                acceleration.z = steering.z * this->accelerationBack_ * clamp((this->maxSpeedBack_ - velocity.z) / this->maxSpeedBack_, 0.0f, 1.0f);
+        }
+        // If there is left-right steering action.
+        if (this->maxSpeedLeftRight_ != 0)
+        {
+            if (steering.x < 0)
+                acceleration.x = steering.x * this->accelerationLeftRight_ * clamp((this->maxSpeedLeftRight_ - -velocity.x) / this->maxSpeedLeftRight_, 0.0f, 1.0f);
+            else if (steering.x > 0)
+                acceleration.x = steering.x * this->accelerationLeftRight_ * clamp((this->maxSpeedLeftRight_ - velocity.x) / this->maxSpeedLeftRight_, 0.0f, 1.0f);
+        }
+        // If there is up-down steering action.
+        if (this->maxSpeedUpDown_ != 0)
+        {
+            if (steering.y < 0)
+                acceleration.y = steering.y * this->accelerationUpDown_ * clamp((this->maxSpeedUpDown_ - -velocity.y) / this->maxSpeedUpDown_, 0.0f, 1.0f);
+            else if (steering.y > 0)
+                acceleration.y = steering.y * this->accelerationUpDown_ * clamp((this->maxSpeedUpDown_ - velocity.y) / this->maxSpeedUpDown_, 0.0f, 1.0f);
+        }
+
+        // NOTE: Bullet always uses global coordinates.
+        this->ship_->addAcceleration(this->ship_->getOrientation() * (acceleration*this->getSpeedMultiply()+Vector3(0,0,-this->getSpeedAdd())), this->ship_->getOrientation() * this->relativePosition_);
+    }
+
+    /**
+    @brief
+        Adds the Engine to the input SpaceShip.
+    @param ship
+        A pointer to the SpaceShip to which the engine is added.
+    */
+    void Engine::addToSpaceShip(SpaceShip* ship)
+    {
+        this->ship_ = ship;
+
+        if (ship)
+        {
+            this->shipID_ = ship->getObjectID();
+            if (!ship->hasEngine(this))
+                ship->addEngine(this);
+        }
+    }
+
+    /**
+    @brief
+        Get the direction and magnitude of the steering imposed upon the Engine.
+    @return
+        Returns the direction and magnitude of the steering imposed upon the Engine.
+        Is the zero vector if the Engine doesn't belong to a ship.
+    */
+    const Vector3& Engine::getSteering() const
+    {
+        if (this->ship_)
+            return this->ship_->getSteeringDirection();
+        else
+            return Vector3::ZERO;
+    }
+
+    /**
+    @brief
+        Load the engine template.
+        Causes all parameters specified by the template to be applied to the Engine.
+    */
+    void Engine::loadEngineTemplate()
+    {
+        if(!this->engineTemplate_.empty())
+        {
+            orxout(verbose, context::templates) << "Loading an engine template: " << this->engineTemplate_ << endl;
+            Template *temp = Template::getTemplate(this->engineTemplate_);
+            if(temp)
+            {
+                this->addTemplate(temp);
+            }
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/items/Engine.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/Engine.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/Engine.h	(revision 11817)
@@ -0,0 +1,286 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Engine_H__
+#define _Engine_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/OrxAssert.h"
+
+#include "Item.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The Engine class provides propulsion to the SpaceShip.
+        
+        There are many parameters that can be specified:
+        - The <b>relativePosition</b>, specifies the position relative to the center of the SpaceShip the Engine is mounted on.
+        - The <b>maximal speed</b>, there are four maximal speeds that can be specified: The <b>speedfront</b>, the maximal forward speed. The <b>speedback</b>, the maximal backward speed. The <b>speedleftright</b>, the maximal speed in y-direction of the SpaceShip coordinate frame. The <b>speedupdown</b>, the maximal speed in z-direction of the SpaceShip coordinate frame. All maximal speeds (naturally) have to be non-negative.
+        - The <b>acceleration</b>, there are five types of acceleration that can be specified: The <b>accelerationfront</b>, the forward acceleration. The <b>accelerationbrake</b>, the braking acceleration. The <b>accelerationback</b>, the backward acceleration. The <b>accelerationleftright</b>, the acceleration in y-direction. The <b>accelerationupdown</b>, the acceleration in z-direction. All accelerations have to be non-negative.
+        - The <b>boostfactor</b>, specifies the factor by which boosting increases the speed. This has to be non-negative, as well. Beware that maximal speeds can be overcome through boosting.
+        - The <b>template</b>, the name of the engine template. Allows for parameters of the Engine be set trough a template.
+        
+    @author
+        Fabian 'x3n' Landau
+    */
+    class _OrxonoxExport Engine : public Item
+    {
+        public:
+            Engine(Context* context);
+            virtual ~Engine();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            void setConfigValues();
+
+            virtual void run(float dt); // Run the engine for a given time interval.
+
+            virtual void addToSpaceShip(SpaceShip* ship); // Adds the Engine to the input SpaceShip.
+            /**
+            @brief Get the SpaceShip this Engine is mounted on.
+            @return Returns a pointer to the SpaceShip. nullptr if it isn't mounted on any ship.
+            */
+            inline SpaceShip* getShip() const
+                { return this->ship_; }
+
+            /**
+            @brief Set the relative position of the Engine.
+            @param position The relative position with respect to the SpaceShip it is mounted on.
+            */
+            inline void setRelativePosition(const Vector3 &position)
+                { this->relativePosition_ = position; }
+            /**
+            @brief Get the relative position of the Engine.
+            @return Returns the relative position with respect to the SpaceShip it is mounted on.
+            */
+            inline const Vector3& getRelativePosition() const
+                { return this->relativePosition_; }
+
+            /**
+            @brief Set the maximal forward speed of the Engine.
+            @param speed The speed to be set. Must be non-negative.
+            */
+            //TODO: Better OrxVerify()?
+            inline void setMaxSpeedFront(float speed)
+                { OrxAssert(speed >= 0.0f, "The input speed must be non-negative."); this->maxSpeedFront_ = speed; }
+            /**
+            @brief Set the maximal backward speed of the Engine.
+            @param speed The speed to be set. Must be non-negative.
+            */
+            inline void setMaxSpeedBack(float speed)
+                { OrxAssert(speed >= 0.0f, "The input speed must be non-negative."); this->maxSpeedBack_ = speed; }
+            /**
+            @brief Set the maximal left-right speed of the Engine.
+            @param speed The speed to be set. Must be non-negative.
+            */
+            inline void setMaxSpeedLeftRight(float speed)
+                { OrxAssert(speed >= 0.0f, "The input speed must be non-negative."); this->maxSpeedLeftRight_ = speed; }
+            /**
+            @brief Set the maximal up-down speed of the Engine.
+            @param speed The speed to be set. Must be non-negative.
+            */
+            inline void setMaxSpeedUpDown(float speed)
+                { OrxAssert(speed >= 0.0f, "The input speed must be non-negative."); this->maxSpeedUpDown_ = speed; }
+
+            /**
+            @brief Get the maximal forward speed of the Engine.
+            @return Returns the maximal forward speed of the Engine. Is non-negative.
+            */
+            inline float getMaxSpeedFront() const
+                { return this->maxSpeedFront_; }
+            /**
+            @brief Get the maximal backward speed of the Engine.
+            @return Returns the maximal backward speed of the Engine. Is non-negative.
+            */
+            inline float getMaxSpeedBack() const
+                { return this->maxSpeedBack_; }
+            /**
+            @brief Get the maximal left-right speed of the Engine.
+            @return Returns the maximal left-right speed of the Engine. Is non-negative.
+            */
+            inline float getMaxSpeedLeftRight() const
+                { return this->maxSpeedLeftRight_; }
+            /**
+            @brief Get the maximal up-down speed of the Engine.
+            @return Returns the maximal up-down speed of the Engine. Is non-negative.
+            */
+            inline float getMaxSpeedUpDown() const
+                { return this->maxSpeedUpDown_; }
+
+            /**
+            @brief Set the forward acceleration produced by the Engine.
+            @param acceleration The forward acceleration produced by the Engine. Must be non-negative.
+            */
+            inline void setAccelerationFront(float acceleration)
+                { OrxAssert(acceleration >= 0.0f, "The input acceleration must be non-negative."); this->accelerationFront_ = acceleration; }
+            /**
+            @brief Set the breaking acceleration produced by the Engine.
+            @param acceleration The breaking acceleration produced by the engine. Must be non-negative.
+            */
+            inline void setAccelerationBrake(float acceleration)
+                { OrxAssert(acceleration >= 0.0f, "The input acceleration must be non-negative."); this->accelerationBrake_ = acceleration; }
+            /**
+            @brief Set the backward acceleration produced by the Engine.
+            @param acceleration The backward acceleration produced by the Engine.
+            */
+            inline void setAccelerationBack(float acceleration)
+                { OrxAssert(acceleration >= 0.0f, "The input acceleration must be non-negative."); this->accelerationBack_ = acceleration; }
+            /**
+            @brief Set the left-right acceleration produced by the Engine.
+            @param acceleration The left-right acceleration produced by the Engine.
+            */
+            inline void setAccelerationLeftRight(float acceleration)
+                { OrxAssert(acceleration >= 0.0f, "The input acceleration must be non-negative."); this->accelerationLeftRight_ = acceleration; }
+            /**
+            @brief Set the up-down acceleration produced by the Engine.
+            @param acceleration The
+            */
+            inline void setAccelerationUpDown(float acceleration)
+                { OrxAssert(acceleration >= 0.0f, "The input acceleration must be non-negative."); this->accelerationUpDown_ = acceleration; }
+
+            /**
+            @brief Get the forward acceleration produced by the Engine.
+            @return Returns the forward acceleration produced by the Engine. Is non-negative.
+            */
+            inline float getAccelerationFront() const
+                { return this->accelerationFront_; }
+            /**
+            @brief Get the breaking acceleration produced by the Engine.
+            @return Returns the breaking acceleration produced by the Engine. Is non-negative.
+            */
+            inline float getAccelerationBrake() const
+                { return this->accelerationBrake_; }
+            /**
+            @brief Get the backward acceleration produced by the Engine.
+            @return Returns the backward acceleration produced by the Engine. Is non-negative.
+            */
+            inline float getAccelerationBack() const
+                { return this->accelerationBack_; }
+            /**
+            @brief Get the left-right acceleration produced by the Engine.
+            @return Returns the left-right acceleration produced by the Engine. Is non-negative.
+            */
+            inline float getAccelerationLeftRight() const
+                { return this->accelerationLeftRight_; }
+            /**
+            @brief Get the up-down acceleration produced by the Engine.
+            @return Returns the up-down acceleration produced by the Engine. Is non-negative.
+            */
+            inline float getAccelerationUpDown() const
+                { return this->accelerationUpDown_; }
+
+            /**
+            @brief Set the factor by which boosting increases the forward acceleration of the Engine.
+            @param factor The boost factor. Needs to be positive.
+            */
+            inline void setBoostFactor(float factor)
+                { OrxAssert(factor > 0.0f, "The input factor must be positive."); this->boostFactor_ = factor; }
+            /**
+            @brief Get the boost factor of the Engine.
+            @return Returns the factor by which boosting increases the forward acceleration of the Engine. Is positive.
+            */
+            inline float getBoostFactor() const
+                { return this->boostFactor_; }
+
+            /**
+            @brief Add to the additional forward speed factor.
+            @param speed The speed that is added to the additional forward speed. Must be non-negative.
+            */
+            inline void addSpeedAdd(float speed)
+                { this->speedAdd_ += speed; }
+            /**
+            @brief Add to the forward speed multiplication factor.
+            @param factor The factor by which the forward speed multiplication factor is multiplied. Must be non-negative.
+            */
+            inline void addSpeedMultiply(float factor)
+                { OrxAssert(factor >= 0.0f, "The factor must be non-negative."); this->speedMultiply_ *= factor; }
+
+            /**
+            @brief Get the additional forward speed.
+            @return Returns the additional forward speed.
+            */
+            inline float getSpeedAdd(void)
+                { return this->speedAdd_; }
+            /**
+            @brief Get the forward speed multiplication factor.
+            @return Returns the forward speed multiplication factor.
+            */
+            inline float getSpeedMultiply(void)
+                { return this->speedMultiply_; }
+
+            /**
+            @brief Set the engine template, that specifies the parameters for the Engine.
+            @param temp The name of the engine template.
+            */
+            inline void setEngineTemplate(const std::string& temp)
+                { this->engineTemplate_ = temp; this->loadEngineTemplate(); }
+            /**
+            @brief Get the engine template, that specifies the parameters for the Engine.
+            @return Returns the name of the engine template.
+            */
+            inline const std::string& getEngineTemplate() const
+                { return this->engineTemplate_; }
+
+        protected:
+            void loadEngineTemplate(); // Load the engine template.
+
+            virtual const Vector3& getSteering() const; // Get the steering direction imposed upon the Engine.
+
+        private:
+            void registerVariables();
+            void networkcallback_shipID();
+
+            std::string engineTemplate_; //!< The template that specifies the Engine's parameters.
+
+            SpaceShip* ship_; //!< A pointer to the SpaceShip the Engine is mounted on.
+            unsigned int shipID_; //!< Object ID of the SpaceShip the Engine is mounted on.
+            Vector3 relativePosition_; //!< The relative position of the Engine with respect to the SpaceShip it is mounted on.
+
+            float boostFactor_; //!< The factor by which boosting increases the forward acceleration.
+
+            float speedAdd_; //!< Additional forward speed. Is not bounded by the maximal forward speed.
+            float speedMultiply_; //!< Forward speed multiplication factor. Is not bounded by the maximal forward speed.
+
+            float maxSpeedFront_; //!< The maximal forward speed.
+            float maxSpeedBack_; //!< The maximal backward speed.
+            float maxSpeedLeftRight_; //!< The maximal left-right speed.
+            float maxSpeedUpDown_; //!< The maximal up-down speed.
+
+            float accelerationFront_; //!< Forward acceleration produced by the Engine.
+            float accelerationBrake_; //!< Breaking acceleration produced by the Engine.
+            float accelerationBack_; //!< Backward acceleration produced by the Engine.
+            float accelerationLeftRight_; //!< Left-right acceleration produced by the Engine.
+            float accelerationUpDown_; //!< Up-down acceleration produced by the Engine.
+
+    };
+}
+
+#endif /* _Engine_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/items/Item.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/Item.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/Item.cc	(revision 11817)
@@ -0,0 +1,40 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Item.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(Item);
+
+    Item::Item(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        RegisterObject(Item);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/items/Item.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/Item.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/Item.h	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Item_H__
+#define _Item_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Item : public BaseObject, public Synchronisable
+    {
+        public:
+            Item(Context* context);
+            virtual ~Item() {}
+    };
+}
+
+#endif /* _Item_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/items/MultiStateEngine.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/MultiStateEngine.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/MultiStateEngine.cc	(revision 11817)
@@ -0,0 +1,263 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MultiStateEngine.h"
+
+extern "C" {
+#include <lua.h>
+}
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/LuaState.h"
+#include "core/XMLPort.h"
+#include "worldentities/EffectContainer.h"
+#include "worldentities/pawns/SpaceShip.h"
+#include "sound/WorldSound.h"
+
+namespace orxonox
+{
+    static const float FORWARD_EFFECT_VELOCITY_THRESHOLD = 0;
+    static const float MAX_VELOCITY_NORMAL = 111;
+    static const float MAX_VELOCITY_BOOST = 221;
+
+    RegisterClass(MultiStateEngine);
+
+    MultiStateEngine::MultiStateEngine(Context* context) : Engine(context)
+    {
+        RegisterObject(MultiStateEngine);
+
+        if (GameMode::isMaster())
+        {
+            this->defEngineSndNormal_ = new WorldSound(this->getContext());
+            this->defEngineSndBoost_  = new WorldSound(this->getContext());
+            this->defEngineSndNormal_->setLooping(true);
+            this->defEngineSndBoost_->setLooping(true);
+            this->defEngineSndNormal_->setVolume(0.8f);
+            this->defEngineSndBoost_->setVolume(0.5f);
+            this->lua_ = new LuaState();
+        }
+        else
+        {
+            this->defEngineSndBoost_ = nullptr;
+            this->defEngineSndNormal_ = nullptr;
+            this->lua_ = nullptr;
+        }
+        this->state_ = 0;
+        this->oldState_ = 0;
+
+        this->setSyncMode(ObjectDirection::Bidirectional);
+        this->registerVariables();
+    }
+
+    MultiStateEngine::~MultiStateEngine()
+    {
+        if (this->isInitialized())
+        {
+            if (!this->getShip())
+            {
+                // We have no ship, so the effects are not attached and won't be destroyed automatically
+                for (EffectContainer* container : this->effectContainers_)
+                    for (WorldEntity* effect : container->getEffects())
+                        effect->destroy();
+                if (this->defEngineSndNormal_)
+                    this->defEngineSndNormal_->destroy();
+                if (this->defEngineSndBoost_)
+                    this->defEngineSndBoost_->destroy();
+            }
+            if (this->lua_)
+                delete this->lua_;
+        }
+    }
+
+    void MultiStateEngine::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MultiStateEngine, XMLPort, xmlelement, mode);
+        XMLPortObject(MultiStateEngine, EffectContainer, "",  addEffectContainer,  getEffectContainer,  xmlelement, mode);
+        XMLPortParam(MultiStateEngine, "defEngineSndNormal",  setDefEngSndNormal,  getDefEngSndNormal,  xmlelement, mode);
+        XMLPortParam(MultiStateEngine, "defEngineSndBoost",  setDefEngSndBoost,  getDefEngSndBoost,  xmlelement, mode);
+    }
+
+    void MultiStateEngine::registerVariables()
+    {
+        registerVariable(this->state_, VariableDirection::ToServer);
+    }
+
+    void MultiStateEngine::run(float dt)
+    {
+        if (this->getShip())
+        {
+            const Vector3& velocity = this->getShip()->getLocalVelocity();
+
+            if (this->getShip()->hasLocalController())
+            {
+                const Vector3& direction = this->getSteering();
+                bool forward = (direction.z < 0.0 && velocity.z < -FORWARD_EFFECT_VELOCITY_THRESHOLD);
+
+                this->state_ = 0;
+                if (this->getShip()->isBoosting() && forward)
+                    this->state_ = EngineState::Boost;
+                else if (forward && !this->state_) // this->state_ == Boost
+                    this->state_ = EngineState::Normal;
+                else if (direction.z > 0.0 && velocity.z < 0.0)
+                    this->state_ = EngineState::Brake;
+                else
+                    this->state_ = EngineState::Idle;
+
+                if (this->state_ == EngineState::Idle && this->getSpeedAdd() > 0)
+                    this->state_ = EngineState::Normal;
+            }
+
+            if (GameMode::isMaster())
+            {
+                int changes = this->state_ | this->oldState_;
+
+                float pitch = velocity.length();
+                if (this->state_ & EngineState::Normal)
+                    defEngineSndNormal_->setPitch(clamp(pitch/MAX_VELOCITY_NORMAL + 1, 0.5f, 2.0f));
+                if (this->state_ & EngineState::Boost)
+                    defEngineSndBoost_->setPitch(clamp(pitch/MAX_VELOCITY_BOOST + 1, 0.5f, 2.0f));
+
+                if (changes & EngineState::Idle)
+                {
+                    lua_pushboolean(this->lua_->getInternalLuaState(), this->state_ & EngineState::Idle);
+                    lua_setglobal(this->lua_->getInternalLuaState(), "idle");
+                }
+                if (changes & EngineState::Normal)
+                {
+                    lua_pushboolean(this->lua_->getInternalLuaState(), this->state_ & EngineState::Normal);
+                    lua_setglobal(this->lua_->getInternalLuaState(), "normal");
+                    if (this->state_ & EngineState::Normal)
+                        defEngineSndNormal_->play();
+                    else
+                        defEngineSndNormal_->stop();
+                }
+                if (changes & EngineState::Brake)
+                {
+                    lua_pushboolean(this->lua_->getInternalLuaState(), this->state_ & EngineState::Brake);
+                    lua_setglobal(this->lua_->getInternalLuaState(), "brake");
+                }
+                if (changes & EngineState::Boost)
+                {
+                    lua_pushboolean(this->lua_->getInternalLuaState(), this->state_ & EngineState::Boost);
+                    lua_setglobal(this->lua_->getInternalLuaState(), "boost");
+                    if (this->state_ & EngineState::Boost)
+                        defEngineSndBoost_->play();
+                    else
+                        defEngineSndBoost_->stop();
+                }
+
+                this->oldState_ = this->state_;
+
+                // Update all effect conditions
+                for (EffectContainer* container : this->effectContainers_)
+                    container->updateCondition();
+            }
+        }
+
+        Engine::run(dt);
+    }
+
+    void MultiStateEngine::addToSpaceShip(SpaceShip* ship)
+    {
+        Engine::addToSpaceShip(ship);
+
+        if (!ship)
+            return;
+
+        if( this->defEngineSndNormal_ )
+            this->getShip()->attach(defEngineSndNormal_);
+        if( this->defEngineSndBoost_ )
+            this->getShip()->attach(defEngineSndBoost_);
+
+        for (EffectContainer* container : this->effectContainers_)
+            for (WorldEntity* effect : container->getEffects())
+                this->getShip()->attach(effect);
+    }
+
+    void MultiStateEngine::addEffectContainer(EffectContainer* container)
+    {
+        if (container == nullptr)
+            return;
+        container->setLuaState(this->lua_, 'f' + multi_cast<std::string>(this->effectContainers_.size()));
+        this->effectContainers_.push_back(container);
+        if (this->getShip())
+        {
+            for (WorldEntity* effect : container->getEffects())
+                this->getShip()->attach(effect);
+        }
+    }
+
+    EffectContainer* MultiStateEngine::getEffectContainer(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (EffectContainer* effectContainer : this->effectContainers_)
+        {
+            if (i == index)
+                return effectContainer;
+            i++;
+        }
+        return nullptr;
+    }
+
+    void MultiStateEngine::setDefEngSndNormal(const std::string &engineSound)
+    {
+        if( defEngineSndNormal_ )
+            defEngineSndNormal_->setSource(engineSound);
+        else
+            assert(0); // This should never happen, because soundpointer is only available on master
+    }
+
+    const std::string& MultiStateEngine::getDefEngSndNormal()
+    {
+        if( defEngineSndNormal_ )
+            return defEngineSndNormal_->getSource();
+        else
+            assert(0);
+        return BLANKSTRING;
+    }
+
+    void MultiStateEngine::setDefEngSndBoost(const std::string &engineSound)
+    {
+        if( defEngineSndBoost_ )
+            defEngineSndBoost_->setSource(engineSound);
+        else
+            assert(0);
+    }
+
+    const std::string& MultiStateEngine::getDefEngSndBoost()
+    {
+        if( this->defEngineSndBoost_ )
+            return defEngineSndBoost_->getSource();
+        else
+            assert(0);
+        return BLANKSTRING;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/items/MultiStateEngine.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/MultiStateEngine.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/MultiStateEngine.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MultiStateEngine_H__
+#define _MultiStateEngine_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <vector>
+#include "Engine.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport MultiStateEngine : public Engine
+    {
+        public:
+            struct EngineState
+            {
+                static constexpr int Idle    = 1;
+                static constexpr int Normal  = 2;
+                static constexpr int Brake   = 4;
+                static constexpr int Boost   = 8;
+            };
+
+            MultiStateEngine(Context* context);
+            virtual ~MultiStateEngine();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void run(float dt) override;
+
+            virtual void addToSpaceShip(SpaceShip* ship) override;
+
+            void addEffectContainer(EffectContainer* effect);
+            EffectContainer* getEffectContainer(unsigned int index) const;
+
+            void setDefEngSndNormal(const std::string& engineSound);
+            const std::string& getDefEngSndNormal();
+            void setDefEngSndBoost(const std::string& engineSound);
+            const std::string& getDefEngSndBoost();
+
+        private:
+            void registerVariables();
+
+            int state_;
+            int oldState_;
+            LuaState* lua_;
+            std::vector<EffectContainer*> effectContainers_;
+            WorldSound* defEngineSndNormal_;
+            WorldSound* defEngineSndBoost_;
+    };
+}
+
+#endif /* _MultiStateEngine_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/items/PartDestructionEvent.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/PartDestructionEvent.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/PartDestructionEvent.cc	(revision 11817)
@@ -0,0 +1,352 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Noe Pedrazzini
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "PartDestructionEvent.h"
+
+#include <algorithm>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "network/NetworkFunction.h"
+#include "Item.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/pawns/ModularSpaceShip.h"
+#include "items/Engine.h"
+#include "gametypes/Gametype.h"
+#include "chat/ChatManager.h"
+
+
+namespace orxonox
+{
+    RegisterClass(PartDestructionEvent);
+
+    PartDestructionEvent::PartDestructionEvent(Context* context)
+        : Item(context)
+    {
+        RegisterObject(PartDestructionEvent);
+        this->setValid(true);
+    }
+
+    PartDestructionEvent::~PartDestructionEvent()
+    {
+
+    }
+
+    void PartDestructionEvent::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(PartDestructionEvent, XMLPort, xmlelement, mode);
+
+        XMLPortParam(PartDestructionEvent, "targetType", setTargetType, getTargetType, xmlelement, mode).defaultValues("NULL");
+        XMLPortParam(PartDestructionEvent, "targetName", setTargetName, getTargetName, xmlelement, mode).defaultValues("NULL");
+        XMLPortParam(PartDestructionEvent, "operation", setOperation, getOperation, xmlelement, mode).defaultValues("NULL");
+        XMLPortParam(PartDestructionEvent, "targetParam", setTargetParam, getTargetParam, xmlelement, mode).defaultValues("NULL");
+        XMLPortParam(PartDestructionEvent, "value", setEventValue, getEventValue, xmlelement, mode).defaultValues(0);
+        XMLPortParam(PartDestructionEvent, "message", setMessage, getMessage, xmlelement, mode).defaultValues("NULL");
+
+        /*
+        XMLPortParam(PartDestructionEvent, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
+        XMLPortParam(PartDestructionEvent, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
+        XMLPortParam(PartDestructionEvent, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
+        */
+    }
+
+    /**
+    @brief
+        Executes this event.
+    */
+    void PartDestructionEvent::execute()
+    {
+        // Do not execute if this event is invalid
+        if(!isValid())
+        {
+            orxout(internal_warning) << "Attempted to execute an invalid PartDestructionEvent!" << endl;
+            return;
+        }
+
+        // Output the destruction-message to the chat
+        if(this->message_ != "NULL")
+            ChatManager::message(this->message_);
+
+        // Modify parameters as configured for all cases
+        if (this->targetType_ == "ship")
+        {
+            switch (this->targetParam_) {
+            case TargetParam::shieldhealth:
+                this->parent_->getParent()->setShieldHealth(operate(this->parent_->getParent()->getShieldHealth()));
+                break;
+            case TargetParam::boostpower:
+                this->parent_->getParent()->setInitialBoostPower(operate(this->parent_->getParent()->getInitialBoostPower()));
+                break;
+            case TargetParam::boostpowerrate:
+                this->parent_->getParent()->setBoostPowerRate(operate(this->parent_->getParent()->getBoostPowerRate()));
+                break;
+            case TargetParam::rotationthrust:
+                this->parent_->getParent()->setRotationThrust(operate(this->parent_->getParent()->getRotationThrust()));
+                break;
+            default:
+                break;
+            }
+            this->setValid(false);
+            return;
+        }
+
+        if (this->targetType_ == "engine")
+        {
+            switch (this->targetParam_) {
+            case TargetParam::null:
+                this->parent_->getParent()->getEngineByName(targetName_)->destroy();
+                break;
+            case TargetParam::boostfactor:
+                this->parent_->getParent()->getEngineByName(targetName_)->setBoostFactor(operate(this->parent_->getParent()->getEngineByName(targetName_)->getBoostFactor()));
+                break;
+            case TargetParam::speedfront:
+                this->parent_->getParent()->getEngineByName(targetName_)->setMaxSpeedFront(operate(this->parent_->getParent()->getEngineByName(targetName_)->getMaxSpeedFront()));
+                break;
+            case TargetParam::accelerationfront:
+                this->parent_->getParent()->getEngineByName(targetName_)->setAccelerationFront(operate(this->parent_->getParent()->getEngineByName(targetName_)->getAccelerationFront()));
+                break;
+            default:
+                break;
+            }
+            this->setValid(false);
+            return;
+        }
+
+        if (this->targetType_ == "part")
+        {
+            switch (this->targetParam_) {
+            case TargetParam::null:
+                if (!this->parent_->getParent()->getShipPartByName(targetName_))
+                    return;
+                this->parent_->getParent()->getShipPartByName(targetName_)->setEventExecution(false);
+                this->parent_->getParent()->killShipPart(targetName_);
+                break;
+            default:
+                break;
+            }
+            this->setValid(false);
+            return;
+        }
+    }
+
+    void PartDestructionEvent::setParent(ShipPart* part)
+    {
+        this->parent_ = part;
+    }
+
+    /**
+    @brief
+        Set type of the target
+    @param type
+        The desired target-type as string. Valid target-types: ship engine weapon
+    */
+    void PartDestructionEvent::setTargetType(std::string type)
+    {
+        if ((type == "ship") || (type == "engine") || (type == "weapon") || (type == "part"))
+        {
+            this->targetType_ = type;
+            return;
+        }
+
+        // Error, if invalid target-type was entered.
+        orxout(internal_warning) << "\"" << type << "\" is not a valid target-type for a PartDestructionEvent. Valid types are: ship engine weapon part" << endl;
+        this->setValid(false);
+        return;
+    }
+
+    void PartDestructionEvent::setTargetName(std::string name)
+    {
+        // Error, if the target-type is "weapon" or "engine", but the name of said target was not defined.
+        if (((this->targetType_ == "weapon") || (this->targetType_ == "engine")) && (name == "NULL"))
+        {
+            orxout(internal_warning) << "The target-name of a PartDestructionEvent with target-type \"" << this->targetType_ << "\" needs to be defined!" << endl;
+            return;
+        }
+
+        this->targetName_ = name;
+    }
+
+    /**
+    @brief
+        Set the operation to be applied.
+    @param param
+        The desired parameter as string. Valid parameters: c.f. @ref TargetParam
+    */
+    void PartDestructionEvent::setTargetParam(std::string param)
+    {
+        // A target-type needs to be defined in order to choose a parameter.
+        if (this->targetType_ == "NULL")
+        {
+            orxout(internal_warning) << "No valid target-type defined. Cannot set target-param for this PartDestructionEvent." << endl;
+            this->setValid(false);
+            return;
+        }
+
+        // engine: NULL boostfactor speedfront accelerationfront
+        if (this->targetType_ == "engine")
+        {
+            if (param == "NULL")
+            {
+                this->targetParam_ = TargetParam::null;
+                return;
+            }
+            if (param == "boostfactor")
+            {
+                this->targetParam_ = TargetParam::boostfactor;
+                return;
+            }
+            if (param == "speedfront")
+            {
+                this->targetParam_ = TargetParam::speedfront;
+                return;
+            }
+            if (param == "accelerationfront")
+            {
+                this->targetParam_ = TargetParam::accelerationfront;
+                return;
+            }
+
+            orxout(internal_warning) << "\"" << param << "\" is not a valid target-param for a PartDestructionEvent with target-type \"engine\". Valid types are: boostfactor speedfront accelerationfront" << endl;
+            return;
+        }
+
+        // weapon:
+
+        // ship: shieldhealth (maxshieldhealth shieldabsorption shieldrechargerate) boostpower boostpowerrate rotationthrust
+        if (this->targetType_ == "ship")
+        {
+            if (param == "shieldhealth")
+            {
+                this->targetParam_ = TargetParam::shieldhealth;
+                return;
+            }
+            if (param == "boostpower")
+            {
+                this->targetParam_ = TargetParam::boostpower;
+                return;
+            }
+            if (param == "boostpowerrate")
+            {
+                this->targetParam_ = TargetParam::boostpowerrate;
+                return;
+            }
+            if (param == "rotationthrust")
+            {
+                this->targetParam_ = TargetParam::rotationthrust;
+                return;
+            }
+
+            orxout(internal_warning) << "\"" << param << "\" is not a valid target-param for a PartDestructionEvent with target-type \"ship\". Valid types are: shieldhealth maxshieldhealth shieldabsorption shieldrechargerate boostpower boostpowerrate rotationthrust" << endl;
+            return;
+        }
+
+        if (this->targetType_ == "part")
+        {
+            if (param == "NULL")
+            {
+                this->targetParam_ = TargetParam::null;
+                return;
+            }
+
+            orxout(internal_warning) << "\"" << param << "\" is not a valid target-param for a PartDestructionEvent with target-type \"part\". Valid types are: NULL (set operation to \"destroy\")" << endl;
+            return;
+        }
+
+        orxout(internal_warning) << "No valid target-param defined. The chosen param is either invalid or not available for this target-type." << endl;
+        this->setValid(false);
+    }
+
+    /**
+    @brief
+        Set the operation to be applied.
+    @param operation
+        The desired operator as string. Valid operators: * + - destroy
+    */
+    void PartDestructionEvent::setOperation(std::string operation)
+    {
+        // * + - destroy
+        if ((operation == "*") || (operation == "+") || (operation == "-") || (operation == "set") || (operation == "destroy"))
+        {
+            this->operation_ = operation;
+            return;
+        }
+        this->operation_ = "NULL";
+        orxout(internal_warning) << "\"" << operation << "\" is not a valid operation for a PartDestructionEvent. Valid operations are: * + - set destroy" << endl;
+    }
+
+    /**
+    @brief
+        Set the message to be shown upon execution of the vent.
+    @param msg
+        The desired message as string.
+    */
+    void PartDestructionEvent::setMessage(std::string msg)
+    {
+        this->message_ = msg;
+    }
+
+
+    /**
+    @brief
+        Apply the configured operation and value to an input.
+    @param input
+        The value which should be modified
+    @return
+        Returns the product / sum / difference of input and configured value,
+        the configured value if the operation is "set",
+        or 0 if the operation is "destroy"
+    */
+    float PartDestructionEvent::operate(float input)
+    {
+        if (this->operation_ == "*")
+            return input * this->value_;
+        if (this->operation_ == "+")
+            return input + this->value_;
+        if (this->operation_ == "-")
+            return input - this->value_;
+        if (this->operation_ == "set")
+            return this->value_;
+        if (this->operation_ == "destroy")
+        {
+            return 0;
+        }
+        return 0;
+    }
+
+    /**
+    @brief
+        Sets the value applied with the chosen operation.
+    @param value
+        The value as float.
+    */
+    void PartDestructionEvent::setEventValue(float value)
+    {
+        this->value_ = value;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/items/PartDestructionEvent.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/PartDestructionEvent.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/PartDestructionEvent.h	(revision 11817)
@@ -0,0 +1,160 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Noe Pedrazzini
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _PartDestructionEvent_H__
+#define _PartDestructionEvent_H__
+
+#include "OrxonoxPrereqs.h"
+#include "Item.h"
+
+#include <string>
+
+
+namespace orxonox // tolua_export
+{ // tolua_export
+    /**
+        @brief
+            In order to assign attached entities to a ShipPart, a ShipPart with the same name as the corresponding entity needs to be created in the <parts> tag.
+            Here is a (primitive) example of a ModularSpaceShip with ShipParts and PartDestructionEvents defined in XML:
+            @code
+            <ModularSpaceShip
+                ...
+                >
+                    <attached>
+                        <StaticEntity name="generator"  . . .  />
+                        <StaticEntity name="tail" . . . />
+                    </attached>
+                    <parts>
+                        <ShipPart name="generator" . . . >
+                            <destructionevents>
+                                <PartDestructionEvent targetType="ship" targetParam="boostpowerrate" operation="-" value="0.5" message="Your boost-regeneration is reduced!" />
+                            </destructionevents>
+                        </ShipPart>
+                        <ShipPart name="tail" . . . >
+                            <destructionevents>
+                                <PartDestructionEvent ... />
+                            </destructionevents>
+                        </ShipPart>
+                    </parts>
+                    <engines>
+                        <Engine />
+                        <Engine />
+                    </engines>
+                </ModularSpaceShip>
+            @endcode
+
+        @author
+            Fabian 'x3n' Landau, Noe Pedrazzini
+        */
+    class _OrxonoxExport PartDestructionEvent // tolua_export
+        : public Item
+    { // tolua_export
+
+        public:
+
+            /**
+                @brief
+                    List of all allowed parameters.
+            */
+            enum class TargetParam
+            {
+                shieldhealth,
+                maxshieldhealth,
+                shieldabsorption,
+                shieldrechargerate,
+                boostpower,         // Amount of available boost
+                boostpowerrate,     // Recharge-rate of boost
+                rotationthrust,
+                boostfactor,
+                speedfront,
+                accelerationfront,
+                null
+            };
+
+            PartDestructionEvent(Context* context);
+            virtual ~PartDestructionEvent();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void execute();
+
+            inline void setValid(bool valid)
+                { this->valid_ = valid; }
+            inline bool isValid()
+                { return this->valid_; }
+
+            void setParent(ShipPart* parent);
+            inline ShipPart* getParent()
+                { return this->parent_; }
+
+            void setTargetType(std::string type);
+            inline std::string getTargetType()
+                { return this->targetType_; }
+
+            void setTargetName(std::string name);
+            inline std::string getTargetName()
+                { return this->targetName_; }
+
+            void setTargetParam(std::string param);
+            inline std::string getTargetParam()
+                { return this->targetName_; }
+
+            void setOperation(std::string operation);
+            inline std::string getOperation()
+                { return this->operation_; }
+
+            void setMessage(std::string msg);
+            inline std::string getMessage()
+                { return this->message_; }
+
+            float operate(float input);
+
+            void setEventValue(float value);
+            inline float getEventValue()
+                { return this->value_; }
+
+        protected:
+
+        private:
+
+            ShipPart* parent_;          //!< Pointer to the ShipPart this event belongs to
+            bool valid_;                //!< Whether this event is valid or not.
+
+            std::string targetType_;    //!< The type of the target. (ship weapon engine)
+            std::string targetName_;    //!< The name of the target.
+            TargetParam targetParam_;   //!< The parameter to be modified
+            std::string operation_;     //!< The operation to be applied
+            float value_;               //!< The value used to do the operation
+            std::string message_;       //!< The message which is shown in chat when the event is executed.
+
+
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _PartDestructionEvent_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/items/ShipPart.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/ShipPart.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/ShipPart.cc	(revision 11817)
@@ -0,0 +1,266 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Noe Pedrazzini
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ShipPart.h"
+
+#include <algorithm>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "network/NetworkFunction.h"
+#include "Item.h"
+#include "worldentities/pawns/Pawn.h"
+#include "worldentities/pawns/ModularSpaceShip.h"
+#include "gametypes/Gametype.h"
+#include "worldentities/StaticEntity.h"
+#include "items/PartDestructionEvent.h"
+#include "chat/ChatManager.h"
+
+
+namespace orxonox
+{
+    RegisterClass(ShipPart);
+
+    ShipPart::ShipPart(Context* context)
+        : Item(context), parent_(nullptr)
+    {
+        RegisterObject(ShipPart);
+        this->eventExecution_ = true;
+        this->healthMem_ = 100;
+    }
+
+    ShipPart::~ShipPart()
+    {
+        if (this->parent_)
+        {
+            // Remove this ShipPart from the parent.
+            this->parent_->removeShipPart(this);
+        }
+    }
+
+    void ShipPart::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ShipPart, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ShipPart, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
+        XMLPortParam(ShipPart, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
+        XMLPortParam(ShipPart, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
+
+        XMLPortParam(ShipPart, "damageabsorption", setDamageAbsorption, getDamageAbsorption, xmlelement, mode).defaultValues(0.5);
+
+        XMLPortParamTemplate(ShipPart, "explosionposition", setExplosionPosition, getExplosionPosition, xmlelement, mode, Vector3);
+
+        XMLPortObject(ShipPart, PartDestructionEvent, "destructionevents", addDestructionEvent, getDestructionEvent, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Is called when the ShipPart dies.
+        Executes PartDestructionEvents.
+        Tells the ModularSpaceShip to remove this ShipPart.
+    */
+    void ShipPart::death()
+    {
+        this->explode();
+
+        if(eventExecution_)
+        {
+            // Execute all destruction events
+            for (unsigned int i = 0; i < this->eventList_.size(); i++)
+            {
+                this->getDestructionEvent(i)->execute();
+            }
+        }
+
+        this->destroyLater();
+    }
+
+    void ShipPart::explode()
+    {
+        // BigExplosion* chunk = new BigExplosion(this->getContext());
+        // chunk->setPosition(this->parent_->getPosition() + this->parent_->getOrientation() * (this->explosionPosition_));
+        // //chunk->setPosition(this->parent_->getPosition() + this->parent_->getOrientation() * Vector3(this->entityList_[0]->getLocalInertia()));
+        // chunk->setVelocity(this->parent_->getVelocity());
+
+        // this->explosionSound_->setPosition(this->parent_->getPosition());
+        // this->explosionSound_->play();
+    }
+
+    /**
+    @brief
+        Add a StaticEntity to the ShipPart.
+    @param entity
+        A pointer to the StaticEntity to be added.
+    */
+    void ShipPart::addEntity(StaticEntity* entity)
+    {
+        OrxAssert(entity != nullptr, "The Entity cannot be nullptr.");
+        this->entityList_.push_back(entity);
+    }
+
+    /**
+    @brief
+        Get the i-th StaticEntity of the ShipPart.
+    @return
+        Returns a pointer to the i-the StaticEntity. nullptr if there is no StaticEntity with that index.
+    */
+    StaticEntity* ShipPart::getEntity(unsigned int index)
+    {
+        if(this->entityList_.size() >= index)
+            return nullptr;
+        else
+            return this->entityList_[index];
+    }
+
+    /**
+    @brief
+        Check whether the ShipPart has a particular Entity.
+    @param search
+        A pointer to the Entity to be checked.
+    */
+    bool ShipPart::hasEntity(StaticEntity* search) const
+    {
+        for(StaticEntity* entity : this->entityList_)
+        {
+            if(entity == search)
+                return true;
+        }
+        return false;
+    }
+
+    /**
+    @brief
+        Add a PartDestructionEvent to the ShipPart.
+    @param event
+        A pointer to the PartDestructionEvent to be added.
+    */
+    void ShipPart::addDestructionEvent(PartDestructionEvent* event)
+    {
+        OrxAssert(event != nullptr, "The PartDestructionEvent cannot be nullptr.");
+        event->setParent(this);
+        this->eventList_.push_back(event);
+    }
+
+    /**
+    @brief
+        Get the i-th PartDestructionEvent of the ShipPart.
+    @return
+        Returns a pointer to the i-the PartDestructionEvent. nullptr if there is no PartDestructionEvent with that index.
+    */
+    PartDestructionEvent* ShipPart::getDestructionEvent(unsigned int index)
+    {
+        if(this->eventList_.size() <= index)
+            return nullptr;
+        else
+            return this->eventList_[index];
+    }
+
+    void ShipPart::setParent(ModularSpaceShip* ship)
+    {
+        this->parent_ = ship;
+    }
+
+    /**
+    @brief
+        Handles a received hit.
+    */
+    void ShipPart::handleHit(float damage, float healthdamage, float shielddamage, Pawn* originator)
+    {
+        if (parent_->getGametype() && parent_->getGametype()->allowPawnDamage(parent_, originator))
+        {
+            if (shielddamage >= parent_->getShieldHealth())
+            {
+                parent_->setShieldHealth(0);
+                this->setHealth(this->health_ - (healthdamage + damage) * this->damageAbsorption_);
+                parent_->setHealth(parent_->getHealth() - (healthdamage + damage) * (1 - this->damageAbsorption_));
+            }
+            else
+            {
+                parent_->setShieldHealth(parent_->getShieldHealth() - shielddamage);
+
+                // remove remaining shieldAbsorpton-Part of damage from shield
+                shielddamage = damage * parent_->getShieldAbsorption();
+                shielddamage = std::min(parent_->getShieldHealth(),shielddamage);
+                parent_->setShieldHealth(parent_->getShieldHealth() - shielddamage);
+
+                // set remaining damage to health
+                this->setHealth(this->health_ - ((damage - shielddamage) - healthdamage) * this->damageAbsorption_);
+                parent_->setHealth(parent_->getHealth() - ((damage - shielddamage) - healthdamage) * (1- this->damageAbsorption_));
+            }
+        }
+        if (this->health_ < 0)
+            this->death();
+
+        // (Ugly) Chatoutput of health, until a GUI for modularspaceships-shipparts is implemented.
+        if ((this->health_ < 0.2 * this->maxHealth_) && (this->healthMem_ == 40))
+        {
+            this->healthMem_ = 20;
+            ChatManager::message("ShipPart " + this->getName() + " remaining health is 20%!");
+            return;
+        }
+        if ((this->health_ < 0.4 * this->maxHealth_) && (this->healthMem_ == 60))
+        {
+            this->healthMem_ = 40;
+            ChatManager::message("ShipPart " + this->getName() + " remaining health is 40%!");
+            return;
+        }
+        if ((this->health_ < 0.6 * this->maxHealth_) && (this->healthMem_ == 80))
+        {
+            this->healthMem_ = 60;
+            ChatManager::message("ShipPart " + this->getName() + " remaining health is 60%!");
+            return;
+        }
+        if ((this->health_ < 0.8 * this->maxHealth_) && (this->healthMem_ == 100))
+        {
+            this->healthMem_ = 80;
+            ChatManager::message("ShipPart " + this->getName() + " remaining health is 80%!");
+            return;
+        }
+    }
+
+
+    /**
+    @brief
+        Adds the ShipPart to the input SpaceShip.
+    @param ship
+        A pointer to the SpaceShip to which the ShipPart is added.
+    */
+    /*void ShipPart::addToSpaceShip(ModularSpaceShip* ship)
+    {
+        this->parent_ = ship;
+
+        if (ship)
+        {
+            this->parentID_ = ship->getObjectID();
+            if (!ship->hasShipPart(this))
+                ship->addShipPart(this);
+        }
+    }*/
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/items/ShipPart.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/items/ShipPart.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/items/ShipPart.h	(revision 11817)
@@ -0,0 +1,131 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Noe Pedrazzini
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ShipPart_H__
+#define _ShipPart_H__
+
+#include "OrxonoxPrereqs.h"
+#include "Item.h"
+#include "items/PartDestructionEvent.h"
+
+#include <string>
+
+
+namespace orxonox // tolua_export
+{ // tolua_export
+    class _OrxonoxExport ShipPart // tolua_export
+        : public Item
+    { // tolua_export
+
+        public:
+            ShipPart(Context* context);
+            virtual ~ShipPart();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void handleHit(float damage, float healthdamage, float shielddamage, Pawn* originator);
+
+            virtual void death();
+            virtual void explode();
+
+            //virtual void attachTo(Pawn* newParent);
+            //virtual void detach();
+
+            void addEntity(StaticEntity* entity);
+            StaticEntity* getEntity(unsigned int index);
+            bool hasEntity(StaticEntity* entity) const;
+
+            void addDestructionEvent(PartDestructionEvent* event);
+            PartDestructionEvent* getDestructionEvent(unsigned int index);
+
+            inline void setDamageAbsorption(float value)
+                { this->damageAbsorption_ = value; }
+            inline float getDamageAbsorption() const
+                { return this->damageAbsorption_; }
+
+            void setParent(ModularSpaceShip* ship);
+            inline ModularSpaceShip* getParent() const
+                { return this->parent_; }
+
+            inline void setEventExecution(bool var)
+                { this->eventExecution_ = var; }
+            inline bool isEventExecution() const
+                { return this->eventExecution_; }
+
+            inline void setHealth(float health)
+                { this->health_ = health; }
+            inline void addHealth(float health)
+                { this->setHealth(this->health_ + health); }
+            inline void removeHealth(float health)
+                { this->setHealth(this->health_ - health); }
+            inline float getHealth() const
+                { return this->health_; }
+
+            inline void setMaxHealth(float maxhealth)
+                { this->maxHealth_ = maxhealth; this->setHealth(this->health_); }
+            inline float getMaxHealth() const
+                { return this->maxHealth_; }
+
+            inline void setInitialHealth(float initialhealth)
+                { this->initialHealth_ = initialhealth; this->setHealth(initialhealth); }
+            inline float getInitialHealth() const
+                { return this->initialHealth_; }
+
+            inline void setExplosionPosition(Vector3 pos)
+                { this->explosionPosition_ = pos; }
+            inline Vector3 getExplosionPosition()
+                { return this->explosionPosition_; }
+
+
+            // FIXME: (noep) Why doesn't this work? Works fine in Engine.h
+            //void addToSpaceShip(ModularSpaceShip* ship);
+
+        protected:
+            ModularSpaceShip* parent_;
+            unsigned int parentID_;     // Object ID of the SpaceShip the Part is mounted on.
+
+            float damageAbsorption_;
+            float health_;
+            float maxHealth_;
+            float initialHealth_;
+
+        private:
+            std::vector<StaticEntity*> entityList_;         // List of all entities which belong to this part
+            std::vector<PartDestructionEvent*> eventList_;  // The list of all PartDestructionEvent assigned to this ShipPart.
+
+            bool eventExecution_;
+
+            float healthMem_;
+
+            Vector3 explosionPosition_;
+
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _ShipPart_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,9 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  GUISheet.cc
+  OrxonoxOverlay.cc
+  OverlayGroup.cc
+
+#COMPILATION_BEGIN OverlayCompilation.cc
+  InGameConsole.cc
+#COMPILATION_END
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/GUISheet.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/GUISheet.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/GUISheet.cc	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "GUISheet.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GUIManager.h"
+#include "core/XMLPort.h"
+#include "core/GameMode.h"
+
+namespace orxonox
+{
+    RegisterClass(GUISheet);
+
+    GUISheet::GUISheet(Context* context)
+        : BaseObject(context)
+        , bShowOnLoad_(false)
+        , bHidePrevious_(false)
+        , bHidePreviousSet_(false)
+    {
+        RegisterObject(GUISheet);
+
+        if (!GameMode::showsGraphics())
+            ThrowException(NoGraphics, "GUISheet construction failed: no graphics");
+    }
+
+    GUISheet::~GUISheet()
+    {
+    }
+
+    void GUISheet::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(GUISheet, XMLPort, xmlelement, mode);
+
+        XMLPortParam(GUISheet, "showOnLoad",   setShowOnLoad,     getShowOnLoad,     xmlelement, mode);
+        XMLPortParam(GUISheet, "hidePrevious", setPreviousHiding, getPreviousHiding, xmlelement, mode);
+        XMLPortParam(GUISheet, "sheetName",    setSheetName,      getSheetName,      xmlelement, mode);
+        XMLPortParam(GUISheet, "backgroundImage",  setBackgroundImage,  getBackgroundImage,  xmlelement, mode);
+
+        if (this->bShowOnLoad_)
+            this->show();
+    }
+
+    void GUISheet::show()
+    {
+        GUIManager::getInstance().setBackgroundImage(this->backgroundImage_);
+        if (this->bHidePreviousSet_)
+            GUIManager::getInstance().showGUI(this->sheetName_, this->bHidePrevious_);
+        else
+            GUIManager::getInstance().showGUI(this->sheetName_);
+    }
+
+    void GUISheet::hide()
+    {
+        GUIManager::getInstance().hideGUI(this->sheetName_);
+        if (!this->backgroundImage_.empty())
+            GUIManager::getInstance().setBackgroundImage("");
+    }
+
+    void GUISheet::setSheetName(const std::string& name)
+    {
+        this->sheetName_ = name;
+        GUIManager::getInstance().loadGUI(this->sheetName_);
+    }
+
+    void GUISheet::setPreviousHiding(bool bHide)
+    {
+        this->bHidePrevious_ = bHide;
+        this->bHidePreviousSet_ = true;
+        // Note: This call has no effect when already showing!
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/GUISheet.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/GUISheet.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/GUISheet.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _GUISheet_H__
+#define _GUISheet_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    //! Simple XML loadable interface to the otherwise Lua coded GUI framework.
+    class _OrxonoxExport GUISheet : public BaseObject
+    {
+    public:
+        GUISheet(Context* context);
+        ~GUISheet();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        void show();
+        void hide();
+
+        void setSheetName(const std::string& name);
+        inline const std::string& getSheetName() const
+            { return this->sheetName_; }
+
+        inline void setShowOnLoad(bool bShow)
+            { this->bShowOnLoad_ = bShow; }
+        inline bool getShowOnLoad() const
+            { return this->bShowOnLoad_; }
+
+        void setPreviousHiding(bool bHide);
+        inline bool getPreviousHiding() const
+            { return this->bHidePrevious_; }
+
+        void setBackgroundImage(const std::string& image)
+            { this->backgroundImage_ = image; }
+        inline const std::string& getBackgroundImage() const
+            { return this->backgroundImage_; }
+
+    private:
+        std::string sheetName_;
+        bool bShowOnLoad_;
+        bool bHidePrevious_;
+        bool bHidePreviousSet_;
+        std::string backgroundImage_;
+  };
+}
+
+#endif /* _GUISheet_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/InGameConsole.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/InGameConsole.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/InGameConsole.cc	(revision 11817)
@@ -0,0 +1,615 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+
+#include "InGameConsole.h"
+
+#include <algorithm>
+#include <string>
+#include <OgreOverlay.h>
+#include <OgreOverlayElement.h>
+#include <OgreOverlayManager.h>
+#include <OgreOverlayContainer.h>
+#include <OgreBorderPanelOverlayElement.h>
+#include <OgreTextAreaOverlayElement.h>
+#include <OgreFontManager.h>
+#include <OgreFont.h>
+
+#include "util/Clock.h"
+#include "util/Convert.h"
+#include "util/Math.h"
+#include "util/DisplayStringConversions.h"
+#include "util/output/MemoryWriter.h"
+#include "util/output/OutputManager.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/GUIManager.h"
+#include "core/input/InputManager.h"
+#include "core/input/InputState.h"
+#include "core/input/InputBuffer.h"
+#include "core/LuaState.h"
+
+namespace orxonox
+{
+    const int LINES = 30;
+    const float CHAR_WIDTH = 8.0f; // fix this please - determine the char-width dynamically
+
+    SetConsoleCommand("InGameConsole", "openConsole", &InGameConsole::openConsole);
+    SetConsoleCommand("InGameConsole", "closeConsole", &InGameConsole::closeConsole);
+
+    ManageScopedSingleton(InGameConsole, ScopeID::GRAPHICS, false);
+
+    RegisterAbstractClass(InGameConsole).inheritsFrom<WindowEventListener>().inheritsFrom<UpdateListener>();
+
+    /**
+        @brief Constructor: Creates and initializes the InGameConsole.
+    */
+    InGameConsole::InGameConsole()
+        : shell_(new Shell("InGameConsole", true))
+        , bShowCursor_(false)
+        , consoleOverlay_(nullptr)
+        , consoleOverlayContainer_(nullptr)
+        , consoleOverlayNoise_(nullptr)
+        , consoleOverlayCursor_(nullptr)
+        , consoleOverlayBorder_(nullptr)
+        , consoleOverlayTextAreas_(nullptr)
+        , inputState_(nullptr)
+    {
+        RegisterObject(InGameConsole);
+
+        this->bActive_ = false;
+        this->cursor_ = 0.0f;
+        this->cursorSymbol_ = '|';
+        this->inputWindowStart_ = 0;
+        this->numLinesShifted_ = LINES - 1;
+        // for the beginning, don't scroll
+        this->scroll_ = 0;
+
+        this->setConfigValues();
+        this->initialise();
+
+        // Output buffering is not anymore needed. Not the best solution to do
+        // this here, but there isn't much of another way.
+        OutputManager::getInstance().getMemoryWriter()->disable();
+    }
+
+    /**
+        @brief Destructor: Destroys the TextAreas.
+    */
+    InGameConsole::~InGameConsole()
+    {
+        this->deactivate();
+
+        // destroy the input state previously created (InputBuffer gets destroyed by the Shell)
+        InputManager::getInstance().destroyState("console");
+
+        // destroy the underlaying shell
+        delete this->shell_;
+
+        Ogre::OverlayManager* ovMan = Ogre::OverlayManager::getSingletonPtr();
+        if (ovMan)
+        {
+            if (this->consoleOverlayNoise_)
+                Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->consoleOverlayNoise_);
+            if (this->consoleOverlayCursor_)
+                Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->consoleOverlayCursor_);
+            Ogre::FontManager::getSingleton().remove("MonofurConsole");
+            if (this->consoleOverlayBorder_)
+                Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->consoleOverlayBorder_);
+            if (this->consoleOverlayTextAreas_)
+            {
+                for (int i = 0; i < LINES; i++)
+                {
+                    if (this->consoleOverlayTextAreas_[i])
+                        Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->consoleOverlayTextAreas_[i]);
+                    this->consoleOverlayTextAreas_[i] = nullptr;
+                }
+
+            }
+            if (this->consoleOverlayContainer_)
+                Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->consoleOverlayContainer_);
+        }
+        if (this->consoleOverlayTextAreas_)
+        {
+            delete[] this->consoleOverlayTextAreas_;
+            this->consoleOverlayTextAreas_ = nullptr;
+        }
+
+        if (this->consoleOverlay_)
+            Ogre::OverlayManager::getSingleton().destroy(consoleOverlay_);
+    }
+
+    /**
+        @brief Sets the config values, describing the size of the console.
+    */
+    void InGameConsole::setConfigValues()
+    {
+        SetConfigValue(relativeWidth, 0.8);
+        SetConfigValue(relativeHeight, 0.4);
+        SetConfigValue(blinkTime, 0.5);
+        SetConfigValue(scrollSpeed_, 3.0f);
+        SetConfigValue(noiseSize_, 1.0f);
+        SetConfigValue(cursorSymbol_, '|');
+        SetConfigValue(bHidesAllInput_, false).callback(this, &InGameConsole::bHidesAllInputChanged);
+    }
+
+    /**
+        @brief Called whenever bHidesAllInput_ changes.
+    */
+    void InGameConsole::bHidesAllInputChanged()
+    {
+        if (inputState_)
+        {
+            if (bHidesAllInput_)
+            {
+                inputState_->setMouseHandler(&InputHandler::EMPTY);
+                inputState_->setJoyStickHandler(&InputHandler::EMPTY);
+            }
+            else
+            {
+                inputState_->setMouseHandler(nullptr);
+                inputState_->setJoyStickHandler(nullptr);
+            }
+        }
+    }
+
+    /**
+        @brief Initializes the InGameConsole.
+    */
+    void InGameConsole::initialise()
+    {
+        // create the corresponding input state
+        inputState_ = InputManager::getInstance().createInputState("console", false, false, InputStatePriority::Console);
+        inputState_->setKeyHandler(this->shell_->getInputBuffer());
+        bHidesAllInputChanged();
+
+        // create overlay and elements
+        Ogre::OverlayManager* ovMan = Ogre::OverlayManager::getSingletonPtr();
+
+        // create actual overlay
+        this->consoleOverlay_ = ovMan->create("InGameConsoleConsole");
+
+        // create a container
+        this->consoleOverlayContainer_ = static_cast<Ogre::OverlayContainer*>(ovMan->createOverlayElement("Panel", "InGameConsoleContainer"));
+        this->consoleOverlayContainer_->setMetricsMode(Ogre::GMM_RELATIVE);
+        this->consoleOverlayContainer_->setPosition((1 - this->relativeWidth) / 2, 0);
+        this->consoleOverlayContainer_->setDimensions(this->relativeWidth, this->relativeHeight);
+        this->consoleOverlay_->add2D(this->consoleOverlayContainer_);
+
+        // create BorderPanel
+        this->consoleOverlayBorder_ = static_cast<Ogre::BorderPanelOverlayElement*>(ovMan->createOverlayElement("BorderPanel", "InGameConsoleBorderPanel"));
+        this->consoleOverlayBorder_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayBorder_->setMaterialName("ConsoleCenter");
+        this->consoleOverlayBorder_->setBorderSize(16, 16, 0, 16);
+        this->consoleOverlayBorder_->setBorderMaterialName("ConsoleBorder");
+        this->consoleOverlayBorder_->setLeftBorderUV(0.0f, 0.49f, 0.5f, 0.51f);
+        this->consoleOverlayBorder_->setRightBorderUV(0.5f, 0.49f, 1.0f, 0.5f);
+        this->consoleOverlayBorder_->setBottomBorderUV(0.49f, 0.5f, 0.51f, 1.0f);
+        this->consoleOverlayBorder_->setBottomLeftBorderUV(0.0f, 0.5f, 0.5f, 1.0f);
+        this->consoleOverlayBorder_->setBottomRightBorderUV(0.5f, 0.5f, 1.0f, 1.0f);
+        this->consoleOverlayContainer_->addChild(this->consoleOverlayBorder_);
+
+        // create a new font to match the requested size exactly
+        Ogre::FontPtr font = static_cast<Ogre::FontPtr>
+            (Ogre::FontManager::getSingleton().create("MonofurConsole", "General"));
+        font->setType(Ogre::FT_TRUETYPE);
+        font->setSource("Monofur.ttf");
+        font->setTrueTypeSize(18);
+        // reto: I don't know why, but setting the resolution twice as high makes the font look a lot clearer
+        font->setTrueTypeResolution(192);
+        font->addCodePointRange(Ogre::Font::CodePointRange(33, 126));
+        font->addCodePointRange(Ogre::Font::CodePointRange(161, 255));
+
+        // create noise
+        this->consoleOverlayNoise_ = static_cast<Ogre::PanelOverlayElement*>(ovMan->createOverlayElement("Panel", "InGameConsoleNoise"));
+        this->consoleOverlayNoise_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayNoise_->setPosition(5,0);
+        this->consoleOverlayNoise_->setMaterialName("ConsoleNoiseSmall");
+        // comment following line to disable noise
+        this->consoleOverlayBorder_->addChild(this->consoleOverlayNoise_);
+
+        // create the text lines
+        this->consoleOverlayTextAreas_ = new Ogre::TextAreaOverlayElement*[LINES];
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i] = static_cast<Ogre::TextAreaOverlayElement*>(ovMan->createOverlayElement("TextArea", "InGameConsoleTextArea" + multi_cast<std::string>(i)));
+            this->consoleOverlayTextAreas_[i]->setMetricsMode(Ogre::GMM_PIXELS);
+            this->consoleOverlayTextAreas_[i]->setFontName("MonofurConsole");
+            this->consoleOverlayTextAreas_[i]->setCharHeight(18);
+            this->consoleOverlayTextAreas_[i]->setParameter("colour_top", "0.21 0.69 0.21");
+            this->consoleOverlayTextAreas_[i]->setLeft(8);
+            this->consoleOverlayTextAreas_[i]->setCaption("");
+            this->consoleOverlayNoise_->addChild(this->consoleOverlayTextAreas_[i]);
+        }
+
+        // create cursor (also a text area overlay element)
+        this->consoleOverlayCursor_ = static_cast<Ogre::TextAreaOverlayElement*>(ovMan->createOverlayElement("TextArea", "InGameConsoleCursor"));
+        this->consoleOverlayCursor_->setMetricsMode(Ogre::GMM_PIXELS);
+        this->consoleOverlayCursor_->setFontName("MonofurConsole");
+        this->consoleOverlayCursor_->setCharHeight(18);
+        this->consoleOverlayCursor_->setParameter("colour_top", "0.21 0.69 0.21");
+        this->consoleOverlayCursor_->setLeft(7);
+        this->consoleOverlayCursor_->setCaption(std::string(this->cursorSymbol_, 1));
+        this->consoleOverlayNoise_->addChild(this->consoleOverlayCursor_);
+
+        this->windowResized(this->getWindowWidth(), this->getWindowWidth());
+
+        // move overlay "above" the top edge of the screen
+        // we take -1.3 because the border makes the panel bigger
+        this->consoleOverlayContainer_->setTop(-1.3f * this->relativeHeight);
+
+        orxout(internal_info) << "InGameConsole initialized" << endl;
+    }
+
+    // ###############################
+    // ###  ShellListener methods  ###
+    // ###############################
+
+    /**
+        @brief Called if all output-lines have to be redrawn.
+    */
+    void InGameConsole::linesChanged()
+    {
+        Shell::LineList::const_iterator it = this->shell_->getNewestLineIterator();
+        int max = 0;
+        for (int i = 1; i < LINES; ++i)
+        {
+            if (it != this->shell_->getEndIterator())
+            {
+                ++it;
+                max = i;
+            }
+            else
+                break;
+        }
+
+        for (int i = LINES - 1; i > max; --i)
+            this->print("", Shell::LineType::DebugOutput, i, true);
+
+        for (int i = max; i >= 1; --i)
+        {
+            --it;
+            this->print(it->first, it->second, i, true);
+        }
+    }
+
+    /**
+        @brief Called if a new output-line was added.
+    */
+    void InGameConsole::lineAdded()
+    {
+        this->numLinesShifted_ = 0;
+        this->shiftLines();
+        if (LINES > 1)
+            this->print(this->shell_->getNewestLineIterator()->first, this->shell_->getNewestLineIterator()->second, 1);
+    }
+
+    /**
+        @brief Called if the text in the input-line has changed.
+    */
+    void InGameConsole::inputChanged()
+    {
+        if (LINES > 0)
+            this->print(this->shell_->getInput(), Shell::LineType::Input, 0);
+
+        if (this->shell_->getInput().empty())
+            this->inputWindowStart_ = 0;
+    }
+
+    /**
+        @brief Called if the position of the cursor in the input-line has changed.
+    */
+    void InGameConsole::cursorChanged()
+    {
+        unsigned int pos = this->shell_->getCursorPosition() - inputWindowStart_;
+        if (pos > maxCharsPerLine_)
+            pos = maxCharsPerLine_;
+
+        this->consoleOverlayCursor_->setCaption(std::string(pos,' ') + cursorSymbol_);
+        this->consoleOverlayCursor_->setTop(static_cast<int>(this->windowH_ * this->relativeHeight) - 24.0f);
+    }
+
+    /**
+        @brief Called if a command is about to be executed
+    */
+    void InGameConsole::executed()
+    {
+        this->shell_->addOutput(this->shell_->getInput(), Shell::LineType::Command);
+    }
+
+    /**
+        @brief Called if the console gets closed.
+    */
+    void InGameConsole::exit()
+    {
+        this->deactivate();
+    }
+
+    // ###############################
+    // ###  other external calls   ###
+    // ###############################
+
+    /**
+        @brief Used to control the actual scrolling and the cursor.
+    */
+    void InGameConsole::preUpdate(const Clock& time)
+    {
+        if (this->scroll_ != 0)
+        {
+            float oldTop = this->consoleOverlayContainer_->getTop();
+
+            if (this->scroll_ > 0)
+            {
+                // scrolling down
+                // enlarge oldTop a little bit so that this exponential function
+                // reaches 0 before infinite time has passed...
+                float deltaScroll = (oldTop - 0.01f) * time.getDeltaTime() * this->scrollSpeed_;
+                if (oldTop - deltaScroll >= 0)
+                {
+                    // window has completely scrolled down
+                    this->consoleOverlayContainer_->setTop(0);
+                    this->scroll_ = 0;
+                }
+                else
+                    this->consoleOverlayContainer_->setTop(oldTop - deltaScroll);
+            }
+
+            else
+            {
+                // scrolling up
+                // note: +0.01 for the same reason as when scrolling down
+                float deltaScroll = (1.3f * this->relativeHeight + 0.01f + oldTop) * time.getDeltaTime() * this->scrollSpeed_;
+                if (oldTop - deltaScroll <= -1.3 * this->relativeHeight)
+                {
+                    // window has completely scrolled up
+                    this->consoleOverlayContainer_->setTop(-1.3f * this->relativeHeight);
+                    this->scroll_ = 0;
+                    this->consoleOverlay_->hide();
+                }
+                else
+                    this->consoleOverlayContainer_->setTop(oldTop - deltaScroll);
+            }
+        }
+
+        if (this->bActive_)
+        {
+            this->cursor_ += time.getDeltaTime();
+            if (this->cursor_ >= this->blinkTime)
+            {
+                this->cursor_ = 0;
+                bShowCursor_ = !bShowCursor_;
+                if (bShowCursor_)
+                    this->consoleOverlayCursor_->show();
+                else
+                    this->consoleOverlayCursor_->hide();
+            }
+
+            // this creates a flickering effect (extracts exactly 80% of the texture at a random location)
+            float uRand = (rand() & 1023) / 1023.0f * 0.2f;
+            float vRand = (rand() & 1023) / 1023.0f * 0.2f;
+            this->consoleOverlayNoise_->setUV(uRand, vRand, 0.8f + uRand, 0.8f + vRand);
+        }
+    }
+
+    /**
+        @brief Resizes the console elements. Call if window size changes.
+    */
+    void InGameConsole::windowResized(unsigned int newWidth, unsigned int newHeight)
+    {
+        this->windowW_ = newWidth;
+        this->windowH_ = newHeight;
+        this->consoleOverlayBorder_->setWidth((float)(int)(this->windowW_* this->relativeWidth));
+        this->consoleOverlayBorder_->setHeight((float)(int)(this->windowH_ * this->relativeHeight));
+        this->consoleOverlayNoise_->setWidth((float)(int)(this->windowW_ * this->relativeWidth) - 10.0f);
+        this->consoleOverlayNoise_->setHeight((float)(int)(this->windowH_ * this->relativeHeight) - 5.0f);
+        this->consoleOverlayNoise_->setTiling(consoleOverlayNoise_->getWidth() / (50.0f * this->noiseSize_), consoleOverlayNoise_->getHeight() / (50.0f * this->noiseSize_));
+
+        // now adjust the text lines...
+        this->desiredTextWidth_ = static_cast<int>(this->windowW_ * this->relativeWidth) - 24;
+
+        if (LINES > 0)
+            this->maxCharsPerLine_ = std::max(10U, static_cast<unsigned int>(static_cast<float>(this->desiredTextWidth_) / CHAR_WIDTH));
+        else
+            this->maxCharsPerLine_ = 10;
+
+        for (int i = 0; i < LINES; i++)
+        {
+            this->consoleOverlayTextAreas_[i]->setWidth((float)this->desiredTextWidth_);
+            this->consoleOverlayTextAreas_[i]->setTop((float)(int)(this->windowH_ * this->relativeHeight) - 24 - 14*i);
+        }
+
+        this->linesChanged();
+        this->cursorChanged();
+    }
+
+    // ###############################
+    // ###    internal methods     ###
+    // ###############################
+
+    /**
+        @brief Prints string to bottom line.
+        @param text The string to be printed
+        @param type The type of the text, defines the color
+        @param index The index of the text overlay in which the string will be displayed
+        @param alwaysShift If true the ohter lines in the console are always shifted by one line
+    */
+    void InGameConsole::print(const std::string& text, Shell::LineType type, int index, bool alwaysShift)
+    {
+        std::string output = text;
+        if (LINES > index)
+        {
+            this->colourLine(type, index);
+
+            if (index > 0)
+            {
+                unsigned int linesUsed = 1;
+                while (output.size() > this->maxCharsPerLine_)
+                {
+                    ++linesUsed;
+                    this->consoleOverlayTextAreas_[index]->setCaption(multi_cast<Ogre::DisplayString>(output.substr(0, this->maxCharsPerLine_)));
+                    output.erase(0, this->maxCharsPerLine_);
+                    output.insert(0, 1, ' ');
+                    if (linesUsed > numLinesShifted_ || alwaysShift)
+                        this->shiftLines();
+                    this->colourLine(type, index);
+                }
+                this->consoleOverlayTextAreas_[index]->setCaption(multi_cast<Ogre::DisplayString>(output));
+                this->displayedText_ = output;
+                this->numLinesShifted_ = linesUsed;
+            }
+            else
+            {
+                if (output.size() > this->maxCharsPerLine_)
+                {
+                    if (this->shell_->getInputBuffer()->getCursorPosition() < this->inputWindowStart_)
+                        this->inputWindowStart_ = this->shell_->getInputBuffer()->getCursorPosition();
+                    else if (this->shell_->getInputBuffer()->getCursorPosition() >= (this->inputWindowStart_ + this->maxCharsPerLine_ - 1))
+                        this->inputWindowStart_ = this->shell_->getInputBuffer()->getCursorPosition() - this->maxCharsPerLine_ + 1;
+
+                    output = output.substr(this->inputWindowStart_, this->maxCharsPerLine_);
+                }
+                else
+                    this->inputWindowStart_ = 0;
+                this->displayedText_ = output;
+                this->consoleOverlayTextAreas_[index]->setCaption(multi_cast<Ogre::DisplayString>(output));
+            }
+        }
+    }
+
+    /**
+        @brief Shows the InGameConsole.
+    */
+    void InGameConsole::activate()
+    {
+        if (!this->bActive_)
+        {
+            this->bActive_ = true;
+            InputManager::getInstance().enterState("console");
+            this->shell_->registerListener(this);
+
+            this->windowResized(this->windowW_, this->windowH_);
+            this->linesChanged();
+            this->cursorChanged();
+            this->consoleOverlay_->show();
+
+            // scroll down
+            this->scroll_ = 1;
+            // the rest is done by tick
+        }
+    }
+
+    /**
+    @brief Hides the InGameConsole.
+    */
+    void InGameConsole::deactivate()
+    {
+        if (this->bActive_)
+        {
+            this->bActive_ = false;
+            GUIManager::getInstance().getLuaState()->doString("inGameConsoleClosed()"); // Notify the SheetManager in lua, that the console has been closed.
+            InputManager::getInstance().leaveState("console");
+            this->shell_->unregisterListener(this);
+
+            // scroll up
+            this->scroll_ = -1;
+            // the rest is done by tick
+        }
+    }
+
+    /**
+        @brief Shifts all output lines one line up
+    */
+    void InGameConsole::shiftLines()
+    {
+        for (unsigned int i = LINES - 1; i > 1; --i)
+        {
+            this->consoleOverlayTextAreas_[i]->setCaption(this->consoleOverlayTextAreas_[i - 1]->getCaption());
+            this->consoleOverlayTextAreas_[i]->setColourTop(this->consoleOverlayTextAreas_[i - 1]->getColourTop());
+            this->consoleOverlayTextAreas_[i]->setColourBottom(this->consoleOverlayTextAreas_[i - 1]->getColourBottom());
+        }
+    }
+
+    void InGameConsole::colourLine(Shell::LineType type, int index)
+    {
+        ColourValue colourTop, colourBottom;
+        switch (type)
+        {
+            case Shell::LineType::Message:
+            case Shell::LineType::DebugOutput:     colourTop = ColourValue(0.9f, 0.9f, 0.9f); break;
+
+            case Shell::LineType::UserError:       colourTop = ColourValue(0.9f, 0.0f, 0.0f); break;
+            case Shell::LineType::UserWarning:     colourTop = ColourValue(0.9f, 0.5f, 0.0f); break;
+            case Shell::LineType::UserStatus:      colourTop = ColourValue(0.0f, 0.9f, 0.0f); break;
+            case Shell::LineType::UserInfo:        colourTop = ColourValue(0.0f, 0.8f, 0.8f); break;
+
+            case Shell::LineType::InternalError:   colourTop = ColourValue(0.5f, 0.0f, 0.0f); break;
+            case Shell::LineType::InternalWarning: colourTop = ColourValue(0.5f, 0.2f, 0.0f); break;
+            case Shell::LineType::InternalStatus:  colourTop = ColourValue(0.0f, 0.5f, 0.0f); break;
+            case Shell::LineType::InternalInfo:    colourTop = ColourValue(0.0f, 0.4f, 0.4f); break;
+
+            case Shell::LineType::Verbose:         colourTop = ColourValue(0.3f, 0.3f, 0.9f); break;
+            case Shell::LineType::VerboseMore:     colourTop = ColourValue(0.2f, 0.2f, 0.7f); break;
+            case Shell::LineType::VerboseUltra:    colourTop = ColourValue(0.1f, 0.1f, 0.5f); break;
+
+            case Shell::LineType::Command:         colourTop = ColourValue(0.8f, 0.2f, 0.8f); break;
+            case Shell::LineType::Hint:            colourTop = ColourValue(0.4f, 0.0f, 0.4f); break;
+            case Shell::LineType::Input:           colourTop = ColourValue(0.9f, 0.9f, 0.9f); break;
+
+            default:                               colourTop = ColourValue(0.5f, 0.5f, 0.5f); break;
+        }
+
+        colourBottom = ColourValue(sqrt(colourTop.r), sqrt(colourTop.g), sqrt(colourTop.b));
+
+        this->consoleOverlayTextAreas_[index]->setColourTop   (colourTop);
+        this->consoleOverlayTextAreas_[index]->setColourBottom(colourBottom);
+    }
+
+    // ################################
+    // ###      static methods      ###
+    // ################################
+
+    /**
+        @brief Activates the console.
+    */
+    /*static*/ void InGameConsole::openConsole()
+    {
+        InGameConsole::getInstance().activate();
+    }
+
+    /**
+        @brief Deactivates the console.
+    */
+    /*static*/ void InGameConsole::closeConsole()
+    {
+        GUIManager::getInstance().getLuaState()->doString("inGameConsoleClosed()");  // Notify the SheetManager in lua, that the console has been closed, but not by ESC.
+        InGameConsole::getInstance().deactivate();
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/InGameConsole.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/InGameConsole.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/InGameConsole.h	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Felix Schulthess
+ *   Co-authors:
+ *      Fabian 'x3n' Landau
+ *
+ */
+
+#ifndef _InGameConsole_H__
+#define _InGameConsole_H__
+
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+
+#include "util/OgreForwardRefs.h"
+#include "util/Singleton.h"
+#include "core/WindowEventListener.h"
+#include "core/command/Shell.h"
+#include "core/UpdateListener.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport InGameConsole : public Singleton<InGameConsole>, public ShellListener, public WindowEventListener, public UpdateListener
+    {
+        friend class Singleton<InGameConsole>;
+    public: // functions
+        InGameConsole();
+        ~InGameConsole();
+
+        void initialise();
+        void setConfigValues();
+
+        virtual void preUpdate(const Clock& time) override;
+        virtual void postUpdate(const Clock& time) override { /*no action*/ }
+
+        static void openConsole();
+        static void closeConsole();
+
+    private: // functions
+        InGameConsole(const InGameConsole& other);
+
+        void activate();
+        void deactivate();
+
+        virtual void linesChanged() override;
+        virtual void lineAdded() override;
+        virtual void inputChanged() override;
+        virtual void cursorChanged() override;
+        virtual void executed() override;
+        virtual void exit() override;
+
+        void shiftLines();
+        void colourLine(Shell::LineType type, int index);
+        void setCursorPosition(unsigned int pos);
+        void print(const std::string& text, Shell::LineType type, int index, bool alwaysShift = false);
+
+        virtual void windowResized(unsigned int newWidth, unsigned int newHeight) override;
+
+        // config value related
+        void bHidesAllInputChanged();
+
+    private: // variables
+        Shell* shell_;
+        bool bActive_;
+        int windowW_;
+        int windowH_;
+        int desiredTextWidth_;
+        unsigned int maxCharsPerLine_;
+        unsigned int numLinesShifted_;
+        int scroll_;
+        float cursor_;
+        unsigned int inputWindowStart_;
+        bool bShowCursor_;
+        std::string displayedText_;
+        Ogre::Overlay* consoleOverlay_;
+        Ogre::OverlayContainer* consoleOverlayContainer_;
+        Ogre::PanelOverlayElement* consoleOverlayNoise_;
+        Ogre::TextAreaOverlayElement* consoleOverlayCursor_;
+        Ogre::BorderPanelOverlayElement* consoleOverlayBorder_;
+        Ogre::TextAreaOverlayElement** consoleOverlayTextAreas_;
+
+        // input related
+        InputState* inputState_;
+
+        // config values
+        float relativeWidth;
+        float relativeHeight;
+        float blinkTime;
+        float scrollSpeed_;
+        float noiseSize_;
+        char cursorSymbol_;
+        bool bHidesAllInput_;
+
+        static InGameConsole* singletonPtr_s;
+    };
+}
+
+#endif /* _InGameConsole_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/OrxonoxOverlay.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/OrxonoxOverlay.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/OrxonoxOverlay.cc	(revision 11817)
@@ -0,0 +1,459 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief Definition of the OrxonoxOverlay class.
+*/
+
+#include "OrxonoxOverlay.h"
+
+#include <cmath>
+#include <OgreOverlay.h>
+#include <OgreOverlayManager.h>
+#include <OgrePanelOverlayElement.h>
+#include <OgreRenderWindow.h>
+#include <OgreMaterialManager.h>
+#include <OgreTechnique.h>
+#include <OgrePass.h>
+
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "core/GameMode.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "OverlayGroup.h"
+
+namespace orxonox
+{
+    unsigned int OrxonoxOverlay::hudOverlayCounter_s = 0;
+    std::map<std::string, OrxonoxOverlay*> OrxonoxOverlay::overlays_s;
+
+    SetConsoleCommand("OrxonoxOverlay", "scaleOverlay",     &OrxonoxOverlay::scaleOverlay);
+    SetConsoleCommand("OrxonoxOverlay", "scrollOverlay",    &OrxonoxOverlay::scrollOverlay);
+    SetConsoleCommand("OrxonoxOverlay", "toggleVisibility", &OrxonoxOverlay::toggleVisibility);
+    SetConsoleCommand("OrxonoxOverlay", "show",     &OrxonoxOverlay::showOverlay);
+    SetConsoleCommand("OrxonoxOverlay", "rotateOverlay",    &OrxonoxOverlay::rotateOverlay);
+
+    RegisterClass(OrxonoxOverlay);
+
+    OrxonoxOverlay::OrxonoxOverlay(Context* context)
+        : BaseObject(context)
+    {
+        RegisterObject(OrxonoxOverlay);
+
+        this->owner_ = nullptr;
+        this->group_ = nullptr;
+
+        if (!GameMode::showsGraphics())
+            ThrowException(NoGraphics, "Can't create OrxonoxOverlay, graphics engine not initialized");
+
+        // create the Ogre::Overlay
+        overlay_ = Ogre::OverlayManager::getSingleton().create("OrxonoxOverlay_overlay_"
+            + multi_cast<std::string>(hudOverlayCounter_s++));
+
+        // create background panel (can be used to show any picture)
+        this->background_ = static_cast<Ogre::PanelOverlayElement*>(
+            Ogre::OverlayManager::getSingleton().createOverlayElement("Panel",
+            "OrxonoxOverlay_background_" + multi_cast<std::string>(hudOverlayCounter_s++)));
+        this->overlay_->add2D(this->background_);
+
+        // Get aspect ratio from the render window. Later on, we get informed automatically
+        this->windowAspectRatio_ = static_cast<float>(this->getWindowWidth()) / this->getWindowHeight();
+
+        this->size_ = Vector2(1.0f, 1.0f);
+        this->pickPoint_= Vector2(0.0f, 0.0f);
+        this->position_ = Vector2(0.0f, 0.0f);
+        this->angle_ = Degree(0.0);
+        this->bCorrectAspect_ = false;
+        this->rotState_ = RotationState::Horizontal;
+        this->angleChanged(); // updates all other values as well
+
+        setBackgroundMaterial("");
+    }
+
+    /**
+    @brief
+        Make sure everything gets removed/destroyed.
+    @remark
+        We assume that the Ogre::OverlayManager exists (there is an assert in Ogre for that!)
+    */
+    OrxonoxOverlay::~OrxonoxOverlay()
+    {
+        if (this->isInitialized())
+        {
+            // erase ourself from the map with all overlays
+            std::map<std::string, OrxonoxOverlay*>::iterator it = overlays_s.find(this->getName());
+            if (it != overlays_s.end())
+                overlays_s.erase(it);
+
+            Ogre::OverlayManager::getSingleton().destroyOverlayElement(this->background_);
+            Ogre::OverlayManager::getSingleton().destroy(this->overlay_);
+        }
+    }
+
+    /**
+    @brief
+        Loads the OrxonoxOverlay.
+
+        This has to be called before usage, otherwise strange behaviour is
+        guaranteed! (there should be no segfaults however).
+    @copydoc BaseObject::XMLPort()
+    */
+    void OrxonoxOverlay::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(OrxonoxOverlay, XMLPort, xmlelement, mode);
+
+        XMLPortParam(OrxonoxOverlay, "size",      setSize,      getSize,      xmlelement, mode);
+        XMLPortParam(OrxonoxOverlay, "pickpoint", setPickPoint, getPickPoint, xmlelement, mode);
+        XMLPortParam(OrxonoxOverlay, "position",  setPosition,  getPosition,  xmlelement, mode);
+        XMLPortParam(OrxonoxOverlay, "rotation",  setRotation,  getRotation,  xmlelement, mode);
+        XMLPortParam(OrxonoxOverlay, "correctaspect", setAspectCorrection,   getAspectCorrection,   xmlelement, mode);
+        XMLPortParam(OrxonoxOverlay, "background",    setBackgroundMaterial, getBackgroundMaterial, xmlelement, mode);
+        XMLPortParam(OrxonoxOverlay, "backgroundtex", setBackgroundTexture,  getBackgroundTexture,  xmlelement, mode);
+    }
+
+    void OrxonoxOverlay::changedName()
+    {
+        SUPER(OrxonoxOverlay, changedName);
+
+        OrxonoxOverlay::overlays_s.erase(this->getOldName());
+
+        if (OrxonoxOverlay::overlays_s.find(this->getName()) != OrxonoxOverlay::overlays_s.end())
+            orxout(internal_warning) << "Overlay names should be unique or you cannnot access them via console. Name: \"" << this->getName() << '"' << endl;
+
+        OrxonoxOverlay::overlays_s[this->getName()] = this;
+    }
+
+    //! Only sets the background material name if not ""
+    void OrxonoxOverlay::setBackgroundMaterial(const std::string& material)
+    {
+        if (this->background_ && !material.empty())
+            this->background_->setMaterialName(material);
+    }
+
+    //! Returns the the material name of the background
+    const std::string& OrxonoxOverlay::getBackgroundMaterial() const
+    {
+        if (this->background_)
+            return this->background_->getMaterialName();
+        else
+            return BLANKSTRING;
+    }
+
+    //! Sets the background texture name and creates a new material if necessary
+    void OrxonoxOverlay::setBackgroundTexture(const std::string& texture)
+    {
+        if (this->background_ && this->background_->getMaterial().isNull() && !texture.empty())
+        {
+            // create new material
+            const std::string& materialname = "generated_material" + getUniqueNumberString();
+            Ogre::MaterialPtr material = static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().create(materialname, "General"));
+            material->getTechnique(0)->getPass(0)->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
+            Ogre::TextureUnitState* textureUnitState_ = material->getTechnique(0)->getPass(0)->createTextureUnitState();
+            textureUnitState_->setTextureName(texture);
+            textureUnitState_->setNumMipmaps(0);
+            this->background_->setMaterialName(materialname);
+        }
+    }
+
+    //! Returns the the texture name of the background
+    const std::string& OrxonoxOverlay::getBackgroundTexture() const
+    {
+        if (this->background_)
+        {
+            Ogre::TextureUnitState* tempTx = this->background_->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0);
+            return tempTx->getTextureName();
+        }
+        else
+            return BLANKSTRING;
+    }
+
+    //! Called by BaseObject when visibility has changed.
+    void OrxonoxOverlay::changedVisibility()
+    {
+        SUPER( OrxonoxOverlay, changedVisibility );
+
+        if (!this->overlay_)
+            return;
+
+        // only set to visible if corresponding OverlayGroup is also visible
+        if (this->isVisible() && (!this->getOverlayGroup() || this->getOverlayGroup()->isVisible()) )
+            this->overlay_->show();
+        else
+            this->overlay_->hide();
+    }
+
+    /**
+    @brief
+        Called by the GraphicsManager whenever the window size changes.
+        Calculates the aspect ratio only.
+    */
+    void OrxonoxOverlay::windowResized(unsigned int newWidth, unsigned int newHeight)
+    {
+        this->windowAspectRatio_ = static_cast<float>(newWidth) / newHeight;
+        this->sizeCorrectionChanged();
+    }
+
+    /**
+    @brief
+        Called whenever the rotation angle has changed.
+    */
+    void OrxonoxOverlay::angleChanged()
+    {
+        if (!this->overlay_)
+            return;
+
+        this->overlay_->setRotate(this->angle_);
+        this->sizeCorrectionChanged();
+    }
+
+    /**
+    @brief
+        Called whenever the aspect ratio or the angle has changed.
+        The method calculates a correction factor for the size to compensate
+        for aspect distortion if desired.
+    @remarks
+        This only works when the angle is about 0 or 90 degrees.
+    */
+    void OrxonoxOverlay::sizeCorrectionChanged()
+    {
+        if (this->bCorrectAspect_)
+        {
+            float angle = this->angle_.valueDegrees();
+            if (angle < 0.0)
+                angle = -angle;
+            angle -= 180.0f * static_cast<int>(angle / 180.0);
+
+            // take the reverse if angle is about 90 degrees
+            float tempAspect;
+            if (angle > 89.0f && angle < 91.0f)
+            {
+                tempAspect = 1.0f / this->windowAspectRatio_;
+                rotState_ = RotationState::Vertical;
+            }
+            else if (angle > 179 || angle < 1)
+            {
+                tempAspect = this->windowAspectRatio_;
+                rotState_ = RotationState::Horizontal;
+            }
+            else
+            {
+                tempAspect = 1.0f;
+                rotState_ = RotationState::Inbetween;
+            }
+
+            // note: this is only an approximation that is mostly valid when the
+            // magnitude of the width is about the magnitude of the height.
+            // Correctly we would have to take the square root of width*height
+            this->sizeCorrection_.x = 2.0f / (tempAspect + 1.0f);
+            this->sizeCorrection_.y = tempAspect * this->sizeCorrection_.x;
+        }
+        else
+        {
+            this->sizeCorrection_ = Vector2::UNIT_SCALE;
+        }
+
+        this->sizeChanged();
+    }
+
+    /**
+    @brief
+        Sets the overlay size using the actual corrected size.
+    */
+    void OrxonoxOverlay::sizeChanged()
+    {
+        if (!this->overlay_)
+            return;
+
+        this->overlay_->setScale(size_.x * sizeCorrection_.x, size_.y * sizeCorrection_.y);
+        positionChanged();
+    }
+
+    /**
+    @brief
+        Determines the position of the overlay.
+        This works also well when a rotation angle is applied. The overlay always
+        gets aligned correctly as well as possible.
+    */
+    void OrxonoxOverlay::positionChanged()
+    {
+        if (!this->overlay_)
+            return;
+
+        // transform the angle to a range of 0 - pi/2 first.
+        float angle = this->angle_.valueRadians();
+        if (angle < 0.0)
+            angle = -angle;
+        angle -= math::pi * static_cast<int>(angle / (math::pi));
+        if (angle > math::pi_2)
+            angle = math::pi - angle;
+
+        // do some mathematical fiddling for a bounding box
+        Vector2 actualSize = size_ * sizeCorrection_;
+        float radius = actualSize.length();
+        float phi = atan(actualSize.y / actualSize.x);
+        Vector2 boundingBox(radius * cos(angle - phi), radius * sin(angle + phi));
+
+        // calculate the scrolling offset
+        Vector2 scroll = (position_ - 0.5 - boundingBox * (pickPoint_ - 0.5)) * 2.0;
+        this->overlay_->setScroll(scroll.x, -scroll.y);
+    }
+
+
+    //########### Console commands ############
+
+    /**
+    @brief
+        Scales an overlay by its name.
+    @param name
+        The name of the overlay defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    @param scale
+        The scaling factor
+    */
+    /*static*/ void OrxonoxOverlay::scaleOverlay(const std::string& name, float scale)
+    {
+        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
+        if (it != overlays_s.end())
+            it->second->scale(Vector2(scale, scale));
+    }
+
+    /**
+    @brief
+        Toggles the visibility of an Overlay by it's name.
+    @param name
+        The name of the overlay defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    */
+    /*static*/ void OrxonoxOverlay::toggleVisibility(const std::string& name)
+    {
+        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
+        if (it != overlays_s.end())
+        {
+            OrxonoxOverlay* overlay= it->second;
+            if(overlay->isVisible())
+            {
+                overlay->hide();
+                orxout(verbose, context::misc::overlays) << "HIDE " << name << endl;
+            }
+            else
+            {
+                overlay->show();
+                orxout(verbose, context::misc::overlays) << "SHOW " << name << endl;
+            }
+        }
+    }
+    
+    /**
+    @brief
+        Shows Overlay by it's name.
+    @param name
+        The name of the overlay defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    */
+    /*static*/ void OrxonoxOverlay::showOverlay(const std::string& name)
+    {
+        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
+        if (it != overlays_s.end())
+        {
+            OrxonoxOverlay* overlay= it->second;
+            if(overlay->isVisible())
+                overlay->changedVisibility();
+            else
+                overlay->show();
+        }
+    }
+
+    /**
+    @brief
+        Scrolls an overlay by its name.
+    @param name
+        The name of the overlay defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    @param scroll
+        The relative translation of the overlay
+    */
+    /*static*/ void OrxonoxOverlay::scrollOverlay(const std::string& name, const Vector2& scroll)
+    {
+        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
+        if (it != overlays_s.end())
+            it->second->scroll(scroll);
+    }
+
+    /**
+    @brief
+        Rotates an overlay by its name.
+    @param name
+        The name of the overlay defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    @param angle
+        The rotation angle in degree
+    */
+    /*static*/ void OrxonoxOverlay::rotateOverlay(const std::string& name, const Degree& angle)
+    {
+        std::map<std::string, OrxonoxOverlay*>::const_iterator it = overlays_s.find(name);
+        if (it != overlays_s.end())
+            it->second->rotate(angle);
+    }
+
+    void OrxonoxOverlay::setOverlayGroup(OverlayGroup* group)
+    {
+        if (group != this->group_)
+        {
+            if (this->group_)
+                this->group_->removeElement(this);
+            this->group_ = group;
+            this->changedOverlayGroup();
+        }
+    }
+
+    void OrxonoxOverlay::setBackgroundAlpha(float alpha)
+    {
+        Ogre::MaterialPtr ptr = this->background_->getMaterial();
+        Ogre::TextureUnitState* tempTx = ptr->getTechnique(0)->getPass(0)->getTextureUnitState(0);
+        tempTx->setAlphaOperation(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, alpha);
+    }
+
+    void OrxonoxOverlay::setBackgroundColour(ColourValue colour)
+    {
+        Ogre::MaterialPtr ptr = this->background_->getMaterial();
+        Ogre::TextureUnitState* tempTx = ptr->getTechnique(0)->getPass(0)->getTextureUnitState(0);
+        tempTx->setColourOperationEx(Ogre::LBX_MODULATE, Ogre::LBS_MANUAL, Ogre::LBS_CURRENT, colour);
+    }
+
+    void OrxonoxOverlay::setZOrder(unsigned short order)
+    {
+        if (this->overlay_)
+        {
+            this->overlay_->setZOrder(order);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/OrxonoxOverlay.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/OrxonoxOverlay.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/OrxonoxOverlay.h	(revision 11817)
@@ -0,0 +1,224 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief Declaration of the OrxonoxOverlay class.
+*/
+
+#ifndef _OrxonoxOverlay_H__
+#define _OrxonoxOverlay_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+
+#include "util/Math.h"
+#include "util/OgreForwardRefs.h"
+#include "core/BaseObject.h"
+#include "core/WindowEventListener.h"
+#include "core/class/Super.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        Base class to display content directly onto the screen.
+        This is merely a wrapper of the Ogre::Overlay to implement more features and integrate it
+        in our class hierarchy for xml loading and config values.
+        The mentioned features are:
+        - Automatic positioning depending on the scale and the rotation angle.
+          You can specify a "pick point" relative to the overlay itself. This point will always be exactly
+          at the position (position_) of the overlay. That allows for margin/corner aligment.
+          It even works when a rotation angle is applied.
+        - Virtual methods for changedVisibilty() (BaseObject), angleChanged(), sizeCorrectionChanged(),
+          sizeChanged() and positionChanged(), that can be overridden by any derivative. This enables for
+          custom configurability of the size, position and rotation attributes. For intance, the HUDNavigation
+          should behave differently to sizeChanged() than a standard overlay.
+        - Console commands for scale, rotate and scroll (accessed by name)
+        - Standard Ogre::PanelOverlayElement for a background image (class doesn't have to be derived
+          only for displaying a picture).
+        - Reacts to changes of the window aspect
+        - Last but not least: On demand you can tell the overlay to automatically rescale to correct for
+          aspect distortion. E.g. if you play 1024x768 you wouldn't want a round object to be oval.
+          Remark: This can (due to the Ogre::Overlay transformation order) only work for angle that are
+                  multiples of 90 degrees. But it's only a small drawback.
+    */
+    class _OrxonoxExport OrxonoxOverlay : public BaseObject, public WindowEventListener
+    {
+    public:
+        /**
+        @brief
+            Describes the rotational state of a an overlay.
+            Horizontal means 0/180 degrees, Vertical is 90/270 degrees
+            and in between is everything else.
+        */
+        enum class RotationState
+        {
+            Horizontal,
+            Vertical,
+            Inbetween
+        };
+
+    public:
+        OrxonoxOverlay(Context* context);
+        virtual ~OrxonoxOverlay();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        virtual void changedName() override;
+
+        //! Shows the overlay with an detour to BaseObject::visibility_
+        void show() { this->setVisible(true); }
+        //! Hides the overlay with an detour to BaseObject::visibility_
+        void hide() { this->setVisible(false); }
+
+        /** Sets whether the aspect of the overlay is corrected.
+            This is for instance useful for round objects that should stay round no matter
+            what the screen resolution is. */
+        void setAspectCorrection(bool val)        { this->bCorrectAspect_ = val; this->sizeCorrectionChanged(); }
+        //! Returns whether the window aspect is corrected
+        bool getAspectCorrection() const          { return this->bCorrectAspect_; }
+
+        //! Sets the position of this overlay on the screen.
+        void setPosition(Vector2 pos)             { this->position_ = pos; this->positionChanged(); }
+
+        //! Returns the current position on the screen.
+        const Vector2& getPosition() const        { return this->position_; }
+
+        //! Scrolls the overlay. @param offset The offset given.
+        void scroll(const Vector2& offset)        { this->position_ += offset; this->positionChanged(); }
+
+        /** Sets the point in the overlay where to pick it when translating.
+            For instance setting it to (1.0,1.0) means that the lower right corner of the
+            overlay will be put at position_.
+            This primarily helps aligning an overlay to any corner/margin on the screen. */
+        void setPickPoint(const Vector2& position){ this->pickPoint_ = position; this->positionChanged(); }
+
+        //! Gets the pick point of this overlay. @see setPickPoint()
+        const Vector2& getPickPoint() const       { return this->pickPoint_; }
+
+        //! Sets the rotation angle applied to this overlay in degrees.
+        void setRotation(const Degree& angle)     { this->angle_ = angle; this->angleChanged(); }
+
+        //! Gets the rotation angle applied to this overlay in degrees.
+        const Degree& getRotation() const         { return this->angle_; }
+
+        //! Rotates the overlay by angle degrees.
+        void rotate(const Degree& angle)          { this->angle_ += angle; this->angleChanged(); }
+
+        //! Sets the size of this overlay.
+        void setSize(const Vector2& size)         { this->size_ = size; this->sizeChanged(); }
+
+        //! Gets the current size that was set (uncorrected)
+        const Vector2& getSize() const            { return this->size_; }
+
+        //! Gets the actual size of the overlay on the screen (corrected)
+        Vector2 getActualSize() const             { return this->size_ * this->sizeCorrection_; }
+
+        //! Gets the current size correction (default: 1.0, 1.0)
+        const Vector2& getSizeCorrection() const  { return this->sizeCorrection_; }
+
+        //! Scales the overlay by scale.
+        void scale(const Vector2& scale)          { this->size_ *= scale; this->sizeChanged(); }
+
+        //! ConsoleCommand: Accesses the overlay by its name and scales it.
+        static void scaleOverlay(const std::string& name, float scale);
+        //! ConsoleCommand: Accesses the overlay by its name and scrolls it.
+        static void scrollOverlay(const std::string& name, const Vector2& scroll);
+        static void toggleVisibility(const std::string& name);
+        static void showOverlay(const std::string& name);
+        //! ConsoleCommand: Accesses the overlay by its name and rotates it.
+        static void rotateOverlay(const std::string& name, const Degree& angle);
+
+        void setBackgroundMaterial(const std::string& material);
+        const std::string& getBackgroundMaterial() const;
+
+        void setBackgroundTexture(const std::string& texture);
+        const std::string& getBackgroundTexture() const;
+
+        void setBackgroundAlpha(float alpha);
+
+        void setBackgroundColour(ColourValue colour);
+
+        virtual void changedVisibility() override;
+
+        inline void setOwner(BaseObject* owner)
+        {
+            if (this->owner_ != owner)
+            {
+                this->owner_ = owner;
+                this->changedOwner();
+            }
+        }
+        inline BaseObject* getOwner() const
+            { return this->owner_; }
+        virtual void changedOwner() {}
+
+        void setOverlayGroup(OverlayGroup* group);
+        inline OverlayGroup* getOverlayGroup() const
+            { return this->group_; }
+        virtual void changedOverlayGroup()
+            { this->changedVisibility(); }
+        void setZOrder(unsigned short order);
+
+    protected:
+        virtual void angleChanged();
+        virtual void sizeCorrectionChanged();
+        virtual void sizeChanged();
+        virtual void positionChanged();
+
+        Ogre::Overlay* overlay_;                   //!< The overlay the entire class is about.
+        Ogre::PanelOverlayElement* background_;    //!< Background image (blank per default).
+
+        float windowAspectRatio_;                  //!< Screen.width / screen.height
+        bool bCorrectAspect_;                      //!< Whether or not to correct the size. @see setAspectCorrection()
+        Vector2 size_;                             //!< Internal size of the overlay.
+        Vector2 sizeCorrection_;                   //!< Value to correct the size because of the window aspect.
+        Vector2 position_;                         //!< Position of the pickPoint on the screen.
+        Vector2 pickPoint_;                        //!< Point on the overlay to pick when translating
+        Degree angle_;                             //!< Rotation angle of the overlay
+        RotationState rotState_;                   //!< horizontal, vertical or inbetween
+
+    private:
+        virtual void windowResized(unsigned int newWidth, unsigned int newHeight) override;
+
+        static unsigned int hudOverlayCounter_s;   //!< Static counter for hud elements
+        /** Contains all the overlays in a map for quick access via console commands.
+            We could also use the ObjectList, but that doesn't guarantee XMLPort(.) was called and is slower. */
+        static std::map<std::string, OrxonoxOverlay*> overlays_s;
+        BaseObject* owner_;
+        OverlayGroup* group_;
+        Ogre::Pass* backgroundAlphaPass_;
+  };
+
+  SUPER_FUNCTION(6, OrxonoxOverlay, changedOwner, false);
+  SUPER_FUNCTION(7, OrxonoxOverlay, changedOverlayGroup, false);
+}
+
+#endif /* _OrxonoxOverlay_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/OverlayGroup.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/OverlayGroup.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/OverlayGroup.cc	(revision 11817)
@@ -0,0 +1,248 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief Definition of the OverlayGroup class.
+*/
+
+#include "OverlayGroup.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "OrxonoxOverlay.h"
+#include "gametypes/Gametype.h"
+
+namespace orxonox
+{
+    namespace autocompletion
+    {
+        /**
+            @brief Returns the names of all currently existing OverlayGroups.
+        */
+        ARGUMENT_COMPLETION_FUNCTION_DECLARATION(overlaygroupnames)();
+        ARGUMENT_COMPLETION_FUNCTION_IMPLEMENTATION(overlaygroupnames)()
+        {
+            ArgumentCompletionList names;
+            for (OverlayGroup* overlayGroup : ObjectList<OverlayGroup>())
+                names.push_back(ArgumentCompletionListElement(overlayGroup->getName(), getLowercase(overlayGroup->getName())));
+            return names;
+        }
+    }
+
+    SetConsoleCommand("OverlayGroup", "toggleVisibility", &OverlayGroup::toggleVisibility).argumentCompleter(0, autocompletion::overlaygroupnames());
+    SetConsoleCommand("OverlayGroup", "show",             &OverlayGroup::show            ).argumentCompleter(0, autocompletion::overlaygroupnames());
+    SetConsoleCommand("OverlayGroup", "scaleGroup",       &OverlayGroup::scaleGroup      ).argumentCompleter(0, autocompletion::overlaygroupnames());
+    SetConsoleCommand("OverlayGroup", "scrollGroup",      &OverlayGroup::scrollGroup     ).argumentCompleter(0, autocompletion::overlaygroupnames());
+
+    RegisterClass(OverlayGroup);
+
+    OverlayGroup::OverlayGroup(Context* context)
+        : BaseObject(context)
+    {
+        RegisterObject(OverlayGroup);
+
+        this->owner_ = nullptr;
+
+        setScale(Vector2(1.0, 1.0));
+        setScroll(Vector2(0.0, 0.0));
+    }
+
+    OverlayGroup::~OverlayGroup()
+    {
+        for (OrxonoxOverlay* hudElement : hudElements_)
+            hudElement->destroy();
+        this->hudElements_.clear();
+    }
+
+    /**
+    @brief
+        Loads the group and all its children OrxonoxOverlays.
+    @copydoc BaseObject::XMLPort()
+    */
+    void OverlayGroup::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(OverlayGroup, XMLPort, xmlelement, mode);
+
+        XMLPortParam(OverlayGroup, "scale",  setScale,  getScale,  xmlelement, mode);
+        XMLPortParam(OverlayGroup, "scroll", setScroll, getScroll, xmlelement, mode);
+        // loads all the child elements
+        XMLPortObject(OverlayGroup, OrxonoxOverlay, "", addElement, getElement, xmlelement, mode);
+    }
+
+    //! Scales every element in the set.
+    void OverlayGroup::setScale(const Vector2& scale)
+    {
+        for (OrxonoxOverlay* hudElement : hudElements_)
+            hudElement->scale(scale / this->scale_);
+        this->scale_ = scale;
+    }
+
+    //! Scrolls every element in the set.
+    void OverlayGroup::setScroll(const Vector2& scroll)
+    {
+        for (OrxonoxOverlay* hudElement : hudElements_)
+            hudElement->scroll(scroll - this->scroll_);
+        this->scroll_ = scroll;
+    }
+
+    /**
+    @brief
+        Adds an element to the set (used when loading with XMLPort).
+    @remarks
+        The names of the OrxonoxOverlays have to be unique!
+    */
+    void OverlayGroup::addElement(OrxonoxOverlay* element)
+    {
+        hudElements_.insert(element);
+        element->setOverlayGroup( this );
+        if (this->owner_)
+            element->setOwner(this->owner_);
+    }
+
+    /**
+    @brief
+        Removes an element from the map.
+    @param element
+        A pointer to the element that is removed.
+    @return
+        Returns true if there was such an element to remove, false if not.
+    */
+    bool OverlayGroup::removeElement(OrxonoxOverlay* element)
+    {
+        if(this->hudElements_.erase(element) == 0)
+            return false;
+        return true;
+    }
+
+    //! Returns a different element as long as index < hudElements_.size().
+    OrxonoxOverlay* OverlayGroup::getElement(unsigned int index)
+    {
+        if (index < this->hudElements_.size())
+        {
+            std::set<StrongPtr<OrxonoxOverlay>>::const_iterator it = hudElements_.begin();
+            for (unsigned int i = 0; i != index; ++it, ++i)
+                ;
+            return *it;
+        }
+        else
+            return nullptr;
+    }
+
+    //! Changes the visibility of all elements
+    void OverlayGroup::changedVisibility()
+    {
+        SUPER( OverlayGroup, changedVisibility );
+
+        for (OrxonoxOverlay* hudElement : hudElements_)
+            hudElement->changedVisibility(); //inform all Child Overlays that our visibility has changed
+    }
+
+    void OverlayGroup::setOwner(BaseObject* owner)
+    {
+        this->owner_ = owner;
+
+        for (OrxonoxOverlay* hudElement : hudElements_)
+            hudElement->setOwner(owner);
+    }
+
+    //########### Console commands ############
+
+    /**
+    @brief
+        Hides/shows an overlay group by its name.
+    @param name
+        The name of the group defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    */
+    /*static*/ void OverlayGroup::toggleVisibility(const std::string& name)
+    {
+        for (OverlayGroup* group : ObjectList<OverlayGroup>())
+        {
+            if (group->getName() == name)
+                group->setVisible(!(group->isVisible()));
+        }
+    }
+    
+    /**
+    @brief
+        Shows an overlay group by its name.
+    @param name
+        The name of the group defined BaseObject::setName() (usually done with the "name" attribute in the xml file).
+    */
+    /*static*/ void OverlayGroup::show(const std::string& name)
+    {
+        for (OverlayGroup* group : ObjectList<OverlayGroup>())
+        {
+            if (group->getName() == name)
+            {
+                if(group->isVisible())
+                    group->changedVisibility();
+                else
+                    group->setVisible(!(group->isVisible()));
+            }
+        }
+    }
+
+    /**
+    @brief
+        Scales an overlay group by its name.
+    @param name
+        The name of the group defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    @param scale
+        The scaling factor
+    */
+    /*static*/ void OverlayGroup::scaleGroup(const std::string& name, float scale)
+    {
+        for (OverlayGroup* group : ObjectList<OverlayGroup>())
+        {
+            if (group->getName() == name)
+                group->scale(Vector2(scale, scale));
+        }
+    }
+
+    /**
+    @brief
+        Scrolls an overlay group by its name.
+    @param name
+        The name of the group defined BaseObject::setName() (usually done with the "name"
+        attribute in the xml file).
+    @param scroll
+        The relative translation of the overlay group
+    */
+    /*static*/ void OverlayGroup::scrollGroup(const std::string& name, const Vector2& scroll)
+    {
+        for (OverlayGroup* group : ObjectList<OverlayGroup>())
+        {
+            if (group->getName() == name)
+                group->scroll(scroll);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/overlays/OverlayGroup.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/overlays/OverlayGroup.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/overlays/OverlayGroup.h	(revision 11817)
@@ -0,0 +1,100 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+@file
+@brief Declaration of the OverlayGroup class.
+*/
+
+#ifndef _OverlayGroup_H__
+#define _OverlayGroup_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <set>
+#include "util/Math.h"
+#include "util/OgreForwardRefs.h"
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        OverlayGroup does almost exactly what it says: It groups OrxonoxOverlays together.
+        You can scroll the entire group by a certain amount. Scale however works differently
+        than expected: Each OrxonoxOverlay scales individually. That's quite useful when you
+        create your HUD with an OverlayGroup and then want to alter its size.
+    */
+    class _OrxonoxExport OverlayGroup : public BaseObject
+    {
+    public:
+        OverlayGroup(Context* context);
+        //! Empty destructor.
+        ~OverlayGroup();
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+        static void toggleVisibility(const std::string& name);
+        static void show(const std::string& name);
+        static void scaleGroup(const std::string& name, float scale);
+        static void scrollGroup(const std::string& name, const Vector2& scroll);
+
+        inline const std::set<StrongPtr<OrxonoxOverlay>>& getOverlays() const
+            { return this->hudElements_; }
+
+        virtual void changedVisibility() override;
+
+        void setOwner(BaseObject* owner);
+        inline BaseObject* getOwner() const
+            { return this->owner_; }
+
+        //! Scales each OrxonoxOverlay individually by scale.
+        void scale(const Vector2& scale) { this->setScale(scale * this->scale_); }
+        void setScale(const Vector2& scale);
+        //! Returns the current size of the group.
+        Vector2 getScale() const { return this->scale_; }
+
+        //! Scrolls each OrxonoxOverlay individually by scroll.
+        void scroll(const Vector2& scroll) { this->setScroll(scroll + this->scroll_); }
+        void setScroll(const Vector2& scroll);
+        //! Returns the current scrolling offset of the group.
+        Vector2 getScroll() const { return this->scale_; }
+
+        void addElement(OrxonoxOverlay* element);
+        bool removeElement(OrxonoxOverlay* element);
+        OrxonoxOverlay* getElement(unsigned int index);
+
+    private:
+        std::set<StrongPtr<OrxonoxOverlay>> hudElements_;    //!< Contains all the OrxonoxOverlays of the this group.
+        Vector2 scale_;                            //!< Current scale (independent of the elements).
+        Vector2 scroll_;                           //!< Current scrolling offset.
+        BaseObject* owner_;                        //!< The owner of this OverlayGroup
+    };
+}
+
+#endif /* _OverlayGroup_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/AmbientSound.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/AmbientSound.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/AmbientSound.cc	(revision 11817)
@@ -0,0 +1,120 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "AmbientSound.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/Resource.h"
+#include "SoundManager.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(AmbientSound).inheritsFrom<BaseSound>().inheritsFrom<MoodListener>();
+
+    AmbientSound::AmbientSound()
+        : bPlayOnLoad_(false)
+    {
+        RegisterObject(AmbientSound);
+
+        // Ambient sounds always fade in
+        this->setVolume(0.0f);
+    }
+
+    void AmbientSound::preDestroy()
+    {
+        if (GameMode::playsSound())
+        {
+            // Smoothly fade out by keeping a StrongPtr
+            SoundManager::getInstance().unregisterAmbientSound(this);
+        }
+    }
+
+    void AmbientSound::play()
+    {
+        if (GameMode::playsSound())
+            SoundManager::getInstance().registerAmbientSound(this);
+    }
+
+    bool AmbientSound::stop()
+    {
+        if (GameMode::playsSound())
+            SoundManager::getInstance().unregisterAmbientSound(this);
+        return false; // sound source not (yet) destroyed - return false
+    }
+
+    void AmbientSound::pause()
+    {
+        if (GameMode::playsSound())
+            SoundManager::getInstance().pauseAmbientSound(this);
+    }
+
+    float AmbientSound::getRealVolume()
+    {
+        assert(GameMode::playsSound());
+        return SoundManager::getInstance().getRealVolume(SoundType::Music);
+    }
+
+    bool AmbientSound::setAmbientSource(const std::string& source)
+    {
+        this->ambientSource_ = source;
+        return(this->moodChanged(MoodManager::getInstance().getMood()));
+    }
+
+    bool AmbientSound::moodChanged(const std::string& mood)
+    {
+        if (GameMode::playsSound())
+        {
+            const std::string& path = "ambient/" + mood + '/' + this->ambientSource_;
+            std::shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(path);
+            if (fileInfo != nullptr)
+            {
+                orxout(user_info) << "Loading ambient sound " << path << "..." << endl; // TODO: make this output internal if we implement sound streaming
+                this->setSource(path);
+
+                // all went fine
+                return true;
+            }
+            else
+            {
+                orxout(internal_warning, context::sound) << this->ambientSource_ << ": Not a valid name! Ambient sound will not change." << endl;
+
+                // everything went southways
+                return false;
+            }
+        }
+        return false;
+    }
+
+    void AmbientSound::setPlayOnLoad(bool val)
+    {
+        this->bPlayOnLoad_ = val;
+        if (val)
+            this->play();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/AmbientSound.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/AmbientSound.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/AmbientSound.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Kevin Young
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _AmbientSound_H__
+#define _AmbientSound_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "BaseSound.h"
+#include "MoodManager.h"
+
+namespace orxonox
+{
+    /**
+     * The AmbientSound class is used to play background music. It can not be placed
+     * directly in a level file, use WorldAmbientSound instead.
+     */
+    class _OrxonoxExport AmbientSound : public BaseSound, public MoodListener
+    {
+        friend class SoundManager;
+        friend class WorldAmbientSound;
+
+    public:
+        AmbientSound();
+
+        virtual void play() override;
+        virtual bool stop() override;
+        virtual void pause() override;
+
+        bool setAmbientSource(const std::string& source);
+        inline const std::string& getAmbientSource() const
+            { return this->ambientSource_; }
+
+        void setPlayOnLoad(bool val);
+        bool getPlayOnLoad() const
+            { return this->bPlayOnLoad_; }
+
+    protected:
+        ~AmbientSound() { }
+
+    private:
+        virtual void preDestroy() override;
+        virtual float getRealVolume() override;
+        virtual bool moodChanged(const std::string& mood) override;
+        inline void ambientSourceChanged()
+            { this->setAmbientSource(this->ambientSource_); }
+        inline void playOnLoadChanged()
+            { this->setPlayOnLoad(this->bPlayOnLoad_); }
+
+        std::string ambientSource_; //!< Analogous to source_, but mood independent
+        bool        bPlayOnLoad_;   //!< Play the sound immediately when loaded
+    };
+}
+
+#endif /* _AmbientSound_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/BaseSound.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/BaseSound.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/BaseSound.cc	(revision 11817)
@@ -0,0 +1,285 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#include "BaseSound.h"
+
+#include <cassert>
+#include <vector>
+#include <al.h>
+
+#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/Resource.h"
+#include "core/XMLPort.h"
+#include "SoundBuffer.h"
+#include "SoundManager.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(BaseSound).inheritsFrom<Listable>();
+
+    BaseSound::BaseSound()
+        : bPooling_(false)
+        , volume_(0.7)
+        , bLooping_(false)
+        , state_(State::Stopped)
+        , pitch_ (1.0)
+    {
+        RegisterObject(BaseSound);
+
+        // Initialise audioSource_ to a value that is not a source
+        // 0 is unfortunately not guaranteed to be no source ID.
+        // HACK!
+        this->audioSource_ = 0;
+        //while (alIsSource(++this->audioSource_));
+    }
+
+    BaseSound::~BaseSound()
+    {
+        if (this->state_ != State::Stopped)
+            this->stop();
+        // Release buffer
+        if (this->soundBuffer_ != nullptr)
+        {
+            assert(GameMode::playsSound());
+            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
+        }
+    }
+
+    void BaseSound::XMLPortExtern(Element& xmlelement, XMLPort::Mode mode)
+    {
+        XMLPortParam(BaseSound, "volume",  setVolume,  getVolume,  xmlelement, mode);
+        XMLPortParam(BaseSound, "looping", setLooping, getLooping, xmlelement, mode);
+        XMLPortParam(BaseSound, "pitch",   setPitch,   getPitch,   xmlelement, mode);
+        XMLPortParam(BaseSound, "source",  setSource,  getSource,  xmlelement, mode);
+    }
+
+    void BaseSound::doPlay()
+    {
+        this->state_ = State::Playing;
+        if (GameMode::playsSound() && this->getSourceState() != AL_PLAYING && this->soundBuffer_ != nullptr)
+        {
+            if (!alIsSource(this->audioSource_))
+            {
+                this->audioSource_ = SoundManager::getInstance().getSoundSource(this);
+                if (!alIsSource(this->audioSource_))
+                    return;
+                this->initialiseSource();
+            }
+
+            alSourcePlay(this->audioSource_);
+            if (int error = alGetError())
+                orxout(internal_error, context::sound) << "Error playing sound: " << SoundManager::getALErrorString(error) << endl;
+        }
+    }
+
+    bool BaseSound::doStop()
+    {
+        this->state_ = State::Stopped;
+        if (alIsSource(this->audioSource_))
+        {
+            alSourceStop(this->audioSource_);
+            // Release buffer
+            alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
+            // Release source again
+            SoundManager::getInstance().releaseSoundSource(this->audioSource_);
+            // Get a no source ID
+            this->audioSource_ += 123455;
+            while (alIsSource(++this->audioSource_));
+
+            return true; // sound source destroyed - return true
+        }
+        return false; // nothing done - return false
+    }
+
+    void BaseSound::doPause()
+    {
+        if (this->isStopped())
+            return;
+        this->state_ = State::Paused;
+        if (alIsSource(this->audioSource_))
+            alSourcePause(this->audioSource_);
+    }
+
+    ALint BaseSound::getSourceState() const
+    {
+        if (alIsSource(this->audioSource_))
+        {
+            ALint state;
+            alGetSourcei(this->audioSource_, AL_SOURCE_STATE, &state);
+            return state;
+        }
+        else
+            return AL_INITIAL;
+    }
+
+    void BaseSound::initialiseSource()
+    {
+        this->updateVolume();
+        this->setPitch(this->getPitch());
+        this->setLooping(this->getLooping());
+        alSource3f(this->audioSource_, AL_POSITION,  0, 0, 0);
+        alSource3f(this->audioSource_, AL_VELOCITY,  0, 0, 0);
+        alSource3f(this->audioSource_, AL_DIRECTION, 0, 0, 0);
+        if (ALint error = alGetError())
+            orxout(internal_warning, context::sound) << "Setting source parameters to 0 failed: "
+                                                     << SoundManager::getALErrorString(error) << endl;
+        assert(this->soundBuffer_ != nullptr);
+        alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
+        if (ALuint error = alGetError())
+            orxout(internal_error, context::sound) << "Could not set buffer \"" << this->source_ << "\": " << SoundManager::getALErrorString(error) << endl;
+    }
+
+    void BaseSound::setVolume(float vol)
+    {
+        this->volume_ = clamp(vol, 0.0f, 1.0f);
+        if (this->volume_ != vol)
+            orxout(internal_warning, context::sound) << "Volume out of range, clamping value." << endl;
+        this->updateVolume();
+    }
+
+    void BaseSound::updateVolume()
+    {
+        if (alIsSource(this->audioSource_))
+        {
+            float volume = this->volume_ * this->getRealVolume();                
+            alSourcef(this->audioSource_, AL_GAIN, volume);
+            if (int error = alGetError())
+                orxout(internal_error, context::sound) << "Error setting volume to " << volume
+                                                       << ": " << SoundManager::getALErrorString(error) << endl;
+        }
+    }
+
+    void BaseSound::setLooping(bool val)
+    {
+        this->bLooping_ = val;
+        if (alIsSource(this->audioSource_))
+            alSourcei(this->audioSource_, AL_LOOPING, (val ? AL_TRUE : AL_FALSE));
+    }
+
+    void BaseSound::setPitch(float pitch)
+    {
+        if (pitch > 2 || pitch < 0.5f)
+        {
+            orxout(internal_warning, context::sound) << "Pitch out of range, cropping value." << endl;
+            pitch = pitch > 2.0f ? 2.0f : pitch;
+            pitch = pitch < 0.5f ? 0.5f : pitch;
+        }
+        this->pitch_ = pitch;
+        if (alIsSource(this->audioSource_))
+        {
+            alSourcef(this->audioSource_, AL_PITCH, pitch);
+            if (int error = alGetError())
+                orxout(internal_error, context::sound) << "Error setting pitch: " << SoundManager::getALErrorString(error) << endl;
+        }
+    }
+
+    void BaseSound::setSource(const std::string& source)
+    {
+        if (!GameMode::playsSound())
+        {
+            this->source_ = source;
+            return;
+        }
+
+        if (this->soundBuffer_ != nullptr)
+        {
+            if (this->soundBuffer_->getFilename() == source)
+            {
+                assert(this->source_ == source_);
+                return;
+            }
+            // Stopping is imperative here!
+            if (alIsSource(this->audioSource_))
+            {
+                alSourceStop(this->audioSource_);
+                alSourcei(this->audioSource_, AL_BUFFER, AL_NONE);
+            }
+            SoundManager::getInstance().releaseSoundBuffer(this->soundBuffer_, this->bPooling_);
+            this->soundBuffer_.reset();
+        }
+
+        this->source_ = source;
+        // Don't load ""
+        if (source_.empty())
+            return;
+
+        // Get new sound buffer
+        this->soundBuffer_ = SoundManager::getInstance().getSoundBuffer(this->source_);
+        if (this->soundBuffer_ == nullptr)
+            return;
+
+        if (alIsSource(this->audioSource_)) // already playing or paused
+        {
+            // Set new buffer
+            alSourcei(this->audioSource_, AL_BUFFER, this->soundBuffer_->getBuffer());
+            if (ALuint error = alGetError())
+            {
+                orxout(internal_error, context::sound) << "Could not set buffer \"" << source << "\": " << SoundManager::getALErrorString(error) << endl;
+                return;
+            }
+
+            // Sound was already playing or paused because there was a source acquired
+            assert(this->isPlaying() || this->isPaused());
+            alSourcePlay(this->audioSource_);
+            if (int error = alGetError())
+                orxout(internal_error, context::sound) << "Error playing sound: " << SoundManager::getALErrorString(error) << endl;
+            if (this->isPaused())
+                alSourcePause(this->audioSource_);
+        }
+        else // No source acquired so far, but might be set to playing or paused
+        {
+            State state = this->state_; // save
+            if (this->isPlaying() || this->isPaused())
+                doPlay();
+            if (state == State::Paused)
+            {
+                this->state_ = State::Paused;
+                doPause();
+            }
+        }
+    }
+
+    void BaseSound::stateChanged()
+    {
+        switch (this->state_)
+        {
+            case State::Playing:
+                this->play();
+                break;
+            case State::Paused:
+                this->pause();
+                break;
+            case State::Stopped:
+            default:
+                this->stop();
+                break;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/BaseSound.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/BaseSound.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/BaseSound.h	(revision 11817)
@@ -0,0 +1,121 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#ifndef _BaseSound_H__
+#define _BaseSound_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <memory>
+#include <OgreDataStream.h>
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    /**
+     * The BaseSound class is the base class for all sound file loader classes.
+     * It serves as main interface to the OpenAL library.
+     */
+    class _OrxonoxExport BaseSound : virtual public Listable
+    {
+    public:
+        BaseSound();
+
+        void XMLPortExtern(Element& xmlelement, XMLPort::Mode mode);
+
+        virtual void play()  { this->doPlay(); }
+        virtual bool stop()  { return this->doStop(); } // returns true if the sound source was destroyed
+        virtual void pause() { this->doPause(); }
+
+        bool isPlaying() const { return this->state_ == State::Playing; }
+        bool isPaused()  const { return this->state_ == State::Paused; }
+        bool isStopped() const { return this->state_ == State::Stopped; }
+
+        virtual void setSource(const std::string& source);
+        virtual const std::string& getSource() const
+            { return this->source_; }
+
+        void setVolume(float vol);
+        float getVolume() const
+            { return this->volume_; }
+        void updateVolume();
+
+        bool getLooping() const
+            { return this->bLooping_; }
+        void setLooping(bool val);
+
+        float getPitch() const
+            { return this->pitch_; }
+        void setPitch(float pitch);
+
+    protected:
+        enum class State
+        {
+            Stopped,
+            Playing,
+            Paused
+        };
+
+        virtual ~BaseSound();
+
+        void doPlay();
+        bool doStop(); // returns true if the sound source was destroyed
+        void doPause();
+
+        // network callbacks
+        inline void pitchChanged()
+            { this->setPitch(this->pitch_); }
+        inline void loopingChanged()
+            { this->setLooping(this->bLooping_); }
+        inline void volumeChanged()
+            { this->setVolume(this->volume_); }
+        inline void sourceChanged()
+            { this->setSource(this->source_); }
+        void stateChanged();
+
+        virtual void initialiseSource();
+        ALint getSourceState() const;
+
+        virtual float getRealVolume() = 0;
+
+        ALuint          audioSource_;
+        bool            bPooling_;
+        std::shared_ptr<SoundBuffer> soundBuffer_;
+        std::string     source_;
+        float           volume_;
+        bool            bLooping_;
+        State           state_;       // This Variable is actually of type State
+        float           pitch_;
+
+    private:
+        DataStreamPtr   dataStream_;
+    };
+}
+
+#endif /* _BaseSound_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,10 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  AmbientSound.cc
+  BaseSound.cc
+  SoundBuffer.cc
+  SoundManager.cc
+  SoundStreamer.cc
+  WorldAmbientSound.cc
+  WorldSound.cc
+)
+
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/SoundBuffer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/SoundBuffer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/SoundBuffer.cc	(revision 11817)
@@ -0,0 +1,187 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SoundBuffer.h"
+
+#include <alut.h>
+#include <vorbis/vorbisfile.h>
+
+#include "util/Exception.h"
+#include "util/StringUtils.h"
+#include "sound/SoundManager.h"
+
+namespace orxonox
+{
+    SoundBuffer::SoundBuffer(const std::string& filename, std::list<std::shared_ptr<SoundBuffer>>::iterator poolIterator)
+        : filename_(filename)
+        , audioBuffer_(AL_NONE)
+        , poolIterator_(poolIterator)
+    {
+        if (this->filename_.empty())
+            ThrowException(General, "SoundBuffer construction: fileInfo was nullptr");
+
+        // Get resource info
+        std::shared_ptr<ResourceInfo> fileInfo = Resource::getInfo(filename);
+        if (fileInfo == nullptr)
+        {
+            orxout(internal_error, context::sound) << "Sound file '" << filename << "' not found" << endl;
+            return;
+        }
+        // Open data stream
+        DataStreamPtr dataStream = Resource::open(fileInfo);
+
+        const std::string& extension = this->filename_.substr(this->filename_.find_last_of('.') + 1);
+        if (getLowercase(extension) == "ogg")
+        {
+            // Try ogg loader
+            this->loadOgg(fileInfo, dataStream);
+        }
+        else
+        {
+            // Try standard OpenAL loader
+            this->loadStandard(fileInfo, dataStream);
+        }
+    }
+
+    SoundBuffer::~SoundBuffer()
+    {
+        // Destroy buffer
+        alDeleteBuffers(1, &this->audioBuffer_);
+    }
+
+    unsigned int SoundBuffer::getSize() const
+    {
+        ALint size;
+        alGetBufferi(this->audioBuffer_, AL_SIZE, &size);
+        return alGetError() ? 0 : size;
+    }
+
+    void SoundBuffer::loadStandard(const std::shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream)
+    {
+        // Read everything into a temporary buffer
+        char* buffer = new char[fileInfo->size];
+        dataStream->read(buffer, fileInfo->size);
+        dataStream->seek(0);
+
+        this->audioBuffer_ = alutCreateBufferFromFileImage(buffer, fileInfo->size);
+        delete[] buffer;
+
+        if (!alIsBuffer(this->audioBuffer_))
+            ThrowException(General, "Sound Error: Standard file loader failed: " << alutGetErrorString(alutGetError()));
+    }
+
+    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource)
+    {
+        return static_cast<Ogre::DataStream*>(datasource)->read(ptr, size * nmemb);
+    }
+
+    int seekVorbis(void* datasource, ogg_int64_t offset, int whence)
+    {
+        Ogre::DataStream* stream = static_cast<Ogre::DataStream*>(datasource);
+        switch (whence)
+        {
+        case SEEK_SET:
+            stream->seek((size_t)offset);
+            break;
+        case SEEK_CUR:
+            stream->skip((size_t)offset);
+            break;
+        case SEEK_END:
+            stream->seek(stream->size() + (size_t)offset);
+            break;
+        default:
+            return -1;
+        }
+        return 0;
+    }
+
+    long tellVorbis(void* datasource)
+    {
+        return static_cast<long>(static_cast<Ogre::DataStream*>(datasource)->tell());
+    }
+
+    void SoundBuffer::loadOgg(const std::shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream)
+    {
+        char inbuffer[256*1024];
+        std::vector<char> outbuffer;
+        outbuffer.reserve(80*1024*1024);
+
+        // Open file with custom streaming
+        ov_callbacks vorbisCallbacks;
+        vorbisCallbacks.read_func  = &readVorbis;
+        vorbisCallbacks.seek_func  = &seekVorbis;
+        vorbisCallbacks.tell_func  = &tellVorbis;
+        vorbisCallbacks.close_func = nullptr;
+
+        OggVorbis_File vf;
+        int ret = ov_open_callbacks(dataStream.get(), &vf, nullptr, 0, vorbisCallbacks);
+        if (ret < 0)
+        {
+            orxout(internal_error, context::sound) << "libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << endl;
+            ov_clear(&vf);
+            ThrowException(General, "Sound Error: Ogg file loader failed when opening the bitstream");
+        }
+
+        int current_section;
+        int eof = false;
+        while (!eof)
+        {
+            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
+            if (ret == 0)
+            {
+                eof = true;
+            }
+            else if (ret < 0)
+            {
+                orxout(internal_error, context::sound) << "libvorbisfile: error reading the file" << endl;
+                ov_clear(&vf);
+                ThrowException(General, "Sound Error: Ogg file loader failed when decoding the file");
+            }
+            else
+            {
+                outbuffer.insert(outbuffer.end(), inbuffer, inbuffer + ret);
+            }
+        }
+
+        vorbis_info* vorbisInfo;
+        vorbisInfo = ov_info(&vf, -1);
+        ALenum format;
+        if (vorbisInfo->channels == 1)
+            format = AL_FORMAT_MONO16;
+        else
+            format = AL_FORMAT_STEREO16;
+
+        alGenBuffers(1, &this->audioBuffer_);
+        alBufferData(this->audioBuffer_, format, &outbuffer[0], outbuffer.size(), vorbisInfo->rate);
+        ov_clear(&vf);
+
+        if (!alIsBuffer(this->audioBuffer_))
+            ThrowException(General, "Sound: Ogg file loader failed when creating the buffer.");
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/SoundBuffer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/SoundBuffer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/SoundBuffer.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SoundBuffer_H__
+#define _SoundBuffer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include <memory>
+#include "core/Resource.h"
+
+namespace orxonox
+{
+    /*
+    @brief
+        The SoundBuffer class is to be used for sounds with position and orientation.
+    */
+    class _OrxonoxExport SoundBuffer
+    {
+        friend class SoundManager;
+
+    public:
+        ~SoundBuffer();
+        inline ALuint getBuffer()
+            { return this->audioBuffer_; }
+
+        unsigned int getSize() const;
+
+        const std::string& getFilename() const
+            { return this->filename_; }
+
+    private:
+        SoundBuffer(const std::string& filename, std::list<std::shared_ptr<SoundBuffer>>::iterator poolIterator);
+        void loadStandard(const std::shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream);
+        void loadOgg(const std::shared_ptr<ResourceInfo>& fileInfo, DataStreamPtr dataStream);
+
+        std::string filename_;
+        ALuint audioBuffer_;
+        std::list<std::shared_ptr<SoundBuffer>>::iterator poolIterator_;
+    };
+}
+
+#endif /* _SoundBuffer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/SoundManager.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/SoundManager.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/SoundManager.cc	(revision 11817)
@@ -0,0 +1,646 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
+ *       Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SoundManager.h"
+
+#include <utility>
+#include <alut.h>
+#include <loki/ScopeGuard.h>
+
+#include "util/Exception.h"
+#include "util/Math.h"
+#include "util/Clock.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/Resource.h"
+#include "SoundBuffer.h"
+#include "BaseSound.h"
+#include "AmbientSound.h"
+#include "WorldSound.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(SoundManager, ScopeID::GRAPHICS, true);
+
+    std::string SoundManager::getALErrorString(ALenum code)
+    {
+        switch (code)
+        {
+        case AL_NO_ERROR:          return "No error";
+        case AL_INVALID_NAME:      return "Invalid AL parameter name";
+        case AL_INVALID_ENUM:      return "Invalid AL enum";
+        case AL_INVALID_VALUE:     return "Invalid AL value";
+        case AL_INVALID_OPERATION: return "Invalid AL operation";
+        case AL_OUT_OF_MEMORY:     return "AL reports out of memory";
+        default:                   return "Unknown AL error";
+        }
+    }
+
+    RegisterAbstractClass(SoundManager).inheritsFrom<Configurable>().inheritsFrom<UpdateListener>();
+
+    SoundManager::SoundManager()
+        : effectsPoolSize_(0)
+    {
+        RegisterObject(SoundManager);
+
+        orxout(user_status) << "Loading sound" << endl;
+
+        this->bDestructorCalled_ = false;
+         
+        // See whether we even want to load
+        bool bDisableSound_ = false;
+        SetConfigValue(bDisableSound_, false);
+        if (bDisableSound_)
+            ThrowException(InitialisationAborted, "Sound: Not loading at all");
+#if !defined(ORXONOX_PLATFORM_APPLE)
+        if (!alutInitWithoutContext(nullptr, nullptr))
+            ThrowException(InitialisationFailed, "Sound Error: ALUT initialisation failed: " << alutGetErrorString(alutGetError()));
+        Loki::ScopeGuard alutExitGuard = Loki::MakeGuard(&alutExit);
+#endif
+
+/*
+        // Get list of available sound devices and display them
+        const char* devices = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
+        char* device = new char[strlen(devices)+1];
+        strcpy(device, devices);
+        std::string renderDevice;
+        SetConfigValue(renderDevice, std::string(device)).description("Sound device used for rendering");
+        orxout(verbose, context::sound) << "Sound: Available devices: ";
+        while (true)
+        {
+            this->deviceNames_.push_back(devices);
+            orxout(verbose, context::sound) << '"' << devices << "\", ";
+            devices += strlen(devices) + 1;
+            if (*devices == '\0')
+                break;
+        }
+        orxout(verbose, context::sound) << endl;
+
+        // Open the selected device
+        orxout(internal_info, context::sound) << "Sound: Opening device \"" << renderDevice << '\' << endl;
+        this->device_ = alcOpenDevice(renderDevice.c_str());
+*/
+        this->device_ = alcOpenDevice(nullptr);
+        if (this->device_ == nullptr)
+            ThrowException(InitialisationFailed, "Sound Error: Could not open sound device.");
+        Loki::ScopeGuard closeDeviceGuard = Loki::MakeGuard(&alcCloseDevice, this->device_);
+
+        // Create sound context and make it the currently used one
+        this->context_ = alcCreateContext(this->device_, nullptr);
+        if (this->context_ == nullptr)
+            ThrowException(InitialisationFailed, "Sound Error: Could not create ALC context");
+        Loki::ScopeGuard desroyContextGuard = Loki::MakeGuard(&alcDestroyContext, this->context_);
+        if (!alcMakeContextCurrent(this->context_))
+            ThrowException(InitialisationFailed, "Sound Error: Could not use ALC context");
+
+        GameMode::setPlaysSound(true);
+        Loki::ScopeGuard resetPlaysSoundGuard = Loki::MakeGuard(&GameMode::setPlaysSound, false);
+
+        // Get some information about the sound
+        if (const char* version = alGetString(AL_VERSION))
+            orxout(internal_info, context::sound) << "Sound: --- OpenAL Version: " << version << endl;
+        if (const char* vendor = alGetString(AL_VENDOR))
+            orxout(internal_info, context::sound) << "Sound: --- OpenAL Vendor : " << vendor << endl;
+        if (const char* types = alutGetMIMETypes(ALUT_LOADER_BUFFER))
+            orxout(internal_info, context::sound) << "Sound: --- Supported MIME Types: " << types << endl;
+        else
+            orxout(internal_warning, context::sound) << "MIME Type retrieval failed: " << alutGetErrorString(alutGetError()) << endl;
+
+        this->mute_[SoundType::All]     = 1.0f;
+        this->mute_[SoundType::Music]   = 1.0f;
+        this->mute_[SoundType::Effects] = 1.0f;
+
+        this->setConfigValues();
+
+        // Try to get exactly one source
+        ALuint source;
+        alGenSources(1, &source);
+        if (!alGetError() && alIsSource(source))
+            this->availableSoundSources_.push_back(source);
+        else
+            ThrowException(InitialisationFailed, "Sound Error: Could not create even a single source");
+        // Create a few initial sources
+        this->createSoundSources(this->minSources_ - 1);
+
+        // Disarm guards
+#if !defined(ORXONOX_PLATFORM_APPLE)
+        alutExitGuard.Dismiss();
+#endif
+        closeDeviceGuard.Dismiss();
+        desroyContextGuard.Dismiss();
+        resetPlaysSoundGuard.Dismiss();
+
+        orxout(internal_status, context::sound) << "Sound: Initialisation complete" << endl;
+    }
+
+    SoundManager::~SoundManager()
+    {
+        // Erase fade lists because of the strong pointers
+        this->bDestructorCalled_ = true;
+        this->fadeInList_.clear();
+        this->fadeOutList_.clear();
+
+        // If there are still used buffers around, well, that's just very bad...
+        if (this->soundBuffers_.size() != this->effectsPool_.size())
+            orxout(internal_error, context::sound) << "Some sound buffers are still in use but OpenAL is about to shut down. Fix this!" << endl;
+        // Empty buffer pool and buffer list
+        this->effectsPool_.clear();
+        this->soundBuffers_.clear();
+
+        // There should not be any sources in use anymore
+        if (!this->usedSoundSources_.empty())
+            orxout(internal_error, context::sound) << "Some sound sources are still in use but OpenAL is about to shut down. Fix this!" << endl;
+        while (!this->availableSoundSources_.empty())
+        {
+            alDeleteSources(1, &this->availableSoundSources_.back());
+            this->availableSoundSources_.pop_back();
+        }
+
+        GameMode::setPlaysSound(false);
+
+        // Relieve context to destroy it
+        if (!alcMakeContextCurrent(nullptr))
+            orxout(internal_error, context::sound) << "Could not unset ALC context" << endl;
+        alcDestroyContext(this->context_);
+        if (ALCenum error = alcGetError(this->device_))
+        {
+            if (error == AL_INVALID_OPERATION)
+                orxout(internal_error, context::sound) << "Could not destroy ALC context because it is the current one" << endl;
+            else
+                orxout(internal_error, context::sound) << "Could not destroy ALC context because it is invalid" << endl;
+        }
+#ifdef AL_VERSION_1_1
+        if (!alcCloseDevice(this->device_))
+            orxout(internal_error, context::sound) << "Could not destroy ALC device. This might be because there are still buffers in use!" << endl;
+#else
+        alcCloseDevice(this->device_);
+#endif
+#if !defined(ORXONOX_PLATFORM_APPLE)
+        if (!alutExit())
+            orxout(internal_error, context::sound) << "Closing ALUT failed: " << alutGetErrorString(alutGetError()) << endl;
+#endif
+    }
+
+    void SoundManager::setConfigValues()
+    {
+        SetConfigValue(crossFadeStep_, 0.2f)
+            .description("Determines how fast sounds should fade, per second.")
+            .callback(this, &SoundManager::checkFadeStepValidity);
+
+        SetConfigValueAlias(volume_[SoundType::All], "soundVolume_", 1.0f)
+            .description("Defines the overall volume.")
+            .callback(this, &SoundManager::checkSoundVolumeValidity);
+        SetConfigValueAlias(volume_[SoundType::Music], "ambientVolume_", 0.7f)
+            .description("Defines the ambient volume.")
+            .callback(this, &SoundManager::checkAmbientVolumeValidity);
+        SetConfigValueAlias(volume_[SoundType::Effects], "effectsVolume_", 1.0f)
+            .description("Defines the effects volume.")
+            .callback(this, &SoundManager::checkEffectsVolumeValidity);
+
+        SetConfigValue(minSources_, 16)
+            .description("Minimum number of sources being generated (if possible)");
+        SetConfigValue(maxSources_, 1024)
+            .description("Maximum number of sources to be made available");
+    }
+
+    void SoundManager::preUpdate(const Clock& time)
+    {
+        this->processCrossFading(time.getDeltaTime());
+
+        // Check whether a sound object has stopped playing
+        for (unsigned int i = 0; i < this->usedSoundSources_.size(); ++i)
+        {
+            ALint state;
+            alGetSourcei(this->usedSoundSources_[i].first, AL_SOURCE_STATE, &state);
+            if (state == AL_STOPPED)
+            {
+                if (this->usedSoundSources_[i].second->stop()) // if stop() returns true, the sound source was removed, thus decrement the array index
+                    --i;
+            }
+        }
+    }
+
+    void SoundManager::checkFadeStepValidity()
+    {
+        if (crossFadeStep_ <= 0.0 || crossFadeStep_ >= 1.0 )
+        {
+            orxout(internal_warning, context::sound) << "Fade step out of range, ignoring change." << endl;
+            ResetConfigValue(crossFadeStep_);
+        }
+    }
+
+    void SoundManager::checkVolumeValidity(SoundType::Value type)
+    {
+        float clampedVolume = clamp(this->volume_[type], 0.0f, 1.0f);
+        if (clampedVolume != this->volume_[type])
+            orxout(internal_warning, context::sound) << "Volume setting (" << type << ") out of range, clamping." << endl;
+        this->updateVolume(type);
+    }
+
+    void SoundManager::setVolume(float vol, SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return;
+        this->volume_[type] = vol;
+        this->checkVolumeValidity(type);
+    }
+
+    float SoundManager::getVolume(SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return 0.0f;
+        return this->volume_[type];
+    }
+
+    float SoundManager::getRealVolume(SoundType::Value type)
+    {
+        if (type != SoundType::Music && type != SoundType::Effects)
+            return 0.0f;
+        return this->volume_[SoundType::All] * this->mute_[SoundType::All] * this->volume_[type] * this->mute_[type];
+    }
+
+    void SoundManager::updateVolume(SoundType::Value type)
+    {
+        switch(type)
+        {
+        case SoundType::All:
+            for (BaseSound* sound : ObjectList<BaseSound>())
+                sound->updateVolume();
+            break;
+        case SoundType::Music:
+            for (AmbientSound* sound : ObjectList<AmbientSound>())
+                sound->updateVolume();
+            break;
+        case SoundType::Effects:
+            for (WorldSound* sound : ObjectList<WorldSound>())
+                sound->updateVolume();
+            break;
+        default:
+            assert(false);
+        }
+    }
+
+    void SoundManager::toggleMute(SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return;
+        this->mute_[type] = (this->mute_[type] == 0) ? 1.0f : 0.0f;
+        this->updateVolume(type);
+    }
+
+    bool SoundManager::getMute(SoundType::Value type)
+    {
+        if (type < 0 || type > SoundType::Effects)
+            return true;
+        return (this->mute_[type] == 0);
+    }
+
+    void SoundManager::setListenerPosition(const Vector3& position)
+    {
+        alListener3f(AL_POSITION, position.x, position.y, position.z);
+        ALenum error = alGetError();
+        if (error == AL_INVALID_VALUE)
+            // @TODO: Follow this constantly appearing, nerve-racking warning
+            orxout(internal_error, context::sound) << "OpenAL: Invalid listener position" << endl;
+    }
+
+    void SoundManager::setListenerOrientation(const Quaternion& orientation)
+    {
+        // update listener orientation
+        const Vector3& direction = -orientation.zAxis();
+        const Vector3& up = orientation.yAxis();
+
+        ALfloat orient[6] = { direction.x, direction.y, direction.z, up.x, up.y, up.z };
+
+        alListenerfv(AL_ORIENTATION, orient);
+        ALenum error = alGetError();
+        if (error == AL_INVALID_VALUE)
+            orxout(internal_error, context::sound) << "OpenAL: Invalid listener orientation" << endl;
+    }
+
+    void SoundManager::registerAmbientSound(AmbientSound* newAmbient)
+    {
+        if (newAmbient != nullptr && !this->bDestructorCalled_)
+        {
+            for (AmbientList::const_iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == newAmbient)
+                {
+                    orxout(internal_warning, context::sound) << "Will not play an AmbientSound twice." << endl;
+                    return;
+                }
+            }
+
+            if (!this->ambientSounds_.empty())
+            {
+                this->fadeOut(ambientSounds_.front().first);
+            }
+            this->ambientSounds_.push_front(std::make_pair(newAmbient, false));
+            newAmbient->doPlay();
+            this->fadeIn(newAmbient);
+        }
+    }
+
+    void SoundManager::unregisterAmbientSound(AmbientSound* oldAmbient)
+    {
+        if (oldAmbient == nullptr || ambientSounds_.empty() || this->bDestructorCalled_)
+            return;
+
+        if (this->ambientSounds_.front().first == oldAmbient)
+        {
+            this->fadeOut(oldAmbient);
+            this->ambientSounds_.pop_front();
+            if (!this->ambientSounds_.empty())
+            {
+                if (!this->ambientSounds_.front().second) // Not paused before
+                {
+                    this->ambientSounds_.front().first->doPlay();
+                }
+                this->fadeIn(this->ambientSounds_.front().first);
+            }
+        }
+        else
+        {
+            for (AmbientList::iterator it = this->ambientSounds_.begin(); it != this->ambientSounds_.end(); ++it)
+            {
+                if (it->first == oldAmbient)
+                {
+                    this->fadeOut(oldAmbient);
+                    this->ambientSounds_.erase(it);
+                    break;
+                }
+            }
+        }
+    }
+
+    void SoundManager::pauseAmbientSound(AmbientSound* ambient)
+    {
+        if (ambient != nullptr)
+        {
+            for (std::pair<AmbientSound*, bool>& pair : this->ambientSounds_)
+            {
+                if (pair.first == ambient)
+                {
+                    pair.second = true;
+                    this->fadeOut(pair.first);
+                    return;
+                }
+            }
+        }
+    }
+
+    void SoundManager::fadeIn(AmbientSound* sound)
+    {
+        // If we're already fading out --> remove that
+        for (std::list<StrongPtr<AmbientSound>>::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); it++)
+        {
+            if (*it == sound)
+            {
+                this->fadeOutList_.erase(it);
+                break;
+            }
+        }
+        // No duplicate entries
+        if (std::find(this->fadeInList_.begin(), this->fadeInList_.end(), sound) == this->fadeInList_.end())
+            this->fadeInList_.push_back(sound);
+    }
+
+    void SoundManager::fadeOut(AmbientSound* sound)
+    {
+        // If we're already fading in --> remove that
+        for (std::list<StrongPtr<AmbientSound>>::iterator it = this->fadeInList_.begin(); it != this->fadeInList_.end(); it++)
+        {
+            if (*it == sound)
+            {
+                this->fadeInList_.erase(it);
+                break;
+            }
+        }
+        // No duplicate entries
+        if (std::find(this->fadeOutList_.begin(), this->fadeOutList_.end(), sound) == this->fadeOutList_.end())
+            this->fadeOutList_.push_back(sound);
+    }
+
+    void SoundManager::processCrossFading(float dt)
+    {
+
+        // Hacky solution to the fade delay while loading a level.
+        if(dt > 0.2)
+        {
+            return;
+        }
+
+        // FADE IN
+        for (std::list<StrongPtr<AmbientSound>>::iterator it= this->fadeInList_.begin(); it != this->fadeInList_.end(); )
+        {
+            if ((*it)->getVolume() + this->crossFadeStep_*dt > 1.0f)
+            {
+                (*it)->setVolume(1.0f);
+                this->fadeInList_.erase(it++);
+            }
+            else
+            {
+                (*it)->setVolume((*it)->getVolume() + this->crossFadeStep_*dt);
+                ++it;
+            }
+        }
+
+        // FADE OUT
+        for (std::list<StrongPtr<AmbientSound>>::iterator it = this->fadeOutList_.begin(); it != this->fadeOutList_.end(); )
+        {
+            if ((*it)->getVolume() - this->crossFadeStep_*dt < 0.0f)
+            {
+                (*it)->setVolume(0.0f);
+
+                // If sound is in the ambient list --> pause
+                for (AmbientList::const_iterator it2 = this->ambientSounds_.begin(); it2 != this->ambientSounds_.end(); ++it2)
+                {
+                    if (it2->first == *it)
+                    {
+                        (*it)->doPause();
+                        break;
+                    }
+                }
+                // If not pause (by loop above for instance) --> stop
+                if (!(*it)->isPaused())
+                    (*it)->doStop();
+
+                this->fadeOutList_.erase(it++);
+            }
+            else
+            {
+                (*it)->setVolume((*it)->getVolume() - this->crossFadeStep_*dt);
+                ++it;
+            }
+        }
+    }
+
+    std::shared_ptr<SoundBuffer> SoundManager::getSoundBuffer(const std::string& filename)
+    {
+        std::shared_ptr<SoundBuffer> buffer;
+        // Check active or pooled buffers
+        SoundBufferMap::const_iterator it = this->soundBuffers_.find(filename);
+        if (it != this->soundBuffers_.end())
+        {
+            buffer = it->second;
+
+            // Remove from effects pool if not active used before
+            if (buffer->poolIterator_ != this->effectsPool_.end())
+            {
+                this->effectsPoolSize_ -= buffer->getSize();
+                this->effectsPool_.erase(buffer->poolIterator_);
+                buffer->poolIterator_ = this->effectsPool_.end();
+            }
+        }
+        else
+        {
+            try
+            {
+                buffer.reset(new SoundBuffer(filename, this->effectsPool_.end()));
+            }
+            catch (const std::exception& ex)
+            {
+                orxout(internal_error, context::sound) << ex.what() << endl;
+                return buffer;
+            }
+            this->soundBuffers_[filename] = buffer;
+        }
+        return buffer;
+    }
+
+    void SoundManager::releaseSoundBuffer(const std::shared_ptr<SoundBuffer>& buffer, bool bPoolBuffer)
+    {
+        // Check if others are still using the buffer
+        if (buffer.use_count() != 2)
+            return;
+        SoundBufferMap::iterator it = this->soundBuffers_.find(buffer->getFilename());
+        if (it != this->soundBuffers_.end())
+        {
+            if (bPoolBuffer)
+            {
+                // Pool already too large?
+                while (this->effectsPoolSize_ + it->second->getSize() > this->maxEffectsPoolSize_s && !this->effectsPool_.empty())
+                {
+                    std::shared_ptr<SoundBuffer> bufferDel = this->effectsPool_.back();
+                    this->effectsPoolSize_ -= bufferDel->getSize();
+                    bufferDel->poolIterator_ = this->effectsPool_.end();
+                    this->effectsPool_.pop_back();
+                    // Remove from buffer map too
+                    SoundBufferMap::iterator itDel = this->soundBuffers_.find(bufferDel->getFilename());
+                    if (itDel != this->soundBuffers_.end())
+                        this->soundBuffers_.erase(itDel);
+                }
+                // Put buffer into the pool
+                this->effectsPoolSize_ += it->second->getSize();
+                this->effectsPool_.push_front(it->second);
+                it->second->poolIterator_ = this->effectsPool_.begin();
+            }
+            else
+                this->soundBuffers_.erase(it);
+        }
+    }
+
+    ALuint SoundManager::getSoundSource(BaseSound* object)
+    {
+        if (!this->availableSoundSources_.empty())
+        {
+            ALuint source = this->availableSoundSources_.back();
+            this->availableSoundSources_.pop_back();
+            this->usedSoundSources_.emplace_back(source, object);
+            return source;
+        }
+        else
+        {
+            if (this->usedSoundSources_.size() < this->maxSources_)
+            {
+                ALuint source;
+                alGenSources(1, &source);
+                // Try to create new sources (50% more, but at least one)
+                if (alIsSource(source) && !alGetError())
+                {
+                    this->usedSoundSources_.emplace_back(source, object);
+                    return source;
+                }
+            }
+            // Return no source ID
+            ALuint source = 123456789;
+            while (alIsSource(++source));
+            return source;
+        }
+    }
+
+    void SoundManager::releaseSoundSource(ALuint source)
+    {
+#ifndef NDEBUG
+        for (std::vector<ALuint>::const_iterator it = this->availableSoundSources_.begin(); it != this->availableSoundSources_.end(); ++it)
+            assert((*it) != source);
+#endif
+        this->availableSoundSources_.push_back(source);
+        for (std::vector<std::pair<ALuint, BaseSound*>>::iterator it = this->usedSoundSources_.begin();
+            it != this->usedSoundSources_.end(); ++it)
+        {
+            if (it->first == source)
+            {
+                this->usedSoundSources_.erase(it);
+                break;
+            }
+        }
+        int used = std::max((unsigned int)(this->usedSoundSources_.size()), this->minSources_);
+        // Subtract those we added in the statement above trough std::max
+        int available = (int)this->availableSoundSources_.size() - (used - (int)this->usedSoundSources_.size());
+        // Delete sources again to free resources if appropriate (more than 50% more available than used)
+        int toDelete = available - used / 2;
+        while (toDelete-- > 0)
+        {
+            alDeleteSources(1, &this->availableSoundSources_.back());
+            if (alGetError())
+                orxout(internal_error, context::sound) << "Failed to delete a source --> lost forever" << endl;
+            this->availableSoundSources_.pop_back();
+        }
+    }
+
+    unsigned int SoundManager::createSoundSources(unsigned int n)
+    {
+        unsigned int count = this->availableSoundSources_.size() + this->usedSoundSources_.size();
+        while (count < this->maxSources_ && count <= n)
+        {
+            ALuint source;
+            alGenSources(1, &source);
+            if (alIsSource(source) && !alGetError())
+                this->availableSoundSources_.push_back(source);
+            else
+                break;
+            ++count;
+        }
+        return count - this->availableSoundSources_.size() - this->usedSoundSources_.size();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/SoundManager.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/SoundManager.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/SoundManager.h	(revision 11817)
@@ -0,0 +1,158 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *       Erwin 'vaiursch' Herrsche
+ *       Kevin Young
+ *       Reto Grieder
+ *   Co-authors:
+ *      ...
+ */
+
+#ifndef _SoundManager_H__
+#define _SoundManager_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include <map>
+#include <string>
+#include <memory>
+
+#include "util/Singleton.h"
+#include "core/config/Configurable.h"
+#include "core/object/StrongPtr.h"
+#include "core/UpdateListener.h"
+
+// tolua_begin
+namespace orxonox
+{
+    //! Enum for the sound type.
+    namespace SoundType
+    {
+        enum Value
+        {
+            All     = 0,
+            Music   = 1,
+            Effects = 2
+        };
+    }
+
+    //! The SoundManager class manages the OpenAL device, context and listener position.
+    class _OrxonoxExport SoundManager
+    // tolua_end
+        : public Singleton<SoundManager>, public Configurable, public UpdateListener
+    { // tolua_export
+        friend class Singleton<SoundManager>;
+
+    public:
+        SoundManager();
+        ~SoundManager();
+
+        virtual void preUpdate(const Clock& time) override;
+        virtual void postUpdate(const Clock& time) override { /*no action*/ }
+        void setConfigValues();
+
+        // tolua_begin
+        static SoundManager& getInstance() { return Singleton<SoundManager>::getInstance(); }
+        static bool exists() { return Singleton<SoundManager>::exists(); }
+
+        std::string getDeviceName(unsigned int index) const
+            { return index < this->deviceNames_.size() ? this->deviceNames_[index] : std::string(); }
+        // tolua_end
+
+        void setListenerPosition(const Vector3& position);
+        void setListenerOrientation(const Quaternion& orientation);
+
+        void registerAmbientSound(AmbientSound* newAmbient);
+        void unregisterAmbientSound(AmbientSound* oldAmbient);
+        void pauseAmbientSound(AmbientSound* ambient);
+
+        // tolua_begin
+        void setVolume(float vol, SoundType::Value type);
+        float getVolume(SoundType::Value type);
+        float getRealVolume(SoundType::Value type);
+
+        void toggleMute(SoundType::Value type);
+        bool getMute(SoundType::Value type);
+        // tolua_end
+
+        std::shared_ptr<SoundBuffer> getSoundBuffer(const std::string& filename);
+        void releaseSoundBuffer(const std::shared_ptr<SoundBuffer>& buffer, bool bPoolBuffer);
+
+        ALuint getSoundSource(BaseSound* object);
+        void releaseSoundSource(ALuint source);
+
+        static std::string getALErrorString(ALenum error);
+
+    private:
+        void processCrossFading(float dt);
+        void fadeIn(AmbientSound* sound);
+        void fadeOut(AmbientSound* sound);
+
+        void checkFadeStepValidity();
+
+        void checkVolumeValidity(SoundType::Value type);
+        void checkSoundVolumeValidity()   { this->checkVolumeValidity(SoundType::All); }
+        void checkAmbientVolumeValidity() { this->checkVolumeValidity(SoundType::Music); }
+        void checkEffectsVolumeValidity() { this->checkVolumeValidity(SoundType::Effects); }
+        void updateVolume(SoundType::Value type);
+
+        unsigned int createSoundSources(unsigned int n);
+
+        // OpenAL device/context related
+        std::vector<std::string> deviceNames_;
+        ALCdevice* device_;
+        ALCcontext* context_;
+
+        // Ambient sound related
+        typedef std::list<std::pair<AmbientSound*, bool>> AmbientList;
+        AmbientList                        ambientSounds_;
+        //! Absolute change per second (0.1 means 10% of the nominal volume) for cross fading
+        float                              crossFadeStep_;
+        std::list<StrongPtr<AmbientSound>> fadeInList_;
+        std::list<StrongPtr<AmbientSound>> fadeOutList_;
+
+        // Volume related
+        float volume_[3];
+        float mute_[3];
+
+        // Sound buffer related
+        static const unsigned int maxEffectsPoolSize_s = 40 * 1024 * 1024;
+        unsigned int effectsPoolSize_;
+        typedef std::list<std::shared_ptr<SoundBuffer>> EffectsPoolList;
+        EffectsPoolList effectsPool_;
+        typedef std::map<std::string, std::shared_ptr<SoundBuffer>> SoundBufferMap;
+        SoundBufferMap soundBuffers_;
+
+        // Sound source related
+        unsigned int minSources_;
+        unsigned int maxSources_;
+        std::vector<ALuint> availableSoundSources_;
+        std::vector<std::pair<ALuint, BaseSound*>> usedSoundSources_;
+
+        bool bDestructorCalled_; ///< Becomes true if the destructor is called - used to prevent ambient sounds from registering after the lists were cleared
+
+        static SoundManager* singletonPtr_s;
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _SoundManager_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/SoundStreamer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/SoundStreamer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/SoundStreamer.cc	(revision 11817)
@@ -0,0 +1,128 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *
+ */
+#include "SoundStreamer.h"
+
+#include <al.h>
+#include <vorbis/vorbisfile.h>
+#include "SoundManager.h"
+
+namespace orxonox
+{
+    // vorbis callbacks
+    size_t readVorbis(void* ptr, size_t size, size_t nmemb, void* datasource);
+    int seekVorbis(void* datasource, ogg_int64_t offset, int whence);
+    long tellVorbis(void* datasource);
+
+    void orxonox::SoundStreamer::operator()(ALuint audioSource, DataStreamPtr dataStream)
+    {
+        // Open file with custom streaming
+        ov_callbacks vorbisCallbacks;
+        vorbisCallbacks.read_func  = &readVorbis;
+        vorbisCallbacks.seek_func  = &seekVorbis;
+        vorbisCallbacks.tell_func  = &tellVorbis;
+        vorbisCallbacks.close_func = nullptr;
+
+        OggVorbis_File vf;
+        int ret = ov_open_callbacks(dataStream.get(), &vf, nullptr, 0, vorbisCallbacks);
+        if (ret < 0)
+        {
+            orxout(internal_error, context::sound) << "libvorbisfile: File does not seem to be an Ogg Vorbis bitstream" << endl;
+            ov_clear(&vf);
+            return;
+        }
+        vorbis_info* vorbisInfo;
+        vorbisInfo = ov_info(&vf, -1);
+        ALenum format;
+        if (vorbisInfo->channels == 1)
+            format = AL_FORMAT_MONO16;
+        else
+            format = AL_FORMAT_STEREO16;
+
+        char inbuffer[256*1024];
+        ALuint initbuffers[4];
+        alGenBuffers(4, initbuffers);
+        int current_section;
+
+        for(ALuint& initbuffer : initbuffers)
+        {
+            long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
+            if (ret == 0)
+            {
+                return;
+            }
+            else if (ret < 0)
+            {
+                orxout(internal_error, context::sound) << "libvorbisfile: error reading the file" << endl;
+                ov_clear(&vf);
+                return;
+            }
+
+            alBufferData(initbuffer, format, &inbuffer, ret, vorbisInfo->rate);
+        }
+        alSourceQueueBuffers(audioSource, 4, initbuffers);
+
+        while(true) // Stream forever, control through thread control
+        {
+            int processed;
+            alGetSourcei(audioSource, AL_BUFFERS_PROCESSED, &processed);
+            if (ALint error = alGetError())
+            orxout(internal_warning, context::sound) << "Couldn't get number of processed buffers: "
+                                                     << SoundManager::getALErrorString(error) << endl;
+
+            if(processed > 0)
+            {
+                ALuint* buffers = new ALuint[processed];
+                alSourceUnqueueBuffers(audioSource, processed, buffers);
+                if (ALint error = alGetError())
+                    orxout(internal_warning, context::sound) << "Couldn't unqueue buffers: "
+                                                             << SoundManager::getALErrorString(error) << endl;
+
+                for(int i = 0; i < processed; i++)
+                {
+                    long ret = ov_read(&vf, inbuffer, sizeof(inbuffer), 0, 2, 1, &current_section);
+                    if (ret == 0)
+                    {
+                        return;
+                    }
+                    else if (ret < 0)
+                    {
+                        orxout(internal_error, context::sound) << "libvorbisfile: error reading the file" << endl;
+                        ov_clear(&vf);
+                        return;
+                    }
+
+                    alBufferData(buffers[i], format, &inbuffer, ret, vorbisInfo->rate);
+                }
+
+                alSourceQueueBuffers(audioSource, processed, buffers);
+                if (ALint error = alGetError())
+                    orxout(internal_warning, context::sound) << "Couldn't queue buffers: "
+                                                             << SoundManager::getALErrorString(error) << endl;
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/SoundStreamer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/SoundStreamer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/SoundStreamer.h	(revision 11817)
@@ -0,0 +1,46 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *   Co-authors:
+ *
+ */
+
+#ifndef _SoundStreamer_H__
+#define _SoundStreamer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <OgreDataStream.h>
+#include "core/CorePrereqs.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport SoundStreamer // class for stream threads
+    {
+    public:
+        void operator()(ALuint audioSource, DataStreamPtr dataStream);
+    };
+}
+
+#endif /* _SoundStreamer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/WorldAmbientSound.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/WorldAmbientSound.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/WorldAmbientSound.cc	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WorldAmbientSound.h"
+
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+#include "AmbientSound.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include <exception>
+
+
+namespace orxonox
+{
+    SetConsoleCommand("WorldAmbientSound", "nextsong",      &WorldAmbientSound::nextSong);
+
+    RegisterClass(WorldAmbientSound);
+
+    WorldAmbientSound::WorldAmbientSound(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        RegisterObject(WorldAmbientSound);
+
+        this->ambientSound_ = new AmbientSound();
+        this->registerVariables();
+        soundList_.emplace_back("Earth.ogg");
+        soundList_.emplace_back("Jupiter.ogg");
+        soundList_.emplace_back("Mars.ogg");
+        soundList_.emplace_back("allgorythm-lift_up.ogg");
+        soundList_.emplace_back("allgorythm-resonance_blaster.ogg");
+        soundList_.emplace_back("AlphaCentauri.ogg");
+        soundList_.emplace_back("Asteroid_rocks.ogg");
+        soundList_.emplace_back("Ganymede.ogg");
+        soundList_.emplace_back("luke_grey_-_hypermode.ogg");
+        soundList_.emplace_back("racetheme.ogg");
+
+
+    }
+    WorldAmbientSound::~WorldAmbientSound()
+    {
+        if (this->isInitialized())
+        {
+            this->ambientSound_->destroy();
+            WorldAmbientSound::soundList_.clear();
+        }
+    }
+
+    void WorldAmbientSound::registerVariables()
+    {
+        registerVariable(this->ambientSound_->ambientSource_, ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this->ambientSound_, &AmbientSound::ambientSourceChanged));
+        registerVariable(this->ambientSound_->bLooping_,      ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this->ambientSound_, &AmbientSound::loopingChanged));
+        registerVariable(this->ambientSound_->pitch_,         ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this->ambientSound_, &AmbientSound::pitchChanged));
+        registerVariable(this->ambientSound_->bPlayOnLoad_,   ObjectDirection::ToClient, new NetworkCallback<AmbientSound>(this->ambientSound_, &AmbientSound::playOnLoadChanged));
+    }
+
+    void WorldAmbientSound::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WorldAmbientSound, XMLPort, xmlelement, mode);
+
+        XMLPortParamExtern(WorldAmbientSound, BaseSound, static_cast<BaseSound*>(this->ambientSound_), "looping", setLooping, getLooping, xmlelement, mode);
+        XMLPortParamExtern(WorldAmbientSound, BaseSound, static_cast<BaseSound*>(this->ambientSound_), "pitch",   setPitch,   getPitch,   xmlelement, mode);
+
+        XMLPortParamExtern(WorldAmbientSound, AmbientSound, this->ambientSound_, "source",     setAmbientSource, getAmbientSource, xmlelement, mode);
+        XMLPortParamExtern(WorldAmbientSound, AmbientSound, this->ambientSound_, "playOnLoad", setPlayOnLoad,    getPlayOnLoad,    xmlelement, mode);
+    }
+
+    void WorldAmbientSound::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WorldAmbientSound, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(WorldAmbientSound, BaseObject, "play", play, xmlelement, mode);
+    }
+
+    void WorldAmbientSound::play()
+    {
+        this->ambientSound_->play();
+    }
+
+    void WorldAmbientSound::changedActivity()
+    {
+        SUPER(WorldAmbientSound, changedActivity);
+
+        if (this->isActive())
+            this->ambientSound_->play();
+        else
+            this->ambientSound_->stop();
+    }
+
+    void WorldAmbientSound::nextSong()
+    {
+
+        //HACK: Assuption - there is only one WorldAmbientSound in a level and only one level is used.
+        for (WorldAmbientSound* sound : ObjectList<WorldAmbientSound>())
+        {
+            while(sound->ambientSound_->setAmbientSource(WorldAmbientSound::soundList_[WorldAmbientSound::soundNumber_]) == false){
+                WorldAmbientSound::soundNumber_ = (WorldAmbientSound::soundNumber_ + 1) % WorldAmbientSound::soundList_.size();
+            }
+            WorldAmbientSound::soundNumber_ = (WorldAmbientSound::soundNumber_ + 1) % WorldAmbientSound::soundList_.size();
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/WorldAmbientSound.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/WorldAmbientSound.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/WorldAmbientSound.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WorldAmbientSound_H__
+#define _WorldAmbientSound_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+#include <string>
+#include <vector>
+
+
+namespace orxonox
+{
+    /**
+        @brief This class is used to play and control ambient sound in a level file. See AmbientSound for the
+        actual implementation of the background music player.
+    */
+    class _OrxonoxExport WorldAmbientSound : public BaseObject, public Synchronisable
+    {
+        public:
+            WorldAmbientSound(Context* context);
+            virtual ~WorldAmbientSound();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual void changedActivity() override;
+
+            void play();
+
+            //This function changes the current ambient song.
+            //You can call nextSong() active in the level
+            //by pressing the key 'M'.
+            static void nextSong();
+
+        private:
+            void registerVariables();
+
+            //Vector with the diffrent available level sounds.
+            //The sound names are pushed in the WorldAmbientSound-constructor.
+            static std::vector<std::string> soundList_;
+
+            // This value will be initialized below, don't make this into
+            // a const, since we want to change it in nextSong().
+            static int soundNumber_;
+
+
+            AmbientSound* ambientSound_;
+    };
+
+    // This is an initialization for the soundnumber variable. Since it is
+    // static, we have to initialize it this way.
+    int WorldAmbientSound::soundNumber_ = 0;
+    std::vector<std::string> WorldAmbientSound::soundList_;
+
+}
+
+#endif /* _WorldAmbientSound_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/WorldSound.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/WorldSound.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/WorldSound.cc	(revision 11817)
@@ -0,0 +1,126 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Erwin 'vaiursch' Herrsche
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WorldSound.h"
+
+#include <alut.h>
+
+#include "util/Math.h"
+#include "core/CoreIncludes.h"
+#include "core/EventIncludes.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+#include "SoundManager.h"
+
+namespace orxonox
+{
+    RegisterClass(WorldSound);
+
+    WorldSound::WorldSound(Context* context)
+        : StaticEntity(context)
+    {
+        RegisterObject(WorldSound);
+        // WorldSound buffers should be pooled when they're not used anymore
+        this->bPooling_ = true;
+        this->registerVariables();
+    }
+
+    void WorldSound::registerVariables()
+    {
+        registerVariable(volume_,   ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::volumeChanged));
+        registerVariable(source_,   ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::sourceChanged));
+        registerVariable(bLooping_, ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::loopingChanged));
+        registerVariable(pitch_,    ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::pitchChanged));
+        registerVariable(BaseSound::state_, ObjectDirection::ToClient, new NetworkCallback<WorldSound>(this, &WorldSound::stateChanged));
+    }
+
+    void WorldSound::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WorldSound, XMLPort, xmlelement, mode);
+        BaseSound::XMLPortExtern(xmlelement, mode);
+    }
+
+    void WorldSound::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WorldSound, XMLEventPort, xmlelement, mode);
+        XMLPortEventState(WorldSound, BaseObject, "play", play, xmlelement, mode);
+    }
+
+    void WorldSound::initialiseSource()
+    {
+        BaseSound::initialiseSource();
+        if (this->getScene())
+        {
+            float refDist = this->getScene()->getSoundReferenceDistance();
+            alSourcef(this->audioSource_, AL_REFERENCE_DISTANCE, refDist);
+            // TODO: 500 is very magical here. Derive something better
+            alSourcef(this->audioSource_, AL_MAX_DISTANCE, refDist * 20);
+        }
+        this->tick(0); // update position, orientation and velocity
+    }
+
+    void WorldSound::tick(float dt)
+    {
+        if (alIsSource(this->audioSource_))
+        {
+            const Vector3& pos = this->getWorldPosition();
+            alSource3f(this->audioSource_, AL_POSITION, pos.x, pos.y, pos.z);
+            ALenum error = alGetError();
+            if (error == AL_INVALID_VALUE)
+                orxout(internal_error, context::sound) << "OpenAL: Invalid sound position" << endl;
+
+            const Vector3& vel = this->getVelocity();
+            alSource3f(this->audioSource_, AL_VELOCITY, vel.x, vel.y, vel.z);
+            error = alGetError();
+            if (error == AL_INVALID_VALUE)
+                orxout(internal_error, context::sound) << "OpenAL: Invalid sound velocity" << endl;
+
+            const Vector3& direction = -this->getWorldOrientation().zAxis();
+            alSource3f(this->audioSource_, AL_DIRECTION, direction.x, direction.y, direction.z);
+            error = alGetError();
+            if (error == AL_INVALID_VALUE)
+                orxout(internal_error, context::sound) << "OpenAL: Invalid sound direction" << endl;
+        }
+    }
+
+    void WorldSound::changedActivity()
+    {
+        SUPER(WorldSound, changedActivity);
+        if (this->isActive())
+            this->play();
+        else
+            this->stop();
+    }
+
+    float WorldSound::getRealVolume()
+    {
+        assert(GameMode::playsSound());
+        return SoundManager::getInstance().getRealVolume(SoundType::Effects);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/sound/WorldSound.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/sound/WorldSound.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/sound/WorldSound.h	(revision 11817)
@@ -0,0 +1,65 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WorldSound_H__
+#define _WorldSound_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "tools/interfaces/Tickable.h"
+#include "sound/BaseSound.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The WorldSound class is to be used for sounds with position and orientation.
+    */
+    class _OrxonoxExport WorldSound : public StaticEntity, public BaseSound, public Tickable
+    {
+    public:
+        WorldSound(Context* context);
+
+        virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+        virtual void changedActivity() override;
+
+        virtual void tick(float dt) override;
+
+    protected:
+        ~WorldSound() {}
+
+    private:
+        void registerVariables();
+        virtual void initialiseSource() override;
+        virtual float getRealVolume() override;
+    };
+}
+
+#endif /* _WorldSound_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,11 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  Munition.cc
+  ReplenishingMunition.cc
+  Weapon.cc
+  WeaponMode.cc
+  WeaponPack.cc
+  WeaponSet.cc
+  WeaponSlot.cc
+  WeaponSystem.cc
+  DefaultWeaponmodeLink.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/DefaultWeaponmodeLink.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/DefaultWeaponmodeLink.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/DefaultWeaponmodeLink.cc	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "DefaultWeaponmodeLink.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "WeaponSystem.h"
+
+namespace orxonox
+{
+    RegisterClass(DefaultWeaponmodeLink);
+
+    DefaultWeaponmodeLink::DefaultWeaponmodeLink(Context* context) : BaseObject(context)
+    {
+        RegisterObject(DefaultWeaponmodeLink);
+
+        this->firemode_ = WeaponSystem::FIRE_MODE_UNASSIGNED;
+        this->weaponmode_ = WeaponSystem::WEAPON_MODE_UNASSIGNED;
+    }
+
+    DefaultWeaponmodeLink::~DefaultWeaponmodeLink()
+    {
+    }
+
+    void DefaultWeaponmodeLink::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(DefaultWeaponmodeLink, XMLPort, xmlelement, mode);
+
+        XMLPortParam(DefaultWeaponmodeLink, "firemode",   setFiremode,   getFiremode,   xmlelement, mode);
+        XMLPortParam(DefaultWeaponmodeLink, "weaponmode", setWeaponmode, getWeaponmode, xmlelement, mode);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/DefaultWeaponmodeLink.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/DefaultWeaponmodeLink.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/DefaultWeaponmodeLink.h	(revision 11817)
@@ -0,0 +1,62 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _DefaultWeaponmodeLink_H__
+#define _DefaultWeaponmodeLink_H__
+
+#include "OrxonoxPrereqs.h"
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport DefaultWeaponmodeLink : public BaseObject
+    {
+        public:
+            DefaultWeaponmodeLink(Context* context);
+            virtual ~DefaultWeaponmodeLink();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setFiremode(const unsigned int firemode)
+                { this->firemode_ = firemode; }
+            inline unsigned int getFiremode() const
+                { return this->firemode_; }
+
+            inline void setWeaponmode(const unsigned int weaponmode)
+                { this->weaponmode_ = weaponmode; }
+            inline unsigned int getWeaponmode() const
+                { return this->weaponmode_; }
+
+        private:
+            unsigned int firemode_;
+            unsigned int weaponmode_;
+    };
+}
+
+#endif /* _DefaultWeaponmodeLink_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Munition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Munition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Munition.cc	(revision 11817)
@@ -0,0 +1,560 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Authors:
+ *      Martin Polak
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Fabien Vultier
+ *
+ */
+
+#include "Munition.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(Munition);
+
+    Munition::Munition(Context* context) : BaseObject(context)
+    {
+        RegisterObject(Munition);
+
+        this->maxMunitionPerMagazine_ = 10;
+        this->maxMagazines_ = 10;
+        this->unassignedMagazines_ = 10;
+
+        this->deployment_ = MunitionDeployment::Stack;
+        this->bAllowMunitionRefilling_ = true;
+        this->bAllowMultiMunitionRemovementUnderflow_ = true;
+
+        this->reloadTime_ = 0.5f;
+
+        this->lastFilledWeaponMode_ = nullptr;
+    }
+
+    Munition::~Munition()
+    {
+        for (const auto& mapEntry : this->assignedMagazines_)
+            delete mapEntry.second;
+    }
+
+    void Munition::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Munition, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Munition, "initialmagazines", setNumMagazines, getNumMagazines, xmlelement, mode);
+        XMLPortParam(Munition, "maxmagazines", setMaxMagazines, getMaxMagazines, xmlelement, mode);
+        XMLPortParam(Munition, "munitionpermagazine", setMaxMunitionPerMagazine, getMaxMunitionPerMagazine, xmlelement, mode);
+    }
+
+    Munition::Magazine* Munition::getMagazine(WeaponMode* user) const
+    {
+        if (deployment_ == MunitionDeployment::Separate)
+        {
+            // For separated magazines we definitively need a given user
+            if (!user)
+                return nullptr;
+
+            // Use the map to get the magazine assigned to the given user
+            std::map<WeaponMode*, Magazine*>::const_iterator it = this->assignedMagazines_.find(user);
+            if (it != this->assignedMagazines_.end())
+                return it->second;
+        }
+        else
+        {
+            // We don't use separate magazines for each user, so just take the first magazine
+            if (this->assignedMagazines_.size() > 0)
+                return this->assignedMagazines_.begin()->second;
+        }
+
+        return nullptr;
+    }
+
+    unsigned int Munition::getNumMunition(WeaponMode* user) const
+    {
+        Magazine* magazine = this->getMagazine(user);
+        if (magazine)
+        {
+            if (deployment_ == MunitionDeployment::Stack)
+                // With stacked munition every magazine contributes to the total amount
+                return this->maxMunitionPerMagazine_ * this->unassignedMagazines_ + magazine->munition_;
+            else
+                // Wihtout stacked munition we just consider the current magazine
+                return magazine->munition_;
+        }
+        return 0;
+    }
+
+    unsigned int Munition::getNumMunitionInCurrentMagazine(WeaponMode* user) const
+    {
+        // In contrast to getNumMunition() we really just consider the current magazine, even if we're stacking munition
+        Magazine* magazine = this->getMagazine(user);
+        if (magazine)
+            return magazine->munition_;
+        else
+            return 0;
+    }
+
+    unsigned int Munition::getNumMagazines() const
+    {
+        if (deployment_ == MunitionDeployment::Stack)
+        {
+            // If we stack munition and the current magazine is still full, it counts too
+            Magazine* magazine = this->getMagazine(0);
+            if (magazine && magazine->munition_ == this->maxMunitionPerMagazine_)
+                return this->unassignedMagazines_ + 1;
+        }
+
+        return this->unassignedMagazines_;
+    }
+
+    void Munition::setNumMagazines(unsigned int numMagazines)
+    {
+        this->unassignedMagazines_ = numMagazines;
+    }
+
+    unsigned int Munition::getMaxMunition() const
+    {
+        if (deployment_ == MunitionDeployment::Stack)
+            return this->maxMunitionPerMagazine_ * this->maxMagazines_;
+        else
+            return this->maxMunitionPerMagazine_;
+    }
+
+    bool Munition::canTakeMunition(unsigned int amount, WeaponMode* user) const
+    {
+        Magazine* magazine = this->getMagazine(user);
+        if (magazine && magazine->bLoaded_)
+        {
+            unsigned int munition = magazine->munition_;
+
+            // If we stack munition, we don't care about the current magazine - we just need enough munition in total
+            if (deployment_ == MunitionDeployment::Stack)
+            {
+                munition += this->maxMunitionPerMagazine_ * this->unassignedMagazines_;
+            }
+
+            if (munition == 0)
+            {
+                // Absolutely no munition - no chance to take munition
+                return false;
+            }
+            else if (this->bAllowMultiMunitionRemovementUnderflow_)
+            {
+                // We're not empty AND we allow underflow, so this will always work
+                return true;
+            }
+            else
+            {
+                // We don't allow underflow, so we have to check the amount
+                return (munition >= amount);
+            }
+
+        }
+        return false;
+    }
+
+    bool Munition::takeMunition(unsigned int amount, WeaponMode* user)
+    {
+        if (!this->canTakeMunition(amount, user))
+            return false;
+
+        Magazine* magazine = this->getMagazine(user);
+        if (magazine && magazine->bLoaded_)
+        {
+            if (magazine->munition_ >= amount)
+            {
+                // Enough munition
+                magazine->munition_ -= amount;
+                return true;
+            }
+            else
+            {
+                // Not enough munition
+                if (deployment_ == MunitionDeployment::Stack)
+                {
+                    // We stack munition, so just take what we can and then load the next magazine
+                    amount -= magazine->munition_;
+                    magazine->munition_ = 0;
+
+                    if (this->reload(nullptr))
+                        // Successfully reloaded, continue recursively
+                        return this->takeMunition(amount, 0);
+                    else
+                        // We don't have more magazines, so let's just hope we allow underflow
+                        return this->bAllowMultiMunitionRemovementUnderflow_;
+                }
+                else
+                {
+                    // We don't stack, so we can only take munition if this is allowed
+                    if (magazine->munition_ > 0 && this->bAllowMultiMunitionRemovementUnderflow_)
+                    {
+                        magazine->munition_ = 0;
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    bool Munition::canReload() const
+    {
+        // As long as we have enough magazines (and don't stack munition) we can reload
+        return (this->unassignedMagazines_ > 0 && deployment_ != MunitionDeployment::Stack);
+    }
+
+    bool Munition::needReload(WeaponMode* user) const
+    {
+        Magazine* magazine = this->getMagazine(user);
+        if (magazine)
+        {
+            if (deployment_ == MunitionDeployment::Stack)
+                // With stacked munition, we never have to reload
+                return false;
+            else
+                // We need to reload if an already loaded magazine is empty
+                return (magazine->bLoaded_ && magazine->munition_ == 0);
+        }
+        else
+            // No magazine - we definitively need to reload
+            return true;
+    }
+
+    bool Munition::reload(WeaponMode* user, bool bUseReloadTime)
+    {
+        // Don't reload if we're already reloading
+        Magazine* magazine = this->getMagazine(user);
+        if (magazine && !magazine->bLoaded_)
+            return false;
+
+        // Check if we actually can reload
+        if (this->unassignedMagazines_ == 0)
+            return false;
+
+        // If we use separate magazines for each user, we definitively need a user given
+        if (deployment_ == MunitionDeployment::Separate && !user)
+            return false;
+
+        // If we don't use separate magazines, set user to 0
+        if (deployment_ != MunitionDeployment::Separate)
+        {
+            user = nullptr;
+        }
+
+        // Remove the current magazine for the given user
+        std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.find(user);
+        if (it != this->assignedMagazines_.end())
+        {
+            if (it->first == lastFilledWeaponMode_)
+            {
+                lastFilledWeaponMode_ = nullptr;
+            }            
+            delete it->second;
+            this->assignedMagazines_.erase(it);
+        }
+
+        // Load a new magazine
+        this->assignedMagazines_[user] = new Magazine(this, bUseReloadTime);
+        this->unassignedMagazines_--;
+
+        return true;
+    }
+
+    bool Munition::canAddMunition(unsigned int amount) const
+    {
+        // TODO: 'amount' is not used
+
+        if (!this->bAllowMunitionRefilling_)
+            return false;
+
+        if (deployment_ == MunitionDeployment::Stack)
+        {
+            // If we stack munition, we can always add munition until we reach the limit
+            return (this->getNumMunition(0) < this->getMaxMunition());
+        }
+        else
+        {
+            // Return true if any of the current magazines is not full (loading counts as full although it returns 0 munition)
+            for (const auto& mapEntry : this->assignedMagazines_)
+                if (mapEntry.second->munition_ < this->maxMunitionPerMagazine_ && mapEntry.second->bLoaded_)
+                    return true;
+        }
+
+        return false;
+    }
+
+    bool Munition::addMunition(unsigned int amount)
+    {
+        if (!this->canAddMunition(amount))
+            return false;
+
+        if (deployment_ == MunitionDeployment::Stack)
+        {
+            // Stacking munition means, if a magazine gets full, the munition adds to a new magazine
+            Magazine* magazine = this->getMagazine(nullptr);
+            if (magazine)
+            {
+                // Add the whole amount
+                magazine->munition_ += amount;
+
+                // Add new magazines if the current magazine is overfull
+                while (magazine->munition_ > this->maxMunitionPerMagazine_)
+                {
+                    magazine->munition_ -= this->maxMunitionPerMagazine_;
+                    this->unassignedMagazines_++;
+                }
+
+                // If we reached the limit, reduce both magazines and munition to the maximum
+                if (this->unassignedMagazines_ >= this->maxMagazines_)
+                {
+                    this->unassignedMagazines_ = this->maxMagazines_;
+                    magazine->munition_ = this->maxMunitionPerMagazine_;
+                }
+
+                return true;
+            }
+
+            // Something went wrong
+            return false;
+        }
+        else
+        {
+            std::map<WeaponMode*, Magazine*>::iterator it;
+
+            // If the pointer to the weapon mode whose magazine got munition added to is nullptr, then set the iterator to the beginning of the map
+            // Otherwise set it to the next weapon mode
+            if (lastFilledWeaponMode_ == nullptr)
+            {
+                it = this->assignedMagazines_.begin();
+            }
+            else
+            {
+                it = this->assignedMagazines_.find(lastFilledWeaponMode_);
+                ++ it;
+            }
+
+            // Share the munition equally to the current magazines
+            bool firstLoop = true;
+            while (amount > 0)
+            {
+                bool change = false;
+                while (it != this->assignedMagazines_.end())
+                {
+                    // Add munition if the magazine isn't full (but only to loaded magazines)
+                    if (amount > 0 && it->second->munition_ < this->maxMunitionPerMagazine_ && it->second->bLoaded_)
+                    {
+                        it->second->munition_++;
+                        amount--;
+                        lastFilledWeaponMode_ = it->first;
+                        change = true;
+                    }
+
+                    ++it;
+                }
+
+                // If there was no change in a loop, all magazines are full (or locked due to loading)
+                // Because the first loop does not start at the beginning of the map we have to treat is separately
+                if (!change && !firstLoop)
+                {
+                    break;
+                }                    
+
+                it = this->assignedMagazines_.begin();
+                firstLoop = false;
+            }
+
+            return true;
+        }
+    }
+
+    bool Munition::canAddMagazines(unsigned int amount) const
+    {
+        // TODO: 'amount' is not used
+
+        if (deployment_ == MunitionDeployment::Stack)
+            // If we stack munition, we can always add new magazines because they contribute directly to the munition
+            return (this->getNumMunition(0) < this->getMaxMunition());
+        else
+            // If we don't stack munition, we're more limited
+            return ((this->assignedMagazines_.size() + this->unassignedMagazines_) < this->maxMagazines_);
+    }
+
+    unsigned int Munition::addMagazines(unsigned int amount)
+    {
+        unsigned int addedMagazines = 0;
+
+        if (!this->canAddMagazines(amount))
+            return 0;
+
+        // Calculate how many magazines are needed
+        int needed_magazines = this->maxMagazines_ - this->unassignedMagazines_ - this->assignedMagazines_.size();
+
+        // If zero or less magazines are needed, we definitively don't need more magazines (unless we stack munition - then a magazine contributes directly to the munition)
+        if (needed_magazines <= 0 && deployment_ != MunitionDeployment::Stack)
+            return 0;
+
+        if (amount <= static_cast<unsigned int>(needed_magazines))
+        {
+            // We need more magazines than we get, so just add them
+            this->unassignedMagazines_ += amount;
+            addedMagazines = amount;
+        }
+        else
+        {
+            // We get more magazines than we need, so just add the needed amount
+            this->unassignedMagazines_ += needed_magazines;
+            addedMagazines = needed_magazines;
+            if (deployment_ == MunitionDeployment::Stack)
+            {
+                // We stack munition, so the additional amount contributes directly to the munition of the current magazine
+                Magazine* magazine = this->getMagazine(0);
+                if (magazine)
+                    magazine->munition_ = this->maxMunitionPerMagazine_;
+            }
+        }
+
+        // Reload as many empty magazines as possible
+        // Double loop and break is needed because the reload function changes the assigned magazines. This may confuse the iterator.
+        for (unsigned int i = 0; i < addedMagazines; ++i)
+        {
+            for (const auto& mapEntry : this->assignedMagazines_)
+            {
+                if (needReload(mapEntry.first))
+                {
+                    reload(mapEntry.first);
+                    break;
+                }
+            }
+        }
+
+        return addedMagazines;
+    }
+
+    bool Munition::canRemoveMagazines(unsigned int amount) const
+    {
+        if (deployment_ == MunitionDeployment::Stack)
+        {
+            if (this->unassignedMagazines_ >= amount)
+            {
+                // We have enough magazines
+                return true;
+            }
+            else if (this->unassignedMagazines_ == amount - 1)
+            {
+                // We lack one magazine, check if the current magazine is still full, if yes we're fine
+                Magazine* magazine = this->getMagazine(0);
+                if (magazine && magazine->munition_ == this->maxMunitionPerMagazine_)
+                    return true;
+            }
+            else
+            {
+                // We don't have enough magazines
+                return false;
+            }
+        }
+        else
+        {
+            // In case we're not stacking munition, just check the number of magazines
+            return (this->unassignedMagazines_ >= amount);
+        }
+
+        return false;
+    }
+
+    bool Munition::removeMagazines(unsigned int amount)
+    {
+        if (!this->canRemoveMagazines(amount))
+            return false;
+
+        if (this->unassignedMagazines_ >= amount)
+        {
+            // We have enough magazines, just remove the amount
+            this->unassignedMagazines_ -= amount;
+        }
+        else if (deployment_ == MunitionDeployment::Stack)
+        {
+            // We don't have enough magazines, but we're stacking munition, so additionally remove the bullets from the current magazine
+            this->unassignedMagazines_ = 0;
+            Magazine* magazine = this->getMagazine(0);
+            if (magazine)
+                magazine->munition_ = 0;
+        }
+
+        return true;
+    }
+
+    bool Munition::dropMagazine(WeaponMode* user)
+    {
+        // If we use separate magazines, we need a user
+        if (deployment_ == MunitionDeployment::Separate && !user)
+            return false;
+
+        // If we don't use separate magazines, set user to 0
+        if (deployment_ != MunitionDeployment::Separate)
+            user = nullptr;
+
+        // Remove the current magazine for the given user
+        std::map<WeaponMode*, Magazine*>::iterator it = this->assignedMagazines_.find(user);
+        if (it != this->assignedMagazines_.end())
+        {
+            if (it->first == lastFilledWeaponMode_)
+            {
+                lastFilledWeaponMode_ = nullptr;
+            }
+            delete it->second;
+            this->assignedMagazines_.erase(it);           
+            return true;
+        }
+
+        return false;
+    }
+
+
+    /////////////////////
+    // Magazine struct //
+    /////////////////////
+    Munition::Magazine::Magazine(Munition* munition, bool bUseReloadTime)
+    {
+        this->munition_ = 0;
+        this->bLoaded_ = false;
+
+        if (bUseReloadTime && munition->reloadTime_ > 0 && munition->deployment_ != MunitionDeployment::Stack)
+        {
+            const ExecutorPtr executor = createExecutor(createFunctor(&Magazine::loaded, this));
+            executor->setDefaultValues(munition);
+
+            this->loadTimer_.setTimer(munition->reloadTime_, false, executor);
+        }
+        else
+            this->loaded(munition);
+    }
+
+    void Munition::Magazine::loaded(Munition* munition)
+    {
+        this->bLoaded_ = true;
+        this->munition_ = munition->maxMunitionPerMagazine_;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Munition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Munition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Munition.h	(revision 11817)
@@ -0,0 +1,132 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Authors:
+ *      Martin Polak
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Fabien Vultier
+ *
+ */
+
+#ifndef _Munition_H__
+#define _Munition_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include "core/BaseObject.h"
+#include "tools/Timer.h"
+
+namespace orxonox
+{
+    enum class MunitionDeployment
+    {
+        Separate, // Every comsuming weapon mode has its own magazine. It is possible that one weapon mode is out of ammo while another still has some.
+        Share, // All comsuming weapon modes take their munition from the same magazine. If this magazine is empty a new one is loaded.
+        Stack // There is only one magazine where all the munition is stored. Use this deployment mode for heavy weapons loke rockets, bombs, ...
+    };
+
+    class _OrxonoxExport Munition : public BaseObject
+    {        
+        struct Magazine
+        {
+            public:
+                Magazine(Munition* munition, bool bUseReloadTime = true);
+                virtual ~Magazine() {}
+
+                unsigned int munition_;
+                Timer loadTimer_;
+                bool bLoaded_;
+
+            private:
+                void loaded(Munition* munition);
+        };
+
+        public:
+            Munition(Context* context);
+            virtual ~Munition();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            unsigned int getNumMunition(WeaponMode* user) const;
+            unsigned int getNumMunitionInCurrentMagazine(WeaponMode* user) const;
+            unsigned int getNumMagazines() const;
+
+            unsigned int getMaxMunition() const;
+            inline unsigned int getMaxMagazines() const
+                { return this->maxMagazines_; }
+            inline unsigned int getMaxMunitionPerMagazine() const
+                { return this->maxMunitionPerMagazine_; }
+            inline MunitionDeployment getMunitionDeployment() const
+                { return deployment_; }
+
+
+            bool canTakeMunition(unsigned int amount, WeaponMode* user) const;
+            bool takeMunition(unsigned int amount, WeaponMode* user);
+
+            bool canReload() const;
+            bool needReload(WeaponMode* user) const;
+            bool reload(WeaponMode* user, bool bUseReloadTime = true);
+            inline float getReloadTime() const
+                { return this->reloadTime_; }
+
+            bool canAddMunition(unsigned int amount) const;
+            bool addMunition(unsigned int amount);
+
+            bool canAddMagazines(unsigned int amount) const;
+            /**
+            @brief Try to add magazines.
+            @param amount The amount of magazines tried to add.
+            @return The amount of magazines sucessfully added.
+            */
+            unsigned int addMagazines(unsigned int amount);
+
+            bool canRemoveMagazines(unsigned int amount) const;
+            bool removeMagazines(unsigned int amount);
+
+            bool dropMagazine(WeaponMode* user);
+
+        protected:
+            unsigned int maxMunitionPerMagazine_;
+            unsigned int maxMagazines_;
+            unsigned int unassignedMagazines_; // Number of magazines that are not assigned to a weapon mode. These are alway treated as full.
+            std::map<WeaponMode*, Magazine*> assignedMagazines_; // Maps weapon modes to magazines that are currently used.
+
+            MunitionDeployment deployment_; // Defines the behaviour how munition and magazines are distributed to the consuming weapon modes.
+
+            bool bAllowMunitionRefilling_;
+            bool bAllowMultiMunitionRemovementUnderflow_;
+
+            float reloadTime_; // The time needed to replace a magazine by a new one.
+            WeaponMode* lastFilledWeaponMode_; // Pointer to the weapon mode that got the last munition during the last call of addMunition.
+
+        private:
+            Magazine* getMagazine(WeaponMode* user) const;
+            inline void setMaxMagazines(unsigned int maxMagazines)
+                { this->maxMagazines_ = maxMagazines; }
+            inline void setMaxMunitionPerMagazine(unsigned int maxMunitionPerMagazine)
+                { this->maxMunitionPerMagazine_ = maxMunitionPerMagazine; }
+            void setNumMagazines(unsigned int numMagazines);
+    };
+}
+
+#endif /* _Munition_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/ReplenishingMunition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/ReplenishingMunition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/ReplenishingMunition.cc	(revision 11817)
@@ -0,0 +1,92 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ReplenishingMunition.h
+    @brief Implementation of the ReplenishingMunition class.
+*/
+
+#include "ReplenishingMunition.h"
+
+#include "core/CoreIncludes.h"
+#include "core/command/Executor.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(ReplenishingMunition);
+
+    ReplenishingMunition::ReplenishingMunition(Context* context) : Munition(context)
+    {
+        RegisterObject(ReplenishingMunition);
+
+        this->replenishInterval_ = 1.0f;
+        this->replenishAmount_ = 1;
+
+        // Use the timer to initialize itself after the first tick (because the real values for
+        // replenishIntervall_ and replenishMunitionAmount_ will be set in the constructor of the
+        // inheriting class, which comes after this constructor)
+        this->replenishingTimer_.setTimer(0.0f, false, createExecutor(createFunctor(&ReplenishingMunition::initializeTimer, this)));
+    }
+
+    void ReplenishingMunition::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ReplenishingMunition, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ReplenishingMunition, "replenishamount", setReplenishAmount, getReplenishAmount, xmlelement, mode);
+        XMLPortParam(ReplenishingMunition, "replenishinterval", setReplenishInterval, getReplenishInterval, xmlelement, mode);
+    }    
+
+    float ReplenishingMunition::getProgress()
+    {
+        return replenishingTimer_.getRemainingTime()/this->replenishInterval_;
+    }
+
+    void ReplenishingMunition::initializeTimer()
+    {
+        // Initialize the timer
+        this->replenishingTimer_.setTimer(this->replenishInterval_, true, createExecutor(createFunctor(&ReplenishingMunition::replenish, this)));
+    }
+
+    void ReplenishingMunition::replenish()
+    {
+        if (this->canAddMagazines(this->replenishAmount_))
+        {
+            // Make a temporary copy of bAllowMunitionRefilling_, because this might be disallowed in every
+            // case except the internal munition replenishing
+            bool temp = this->bAllowMunitionRefilling_;
+            this->bAllowMunitionRefilling_ = true;
+
+            // Replenish munition
+            this->addMagazines(this->replenishAmount_);
+
+            // Write back the temporary value
+            this->bAllowMunitionRefilling_ = temp;            
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/ReplenishingMunition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/ReplenishingMunition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/ReplenishingMunition.h	(revision 11817)
@@ -0,0 +1,81 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+/**
+    @file ReplenishingMunition.h
+    @brief Definition of the ReplenishingMunition class.
+*/
+
+#ifndef _ReplenishingMunition_H__
+#define _ReplenishingMunition_H__
+
+#include "tools/Timer.h"
+#include "Munition.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Munition that is replenished by a certain amount each time interval.
+    @author
+        Fabian 'x3n' Landau
+    @ingroup WeaponsMunitions
+    */
+    class _OrxonoxExport ReplenishingMunition : public Munition
+    {
+        public:
+            ReplenishingMunition(Context* context);
+            virtual ~ReplenishingMunition() = default;
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            
+            float getProgress();
+            inline unsigned int getReplenishAmount() const
+                { return replenishAmount_; }
+            inline float getReplenishInterval() const
+                { return replenishInterval_; }
+
+        protected:                          
+            float replenishInterval_; //!< The interval in which the munition is replenished.
+            unsigned int replenishAmount_; //!< The amount of magazines by which it is replenished.
+
+        private:
+            void replenish(); //!< Every call of this function replenishes the munition. This function is called by the timer.
+            void initializeTimer();
+
+            Timer replenishingTimer_; //!< Timer to do the replenishing.
+
+            inline void setReplenishAmount(unsigned int replenishAmount)
+                { this->replenishAmount_ = replenishAmount; }
+            inline void setReplenishInterval(float replenishInterval)
+                { this->replenishInterval_ = replenishInterval; }              
+    };
+}
+
+#endif /* _ReplenishingMunition_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Weapon.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Weapon.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Weapon.cc	(revision 11817)
@@ -0,0 +1,163 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Weapon.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "WeaponMode.h"
+#include "WeaponPack.h"
+#include "WeaponSystem.h"
+
+namespace orxonox
+{
+    RegisterClass(Weapon);
+
+    Weapon::Weapon(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Weapon);
+
+        this->weaponPack_ = nullptr;
+        this->weaponSlot_ = nullptr;
+        this->bReloading_ = false;
+        this->reloadingWeaponmode_ = WeaponSystem::WEAPON_MODE_UNASSIGNED;
+
+        this->reloadTimer_.setTimer(0.0f, false, createExecutor(createFunctor(&Weapon::reloaded, this)));
+        this->reloadTimer_.stopTimer();
+    }
+
+    Weapon::~Weapon()
+    {
+        if (this->isInitialized())
+        {
+            if (this->weaponPack_)
+                this->weaponPack_->removeWeapon(this);
+
+            for (const auto& mapEntry : this->weaponmodes_)
+                mapEntry.second->destroy();
+        }
+    }
+
+    void Weapon::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Weapon, XMLPort, xmlelement, mode);
+
+        XMLPortObject(Weapon, WeaponMode, "", addWeaponmode, getWeaponmode, xmlelement, mode);
+    }
+
+    void Weapon::addWeaponmode(WeaponMode* weaponmode)
+    {
+        if (!weaponmode)
+            return;
+
+        this->weaponmodes_.insert(std::pair<unsigned int, WeaponMode*>(weaponmode->getMode(), weaponmode));
+        weaponmode->setWeapon(this);
+    }
+
+    WeaponMode* Weapon::getWeaponmode(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (const auto& mapEntry : this->weaponmodes_)
+        {
+            if (i == index)
+                return mapEntry.second;
+
+            ++i;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Fire this Weapon with the the WeaponMode defined by @param mode
+    */
+    void Weapon::fire(unsigned int mode)
+    {
+        // To avoid firing with more than one mode at the same time, we lock the weapon (reloading) for
+        // all modes except the one which is currently reloading.
+        //
+        // Example:
+        // WeaponMode A -> mode 0
+        // WeaponMode B -> mode 0
+        // WeaponMode C -> mode 1
+        //
+        // -> A and B can fire at the same time, but C has to wait until both (A and B) have reloaded
+        // -> If C fires, A and B have to wait until C has reloaded
+        //
+        // Note: The reloading of each WeaponMode is internally handled by each A, B and C.
+        //       The reloading of the weapon is only performed to avoid firing with different modes at the same time.
+        if (this->bReloading_ && this->reloadingWeaponmode_ != mode)
+            return;
+
+        std::multimap<unsigned int, WeaponMode*>::iterator start = this->weaponmodes_.lower_bound(mode);
+        std::multimap<unsigned int, WeaponMode*>::iterator end   = this->weaponmodes_.upper_bound(mode);
+
+        for (std::multimap<unsigned int, WeaponMode*>::iterator it = start; it != end; ++it)
+        {
+            float reloading_time = 0;
+            if (it->second->fire(&reloading_time))
+            {
+                this->bReloading_ = true;
+                this->reloadingWeaponmode_ = mode;
+
+                this->reloadTimer_.setInterval(reloading_time);
+                this->reloadTimer_.startTimer();
+            }
+        }
+    }
+
+    /**
+    @brief
+        Reload all @ref orxonox::WeaponMode weapon modes of this weapon.
+    */
+    void Weapon::reload()
+    {
+        for (const auto& mapEntry : this->weaponmodes_)
+            mapEntry.second->reload();
+    }
+
+    void Weapon::reloaded()
+    {
+        this->bReloading_ = false;
+        this->reloadingWeaponmode_ = WeaponSystem::WEAPON_MODE_UNASSIGNED;
+    }
+
+    void Weapon::notifyWeaponModes()
+    {
+        for (const auto& mapEntry : this->weaponmodes_)
+            mapEntry.second->setWeapon(this);
+    }
+
+    void Weapon::updateMunition()
+    {
+        for (const auto& mapEnty : this->weaponmodes_)
+            mapEnty.second->updateMunition();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Weapon.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Weapon.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/Weapon.h	(revision 11817)
@@ -0,0 +1,97 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Weapon_H__
+#define _Weapon_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include "tools/Timer.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        A Weapon is a StaticEntity that can be attached to a WeaponSlot. A Weapon can shoot with different @ref orxonox::WeaponMode modes.
+        Imagine for example that a machine gun can shoot normal bullets, tracer bullets or even grenades.
+    */    
+    class _OrxonoxExport Weapon : public StaticEntity
+    {
+        public:
+            Weapon(Context* context);
+            virtual ~Weapon();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void fire(unsigned int mode);
+            void reload();
+
+            void addWeaponmode(WeaponMode* weaponmode);
+            WeaponMode* getWeaponmode(unsigned int index) const;
+            inline const std::multimap<unsigned int, WeaponMode*>& getAllWeaponmodes() const
+                { return weaponmodes_; }
+            inline int getNumWeaponModes() const
+                { return weaponmodes_.size(); }
+
+            /**
+            @brief
+                This function is called by a @ref orxonox::WeaponPack if this Weapon is added to the WeaponPack.
+            */
+            inline void setWeaponPack(WeaponPack * weaponPack)
+                { this->weaponPack_ = weaponPack; this->notifyWeaponModes(); }
+            inline WeaponPack * getWeaponPack() const
+                { return this->weaponPack_; }
+
+            /**
+            @brief
+                This function is called by a @ref orxonox::WeaponSlot if this Weapon gets attached to the WeaponSlot.
+            */
+            inline void setWeaponSlot(WeaponSlot * wSlot)
+                { this->weaponSlot_ = wSlot; }
+            inline WeaponSlot * getWeaponSlot() const
+                { return this->weaponSlot_; }
+            void updateMunition();
+
+        private:
+            void reloaded();
+            void notifyWeaponModes();
+
+            WeaponPack* weaponPack_;
+            WeaponSlot* weaponSlot_;
+            std::multimap<unsigned int, WeaponMode*> weaponmodes_;
+
+            Timer reloadTimer_;
+            bool bReloading_;
+            unsigned int reloadingWeaponmode_;
+    };
+}
+
+#endif /* _Weapon_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponMode.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponMode.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponMode.cc	(revision 11817)
@@ -0,0 +1,366 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WeaponMode.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "controllers/Controller.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "Munition.h"
+#include "Weapon.h"
+#include "WeaponPack.h"
+#include "WeaponSystem.h"
+#include "WeaponSlot.h"
+
+#include "sound/WorldSound.h"
+
+namespace orxonox
+{
+    RegisterAbstractClass(WeaponMode).inheritsFrom<BaseObject>();
+
+    WeaponMode::WeaponMode(Context* context) : BaseObject(context)
+    {
+        RegisterObject(WeaponMode);
+
+        this->weapon_ = nullptr;
+        this->mode_ = WeaponSystem::WEAPON_MODE_UNASSIGNED;
+
+        this->munition_ = nullptr;
+        this->initialMunition_ = 0;
+        this->initialMagazines_ = 0;
+        this->munitionPerShot_ = 1;
+
+        this->reloadTime_ = 0.25;
+        this->bReloading_ = false;
+        this->bAutoReload_ = true;
+        this->bParallelReload_ = true;
+
+        this->reloadTimer_.setTimer(0.0f, false, createExecutor(createFunctor(&WeaponMode::reloaded, this)));
+        this->reloadTimer_.stopTimer();
+
+        this->damage_ = 0;
+        this->healthdamage_ = 0;
+        this->shielddamage_ = 0;
+
+        this->muzzleOffset_ = Vector3::ZERO;
+        this->muzzlePosition_ = Vector3::ZERO;
+        this->muzzleOrientation_ = Quaternion::IDENTITY;
+
+        hudImageString_ = "Orxonox/WSHUD_WM_Unknown";
+
+        this->fireSoundPath_ = BLANKSTRING;
+        this->fireSoundVolume_ = 1.0;
+        this->fireSounds_.clear();
+
+        this->reloadSoundPath_ = BLANKSTRING;
+        this->reloadSoundVolume_ = 1.0;
+        this->reloadSound_ = nullptr;
+    }
+
+    WeaponMode::~WeaponMode()
+    {
+        if (this->isInitialized())
+        {
+            for (auto sound : fireSounds_)
+            {
+                sound->destroy();
+            }
+        }
+    }
+
+    void WeaponMode::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WeaponMode, XMLPort, xmlelement, mode);
+
+        XMLPortParam(WeaponMode, "mode",             setMode,             getMode,             xmlelement, mode);
+
+        XMLPortParam(WeaponMode, "munitiontype",     setMunitionName,     getMunitionName,     xmlelement, mode);
+        XMLPortParam(WeaponMode, "initialmunition",  setInitialMunition,  getInitialMunition,  xmlelement, mode);
+        XMLPortParam(WeaponMode, "initialmagazines", setInitialMagazines, getInitialMagazines, xmlelement, mode);
+        XMLPortParam(WeaponMode, "munitionpershot",  setMunitionPerShot,  getMunitionPerShot,  xmlelement, mode);
+
+        XMLPortParam(WeaponMode, "reloadtime",       setReloadTime,       getReloadTime,       xmlelement, mode);
+        XMLPortParam(WeaponMode, "autoreload",       setAutoReload,       getAutoReload,       xmlelement, mode).description("If true, the weapon reloads the magazine automatically");
+        XMLPortParam(WeaponMode, "parallelreload",   setParallelReload,   getParallelReload,   xmlelement, mode).description("If true, the weapon reloads in parallel to the magazine reloading");
+
+        XMLPortParam(WeaponMode, "damage",           setDamage,           getDamage,           xmlelement, mode);
+        XMLPortParam(WeaponMode, "healthdamage",     setHealthDamage,     getHealthDamage,     xmlelement, mode);
+        XMLPortParam(WeaponMode, "shielddamage",     setShieldDamage,     getShieldDamage,     xmlelement, mode);
+        XMLPortParam(WeaponMode, "muzzleoffset",     setMuzzleOffset,     getMuzzleOffset,     xmlelement, mode);
+    }
+
+    bool WeaponMode::fire(float* reloadTime)
+    {
+        (*reloadTime) = this->reloadTime_;
+        
+        // Fireing is only possible if this weapon mode is not reloading and there is enough munition
+        if (!this->bReloading_ && this->munition_ && this->munition_->takeMunition(this->munitionPerShot_, this))
+        {
+            float tempReloadtime = this->reloadTime_;
+
+            if (this->bAutoReload_ && this->munition_->needReload(this))
+            {
+                if (this->munition_->reload(this))
+                {
+                    // If true, the weapon reloads in parallel to the magazine reloading
+                    if (this->bParallelReload_)
+                    {
+                        // The time needed to reload is the maximum of the reload time of the weapon mode and the magazine.
+                        tempReloadtime = std::max(this->reloadTime_, this->munition_->getReloadTime());
+                    }                        
+                    else
+                    {
+                        // The time needed to reload is the sum of the reload time of the weapon mode and the magazine.
+                        tempReloadtime = this->reloadTime_ + this->munition_->getReloadTime();
+                    }
+                    playReloadSound();
+                }
+            }
+
+            // For stacked munition, a reload sound is played after every fired projectile
+            if (this->munition_->getMunitionDeployment() == MunitionDeployment::Stack)
+            {
+                playReloadSound();
+            }
+
+            // Mark this weapon mode as reloading and start the reload timer
+            this->bReloading_ = true;
+            this->reloadTimer_.setInterval(tempReloadtime);
+            this->reloadTimer_.startTimer();
+
+            // Play the fire sound and fire the weapon mode
+            this->playFireSound();
+            this->fire();
+
+            return true;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    bool WeaponMode::reload()
+    {
+        if (this->munition_ && this->munition_->reload(this))
+        {
+            if (!this->bParallelReload_)
+            {
+                this->bReloading_ = true;
+                this->reloadTimer_.setInterval(this->reloadTime_ + this->munition_->getReloadTime());
+                this->reloadTimer_.startTimer();
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    void WeaponMode::setMunitionType(Identifier* identifier)
+    {
+        this->munitionname_ = identifier->getName();
+        this->munitiontype_ = identifier;
+        this->updateMunition();
+    }
+
+    void WeaponMode::setMunitionName(const std::string& munitionname)
+    {
+        this->munitionname_ = munitionname;
+        Identifier* identifier = ClassByString(this->munitionname_);
+        if (identifier)
+            this->munitiontype_ = identifier;
+        else
+            orxout(internal_warning) << "No munition class defined in WeaponMode " << this->getName() << endl;
+        this->updateMunition();
+    }
+
+    void WeaponMode::updateMunition()
+    {
+        if (this->munitiontype_ && this->weapon_ && this->weapon_->getWeaponPack() && this->weapon_->getWeaponPack()->getWeaponSystem())
+        {
+            this->munition_ = this->weapon_->getWeaponPack()->getWeaponSystem()->getMunition(&this->munitiontype_);
+
+            if (this->munition_)
+            {
+                // Add the initial magazines
+                this->munition_->addMagazines(this->initialMagazines_);
+
+                // Maybe we have to reload (if this munition is used the first time or if there weren't any magazines available before)
+                if (this->munition_->needReload(this))
+                    this->munition_->reload(this, false);
+
+                // Add the initial munition
+                if (this->initialMunition_ > 0 && this->munition_->getNumMunitionInCurrentMagazine(this) == this->munition_->getMaxMunitionPerMagazine())
+                {
+                    // The current magazine is still full, so let's just add another magazine to
+                    // the stack and reduce the current magazine to the given amount of munition
+
+                    unsigned int initialmunition = this->initialMunition_;
+                    if (initialmunition > this->munition_->getMaxMunitionPerMagazine())
+                        initialmunition = this->munition_->getMaxMunitionPerMagazine();
+
+                    this->munition_->takeMunition(this->munition_->getMaxMunitionPerMagazine() - initialmunition, this);
+                    this->munition_->addMagazines(1);
+                }
+                else
+                {
+                    // The current magazine isn't full, add the munition directly
+
+                    this->munition_->addMunition(this->initialMunition_);
+                }
+            }
+        }
+        else
+        {
+            this->munition_ = nullptr;
+        }
+    }
+
+    void WeaponMode::reloaded()
+    {
+        this->bReloading_ = false;
+    }
+
+    void WeaponMode::computeMuzzleParameters(const Vector3& target)
+    {
+        if (this->weapon_)
+        {
+            this->muzzlePosition_ = this->weapon_->getWorldPosition() + this->weapon_->getWorldOrientation() * this->muzzleOffset_;
+
+            Vector3 muzzleDirection;
+            muzzleDirection = target - this->muzzlePosition_;
+            this->muzzleOrientation_ = (this->weapon_->getWorldOrientation() * WorldEntity::FRONT).getRotationTo(muzzleDirection) * this->weapon_->getWorldOrientation();
+        }
+        else
+        {
+            this->muzzlePosition_ = this->muzzleOffset_;
+            this->muzzleOrientation_ = Quaternion::IDENTITY;
+        }
+    }
+
+    Vector3 WeaponMode::getMuzzleDirection() const
+    {
+        if (this->weapon_)
+            return (this->getMuzzleOrientation() * WorldEntity::FRONT);
+        else
+            return WorldEntity::FRONT;
+    }
+
+    void WeaponMode::setFireSound(const std::string& soundPath, const float soundVolume)
+    {
+        fireSoundPath_ = soundPath;
+        fireSoundVolume_ = soundVolume;
+    }
+
+    const std::string& WeaponMode::getFireSound()
+    {
+        return fireSoundPath_;
+    }
+
+    void WeaponMode::setReloadSound(const std::string& soundPath, const float soundVolume)
+    {
+        reloadSoundPath_ = soundPath;
+        reloadSoundVolume_ = soundVolume;
+    }
+
+    const std::string& WeaponMode::getReloadSound()
+    {
+        return reloadSoundPath_;
+    }
+
+    void WeaponMode::playFireSound()
+    {
+        WorldSound* unusedSound = nullptr;
+
+        if (!GameMode::isMaster())
+        {
+            return;
+        }
+
+        // If no sound path or no weapon was specified, then no sound is played.
+        if (fireSoundPath_ == BLANKSTRING || !this->getWeapon())
+        {
+            return;
+        }
+
+        // Search in the sound list for a WorldSound that may be used. It must be an idle WorldSound instance (i.e. it is not playing a sound now)
+        for (auto sound : fireSounds_)
+        {
+            if( sound && !(sound->isPlaying()))
+            {
+                // Unused sound found
+                unusedSound = sound;
+                break;
+            }
+        }
+
+        // If no unused sound was found, create a new one and add it to the list
+        if (!unusedSound)
+        {
+            unusedSound = new WorldSound(this->getContext());
+            fireSounds_.push_back(unusedSound);
+            unusedSound->setLooping(false);
+            unusedSound->setSource(fireSoundPath_);
+            unusedSound->setVolume(fireSoundVolume_);
+            this->getWeapon()->attach(unusedSound);
+        }
+
+        // Play the fire sound
+        unusedSound->play();
+    }
+
+    void WeaponMode::playReloadSound()
+    {
+        if (!GameMode::isMaster())
+        {
+            return;
+        }
+
+        // If no sound path or no weapon was specified, then no sound is played.
+        if (reloadSoundPath_ == BLANKSTRING || !this->getWeapon())
+        {
+            return;
+        }
+
+        // Create a reload WorldSound if not done yet
+        if (!reloadSound_)
+        {
+            reloadSound_ = new WorldSound(this->getContext());
+            reloadSound_->setSource(reloadSoundPath_);
+            reloadSound_->setVolume(reloadSoundVolume_);
+            this->getWeapon()->attach(reloadSound_);
+        }
+
+        // Play the reload sound
+        reloadSound_->play();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponMode.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponMode.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponMode.h	(revision 11817)
@@ -0,0 +1,205 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WeaponMode_H__
+#define _WeaponMode_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <vector>
+#include "util/Math.h"
+#include "core/BaseObject.h"
+#include "core/class/SubclassIdentifier.h"
+#include "tools/Timer.h"
+#include "Munition.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        A WeaponMode defines how a Weapon is used. It specifies what kind of @ref orxonox::Projectile is created when you fire it, how much time it takes to reload, what sound you hear while shooting, how much damage the projectile deals to a target, ...
+    */
+    class _OrxonoxExport WeaponMode : public BaseObject
+    {
+        public:
+            WeaponMode(Context* context);
+            virtual ~WeaponMode();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            virtual bool fire(float* reloadTime);
+            bool reload();
+
+            // Munition
+            inline Munition* getMunition() const
+                { return this->munition_; }
+
+            void setMunitionType(Identifier* identifier);
+            inline Identifier* getMunitionType() const
+                { return this->munitiontype_; }
+
+            void setMunitionName(const std::string& munitionname);
+            inline const std::string& getMunitionName() const
+                { return this->munitionname_; }
+
+            inline void setInitialMunition(unsigned int amount)
+                { this->initialMunition_ = amount; }
+            inline unsigned int getInitialMunition() const
+                { return this->initialMunition_; }
+
+            inline void setInitialMagazines(unsigned int amount)
+                { this->initialMagazines_ = amount; }
+            inline unsigned int getInitialMagazines() const
+                { return this->initialMagazines_; }
+
+            inline void setMunitionPerShot(unsigned int amount)
+                { this->munitionPerShot_ = amount; }
+            inline unsigned int getMunitionPerShot() const
+                { return this->munitionPerShot_; }
+
+
+            // Reloading
+            inline void setReloadTime(float time)
+                { this->reloadTime_ = time; }
+            inline float getReloadTime() const
+                { return this->reloadTime_; }
+
+            inline void setAutoReload(bool autoreload)
+                { this->bAutoReload_ = autoreload; }
+            inline bool getAutoReload() const
+                { return this->bAutoReload_; }
+
+            inline void setParallelReload(bool parallelreload)
+                { this->bParallelReload_ = parallelreload; }
+            inline bool getParallelReload() const
+                { return this->bParallelReload_; }
+            inline bool getReloading() const
+                { return this->bReloading_; }
+
+
+            // Fire
+            inline void setDamage(float damage)
+                { this->damage_ = damage;}
+            inline float getDamage() const
+                { return this->damage_; }
+            inline void setHealthDamage(float healthdamage)
+                { this->healthdamage_ = healthdamage; }
+            inline float getHealthDamage() const
+                { return this->healthdamage_; }
+
+            inline void setShieldDamage(float shielddamage)
+                { this->shielddamage_ = shielddamage;}
+            inline float getShieldDamage() const
+                { return this->shielddamage_; }
+
+            inline void setMuzzleOffset(const Vector3& offset)
+                { this->muzzleOffset_ = offset; }
+            inline const Vector3& getMuzzleOffset() const
+                { return this->muzzleOffset_; }
+
+            void computeMuzzleParameters(const Vector3& target);
+            const Vector3& getMuzzlePosition() const
+                { return this->muzzlePosition_; }
+            const Quaternion& getMuzzleOrientation() const
+                { return this->muzzleOrientation_; }
+            Vector3 getMuzzleDirection() const;
+
+
+            // Weapon
+            inline void setWeapon(Weapon* weapon)
+                { this->weapon_ = weapon; this->updateMunition(); }
+            inline Weapon* getWeapon() const
+                { return this->weapon_; }
+
+            inline void setMode(unsigned int mode)
+                { this->mode_ = mode; }
+            inline unsigned int getMode() const
+                { return this->mode_; }
+
+            Vector3 getTarget();
+
+            inline const std::string& getHUDImageString() const
+                { return this->hudImageString_; }            
+
+            void updateMunition();
+        protected:
+            // Interacting with the firing sound
+            void setFireSound(const std::string& soundPath, const float soundVolume = 1.0);
+            const std::string& getFireSound();
+            void playFireSound();
+
+            // Interacting with the reloading sound
+            void setReloadSound(const std::string& soundPath, const float soundVolume = 1.0);
+            const std::string& getReloadSound();
+            void playReloadSound();
+
+            virtual void fire() = 0;
+
+            unsigned int initialMunition_;
+            unsigned int initialMagazines_;
+            unsigned int munitionPerShot_;
+
+            float reloadTime_;
+            bool bAutoReload_; // If true, the weapon reloads the magazine automatically.
+            bool bParallelReload_; // If true, the weapon reloads in parallel to the magazine reloading.
+
+            float damage_;
+            float healthdamage_;
+            float shielddamage_;
+            Vector3 muzzleOffset_;
+
+            std::string hudImageString_;
+
+        private:            
+            void reloaded();
+
+            Weapon* weapon_;
+            unsigned int mode_;
+
+            Munition* munition_;
+            SubclassIdentifier<Munition> munitiontype_;
+            std::string munitionname_;
+
+            Timer reloadTimer_;
+            bool bReloading_; // If true, this weapon mode is marked as reloading.
+
+            Vector3 muzzlePosition_;
+            Quaternion muzzleOrientation_;
+
+            std::string fireSoundPath_; // The path of the sound played when fireing
+            float fireSoundVolume_; // The volume of the sound played when fireing
+            std::vector<WorldSound*> fireSounds_; // List of sounds used by the weapon mode. Because multiple sounds may overlap, we need mor than one WorldSound instance.
+            std::string reloadSoundPath_; // The path of the sound played when reloading
+            float reloadSoundVolume_; // The volume of the sound played when reloading
+            WorldSound* reloadSound_;
+    };
+}
+
+#endif /* _WeaponMode_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponPack.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponPack.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponPack.cc	(revision 11817)
@@ -0,0 +1,164 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WeaponPack.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Weapon.h"
+#include "WeaponSystem.h"
+#include "DefaultWeaponmodeLink.h"
+
+namespace orxonox
+{
+    RegisterClass(WeaponPack);
+
+    WeaponPack::WeaponPack(Context* context) : BaseObject(context)
+    {
+        RegisterObject(WeaponPack);
+
+        this->weaponSystem_ = nullptr;
+    }
+
+    WeaponPack::~WeaponPack()
+    {
+        if (this->isInitialized())
+        {
+            if( this->weaponSystem_ )
+                this->weaponSystem_->removeWeaponPack(this);
+
+            while (!this->weapons_.empty())
+                (*this->weapons_.begin())->destroy();
+
+            for (std::set<DefaultWeaponmodeLink*>::iterator it = this->links_.begin(); it != this->links_.end(); )
+                (*(it++))->destroy();
+        }
+    }
+
+    void WeaponPack::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WeaponPack, XMLPort, xmlelement, mode);
+
+        XMLPortObjectExtended(WeaponPack, Weapon, "", addWeapon, getWeapon, xmlelement, mode, false, false);
+        XMLPortObject(WeaponPack, DefaultWeaponmodeLink, "links", addDefaultWeaponmodeLink, getDefaultWeaponmodeLink, xmlelement, mode);
+    }
+
+    /**
+    @brief
+        Fire all weapons in this WeaponSet with the defined weaponmode.
+    */
+    void WeaponPack::fire(unsigned int weaponmode)
+    {
+        for (Weapon* weapon : this->weapons_)
+            weapon->fire(weaponmode);
+    }
+
+    /**
+    @brief
+        Reload all weapons in this WeaponSet.
+    */
+    void WeaponPack::reload()
+    {
+        for (Weapon* weapon : this->weapons_)
+            weapon->reload();
+    }
+
+    void WeaponPack::addWeapon(Weapon * weapon)
+    {
+        if (!weapon)
+            return;
+
+        this->weapons_.push_back(weapon);
+        weapon->setWeaponPack(this);
+    }
+
+    void WeaponPack::removeWeapon(Weapon * weapon)
+    {
+        if (!weapon)
+            return;
+
+        std::vector<Weapon*>::iterator it = std::find(this->weapons_.begin(), this->weapons_.end(), weapon);
+        assert(it != this->weapons_.end());
+        this->weapons_.erase(it);
+        weapon->setWeaponPack(nullptr);
+    }
+
+    Weapon * WeaponPack::getWeapon(unsigned int index) const
+    {
+        unsigned int i = 0;
+
+        for (Weapon* weapon : this->weapons_)
+        {
+            if (i == index)
+                return weapon;
+            ++i;
+        }
+
+        return nullptr;
+    }
+
+    void WeaponPack::addDefaultWeaponmodeLink(DefaultWeaponmodeLink* link)
+    {
+        this->links_.insert(link);
+    }
+
+    DefaultWeaponmodeLink* WeaponPack::getDefaultWeaponmodeLink(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (DefaultWeaponmodeLink* link : this->links_)
+        {
+            if (i == index)
+                return link;
+
+            ++i;
+        }
+        return nullptr;
+    }
+
+    unsigned int WeaponPack::getDesiredWeaponmode(unsigned int firemode) const
+    {
+        for (DefaultWeaponmodeLink* link : this->links_)
+            if (link->getFiremode() == firemode)
+                return link->getWeaponmode();
+
+        return WeaponSystem::WEAPON_MODE_UNASSIGNED;
+    }
+
+    void WeaponPack::notifyWeapons()
+    {
+        for (Weapon* weapon : this->weapons_)
+            weapon->setWeaponPack(this);
+    }
+
+    void WeaponPack::updateMunition()
+    {
+        for (Weapon* weapon : this->weapons_)
+            weapon->updateMunition();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponPack.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponPack.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponPack.h	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _WeaponPack_H__
+#define _WeaponPack_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <set>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport WeaponPack : public BaseObject
+    {
+        public:
+            WeaponPack(Context* context);
+            virtual ~WeaponPack();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void fire(unsigned int weaponmode);
+            void reload();
+
+            void addWeapon(Weapon * weapon);
+            void removeWeapon(Weapon * weapon);
+            Weapon * getWeapon(unsigned int index) const;
+            inline const std::vector<Weapon*>& getAllWeapons() const
+                { return weapons_; }
+
+            inline size_t getNumWeapons() const
+                { return this->weapons_.size(); }
+
+            void addDefaultWeaponmodeLink(DefaultWeaponmodeLink* link);
+            DefaultWeaponmodeLink* getDefaultWeaponmodeLink(unsigned int index) const;
+
+            unsigned int getDesiredWeaponmode(unsigned int firemode) const;
+
+            inline void setWeaponSystem(WeaponSystem * weaponSystem)
+                { this->weaponSystem_ = weaponSystem; this->notifyWeapons(); }
+            inline WeaponSystem * getWeaponSystem() const
+                { return this->weaponSystem_; }
+            void updateMunition();
+
+        private:
+            void notifyWeapons();
+
+            std::vector<Weapon *> weapons_;
+            std::set<DefaultWeaponmodeLink *> links_;
+            WeaponSystem * weaponSystem_;
+    };
+}
+
+#endif /* _WeaponPack_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSet.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSet.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSet.cc	(revision 11817)
@@ -0,0 +1,95 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WeaponSet.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "WeaponSystem.h"
+#include "WeaponPack.h"
+
+namespace orxonox
+{
+    RegisterClass(WeaponSet);
+
+    WeaponSet::WeaponSet(Context* context) : BaseObject(context)
+    {
+        RegisterObject(WeaponSet);
+
+        this->weaponSystem_ = nullptr;
+        this->desiredFiremode_ = WeaponSystem::FIRE_MODE_UNASSIGNED;
+    }
+
+    WeaponSet::~WeaponSet()
+    {
+        if (this->isInitialized() && this->weaponSystem_)
+            this->weaponSystem_->removeWeaponSet(this);
+    }
+
+    void WeaponSet::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WeaponSet, XMLPort, xmlelement, mode);
+
+        XMLPortParam(WeaponSet, "firemode", setDesiredFiremode, getDesiredFiremode, xmlelement, mode);
+    }
+
+    void WeaponSet::fire()
+    {
+        // Fire all WeaponPacks with their defined weaponmode
+        for (const auto& mapEntry : this->weaponpacks_)
+            if (mapEntry.second != WeaponSystem::WEAPON_MODE_UNASSIGNED)
+                mapEntry.first->fire(mapEntry.second);
+    }
+
+    void WeaponSet::reload()
+    {
+        // Reload all WeaponPacks with their defined weaponmode
+        for (const auto& mapEntry : this->weaponpacks_)
+            mapEntry.first->reload();
+    }
+
+    void WeaponSet::setWeaponmodeLink(WeaponPack* weaponpack, unsigned int weaponmode)
+    {
+        this->weaponpacks_[weaponpack] = weaponmode;
+    }
+
+    void WeaponSet::removeWeaponmodeLink(WeaponPack* weaponpack)
+    {
+        this->weaponpacks_.erase(weaponpack);
+    }
+
+    unsigned int WeaponSet::getWeaponmodeLink(WeaponPack* weaponpack)
+    {
+        std::map<WeaponPack*, unsigned int>::iterator it = this->weaponpacks_.find(weaponpack);
+        if (it != this->weaponpacks_.end())
+            return it->second;
+        else
+            return WeaponSystem::WEAPON_MODE_UNASSIGNED;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSet.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSet.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSet.h	(revision 11817)
@@ -0,0 +1,72 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _WeaponSet_H__
+#define _WeaponSet_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport WeaponSet : public BaseObject
+    {
+        public:
+            WeaponSet(Context* context);
+            virtual ~WeaponSet();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void fire();
+            void reload();
+
+            void setWeaponmodeLink(WeaponPack* weaponpack, unsigned int weaponmode);
+            void removeWeaponmodeLink(WeaponPack* weaponpack);
+            unsigned int getWeaponmodeLink(WeaponPack* weaponpack);
+
+            inline void setDesiredFiremode(const unsigned int firemode)
+                { this->desiredFiremode_ = firemode; }
+            inline unsigned int getDesiredFiremode() const
+                { return this->desiredFiremode_; }
+
+            inline void setWeaponSystem(WeaponSystem *weaponSystem)
+                { this->weaponSystem_ = weaponSystem; }
+            inline WeaponSystem * getWeaponSystem() const
+                { return this->weaponSystem_; }
+
+        private:
+            WeaponSystem * weaponSystem_;
+            unsigned int desiredFiremode_;
+            std::map<WeaponPack*, unsigned int> weaponpacks_;
+    };
+}
+
+#endif /* _WeaponSet_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSlot.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSlot.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSlot.cc	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WeaponSlot.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Weapon.h"
+#include "WeaponSystem.h"
+
+namespace orxonox
+{
+    RegisterClass(WeaponSlot);
+
+    WeaponSlot::WeaponSlot(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(WeaponSlot);
+
+        this->weaponSystem_ = nullptr;
+        this->weapon_ = nullptr;
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    WeaponSlot::~WeaponSlot()
+    {
+        if (this->isInitialized() && this->weaponSystem_)
+            this->weaponSystem_->removeWeaponSlot(this);
+    }
+
+    void WeaponSlot::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WeaponSlot, XMLPort, xmlelement, mode);
+
+        // In the future, there might be parameters like allowed weapon types or max size of the weapon
+    }
+
+    /**
+    @brief
+        Attaches the passed Weapon to this WeaponSlot. If this WeaponSlot is already occupied the old Weapon is removed and replaced by the new one.
+    */
+    void WeaponSlot::attachWeapon(Weapon *weapon)
+    {
+        if (this->weapon_)
+            this->removeWeapon();
+
+        this->weapon_ = weapon;
+
+        if (this->weapon_)
+        {
+            this->weapon_->setWeaponSlot(this);
+            this->weapon_->setPosition(this->getPosition());
+        }
+    }
+
+    /**
+    @brief
+        Removes the attached weapon if there is any.
+    */
+    void WeaponSlot::removeWeapon()
+    {
+        if (this->weapon_)
+        {
+            this->weapon_->setWeaponSlot(nullptr);
+            this->weapon_ = nullptr;
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSlot.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSlot.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSlot.h	(revision 11817)
@@ -0,0 +1,91 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WeaponSlot_H__
+#define _WeaponSlot_H__
+
+#include "OrxonoxPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The a WeaponSlot defines where a @ref orxonox::Weapon "Weapon" is placed on a pawn. A WeaponSlot is a @ref orxonox::StaticEntity, therefore it has a position and orientation.
+        In a WeaponSlot there can be only one "Weapon", but a Weapon can have several @ref orxonox::WeaponMode "WeaponModes".
+        A WeaponMode is what one intuitively imagines as weapon. (E.g. RocketFire, LightningGun, LaserFire are weaponmodes)
+
+        A WeaponSlot is created in XML (in a weaponsettings file), which can be done in the following fashion:
+        @code
+        <weaponslots>
+          <WeaponSlot position="-15.0,-1.5,0" />
+          <WeaponSlot position=" 15.0,-1.5,0" />
+          <WeaponSlot position="    0,   0,0" />
+        </weaponslots>
+        @endcode
+
+        A WeaponSlot can be attached to a @ref orxonox::Pawn because WeaponSlot inherits from @ref orxonox::StaticEntity.
+
+    @author
+        Martin Polak
+
+    @ingroup Weaponsystem
+    */
+    class _OrxonoxExport WeaponSlot : public StaticEntity
+    {
+        public:
+            WeaponSlot(Context* context);
+            virtual ~WeaponSlot();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void attachWeapon(Weapon * weapon);
+            void removeWeapon();
+            Weapon * getWeapon() const
+                { return this->weapon_; }
+
+            /**
+            @brief
+                Checks whether there is a Weapon attached to this WeaponSlot.
+            */
+            inline bool isOccupied() const
+                { return (this->weapon_ != nullptr); }
+
+            inline void setWeaponSystem(WeaponSystem * weaponSystem)
+                { this->weaponSystem_ = weaponSystem; }
+            inline WeaponSystem * getWeaponSystem() const
+                { return this->weaponSystem_; }
+
+
+        private:
+            WeaponSystem * weaponSystem_; // Pointer to the WeaponSystem
+            Weapon * weapon_; // If the WeaponSlot is occupied a pointer to the attached Weapon is stored here.
+    };
+}
+
+#endif /* _WeaponSlot_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSystem.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSystem.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSystem.cc	(revision 11817)
@@ -0,0 +1,345 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WeaponSystem.h"
+
+#include "core/CoreIncludes.h"
+#include "core/class/SubclassIdentifier.h"
+#include "worldentities/pawns/Pawn.h"
+
+#include "WeaponSlot.h"
+#include "WeaponPack.h"
+#include "WeaponSet.h"
+#include "Weapon.h"
+#include "Munition.h"
+
+/* WeaponSystem
+ *
+ *  www.orxonox.net/wiki/WeaponSystem
+ */
+
+namespace orxonox
+{
+    RegisterClass(WeaponSystem);
+
+    WeaponSystem::WeaponSystem(Context* context) : BaseObject(context)
+    {
+        RegisterObject(WeaponSystem);
+
+        this->pawn_ = nullptr;
+    }
+
+    WeaponSystem::~WeaponSystem()
+    {
+        if (this->isInitialized())
+        {
+            if (this->pawn_)
+                this->pawn_->setWeaponSystem(nullptr);
+
+            while (!this->weaponSets_.empty())
+                this->weaponSets_.begin()->second->destroy();
+
+            while (!this->weaponPacks_.empty())
+                (*this->weaponPacks_.begin())->destroy();
+
+            while (!this->weaponSlots_.empty())
+                (*this->weaponSlots_.begin())->destroy();
+
+            while (!this->munitions_.empty())
+                { this->munitions_.begin()->second->destroy(); this->munitions_.erase(this->munitions_.begin()); }
+        }
+    }
+
+    void WeaponSystem::addWeaponSlot(WeaponSlot * wSlot)
+    {
+        if (!wSlot)
+            return;
+
+        this->weaponSlots_.push_back(wSlot);
+        wSlot->setWeaponSystem(this);
+    }
+
+    void WeaponSystem::removeWeaponSlot(WeaponSlot * wSlot)
+    {
+        if (!wSlot)
+            return;
+
+        if (wSlot->getWeapon())
+            this->removeWeaponPack(wSlot->getWeapon()->getWeaponPack());
+
+        for (std::vector<WeaponSlot*>::iterator it = this->weaponSlots_.begin(); it != this->weaponSlots_.end(); ++it)
+        {
+            if ((*it) == wSlot)
+            {
+                this->weaponSlots_.erase(it);
+                break;
+            }
+        }
+    }
+
+    WeaponSlot * WeaponSystem::getWeaponSlot(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (WeaponSlot* weaponSlot : this->weaponSlots_)
+        {
+            ++i;
+            if (i > index)
+                return weaponSlot;
+        }
+        return nullptr;
+    }
+
+    bool WeaponSystem::addWeaponSet(WeaponSet * wSet)
+    {
+        if (wSet)
+            return this->addWeaponSet(wSet, wSet->getDesiredFiremode());
+        else
+            return false;
+    }
+
+    bool WeaponSystem::addWeaponSet(WeaponSet * wSet, unsigned int firemode)
+    {
+        if (!wSet || firemode >= WeaponSystem::MAX_FIRE_MODES)
+            return false;
+
+        std::map<unsigned int, WeaponSet*>::const_iterator it = this->weaponSets_.find(firemode);
+        if (it == this->weaponSets_.end())
+        {
+            this->weaponSets_[firemode] = wSet;
+            wSet->setWeaponSystem(this);
+            return true;
+        }
+
+        return false;
+    }
+
+    void WeaponSystem::removeWeaponSet(WeaponSet * wSet)
+    {
+        for (std::map<unsigned int, WeaponSet*>::iterator it = this->weaponSets_.begin(); it != this->weaponSets_.end(); )
+        {
+            if (it->second == wSet)
+                this->weaponSets_.erase(it++);
+            else
+                ++it;
+        }
+    }
+
+    WeaponSet * WeaponSystem::getWeaponSet(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (const auto& mapEntry : this->weaponSets_)
+        {
+            ++i;
+            if (i > index)
+                return mapEntry.second;
+        }
+        return nullptr;
+    }
+
+    bool WeaponSystem::canAddWeaponPack(WeaponPack * wPack)
+    {
+        if (!wPack)
+            return false;
+
+        unsigned int freeSlots = 0;
+        for (WeaponSlot* weaponSlot : this->weaponSlots_)
+        {
+            if (!weaponSlot->isOccupied())
+                ++freeSlots;
+        }
+
+        return (freeSlots >= wPack->getNumWeapons());
+    }
+
+    bool WeaponSystem::addWeaponPack(WeaponPack * wPack)
+    {
+        if (!this->canAddWeaponPack(wPack))
+            return false;
+
+        // Attach all weapons to the first free slots (and to the Pawn)
+        unsigned int i = 0;
+        for (WeaponSlot* weaponSlot : this->weaponSlots_)
+        {
+            if (!weaponSlot->isOccupied() && i < wPack->getNumWeapons())
+            {
+                Weapon* weapon = wPack->getWeapon(i);
+                weaponSlot->attachWeapon(weapon);
+                this->getPawn()->attach(weapon);
+                ++i;
+            }
+        }
+
+        // Assign the desired weaponmode to the firemodes
+        for (const auto& mapEntry : this->weaponSets_)
+        {
+            unsigned int weaponmode = wPack->getDesiredWeaponmode(mapEntry.first);
+            if (weaponmode != WeaponSystem::WEAPON_MODE_UNASSIGNED)
+                mapEntry.second->setWeaponmodeLink(wPack, weaponmode);
+        }
+
+        this->weaponPacks_.push_back(wPack);
+        wPack->setWeaponSystem(this);
+
+        return true;
+    }
+
+    void WeaponSystem::removeWeaponPack(WeaponPack * wPack)
+    {
+        // Remove all weapons from their WeaponSlot
+        unsigned int i = 0;
+        Weapon* weapon = nullptr;
+        while ((weapon = wPack->getWeapon(i++)))
+            if (weapon->getWeaponSlot())
+                weapon->getWeaponSlot()->removeWeapon();
+
+        // Remove all added links from the WeaponSets
+        for (const auto& mapEntry : this->weaponSets_)
+            mapEntry.second->removeWeaponmodeLink(wPack);
+
+        // Remove the WeaponPack from the WeaponSystem
+        std::vector<WeaponPack*>::iterator it2 = std::find(this->weaponPacks_.begin(),this->weaponPacks_.end(), wPack);
+        assert(it2 !=this->weaponPacks_.end());
+        this->weaponPacks_.erase(it2);
+    }
+
+    WeaponPack * WeaponSystem::getWeaponPack(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (WeaponPack* weaponPack : this->weaponPacks_)
+        {
+            ++i;
+            if (i > index)
+                return weaponPack;
+        }
+        return nullptr;
+    }
+
+    bool WeaponSystem::swapWeaponSlots(WeaponSlot * wSlot1, WeaponSlot * wSlot2)
+    {
+        if (!wSlot1 || !wSlot2)
+            return false;
+
+        Weapon* weapon1 = wSlot1->getWeapon();
+        Weapon* weapon2 = wSlot2->getWeapon();
+
+        wSlot1->attachWeapon(weapon2);
+        wSlot2->attachWeapon(weapon1);
+
+        return true;
+        // In the future, certain weapons might not fit to some slots. Swapping would then be
+        // impossible and the returnvalue would be false.
+    }
+
+    void WeaponSystem::changeWeaponmode(WeaponPack * wPack, WeaponSet * wSet, unsigned int weaponmode)
+    {
+        if (!wPack || !wSet)
+            return;
+
+        // Check if the WeaponPack belongs to this WeaponSystem
+        std::vector<WeaponPack *>::iterator it1 = std::find( this->weaponPacks_.begin(), this->weaponPacks_.end(), wPack );
+        if (it1 == this->weaponPacks_.end())
+            return;
+
+        // Check if the WeaponSet belongs to this WeaponSystem
+        bool foundWeaponSet = false;
+        for (const auto& mapEntry : this->weaponSets_)
+        {
+            if (mapEntry.second == wSet)
+            {
+                foundWeaponSet = true;
+                break;
+            }
+        }
+        if (!foundWeaponSet)
+            return;
+
+        // Finally set the link between firemode and weaponmode
+        wSet->setWeaponmodeLink(wPack, weaponmode);
+    }
+
+    /**
+    @brief
+        Fires the @ref orxonox::WeaponSet with the specified firemode.
+    */
+    void WeaponSystem::fire(unsigned int firemode)
+    {
+        std::map<unsigned int, WeaponSet *>::iterator it = this->weaponSets_.find(firemode);
+        if (it != this->weaponSets_.end() && it->second)
+            it->second->fire();
+    }
+
+    void WeaponSystem::reload()
+    {
+        for (const auto& mapEntry : this->weaponSets_)
+            mapEntry.second->reload();
+    }
+
+    Munition * WeaponSystem::getMunition(SubclassIdentifier<Munition> * identifier)
+    {
+        if (!identifier || !identifier->getIdentifier())
+            return nullptr;
+
+        std::map<Identifier *, Munition *>::iterator it = this->munitions_.find(identifier->getIdentifier());
+        if (it != this->munitions_.end())
+        {
+            return it->second;
+        }
+        else
+        {
+            return nullptr;
+        }
+    }
+
+    void WeaponSystem::addMunition(Munition* munition)
+    {
+        if (munition == nullptr)
+        {
+            return;
+        }
+
+        SubclassIdentifier<Munition> identifier = munition->getIdentifier();
+
+        if (identifier)
+        {
+            this->munitions_[identifier] = munition;
+            updateMunition();
+        }
+        else
+        {
+            orxout(internal_warning) << "Adding munition failed. identifier == nullptr " << endl;
+        }
+    }
+
+    void WeaponSystem::updateMunition()
+    {
+        for (WeaponPack* weaponPack : this->weaponPacks_)
+        {
+            weaponPack->updateMunition();
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSystem.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSystem.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/weaponsystem/WeaponSystem.h	(revision 11817)
@@ -0,0 +1,112 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Martin Polak
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#ifndef _WeaponSystem_H__
+#define _WeaponSystem_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <map>
+#include <set>
+#include <vector>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        An @ref orxonox::Pawn that is able to fire weapons always need to have a WeaponSystem. The WeaponSystem manages all the @ref orxonox::WeaponSet, @ref orxonox::WeaponPack and @ref orxonox::WeaponSlot classes.
+        
+    */       
+    class _OrxonoxExport WeaponSystem : public BaseObject
+    {
+        public:
+            WeaponSystem(Context* context);
+            virtual ~WeaponSystem();
+
+            // adding and removing WeaponSlots
+            void addWeaponSlot(WeaponSlot * wSlot);
+            void removeWeaponSlot(WeaponSlot * wSlot);
+            WeaponSlot * getWeaponSlot(unsigned int index) const;
+            inline const std::vector<WeaponSlot *>& getAllWeaponSlots() const
+                { return weaponSlots_; }
+
+            // adding and removing WeaponSets
+            bool addWeaponSet(WeaponSet * wSet);
+            bool addWeaponSet(WeaponSet * wSet, unsigned int firemode);
+            void removeWeaponSet(WeaponSet * wSet);
+            WeaponSet * getWeaponSet(unsigned int index) const;
+
+            // adding and removing WeaponPacks
+            bool canAddWeaponPack(WeaponPack * wPack);
+            bool addWeaponPack(WeaponPack * wPack);
+            void removeWeaponPack(WeaponPack * wPack);
+            WeaponPack * getWeaponPack(unsigned int index) const;
+            inline const std::vector<WeaponPack *>& getAllWeaponPacks() const
+                { return weaponPacks_; }
+
+            // configure slots and firemodes
+            bool swapWeaponSlots(WeaponSlot * wSlot1, WeaponSlot * wSlot2);
+            void changeWeaponmode(WeaponPack * wPack, WeaponSet * wSet, unsigned int weaponmode);
+
+            void fire(unsigned int firemode);
+            void reload();
+
+            Munition * getMunition(SubclassIdentifier<Munition> * identifier);
+            void addMunition(Munition* munition);
+
+            inline void setPawn(Pawn * pawn)
+                { this->pawn_ = pawn; }
+            inline Pawn * getPawn() const
+                { return this->pawn_; }
+
+            inline int getWeaponSlotSize() const
+                { return this->weaponSlots_.size(); }
+
+            static inline unsigned int getFiremodeMask(unsigned int firemode)
+                { return (0x1 << firemode); }
+
+            static const unsigned int MAX_FIRE_MODES = 8;
+            static const unsigned int FIRE_MODE_UNASSIGNED = static_cast<unsigned int>(-1);
+
+            static const unsigned int MAX_WEAPON_MODES = 8;
+            static const unsigned int WEAPON_MODE_UNASSIGNED = static_cast<unsigned int>(-1);
+
+        private:
+            void updateMunition();
+            
+            std::map<unsigned int, WeaponSet *> weaponSets_;
+            std::vector<WeaponSlot *> weaponSlots_;
+            std::vector<WeaponPack *> weaponPacks_;
+            std::map<Identifier *, Munition *> munitions_;
+            Pawn * pawn_;
+    };
+}
+
+#endif /* _WeaponSystem_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/Actionpoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/Actionpoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/Actionpoint.cc	(revision 11817)
@@ -0,0 +1,88 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Actionpoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(Actionpoint);
+
+    Actionpoint::Actionpoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(Actionpoint);
+        
+        this->actionName_ = "";
+        this->name_ = "";
+        
+        this->bLoopStart_ = false;
+        this->bLoopEnd_ = false;
+        this->bProtectMe_ = false;
+    }
+    
+    void Actionpoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Actionpoint, XMLPort, xmlelement, mode);
+        
+        XMLPortParam(Actionpoint, "action", setActionXML, getActionXML,  xmlelement, mode);
+        XMLPortParam(Actionpoint, "protect", setProtectXML, getProtectXML,  xmlelement, mode);
+        XMLPortParam(Actionpoint, "attack", setAttackXML, getAttackXML,  xmlelement, mode);
+        XMLPortParam(Actionpoint, "protectMe", setProtectMeXML, getProtectMeXML,  xmlelement, mode).defaultValues(false);
+        XMLPortParam(Actionpoint, "loopStart", setLoopStart, getLoopStart,  xmlelement, mode).defaultValues(false);
+        XMLPortParam(Actionpoint, "loopEnd", setLoopEnd, getLoopEnd,  xmlelement, mode).defaultValues(false);
+    }
+    /**
+    @brief
+        action is ATTACK -> returns name of object to attack
+        action is PROTECT -> returns name of object to protect 
+        if asked to protect human, returns a special string.
+    @return
+        name of an object to interact with.
+    @note
+        never use more than one of following arguments for XMLPort:
+        attack, protect, protectMe or
+        loopStart and loopEnd.
+    */
+    std::string Actionpoint::getName() const
+    {
+        if (this->name_ != "")
+        {
+            return this->name_;
+        }
+        else if (this->bProtectMe_)
+        {
+            return "reservedKeyword:human";
+        }
+        else
+        {
+            return "";
+        }
+    }    
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/Actionpoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/Actionpoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/Actionpoint.h	(revision 11817)
@@ -0,0 +1,160 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Gani Aliguzhinov
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Actionpoint_H__
+#define _Actionpoint_H__
+
+#include <string>                           //need string for XML input
+
+#include "core/XMLPort.h"                   //need XMLPort
+#include "worldentities/StaticEntity.h"     //this is a child of StaticEntity
+
+namespace orxonox
+{ 
+    /**
+    @brief
+        Actionpoints are used by ActionpointController and all derived classes.
+        Such classes will execute actions set in Actionpoints.
+
+        In XML file one can pass an array of Actionpoints to a controller. Each
+        Actionpoint can take action type, string and boolean or 
+        action and two booleans as an argument.
+        If action is set to fly, Actionpoint's position is assumed to be the desired
+        location.
+        Example XML code:
+
+        @code
+        <SpaceShip position="-2000, 1500, -1000" lookat="0,0,0" team=0 name="thisShipName">
+          <templates>
+            <Template link=spaceshipassff />
+          </templates>
+          <controller>
+            <DivisionController team=0 formationMode="WALL">
+              <actionpoints>
+                <Actionpoint position="0,0,0" action="FLY" /> 
+                <Actionpoint position="-1000,750,-500" action="ATTACK" attack="someShipName" />
+                <Actionpoint position="-1000,750,-500" action="PROTECT" protectMe=true />
+                <Actionpoint position="-1000,750,-500" action="PROTECT" protect="otherShipName" /> 
+                <Actionpoint position="-1000,750,-500" action="FIGHTALL" />
+               </actionpoints>
+            </DivisionController>
+          </controller>
+        </SpaceShip>
+        @endcode
+
+        Example with loops:
+
+        @code
+        <SpaceShip position="-1500, 1500, -1000" lookat="0,0,0" team=0 name="thisShipName">
+          <templates>
+            <Template link=spaceshipassff />
+          </templates>
+          <controller>
+            <DivisionController team=0 formationMode="finger4">
+              <actionpoints>
+                <Actionpoint position="  0,2000,-600" action="FLY" loopStart=true/>
+                <Actionpoint position="  0,2000,-700" action="FLY"  />
+                <Actionpoint position="100,2000,-700" action="FLY" />
+                <Actionpoint position="100,2000,-600" action="FLY" loopEnd=true />
+              </actionpoints>
+            </DivisionController>
+          </controller>
+        </SpaceShip>
+        @endcode
+        
+        One can also use other Worldentities instead of Actionpoints just like Waypoints, but those points
+        will be included in loop.
+        For more information read descriptions of the methods.
+    */
+    class _OrxonoxExport Actionpoint : public StaticEntity
+    {
+        public:
+            Actionpoint(Context* context);
+            virtual ~Actionpoint() = default;
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            /** @brief Decides what AI will do. @param val action to execute */
+            void setActionXML(std::string val)
+                { this->actionName_ = getUppercase (val); }
+            std::string getActionXML() const
+                { return this->actionName_; }
+
+            /** @brief Makes AI follow an entity. @param val name of entity to protect */
+            void setProtectXML(std::string val)
+                { this->name_ = val; }
+            std::string getProtectXML() const
+                { return this->name_; }
+
+            /** @brief Makes AI attack an entity. @param val name of entity to attack */
+            void setAttackXML(std::string val)
+                { this->name_ = val; }
+            std::string getAttackXML() const
+                { return this->name_; }
+
+            /** @brief Makes AI follow human player. @param c protect Human? */
+            void setProtectMeXML(bool c)
+                { this->bProtectMe_ = c; }
+            bool getProtectMeXML() const
+                { return this->bProtectMe_; }
+
+            /** @brief Starts a loop of Actionpoints. @param value start loop? */
+            void setLoopStart(bool value)
+                { this->bLoopStart_ = value; }
+            bool getLoopStart() const
+                { return this->bLoopStart_; }
+            /** @brief Ends a loop of Actionpoints. @param value end loop? */
+            void setLoopEnd (bool value)
+                { this->bLoopEnd_ = value; }
+            bool getLoopEnd() const
+                { return this->bLoopEnd_; }
+
+            std::string getName() const;
+
+        private:    
+            std::string actionName_;    //!< can be set to "FLY", "ATTACK",
+                                        //!< "PROTECT", "FIGHT", "FIGHTALL"
+                                        //!< or "NONE".
+
+            std::string name_;          //!< name of the ship that is to be
+                                        //!< attacked or protected.
+
+            bool bLoopStart_;           //!< if true, this and all following Actionpoints
+                                        //!< until the first Actionpoint with bLoopEnd_
+                                        //!< set to true are executed in a loop.
+
+            bool bLoopEnd_;             //!< if true, this is the last element of
+                                        //!< a loop started by loopStart=true argument
+
+            bool bProtectMe_;           //!< if player is to be protected,
+                                        //!< instead of passing name, one has
+                                        //!< to set protectMe to true.
+    };
+}
+
+#endif /* _Actionpoint_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/Arrow.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/Arrow.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/Arrow.cc	(revision 11817)
@@ -0,0 +1,42 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      jostoffe
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Arrow.h"
+
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+
+    RegisterClass(Arrow);
+
+    Arrow::Arrow(Context* context) : ControllableEntity(context)
+    {
+        RegisterObject(Arrow);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/Arrow.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/Arrow.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/Arrow.h	(revision 11817)
@@ -0,0 +1,49 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      jostoffe
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Arrow_H__
+#define _Arrow_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "core/XMLPort.h"
+
+#include "ControllableEntity.h"
+
+namespace orxonox {
+
+    class _OrxonoxExport Arrow : public ControllableEntity
+    {
+        public:
+            Arrow(Context* context);
+            virtual ~Arrow() = default;
+    };
+
+}
+
+#endif // _Arrow_H__
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,19 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  WorldEntity.cc
+  StaticEntity.cc
+  MovableEntity.cc
+  MobileEntity.cc
+  ControllableEntity.cc
+  Drone.cc
+  EffectContainer.cc
+  ExplosionChunk.cc
+  CameraPosition.cc
+  SpawnPoint.cc
+  TeamSpawnPoint.cc
+  ExplosionPart.cc
+  Actionpoint.cc
+  NameableStaticEntity.cc
+  Arrow.cc
+)
+
+ADD_SUBDIRECTORY(pawns)
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/CameraPosition.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/CameraPosition.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/CameraPosition.cc	(revision 11817)
@@ -0,0 +1,80 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "CameraPosition.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "graphics/Camera.h"
+
+namespace orxonox
+{
+    RegisterClass(CameraPosition);
+
+    CameraPosition::CameraPosition(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(CameraPosition);
+
+        this->bDrag_ = false;
+        this->bAllowMouseLook_ = false;
+        this->bAbsolute_ = false;
+        this->bRenderCamera_ = false;
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    CameraPosition::~CameraPosition()
+    {
+    }
+
+    void CameraPosition::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(CameraPosition, XMLPort, xmlelement, mode);
+
+        XMLPortParam(CameraPosition, "drag", setDrag, getDrag, xmlelement, mode).defaultValues(false);
+        XMLPortParam(CameraPosition, "mouselook", setAllowMouseLook, getAllowMouseLook, xmlelement, mode).defaultValues(false);
+        XMLPortParam(CameraPosition, "absolute", setIsAbsolute, getIsAbsolute, xmlelement, mode).defaultValues(false);
+        XMLPortParam(CameraPosition, "rendercamera", setRenderCamera, getRenderCamera, xmlelement, mode).defaultValues(false);
+    }
+
+    void CameraPosition::attachCamera(Camera* camera)
+    {
+        if (!this->bDrag_)
+            camera->setDrag(false);
+
+        this->attach(camera);
+
+        if (this->bDrag_)
+            camera->setDrag(true);
+    }
+
+    void CameraPosition::attachCamera(Ogre::Camera* camera)
+    {
+        this->attachOgreObject(camera);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/CameraPosition.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/CameraPosition.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/CameraPosition.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _CameraPosition_H__
+#define _CameraPosition_H__
+
+#include "OrxonoxPrereqs.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport CameraPosition : public StaticEntity
+    {
+        public:
+            CameraPosition(Context* context);
+            virtual ~CameraPosition();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setDrag(bool bDrag)
+                { this->bDrag_ = bDrag; }
+            inline bool getDrag() const
+                { return this->bDrag_; }
+
+            inline void setAllowMouseLook(bool bAllow)
+                { this->bAllowMouseLook_ = bAllow; }
+            inline bool getAllowMouseLook() const
+                { return this->bAllowMouseLook_; }
+
+            inline void setIsAbsolute(bool bAbsolute)
+                { this->bAbsolute_ = bAbsolute; }
+            inline bool getIsAbsolute() const
+                { return this->bAbsolute_; }
+
+            inline void setRenderCamera(bool bRenderCamera)
+                { this->bRenderCamera_ = bRenderCamera; }
+            inline bool getRenderCamera() const
+                { return this->bRenderCamera_; }
+
+            void attachCamera(Camera* camera);
+            void attachCamera(Ogre::Camera* camera);
+
+        private:
+            bool bDrag_;
+            bool bAllowMouseLook_;
+            bool bAbsolute_;
+            bool bRenderCamera_;
+    };
+}
+
+#endif /* _CameraPosition_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/ControllableEntity.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/ControllableEntity.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/ControllableEntity.cc	(revision 11817)
@@ -0,0 +1,685 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#include "ControllableEntity.h"
+
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "network/NetworkFunctionIncludes.h"
+
+#include "Scene.h"
+#include "infos/PlayerInfo.h"
+#include "controllers/NewHumanController.h"
+#include "graphics/Camera.h"
+#include "worldentities/CameraPosition.h"
+#include "overlays/OverlayGroup.h"
+
+namespace orxonox
+{
+    RegisterClass(ControllableEntity);
+
+    registerMemberNetworkFunction( ControllableEntity, fire );
+    registerMemberNetworkFunction( ControllableEntity, setTargetInternal );
+
+    ControllableEntity::ControllableEntity(Context* context) : MobileEntity(context)
+    {
+        RegisterObject(ControllableEntity);
+
+        this->bHasLocalController_ = false;
+        this->bHasHumanController_ = false;
+
+        this->server_overwrite_ = 0;
+        this->client_overwrite_ = 0;
+        this->player_ = nullptr;
+        this->formerPlayer_ = nullptr;
+        this->playerID_ = OBJECTID_UNKNOWN;
+        this->hud_ = nullptr;
+        this->camera_ = nullptr;
+        this->xmlcontroller_ = nullptr;
+        //this->controller_ = nullptr;
+        this->reverseCamera_ = nullptr;
+        this->bDestroyWhenPlayerLeft_ = false;
+        this->cameraPositionRootNode_ = this->node_->createChildSceneNode();
+        this->currentCameraPosition_ = nullptr;
+        this->bMouseLook_ = false;
+        this->mouseLookSpeed_ = 200;
+
+        this->server_position_         = Vector3::ZERO;
+        this->client_position_         = Vector3::ZERO;
+        this->server_linear_velocity_  = Vector3::ZERO;
+        this->client_linear_velocity_  = Vector3::ZERO;
+        this->server_orientation_      = Quaternion::IDENTITY;
+        this->client_orientation_      = Quaternion::IDENTITY;
+        this->server_angular_velocity_ = Vector3::ZERO;
+        this->client_angular_velocity_ = Vector3::ZERO;
+
+        this->setConfigValues();
+        this->setPriority( Priority::VeryHigh );
+        this->registerVariables();
+        this->team_ = -1;
+    }
+
+    ControllableEntity::~ControllableEntity()
+    {
+        if (this->isInitialized())
+        {
+            this->bDestroyWhenPlayerLeft_ = false;
+
+            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
+                this->getPlayer()->stopControl();
+
+            if (this->xmlcontroller_)
+                this->xmlcontroller_->destroy();
+
+            if (this->hud_)
+                this->hud_->destroy();
+
+            if (this->camera_)
+                this->camera_->destroy();
+
+            for (CameraPosition* cameraPosition : this->cameraPositions_)
+                cameraPosition->destroy();
+
+            if (this->getScene()->getSceneManager())
+                this->getScene()->getSceneManager()->destroySceneNode(this->cameraPositionRootNode_->getName());
+        }
+    }
+
+    void ControllableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ControllableEntity, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ControllableEntity, "team", setTeam, getTeam, xmlelement, mode).defaultValues(-1);
+        XMLPortParam(ControllableEntity, "hudtemplate", setHudTemplate, getHudTemplate, xmlelement, mode);
+        XMLPortParam(ControllableEntity, "camerapositiontemplate", setCameraPositionTemplate, getCameraPositionTemplate, xmlelement, mode);
+
+        XMLPortObject(ControllableEntity, CameraPosition, "camerapositions", addCameraPosition, getCameraPosition, xmlelement, mode);
+        XMLPortObject(ControllableEntity, Controller,     "controller",      setXMLController,  getXMLController,  xmlelement, mode);
+    }
+
+    void ControllableEntity::setConfigValues()
+    {
+        SetConfigValue(mouseLookSpeed_, 3.0f);
+    }
+
+    void ControllableEntity::preDestroy()
+    {
+        // HACK - solve this clean and without preDestroy hook for multiplayer where removePlayer() isn't called
+        if (this->isInitialized() && this->bHasLocalController_ && this->bHasHumanController_)
+            this->stopLocalHumanControl();
+    }
+
+    void ControllableEntity::addCameraPosition(CameraPosition* position)
+    {
+        if (!position->getIsAbsolute())
+        {
+            if (position->getAllowMouseLook())
+                position->attachToNode(this->cameraPositionRootNode_);
+            else
+                this->attach(position);
+        }
+        else
+        {
+            WorldEntity* parent = this->getParent();
+            if (parent)
+                parent->attach(position);
+        }
+
+        if (!position->getRenderCamera())
+            this->cameraPositions_.push_back(position);
+        else
+            this->setReverseCamera(position);
+    }
+
+    CameraPosition* ControllableEntity::getCameraPosition(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (CameraPosition* cameraPosition : this->cameraPositions_)
+        {
+            if (i == index)
+                return cameraPosition;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    unsigned int ControllableEntity::getCurrentCameraIndex() const
+    {
+        if (this->cameraPositions_.size() <= 0)
+            return 0;
+
+        unsigned int counter = 0;
+        for (CameraPosition* cameraPosition : this->cameraPositions_)
+        {
+            if (cameraPosition == this->currentCameraPosition_)
+                break;
+            counter++;
+        }
+        if (counter >= this->cameraPositions_.size())
+            return 0;
+
+        return counter;
+    }
+
+    bool ControllableEntity::setCameraPosition(unsigned int index)
+    {
+        if(this->camera_ != nullptr && this->cameraPositions_.size() > 0)
+        {
+            if(index >= this->cameraPositions_.size())
+                index = 0;
+
+            CameraPosition* position = this->getCameraPosition(index);
+            position->attachCamera(this->camera_);
+            this->currentCameraPosition_ = position;
+            return true;
+        }
+
+        return false;
+    }
+
+    void ControllableEntity::switchCamera()
+    {
+        if (this->camera_)
+        {
+            if (this->camera_->getParent() == this && this->cameraPositions_.size() > 0)
+            {
+                this->cameraPositions_.front()->attachCamera(this->camera_);
+                this->currentCameraPosition_ = this->cameraPositions_.front();
+            }
+            else if (this->cameraPositions_.size() > 0)
+            {
+                for (std::list<StrongPtr<CameraPosition>>::const_iterator it = this->cameraPositions_.begin(); it != this->cameraPositions_.end(); ++it)
+                {
+                    if ((*it) == this->camera_->getParent())
+                    {
+                        ++it;
+                        if (it != this->cameraPositions_.end())
+                        {
+                            (*it)->attachCamera(this->camera_);
+                            this->currentCameraPosition_ = *it;
+                        }
+                        else
+                        {
+                            (*this->cameraPositions_.begin())->attachCamera(this->camera_);
+                            this->currentCameraPosition_ = *this->cameraPositions_.begin();
+                        }
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                this->camera_->attachToNode(this->cameraPositionRootNode_);
+                this->currentCameraPosition_ = nullptr;
+            }
+
+            // disable mouse look if the new camera position doesn't allow it
+            if (this->currentCameraPosition_ && !this->currentCameraPosition_->getAllowMouseLook() && this->bMouseLook_)
+                this->mouseLook();
+
+            // disable drag if in mouse look
+            if (this->bMouseLook_)
+                this->getCamera()->setDrag(false);
+        }
+    }
+
+    void ControllableEntity::mouseLook()
+    {
+        // enable mouse look only if allowed - disabling it works always
+        if (this->currentCameraPosition_ && (this->currentCameraPosition_->getAllowMouseLook() || this->bMouseLook_))
+        {
+            this->bMouseLook_ = !this->bMouseLook_;
+
+            if (!this->bMouseLook_)
+            {
+                this->cameraPositionRootNode_->setOrientation(Quaternion::IDENTITY);
+                this->cameraPositionRootNode_->_update(true, false); // update the camera node because otherwise the camera will drag back in position which looks strange
+
+                NewHumanController* controller = orxonox_cast<NewHumanController*>(this->getController());
+                if (controller)
+                    controller->centerCursor();
+            }
+
+            if (this->getCamera())
+            {
+                if (!this->bMouseLook_ && this->currentCameraPosition_->getDrag())
+                    this->getCamera()->setDrag(true);
+                else
+                    this->getCamera()->setDrag(false);
+            }
+        }
+    }
+
+    void ControllableEntity::rotateYaw(const Vector2& value)
+    {
+        if (this->bMouseLook_)
+            this->cameraPositionRootNode_->yaw(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
+    }
+
+    void ControllableEntity::rotatePitch(const Vector2& value)
+    {
+        if (this->bMouseLook_)
+            this->cameraPositionRootNode_->pitch(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
+    }
+
+    void ControllableEntity::rotateRoll(const Vector2& value)
+    {
+        if (this->bMouseLook_)
+            this->cameraPositionRootNode_->roll(Radian(value.y * this->mouseLookSpeed_), Ogre::Node::TS_LOCAL);
+    }
+
+    void ControllableEntity::fire(unsigned int firemode)
+    {
+        if(GameMode::isMaster())
+        {
+            this->fired(firemode);
+        }
+        else
+        {
+            callMemberNetworkFunction(&ControllableEntity::fire, this->getObjectID(), 0, firemode);
+        }
+    }
+
+    void ControllableEntity::setController(Controller* val)
+    {
+        this->controller_ = val;
+    }
+
+    void ControllableEntity::setTarget( WorldEntity* target )
+    {
+        this->target_ = target;
+        if ( !GameMode::isMaster() )
+        {
+            if ( target != nullptr )
+            {
+                callMemberNetworkFunction(&ControllableEntity::setTargetInternal, this->getObjectID(), 0, target->getObjectID() );
+            }
+           else
+           {
+                callMemberNetworkFunction(&ControllableEntity::setTargetInternal, this->getObjectID(), 0, OBJECTID_UNKNOWN );
+           }
+        }
+    }
+
+    void ControllableEntity::setTargetInternal( uint32_t targetID )
+    {
+        this->setTarget( orxonox_cast<WorldEntity*>(Synchronisable::getSynchronisable(targetID)) );
+    }
+
+    void ControllableEntity::setPlayer(PlayerInfo* player)
+    {
+        if (!player)
+        {
+            this->removePlayer();
+            return;
+        }
+
+        this->player_ = player;
+        this->formerPlayer_ = player;
+        this->playerID_ = player->getObjectID();
+        this->bHasLocalController_ = player->isLocalPlayer();
+        this->bHasHumanController_ = player->isHumanPlayer();
+        if(controller_ != nullptr)
+            this->team_ = controller_->getTeam(); // forward controller team number
+
+        if (this->bHasLocalController_ && this->bHasHumanController_)
+        {
+            this->startLocalHumanControl();
+
+            if (!GameMode::isMaster())
+            {
+                this->client_overwrite_ = this->server_overwrite_;
+                this->setSyncMode(ObjectDirection::Bidirectional);
+            }
+        }
+
+        this->changedPlayer();
+    }
+
+    void ControllableEntity::removePlayer()
+    {
+        if (this->bHasLocalController_ && this->bHasHumanController_)
+            this->stopLocalHumanControl();
+
+        this->player_ = nullptr;
+        this->playerID_ = OBJECTID_UNKNOWN;
+        this->bHasLocalController_ = false;
+        this->bHasHumanController_ = false;
+        this->setSyncMode(ObjectDirection::ToClient);
+
+        this->changedPlayer();
+
+        if (this->bDestroyWhenPlayerLeft_)
+            this->destroy();
+    }
+
+    void ControllableEntity::networkcallback_changedplayerID()
+    {
+        // just do this in case the entity wasn't yet synchronized when the corresponding PlayerInfo got our objectID
+        if (this->playerID_ != OBJECTID_UNKNOWN)
+        {
+            this->player_ = orxonox_cast<PlayerInfo*>(Synchronisable::getSynchronisable(this->playerID_));
+            if (this->player_ && (this->player_->getControllableEntity() != this))
+                this->player_->startControl(this);
+        }
+    }
+
+    void ControllableEntity::startLocalHumanControl()
+    {
+        if (!this->camera_ && GameMode::showsGraphics())
+        {
+            this->camera_ = new Camera(this->getContext());
+            this->camera_->requestFocus();
+            if (!this->cameraPositionTemplate_.empty())
+                this->addTemplate(this->cameraPositionTemplate_);
+            if (this->cameraPositions_.size() > 0)
+            {
+                this->cameraPositions_.front()->attachCamera(this->camera_);
+                this->currentCameraPosition_ = this->cameraPositions_.front();
+            }
+            else
+            {
+                this->camera_->attachToNode(this->cameraPositionRootNode_);
+                this->currentCameraPosition_ = nullptr;
+            }
+        }
+
+        this->createHud();
+    }
+
+    // HACK-ish
+    void ControllableEntity::createHud(void)
+    {
+        if (!this->hud_ && GameMode::showsGraphics())
+        {
+            if (!this->hudtemplate_.empty())
+            {
+                this->hud_ = new OverlayGroup(this->getContext());
+                this->hud_->addTemplate(this->hudtemplate_);
+                this->hud_->setOwner(this);
+            }
+        }
+    }
+
+    void ControllableEntity::destroyHud(void)
+    {
+        if (this->hud_ != nullptr)
+        {
+            this->hud_->destroy();
+            this->hud_ = nullptr;
+        }
+    }
+
+    void ControllableEntity::stopLocalHumanControl()
+    {
+        if (this->camera_)
+        {
+            this->camera_->detachFromParent();
+            this->camera_->destroy();
+            this->camera_ = nullptr;
+        }
+
+        if (this->hud_)
+        {
+            this->hud_->destroy();
+            this->hud_ = nullptr;
+        }
+    }
+
+    void ControllableEntity::setXMLController(Controller* controller)
+    {
+        if (!this->xmlcontroller_)
+        {
+            this->xmlcontroller_ = controller;
+            this->bHasLocalController_ = true;
+            this->xmlcontroller_->setControllableEntity(this);
+            this->team_ = this->xmlcontroller_->getTeam(); //forward the team number
+        }
+        else
+            orxout(internal_warning) << "ControllableEntity \"" << this->getName() << "\" already has a Controller." << endl;
+    }
+
+    void ControllableEntity::parentChanged()
+    {
+        WorldEntity::parentChanged();
+
+        WorldEntity* parent = this->getParent();
+        if (parent)
+        {
+            for (CameraPosition* cameraPosition : this->cameraPositions_)
+                if (cameraPosition->getIsAbsolute())
+                    parent->attach(cameraPosition);
+        }
+    }
+
+    void ControllableEntity::tick(float dt)
+    {
+        MobileEntity::tick(dt);
+
+        if (this->isActive())
+        {
+            // Check whether Bullet doesn't do the physics for us
+            if (!this->isDynamic())
+            {
+                if (GameMode::isMaster())
+                {
+                    this->server_position_ = this->getPosition();
+                    this->server_orientation_ = this->getOrientation();
+                    this->server_linear_velocity_ = this->getVelocity();
+                    this->server_angular_velocity_ = this->getAngularVelocity();
+                }
+                else if (this->bHasLocalController_)
+                {
+                    this->client_position_ = this->getPosition();
+                    this->client_orientation_ = this->getOrientation();
+                    this->client_linear_velocity_ = this->getVelocity();
+                    this->client_angular_velocity_ = this->getAngularVelocity();
+                }
+            }
+        }
+    }
+
+    void ControllableEntity::registerVariables()
+    {
+        registerVariable(this->cameraPositionTemplate_,  VariableDirection::ToClient);
+        registerVariable(this->hudtemplate_,             VariableDirection::ToClient);
+
+        registerVariable(this->server_position_,         VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerPosition));
+        registerVariable(this->server_linear_velocity_,  VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerLinearVelocity));
+        registerVariable(this->server_orientation_,      VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerOrientation));
+        registerVariable(this->server_angular_velocity_, VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processServerAngularVelocity));
+
+        registerVariable(this->server_overwrite_,        VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processOverwrite));
+        registerVariable(this->client_overwrite_,        VariableDirection::ToServer);
+
+        registerVariable(this->client_position_,         VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientPosition));
+        registerVariable(this->client_linear_velocity_,  VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientLinearVelocity));
+        registerVariable(this->client_orientation_,      VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientOrientation));
+        registerVariable(this->client_angular_velocity_, VariableDirection::ToServer, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::processClientAngularVelocity));
+
+
+        registerVariable(this->playerID_,                VariableDirection::ToClient, new NetworkCallback<ControllableEntity>(this, &ControllableEntity::networkcallback_changedplayerID));
+    }
+
+    void ControllableEntity::processServerPosition()
+    {
+        if (!this->bHasLocalController_)
+            MobileEntity::setPosition(this->server_position_);
+    }
+
+    void ControllableEntity::processServerLinearVelocity()
+    {
+        if (!this->bHasLocalController_)
+            MobileEntity::setVelocity(this->server_linear_velocity_);
+    }
+
+    void ControllableEntity::processServerOrientation()
+    {
+        if (!this->bHasLocalController_)
+            MobileEntity::setOrientation(this->server_orientation_);
+    }
+
+    void ControllableEntity::processServerAngularVelocity()
+    {
+        if (!this->bHasLocalController_)
+            MobileEntity::setAngularVelocity(this->server_angular_velocity_);
+    }
+
+    void ControllableEntity::processOverwrite()
+    {
+        if (this->bHasLocalController_)
+        {
+            this->setPosition(this->server_position_);
+            this->setOrientation(this->server_orientation_);
+            this->setVelocity(this->server_linear_velocity_);
+            this->setAngularVelocity(this->server_angular_velocity_);
+
+            this->client_overwrite_ = this->server_overwrite_;
+        }
+    }
+
+    void ControllableEntity::processClientPosition()
+    {
+        if (this->server_overwrite_ == this->client_overwrite_)
+        {
+            MobileEntity::setPosition(this->client_position_);
+            this->server_position_ = this->getPosition();
+        }
+    }
+
+    void ControllableEntity::processClientLinearVelocity()
+    {
+        if (this->server_overwrite_ == this->client_overwrite_)
+        {
+            MobileEntity::setVelocity(this->client_linear_velocity_);
+            this->server_linear_velocity_ = this->getVelocity();
+        }
+    }
+
+    void ControllableEntity::processClientOrientation()
+    {
+        if (this->server_overwrite_ == this->client_overwrite_)
+        {
+            MobileEntity::setOrientation(this->client_orientation_);
+            this->server_orientation_ = this->getOrientation();
+        }
+    }
+
+    void ControllableEntity::processClientAngularVelocity()
+    {
+        if (this->server_overwrite_ == this->client_overwrite_)
+        {
+            MobileEntity::setAngularVelocity(this->client_angular_velocity_);
+            this->server_angular_velocity_ = this->getAngularVelocity();
+        }
+    }
+
+    void ControllableEntity::setPosition(const Vector3& position)
+    {
+        if (GameMode::isMaster())
+        {
+            MobileEntity::setPosition(position);
+            this->server_position_ = this->getPosition();
+            ++this->server_overwrite_;
+        }
+        else if (this->bHasLocalController_)
+        {
+            MobileEntity::setPosition(position);
+            this->client_position_ = this->getPosition();
+        }
+    }
+
+    void ControllableEntity::setOrientation(const Quaternion& orientation)
+    {
+        if (GameMode::isMaster())
+        {
+            MobileEntity::setOrientation(orientation);
+            this->server_orientation_ = this->getOrientation();
+            ++this->server_overwrite_;
+        }
+        else if (this->bHasLocalController_)
+        {
+            MobileEntity::setOrientation(orientation);
+            this->client_orientation_ = this->getOrientation();
+        }
+    }
+
+    void ControllableEntity::setVelocity(const Vector3& velocity)
+    {
+        if (GameMode::isMaster())
+        {
+            MobileEntity::setVelocity(velocity);
+            this->server_linear_velocity_ = this->getVelocity();
+            ++this->server_overwrite_;
+        }
+        else if (this->bHasLocalController_)
+        {
+            MobileEntity::setVelocity(velocity);
+            this->client_linear_velocity_ = this->getVelocity();
+        }
+    }
+
+    void ControllableEntity::setAngularVelocity(const Vector3& velocity)
+    {
+        if (GameMode::isMaster())
+        {
+            MobileEntity::setAngularVelocity(velocity);
+            this->server_angular_velocity_ = this->getAngularVelocity();
+            ++this->server_overwrite_;
+        }
+        else if (this->bHasLocalController_)
+        {
+            MobileEntity::setAngularVelocity(velocity);
+            this->client_angular_velocity_ = this->getAngularVelocity();
+        }
+    }
+
+    void ControllableEntity::setWorldTransform(const btTransform& worldTrans)
+    {
+        MobileEntity::setWorldTransform(worldTrans);
+        if (GameMode::isMaster())
+        {
+            this->server_position_ = this->getPosition();
+            this->server_orientation_ = this->getOrientation();
+            this->server_linear_velocity_ = this->getVelocity();
+            this->server_angular_velocity_ = this->getAngularVelocity();
+        }
+        else if (this->bHasLocalController_)
+        {
+            this->client_position_ = this->getPosition();
+            this->client_orientation_ = this->getOrientation();
+            this->client_linear_velocity_ = this->getVelocity();
+            this->client_angular_velocity_ = this->getAngularVelocity();
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/ControllableEntity.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/ControllableEntity.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/ControllableEntity.h	(revision 11817)
@@ -0,0 +1,256 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Reto Grieder
+ *
+ */
+
+#ifndef _ControllableEntity_H__
+#define _ControllableEntity_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <list>
+#include <string>
+#include "util/Math.h"
+#include "MobileEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The ControllableEntity is derived from the @ref orxonox::MobileEntity. ControllableEntities can be controlled by @ref orxonox::Controller Controllers.
+        A Controller will call (based on user input, AI decision, ...) for example the function @see moveFrontBack or the function @see rotateYaw to
+        move the ControllableEntity through space. A Controller could also call the @see boost function to tell the ControllableEntity that he wants it to boost.
+    */
+
+    class _OrxonoxExport ControllableEntity : public MobileEntity
+    {
+        friend class PlayerInfo; // PlayerInfo uses setPlayer and removePlayer
+
+        public:
+            ControllableEntity(Context* context);
+            virtual ~ControllableEntity();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+            void setConfigValues();
+
+            virtual void changedPlayer() {}
+
+            inline PlayerInfo* getPlayer() const
+                { return this->player_; }
+            /**
+            @brief Get the player even after the ControllableEntity has stopped being the players ControllableEntity.
+            @return Returns the most recent PlayerInfo.
+            */
+            inline PlayerInfo* getFormerPlayer() const
+                { return this->formerPlayer_; }
+
+            inline void setDestroyWhenPlayerLeft(bool bDestroy)
+                { this->bDestroyWhenPlayerLeft_ = bDestroy; }
+            inline bool getDestroyWhenPlayerLeft() const
+                { return this->bDestroyWhenPlayerLeft_; }
+
+            virtual void moveFrontBack(const Vector2& value) {}
+            virtual void moveRightLeft(const Vector2& value) {}
+            virtual void moveUpDown(const Vector2& value) {}
+
+            virtual void rotateYaw(const Vector2& value);
+            virtual void rotatePitch(const Vector2& value);
+            virtual void rotateRoll(const Vector2& value);
+
+            inline void moveFrontBack(float value)
+                { this->moveFrontBack(Vector2(value, 0)); }
+            inline void moveRightLeft(float value)
+                { this->moveRightLeft(Vector2(value, 0)); }
+            inline void moveUpDown(float value)
+                { this->moveUpDown(Vector2(value, 0)); }
+
+            inline void rotateYaw(float value)
+                { this->rotateYaw(Vector2(value, 0)); }
+            inline void rotatePitch(float value)
+                { this->rotatePitch(Vector2(value, 0)); }
+            inline void rotateRoll(float value)
+                { this->rotateRoll(Vector2(value, 0)); }
+
+            void fire(unsigned int firemode);
+            virtual void fired(unsigned int firemode) {}
+            virtual void reload() {}
+
+            /**
+            @brief Tells the ControllableEntity to either start or stop boosting.
+                   This doesn't mean, that the ControllableEntity will do so, there might be additional restrictions on boosting, but if it can, then it will.
+            @param bBoost If true the ControllableEntity is told to start boosting, if false it is told to stop.
+            */
+            virtual void boost(bool bBoost) {}
+
+            virtual void greet() {}
+            virtual void switchCamera();
+            virtual void mouseLook();
+
+            inline const std::string& getHudTemplate() const
+                { return this->hudtemplate_; }
+
+            inline Camera* getCamera() const
+                { return this->camera_; }
+            inline OverlayGroup* getHUD() const
+                { return this->hud_; }
+
+            void addCameraPosition(CameraPosition* position);
+            CameraPosition* getCameraPosition(unsigned int index) const;
+            inline const std::list<StrongPtr<CameraPosition>>& getCameraPositions() const
+                { return this->cameraPositions_; }
+            unsigned int getCurrentCameraIndex() const;
+            bool setCameraPosition(unsigned int index);
+
+            inline void setCameraPositionTemplate(const std::string& name)
+                { this->cameraPositionTemplate_ = name; }
+            inline const std::string& getCameraPositionTemplate() const
+                { return this->cameraPositionTemplate_; }
+
+            inline void setReverseCamera(CameraPosition* camera)
+                { this->reverseCamera_ = camera; }
+            inline CameraPosition* getReverseCamera() const
+                { return this->reverseCamera_; }
+
+            using WorldEntity::setPosition;
+            using WorldEntity::setOrientation;
+            using MobileEntity::setVelocity;
+            using MobileEntity::setAngularVelocity;
+
+            virtual void setPosition(const Vector3& position) override;
+            virtual void setOrientation(const Quaternion& orientation) override;
+            virtual void setVelocity(const Vector3& velocity) override;
+            virtual void setAngularVelocity(const Vector3& velocity) override;
+
+            inline bool hasLocalController() const
+                { return this->bHasLocalController_; }
+            inline bool hasHumanController() const
+                { return this->bHasHumanController_; }
+
+            inline bool isInMouseLook() const
+                { return this->bMouseLook_; }
+            inline float getMouseLookSpeed() const
+                { return this->mouseLookSpeed_; }
+            inline CameraPosition* getCurrentCameraPosition()
+                { return this->currentCameraPosition_; }
+
+            inline Controller* getXMLController() const
+                { return this->xmlcontroller_; }
+
+            inline Controller* getController() const
+                { return this->controller_; }
+            void setController(Controller* val);
+
+
+            virtual void setTarget( WorldEntity* target );
+            virtual WorldEntity* getTarget()
+                { return this->target_; }
+            void setTargetInternal( uint32_t targetID );
+
+            inline void setTeam(int team)
+                { this->team_ = team; }
+            inline int getTeam() const
+                { return this->team_; }
+
+        protected:
+            virtual void preDestroy() override;
+
+            virtual void setPlayer(PlayerInfo* player); // don't call this directly, use friend class PlayerInfo instead
+            virtual void removePlayer();                // don't call this directly, use friend class PlayerInfo instead
+
+            virtual void startLocalHumanControl();
+            virtual void stopLocalHumanControl();
+            virtual void parentChanged() override;
+
+            inline void setHudTemplate(const std::string& name)
+                { this->hudtemplate_ = name; }
+            // HACK-ish
+            void createHud(void);
+            void destroyHud(void);
+
+            Ogre::SceneNode* cameraPositionRootNode_;
+
+        private:
+            void registerVariables();
+            void setXMLController(Controller* controller);
+
+            void overwrite();
+            void processOverwrite();
+
+            void processServerPosition();
+            void processServerLinearVelocity();
+            void processServerOrientation();
+            void processServerAngularVelocity();
+
+            void processClientPosition();
+            void processClientLinearVelocity();
+            void processClientOrientation();
+            void processClientAngularVelocity();
+
+            void networkcallback_changedplayerID();
+
+            // Bullet btMotionState related
+            virtual void setWorldTransform(const btTransform& worldTrans) override;
+
+            unsigned int server_overwrite_;
+            unsigned int client_overwrite_;
+
+            bool bHasLocalController_;
+            bool bHasHumanController_;
+            bool bDestroyWhenPlayerLeft_;
+
+            Vector3 server_position_;
+            Vector3 client_position_;
+            Vector3 server_linear_velocity_;
+            Vector3 client_linear_velocity_;
+            Quaternion server_orientation_;
+            Quaternion client_orientation_;
+            Vector3 server_angular_velocity_;
+            Vector3 client_angular_velocity_;
+
+            PlayerInfo* player_;
+            PlayerInfo* formerPlayer_;
+            unsigned int playerID_;
+
+            std::string hudtemplate_;
+            OverlayGroup* hud_;
+
+            Camera* camera_;
+            bool bMouseLook_;
+            float mouseLookSpeed_;
+            std::list<StrongPtr<CameraPosition>> cameraPositions_;
+            CameraPosition* currentCameraPosition_;
+            std::string cameraPositionTemplate_;
+            Controller* xmlcontroller_;
+            WeakPtr<Controller> controller_;
+            CameraPosition* reverseCamera_;
+            WeakPtr<WorldEntity> target_;
+
+            int team_ ; //<! teamnumber
+    };
+}
+
+#endif /* _ControllableEntity_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/Drone.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/Drone.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/Drone.cc	(revision 11817)
@@ -0,0 +1,179 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oli Scheuss
+ *   Co-authors:
+ *      ...
+ */
+
+
+#include "Drone.h"
+
+#include "core/XMLPort.h"
+#include "core/CoreIncludes.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+
+namespace orxonox
+{
+    RegisterClass(Drone);
+    /**
+    @brief
+        Constructor. Registers the object and initializes some default values.
+    */
+    Drone::Drone(Context* context) : Pawn(context)
+    {
+        RegisterObject(Drone);
+
+        this->myController_ = nullptr;
+
+        this->localLinearAcceleration_.setValue(0, 0, 0);
+        this->localAngularAcceleration_.setValue(0, 0, 0);
+        this->setRadarVisibility(false);
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+
+        myController_ = new DroneController(this->getContext()); //!< Creates a new controller and passes our this pointer to it as creator.
+        myController_->setDrone(this);
+
+        this->setController(myController_);
+    }
+
+    /**
+    @brief
+        Destructor. Destroys controller, if present.
+    */
+    Drone::~Drone()
+    {
+        if( this->isInitialized() && this->myController_ )
+            this->myController_->destroy();
+    }
+
+    /**
+    @brief
+        Method for creating a Drone through XML.
+    */
+    void Drone::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Drone, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Drone, "primaryThrust_", setPrimaryThrust, getPrimaryThrust, xmlelement, mode);
+        XMLPortParam(Drone, "auxilaryThrust_", setAuxilaryThrust, getAuxilaryThrust, xmlelement, mode);
+        XMLPortParam(Drone, "rotationThrust_", setRotationThrust, getRotationThrust, xmlelement, mode);
+        XMLPortParam(Drone, "maxDistanceToOwner_", setMaxDistanceToOwner, getMaxDistanceToOwner, xmlelement, mode);
+        XMLPortParam(Drone, "minDistanceToOwner_", setMinDistanceToOwner, getMinDistanceToOwner, xmlelement, mode);
+        XMLPortParam(Drone, "maxShootingRange_", setMaxShootingRange, getMaxShootingRange, xmlelement, mode);
+    }
+
+
+    /**
+    @brief
+        Defines which actions the Drone has to take in each tick.
+    @param dt
+        The length of the tick.
+    */
+    void Drone::tick(float dt)
+    {
+        SUPER(Drone, tick, dt);
+
+        //if (this->hasLocalController())
+        //{
+            this->localLinearAcceleration_.setX(this->localLinearAcceleration_.x() * getMass() * this->auxilaryThrust_);
+            this->localLinearAcceleration_.setY(this->localLinearAcceleration_.y() * getMass() * this->auxilaryThrust_);
+            if (this->localLinearAcceleration_.z() > 0)
+              this->localLinearAcceleration_.setZ(this->localLinearAcceleration_.z() * getMass() * this->auxilaryThrust_);
+            else
+              this->localLinearAcceleration_.setZ(this->localLinearAcceleration_.z() * getMass() * this->primaryThrust_);
+            this->physicalBody_->applyCentralForce(physicalBody_->getWorldTransform().getBasis() * this->localLinearAcceleration_);
+            this->localLinearAcceleration_.setValue(0, 0, 0);
+
+            this->localAngularAcceleration_ *= this->getLocalInertia() * this->rotationThrust_;
+            this->physicalBody_->applyTorque(physicalBody_->getWorldTransform().getBasis() * this->localAngularAcceleration_);
+            this->localAngularAcceleration_.setValue(0, 0, 0);
+        //}
+    }
+
+    /**
+    @brief
+        Moves the Drone in the negative z-direction (Front/Back) by an amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the movement.
+    */
+    void Drone::moveFrontBack(const Vector2& value)
+    {
+        this->localLinearAcceleration_.setZ(this->localLinearAcceleration_.z() - value.x);
+    }
+
+    /**
+    @brief
+        Moves the Drone in the x-direction (Right/Left) by an amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the movement.
+    */
+    void Drone::moveRightLeft(const Vector2& value)
+    {
+        this->localLinearAcceleration_.setX(this->localLinearAcceleration_.x() + value.x);
+    }
+
+    /**
+    @brief
+        Moves the Drone in the y-direction (Up/Down) by an amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the movement.
+    */
+    void Drone::moveUpDown(const Vector2& value)
+    {
+        this->localLinearAcceleration_.setY(this->localLinearAcceleration_.y() + value.x);
+    }
+
+    /**
+    @brief
+        Rotates the Drone around the y-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void Drone::rotateYaw(const Vector2& value)
+    {
+        this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x);
+    }
+
+    /**
+    @brief
+        Rotates the Drone around the x-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void Drone::rotatePitch(const Vector2& value)
+    {
+        this->localAngularAcceleration_.setX(this->localAngularAcceleration_.x() + value.x);
+    }
+
+    /**
+    @brief
+        Rotates the Drone around the z-axis by the amount specified by the first component of the input 2-dim vector.
+    @param value
+        The vector determining the amount of the angular movement.
+    */
+    void Drone::rotateRoll(const Vector2& value)
+    {
+        this->localAngularAcceleration_.setZ(this->localAngularAcceleration_.z() + value.x);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/Drone.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/Drone.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/Drone.h	(revision 11817)
@@ -0,0 +1,152 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Oli Scheuss
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Drone_H__
+#define _Drone_H__
+
+#include "OrxonoxPrereqs.h"
+#include "worldentities/pawns/Pawn.h"
+#include "controllers/DroneController.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        Drone, that is made to move upon a specified pattern.
+        This class was constructed for the PPS tutorial.
+    @author
+        Oli Scheuss
+    */
+    class _OrxonoxExport Drone : public Pawn
+    {
+        public:
+            Drone(Context* context);
+            virtual ~Drone();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override; //!< Method for creating a Drone through XML.
+            virtual void tick(float dt) override; //!< Defines which actions the Drone has to take in each tick.
+
+
+            virtual void moveFrontBack(const Vector2& value) override;
+            virtual void moveRightLeft(const Vector2& value) override;
+            virtual void moveUpDown(const Vector2& value) override;
+
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+
+            /**
+            @brief Moves the Drone in the Front/Back-direction by the specifed amount.
+            @param value  The amount by which the drone is to be moved.
+            */
+            inline void moveFrontBack(float value)
+            { this->moveFrontBack(Vector2(value, 0)); }
+            /**
+            @brief Moves the Drone in the Right/Left-direction by the specifed amount.
+            @param value  The amount by which the drone is to be moved.
+            */
+            inline void moveRightLeft(float value)
+            { this->moveRightLeft(Vector2(value, 0)); }
+            /**
+            @brief Moves the Drone in the Up/Down-direction by the specifed amount.
+            @param value  The amount by which the drone is to be moved.
+            */
+            inline void moveUpDown(float value)
+            { this->moveUpDown(Vector2(value, 0)); }
+
+            /**
+            @brief Rotates the Drone around the y-axis by the specifed amount.
+            @param value  The amount by which the drone is to be rotated.
+            */
+            inline void rotateYaw(float value)
+            { this->rotateYaw(Vector2(value, 0)); }
+            /**
+            @brief Rotates the Drone around the x-axis by the specifed amount.
+            @param value  The amount by which the drone is to be rotated.
+            */
+            inline void rotatePitch(float value)
+            { this->rotatePitch(Vector2(value, 0)); }
+            /**
+            @brief Rotates the Drone around the z-axis by the specifed amount.
+            @param value  The amount by which the drone is to be rotated.
+            */
+            inline void rotateRoll(float value)
+            { this->rotateRoll(Vector2(value, 0)); }
+
+            /**
+            @brief Sets the primary thrust to the input amount.
+            @param thrust The amount of thrust.
+            */
+            inline void setPrimaryThrust( float thrust )
+                { this->primaryThrust_=thrust; }
+            inline void setAuxilaryThrust( float thrust )
+                { this->auxilaryThrust_=thrust; }
+            inline void setRotationThrust( float thrust )
+                { this->rotationThrust_=thrust; }
+            inline void setMaxDistanceToOwner( float distance)
+                { this->maxDistanceToOwner_=distance; }
+            inline void setMinDistanceToOwner( float distance)
+                { this->minDistanceToOwner_=distance; }
+            inline void setMaxShootingRange( float distance)
+                { this->maxShootingRange_=distance; }
+
+
+            /**
+            @brief Gets the primary thrust to the input amount.
+            @return The amount of thrust.
+            */
+            inline float getPrimaryThrust()
+                { return this->primaryThrust_; }
+            inline float getAuxilaryThrust()
+                { return this->auxilaryThrust_; }
+            inline float getRotationThrust()
+                { return this->rotationThrust_; }
+            inline float getMaxDistanceToOwner()
+                { return this->maxDistanceToOwner_; }
+            inline float getMinDistanceToOwner()
+                { return this->minDistanceToOwner_; }
+            inline float getMaxShootingRange()
+                { return this->maxShootingRange_; }
+
+        private:
+            DroneController *myController_; //!< The controller of the Drone.
+
+            btVector3 localLinearAcceleration_; //!< The linear acceleration that is used to move the Drone the next tick.
+            btVector3 localAngularAcceleration_; //!< The linear angular acceleration that is used to move the Drone the next tick.
+            float primaryThrust_; //!< The amount of primary thrust. This is just used, when moving forward.
+            float auxilaryThrust_; //!< The amount of auxilary thrust. Used for all other movements (except for rotations).
+            float rotationThrust_; //!< The amount of rotation thrust. Used for rotations only.
+            float maxDistanceToOwner_; //Maximum Distance to owner
+            float minDistanceToOwner_; //Minimum Distance to owner
+            float maxShootingRange_;
+    };
+
+}
+
+#endif /* _Drone_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/EffectContainer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/EffectContainer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/EffectContainer.cc	(revision 11817)
@@ -0,0 +1,111 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "EffectContainer.h"
+
+extern "C" {
+#include <lua.h>
+}
+
+#include "core/CoreIncludes.h"
+#include "core/LuaState.h"
+#include "core/XMLPort.h"
+#include "worldentities/WorldEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(EffectContainer);
+
+    EffectContainer::EffectContainer(Context* context)
+        : BaseObject(context)
+        , lua_(nullptr)
+    {
+        RegisterObject(EffectContainer);
+    }
+
+    EffectContainer::~EffectContainer()
+    {
+    }
+
+    void EffectContainer::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(EffectContainer, XMLPort, xmlelement, mode);
+        XMLPortParam(EffectContainer, "condition", setCondition, getCondition, xmlelement, mode);
+        XMLPortObject(EffectContainer, WorldEntity, "", addEffect, getEffect, xmlelement, mode);
+    }
+
+    void EffectContainer::setCondition(const std::string& condition)
+    {
+        // TODO: Watch out for code injection!
+        this->condition_ = condition;
+        if (this->lua_)
+        {
+            this->lua_->doString(
+                this->functionName_ + " = function() \n"
+                "    return (" + condition + ") \n"
+                "end"
+            );
+        }
+    }
+
+    void EffectContainer::setLuaState(LuaState* state, const std::string& functionName)
+    {
+        this->functionName_ = functionName;
+        this->lua_ = state;
+        this->setCondition(this->condition_);
+    }
+
+    void EffectContainer::addEffect(WorldEntity* effect)
+    {
+        this->effects_.push_back(effect);
+    }
+
+    WorldEntity* EffectContainer::getEffect(unsigned int index) const
+    {
+        unsigned int i = 0;
+        for (WorldEntity* effect : this->effects_)
+            if (i == index)
+                return effect;
+        return nullptr;
+    }
+
+    void EffectContainer::updateCondition()
+    {
+        if (this->lua_)
+        {
+            lua_getglobal(this->lua_->getInternalLuaState(), this->functionName_.c_str());
+            lua_call(this->lua_->getInternalLuaState(), 0, 1);
+            bool result = (bool)lua_toboolean(this->lua_->getInternalLuaState(), -1);
+            lua_pop(this->lua_->getInternalLuaState(), 1);
+            for (WorldEntity* effect : this->effects_)
+            {
+                effect->setMainState(result);
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/EffectContainer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/EffectContainer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/EffectContainer.h	(revision 11817)
@@ -0,0 +1,69 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _EffectContainer_H__
+#define _EffectContainer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <vector>
+#include "core/BaseObject.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport EffectContainer : public BaseObject
+    {
+        public:
+            EffectContainer(Context* context);
+            virtual ~EffectContainer();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setLuaState(LuaState* state, const std::string& functionName);
+
+            void setCondition(const std::string& condition);
+            inline const std::string& getCondition() const
+                { return this->condition_; }
+
+            void addEffect(WorldEntity* effect);
+            WorldEntity* getEffect(unsigned int index) const;
+
+            inline const std::vector<WorldEntity*>& getEffects() const
+                { return this->effects_; }
+
+            void updateCondition();
+
+        private:
+            std::string               condition_;
+            std::string               functionName_;
+            LuaState*                 lua_;
+            std::vector<WorldEntity*> effects_;
+    };
+}
+
+#endif /* _EffectContainer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionChunk.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionChunk.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionChunk.cc	(revision 11817)
@@ -0,0 +1,160 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "ExplosionChunk.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/command/Executor.h"
+#include "util/Exception.h"
+#include "Scene.h"
+#include "tools/ParticleInterface.h"
+
+namespace orxonox
+{
+    RegisterClass(ExplosionChunk);
+
+    ExplosionChunk::ExplosionChunk(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(ExplosionChunk);
+
+        if ( GameMode::showsGraphics() && ( !this->getScene() || !this->getScene()->getSceneManager() ) )
+            ThrowException(AbortLoading, "Can't create ExplosionChunk, no scene or no scene manager given.");
+
+        this->bStop_ = false;
+        this->LOD_ = LODParticle::Normal;
+
+        if ( GameMode::showsGraphics() )
+        {
+            try
+            {
+                this->fire_ = new ParticleInterface(this->getScene()->getSceneManager(), "Orxonox/fire4", this->LOD_);
+                this->attachOgreObject(this->fire_->getParticleSystem());
+                this->smoke_ = new ParticleInterface(this->getScene()->getSceneManager(), "Orxonox/smoke7", this->LOD_);
+                this->attachOgreObject(this->smoke_->getParticleSystem());
+            }
+            catch (const std::exception& ex)
+            {
+                orxout(internal_error) << "Couldn't load particle effect in ExplosionChunk: " << ex.what() << endl;
+                this->fire_ = nullptr;
+                this->smoke_ = nullptr;
+            }
+        }
+        else
+        {
+            this->fire_ = nullptr;
+            this->smoke_ = nullptr;
+        }
+
+        if (GameMode::isMaster())
+        {
+            Vector3 velocity(rnd(-1, 1), rnd(-1, 1), rnd(-1, 1));
+            velocity.normalise();
+            velocity *= rnd(60, 80);
+            this->setVelocity(velocity);
+
+            this->destroyTimer_.setTimer(rnd(1, 2), false, createExecutor(createFunctor(&ExplosionChunk::stop, this)));
+        }
+
+        this->registerVariables();
+    }
+
+    ExplosionChunk::~ExplosionChunk()
+    {
+        if (this->isInitialized())
+        {
+            if (this->fire_)
+            {
+                this->detachOgreObject(this->fire_->getParticleSystem());
+                delete this->fire_;
+            }
+            if (this->smoke_)
+            {
+                this->detachOgreObject(this->smoke_->getParticleSystem());
+                delete this->smoke_;
+            }
+        }
+    }
+
+    void ExplosionChunk::registerVariables()
+    {
+        registerVariable((int&)(this->LOD_), VariableDirection::ToClient, new NetworkCallback<ExplosionChunk>(this, &ExplosionChunk::LODchanged));
+        registerVariable(this->bStop_,       VariableDirection::ToClient, new NetworkCallback<ExplosionChunk>(this, &ExplosionChunk::checkStop));
+    }
+
+    void ExplosionChunk::LODchanged()
+    {
+        if (this->fire_)
+            this->fire_->setDetailLevel(this->LOD_);
+        if (this->smoke_)
+            this->smoke_->setDetailLevel(this->LOD_);
+    }
+
+    void ExplosionChunk::checkStop()
+    {
+        if (this->bStop_)
+            this->stop();
+    }
+
+    void ExplosionChunk::stop()
+    {
+        if (this->fire_)
+            this->fire_->setEnabled(false);
+        if (this->smoke_)
+            this->smoke_->setEnabled(false);
+
+        if (GameMode::isMaster())
+        {
+            this->bStop_ = true;
+            this->destroyTimer_.setTimer(1.0f, false, createExecutor(createFunctor(&ExplosionChunk::destroy, this)));
+        }
+    }
+
+    void ExplosionChunk::tick(float dt)
+    {
+        static const unsigned int CHANGES_PER_SECOND = 5;
+
+        if (GameMode::isMaster() && rnd() < dt*CHANGES_PER_SECOND)
+        {
+            float length = this->getVelocity().length();
+
+            Vector3 change(rnd(-1, 1), rnd(-1, 1), rnd(-1, 1));
+            change.normalise();
+            change *= rnd(0.4f, 0.8f);
+            Vector3 velocity = this->getVelocity();
+            velocity.normalise();
+            velocity += change;
+            velocity.normalise();
+            velocity *= length * rnd(0.8f, 1.0f);
+
+            this->setVelocity(velocity);
+        }
+
+        SUPER(ExplosionChunk, tick, dt);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionChunk.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionChunk.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionChunk.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ExplosionChunk_H__
+#define _ExplosionChunk_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "tools/Timer.h"
+#include "MovableEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport ExplosionChunk : public MovableEntity
+    {
+        public:
+            ExplosionChunk(Context* context);
+            virtual ~ExplosionChunk();
+
+            virtual void tick(float dt) override;
+
+            inline void setLOD(LODParticle::Value level)
+                { this->LOD_ = level; this->LODchanged(); }
+            inline LODParticle::Value getLOD() const
+                { return this->LOD_; }
+
+        private:
+            void registerVariables();
+            void LODchanged();
+            void checkStop();
+            void stop();
+
+            bool                  bStop_;
+            ParticleInterface*    fire_;
+            ParticleInterface*    smoke_;
+            LODParticle::Value    LOD_;
+            Timer                 destroyTimer_;
+    };
+}
+
+#endif /* _ExplosionChunk_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionPart.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionPart.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionPart.cc	(revision 11817)
@@ -0,0 +1,260 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Vedat Aydin
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+
+#include "ExplosionPart.h"
+#include "core/XMLPort.h"
+
+
+namespace orxonox
+{
+
+    RegisterClass(ExplosionPart);
+
+    ExplosionPart::ExplosionPart(Context* context) : MovableEntity(context)
+    {
+        RegisterObject(ExplosionPart);
+        this->bStop_ = false;
+        this->LOD_ = LODParticle::Normal;
+        this->mesh_ = "";
+        this->effect1_ = "";
+        this->effect2_ = "";
+        this->model_= new Model(this->getContext());
+        this->effect1Particle_= nullptr;
+        this->effect2Particle_= nullptr;
+        this->explosionEntity_ = new MovableEntity(this->getContext());
+        this->posOffset_ = Vector3::ZERO;
+
+
+
+    }
+
+
+    ExplosionPart::~ExplosionPart()
+    {
+        if (this->isInitialized())
+        {
+            if (this->effect1Particle_)
+            {
+                this->model_->detachOgreObject(this->effect1Particle_->getParticleSystem());
+                delete this->effect1Particle_;
+            }
+            if (this->effect2Particle_)
+            {
+                this->model_->detachOgreObject(this->effect2Particle_->getParticleSystem());
+                delete this->effect2Particle_;
+            }
+        }
+    }
+
+
+    void ExplosionPart::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ExplosionPart, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ExplosionPart, "mesh", setMesh, getMesh, xmlelement, mode).defaultValues(""); //Define mesh file, that is going to fly out
+        XMLPortParam(ExplosionPart, "minspeed", setMinSpeed, getMinSpeed, xmlelement, mode).defaultValues(50); //Minimum velocity at which parts fly out
+        XMLPortParam(ExplosionPart, "maxspeed", setMaxSpeed, getMaxSpeed, xmlelement, mode).defaultValues(100); //Maximum velocity at which parts fly out, set both minspeed and maxspeed to 0 to have stationary effects
+        XMLPortParam(ExplosionPart, "effect1", setEffect1, getEffect1, xmlelement, mode).defaultValues(""); //particle effect 1
+        XMLPortParam(ExplosionPart, "effect2", setEffect2, getEffect2, xmlelement, mode).defaultValues(""); //particle effect 2
+        XMLPortParam(ExplosionPart, "offset", setOffset, getOffset, xmlelement, mode).defaultValues(Vector3::ZERO); //Offset of the position if you need to have an explosion off-center
+        XMLPortParam(ExplosionPart, "direction", setDirection, getDirection, xmlelement, mode).defaultValues(Vector3(1,1,1)); //general direction the parts fly in
+        XMLPortParam(ExplosionPart, "angle", setAngle, getAngle, xmlelement, mode).defaultValues(180); //defines a cone shape with direction "direction" and angle "angle" inside which the parts fly out of
+        XMLPortParam(ExplosionPart, "delay", setDelay, getDelay, xmlelement, mode).defaultValues(0); //delay to the explosion in seconds
+    }
+
+
+    void ExplosionPart::Explode()
+    {
+        this->destroyTimer_.setTimer(delay_, false, createExecutor(createFunctor(&ExplosionPart::ActuallyExplode, this)));
+    }
+
+    void ExplosionPart::stop()
+    {
+        if (this->effect1Particle_)
+            this->effect1Particle_->setEnabled(false);
+        if (this->effect2Particle_)
+            this->effect2Particle_->setEnabled(false);
+        if (this->model_)
+            this->model_->setVisible(false);
+
+        if (GameMode::isMaster())
+        {
+            this->bStop_ = true;
+            this->destroyTimer_.setTimer(1.0f, false, createExecutor(createFunctor(&ExplosionPart::destroy, this)));
+        }
+    }
+
+    void ExplosionPart::ActuallyExplode()
+    {
+        this->model_->setVisible(true);
+
+        //this->explosionEntity_->setSyncMode(0);
+
+        //this->model_->setSyncMode(0);
+
+
+        if(effect1_ != "")
+        {
+            this->effect1Particle_ = new ParticleInterface(this->getScene()->getSceneManager(), effect1_, this->LOD_);
+            this->effect1Particle_->setDimensions(this->getScale());
+            this->model_->attachOgreObject(this->effect1Particle_->getParticleSystem());
+        }
+
+        if(effect2_ != "")
+        {
+            this->effect2Particle_ = new ParticleInterface(this->getScene()->getSceneManager(), effect2_, this->LOD_);
+            this->effect2Particle_->setDimensions(this->getScale());
+            this->model_->attachOgreObject(this->effect2Particle_->getParticleSystem());
+        }
+
+
+
+
+        Vector3 velocityOffset = direction_.perpendicular();
+        velocityOffset.normalise();
+        Degree offsetDirection = Degree(rnd(0,360));
+        velocityOffset = Quaternion(offsetDirection, direction_.normalisedCopy()) * velocityOffset;
+        velocityOffset.normalise();
+        direction_.normalise();
+
+        Vector3 finalDirection = direction_ + sin((rnd(0, angle_))*math::pi/180)*velocityOffset;
+
+        this->explosionEntity_->setVelocity(finalDirection*rnd(minSpeed_,maxSpeed_));
+        this->explosionEntity_->setAngularVelocity(Vector3(rnd(-1, 1), rnd(-1, 1), rnd(-1, 1)).normalisedCopy() * Degree(400).valueRadians());
+        this->explosionEntity_->setScale(this->getScale() * 4);
+
+
+        this->explosionEntity_->attach(model_);
+
+
+        this->attach(explosionEntity_);
+
+        if (GameMode::isMaster())
+        {
+            this->destroyTimer_.setTimer(rnd(2, 4), false, createExecutor(createFunctor(&ExplosionPart::stop, this)));
+        }
+    }
+
+
+
+
+    void ExplosionPart::setMesh(const std::string& newString)
+    {
+        if(newString != "")
+        {
+            this->mesh_ = newString;
+            this->model_->setMeshSource(mesh_);
+            this->model_->setVisible(false);
+        }
+    }
+
+    void ExplosionPart::setEffect1(const std::string& newString)
+    {
+        this->effect1_ = newString;
+    }
+
+    void ExplosionPart::setEffect2(const std::string& newString)
+    {
+        this->effect2_ = newString;
+    }
+
+    void ExplosionPart::setMinSpeed(float speed)
+    {
+        this->minSpeed_ = speed;
+    }
+
+    void ExplosionPart::setMaxSpeed(float speed)
+    {
+        this->maxSpeed_ = speed;
+    }
+
+    void ExplosionPart::setOffset(Vector3 newVector)
+    {
+        this->posOffset_ = newVector;
+        this->explosionEntity_->setPosition(this->getPosition() + this->posOffset_ / this->getScale());
+    }
+
+    void ExplosionPart::setDirection(Vector3 newDirection)
+    {
+        this->direction_ = newDirection;
+    }
+
+    void ExplosionPart::setAngle(float newAngle)
+    {
+        this->angle_ = newAngle;
+    }
+
+    void ExplosionPart::setDelay(float newDelay)
+    {
+        this->delay_ = newDelay;
+    }
+
+    std::string& ExplosionPart::getMesh()
+    { return this->mesh_; }
+
+    std::string& ExplosionPart::getEffect1()
+    { return this->effect1_; }
+
+    std::string& ExplosionPart::getEffect2()
+    { return this->effect2_; }
+
+    float ExplosionPart::getMinSpeed()
+    {
+        return this->minSpeed_;
+    }
+
+    float ExplosionPart::getMaxSpeed()
+    {
+        return this->maxSpeed_;
+    }
+
+    Vector3 ExplosionPart::getOffset()
+    {
+        return this->posOffset_;
+    }
+
+    Vector3 ExplosionPart::getDirection()
+    {
+        return direction_;
+    }
+
+    float ExplosionPart::getAngle()
+    {
+        return angle_;
+    }
+
+    float ExplosionPart::getDelay()
+    {
+        return delay_;
+    }
+
+
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionPart.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionPart.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/ExplosionPart.h	(revision 11817)
@@ -0,0 +1,109 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Vedat Aydin
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _ExplosionPart_H__
+#define _ExplosionPart_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "graphics/Model.h"
+#include "tools/ParticleInterface.h"
+#include "MovableEntity.h"
+#include "graphics/ParticleSpawner.h"
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "util/Exception.h"
+#include "core/command/Executor.h"
+#include "Scene.h"
+#include "tools/Timer.h"
+
+
+ namespace orxonox
+{
+    class _OrxonoxExport ExplosionPart : public MovableEntity
+    {
+        public:
+            ExplosionPart(Context* context);
+            ~ExplosionPart();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void Explode();
+            void stop();
+            void ActuallyExplode();
+
+            void setMesh(const std::string& newString);
+            std::string& getMesh();
+            void setEffect1(const std::string& newString);
+            std::string& getEffect1();
+            void setEffect2(const std::string& newString);
+            std::string& getEffect2();
+            void setMinSpeed(float speed);
+            float getMinSpeed();
+            void setMaxSpeed(float speed);
+            float getMaxSpeed();
+            void setOffset(Vector3 newVector);
+            Vector3 getOffset();
+            void setDirection(Vector3 newDirection);
+            Vector3 getDirection();
+            void setAngle(float newAgnle);
+            float getAngle();
+            void setDelay(float newDelay);
+            float getDelay();
+         
+
+        private:
+
+            bool bStop_;
+            LODParticle::Value LOD_;
+
+
+            Model* model_;
+            ParticleInterface* effect1Particle_;
+            ParticleInterface* effect2Particle_;
+
+
+            float minSpeed_;
+            float maxSpeed_;
+            std::string mesh_;
+            std::string effect1_;
+            std::string effect2_;
+            Vector3 posOffset_;
+            Vector3 direction_;
+            float angle_;
+            float delay_;
+
+            MovableEntity* explosionEntity_;
+
+            Timer destroyTimer_;
+
+
+
+    };
+}
+
+#endif /* _ExplosionPart_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/MobileEntity.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/MobileEntity.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/MobileEntity.cc	(revision 11817)
@@ -0,0 +1,228 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Martin Stypinski
+ *
+ */
+
+#include "MobileEntity.h"
+
+#include <OgreSceneNode.h>
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(MobileEntity);
+
+    MobileEntity::MobileEntity(Context* context) : WorldEntity(context)
+    {
+        RegisterObject(MobileEntity);
+
+        this->linearAcceleration_  = Vector3::ZERO;
+        this->linearVelocity_      = Vector3::ZERO;
+        this->angularAcceleration_ = Vector3::ZERO;
+        this->angularVelocity_     = Vector3::ZERO;
+    }
+
+    MobileEntity::~MobileEntity()
+    {
+    }
+
+    void MobileEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MobileEntity, XMLPort, xmlelement, mode);
+
+        XMLPortParamTemplate(MobileEntity, "velocity",     setVelocity,     getVelocity,     xmlelement, mode, const Vector3&);
+
+        Vector3 rotationAxis(this->getRotationAxis());
+        Degree rotationRate = this->getRotationRate();
+        XMLPortParamVariable(MobileEntity, "rotationaxis", rotationAxis, xmlelement, mode);
+        XMLPortParamVariable(MobileEntity, "rotationrate", rotationRate, xmlelement, mode);
+        if (mode == XMLPort::LoadObject)
+        {
+            if (rotationAxis == Vector3::ZERO)
+                this->setAngularVelocity(Vector3::ZERO);
+            else
+                this->setAngularVelocity(rotationAxis.normalisedCopy() * rotationRate.valueRadians());
+        }
+    }
+
+    void MobileEntity::tick(float dt)
+    {
+        if (this->isActive())
+        {
+            // Check whether Bullet doesn't do the physics for us
+            if (!this->isDynamic())
+            {
+                // Linear part
+                this->linearVelocity_.x += this->linearAcceleration_.x * dt;
+                this->linearVelocity_.y += this->linearAcceleration_.y * dt;
+                this->linearVelocity_.z += this->linearAcceleration_.z * dt;
+                this->node_->translate(this->linearVelocity_ * dt);
+
+                // Angular part
+                // Note: angularVelocity_ is a Quaternion with w = 0 while angularAcceleration_ is a Vector3
+                this->angularVelocity_.x += angularAcceleration_.x * dt;
+                this->angularVelocity_.y += angularAcceleration_.y * dt;
+                this->angularVelocity_.z += angularAcceleration_.z * dt;
+                // Calculate new orientation with quaternion derivative. This is about 30% faster than with angle/axis method.
+                float mult = dt * 0.5f;
+                // TODO: this could be optimized by writing it out. The calls currently create 4 new Quaternions!
+                Quaternion newOrientation(0.0f, this->angularVelocity_.x * mult, this->angularVelocity_.y * mult, this->angularVelocity_.z * mult);
+                newOrientation = this->node_->getOrientation() + newOrientation * this->node_->getOrientation();
+                newOrientation.normalise();
+                this->node_->setOrientation(newOrientation);
+            }
+        }
+    }
+
+    void MobileEntity::setPosition(const Vector3& position)
+    {
+        if (this->isDynamic())
+        {
+            btTransform transf = this->physicalBody_->getWorldTransform();
+            transf.setOrigin(btVector3(position.x, position.y, position.z));
+            this->physicalBody_->setWorldTransform(transf);
+        }
+
+        this->node_->setPosition(position);
+    }
+
+    void MobileEntity::setOrientation(const Quaternion& orientation)
+    {
+        if (this->isDynamic())
+        {
+            btTransform transf = this->physicalBody_->getWorldTransform();
+            transf.setRotation(btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w));
+            this->physicalBody_->setWorldTransform(transf);
+        }
+
+        this->node_->setOrientation(orientation);
+    }
+
+    void MobileEntity::setVelocity(const Vector3& velocity)
+    {
+        if (this->isDynamic())
+            this->physicalBody_->setLinearVelocity(btVector3(velocity.x, velocity.y, velocity.z));
+
+        this->linearVelocity_ = velocity;
+    }
+
+    void MobileEntity::setAngularVelocity(const Vector3& velocity)
+    {
+        if (this->isDynamic())
+            this->physicalBody_->setAngularVelocity(btVector3(velocity.x, velocity.y, velocity.z));
+
+        this->angularVelocity_ = velocity;
+    }
+
+    void MobileEntity::setAcceleration(const Vector3& acceleration)
+    {
+        if (this->isDynamic())
+        {
+            this->physicalBody_->applyCentralForce(btVector3(acceleration.x * this->getMass(), acceleration.y * this->getMass(), acceleration.z * this->getMass()));
+        }
+
+        // If not bullet-managed (deprecated? SpaceShip doesn't use this anymore for movement) TODO: Find out!
+        this->linearAcceleration_ = acceleration;
+    }
+
+    /**
+    @brief
+        Adds the input acceleration at the input position to the MobileEntity.
+    @param acceleration
+        The acceleration to be additionally applied to the MobileEntity.
+    @param relativePosition
+        The position relative to the MobileEntity at which the acceleration is applied.
+    */
+    void MobileEntity::addAcceleration(const Vector3 &acceleration, const Vector3 &relativePosition)
+    {
+        if(this->isDynamic())
+        {
+            this->physicalBody_->applyForce(this->getMass() * btVector3(acceleration.x, acceleration.y, acceleration.z), btVector3(relativePosition.x, relativePosition.y, relativePosition.z));
+        }
+    }
+
+    void MobileEntity::setAngularAcceleration(const Vector3& acceleration)
+    {
+        if (this->isDynamic())
+        {
+            btVector3 inertia(btVector3(1, 1, 1) / this->physicalBody_->getInvInertiaDiagLocal());
+            this->physicalBody_->applyTorque(btVector3(acceleration.x, acceleration.y, acceleration.z) * inertia);
+        }
+
+        this->angularAcceleration_ = acceleration;
+    }
+
+    void MobileEntity::applyCentralForce(const Vector3& force)
+    {
+        if (this->isDynamic())
+            this->physicalBody_->applyCentralForce(btVector3(force.x * this->getMass(), force.y * this->getMass(), force.z * this->getMass()));
+    }
+
+    bool MobileEntity::isCollisionTypeLegal(WorldEntity::CollisionType type) const
+    {
+        if (type == WorldEntity::CollisionType::Static)
+        {
+            orxout(internal_warning) << "Cannot tell a MobileEntity to have static collision type! Ignoring." << endl;
+            assert(false); // Only in debug mode
+            return false;
+        }
+        else
+            return true;
+    }
+
+    void MobileEntity::setWorldTransform(const btTransform& worldTrans)
+    {
+        // We use a dynamic body. So we translate our node accordingly.
+        this->node_->setPosition(Vector3(worldTrans.getOrigin().x(), worldTrans.getOrigin().y(), worldTrans.getOrigin().z()));
+        btQuaternion temp(worldTrans.getRotation());
+        this->node_->setOrientation(Quaternion(temp.w(), temp.x(), temp.y(), temp.z()));
+        this->linearVelocity_.x = this->physicalBody_->getLinearVelocity().x();
+        this->linearVelocity_.y = this->physicalBody_->getLinearVelocity().y();
+        this->linearVelocity_.z = this->physicalBody_->getLinearVelocity().z();
+        this->angularVelocity_.x = this->physicalBody_->getAngularVelocity().x();
+        this->angularVelocity_.y = this->physicalBody_->getAngularVelocity().y();
+        this->angularVelocity_.z = this->physicalBody_->getAngularVelocity().z();
+    }
+
+    void MobileEntity::getWorldTransform(btTransform& worldTrans) const
+    {
+        // We use a kinematic body
+        worldTrans.setOrigin(btVector3(node_->getPosition().x, node_->getPosition().y, node_->getPosition().z));
+        worldTrans.setRotation(btQuaternion(node_->getOrientation().x, node_->getOrientation().y, node_->getOrientation().z, node_->getOrientation().w));
+        if (this->isDynamic())
+        {
+            // This function gets called only once for dynamic objects to set the initial conditions
+            // We have to set the velocities too.
+            this->physicalBody_->setLinearVelocity(btVector3(linearVelocity_.x, linearVelocity_.y, linearVelocity_.z));
+            this->physicalBody_->setAngularVelocity(btVector3(angularVelocity_.x, angularVelocity_.y, angularVelocity_.z));
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/MobileEntity.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/MobileEntity.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/MobileEntity.h	(revision 11817)
@@ -0,0 +1,125 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Reto Grieder
+ *   Co-authors:
+ *      Martin Stypinski
+ *
+ */
+
+#ifndef _MobileEntity_H__
+#define _MobileEntity_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+#include "tools/interfaces/Tickable.h"
+#include "WorldEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The MobileEntity is a derived class from @ref orxonox::WorldEntity and @ref orxonox::Tickable. It is supposed to be the base class of 
+        @ref orxonox::MovableEntity and @ref orxonox::ControllableEntity. You will never need to instanciate a MobileEntity directly.
+        Use only its derivatives.
+        In addition to the functionalities of the @ref orxonox::WorldEntity this class has a linear and angular velocity and a linear and angular acceleration.
+        Every time the @see tick function is called the linear acceleration is multiplied by the time since the last call of tick and then added to the
+        linear velocity. Then the linear velocity is multiplied by the time since the last call of tick and then added to the position. The same happens with
+        the angular acceleration and velocity. With this procedure MobileEntities can change their position and orientation with time.
+
+        A MobileEntity can only have the collisition type WorldEntity::None, WorldEntity::Dynamic or WorldEntity::Kinematic. The collsion type WorldEntity::Static is illegal.
+    */
+
+    class _OrxonoxExport MobileEntity : public WorldEntity, public Tickable
+    {
+        public:
+            MobileEntity(Context* context);
+            virtual ~MobileEntity();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+            virtual void setPosition(const Vector3& position) override;
+            virtual void setOrientation(const Quaternion& orientation) override;
+
+            virtual void setVelocity(const Vector3& velocity);
+            inline void setVelocity(float x, float y, float z)
+                { this->setVelocity(Vector3(x, y, z)); }
+            virtual inline const Vector3& getVelocity() const override
+                { return this->linearVelocity_; }
+            /**
+            @brief Get the velocity in the coordinate-system of the MoblieEntity.
+            @return Returns the velocity of the MobileEntity in its coordinate-system.
+            */
+            inline Vector3 getLocalVelocity() const
+                { return (this->getOrientation().Inverse() * this->getVelocity()); }
+
+            virtual void setAngularVelocity(const Vector3& velocity);
+            inline void setAngularVelocity(float x, float y, float z)
+                { this->setAngularVelocity(Vector3(x, y, z)); }
+            inline const Vector3& getAngularVelocity() const
+                { return this->angularVelocity_; }
+
+            void setAcceleration(const Vector3& acceleration);
+            inline void setAcceleration(float x, float y, float z)
+                { this->setAcceleration(Vector3(x, y, z)); }
+            inline const Vector3& getAcceleration() const
+                { return this->linearAcceleration_; }
+            void addAcceleration(const Vector3& acceleration, const Vector3 &relativePosition = Vector3::ZERO); // Adds the input acceleration at the input position to the MobileEntity.
+
+            void setAngularAcceleration(const Vector3& acceleration);
+            inline void setAngularAcceleration(float x, float y, float z)
+                { this->setAngularAcceleration(Vector3(x, y, z)); }
+            inline const Vector3& getAngularAcceleration() const
+                { return this->angularAcceleration_; }
+
+            void applyCentralForce(const Vector3& force);
+            inline void applyCentralForce(float x, float y, float z)
+                { this->applyCentralForce(Vector3(x, y, z)); }
+
+            inline void setRotationRate(Degree rate)
+                { this->setAngularVelocity(this->getAngularVelocity().normalisedCopy() * rate.valueRadians()); }
+            inline Degree getRotationRate() const
+                { return Radian(this->getAngularVelocity().length()); }
+
+            inline void setRotationAxis(const Vector3& axis)
+                { this->setAngularVelocity(axis * this->getAngularVelocity().length()); }
+            inline Vector3 getRotationAxis() const
+                { return this->getAngularVelocity().normalisedCopy(); }
+
+        protected:
+            // Bullet btMotionState related
+            virtual void setWorldTransform(const btTransform& worldTrans) override;
+            virtual void getWorldTransform(btTransform& worldTrans) const override;
+
+            Vector3 linearAcceleration_;
+            Vector3 linearVelocity_;
+            Vector3 angularAcceleration_;
+            Vector3 angularVelocity_;
+
+        private:
+            virtual bool isCollisionTypeLegal(WorldEntity::CollisionType type) const override;
+    };
+}
+
+#endif /* _MobileEntity_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/MovableEntity.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/MovableEntity.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/MovableEntity.cc	(revision 11817)
@@ -0,0 +1,119 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "MovableEntity.h"
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "core/command/Executor.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    static const float MAX_RESYNCHRONIZE_TIME = 3.0f;
+    static const float CONTINUOUS_SYNCHRONIZATION_TIME = 10.0f;
+
+    RegisterClass(MovableEntity);
+
+    MovableEntity::MovableEntity(Context* context) : MobileEntity(context)
+    {
+        RegisterObject(MovableEntity);
+
+        this->overwrite_position_    = Vector3::ZERO;
+        this->overwrite_orientation_ = Quaternion::IDENTITY;
+
+        this->continuousResynchroTimer_ = nullptr;
+
+        this->setPriority(Priority::Low);
+
+        this->registerVariables();
+    }
+
+    MovableEntity::~MovableEntity()
+    {
+        if (this->isInitialized())
+            if (this->continuousResynchroTimer_)
+                delete this->continuousResynchroTimer_;
+    }
+
+    void MovableEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(MovableEntity, XMLPort, xmlelement, mode);
+
+        XMLPortParam(MovableEntity, "enablecollisiondamage", setEnableCollisionDamage, getEnableCollisionDamage, xmlelement, mode).defaultValues(false);
+        XMLPortParam(MovableEntity, "collisiondamage", setCollisionDamage, getCollisionDamage, xmlelement, mode).defaultValues(1);
+    }
+
+    bool MovableEntity::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        if (GameMode::isMaster() && enableCollisionDamage_)
+        {
+            Pawn* victim = orxonox_cast<Pawn*>(otherObject);
+            if (victim)
+            {
+                float damage = this->collisionDamage_ * (victim->getVelocity() - this->getVelocity()).length();
+                victim->hit(nullptr, contactPoint, ownCollisionShape, damage);
+            }
+        }
+
+        return false;
+    }
+
+    void MovableEntity::registerVariables()
+    {
+        registerVariable(this->linearVelocity_,        VariableDirection::ToClient, new NetworkCallback<MovableEntity>(this, &MovableEntity::processLinearVelocity));
+        registerVariable(this->angularVelocity_,       VariableDirection::ToClient, new NetworkCallback<MovableEntity>(this, &MovableEntity::processAngularVelocity));
+
+        registerVariable(this->overwrite_position_,    VariableDirection::ToClient, new NetworkCallback<MovableEntity>(this, &MovableEntity::overwritePosition));
+        registerVariable(this->overwrite_orientation_, VariableDirection::ToClient, new NetworkCallback<MovableEntity>(this, &MovableEntity::overwriteOrientation));
+    }
+
+    void MovableEntity::clientConnected(unsigned int clientID)
+    {
+        this->resynchronizeTimer_.setTimer(rnd() * MAX_RESYNCHRONIZE_TIME, false, createExecutor(createFunctor(&MovableEntity::resynchronize, this)));
+    }
+
+    void MovableEntity::clientDisconnected(unsigned int clientID)
+    {
+    }
+
+    void MovableEntity::resynchronize()
+    {
+        if (GameMode::isMaster() && !this->continuousResynchroTimer_)
+        {
+            // Resynchronise every few seconds because we only work with velocities (no positions)
+            continuousResynchroTimer_ = new Timer(CONTINUOUS_SYNCHRONIZATION_TIME + rnd(-1, 1),
+                true, createExecutor(createFunctor(&MovableEntity::resynchronize, this)), false);
+        }
+
+        this->overwrite_position_ = this->getPosition();
+        this->overwrite_orientation_ = this->getOrientation();
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/MovableEntity.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/MovableEntity.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/MovableEntity.h	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _MovableEntity_H__
+#define _MovableEntity_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+#include "network/ClientConnectionListener.h"
+#include "tools/Timer.h"
+#include "MobileEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport MovableEntity : public MobileEntity, public ClientConnectionListener
+    {
+        public:
+            MovableEntity(Context* context);
+            virtual ~MovableEntity();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+
+            using WorldEntity::setPosition;
+            using WorldEntity::setOrientation;
+
+            virtual inline void setPosition(const Vector3& position) override
+                { MobileEntity::setPosition(position); this->overwrite_position_ = this->getPosition(); }
+            virtual inline void setOrientation(const Quaternion& orientation) override
+                { MobileEntity::setOrientation(orientation); this->overwrite_orientation_ = this->getOrientation(); }
+
+            inline void setOwner(Pawn* owner)
+                { this->owner_ = owner; }
+            inline Pawn* getOwner() const
+                { return this->owner_; }
+
+            inline void setCollisionDamage(float c)
+                { this->collisionDamage_ = c; }
+
+            inline float getCollisionDamage()
+                { return this->collisionDamage_; }
+
+            inline void setEnableCollisionDamage(bool c)
+            {
+                this->enableCollisionDamage_ = c;
+                this->enableCollisionCallback();
+            }
+
+            inline bool getEnableCollisionDamage()
+                { return this->enableCollisionDamage_; }
+
+        private:
+            void registerVariables();
+            virtual void clientConnected(unsigned int clientID) override;
+            virtual void clientDisconnected(unsigned int clientID) override;
+            void resynchronize();
+
+            inline void processLinearVelocity()
+                { this->setVelocity(this->linearVelocity_); }
+            inline void processAngularVelocity()
+                { this->setAngularVelocity(this->angularVelocity_); }
+
+            inline void overwritePosition()
+                { this->setPosition(this->overwrite_position_); }
+            inline void overwriteOrientation()
+                { this->setOrientation(this->overwrite_orientation_); }
+
+            Vector3    overwrite_position_;
+            Quaternion overwrite_orientation_;
+
+            Timer resynchronizeTimer_;
+            Timer* continuousResynchroTimer_;
+
+            Pawn* owner_;
+            float collisionDamage_;
+            bool enableCollisionDamage_;
+    };
+}
+
+#endif /* _MovableEntity_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/NameableStaticEntity.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/NameableStaticEntity.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/NameableStaticEntity.cc	(revision 11817)
@@ -0,0 +1,55 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Bolt Nikola
+ *   Co-authors:
+ *      Claudio Fanconi
+ *
+ *
+ *   Authors' Note:
+ *   The following class inherits of its superclass planet
+ *   It is meant only for the Campaign Map
+ *   This subclass of planet has the addition, that they can be labeled ingame, just like bots are in a level gameplay (As it would be nice to see which level you can play)
+ *
+ */
+
+#include "NameableStaticEntity.h"
+
+namespace orxonox
+{
+    RegisterClass(NameableStaticEntity);
+
+
+    NameableStaticEntity::NameableStaticEntity(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(NameableStaticEntity);
+    }
+
+    NameableStaticEntity::~NameableStaticEntity()
+    {
+    }
+
+    void NameableStaticEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode){
+        SUPER(NameableStaticEntity, XMLPort, xmlelement, mode);
+        XMLPortParam(NameableStaticEntity, "levelName", setLevelName, getLevelName, xmlelement, mode);
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/NameableStaticEntity.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/NameableStaticEntity.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/NameableStaticEntity.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Bolt Nikola
+ *   Co-authors:
+ *      Claudio Fanconi
+ *
+ *   This is the header of the NameableStaticEntity.cc file
+ *   In this file we define a constructor, destructor and additional function (which is important to name a planet)
+ *
+ */
+
+#ifndef _NameableStaticEntity_H__
+#define _NameableStaticEntity_H__
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{ 
+    class _OrxonoxExport NameableStaticEntity : public StaticEntity
+    {
+        public:
+            NameableStaticEntity(Context* context);
+            virtual ~NameableStaticEntity();
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setLevelName(const std::string& levelname)
+                { this->levelName_ = levelname; }
+
+            inline const std::string& getLevelName()
+                { return this->levelName_; }
+
+        private:
+            std::string levelName_;
+    };
+}
+#endif
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/SpawnPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/SpawnPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/SpawnPoint.cc	(revision 11817)
@@ -0,0 +1,107 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SpawnPoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+#include "gametypes/Gametype.h"
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox
+{
+    RegisterClass(SpawnPoint);
+
+    SpawnPoint::SpawnPoint(Context* context) : StaticEntity(context)
+    {
+        RegisterObject(SpawnPoint);
+
+        this->template_ = nullptr;
+
+        if (this->getGametype())
+            this->getGametype()->registerSpawnPoint(this);
+        else
+            orxout(internal_error) << "SpawnPoint has no Gametype" << endl;
+
+        this->setSyncMode(ObjectDirection::None);
+    }
+
+    void SpawnPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SpawnPoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(SpawnPoint, "spawnclass", setSpawnClassName, getSpawnClassName, xmlelement, mode);
+        XMLPortParam(SpawnPoint, "pawndesign", setTemplateName, getTemplateName, xmlelement, mode);
+    }
+
+    void SpawnPoint::setSpawnClassName(const std::string& name)
+    {
+        this->spawnclassname_ = name;
+        this->spawnclass_ = ClassByString(name);
+    }
+
+    void SpawnPoint::setTemplateName(const std::string& name)
+    {
+        this->templatename_ = name;
+        this->template_ = Template::getTemplate(name);
+    }
+
+    void SpawnPoint::setTemplate(Template* temp)
+    {
+        this->template_ = temp;
+        this->templatename_ = temp->getName();
+    }
+
+    Pawn* SpawnPoint::spawn()
+    {
+        Pawn* entity = this->spawnclass_.fabricate(this->getContext());
+        if (entity)
+        {
+            this->getGametype()->pawnPreSpawn(entity);
+
+            this->spawn(entity);
+
+            if (this->template_)
+                entity->addTemplate(this->template_);
+
+            entity->postSpawn();
+
+            this->getGametype()->pawnPostSpawn(entity);
+
+            this->fireEvent();
+        }
+        return entity;
+    }
+
+    void SpawnPoint::spawn(ControllableEntity* entity)
+    {
+        entity->setPosition(this->getWorldPosition());
+        entity->setOrientation(this->getWorldOrientation());
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/SpawnPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/SpawnPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/SpawnPoint.h	(revision 11817)
@@ -0,0 +1,76 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SpawnPoint_H__
+#define _SpawnPoint_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include "core/class/SubclassIdentifier.h"
+#include "worldentities/StaticEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport SpawnPoint : public StaticEntity
+    {
+        public:
+            SpawnPoint(Context* context);
+            virtual ~SpawnPoint() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline void setSpawnClass(Identifier* identifier)
+                { this->spawnclass_ = identifier; this->spawnclassname_ = identifier->getName(); }
+            inline Identifier* getSpawnClass() const
+                { return this->spawnclass_; }
+
+            void setTemplate(Template* temp);
+            inline Template* getTemplate() const
+                { return this->template_; }
+
+            virtual Pawn* spawn();
+            void spawn(ControllableEntity* entity);
+
+        private:
+            void setSpawnClassName(const std::string& name);
+            inline const std::string& getSpawnClassName() const
+                { return this->spawnclassname_; }
+
+            void setTemplateName(const std::string& name);
+            inline const std::string& getTemplateName() const
+                { return this->templatename_; }
+
+            SubclassIdentifier<Pawn> spawnclass_;
+            std::string spawnclassname_;
+            Template* template_;
+            std::string templatename_;
+    };
+}
+
+#endif /* _SpawnPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/StaticEntity.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/StaticEntity.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/StaticEntity.cc	(revision 11817)
@@ -0,0 +1,118 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder (physics)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "StaticEntity.h"
+
+#include <OgreSceneNode.h>
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+#include "util/OrxAssert.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    RegisterClass(StaticEntity);
+
+    StaticEntity::StaticEntity(Context* context) : WorldEntity(context)
+    {
+        RegisterObject(StaticEntity);
+
+        this->setPriority(Priority::VeryLow);
+
+        this->registerVariables();
+    }
+
+    StaticEntity::~StaticEntity()
+    {
+    }
+
+    void StaticEntity::registerVariables()
+    {
+        // Ugly const casts, but are valid because position and orientation are not actually const
+        registerVariable(const_cast<Vector3&>(this->getPosition()),    VariableDirection::ToClient, new NetworkCallback<StaticEntity>(this, &StaticEntity::positionChanged));
+        registerVariable(const_cast<Quaternion&>(this->getOrientation()), VariableDirection::ToClient, new NetworkCallback<StaticEntity>(this, &StaticEntity::orientationChanged));
+    }
+
+
+    void StaticEntity::setPosition(const Vector3& position)
+    {
+        if (this->addedToPhysicalWorld())
+        {
+            orxout(internal_warning) << "Attempting to change the position of a StaticEntity at physics run time. Ignoring change." << endl;
+            return;
+        }
+        if (this->isStatic())
+        {
+            btTransform transf = this->physicalBody_->getWorldTransform();
+            transf.setOrigin(btVector3(position.x, position.y, position.z));
+            this->physicalBody_->setWorldTransform(transf);
+        }
+
+        this->node_->setPosition(position);
+    }
+
+    void StaticEntity::setOrientation(const Quaternion& orientation)
+    {
+        if (this->addedToPhysicalWorld())
+        {
+            orxout(internal_warning) << "Attempting to change the orientation of a StaticEntity at physics run time. Ignoring change." << endl;
+            return;
+        }
+        if (this->isStatic())
+        {
+            btTransform transf = this->physicalBody_->getWorldTransform();
+            transf.setRotation(btQuaternion(orientation.x, orientation.y, orientation.z, orientation.w));
+            this->physicalBody_->setWorldTransform(transf);
+        }
+
+        this->node_->setOrientation(orientation);
+    }
+
+    bool StaticEntity::isCollisionTypeLegal(WorldEntity::CollisionType type) const
+    {
+        if (type == WorldEntity::CollisionType::Kinematic || type == WorldEntity::CollisionType::Dynamic)
+        {
+            orxout(internal_warning) << "Cannot tell a StaticEntity to have kinematic or dynamic collision type! Ignoring." << endl;
+            assert(false); // Only in debug mode
+            return false;
+        }
+        else
+            return true;
+    }
+
+    void StaticEntity::setWorldTransform(const btTransform& worldTrans)
+    {
+        OrxAssert(false, "Setting world transform of a StaticEntity, which is CF_STATIC!");
+    }
+
+    void StaticEntity::getWorldTransform(btTransform& worldTrans) const
+    {
+        worldTrans.setOrigin(btVector3(node_->getPosition().x, node_->getPosition().y, node_->getPosition().z));
+        worldTrans.setRotation(btQuaternion(node_->getOrientation().x, node_->getOrientation().y, node_->getOrientation().z, node_->getOrientation().w));
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/StaticEntity.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/StaticEntity.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/StaticEntity.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _StaticEntity_H__
+#define _StaticEntity_H__
+
+#include "OrxonoxPrereqs.h"
+#include "WorldEntity.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The StaticEntity is the simplest derivative of the @ref orxonox::WorldEntity class. This means all StaticEntity instances also have
+        a position in space, a mass, a scale, a frication, ... because every StaticEntity is a WorldEntity. You can attach StaticEntities to eachother ike @ref orxonox::WorldEntity WorldEntities.
+
+        In contrast to the MobileEntity the StaticEntity cannot move with respect to the parent to which it is attached. That's why
+        it is called StaticEntity. It will keep the same position (always with respect to its parent) forever unless you call the
+        function @see setPosition to changee it.
+
+        A StaticEntity can only have the collisition type WorldEntity::None or WorldEntity::Static. The collsion types WorldEntity::Dynamic and WorldEntity::Kinematic are illegal.
+    */
+
+    class _OrxonoxExport StaticEntity : public WorldEntity
+    {
+        public:
+            StaticEntity(Context* context);
+            virtual ~StaticEntity();
+
+            using WorldEntity::setPosition;
+            using WorldEntity::setOrientation;
+
+            virtual void setPosition(const Vector3& position) override;
+            virtual void setOrientation(const Quaternion& orientation) override;
+
+        private:
+            void registerVariables();
+            virtual bool isCollisionTypeLegal(CollisionType type) const override;
+
+            // network callbacks
+            inline void positionChanged()
+                { this->setPosition(this->getPosition()); }
+            inline void orientationChanged()
+                { this->setOrientation(this->getOrientation()); }
+
+            // Bullet btMotionState related
+            virtual void setWorldTransform(const btTransform& worldTrans) override;
+            virtual void getWorldTransform(btTransform& worldTrans) const override;
+    };
+}
+
+#endif /* _StaticEntity_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/TeamSpawnPoint.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/TeamSpawnPoint.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/TeamSpawnPoint.cc	(revision 11817)
@@ -0,0 +1,57 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "TeamSpawnPoint.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(TeamSpawnPoint);
+
+    TeamSpawnPoint::TeamSpawnPoint(Context* context) : SpawnPoint(context)
+    {
+        RegisterObject(TeamSpawnPoint);
+
+        this->teamNumber_ = 0;
+    }
+
+    void TeamSpawnPoint::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(TeamSpawnPoint, XMLPort, xmlelement, mode);
+
+        XMLPortParam(TeamSpawnPoint, "team", setTeamNumber, getTeamNumber, xmlelement, mode).defaultValues(0);
+    }
+    Pawn* TeamSpawnPoint::spawn()
+    {
+        Pawn* entity = SpawnPoint::spawn();
+        static_cast<ControllableEntity*>(entity)->setTeam (this->teamNumber_);
+        return entity;
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/TeamSpawnPoint.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/TeamSpawnPoint.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/TeamSpawnPoint.h	(revision 11817)
@@ -0,0 +1,58 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamSpawnPoint_H__
+#define _TeamSpawnPoint_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "worldentities/pawns/Pawn.h"
+#include "SpawnPoint.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport TeamSpawnPoint : public SpawnPoint
+    {
+        public:
+            TeamSpawnPoint(Context* context);
+            virtual ~TeamSpawnPoint() {}
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            void setTeamNumber(unsigned int team)
+                { this->teamNumber_ = team; }
+            unsigned int getTeamNumber() const
+                { return this->teamNumber_; }
+            virtual Pawn* spawn() override;
+
+        private:
+            int teamNumber_;
+    };
+}
+
+#endif /* _TeamSpawnPoint_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/WorldEntity.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/WorldEntity.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/WorldEntity.cc	(revision 11817)
@@ -0,0 +1,1015 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder (physics)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "WorldEntity.h"
+
+#include <OgreBillboardSet.h>
+#include <OgreCamera.h>
+#include <OgreEntity.h>
+#include <OgreParticleSystem.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "util/OrxAssert.h"
+#include "util/Convert.h"
+#include "util/Exception.h"
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+#include "Scene.h"
+#include "collisionshapes/WorldEntityCollisionShape.h"
+
+namespace orxonox
+{
+    const Vector3 WorldEntity::FRONT = Vector3::NEGATIVE_UNIT_Z;
+    const Vector3 WorldEntity::BACK  = Vector3::UNIT_Z;
+    const Vector3 WorldEntity::LEFT  = Vector3::NEGATIVE_UNIT_X;
+    const Vector3 WorldEntity::RIGHT = Vector3::UNIT_X;
+    const Vector3 WorldEntity::DOWN  = Vector3::NEGATIVE_UNIT_Y;
+    const Vector3 WorldEntity::UP    = Vector3::UNIT_Y;
+
+    // Be sure we don't do bad conversions
+    static_assert((int)Ogre::Node::TS_LOCAL  == (int)WorldEntity::TransformSpace::Local,  "check enum");
+    static_assert((int)Ogre::Node::TS_PARENT == (int)WorldEntity::TransformSpace::Parent, "check enum");
+    static_assert((int)Ogre::Node::TS_WORLD  == (int)WorldEntity::TransformSpace::World,  "check enum");
+
+    RegisterAbstractClass(WorldEntity).inheritsFrom<BaseObject>().inheritsFrom<Synchronisable>();
+
+    /**
+    @brief
+        Creates a new WorldEntity that may immediately be used.
+        All the default values are being set here.
+    */
+    WorldEntity::WorldEntity(Context* context) : BaseObject(context), Synchronisable(context)
+    {
+        RegisterObject(WorldEntity);
+
+        if (!this->getScene() || !this->getScene()->getRootSceneNode())
+            ThrowException(AbortLoading, "Can't create WorldEntity, no scene or no root-scenenode given.");
+
+        this->node_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
+
+        this->parent_ = nullptr;
+        this->parentID_ = OBJECTID_UNKNOWN;
+        this->bDeleteWithParent_ = true;
+
+        this->node_->setPosition(Vector3::ZERO);
+        this->node_->setOrientation(Quaternion::IDENTITY);
+
+        // Activity and visibility memory.
+        this->bActiveMem_ = true;
+        this->bVisibleMem_ = true;
+
+
+        // Default behaviour does not include physics
+        this->physicalBody_   = nullptr;
+        this->bPhysicsActive_ = false;
+        this->bPhysicsActiveSynchronised_    = false;
+        this->bPhysicsActiveBeforeAttaching_ = false;
+        this->collisionShape_ = new WorldEntityCollisionShape(this->getContext());
+        this->collisionShape_->setWorldEntityOwner(this);
+        this->collisionType_             = CollisionType::None;
+        this->collisionTypeSynchronised_ = CollisionType::None;
+        this->mass_                 = 1.0f;
+        this->childrenMass_         = 0;
+        // Using bullet default values
+        this->restitution_          = 0;
+        this->angularFactor_        = 1;
+        this->linearDamping_        = 0;
+        this->angularDamping_       = 0;
+        this->friction_             = 0.5;
+        this->ccdMotionThreshold_   = 0.0;
+        this->ccdSweptSphereRadius_ = 0.0;
+        this->bCollisionCallbackActive_ = false;
+        this->bCollisionResponseActive_ = true;
+
+        this->registerVariables();
+    }
+
+    /**
+    @brief
+        Destroys the WorldEntity AND ALL its children with it.
+    */
+    WorldEntity::~WorldEntity()
+    {
+        if (this->isInitialized())
+        {
+            if (this->parent_)
+                this->detachFromParent();
+
+            std::set<WorldEntity*>::iterator it;
+            while ((it = this->children_.begin()) != this->children_.end())
+            {
+                WorldEntity* entity = *it;
+
+                // do this for all children, because even if getDeleteWithParent() returns true a child might still stay active due to strong pointers pointing to it
+                entity->setPosition(entity->getWorldPosition());
+                this->detach(entity); // detach also erases the element from the children set
+
+                if (entity->getDeleteWithParent())
+                    entity->destroy();
+            }
+
+            if (this->physicalBody_)
+            {
+                this->deactivatePhysics();
+                delete this->physicalBody_;
+            }
+            this->collisionShape_->destroy();
+
+            this->node_->detachAllObjects();
+            this->node_->removeAllChildren();
+
+            OrxAssert(this->getScene()->getSceneManager(), "No SceneManager defined in a WorldEntity.");
+            this->getScene()->getSceneManager()->destroySceneNode(this->node_->getName());
+        }
+    }
+
+    void WorldEntity::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(WorldEntity, XMLPort, xmlelement, mode);
+
+        XMLPortParamTemplate(WorldEntity, "position",    setPosition,    getPosition,    xmlelement, mode, const Vector3&);
+        XMLPortParamTemplate(WorldEntity, "orientation", setOrientation, getOrientation, xmlelement, mode, const Quaternion&);
+        XMLPortParamTemplate(WorldEntity, "scale3D",     setScale3D,     getScale3D,     xmlelement, mode, const Vector3&);
+        XMLPortParam        (WorldEntity, "scale",       setScale,       getScale,       xmlelement, mode);
+        XMLPortParamLoadOnly(WorldEntity, "lookat",      lookAt_xmlport,       xmlelement, mode);
+        XMLPortParamLoadOnly(WorldEntity, "direction",   setDirection_xmlport, xmlelement, mode);
+        XMLPortParamLoadOnly(WorldEntity, "yaw",         yaw_xmlport,          xmlelement, mode);
+        XMLPortParamLoadOnly(WorldEntity, "pitch",       pitch_xmlport,        xmlelement, mode);
+        XMLPortParamLoadOnly(WorldEntity, "roll",        roll_xmlport,         xmlelement, mode);
+        XMLPortParam        (WorldEntity, "deletewithparent", setDeleteWithParent, getDeleteWithParent, xmlelement, mode);
+
+        // Physics
+        XMLPortParam(WorldEntity, "collisionType",     setCollisionTypeStr,  getCollisionTypeStr,  xmlelement, mode);
+        XMLPortParam(WorldEntity, "collisionResponse", setCollisionResponse, hasCollisionResponse, xmlelement, mode);
+        XMLPortParam(WorldEntity, "mass",              setMass,              getMass,              xmlelement, mode);
+        XMLPortParam(WorldEntity, "restitution",       setRestitution,       getRestitution,       xmlelement, mode);
+        XMLPortParam(WorldEntity, "angularFactor",     setAngularFactor,     getAngularFactor,     xmlelement, mode);
+        XMLPortParam(WorldEntity, "linearDamping",     setLinearDamping,     getLinearDamping,     xmlelement, mode);
+        XMLPortParam(WorldEntity, "angularDamping",    setAngularDamping,    getAngularDamping,    xmlelement, mode);
+        XMLPortParam(WorldEntity, "friction",          setFriction,          getFriction,          xmlelement, mode);
+
+        // Other attached WorldEntities
+        XMLPortObject(WorldEntity, WorldEntity, "attached", attach, getAttachedObject, xmlelement, mode);
+        // Attached collision shapes
+        XMLPortObject(WorldEntity, CollisionShape, "collisionShapes", attachCollisionShape, getAttachedCollisionShape, xmlelement, mode);
+    }
+
+    void WorldEntity::registerVariables()
+    {
+        registerVariable(this->mainStateName_,  VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedMainStateName));
+
+        registerVariable(this->bActive_,        VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedActivity));
+        registerVariable(this->bVisible_,       VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::changedVisibility));
+
+        // Ugly const cast, but is valid because the scale is not actually const
+        registerVariable(const_cast<Vector3&>(this->getScale3D()),    VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::scaleChanged));
+
+        // Physics stuff
+        registerVariable(this->mass_,           VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::massChanged));
+        registerVariable(this->restitution_,    VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::restitutionChanged));
+        registerVariable(this->angularFactor_,  VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::angularFactorChanged));
+        registerVariable(this->linearDamping_,  VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::linearDampingChanged));
+        registerVariable(this->angularDamping_, VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::angularDampingChanged));
+        registerVariable(this->friction_,       VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::frictionChanged));
+        registerVariable(this->ccdMotionThreshold_,
+                                                VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::ccdMotionThresholdChanged));
+        registerVariable(this->ccdSweptSphereRadius_,
+                                                VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::ccdSweptSphereRadiusChanged));
+        registerVariable(this->bCollisionCallbackActive_,
+                                                VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::collisionCallbackActivityChanged));
+        registerVariable(this->bCollisionResponseActive_,
+                                                VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::collisionResponseActivityChanged));
+        registerVariable(this->collisionTypeSynchronised_,
+                                                VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::collisionTypeChanged));
+        registerVariable(this->bPhysicsActiveSynchronised_,
+                                                VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::physicsActivityChanged));
+
+        // Attach to parent if necessary
+        registerVariable(this->parentID_,       VariableDirection::ToClient, new NetworkCallback<WorldEntity>(this, &WorldEntity::networkcallback_parentChanged));
+    }
+
+    /**
+    @brief
+        When the activity is changed, it is changed for all attached objects as well.
+    */
+    void WorldEntity::changedActivity(void)
+    {
+        SUPER(WorldEntity, changedActivity);
+
+        if(GameMode::isMaster())
+        {
+            // physics is only enabled if the WorldEntity is active
+            if (this->isActive())
+                this->activatePhysics();
+            else
+                this->deactivatePhysics();
+
+            // iterate over all children and change their activity as well
+            for (WorldEntity* object : this->getAttachedObjects())
+            {
+                if(!this->isActive())
+                {
+                    object->bActiveMem_ = object->isActive();
+                    object->setActive(this->isActive());
+                }
+                else
+                {
+                    object->setActive(object->bActiveMem_);
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        When the visibility is changed, it is changed for all attached objects as well.
+    */
+    void WorldEntity::changedVisibility(void)
+    {
+        SUPER(WorldEntity, changedVisibility);
+
+        if(GameMode::isMaster())
+        {
+            // iterate over all children and change their visibility as well
+            for (WorldEntity* object : this->getAttachedObjects())
+            {
+                if(!this->isVisible())
+                {
+                    object->bVisibleMem_ = object->isVisible();
+                    object->setVisible(this->isVisible());
+                }
+                else
+                {
+                    object->setVisible(object->bVisibleMem_);
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        Network function that object this instance to its correct parent.
+    */
+    void WorldEntity::networkcallback_parentChanged()
+    {
+        if (this->parentID_ != OBJECTID_UNKNOWN)
+        {
+            WorldEntity* parent = orxonox_cast<WorldEntity*>(Synchronisable::getSynchronisable(this->parentID_));
+            if (parent)
+                this->attachToParent(parent);
+        }
+    }
+
+    /**
+    @brief
+        Attaches this object to a parent SceneNode.
+    @remarks
+        Only use this method if you know exactly what you're doing!
+        Normally, attaching works internally by attaching WE's.
+    */
+    void WorldEntity::attachToNode(Ogre::SceneNode* node)
+    {
+        Ogre::Node* parent = this->node_->getParent();
+        if (parent)
+            parent->removeChild(this->node_);
+        node->addChild(this->node_);
+    }
+
+    /**
+    @brief
+        Detaches this object from a parent SceneNode.
+    @remarks
+        Only use this method if you know exactly what you're doing!
+        Normally, attaching works internally by attaching WE's.
+    */
+    void WorldEntity::detachFromNode(Ogre::SceneNode* node)
+    {
+        node->removeChild(this->node_);
+//        this->getScene()->getRootSceneNode()->addChild(this->node_);
+    }
+
+    /**
+    @brief
+        Network callback for the collision type. Only change the type if it was valid.
+    */
+    void WorldEntity::collisionTypeChanged()
+    {
+        if (this->collisionTypeSynchronised_ != CollisionType::Dynamic &&
+            this->collisionTypeSynchronised_ != CollisionType::Kinematic &&
+            this->collisionTypeSynchronised_ != CollisionType::Static &&
+            this->collisionTypeSynchronised_ != CollisionType::None)
+        {
+            orxout(internal_error) << "Error when collsion Type was received over network. Unknown enum value:" << this->collisionTypeSynchronised_ << endl;
+        }
+        else if (this->collisionTypeSynchronised_ != collisionType_)
+        {
+            if (this->parent_)
+                orxout(internal_warning) << "Network connection tried to set the collision type of an attached WE. Ignoring." << endl;
+            else
+                this->setCollisionType(this->collisionTypeSynchronised_);
+        }
+    }
+
+    //! Network callback for this->bPhysicsActive_
+    void WorldEntity::physicsActivityChanged()
+    {
+        if (this->bPhysicsActiveSynchronised_)
+            this->activatePhysics();
+        else
+            this->deactivatePhysics();
+    }
+
+    //! Function sets whether Bullet should issue a callback on collisions
+    void WorldEntity::collisionCallbackActivityChanged()
+    {
+        if (this->hasPhysics())
+        {
+            if (this->bCollisionCallbackActive_)
+                this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() |
+                    btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+            else
+                this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() &
+                    ~btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+        }
+    }
+
+    //! Function sets whether Bullet should react itself to a collision
+    void WorldEntity::collisionResponseActivityChanged()
+    {
+        if (this->hasPhysics())
+        {
+            if (this->bCollisionResponseActive_)
+                this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() &
+                    ~btCollisionObject::CF_NO_CONTACT_RESPONSE);
+            else
+                this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() |
+                    btCollisionObject::CF_NO_CONTACT_RESPONSE);
+        }
+    }
+
+    /**
+    @brief
+        Attaches a child WorldEntity to this object. This calls notifyBeingAttached()
+        of the child WE.
+    @note
+        The collision shape of the child object gets attached nevertheless. That also means
+        that you can change the collision shape of the child and it correctly cascadeds the changes to this instance.
+        Be aware of this implication: When implementing attaching of kinematic objects to others, you have to change
+        this behaviour because you then might not want to merge the collision shapes.
+    */
+    void WorldEntity::attach(WorldEntity* object)
+    {
+        if (object == this)
+        {
+            orxout(internal_warning) << "Can't attach a WorldEntity to itself." << endl;
+            return;
+        }
+
+        if (!object->notifyBeingAttached(this))
+            return;
+
+        this->attachNode(object->node_);
+        this->children_.insert(object);
+
+        this->attachCollisionShape(object->collisionShape_);
+        // mass
+        this->childrenMass_ += object->getMass();
+        recalculateMassProps();
+    }
+
+    /**
+    @brief
+        Function gets called when this object is being attached to a new parent.
+
+        This operation is only allowed if the collision types "like" each other.
+        - You cannot a attach a non physical object to a physical one.
+        - Dynamic object can NOT be attached at all.
+        - It is also not possible to attach a kinematic to a dynamic one.
+        - Attaching of kinematic objects otherwise is not yet supported.
+    */
+    bool WorldEntity::notifyBeingAttached(WorldEntity* newParent)
+    {
+        // check first whether attaching is even allowed
+        if (this->hasPhysics())
+        {
+            if (!newParent->hasPhysics())
+            {
+                orxout(internal_warning) << " Cannot attach a physical object to a non physical one." << endl;
+                return false;
+            }
+            else if (this->isDynamic())
+            {
+                orxout(internal_warning) << "Cannot attach a dynamic object to a WorldEntity." << endl;
+                return false;
+            }
+            else if (this->isKinematic() && newParent->isDynamic())
+            {
+                orxout(internal_warning) << "Cannot attach a kinematic object to a dynamic one." << endl;
+                return false;
+            }
+            else if (this->isKinematic())
+            {
+                orxout(internal_warning) << "Cannot attach a kinematic object to a static or kinematic one: Not yet implemented." << endl;
+                return false;
+            }
+        }
+
+        if (this->isPhysicsActive())
+            this->bPhysicsActiveBeforeAttaching_ = true;
+        this->deactivatePhysics();
+
+        if (this->parent_)
+            this->detachFromParent();
+
+        this->parent_ = newParent;
+        this->parentID_ = newParent->getObjectID();
+
+        this->parentChanged();
+
+        // apply transform to collision shape
+        this->collisionShape_->setPosition(this->getPosition());
+        this->collisionShape_->setOrientation(this->getOrientation());
+        // TODO: Scale
+
+        return true;
+    }
+
+    /**
+    @brief
+        Detaches a child WorldEntity from this instance.
+    */
+    void WorldEntity::detach(WorldEntity* object)
+    {
+        std::set<WorldEntity*>::iterator it = this->children_.find(object);
+        if (it == this->children_.end())
+        {
+            orxout(internal_warning) << "Cannot detach an object that is not a child." << endl;
+            return;
+        }
+
+        // collision shapes
+        this->detachCollisionShape(object->collisionShape_);
+
+        // mass
+        if (object->getMass() > 0.0f)
+        {
+            this->childrenMass_ -= object->getMass();
+            recalculateMassProps();
+        }
+
+        this->detachNode(object->node_);
+        this->children_.erase(it);
+
+        object->notifyDetached();
+    }
+
+    /**
+    @brief
+        Function gets called when the object has been detached from its parent.
+    */
+    void WorldEntity::notifyDetached()
+    {
+        this->parent_ = nullptr;
+        this->parentID_ = OBJECTID_UNKNOWN;
+
+        this->parentChanged();
+
+        // reset orientation of the collisionShape (cannot be set within a WE usually)
+        this->collisionShape_->setPosition(Vector3::ZERO);
+        this->collisionShape_->setOrientation(Quaternion::IDENTITY);
+        // TODO: Scale
+
+        if (this->bPhysicsActiveBeforeAttaching_)
+        {
+            this->activatePhysics();
+            this->bPhysicsActiveBeforeAttaching_ = false;
+        }
+    }
+
+    //! Returns an attached object (merely for XMLPort).
+    WorldEntity* WorldEntity::getAttachedObject(unsigned int index)
+    {
+        unsigned int i = 0;
+        for (WorldEntity* child : this->children_)
+        {
+            if (i == index)
+                return child;
+            ++i;
+        }
+        return nullptr;
+    }
+
+    //! Attaches an Ogre::SceneNode to this WorldEntity.
+    void WorldEntity::attachNode(Ogre::SceneNode* node)
+    {
+        Ogre::Node* parent = node->getParent();
+        if (parent)
+            parent->removeChild(node);
+        this->node_->addChild(node);
+    }
+
+    //! Detaches an Ogre::SceneNode from this WorldEntity.
+    void WorldEntity::detachNode(Ogre::SceneNode* node)
+    {
+        this->node_->removeChild(node);
+//        this->getScene()->getRootSceneNode()->addChild(node);
+    }
+
+    //! Attaches an Ogre::MovableObject to this WorldEntity.
+    void WorldEntity::attachOgreObject(Ogre::MovableObject* object)
+    {
+        this->node_->attachObject(object);
+        object->setUserAny(Ogre::Any(static_cast<OrxonoxClass*>(this)));
+    }
+
+    void WorldEntity::attachOgreObject(Ogre::BillboardSet* object)
+        { this->attachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+    void WorldEntity::attachOgreObject(Ogre::Camera* object)
+        { this->attachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+    void WorldEntity::attachOgreObject(Ogre::Entity* object)
+        { this->attachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+    void WorldEntity::attachOgreObject(Ogre::ParticleSystem* object)
+        { this->attachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+
+    //! Detaches an Ogre::MovableObject from this WorldEntity.
+    void WorldEntity::detachOgreObject(Ogre::MovableObject* object)
+    {
+        object->setUserAny(Ogre::Any(static_cast<OrxonoxClass*>(nullptr)));
+        this->node_->detachObject(object);
+    }
+
+    void WorldEntity::detachOgreObject(Ogre::BillboardSet* object)
+        { this->detachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+    void WorldEntity::detachOgreObject(Ogre::Camera* object)
+        { this->detachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+    void WorldEntity::detachOgreObject(Ogre::Entity* object)
+        { this->detachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+    void WorldEntity::detachOgreObject(Ogre::ParticleSystem* object)
+        { this->detachOgreObject(static_cast<Ogre::MovableObject*>(object)); }
+
+    //! Detaches an Ogre::MovableObject (by string) from this WorldEntity.
+    Ogre::MovableObject* WorldEntity::detachOgreObject(const Ogre::String& name)
+    {
+        return this->node_->detachObject(name);
+    }
+
+    //! Attaches a collision Shape to this object (delegated to the internal CompoundCollisionShape)
+    void WorldEntity::attachCollisionShape(CollisionShape* shape)
+    {
+        this->collisionShape_->attach(shape);
+        // Note: this->collisionShape_ already notifies us of any changes.
+    }
+
+    //! Detaches a collision Shape from this object (delegated to the internal CompoundCollisionShape)
+    void WorldEntity::detachCollisionShape(CollisionShape* shape)
+    {
+        // Note: The collision shapes may not be detached with this function!
+        this->collisionShape_->detach(shape);
+        // Note: this->collisionShape_ already notifies us of any changes.
+    }
+
+    //! Returns an attached collision Shape of this object (delegated to the internal CompoundCollisionShape)
+    CollisionShape* WorldEntity::getAttachedCollisionShape(unsigned int index)
+    {
+        return this->collisionShape_->getAttachedShape(index);
+    }
+
+    // Note: These functions are placed in WorldEntity.h as inline functions for the release build.
+#ifndef ORXONOX_RELEASE
+    const Vector3& WorldEntity::getPosition() const
+    {
+        return this->node_->getPosition();
+    }
+
+    const Quaternion& WorldEntity::getOrientation() const
+    {
+        return this->node_->getOrientation();
+    }
+
+    const Vector3& WorldEntity::getScale3D() const
+    {
+        return this->node_->getScale();
+    }
+#endif
+
+    //! Returns the position relative to the root space
+    const Vector3& WorldEntity::getWorldPosition() const
+    {
+        return this->node_->_getDerivedPosition();
+    }
+
+    //! Returns the orientation relative to the root space
+    const Quaternion& WorldEntity::getWorldOrientation() const
+    {
+        return this->node_->_getDerivedOrientation();
+    }
+
+    //! Returns the scaling applied relative to the root space in 3 coordinates
+    const Vector3& WorldEntity::getWorldScale3D() const
+    {
+        return this->node_->_getDerivedScale();
+    }
+
+    /**
+    @brief
+        Returns the scaling applied relative to the root space in 3 coordinates
+    @return
+        Returns the scaling if it is uniform, 1.0f otherwise.
+    */
+    float WorldEntity::getWorldScale() const
+    {
+        Vector3 scale = this->getWorldScale3D();
+        return (scale.x == scale.y && scale.x == scale.z) ? scale.x : 1;
+    }
+
+    /**
+    @brief
+        Sets the three dimensional scaling of this object.
+    @note
+        Scaling physical objects has not yet been implemented and is therefore forbidden.
+    */
+    void WorldEntity::setScale3D(const Vector3& scale)
+    {
+        // If physics is enabled scale the attached CollisionShape.
+        /*if (this->hasPhysics() && this->collisionShape_ != nullptr)
+        {
+            this->collisionShape_->setScale3D(scale);
+        }*/
+
+        this->node_->setScale(scale);
+
+        this->changedScale();
+    }
+
+    /**
+    @brief
+        Translates this WorldEntity by a vector.
+    @param distance
+        The relative distance of the translation
+    @param relativeTo
+        The TransformSpace of this translation
+    */
+    void WorldEntity::translate(const Vector3& distance, TransformSpace relativeTo)
+    {
+        switch (relativeTo)
+        {
+        case TransformSpace::Local:
+            // position is relative to parent so transform downwards
+            this->setPosition(this->getPosition() + this->getOrientation() * distance);
+            break;
+        case TransformSpace::Parent:
+            this->setPosition(this->getPosition() + distance);
+            break;
+        case TransformSpace::World:
+            // position is relative to parent so transform upwards
+            if (this->node_->getParent())
+                setPosition(getPosition() + (node_->getParent()->_getDerivedOrientation().Inverse() * distance)
+                    / node_->getParent()->_getDerivedScale());
+            else
+                this->setPosition(this->getPosition() + distance);
+            break;
+        }
+    }
+
+    /**
+    @brief
+        Rotates this WorldEntity by a quaternion.
+    @param rotation
+        The desired relative rotation
+    @param relativeTo
+        The TransformSpace of this translation
+    */
+    void WorldEntity::rotate(const Quaternion& rotation, TransformSpace relativeTo)
+    {
+        switch(relativeTo)
+        {
+        case TransformSpace::Local:
+            this->setOrientation(this->getOrientation() * rotation);
+            break;
+        case TransformSpace::Parent:
+            // Rotations are normally relative to local axes, transform up
+            this->setOrientation(rotation * this->getOrientation());
+            break;
+        case TransformSpace::World:
+            // Rotations are normally relative to local axes, transform up
+            this->setOrientation(this->getOrientation() * this->getWorldOrientation().Inverse()
+                * rotation * this->getWorldOrientation());
+            break;
+        }
+    }
+
+    /**
+    @brief
+        Makes this WorldEntity look at a specific target location.
+    @param target
+        An absolute point in the space which defines the direction of the entity
+    @param relativeTo
+        The TransformSpace of this translation
+    @param localDirectionVector
+        The vector which normally describes the natural direction of the object, usually -Z.
+    */
+    void WorldEntity::lookAt(const Vector3& target, TransformSpace relativeTo, const Vector3& localDirectionVector)
+    {
+        Vector3 origin(0, 0, 0);
+        switch (relativeTo)
+        {
+        case TransformSpace::Local:
+            origin = Vector3::ZERO;
+            break;
+        case TransformSpace::Parent:
+            origin = this->getPosition();
+            break;
+        case TransformSpace::World:
+            origin = this->getWorldPosition();
+            break;
+        }
+        this->setDirection(target - origin, relativeTo, localDirectionVector);
+    }
+
+    /**
+    @brief
+        Makes this WorldEntity look in specific direction.
+    @param direction
+        A point relative to the position of the WorldEntity which defines its orientation
+    @param relativeTo
+        The TransformSpace of this translation
+    @param localDirectionVector
+        The vector which normally describes the natural direction of the object, usually -Z.
+    */
+    void WorldEntity::setDirection(const Vector3& direction, TransformSpace relativeTo, const Vector3& localDirectionVector)
+    {
+        Quaternion savedOrientation(this->getOrientation());
+        this->node_->setDirection(direction, static_cast<Ogre::Node::TransformSpace>(relativeTo), localDirectionVector);
+        Quaternion newOrientation(this->node_->getOrientation());
+        this->node_->setOrientation(savedOrientation);
+        this->setOrientation(newOrientation);
+    }
+
+    //! Activates physics if the CollisionType is not None.
+    void WorldEntity::activatePhysics()
+    {
+        if (this->isActive() && this->hasPhysics() && !this->isPhysicsActive() && !this->parent_)
+        {
+            this->getScene()->addPhysicalObject(this);
+            this->bPhysicsActive_ = true;
+            this->bPhysicsActiveSynchronised_ = true;
+        }
+    }
+
+    //! Deactivates physics but the CollisionType does not change.
+    void WorldEntity::deactivatePhysics()
+    {
+        if (this->isPhysicsActive())
+        {
+            this->getScene()->removePhysicalObject(this);
+            this->bPhysicsActive_ = false;
+            this->bPhysicsActiveSynchronised_ = false;
+        }
+    }
+
+    //! Tells whether the object has already been added to the Bullet physics World.
+    bool WorldEntity::addedToPhysicalWorld() const
+    {
+        return this->physicalBody_ && this->physicalBody_->isInWorld();
+    }
+
+    /**
+    @brief
+        Sets the CollisionType. This alters the object significantly!
+    @note
+        Operation does not work on attached WorldEntities.
+    */
+    void WorldEntity::setCollisionType(CollisionType type)
+    {
+        if (this->collisionType_ == type)
+            return;
+
+        // If we are already attached to a parent, this would be a bad idea..
+        if (this->parent_)
+        {
+            orxout(internal_warning) << "Cannot set the collision type of a WorldEntity with a parent." << endl;
+            return;
+        }
+
+        // Check for type legality. Could be StaticEntity or MobileEntity.
+        if (!this->isCollisionTypeLegal(type))
+            return;
+
+        if (this->isPhysicsActive())
+            this->deactivatePhysics();
+
+        bool bReactivatePhysics = true;
+        if (this->hasPhysics() && !this->isPhysicsActive())
+            bReactivatePhysics = false;
+
+        // Check whether we have to create or destroy.
+        if (type != CollisionType::None && this->collisionType_ == CollisionType::None)
+        {
+/*
+HACK HACK HACK
+            // Check whether there was some scaling applied.
+            if (!this->node_->getScale().positionEquals(Vector3(1, 1, 1), 0.001))
+            {
+                orxout(internal_warning) << "Cannot create a physical body if there is scaling applied to the node: Not yet implemented." << endl;
+                return;
+            }
+HACK HACK HACK
+*/
+            // Create new rigid body
+            btRigidBody::btRigidBodyConstructionInfo bodyConstructionInfo(0, this, this->collisionShape_->getCollisionShape());
+            this->physicalBody_ = new btRigidBody(bodyConstructionInfo);
+            this->physicalBody_->setUserPointer(this);
+            this->physicalBody_->setActivationState(DISABLE_DEACTIVATION);
+        }
+        else if (type == CollisionType::None && this->collisionType_ != CollisionType::None)
+        {
+            // Destroy rigid body
+            assert(this->physicalBody_);
+            deactivatePhysics();
+            delete this->physicalBody_;
+            this->physicalBody_ = nullptr;
+            this->collisionType_ = CollisionType::None;
+            this->collisionTypeSynchronised_ = CollisionType::None;
+            return;
+        }
+
+        // Change type
+        switch (type)
+        {
+        case CollisionType::Dynamic:
+            this->physicalBody_->setCollisionFlags(this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_STATIC_OBJECT & !btCollisionObject::CF_KINEMATIC_OBJECT);
+            break;
+        case CollisionType::Kinematic:
+            this->physicalBody_->setCollisionFlags((this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_STATIC_OBJECT) | btCollisionObject::CF_KINEMATIC_OBJECT);
+            break;
+        case CollisionType::Static:
+            this->physicalBody_->setCollisionFlags((this->physicalBody_->getCollisionFlags() & !btCollisionObject::CF_KINEMATIC_OBJECT) | btCollisionObject::CF_STATIC_OBJECT);
+            break;
+        case CollisionType::None:
+            assert(false); // Doesn't happen
+            return;
+        }
+        this->collisionType_ = type;
+        this->collisionTypeSynchronised_ = type;
+
+        // update mass and inertia tensor
+        recalculateMassProps();
+        internalSetPhysicsProps();
+        collisionCallbackActivityChanged();
+        collisionResponseActivityChanged();
+        if (bReactivatePhysics)
+            activatePhysics();
+    }
+
+    //! Sets the CollisionType by string (used for the XMLPort)
+    void WorldEntity::setCollisionTypeStr(const std::string& typeStr)
+    {
+        const std::string& typeStrLower = getLowercase(typeStr);
+        CollisionType type;
+        if (typeStrLower == "dynamic")
+            type = CollisionType::Dynamic;
+        else if (typeStrLower == "static")
+            type = CollisionType::Static;
+        else if (typeStrLower == "kinematic")
+            type = CollisionType::Kinematic;
+        else if (typeStrLower == "none")
+            type = CollisionType::None;
+        else
+            ThrowException(ParseError, std::string("Attempting to set an unknown collision type: '") + typeStr + "'.");
+        this->setCollisionType(type);
+    }
+
+    //! Gets the CollisionType by string (used for the XMLPort)
+    std::string WorldEntity::getCollisionTypeStr() const
+    {
+        switch (this->getCollisionType())
+        {
+            case CollisionType::Dynamic:
+                return "dynamic";
+            case CollisionType::Kinematic:
+                return "kinematic";
+            case CollisionType::Static:
+                return "static";
+            case CollisionType::None:
+                return "none";
+            default:
+                assert(false);
+                return "";
+        }
+    }
+
+    /**
+    @brief
+        Recalculates the accumulated child mass and calls recalculateMassProps()
+        and notifies the parent of the change.
+    @note
+        Called by a child WE
+    */
+    void WorldEntity::notifyChildMassChanged()
+    {
+        // Note: CollisionShape changes of a child get handled over the internal CompoundCollisionShape already
+        // Recalculate mass
+        this->childrenMass_ = 0.0f;
+        for (WorldEntity* child : this->children_)
+            this->childrenMass_ += child->getMass();
+        recalculateMassProps();
+        // Notify parent WE
+        if (this->parent_)
+            parent_->notifyChildMassChanged();
+    }
+
+    /**
+    @brief
+        Undertakes the necessary steps to change the collision shape in Bullet, even at runtime.
+    @note
+        - called by this->collisionShape_
+        - May have a REALLY big overhead when called continuously at runtime, because then we need
+          to remove the physical body from Bullet and add it again.
+    */
+    void WorldEntity::notifyCollisionShapeChanged()
+    {
+        if (hasPhysics())
+        {
+            // Bullet doesn't like sudden changes of the collision shape, so we remove and add it again
+            if (this->addedToPhysicalWorld())
+            {
+                this->deactivatePhysics();
+                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
+                this->activatePhysics();
+            }
+            else
+                this->physicalBody_->setCollisionShape(this->collisionShape_->getCollisionShape());
+        }
+        recalculateMassProps();
+    }
+
+    //! Updates all mass dependent parameters (mass, inertia tensor and child mass)
+    void WorldEntity::recalculateMassProps()
+    {
+        // Store local inertia for faster access. Evaluates to (0,0,0) if there is no collision shape.
+        float totalMass = this->mass_ + this->childrenMass_;
+        this->collisionShape_->calculateLocalInertia(totalMass, this->localInertia_);
+        if (this->hasPhysics())
+        {
+            if (this->isStatic())
+            {
+                // Just set everything to zero
+                this->physicalBody_->setMassProps(0.0f, btVector3(0, 0, 0));
+            }
+            else if (totalMass == 0.0f)
+            {
+                // Use default values to avoid very large or very small values
+                orxout(internal_warning) << "Setting the internal physical mass to 1.0 because mass_ is 0.0" << endl;
+                btVector3 inertia(0, 0, 0);
+                this->collisionShape_->calculateLocalInertia(1.0f, inertia);
+                this->physicalBody_->setMassProps(1.0f, inertia);
+            }
+            else
+            {
+                this->physicalBody_->setMassProps(totalMass, this->localInertia_);
+            }
+        }
+    }
+
+    //! Copies our own parameters for restitution, angular factor, damping and friction to the bullet rigid body.
+    void WorldEntity::internalSetPhysicsProps()
+    {
+        if (this->hasPhysics())
+        {
+            this->physicalBody_->setRestitution(this->restitution_);
+            this->physicalBody_->setAngularFactor(this->angularFactor_);
+            this->physicalBody_->setDamping(this->linearDamping_, this->angularDamping_);
+            this->physicalBody_->setFriction(this->friction_);
+            this->physicalBody_->setCcdMotionThreshold(this->ccdMotionThreshold_);
+            this->physicalBody_->setCcdSweptSphereRadius(this->ccdSweptSphereRadius_);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/WorldEntity.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/WorldEntity.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/WorldEntity.h	(revision 11817)
@@ -0,0 +1,516 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *      Reto Grieder (physics)
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _WorldEntity_H__
+#define _WorldEntity_H__
+
+#include "OrxonoxPrereqs.h"
+
+#ifdef ORXONOX_RELEASE
+#  include <OgreSceneNode.h>
+#endif
+#include <LinearMath/btMotionState.h>
+#include <LinearMath/btAlignedAllocator.h>
+
+#include "util/Math.h"
+#include "util/OgreForwardRefs.h"
+#include "core/BaseObject.h"
+#include "network/synchronisable/Synchronisable.h"
+
+namespace orxonox
+{
+    /**
+    @brief
+        The WorldEntity represents everything that can be put in a Scene at a certain location.
+
+        It is supposed to be the base class of everything you would call an 'object' in a Scene.
+        The class itself is abstract which means you cannot use it directly. You may use StaticEntity
+        as the simplest derivative or (derived from MobileEntity) MovableEntity and ControllableEntity
+        as more advanced ones.
+
+        The basic task of the WorldEntity is provide a location, a direction and a scaling and the possibility
+        to create an entire hierarchy of derived objects.
+        It is also the basis for the physics interface to the Bullet physics engine.
+        Every WorldEntity can have a specific collision type: @see CollisionType
+        This would then imply that every scene object could have any collision type. To limit this, you can always
+        override this->isCollisionTypeLegal(CollisionType). Return false if the collision type is not supported
+        for a specific object.
+        There is also support for attaching WorldEntities with physics to each other. Currently, the collision shape
+        of both objects simply get merged into one larger shape (for static collision type).
+        The physical body that is internally stored and administrated has the following supported properties:
+        - Restitution, angular factor, linear damping, angular damping, friction, mass and collision shape.
+        You can get more information at the corresponding set function.
+
+        Collision shapes: These are controlled by the internal WorldEntityCollisionShape. @see WorldEntityCollisionShape.
+    */
+    class _OrxonoxExport WorldEntity : public BaseObject, public Synchronisable, public btMotionState
+    {
+        friend class Scene;
+
+        public:
+            BT_DECLARE_ALIGNED_ALLOCATOR();
+
+            // Define our own transform space enum to avoid Ogre includes here
+            /**
+            @brief
+                Enumeration denoting the spaces which a transform can be relative to.
+            */
+            enum class TransformSpace
+            {
+                //! Transform is relative to the local space
+                Local,
+                //! Transform is relative to the space of the parent node
+                Parent,
+                //! Transform is relative to world space
+                World
+            };
+
+        public:
+            WorldEntity(Context* context);
+            virtual ~WorldEntity();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+
+            inline const Ogre::SceneNode* getNode() const
+                { return this->node_; }
+
+            static const Vector3 FRONT;
+            static const Vector3 BACK;
+            static const Vector3 LEFT;
+            static const Vector3 RIGHT;
+            static const Vector3 DOWN;
+            static const Vector3 UP;
+
+            virtual void changedActivity(void) override;
+            virtual void changedVisibility(void) override;
+
+            virtual void setPosition(const Vector3& position) = 0;
+            inline void setPosition(float x, float y, float z)
+                { this->setPosition(Vector3(x, y, z)); }
+            const Vector3& getPosition() const;
+            const Vector3& getWorldPosition() const;
+
+            void translate(const Vector3& distance, TransformSpace relativeTo = TransformSpace::Parent);
+            inline void translate(float x, float y, float z, TransformSpace relativeTo = TransformSpace::Parent)
+                { this->translate(Vector3(x, y, z), relativeTo); }
+
+            virtual inline const Vector3& getVelocity() const
+                { return Vector3::ZERO; }
+
+            virtual void setOrientation(const Quaternion& orientation) = 0;
+            inline void setOrientation(float w, float x, float y, float z)
+                { this->setOrientation(Quaternion(w, x, y, z)); }
+            inline void setOrientation(const Vector3& axis, const Radian& angle)
+                { this->setOrientation(Quaternion(angle, axis)); }
+            inline void setOrientation(const Vector3& axis, const Degree& angle)
+                { this->setOrientation(Quaternion(angle, axis)); }
+            const Quaternion& getOrientation() const;
+            const Quaternion& getWorldOrientation() const;
+
+            void rotate(const Quaternion& rotation, TransformSpace relativeTo = TransformSpace::Local);
+            inline void rotate(const Vector3& axis, const Degree& angle, TransformSpace relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, axis), relativeTo); }
+
+            inline void yaw(const Degree& angle, TransformSpace relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, Vector3::UNIT_Y), relativeTo); }
+            inline void pitch(const Degree& angle, TransformSpace relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, Vector3::UNIT_X), relativeTo); }
+            inline void roll(const Degree& angle, TransformSpace relativeTo = TransformSpace::Local)
+                { this->rotate(Quaternion(angle, Vector3::UNIT_Z), relativeTo); }
+
+            void lookAt(const Vector3& target, TransformSpace relativeTo = TransformSpace::Parent, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+            void setDirection(const Vector3& direction, TransformSpace relativeTo = TransformSpace::Local, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z);
+            inline void setDirection(float x, float y, float z, TransformSpace relativeTo = TransformSpace::Local, const Vector3& localDirectionVector = Vector3::NEGATIVE_UNIT_Z)
+                { this->setDirection(Vector3(x, y, z), relativeTo, localDirectionVector); }
+
+            virtual void setScale3D(const Vector3& scale);
+            inline void setScale3D(float x, float y, float z)
+                { this->setScale3D(Vector3(x, y, z)); }
+            const Vector3& getScale3D() const;
+            const Vector3& getWorldScale3D() const;
+
+            inline void setScale(float scale)
+                { this->setScale3D(scale, scale, scale); }
+            inline float getScale() const
+                { Vector3 scale = this->getScale3D(); return (scale.x == scale.y && scale.x == scale.z) ? scale.x : 1; }
+            float getWorldScale() const;
+
+            inline void scale3D(const Vector3& scale)
+                { this->setScale3D(this->getScale3D() * scale); }
+            inline void scale3D(float x, float y, float z)
+                { this->scale3D(Vector3(x, y, z)); }
+            inline void scale(float scale)
+                { this->scale3D(scale, scale, scale); }
+
+            virtual void changedScale() {}
+
+            void attach(WorldEntity* object);
+            void detach(WorldEntity* object);
+            WorldEntity* getAttachedObject(unsigned int index);
+            inline const std::set<WorldEntity*>& getAttachedObjects() const
+                { return this->children_; }
+
+            void attachOgreObject(Ogre::MovableObject*  object);
+            void attachOgreObject(Ogre::BillboardSet*   object);
+            void attachOgreObject(Ogre::Camera*         object);
+            void attachOgreObject(Ogre::Entity*         object);
+            void attachOgreObject(Ogre::ParticleSystem* object);
+
+            void detachOgreObject(Ogre::MovableObject*  object);
+            void detachOgreObject(Ogre::BillboardSet*   object);
+            void detachOgreObject(Ogre::Camera*         object);
+            void detachOgreObject(Ogre::Entity*         object);
+            void detachOgreObject(Ogre::ParticleSystem* object);
+
+            Ogre::MovableObject* detachOgreObject(const Ogre::String& name);
+
+            inline void attachToParent(WorldEntity* parent)
+                { parent->attach(this); }
+            inline void detachFromParent()
+                { if (this->parent_) { this->parent_->detach(this); } }
+            inline WorldEntity* getParent() const
+                { return this->parent_; }
+
+            void attachNode(Ogre::SceneNode* node);
+            void detachNode(Ogre::SceneNode* node);
+            void attachToNode(Ogre::SceneNode* node);
+            void detachFromNode(Ogre::SceneNode* node);
+
+            inline void setDeleteWithParent(bool value)
+                { this->bDeleteWithParent_ = value; }
+            inline bool getDeleteWithParent() const
+                { return this->bDeleteWithParent_; }
+
+            void notifyChildPropsChanged();
+
+        protected:
+            virtual void parentChanged() {}
+
+            Ogre::SceneNode* node_;
+
+        private:
+            void registerVariables();
+
+            inline void lookAt_xmlport(const Vector3& target)
+                { this->lookAt(target); }
+            inline void setDirection_xmlport(const Vector3& direction)
+                { this->setDirection(direction); }
+            inline void yaw_xmlport(const Degree& angle)
+                { this->yaw(angle); }
+            inline void pitch_xmlport(const Degree& angle)
+                { this->pitch(angle); }
+            inline void roll_xmlport(const Degree& angle)
+                { this->roll(angle); }
+
+            // network callbacks
+            void networkcallback_parentChanged();
+            inline void scaleChanged()
+                { this->setScale3D(this->getScale3D()); }
+
+            WorldEntity* parent_;
+            unsigned int parentID_;
+            std::set<WorldEntity*> children_;
+            bool bDeleteWithParent_;
+
+            bool bActiveMem_;
+            bool bVisibleMem_;
+
+
+        /////////////
+        // Physics //
+        /////////////
+
+        public:
+            /**
+            @brief
+                Denotes the possible types of physical objects in a Scene.
+
+                Dynamic:   The object is influenced by its physical environment, like for instance little ball.
+                Kinematic: The object can only influence other dynamic objects. It's movement is coordinated by your own saying.
+                Static:    Like kinematic but the object is not allowed to move during the simulation.
+                None:      The object has no physics at all.
+            */
+            enum class CollisionType
+            {
+                Dynamic,
+                Kinematic,
+                Static,
+                None
+            };
+
+            //! Tells whether the object has any connection to the Bullet physics engine. If hasPhysics() is false, the object may still have a velocity.
+            bool hasPhysics()       const { return getCollisionType() != CollisionType::None     ; }
+            //! @see CollisionType
+            bool isStatic()         const { return getCollisionType() == CollisionType::Static   ; }
+            //! @see CollisionType
+            bool isKinematic()      const { return getCollisionType() == CollisionType::Kinematic; }
+            //! @see CollisionType
+            bool isDynamic()        const { return getCollisionType() == CollisionType::Dynamic  ; }
+            //! Tells whether physics has been activated (you can temporarily deactivate it)
+            bool isPhysicsActive()  const { return this->bPhysicsActive_; }
+            bool addedToPhysicalWorld() const;
+
+            void activatePhysics();
+            void deactivatePhysics();
+
+            //! Returns the CollisionType. @see CollisionType.
+            inline CollisionType getCollisionType() const
+                { return this->collisionType_; }
+            void setCollisionType(CollisionType type);
+
+            void setCollisionTypeStr(const std::string& type);
+            std::string getCollisionTypeStr() const;
+
+            //! Sets the mass of this object. Note that the total mass may be influenced by attached objects!
+            inline void setMass(float mass)
+                { this->mass_ = mass; recalculateMassProps(); }
+            //! Returns the mass of this object without its children.
+            inline float getMass() const
+                { return this->mass_; }
+
+            //! Returns the total mass of this object with all its attached children.
+            inline float getTotalMass() const
+                { return this->mass_ + this->childrenMass_; }
+
+            /**
+            @brief
+                Returns the diagonal elements of the inertia tensor when calculated in local coordinates.
+            @note
+                The local inertia tensor cannot be set, but is calculated by Bullet according to the collisionShape.
+                With compound collision shapes, an approximation is used.
+            */
+            inline const btVector3& getLocalInertia() const
+                { return this->localInertia_; }
+
+            /**
+            @brief
+                Sets how much reaction is applied in a collision.
+
+                Consider two equal spheres colliding with equal velocities:
+                Restitution 1 means that both spheres simply reverse their velocity (no loss of energy)
+                Restitution 0 means that both spheres will immediately stop moving
+                (maximum loss of energy without violating of the preservation of momentum)
+            */
+            inline void setRestitution(float restitution)
+                { this->restitution_ = restitution; internalSetPhysicsProps(); }
+            //! Returns the restitution parameter. @see setRestitution.
+            inline float getRestitution() const
+                { return this->restitution_; }
+
+            /**
+            @brief
+                Sets an artificial parameter that tells how much torque is applied when you apply a non-central force.
+
+                Normally the angular factor is 1, which means it's physically 'correct'. However if you have a player
+                character that should not rotate when hit sideways, you can set the angular factor to 0.
+            */
+            inline void setAngularFactor(float angularFactor)
+                { this->angularFactor_ = angularFactor; internalSetPhysicsProps(); }
+            //! Returns the angular factor. @see setAngularFactor.
+            inline float getAngularFactor() const
+                { return this->angularFactor_; }
+
+            //! Applies a mass independent damping. Velocities will simply diminish exponentially.
+            inline void setLinearDamping(float linearDamping)
+                { this->linearDamping_ = linearDamping; internalSetPhysicsProps(); }
+            //! Returns the linear damping. @see setLinearDamping.
+            inline float getLinearDamping() const
+                { return this->linearDamping_; }
+
+            //! Applies a tensor independent rotation damping. Angular velocities will simply diminish exponentially.
+            inline void setAngularDamping(float angularDamping)
+                { this->angularDamping_ = angularDamping; internalSetPhysicsProps(); }
+            //! Returns the angular damping. @see setAngularDamping.
+            inline float getAngularDamping() const
+                { return this->angularDamping_; }
+
+            //! Applies friction to the object. Friction occurs when two objects collide.
+            inline void setFriction(float friction)
+                { this->friction_ = friction; internalSetPhysicsProps(); }
+            //! Returns the amount of friction applied to the object.
+            inline float getFriction() const
+                { return this->friction_; }
+
+            /**
+             * Sets the motion threshold for continuous collision detection (CCD). This should be activated if an object moves further in one tick than its own
+             * size. This means that in one tick the object may be in front of a wall and in the next tick it will be behind the wall without ever triggering a
+             * collision. CCD ensures that collisions are still detected. By default it is deactivated (threshold = 0) which is fine for slow or static
+             * objects, but it should be set to a real value for fast moving objects (e.g. projectiles).
+             *
+             * A good value for the threshold is (diameter^2).
+             *
+             * @param ccdMotionThreshold CCD is enabled if the squared velocity of the object is > ccdMotionThreshold (default 0.0). 0.0 means deactivated.
+             */
+            inline void setCcdMotionThreshold(float ccdMotionThreshold)
+                { this->ccdMotionThreshold_ = ccdMotionThreshold; internalSetPhysicsProps(); }
+            //! Returns the currently used motion threshold for CCD (0 means CCD is deactivated).
+            inline float getCcdMotionThreshold() const
+                { return this->ccdMotionThreshold_; }
+
+            /**
+             * Sets the radius of the sphere which is used for continuous collision detection (CCD). The sphere should be embedded inside the objects collision
+             * shape, preferably smaller. @see setCcdMotionThreshold for more information about CCD.
+             *
+             * A good value for the radius is (diameter/5).
+             *
+             * @param ccdSweptSphereRadius The diameter of the sphere which is used for CCD (default 0.0).
+             */
+            inline void setCcdSweptSphereRadius(float ccdSweptSphereRadius)
+                { this->ccdSweptSphereRadius_ = ccdSweptSphereRadius; internalSetPhysicsProps(); }
+            //! Returns the currently used radius of the sphere for CCD.
+            inline float getCcdSweptSphereRadius() const
+                { return this->ccdSweptSphereRadius_; }
+
+            void attachCollisionShape(CollisionShape* shape);
+            void detachCollisionShape(CollisionShape* shape);
+            CollisionShape* getAttachedCollisionShape(unsigned int index);
+
+            void notifyCollisionShapeChanged();
+            void notifyChildMassChanged();
+
+            /**
+            @brief
+                Virtual function that gets called when this object collides with another.
+            @param otherObject
+                The object this one has collided into.
+            @param ownCollisionShape
+                The collision shape of the other object
+            @param contactPoint
+                Contact point provided by Bullet. Holds more information and can me modified. See return value.
+            @return
+                Returning false means that no modification to the contactPoint has been made. Return true otherwise!
+            @note
+                Condition is that enableCollisionCallback() was called.
+            */
+            virtual inline bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+                { return false; } /* With false, Bullet assumes no modification to the collision objects. */
+
+            //! Enables the collidesAgainst(.) function. The object doesn't respond to collision otherwise!
+            inline void enableCollisionCallback()
+                { this->bCollisionCallbackActive_ = true; this->collisionCallbackActivityChanged(); }
+            //! Disables the collidesAgainst(.) function. @see enableCollisionCallback()
+            inline void disableCollisionCallback()
+                { this->bCollisionCallbackActive_ = false; this->collisionCallbackActivityChanged(); }
+            //! Tells whether there could be a collision callback via collidesAgainst(.)
+            inline bool isCollisionCallbackActive() const
+                { return this->bCollisionCallbackActive_; }
+
+            //! Enables or disables collision response (default is of course on)
+            inline void setCollisionResponse(bool value)
+                { this->bCollisionResponseActive_ = value; this->collisionResponseActivityChanged(); }
+            //! Tells whether there could be a collision response
+            inline bool hasCollisionResponse()
+                { return this->bCollisionResponseActive_; }
+
+        protected:
+            /**
+            @brief
+                Function checks whether the requested collision type is legal to this object.
+
+                You can override this function in a derived class to constrain the collision to e.g. None or Dynamic.
+                A projectile may not prove very useful if there is no physical body. Simply set the CollisionType
+                in its constructor and override this method. But be careful that a derived class's virtual functions
+                don't yet exist in the constructor if a base class.
+            */
+            virtual bool isCollisionTypeLegal(CollisionType type) const = 0;
+
+            btRigidBody*  physicalBody_; //!< Bullet rigid body. Everything physical is applied to this instance.
+
+        private:
+            void recalculateMassProps();
+            void internalSetPhysicsProps();
+
+            bool notifyBeingAttached(WorldEntity* newParent);
+            void notifyDetached();
+
+            // network callbacks
+            void collisionTypeChanged();
+            void physicsActivityChanged();
+            void collisionCallbackActivityChanged();
+            void collisionResponseActivityChanged();
+            //! Network callback workaround to call a function when the value changes.
+            inline void massChanged()
+                { this->setMass(this->mass_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void restitutionChanged()
+                { this->setRestitution(this->restitution_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void angularFactorChanged()
+                { this->setAngularFactor(this->angularFactor_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void linearDampingChanged()
+                { this->setLinearDamping(this->linearDamping_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void angularDampingChanged()
+                { this->setAngularDamping(this->angularDamping_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void frictionChanged()
+                { this->setFriction(this->friction_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void ccdMotionThresholdChanged()
+                { this->setCcdMotionThreshold(this->ccdMotionThreshold_); }
+            //! Network callback workaround to call a function when the value changes.
+            inline void ccdSweptSphereRadiusChanged()
+                { this->setCcdSweptSphereRadius(this->ccdSweptSphereRadius_); }
+
+            CollisionType                collisionType_;                 //!< @see setCollisionType
+            CollisionType                collisionTypeSynchronised_;     //!< Network synchronised variable for collisionType_
+            bool                         bPhysicsActive_;                //!< @see isPhysicsActive
+            bool                         bPhysicsActiveSynchronised_;    //!< Network synchronised variable for bPhysicsActive_
+            //! When attaching objects hierarchically this variable tells this object (as child) whether physics was activated before attaching (because the deactivate physics while being attached).
+            bool                         bPhysicsActiveBeforeAttaching_;
+            WorldEntityCollisionShape*   collisionShape_;                //!< Attached collision shapes go here
+            btScalar                     mass_;                          //!< @see setMass
+            btVector3                    localInertia_;                  //!< @see getLocalInertia
+            btScalar                     restitution_;                   //!< @see setRestitution
+            btScalar                     angularFactor_;                 //!< @see setAngularFactor
+            btScalar                     linearDamping_;                 //!< @see setLinearDamping
+            btScalar                     angularDamping_;                //!< @see setAngularDamping
+            btScalar                     friction_;                      //!< @see setFriction
+            btScalar                     childrenMass_;                  //!< Sum of all the children's masses
+            btScalar                     ccdMotionThreshold_;            //!< @see setCcdMotionThreshold
+            btScalar                     ccdSweptSphereRadius_;          //!< @see setCcdSweptSphereRadius
+            bool                         bCollisionCallbackActive_;      //!< @see enableCollisionCallback
+            bool                         bCollisionResponseActive_;      //!< Tells whether the object should respond to collisions
+    };
+
+    // Inline heavily used functions for release builds. In debug, we better avoid including OgreSceneNode here.
+#ifdef ORXONOX_RELEASE
+    inline const Vector3& WorldEntity::getPosition() const
+        { return this->node_->getPosition(); }
+    inline const Quaternion& WorldEntity::getOrientation() const
+        { return this->node_->getOrientation(); }
+    inline const Vector3& WorldEntity::getScale3D() const
+        { return this->node_->getScale(); }
+#endif
+
+    SUPER_FUNCTION(5, WorldEntity, changedScale, false);
+}
+
+#endif /* _WorldEntity_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,11 @@
+ADD_SOURCE_FILES(ORXONOX_SRC_FILES
+  FpsPlayer.cc
+  Spectator.cc
+  Pawn.cc
+  SpaceShip.cc
+  ModularSpaceShip.cc
+  TeamBaseMatchBase.cc
+  Destroyer.cc
+  StoryModePawn.cc
+  ShootableObstacle.cc
+)
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Destroyer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Destroyer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Destroyer.cc	(revision 11817)
@@ -0,0 +1,48 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Matthias Mock
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Destroyer.h"
+
+#include "core/CoreIncludes.h"
+#include "gametypes/UnderAttack.h"
+
+namespace orxonox
+{
+    RegisterClass(Destroyer);
+
+    Destroyer::Destroyer(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(Destroyer);
+
+        UnderAttack* gametype = orxonox_cast<UnderAttack*>(this->getGametype());
+        if (gametype)
+        {
+            gametype->addDestroyer(this);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Destroyer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Destroyer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Destroyer.h	(revision 11817)
@@ -0,0 +1,47 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Matthias Mock
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Destroyer_H__
+#define _Destroyer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "SpaceShip.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Destroyer : public SpaceShip
+    {
+        public:
+            Destroyer(Context* context);
+            virtual ~Destroyer() {};
+
+    };
+}
+
+#endif /* _Destroyer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/FpsPlayer.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/FpsPlayer.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/FpsPlayer.cc	(revision 11817)
@@ -0,0 +1,307 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Frei
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "FpsPlayer.h"
+
+#include <OgreSceneNode.h>
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+#include <LinearMath/btVector3.h>
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+#include <OgreSceneManager.h>
+#include <OgreSceneNode.h>
+#include <OgreEntity.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+#include "items/Engine.h"
+#include "Scene.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSlot.h"
+#include "weaponsystem/Weapon.h"
+
+#include <cmath>
+
+namespace orxonox
+{
+    const float orientationGain_ = 100;
+    const float jumpValue_ = 300;
+    RegisterClass(FpsPlayer);
+
+    FpsPlayer::FpsPlayer(Context* context) : Pawn(context)
+    {
+        RegisterObject(FpsPlayer);
+        this->speed_ = 200;
+        this->localVelocity_ = Vector3::ZERO;
+/*
+ *        this->primaryThrust_  = 100;
+ *        this->auxilaryThrust_ =  30;
+ *        this->rotationThrust_ =  10;
+ *
+ *        this->localLinearAcceleration_.setValue(0, 0, 0);
+ *        this->localAngularAcceleration_.setValue(0, 0, 0);
+ *        this->bBoost_ = false;
+ *        this->bPermanentBoost_ = false;
+ *        this->steering_ = Vector3::ZERO;
+*/
+
+
+        this->bInvertYAxis_ = false;
+
+        this->setDestroyWhenPlayerLeft(true);
+
+        // FpsPlayer is always a physical object per default
+        // Be aware of this call: The collision type legality check will not reach derived classes!
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+        // Get notification about collisions
+        this->enableCollisionCallback();
+
+        this->setConfigValues();
+        this->registerVariables();
+
+        //this->weaponNode = this->cameraPositionRootNode_;
+        this->weaponNode_ = this->getScene()->getRootSceneNode()->createChildSceneNode();
+        this->attachNode(this->weaponNode_);
+    }
+
+    FpsPlayer::~FpsPlayer()
+    {
+        if (this->isInitialized())
+        {
+            if (this->mesh_.getEntity())
+                this->detachOgreObject(this->mesh_.getEntity());
+
+            if (this->weaponNode_ && this->getScene()->getSceneManager())
+                this->getScene()->getSceneManager()->destroySceneNode(this->weaponNode_->getName());
+        }
+    }
+
+    void FpsPlayer::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(FpsPlayer, XMLPort, xmlelement, mode);
+
+        XMLPortParamVariable(FpsPlayer, "primaryThrust",  primaryThrust_,  xmlelement, mode);
+        XMLPortParamVariable(FpsPlayer, "auxilaryThrust", auxilaryThrust_, xmlelement, mode);
+        XMLPortParamVariable(FpsPlayer, "rotationThrust", rotationThrust_, xmlelement, mode);
+        XMLPortParam(FpsPlayer, "weapon", setMeshSource, getMeshSource, xmlelement, mode);
+    }
+
+    void FpsPlayer::registerVariables()
+    {
+        registerVariable(this->primaryThrust_,  VariableDirection::ToClient);
+        registerVariable(this->auxilaryThrust_, VariableDirection::ToClient);
+        registerVariable(this->rotationThrust_, VariableDirection::ToClient);
+        registerVariable(this->weaponMashName_, VariableDirection::ToClient);
+    }
+
+
+
+    void FpsPlayer::setConfigValues()
+    {
+        SetConfigValue(bInvertYAxis_, false).description("Set this to true for joystick-like mouse behaviour (mouse up = targetting down).");
+    }
+
+    bool FpsPlayer::isCollisionTypeLegal(WorldEntity::CollisionType type) const
+    {
+        if (type != WorldEntity::CollisionType::Dynamic)
+        {
+            orxout(internal_warning) << "Cannot tell a FpsPlayer not to be dynamic! Ignoring." << endl;
+            assert(false); // Only in debug mode
+            return false;
+        }
+        else
+            return true;
+    }
+
+    void FpsPlayer::tick(float dt)
+    {
+        if (this->hasLocalController())
+        {
+            this->setOrientation(savedOrientation_);
+
+            this->thisTickBoost_ = false;
+
+            float localSpeedSquared = this->localVelocity_.squaredLength();
+            float localSpeed;
+            if (localSpeedSquared > 1.0)
+                localSpeed = this->speed_ / sqrtf(localSpeedSquared);
+            else
+                localSpeed = this->speed_;
+
+            this->localVelocity_.x *= localSpeed;
+            this->localVelocity_.z *= localSpeed;
+            Vector3 temp = this->getOrientation() * this->localVelocity_;
+            if (localVelocity_.y == jumpValue_)
+                this->setVelocity(Vector3(temp.x, temp.y + this->getVelocity().y, temp.z));
+            else
+                this->setVelocity(Vector3(temp.x, this->getVelocity().y, temp.z));
+            this->localVelocity_.x = 0;
+            this->localVelocity_.y = 0;
+            this->localVelocity_.z = 0;
+
+            if (!this->isInMouseLook())
+            {
+                this->yaw(Radian(this->yaw_ * this->getMouseLookSpeed()), WorldEntity::TransformSpace::Parent);
+
+                Radian pitch = this->cameraPositionRootNode_->getOrientation().getPitch();
+                if (pitch < Radian(math::pi_2) && pitch > Radian(-math::pi_2))
+                {
+                    this->cameraPositionRootNode_->pitch(Radian(this->pitch_ * this->getMouseLookSpeed()));
+                }
+                else if (pitch < Radian(-math::pi_2))
+                {
+                    if (this->pitch_ > 0.0f)
+                        this->cameraPositionRootNode_->pitch(Radian(this->pitch_ * this->getMouseLookSpeed()));
+                    else if (pitch < Radian(-math::pi_2))
+                        this->cameraPositionRootNode_->pitch(-pitch + Radian(-math::pi_2));
+                }
+                else if (pitch > Radian(math::pi_2))
+                {
+                    if (this->pitch_ < 0.0f)
+                        this->cameraPositionRootNode_->pitch(Radian(this->pitch_ * this->getMouseLookSpeed()));
+                    else if (pitch > Radian(math::pi_2))
+                        this->cameraPositionRootNode_->pitch(-pitch + Radian(math::pi_2));
+                }
+                this->weaponNode_->setOrientation(this->cameraPositionRootNode_->getOrientation());
+            }
+
+            this->yaw_ = this->pitch_ = this->roll_ = 0;
+
+            this->setAngularVelocity(0.0, 0.0, 0.0);
+            this->savedOrientation_ = this->getOrientation();
+        }
+
+        SUPER(FpsPlayer, tick, dt);
+    }
+
+    void FpsPlayer::changedMesh()
+    {
+        if (GameMode::showsGraphics())
+        {
+            if (this->mesh_.getEntity())
+                this->weaponNode_->detachObject(this->mesh_.getEntity());
+
+            this->mesh_.setMeshSource(this->getScene()->getSceneManager(), this->meshSrc_);
+
+            if (this->mesh_.getEntity())
+            {
+                this->weaponNode_->attachObject(this->mesh_.getEntity());
+            }
+        }
+    }
+
+    void FpsPlayer::setPlayer(PlayerInfo* player)
+    {
+        ControllableEntity::setPlayer(player);
+
+//        this->setSyncMode(ObjectDirection::ToClient);
+    }
+
+    void FpsPlayer::startLocalHumanControl()
+    {
+        ControllableEntity::startLocalHumanControl();
+    }
+
+    void FpsPlayer::moveFrontBack(const Vector2& value)
+    {
+        this->localVelocity_.z -= value.x;
+    }
+
+
+    void FpsPlayer::moveRightLeft(const Vector2& value)
+    {
+        this->localVelocity_.x += value.x;
+    }
+
+    void FpsPlayer::moveUpDown(const Vector2& value)
+    {
+        //this->localVelocity_.y += value.x;
+    }
+
+    void FpsPlayer::rotateYaw(const Vector2& value)
+    {
+        this->yaw_ += value.y;
+
+        ControllableEntity::rotateYaw(value);
+    }
+
+    void FpsPlayer::rotatePitch(const Vector2& value)
+    {
+        this->pitch_ += value.y;
+
+        ControllableEntity::rotatePitch(value);
+    }
+
+    void FpsPlayer::rotateRoll(const Vector2& value)
+    {
+        this->roll_ += value.y;
+
+        ControllableEntity::rotateRoll(value);
+    }
+
+    void FpsPlayer::fire()
+    {
+    }
+
+    void FpsPlayer::boost(bool bBoost) //acctually jump
+    {
+        if (this->isFloor_)
+        {
+            if (!this->thisTickBoost_)
+                this->localVelocity_.y = jumpValue_;
+            //this->physicalBody_->applyCentralImpulse(btVector3(0, jumpvalue, 0));
+            this->thisTickBoost_ = true;
+            this->isFloor_ = false;
+        }
+    }
+
+    bool FpsPlayer::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        if (contactPoint.m_normalWorldOnB.y() > 0.6)
+            this->isFloor_ = true;
+        else
+            this->isFloor_ = false;
+
+        return false;
+    }
+
+    void FpsPlayer::addedWeaponPack(WeaponPack* wPack)
+    {
+        for (size_t i = 0; i < wPack->getNumWeapons(); ++i)
+        {
+            Weapon* weapon = wPack->getWeapon(i);
+            if (weapon->getWeaponSlot())
+            {
+                weapon->getWeaponSlot()->removeWeapon();
+                weapon->detachFromParent();
+                weapon->attachToNode(this->weaponNode_);
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/FpsPlayer.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/FpsPlayer.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/FpsPlayer.h	(revision 11817)
@@ -0,0 +1,108 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Cyrill Frei
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _FpsPlayer_H__
+#define _FpsPlayer_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <LinearMath/btVector3.h>
+#include "util/Math.h"
+#include "tools/Mesh.h"
+#include "Pawn.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport FpsPlayer : public Pawn
+    {
+        public:
+            FpsPlayer(Context* context);
+            virtual ~FpsPlayer();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+            void registerVariables();
+            void setConfigValues();
+
+            virtual void moveFrontBack(const Vector2& value) override;
+            virtual void moveRightLeft(const Vector2& value) override;
+            virtual void moveUpDown(const Vector2& value) override;
+
+            virtual void rotateYaw(const Vector2& value) override;
+            virtual void rotatePitch(const Vector2& value) override;
+            virtual void rotateRoll(const Vector2& value) override;
+
+
+            inline void setMeshSource(const std::string& meshname)
+                { this->meshSrc_ = meshname; this->changedMesh(); }
+            inline const std::string& getMeshSource() const
+                { return this->meshSrc_; }
+
+            virtual void boost(bool bBoost) override; //actually jump
+
+            virtual void fire();
+
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint) override;
+
+            virtual void addedWeaponPack(WeaponPack* wPack) override;
+
+        protected:
+            virtual void setPlayer(PlayerInfo* player) override;
+            virtual void startLocalHumanControl() override;
+            bool bInvertYAxis_;
+
+            bool bBoost_;
+            bool bPermanentBoost_;
+            Vector3 steering_;
+            float primaryThrust_;
+            float auxilaryThrust_;
+            float rotationThrust_;
+            std::string weaponMashName_;
+            btVector3 localLinearAcceleration_;
+            btVector3 localAngularAcceleration_;
+
+        private:
+            virtual bool isCollisionTypeLegal(WorldEntity::CollisionType type) const override;
+            float speed_;
+
+            void changedMesh();
+            Mesh mesh_;
+            std::string meshSrc_;
+            float yaw_;
+            float pitch_;
+            float roll_;
+            Vector3 localVelocity_;
+            bool isFloor_;
+            bool thisTickBoost_;
+            Quaternion savedOrientation_;
+            Ogre::SceneNode* weaponNode_;
+    };
+}
+
+#endif /* _FpsPlayer_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ModularSpaceShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ModularSpaceShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ModularSpaceShip.cc	(revision 11817)
@@ -0,0 +1,309 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Noe Pedrazzini
+ *
+ */
+
+#include "ModularSpaceShip.h"
+
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+#include "util/Math.h"
+#include "gametypes/Gametype.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "items/ShipPart.h"
+#include "items/Engine.h"
+#include "worldentities/StaticEntity.h"
+#include <BulletCollision/CollisionShapes/btCollisionShape.h>
+#include <BulletCollision/CollisionShapes/btCompoundShape.h>
+
+
+
+namespace orxonox
+{
+    SetConsoleCommand("ModularSpaceShip", "killshippart", &ModularSpaceShip::killShipPartStatic);
+
+    RegisterClass(ModularSpaceShip);
+
+    std::map<StaticEntity*, ShipPart*>* ModularSpaceShip::partMap_s = nullptr;
+
+    ModularSpaceShip::ModularSpaceShip(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(ModularSpaceShip);
+
+        this->registerVariables();
+
+        ModularSpaceShip::partMap_s = &(this->partMap_);
+
+    }
+
+    ModularSpaceShip::~ModularSpaceShip()
+    {
+        if (this->isInitialized())
+        {
+            while (!this->partList_.empty())
+                this->partList_[0]->destroy();
+        }
+    }
+
+    void ModularSpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ModularSpaceShip, XMLPort, xmlelement, mode);
+        XMLPortObject(ModularSpaceShip, ShipPart, "parts", addShipPart, getShipPart, xmlelement, mode);
+    }
+
+    void ModularSpaceShip::registerVariables()
+    {
+        return;
+    }
+
+    /**
+    @brief
+        Searches for ShipParts matching to StaticEntities.
+    */
+    void ModularSpaceShip::updatePartAssignment()
+    {
+        // iterate through all attached objects
+        for (unsigned int i=0; i < this->getAttachedObjects().size(); i++)
+        {
+            if (this->getAttachedObject(i) == nullptr)
+            {
+                break;
+            }
+            // iterate through all attached parts
+            for(ShipPart* part : this->partList_)
+            {
+                // if the name of the part matches the name of the object, add the object to that parts entitylist (unless it was already done).
+                if((part->getName() == this->getAttachedObject(i)->getName()) && !part->hasEntity(orxonox_cast<StaticEntity*>(this->getAttachedObject(i))))
+                {
+                    // The Entity is added to the part's entityList_
+                    part->addEntity(orxonox_cast<StaticEntity*>(this->getAttachedObject(i)));
+                    // An entry in the partMap_ is created, assigning the part to the entity.
+                    this->addPartEntityAssignment((StaticEntity*)(this->getAttachedObject(i)), part);
+                }
+            }
+        }
+    }
+
+    /**
+    @brief
+        Creates a new assignment for the given StaticEntity and ShipPart in the partMap_
+    @param entity
+        A pointer to the StaticEntity
+    @param part
+        A pointer to the ShipPart.
+    */
+    void ModularSpaceShip::addPartEntityAssignment(StaticEntity* entity, ShipPart* part)
+    {
+        if (!entity || !part)
+            return;
+
+        if (this->partMap_.find(entity) != this->partMap_.end())
+                {
+                    orxout(internal_warning) << "Assigning an Entity to multiple parts is not yet supported." << endl;
+                    return;
+                }
+
+        this->partMap_[entity] = part;
+    }
+
+
+    /**
+    @brief
+        Get the ShipPart an attached entity belongs to.
+    @param entity
+        The entity to be searched.
+    @return
+        Returns a pointer to the ShipPart the entity belongs to.
+    */
+    ShipPart* ModularSpaceShip::getPartOfEntity(StaticEntity* entity) const
+    {
+        for (const auto& mapEntry : this->partMap_)
+        {
+            if (mapEntry.first == entity)
+                return mapEntry.second;
+        }
+        return nullptr;
+    }
+
+    /**
+    @brief
+        If the damage occurred on an attached StaticEntity, the damage is given to the corresponding ShipPart to handle.
+    */
+    void ModularSpaceShip::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        if (cs != nullptr && this->getPartOfEntity((StaticEntity*)(cs->getUserPointer())) != nullptr)
+            this->getPartOfEntity((StaticEntity*)(cs->getUserPointer()))->handleHit(damage, healthdamage, shielddamage, originator);
+        else
+            SpaceShip::damage(damage, healthdamage, shielddamage, originator, cs);
+    }
+
+    /**
+    @brief
+        STATIC: Needed for consolecommand. Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
+    @param name
+        The name of the part to be killed.
+    */
+    void ModularSpaceShip::killShipPartStatic(std::string name)
+    {
+        for (const auto& mapEntry : *ModularSpaceShip::partMap_s)
+        {
+            if (mapEntry.second->getName() == name)
+            {
+                mapEntry.second->death();
+                return;
+            }
+        }
+        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
+    }
+
+    /**
+    @brief
+        Kills the ShipPart with the given name. Used from the console-command "ModularSpaceShip killshippart [string]".
+    @param name
+        The name of the part to be killed.
+    */
+    void ModularSpaceShip::killShipPart(std::string name)
+    {
+        for (const auto& mapEntry : ModularSpaceShip::partMap_)
+        {
+            if (mapEntry.second->getName() == name)
+            {
+                mapEntry.second->death();
+                return;
+            }
+        }
+        orxout(internal_warning) << "Could not apply damage to ShipPart \"" << name << "\". Part not found." << endl;
+    }
+
+    /**
+    @brief
+        Add a ShipPart to the SpaceShip.
+    @param part
+        A pointer to the ShipPart to be added.
+    */
+    void ModularSpaceShip::addShipPart(ShipPart* part)
+    {
+        OrxAssert(part != nullptr, "The ShipPart cannot be nullptr.");
+        this->partList_.push_back(part);
+        part->setParent(this);
+        this->updatePartAssignment();
+    }
+
+    /**
+    @brief
+        Get the i-th ShipPart of the SpaceShip.
+    @return
+        Returns a pointer to the i-the ShipPart. nullptr if there is no ShipPart with that index.
+    */
+    ShipPart* ModularSpaceShip::getShipPart(unsigned int index)
+    {
+        if(this->partList_.size() <= index)
+            return nullptr;
+        else
+            return this->partList_[index];
+    }
+
+    /**
+    @brief
+        Looks for an attached ShipPart with a certain name.
+    @param name
+        The name of the ShipPart to be returned.
+    @return
+        Pointer to the ShipPart with the given name, or nullptr if not found.
+    */
+    ShipPart* ModularSpaceShip::getShipPartByName(std::string name)
+    {
+        for(ShipPart* part : this->partList_)
+        {
+            if(orxonox_cast<ShipPart*>(part)->getName() == name)
+            {
+                return orxonox_cast<ShipPart*>(part);
+            }
+        }
+        orxout(internal_warning) << "Couldn't find ShipPart with name \"" << name << "\"." << endl;
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Check whether the SpaceShip has a particular Engine.
+    @param search
+        A pointer to the Engine to be checked.
+    */
+    bool ModularSpaceShip::hasShipPart(ShipPart* search) const
+    {
+        for(ShipPart* part : this->partList_)
+        {
+            if(part == search)
+                return true;
+        }
+        return false;
+    }
+
+
+    /**
+    @brief
+        Removes a ShipPart from the SpaceShip, destroying the corresponding StaticEntity
+    @param part
+        The ShipPart to be removed.
+    */
+    void ModularSpaceShip::removeShipPart(ShipPart* part)
+    {
+        // Remove the part from the partList_
+        std::vector<ShipPart*>::iterator it = this->partList_.begin();
+        for(unsigned int i = 0; i < this->partList_.size(); i++)
+        {
+            if(this->partList_[i] == part)
+            {
+                this->partList_.erase(it);
+                break;
+            }
+            it++;
+        }
+        // Remove the part-entity assignment and detach the Entity of this ShipPart
+        for (std::map<StaticEntity*, ShipPart*>::iterator itt = this->partMap_.begin(); itt != this->partMap_.end(); )
+        {
+            if (itt->second == part)
+            {
+                this->detach(itt->first);
+                itt->first->destroy();
+                //itt->first->setActive(false);
+                //itt->first->setVisible(false);
+                //itt->first->setCollisionResponse(false);
+                //itt->first->setCollisionType(None);
+                //itt->first->deactivatePhysics();
+                this->partMap_.erase(itt++);
+            } else {
+                ++itt;
+            }
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ModularSpaceShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ModularSpaceShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ModularSpaceShip.h	(revision 11817)
@@ -0,0 +1,141 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Noe Pedrazzini
+ *
+ */
+
+#ifndef _ModularSpaceShip_H__
+#define _ModularSpaceShip_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <LinearMath/btVector3.h>
+
+#include "tools/Timer.h"
+#include "util/Math.h"
+#include "util/OrxAssert.h"
+
+#include "SpaceShip.h"
+#include "items/ShipPart.h"
+#include <map>
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The SpaceShip is the principal entity through which the player interacts with the game. Its main function is to fly, however many things, such as @ref orxonox::Engine Engines or @ref orxonox::Weapon Weapons, can be attached to it.
+        The ModularSpaceShip is an extension of a @ref orxonox::SpaceShip SpaceShip, which uses @ref orxonox::ShipPart ShipParts to allow entities attached to it to be destroyed individually.
+
+        There are several parameters that define the behavior of the ModularSpaceShip>
+        - The <b>rotationThrust</b>, specifies the force with which the ModularSpaceShip rotates.
+        - The <b>boost</b>, there are quite some parameters pertaining to boosting. The boost is a special move of the ModularSpaceShip, where, for a limited amount of time, it can fly considerably faster than usual. The <b>boostPower</b> is the amount of power available for boosting. The <b>boostPowerRate</b> is the rate at which the boost power is replenished. The <b>boostRate</b> is the rate at which boosting uses power. And the <b>boostCooldownDuration</b> is the time the ModularSpaceShip cannot boost, once all the boost power has been used up. Naturally all of these parameters must be non-negative.
+        - The <b>boost shaking</b>, when the ModularSpaceShip boosts, the camera shakes to create a more immersive effect. Two parameters can be used to adjust the effect. The <b>shakeFrequency</b> is the frequency with which the camera shakes. And the <b>shakeAmplitude</b> is the amount with which the camera shakes. Again these parameters must bee non-negative.
+        - The <b>lift</b> creates a more natural flight feeling through the addition of a lift force. There are again tow parameters that can be specified. The <b>lift</b> which is the lift force that is applied. And the <b>stallSpeed</b> which is the forward speed after which no more lift is generated.
+
+        As mentioned @ref orxonox::Engine Engines can be mounted on the ModularSpaceShip.
+        In order to assign attached entities to a ShipPart, a ShipPart with the same name as the corresponding entity needs to be created in the \<parts\> tag.
+        Here is a (primitive) example of a ModularSpaceShip defined in XML:
+        @code
+        <ModularSpaceShip
+            rotationThrust    = 50
+
+            lift = 1;
+            stallSpeed = 220;
+
+            boostPower            = 15
+            boostPowerRate        = 1
+            boostRate             = 5
+            boostCooldownDuration = 10
+
+            shakeFrequency = 15
+            shakeAmplitude = 9
+
+            collisionType     = "dynamic"
+            mass              = 100
+            linearDamping     = 0.7
+            angularDamping    = 0.9999999
+            >
+                <attached>
+                    <StaticEntity name="wing"  . . .  />
+                    <StaticEntity name="tail" . . . />
+                </attached>
+                <parts>
+                    <ShipPart name="wing" . . . />
+                    <ShipPart name="tail" . . . />
+                </parts>
+                <engines>
+                    <Engine />
+                    <Engine />
+                </engines>
+            </ModularSpaceShip>
+        @endcode
+
+    @author
+        Fabian 'x3n' Landau, Noe Pedrazzini
+    */
+    class _OrxonoxExport ModularSpaceShip : public SpaceShip
+    {
+        public:
+            ModularSpaceShip(Context* context);
+            virtual ~ModularSpaceShip();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+
+            void addPartEntityAssignment(StaticEntity* entity, ShipPart* part);
+            ShipPart* getPartOfEntity(StaticEntity* entity) const;
+
+            virtual void damage(float damage, float healthdamage = 0.0f, float shielddamage = 0.0f, Pawn* originator = nullptr, const btCollisionShape* cs = nullptr);
+
+            static void killShipPartStatic(std::string name);
+            void killShipPart(std::string name);
+
+            void addShipPart(ShipPart* part);
+            ShipPart* getShipPart(unsigned int index);
+            ShipPart* getShipPartByName(std::string name);
+            bool hasShipPart(ShipPart* part) const;
+            void removeShipPart(ShipPart* part);
+
+            inline void setRotationThrust(float val)
+                { this->rotationThrust_ = val; }
+            inline float getRotationThrust()
+                { return this->rotationThrust_; }
+
+            virtual void updatePartAssignment();
+
+        protected:
+
+
+        private:
+            void registerVariables();
+            std::vector<ShipPart*> partList_;                       // The list of all Parts mounted on this ModularSpaceShip.
+            std::map<StaticEntity*, ShipPart*> partMap_;            // Map of Part-Entity-assignments
+            static std::map<StaticEntity*, ShipPart*>* partMap_s;
+        
+    };
+}
+
+#endif /* _ModularSpaceShip_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Pawn.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Pawn.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Pawn.cc	(revision 11817)
@@ -0,0 +1,652 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      Simon Miescher
+ *
+ */
+
+#include "Pawn.h"
+
+#include <algorithm>
+
+#include "core/CoreIncludes.h"
+#include "core/GameMode.h"
+#include "core/XMLPort.h"
+#include "core/EventIncludes.h"
+#include "network/NetworkFunction.h"
+
+#include "infos/PlayerInfo.h"
+#include "controllers/Controller.h"
+#include "gametypes/Gametype.h"
+#include "graphics/ParticleSpawner.h"
+#include "worldentities/ExplosionChunk.h"
+#include "worldentities/ExplosionPart.h"
+#include "weaponsystem/WeaponSystem.h"
+#include "weaponsystem/WeaponSlot.h"
+#include "weaponsystem/WeaponPack.h"
+#include "weaponsystem/WeaponSet.h"
+#include "weaponsystem/Munition.h"
+#include "sound/WorldSound.h"
+#include "core/object/ObjectListIterator.h"
+
+#include "controllers/FormationController.h"
+
+namespace orxonox
+{
+    RegisterClass(Pawn);
+
+    SetConsoleCommand("Pawn", "debugDrawWeapons", &Pawn::consoleCommand_debugDrawWeapons).addShortcut();
+
+    Pawn::Pawn(Context* context)
+        : ControllableEntity(context)
+        , RadarViewable(this, static_cast<WorldEntity*>(this))
+    {
+        RegisterObject(Pawn);
+
+        this->bAlive_ = true;
+        this->bVulnerable_ = true;
+
+        this->health_ = 0;
+        this->maxHealth_ = 0;
+        this->initialHealth_ = 0;
+
+        this->shieldHealth_ = 0;
+        this->initialShieldHealth_ = 0;
+        this->maxShieldHealth_ = 100; //otherwise shield might increase to float_max
+        this->shieldAbsorption_ = 0.5;
+        this->shieldRechargeRate_ = 0;
+        this->shieldRechargeWaitTime_ = 1.0f;
+        this->shieldRechargeWaitCountdown_ = 0;
+
+        this->lastHitOriginator_ = nullptr;
+
+        // set damage multiplier to default value 1, meaning nominal damage
+        this->damageMultiplier_ = 1;
+        this->acceptsPickups_ = true;
+
+        this->spawnparticleduration_ = 3.0f;
+
+        this->aimPosition_ = Vector3::ZERO;
+
+        //this->explosionPartList_ = nullptr;
+
+        if (GameMode::isMaster())
+        {
+            this->weaponSystem_ = new WeaponSystem(this->getContext());
+            this->weaponSystem_->setPawn(this);
+        }
+        else
+            this->weaponSystem_ = nullptr;
+
+        this->setRadarObjectColour(ColourValue::Red);
+        this->setRadarObjectShape(RadarViewable::Shape::Dot);
+
+        this->registerVariables();
+
+        this->isHumanShip_ = this->hasLocalController();
+
+        this->setSyncMode(ObjectDirection::Bidirectional); // needed to synchronise e.g. aimposition
+
+        if (GameMode::isMaster())
+        {
+            this->explosionSound_ = new WorldSound(this->getContext());
+            this->explosionSound_->setVolume(1.0f);
+        }
+        else
+        {
+            this->explosionSound_ = nullptr;
+        }
+    }
+
+    Pawn::~Pawn()
+    {
+        if (this->isInitialized())
+        {
+            if (this->weaponSystem_)
+                this->weaponSystem_->destroy();
+        }
+    }
+
+    void Pawn::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Pawn, XMLPort, xmlelement, mode);
+
+        XMLPortParam(Pawn, "health", setHealth, getHealth, xmlelement, mode).defaultValues(100);
+        XMLPortParam(Pawn, "maxhealth", setMaxHealth, getMaxHealth, xmlelement, mode).defaultValues(200);
+        XMLPortParam(Pawn, "initialhealth", setInitialHealth, getInitialHealth, xmlelement, mode).defaultValues(100);
+
+        XMLPortParam(Pawn, "shieldhealth", setShieldHealth, getShieldHealth, xmlelement, mode).defaultValues(0);
+        XMLPortParam(Pawn, "initialshieldhealth", setInitialShieldHealth, getInitialShieldHealth, xmlelement, mode).defaultValues(0);
+        XMLPortParam(Pawn, "maxshieldhealth", setMaxShieldHealth, getMaxShieldHealth, xmlelement, mode).defaultValues(100);
+        XMLPortParam(Pawn, "shieldabsorption", setShieldAbsorption, getShieldAbsorption, xmlelement, mode).defaultValues(0);
+
+        XMLPortParam(Pawn, "vulnerable", setVulnerable, isVulnerable, xmlelement, mode).defaultValues(true);
+
+        XMLPortParam(Pawn, "spawnparticlesource", setSpawnParticleSource, getSpawnParticleSource, xmlelement, mode);
+        XMLPortParam(Pawn, "spawnparticleduration", setSpawnParticleDuration, getSpawnParticleDuration, xmlelement, mode).defaultValues(3.0f);
+        XMLPortParam(Pawn, "explosionchunks", setExplosionChunks, getExplosionChunks, xmlelement, mode).defaultValues(0);
+
+        XMLPortObject(Pawn, WeaponSlot, "weaponslots", addWeaponSlot, getWeaponSlot, xmlelement, mode);
+        XMLPortObject(Pawn, WeaponSet, "weaponsets", addWeaponSet, getWeaponSet, xmlelement, mode);
+        XMLPortObject(Pawn, WeaponPack, "weaponpacks", addWeaponPackXML, getWeaponPack, xmlelement, mode);
+        XMLPortObject(Pawn, Munition, "munition", addMunitionXML, getMunitionXML, xmlelement, mode);
+
+        XMLPortObject(Pawn, ExplosionPart, "explosion", addExplosionPart, getExplosionPart, xmlelement, mode);
+        XMLPortParam(Pawn, "shieldrechargerate", setShieldRechargeRate, getShieldRechargeRate, xmlelement, mode).defaultValues(0);
+        XMLPortParam(Pawn, "shieldrechargewaittime", setShieldRechargeWaitTime, getShieldRechargeWaitTime, xmlelement, mode).defaultValues(1.0f);
+
+        XMLPortParam(Pawn, "explosionSound",  setExplosionSound,  getExplosionSound,  xmlelement, mode);
+
+        XMLPortParam ( RadarViewable, "radarname", setRadarName, getRadarName, xmlelement, mode );
+    }
+
+    void Pawn::XMLEventPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(Pawn, XMLEventPort, xmlelement, mode);
+
+        XMLPortEventState(Pawn, BaseObject, "vulnerability", setVulnerable, xmlelement, mode);
+    }
+
+    void Pawn::registerVariables()
+    {
+        registerVariable(this->bAlive_,            VariableDirection::ToClient);
+        registerVariable(this->bVulnerable_,       VariableDirection::ToClient);
+        registerVariable(this->health_,            VariableDirection::ToClient);
+        registerVariable(this->maxHealth_,         VariableDirection::ToClient);
+        registerVariable(this->shieldHealth_,      VariableDirection::ToClient);
+        registerVariable(this->maxShieldHealth_,   VariableDirection::ToClient);
+        registerVariable(this->shieldAbsorption_,  VariableDirection::ToClient);
+        registerVariable(this->aimPosition_,       VariableDirection::ToServer);  // For the moment this variable gets only transfered to the server
+    }
+
+    void Pawn::tick(float dt)
+    {
+        //BigExplosion* chunk = new BigExplosion(this->getContext());
+        SUPER(Pawn, tick, dt);
+
+        // Recharge the shield
+        // TODO: use the existing timer functions instead
+        if(this->shieldRechargeWaitCountdown_ > 0)
+        {
+            this->decreaseShieldRechargeCountdownTime(dt);
+        }
+        else
+        {
+            this->addShieldHealth(this->getShieldRechargeRate() * dt);
+            this->resetShieldRechargeCountdown();
+        }
+
+        if (GameMode::isMaster())
+        {
+            if (this->health_ <= 0 && bAlive_)
+            {
+                this->fireEvent(); // Event to notify anyone who wants to know about the death.
+                this->death();
+            }
+        }
+    }
+
+    void Pawn::preDestroy()
+    {
+        // yay, multiple inheritance!
+        this->ControllableEntity::preDestroy();
+        this->PickupCarrier::preDestroy();
+    }
+
+    void Pawn::setPlayer(PlayerInfo* player)
+    {
+        ControllableEntity::setPlayer(player);
+
+        if (this->getGametype())
+            this->getGametype()->playerStartsControllingPawn(player, this);
+    }
+
+    void Pawn::removePlayer()
+    {
+        if (this->getGametype())
+            this->getGametype()->playerStopsControllingPawn(this->getPlayer(), this);
+
+        ControllableEntity::removePlayer();
+    }
+
+
+    void Pawn::setHealth(float health)
+    {
+        this->health_ = std::min(health, this->maxHealth_); //Health can't be set to a value bigger than maxHealth, otherwise it will be reduced at first hit
+    }
+
+    void Pawn::setShieldHealth(float shieldHealth)
+    {
+        this->shieldHealth_ = std::min(shieldHealth, this->maxShieldHealth_);
+    }
+
+    void Pawn::setMaxShieldHealth(float maxshieldhealth)
+    {
+        this->maxShieldHealth_ = maxshieldhealth;
+    }
+
+    void Pawn::setShieldRechargeRate(float shieldRechargeRate)
+    {
+        this->shieldRechargeRate_ = shieldRechargeRate;
+    }
+
+    void Pawn::setShieldRechargeWaitTime(float shieldRechargeWaitTime)
+    {
+        this->shieldRechargeWaitTime_ = shieldRechargeWaitTime;
+    }
+
+    void Pawn::decreaseShieldRechargeCountdownTime(float dt)
+    {
+        this->shieldRechargeWaitCountdown_ -= dt;
+    }
+
+    void Pawn::changedVulnerability()
+    {
+
+    }
+
+    void Pawn::damage(float damage, float healthdamage, float shielddamage, Pawn* originator, const btCollisionShape* cs)
+    {
+        // A pawn can only get damaged if it is vulnerable
+        if (!isVulnerable())
+        {
+            return;
+        }
+
+        // Applies multiplier given by the DamageBoost Pickup.
+        if (originator)
+            damage *= originator->getDamageMultiplier();
+
+        if (this->getGametype() && this->getGametype()->allowPawnDamage(this, originator))
+        {
+            // Health-damage cannot be absorbed by shields.
+            // Shield-damage only reduces shield health. 
+            // Normal damage can be (partially) absorbed by shields.
+
+            if (shielddamage >= this->getShieldHealth())
+            {
+                this->setShieldHealth(0);
+                this->setHealth(this->health_ - (healthdamage + damage));
+            }
+            else
+            {
+                this->setShieldHealth(this->shieldHealth_ - shielddamage);
+
+                // remove remaining shieldAbsorpton-Part of damage from shield
+                shielddamage = damage * this->shieldAbsorption_;
+                shielddamage = std::min(this->getShieldHealth(),shielddamage);
+                this->setShieldHealth(this->shieldHealth_ - shielddamage);
+
+                // set remaining damage to health
+                this->setHealth(this->health_ - (damage - shielddamage) - healthdamage);
+            }
+
+            this->lastHitOriginator_ = originator;
+        }
+    }
+
+// TODO: Still valid?
+/* HIT-Funktionen
+    Die hit-Funktionen muessen auch in src/orxonox/controllers/Controller.h angepasst werden! (Visuelle Effekte)
+
+*/
+    void Pawn::hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage)
+    {
+        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
+        {
+            this->damage(damage, healthdamage, shielddamage, originator, cs);
+            this->setVelocity(this->getVelocity() + force);
+        }
+    }
+
+    void Pawn::hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage, float shielddamage)
+    {
+        if (this->getGametype() && this->getGametype()->allowPawnHit(this, originator) && (!this->getController() || !this->getController()->getGodMode()) )
+        {
+            this->damage(damage, healthdamage, shielddamage, originator, cs);
+
+            if ( this->getController() )
+                this->getController()->hit(originator, contactpoint, damage); // changed to damage, why shielddamage?
+        }
+    }
+
+    void Pawn::kill()
+    {
+        this->damage(this->health_);
+        this->death();
+    }
+
+    void Pawn::spawneffect()
+    {
+        // play spawn effect
+        if (!this->spawnparticlesource_.empty())
+        {
+            ParticleSpawner* effect = new ParticleSpawner(this->getContext());
+            effect->setPosition(this->getPosition());
+            effect->setOrientation(this->getOrientation());
+            effect->setDestroyAfterLife(true);
+            effect->setSource(this->spawnparticlesource_);
+            effect->setLifetime(this->spawnparticleduration_);
+        }
+    }
+
+    void Pawn::death()
+    {
+        this->setHealth(1);
+        if (this->getGametype() && this->getGametype()->allowPawnDeath(this, this->lastHitOriginator_))
+        {
+            // Set bAlive_ to false and wait for destroyLater() to do the destruction
+            this->bAlive_ = false;
+            this->destroyLater();
+
+            this->setDestroyWhenPlayerLeft(false);
+
+            if (this->getGametype())
+                this->getGametype()->pawnKilled(this, this->lastHitOriginator_);
+
+            if (this->getPlayer() && this->getPlayer()->getControllableEntity() == this)
+            {
+                // Start to control a new entity if you're the master of a formation
+                if(this->hasSlaves())
+                {
+                    Controller* slave = this->getSlave();
+                    ControllableEntity* entity = slave->getControllableEntity();
+
+
+                    if(!entity->hasHumanController())
+                    {
+                        // delete the AIController // <-- TODO: delete? nothing is deleted here... should we delete the controller?
+                        slave->setControllableEntity(nullptr);
+
+                        // set a new master within the formation
+                        orxonox_cast<FormationController*>(this->getController())->setNewMasterWithinFormation(orxonox_cast<FormationController*>(slave));
+
+                        // start to control a slave
+                        this->getPlayer()->startControl(entity);
+                    }
+                    else
+                    {
+                        this->getPlayer()->stopControl();
+                    }
+
+                }
+                else
+                {
+                    this->getPlayer()->stopControl();
+                }
+            }
+            if (GameMode::isMaster())
+            {
+                this->goWithStyle();
+            }
+        }
+    }
+    void Pawn::goWithStyle()
+    {
+
+        this->bAlive_ = false;
+        this->setDestroyWhenPlayerLeft(false);
+
+        while(!explosionPartList_.empty())
+        {
+            explosionPartList_.back()->setPosition(this->getPosition());
+            explosionPartList_.back()->setVelocity(this->getVelocity());
+            explosionPartList_.back()->setOrientation(this->getOrientation());
+            explosionPartList_.back()->Explode();
+            explosionPartList_.pop_back();
+        }
+
+        for (unsigned int i = 0; i < this->numexplosionchunks_; ++i)
+        {
+            ExplosionChunk* chunk = new ExplosionChunk(this->getContext());
+            chunk->setPosition(this->getPosition());
+        }
+
+        this->explosionSound_->setPosition(this->getPosition());
+        this->explosionSound_->play();
+    }
+
+    /**
+    @brief
+        Check whether the Pawn has a @ref orxonox::WeaponSystem and fire it with the specified firemode if it has one.
+    */
+
+    void Pawn::fired(unsigned int firemode)
+    {
+        if (this->weaponSystem_)
+            this->weaponSystem_->fire(firemode);
+    }
+
+    void Pawn::postSpawn()
+    {
+        this->setHealth(this->initialHealth_);
+        if (GameMode::isMaster())
+            this->spawneffect();
+    }
+
+
+    void Pawn::addExplosionPart(ExplosionPart* ePart)
+    {this->explosionPartList_.push_back(ePart);}
+
+
+    ExplosionPart * Pawn::getExplosionPart()
+    {return this->explosionPartList_.back();}
+
+
+
+    /* WeaponSystem:
+    *   functions load Slot, Set, Pack from XML and make sure all parent-pointers are set.
+    *   with setWeaponPack you can not just load a Pack from XML but if a Pack already exists anywhere, you can attach it.
+    *       --> e.g. Pickup-Items
+    */
+    void Pawn::addWeaponSlot(WeaponSlot * wSlot)
+    {
+        this->attach(wSlot);
+        if (this->weaponSystem_)
+            this->weaponSystem_->addWeaponSlot(wSlot);
+    }
+
+    WeaponSlot * Pawn::getWeaponSlot(unsigned int index) const
+    {
+        if (this->weaponSystem_)
+            return this->weaponSystem_->getWeaponSlot(index);
+        else
+            return nullptr;
+    }
+
+    void Pawn::addWeaponSet(WeaponSet * wSet)
+    {
+        if (this->weaponSystem_)
+            this->weaponSystem_->addWeaponSet(wSet);
+    }
+
+    WeaponSet * Pawn::getWeaponSet(unsigned int index) const
+    {
+        if (this->weaponSystem_)
+            return this->weaponSystem_->getWeaponSet(index);
+        else
+            return nullptr;
+    }
+
+    void Pawn::addWeaponPack(WeaponPack * wPack)
+    {
+        if (this->weaponSystem_)
+        {
+            this->weaponSystem_->addWeaponPack(wPack);
+            this->addedWeaponPack(wPack);
+        }
+    }
+
+    void Pawn::addWeaponPackXML(WeaponPack * wPack)
+    {
+        if (this->weaponSystem_)
+        {
+            if (!this->weaponSystem_->addWeaponPack(wPack))
+                wPack->destroy();
+            else
+                this->addedWeaponPack(wPack);
+        }
+    }
+
+    WeaponPack * Pawn::getWeaponPack(unsigned int index) const
+    {
+        if (this->weaponSystem_)
+            return this->weaponSystem_->getWeaponPack(index);
+        else
+            return nullptr;
+    }
+
+    void Pawn::addMunitionXML(Munition* munition)
+    {
+        if (this->weaponSystem_ && munition)
+        {
+            this->weaponSystem_->addMunition(munition);
+        }
+    }
+
+    Munition* Pawn::getMunitionXML() const
+    {
+        return nullptr;
+    }
+
+    Munition* Pawn::getMunition(SubclassIdentifier<Munition> * identifier)
+    {
+        if (weaponSystem_)
+        {
+            return weaponSystem_->getMunition(identifier);
+        }
+
+        return nullptr;
+    }
+
+    //Tell the Map (RadarViewable), if this is a playership
+    void Pawn::startLocalHumanControl()
+    {
+//        SUPER(ControllableEntity, startLocalHumanControl());
+        ControllableEntity::startLocalHumanControl();
+        this->isHumanShip_ = true;
+    }
+
+    void Pawn::changedVisibility(void)
+    {
+        SUPER(Pawn, changedVisibility);
+
+        // enable proper radarviewability when the visibility is changed
+        this->RadarViewable::settingsChanged();
+    }
+
+
+    // A function to check if this pawn's controller is the master of any formationcontroller
+    bool Pawn::hasSlaves()
+    {
+        for (FormationController* controller : ObjectList<FormationController>())
+        {
+            // checks if the pawn's controller has a slave
+            if (this->hasHumanController() && controller->getMaster() == this->getPlayer()->getController())
+                return true;
+        }
+        return false;
+    }
+
+    // A function that returns a slave of the pawn's controller
+    Controller* Pawn::getSlave(){
+        for (FormationController* controller : ObjectList<FormationController>())
+        {
+            if (this->hasHumanController() && controller->getMaster() == this->getPlayer()->getController())
+                return controller->getController();
+        }
+        return nullptr;
+    }
+
+
+    void Pawn::setExplosionSound(const std::string &explosionSound)
+    {
+        if(explosionSound_ )
+            explosionSound_->setSource(explosionSound);
+        else
+            assert(0); // This should never happen, because soundpointer is only available on master
+    }
+
+    const std::string& Pawn::getExplosionSound()
+    {
+        if( explosionSound_ )
+            return explosionSound_->getSource();
+        else
+            assert(0);
+        return BLANKSTRING;
+    }
+
+    void Pawn::drawWeapons(bool bDraw)
+    {
+        if (bDraw)
+        {
+            std::vector<WeaponSlot*> weaponSlots = weaponSystem_->getAllWeaponSlots();
+            int numWeaponSlots = weaponSlots.size();
+            Vector3 slotPosition = Vector3::ZERO;
+            Quaternion slotOrientation = Quaternion::IDENTITY;
+            Model* slotModel = nullptr;
+
+            for (int i = 0; i < numWeaponSlots; ++i)
+            {
+                slotPosition = weaponSlots.at(i)->getPosition();
+                slotOrientation = weaponSlots.at(i)->getOrientation();
+                slotModel = new Model(this->getContext());
+                slotModel->setMeshSource("Coordinates.mesh");
+                slotModel->setScale(3.0f);
+                slotModel->setOrientation(slotOrientation);
+                slotModel->setPosition(slotPosition);
+
+                this->attach(slotModel);
+                debugWeaponSlotModels_.push_back(slotModel);
+            }
+        }
+        else
+        {
+            // delete all debug models
+            for(Model* model : debugWeaponSlotModels_) 
+            {
+                model->destroy();
+            }
+            debugWeaponSlotModels_.clear();
+        }
+    }
+
+    /*static*/ void Pawn::consoleCommand_debugDrawWeapons(bool bDraw)
+    {
+        if (bDraw)
+        {
+            orxout() << "WeaponSlot visualization enabled." << endl;
+        }
+        else
+        {
+            orxout() << "WeaponSlot visualization disabled." << endl;
+        }
+
+        ObjectList<Pawn> pawnList;
+        for (ObjectListIterator<Pawn> it = pawnList.begin(); it != pawnList.end(); ++it)
+        {
+            it->drawWeapons(bDraw);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Pawn.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Pawn.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Pawn.h	(revision 11817)
@@ -0,0 +1,292 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Pawn_H__
+#define _Pawn_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <vector>
+#include "interfaces/PickupCarrier.h"
+#include "interfaces/RadarViewable.h"
+#include "worldentities/ControllableEntity.h"
+#include "worldentities/ExplosionPart.h"
+
+
+namespace orxonox // tolua_export
+{
+    /**
+    @brief
+        Everything in Orxonox that has a health attribute is a Pawn. After a Pawn is spawned its health is set to
+        its initial health. In every call of the Pawns tick function the game checks whether the pawns health is at
+        or below zero. If it is, the pawn gets killed.
+
+        Pawns can carry pickups and fire weapons. They can also have shields.
+
+        Notice that every Pawn is a ControllableEntity.
+    */
+
+    // tolua_export
+    class _OrxonoxExport Pawn // tolua_export
+        : public ControllableEntity, public RadarViewable, public PickupCarrier
+    { // tolua_export
+        friend class WeaponSystem;
+
+        public:
+            Pawn(Context* context);
+            virtual ~Pawn();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void XMLEventPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual void tick(float dt) override;
+
+            inline bool isAlive() const
+                { return this->bAlive_; }
+
+
+            void setHealth(float health);
+            inline void addHealth(float health)
+                { this->setHealth(this->health_ + health); }
+            inline void removeHealth(float health)
+                { this->setHealth(this->health_ - health); }
+            inline float getHealth() const
+                { return this->health_; }
+
+            inline void setMaxHealth(float maxhealth)
+                { this->maxHealth_ = maxhealth; this->setHealth(this->health_); }
+            inline float getMaxHealth() const
+                { return this->maxHealth_; }
+
+            inline void setInitialHealth(float initialhealth)
+                { this->initialHealth_ = initialhealth; this->setHealth(initialhealth); }
+            inline float getInitialHealth() const
+                { return this->initialHealth_; }
+
+            void setShieldHealth(float shieldHealth);
+
+            inline float getShieldHealth()
+                { return this->shieldHealth_; }
+
+            inline void addShieldHealth(float amount)
+                { this->setShieldHealth(this->shieldHealth_ + amount); }
+
+            inline bool hasShield()
+                { return (this->getShieldHealth() > 0); }
+
+            void setMaxShieldHealth(float maxshieldhealth);
+            inline float getMaxShieldHealth() const
+                { return this->maxShieldHealth_; }
+
+            inline void setInitialShieldHealth(float initialshieldhealth)
+                { this->initialShieldHealth_ = initialshieldhealth; this->setShieldHealth(initialshieldhealth); }
+            inline float getInitialShieldHealth() const
+                { return this->initialShieldHealth_; }
+
+            inline void restoreInitialShieldHealth()
+                { this->setShieldHealth(this->initialShieldHealth_); }
+            inline void restoreMaxShieldHealth()
+                { this->setShieldHealth(this->maxShieldHealth_); }
+
+            inline void setShieldAbsorption(float shieldAbsorption)
+                { this->shieldAbsorption_ = shieldAbsorption; }
+            inline float getShieldAbsorption()
+                { return this->shieldAbsorption_; }
+
+            void setShieldRechargeRate(float shieldRechargeRate);
+            inline float getShieldRechargeRate() const
+                { return this->shieldRechargeRate_; }
+
+            void setShieldRechargeWaitTime(float shieldRechargeWaitTime);
+            inline float getShieldRechargeWaitTime() const
+                { return this->shieldRechargeWaitTime_; }
+
+            inline void resetShieldRechargeCountdown()
+                { this->shieldRechargeWaitCountdown_ = 0; }
+
+            inline void startShieldRechargeCountdown()
+                { this->shieldRechargeWaitCountdown_ = this->getShieldRechargeWaitTime(); } // TODO: Implement in Projectile.cc
+
+            void decreaseShieldRechargeCountdownTime(float dt);
+
+            /** @brief Sets the state of the pawns vulnerability. @param bVulnerable */
+            inline void setVulnerable(bool bVulnerable)
+            {
+                if (this->bVulnerable_ != bVulnerable)
+                {
+                    this->bVulnerable_ = bVulnerable;
+                    this->changedVulnerability();
+                }
+            }
+            /** @brief Returns the state of the pawns vulnerability. @return The state of the vulnerability */
+            inline const bool& isVulnerable() const { return this->bVulnerable_; }
+            /** @brief This function gets called if the vulnerability of the pawn changes. */
+            virtual void changedVulnerability();
+
+            inline ControllableEntity* getLastHitOriginator() const
+                { return this->lastHitOriginator_; }
+
+            virtual void hit(Pawn* originator, const Vector3& force, const btCollisionShape* cs, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
+            virtual void hit(Pawn* originator, btManifoldPoint& contactpoint, const btCollisionShape* cs, float damage, float healthdamage = 0.0f, float shielddamage = 0.0f);
+
+            virtual void kill();
+
+            virtual void fired(unsigned int firemode) override;
+            virtual void postSpawn();
+
+            void addExplosionPart(ExplosionPart* ePart);
+            ExplosionPart * getExplosionPart();
+
+            void addWeaponSlot(WeaponSlot * wSlot);
+            WeaponSlot * getWeaponSlot(unsigned int index) const;
+            void addWeaponSet(WeaponSet * wSet);
+            WeaponSet * getWeaponSet(unsigned int index) const;
+            void addWeaponPack(WeaponPack * wPack);
+            void addWeaponPackXML(WeaponPack * wPack);
+            WeaponPack * getWeaponPack(unsigned int index) const;
+
+            void addMunitionXML(Munition* munition);
+            Munition* getMunitionXML() const;
+            
+            Munition* getMunition(SubclassIdentifier<Munition> * identifier);
+
+            virtual void addedWeaponPack(WeaponPack* wPack) {}
+
+            inline void setSpawnParticleSource(const std::string& source)
+                { this->spawnparticlesource_ = source; }
+            inline const std::string& getSpawnParticleSource() const
+                { return this->spawnparticlesource_; }
+
+            inline void setSpawnParticleDuration(float duration)
+                { this->spawnparticleduration_ = duration; }
+            inline float getSpawnParticleDuration() const
+                { return this->spawnparticleduration_; }
+
+            inline void setExplosionChunks(unsigned int chunks)
+                { this->numexplosionchunks_ = chunks; }
+            inline unsigned int getExplosionChunks() const
+                { return this->numexplosionchunks_; }
+
+            // These are used with the Damage Boost Pickup to use the damage multiplier.
+            inline void setDamageMultiplier(float multiplier)
+                { this->damageMultiplier_ = multiplier; }
+            inline float getDamageMultiplier() const
+                { return this->damageMultiplier_; }
+
+            // Some pawns can-t harvest pickups (e.g. AsteroidMinables). Checked in PickupSpawner. 
+            inline void setPickupAcceptance(bool b)
+                { this->acceptsPickups_ = b; }
+            inline bool doesAcceptPickups()
+                { return this->acceptsPickups_;}
+
+            virtual void startLocalHumanControl() override;
+
+            void setAimPosition( Vector3 position )
+                { this->aimPosition_ = position; }
+            Vector3 getAimPosition()
+                { return this->aimPosition_; }
+
+            virtual const Vector3& getCarrierPosition(void) const override
+                { return this->getWorldPosition(); };
+
+            virtual void changedVisibility() override;
+
+            void setExplosionSound(const std::string& engineSound);
+            const std::string& getExplosionSound();
+
+            inline const WeaponSystem* getWeaponSystem() const
+                { return this->weaponSystem_; }
+
+            static void consoleCommand_debugDrawWeapons(bool bDraw); 
+
+
+
+        protected:
+            virtual void preDestroy() override;
+
+            virtual void setPlayer(PlayerInfo* player) override;
+            virtual void removePlayer() override;
+
+            virtual void death();
+            virtual bool hasSlaves();
+            virtual Controller* getSlave();
+            virtual void goWithStyle();
+            virtual void spawneffect();
+
+            virtual void damage(float damage, float healthdamage = 0.0f, float shielddamage = 0.0f, Pawn* originator = nullptr, const btCollisionShape* cs = nullptr);
+
+            bool bAlive_;
+            bool bVulnerable_; ///< If this is false, then the pawn may not take damage
+
+            virtual std::vector<PickupCarrier*>* getCarrierChildren(void) const override
+                { return new std::vector<PickupCarrier*>(); }
+            virtual PickupCarrier* getCarrierParent(void) const override
+                { return nullptr; }
+
+
+            float health_;
+            float maxHealth_;
+            float initialHealth_;
+
+            float shieldHealth_;
+            float maxShieldHealth_;
+            float initialShieldHealth_;
+            float shieldAbsorption_; ///< Has to be between 0 and 1
+            float shieldRechargeRate_;
+            float shieldRechargeWaitTime_;
+            float shieldRechargeWaitCountdown_;
+
+            float damageMultiplier_; ///< Used by the Damage Boost Pickup.
+            bool acceptsPickups_; // Added for the asteroidMinable class, avoid that they attempt to grab the resources
+
+            WeakPtr<Pawn> lastHitOriginator_;
+
+            WeaponSystem* weaponSystem_;
+
+            std::string spawnparticlesource_;
+            float spawnparticleduration_;
+            unsigned int numexplosionchunks_;
+
+            std::vector<ExplosionPart*> explosionPartList_;
+
+        private:
+            void registerVariables();
+            inline void setWeaponSystem(WeaponSystem* weaponsystem)
+                { this->weaponSystem_ = weaponsystem; }
+            void drawWeapons(bool bDraw);
+
+            Vector3 aimPosition_;
+
+            WorldSound* explosionSound_; // TODO: Does this really belong here? Maybe move it to BigExplosion?
+
+            std::vector<Model*> debugWeaponSlotModels_;
+
+    }; // tolua_export
+} // tolua_export
+
+#endif /* _Pawn_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ShootableObstacle.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ShootableObstacle.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ShootableObstacle.cc	(revision 11817)
@@ -0,0 +1,63 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leon Rigoni
+ *
+ */
+
+#include "ShootableObstacle.h"
+#include "core/XMLPort.h"
+
+namespace orxonox
+{
+    RegisterClass(ShootableObstacle);
+
+    ShootableObstacle::ShootableObstacle(Context* context) : Pawn(context)
+    {
+        RegisterObject(ShootableObstacle);
+        this->enableCollisionCallback();
+    }
+
+    bool ShootableObstacle::collidesAgainst(WorldEntity* otherObject, const btCollisionShape* ownCollisionShape, btManifoldPoint& contactPoint)
+    {
+        if (GameMode::isMaster() && enableCollisionDamage_)
+        {
+            Pawn* victim = orxonox_cast<Pawn*>(otherObject);
+            if (victim)
+            {
+                float damage = this->collisionDamage_ * (victim->getVelocity() - this->getVelocity()).length();
+                victim->hit(nullptr, contactPoint, ownCollisionShape, damage);
+            }
+        }
+
+        return false;
+    }
+
+    void ShootableObstacle::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(ShootableObstacle, XMLPort, xmlelement, mode);
+
+        XMLPortParam(ShootableObstacle, "enablecollisiondamage", setEnableCollisionDamage, getEnableCollisionDamage, xmlelement, mode).defaultValues(false);
+        XMLPortParam(ShootableObstacle, "collisiondamage", setCollisionDamage, getCollisionDamage, xmlelement, mode).defaultValues(1);
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ShootableObstacle.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ShootableObstacle.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/ShootableObstacle.h	(revision 11817)
@@ -0,0 +1,66 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Leon Rigoni
+ *
+ */
+#ifndef _ShootableObstacle_H__
+#define _ShootableObstacle_H__
+#include "worldentities/pawns/Pawn.h"
+
+namespace orxonox // tolua_export
+{
+    /**
+    @brief
+        This class encapsulates a pawn (so an object with health) with the addition, that it damages other objects when it hits them.
+    */
+
+    class _OrxonoxExport ShootableObstacle
+        : public Pawn
+    {
+        public:
+            ShootableObstacle(Context* context);
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override;
+            virtual bool collidesAgainst(WorldEntity* otherObject, const btCollisionShape* cs, btManifoldPoint& contactPoint) override;
+
+            inline void setCollisionDamage(float c)
+                    { this->collisionDamage_ = c; }
+
+            inline float getCollisionDamage()
+                { return this->collisionDamage_; }
+
+            inline void setEnableCollisionDamage(bool c)
+            {
+                this->enableCollisionDamage_ = c;
+                this->enableCollisionCallback();
+            }
+
+            inline bool getEnableCollisionDamage()
+                { return this->enableCollisionDamage_; }
+
+        private:
+            float collisionDamage_;
+            bool enableCollisionDamage_;
+    };
+}
+
+#endif
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/SpaceShip.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/SpaceShip.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/SpaceShip.cc	(revision 11817)
@@ -0,0 +1,559 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "SpaceShip.h"
+
+#include <BulletDynamics/Dynamics/btRigidBody.h>
+
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/Template.h"
+#include "core/XMLPort.h"
+#include "tools/Shader.h"
+#include "util/Math.h"
+
+#include "graphics/Camera.h"
+#include "items/Engine.h"
+
+#include "CameraManager.h"
+#include "Scene.h"
+
+namespace orxonox
+{
+    RegisterClass(SpaceShip);
+
+    SpaceShip::SpaceShip(Context* context) : Pawn(context), boostBlur_(nullptr)
+    {
+        RegisterObject(SpaceShip);
+
+        this->bInvertYAxis_ = false;
+
+        this->steering_ = Vector3::ZERO;
+
+        this->rotationThrust_ =  10;
+        this->localAngularAcceleration_.setValue(0, 0, 0);
+
+        this->bBoost_ = false;
+        this->bBoostCooldown_ = false;
+        this->initialBoostPower_ = 10.0f;
+        this->boostPower_ = 10.0f;
+        this->boostPowerRate_ = 1.0f;
+        this->boostRate_ = 5.0f;
+        this->boostCooldownDuration_ = 5.0f;
+
+        this->shakeFrequency_ = 15.0f;
+        this->shakeAmplitude_ = 5.0f;
+        this->shakeDt_ = 0.0f;
+        this->cameraOriginalPosition_ = Vector3::UNIT_SCALE;
+        this->cameraOriginalOrientation_ = Quaternion::IDENTITY;
+
+        this->lift_ = 1.0f;
+        this->stallSpeed_ = 220.0f;
+
+        this->setDestroyWhenPlayerLeft(true);
+
+        // SpaceShip is always a physical object per default
+        // Be aware of this call: The collision type legality check will not reach derived classes!
+        this->setCollisionType(WorldEntity::CollisionType::Dynamic);
+        // Get notification about collisions
+        this->enableCollisionCallback();
+
+        this->setConfigValues();
+        this->registerVariables();
+
+    }
+
+    SpaceShip::~SpaceShip()
+    {
+        if (this->isInitialized())
+        {
+            this->removeAllEngines();
+
+            if (this->boostBlur_)
+                delete this->boostBlur_;
+        }
+    }
+
+    void SpaceShip::XMLPort(Element& xmlelement, XMLPort::Mode mode)
+    {
+        SUPER(SpaceShip, XMLPort, xmlelement, mode);
+
+        XMLPortParamVariable(SpaceShip, "rotationThrust", rotationThrust_, xmlelement, mode);
+        XMLPortParam(SpaceShip, "boostPower", setInitialBoostPower, getInitialBoostPower, xmlelement, mode);
+        XMLPortParam(SpaceShip, "boostPowerRate", setBoostPowerRate, getBoostPowerRate, xmlelement, mode);
+        XMLPortParam(SpaceShip, "boostRate", setBoostRate, getBoostRate, xmlelement, mode);
+        XMLPortParam(SpaceShip, "boostCooldownDuration", setBoostCooldownDuration, getBoostCooldownDuration, xmlelement, mode);
+        XMLPortParam(SpaceShip, "shakeFrequency", setShakeFrequency, getShakeFrequency, xmlelement, mode);
+        XMLPortParam(SpaceShip, "shakeAmplitude", setShakeAmplitude, getShakeAmplitude, xmlelement, mode);
+        XMLPortParamVariable(SpaceShip, "lift", lift_, xmlelement, mode);
+        XMLPortParamVariable(SpaceShip, "stallSpeed", stallSpeed_, xmlelement, mode);
+
+        XMLPortObject(SpaceShip, Engine, "engines", addEngine, getEngine, xmlelement, mode);
+
+        
+    }
+
+    void SpaceShip::registerVariables()
+    {
+        registerVariable(this->rotationThrust_, VariableDirection::ToClient);
+        registerVariable(this->boostPower_, VariableDirection::ToClient);
+        registerVariable(this->boostPowerRate_, VariableDirection::ToClient);
+        registerVariable(this->boostRate_, VariableDirection::ToClient);
+        registerVariable(this->boostCooldownDuration_, VariableDirection::ToClient);
+        registerVariable(this->shakeFrequency_, VariableDirection::ToClient);
+        registerVariable(this->shakeAmplitude_, VariableDirection::ToClient);
+        registerVariable(this->lift_, VariableDirection::ToClient);
+        registerVariable(this->stallSpeed_, VariableDirection::ToClient);
+    }
+
+    void SpaceShip::setConfigValues()
+    {
+        SetConfigValue(bInvertYAxis_, false).description("Set this to true for joystick-like mouse behaviour (mouse up = ship down).");
+
+        SetConfigValueExternal(bEnableMotionBlur_, "GraphicsSettings", "enableMotionBlur", true)
+            .description("Enable or disable the motion blur effect when moving very fast")
+            .callback(this, &SpaceShip::changedEnableMotionBlur);
+        SetConfigValueExternal(blurStrength_, "GraphicsSettings", "blurStrength", 3.0f)
+            .description("Defines the strength of the motion blur effect");
+    }
+
+    bool SpaceShip::isCollisionTypeLegal(WorldEntity::CollisionType type) const
+    {
+        if (type != WorldEntity::CollisionType::Dynamic)
+        {
+            orxout(internal_warning) << "Cannot tell a SpaceShip not to be dynamic! Ignoring." << endl;
+            assert(false); // Only in debug mode
+            return false;
+        }
+        else
+            return true;
+    }
+
+    void SpaceShip::tick(float dt)
+    {
+        SUPER(SpaceShip, tick, dt);
+
+        // Run the engines
+        for(Engine* engine : this->engineList_)
+            engine->run(dt);
+
+        if (this->hasLocalController())
+        {
+            // If not in mouse look apply the angular movement to the ship.
+            if (!this->isInMouseLook())
+            {
+                this->localAngularAcceleration_ *= this->getLocalInertia() * this->rotationThrust_;
+                this->physicalBody_->applyTorque(physicalBody_->getWorldTransform().getBasis() * this->localAngularAcceleration_);
+            }
+            this->localAngularAcceleration_.setValue(0, 0, 0);
+
+            // If not in boost cooldown, the boost power is recharged up to the initial boost power.
+            if(!this->isBoostCoolingDown() && this->boostPower_ < this->initialBoostPower_)
+            {
+                this->boostPower_ += this->boostPowerRate_*dt;
+            }
+            // If boosting
+            if(this->isBoosting())
+            {
+                // Discount the used power
+                this->boostPower_ -= this->boostRate_*dt;
+                // If the power has been used up boosting is stopped and boost cooldown is initiated.
+                if(this->boostPower_ <= 0.0f)
+                {
+                    this->boost(false);
+                    this->bBoostCooldown_ = true;
+                    this->timer_.setTimer(this->boostCooldownDuration_, false, createExecutor(createFunctor(&SpaceShip::boostCooledDown, this)));
+                }
+
+                // Shake the camera because of the boosting.
+                this->shakeCamera(dt);
+            }
+
+            // Enable Blur depending on settings
+            if(this->bEnableMotionBlur_)
+            {
+                if (this->boostBlur_ == nullptr && this->hasLocalController() && this->hasHumanController())
+                {
+                    this->boostBlur_ = new Shader(this->getScene()->getSceneManager());
+                    this->boostBlur_->setCompositorName("Radial Blur");
+                }
+                if (this->boostBlur_)
+                {
+                    float blur = this->blurStrength_ * clamp(-this->getLocalVelocity().z/(this->getMaxSpeedFront()*this->getBoostFactor()), 0.0f, 1.0f);
+
+                    // Show and hide blur effect depending on state of booster
+                    if(this->isBoosting())
+                        this->boostBlur_->setVisible(blur > 0.0f);
+                    else
+                        this->boostBlur_->setVisible(false);
+
+                    this->boostBlur_->setParameter(0, 0, "sampleStrength", blur);
+                }
+            }
+        }
+
+        this->steering_ = Vector3::ZERO;
+    }
+
+    /**
+    @brief
+        Rotate in yaw direction.
+        Due to added lift, can also lead to an additional right-left motion.
+    @param value
+        A vector whose first component specifies the magnitude of the rotation. Positive means yaw left, negative means yaw right.
+    */
+    void SpaceShip::rotateYaw(const Vector2& value)
+    {
+        this->localAngularAcceleration_.setY(this->localAngularAcceleration_.y() + value.x);
+
+        Pawn::rotateYaw(value);
+
+        // This function call adds a lift to the ship when it is rotating to make it's movement more "realistic" and enhance the feeling.
+        if (this->getLocalVelocity().z < 0 && std::abs(this->getLocalVelocity().z) < stallSpeed_)
+            this->moveRightLeft(-lift_ / 5.0f * value * sqrt(std::abs(this->getLocalVelocity().z)));
+    }
+
+    /**
+    @brief
+        Rotate in pitch direction.
+        Due to added left, can also lead to an additional up-down motion.
+    @param value
+        A vector whose first component specifies the magnitude of the rotation. Positive means pitch up, negative means pitch down.
+    */
+    void SpaceShip::rotatePitch(const Vector2& value)
+    {
+        Vector2 pitch = value;
+        if(this->bInvertYAxis_)
+            pitch.x = -pitch.x;
+
+        this->localAngularAcceleration_.setX(this->localAngularAcceleration_.x() + pitch.x*0.8f);
+
+        Pawn::rotatePitch(pitch);
+
+        // This function call adds a lift to the ship when it is pitching to make it's movement more "realistic" and enhance the feeling.
+        if (this->getLocalVelocity().z < 0 && std::abs(this->getLocalVelocity().z) < stallSpeed_)
+            this->moveUpDown(lift_ / 5.0f * pitch * sqrt(std::abs(this->getLocalVelocity().z)));
+    }
+
+    /**
+    @brief
+        Rotate in roll direction.
+    @param value
+        A vector whose first component specifies the magnitude of the rotation. Positive means roll left, negative means roll right.
+    */
+    void SpaceShip::rotateRoll(const Vector2& value)
+    {
+        this->localAngularAcceleration_.setZ(this->localAngularAcceleration_.z() + value.x);
+
+        Pawn::rotateRoll(value);
+    }
+
+    void SpaceShip::fire()
+    {
+    }
+
+    /**
+    @brief
+        Starts or stops boosting.
+    @param bBoost
+        Whether to start or stop boosting.
+    */
+    void SpaceShip::boost(bool bBoost)
+    {
+        // Can only boost if not cooling down.
+        if(bBoost && !this->isBoostCoolingDown())
+        {
+            this->bBoost_ = true;
+            this->backupCamera();
+        }
+        // Stop boosting.
+        if(!bBoost)
+        {
+            this->bBoost_ = false;
+            this->resetCamera();
+        }
+    }
+
+    void SpaceShip::gainBoostPower(float gainedBoostPower)
+    {
+        this->boostPower_ += gainedBoostPower;
+        
+        if (this->boostPower_ > this->initialBoostPower_)
+        {
+            this->boostPower_ = this->initialBoostPower_;
+        }
+
+        // If the booster is in cooldown mode and we gained boost power, the abort the cooldown.
+        if (this->isBoostCoolingDown() && this->boostPower_ > 0.0f)
+        {
+            timer_.stopTimer();
+            this->boostCooledDown();
+        }
+    }
+
+    /**
+    @brief
+        Add an Engine to the SpaceShip.
+    @param engine
+        A pointer to the Engine to be added.
+    */
+    void SpaceShip::addEngine(orxonox::Engine* engine)
+    {
+        OrxAssert(engine != nullptr, "The engine cannot be nullptr.");
+        this->engineList_.push_back(engine);
+        engine->addToSpaceShip(this);
+    }
+
+    /**
+    @brief
+        Check whether the SpaceShip has a particular Engine.
+    @param search
+        A pointer to the Engine to be checked.
+    */
+    bool SpaceShip::hasEngine(Engine* search) const
+    {
+        for(Engine* engine : this->engineList_)
+        {
+            if(engine == search)
+                return true;
+        }
+        return false;
+    }
+
+    /**
+    @brief
+        Get the i-th Engine of the SpaceShip.
+    @return
+        Returns a pointer to the i-the Engine. nullptr if there is no Engine with that index.
+    */
+    Engine* SpaceShip::getEngine(unsigned int i)
+    {
+        if(this->engineList_.size() >= i)
+            return nullptr;
+        else
+            return this->engineList_[i];
+    }
+
+    /**
+    @brief
+        Looks for an attached Engine with a certain name.
+    @param name
+        The name of the engine to be returned.
+    @return
+        Pointer to the engine with the given name, or nullptr if not found.
+    */
+    Engine* SpaceShip::getEngineByName(const std::string& name)
+    {
+        for(Engine* engine : this->engineList_)
+            if(engine->getName() == name)
+                return engine;
+
+        orxout(internal_warning) << "Couldn't find Engine with name \"" << name << "\"." << endl;
+        return nullptr;
+    }
+
+    /**
+    @brief
+        Remove and destroy all Engines of the SpaceShip.
+    */
+    void SpaceShip::removeAllEngines()
+    {
+        while(this->engineList_.size())
+            this->engineList_.back()->destroy();
+    }
+
+    /**
+    @brief
+        Remove a particular Engine from the SpaceShip.
+    @param engine
+        A pointer to the Engine to be removed.
+    @note
+        Don't forget to reset the Engine's ship pointer after it was removed (or destroy the engine).
+    */
+    void SpaceShip::removeEngine(Engine* engine)
+    {
+        for(std::vector<Engine*>::iterator it = this->engineList_.begin(); it != this->engineList_.end(); ++it)
+        {
+            if(*it == engine)
+            {
+                this->engineList_.erase(it);
+                return;
+            }
+        }
+    }
+
+    /**
+    @brief
+        Add to the speed factor for all engines of the SpaceShip.
+    @param factor
+        The factor to be added.
+    */
+    void SpaceShip::addSpeedFactor(float factor)
+    {
+        for(Engine* engine : this->engineList_)
+            engine->addSpeedMultiply(factor);
+    }
+
+    /**
+    @brief
+        Add to the speed factor for all engines of the SpaceShip.
+    @param speed
+        The speed to be added.
+    */
+    void SpaceShip::addSpeed(float speed)
+    {
+        for(Engine* engine : this->engineList_)
+            engine->addSpeedAdd(speed);
+    }
+
+    /**
+    @brief
+        Get the mean speed factor over all engines of the SpaceShip.
+    @return
+        Returns the mean speed factor over all engines of the SpaceShip.
+    */
+    float SpaceShip::getSpeedFactor() const
+    {
+        float sum = 0;
+        unsigned int i = 0;
+        for(; i<this->engineList_.size(); i++)
+            sum += this->engineList_[i]->getSpeedMultiply();
+        return sum/float(i);
+    }
+
+    /**
+    @brief
+        Get the largest maximal forward speed over all engines of the SpaceShip.
+    @return
+        Returns the largest forward speed over all engines of the SpaceShip.
+    */
+    float SpaceShip::getMaxSpeedFront() const
+    {
+        float speed=0;
+        for(Engine* engine : this->engineList_)
+        {
+            if(engine->getMaxSpeedFront() > speed)
+                speed = engine->getMaxSpeedFront();
+        }
+        return speed;
+    }
+
+    /**
+    @brief
+        Get the mean boost factor over all engines of the SpaceShip.
+    @return
+        Returns the mean boost factor over all engines of the SpaceShip.
+    */
+    float SpaceShip::getBoostFactor() const
+    {
+        float sum = 0;
+        unsigned int i=0;
+        for(; i<this->engineList_.size(); i++)
+            sum += this->engineList_[i]->getBoostFactor();
+        return sum/float(i);
+    }
+
+    /**
+    @brief
+        Is called when the enableMotionBlur config value has changed.
+    */
+    void SpaceShip::changedEnableMotionBlur()
+    {
+        if (!this->bEnableMotionBlur_ && this->boostBlur_ != nullptr)
+        {
+            delete this->boostBlur_;
+            this->boostBlur_ = nullptr;
+        }
+    }
+
+    /**
+    @brief
+        Shake the camera for a given time interval.
+    @param dt
+        The time interval in seconds.
+    */
+    void SpaceShip::shakeCamera(float dt)
+    {
+        // Make sure the ship is only shaking if it's moving forward and above the maximal forward speed.
+        if (-this->getLocalVelocity().z > this->getMaxSpeedFront())
+        {
+            this->shakeDt_ += dt;
+
+            float frequency = this->shakeFrequency_ * (square(std::abs(this->getLocalVelocity().z)));
+
+            if (this->shakeDt_ >= 1.0f/frequency)
+                this->shakeDt_ -= 1.0f/frequency;
+
+            Degree angle = Degree(sin(this->shakeDt_ * math::twoPi * frequency) * this->shakeAmplitude_);
+
+            Camera* camera = this->getCamera();
+            //Shaking Camera effect
+            if (camera != nullptr)
+                camera->setOrientation(Vector3::UNIT_X, angle);
+
+        }
+        // If the camera is no shaking, reset it.
+        else
+            this->resetCamera();
+    }
+
+    /**
+    @brief
+        Save the original position and orientation of the camera.
+    */
+    void SpaceShip::backupCamera()
+    {
+        Camera* camera = CameraManager::getInstance().getActiveCamera();
+        if(camera != nullptr)
+        {
+            this->cameraOriginalPosition_ = camera->getPosition();
+            this->cameraOriginalOrientation_ = camera->getOrientation();
+        }
+    }
+
+    /**
+    @brief
+        Reset the camera to its original position.
+    */
+    void SpaceShip::resetCamera()
+    {
+        if(this->hasLocalController() && this->hasHumanController())
+        {
+            Camera *camera = this->getCamera();
+            if (camera == nullptr)
+            {
+                orxout(internal_warning) << "Failed to reset camera!" << endl;
+                return;
+            }
+            this->shakeDt_ = 0.0f;
+            camera->setPosition(this->cameraOriginalPosition_);
+            camera->setOrientation(this->cameraOriginalOrientation_);
+        }
+    }
+
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/SpaceShip.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/SpaceShip.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/SpaceShip.h	(revision 11817)
@@ -0,0 +1,310 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _SpaceShip_H__
+#define _SpaceShip_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include <string>
+#include <LinearMath/btVector3.h>
+
+#include "tools/Timer.h"
+#include "util/Math.h"
+#include "util/OrxAssert.h"
+
+#include "Pawn.h"
+
+namespace orxonox
+{
+
+    /**
+    @brief
+        The SpaceShip is the principal entity through which the player interacts with the game. Its main function is to fly, however many things, such as @ref orxonox::Engine Engines or @ref orxonox::Weapon Weapons, can be attached to it.
+        The feature that you can add @ref orxonox::Engine Engines is new in this class. However adding @ref orxonox::Weapon Weapons is possible because every Spaceship is a Pawn (due to inheritance) and every Pawn can carry @ref orxonox::Weapon Weapons.
+
+        There are several parameters that define the behavior of the SpaceShip>
+        - The <b>rotationThrust</b>, specifies the force with which the SpaceShip rotates.
+        - The <b>boost</b>, there are quite some parameters pertaining to boosting. The boost is a special move of the SpaceShip, where, for a limited amount of time, it can fly considerably faster than usual. The <b>boostPower</b> is the amount of power available for boosting. The <b>boostPowerRate</b> is the rate at which the boost power is replenished. The <b>boostRate</b> is the rate at which boosting uses power. And the <b>boostCooldownDuration</b> is the time the SpaceShip cannot boost, once all the boost power has been used up. Naturally all of these parameters must be non-negative.
+        - The <b>boost shaking</b>, when the SpaceShip boosts, the camera shakes to create a more immersive effect. Two parameters can be used to adjust the effect. The <b>shakeFrequency</b> is the frequency with which the camera shakes. And the <b>shakeAmplitude</b> is the amount with which the camera shakes. Again these parameters must bee non-negative.
+        - The <b>lift</b> creates a more natural flight feeling through the addition of a lift force. There are again two parameters that can be specified. The <b>lift</b> which is the lift force that is applied. And the <b>stallSpeed</b> which is the forward speed after which no more lift is generated.
+
+        A spaceship always needs to have the collision type "dynamic". Other collision types are illegal.
+
+        As mentioned @ref orxonox::Engine Engines can be mounted on the SpaceShip. Here is a (primitive) example of a SpaceShip defined in XML:
+        @code
+        <SpaceShip
+            rotationThrust    = 50
+
+            lift = 1;
+            stallSpeed = 220;
+
+            boostPower            = 15
+            boostPowerRate        = 1
+            boostRate             = 5
+            boostCooldownDuration = 10
+
+            shakeFrequency = 15
+            shakeAmplitude = 9
+
+            collisionType     = "dynamic"
+            mass              = 100
+            linearDamping     = 0.7
+            angularDamping    = 0.9999999
+            >
+                <engines>
+                    <Engine />
+                    <Engine />
+                </engines>
+            </SpaceShip>
+        @endcode
+
+    @author
+        Fabian 'x3n' Landau
+    */
+    class _OrxonoxExport SpaceShip : public Pawn
+    {
+        public:
+            SpaceShip(Context* context);
+            virtual ~SpaceShip();
+
+            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
+            virtual void tick(float dt);
+            void setConfigValues();
+
+            /**
+            @brief Move forward or backward,
+            @param value A vector whose first component specifies the amount of movement. Positive means forward, negative means backward.
+            */
+            virtual void moveFrontBack(const Vector2& value)
+                { this->steering_.z -= value.x; }
+            /**
+            @brief Move right or left.
+            @param value A vector whose first component specifies the amount of movement. Positive means right, negative means left.
+            */
+            virtual void moveRightLeft(const Vector2& value)
+                { this->steering_.x += value.x; }
+            /**
+            @brief Move up or down.
+            @param value A vector whose first component specifies the amount of movement. Positive means up, negative means down.
+            */
+            virtual void moveUpDown(const Vector2& value)
+                { this->steering_.y += value.x; }
+
+            virtual void rotateYaw(const Vector2& value); // Rotate in yaw direction.
+            virtual void rotatePitch(const Vector2& value); // Rotate in pitch direction.
+            virtual void rotateRoll(const Vector2& value); // Rotate in roll direction.
+
+            virtual void fire();
+            virtual void boost(bool bBoost); // Starts or stops boosting.
+
+            void addEngine(Engine* engine); // Add an Engine to the SpaceShip.
+            bool hasEngine(Engine* engine) const; // Check whether the SpaceShip has a particular Engine.
+            Engine* getEngine(unsigned int i); // Get the i-th Engine of the SpaceShip.
+            Engine* getEngineByName(const std::string& name);
+            /**
+            @brief Get the list of all Engines that are mounted on the SpaceShip.
+            @return Returns a vector of all Engines of the SpaceShip.
+            */
+            inline const std::vector<Engine*>& getEngineList() const
+                { return this->engineList_; }
+            void removeEngine(Engine* engine); // Remove and destroy all Engines of the SpaceShip.
+            void removeAllEngines(); // Remove a particular Engine from the SpaceShip.
+
+            void addSpeedFactor(float factor); // Add to the speed factor for all engines of the SpaceShip.
+            void addSpeed(float speed); // Add to the speed of all engines of the SpaceShip.
+            float getSpeedFactor() const; // Get the mean speed factor over all engines of the SpaceShip.
+    
+            float getMaxSpeedFront() const; // Get the largest maximal forward speed over all engines of the SpaceShip.
+            float getBoostFactor() const; // Get the mean boost factor over all engines of the SpaceShip.
+
+            /**
+            @brief Set the steering direction of the SpaceShip.
+                   This is set through the user input.
+            @param direction The direction the SpaceShip should steer in.
+            */
+            inline void setSteeringDirection(const Vector3& direction)
+                { this->steering_ = direction; }
+            /**
+            @brief Get the steering direction of the SpaceShip.
+            @return Returns the steering direction of the SpaceShip. The length of the vector is the amount of steering needed.
+            */
+            inline const Vector3& getSteeringDirection() const
+                { return this->steering_; }
+
+            /**
+            @brief Check whether the SpaceShip is currently boosting.
+            @return Returns true if the SpaceShip is boosting, false if not.
+            */
+            inline bool isBoosting() const
+                { return this->bBoost_; }
+            /**
+            @brief Check whether the SpaceShip boost is cooling down.
+            @return Returns true if the SpaceShip is cooling down from boosting.
+            */
+            inline bool isBoostCoolingDown() const
+                { return bBoostCooldown_; }
+
+            /**
+            @brief Set the initial power available for boosting to the input value.
+                   The current boost power is set to the input value as well.
+            @param power The initial boost power. Must be non-negative.
+            */
+            inline void setInitialBoostPower(float power)
+                { OrxAssert(power >= 0.0f, "The boost power must be non-negative."); this->initialBoostPower_ = power; this->boostPower_ = power; }
+            /**
+            @brief Set the rate, at which boost power is recharged, to the input value.
+            @param rate The boost power rate in units per second. Must be non-negative.
+            */
+            inline void setBoostPowerRate(float rate)
+                { OrxAssert(rate >= 0.0f, "The boost power rate must be non-negative."); this->boostPowerRate_ = rate; }
+            /**
+            @brief Set the rate, at which boost power us used up, to the input value.
+            @param rate The boost rate in units per second. Must be non-negative.
+            */
+            inline void setBoostRate(float rate)
+                { OrxAssert(rate >= 0.0f, "The boost rate must be non-negative."); this->boostRate_ = rate; }
+            /**
+            @brief Set the duration for which boosting, if in cooldown, is not possible.
+                   Cooldown is reached if all boost power is depleted.
+            @param duration The cooldown duration in seconds. Must be non-negative.
+            */
+            inline void setBoostCooldownDuration(float duration)
+                { OrxAssert(duration >= 0.0f, "The boost cooldown duration must be non-negative."); this->boostCooldownDuration_ = duration; }
+            /**
+            @brief Set the frequency with which the camera shakes during boosting.
+            @param frequency The frequency in times per second. Must be non-negative.
+            */
+            inline void setShakeFrequency(float frequency)
+                { OrxAssert(frequency >= 0.0f, "The shake frequency must be non-negative."); this->shakeFrequency_ = frequency; }
+            /**
+            @brief Set the amplitude with which the camera shakes during boosting.
+            @param amplitude The amplitude. Must be non-negative.
+            */
+            inline void setShakeAmplitude(float amplitude)
+                { OrxAssert(amplitude >= 0.0f, "The shake amplitude must be non-negative."); this->shakeAmplitude_ = amplitude; }
+
+            /**
+            @brief Get the initial boost power. Is non-negative.
+            @return Returns the initial boost power.
+            */
+            inline float getInitialBoostPower() const
+                { return this->initialBoostPower_; }
+            /**
+            @brief Get the current boost power. Is non-negative.
+            @return Returns the current boost power.
+            */
+            inline float getBoostPower() const
+                { return this->boostPower_; }
+            /**
+            @brief Get the boost power rate.
+            @return Returns the boost power rate in units per second. Is non-negative.
+            */
+            inline float getBoostPowerRate() const
+                { return this->boostPowerRate_; }
+            /**
+            @brief Get the boost rate.
+            @return Returns the boost rate in units per second. Is non-negative.
+            */
+            inline float getBoostRate() const
+                { return this->boostRate_; }
+            /**
+            @brief Get the cooldown duration.
+            @return Returns the cooldown duration in seconds. Is non-negative.
+            */
+            inline float getBoostCooldownDuration() const
+                { return this->boostCooldownDuration_; }
+            /**
+            @brief Get the shake frequency.
+            @return Returns the shake frequency in times per seconds. Is non-negative.
+            */
+            inline float getShakeFrequency() const
+                { return this->shakeFrequency_; }
+            /**
+            @brief Get the shake amplitude.
+            @return Returns the shake amplitude. Is non-negative.
+            */
+            inline float getShakeAmplitude() const
+                { return this->shakeAmplitude_; }
+            /**
+            @brief Add boost power. Is non-negative.
+            @return Returns the current boost power.
+            */
+            void gainBoostPower(float gainedBoostPower);
+
+        protected:
+            bool bInvertYAxis_;
+
+            Vector3 steering_; //!< The direction and magnitude of the steering action given through user input.
+
+            float rotationThrust_;               //!< Force with which the SpaceShip rotates.
+            btVector3 localAngularAcceleration_; //!< The acceleration that accounts for angular movement and is used internally.
+
+            bool bBoost_;                 //!< Whether the SpaceShip is currently boosting.
+            bool bBoostCooldown_;         //!< Whether the SpaceShip is currently in boost cooldown, during which boosting is impossible.
+            float initialBoostPower_;     //!< The initial (and maximal) boost power.
+            float boostPower_;            //!< The current boost power. If the boost power is reduced to zero the boost cooldown will start.
+            float boostPowerRate_;        //!< The rate at which the boost power is recharged.
+            float boostRate_;             //!< The rate at which boost power is used up.
+            float boostCooldownDuration_; //!< The duration for which boost cooldown is in effect.
+            float shakeFrequency_;        //!< The frequency of the shaking of the camera due to boosting.
+            float shakeAmplitude_;        //!< The amplitude of the shaking of the camera due to boosting.
+
+            float lift_;       //!< The amount of lift that is added.
+            float stallSpeed_; //!< The forward speed where no more lift is added.
+
+        private:
+            void registerVariables();
+            virtual bool isCollisionTypeLegal(WorldEntity::CollisionType type) const;
+
+            void changedEnableMotionBlur(); // Is called when the enableMotionBlur config value has changed.
+            /**
+            @brief Callback function. Is called when the boost has cooled down.
+            */
+            void boostCooledDown(void)
+                { this->bBoostCooldown_ = false; }
+
+            void shakeCamera(float dt); // Shake the camera for a given time interval.
+            void backupCamera(); // Save the original position and orientation of the camera.
+            void resetCamera(); // Reset the camera to its original position.
+
+            std::vector<Engine*> engineList_; //!< The list of all Engines mounted on this SpaceShip.
+
+            Timer timer_;                          //!< Timer for the cooldown of the boost.
+            float shakeDt_;                        //!< Temporary variable for the shaking of the camera.
+            Vector3 cameraOriginalPosition_;       //!< The original position of the camera before shaking it.
+            Quaternion cameraOriginalOrientation_; //!< The original orientation of the camera before shaking it.
+
+            Shader* boostBlur_;      //!< A radial blur shader, applied when boosting according to the amount of boosting.
+            float blurStrength_;     //!< The strength of the applied blur.
+            bool bEnableMotionBlur_; //!< Whether motion blur is enabled or not.
+        
+    };
+}
+
+#endif /* _SpaceShip_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Spectator.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Spectator.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Spectator.cc	(revision 11817)
@@ -0,0 +1,247 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#include "Spectator.h"
+
+#include "util/Convert.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+#include "core/GameMode.h"
+#include "core/command/CommandExecutor.h"
+#include "core/command/ConsoleCommandIncludes.h"
+
+#include "tools/BillboardSet.h"
+#include "Scene.h"
+#include "infos/PlayerInfo.h"
+
+namespace orxonox
+{
+    extern const std::string __CC_fire_name;
+    extern const std::string __CC_suicide_name;
+
+    RegisterClass(Spectator);
+
+    Spectator::Spectator(Context* context) : ControllableEntity(context)
+    {
+        RegisterObject(Spectator);
+
+        this->speed_ = 200;
+
+        this->yaw_ = 0;
+        this->pitch_ = 0;
+        this->roll_ = 0;
+        this->localVelocity_ = Vector3::ZERO;
+        this->setHudTemplate("spectatorhud");
+        this->greetingFlare_ = nullptr;
+
+        this->setDestroyWhenPlayerLeft(true);
+
+        if (GameMode::showsGraphics())
+        {
+            this->greetingFlare_ = new BillboardSet();
+            this->greetingFlare_->setBillboardSet(this->getScene()->getSceneManager(), "Examples/Flare", ColourValue(1.0f, 1.0f, 0.8f), Vector3(0, 20, 0), 1);
+            if (this->greetingFlare_->getBillboardSet())
+                this->attachOgreObject(this->greetingFlare_->getBillboardSet());
+            this->greetingFlare_->setVisible(false);
+        }
+
+        this->bGreetingFlareVisible_ = false;
+        this->bGreeting_ = false;
+
+        this->setConfigValues();
+        this->registerVariables();
+    }
+
+    Spectator::~Spectator()
+    {
+        if (this->isInitialized())
+        {
+            if (this->greetingFlare_)
+            {
+                if (this->greetingFlare_->getBillboardSet())
+                    this->detachOgreObject(this->greetingFlare_->getBillboardSet());
+
+                delete this->greetingFlare_;
+            }
+        }
+    }
+
+    void Spectator::setConfigValues()
+    {
+        SetConfigValue(speed_, 200.0f);
+    }
+
+    void Spectator::registerVariables()
+    {
+        registerVariable(this->bGreetingFlareVisible_, VariableDirection::ToClient, new NetworkCallback<Spectator>(this, &Spectator::changedFlareVisibility));
+        registerVariable(this->bGreeting_,             VariableDirection::ToServer, new NetworkCallback<Spectator>(this, &Spectator::changedGreeting));
+    }
+
+    void Spectator::changedGreeting()
+    {
+        this->bGreetingFlareVisible_ = this->bGreeting_;
+        this->changedFlareVisibility();
+    }
+
+    void Spectator::changedFlareVisibility()
+    {
+        if (this->greetingFlare_)
+            this->greetingFlare_->setVisible(this->bGreetingFlareVisible_);
+    }
+
+    void Spectator::tick(float dt)
+    {
+        if (this->hasLocalController())
+        {
+            float localSpeedSquared = this->localVelocity_.squaredLength();
+            float localSpeed;
+            if (localSpeedSquared > 1.0)
+                localSpeed = this->speed_ / sqrtf(localSpeedSquared);
+            else
+                localSpeed = this->speed_;
+
+            this->localVelocity_.x *= localSpeed;
+            this->localVelocity_.y *= localSpeed;
+            this->localVelocity_.z *= localSpeed;
+            this->setVelocity(this->getOrientation() * this->localVelocity_);
+            this->localVelocity_.x = 0;
+            this->localVelocity_.y = 0;
+            this->localVelocity_.z = 0;
+
+            if (!this->isInMouseLook())
+            {
+                this->yaw(Radian(this->yaw_ * this->getMouseLookSpeed()));
+                this->pitch(Radian(this->pitch_ * this->getMouseLookSpeed()));
+                this->roll(Radian(this->roll_ * this->getMouseLookSpeed()));
+            }
+
+            this->yaw_ = this->pitch_ = this->roll_ = 0;
+        }
+
+        SUPER(Spectator, tick, dt);
+    }
+
+    void Spectator::setPlayer(PlayerInfo* player)
+    {
+        ControllableEntity::setPlayer(player);
+
+//        this->setSyncMode(ObjectDirection::ToClient);
+    }
+
+    /**
+        @brief Changes the behavior of some console commands.
+    */
+    void Spectator::startLocalHumanControl()
+    {
+        ControllableEntity::startLocalHumanControl();
+
+        // change keybind mode of fire command to OnPress to avoid firing after respawn
+        ModifyConsoleCommand(__CC_fire_name).keybindMode(KeybindMode::OnPress);
+
+        // disable suicide
+        ModifyConsoleCommand(__CC_suicide_name).pushFunction(&prototype::void__void);
+    }
+
+    /**
+        @brief Changes the behavior of some console commands back to the original state.
+    */
+    void Spectator::stopLocalHumanControl()
+    {
+        ControllableEntity::stopLocalHumanControl();
+
+        // change fire command to a helper function and change keybind mode to OnPress
+        // as soon as the player releases and presses the button again, the helper function will be called which changes the keybind mode back to OnHold
+        ModifyConsoleCommand(__CC_fire_name).pushFunction(&Spectator::resetFireCommand).keybindMode(KeybindMode::OnPress);
+
+        // enable suicide
+        ModifyConsoleCommand(__CC_suicide_name).popFunction();
+    }
+
+    /**
+        @brief Helper function which changes the fire command back to the original function and keybind mode to OnHold.
+    */
+    void Spectator::resetFireCommand(unsigned int firemode)
+    {
+        ModifyConsoleCommand(__CC_fire_name).popFunction().keybindMode(KeybindMode::OnHold); // pop this helper function and change keybind mode
+
+        CommandExecutor::execute(__CC_fire_name + " " + multi_cast<std::string>(firemode)); // call the fire command again, this time with the real function
+    }
+
+    void Spectator::moveFrontBack(const Vector2& value)
+    {
+        this->localVelocity_.z -= value.x;
+    }
+
+    void Spectator::moveRightLeft(const Vector2& value)
+    {
+        this->localVelocity_.x += value.x;
+    }
+
+    void Spectator::moveUpDown(const Vector2& value)
+    {
+        this->localVelocity_.y += value.x;
+    }
+
+    void Spectator::rotateYaw(const Vector2& value)
+    {
+        this->yaw_ += value.y;
+
+        ControllableEntity::rotateYaw(value);
+    }
+
+    void Spectator::rotatePitch(const Vector2& value)
+    {
+        this->pitch_ += value.y;
+
+        ControllableEntity::rotatePitch(value);
+    }
+
+    void Spectator::rotateRoll(const Vector2& value)
+    {
+        this->roll_ += value.y;
+
+        ControllableEntity::rotateRoll(value);
+    }
+
+    void Spectator::fired(unsigned int firemode)
+    {
+        if (this->getPlayer())
+            this->getPlayer()->setReadyToSpawn(true);
+    }
+
+    void Spectator::greet()
+    {
+        this->bGreeting_ = !this->bGreeting_;
+
+        if (GameMode::isMaster())
+        {
+            this->bGreetingFlareVisible_ = this->bGreeting_;
+            this->changedFlareVisibility();
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Spectator.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Spectator.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/Spectator.h	(revision 11817)
@@ -0,0 +1,86 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Fabian 'x3n' Landau
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _Spectator_H__
+#define _Spectator_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "util/Math.h"
+#include "worldentities/ControllableEntity.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport Spectator : public ControllableEntity
+    {
+        public:
+            Spectator(Context* context);
+            virtual ~Spectator();
+
+            void setConfigValues();
+            virtual void tick(float dt);
+
+            virtual void moveFrontBack(const Vector2& value);
+            virtual void moveRightLeft(const Vector2& value);
+            virtual void moveUpDown(const Vector2& value);
+
+            virtual void rotateYaw(const Vector2& value);
+            virtual void rotatePitch(const Vector2& value);
+            virtual void rotateRoll(const Vector2& value);
+
+            virtual void fired(unsigned int firemode);
+            virtual void greet();
+            virtual void mouseLook() {}
+
+        protected:
+            virtual void setPlayer(PlayerInfo* player);
+            virtual void startLocalHumanControl();
+            virtual void stopLocalHumanControl();
+
+        private:
+            void registerVariables();
+            void changedGreeting();
+            void changedFlareVisibility();
+
+            static void resetFireCommand(unsigned int firemode);
+
+            BillboardSet* greetingFlare_;
+            bool bGreetingFlareVisible_;
+            bool bGreeting_;
+
+            float speed_;
+
+            float yaw_;
+            float pitch_;
+            float roll_;
+
+            Vector3 localVelocity_;
+    };
+}
+
+#endif /* _Spectator_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/StoryModePawn.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/StoryModePawn.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/StoryModePawn.cc	(revision 11817)
@@ -0,0 +1,94 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Nikola Bolt
+ *   Co-Author:
+ *      Claudio Fanconi
+ *
+ */
+
+/**
+    @file StoryModePawn.cc
+    @brief Implementation of the StoryModePawn control
+*/
+
+#include "StoryModePawn.h"
+
+#include "core/CoreIncludes.h"
+#include "core/XMLPort.h"
+
+#include "graphics/Camera.h"
+
+#include <BulletCollision/NarrowPhaseCollision/btManifoldPoint.h>
+
+namespace orxonox
+{
+    RegisterClass(StoryModePawn);
+
+    StoryModePawn::StoryModePawn(Context* context) : SpaceShip(context)
+    {
+        RegisterObject(StoryModePawn);
+    }
+
+    void StoryModePawn::moveFrontBack(const Vector2& value)
+        {
+            //this->getCamera()->setOrientation(Vector3::UNIT_X, Degree(-30));
+            Vector3 newPos = this->getCamera()->getPosition();
+            newPos.z -= 5*value.x;
+            this->getCamera()->setPosition(newPos);
+        }
+
+    void StoryModePawn::moveRightLeft(const Vector2& value)
+        {   
+            Vector3 newPos = this->getCamera()->getPosition();
+            newPos.x += 5*value.x;
+            this->getCamera()->setPosition(newPos);
+        }
+
+    void StoryModePawn::moveUpDown(const Vector2& value) {}
+
+    void StoryModePawn::rotateYaw(const Vector2& value) {
+
+        Pawn::rotateYaw(value);
+    }
+
+    /**
+    @brief
+        Removed, does nothing.
+    @param value
+    */
+    void StoryModePawn::rotatePitch(const Vector2& value) { }
+
+    /**
+    @brief
+        Removed, does nothing.
+    @param value
+    */
+    void StoryModePawn::rotateRoll(const Vector2& value) { }
+
+    /**
+    @brief
+        Removed, does nothing
+    @param bBoost
+    */
+    void StoryModePawn::boost(bool bBoost) { }
+}
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/StoryModePawn.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/StoryModePawn.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/StoryModePawn.h	(revision 11817)
@@ -0,0 +1,61 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Claudio Fanconi & Nikola Bolt
+ *
+ */
+
+/**
+    @file StoryModePawn.h
+    @brief Declaration of the StoryModePawn class.
+*/
+
+#ifndef _StoryModePawn_H__
+#define _StoryModePawn_H__
+
+#include "worldentities/pawns/SpaceShip.h"
+
+namespace orxonox
+{
+    class _OrxonoxExport StoryModePawn : public SpaceShip
+    {
+        public:
+            StoryModePawn(Context* context);
+
+            virtual void moveFrontBack(const Vector2& value) override;
+
+            virtual void moveRightLeft(const Vector2& value) override;
+
+            virtual void moveUpDown(const Vector2& value) override;
+
+            virtual void rotateYaw(const Vector2& value) override;
+
+            virtual void rotatePitch(const Vector2& value) override;
+
+            virtual void rotateRoll(const Vector2& value) override;
+
+            virtual void boost(bool bBoost) override;
+
+    };
+}
+
+#endif /* _StoryModePawn_H__ */
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/TeamBaseMatchBase.cc
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/TeamBaseMatchBase.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/TeamBaseMatchBase.cc	(revision 11817)
@@ -0,0 +1,98 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Val Mikos
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+
+#include "TeamBaseMatchBase.h"
+
+#include "core/CoreIncludes.h"
+#include "controllers/ArtificialController.h"
+#include "interfaces/TeamColourable.h"
+#include "gametypes/TeamBaseMatch.h"
+
+namespace orxonox
+{
+    RegisterClass(TeamBaseMatchBase);
+
+    TeamBaseMatchBase::TeamBaseMatchBase(Context* context) : Pawn(context)
+    {
+        RegisterObject(TeamBaseMatchBase);
+
+        this->state_ = BaseState::Uncontrolled;
+
+        TeamBaseMatch* gametype = orxonox_cast<TeamBaseMatch*>(this->getGametype());
+        if (gametype)
+        {
+            gametype->addBase(this);
+        }
+
+        this->setRadarObjectShape(RadarViewable::Shape::Triangle);
+    }
+
+    void TeamBaseMatchBase::changeTeamColour()
+    {
+        this->fireEvent();
+
+        TeamDeathmatch* gametype = orxonox_cast<TeamDeathmatch*>(this->getGametype());
+        if (!gametype)
+            return;
+
+        ColourValue colour;
+
+        switch (this->state_)
+        {
+            case BaseState::ControlTeam1:
+                colour = gametype->getTeamColour(0);
+                break;
+            case BaseState::ControlTeam2:
+                colour = gametype->getTeamColour(1);
+                break;
+            case BaseState::Uncontrolled:
+            default:
+                colour = ColourValue(0.5, 0.5, 0.5, 1.0);
+                break;
+        }
+
+
+        std::set<WorldEntity*> attachments = this->getAttachedObjects();
+        for (WorldEntity* attachment : attachments)
+        {
+            if (attachment->isA(Class(TeamColourable)))
+            {
+                TeamColourable* tc = orxonox_cast<TeamColourable*>(attachment);
+                tc->setTeamColour(colour);
+            }
+        }
+
+        this->setRadarObjectColour(colour);
+
+        // Call this so bots stop shooting at the base after they converted it
+        for (ArtificialController* controller : ObjectList<ArtificialController>())
+            controller->abandonTarget(this);
+    }
+}
+
Index: /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/TeamBaseMatchBase.h
===================================================================
--- /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/TeamBaseMatchBase.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/orxonox/worldentities/pawns/TeamBaseMatchBase.h	(revision 11817)
@@ -0,0 +1,78 @@
+/*
+ *   ORXONOX - the hottest 3D action shooter ever to exist
+ *                    > www.orxonox.net <
+ *
+ *
+ *   License notice:
+ *
+ *   This program 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.
+ *
+ *   This program 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 this program; if not, write to the Free Software
+ *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ *   Author:
+ *      Val Mikos
+ *   Co-authors:
+ *      ...
+ *
+ */
+
+#ifndef _TeamBaseMatchBase_H__
+#define _TeamBaseMatchBase_H__
+
+#include "OrxonoxPrereqs.h"
+
+#include "Pawn.h"
+
+namespace orxonox
+{
+    enum class BaseState
+    {
+        Uncontrolled,
+        ControlTeam1,
+        ControlTeam2,
+    };
+
+
+    class _OrxonoxExport TeamBaseMatchBase : public Pawn
+    {
+        public:
+            TeamBaseMatchBase(Context* context);
+
+            // if class closes, close everything
+            virtual ~TeamBaseMatchBase() {}
+
+
+
+            // Set the state of a base to whatever the argument of the function is
+            void setState(BaseState state)
+            {
+                this->state_ = state;
+                this->changeTeamColour();
+            }
+
+
+            // Get the state of a base as a return value
+            BaseState getState() const
+            {
+                return this->state_;
+            }
+
+
+        protected:
+            void changeTeamColour();
+
+            BaseState state_;
+    };
+}
+
+#endif /* _TeamBaseMatchBase_H__ */
Index: /code/branches/RacingBots_FS18/src/template.vcproj.user.in
===================================================================
--- /code/branches/RacingBots_FS18/src/template.vcproj.user.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/template.vcproj.user.in	(revision 11817)
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioUserFile
+	ProjectType="Visual C++"
+	Version="${VISUAL_STUDIO_VERSION_SIMPLE}.00"
+	ShowAllFiles="false"
+	>
+	<Configurations>
+		<Configuration
+			Name="Debug|${MSVC_PLATFORM}"
+			>
+			<DebugSettings
+				WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
+				Environment="PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%"
+				EnvironmentMerge="true"
+			/>
+		</Configuration>
+		<Configuration
+			Name="RelForDevs|${MSVC_PLATFORM}"
+			>
+			<DebugSettings
+				WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
+				Environment="PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%"
+				EnvironmentMerge="true"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|${MSVC_PLATFORM}"
+			>
+			<DebugSettings
+				WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
+				Environment="PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%"
+				EnvironmentMerge="true"
+			/>
+		</Configuration>
+		<Configuration
+			Name="MinSizeRel|${MSVC_PLATFORM}"
+			>
+			<DebugSettings
+				WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
+				Environment="PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%"
+				EnvironmentMerge="true"
+			/>
+		</Configuration>
+		<Configuration
+			Name="RelWithDebInfo|${MSVC_PLATFORM}"
+			>
+			<DebugSettings
+				WorkingDirectory="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$(OutDir)"
+				Environment="PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%"
+				EnvironmentMerge="true"
+			/>
+		</Configuration>
+	</Configurations>
+</VisualStudioUserFile>
Index: /code/branches/RacingBots_FS18/src/template.vcxproj.user.in
===================================================================
--- /code/branches/RacingBots_FS18/src/template.vcxproj.user.in	(revision 11817)
+++ /code/branches/RacingBots_FS18/src/template.vcxproj.user.in	(revision 11817)
@@ -0,0 +1,28 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|${MSVC_PLATFORM}'">
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerEnvironment>PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%</LocalDebuggerEnvironment>
+    <LocalDebuggerWorkingDirectory>$(Outdir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelForDevs|${MSVC_PLATFORM}'">
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerEnvironment>PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%</LocalDebuggerEnvironment>
+    <LocalDebuggerWorkingDirectory>$(Outdir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|${MSVC_PLATFORM}'">
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerEnvironment>PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%</LocalDebuggerEnvironment>
+    <LocalDebuggerWorkingDirectory>$(Outdir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|${MSVC_PLATFORM}'">
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerEnvironment>PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%</LocalDebuggerEnvironment>
+    <LocalDebuggerWorkingDirectory>$(Outdir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|${MSVC_PLATFORM}'">
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+    <LocalDebuggerEnvironment>PATH=${RUNTIME_LIBRARY_DIRECTORY};%PATH%</LocalDebuggerEnvironment>
+    <LocalDebuggerWorkingDirectory>$(Outdir)</LocalDebuggerWorkingDirectory>
+  </PropertyGroup>
+</Project>
Index: /code/branches/RacingBots_FS18/test/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/test/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,69 @@
+ #
+ #             ORXONOX - the hottest 3D action shooter ever to exist
+ #                             > www.orxonox.net <
+ #
+ #        This program 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.
+ #
+ #       This program 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 this program; if not, write to the Free Software Foundation,
+ #     Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ #
+ #
+ #  Author:
+ #    Fabian 'x3n' Landau
+ #  Description:
+ #    Configures the compilers and sets build options.
+ #
+
+# Required macros and functions
+INCLUDE(FlagUtilities)
+INCLUDE(TargetUtilities)
+
+INCLUDE(../src/SourceConfig.cmake)
+
+################ Testing Configuration ################
+
+ENABLE_TESTING()
+
+# A target to execute tests. This override the native 'test' target of cmake and allows us to
+# define dependences (i.e. to let cmake build the tests before executing them)
+IF (POLICY CMP0037)
+  CMAKE_POLICY(PUSH)
+  CMAKE_POLICY(SET CMP0037 OLD) # we currently have to override the original 'test' target until cmake provides a better way to define dependencies to the test target
+ENDIF()
+ADD_CUSTOM_TARGET(test COMMAND ${CMAKE_CTEST_COMMAND} "$(ARGS)" COMMENT "Running tests")
+IF (POLICY CMP0037)
+  CMAKE_POLICY(POP) # restore policy settings
+ENDIF()
+
+# A target to build all tests
+ADD_CUSTOM_TARGET(all_tests)
+ADD_DEPENDENCIES(test all_tests) # build tests before executing them
+
+CONFIGURE_FILE("CTestCustom.cmake" "CTestCustom.cmake" @ONLY)
+
+############## Include Directories ##############
+
+INCLUDE_DIRECTORIES(
+  ../src/external
+  ../src/libraries
+  ../src/orxonox
+  ../src/modules
+  ../src/external/gtest/include
+  ../src/external/gmock/include
+  ${CMAKE_BINARY_DIR}/src
+)
+
+################ Sub Directories ################
+
+ADD_SUBDIRECTORY(util)
+ADD_SUBDIRECTORY(core)
+ADD_SUBDIRECTORY(core_plugin)
Index: /code/branches/RacingBots_FS18/test/CTestCustom.cmake
===================================================================
--- /code/branches/RacingBots_FS18/test/CTestCustom.cmake	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/CTestCustom.cmake	(revision 11817)
@@ -0,0 +1,1 @@
+SET(ENV{PATH} "@RUNTIME_LIBRARY_DIRECTORY@;$ENV{PATH}")
Index: /code/branches/RacingBots_FS18/test/core/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/test/core/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,38 @@
+ORXONOX_ADD_EXECUTABLE(
+    core_test
+    EXCLUDE_FROM_ALL
+    NO_INSTALL
+  LINK_LIBRARIES
+    core
+    gmock_orxonox
+  SOURCE_FILES
+    ${GMOCK_MAIN}
+    class/IdentifiableTest.cc
+    class/IdentifierTest.cc
+    class/IdentifierClassHierarchyTest.cc
+    class/IdentifierSimpleClassHierarchyTest.cc
+    class/IdentifierNestedClassHierarchyTest.cc
+    class/IdentifierExternalClassHierarchyTest.cc
+    class/OrxonoxClassTest.cc
+    class/OrxonoxInterfaceTest.cc
+    class/SubclassIdentifierTest.cc
+    class/SuperTest.cc
+    command/CommandTest.cc
+    command/FunctorPtrTest.cc
+    command/FunctorTest.cc
+    command/ExecutorPtrTest.cc
+    object/ClassFactoryTest.cc
+    object/ContextTest.cc
+    object/DestroyableTest.cc
+    object/IteratorTest.cc
+    object/ListableTest.cc
+    object/ObjectListBaseTest.cc
+    object/ObjectListTest.cc
+    object/ObjectListIteratorTest.cc
+    object/StrongPtrTest.cc
+    object/WeakPtrTest.cc
+    singleton/ScopeTest.cc
+)
+ADD_DEPENDENCIES(all_tests core_test)
+
+ADD_TEST(core_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/core_test --gtest_output=xml)
Index: /code/branches/RacingBots_FS18/test/core/class/IdentifiableTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/IdentifiableTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/IdentifiableTest.cc	(revision 11817)
@@ -0,0 +1,54 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class IdentifiableClass : public Identifiable
+        {
+            public:
+                IdentifiableClass() { RegisterObject(IdentifiableClass); }
+        };
+
+        RegisterClassNoArgs(IdentifiableClass);
+
+        // Fixture
+        class IdentifiableTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                }
+
+                virtual void TearDown() override
+                {
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(IdentifiableTest, CanCreate)
+    {
+        IdentifiableClass* test = new IdentifiableClass();
+        ASSERT_TRUE(test != nullptr);
+        delete test;
+    }
+
+    TEST_F(IdentifiableTest, HasIdentifierAssigned)
+    {
+        IdentifiableClass test;
+        EXPECT_TRUE(test.getIdentifier());
+    }
+
+    TEST_F(IdentifiableTest, CanBeIdentified)
+    {
+        IdentifiableClass test;
+        EXPECT_TRUE(test.isA(Class(IdentifiableClass)));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/IdentifierClassHierarchyTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/IdentifierClassHierarchyTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/IdentifierClassHierarchyTest.cc	(revision 11817)
@@ -0,0 +1,413 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/OrxonoxInterface.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    //                 +------ Class0
+    // BaseClass <-----+---------------------+--- Class1
+    //                 +---------------------+-+- Class2a
+    //                 +---------------------+-+- Class2b
+    //                 +-+-+-- Class3        | |
+    //                   | |                 | |
+    // BaseInterface1 <--+---- Interface1 <--´ |
+    //                     |                   |
+    // BaseInterface2 <----+-- Interface2 <----´
+
+    namespace
+    {
+        class BaseInterface1 : virtual public OrxonoxInterface
+        {
+            public:
+                BaseInterface1()
+                {
+                    RegisterObject(BaseInterface1);
+                }
+
+                virtual void test1() = 0;
+        };
+
+        class BaseInterface2 : virtual public OrxonoxInterface
+        {
+            public:
+                BaseInterface2()
+                {
+                    RegisterObject(BaseInterface2);
+                }
+
+                virtual void test2() = 0;
+        };
+
+        class Interface1 : public BaseInterface1
+        {
+            public:
+                Interface1()
+                {
+                    RegisterObject(Interface1);
+                }
+        };
+
+        class Interface2 : public BaseInterface2
+        {
+            public:
+                Interface2()
+                {
+                    RegisterObject(Interface2);
+                }
+        };
+
+        class BaseClass : public OrxonoxClass
+        {
+            public:
+                BaseClass()
+                {
+                    RegisterObject(BaseClass);
+                }
+        };
+
+        class Class0 : public BaseClass
+        {
+            public:
+                Class0()
+                {
+                    RegisterObject(Class0);
+                }
+        };
+
+        class Class1 : public BaseClass, public Interface1
+        {
+            public:
+                Class1()
+                {
+                    RegisterObject(Class1);
+                }
+
+                virtual void test1() override {}
+        };
+
+        class Class2a : public BaseClass, public Interface1, Interface2
+        {
+            public:
+                Class2a()
+                {
+                    RegisterObject(Class2a);
+                }
+
+                virtual void test1() override {}
+                virtual void test2() override {}
+        };
+
+        class Class2b : public BaseClass, public Interface2, Interface1
+        {
+            public:
+                Class2b()
+                {
+                    RegisterObject(Class2b);
+                }
+
+                virtual void test1() override {}
+                virtual void test2() override {}
+        };
+
+        class Class3 : public BaseClass, public BaseInterface1, BaseInterface2
+        {
+            public:
+                Class3()
+                {
+                    RegisterObject(Class3);
+                }
+
+                virtual void test1() override {}
+                virtual void test2() override {}
+        };
+
+        RegisterAbstractClass(BaseInterface1).inheritsFrom<OrxonoxInterface>();
+        RegisterAbstractClass(BaseInterface2).inheritsFrom<OrxonoxInterface>();
+        RegisterAbstractClass(Interface1).inheritsFrom<BaseInterface1>();
+        RegisterAbstractClass(Interface2).inheritsFrom<BaseInterface2>();
+        RegisterClassNoArgs(BaseClass);
+        RegisterClassNoArgs(Class0);
+        RegisterClassNoArgs(Class1);
+        RegisterClassNoArgs(Class2a);
+        RegisterClassNoArgs(Class2b);
+        RegisterClassNoArgs(Class3);
+
+        // Fixture
+        class IdentifierClassHierarchyTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+
+        bool contains(const std::list<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return std::find(identifiers.begin(), identifiers.end(), identifier) != identifiers.end();
+        }
+
+        bool contains(const std::set<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return identifiers.find(identifier) != identifiers.end();
+        }
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestBaseInterface1)
+    {
+        Identifier* identifier = Class(BaseInterface1);
+
+        EXPECT_EQ(2u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Interface1)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3)));
+
+        EXPECT_EQ(5u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Interface1)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class1)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2b)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxInterface)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestBaseInterface2)
+    {
+        Identifier* identifier = Class(BaseInterface2);
+
+        EXPECT_EQ(2u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Interface2)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3)));
+
+        EXPECT_EQ(4u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Interface2)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2b)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxInterface)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestInterface1)
+    {
+        Identifier* identifier = Class(Interface1);
+
+        EXPECT_EQ(3u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class1)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2b)));
+
+        EXPECT_EQ(3u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class1)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2b)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseInterface1)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface1)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestInterface2)
+    {
+        Identifier* identifier = Class(Interface2);
+
+        EXPECT_EQ(2u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2b)));
+
+        EXPECT_EQ(2u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2b)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseInterface2)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface2)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestBaseClass)
+    {
+        Identifier* identifier = Class(BaseClass);
+
+        EXPECT_EQ(5u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class0)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class1)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2b)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3)));
+
+        EXPECT_EQ(5u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class0)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class1)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2a)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2b)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestClass0)
+    {
+        Identifier* identifier = Class(Class0);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestClass1)
+    {
+        Identifier* identifier = Class(Class1);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(2u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface1)));
+
+        EXPECT_EQ(8u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface1)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface1)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestClass2a)
+    {
+        Identifier* identifier = Class(Class2a);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(3u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface1)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface2)));
+
+        EXPECT_EQ(10u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface1)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface1)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface2)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface2)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestClass2b)
+    {
+        Identifier* identifier = Class(Class2b);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(3u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface1)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface2)));
+
+        EXPECT_EQ(10u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface1)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface1)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface2)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface2)));
+    }
+
+    TEST_F(IdentifierClassHierarchyTest, TestClass3)
+    {
+        Identifier* identifier = Class(Class3);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(3u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseInterface1)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseInterface2)));
+
+        EXPECT_EQ(8u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface1)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseInterface2)));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/IdentifierExternalClassHierarchyTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/IdentifierExternalClassHierarchyTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/IdentifierExternalClassHierarchyTest.cc	(revision 11817)
@@ -0,0 +1,129 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class Interface : virtual public Identifiable
+        {
+            public:
+                Interface()
+                {
+                    RegisterObject(Interface);
+                }
+
+                virtual void test() = 0;
+        };
+
+        class BaseClass : virtual public Identifiable
+        {
+            public:
+                BaseClass()
+                {
+                    RegisterObject(BaseClass);
+                }
+        };
+
+        class RealClass : public BaseClass, public Interface
+        {
+            public:
+                RealClass()
+                {
+                    RegisterObject(RealClass);
+                }
+
+                virtual void test() override {}
+        };
+
+        RegisterAbstractClass(Interface).inheritsFrom<Identifiable>();
+        RegisterClassNoArgs(BaseClass);
+        RegisterClassNoArgs(RealClass);
+
+        // Fixture
+        class IdentifierExternalClassHierarchyTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+
+        bool contains(const std::list<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return std::find(identifiers.begin(), identifiers.end(), identifier) != identifiers.end();
+        }
+
+        bool contains(const std::set<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return identifiers.find(identifier) != identifiers.end();
+        }
+    }
+
+    TEST_F(IdentifierExternalClassHierarchyTest, TestInterface)
+    {
+        Identifier* identifier = Class(Interface);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Identifiable)));
+
+        EXPECT_EQ(1u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+    }
+
+    TEST_F(IdentifierExternalClassHierarchyTest, BaseClass)
+    {
+        Identifier* identifier = Class(BaseClass);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Identifiable)));
+
+        EXPECT_EQ(1u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+    }
+
+    TEST_F(IdentifierExternalClassHierarchyTest, RealClass)
+    {
+        Identifier* identifier = Class(RealClass);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(2u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(3u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/IdentifierNestedClassHierarchyTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/IdentifierNestedClassHierarchyTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/IdentifierNestedClassHierarchyTest.cc	(revision 11817)
@@ -0,0 +1,355 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/OrxonoxInterface.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    // Tests the class hierarchy with classes that contain other classes as members.
+    //
+    //                    +------ Nested1         +------ Class1_notNested
+    //                    +------ Nested2         +------ Class2_oneNested
+    // OrxonoxClass <-----+------ BaseClass <-----+------ Class3_twoNested <----------- Class3_Child
+    //                                            +------ Class4_class1Nested
+    //                                            +------ Class5_class2Nested
+    //                                            +------ Class6_class3Nested <-------- Class6_Child
+
+    namespace
+    {
+        class Nested1 : public OrxonoxClass
+        {
+            public:
+                Nested1() { RegisterObject(Nested1); }
+        };
+
+        class Nested2 : public OrxonoxClass
+        {
+            public:
+                Nested2() { RegisterObject(Nested2); }
+        };
+
+        class BaseClass : public OrxonoxClass
+        {
+            public:
+                BaseClass() { RegisterObject(BaseClass); }
+        };
+
+        class Class1_notNested : public BaseClass
+        {
+            public:
+                Class1_notNested() { RegisterObject(Class1_notNested); }
+        };
+
+        class Class2_oneNested : public BaseClass
+        {
+            public:
+                Class2_oneNested() { RegisterObject(Class2_oneNested); }
+                Nested1 nested1_;
+        };
+
+        class Class3_twoNested : public BaseClass
+        {
+            public:
+                Class3_twoNested() { RegisterObject(Class3_twoNested); }
+                Nested1 nested1_;
+                Nested2 nested2_;
+        };
+
+        class Class4_class1Nested : public BaseClass
+        {
+            public:
+                Class4_class1Nested() { RegisterObject(Class4_class1Nested); }
+                Class1_notNested nested_;
+        };
+
+        class Class5_class2Nested : public BaseClass
+        {
+            public:
+                Class5_class2Nested() { RegisterObject(Class5_class2Nested); }
+                Class2_oneNested nested_;
+        };
+
+        class Class6_class3Nested : public BaseClass
+        {
+            public:
+                Class6_class3Nested() { RegisterObject(Class6_class3Nested); }
+                Class3_twoNested nested_;
+        };
+
+        class Class3_Child : public Class3_twoNested
+        {
+            public:
+                Class3_Child() { RegisterObject(Class3_Child); }
+        };
+
+        class Class6_Child : public Class6_class3Nested
+        {
+            public:
+                Class6_Child() { RegisterObject(Class6_Child); }
+        };
+
+        RegisterClassNoArgs(Nested1);
+        RegisterClassNoArgs(Nested2);
+        RegisterClassNoArgs(BaseClass);
+        RegisterClassNoArgs(Class1_notNested);
+        RegisterClassNoArgs(Class2_oneNested);
+        RegisterClassNoArgs(Class3_twoNested);
+        RegisterClassNoArgs(Class4_class1Nested);
+        RegisterClassNoArgs(Class5_class2Nested);
+        RegisterClassNoArgs(Class6_class3Nested);
+        RegisterClassNoArgs(Class3_Child);
+        RegisterClassNoArgs(Class6_Child);
+
+        // Fixture
+        class IdentifierNestedClassHierarchyTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+
+        bool contains(const std::list<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return std::find(identifiers.begin(), identifiers.end(), identifier) != identifiers.end();
+        }
+
+        bool contains(const std::set<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return identifiers.find(identifier) != identifiers.end();
+        }
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestNested1)
+    {
+        Identifier* identifier = Class(Nested1);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestNested2)
+    {
+        Identifier* identifier = Class(Nested2);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestBaseClass)
+    {
+        Identifier* identifier = Class(BaseClass);
+
+        EXPECT_EQ(6u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class1_notNested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class2_oneNested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3_twoNested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class4_class1Nested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class5_class2Nested)));
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class6_class3Nested)));
+
+        EXPECT_EQ(8u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class1_notNested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class2_oneNested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3_twoNested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class4_class1Nested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class5_class2Nested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class6_class3Nested)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3_Child)));
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class6_Child)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass1_notNested)
+    {
+        Identifier* identifier = Class(Class1_notNested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass2_oneNested)
+    {
+        Identifier* identifier = Class(Class2_oneNested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass3_twoNested)
+    {
+        Identifier* identifier = Class(Class3_twoNested);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class3_Child)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class3_Child)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass4_class1Nested)
+    {
+        Identifier* identifier = Class(Class4_class1Nested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass5_class2Nested)
+    {
+        Identifier* identifier = Class(Class5_class2Nested);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass6_class3Nested)
+    {
+        Identifier* identifier = Class(Class6_class3Nested);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(Class6_Child)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(Class6_Child)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(5u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass3_Child)
+    {
+        Identifier* identifier = Class(Class3_Child);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Class3_twoNested)));
+
+        EXPECT_EQ(6u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Class3_twoNested)));
+    }
+
+    TEST_F(IdentifierNestedClassHierarchyTest, TestClass6_Child)
+    {
+        Identifier* identifier = Class(Class6_Child);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Class6_class3Nested)));
+
+        EXPECT_EQ(6u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Class6_class3Nested)));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/IdentifierSimpleClassHierarchyTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/IdentifierSimpleClassHierarchyTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/IdentifierSimpleClassHierarchyTest.cc	(revision 11817)
@@ -0,0 +1,141 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/OrxonoxInterface.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class Interface : virtual public OrxonoxInterface
+        {
+            public:
+                Interface()
+                {
+                    RegisterObject(Interface);
+                }
+
+                virtual void test() = 0;
+        };
+
+        class BaseClass : public OrxonoxClass
+        {
+            public:
+                BaseClass()
+                {
+                    RegisterObject(BaseClass);
+                }
+        };
+
+        class RealClass : public BaseClass, public Interface
+        {
+            public:
+                RealClass()
+                {
+                    RegisterObject(RealClass);
+                }
+
+                virtual void test() override {}
+        };
+
+        RegisterAbstractClass(Interface).inheritsFrom<OrxonoxInterface>();
+        RegisterClassNoArgs(BaseClass);
+        RegisterClassNoArgs(RealClass);
+
+        // Fixture
+        class IdentifierSimpleClassHierarchyTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+
+        bool contains(const std::list<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return std::find(identifiers.begin(), identifiers.end(), identifier) != identifiers.end();
+        }
+
+        bool contains(const std::set<const Identifier*> identifiers, Identifier* identifier)
+        {
+            return identifiers.find(identifier) != identifiers.end();
+        }
+    }
+
+    TEST_F(IdentifierSimpleClassHierarchyTest, TestInterface)
+    {
+        Identifier* identifier = Class(Interface);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxInterface)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+    }
+
+    TEST_F(IdentifierSimpleClassHierarchyTest, BaseClass)
+    {
+        Identifier* identifier = Class(BaseClass);
+
+        EXPECT_EQ(1u, identifier->getDirectChildren().size());
+        EXPECT_TRUE(contains(identifier->getDirectChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getChildren().size());
+        EXPECT_TRUE(contains(identifier->getChildren(), Class(RealClass)));
+
+        EXPECT_EQ(1u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(OrxonoxClass)));
+
+        EXPECT_EQ(4u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+    }
+
+    TEST_F(IdentifierSimpleClassHierarchyTest, RealClass)
+    {
+        Identifier* identifier = Class(RealClass);
+
+        EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+        EXPECT_EQ(0u, identifier->getChildren().size());
+
+        EXPECT_EQ(2u, identifier->getDirectParents().size());
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(Interface)));
+        EXPECT_TRUE(contains(identifier->getDirectParents(), Class(BaseClass)));
+
+        EXPECT_EQ(7u, identifier->getParents().size());
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Identifiable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Listable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Configurable)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxInterface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(OrxonoxClass)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(Interface)));
+        EXPECT_TRUE(contains(identifier->getParents(), Class(BaseClass)));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/IdentifierTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/IdentifierTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/IdentifierTest.cc	(revision 11817)
@@ -0,0 +1,74 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestClass : public Identifiable
+        {
+            public:
+                TestClass() { RegisterObject(TestClass); }
+        };
+
+        class TestSubclass : public TestClass
+        {
+            public:
+                TestSubclass() { RegisterObject(TestSubclass); }
+        };
+
+        RegisterClassNoArgs(TestClass);
+        RegisterClassNoArgs(TestSubclass);
+
+        // Fixture
+        class IdentifierTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                }
+
+                virtual void TearDown() override
+                {
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(IdentifierTest, IdentifierExistsOfClass)
+    {
+        TestClass test;
+
+        Identifier* identifier = Class(TestClass);
+        EXPECT_TRUE(identifier != nullptr);
+    }
+
+    TEST_F(IdentifierTest, IdentifierExistsOfSubclass)
+    {
+        TestSubclass test;
+
+        Identifier* identifier = Class(TestSubclass);
+        EXPECT_TRUE(identifier != nullptr);
+    }
+
+    TEST_F(IdentifierTest, HasNameOfClass)
+    {
+        TestClass test;
+
+        Identifier* identifier = Class(TestClass);
+        EXPECT_EQ("TestClass", identifier->getName());
+    }
+
+    TEST_F(IdentifierTest, HasNameOfSubClass)
+    {
+        TestSubclass test;
+
+        Identifier* identifier = Class(TestSubclass);
+        EXPECT_EQ("TestSubclass", identifier->getName());
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/OrxonoxClassTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/OrxonoxClassTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/OrxonoxClassTest.cc	(revision 11817)
@@ -0,0 +1,38 @@
+#include <gtest/gtest.h>
+#include "core/class/OrxonoxClass.h"
+#include "core/class/IdentifierManager.h"
+#include "core/object/Context.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestClass : public OrxonoxClass
+        {
+        };
+
+        // Fixture
+        class OrxonoxClassTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(OrxonoxClassTest, CanCreate)
+    {
+        TestClass* test = new TestClass();
+        ASSERT_TRUE(test != nullptr);
+        delete test;
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/OrxonoxInterfaceTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/OrxonoxInterfaceTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/OrxonoxInterfaceTest.cc	(revision 11817)
@@ -0,0 +1,60 @@
+#include <gtest/gtest.h>
+#include "core/class/OrxonoxInterface.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/IdentifierManager.h"
+#include "core/object/Context.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class Interface1 : virtual public OrxonoxInterface
+        {
+        };
+        class Interface2 : virtual public OrxonoxInterface
+        {
+        };
+        class Interface3 : virtual public OrxonoxInterface
+        {
+        };
+
+        class TestClass1 : public Interface1, public Interface2, public Interface3
+        {
+        };
+
+        class TestClass2 : public OrxonoxClass, public Interface1, public Interface2, public Interface3
+        {
+        };
+
+        // Fixture
+        class OrxonoxInterfaceTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(OrxonoxInterfaceTest, CanCreate1)
+    {
+        TestClass1* test = new TestClass1();
+        ASSERT_TRUE(test != nullptr);
+        delete test;
+    }
+
+    TEST_F(OrxonoxInterfaceTest, CanCreate2)
+    {
+        TestClass2* test = new TestClass2();
+        ASSERT_TRUE(test != nullptr);
+        delete test;
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/SubclassIdentifierTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/SubclassIdentifierTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/SubclassIdentifierTest.cc	(revision 11817)
@@ -0,0 +1,84 @@
+#include <gtest/gtest.h>
+#include "core/CoreIncludes.h"
+#include "core/class/Identifiable.h"
+#include "core/class/SubclassIdentifier.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestClass : public OrxonoxClass
+        {
+            public:
+                TestClass(Context* context = nullptr) { RegisterObject(TestClass); }
+        };
+
+        class TestSubclass : public TestClass
+        {
+            public:
+                TestSubclass(Context* context = nullptr) { RegisterObject(TestSubclass); }
+        };
+
+        RegisterClass(TestClass);
+        RegisterClass(TestSubclass);
+
+        // Fixture
+        class SubclassIdentifierTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(SubclassIdentifierTest, CanCreateIdentifier)
+    {
+        TestSubclass test;
+
+        SubclassIdentifier<TestClass> subclassIdentifier;
+    }
+
+    TEST_F(SubclassIdentifierTest, DefaultsToNormalIdentifier)
+    {
+        TestSubclass test;
+
+        SubclassIdentifier<TestClass> subclassIdentifier;
+        EXPECT_EQ(Class(TestClass), subclassIdentifier.getIdentifier());
+    }
+
+    TEST_F(SubclassIdentifierTest, CanAssignIdentifierOfSubclass)
+    {
+        TestSubclass test;
+        SubclassIdentifier<TestClass> subclassIdentifier;
+        subclassIdentifier = Class(TestSubclass);
+        EXPECT_EQ(Class(TestSubclass), subclassIdentifier.getIdentifier());
+    }
+
+    TEST_F(SubclassIdentifierTest, CanCreateSubclass)
+    {
+        TestSubclass test;
+        SubclassIdentifier<TestClass> subclassIdentifier;
+        subclassIdentifier = Class(TestSubclass);
+
+        TestClass* instance = subclassIdentifier.fabricate(nullptr);
+        ASSERT_TRUE(instance != nullptr);
+        EXPECT_EQ(Class(TestSubclass), instance->getIdentifier());
+        delete instance;
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/class/SuperTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/class/SuperTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/class/SuperTest.cc	(revision 11817)
@@ -0,0 +1,142 @@
+#include <gtest/gtest.h>
+#include <tinyxml/tinyxml.h>
+
+#include "core/CoreIncludes.h"
+#include "core/BaseObject.h"
+#include "core/class/Super.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestClass : public BaseObject
+        {
+            public:
+                TestClass(Context* context = nullptr) : BaseObject(context), changedNameBase_(false), xmlPortBase_(false), modeBase_(XMLPort::NOP)
+                {
+                    RegisterObject(TestClass);
+                }
+
+                virtual void changedName() override
+                {
+                    this->changedNameBase_ = true;
+                }
+
+                virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override
+                {
+                    this->xmlPortBase_ = true;
+                    this->modeBase_ = mode;
+                }
+
+                bool changedNameBase_;
+                bool xmlPortBase_;
+                XMLPort::Mode modeBase_;
+        };
+
+        class TestSubclass : public TestClass
+        {
+            public:
+                TestSubclass(Context* context = nullptr) : TestClass(context), changedNameSubclass_(false), xmlPortSubclass_(false), modeSubclass_(XMLPort::NOP)
+                {
+                    RegisterObject(TestSubclass);
+                }
+
+                virtual void changedName() override
+                {
+                    this->changedNameSubclass_ = true;
+
+                    SUPER(TestSubclass, changedName);
+                }
+
+                virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode) override
+                {
+                    this->xmlPortSubclass_ = true;
+                    this->modeSubclass_ = mode;
+
+                    SUPER(TestSubclass, XMLPort, xmlelement, mode);
+                }
+
+                bool changedNameSubclass_;
+                bool xmlPortSubclass_;
+                XMLPort::Mode modeSubclass_;
+        };
+
+        RegisterClass(TestClass);
+        RegisterClass(TestSubclass);
+
+        // Fixture
+        class SuperTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(SuperTest, ClassHierarchyIsCorrect)
+    {
+        {
+            Identifier* identifier = Class(TestSubclass);
+
+            EXPECT_EQ(0u, identifier->getDirectChildren().size());
+
+            EXPECT_EQ(1u, identifier->getDirectParents().size());
+            EXPECT_TRUE(std::find(identifier->getDirectParents().begin(), identifier->getDirectParents().end(), Class(TestClass)) != identifier->getDirectParents().end());
+        }
+        {
+            Identifier* identifier = Class(TestClass);
+
+            EXPECT_EQ(1u, identifier->getDirectChildren().size());
+            EXPECT_TRUE(identifier->getDirectChildren().find(Class(TestSubclass)) != identifier->getDirectChildren().end());
+
+            EXPECT_EQ(1u, identifier->getDirectParents().size());
+            EXPECT_TRUE(std::find(identifier->getDirectParents().begin(), identifier->getDirectParents().end(), Class(BaseObject)) != identifier->getDirectParents().end());
+        }
+    }
+
+    TEST_F(SuperTest, SuperCallWithoutArguments)
+    {
+        TestSubclass test;
+
+        EXPECT_FALSE(test.changedNameBase_);
+        EXPECT_FALSE(test.changedNameSubclass_);
+
+        test.changedName();
+
+        EXPECT_TRUE(test.changedNameBase_);
+        EXPECT_TRUE(test.changedNameSubclass_);
+    }
+
+    TEST_F(SuperTest, SuperCallWithArguments)
+    {
+        TestSubclass test;
+
+        EXPECT_FALSE(test.xmlPortBase_);
+        EXPECT_FALSE(test.xmlPortSubclass_);
+        EXPECT_EQ(XMLPort::NOP, test.modeBase_);
+        EXPECT_EQ(XMLPort::NOP, test.modeSubclass_);
+
+        Element* element = nullptr;
+        test.XMLPort(*element, XMLPort::SaveObject);
+
+        EXPECT_TRUE(test.xmlPortBase_);
+        EXPECT_TRUE(test.xmlPortSubclass_);
+        EXPECT_EQ(XMLPort::SaveObject, test.modeBase_);
+        EXPECT_EQ(XMLPort::SaveObject, test.modeSubclass_);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/command/CommandTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/command/CommandTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/command/CommandTest.cc	(revision 11817)
@@ -0,0 +1,202 @@
+#include <gtest/gtest.h>
+#include "core/class/Identifier.h"
+#include "core/class/IdentifierManager.h"
+#include "core/command/ConsoleCommandIncludes.h"
+#include "core/command/CommandExecutor.h"
+#include "core/object/Destroyable.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        int functionNr = 0;
+        int valueA = 0;
+        int valueB = 0;
+        int valueC = 0;
+
+        void testfunction1(int a);
+        void testfunction2(int a, int b);
+        void testfunction3(int a, int b);
+        void testfunction4(int a, int b, int c);
+
+        class Testclass : public Destroyable
+        {
+            public:
+                void testfunction5(int a);
+                void testfunction6(int a);
+
+                Testclass* other_;
+                int b_;
+        };
+
+        SetConsoleCommand("test", &testfunction1);
+
+        Testclass* class1 = new Testclass();
+        Testclass* class2 = new Testclass();
+
+        void testfunction1(int a)
+        {
+            functionNr = 1;
+            valueA = a;
+            valueB = 0;
+            valueC = 0;
+
+            if (a == 1)
+                ModifyConsoleCommand("test").pushFunction().defaultValue(1, 10).setFunction(&testfunction2);
+            else if (a == -1)
+                ModifyConsoleCommand("test").popFunction();
+        }
+
+        void testfunction2(int a, int b)
+        {
+            functionNr = 2;
+            valueA = a;
+            valueB = b;
+            valueC = 0;
+
+            if (a == 1)
+                ModifyConsoleCommand("test").pushFunction().defaultValue(1, 20).setFunction(&testfunction3);
+            else if (a == -1)
+                ModifyConsoleCommand("test").popFunction();
+        }
+
+        void testfunction3(int a, int b)
+        {
+            functionNr = 3;
+            valueA = a;
+            valueB = b;
+            valueC = 0;
+
+            if (a == 1)
+                ModifyConsoleCommand("test").pushFunction().defaultValue(1, 30).defaultValue(2, 40).setFunction(&testfunction4);
+            else if (a == -1)
+                ModifyConsoleCommand("test").popFunction();
+        }
+
+        void testfunction4(int a, int b, int c)
+        {
+            functionNr = 4;
+            valueA = a;
+            valueB = b;
+            valueC = c;
+
+            if (a == 1)
+                ModifyConsoleCommand("test").pushFunction().setFunction(&Testclass::testfunction5).setObject(class1);
+            else if (a == -1)
+                ModifyConsoleCommand("test").popFunction();
+        }
+
+        void Testclass::testfunction5(int a)
+        {
+            class1->b_ = 11;
+            class2->b_ = 22;
+
+            class1->other_ = class2;
+            class2->other_ = class1;
+
+            functionNr = 5;
+            valueA = a;
+            valueB = b_;
+            valueC = 0;
+
+            if (a == 2)
+                ModifyConsoleCommand("test").pushObject(this->other_);
+            else if (a == -2)
+                ModifyConsoleCommand("test").popObject();
+            else if (a == 1)
+                ModifyConsoleCommand("test").pushFunction(&Testclass::testfunction6, this);
+            else if (a == -1)
+                ModifyConsoleCommand("test").popFunction();
+        }
+
+        void Testclass::testfunction6(int a)
+        {
+            class1->b_ = 11;
+            class2->b_ = 22;
+
+            class1->other_ = class2;
+            class2->other_ = class1;
+
+            functionNr = 6;
+            valueA = a;
+            valueB = b_;
+            valueC = 0;
+
+            if (a == 2)
+                ModifyConsoleCommand("test").pushObject(this->other_);
+            else if (a == -2)
+                ModifyConsoleCommand("test").popObject();
+            else if (a == 1)
+                ModifyConsoleCommand("test").setFunction(FunctorPtr(nullptr));
+            else if (a == -1)
+                ModifyConsoleCommand("test").popFunction();
+        }
+
+        // Fixture
+        class CommandTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    new ConsoleCommandManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::CONSOLE_COMMAND);
+                    Context::setRootContext(new Context(nullptr));
+                    Identifier::initConfigValues_s = false; // TODO: hack!
+                    IdentifierManager::getInstance().createClassHierarchy();
+                }
+
+                virtual void TearDown() override
+                {
+                    IdentifierManager::getInstance().destroyClassHierarchy();
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::CONSOLE_COMMAND);
+                    delete &ConsoleCommandManager::getInstance();
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    void test(int function, int b, int c)
+    {
+        EXPECT_EQ(function, functionNr);
+        EXPECT_EQ(b, valueB);
+        EXPECT_EQ(c, valueC);
+    }
+
+    TEST_F(CommandTest, ModuleTest)
+    {
+        test(0, 0, 0);
+        CommandExecutor::execute("test 0", false);
+        test(1, 0, 0);
+        CommandExecutor::execute("test 1", false);
+        test(1, 0, 0);
+        CommandExecutor::execute("test 0", false);
+        test(2, 10, 0);
+        CommandExecutor::execute("test 0 123", false);
+        test(2, 123, 0);
+        CommandExecutor::execute("test 1 1234", false);
+        test(2, 1234, 0);
+        CommandExecutor::execute("test 1", false);
+        test(3, 20, 0);
+        CommandExecutor::execute("test 0", false);
+        test(4, 30, 40);
+        CommandExecutor::execute("test 1 100 200", false);
+        test(4, 100, 200);
+        CommandExecutor::execute("test 0", false);
+        test(5, 11, 0);
+        CommandExecutor::execute("test 1", false);
+        test(5, 11, 0);
+        CommandExecutor::execute("test 2", false);
+        test(6, 11, 0);
+        CommandExecutor::execute("test 0", false);
+        test(6, 22, 0);
+        CommandExecutor::execute("test -1", false);
+        test(6, 22, 0);
+        CommandExecutor::execute("test -1", false);
+        test(5, 11, 0);
+        CommandExecutor::execute("test 0", false);
+        test(4, 30, 40);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/command/ExecutorPtrTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/command/ExecutorPtrTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/command/ExecutorPtrTest.cc	(revision 11817)
@@ -0,0 +1,84 @@
+#include <gtest/gtest.h>
+#include "core/command/Executor.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class Testclass : public Destroyable
+        {
+            public:
+                void testMember() {}
+                static void testStatic() {}
+        };
+
+        class Subclass : public Testclass
+        {
+        };
+
+        // Fixture
+        class ExecutorPtrTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                }
+
+                virtual void TearDown() override
+                {
+                }
+        };
+    }
+
+    TEST_F(ExecutorPtrTest, emptyPtr)
+    {
+        ExecutorMemberPtr<Testclass> ptr1;
+        ExecutorStaticPtr ptr2;
+        ExecutorPtr ptr3;
+
+        ASSERT_FALSE(static_cast<bool>(ptr1));
+        ASSERT_FALSE(static_cast<bool>(ptr2));
+        ASSERT_FALSE(static_cast<bool>(ptr3));
+    }
+
+    TEST_F(ExecutorPtrTest, canAssignToExecutorMemberPtr)
+    {
+        ExecutorMemberPtr<Testclass> ptr = createExecutor(createFunctor(&Testclass::testMember));
+        ASSERT_TRUE(static_cast<bool>(ptr));
+    }
+
+    TEST_F(ExecutorPtrTest, canAssignToExecutorStaticPtr)
+    {
+        ExecutorStaticPtr ptr = createExecutor(createFunctor(&Testclass::testStatic));
+        ASSERT_TRUE(static_cast<bool>(ptr));
+    }
+
+    TEST_F(ExecutorPtrTest, canAssignToExecutorPtr)
+    {
+        ExecutorPtr ptr1 = createExecutor(createFunctor(&Testclass::testMember));
+        ASSERT_TRUE(static_cast<bool>(ptr1));
+        ExecutorPtr ptr2 = createExecutor(createFunctor(&Testclass::testStatic));
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+
+    TEST_F(ExecutorPtrTest, canCastFromExecutorMemberPtr)
+    {
+        ExecutorMemberPtr<Testclass> ptr1 = createExecutor(createFunctor(&Testclass::testMember));
+        ExecutorPtr ptr2 = ptr1;
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+
+    TEST_F(ExecutorPtrTest, canCastFromExecutorStaticPtr)
+    {
+        ExecutorStaticPtr ptr1 = createExecutor(createFunctor(&Testclass::testStatic));
+        ExecutorPtr ptr2 = ptr1;
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+
+    TEST_F(ExecutorPtrTest, canCastToExecutorMemberOfSubclass)
+    {
+        ExecutorPtr ptr1 = createExecutor(createFunctor(&Subclass::testMember));
+        ExecutorMemberPtr<Subclass> ptr2 = std::static_pointer_cast<ExecutorMember<Subclass>>(ptr1);
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/command/FunctorPtrTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/command/FunctorPtrTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/command/FunctorPtrTest.cc	(revision 11817)
@@ -0,0 +1,84 @@
+#include <gtest/gtest.h>
+#include "core/command/Functor.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class Testclass : public Destroyable
+        {
+            public:
+                void testMember() {}
+                static void testStatic() {}
+        };
+
+        class Subclass : public Testclass
+        {
+        };
+
+        // Fixture
+        class FunctorPtrTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                }
+
+                virtual void TearDown() override
+                {
+                }
+        };
+    }
+
+    TEST_F(FunctorPtrTest, emptyPtr)
+    {
+        FunctorMemberPtr<Testclass> ptr1;
+        FunctorStaticPtr ptr2;
+        FunctorPtr ptr3;
+
+        ASSERT_FALSE(static_cast<bool>(ptr1));
+        ASSERT_FALSE(static_cast<bool>(ptr2));
+        ASSERT_FALSE(static_cast<bool>(ptr3));
+    }
+
+    TEST_F(FunctorPtrTest, canAssignToFunctorMemberPtr)
+    {
+        FunctorMemberPtr<Testclass> ptr = createFunctor(&Testclass::testMember);
+        ASSERT_TRUE(static_cast<bool>(ptr));
+    }
+
+    TEST_F(FunctorPtrTest, canAssignToFunctorStaticPtr)
+    {
+        FunctorStaticPtr ptr = createFunctor(&Testclass::testStatic);
+        ASSERT_TRUE(static_cast<bool>(ptr));
+    }
+
+    TEST_F(FunctorPtrTest, canAssignToFunctorPtr)
+    {
+        FunctorPtr ptr1 = createFunctor(&Testclass::testMember);
+        ASSERT_TRUE(static_cast<bool>(ptr1));
+        FunctorPtr ptr2 = createFunctor(&Testclass::testStatic);
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+
+    TEST_F(FunctorPtrTest, canCastFromFunctorMemberPtr)
+    {
+        FunctorMemberPtr<Testclass> ptr1 = createFunctor(&Testclass::testMember);
+        FunctorPtr ptr2 = ptr1;
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+
+    TEST_F(FunctorPtrTest, canCastFromFunctorStaticPtr)
+    {
+        FunctorStaticPtr ptr1 = createFunctor(&Testclass::testStatic);
+        FunctorPtr ptr2 = ptr1;
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+
+    TEST_F(FunctorPtrTest, canCastToFunctorMemberOfSubclass)
+    {
+        FunctorPtr ptr1 = createFunctor(&Subclass::testMember);
+        FunctorMemberPtr<Subclass> ptr2 = std::static_pointer_cast<FunctorMember<Subclass>>(ptr1);
+        ASSERT_TRUE(static_cast<bool>(ptr2));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/command/FunctorTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/command/FunctorTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/command/FunctorTest.cc	(revision 11817)
@@ -0,0 +1,832 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <functional>
+#include "core/command/Functor.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        // Fixture
+        class FunctorTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                }
+
+                virtual void TearDown() override
+                {
+                }
+        };
+
+        class DestroyableClass : public Destroyable
+        {
+            public:
+                virtual void        method0() { return; }
+                virtual int         method1(int arg1) { return arg1; }
+                virtual float       method2(int arg1, float arg2) { return arg2; }
+                virtual bool        method3(int arg1, float arg2, bool arg3) { return arg3; }
+                virtual std::string method4(int arg1, float arg2, bool arg3, const std::string& arg4) { return arg4; }
+                virtual Vector3     method5(int arg1, float arg2, bool arg3, const std::string& arg4, const Vector3& arg5) { return arg5; }
+
+                static void        staticmethod0()
+                    { return staticinstance->method0(); }
+                static int         staticmethod1(int arg1)
+                    { return staticinstance->method1(arg1); }
+                static float       staticmethod2(int arg1, float arg2)
+                    { return staticinstance->method2(arg1, arg2); }
+                static bool        staticmethod3(int arg1, float arg2, bool arg3)
+                    { return staticinstance->method3(arg1, arg2, arg3); }
+                static std::string staticmethod4(int arg1, float arg2, bool arg3, const std::string& arg4)
+                    { return staticinstance->method4(arg1, arg2, arg3, arg4); }
+                static Vector3     staticmethod5(int arg1, float arg2, bool arg3, const std::string& arg4, const Vector3& arg5)
+                    { return staticinstance->method5(arg1, arg2, arg3, arg4, arg5); }
+
+                static DestroyableClass* staticinstance;
+        };
+
+        DestroyableClass* DestroyableClass::staticinstance = nullptr;
+
+        class MockDestroyableClass : public DestroyableClass
+        {
+            public:
+                MOCK_METHOD0(method0, void());
+                MOCK_METHOD1(method1, int(int));
+                MOCK_METHOD2(method2, float(int, float));
+                MOCK_METHOD3(method3, bool(int, float, bool));
+                MOCK_METHOD4(method4, std::string(int, float, bool, const std::string&));
+                MOCK_METHOD5(method5, Vector3(int, float, bool, const std::string&, const Vector3&));
+        };
+
+        class NonDestroyableClass
+        {
+            public:
+                void method() {}
+        };
+
+        void f1(int, double) {}
+        void f2(int, double, double) {}
+        int f3(int, double, double) { return 0; }
+        int f4a(int arg) { return arg*2; }
+        int f4b(int arg) { return arg*3; }
+        int multiply(int a, int b) { return a*b; }
+
+        struct CallableStruct
+        {
+            public:
+                int operator()()
+                {
+                    return 1;
+                }
+        };
+    }
+
+
+    ///////////////////////////////////////////////////////////////
+    ////////////////////// Functor (general) //////////////////////
+    ///////////////////////////////////////////////////////////////
+
+    TEST_F(FunctorTest, HasCorrectType)
+    {
+        FunctorMemberPtr<DestroyableClass> functor1 = createFunctor(&DestroyableClass::method0);
+        FunctorStaticPtr functor2 = createFunctor(&DestroyableClass::staticmethod0);
+        EXPECT_EQ(Functor::Type::Member, functor1->getType());
+        EXPECT_EQ(Functor::Type::Static, functor2->getType());
+    }
+
+    TEST_F(FunctorTest, ReturnsCorrectParamCount)
+    {
+        EXPECT_EQ(0u, createFunctor(&DestroyableClass::method0)->getParamCount());
+        EXPECT_EQ(1u, createFunctor(&DestroyableClass::method1)->getParamCount());
+        EXPECT_EQ(2u, createFunctor(&DestroyableClass::method2)->getParamCount());
+        EXPECT_EQ(3u, createFunctor(&DestroyableClass::method3)->getParamCount());
+        EXPECT_EQ(4u, createFunctor(&DestroyableClass::method4)->getParamCount());
+        EXPECT_EQ(5u, createFunctor(&DestroyableClass::method5)->getParamCount());
+    }
+
+    TEST_F(FunctorTest, HasReturnValue)
+    {
+        EXPECT_FALSE(createFunctor(&DestroyableClass::method0)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method1)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method2)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method3)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method4)->hasReturnvalue());
+        EXPECT_TRUE(createFunctor(&DestroyableClass::method5)->hasReturnvalue());
+    }
+
+    TEST_F(FunctorTest, GetTypenameParam)
+    {
+        FunctorPtr functor = createFunctor(&DestroyableClass::method5);
+        EXPECT_EQ("int",     functor->getTypenameParam(0));
+        EXPECT_EQ("float",   functor->getTypenameParam(1));
+        EXPECT_EQ("bool",    functor->getTypenameParam(2));
+        EXPECT_EQ("string",  functor->getTypenameParam(3));
+        EXPECT_EQ("Vector3", functor->getTypenameParam(4));
+        EXPECT_EQ("",        functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
+    }
+
+    TEST_F(FunctorTest, TypenameParamIsAlwaysVoidForFunctionWithoutParams)
+    {
+        FunctorPtr functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ("void", functor->getTypenameParam(0));
+        EXPECT_EQ("void", functor->getTypenameParam(1));
+        EXPECT_EQ("void", functor->getTypenameParam(2));
+        EXPECT_EQ("void", functor->getTypenameParam(3));
+        EXPECT_EQ("void", functor->getTypenameParam(4));
+        EXPECT_EQ("",     functor->getTypenameParam(5)); // max 5 arguments supported (index 0-4) -> this returns empty string
+    }
+
+    TEST_F(FunctorTest, GetTypenameReturnvalue)
+    {
+        EXPECT_EQ("void",    createFunctor(&DestroyableClass::method0)->getTypenameReturnvalue());
+        EXPECT_EQ("int",     createFunctor(&DestroyableClass::method1)->getTypenameReturnvalue());
+        EXPECT_EQ("float",   createFunctor(&DestroyableClass::method2)->getTypenameReturnvalue());
+        EXPECT_EQ("bool",    createFunctor(&DestroyableClass::method3)->getTypenameReturnvalue());
+        EXPECT_EQ("string",  createFunctor(&DestroyableClass::method4)->getTypenameReturnvalue());
+        EXPECT_EQ("Vector3", createFunctor(&DestroyableClass::method5)->getTypenameReturnvalue());
+    }
+
+    TEST_F(FunctorTest, GetFullIdentifier)
+    {
+        // static
+        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getFullIdentifier());
+        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getFullIdentifier());
+        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getFullIdentifier());
+        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getFullIdentifier());
+        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getFullIdentifier());
+        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getFullIdentifier());
+
+        // member
+        EXPECT_EQ(typeid(       void(DestroyableClass::*)()),                                                     createFunctor(&DestroyableClass::method0)->getFullIdentifier());
+        EXPECT_EQ(typeid(        int(DestroyableClass::*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getFullIdentifier());
+        EXPECT_EQ(typeid(      float(DestroyableClass::*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getFullIdentifier());
+        EXPECT_EQ(typeid(       bool(DestroyableClass::*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getFullIdentifier());
+        EXPECT_EQ(typeid(std::string(DestroyableClass::*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getFullIdentifier());
+        EXPECT_EQ(typeid(    Vector3(DestroyableClass::*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getFullIdentifier());
+    }
+
+    TEST_F(FunctorTest, GetHeaderIdentifier)
+    {
+        // static
+        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier());
+
+        // member
+        EXPECT_EQ(typeid(       void(*)()),                                                     createFunctor(&DestroyableClass::method0)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(        int(*)(int)),                                                  createFunctor(&DestroyableClass::method1)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(      float(*)(int, float)),                                           createFunctor(&DestroyableClass::method2)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(       bool(*)(int, float, bool)),                                     createFunctor(&DestroyableClass::method3)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(std::string(*)(int, float, bool, const std::string&)),                 createFunctor(&DestroyableClass::method4)->getHeaderIdentifier());
+        EXPECT_EQ(typeid(    Vector3(*)(int, float, bool, const std::string&, const Vector3&)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier());
+    }
+
+    TEST_F(FunctorTest, GetHeaderIdentifierFor2Params)
+    {
+        // static
+        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::staticmethod0)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::staticmethod1)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::staticmethod2)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::staticmethod3)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::staticmethod4)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::staticmethod5)->getHeaderIdentifier(2));
+
+        // member
+        EXPECT_EQ(typeid(       void(*)()),           createFunctor(&DestroyableClass::method0)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(        int(*)(int)),        createFunctor(&DestroyableClass::method1)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(      float(*)(int, float)), createFunctor(&DestroyableClass::method2)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(       bool(*)(int, float)), createFunctor(&DestroyableClass::method3)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(std::string(*)(int, float)), createFunctor(&DestroyableClass::method4)->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(    Vector3(*)(int, float)), createFunctor(&DestroyableClass::method5)->getHeaderIdentifier(2));
+    }
+
+    TEST_F(FunctorTest, GetHeaderIdentifierForNParams)
+    {
+        // static
+        FunctorStaticPtr functorStatic = createFunctor(&DestroyableClass::staticmethod5);
+        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorStatic->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorStatic->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorStatic->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorStatic->getHeaderIdentifier(3));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorStatic->getHeaderIdentifier(4));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(5));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorStatic->getHeaderIdentifier(6));
+
+        // member
+        FunctorMemberPtr<DestroyableClass> functorMember = createFunctor(&DestroyableClass::method5);
+        EXPECT_EQ(typeid(Vector3(*)()),                                                     functorMember->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(Vector3(*)(int)),                                                  functorMember->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(Vector3(*)(int, float)),                                           functorMember->getHeaderIdentifier(2));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool)),                                     functorMember->getHeaderIdentifier(3));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&)),                 functorMember->getHeaderIdentifier(4));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(5));
+        EXPECT_EQ(typeid(Vector3(*)(int, float, bool, const std::string&, const Vector3&)), functorMember->getHeaderIdentifier(6));
+    }
+
+    TEST_F(FunctorTest, CanClone)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPtr clone = functor->clone();
+        EXPECT_NE(nullptr, clone.get());
+    }
+
+    TEST_F(FunctorTest, ClonedFunctorCanBeCalled)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPtr clone = functor->clone();
+
+        EXPECT_EQ(8, (*functor)(4).get<int>());
+        EXPECT_EQ(8, (*clone)(4).get<int>());
+    }
+
+    TEST_F(FunctorTest, ClonedFunctorKeepsFunction)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
+
+        FunctorPtr clone = functor->clone();
+        FunctorPointer<int(*)(int)>* clonePointer = static_cast<FunctorPointer<int(*)(int)>*>(clone.get());
+
+        EXPECT_EQ(&f4a, pointer->getFunction());
+        EXPECT_EQ(&f4a, clonePointer->getFunction());
+    }
+
+    TEST_F(FunctorTest, ClonedFunctorKeepsObject)
+    {
+        DestroyableClass object;
+        FunctorPtr functor = createFunctor(&DestroyableClass::method0, &object);
+        FunctorPtr clone = functor->clone();
+
+        EXPECT_EQ(&object, functor->getRawObjectPointer());
+        EXPECT_EQ(&object, clone->getRawObjectPointer());
+    }
+
+    // TODO: test fails... fix or delete clone()
+//    TEST_F(FunctorTest, ClonedFunctorKeepsSafeMode)
+//    {
+//        DestroyableClass* object = new DestroyableClass();
+//        FunctorPtr functor = createFunctor(&DestroyableClass::method0, object);
+//        functor->setSafeMode(true);
+//        FunctorPtr clone = functor->clone();
+//
+//        EXPECT_EQ(object, functor->getRawObjectPointer());
+//        EXPECT_EQ(object, clone->getRawObjectPointer());
+//        object->destroy();
+//        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+//        EXPECT_EQ(nullptr, clone->getRawObjectPointer());
+//
+//    }
+
+    TEST_F(FunctorTest, CanEvaluateArgument)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        MultiType value("5");
+        EXPECT_FALSE(value.isType<int>());
+        EXPECT_TRUE(value.isType<std::string>());
+        functor->evaluateArgument(0, value);
+        EXPECT_TRUE(value.isType<int>());
+        EXPECT_FALSE(value.isType<std::string>());
+    }
+
+    TEST_F(FunctorTest, CanGetAndSetFunctionPointer)
+    {
+        FunctorPtr functor = createFunctor(&f4a);
+        FunctorPointer<int(*)(int)>* pointer = static_cast<FunctorPointer<int(*)(int)>*>(functor.get());
+
+        EXPECT_EQ(6, (*functor)(3).get<int>()); // 3*2 = 6
+        EXPECT_EQ(&f4a, pointer->getFunction());
+
+        pointer->setFunction(&f4b);
+
+        EXPECT_EQ(9, (*functor)(3).get<int>()); // 3*3 = 9
+        EXPECT_EQ(&f4b, pointer->getFunction());
+    }
+
+    TEST_F(FunctorTest, ReturnsValue)
+    {
+        DestroyableClass object;
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
+            int result = (*functor)(&object, 13);
+            EXPECT_EQ(13, result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
+            float result = (*functor)(&object, 0, 111.11f);
+            EXPECT_FLOAT_EQ(111.11f, result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
+            bool result = (*functor)(&object, 0, 0, true);
+            EXPECT_EQ(true, result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
+            std::string result = (*functor)(&object, 0, 0, false, "test");
+            EXPECT_EQ("test", result);
+        }
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
+            Vector3 result = (*functor)(&object, 0, 0, false, "", Vector3(3, 2, 1));
+            EXPECT_EQ(Vector3(3, 2, 1), result);
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////
+    ////////////////////// FunctorMember //////////////////////
+    ///////////////////////////////////////////////////////////
+
+    TEST_F(FunctorTest, FunctorMember_CanSetObject)
+    {
+        DestroyableClass object;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ(nullptr, functor->getObject());
+        functor->setObject(&object);
+        EXPECT_EQ(&object, functor->getObject());
+        functor->setObject(nullptr);
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanSetObjectInConstructor)
+    {
+        DestroyableClass object;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &object);
+        EXPECT_EQ(&object, functor->getObject());
+        functor->setObject(nullptr);
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanSetRawObjectPointer)
+    {
+        DestroyableClass object;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(&object);
+        EXPECT_EQ(&object, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(nullptr);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_RawObjectPointerAndObjectAreEqual)
+    {
+        DestroyableClass object1;
+        DestroyableClass object2;
+
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        EXPECT_EQ(nullptr, functor->getObject());
+        functor->setObject(&object1);
+        EXPECT_EQ(&object1, functor->getRawObjectPointer());
+        EXPECT_EQ(&object1, functor->getObject());
+        functor->setObject(&object2);
+        EXPECT_EQ(&object2, functor->getRawObjectPointer());
+        EXPECT_EQ(&object2, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_SetObjectThenActivateSafeMode)
+    {
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        {
+            DestroyableClass object;
+            functor->setObject(&object);
+            functor->setSafeMode(true);
+            EXPECT_EQ(&object, functor->getObject());
+        }
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_ActivateSafeModeThenSetObject)
+    {
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        {
+            DestroyableClass object;
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            EXPECT_EQ(&object, functor->getObject());
+        }
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeCanBeDisabledAfterObjectWasSet)
+    {
+        DestroyableClass* ptr;
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        {
+            DestroyableClass object;
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            functor->setSafeMode(false);
+            ptr = &object; // remember the pointer
+            EXPECT_EQ(ptr, functor->getObject());
+        }
+        EXPECT_EQ(ptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeWorks_CanChangeObject)
+    {
+        FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+        DestroyableClass* object1 = new DestroyableClass();
+        DestroyableClass* object2 = new DestroyableClass();
+        functor->setSafeMode(true);
+
+        functor->setObject(object1);
+        EXPECT_EQ(object1, functor->getObject());
+        functor->setObject(object2);
+        EXPECT_EQ(object2, functor->getObject());
+        object1->destroy();
+        EXPECT_EQ(object2, functor->getObject());
+        object2->destroy();
+        EXPECT_EQ(nullptr, functor->getObject());
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanDestroyFunctorWhenObjectInSafeModeStillExists)
+    {
+        DestroyableClass object;
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            EXPECT_EQ(&object, functor->getObject());
+        } // functor is destroyed here
+    }
+
+    TEST_F(FunctorTest, FunctorMember_SafeModeDoesntDoAnythingWithObjectsNotInheritedFromDestroyable)
+    {
+        NonDestroyableClass* ptr;
+        FunctorMemberPtr<NonDestroyableClass> functor = createFunctor(&NonDestroyableClass::method);
+        {
+            NonDestroyableClass object;
+            functor->setSafeMode(true);
+            functor->setObject(&object);
+            ptr = &object; // remember the pointer
+            EXPECT_EQ(ptr, functor->getObject());
+        }
+        EXPECT_EQ(ptr, functor->getObject()); // pointer is still set because safe mode doesn't work on NonDestroyableClass
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInCall)
+    {
+        MockDestroyableClass mock;
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0);
+            (*functor)(&mock);
+        }
+        {
+            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
+            (*functor)(&mock, 13);
+        }
+        {
+            EXPECT_CALL(mock, method2(13, 111.11f)).WillOnce(::testing::Return(0.0f));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2);
+            (*functor)(&mock, 13, 111.11f);
+        }
+        {
+            EXPECT_CALL(mock, method3(13, 111.11f, true)).WillOnce(::testing::Return(false));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3);
+            (*functor)(&mock, 13, 111.11f, true);
+        }
+        {
+            EXPECT_CALL(mock, method4(13, 111.11f, true, "test")).WillOnce(::testing::Return(""));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4);
+            (*functor)(&mock, 13, 111.11f, true, "test");
+        }
+        {
+            EXPECT_CALL(mock, method5(13, 111.11f, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5);
+            (*functor)(&mock, 13, 111.11f, true, "test", Vector3(3, 2, 1));
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorMember_CanCall_WithObjectInConstructor)
+    {
+        MockDestroyableClass mock;
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method0, &mock);
+            (*functor)();
+        }
+        {
+            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1, &mock);
+            (*functor)(13);
+        }
+        {
+            EXPECT_CALL(mock, method2(13, 111.11f)).WillOnce(::testing::Return(0.0f));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method2, &mock);
+            (*functor)(13, 111.11f);
+        }
+        {
+            EXPECT_CALL(mock, method3(13, 111.11f, true)).WillOnce(::testing::Return(false));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method3, &mock);
+            (*functor)(13, 111.11f, true);
+        }
+        {
+            EXPECT_CALL(mock, method4(13, 111.11f, true, "test")).WillOnce(::testing::Return(""));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method4, &mock);
+            (*functor)(13, 111.11f, true, "test");
+        }
+        {
+            EXPECT_CALL(mock, method5(13, 111.11f, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method5, &mock);
+            (*functor)(13, 111.11f, true, "test", Vector3(3, 2, 1));
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorMember_ReturnsZeroIfCalledWithoutObject)
+    {
+        DestroyableClass object;
+        {
+            FunctorMemberPtr<DestroyableClass> functor = createFunctor(&DestroyableClass::method1);
+            int resultWithObject = (*functor)(&object, 13);
+            int resultWithoutObject = (*functor)(13);
+            EXPECT_EQ(13, resultWithObject);
+            EXPECT_EQ(0, resultWithoutObject);
+        }
+    }
+
+
+    ///////////////////////////////////////////////////////////
+    ////////////////////// FunctorStatic //////////////////////
+    ///////////////////////////////////////////////////////////
+
+    TEST_F(FunctorTest, FunctorStatic_CanCall)
+    {
+        MockDestroyableClass mock;
+        DestroyableClass::staticinstance = &mock;
+
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+            (*functor)();
+        }
+        {
+            EXPECT_CALL(mock, method1(13)).WillOnce(::testing::Return(0));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod1);
+            (*functor)(13);
+        }
+        {
+            EXPECT_CALL(mock, method2(13, 111.11f)).WillOnce(::testing::Return(0.0f));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod2);
+            (*functor)(13, 111.11f);
+        }
+        {
+            EXPECT_CALL(mock, method3(13, 111.11f, true)).WillOnce(::testing::Return(false));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod3);
+            (*functor)(13, 111.11f, true);
+        }
+        {
+            EXPECT_CALL(mock, method4(13, 111.11f, true, "test")).WillOnce(::testing::Return(""));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod4);
+            (*functor)(13, 111.11f, true, "test");
+        }
+        {
+            EXPECT_CALL(mock, method5(13, 111.11f, true, "test", Vector3(3, 2, 1))).WillOnce(::testing::Return(Vector3()));
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod5);
+            (*functor)(13, 111.11f, true, "test", Vector3(3, 2, 1));
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorStatic_CanCallWithObject)
+    {
+        MockDestroyableClass mock;
+        DestroyableClass::staticinstance = &mock;
+
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+            (*functor)(&mock); // object is ignored
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorStatic_CanCallWithNull)
+    {
+        MockDestroyableClass mock;
+        DestroyableClass::staticinstance = &mock;
+
+        {
+            EXPECT_CALL(mock, method0());
+            FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+            (*functor)(nullptr); // pointer is ignored
+        }
+    }
+
+    TEST_F(FunctorTest, FunctorStatic_RawObjectPointerIsAlwaysNull)
+    {
+        DestroyableClass object;
+
+        FunctorStaticPtr functor = createFunctor(&DestroyableClass::staticmethod0);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(&object);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+        functor->setRawObjectPointer(nullptr);
+        EXPECT_EQ(nullptr, functor->getRawObjectPointer());
+    }
+
+    ////////////////////////////// Various tests //////////////////////////////
+
+    TEST_F(FunctorTest, CreateFunctorWithVariousFunctionTypes)
+    {
+        FunctorPtr c1 = createFunctor(&f4a);
+        FunctorPtr c2 = createFunctor(&f4b);
+        FunctorPtr c3 = createFunctor([] (int arg) { return arg*4; });
+        auto lambda = [] (int arg1, int arg2) { return arg1*arg2; };
+        FunctorPtr c4 = createFunctor(lambda);
+
+        std::function<int()> bind0 = std::bind(multiply, 4, 6);
+        std::function<int(int)> bind1 = std::bind(multiply, std::placeholders::_1, 7);
+        std::function<int(int, int)> bind2 = std::bind(multiply, std::placeholders::_1, std::placeholders::_2);
+        std::function<int(int)> function = f4a;
+
+        FunctorPtr c5 = createFunctor(bind0);
+        FunctorPtr c6 = createFunctor(bind1);
+        FunctorPtr c7 = createFunctor(bind2);
+        FunctorPtr c8 = createFunctor(function);
+
+
+        EXPECT_EQ(8,  (*c1)(4).get<int>());
+        EXPECT_EQ(12, (*c2)(4).get<int>());
+        EXPECT_EQ(16, (*c3)(4).get<int>());
+        EXPECT_EQ(20, (*c4)(4, 5).get<int>());
+        EXPECT_EQ(24, (*c5)(4).get<int>());
+        EXPECT_EQ(28, (*c6)(4).get<int>());
+        EXPECT_EQ(32, (*c7)(4, 8).get<int>());
+        EXPECT_EQ(8,  (*c8)(4).get<int>());
+
+        EXPECT_EQ(1u, c1->getParamCount());
+        EXPECT_EQ(1u, c2->getParamCount());
+        EXPECT_EQ(1u, c3->getParamCount());
+        EXPECT_EQ(2u, c4->getParamCount());
+        EXPECT_EQ(0u, c5->getParamCount());
+        EXPECT_EQ(1u, c6->getParamCount());
+        EXPECT_EQ(2u, c7->getParamCount());
+        EXPECT_EQ(1u, c8->getParamCount());
+
+        EXPECT_EQ(typeid(int(*)(int)), c1->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c2->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c3->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)(int, int)), c4->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)()), c5->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c6->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)(int, int)), c7->getFullIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c8->getFullIdentifier());
+
+        EXPECT_EQ(typeid(int(*)(int)), c1->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c2->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c3->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)(int, int)), c4->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c6->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)(int, int)), c7->getHeaderIdentifier());
+        EXPECT_EQ(typeid(int(*)(int)), c8->getHeaderIdentifier());
+
+        EXPECT_EQ(typeid(int(*)(int)), c1->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)(int)), c2->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)(int)), c3->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)(int)), c4->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)(int)), c6->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)(int)), c7->getHeaderIdentifier(1));
+        EXPECT_EQ(typeid(int(*)(int)), c8->getHeaderIdentifier(1));
+
+        EXPECT_EQ(typeid(int(*)()), c1->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c2->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c3->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c4->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c5->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c6->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c7->getHeaderIdentifier(0));
+        EXPECT_EQ(typeid(int(*)()), c8->getHeaderIdentifier(0));
+    }
+
+    TEST_F(FunctorTest, CanCallFunctorWithLambdaWichIsAlreadyOutOfScope)
+    {
+        int var1 = 1;
+        FunctorPtr fp1a = createFunctor([&var1] () { return var1++; });
+        FunctorPtr fp1b = createFunctor([&var1] () { return var1; });
+        FunctorPtr fp2;
+        FunctorPtr fp3;
+
+        {
+            int var2 = 2;
+            fp2 = createFunctor([var2] () { return var2; });
+        }
+        {
+            int var3 = 3;
+            fp3 = createFunctor([var3] () { return var3; });
+        }
+
+        EXPECT_EQ(1, var1);
+        EXPECT_EQ(1, (*fp1a)().get<int>());
+        EXPECT_EQ(2, var1);
+        EXPECT_EQ(2, (*fp1b)().get<int>());
+
+        EXPECT_EQ(2, (*fp2)().get<int>());
+        EXPECT_EQ(3, (*fp3)().get<int>());
+    }
+
+    TEST_F(FunctorTest, canCompareHeaderIdentifiers)
+    {
+        FunctorPtr fp1 = createFunctor(&f1);
+        FunctorPtr fp2 = createFunctor(&f2);
+        FunctorPtr fp3 = createFunctor(&f3);
+        ASSERT_STREQ(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(1).name());
+        ASSERT_STREQ(fp1->getHeaderIdentifier(2).name(), fp2->getHeaderIdentifier(2).name());
+        ASSERT_STRNE(fp1->getHeaderIdentifier(1).name(), fp2->getHeaderIdentifier(2).name());
+        ASSERT_STRNE(fp1->getHeaderIdentifier(10).name(), fp2->getHeaderIdentifier(10).name());
+        ASSERT_STRNE(fp2->getHeaderIdentifier(2).name(), fp3->getHeaderIdentifier(2).name());
+        ASSERT_STRNE(fp1->getHeaderIdentifier().name(), fp2->getHeaderIdentifier().name());
+        ASSERT_STRNE(fp2->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name());
+    }
+
+    TEST_F(FunctorTest, canCompareTypenames)
+    {
+        FunctorPtr fp1 = createFunctor(&f1);
+        FunctorPtr fp2 = createFunctor(&f2);
+        FunctorPtr fp3 = createFunctor(&f3);
+        ASSERT_EQ(fp1->getTypenameReturnvalue(), fp2->getTypenameReturnvalue());
+        ASSERT_EQ(fp1->getTypenameParam(0), fp3->getTypenameParam(0));
+        ASSERT_EQ("void", fp1->getTypenameReturnvalue());
+        ASSERT_EQ("int", fp3->getTypenameReturnvalue());
+        ASSERT_EQ("int", fp2->getTypenameParam(0));
+        ASSERT_EQ("double", fp3->getTypenameParam(2));
+        ASSERT_EQ("", fp3->getTypenameParam(6));
+    }
+
+    TEST_F(FunctorTest, testGetParamCountAndHasReturnValue)
+    {
+        FunctorPtr fp1 = createFunctor(&f1);
+        FunctorPtr fp2 = createFunctor(&f2);
+        FunctorPtr fp3 = createFunctor(&f3);
+        ASSERT_EQ(3u, fp2->getParamCount());
+        ASSERT_NE(fp1->getParamCount(), fp3->getParamCount());
+        ASSERT_FALSE(fp2->hasReturnvalue());
+        ASSERT_TRUE(fp3->hasReturnvalue());
+    }
+
+    TEST_F(FunctorTest, canEvaluateArgument)
+    {
+        FunctorPtr fp1 = createFunctor(&f1);
+        MultiType mttype = "2";
+        fp1->evaluateArgument(0, mttype);
+        ASSERT_TRUE(mttype.isType<int>());
+        ASSERT_EQ(2, mttype.get<int>());
+        fp1->evaluateArgument(1, mttype);
+        ASSERT_TRUE(mttype.isType<double>());
+        ASSERT_EQ(2.0, mttype.get<double>());
+        mttype.reset();
+        fp1->evaluateArgument(5, mttype);
+        ASSERT_TRUE(mttype.null());
+    }
+
+    TEST_F(FunctorTest, canUseCallables)
+    {
+        int a = 0;
+        FunctorPtr fp1 = createFunctor(CallableStruct{});
+        FunctorPtr fp2 = createFunctor([](bool val) { return val; });
+        FunctorPtr fp3 = createFunctor([&a]() {return a++; });
+        FunctorPtr fp4 = createFunctor([a]() {return a; });
+        ASSERT_EQ(1, (*fp1)().get<int>());
+        ASSERT_EQ(true, (*fp2)(true).get<bool>());
+        ASSERT_EQ(0, (*fp3)().get<int>());
+        ASSERT_EQ(1, a);
+        ASSERT_EQ(0, (*fp4)().get<int>());
+        ASSERT_STREQ(fp1->getHeaderIdentifier().name(), fp3->getHeaderIdentifier().name());
+    }
+
+    TEST_F(FunctorTest, SafeModeWorks)
+    {
+        DestroyableClass* testclass = new DestroyableClass();
+        DestroyableClass* testclass2 = new DestroyableClass();
+        FunctorPtr fp1 = createFunctor(&DestroyableClass::method0, testclass);
+        fp1->setSafeMode(true);
+        FunctorPtr fp2 = createFunctor(&DestroyableClass::method0, testclass);
+        fp2->setSafeMode(true);
+        FunctorPtr fp3 = createFunctor(&DestroyableClass::method0, testclass);
+        fp2->setRawObjectPointer(testclass2);
+
+        ASSERT_NE(nullptr, fp1->getRawObjectPointer());
+        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
+        ASSERT_NE(nullptr, fp3->getRawObjectPointer());
+        testclass->destroy();
+        ASSERT_EQ(nullptr, fp1->getRawObjectPointer());
+        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
+        ASSERT_NE(nullptr, fp3->getRawObjectPointer());
+
+        fp3->setRawObjectPointer(testclass2);
+        fp3->setSafeMode(true);
+        fp2->setSafeMode(false);
+        testclass2->destroy();
+        ASSERT_NE(nullptr, fp2->getRawObjectPointer());
+        ASSERT_EQ(nullptr, fp3->getRawObjectPointer());
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/ClassFactoryTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/ClassFactoryTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/ClassFactoryTest.cc	(revision 11817)
@@ -0,0 +1,42 @@
+#include <gtest/gtest.h>
+#include "core/object/ClassFactory.h"
+#include "core/BaseObject.h"
+#include "core/object/Context.h"
+#include "core/module/ModuleInstance.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        // Fixture
+        class ClassFactoryTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(ClassFactoryTest, CanFabricateObject)
+    {
+        Factory* factory = new ClassFactoryWithContext<BaseObject>();
+        Identifiable* object = factory->fabricate(nullptr);
+        ASSERT_TRUE(object != nullptr);
+        BaseObject* baseObject = dynamic_cast<BaseObject*>(object);
+        EXPECT_TRUE(baseObject != nullptr);
+        delete object;
+        // don't delete factory - it remains in the identifier
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/ContextTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/ContextTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/ContextTest.cc	(revision 11817)
@@ -0,0 +1,87 @@
+#include <gtest/gtest.h>
+#include "core/object/Context.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/CoreIncludes.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class SubclassContext : public OrxonoxClass, public Context
+        {
+            public:
+                SubclassContext() : Context(nullptr) { RegisterObject(SubclassContext); }
+        };
+
+        RegisterClassNoArgs(SubclassContext);
+
+        // Fixture
+        class ContextTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(ContextTest, CanCreateContext)
+    {
+        Context context(nullptr);
+    }
+
+    TEST_F(ContextTest, CanCreateSubclassContext)
+    {
+        SubclassContext context;
+    }
+
+    TEST_F(ContextTest, ContextIsItsOwnContext)
+    {
+        Context context(nullptr);
+        EXPECT_EQ(&context, context.getContext());
+    }
+
+    TEST_F(ContextTest, SubclassContextIsItsOwnContext)
+    {
+        SubclassContext context;
+        EXPECT_EQ(&context, context.getContext());
+    }
+
+    TEST_F(ContextTest, SubclassAddsToItsOwnObjectList)
+    {
+        SubclassContext context;
+        EXPECT_EQ(&context, context.getContext());
+        EXPECT_EQ(1u, context.getObjectList<SubclassContext>()->size());
+    }
+
+    TEST_F(ContextTest, ContextIsAddedToItsOwnObjectList)
+    {
+        Context context(nullptr);
+        ASSERT_EQ(1u, context.getObjectList<Context>()->size());
+        EXPECT_TRUE(context.getObjectList<Context>()->begin()->objectBase_ == static_cast<Listable*>(&context));
+    }
+
+    TEST_F(ContextTest, ContextIsAddedToObjectListOfBaseContext)
+    {
+        Context baseContext(nullptr);
+        Context subContext(&baseContext);
+
+        ASSERT_EQ(1u, subContext.getObjectList<Context>()->size());
+        EXPECT_TRUE(subContext.getObjectList<Context>()->begin()->objectBase_ == static_cast<Listable*>(&subContext));
+
+        ASSERT_EQ(2u, baseContext.getObjectList<Context>()->size());
+        EXPECT_TRUE(baseContext.getObjectList<Context>()->begin()->objectBase_ == static_cast<Listable*>(&baseContext));
+        EXPECT_TRUE(baseContext.getObjectList<Context>()->begin()->next_->objectBase_ == static_cast<Listable*>(&subContext));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/DestroyableTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/DestroyableTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/DestroyableTest.cc	(revision 11817)
@@ -0,0 +1,64 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "core/object/Destroyable.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class DestroyableTest : public Destroyable
+        {
+            public:
+                DestroyableTest(bool& destroyed) : destroyed_(destroyed) { destroyed_ = false; }
+                virtual ~DestroyableTest() { destroyed_ = true; }
+                MOCK_METHOD0(preDestroy, void());
+
+            private:
+                bool& destroyed_;
+        };
+
+        class DestructionListenerMock : public DestructionListener
+        {
+            public:
+                MOCK_METHOD0(objectDeleted, void());
+                inline void registerAsDestructionListener(Destroyable* object)
+                    { this->DestructionListener::registerAsDestructionListener(object); }
+        };
+    }
+
+    TEST(DestroyableTest, DestroyDeletesInstance)
+    {
+        bool destroyed = false;
+        DestroyableTest* test = new DestroyableTest(destroyed);
+        EXPECT_FALSE(destroyed);
+        EXPECT_TRUE(test != nullptr);
+        test->destroy();
+        EXPECT_TRUE(destroyed);
+    }
+
+    TEST(DestroyableTest, DestroyCallsPreDestroy)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        EXPECT_CALL(*test, preDestroy());
+        test->destroy();
+    }
+
+    TEST(DestroyableTest, DestroyCallsListener)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        DestructionListenerMock listener;
+        listener.registerAsDestructionListener(test);
+        EXPECT_CALL(listener, objectDeleted());
+        test->destroy();
+    }
+
+    TEST(DestroyableTest, ReferenceCounterIsZero)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        EXPECT_EQ(0u, test->getReferenceCount());
+        test->destroy();
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/IteratorTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/IteratorTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/IteratorTest.cc	(revision 11817)
@@ -0,0 +1,147 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "core/object/Iterator.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/OrxonoxInterface.h"
+#include "core/CoreIncludes.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestInterface : virtual public OrxonoxInterface
+        {
+            public:
+                TestInterface() { RegisterObject(TestInterface); }
+        };
+
+        class TestClass : public OrxonoxClass, public TestInterface
+        {
+            public:
+                TestClass() { RegisterObject(TestClass); }
+                MOCK_METHOD0(test, void());
+        };
+
+        RegisterClassNoArgs(TestInterface);
+        RegisterClassNoArgs(TestClass);
+
+        // Fixture
+        class IteratorTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(IteratorTest, CanCreateIterator)
+    {
+        Iterator<TestInterface> it;
+    }
+
+    TEST_F(IteratorTest, CanAssignIterator)
+    {
+        ObjectList<TestInterface> list;
+        Iterator<TestInterface> it = list.begin();
+    }
+
+    TEST_F(IteratorTest, CanIterateOverEmptyList)
+    {
+        size_t i = 0;
+        ObjectList<TestInterface> list;
+        for (Iterator<TestInterface> it = list.begin(); it != list.end(); ++it)
+            ++i;
+        EXPECT_EQ(0u, i);
+    }
+
+    TEST_F(IteratorTest, CanCallObjects)
+    {
+        TestClass test1;
+        TestClass test2;
+        TestClass test3;
+
+        EXPECT_CALL(test1, test());
+        EXPECT_CALL(test2, test());
+        EXPECT_CALL(test3, test());
+
+        // iterate over interfaces but use a TestClass iterator - now we can call TestClass::test()
+        ObjectList<TestInterface> list;
+        for (Iterator<TestClass> it = list.begin(); it != list.end(); ++it)
+            it->test();
+    }
+
+    TEST_F(IteratorTest, CanIterateOverInterfaceListWithInterfaceIterator)
+    {
+        TestClass testClass;
+        TestInterface testInterface;
+
+        size_t i = 0;
+        ObjectList<TestInterface> list;
+        for (Iterator<TestInterface> it = list.begin(); it != list.end(); ++it)
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&testClass, *it);
+            if (i == 2u) EXPECT_EQ(&testInterface, *it);
+        }
+        EXPECT_EQ(2u, i);
+    }
+
+    TEST_F(IteratorTest, CanIterateOverClassListWithClassIterator)
+    {
+        TestClass testClass;
+        TestInterface testInterface;
+
+        size_t i = 0;
+        ObjectList<TestClass> list;
+        for (Iterator<TestClass> it = list.begin(); it != list.end(); ++it)
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&testClass, *it);
+        }
+        EXPECT_EQ(1u, i);
+    }
+
+    TEST_F(IteratorTest, CanIterateOverInterfaceListWithClassIterator)
+    {
+        TestClass testClass;
+        TestInterface testInterface;
+
+        size_t i = 0;
+        ObjectList<TestInterface> list;
+        for (Iterator<TestClass> it = list.begin(); it != list.end(); ++it)
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&testClass, *it);
+            if (i == 2u) EXPECT_EQ(nullptr, *it);
+        }
+        EXPECT_EQ(2u, i);
+    }
+
+    TEST_F(IteratorTest, CanIterateOverClassListWithInterfaceIterator)
+    {
+        TestClass testClass;
+        TestInterface testInterface;
+
+        size_t i = 0;
+        ObjectList<TestClass> list;
+        for (Iterator<TestInterface> it = list.begin(); it != list.end(); ++it)
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&testClass, *it);
+        }
+        EXPECT_EQ(1u, i);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/ListableTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/ListableTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/ListableTest.cc	(revision 11817)
@@ -0,0 +1,251 @@
+#include <gtest/gtest.h>
+#include "core/object/Listable.h"
+#include "core/CoreIncludes.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class ListableClassTest : public Listable
+        {
+            public:
+                ListableClassTest() { RegisterObject(ListableClassTest); }
+        };
+
+        class ListableSubclassTest : public ListableClassTest
+        {
+            public:
+                ListableSubclassTest() { RegisterObject(ListableSubclassTest); }
+        };
+
+        RegisterClassNoArgs(ListableClassTest);
+        RegisterClassNoArgs(ListableSubclassTest);
+
+        template <class T>
+        bool objectListContains(T* element, Context* context = Context::getRootContext())
+        {
+            for (typename ObjectList<T>::iterator it = static_cast<ObjectListElement<T>*>(context->getObjectList<T>()->begin());
+                    it != static_cast<ObjectListElement<T>*>(context->getObjectList<T>()->end()); ++it)
+                if (*it == element)
+                    return true;
+            return false;
+        }
+
+        // Fixture
+        class ListableTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(ListableTest, CanCreate)
+    {
+        ListableClassTest* test = new ListableClassTest();
+        ASSERT_TRUE(test != nullptr);
+        delete test;
+    }
+
+    TEST_F(ListableTest, AddsToObjectList)
+    {
+        ListableClassTest test;
+        EXPECT_EQ(1u, ObjectList<ListableClassTest>().size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test));
+    }
+
+    TEST_F(ListableTest, AddsToAllObjectLists)
+    {
+        ListableSubclassTest test;
+        EXPECT_EQ(1u, ObjectList<ListableClassTest>().size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test));
+        EXPECT_EQ(1u, ObjectList<ListableSubclassTest>().size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test));
+    }
+
+    TEST_F(ListableTest, RemovesFromObjectList)
+    {
+        EXPECT_EQ(0u, ObjectList<ListableClassTest>().size());
+        {
+            ListableClassTest test;
+            EXPECT_EQ(1u, ObjectList<ListableClassTest>().size());
+            EXPECT_TRUE(objectListContains<ListableClassTest>(&test));
+        }
+        EXPECT_EQ(0u, ObjectList<ListableClassTest>().size());
+    }
+
+    TEST_F(ListableTest, RemovesFromAllObjectLists)
+    {
+        EXPECT_EQ(0u, ObjectList<ListableClassTest>().size());
+        EXPECT_EQ(0u, ObjectList<ListableSubclassTest>().size());
+        {
+            ListableSubclassTest test;
+            EXPECT_EQ(1u, ObjectList<ListableClassTest>().size());
+            EXPECT_TRUE(objectListContains<ListableClassTest>(&test));
+            EXPECT_EQ(1u, ObjectList<ListableSubclassTest>().size());
+            EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test));
+        }
+        EXPECT_EQ(0u, ObjectList<ListableClassTest>().size());
+        EXPECT_EQ(0u, ObjectList<ListableSubclassTest>().size());
+    }
+
+    TEST_F(ListableTest, CanAddObjectToContext)
+    {
+        Context context(nullptr);
+        ListableSubclassTest test;
+
+        test.setContext(&context);
+
+        // object is in new context
+        EXPECT_EQ(1u, context.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &context));
+        EXPECT_EQ(1u, context.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &context));
+    }
+
+    TEST_F(ListableTest, CanAddObjectToSubContext)
+    {
+        Context baseContext(nullptr);
+        Context subContext(&baseContext);
+        ListableSubclassTest test;
+
+        test.setContext(&subContext);
+
+        // object is in both contexts
+        EXPECT_EQ(1u, baseContext.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &baseContext));
+        EXPECT_EQ(1u, baseContext.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &baseContext));
+
+        EXPECT_EQ(1u, subContext.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &subContext));
+        EXPECT_EQ(1u, subContext.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &subContext));
+    }
+
+    TEST_F(ListableTest, CanChangeContext)
+    {
+        Context* rootContext = Context::getRootContext();
+        Context newContext(nullptr);
+        ListableSubclassTest test;
+
+        // object is in root context
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, rootContext));
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, rootContext));
+
+        // object is NOT in new context
+        EXPECT_EQ(0u, newContext.getObjectList<ListableClassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableClassTest>(&test, &newContext));
+        EXPECT_EQ(0u, newContext.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableSubclassTest>(&test, &newContext));
+
+        test.setContext(&newContext);
+
+        // object was removed from root context
+        EXPECT_EQ(0u, rootContext->getObjectList<ListableClassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableClassTest>(&test, rootContext));
+        EXPECT_EQ(0u, rootContext->getObjectList<ListableSubclassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableSubclassTest>(&test, rootContext));
+
+        // object is now in new context
+        EXPECT_EQ(1u, newContext.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &newContext));
+        EXPECT_EQ(1u, newContext.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &newContext));
+    }
+
+    TEST_F(ListableTest, CanChangeToSubContext)
+    {
+        Context* rootContext = Context::getRootContext();
+        Context subContext(rootContext);
+        ListableSubclassTest test;
+
+        // object is in root context
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, rootContext));
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, rootContext));
+
+        // object is NOT in sub context
+        EXPECT_EQ(0u, subContext.getObjectList<ListableClassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableClassTest>(&test, &subContext));
+        EXPECT_EQ(0u, subContext.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableSubclassTest>(&test, &subContext));
+
+        test.setContext(&subContext);
+
+        // object is still in root context
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, rootContext));
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, rootContext));
+
+        // object is now also in sub context
+        EXPECT_EQ(1u, subContext.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &subContext));
+        EXPECT_EQ(1u, subContext.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &subContext));
+    }
+
+    TEST_F(ListableTest, CanChangeFromSubcontextToSubContext)
+    {
+        Context* rootContext = Context::getRootContext();
+        Context subContext1(rootContext);
+        Context subContext2(rootContext);
+        ListableSubclassTest test;
+
+        test.setContext(&subContext1);
+
+        // object is in root context
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, rootContext));
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, rootContext));
+
+        // object is also in sub context 1
+        EXPECT_EQ(1u, subContext1.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &subContext1));
+        EXPECT_EQ(1u, subContext1.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &subContext1));
+
+        // object is NOT in sub context 2
+        EXPECT_EQ(0u, subContext2.getObjectList<ListableClassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableClassTest>(&test, &subContext2));
+        EXPECT_EQ(0u, subContext2.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableSubclassTest>(&test, &subContext2));
+
+        test.setContext(&subContext2);
+
+        // object is still in root context
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, rootContext));
+        EXPECT_EQ(1u, rootContext->getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, rootContext));
+
+        // object was removed from sub context 1
+        EXPECT_EQ(0u, subContext1.getObjectList<ListableClassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableClassTest>(&test, &subContext1));
+        EXPECT_EQ(0u, subContext1.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_FALSE(objectListContains<ListableSubclassTest>(&test, &subContext1));
+
+        // object is now in sub context 2
+        EXPECT_EQ(1u, subContext2.getObjectList<ListableClassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableClassTest>(&test, &subContext2));
+        EXPECT_EQ(1u, subContext2.getObjectList<ListableSubclassTest>()->size());
+        EXPECT_TRUE(objectListContains<ListableSubclassTest>(&test, &subContext2));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/ObjectListBaseTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/ObjectListBaseTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/ObjectListBaseTest.cc	(revision 11817)
@@ -0,0 +1,84 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "core/object/ObjectListBase.h"
+#include "core/class/Identifier.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class ObjectListElementRemovalListenerMock : public ObjectListElementRemovalListener
+        {
+            public:
+                MOCK_METHOD1(removedElement, void(ObjectListBaseElement*));
+        };
+    }
+
+    TEST(ObjectListBaseTest, EmptyListHasSizeZero)
+    {
+        ObjectListBase list;
+        EXPECT_EQ(0u, list.size());
+    }
+
+    TEST(ObjectListBaseTest, CanAddElement)
+    {
+        ObjectListBase list;
+        ObjectListBaseElement* element = new ObjectListElement<Listable>(nullptr);
+        list.addElement(element);
+        EXPECT_EQ(1u, list.size());
+    }
+
+    TEST(ObjectListBaseTest, CanRemoveElement)
+    {
+        ObjectListBase list;
+        ObjectListBaseElement* element = new ObjectListElement<Listable>(nullptr);
+        list.addElement(element);
+        EXPECT_EQ(1u, list.size());
+        list.removeElement(element);
+        EXPECT_EQ(0u, list.size());
+        delete element;
+    }
+
+    TEST(ObjectListBaseTest, CanAddObject)
+    {
+        ObjectListBase list;
+        list.addElement(new ObjectListElement<Listable>(nullptr));
+        EXPECT_EQ(1u, list.size());
+    }
+
+    TEST(ObjectListBaseTest, HasCorrectSize)
+    {
+        ObjectListBase list;
+        EXPECT_EQ(0u, list.size());
+        {
+            ObjectListElement<Listable> element1(nullptr);
+            list.addElement(&element1);
+            EXPECT_EQ(1u, list.size());
+            {
+                ObjectListElement<Listable> element1(nullptr);
+                list.addElement(&element1);
+                EXPECT_EQ(2u, list.size());
+                {
+                    ObjectListElement<Listable> element1(nullptr);
+                    list.addElement(&element1);
+                    EXPECT_EQ(3u, list.size());
+                }
+                EXPECT_EQ(2u, list.size());
+            }
+            EXPECT_EQ(1u, list.size());
+        }
+        EXPECT_EQ(0u, list.size());
+    }
+
+    TEST(ObjectListBaseTest, CallsListenerOnRemoval)
+    {
+        ObjectListBase list;
+        ObjectListElementRemovalListenerMock listener;
+        list.registerRemovalListener(&listener);
+        ObjectListBaseElement* element = new ObjectListElement<Listable>(nullptr);
+        list.addElement(element);
+        EXPECT_CALL(listener, removedElement(element));
+        list.removeElement(element);
+        delete element;
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/ObjectListIteratorTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/ObjectListIteratorTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/ObjectListIteratorTest.cc	(revision 11817)
@@ -0,0 +1,123 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "core/object/ObjectListIterator.h"
+#include "core/class/OrxonoxClass.h"
+#include "core/class/OrxonoxInterface.h"
+#include "core/CoreIncludes.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestInterface : virtual public OrxonoxInterface
+        {
+            public:
+                TestInterface() { RegisterObject(TestInterface); }
+        };
+
+        class TestClass : public OrxonoxClass, public TestInterface
+        {
+            public:
+                TestClass() { RegisterObject(TestClass); }
+                MOCK_METHOD0(test, void());
+        };
+
+        RegisterClassNoArgs(TestInterface);
+        RegisterClassNoArgs(TestClass);
+
+        // Fixture
+        class ObjectListIteratorTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(ObjectListIteratorTest, CanCreateIterator)
+    {
+        ObjectListIterator<TestClass> it;
+    }
+
+    TEST_F(ObjectListIteratorTest, CanAssignIterator)
+    {
+        ObjectList<TestClass> list;
+        ObjectListIterator<TestClass> it = list.begin();
+    }
+
+    TEST_F(ObjectListIteratorTest, CanIterateOverEmptyList)
+    {
+        size_t i = 0;
+        ObjectList<TestClass> list;
+        for (ObjectListIterator<TestClass> it = list.begin(); it != list.end(); ++it)
+            ++i;
+        EXPECT_EQ(0u, i);
+    }
+
+    TEST_F(ObjectListIteratorTest, CanIterateOverFullList)
+    {
+        TestClass test1;
+        TestClass test2;
+        TestClass test3;
+        TestInterface interface;
+
+        size_t i = 0;
+        ObjectList<TestClass> list;
+        for (ObjectListIterator<TestClass> it = list.begin(); it != list.end(); ++it)
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&test1, *it);
+            if (i == 2u) EXPECT_EQ(&test2, *it);
+            if (i == 3u) EXPECT_EQ(&test3, *it);
+        }
+        EXPECT_EQ(3u, i);
+    }
+
+    TEST_F(ObjectListIteratorTest, CanIterateReverseOverFullList)
+    {
+        TestClass test1;
+        TestClass test2;
+        TestClass test3;
+        TestInterface interface;
+
+        size_t i = 0;
+        ObjectList<TestClass> list;
+        for (ObjectListIterator<TestClass> it = list.rbegin(); it != list.rend(); --it)
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&test3, *it);
+            if (i == 2u) EXPECT_EQ(&test2, *it);
+            if (i == 3u) EXPECT_EQ(&test1, *it);
+        }
+        EXPECT_EQ(3u, i);
+    }
+
+    TEST_F(ObjectListIteratorTest, CanCallObjects)
+    {
+        TestClass test1;
+        TestClass test2;
+        TestClass test3;
+        TestInterface interface;
+
+        EXPECT_CALL(test1, test());
+        EXPECT_CALL(test2, test());
+        EXPECT_CALL(test3, test());
+
+        ObjectList<TestClass> list;
+        for (ObjectListIterator<TestClass> it = list.begin(); it != list.end(); ++it)
+            it->test();
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/ObjectListTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/ObjectListTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/ObjectListTest.cc	(revision 11817)
@@ -0,0 +1,150 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include "core/object/ObjectListIterator.h"
+#include "core/object/Listable.h"
+#include "core/CoreIncludes.h"
+#include "core/module/ModuleInstance.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class ListableTest : public Listable
+        {
+            public:
+                ListableTest() { RegisterObject(ListableTest); }
+                ListableTest(Context* context) : Listable(context) { RegisterObject(ListableTest); }
+                MOCK_METHOD0(test, void());
+        };
+
+        RegisterClassNoArgs(ListableTest);
+
+        // Fixture
+        class ObjectListTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+    
+    TEST_F(ObjectListTest, CanIterateOverEmptyList)
+    {
+        size_t i = 0;
+        for (ListableTest* object : ObjectList<ListableTest>())
+        {
+            ++i;
+            ((void*)object); // avoid warning about unused variable
+        }
+        EXPECT_EQ(0u, i);
+    }
+
+    TEST_F(ObjectListTest, CanIterateOverFullList)
+    {
+        ListableTest test1;
+        ListableTest test2;
+        ListableTest test3;
+
+        size_t i = 0;
+        for (ListableTest* object : ObjectList<ListableTest>())
+        {
+            ++i;
+            if (i == 1u) EXPECT_EQ(&test1, object);
+            if (i == 2u) EXPECT_EQ(&test2, object);
+            if (i == 3u) EXPECT_EQ(&test3, object);
+        }
+        EXPECT_EQ(3u, i);
+    }
+    
+    TEST_F(ObjectListTest, CanIterateOverFullList_Expanded)
+    {
+        ListableTest test1;
+        ListableTest test2;
+        ListableTest test3;
+
+        size_t i = 0;
+        ObjectList<ListableTest>&& __range = ObjectList<ListableTest>();
+        ObjectListIterator<ListableTest> __begin = __range.begin();
+        ObjectListIterator<ListableTest>__end = __range.end();
+        for (; __begin != __end; ++__begin)
+        {
+            ListableTest* object = *__begin;
+
+            ++i;
+            if (i == 1u) EXPECT_EQ(&test1, object);
+            if (i == 2u) EXPECT_EQ(&test2, object);
+            if (i == 3u) EXPECT_EQ(&test3, object);
+        }
+        EXPECT_EQ(3u, i);
+    }
+    
+    TEST_F(ObjectListTest, CanCallObjects)
+    {
+        ListableTest test1;
+        ListableTest test2;
+        ListableTest test3;
+
+        EXPECT_CALL(test1, test());
+        EXPECT_CALL(test2, test());
+        EXPECT_CALL(test3, test());
+
+        for (ListableTest* object : ObjectList<ListableTest>())
+            object->test();
+    }
+
+    TEST_F(ObjectListTest, UsesCorrectContext)
+    {
+        Context context1(Context::getRootContext());
+        Context context2(Context::getRootContext());
+
+        ListableTest test1(&context1);
+        ListableTest test2(&context1);
+        ListableTest test3(&context2);
+
+        EXPECT_EQ(3u, ObjectList<ListableTest>().size());
+        EXPECT_EQ(2u, ObjectList<ListableTest>(&context1).size());
+        EXPECT_EQ(1u, ObjectList<ListableTest>(&context2).size());
+    }
+
+    TEST_F(ObjectListTest, CanIterateOverCorrectContext)
+    {
+        Context context1(Context::getRootContext());
+        Context context2(Context::getRootContext());
+
+        ListableTest test1(&context1);
+        ListableTest test2(&context1);
+        ListableTest test3(&context2);
+
+        {
+            size_t i = 0;
+            for (ListableTest* object : ObjectList<ListableTest>(&context1))
+            {
+                ++i;
+                if (i == 1u) EXPECT_EQ(&test1, object);
+                if (i == 2u) EXPECT_EQ(&test2, object);
+            }
+            EXPECT_EQ(2u, i);
+        }
+        {
+            size_t i = 0;
+            for (ListableTest* object : ObjectList<ListableTest>(&context2))
+            {
+                ++i;
+                if (i == 1u) EXPECT_EQ(&test3, object);
+            }
+            EXPECT_EQ(1u, i);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/StrongPtrTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/StrongPtrTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/StrongPtrTest.cc	(revision 11817)
@@ -0,0 +1,308 @@
+#include <utility>
+#include <gtest/gtest.h>
+#include "core/object/StrongPtr.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class DestroyableTest : public Destroyable
+        {
+            public:
+                DestroyableTest(bool& destroyed) : destroyed_(destroyed) { destroyed_ = false; }
+                virtual ~DestroyableTest() { destroyed_ = true; }
+
+            private:
+                bool& destroyed_;
+        };
+    }
+
+    TEST(StrongPtrTest, CanReferenceObject)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        StrongPtr<DestroyableTest> strongPtr = test;
+        EXPECT_EQ(test, strongPtr.get());
+        EXPECT_EQ(test, &(*strongPtr));
+        EXPECT_EQ(static_cast<Destroyable*>(test), strongPtr.getBase());
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, CanHaveMultiplePointers)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        StrongPtr<DestroyableTest> strongPtr1 = test;
+        StrongPtr<DestroyableTest> strongPtr2 = test;
+        StrongPtr<DestroyableTest> strongPtr3 = test;
+        EXPECT_EQ(test, strongPtr1.get());
+        EXPECT_EQ(test, strongPtr2.get());
+        EXPECT_EQ(test, strongPtr3.get());
+        EXPECT_EQ(3u, test->getReferenceCount());
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, IncreasesReferenceCount)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        EXPECT_EQ(0u, test->getReferenceCount());
+        {
+            StrongPtr<DestroyableTest> strongPtr = test;
+            EXPECT_EQ(1u, test->getReferenceCount());
+        }
+        EXPECT_EQ(0u, test->getReferenceCount());
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, DestroyDeletesInstance)
+    {
+        bool destroyed = false;
+        DestroyableTest* test = new DestroyableTest(destroyed);
+        EXPECT_FALSE(destroyed);
+        test->destroy();
+        EXPECT_TRUE(destroyed);
+    }
+
+    TEST(StrongPtrTest, PreventsDestruction)
+    {
+        bool destroyed = false;
+        DestroyableTest* test = new DestroyableTest(destroyed);
+        EXPECT_FALSE(destroyed);
+        StrongPtr<DestroyableTest> strongPtr = test;
+        test->destroy();
+        EXPECT_FALSE(destroyed);
+    }
+
+    TEST(StrongPtrTest, DestroysIfStrongPtrRemoved)
+    {
+        bool destroyed = false;
+        DestroyableTest* test = new DestroyableTest(destroyed);
+        EXPECT_FALSE(destroyed);
+        {
+            StrongPtr<DestroyableTest> strongPtr = test;
+            test->destroy();
+            EXPECT_FALSE(destroyed);
+        }
+        EXPECT_TRUE(destroyed);
+    }
+
+    TEST(StrongPtrTest, DestroysIfAllStrongPtrsRemoved)
+    {
+        bool destroyed = false;
+        DestroyableTest* test = new DestroyableTest(destroyed);
+        EXPECT_FALSE(destroyed);
+        {
+            StrongPtr<DestroyableTest> strongPtr1 = test;
+            {
+                StrongPtr<DestroyableTest> strongPtr2 = test;
+                {
+                    StrongPtr<DestroyableTest> strongPtr3 = test;
+                    test->destroy();
+                    EXPECT_FALSE(destroyed);
+                }
+                EXPECT_FALSE(destroyed);
+            }
+            EXPECT_FALSE(destroyed);
+        }
+        EXPECT_TRUE(destroyed);
+    }
+
+    void isNull(const StrongPtr<DestroyableTest> strongPtr)
+    {
+        EXPECT_TRUE(strongPtr == nullptr);
+        EXPECT_TRUE(strongPtr == nullptr);
+        EXPECT_TRUE(!strongPtr);
+        EXPECT_FALSE(strongPtr != nullptr);
+        EXPECT_FALSE(strongPtr != nullptr);
+        EXPECT_FALSE(strongPtr);
+    }
+
+    TEST(StrongPtrTest, IsNull)
+    {
+        {
+            StrongPtr<DestroyableTest> strongPtr;
+            isNull(strongPtr);
+        }
+        {
+            StrongPtr<DestroyableTest> strongPtr = nullptr;
+            isNull(strongPtr);
+        }
+        {
+            StrongPtr<DestroyableTest> strongPtr;
+            strongPtr = nullptr;
+            isNull(strongPtr);
+        }
+        {
+            StrongPtr<DestroyableTest> strongPtr = nullptr;
+            isNull(strongPtr);
+        }
+        {
+            StrongPtr<DestroyableTest> strongPtr;
+            strongPtr = nullptr;
+            isNull(strongPtr);
+        }
+    }
+
+    TEST(StrongPtrTest, IsNotNull)
+    {
+        bool destroyed = false;
+        DestroyableTest* test = new DestroyableTest(destroyed);
+        StrongPtr<DestroyableTest> strongPtr = test;
+        EXPECT_FALSE(strongPtr == nullptr);
+        EXPECT_FALSE(strongPtr == nullptr);
+        EXPECT_FALSE(!strongPtr);
+        EXPECT_TRUE(strongPtr != nullptr);
+        EXPECT_TRUE(strongPtr != nullptr);
+        EXPECT_TRUE(strongPtr);
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, TestConstructors)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+
+        // default
+        StrongPtr<DestroyableTest> strongPtr1;
+        EXPECT_EQ(nullptr, strongPtr1.get());
+
+        // pointer
+        StrongPtr<DestroyableTest> strongPtr2a = test;
+        StrongPtr<DestroyableTest> strongPtr2b(test);
+        EXPECT_EQ(test, strongPtr2a.get());
+        EXPECT_EQ(test, strongPtr2b.get());
+
+        // copy
+        StrongPtr<DestroyableTest> strongPtr3a = strongPtr2a;
+        StrongPtr<DestroyableTest> strongPtr3b(strongPtr2b);
+        EXPECT_EQ(test, strongPtr3a.get());
+        EXPECT_EQ(test, strongPtr3b.get());
+
+        // move
+        StrongPtr<DestroyableTest> strongPtr4a = std::move(strongPtr3a);
+        StrongPtr<DestroyableTest> strongPtr4b(std::move(strongPtr3b));
+        EXPECT_EQ(test, strongPtr4a.get());
+        EXPECT_EQ(test, strongPtr4b.get());
+
+        // other
+        StrongPtr<Destroyable> strongPtr5a = strongPtr4a;
+        StrongPtr<Destroyable> strongPtr5b(strongPtr4b);
+        EXPECT_EQ(test, strongPtr5a.get());
+        EXPECT_EQ(test, strongPtr5b.get());
+
+        // weakPtr
+        WeakPtr<DestroyableTest> weakPtr = test;
+        StrongPtr<DestroyableTest> strongPtr6a = weakPtr;
+        StrongPtr<DestroyableTest> strongPtr6b(weakPtr);
+        EXPECT_EQ(test, strongPtr6a.get());
+        EXPECT_EQ(test, strongPtr6b.get());
+
+        // weakPtr other
+        StrongPtr<Destroyable> strongPtr7a = weakPtr;
+        StrongPtr<Destroyable> strongPtr7b(weakPtr);
+        EXPECT_EQ(test, strongPtr7a.get());
+        EXPECT_EQ(test, strongPtr7b.get());
+
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, TestAssignments)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+
+        // pointer
+        StrongPtr<DestroyableTest> strongPtr1;
+        strongPtr1 = test;
+        EXPECT_EQ(test, strongPtr1.get());
+
+        // copy
+        StrongPtr<DestroyableTest> strongPtr2;
+        strongPtr2 = strongPtr1;
+        EXPECT_EQ(test, strongPtr2.get());
+
+        // move
+        StrongPtr<DestroyableTest> strongPtr3;
+        strongPtr3 = std::move(strongPtr2);
+        EXPECT_EQ(test, strongPtr3.get());
+
+        // other
+        StrongPtr<Destroyable> strongPtr4;
+        strongPtr4 = strongPtr3;
+        EXPECT_EQ(test, strongPtr4.get());
+
+        // weakPtr
+        WeakPtr<DestroyableTest> weakPtr = test;
+        StrongPtr<DestroyableTest> strongPtr5;
+        strongPtr5 = weakPtr;
+        EXPECT_EQ(test, strongPtr5.get());
+
+        // weakPtr other
+        StrongPtr<Destroyable> strongPtr6;
+        strongPtr6 = weakPtr;
+        EXPECT_EQ(test, strongPtr6.get());
+
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, TestStrongPtrInVector)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+
+        std::vector<StrongPtr<DestroyableTest>> vector;
+        vector.push_back(test);
+        vector.push_back(test);
+        vector.push_back(test);
+
+        ASSERT_EQ(3u, vector.size());
+        EXPECT_EQ(test, vector[0].get());
+        EXPECT_EQ(test, vector[1].get());
+        EXPECT_EQ(test, vector[2].get());
+        EXPECT_EQ(3u, test->getReferenceCount());
+
+        vector.clear();
+        EXPECT_EQ(0u, test->getReferenceCount());
+
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, TestReset)
+    {
+        bool bla;
+        DestroyableTest* test = new DestroyableTest(bla);
+        StrongPtr<DestroyableTest> strongPtr(test);
+        EXPECT_EQ(test, strongPtr.get());
+        EXPECT_EQ(1u, test->getReferenceCount());
+        strongPtr.reset();
+        EXPECT_EQ(nullptr, strongPtr.get());
+        EXPECT_EQ(0u, test->getReferenceCount());
+
+        test->destroy();
+    }
+
+    TEST(StrongPtrTest, TestSwap)
+    {
+        bool bla;
+        DestroyableTest* test1 = new DestroyableTest(bla);
+        DestroyableTest* test2 = new DestroyableTest(bla);
+
+        StrongPtr<DestroyableTest> strongPtr1(test1);
+        StrongPtr<DestroyableTest> strongPtr2(test2);
+        EXPECT_EQ(test1, strongPtr1.get());
+        EXPECT_EQ(test2, strongPtr2.get());
+        EXPECT_EQ(1u, test1->getReferenceCount());
+        EXPECT_EQ(1u, test2->getReferenceCount());
+
+        strongPtr1.swap(strongPtr2);
+
+        EXPECT_EQ(test2, strongPtr1.get());
+        EXPECT_EQ(test1, strongPtr2.get());
+        EXPECT_EQ(1u, test1->getReferenceCount());
+        EXPECT_EQ(1u, test2->getReferenceCount());
+
+        test1->destroy();
+        test2->destroy();
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/object/WeakPtrTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/object/WeakPtrTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/object/WeakPtrTest.cc	(revision 11817)
@@ -0,0 +1,227 @@
+#include <utility>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "core/object/WeakPtr.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class DestroyableTest : public Destroyable
+        {
+        };
+
+        class Callback
+        {
+            public:
+                virtual ~Callback() {}
+                MOCK_METHOD0(callback, void());
+        };
+    }
+
+    TEST(WeakPtrTest, CanReferenceObject)
+    {
+        DestroyableTest* test = new DestroyableTest();
+        WeakPtr<DestroyableTest> weakPtr = test;
+        EXPECT_EQ(test, weakPtr.get());
+        EXPECT_EQ(test, &(*weakPtr));
+        EXPECT_EQ(static_cast<Destroyable*>(test), weakPtr.getBase());
+        test->destroy();
+    }
+
+    TEST(WeakPtrTest, DestroyRemovesReference)
+    {
+        DestroyableTest* test = new DestroyableTest();
+        WeakPtr<DestroyableTest> weakPtr = test;
+        EXPECT_EQ(test, weakPtr.get());
+        test->destroy();
+        EXPECT_EQ(nullptr, weakPtr.get());
+    }
+
+    TEST(WeakPtrTest, CanHaveMultiplePointers)
+    {
+        DestroyableTest* test = new DestroyableTest();
+        WeakPtr<DestroyableTest> weakPtr1 = test;
+        WeakPtr<DestroyableTest> weakPtr2 = test;
+        WeakPtr<DestroyableTest> weakPtr3 = test;
+        EXPECT_EQ(test, weakPtr1.get());
+        EXPECT_EQ(test, weakPtr2.get());
+        EXPECT_EQ(test, weakPtr3.get());
+        test->destroy();
+        EXPECT_EQ(nullptr, weakPtr1.get());
+        EXPECT_EQ(nullptr, weakPtr2.get());
+        EXPECT_EQ(nullptr, weakPtr3.get());
+    }
+
+    TEST(WeakPtrTest, DestroyCallsCallback)
+    {
+        DestroyableTest* test = new DestroyableTest();
+        WeakPtr<DestroyableTest> weakPtr = test;
+        Callback callback;
+        weakPtr.setCallback(createFunctor(&Callback::callback, &callback));
+        EXPECT_CALL(callback, callback());
+        test->destroy();
+    }
+
+    void isNull(const WeakPtr<DestroyableTest> weakPtr)
+    {
+        EXPECT_TRUE(weakPtr == nullptr);
+        EXPECT_TRUE(weakPtr == nullptr);
+        EXPECT_TRUE(!weakPtr);
+        EXPECT_FALSE(weakPtr != nullptr);
+        EXPECT_FALSE(weakPtr != nullptr);
+        EXPECT_FALSE(weakPtr);
+    }
+
+    TEST(WeakPtrTest, IsNull)
+    {
+        {
+            WeakPtr<DestroyableTest> weakPtr;
+            isNull(weakPtr);
+        }
+        {
+            WeakPtr<DestroyableTest> weakPtr = nullptr;
+            isNull(weakPtr);
+        }
+        {
+            WeakPtr<DestroyableTest> weakPtr;
+            weakPtr = nullptr;
+            isNull(weakPtr);
+        }
+        {
+            WeakPtr<DestroyableTest> weakPtr = nullptr;
+            isNull(weakPtr);
+        }
+        {
+            WeakPtr<DestroyableTest> weakPtr;
+            weakPtr = nullptr;
+            isNull(weakPtr);
+        }
+    }
+
+    TEST(WeakPtrTest, IsNotNull)
+    {
+        DestroyableTest* test = new DestroyableTest();
+        WeakPtr<DestroyableTest> weakPtr = test;
+        EXPECT_FALSE(weakPtr == nullptr);
+        EXPECT_FALSE(weakPtr == nullptr);
+        EXPECT_FALSE(!weakPtr);
+        EXPECT_TRUE(weakPtr != nullptr);
+        EXPECT_TRUE(weakPtr != nullptr);
+        EXPECT_TRUE(weakPtr);
+        test->destroy();
+    }
+
+    TEST(WeakPtrTest, TestConstructors)
+    {
+        DestroyableTest* test = new DestroyableTest();
+
+        // default
+        WeakPtr<DestroyableTest> weakPtr1;
+        EXPECT_EQ(nullptr, weakPtr1.get());
+
+        // pointer
+        WeakPtr<DestroyableTest> weakPtr2a = test;
+        WeakPtr<DestroyableTest> weakPtr2b(test);
+        EXPECT_EQ(test, weakPtr2a.get());
+        EXPECT_EQ(test, weakPtr2b.get());
+
+        // copy
+        WeakPtr<DestroyableTest> weakPtr3a = weakPtr2a;
+        WeakPtr<DestroyableTest> weakPtr3b(weakPtr2b);
+        EXPECT_EQ(test, weakPtr3a.get());
+        EXPECT_EQ(test, weakPtr3b.get());
+
+        // move
+        WeakPtr<DestroyableTest> weakPtr4a = std::move(weakPtr3a);
+        WeakPtr<DestroyableTest> weakPtr4b(std::move(weakPtr3b));
+        EXPECT_EQ(test, weakPtr4a.get());
+        EXPECT_EQ(test, weakPtr4b.get());
+
+        // other
+        WeakPtr<Destroyable> weakPtr5a = weakPtr4a;
+        WeakPtr<Destroyable> weakPtr5b(weakPtr4b);
+        EXPECT_EQ(test, weakPtr5a.get());
+        EXPECT_EQ(test, weakPtr5b.get());
+
+        test->destroy();
+    }
+
+    TEST(WeakPtrTest, TestAssignments)
+    {
+        DestroyableTest* test = new DestroyableTest();
+
+        // pointer
+        WeakPtr<DestroyableTest> weakPtr1;
+        weakPtr1 = test;
+        EXPECT_EQ(test, weakPtr1.get());
+
+        // copy
+        WeakPtr<DestroyableTest> weakPtr2;
+        weakPtr2 = weakPtr1;
+        EXPECT_EQ(test, weakPtr2.get());
+
+        // move
+        WeakPtr<DestroyableTest> weakPtr3;
+        weakPtr3 = std::move(weakPtr2);
+        EXPECT_EQ(test, weakPtr3.get());
+
+        // other
+        WeakPtr<Destroyable> weakPtr4;
+        weakPtr4 = weakPtr3;
+        EXPECT_EQ(test, weakPtr4.get());
+
+        test->destroy();
+    }
+
+    TEST(WeakPtrTest, TestWeakPtrInVector)
+    {
+        DestroyableTest* test = new DestroyableTest();
+
+        std::vector<WeakPtr<DestroyableTest>> vector;
+        vector.push_back(test);
+        vector.push_back(test);
+        vector.push_back(test);
+
+        ASSERT_EQ(3u, vector.size());
+        EXPECT_EQ(test, vector[0].get());
+        EXPECT_EQ(test, vector[1].get());
+        EXPECT_EQ(test, vector[2].get());
+
+        test->destroy();
+
+        EXPECT_EQ(nullptr, vector[0].get());
+        EXPECT_EQ(nullptr, vector[1].get());
+        EXPECT_EQ(nullptr, vector[2].get());
+    }
+
+    TEST(WeakPtrTest, TestReset)
+    {
+        DestroyableTest* test = new DestroyableTest();
+        WeakPtr<DestroyableTest> weakPtr(test);
+        EXPECT_EQ(test, weakPtr.get());
+        weakPtr.reset();
+        EXPECT_EQ(nullptr, weakPtr.get());
+
+        test->destroy();
+    }
+
+    TEST(WeakPtrTest, TestSwap)
+    {
+        DestroyableTest* test1 = new DestroyableTest();
+        DestroyableTest* test2 = new DestroyableTest();
+
+        WeakPtr<DestroyableTest> weakPtr1(test1);
+        WeakPtr<DestroyableTest> weakPtr2(test2);
+        EXPECT_EQ(test1, weakPtr1.get());
+        EXPECT_EQ(test2, weakPtr2.get());
+
+        weakPtr1.swap(weakPtr2);
+
+        EXPECT_EQ(test2, weakPtr1.get());
+        EXPECT_EQ(test1, weakPtr2.get());
+
+        test1->destroy();
+        test2->destroy();
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core/singleton/ScopeTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core/singleton/ScopeTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core/singleton/ScopeTest.cc	(revision 11817)
@@ -0,0 +1,109 @@
+#include <gtest/gtest.h>
+#include "core/singleton/ScopedSingletonIncludes.h"
+#include "core/module/ModuleInstance.h"
+#include "core/CoreIncludes.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestSingletonRoot : public Singleton<TestSingletonRoot>
+        {
+            friend class Singleton<TestSingletonRoot>;
+            static TestSingletonRoot* singletonPtr_s;
+        };
+        class TestSingletonGraphics : public Singleton<TestSingletonGraphics>
+        {
+            friend class Singleton<TestSingletonGraphics>;
+            static TestSingletonGraphics* singletonPtr_s;
+        };
+
+        ManageScopedSingleton(TestSingletonRoot, ScopeID::ROOT, false);
+        ManageScopedSingleton(TestSingletonGraphics, ScopeID::GRAPHICS, false);
+
+        // Fixture
+        class ScopeTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    new IdentifierManager();
+                    new ScopeManager();
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    ModuleInstance::getCurrentModuleInstance()->loadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
+                    Context::setRootContext(new Context(nullptr));
+                }
+
+                virtual void TearDown() override
+                {
+                    Context::destroyRootContext();
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::SCOPED_SINGLETON_WRAPPER);
+                    ModuleInstance::getCurrentModuleInstance()->unloadAllStaticallyInitializedInstances(StaticInitialization::IDENTIFIER);
+                    delete &ScopeManager::getInstance();
+                    delete &IdentifierManager::getInstance();
+                }
+        };
+    }
+
+    TEST_F(ScopeTest, ScopesDoNotExist)
+    {
+        EXPECT_FALSE(Scope<ScopeID::ROOT>::isActive());
+        EXPECT_FALSE(Scope<ScopeID::GRAPHICS>::isActive());
+    }
+
+    TEST_F(ScopeTest, SingletonsDoNotExist)
+    {
+        EXPECT_FALSE(TestSingletonRoot::exists());
+        EXPECT_FALSE(TestSingletonGraphics::exists());
+    }
+
+    TEST_F(ScopeTest, RootScope)
+    {
+        EXPECT_FALSE(Scope<ScopeID::ROOT>::isActive());
+        {   // create root scope
+            Scope<ScopeID::ROOT> scope;
+            EXPECT_TRUE(Scope<ScopeID::ROOT>::isActive());
+        }   // destroy root scope
+        EXPECT_FALSE(Scope<ScopeID::ROOT>::isActive());
+    }
+
+    TEST_F(ScopeTest, DISABLED_RootAndGraphicsScope)
+    {
+        EXPECT_FALSE(Scope<ScopeID::GRAPHICS>::isActive());
+        {   // create root scope
+            Scope<ScopeID::ROOT> scope;
+            EXPECT_FALSE(Scope<ScopeID::GRAPHICS>::isActive());
+            {   // create graphics scope
+                Scope<ScopeID::GRAPHICS> scope;
+                EXPECT_TRUE(Scope<ScopeID::GRAPHICS>::isActive());
+            }   // destroy graphics scope
+            EXPECT_FALSE(Scope<ScopeID::GRAPHICS>::isActive());
+        }   // destroy root scope
+        EXPECT_FALSE(Scope<ScopeID::GRAPHICS>::isActive());
+    }
+
+    TEST_F(ScopeTest, RootSingleton)
+    {
+        EXPECT_FALSE(TestSingletonRoot::exists());
+        {   // create root scope
+            Scope<ScopeID::ROOT> scope;
+            EXPECT_TRUE(TestSingletonRoot::exists());
+        }   // destroy root scope
+        EXPECT_FALSE(TestSingletonRoot::exists());
+    }
+
+    TEST_F(ScopeTest, DISABLED_RootAndGraphicsSingleton)
+    {
+        EXPECT_FALSE(TestSingletonGraphics::exists());
+        {   // create root scope
+            Scope<ScopeID::ROOT> scope;
+            EXPECT_FALSE(TestSingletonGraphics::exists());
+            {   // create graphics scope
+                Scope<ScopeID::GRAPHICS> scope;
+                EXPECT_TRUE(TestSingletonGraphics::exists());
+            }   // destroy graphics scope
+            EXPECT_FALSE(TestSingletonGraphics::exists());
+        }   // destroy root scope
+        EXPECT_FALSE(TestSingletonGraphics::exists());
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core_plugin/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,33 @@
+# Test-executable that loads and unloads the plugin at runtime an tests if it correctly (un-)registers static instances
+ORXONOX_ADD_EXECUTABLE(
+    core_plugin_test
+    EXCLUDE_FROM_ALL
+    NO_INSTALL
+  LINK_LIBRARIES
+    core
+    gmock_orxonox
+  SOURCE_FILES
+    ${GMOCK_MAIN}
+    PluginTest.cc
+)
+
+# A plugin that statically registers some instances
+ORXONOX_ADD_LIBRARY(
+  testplugin
+    PLUGIN
+    EXCLUDE_FROM_ALL
+    NO_INSTALL
+  LINK_LIBRARIES
+    core
+  SOURCE_FILES
+    Testclass.cc
+    Testcommandlineargument.cc
+    Testconsolecommand.cc
+    Testsingleton.cc
+)
+
+# let the test-executable depend on the plugin to ensure that the plugin always gets built before the test runs
+ADD_DEPENDENCIES(core_plugin_test testplugin)
+
+ADD_DEPENDENCIES(all_tests core_plugin_test)
+ADD_TEST(core_plugin_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/core_plugin_test --gtest_output=xml)
Index: /code/branches/RacingBots_FS18/test/core_plugin/PluginTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/PluginTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/PluginTest.cc	(revision 11817)
@@ -0,0 +1,293 @@
+#include <gtest/gtest.h>
+#include <vector>
+
+#include "util/Exception.h"
+#include "core/Core.h"
+#include "core/CoreIncludes.h"
+#include "core/module/PluginReference.h"
+#include "core/commandline/CommandLineParser.h"
+#include "core/command/ConsoleCommand.h"
+#include "core/command/ConsoleCommandManager.h"
+
+#include "Testclass.h"
+#include "Testsingleton.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        // Fixture
+        class PluginTest : public ::testing::Test
+        {
+            public:
+                PluginTest()
+                {
+                    this->plugin_ = nullptr;
+                }
+
+                static void SetUpTestCase()
+                {
+                    new Core("--noIOConsole");
+                }
+
+                static void TearDownTestCase()
+                {
+                    delete &Core::getInstance();
+                }
+
+                void loadPlugin()
+                {
+                    this->plugin_ = new PluginReference("testplugin");
+                }
+
+                void unloadPlugin()
+                {
+                    delete this->plugin_;
+                    this->plugin_ = nullptr;
+                }
+
+                virtual void TearDown() override
+                {
+                    // make sure the plugin is unloaded
+                    this->unloadPlugin();
+                }
+
+            private:
+                PluginReference* plugin_;
+        };
+    }
+
+
+    TEST_F(PluginTest, CanLoadPlugin)
+    {
+        this->loadPlugin();
+        this->unloadPlugin();
+    }
+
+
+    ///////////////////////////////////////////
+    /////////////// Identifier ////////////////
+    ///////////////////////////////////////////
+
+    Identifier* getIdentifier()
+    {
+        return ClassByString("Testclass");
+    }
+
+    TEST_F(PluginTest, LoadsIdentifier)
+    {
+        EXPECT_TRUE(getIdentifier() == nullptr);
+        this->loadPlugin();
+        EXPECT_TRUE(getIdentifier() != nullptr);
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, UnloadsIdentifier)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(getIdentifier() != nullptr);
+        this->unloadPlugin();
+        EXPECT_TRUE(getIdentifier() == nullptr);
+    }
+
+    TEST_F(PluginTest, ReloadsIdentifier)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(getIdentifier() != nullptr);
+        this->unloadPlugin();
+        EXPECT_TRUE(getIdentifier() == nullptr);
+        this->loadPlugin();
+        EXPECT_TRUE(getIdentifier() != nullptr);
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, CanCreateObjectFromIdentifier)
+    {
+        this->loadPlugin();
+
+        Identifier* identifier = getIdentifier();
+        ASSERT_TRUE(identifier != nullptr);
+
+        Identifiable* object = identifier->fabricate(nullptr);
+        ASSERT_TRUE(object != nullptr);
+
+        Testclass* testclass = orxonox_cast<Testclass*>(object);
+        ASSERT_TRUE(testclass != nullptr);
+
+        EXPECT_EQ(666, testclass->getValue());
+
+        this->unloadPlugin();
+    }
+
+
+    ///////////////////////////////////////////
+    //////////////// Singleton ////////////////
+    ///////////////////////////////////////////
+
+    // Cannot directly use Testsingleton::getInstance() because we don't link the test to the plugin.
+    // Also cannot directly use ObjectList<Testsingleton> because the Identifier is not known before the plugin is loaded.
+    Testsingleton* getSingleton()
+    {
+        std::vector<Testsingleton*> singletons;
+
+        for (Listable* listable : ObjectList<Listable>())
+        {
+            Testsingleton* singleton = dynamic_cast<Testsingleton*>(listable);
+            if (singleton)
+                singletons.push_back(singleton);
+        }
+
+        switch (singletons.size())
+        {
+            case 0:
+                return nullptr;
+            case 1:
+                return singletons[0];
+            default:
+                throw std::exception(); // unexpected number of singletons found
+        }
+    }
+
+    TEST_F(PluginTest, LoadsSingleton)
+    {
+        EXPECT_TRUE(getSingleton() == nullptr);
+        this->loadPlugin();
+        EXPECT_TRUE(getSingleton() != nullptr);
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, UnloadsSingleton)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(getSingleton() != nullptr);
+        this->unloadPlugin();
+        EXPECT_TRUE(getSingleton() == nullptr);
+    }
+
+    TEST_F(PluginTest, ReloadsSingleton)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(getSingleton() != nullptr);
+        this->unloadPlugin();
+        EXPECT_TRUE(getSingleton() == nullptr);
+        this->loadPlugin();
+        EXPECT_TRUE(getSingleton() != nullptr);
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, CanCallFunctionOnSingleton)
+    {
+        this->loadPlugin();
+
+        Testsingleton* singleton = getSingleton();
+        ASSERT_TRUE(singleton != nullptr);
+
+        EXPECT_EQ(999, singleton->getValue());
+
+        this->unloadPlugin();
+    }
+
+
+    ///////////////////////////////////////////
+    ////////// Command Line Argument //////////
+    ///////////////////////////////////////////
+
+    bool hasCommandLineArgument()
+    {
+        try
+        {
+            CommandLineParser::getValue("testvalue");
+            return true;
+        }
+        catch (const ArgumentException&)
+        {
+            return false;
+        }
+    }
+
+    TEST_F(PluginTest, LoadsCommandLineArgument)
+    {
+        EXPECT_FALSE(hasCommandLineArgument());
+        this->loadPlugin();
+        EXPECT_TRUE(hasCommandLineArgument());
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, UnloadsCommandLineArgument)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(hasCommandLineArgument());
+        this->unloadPlugin();
+        EXPECT_FALSE(hasCommandLineArgument());
+    }
+
+    TEST_F(PluginTest, ReloadsCommandLineArgument)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(hasCommandLineArgument());
+        this->unloadPlugin();
+        EXPECT_FALSE(hasCommandLineArgument());
+        this->loadPlugin();
+        EXPECT_TRUE(hasCommandLineArgument());
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, CommandLineArgumentHasCorrectValue)
+    {
+        this->loadPlugin();
+
+        ASSERT_TRUE(hasCommandLineArgument());
+        EXPECT_EQ(333, CommandLineParser::getValue("testvalue").get<int>());
+
+        this->unloadPlugin();
+    }
+
+
+    ///////////////////////////////////////////
+    ///////////// Console Command /////////////
+    ///////////////////////////////////////////
+
+    ConsoleCommand* getConsoleCommand()
+    {
+        return ConsoleCommandManager::getInstance().getCommand("testcommand");
+    }
+
+    TEST_F(PluginTest, LoadsConsoleCommand)
+    {
+        EXPECT_TRUE(getConsoleCommand() == nullptr);
+        this->loadPlugin();
+        EXPECT_TRUE(getConsoleCommand() != nullptr);
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, UnloadsConsoleCommand)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(getConsoleCommand() != nullptr);
+        this->unloadPlugin();
+        EXPECT_TRUE(getConsoleCommand() == nullptr);
+    }
+
+    TEST_F(PluginTest, ReloadsConsoleCommand)
+    {
+        this->loadPlugin();
+        EXPECT_TRUE(getConsoleCommand() != nullptr);
+        this->unloadPlugin();
+        EXPECT_TRUE(getConsoleCommand() == nullptr);
+        this->loadPlugin();
+        EXPECT_TRUE(getConsoleCommand() != nullptr);
+        this->unloadPlugin();
+    }
+
+    TEST_F(PluginTest, CanCallConsoleCommand)
+    {
+        this->loadPlugin();
+
+        ConsoleCommand* command = getConsoleCommand();
+        ASSERT_TRUE(command != nullptr);
+
+        EXPECT_EQ(999, (*command->getExecutor())(333, 666).get<int>());
+
+        this->unloadPlugin();
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core_plugin/Testclass.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/Testclass.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/Testclass.cc	(revision 11817)
@@ -0,0 +1,20 @@
+#include "Testclass.h"
+#include "core/CoreIncludes.h"
+#include "core/config/ConfigValueIncludes.h"
+
+namespace orxonox
+{
+    RegisterClassNoArgs(Testclass);
+
+    Testclass::Testclass()
+    {
+        RegisterObject(Testclass);
+
+        this->setConfigValues();
+    }
+
+    void Testclass::setConfigValues()
+    {
+        SetConfigValue(value_, 666);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core_plugin/Testclass.h
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/Testclass.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/Testclass.h	(revision 11817)
@@ -0,0 +1,22 @@
+#ifndef _Testclass_H__
+#define _Testclass_H__
+
+#include "core/class/OrxonoxClass.h"
+
+namespace orxonox
+{
+    class Testclass : public OrxonoxClass
+    {
+        public:
+            Testclass();
+            void setConfigValues();
+
+            int getValue() const
+                { return this->value_; }
+
+        private:
+            int value_;
+    };
+}
+
+#endif /* _Testclass_H__ */
Index: /code/branches/RacingBots_FS18/test/core_plugin/Testcommandlineargument.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/Testcommandlineargument.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/Testcommandlineargument.cc	(revision 11817)
@@ -0,0 +1,6 @@
+#include "core/commandline/CommandLineIncludes.h"
+
+namespace orxonox
+{
+    SetCommandLineArgument(testvalue, 333);
+}
Index: /code/branches/RacingBots_FS18/test/core_plugin/Testconsolecommand.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/Testconsolecommand.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/Testconsolecommand.cc	(revision 11817)
@@ -0,0 +1,11 @@
+#include "core/command/ConsoleCommandIncludes.h"
+
+namespace orxonox
+{
+    int testcommand(int a, int b)
+    {
+        return a + b;
+    }
+
+    SetConsoleCommand("testcommand", &testcommand);
+}
Index: /code/branches/RacingBots_FS18/test/core_plugin/Testsingleton.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/Testsingleton.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/Testsingleton.cc	(revision 11817)
@@ -0,0 +1,17 @@
+#include "Testsingleton.h"
+#include "core/CoreIncludes.h"
+#include "core/singleton/ScopedSingletonIncludes.h"
+
+namespace orxonox
+{
+    ManageScopedSingleton(Testsingleton, ScopeID::ROOT, false);
+
+    RegisterAbstractClass(Testsingleton).inheritsFrom<Listable>();
+
+    Testsingleton::Testsingleton()
+    {
+        RegisterObject(Testsingleton);
+
+        this->value_ = 999;
+    }
+}
Index: /code/branches/RacingBots_FS18/test/core_plugin/Testsingleton.h
===================================================================
--- /code/branches/RacingBots_FS18/test/core_plugin/Testsingleton.h	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/core_plugin/Testsingleton.h	(revision 11817)
@@ -0,0 +1,26 @@
+#ifndef _Testsingleton_H__
+#define _Testsingleton_H__
+
+#include "util/Singleton.h"
+#include "core/object/Listable.h"
+
+namespace orxonox
+{
+    class Testsingleton : public Singleton<Testsingleton>, public Listable
+    {
+        friend class Singleton<Testsingleton>;
+
+        public:
+            Testsingleton();
+
+            int getValue() const
+                { return this->value_; }
+
+        private:
+            int value_;
+
+            static Testsingleton* singletonPtr_s;
+    };
+}
+
+#endif /* _Testsingleton_H__ */
Index: /code/branches/RacingBots_FS18/test/util/CMakeLists.txt
===================================================================
--- /code/branches/RacingBots_FS18/test/util/CMakeLists.txt	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/CMakeLists.txt	(revision 11817)
@@ -0,0 +1,34 @@
+ORXONOX_ADD_EXECUTABLE(
+    util_test
+    EXCLUDE_FROM_ALL
+    NO_INSTALL
+  LINK_LIBRARIES
+    util
+    gmock_orxonox
+  SOURCE_FILES
+    ${GMOCK_MAIN}
+    ConvertTest.cc
+    MathTest.cc
+    mboolTest.cc
+    MultiTypeTest.cc
+    OutputTest.cc
+    SharedPtrTest.cc
+    SingletonTest.cc
+    SmallObjectAllocatorTest.cc
+    StringUtilsTest.cc
+    SubStringTest.cc
+    VA_NARGSTest.cc
+
+    output/BaseWriterTest.cc
+    output/ConsoleWriterTest.cc
+    output/LogWriterTest.cc
+    output/MemoryWriterTest.cc
+    output/OutputDefinitionsTest.cc
+    output/OutputListenerTest.cc
+    output/OutputManagerTest.cc
+    output/OutputStreamTest.cc
+    output/SubcontextOutputListenerTest.cc
+)
+ADD_DEPENDENCIES(all_tests util_test)
+
+ADD_TEST(util_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/util_test --gtest_output=xml)
Index: /code/branches/RacingBots_FS18/test/util/ConvertTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/ConvertTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/ConvertTest.cc	(revision 11817)
@@ -0,0 +1,135 @@
+#include <gtest/gtest.h>
+#include "util/Convert.h"
+#include "util/Math.h"
+#include "util/MathConvert.h"
+
+namespace orxonox
+{
+    TEST(multi_cast, ToString)
+    {
+        // int
+        EXPECT_EQ("5", multi_cast<std::string>(static_cast<int>(5)));
+        EXPECT_EQ("-13", multi_cast<std::string>(static_cast<int>(-13)));
+
+        // unsigned int
+        EXPECT_EQ("0", multi_cast<std::string>(static_cast<unsigned int>(0)));
+        EXPECT_EQ("4000000000", multi_cast<std::string>(static_cast<unsigned int>(4000000000LL)));
+
+        // float
+        EXPECT_EQ("0", multi_cast<std::string>(0.0f));
+        EXPECT_EQ("10", multi_cast<std::string>(10.0f));
+        EXPECT_EQ("123.456", multi_cast<std::string>(123.456f));
+        {
+            // expect 1.234e+012 or 1.234e+12
+            std::string value = multi_cast<std::string>(1234000000000.0f);
+            EXPECT_TRUE(value == "1.234e+012" || value == "1.234e+12");
+        }
+
+        // double
+        EXPECT_EQ("0", multi_cast<std::string>(0.0));
+        EXPECT_EQ("10", multi_cast<std::string>(10.0));
+        EXPECT_EQ("123.456", multi_cast<std::string>(123.456));
+        {
+            // expect 1.234e+012 or 1.234e+12
+            std::string value = multi_cast<std::string>(1234000000000.0);
+            EXPECT_TRUE(value == "1.234e+012" || value == "1.234e+12");
+        }
+
+        // char
+        EXPECT_EQ("a", multi_cast<std::string>('a'));
+        EXPECT_EQ("\n", multi_cast<std::string>('\n'));
+
+        // bool
+        EXPECT_EQ("true", multi_cast<std::string>(true));
+        EXPECT_EQ("false", multi_cast<std::string>(false));
+
+        // string
+        EXPECT_EQ("testTEST123", multi_cast<std::string>("testTEST123"));
+        EXPECT_EQ("", multi_cast<std::string>(""));
+
+        // TODO: Check consistency of conversion depending on MathConvert.h and reversibility
+/*
+        // Vector2
+        EXPECT_EQ("Vector2(10.1, 20)", multi_cast<std::string>(Vector2(10.1, 20)));
+
+        // Vector3
+        EXPECT_EQ("Vector3(10.1, 20, 300000)", multi_cast<std::string>(Vector3(10.1, 20, 300000)));
+
+        // Vector4
+        EXPECT_EQ("Vector4(10.1, 20, 300000, -321)", multi_cast<std::string>(Vector4(10.1, 20, 300000, -321)));
+
+        // Quaternion
+        EXPECT_EQ("Quaternion(10.1, 20, 300000, -321)", multi_cast<std::string>(Quaternion(10.1, 20, 300000, -321)));
+
+        // ColourValue
+        EXPECT_EQ("ColourValue(10.1, 20, 300000, -321)", multi_cast<std::string>(ColourValue(10.1, 20, 300000, -321)));
+
+        // Radian
+        EXPECT_EQ("Radian(1.234)", multi_cast<std::string>(Radian(1.234)));
+
+        // Degree
+        EXPECT_EQ("Degree(123)", multi_cast<std::string>(Degree(123)));
+*/
+    }
+
+    TEST(multi_cast, FromString)
+    {
+        // int
+        EXPECT_EQ(5, multi_cast<int>(std::string("5")));
+        EXPECT_EQ(-13, multi_cast<int>(std::string("-13")));
+
+        // unsigned int
+        EXPECT_EQ(0U, multi_cast<unsigned int>(std::string("0")));
+        EXPECT_EQ(4000000000LL, multi_cast<unsigned int>(std::string("4000000000")));
+
+        // float
+        EXPECT_EQ(0.0f, multi_cast<float>(std::string("0")));
+        EXPECT_EQ(10.0f, multi_cast<float>(std::string("10")));
+        EXPECT_EQ(123.456f, multi_cast<float>(std::string("123.456")));
+        EXPECT_EQ(1234000000000.0f, multi_cast<float>(std::string("1.234e+012")));
+
+        // double
+        EXPECT_EQ(0.0, multi_cast<double>(std::string("0")));
+        EXPECT_EQ(10.0, multi_cast<double>(std::string("10")));
+        EXPECT_EQ(123.456, multi_cast<double>(std::string("123.456")));
+        EXPECT_EQ(1234000000000.0, multi_cast<double>(std::string("1.234e+012")));
+
+        // char
+        EXPECT_EQ('a', multi_cast<char>(std::string("a")));
+        EXPECT_EQ('\n', multi_cast<char>(std::string("\n")));
+        EXPECT_EQ('\0', multi_cast<char>(std::string("")));
+        EXPECT_EQ('1', multi_cast<char>(std::string("123")));
+
+        // bool
+        EXPECT_TRUE(multi_cast<bool>(std::string("true")));
+        EXPECT_FALSE(multi_cast<bool>(std::string("false")));
+        EXPECT_FALSE(multi_cast<bool>(std::string("0")));
+        EXPECT_FALSE(multi_cast<bool>(std::string("0.123")));
+        EXPECT_TRUE(multi_cast<bool>(std::string("1")));
+        EXPECT_TRUE(multi_cast<bool>(std::string("123.456")));
+
+        // TODO: Check consistency of conversion depending on MathConvert.h and reversibility
+/*
+        // Vector2
+        EXPECT_EQ(Vector2(10.1, 20), multi_cast<Vector2>(std::string("Vector2(10.1, 20)")));
+
+        // Vector3
+        EXPECT_EQ(Vector3(10.1, 20, 300000), multi_cast<Vector3>(std::string("Vector3(10.1, 20, 300000)")));
+
+        // Vector4
+        EXPECT_EQ(Vector4(10.1, 20, 300000, -321), multi_cast<Vector4>(std::string("Vector4(10.1, 20, 300000, -321)")));
+
+        // Quaternion
+        EXPECT_EQ(Quaternion(10.1, 20, 300000, -321), multi_cast<Quaternion>(std::string("Quaternion(10.1, 20, 300000, -321)")));
+
+        // ColourValue
+        EXPECT_EQ(ColourValue(10.1, 20, 300000, -321), multi_cast<ColourValue>(std::string("ColourValue(10.1, 20, 300000, -321)")));
+
+        // Radian
+        EXPECT_EQ(Radian(1.234), multi_cast<Radian>(std::string("Radian(1.234)")));
+
+        // Degree
+        EXPECT_EQ(Degree(123), multi_cast<Degree>(std::string("Degree(123)")));
+*/
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/MathTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/MathTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/MathTest.cc	(revision 11817)
@@ -0,0 +1,342 @@
+#include <gtest/gtest.h>
+#include "util/Math.h"
+#include <cmath>
+
+namespace orxonox
+{
+    ///////////
+    // sgn() //
+    ///////////
+    TEST(sgn, PositiveInt)
+    {
+        EXPECT_EQ(1, sgn( 1));
+        EXPECT_EQ(1, sgn(10));
+    }
+
+    TEST(sgn, PositiveDouble)
+    {
+        EXPECT_DOUBLE_EQ(1.0, sgn( 0.1));
+        EXPECT_DOUBLE_EQ(1.0, sgn( 1.0));
+        EXPECT_DOUBLE_EQ(1.0, sgn(10.0));
+    }
+
+    TEST(sgn, NegativeInt)
+    {
+        EXPECT_EQ(-1, sgn( -1));
+        EXPECT_EQ(-1, sgn(-10));
+    }
+
+    TEST(sgn, NegativeDouble)
+    {
+        EXPECT_DOUBLE_EQ(-1.0, sgn( -0.1));
+        EXPECT_DOUBLE_EQ(-1.0, sgn( -1.0));
+        EXPECT_DOUBLE_EQ(-1.0, sgn(-10.0));
+    }
+
+    TEST(sgn, ZeroInt)
+    {
+        EXPECT_EQ(1, sgn(0));
+    }
+
+    TEST(sgn, ZeroDouble)
+    {
+        EXPECT_DOUBLE_EQ(1.0, sgn(0.0));
+    }
+
+    /////////////
+    // clamp() //
+    /////////////
+    TEST(clamp, InRange)
+    {
+        // positive
+        EXPECT_EQ(10, clamp(10, 10, 20));
+        EXPECT_EQ(15, clamp(15, 10, 20));
+        EXPECT_EQ(20, clamp(20, 10, 20));
+
+        // netagive
+        EXPECT_EQ(-10, clamp(-10, -20, -10));
+        EXPECT_EQ(-15, clamp(-15, -20, -10));
+        EXPECT_EQ(-20, clamp(-20, -20, -10));
+
+        // mixed
+        EXPECT_EQ(-10, clamp(-10, -10, 10));
+        EXPECT_EQ(  0, clamp(  0, -10, 10));
+        EXPECT_EQ( 10, clamp( 10, -10, 10));
+    }
+
+    TEST(clamp, OutOfRange)
+    {
+        // positive
+        EXPECT_EQ(10, clamp( 5, 10, 20));
+        EXPECT_EQ(20, clamp(25, 10, 20));
+
+        // netagive
+        EXPECT_EQ(-10, clamp( -5, -20, -10));
+        EXPECT_EQ(-20, clamp(-25, -20, -10));
+
+        // mixed
+        EXPECT_EQ(-10, clamp(-15, -10, 10));
+        EXPECT_EQ( 10, clamp( 15, -10, 10));
+    }
+
+    //////////////
+    // square() //
+    //////////////
+    TEST(square, Int)
+    {
+        // zero
+        EXPECT_EQ( 0, square(0));
+
+        // positive
+        EXPECT_EQ(1, square(1));
+        EXPECT_EQ(4, square(2));
+        EXPECT_EQ(9, square(3));
+
+        // negative
+        EXPECT_EQ(1, square(-1));
+        EXPECT_EQ(4, square(-2));
+        EXPECT_EQ(9, square(-3));
+    }
+
+    TEST(square, Double)
+    {
+        // zero
+        EXPECT_DOUBLE_EQ( 0.0, square(0.0));
+
+        // positive
+        EXPECT_DOUBLE_EQ( 1.00, square(1.0));
+        EXPECT_DOUBLE_EQ( 2.25, square(1.5));
+        EXPECT_DOUBLE_EQ( 4.00, square(2.0));
+
+        // negative
+        EXPECT_DOUBLE_EQ( 1.00, square(-1.0));
+        EXPECT_DOUBLE_EQ( 2.25, square(-1.5));
+        EXPECT_DOUBLE_EQ( 4.00, square(-2.0));
+    }
+
+    ////////////
+    // cube() //
+    ////////////
+    TEST(cube, Int)
+    {
+        // zero
+        EXPECT_EQ( 0, cube(0));
+
+        // positive
+        EXPECT_EQ( 1, cube(1));
+        EXPECT_EQ( 8, cube(2));
+        EXPECT_EQ(27, cube(3));
+
+        // negative
+        EXPECT_EQ( -1, cube(-1));
+        EXPECT_EQ( -8, cube(-2));
+        EXPECT_EQ(-27, cube(-3));
+    }
+
+    TEST(cube, Double)
+    {
+        // zero
+        EXPECT_DOUBLE_EQ( 0.0, cube(0.0));
+
+        // positive
+        EXPECT_DOUBLE_EQ( 1.000, cube(1.0));
+        EXPECT_DOUBLE_EQ( 3.375, cube(1.5));
+        EXPECT_DOUBLE_EQ( 8.000, cube(2.0));
+
+        // negative
+        EXPECT_DOUBLE_EQ( -1.000, cube(-1.0));
+        EXPECT_DOUBLE_EQ( -3.375, cube(-1.5));
+        EXPECT_DOUBLE_EQ( -8.000, cube(-2.0));
+    }
+
+    ///////////
+    // mod() //
+    ///////////
+    TEST(mod, ModOperator)
+    {
+        // zero
+        EXPECT_EQ(0,  0 % 10);
+
+        // positive
+        EXPECT_EQ(1,  1 % 10);
+        EXPECT_EQ(5,  5 % 10);
+        EXPECT_EQ(9,  9 % 10);
+        EXPECT_EQ(0, 10 % 10);
+        EXPECT_EQ(5, 15 % 10);
+
+        // negative
+        EXPECT_EQ(-1,  -1 % 10);
+        EXPECT_EQ(-5,  -5 % 10);
+        EXPECT_EQ(-9,  -9 % 10);
+        EXPECT_EQ( 0, -10 % 10);
+        EXPECT_EQ(-5, -15 % 10);
+    }
+
+    TEST(mod, ModFunction)
+    {
+        // zero
+        EXPECT_EQ(0,  mod(0, 10));
+
+        // positive
+        EXPECT_EQ(1, mod( 1, 10));
+        EXPECT_EQ(5, mod( 5, 10));
+        EXPECT_EQ(9, mod( 9, 10));
+        EXPECT_EQ(0, mod(10, 10));
+        EXPECT_EQ(5, mod(15, 10));
+
+        // negative
+        EXPECT_EQ(9, mod( -1, 10));
+        EXPECT_EQ(5, mod( -5, 10));
+        EXPECT_EQ(1, mod( -9, 10));
+        EXPECT_EQ(0, mod(-10, 10));
+        EXPECT_EQ(5, mod(-15, 10));
+    }
+
+    ///////////////
+    // zeroise() //
+    ///////////////
+    TEST(zeroise, Test)
+    {
+        EXPECT_EQ(0, zeroise<int>());
+        EXPECT_EQ((unsigned int)0, zeroise<unsigned int>());
+        EXPECT_DOUBLE_EQ(0.0, zeroise<double>());
+        EXPECT_EQ("", zeroise<std::string>());
+        EXPECT_EQ(Vector3::ZERO, zeroise<Vector3>());
+    }
+
+    ///////////////////
+    // interpolate() //
+    ///////////////////
+    TEST(interpolate, Linear)
+    {
+        EXPECT_EQ( 0, interpolate(0.00f, 0, 20));
+        EXPECT_EQ( 5, interpolate(0.25f, 0, 20));
+        EXPECT_EQ(10, interpolate(0.50f, 0, 20));
+        EXPECT_EQ(15, interpolate(0.75f, 0, 20));
+        EXPECT_EQ(20, interpolate(1.00f, 0, 20));
+    }
+
+    TEST(interpolate, Smooth)
+    {
+        EXPECT_EQ( 0, interpolateSmooth(0.00f, 0, 20));
+        EXPECT_GT( 5, interpolateSmooth(0.25f, 0, 20));
+        EXPECT_EQ(10, interpolateSmooth(0.50f, 0, 20));
+        EXPECT_LT(15, interpolateSmooth(0.75f, 0, 20));
+        EXPECT_EQ(20, interpolateSmooth(1.00f, 0, 20));
+    }
+
+    ///////////
+    // rnd() //
+    ///////////
+    TEST(rnd, Default)
+    {
+        // how to test randomness?
+        std::set<float> numbers;
+
+        const float max = 1.0;
+        const float min = 0.0;
+        const size_t iterations = 1000;
+
+        for (size_t i = 0; i < iterations; ++i)
+            numbers.insert(rnd());
+
+        // must have at most <iterations> numbers in the set
+        EXPECT_GE(iterations, numbers.size());
+
+        // all numbers must satisfy 0 <= <number> < 1
+        for (float number : numbers)
+        {
+            EXPECT_LE(min, number);
+            EXPECT_GT(max, number);
+        }
+    }
+
+    TEST(rnd, Max)
+    {
+        // how to test randomness?
+        std::set<float> numbers;
+
+        const float max = 10.0;
+        const float min = 0.0;
+        const size_t iterations = 1000;
+
+        for (size_t i = 0; i < iterations; ++i)
+            numbers.insert(rnd(max));
+
+        // must have at most <iterations> numbers in the set
+        EXPECT_GE(iterations, numbers.size());
+
+        // all numbers must satisfy 0 <= <number> < <max>
+        for (float number : numbers)
+        {
+            EXPECT_LE(min, number);
+            EXPECT_GT(max, number);
+        }
+    }
+
+    TEST(rnd, MinMax)
+    {
+        // how to test randomness?
+        std::set<float> numbers;
+
+        const float max = 10.0;
+        const float min = 5.0;
+        const size_t iterations = 1000;
+
+        for (size_t i = 0; i < iterations; ++i)
+            numbers.insert(rnd(min, max));
+
+        // must have at most <iterations> numbers in the set
+        EXPECT_GE(iterations, numbers.size());
+
+        // all numbers must satisfy <min> <= <number> < <max>
+        for (float number : numbers)
+        {
+            EXPECT_LE(min, number);
+            EXPECT_GT(max, number);
+        }
+    }
+
+    //////////////
+    // rndsgn() //
+    //////////////
+    TEST(rndsgn, Test)
+    {
+        // how to test randomness?
+        std::set<float> numbers;
+
+        const size_t iterations = 100;
+
+        for (size_t i = 0; i < iterations; ++i)
+            numbers.insert(rndsgn());
+
+        // must have at most 2 numbers in the set
+        EXPECT_GE((size_t)2, numbers.size());
+
+        // all numbers must be either 1 oder -1
+        for (float number : numbers)
+            EXPECT_TRUE(number == 1 || number == -1);
+    }
+
+    ///////////////////////
+    // getUniqueNumber() //
+    ///////////////////////
+    TEST(getUniqueNumber, Test)
+    {
+        std::set<unsigned long> numbers;
+
+        const size_t iterations = 1000;
+
+        for (size_t i = 0; i < iterations; ++i)
+            numbers.insert(getUniqueNumber());
+
+        // must have exactly <iterations> numbers in the set, since all numbers should be unique
+        EXPECT_EQ(iterations, numbers.size());
+    }
+/*
+    getAngle
+    get2DViewdirection
+    get2DViewCoordinates
+    getPredictedPosition
+*/
+}
Index: /code/branches/RacingBots_FS18/test/util/MultiTypeTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/MultiTypeTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/MultiTypeTest.cc	(revision 11817)
@@ -0,0 +1,938 @@
+#include <gtest/gtest.h>
+#include "util/MultiType.h"
+
+namespace orxonox
+{
+    // x constructor()
+    // x constructor(value)
+    // x constructor(other)
+
+    // x assignment(value)
+    // ? assignment(pointer)
+    // x assignment(other)
+
+    // x set(value)
+    // ? set(pointer)
+    // x force<type>(value)
+
+    // x convert<type>()
+    // x reset
+    // x reset<type>()
+    // x resetValue
+
+    // x isType<type>()
+
+    // x (type) conversion
+    // ? (pointer class) conversion
+    // x getValue(pointer)
+    // x get<type>()
+    // ? getPointer()
+
+    // x lastConversionSuccessful()
+    // x null()
+
+    /////////////////////////
+    // Default Constructor //
+    /////////////////////////
+    TEST(MultiType, DefaultConstructor)
+    {
+        MultiType mt;
+        EXPECT_TRUE(mt.null());
+        EXPECT_TRUE(mt.isType<void>());
+    }
+
+    /////////////////
+    // Constructor //
+    /////////////////
+    TEST(MultiType, ValueChar)              { char value = -100;                                MultiType mt(value);    EXPECT_TRUE(mt.isType<char>());                 EXPECT_EQ(-100, mt.get<char>()); }
+    TEST(MultiType, ValueUnsignedChar)      { unsigned char value = 255u;                       MultiType mt(value);    EXPECT_TRUE(mt.isType<unsigned char>());        EXPECT_EQ(255u, mt.get<unsigned char>()); }
+    TEST(MultiType, ValueShort)             { short value = -10000;                             MultiType mt(value);    EXPECT_TRUE(mt.isType<short>());                EXPECT_EQ(-10000, mt.get<short>()); }
+    TEST(MultiType, ValueUnsignedShort)     { unsigned short value = 65535u;                    MultiType mt(value);    EXPECT_TRUE(mt.isType<unsigned short>());       EXPECT_EQ(65535u, mt.get<unsigned short>()); }
+    TEST(MultiType, ValueInt)               { int value = -1000000000;                          MultiType mt(value);    EXPECT_TRUE(mt.isType<int>());                  EXPECT_EQ(-1000000000, mt.get<int>()); }
+    TEST(MultiType, ValueUnsignedInt)       { unsigned int value = 4000000000u;                 MultiType mt(value);    EXPECT_TRUE(mt.isType<unsigned int>());         EXPECT_EQ(4000000000u, mt.get<unsigned int>()); }
+    TEST(MultiType, ValueLong)              { long value = -1000000000;                         MultiType mt(value);    EXPECT_TRUE(mt.isType<long>());                 EXPECT_EQ(-1000000000, mt.get<long>()); }
+    TEST(MultiType, ValueUnsignedLong)      { unsigned long value = 4000000000u;                MultiType mt(value);    EXPECT_TRUE(mt.isType<unsigned long>());        EXPECT_EQ(4000000000u, mt.get<unsigned long>()); }
+    TEST(MultiType, ValueLongLong)          { long long value = -1000000000000000000L;          MultiType mt(value);    EXPECT_TRUE(mt.isType<long long>());            EXPECT_EQ(-1000000000000000000L, mt.get<long long>()); }
+    TEST(MultiType, ValueUnsignedLongLong)  { unsigned long long value = 4000000000000000000UL; MultiType mt(value);    EXPECT_TRUE(mt.isType<unsigned long long>());   EXPECT_EQ(4000000000000000000UL, mt.get<unsigned long long>()); }
+    TEST(MultiType, ValueFloat)             { float value = 0.123456f;                          MultiType mt(value);    EXPECT_TRUE(mt.isType<float>());                EXPECT_EQ(0.123456f, mt.get<float>()); }
+    TEST(MultiType, ValueDouble)            { double value = 0.123456789;                       MultiType mt(value);    EXPECT_TRUE(mt.isType<double>());               EXPECT_EQ(0.123456789, mt.get<double>()); }
+    TEST(MultiType, ValueLongDouble)        { long double value = 0.123456789123456789;         MultiType mt(value);    EXPECT_TRUE(mt.isType<long double>());          EXPECT_EQ(0.123456789123456789, mt.get<long double>()); }
+    TEST(MultiType, ValueBool)              { bool value = true;                                MultiType mt(value);    EXPECT_TRUE(mt.isType<bool>());                 EXPECT_EQ(true, mt.get<bool>()); }
+    TEST(MultiType, ValueVoidpointer)       { int* pointer = new int; void* value = pointer;    MultiType mt(value);    EXPECT_TRUE(mt.isType<void*>());                EXPECT_EQ(value, mt.get<void*>()); delete pointer; }
+    TEST(MultiType, ValueSomepointer)       { int* value = new int;                             MultiType mt(value);    EXPECT_TRUE(mt.isType<void*>());                EXPECT_EQ(value, mt.get<int*>()); delete value; }
+    TEST(MultiType, ValueString)            { std::string value = "Hello World";                MultiType mt(value);    EXPECT_TRUE(mt.isType<std::string>());          EXPECT_EQ("Hello World", mt.get<std::string>()); }
+    TEST(MultiType, ValueVector2)           { Vector2 value = Vector2(11, 22);                  MultiType mt(value);    EXPECT_TRUE(mt.isType<Vector2>());              EXPECT_EQ(Vector2(11, 22), mt.get<Vector2>()); }
+    TEST(MultiType, ValueVector3)           { Vector3 value = Vector3(11, 22, 33);              MultiType mt(value);    EXPECT_TRUE(mt.isType<Vector3>());              EXPECT_EQ(Vector3(11, 22, 33), mt.get<Vector3>()); }
+    TEST(MultiType, ValueVector4)           { Vector4 value = Vector4(11, 22, 33, 44);          MultiType mt(value);    EXPECT_TRUE(mt.isType<Vector4>());              EXPECT_EQ(Vector4(11, 22, 33, 44), mt.get<Vector4>()); }
+    TEST(MultiType, ValueColourValue)       { ColourValue value = ColourValue(11, 22, 33, 44);  MultiType mt(value);    EXPECT_TRUE(mt.isType<ColourValue>());          EXPECT_EQ(ColourValue(11, 22, 33, 44), mt.get<ColourValue>()); }
+    TEST(MultiType, ValueQuaternion)        { Quaternion value = Quaternion(11, 22, 33, 44);    MultiType mt(value);    EXPECT_TRUE(mt.isType<Quaternion>());           EXPECT_EQ(Quaternion(11, 22, 33, 44), mt.get<Quaternion>()); }
+    TEST(MultiType, ValueRadian)            { Radian value = Radian(0.123);                     MultiType mt(value);    EXPECT_TRUE(mt.isType<Radian>());               EXPECT_EQ(Radian(0.123), mt.get<Radian>()); }
+    TEST(MultiType, ValueDegree)            { Degree value = Degree(123);                       MultiType mt(value);    EXPECT_TRUE(mt.isType<Degree>());               EXPECT_EQ(Degree(123), mt.get<Degree>()); }
+    TEST(MultiType, ValueMbool)             { mbool value = mbool(true);                        MultiType mt(value);    EXPECT_TRUE(mt.isType<bool>());                 EXPECT_EQ(mbool(true), mt.get<bool>()); }
+    TEST(MultiType, ValueCharPointer)       { const char* value = "Hello World";                MultiType mt(value);    EXPECT_TRUE(mt.isType<std::string>());          EXPECT_EQ("Hello World", mt.get<std::string>()); }
+
+    //////////////////////
+    // Copy-Constructor //
+    //////////////////////
+    TEST(MultiType, CopyConstructorEmpty)
+    {
+        MultiType mt1;
+        MultiType mt2(mt1);
+
+        EXPECT_TRUE(mt2.null());
+    }
+
+    TEST(MultiType, CopyConstructorFloat)
+    {
+        MultiType mt1(0.1234f);
+        MultiType mt2(mt1);
+
+        EXPECT_TRUE(mt2.isType<float>());
+        EXPECT_EQ(0.1234f, mt2.get<float>());
+    }
+
+    //////////////////////
+    // Assignment Value //
+    //////////////////////
+    TEST(MultiType, AssignmentIntToEmpty)
+    {
+        MultiType mt;
+
+        EXPECT_TRUE(mt.null());
+
+        mt = 55;
+
+        EXPECT_FALSE(mt.null());
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(55, mt.get<int>());
+    }
+
+    TEST(MultiType, AssignmentFloatToInt)
+    {
+        MultiType mt(66);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(66, mt.get<int>());
+
+        mt = 77.7f; // will be converted to int
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(77, mt.get<int>());
+        EXPECT_EQ(77.0f, mt.get<float>());
+    }
+
+    TEST(MultiType, AssignmentFloatToFloat)
+    {
+        MultiType mt(66.6f);
+
+        EXPECT_TRUE(mt.isType<float>());
+        EXPECT_EQ(66, mt.get<int>());
+        EXPECT_EQ(66.6f, mt.get<float>());
+
+        mt = 77.7f;
+
+        EXPECT_TRUE(mt.isType<float>());
+        EXPECT_EQ(77, mt.get<int>());
+        EXPECT_EQ(77.7f, mt.get<float>());
+    }
+
+    TEST(MultiType, AssignmentFloatToVector3)
+    {
+        MultiType mt(Vector3(1, 2, 3));
+
+        EXPECT_TRUE(mt.isType<Vector3>());
+        EXPECT_EQ(Vector3(1, 2, 3), mt.get<Vector3>());
+        EXPECT_TRUE(mt.lastConversionSuccessful());
+
+        mt = 77.7f;
+
+        EXPECT_TRUE(mt.isType<Vector3>());
+        EXPECT_EQ(Vector3::ZERO, mt.get<Vector3>());
+        EXPECT_FALSE(mt.lastConversionSuccessful());
+    }
+
+    //////////////////////
+    // Assignment Other //
+    //////////////////////
+    TEST(MultiType, AssignmentOther)
+    {
+        MultiType mt1(33);
+        MultiType mt2(44.4f);
+
+        EXPECT_TRUE(mt1.isType<int>());
+        EXPECT_TRUE(mt2.isType<float>());
+
+        EXPECT_EQ(33, mt1.get<int>());
+        EXPECT_EQ(33.0f, mt1.get<float>());
+        EXPECT_EQ(44.4f, mt2.get<float>());
+
+        mt1 = mt2;
+
+        EXPECT_TRUE(mt1.isType<int>());
+        EXPECT_TRUE(mt2.isType<float>());
+
+        EXPECT_EQ(44, mt1.get<int>());
+        EXPECT_EQ(44.0f, mt1.get<float>());
+        EXPECT_EQ(44.4f, mt2.get<float>());
+    }
+
+    ////////////////
+    // set(value) //
+    ////////////////
+    TEST(MultiType, SetValueBoolToEmpty)
+    {
+        MultiType mt;
+
+        mt.set(true);
+
+        EXPECT_TRUE(mt.isType<bool>());
+        EXPECT_EQ(true, mt.get<bool>());
+    }
+
+    TEST(MultiType, SetValueIntToString)
+    {
+        MultiType mt("Hello");
+
+        EXPECT_TRUE(mt.isType<std::string>());
+        EXPECT_EQ("Hello", mt.get<std::string>());
+
+        mt.set(1234);
+
+        EXPECT_TRUE(mt.isType<std::string>());
+        EXPECT_EQ("1234", mt.get<std::string>());
+    }
+
+    //////////////////////
+    // force<type>(value) //
+    //////////////////////
+    TEST(MultiType, SetValueWithTypeIntToString)
+    {
+        MultiType mt("Hello");
+
+        EXPECT_TRUE(mt.isType<std::string>());
+        EXPECT_EQ("Hello", mt.get<std::string>());
+
+        mt.force<int>(1234);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(1234, mt.get<int>());
+    }
+
+    TEST(MultiType, SetValueWithTypeIntAsStringToString)
+    {
+        MultiType mt("Hello");
+
+        EXPECT_TRUE(mt.isType<std::string>());
+        EXPECT_EQ("Hello", mt.get<std::string>());
+
+        mt.force<int>("1234");
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(1234, mt.get<int>());
+    }
+
+    TEST(MultiType, SetValueWithTypeIntToInt)
+    {
+        MultiType mt(4321);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(4321, mt.get<int>());
+
+        mt.force<int>(1234);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(1234, mt.get<int>());
+    }
+
+    /////////////////////
+    // convert<type>() //
+    /////////////////////
+    TEST(MultiType, ConvertEmptyToInt)
+    {
+        MultiType mt;
+        mt.convert<int>();
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(0, mt.get<int>());
+    }
+
+    TEST(MultiType, ConvertFloatToInt)
+    {
+        MultiType mt(1.234f);
+
+        EXPECT_TRUE(mt.isType<float>());
+        EXPECT_EQ(1.234f, mt.get<float>());
+        EXPECT_EQ(1, mt.get<int>());
+
+        mt.convert<int>();
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(1.0f, mt.get<float>());
+        EXPECT_EQ(1, mt.get<int>());
+    }
+
+    TEST(MultiType, ConvertFloatToVector3)
+    {
+        MultiType mt(1.234f);
+
+        EXPECT_TRUE(mt.isType<float>());
+        EXPECT_EQ(1.234f, mt.get<float>());
+        EXPECT_EQ(Vector3::ZERO, mt.get<Vector3>());
+
+        mt.convert<Vector3>();
+
+        EXPECT_TRUE(mt.isType<Vector3>());
+        EXPECT_EQ(0.0f, mt.get<float>());
+        EXPECT_EQ(Vector3::ZERO, mt.get<Vector3>());
+
+        EXPECT_FALSE(mt.lastConversionSuccessful());
+    }
+
+    ///////////
+    // reset //
+    ///////////
+    TEST(MultiType, Reset)
+    {
+        MultiType mt(10);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_FALSE(mt.isType<void>());
+        EXPECT_FALSE(mt.null());
+        EXPECT_EQ(10, mt.get<int>());
+
+        mt.reset();
+
+        EXPECT_FALSE(mt.isType<int>());
+        EXPECT_TRUE(mt.isType<void>());
+        EXPECT_TRUE(mt.null());
+        EXPECT_EQ(0, mt.get<int>());
+    }
+
+    ///////////////////
+    // reset<type>() //
+    ///////////////////
+    TEST(MultiType, SetType)
+    {
+        MultiType mt(10);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_FALSE(mt.isType<float>());
+        EXPECT_EQ(10, mt.get<int>());
+
+        mt.reset<float>();
+
+        EXPECT_FALSE(mt.isType<int>());
+        EXPECT_TRUE(mt.isType<float>());
+        EXPECT_EQ(0, mt.get<int>());
+    }
+
+    ////////////////
+    // resetValue //
+    ////////////////
+    TEST(MultiType, resetValue)
+    {
+        MultiType mt(10);
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(10, mt.get<int>());
+
+        mt.resetValue();
+
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_EQ(0, mt.get<int>());
+    }
+
+    /////////////////////
+    // type operator() //
+    /////////////////////
+    TEST(MultiType, ConversionOperatorFloatToFloat)
+    {
+        MultiType mt(12.34f);
+        float value = mt;
+        EXPECT_EQ(12.34f, value);
+    }
+
+    TEST(MultiType, ConversionOperatorFloatToInt)
+    {
+        MultiType mt(12.34f);
+        int value = mt;
+        EXPECT_EQ(12, value);
+    }
+
+    TEST(MultiType, ConversionOperatorIntToFloat)
+    {
+        MultiType mt(123);
+        float value = mt;
+        EXPECT_EQ(123, value);
+    }
+
+    TEST(MultiType, ConversionOperatorIntToString)
+    {
+        MultiType mt(123);
+        std::string value = mt;
+        EXPECT_EQ("123", value);
+    }
+
+    TEST(MultiType, ConversionOperatorStringToInt)
+    {
+        MultiType mt("321");
+        int value = mt;
+        EXPECT_EQ(321, value);
+    }
+
+    namespace
+    {
+        void helper_function(const std::string& a, float b, int c)
+        {
+            EXPECT_EQ("555.555", a);
+            EXPECT_EQ(555.555f, b);
+            EXPECT_EQ(555, c);
+        }
+    }
+
+    TEST(MultiType, ConversionOperatorPassToFunction)
+    {
+        MultiType mt("555.555");
+
+        helper_function(mt, mt, mt);
+    }
+
+    ///////////////////////
+    // getValue(pointer) //
+    ///////////////////////
+    TEST(MultiType, GetValueIntToInt)
+    {
+        MultiType mt(33);
+
+        int value = 0;
+        EXPECT_TRUE(mt.getValue(&value));
+        EXPECT_EQ(33, value);
+    }
+
+    TEST(MultiType, GetValueIntToFloat)
+    {
+        MultiType mt(33);
+
+        float value = 0;
+        EXPECT_TRUE(mt.getValue(&value));
+        EXPECT_EQ(33.0f, value);
+    }
+
+    TEST(MultiType, GetValueIntToVector3)
+    {
+        MultiType mt(33);
+
+        Vector3 value = Vector3::ZERO;
+        EXPECT_FALSE(mt.getValue(&value));
+        EXPECT_EQ(Vector3::ZERO, value);
+    }
+
+    //////////////
+    // get<type>() //
+    //////////////
+    TEST(MultiType, GetValueFromInt)
+    {
+        MultiType mt(256);
+
+        EXPECT_EQ(0, mt.get<char>());
+        EXPECT_EQ(0u, mt.get<unsigned char>());
+        EXPECT_EQ(256, mt.get<short>());
+        EXPECT_EQ(256u, mt.get<unsigned short>());
+        EXPECT_EQ(256, mt.get<int>());
+        EXPECT_EQ(256u, mt.get<unsigned int>());
+        EXPECT_EQ(256, mt.get<long>());
+        EXPECT_EQ(256u, mt.get<unsigned long>());
+        EXPECT_EQ(256, mt.get<long long>());
+        EXPECT_EQ(256u, mt.get<unsigned long long>());
+        EXPECT_EQ(256.0f, mt.get<float>());
+        EXPECT_EQ(256.0, mt.get<double>());
+        EXPECT_EQ(256.0, mt.get<long double>());
+        EXPECT_TRUE(mt.get<bool>());
+        EXPECT_EQ("256", mt.get<std::string>());
+    }
+
+    TEST(MultiType, GetValueFromFloat)
+    {
+        MultiType mt(128.821);
+
+        EXPECT_EQ(-128, mt.get<char>());
+        EXPECT_EQ(128u, mt.get<unsigned char>());
+        EXPECT_EQ(128, mt.get<short>());
+        EXPECT_EQ(128u, mt.get<unsigned short>());
+        EXPECT_EQ(128, mt.get<int>());
+        EXPECT_EQ(128u, mt.get<unsigned int>());
+        EXPECT_EQ(128, mt.get<long>());
+        EXPECT_EQ(128u, mt.get<unsigned long>());
+        EXPECT_EQ(128, mt.get<long long>());
+        EXPECT_EQ(128u, mt.get<unsigned long long>());
+        EXPECT_EQ(128.821f, mt.get<float>());
+        EXPECT_EQ(128.821, mt.get<double>());
+        EXPECT_EQ(128.821, mt.get<long double>());
+        EXPECT_TRUE(mt.get<bool>());
+        EXPECT_EQ("128.821", mt.get<std::string>());
+    }
+
+    TEST(MultiType, GetValueFromString)
+    {
+        MultiType mt("0.123");
+
+        EXPECT_EQ('0', mt.get<char>());
+        EXPECT_EQ('0', mt.get<unsigned char>());
+        EXPECT_EQ(0, mt.get<short>());
+        EXPECT_EQ(0u, mt.get<unsigned short>());
+        EXPECT_EQ(0, mt.get<int>());
+        EXPECT_EQ(0u, mt.get<unsigned int>());
+        EXPECT_EQ(0, mt.get<long>());
+        EXPECT_EQ(0u, mt.get<unsigned long>());
+        EXPECT_EQ(0, mt.get<long long>());
+        EXPECT_EQ(0u, mt.get<unsigned long long>());
+        EXPECT_EQ(0.123f, mt.get<float>());
+        EXPECT_EQ(0.123, mt.get<double>());
+        EXPECT_DOUBLE_EQ(0.123, mt.get<long double>());
+        EXPECT_FALSE(mt.get<bool>());
+        EXPECT_EQ("0.123", mt.get<std::string>());
+    }
+
+    ////////////////////
+    // isType<type>() //
+    ////////////////////
+    TEST(MultiType, IsTypeInt)
+    {
+        MultiType mt(1);
+
+        EXPECT_FALSE(mt.isType<void>());
+        EXPECT_FALSE(mt.isType<char>());
+        EXPECT_FALSE(mt.isType<unsigned char>());
+        EXPECT_FALSE(mt.isType<short>());
+        EXPECT_FALSE(mt.isType<unsigned short>());
+        EXPECT_TRUE(mt.isType<int>());
+        EXPECT_FALSE(mt.isType<unsigned int>());
+        EXPECT_FALSE(mt.isType<long>());
+        EXPECT_FALSE(mt.isType<unsigned long>());
+        EXPECT_FALSE(mt.isType<long long>());
+        EXPECT_FALSE(mt.isType<unsigned long long>());
+        EXPECT_FALSE(mt.isType<float>());
+        EXPECT_FALSE(mt.isType<double>());
+        EXPECT_FALSE(mt.isType<long double>());
+        EXPECT_FALSE(mt.isType<bool>());
+        EXPECT_FALSE(mt.isType<void*>());
+        EXPECT_FALSE(mt.isType<std::string>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector2>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector3>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector4>());
+        EXPECT_FALSE(mt.isType<orxonox::ColourValue>());
+        EXPECT_FALSE(mt.isType<orxonox::Quaternion>());
+        EXPECT_FALSE(mt.isType<orxonox::Radian>());
+        EXPECT_FALSE(mt.isType<orxonox::Degree>());
+    }
+
+    TEST(MultiType, IsTypeUnsignedInt)
+    {
+        MultiType mt(1u);
+
+        EXPECT_FALSE(mt.isType<void>());
+        EXPECT_FALSE(mt.isType<char>());
+        EXPECT_FALSE(mt.isType<unsigned char>());
+        EXPECT_FALSE(mt.isType<short>());
+        EXPECT_FALSE(mt.isType<unsigned short>());
+        EXPECT_FALSE(mt.isType<int>());
+        EXPECT_TRUE(mt.isType<unsigned int>());
+        EXPECT_FALSE(mt.isType<long>());
+        EXPECT_FALSE(mt.isType<unsigned long>());
+        EXPECT_FALSE(mt.isType<long long>());
+        EXPECT_FALSE(mt.isType<unsigned long long>());
+        EXPECT_FALSE(mt.isType<float>());
+        EXPECT_FALSE(mt.isType<double>());
+        EXPECT_FALSE(mt.isType<long double>());
+        EXPECT_FALSE(mt.isType<bool>());
+        EXPECT_FALSE(mt.isType<void*>());
+        EXPECT_FALSE(mt.isType<std::string>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector2>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector3>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector4>());
+        EXPECT_FALSE(mt.isType<orxonox::ColourValue>());
+        EXPECT_FALSE(mt.isType<orxonox::Quaternion>());
+        EXPECT_FALSE(mt.isType<orxonox::Radian>());
+        EXPECT_FALSE(mt.isType<orxonox::Degree>());
+    }
+
+    TEST(MultiType, IsTypeDouble)
+    {
+        MultiType mt(1.0);
+
+        EXPECT_FALSE(mt.isType<void>());
+        EXPECT_FALSE(mt.isType<char>());
+        EXPECT_FALSE(mt.isType<unsigned char>());
+        EXPECT_FALSE(mt.isType<short>());
+        EXPECT_FALSE(mt.isType<unsigned short>());
+        EXPECT_FALSE(mt.isType<int>());
+        EXPECT_FALSE(mt.isType<unsigned int>());
+        EXPECT_FALSE(mt.isType<long>());
+        EXPECT_FALSE(mt.isType<unsigned long>());
+        EXPECT_FALSE(mt.isType<long long>());
+        EXPECT_FALSE(mt.isType<unsigned long long>());
+        EXPECT_FALSE(mt.isType<float>());
+        EXPECT_TRUE(mt.isType<double>());
+        EXPECT_FALSE(mt.isType<long double>());
+        EXPECT_FALSE(mt.isType<bool>());
+        EXPECT_FALSE(mt.isType<void*>());
+        EXPECT_FALSE(mt.isType<std::string>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector2>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector3>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector4>());
+        EXPECT_FALSE(mt.isType<orxonox::ColourValue>());
+        EXPECT_FALSE(mt.isType<orxonox::Quaternion>());
+        EXPECT_FALSE(mt.isType<orxonox::Radian>());
+        EXPECT_FALSE(mt.isType<orxonox::Degree>());
+    }
+
+    TEST(MultiType, IsTypeString)
+    {
+        MultiType mt("1");
+
+        EXPECT_FALSE(mt.isType<void>());
+        EXPECT_FALSE(mt.isType<char>());
+        EXPECT_FALSE(mt.isType<unsigned char>());
+        EXPECT_FALSE(mt.isType<short>());
+        EXPECT_FALSE(mt.isType<unsigned short>());
+        EXPECT_FALSE(mt.isType<int>());
+        EXPECT_FALSE(mt.isType<unsigned int>());
+        EXPECT_FALSE(mt.isType<long>());
+        EXPECT_FALSE(mt.isType<unsigned long>());
+        EXPECT_FALSE(mt.isType<long long>());
+        EXPECT_FALSE(mt.isType<unsigned long long>());
+        EXPECT_FALSE(mt.isType<float>());
+        EXPECT_FALSE(mt.isType<double>());
+        EXPECT_FALSE(mt.isType<long double>());
+        EXPECT_FALSE(mt.isType<bool>());
+        EXPECT_FALSE(mt.isType<void*>());
+        EXPECT_TRUE(mt.isType<std::string>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector2>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector3>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector4>());
+        EXPECT_FALSE(mt.isType<orxonox::ColourValue>());
+        EXPECT_FALSE(mt.isType<orxonox::Quaternion>());
+        EXPECT_FALSE(mt.isType<orxonox::Radian>());
+        EXPECT_FALSE(mt.isType<orxonox::Degree>());
+    }
+
+    TEST(MultiType, IsTypeDegree)
+    {
+        MultiType mt(Degree(1));
+
+        EXPECT_FALSE(mt.isType<void>());
+        EXPECT_FALSE(mt.isType<char>());
+        EXPECT_FALSE(mt.isType<unsigned char>());
+        EXPECT_FALSE(mt.isType<short>());
+        EXPECT_FALSE(mt.isType<unsigned short>());
+        EXPECT_FALSE(mt.isType<int>());
+        EXPECT_FALSE(mt.isType<unsigned int>());
+        EXPECT_FALSE(mt.isType<long>());
+        EXPECT_FALSE(mt.isType<unsigned long>());
+        EXPECT_FALSE(mt.isType<long long>());
+        EXPECT_FALSE(mt.isType<unsigned long long>());
+        EXPECT_FALSE(mt.isType<float>());
+        EXPECT_FALSE(mt.isType<double>());
+        EXPECT_FALSE(mt.isType<long double>());
+        EXPECT_FALSE(mt.isType<bool>());
+        EXPECT_FALSE(mt.isType<void*>());
+        EXPECT_FALSE(mt.isType<std::string>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector2>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector3>());
+        EXPECT_FALSE(mt.isType<orxonox::Vector4>());
+        EXPECT_FALSE(mt.isType<orxonox::ColourValue>());
+        EXPECT_FALSE(mt.isType<orxonox::Quaternion>());
+        EXPECT_FALSE(mt.isType<orxonox::Radian>());
+        EXPECT_TRUE(mt.isType<orxonox::Degree>());
+    }
+
+    ////////////////////////////////
+    // lastConversionSuccessful() //
+    ////////////////////////////////
+    TEST(MultiType, LastConversionSuccessful)
+    {
+        MultiType mt;
+
+        EXPECT_TRUE(mt.lastConversionSuccessful());
+
+        mt = 5.55;
+
+        EXPECT_TRUE(mt.lastConversionSuccessful());
+
+        mt.convert<int>();
+
+        EXPECT_TRUE(mt.lastConversionSuccessful());
+
+        mt.convert<Vector3>();
+
+        EXPECT_FALSE(mt.lastConversionSuccessful());
+
+        mt.convert<std::string>();
+
+        EXPECT_TRUE(mt.lastConversionSuccessful());
+    }
+
+    ////////////
+    // null() //
+    ////////////
+    TEST(MultiType, Null1)
+    {
+        MultiType mt;
+
+        EXPECT_TRUE(mt.null());
+
+        mt = 5;
+
+        EXPECT_FALSE(mt.null());
+    }
+
+    TEST(MultiType, Null2)
+    {
+        MultiType mt(5);
+
+        EXPECT_FALSE(mt.null());
+
+        mt.reset();
+
+        EXPECT_TRUE(mt.null());
+    }
+
+    ///////////////////////////////
+    // Strongly typed enum class //
+    ///////////////////////////////
+    enum class EnumWithChar : unsigned char
+    {
+        ValueA = 'A',
+        ValueB = 'B',
+        ValueC = 'C',
+    };
+    enum class EnumWithInt
+    {
+        Value1 = 50,
+        Value2 = 0,
+        Value3,
+    };
+
+    TEST(MultiType, Enum_Constructor)
+    {
+        // Constructor:
+        {
+            MultiType mt = EnumWithChar::ValueA;
+
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_EQ(EnumWithChar::ValueA, mt.get<EnumWithChar>());
+        }
+        {
+            MultiType mt = MultiType(EnumWithInt::Value1);
+
+            EXPECT_TRUE(mt.isType<EnumWithInt>());
+            EXPECT_EQ(EnumWithInt::Value1, mt.get<EnumWithInt>());
+        }
+    }
+
+    TEST(MultiType, Enum_Assignment)
+    {
+        // operator=:
+        MultiType mt;
+        mt = EnumWithChar::ValueB;
+
+        EXPECT_TRUE(mt.isType<EnumWithChar>());
+        EXPECT_EQ(EnumWithChar::ValueB, mt.get<EnumWithChar>());
+    }
+
+    TEST(MultiType, Enum_Set)
+    {
+        // set(value):
+        {
+            MultiType mt;
+            mt.set(EnumWithInt::Value2); // assign enum to an empty MultiType
+
+            EXPECT_TRUE(mt.isType<EnumWithInt>());
+            EXPECT_EQ(EnumWithInt::Value2, mt.get<EnumWithInt>());
+        }
+        {
+            MultiType mt = "string";
+            mt.set(EnumWithChar::ValueC); // assign enum to a MultiType with type std::string
+
+            EXPECT_TRUE(mt.isType<std::string>());
+            EXPECT_EQ("C", mt.get<std::string>());
+        }
+        {
+            MultiType mt = EnumWithChar::ValueA;
+            mt.set(EnumWithChar::ValueB); // assign enum to a MultiType with type std::string
+
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_EQ(EnumWithChar::ValueB, mt.get<EnumWithChar>());
+        }
+        {
+            MultiType mt = EnumWithInt::Value3;
+            mt.set("50"); // assign enum to a MultiType with type std::string
+
+            EXPECT_TRUE(mt.isType<EnumWithInt>());
+            EXPECT_EQ(EnumWithInt::Value1, mt.get<EnumWithInt>());
+        }
+    }
+
+    TEST(MultiType, Enum_Force)
+    {
+        // force(value):
+        {
+            MultiType mt = "string";
+            EXPECT_TRUE(mt.isType<std::string>());
+            EXPECT_EQ("string", mt.get<std::string>());
+
+            mt.force<EnumWithChar>("C");
+
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_EQ(EnumWithChar::ValueC, mt.get<EnumWithChar>());
+        }
+        {
+            MultiType mt = EnumWithChar::ValueA;
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_EQ(EnumWithChar::ValueA, mt.get<EnumWithChar>());
+
+            mt.force<std::string>(EnumWithChar::ValueB);
+
+            EXPECT_TRUE(mt.isType<std::string>());
+            EXPECT_EQ("B", mt.get<std::string>());
+        }
+    }
+
+    TEST(MultiType, Enum_Convert)
+    {
+        // convert():
+        {
+            MultiType mt = "C";
+            mt.convert<EnumWithChar>();
+
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_EQ(EnumWithChar::ValueC, mt.get<EnumWithChar>());
+        }
+        {
+            MultiType mt = EnumWithChar::ValueA;
+            mt.convert<std::string>();
+
+            EXPECT_TRUE(mt.isType<std::string>());
+            EXPECT_EQ("A", mt.get<std::string>());
+        }
+    }
+
+    TEST(MultiType, Enum_Reset)
+    {
+        // reset():
+        {
+            MultiType mt = EnumWithChar::ValueA;
+            mt.reset<EnumWithChar>();
+
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_TRUE(mt.isType<unsigned char>());
+            EXPECT_EQ('\0', mt.get<unsigned char>());
+        }
+        {
+            MultiType mt = "string";
+            mt.reset<EnumWithInt>();
+
+            EXPECT_TRUE(mt.isType<EnumWithInt>());
+            EXPECT_TRUE(mt.isType<int>());
+            EXPECT_EQ(0, mt.get<int>());
+        }
+    }
+
+    TEST(MultiType, Enum_IsType)
+    {
+        // isType():
+        {
+            MultiType mt = EnumWithChar::ValueB;
+            EXPECT_TRUE(mt.isType<EnumWithChar>());
+            EXPECT_TRUE(mt.isType<unsigned char>());
+            EXPECT_FALSE(mt.isType<char>());
+            EXPECT_FALSE(mt.isType<int>());
+            EXPECT_FALSE(mt.isType<bool>());
+            EXPECT_FALSE(mt.isType<std::string>());
+        }
+        {
+            MultiType mt = EnumWithInt::Value3;
+            EXPECT_TRUE(mt.isType<EnumWithInt>());
+            EXPECT_TRUE(mt.isType<int>());
+            EXPECT_FALSE(mt.isType<unsigned char>());
+            EXPECT_FALSE(mt.isType<char>());
+            EXPECT_FALSE(mt.isType<bool>());
+            EXPECT_FALSE(mt.isType<std::string>());
+        }
+    }
+
+    TEST(MultiType, Enum_ConversionOperator)
+    {
+        // conversion operator:
+        {
+            MultiType mt = EnumWithChar::ValueA;
+            EnumWithChar value = mt;
+            EXPECT_EQ(EnumWithChar::ValueA, value);
+        }
+        {
+            MultiType mt = 'B';
+            EnumWithChar value = mt;
+            EXPECT_EQ(EnumWithChar::ValueB, value);
+        }
+        {
+            MultiType mt = EnumWithInt::Value1;
+            std::string value = mt;
+            EXPECT_EQ("50", value);
+        }
+    }
+
+    TEST(MultiType, Enum_GetValue)
+    {
+        // getValue():
+        {
+            MultiType mt = EnumWithChar::ValueA;
+            EnumWithChar value;
+            mt.getValue(&value);
+            EXPECT_EQ(EnumWithChar::ValueA, value);
+        }
+        {
+            MultiType mt = 'B';
+            EnumWithChar value;
+            mt.getValue(&value);
+            EXPECT_EQ(EnumWithChar::ValueB, value);
+        }
+        {
+            MultiType mt = EnumWithInt::Value1;
+            std::string value;
+            mt.getValue(&value);
+            EXPECT_EQ("50", value);
+        }
+    }
+
+    TEST(MultiType, Enum_Get)
+    {
+        // get():
+        {
+            MultiType mt = EnumWithChar::ValueB;
+            EXPECT_EQ(EnumWithChar::ValueB, mt.get<EnumWithChar>());
+
+            EXPECT_EQ('B', mt.get<unsigned char>());
+            EXPECT_EQ("B", mt.get<std::string>());
+            EXPECT_EQ(66, mt.get<int>());
+            EXPECT_TRUE(mt.get<bool>());
+        }
+        {
+            MultiType mt = EnumWithInt::Value1;
+            EXPECT_EQ(EnumWithInt::Value1, mt.get<EnumWithInt>());
+
+            EXPECT_EQ('2', mt.get<unsigned char>());
+            EXPECT_EQ("50", mt.get<std::string>());
+            EXPECT_EQ(50, mt.get<int>());
+            EXPECT_TRUE(mt.get<bool>());
+        }
+        {
+            MultiType mt = EnumWithInt::Value2;
+            EXPECT_EQ(EnumWithInt::Value2, mt.get<EnumWithInt>());
+
+            EXPECT_EQ('\0', mt.get<unsigned char>());
+            EXPECT_EQ("0", mt.get<std::string>());
+            EXPECT_EQ(0, mt.get<int>());
+            EXPECT_FALSE(mt.get<bool>());
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/OutputTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/OutputTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/OutputTest.cc	(revision 11817)
@@ -0,0 +1,49 @@
+#include <gtest/gtest.h>
+#include "util/Output.h"
+
+namespace orxonox
+{
+    namespace context
+    {
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(unittest);
+        }
+    }
+
+    TEST(OutputTest, CanUseOrxout)
+    {
+        orxout() << "test" << endl;
+    }
+
+    TEST(OutputTest, OrxoutUsesCorrectOutputLevel)
+    {
+        {
+            const OutputStream& stream = orxout(internal_warning);
+            EXPECT_EQ(internal_warning, stream.getOutputLevel());
+        }
+
+        {
+            const OutputStream& stream = orxout(debug_output);
+            EXPECT_EQ(debug_output, stream.getOutputLevel());
+        }
+    }
+
+    TEST(OutputTest, OrxoutUsesCorrectOutputContext)
+    {
+        const OutputStream& stream = orxout(verbose, context::unittest());
+        EXPECT_EQ(verbose, stream.getOutputLevel());
+        EXPECT_EQ(context::unittest().mask, stream.getOutputContext()->mask);
+        EXPECT_EQ(context::unittest().name, stream.getOutputContext()->name);
+        EXPECT_EQ(context::unittest().sub_id, stream.getOutputContext()->sub_id);
+    }
+
+    TEST(OutputTest, OrxoutAcceptsFunctionPointer)
+    {
+        const OutputStream& stream = orxout(verbose, context::unittest);
+        EXPECT_EQ(verbose, stream.getOutputLevel());
+        EXPECT_EQ(context::unittest().mask, stream.getOutputContext()->mask);
+        EXPECT_EQ(context::unittest().name, stream.getOutputContext()->name);
+        EXPECT_EQ(context::unittest().sub_id, stream.getOutputContext()->sub_id);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/SharedPtrTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/SharedPtrTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/SharedPtrTest.cc	(revision 11817)
@@ -0,0 +1,269 @@
+#include <memory>
+#include <utility>
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestClass
+        {
+            public:
+                TestClass() : value_(0) {}
+                virtual ~TestClass() {}
+
+                void setValue(int value) { this->value_ = value; }
+                int getValue() const { return this->value_; }
+
+            private:
+                int value_;
+        };
+
+        class TestChildClass : public TestClass
+        {
+            public:
+                TestChildClass() {}
+                virtual ~TestChildClass() {}
+        };
+
+        class TestChildClassMock : public TestChildClass
+        {
+            public:
+                TestChildClassMock() {}
+                ~TestChildClassMock() { objectDestroyed(); }
+
+                MOCK_METHOD0(objectDestroyed, void());
+        };
+    }
+
+    TEST(SharedPtr, ConstructorDefault)
+    {
+        std::shared_ptr<TestClass> test;
+        EXPECT_EQ(nullptr, test.get());
+    }
+
+    TEST(SharedPtr, ConstructorPointer)
+    {
+        TestClass* pointer = new TestClass();
+
+        std::shared_ptr<TestClass> test(pointer);
+        EXPECT_EQ(pointer, test.get());
+        EXPECT_EQ(pointer, &(*test));
+    }
+
+    TEST(SharedPtr, ConstructorChildPointer)
+    {
+        TestChildClass* pointer = new TestChildClass();
+
+        std::shared_ptr<TestClass> test(pointer);
+        EXPECT_EQ(pointer, test.get());
+    }
+
+    TEST(SharedPtr, ConstructorOther)
+    {
+        TestClass* pointer = new TestClass();
+
+        std::shared_ptr<TestClass> other(pointer);
+        EXPECT_EQ(pointer, other.get());
+
+        std::shared_ptr<TestClass> test = other;
+        EXPECT_EQ(pointer, test.get());
+    }
+
+    TEST(SharedPtr, ConstructorOtherChild)
+    {
+        TestChildClass* pointer = new TestChildClass();
+
+        std::shared_ptr<TestChildClass> other(pointer);
+        EXPECT_EQ(pointer, other.get());
+
+        std::shared_ptr<TestClass> test = other;
+        EXPECT_EQ(pointer, test.get());
+    }
+
+    TEST(SharedPtr, Assign)
+    {
+        TestClass* pointer = new TestClass();
+
+        std::shared_ptr<TestClass> other(pointer);
+        EXPECT_EQ(pointer, other.get());
+
+        std::shared_ptr<TestClass> test;
+        EXPECT_EQ(nullptr, test.get());
+
+        test = other;
+        EXPECT_EQ(pointer, test.get());
+    }
+
+    TEST(SharedPtr, AssignChild)
+    {
+        TestChildClass* pointer = new TestChildClass();
+
+        std::shared_ptr<TestChildClass> other(pointer);
+        EXPECT_EQ(pointer, other.get());
+
+        std::shared_ptr<TestClass> test;
+        EXPECT_EQ(nullptr, test.get());
+
+        test = other;
+        EXPECT_EQ(pointer, test.get());
+    }
+
+    TEST(SharedPtr, Cast)
+    {
+        TestChildClass* pointer = new TestChildClass();
+
+        std::shared_ptr<TestChildClass> other(pointer);
+        EXPECT_EQ(pointer, other.get());
+
+        std::shared_ptr<TestClass> test = std::static_pointer_cast<TestClass>(other);
+        EXPECT_EQ(pointer, test.get());
+    }
+
+    TEST(SharedPtr, Access)
+    {
+        TestClass* pointer = new TestClass();
+
+        std::shared_ptr<TestClass> test(pointer);
+        EXPECT_EQ(pointer, test.get());
+
+        EXPECT_EQ(0, test->getValue());
+        test->setValue(5);
+        EXPECT_EQ(5, test->getValue());
+        EXPECT_EQ(5, (*test).getValue());
+    }
+
+    TEST(SharedPtr, Boolean)
+    {
+        std::shared_ptr<TestClass> test;
+        EXPECT_EQ(nullptr, test.get());
+        EXPECT_FALSE(test);
+
+        TestClass* pointer = new TestClass();
+
+        test.reset(pointer);
+        EXPECT_EQ(pointer, test.get());
+        EXPECT_TRUE(static_cast<bool>(test));
+    }
+
+    TEST(SharedPtr, Swap)
+    {
+        TestClass* pointer1 = new TestClass();
+        TestClass* pointer2 = new TestClass();
+
+        std::shared_ptr<TestClass> test1(pointer1);
+        std::shared_ptr<TestClass> test2(pointer2);
+
+        EXPECT_EQ(pointer1, test1.get());
+        EXPECT_EQ(pointer2, test2.get());
+
+        test1.swap(test2);
+
+        EXPECT_EQ(pointer2, test1.get());
+        EXPECT_EQ(pointer1, test2.get());
+    }
+
+    TEST(SharedPtr, ObjectDestroyedOnePointer)
+    {
+        TestChildClassMock* pointer = new TestChildClassMock();
+        std::shared_ptr<TestClass> test(pointer);
+
+        EXPECT_CALL(*pointer, objectDestroyed()).Times(1);
+    }
+
+    TEST(SharedPtr, ObjectDestroyedManyPointers)
+    {
+        TestChildClassMock* pointer = new TestChildClassMock();
+
+        std::shared_ptr<TestClass> test(pointer);
+        std::vector<std::shared_ptr<TestClass>> tests;
+        for (size_t i = 0; i < 100; ++i)
+            tests.push_back(std::shared_ptr<TestClass>(test));
+
+        EXPECT_CALL(*pointer, objectDestroyed()).Times(1);
+    }
+
+    TEST(SharedPtr, TestConstructors)
+    {
+        {
+        TestChildClassMock* pointer = new TestChildClassMock();
+
+        // default
+        std::shared_ptr<TestChildClass> sharedPtr1;
+        EXPECT_EQ(nullptr, sharedPtr1.get());
+
+        // pointer
+        std::shared_ptr<TestChildClass> sharedPtr2(pointer);
+        EXPECT_EQ(pointer, sharedPtr2.get());
+
+        // copy
+        std::shared_ptr<TestChildClass> sharedPtr3(sharedPtr2);
+        EXPECT_EQ(pointer, sharedPtr3.get());
+
+        // move
+        std::shared_ptr<TestChildClass> sharedPtr4(std::move(sharedPtr3));
+        EXPECT_EQ(pointer, sharedPtr4.get());
+
+        // other
+        std::shared_ptr<TestClass> sharedPtr5(sharedPtr4);
+        EXPECT_EQ(pointer, sharedPtr5.get());
+
+        EXPECT_CALL(*pointer, objectDestroyed()).Times(1);
+        }
+    }
+
+    TEST(SharedPtr, TestConstructors2)
+    {
+        {
+        TestChildClassMock* pointer = new TestChildClassMock();
+
+        // default
+        std::shared_ptr<TestChildClass> sharedPtr1;
+        EXPECT_EQ(nullptr, sharedPtr1.get());
+
+        // pointer
+        std::shared_ptr<TestChildClass> sharedPtr2(pointer);
+        EXPECT_EQ(pointer, sharedPtr2.get());
+
+        // copy
+        std::shared_ptr<TestChildClass> sharedPtr3 = sharedPtr2;
+        EXPECT_EQ(pointer, sharedPtr3.get());
+
+        // move
+        std::shared_ptr<TestChildClass> sharedPtr4 = std::move(sharedPtr3);
+        EXPECT_EQ(pointer, sharedPtr4.get());
+
+        // other
+        std::shared_ptr<TestClass> sharedPtr5 = sharedPtr4;
+        EXPECT_EQ(pointer, sharedPtr5.get());
+
+        EXPECT_CALL(*pointer, objectDestroyed()).Times(1);
+        }
+    }
+
+    TEST(SharedPtr, TestAssignments)
+    {
+        TestChildClassMock* pointer = new TestChildClassMock();
+
+        std::shared_ptr<TestChildClass> sharedPtr1(pointer);
+        EXPECT_EQ(pointer, sharedPtr1.get());
+
+        // copy
+        std::shared_ptr<TestChildClass> sharedPtr2;
+        sharedPtr2 = sharedPtr1;
+        EXPECT_EQ(pointer, sharedPtr2.get());
+
+        // move
+        std::shared_ptr<TestChildClass> sharedPtr3;
+        sharedPtr3 = std::move(sharedPtr2);
+        EXPECT_EQ(pointer, sharedPtr3.get());
+
+        // other
+        std::shared_ptr<TestClass> sharedPtr4;
+        sharedPtr4 = sharedPtr3;
+        EXPECT_EQ(pointer, sharedPtr4.get());
+
+        EXPECT_CALL(*pointer, objectDestroyed()).Times(1);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/SingletonTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/SingletonTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/SingletonTest.cc	(revision 11817)
@@ -0,0 +1,84 @@
+#include <gtest/gtest.h>
+#include "util/Singleton.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class TestSingleton : public Singleton<TestSingleton>
+        {
+            friend class Singleton<TestSingleton>;
+
+            public:
+                TestSingleton() : value_(MAGIC_VALUE) {}
+                virtual ~TestSingleton() {}
+
+                size_t getValue() const { return this->value_; }
+
+                static const size_t MAGIC_VALUE;
+
+            private:
+                size_t value_;
+                static TestSingleton* singletonPtr_s;
+        };
+
+        TestSingleton* TestSingleton::singletonPtr_s = nullptr;
+        const size_t TestSingleton::MAGIC_VALUE = 0xCAFEBABE;
+    }
+
+    TEST(DISABLED_SingletonDeathTest, MustBeUnique)
+    {
+        // create first instance
+        TestSingleton* instance = new TestSingleton();
+        // create second instance, must abort
+        EXPECT_DEATH(new TestSingleton(), ".*");
+
+        delete instance;
+    }
+
+    TEST(DISABLED_SingletonDeathTest, MustBeCreated)
+    {
+        // no instance created, must abort
+        EXPECT_DEATH(TestSingleton::getInstance(), ".*");
+    }
+
+    TEST(DISABLED_SingletonDeathTest, MustBeReset)
+    {
+        // create instance
+        TestSingleton* instance = new TestSingleton();
+        // getInstance() must return newly created instance
+        EXPECT_EQ(instance, &TestSingleton::getInstance());
+
+        // delete instance
+        delete instance;
+        // must abort
+        EXPECT_DEATH(TestSingleton::getInstance(), ".*");
+    }
+
+    TEST(Singleton, MustBeTheSame)
+    {
+        // create instance
+        TestSingleton* instance = new TestSingleton();
+
+        EXPECT_EQ(instance, &TestSingleton::getInstance());
+        EXPECT_EQ(TestSingleton::MAGIC_VALUE, TestSingleton::getInstance().getValue());
+
+        // delete instance
+        delete instance;
+    }
+
+    TEST(Singleton, Exists)
+    {
+        EXPECT_FALSE(TestSingleton::exists());
+
+        // create instance
+        TestSingleton* instance = new TestSingleton();
+
+        EXPECT_TRUE(TestSingleton::exists());
+
+        // delete instance
+        delete instance;
+
+        EXPECT_FALSE(TestSingleton::exists());
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/SmallObjectAllocatorTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/SmallObjectAllocatorTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/SmallObjectAllocatorTest.cc	(revision 11817)
@@ -0,0 +1,282 @@
+#include <gtest/gtest.h>
+#include "util/SmallObjectAllocator.h"
+
+namespace orxonox
+{
+    //////////////////////////////////////////
+    // Allocate objects with primitive type //
+    //////////////////////////////////////////
+
+    class SmallObjectAllocatorTestInt : public testing::Test
+    {
+        public:
+            SmallObjectAllocatorTestInt() : allocator_(sizeof(size_t), 10)
+            {
+                SmallObjectAllocatorTestInt::count++;
+            }
+
+        protected:
+            size_t* create(size_t value)
+            {
+                void* chunk = this->allocator_.alloc();
+                size_t* pointer = new (chunk) size_t;
+                *pointer = value;
+
+                return pointer;
+            }
+
+            void destroy(size_t* pointer)
+            {
+                this->allocator_.free(pointer);
+            }
+
+            SmallObjectAllocator allocator_;
+            static size_t count;
+    };
+
+    size_t SmallObjectAllocatorTestInt::count = 0;
+
+    TEST_F(SmallObjectAllocatorTestInt, Default)
+    {
+        // Test if the fixture was created
+        EXPECT_EQ(1u, SmallObjectAllocatorTestInt::count);
+    }
+
+    TEST_F(SmallObjectAllocatorTestInt, Create)
+    {
+        // create an integer
+        size_t* pointer = this->create(5);
+        ASSERT_NE((void*)nullptr, pointer);
+        EXPECT_EQ(5u, *pointer);
+    }
+
+    TEST_F(SmallObjectAllocatorTestInt, CreateAndDestroy)
+    {
+        // create an integer
+        size_t* pointer = this->create(5);
+        ASSERT_NE((void*)nullptr, pointer);
+        EXPECT_EQ(5u, *pointer);
+
+        // destroy it again
+        this->destroy(pointer);
+    }
+
+    TEST_F(SmallObjectAllocatorTestInt, Create100)
+    {
+        std::vector<size_t*> pointers;
+
+        // create 100 integers. this is greater than the amount of chunks per block, hence the allocator has to allocate multiple blocks
+        static const size_t LIMIT = 100;
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            size_t* pointer = this->create(i);
+            EXPECT_EQ(i, *pointer);
+            pointers.push_back(pointer);
+        }
+
+        EXPECT_EQ(LIMIT, pointers.size());
+
+        // check if all integers are still valid
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            EXPECT_EQ(i, *pointers[i]);
+        }
+    }
+
+    TEST_F(SmallObjectAllocatorTestInt, Create100Destroy50)
+    {
+        std::vector<size_t*> pointers;
+
+        // create 100 integers
+        static const size_t LIMIT = 100;
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            size_t* pointer = this->create(i);
+            EXPECT_EQ(i, *pointer);
+            pointers.push_back(pointer);
+        }
+
+        EXPECT_EQ(LIMIT, pointers.size());
+
+        // destroy the first 50
+        for (size_t i = 0; i < LIMIT / 2; ++i)
+        {
+            this->destroy(pointers[i]);
+        }
+
+        // check if the remaining integers are still valid
+        for (size_t i = LIMIT / 2; i < LIMIT; ++i)
+        {
+            EXPECT_EQ(i, *pointers[i]);
+        }
+    }
+
+    TEST_F(SmallObjectAllocatorTestInt, Create100Destroy50Create100)
+    {
+        std::vector<size_t*> pointers;
+
+        // create 100 integers
+        static const size_t LIMIT = 100;
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            size_t* pointer = this->create(i);
+            EXPECT_EQ(i, *pointer);
+            pointers.push_back(pointer);
+        }
+
+        EXPECT_EQ(LIMIT, pointers.size());
+
+        // destroy the first 50
+        for (size_t i = 0; i < LIMIT / 2; ++i)
+        {
+            this->destroy(pointers[i]);
+        }
+
+        // create 100 more integers
+        for (size_t i = LIMIT; i < LIMIT * 2; ++i)
+        {
+            size_t* pointer = this->create(i);
+            EXPECT_EQ(i, *pointer);
+            pointers.push_back(pointer);
+        }
+
+        EXPECT_EQ(LIMIT * 2, pointers.size());
+
+        // check if the remaining and the new integers are valid
+        for (size_t i = LIMIT / 2; i < LIMIT * 2; ++i)
+        {
+            EXPECT_EQ(i, *pointers[i]);
+        }
+    }
+
+
+    /////////////////////////////////////////////////////
+    // Allocate objects which are instances of a class //
+    /////////////////////////////////////////////////////
+
+    class SmallObjectAllocatorTestObject : public testing::Test
+    {
+        protected:
+            class SmallObject
+            {
+                public:
+                    static size_t total_s;
+
+                    SmallObject(size_t value)
+                    {
+                        this->value_ = value;
+                        SmallObject::total_s += this->value_;
+                    }
+
+                    ~SmallObject()
+                    {
+                        SmallObject::total_s -= this->value_;
+                    }
+
+                    size_t getValue() const
+                    {
+                        return this->value_;
+                    }
+
+                private:
+                    size_t value_;
+            };
+
+        public:
+            SmallObjectAllocatorTestObject() : allocator_(sizeof(SmallObject), 10)
+            {
+                SmallObjectAllocatorTestObject::count++;
+                SmallObject::total_s = 0;
+            }
+
+        protected:
+            SmallObject* create(size_t value)
+            {
+                // allocate memory
+                void* chunk = this->allocator_.alloc();
+                // execute placement new operator
+                SmallObject* pointer = new (chunk) SmallObject(value);
+
+                return pointer;
+            }
+
+            void destroy(SmallObject* pointer)
+            {
+                // call destructor
+                pointer->~SmallObject();
+                // free memory
+                this->allocator_.free(pointer);
+            }
+
+            SmallObjectAllocator allocator_;
+            static size_t count;
+    };
+
+    size_t SmallObjectAllocatorTestObject::count = 0;
+    size_t SmallObjectAllocatorTestObject::SmallObject::total_s = 0;
+
+    TEST_F(SmallObjectAllocatorTestObject, Default)
+    {
+        // Test if the fixture was created
+        EXPECT_EQ(1u, SmallObjectAllocatorTestObject::count);
+    }
+
+    TEST_F(SmallObjectAllocatorTestObject, Create)
+    {
+        EXPECT_EQ(0u, SmallObject::total_s);
+
+        // create an object
+        SmallObject* pointer = this->create(5);
+        ASSERT_NE((void*)nullptr, pointer);
+        EXPECT_EQ(5u, pointer->getValue());
+        EXPECT_EQ(5u, SmallObject::total_s);
+    }
+
+    TEST_F(SmallObjectAllocatorTestObject, CreateAndDestroy)
+    {
+        EXPECT_EQ(0u, SmallObject::total_s);
+
+        // create an object
+        SmallObject* pointer = this->create(5);
+        ASSERT_NE((void*)nullptr, pointer);
+        EXPECT_EQ(5u, pointer->getValue());
+        EXPECT_EQ(5u, SmallObject::total_s);
+
+        // destroy it again
+        this->destroy(pointer);
+        EXPECT_EQ(0u, SmallObject::total_s);
+    }
+
+    TEST_F(SmallObjectAllocatorTestObject, CreateAndDestroy100)
+    {
+        std::vector<SmallObject*> pointers;
+
+        // create 100 objects. this is greater than the amount of chunks per block, hence the allocator has to allocate multiple blocks
+        static const size_t LIMIT = 100;
+        size_t total = 0;
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            SmallObject* pointer = this->create(i);
+            EXPECT_EQ(i, pointer->getValue());
+            pointers.push_back(pointer);
+            total += i;
+        }
+
+        EXPECT_EQ(LIMIT, pointers.size());
+        EXPECT_EQ(total, SmallObject::total_s);
+
+        // check if all objects are still valid
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            EXPECT_EQ(i, pointers[i]->getValue());
+        }
+
+        // destroy all objects
+        for (size_t i = 0; i < LIMIT; ++i)
+        {
+            this->destroy(pointers[i]);
+        }
+
+        EXPECT_EQ(0u, SmallObject::total_s);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/StringUtilsTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/StringUtilsTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/StringUtilsTest.cc	(revision 11817)
@@ -0,0 +1,355 @@
+#include <gtest/gtest.h>
+#include "util/StringUtils.h"
+
+namespace orxonox
+{
+    TEST(StringUtils, BLANKSTRING)
+    {
+        EXPECT_EQ("", BLANKSTRING);
+    }
+
+    TEST(StringUtils, getUniqueNumberString)
+    {
+        std::set<std::string> numberStrings;
+
+        const size_t iterations = 1000;
+
+        for (size_t i = 0; i < iterations; ++i)
+            numberStrings.insert(getUniqueNumberString());
+
+        // must have exactly <iterations> entries in the set, since all strings should be unique
+        EXPECT_EQ(iterations, numberStrings.size());
+    }
+
+//    _UtilExport std::string  getStripped(const std::string& str);
+    TEST(StringUtils, getStripped)
+    {
+        EXPECT_EQ("", getStripped(""));
+        EXPECT_EQ("test", getStripped("test"));
+        EXPECT_EQ("test", getStripped("te st"));
+        EXPECT_EQ("test", getStripped("   test"));
+        EXPECT_EQ("test", getStripped("test  "));
+        EXPECT_EQ("test", getStripped("   test   "));
+        EXPECT_EQ("test", getStripped("   t  e  s  t   "));
+        EXPECT_EQ("test", getStripped("  \t te \n\n\n  st\n"));
+    }
+
+//    _UtilExport std::string  removeTrailingWhitespaces(const std::string& str);
+    TEST(StringUtils, removeTrailingWhitespaces)
+    {
+        EXPECT_EQ("", removeTrailingWhitespaces(""));
+        EXPECT_EQ("test", removeTrailingWhitespaces("test"));
+        EXPECT_EQ("test", removeTrailingWhitespaces("   test"));
+        EXPECT_EQ("test", removeTrailingWhitespaces("test"));
+        EXPECT_EQ("test", removeTrailingWhitespaces("   test   "));
+        EXPECT_EQ("test", removeTrailingWhitespaces(" \t  test  \n "));
+        EXPECT_EQ("te  st", removeTrailingWhitespaces("te  st"));
+        EXPECT_EQ("te  st", removeTrailingWhitespaces("   te  st   "));
+        EXPECT_EQ("Hel lo\nWo rld", removeTrailingWhitespaces(" \t Hel lo\nWo rld \n"));
+    }
+
+//    _UtilExport void         vectorize(const std::string& str, char delimiter, std::vector<std::string>* output);
+    TEST(StringUtils, vectorize)
+    {
+        std::vector<std::string> output;
+        vectorize("this is a test", ' ', &output);
+        ASSERT_EQ(4u, output.size());
+        EXPECT_EQ("this", output[0]);
+        EXPECT_EQ("is", output[1]);
+        EXPECT_EQ("a", output[2]);
+        EXPECT_EQ("test", output[3]);
+
+        vectorize("this is a test", 't', &output);
+        ASSERT_EQ(4u, output.size());
+        EXPECT_EQ("", output[0]);
+        EXPECT_EQ("his is a ", output[1]);
+        EXPECT_EQ("es", output[2]);
+        EXPECT_EQ("", output[3]);
+    }
+
+//    _UtilExport size_t       getNextQuote(const std::string& str, size_t start = 0);
+    TEST(StringUtils, getNextQuote)
+    {
+        EXPECT_EQ(std::string::npos, getNextQuote(""));
+        EXPECT_EQ(std::string::npos, getNextQuote("text"));
+        EXPECT_EQ(0u, getNextQuote("\"text"));
+        EXPECT_EQ(4u, getNextQuote("text\""));
+        EXPECT_EQ(std::string::npos, getNextQuote("\\\"text"));
+        EXPECT_EQ(std::string::npos, getNextQuote("text\\\""));
+        EXPECT_EQ(3u, getNextQuote("012\"456\"89", 0));
+        EXPECT_EQ(7u, getNextQuote("012\"456\"89", 5));
+    }
+
+//    _UtilExport bool         isBetweenQuotes(const std::string& str, size_t pos);
+    TEST(StringUtils, isBetweenQuotes)
+    {
+        EXPECT_FALSE(isBetweenQuotes("", 0));
+
+        EXPECT_FALSE(isBetweenQuotes("abc", 0));
+        EXPECT_FALSE(isBetweenQuotes("abc", 1));
+        EXPECT_FALSE(isBetweenQuotes("abc", 2));
+        EXPECT_FALSE(isBetweenQuotes("abc", 3));
+
+        EXPECT_FALSE(isBetweenQuotes("\"abc", 0));
+        EXPECT_FALSE(isBetweenQuotes("\"abc", 1));
+        EXPECT_FALSE(isBetweenQuotes("\"abc", 2));
+        EXPECT_FALSE(isBetweenQuotes("\"abc", 3));
+
+        EXPECT_FALSE(isBetweenQuotes("abc\"", 0));
+        EXPECT_FALSE(isBetweenQuotes("abc\"", 1));
+        EXPECT_FALSE(isBetweenQuotes("abc\"", 2));
+        EXPECT_FALSE(isBetweenQuotes("abc\"", 3));
+
+        EXPECT_FALSE(isBetweenQuotes("\"abc\"", 0));
+        EXPECT_TRUE(isBetweenQuotes("\"abc\"", 1));
+        EXPECT_TRUE(isBetweenQuotes("\"abc\"", 2));
+        EXPECT_TRUE(isBetweenQuotes("\"abc\"", 3));
+        EXPECT_FALSE(isBetweenQuotes("\"abc\"", 4));
+
+        //                            012 3456 7890
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 0));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 1));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 2));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 3));
+        EXPECT_TRUE(isBetweenQuotes("abc\"abc\"abc", 4));
+        EXPECT_TRUE(isBetweenQuotes("abc\"abc\"abc", 5));
+        EXPECT_TRUE(isBetweenQuotes("abc\"abc\"abc", 6));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 7));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 8));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 9));
+        EXPECT_FALSE(isBetweenQuotes("abc\"abc\"abc", 10));
+    }
+
+//    _UtilExport bool         hasStringBetweenQuotes(const std::string& str);
+    TEST(StringUtils, hasStringBetweenQuotes)
+    {
+        EXPECT_FALSE(hasStringBetweenQuotes(""));
+        EXPECT_FALSE(hasStringBetweenQuotes("test"));
+        EXPECT_FALSE(hasStringBetweenQuotes("\"test"));
+        EXPECT_FALSE(hasStringBetweenQuotes("te\"st"));
+        EXPECT_FALSE(hasStringBetweenQuotes("test\""));
+        EXPECT_TRUE(hasStringBetweenQuotes("\"test\""));
+        EXPECT_TRUE(hasStringBetweenQuotes("te\"st\""));
+        EXPECT_TRUE(hasStringBetweenQuotes("\"te\"st"));
+        EXPECT_FALSE(hasStringBetweenQuotes("te\"\"st"));
+        EXPECT_FALSE(hasStringBetweenQuotes("\"\"test"));
+        EXPECT_FALSE(hasStringBetweenQuotes("test\"\""));
+    }
+
+//    _UtilExport std::string  getStringBetweenQuotes(const std::string& str);
+    TEST(StringUtils, getStringBetweenQuotes)
+    {
+        EXPECT_EQ("", getStringBetweenQuotes(""));
+        EXPECT_EQ("", getStringBetweenQuotes("test"));
+        EXPECT_EQ("", getStringBetweenQuotes("\"test"));
+        EXPECT_EQ("", getStringBetweenQuotes("te\"st"));
+        EXPECT_EQ("", getStringBetweenQuotes("test\""));
+        EXPECT_EQ("test", getStringBetweenQuotes("\"test\""));
+        EXPECT_EQ("st", getStringBetweenQuotes("te\"st\""));
+        EXPECT_EQ("te", getStringBetweenQuotes("\"te\"st"));
+        EXPECT_EQ("", getStringBetweenQuotes("te\"\"st"));
+        EXPECT_EQ("", getStringBetweenQuotes("\"\"test"));
+        EXPECT_EQ("", getStringBetweenQuotes("test\"\""));
+    }
+
+//    _UtilExport std::string  stripEnclosingQuotes(const std::string& str);
+    TEST(StringUtils, stripEnclosingQuotes)
+    {
+        EXPECT_EQ("", stripEnclosingQuotes(""));
+        EXPECT_EQ("test", stripEnclosingQuotes("test"));
+        EXPECT_EQ(" test", stripEnclosingQuotes(" test"));
+        EXPECT_EQ("   test   ", stripEnclosingQuotes("   test   "));
+        EXPECT_EQ("\"test", stripEnclosingQuotes("\"test"));
+        EXPECT_EQ("test\"", stripEnclosingQuotes("test\""));
+        EXPECT_EQ(" \"test", stripEnclosingQuotes(" \"test"));
+        EXPECT_EQ("test\" ", stripEnclosingQuotes("test\" "));
+        EXPECT_EQ("test", stripEnclosingQuotes("\"test\""));
+        EXPECT_EQ("test", stripEnclosingQuotes("  \"test\"  "));
+        EXPECT_EQ("a  \"test\"  ", stripEnclosingQuotes("a  \"test\"  "));
+    }
+
+//    _UtilExport std::string  stripEnclosingBraces(const std::string& str);
+    TEST(StringUtils, stripEnclosingBraces)
+    {
+        EXPECT_EQ("", stripEnclosingBraces(""));
+        EXPECT_EQ("test", stripEnclosingBraces("test"));
+        EXPECT_EQ("{test", stripEnclosingBraces("{test"));
+        EXPECT_EQ("test}", stripEnclosingBraces("test}"));
+        EXPECT_EQ("t{es}t", stripEnclosingBraces("t{es}t"));
+        EXPECT_EQ(" {test}", stripEnclosingBraces(" {test}"));
+        EXPECT_EQ("}test}", stripEnclosingBraces("}test}"));
+        EXPECT_EQ("{test{", stripEnclosingBraces("{test{"));
+        EXPECT_EQ("test", stripEnclosingBraces("{test}"));
+    }
+
+//    _UtilExport bool         isEmpty(const std::string& str);
+    TEST(StringUtils, isEmpty)
+    {
+        EXPECT_TRUE(isEmpty(""));
+        EXPECT_TRUE(isEmpty(" "));
+        EXPECT_TRUE(isEmpty("       "));
+        EXPECT_TRUE(isEmpty("\t"));
+        EXPECT_TRUE(isEmpty("\n"));
+        EXPECT_TRUE(isEmpty(" \t\n\t\n  \t"));
+        EXPECT_FALSE(isEmpty("a"));
+        EXPECT_FALSE(isEmpty("test"));
+        EXPECT_FALSE(isEmpty("    a   "));
+    }
+
+//    _UtilExport bool         isComment(const std::string& str);
+    TEST(StringUtils, isComment)
+    {
+        EXPECT_FALSE(isComment(""));
+        EXPECT_FALSE(isComment("test"));
+        EXPECT_TRUE(isComment("#test"));
+        EXPECT_TRUE(isComment("%test"));
+        EXPECT_TRUE(isComment(";test"));
+        EXPECT_TRUE(isComment("//test"));
+        EXPECT_FALSE(isComment("/test"));
+
+        EXPECT_TRUE(isComment("        #test"));
+        EXPECT_TRUE(isComment("      %test"));
+        EXPECT_TRUE(isComment("    ;test"));
+        EXPECT_TRUE(isComment("  //test"));
+    }
+
+//    _UtilExport std::string  addSlashes(const std::string& str);
+    TEST(StringUtils, addSlashes)
+    {
+        EXPECT_EQ("", addSlashes(""));
+        EXPECT_EQ("test", addSlashes("test"));
+        EXPECT_EQ("test\\ntest", addSlashes("test\ntest"));
+        EXPECT_EQ("\\n\\t\\r\\f\\a\\b\\v\\\"\\\\", addSlashes("\n\t\r\f\a\b\v\"\\"));
+    }
+
+//    _UtilExport std::string  removeSlashes(const std::string& str);
+    TEST(StringUtils, removeSlashes)
+    {
+        EXPECT_EQ("", removeSlashes(""));
+        EXPECT_EQ("test", removeSlashes("test"));
+        EXPECT_EQ("test\ntest", removeSlashes("test\\ntest"));
+        EXPECT_EQ("\n\t\r\f\a\b\v\"\\", removeSlashes("\\n\\t\\r\\f\\a\\b\\v\\\"\\\\"));
+    }
+
+//    _UtilExport std::string  getLowercase(const std::string& str);
+    TEST(StringUtils, getLowercase)
+    {
+        EXPECT_EQ("", getLowercase(""));
+        EXPECT_EQ("test", getLowercase("test"));
+        EXPECT_EQ("test", getLowercase("Test"));
+        EXPECT_EQ("test", getLowercase("TeSt"));
+        EXPECT_EQ("test", getLowercase("TEST"));
+        EXPECT_EQ("a test b", getLowercase("a TEST b"));
+    }
+
+//    _UtilExport std::string  getUppercase(const std::string& str);
+    TEST(StringUtils, getUppercase)
+    {
+        EXPECT_EQ("", getUppercase(""));
+        EXPECT_EQ("TEST", getUppercase("test"));
+        EXPECT_EQ("TEST", getUppercase("Test"));
+        EXPECT_EQ("TEST", getUppercase("TeSt"));
+        EXPECT_EQ("TEST", getUppercase("TEST"));
+        EXPECT_EQ("A TEST B", getUppercase("A test B"));
+    }
+
+//    _UtilExport int          nocaseCmp(const std::string& s1, const std::string& s2);
+    TEST(StringUtils, nocaseCmp)
+    {
+        EXPECT_EQ(0, nocaseCmp("", ""));
+        EXPECT_EQ(0, nocaseCmp("a", "a"));
+        EXPECT_EQ(0, nocaseCmp("a", "A"));
+        EXPECT_EQ(0, nocaseCmp("A", "a"));
+        EXPECT_EQ(0, nocaseCmp("A", "A"));
+        EXPECT_EQ(0, nocaseCmp("test", "test"));
+        EXPECT_EQ(0, nocaseCmp("test", "TEST"));
+        EXPECT_EQ(0, nocaseCmp("tESt", "test"));
+        EXPECT_EQ(0, nocaseCmp("TesT", "teST"));
+
+        EXPECT_EQ(strcmp("a", "b") < 0, nocaseCmp("a", "b") < 0);
+        EXPECT_EQ(strcmp("b", "a") > 0, nocaseCmp("b", "a") > 0);
+        EXPECT_EQ(strcmp("hello", "world") < 0, nocaseCmp("hello", "world") < 0);
+    }
+
+//    _UtilExport int          nocaseCmp(const std::string& s1, const std::string& s2, size_t len);
+    TEST(StringUtils, nocaseCmpWithLen)
+    {
+        EXPECT_EQ(0, nocaseCmp("test", "TEST", 0));
+        EXPECT_EQ(0, nocaseCmp("test", "TEST", 1));
+        EXPECT_EQ(0, nocaseCmp("test", "TEST", 2));
+        EXPECT_EQ(0, nocaseCmp("test", "TEST", 3));
+        EXPECT_EQ(0, nocaseCmp("test", "TEST", 4));
+        EXPECT_EQ(0, nocaseCmp("test", "TEST", 5));
+    }
+
+//    _UtilExport bool         hasComment(const std::string& str);
+    TEST(StringUtils, hasComment)
+    {
+        EXPECT_FALSE(hasComment(""));
+        EXPECT_FALSE(hasComment("test"));
+        EXPECT_FALSE(hasComment(" asdf / asdf "));
+        EXPECT_TRUE(hasComment("#test"));
+        EXPECT_TRUE(hasComment(" %test"));
+        EXPECT_TRUE(hasComment("test ;test"));
+        EXPECT_TRUE(hasComment("test // test // test"));
+    }
+
+//    _UtilExport std::string  getComment(const std::string& str);
+    TEST(StringUtils, getComment)
+    {
+        EXPECT_EQ("", getComment(""));
+        EXPECT_EQ("", getComment("test"));
+        EXPECT_EQ("", getComment(" asdf / asdf "));
+        EXPECT_EQ("#test", getComment("#test"));
+        EXPECT_EQ(" %test", getComment(" %test"));
+        EXPECT_EQ(" ;test", getComment("test ;test"));
+        EXPECT_EQ(" // test // test", getComment("test // test // test"));
+    }
+
+//    _UtilExport size_t       getNextCommentPosition(const std::string& str, size_t start = 0);
+    TEST(StringUtils, getNextCommentPosition)
+    {
+        EXPECT_EQ(std::string::npos, getNextCommentPosition(""));
+        EXPECT_EQ(std::string::npos, getNextCommentPosition("test"));
+        EXPECT_EQ(std::string::npos, getNextCommentPosition(" asdf / asdf "));
+        EXPECT_EQ(0u, getNextCommentPosition("#test"));
+        EXPECT_EQ(0u, getNextCommentPosition(" %test"));
+        EXPECT_EQ(4u, getNextCommentPosition("test ;test"));
+        EXPECT_EQ(4u, getNextCommentPosition("test // test // test"));
+
+        EXPECT_EQ(std::string::npos, getNextCommentPosition("", 10));
+        EXPECT_EQ(std::string::npos, getNextCommentPosition("test", 10));
+        EXPECT_EQ(std::string::npos, getNextCommentPosition(" asdf / asdf ", 3));
+        EXPECT_EQ(std::string::npos, getNextCommentPosition("#test", 1));
+        EXPECT_EQ(1u, getNextCommentPosition(" %test", 1));
+        EXPECT_EQ(5u, getNextCommentPosition("test ;test", 5));
+        EXPECT_EQ(12u, getNextCommentPosition("test // test // test", 6));
+    }
+
+//    _UtilExport size_t       replaceCharacters(std::string& str, char target, char replacement);
+    TEST(StringUtils, replaceCharacters)
+    {
+        std::string test1 = "test";
+        EXPECT_EQ(1u, replaceCharacters(test1, 'e', '3'));
+        EXPECT_EQ("t3st", test1);
+
+        std::string test2 = "test";
+        EXPECT_EQ(2u, replaceCharacters(test2, 't', '1'));
+        EXPECT_EQ("1es1", test2);
+    }
+
+//    _UtilExport unsigned int getLevenshteinDistance(const std::string& str1, const std::string& str2);
+    TEST(StringUtils, getLevenshteinDistance)
+    {
+        EXPECT_EQ(0u, getLevenshteinDistance("test", "test"));
+        EXPECT_EQ(1u, getLevenshteinDistance("test", "tes"));
+        EXPECT_EQ(1u, getLevenshteinDistance("test", "testt"));
+        EXPECT_EQ(1u, getLevenshteinDistance("test", "t3st"));
+        EXPECT_EQ(1u, getLevenshteinDistance("test", "te1st"));
+        EXPECT_EQ(2u, getLevenshteinDistance("test", "1es1"));
+        EXPECT_EQ(3u, getLevenshteinDistance("test", "1es11"));
+        EXPECT_EQ(4u, getLevenshteinDistance("test", "blub"));
+        EXPECT_EQ(5u, getLevenshteinDistance("test", "abcde"));
+        EXPECT_EQ(6u, getLevenshteinDistance("test", "abcdef"));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/SubStringTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/SubStringTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/SubStringTest.cc	(revision 11817)
@@ -0,0 +1,191 @@
+#include <gtest/gtest.h>
+#include "util/SubString.h"
+
+namespace orxonox
+{
+    TEST(SubString, Empty)
+    {
+        SubString test;
+        EXPECT_TRUE(test.empty());
+        EXPECT_EQ(0u, test.size());
+    }
+
+    TEST(SubString, CreateSimple)
+    {
+        SubString test("This is a test");
+        EXPECT_FALSE(test.empty());
+        ASSERT_EQ(4u, test.size());
+
+        EXPECT_EQ("This", test[0]);
+        EXPECT_EQ("is", test[1]);
+        EXPECT_EQ("a", test[2]);
+        EXPECT_EQ("test", test[3]);
+
+        EXPECT_EQ("This", test.getString(0));
+        EXPECT_EQ("is", test.getString(1));
+        EXPECT_EQ("a", test.getString(2));
+        EXPECT_EQ("test", test.getString(3));
+
+        EXPECT_EQ("This", test.front());
+        EXPECT_EQ("test", test.back());
+    }
+
+    TEST(SubString, CreateDelimiter)
+    {
+        SubString test1("This|is|a|test");
+        EXPECT_EQ(1u, test1.size());
+
+        SubString test2("This|is|a|test", "|");
+        EXPECT_EQ(4u, test2.size());
+
+        SubString test3("This|is|a|test", "|e");
+        EXPECT_EQ(5u, test3.size());
+    }
+
+    TEST(SubString, CreateDelimiterNeighbours)
+    {
+        SubString test1("This | is | a | test", "|");
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ(" a ", test1[2]);
+
+        SubString test2("This | is | a | test", "|", " ");
+        EXPECT_EQ(4u, test2.size());
+        EXPECT_EQ("a", test2[2]);
+    }
+
+    TEST(SubString, CreateAllowEmptyEntries)
+    {
+        SubString test1("This |  | is |  | a ||| test", "|", " ");
+        EXPECT_EQ(4u, test1.size());
+
+        SubString test2("This |  | is |  | a ||| test", "|", " ", true);
+        EXPECT_EQ(8u, test2.size());
+    }
+
+    TEST(SubString, CreateEscapeChar)
+    {
+        SubString test1("This is a test", SubString::WhiteSpaces, "", false, '\\', true);
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ("is", test1[1]);
+
+        SubString test2("This is\\ a test", SubString::WhiteSpaces, "", false, '\\', true);
+        EXPECT_EQ(3u, test2.size());
+        EXPECT_EQ("is a", test2[1]);
+
+        SubString test3("This is\\ a test", SubString::WhiteSpaces, "", false, '\\', false);
+        EXPECT_EQ(3u, test3.size());
+        EXPECT_EQ("is\\ a", test3[1]);
+    }
+
+    TEST(SubString, CreateSafemodeChar)
+    {
+        SubString test1("This is a test", SubString::WhiteSpaces, "", false, '\\', true, '"', true);
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ("is", test1[1]);
+
+        SubString test2("This \"is a\" test", SubString::WhiteSpaces, "", false, '\\', true, '"', true);
+        EXPECT_EQ(3u, test2.size());
+        EXPECT_EQ("is a", test2[1]);
+
+        SubString test3("This \"is a\" test", SubString::WhiteSpaces, "", false, '\\', true, '"', false);
+        EXPECT_EQ(3u, test3.size());
+        EXPECT_EQ("\"is a\"", test3[1]);
+    }
+
+    TEST(SubString, CreateParenthesisChars)
+    {
+        SubString test1("This is a test", SubString::WhiteSpaces, "", false, '\\', true, '"', true, '{', '}', true);
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ("is", test1[1]);
+
+        SubString test2("This {is a} test", SubString::WhiteSpaces, "", false, '\\', true, '"', true, '{', '}', true);
+        EXPECT_EQ(3u, test2.size());
+        EXPECT_EQ("is a", test2[1]);
+
+        SubString test3("This {is a} test", SubString::WhiteSpaces, "", false, '\\', true, '"', true, '{', '}', false);
+        EXPECT_EQ(3u, test3.size());
+        EXPECT_EQ("{is a}", test3[1]);
+    }
+
+    TEST(SubString, Compare)
+    {
+        SubString test1("This is a test");
+        SubString test2("This is a test");
+        SubString test3("This is not a test");
+
+        EXPECT_TRUE(test1 == test2);
+        EXPECT_TRUE(test1.compare(test2));
+
+        EXPECT_FALSE(test1 == test3);
+        EXPECT_FALSE(test1.compare(test3));
+
+        EXPECT_FALSE(test1.compare(test3, 100));
+        EXPECT_FALSE(test1.compare(test3, 4));
+        EXPECT_FALSE(test1.compare(test3, 3));
+        EXPECT_TRUE(test1.compare(test3, 2));
+        EXPECT_TRUE(test1.compare(test3, 1));
+        EXPECT_TRUE(test1.compare(test3, 0));
+    }
+
+    TEST(SubString, Assign)
+    {
+        SubString test1("This is a test");
+        SubString test2("Hello World");
+
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ(2u, test2.size());
+        EXPECT_FALSE(test1 == test2);
+
+        test2 = test1;
+
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ(4u, test2.size());
+        EXPECT_TRUE(test1 == test2);
+    }
+
+    TEST(SubString, Append)
+    {
+        SubString test1("This is a test");
+        SubString test2("Hello World");
+
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ(2u, test2.size());
+
+        test1 += test2;
+
+        EXPECT_EQ(6u, test1.size());
+        EXPECT_EQ(2u, test2.size());
+    }
+
+    TEST(SubString, Join)
+    {
+        SubString test1("This is a test");
+
+        EXPECT_EQ("This is a test", test1.join());
+        EXPECT_EQ("This|is|a|test", test1.join("|"));
+        EXPECT_EQ("This123is123a123test", test1.join("123"));
+
+        SubString test2("Hello World");
+
+        EXPECT_EQ("Hello World", test2.join());
+
+        test1 += test2;
+
+        EXPECT_EQ("This is a test Hello World", test1.join());
+    }
+
+    TEST(SubString, Subset)
+    {
+        SubString test1("This is a test");
+        EXPECT_EQ(4u, test1.size());
+        EXPECT_EQ("This is a test", test1.join());
+
+        SubString test2 = test1.subSet(1);
+        ASSERT_EQ(3u, test2.size());
+        EXPECT_EQ("is a test", test2.join());
+
+        SubString test3 = test1.subSet(1, 2);
+        ASSERT_EQ(2u, test3.size());
+        EXPECT_EQ("is a", test3.join());
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/VA_NARGSTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/VA_NARGSTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/VA_NARGSTest.cc	(revision 11817)
@@ -0,0 +1,62 @@
+#include <gtest/gtest.h>
+#include "util/VA_NARGS.h"
+
+TEST(VA_NARGS, DirectCall)
+{
+    //EXPECT_EQ(0, ORXONOX_VA_NARGS()); // documented issue of the macro - min number of elements is 1
+
+    EXPECT_EQ(1, ORXONOX_VA_NARGS(some));
+    EXPECT_EQ(2, ORXONOX_VA_NARGS(some, argument));
+    EXPECT_EQ(3, ORXONOX_VA_NARGS(some, argument, to));
+    EXPECT_EQ(4, ORXONOX_VA_NARGS(some, argument, to, test));
+    EXPECT_EQ(5, ORXONOX_VA_NARGS(some, argument, to, test, the));
+    EXPECT_EQ(6, ORXONOX_VA_NARGS(some, argument, to, test, the, macro));
+}
+
+
+#define TEST_MACRO_CONSTANT(...) \
+    BOOST_PP_EXPAND(BOOST_PP_CAT(TEST_MACRO_CONSTANT, ORXONOX_VA_NARGS(__VA_ARGS__)))
+
+#define TEST_MACRO_CONSTANT0 000
+#define TEST_MACRO_CONSTANT1 100
+#define TEST_MACRO_CONSTANT2 200
+#define TEST_MACRO_CONSTANT3 300
+#define TEST_MACRO_CONSTANT4 400
+#define TEST_MACRO_CONSTANT5 500
+#define TEST_MACRO_CONSTANT6 600
+
+TEST(VA_NARGS, MacroConstant)
+{
+    //EXPECT_EQ(000, TEST_MACRO_CONSTANT()); // documented issue of the macro - min number of elements is 1
+
+    EXPECT_EQ(100, TEST_MACRO_CONSTANT(some));
+    EXPECT_EQ(200, TEST_MACRO_CONSTANT(some, argument));
+    EXPECT_EQ(300, TEST_MACRO_CONSTANT(some, argument, to));
+    EXPECT_EQ(400, TEST_MACRO_CONSTANT(some, argument, to, test));
+    EXPECT_EQ(500, TEST_MACRO_CONSTANT(some, argument, to, test, the));
+    EXPECT_EQ(600, TEST_MACRO_CONSTANT(some, argument, to, test, the, macro));
+}
+
+
+#define TEST_MACRO_FUNCTION(...) \
+    BOOST_PP_EXPAND(BOOST_PP_CAT(TEST_MACRO_FUNCTION, ORXONOX_VA_NARGS(__VA_ARGS__))(__VA_ARGS__))
+
+#define TEST_MACRO_FUNCTION0(...) 000
+#define TEST_MACRO_FUNCTION1(...) 100
+#define TEST_MACRO_FUNCTION2(...) 200
+#define TEST_MACRO_FUNCTION3(...) 300
+#define TEST_MACRO_FUNCTION4(...) 400
+#define TEST_MACRO_FUNCTION5(...) 500
+#define TEST_MACRO_FUNCTION6(...) 600
+
+TEST(VA_NARGS, MacroFunction)
+{
+    //EXPECT_EQ(000, TEST_MACRO_FUNCTION()); // documented issue of the macro - min number of elements is 1
+
+    EXPECT_EQ(100, TEST_MACRO_FUNCTION(some));
+    EXPECT_EQ(200, TEST_MACRO_FUNCTION(some, argument));
+    EXPECT_EQ(300, TEST_MACRO_FUNCTION(some, argument, to));
+    EXPECT_EQ(400, TEST_MACRO_FUNCTION(some, argument, to, test));
+    EXPECT_EQ(500, TEST_MACRO_FUNCTION(some, argument, to, test, the));
+    EXPECT_EQ(600, TEST_MACRO_FUNCTION(some, argument, to, test, the, macro));
+}
Index: /code/branches/RacingBots_FS18/test/util/mboolTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/mboolTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/mboolTest.cc	(revision 11817)
@@ -0,0 +1,105 @@
+#include <gtest/gtest.h>
+#include "util/mbool.h"
+
+namespace orxonox
+{
+    TEST(mbool, Create)
+    {
+        // default constructor
+        mbool test1;
+        EXPECT_FALSE((bool)test1);
+
+        // initialize with false
+        mbool test2(false);
+        EXPECT_FALSE((bool)test2);
+
+        // initialize with true
+        mbool test3(true);
+        EXPECT_TRUE((bool)test3);
+
+        // copy constructor
+        mbool test4(test2);
+        EXPECT_FALSE((bool)test4);
+
+        // copy constructor
+        mbool test5(test3);
+        EXPECT_TRUE((bool)test5);
+
+        // default constructor & assignment
+        mbool test6;
+        test6 = test2;
+        EXPECT_FALSE((bool)test6);
+
+        // default constructor & assignment
+        mbool test7;
+        test7 = test3;
+        EXPECT_TRUE((bool)test7);
+    }
+
+    TEST(mbool, Compare)
+    {
+        mbool test1(false);
+        mbool test2(true);
+        mbool test3(false);
+        mbool test4(true);
+
+        EXPECT_NE(test1, test2);
+        EXPECT_EQ(test1, test3);
+        EXPECT_EQ(test2, test4);
+
+        EXPECT_FALSE(test1 == true);
+        EXPECT_TRUE (test1 != true);
+        EXPECT_FALSE(test1 == test2);
+        EXPECT_TRUE (test1 != test2);
+        EXPECT_TRUE (test1 == false);
+        EXPECT_FALSE(test1 != false);
+        EXPECT_TRUE (test1 == test3);
+        EXPECT_FALSE(test1 != test3);
+
+
+        EXPECT_FALSE(test2 == false);
+        EXPECT_TRUE (test2 != false);
+        EXPECT_FALSE(test2 == test1);
+        EXPECT_TRUE (test2 != test1);
+        EXPECT_TRUE (test2 == true);
+        EXPECT_FALSE(test2 != true);
+        EXPECT_TRUE (test2 == test4);
+        EXPECT_FALSE(test2 != test4);
+
+        EXPECT_EQ(!test1, true);
+        EXPECT_EQ(!test2, false);
+    }
+
+    TEST(mbool, Assign)
+    {
+        mbool test(false);
+        mbool test_false = false;
+        mbool test_true = true;
+
+        EXPECT_EQ(test, false);        // eq because initialized with false
+        EXPECT_NE(test, true);         // "
+        EXPECT_EQ(test, test_false);   // eq because both initialized with false
+        EXPECT_NE(test, test_true);    // ne because initialized differently
+
+        test = false; // expect no change after assigning false again
+
+        EXPECT_EQ(test, false);        // no change, so still the same
+        EXPECT_NE(test, true);         // "
+        EXPECT_EQ(test, test_false);   // "
+        EXPECT_NE(test, test_true);    // "
+
+        test = true; // expect change after assigning true
+
+        EXPECT_NE(test, false);        // ne because assigned true
+        EXPECT_EQ(test, true);         // eq "
+        EXPECT_NE(test, test_false);   // ne "
+        EXPECT_EQ(test, test_true);    // eq "
+
+        test = false; // expect change after assigning false again
+
+        EXPECT_EQ(test, false);        // eq because assigned false again
+        EXPECT_NE(test, true);         // ne "
+        EXPECT_NE(test, test_false);   // ne because changed state in between, so internal memory differs !!!!!
+        EXPECT_NE(test, test_true);    // ne because assigned false again
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/BaseWriterTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/BaseWriterTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/BaseWriterTest.cc	(revision 11817)
@@ -0,0 +1,176 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "util/Output.h"
+#include "util/output/BaseWriter.h"
+#include "util/output/OutputManager.h"
+
+namespace orxonox
+{
+    namespace context
+    {
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(unittest1);
+            REGISTER_OUTPUT_CONTEXT(unittest2);
+            REGISTER_OUTPUT_CONTEXT(unittest3);
+
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub1);
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub2);
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub3);
+        }
+    }
+
+    namespace
+    {
+        class MockBaseWriter : public BaseWriter
+        {
+            public:
+                MockBaseWriter(const std::string& name, bool bRegister = true) : BaseWriter(name, bRegister) {}
+
+                MOCK_METHOD2(printLine, void(const std::string&, OutputLevel));
+
+                virtual void output(OutputLevel level, const OutputContextContainer& context, const std::vector<std::string>& lines) override
+                    { this->BaseWriter::output(level, context, lines); }
+        };
+    }
+
+    // test getName
+    TEST(BaseWriterTest, GetName)
+    {
+        MockBaseWriter writer("mytestname");
+        EXPECT_EQ("mytestname", writer.getName());
+    }
+
+    // test configurable names contain name
+    TEST(BaseWriterTest, ConfigurableNamesContainName)
+    {
+        MockBaseWriter writer("mytestname");
+        EXPECT_NE(writer.getConfigurableMaxLevelName().find(writer.getName()), std::string::npos);
+        EXPECT_NE(writer.getConfigurableAdditionalContextsMaxLevelName().find(writer.getName()), std::string::npos);
+        EXPECT_NE(writer.getConfigurableAdditionalContextsName().find(writer.getName()), std::string::npos);
+
+        // but the section name is 'static' (does not contain the name)
+        EXPECT_EQ(writer.getConfigurableSectionName().find(writer.getName()), std::string::npos);
+    }
+
+    // output calls printLine for each line
+    TEST(BaseWriterTest, OutputCallsPrintLine)
+    {
+        MockBaseWriter writer("mytestname");
+
+        std::vector<std::string> lines;
+        lines.push_back("line1");
+        lines.push_back("line2");
+
+        EXPECT_CALL(writer, printLine(::testing::_, level::debug_output)).Times(2);
+
+        writer.output(level::debug_output, context::undefined(), lines);
+    }
+
+    // output adds prefix to first line
+    TEST(BaseWriterTest, OutputAddsPrefixToFirstLine)
+    {
+        MockBaseWriter writer("mytestname");
+
+        std::vector<std::string> lines;
+        lines.push_back("line1");
+
+        std::string prefix = OutputManager::getInstance().getDefaultPrefix(level::debug_output, context::undefined());
+        EXPECT_CALL(writer, printLine(prefix + "line1", level::debug_output));
+
+        writer.output(level::debug_output, context::undefined(), lines);
+    }
+
+    // setLevelMax sets level max
+    void testLevelMaxUserWarning(OutputLevel mask)
+    {
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_TRUE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_TRUE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+        EXPECT_FALSE(mask & level::verbose);
+    }
+
+    TEST(BaseWriterTest, SetLevelMax)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.setLevelMax(level::user_warning);
+        testLevelMaxUserWarning(writer.getLevelMask());
+    }
+
+    // setAdditionalContextsLevelMax sets additional contexts level max
+    TEST(BaseWriterTest, SetAdditionalContextsLevelMax)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.setAdditionalContextsLevelMax(level::user_warning);
+        testLevelMaxUserWarning(writer.getAdditionalContextsLevelMask());
+    }
+
+    // changedConfigurableLevel sets max level to configurableMaxLevel_
+    TEST(BaseWriterTest, ChangedConfigurableLevel)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.configurableMaxLevel_ = level::user_warning;
+        writer.changedConfigurableLevel();
+
+        testLevelMaxUserWarning(writer.getLevelMask());
+    }
+
+    // changedConfigurableAdditionalContextsLevel sets additional contexts level max to configurableAdditionalContextsMaxLevel_
+    TEST(BaseWriterTest, ChangedConfigurableAdditionalContextsLevel)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.configurableAdditionalContextsMaxLevel_ = level::user_warning;
+        writer.changedConfigurableAdditionalContextsLevel();
+
+        testLevelMaxUserWarning(writer.getAdditionalContextsLevelMask());
+    }
+
+    // changedConfigurableAdditionalContexts sets additional contexts to configurableAdditionalContexts_
+    TEST(BaseWriterTest, ChangedConfigurableAdditionalContexts)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.configurableAdditionalContexts_.push_back("unittest1");
+        writer.changedConfigurableAdditionalContexts();
+
+        EXPECT_TRUE(writer.getAdditionalContextsMask() & context::unittest1().mask);
+    }
+
+    // contexts added by name
+    TEST(BaseWriterTest, DefineContextsByName)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.configurableAdditionalContexts_.push_back("unittest1");
+        writer.configurableAdditionalContexts_.push_back("unittest2");
+        writer.changedConfigurableAdditionalContexts();
+
+        EXPECT_TRUE(writer.acceptsOutput(level::message, context::unittest1()));
+        EXPECT_TRUE(writer.acceptsOutput(level::message, context::unittest2()));
+        EXPECT_FALSE(writer.acceptsOutput(level::message, context::unittest3()));
+    }
+
+    // subcontexts added by name, separated from base context with "::"
+    TEST(BaseWriterTest, DefineSubcontextsByName)
+    {
+        MockBaseWriter writer("mytestname");
+
+        writer.configurableAdditionalContexts_.push_back("unittest3::sub1");
+        writer.configurableAdditionalContexts_.push_back("unittest3::sub3");
+        writer.changedConfigurableAdditionalContexts();
+
+        EXPECT_FALSE(writer.acceptsOutput(level::message, context::unittest3()));
+        EXPECT_FALSE(writer.acceptsOutput(level::message, context::unittest3()));
+        EXPECT_FALSE(writer.acceptsOutput(level::message, context::unittest3()));
+        EXPECT_TRUE(writer.acceptsOutput(level::message, context::sub1()));
+        EXPECT_FALSE(writer.acceptsOutput(level::message, context::sub2()));
+        EXPECT_TRUE(writer.acceptsOutput(level::message, context::sub3()));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/ConsoleWriterTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/ConsoleWriterTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/ConsoleWriterTest.cc	(revision 11817)
@@ -0,0 +1,81 @@
+#include <gtest/gtest.h>
+#include "util/Output.h"
+#include "util/output/ConsoleWriter.h"
+#include "util/output/OutputManager.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        // Fixture
+        class ConsoleWriterTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    // reset output manager
+                    OutputManager::Testing::getInstancePointer().reset(new OutputManager());
+                }
+
+                virtual void TearDown() override
+                {
+                }
+        };
+    }
+
+    TEST_F(ConsoleWriterTest, Disable)
+    {
+        std::ostream stream(nullptr);
+        EXPECT_EQ(0U, OutputManager::getInstance().getListeners().size());
+        ConsoleWriter writer(stream);
+        EXPECT_EQ(1U, OutputManager::getInstance().getListeners().size());
+        writer.disable();
+        EXPECT_EQ(0U, OutputManager::getInstance().getListeners().size());
+    }
+
+    TEST_F(ConsoleWriterTest, Enable)
+    {
+        std::ostream stream(nullptr);
+        ConsoleWriter writer(stream);
+        writer.disable();
+        EXPECT_EQ(0U, OutputManager::getInstance().getListeners().size());
+        writer.enable();
+        EXPECT_EQ(1U, OutputManager::getInstance().getListeners().size());
+    }
+
+    TEST_F(ConsoleWriterTest, WritesNoOutputToOutputStream)
+    {
+        std::stringbuf buffer;
+        std::ostream stream(&buffer);
+        ConsoleWriter writer(stream);
+        writer.setLevelMax(level::verbose);
+
+        EXPECT_EQ(0, buffer.in_avail());
+        EXPECT_EQ("", buffer.str());
+    }
+
+    TEST_F(ConsoleWriterTest, WritesOutputToOutputStream)
+    {
+        std::stringbuf buffer;
+        std::ostream stream(&buffer);
+        ConsoleWriter writer(stream);
+        writer.setLevelMax(level::verbose);
+
+        std::vector<std::string> lines;
+        lines.push_back("test");
+
+        EXPECT_TRUE(writer.acceptsOutput(level::debug_output, context::undefined()));
+
+        writer.unfilteredOutput(level::debug_output, context::undefined(), lines);
+
+        EXPECT_LT(0, buffer.in_avail());
+        EXPECT_NE("", buffer.str());
+        EXPECT_NE(std::string::npos, buffer.str().find("test"));
+    }
+
+    TEST_F(ConsoleWriterTest, DefaultConsoleWriterUsesCout)
+    {
+        OutputManager::getInstanceAndCreateListeners();
+        EXPECT_EQ(&std::cout, &OutputManager::getInstance().getConsoleWriter()->getOutputStream());
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/LogWriterTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/LogWriterTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/LogWriterTest.cc	(revision 11817)
@@ -0,0 +1,245 @@
+#include <gtest/gtest.h>
+#include "util/Output.h"
+#include "util/output/LogWriter.h"
+#include "util/Convert.h"
+#include "util/output/OutputManager.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class MockLogWriter : public LogWriter
+        {
+            public:
+                virtual void printLine(const std::string& line, OutputLevel level) override
+                    { this->LogWriter::printLine(line, level); }
+        };
+
+        // Fixture
+        class LogWriterTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    // reset output manager
+                    OutputManager::Testing::getInstancePointer().reset(new OutputManager());
+                }
+
+                virtual void TearDown() override
+                {
+                }
+        };
+    }
+
+    // test constructor opens file
+    TEST_F(LogWriterTest, ConstructorOpensFile)
+    {
+        LogWriter logWriter;
+        EXPECT_TRUE(logWriter.getFile().is_open());
+    }
+
+    // setLogDirectory changes file, opens correct file
+    bool fileExists(const std::string& path)
+    {
+        std::ifstream stream(path.c_str());
+        bool exists = stream.is_open() && stream.good();
+        stream.close();
+        return exists;
+    }
+
+    std::string getLineWhichContains(const std::string& path, const std::string& message)
+    {
+        std::ifstream file(path.c_str());
+        EXPECT_TRUE(file.is_open());
+        EXPECT_TRUE(file.good());
+        EXPECT_FALSE(file.eof());
+
+        while (file.is_open() && file.good() && !file.eof())
+        {
+            std::string line;
+            std::getline(file, line);
+
+            // see if we find the output and return
+            if (line.find(message) == (line.size() - message.size()))
+                return line;
+        }
+
+        return std::string();
+    }
+
+    bool fileContains(const std::string& path, const std::string& message)
+    {
+        return !getLineWhichContains(path, message).empty();
+    }
+
+    bool deleteFile(const std::string& path)
+    {
+        bool result = std::remove(path.c_str()) == 0;
+        EXPECT_FALSE(fileExists(path));
+        return result;
+    }
+
+    TEST_F(LogWriterTest, SetLogDirectoryOpensNewFile)
+    {
+        std::string path = "./orxonox.log";
+
+        // cleanup before test
+        deleteFile(path);
+
+        {
+            LogWriter logWriter;
+            EXPECT_FALSE(fileExists(path));
+            logWriter.setLogDirectory(".");
+            EXPECT_TRUE(fileExists(path));
+        }
+
+        // cleanup after test
+        EXPECT_TRUE(deleteFile(path));
+    }
+
+    // prints output to logfile
+    TEST_F(LogWriterTest, PrintsOutputToLogfile)
+    {
+        std::string path;
+
+        {
+            // write lines to log file
+            std::vector<std::string> lines;
+            lines.push_back("mytestoutput");
+
+            LogWriter logWriter;
+            logWriter.setLogDirectory(".");
+            logWriter.unfilteredOutput(level::debug_output, context::undefined(), lines);
+
+            path = logWriter.getPath();
+        }
+
+        EXPECT_TRUE(fileContains(path, "mytestoutput"));
+    }
+
+    // prints time to logfile
+    TEST_F(LogWriterTest, PrintsTimestampToLogfile)
+    {
+        std::string path;
+
+        {
+            // write lines to log file
+            std::vector<std::string> lines;
+            lines.push_back("myothertestoutput");
+
+            LogWriter logWriter;
+            logWriter.setLogDirectory(".");
+            logWriter.unfilteredOutput(level::debug_output, context::undefined(), lines);
+
+            path = logWriter.getPath();
+        }
+
+        std::string line = getLineWhichContains(path, "myothertestoutput");
+        EXPECT_FALSE(line.empty());
+        ASSERT_TRUE(line.length() > 12);
+
+        EXPECT_TRUE(isdigit(line[0]));
+        EXPECT_TRUE(isdigit(line[1]));
+        EXPECT_EQ(':', line[2]);
+        EXPECT_TRUE(isdigit(line[3]));
+        EXPECT_TRUE(isdigit(line[4]));
+        EXPECT_EQ(':', line[5]);
+        EXPECT_TRUE(isdigit(line[6]));
+        EXPECT_TRUE(isdigit(line[7]));
+        EXPECT_EQ(':', line[8]);
+        EXPECT_TRUE(isdigit(line[9]));
+        EXPECT_TRUE(isdigit(line[10]));
+        EXPECT_TRUE(isdigit(line[11]));
+        EXPECT_EQ(' ', line[12]);
+    }
+
+    void deleteAllLogFiles()
+    {
+        std::string path;
+        {
+            LogWriter writer;
+            path = writer.getPath();
+        }
+
+        deleteFile(path);
+        deleteFile(path + ".1");
+        deleteFile(path + ".2");
+        deleteFile(path + ".3");
+        deleteFile(path + ".4");
+        deleteFile(path + ".5");
+        deleteFile(path + ".6");
+        deleteFile(path + ".7");
+        deleteFile(path + ".8");
+        deleteFile(path + ".9");
+    }
+
+    TEST_F(LogWriterTest, ArchivesOldLogFile)
+    {
+        deleteAllLogFiles();
+
+        std::string path;
+
+        {
+            MockLogWriter writer;
+            path = writer.getPath();
+            writer.printLine("test1", level::message);
+        }
+
+        EXPECT_TRUE(fileExists(path));
+        EXPECT_TRUE(fileContains(path, "test1"));
+        EXPECT_FALSE(fileExists(path + ".1"));
+        EXPECT_FALSE(fileExists(path + ".2"));
+        EXPECT_FALSE(fileExists(path + ".3"));
+
+        {
+            MockLogWriter writer;
+            writer.printLine("test2", level::message);
+        }
+
+        EXPECT_TRUE(fileExists(path));
+        EXPECT_TRUE(fileContains(path, "test2"));
+        EXPECT_TRUE(fileExists(path + ".1"));
+        EXPECT_TRUE(fileContains(path + ".1", "test1"));
+        EXPECT_FALSE(fileExists(path + ".2"));
+        EXPECT_FALSE(fileExists(path + ".3"));
+
+        {
+            MockLogWriter writer;
+            writer.printLine("test3", level::message);
+        }
+
+        EXPECT_TRUE(fileExists(path));
+        EXPECT_TRUE(fileContains(path, "test3"));
+        EXPECT_TRUE(fileExists(path + ".1"));
+        EXPECT_TRUE(fileContains(path + ".1", "test2"));
+        EXPECT_TRUE(fileExists(path + ".2"));
+        EXPECT_TRUE(fileContains(path + ".2", "test1"));
+        EXPECT_FALSE(fileExists(path + ".3"));
+    }
+
+    TEST_F(LogWriterTest, ArchivesNineLogFiles)
+    {
+        deleteAllLogFiles();
+
+        std::string path;
+        for (int i = 0; i < 20; ++i)
+        {
+            MockLogWriter writer;
+            path = writer.getPath();
+            writer.printLine("test" + multi_cast<std::string>(i), level::message);
+        }
+
+        EXPECT_TRUE(fileContains(path, "test19"));
+        EXPECT_TRUE(fileContains(path + ".1", "test18"));
+        EXPECT_TRUE(fileContains(path + ".2", "test17"));
+        EXPECT_TRUE(fileContains(path + ".3", "test16"));
+        EXPECT_TRUE(fileContains(path + ".4", "test15"));
+        EXPECT_TRUE(fileContains(path + ".5", "test14"));
+        EXPECT_TRUE(fileContains(path + ".6", "test13"));
+        EXPECT_TRUE(fileContains(path + ".7", "test12"));
+        EXPECT_TRUE(fileContains(path + ".8", "test11"));
+        EXPECT_TRUE(fileContains(path + ".9", "test10"));
+        EXPECT_FALSE(fileExists(path + ".10"));
+        EXPECT_FALSE(fileExists(path + ".11"));
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/MemoryWriterTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/MemoryWriterTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/MemoryWriterTest.cc	(revision 11817)
@@ -0,0 +1,61 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "util/Output.h"
+#include "util/output/MemoryWriter.h"
+#include "util/output/OutputManager.h"
+
+namespace orxonox
+{
+    namespace
+    {
+        class MockOutputListener : public OutputListener
+        {
+            public:
+                MOCK_METHOD3(output, void(OutputLevel, const OutputContextContainer&, const std::vector<std::string>&));
+        };
+
+        // Fixture
+        class MemoryWriterTest : public ::testing::Test
+        {
+            public:
+                virtual void SetUp() override
+                {
+                    // reset output manager
+                    OutputManager::Testing::getInstancePointer().reset(new OutputManager());
+                }
+
+                virtual void TearDown() override
+                {
+                }
+        };
+    }
+
+    TEST_F(MemoryWriterTest, Disable)
+    {
+        EXPECT_EQ(0U, OutputManager::getInstance().getListeners().size());
+        MemoryWriter writer;
+        EXPECT_EQ(1U, OutputManager::getInstance().getListeners().size());
+        writer.disable();
+        EXPECT_EQ(0U, OutputManager::getInstance().getListeners().size());
+    }
+
+    TEST_F(MemoryWriterTest, ResendOutput)
+    {
+        MemoryWriter writer;
+
+        std::vector<std::string> lines;
+        lines.push_back("random line of output");
+        lines.push_back("another line of output");
+
+        writer.unfilteredOutput(level::user_info, context::undefined(), lines);
+        writer.unfilteredOutput(level::verbose, context::xml(), lines);
+
+        MockOutputListener other;
+        other.setLevelMask(level::all);
+
+        EXPECT_CALL(other, output(level::user_info, context::undefined(), lines));
+        EXPECT_CALL(other, output(level::verbose, context::xml(), lines));
+
+        writer.resendOutput(&other);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/OutputDefinitionsTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/OutputDefinitionsTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/OutputDefinitionsTest.cc	(revision 11817)
@@ -0,0 +1,46 @@
+#include <gtest/gtest.h>
+#include "util/Output.h"
+
+namespace orxonox
+{
+    TEST(OutputDefinitionsTest, Levels)
+    {
+        EXPECT_EQ(0x0000, level::none);
+    }
+
+    TEST(OutputDefinitionsTest, OutputContextContainer)
+    {
+        OutputContextContainer container1;
+        container1.mask = 1;
+        container1.sub_id = 1;
+        container1.name = "1";
+
+        OutputContextContainer container2;
+        container2.mask = 1;
+        container2.sub_id = 1;
+        container2.name = "1";
+
+        EXPECT_TRUE(container1 == container2);
+
+        {
+            OutputContextContainer container3(container2);
+            EXPECT_TRUE(container1 == container3);
+            container3.mask = 2;
+            EXPECT_FALSE(container1 == container3);
+        }
+
+        {
+            OutputContextContainer container3(container2);
+            EXPECT_TRUE(container1 == container3);
+            container3.sub_id = 2;
+            EXPECT_FALSE(container1 == container3);
+        }
+
+        {
+            OutputContextContainer container3(container2);
+            EXPECT_TRUE(container1 == container3);
+            container3.name = "2";
+            EXPECT_FALSE(container1 == container3);
+        }
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/OutputListenerTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/OutputListenerTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/OutputListenerTest.cc	(revision 11817)
@@ -0,0 +1,375 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "util/output/OutputListener.h"
+#include "util/output/OutputManager.h"
+
+namespace orxonox
+{
+    namespace context
+    {
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(unittest1);
+            REGISTER_OUTPUT_CONTEXT(unittest2);
+            REGISTER_OUTPUT_CONTEXT(unittest3);
+        }
+    }
+
+    namespace
+    {
+        class MockOutputListener : public OutputListener
+        {
+            public:
+                MockOutputListener(bool bRegister = true) : OutputListener(bRegister) {}
+
+                MOCK_METHOD3(output, void(OutputLevel, const OutputContextContainer&, const std::vector<std::string>&));
+
+                inline const std::vector<AdditionalContextListener*>& getListeners() const
+                    { return OutputListener::getListeners(); }
+        };
+
+        class MockAdditionalContextListener : public AdditionalContextListener
+        {
+            public:
+                MOCK_METHOD1(updatedLevelMask, void(const OutputListener*));
+                MOCK_METHOD1(updatedAdditionalContextsLevelMask, void(const OutputListener*));
+                MOCK_METHOD1(updatedAdditionalContextsMask, void(const OutputListener*));
+        };
+
+        class MockOutputManager : public OutputManager
+        {
+            public:
+                MOCK_METHOD1(registerListener, void(OutputListener*));
+                MOCK_METHOD1(unregisterListener, void(OutputListener*));
+        };
+    }
+
+    // test default settings
+    TEST(OutputListenerTest, DefaultConstructorAcceptsNothing)
+    {
+        MockOutputListener listener;
+
+        EXPECT_EQ(level::none, listener.getLevelMask());
+        EXPECT_EQ(level::none, listener.getAdditionalContextsLevelMask());
+        EXPECT_EQ(context::none, listener.getAdditionalContextsMask());
+    }
+
+    // test setLevelMax
+    TEST(OutputListenerTest, SetLevelMax)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMax(level::user_warning);
+
+        OutputLevel mask = listener.getLevelMask();
+
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_TRUE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_TRUE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+    }
+
+    // test setLevelRange
+    TEST(OutputListenerTest, SetLevelRange)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelRange(level::debug_output, level::user_warning);
+
+        OutputLevel mask = listener.getLevelMask();
+
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_FALSE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_TRUE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+    }
+
+    // test setLevelMask
+    TEST(OutputListenerTest, SetLevelMask)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMask(static_cast<OutputLevel>(level::debug_output | level::user_warning));
+
+        OutputLevel mask = listener.getLevelMask();
+
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_FALSE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_FALSE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+    }
+
+    // test setAdditionalContextsLevelMax
+    TEST(OutputListenerTest, SetAdditionalContextsLevelMax)
+    {
+        MockOutputListener listener;
+
+        listener.setAdditionalContextsLevelMax(level::user_warning);
+
+        OutputLevel mask = listener.getAdditionalContextsLevelMask();
+
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_TRUE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_TRUE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+    }
+
+    // test setAdditionalContextsLevelRange
+    TEST(OutputListenerTest, SetAdditionalContextsLevelRange)
+    {
+        MockOutputListener listener;
+
+        listener.setAdditionalContextsLevelRange(level::debug_output, level::user_warning);
+
+        OutputLevel mask = listener.getAdditionalContextsLevelMask();
+
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_FALSE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_TRUE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+    }
+
+    // test setAdditionalContextsLevelMask
+    TEST(OutputListenerTest, SetAdditionalContextsLevelMask)
+    {
+        MockOutputListener listener;
+
+        listener.setAdditionalContextsLevelMask(static_cast<OutputLevel>(level::debug_output | level::user_warning));
+
+        OutputLevel mask = listener.getAdditionalContextsLevelMask();
+
+        EXPECT_FALSE(mask & level::none);
+        EXPECT_FALSE(mask & level::message);
+        EXPECT_TRUE(mask & level::debug_output);
+        EXPECT_FALSE(mask & level::user_error);
+        EXPECT_TRUE(mask & level::user_warning);
+        EXPECT_FALSE(mask & level::user_status);
+    }
+
+    // test setAdditionalContextsMask
+    TEST(OutputListenerTest, SetAdditionalContextsMask)
+    {
+        MockOutputListener listener;
+
+        listener.setAdditionalContextsMask(context::unittest1().mask | context::unittest3().mask);
+
+        OutputContextMask mask = listener.getAdditionalContextsMask();
+
+        EXPECT_TRUE(mask & context::unittest1().mask);
+        EXPECT_FALSE(mask & context::unittest2().mask);
+        EXPECT_TRUE(mask & context::unittest3().mask);
+    }
+
+    // test registerListener
+    TEST(OutputListenerTest, RegisterListener)
+    {
+        MockOutputListener outputListener(false);
+        MockAdditionalContextListener additionalContextListener;
+
+        EXPECT_EQ(0u, outputListener.getListeners().size());
+        outputListener.registerListener(&additionalContextListener);
+        EXPECT_EQ(1u, outputListener.getListeners().size());
+        EXPECT_EQ(&additionalContextListener, outputListener.getListeners()[0]);
+    }
+
+    // test unregisterListener
+    TEST(OutputListenerTest, UnregisterListener)
+    {
+        MockOutputListener outputListener(false);
+        MockAdditionalContextListener additionalContextListener;
+
+        outputListener.registerListener(&additionalContextListener);
+        EXPECT_EQ(1u, outputListener.getListeners().size());
+        EXPECT_EQ(&additionalContextListener, outputListener.getListeners()[0]);
+
+        outputListener.unregisterListener(&additionalContextListener);
+        EXPECT_EQ(0u, outputListener.getListeners().size());
+    }
+
+    // test setLevelMask calls OutputManager::updatedLevelMask
+    TEST(OutputListenerTest, SetLevelMaskCallsListeners)
+    {
+        MockOutputListener listener;
+        MockAdditionalContextListener additionalContextListener;
+        listener.registerListener(&additionalContextListener);
+
+        EXPECT_CALL(additionalContextListener, updatedLevelMask(&listener)).Times(1);
+
+        listener.setLevelMask(level::debug_output);
+    }
+
+    // test setAdditionalContextsLevelMask calls OutputManager::updatedAdditionalContextsLevelMask
+    TEST(OutputListenerTest, SetAdditionalContextsLevelMaskCallsListeners)
+    {
+        MockOutputListener listener;
+        MockAdditionalContextListener additionalContextListener;
+        listener.registerListener(&additionalContextListener);
+
+        EXPECT_CALL(additionalContextListener, updatedAdditionalContextsLevelMask(&listener)).Times(1);
+
+        listener.setAdditionalContextsLevelMask(level::debug_output);
+    }
+
+    // test setAdditionalContextsMask calls OutputManager::updatedAdditionalContextsMask
+    TEST(OutputListenerTest, SetAdditionalContextsMaskCallsListeners)
+    {
+        MockOutputListener listener;
+        MockAdditionalContextListener additionalContextListener;
+        listener.registerListener(&additionalContextListener);
+
+        EXPECT_CALL(additionalContextListener, updatedAdditionalContextsMask(&listener)).Times(1);
+
+        listener.setAdditionalContextsMask(context::unittest1().mask);
+    }
+
+    // test acceptsOutput
+    namespace
+    {
+        void testContext(const OutputListener& listener, const OutputContextContainer& context, bool accepted)
+        {
+            EXPECT_TRUE(listener.acceptsOutput(level::message, context));
+            EXPECT_TRUE(listener.acceptsOutput(level::user_error, context));
+            EXPECT_TRUE(listener.acceptsOutput(level::user_warning, context));
+
+            if (accepted)
+            {
+                EXPECT_TRUE(listener.acceptsOutput(level::user_status, context));
+                EXPECT_TRUE(listener.acceptsOutput(level::internal_error, context));
+                EXPECT_TRUE(listener.acceptsOutput(level::internal_info, context));
+            }
+            else
+            {
+                EXPECT_FALSE(listener.acceptsOutput(level::user_status, context));
+                EXPECT_FALSE(listener.acceptsOutput(level::internal_error, context));
+                EXPECT_FALSE(listener.acceptsOutput(level::internal_info, context));
+            }
+
+            EXPECT_FALSE(listener.acceptsOutput(level::verbose, context));
+            EXPECT_FALSE(listener.acceptsOutput(level::verbose_ultra, context));
+        }
+    }
+
+    TEST(OutputListenerTest, AcceptsOutputNoAdditionalContext)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMax(level::user_warning);
+
+        testContext(listener, context::undefined(), false);
+        testContext(listener, context::unittest1(), false);
+        testContext(listener, context::unittest2(), false);
+    }
+
+    TEST(OutputListenerTest, AcceptsOutputWithAdditionalContext)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMax(level::user_warning);
+        listener.setAdditionalContextsMask(context::unittest1().mask);
+        listener.setAdditionalContextsLevelMax(level::internal_info);
+
+        testContext(listener, context::undefined(), false);
+        testContext(listener, context::unittest1(), true);
+        testContext(listener, context::unittest2(), false);
+    }
+
+    TEST(OutputListenerTest, AcceptsOutputWithTwoAdditionalContexts)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMax(level::user_warning);
+
+        listener.setLevelMax(level::user_warning);
+        listener.setAdditionalContextsMask(context::unittest1().mask | context::unittest2().mask);
+        listener.setAdditionalContextsLevelMax(level::internal_info);
+
+        testContext(listener, context::undefined(), false);
+        testContext(listener, context::unittest1(), true);
+        testContext(listener, context::unittest2(), true);
+    }
+
+    // test unfilteredOutput
+    TEST(OutputListenerTest, UnfilteredOutputCallsOutputIfOutputAccepted)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMax(level::user_warning);
+
+        const OutputLevel& level = level::message;
+        const OutputContextContainer& context = context::undefined();
+
+        EXPECT_TRUE(listener.acceptsOutput(level, context));
+
+        std::vector<std::string> lines;
+        EXPECT_CALL(listener, output(level, context, lines)).Times(1);
+
+        listener.unfilteredOutput(level, context, lines);
+    }
+
+    TEST(OutputListenerTest, UnfilteredOutputDoesNotCallOutputIfOutputNotAccepted)
+    {
+        MockOutputListener listener;
+
+        listener.setLevelMax(level::user_warning);
+
+        const OutputLevel& level = level::verbose;
+        const OutputContextContainer& context = context::undefined();
+
+        EXPECT_FALSE(listener.acceptsOutput(level, context));
+
+        std::vector<std::string> lines;
+        EXPECT_CALL(listener, output(level, context, lines)).Times(0);
+
+        listener.unfilteredOutput(level, context, lines);
+    }
+
+    // Fixture
+    class OutputListenerTestWithMockedOutputManager : public ::testing::Test
+    {
+        public:
+            virtual void SetUp()
+            {
+                this->manager_ = new MockOutputManager();
+                OutputManager::Testing::getInstancePointer().reset(this->manager_);
+            }
+
+            virtual void TearDown()
+            {
+                OutputManager::Testing::getInstancePointer().reset(new OutputManager());
+            }
+
+        protected:
+            MockOutputManager* manager_;
+    };
+
+    // test default-constructor calls OutputManager::registerListener
+    TEST_F(OutputListenerTestWithMockedOutputManager, ConstructorRegistersInOutputManager)
+    {
+        EXPECT_CALL(*this->manager_, registerListener(::testing::_)).Times(1);
+        MockOutputListener listener;
+    }
+
+    // test prevent constructor from calling OutputManager::registerListener
+    TEST_F(OutputListenerTestWithMockedOutputManager, PreventRegisteringInOutputManager)
+    {
+        EXPECT_CALL(*this->manager_, registerListener(::testing::_)).Times(0);
+        MockOutputListener listener(false);
+    }
+
+    // test destructor calls OutputManager::unregisterListener
+    TEST_F(OutputListenerTestWithMockedOutputManager, DestructorUnregistersFromOutputManager)
+    {
+        MockOutputListener listener;
+        EXPECT_CALL(*this->manager_, unregisterListener(::testing::_)).Times(1);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/OutputManagerTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/OutputManagerTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/OutputManagerTest.cc	(revision 11817)
@@ -0,0 +1,454 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#define DISABLE_OUTPUT_CONTEXT_STATIC_CACHE
+
+#include "util/Output.h"
+#include "util/output/OutputManager.h"
+#include "util/output/OutputListener.h"
+
+namespace orxonox
+{
+    namespace context
+    {
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(unittest1);
+            REGISTER_OUTPUT_CONTEXT(unittest2);
+            REGISTER_OUTPUT_CONTEXT(unittest3);
+
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub1);
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub2);
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub3);
+        }
+    }
+
+    namespace
+    {
+        class MockOutputManager : public OutputManager
+        {
+            public:
+                MOCK_METHOD1(updatedLevelMask, void(const OutputListener*));
+                MOCK_METHOD1(updatedAdditionalContextsLevelMask, void(const OutputListener*));
+                MOCK_METHOD1(updatedAdditionalContextsMask, void(const OutputListener*));
+
+                void originalUpdatedLevelMask(const OutputListener* listener) { this->OutputManager::updatedLevelMask(listener); }
+                void originalUpdatedAdditionalContextsLevelMask(const OutputListener* listener) { this->OutputManager::updatedAdditionalContextsLevelMask(listener); }
+                void originalUpdatedAdditionalContextsMask(const OutputListener* listener) { this->OutputManager::updatedAdditionalContextsMask(listener); }
+        };
+
+        class MockOutputListener : public OutputListener
+        {
+            public:
+                MockOutputListener(bool bRegister = true) : OutputListener(bRegister) {}
+
+                MOCK_METHOD3(output, void(OutputLevel, const OutputContextContainer&, const std::vector<std::string>&));
+                MOCK_METHOD3(unfilteredOutput, void(OutputLevel, const OutputContextContainer&, const std::vector<std::string>&));
+
+                inline const std::vector<AdditionalContextListener*>& getListeners() const
+                    { return OutputListener::getListeners(); }
+        };
+    }
+
+    // test getInstance does not create listeners
+    TEST(OutputManagerTest, GetInstanceDoesNotCreateDefaultListeners)
+    {
+        EXPECT_TRUE(nullptr == OutputManager::getInstance().getMemoryWriter());
+        EXPECT_TRUE(nullptr == OutputManager::getInstance().getConsoleWriter());
+        EXPECT_TRUE(nullptr == OutputManager::getInstance().getLogWriter());
+    }
+
+    // test getInstanceAndCreateListeners creates listeners
+    TEST(OutputManagerTest, GetInstanceAndCreateListenersCreatesDefaultListeners)
+    {
+        EXPECT_TRUE(nullptr != OutputManager::getInstanceAndCreateListeners().getMemoryWriter());
+        EXPECT_TRUE(nullptr != OutputManager::getInstanceAndCreateListeners().getConsoleWriter());
+        EXPECT_TRUE(nullptr != OutputManager::getInstanceAndCreateListeners().getLogWriter());
+    }
+
+    // test getInstanceAndCreateListeners called again does not re-create listeners
+    TEST(OutputManagerTest, GetInstanceAndCreateListenersDoesNotCreateDefaultListenersTwice)
+    {
+        MemoryWriter* memoryWriter = OutputManager::getInstanceAndCreateListeners().getMemoryWriter();
+        ConsoleWriter* consoleWriter = OutputManager::getInstanceAndCreateListeners().getConsoleWriter();
+        LogWriter* logWriter = OutputManager::getInstanceAndCreateListeners().getLogWriter();
+
+        EXPECT_TRUE(memoryWriter == OutputManager::getInstanceAndCreateListeners().getMemoryWriter());
+        EXPECT_TRUE(consoleWriter == OutputManager::getInstanceAndCreateListeners().getConsoleWriter());
+        EXPECT_TRUE(logWriter == OutputManager::getInstanceAndCreateListeners().getLogWriter());
+    }
+
+    // test constructor
+    TEST(OutputManagerTest, MasksAreZeroAfterConstruction)
+    {
+        OutputManager manager;
+        EXPECT_EQ(0u, manager.getCombinedLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsMask());
+    }
+
+    // test registerListener adds listener to list
+    TEST(OutputManagerTest, RegisterListenerAddsListenerToList)
+    {
+        OutputManager manager;
+        MockOutputListener listener;
+        EXPECT_TRUE(manager.getListeners().empty());
+
+        manager.registerListener(&listener);
+
+        EXPECT_FALSE(manager.getListeners().empty());
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test unregisterListener removes listener from list
+    TEST(OutputManagerTest, UnregisterListenerRemovesListenerFromList)
+    {
+        OutputManager manager;
+        MockOutputListener listener;
+        manager.registerListener(&listener);
+        EXPECT_FALSE(manager.getListeners().empty());
+
+        manager.unregisterListener(&listener);
+
+        EXPECT_TRUE(manager.getListeners().empty());
+    }
+
+    // test registerListener registers manager at listener
+    TEST(OutputManagerTest, RegisterListenerRegistersManagerAtListener)
+    {
+        OutputManager manager;
+        MockOutputListener listener(false);
+        EXPECT_TRUE(listener.getListeners().empty());
+
+        manager.registerListener(&listener);
+
+        EXPECT_FALSE(listener.getListeners().empty());
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test unregisterListener unregisters manager from listener
+    TEST(OutputManagerTest, UnregisterListenerRemovesManagerFromListener)
+    {
+        OutputManager manager;
+        MockOutputListener listener(false);
+        manager.registerListener(&listener);
+        EXPECT_FALSE(listener.getListeners().empty());
+
+        manager.unregisterListener(&listener);
+
+        EXPECT_TRUE(listener.getListeners().empty());
+    }
+
+    // test registerListener adjusts masks
+    TEST(OutputManagerTest, RegisterListenerAdjustsMasks)
+    {
+        OutputManager manager;
+        EXPECT_EQ(0u, manager.getCombinedLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsMask());
+
+        MockOutputListener listener;
+        listener.setLevelMask(level::internal_warning);
+        listener.setAdditionalContextsLevelMask(level::verbose_more);
+        listener.setAdditionalContextsMask(context::unittest2().mask);
+
+        manager.registerListener(&listener);
+
+        EXPECT_EQ(level::internal_warning, manager.getCombinedLevelMask());
+        EXPECT_EQ(level::verbose_more, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(context::unittest2().mask, manager.getCombinedAdditionalContextsMask());
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test unregisterListener adjusts masks
+    TEST(OutputManagerTest, UnregisterListenerAdjustsMasks)
+    {
+        OutputManager manager;
+        MockOutputListener listener;
+        listener.setLevelMask(level::internal_warning);
+        listener.setAdditionalContextsLevelMask(level::verbose_more);
+        listener.setAdditionalContextsMask(context::unittest2().mask);
+
+        manager.registerListener(&listener);
+
+        EXPECT_EQ(level::internal_warning, manager.getCombinedLevelMask());
+        EXPECT_EQ(level::verbose_more, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(context::unittest2().mask, manager.getCombinedAdditionalContextsMask());
+
+        manager.unregisterListener(&listener);
+
+        EXPECT_EQ(0u, manager.getCombinedLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsMask());
+    }
+
+    // test updatedLevelMask updates mask
+    TEST(OutputManagerTest, UpdatedLevelMask)
+    {
+        MockOutputManager manager;
+        MockOutputListener listener;
+        manager.registerListener(&listener);
+
+        EXPECT_EQ(0u, manager.getCombinedLevelMask());
+        EXPECT_CALL(manager, updatedLevelMask(&listener)).WillRepeatedly(::testing::Invoke(&manager, &MockOutputManager::originalUpdatedLevelMask));
+
+        listener.setLevelMask(level::internal_warning);
+
+        EXPECT_EQ(level::internal_warning, manager.getCombinedLevelMask());
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test updatedAdditionalContextsLevelMask updates mask
+    TEST(OutputManagerTest, UpdatedAdditionalContextsLevelMask)
+    {
+        MockOutputManager manager;
+        MockOutputListener listener;
+        manager.registerListener(&listener);
+
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_CALL(manager, updatedAdditionalContextsLevelMask(&listener)).WillRepeatedly(::testing::Invoke(&manager, &MockOutputManager::originalUpdatedAdditionalContextsLevelMask));
+
+        listener.setAdditionalContextsLevelMask(level::internal_warning);
+
+        EXPECT_EQ(level::internal_warning, manager.getCombinedAdditionalContextsLevelMask());
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test updatedAdditionalContextsMask updates mask
+    TEST(OutputManagerTest, UpdatedAdditionalContextsMask)
+    {
+        MockOutputManager manager;
+        MockOutputListener listener;
+        manager.registerListener(&listener);
+
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsMask());
+        EXPECT_CALL(manager, updatedAdditionalContextsMask(&listener)).WillRepeatedly(::testing::Invoke(&manager, &MockOutputManager::originalUpdatedAdditionalContextsMask));
+
+        listener.setAdditionalContextsMask(context::unittest2().mask);
+
+        EXPECT_EQ(context::unittest2().mask, manager.getCombinedAdditionalContextsMask());
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test combines masks of all listeners
+    TEST(OutputManagerTest, CombinesMasksOfAllListeners)
+    {
+        OutputManager manager;
+        EXPECT_EQ(0u, manager.getCombinedLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(0u, manager.getCombinedAdditionalContextsMask());
+
+        MockOutputListener listener1;
+        listener1.setLevelMask(level::user_error);
+        listener1.setAdditionalContextsLevelMask(level::verbose);
+        listener1.setAdditionalContextsMask(context::unittest1().mask);
+        manager.registerListener(&listener1);
+
+        MockOutputListener listener2;
+        listener2.setLevelMask(level::user_warning);
+        listener2.setAdditionalContextsLevelMask(level::verbose_more);
+        listener2.setAdditionalContextsMask(context::unittest2().mask);
+        manager.registerListener(&listener2);
+
+        MockOutputListener listener3;
+        listener3.setLevelMask(level::internal_warning);
+        listener3.setAdditionalContextsLevelMask(level::verbose_ultra);
+        listener3.setAdditionalContextsMask(context::unittest3().mask);
+        manager.registerListener(&listener3);
+
+        EXPECT_EQ(level::user_error | level::user_warning | level::internal_warning, manager.getCombinedLevelMask());
+        EXPECT_EQ(level::verbose | level::verbose_more | level::verbose_ultra, manager.getCombinedAdditionalContextsLevelMask());
+        EXPECT_EQ(context::unittest1().mask | context::unittest2().mask | context::unittest3().mask, manager.getCombinedAdditionalContextsMask());
+
+        manager.unregisterListener(&listener1);
+        manager.unregisterListener(&listener2);
+        manager.unregisterListener(&listener3);
+    }
+
+    // test acceptsOutput
+    TEST(OutputManagerTest, AcceptsOutput)
+    {
+        OutputManager manager;
+        MockOutputListener listener;
+        listener.setLevelMask(level::internal_warning);
+        listener.setAdditionalContextsLevelMask(level::verbose_more);
+        listener.setAdditionalContextsMask(context::unittest2().mask);
+
+        manager.registerListener(&listener);
+
+        EXPECT_FALSE(manager.acceptsOutput(level::user_error, context::undefined()));
+        EXPECT_FALSE(manager.acceptsOutput(level::internal_error, context::undefined()));
+        EXPECT_TRUE(manager.acceptsOutput(level::internal_warning, context::undefined()));
+        EXPECT_FALSE(manager.acceptsOutput(level::internal_status, context::undefined()));
+        EXPECT_FALSE(manager.acceptsOutput(level::verbose_more, context::undefined()));
+        EXPECT_FALSE(manager.acceptsOutput(level::verbose_ultra, context::undefined()));
+
+        EXPECT_FALSE(manager.acceptsOutput(level::user_error, context::unittest1()));
+        EXPECT_FALSE(manager.acceptsOutput(level::internal_error, context::unittest1()));
+        EXPECT_TRUE(manager.acceptsOutput(level::internal_warning, context::unittest1()));
+        EXPECT_FALSE(manager.acceptsOutput(level::internal_status, context::unittest1()));
+        EXPECT_FALSE(manager.acceptsOutput(level::verbose_more, context::unittest1()));
+        EXPECT_FALSE(manager.acceptsOutput(level::verbose_ultra, context::unittest1()));
+
+        EXPECT_FALSE(manager.acceptsOutput(level::user_error, context::unittest2()));
+        EXPECT_FALSE(manager.acceptsOutput(level::internal_error, context::unittest2()));
+        EXPECT_TRUE(manager.acceptsOutput(level::internal_warning, context::unittest2()));
+        EXPECT_FALSE(manager.acceptsOutput(level::internal_status, context::unittest2()));
+        EXPECT_TRUE(manager.acceptsOutput(level::verbose_more, context::unittest2()));
+        EXPECT_FALSE(manager.acceptsOutput(level::verbose_ultra, context::unittest2()));
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test pushMessage sends lines to listeners
+    TEST(OutputManagerTest, PushMessageSendsLinesToListeners)
+    {
+        OutputManager manager;
+        MockOutputListener listener;
+        manager.registerListener(&listener);
+
+        std::vector<std::string> lines;
+        lines.push_back("some output");
+
+        EXPECT_CALL(listener, unfilteredOutput(level::user_status, context::unittest1(), lines));
+
+        manager.pushMessage(level::user_status, context::unittest1(), "some output");
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test pushMessage splits lines by \n
+    TEST(OutputManagerTest, PushMessageSplitsTextAtNewlineChar)
+    {
+        OutputManager manager;
+        MockOutputListener listener;
+        manager.registerListener(&listener);
+
+        std::vector<std::string> lines;
+        lines.push_back("some output");
+        lines.push_back("and some more output");
+        lines.push_back("!!!");
+
+        EXPECT_CALL(listener, unfilteredOutput(level::user_status, context::unittest1(), lines));
+
+        manager.pushMessage(level::user_status, context::unittest1(), "some output\nand some more output\n!!!");
+
+        manager.unregisterListener(&listener);
+    }
+
+    // test registerContext for new context
+    TEST(OutputManagerTest, RegisterNewContext)
+    {
+        OutputManager manager;
+        OutputContextContainer container = manager.registerContext("whatever");
+        EXPECT_EQ("whatever", container.name);
+        EXPECT_EQ(0, container.sub_id);
+    }
+
+    // test registerContext for existing context
+    TEST(OutputManagerTest, RegisterContextTwice)
+    {
+        OutputManager manager;
+        OutputContextContainer container1 = manager.registerContext("whatever");
+        OutputContextContainer container2 = manager.registerContext("whatever");
+        EXPECT_EQ("whatever", container1.name);
+        EXPECT_EQ(0, container1.sub_id);
+        EXPECT_EQ(container1, container2);
+    }
+
+    // test registerContext for multiple contexts
+    TEST(OutputManagerTest, RegisterMultipleContexts)
+    {
+        OutputManager manager;
+        OutputContextContainer container1 = manager.registerContext("whatever");
+        OutputContextContainer container2 = manager.registerContext("asdf");
+        EXPECT_EQ("whatever", container1.name);
+        EXPECT_EQ(0, container1.sub_id);
+        EXPECT_EQ("asdf", container2.name);
+        EXPECT_EQ(0, container2.sub_id);
+        EXPECT_NE(container1.mask, container2.mask);
+    }
+
+    // test registerContext for new subcontext
+    TEST(OutputManagerTest, RegisterNewSubcontext)
+    {
+        OutputManager manager;
+        OutputContextContainer container = manager.registerContext("base", "subcontext");
+        EXPECT_EQ("base::subcontext", container.name);
+        EXPECT_NE(0, container.sub_id);
+    }
+
+    // test registerContext for existing subcontext
+    TEST(OutputManagerTest, RegisterSubcontextTwice)
+    {
+        OutputManager manager;
+        OutputContextContainer container1 = manager.registerContext("base", "subcontext");
+        OutputContextContainer container2 = manager.registerContext("base", "subcontext");
+        EXPECT_EQ("base::subcontext", container1.name);
+        EXPECT_NE(0, container1.sub_id);
+        EXPECT_EQ(container1, container2);
+    }
+
+    // test registerContext for multiple subcontexts
+    TEST(OutputManagerTest, RegisterMultipleSubcontexts)
+    {
+        OutputManager manager;
+        OutputContextContainer container1 = manager.registerContext("base", "subcontext");
+        OutputContextContainer container2 = manager.registerContext("base", "meh");
+        EXPECT_EQ("base::subcontext", container1.name);
+        EXPECT_NE(0, container1.sub_id);
+        EXPECT_EQ("base::meh", container2.name);
+        EXPECT_NE(0, container2.sub_id);
+        EXPECT_EQ(container1.mask, container2.mask);
+        EXPECT_NE(container1.sub_id, container2.sub_id);
+    }
+
+    // test subcontext has mask of base context
+    TEST(OutputManagerTest, SubcontextHasMaskOfBaseContext)
+    {
+        OutputManager manager;
+        OutputContextContainer container1 = manager.registerContext("base", "subcontext");
+        EXPECT_EQ("base::subcontext", container1.name);
+        EXPECT_NE(0, container1.sub_id);
+
+        OutputContextContainer container2 = manager.registerContext("base");
+        EXPECT_EQ("base", container2.name);
+        EXPECT_EQ(0, container2.sub_id);
+
+        EXPECT_EQ(container1.mask, container2.mask);
+    }
+
+    // test getLevelName
+    TEST(OutputManagerTest, GetLevelName)
+    {
+        OutputManager manager;
+        EXPECT_EQ("Debug", manager.getLevelName(level::debug_output));
+        EXPECT_EQ("Error", manager.getLevelName(level::user_error));
+        EXPECT_EQ("Status", manager.getLevelName(level::user_status));
+        EXPECT_EQ("Warning (internal)", manager.getLevelName(level::internal_warning));
+        EXPECT_EQ("Info (internal)", manager.getLevelName(level::internal_info));
+        EXPECT_EQ("Verbose", manager.getLevelName(level::verbose));
+    }
+
+    // test getDefaultPrefix for undefined context
+    TEST(OutputManagerTest, GetDefaultPrefixWithoutContext)
+    {
+        OutputManager manager;
+        std::string prefix = manager.getDefaultPrefix(level::debug_output, context::undefined());
+        EXPECT_EQ(manager.getLevelName(level::debug_output) + ": ", prefix);
+    }
+
+    // test getDefaultPrefix for regular context
+    TEST(OutputManagerTest, GetDefaultPrefixWithContext)
+    {
+        OutputManager manager;
+        std::string prefix = manager.getDefaultPrefix(level::debug_output, context::unittest1());
+        EXPECT_EQ(manager.getLevelName(level::debug_output) + ": [unittest1] ", prefix);
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/OutputStreamTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/OutputStreamTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/OutputStreamTest.cc	(revision 11817)
@@ -0,0 +1,169 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#define DISABLE_OUTPUT_CONTEXT_STATIC_CACHE
+
+#include "util/Output.h"
+#include "util/output/OutputStream.h"
+#include "util/output/OutputManager.h"
+#include "util/output/MemoryWriter.h"
+
+namespace orxonox
+{
+    namespace context
+    {
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(unittest1);
+        }
+    }
+
+    namespace
+    {
+        class MockOutputManager : public OutputManager
+        {
+            public:
+                MOCK_METHOD3(pushMessage, void(OutputLevel, const OutputContextContainer&, const std::string&));
+        };
+    }
+
+    // test level and context in constructor
+    TEST(OutputStreamTest, Constructor)
+    {
+        OutputStream stream(level::user_warning, context::unittest1());
+
+        EXPECT_EQ(level::user_warning, stream.getOutputLevel());
+        EXPECT_EQ(&context::unittest1(), stream.getOutputContext());
+    }
+
+    // test setOutputAttributes
+    TEST(OutputStreamTest, SetOutputAttributes)
+    {
+        OutputStream stream;
+        stream.setOutputAttributes(level::user_warning, context::unittest1());
+
+        EXPECT_EQ(level::user_warning, stream.getOutputLevel());
+        EXPECT_EQ(&context::unittest1(), stream.getOutputContext());
+    }
+
+    // test manipulator applied
+    TEST(OutputStreamTest, ManipulatorApplied)
+    {
+        OutputStream stream;
+        stream << "test";
+        EXPECT_EQ(4u, stream.str().size());
+
+        // apply manipulator
+        stream << std::ends;
+        EXPECT_EQ(5u, stream.str().size());
+    }
+
+    // test manipulator only applied if output accepted
+    TEST(OutputStreamTest, ManipulatorOnlyAppliedIfOutputAccepted)
+    {
+        // disable MemoryWriter because otherwise we would always accept all output
+        OutputManager::getInstance().getMemoryWriter()->disable();
+
+        {
+            OutputStream stream;
+            EXPECT_TRUE(stream.acceptsOutput());
+            stream << std::ends;
+            EXPECT_EQ(1u, stream.str().size());
+        }
+
+        {
+            OutputStream stream(level::verbose, context::undefined());
+            EXPECT_FALSE(stream.acceptsOutput());
+            stream << std::ends;
+            EXPECT_EQ(0u, stream.str().size());
+        }
+    }
+
+    // Fixture
+    class OutputStreamTestWithMockedOutputManager : public ::testing::Test
+    {
+        public:
+            virtual void SetUp()
+            {
+                this->manager_ = new MockOutputManager();
+                OutputManager::Testing::getInstancePointer().reset(this->manager_);
+            }
+
+            virtual void TearDown()
+            {
+                OutputManager::Testing::getInstancePointer().reset(new OutputManager());
+            }
+
+        protected:
+            MockOutputManager* manager_;
+    };
+
+    // test endl-manipulator sends output to OutputManager
+    TEST_F(OutputStreamTestWithMockedOutputManager, EndlSendsToOutputManager)
+    {
+        OutputStream stream;
+
+        const OutputContextContainer& context = context::unittest1();
+
+        stream.setOutputAttributes(level::user_warning, context);
+        EXPECT_TRUE(stream.acceptsOutput());
+        EXPECT_EQ(context, *stream.getOutputContext());
+
+        EXPECT_CALL(*this->manager_, pushMessage(level::user_warning, context, "some output"));
+
+        stream << "some output" << std::endl;
+    }
+
+    // test multiple lines sent to OutputManager
+    TEST_F(OutputStreamTestWithMockedOutputManager, MultipleLinesSentToOutputManager)
+    {
+        OutputStream stream;
+
+        const OutputContextContainer& context = context::unittest1();
+
+        stream.setOutputAttributes(level::user_warning, context);
+        EXPECT_TRUE(stream.acceptsOutput());
+        EXPECT_EQ(context, *stream.getOutputContext());
+
+        EXPECT_CALL(*this->manager_, pushMessage(level::user_warning, context, "some output"));
+        EXPECT_CALL(*this->manager_, pushMessage(level::user_warning, context, "more output"));
+        EXPECT_CALL(*this->manager_, pushMessage(level::user_warning, context, "yet another line of output"));
+
+        stream << "some output" << std::endl;
+        stream << "more output" << std::endl;
+        stream << "yet another line of output" << std::endl;
+    }
+
+    // test output only sent if accepted
+    TEST_F(OutputStreamTestWithMockedOutputManager, OutputOnlySentToOutputManagerIfAccepted)
+    {
+        // disable MemoryWriter because otherwise we would always accept all output
+        OutputManager::getInstanceAndCreateListeners().getMemoryWriter()->disable();
+
+        OutputStream stream;
+
+        const OutputContextContainer& context = context::unittest1();
+
+        stream.setOutputAttributes(level::verbose, context);
+        EXPECT_FALSE(stream.acceptsOutput());
+
+        EXPECT_CALL(*this->manager_, pushMessage(::testing::_, ::testing::_, ::testing::_)).Times(0);
+
+        stream << "some output" << std::endl;
+    }
+
+    // test desctructor sends remaining output to OutputManager
+    TEST_F(OutputStreamTestWithMockedOutputManager, DestructorSendsRemainingOutputToOutputManager)
+    {
+        OutputStream stream;
+
+        const OutputContextContainer& context = context::undefined();
+
+        stream.setOutputAttributes(level::verbose, context);
+        EXPECT_TRUE(stream.acceptsOutput());
+
+        EXPECT_CALL(*this->manager_, pushMessage(::testing::_, ::testing::_, "some output [missing endl]"));
+
+        stream << "some output";
+    }
+}
Index: /code/branches/RacingBots_FS18/test/util/output/SubcontextOutputListenerTest.cc
===================================================================
--- /code/branches/RacingBots_FS18/test/util/output/SubcontextOutputListenerTest.cc	(revision 11817)
+++ /code/branches/RacingBots_FS18/test/util/output/SubcontextOutputListenerTest.cc	(revision 11817)
@@ -0,0 +1,217 @@
+#include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include "util/Output.h"
+#include "util/output/SubcontextOutputListener.h"
+
+namespace orxonox
+{
+    namespace context
+    {
+        namespace
+        {
+            REGISTER_OUTPUT_CONTEXT(unittest1);
+            REGISTER_OUTPUT_CONTEXT(unittest2);
+            REGISTER_OUTPUT_CONTEXT(unittest3);
+
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub1);
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub2);
+            REGISTER_OUTPUT_SUBCONTEXT(unittest3, sub3);
+        }
+    }
+
+    namespace
+    {
+        class MockSubcontextOutputListener : public SubcontextOutputListener
+        {
+            public:
+                MockSubcontextOutputListener(bool bRegister = true) : SubcontextOutputListener(bRegister) {}
+                MOCK_METHOD3(output, void(OutputLevel, const OutputContextContainer&, const std::vector<std::string>&));
+        };
+    }
+
+    TEST(SubcontextOutputListenerTest, ContextsDefinedCorrectly)
+    {
+        EXPECT_TRUE(context::unittest1().sub_id == context::no_subcontext);
+        EXPECT_TRUE(context::unittest2().sub_id == context::no_subcontext);
+        EXPECT_TRUE(context::unittest3().sub_id == context::no_subcontext);
+        EXPECT_FALSE(context::sub1().sub_id == context::no_subcontext);
+        EXPECT_FALSE(context::sub2().sub_id == context::no_subcontext);
+        EXPECT_FALSE(context::sub3().sub_id == context::no_subcontext);
+    }
+
+    // test setAdditionalContextsMask
+    TEST(SubcontextOutputListenerTest, SetAdditionalContextsMask)
+    {
+        MockSubcontextOutputListener listener;
+
+        listener.setAdditionalContextsMask(context::unittest1().mask | context::unittest2().mask);
+
+        OutputContextMask mask = listener.getAdditionalContextsMask();
+
+        EXPECT_TRUE(mask & context::unittest1().mask);
+        EXPECT_TRUE(mask & context::unittest2().mask);
+        EXPECT_FALSE(mask & context::unittest3().mask);
+    }
+
+    // test setAdditionalSubcontexts
+    TEST(SubcontextOutputListenerTest, SetAdditionalSubcontexts)
+    {
+        MockSubcontextOutputListener listener;
+
+        std::set<const OutputContextContainer*> subcontexts;
+        subcontexts.insert(&context::sub1());
+        subcontexts.insert(&context::sub3());
+
+        listener.setAdditionalSubcontexts(subcontexts);
+        OutputContextMask mask = listener.getAdditionalContextsMask();
+
+        EXPECT_FALSE(mask & context::unittest1().mask);
+        EXPECT_FALSE(mask & context::unittest2().mask);
+        EXPECT_TRUE(mask & context::unittest3().mask);
+    }
+
+    // test setAdditionalContextsMask and setAdditionalSubcontexts
+    TEST(SubcontextOutputListenerTest, SetAdditionalContextsAndSubcontexts)
+    {
+        MockSubcontextOutputListener listener;
+
+        std::set<const OutputContextContainer*> subcontexts;
+        subcontexts.insert(&context::sub1());
+        subcontexts.insert(&context::sub3());
+
+        listener.setAdditionalSubcontexts(subcontexts);
+        listener.setAdditionalContextsMask(context::unittest1().mask | context::unittest2().mask);
+
+        OutputContextMask mask = listener.getAdditionalContextsMask();
+
+        EXPECT_TRUE(mask & context::unittest1().mask);
+        EXPECT_TRUE(mask & context::unittest2().mask);
+        EXPECT_TRUE(mask & context::unittest3().mask);
+    }
+
+    // test acceptsOutput
+    namespace
+    {
+        void testContext(const OutputListener& listener, const OutputContextContainer& context, bool accepted)
+        {
+            EXPECT_TRUE(accepted == listener.acceptsOutput(level::message, context));
+            EXPECT_TRUE(accepted == listener.acceptsOutput(level::user_error, context));
+            EXPECT_TRUE(accepted == listener.acceptsOutput(level::internal_info, context));
+        }
+    }
+
+    TEST(SubcontextOutputListenerTest, NoContext)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        testContext(listener, context::unittest1(), false);
+        testContext(listener, context::unittest2(), false);
+        testContext(listener, context::unittest3(), false);
+        testContext(listener, context::sub1(), false);
+        testContext(listener, context::sub2(), false);
+        testContext(listener, context::sub3(), false);
+    }
+
+    TEST(SubcontextOutputListenerTest, OneContext)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        listener.setAdditionalContextsMask(context::unittest1().mask);
+
+        testContext(listener, context::unittest1(), true);
+        testContext(listener, context::unittest2(), false);
+        testContext(listener, context::unittest3(), false);
+        testContext(listener, context::sub1(), false);
+        testContext(listener, context::sub2(), false);
+        testContext(listener, context::sub3(), false);
+    }
+
+    TEST(SubcontextOutputListenerTest, TwoContexts)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        listener.setAdditionalContextsMask(context::unittest1().mask | context::unittest2().mask);
+
+        testContext(listener, context::unittest1(), true);
+        testContext(listener, context::unittest2(), true);
+        testContext(listener, context::unittest3(), false);
+        testContext(listener, context::sub1(), false);
+        testContext(listener, context::sub2(), false);
+        testContext(listener, context::sub3(), false);
+    }
+
+    TEST(SubcontextOutputListenerTest, OneSubcontext)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        std::set<const OutputContextContainer*> subcontexts;
+        subcontexts.insert(&context::sub1());
+
+        listener.setAdditionalSubcontexts(subcontexts);
+
+        testContext(listener, context::unittest1(), false);
+        testContext(listener, context::unittest2(), false);
+        testContext(listener, context::unittest3(), false);
+        testContext(listener, context::sub1(), true);
+        testContext(listener, context::sub2(), false);
+        testContext(listener, context::sub3(), false);
+    }
+
+    TEST(SubcontextOutputListenerTest, TwoSubcontexts)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        std::set<const OutputContextContainer*> subcontexts;
+        subcontexts.insert(&context::sub1());
+        subcontexts.insert(&context::sub3());
+
+        listener.setAdditionalSubcontexts(subcontexts);
+
+        testContext(listener, context::unittest1(), false);
+        testContext(listener, context::unittest2(), false);
+        testContext(listener, context::unittest3(), false);
+        testContext(listener, context::sub1(), true);
+        testContext(listener, context::sub2(), false);
+        testContext(listener, context::sub3(), true);
+    }
+
+    TEST(SubcontextOutputListenerTest, ContextsAndSubcontexts)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        std::set<const OutputContextContainer*> subcontexts;
+        subcontexts.insert(&context::sub1());
+        subcontexts.insert(&context::sub3());
+
+        listener.setAdditionalContextsMask(context::unittest1().mask | context::unittest2().mask);
+        listener.setAdditionalSubcontexts(subcontexts);
+
+        testContext(listener, context::unittest1(), true);
+        testContext(listener, context::unittest2(), true);
+        testContext(listener, context::unittest3(), false);
+        testContext(listener, context::sub1(), true);
+        testContext(listener, context::sub2(), false);
+        testContext(listener, context::sub3(), true);
+    }
+
+    TEST(SubcontextOutputListenerTest, BaseContextEnablesAllSubcontexts)
+    {
+        MockSubcontextOutputListener listener;
+        listener.setAdditionalContextsLevelMax(level::verbose);
+
+        listener.setAdditionalContextsMask(context::unittest3().mask);
+
+        testContext(listener, context::unittest1(), false);
+        testContext(listener, context::unittest2(), false);
+        testContext(listener, context::unittest3(), true);
+        testContext(listener, context::sub1(), true);
+        testContext(listener, context::sub2(), true);
+        testContext(listener, context::sub3(), true);
+    }
+}
